This commit was manufactured by cvs2svn to create branch 't-gnus-
authortomo <tomo>
Sun, 4 Jan 2004 23:53:00 +0000 (23:53 +0000)
committertomo <tomo>
Sun, 4 Jan 2004 23:53:00 +0000 (23:53 +0000)
6_17-quimby'.

540 files changed:
ChangeLog
ChangeLog.1 [new file with mode: 0644]
ChangeLog.2 [new file with mode: 0644]
ChangeLog.3 [new file with mode: 0644]
ChangeLog.4 [new file with mode: 0644]
GNUS-NEWS
INSTALL.ja [new file with mode: 0644]
Makefile [deleted file]
Makefile.in
Mule23@1934.en [new file with mode: 0644]
Mule23@1934.ja [new file with mode: 0644]
README-gnus-bbdb.en [new file with mode: 0644]
README-gnus-bbdb.ja [new file with mode: 0644]
README-offline.en [new file with mode: 0644]
README-offline.ja [new file with mode: 0644]
README.T-gnus [new file with mode: 0644]
README.branch [new file with mode: 0644]
README.branch.ja [new file with mode: 0644]
README.semi [new file with mode: 0644]
README.semi.ja [new file with mode: 0644]
TODO.ja [new file with mode: 0644]
aclocal.m4
configure
configure.in
contrib/ChangeLog [new file with mode: 0644]
contrib/README [new file with mode: 0644]
contrib/base64.el [new file with mode: 0644]
contrib/cus-dep.el [new file with mode: 0644]
contrib/gnus-idna.el [new file with mode: 0644]
contrib/gpg-ring.el [new file with mode: 0644]
contrib/gpg.el [new file with mode: 0644]
contrib/hashcash.el [new file with mode: 0644]
contrib/md5.el [new file with mode: 0644]
contrib/nnir.el [new file with mode: 0644]
contrib/one-line-cookie.diff [new file with mode: 0644]
contrib/passwd.el [new file with mode: 0644]
contrib/regexp-opt.el [new file with mode: 0644]
contrib/ssl.el [new file with mode: 0644]
contrib/starttls.el [new file with mode: 0644]
contrib/timer.el [new file with mode: 0644]
contrib/ucs-tables.el [new file with mode: 0644]
contrib/vcard.el [new file with mode: 0644]
contrib/xml.el [new file with mode: 0644]
etc/Makefile.in [new file with mode: 0644]
etc/gnus-tut.txt
etc/gnus/bar.xbm [new file with mode: 0644]
etc/gnus/bar.xpm [new file with mode: 0644]
etc/gnus/catchup.pbm [new file with mode: 0644]
etc/gnus/catchup.xpm [new file with mode: 0644]
etc/gnus/cu-exit.pbm [new file with mode: 0644]
etc/gnus/cu-exit.xpm [new file with mode: 0644]
etc/gnus/describe-group.pbm [new file with mode: 0644]
etc/gnus/describe-group.xpm [new file with mode: 0644]
etc/gnus/exit-gnus.pbm [new file with mode: 0644]
etc/gnus/exit-gnus.xpm [new file with mode: 0644]
etc/gnus/exit-summ.pbm [new file with mode: 0644]
etc/gnus/exit-summ.xpm [new file with mode: 0644]
etc/gnus/followup.pbm [new file with mode: 0644]
etc/gnus/followup.xpm [new file with mode: 0644]
etc/gnus/fuwo.pbm [new file with mode: 0644]
etc/gnus/fuwo.xpm [new file with mode: 0644]
etc/gnus/get-news.pbm [new file with mode: 0644]
etc/gnus/get-news.xpm [new file with mode: 0644]
etc/gnus/gnntg.pbm [new file with mode: 0644]
etc/gnus/gnntg.xpm [new file with mode: 0644]
etc/gnus/gnus-group-catchup-current-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-catchup-current-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-catchup-current.xbm [new file with mode: 0644]
etc/gnus/gnus-group-catchup-current.xpm [new file with mode: 0644]
etc/gnus/gnus-group-describe-group-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-describe-group-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-exit-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-exit-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-get-new-news-this-group-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-get-new-news-this-group-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-get-new-news-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-get-new-news-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-kill-group-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-kill-group-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-subscribe-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-subscribe-up.xpm [new file with mode: 0644]
etc/gnus/gnus-group-unsubscribe-up.xbm [new file with mode: 0644]
etc/gnus/gnus-group-unsubscribe-up.xpm [new file with mode: 0644]
etc/gnus/gnus-pointer.xbm [new file with mode: 0644]
etc/gnus/gnus-pointer.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-caesar-message-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-caesar-message-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-cancel-article-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-cancel-article-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-catchup-and-exit-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-catchup-and-exit-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-catchup-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-catchup-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-exit-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-exit-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-followup-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-followup-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-followup-with-original-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-followup-with-original-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-copy-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-copy-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-delete-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-delete-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-forward-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-forward-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-get-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-get-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-originate-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-originate-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-reply-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-reply-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-save-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-mail-save-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-next-unread-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-next-unread-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-post-news-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-post-news-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-prev-unread-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-prev-unread-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-reply-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-reply-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-reply-with-original-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-reply-with-original-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-save-article-file-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-save-article-file-up.xpm [new file with mode: 0644]
etc/gnus/gnus-summary-save-article-up.xbm [new file with mode: 0644]
etc/gnus/gnus-summary-save-article-up.xpm [new file with mode: 0644]
etc/gnus/gnus-uu-decode-uu-up.xbm [new file with mode: 0644]
etc/gnus/gnus-uu-decode-uu-up.xpm [new file with mode: 0644]
etc/gnus/gnus-uu-post-news-up.xbm [new file with mode: 0644]
etc/gnus/gnus-uu-post-news-up.xpm [new file with mode: 0644]
etc/gnus/gnus.xbm [new file with mode: 0644]
etc/gnus/gnus.xpm [new file with mode: 0644]
etc/gnus/important.xpm [new file with mode: 0644]
etc/gnus/kill-group.pbm [new file with mode: 0644]
etc/gnus/kill-group.xpm [new file with mode: 0644]
etc/gnus/mail-reply.pbm [new file with mode: 0644]
etc/gnus/mail-reply.xpm [new file with mode: 0644]
etc/gnus/next-ur.pbm [new file with mode: 0644]
etc/gnus/next-ur.xpm [new file with mode: 0644]
etc/gnus/oort.xface [new file with mode: 0644]
etc/gnus/post.pbm [new file with mode: 0644]
etc/gnus/post.xpm [new file with mode: 0644]
etc/gnus/prev-ur.pbm [new file with mode: 0644]
etc/gnus/prev-ur.xpm [new file with mode: 0644]
etc/gnus/preview.xbm [new file with mode: 0644]
etc/gnus/preview.xpm [new file with mode: 0644]
etc/gnus/receipt.xpm [new file with mode: 0644]
etc/gnus/reply-wo.pbm [new file with mode: 0644]
etc/gnus/reply-wo.xpm [new file with mode: 0644]
etc/gnus/reply.pbm [new file with mode: 0644]
etc/gnus/reply.xpm [new file with mode: 0644]
etc/gnus/rot13.pbm [new file with mode: 0644]
etc/gnus/rot13.xpm [new file with mode: 0644]
etc/gnus/save-aif.pbm [new file with mode: 0644]
etc/gnus/save-aif.xpm [new file with mode: 0644]
etc/gnus/save-art.pbm [new file with mode: 0644]
etc/gnus/save-art.xpm [new file with mode: 0644]
etc/gnus/subscribe.pbm [new file with mode: 0644]
etc/gnus/subscribe.xpm [new file with mode: 0644]
etc/gnus/unimportant.xpm [new file with mode: 0644]
etc/gnus/unsubscribe.pbm [new file with mode: 0644]
etc/gnus/unsubscribe.xpm [new file with mode: 0644]
etc/gnus/uu-decode.pbm [new file with mode: 0644]
etc/gnus/uu-decode.xpm [new file with mode: 0644]
etc/gnus/uu-post.pbm [new file with mode: 0644]
etc/gnus/uu-post.xpm [new file with mode: 0644]
etc/gnus/x-splash [new file with mode: 0644]
etc/smilies/blink.pbm [new file with mode: 0644]
etc/smilies/blink.xpm [new file with mode: 0644]
etc/smilies/braindamaged.xpm [new file with mode: 0644]
etc/smilies/cry.xpm [new file with mode: 0644]
etc/smilies/dead.xpm [new file with mode: 0644]
etc/smilies/evil.xpm [new file with mode: 0644]
etc/smilies/forced.xpm [new file with mode: 0644]
etc/smilies/frown.pbm [new file with mode: 0644]
etc/smilies/frown.xpm [new file with mode: 0644]
etc/smilies/grin.xpm [new file with mode: 0644]
etc/smilies/indifferent.xpm [new file with mode: 0644]
etc/smilies/reverse-smile.xpm [new file with mode: 0644]
etc/smilies/sad.pbm [new file with mode: 0644]
etc/smilies/sad.xpm [new file with mode: 0644]
etc/smilies/smile.pbm [new file with mode: 0644]
etc/smilies/smile.xpm [new file with mode: 0644]
etc/smilies/wry.pbm [new file with mode: 0644]
etc/smilies/wry.xpm [new file with mode: 0644]
lisp/ChangeLog
lisp/ChangeLog.1 [new file with mode: 0644]
lisp/Makefile [deleted file]
lisp/Makefile.in
lisp/base64.el [new file with mode: 0644]
lisp/binhex.el [new file with mode: 0644]
lisp/canlock-om.el [new file with mode: 0644]
lisp/canlock.el [new file with mode: 0644]
lisp/compface.el [new file with mode: 0644]
lisp/deuglify.el [new file with mode: 0644]
lisp/dgnushack.el
lisp/dgnuspath.el.in [new file with mode: 0644]
lisp/dig.el [new file with mode: 0644]
lisp/dns.el [new file with mode: 0644]
lisp/earcon.el
lisp/flow-fill.el [new file with mode: 0644]
lisp/format-spec.el [new file with mode: 0644]
lisp/gnus-agent.el
lisp/gnus-art.el
lisp/gnus-async.el
lisp/gnus-audio.el
lisp/gnus-bbdb.el [new file with mode: 0644]
lisp/gnus-bcklg.el
lisp/gnus-cache.el
lisp/gnus-cite.el
lisp/gnus-clfns.el [new file with mode: 0644]
lisp/gnus-cus.el
lisp/gnus-delay.el [new file with mode: 0644]
lisp/gnus-demon.el
lisp/gnus-diary.el [new file with mode: 0644]
lisp/gnus-dired.el [new file with mode: 0644]
lisp/gnus-draft.el
lisp/gnus-dup.el
lisp/gnus-eform.el
lisp/gnus-ems.el
lisp/gnus-fun.el [new file with mode: 0644]
lisp/gnus-gl.el
lisp/gnus-group.el
lisp/gnus-i18n.el [new file with mode: 0644]
lisp/gnus-int.el
lisp/gnus-kill.el
lisp/gnus-load.el [deleted file]
lisp/gnus-logic.el
lisp/gnus-mailcap.el [new file with mode: 0644]
lisp/gnus-mh.el
lisp/gnus-ml.el [new file with mode: 0644]
lisp/gnus-mlspl.el [new file with mode: 0644]
lisp/gnus-move.el
lisp/gnus-msg.el
lisp/gnus-namazu.el [new file with mode: 0644]
lisp/gnus-nocem.el
lisp/gnus-offline.el [new file with mode: 0644]
lisp/gnus-ofsetup.el [new file with mode: 0644]
lisp/gnus-picon.el
lisp/gnus-range.el
lisp/gnus-registry.el [new file with mode: 0644]
lisp/gnus-salt.el
lisp/gnus-score.el
lisp/gnus-setup.el
lisp/gnus-sieve.el [new file with mode: 0644]
lisp/gnus-soup.el
lisp/gnus-spec.el
lisp/gnus-srvr.el
lisp/gnus-start.el
lisp/gnus-sum.el
lisp/gnus-topic.el
lisp/gnus-undo.el
lisp/gnus-util.el
lisp/gnus-uu.el
lisp/gnus-vers.el [new file with mode: 0644]
lisp/gnus-vm.el
lisp/gnus-win.el
lisp/gnus-xmas.el
lisp/gnus.el
lisp/hex-util.el [new file with mode: 0644]
lisp/html2text.el [new file with mode: 0644]
lisp/ietf-drums.el [new file with mode: 0644]
lisp/imap.el [new file with mode: 0644]
lisp/lpath.el
lisp/mail-parse.el [new file with mode: 0644]
lisp/mail-prsvr.el [new file with mode: 0644]
lisp/mail-source.el [new file with mode: 0644]
lisp/mailheader.el
lisp/md5.el
lisp/message.el
lisp/messagexmas.el
lisp/messcompat.el
lisp/mm-bodies.el [new file with mode: 0644]
lisp/mm-decode.el [new file with mode: 0644]
lisp/mm-encode.el [new file with mode: 0644]
lisp/mm-extern.el [new file with mode: 0644]
lisp/mm-partial.el [new file with mode: 0644]
lisp/mm-url.el [new file with mode: 0644]
lisp/mm-util.el [new file with mode: 0644]
lisp/mm-uu.el [new file with mode: 0644]
lisp/mm-view.el [new file with mode: 0644]
lisp/mmgnus.el [new file with mode: 0644]
lisp/mml-sec.el [new file with mode: 0644]
lisp/mml-smime.el [new file with mode: 0644]
lisp/mml.el [new file with mode: 0644]
lisp/mml1991.el [new file with mode: 0644]
lisp/mml2015.el [new file with mode: 0644]
lisp/netrc.el [new file with mode: 0644]
lisp/nnagent.el
lisp/nnbabyl.el
lisp/nndb.el
lisp/nndiary.el [new file with mode: 0644]
lisp/nndir.el
lisp/nndoc.el
lisp/nndraft.el
lisp/nneething.el
lisp/nnfolder.el
lisp/nngateway.el
lisp/nnheader.el
lisp/nnheaderxm.el
lisp/nnimap.el [new file with mode: 0644]
lisp/nnir.el [new file with mode: 0644]
lisp/nnkiboze.el
lisp/nnlistserv.el
lisp/nnmail.el
lisp/nnmaildir.el [new file with mode: 0644]
lisp/nnmbox.el
lisp/nnmh.el
lisp/nnml.el
lisp/nnnil.el [new file with mode: 0644]
lisp/nnoo.el
lisp/nnrss.el [new file with mode: 0644]
lisp/nnshimbun.el [new file with mode: 0644]
lisp/nnslashdot.el [new file with mode: 0644]
lisp/nnsoup.el
lisp/nnspool.el
lisp/nntp.el
lisp/nnultimate.el [new file with mode: 0644]
lisp/nnvirtual.el
lisp/nnwarchive.el [new file with mode: 0644]
lisp/nnweb.el
lisp/nnwfm.el [new file with mode: 0644]
lisp/parse-time.el
lisp/pop3.el
lisp/qp.el [new file with mode: 0644]
lisp/read-passwd.el [new file with mode: 0644]
lisp/rfc1843.el [new file with mode: 0644]
lisp/rfc2045.el [new file with mode: 0644]
lisp/rfc2047.el [new file with mode: 0644]
lisp/rfc2104.el [new file with mode: 0644]
lisp/rfc2231.el [new file with mode: 0644]
lisp/score-mode.el
lisp/sha1-el.el [new file with mode: 0644]
lisp/sieve-manage.el [new file with mode: 0644]
lisp/sieve-mode.el [new file with mode: 0644]
lisp/sieve.el [new file with mode: 0644]
lisp/smiley.el
lisp/smime.el [new file with mode: 0644]
lisp/spam-report.el [new file with mode: 0644]
lisp/spam-stat.el [new file with mode: 0644]
lisp/spam.el [new file with mode: 0644]
lisp/starttls.el [new file with mode: 0644]
lisp/time-date.el [new file with mode: 0644]
lisp/tls.el [new file with mode: 0644]
lisp/utf7.el [new file with mode: 0644]
lisp/uudecode.el [new file with mode: 0644]
lisp/webmail.el [new file with mode: 0644]
lisp/yenc.el [new file with mode: 0644]
make.bat [new file with mode: 0755]
mkinstalldirs
readme [deleted file]
sample.lpath.el [new file with mode: 0644]
texi/ChangeLog
texi/Makefile [deleted file]
texi/Makefile.in
texi/TRANSLATION.ja [new file with mode: 0644]
texi/bk-a4.tex [new file with mode: 0644]
texi/bk-lt.tex [new file with mode: 0644]
texi/booklet.tex [new file with mode: 0644]
texi/custom.texi [deleted file]
texi/dir
texi/doclicense.texi [new file with mode: 0644]
texi/emacs-mime.texi [new file with mode: 0644]
texi/etc/bar.xpm [new file with mode: 0644]
texi/etc/gnus-group-catchup-current-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-catchup-current.xpm [new file with mode: 0644]
texi/etc/gnus-group-describe-group-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-exit-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-get-new-news-this-group-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-get-new-news-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-kill-group-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-subscribe-up.xpm [new file with mode: 0644]
texi/etc/gnus-group-unsubscribe-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-caesar-message-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-cancel-article-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-catchup-and-exit-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-catchup-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-exit-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-followup-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-followup-with-original-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-copy-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-delete-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-forward-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-get-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-originate-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-reply-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-mail-save-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-next-unread-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-post-news-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-prev-unread-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-reply-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-reply-with-original-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-save-article-file-up.xpm [new file with mode: 0644]
texi/etc/gnus-summary-save-article-up.xpm [new file with mode: 0644]
texi/etc/gnus-uu-decode-uu-up.xpm [new file with mode: 0644]
texi/etc/gnus-uu-post-news-up.xpm [new file with mode: 0644]
texi/etc/gnus.xpm [new file with mode: 0644]
texi/gnus-faq-ja.texi [new file with mode: 0644]
texi/gnus-faq.texi
texi/gnus-ja.texi [new file with mode: 0644]
texi/gnus-terms.ja [new file with mode: 0644]
texi/gnus.texi
texi/gnusconfig.tex.in [new file with mode: 0644]
texi/gnuslogo-booklet.eps [new file with mode: 0644]
texi/gnuslogo-refcard.eps [new file with mode: 0644]
texi/gnuslogo.refcard [deleted file]
texi/gnusref-ja.tex [new file with mode: 0644]
texi/gnusref.tex
texi/herds/convol11.pnm [new file with mode: 0644]
texi/herds/convol5.pnm [new file with mode: 0644]
texi/herds/gnus-herd-bw.png [new file with mode: 0644]
texi/herds/gnus-herd-new.png [new file with mode: 0644]
texi/herds/new-herd-1.png [new file with mode: 0644]
texi/herds/new-herd-2.png [new file with mode: 0644]
texi/herds/new-herd-3.png [new file with mode: 0644]
texi/herds/new-herd-4.png [new file with mode: 0644]
texi/herds/new-herd-5.png [new file with mode: 0644]
texi/herds/new-herd-6.png [new file with mode: 0644]
texi/herds/new-herd-7.png [new file with mode: 0644]
texi/herds/new-herd-8.png [new file with mode: 0644]
texi/herds/new-herd-9.png [new file with mode: 0644]
texi/herds/new-herd-section.png [new file with mode: 0644]
texi/herds/new-herd.png [new file with mode: 0644]
texi/herds/new-herd2.png [new file with mode: 0644]
texi/infohack.el [new file with mode: 0644]
texi/message-ja.texi [new file with mode: 0644]
texi/message.texi
texi/misc/ered.tif [new file with mode: 0644]
texi/misc/eseptember.tif [new file with mode: 0644]
texi/misc/fred.tif [new file with mode: 0644]
texi/misc/fseptember.tif [new file with mode: 0644]
texi/misc/larsi.png [new file with mode: 0644]
texi/misc/red.png [new file with mode: 0644]
texi/misc/red.ps [new file with mode: 0644]
texi/misc/september.png [new file with mode: 0644]
texi/pagestyle.sty [new file with mode: 0644]
texi/picons/att.png [new file with mode: 0644]
texi/picons/berkeley.png [new file with mode: 0644]
texi/picons/caltech.png [new file with mode: 0644]
texi/picons/canada.png [new file with mode: 0644]
texi/picons/cr.png [new file with mode: 0644]
texi/picons/cygnus.xbm [new file with mode: 0644]
texi/picons/gnu.xbm [new file with mode: 0644]
texi/picons/gov.xbm [new file with mode: 0644]
texi/picons/laurie.png [new file with mode: 0644]
texi/picons/mit.png [new file with mode: 0644]
texi/picons/nasa.png [new file with mode: 0644]
texi/picons/qmw.xbm [new file with mode: 0644]
texi/picons/rms.png [new file with mode: 0644]
texi/picons/ruu.xbm [new file with mode: 0644]
texi/picons/seuu.xbm [new file with mode: 0644]
texi/picons/stanford.png [new file with mode: 0644]
texi/picons/sun.png [new file with mode: 0644]
texi/picons/ubc.xbm [new file with mode: 0644]
texi/picons/ufl.png [new file with mode: 0644]
texi/picons/uio.png [new file with mode: 0644]
texi/picons/unit.png [new file with mode: 0644]
texi/picons/upenn.xbm [new file with mode: 0644]
texi/picons/wesleyan.xbm [new file with mode: 0644]
texi/picons/yale.xbm [new file with mode: 0644]
texi/postamble.tex
texi/ps/Makefile.in [new file with mode: 0644]
texi/ps/gnus-big-logo.eps [new file with mode: 0644]
texi/ps/gnus-head.eps [new file with mode: 0644]
texi/ptexinfmt.el [new file with mode: 0644]
texi/refcard-ja.tex [new file with mode: 0644]
texi/refcard.tex
texi/screen/group-topic.png [new file with mode: 0644]
texi/screen/group.png [new file with mode: 0644]
texi/screen/server.png [new file with mode: 0644]
texi/screen/summary-adopt.png [new file with mode: 0644]
texi/screen/summary-article-c-ug.png [new file with mode: 0644]
texi/screen/summary-article.png [new file with mode: 0644]
texi/screen/summary-dummy.png [new file with mode: 0644]
texi/screen/summary-empty.png [new file with mode: 0644]
texi/screen/summary-none.png [new file with mode: 0644]
texi/screen/summary-unthreaded.png [new file with mode: 0644]
texi/screen/summary.png [new file with mode: 0644]
texi/sieve.texi [new file with mode: 0644]
texi/smilies/BigFace.tif [new file with mode: 0644]
texi/smilies/FaceAngry.xpm [new file with mode: 0644]
texi/smilies/FaceDevilish.xpm [new file with mode: 0644]
texi/smilies/FaceGoofy.xpm [new file with mode: 0644]
texi/smilies/FaceGrinning.xpm [new file with mode: 0644]
texi/smilies/FaceHappy.xpm [new file with mode: 0644]
texi/smilies/FaceIronic.xpm [new file with mode: 0644]
texi/smilies/FaceKOed.xpm [new file with mode: 0644]
texi/smilies/FaceNyah.xpm [new file with mode: 0644]
texi/smilies/FaceSad.xpm [new file with mode: 0644]
texi/smilies/FaceStartled.xpm [new file with mode: 0644]
texi/smilies/FaceStraight.xpm [new file with mode: 0644]
texi/smilies/FaceTalking.xpm [new file with mode: 0644]
texi/smilies/FaceTasty.xpm [new file with mode: 0644]
texi/smilies/FaceWinking.xpm [new file with mode: 0644]
texi/smilies/FaceWry.xpm [new file with mode: 0644]
texi/smilies/FaceYukky.xpm [new file with mode: 0644]
texi/smilies/WideFaceAse1.xbm [new file with mode: 0644]
texi/smilies/WideFaceAse2.xbm [new file with mode: 0644]
texi/smilies/WideFaceAse3.xbm [new file with mode: 0644]
texi/smilies/WideFaceSmile.xbm [new file with mode: 0644]
texi/smilies/WideFaceWeep.xbm [new file with mode: 0644]
texi/splitindex [new file with mode: 0755]
texi/texi2latex.el [new file with mode: 0644]
texi/widget.texi [deleted file]
texi/xface/abrahamsen.png [new file with mode: 0644]
texi/xface/aichner.png [new file with mode: 0644]
texi/xface/blanks.png [new file with mode: 0644]
texi/xface/cosgriff.png [new file with mode: 0644]
texi/xface/drazen.png [new file with mode: 0644]
texi/xface/gertzfield.png [new file with mode: 0644]
texi/xface/goldberg.png [new file with mode: 0644]
texi/xface/graf.png [new file with mode: 0644]
texi/xface/hardaker.png [new file with mode: 0644]
texi/xface/hedbor.png [new file with mode: 0644]
texi/xface/ingrand.png [new file with mode: 0644]
texi/xface/kaplan.png [new file with mode: 0644]
texi/xface/karlheg.png [new file with mode: 0644]
texi/xface/kleinpaste.png [new file with mode: 0644]
texi/xface/kyle.png [new file with mode: 0644]
texi/xface/love.png [new file with mode: 0644]
texi/xface/moll.png [new file with mode: 0644]
texi/xface/niksic.png [new file with mode: 0644]
texi/xface/olsen.png [new file with mode: 0644]
texi/xface/patch.png [new file with mode: 0644]
texi/xface/petersen.png [new file with mode: 0644]
texi/xface/pjf.png [new file with mode: 0644]
texi/xface/riocreux.png [new file with mode: 0644]
texi/xface/schauer.png [new file with mode: 0644]
texi/xface/simmonmt.png [new file with mode: 0644]
texi/xface/simmons.png [new file with mode: 0644]
texi/xface/siu.png [new file with mode: 0644]
texi/xface/smb.png [new file with mode: 0644]
texi/xface/sobek.png [new file with mode: 0644]
texi/xface/thomas.png [new file with mode: 0644]
texi/xface/valdis.png [new file with mode: 0644]
texi/xface/verna1.png [new file with mode: 0644]
texi/xface/verna2.png [new file with mode: 0644]
texi/xface/yamaoka.png [new file with mode: 0644]
todo [new file with mode: 0644]

index db57397..ea338cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-1998-01-08  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+2004-01-04  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * lisp/smtpmail.el (smtpmail-via-smtp): Bind
-       `coding-system-for-read' by `smtpmail-coding-system' to avoid
-       dead-locking in Emacs 20.
+       * lisp/gnus-vers.el: T-gnus 6.16.6 revision 00.
 
-       * lisp/gnus.el: gnus.el (gnus-version-number): Update to version
-       6.0.2.
+2004-01-04  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-1998-01-07  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+       * lisp/gnus-vers.el: T-gnus 6.16.5 revision 00.
 
-       * lisp/nnmail.el, lisp/message.el: Sync with Quassia Gnus v0.22.
+2004-01-04  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * lisp/gnus.el: Delete autoload setting for `metamail-buffer'.
+       * lisp/gnus-vers.el: T-gnus 6.16.4 revision 00.
 
-       * lisp/gnus.el, lisp/gnus-sum.el: Sync with Quassia Gnus v0.22.
+2004-01-03  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * lisp/gnus-msg.el: Abolish function
-       `gnus-inews-insert-mime-headers'.
+       * GNUS-NEWS: Update copyright.
 
-       * lisp/gnus-msg.el, lisp/gnus-draft.el, lisp/gnus-art.el: Sync
-       with Quassia Gnus v0.22.
+       * etc/gnus-tut.txt (Gnus FAQ): Remove text version.  Refer to info
+       documentation and online version instead.
 
-       * lisp/smtpmail.el (smtpmail-coding-system): New variable; abolish
-       `smtpmail-code-conv-from'.
-       (smtpmail-via-smtp): Guard `coding-system-for-write' by
-       `smtpmail-coding-system'.
+       * GNUS-NEWS: Changed "Dired integration"
 
-       * lisp/smtpmail.el: Imported from Emacs 20.2.
+2004-01-02  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * lisp/pop3.el (pop3-movemail-file-coding-system): Change default
-       value to `binary'.
-       (pop3-open-server): Guard `coding-system-for-read' by `binary'.
+       * GNUS-NEWS: Add `gnus-group-read-ephemeral-group'.
 
-1998-01-06  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+2003-12-30  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/nnoo.el,
-       lisp/nnml.el, lisp/message.el, lisp/gnus.el, lisp/gnus-sum.el,
-       lisp/gnus-start.el, lisp/gnus-ems.el, lisp/gnus-draft.el,
-       lisp/gnus-agent.el, lisp/ChangeLog: Importing qgnus-0.22
+       * lisp/gnus-vers.el: T-gnus 6.16.3 revision 00.
 
-       * texi/message.texi, texi/gnus.texi, lisp/gnus.el, lisp/ChangeLog:
-       Importing qgnus-0.21
+2003-12-25  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * texi/message.texi, texi/gnus.texi, texi/ChangeLog,
-       lisp/nnvirtual.el, lisp/nnsoup.el, lisp/nnoo.el, lisp/nnmh.el,
-       lisp/nnmail.el, lisp/nndraft.el, lisp/gnus.el, lisp/gnus-xmas.el,
-       lisp/gnus-sum.el, lisp/gnus-start.el, lisp/gnus-score.el,
-       lisp/gnus-msg.el, lisp/gnus-group.el, lisp/gnus-draft.el,
-       lisp/gnus-art.el, lisp/ChangeLog: Importing qgnus-0.20
+       * lisp/pop3.el: Autoload `open-ssl-stream' when compiling.
 
-       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/pop3.el,
-       lisp/nntp.el, lisp/nnml.el, lisp/nnmail.el, lisp/nndoc.el,
-       lisp/message.el, lisp/gnus.el, lisp/gnus-uu.el,
-       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-start.el,
-       lisp/gnus-score.el, lisp/gnus-group.el, lisp/gnus-cache.el,
-       lisp/gnus-agent.el, lisp/ChangeLog: Importing qgnus-0.19
+2003-12-23  Reiner Steib  <Reiner.Steib@gmx.de>
 
-1997-12-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+       * GNUS-NEWS: Mention change of `e' in draft groups.
 
-       * lisp/gnus.el (gnus-version-number): Update to version 6.0.1.
+2003-12-17  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * lisp/message.el (message-resend): Enclose `message-setup' with
-       `(let (message-setup-hook) ...)' to avoid to `turn-on-mime-edit';
-       must setup `message-encoding-buffer' and `message-edit-buffer' for
-       `message-send-mail'.
+       * gnus-group.el (gnus-group-edit-group): Let the `C-c C-i' command
+       choose the language specific info file.
 
-1997-12-08  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+2003-12-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * lisp/pop3.el, lisp/message.el, lisp/gnus.el, lisp/gnus-sum.el,
-       lisp/gnus-art.el, lisp/ChangeLog: Synch'ed up to qgnus-0.18.
+       * lisp/gnus-art.el: Require `mime-image' when Emacs is running on
+       the window system.
 
-       * texi/message.texi, texi/gnus.texi, texi/ChangeLog,
-       lisp/smiley.el, lisp/pop3.el, lisp/nnweb.el, lisp/nntp.el,
-       lisp/nnml.el, lisp/nnmail.el, lisp/nnheader.el, lisp/nndraft.el,
-       lisp/message.el, lisp/lpath.el, lisp/gnus.el, lisp/gnus-util.el,
-       lisp/gnus-sum.el, lisp/gnus-start.el, lisp/gnus-picon.el,
-       lisp/gnus-nocem.el, lisp/gnus-mh.el, lisp/gnus-group.el,
-       lisp/gnus-ems.el, lisp/gnus-cite.el, lisp/gnus-art.el,
-       lisp/gnus-agent.el, lisp/dgnushack.el, lisp/ChangeLog: Importing
-       qgnus-0.18
-
-1997-11-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
-
-       * README.semi: New file.
-
-       * lisp/gnus.el (gnus-version): Rename to "Semi-gnus".
-
-1997-11-28  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
-
-       * lisp/gnus-draft.el (gnus-draft-decoding-function): New variable.
-       (gnus-draft-setup): Use `gnus-draft-decoding-function'.
-
-1997-11-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
-
-       * lisp/nnmail.el, lisp/nnheader.el, lisp/message.el, lisp/gnus.el,
-       lisp/gnus-sum.el, lisp/gnus-msg.el, lisp/gnus-art.el: sync with
-       qgnus-0.17.
-
-       * texi/message.texi, texi/gnus.texi, lisp/smiley.el, lisp/nnoo.el,
-       lisp/nnml.el, lisp/nnmail.el, lisp/nnheader.el,
-       lisp/messagexmas.el, lisp/message.el, lisp/gnus.el,
-       lisp/gnus-xmas.el, lisp/gnus-util.el, lisp/gnus-sum.el,
-       lisp/gnus-start.el, lisp/gnus-spec.el, lisp/gnus-score.el,
-       lisp/gnus-picon.el, lisp/gnus-move.el, lisp/gnus-msg.el,
-       lisp/gnus-kill.el, lisp/gnus-group.el, lisp/gnus-draft.el,
-       lisp/gnus-demon.el, lisp/gnus-cite.el, lisp/gnus-art.el,
-       lisp/ChangeLog: Quassia Gnus v0.17.
-
-       * lisp/gnus-i18n.el: New file.
-
-       * lisp/nnmail.el (nnmail-file-coding-system): Use `raw-text' in
-       default.
-
-       * lisp/nnheader.el (nnheader-file-coding-system): Use `raw-text'
-       in default.
-
-       * lisp/message.el (message-encode-function): New variable.
-       (message-forward-start-separator): Modify for mime-edit.
-       (message-forward-end-separator): Modify for mime-edit.
-       (message-setup-hook): Use `(message-maybe-setup-default-charset
-       turn-on-mime-edit)' in default.
-       (message-header-hook): Use `(eword-encode-header)' in default.
-
-       (message-send): Use local variable `message-encoding-buffer',
-       `message-edit-buffer' and `message-mime-mode' as public variables;
-       use `message-encode-function'.
-       (message-send-mail): Use `message-encoding-buffer' to get contents
-       of body; abolish `message-encode-mail-hook'; use
-       `mime-edit-maybe-split-and-send'; use `message-edit-buffer' to
-       refer original editing buffer.
-       (message-send-news): Use `message-encoding-buffer' to get contents
-       of body; abolish `message-encode-news-hook'; use
-       `mime-edit-maybe-split-and-send'; use `message-edit-buffer' to
-       refer original editing buffer.
-       (message-check-news-syntax): Call `message-check-news-body-syntax'
-       in `mime-edit-buffer'.
-       (message-do-fcc): Use `message-encoding-buffer' to get contents;
-       run `message-header-hook'.
-       (message-cancel-news): Use `std11-extract-address-components'
-       instead of `mail-extract-address-components'; bind
-       `message-encoding-buffer' and `message-edit-buffer'.
-
-       (message-maybe-setup-default-charset): New function.
-       (message-maybe-encode): New function.
-       (message-mime-insert-article): New function.
-       Add setting for mime-view.
-
-       * lisp/gnus.el (gnus-version-number): for version number for Open
-       gnus.
-       (gnus-version): Modify for Open gnus.
-
-       * lisp/gnus-sum.el: Autoload gnus-i18n.
-
-       (gnus-show-mime): `t' in default.
-       (gnus-structured-field-decoder): Use
-       `eword-decode-structured-field-body' in default.
-       (gnus-unstructured-field-decoder): Use
-       `eword-decode-unstructured-field-body' in default.
-
-       (gnus-parse-headers-hook): Use
-       `(gnus-set-summary-default-charset)' in default.
-
-       (gnus-summary-mode-map): Add binding for
-       `gnus-summary-scroll-down' and
-       `gnus-summary-preview-mime-message'.
-
-       (gnus-summary-preview-mime-message): New function.
-       (gnus-mime-partial-preview-function): New function.
-       Add setting for mime-view.
-
-       * lisp/gnus-msg.el (gnus-summary-cancel-article): Display
-       `gnus-article-buffer' instead ofb `gnus-original-article-buffer'.
-       (gnus-extended-version): Don't return version of emacsen.
-       (gnus-inews-do-gcc): Refer `message-encoding-buffer'.
-
-       * lisp/gnus-art.el (gnus-show-mime-method): Use
-       `gnus-article-preview-mime-message' instead of `metamail-buffer'
-       in default.
-       (gnus-decode-encoded-word-method): Use
-       `gnus-article-decode-encoded-word' instead of
-       `gnus-article-de-quoted-unreadable' in default.
-
-       Abolish `gnus-hack-decode-rfc1522', `gnus-decode-rfc1522',
-       `article-decode-rfc1522', `article-de-quoted-unreadable',
-       `article-mime-decode-quoted-printable-buffer' and
-       `article-mime-decode-quoted-printable'.
-       (gnus-article-decode-rfc1522): New implementation (use
-       `eword-decode-header').
-
-       (gnus-article-preview-mime-message): New function.
-       (gnus-article-decode-encoded-word): New function.
-       (gnus-content-header-filter): New function.
-       (mime-view-quitting-method-for-gnus): New function.
-       Add setting for mime-view.
-
-       * lisp/message.el: Abolish `message-max-size' because it is not
-       used.
-
-       * lisp/message.el: sync with qgnus-0.16.
-
-       * texi/Makefile, texi/message.texi, texi/gnus.texi, lisp/nnweb.el,
-       lisp/nnmh.el, lisp/nnheader.el, lisp/nnfolder.el, lisp/message.el,
-       lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
-       lisp/gnus-sum.el, lisp/gnus-srvr.el, lisp/gnus-picon.el,
-       lisp/gnus-group.el, lisp/gnus-cite.el, lisp/gnus-art.el: Quassia
-       Gnus v0.16.
-
-       * lisp/nnmh.el (nnmh-request-list-1): fix maybe.
-
-       * lisp/message.el (message-do-fcc): Guard
-       `coding-system-for-write' by `raw-text'; run
-       `message-before-do-fcc-hook'.
-
-       * lisp/gnus-msg.el (gnus-inews-do-gcc): Guard
-       `coding-system-for-write' by `raw-text'; run
-       `gnus-before-do-gcc-hook'.
-
-       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/nntp.el,
-       lisp/nnoo.el, lisp/nnml.el, lisp/nndraft.el, lisp/nnbabyl.el,
-       lisp/message.el, lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
-       lisp/gnus-util.el, lisp/gnus-sum.el, lisp/gnus-start.el,
-       lisp/gnus-spec.el, lisp/gnus-soup.el, lisp/gnus-score.el,
-       lisp/gnus-msg.el, lisp/gnus-gl.el, lisp/gnus-ems.el,
-       lisp/gnus-draft.el, lisp/gnus-cache.el, lisp/gnus-audio.el,
-       lisp/gnus-art.el, lisp/gnus-agent.el, lisp/ChangeLog: Quassia Gnus
-       v0.15.
-
-       * lisp/message.el, lisp/ChangeLog: sync with qgnus-0.14.
-
-       * texi/Makefile, texi/gnus.texi: Quassia Gnus v0.14.
-
-       * texi/dir: New file.
-
-       * texi/dir, lisp/pop3.el, lisp/nntp.el, lisp/nnml.el,
-       lisp/nnmail.el, lisp/nnfolder.el, lisp/message.el, lisp/lpath.el,
-       lisp/gnus.el, lisp/gnus-win.el, lisp/gnus-util.el,
-       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-start.el,
-       lisp/gnus-score.el, lisp/gnus-msg.el, lisp/gnus-mh.el,
-       lisp/gnus-cus.el, lisp/gnus-art.el, lisp/gnus-agent.el,
-       lisp/ChangeLog: Quassia Gnus v0.14.
-
-       * lisp/message.el, lisp/ChangeLog: sync with qgnus-0.13.
-
-       * texi/gnus.texi, texi/ChangeLog, lisp/pop3.el, lisp/nnweb.el,
-       lisp/nnmail.el: Quassia Gnus v0.13.
-
-       * lisp/nnlistserv.el: New file.
-
-       * lisp/nnlistserv.el, lisp/message.el, lisp/md5.el, lisp/lpath.el,
-       lisp/gnus.el, lisp/gnus-topic.el, lisp/gnus-sum.el,
-       lisp/gnus-score.el, lisp/gnus-picon.el, lisp/gnus-msg.el,
-       lisp/gnus-group.el, lisp/gnus-art.el, lisp/gnus-agent.el,
-       lisp/dgnushack.el, lisp/ChangeLog, GNUS-NEWS: Quassia Gnus v0.13.
-
-       * lisp/message.el: sync with qgnus-0.12.
-
-       * texi/message.texi, texi/gnus.texi, texi/gnus-faq.texi,
-       texi/ChangeLog, lisp/nntp.el, lisp/nnmh.el, lisp/nnmail.el,
-       lisp/nndraft.el, lisp/messcompat.el, lisp/message.el,
-       lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
-       lisp/gnus-sum.el, lisp/gnus-score.el, lisp/gnus-salt.el,
-       lisp/gnus-msg.el, lisp/gnus-int.el, lisp/gnus-group.el,
-       lisp/gnus-demon.el, lisp/gnus-cache.el, lisp/gnus-art.el,
-       lisp/gnus-agent.el, lisp/ChangeLog, GNUS-NEWS: Quassia Gnus v0.12.
-
-       * lisp/message.el (message-send-news-function): Use
-       `message-send-news-with-gnus' in default.
-       (message-send-via-news): Use `message-send-news' instead of
-       `message-send-news-function'.
-       (message-send-mail): Don't avoid text properties; run
-       `message-encode-mail-hook'.
-       (message-send-news): Don't avoid text properties; run
-       `message-encode-news-hook'; use `message-send-news-function'.
-       (message-send-news-with-gnus): New function.
-       (message-cancel-news): Use `message-send-news' instead of
-       `message-send-news-function'.
+       * lisp/gnus-sum.el: Don't require `mime-view'.
+
+2003-12-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnmail.el (nnmail-lazy): Replace `widget-default-get' with
+       the expanded form for Mule 2.
+
+2003-12-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-make-cus-load): Use
+       contrib/cus-dep.el to build T-gnus with Mule 2.
+
+       * contrib/cus-dep.el: Imported from Emacs 20.7 for Mule 2.
+
+2003-11-03  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/message.el (message-forward-subject-name-subject): Fixed.
+
+2003-10-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el: Don't fiddle with the `features' variable;
+       fix directories relative to the ../lisp directory in `load-path'.
+
+2003-10-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * Makefile.in (install-package): Don't call `compose-package'.
+       (install-package-ja): Ditto.
+       (package): Ditto.
+       (package-ja): Ditto.
+       (compose-package): Abolish.
+
+       * lisp/Makefile.in (compose-package): Abolish.
+
+       * lisp/dgnushack.el (dgnushack-unexporting-files): Add
+       gnus-load.el when using XEmacs.
+       (dgnushack-dont-compile-files): Add gnus-load.el.
+       (dgnushack-auto-load-file): Abolish.
+       (dgnushack-make-auto-load): Don't delete the file specified by
+       `dgnushack-auto-load-file'.
+       (dgnushack-compose-package): Abolish.
+
+2003-08-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-treat-display-x-face): Use `set-default'
+       instead of `custom-set-default' for old Emacsen.
+
+       * lisp/gnus-sum.el
+       (gnus-summary-search-article-highlight-matched-text): Replace
+       `gnus-treat-display-xface' with `gnus-treat-display-x-face'.
+
+2003-08-01  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/search): Small modified to
+       reduce its spending time.
+
+2003-07-30  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * gnus-namazu.el (gnus-namazu/group-prefixed-name): Removed.
+       (gnus-namazu/real-group-name): Removed.
+       (gnus-namazu/decode-group-name): Removed.
+       (gnus-namazu/directory-table): New internal variable.
+       (gnus-namazu/make-directory-table): New function.
+       (gnus-namazu/search): Call the above function, and use
+       `gnus-namazu/directory-table' to get a real group name from a file
+       name.
+       (gnus-namazu-create-index): Call `gnus-namazu/make-directory-table'.
+       (gnus-namazu/update-sentinel): Ditto.
+       (gnus-namazu-update-all-indices): Simplified.
+       (gnus-namazu-update-indices): New function.
+
+2003-07-28  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/group-prefixed-name): Return
+       the whole name from a given group and a method, only when it
+       exists.  Otherwise, return nil.
+       (gnus-namazu/possible-real-groups): Removed.
+       (gnus-namazu/decode-group-name): The successor of the above
+       function.
+       (gnus-namazu/real-group-name): Use the above functions, and accept
+       the third optional argument, `method'.
+       (gnus-namazu/search): Change the order getting groups and article
+       numbers from file names.
+
+2003-07-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el: Silence the byte-compiler when modifying
+       `byte-compile-function-environment' for `md5' under latest Emacs.
+
+       * texi/ptexinfmt.el (texinfo-discard-command-and-arg): Revive it
+       for Mule 2.
+
+2003-07-01  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * texi/ptexinfmt.el: @verb, @tie, @/ support.
+       (ptexinfmt-broken-facility): Abolish NO-NOTICE argument.
+       Use `ptexinfmt-disable-broken-notice-flag' instead.
+
+2003-06-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el (infohack-texi-format): Include other files
+       first.
+
+2003-06-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `read-passwd' for Mule 2.
+
+2003-06-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el: Require `bytecomp'.
+
+2003-06-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/nnshimbun.el: Moved to the emacs-w3m package.
+
+2003-06-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el (infohack-texi-format): Encode messages to
+       terminal while formatting info pages.
+
+2003-06-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-check-news-header-syntax): Replace
+       `mail-extract-address-components' with
+       `std11-extract-address-components'.
+       (message-sendmail-envelope-from): Ditto.
+       (message-buffer-name): Ditto.
+       (message-do-send-housekeeping): Ditto.
+
+2003-06-10  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/message.el (message-yank-original): When
+       `message-reply-headers' is equal to nil, do not reset its
+       message-id and references.
+
+       * .cvsignore, etc/.cvsignore, lisp/.cvsignore, texi/.cvsignore,
+       texi/ps/.cvsignore: Created.
+
+2003-06-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-fix-before-sending): Don't check for
+       `illegible text' messages (see the comment).
+
+2003-05-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+2001-07-11 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       We thank to Thierry Emery <thierry.emery@club-internet.fr> who
+       made it notice that there was a change to have to be merged from
+       Gnus. -- 2003-05-21 ky
+
+       * lisp/nnfolder.el (nnfolder-read-folder): Force to use a
+       multibyte buffer.
+
+2003-05-21  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/gnus-msg.el (gnus-message-make-user-agent): Don't use `@'
+       for rfc2616 compliance.
+
+2003-05-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-message-make-user-agent): Check whether
+       Mule 2 is running.
+
+2003-05-14  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/gnus-msg.el (gnus-user-agent): Added `gnus-mime-edit'.
+       (gnus-inews-add-send-actions): Use `gnus-message-make-user-agent'
+       instead of `gnus-extended-version'.
+       (xemacs-codename): Defvar while compiling.
+       (gnus-message-make-user-agent): Use `gnus-user-agent'.
+
+       * lisp/message.el (message-make-user-agent): If the "User-Agent" field
+       has alread exist, remove it.
+
+2003-05-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.16.2 revision 00.
+
+2003-05-05  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-sum.el (gnus-summary-toggle-header): Call
+       article-decode-encoded-words explicitly.
+
+2003-05-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * lisp/nnheader.el: Don't use `defun-maybe' for the extra std11-
+       stuff.
+
+2003-05-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.16.1 revision 00.
+
+See ChangeLog.4 for earlier changes.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/ChangeLog.1 b/ChangeLog.1
new file mode 100644 (file)
index 0000000..711e7f1
--- /dev/null
@@ -0,0 +1,4125 @@
+1999-06-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 16.
+
+       * lisp/gnus-sum.el (gnus-article-sort-by-author): Bug fix - use the
+       car of the return value of `mime-read-field'.
+
+1999-05-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 15.
+
+       * texi/gnus.texi (Customizing Articles): Abolish the treatment
+       variable `nomime' and rename
+       `gnus-treat-decode-message-body-as-default-mime-charset' with
+       `gnus-treat-decode-article-as-default-mime-charset'.
+
+       * lisp/gnus-art.el (gnus-treat-predicate): Abolish the treatment
+       variable `nomime'.
+       (gnus-article-prepare-mime-display): Call `gnus-treat-article' with
+       the 1st arg t for treating if the part is not the last one.
+       (gnus-article-decode-article-as-default-mime-charset): Renamed from
+       `gnus-article-decode-message-body-as-default-mime-charset'; Don't
+       work if `gnus-show-mime' is non-nil.
+       (gnus-treat-decode-article-as-default-mime-charset): Renamed from
+       `gnus-treat-decode-message-body-as-default-mime-charset'; add
+       choice item for decoding the whole article.
+
+1999-05-28  Yoshiki Hayashi <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * lisp/message.el (message-header-hook): Pass optional argument
+       code-conversion.
+
+1999-05-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 14.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Narrow to
+       header with trailing newline instead of the use of
+       `std11-narrow-to-header'.
+       (article-date-ut): Use `text-property-any' instead of
+       `next-single-property-change'.
+       (article-toggle-headers): Use `text-property-any' and
+       `text-property-not-all' instead of `get-text-property' or
+       `next-single-property-change'; use `gnus-hidden-properties' instead
+       of the property `invisible' with the function `add-text-properties'
+       or `remove-text-properties'; use `article-hide-headers' instead of
+       `gnus-article-maybe-hide-headers'; re-display X-Face image under
+       XEmacs after sorting fields.
+
+1999-05-25  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 13.
+       (TopLevel): Autoload "gnus-art" for `gnus-article-toggle-headers'.
+
+       * texi/gnus.texi, texi/gnus-ja.texi (Article Hiding): Replace
+       `gnus-article-hide-headers' with `gnus-article-toggle-headers'.
+
+       * lisp/gnus-sum.el (gnus-summary-article-menu,
+       gnus-summary-wash-hide-map, gnus-summary-wash-map,
+       gnus-summary-mode-map): Use `gnus-article-toggle-headers' instead
+       of `gnus-article-hide-headers'.
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Remove bitmap images
+       with text property `x-face-mule-bitmap-image';
+       don't bind `inhibit-read-only'.
+
+       * lisp/gnus-art.el (gnus-article-display-x-face-with-x-face-mule):
+       Do nothing if `window-system' is nil.
+       (gnus-article-decode-message-body-as-default-mime-charset): Don't
+       bind `buffer-read-only'; decode from (point-min) instead of (point).
+       (gnus-article-prepare-display): Bind `inhibit-read-only' to t; bind
+       `buffer-read-only' to nil; don't bind
+       `mime-preview-over-to-next-method-alist';
+       strip read-only properties after preparing.
+       (gnus-article-prepare-mime-display): Put text property
+       `article-treated-header' to the header; don't use
+       `mime-preview-move-to-next'; reduce a number of bound variables.
+       (gnus-article-display-traditional-message): Don't bind
+       `inhibit-read-only'.
+       (gnus-article-make-menu-bar): Use `gnus-article-toggle-headers'
+       instead of `gnus-article-hide-headers'.
+       (article-toggle-headers): New function.
+
+1999-05-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 12.
+
+       * texi/gnus.texi (Customizing Articles): Remove duplicates; add the
+       function `gnus-treat-decode-message-body-as-default-mime-charset'.
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Bind
+       `inhibit-read-only' to t during modifying the destination buffer.
+
+       * lisp/gnus-art.el (gnus-article-prepare-mime-display): Rewrite.
+       (article-date-ut): If there is a forwarded message, fetch Date from
+       its header instead of `gnus-current-headers'.
+       (gnus-article-display-x-face-with-x-face-mule): New function.
+       (TopLevel): Autoload "x-face-mule" for the function
+       `x-face-mule-x-face-decode-message-header'.
+       (gnus-treatment-function-alist): Remove duplicates.
+
+1999-05-21  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 11.
+
+       * lisp/gnus-art.el (gnus-article-prepare-mime-display): Don't treat
+       as a MIME message if the article is not so.
+       (gnus-article-display-traditional-message): Bind
+       `inhibit-read-only' to t.
+       (article-hide-headers): Ditto.
+
+1999-05-19  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+       (gnus-article-display-hook): Default to nil; annotate that it is an
+       obsolete variable.
+
+       * texi/gnus.texi (Customizing Articles): Document the new treatment
+       variables `mime' and `nomime'.
+
+       * lisp/gnus-art.el (gnus-treat-predicate): Handle the new treatment
+       variables `mime' and `nomime'.
+       (gnus-article-decode-message-body-as-default-mime-charset): New
+       function.
+       (gnus-article-prepare-display): Rewrite for the use of
+       `gnus-treat-article'.
+       (gnus-article-prepare-mime-display): New function.
+       (article-date-ut): Use `next-single-property-change' instead of
+       re-search.
+       (gnus-treatment-function-alist): Add a pair of
+       `gnus-treat-decode-message-body-as-default-mime-charset' and
+       `gnus-article-decode-message-body-as-default-mime-charset'.
+       (gnus-treat-decode-message-body-as-default-mime-charset): New user
+       option.
+
+1999-05-19  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-art.el (article-date-ut): Keep the original X-Sent
+       field, fix the position of the converted date to be displayed,
+       etc.
+
+1999-05-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Undo the last
+       change - don't call `gnus-treat-article'.
+
+1999-05-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Call
+       `gnus-treat-article'.
+
+1999-05-17   Daiki Ueno  <daiki@kiss.kake.info.waseda.ac.jp>
+
+       * lisp/gnus-art.el (article-date-ut): Always detete the last
+       newline of any old Date fields.
+
+1999-05-17   Daiki Ueno  <daiki@kiss.kake.info.waseda.ac.jp>
+            Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/mail-source.el (mail-source-keyword-map): New keyword
+       :connection for pop. It is introduced to enable SSL connection.
+       (mail-source-fetch-pop): Use it to bind `pop3-connection-type'.
+
+       * lisp/pop3.el : Add an autoload for `open-ssl-stream' defined in
+       `ssl'.
+       (pop3-connection-type, pop3-ssl-program-arguments): New variables.
+       (pop3-open-ssl-stream-1, pop3-open-ssl-stream): New functions.
+       (pop3-open-server): Call the latter when `pop3-connection-type' is
+       ssl.
+
+1999-05-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+       (TopLevel): Remove autoloads for `gnus-picons-display-x-face' and
+       `gnus-picons-article-display-x-face'.
+
+1999-05-16  Tsukamoto Tetsuo   <czkmt@remus.dti.ne.jp>
+
+       * texi/gnusref-ja.tex (subsec Notes): Complete words.
+       (sec GroupMode): Translate description of "P".
+
+1999-05-15  Tsukamoto Tetsuo   <czkmt@remus.dti.ne.jp>
+
+       * texi/gnusref-ja.tex: Undo the last change.
+
+1999-05-15  Tsukamoto Tetsuo   <czkmt@remus.dti.ne.jp>
+
+       * texi/gnusref-ja.tex: Fix typo.
+
+1999-05-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/*.el: Undo all of the last changes.
+
+1999-05-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/nnsoup.el (nnsoup-store-reply): Use `forward-char' instead
+       of `backward-char'.
+       * lisp/message.el (message-send-news-with-gnus,
+       message-send-mail-with-smtp, message-send-mail-with-qmail,
+       message-send-mail-with-sendmail): Ditto.
+       * lisp/gnus-picon.el (gnus-group-display-picons): Ditto.
+
+       * lisp/nnsoup.el (nnsoup-store-reply): Use `(bolp)' instead of
+       `(= (preceding-char) ?\n)'.
+       * lisp/message.el (message-send-news, message-send-mail): Ditto.
+
+       * lisp/gnus-sum.el (gnus-summary-reparent-thread): Use
+       `(end-of-line 0)' to go to the end of the previous line.
+
+       * lisp/nnmail.el (nnmail-decode-status): Don't use regexp search.
+       * lisp/message.el (message-next-header, message-remove-header):
+       Ditto.
+       * lisp/gnus-art.el (gnus-article-add-buttons-to-head,
+       gnus-article-highlight-headers, gnus-article-hide-header,
+       article-hide-boring-headers, article-hide-headers): Ditto.
+
+       * lisp/nntp.el (nntp-snarf-error-message, nntp-read-server-type):
+       Use `buffer-substring' instead of `buffer-string'.
+       * lisp/nnspool.el (nnspool-inews-sentinel): Ditto.
+       * lisp/message.el (message-wash-subject, message-reply,
+       message-make-from, message-make-organization): Ditto.
+       * lisp/md5.el (md5): Ditto.
+       * lisp/mail-source.el (mail-source-movemail): Ditto.
+       * lisp/gnus.el (gnus-getenv-nntpserver): Ditto.
+       * lisp/gnus-xmas.el (gnus-xmas-article-display-xface): Ditto.
+       * lisp/gnus-util.el (gnus-mode-string-quote): Ditto.
+       * lisp/gnus-sum.el (gnus-summary-edit-article-done,
+       gnus-simplify-subject-fuzzy): Ditto.
+       * lisp/gnus-spec.el (gnus-parse-simple-format): Ditto.
+       * lisp/gnus-picon.el (gnus-picons-make-glyph): Ditto.
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Ditto.
+       * lisp/gnus-mh.el (gnus-summary-save-in-folder): Ditto.
+       * lisp/gnus-kill.el (gnus-kill-file-apply-buffer): Ditto.
+       * lisp/gnus-art.el (gnus-article-mime-edit-exit,
+       gnus-article-edit-exit): Ditto.
+       * lisp/format-spec.el (format-spec): Ditto.
+       * lisp/dgnushack.el (dgnushack-make-package): Ditto.
+       * lisp/base64.el (base64-decode, base64-encode,
+       base64-run-command-on-region): Ditto.
+
+1999-05-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Don't specify
+       the authentication scheme if `password' is selected.
+
+1999-05-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * texi/gnus-ja.texi: (gnus-summary-enter-digest-group): Change the
+       key assignment "C-d" into "A D".
+       (Article treatment): Document the new variable
+       `gnus-article-date-lapsed-new-header'.
+
+       * lisp/mail-source.el: Use the original source without any changes.
+
+       * lisp/gnus-art.el (article-hide-headers): To work toggle hiding.
+
+       * README.T-gnus: Update what is the latest T-gnus.
+
+1999-05-04  Tatsuya Ichikawa   <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.064.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.84.
+
+1999-04-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-vm.el (gnus-summary-save-in-vm): Use
+       `vm-read-file-name' instead of `read-file-name'. This allows to use
+       the optional sixth argument HISTORY for the various environments.
+       (gnus-summary-save-article-vm): Ditto.
+       (TopLevel): Autoload "vm" for the function `vm-read-file-name'.
+
+1999-04-27  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-vm.el (gnus-summary-save-in-vm): To read the name of
+       FOLDER in the way of VM; give the value of `gnus-current-article'
+       to the function `gnus-summary-select-article' if it is called non
+       interactively.
+       (gnus-summary-save-article-vm): Accept the optional 2nd arg FOLDER.
+       If it is called interactively the name of FOLDER is read from the
+       minibuffer; bind `mime-display-header-hook',
+       `mime-display-text/plain-hook', `mime-text-decode-hook',
+       `mime-view-define-keymap-hook' and `mime-view-mode-hook' to nil
+       when the function `gnus-summary-save-article' is called.
+       (gnus-summary-save-article-vm-count,
+       gnus-summary-save-article-vm-folder): New internal variables.
+       (gnus-vm-make-folder): Bind `mime-display-header-hook',
+       `mime-display-text/plain-hook', `mime-text-decode-hook',
+       `mime-view-define-keymap-hook' and `mime-view-mode-hook' to nil
+       when the function `vm-mode' is called.
+       (vm-use-toolbar, vm-primary-inbox, vm-folder-history,
+       vm-folder-directory): Define variables for avoiding byte compile
+       warning.
+       (gnus-vm-inhibit-window-system): Abolish variable; don't require
+       `win-vm'.
+       (TopLevel): Don't autoload "vm" for the functions
+       `vm-forward-message', `vm-reply' or `vm-mail'; don't require
+       `sendmail', `message', `gnus' or `gnus-msg' but `gnus-art'.
+
+1999-04-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/pop3.el (pop3-munge-message-separator): Don't put the
+       Content-Length field break into the other fields.
+
+1999-04-18  Sin'ya Kanematsu <ksinya@quartz.ocn.ne.jp>
+
+       * texi/gnus-ja.texi: Fix typo - `gnus-auto-expirable-newgroups' ->
+       `gnus-auto-expirable-newsgroups'.
+
+1999-04-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.063.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.83.
+
+1999-04-15  NAKAGAWA Tsuneo <yaemon@alles.or.jp>
+
+       * REDME.semi.ja: Fix where the required packages are.
+
+1999-04-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+1999-04-13  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-sum.el (gnus-summary-move-article): Fix,
+       `gnus-article-mark-lists' will be broken by side effect.
+
+1999-04-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-art.el (TopLevel): Remove symbol's function definition
+       for `gnus-article-mime-decode-quoted-printable'.
+
+1999-04-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+1999-03-30  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Some fixes.
+
+1999-03-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/pop3.el (pop3-munge-message-separator): If a retrieved
+       message has a illegal date field, use `(current-time)' instead.
+
+1999-03-25  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send): Kill `message-encoding-buffer'
+       after sending.
+
+1999-03-25  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-maybe-encode): Inherit the buffer local
+       variable `mime-edit-pgp-processing' and call
+       `mime-edit-pgp-enclose-buffer'.
+
+1999-03-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/gnus-art.el (gnus-article-display-mime-message): Set up the
+       buffer local variable `default-mime-charset' of
+       `gnus-article-buffer' before `mime-display-message' is called.
+
+       * lisp/gnus-i18n.el (gnus-newsgroup-default-charset-alist): Be also
+       matched with the group name which has a method name and/or a
+       foreign server name.
+       (gnus-set-summary-default-charset): Cancel the last change.
+
+1999-03-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-i18n.el (gnus-set-summary-default-charset): Strip
+       method and foreign server name from the newsgroup name.
+
+1999-03-22  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-popup-menu): Fix.
+
+1999-03-22  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-offline.el (gnus-offline-popup-menu): Modify so that
+       the title of a popup menu is displayed under Emacs 19.34.
+       (gnus-offline-define-menu-and-key): Rewrite the function to change
+       the behavior of "Get new news" button, under XEmacs.
+
+       * lisp/gnus-ofsetup.el: Modify for Semi-gnus 6.10.xx so that
+       `pop3-fma-password' can be saved in .newsrc.eld.
+
+       * README-offline.en: Update.
+       * README-offline.ja: Ditto.
+
+1999-03-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el  (gnus-revision-number): Increment to 02.
+
+       * lisp/message.el (message-yank-original): Keep the existing
+       references.
+
+1999-03-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el  (gnus-revision-number): Increment to 01.
+       (gnus-other-frame): Rewrite on the model of `toolbar-gnus'.
+       (gnus-frame): New internal variable.
+       (gnus-frame-properties): New user option.
+
+1999-03-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.062.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.80.
+
+       * lisp/gnus-sum.el (gnus-summary-edit-article): Don't use
+       `mime-to-mml' nor `mml-to-mime'.
+
+1999-03-02  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-sum.el (gnus-select-newsgroup): Examine cached articles
+       with `gnus-cache-articles-in-group' if the current group is not
+       a virtual group.
+       (TopLevel): Autoload `gnus-cache-articles-in-group'
+
+1999-03-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * texi/gnus-ja.texi: Sync up with Semi-gnus 6.10.
+
+       * lisp/dgnushack.el (dgnushack-install-package): Don't refer to
+       `configure-package-path'. Use `early-packages', `late-packages' or
+       `last-packages' instead.
+
+1999-03-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/message.el (messgage-inhibit-body-encoding): Default to t.
+       (message-mode): Abolish `message-mime-attach-file' from doc
+       string.
+       (message-mode-map): Abolish `message-mime-attach-file' from
+       `message-mode-menu'.
+
+       * lisp/gnus-start.el (save-buffer-as-coding-system): Abolished. It
+       is given in APEL 9.13 by now.
+
+       * lisp/gnus-ems.el (gnus-decode-coding-string): Abolished.
+       (gnus-encode-coding-string): Abolished.
+       (gnus-mule-cite-add-face): Restored.
+       (gnus-cite-add-face): Restored.
+
+       * README.semi.ja: Note that APEL 9.13 or later is required.
+       * README.semi: Ditto.
+       * README.T-gnus: Ditto.
+
+1999-02-27  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.061.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.79.
+
+1999-02-27  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.060.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.78.
+
+1999-02-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * Makefile.in (add-info-suffix, remove-info-suffix): New targets.
+       (package, install-package, package-ja, install-package-ja): Use
+       them.
+       (xinfo, xinfo-ja): Only build infos.
+
+       * texi/Makefile.in (add-info-suffix): Chdir ../lisp first.
+
+       * lisp/dgnushack.el (dgnushack-add-info-suffix-maybe): Chdir
+       ../texi first.
+       (dgnushack-install-package): Don't refer to `package-path'; error
+       if the package path does not found.
+       (TopLevel): Don't define `gnus-revision-number',
+       `gnus-version-number' and `package-path'.
+
+1999-02-24  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * README.ichikawa : Removed.
+
+       * README.T-gnus : Renamed from README.ichikawa
+                         Remove description about T-gnus 6.8.
+
+1999-02-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * Makefile.in (xinfo, xinfo-ja): Make add-info-suffix, formatting,
+       and make remove-info-suffix.
+
+       * texi/Makefile.in (.texi): Don't specify the output filename when
+       makeinfo command is used.
+       (add-info-suffix, remove-info-suffix): New targets.
+
+       * lisp/dgnushack.el (dgnushack-add-info-suffix-maybe): New
+       function. It will be used for adding ".info" suffix to @setfilename
+       line in each .texi files.
+       (dgnushack-texi-file-regexp): New constant.
+       (dgnushack-info-file-regexp): Add ".info" suffix.
+
+1999-02-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/Makefile.in (all, total): Remove "auto-autoloads.el" and
+       "custom-load.el" as well.
+
+       * Makefile.in (xlick, xinfo, xinfo-ja): New targets.
+       (install-package-ja, package-ja, install-package, package): Use
+       them; use $XEMACS instead of $EMACS.
+       (osome): Use $XEMACS instead of "xemacs21".
+       (x): Ditto.
+       (XEMACS): Use "xemacs" instead of "xemacs21" in default.
+
+       * lisp/dgnushack.el (dgnushack-install-package): Remove extra files
+       in destination lisp directory.
+       (dgnushack-make-package): Don't generate "_pkg.el" file; don't
+       remove "auto-autoloads.el*" files.
+       (dgnushack-compile): Don't remove "_pkg.el" from the list.
+
+1999-02-23  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/mail-source.el (mail-source-fetch-pop): Fix typo in original
+       source and merged it.
+
+       * README.ichikawa: Update description about the latest T-gnus.
+
+1999-02-22  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-art.el (gnus-narrow-to-page): Fix that "^L" do not work.
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+1999-02-21  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/mail-source.el (mail-source-fetch-pop): Comment out
+       postscript block - I don't know why it does not work.
+       There is no Bug report from ding ML.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.059.
+       (gnus-revision-number): Fresh start from 00.
+
+       * Sync up with Pterodactyl Gnus v0.77.
+
+1999-02-18  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-start.el (save-buffers-kill-emacs): Rewrite the
+       advice. Call `gnus-offer-save-summaries'.
+
+1999-02-18  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-start.el (save-buffers-kill-emacs): Advice. Call
+       `gnus-save-newsrc-file' before `save-some-buffers' is called.
+
+       * README-offline.en: Update.
+
+       * README-offline.ja: Fix typo.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Set
+       `gnus-offline-hangup-program' and `gnus-offline-dialup-program' to
+       nil when null string is given.
+
+1999-02-18  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * texi/Makefile.in: Change to work on Windows environment and
+       other platforms.
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+1999-02-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-make-package): Fix typo.
+
+1999-02-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * Makefile.in (install-package-ja, package-ja, install-package,
+       package): New targets.
+       (PACKAGEDIR): New user option.
+
+       * lisp/Makefile.in (install-package, package): New targets.
+       (PACKAGEDIR): New user option.
+
+       * lisp/dgnushack.el (dgnushack-install-package): New function.
+       (dgnushack-make-package): New function.
+       (dgnushack-info-file-regexp): New constant.
+       (dgnushack-compile): Remove "_pkg.el" from the list.
+
+       * configure: Regenerate by autoconf-2.13.
+
+1999-02-17  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * aclocal.m4: install .el files to site-lisp/gnus instead of
+       site-lisp.
+       * Makefile.in: add new rule `all-ja'.
+
+1999-02-15  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Bug fix when
+       using nnspool.
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+1999-02-12  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/read-passwd.el: Change location of (provide 'read-passwd)
+
+       * lisp/gnus-offline.el: ditto.
+
+1999-02-12   Hidekazu Nakamura <u90121@uis-inf.co.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): To work with APOP
+       authentication scheme.
+
+       * lisp/read-passwd..el (read-pw-set-mail-source-passwd-cache):
+       Undo my change.
+
+1999-02-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-sum.el (gnus-summary-mode-map): Bound the command
+       `gnus-article-hide-headers' to "t".
+
+       * lisp/gnus-art.el (article-hide-headers): Show all headers when
+       unhiding.
+
+       * texi/gnus.texi: Fix latin chars.
+
+1999-02-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * texi/emacs-mime.texi: Fix latin chars.
+
+1999-02-12  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-sum.el (gnus-nov-parse-line): Use
+       `nnheader-nov-read-message-id' instead of `nnheader-nov-field' or
+       `nnheader-generate-fake-message-id'; use `(eobp)' instead of
+       `(eq (char-after) ?\n)'.
+
+1999-02-11  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.058.
+       (gnus-revision-number): Fresh start from 00.
+
+       * lisp/message.el (message-forward): Get back to the previous
+       design.
+       * lisp/gnus-msg.el (gnus-summary-mail-forward): Ditto.
+
+       * lisp/mail-source.el (mail-source-fetch-pop): Ignore program and
+       authentication scheme..
+
+       * lisp/message.el (message-forward-start-separator): Restored.
+       (message-forward-end-separator): Restored.
+       (message-signature-before-forwarded-message): Restored.
+       (message-included-forward-headers): Restored.
+
+       * lisp/message.el (message-make-forward-subject): Use "(none)" if
+       the original article has no subject.
+
+       * Sync up with Pterodactyl Gnus v0.76.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Change for pGnus 0.76.
+
+1999-02-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/score-mode.el (gnus-score-edit-exit): Use
+       `save-buffer-as-coding-system' instead of
+       `write-region-as-coding-system'.
+       * lisp/gnus-start.el (gnus-save-newsrc-file): Ditto.
+
+       * lisp/gnus-start.el (save-buffer-as-coding-system): New function
+       defined with `defun-maybe'. NOTE: It should be deleted in the
+       future.
+
+       * lisp/gnus-sum.el (TopLevel): Require `mime-play' when compile.
+
+1999-02-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus-sum.el (gnus-mime-extract-message/rfc822): New
+       implementation.
+
+1999-02-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+1999-02-08  Masatoshi Tsuchiya  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-articles-to-read): Use maximum number in
+       default instead of `gnus-large-newsgroup'.
+
+1999-02-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+1999-02-08  Masatoshi Tsuchiya  <tsuchiya@pine.kuee.kyoto-u.ac.jp>,
+            Katsumi Yamaoka   <yamaoka@jpl.org>,
+            Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-sum.el (gnus-articles-to-read): If the number of
+       unread articles is more than `gnus-large-newsgroup', use it in
+       default instead of the maximum number.
+
+1999-02-08  MORIOKA Tomohiko  <morioka@jaist.ac.jp>,
+            Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-mime-extract-multipart): New function;
+       add it to the acting-condition for extracting mulitpart messages.
+       (gnus-mime-extract-message/rfc822): New function; add it to the
+       acting-condition for extracting message/rfc822 or message/news.
+
+1999-02-08  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/nntp.el: Change nnmail-read-passwd -> mail-source-read-passwd.
+
+1999-02-08  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * README-offline.ja: Change for current version.
+       * README-offline.en: Ditto.
+
+1999-02-07  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+1999-02-04  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el: Delete security notice.
+       (gnus-offline-pop-password-file): Removed.
+       (gnus-offline-pop-password-decoding-function): Removed.
+       (gnus-offline-gnus-get-new-news): Revert to its original.
+
+1999-02-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+1999-02-04  YOSHIZAWA Masahiro <manbou@ceres.dti.ne.jp>
+
+       * README-offline.en: New description.
+       * README-offline.ja: Ditto.
+
+1999-02-03  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Change to 01
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Add default value.
+
+1999-02-03  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): New constant.
+
+1999-02-02  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Ask save password
+       information to .newsrc file.
+
+       * lisp/gnus.el (gnus-variable-list): Undo my last change.
+
+       * lisp/read-password.el (read-pw-set-mail-source-passwd-cache): Do
+       not input password if mail-source-password-cache is non nil.
+
+1999-02-03   Hidekazu Nakamura <u90121@uis-inf.co.jp>
+
+       * lisp/read-passwd.el (read-pw-set-mail-source-passwd-cache): To
+       work with APOP authentication scheme.
+
+1999-02-02  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): To work with
+       external movemail program.
+
+       * lisp/gnus.el (gnus-variable-list): Add
+       mail-source-password-cache to save password information.
+
+1999-02-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.057.
+
+       * Sync up with Pterodactyl Gnus v0.75.
+
+1999-02-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-gnus-get-new-news): Undo my
+       change.
+
+1999-02-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Close
+       parentheses.
+       (gnus-offline-define-menu-on-agent): Ditto.
+
+1999-02-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * README.ichikawa: Fix about the last version of T-gnus based on
+       Gnus 5.6.
+
+1999-02-01  Akihiro Arisawa   <ari@mei9.advantest.co.jp>
+
+       * lisp/nndoc.el (nndoc-mime-digest-type-p): Add the element of
+       `header-begin' to type-alist for mime-digest.
+
+1999-02-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * README-offline.ja: Add description written by YOSHIZAWA Masahiro
+       <manbou@ceres.dti.ne.jp>
+
+1999-02-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+            Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-gnus-get-new-news): Modify for
+       pGnus with mail-source.el.
+
+       * lisp/gnus-offline.el: Use (running-pterodactyl-gnus-0_73-or-later)
+        to check pGnus 0.73 or later instead of (locate-library "mail-source")
+
+1999-02-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nndoc.el (nndoc-mime-parts-type-p): Strip leading white
+       space from the matching pattern.
+
+1999-02-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-nov-parse-extra): Abolished.
+       (gnus-nov-parse-line): Use `char-after' instead of `following-char'
+       ; use `nnheader-nov-parse-extra' instead of `gnus-nov-parse-extra'.
+
+1999-01-31  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el: Abolish macro `gnus-nov-read-integer',
+       `gnus-nov-skip-field' and `gnus-nov-field'.
+       (gnus-nov-parse-line): Use `nnheader-nov-field' and
+       `nnheader-nov-read-integer' instead of `gnus-nov-field' and
+       `gnus-nov-read-integer'.
+       (gnus-get-newsgroup-headers-xover): Use
+       `gnus-retrieve-parsed-headers'.
+
+       * lisp/gnus-cache.el (gnus-cache-retrieve-parsed-headers): Use
+       `gnus-cache-braid-headers',
+       `nnheader-get-newsgroup-headers-xover*' and
+       `nnheader-retrieve-headers-from-directory*' instead of
+       `gnus-get-newsgroup-headers-xover', `gnus-cache-braid-parsed-nov'
+       nor `gnus-cache-braid-parsed-heads'; abolish function
+       `gnus-cache-braid-parsed-nov' and `gnus-cache-braid-parsed-nov'.
+       (gnus-cache-braid-headers): New function.
+
+       * lisp/nnheader.el (nnheader-nov-read-integer): Use
+       `(search-forward "\t" eol 'move)' instead of `(forward-char 1)' as
+       same as `gnus-nov-read-integer'.
+       (nnheader-retrieve-headers-from-directory*): New function.
+       (nnheader-retrieve-headers-from-directory): Use
+       `nnheader-retrieve-headers-from-directory*'.
+       (nnheader-get-newsgroup-headers-xover*): New function.
+
+1999-01-30  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnmh.el (nnmh-retrieve-parsed-headers): Use
+       `nnheader-retrieve-headers-from-directory'.
+
+       * lisp/nnheader.el (nnheader-retrieve-headers-from-directory): New
+       function.
+
+1999-01-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version): Modify for SEMI 1.13.
+
+       * lisp/gnus-int.el (gnus-retrieve-parsed-headers): Use
+       `gnus-cache-retrieve-parsed-headers' instead of
+       `gnus-cache-retrieve-headers'.
+
+       * lisp/gnus-cache.el (gnus-cache-retrieve-parsed-headers): New
+       function.
+       (gnus-cache-braid-parsed-nov): New function.
+       (gnus-cache-braid-parsed-heads): New function.
+
+1999-01-30  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: Rewrite to work with pGnus v0.74 based T-gnus.
+       * lisp/gnus-ofsetup.el: Ditto.
+
+       * lisp/pop3-fma.el: Removed because after pGnus0.73 , pGnus can treat
+       multiple pop3 account.
+
+1999-01-29  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/read-passwd.el: New file.
+
+1999-01-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (running-pterodactyl-gnus-0_73-or-later): Provide as
+       a new feature.
+
+       * lisp/mail-source.el (mail-source-read-passwd): Don't load
+       "passwd" if the function `read-passwd' already exists.
+
+       * lisp/gnus-start.el (gnus-read-active-file): Eliminate duplicated
+       select methods.
+
+       * lisp/gnus-group.el (gnus-group-catchup-current): Fix typo.
+
+1999-01-27  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.056.
+
+       * Sync up with Pterodactyl Gnus v0.74.
+
+1999-01-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-mail-digest): Reselect the message
+       frame after selecting a new article if the value of
+       `message-use-multi-frames' is non-nil and more than one articles
+       are given.
+
+1999-01-28  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-move-article): Fix, could not
+       respool article.
+
+1999-01-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnmh.el (nnmh-retrieve-parsed-headers): Bind `in-reply-to'
+       and `cur' as temporary variables.
+
+1999-01-25  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-article-sort-by-author): fixed.
+
+1999-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-int.el (gnus-retrieve-parsed-headers): Add new
+       optional arguments `dependencies' and `force-new'; new
+       implementation; call `retrieve-parsed-headers' if it is found.
+
+       * lisp/nnmh.el (nnmh-retrieve-parsed-headers): New function.
+
+1999-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-select-newsgroup): Use
+       `gnus-retrieve-parsed-headers' instead of `gnus-retrieve-headers'
+       and `gnus-get-newsgroup-headers-xover' or
+       `gnus-get-newsgroup-headers'.
+
+       * lisp/gnus-int.el (gnus-retrieve-parsed-headers): New function.
+
+1999-01-26  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el: Add security notice.
+
+1999-01-25  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * README-offline.ja: New file - Variable and command description
+       for gnus-offline(Japanese edition).
+       * README-offline.en: New file - Ditto (English edition).
+
+1999-01-25  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-pop-password-file): New
+       variable.
+       (gnus-offline-pop-password-decoding-function): New variable.
+       (gnus-offline-get-new-news): When `gnus-offline-pop-password-file'
+       is non-nil, get one's password information from a file specified
+       by this variable, and don't store the passwords as a variable.
+       * lisp/smiley.el (smiley-buffer): Avoid a few duplicate
+       translations.
+
+1999-01-23  Kiyokazu SUTO  <suto@merry.xmath.ous.ac.jp>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Use
+       `message-list-references' for gathering IDs from yanked articles.
+
+       * lisp/message.el (message-list-references): New function.
+       (message-yank-original): Use it for gathering IDs from a yanked
+       article.
+
+1999-01-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-reply): Get the references from
+       `In-Reply-To' field if there were no references and `In-Reply-To'
+       field looks promising.
+       (message-yank-original): Try to fetch ID from `In-Reply-To' field
+       if `References' field does not exist.
+       (message-yank-original): Use `std11-narrow-to-header' instead of
+       `message-narrow-to-head'.
+
+1999-01-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Fetch IDs from
+       `gnus-current-headers' instead of article header.
+
+1999-01-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Save the beginning
+       position of the yanked articles -- apologize to SUTO-san, it has
+       been supported in his original code, but I didn't.
+
+       * lisp/message.el: Replace line endings from `CRLF' to `LF'.
+
+1999-01-21  Hiroaki Matsui <matu@uxd.fc.nec.co.jp>
+
+       * lisp/message.el : Fix typo.
+
+1999-01-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-yank-original): If
+       `message-yank-add-new-references' is non-nil and this command is
+       called interactively, new IDs from the yanked article will be added
+       to `References' field.
+       (message-yank-add-new-references): New user option.
+       (message-header-format-alist): Use `message-shorten-references' for
+       `References' in default.
+
+1999-01-20  Kiyokazu SUTO  <suto@merry.xmath.ous.ac.jp>,
+            Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Replace `References'
+       field with the gathered Message-IDs and References if more than one
+       articles are given.
+
+1999-01-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Reselect the message
+       frame after selecting a new article if the value of
+       `message-use-multi-frames' is non-nil and more than one articles
+       are given.
+
+1999-01-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.055.
+
+       * Sync up with Pterodactyl Gnus v0.72.
+
+1999-01-19  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * README.semi.ja: Add keiichi and nana-gnus to the branches info.
+       Modify the directory name for the daily snapshots.
+       * README.semi: Ditto.
+
+       * README.branch.ja: Modified for Semi-gnus 6.10, etc.
+       * README.branch: Ditto.
+
+1999-01-19  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-reply): Cancel the last change.
+       (message-followup): Cancel the last change.
+       (message-wide-reply): Cancel the last change.
+
+       * lisp/gnus-msg.el (gnus-summary-gather-references): Abolished.
+       (gnus-summary-reply): Cancel the last change.
+       (gnus-post-news): Cancel the last change.
+
+1999-01-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-move-article): Don't copy
+       expirable marks if the destination group is not expirable.
+
+1999-01-16  Kiyokazu SUTO  <suto@merry.xmath.ous.ac.jp>
+
+       * lisp/message.el (message-reply): Accept references as a new
+       optional arg.
+       (message-followup): Ditto.
+       (message-wide-reply): Ditto.
+
+       * lisp/gnus-msg.el (gnus-summary-gather-references): New function.
+       (gnus-summary-reply): Use it
+       (gnus-post-news): Use it.
+
+1999-01-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.054.
+
+       * Sync up with Pterodactyl Gnus v0.71.
+
+1999-01-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.053.
+
+       * Sync up with Pterodactyl Gnus v0.70.
+
+1999-01-13  Kiyokazu SUTO  <suto@merry.xmath.ous.ac.jp>
+
+       * lisp/nnspool.el (nnspool-retrieve-headers): Protect against empty
+       body.
+
+1999-01-13  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: Add Tsukamoto Tetsuo
+       <czkmt@remus.dti.ne.jp> to author and maintainer.
+
+1999-01-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnmail.el (nnmail-article-group): Don't infloop.
+
+1999-01-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * TODO.ja: Modified for Cancel-Lock feature.
+
+       * lisp/nntp.el (nntp-request-post): Put a Message-ID generated by
+       server if it does not exist in the article.
+       (nntp-request-post): Run `nntp-prepare-post-hook'.
+       (nntp-async-trigger): Save a response from the server in
+       `nntp-process-response' after sending a command.
+       (nntp-wait-for): Ditto.
+       (nntp-prepare-post-hook): New hook, run just before posting an
+       article.
+
+       * lisp/nnheader.el (nnheader-init-server-buffer): Make
+       `nntp-process-response' be buffer-local in `nntp-server-buffer'.
+       (nntp-process-response): New variable, used for holding a response
+       from the server after sending a command.
+
+1999-01-11  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/message.el (message-draft-coding-system): Don't Call
+       `coding-system-p'. Find its default value using
+       `find-coding-system' instead.
+
+1999-01-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-munge-message-separator): Use
+       `parse-time-string'.
+
+       * lisp/gnus-vm.el (gnus-summary-save-in-vm): Save window config,
+       select the article before saving.
+
+1999-01-09  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-popup-menu): Bug fix -- Use
+       `gnus-offline-menu-on-agent' if `miee-popup-menu' does not exist.
+
+1999-01-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-last): Use `split-string' instead of
+       `pop3-string-to-list'.
+       (pop3-stat): Ditto.
+       (pop3-munge-message-separator): Ditto.
+       (pop3-string-to-list): Abolished.
+
+1999-01-06  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-setup): Don't call
+       `gnus-offline-agent-expire' when 'gnus-agent-expire-all' is
+       non-nil.
+       (gnus-offline-define-menu-on-miee): Call `easy-menu-add' under
+       XEmacs.
+       (gnus-offline-popup-menu): New function.
+       (gnus-offline-define-menu-and-key): Call it under Emacs to create
+       a popup menu in the group buffer.
+
+1999-01-04  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.052.
+
+       * Sync up with Pterodactyl Gnus v0.69.
+
+1998-12-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-preview-mime-message): Always
+       select the article before previewing. Abolish prefix arg.
+
+       * lisp/gnus-art.el (gnus-mime-preview-quitting-method): re-select
+       the article without reservation.
+       (gnus-article-display-mime-message): Show all headers if
+       `gnus-have-all-headers' the local var of summary buffer is non-nil.
+
+1998-12-25  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-check-buffer): Rewrite (checking
+       for buffer object).
+
+1998-12-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (mime-preview-over-to-next-method-alist): Use
+       `gnus-summary-next-article' in `gnus-original-article-mode'.
+       (mime-preview-over-to-previous-method-alist): Use
+       `gnus-summary-prev-article' in `gnus-original-article-mode'.
+
+1998-12-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-bbdb.el (toplevel): Define `bbdb-pop-up-elided-display'
+       for avoiding byte-compile warning.
+
+       * lisp/gnus-art.el (gnus-article-mode-map): Define almost undefined
+       keys to `gnus-article-read-summary-keys'.
+       (gnus-article-check-buffer): Check for a major-mode in
+       `gnus-original-article-buffer' as well.
+       (gnus-article-prepare-display): Set `gnus-article-current-summary'
+       to `gnus-summary-buffer'.
+
+1998-12-21  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el (pop3-fma-movemail): Work with movemail.exe
+       with APOP extention.
+
+1998-12-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-read-newsrc-el-file): Bug (referring to
+       unbounded variable) fix.
+
+1998-12-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-read-newsrc-el-file): Don't load newsrc
+       file if it does not exist.
+
+1998-12-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: (gnus-offline-define-menu-on-miee)
+       (gnus-offline-define-menu-on-agent): Use Japanized menu when using
+       under Meadow.
+
+1998-12-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.051.
+
+       * Sync up with Pterodactyl Gnus v0.68.
+
+1998-12-14  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Bug
+       fix.
+
+1998-12-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-find-file-noselect): Call
+       `find-file-noselect-as-coding-system' with CODING-SYSTEM as the
+       1st arg.
+
+       * lisp/gnus-score.el (gnus-score-load-score-alist): Call
+       `insert-file-contents-as-coding-system' with CODING-SYSTEM as the
+       1st arg.
+       * lisp/nnmail.el (nnmail-find-file): Ditto.
+       * lisp/nnheader.el (nnheader-insert-file-contents): Ditto.
+
+       * lisp/score-mode.el (gnus-score-edit-exit): Call
+       `write-region-as-coding-system' as the 1st arg.
+       * lisp/gnus-start.el (gnus-save-newsrc-file): Ditto.
+
+       * lisp/gnus-start.el (gnus-read-newsrc-el-file): Call
+       `insert-file-contents-as-coding-system' with CODING-SYSTEM as the
+       1st arg.
+
+       * lisp/gnus-score.el (gnus-score-save): Call
+       `gnus-write-buffer-as-coding-system' with CODING-SYSTEM as the 1st
+       arg.
+       * lisp/gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
+       (gnus-cache-save-buffers): Ditto.
+
+       * lisp/gnus-util.el (gnus-write-buffer-as-coding-system): Be
+       CODING-SYSTEM the 1st arg.
+
+       * lisp/nnmail.el (nnmail-write-region): Call
+       `write-region-as-coding-system' as the 1st arg.
+       * lisp/gnus-agent.el (gnus-agent-expire): Ditto.
+       (gnus-agent-fetch-headers): Ditto.
+       (gnus-agent-flush-cache): Ditto.
+       (gnus-agent-fetch-articles): Ditto.
+       (gnus-agent-save-history): Ditto.
+       (gnus-agent-save-groups): Ditto.
+       (gnus-agent-save-active): Ditto.
+
+1998-12-14  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-and-key): Bug
+       fix.
+       Overwrite the toolbar spec for gnus-group-mode, under XEmacs.
+
+1998-12-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-find-file-noselect): Use
+       `find-file-noselect-as-coding-system' (renamed from
+       `find-file-noselect-as-specified-coding-system').
+
+       * lisp/gnus-score.el (gnus-score-load-score-alist): Use
+       `insert-file-contents-as-coding-system' (renamed from
+       `insert-file-contents-as-specified-coding-system').
+       * lisp/nnmail.el (nnmail-find-file): Ditto.
+       * lisp/nnheader.el (nnheader-insert-file-contents): Ditto.
+
+       * lisp/score-mode.el (gnus-score-edit-exit): Use
+       `write-region-as-coding-system' (renamed from
+       `write-region-as-specified-coding-system').
+       * lisp/gnus-start.el (gnus-save-newsrc-file): Ditto.
+
+       * lisp/gnus-start.el (gnus-read-newsrc-el-file): Use
+       `insert-file-contents-as-coding-system' (renamed from
+       `insert-file-contents-as-specified-coding-system').
+
+       * lisp/gnus-score.el (gnus-score-save): Use
+       `gnus-write-buffer-as-coding-system' (renamed from
+       `gnus-write-buffer-as-specified-coding-system').
+       * lisp/gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
+       (gnus-cache-save-buffers): Ditto.
+
+       * lisp/gnus-util.el (gnus-write-buffer-as-coding-system): Renamed
+       from 'gnus-write-buffer-as-specified-coding-system'.
+
+       * lisp/nnmail.el (nnmail-write-region): Use
+       `write-region-as-coding-system' (renamed from
+       `write-region-as-specified-coding-system').
+       * lisp/gnus-agent.el (gnus-agent-expire): Ditto.
+       (gnus-agent-fetch-headers): Ditto.
+       (gnus-agent-flush-cache): Ditto.
+       (gnus-agent-fetch-articles): Ditto.
+       (gnus-agent-save-history): Ditto.
+       (gnus-agent-save-groups): Ditto.
+       (gnus-agent-save-active): Ditto.
+
+1998-12-14  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Bug
+       fix.
+       (gnus-offline-set-offline-sendmail-function): Bug fix.
+
+1998-12-12  Hidekazu Nakamura <u90121@uis-inf.co.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Bug fix.
+
+1998-12-12  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Bug
+       fix.
+       (gnus-offline-set-offline-sendmail-function): Bug fix.
+
+1998-12-11  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Change
+       easy-menu-define to easy-menu-change to override miee menu.
+
+1998-12-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-find-file-noselect): Call
+       `find-file-noselect-as-specified-coding-system' directly.
+
+1998-12-10  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-setup): Add
+       gnus-offline-setup to gnus-group-mode-hook.
+       (gnus-offline-set-offline-sendmail-function): Bug fix.
+
+1998-12-10  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-on-miee): Bug
+       fix.
+       (gnus-offline-define-menu-on-agent): Bug fix.
+
+1998-12-10  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-movemail): Use `write-region-as-binary'
+       instead of `append-to-file'.
+       (pop3-movemail-file-coding-system): Abolished.
+
+       * lisp/nnheader.el (nnheader-find-file-noselect): Use
+       `find-file-noselect-as-specified-coding-system' instead of
+       `find-file-noselect'.
+
+       * lisp/gnus-score.el (gnus-score-load-score-alist): Use
+       `insert-file-contents-as-specified-coding-system' instead of
+       `insert-file-contents'.
+       * lisp/nnmail.el (nnmail-find-file): Ditto.
+       * lisp/nnheader.el (nnheader-insert-file-contents): Ditto.
+
+       * lisp/message.el (message-send-mail-with-qmail): Enclose
+       `call-process-region' with `as-binary-process'.
+       (message-send-mail-with-sendmail): Ditto.
+       (message-send-coding-system): Abolished.
+
+       * lisp/score-mode.el (gnus-score-edit-exit): Emulate
+       `save-buffer' with `write-region-as-specified-coding-system'.
+       * lisp/gnus-start.el (gnus-save-newsrc-file): Ditto.
+
+       * lisp/gnus-start.el (gnus-read-newsrc-el-file): Emulate `load'
+       with `insert-file-contents-as-specified-coding-system' and
+       `eval-region'.
+
+       * lisp/gnus-score.el (gnus-score-save): Use
+       `gnus-write-buffer-as-specified-coding-system' instead of
+       `gnus-write-buffer'.
+       * lisp/gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
+       (gnus-cache-save-buffers): Ditto.
+
+       * lisp/gnus-util.el (gnus-output-to-mail): Use
+       `write-region-as-binary' instead of `append-to-file'.
+       (gnus-output-to-mail): Use `gnus-write-buffer-as-binary' instead
+       of `gnus-write-buffer'.
+       (gnus-write-buffer-as-specified-coding-system): New function.
+       (gnus-write-buffer-as-binary): New function.
+
+       * lisp/nnmail.el (nnmail-write-region): Use
+       `write-region-as-specified-coding-system' instead of
+       `write-region'.
+       * lisp/gnus-agent.el (gnus-agent-expire): Ditto.
+       (gnus-agent-fetch-headers): Ditto.
+       (gnus-agent-flush-cache): Ditto.
+       (gnus-agent-fetch-articles): Ditto.
+       (gnus-agent-save-history): Ditto.
+       (gnus-agent-save-groups): Ditto.
+       (gnus-agent-save-active): Ditto.
+
+1998-12-10  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-after-jobs-done): Create menu
+       using 'easymenu'.
+
+1998-12-09  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-after-jobs-done): Don't call
+       `gnus-offline-agent-expire' under XEmacs.
+
+1998-12-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/gnus-ja.texi: Fix latin chars.
+       * texi/gnus.texi: Ditto.
+
+       * texi/ChangeLog: Shrunk.
+
+       * text/widget.texi: Removed.
+       * texi/custom.texi: Removed.
+
+       * lisp/ChangeLog: Fix latin chars.
+
+       * lisp/pop3.el (pop3-open-server): Use
+       `open-network-stream-as-binary' instead of `open-network-stream'.
+       * lisp/nntp.el (nntp-open-network-stream): Ditto.
+       * lisp/gnus-gl.el (bbb-connect-to-bbbd): Ditto.
+
+       * lisp/nntp.el (nntp-open-rlogin): Enclose `start-process' with
+       `as-binary-process'.
+       (nntp-open-telnet): Ditto.
+
+       * lisp/nntp.el (nntp-coding-system-for-write): Abolished.
+       (nntp-coding-system-for-read): Abolished.
+
+       * lisp/nndb.el: Don't require `tcp'.
+
+1998-12-07  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-get-parameter-with-eval): Call
+       `message-get-parameter' with arg `key' first.
+
+1998-12-07  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.050.
+
+       * Sync up with Pterodactyl Gnus 0.65.
+
+1998-12-06  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/message.el (message-cite-original-without-signature): Do
+       not use mml-quote-region.
+
+       * lisp/message.el (message-cite-original): Ditto.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.049.
+
+       * Sync up with Pterodactyl Gnus 0.64.
+
+1998-12-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-show-article): Don't use
+       `mm-destroy-parts'.
+
+1998-12-04  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.048.
+
+       * Sync up with Pterodactyl Gnus 0.63.
+
+1998-12-04  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.047.
+
+       * Sync up with Pterodactyl Gnus 0.62.
+
+       * README.ichikawa: Add description of required APEL/FLIM/SEMI.
+
+1998-12-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nndraft.el (nndraft-request-article): Don't bind
+       `nnmail-file-coding-system'.
+
+1998-12-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.046.
+
+       * Sync up with Pterodactyl Gnus 0.61.
+
+1998-12-02  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/smtp.el: Abolished - Use smtp.el in FLIM.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.045.
+
+       * Sync up with Pterodactyl Gnus 0.59.
+
+1998-12-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.044.
+
+       * Sync up with Pterodactyl Gnus 0.58.
+
+1998-12-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.043.
+
+       * Sync up with Pterodactyl Gnus 0.57.
+
+1998-11-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/base64.el (base64-decode-region): Use `defun-maybe'.
+       (base64-encode-region): Ditto.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.042.
+
+       * Sync up with Pterodactyl Gnus 0.56.
+
+1998-11-29  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: Fix typo of DOC string.
+
+       * lisp/score-mode.el: Change default value
+       score-mode-coding-system 'binary to 'ctext.
+
+1998-11-28  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.041.
+
+       * Sync up with Pterodactyl Gnus 0.55.
+
+1998-11-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-supersede-article): Bind
+       `gnus-message-setup-hook' to minimum setting.
+
+       * lisp/message.el (message-supersede-setup-for-mime-edit): New
+       function.
+       (message-supersede-setup-function): New user option. Use
+       `message-supersede-setup-for-mime-edit' in default.
+       (message-supersede): Call `message-supersede-setup-function' if it
+       is non-nil.
+       (message-supersede-setup-hook): New user option.
+
+       * lisp/message.el (message-bounce-setup-for-mime-edit): Don't
+       delete header separator. It is up to MIME-Edit to do so.
+
+1998-11-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.040.
+
+       * Sync up with Pterodactyl Gnus 0.54.
+
+1998-11-24  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-version-number): Update to
+       2.00.
+
+       * lisp/pop3-fma.el (pop3-fma-save-password-information): New
+       variable. Do not save password information when
+       `pop3-fma-save-password-information' set to nil (in default).
+       (pop3-fma-encode-string): abolished - because of difference of
+       FLIM API.
+       (pop3-fma-decode-string): Ditto.
+
+1998-11-21  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.039.
+
+       * Sync up with Pterodactyl Gnus 0.53.
+
+       * lisp/pop3-fma.el (pop3-fma-init-message-hook): Change
+       message-send-hook to mime-edit-translate-hook - enbug.
+
+1998-11-20  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: Update to beta5.
+
+       * lisp/gnus-ofsetup.el: Update to beta5.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.038.
+
+       * Sync up with Pterodactyl Gnus 0.52.
+
+1998-11-19  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/message.el (message-get-reply-buffer): Abolished.
+       (message-get-original-reply-buffer): Abolished.
+       (message-get-parameter): New inline function.
+       (message-get-parameter-with-eval): New macro.
+       (message-fetch-reply-field): Do not use `message-get-reply-buffer'.
+       (message-yank-original): Ditto.
+       (message-setup): Use `message-get-parameter'.
+       (message-mime-insert-article): Use
+       `message-get-parameter-with-eval' instead of
+       `message-get-original-reply-buffer'.
+
+       * lisp/gnus-msg.el (gnus-inews-add-send-actions): Do not add
+       `set-window-configuration' to action when
+       `message-use-multi-frames' is non-`nil'.
+
+1998-11-19  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.037.
+
+       * Sync up with Pterodactyl Gnus 0.51.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Force set
+       `use-miee' to t if `news-method' is equal to "nnspool".
+       (gnus-setup-for-offline): Put a question for "Agent directory"
+       only if `gnus-offline-news-fetch-method' is equal to `nnagent'.
+       (Top-Level): Defvar `use-miee' for avoiding byte-compile warning.
+
+1998-11-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-save-article-rmail): Use
+       `gnus-summary-save-in-rmail' instead of
+       `rmail-output-to-rmail-file'.
+
+1998-11-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-mimic-kill-buffer): Rewrite.
+
+1998-11-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.036.
+
+       * Sync up with Pterodactyl Gnus 0.50.
+
+1998-11-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-mimic-kill-buffer): New function.
+       (message-mode-map): Use it for `C-x k'.
+
+1998-11-18  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/message.el (message-dont-send): Use `message-delete-frame'.
+
+1998-11-18  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.035.
+
+       * Sync up with Pterodactyl Gnus 0.49.
+
+1998-11-17  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/message.el (message-dont-send): Use `message-save-drafts'
+       instead of `save-buffer'.
+
+1998-11-17  Hiroaki Matsui  <matu@uxd.fc.nec.co.jp>
+
+       * lisp/message.el (message-clone-locals): Add
+       "user-mail-address" and "user-full-name" to matching pattern.
+
+1998-11-14  Kenji Itoh  <keit@tpj.co.jp>
+
+       * lisp/nnmail.el (nnmail-read-passwd): Use `read-passwd' if it
+       exists as a function.
+
+       * lisp/pop3.el (pop3-read-passwd): Ditto.
+
+1998-11-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.034.
+       (gnus-version): Modify for SEMI 1.11, FLIM 1.12.
+
+1998-11-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * make.bat: Replace line endings from `LF' to `CRLF'.
+
+1998-11-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.033.
+
+       * Sync up with Pterodactyl Gnus 0.48.
+
+1998-11-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/emacs-mime.texi: Fix iso-8859-1 chars.
+
+       * lisp/message.el (message-send-news): Call
+       `message-maybe-split-and-send-news' with an arg `method'.
+       (message-maybe-split-and-send-news): Accept an arg `method'.
+
+       * lisp/rfc1843.el: Defvar `gnus-decode-encoded-word-function'.
+
+       * lisp/mm-uu.el: Require `gnus-mailcap'.
+       * lisp/mm-decode.el: Require `gnus-mailcap' instead of `mailcap'.
+       * lisp/mm-encode.el: Ditto.
+       * lisp/gnus-mailcap.el: Provide `gnus-mailcap' instead of `mailcap'.
+
+1998-11-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.032.
+
+       * Sync up with Pterodactyl Gnus 0.47.
+
+1998-11-15  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.031.
+
+       * Sync up with Pterodactyl Gnus 0.46.
+
+1998-11-14  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.030.
+
+       * Sync up with Pterodactyl Gnus 0.44.
+
+1998-11-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-header-presentation-method): Use
+       `mime-insert-header' instead of `mime-insert-decoded-header'.
+
+       * lisp/nnheader.el (nnheader-decode-subject): Change the 2nd arg of
+       `mime-find-field-decoder' to 'nov'.
+       (nnheader-decode-from): Ditto.
+
+       * lisp/message.el (message-maybe-split-and-send-mail): Discard
+       a return from `message-send-mail-function'.
+
+1998-11-12  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: bug fix.
+
+       * lisp/gnus-ofsetup.el: Bug fix.
+
+1998-11-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/Makefile.in (.texi:): Don't escape double quote.
+       (texi2latex.elc:): Ditto.
+
+1998-11-12  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * texi/gnus-ja.texi: Add infos about `pop3-fma' and `gnus-offline'.
+
+1998-11-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-maybe-split-and-send-mail): Use
+       `defsubst' instead of `defun'.
+       (message-maybe-split-and-send-news): Ditto.
+
+1998-11-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-resend-bounced-mail): Bind
+       `gnus-message-setup-hook' to minimum setting.
+
+       * lisp/message.el (message-bounce-setup-for-mime-edit): New
+       function.
+       (message-bounce-setup-function): New user option. Use
+       `message-bounce-setup-for-mime-edit' in default.
+       (message-bounce): Call `message-bounce-setup-function' if it is
+       non-nil.
+       (message-bounce-setup-hook): New user option.
+       (message-send-mail): Delete useless things.
+
+1998-11-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-maybe-split-and-send-mail): New function.
+       (message-send-mail): Use it.
+       (message-maybe-split-and-send-news): New function.
+       (message-send-news): Use it.
+
+1998-11-11  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: bug fix.
+
+       * lisp/gnus-ofsetup.el: Bug fix.
+
+1998-11-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send-mail): Protect against errors.
+       (message-send-news): Ditto.
+
+1998-11-11  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/message.el (message-do-fcc): Sync up with Semi-gnus 6.8.
+       (message-8bit-encoding-list): New variable.
+       (message-check-encoding): Use `message-8bit-encoding-list'. Change
+       search pattern.
+
+1998-11-11  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/extract-address-components): Normalize
+       return value.
+       (gnus-bbdb/update-record): Change condition for checking own message.
+
+1998-11-11  Yoshiki Hayashi  <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * README.semi.ja, README.branch.ja: New file.
+
+1998-11-10  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: bug fix.
+
+       * lisp/gnus-ofsetup.el: Bug fix.
+
+1998-11-09  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el: v2.00b1 Separate setting part and
+       functional part - setting part move to gnus-ofsetup.el (New file).
+
+       * lisp/gnus-ofsetup.el: New file - setting function for
+       gnus-offline.
+
+1998-11-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-decode-subject): Call
+       `mime-find-field-decoder' with `summary' as the 2nd arg.
+       (nnheader-decode-from): Ditto.
+
+1998-11-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3-fma.el: Set the value of `nnmail-read-passwd' as a
+       symbol `pop3-fma-read-passwd'.
+
+1998-11-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.029.
+
+       * Sync up with Pterodactyl Gnus 0.42.
+
+1998-11-09  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.028.
+
+       * Sync up with Pterodactyl Gnus 0.41.
+
+1998-11-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-make-full-mail-header): New
+       function.
+       (gnus-article-mime-edit-article-setup): Use it.
+       (gnus-article-mime-edit-exit): Use it.
+
+       (gnus-article-mime-edit-article-setup): Set `gnus-show-mime' to t.
+
+       * lisp/gnus-bbdb.el: Modify header description.
+
+1998-11-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-edit-done): Remove
+       `gnus-article-mime-edit-article-unwind' from
+       `gnus-article-mode-hook' before run `gnus-article-edit-exit'.
+       (gnus-article-mime-edit-article-setup): Revised.
+       (gnus-article-mime-edit-article-unwind): New function.
+       (gnus-article-mime-edit-exit): New function.
+
+       (gnus-insert-mime-button): Fix typo.
+
+1998-11-04  Yoshiki Hayashi  <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * lisp/message.el: (message-do-fcc): Don't run message-header-hook
+       and message-before-do-fcc-hook.
+
+1998-11-04  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/mmgnus.el (entity-buffer): Must move to (point-min) before
+       search boundary between header and body (to fix problem with
+       Emacs).
+
+1998-11-03  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnmh.el (nnmh-retrieve-headers): Don't use
+       `nnheader-fold-continuation-lines'.
+
+       * lisp/gnus-sum.el (gnus-get-newsgroup-headers): Don't expect
+       unfolded (to fix problem when using gnus-cache).
+
+1998-11-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-in-reply-to): Quote date.
+
+1998-11-02  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/canonicalize-full-name-methods):
+       New variable. (Merged from `mime-bbdb.el' in SEMI.)
+       (gnus-bbdb/extract-address-components): New function. (Merged from
+       `mime-bbdb.el' in SEMI.)
+       (gnus-bbdb/canonicalize-spaces): Ditto.
+       (gnus-bbdb/canonicalize-dots): Ditto.
+       (gnus-bbdb/update-record): Use
+       `gnus-bbdb/extract-address-components'.
+       (gnus-bbdb/lines-and-from): Ditto.
+       (gnus-bbdb/summary-get-author): Ditto.
+       (gnus-bbdb/summary-author-in-bbdb): Ditto.
+       (gnus-bbeb/decode-field-body-function): New variable.
+       (gnus-bbdb/decode-field-body): New macro.
+       (gnus-bbdb/update-record): Use `gnus-bbdb/decode-field-body'.
+       (gnus-bbdb/extract-field-value): Ditto.
+       (gnus-bbdb/decode-field-body-function): Fix typo.
+       (gnus-bbdb/decode-field-body): Ditto.
+       (gnus-bbdb/update-record): Use `save-excursion' and change timing
+       of `save-restriction'.
+
+1998-10-31  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-draft.el (gnus-draft-decoding-function): Use
+       `mime-edit-decode-message-in-buffer' instead of
+       `mime-edit-decode-buffer'.
+
+1998-10-31  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/nnheader.el (nnheader-decode-field-body): New inline
+       function.
+
+       * lisp/gnus-draft.el (gnus-draft-decoding-function): Use
+       `mime-edit-decode-buffer' and `mime-decode-header-in-buffer'.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Use
+       `nnheader-decode-field-body' instead of `mime-decode-field-body'.
+       (gnus-bbdb/extract-field-value): Ditto.
+
+1998-10-30  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Check existance of
+       `To' field before decoding.
+
+1998-10-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * README-gnus-bbdb.en: New file, translated by courtesy of
+       Hiroshi Kawaguchi <taicho@shiba.sony.co.jp>.
+
+1998-10-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-compile): Add `gnus-bbdb.el'.
+
+       * lisp/gnus-bbdb.el: New file. By courtesy of Keiichi Suzuki.
+       * README-gnus-bbdb.ja: Ditto (A part of Nana-TIPS.ja).
+
+1998-10-30  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el: Add autoload setting for `gnus-offline' and
+       `pop3-fma'.
+
+1998-10-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-decode-encoded-words): Use
+       `mime-decode-header-in-buffer' instead of `eword-decode-header'.
+       (gnus-article-display-message-with-encoded-word): Likewise.
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-article-setup): Fix
+       typo.
+
+1998-10-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-decoding-function): Use
+       `mime-edit-decode-buffer' simply as initial value.
+
+       * lisp/message.el (message-make-forward-subject): Use
+       `nnheader-decode-subject' instead of
+       `eword-decode-unstructured-field-body'.
+
+       * lisp/nnheader.el (nnheader-decode-subject): New alias.
+       (nnheader-decode-from): New alias.
+       (make-full-mail-header): Use `nnheader-decode-subject' and
+       `nnheader-decode-from' instead of
+       `eword-decode-and-unfold-unstructured-field' and
+       `eword-decode-and-unfold-structured-field'.
+
+1998-10-29  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-article-setup): Force
+       `font-lock' to turn on at the beginning. Turn off `font-lock'
+       after editing article.
+
+1998-10-29  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-edit-article-done): Abolish
+       `gnus-article-decoded-p'.
+
+       * lisp/nnheader.el: Delete useless comments.
+
+       * lisp/gnus-art.el (gnus-article-edit-article): Call
+       `gnus-article-edit-article-setup-function' if it is non nil.
+       (gnus-article-mime-edit-article-setup): New function.
+       (gnus-article-mime-edit-article-setup-hook): New hook.
+       (gnus-article-edit-article-setup-function): New user option. Use
+       `gnus-article-mime-edit-article-setup' in default.
+
+1998-10-28  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el: Determin base64 encode/decode function by FLIM.
+
+1998-10-26  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el: Require `mel-b-el' if `mel-b' does not exist.
+
+1998-10-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3-fma.el: Require `mel-b-ccl' or `mel-b-el' if `mel-b'
+       does not exist.
+
+       * lisp/nnheader.el (nnheader-file-coding-system): Restore the
+       previous default value.
+
+1998-10-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.027.
+
+       * Sync up with Pterodactyl Gnus 0.40.
+
+1998-10-23  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.026.
+       (gnus-version): Modify supported version for FLIM and SEMI.
+
+1998-10-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-cache.el (gnus-cache-possibly-enter-article): Use
+       `mime-fetch-field' for getting Subject and From field.
+
+1998-10-20  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el (nnheader-insert-nov): Use `mime-fetch-field'
+       for Subject and From field.
+
+1998-10-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-parse-nov): Use
+       `make-full-mail-header'.
+
+1998-10-20  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el (nnheader-parse-head): Use
+       `make-full-mail-header'.
+
+1998-10-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (make-full-mail-header): Sync up with
+       "chao-6_9" branch.
+       (mail-header-set-xref): Use `mime-entity-set-xref-internal'.
+       (mail-header-xref): Use `mime-entity-xref-internal'
+       (mail-header-set-lines): mime-entity-set-lines-internal'.
+       (mail-header-lines): Use `mime-entity-lines-internal'
+       (mail-header-set-chars): Use `mime-entity-set-chars-internal'.
+       (mail-header-chars): Use `mime-entity-chars-internal'.
+       (mail-header-set-references): Use
+       `mime-entity-set-references-internal'.
+       (mail-header-references): Use `mime-entity-references-internal'.
+       (mail-header-set-message-id): Use
+       `mime-entity-set-message-id-internal'.
+       (mail-header-message-id): Use `mime-entity-message-id-internal'.
+       (mail-header-set-date): Use `mime-entity-set-date-internal'.
+       (mail-header-date): Use `mime-entity-date-internal'.
+       (mail-header-set-from): Use
+       `mime-entity-set-decoded-from-internal'.
+       (mail-header-from): Use `mime-entity-decoded-from-internal'.
+       (mail-header-set-subject): Use
+       `mime-entity-set-decoded-subject-internal'.
+       (mail-header-subject): Use `mime-entity-decoded-subject-internal'.
+       All changes are imported from "chao-6_9" branch.
+
+       * lisp/message.el (message-reply): Use
+       `make-full-mail-header-from-decoded-header`.
+       (message-followup): Ditto.
+       (message-get-reply-buffer-function): Abolished.
+       (message-fill-address): Don't fold if the current column number is
+       less than 79.
+
+       * lisp/gnus-sum.el (gnus-summary-insert-line): Use
+       `gnus-put-text-property-excluding-characters-with-faces' instead
+       of `gnus-put-text-property'.
+       (gnus-summary-mode-map): Abolish key definition
+       "b" for `gnus-article-view-part'.
+       (gnus-encoded-word-method-alist): Abolished.
+       (gnus-multi-decode-encoded-word-string) Abolished.
+
+       * lisp/gnus-int.el (gnus-request-replace-article): Don't encode
+       message body.
+
+       * lisp/gnus-i18n.el (gnus-get-summary-default-charset): Abolished.
+       (gnus-set-summary-default-charset): Sync up with "chao-6_9" branch.
+
+       * lisp/gnus-art.el (gnus-article-display-method-for-encoded-word):
+       Abolished.
+       (gnus-article-display-message-with-encoded-word): Abolished.
+
+1998-10-14  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-line-format-alist): Use
+       `mime-read-field', `std11-address-string' and
+       `std11-full-name-string' instead of
+       `gnus-extract-address-components'.
+       (gnus-article-sort-by-author): Likewise.
+
+1998-10-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el (make-full-mail-header-from-decoded-header):
+       New function.
+
+1998-10-05  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-display-mime-message): Set up
+       buffer local variable `default-mime-charset' of
+       `gnus-original-article-buffer' and `gnus-article-buffer'.
+
+1998-09-30  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el: Use `mime-entity' as gnus-header structure.
+       (mail-header-number): Use `mime-entity-location-internal'.
+       (mail-header-set-number): Use `mime-entity-set-location-internal'.
+       - Change other `mail-header-*' and `mail-header-set-*' to alias of
+       reference and set functions for mime-entity-internal.
+
+       * lisp/mmgnus.el: New module.
+
+       * lisp/gnus-sum.el: Abolish variable
+       `gnus-structured-field-decoder' and
+       `gnus-unstructured-field-decoder'.
+       (gnus-nov-parse-line): Don't decode from and subject.
+       (gnus-get-newsgroup-headers): Likewise.
+
+       * lisp/gnus-score.el (gnus-header-index): Modify to use
+       mime-entity structure as gnus-header structure.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Use content of
+       `gnus-current-headers' as mime-message-structure.
+
+1998-09-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-update-summary-mark-positions): Use
+       `make-full-mail-header'.
+
+1997-11-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       (gnus-parse-headers-hook): Use
+       `(gnus-set-summary-default-charset)' in default.
+
+\f
+1998-10-21  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-xmas.el (gnus-tilde-pad-form): Guard for non string
+       symbol.
+
+1998-10-21  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.025.
+       (gnus-version): Fix supported version for FLIM and SEMI.
+
+       * Sync up with Pterodactyl Gnus 0.36.
+
+1998-10-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.024.
+       Fix supported version for FLIM and SEMI.
+
+       * Sync up with Pterodactyl Gnus 0.35.
+
+1998-10-17  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-setup-needed-hooks): Change
+       message-send-hook to mime-edit-translate-hook.
+
+       * lisp/pop3-fma.el (pop3-fma-init-message-hook): Change
+       message-send-hook to mime-edit-translate-hook.
+
+       * lisp/message.el (message-save-drafts): New function to save
+       drafts in network code.
+
+1998-10-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-message-setup-hook): Replace the default
+       value to `gnus-maybe-setup-default-charset'.
+       (gnus-maybe-setup-default-charset): New function. It is called
+       `message-maybe-setup-default-charset' at one time.
+
+       * lisp/message.el (message-maybe-setup-default-charset): Abolished.
+
+1998-10-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * TODO.ja: Update.
+
+1998-10-15  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-spec.el (gnus-update-format-specifications): Force
+       update `gnus-format-specs' when `gnus-version' is differ from
+       saved version.
+
+1998-10-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/pop3-fma.el (pop3-fma-read-char-exclusive): New macro. Use
+       `next-command-event' instead of `read-char-exclusive' under XEmacs.
+       (pop3-fma-read-noecho): Use it.
+
+1998-10-13  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nnheaderxm.el (nnheader-xmas-Y-or-n-p): New function.
+       It will be used for the substitute of `nnheader-Y-or-n-p' under
+       XEmacs.
+
+       * lisp/nnheader.el (nnheader-Y-or-n-p): Rewrite for Emacs 19 or
+       later except for XEmacs.
+
+1998-10-12  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/uudecode.el: New file.
+
+1998-10-11  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.023.
+       Add version information for SEMI-1.9/FLIM-1.10.
+
+       * Sync up with Pterodactyl Gnus 0.34.
+
+1998-10-10  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-message-make-user-agent): Fix typo in doc
+       string.
+
+1998-10-07  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * lisp/nnagent.el (nnagent-open-server): Small bug fix.
+
+1998-10-07  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * TODO.ja: New file.
+
+1998-10-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-mime-insert-article): Don't refer to
+       `mark' position.
+
+       * lisp/message.el (message-mime-insert-article): If the optional
+       arg FULL-HEADERS is non-nil, include full headers when inserting.
+
+1998-10-06  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/message.el (message-parameter-alist): New variable.
+       (message-startup-parameter-alist):  New variable.
+       (message-fetch-reply-field): Get reply buffer with
+       `message-get-reply-buffer()'.
+       (message-yank-original): Ditto.
+       (message-eval-parameter): New function.
+       (message-get-reply-buffer): Ditto.
+       (message-get-original-reply-buffer): Ditto.
+       (message-mode): New buffer local variable
+       `message-parameter-alist'.
+       (message-setup): Set up `message-reply-buffer' from
+       `message-parameter-alist'.
+       (message-mime-insert-article): Get `Original message buffer' with
+       `message-get-original-reply-buffer' instead of
+       `gnus-original-article-buffer'.
+       Remove bogus header fields for forwarding message.
+
+       * lisp/gnus-msg.el (gnus-setup-message): Setup
+       `message-startup-parameter-alist'.
+
+1998-10-05  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * lisp/gnus.el (gnus-info-filename): New variable.
+       (gnus-info-find-node): Use `gnus-info-filename' and
+       `current-language-environment'.
+
+1998-10-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send-mail): Remove misplaced
+       `interactive'.
+
+       * lisp/message.el (message-yank-original): Get back to the previous
+       state.
+       (message-fetch-reply-field): Ditto.
+       (message-setup): Ditto.
+       * lisp/gnus-msg.el (gnus-setup-message): Ditto.
+
+1998-10-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-draft.el: Remove some useless comments.
+
+       * lisp/gnus-draft.el (gnus-draft-send-draft): Abolished.
+
+1998-10-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-yank-original):  Use the value of
+       `message-reply-buffer' as a function if it is a function.
+       (message-fetch-reply-field): Ditto.
+
+       * lisp/message.el (message-setup): Set the value of
+       `message-reply-buffer' if the variable
+       `gnus-message-get-reply-buffer' exists.
+
+       * lisp/gnus-msg.el (gnus-setup-message): Bind
+       `gnus-message-get-reply-buffer' as the function
+       `gnus-copy-article-buffer'.
+
+1998-10-03  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-send): Call
+       `message-send-news-function' or `message-send-mail-function'
+       instead of `message-send-and-exit'.
+
+1998-10-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-mode-map): Use `define-key' instead of
+       `substitute-key-definition' for `message-kill-buffer'.
+
+1998-10-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Replace with the
+       new code again. It is based on MORIOKA-san's code.
+
+1998-10-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Replace with the
+       new code.
+
+       * lisp/gnus-msg.el (gnus-message-make-user-agent): New function.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Needn't be interactive.
+
+       * lisp/gnus-msg.el (gnus-inviolable-extended-version): Abolished.
+
+1998-10-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-kill-buffer): Change the prompt string.
+
+       * lisp/message.el (message-mode-map): Substitute key definition
+       from `kill-buffer' to `message-kill-buffer'.
+
+1998-10-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-message-setup-hook): Set the default value
+       to `message-maybe-setup-default-charset'.
+
+       * lisp/message.el (message-setup-hook): Move
+       'message-maybe-setup-default-charset' to `gnus-message-setup-hook'.
+
+1998-10-02  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-kill-buffer): Refer to
+       `message-kill-buffer-query-function'.
+
+       * lisp/message.el (message-kill-buffer-query-function): New user
+       option.
+
+       * lisp/nnheader.el (nnheader-Y-or-n-p): New function.
+
+1998-10-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el (pop3-fma-movemail): Bug fix.
+       Delete variable pop3-fma-movemail options.
+       Add new variabel pop3-fma-commandline-arguments.
+
+1998-10-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el: Fix my stupid changes.
+
+1998-09-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Add the value of
+       `system-configuration' to Emacs and XEmacs as a comment.
+
+       * lisp/message.el (message-make-user-agent): Fold up the return
+       value if the optional arg MAX-COLUMN is specified.
+
+1998-09-29  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Make a user-agent
+       string without MUA info, if the value of `message-user-agent' is
+       nil nor `gnus-inviolable-extended-version' is not exists.
+
+1998-09-28  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/nnmh.el (nnmh-request-accept-article): Insert `Message-ID'
+       only if `group' name is neither "queue" nor "draft".
+       Fix typo (at 23:25).
+
+       * lisp/message.el (message-send-mail): Add different Message-ID in
+       each message/partial
+
+1998-09-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/gnus-ja.texi: Sync up with Semi-gnus 6.8.19.
+
+       * lisp/gnus.el: Add autoload setting for
+       `gnus-quote-arg-for-sh-or-csh'.
+
+1998-09-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-insert-pseudos): Use
+       `gnus-quote-arg-for-sh-or-csh' instead of `mm-quote-arg'.
+
+       * lisp/nndoc.el (nndoc-possibly-change-buffer): Don't eval
+       `mm-enable-multibyte'.
+       * lisp/nnmbox.el (nnmbox-possibly-change-newsgroup): Ditto.
+
+1998-09-25  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.022.
+
+       * Sync up with Pterodactyl Gnus 0.32.
+
+1998-09-24  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.021.
+
+       * Sync up with Pterodactyl Gnus 0.31.
+
+1998-09-23  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Add extended version
+       number to Emacs/{VERSION} (e.g. "Emacs/20.3.90").
+
+1998-09-22  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-agent.el (gnus-agent-expire): Bug fix when variable
+       expired is nil.
+
+1998-09-18  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-draft.el: (gnus-draft-edit-message): Fix typo.
+
+1998-09-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): Use
+       `gnus-inviolable-extended-version' if `message-user-agent' is nil.
+
+       * lisp/message.el (message-make-user-agent): In message-mode, make
+       the most of the `User-Agent' field value if already exists.
+
+       * lisp/gnus-msg.el (gnus-inviolable-extended-version): New constant.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Remove trailing white
+       space.
+
+1998-09-17  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-send-draft): Expire queued message
+       after news posting.
+
+1998-09-17  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-send-draft): Error if no
+       recipients.
+
+1998-09-17  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-decoding-function): Uncommented.
+
+1998-09-17  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-edit-message): Use
+       `gnus-draft-setup-for-editing' instead of `gnus-draft-setup'.
+       (gnus-draft-send): Use `gnus-draft-setup-for-sending' instead of
+       `gnus-draft-setup'.
+       (gnus-draft-setup-for-editing): New function (renamed from
+       `gnus-draft-setup').
+       (gnus-draft-setup-for-sending): New function.
+       (gnus-draft-send-draft-buffer): New variable.
+
+1998-09-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/gnus-ja.texi: Sync up with Semi-gnus 6.8.18.
+
+       * Makefile.in: Add entry `info-ja'.
+       * texi/Makefile.in: Add entry `ja'.
+
+1998-09-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.020.
+
+       * lisp/ietf-drums.el: New file.
+       * lisp/date.el: Abolished.
+       * lisp/mm.el: Abolished.
+
+       * Sync up with Pterodactyl Gnus 0.31.
+
+1998-09-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-encode-message-body): Copied from
+       Pterodactyl Gnus 0.30. It is useless for Semi-gnus but usefull for
+       reducing differences while at work for synchronizing up. It will
+       be removed when the Gnus becomes stable.
+       * lisp/gnus-art.el (gnus-mime-display-alternative)
+       (gnus-display-mime) (gnus-widget-press-button)
+       (gnus-insert-mime-button) (gnus-mime-copy-part)
+       (gnus-mime-view-part) (gnus-mime-pipe-part) (gnus-mime-save-part)
+       (gnus-mime-button-map) (gnus-mime-button-line-format-alist)
+       (gnus-mime-button-line-format)
+       (article-mime-decode-quoted-printable-buffer)
+       (article-de-quoted-unreadable) (article-decode-charset)
+       (article-decode-mime-words) (gnus-decode-header-function)
+       (gnus-display-mime-function): Ditto.
+
+1998-09-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-decode-encoded-words): Renamed from
+       `gnus-article-decode-rfc1522'.
+
+       * lisp/mail-parse.el: New file.
+       * lisp/mm-view.el: New file.
+       * lisp/rfc2231.el: New file.
+       * texi/emacs-mime.texi: New file.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.019.
+
+       * Sync up with Pterodactyl Gnus 0.30.
+
+1998-09-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.018.
+
+       * Sync up with Pterodactyl Gnus 0.26.
+
+1998-09-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.017.
+
+       * lisp/gnus-art.el (gnus-show-mime) (gnus-summary-toggle-mime):
+       Revived.
+
+       * lisp/gnus-mailcap.el: New file. Renamed from `mailcap.el'.
+
+       * Sync up with Pterodactyl Gnus 0.25.
+
+1998-09-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-make-date-line): Add TZ value to
+       `local' and `ut' date.
+
+       * lisp/gnus-art.el (article-make-date-line): Fix `ut' date.
+
+       * lisp/parse-time.el (parse-time-string): The last element of the
+       return list should be TZ.
+
+       * lisp/message.el (message-send): Eval 'message-fix-before-sending'
+       after encoding.
+
+1998-09-10  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-spec.el (gnus-tilde-pad-form): Use old macro form.
+
+       * lisp/gnus-art.el (article-decode-mime-words): Abolished.
+
+1998-09-10  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.016.
+
+       * Sync up with Pterodactyl Gnus 0.24.
+
+1998-09-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.015.
+
+       * Sync up with Pterodactyl Gnus 0.23.
+
+1998-09-09  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.014.
+
+       * Sync up with Pterodactyl Gnus 0.22.
+
+1998-09-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.013.
+
+       * Sync up with Pterodactyl Gnus 0.19.
+
+1998-09-08  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-send-draft) (gnus-draft-send): New
+       implementations for testing.
+
+       * lisp/gnus-agent.el (gnus-agent-expire) (gnus-agent-fetch-headers)
+       (gnus-agent-flush-cache) (gnus-agent-save-history)
+       (gnus-agent-save-groups): Bind `coding-system-for-write' by
+       `gnus-agent-file-coding-system' while writing a file.
+
+       * lisp/gnus-agent.el (gnus-agent-file-coding-system): Renamed from
+       `gnus-agent-article-file-coding-system'.
+
+1998-09-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.012.
+
+       * Sync up with Pterodactyl Gnus 0.18.
+
+1998-09-07  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-setup): Do not use message mode.
+       (gnus-draft-send): Ditto.
+       gnus-draft-send-draft-buffer: New variable.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Display original Gnus
+       version.
+
+       * lisp/gnus-agent.el : Use pGnus 0.17 gnus-agent.el
+
+1998-09-07  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-continuum-version): Use `char-int' instead of
+       `mm-char-int'.
+       * lisp/messagexmas.el (message-xmas-make-caesar-translation-table):
+       Ditto.
+
+       * lisp/gnus-art.el (gnus-article-setup-buffer): Don't use
+       `mm-enable-multibyte'.
+
+1998-09-07  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.011.
+
+       * Sync up with Pterodactyl Gnus 0.17.
+
+1998-09-06  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.10.010.
+
+       * Sync up with Pterodactyl Gnus 0.16.
+
+1998-09-04  Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el (pop3-fma-movemail): Add error handle.
+       (pop3-fma-get-movemail-type): Fix typo.
+
+1998-09-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.09.
+
+       * Sync up with Pterodactyl Gnus 0.14.
+
+1998-09-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/nndoc.el (nndoc-transform-mime-parts): Insert
+       "MIME-Version:" instead of "Mime-Version:".
+
+       * lisp/message.el (message-encode-message-body): Abolished.
+
+       * lisp/message.el: Don't require `rfc2047'.
+
+       * lisp/gnus.el: Delete autoload settings for `qp' and `rfc2047'.
+
+       * lisp/gnus.el (semi-gnus-developers): New constant.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.08.
+
+       * lisp/gnus-xmas.el (gnus-tilde-pad-form): Move to
+       `gnus-xmas-redefine' from `gnus-xmas-define'.
+
+       * lisp/gnus-sum.el (gnus-set-mode-line): Use `gnus-truncate-string'
+       instead of `truncate-string'.
+
+       * lisp/gnus-sum.el: Don't define menu for "MIME".
+
+       * lisp/gnus-sum.el: Delete key definitions for
+       `gnus-article-decode-mime-words' and `gnus-article-decode-charset'.
+
+       * lisp/gnus-spec.el (gnus-tilde-pad-form): New function for the
+       benefit of avoiding byte-compile warning.
+
+       * lisp/gnus-soup.el (gnus-soup-send-packet): Set
+       `message-user-agent' instead of `message-newsreader'.
+
+       * lisp/message.el (message-set-work-buffer) (message-mode):  Don't
+       use `mm-enable-multibyte'.
+       * lisp/gnus-util.el (gnus-set-work-buffer): Ditto.
+       * lisp/gnus-sum.el (gnus-summary-mode): Ditto.
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Ditto.
+       * lisp/gnus-art.el (gnus-article-mode): Ditto.
+
+       * lisp/gnus-art.el (gnus-article-decode-mime-words)
+       (gnus-article-decode-charset) (gnus-decode-rfc1522)
+       (article-decode-rfc1522) (article-de-quoted-unreadable)
+       (article-mime-decode-quoted-printable-buffer): Abolished.
+
+       * lisp/message.el: Don't require `mm-bodies'.
+       * lisp/gnus-art.el: Ditto.
+
+       * lisp/gnus-agent.el (gnus-category-line-format-alist): Change
+       variable name `name' and `groups' to `gnus-tmp-name' and
+       `gnus-tmp-groups'.
+       (gnus-category-insert-line): Ditto.
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-articles): Delete useless
+       binding variables.
+
+1998-09-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.07.
+
+       * Sync up with Pterodactyl Gnus 0.13.
+
+1998-08-31  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.04.
+
+       * Sync up with Pterodactyl Gnus 0.10.
+
+       * lisp/gnus-agent.el : back to version Gnus 5.6.32.
+
+1998-08-31  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/rfc1522.el: Abolished.
+
+       * lisp/message.el: (message-send-mail) (message-send-news): Don't
+       use `mm-encode-message-header'.
+
+       * lisp/gnus.el: Delete autoload settings for
+       `hexl-hex-string-to-integer', `mm-decode-words-region',
+       `mm-decode-words-string', `gnus-hack-decode-rfc1522',
+       `gnus-article-de-quoted-unreadable', `gnus-decode-rfc1522' and
+       `article-decode-rfc1522'.
+
+       * lisp/gnus-sum.el: Delete key definitions for
+       `gnus-article-decode-mime-words', `gnus-article-decode-mime-words'
+       and `gnus-article-de-quoted-unreadable'.
+
+       * lisp/gnus-art.el (gnus-article-decode-mime-words)
+       (gnus-decode-rfc1522) (article-de-quoted-unreadable)
+       (article-mime-decode-quoted-printable-buffer): Abolished.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.03.
+
+       * Sync up with Pterodactyl Gnus 0.9.
+
+1998-08-31  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-agent.el: Do not use nnheader-temp-write.
+
+       * lisp/gnus-ems.el: Do not use nnheader-temp-write.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.02.
+
+       * Sync up with Pterodactyl Gnus 0.8.
+
+1998-08-30  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * New branch ... pgnus-ichikawa
+
+       * lisp/gnus.el (gnus-original-version-number)
+       (gnus-original-product-name) : New variable.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.9.01.
+       Third version number 0x means Original gnus's status in beta version.
+
+       * Sync up with Pterodactyl Gnus 0.6.
+
+1998-08-30  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-headers): Bug Fix.
+       When add a new newsgroup , gnus-agent cannot fetch articles.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.17.
+
+       * Sync up with Gnus 5.6.42.
+
+1998-08-28  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-i18n.el (gnus-set-summary-default-charset): Try
+       "qualified" newsgroup name first.
+
+1998-08-28  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-i18n.el (gnus-set-summary-default-charset): Match
+       "real" newsgroup name; strip "backend+server" prefix.
+
+1998-08-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/message.el (message-make-user-agent): New function.
+       (message-generate-headers): Use it.
+       These changes are copied from Shoe-gnus.
+
+1998-08-28  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/message.el (message-make-in-reply-to):
+       Use `std11-extract-address-components'.
+       (message-use-mail-reply-to): Doc fix.
+
+1998-08-27  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.16.
+
+       * Sync up with Gnus 5.6.41.
+
+1998-08-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-spec.el (gnus-parse-simple-format): Use
+       `gnus-tilde-pad-form' instead of the padding faculty of `format'
+       under XEmacs-mule.
+
+       * lisp/gnus-xmas.el
+       (gnus-xmas-redefine): Redifine `gnus-truncate-string',
+       `gnus-tilde-max-form' and `gnus-tilde-cut-form' for XEmacs-mule.
+       (gnus-xmas-define): New function 'gnus-tilde-pad-form' for
+       XEmacs-mule.
+
+1998-08-26  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-narrow-to-signature):
+       Removed TM stuff.
+       (gnus-article-display-mime-message):
+       Set `mime-button-mother-dispatcher' in correct buffer.
+       (gnus-url-mailto): Use `gnus-setup-message'.
+       (gnus-button-mailto): Ditto.
+       (gnus-button-reply): Ditto.
+
+       * lisp/gnus-ems.el (gnus-mule-max-width-function): Removed.
+       (gnus-truncate-string): Use `truncate-string-to-width' if available.
+       (gnus-tilde-max-form): New implementation.
+       (gnus-tilde-cut-form): Ditto.
+
+       * lisp/gnus-msg.el (gnus-summary-mail-digest): New function.
+       (gnus-summary-post-digest): New function.
+
+       * lisp/gnus-sum.el (gnus-summary-make-menu-bar): Use
+       `gnus-summary-mail-digest' and `gnus-summary-post-digest' instead
+       of `gnus-uu-digest-mail-forward' and `gnus-uu-digest-post-forward'.
+
+       * lisp/gnus-util.el (gnus-truncate-string): Ignore more than two
+       arguments.
+
+       * lisp/message.el (message-forward-end-separator): Use
+       `text/plain' tag.
+
+1998-08-25  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-cache.el (gnus-cache-possibly-enter-article): Write
+       file in raw-text coding system.
+       (gnus-cache-save-buffers): Ditto.
+       * lisp/gnus-cache.el (gnus-cache-write-file-coding-system): New variable.
+       * lisp/gnus-util.el (gnus-write-buffer): Undo change.
+
+       * lisp/gnus-util.el (gnus-write-file-coding-system): Delete variable.
+
+1998-08-25  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-msg.el (gnus-bug-message): About Semi-gnus.
+       (gnus-extended-version): Return gnus version only.
+       (gnus-bug): Add Semi-gnus developers to recipients.
+
+       * lisp/message.el (message-make-user-agent): New function.
+       (message-generate-headers): Use it.
+
+1998-08-24  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-setup): Bug fix and version
+       changed to 1.53.
+
+       * lisp/gnus-util.el (gnus-write-buffer): Write file in raw-text coding
+       system.
+
+       * lisp/gnus-util.el (gnus-write-file-coding-system): New variable.
+
+1998-08-23  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/message.el: Suppress some byte-compile warnings.
+       (message-make-forward-subject): Failed to sync.
+       (message-setup): Ditto.
+       (message-clone-locals): Modify regexp.
+
+       * lisp/message.el (message-fill-references): Reverted.
+
+1998-08-23  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-agent.el (gnus-agent-braid-nov): Use
+       `nnheader-insert-file-contents'.
+
+       * lisp/gnus-i18n.el (gnus-set-summary-default-charset): Sync up
+       with "akr" branch.
+
+1998-08-23  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.15.
+
+       * Sync up with Gnus 5.6.39.
+
+1998-08-20  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.14.
+
+       * Sync up with Gnus 5.6.38.
+
+       * lisp/gnus-offline.el (gnus-offline-enable-fetch-mail): Enable to get
+       APOP server.
+
+       * lisp/pop3-fma.el (pop3-fma-movemail): Enable to get from APOP server.
+       (pop3-fma-set-pop3-password) Enable to get from APOP server.
+
+1998-08-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.13.
+
+       * Sync up with Gnus 5.6.37.
+
+       * lisp/gnus-offline.el (gnus-offline-setup) : To create spol directory
+       if not exists.
+       Change default value of gnus-offline-drafts-queue-type 'miee to 'agent
+
+1998-08-16  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.12.
+
+       * Sync up with Gnus 5.6.36.
+
+       * lisp/gnus-offline.el : New file.
+       Merge gnus-offline to ichikawa branch.
+
+1998-08-15  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Update.
+
+1998-08-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-save-newsrc-file): Bind
+       `coding-system-for-write' by `gnus-startup-file-coding-system'
+       while saving the quick newsrc file.
+
+       * lisp/gnus-start.el (gnus-startup-file-coding-system): Change
+       default value to `ctext'.
+
+1998-08-13  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.11.
+
+       * Sync up with Gnus 5.6.34.
+
+1998-08-12  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.10.
+
+       * Sync up with Gnus 5.6.33.
+
+1998-08-11  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/message.el (message-frames): New custom group.
+       (message-original-frame): New variable.
+       (message-use-multi-frames): New variable.
+       (message-delete-frame-on-exit): New variable.
+       (message-send-and-exit): Delete frame which made for editing
+       message.
+       (message-kill-buffer): Ditto.
+       (message-delete-frame): New function.
+       (message-pop-to-buffer): Make new frame when edit message.
+
+1998-08-11  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.9.
+
+       * Sync up with Gnus 5.6.31.
+
+1998-08-10  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.8.
+
+       * Sync up with Gnus 5.6.30.
+
+1998-08-10  Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.7.
+
+1998-08-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/smtp.el: Do not insert empty line at the end of message.
+
+1998-08-06  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.6.
+
+       * Sync up with Gnus 5.6.29.
+
+1998-08-05  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-start.el (gnus-read-init-file): Fix indent.
+       * lisp/gnus-ems.el (gnus-tilde-max-form): Redefine instead of
+       (gnus-summary-line-format-spec) to display Japanese character
+       correctly in Gnus summaly.
+
+1998-08-05  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-start.el (gnus-read-init-file): Don't restrict
+       `coding-system-for-read' by `binary' when loading `.gnus'.
+
+1998-08-04  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.5.
+
+       * Sync up with Gnus 5.6.28.
+
+1998-07-27  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.4.
+
+       * Sync up with Gnus 5.6.27.
+
+1998-07-27  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/message-ja.texi: Japanese translation of "message.texi".
+
+1998-07-26  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.3.
+
+       * Sync up with Gnus 5.6.26.
+
+1998-07-23  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.2.
+       (gnus-version): Change to "Semi-gnus". Change comment format.
+
+1998-07-21  Keisuke Mori   <ksk@ntts.com>
+
+       * texi/gnus-ja.texi: Add "Appendices".
+
+1998-07-21  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Appendices".
+
+1998-07-16  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.1.
+
+       * Sync up with Gnus 5.6.24.
+
+1998-07-10  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-ems.el (gnus-mule-cite-add-face): Fix problem when multi
+       bytes charactors are used in cite prefix. (for Emacs 20.1 and 20.2)
+       (gnus-ems-redefine): for Emacs 20.1 and 20.2
+
+       * lisp/gnus-cite.el (gnus-cite-add-face): Abolish my last bogus change.
+
+1998-07-09  Keiichi Suzuki  <kei-suzu@mail.wbs.ne.jp>
+
+       * lisp/gnus-cite.el (gnus-cite-add-face): Fix problem when multi
+       bytes charactors are used in cite prefix.
+
+1998-07-07  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "The End".
+
+1998-07-06  Keisuke Mori   <ksk@ntts.com>
+
+       * texi/gnus-ja.texi: Add "Various".
+
+1998-07-06  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Various".
+       * texi/gnus-ja.texi: Sync up with Gnus 5.6.22
+
+1998-07-02  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el (message-header-format-alist): Repair to use
+       `message-fill-references' for References.
+
+1998-07-01  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-header-presentation-method):
+       Delete nil optional arguments.
+       - Delete setting for `mime-raw-representation-type-alist'.
+
+1998-07-01  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.8.0.
+       (gnus-version): Modify for FLIM 1.8.
+
+       * lisp/gnus-art.el (gnus-article-header-presentation-method):
+       Modify for FLIM 1.8.
+
+1998-06-30  Keisuke Mori   <ksk@ntts.com>
+
+       * texi/gnus-ja.texi: Add "Scroing".
+
+1998-06-30  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Scoring".
+
+1998-06-30  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * Sync up with Gnus 5.6.22
+       * lisp/gnus.el (gnus-version-number): Update to 6.7.8.
+       * lisp/pop3-fma.el : Enable to get localhost mail spool.
+
+1998-06-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.7.7.
+
+       * lisp/gnus-art.el (gnus-article-prepare): Set up
+       `gnus-article-current-summary' of gnus-article-buffer.
+       (gnus-request-article-this-buffer): Don't set up
+       `gnus-article-current-summary'.
+
+1998-06-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.7.6.
+
+1998-06-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-mime-preview-quitting-method): Renamed
+       from `mime-preview-quitting-method-for-gnus'.
+
+1998-06-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-preview-mime-message): New
+       implementation.
+
+       * lisp/gnus-art.el (mime-preview-quitting-method-for-gnus): Use
+       `gnus-article-show-summary' is `gnus-show-mime' is not nil.
+
+1998-06-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/ChangeLog, texi/gnus.texi, texi/message.texi,
+       lisp/ChangeLog, lisp/gnus.el, lisp/nngateway.el, lisp/nnfolder.el,
+       lisp/message.el, lisp/gnus-sum.el, lisp/gnus-soup.el: Sync up with
+       Gnus 5.6.20.
+
+1998-06-26  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * README, texi/ChangeLog, texi/gnus.texi, texi/message.texi,
+       lisp/ChangeLog, lisp/nnweb.el, lisp/nnmail.el, lisp/nndoc.el,
+       lisp/message.el, lisp/lpath.el, lisp/gnus.el, lisp/gnus-util.el,
+       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-score.el,
+       lisp/gnus-group.el, lisp/gnus-ems.el, lisp/gnus-demon.el,
+       lisp/gnus-art.el: Sync up with Gnus 5.6.16.
+
+1998-06-26  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.7.3.
+
+       * lisp/gnus-sum.el (gnus-summary-move-article): Use
+       `gnus-request-article-this-buffer'.
+       (gnus-request-partial-message): Likewise.
+
+       * lisp/gnus-art.el (gnus-article-prepare): Use
+       `gnus-request-article-this-buffer'.
+       (gnus-request-article-this-buffer): Renamed from
+       `gnus-request-original-article'; abolish conventional
+       implementation.
+       - Abolish unused setting for `mime-view-show-summary-method'.
+
+1998-06-26  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * readme, texi/ChangeLog, texi/gnus.texi, texi/message.texi,
+       lisp/ChangeLog, lisp/gnus.el, lisp/nnmail.el, lisp/nnheader.el,
+       lisp/nngateway.el, lisp/nnfolder.el, lisp/nnagent.el,
+       lisp/message.el, lisp/gnus-sum.el, lisp/gnus-score.el,
+       lisp/gnus-salt.el, lisp/gnus-msg.el, lisp/gnus-cus.el,
+       lisp/gnus-cache.el, lisp/gnus-art.el: Sync up with Gnus 5.6.15.
+
+1998-06-24  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus.texi, texi/message.texi, texi/ChangeLog: Sync up with
+       Gnus 5.6.13.
+
+1998-06-14  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * Sync up with Gnus 5.6.13.
+
+1998-06-24  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-display-mime-message): Don't
+       `save-excursion'.
+       (gnus-article-prepare): Use `mime-fetch-field' instead of
+       `mime-entity-fetch-field'.
+
+1998-06-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-display-mime-message): Use
+       `mime-display-message' instead of `mime-view-buffer'.
+       (gnus-article-display-traditional-message): Set
+       `gnus-article-buffer'.
+       (gnus-article-display-message-with-encoded-word): Modify for
+       `gnus-article-display-traditional-message'.
+       (gnus-article-prepare): Use `mime-parse-buffer' and
+       `mime-entity-fetch-field'; don't set gnus-article-buffer.
+
+1998-06-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-move-article): Use
+       `gnus-request-original-article' instead of
+       `gnus-request-article-this-buffer'.
+
+1998-06-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus-ja.texi, texi/gnus.texi (Using MIME): Modify
+       description about new display mechanism.
+
+1998-06-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.6.0.
+       (gnus-version): Modify for this branch.
+
+       * lisp/gnus-art.el (gnus-article-display-method-for-mime): New
+       variable; abolish `gnus-show-mime-method'.
+       (gnus-article-display-method-for-encoded-word): New variable;
+       abolish `gnus-decode-encoded-word-method'.
+       (gnus-article-display-method-for-traditional): New variable.
+       (gnus-article-display-mime-message): New function; abolish
+       `gnus-article-preview-mime-message'.
+       (gnus-article-display-traditional-message): New function.
+       (gnus-article-display-message-with-encoded-word): New function;
+       abolish `gnus-article-decode-encoded-word'.
+       (gnus-article-prepare): Change display mechanism; use
+       `gnus-request-original-article' instead of
+       `gnus-request-article-this-buffer'.
+       (gnus-request-original-article): New function.
+
+1998-06-22  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.6.0.
+       (gnus-version): Modify for SEMI 1.8.
+
+       * lisp/gnus-sum.el: Modify for interface change in SEMI 1.8 about
+       automatic message/partial combining.
+
+1998-06-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.5.0.
+       (gnus-version): Modify for SEMI 1.7.
+
+       * lisp/gnus-sum.el: Rename
+       `mime-method-to-combine-message/partial-pieces' to
+       `mime-combine-message/partial-pieces-automatically'.
+
+       * lisp/gnus-art.el (gnus-article-preview-mime-message): Use
+       `mime-view-buffer'.
+       (gnus-article-decode-encoded-word): Fix DOC-string.
+       (gnus-article-header-presentation-method): New function; abolish
+       `gnus-content-header-filter'.
+       Modify for SEMI 1.7.
+
+1998-06-18  Keisuke Mori   <ksk@ntts.com>
+
+       * texi/gnus-ja.texi: Add "Select Methods".
+
+1998-06-18  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Select Methods".
+
+1998-06-17  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el: Small bug fix.
+
+       * lisp/pop3-fma.el: Delete variable pop3-fma-cypher-key
+       Use base64-encode-string , base64-decode-string instead.
+       Both change by Yasuo OKABE <okabe@kuis.kyoto-u.ac.jp>
+
+1998-06-13  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el: New function pop3-fma-cypher-string
+       New variable pop3-fma-cypher-key
+
+1998-06-12  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/message.el (message-required-news-headers): `X-Newsreader'
+       was replaced by `User-Agent'.
+       (message-required-mail-headers): `X-Mailer' was replaced by
+       `User-Agent'.
+       (message-header-format-alist): `X-Mailer' and `X-Newsreader' were
+       replaced by `User-Agent'.
+       (message-generate-headers): Ditto.
+
+       (message-user-agent): New variable.
+       (message-newsreader): Replaced by `message-user-agent'.
+       (message-mailer): Ditto.
+       (message-mode): `message-mailer' and `message-newsreader' were
+       replaced by `message-user-agent'.
+
+       * lisp/gnus-msg.el (gnus-inews-add-send-actions): `message-mailer'
+       and `message-newsreader' were replaced by `message-user-agent'.
+       (gnus-extended-version): Generate "PRODUCT/VERSION" style strings.
+
+       * lisp/gnus-soup.el (gnus-soup-send-packet): `message-mailer' and
+       `message-newsreader' were replaced by `message-user-agent'.
+
+1998-06-07  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el: Delete setting for
+       `article-de-quoted-unreadable' and
+       `article-mime-decode-quoted-printable' because they have been
+       already abolished.
+
+1998-06-07  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus-ja.texi: Sync up with latest gnus.texi.
+
+       * texi/gnus.texi: Modify for Semi-gnus 6.4.0.
+
+1998-06-06  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-extract-address-components): Add
+       `std11-extract-address-components' as a choice.
+
+1998-06-06  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Composing Messages".
+
+1998-06-04  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-ems.el (gnus-ems-redefine): Must require 'path-util
+       before call `module-installed-p'.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.4.0.
+       (gnus-version): Modify for SEMI 1.5.
+
+       * lisp/gnus-art.el: Modify for SEMI 1.5 API.
+
+1998-06-04  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/pop3-fma.el: New file. To handle multiple POP account.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.3.4.
+       And fix typo 5.6.10 -> 5.6.11.
+
+1998-06-03  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.3.3.
+
+       * Sync up with Gnus 5.6.11.
+
+1998-06-03  Keisuke Mori   <ksk@ntts.com>
+
+       * texi/gnus-ja.texi: Add "The Article Buffer".
+
+1998-06-03  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "The Summary Buffer".
+
+1998-06-02  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.3.2.
+
+       * Sync up with Gnus 5.6.10.
+
+1998-05-30  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * README.semi: Add description of `shuhei-k' branch.
+
+1998-05-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.3.1.
+
+1998-05-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-util.el (gnus-output-to-rmail): Guard as binary.
+
+       * lisp/gnus-util.el (gnus-output-to-mail): Guard as binary.
+
+1998-04-24  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "The Active File".
+
+1998-05-04  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.3.0.
+       (gnus-version): Modify for SEMI 1.4.
+
+       * lisp/gnus-sum.el: Use 'mime-add-condition to set up
+       acting-condition.
+
+1998-05-04  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/lpath.el: Must add "flim" instead of "mel" to load-path.
+
+1998-05-03  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.5.
+
+       * texi/gnus.texi, lisp/ChangeLog: Sync up with Gnus v5.6.9.
+
+       * lisp/gnus.el, lisp/message.el, lisp/gnus-sum.el,
+       lisp/gnus-msg.el, lisp/gnus-draft.el, lisp/gnus-agent.el: Sync up
+       with Gnus v5.6.9.
+
+1998-04-30  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.4.
+
+       * texi/gnus.texi, lisp/ChangeLog: Sync up with Gnus 5.6.7.
+
+       * lisp/gnus.el, lisp/message.el, lisp/gnus-sum.el,
+       lisp/gnus-msg.el, lisp/gnus-cache.el, lisp/gnus-art.el: Sync up
+       with Gnus 5.6.7.
+
+1998-04-28  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.3.
+
+       * Sync up with Gnus 5.6.6.
+
+1998-04-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el: Sync up with Gnus 5.6.5.
+
+1998-04-26  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.2.
+
+       * Sync up with Gnus 5.6.5.
+
+       * texi/custom.texi, texi/widget.texi: Removed from Semi-gnus.
+
+1998-04-25  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * README.semi (How to get? (via CVS)): Modify descriptions about
+       TAG.
+
+1998-04-23  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.1.
+
+1998-04-23  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el (message-make-forward-subject): Use
+       `eword-decode-unstructured-field-body' for subject.
+
+       * lisp/gnus-msg.el (gnus-summary-mail-forward): Make local
+       variable `default-mime-charset' of `gnus-original-article-buffer'
+       and set up by `default-mime-charset' of `gnus-summary-buffer'.
+
+1998-04-23  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus-ja.texi: Fix typos.
+
+       * texi/gnus.texi: Modify for Semi-gnus.
+
+1998-04-23  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Auto Save".
+
+1998-04-22  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Startup Files".
+
+1998-04-21  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.2.0.
+       (gnus-version): Modify for SEMI 1.3.
+
+       * lisp/gnus-sum.el: Use 'ctree-set-calist-strictly instead of
+       'set-atype to set up for 'mime-acting-condition.
+
+1998-04-21  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "Changing Servers".
+
+1998-04-20  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus-ja.texi: Modify styles.
+
+       * texi/gnus.texi: Modify for Semi-gnus (sync up with
+       gnus-ja.texi).
+
+1998-04-20  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Add "New Groups".
+
+1998-04-20  Yoshiki Hayashi   <penny@tb3.so-net.ne.jp>
+
+       * texi/gnus-ja.texi: Modify styles.
+
+1998-04-18  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus-ja.texi: Check and modify for Semi-gnus.
+
+1998-04-18  Yoshiki Hayashi   <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: New file.
+
+1998-04-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.1.3.
+
+1998-04-19  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-following-method): New function; set up
+       for 'mime-view-following-method-alist.
+
+1998-04-18  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus.texi: Add and modify description for Semi-gnus.
+
+1998-04-16  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * texi/gnus.texi: "Gnus 5.6.4" -> "Semi-gnus 6.1.2".
+       (Top): "Gnus" -> "gnus".
+       (Starting Up): "Gnus" -> "gnus".
+
+1998-04-10  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/ChangeLog, lisp/gnus-agent.el: Sync up with Gnus 5.6.4.
+
+1998-04-08  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.1.2.
+       (gnus-version): Include corresponding SEMI version.
+
+       * lisp/gnus.el, lisp/nnkiboze.el, lisp/message.el,
+       lisp/gnus-sum.el, lisp/gnus-agent.el: Sync up with Gnus 5.6.4.
+
+1998-03-27  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * README.semi: Change descriptions of sending bug report.
+
+1998-03-20  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.1.1.
+       (gnus-version): Include corresponding SEMI version.
+
+       * Sync up with Gnus 5.6.3.
+
+1998-03-15  Shuhei KOBAYASHI  <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus-agent.el (gnus-agent-crosspost): Use
+       `nnheader-insert-file-contents'.
+       (gnus-agent-braid-nov): Ditto.
+       (gnus-agent-expire): Ditto.
+
+       * lisp/gnus-cache.el (gnus-cache-request-article): Ditto.
+       (gnus-cache-retrieve-headers): Ditto.
+       (gnus-cache-change-buffer): Ditto.
+       (gnus-cache-braid-nov): Ditto.
+
+       * lisp/gnus-sum.el (gnus-summary-import-article): Ditto.
+
+       * lisp/nnkiboze.el (nnkiboze-retrieve-headers): Ditto.
+
+       * lisp/message.el (message-generate-headers): Fix regexp.
+       (cf. [semi-gnus-ja:107])
+
+1998-03-14  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el: Add setting for
+       `mime-raw-buffer-coding-system-alist'.
+
+1998-03-13  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el: Rename `mime-view-quitting-method-for-gnus' ->
+       `mime-preview-quitting-method-for-gnus'.
+
+       * lisp/gnus-art.el: Rename `mime-view-quitting-method-alist' ->
+       `mime-preview-quitting-method-alist'.
+
+       * lisp/gnus-art.el: Rename `mime-view-kill-buffer' ->
+       `mime-preview-kill-buffer'.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.10.
+
+       * lisp/gnus-sum.el: Add code to check latest SEMI.
+       (mime-acting-condition): Separate type and subtype; rename
+       `mime-combine-message/partials-automatically' ->
+       `mime-method-to-combine-message/partial-pieces'.
+
+1998-03-08  Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.9.
+
+       * README.semi (How to get?): Add description of daily snapshot.
+       (How to join development): Change mailing list command address.
+
+       * Sync up with Gnus 5.6.2.
+
+1998-03-01  Tatsuya Ichikawa  <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/gnus-ems.el: Change variable name
+       gnus-bdf-image-file to gnus-mule-bitmap-image-file.
+
+1998-02-28  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.8.
+
+       * lisp/gnus.el: Sync up with qgnus-0.34.
+
+1998-02-28  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el: Sync up with qgnus-0.33.
+
+       * lisp/gnus-ems.el (gnus-bdf-image-file): New variable; moved from
+       gnus.el.
+       (gnus-mule-group-startup-message): New function; moved and renamed
+       from `gnus-group-startup-message' of gnus.el.
+
+       * lisp/gnus.el, lisp/gnus-sum.el, lisp/gnus-art.el,
+       lisp/gnus-agent.el: Sync up with qgnus-0.33.
+
+1998-02-28  Tatsuya Ichikawa  <t-ichi@niagara.shiojiri.ne.jp>
+
+       * lisp/gnus.el (gnus-bdf-image-file): New variable.
+       (gnus-mule-group-startup-message): Display bitmap image using
+       bitmap.el running with Emacs 20.
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-headers): Fix problem when
+       Xref field is not exist.
+
+1998-02-26  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * README.semi (How to join development): Modify for Semi-gnus
+       mailing list.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.7.
+
+       * lisp/gnus.el (gnus-article-display-hook): Delete
+       `gnus-article-de-quoted-unreadable' from options.
+
+       * lisp/gnus-sum.el (gnus-article-make-menu-bar): Delete key for
+       `gnus-article-de-quoted-unreadable'.
+       (gnus-summary-make-menu-bar): Delete menu for
+       `gnus-article-de-quoted-unreadable'.
+
+       * lisp/gnus-art.el (gnus-article-make-menu-bar): Delete menu for
+       `gnus-article-de-quoted-unreadable'.
+
+1998-02-24  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el, lisp/message.el: Sync up with qgnus-0.32.
+
+1998-02-23  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.6.
+
+       * lisp/message.el (message-fill-references): Abolish unused local
+       variables.
+
+       * lisp/pop3.el, lisp/message.el, lisp/gnus.el, lisp/gnus-sum.el,
+       lisp/gnus-art.el: Sync up with qgnus-0.31.
+
+       * lisp/gnus.el, lisp/message.el, lisp/gnus-sum.el,
+       lisp/gnus-art.el: Sync up with qgnus-0.30.
+
+1998-02-20  Christophe Broult <christophe.broult@info.unicaen.fr>
+
+       * README.semi (How to get?): The command `update' must come before
+       `-r semi-gnus'. (cf. [tm-en:1559])
+
+1998-02-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el: Sync up with qgnus-0.29.
+
+       * lisp/gnus.el, lisp/message.el: Sync up with qgnus-0.28.
+
+       * lisp/message.el: Abolish variable
+       `message-references-generator'.  Abolish function
+       `message-generate-filled-references',
+       `message-generate-folded-references' and
+       `message-generate-unfolded-references'.
+       (message-reply): Don't use `message-references-generator'.
+       (message-followup): Don't use `message-references-generator'.
+
+       (message-fill-references): New function.
+       (message-header-format-alist): Use `message-fill-references' for
+       References.
+
+1998-02-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.5.
+
+1998-02-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-sum.el: Check SEMI-0.118.2 (Otomaru) or later.
+       (gnus-structured-field-decoder): Use
+       `eword-decode-and-unfold-structured-field'.
+
+       * lisp/gnus-art.el (gnus-article-decode-rfc1522): Use charset
+       conversion option of `eword-decode-header'.
+       (gnus-article-decode-encoded-word): Use charset conversion option
+       of `eword-decode-header'; use `gnus-run-hooks'.
+       (gnus-content-header-filter): Use charset conversion option of
+       `eword-decode-header'.
+
+       * README.semi (How to get?): Should specify "-r semi-gnus".
+
+1998-02-16  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-decode-rfc1522): Decode header by
+       localized code.
+
+1998-02-16  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-msg.el: Delete commented-out function
+       `gnus-inews-insert-mime-headers'.
+
+       * lisp/gnus.el, lisp/message.el, lisp/gnus-sum.el,
+       lisp/gnus-art.el: Sync up with qgnus-0.27.
+
+1998-02-16  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnheader.el: Use original.
+
+       * lisp/gnus.el, lisp/pop3.el, lisp/message.el, lisp/gnus-sum.el,
+       lisp/gnus-msg.el, lisp/gnus-draft.el, lisp/gnus-art.el: Sync up
+       with qgnus-0.26.
+
+1998-02-15  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnmail.el, lisp/nnmh.el: Use original.
+
+       * lisp/gnus.el, lisp/gnus-draft.el, lisp/gnus-sum.el,
+       lisp/message.el, lisp/gnus-art.el: Sync up with qgnus-0.25.
+
+1998-02-11  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog,
+       lisp/message.el, lisp/gnus.el, lisp/gnus-uu.el,
+       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-start.el,
+       lisp/gnus-score.el, lisp/gnus-group.el, lisp/gnus-art.el,
+       lisp/gnus-agent.el, lisp/ChangeLog: Importing qgnus-0.24
+
+1998-02-10  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-prepare): Don't bind coding
+       systems.
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.0.4.
+       (gnus-version): Sync with qgnus-0.23.
+
+       * lisp/pop3.el, lisp/nnmh.el, lisp/nnheader.el, lisp/message.el,
+       lisp/gnus-sum.el, lisp/gnus-msg.el, lisp/gnus-draft.el,
+       lisp/gnus-art.el: Merge qgnus-0.23.
+
+1998-02-09  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/nntp.el,
+       lisp/nnheader.el, lisp/message.el, lisp/gnus.el,
+       lisp/gnus-xmas.el, lisp/gnus-sum.el, lisp/gnus-start.el,
+       lisp/gnus-msg.el, lisp/gnus-group.el, lisp/gnus-draft.el,
+       lisp/gnus-art.el, lisp/gnus-agent.el, lisp/ChangeLog: Importing
+       qgnus-0.23
+
+1998-02-04  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el (message-references-generator): New variable.
+       (message-generate-filled-references): New function.
+       (message-generate-folded-references): New function.
+       (message-generate-unfolded-references): New function.
+       (message-reply): Refer `message-references-generator'.
+       (message-followup): Refer `message-references-generator'.
+
+1998-01-17  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el (message-send-mail-with-sendmail): Guard
+       `coding-system-for-write' by binary.
+       (message-send-mail-with-qmail): Likewise.
+
+1998-01-16  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/lpath.el: Require path-util; add load-path of APEL, MEL and
+       SEMI.
+
+1998-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el: Require smtp.el when compile.
+
+       * lisp/message.el (message-send-mail-with-smtp): Use
+       `(current-buffer)' instead of `tembuf'; rename
+       `smtp-recipient-address-list' -> `recipient-address-list'.
+
+1998-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/smtp.el (smtp-deduce-address-list): Don't use
+       `smtp-recipient-address-list' as global variable.
+
+       * lisp/message.el (message-send-mail-with-smtp): Don't use
+       `smtp-recipient-address-list' as global variable.
+
+       * lisp/smtpmail.el (smtpmail-recipient-address-list): New
+       variable; renamed from `smtp-recipient-address-list'.
+       (smtpmail-send-it): Remove `(not (null ...))'.
+       (smtpmail-send-queued-mail): Likewise.
+
+1998-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/message.el (message-send-mail-with-smtp): Don't generate
+       temporary buffer for message; don't generate and kill
+       `smtp-address-buffer' for `smtp-deduce-address-list'.
+
+       * lisp/smtpmail.el (smtpmail-send-it): Don't generate and kill
+       `smtp-address-buffer' for `smtp-deduce-address-list'.
+
+       * lisp/smtp.el (smtp-deduce-address-list): Bind and generate
+       `smtp-address-buffer' in itself.
+
+1998-01-12  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to version 6.0.3.
+
+1998-01-11  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/smtp.el: New file.
+
+       * lisp/smtpmail.el: Split basic features into smtp.el.
+
+       * lisp/message.el (message-send-mail-function): Add
+       `message-send-mail-with-smtp' as an item.
+       (message-send-mail-with-smtp): New function.
+
+       * ChangeLog: New file.
+
+1998-01-08  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/smtpmail.el (smtpmail-via-smtp): Bind
+       `coding-system-for-read' by `smtpmail-coding-system' to avoid
+       dead-locking in Emacs 20.
+
+       * lisp/gnus.el: gnus.el (gnus-version-number): Update to version
+       6.0.2.
+
+1998-01-07  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnmail.el, lisp/message.el: Sync with Quassia Gnus v0.22.
+
+       * lisp/gnus.el: Delete autoload setting for `metamail-buffer'.
+
+       * lisp/gnus.el, lisp/gnus-sum.el: Sync with Quassia Gnus v0.22.
+
+       * lisp/gnus-msg.el: Abolish function
+       `gnus-inews-insert-mime-headers'.
+
+       * lisp/gnus-msg.el, lisp/gnus-draft.el, lisp/gnus-art.el: Sync
+       with Quassia Gnus v0.22.
+
+       * lisp/smtpmail.el (smtpmail-coding-system): New variable; abolish
+       `smtpmail-code-conv-from'.
+       (smtpmail-via-smtp): Guard `coding-system-for-write' by
+       `smtpmail-coding-system'.
+
+       * lisp/smtpmail.el: Imported from Emacs 20.2.
+
+       * lisp/pop3.el (pop3-movemail-file-coding-system): Change default
+       value to `binary'.
+       (pop3-open-server): Guard `coding-system-for-read' by `binary'.
+
+1998-01-06  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/nnoo.el,
+       lisp/nnml.el, lisp/message.el, lisp/gnus.el, lisp/gnus-sum.el,
+       lisp/gnus-start.el, lisp/gnus-ems.el, lisp/gnus-draft.el,
+       lisp/gnus-agent.el, lisp/ChangeLog: Importing qgnus-0.22
+
+       * texi/message.texi, texi/gnus.texi, lisp/gnus.el, lisp/ChangeLog:
+       Importing qgnus-0.21
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog,
+       lisp/nnvirtual.el, lisp/nnsoup.el, lisp/nnoo.el, lisp/nnmh.el,
+       lisp/nnmail.el, lisp/nndraft.el, lisp/gnus.el, lisp/gnus-xmas.el,
+       lisp/gnus-sum.el, lisp/gnus-start.el, lisp/gnus-score.el,
+       lisp/gnus-msg.el, lisp/gnus-group.el, lisp/gnus-draft.el,
+       lisp/gnus-art.el, lisp/ChangeLog: Importing qgnus-0.20
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/pop3.el,
+       lisp/nntp.el, lisp/nnml.el, lisp/nnmail.el, lisp/nndoc.el,
+       lisp/message.el, lisp/gnus.el, lisp/gnus-uu.el,
+       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-start.el,
+       lisp/gnus-score.el, lisp/gnus-group.el, lisp/gnus-cache.el,
+       lisp/gnus-agent.el, lisp/ChangeLog: Importing qgnus-0.19
+
+1997-12-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to version 6.0.1.
+
+       * lisp/message.el (message-resend): Enclose `message-setup' with
+       `(let (message-setup-hook) ...)' to avoid to `turn-on-mime-edit';
+       must setup `message-encoding-buffer' and `message-edit-buffer' for
+       `message-send-mail'.
+
+1997-12-08  Shuhei Kobayashi  <shuhei-k@jaist.ac.jp>
+
+       * lisp/pop3.el, lisp/message.el, lisp/gnus.el, lisp/gnus-sum.el,
+       lisp/gnus-art.el, lisp/ChangeLog: Synch'ed up to qgnus-0.18.
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog,
+       lisp/smiley.el, lisp/pop3.el, lisp/nnweb.el, lisp/nntp.el,
+       lisp/nnml.el, lisp/nnmail.el, lisp/nnheader.el, lisp/nndraft.el,
+       lisp/message.el, lisp/lpath.el, lisp/gnus.el, lisp/gnus-util.el,
+       lisp/gnus-sum.el, lisp/gnus-start.el, lisp/gnus-picon.el,
+       lisp/gnus-nocem.el, lisp/gnus-mh.el, lisp/gnus-group.el,
+       lisp/gnus-ems.el, lisp/gnus-cite.el, lisp/gnus-art.el,
+       lisp/gnus-agent.el, lisp/dgnushack.el, lisp/ChangeLog: Importing
+       qgnus-0.18
+
+1997-11-29  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * README.semi: New file.
+
+       * lisp/gnus.el (gnus-version): Rename to "Semi-gnus".
+
+1997-11-28  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-decoding-function): New variable.
+       (gnus-draft-setup): Use `gnus-draft-decoding-function'.
+
+1997-11-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+
+       * lisp/nnmail.el, lisp/nnheader.el, lisp/message.el, lisp/gnus.el,
+       lisp/gnus-sum.el, lisp/gnus-msg.el, lisp/gnus-art.el: sync with
+       qgnus-0.17.
+
+       * texi/message.texi, texi/gnus.texi, lisp/smiley.el, lisp/nnoo.el,
+       lisp/nnml.el, lisp/nnmail.el, lisp/nnheader.el,
+       lisp/messagexmas.el, lisp/message.el, lisp/gnus.el,
+       lisp/gnus-xmas.el, lisp/gnus-util.el, lisp/gnus-sum.el,
+       lisp/gnus-start.el, lisp/gnus-spec.el, lisp/gnus-score.el,
+       lisp/gnus-picon.el, lisp/gnus-move.el, lisp/gnus-msg.el,
+       lisp/gnus-kill.el, lisp/gnus-group.el, lisp/gnus-draft.el,
+       lisp/gnus-demon.el, lisp/gnus-cite.el, lisp/gnus-art.el,
+       lisp/ChangeLog: Quassia Gnus v0.17.
+
+       * lisp/gnus-i18n.el: New file.
+
+       * lisp/nnmail.el (nnmail-file-coding-system): Use `raw-text' in
+       default.
+
+       * lisp/nnheader.el (nnheader-file-coding-system): Use `raw-text'
+       in default.
+
+       * lisp/message.el (message-encode-function): New variable.
+       (message-forward-start-separator): Modify for mime-edit.
+       (message-forward-end-separator): Modify for mime-edit.
+       (message-setup-hook): Use `(message-maybe-setup-default-charset
+       turn-on-mime-edit)' in default.
+       (message-header-hook): Use `(eword-encode-header)' in default.
+
+       (message-send): Use local variable `message-encoding-buffer',
+       `message-edit-buffer' and `message-mime-mode' as public variables;
+       use `message-encode-function'.
+       (message-send-mail): Use `message-encoding-buffer' to get contents
+       of body; abolish `message-encode-mail-hook'; use
+       `mime-edit-maybe-split-and-send'; use `message-edit-buffer' to
+       refer original editing buffer.
+       (message-send-news): Use `message-encoding-buffer' to get contents
+       of body; abolish `message-encode-news-hook'; use
+       `mime-edit-maybe-split-and-send'; use `message-edit-buffer' to
+       refer original editing buffer.
+       (message-check-news-syntax): Call `message-check-news-body-syntax'
+       in `mime-edit-buffer'.
+       (message-do-fcc): Use `message-encoding-buffer' to get contents;
+       run `message-header-hook'.
+       (message-cancel-news): Use `std11-extract-address-components'
+       instead of `mail-extract-address-components'; bind
+       `message-encoding-buffer' and `message-edit-buffer'.
+
+       (message-maybe-setup-default-charset): New function.
+       (message-maybe-encode): New function.
+       (message-mime-insert-article): New function.
+       Add setting for mime-view.
+
+       * lisp/gnus.el (gnus-version-number): for version number for Open
+       gnus.
+       (gnus-version): Modify for Open gnus.
+
+       * lisp/gnus-sum.el: Autoload gnus-i18n.
+
+       (gnus-show-mime): `t' in default.
+       (gnus-structured-field-decoder): Use
+       `eword-decode-structured-field-body' in default.
+       (gnus-unstructured-field-decoder): Use
+       `eword-decode-unstructured-field-body' in default.
+
+       (gnus-parse-headers-hook): Use
+       `(gnus-set-summary-default-charset)' in default.
+
+       (gnus-summary-mode-map): Add binding for
+       `gnus-summary-scroll-down' and
+       `gnus-summary-preview-mime-message'.
+
+       (gnus-summary-preview-mime-message): New function.
+       (gnus-mime-partial-preview-function): New function.
+       Add setting for mime-view.
+
+       * lisp/gnus-msg.el (gnus-summary-cancel-article): Display
+       `gnus-article-buffer' instead ofb `gnus-original-article-buffer'.
+       (gnus-extended-version): Don't return version of emacsen.
+       (gnus-inews-do-gcc): Refer `message-encoding-buffer'.
+
+       * lisp/gnus-art.el (gnus-show-mime-method): Use
+       `gnus-article-preview-mime-message' instead of `metamail-buffer'
+       in default.
+       (gnus-decode-encoded-word-method): Use
+       `gnus-article-decode-encoded-word' instead of
+       `gnus-article-de-quoted-unreadable' in default.
+
+       Abolish `gnus-hack-decode-rfc1522', `gnus-decode-rfc1522',
+       `article-decode-rfc1522', `article-de-quoted-unreadable',
+       `article-mime-decode-quoted-printable-buffer' and
+       `article-mime-decode-quoted-printable'.
+       (gnus-article-decode-rfc1522): New implementation (use
+       `eword-decode-header').
+
+       (gnus-article-preview-mime-message): New function.
+       (gnus-article-decode-encoded-word): New function.
+       (gnus-content-header-filter): New function.
+       (mime-view-quitting-method-for-gnus): New function.
+       Add setting for mime-view.
+
+       * lisp/message.el: Abolish `message-max-size' because it is not
+       used.
+
+       * lisp/message.el: sync with qgnus-0.16.
+
+       * texi/Makefile, texi/message.texi, texi/gnus.texi, lisp/nnweb.el,
+       lisp/nnmh.el, lisp/nnheader.el, lisp/nnfolder.el, lisp/message.el,
+       lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
+       lisp/gnus-sum.el, lisp/gnus-srvr.el, lisp/gnus-picon.el,
+       lisp/gnus-group.el, lisp/gnus-cite.el, lisp/gnus-art.el: Quassia
+       Gnus v0.16.
+
+       * lisp/nnmh.el (nnmh-request-list-1): fix maybe.
+
+       * lisp/message.el (message-do-fcc): Guard
+       `coding-system-for-write' by `raw-text'; run
+       `message-before-do-fcc-hook'.
+
+       * lisp/gnus-msg.el (gnus-inews-do-gcc): Guard
+       `coding-system-for-write' by `raw-text'; run
+       `gnus-before-do-gcc-hook'.
+
+       * texi/message.texi, texi/gnus.texi, texi/ChangeLog, lisp/nntp.el,
+       lisp/nnoo.el, lisp/nnml.el, lisp/nndraft.el, lisp/nnbabyl.el,
+       lisp/message.el, lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
+       lisp/gnus-util.el, lisp/gnus-sum.el, lisp/gnus-start.el,
+       lisp/gnus-spec.el, lisp/gnus-soup.el, lisp/gnus-score.el,
+       lisp/gnus-msg.el, lisp/gnus-gl.el, lisp/gnus-ems.el,
+       lisp/gnus-draft.el, lisp/gnus-cache.el, lisp/gnus-audio.el,
+       lisp/gnus-art.el, lisp/gnus-agent.el, lisp/ChangeLog: Quassia Gnus
+       v0.15.
+
+       * lisp/message.el, lisp/ChangeLog: sync with qgnus-0.14.
+
+       * texi/Makefile, texi/gnus.texi: Quassia Gnus v0.14.
+
+       * texi/dir: New file.
+
+       * texi/dir, lisp/pop3.el, lisp/nntp.el, lisp/nnml.el,
+       lisp/nnmail.el, lisp/nnfolder.el, lisp/message.el, lisp/lpath.el,
+       lisp/gnus.el, lisp/gnus-win.el, lisp/gnus-util.el,
+       lisp/gnus-topic.el, lisp/gnus-sum.el, lisp/gnus-start.el,
+       lisp/gnus-score.el, lisp/gnus-msg.el, lisp/gnus-mh.el,
+       lisp/gnus-cus.el, lisp/gnus-art.el, lisp/gnus-agent.el,
+       lisp/ChangeLog: Quassia Gnus v0.14.
+
+       * lisp/message.el, lisp/ChangeLog: sync with qgnus-0.13.
+
+       * texi/gnus.texi, texi/ChangeLog, lisp/pop3.el, lisp/nnweb.el,
+       lisp/nnmail.el: Quassia Gnus v0.13.
+
+       * lisp/nnlistserv.el: New file.
+
+       * lisp/nnlistserv.el, lisp/message.el, lisp/md5.el, lisp/lpath.el,
+       lisp/gnus.el, lisp/gnus-topic.el, lisp/gnus-sum.el,
+       lisp/gnus-score.el, lisp/gnus-picon.el, lisp/gnus-msg.el,
+       lisp/gnus-group.el, lisp/gnus-art.el, lisp/gnus-agent.el,
+       lisp/dgnushack.el, lisp/ChangeLog, GNUS-NEWS: Quassia Gnus v0.13.
+
+       * lisp/message.el: sync with qgnus-0.12.
+
+       * texi/message.texi, texi/gnus.texi, texi/gnus-faq.texi,
+       texi/ChangeLog, lisp/nntp.el, lisp/nnmh.el, lisp/nnmail.el,
+       lisp/nndraft.el, lisp/messcompat.el, lisp/message.el,
+       lisp/gnus.el, lisp/gnus-xmas.el, lisp/gnus-uu.el,
+       lisp/gnus-sum.el, lisp/gnus-score.el, lisp/gnus-salt.el,
+       lisp/gnus-msg.el, lisp/gnus-int.el, lisp/gnus-group.el,
+       lisp/gnus-demon.el, lisp/gnus-cache.el, lisp/gnus-art.el,
+       lisp/gnus-agent.el, lisp/ChangeLog, GNUS-NEWS: Quassia Gnus v0.12.
+
+       * lisp/message.el (message-send-news-function): Use
+       `message-send-news-with-gnus' in default.
+       (message-send-via-news): Use `message-send-news' instead of
+       `message-send-news-function'.
+       (message-send-mail): Don't avoid text properties; run
+       `message-encode-mail-hook'.
+       (message-send-news): Don't avoid text properties; run
+       `message-encode-news-hook'; use `message-send-news-function'.
+       (message-send-news-with-gnus): New function.
+       (message-cancel-news): Use `message-send-news' instead of
+       `message-send-news-function'.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/ChangeLog.2 b/ChangeLog.2
new file mode 100644 (file)
index 0000000..fad70e3
--- /dev/null
@@ -0,0 +1,624 @@
+1999-08-03  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * Makefile.in (clean): Exec make clean in both lisp and texi
+       subdirectories.
+       (distclean): Use $(MAKE), not `make'.
+
+1999-08-03  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * message.el (TopLevel): Autoload "mu-cite" for the function
+       `mu-cite-original' instead of the function `mu-cite/cite-original'.
+       (message-cite-function): Replace `mu-cite/cite-original' with
+       `mu-cite-original'.
+
+1999-08-02  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/Makefile.in (distclean): Remove dgnuspath.el instead of
+       paths.el.
+       (install): Don't install dgnuspath.el; don't touch the installed
+       files.
+
+1999-08-01  YAMAMOTO Kouji    <kouji@pobox.com>
+
+       * lisp/nnmail.el (nnmail-split-it): Don't compare ".*" and VALUE
+       of each element of `nnmail-split-fancy' if the length of VALUE is
+       less than 2.
+
+1999-07-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+1999-07-30  NAKAJI Hiroyuki   <nakaji@tutrp.tut.ac.jp>
+
+       * lisp/Makefile.in (install): install *.el files too.
+       to avoid warning about el is newer than elc, exec touch
+       $(lispdir)/*.elc.
+
+1999-07-29  Yoshiki Hayashi   <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * texi/gnus-ja.texi: Sync up with pGnus 0.95.
+
+1999-07-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-cite.el (gnus-ems-redefine): Don't replace the function
+       `gnus-cite-add-face' with `gnus-mule-cite-add-face' because the
+       former will work well under old Emacsen by now.
+       (gnus-mule-cite-add-face): Abolish function.
+
+1999-07-27  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * texi/Makefile.in (prefix): Define it first.
+
+       * lisp/dgnuspath.el.in: Rename from paths.el.
+
+       * lisp/dgnushack.el (dgnushack-install-package): Don't install
+       dgnuspath.el nor dgnuspath.elc.
+       (dgnushack-make-package): Don't enter dgnuspath.el nor
+       dgnuspath.elc to MANIFEST file.
+       (dgnushack-compile): Don't compile dgnuspath.el.
+       (TopLevel): Use `expand-file-name' for the file "./dgnuspath.el";
+       use dgnuspath.el instead of paths.el.
+
+       * lisp/Makefile.in (PACKAGEDIR): Default to @PACKAGEDIR@.
+
+       * configure.in (AC_OUTPUT): Use dgnuspath.el instead of paths.el.
+       (TopLevel): Add options `--with-xemacs' and `--with-packagedir'.
+       (ADDITIONAL_LOAD_PATH): Default to empty string.
+
+       * configure: Regenerate.
+
+       * README.T-gnus: Update for the new features.
+
+       * Makefile.in (PACKAGEDIR): Default to @PACKAGEDIR@.
+       (XEMACS): Default to @XEMACS@.
+
+1999-07-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/dgnushack.el: Load ./paths.el.
+
+       * lisp/paths.el.in: New file.
+
+       * lisp/Makefile.in (distclean): Remove paths.el.
+
+       * Mule23@1934: Update for the new configure usage.
+
+       * configure: Regenerate.
+
+1999-07-22  TSUCHIYA Masatoshi <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * configure.in: Add an option `--with-addpath' to specify load-path.
+
+       * aclocal.m4: New implementation.
+
+       * acinclude.m4: New file.
+
+1999-07-20   Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-ofsetup.el (gnus-ofsetup-prepare-for-miee,
+       gnus-ofsetup-write-setting-file): New functions.
+       (gnus-setup-for-offline): Use them.
+       (gnus-ofsetup-parameters, gnus-ofsetup-customize,
+       gnus-ofsetup-customize-done): New functions for customization
+       support.
+
+       * lisp/gnus-offline.el (gnus-offline-version-number): Update to
+       2.20.
+       (gnus-offline-define-menu-on-miee,
+       gnus-offline-define-menu-on-agent): Add a menu item which calls
+       `gnus-ofsetup-customize'.
+
+1999-07-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.08.
+       (gnus-revision-number): Fresh start from 00.
+
+       * texi/{gnus.texi,gnus-ja.texi,ChangeLog}: Update for T-gnus
+       6.11.08.
+
+       * lisp{pop3.el,nnmh.el,nnfolder.el,mm-util.el,mm-encode.el,
+       mm-decode.el,message.el,mail-source.el,gnus-util.el,gnus-topic.el,
+       gnus-sum.el,gnus-mlspl.el,gnus-mailcap.el,gnus-group.el,
+       gnus-cus.el,gnus-art.el,ChangeLog}: Sync up with Pterodactyl Gnus
+       v0.95.
+
+       * README.T-gnus: Update for T-gnus 6.11.08.
+
+1999-07-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/nnheader.el (make-full-mail-header-from-decoded-header): Add
+       `extra' as a luna-class.
+       (make-full-mail-header): Ditto.
+       (nnheader-decode-field-body): Redefine as a regular function.
+       (mail-header-set-extra): Alias to
+       `mime-gnus-entity-set-extra-internal'.
+       (mail-header-extra): Alias to `mime-gnus-entity-extra-internal'.
+
+       * lisp/mmgnus.el (TopLevel): Add definition of `extra' as a
+       luna-class.
+
+       * lisp/gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): Bind
+       the value of `default-mime-charset' to its local value in
+       `gnus-summary-buffer'; don't bind `mail-parse-charset' and
+       `mail-parse-ignored-charsets'.
+       (gnus-decode-encoded-word-function): New variable.
+
+1999-07-07  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.07.
+
+       * texi/{gnus.texi,gnus-ja.texi,ChangeLog}: Sync up with Pterodactyl
+       Gnus v0.93.
+
+       * lisp/{pop3.el,nnmail.el,mml.el,mm-view.el,mm-uu.el,mm-util.el,
+       mm-decode.el,message.el,gnus-util.el,gnus-sum.el,gnus-start.el,
+       gnus-srvr.el,gnus-score.el,gnus-mlspl.el,gnus-art.el,gnus-agent.el,
+       ChangeLog}: Sync up with Pterodactyl Gnus v0.93.
+
+       * README.T-gnus: Update for T-gnus 6.11.07.
+
+1999-07-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.06.
+       (gnus-revision-number): Fresh start from 00.
+
+       * texi/{gnus-ja.texi,gnus.texi,emacs-mime.texi,ChangeLog}: Sync up
+       with Pterodactyl Gnus v0.92.
+
+       * lisp/gnus-mlspl.el: New file copied from Pterodactyl Gnus v0.92.
+
+       * lisp/{nntp.el,nnmail.el,nnfolder.el,nndraft.el,nndoc.el,mml.el,
+       mm-view.el,mm-util.el,mm-decode.el,message.el,gnus-xmas.el,
+       gnus-util.el,gnus-sum.el,gnus-start.el,gnus-mailcap.el,
+       gnus-group.el,gnus-art.el,gnus-agent.el,Makefile.in,ChangeLog}:
+       Sync up with Pterodactyl Gnus v0.92.
+
+       * README.T-gnus: Update for T-gnus 6.11.06.
+
+1999-07-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-util.el (gnus-point-at-eol, gnus-point-at-bol): Use
+       `static-cond'.  NOTE: It requires APEL 9.20 or later.
+
+1999-07-05  Tsukamoto Tetsuo   <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-agent.el (gnus-agent-expire): Refresh the value of
+       `gnus-active-hashtb' for each method.
+
+1999-07-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.05.
+       (gnus-revision-number): Fresh start from 00.
+
+       * texi/gnus-ja.texi (Mail in a Newsreader): Translate into Japanese.
+
+       * README.T-gnus: Update for T-gnus 6.11.05.
+
+       * lisp/nnmbox.el (nnmbox-save-buffer): Bind `output-coding-system'
+       instead of `coding-system-for-write' Under Mule 2.
+
+       * lisp/nnmbox.el (nnmbox-active-file-coding-system,
+       nnmbox-file-coding-system): Default to `raw-text-dos' or 'raw-text'.
+       * lisp/nnfolder.el (nnfolder-file-coding-system,
+       nnfolder-active-file-coding-system): Ditto.
+
+       * lisp/mm-view.el (TopLevel): Don't bind vars `w3-meta-*'.
+
+       * lisp/gnus-util.el (gnus-write-active-file): Abolish function.
+       (gnus-write-active-file-as-coding-system): New function.
+
+       * lisp/gnus-cache.el (gnus-cache-write-active): Use
+       `gnus-write-active-file-as-coding-system' instead of
+       `gnus-write-active-file'.
+       * lisp/gnus-agent.el (gnus-agent-expire, gnus-agent-write-active):
+       Ditto.
+
+       * lisp/gnus-agent.el (gnus-agent-expire, gnus-agent-write-active,
+       gnus-agent-save-active-1): Use
+       `insert-file-contents-as-coding-system' instead of
+       `insert-file-contents-literally' or `insert-file-contents'.
+
+1999-07-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * texi/{emacs-mime.texi,ChangeLog}: Sync up with Pterodactyl Gnus
+       v0.91.
+       * lisp/{smiley.el,rfc2047.el,qp.el,nnml.el,nnmbox.el,nnmail.el,
+       nnheader.el,nnfolder.el,mml.el,mm-view.el,mm-uu.el,mm-util.el,
+       mm-encode.el,mm-decode.el,message.el,lpath.el,gnus-util.el,
+       gnus-sum.el,gnus-start.el,gnus-srvr.el,gnus-msg.el,gnus-mailcap.el,
+       gnus-cache.el,gnus-art.el,gnus-agent.el,base64.el}: Ditto.
+       * GNUS-NEWS: Ditto.
+
+1999-07-04  Yoshiki Hayashi   <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * texi/{gnusref-ja.tex,refcard-ja.tex}: Update to the version 5.5.
+
+1999-07-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+1999-07-04  Tsukamoto Tetsuo   <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-sum.el (gnus-get-newsgroup-headers): Don't bind the
+       value of `mail-parse-ignored-charsets' if its local value in
+       `gnus-summary-buffer' is nil.
+
+1999-07-02  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+       (gnus-other-frame): Use `static-if'.
+       (TopLevel): Require `static'.
+
+       * lisp/score-mode.el (score-mode-coding-system): Use `static-if'.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-util.el (gnus-point-at-eol, gnus-point-at-bol): Use
+       `static-cond' if it exists.  NOTE: It should be simplified in the
+       future.
+
+       * lisp/gnus-start.el (gnus-startup-file-coding-system): Use
+       `static-if'.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-art.el (gnus-article-display-x-face-with-x-face-mule):
+       Abolish function.
+
+       * lisp/dgnushack.el (dgnushack-make-package): Suppress verbose
+       messages while generating auto-autoloads.el.
+       (TopLevel): Set coding priority of Shift-JIS to the bottom.
+
+1999-06-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/message.el (message-pop-to-buffer-1): New macro.
+       (message-pop-to-buffer): Use it.
+       (message-delete-frame): Use `static-if'.
+       (TopLevel): Autoload "mu-cite".
+       (message-cite-function): Add `mu-cite/cite-original'.
+
+       * lisp/dgnushack.el (TopLevel): Bind functions defined by
+       `defun-maybe' for all Emacsen.
+
+       * lisp/Makefile.in (clean): Fix typo.
+
+       * Makefile.in (elclean): Remove auto-autoloads.el and
+       custom-load.el as well.
+
+1999-06-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.04.
+       (gnus-revision-number): Fresh start from 00.
+
+       * configure: Regenerate.
+
+       * lisp/mm-view.el (TopLevel): Define `gnus-article-mime-handles'
+       for avoiding byte compile warning.
+
+       * lisp/{rfc2047.el,nnmail.el,mml.el,mm-view.el,mm-util.el,
+       mm-bodies.el,message.el,mail-prsvr.el,gnus-xmas.el,gnus-sum.el,
+       gnus-start.el,gnus-draft.el,gnus-cus.el,gnus-cache.el,gnus-art.el,
+       ChangeLog}: Sync up with Pterodactyl Gnus v0.89.
+       * aclocal.m4: Ditto.
+
+       * README.T-gnus: Update for T-gnus 6.11.04.
+
+1999-06-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * Mule23@1934: New file.
+
+1999-06-23  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus-sum.el (gnus-articles-to-read): Use
+       `read-from-minibuffer' with specifying the input position instead
+       of the use of `read-string' with modifying `minibuffer-setup-hook'.
+       Exceptionally, don't specify the input position under Emacs 19 or
+       earlier against the mysterious bug. [cf. <semi-gnus-ja:3469>]
+       (TopLevel): Require `static'.
+
+1999-06-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+1999-06-22  NAKAJI Hiroyuki   <nakaji@tutrp.tut.ac.jp>
+
+       * texi/Makefile.in (distclean, veryclean): Use `clean' instead of
+       `make clean'.
+       (complete, tmps, latexboth, psout, pss, latexps): Use `$(MAKE)'
+       instead of `make'.
+       (TopLevel): Use `@SET_MAKE@'.
+
+       * lisp/Makefile.in (distclean): New target.
+       (clean): Renamed from `distclean'; don't remove Makefile.
+
+       * Makefile.in (distclean): Use `clean' instead of `make clean'.
+       (x, osome): Use `$(MAKE)' instead of `make'.
+       (elclean): Use the arg `-f'.
+       (clean): Remove MANIFEST.*.
+
+1999-06-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-dont-select-after-jump-to-other-group):
+       New user option.
+       (gnus-summary-jump-to-other-group): Use it.
+
+       * lisp/gnus-cite.el (gnus-cite-add-face): Add check for Emacs 21 or
+       later.
+
+1999-06-21  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-cite.el (gnus-cite-add-face): Use `move-to-column'
+       statically to skip the prefix string under Emacs 20.2 or earlier.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Move
+       `gnus-revision-number' to the last.
+
+1999-06-21  Daiji KANEMATSU   <kanematu@sra.co.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-jump-to-other-group): Call
+       `gnus-summary-read-group' with the 3rd arg T.
+
+1999-06-21  NAKAJI Hiroyuki   <nakaji@tutrp.tut.ac.jp>
+
+       * texi/Makefile.in (clean): Remove gnus.info*, gnus-ja.info*,
+       message.info*, message-ja.info*, *.texi_ and emacs-mime.info.
+
+       * lisp/Makefile.in (distclean): Remove auto-autoload.el and
+       custom-load.el.
+
+1999-06-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-sum.el (gnus-summary-mark-article): Call
+       `gnus-cache-possibly-enter-article' with the arg `headers'.
+       (gnus-summary-mark-article-as-unread): Ditto.
+       (gnus-summary-move-article): Ditto.
+
+       * lisp/gnus-cache.el (gnus-cache-update-article): Call
+       `gnus-cache-possibly-enter-article' with the arg `headers'.
+       (gnus-cache-enter-article): Ditto.
+       (gnus-cache-possibly-enter-article): Accept parameter `headers'.
+
+1999-06-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-sum.el (gnus-summary-jump-to-other-group): Rewrite as
+       an independent function.
+       (gnus-summary-read-group): Revert to the previous form.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Include
+       `gnus-revision-number' if it is non-zero.
+
+1999-06-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+       (TopLevel): Autoload "gnus-sum" for the command
+       `gnus-summary-jump-to-other-group'.
+
+       * lisp/gnus-art.el (gnus-article-read-summary-keys): Add key "ZJ"
+       to the list `nosaves'; convert key events to string statically
+       under XEmacs.
+       (gnus-article-display-x-face-with-x-face-mule): Use `gnus-xemacs'
+       instead of `featurep' with an arg `xemacs'.
+       (article-toggle-headers): Ditto.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-sum.el (gnus-summary-exit-map): New keystroke "ZJ" for
+       the command `gnus-summary-jump-to-other-group'.
+
+1999-06-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+           Daiji KANEMATSU   <kanematu@sra.co.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-read-group): Allow it to be an
+       user command.
+       (gnus-summary-jump-to-other-group): Defalias to
+       `gnus-summary-read-group'.
+
+1999-06-15  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.03.
+       (gnus-revision-number): Fresh start from 00.
+
+       * lisp/{gnus-sum.el,nnmail.el,ChangeLog}: Sync up with Pterodactyl
+       Gnus v0.88.
+
+       * README.T-gnus: Update for T-gnus 6.11.03.
+
+1999-06-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/message.el (message-send-news): Don't generate the Lines
+       field; don't make `tembuf' as unmodified.
+       (message-send-mail): Ditto.
+
+1999-06-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.02.
+
+       * lisp/{mail-source.el,gnus-sum.el,gnus-art.el}: Sync up with
+       Pterodactyl Gnus v0.87.
+
+       * text/gnus-ja.text (Troubleshooting): Make the return value of
+       `gnus-version' ambiguous.
+
+       * lisp/message.el (message-send-news): Make `tembuf' as unmodified
+       after inserting a text from `message-encoding-buffer'.
+       (message-send-mail): Ditto.
+
+1999-06-14  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.11.01.
+       (gnus-revision-number): Fresh start from 00.
+
+       * lisp/mm-view.el (TopLevel): Avoid byte compile warnings for the
+       use of old W3.
+
+       * lisp/dgnushack.el (TopLevel): Bind `:file' for old Emacsen.
+
+       * texi/{gnus.texi,gnus-ja.texi,ChangeLog}: Sync up with Pterodactyl
+       Gnus v0.86.
+       * lisp/{nnmail.el,nnheader.el,nndoc.el,mml.el,mm-view.el,
+       mm-decode.el,mm-bodies.el,message.el,mail-source.el,lpath.el,
+       gnus.el,gnus-xmas.el,gnus-uu.el,gnus-util.el,gnus-sum.el,
+       gnus-start.el,gnus-score.el,gnus-range.el,gnus-msg.el,
+       gnus-mailcap.el,gnus-group.el,gnus-cus.el,gnus-cite.el,
+       gnus-cache.el,gnus-art.el,gnus-agent.el,ChangeLog}: Ditto.
+
+       * etc/gnus/x-splash: New file copied from pgnus 0.86.
+
+1999-06-12  Daiki Ueno        <daiki@kiss.kake.info.waseda.ac.jp>
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Bind
+       `inhibit-read-only' to t during modifying the destination buffer.
+
+1999-06-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * sample.lpath.el: New file. It is supposed to be used for telling
+       old Emacsen where EMU, APEL or CUSTOM packages have already
+       installed.
+
+       * lisp/score-mode.el (score-mode-coding-system): Default to
+       `*ctext*' under Mule 2.
+
+       * lisp/nnmail.el (nnmail-save-active): Bind `output-coding-system'
+       to the value of `nnmail-active-file-coding-system'.
+
+       * lisp/message.el (message-set-auto-save-file-name): Use
+       `set-file-coding-system' statically under Mule 2.
+       (message-do-fcc): Bind `output-coding-system' to `raw-text'.
+       (message-draft-coding-system): Default to `*junet*' under Mule 2.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-util.el (gnus-point-at-eol): Defun statically for the
+       various Emacsen.
+       (gnus-point-at-bol): Ditto.
+       (TopLevel): Require `static'.
+
+       * lisp/gnus-start.el (gnus-startup-file-coding-system): Default to
+       `*ctext*' under Mule 2.
+
+       * lisp/gnus-msg.el (gnus-inews-do-gcc): Bind `output-coding-system'
+       to `raw-text'.
+
+       * lisp/gnus-ems.el (language-info-alist): Defvar-maybe for old
+       Emacsen.
+       (current-language-environment): Ditto.
+       (set-language-info): Defun-maybe for old Emacsen.
+       (get-language-info): Ditto.
+       (assoc-ignore-case): Ditto.
+
+       * lisp/gnus-cite.el (gnus-cite-parse): Bind `mc-flag' to nil.
+
+       * lisp/dgnushack.el (TopLevel): Define some unknown functions for
+       avoiding byte compile warnings.
+       (TopLevel): Require `emu' for picking up some macros, bind some
+       colon keywords, bind functions defined by `defun-maybe', bind
+       defcustom'ed variables and optimize byte code for `char-after' and
+       `char-before' for old Emacsen.
+       (TopLevel): Attempt to load ~/.lpath.el.
+
+       * configure: Regenerate by autoconf 2.14.1.
+
+1999-06-11  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-art.el (gnus-article-display-x-face-with-x-face-mule):
+       Warn if it is used with X-Face-Mule 0.25 or later.  Note that it
+       should be abolished in the future.
+
+1999-06-08  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version): Modify for SEMI 1.13, FLIM 1.13.
+       (gnus-revision-number): Fresh start from 00.
+       (gnus-version-number): Update to 6.11.0.
+       (gnus-product-name): Rename to ET-gnus. E is short for Experimental.
+
+       * lisp/gnus-sum.el (gnus-summary-reselect-current-group): Rescan
+       the current newsgroup before exiting.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Change
+       representation-type of `mime-message-structure'.
+
+       * ChangeLog: New file.
+       * ChangeLog.1: Renamed from ChangeLog.
+
+1999-06-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * lisp/gnus-score.el (gnus-header-index): Use
+       `luna-class-slot-index' and `luna-find-class' to get index number
+       for an entity.
+
+1999-05-31  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * lisp/nnheader.el: Require `mmgnus'.
+       (mail-header-subject): Now an alias for
+       `mime-gnus-entity-subject-internal'.
+       (mail-header-set-subject): Now an alias for
+       `mime-gnus-entity-set-subject-internal)'.
+       (mail-header-from): Now an alias for
+       `mime-gnus-entity-from-internal'.
+       (mail-header-set-from): Now an alias for
+       `mime-gnus-entity-set-from-internal'.
+       (mail-header-date): Now an alias for
+       `mime-gnus-entity-date-internal'.
+       (mail-header-set-date): Now an alias for
+       `mime-gnus-entity-set-date-internal'.
+       (mail-header-message-id): Now an alias for
+       `mime-gnus-entity-id-internal'.
+       (mail-header-id): Likewise.
+       (mail-header-set-message-id): Now an alias for
+       `mime-gnus-entity-set-id-internal'.
+       (mail-header-set-id): Likewise.
+       (mail-header-references): Now an alias for
+       `mime-gnus-entity-references-internal'.
+       (mail-header-set-references): Now an alias for
+       `mime-gnus-entity-set-references-internal'.
+       (mail-header-chars): Now an alias for
+       `mime-gnus-entity-chars-internal.
+       (mail-header-set-chars): Now an alias for
+       `mime-gnus-entity-set-chars-internal.
+       (mail-header-lines): Now an alias for
+       `mime-gnus-entity-lines-internal'.
+       (mail-header-set-lines): Now an alias for
+       `mime-gnus-entity-set-lines-internal'.
+       (mail-header-xref): Now an alias for
+       `mime-gnus-entity-xref-internal'.
+       (mail-header-set-xref): Now an alias for
+       `mime-gnus-entity-set-xref-internal'.
+       (make-full-mail-header): New implementation [use
+       `luna-make-entity'].
+       (make-full-mail-header-from-decoded-header): Likewise.
+
+       * lisp/mmgnus.el (mime-gnus-entity): New definition of luna-class.
+       (mime-entity-buffer): Abolished.
+       (initialize-instance): New method.
+
+See ChangeLog.1 for earlier changes.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/ChangeLog.3 b/ChangeLog.3
new file mode 100644 (file)
index 0000000..d661655
--- /dev/null
@@ -0,0 +1,2920 @@
+2000-12-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (TopLevel): Defalias `coding-system-category'
+       to `get-code-mnemonic' for Mule.
+       (TopLevel): Make codesys `euc-japan' and `shift_jis' for Mule.
+       (nnshimbun-type-definition): Use `static-if' to determine codesys.
+       (TopLevel): Require `static'.
+
+2000-12-06  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-retrieve-url): coding detection is
+       improved.
+       (nnshimbun-meta-content-type-charset-regexp): New constant.
+       (nnshimbun-meta-charset-content-type-regexp): Ditto.
+
+2000-12-03  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * texi/gnus-ja.texi: Fixes for the last modification.
+
+2000-12-02  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * texi/gnus-ja.texi: Translate description about
+       `nnmail-split-fancy-with-parent'.
+
+       * texi/message-ja.texi: Use two lines for direntry.
+
+2000-12-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Attempt to add another FLIM path to `load-path'
+       if the module `mel' does not found.  This procedure may be needed
+       when recent FLIM 1.14 is used under old Emacsen.
+
+2000-11-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 08.
+
+       * lisp/message.el (message-send-mail-with-smtp): Leave the error
+       handling in `smtp-send-buffer's own care.
+
+2000-11-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus.el: Add autoloads for x-face-e21.
+
+       * lisp/gnus-sum.el (gnus-summary-search-article-position-point):
+       Search for `x-face-image' as well as `x-face-mule-bitmap-image'.
+
+       * lisp/gnus-art.el (gnus-article-x-face-command): Default to
+       `x-face-decode-message-header' when Emacs 21 is running and
+       x-face-e21 is installed.
+
+2000-11-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send-mail-with-smtp): Use
+       `smtp-send-buffer' if it exists instead of `smtp-via-smtp'.
+
+       * lisp/dgnushack.el (describe-key-briefly): New compiler macro for
+       old Emacsen.
+
+2000-11-17  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnheader.el (nnheader-header-value): Save point.
+
+2000-11-16  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * texi/gnus-ja.texi (Drafts): Fix typo.
+
+2000-11-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-verify-x-pgp-sig): Autoload "mm-uu".
+       (gnus-treat-x-pgp-sig): Default to nil.
+
+2000-11-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * Mule23@1934.en, Mule23@1934.ja, sample.lpath.el: Upgrade.
+
+       * configure: Regenerate.
+       * aclocal.m4 (AC_PATH_PACKAGEDIR): No need to quote a string for
+       `AC_MSG_RESULT'.
+       (AC_CHECK_W3): Ignore cache; no need to quote a string for
+       `AC_MSG_RESULT'.
+       (AC_CHECK_EMACS_FLAVOR): Ignore cache.
+       (AC_CHECK_EMACS): Ignore cache.
+       (AC_DEFINE_GNUS_PRODUCT_NAME): Cache.
+
+2000-11-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * configure: Regenerate.
+
+       * aclocal.m4 (AC_CHECK_W3): Substitute `W3' with empty string
+       instead of "no" if it is not acceptable.
+
+       * lisp/dgnushack.el: Load dgnuspath.el and ~/.lpath.el just before
+       path-util is loaded.
+       (dgnushack-compile): Show `load-path'.
+       (dgnushack-w3-dir): Ignore the env var W3DIR if it is empty.
+
+       * lisp/lpath.el: Move out `load-path' modification for APEL, FLIM
+       and SEMI to dgnushack.el.
+       * lisp/dgnushack.el: Move here.
+
+       * lisp/lpath.el (md5): Don't bind.
+       (url-insert-file-contents): Fbind for FSF Emacsen.
+
+2000-11-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/Makefile.in (install-ja-info): Specify `EMACS' and
+       `infodir'.
+       (install-info): Ditto.
+       (install-ja): Ditto.
+
+       * lisp/lpath.el (md5): Fbind using `maybe-fbind'.
+
+       * lisp/dgnushack.el (dgnushack-compose-package): Remove function.
+       (dgnushack-install-package-info-ja): Remove function.
+       (dgnushack-install-package-info): Remove function.
+       (dgnushack-install-package-lick): Remove function.
+       (dgnushack-install-package-pkginfo): Remove function.
+       (dgnushack-install-package-info-files): Remove function.
+       (dgnushack-install-package-manifest): New function.
+       (dgnushack-remove-extra-files-in-package): New function.
+       (dgnushack-gnus-product-name): Remove function.
+       (dgnushack-examine-package-dir): Remove function.
+       (dgnushack-exporting-files): Rename from `dgnushack-exported-files'.
+       (dgnushack-unexporting-files): Rename from
+       `dgnushack-unexported-files'; attempt to fix `load-path' for W3 and
+       retry to load `w3-forms' if it is failed.
+       (dgnushack-w3-dir): New variable.
+
+       * lisp/Makefile.in (remove-extra-files-in-package): New target.
+       (install-package-manifest): New target.
+       (install-package-info-ja): Remove target.
+       (install-package-info): Remove target.
+       (install-package-lick): Remove target.
+       (install-lisp): New target detached from `install'.
+       (install): Call `clever' and `install-lisp'.
+       (EXPORTING_FILES, GNUS_PRODUCT_NAME): New variables.
+
+       * configure: Regenerate.
+
+       * aclocal.m4 (AC_PATH_PACKAGEDIR): Examine `PACKAGEDIR' if it is
+       not specified under XEmacs.
+       (AC_EXAMINE_PACKAGEDIR): New function.
+       (AC_PATH_LISPDIR): Don't say annotations about install-package if
+       FSFmacs is used.
+       (AC_DEFINE_GNUS_PRODUCT_NAME): Add substitution for
+       `GNUS_PRODUCT_NAME'.
+
+       * Makefile.in (remove-extra-files-in-package): New target.
+       (install-package-manifest): New target.
+       (install-package-info-ja): Examine `PACKAGEDIR' if it is not
+       specified; call install-ja-info in texi/Makefile.
+       (install-package-info): Examine `PACKAGEDIR' if it is not
+       specified; call install-info in texi/Makefile.
+       (install-package-lisp): Rename from `install-package-lick'; examine
+       `PACKAGEDIR' if it is not specified; call `install-lisp' in
+       lisp/Makefile.
+       (install-package-ja): Call `xlick', `compose-package',
+       `remove-extra-files-in-package', `install-package-lisp',
+       `install-package-info', `install-package-info-ja' and
+       `install-package-manifest'.
+       (install-package): Call `xlick', `compose-package',
+       `remove-extra-files-in-package', `install-package-lisp',
+       `install-package-info' and `install-package-manifest'.
+       (install-info-ja, install-info): Specify `infodir'.
+       (EXAMINE_PACKAGEDIR, GNUS_PRODUCT_NAME, infodir): New variables.
+
+2000-11-07  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * texi/gnus-ja.texi: Do not use characters other than ascii ones
+       for direntries.
+       * texi/message-ja.texi: Ditto.
+
+2000-11-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/Makefile.in (install): Don't check for the file names.
+
+2000-11-04  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * lisp/gnus-topic.el (gnus-group-topic-map): Define "T" prefix
+       command in `gnus-topic-mode-map' instead of `gnus-group-mode-map'.
+
+2000-10-25  Katsuhiro Hermit Endo  <hermit@tomato.saino.ne.jp>
+
+       * lisp/gnus-topic.el (gnus-topic-rename): Use current topic as
+       initial value for read-string.
+
+2000-11-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/Makefile.in (install): Use the lisp function
+       `dgnushack-exported-files'.
+
+       * lisp/nnmail.el (nnmail-pathname-coding-system): Default to
+       `binary'.
+       * lisp/nnheader.el (nnheader-pathname-coding-system): Ditto.
+
+       * lisp/message.el (message-get-reply-headers): Remove useless
+       `concat'.
+
+       * lisp/md5.el: Restore the file.
+
+       * lisp/dgnushack.el (dgnushack-compile): Refer to the constant
+       `dgnushack-exported-files'.
+       (dgnushack-exported-files): New function.
+       (dgnushack-exported-files): New constant.
+       (dgnushack-unexported-files): Add some files.
+       (dgnushack-tool-files): Remove, merge it into
+       `dgnushack-unexported-files'.
+
+       * lisp/base64.el: New file -- base64 encoding functions using MEL.
+
+2000-11-05  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * lisp/smiley.el (smiley-deformed-regexp-alist): Modify regexp for
+       the winking face.
+
+2000-11-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-make-manifest): Fix info directory.
+
+2000-11-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * Makefile.in (install-package-ja): Compile and install lisp files
+       first.
+       (install-package): Ditto.
+       (compose-package, install-package-info-ja, install-package-info,
+       install-package-lick): New sub targets.
+
+       * lisp/Makefile.in (install-package-info-ja, install-package-info,
+       install-package-lick): New targets.
+       (compose-package): Rename from `package'.
+       (install-package): Remove.
+
+       * lisp/dgnushack.el (dgnushack-install-package-info-ja,
+       dgnushack-install-package-info, dgnushack-install-package-lick,
+       dgnushack-install-package-pkginfo,
+       dgnushack-install-package-info-files, dgnushack-make-manifest,
+       dgnushack-gnus-product-name, dgnushack-examine-package-dir,
+       dgnushack-make-autoloads): New functions.
+       (dgnushack-install-package): Remove.
+       (dgnushack-compose-package): Rename from `dgnushack-make-package'.
+       (dgnushack-info-file-regexp-ja, dgnushack-info-file-regexp-en):
+       Split from `dgnushack-info-file-regexp'.
+       (dgnushack-texi-file-regexp): Remove.
+
+2000-11-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Remove @ignore'd areas
+       before processing.
+
+2000-11-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus.el (gnus-product-variable-file-list): Check for
+       `emacs-version' in the file "cache" as well.
+       * lisp/gnus-start.el (gnus-product-read-variable-file-1): Make it
+       talkative.
+
+2000-10-31  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Bind `:key-type' and `:value-type' for old
+       Emacsen.
+
+2000-10-31  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (texinfo-format-direntry): Fixed broken
+       direntry generate probrem.
+       (Advised by Tetsuo Tsukamoto <czkmt@remus.dti.ne.jp>)
+
+2000-10-31  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-insert-line): Work with quoted
+       double-quote characters.
+       (gnus-summary-prepare-threads): Ditto.
+
+2000-10-30  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (ptexinfmt-disable-broken-notice-flag): Renamed
+       from `ptexinfmt-disable-broken-notice'.
+
+2000-10-27  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (texinfo-format-printindex): Mule for Windows
+       detection fixed.
+
+2000-10-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-group-startup-message): Rewrite for Emacs 21.
+       * lisp/lpath.el: Fbind `propertize'.
+
+2000-10-22  Katsuhiro Hermit Endo <hermit@tomato.saino.ne.jp>
+
+       * texi/gnus-ja.texi (Changing Servers): Fix typo.
+
+2000-10-19  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-netbsd-get-headers): Fix regular
+       expression to extract xover urls.
+
+2000-10-12  Jesper Harder <jesper_harder@hotmail.com>
+
+       * make.bat: Makes it possible to generate the Info files on
+       windows again.
+
+2000-10-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * Makefile.in (info-ja, xinfo-ja): No need to use `MAKEINFO=no'.
+       (install-info-ja, install-info, install-lisp, install-ja): New
+       targets (possibly for FSF Emacsen).
+
+       * texi/Makefile.in (install-ja-info, install-info, install-ja,
+       %-ja.info, %-ja): New targets.
+
+       * texi/message-ja.texi (direntry): Replace "message" with
+       "message-ja".
+
+2000-10-08  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-type-definition): Fix regular
+       expression to extract article body from `ZDNet'.
+
+2000-10-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/imap.el: Require `base64' instead of to autoload it.
+
+2000-10-05  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Don't use
+       `gnus-point-at-eol'.
+       * lisp/gnus.el (gnus-group-startup-message): Ditto.
+
+       * lisp/gnus-ems.el (gnus-ems-redefine): Revive annulling of
+       `gnus-summary-set-display-table'.
+
+2000-10-04  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/gnus-sum.el (gnus-build-sparse-threads): Use
+       `make-full-mail-header-from-decoded-header' instead of
+       `make-full-mail-header'.
+
+2000-10-03  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-get-new-news): Update modeline
+       using `gnus-agent-toggle-plugged' if agent is activated.
+       * lisp/gnus-agent.el (gnus-group-get-new-news): Don't advise it,
+       merge it into gnus-group.el instead.
+
+       * lisp/gnus-offline.el (gnus-offline-after-jobs-done): Use `ding'
+       with `play-sound-file' for XEmacs statically.
+
+       * lisp/gnus-art.el (gnus-article-add-button): Quote
+       `:button-keymap' for Mule 2.3 but it won't work.
+
+2000-09-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-ignored-supersedes-headers): Synch with
+       Gnus.
+
+2000-09-27  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * list/ptexinfmt.el (texinfo-multitable-widths): Fix
+       broken-facility probrem when use multitable unsupported
+       texinfmt.el.
+
+2000-09-26  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (texinfo-format-printindex): Use (featurep
+       'meadow) instead of `texinfmt-version'.
+
+2000-09-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 05.
+
+       * texi/gnus-faq-ja.texi, lisp/gnus.el, README.semi.ja, README.semi,
+       README: Replace "<semi-gnus-*@meadow.scphys.kyoto-u.ac.jp>" with
+       "<semi-gnus-*@meadowy.org>".
+
+2000-09-22  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (texinfo-format-printindex): Add
+       broken-facility check, for Mule for Windows.
+       (texinfo-format-printindex): New function.
+
+2000-09-19  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Encode bitmap
+       smileys to ordinary text before removing any text properties.  It
+       is synchronized with the latest smiley-mule.el.
+
+2000-09-19  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-type-definition): Follow URL change
+       of `ZDNet'.
+
+2000-09-15   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-art.el: Always require `wid-edit'.
+
+2000-09-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-compile): Don't compile gnus-ml.el
+       when FSFmacs is running.
+
+       * lisp/gnus-ml.el: Bind some undeclared variables.
+
+       * lisp/gnus-art.el (gnus-article-add-button): Add widget button.
+       (gnus-article-display-mime-message): Don't set
+       `mime-button-mother-dispatcher'.
+
+       * lisp/message.el: Require `reporter' for the function
+       `define-mail-user-agent' when Mule 2.3 is running.
+
+2000-09-07  Tadashi Watanabe  <watanabe@sigmaitec.co.jp>
+
+       * lisp/smiley.el (smiley-buffer, smiley-create-glyph): Work with
+       GTK XEmacs as well.
+
+2000-09-06  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-header-xref): New function.
+       (nnshimbun-insert-header): Use `nnshimbun-header-xref', instead of
+       `mail-header-xref'.
+       (nnshimbun-make-mhonarc-contents): Took a measure against
+       unexpected TAB characters.
+
+2000-09-05  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: Add `netbsd' support.
+       (nnshimbun-nov-fix-header): Change a form storing Message-Id.
+       (nnshimbun-search-id): Ditto.
+       (nnshimbun-make-mhonarc-contents): Use optional header
+       information.
+
+2000-09-05   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/pop3.el (pop3-quit): Don't clear `pop3-uidl-obarray'.
+       (pop3-save-uidls): Clear `pop3-uidl-obarray' here.
+
+2000-09-04   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/mail-source.el (pop3-leave-mail-on-server): Declare.
+       (mail-source-keyword-map): New keyword `:leave' for pop.
+       (mail-source-fetch-pop): Refer it.
+
+       * lisp/pop3.el (pop3-ssl-program-name): New variable.
+
+2000-08-31  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * lisp/ptexinfmt.el (texinfo-multitable-widths,
+       texinfo-multitable-item): Apply char-width probrem fix patch
+       (by KOIE Hidetaka <koie@skipjack.koie.org>).
+       Newsgroups: fj.editor.emacs
+       Message-ID: <5dzom3nxq7.fsf@skipjack.koie.org>
+
+       * lisp/ptexinfmt.el (ptexinfmt-disable-broken-notice): New
+       variable.
+
+2000-08-29  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-zdnet-get-headers): Follow changes
+       of ZDNet.
+
+2000-08-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 04.
+
+2000-08-25  Yagi Tatsuya  <yagi@is.titech.ac.jp>
+            Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nntp.el (nntp-list-options, nntp-options-subscribe,
+       nntp-options-not-subscribe): New server variables.
+       (nntp-request-list): Use them.
+       * texi/gnus.texi, texi/gnus-ja.texi: Update for them.
+
+2000-08-23  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-group-startup-message): Use `image-size' to
+       simplify the program.
+
+       * lisp/gnus-group.el (gnus-group-rename-group): Inhibit renaming of
+       zombie or killed groups.
+
+2000-08-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-replace-chars-in-string): Use
+       `static-if'.
+       * lisp/message.el (message-replace-chars-in-string): Ditto.
+
+2000-08-19  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-type-definition): Follow changes of
+       ZDNet.
+       (nnshimbun-make-text-or-html-contents): Ditto.
+       (nnshimbun-make-html-contents): Ditto.
+
+2000-08-18  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+            Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnshimbun.el: Add `mew' and `xemacs' support.
+
+2000-08-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Require `ptexinfmt'
+       instead of `texinfmt'.
+       (dgnushack-install-package): Don't install ptexinfmt.el.
+       (dgnushack-make-package): Don't include ptexinfmt.el in MANIFEST.
+       (dgnushack-compile): Don't compile dgnushack.el nor ptexinfmt.el.
+       (dgnushack-unexported-files, dgnushack-tool-files): New constants.
+
+       * lisp/Makefile.in (install-package): No need to remove
+       dgnushack.elc.
+       (install): Don't install ptexinfmt.el; no need to remove
+       dgnushack.elc.
+
+       * lisp/ptexinfmt.el: New file imported from Wanderlust.
+
+2000-08-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nntp.el (nntp-open-telnet): Wait for the telnet prompt
+       before sending a command; allow the rtelnet prompt as well.
+
+       * lisp/message.el (message-make-forward-subject): Remove garbage
+       line.
+
+2000-08-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * configure: Regenerate.
+       * aclocal.m4 (AC_CHECK_EMACS): Unset `EMACS' environment variable
+       if it is `t'.
+
+2000-07-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+       * configure: Regenerate with autoconf v2.14.1.
+
+       * configure.in: Rewrite for using new macros in aclocal.m4.
+
+       * aclocal.m4: (AC_ADD_LOAD_PATH, AC_PATH_PACKAGEDIR,
+       AC_CHECK_EMACS, AC_DEFINE_GNUS_PRODUCT_NAME): New macros.
+       (AC_PATH_LISPDIR): Set `lispdir' to ".../site-lisp/t-gnus" by
+       default.
+       (AC_CHECK_EMACS_FLAVOR): Rename from `AC_XEMACS_P'; check for
+       `MULE' as well.
+       (AM_PATH_LISPDIR): Remove.
+
+       * acinclude.m4: Remove.
+
+       * lisp/dgnushack.el: Don't add "/usr/share/emacs/site-lisp" to
+       `load-path'.
+
+       * lisp/gnus-ems.el (gnus-ems-redefine): Defalias
+       `gnus-summary-set-display-table' to `(lambda ())' instead of
+       `ignore' (don't synch. with Gnus).
+
+2000-07-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Use
+       mime-entity-fetch-field instead of mail-header-from.
+
+2000-07-18   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Don't refer
+       gnus-original-article-buffer.
+       (gnus-bbdb-insinuate): Set gnus-article-display-hook instead of
+       gnus-article-prepare-hook.
+       (gnus-bbdb/extract-field-value): Use mime-entity-fetch-field
+       instead of mail-fetch-field.
+       (gnus-bbdb/extract-field-value-init): Just return extractor.
+
+2000-07-15   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * README-gnus-bbdb.{ja|en}: Add example setting about
+       gnus-bbdb-insinuate-message.
+       (bbdb-auto-notes-hook): Don't use pop.
+
+       * lisp/gnus-bbdb.el: Check defvaralias when compiling.
+
+       * lisp/gnus-art.el (gnus-article-setup-buffer): Set
+       gnus-original-article-buffer as unibyte.
+       (gnus-request-article-this-buffer): Ditto.
+
+       * lisp/nnimap.el (nnimap-callback): Don't use nnimap-demule.
+       (nnimap-request-article-part): Ditto.
+
+       * lisp/imap.el (imap-open): Set process buffer as unibyte.
+
+2000-07-13 10:09:52  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * acinclude.m4 (AC_CHECK_W3): Fix typo.
+
+2000-07-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * configure: Regenerate with autoconf v2.14.1.
+       * aclocal.m4: Regenerate with aclocal v1.4.
+
+       * configure.in: Don't call `AC_CHECK_PROG' for `EMACS'.
+
+       * acinclude.m4: Merge ShengHuo's changes.
+       (AC_CHECK_W3): Use `quote' instead of '.
+       (AC_XEMACS_P): Don't modify the value of `XEMACS'.
+       (AC_EMACS_LISP): Safely quote the elisp form.
+
+2000-07-12 15:47:06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * aclocal.m4: Stolen macros from w3.
+       * configure.in: Use them.
+       * configure: Generate it.
+
+2000-07-03  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (T-gnus): Update to 6.14.5.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * lisp/{webmail.el,rfc2047.el,qp.el,pop3.el,nnwarchive.el,
+       nnsoup.el,nnslashdot.el,nnml.el,nnmh.el,nnmbox.el,nnmail.el,
+       nnimap.el,nnheader.el,nnfolder.el,nndraft.el,nndoc.el,mml.el,
+       mm-view.el,mm-uu.el,mm-util.el,mm-decode.el,mm-bodies.el,
+       message.el,mail-source.el,lpath.el,imap.el,gnus.el,gnus-uu.el,
+       gnus-util.el,gnus-topic.el,gnus-sum.el,gnus-start.el,gnus-srvr.el,
+       gnus-soup.el,gnus-score.el,gnus-msg.el,gnus-mailcap.el,
+       gnus-group.el,gnus-ems.el,gnus-demon.el,gnus-cus.el,gnus-art.el,
+       gnus-agent.el,ChangeLog}: Sync up with Gnus v5.8.7.
+
+       * texi/{message.texi,gnus.texi,gnus-ja.texi,ChangeLog}: Sync up
+       with Gnus v5.8.7.
+
+       * contrib/rfc2015.el: New file.
+
+2000-06-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-sum.el (gnus-mime-extract-message/rfc822): Use
+       `mime-insert-entity-content' instead of obsolete functions.
+
+2000-06-13  Hirokazu FUKUI  <hfukui@sannet.ne.jp>
+
+       * lisp/gnus-bbdb.el(gnus-bbdb/update-record): Fix to fetch last
+       mail field.
+
+2000-06-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-news-group-p): Sync with Gnus.
+       (gnus-select-method): Remove "*" from doc string.
+       (gnus-group-startup-message): Use `dino' colors.
+
+2000-06-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-fix-before-sending): Expose all
+       invisible text with the property `message-invisible'; don't expose
+       invisible X-Face fields; widen at first.
+       (message-invisible-region): New function, substitute for
+       `invisible-region'.
+       (message-send): Call `message-fix-before-sending' after evaluating
+       `message-send-hook'.
+       (message-check-ignore-invisible-x-face-field): Remove.  You can use
+       (add-hook 'message-send-hook 'x-face-xmas-remove-x-face-glyph)
+       instead.
+
+2000-06-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-save-drafts): Rewrite.
+
+       * lisp/nnheader.el (nnheader-text-coding-system-for-write,
+       nnheader-text-coding-system): New variables, substitutes for
+       `mm-text-coding-system-for-write' or `mm-text-coding-system'.
+
+       * lisp/nnmbox.el (nnmbox-active-file-coding-system,
+       nnmbox-file-coding-system): Use `nnheader-text-coding-system'.
+       * lisp/nnmail.el (nnmail-incoming-coding-system): Ditto.
+       * lisp/nnfolder.el (nnfolder-file-coding-system): Ditto.
+       (nnfolder-active-file-coding-system): Ditto.
+
+       * lisp/mail-source.el (mail-source-text-coding-system): Remove.
+       (TopLevel): require `nnheader'.
+
+       * lisp/nndraft.el (nndraft-request-article): Bind coding system to
+       `nnheader-text-coding-system'.
+       (nndraft-request-replace-article): Ditto.
+       * lisp/mail-source.el (mail-source-fetch-maildir): Ditto.
+       * lisp/gnus-uu.el (gnus-uu-save-article): Ditto.
+       * lisp/gnus-util.el (gnus-output-to-mail, gnus-output-to-rmail):
+       Ditto.
+       * lisp/gnus-soup.el (gnus-soup-write-prefixes): Ditto.
+
+       * lisp/gnus-util.el (gnus-write-buffer): Bind
+       `file-name-coding-system' to `nnmail-pathname-coding-system'.
+       * lisp/gnus-start.el (gnus-slave-save-newsrc): Bind coding system
+       to `gnus-startup-file-coding-system'.
+
+2000-06-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+       * lisp/message.el (message-fix-before-sending): Don't check for
+       invisible X-Face fields if
+       `message-check-ignore-invisible-x-face-field' is non-nil.
+       (message-send): Call `message-fix-before-sending' before encoding.
+       (message-check-ignore-invisible-x-face-field): New user option.
+
+2000-06-01  KANEMATSU Daiji <kanematu@sra.co.jp>
+
+       * texi/gnus-ja.texi (gnus-summary-hide-all-threads): Fix typo.
+
+2000-05-28  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * nnshimbun.el (nnshimbun-request-article-1): Fix to insert x-face
+       unless SERVER.
+       (nnshimbun-asahi-get-headers): Fix for subjects which contain ^M.
+
+2000-05-26  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-write-nov): New function.
+       (nnshimbun-close-group): Call nnshimbun-write-nov.
+       (nnshimbun-generate-nov-database): Ditto.
+       (nnshimbun-generate-nov-for-each-group): Fix bug which occur new
+       entries add NOV database.
+       (nnshimbun-generate-nov-for-all-groups): Ditto.
+       (nnshimbun-search-id): Add argument to return header, and modify
+       for search of original message id.
+       (nnshimbun-nov-fix-header): New function.
+       (nnshimbun-make-date-string): Fix for a two-digit year.
+
+2000-05-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-make-html-contents): Show X-Face.
+       (nnshimbun-make-text-or-html-contents): Ditto.
+       (nnshimbun-request-article-1): Ditto.
+       (nnshimbun-x-face-alist): New variable.
+
+2000-05-25  Tanaka Akira      <akr@m17n.org>
+
+       * README.semi, README.semi.ja: Update for CVS via SSH.
+
+2000-05-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/gnus-ja.texi: Change coding-system to `iso-2022-7bit-ss2'.
+       * texi/TRANSLATION.ja: Replace CRLF with LF.
+
+2000-05-25  Keiichi Suzuki  <keiichi@mdcnet.co.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-fill-line): Use
+       `nnshimbun-fill-column' instead of `fill-column'.
+
+2000-05-25  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: Clean up codes.
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): Follow
+       changes in nnshimbun.el.
+       * texi/gnus-ja.texi (nnshimbun): Ditto.
+
+2000-05-24  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: Add `ZDNet Japan', `Yomiuri', and `Wired
+       News' support.
+       (nnshimbun-regexp-opt): New function.
+       (nnshimbun-wired-get-all-headers): Replace regexp-opt with
+       nnshimbun-regexp-opt.
+
+2000-05-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): Complete
+       completions.
+
+2000-05-24  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: Add `CNET Japan' support.
+       (nnshimbun-make-date-string): New function.
+       (nnshimbun-asahi-get-headers): Use nnshimbun-make-date-string.
+       (nnshimbun-sponichi-get-headers): Ditto.
+
+2000-05-24  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-retrieve-url): Add argument to
+       ignore w3's cache.
+
+2000-05-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): Add
+       completion to the shimbun address; delete empty strings from
+       `gnus-group-shimbun-type-history' and
+       `gnus-group-shimbun-address-history'.
+
+       * lisp/nnshimbun.el (nnshimbun-asahi-get-headers): Don't use
+       `timezone'.
+       (nnshimbun-type-definition): Add address.
+
+2000-05-23  Tatsuya Ichikawa <ichikawa@erc.epson.com>
+
+       * lisp/nnshimbun.el: Add `sponichi' support.
+
+2000-05-23  KOSEKI Yoshinori  <kose@wizard.tamra.co.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-mime-encode-string): Fix wrong
+       close brackets.
+
+2000-05-23  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: Change coding-system.
+
+2000-05-21  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * texi/gnus-ja.texi (nnshimbun): Add description.
+
+2000-05-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Fix last change.
+
+2000-05-21  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el: New backend.
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): New command.
+
+2000-05-17  Kenichi OKADA <okada@opaopa.org>
+
+       * lisp/imap.el (imap-digest-md5-auth): Rewrite for the use of
+       `sasl-digest-md5-digest-response' instead of
+       `digest-md5-digest-response'.
+       (TopLevel): Require `sasl' when compiling instead of `digest-md5';
+       don't autoload "digest-md5".
+
+2000-05-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nndraft.el (nndraft-request-replace-article): Replace
+       `mm-text-coding-system' with `mail-source-text-coding-system';
+       Replace `mm-auto-save-coding-system' with
+       `message-draft-coding-system'.
+
+       * lisp/mail-source.el (mail-source-fetch-maildir): Replace
+       `mm-text-coding-system' with `mail-source-text-coding-system'.
+       (mail-source-text-coding-system): New variable.
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Use
+       `output-coding-system' instead of `coding-system-for-write' when
+       old Mule is used.
+
+2000-05-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-forward) Replace the use of `eolp' with
+       `bolp' for detecting the start of the line.
+       (message-indent-citation): Ditto.
+
+2000-05-10   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/pop-up-bbdb-buffer): Don't bind
+       `bbdb-use-pop-up' while executing `bbdb-pop-up-bbdb-buffer'.
+
+2000-05-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-debug): Break MIME tags from the snoopies.
+       (gnus-bug): Insert text/plain tag at the end of the buffer.
+
+2000-05-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+2000-05-10  Keiichi Suzuki  <keiichi@mdcnet.co.jp>
+
+       * lisp/message.el (message-list-references): Do not insert
+       duplicate Message-Id, when specified
+       `message-list-references-add-position'.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/split-mail): Support group address.
+       (gnus-bbdb/insert-address-regexp): New function.
+
+2000-05-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-debug): Add "nntp.el" and `defvoo'.
+
+2000-05-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (T-gnus): Update to 6.14.4.
+
+       * README.T-gnus: Update.
+
+       * lisp/{webmail.el,rfc2047.el,nnmbox.el,nndoc.el,mml.el,mm-view.el,
+       mm-partial.el,mm-decode.el,mm-bodies.el,message.el,lpath.el,
+       gnus.el,gnus-vers.el,gnus-util.el,gnus-start.el,gnus-score.el,
+       gnus-msg.el,gnus-mailcap.el,gnus-ems.el,gnus-draft.el,gnus-art.el,
+       ChangeLog}: Sync up with Gnus v5.8.6.
+       * texi/{postamble.tex,message.texi,message-ja.texi,gnusref.tex,
+       gnus.texi,gnus-ja.texi,emacs-mime.texi,Makefile.in,ChangeLog}: Sync
+       up with Gnus v5.8.6.
+
+2000-04-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/gnus.texi, texi/gnus-ja.texi, texi/gnus-faq-ja.texi, README:
+       You might be able to use T-gnus with the versions of XEmacs prior
+       to 21.1.1.
+
+       * contrib/timer.el: New file. Imported from fsf-compat-1.07-pkg.
+
+2000-04-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/mm-view.el (gnus-article-mime-handles): Don't bind it.
+
+       * lisp/gnus-sum.el (gnus-article-mime-handles): Restore from Gnus.
+       (gnus-article-decoded-p): Ditto.
+
+       * lisp/gnus-art.el (gnus-article-mime-handles): Don't bind it.
+       (gnus-article-decoded-p): Ditto.
+
+2000-04-25  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * lisp/dgnushack.el: Add code to avoid mule-2.3@19.34 failing to
+       make info from texi. Thanks to Hayashi-san.
+
+2000-04-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (union, member-if, mapcon, last): Remove
+       compiler macros.
+
+2000-04-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (T-gnus): Update to 6.14.3.
+
+       * README.T-gnus: Update.
+
+       * GNUS-NEWS: Sync up with Gnus v5.8.5.
+       * lisp/{webmail.el,utf7.el,time-date.el,smiley.el,rfc2047.el,
+       rfc1843.el,qp.el,pop3.el,parse-time.el,nnweb.el,nnwarchive.el,
+       nnvirtual.el,nnultimate.el,nntp.el,nnspool.el,nnslashdot.el,
+       nnml.el,nnmail.el,nnimap.el,nnheader.el,nnfolder.el,nndraft.el,
+       nndoc.el,nnagent.el,mml.el,mm-view.el,mm-uu.el,mm-util.el,
+       mm-encode.el,mm-decode.el,mm-bodies.el,message.el,mail-source.el,
+       mail-prsvr.el,mail-parse.el,lpath.el,imap.el,ietf-drums.el,gnus.el,
+       gnus-xmas.el,gnus-win.el,gnus-uu.el,gnus-util.el,gnus-topic.el,
+       gnus-sum.el,gnus-start.el,gnus-srvr.el,gnus-spec.el,gnus-score.el,
+       gnus-msg.el,gnus-move.el,gnus-mlspl.el,gnus-mh.el,gnus-mailcap.el,
+       gnus-logic.el,gnus-kill.el,gnus-int.el,gnus-group.el,gnus-ems.el,
+       gnus-eform.el,gnus-dup.el,gnus-draft.el,gnus-cite.el,gnus-cache.el,
+       gnus-bcklg.el,gnus-async.el,gnus-art.el,gnus-agent.el,
+       format-spec.el,flow-fill.el,fill-flowed.el,dgnushack.el,ChangeLog}:
+       Sync up with Gnus v5.8.5.
+       * texi/{refcard.tex,gnusref.tex,gnus.texi,gnus-ja.texi,
+       gnus-faq-ja.texi,Makefile.in,ChangeLog}: Sync up with Gnus v5.8.5.
+
+       * README: Requires XEmacs 21.1.1 and later.
+       * texi/{gnus.texi, gnus-faq-ja.texi}: Ditto.
+
+2000-04-20  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (T-gnus): Update to 6.14.2.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * lisp/{webmail.el,utf7.el,time-date.el,rfc2047.el,qp.el,pop3.el,
+       parse-time.el,nnweb.el,nnwarchive.el,nnultimate.el,nntp.el,
+       nnslashdot.el,nnml.el,nnmail.el,nnimap.el,nnheader.el,nnfolder.el,
+       mm-view.el,mm-util.el,mm-decode.el,mm-bodies.el,message.el,
+       mail-source.el,mail-parse.el,lpath.el,imap.el,ietf-drums.el,
+       gnus.el,gnus-win.el,gnus-vers.el,gnus-uu.el,gnus-topic.el,
+       gnus-sum.el,gnus-start.el,gnus-srvr.el,gnus-mailcap.el,
+       gnus-group.el,gnus-cus.el,gnus-art.el,gnus-agent.el,base64.el,
+       ChangeLog}: Sync up with Gnus v5.8.4.
+
+       * lisp/fill-flowed.el: New file.
+
+       * texi/{gnus.texi,gnus-ja.texi,ChangeLog}: Sync up with Gnus v5.8.4.
+
+       * contrib/{vcard.el,one-line-cookie.diff,README}: New files.
+
+2000-04-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-yank-message): Rewrite for the use
+       of the separated message frames; use `gnus-copy-article-buffer'.
+
+2000-04-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 18.
+       (gnus-extended-version): Use `gnus-product-name' and
+       `gnus-version-number' instead of the use of `product-string'.
+       (gnus-version-number): Exclude `gnus-revision-number'.
+       (Defining product): Include `gnus-revision-number'.
+       (TopLevel): Require `poe' for the function `butlast'.
+
+2000-04-13  Keiichi Suzuki  <keiichi@mdcnet.co.jp>
+
+       * lisp/gnus-spec.el (gnus-update-format): Fix a bug in last
+       modification.
+       (gnus-search-or-regist-spec): Change interface.
+
+2000-04-12  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-prev-page): Bind
+       `window-pixel-scroll-increment' to nil while scrolling for
+       canceling a backlash and a modeline erosion.  It may work under
+       XEmacs 21.2.20 and later.
+       (gnus-article-next-page): Ditto.
+
+2000-04-12  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 17.
+
+       * lisp/gnus-spec.el (gnus-format-specs-compiled): Fix doc string.
+
+2000-04-11  Keiichi Suzuki  <keiichi@mdcnet.co.jp>
+
+       * lisp/gnus-start.el (gnus-product-variable-touch): Support multiple
+       arguments.
+
+       * lisp/gnus-spec.el (gnus-search-or-regist-spec): New utility macro.
+       (gnus-update-format-specifications): Support new data structure of
+       `gnus-format-specs-compiled'.
+       (gnus-update-format-specification-1): Likewise.
+       (gnus-update-format): Support new data structure of
+       `gnus-format-specs'.
+       (gnus-format-specs): Modify data structure.
+
+2000-04-10   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/imap.el (imap-body-lines): Check Content-Type: of the
+       article case insensitively.
+
+2000-04-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-cite-original): Use "unknown sender" if
+       from field does not exist in the yanked article.
+
+2000-04-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-cite-original): Extract from field for
+       the simple citation line.
+
+2000-03-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnimap.el (nnimap-request-article-part): Returns nil if the
+       article does not exist.
+
+2000-03-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 16.
+
+       * lisp/nnweb.el (nnweb-fetch-url): Bind `input-coding-system' and
+       `output-coding-system' for Mule 2.3.
+       * lisp/mail-source.el (mail-source-fetch-imap): Ditto.
+       * lisp/imap.el (imap-ssl-open): Ditto.
+       * lisp/gnus-start.el (gnus-product-read-variable-file-1): Ditto.
+
+2000-03-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-re-read-newsrc-el-file): New function.
+       (gnus-read-newsrc-el-file): If it fails, attempt to re-read the
+       file using `gnus-re-read-newsrc-el-file'.  In that case, the
+       compiled format specs in the file which may be created by the other
+       Gnusae should be ignored.
+
+2000-03-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-product-variable-file-list): Use `*ctext*'
+       when Mule 2.3 is running.
+
+2000-03-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 15.
+
+       * lisp/gnus.el (gnus-continuum-version): Remove.
+       (gnus-product-variable-file-list): Use `product-version' instead of
+       the constant values.
+       (TopLevel): Don't autoload "gnus-msg" for the function
+       `gnus-extended-version'.
+       (gnus-version): Move to gnus-vers.el.
+       (gnus-version): Ditto.
+       (gnus-version-number): Ditto.
+       (gnus-product-name): Ditto.
+       (gnus-original-product-name): Ditto.
+       (running-pterodactyl-gnus-0_73-or-later): Ditto.
+       (gnus-original-version-number): Ditto.
+       (gnus-revision-number): Ditto.
+
+       * lisp/gnus-vers.el (gnus-extended-version): Move from gnus-msg.el.
+       (gnus-version): Move from gnus.el.
+       (gnus-version): Ditto.
+       (gnus-version-number): Ditto.
+       (gnus-product-name): Ditto.
+       (gnus-original-product-name): Ditto.
+       (running-pterodactyl-gnus-0_73-or-later): Ditto.
+       (gnus-original-version-number): Ditto.
+       (gnus-revision-number): Ditto.
+
+       * lisp/gnus-start.el (gnus-product-quick-file-format): Use
+       `gnus-vers' instead of `gnus' for the product.
+       (gnus-product-save-variable-file-1): Message an absolute file name;
+       use `save-buffer-as-coding-system'; use `gnus-vers' instead of
+       `gnus' for the product.
+       (gnus-convert-old-ticks): Remove.
+       (gnus-convert-old-newsrc): Remove.
+       (gnus-read-newsrc-file): Don't call `gnus-read-newsrc-file'.
+
+       * lisp/gnus-spec.el (gnus-compile): Modify for the new form of
+       `gnus-format-specs-compiled'.
+       (gnus-update-format-specifications): Specify the arg `format' for
+       `gnus-update-format-specification-1'.
+       (gnus-update-format-specification-1): Modify for the new form of
+       `gnus-format-specs-compiled'; add a new arg `format'.
+       (gnus-format-specs-compiled): Allow the plural compiled functions
+       for each element.
+
+       * lisp/gnus-msg.el (gnus-extended-version): Move to gnus-vers.el.
+
+2000-03-14  Keiichi Suzuki  <keiichi@nanap.org>
+
+       NOTE: It requires `product' in APEL 10.0 or later.
+       Will be created ``~/News/.T-gnus/'' directory automatically by
+       default.   You can customize location by `gnus-product-directory'.
+       ``cache'' and  ``strict-cache'' files will be created under the
+       directory.
+
+       * lisp/gnus.el (TopLevel): Require `gnus-vers'.
+       (gnus-product-name): Abolished.
+       (gnus-version-number): Ditto.
+       (gnus-version): Use `product-string'. (Format changed)
+       (gnus-variable-list): Delete `gnus-format-specs'.
+       (gnus-product-variable-file-list): New variable.
+       (TopLevel): Use `product-provide'.
+
+       * lisp/gnus-vers.el: New file.
+
+       * lisp/gnus-start.el (gnus-product-directory): New user option.
+       (gnus-clear-quick-file-variables): New function.
+       (gnus-clear-system): Use `gnus-clear-quick-file-variables'.
+       (gnus-read-newsrc-file): Likewise.
+       (gnus-read-newsrc-el-file): Read product's variable files.
+       (gnus-product-read-variable-file-1): New function.
+       (gnus-save-newsrc-file): Save product's variable files.
+       (gnus-product-variable-touch): New function.
+       (gnus-product-variables-dirty-p): Ditto.
+       (gnus-product-save-variable-file): Ditto.
+       (gnus-product-save-variable-file-1): Ditto.
+       (gnus-product-quick-file-format): Ditto.
+
+       * lisp/gnus-spec.el (gnus-update-format): Use
+       `gnus-product-variable-touch'.
+       (gnus-update-format-specification-1): Likewise.
+       (gnus-update-format-specifications): Do not check `emacs-version'
+       and `gnus-newsrc-file-version'.  Use
+       `gnus-product-variable-touch'.
+
+       * lisp/gnus-msg.el (gnus-inews-add-send-actions): Use
+       `product-string'.
+
+2000-03-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 14.
+       (gnus-compile-user-specs): New user option.
+
+       * texi/gnus.texi: Update.
+       * texi/gnus-ja.texi: Update.
+
+       * lisp/gnus-start.el (gnus-setup-news): Revert.
+       (gnus-setup-news-hook): Revert.
+
+       * lisp/gnus-spec.el (gnus-compile): Modify the actual format specs
+       as well; don't bind `gnus-tmp-func'.
+       (gnus-update-format-specifications): Revert; use
+       `gnus-update-format-specification-1'.
+       (gnus-update-format-specification-1): New function.
+       (gnus-format-specs-compiled): Modify the form.
+       (TopLevel): Require `alist'.
+
+2000-03-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 13.
+
+       * texi/gnus.texi: Update.
+       * texi/gnus-ja.texi: Update.
+
+       * lisp/gnus-start.el (gnus-setup-news): Update all format specs
+       just before `gnus-setup-news-hook' is evaluated.
+       (gnus-setup-news-hook): Default to `gnus-compile'.
+
+       * lisp/gnus-spec.el (gnus-compile): Don't modify the value of
+       `gnus-format-specs', generate compiled specs in
+       `gnus-format-specs-compiled' instead; don't touch the dribble
+       buffer.
+       (gnus-update-format-specifications): Bind `gnus-format-specs' to
+       `gnus-format-specs-compiled' if the latter is non-nil; use
+       `gnus-update-format-specifications-1'.
+       (gnus-update-format-specifications-1): Rename from
+       `gnus-update-format-specifications'; update the value of
+       `gnus-newsrc-file-version' if the updating is forced.
+       (gnus-format-specs-compiled): New internal variable.
+
+2000-03-05  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-spec.el (gnus-update-format-specifications): Force
+       update format specifications, when differ `gnus-version' and
+       `gnus-newsrc-file-version' instead of `gnus-version' and
+       `gnus-version' in `gnus-format-specs'.
+       Do not add `gnus-version' into `gnus-format-specs'.
+
+2000-03-04   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-spec.el (gnus-compile): Remove gnus-version entry
+       from gnus-format-specs.
+
+2000-02-21  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * nnvirtual.el (nnvirtual-request-article):
+       Bind gnus-override-method to nil.
+       (nnvirtual-request-update-mark): Don't update mark when
+       article is not there.
+
+2000-03-03   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 12.
+
+       * lisp/gnus-sum.el: Add autoload setting for `pgg-decrypt-region'
+       and `pgg-verify-region'.
+       (gnus-summary-decrypt-article): New command.
+       (gnus-summary-verify-article): New command.
+       (gnus-summary-article-map): Bind them.
+       (gnus-wheel-summary-scroll): Fix paren style.
+
+2000-03-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 11.
+
+2000-03-01  MORIOKA Tomohiko  <tomo@m17n.org>
+
+       * lisp/nnheader.el (nnheader-insert-nov): Use
+       `mime-entity-fetch-field' instead of `mime-fetch-field'.
+
+       * lisp/gnus-sum.el (gnus-summary-line-format-alist): Use
+       `mime-entity-read-field' instead of `mime-read-field'.
+       (gnus-article-sort-by-author): Likewise.
+
+2000-03-02   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/nnimap.el (nnimap-request-article-part): Don't use
+       `imap-capability' to detect BODYDETAIL response.
+
+2000-03-01   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+
+       * lisp/nnimap.el
+       (nnimap-request-article-part): Handle `BODY' fetch response when
+       the server implements IMAP4 rev1 capabilities.
+       (nnimap-request-article): Use BODY.PEEK rather than RFC822.PEEK.
+       this attribute was obsoleted in RFC2060.
+       (nnimap-request-body): Ditto.
+
+2000-02-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-ems.el (gnus-tilde-cut-form, gnus-tilde-max-form): Copy
+       from gnus-xmas.el; share them with XEmacs-MULE.
+
+       * lisp/gnus-xmas.el (gnus-tilde-cut-form, gnus-tilde-max-form):
+       Move to gnus-ems.el.
+
+2000-02-20   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-bbdb.el: Sync up with Nana-gnus 7 for supporting
+       `gnus-bbdb/split-mail'.
+       * README-gnus-bbdb.ja: Ditto.
+
+2000-02-08  Yoshiki Hayashi <yoshiki@xemacs.org>
+
+       * gnus-art.el (article-display-face): Show folded X-Face.
+
+2000-02-08  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/nnmail.el (nnmail-get-new-mail): Do not check
+       `nnmail-spool-file'.
+
+2000-02-06   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus-ofsetup.el: Provide `gnus-ofsetup'.
+       (gnus-setup-for-offline): Add `starttls' to IMAP streams; add
+       `digest-md5' to IMAP authenticators.
+
+       * lisp/gnus-offline.el (gnus-group-get-new-news,
+       gnus-agent-toggle-plugged,gnus-agent-expire,
+       gnus-agent-mode): Check whether `gnus-ofsetup' is provided before
+       redefining.
+
+       * lisp/imap.el (imap-stream-alist): Remove redundant entry for TLS.
+
+       * lisp/nnimap.el (nnimap-retrieve-headers-progress): Remove
+       confusing tabs from original header.
+
+2000-02-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-md5): Fset to `md5' if the module `md5' is
+       installed.
+       (pop3-apop): Use built-in `md5' if it exists.
+
+2000-01-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/gnus-art.el (gnus-treat-display-smileys): Check for the
+       module `gnus-bitmap' instead of `smiley-mule'.
+
+       * lisp/gnus-sum.el (gnus-summary-exit): Recenter the group buffer
+       without redisplaying if the point is out of view.
+
+2000-01-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+2000-01-24  SANETO Takanori <sanewo@ba2.so-net.ne.jp>
+
+       * lisp/gnus-spec.el: Call `gnus-ems-redefine'.
+
+       * lisp/pop3.el (pop3-movemail): Don't use `format' for `message'.
+       * lisp/gnus-offline.el (gnus-offline-toggle-articles-to-fetch):
+       Ditto.
+
+       * lisp/read-passwd.el (read-pw-read-noecho): Use "%s" for the 1st
+       arg of `message'.
+       * lisp/gnus.el (gnus-version): Ditto.
+       * lisp/gnus-sum.el (gnus-summary-simplify-subject-query): Ditto.
+       * lisp/gnus-offline.el (gnus-offline-set-interval-time,
+       gnus-offline-empting-spool, gnus-offline-toggle-on/off-send-mail,
+       gnus-offline-set-auto-ppp, gnus-offline-after-jobs-done,
+       gnus-offline-hangup-line, gnus-offline-get-new-news-function,
+       gnus-offline-connect-server): Ditto.
+       * lisp/dgnushack.el (dgnushack-make-package): Ditto.
+
+2000-01-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-sum.el (gnus-summary-exit): Don't recenter the group
+       buffer if it is called non-interactively.
+
+2000-01-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-sum.el (gnus-summary-exit): Recenter the group buffer
+       if the point is out of view.
+
+2000-01-15  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-art.el (gnus-article-next-page): Scroll up LINES if
+       `pos-visible-in-window-p' returns nil.
+
+2000-01-15  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-agent-mode): New advice.
+
+2000-01-12  Hirokazu FUKUI  <hfukui@sannet.ne.jp>
+
+       * lisp/base64.el: Unbound base64-*-string and base64-*-region
+       when defined by autoload.
+
+2000-01-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-reselect-current-group): Restore
+       the original code; hide group contents while rescanning.
+
+2000-01-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-reselect-current-group): Truncate
+       lines in the imitation buffer; turn off h-scrollbar for XEmacs.
+
+2000-01-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/{rfc2231.el,nnweb.el,nnultimate.el,nntp.el,nnspool.el,
+       nnslashdot.el,nnml.el,nnmh.el,nnkiboze.el,nnimap.el,gnus-topic.el,
+       gnus-ofsetup.el,gnus-offline.el,gnus-mlspl.el,gnus-cache.el,
+       gnus-agent.el}: Require `gnus-clfns' when compiling.
+
+       * lisp/rfc2231.el: Require `cl' when compiling.
+
+       * lisp/gnus-clfns.el: New file.
+
+       * lisp/dgnushack.el: Move compiler macros to gnus-clfns.el; load
+       gnus-clfns.el.
+
+       * lisp/gnus-sum.el (gnus-summary-reselect-current-group): Don't
+       rescan the current newsgroup before exiting; wear an imitation
+       summary buffer while rescanning.
+
+2000-01-06  Hirokazu FUKUI  <hfukui@sannet.ne.jp>
+
+       * lisp/dgnushack.el (char-before): Use the byte-optimaization.
+
+2000-01-05  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.14.1.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * lisp/{webmail.el,uudecode.el,utf7.el,time-date.el,smiley.el,
+       score-mode.el,rfc2047.el,rfc1843.el,qp.el,pop3.el,parse-time.el,
+       nnweb.el,nnwarchive.el,nnvirtual.el,nnultimate.el,nntp.el,
+       nnspool.el,nnsoup.el,nnslashdot.el,nnml.el,nnmh.el,nnmbox.el,
+       nnmail.el,nnlistserv.el,nnkiboze.el,nnimap.el,nnheader.el,
+       nnfolder.el,nneething.el,nndraft.el,nndoc.el,nndb.el,nnbabyl.el,
+       nnagent.el,mml.el,mm-view.el,mm-uu.el,mm-util.el,mm-encode.el,
+       mm-decode.el,mm-bodies.el,messcompat.el,message.el,md5.el,
+       mail-source.el,mail-prsvr.el,lpath.el,imap.el,ietf-drums.el,
+       gnus-xmas.el,gnus-win.el,gnus-vm.el,gnus-uu.el,gnus-util.el,
+       gnus-undo.el,gnus-topic.el,gnus-sum.el,gnus-start.el,gnus-srvr.el,
+       gnus-spec.el,gnus-soup.el,gnus-setup.el,gnus-score.el,gnus-salt.el,
+       gnus-range.el,gnus-picon.el,gnus-nocem.el,gnus-msg.el,
+       gnus-mlspl.el,gnus-mh.el,gnus-mailcap.el,gnus-logic.el,
+       gnus-load.el,gnus-kill.el,gnus-group.el,gnus-gl.el,gnus-ems.el,
+       gnus-draft.el,gnus-demon.el,gnus-cus.el,gnus-cite.el,gnus-cache.el,
+       gnus-bcklg.el,gnus-audio.el,gnus-async.el,gnus-art.el,
+       gnus-agent.el,binhex.el,base64.el,ChangeLog}: Sync up with Gnus
+       v5.8.3.
+
+       * texi/{postamble.tex,message.texi,gnus.texi,gnus-ja.texi,
+       emacs-mime.texi,ChangeLog}: Sync up with Gnus v5.8.3.
+
+2000-01-05  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * README.semi, README.semi.ja, texi/gnus-faq-ja.texi: Update for
+       the new CVS server.
+
+       * lisp/gnus-sum.el (gnus-articles-to-read): Bind
+       `cursor-in-echo-area' to nil while `read-from-minibuffer'.
+
+1999-12-30  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (TopLevel): Call
+       `define-process-argument-editiong' only under Meadow -- i.e. don't
+       call this function under NTEmacs.
+
+1999-12-28  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 15.
+
+       * lisp/gnus-offline.el (gnus-offline-auto-expire): Rename from
+       `gnus-offline-agent-automatic-expire'.
+       (gnus-agent-expire): Fix the advice.
+       (gnus-offline-after-jobs-done): Refer to
+       `gnus-offline-auto-expire'.
+
+       * lisp/gnus-ofsetup.el (gnus-offline-resource-en): Reorder the
+       messages.
+       (gnus-offline-resource-ja): Ditto.
+
+       * lisp/imap.el (imap-ssl-open-2): If `system-type' is windows-nt,
+       bind `coding-system-for-read' to raw-text-dos, else bind it to
+       binary.
+
+1999-12-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 14.
+
+       * lisp/dgnushack.el (mapcon): Bind the 1st arg `fn' as a temp var.
+
+1999-12-27  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/pop3.el (pop3-ssl-program-arguments): Add "s_client".
+       (pop3-open-ssl-stream-1): Bind `ssl-program-name' because its
+       value depends on the version of ssl.el.
+       (pop3-open-ssl-stream): If `system-type' is windows-nt, bind
+       `coding-system-for-read' to raw-text-dos, else bind it to binary.
+
+1999-12-23  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Fix timing of
+       `save-restriction'.
+
+1999-12-21   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/imap.el (imap-streams,imap-stream-alist,
+       imap-authenticators,imap-authenticator-alist,
+       imap-digest-md5-p): Sync with latest Gnus.
+       (imap-starttls-p): Rename from `imap-tls-p'.
+       (imap-starttls-open): Rename from `imap-tls-open'.
+
+1999-12-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 13.
+
+       * lisp/dgnuspath.el.in: Add the path of APEL to `load-path' as well
+       as its parent directory.
+
+       * lisp/imap.el (base64-encode-string, base64-decode-string):
+       Autoload "base64" instead of the tricky definitions.
+
+       * lisp/base64.el: Restore the original code and invalidate it; use
+       mel for the base64 codec.
+
+1999-12-20  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/imap.el (mel-find-function): Always require `mel' instead of
+       the use of autoloading.  Because the function `mel-find-function'
+       is defined by `defsubst'.
+
+1999-12-18  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-after-get-new-news): Refer to
+       `gnus-offline-connected', not `gnus-plugged'.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): No need to use
+       `unless'. Use `when'.
+
+       * lisp/imap.el (base64-encode-string): Fix. May work.
+
+1999-12-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-goto-mail-copies-to): If the field is
+       newly created, a string "never" is inserted in default.
+       (message-goto-mail-followup-to): If the field is newly created and
+       To field contains only one address, the address is inserted in
+       default.
+       (message-mode-map): New key stroke `C-c C-f c' for the command
+       `message-goto-mail-copies-to'.
+
+1999-12-15  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 12.
+
+       * lisp/nnimap.el (nnimap-request-newgroups): Use `member-if'.
+
+       * lisp/lpath.el (toolbar-gnus, get-charset-property,
+       font-lock-set-defaults, find-coding-system, coding-system-get):
+       Bind them for FSF Emacsen.
+       (read-color, x-defined-colors, compute-motion): Don't bind.
+
+       * lisp/imap.el (imap-digest-md5-auth, imap-cram-md5-auth): Use
+       `base64-encode-string' and `base64-decode-string' instead of
+       `imap-base64-encode-string' or `imap-base64-decode-string'.
+       (base64-encode-string): New function.  It won't be defined if it
+       is already bound and the optional second arg is allowed.
+       (base64-decode-string): New function defined by `defun-maybe'.
+       (imap-base64-encode-string, imap-base64-decode-string): Remove.
+       (mel-find-function): Autoload "mel".
+
+       * lisp/dgnushack.el (read-color, x-defined-colors, event-object,
+       get-popup-menu-response, toolbar-gnus, get-charset-property,
+       find-coding-system, coding-system-get, font-lock-set-defaults):
+       Don't bind.
+       (union, member-if, mapcon, mapc, last): Don't define as compiler
+       macros under XEmacs.  It is based on Hrvoje's advice.
+       (member-if): New compiler macro for emulating cl function.
+
+1999-12-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/imap.el (imap-base64-encode-string): Use `static-if' instead
+       of `static-condition-case'.
+
+1999-12-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 11.
+
+       * lisp/imap.el (imap-base64-encode-string): Allow the optional 2nd
+       arg `no-line-break'.
+
+1999-12-14   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/imap.el: Require `digest-md5' when compiling; add autoload
+       settings for `digest-md5-parse-digest-challenge' and
+       `digest-md5-digest-response'.
+       (imap-authenticators): Add `digest-md5'.
+       (imap-authenticator-alist): Setup for `digest-md5'.
+       (imap-digest-md5-p): New function.
+       (imap-digest-md5-auth): New function.
+
+1999-12-12  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/mail-source.el (mail-source-fetch-imap): Each temporary
+       buffer name must be specific to its mail source.
+
+1999-12-11  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-and-key): Don't
+       call too many `static-if's.
+
+       * lisp/gnus-uu.el (gnus-uu-grab-move): Simply copy FILE if
+       `make-symbolic-link' is not availabe.
+
+       * lisp/lpath.el (TopLevel): Don't warn about `make-symbolic-link'.
+
+1999-12-11  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-set-unplugged-state): Call
+       the original `gnus-agent-toggle-plugged'.
+
+       * lisp/mail-source.el (mail-source-fetch-imap): Don't create
+       multiple temporary buffers, and don't kill one.
+
+1999-12-10  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-ofsetup.el (gnus-setup-for-offline): Accept an
+       optional argument `force'. Use `read-file-name' instead of
+       `read-directory-name'.
+
+1999-12-10  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-numbser): Increment to 08.
+
+       * lisp/gnus-agent.el (gnus): Give up to advise here.
+       (gnus-group-get-new-news): New advice instead.
+
+       * lisp/gnus-offline.el (gnus-offline-setup): Call
+       `gnus-offline-processed-by-timer' and `gnus-offline-error-check'
+       here.
+       (gnus-offline-define-menu-and-key): Simplify.
+       (gnus-offline-processed-by-timer): Call `gnus-group-get-new-news'
+       interactively.
+
+       * lisp/gnus-ofsetup.el (TopLevel): Require `read-passwd' here, not in
+       `gnus-offline-setting-file'.
+       (gnus-nntp-service): Set this variable here, not in
+       `gnus-offline-setting-file'
+       (gnus-nntp-server): Ditto.
+       (gnus-after-getting-new-news-hook): Ditto.
+       (message-send-hook): Ditto.
+       (mail-source-read-passwd): Ditto.
+       (gnus-setup-news-hook): Ditto.
+       (gnus-setup-for-offline): Now one can get mails from `imap',
+       `file', `directory' or `maildir'.
+
+       * lisp/read-passwd.el (read-pw-set-mail-source-passwd-cache):
+       Ignore non-POP mail sources.
+
+1999-12-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus-util.el (gnus-union): Remove.
+       (gnus-ems-redefine): Don't call it; don't require `gnus-ems'.
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-headers): Use `union'
+       instead of `gnus-union'.
+
+1999-12-10  A.Hitachi       <a_hitachi@msi.biglobe.ne.jp>
+            Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (union): New compiler macro for emulating cl
+       function.
+
+1999-12-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-util.el: Require `gnus-ems'.
+       (gnus-ems-redefine): Call it to redefine the functions
+       `gnus-truncate-string', etc.
+       (gnus-union): Fix doc string.
+
+       * lisp/dgnushack.el (mapcon, mapc): Eliminate the redundant code.
+
+1999-12-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+1999-12-09  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/dgnushack.el (dgnushack-install-package): Preserve any file
+       in $(PACKAGEDIR)/lisp/t-gnus if it is without .el or .elc suffix.
+
+1999-12-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (mapcon): New compiler macro for emulating cl
+       function.
+       (mapc): Bug fix - treat the last arg as a list.
+
+1999-12-08  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/gnus-agent.el (gnus): New advice. Always synchronize the
+       modeline "Plugged" status display with the value of
+       `gnus-plugged'.
+
+       * lisp/gnus-offline.el (TopLevel): Require `gnus-group' at the
+       compile time.
+       (gnus-offline-set-online-sendmail-function): defsubst.
+       (gnus-offline-set-offline-sendmail-function): Ditto.
+       (gnus-offline-set-offline-post-news-function): Ditto.
+       (gnus-offline-set-online-post-news-function): Ditto.
+       (gnus-offline-disable-fetch-mail): Ditto.
+       (gnus-offline-enable-fetch-mail): Ditto.
+       (gnus-offline-setup): Fix typo.
+       (gnus-offline-gnus-get-new-news): Abolish.
+       (gnus-offline-toggle-plugged): Ditto.
+       (gnus-offline-agent-expire): Ditto.
+       (gnus-group-get-new-news): New advice which does things
+       `gnus-offline-gnus-get-new-news' was doing.
+       (gnus-agent-toggle-plugged): New advice which does thing
+       `gnus-offline-toggle-plugged' was doing.
+       (gnus-agent-expire): New advice which does things
+       `gnus-offline-agent-expire' was doing.
+       (gnus-offline-define-menu-and-key): No longer substitute key
+       definitions on `gnus-group-mode-map'. No longer swap commands for
+       a toolbar button.
+       (gnus-offline-after-get-new-news): Do jobs only when
+       `gnus-plugged' is t.
+
+       * lisp/gnus-ofsetup.el (gnus-ofsetup-customize): Compile lambda
+       expressions.
+
+1999-12-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-yank-add-new-references): Fix doc string.
+
+       * texi/{message-ja.texi, message.texi}
+       (message-list-references-add-position,
+       message-yank-add-new-references): Add documentations.
+
+1999-12-07  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-offline.el (gnus-offline-gettext): Rename from
+       `gnus-offline-get-message'.
+
+       * lisp/gnus-ofsetup.el (gnus-ofsetup-gettext): Rename from
+       `gnus-ofsetup-get-message'.
+
+1999-12-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+       (smiley-toggle-buffer): Autoload "smiley" or "gnus-bitmap".
+
+       * lisp/gnus-art.el (gnus-article-prepare-mime-display): Don't use
+       `get-text-property' in the outside of the boundary.
+       (gnus-article-smiley-display): New function.
+       (gnus-treatment-function-alist): Use it.
+
+       * lisp/dgnushack.el (byte-optimize-form-code-walker): Replace with
+       the bug fixed version rigidly instead of the use of `defadvice'.
+
+       * lisp/message.el (font-lock-after-change-function): Don't use
+       `compile' for the arg of `defadvice'.
+
+1999-12-06  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/message.el (message-yank-add-new-references): New option
+       value `message-id-only'.
+       (message-yank-original): Likewise.
+       (message-list-references-add-position): New user option.
+       (message-list-references): When
+       `message-list-references-add-position' is integer value, the order
+       of designate number message-ids is kept.
+
+1999-12-06  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-offline.el (gnus): Don't advise here.
+       (TopLevel): Call `gnus-offline-define-menu-and-key'.
+       (gnus-offline-setup): Don't call
+       `gnus-offline-define-menu-and-key' here.
+
+       * lisp/gnus-ofsetup.el (gnus-offline-update-setting-file): Don't
+       rely on `gnus-load-hook'.
+       (gnus): New advice. Call `gnus-offline-setup' when everything is
+       done.
+
+       * lisp/gnus-start.el (save-buffers-kill-emacs): Compile the advice
+       at the compile time. Use `gnus-alive-p'.
+
+1999-12-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/dgnushack.el (char-after): Uncomment the byte-optimization;
+       don't use `byte-defop-compiler'.
+       (byte-optimize-form-code-walker): Advise it for fixing the bug in
+       and/or forms.  The original idea is devised by FUKUI-san, modified
+       by KOBAYASHI-san.
+       (max-specpdl-size): Set 3000.
+
+1999-12-05  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-offline.el (gnus): New advice. synchronize
+       `gnus-offline-connected' with `gnus-plugged'.
+
+1999-12-04   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.14.0.
+       (gnus-revision-number): Clear to 00.
+
+       * README.branch.ja: Update for t-gnus-6_14 branch.
+       * README.branch: Ditto.
+       * README.T-gnus: Ditto.
+       * README.semi.ja: Ditto.
+       * README.semi: Ditto.
+
+       * lisp/{rfc2047.el,nnweb.el,nnultimate.el,nntp.el,nnslashdot.el,
+       nnmh.el,nnfolder.el,nndoc.el,mml.el,mm-view.el,mm-util.el,
+       mm-bodies.el,message.el,mail-source.el,gnus.el,gnus-uu.el,
+       gnus-sum.el,gnus-start.el,gnus-msg.el,gnus-int.el,gnus-cache.el,
+       gnus-art.el,dgnushack.el,ChangeLog}: Sync up with Gnus v5.8.2.
+
+       * texi/{message.texi,message-ja.texi,gnus.texi,gnus-ja.texi,
+       gnus-faq-ja.texi,ChangeLog}: Modify for T-gnus 6.14; sync up with
+       Gnus v5.8.2.
+
+       * t-gnus-6_14: NEW PUBLIC BRANCH.
+
+1999-12-03  Hirokazu FUKUI  <hfukui@sannet.ne.jp>
+            Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/dgnushack.el (char-before): Use compiler macro instead of
+       byte-optimizer.
+       (char-after): Comment out the byte-optimization.
+
+       * imap.el (imap-base64-encode-string, imap-base64-decode-string):
+       New functions.  They are identical to the built-in codec if
+       possible, otherwise the functions defined in mel are used.
+       (imap-cram-md5-auth): Use them.
+
+1999-12-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/imap.el: Remove autoload settings for `base64-decode-string'
+       and `base64-encode-string'.
+
+1999-12-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.13.4.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * GNUS-NEWS: Sync up with Pterodactyl Gnus v0.99.
+
+       * lisp/{rfc2047.el,rfc1843.el,nnweb.el,nnvirtual.el,nntp.el,
+       nnmh.el,nnmail.el,nnimap.el,nnheader.el,nnfolder.el,nndraft.el,
+       nndoc.el,mml.el,mm-view.el,mm-uu.el,mm-util.el,mm-encode.el,
+       mm-decode.el,mm-bodies.el,message.el,mail-source.el,lpath.el,
+       gnus-xmas.el,gnus-uu.el,gnus-util.el,gnus-topic.el,gnus-sum.el,
+       gnus-start.el,gnus-srvr.el,gnus-spec.el,gnus-score.el,gnus-salt.el,
+       gnus-picon.el,gnus-msg.el,gnus-mailcap.el,gnus-int.el,
+       gnus-group.el,gnus-ems.el,gnus-cus.el,gnus-cache.el,gnus-async.el,
+       gnus-art.el,gnus-agent.el,dgnushack.el,base64.el,Makefile.in,
+       ChangeLog}: Sync up with Pterodactyl Gnus v0.99.
+
+       * lisp/{webmail.el,nnwarchive.el,nnultimate.el,nnslashdot.el}: New
+       files.
+
+       * texi/{message.texi,message-ja.texi,gnus.texi,gnus-ja.texi,
+       emacs-mime.texi,Makefile.in,ChangeLog}: Sync up with Pterodactyl
+       Gnus v0.99.
+
+1999-12-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-select-method): Undo (`if' -> `when').
+       * lisp/gnus-picon.el (gnus-picons-file-suffixes): Ditto.
+       * lisp/gnus-start.el (save-buffers-kill-emacs): Ditto.
+       (gnus-after-getting-new-news-hook): Ditto.
+
+       * lisp/gnus-group.el (gnus-useful-groups): Undo (`or' -> `unless').
+
+1999-12-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+
+       * lisp/gnus-art.el (article-treat-overstrike): Work for multibyte
+       char with old Emacsen as well.
+
+1999-12-01   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-agent.el (gnus-category-edit-predicate): Expand `setf'
+       appears in the backquoted form.
+       (gnus-category-edit-score): Ditto.
+
+       * lisp/gnus-sum.el (gnus-data-set-header): Expand `setf'
+       appears in the backquoted form.
+
+1999-11-30  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-offline.el (gnus-offline-define-menu-and-key): Fix a
+       bug -- do add-hook.
+       (gnus-offline-popup): Examine whether `easy-menu-create-menu' is
+       defined. If not, call `easy-menu-create-keymaps'.
+
+1999-11-30  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-offline.el (TopLevel): Use `static-if', requiring
+       "static" at the compile time.
+       (gnus-offline-hangup-function): Abolish.
+       (gnus-offline-auto-ppp): New variable.
+       (gnus-offline-gnus-get-new-news): Refer to it.
+       (gnus-offline-set-unplugged-state): Ditto.
+       (gnus-offline-set-auto-ppp): New function. It replaces the
+       function `gnus-offline-toggle-auto-hangup'.
+       (gnus-offline-toggle-auto-hangup): Abolish.
+       (gnus-offline-define-menu-and-key): Use `static-if' and
+       `static-cond'.
+       (gnus-offline-popup-menu): Do not define this function under XEmacs.
+       (gnus-offline-popup): New function.
+
+       * gnus-ofsetup.el (gnus-ofsetup-update-setting-file): Typo.
+       (gnus-ofsetup-resource-en): Fix doc strings.
+       (gnus-ofsetup-resource-ja): Ditto.
+
+1999-11-30  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus-art.el (gnus-article-wash-status): Sync up with
+       Pterodactyl Gnus v0.98.
+
+1999-11-30  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnimap.el (nnimap-request-newgroups): Don't use `member-if'.
+
+       * lisp/gnus.el (gnus-select-method): Use `if' instead of `when'.
+
+       * lisp/gnus-sum.el (gnus-summary-make-marking-command-1): Use
+       `car' and `cdr' instead of `cadr'.
+
+       * lisp/gnus-picon.el (gnus-picons-file-suffixes): Use `cons'
+       instead of `push'; use `if' instead of `when'.
+
+       * lisp/gnus-group.el (gnus-group-iterate): Use `car' and `cdr'
+       instead of `pop'.
+       (gnus-useful-groups): Use `or' instead of `unless'.
+
+       * lisp/gnus-art.el (gnus-emphasis-alist): Use `car' and `cdr'
+       instead of `cadr'.
+
+1999-11-30  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (save-buffers-kill-emacs): Don't use the macro
+       `when' in the body of `defadvice'.  Use `if' instead.
+
+       * lisp/dgnushack.el (last, mapc): New compiler macros for emulating
+       cl functions.
+
+1999-11-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-after-getting-new-news-hook): Don't use
+       the macro `when' in the arg of `defcustom'.  Use `if' instead.
+
+1999-11-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus-art.el (gnus-signature-toggle): Specify the 4th arg of
+       `next-single-property-change' LIMIT as `point-max'.
+       (gnus-article-prepare-mime-display): Ditto.
+       (article-hide-signature): Ditto.
+
+1999-11-26  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * lisp/gnus.el (gnus-version): Parentheses of gnus-revision-number
+       are removed to fill gnus-version within 80 columns.
+
+1999-11-25  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * lisp/gnus.el (gnus-version): Shows also gnus-revision-number.
+
+1999-11-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-headers): Use `gnus-union'
+       instead of `union'.
+
+       * lisp/gnus-util.el (gnus-union): New function.
+
+       * lisp/gnus-sum.el (gnus-summary-exit-no-update):  Use
+       `copy-sequence' instead of `copy-list'.
+       * lisp/gnus-art.el (gnus-article-setup-highlight-words): Ditto.
+
+       * lisp/dgnushack.el (union, copy-list): Remove compiler macros.
+
+1999-11-24  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/dgnushack.el (union, copy-list): New compiler macros for
+       emulating cl functions.
+
+1999-11-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+       (gnus-select-method): Use `condition-case' instead of
+       `ignore-errors'.
+
+       * lisp/gnus-start.el (gnus-site-init-file): Use `condition-case'
+       instead of `ignore-errors'.
+
+       * lisp/{gnus-ofsetup.el,gnus-offline.el}: Remove RCS magic cookie.
+
+       * lisp/{time-date.el,smiley.el,score-mode.el,pop3.el,nnweb.el,
+       nnvirtual.el,nntp.el,nnspool.el,nnsoup.el,nnoo.el,nnml.el,nnmh.el,
+       nnmbox.el,nnmail.el,nnlistserv.el,nnimap.el,nnheader.el,
+       nneething.el,nndraft.el,nndoc.el,nnbabyl.el,message.el,imap.el,
+       gnus-win.el,gnus-vm.el,gnus-util.el,gnus-topic.el,gnus-sum.el,
+       gnus-start.el,gnus-srvr.el,gnus-spec.el,gnus-score.el,gnus-salt.el,
+       gnus-range.el,gnus-picon.el,gnus-ofsetup.el,gnus-offline.el,
+       gnus-msg.el,gnus-mlspl.el,gnus-mailcap.el,gnus-logic.el,
+       gnus-kill.el,gnus-group.el,gnus-cite.el,gnus-async.el,gnus-art.el,
+       gnus-agent.el,earcon.el}: Require `cl' using `eval-when-compile'.
+
+1999-11-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/{time-date.el,smiley.el,pop3.el,nnweb.el,nnvirtual.el,
+       nntp.el,nnspool.el,nnsoup.el,nnoo.el,nnml.el,nnmh.el,nnmbox.el,
+       nnmail.el,nnlistserv.el,nnimap.el,nnheader.el,nneething.el,
+       nndoc.el,nnbabyl.el,message.el,imap.el,gnus.el,gnus-win.el,
+       gnus-util.el,gnus-topic.el,gnus-sum.el,gnus-start.el,gnus-srvr.el,
+       gnus-spec.el,gnus-score.el,gnus-salt.el,gnus-range.el,
+       gnus-picon.el,gnus-ofsetup.el,gnus-offline.el,gnus-mlspl.el,
+       gnus-mailcap.el,gnus-logic.el,gnus-kill.el,gnus-group.el,
+       gnus-cite.el,gnus-async.el,gnus-art.el,gnus-agent.el,earcon.el}:
+       Require `cl' at the top level.
+
+       * lisp/gnus.el (gnus-select-method): Undo last change.
+       * lisp/gnus-util.el (copy-list): Undo last change (remove it).
+       * lisp/gnus-start.el (gnus-site-init-file): Undo last change.
+
+       * lisp/gnus-ems.el (gnus-split-string): Remove.
+
+1999-11-21   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/pop3.el: Add description about STLS extension; add autoload
+       setting for `starttls-open-stream' and `starttls-negotiate'.
+       (pop3-stls): New function.
+       (pop3-open-tls-stream): New function.
+       (pop3-open-server): Use `pop3-open-tls-stream' if
+       'pop3-connection-type' is bound to `tls'.
+
+1999-11-20   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/imap.el: Add autoload setting for `starttls-open-stream'
+       and `starttls-negotiate'.
+       (imap-stream-alist): Add TLS entry.
+       (imap-tls-p): New function.
+       (imap-tls-open): New function.
+       (imap-ssl-open): Enclose `open-ssl-stream' with
+       `as-binary-process'.
+
+1999-11-19  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+       (gnus-select-method): Use `condition-case' instead of
+       `ignore-errors'.
+
+       * lisp/pop3.el (pop3-apop): Move the autoload seting to the top
+       level.
+
+       * lisp/md5.el (md5): Allow the optional 4th and 5th arguments
+       `coding' and `noerror' for the stopgaps.
+
+       * lisp/lpath.el (md5): Allow the optional 4th and 5th arguments
+       `coding' and `noerror'.
+       (function-max-args): Maybe-fbind for FSF Emacsen.
+
+       * lisp/imap.el (imap-cram-md5-auth): Specify the 4th arg to `md5'
+       as `binary' if possible.
+       (imap-log): Default to nil (synched with pgnus 0.99).
+       (base64-decode-string): Autoload "mel" instead of "base64".
+       (md5): Autoload "md5" without `eval-and-compile'.
+
+       * lisp/gnus-util.el (copy-list): New function defined by
+       `defun-maybe'.
+
+       * lisp/gnus-sum.el (gnus-update-summary-mark-positions): Specify
+       the 3rd arg of `make-full-mail-header' to "nobody" instead of "".
+
+       * lisp/gnus-start.el (gnus-site-init-file): Use `condition-case'
+       instead of `ignore-errors'.
+
+       * lisp/gnus-picon.el: Require `cl'.
+
+       * lisp/{smiley.el,rfc2104.el,nnvirtual.el,mailheader.el,
+       gnus-offline.el} (cl): Enclose the requiring procedure with
+       `eval-when-compile'.
+
+       * lisp/{imap.el,gnus-mailcap.el} (cl): Enclose the requiring
+       procedure with `eval-when-compile' instead of `eval-and-compile'.
+
+1999-11-09  Yoshiki Hayashi  <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * lisp/read-passwd.el (read-pw-set-mail-source-passwd-cache):
+       Use mail-sources instead of nnmail-spool-file.
+       From: Toshiaki -PCX- Tanaka.
+
+1999-11-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-group-startup-message): Insert space before
+       "based on".
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Ditto.
+
+1999-11-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.13.3.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * lisp/{rfc1843.el,qp.el,nntp.el,nnmail.el,nnfolder.el,nnagent.el,
+       mml.el,mm-view.el,mm-uu.el,mm-util.el,mm-decode.el,mm-bodies.el,
+       message.el,mail-source.el,lpath.el,gnus-util.el,gnus-topic.el,
+       gnus-sum.el,gnus-start.el,gnus-srvr.el,gnus-msg.el,gnus-mailcap.el,
+       gnus-group.el,gnus-art.el,gnus-agent.el,dgnushack.el,binhex.el,
+       ChangeLog}: Sync up with Pterodactyl Gnus v0.98.
+
+       * lisp/{rfc2104.el,nnimap.el,imap.el}: New files.
+
+       * texi/gnus-ja.texi: Sync up with Pterodactyl Gnus v0.98 without
+       translation.
+
+       * texi/{gnus.texi,ChangeLog}: Sync up with Pterodactyl Gnus v0.98.
+
+1999-11-08  Kinji Itoh  <kinji-i@ma.neweb.ne.jp>
+
+       * lisp/gnus-draft.el (gnus-draft-edit-message): Use
+       `message-save-drafts' instead of `set-buffer-modified-p' and
+       `save-buffer'.
+       * lisp/message.el (message-save-drafts): Insert In-Reply-To header
+       because the reply data is lost in Drafts.
+       * lisp/gnus-art.el (gnus-signature-face): Don't check
+       window-system type.
+
+1999-11-08   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/pop3.el (pop3-progress-message): New function.
+       (pop3-movemail): Use it.
+
+1999-10-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (TopLevel): Autolaod "gnus-msg" for the function
+       `gnus-following-method'.
+
+       * lisp/gnus-msg.el (gnus-following-method): Move from gnus-msg.el;
+       wide reply as a mail if the message is not a news; use the macro
+       `gnus-setup-message'.
+
+       * lisp/gnus-art.el (gnus-following-method): Move to gnus-msg.el.
+
+1999-10-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 14.
+       (TopLevel): Autoload "gnus-bitmap" instead of "smiley-mule" for the
+       function `gnus-smiley-display'.
+
+       * lisp/gnus-art.el (gnus-treat-display-smileys): Default to nil if
+       `window-system' is nil.
+       (gnus-article-x-face-command): Default to external command if
+       `window-system' is nil.
+
+1999-10-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 13.
+       (TopLevel): Rearrange autoload settings.
+
+       * lisp/gnus-art.el (gnus-treatment-function-alist): Don't use
+       `smiley-buffer'.
+
+       * lisp/gnus-sum.el (gnus-summary-make-menu-bar): Add button
+       "Toggle smileys" in "Washing" menu.
+       (gnus-summary-wash-map): Add "s" key for `smiley-toggle-buffer'.
+
+       * lisp/smiley.el (gnus-smiley-display): Use `smiley-toggle-buffer'.
+       (smiley-toggle-buffer): New function.
+       (smiley-buffer): Don't quote the function.
+       (smiley-toggle-extents): Ditto.
+
+1999-10-24  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 12.
+       (TopLevel): Add and delete autoloads for functions defined in
+       "gnus-cus", "gnus-offline", "miee", "pop3-fma" and "mw32misc".
+
+       * lisp/gnus-offline.el (TopLevel): Do not consider the functions
+       defined in "miee".
+
+       * lisp/gnus-ofsetup.el (TopLEvel): Do not autoload
+       `gnus-custom-mode' defined in "gnus-cus".
+
+1999-10-21  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 11.
+
+       * lisp/gnus-offline.el (TopLevel): Call `mime-set-field-decoder'
+       when "eword-decode" is loaded. It is for X-Gnus-Offline-Backend
+       header.
+
+1999-10-19  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+       (TopLevel): Autoload "x-face-mule" and "smiley-mule" for the
+       functions `x-face-mule-gnus-article-display-x-face' and
+       `smiley-buffer'.
+
+       * lisp/lpath.el (smiley-encode-buffer): Bind it for FSF Emacsen.
+
+       * lisp/gnus-ems.el (gnus-group-startup-message): Don't replace with
+       `gnus-mule-group-startup-message'.
+       (gnus-mule-group-startup-message): Remove.
+       (gnus-mule-bitmap-image-file): Remove.
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Encode smileys to
+       ordinary text if the feature `smiley-mule' is provided and FSF
+       Emacs is used.
+       (TopLevel): Require `static' at the compile time.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Bind
+       `mime-display-text/plain-hook' to nil.
+       (gnus-article-prepare-mime-display): Use `let' instead of `let*';
+       treat the next entity position as a marker.
+       (gnus-treatment-function-alist): Use `smiley-buffer' instead of
+       `gnus-smiley-display' under FSF Emacsen.
+       (gnus-treat-display-smileys): Default to t if the module
+       `smiley-mule' is installed.
+       (gnus-treat-display-xface): Default to `head' if the value of
+       `gnus-article-x-face-command' is
+       `x-face-mule-gnus-article-display-x-face'.
+       (gnus-article-x-face-command): Default to
+       `x-face-mule-gnus-article-display-x-face' if the module
+       `x-face-mule' is installed.
+       (TopLevel): Require `static' first; require `path-util'.
+
+1999-10-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/message.el (message-mode): Make
+       `message-font-lock-last-position' as buffer local.
+       (message-font-lock-keywords-2): Use
+       `message-font-lock-cited-text-matcher' instead of regexp.
+       (message-font-lock-cited-text-matcher): New function.
+       (font-lock-after-change-function): Advice to the keep last cursor
+       position in `message-font-lock-last-position' before fontifying.
+       (message-font-lock-last-position): New variable.
+       (message-font-lock-citation-name-max-column): New variable.
+       (message-font-lock-cited-text-regexp): New variable.
+       (message-font-lock-fence-close-position): New variable.
+       (message-font-lock-fence-open-position): New variable.
+       (message-font-lock-fence-close-regexp): New variable.
+       (message-font-lock-fence-open-regexp): New variables.
+
+1999-10-04  Masatoshi Tsuchiya <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/message.el (message-mode): Rearrange `font-lock-defaults'
+       using `message-font-lock-keywords', `message-font-lock-keywords-1'
+       and `message-font-lock-keywords-2'.
+       (message-font-lock-keywords): Restruct.
+       (message-font-lock-keywords-1): New variable split from
+       `message-font-lock-keywords'.
+       (message-font-lock-keywords-2): Ditto.
+
+1999-10-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-art.el (gnus-treat-article): Buttonize the signature
+       before highlighting or hiding it.
+       (gnus-article-buttonize-signature): New function.
+       (gnus-article-highlight-signature): Don't buttonize.
+       (gnus-treatment-function-alist): Undo the last change.
+       (gnus-treat-emphasize): Default to nil.
+
+1999-10-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+       (TopLevel): Autoload "gnus-art" for the function
+       `gnus-article-show-all'.
+
+       * lisp/gnus-sum.el (gnus-summary-select-article): Expose all
+       hidden text if the command `gnus-summary-toggle-mime' is used.
+
+       * lisp/gnus-art.el (gnus-signature-toggle): Don't hide the
+       following parts.
+       (gnus-article-highlight-signature): Work for forwarded messages.
+       (gnus-article-show-all): New function based on `article-show-all'.
+       (gnus-article-show-all-headers): Based on
+       `article-show-all-headers'.
+       (article-show-all-headers): New function to show all *HEADERS*.
+       (article-show-all): Show *ALL* literally.
+       (article-hide-signature): Work for forwarded messages.
+       (gnus-treatment-function-alist): Put `gnus-treat-hide-signature'
+       off after `gnus-treat-highlight-signature'.
+
+1999-10-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus-art.el (gnus-article-prepare-mime-display): Protect
+       against forwarded messages without MIME structure.
+       (gnus-treatment-function-alist): Move
+       'gnus-treat-decode-article-as-default-mime-charset' to the top;
+       put `gnus-treat-emphasize' off after
+       `gnus-treat-highlight-headers'.
+
+1999-10-07  Yoshiki Hayashi <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+1999-10-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-treat-predicate): Examine whether the
+       argument is list or not before condition.
+
+1999-10-07  Yoshiki Hayashi <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * lisp/gnus-art.el (gnus-treat-predicate): Work for
+       (typep "something").
+
+1999-10-07  Yoshiki Hayashi  <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * lisp/gnus-art.el (gnus-article-prepare-display):
+       Pass argument nil as a condition to gnus-treat-article.
+       * lisp/gnus-art.el (gnus-article-prepare-mime-display):
+       Ditto. Also, treat last part of multipart article correctly.
+
+1999-10-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/message.el (message-generate-headers): Don't insert
+       excessive newline.
+
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Don't use
+       negative number for the 2nd arg of `insert-char'.
+
+1999-10-06  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus-ofsetup.el (gnus-ofsetup-customize): Info link to
+       gnus-ja instead of gnus if Japanese environment is on.
+
+1999-10-06  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+       (semi-gnus-developers): Remove.
+       (gnus-maintainer): Change mail address.
+       (gnus-group-startup-message): Display version string.
+
+       * lisp/gnus-msg.el (gnus-bug): Delete `Cc'; modify version string.
+
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Display
+       version string; fix glyph position.
+
+1999-10-06  Yoshiki Hayashi  <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-read-move-group-name): Revert
+       to previous version until problem of respooling from
+       nnimap to nnml is solved.
+       (gnus-summary-move-article): Ditto.
+
+1999-10-05  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-art.el (gnus-treat-predicate): Check whether arg's
+       value is t before checking for `condition'.
+       (gnus-article-prepare-mime-display): Search for the entity children
+       if the primary type is `multipart'.
+
+1999-10-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-sum.el (gnus-read-move-group-name): Returns nil
+       instead of signaling an error if the destination group is not
+       newly created.
+       (gnus-summary-move-article): Do nothing if the destination group
+       is not newly created.
+
+       * lisp/gnus-msg.el (gnus-bug): Use text/plain for the snooped
+       environment part.
+
+1999-09-30   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * nnfolder.el (nnfolder-possibly-change-group): Don't create an
+       active entry for the group even if it doesn't exist.
+
+1999-09-28   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * gnus-art.el (gnus-article-mime-part-status): Use `mime-entity-children'.
+
+1999-09-28  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.13.2.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * texi/{message.texi,message-ja.texi,gnus.texi,gnus-ja.texi,
+       emacs-mime.texi,ChangeLog}: Sync up with Pterodactyl Gnus v0.97.
+
+       * lisp/{qp.el,nntp.el,nnmail.el,mml.el,mm-util.el,mm-encode.el,
+       mm-decode.el,message.el,mail-source.el,gnus.el,gnus-xmas.el,
+       gnus-util.el,gnus-sum.el,gnus-srvr.el,gnus-score.el,gnus-nocem.el,
+       gnus-msg.el,gnus-group.el,gnus-cache.el,gnus-art.el,gnus-agent.el,
+       ChangeLog}: Sync up with Pterodactyl Gnus v0.97.
+
+1999-09-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/gnus-art.el (gnus-article-prev-page): Rewrite to realize
+       smooth scrolling under XEmacs.
+       (gnus-article-next-page):Ditto.
+
+       * Mule23@1934.en, Mule23@1934.ja: Separate from Mule23@1934; add
+       descriptions about the problem of loaddefs.el and the patch for
+       CUSTOM 1.9962.
+
+1999-09-22  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/nnmail.el (TopLevel): Bind keywords `:user', `:path' and
+       `:predicate' for old Emacsen; require `static'.
+
+       * lisp/dgnushack.el (TopLevel): Don't bind keywords `:user',
+       `:path' and `:predicate'.
+
+1999-09-20   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * gnus-agent.el (gnus-agent-toggle-plugged): Mark the current
+       modeline as modified.
+
+1999-09-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/gnus-art.el (gnus-treat-article): Inherit the text property
+       `mime-view-entity' in the modified header under FSF Emacsen.
+
+1999-09-13  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * README-offline.en: Rewrite the usage description.
+       * README-offline.ja: Ditto.
+
+1999-09-12  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-ofsetup.el (gnus-offline-lang): Declare before loading
+       `gnus-offline'.
+
+1999-09-12  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * README-offline.en: Do not refer to `gnus-agent-toggle-plugged'.
+       * README-offline.ja: Ditto.
+
+1999-09-11  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-agent.el (gnus-agent-toggle-plugged): Do not mark
+       the current buffer as modified.
+
+       * lisp/gnus-offline.el (gnus-offline-menu): New variable.
+       (gnus-offline-get-menu-items): New function.
+       (gnus-offline-define-menu-on-miee): Use it.
+       (gnus-offline-define-menu-on-agent): Ditto.
+
+1999-09-04   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-msg.el (gnus-configure-posting-styles): Quote `:file'.
+
+       * lisp/pop3.el (pop3-save-uidls): Don't use `dotimes' to check
+       backets of `pop3-uidl-obarray'; don't clear `pop3-uidl-obarray'.
+       (pop3-quit): Clear `pop3-uidl-obarray'.
+
+1999-09-03  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-offline.el (gnus-offline-resource-en,
+       gnus-offline-resource-ja,
+       gnus-offline-resource-ja_complete): New variables.
+       (gnus-offline-get-message): News function.
+       (gnus-offline-error-check): Use it.
+       (gnus-offline-connect-server): Ditto.
+       (gnus-offline-get-new-news-function): Ditto.
+       (gnus-offline-set-mail-group-level): Ditto.
+       (gnus-offline-hangup-line): Ditto.
+       (gnus-offline-after-jobs-done): Ditto.
+       (gnus-offline-toggle-auto-hangup): Ditto.
+       (gnus-offline-toggle-on/off-send-mail): Ditto.
+       (gnus-offline-toggle-articles-to-fetch): Ditto.
+       (gnus-offline-empting-spool): Ditto.
+       (gnus-offline-set-interval-time): Ditto.
+
+       * lisp/gnus-ofsetup.el (gnus-offline-lang,
+       gnus-ofsetup-resource-en, gnus-ofsetup-resource-ja): New
+       variables.
+       (gnus-ofsetup-get-message): New function.
+       (gnus-setup-for-offline): Use it.
+       (gnus-ofsetup-find-parameters): Ditto.
+       (gnus-ofsetup-prepapre-for-miee): Ditto.
+       (gnus-ofsetup-completing-read-symbol): Ditto.
+       (gnus-ofsetup-customize): Ditto.
+       (gnus-ofsetup-customize-done): Ditto.
+
+1999-09-01  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-isearch-article): Don't bind
+       `isearch-lazy-highlight'.
+
+1999-08-30  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/lpath.el (babel-as-string): Bind it.
+
+       * lisp/gnus-sum.el (gnus-summary-search-article): Keep the
+       original X-Face field while searching.  It is done for only FSF
+       Emacsen.
+       (gnus-summary-search-article-highlight-matched-text): Ditto.
+       (gnus-summary-search-article-matched-data): Bind it explicitly.
+
+1999-08-29  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-version-number): Update to 6.13.1.
+       (gnus-revision-number): Clear to 00.
+
+       * README.T-gnus: Update.
+
+       * README: Sync up with Pterodactyl Gnus v0.96.
+       * lisp/{smiley.el,nntp.el,nnmail.el,nnfolder.el,mml.el,mm-view.el,
+       mm-uu.el,mm-util.el,mm-encode.el,mm-decode.el,mm-bodies.el,
+       gnus-uu.el,gnus-util.el,gnus-sum.el,gnus-start.el,gnus-score.el,
+       gnus-mlspl.el,gnus-group.el,gnus-bcklg.el,gnus-art.el,
+       gnus-agent.el,ChangeLog}: Ditto.
+       * texi/{gnus.texi,gnus-ja.texi,ChangeLog}: Ditto.
+
+1999-08-27  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/pop3.el (pop3-movemail): If the argument `crashbox' is t,
+       don't retrieve any incoming mails.; Don't filter articles here.
+       Use `convert-standard-filename' to generate fresh UIDL file names.
+       (pop3-get-message-numbers): Rewrite.
+       (pop3-save-uidls): Clear UIDL hash.; Use `with-temp-file' instead
+       of `with-temp-buffer'.
+
+1999-08-27  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * README-offline.ja : Fix.
+
+       * lisp/gnus-offline.el (gnus-offline-agent-automatic-expire):
+       Fix typo.
+
+       * lisp/gnus-ofsetup.el : Remove gnus-cus from compile time
+       requirements; Enclose the autoload for `gnus-custom-mode' with
+       `eval-and-compile'.
+
+1999-08-27  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 15.
+
+       * lisp/dgnushack.el (char-before, char-after): Optimize byte code
+       for them before lpath.el is loaded.  Because lpath.el requires
+       `poe' via `path-util'.  [cf. <tm-ja:5051>]
+
+       * lisp/gnus-sum.el (gnus-summary-search-article): Search for
+       X-Face image if the regexp "^X-Face:" is specified.
+       (gnus-summary-search-article-highlight-matched-text): Use
+       `gnus-summary-search-article-highlight-goto-x-face'; maybe display
+       X-Face image if it is requested.
+       (gnus-summary-search-article-highlight-goto-x-face): New macro.
+
+1999-08-26  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 14.
+
+       * lisp/gnus-sum.el (gnus-summary-search-article): Treat and
+       recenter the article when touchdown; popup the article buffer if
+       it is disappeared.
+       (gnus-summary-search-article-highlight-matched-text): Treat the
+       article before highlighting; use old style backquote syntax.
+       (gnus-summary-search-article-position-point): Fix the beginning
+       position; use old style backquote syntax.
+       (gnus-summary-select-article): Undo the last change.
+       (gnus-summary-display-article): Bind
+       `gnus-summary-search-article-matched-data' in the article buffer
+       locally.  It is moved from `gnus-summary-select-article'.
+
+1999-08-25  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * texi/Makefile.in (EMACS): Use @EMACS@, not emacs directly.
+       (clean): Remove formatted info files.
+       (distclean): Just remove Makefile.
+
+1999-08-25  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 13.
+
+       * lisp/gnus-agent.el (gnus-agent-large-newsgroup): New variable.
+       (gnus-agent-fetch-headers): Limit downloadable articles if the
+       number of unread articles exceeds `gnus-agent-large-newsgroup'.
+       (gnus-agent-expire): Do not expire saved or replied articles when
+       `gnus-agent-expire-all' is nil.
+
+       * lisp/gnus-offline.el (gnus-offline-agent-automatic-expire): New
+       variable.
+       (gnus-offline-agent-expire): Check it; Bind
+       `gnus-agent-expire-all' to nil if `gnus-agent-expire-days' is 0.
+       (gnus-offline-after-jobs-done): Don't check
+       `gnus-agent-expire-all'.
+
+       * lisp/gnus-ofsetup.el (gnus-offline-setting-file): Check if
+       `user-login-name' and `user-real-login-name' returns the same
+       value or not.
+       (gnus-ofsetup-prepare-for-miee): Write forms as a variable.
+       (gnus-ofsetup-update-setting-file): Ditto.
+       (gnus-ofsetup-prepare): New macro.
+       (gnus-setup-for-offline): Use it.
+       (gnus-ofsetup-customize-done): Ditto.
+
+1999-08-25  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 12.
+
+       * lisp/gnus-sum.el (gnus-summary-search-article): Rearrange.
+       (gnus-summary-search-article-highlight-matched-text): Rearrange.
+       (gnus-summary-search-article-position-point): New macro.
+       (gnus-summary-search-article-matched-data): Rename from
+       `gnus-summary-search-article-matched-text'.
+       (gnus-summary-isearch-article): Bind `gnus-inhibit-treatment' to t;
+       use `gnus-article-show-all-headers' for exposing the visited
+       article.
+       (gnus-summary-select-article): Bind
+       `gnus-summary-search-article-matched-data' in the article buffer
+       locally.
+
+       * lisp/gnus-art.el (gnus-treat-article): Don't treat the article
+       if the value of `gnus-inhibit-treatment' is non-nil.
+       (article-toggle-headers): Don't redisplay X-Face if the value of
+       `gnus-inhibit-treatment' is non-nil.
+       (gnus-article-treat-custom): Add new treatment variable `mime'.
+
+1999-08-25  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-group.el (gnus-group-line-format): Fix typo in
+       documentation.
+
+       * lisp/gnus-sum.el (gnus-summary-mode): Don't set
+       `gnus-newsgroup-incorporated' explicitly.
+
+1999-08-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * README.semi: Update for the recent a-ftp sites and directories.
+       * README.semi.ja: Ditto.
+       * texi/gnus-faq.texi: Ditto.
+       * texi/gnus-faq-ja.texi: Ditto.
+
+1999-08-24  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 11.
+       (gnus-summary-incorporated-face): New face spec.
+
+       * lisp/gnus-group.el (gnus-group-line-format-alist): Add
+       entry about the format specifier `w'.
+       (gnus-group-line-format): Fix documentation.
+
+       * lisp/gnus-sum.el (gnus-summary-highlight): Highlight lines on
+       newly incorporated mails with `gnus-summary-incorporated-face'.
+       (gnus-newsgroup-incorporated): New variable.
+       (gnus-summary-local-variables): Add `gnus-newsgroup-incorporated'.
+       (gnus-summary-mode): Set `gnus-newsgroup-incorporated'.
+
+       * lisp/nnmail.el (nnmail-new-mail-numbers): New function.
+
+       * lisp/gnus-srvr.el (gnus-browse-foreign-server): Don't prepend
+       `K' if the group has already been subscribed.
+
+1999-08-24  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-isearch-article): Set
+       `isearch-lazy-highlight' t in the buffer locally; goto the
+       beginning of the buffer before searching.
+
+       * lisp/gnus-util.el (gnus-eval-in-buffer-window): Select the last
+       selected frame.
+
+1999-08-23  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 10.
+
+       * lisp/gnus-sum.el (gnus-summary-search-article): Highlight
+       matched text after the searching is done; call
+       `gnus-summary-select-article' with the args nil and t; bind
+       `gnus-treat-*' to nil.
+       (gnus-summary-search-article-highlight-matched-text): New macro
+       for highlighting matched text.  It is bound at the compile time
+       only.
+       (gnus-summary-isearch-article): Call `gnus-summary-select-article'
+       with the args nil and t; bind `gnus-treat-*' to nil.
+
+       * lisp/gnus-ems.el (gnus-x-splash): Change the foreground color of
+       `gnus-splash' to "Brown"; use `with-temp-buffer' instead of
+       `with-temp-file'; use `insert-file-contents-as-binary' instead of
+       `insert-file-contents'.
+
+1999-08-20  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-offline.el: Fix comments.
+       (TopLevel): Delete the code for emulating custom. Do not inhibit
+       byte-compile-warnings, but hide useless ones.
+       (gnus-offline-dialup-program-arguments): defvar instead of
+       defcustom.
+       (gnus-offline-hangup-program-arguments): Ditto.
+       (gnus-offline-interval-time): Ditto.
+       (gnus-offline-dialup-program, gnus-offline-hangup-program,
+       gnus-offline-drafts-queue-type, gnus-offline-MTA-type): defvar.
+       (gnus-offline-disable-fetch-mail): Remove pop3-fma dependent
+       codes.
+       Set `mail-sources' instead of `nnmail-spool-file'.
+       (gnus-offline-enable-fetch-mail): Ditto.
+       (gnus-offline-toggle-movemail-program): Abolish.
+       (gnus-offline-define-menu-and-key): Modify according to it.
+       (gnus-offline-define-menu-on-miee): Ditto.
+       (gnus-offline-define-menu-on-agent): Ditto.
+       (gnus-offline-message-add-header): Bind temporary variables.
+       (gnus-offline-add-custom-header): Ditto.
+       (gnus-offline-restore-mail-group-level): Ditto.
+
+       * lisp/gnus-ofsetup.el (TopLevel): Require gnus-cus and
+       gnus-offline at the compile time. Do not inhibit
+       byte-compile-warnings.
+       (gnus-setup-for-offline): Really bind all temporary variables.
+       (gnus-ofsetup-write-settting-file): Check if interval is a
+       integer.
+       Use `mail-sources' instead of `nnmail-spool-file'.
+       (gnus-ofsetup-update-setting-file): Redefine as a macro.
+       (gnus-ofsetup-prepare-for-miee): Ditto.
+
+       * README-offline.en : Update.
+       * README-offline.ja : Ditto.
+
+1999-08-20  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-sum.el (gnus-wheel-summary-scroll): Bind
+       `inhibit-read-only' to t; bind `buffer-read-only' to nil.
+
+1999-08-20  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 08.
+
+1999-08-19  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/nnmail.el (nnmail-split-it): Match whole word for getting
+       group name with `\N'.
+
+1999-08-19  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 07.
+
+       * lisp/pop3.el (pop3-except-header-regexp): New variable.
+       (pop3-movemail): Don't retrieve messages whose headers are
+       matching `pop3-except-header-regexp'.
+       (pop3-top): New function.
+       (pop3-retr): Don't use `save-restriction'.
+
+1999-08-18  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/pop3.el (pop3-get-extended-response): Fix regexp.
+
+1999-08-18  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 06.
+
+       * lisp/gnus-art.el (mime-preview-over-to-next-method-alist): Use
+       `gnus-article-next-page' when the last page is not displayed.
+       (mime-preview-over-to-previous-method-alist): Use
+       `gnus-article-prev-page' when the first page is not displayed.
+       (gnus-next-page-map): Use `make-sparse-keymap' instead of
+       `make-keymap'; don't use `suppress-keymap'.
+       (gnus-insert-next-page-button, gnus-insert-prev-page-button):
+       Succeed to the value of the text property `mime-view-situation' in
+       the Next/Prev buttons; make `gnus-{next|prev}-page-map' have the
+       current local map as a parent under FSF Emacsen.
+
+1999-08-18  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/pop3.el (pop3-retr): Undo last change.
+
+1999-08-17  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 05.
+
+       * lisp/pop3.el (pop3-get-extended-response): Enable timeout of
+       `accept-process-output'; Move point to the end of the normal
+       response.
+       (pop3-movemail): Add suffix to `pop3-uidl-file-name'.
+       (pop3-get-list): Abolish.
+       (pop3-retr): Don't use `save-restriction'.
+       (pop3-uidl): Don't use `condition-case' when checking UIDL support.
+       (pop3-list): Likewise.
+
+1999-08-17  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 04.
+
+       * lisp/gnus-sum.el (gnus-wheel-summary-scroll): Use
+       `event-basic-type' instead of `event-button' under FSF Emacsen.
+
+1999-08-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 03.
+
+1999-08-16  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * lisp/gnus-sum.el: Add `gnus-wheel-install' to
+       `gnus-summary-mode-hook'.
+       (gnus-use-wheel): New variable.
+       (gnus-wheel-scroll-amount): New variable.
+       (gnus-wheel-edge-resistance): New variable.
+       (gnus-wheel-summary-scroll): New function.
+       (gnus-wheel-install): New function.
+
+1999-08-16  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 02.
+
+       * lisp/nnheader.el (make-full-mail-header-from-decoded-header): Use
+       `defun' instead of `defsubst'.
+       (make-full-mail-header): Ditto.
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Fold up long lines.
+       (TopLevel): Autoload "texinfmt" for avoiding byte compile warning.
+
+1999-08-16  Tsukamoto Tetsuo  <czkmt@remus.dti.ne.jp>
+
+       * lisp/gnus.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-draft.el (gnus-group-send-drafts): Say which message
+       is being sent.
+
+       * lisp/gnus-ofsetup.el (gnus-ofsetup-completing-read-symbol): New
+       function from Nana-gnus.
+       (gnus-setup-for-offline): Rewrite. Bind all temporary variables.
+       (gnus-ofsetup-update-setting-file): Rename from
+       `gnus-ofsetup-write-setting-file'.
+       (gnus-ofsetup-find-parameters): Rename from
+       `gnus-ofsetup-parameters'.
+       (gnus-ofsetup-customize-done): Rewrite.
+
+1999-08-15  Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * pop3.el: Sync up with pop3.el version 2.04.
+       (pop3-leave-mail-on-server): New variable.
+       (pop3-maximum-message-size): New variable.
+       (pop3-uidl-file-name): New variable.
+       (pop3-uidl-support): New variable.
+       (pop3-uidl-obarray): New variable.
+       (pop3-movemail): Check message size on every retrieval.
+       (pop3-open-ssl-stream-1): Use new style macro.
+       (pop3-get-message-numbers): New function.
+       (pop3-get-list): New function.
+       (pop3-get-uidl): New function.
+       (pop3-get-unread-message-numbers): New function.
+       (pop3-save-uidls): New function.
+       (pop3-retr): Use `pop3-get-extended-response'.
+       (pop3-list): New implementation.
+       (pop3-uidl): New function.
+       (pop3-get-extended-response): New function.
+
+1999-08-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * lisp/gnus.el: T-gnus 6.13.0 is released.
+
+1999-08-04  Katsumi Yamaoka   <yamaoka@jpl.org>
+
+       * ChangeLog.2: New file, rename from ChangeLog.
+
+       * lisp/dgnushack.el (TopLevel): Rearrange.
+
+       * README.branch.ja: Update for t-gnus-6_12 and t-gnus-6_13 branch.
+       * README.branch: Ditto.
+
+       * texi/gnus-faq.texi: Replace ftp.jaist.ac.jp with ftp.etl.go.jp.
+
+       * texi/gnus-faq-ja.texi: Modify for T-gnus 6.13.
+       * texi/message-ja.texi: Ditto.
+       * texi/message.texi: Ditto.
+       * texi/gnus-ja.texi: Ditto.
+       * texi/gnus.texi: Ditto.
+       * README-offline.ja: Ditto.
+       * README-offline.en: Ditto.
+       * README.semi.ja: Ditto.
+       * README.semi: Ditto.
+       * README.T-gnus: Ditto.
+
+       * t-gnus-6_13: NEW PUBLIC BRANCH.
+
+See ChangeLog.2 for earlier changes.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/ChangeLog.4 b/ChangeLog.4
new file mode 100644 (file)
index 0000000..aacb375
--- /dev/null
@@ -0,0 +1,2822 @@
+2003-05-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.24 revision 00.
+
+2003-05-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * etc/gnus-tut.txt (http): Update.
+
+2003-05-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.23 revision 00.
+
+2003-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Add prefix limit feature.
+
+2003-05-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.22 revision 00.
+
+2003-05-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.20 revision 00.
+
+2003-04-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * GNUS-NEWS: Added Article Buttons.  Added Upgrading (from Simon
+       Josefsson).  Add gnus-mime-delete-part, markup fixes and some
+       other corrections.  Mention Gnus FAQ.
+
+2003-04-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * GNUS-NEWS: Additions.
+
+2003-04-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Bind `default-mime-charset-unlimited'.
+
+2003-04-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Autoload font-lock and nnheader for XEmacs
+       -no-autoloads.
+
+       * lisp/pop3.el: Require `advice' for compiling it in Gnus.
+
+2003-04-28  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * GNUS-NEWS: Fixed X-Draft-Headers entry.
+
+2003-04-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Make sure `dolist' is available; require
+       `advice' before `path-util'; revoke the bogus change of 2003-04-17
+       (removing function bindings for XEmacs).
+       (dgnushack-remove-extra-files-in-package): Clear the value for
+       `command-line-args-left'.
+       (dgnushack-install-package-manifest): Ditto.
+
+       * texi/infohack.el: Load dgnushack.el and ptexinfmt.el first.
+
+2003-04-27  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Fix PGP entry.  Doc GCC variable change.
+
+2003-04-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.19 revision 00.
+
+2003-04-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-coding-system-p): New function.
+       (mm-coding-system-p): Alias to `nnheader-coding-system-p'.
+
+2003-04-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (coerce, copy-list, merge, string, subseq):
+       Comment out those compiler macros.
+       (mapc): Make it comeback.
+
+2003-04-22  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * make.bat: Flag as binary to ensure DOS line terminators.  Delete
+       trailing whitespace.
+
+2003-04-21  Reiner Steib  <Reiner.Steib@gmx.de>
+       From Frank Schmitt  <ich@frank-schmitt.net>
+
+       * etc/gnus-tut.txt: Update Gnus FAQ, delete trailing whitespace.
+
+2003-04-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * Makefile.in (xclever-package, xlick-package): New rules.
+       (install-package, install-package-ja, package, package-ja): Use
+       them.
+       (install-package-manifest, remove-extra-files-in-package,
+       compose-package): Specify the lisp directory for XEmacs package.
+
+       * aclocal.m4 (AC_PATH_INFO_DIR): Say a note for XEmacs package.
+
+       * lisp/dgnushack.el: Remove useless function bindings for XEmacs.
+       (dgnushack-install-package-manifest): Create the pkginfo directory.
+
+       * lisp/lpath.el: Fbind `compare-strings' for Mule 2.
+
+2003-04-17  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * make.bat: Cleaned up end-of-line characters.
+
+2003-04-17  Steve Youngs  <youngs@xemacs.org>
+
+       * Makefile.in (XEMACS): Use @EMACS@.
+
+       * aclocal.m4 (AC_PATH_LISPDIR): Set $datadir to $prefix/lib if
+       building with XEmacs.
+
+       * aclocal.m4 (AC_SET_BUILD_FLAGS): New.  So we can set XEmacs
+       command line options to '-batch -no-autoloads...' for a cleaner
+       build environment.
+
+       * configure.in: Use it.
+
+       * configure: Regenerate.
+
+2003-04-16  Reiner Steib  <Reiner.Steib@gmx.de>
+       From Frank Schmitt  <ich@frank-schmitt.net>
+
+       * make.bat: New variable EMACS_ARGS.  Changed XEmacs args.
+
+2003-04-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `coding-system-base' for Mule 2.
+
+2003-04-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.18 revision 00.
+
+       * lisp/message.el (message-forward-subject-name-subject): Rewrite.
+
+       * lisp/mail-source.el (mail-source-fetch-pop): Require `pop3'
+       explicitly.
+       (mail-source-check-pop): Ditto.
+
+2003-04-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnmail.el (nnmail-split-it): Revoke the change of 1999-08-19.
+
+2003-04-03  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-uidl-support): Default to nil; change the
+       meaning of a value which it may contain into an alist of servers
+       and flags of whether they support UIDLs.
+       (pop3-get-message-numbers): Don't check uidls when
+       `pop3-leave-mail-on-server' is nil; synch it with the change of
+       `pop3-uidl-support'.
+       (pop3-get-uidl): Synch it with the change of `pop3-uidl-support'.
+
+2003-03-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.17 revision 00.
+
+2003-03-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-x-face-command): Don't examine
+       functions if `noninteractive'.
+       (gnus-article-should-use-smiley-mule): Don't examine values if
+       `noninteractive'.
+       (gnus-treat-display-face): Default to nil if x-face-e21 is
+       available.
+       (gnus-treat-display-smileys): Don't examine values if
+       `noninteractive'.
+
+       * lisp/message.el (message-yank-original): Check not only the
+       References field but the `message-reply-headers' variable.
+
+       * lisp/imap.el (imap-tls-open): Don't bind coding-systems; use
+       `set-buffer-multibyte' instead of `imap-disable-multibyte'.
+
+       * lisp/tls.el: Require `pces'.
+       (open-tls-stream): Use `as-binary-process'.
+
+2003-03-23  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Add IDNA.  Add TLS.  Fix USEFOR reference.
+
+2003-03-22  Frank Schmitt  <ich@frank-schmitt.net>
+
+       * make.bat: Redone from scratch; supports both Emacs and XEmacs
+       now; correctly generate gnus-load.el; check for errors; use
+       makeinfo if available, infohack.el if it isn't; be less verbose
+       when copying files; copy files from etc/gnus and etc/smilies, too
+
+2003-03-22  Frank Schmitt  <ich@frank-schmitt.net>
+
+       * make-x.bat: Removed, make.bat does its job now.
+
+2003-03-22  Frank Schmitt  <ich@frank-schmitt.net>
+
+       * etc/gnus-tut.txt: Include Gnus FAQ from http://my.gnus.org.
+
+2003-03-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.16 revision 00.
+
+2003-03-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-ofsetup.el: Don't require `read-passwd'; don't set
+       `mail-source-read-passwd' and `gnus-setup-news-hook'.
+
+       * contrib/passwd.el: New file.
+
+2003-02-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-offline.el (gnus-offline-add-custom-header): Use
+       insert instead of insert-string which is obsolete in Emacs 21.4
+       (synch to the change of Jesper Harder at 2003-02-20).
+
+2003-02-19  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * GNUS-NEWS: Renamed `gnus-unsightly-citation-regexp' to
+       `gnus-cite-unsightly-citation-regexp'.
+
+2003-02-18  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Talk about canlock more.
+
+2003-02-13  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * GNUS-NEWS: Add user visible changes from Michael Shields from
+       the past couple of days.  Actual text from Michael.
+
+2003-02-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.15 revision 00.
+
+2003-01-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.14 revision 00.
+
+2003-01-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * etc/gnus-tut.txt: Update.
+
+2003-01-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el (infohack-texi-format): Withdraw the change of
+       2003-01-17.
+
+2003-01-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.13 revision 00.
+
+2003-01-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/infohack.el (infohack-texi-format): Insert one excessive
+       newline after a @foo{bar} thing to prevent clinging of a line and
+       a line (old texinfmt bug?) if it should be considered only one
+       thing in a line.
+
+2003-01-17  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * .cvsignore: Import from Oort Gnus.
+       * contrib/.cvsignore: Ditto.
+       * etc/.cvsignore: Ditto.
+       * lisp/.cvsignore: Ditto.
+       * texi/.cvsignore: Ditto.
+       * texi/ps/.cvsignore: Ditto.
+
+2003-01-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-digest-mail-forward): Set article
+       numbers to be marked.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       (A forgotten thing to synchronize to Oort Gnus.)
+       * lisp/gnus-msg.el (gnus-summary-mail-forward): To many lists of
+       lists.
+
+2003-01-15  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Add.  Fix from Reiner Steib
+       <4uce.02.r.steib@gmx.net>.
+
+2003-01-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/binhex.el: Require `path-util'.
+       * lisp/gnus-audio.el: Ditto.
+       * lisp/spam.el: Ditto.
+       * lisp/uudecode.el: Ditto.
+
+       * lisp/binhex.el (binhex-use-external): Replace `executable-find'
+       with `exec-installed-p'.
+       * lisp/gnus-audio.el (gnus-audio-au-player): Ditto.
+       (gnus-audio-wav-player): Ditto.
+       * lisp/spam.el (spam-ifile-path): Ditto.
+       (spam-bogofilter-path): Ditto.
+       * lisp/uudecode.el (uudecode-use-external): Ditto.
+
+       * lisp/gnus-int.el (gnus-agent-expire): Make arguments optional.
+
+2003-01-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-util.el (gnus-read-event-char): Take an optional
+       parameter even if Mule 2.3 is running.
+
+2003-01-10  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * make.bat: Removed "-no-init-file" (it's the same as "-q").  Use
+       new variables EMACSBATCH and GNUS_INFO_DIR.  Install gnus-?,
+       message-?, sieve and pgg (in texi).  Added hint for dir entries.
+
+       * make-x.bat: Ditto.
+
+2003-01-13  Simon Josefsson  <jas@extundo.com>
+
+       * GNUS-NEWS: Add smileys, Sender:, message-utils.
+       Expand anti-spam.  Fixes.
+
+2003-01-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.12 revision 00.
+
+2003-01-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.11 revision 00.
+
+2003-01-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus.art.el (gnus-treat-predicate): Don't follow the Change
+       of Oort Gnus at 2003-01-02; reverted.
+
+       * lisp/message.el (message-tool-bar-map): Commented out MIME-Edit
+       buttons.
+
+2003-01-09  Simon Josefsson  <jas@extundo.com>
+
+       * etc/gnus/preview.xpm: Add.
+
+2003-01-06  Simon Josefsson  <jas@extundo.com>
+
+       * etc/gnus/receipt.xpm: Add.
+
+2003-01-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * etc/gnus/preview.xbm: Add.
+
+2003-01-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-tool-bar-map): Fix keymap for MIME-Edit.
+
+2003-01-09  NAKAJI Hiroyuki  <nakaji@tutrp.tut.ac.jp>
+
+       * README.semi.ja: "What's T-gnus?" is revised.
+
+       * README.semi: Ditto.
+
+2003-01-07  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/message.el (message-setup-1): Don't call
+       `message-use-alternative-email-as-from' if it isn't for replying.
+
+2003-01-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * etc/gnus/gnus.xpm (oort): Make the color replaceable.
+
+2003-01-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.10 revision 00.
+
+2003-01-03  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Bind the
+       color for the symbol `oort' as `gnus-group-startup-message' does.
+
+2002-12-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-re-read-newsrc-el-file): Commented out.
+       (gnus-load): Allow coding-system as an argument.
+
+2002-12-16  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/nnimap.el (nnimap-callback): Use `nnimap-demule'.
+       (nnimap-request-article-part): Ditto.
+
+2002-12-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/Makefile.in (%.info, .texi): Conceal control procedures.
+
+2002-12-05  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * etc/smilies/*.pbm: Made them binary.
+
+2002-11-28  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-headers): Don't refer to
+       the value of `gnus-agent-file-name'.
+
+2002-11-28  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-agent.el (gnus-agent-fetch-group-1): Article numbers
+       should be accessed through `mail-header-number'.
+
+2002-11-24  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/mm-url.el (mm-url-program): Use `exec-installed-p' instead of
+       `executable-find'.
+
+2002-11-13  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * etc/smilies/blink.xpm: Changed smileys and some new ones from
+       Alex Schroeder <alex@emacswiki.org>.
+
+2002-11-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-inherit-default-charset): Inherit
+       the value for `default-mime-charset-unlimited' as well.
+       (gnus-summary-setup-default-charset): Bind
+       `default-mime-charset-unlimited' to nil for nndraft:delayed or
+       nndraft:drafts groups.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Don't use
+       MIME-View for nndraft:delayed or nndraft:drafts groups.
+       (gnus-article-decode-article-as-default-mime-charset): Don't
+       decode an article for nndraft:delayed or nndraft:drafts groups.
+
+2002-11-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nndraft.el (nndraft-request-article): Don't give a special
+       treatment to Mule.
+
+       * lisp/nnheader.el (nnheader-auto-save-coding-system): Undo last
+       change to restore the default value to emacs-mule or escape-quoted.
+
+2002-11-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-article-setup): Don't
+       perform `mime-edit-again' for a delayed or a queued article.
+       (gnus-article-mime-edit-done): Bind `inhibit-read-only' to t while
+       running `gnus-article-edit-done'.
+
+2002-10-30  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/dgnushack.el (dgnushack-bind-colon-keywords): Protect
+       against unexpected data structure.
+
+2002-10-30  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el: Clean up codes.
+       (nnshimbun-buffer, nnshimbun-current-directory)
+       (nnshimbun-current-group, nnshimbun-server-directory): Removed.
+       (nnshimbun-current-server, nnshimbun-server-directory)
+       (nnshimbun-current-group, nnshimbun-current-directory): New macros.
+       (nnshimbun-backlog, nnshimbun-find-parameter): Use
+       `nnshimbun-current-server'.
+       (nnshimbun-possibly-change-group, nnshimbun-open-server):
+       Reimplemented.
+       (nnshimbun-close-server): Do not kill `nnshimbun-buffer'.
+       (nnshimbun-request-article-1, nnshimbun-request-list): Use
+       `erase-buffer' instead of `delete-region'.
+       (nnshimbun-request-article): Use `nnshimbun-current-group'.
+       (nnshimbun-request-group): Remove redundant checks.
+       (nnshimbun-request-scan): Check arguments strictly.
+       (nnshimbun-retrieve-headers, nnshimbun-retrieve-headers-with-nov):
+       Reimplemented.
+       (nnshimbun-generate-nov-database, nnshimbun-search-id)
+       (nnshimbun-write-nov, nnshimbun-request-expire-articles):
+       Simplified.
+       (nnshimbun-nov-buffer-name, nnshimbun-nov-file-name): Make the
+       first argument optional.
+       (nnshimbun-open-nov): Bind variables to set coding systems for
+       path names.
+       (nnshimbun-possibly-change-group, nnshimbun-request-article)
+       (nnshimbun-write-nov): Strict checking.
+       (nnshimbun-request-expire-articles): Small fix.
+
+2002-10-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 05.
+
+       * lisp/nnheader.el (nnheader-auto-save-coding-system): Default to
+       `iso-2022-7bit'.
+
+2002-10-29  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-article-1): Install trick
+       to keep compatibility between T-gnus and Oort Gnus.
+
+2002-10-29  Tadashi Watanabe  <watanabe@sigmaitec.co.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Do not
+       use removed variables.
+
+2002-10-29  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el: Clean up.
+       (nnshimbun-nov-last-check): Removed.
+       (nnshimbun-nov-buffer-alist): Removed.
+       (nnshimbun-nov-buffer-file-name): Removed.
+       (nnshimbun-close-server): Use `nnshimbun-write-nov' instead of
+       `nnshimbun-save-nov'.
+       (nnshimbun-mail-header-subject): Removed.
+       (nnshimbun-mail-header-from): Removed.
+       (nnshimbun-make-shimbun-header): Removed.
+       (nnshimbun-parse-nov): New function.
+       (nnshimbun-request-article-1): Use `nnshimbun-parse-nov' instead
+       of `nnheader-parse-nov'.
+       (nnshimbun-retrieve-headers): Likewise.
+       (nnshimbun-nov-buffer-name): New function.
+       (nnshimbun-nov-file-name): Ditto.
+       (nnshimbun-open-nov): Clean up.
+       (nnshimbun-write-nov): Ditto; Aceept the 2nd optional argument.
+       (nnshimbun-save-nov): Removed.
+
+2002-10-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-dont-compile-files): New constant
+       containing almost all mm*.el.
+       (dgnushack-compile): Don't byte-compile the file in
+       `dgnushack-dont-compile-files'.
+
+2002-10-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 04.
+       (gnus-version): T-gnus supports SEMI 1.14 and FLIM 1.14.
+
+       * lisp/mmgnus.el: Remove commented obsolete definitions.
+
+       * lisp/message.el (message-header-hook): Replace
+       `eword-encode-header' with `mime-encode-header-in-buffer'.
+       (message-send-mail-with-smtp): Don't use `smtp-via-smtp'.
+
+2002-10-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/mm-url.el (mm-url-form-encode-xwfu): Use
+       `file-coding-system' instead of `buffer-file-coding-system' when
+       Mule 2 is running.
+
+       * lisp/gnus-group.el: Require `mm-url' only when compiling.
+       (gnus-group-fetch-charter): Require `mm-url'.
+
+       * lisp/gnus.el (gnus-default-charset): Default to `iso-8859-1'.
+
+2002-09-13  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnheader.el (toplevel) [XEmacs]: Remove code to define
+       `emacs-mule' coding-system, because the generated coding system is
+       not compatible to the original coding system of FSF Emacs.
+
+2002-09-12  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnheader.el (toplevel) [XEmacs]: Define `emacs-mule' coding
+       system in order to cancel difference on coding systems of
+       auto-saved files between FSF Emacs and XEmacs.
+       (nnheader-auto-save-coding-system) [Mule]: The default value of
+       Mule2 is changed from `*junet*' to `*internal*', in order to unify
+       coding system of files auto-saved by Mule2.
+
+2002-09-08  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-msg.el (gnus-configure-posting-styles): Follow the
+       change of arglist of gnus-configure-posting-style.
+       (gnus-configure-posting-style): Check circular import.
+
+2002-09-08  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-msg.el (gnus-named-posting-styles): Defcustom.
+       (gnus-posting-styles): Allow (import "...").
+       (gnus-configure-posting-style): Splitted from
+       gnus-configure-posting-styles.
+       (gnus-summary-execute-command-with-posting-style): Fix prompt string.
+
+       * lisp/gnus-cus.el (gnus-group-parameters): Allow (import "...")
+       in posting-styles.
+
+2002-09-08  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-msg.el (gnus-named-posting-styles): New variable.
+       (gnus-summary-send-map): Bind "P" to
+       gnus-summary-execute-command-with-posting-style.
+       (gnus-configure-posting-styles): Expand named entries in
+       gnus-posting-styles.
+       (gnus-summary-execute-command-with-posting-style): New command.
+
+2002-09-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Set a copy buffer
+       mutibyte; remove invisible and intangible test properties from a
+       copied article.
+
+2002-09-05  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * texi/ptexinfmt.el: discard @documentdescription.  Support
+       @ifplaintext, @ifnotplaintext, @ifhtml.  Remove obsolete commands.
+       (texinfo-format-ifhtml, texinfo-format-ifplaintext): New function.
+
+2002-09-04  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/highlight-words): Stricten
+       regular expression to highlight keywords.
+
+2002-08-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `smtpmail-send-it' for Mule 2.
+
+2002-08-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-util.el (frame-parameter): New function for oldies.
+
+2002-08-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-frame): Remove.
+
+2002-08-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: Fix T-gnus version number.
+
+2002-08-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.8 revision 00.
+
+2002-08-06  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-update-index): Handle error
+       messages printed by Namazu.
+       (gnus-namazu/update-sentinel): Likewise.
+       (gnus-namazu-need-path-normalization): Change its default value.
+       (gnus-namazu/normalize-results): Remove `file://' prefix.
+
+       * texi/gnus-ja.texi (Namazu Groups): Update documents.
+
+       * lisp/gnus-namazu.el (gnus-namazu/update-p): Print error
+       messages.
+       (gnus-namazu-update-index): Small clean up.
+       (gnus-namazu-update-all-indices): Ditto.
+
+2002-08-05  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el: Bug fix of updating multiple indices.
+       (gnus-namazu/setup): Call `gnus-namazu-update-all-indices' without
+       arguments.
+       (gnus-namazu-create-index): Clean temporary files even if an
+       indexer is killed.
+       (gnus-namazu/update-p): New function.
+       (gnus-namazu-update-all-indices): Reimplemented.
+       (gnus-namazu-update-index): Call `gnus-namazu/update-p' to decide
+       whether the specified index will be updated.
+       (gnus-namazu/update-sentinel): Follow the change of
+       `gnus-namazu-update-all-indices'.
+
+2002-08-05  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus.el (toplevel): Add autoloads for
+       `gnus-namazu-create-index', and `gnus-namazu-update-all-indices'
+       and `gnus-namazu-update-index'.
+
+       * lisp/gnus-namazu.el: Support automatically updating multiple
+       indices.
+       (gnus-namazu-make-index-interval): Abolished.
+       (gnus-namazu-index-update-interval): New option.
+       (gnus-namazu/setup): Call `gnus-namazu-update-all-indices' instead
+       of `gnus-namazu-make-index'.
+       (gnus-namazu/mknmz-process): Abolished.
+       (gnus-namazu/status-file-name): New macro.
+       (gnus-namazu-make-index, gnus-namazu-make-index-stop,
+       gnus-namazu/mknmz-sentinel): Removed.
+       (gnus-namazu/mknmz-cleanup, gnus-namazu/index-old-p): New function.
+       (gnus-namazu-create-index, gnus-namazu-update-all-indices,
+       gnus-namazu-update-index, gnus-namazu-stop-update): New command.
+       (gnus-namazu/update-directories, gnus-namazu/update-process): New
+       internal variable.
+
+2002-07-31  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el: Support automatically updating index.
+       (gnus-namazu-default-index-directory): New constant.
+       (gnus-namazu-make-index-interval, gnus-namazu-make-index-command,
+       gnus-namazu-make-index-arguments): New options.
+       (gnus-namazu/setup): Call `gnus-namazu-make-index'.
+       (gnus-namazu/real-group-name): Renamed from
+       `gnus-namazu/check-cache-group'.
+       (gnus-namazu/cache-group-candidates): Renamed from
+       `gnus-namazu/cache-group-candidates'.
+       (gnus-namazu/search): Experimental support of articles covered by
+       agent.
+       (gnus-namazu/default-index-directory, gnus-namazu/lapse-seconds,
+       gnus-namazu/mknmz-sentinel): New internal functions.
+       (gnus-namazu/mknmz-process): New internal variable.
+       (gnus-namazu/lock-file-name, gnus-namazu/index-file-name): New
+       macros.
+       (gnus-namazu-make-index, gnus-namazu-make-index-stop): New
+       commands.
+
+2002-07-30  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/request-list): Removed.
+       (gnus-namazu/get-current-to): New function.
+       (gnus-namazu/complete-query): Call the above.
+
+2002-07-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el: Don't autoload "ssl".
+       (pop3-open-ssl-stream-1): Require `ssl' before binding ssl-* vars.
+
+2002-07-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/truncate-article-list): Remove
+       a redundancy.
+
+2002-07-11  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * texi/gnus-ja.texi (Web Newspaper): Update the url of w3m.
+
+2002-07-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-mode-map): Replace
+       `gnus-article-toggle-headers' with `gnus-summary-toggle-header'.
+       (gnus-summary-wash-map): Ditto.
+       (gnus-summary-wash-hide-map): Replace
+       `gnus-article-toggle-headers' with `gnus-article-hide-headers'.
+       (gnus-summary-article-menu): Ditto.
+
+       * lisp/gnus.el: Remove autoload for `gnus-article-toggle-headers'.
+
+       * lisp/gnus-art.el (article-toggle-headers): Abolished.
+
+2002-07-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (byte-optimize-form-code-walker): Don't modify
+       the function definition if the bug has already gone; revert to the
+       use of `defadvice'.
+
+2002-07-03  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-logic.el (gnus-advanced-index): Use luna based index
+       numbers.
+
+2002-06-26  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * lisp/imap.el (imap-ssl-open-2): Do away with w32-related
+       workaround I installed on 1999-12-28, i.e. also call
+       `as-binary-process' in windows-nt.
+
+2002-06-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * contrib/hashcash.el: Require `cl' when compiling.
+       (hashcash-strip-quoted-names): Replace `subseq' with `substring'.
+       (mail-add-payment): Allow no `mail-header-separator' in the buffer;
+       don't use `mapc'.
+
+2002-06-25  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/truncate-article-list): When
+       `gnus-large-newsgroup' is equal to nil, no confirmation is
+       required.
+
+2002-06-23  Tetsuo Tsukamoto  <czkmt@remus.dti.ne.jp>
+
+       * lisp/pop3.el (pop3-open-ssl-stream): Do away with w32-related
+       workaround I installed on 1999-12-27, i.e. also call
+       `as-binary-process' in windows-nt.
+
+2002-06-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send): Kill `message-encoding-buffer'
+       even if sending failed.
+
+2002-06-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-msg.el (gnus-message-setup-hook): Default to nil.
+       (gnus-setup-message): Run `gnus-maybe-setup-default-charset'.
+       (gnus-summary-supersede-article): Don't bind the value for
+       `gnus-message-setup-hook'.
+       (gnus-summary-resend-bounced-mail): Ditto.
+
+       * lisp/dns.el (dns-make-network-process): Bind
+       `default-process-coding-system' to `(binary . binary)'; bind
+       `program-coding-system-alist' to nil.
+
+       * lisp/gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Bind
+       `input-coding-system' and `output-coding-system' to `binary'.
+
+       * lisp/gnus-namazu.el (gnus-namazu/call-namazu): Bind
+       `input-coding-system' and `output-coding-system' to the velue of
+       `gnus-namazu-coding-system'.
+
+       * lisp/imap.el (imap-ssl-open): Don't bind the values for
+       `input-coding-system' and `output-coding-system'.
+
+       * lisp/nnmaildir.el (nnmaildir-request-scan): Bind
+       `output-coding-system' to the value of
+       `nnheader-file-coding-system'; bind `file-coding-system' to nil.
+       (nnmaildir-request-rename-group): Ditto.
+       (nnmaildir-request-replace-article): Ditto.
+       (nnmaildir-request-accept-article): Ditto.
+       (nnmaildir-request-set-mark): Ditto.
+
+       * lisp/nnmbox.el (nnmbox-save-buffer): Simplify the source code.
+
+       * lisp/nnrss.el (nnrss-read-server-data): Bind
+       `input-coding-system' to `binary'.
+       (nnrss-save-server-data): Bind `output-coding-system' to `binary'.
+       (nnrss-read-group-data): Bind `input-coding-system' to `binary'.
+       (nnrss-save-group-data): Bind `output-coding-system' to `binary'.
+
+2002-06-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el: Add a comment for the use of `ssl' or `tls'
+       connection with Gnus; always require `pces' and `path-util' for
+       Gnus.
+       (pop3-open-ssl-stream-1): Don't require `path-util' here.
+
+2002-06-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el: Make it can be byte-compiled in the Gnus source
+       tree with neither errors nor warnings.
+       (pop3-md5): Fix the logic to check whether the built-in `md5'
+       allows the 4th argument CODING-SYSTEM.
+
+2002-06-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * contrib/gpg-ring.el: Remove RCS magic cookie.
+       * lisp/nnir.el: Ditto.
+
+       * texi/ptexinfmt.el (texinfo-discard-command-and-arg): New
+       function.
+
+2002-06-03  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * texi/ptexinfmt.el: discard @cartouche.  @anchor discard for Mule
+       2.3.  Support @., @:, @-.
+       (texinfo-format-inforef): New function.
+
+2002-05-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (nnheader-unfold-fws): New function copied from
+       `ietf-drums-unfold-fws'.
+       (ietf-drums-unfold-fws): Alias to `nnheader-unfold-fws'.
+
+2002-05-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.7 revision 00.
+
+2002-04-30  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/message.el (message-expand-name-function): New user option.
+       (message-expand-name): Use it.
+       * lisp/lpath.el: Don't bind lsdb-complete-name and bbdb-complete-name.
+
+2002-04-30  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/message.el (message-expand-name): Use lsdb-complete-name if
+       available.
+       * lisp/lpath.el: Bind lsdb-complete-name.
+
+2002-04-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-bind-colon-keywords): Also examine
+       backquote'd forms.
+
+       * lisp/nnheader.el (nnheader-with-unibyte): New macro.
+       (mm-with-unibyte): Alias to `nnheader-with-unibyte'.
+
+2002-04-26  Steve Youngs  <youngs@xemacs.org>
+
+       * aclocal.m4 (AC_PATH_INFODIR): New.  Defaults to '$prefix/info'
+       for Emacs and 'site-packages/info' for XEmacs.
+       (AC_PATH_ETCDIR): Drop 'gnus' off the end of the default directory
+       for XEmacs.
+
+       * configure.in: Use 'AC_PATH_INFO_DIR'.
+
+2002-04-23  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Disregard the
+       message cache when bbdb/news-auto-create-p is nil.
+
+2002-04-23  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Work around the
+       incompatibility with BBDB 2.3x.
+
+2002-04-22  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/message.el (message-make-user-agent): Remove product tokens
+       for gnus-vers.  [cf. <semi-gnus-ja:6798>]
+
+2002-04-22  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Tweak BBDB message
+       caching.
+       (gnus-bbdb/extract-message-sender-function): New user option.
+       (gnus-bbdb/extract-message-sender): New function.
+
+2002-04-20  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/gnus-sum.el: Don't autoload gnus-set-summary-default-charset.
+       (gnus-summary-inherit-default-charset): New function.
+       (gnus-parse-headers-hook): Use it.
+       (gnus-summary-setup-default-charset): Set default-mime-charset here.
+
+       * lisp/gnus-delay.el (gnus-delay-article): Undo the last change.
+
+       * lisp/gnus-draft.el: Revert to the original implementation.
+       (gnus-draft-edit-message): Pass restore as the 3rd argument of
+       gnus-draft-setup; call save-buffer instead of message-save-drafts.
+       (gnus-draft-setup): Rename from gnus-draft-setup-for-editing.
+       (gnus-draft-setup-for-sending): Abolish.
+
+       * lisp/nnheader.el (nnheader-auto-save-coding-system): New variable.
+
+       * lisp/message.el (message-draft-coding-system): Delegate the
+       value to nnheader-auto-save-coding-system.
+       (message-mode-map): Don't bind message-save-drafts.
+       (message-dont-send): Use save-buffer instead of message-save-buffer.
+       (message-save-drafts): Abolish.
+
+       * lisp/nndraft.el (nndraft-request-article): Revert to the
+       original implementation.
+
+2002-04-18   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-draft.el (gnus-group-send-queue): Pass group and
+       interactive as the arguments of gnus-draft-send.
+       (gnus-draft-send): Don't give "nndraft:queue" special treatment.
+
+2002-04-17   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-delay.el (gnus-delay-article): Use `message-save-drafts'
+        instead of `save-buffer'.
+
+2002-04-08  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-draft.el (gnus-draft-send): Always enter the Message
+       mode.
+
+2002-03-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-completing-read-group-name): Use
+       `mapatoms' to extract all groups from `gnus-active-hashtb'.
+
+2002-03-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-completing-read-group-name):
+       Improve to speed up.
+       (gnus-group-name-charset-group-alist): Change the default value.
+
+2002-03-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * lisp/message.el (message-save-drafts, message-check-8bit,
+       message-send-news, message-send-mail, message-send): Replace
+       `insert-buffer' with `insert-buffer-substring'.
+       * lisp/gnus-art.el (gnus-article-mime-edit-article-setup,
+       gnus-article-edit-exit, article-verify-x-pgp-sig): Ditto.
+
+2002-03-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-make-menu-bar): Don't provide
+       "View as different encoding" submenu if the function
+       `coding-system-list' is not available.
+
+2002-03-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/pop3.el (pop3-md5): Treat a given string as binary.
+
+2002-03-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-summary-resend-message-edit): Use
+       `mime-edit-again' instead of `mime-to-mml' to recompose a message.
+
+2002-03-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (mm-make-temp-file): Copied from mm-util.el.
+
+2002-03-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-fix-before-sending): Bind
+       `mm-7bit-chars' to the value that concat the original value and
+       escape.
+
+       * lisp/nnheader.el (mm-7bit-chars): Remove.
+
+2002-03-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-edit-mode): Don't call `mml-mode'.
+
+       * lisp/nnheader.el (mm-7bit-chars): Copied from mm-bodies.el.
+       (mm-multibyte-p): New alias.
+       (mm-char-int): Alias to `char-int'.
+
+2002-02-26  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-art.el (gnus-request-article-this-buffer): Sync up
+       with Oort-gnus.
+
+       * lisp/nntp.el (nntp-open-via-rlogin-and-telnet): Wrap
+       `call-process' with `as-binary-process'.
+
+2002-02-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/smiley.el (smiley-regexp-alist): Fix the order of faces.
+
+2002-02-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/smiley.el (smiley-regexp-alist): Use faces which originate
+       in etc-0.27.tar.gz if exist.
+       (gnus-smiley-file-types): Add xbm if available.
+       (smiley-region): Don't put two or more faces in one place.
+
+2002-02-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-request-article-this-buffer): Temporally
+       fix: erase the buffer before inserting (and saving) an article.
+
+2002-02-22  Steve Youngs  <youngs@xemacs.org>
+
+       * aclocal.m4 (AC_PATH_LISPDIR): Default to
+       .../site-packages/lisp/gnus for XEmacs.
+       (AC_PATH_ETCDIR): Default to .../site-packages/etc/gnus for
+       XEmacs.
+
+2002-02-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-group.el (gnus-group-name-encode): New function.
+       (gnus-group-encoded-name): New function.
+       (gnus-group-completing-read-group-name): New function.
+       (gnus-fetch-group): Use it.
+       (gnus-group-jump-to-group): Use it.
+       (gnus-group-unsubscribe-current-group): Use it.
+
+2002-02-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/nnheader.el (mm-string-as-unibyte): Undo the last change.
+       * lisp/gnus-srvr.el (gnus-browse-foreign-server): Ditto.
+
+2002-02-21   Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/nnheader.el (mm-string-as-unibyte): Alias to
+       `string-as-unibyte'.
+
+       * lisp/gnus-srvr.el (gnus-browse-foreign-server): Return unibyte
+       group names.
+
+2002-02-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Bind `navi2ch-mona-font'.
+
+2002-02-18  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/gnus-art.el (gnus-treat-monafy): New user option.
+       (article-monafy): New function.
+
+2002-02-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (std11-field-value): Fix regexp.
+
+2002-02-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-treat-display-grey-xface): Default to nil
+       under NTEmacs 21.
+
+2002-02-14  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-kill-summary-buffers): New
+       advice.
+
+2002-02-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/mm-view.el: Require `gnus-mailcap' rather than `mailcap'.
+
+       * lisp/nnheader.el (mm-with-unibyte-buffer): Bind `default-mc-flag'
+       instead of `mc-flag'.
+       (nnheader-with-unibyte-current-buffer): New macro.
+       (mm-with-unibyte-current-buffer): Alias to
+       `nnheader-with-unibyte-current-buffer'.
+       (nnheader-guess-mime-charset): New macro.
+       (mm-guess-mime-charset): Alias to `nnheader-guess-mime-charset'.
+       (shell-command-to-string): New function for old Emacsen.
+
+       * lisp/lpath.el: Don't fbind `shell-command-to-string'.
+
+2002-02-09  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/group-alist): Abolished.
+       (gnus-namazu/setup): Not set it.
+       (gnus-namazu/shutdown): Removed.
+       (gnus-namazu/group-prefixed-name): Handle case-insensitive file
+       names by itself.
+
+2002-02-09  NISHIDA Masakazu  <m_nisida@ca2.so-net.ne.jp>
+
+       * lisp/gnus-namazu.el (gnus-namazu/complete-query): Relaxed the
+       regexp which matches field search keywords.
+
+2002-02-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * etc/gnus/gnus.xpm: Remove some garbages at the end of the file.
+
+2002-02-03  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/nnir.el (nnir-run-namazu): According to SUSv3, LC_ALL is
+       prior to the other environment variables whose names are starting
+       with "LC_".  So there is no need to setting them.
+
+2002-02-03  Daiki Ueno  <ueno@unixuser.org>
+
+       * lisp/nnir.el (nnir-imap-default-charset): New user option.
+       (nnir-run-imap): Supply the charset of a search criteria.
+
+2002-02-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Suggested by Kenichi OKADA <okada@opaopa.org>
+
+       * lisp/message.el (message-save-drafts): Override
+       `mime-header-encode-method-alist'.
+
+2002-02-01  Taiji Can  <Taiji.Can@grd.advantest.co.jp>
+
+       * texi/gnus-ja.texi (Posting Styles): Fix typo.
+
+2002-01-31  ARISAWA Akihiro  <ari@atesoft.advantest.co.jp>
+
+       * lisp/gnus-art.el (gnus-article-display-traditional-message):
+       Reverted.
+
+2002-01-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-setup-buffer): Enable multibyte
+       in `gnus-original-article-buffer'.
+
+2002-01-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-cite-prefix-regexp): Fix the regexp.
+
+       * lisp/gnus-sum.el (gnus-mime-extract-message/rfc822): New
+       implementation.
+
+2002-01-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (find-cl-run-time-functions): Insert a
+       newline before filling a result; ignore non-list forms.
+
+2002-01-24  ARISAWA Akihiro  <ari@atesoft.advantest.co.jp>
+
+       * lisp/gnus-sum.el (gnus-summary-show-article): If coding-system is
+       specified, bind `default-mime-charset' to it.
+
+2002-01-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el: Require `base64' before `canlock-om' to avoid
+       damage to define `base64-encode-string' by MEL.
+
+       * lisp/dgnushack.el: Load base64.el before canlock-om.el to avoid
+       damage to define `base64-encode-string' by MEL.
+
+2002-01-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-article-commands-menu): Bind "Html" to
+       the command `gnus-article-wash-html'.
+       (gnus-summary-article-menu): Ditto.
+       (gnus-summary-wash-map): Bind "h" to the command
+       `gnus-article-wash-html'.
+
+       * lisp/gnus-art.el (gnus-article-treatment-menu): Bind
+       "Treat html" to the command `gnus-article-wash-html'.
+
+       * lisp/nnheader.el: Place mm- stuff and mail-parse stuff in front
+       of the codes which use (or may use) them.
+
+2002-01-21  ARISAWA Akihiro  <ari@mbf.sphere.ne.jp>
+
+       * lisp/gnus-art.el (gnus-article-display-traditional-message): Use
+       `set-buffer-multibyte'.
+
+2002-01-21  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-sum.el (gnus-summary-preview-mime-message): Protect
+       against dead windows.
+
+       * lisp/nnheader.el (mm-encode-coding-string): Alias to
+       `encode-coding-string'.
+       (mm-decode-coding-string): Alias to 'decode-coding-string'.
+
+2002-01-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.6 revision 00.
+
+       * lisp/nnheader.el (std11-unfold-region): New function copied from
+       `rfc2047-unfold-region'.
+       (std11-unfold-field): New function.
+       (mail-header-unfold-field): Alias to `std11-unfold-field'.
+
+2002-01-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02 (synch
+       with the released version of Oort Gnus v0.05).
+
+2002-01-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Advise `byte-compile-inline-expand' for Mule
+       to ignore built-in functions as Emacs 20+ does.
+
+2002-01-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-adjust-marked-articles): Fix the record
+       for `seen' if it looks like (seen NUM1 . NUM2).  It should be
+       (seen (NUM1 . NUM2)).
+
+2002-01-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nntp.el (nntp-send-buffer): Bind `mc-flag' to nil.
+
+       * lisp/nnheader.el (mm-with-unibyte-buffer): Alias to
+       `nnheader-with-unibyte-buffer'.
+       (nnheader-with-unibyte-buffer): New macro.
+
+2002-01-12  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * texi/gnus-ja.texi (Article Date): Update Japanese translation.
+
+2002-01-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (butlast): Fix a serious bug that it behaved
+       like `nbutlast'.  Special thanks to Keiichi-san for the great
+       discovery.
+
+       * lisp/gnus.el (gnus-product-variable-file-list): Add a check for
+       the value of `gnus-use-correct-string-widths' in the forms.
+
+       * lisp/gnus-start.el (gnus-product-quick-file-format): Include the
+       value of `gnus-use-correct-string-widths' in the file form.
+       (gnus-product-read-variable-file-1): Check for the equality in the
+       value of `gnus-use-correct-string-widths' as well.
+
+2002-01-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01 in
+       order to force update cached format specs.
+
+       * lisp/gnus-spec.el (gnus-use-correct-string-widths): Default to t.
+
+2002-01-10  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el: Adopt for old Gnusae.
+
+2002-01-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-strip-forbidden-properties): Don't
+       strip properties when the invisible MIME part is inserted.
+
+       * lisp/gnus-xmas.el (gnus-xmas-group-startup-message): Position
+       point to the top.
+
+2002-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * etc/gnus/oort.xface (X-Face): Oort X-Face from
+       Raymond Scholz <ray-2002@zonix.de>.
+
+2002-01-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `coding-system-to-mime-charset' for Mule 2.
+
+       * lisp/nnheader.el (std11-fold-region): New function copied from
+       `rfc2047-fold-region'.
+       (std11-fold-field): Use it.
+
+2002-01-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el: Don't autoload "gnus-bitmap".
+
+       * lisp/gnus-ems.el: Autoload "smiley-mule" if running Emacs
+       version is less than 21.
+
+       * lisp/gnus-art.el (gnus-article-smiley-display): Remove.
+       (gnus-treat-smiley): Reload "smiley-ems" or "smiley-mule" if
+       needed.
+       (gnus-treat-display-smileys): Use `gnus-image-type-available-p'.
+       (gnus-article-smiley-mule-loaded-p): New internal variable.
+       (gnus-article-should-use-smiley-mule): New user option.
+
+2002-01-09  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nneething.el (nneething-mime-extensions): New variable.
+       (nneething-request-article): Refer it.
+
+       * lisp/nnheader.el (mm-detect-coding-region): Alias to
+       `nnheader-detect-coding-region'.
+       (nnheader-detect-coding-region): New function.
+       (mm-detect-mime-charset-region): Alias to
+       `nnheader-detect-mime-charset-region'.
+       (nnheader-detect-mime-charset-region) New function.
+
+2002-01-08  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * texi/gnus-ja.texi (Web Newspaper): Update the document of
+       mime-w3m.el.
+
+2002-01-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-toggle-headers): Expose headers even
+       if there is a boundary line.
+
+       * lisp/nntp.el (nntp-send-buffer): Don't use
+       `mm-with-unibyte-current-buffer'.  Use expanded form instead.
+
+       * lisp/gnus-art.el (gnus-treatment-function-alist): Move X-Face
+       stuff down after unfolding stuff.
+
+2002-01-08  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu/highlight-words): Reimplemented.
+
+2002-01-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (mail-narrow-to-head): Copy from ietf-drums.el;
+       it should go to the beginning of the header after narrowing.
+       (std11-extract-addresses-components): Protect against nil argument.
+
+2002-01-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (mail-header-field-value): Alias to
+       `std11-field-value'.
+       (std11-field-value): New function.
+
+2002-01-08  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnheader.el (mail-header-parse-addresses): New function.
+       (std11-extract-addresses-components): New function.
+
+2002-01-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-picon.el: Don't require `mail-parse'.
+
+2002-01-07  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnheader.el (mail-header-fold-field): Alias to
+       `std11-fold-field'.
+       (std11-fold-field): New function.
+       (mail-narrow-to-head): Alias to `std11-narrow-to-header'.
+       (mail-header-narrow-to-field): Alias to `std11-narrow-to-field'.
+       (std11-narrow-to-field): New function.
+
+2002-01-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.5 revision 00.
+
+2002-01-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * etc/gnus/describe-group.xpm: Set pixels of first line to
+       background color. A bug in Emacs?
+
+2002-01-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 10.
+
+       * lisp/gnus-picon.el: Require `mail-parse'.
+
+       * lisp/sha1-el.el (sha1-use-external): Replace `executable-find'
+       with `exec-installed-p'.
+
+2002-01-06  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el: Update comments.
+       (gnus-namazu/search): Convert `gnus-cache-directory' to absolute
+       before the regular expression which matches paths of persistent
+       articles is generated.  Clean up codes.
+
+2002-01-05  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-article): Handle the
+       article properly when no group is specified.
+       (nnshimbun-write-nov, nnshimbun-save-nov): Save nov databases only
+       when their sizes are greater than zero.
+
+       * lisp/gnus-namazu.el (gnus-namazu-query-highlight): New option.
+       (gnus-namazu-query-highlight-face): New face.
+       (gnus-namazu/check-cache-group): New function.
+       (gnus-namazu/cache-group-candidates): Ditto.
+       (gnus-namazu/search): Call `gnus-namazu/check-cache-group' to get
+       groups for cached articles.
+       (gnus-namazu/highlight-words): New function.
+       (gnus-namazu-search): Set the group parameter `highlight-words'
+       when `gnus-namazu-query-highlight' is equal to the other value
+       than nil.
+
+       * lisp/gnus-ja.texi (Namazu Groups): Updated.
+
+2001-12-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-bind-colon-keywords): Ignore
+       non-list forms in the top level.
+
+2001-12-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog, todo: (oops) changed buffer-file-coding-system back
+       to coding.
+
+2001-12-18  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * make-x.bat: Ensure nonempty variable value.  Reported by Frank
+       Haun <pille3000@gmx.net>.
+
+2001-12-18 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * ChangeLog, todo: Add `coding'.
+
+2001-12-17  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog: changed coding to buffer-file-coding-system
+       * todo: same
+
+2001-12-10  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * make-x.bat: Code cleanup.  Fix a bug with "/copy".  From Frank
+       Schmitt <ich@Frank-Schmitt.net>.
+
+2001-12-10  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-summary-buffer-name): Changed
+       the expression to decide whether `gnus-summary-buffer-name' should
+       be advised.
+       (gnus-namazu/setup): Strict checking the other Gnus variants than
+       Oort-Gnus before handling `gnus-group-name-charset-group-alist'.
+
+2001-12-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (mm-multibyte-string-p): Alias to
+       `multibyte-string-p' or `ignore'.
+
+2001-12-09  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-summary-buffer-name): New
+       advice.
+
+       * lisp/gnus-namazu.el (top): Update comments.
+       (gnus-namazu-indexed-servers): Abolished.
+       (gnus-namazu-index-directories, gnus-namazu-command): Changed the
+       default value.
+       (gnus-namazu/group-name-regexp): New internal constant.
+       (gnus-namazu/indexed-servers): New function.
+       (gnus-namazu/setup): Not initialize `gnus-namazu-indexed-servers'.
+       Add the entry for ephemeral groups generated by
+       `gnus-namazu-search' to `gnus-group-name-charset-group-alist'.
+       (gnus-namazu/group-prefixed-name): Fix.
+       (gnus-namazu/search): Stricten checking the return value of
+       `gnus-namazu/call-namazu'.  Install changes in order to avoid the
+       difference between regexp-opt module of FSF Emacs and one of XEmacs.
+       (gnus-namazu/get-target-groups, gnus-namazu/get-current-query):
+       Refer `gnus-namazu/group-name-regexp'.
+       (gnus-namazu-search): Slightly modified.
+
+2001-12-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-mimic-kill-buffer): Bind
+       `message-kill-buffer-and-remove-file' to nil while calling the
+       function `message-kill-buffer'.
+
+       * texi/message-ja.texi, texi/message-ja.texi: Update.
+
+       * lisp/lpath.el: Fbind `replace-regexp-in-string' for XEmacs and
+       Mule; don't fbind coding-system-list for Mule.
+
+2001-12-03  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+       (cf. news://news.gnus.org/gnus.gnus-bug #48523)
+
+       * lisp/message.el (message-kill-buffer-and-remove-file): New user
+       option.
+       (message-kill-buffer): Don't remove the backup file if
+       `message-kill-buffer-and-remove-file' is nil.
+
+2001-12-07  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-case-sensitive-filesystem): New
+       option.
+       (gnus-namazu/group-alist): New internal variable.
+       (gnus-namazu/setup): Initialize it.
+       (gnus-namazu/shutdown) New function.
+       (gnus-namazu/request-list): Ditto.
+       (gnus-namazu/group-prefixed-name): Ditto.
+       (gnus-namazu/search): Call it instead of
+       `gnus-group-prefixed-name' in order to normalize a group name on a
+       case-insensitive file system.
+
+2001-12-05  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (gnus-namazu-need-path-normalization): New
+       option.
+       (gnus-namazu/normalize-results): Refined.
+
+       * lisp/gnus-namazu.el (gnus-namazu-index-directory): Abolished.
+       (gnus-namazu-index-directories): New option.
+       (gnus-namazu-coding-system): Changed the default value for Windows
+       and OS/2.
+       (gnus-namazu/setup): Follow the abolition of
+       `gnus-namazu-index-directory'.
+       (gnus-namazu/normalize-results): New inline function.
+       (gnus-namazu/call-namazu): Set `file-name-coding-system' and
+       `pathname-coding-system' to handle querys which include multibyte
+       characters.  Not reset locale environments.  Refer
+       `gnus-namazu-locale' and `gnus-namazu-index-directories'.
+       (gnus-namazu/search): Call `gnus-namazu/normalize-results'.
+       Modify a regular expression.
+       (gnus-namazu/get-target-groups): Modify a regular expression.
+       (gnus-namazu/get-current-query): Ditto.
+       (gnus-namazu/truncate-article-list): Ditto.
+
+2001-12-03  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/mm-url.el: Require `path-util'.
+       (mm-url-program): Replace `executable-find' to `exec-installed-p'.
+
+2001-11-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 09.
+
+       * lisp/canlock-om.el: New file.
+       * lips/dgnushack.el: Load canlock-om.el for compiling canlock.el
+       when `MULE' is bound.
+       (dgnushack-unexporting-files): Add canlock-om.el when `MULE' is
+       not bound.
+       * lisp/message.el: Require `canlock-om' when Mule is running;
+       autoload cus-edit for the function `customize-save-variable'.
+       * lisp/nnheader.el (customize-save-variable): Remove.
+
+2001-11-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-strip-special-text-properties): Default
+       to t because of the new function `message-tamago-not-in-use-p'.
+
+2001-11-26  Kai Gro\eN_johann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * make-x.bat: Use parameter "/copy" rather than "copy" for increased
+       dwimishness for old-time DOS users.  From Frank Schmitt
+       <ich@Frank-Schmitt.net>.
+
+2001-11-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-strip-special-text-properties): Default
+       to nil temporarily (it should be automated).
+       (message-forbidden-properties): Undo last change.
+       (message-strip-forbidden-properties): Undo last change; synch with
+       Oort Gnus.
+
+2001-11-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-forbidden-properties): Defcustom; make
+       it a list; don't include `intangible', `invisible',
+       `modification-hooks' or `read-only'.
+       (message-strip-forbidden-properties): Convert the value of
+       `message-forbidden-properties' to plist.
+
+2001-11-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-group.el (gnus-group-group-map): Bind `G n' key to the
+       command `gnus-group-make-shimbun-group'.
+       (gnus-group-group-menu): Add `gnus-group-make-shimbun-group'.
+
+       * texi/gnus-ja.texi (Foreign Groups): Add a documentation for the
+       shimbun groups.
+       (Web Newspaper): Use `G n' key for `gnus-group-make-shimbun-group'.
+
+2001-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * etc/gnus/unimportant.xpm, etc/gnus/important.xpm: New files.
+
+2001-11-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-wash-map): Remove
+       `gnus-smiley-display'.
+
+2001-11-11  Simon Josefsson  <jas@extundo.com>
+
+       * make-x.bat: Don't use -nw.  Suggested by Frank Haun
+       <pille3000@gmx.net>.
+
+2001-11-09  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * texi/infohack.el (infohack-texi-format): To process
+       write-protected files safely, make this buffer be writable after
+       `find-file'
+
+2001-11-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnheader.el (customize-save-variable): Defun-maybe.
+
+2001-11-01 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * etc/smilies/blink.xpm: New set of xpm. From Oliver Scholz
+       <oscholz@my.gnus.org>.
+
+2001-10-29  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * etc/smilies/sad.pbm: New bitmap.
+       * etc/smilies/blink.pbm: Ditto.
+       Contributed by Kim F. Storm <storm@cua.dk>.
+
+2001-10-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (rfc822-goto-eoh): Remove.
+
+2001-10-19  Kai Gro\eN_johann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Frank Schmitt <ich@Frank-Schmitt.net>.
+
+       * make-x.bat: Use correct directory structure for XEmacs on Windows.
+
+2001-10-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (rfc822-goto-eoh): Define it when void.
+
+2001-10-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-resend, message-send): Undo.
+
+2001-10-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-resend): Bind
+       `inhibit-field-text-motion' to t while resending a mail.
+
+2001-10-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send): Remove the text property `field'
+       from the encoding buffer.
+
+2001-10-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-start.el (gnus-re-read-newsrc-el-file): Use
+       `gnus-ding-file-coding-system' instead of
+       `gnus-startup-file-coding-system'; go to the beginning of the
+       buffer before searching.
+       (gnus-read-newsrc-el-file): Use `gnus-ding-file-coding-system'
+       instead of `gnus-startup-file-coding-system'.
+
+2001-10-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-send-news): Modify the value of
+       `mime-field-encoding-method-alist' to encode newsgroup names.
+
+       * lisp/gnus-art.el (gnus-article-header-presentation-method): Call
+       `article-decode-group-name' to decode newsgroup names.
+       (gnus-article-decode-hook): Default to nil.
+
+2001-10-06 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (uninstall): Add.
+
+       * etc/Makefile.in (uninstall): Add.
+
+2001-10-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-fix-before-sending): Don't expose
+       invisible MIME parts; don't use `message-find-invisible-regions'.
+       (message-find-invisible-regions): Remove.
+       (invisible-region): Advise the function to add the text property
+       `mime-edit-invisible'.
+       (message-invisible-region): Remove.
+       (message-save-drafts): Copy all the text properties from the
+       editing buffer to the encoding buffer.
+       (message-send): Ditto.
+
+2001-10-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nndoc.el (nndoc-oe-dbx-type-p): Use `string-as-multibyte'
+       instead of `mm-string-as-multibyte'.
+       (nndoc-possibly-change-buffer): Use `nnheader-insert-file-contents'
+       instead of `mm-insert-file-contents'.
+
+2001-09-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 08.
+
+2001-09-27 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * aclocal.m4 (GNUS_CHECK_FONTS): Typo. Use /dev/null as latex input.
+
+2001-09-27 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * aclocal.m4, configure.in: Check commercial fonts.
+
+2001-09-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/message.el (message-find-invisible-regions): Look for the
+       text-property `mime-edit-invisible' as well as `message-invisible'.
+       (message-save-drafts): Copy the text-property `mime-edit-invisible'
+       from the message editing buffer to the encoding buffer.
+       (message-send): Ditto.
+
+2001-09-27  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * texi/gnus-ja.texi (Article Hiding): Fix typo.
+
+2001-09-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 07.
+
+2001-09-24 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * configure.in: Generate texi/ps/Makefile.
+
+2001-09-21  Kai Gro\eN_johann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * make.bat: Use parameter "/copy" rather than "copy" for increased
+       dwimishness for old-time DOS users.
+
+2001-09-18 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * make-x.bat: New.
+
+2001-09-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: If W3DIR is identical to URLDIR, don't add it
+       to `load-path'.
+
+2001-09-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-diary.el: Don't use `easy-menu-add-item' if it is not
+       available.
+
+2001-09-17  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/insert-address-regexp):
+       `regexp-quote' for each addresses.
+
+2001-09-16  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * texi/gnus-ja.texi (Drafts): Fix typo.
+
+2001-09-12  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/lpath.el: Removed `current-language-environment' and
+       `language-info-alist'.
+
+2001-09-11  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-art.el (gnus-request-article-this-buffer): Make a copy
+       of the requested article only when the current directory does noe
+       equal to `gnus-original-article-buffer'.
+
+       * lisp/gnus-art.el (gnus-request-article-this-buffer): Copy an
+       article from `gnus-original-article-buffer' to
+       `gnus-article-buffer'.  Generate `gnus-original-article-buffer'
+       safely.
+
+2001-09-10  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el: Updated documents.
+
+       * texi/gnus-ja.texi (Namazu Groups): New subsection.
+
+2001-09-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-namazu.el: Autoload "regexp-opt" for Mule 2.3.
+
+       * Mule23@1934.en, Mule23@1934.ja: To install contrib/regexp-opt.el
+       is required.
+
+       * contrib/regexp-opt.el: Imported from Emacs 20.2.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/pop-up-bbdb-buffer): Use
+       `bbdb-display-layout' or `bbdb-pop-up-display-layout' instead of
+       `bbdb-elided-display' or `bbdb-pop-up-elided-display' when BBDB
+       v2.33 or later is running.
+
+2001-09-10  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-namazu.el (top): Not require `std11'.
+       (gnus-namazu/get-current-from): Use
+       `mail-extract-address-components' instead of
+       `std11-extract-address-components'.
+
+       * lisp/gnus-namazu.el: New file.
+
+       * lisp/gnus.el (top): Add autoload of `gnus-namazu-search'.
+
+       * lisp/gnus-sum.el (gnus-summary-mode-map): Define "\C-c\C-n" as
+       `gnus-namazu-search'.
+
+       * lisp/gnus-group.el (gnus-group-mode-map): Define "\C-c\C-n" as
+       `gnus-namazu-search', and removed `gnus-group-make-shimbun-group'.
+
+2001-09-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-xmas.el (gnus-tilde-pad-form): Abolished.  Use the
+       new function `gnus-correct-pad-form' instead.
+       * lisp/gnus-spec.el (gnus-tilde-pad-form): Ditto.
+
+2001-09-05  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnir.el (nnir-run-namazu): Fix a side effect when handling
+       of process environments.
+
+2001-09-04  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnir.el (top): Added code to avoid byte-compile warning
+       about `nnimap-server-buffer'.
+       (nnir-run-namazu): Disable locale of Namazu.
+
+2001-09-04  KOSEKI Yoshinori  <kose@meadowy.org>
+
+       * lisp/nnir.el (gnus-group-mode-hook): Fix typo.
+
+2001-09-04  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnir.el (top): Don't call `nnir-group-mode-hook' in T-gnus.
+
+       * lisp/gnus-group.el (gnus-group-group-map): Define "G" as
+       `gnus-group-make-nnir-group', and define "S" as
+       `gnus-group-make-shimbun-group'.
+
+       * lisp/gnus.el (top): Add autoload of
+       `gnus-group-make-nnir-group'.
+
+       * lisp/nnir.el: Import from
+       ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/nnir.el.
+
+2001-08-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-util.el (gnus-truncate-string): Abolished.
+
+2001-08-18  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (gnus-group-make-shimbun-group): Call
+       `shimbun-groups' to detect avaiable groups of specified server.
+
+2001-08-17  KANEMATSU Daiji  <kanematu@sra.co.jp>
+
+       * lisp/message.el (message-signature-separator-for-insertion): New
+       customizable variable which is used for signature separator.
+       * lisp/message.el (message-insert-signature): Use variable
+       `message-signature-separator-for-insertion' instead of hard code.
+
+2001-08-15  Yoichi NAKAYAMA  <yoichi@eken.phys.nagoya-u.ac.jp>
+
+       * texi/gnus-ja.texi (Browsing the Web): Fix typo.
+
+2001-08-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 06.
+
+2001-08-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-request-article-this-buffer): Insert an
+       article into `gnus-original-article-buffer' instead of
+       `gnus-article-buffer'.
+
+2001-07-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/mml2015.el: Require `gnus-clfns' when compiling.
+       * lisp/gnus-clfns.el (string-to-list): New compiler macro.
+
+2001-07-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-select-newsgroup): Don't examine cached
+       articles with `gnus-cache-articles-in-group' even if the current
+       group is not a virtual group (see ChangeLog.1 1999-03-02).
+
+2001-07-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 05.
+
+       * lisp/nnmh.el (nnmh-retrieve-parsed-headers): Abolished.
+
+       * lisp/gnus-sum.el (gnus-get-newsgroup-headers-xover): Don't use
+       `gnus-retrieve-parsed-headers'.
+       (gnus-fetch-headers): Ditto.
+
+       * lisp/gnus-int.el (gnus-retrieve-parsed-headers): Abolished.
+
+       * lisp/gnus-cache.el (gnus-cache-braid-headers): Abolished.
+       (gnus-cache-retrieve-parsed-headers): Abolished.
+
+2001-07-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Bind
+       `nnmail-expiry-wait-function' to nil if the group's parameter
+       `expiry-wait' is specified by the user or the shimbun's default
+       value is provided.
+
+2001-07-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-message-make-user-agent): New
+       implementation.
+
+2001-07-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (copy-list): New compiler macro.
+
+2001-07-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-delay.el (gnus-delay-initialize): Don't use the macro
+       `kbd'.
+
+       * lisp/nnheader.el (mm-read-coding-system): New function which is
+       a substitute for mm-util.el.
+
+2001-07-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 04.
+
+       * lisp/nntp.el (nntp-request-newgroups): Use UTC date for
+       NEWGROUPS command.
+
+       * lisp/gnus-start.el (gnus-find-new-newsgroups): Use
+       `message-make-date' instead of `current-time-string'.
+       (gnus-ask-server-for-new-groups): Ditto.
+       (gnus-check-first-time-used): Ditto.
+
+2001-07-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * texi/message-ja.texi (message-citation-line-function): Add a
+       comma just after the `@xref' form.
+
+       * lisp/nnheader.el (nnheader-header-value): Ignore leading
+       whitespaces.
+
+       * lisp/dgnushack.el (dgnushack-make-auto-load): Advise
+       `make-autoload' to handle `define-derived-mode'.
+
+2001-07-12  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-yank-original): Unwind-protect while
+       suspending font-lock.
+       (message-mode): Modify for the following changes.
+       (message-font-lock-keywords-2): Abolished.
+       (message-font-lock-keywords-1): Abolished.
+       (message-font-lock-keywords): Unified.
+       (message-font-lock-cited-text-matcher): Abolished.
+       (font-lock-after-change-function): Don't advise it.
+       (message-font-lock-last-position): Abolished.
+       (message-font-lock-citation-name-max-column): Abolished.
+       (message-font-lock-cited-text-regexp) Abolished.
+       (message-font-lock-fence-close-position): Abolished.
+       (message-font-lock-fence-open-position): Abolished.
+       (message-font-lock-fence-close-regexp): Abolished.
+       (message-font-lock-fence-open-regexp): Abolished.
+
+2001-07-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-font-lock-keywords-1): Replace regexp
+       for mml tags with `mime-edit-tag-regexp'.
+
+2001-07-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-font-lock-keywords-2): Move definitions
+       for cited texts and mml tags to `message-font-lock-keywords-1'.
+
+2001-07-10  Katsuhiro Hermit Endo <hermit@koka-in.org>
+
+       * texi/gnus-ja.texi (Mail Group Commands): Fix a slight mistake.
+
+2001-07-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Add the parent directory of the directory
+       where the APEL modules are installed to `load-path' according to
+       the description of the file Mule23@1934.
+
+2001-07-04  Yair Friedman  <yairfr@Amdocs.com>
+
+       * make.bat: Use infohack.el to create info files.
+
+2001-07-09  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * README.semi: Modify URI of emacs-w3m.
+       * README.semi.ja: Ditto.
+       * Mule23@1934.en: Ditto.
+       * Mule23@1934.ja: Ditto.
+       * lisp/nnshimbun.el: Ditto.
+
+       * texi/gnus-ja.texi (Top, Article Treatment): Fix typo.
+       (Web Newspaper): Modify URI of emacs-w3m.
+
+2001-07-06  KITAGAWA Takurou  <i30x1641@ip.media.kyoto-u.ac.jp>
+
+       * lisp/Makefile.in (clever): Use `if test... then' instead of
+       `test... &&'.
+
+2001-07-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/Makefile.in (clever): Change the quoting style for the
+       elisp form to check for XEmacs-p.
+
+       * lisp/dgnushack.el: Require `path-util' first, and then search
+       for the path if it is not found.
+
+2001-07-05  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+2001-06-28  Akitada Koyama  <cx2@kh.rim.or.jp>
+
+       * texi/gnus-ja.texi (Web Newspaper): Add a description how to show
+       html documents inline.
+
+2001-06-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/message-ja.texi (message-suspend-font-lock-when-citing): Add
+       a description.
+       * texi/message.texi (message-suspend-font-lock-when-citing): Ditto.
+
+       * lisp/message.el (message-yank-original): Suspend font-lock'ing
+       while citing an original message.
+       (message-suspend-font-lock-when-citing): New user option.
+
+2001-06-25  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (find-cl-run-time-functions): New
+       implementation.
+
+2001-06-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (article-display-x-face): Don't gather X-Face
+       fields in `gnus-original-article-buffer'.
+
+2001-06-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-find-parameter): Undo the last
+       bogus changes; use the value of `nnshimbun-pre-fetch-article' if
+       the value of the group parameter `prefetch-articles' is nil; do
+       likewise for `encapsulate-images'.
+
+2001-06-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-find-parameter): Use the value of
+       `nnshimbun-pre-fetch-article' if the value of the group parameter
+       `prefetch-articles' is `off'; do likewise for `encapsulate-images'.
+
+2001-06-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-encapsulate-images): Fix a
+       doc-string that both the values `off' and nil specifies not to
+       encapsulate images.
+       (nnshimbun-pre-fetch-article): Default to `off'.
+
+2001-06-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-encapsulate-images): Renamed from
+       `nnshimbun-encapsulate-article'.
+       (nnshimbun-request-article-1): Replace `encapsulate-article' with
+       `encapsulate-images'.
+       (nnshimbun-find-parameter): Ditto.
+       (nnshimbun-group-parameters): Ditto.
+       (nnshimbun-group-parameters-custom): Ditto.
+
+2001-06-15  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-group-parameters-custom): Add
+       `encapsulate-article' as a customizable option, and modified
+       `prefetch-articles'.
+       (nnshimbun-group-parameters): Add document for
+       `encapsulate-article'.
+       (nnshimbun-encapsulate-article): New server variable.
+       (nnshimbun-find-parameter): Add code for `encapsulate-article'.
+       (nnshimbun-request-article-1): Refer `encapsulate-article' group
+       parameter to control `shimbun-encapsulate-article' value when
+       `shimbun-article' is called.
+
+2001-06-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+2001-06-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Use
+       `nnshimbun-find-parameter'.
+       (nnshimbun-generate-nov-database): Bind a full group name while
+       processing.
+       (nnshimbun-find-parameter): New implementation to refer to the
+       nnshimbun group parameters.
+       (nnshimbun-index-range): Add a document that it's just a default.
+       (nnshimbun-pre-fetch-article): Ditto.
+       (nnshimbun-group-parameters): Specify a parameter type as `list'.
+       (TopLevel): Remove the local variable "-*- coding: junet; -*-".
+
+2001-06-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-group-parameters): New group
+       parameter.  It also provides the user option
+       `nnshimbun-group-parameters-alist' and the function
+       `nnshimbun-find-group-parameters'.
+       (nnshimbun-group-parameters-custom): New variable.
+       (TopLevel): Require `gnus' expressly.
+
+2001-06-12  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-find-parameter): New macro.
+       (nnshimbun-generate-nov-database): Use `nnshimbun-find-parameter'.
+       (nnshimbun-request-expire-articles): Fixed.
+
+2001-06-12  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (Gnus-p): Use `file-exists-p' instead of
+       `locate-library' to check for the existence of mailcap.el in the
+       same directory of gnus.el.
+       (nnshimbun-retrieve-headers-with-nov): Remove a redundant check
+       that I made.
+
+2001-06-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Don't Fbind `xml-node-children'.
+
+2001-06-11  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Fix
+       inhibiting the expiring when `nnshimbun-keep-unparsable-dated-articles'
+       is nil.
+
+2001-06-11  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/gnus-group.el (toplevel): Removed autoload code for
+       "nnshimbun".
+
+       * texi/gnus-ja.texi (Web Newspaper): Add documents about
+       `nnshimbun-index-range'.
+
+2001-06-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Don't
+       refer to the variable `nnshimbun-keep-last-article', we should
+       keep the last article anyway.
+       (nnshimbun-keep-last-article): Abolished.
+
+       * lisp/gnus.el: Autoload "nnshimbun" for the command `gnus-group-
+       make-shimbun-group'.
+
+2001-06-11  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el: Remove some garbage.
+
+2001-06-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/message-ja.texi: Use `iso-2022-7bit' instead of
+       `iso-2022-7bit-ss2' to keep a compatibility between XEmacsen and
+       FSF Emacsen.
+       * texi/gnus-ja.texi: Ditto.
+
+2001-06-09  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (top-level): Updated comments.
+       (nnshimbun): New customize group.
+       (nnshimbun-keep-last-article): Defined as customize variable.
+       (nnshimbun-keep-unparsable-dated-articles): Ditto.
+       (nnshimbun-insert-nov): Use `when' instead of `if'.
+       (gnus-group-shimbun-server-history): Imported from
+       `gnus-group.el'.
+       (gnus-group-make-shimbun-group): Ditto.
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): Its real
+       definition is moved to `nnshimbun.el' and autload code is added.
+       (gnus-group-shimbun-server-history): Its definition is moved to
+       `nnshimbun.el'.
+
+2001-06-08  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-use-entire-index): Removed.
+       (nnshimbun-index-range): New variable.
+       (nnshimbun-close-server): Check status strictly to close server
+       safely.
+       (nnshimbun-generate-nov-database): Refer the group paramter
+       `nnshimbun-index-range' as the second parameter of
+       `shimbun-headers'.
+       (shimbun-mua-use-entire-index): Removed.
+       (nnshimbun-request-article-1): Replace a date string in
+       `gnus-newsgroup-data' only when article header has non-nil value.
+       (nnshimbun-insert-nov): Fixed condition to decide whether
+       `X-Nnshimbun-Id' should be inseted or not.
+
+2001-06-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-expire-nov-databases): Removed.
+       (nnshimbun-request-expire-articles): Simplified; refer to the
+       shimbun's default expiration days.
+
+2001-06-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `xml-node-children' for XEmacsen and old FSF
+       Emacsen.
+
+2001-06-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Prefer the
+       group parameter `expiry-wait' when expiring a closed group.
+
+2001-06-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-article-1): Replace a date
+       string in `gnus-newsgroup-data' based on the newly retrieved
+       article.
+
+2001-06-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-request-expire-articles): Fix
+       inhibiting the expiring.
+
+2001-06-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-expire-nov-databases): New command.
+       (nnshimbun-request-expire-articles): New function.
+       (nnshimbun-keep-unparsable-dated-articles): New variable.
+       (nnshimbun-keep-last-article): New variable.
+       (nnshimbun-insert-nov): Rewrite using `nnshimbun-string-or'.
+       (nnshimbun-string-or): New macro.
+       (nnshimbun-tmp-string): New internal variable.
+       (TopLevel): Require `message' for `message-make-date'.
+
+2001-05-30  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (find-cl-run-time-functions): Remove a
+       useless non-global var; scroll the output window automatically.
+
+2001-05-31  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el (nnshimbun-header-xref): Removed.
+       (nnshimbun-check-header): Removed.
+       (nnshimbun-make-shimbun-header): Don't call
+       `nnshimbun-header-xref'.
+       (nnshimbun-request-group): Simplified.
+       (nnshimbun-request-article-1): Call `nnshimbun-replace-nov-entry'
+       instead of `nnshimbun-check-header'.
+       (nnshimbun-insert-nov): New function.
+       (nnshimbun-generate-nov-database): Call `nnshimbun-insert-nov'
+       instead of `nnheader-insert-nov'.
+       (nnshimbun-replace-nov-entry): New function.
+
+2001-05-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-clfns.el (find-cl-run-time-functions): Add a parser for
+       `dolist'; protect against errors.
+
+2001-05-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-retrieve-headers-with-nov): Don't
+       use `last'.
+       (nnshimbun-make-shimbun-header): Use the following macros.
+       (nnshimbun-mail-header-from): New macro whose definition will be
+       changed statically for Gnus or gnus.
+       (nnshimbun-mail-header-subject): Ditto.
+       (TopLevel): Don't require `gnus-clfns'.
+
+       * lisp/gnus.el: Add autoload for `find-cl-run-time-functions'.
+
+       * lisp/gnus-clfns.el (find-cl-run-time-functions): New command for
+       the developers.
+       (cl-run-time-functions): New variable.
+       (TopLevel): Don't require `cl' at run-time.
+
+2001-05-28  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * texi/gnus-ja.texi (Web Newspaper): Updated.
+
+2001-05-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-unexporting-files): Add
+       "nnshimbun.el" if the library "shimbun" is not found.
+       (TopLevel): Add "/somewhere/apel/" to `load-path' if it is needed.
+       (locate-library): Redefine it for Mule before it is called.
+
+       * README.semi.ja: Update for the use of Emacs-W3M.
+       * README.semi: Ditto.
+       * Mule23@1934.ja: Ditto.
+       * Mule23@1934.en: Ditto.
+
+2001-05-28  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * lisp/nnshimbun.el: Reconstructed to use `shimbun'.
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group):
+       Reconstructed to use `shimbun'.
+
+       * lisp/dgnushack.el (toplevel): Add paths if and only if APEL and
+       FLIM can't be found.
+
+2001-05-17  Kai =?iso-8859-1?q?Gro=DFjohann?=  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * etc/Makefile.in (datadir): Set this variable, like in the other
+       Makefile.in's.  Patch from Gaute B Strokkenes <gs234@cam.ac.uk>.
+
+2001-05-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-bind-colon-keywords): Don't ignore
+       `widget-convert-button', `widget-create' and `widget-put'; ignore
+       `defface'.
+
+2001-05-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el: Require `base64' if `base64-encode-string' is not a
+       built-in function.
+
+       * lisp/dgnushack.el (dgnushack-bind-colon-keywords): Ignore
+       `defgroup'.
+
+2001-05-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * lisp/nnmail.el: Don't bind the colon keywords here.
+       * lisp/gnus.el (gnus-colon-keywords): New variable which will
+       default to the value of `dgnushack-colon-keywords'; bind them.
+       * lisp/dgnushack.el (dgnushack-unexporting-files): Add
+       dgnuskwds.el.
+       (dgnushack-colon-keywords): New constant which will have the colon
+       keywords shuld be bound at run-time for old Emacsen; cache them in
+       the file dgnuskwds.el and bind them.
+       (dgnushack-bind-colon-keywords): New function.
+       (locate-library): Make the function to be silent for Mule.
+       * lisp/Makefile.in (clean): Remove dgnuskwds.el.
+
+2001-05-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-maybe-encode): Don't use
+       `end-of-invisible'.
+
+2001-05-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.4 revision 00.
+
+2001-04-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-exit): Set buffer to
+       `gnus-article-buffer' just before `gnus-article-prepare-display' is
+       called.
+       (gnus-article-mime-edit-article-setup): Ditto.
+       (gnus-article-prepare-display): Don't bind `buffer-read-only'
+       because of `inhibit-read-only'; don't set the value of
+       `gnus-article-current-summary' here; delete all extents or overlays
+       and clear the value of `gnus-button-marker-list' in advance; make
+       it to run in `gnus-article-buffer'.
+       (gnus-article-prepare): Make it to run in `gnus-article-buffer'.
+       (article-toggle-headers): Don't bind `buffer-read-only' because of
+       `inhibit-read-only'.
+       (article-hide-headers): Ditto.
+
+2001-04-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.3 revision 00.
+
+2001-04-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.2 revision 00.
+
+2001-04-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.1 revision 00.
+
+2001-04-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `xml-parse-region' for XEmacsen and old FSF
+       Emacsen; don't bind `mh-lib-progs'.
+
+2001-04-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el: Enclose w3m stuff with `eval-and-compile';
+       bind `w3m-work-buffer-name' and `w3m-retrieve' when compiling.
+
+2001-04-09  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 10.
+
+2001-04-03  TSUCHIYA Masatoshi  <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-type-definition: Follow changes in
+       asahi.com.
+       (nnshimbun-asahi-get-headers): Ditto.
+       (nnshimbun-retrieve-url): Use `w3m-retrieve' if it is available.
+
+2001-04-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-inews-yank-articles): Make it to work with
+       multiple articles even if there is a detached minibuffer frame on
+       some window managers.
+
+2001-03-21  Thierry Emery <thierry.emery@club-internet.fr>
+
+       * lisp/mm-decode.el (mm-copy-to-buffer): Copy buffer in unibyte
+       mode.
+
+2001-03-19  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-kill.el (gnus-execute): Work with the extra headers.
+       * lisp/gnus-sum.el (gnus-summary-execute-command): Ditto.
+
+2001-03-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-fix-before-sending): Hide again the
+       invisible property of encoded binary data parts after checking is
+       done.
+       (message-find-invisible-regions): New function.
+       (message-save-drafts, message-send): Inherit the invisible property
+       of encoded binary data parts to make MIME-Edit find the MIME part
+       boundaries.
+
+       * lisp/dgnushack.el (dgnushack-compose-package): Tidy up.
+       (dgnushack-make-load): Ditto.
+
+2001-03-12  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-compose-package): New function.
+       (dgnushack-make-load): Add autoload for cus-load if it is missing.
+
+       * lisp/Makefile.in (compose-package): Use
+       `dgnushack-compose-package'.
+       (clean, clever): Remove custom-load.el.
+
+       * Makefile.in (elclean): Remove custom-load.el.
+
+2001-03-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Setup MIME
+       entity even if `gnus-show-mime' is nil.
+
+2001-03-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Load gnus-clfns.el after `load-path' is
+       adjusted.
+
+       * lisp/gnus-clfns.el (string): New compiler macro.
+       (string): Defun-maybe as an ordinary function since it won't be
+       provided in cl.
+       * lisp/gnus-score.el (gnus-score-find-bnews): Use it as Gnus does.
+
+2001-03-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-retrieve-url): Check if
+       `url-current-mime-charset' is bound.
+
+2001-03-04  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el (gnus-info-find-node): Pretend to be
+       `gnus-article-mode' in the article buffer.
+
+2001-03-02  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-kinsoku-eol-list): Simplified.
+       (nnshimbun-kinsoku-bol-list): Ditto.
+
+2001-03-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 09.
+
+       * lisp/gnus-offline.el (gnus-offline-get-menu-items): Rewrite using
+       `dolist'.
+
+       * lisp/gnus-group.el (gnus-group-make-shimbun-group): Simplified.
+
+       * lisp/dgnushack.el: Load cl-macs to ensure that the macro `dolist'
+       is defined properly.
+
+2001-02-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnwfm.el: Require `gnus-clfns' when compiling.
+       * lisp/nnshimbun.el: Ditto.
+       * lisp/nnfolder.el: Ditto.
+       * lisp/mm-util.el: Ditto.
+       * lisp/gnus-vers.el: Ditto.
+       * lisp/gnus-sum.el: Ditto.
+       * lisp/gnus-score.el: Ditto.
+       * lisp/gnus-nocem.el: Ditto.
+
+       * lisp/gnus-ofsetup.el: Don't require `gnus-clfns'.
+       (gnus-ofsetup-customize-done): Use `dolist' instead of `mapc'.
+       (gnus-setup-for-offline): Ditto.
+
+       * lisp/gnus-offline.el: Don't use `mapc' for binding some vars;
+       don't require `gnus-clfns'.
+
+       * lisp/gnus-clfns.el (subseq, merge, coerce, butlast): New compiler
+       macros.
+       (mapc): Remove.
+
+       * lisp/gnus-art.el: Use `dolist' instead of `mapcar' for defining
+       `gnus-article-read-summary-keys'.
+
+2001-02-28  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-article-setup): Leave
+       the forwarded parts undecoded.
+       (gnus-article-decode-article-as-default-mime-charset): Set the
+       value of `default-mime-charset' buffer-locally.
+
+2001-02-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el: Add autoloads for
+       `gnus-summary-digest-post-forward' and
+       `gnus-summary-digest-mail-forward'.
+
+       * lisp/gnus-sum.el (gnus-summary-post-menu): Replace
+       `gnus-uu-digest-mail-forward' and `gnus-uu-digest-post-forward'
+       with `gnus-summary-digest-post-forward' and
+       `gnus-summary-digest-mail-forward'.
+
+       * lisp/gnus-msg.el (gnus-summary-digest-post-forward): Restore and
+       repair the command `gnus-summary-post-digest' and rename it.
+       (gnus-summary-digest-mail-forward): Ditto.
+       (gnus-summary-send-map): Replace `gnus-uu-digest-mail-forward' and
+       `gnus-uu-digest-post-forward' with
+       `gnus-summary-digest-post-forward' and
+       `gnus-summary-digest-mail-forward'.
+
+2001-02-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-show-article): Bind
+       `gnus-inhibit-treatment' to t while fetching the raw article.
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-exit): Bind
+       `mime-edit-insert-user-agent-field' to nil while `mime-edit-exit'
+       is being done;  turn off font-lock first;  query if the buffer is
+       modified.
+       (gnus-article-mime-edit-done): New function.
+       (gnus-article-mime-edit-article-setup): Make the window fill its
+       frame;  clear the buffere modified flag;  substitute key definition
+       `gnus-article-edit-done' with `gnus-article-mime-edit-done';  don't
+       turn off font-lock here;  bind `mime-edit-insert-user-agent-field'
+       to nil while `mime-edit-exit' is being done.
+       (gnus-article-mime-edit-article-unwind): Turn off font-lock first.
+
+2001-02-23  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el: Don't require `emu'.
+
+2001-02-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-forward-subject-author-subject): Decode
+       `From' field.
+
+2001-02-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 08.
+
+       * lisp/gnus-sum.el (gnus-get-newsgroup-headers-xover): Don't use
+       `gnus-retrieve-parsed-headers' when the backend is nnimap.  It is
+       only a temporary fix for an infloop on nnimap.  FIXME!!!
+       (gnus-select-newsgroup): Ditto.
+
+2001-02-16  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/gnus-ja.texi (New features in Gnus 5.8): Remove annotation
+       about `gnus-article-display-hook.'
+       * texi/gnus-faq-ja.texi (Q2.1): Remove mention of
+       `gnus-article-display-hook.'
+
+       * lisp/gnus.el (gnus-article-display-hook): Abolished.
+
+       * lisp/gnus-uu.el (gnus-uu-grab-articles): Don't care about
+       `gnus-article-display-hook'.
+       * lisp/gnus-sum.el (gnus-summary-show-article): Ditto.
+       (gnus-summary-search-article): Ditto.
+
+       * lisp/gnus-bbdb.el (gnus-bbdb-insinuate): Use
+       `gnus-article-prepare-hook' instead of `gnus-article-display-hook'.
+
+       * lisp/gnus-art.el (gnus-article-prepare-display): Evaluate
+       `gnus-article-prepare-hook' after an article has been prepared;
+       don't evaluate `gnus-article-display-hook'.
+
+2001-02-15  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/message.el (message-cite-original-without-signature):
+       Extract from field for the simple citation line.
+
+2001-02-14  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 07.
+
+       * lisp/dgnushack.el (dgnushack-make-autoloads): Remove function.
+       (dgnushack-make-load): Ignore cus-load.el if it does not exist.
+       (dgnushack-make-auto-load): Remove auto-autoloads.el.
+       (dgnushack-make-cus-load): Do nothing if loading cus-dep is failed.
+
+       * lisp/Makefile.in (clean): Remove gnus-load.el instead of
+       custom-load.el.
+       (compose-package): Call `gnus-load.elc' and then rename
+       gnus-load.el(c) to auto-autoloads.el(c) instead of the use of
+       `dgnushack-make-autoloads'.
+       (clever): No need to remove custom-load.el.
+
+       * Makefile.in (elclean): Remove gnus-load.el instead of
+       custom-load.el.
+
+       * aclocal.m4 (AC_CHECK_URL): Ignore cache.
+
+2001-02-13  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 06.
+
+2001-02-11 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * GNUS-NEWS: Copyright and others.
+
+2001-02-09 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * aclocal.m4 (AC_CHECK_URL): Add.
+
+       * configure.in: Use it.
+
+2001-02-08  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnshimbun.el (nnshimbun-fml-get-headers): Fix unbalanced
+       parentheses.
+
+2001-02-08  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnshimbun.el: Add `bbdb-ml' support.
+
+2001-02-02  Akihiro Arisawa  <ari@atesoft.advantest.co.jp>
+
+       * lisp/nnshimbun.el (nnshimbun-type-definition): Follow URL change
+       of `xemacs'.
+       (nnshimbun-xemacs-get-headers): Ditto.
+
+2001-02-06  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * README-gnus-bbdb.{en,ja}: Update the patch for BBDB v2.2.
+
+2001-02-01  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/Makefile.in (.texi, %.info): Don't use makeinfo command when
+       gnus-ja.texi or message-ja.texi is given.  It is needed for some
+       make command if which can not understand "%-ja:" or "%-ja.info:".
+
+2001-01-31  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-sum.el (gnus-summary-display-article): Replace
+       `mm-enable-multibyte-mule4' with `set-buffer-multibyte'.
+
+2001-01-29  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-art.el (gnus-article-mime-edit-exit): Use
+       `buffer-substring-no-properties' instead of `format'.
+
+2001-01-23  TAKAHASHI Kaoru  <kaoru@kaisei.org>
+
+       * texi/ptexinfmt.el: Support @letterpaper and @afivepaper.
+
+2001-01-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 05.
+
+       * Makefile.in (install-package-lisp): Use
+       `install-without-compiling' instead of `install'.
+
+       * lisp/Makefile.in (install): Use `install-without-compiling'.
+       (install-without-compiling): New target.
+
+2001-01-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * texi/Makefile.in (.texi, %.info, %-ja.info, %-ja): Use
+       `infohack-texi-format'.
+
+       * texi/infohack: (infohack-texi-format): New function.
+       * lisp/dgnushack.el (dgnushack-texi-format): Move to
+       texi/infohack.el and rename.
+       (dgnushack-texi-add-suffix-and-format): Remove.
+
+       * texi/ptexinfmt.el: New file.
+       * lisp/ptexinfmt.el: Move to texi/.
+
+2001-01-18  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 04.
+
+2001-01-17  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/dgnushack.el (dgnushack-make-autoloads): Do nothing if the
+       files for autoloads already exist.
+       (dgnushack-unexporting-files): More useful message.
+
+       * lisp/Makefile.in (install): Call `clever' before installing.
+       (install-lisp): Remove.
+       (clever): Check for whether the all elc files should be recompiled.
+
+       * Makefile.in (xclever): New target.
+       (install-package-lisp): Replace `install-lisp' with `install'.
+       (install-package-ja): Replace `xlick' with `xclever'.
+       (install-package): Ditto.
+
+2001-01-17  KOSEKI Yoshinori  <kose@wizard.tamra.co.jp>
+
+       * Makefile.in: Unset `PWD' for Meadow/NTEmacs.
+
+2001-01-15  Jesper Harder <harder@ifa.au.dk>
+
+       * make.bat: Fix doc.
+
+2001-01-15  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/nnheader.el: Require `pces', `poem' and `std11' to reduce
+       the required value of `recursive-load-depth-limit' for Emacs 21.
+
+       * lisp/message.el (message-followup): Handle "Mail-Copies-To:"
+       correctly.
+       (message-get-reply-headers): Ditto.
+
+2001-01-15  Keiichi Suzuki  <keiichi@nanap.org>
+
+       * lisp/gnus-bbdb.el (gnus-bbdb/update-record): Save excursion
+       while `bbdb-annotate-message-sender' is being done.
+
+2001-01-13  Kinji Itoh  <kinji-i@ma.neweb.ne.jp>
+
+       * Makefile.in (install-package-lisp): Specify EMACS=$(XEMACS).
+
+2001-01-11  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-copy-article-buffer): Remove smiley
+       extents for XEmacs 21.1 using `format'.
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Cancel last change.
+
+2001-01-10  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 03.
+
+       * lisp/gnus.el: Don't autoload "smiley" for `smiley-toggle-buffer';
+       don't autoload "gnus-bitmap" or "x-face-mule" when Emacs 21 is
+       running.
+
+       * lisp/gnus-art.el (TopLevel): Autoload "gnus-bitmap" for
+       `smiley-toggle-buffer' when compiling.
+       (gnus-treatment-function-alist): Use `gnus-smiley-display' for
+       `gnus-treat-display-smileys' by default when XEmacs or Emacs 21 is
+       running.
+       (gnus-treat-display-smileys): Check for `smiley-mule' instead of
+       `gnus-bitmap'.
+       (gnus-article-x-face-command): Don't check for xbm for x-face-e21.
+
+2001-01-05  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 02.
+
+       * lisp/dgnushack.el (dgnushack-texi-format): Remove "@anchor" if it
+       is not supported.
+
+2000-12-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus.el: Bind `:parameter-type', `:parameter-document',
+       `:function', `:function-document', `:variable',
+       `:variable-document', `:variable-group', `:variable-type' and
+       `:variable-default' for old Emacsen.
+
+2000-12-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el (gnus-revision-number): Increment to 01.
+
+       * configure: Regenerate.
+       * configure.in: Add `AC_PATH_ETCDIR'.
+       * Makefile.in (install-etc): New target.
+
+       * lisp/nnheader.el (mm-image-load-path): Alias to
+       `nnheader-image-load-path'.
+       (nnheader-image-load-path): New function copied from
+       the function `mm-image-load-path' in mm-util.el.
+
+       * lisp/drums.el: Remove.
+
+2000-12-22 03:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * configure.in: Add etc/Makefile.
+
+2000-12-22  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-msg.el (gnus-debug): Use `sit-for' in the inside of
+       `save-excursion'.
+       (gnus-bug): Pop up the sending buffer first.
+
+       * lisp/gnus-art.el (article-treat-dumbquotes): Quote backslashes in
+       doc-string.
+
+       * lisp/dgnushack.el
+       (byte-compile-file-form-custom-declare-variable): Use `defvar'
+       instead of `custom-declare-variable' to make the variable
+       uncustomizable if the arguments has the keyword `:version'.
+
+2000-12-22  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+
+       * README.semi.ja: Fix typo.
+
+2000-12-21  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/lpath.el: Fbind `compose-mail' for Mule.
+
+       * lisp/dgnushack.el (TopLevel): Byte-optimize
+       `custom-declare-variable', `custom-declare-group, and
+       `custom-declare-face' to omit unsupported keywords when Mule is
+       running.
+
+2000-12-20  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lisp/gnus-vers.el: T-gnus 6.15.0 revision 00.
+
+       * lisp/dgnushack.el (TopLevel): Advise `custom-handle-keyword' not
+       to signal an error when Mule is running.
+       (TopLevel): Bind `:ascent', `:foreground', `:help', `:version' and
+       `:set-after' if colon keyword is not available.
+       (TopLevel): Require `custom'.
+
+       * lisp/lpath.el (TopLevel): Fbind `shell-command-to-string' for
+       Mule.
+       (TopLevel): Don't require `custom' here.
+
+2000-12-20  Jesper Harder <jesper_harder@hotmail.com>
+
+       * make.bat: set max-lisp-eval-depth.
+
+See ChangeLog.3 for earlier changes.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
index e4a0a67..b891063 100644 (file)
--- a/GNUS-NEWS
+++ b/GNUS-NEWS
-** Gnus changes.
+GNUS NEWS -- history of user-visible changes.
+Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+See the end for copying conditions.
 
-*** The Gnus alpha distribution no longer bundles Custom and Widget.
-If your Emacs doesn't come with these libraries, fetch them from
-<URL:http://www.dina.kvl.dk/~abraham/custom/>.  You also then need to
-add the following to the lisp/dgnushack.el file:
+Please send Gnus bug reports to bugs@gnus.org.
+For older news, see Gnus info node "New Features".
 
-     (push "~/lisp/custom" load-path)
+\f
+* Changes in Oort Gnus
 
-Modify to suit your needs.
+** `gnus-group-read-ephemeral-group' can be called interactively, using `G M'.
 
-*** New functionality for using Gnus as an offline newsreader has been
-added.  A plethora of new commands and modes have been added.  See the
-Gnus manual for the full story.
+** In draft groups, `e' is now bound to `gnus-draft-edit-message'.
+Use `B w' for `gnus-summary-edit-article' instead.
 
-*** The nndraft backend has returned, but works differently than
-before.  All Message buffers are now also articles in the nndraft
-group, which is created automatically.
+** The revised Gnus FAQ is included in the manual.
+See the info node "Frequently Asked Questions".
 
-*** `gnus-alter-header-function' can now be used to alter header
-values.
+** Upgrading from previous (stable) version if you have used Oort.
 
-*** `gnus-summary-goto-article' now accept Message-ID's.
+If you have tried Oort (the unstable Gnus branch leading to this
+release) but went back to a stable version, be careful when upgrading
+to this version.  In particular, you will probably want to remove all
+.marks (nnml) and .mrk (nnfolder) files, so that flags are read from
+your ~/.newsrc.eld instead of from the .marks/.mrk file where this
+release store flags.  See a later entry for more information about
+marks.  Note that downgrading isn't safe in general.
 
-*** A new Message command for deleting text in the body of a message
-outside the region: `C-c C-v'.
+** Article Buttons
 
-*** You can now post to component group in nnvirtual groups with
-`C-u C-c C-c'.
+More buttons for URLs, mail addresses, Message-IDs, Info links, man pages and
+Emacs or Gnus related references, see the info node "Article Buttons".  The
+variables `gnus-button-*-level' can be used to control the appearance of all
+article buttons, see the info node "Article Button Levels".
 
-*** `nntp-rlogin-program' -- new variable to ease customization.
+** Dired integration
 
-*** `C-u C-c C-c' in `gnus-article-edit-mode' will now inhibit
-re-highlighting of the article buffer.
+`gnus-dired-minor-mode' installs key bindings in dired buffers to send a file
+as an attachment (`C-c C-m C-a'), open a file using the approriate mailcap
+entry (`C-c C-m C-l'), and print a file using the mailcap entry (`C-c C-m
+C-p').  See the info node "Other modes".
 
-*** New element in `gnus-boring-article-headers' -- `long-to'.
 
-*** `M-i' symbolic prefix command.  See the section "Symbolic
-Prefixes" in the Gnus manual for details.
+** Gnus can display RSS newsfeeds as a newsgroup.  To get started do `B
+nnrss RET RET' in the Group buffer.
 
-*** `L' and `I' in the summary buffer now take the symbolic prefix
-`a' to add the score rule to the "all.SCORE" file.
+** Single-part yenc encoded attachments can be decoded.
 
-*** `gnus-simplify-subject-functions' variable to allow greater
-control over simplification.
+** Picons
+The picons code has been reimplemented to work in Emacs 21 -- some of
+the previous options have been removed or renamed.
 
-*** `A T' -- new command for fetching the current thread.
+Picons are small "personal icons" representing users, domain and
+newsgroups, which can be displayed in the Article buffer.  To enable
+picons, install the picons database from
 
-*** `/ T' -- new command for including the current thread in the
-limit.
+      http://www.cs.indiana.edu/picons/ftp/index.html
 
-*** `M-RET' is a new Message command for breaking cited text.
+and point `gnus-picon-databases' to that location.
 
-*** \\1-expressions are now valid in `nnmail-split-methods'.
+** If the new option `gnus-treat-body-boundary' is `head', a boundary 
+line is drawn at the end of the headers.
 
-*** The `custom-face-lookup' function has been removed.  
-If you used this function in your initialization files, you must
-rewrite them to use `face-spec-set' instead.
+** Retrieval of charters and control messages
+There are new commands for fetching newsgroup charters (`H c') and
+control messages (`H C').
 
-*** Cancelling now uses the current select method.  Symbolic prefix
-`a' forces normal posting method.
+** Delayed articles
+You can delay the sending of a message with `C-c C-j' in the Message
+buffer.  The messages are delivered at specified time.  This is useful
+for sending yourself reminders.  Setup with (gnus-delay-initialize).
 
-*** New command to translate M******** sm*rtq**t*s into proper text
--- `W d'.
+** If `auto-compression-mode' is enabled, attachments are automatically
+decompressed when activated.
 
+** If the new option `nnml-use-compressed-files' is non-nil, 
+the nnml back end allows compressed message files.
+
+** Signed article headers (X-PGP-Sig) can be verified with `W p'.
+
+** The Summary Buffer uses an arrow in the fringe to indicate the
+current article in Emacs 21 running on a graphical display.  Customize
+`gnus-summary-display-arrow' to disable it.
+
+** Warn about email replies to news
+Do you often find yourself replying to news by email by mistake?  Then
+the new option `gnus-confirm-mail-reply-to-news' is just the thing for
+you.
+
+** If the new option `gnus-summary-display-while-building' is non-nil, 
+the summary buffer is shown and updated as it's being built.
+
+** The new `recent' mark "." indicates newly arrived messages (as
+opposed to old but unread messages).
+
+** The new option `gnus-gcc-mark-as-read' automatically marks 
+Gcc articles as read.
+
+** The nndoc back end now supports mailman digests and exim bounces.
+
+** Gnus supports RFC 2369 mailing list headers, and adds a number of 
+related commands in mailing list groups.
+
+** The Date header can be displayed in a format that can be read aloud
+in English, see `gnus-treat-date-english'.
+
+** The envelope sender address can be customized when using Sendmail, see 
+`message-sendmail-envelope-from'.
+
+** diffs are automatically highlighted in groups matching
+`mm-uu-diff-groups-regexp'
+
+** TLS wrapper shipped with Gnus
+
+TLS/SSL is now supported in IMAP and NNTP via tls.el and GNUTLS.  The
+old TLS/SSL support via (external third party) ssl.el and OpenSSL
+still works.
+
+** New make.bat for compiling and installing Gnus under MS Windows
+
+Use make.bat if you want to install Gnus under MS Windows, the first
+argument to the batch-program should be the directory where xemacs.exe
+respectively emacs.exe is located, iff you want to install Gnus after
+compiling it, give make.bat /copy as the second parameter.
+
+`make.bat' has been rewritten from scratch, it now features automatic
+recognition of XEmacs and GNU Emacs, generates gnus-load.el, checks if
+errors occur while compilation and generation of info files and reports
+them at the end of the build process.  It now uses makeinfo if it is
+available and falls back to infohack.el otherwise.  `make.bat' should now
+install all files which are necessary to run Gnus and be generally a
+complete replacement for the "configure; make; make install" cycle used
+under Unix systems.
+
+The new make.bat makes make-x.bat superfluous, so it has been removed.
+
+** Support for non-ASCII domain names
+
+Message supports non-ASCII domain names in From:, To: and Cc: and will
+query you whether to perform encoding when you try to send a message.
+The variable `message-use-idna' controls this.  Gnus will also decode
+non-ASCII domain names in From:, To: and Cc: when you view a message.
+The variable `gnus-use-idna' controls this.
+
+** Better handling of Microsoft citation styles
+
+Gnus now tries to recognize the mangled header block that some Microsoft
+mailers use to indicate that the rest of the message is a citation, even
+though it is not quoted in any way.  The variable
+`gnus-cite-unsightly-citation-regexp' matches the start of these
+citations.
+
+** gnus-article-skip-boring
+
+If you set `gnus-article-skip-boring' to t, then Gnus will not scroll
+down to show you a page that contains only boring text, which by
+default means cited text and signature.  You can customize what is
+skippable using `gnus-article-boring-faces'.
+
+This feature is especially useful if you read many articles that
+consist of a little new content at the top with a long, untrimmed
+message cited below.
+
+** The format spec %C for positioning point has changed to %*.
+
+** The new variable `gnus-parameters' can be used to set group parameters.
+
+Earlier this was done only via `G p' (or `G c'), which stored the
+parameters in ~/.newsrc.eld, but via this variable you can enjoy the
+powers of customize, and simplified backups since you set the variable
+in ~/.emacs instead of ~/.newsrc.eld.  The variable maps regular
+expressions matching group names to group parameters, a'la:
+
+     (setq gnus-parameters
+           '(("mail\\..*"
+              (gnus-show-threads nil)
+              (gnus-use-scoring nil))
+             ("^nnimap:\\(foo.bar\\)$"
+              (to-group . "\\1"))))
+
+** Smileys (":-)", ";-)" etc) are now iconized for Emacs too.
+
+Customize `gnus-treat-display-smileys' to disable it.
+
+** Gnus no longer generates the Sender: header automatically.
+
+Earlier it was generated iff the user configurable email address was
+different from the Gnus guessed default user address.  As the guessing
+algorithm is rarely correct these days, and (more controversially) the
+only use of the Sender: header was to check if you are entitled to
+cancel/supersede news (which is now solved by Cancel Locks instead,
+see another entry), generation of the header has been disabled by
+default.  See the variables `message-required-headers',
+`message-required-news-headers', and `message-required-mail-headers'.
+
+** Features from third party message-utils.el added to message.el.
+
+Message now asks if you wish to remove "(was: <old subject>)" from
+subject lines (see `message-subject-trailing-was-query').  C-c M-m and
+C-c M-f inserts markers indicating included text.  C-c C-f a adds a
+X-No-Archive: header.  C-c C-f x inserts appropriate headers and a
+note in the body for cross-postings and followups (see the variables
+`message-cross-post-*').
+
+** References and X-Draft-Headers are no longer generated when you
+start composing messages and `message-generate-headers-first' is nil.
+
+** Improved anti-spam features.
+
+Gnus is now able to take out spam from your mail and news streams
+using a wide variety of programs and filter rules.  Among the supported
+methods are RBL blocklists, bogofilter and white/blacklists.  Hooks
+for easy use of external packages such as SpamAssassin and Hashcash
+are also new.
+
+** Easy inclusion of X-Faces headers.
+
+** In the summary buffer, the new command / N inserts new messages and
+/ o inserts old messages.
+
+** Gnus decodes morse encoded messages if you press W m.
+
+** Unread count correct in nnimap groups.
+
+The estimated number of unread articles in the group buffer should now
+be correct for nnimap groups.  This is achieved by calling
+`nnimap-fixup-unread-after-getting-new-news' from the
+`gnus-setup-news-hook' (called on startup) and
+`gnus-after-getting-new-news-hook' (called after getting new mail).
+If you have modified those variables from the default, you may want to
+add n-f-u-a-g-n-n again.  If you were happy with the estimate and want
+to save some (minimal) time when getting new mail, remove the
+function.
+
+** Group Carbon Copy (GCC) quoting
+
+To support groups that contains SPC and other weird characters, groups
+are quoted before they are placed in the Gcc: header.  This means
+variables such as `gnus-message-archive-group' should no longer
+contain quote characters to make groups containing SPC work.  Also, if
+you are using the string "nnml:foo, nnml:bar" (indicating Gcc into two
+groups) you must change it to return the list ("nnml:foo" "nnml:bar"),
+otherwise the Gcc: line will be quoted incorrectly.  Note that
+returning the string "nnml:foo, nnml:bar" was incorrect earlier, it
+just didn't generate any problems since it was inserted directly.
+
+** ~/News/overview/ not used.
+
+As a result of the following change, the ~/News/overview/ directory is
+not used any more.  You can safely delete the entire hierarchy.
+
+** gnus-agent
+
+The Gnus Agent has seen a major update.  It is now enabled by default,
+and all nntp and nnimap servers from `gnus-select-method' and
+`gnus-secondary-select-method' are agentized by default.  Earlier only
+the server in `gnus-select-method' was agentized by the default, and the
+agent was disabled by default.  When the agent is enabled, headers are
+now also retrieved from the Agent cache instead of the backends when
+possible.  Earlier this only happened in the unplugged state.  You can
+enroll or remove servers with `J a' and `J r' in the server buffer.
+Gnus will not download articles into the Agent cache, unless you
+instruct it to do so, though, by using `J u' or `J s' from the Group
+buffer.  You revert to the old behaviour of having the Agent disabled
+by customizing `gnus-agent'.  Note that putting `(gnus-agentize)' in
+~/.gnus is not needed any more.
+
+** gnus-summary-line-format
+
+The default value changed to "%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n".
+Moreover `gnus-extra-headers', `nnmail-extra-headers' and
+`gnus-ignored-from-addresses' changed their default so that the users
+name will be replaced by the recipient's name or the group name
+posting to for NNTP groups.
+
+** deuglify.el (gnus-article-outlook-deuglify-article)
+
+A new file from Raymond Scholz <rscholz@zonix.de> for deuglifying
+broken Outlook (Express) articles.
+
+** (require 'gnus-load)
+
+If you use a stand-alone Gnus distribution, you'd better add
+"(require 'gnus-load)" to your ~/.emacs after adding the Gnus
+lisp directory into load-path.
+
+File gnus-load.el contains autoload commands, functions and variables,
+some of which may not be included in distributions of Emacsen.
+
+** gnus-slave-unplugged
+
+A new command which starts gnus offline in slave mode.
+
+** message-insinuate-rmail
+
+Adding (message-insinuate-rmail) in .emacs and customizing
+`mail-user-agent' to `gnus-user-agent' convinces Rmail to compose,
+reply and forward messages in Message mode, where you can enjoy the
+power of MML.
+
+** message-minibuffer-local-map
+
+The line below enables BBDB in resending a message:
+
+(define-key message-minibuffer-local-map [?\t] 'bbdb-complete-name)
+
+** Externalizing and deleting of attachments.
+
+If `gnus-gcc-externalize-attachments' (or
+`message-fcc-externalize-attachments') is non-nil, attach local files
+as external parts.
+
+The command `gnus-mime-save-part-and-strip' (bound to `C-o' on MIME
+buttons) saves a part and replaces the part with an external one.
+`gnus-mime-delete-part' (bound to `d' on MIME buttons) removes a part.
+It works only on back ends that support editing.
+
+** gnus-default-charset
+
+The default value now guesses on the basis of your environment instead
+of using Latin-1.  Also the ".*" item in gnus-group-charset-alist is
+removed.
+
+** gnus-posting-styles
+
+Add a new format of match like
+
+        ((header "to" "larsi.*org")
+         (Organization "Somewhere, Inc."))
+
+The old format like the lines below is obsolete, but still accepted.
+
+        (header "to" "larsi.*org"
+         (Organization "Somewhere, Inc."))
+
+** message-ignored-news-headers and message-ignored-mail-headers
+
+X-Draft-From and X-Gnus-Agent-Meta-Information have been added into
+these two variables.  If you customized those, perhaps you need add
+those two headers too.
+
+** Gnus reads the NOV and articles in the Agent if plugged.
+
+If one reads an article while plugged, and the article already exists
+in the Agent, it won't get downloaded once more.  Customize
+`gnus-agent-cache' to revert to the old behavior.
+
+** Gnus supports the "format=flowed" (RFC 2646) parameter.
+
+On composing messages, it is enabled by `use-hard-newlines'.  Decoding
+format=flowed was present but not documented in earlier versions.
+
+** Gnus supports the generation of RFC 2298 Disposition Notification requests.
+
+This is invoked with the C-c M-n key binding from message mode.
+
+** Gnus supports Maildir groups.
+
+Gnus includes a new backend nnmaildir.el.
+
+** Printing capabilities are enhanced.
+
+Gnus supports Muttprint natively with O P from the Summary and Article
+buffers.  Also, each individual MIME part can be printed using p on
+the MIME button.
+
+** Message supports the Importance: (RFC 2156) header.
+
+In the message buffer, `C-c C-f C-i' or `C-c C-u' cycles through the
+valid values.
+
+** Gnus supports Cancel Locks in News.
+
+This means a header "Cancel-Lock" is inserted in news posting.  It is
+used to determine if you wrote a article or not (for cancelling and
+superseding).  Gnus generates a random password string the first time
+you post a message, and saves it using the Custom system.  While the
+variable is called `canlock-password', it is not security sensitive
+data.  Publishing your canlock string on the web will not allow anyone
+to be able to anything she could not already do.  The behaviour can be
+changed by customizing `message-insert-canlock'.
+
+** Gnus supports server-side mail filtering using Sieve.
+
+Sieve rules can be added as Group Parameters for groups, and the
+complete Sieve script is generated using `D g' from the Group buffer,
+and then uploaded to the server using `C-c C-l' in the generated Sieve
+buffer.  Search the online Gnus manual for "sieve", and see the new
+Sieve manual, for more information.
+
+** Extended format specs.
+
+Format spec "%&user-date;" is added into
+`gnus-summary-line-format-alist'.  Also, user defined extended format
+specs are supported.  The extended format specs look like "%u&foo;",
+which invokes function `gnus-user-format-function-foo'.  Because "&" is
+used as the escape character, old user defined format "%u&" is no
+longer supported.
+
+** `/ *' (gnus-summary-limit-include-cached) is rewritten.
+
+It was aliased to `Y c' (gnus-summary-insert-cached-articles). The new
+function filters out other articles.
+
+** Some limiting commands accept a C-u prefix to negate the match.
+
+If C-u is used on subject, author or extra headers, i.e., `/ s', `/
+a', and `/ x' (gnus-summary-limit-to-{subject,author,extra})
+respectively, the result will be to display all articles that do not
+match the expression.
+
+** Group names are treated as UTF-8 by default.
+
+This is supposedly what USEFOR wanted to migrate to.  See
+`gnus-group-name-charset-group-alist' and
+`gnus-group-name-charset-method-alist' for customization.
+
+** The nnml and nnfolder backends store marks for each group.
+
+This makes it possible to take backup of nnml/nnfolder servers/groups
+separately of ~/.newsrc.eld, while preserving marks.  It also makes it
+possible to share articles and marks between users (without sharing
+the ~/.newsrc.eld file) within e.g. a department.  It works by storing
+the marks stored in ~/.newsrc.eld in a per-group file ".marks" (for
+nnml) and "groupname.mrk" (for nnfolder, named "groupname").  If the
+nnml/nnfolder is moved to another machine, Gnus will automatically use
+the .marks or .mrk file instead of the information in ~/.newsrc.eld.
+The new server variables `nnml-marks-is-evil' and
+`nnfolder-marks-is-evil' can be used to disable this feature.
+
+** The menu bar item (in Group and Summary buffer) named "Misc" has
+been renamed to "Gnus".
+
+** The menu bar item (in Message mode) named "MML" has been renamed to
+"Attachments".  Note that this menu also contains security related
+stuff, like signing and encryption.
+
+** gnus-group-charset-alist and gnus-group-ignored-charsets-alist.
+
+The regexps in these variables are compared with full group names
+instead of real group names in 5.8.  Users who customize these
+variables should change those regexps accordingly. For example:
+
+   ("^han\\>" euc-kr) -> ("\\(^\\|:\\)han\\>" euc-kr)
+
+** Gnus supports PGP (RFC 1991/2440), PGP/MIME (RFC 2015/3156) and
+S/MIME (RFC 2630-2633).
+
+It needs an external S/MIME and OpenPGP implementation, but no
+additional lisp libraries.  This add several menu items to the
+Attachments menu, and C-c RET key bindings, when composing messages.
+This also obsoletes `gnus-article-hide-pgp-hook'.
+
+** Gnus inlines external parts (message/external).
+
+** MML (Mime compose) prefix changed from `M-m' to `C-c C-m'.
+
+This change was made to avoid conflict with the standard binding of
+`back-to-indentation', which is also useful in message mode.
+
+** The default for message-forward-show-mml changed to symbol best.
+
+The behaviour for the `best' value is to show MML (i.e., convert MIME
+to MML) when appropriate.  MML will not be used when forwarding signed
+or encrypted messages, as the conversion invalidate the digital
+signature.
+
+** Bug fixes.
+
+\f
+* Changes in Pterodactyl Gnus (5.8/5.9)
+
+The Gnus NEWS entries are short, but they reflect sweeping changes in
+four areas: Article display treatment, MIME treatment,
+internationalization and mail-fetching.
+
+** The mail-fetching functions have changed.  See the manual for the
+many details.  In particular, all procmail fetching variables are gone.
+
+If you used procmail like in
+
+(setq nnmail-use-procmail t)
+(setq nnmail-spool-file 'procmail)
+(setq nnmail-procmail-directory "~/mail/incoming/")
+(setq nnmail-procmail-suffix "\\.in")
+
+this now has changed to 
+
+(setq mail-sources
+      '((directory :path "~/mail/incoming/"
+                  :suffix ".in")))
+
+More information is available in the info doc at Select Methods ->
+Getting Mail -> Mail Sources
+
+** Gnus is now a MIME-capable reader.  This affects many parts of
+Gnus, and adds a slew of new commands.  See the manual for details.
+
+** Gnus has also been multilingualized.  This also affects too
+many parts of Gnus to summarize here, and adds many new variables.
+
+** gnus-auto-select-first can now be a function to be
+called to position point.
+
+** The user can now decide which extra headers should be included in
+summary buffers and NOV files.
+
+** `gnus-article-display-hook' has been removed.  Instead, a number
+of variables starting with `gnus-treat-' have been added.
+
+** The Gnus posting styles have been redone again and now works in a
+subtly different manner.
+
+** New web-based backends have been added: nnslashdot, nnwarchive
+and nnultimate.  nnweb has been revamped, again, to keep up with
+ever-changing layouts.
+
+** Gnus can now read IMAP mail via nnimap.
+
+\f
+* For older news, see Gnus info node "New Features".
+
+----------------------------------------------------------------------
+Copyright information:
+
+Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+   Permission is granted to anyone to make or distribute verbatim copies
+   of this document as received, in any medium, provided that the
+   copyright notice and this permission notice are preserved,
+   thus giving the recipient permission to redistribute in turn.
+
+   Permission is granted to distribute modified versions
+   of this document, or of portions of it,
+   under the above conditions, provided also that they
+   carry prominent notices stating who last changed them.
+\f
+Local variables:
+mode: outline
+paragraph-separate: "[         \f]*$"
+end:
diff --git a/INSTALL.ja b/INSTALL.ja
new file mode 100644 (file)
index 0000000..bb14b03
--- /dev/null
@@ -0,0 +1,91 @@
+T-gnus \e$B$N%$%s%9%H!<%kJ}K!\e(B
+=========================
+
+\e$BI,MW$J$b$N\e(B
+==========
+
+T-gnus \e$B$rMxMQ$9$k$K$O!"0J2<$K<($9%P!<%8%g%s$N\e(B APEL, FLIM \e$B$*$h$S\e(B SEMI
+\e$B%Q%C%1!<%8$,I,MW$G$9$N$G!"\e(BT-gnus \e$B$r%$%s%9%H!<%k$9$kA0$K$=$l$i$r%$%s%9\e(B
+\e$B%H!<%k$7$F$/$@$5$$!#\e(B
+
+o APEL 10.0 \e$B0J>e\e(B
+o FLIM 1.14
+o SEMI 1.14
+
+\e$B$=$l$>$l!"\e(B
+
+ftp://ftp.m17n.org/pub/mule/apel/
+ftp://ftp.m17n.org/pub/mule/flim/flim-1.14/
+ftp://ftp.m17n.org/pub/mule/semi/semi-1.14-for-flim-1.14/
+
+\e$B$+$i%@%&%s%m!<%I$9$k$3$H$,$G$-$^$9!#\e(B
+
+configure \e$B$N<B9T\e(B
+================
+
+\e$B$^$:!"\e(Bconfigure \e$B%9%/%j%W%H$r<B9T$7$^$9!#$$$/$D$+$N%*%W%7%g%s$r;XDj$G$-\e(B
+\e$B$^$9!#\e(B
+
+  --with-emacs=EMACS      compile with EMACS [EMACS=emacs, mule...]
+  --with-xemacs=XEMACS    compile with XEMACS [XEMACS=xemacs]
+  --with-lispdir=DIR      Where to install lisp files
+                          (for XEmacs package, use --with-packagedir instead)
+  --with-etcdir=DIR       Where to install etc files
+  --with-url=DIR          Specify where to find the url package
+  --with-w3=DIR           Specify where to find the w3 package
+  --with-fonts            Assume all fonts required are available
+  --with-packagedir=DIR   package DIR for XEmacs
+  --with-addpath=PATH     search Emacs-Lisp libraries with PATH
+                          use colons to separate directory names
+
+\e$B%3%s%Q%$%k\e(B
+==========
+
+configure \e$B$N<B9T40N;8e!"\e(B`make all' \e$B$r<B9T$7$^$9!#F|K\8lLu$5$l$?\e(B info
+\e$B$rMxMQ$7$?$$>l9g$O!"\e(B`make all-ja' \e$B$r<B9T$7$^$9!#\e(B
+
+\e$B%$%s%9%H!<%k\e(B
+============
+
+`make install' \e$B$r<B9T$9$k$H!"\e(BT-gnus \e$B$NMxMQ$KI,MW$J\e(B Emacs Lisp \e$B%U%!%$%k\e(B
+\e$B$H%P%$%H%3%s%Q%$%k:Q$N\e(B elc \e$B%U%!%$%k$,\e(B ${lispdir} \e$B$K%3%T!<$5$l!"\e(Binfo \e$B%U%!\e(B
+\e$B%$%k$,\e(B ${prefix}/info \e$B$K%3%T!<$5$l$^$9!#\e(B
+
+\e$BF|K\8lLu$5$l$?\e(B info \e$B%U%!%$%k$b%$%s%9%H!<%k$7$?$$>l9g$O!"\e(B
+`make install-ja' \e$B$r<B9T$7$^$9!#\e(B
+
+Emacs 21.x \e$B$^$?$O\e(B XEmacs \e$B$G$O%"%$%3%s$d\e(B gnus \e$B5/F0;~$N%m%4$K2hA|$r;HMQ\e(B
+\e$B$9$k$3$H$,$G$-$^$9!#\e(BT-gnus \e$B$KIUB0$N$3$l$i$N2hA|%U%!%$%k$r%$%s%9%H!<%k\e(B
+\e$B$9$k$K$O\e(B `make install-etc' \e$B$r<B9T$7$^$9!#\e(B
+
+XEmacs \e$B$N>l9g!"\e(B`make install-package' \e$B$^$?$O\e(B `make install-package-ja'
+\e$B$r<B9T$9$k$H!"\e(Bconfigure \e$B$N\e(B --with-packagedir \e$B%*%W%7%g%s$G;XDj$7$?%G%#\e(B
+\e$B%l%/%H%j$K>e5-$N%U%!%$%k$,E,@Z$K%$%s%9%H!<%k$5$l$^$9!#\e(B
+
+T-gnus \e$B$N=`Hw\e(B
+=============
+
+o SEMI \e$B$r;H$&$h$&$K\e(B ~/.emacs \e$B$K0J2<$rDI2C$7$^$9\e(B
+
+  (load "mime-setup")
+
+o configure \e$B$N\e(B --with-lispdir \e$B%*%W%7%g%s$G;XDj$7$?%G%#%l%/%H%j\e(B (\e$BNc$($P\e(B
+  /usr/local/share/emacs/site-lisp/t-gnus) \e$B$r\e(B load-path \e$B$KDI2C$7$^$9\e(B
+
+  ;; mime-setup \e$B$r\e(B load \e$B$7$F$$$k$H\e(B add-path \e$B$H$$$&4X?t$,;H$($^$9\e(B
+  (add-path "/usr/local/share/emacs/site-lisp/t-gnus")
+
+T-gnus \e$B$N<B9T\e(B
+=============
+
+Emacs \e$B$N5/F08e!"\e(B
+
+  M-x gnus
+
+\e$B$H$9$k$+!"\e(B*scratch* \e$B%P%C%U%!$G\e(B Emacs Lisp \e$B$N<0\e(B
+
+  (gnus)
+
+\e$B$rI>2A$9$k$H\e(B T-gnus \e$B$,5/F0$7$^$9!#:G=i$K8=$l$k\e(B *Group* \e$B%P%C%U%!$J$I$G\e(B 
+C-c C-i \e$B$r%?%$%W$9$k$H!"$=$l$>$l$N5!G=$KBP1~$7$?\e(B info \e$B$r8+$k$3$H$,$G$-\e(B
+\e$B$k$N$G!"MxMQJ}K!$K4X$9$k>\$7$$$3$H$K$D$$$F$O\e(B info \e$B$r;2>H$7$F$/$@$5$$!#\e(B
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 05503f4..0000000
--- a/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-EMACS=emacs
-XEMACS=xemacs
-
-all: lick info
-
-lick:
-       cd lisp; $(MAKE) EMACS=$(EMACS) all
-
-# Rule for Lars and nobody else.
-some:
-       cd lisp; $(MAKE) EMACS=$(EMACS) some
-l:
-       cd lisp; $(MAKE) EMACS=$(EMACS) clever
-
-info:
-       cd texi; $(MAKE) EMACS=$(EMACS) all
-
-clean:
-       rm -f */*.orig */*.rej *.orig *.rej
-
-xsome: 
-       cd lisp; $(MAKE) EMACS=$(XEMACS) some
-
-elclean:
-       rm lisp/*.elc
-
-x:
-       make EMACS=xemacs
-
-distclean:
-       make clean
-       rm -r *~
-       for i in lisp texi; do (cd $$i; make distclean); done
-
-osome:
-       make EMACS=emacs-19.34 some
index 5b6b592..c566844 100644 (file)
+prefix = @prefix@
+datadir = @datadir@
+infodir = @infodir@
+lispdir = @lispdir@
 srcdir = @srcdir@
 
 @SET_MAKE@
-EMACS = emacs
-XEMACS = xemacs
+EMACS = @EMACS@
+XEMACS = @XEMACS@
+PACKAGEDIR = @PACKAGEDIR@
+GNUS_PRODUCT_NAME = @GNUS_PRODUCT_NAME@
+
+# It may be needed for Meadow/NTEmacs when sh.exe is used for SHELL.
+# Because Meadow/NTEmacs will get the value of the current-directory from
+# the environment variable PWD, but sh.exe will not take care of it even
+# if the current-directory has changed.  So we should invalidate it.
+PWD=
+
+# It will be used to look for the XEmacs package path if this file is
+# mis-configured (e.g. configured for FSFmacs).
+EXAMINE_PACKAGEDIR = $(XEMACS) -batch -q -no-site-file -eval \
+       "(let (package-dir) \
+          (if (boundp (quote early-packages)) \
+              (let ((dirs (delq nil (append (if early-package-load-path \
+                                                early-packages) \
+                                            (if late-package-load-path \
+                                                late-packages) \
+                                            (if last-package-load-path \
+                                                last-packages))))) \
+                (while (and dirs (not package-dir)) \
+                  (if (file-directory-p (car dirs)) \
+                      (setq package-dir (car dirs) \
+                            dirs (cdr dirs)))))) \
+          (princ (or package-dir \"\")))" 2>/dev/null
 
 all: lick info
 
+all-ja: lick info info-ja
+
 lick:
-       cd lisp && $(MAKE) EMACS=$(EMACS) all
+       cd lisp && $(MAKE) EMACS="$(EMACS)" lispdir="$(lispdir)" all
+
+#install: install-lisp install-info install-etc
+install: install-lisp install-info
+
+install-ja: install install-info-ja
+
+install-lisp:
+       cd lisp && $(MAKE) EMACS="$(EMACS)" lispdir="$(lispdir)" install
+
+install-info:
+       cd texi && $(MAKE) EMACS="$(EMACS)" infodir="$(infodir)" install
+
+install-etc:
+       cd etc && $(MAKE) EMACS="$(EMACS)" install
+
+install-info-ja:
+       cd texi && $(MAKE) EMACS="$(EMACS)" infodir="$(infodir)" install-ja
+
+## Rule for XEmacs package.
+install-package: \
+       xclever-package \
+       remove-extra-files-in-package \
+       install-package-lisp \
+       install-package-info install-package-manifest
+
+install-package-ja: \
+       xclever-package \
+       remove-extra-files-in-package \
+       install-package-lisp \
+       install-package-info install-package-info-ja \
+       install-package-manifest
+
+package: xlick-package xinfo
+
+package-ja: xlick-package xinfo xinfo-ja
+
+# Sub-rule for XEmacs package.
+install-package-lisp:
+       @if test x$(PACKAGEDIR) = x; then \
+         package_dir=`$(EXAMINE_PACKAGEDIR)`; \
+       else \
+         package_dir="$(PACKAGEDIR)"; \
+       fi; \
+       echo "cd lisp && $(MAKE) EMACS=$(XEMACS)" \
+               "lispdir=$$package_dir""/lisp/$(GNUS_PRODUCT_NAME)" \
+               "install-without-compiling"; \
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" \
+               lispdir="$$package_dir""/lisp/$(GNUS_PRODUCT_NAME)" \
+               install-without-compiling
 
-install:
-       cd lisp && $(MAKE) EMACS=$(EMACS) install
-       cd texi && $(MAKE) EMACS=$(EMACS) install
+install-package-info:
+       @if test x$(PACKAGEDIR) = x; then \
+         package_dir=`$(EXAMINE_PACKAGEDIR)`; \
+       else \
+         package_dir="$(PACKAGEDIR)"; \
+       fi; \
+       echo "cd texi && $(MAKE) EMACS=$(XEMACS)" \
+               "infodir=$$package_dir""/info install-info"; \
+       cd texi && $(MAKE) EMACS="$(XEMACS)" \
+               infodir="$$package_dir""/info" install-info
+
+install-package-info-ja:
+       @if test x$(PACKAGEDIR) = x; then \
+         package_dir=`$(EXAMINE_PACKAGEDIR)`; \
+       else \
+         package_dir="$(PACKAGEDIR)"; \
+       fi; \
+       echo "cd texi && $(MAKE) EMACS=$(XEMACS)" \
+               "infodir=$$package_dir""/info install-ja-info"; \
+       cd texi && $(MAKE) EMACS="$(XEMACS)" \
+               infodir="$$package_dir""/info" install-ja-info
+
+install-package-manifest:
+       @if test x$(PACKAGEDIR) = x; then \
+         package_dir=`$(EXAMINE_PACKAGEDIR)`; \
+       else \
+         package_dir="$(PACKAGEDIR)"; \
+       fi; \
+       echo "cd lisp && $(MAKE) EMACS=$(XEMACS) PACKAGEDIR=$$package_dir" \
+               "lispdir=$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" \
+               "install-package-manifest"; \
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" PACKAGEDIR=$$package_dir \
+               lispdir="$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" \
+               install-package-manifest
+
+remove-extra-files-in-package:
+       @if test x$(PACKAGEDIR) = x; then \
+         package_dir=`$(EXAMINE_PACKAGEDIR)`; \
+       else \
+         package_dir="$(PACKAGEDIR)"; \
+       fi; \
+       echo "cd lisp && $(MAKE) EMACS=$(XEMACS) PACKAGEDIR=$$package_dir" \
+               "lispdir=$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" \
+               "remove-extra-files-in-package"; \
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" PACKAGEDIR=$$package_dir \
+               lispdir="$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" \
+               remove-extra-files-in-package
+##
+
+xclever:
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" lispdir="$(lispdir)" clever
+
+xclever-package:
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" \
+       lispdir="$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" clever
+
+xlick:
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" lispdir="$(lispdir)" all
+
+xlick-package:
+       cd lisp && $(MAKE) EMACS="$(XEMACS)" \
+       lispdir="$(PACKAGEDIR)/lisp/$(GNUS_PRODUCT_NAME)" all
+
+xinfo:
+       cd texi && $(MAKE) EMACS="$(XEMACS)" all-info
+
+xinfo-ja:
+       cd texi && $(MAKE) EMACS="$(XEMACS)" ja-info
+
+uninstall:
+       cd lisp && $(MAKE) lispdir="$(lispdir)" uninstall
+       cd texi && $(MAKE) uninstall
+       cd etc && $(MAKE) uninstall
 
 # Rule for Lars and nobody else.
 some:
-       cd lisp && $(MAKE) EMACS=$(EMACS) some
+       cd lisp && $(MAKE) EMACS="$(EMACS)" some
 l:
-       cd lisp && $(MAKE) EMACS=$(EMACS) clever
+       cd lisp && $(MAKE) EMACS="$(EMACS)" clever
 
 info:
-       cd texi && $(MAKE) EMACS=$(EMACS) all
+       cd texi && $(MAKE) EMACS="$(EMACS)" all
+
+info-ja:
+       cd texi && $(MAKE) EMACS=$(EMACS) ja
 
 clean:
        rm -f */*.orig */*.rej *.orig *.rej
-
-xsome:
-       cd lisp && $(MAKE) EMACS=$(XEMACS) some
+       rm -f MANIFEST.*
+       for i in lisp texi; do (cd $$i; $(MAKE) clean); done
 
 elclean:
-       rm lisp/*.elc
+       cd lisp && rm -f *.elc auto-autoloads.el custom-load.el gnus-load.el
 
 x:
-       make EMACS=xemacs
+       $(MAKE) EMACS="$(XEMACS)"
 
-distclean:
-       make clean
-       rm -r *~
-       for i in lisp texi; do (cd $$i; make distclean); done
-       rm -f config.log config.status Makefile
+xsome:
+       $(MAKE) EMACS="$(XEMACS)" some
 
-osome:
-       make EMACS=emacs-19.34 some
+distclean: clean
+       rm -rf *~
+       for i in lisp texi etc texi/ps; do (cd $$i; $(MAKE) distclean); done
+       rm -f config.log config.status config.cache Makefile
 
 config.status: $(srcdir)/configure
        $(SHELL) ./config.status --recheck
diff --git a/Mule23@1934.en b/Mule23@1934.en
new file mode 100644 (file)
index 0000000..ba70609
--- /dev/null
@@ -0,0 +1,179 @@
+How to build T-gnus with Mule 2.3 based on Emacs 19.34.
+
+FIXING loaddefs.el
+==================
+
+Unfortunately, some variables for `message' are predefined in lisp/
+loaddefs.el which is dumped in Mule executable file.  It is uninvited,
+moreover, it has a bad influence.  So you should remove these
+definitions from lisp/loaddefs.el and rebuild Mule.  However, if you
+don't want to rebuild Mule, you may put the following lines in the
+beginning of .emacs file instead of rebuilding Mule.
+
+(let ((symbols '(citation-line-function
+                cite-function courtesy-message default-headers
+                default-mail-headers default-news-headers
+                deletable-headers fcc-handler-function
+                followup-to-function from-style
+                generate-headers-first generate-new-buffers
+                ignored-bounced-headers ignored-cited-headers
+                ignored-mail-headers ignored-news-headers
+                ignored-resent-headers ignored-supersedes-headers
+                included-forward-headers indent-citation-function
+                interactive kill-buffer-on-exit post-method
+                reply-to-function required-mail-headers
+                required-news-headers send-mail-function
+                send-news-function signature
+                signature-before-forwarded-message signature-file
+                signature-separator syntax-checks use-followup-to
+                user-organization-file wide-reply-to-function
+                yank-prefix))
+      symbol)
+  (while symbols
+    (setq symbol (car symbols)
+         symbols (cdr symbol))
+    (makunbound (intern (format "message-%s" symbol)))))
+
+
+INSTALL CUSTOM, APEL, CLIME, SEMI
+=================================
+
+T-gnus requires the latest version of CUSTOM, APEL, CLIME and SEMI;
+CLIME 1.14 provides the same features as FLIM 1.14 for old Emacsen,
+which is currently available from:
+
+ftp://ftp.jpl.org/pub/m17n/clime-1_14-************.tar.gz
+
+You should install these packages before installing T-gnus.  As for
+CUSTOM, you should apply the following patch before building it.
+
+------ cut here ------ cut here ------ cut here ------ cut here ------
+--- custom-1.9962/cus-face.el~ Wed Mar  4 19:52:39 1998
++++ custom-1.9962/cus-face.el  Mon Mar  9 08:05:33 1998
+@@ -96,7 +96,7 @@
+       "Define a new FACE on all frames, ignoring X resources."
+       (interactive "SMake face: ")
+       (or (internal-find-face name)
+-        (let ((face (make-vector 8 nil)))
++        (let ((face (make-vector face-vector-length nil)))
+           (aset face 0 'face)
+           (aset face 1 name)
+           (let* ((frames (frame-list))
+------ cut here ------ cut here ------ cut here ------ cut here ------
+
+By the way, the latest CUSTOM package for Emacs v19 is available from:
+
+ftp://ftp.dina.kvl.dk/pub/Staff/Per.Abrahamsen/custom/custom-1.9962.tar.gz
+
+However, since the `custom-make-dependencies' function does not exist
+in this version of CUSTOM, we will use the contrib/cus-dep.el which is
+imported from Emacs 20.7 when building T-gnus.
+
+
+INSTALL regexp-opt.el
+=====================
+
+Some T-gnus modules use the functions `regexp-opt', etc.  That
+functions are defined in regexp-opt.el(c) in the recent Emacsen,
+however, Mule 2.3 does not contain it in the standard Lisp libraries.
+Copy the file contrib/regexp-opt.el to site-lisp directory (or any
+other directory), and byte-compile it as follows:
+
+   % cp -p contrib/regexp-opt.el /usr/local/share/mule/site-lisp
+   % cd /usr/local/share/mule/site-lisp/
+   % mule -batch -q -no-site-file -f batch-byte-compile regexp-opt.el
+
+
+INSTALL passwd.el
+=================
+
+This module provide the `read-passwd' function.  You have to install
+it if you don't have that function.  To do this:
+
+   % cp -p contrib/passwd.el /usr/local/share/mule/site-lisp
+   % cd /usr/local/share/mule/site-lisp/
+   % mule -batch -q -no-site-file -f batch-byte-compile passwd.el
+
+And add the following line in your .emacs file:
+
+   (autoload 'read-passwd "passwd")
+
+
+INSTALL T-gnus
+==============
+
+There are three ways of making T-gnus with Mule 2.3 based on Emacs 19.34.
+
+1. If you have installed EMU, APEL, CLIME and SEMI packages under the
+   standard load-path, for instance:
+
+   EMU:   /usr/local/share/mule/19.34/site-lisp/
+   APEL:  /usr/local/share/mule/site-lisp/apel/
+   CLIME: /usr/local/share/mule/site-lisp/flim/
+   SEMI:  /usr/local/share/mule/site-lisp/semi/
+
+   What is more, if you have been replaced old CUSTOM with new CUSTOM
+   or if you have installed new CUSTOM directly under the standard
+   load-path as such as /usr/local/share/mule/19.34/site-lisp/, you
+   may have nothing to be done; type the following commands right now.
+
+   % ./configure --with-emacs=mule
+   % make install
+
+   However, if you have installed new CUSTOM in the subdirectory under
+   the standard load-path, use the configure option `--with-addpath='
+   as follows:
+
+   % ./configure --with-emacs=mule\
+     --with-addpath=/usr/local/share/mule/site-lisp/custom/
+   % make install
+
+   or you can use the file subdirs.el under the parent directory of
+   the subdirectory of CUSTOM to add it into load-path which contain
+   the following contents:
+
+   (normal-top-level-add-to-load-path
+    '("custom/" "and the other subdirectories.../"))
+
+   and then just type:
+
+   % ./configure --with-emacs=mule
+   % make install
+
+2. If you have installed EMU, APEL, CLIME and SEMI packages in the
+   non-standard load-path, use the configure option `--with-addpath='
+   with the colon separated directory names where EMU, APEL or CUSTOM
+   packages are installed.  For example:
+
+   % ./configure --with-emacs=mule\
+     --with-addpath=~/elisp/emu/:~/elisp/apel/:~/elisp/custom/
+   % make install
+
+   In this case, you have no need to add paths of CLIME, SEMI if they
+   are installed under the directory which is same as the parent
+   directory of APEL.
+
+3. This is another way to install T-gnus when you have installed EMU,
+   APEL, CLIME and SEMI packages in the non-standard load-path.  Copy
+   the file `sample.lpath.el' which is included in the distribution to
+   `~/.lpath.el' and modify it suitably for your environment.  And
+   then type the following command.
+
+   % ./configure --with-emacs=mule
+   % make install
+
+
+USING emacs-w3m (and Emacs/W3)
+==============================
+The `nnshimbun' web based back end has been moved to the emacs-w3m
+package at 18 June 2003.  You need to install the latest version of
+emacs-w3m if you want to browse web newspapers using T-gnus as before.
+In that case, you *must* delete nnshimbun.el and nnshimbun.elc files
+originated by T-gnus.  Emacs-w3m is an Emacs interface to the external
+command w3m, visit the following pages for more information:
+
+   http://emacs-w3m.namazu.org/
+   http://w3m.sourceforge.net/
+
+Please give up the idea to use Emacs/W3 under Mule 2.3.  There is no
+information, sorry.
diff --git a/Mule23@1934.ja b/Mule23@1934.ja
new file mode 100644 (file)
index 0000000..65b6607
--- /dev/null
@@ -0,0 +1,183 @@
+Emacs 19.34 \e$B$r%Y!<%9$K$7$?\e(B Mule 2.3 \e$B$G\e(B T-gnus \e$B$r:n$kJ}K!!#\e(B
+
+FIXING loaddefs.el
+==================
+
+\e$B;DG0$J$3$H$K$$$/$D$+$N\e(B `message' \e$B$G;H$&JQ?t$,\e(B lisp/loaddefs.el \e$B$GDj5A\e(B
+\e$B$5$l$F$$$F\e(B Mule \e$B$N<B9T%U%!%$%k$KAH$_9~$^$l$F$7$^$C$F$$$^$9!#$3$l$OM>7W\e(B
+\e$B$J$*@$OC$@$7!"$7$+$b0-1F6A$,$"$j$^$9!#$=$3$G$"$J$?$O$=$l$i$NDj5A$r\e(B
+lisp/loaddefs.el \e$B$+$i:o=|$7$F!"\e(BMule \e$B$r:n$jD>$5$J$1$l$P$J$j$^$;$s!#\e(B
+\e$B$7$+$7!"$b$7$"$J$?$,\e(B Mule \e$B$r:n$jD>$9$3$H$rK>$^$J$$$J$i$P!"\e(B.emacs \e$B%U%!\e(B
+\e$B%$%k$N@hF,$K0J2<$N3F9T$r=q$-9~$`$3$H$G!"\e(BMule \e$B$r:n$jD>$9Be$o$j$K$9$k$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+(let ((symbols '(citation-line-function
+                cite-function courtesy-message default-headers
+                default-mail-headers default-news-headers
+                deletable-headers fcc-handler-function
+                followup-to-function from-style
+                generate-headers-first generate-new-buffers
+                ignored-bounced-headers ignored-cited-headers
+                ignored-mail-headers ignored-news-headers
+                ignored-resent-headers ignored-supersedes-headers
+                included-forward-headers indent-citation-function
+                interactive kill-buffer-on-exit post-method
+                reply-to-function required-mail-headers
+                required-news-headers send-mail-function
+                send-news-function signature
+                signature-before-forwarded-message signature-file
+                signature-separator syntax-checks use-followup-to
+                user-organization-file wide-reply-to-function
+                yank-prefix))
+      symbol)
+  (while symbols
+    (setq symbol (car symbols)
+         symbols (cdr symbol))
+    (makunbound (intern (format "message-%s" symbol)))))
+
+
+INSTALL CUSTOM, APEL, CLIME, SEMI
+=================================
+
+T-gnus \e$B$O:G?7HG$N\e(B CUSTOM, APEL, CLIME \e$B$*$h$S\e(B SEMI \e$B$rI,MW$H$7$^$9!#\e(B
+CLIME 1.14 \e$B$O8E$$\e(B Emacs \e$B$K\e(B FLIM 1.14 \e$B$HF1$85!G=$rDs6!$9$k$b$N$G!"8=:_\e(B
+\e$B0J2<$N$b$N$,F~<j$G$-$^$9!#\e(B
+
+ftp://ftp.jpl.org/pub/m17n/clime-1_14-************.tar.gz
+
+\e$B$"$J$?$O$3$l$i$N%Q%C%1!<%8$r\e(B T-gnus \e$B$NA0$K%$%s%9%H!<%k$7$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#\e(BCUSTOM \e$B$K$D$$$F$O!":n$kA0$K$"$J$?$O0J2<$N%Q%C%A$rEv$F$kI,MW$,$"\e(B
+\e$B$j$^$9!#\e(B
+
+------ cut here ------ cut here ------ cut here ------ cut here ------
+--- custom-1.9962/cus-face.el~ Wed Mar  4 19:52:39 1998
++++ custom-1.9962/cus-face.el  Mon Mar  9 08:05:33 1998
+@@ -96,7 +96,7 @@
+       "Define a new FACE on all frames, ignoring X resources."
+       (interactive "SMake face: ")
+       (or (internal-find-face name)
+-        (let ((face (make-vector 8 nil)))
++        (let ((face (make-vector face-vector-length nil)))
+           (aset face 0 'face)
+           (aset face 1 name)
+           (let* ((frames (frame-list))
+------ cut here ------ cut here ------ cut here ------ cut here ------
+
+\e$B$J$*!"\e(BEmacs v19 \e$BMQ$N:G?7$N\e(B CUSTOM \e$B$O0J2<$N$b$N$rF~<j$9$k$3$H$,$G$-$^$9!#\e(B
+
+ftp://ftp.dina.kvl.dk/pub/Staff/Per.Abrahamsen/custom/custom-1.9962.tar.gz
+
+\e$B$?$@$7!"$3$NHG$N\e(B CUSTOM \e$B$K$O\e(B `custom-make-dependencies' \e$B4X?t$,L5$$$N$G!"\e(B
+T-gnus \e$B$N@8@.;~$K\e(B Emacs 20.7 \e$B$+$i0\F~$7$?\e(B contrib/cus-dep.el \e$B$r;H$$$^\e(B
+\e$B$9!#\e(B
+
+
+INSTALL regexp-opt.el
+=====================
+
+T-gnus \e$B$N$$$/$D$+$N%b%8%e!<%k$O\e(B `regexp-opt' \e$B$J$I$N4X?t$r;H$$$^$9!#$=\e(B
+\e$B$l$i$N4X?t$O!":G6a$N\e(B Emacsen \e$B$G$O\e(B regexp-opt.el(c) \e$B$GDj5A$5$l$F$$$k$N\e(B
+\e$B$G$9$,!"\e(BMule 2.3 \e$B$O$=$l$rI8=`$N\e(B Lisp \e$B%i%$%V%i%j$NCf$K4^$s$G$$$^$;$s!#\e(B
+\e$B0J2<$N$h$&$K\e(B contrib/regexp-opt.el \e$B$r\e(B site-lisp \e$B%G%#%l%/%H%j\e(B (\e$B$^$?$OB>\e(B
+\e$B$N%G%#%l%/%H%j\e(B) \e$B$K%3%T!<$7$F!"\e(Bbyte-compile \e$B$7$F2<$5$$!#\e(B
+
+   % cp -p contrib/regexp-opt.el /usr/local/share/mule/site-lisp
+   % cd /usr/local/share/mule/site-lisp/
+   % mule -batch -q -no-site-file -f batch-byte-compile regexp-opt.el
+
+
+INSTALL passwd.el
+=================
+
+\e$B$3$N%b%8%e!<%k$O\e(B `read-passwd' \e$B4X?t$rDs6!$7$^$9!#L5$$>l9g$O%$%s%9%H!<\e(B
+\e$B%k$7$J$1$l$P$J$j$^$;$s!#$=$l$K$O$3$&$7$F2<$5$$!#\e(B
+
+   % cp -p contrib/passwd.el /usr/local/share/mule/site-lisp
+   % cd /usr/local/share/mule/site-lisp/
+   % mule -batch -q -no-site-file -f batch-byte-compile passwd.el
+
+\e$B$=$7$F\e(B .emacs \e$B%U%!%$%k$K0J2<$N9T$rDI2C$7$F2<$5$$!#\e(B
+
+   (autoload 'read-passwd "passwd")
+
+
+INSTALL T-gnus
+==============
+
+Emacs 19.34 \e$B$r%Y!<%9$K$7$?\e(B Mule 2.3 \e$B$G\e(B gnus \e$B$r:n$k$K$O;0$D$NJ}K!$,$"$j\e(B
+\e$B$^$9!#\e(B
+
+1. \e$B$b$7$"$J$?$,\e(B EMU, APEL, CLIME \e$B$*$h$S\e(B SEMI \e$B$N3F%Q%C%1!<%8$rI8=`$N\e(B
+   load-path \e$B$N2<$K%$%s%9%H!<%k$7$F$$$k$H$7$^$9!#Nc$($P$3$&!#\e(B
+
+   EMU:   /usr/local/share/mule/19.34/site-lisp/
+   APEL:  /usr/local/share/mule/site-lisp/apel/
+   CLIME: /usr/local/share/mule/site-lisp/flim/
+   SEMI:  /usr/local/share/mule/site-lisp/semi/
+
+   \e$B$7$+$b!"$b$7$"$J$?$,8E$$\e(B CUSTOM \e$B$r?7$7$$\e(B CUSTOM \e$B$GCV$-49$($F$$$k$+!"\e(B
+   \e$B?7$7$$\e(B CUSTOM \e$B$r\e(B /usr/local/share/mule/19.34/site-lisp/ \e$B$N$h$&$JI8\e(B
+   \e$B=`$N\e(B load-path \e$B$ND>2<$K%$%s%9%H!<%k$7$F$$$k$J$i$P!"$"$J$?$O2?$b$9\e(B
+   \e$B$kI,MW$,$"$j$^$;$s!#:#$9$0$K0J2<$N%3%^%s%I$r%?%$%W$7$F2<$5$$!#\e(B
+
+   % ./configure --with-emacs=mule
+   % make install
+
+   \e$B$7$+$7!"$b$7$"$J$?$,?7$7$$\e(B CUSTOM \e$B$rI8=`$N\e(B load-path \e$B$N2<$N%5%V%G%#\e(B
+   \e$B%l%/%H%j$K%$%s%9%H!<%k$7$F$"$k$J$i$P!"0J2<$N$h$&$K\e(B configure \e$B%*%W\e(B
+   \e$B%7%g%s$N\e(B `--with-addpath=' \e$B$r;H$&$+!"\e(B
+
+   % ./configure --with-emacs=mule\
+     --with-addpath=/usr/local/share/mule/site-lisp/custom/
+   % make install
+
+   \e$B$"$k$$$O$"$J$?$O0J2<$NFbMF$r4^$`!"\e(BCUSTOM \e$B%5%V%G%#%l%/%H%j$N?F%G%#\e(B
+   \e$B%l%/%H%j$N2<$N\e(B subdirs.el \e$B%U%!%$%k$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+   (normal-top-level-add-to-load-path
+    '("custom/" "and the other subdirectories.../"))
+
+   \e$B$=$7$FC1$K\e(B
+
+   % ./configure --with-emacs=mule
+   % make install
+
+   \e$B$H%?%$%W$7$F2<$5$$!#\e(B
+
+2. \e$B$b$7$"$J$?$,\e(B EMU, APEL, CLIME \e$B$*$h$S\e(B SEMI \e$B$N3F%Q%C%1!<%8$rI8=`$G$O\e(B
+   \e$B$J$$\e(B load-path \e$B$K%$%s%9%H!<%k$7$F$$$k$J$i$P!"%3%m%s$G6h@Z$i$l$?\e(B
+   EMU, APEL \e$B$*$h$S\e(B CUSTOM \e$B$,%$%s%9%H!<%k$5$l$F$$$k%G%#%l%/%H%jL>$H\e(B
+   configure \e$B%*%W%7%g%s$N\e(B `--with-addpath=' \e$B$r;H$C$F2<$5$$!#Nc$($P\e(B
+
+   % ./configure --with-emacs=mule\
+     --with-addpath=~/elisp/emu/:~/elisp/apel/:~/elisp/custom/
+   % make
+
+   \e$B$3$N>l9g!"$b$7\e(B CLIME, SEMI \e$B$,\e(B APEL \e$B$N?F%G%#%l%/%H%j$HF1$8%G%#%l%/%H\e(B
+   \e$B%j$N2<$K%$%s%9%H!<%k$5$l$F$$$k$J$i$P!"$=$l$i$N\e(B path \e$B$rDI2C$9$kI,MW\e(B
+   \e$B$O$"$j$^$;$s!#\e(B
+
+3. \e$B$3$l$O!"\e(BEMU, APEL, CLIME \e$B$*$h$S\e(B SEMI \e$B$N3F%Q%C%1!<%8$rI8=`$G$O$J$$\e(B
+   load-path \e$B$K%$%s%9%H!<%k$7$F$$$k>l9g$N!"JL$NJ}K!$G$9!#G[I[$K4^$^$l\e(B
+   \e$B$F$$$k%U%!%$%k\e(B `sample.lpath.el' \e$B$r\e(B `~/.lpath.el' \e$B$K%3%T!<$7$F!"$"\e(B
+   \e$B$J$?$N4D6-$K9g$&$h$&$K=q$-49$($F2<$5$$!#$=$7$F<!$N%3%^%s%I$r%?%$%W\e(B
+   \e$B$7$F2<$5$$!#\e(B
+
+   % ./configure --with-emacs=mule
+   % make install
+
+
+USING emacs-w3m (and Emacs/W3)
+==============================
+\e$B%&%'%V$K4p$E$$$?%P%C%/%(%s%I$G$"$k\e(B `nnshimbun' \e$B$O!"\e(B2003\e$BG/\e(B6\e$B7n\e(B18\e$BF|$r0J$F\e(B
+emacs-w3m \e$B%Q%C%1!<%8$K0\@R$5$l$^$7$?!#:#$^$G$N$h$&$K\e(B T-gnus \e$B$G%&%'%V$N\e(B
+\e$B?7J9$r1\Mw$7$?$$$N$G$"$l$P!":G?7HG$N\e(B emacs-w3m \e$B$r%$%s%9%H!<%k$9$kI,MW\e(B
+\e$B$,$"$j$^$9!#$=$N:]!"\e(B*\e$BI,$:\e(B* T-gnus \e$BM3Mh$N\e(B nnshimbun.el \e$B$H\e(B nnshimbun.elc
+\e$B%U%!%$%k$r>C$7$F2<$5$$!#\e(BEmacs-w3m \e$B$O30It%3%^%s%I\e(B w3m \e$B$X$N\e(B Emacs \e$B$N%$%s\e(B
+\e$B%?!<%U%'!<%9$G$9!#>\:Y>pJs$K$D$$$F$O0J2<$N%Z!<%8$rK,$M$F$_$F2<$5$$!#\e(B
+
+   http://emacs-w3m.namazu.org/
+   http://w3m.sourceforge.net/
+
+Mule 2.3 \e$B$G\e(B Emacs/W3 \e$B$r;H$&$3$H$OD|$a$F2<$5$$!#$9$_$^$;$s$,>pJs$O$"$j\e(B
+\e$B$^$;$s!#\e(B
diff --git a/README-gnus-bbdb.en b/README-gnus-bbdb.en
new file mode 100644 (file)
index 0000000..5ec9011
--- /dev/null
@@ -0,0 +1,129 @@
+-*- mode: text; fill-column: 70; -*-
+
+---
+ If BBDB is used then, bbdb-gnus.elc can't be shared with them before
+Semi-gnus 6.8.X. It is necessary to byte-compile it again.
+
+;; It is a simple way that only bbdb-gnus.el is byte-compiled after
+;; gnus starts.
+
+---
+gnus-bbdb.el
+
+ This is the BBDB API module for Semi-gnus. `mime-bbdb' should not be
+necessary for Semi-gnus, if that module were used.
+
+ You need FLIM 1.11.3 or later (T-gnus requires FLIM 1.14).
+
+ If you are using bbdb-auto-notes-hook, the patch listed at the end
+of this file should be applied. If not, it might not.
+
+ EXAMPLE:
+
+;; You need to set nothing for `mime-bbdb'.
+;(setq mime-bbdb/use-mail-extr nil)
+;(eval-after-load "mail-extr" '(require 'mime-bbdb))
+
+(require 'bbdb)
+(require 'gnus-bbdb)
+(bbdb-initialize 'sc)  ;; 'Gnus or 'gnus should be deleted.
+(add-hook 'gnus-startup-hook 'gnus-bbdb-insinuate)
+
+;; No need to use the following lines under T-gnus 6.15.5 and later.
+;(eval-after-load "message"
+;  '(add-hook 'message-setup-hook 'gnus-bbdb-insinuate-message))
+
+ If you would like to decode the quoted encoded words forcibly, even
+though FLIM does not decode them, put the following lines in your
+.gnus file.
+
+(setq gnus-bbdb/decode-field-body-function
+      (function
+       (lambda (field-body field-name)
+         (eword-decode-string field-body))))
+
+---
+ This is a patch for bbdb-com.el, bbdb-hooks.el and bbdb.el.
+
+------ cut here ------ cut here ------ cut here ------ cut here ------
+--- bbdb-2.34/lisp/bbdb-com.el~        Tue Jan 15 23:00:57 2002
++++ bbdb-2.34/lisp/bbdb-com.el Thu Jan 31 03:55:01 2002
+@@ -1686,7 +1686,7 @@
+           ;; to be enclosed in quotes.  Double-quotes and backslashes have
+           ;; already been escaped.  This quotes a few extra characters as
+           ;; well (!,%, and $) just for common sense.
+-          ((string-match "[][\000-\037\177()<>@,;:.!$%]" name)
++        ((string-match "[][\000-\037\177<>@,;.!$%]" name)
+            (format "\"%s\" <%s>" name net))
+           (t
+            (format "%s <%s>" name net)))))
+--- bbdb-2.34/lisp/bbdb-hooks.el~      Tue Jan 15 09:00:11 2002
++++ bbdb-2.34/lisp/bbdb-hooks.el       Thu Jan 31 03:55:01 2002
+@@ -36,4 +36,6 @@
+ ;;
++(eval-when-compile (require 'cl))
++
+ (require 'bbdb)
+ (require 'bbdb-com)
+@@ -405,13 +407,23 @@
+          ignore
+          field pairs fieldval  ; do all bindings here for speed
+          regexp string notes-field-name notes
+-         replace-p)
++         replace-p extract-field-value-funtion)
+     (set-buffer (marker-buffer marker))
+     (save-restriction
+-      (widen)
+-      (goto-char marker)
+-      (if (and (setq fieldval (bbdb-extract-field-value "From"))
+-               (string-match (bbdb-user-mail-names) fieldval))
++      (let ((function-list bbdb-extract-field-value-function-list)
++          function)
++      (or (progn
++            (while (and (not extract-field-value-funtion)
++                        (setq function (car function-list)))
++              (setq extract-field-value-funtion (funcall function)
++                    function-list (cdr function-list)))
++            extract-field-value-funtion)
++          (progn
++            (widen)
++            (goto-char marker)
++            (setq extract-field-value-funtion 'bbdb-extract-field-value))))
++      (if (and (setq fieldval (funcall extract-field-value-funtion "From"))
++             (string-match (bbdb-user-mail-names) fieldval))
+           ;; Don't do anything if this message is from us.  Note that we have
+           ;; to look at the message instead of the record, because the record
+           ;; will be of the recipient of the message if it is from us.
+@@ -421,7 +433,7 @@
+           (goto-char marker)
+           (setq field (car (car ignore-all))
+                 regexp (cdr (car ignore-all))
+-                fieldval (bbdb-extract-field-value field))
++                fieldval (funcall extract-field-value-funtion field))
+           (if (and fieldval
+                    (string-match regexp fieldval))
+               (setq ignore t)
+@@ -434,7 +446,8 @@
+                 pairs (cdr (car rest))  ; (REGEXP . STRING) or
+                                         ; (REGEXP FIELD-NAME STRING) or
+                                         ; (REGEXP FIELD-NAME STRING REPLACE-P)
+-                fieldval (bbdb-extract-field-value field)) ; e.g., Subject line
++                fieldval (funcall extract-field-value-funtion field))
++                                        ; e.g., Subject line
+           (when fieldval
+             ;; we perform the auto notes stuff only for authors of a message
+             ;; or if explicitly requested
+--- bbdb-2.34/lisp/bbdb.el~    Tue Jan 15 23:00:58 2002
++++ bbdb-2.34/lisp/bbdb.el     Thu Jan 31 03:55:01 2002
+@@ -737,6 +737,7 @@
+ (defvar bbdb-showing-changed-ones nil)
+ (defvar bbdb-modified-p nil)
+ (defvar bbdb-address-print-formatting-alist) ; "bbdb-print"
++(defvar bbdb-extract-field-value-function-list nil)
+ (defvar bbdb-debug t)
+ (defmacro bbdb-debug (&rest body)
+------ cut here ------ cut here ------ cut here ------ cut here ------
+
+---
diff --git a/README-gnus-bbdb.ja b/README-gnus-bbdb.ja
new file mode 100644 (file)
index 0000000..a2667c8
--- /dev/null
@@ -0,0 +1,163 @@
+-*- mode: text; fill-column: 70; -*-
+
+---
+BBDB \e$B$r;HMQ$5$l$F$$$kJ}$O!"\e(B bbdb-gnus.elc \e$B$r\e(B Semi-gnus 6.8.X \e$B0JA0$N$b\e(B
+\e$B$N$H6&M-$9$k$3$H$O$G$-$^$;$s!#I,$:!"\e(B byte-compile \e$B$7D>$7$F$/$@$5$$!#\e(B
+
+;; gnus \e$B$r5/F0$7$?$"$H$G!"\e(B bbdb-gnus.el \e$B$N$_$r\e(B byte-compile \e$B$9$k$H$$$&\e(B
+;; \e$B$N$,$*<j7Z$G$9!#\e(B :-)
+
+---
+gnus-bbdb.el
+
+Semi-gnus \e$B$KFC2=$7$?\e(B BBDB API \e$B%b%8%e!<%k$G$9!#$3$N%b%8%e!<%k$r;HMQ$9$k\e(B
+\e$B$3$H$K$h$C$F!"\e(B Semi-gnus \e$B$G;HMQ$9$k>l9g$K$O\e(B mime-bbdb \e$B$,ITMW$K$J$j$^$9!#\e(B
+
+1.11.3 \e$B0J9_$N\e(B FLIM \e$B$,I,MW\e(B (T-gnus \e$B$G$O\e(B FLIM 1.14 \e$B$,I,MW\e(B) \e$B$G$9!#\e(B
+
+bbdb-auto-notes-hook \e$B$r;HMQ$7$F$$$J$$J}$K$OITMW$G$9$,!";HMQ$7$F$$$kJ}\e(B
+\e$B$O\e(B bbdb.el / bbdb-hooks.el \e$B$K$3$N%U%!%$%k$N:G8e$K$"$k\e(B patch \e$B$r$"$F$kI,\e(B
+\e$BMW$,$"$j$^$9!#\e(B
+
+\e$B@_DjNc\e(B:
+
+;; mime-bbdb \e$B$K4X$9$k@_Dj$OITMW$G$9!#\e(B
+;(setq mime-bbdb/use-mail-extr nil)
+;(eval-after-load "mail-extr" '(require 'mime-bbdb))
+
+(require 'bbdb)
+(require 'gnus-bbdb)
+(bbdb-initialize 'sc)  ;; 'gnus / 'Gnus \e$B$O$O$:$7$F$/$@$5$$!#\e(B
+(add-hook 'gnus-startup-hook 'gnus-bbdb-insinuate)
+
+;; T-gnus 6.15.5 \e$B0J>e$G$OITMW$G$9!#\e(B
+;(eval-after-load "message"
+;  '(add-hook 'message-setup-hook 'gnus-bbdb-insinuate-message))
+
+FLIM \e$B$G$O\e(B quote \e$B$5$l$?\e(B eword encoded word \e$B$O\e(B decode \e$B$5$l$^$;$s$,!"$=$l\e(B
+\e$B$r6/@)E*$K\e(B decode \e$B$7$?$$>l9g$K$O!"<!$N@_Dj$r2C$($F$/$@$5$$!#\e(B
+
+(setq gnus-bbdb/decode-field-body-function
+      (function
+       (lambda (field-body field-name)
+         (eword-decode-string field-body))))
+
+---
+\e$B0J2<$O\e(B bbdb-com.el\e$B!"\e(Bbbdb-hooks.el \e$B$*$h$S\e(B bbdb.el \e$B$K$"$F$k\e(B patch \e$B$G$9!#\e(B
+
+------ cut here ------ cut here ------ cut here ------ cut here ------
+--- bbdb-2.34/lisp/bbdb-com.el~        Tue Jan 15 23:00:57 2002
++++ bbdb-2.34/lisp/bbdb-com.el Thu Jan 31 03:55:01 2002
+@@ -1686,7 +1686,7 @@
+           ;; to be enclosed in quotes.  Double-quotes and backslashes have
+           ;; already been escaped.  This quotes a few extra characters as
+           ;; well (!,%, and $) just for common sense.
+-          ((string-match "[][\000-\037\177()<>@,;:.!$%]" name)
++        ((string-match "[][\000-\037\177<>@,;.!$%]" name)
+            (format "\"%s\" <%s>" name net))
+           (t
+            (format "%s <%s>" name net)))))
+--- bbdb-2.34/lisp/bbdb-hooks.el~      Tue Jan 15 09:00:11 2002
++++ bbdb-2.34/lisp/bbdb-hooks.el       Thu Jan 31 03:55:01 2002
+@@ -36,4 +36,6 @@
+ ;;
++(eval-when-compile (require 'cl))
++
+ (require 'bbdb)
+ (require 'bbdb-com)
+@@ -405,13 +407,23 @@
+          ignore
+          field pairs fieldval  ; do all bindings here for speed
+          regexp string notes-field-name notes
+-         replace-p)
++         replace-p extract-field-value-funtion)
+     (set-buffer (marker-buffer marker))
+     (save-restriction
+-      (widen)
+-      (goto-char marker)
+-      (if (and (setq fieldval (bbdb-extract-field-value "From"))
+-               (string-match (bbdb-user-mail-names) fieldval))
++      (let ((function-list bbdb-extract-field-value-function-list)
++          function)
++      (or (progn
++            (while (and (not extract-field-value-funtion)
++                        (setq function (car function-list)))
++              (setq extract-field-value-funtion (funcall function)
++                    function-list (cdr function-list)))
++            extract-field-value-funtion)
++          (progn
++            (widen)
++            (goto-char marker)
++            (setq extract-field-value-funtion 'bbdb-extract-field-value))))
++      (if (and (setq fieldval (funcall extract-field-value-funtion "From"))
++             (string-match (bbdb-user-mail-names) fieldval))
+           ;; Don't do anything if this message is from us.  Note that we have
+           ;; to look at the message instead of the record, because the record
+           ;; will be of the recipient of the message if it is from us.
+@@ -421,7 +433,7 @@
+           (goto-char marker)
+           (setq field (car (car ignore-all))
+                 regexp (cdr (car ignore-all))
+-                fieldval (bbdb-extract-field-value field))
++                fieldval (funcall extract-field-value-funtion field))
+           (if (and fieldval
+                    (string-match regexp fieldval))
+               (setq ignore t)
+@@ -434,7 +446,8 @@
+                 pairs (cdr (car rest))  ; (REGEXP . STRING) or
+                                         ; (REGEXP FIELD-NAME STRING) or
+                                         ; (REGEXP FIELD-NAME STRING REPLACE-P)
+-                fieldval (bbdb-extract-field-value field)) ; e.g., Subject line
++                fieldval (funcall extract-field-value-funtion field))
++                                        ; e.g., Subject line
+           (when fieldval
+             ;; we perform the auto notes stuff only for authors of a message
+             ;; or if explicitly requested
+--- bbdb-2.34/lisp/bbdb.el~    Tue Jan 15 23:00:58 2002
++++ bbdb-2.34/lisp/bbdb.el     Thu Jan 31 03:55:01 2002
+@@ -737,6 +737,7 @@
+ (defvar bbdb-showing-changed-ones nil)
+ (defvar bbdb-modified-p nil)
+ (defvar bbdb-address-print-formatting-alist) ; "bbdb-print"
++(defvar bbdb-extract-field-value-function-list nil)
+ (defvar bbdb-debug t)
+ (defmacro bbdb-debug (&rest body)
+------ cut here ------ cut here ------ cut here ------ cut here ------
+
+---
+gnus-bbdb/split-mail()
+
+nnmail-split-fancy \e$B$G;HMQ$9$k$?$a$N4X?t$G$9!#<!$N$h$&$K;HMQ$7$F$/$@$5$$!#\e(B
+
+(setq nnmail-split-methods 'nnmail-split-fancy
+      nnmail-split-fancy
+      '(|
+        .....
+*1      (: gnus-bbdb/split-mail "from\\|to\\|cc"
+           'company "foo" "foo-group") 
+        .....
+*2      (: gnus-bbdb/split-mail "from\\|to\\|cc" 'company "^bar")
+        .....
+*3      (: gnus-bbdb/split-mail "from\\|to\\|cc" 'group)
+        .....
+*4      (: gnus-bbdb/split-mail "from\\|to\\|cc" 'note "my friend"
+          '(|
+             .....
+        .....
+        ))
+
+*1 : From, To, Cc \e$B$$$:$l$+$N%X%C%@!<!&%U%#!<%k%I$K4^$^$l$k%a%$%k!&%"%I\e(B
+     \e$B%l%9$N$&$A\e(B BBDB \e$B$N\e(B `company' \e$B%U%#!<%k%I$K\e(B `foo' \e$B$,4^$^$l$k>l9g!"\e(B
+     `foo-group' \e$B$K?6$jJ,$1$^$9!#\e(B
+
+*2 : `company' \e$B%U%#!<%k%I$,\e(B `bar' \e$B$G;O$^$C$F$$$k>l9g!"\e(B`company' \e$B%U%#!<\e(B
+     \e$B%k%I$NFbMF$r$=$N$^$^%0%k!<%WL>$H$7$F;HMQ$7!"?6$jJ,$1$^$9!#\e(B
+
+*3 : `group' \e$B%U%#!<%k%I$,$"$k>l9g!"\e(B`group' \e$B%U%#!<%k%I$NFbMF$r$=$N$^$^\e(B
+     \e$B%0%k!<%WL>$H$7$F;HMQ$7!"?6$jJ,$1$^$9!#\e(B
+
+*4 : `note' \e$B%U%#!<%k%I$K\e(B `my friend' \e$B$,4^$^$l$k>l9g!"$=$N8e$m$K;XDj$5\e(B
+     \e$B$l$?5,B'$G?6$jJ,$1$^$9!#$3$N5,B'$N5-=RJ}K!$O!"DL>o$N\e(B
+     `nnmail-split-fancy' \e$B$G$N5-=RJ}K!$HF1$8$b$N$G$9!#\e(B
diff --git a/README-offline.en b/README-offline.en
new file mode 100644 (file)
index 0000000..65af7ee
--- /dev/null
@@ -0,0 +1,203 @@
+1) What's "gnus-offline (Gnus Offline Backend Utility)" ?
+=========================================================
+
+This program is a utility for T-gnus that handles messages
+(i.e. mail and news) in the "offline" state in a more simple way.
+
+It is basically designed for "gnus-agent". (See info about gnus-agent.)
+
+You can also use it with a function "nnspool"(*1) (which needs an
+external program such as "gnspool"(*2) ), or with "miee.el"(*3) for
+posting and/or sending messages.
+
+     (*1) See info about nnspool.
+     (*2) gnspool comes with a newsreader "gn".
+     (*3) The latest version of miee.el (or MIEE) is available at
+          http://www.shiojiri.ne.jp/%7Et-ichi/meadow.html
+
+You can handle messages in the offline state without "gnus-offline",
+but "gnus-offline" provides a simple way for setup and operation.
+
+**Features**
+
+o Simple configuration -- An "INTERACTIVE" configuration to set
+         the variables.
+
+o Simple operation -- Type "g" in the *Group* buffer, and gnus-offline
+         will:
+           o Dial (*)
+           o Send mails & post news articles
+           o Fetch new mails & articles
+           o Hang up (*)
+
+      (*) For dialing and hanging up, external softwares are needed.
+          But you can do without ones if you connect and disconnect
+          manually.
+
+This document is written mainly for the case using "gnus-agent" with
+gnus-offline.el bundled in T-gnus 6.12.0 or later.
+
+2) Installation
+===============
+
+As you are reading this document, this version of T-gnus includes
+gnus-offline. Installation is simple. "make install" will
+automatically install "gnus-offline".
+
+3) How to use
+=============
+
+o First, you must do a general setup for T-gnus (See info about the
+  setup).
+
+o Add the following code to ~/.emacs
+
+        (autoload 'gnus-plugged "gnus-agent" nil t)
+        (autoload 'gnus-unplugged "gnus-agent" nil t)
+
+o Add the following code to ~/.emacs
+
+       (load "gnus-ofsetup")
+       (gnus-setup-for-offline)
+
+o Add the following code to ~/.gnus
+
+       (gnus-agentize)
+
+o Restart Emacs. gnus-ofsetup.el will ask you some questions and
+ create ~/.gnus-offline.el. (*)
+
+      (*) If you don't know how to answer some questions, typing "TAB"
+          key may show you the possible answers. See the next section
+          which explains the user options.
+          You will also be asked whether to save the POP password in
+          ~/.newsrc.eld or not. Answer it carefully. See section 6)
+          for details.
+
+o At the first time, you must start Gnus in the online state
+ (by M-x gnus-plugged) and decide which groups to subscribe (See info
+ about subscribing).
+
+ From now on you can start Gnus as an offline reader by M-x gnus-unplugged.
+ Try typing "g" in the *Group* buffer.
+
+o You may want M-x gnus to start Gnus as an offline reader as
+ M-x gnus-unplugged. Then write the following code to ~/.emacs
+
+       (setq gnus-plugged nil)
+
+ you can put it into ~/.gnus if there's no need to start Gnus as an online
+ reader (by M-x gnus-plugged).
+
+4) User customizable variables in gnus-offline
+==============================================
+
+o gnus-offline-dialup-program
+    Program name to dialup.
+
+o gnus-offline-dialup-program-arguments
+    List of dialup program arguments.
+
+o gnus-offline-hangup-program
+    Program name to hangup.
+
+o gnus-offline-hangup-program-arguments
+    List of hangup program arguments.
+
+o gnus-offline-mail-spool-directory
+    Spool directory for sending mail.
+    This variable is available only using MIEE.
+
+o gnus-offline-news-spool-directory
+    Spool directory for sending news.
+    This variable is available only using MIEE.
+
+o gnus-offline-mail-treat-environ
+    If t , gnus-offline sends mail to spool first.
+    If nil , gnus-offline sends mail immediately.
+
+o gnus-offline-articles-to-fetch
+    Article type you want to fetch.
+
+       'both ... Fetch both Mail/News.
+       'Mail ... Fetch only Mail.
+       'News ... Fetch only News.
+
+    Default value is both.
+
+o gnus-offline-load-hook
+    Hook before gnus-offline load.
+
+o gnus-offline-before-online-hook
+    Hook before all online jobs.
+
+o gnus-offline-after-online-hook
+    Hook after all online jobs.
+
+o gnus-offline-interval-time
+    Interval time to do all online jobs.(minutes)
+
+o gnus-offline-MTA-type
+    MTA type to sending mail.
+
+   'smtp     ... Use smtp.el.
+   'sendmail ... Use sendmail.el.
+
+o gnus-offline-drafts-queue-type
+   Message queue type when spooling message.
+
+   'miee  ... Use miee.el.
+   'agent ... Use gnus-agent.el.
+
+o gnus-offline-after-empting-spool-hook
+   Hook before empting spool.
+
+o gnus-offline-before-empting-spool-hook
+   Hook after emoting spool.
+
+o gnus-offline-dialup-function
+   Function to dialup.
+
+o gnus-offline-hangup-function
+   Function to hangup.
+
+5) Commands in gnus-offline
+===========================
+
+o M-x gnus-offline-toggle-plugged
+   Toggle offline/online state.
+
+o M-x gnus-offline-toggle-auto-hangup
+   Change current state to offline.
+
+o M-x gnus-offline-toggle-on/off-send-mail
+   Toggle method to sending mail.
+
+o M-x gnus-offline-toggle-articles-to-fetch
+   Toggle articles you want to fetch.
+
+o M-x gnus-offline-set-interval-time
+   Set interval time(minute) to fetch article.
+
+o M-x gnus-offline-agent-expire
+   Expire articles.
+
+6) [!!!IMPORTANT!!!] About the pop password
+===========================================
+
+If your machine is stand alone, and nobody else uses it, you can save
+the password. (But, on your own responsibility!)
+
+At the first interactive configuration, it will ask you whether to
+save the password in ~/.newsrc.eld or not. When you answer "y" to this
+question, the password will be saved in ~/.newsrc.eld. (*)
+
+       (*) Actually the following will be added to ~/.gnus-offline.el.
+
+           (add-hook
+            'gnus-setup-news-hook
+            (lambda ()
+              (add-to-list 'gnus-variable-list 'mail-source-password-cache)))
+
+Answer this question carefully, because the password will NOT be
+encoded!
diff --git a/README-offline.ja b/README-offline.ja
new file mode 100644 (file)
index 0000000..40e7245
--- /dev/null
@@ -0,0 +1,206 @@
+1) gnus-offline (Gnus Offline Backend Utility)\e$B$C$F2?\e(B?
+
+\e$B$3$l$O\e(B T-gnus \e$B$G%a%C%;!<%8$r$h$jMF0W$K%*%U%i%$%s4D6-$G07$&$?$a$N%f!<%F%#\e(B
+\e$B%j%F%#$G$9!#\e(B
+
+\e$B<g$H$7$F\e(B T-gnus \e$B$N\e(B `Agent' \e$B$H8F$P$l$k5!G=$N$?$a$K=q$+$l$F$$$^$9!#\e(B
+
+\e$B$^$?!"\e(Bgnspool \e$B$J$I$N30It%W%m%0%i%`$rMQ$$$?\e(B nnspool \e$B$G$b;H$&$3$H$,$G$-\e(B
+\e$B$^$9!#$^$?!"JLESG[I[$N\e(B miee.el \e$B$rAw?.$K;HMQ$9$k$3$H$b2DG=$G$9!#\e(B
+
+     (*) nspool \e$B$K$D$$$F$O\e(B info \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+     (*) gnspool \e$B$O\e(B gn \e$B$H$$$&%K%e!<%9%j!<%@!<$H6&$KG[I[$5$l$F$$$^$9!#\e(B
+     (*) miee.el \e$B$N:G?7HG$O0J2<$N>l=j$+$i<hF@$G$-$^$9!#\e(B
+         http://www.shiojiri.ne.jp/%7Et-ichi/meadow.html
+
+;; gnus-offline \e$B$r;H$o$J$/$F$b%*%U%i%$%s$G$NFI$_=q$-$O=PMh$^$9$,!"\e(B
+;; gnus-offline \e$B$r;H$($P$h$j@_Dj!&A`:n$,4JC1$K=PMh$^$9!#\e(B
+
+\e$B6qBNE*$K$O\e(B
+
+\e$B!&F0:n$KI,MW$JJQ?t$NBPOCE*@_Dj$,2DG=\e(B
+
+\e$B!&%0%k!<%W%P%C%U%!$G!H\e(Bg\e$B!I$H%?%$%W$9$k$@$1$G!"%@%$%"%k%"%C%W\e(B->\e$B%a%$%k\e(B
+  \e$B$*$h$S\e(B \e$B%M%C%H%K%e!<%9$NAw<u?.\e(B->\e$B%@%$%"%k%"%C%W$N@ZCG\e(B \e$B$H$$$&F0:n$r0l5$\e(B
+  \e$B$K9T$&$3$H$,2DG=$K$J$j$^$9!#\e(B(\e$B$?$@$7@\B3!&$*$h$S@ZCG$OJLES@lMQ$N%D!<\e(B
+  \e$B%k$,I,MW$G$9\e(B)
+
+\e$B$J$*!"$3$N%I%-%e%a%s%H$G$O<g$K\e(B T-gnus 6.12.0 \e$B0J9_$KImB0$9$k\e(B 
+gnus-offline.el \e$B$K$D$$$F!"Aw<u?.$H$b$K\e(B gnus-agent\e$B$r;H$&$3$H$rA0Ds$K2r\e(B
+\e$B@b$7$^$9!#\e(B
+
+2) \e$B%$%s%9%H!<%k\e(B
+
+T-gnus \e$B$r$*;H$$$N>l9g!"\e(Bgnus-offline.el \e$B$OFC$K2?$b9M$($J$/$F$b\e(B T-gnus
+\e$B$HF1;~$K%$%s%9%H!<%k$5$l$^$9!#\e(B
+
+3) \e$B;H$$J}\e(B
+
+\e$B!&\e(BT-gnus \e$B$N0lHLE*$J;HMQJ}K!$K$D$$$F\e(B info \e$B$J$I$GD4$Y$F@_Dj$7$F$/$@$5$$!#\e(B
+
+\e$B!&0J2<$N%3!<%I$r\e(B .emacs \e$B$K2C$($^$9!#\e(B
+
+        (autoload 'gnus-plugged "gnus-agent" nil t)
+        (autoload 'gnus-unplugged "gnus-agent" nil t)
+
+\e$B!&0J2<$N%3!<%I$r\e(B .emacs \e$B$K2C$($^$9!#\e(B
+
+       (load "gnus-ofsetup")
+       (gnus-setup-for-offline)
+
+\e$B!&0J2<$N%3!<%I$r\e(B .gnus \e$B$K2C$($^$9!#\e(B
+
+       (gnus-agentize)
+
+\e$B!&\e(BEmacs \e$B$r:F5/F0$7$^$9!#$9$k$H!"\e(Bgnus-ofsetup.el \e$B$,5/F0$7$^$9$N$G!"BPOC\e(B
+  \e$BE*$KI,MW$JJQ?t$N@_Dj$r9T$$$^$9!#\e(B
+    (\e$B2?$rF~NO$7$?$i$$$$$+$o$+$i$J$$>l9g$O\e(B 4) \e$B$r;2>H$9$k$+!"\e(BTAB \e$B$GF~NO\e(B
+     \e$B2DG=$J8uJd$r0lMwI=<($5$;$k$+$7$F$/$@$5$$\e(B)
+  \e$B$9$Y$F@_Dj$9$k$H%[!<%`%G%#%l%/%H%j$K\e(B .gnus-offline.el \e$B$H$$$&%U%!%$%k\e(B
+  \e$B$,=PMh>e$,$j$^$9!#\e(B(*)
+
+      (*) \e$B!V\e(BPOP \e$B%Q%9%o!<%I$r\e(B ~/.newsrc.eld \e$B$KJ]B8$9$k$+$I$&$+!W<ALd$5\e(B
+          \e$B$l$^$9!#$3$l$K$O$h$/9MN8$7$?>e$GEz$($F$/$@$5$$!#>\$7$/$O\e(B 6)
+          \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+\e$B!&$3$N$"$H0lC6\e(B M-x gnus-plugged \e$B$G\e(B Gnus \e$B$r5/F0$7$F!"9XFI$9$k%0%k!<%W$r\e(B
+  \e$B7h$a$F$/$@$5$$!#\e(B(\e$B>\$7$$J}K!$O\e(B Gnus \e$B$N\e(B info \e$B$r8+$F$/$@$5$$\e(B)
+
+  \e$B$=$7$F\e(B \e$B<!2s$+$i$O\e(B M-x gnus-unplugged \e$B$G\e(B Gnus \e$B$r5/F0$7$F$/$@$5$$!#%0%k!<\e(B
+  \e$B%W%P%C%U%!$G!H\e(Bg\e$B!I$H%?%$%W$9$k$3$H$K$h$jA05-$NF0:n$r$9$k$O$:$G$9!#\e(B
+
+\e$B!&\e(BM-x gnus \e$B$G$b%*%U%i%$%s5/F0$7$FM_$7$$>l9g$O!"\e(B.emacs \e$B$K\e(B
+
+       (setq gnus-plugged nil)
+
+  \e$B$r=q$$$F2<$5$$!#$b$7\e(B M-x gnus-plugged \e$B$r;H$o$J$$$J$i$P!"$3$l$r\e(B .gnus \e$B$K\e(B
+  \e$B=q$/$H$$$&<j$b$"$k$G$7$g$&!#\e(B
+
+4) gnus-offline \e$B$G@_Dj2DG=$JJQ?t0lMw\e(B
+
+\e$B!&\e(Bgnus-offline-dialup-program
+    \e$B%@%$%"%k%"%C%W$9$k%W%m%0%i%`L>\e(B
+
+\e$B!&\e(Bgnus-offline-dialup-program-arguments
+    \e$B%@%$%"%k%"%C%W%W%m%0%i%`$N0z?t$N%j%9%H\e(B
+    \e$BNc$($P!"\e(Bgnus-offline-dialup-program \e$B$K\e(B "-s AAA" \e$B$rEO$9>l9g$O\e(B
+    (setq gnus-offline-dialup-program-arguments '("-s" "AAA"))
+    \e$B$H5-=R$7$F$/$@$5$$!#\e(B
+
+\e$B!&\e(Bgnus-offline-hangup-program
+    \e$B2s@~$r@ZCG$9$k%W%m%0%i%`L>\e(B
+
+\e$B!&\e(Bgnus-offline-hangup-program-arguments
+    \e$B@ZCG$9$k%W%m%0%i%`$N0z?t$N%j%9%H\e(B
+    \e$BNc$($P!"\e(Bgnus-offline-hangup-program \e$B$K\e(B "-s AAA" \e$B$rEO$9>l9g$O\e(B
+    (setq gnus-offline-hangup-program-arguments '("-s" "AAA"))
+    \e$B$H5-=R$7$F$/$@$5$$!#\e(B
+
+\e$B!&\e(Bgnus-offline-mail-spool-directory
+    \e$BAw?.%a!<%k$N%9%W!<%k%G%#%l%/%H%j\e(B
+    Offline \e$B>uBV$G\e(B Mail \e$B$rAw?.$9$k$H0lC6$3$3$G;XDj$7$?%G%#%l%/%H%j$KJ]\e(B
+    \e$BB8$5$l$^$9!#\e(B
+    MIEE \e$B$r;HMQ$9$k>l9g0J30L58z$G$9!#\e(B
+
+\e$B!&\e(Bgnus-offline-news-spool-directory
+    \e$BAw?.%K%e!<%9$N%9%W!<%k%G%#%l%/%H%j\e(B
+    Offline \e$B>uBV$G\e(B News \e$B$rAw?.$9$k$H0lC6$3$3$G;XDj$7$?%G%#%l%/%H%j$KJ]\e(B
+    \e$BB8$5$l$^$9!#\e(B
+    MIEE \e$B$r;HMQ$9$k>l9g0J30L58z$G$9!#\e(B
+
+\e$B!&\e(Bgnus-offline-mail-treat-environ
+    Mail \e$B$NAw?.$r\e(B Online/Offline \e$B$G9T$&;v$r@Z$jBX$($k\e(B
+
+\e$B!&\e(Bgnus-offline-articles-to-fetch
+    fetch \e$B$9$k5-;v$r@Z$jBX$($k\e(B both->mail->news->both...
+       'both ... Mail/News \e$B$rN>J}<u?.\e(B
+       'Mail ... Mail \e$B$@$1<u?.\e(B
+       'News ... News \e$B$@$1<u?.\e(B
+    \e$B%G%U%)%k%HCM$O\e(B 'both \e$B$G$9!#\e(B
+
+\e$B!&\e(Bgnus-offline-load-hook
+    gnus-offline \e$B$,\e(B load \e$B$5$l$k$H$-$KI>2A$5$l$k\e(B hook
+
+\e$B!&\e(Bgnus-offline-before-online-hook
+    Online job \e$BD>A0$KI>2A$5$l$k\e(B hook
+
+\e$B!&\e(Bgnus-offline-after-online-hook
+    Online job \e$B=*N;D>A0$KI>2A$5$l$k\e(B hook
+
+\e$B!&\e(Bgnus-offline-interval-time
+    Online job \e$B$r9T$&4V3V\e(B(\e$BJ,\e(B)
+    Emacs \e$B$,\e(B idle \e$B>uBV$K$J$C$F$+$i$3$3$G;XDj$7$?;~4VKh$K\e(B Online \e$B>uBV$K\e(B
+    \e$B$7\e(B Mail/News \e$B$r<hF@$7$^$9!#\e(B
+
+\e$B!&\e(Bgnus-offline-MTA-type
+    Message \e$B$r\e(B Online \e$B;~$KAw?.$9$k%W%m%0%i%`$N%?%$%W$G!"%G%U%)%k%H$O\e(B
+    'smtp \e$B$G$9!#\e(B
+   'smtp     ... smtp.el \e$B$r;HMQ\e(B
+   'sendmail ... sendmail.el \e$B$r;HMQ\e(B
+
+\e$B!&\e(Bgnus-offline-drafts-queue-type
+   \e$BAw?.%a%C%;!<%8$r%-%e!<$KN/$a$k$b$N$N%?%$%W$G!"%G%U%)%k%H$O\e(B 'miee \e$B$G\e(B
+   \e$B$9!#\e(B
+   'miee \e$B$O\e(B miee.el \e$B$r;HMQ\e(B.
+   'agent \e$B$O\e(B gnus-agent.el \e$B$r;HMQ\e(B.
+
+\e$B!&\e(Bgnus-offline-after-empting-spool-hook
+  \e$BAw?.%a%C%;!<%8$N%-%e!<$r6u$K$9$kA0$KI>2A$5$l$k\e(B hook
+
+\e$B!&\e(Bgnus-offline-before-empting-spool-hook
+  \e$BAw?.%a%C%;!<%8$rAw?.8e$K!"6u$K$J$C$?8eI>2A$5$l$k\e(B hook
+
+\e$B!&\e(Bgnus-offline-dialup-function
+  \e$B@\B3$K;HMQ$9$k4X?tL>\e(B
+
+\e$B!&\e(Bgnus-offline-hangup-function
+  \e$B@ZCG$K;HMQ$9$k4X?tL>\e(B
+
+\e$B!&\e(Bgnus-offline-mail-source
+  \e$B%a!<%k%5!<%P!<!"%f!<%6!<L>$N%j%9%H\e(B
+
+5) gnus-offline M-x \e$B$G<B9T2DG=$J%3%^%s%I0lMw\e(B
+
+\e$B!&\e(BM-x gnus-offline-toggle-plugged
+  offline \e$B>uBV\e(B/Online \e$B>uBV$r@ZBX$($^$9!#\e(B
+
+\e$B!&\e(BM-x gnus-offline-toggle-auto-hangup
+  offline \e$B>uBV$K$7$^$9!#\e(B
+
+\e$B!&\e(BM-x gnus-offline-toggle-on/off-send-mail
+  Online \e$B>uBV\e(B/Offline \e$B>uBV$G$N\e(B Mail \e$BAw?.>uBV$r@ZBX$($^$9!#\e(B
+  Online \e$B>uBV$G$OD>@\Aw?.$7$^$9$,!"\e(BOffline \e$B>uBV$G$O0lC6\e(B spool \e$B$K=q$-9~\e(B
+  \e$B$_!"\e(B"g" \e$B$r2!$7$?;~$KA4ItAw?.$5$l$^$9!#\e(B
+
+\e$B!&\e(BM-x gnus-offline-toggle-articles-to-fetch
+  \e$B<hF@$9$k5-;v$rA*Br$7$^$9!#\e(Bboth -> mail -> news -> both ... \e$B$N$h$&$K\e(B
+  \e$B@Z$jBX$o$j$^$9!#\e(B
+
+\e$B!&\e(BM-x gnus-offline-set-interval-time
+  \e$B5-;v\e(B/Mail \e$B$N<hF@!"Aw?.$r<+F0E*$K9T$&4V3V\e(B(\e$BJ,\e(B)\e$B$r@_Dj$7$^$9!#\e(B
+  \e$B$3$N4V3V$O\e(B Emacs \e$B$,\e(B Idle \e$B$K$J$C$F$+$i$N;~4V$G$9!#\e(B
+
+\e$B!&\e(BM-x gnus-offline-agent-expire
+  \e$B4{FI$N5-;v$r\e(B expire \e$B$7$^$9!#\e(B
+
+
+6)\e$B!Z\e(B!!!\e$B=EMW\e(B!!!\e$B![\e(B pop \e$B%Q%9%o!<%I$N4IM}J}K!$K$D$$$F\e(B
+
+\e$B!V$I$&$;<+J,0l?M$7$+;H$o$J$$%3%s%T%e!<%?$@$+$i$=$l$[$I%Q%9%o!<%I$N4IM}\e(B
+\e$B$K$OCm0U$rJ'$&I,MW$,$J$$!W$H$$$&>l9g$K$OF~NO$N<j4V$r>J$/J}K!$,$"$j$^$9!#\e(B
+\e$B$?$@$7!"EvA3%Q%9%o!<%I$rEp$^$l$k4m81$OA}$7$^$9$N$G<B9T$9$k:]$K$O\e(B 100%
+\e$B<+8J$N@UG$$N$b$H$G9T$C$F$/$@$5$$!#\e(B
+
+\e$B=i2s5/F0;~$N\e(B gnus-ofsetup.el \e$B$K$h$kJQ?t@_Dj$N:]!"\e(B(=~/.gnus-offline.el
+\e$B$,$J$$$H$-\e(B)\e$B%Q%9%o!<%I$r\e(B ~/.newsrc.eld \e$B$KJ]B8$9$k$+$I$&$+<ALd$5$l!"!H\e(By\e$B!I\e(B
+\e$B$HEz$($k$HJ]B8$5$l$k$h$&$K$J$j$^$9!#\e(B (*)
+
+      (*) \e$B<B:]$K$O\e(B ~/.gnus-offline.el \e$B$K0J2<$N%3!<%I$,DI2C$5$l$^$9!#\e(B
+
+           (add-hook
+            'gnus-setup-news-hook
+            (lambda ()
+              (add-to-list 'gnus-variable-list 'mail-source-password-cache)))
+
+\e$B$?$@$7$3$N>l9g$OJ]B8$5$l$k%Q%9%o!<%I$OJ?J8$N$^$^$J$N$G$+$J$j4m81$G$"$k\e(B
+\e$B$3$H$r$4>5CN$N$&$($*;H$$$/$@$5$$!#\e(B
diff --git a/README.T-gnus b/README.T-gnus
new file mode 100644 (file)
index 0000000..e7782dc
--- /dev/null
@@ -0,0 +1,37 @@
+========================================================================
+Codename:      T-gnus
+Branch Tag:    t-gnus-6_16
+Branch Status: Develop, Synchronize with Gnus
+Branch Goal:   Implement latest features of gnus and offline features
+               Use Gnus in Offline status.
+Branch Policy: (not defined yet)
+========================================================================
+NEWS:
+
+* New codename: "T-gnus"
+
+  In order to distinguish this branch from the other branches, codename
+  was changed to "T-gnus" , gnu with T-Shirt.
+
+* New Features
+
+  Use T-gnus in offline(Unplugged) status using gnus-offline.
+  T-gnus have also features that have the branches `shuhei-k', `chao-6_9'
+  `keiichi', ... and the MainTrunk.
+
+  If you would like to make T-gnus with Mule 2.3 based on Emacs 19.34,
+  see Mule23@1934 file for more information.
+
+  You can use some convenient configure options, e.g. `--with-addpath=',
+  to build T-gnus easier.  Try `./configure --help'.
+
+  And added many other features by "ELIPS"
+
+* TODO
+
+  See TODO.ja
+
+* T-gnus 6.16 - this is based on Gnus.
+
+  The latest T-gnus is T-gnus 6.16.6 (based on Gnus 5.10.6).  It
+  requires SEMI 1.14, FLIM 1.14, and APEL 10.0 or later.
diff --git a/README.branch b/README.branch
new file mode 100644 (file)
index 0000000..d8f40eb
--- /dev/null
@@ -0,0 +1,178 @@
+README.branch --- description of branches and tags. (DRAFT)
+========================================================================
+
+Semi-gnus revision tree (2003-05-02)
+
+    vendor      personal    main trunk      public
+    branch      branches                    branches
+------------------------------------------------------------------------
+qGnus 0.??  ------> Semi-gnus 6.0.0
+       :                        :
+       :        himi     <--  6.0.7
+       :    ichikawa <------  6.0.8
+       :       |                |
+       :     6.8.17 ---+        :
+       :       :       :        :
+       :               V        :
+       :         pgnus-ichikawa :
+       :               |        :
+       :             6.9.01     :
+       :               :        : (1999.07.02: turn into the public branch)
+       :               +-------->---------------+
+       :                        :               :
+       :                        :               V
+       :                        :            6.10.072 -----> t-gnus-6_12
+       :                        :               :     \      (for FLIM 1.12,
+       :                        :               :      \      stable)
+       :                        :               :       \
+       :                        :               :        --> t-gnus-6_13
+       :                        :               :            (for FLIM 1.13,
+       :                        :               :             develop)
+       :                        :               :               :
+       :                        :         t-gnus-6_10-last-  t-gnus-6_13-last-
+       :                        :               | feedback      |
+       :                        :               +<--------------+
+       :                        :               |               |
+       :            ------------<---------------+            t-gnus-6_14
+       : Oort Gnus /            :               |            (for FLIM 1.13,
+       :     |    |             :               :             develop)
+       :     V    V             :               :               |
+       :  t-gnus-6_15-quimby<---<-----(t-gnus-6_14-quimby)<-----+
+       :          |             :               :               |
+       :          |             :               | feedback      |
+       :          |             : (Gnus 5.8.8)->+<--------------+
+       :          |             :               |               |
+       :          |             :               |            t-gnus-6_15
+       :          +------------->--------------->----------> (for FLIM 1.14,
+       :                        :               |             develop)
+       :                        :               | feedback      |
+       :                        :  (Gnus 5.10)->+<--------------+
+       :                        :              /|\
+       :          +------------->-------------- | ------------- +
+       :          |             :               :               |
+       :  t-gnus-6_16-quimby    :               :               V
+       :          |             :               :            t-gnus-6_16
+       :          +------------->--------------->----------> (for FLIM 1.14,
+       :                        :               :             develop)
+       :        akr      <--  6.2.3             :               |
+       :        shuhei-k <--  6.3.1                             :
+Gnus 5.6.11 ------>           6.3.3
+       :                      6.4.0 (for SEMI 1.5)
+       :                      (6.4.?)------> for SEMI 1.5
+       :                        |    \
+       :                        |     \
+(Synch with original Gnus       |      ---> for SEMI 1.6
+ was done many times, but    (6.4.?)------> 6.5 (for SEMI 1.7)
+ we don't include them.)        |        /    6.5.0
+       :                        |    (?)/
+       :                        |   <---
+       :                     (6.5.?)------> 6.6 (for SEMI 1.8, FLIM 1.7)
+       :                        |    \        6.6.0        stable branch
+       :                        |     \
+       :                        |      ---> 6.7 (for SEMI 1.8, FLIM 1.7)
+       :                        |             6.7.0        stable branch
+       :     sync               |               :
+Gnus 5.6.22 ------>             |   feedback  6.7.7
+       :                     (6.7.8)<------   6.7.8
+       :                        |    \
+       :                        |     \
+       :                        |      ---> 6.8 (for SEMI 1.8, FLIM 1.8)
+       :        keiichi  <--  6.8.18          6.8.0        stable branch
+       :     sync               |               :
+Gnus 5.6.45 ------>             |   feedback  6.8.20
+       :                     (6.8.20)<------  6.8.20
+       :                        |     \
+       :                        |      \
+       :                        |       --> 6.9 (for SEMI 1.11, FLIM 1.12)
+       :                        |             6.9.1        stable branch
+       :                        |   feedback  6.9.2
+       :                     (6.9.2)<---------6.9.2
+       :                        |    \
+       :                        |     \
+       :                        |       --> 6.10 (for SEMI 1.12, FLIM 1.12)
+       :                        |             6.10.1      develop branch
+       :                        :               :
+       :                        :               :
+========================================================================
+
+The Vendor Branch
+
+    Original version of Gnus.
+    Each version has a tag of the form "qgnus-0_XY" or "gnus-5_X_Y" or
+    "pgnus-0_XY".
+
+    The branch tag for the vendor branch is "larsi".
+
+The Main Trunk
+
+    Semi-gnus was developed on the main trunk until current branch-
+    management plan (See "Public Branches" below) was introduced.
+    Each version has a tag of the form "gnus-6_N2_N3". (0 < N2 < 5)
+
+Public Branches
+
+    Current main stream of Semi-gnus development.
+
+    [Goal and policy of public branches here ???]
+
+    Each branch has a tag of the form "gnus-N1_N2" and each version
+    has a tag of the form "gnus-N1_N2_N3".
+
+    N1, N2, and N3 are changed by the following rules.
+
+    N1 will be incremented if any fundamental architecture change is
+    made.  Of cource, in this case, N2 and N3 will be reset to zero.
+
+    N2 will be incremented and new branch will be made if any "major
+    changes" are made.  "major changes" include API changes, major
+    version up of original Gnus, or synchronization with original Gnus
+    which requires design decision.
+
+    N3 will be incremented if some "minor changes" are made.  "minor
+    changes" include small bug fix or synchronization with original Gnus
+    without design decision.
+
+    The following branch tags are currently available.
+
+       for-semi-1_5    Semi-gnus for SEMI 1.5 API
+       for-semi-1_6    Semi-gnus for SEMI 1.6 API
+       gnus-6_5        Semi-gnus for SEMI 1.7 API
+       gnus-6_6        Semi-gnus for SEMI 1.8, FLIM 1.7 API (stable)
+       gnus-6_7        Semi-gnus for SEMI 1.8, FLIM 1.7 API (stable)
+       gnus-6_8        Semi-gnus for SEMI 1.8, FLIM 1.8 API (stable)
+       gnus-6_9        Semi-gnus for SEMI 1.11, FLIM 1.12 API (stable)
+       gnus-6_10       Semi-gnus for SEMI 1.12, FLIM 1.12 API (develop)
+       pgnus-ichikawa  (Main trunk of T-gnus)
+       t-gnus-6_12     T-gnus for SEMI 1.12/1.13, FLIM 1.12 API (stable)
+       t-gnus-6_13     T-gnus for SEMI 1.13, FLIM 1.13 API (develop)
+       t-gnus-6_14     T-gnus for SEMI 1.13, FLIM 1.13 API (develop)
+       t-gnus-6_15     T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+       t-gnus-6_16     T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+     t-gnus-6_16-quimby        T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+
+    Note: T-gnus versions 6.15 based on Oort Gnus v0.03 and earlier
+          had supported SEMI 1.13 and FLIM 1.13 as well.
+
+Personal Branches
+
+    Some Semi-gnus developers have their own "personal branches".
+    Each personal branch may have its own goal and/or policy.
+    See README.${tag} (if exists) for information of each branch.
+
+    The following branch tags are curretly available.
+
+       himi            Owner: Miyashita Hisashi
+       ichikawa        Owner: Tatsuya Ichikawa
+       akr             Owner: Tanaka Akira
+       shuhei-k        Owner: Shuhei KOBAYASHI
+       keiichi         Owner: Keiichi Suzuki
+
+"semi-gnus" Tag
+
+    Was assigned to the latest stable version.
+    Currently not maintained. (XXX: ???)
+
+"for-semi-N1_N2" Tags
+
+    Were assigned to corresponding version of SEMI API N1.N2.
+    We will not use this convention any longer. (XXX: ???)
diff --git a/README.branch.ja b/README.branch.ja
new file mode 100644 (file)
index 0000000..5f91504
--- /dev/null
@@ -0,0 +1,179 @@
+README.branch.ja --- branch \e$B$H\e(B tag \e$B$N@bL@\e(B (\e$BAp9F\e(B)
+========================================================================
+
+Semi-gnus revision tree (2003-05-02)
+
+    vendor      personal    main trunk      public
+    branch      branches                    branches
+------------------------------------------------------------------------
+qGnus 0.??  ------> Semi-gnus 6.0.0
+       :                        :
+       :        himi     <--  6.0.7
+       :    ichikawa <------  6.0.8
+       :       |                |
+       :     6.8.17 ---+        :
+       :       :       :        :
+       :               V        :
+       :         pgnus-ichikawa :
+       :               |        :
+       :             6.9.01     :
+       :               :        :              (1999.07.02: \e$B8xE*;^$K0a99$(\e(B)
+       :               +-------->---------------+
+       :                        :               :
+       :                        :               V
+       :                        :            6.10.072 -----> t-gnus-6_12
+       :                        :               :     \      (for FLIM 1.12,
+       :                        :               :      \      stable)
+       :                        :               :       \
+       :                        :               :        --> t-gnus-6_13
+       :                        :               :            (for FLIM 1.13,
+       :                        :               :             develop)
+       :                        :               :               :
+       :                        :         t-gnus-6_10-last-  t-gnus-6_13-last-
+       :                        :               | feedback      |
+       :                        :               +<--------------+
+       :                        :               |               |
+       :            ------------<---------------+            t-gnus-6_14
+       : Oort Gnus /            :               |            (for FLIM 1.13,
+       :     |    |             :               :             develop)
+       :     V    V             :               :               |
+       :  t-gnus-6_15-quimby<---<-----(t-gnus-6_14-quimby)<-----+
+       :          |             :               :               |
+       :          :             :               | feedback      |
+       :          |             : (Gnus 5.8.8)->+<--------------+
+       :          |             :               |               |
+       :          |             :               |            t-gnus-6_15
+       :          +------------->--------------->----------> (for FLIM 1.14,
+       :                        :               |             develop)
+       :                        :               | feedback      |
+       :                        :  (Gnus 5.10)->+<--------------+
+       :                        :              /|\
+       :          +------------->-------------- | ------------- +
+       :          |             :               :               |
+       :  t-gnus-6_16-quimby    :               :               V
+       :          |             :               :            t-gnus-6_16
+       :          +------------->--------------->----------> (for FLIM 1.14,
+       :                        :               :             develop)
+       :        akr      <--  6.2.3             :               |
+       :        shuhei-k <--  6.3.1                             :
+Gnus 5.6.11 ------>           6.3.3
+       :                      6.4.0 (for SEMI 1.5)
+       :                      (6.4.?)------> for SEMI 1.5
+       :                        |    \
+       :                        |     \
+(\e$B85$N\e(B Gnus \e$B$H$N\e(B Sync \e$B$O2?EY\e(B     |      ---> for SEMI 1.6
\e$B$b$J$5$l$F$$$^$9$,!"$3$3$K\e(B  (6.4.?)------> 6.5 (for SEMI 1.7)
\e$B$O=q$-$^$;$s!#\e(B)                |        /    6.5.0
+       :                        |    (?)/
+       :                        |   <---
+       :                     (6.5.?)------> 6.6 (for SEMI 1.8, FLIM 1.7)
+       :                        |    \        6.6.0        stable branch
+       :                        |     \
+       :                        |      ---> 6.7 (for SEMI 1.8, FLIM 1.7)
+       :                        |             6.7.0        stable branch
+       :     sync               |               :
+Gnus 5.6.22 ------>             |   feedback  6.7.7
+       :                     (6.7.8)<------   6.7.8
+       :                        |    \
+       :                        |     \
+       :                        |      ---> 6.8 (for SEMI 1.8, FLIM 1.8)
+       :        keiichi  <--  6.8.18          6.8.0        stable branch
+       :     sync               |               :
+Gnus 5.6.45 ------>             |   feedback  6.8.20
+       :                     (6.8.20)<------  6.8.20
+       :                        |     \
+       :                        |      \
+       :                        |       --> 6.9 (for SEMI 1.11, FLIM 1.12)
+       :                        |             6.9.1        stable branch
+       :                        |   feedback  6.9.2
+       :                     (6.9.2)<---------6.9.2
+       :                        |    \
+       :                        |     \
+       :                        |       --> 6.10 (for SEMI 1.12, FLIM 1.12)
+       :                        |             6.10.1      develop branch
+       :                        :               :
+       :                        :               :
+========================================================================
+
+The Vendor Branch
+
+    Gnus \e$B$N85$N%P!<%8%g%s$G$9!#\e(B
+    \e$B$=$l$>$l$N%P!<%8%g%s$O\e(B "qgnus-0_XY" \e$B$d\e(B "gnus-5_X_Y" \e$B$d\e(B
+    "pgnus-0_XY" \e$B$H$$$&7A<0$N\e(B tag \e$B$,IU$$$F$$$^$9!#\e(B
+
+    vendor branch \e$B$N\e(B branch tag \e$B$O\e(B "larsi" \e$B$G$9!#\e(B
+
+The Main Trunk
+
+    \e$B8=:_$N\e(B branch \e$B4IM}7W2h$,F3F~$5$l$k$^$G!"\e(BSemi-gnus \e$B$O\e(B main trunk \e$B$G\e(B
+    \e$B3+H/$5$l$F$$$^$7$?\e(B (\e$B2<$N\e(B "Public Branches" \e$B$rFI$s$G$/$@$5$$\e(B)\e$B!#$=$l\e(B
+    \e$B$>$l$N%P!<%8%g%s$O\e(B "gnus-6_N2_N3" \e$B$H$$$&7A<0$G$9!#\e(B(0 < N2 < 5)
+
+Public Branches
+
+    \e$B8=:_$N\e(B Semi-gnus \e$B3+H/$N<gN.$G$9!#\e(B
+
+    [public branch \e$B$NL\I8$H<g5A$r=q$/\e(B ???]
+
+    \e$B$=$l$>$l$N\e(B branch \e$B$O\e(B "gnus-N1_N2" \e$B$H$$$&7A<0$N\e(B tag \e$B$,IU$$$F$$$F!"\e(B
+    \e$B$=$l$>$l$N%P!<%8%g%s$O\e(B "gnus-N1_N2_N3" \e$B$H$$$&7A<0$N\e(B tag \e$B$,IU$$$F$$\e(B
+    \e$B$^$9!#\e(B
+
+    N1, N2, N3 \e$B$O0J2<$N5,B'$K=>$C$FJQ99$5$l$^$9!#\e(B
+
+    N1 \e$B$O4pACE*$J;EAH$_$NJQ99$,$J$5$l$?$H$-$KA}$d$5$l$^$9!#$b$A$m$s!"\e(B
+    \e$B$3$N>l9g$O\e(B N2 \e$B$H\e(B N3 \e$B$O\e(B 0 \e$B$K$J$j$^$9!#\e(B
+
+    N2 \e$B$O?7$7$$\e(B branch \e$B$,\e(B "\e$B<g$JJQ99\e(B" \e$B$r9T$C$?$H$-$KA}$d$5$l$^$9!#\e(B "\e$B<g\e(B
+    \e$B$JJQ99\e(B" \e$B$H$O!"\e(BAPI \e$B$NJQ99!"85$N\e(B Gnus \e$B$NBg$-$J99?7!"@_7W$N7hDj$rH<$&\e(B
+    \e$B$h$&$J85$N\e(B Gnus \e$B$H$NF14|$J$I$G$9!#\e(B
+
+    N3 \e$B$O\e(B "\e$B>.$5$JJQ99\e(B" \e$B$,$J$5$l$?$H$-$KA}$d$5$l$^$9!#\e(B"\e$B>.$5$JJQ99\e(B" \e$B$O>.\e(B
+    \e$B$5$J%P%0=$@5$d!"@_7W$N7hDj$rH<$o$J$$85$N\e(B Gnus \e$B$H$NF14|$J$I$G$9!#\e(B
+
+    \e$B8=:_$O0J2<$N\e(B branch tag \e$B$,;HMQ2DG=$G$9!#\e(B
+    The following branch tags are currently available.
+
+       for-semi-1_5    Semi-gnus for SEMI 1.5 API
+       for-semi-1_6    Semi-gnus for SEMI 1.6 API
+       gnus-6_5        Semi-gnus for SEMI 1.7 API
+       gnus-6_6        Semi-gnus for SEMI 1.8, FLIM 1.7 API (stable)
+       gnus-6_7        Semi-gnus for SEMI 1.8, FLIM 1.7 API (stable)
+       gnus-6_8        Semi-gnus for SEMI 1.8, FLIM 1.8 API (stable)
+       gnus-6_9        Semi-gnus for SEMI 1.11, FLIM 1.12 API (stable)
+       gnus-6_10       Semi-gnus for SEMI 1.12, FLIM 1.12 API (develop)
+       pgnus-ichikawa  (Main trunk of T-gnus)
+       t-gnus-6_12     T-gnus for SEMI 1.12/1.13, FLIM 1.12 API (stable)
+       t-gnus-6_13     T-gnus for SEMI 1.13, FLIM 1.13 API (develop)
+       t-gnus-6_14     T-gnus for SEMI 1.13, FLIM 1.13 API (develop)
+       t-gnus-6_15     T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+       t-gnus-6_16     T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+     t-gnus-6_16-quimby        T-gnus for SEMI 1.14, FLIM 1.14 API (develop)
+
+    \e$BCm\e(B: v0.03 \e$B0JA0$N\e(B Oort Gnus \e$B$r85$K$7$?\e(B T-gnus 6.15 \e$B$O!"\e(BSEMI 1.13 \e$B$H\e(B
+        FLIM 1.13 \e$B$b%5%]!<%H$7$F$$$^$7$?!#\e(B
+
+Personal Branches
+
+    Semi-gnus \e$B3+H/<T$NCf$K$O<+J,$N\e(B "personal branch" \e$B$r;}$C$F$$$k?M$b\e(B
+    \e$B$$$^$9!#$=$l$>$l$N\e(B personal branch \e$B$OL\I8!"<g5A$r;}$C$F$$$k$G$7$g\e(B
+    \e$B$&!#$=$l$>$l$N\e(B branch \e$B$N>pJs$O\e(B (\e$BB8:_$9$k$J$i$P!"\e(B) README.${tag} \e$B$r\e(B
+    \e$BFI$s$G$/$@$5$$!#\e(B
+
+    \e$B0J2<$N\e(B branch tag \e$B$,8=:_;HMQ2DG=$G$9!#\e(B
+
+       himi            Owner: Miyashita Hisashi
+       ichikawa        Owner: Tatsuya Ichikawa
+       akr             Owner: Tanaka Akira
+       shuhei-k        Owner: Shuhei KOBAYASHI
+       keiichi         Owner: Keiichi Suzuki
+
+"semi-gnus" Tag
+
+    \e$B$3$l$O:G?7$N0BDjHG$K3d$jEv$F$i$l$F$$$^$7$?!#8=:_$O0];}$5$l$F$$$^$;\e(B
+    \e$B$s!#\e(B(XXX: ???)
+
+"for-semi-N1_N2" Tags
+
+    \e$B$3$l$O\e(B SEMI API N1.N2 \e$B$KBP1~$9$k%P!<%8%g%s$K3d$jEv$F$i$l$F$$$^$7$?!#\e(B
+    \e$B$3$N=,47$O$b$&;H$o$l$^$;$s!#\e(B(XXX: ???)
diff --git a/README.semi b/README.semi
new file mode 100644 (file)
index 0000000..5b41eb8
--- /dev/null
@@ -0,0 +1,133 @@
+This package contains T-gnus 6.16.
+
+What is T-gnus?
+===============
+
+  T-gnus is an improvement of Gnus with SEMI's MIME feature. T-gnus
+6.16 is based on Gnus v5.10.  SEMI may stand for "SEMI is Emacs MIME
+Interface" and is developped to provide an easy interfaces for users
+to handle MIME message structures. For further information, refer to
+README.en of SEMI.
+
+  It requires APEL, FLIM and SEMI packages, so please get and install
+them before to install it.  T-gnus 6.16 requires APEL 10.0 or later,
+FLIM 1.14 and SEMI 1.14.  You can get these packages from:
+
+ftp://ftp.m17n.org/pub/mule/apel/
+ftp://ftp.m17n.org/pub/mule/flim/flim-1.14/
+ftp://ftp.m17n.org/pub/mule/semi/semi-1.14-for-flim-1.14/
+
+Required environment for SEMI is written in README.en of SEMI package.
+
+  In addition, if you wish to use the web based backend `nnshimbun',
+you have to install the package emacs-w3m and the external command w3m.
+Visit the following pages for more information.
+
+http://emacs-w3m.namazu.org/
+http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/
+
+
+How to get? (via CVS)
+=====================
+
+(0) cvs login (first time only)
+
+    % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root login
+
+    CVS password: [CR] # NULL string
+
+(1) checkout
+
+    % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root \
+       checkout -r t-gnus-6_16 gnus
+
+(2) compile
+
+    % cd gnus
+    % configure [options]
+    % make [options]
+
+(3) update
+
+    % cvs update -r t-gnus-6_16 gnus
+
+Major tags are following:
+
+    t-gnus-6_16-quimby Assigned to the latest version of T-gnus for
+                       developing and synchronizing with Gnus.
+
+    t-gnus-6_16                Assigned to the latest version of T-gnus for
+                       developing and synchronizing with the released
+                       version of Gnus.
+
+    pgnus-ichikawa     The main trunk of T-gnus.
+
+    semi-gnus          Assigned to the latest stable version.  It is
+                       very conservative. Currently it is not used.
+
+    for-semi-N1_N2     assigned to the latest stable version for SEMI
+                       API N1.N2 (N1 and N2 are natural number).
+                       (e.g. `for-semi-1_3' is for SEMI API 1.3)
+
+    gnus-N1_N2_N3      assigned to gnus(Gnus) N1.N2.N3
+                       (e.g. `gnus-6_2_1' means gnus 6.2.1).
+
+    larsi              Original Gnus
+
+    himi               himi branch
+
+    akr                        akr branch
+
+    shuhei-k           shuhei-k branch
+                       Mail-Followup-To/Mail-Reply-To, gnus-cache fix.
+
+    keiichi            keiichi branch
+    nana-gnus-N1_N2    Stable version of `keiichi branch'.
+
+For more detailed information, please read README.branch.
+
+
+How to get? (via ftp)
+=====================
+
+  T-gnus 6.16 is available from
+
+    ftp://ftp.jpl.org/pub/elisp/t-gnus-6.16/snapshots/
+
+  NOTE: These snapshots are manually created when the urge takes the
+  administrator of the a-ftp site, and will usually not be tested.
+
+
+How to join development
+=======================
+
+  If you have found a bug in Gnus proper, please do `M-x gnus-bug' and
+send a bug report to the Gnus maintainers.
+
+  If you have found a bug in T-gnus, or if you're not sure whether it
+is a Gnus proper, please send a bug report to the Semi-gnus mailing
+list:
+
+    semi-gnus-en@meadowy.org   (English)
+    semi-gnus-ja@meadowy.org   (Japanese)
+
+Suggestions for T-gnus improvements are also welcome.
+
+  Via the Semi-gnus ML, you can report T-gnus related bugs, obtain the
+latest release of T-gnus, and discuss future enhancements to T-gnus.
+To join the Semi-gnus ML, send an empty e-mail to
+
+    semi-gnus-en-help@meadowy.org      (English)
+    semi-gnus-ja-help@meadowy.org      (Japanese)
+
+  In addition, we need developers.  If you would like to develop it,
+please send mail to cvs@cvs.m17n.org with your account name and your
+public key for ssh.  cvsroot is :ext:cvs@cvs.m17n.org:/cvs/root.
+If you cannot use ssh, please send UNIX /etc/passwd style crypted
+password instead.  cvsroot is
+:pserver:<accountname>@cvs.m17n.org:/cvs/root in this case.  You can
+get the notice of modifications in m17n open CVS server via the mail
+which also contains informations on the other modules.  To subscribe
+it, send an empty e-mail to
+
+    cvs-info-help@cvs.m17n.org
diff --git a/README.semi.ja b/README.semi.ja
new file mode 100644 (file)
index 0000000..57dda96
--- /dev/null
@@ -0,0 +1,136 @@
+\e$B$3$N%Q%C%1!<%8$K$O\e(B T-gnus 6.16 \e$B$,F~$C$F$$$^$9!#\e(B
+
+T-gnus \e$B$H$O!)\e(B
+=============
+
+  T-gnus \e$B$O!"\e(BSEMI \e$B$rMxMQ$7$F\e(B Gnus \e$B$K\e(B MIME \e$B5!G=$rDI2C$9$k$b$N$G$9!#\e(B
+T-gnus 6.16 \e$B$O\e(B Gnus v5.10 \e$B$r%Y!<%9$K$7$F$$$^$9!#\e(BSEMI \e$B$O\e(B Emacs \e$B$G\e(B MIME
+\e$B$r;H$($k$h$&$K$9$k$b$N$G!"\e(BMIME message \e$B$N9=J8$N9=B$$HMxMQ<T$N4V$r$D$J\e(B
+\e$B$0%$%s%?!<%U%'!<%9$rDs6!$7$^$9!#>\$7$/$O!"\e(BSEMI \e$B$N\e(B README.en \e$B$r;2>H$7$F\e(B
+\e$B$/$@$5$$!#\e(B
+
+  T-gnus \e$B$rMxMQ$9$k$K$O\e(B APEL, FLIM \e$B$*$h$S\e(B SEMI \e$B%Q%C%1!<%8$,I,MW$G$9$N\e(B
+\e$B$G!"%$%s%9%H!<%k$9$kA0$K$=$l$i$r%$%s%9%H!<%k$7$F$/$@$5$$!#\e(BT-gnus 6.16 
+\e$B$O\e(B APEL 10.0 \e$B0J>e!"\e(BFLIM 1.14 \e$B$*$h$S\e(B SEMI 1.14 \e$B$rI,MW$H$7$^$9!#$=$l$i$N\e(B
+\e$B%Q%C%1!<%8$O\e(B
+
+ftp://ftp.m17n.org/pub/mule/apel/
+ftp://ftp.m17n.org/pub/mule/flim/flim-1.14/
+ftp://ftp.m17n.org/pub/mule/semi/semi-1.14-for-flim-1.14/
+
+\e$B$+$i<hF@$9$k$3$H$,$G$-$^$9!#I,MW$J4D6-$O\e(B SEMI \e$B$N\e(B README.en \e$B$r;2>H$7$F\e(B
+\e$B$/$@$5$$!#\e(B
+
+  \e$B2C$($F!"\e(B`nnshimbun' \e$B$r;H$$$?$$>l9g$K$O!"\e(Bemacs-w3m \e$B%Q%C%1!<%8$H30It\e(B
+\e$B%3%^%s%I$N\e(B w3m \e$B$,I,MW$G$9!#>\$7$$$3$H$O0J2<$N%Z!<%8$r$4Mw2<$5$$!#\e(B
+
+http://emacs-w3m.namazu.org/
+http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/
+
+
+\e$B<hF@J}K!\e(B (CVS)
+==============
+
+(0) cvs login (\e$B=i2s$N$_\e(B)
+
+    % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root login
+
+    CVS password: [CR] # \e$B6uJ8;zNs\e(B
+
+(1) checkout
+
+    % cvs -d :pserver:anonymous@cvs.m17n.org:/cvs/root \
+       checkout -r t-gnus-6_16 gnus
+
+(2) compile
+
+    % cd gnus
+    % configure [options]
+    % make [options]
+
+(3) update
+
+    % cvs update -r t-gnus-6_16 gnus
+
+\e$B<g$J%?%0$O0J2<$N$h$&$K$J$C$F$$$^$9\e(B:
+
+    t-gnus-6_16-quimby \e$B:G?7$N\e(B T-gnus \e$B$K3d$jEv$F$i$l!"3+H/$H\e(B Gnus \e$B$H$N\e(B
+                       \e$BF14|$r9T$J$$$^$9!#\e(B
+
+    t-gnus-6_16                \e$B:G?7$N\e(B T-gnus \e$B$K3d$jEv$F$i$l!"3+H/$H%j%j!<%9$5\e(B
+                       \e$B$l$?\e(B Gnus \e$B$H$NF14|$r9T$J$$$^$9!#\e(B
+
+    pgnus-ichikawa     T-gnus \e$B$N44$G$9!#\e(B
+
+    semi-gnus          \e$B:G?7$N0BDjHG$K3d$jEv$F$i$l$^$9!#Hs>o$KJ]<iE*$G\e(B
+                       \e$B$9!#8=:_$O;HMQ$5$l$F$$$^$;$s!#\e(B
+
+    for-semi-N1_N2     SEMI API N1.N2 (N1 \e$B$H\e(B N2 \e$B$O<+A3?t\e(B) \e$B$KBP1~$7$F\e(B
+                       \e$B:G?7$N0BDjHG$K3d$jEv$F$i$l$^$9!#\e(B(\e$BNc\e(B
+                       `for-semi-1_3' \e$B$O\e(B SEMI API 1.3 \e$BMQ$G$9!#\e(B)
+                       (\e$B8=:_$O;HMQ$5$l$F$$$^$;$s!#\e(B)
+
+    gnus-N1_N2_N3      gnus(Gnus) N1.N2.N3 \e$B$K3d$jEv$F$i$l$^$9!#\e(B
+                       (\e$BNc\e(B `gnus-6_2_1' \e$B$O\e(B gnus 6.2.1 \e$B$G$9!#\e(B)
+
+    larsi              \e$B85$N\e(B Gnus
+
+    himi               himi branch
+
+    akr                        akr branch
+
+    shuhei-k           shuhei-k branch
+                       Mail-Followup-To/Mail-Reply-To, gnus-cache fix.
+
+    keiichi            keiichi branch
+    nana-gnus-N1_N2    Stable version of `keiichi branch'.
+
+\e$B>\$7$/$O!"\e(BREADME.branch.ja \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+
+\e$B<hF@J}K!\e(B (ftp)
+==============
+
+  T-gnus 6.16 \e$B$O0J2<$N>l=j$+$i<hF@2DG=$G$9!#\e(B
+
+    ftp://ftp.jpl.org/pub/elisp/t-gnus-6.16/snapshots/
+
+  \e$BCm0U\e(B: \e$B$3$l$i$N\e(B snapshot \e$B$O\e(B a-ftp site \e$B$N4IM}<T$N5$$,8~$$$?$H$-$K<jF0\e(B
+  \e$B$G:n@.$5$l!"IaDL$O%F%9%H$5$l$F$$$^$;$s!#\e(B
+
+
+\e$B3+H/$X$N;22CJ}K!\e(B
+================
+
+  Gnus \e$B$N%P%0$r8+$D$1$?$H$-$O!"\e(B`M-x gnus-bug' \e$B$H$7$F!"\e(BGnus \e$B$N0];}<T$K\e(B
+  \e$B%P%0Js9p$rAw$C$F$/$@$5$$!#\e(B
+
+  T-gnus \e$B$N%P%0$r8+$D$1$?$+!"\e(BGnus \e$B$N%P%0$G$"$k$+$I$&$+$,J,$+$i$J$$$H$-\e(B
+  \e$B$O!"%P%0Js9p$r\e(B Semi-gnus \e$B%a!<%j%s%0%j%9%H$KAw$C$F$/$@$5$$\e(B:
+
+    semi-gnus-en@meadowy.org   (\e$B1Q8l\e(B)
+    semi-gnus-ja@meadowy.org   (\e$BF|K\8l\e(B)
+
+  T-gnus \e$B$N2~A1$N$?$a$NDs0F$b4?7^$5$l$^$9!#\e(B
+
+  Semi-gnus ML \e$B$G$O!"\e(BT-gnus \e$B4XO"$N%P%0$rJs9p$7$?$j!":G?7$N\e(B T-gnus \e$B$N%j\e(B
+  \e$B%j!<%9$r<hF@$7$?$j!"\e(BT-gnus \e$B$N>-Mh$N3HD%$r5DO@$7$?$j$9$k$3$H$,$G$-$^\e(B
+  \e$B$9!#\e(BSemi-gnus ML \e$B$K;22C$9$k$?$a$K$O\e(B
+
+    semi-gnus-en-help@meadowy.org      (\e$B1Q8l\e(B)
+    semi-gnus-ja-help@meadowy.org      (\e$BF|K\8l\e(B)
+
+  \e$B$K6u$N%a!<%k$rAw$C$F$/$@$5$$!#\e(B
+
+  \e$B2C$($F!"3+H/<T$rI,MW$H$7$F$$$^$9!#3+H/$K;22C$7$?$$>l9g$O!"\e(B
+  cvs@cvs.m17n.org \e$B$K%"%+%&%s%HL>$H\e(B ssh \e$B$N8x3+80$rAw$C$F$/$@$5$$!#\e(Bssh
+  \e$B7PM3$G$N\e(B cvsroot \e$B$O\e(B :ext:cvs@cvs.m17n.org:/cvs/root \e$B$H$J$j$^$9!#$I$&\e(B
+  \e$B$7$F$b\e(B ssh \e$B$,;H$($J$$>l9g!"\e(BUNIX \e$B$N\e(B /etc/passwd \e$B$NMM<0$G0E9f2=$5$l$?\e(B
+  \e$B%Q%9%o!<%I$r%a!<%k$rAw$C$F$/$@$5$$!#$3$N>l9g\e(B cvsroot \e$B$O\e(B
+  :pserver:<\e$B%"%+%&%s%HL>\e(B>@cvs.m17n.org:/cvs/root \e$B$H$J$j$^$9!#\e(Bm17n open
+  CVS server \e$B$G9T$J$o$l$?JQ99$r%a!<%k$GDLCN$7$F$b$i$&$3$H$b2DG=$G$9!#\e(B
+  \e$B$3$l$K$O\e(B gnus \e$B0J30$N\e(B module \e$B$K4X$9$k>pJs$b4^$^$l$^$9!#I,MW$JJ}$O\e(B
+
+    cvs-info-help@cvs.m17n.org
+
+  \e$B$K6u$N%a!<%k$rAw$C$F0FFb$K=>$C$F2<$5$$!#\e(B
diff --git a/TODO.ja b/TODO.ja
new file mode 100644 (file)
index 0000000..0223ce8
--- /dev/null
+++ b/TODO.ja
@@ -0,0 +1,110 @@
+-*- mode: text; left-margin: 4; fill-column: 70; -*-
+
+To do list.
+
+;; \e$BBP:v:Q$N$b$N$O!"E,Ev$J%?%$%_%s%0\e(B(\e$B%j%j!<%9;~\e(B?)\e$B$G:o=|$7$F$/$@$5$$!#\e(B
+;; \e$B$^$?!"3F\e(B personal branch \e$B$GBP:vCf!"$^$?$OBP:v:Q$N$b$N$K4X$7$F$O$=$N\e(B
+;; \e$B;]$r5-:\$7$F$/$@$5$$!#\e(B
+
+----------- \e$BL$BP:v\e(B -----------
+
+*1998/09/25-1 message/partial \e$B$N7k9g5!G=$N2~NI\e(B
+
+    Subject \e$B$G\e(B summary \e$B$r8!:w$9$kBe$o$j$K!"\e(Bgnus-newsgroup-headers \e$B$J\e(B
+    \e$B$I$N>pJs$r;H$C$F!"3N<B$K<+F07k9g$G$-$k$h$&$K$9$k!#\e(B
+
+*1998/10/02-2 \e$B@_Dj%U%!%$%k72FI$_9~$_;~$N\e(B coding-system \e$BLdBj\e(B
+
+    \e$B8=9T$N\e(B ctext \e$B$G$O\e(B byte code \e$B$rGK2u$7$F$7$^$&!#\e(B
+
+*1998/10/02-12 \e$B%X%C%@!<!&%U%#!<%k%I$KBP$9$kITMW$J\e(B decode \e$B$rGS=|\e(B
+
+    \e$B4{$K\e(B decode \e$B$5$l$F$$$k%X%C%@!<!&%U%#!<%k%I$r:FEY\e(B decode \e$B$7$F$7$^$&\e(B
+    \e$B8D=j$,$"$k$h$&$J$N$G!"$=$l$rGS=|$9$k!#\e(B
+
+*1998/10/02-13 .gnus.el \e$B$N%F%s%W%l!<%H:n@.\e(B
+
+    .gnus.el \e$B$N%F%s%W%l!<%H!&%U%!%$%k$H!"$=$N2r@b=q$r:n@.$9$k!#\e(B
+
+*1998/10/05-1 \e$BBg@9$j%Q%C%1!<%8:n@.\e(B
+
+    SEMI / FLIM / APEL / Semi-gnus \e$B$N%P!<%8%g%sIT0lCW$K$h$k:.Mp$rHr$1\e(B
+    \e$B$k$?$a$K$3$l$i$r0l$D$N%Q%C%1!<%8$H$7$F!"G[I[$9$k$h$&$K$9$k!#\e(B
+
+----------- \e$BBP:v:Q\e(B -----------
+
+*1998/10/02-3 message/partial \e$B;HMQ;~$N\e(B Message-Id \e$BLdBj\e(B
+
+    \e$B$=$l$>$l$K\e(B Message-Id \e$B$rIU2C$9$k!#\e(B
+
+    1998/09/28 - \e$B40N;\e(B
+
+*1998/10/02-5 Edit article \e$B;~$K%a%C%;!<%8$rGK2u$9$kLdBj\e(B
+
+    1998/10/29 - \e$B40N;\e(B
+
+*1998/10/02-6 smtpmail.el \e$B:o=|\e(B
+
+    1998/??/?? - \e$B40N;\e(B
+
+*1998/10/02-8 User-Agent \e$B%X%C%@!<!&%U%#!<%k%I:NMQ\e(B
+
+    1998/10/05 - \e$B40N;\e(B
+
+*1998/10/02-9 In-Reply-To \e$B%X%C%@!<7A<0JQ99\e(B
+
+    draft-ietf-drums-msg-fmt-05.txt \e$B$K=>$C$?7A<0$KJQ99$9$k!#\e(B
+
+    1998/11/02 - \e$B40N;\e(B
+
+*1998/10/02-10 \e$B$O$8$a$F\e(B gnus-agent \e$B$r;HMQ$7$?$H$-$NLdBj\e(B
+
+    1998/10/16 - \e$B40N;\e(B (cf. semi-gnus-ja: 1482, 1536)
+
+*1998/10/02-11 message.el \e$B$NFHN)$7$?;HMQ;~$NLdBj\e(B
+
+    gnus \e$B$K0MB8$9$k$b$N$r\e(B gnus-msg.el \e$B$K0\F0!#\e(B
+
+    1998/10/03 - \e$B40N;\e(B
+
+*1998/10/03-01 \e$BG$0U%a%C%;!<%8\e(B cite \e$B5!G=$N<BAuJ}K!JQ99\e(B
+
+    keiichi branch \e$B$h$jM"F~!#\e(B
+
+    1998/10/06 - \e$B40N;\e(B
+
+*1998/10/03-2 Info (gnus/gnus-ja) \e$B$NA*Br\e(B
+
+    gnus-6_8 \e$B$h$jM"F~!#\e(B
+
+    1998/10/06 - \e$B40N;\e(B (cf. semi-gnus-ja: 1452)
+
+*1998/10/16-1 Draft \e$B$NJT=8!&Aw?.;~$N\e(B encode / decode \e$BLdBj\e(B
+
+    \e$BJT=8Cf$N%a%C%;!<%8$r\e(B draft \e$BFb$KJ]B8$9$k>l9g!"DL>o$N%F%-%9%H!&%G!<\e(B
+    \e$B%?$H$7$FJ]B8$7$F$$$k$,!"$3$l$r\e(B network \e$B7A<0$GJ]B8$9$k$h$&$KJQ99$7!"\e(B
+    \e$B:FJT=8$O\e(B decode \e$B$7$F$+$i9T$$!"Aw?.$O$=$N$^$^$N7A<0$G9T$&$h$&$K$9$k!#\e(B
+
+    1998/10/17 - \e$B40N;\e(B
+
+*1998/10/16-2 Offline \e$B;~$K:n@.$7$?%a%C%;!<%8$N\e(B Message-Id \e$BLdBj\e(B
+
+    Offline \e$B;~$K%a%C%;!<%8$r:n@.$7$?>l9g!"\e(B Message-Id \e$B$N7A<0$,ITEv$J$b\e(B
+    \e$B$N$K$J$C$F$7$^$&$,!"8=>u$G$O\e(B Message-ID \e$B$rIU$1$J$$;v$GBP:v!#\e(B
+
+    1998/09/28 - \e$B40N;\e(B
+
+*1998/11/05-1 Cancel-Lock
+
+    \e$B%K%e!<%9Aw?.;~\e(B Cancel-Lock \e$B%U%#!<%k%I$rIU2C$9$k!#\e(B
+    Cancel/Replaces/Supersedes \e$B$N$H$-$O\e(B Cancel-Key \e$B%U%#!<%k%I$rIU2C$9$k!#\e(B
+
+    1999/01/12 - \e$B40N;\e(B
+
+*1998/10/02-7 smtp.el \e$B0\F0\e(B
+
+    smtp.el \e$B$O!"B>$N\e(B package \e$B$G$b;HMQ$9$k2DG=@-$,$"$k$N$G!"\e(B FLIM \e$B$K0\\e(B
+    \e$BF0$9$k!#\e(B
+    \e$B$=$NA0$K!"\e(B shuhei-k \e$B;^$N\e(B smtp.el \e$B$H$N;EMM$r6&DL2=$9$kI,MW$,$"$k!#\e(B
+
+    1998/12/02 - \e$B40N;\e(B
index b56880a..047cd6b 100644 (file)
-# serial 1
+AC_DEFUN(AC_DEFINE_GNUS_PRODUCT_NAME,
+ [echo $ECHO_N "defining gnus product name... $ECHO_C"
+  AC_CACHE_VAL(EMACS_cv_GNUS_PRODUCT_NAME,[EMACS_cv_GNUS_PRODUCT_NAME=$1])
+  GNUS_PRODUCT_NAME=${EMACS_cv_GNUS_PRODUCT_NAME}
+  AC_MSG_RESULT(${GNUS_PRODUCT_NAME})
+  AC_SUBST(GNUS_PRODUCT_NAME)])
 
-AC_DEFUN(AM_PATH_LISPDIR,
- [# If set to t, that means we are running in a shell under Emacs.
-  # If you have an Emacs named "t", then use the full path.
+AC_DEFUN(AC_CHECK_EMACS,
+ [dnl Check for Emacsen.
+
+  dnl Apparently, if you run a shell window in Emacs, it sets the EMACS
+  dnl environment variable to 't'.  Lets undo the damage.
   test "$EMACS" = t && EMACS=
-  AC_PATH_PROG(EMACS, emacs xemacs, no)
-  if test $EMACS != "no"; then
-    AC_MSG_CHECKING([where .elc files should go])
+
+  dnl Ignore cache.
+  unset ac_cv_prog_EMACS; unset ac_cv_prog_XEMACS;
+
+  AC_ARG_WITH(emacs,
+   [  --with-emacs=EMACS      compile with EMACS [[EMACS=emacs, mule...]]],
+   [if test "$withval" = yes -o -z "$withval"; then
+      AC_CHECK_PROGS(EMACS, emacs xemacs mule, emacs)
+    else
+      AC_CHECK_PROG(EMACS, $withval, $withval, emacs)
+    fi])
+  AC_ARG_WITH(xemacs,
+   [  --with-xemacs=XEMACS    compile with XEMACS [[XEMACS=xemacs]]],
+   [if test "$withval" = yes -o -z "$withval"; then
+      AC_CHECK_PROG(XEMACS, xemacs, xemacs, xemacs)
+    else
+      AC_CHECK_PROG(XEMACS, $withval, $withval, xemacs)
+    fi
+    EMACS=$XEMACS],
+   [XEMACS=xemacs
+    test -z "$EMACS" && AC_CHECK_PROGS(EMACS, emacs xemacs mule, emacs)])
+  AC_SUBST(EMACS)
+  AC_SUBST(XEMACS)])
+
+AC_DEFUN(AC_EMACS_LISP, [
+elisp="$2"
+if test -z "$3"; then
+       AC_MSG_CHECKING(for $1)
+fi
+AC_CACHE_VAL(EMACS_cv_SYS_$1,[
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& AC_FD_CC 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& AC_FD_CC 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& AC_FD_CC 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_$1=$retval
+])
+$1=${EMACS_cv_SYS_$1}
+if test -z "$3"; then
+       AC_MSG_RESULT($$1)
+fi
+])
+
+AC_DEFUN(AC_CHECK_EMACS_FLAVOR,
+ [AC_MSG_CHECKING([what a flavor does $EMACS have])
+
+  dnl Ignore cache.
+  unset EMACS_cv_SYS_flavor;
+
+  AC_EMACS_LISP(flavor,
+    (cond ((featurep (quote xemacs)) \"XEmacs\")\
+          ((boundp (quote MULE)) \"MULE\")\
+          (t \"FSF Emacs\")),
+    "noecho")
+  case $EMACS_cv_SYS_flavor in
+  XEmacs)
+    EMACS_FLAVOR=xemacs;;
+  MULE)
+    EMACS_FLAVOR=mule;;
+  *)
+    EMACS_FLAVOR=emacs;;
+  esac
+  AC_MSG_RESULT($EMACS_cv_SYS_flavor)])
+
+AC_DEFUN(AC_PATH_LISPDIR, [
+  AC_CHECK_EMACS_FLAVOR
+  if test "$prefix" = NONE; then
+       AC_MSG_CHECKING([prefix for your Emacs])
+       AC_EMACS_LISP(prefix,(expand-file-name \"..\" invocation-directory),"noecho")
+       prefix=${EMACS_cv_SYS_prefix}
+       AC_MSG_RESULT($prefix)
+  fi
+  AC_ARG_WITH(lispdir,
+    [  --with-lispdir=DIR      Where to install lisp files
+                          (for XEmacs package, use --with-packagedir instead)],
+    lispdir=${withval})
+  AC_MSG_CHECKING([where lisp files should go])
+  if test -z "$lispdir"; then
     dnl Set default value
-    lispdir="\$(datadir)/emacs/site-lisp"
-    if test "x$prefix" = "xNONE"; then
-      if test -d $ac_default_prefix/share/emacs/site-lisp; then
-       lispdir="\$(prefix)/share/emacs/site-lisp"
-      else
-       if test -d $ac_default_prefix/lib/emacs/site-lisp; then
-         lispdir="\$(prefix)/lib/emacs/site-lisp"
+    theprefix=$prefix
+    if test "$theprefix" = NONE; then
+       theprefix=$ac_default_prefix
+    fi
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+       datadir="\$(prefix)/lib"
+       lispdir="\$(datadir)/${EMACS_FLAVOR}/site-packages/lisp/${GNUS_PRODUCT_NAME}"
+    else
+       lispdir="\$(datadir)/${EMACS_FLAVOR}/site-lisp/${GNUS_PRODUCT_NAME}"
+    fi
+    for thedir in share lib; do
+       potential=
+       if test -d ${theprefix}/${thedir}/${EMACS_FLAVOR}/site-lisp; then
+          if test "$EMACS_FLAVOR" = "xemacs"; then
+              lispdir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-packages/lisp/${GNUS_PRODUCT_NAME}"
+          else
+              lispdir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-lisp/${GNUS_PRODUCT_NAME}"
+          fi
+          break
        fi
-      fi
+    done
+  fi
+  if test ${EMACS_FLAVOR} = xemacs; then
+    AC_MSG_RESULT([$lispdir
+         (it will be ignored when \"make install-package[[-ja]]\" is done)])
+  else
+    AC_MSG_RESULT([$lispdir])
+  fi
+  AC_SUBST(lispdir)
+])
+
+AC_DEFUN(AC_PATH_ETCDIR, [
+  AC_ARG_WITH(etcdir,[  --with-etcdir=DIR       Where to install etc files], etcdir=${withval})
+  AC_MSG_CHECKING([where etc files should go])
+  if test -z "$etcdir"; then
+    dnl Set default value.
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+      etcdir="\$(lispdir)/../../etc"
+    else
+    etcdir="\$(lispdir)/../etc"
+    fi
+  fi
+  AC_MSG_RESULT($etcdir)
+  AC_SUBST(etcdir)
+])
+
+dnl 
+dnl This is a bit on the "evil hack" side of things.  It is so we can
+dnl have a different default infodir for XEmacs.  A user can still specify
+dnl someplace else with '--infodir=DIR'.
+dnl
+AC_DEFUN(AC_PATH_INFO_DIR, [
+  AC_MSG_CHECKING([where the TeXinfo docs should go])
+  dnl Set default value.  This must be an absolute path.
+  if test "$infodir" = "\${prefix}/info"; then
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+      info_dir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-packages/info"
+    else
+      info_dir="\$(prefix)/info"
+    fi
+  else
+    info_dir=$infodir
+  fi
+  AC_MSG_RESULT([$info_dir
+         (it will be ignored when \"make install-package[[-ja]]\" is done)])
+  AC_SUBST(info_dir)
+])
+
+dnl
+dnl This will set the XEmacs command line options to be slightly different
+dnl from the Emacs ones.  If building with XEmacs the options will be
+dnl "-batch -no-autoloads..." to give a much cleaner build environment.
+dnl
+AC_DEFUN(AC_SET_BUILD_FLAGS, [
+  AC_MSG_CHECKING([which options to pass on to (X)Emacs])
+  if test "x$FLAGS" = "x"; then
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+      FLAGS="-batch -no-autoloads -l \$(srcdir)/dgnushack.el"
     else
-      if test -d $prefix/share/emacs/site-lisp; then
-       lispdir="\$(prefix)/share/emacs/site-lisp"
+      FLAGS="-batch -q -no-site-file -l \$(srcdir)/dgnushack.el"
+    fi
+  else
+    FLAGS=$FLAGS
+  fi
+  AC_MSG_RESULT($FLAGS)
+  AC_SUBST(FLAGS)
+])
+
+dnl
+dnl Check whether a function exists in a library
+dnl All '_' characters in the first argument are converted to '-'
+dnl
+AC_DEFUN(AC_EMACS_CHECK_LIB, [
+if test -z "$3"; then
+       AC_MSG_CHECKING(for $2 in $1)
+fi
+library=`echo $1 | tr _ -`
+AC_EMACS_LISP($1,(progn (fmakunbound (quote $2)) (condition-case nil (progn (require (quote $library)) (fboundp (quote $2))) (error (prog1 nil (message \"$library not found\"))))),"noecho")
+if test "${EMACS_cv_SYS_$1}" = nil; then
+       EMACS_cv_SYS_$1=no
+fi
+if test "${EMACS_cv_SYS_$1}" = t; then
+       EMACS_cv_SYS_$1=yes
+fi
+HAVE_$1=${EMACS_cv_SYS_$1}
+AC_SUBST(HAVE_$1)
+if test -z "$3"; then
+       AC_MSG_RESULT($HAVE_$1)
+fi
+])
+
+dnl
+dnl Perform sanity checking and try to locate the W3 package
+dnl
+AC_DEFUN(AC_CHECK_W3, [
+AC_MSG_CHECKING(for acceptable W3 version)
+
+dnl Ignore cache.
+unset EMACS_cv_ACCEPTABLE_W3;
+unset EMACS_cv_SYS_w3_dir;
+unset EMACS_cv_SYS_w3_forms;
+
+AC_CACHE_VAL(EMACS_cv_ACCEPTABLE_W3,[
+AC_EMACS_CHECK_LIB(w3_forms, w3-form-encode-xwfu,"noecho")
+if test "${HAVE_w3_forms}" = yes; then
+       EMACS_cv_ACCEPTABLE_W3=yes
+else
+       EMACS_cv_ACCEPTABLE_W3=
+fi
+
+if test "${EMACS_cv_ACCEPTABLE_W3}" = yes; then
+       AC_EMACS_LISP(w3_dir,(file-name-directory (locate-library \"w3-forms\")),"noecho")
+       EMACS_cv_ACCEPTABLE_W3=$EMACS_cv_SYS_w3_dir
+fi
+])
+   AC_ARG_WITH(w3,[  --with-w3=DIR           Specify where to find the w3 package], [ EMACS_cv_ACCEPTABLE_W3=`( cd $withval && pwd || echo "$withval" ) 2> /dev/null` ])
+   W3=${EMACS_cv_ACCEPTABLE_W3}
+   AC_SUBST(W3)
+   if test -z "${EMACS_cv_ACCEPTABLE_W3}"; then
+       AC_MSG_RESULT(not found)
+   else
+       AC_MSG_RESULT(${W3})
+   fi
+])
+
+dnl
+dnl Perform sanity checking and try to locate the W3 package
+dnl
+AC_DEFUN(AC_CHECK_URL, [
+AC_MSG_CHECKING(for acceptable URL version)
+
+dnl Ignore cache.
+unset EMACS_cv_ACCEPTABLE_URL;
+unset EMACS_cv_SYS_url_dir;
+unset EMACS_cv_SYS_url;
+
+AC_CACHE_VAL(EMACS_cv_ACCEPTABLE_URL,[
+AC_EMACS_CHECK_LIB(url, url-retrieve, "noecho")
+if test "${HAVE_url}" = yes; then
+       EMACS_cv_ACCEPTABLE_URL=yes
+else
+       EMACS_cv_ACCEPTABLE_URL=
+fi
+
+if test "${EMACS_cv_ACCEPTABLE_URL}" = yes; then
+       AC_EMACS_LISP(url_dir,(file-name-directory (locate-library \"url\")),"noecho")
+       EMACS_cv_ACCEPTABLE_URL=$EMACS_cv_SYS_url_dir
+fi
+])
+   AC_ARG_WITH(url,[  --with-url=DIR          Specify where to find the url package], [ EMACS_cv_ACCEPTABLE_URL=`( cd $withval && pwd || echo "$withval" ) 2> /dev/null` ])
+   URL=${EMACS_cv_ACCEPTABLE_URL}
+   AC_SUBST(URL)
+   if test -z "${EMACS_cv_ACCEPTABLE_URL}"; then
+       AC_MSG_RESULT(not found)
+   else
+       AC_MSG_RESULT(${URL})
+   fi
+])
+
+dnl
+dnl Perform checking available fonts: Adobe Bembo, Adobe Futura and 
+dnl Bitstream Courier.
+dnl
+
+AC_DEFUN(GNUS_CHECK_FONTS, [
+test "$LATEX" = t && LATEX=
+test "$LATEX" || AC_PATH_PROGS(LATEX, latex, no)
+AC_MSG_CHECKING(for available fonts)
+AC_ARG_WITH(fonts,[  --with-fonts            Assume all fonts required are available],[USE_FONTS="$withval"])
+WITH_FONTS_bembo='%'
+WITHOUT_FONTS_bembo=
+WITH_FONTS_pfu='%'
+WITHOUT_FONTS_pfu=
+WITH_FONTS_bcr='%'
+WITHOUT_FONTS_bcr=
+if test -z "${USE_FONTS}"; then
+  if test "${LATEX}" = no; then
+       :
+  else
+    OUTPUT=./conftest-$$
+    echo '\nonstopmode\documentclass{article}\usepackage{bembo}\begin{document}\end{document}' > ${OUTPUT}
+    if ${LATEX} ${OUTPUT} </dev/null >& AC_FD_CC 2>&1  ; then  
+      if test -z "${USE_FONTS}"; then
+       USE_FONTS="Adobe Bembo"
       else
-       if test -d $prefix/lib/emacs/site-lisp; then
-         lispdir="\$(prefix)/lib/emacs/site-lisp"
-       fi
+       USE_FONTS="${USE_FONTS}, Adobe Bembo"
       fi
+      WITH_FONTS_bembo=
+      WITHOUT_FONTS_bembo='%'
     fi
-    AC_MSG_RESULT($lispdir)
+    echo '\nonstopmode\documentclass{article}\begin{document}{\fontfamily{pfu}\fontsize{10pt}{10}\selectfont test}\end{document}' > ${OUTPUT}
+    if retval=`${LATEX} ${OUTPUT} </dev/null 2>& AC_FD_CC`; then
+      if echo "$retval" | grep 'Some font shapes were not available' >& AC_FD_CC 2>&1  ; then  
+       :
+      else
+        if test -z "${USE_FONTS}"; then
+         USE_FONTS="Adobe Futura"
+        else
+         USE_FONTS="${USE_FONTS}, Adobe Futura"
+        fi
+        WITH_FONTS_pfu=
+        WITHOUT_FONTS_pfu='%'
+      fi
+    fi
+    echo '\nonstopmode\documentclass{article}\begin{document}{\fontfamily{bcr}\fontsize{10pt}{10}\selectfont test}\end{document}' > ${OUTPUT}
+    if retval=`${LATEX} ${OUTPUT} </dev/null 2>& AC_FD_CC`; then
+      if echo "$retval" | grep 'Some font shapes were not available' >& AC_FD_CC 2>&1  ; then  
+       :
+      else
+        if test -z "${USE_FONTS}"; then
+         USE_FONTS="Bitstream Courier"
+        else
+         USE_FONTS="${USE_FONTS}, Bitstream Courier"
+        fi
+        WITH_FONTS_bcr=
+        WITHOUT_FONTS_bcr='%'
+      fi
+    fi
+    rm -f ${OUTPUT} ${OUTPUT}.aux ${OUTPUT}.log ${OUTPUT}.dvi
   fi
-  AC_SUBST(lispdir)])
+elif test "${USE_FONTS}" = yes ; then
+  WITH_FONTS_bembo=
+  WITHOUT_FONTS_bembo='%'
+  WITH_FONTS_pfu=
+  WITHOUT_FONTS_pfu='%'
+  WITH_FONTS_bcr=
+  WITHOUT_FONTS_bcr='%'
+fi
+AC_SUBST(WITH_FONTS_bembo)
+AC_SUBST(WITHOUT_FONTS_bembo)
+AC_SUBST(WITH_FONTS_pfu)
+AC_SUBST(WITHOUT_FONTS_pfu)
+AC_SUBST(WITH_FONTS_bcr)
+AC_SUBST(WITHOUT_FONTS_bcr)
+if test -z "${USE_FONTS}" ; then
+  USE_FONTS=no
+fi
+USE_FONTS=`echo "${USE_FONTS}" | sed 's/,\([[^,]]*\)$/ and\1/'`
+AC_MSG_RESULT(${USE_FONTS})
+if test "${USE_FONTS}" = yes ; then
+  USE_FONTS='Set in Adobe Bembo, Adobe Futura and Bitstream Courier.'
+elif test "${USE_FONTS}" = no ; then
+  USE_FONTS=''
+else
+  USE_FONTS="Set in ${USE_FONTS}."
+fi
+AC_SUBST(USE_FONTS)
+])
+
+AC_DEFUN(AC_EXAMINE_PACKAGEDIR,
+ [dnl Examine PACKAGEDIR.
+  AC_EMACS_LISP(PACKAGEDIR,
+    (let (package-dir)\
+      (if (boundp (quote early-packages))\
+         (let ((dirs (delq nil (append (if early-package-load-path\
+                                           early-packages)\
+                                       (if late-package-load-path\
+                                           late-packages)\
+                                       (if last-package-load-path\
+                                           last-packages)))))\
+           (while (and dirs (not package-dir))\
+             (if (file-directory-p (car dirs))\
+                 (setq package-dir (car dirs)\
+                       dirs (cdr dirs))))))\
+      (or package-dir \"\")),
+    "noecho")])
+
+AC_DEFUN(AC_PATH_PACKAGEDIR,
+ [dnl Check for PACKAGEDIR.
+  if test ${EMACS_FLAVOR} = xemacs; then
+    AC_MSG_CHECKING([where the XEmacs package is])
+    AC_ARG_WITH(packagedir,
+      [  --with-packagedir=DIR   package DIR for XEmacs],
+      [if test "$withval" != yes -a -n "$withval"; then
+       PACKAGEDIR=$withval
+      else
+       AC_EXAMINE_PACKAGEDIR
+      fi],
+      AC_EXAMINE_PACKAGEDIR)
+    if test -z "$PACKAGEDIR"; then
+      AC_MSG_RESULT(not found)
+    else
+      AC_MSG_RESULT($PACKAGEDIR)
+    fi
+  else
+    PACKAGEDIR=
+  fi
+  AC_SUBST(PACKAGEDIR)])
+
+AC_DEFUN(AC_ADD_LOAD_PATH,
+ [dnl Check for additional load path.
+  AC_ARG_WITH(addpath,
+   [  --with-addpath=PATH     search Emacs-Lisp libraries with PATH
+                          use colons to separate directory names],
+   [if test "$withval" != yes -a -n "$withval"; then
+      AC_MSG_CHECKING([where to find the additional elisp libraries])
+      ADDITIONAL_LOAD_PATH=$withval
+      AC_MSG_RESULT($ADDITIONAL_LOAD_PATH)
+    fi],
+    ADDITIONAL_LOAD_PATH=)
+  AC_SUBST(ADDITIONAL_LOAD_PATH)])
index 41263dc..f9209ed 100755 (executable)
--- a/configure
+++ b/configure
 #! /bin/sh
-
 # Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12 
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by GNU Autoconf 2.57.
 #
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  as_mkdir_p=false
+fi
 
-# Defaults:
-ac_help=
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
 ac_default_prefix=/usr/local
-# Any additions from configure.in:
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="lisp/gnus.el"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS GNUS_PRODUCT_NAME SET_MAKE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MAKEINFO EMACS XEMACS lispdir etcdir info_dir HAVE_url URL HAVE_w3_forms W3 FLAGS LATEX WITH_FONTS_bembo WITHOUT_FONTS_bembo WITH_FONTS_pfu WITHOUT_FONTS_pfu WITH_FONTS_bcr WITHOUT_FONTS_bcr USE_FONTS PACKAGEDIR ADDITIONAL_LOAD_PATH LIBOBJS LTLIBOBJS'
+ac_subst_files=''
 
 # Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
 # The variables have the same names as the options, with
 # dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
 exec_prefix=NONE
-host=NONE
 no_create=
-nonopt=NONE
 no_recursion=
 prefix=NONE
 program_prefix=NONE
@@ -29,10 +290,15 @@ program_transform_name=s,x,x,
 silent=
 site=
 srcdir=
-target=NONE
 verbose=
 x_includes=NONE
 x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
 bindir='${exec_prefix}/bin'
 sbindir='${exec_prefix}/sbin'
 libexecdir='${exec_prefix}/libexec'
@@ -46,16 +312,9 @@ oldincludedir='/usr/include'
 infodir='${prefix}/info'
 mandir='${prefix}/man'
 
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
 ac_prev=
 for ac_option
 do
-
   # If the previous option needs an argument, assign it.
   if test -n "$ac_prev"; then
     eval "$ac_prev=\$ac_option"
@@ -63,59 +322,59 @@ do
     continue
   fi
 
-  case "$ac_option" in
-  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) ac_optarg= ;;
-  esac
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
 
   # Accept the important Cygnus configure options, so we can diagnose typos.
 
-  case "$ac_option" in
+  case $ac_option in
 
   -bindir | --bindir | --bindi | --bind | --bin | --bi)
     ac_prev=bindir ;;
   -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir="$ac_optarg" ;;
+    bindir=$ac_optarg ;;
 
   -build | --build | --buil | --bui | --bu)
-    ac_prev=build ;;
+    ac_prev=build_alias ;;
   -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build="$ac_optarg" ;;
+    build_alias=$ac_optarg ;;
 
   -cache-file | --cache-file | --cache-fil | --cache-fi \
   | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
     ac_prev=cache_file ;;
   -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
   | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file="$ac_optarg" ;;
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
 
   -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
     ac_prev=datadir ;;
   -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
   | --da=*)
-    datadir="$ac_optarg" ;;
+    datadir=$ac_optarg ;;
 
   -disable-* | --disable-*)
-    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
     # Reject names that are not valid shell variable names.
-    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
-      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
-    fi
-    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
-    eval "enable_${ac_feature}=no" ;;
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
 
   -enable-* | --enable-*)
-    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
-    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
-      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
-    fi
-    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
-    case "$ac_option" in
-      *=*) ;;
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
       *) ac_optarg=yes ;;
     esac
-    eval "enable_${ac_feature}='$ac_optarg'" ;;
+    eval "enable_$ac_feature='$ac_optarg'" ;;
 
   -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
   | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -124,95 +383,47 @@ do
   -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
   | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
   | --exec=* | --exe=* | --ex=*)
-    exec_prefix="$ac_optarg" ;;
+    exec_prefix=$ac_optarg ;;
 
   -gas | --gas | --ga | --g)
     # Obsolete; use --with-gas.
     with_gas=yes ;;
 
-  -help | --help | --hel | --he)
-    # Omit some internal or obsolete options to make the list less imposing.
-    # This message is too long to be a string in the A/UX 3.1 sh.
-    cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
-  --cache-file=FILE       cache test results in FILE
-  --help                  print this message
-  --no-create             do not create output files
-  --quiet, --silent       do not print \`checking...' messages
-  --version               print the version of autoconf that created configure
-Directory and file names:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-                          [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-                          [same as prefix]
-  --bindir=DIR            user executables in DIR [EPREFIX/bin]
-  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
-  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
-  --datadir=DIR           read-only architecture-independent data in DIR
-                          [PREFIX/share]
-  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
-  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
-                          [PREFIX/com]
-  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
-  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
-  --includedir=DIR        C header files in DIR [PREFIX/include]
-  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
-  --infodir=DIR           info documentation in DIR [PREFIX/info]
-  --mandir=DIR            man documentation in DIR [PREFIX/man]
-  --srcdir=DIR            find the sources in DIR [configure dir or ..]
-  --program-prefix=PREFIX prepend PREFIX to installed program names
-  --program-suffix=SUFFIX append SUFFIX to installed program names
-  --program-transform-name=PROGRAM
-                          run sed PROGRAM on installed program names
-EOF
-    cat << EOF
-Host type:
-  --build=BUILD           configure for building on BUILD [BUILD=HOST]
-  --host=HOST             configure for HOST [guessed]
-  --target=TARGET         configure for TARGET [TARGET=HOST]
-Features and packages:
-  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
-  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
-  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
-  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
-  --x-includes=DIR        X include files are in DIR
-  --x-libraries=DIR       X library files are in DIR
-EOF
-    if test -n "$ac_help"; then
-      echo "--enable and --with options recognized:$ac_help"
-    fi
-    exit 0 ;;
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
 
   -host | --host | --hos | --ho)
-    ac_prev=host ;;
+    ac_prev=host_alias ;;
   -host=* | --host=* | --hos=* | --ho=*)
-    host="$ac_optarg" ;;
+    host_alias=$ac_optarg ;;
 
   -includedir | --includedir | --includedi | --included | --include \
   | --includ | --inclu | --incl | --inc)
     ac_prev=includedir ;;
   -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
   | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir="$ac_optarg" ;;
+    includedir=$ac_optarg ;;
 
   -infodir | --infodir | --infodi | --infod | --info | --inf)
     ac_prev=infodir ;;
   -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir="$ac_optarg" ;;
+    infodir=$ac_optarg ;;
 
   -libdir | --libdir | --libdi | --libd)
     ac_prev=libdir ;;
   -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir="$ac_optarg" ;;
+    libdir=$ac_optarg ;;
 
   -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
   | --libexe | --libex | --libe)
     ac_prev=libexecdir ;;
   -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
   | --libexe=* | --libex=* | --libe=*)
-    libexecdir="$ac_optarg" ;;
+    libexecdir=$ac_optarg ;;
 
   -localstatedir | --localstatedir | --localstatedi | --localstated \
   | --localstate | --localstat | --localsta | --localst \
@@ -221,19 +432,19 @@ EOF
   -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
   | --localstate=* | --localstat=* | --localsta=* | --localst=* \
   | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
-    localstatedir="$ac_optarg" ;;
+    localstatedir=$ac_optarg ;;
 
   -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
     ac_prev=mandir ;;
   -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir="$ac_optarg" ;;
+    mandir=$ac_optarg ;;
 
   -nfp | --nfp | --nf)
     # Obsolete; use --without-fp.
     with_fp=no ;;
 
   -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c)
+  | --no-cr | --no-c | -n)
     no_create=yes ;;
 
   -no-recursion | --no-recursion | --no-recursio | --no-recursi \
@@ -247,26 +458,26 @@ EOF
   -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
   | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
   | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir="$ac_optarg" ;;
+    oldincludedir=$ac_optarg ;;
 
   -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
     ac_prev=prefix ;;
   -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix="$ac_optarg" ;;
+    prefix=$ac_optarg ;;
 
   -program-prefix | --program-prefix | --program-prefi | --program-pref \
   | --program-pre | --program-pr | --program-p)
     ac_prev=program_prefix ;;
   -program-prefix=* | --program-prefix=* | --program-prefi=* \
   | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix="$ac_optarg" ;;
+    program_prefix=$ac_optarg ;;
 
   -program-suffix | --program-suffix | --program-suffi | --program-suff \
   | --program-suf | --program-su | --program-s)
     ac_prev=program_suffix ;;
   -program-suffix=* | --program-suffix=* | --program-suffi=* \
   | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix="$ac_optarg" ;;
+    program_suffix=$ac_optarg ;;
 
   -program-transform-name | --program-transform-name \
   | --program-transform-nam | --program-transform-na \
@@ -283,7 +494,7 @@ EOF
   | --program-transfo=* | --program-transf=* \
   | --program-trans=* | --program-tran=* \
   | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name="$ac_optarg" ;;
+    program_transform_name=$ac_optarg ;;
 
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil)
@@ -293,7 +504,7 @@ EOF
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
   | --sbi=* | --sb=*)
-    sbindir="$ac_optarg" ;;
+    sbindir=$ac_optarg ;;
 
   -sharedstatedir | --sharedstatedir | --sharedstatedi \
   | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -304,58 +515,57 @@ EOF
   | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
   | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
   | --sha=* | --sh=*)
-    sharedstatedir="$ac_optarg" ;;
+    sharedstatedir=$ac_optarg ;;
 
   -site | --site | --sit)
     ac_prev=site ;;
   -site=* | --site=* | --sit=*)
-    site="$ac_optarg" ;;
+    site=$ac_optarg ;;
 
   -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
     ac_prev=srcdir ;;
   -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir="$ac_optarg" ;;
+    srcdir=$ac_optarg ;;
 
   -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
   | --syscon | --sysco | --sysc | --sys | --sy)
     ac_prev=sysconfdir ;;
   -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
   | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir="$ac_optarg" ;;
+    sysconfdir=$ac_optarg ;;
 
   -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target ;;
+    ac_prev=target_alias ;;
   -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target="$ac_optarg" ;;
+    target_alias=$ac_optarg ;;
 
   -v | -verbose | --verbose | --verbos | --verbo | --verb)
     verbose=yes ;;
 
-  -version | --version | --versio | --versi | --vers)
-    echo "configure generated by autoconf version 2.12"
-    exit 0 ;;
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
 
   -with-* | --with-*)
-    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
     # Reject names that are not valid shell variable names.
-    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
-      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
-    fi
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
     ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case "$ac_option" in
-      *=*) ;;
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
       *) ac_optarg=yes ;;
     esac
-    eval "with_${ac_package}='$ac_optarg'" ;;
+    eval "with_$ac_package='$ac_optarg'" ;;
 
   -without-* | --without-*)
-    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
     # Reject names that are not valid shell variable names.
-    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
-      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
-    fi
-    ac_package=`echo $ac_package| sed 's/-/_/g'`
-    eval "with_${ac_package}=no" ;;
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
 
   --x)
     # Obsolete; use --with-x.
@@ -366,99 +576,110 @@ EOF
     ac_prev=x_includes ;;
   -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
   | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes="$ac_optarg" ;;
+    x_includes=$ac_optarg ;;
 
   -x-libraries | --x-libraries | --x-librarie | --x-librari \
   | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
     ac_prev=x_libraries ;;
   -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
   | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries="$ac_optarg" ;;
+    x_libraries=$ac_optarg ;;
 
-  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
     ;;
 
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
   *)
-    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
-      echo "configure: warning: $ac_option: invalid host type" 1>&2
-    fi
-    if test "x$nonopt" != xNONE; then
-      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
-    fi
-    nonopt="$ac_option"
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
     ;;
 
   esac
 done
 
 if test -n "$ac_prev"; then
-  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
-  exec 6>/dev/null
-else
-  exec 6>&1
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
 fi
-exec 5>./config.log
 
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
 
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir
 do
-  case "$ac_arg" in
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c) ;;
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
-  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
-  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
   esac
 done
 
-# NLS nuisances.
-# Only set these to C if already set.  These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
 
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
 
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=lisp/gnus.el
 
 # Find the source files, if location was not specified.
 if test -z "$srcdir"; then
   ac_srcdir_defaulted=yes
   # Try the directory containing this script, then its parent.
-  ac_prog=$0
-  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
-  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$0" : 'X\(//\)[^/]' \| \
+         X"$0" : 'X\(//\)$' \| \
+         X"$0" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
   srcdir=$ac_confdir
   if test ! -r $srcdir/$ac_unique_file; then
     srcdir=..
@@ -468,13 +689,405 @@ else
 fi
 if test ! -r $srcdir/$ac_unique_file; then
   if test "$ac_srcdir_defaulted" = yes; then
-    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
   else
-    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
   fi
 fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-emacs=EMACS      compile with EMACS [EMACS=emacs, mule...]
+  --with-xemacs=XEMACS    compile with XEMACS [XEMACS=xemacs]
+  --with-lispdir=DIR      Where to install lisp files
+                          (for XEmacs package, use --with-packagedir instead)
+  --with-etcdir=DIR       Where to install etc files
+  --with-url=DIR          Specify where to find the url package
+  --with-w3=DIR           Specify where to find the w3 package
+  --with-fonts            Assume all fonts required are available
+  --with-packagedir=DIR   package DIR for XEmacs
+  --with-addpath=PATH     search Emacs-Lisp libraries with PATH
+                          use colons to separate directory names
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+           test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.57.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+        ac_must_keep_next=false # Got value, back to normal.
+      else
+        case $ac_arg in
+          *=* | --config-cache | -C | -disable-* | --disable-* \
+          | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+          | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+          | -with-* | --with-* | -without-* | --without-* | --x)
+            case "$ac_configure_args0 " in
+              "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+            esac
+            ;;
+          -* ) ac_must_keep_next=true ;;
+        esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=$`echo $ac_var`
+        echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core core.* *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
 
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
 # Prefer explicitly selected file to automatically selected ones.
 if test -z "$CONFIG_SITE"; then
   if test "x$prefix" != xNONE; then
@@ -485,63 +1098,142 @@ if test -z "$CONFIG_SITE"; then
 fi
 for ac_site_file in $CONFIG_SITE; do
   if test -r "$ac_site_file"; then
-    echo "loading site script $ac_site_file"
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
     . "$ac_site_file"
   fi
 done
 
 if test -r "$cache_file"; then
-  echo "loading cache $cache_file"
-  . $cache_file
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
 else
-  echo "creating cache $cache_file"
-  > $cache_file
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+        ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
 fi
 
 ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
 ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
-  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
-  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
-    ac_n= ac_c='
-' ac_t='       '
-  else
-    ac_n=-n ac_c= ac_t=
-  fi
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+echo $ECHO_N "defining gnus product name... $ECHO_C"
+  if test "${EMACS_cv_GNUS_PRODUCT_NAME+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_n= ac_c='\c' ac_t=
+  EMACS_cv_GNUS_PRODUCT_NAME=t-gnus
 fi
 
+  GNUS_PRODUCT_NAME=${EMACS_cv_GNUS_PRODUCT_NAME}
+  echo "$as_me:$LINENO: result: ${GNUS_PRODUCT_NAME}" >&5
+echo "${ECHO_T}${GNUS_PRODUCT_NAME}" >&6
 
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:523: checking whether ${MAKE-make} sets \${MAKE}" >&5
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat > conftestmake <<\EOF
+  cat >conftest.make <<\_ACEOF
 all:
-       @echo 'ac_maketemp="${MAKE}"'
-EOF
+       @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
 # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
 if test -n "$ac_maketemp"; then
   eval ac_cv_prog_make_${ac_make}_set=yes
 else
   eval ac_cv_prog_make_${ac_make}_set=no
 fi
-rm -f conftestmake
+rm -f conftest.make
 fi
 if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
   SET_MAKE=
 else
-  echo "$ac_t""no" 1>&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
   SET_MAKE="MAKE=${MAKE-make}"
 fi
 
@@ -555,14 +1247,20 @@ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/install.sh -c"
     break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
   fi
 done
 if test -z "$ac_aux_dir"; then
-  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
 fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
 
 # Find a good install program.  We prefer a C program (faster),
 # so one script is as good as another.  But avoid the broken or
@@ -571,408 +1269,1874 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SunOS /usr/etc/install
 # IRIX /sbin/install
 # AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
 # AFS /usr/afsws/bin/install, which mishandles nonexistent args
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:579: checking for a BSD compatible install" >&5
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
 if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
-  for ac_dir in $PATH; do
-    # Account for people who put trailing slashes in PATH elements.
-    case "$ac_dir/" in
-    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
-    *)
-      # OSF1 and SCO ODT 3.0 have their own names for install.
-      for ac_prog in ginstall installbsd scoinst install; do
-        if test -f $ac_dir/$ac_prog; then
-         if test $ac_prog = install &&
-            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
-           # AIX install.  It has an incompatible calling convention.
-           # OSF/1 installbsd also uses dspmsg, but is usable.
-           :
-         else
-           ac_cv_path_install="$ac_dir/$ac_prog -c"
-           break 2
-         fi
-       fi
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
       done
-      ;;
-    esac
-  done
-  IFS="$ac_save_IFS"
+    done
+    ;;
+esac
+done
+
 
 fi
   if test "${ac_cv_path_install+set}" = set; then
-    INSTALL="$ac_cv_path_install"
+    INSTALL=$ac_cv_path_install
   else
     # As a last resort, use the slow shell script.  We don't cache a
     # path for INSTALL within a source directory, because that will
     # break other packages using the cache if that directory is
     # removed, or if the path is relative.
-    INSTALL="$ac_install_sh"
+    INSTALL=$ac_install_sh
   fi
 fi
-echo "$ac_t""$INSTALL" 1>&6
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
 
 # Use test -z because SunOS4 sh mishandles braces in ${var-val}.
 # It thinks the first close brace ends the variable substitution.
 test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
 
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
-# If set to t, that means we are running in a shell under Emacs.
-  # If you have an Emacs named "t", then use the full path.
-  test "$EMACS" = t && EMACS=
-  # Extract the first word of "emacs xemacs", so it can be a program name with args.
-set dummy emacs xemacs; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:634: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_path_EMACS'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  case "$EMACS" in
-  /*)
-  ac_cv_path_EMACS="$EMACS" # Let the user override the test with a path.
-  ;;
-  *)
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
-  for ac_dir in $PATH; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/$ac_word; then
-      ac_cv_path_EMACS="$ac_dir/$ac_word"
-      break
-    fi
-  done
-  IFS="$ac_save_ifs"
-  test -z "$ac_cv_path_EMACS" && ac_cv_path_EMACS="no"
-  ;;
-esac
+# Extract the first word of "makeinfo", so it can be a program name with args.
+set dummy makeinfo; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_MAKEINFO+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$MAKEINFO"; then
+  ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MAKEINFO="makeinfo"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_MAKEINFO" && ac_cv_prog_MAKEINFO="no"
 fi
-EMACS="$ac_cv_path_EMACS"
-if test -n "$EMACS"; then
-  echo "$ac_t""$EMACS" 1>&6
+fi
+MAKEINFO=$ac_cv_prog_MAKEINFO
+if test -n "$MAKEINFO"; then
+  echo "$as_me:$LINENO: result: $MAKEINFO" >&5
+echo "${ECHO_T}$MAKEINFO" >&6
 else
-  echo "$ac_t""no" 1>&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-  if test $EMACS != "no"; then
-    echo $ac_n "checking where .elc files should go""... $ac_c" 1>&6
-echo "configure:665: checking where .elc files should go" >&5
-        lispdir="\$(datadir)/emacs/site-lisp"
-    if test "x$prefix" = "xNONE"; then
-      if test -d $ac_default_prefix/share/emacs/site-lisp; then
-       lispdir="\$(prefix)/share/emacs/site-lisp"
-      else
-       if test -d $ac_default_prefix/lib/emacs/site-lisp; then
-         lispdir="\$(prefix)/lib/emacs/site-lisp"
-       fi
-      fi
+
+      test "$EMACS" = t && EMACS=
+
+    unset ac_cv_prog_EMACS; unset ac_cv_prog_XEMACS;
+
+
+# Check whether --with-emacs or --without-emacs was given.
+if test "${with_emacs+set}" = set; then
+  withval="$with_emacs"
+  if test "$withval" = yes -o -z "$withval"; then
+      for ac_prog in emacs xemacs mule
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_EMACS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$EMACS"; then
+  ac_cv_prog_EMACS="$EMACS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_EMACS="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+EMACS=$ac_cv_prog_EMACS
+if test -n "$EMACS"; then
+  echo "$as_me:$LINENO: result: $EMACS" >&5
+echo "${ECHO_T}$EMACS" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$EMACS" && break
+done
+test -n "$EMACS" || EMACS="emacs"
+
     else
-      if test -d $prefix/share/emacs/site-lisp; then
-       lispdir="\$(prefix)/share/emacs/site-lisp"
-      else
-       if test -d $prefix/lib/emacs/site-lisp; then
-         lispdir="\$(prefix)/lib/emacs/site-lisp"
+      # Extract the first word of "$withval", so it can be a program name with args.
+set dummy $withval; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_EMACS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$EMACS"; then
+  ac_cv_prog_EMACS="$EMACS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_EMACS="$withval"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_EMACS" && ac_cv_prog_EMACS="emacs"
+fi
+fi
+EMACS=$ac_cv_prog_EMACS
+if test -n "$EMACS"; then
+  echo "$as_me:$LINENO: result: $EMACS" >&5
+echo "${ECHO_T}$EMACS" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    fi
+fi;
+
+# Check whether --with-xemacs or --without-xemacs was given.
+if test "${with_xemacs+set}" = set; then
+  withval="$with_xemacs"
+  if test "$withval" = yes -o -z "$withval"; then
+      # Extract the first word of "xemacs", so it can be a program name with args.
+set dummy xemacs; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_XEMACS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$XEMACS"; then
+  ac_cv_prog_XEMACS="$XEMACS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_XEMACS="xemacs"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_XEMACS" && ac_cv_prog_XEMACS="xemacs"
+fi
+fi
+XEMACS=$ac_cv_prog_XEMACS
+if test -n "$XEMACS"; then
+  echo "$as_me:$LINENO: result: $XEMACS" >&5
+echo "${ECHO_T}$XEMACS" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    else
+      # Extract the first word of "$withval", so it can be a program name with args.
+set dummy $withval; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_XEMACS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$XEMACS"; then
+  ac_cv_prog_XEMACS="$XEMACS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_XEMACS="$withval"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_XEMACS" && ac_cv_prog_XEMACS="xemacs"
+fi
+fi
+XEMACS=$ac_cv_prog_XEMACS
+if test -n "$XEMACS"; then
+  echo "$as_me:$LINENO: result: $XEMACS" >&5
+echo "${ECHO_T}$XEMACS" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    fi
+    EMACS=$XEMACS
+else
+  XEMACS=xemacs
+    test -z "$EMACS" && for ac_prog in emacs xemacs mule
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_EMACS+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$EMACS"; then
+  ac_cv_prog_EMACS="$EMACS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_EMACS="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+EMACS=$ac_cv_prog_EMACS
+if test -n "$EMACS"; then
+  echo "$as_me:$LINENO: result: $EMACS" >&5
+echo "${ECHO_T}$EMACS" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$EMACS" && break
+done
+test -n "$EMACS" || EMACS="emacs"
+
+fi;
+
+
+
+  echo "$as_me:$LINENO: checking what a flavor does $EMACS have" >&5
+echo $ECHO_N "checking what a flavor does $EMACS have... $ECHO_C" >&6
+
+    unset EMACS_cv_SYS_flavor;
+
+
+elisp="(cond ((featurep (quote xemacs)) \"XEmacs\")\
+          ((boundp (quote MULE)) \"MULE\")\
+          (t \"FSF Emacs\"))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for flavor" >&5
+echo $ECHO_N "checking for flavor... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_flavor+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_flavor=$retval
+
+fi
+
+flavor=${EMACS_cv_SYS_flavor}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $flavor" >&5
+echo "${ECHO_T}$flavor" >&6
+fi
+
+  case $EMACS_cv_SYS_flavor in
+  XEmacs)
+    EMACS_FLAVOR=xemacs;;
+  MULE)
+    EMACS_FLAVOR=mule;;
+  *)
+    EMACS_FLAVOR=emacs;;
+  esac
+  echo "$as_me:$LINENO: result: $EMACS_cv_SYS_flavor" >&5
+echo "${ECHO_T}$EMACS_cv_SYS_flavor" >&6
+  if test "$prefix" = NONE; then
+       echo "$as_me:$LINENO: checking prefix for your Emacs" >&5
+echo $ECHO_N "checking prefix for your Emacs... $ECHO_C" >&6
+
+elisp="(expand-file-name \"..\" invocation-directory)"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for prefix" >&5
+echo $ECHO_N "checking for prefix... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_prefix+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_prefix=$retval
+
+fi
+
+prefix=${EMACS_cv_SYS_prefix}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $prefix" >&5
+echo "${ECHO_T}$prefix" >&6
+fi
+
+       prefix=${EMACS_cv_SYS_prefix}
+       echo "$as_me:$LINENO: result: $prefix" >&5
+echo "${ECHO_T}$prefix" >&6
+  fi
+
+# Check whether --with-lispdir or --without-lispdir was given.
+if test "${with_lispdir+set}" = set; then
+  withval="$with_lispdir"
+  lispdir=${withval}
+fi;
+  echo "$as_me:$LINENO: checking where lisp files should go" >&5
+echo $ECHO_N "checking where lisp files should go... $ECHO_C" >&6
+  if test -z "$lispdir"; then
+        theprefix=$prefix
+    if test "$theprefix" = NONE; then
+       theprefix=$ac_default_prefix
+    fi
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+       datadir="\$(prefix)/lib"
+       lispdir="\$(datadir)/${EMACS_FLAVOR}/site-packages/lisp/${GNUS_PRODUCT_NAME}"
+    else
+       lispdir="\$(datadir)/${EMACS_FLAVOR}/site-lisp/${GNUS_PRODUCT_NAME}"
+    fi
+    for thedir in share lib; do
+       potential=
+       if test -d ${theprefix}/${thedir}/${EMACS_FLAVOR}/site-lisp; then
+          if test "$EMACS_FLAVOR" = "xemacs"; then
+              lispdir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-packages/lisp/${GNUS_PRODUCT_NAME}"
+          else
+              lispdir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-lisp/${GNUS_PRODUCT_NAME}"
+          fi
+          break
        fi
-      fi
+    done
+  fi
+  if test ${EMACS_FLAVOR} = xemacs; then
+    echo "$as_me:$LINENO: result: $lispdir
+         (it will be ignored when \"make install-package[-ja]\" is done)" >&5
+echo "${ECHO_T}$lispdir
+         (it will be ignored when \"make install-package[-ja]\" is done)" >&6
+  else
+    echo "$as_me:$LINENO: result: $lispdir" >&5
+echo "${ECHO_T}$lispdir" >&6
+  fi
+
+
+
+
+# Check whether --with-etcdir or --without-etcdir was given.
+if test "${with_etcdir+set}" = set; then
+  withval="$with_etcdir"
+  etcdir=${withval}
+fi;
+  echo "$as_me:$LINENO: checking where etc files should go" >&5
+echo $ECHO_N "checking where etc files should go... $ECHO_C" >&6
+  if test -z "$etcdir"; then
+        if test "$EMACS_FLAVOR" = "xemacs"; then
+      etcdir="\$(lispdir)/../../etc"
+    else
+    etcdir="\$(lispdir)/../etc"
     fi
-    echo "$ac_t""$lispdir" 1>&6
   fi
-  
-# Extract the first word of "makeinfo", so it can be a program name with args.
-set dummy makeinfo; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:690: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_path_MAKEINFO'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  case "$MAKEINFO" in
-  /*)
-  ac_cv_path_MAKEINFO="$MAKEINFO" # Let the user override the test with a path.
+  echo "$as_me:$LINENO: result: $etcdir" >&5
+echo "${ECHO_T}$etcdir" >&6
+
+
+
+  echo "$as_me:$LINENO: checking where the TeXinfo docs should go" >&5
+echo $ECHO_N "checking where the TeXinfo docs should go... $ECHO_C" >&6
+    if test "$infodir" = "\${prefix}/info"; then
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+      info_dir="\$(prefix)/${thedir}/${EMACS_FLAVOR}/site-packages/info"
+    else
+      info_dir="\$(prefix)/info"
+    fi
+  else
+    info_dir=$infodir
+  fi
+  echo "$as_me:$LINENO: result: $info_dir
+         (it will be ignored when \"make install-package[-ja]\" is done)" >&5
+echo "${ECHO_T}$info_dir
+         (it will be ignored when \"make install-package[-ja]\" is done)" >&6
+
+
+
+echo "$as_me:$LINENO: checking for acceptable URL version" >&5
+echo $ECHO_N "checking for acceptable URL version... $ECHO_C" >&6
+
+unset EMACS_cv_ACCEPTABLE_URL;
+unset EMACS_cv_SYS_url_dir;
+unset EMACS_cv_SYS_url;
+
+if test "${EMACS_cv_ACCEPTABLE_URL+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for url-retrieve in url" >&5
+echo $ECHO_N "checking for url-retrieve in url... $ECHO_C" >&6
+fi
+library=`echo url | tr _ -`
+
+elisp="(progn (fmakunbound (quote url-retrieve)) (condition-case nil (progn (require (quote $library)) (fboundp (quote url-retrieve))) (error (prog1 nil (message \"$library not found\")))))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for url" >&5
+echo $ECHO_N "checking for url... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_url+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_url=$retval
+
+fi
+
+url=${EMACS_cv_SYS_url}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $url" >&5
+echo "${ECHO_T}$url" >&6
+fi
+
+if test "${EMACS_cv_SYS_url}" = nil; then
+       EMACS_cv_SYS_url=no
+fi
+if test "${EMACS_cv_SYS_url}" = t; then
+       EMACS_cv_SYS_url=yes
+fi
+HAVE_url=${EMACS_cv_SYS_url}
+
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $HAVE_url" >&5
+echo "${ECHO_T}$HAVE_url" >&6
+fi
+
+if test "${HAVE_url}" = yes; then
+       EMACS_cv_ACCEPTABLE_URL=yes
+else
+       EMACS_cv_ACCEPTABLE_URL=
+fi
+
+if test "${EMACS_cv_ACCEPTABLE_URL}" = yes; then
+
+elisp="(file-name-directory (locate-library \"url\"))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for url_dir" >&5
+echo $ECHO_N "checking for url_dir... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_url_dir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_url_dir=$retval
+
+fi
+
+url_dir=${EMACS_cv_SYS_url_dir}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $url_dir" >&5
+echo "${ECHO_T}$url_dir" >&6
+fi
+
+       EMACS_cv_ACCEPTABLE_URL=$EMACS_cv_SYS_url_dir
+fi
+
+fi
+
+
+# Check whether --with-url or --without-url was given.
+if test "${with_url+set}" = set; then
+  withval="$with_url"
+   EMACS_cv_ACCEPTABLE_URL=`( cd $withval && pwd || echo "$withval" ) 2> /dev/null`
+fi;
+   URL=${EMACS_cv_ACCEPTABLE_URL}
+
+   if test -z "${EMACS_cv_ACCEPTABLE_URL}"; then
+       echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+   else
+       echo "$as_me:$LINENO: result: ${URL}" >&5
+echo "${ECHO_T}${URL}" >&6
+   fi
+
+
+echo "$as_me:$LINENO: checking for acceptable W3 version" >&5
+echo $ECHO_N "checking for acceptable W3 version... $ECHO_C" >&6
+
+unset EMACS_cv_ACCEPTABLE_W3;
+unset EMACS_cv_SYS_w3_dir;
+unset EMACS_cv_SYS_w3_forms;
+
+if test "${EMACS_cv_ACCEPTABLE_W3+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for w3-form-encode-xwfu in w3_forms" >&5
+echo $ECHO_N "checking for w3-form-encode-xwfu in w3_forms... $ECHO_C" >&6
+fi
+library=`echo w3_forms | tr _ -`
+
+elisp="(progn (fmakunbound (quote w3-form-encode-xwfu)) (condition-case nil (progn (require (quote $library)) (fboundp (quote w3-form-encode-xwfu))) (error (prog1 nil (message \"$library not found\")))))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for w3_forms" >&5
+echo $ECHO_N "checking for w3_forms... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_w3_forms+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_w3_forms=$retval
+
+fi
+
+w3_forms=${EMACS_cv_SYS_w3_forms}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $w3_forms" >&5
+echo "${ECHO_T}$w3_forms" >&6
+fi
+
+if test "${EMACS_cv_SYS_w3_forms}" = nil; then
+       EMACS_cv_SYS_w3_forms=no
+fi
+if test "${EMACS_cv_SYS_w3_forms}" = t; then
+       EMACS_cv_SYS_w3_forms=yes
+fi
+HAVE_w3_forms=${EMACS_cv_SYS_w3_forms}
+
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $HAVE_w3_forms" >&5
+echo "${ECHO_T}$HAVE_w3_forms" >&6
+fi
+
+if test "${HAVE_w3_forms}" = yes; then
+       EMACS_cv_ACCEPTABLE_W3=yes
+else
+       EMACS_cv_ACCEPTABLE_W3=
+fi
+
+if test "${EMACS_cv_ACCEPTABLE_W3}" = yes; then
+
+elisp="(file-name-directory (locate-library \"w3-forms\"))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for w3_dir" >&5
+echo $ECHO_N "checking for w3_dir... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_w3_dir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_w3_dir=$retval
+
+fi
+
+w3_dir=${EMACS_cv_SYS_w3_dir}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $w3_dir" >&5
+echo "${ECHO_T}$w3_dir" >&6
+fi
+
+       EMACS_cv_ACCEPTABLE_W3=$EMACS_cv_SYS_w3_dir
+fi
+
+fi
+
+
+# Check whether --with-w3 or --without-w3 was given.
+if test "${with_w3+set}" = set; then
+  withval="$with_w3"
+   EMACS_cv_ACCEPTABLE_W3=`( cd $withval && pwd || echo "$withval" ) 2> /dev/null`
+fi;
+   W3=${EMACS_cv_ACCEPTABLE_W3}
+
+   if test -z "${EMACS_cv_ACCEPTABLE_W3}"; then
+       echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+   else
+       echo "$as_me:$LINENO: result: ${W3}" >&5
+echo "${ECHO_T}${W3}" >&6
+   fi
+
+
+  echo "$as_me:$LINENO: checking which options to pass on to (X)Emacs" >&5
+echo $ECHO_N "checking which options to pass on to (X)Emacs... $ECHO_C" >&6
+  if test "x$FLAGS" = "x"; then
+    if test "$EMACS_FLAVOR" = "xemacs"; then
+      FLAGS="-batch -no-autoloads -l \$(srcdir)/dgnushack.el"
+    else
+      FLAGS="-batch -q -no-site-file -l \$(srcdir)/dgnushack.el"
+    fi
+  else
+    FLAGS=$FLAGS
+  fi
+  echo "$as_me:$LINENO: result: $FLAGS" >&5
+echo "${ECHO_T}$FLAGS" >&6
+
+
+
+test "$LATEX" = t && LATEX=
+test "$LATEX" || for ac_prog in latex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_LATEX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $LATEX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path.
   ;;
   *)
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
-  for ac_dir in $PATH; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/$ac_word; then
-      ac_cv_path_MAKEINFO="$ac_dir/$ac_word"
-      break
-    fi
-  done
-  IFS="$ac_save_ifs"
-  test -z "$ac_cv_path_MAKEINFO" && ac_cv_path_MAKEINFO="no"
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
   ;;
 esac
 fi
-MAKEINFO="$ac_cv_path_MAKEINFO"
-if test -n "$MAKEINFO"; then
-  echo "$ac_t""$MAKEINFO" 1>&6
+LATEX=$ac_cv_path_LATEX
+
+if test -n "$LATEX"; then
+  echo "$as_me:$LINENO: result: $LATEX" >&5
+echo "${ECHO_T}$LATEX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$LATEX" && break
+done
+test -n "$LATEX" || LATEX="no"
+
+echo "$as_me:$LINENO: checking for available fonts" >&5
+echo $ECHO_N "checking for available fonts... $ECHO_C" >&6
+
+# Check whether --with-fonts or --without-fonts was given.
+if test "${with_fonts+set}" = set; then
+  withval="$with_fonts"
+  USE_FONTS="$withval"
+fi;
+WITH_FONTS_bembo='%'
+WITHOUT_FONTS_bembo=
+WITH_FONTS_pfu='%'
+WITHOUT_FONTS_pfu=
+WITH_FONTS_bcr='%'
+WITHOUT_FONTS_bcr=
+if test -z "${USE_FONTS}"; then
+  if test "${LATEX}" = no; then
+       :
+  else
+    OUTPUT=./conftest-$$
+    echo '\nonstopmode\documentclass{article}\usepackage{bembo}\begin{document}\end{document}' > ${OUTPUT}
+    if ${LATEX} ${OUTPUT} </dev/null >& 5 2>&1  ; then
+      if test -z "${USE_FONTS}"; then
+       USE_FONTS="Adobe Bembo"
+      else
+       USE_FONTS="${USE_FONTS}, Adobe Bembo"
+      fi
+      WITH_FONTS_bembo=
+      WITHOUT_FONTS_bembo='%'
+    fi
+    echo '\nonstopmode\documentclass{article}\begin{document}{\fontfamily{pfu}\fontsize{10pt}{10}\selectfont test}\end{document}' > ${OUTPUT}
+    if retval=`${LATEX} ${OUTPUT} </dev/null 2>& 5`; then
+      if echo "$retval" | grep 'Some font shapes were not available' >& 5 2>&1  ; then
+       :
+      else
+        if test -z "${USE_FONTS}"; then
+         USE_FONTS="Adobe Futura"
+        else
+         USE_FONTS="${USE_FONTS}, Adobe Futura"
+        fi
+        WITH_FONTS_pfu=
+        WITHOUT_FONTS_pfu='%'
+      fi
+    fi
+    echo '\nonstopmode\documentclass{article}\begin{document}{\fontfamily{bcr}\fontsize{10pt}{10}\selectfont test}\end{document}' > ${OUTPUT}
+    if retval=`${LATEX} ${OUTPUT} </dev/null 2>& 5`; then
+      if echo "$retval" | grep 'Some font shapes were not available' >& 5 2>&1  ; then
+       :
+      else
+        if test -z "${USE_FONTS}"; then
+         USE_FONTS="Bitstream Courier"
+        else
+         USE_FONTS="${USE_FONTS}, Bitstream Courier"
+        fi
+        WITH_FONTS_bcr=
+        WITHOUT_FONTS_bcr='%'
+      fi
+    fi
+    rm -f ${OUTPUT} ${OUTPUT}.aux ${OUTPUT}.log ${OUTPUT}.dvi
+  fi
+elif test "${USE_FONTS}" = yes ; then
+  WITH_FONTS_bembo=
+  WITHOUT_FONTS_bembo='%'
+  WITH_FONTS_pfu=
+  WITHOUT_FONTS_pfu='%'
+  WITH_FONTS_bcr=
+  WITHOUT_FONTS_bcr='%'
+fi
+
+
+
+
+
+
+if test -z "${USE_FONTS}" ; then
+  USE_FONTS=no
+fi
+USE_FONTS=`echo "${USE_FONTS}" | sed 's/,\([^,]*\)$/ and\1/'`
+echo "$as_me:$LINENO: result: ${USE_FONTS}" >&5
+echo "${ECHO_T}${USE_FONTS}" >&6
+if test "${USE_FONTS}" = yes ; then
+  USE_FONTS='Set in Adobe Bembo, Adobe Futura and Bitstream Courier.'
+elif test "${USE_FONTS}" = no ; then
+  USE_FONTS=''
+else
+  USE_FONTS="Set in ${USE_FONTS}."
+fi
+
+
+  if test ${EMACS_FLAVOR} = xemacs; then
+    echo "$as_me:$LINENO: checking where the XEmacs package is" >&5
+echo $ECHO_N "checking where the XEmacs package is... $ECHO_C" >&6
+
+# Check whether --with-packagedir or --without-packagedir was given.
+if test "${with_packagedir+set}" = set; then
+  withval="$with_packagedir"
+  if test "$withval" != yes -a -n "$withval"; then
+       PACKAGEDIR=$withval
+      else
+
+elisp="(let (package-dir)\
+      (if (boundp (quote early-packages))\
+         (let ((dirs (delq nil (append (if early-package-load-path\
+                                           early-packages)\
+                                       (if late-package-load-path\
+                                           late-packages)\
+                                       (if last-package-load-path\
+                                           last-packages)))))\
+           (while (and dirs (not package-dir))\
+             (if (file-directory-p (car dirs))\
+                 (setq package-dir (car dirs)\
+                       dirs (cdr dirs))))))\
+      (or package-dir \"\"))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for PACKAGEDIR" >&5
+echo $ECHO_N "checking for PACKAGEDIR... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_PACKAGEDIR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_PACKAGEDIR=$retval
+
+fi
+
+PACKAGEDIR=${EMACS_cv_SYS_PACKAGEDIR}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $PACKAGEDIR" >&5
+echo "${ECHO_T}$PACKAGEDIR" >&6
+fi
+
+      fi
 else
-  echo "$ac_t""no" 1>&6
+
+elisp="(let (package-dir)\
+      (if (boundp (quote early-packages))\
+         (let ((dirs (delq nil (append (if early-package-load-path\
+                                           early-packages)\
+                                       (if late-package-load-path\
+                                           late-packages)\
+                                       (if last-package-load-path\
+                                           last-packages)))))\
+           (while (and dirs (not package-dir))\
+             (if (file-directory-p (car dirs))\
+                 (setq package-dir (car dirs)\
+                       dirs (cdr dirs))))))\
+      (or package-dir \"\"))"
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: checking for PACKAGEDIR" >&5
+echo $ECHO_N "checking for PACKAGEDIR... $ECHO_C" >&6
+fi
+if test "${EMACS_cv_SYS_PACKAGEDIR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       OUTPUT=./conftest-$$
+       echo ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       eval ${EMACS}' -batch -eval '\''(let ((x '${elisp}')) (write-region (if (stringp x) (princ x) (prin1-to-string x)) nil "'${OUTPUT}'" nil 5))'\' >& 5 2>&1
+       retval=`cat ${OUTPUT}`
+       echo "=> ${retval}" >& 5 2>&1
+       rm -f ${OUTPUT}
+       EMACS_cv_SYS_PACKAGEDIR=$retval
+
 fi
 
-trap '' 1 2 15
-cat > confcache <<\EOF
+PACKAGEDIR=${EMACS_cv_SYS_PACKAGEDIR}
+if test -z ""noecho""; then
+       echo "$as_me:$LINENO: result: $PACKAGEDIR" >&5
+echo "${ECHO_T}$PACKAGEDIR" >&6
+fi
+
+fi;
+    if test -z "$PACKAGEDIR"; then
+      echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6
+    else
+      echo "$as_me:$LINENO: result: $PACKAGEDIR" >&5
+echo "${ECHO_T}$PACKAGEDIR" >&6
+    fi
+  else
+    PACKAGEDIR=
+  fi
+
+
+# Check whether --with-addpath or --without-addpath was given.
+if test "${with_addpath+set}" = set; then
+  withval="$with_addpath"
+  if test "$withval" != yes -a -n "$withval"; then
+      echo "$as_me:$LINENO: checking where to find the additional elisp libraries" >&5
+echo $ECHO_N "checking where to find the additional elisp libraries... $ECHO_C" >&6
+      ADDITIONAL_LOAD_PATH=$withval
+      echo "$as_me:$LINENO: result: $ADDITIONAL_LOAD_PATH" >&5
+echo "${ECHO_T}$ADDITIONAL_LOAD_PATH" >&6
+    fi
+else
+  ADDITIONAL_LOAD_PATH=
+fi;
+
+                                                                      ac_config_files="$ac_config_files Makefile etc/Makefile lisp/Makefile texi/Makefile texi/gnusconfig.tex texi/ps/Makefile lisp/dgnuspath.el"
+cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
-# scripts and configure runs.  It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
 #
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already.  You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
 #
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
 # The following way of writing the cache mishandles newlines in values,
 # but we know of no workaround that is simple, portable, and efficient.
 # So, don't put newlines in cache variables' values.
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
-  case `(ac_space=' '; set) 2>&1` in
-  *ac_space=\ *)
-    # `set' does not quote correctly, so add quotes (double-quote substitution
-    # turns \\\\ into \\, and sed turns \\ into \).
-    sed -n \
-      -e "s/'/'\\\\''/g" \
-      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
-    ;;
-  *)
-    # `set' quotes correctly as required by POSIX, so do not add quotes.
-    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
-    ;;
-  esac >> confcache
-if cmp -s $cache_file confcache; then
-  :
-else
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+        "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
   if test -w $cache_file; then
-    echo "updating cache $cache_file"
-    cat confcache > $cache_file
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
   else
     echo "not updating unwritable cache $cache_file"
   fi
 fi
 rm -f confcache
 
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
 test "x$prefix" = xNONE && prefix=$ac_default_prefix
 # Let make expand exec_prefix.
 test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
 if test "x$srcdir" = x.; then
-  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+  ac_vpsub='/^[        ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[   ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[     ]*$//;
+}'
 fi
 
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
 # Transform confdefs.h into DEFS.
 # Protect against shell expansion while executing Makefile rules.
 # Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[    `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[   ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\),-D\1=\2,g
+t quote
+s,^[   ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[    `~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output.  A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+         sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
 
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
 # Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
 # Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
 
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
 do
-  case "\$ac_option" in
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
-    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
-    echo "$CONFIG_STATUS generated by autoconf version 2.12"
-    exit 0 ;;
-  -help | --help | --hel | --he | --h)
-    echo "\$ac_cs_usage"; exit 0 ;;
-  *) echo "\$ac_cs_usage"; exit 1 ;;
-  esac
+  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
 done
 
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
 
-trap 'rm -fr `echo "Makefile lisp/Makefile texi/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
 
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@SET_MAKE@%$SET_MAKE%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@EMACS@%$EMACS%g
-s%@lispdir@%$lispdir%g
-s%@MAKEINFO@%$MAKEINFO%g
 
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
-  if test $ac_beg -gt 1; then
-    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
   else
-    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
   fi
-  if test ! -s conftest.s$ac_file; then
-    ac_more_lines=false
-    rm -f conftest.s$ac_file
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
   else
-    if test -z "$ac_sed_cmds"; then
-      ac_sed_cmds="sed -f conftest.s$ac_file"
-    else
-      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
-    fi
-    ac_file=`expr $ac_file + 1`
-    ac_beg=$ac_end
-    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+    as_ln_s='ln -s'
   fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.57.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.57,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
 done
-if test -z "$ac_sed_cmds"; then
-  ac_sed_cmds=cat
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
 fi
-EOF
 
-cat >> $CONFIG_STATUS <<EOF
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
 
-CONFIG_FILES=\${CONFIG_FILES-"Makefile lisp/Makefile texi/Makefile"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case "$ac_file" in
-  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
-       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
-  *) ac_file_in="${ac_file}.in" ;;
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "etc/Makefile" ) CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;;
+  "lisp/Makefile" ) CONFIG_FILES="$CONFIG_FILES lisp/Makefile" ;;
+  "texi/Makefile" ) CONFIG_FILES="$CONFIG_FILES texi/Makefile" ;;
+  "texi/gnusconfig.tex" ) CONFIG_FILES="$CONFIG_FILES texi/gnusconfig.tex" ;;
+  "texi/ps/Makefile" ) CONFIG_FILES="$CONFIG_FILES texi/ps/Makefile" ;;
+  "lisp/dgnuspath.el" ) CONFIG_FILES="$CONFIG_FILES lisp/dgnuspath.el" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
   esac
+done
 
-  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
 
-  # Remove last slash and all that follows it.  Not all systems have dirname.
-  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
-  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
-    # The file is in a subdirectory.
-    test ! -d "$ac_dir" && mkdir "$ac_dir"
-    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
-    # A "../" for each directory in $ac_dir_suffix.
-    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
-  else
-    ac_dir_suffix= ac_dots=
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@GNUS_PRODUCT_NAME@,$GNUS_PRODUCT_NAME,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@EMACS@,$EMACS,;t t
+s,@XEMACS@,$XEMACS,;t t
+s,@lispdir@,$lispdir,;t t
+s,@etcdir@,$etcdir,;t t
+s,@info_dir@,$info_dir,;t t
+s,@HAVE_url@,$HAVE_url,;t t
+s,@URL@,$URL,;t t
+s,@HAVE_w3_forms@,$HAVE_w3_forms,;t t
+s,@W3@,$W3,;t t
+s,@FLAGS@,$FLAGS,;t t
+s,@LATEX@,$LATEX,;t t
+s,@WITH_FONTS_bembo@,$WITH_FONTS_bembo,;t t
+s,@WITHOUT_FONTS_bembo@,$WITHOUT_FONTS_bembo,;t t
+s,@WITH_FONTS_pfu@,$WITH_FONTS_pfu,;t t
+s,@WITHOUT_FONTS_pfu@,$WITHOUT_FONTS_pfu,;t t
+s,@WITH_FONTS_bcr@,$WITH_FONTS_bcr,;t t
+s,@WITHOUT_FONTS_bcr@,$WITHOUT_FONTS_bcr,;t t
+s,@USE_FONTS@,$USE_FONTS,;t t
+s,@PACKAGEDIR@,$PACKAGEDIR,;t t
+s,@ADDITIONAL_LOAD_PATH@,$ADDITIONAL_LOAD_PATH,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
   fi
+fi # test -n "$CONFIG_FILES"
 
-  case "$ac_given_srcdir" in
-  .)  srcdir=.
-      if test -z "$ac_dots"; then top_srcdir=.
-      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
-  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
-  *) # Relative path.
-    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
-    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
   esac
 
-  case "$ac_given_INSTALL" in
-  [/$]*) INSTALL="$ac_given_INSTALL" ;;
-  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
-  esac
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$as_dir" : 'X\(//\)[^/]' \| \
+         X"$as_dir" : 'X\(//\)$' \| \
+         X"$as_dir" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
 
-  echo creating "$ac_file"
-  rm -f "$ac_file"
-  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
-  case "$ac_file" in
-  *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
-  *) ac_comsub= ;;
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
   esac
 
-  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
-  sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
 
-EOF
-cat >> $CONFIG_STATUS <<EOF
+done
+_ACEOF
 
-EOF
-cat >> $CONFIG_STATUS <<\EOF
+cat >>$CONFIG_STATUS <<\_ACEOF
 
-exit 0
-EOF
+{ (exit 0); exit 0; }
+_ACEOF
 chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
 
index 675635b..92f7eae 100644 (file)
@@ -1,6 +1,17 @@
 AC_INIT(lisp/gnus.el)
+AC_DEFINE_GNUS_PRODUCT_NAME(t-gnus)
 AC_SET_MAKE
 AC_PROG_INSTALL
-AM_PATH_LISPDIR
-AC_PATH_PROG(MAKEINFO, makeinfo, no)
-AC_OUTPUT(Makefile lisp/Makefile texi/Makefile)
+AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo, no)
+AC_CHECK_EMACS
+AC_PATH_LISPDIR
+AC_PATH_ETCDIR
+AC_PATH_INFO_DIR
+AC_CHECK_URL
+AC_CHECK_W3
+AC_SET_BUILD_FLAGS
+GNUS_CHECK_FONTS
+AC_PATH_PACKAGEDIR
+AC_ADD_LOAD_PATH
+AC_OUTPUT(Makefile etc/Makefile lisp/Makefile texi/Makefile \
+ texi/gnusconfig.tex texi/ps/Makefile lisp/dgnuspath.el)
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
new file mode 100644 (file)
index 0000000..999d5d9
--- /dev/null
@@ -0,0 +1,240 @@
+2003-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * starttls.el: Sync with recent gnu.emacs.sources post.
+
+2003-10-24  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * nnir.el: Autoload `read-kbd-macro' at compile time.
+
+2003-09-30  Kai Grossjohann  <kai.grossjohann@gmx.net>
+       From Torsten Hilbrich <torsten.hilbrich@gmx.net>.
+
+       * nnir.el (nnir-imap-search-field, nnir-imap-search-arguments)
+       (nnir-imap-search-argument-history): New variables.
+       (nnir-engines, nnir-run-imap): Use them.
+       (nnir-read-parm): Support reading the new IMAP query parameters.
+
+2003-06-03  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * README: Explain purpose of each file (well, most files).
+
+2003-05-01  Vasily Korytov  <deskpot@despammed.com>
+
+       * gpg.el (gpg-passphrase-forget): Check that gpg-passphrase is
+       set. 
+
+2003-04-17  Steve Youngs  <youngs@xemacs.org>
+
+       * hashcash.el (hashcash-point-at-bol): Move the fbound test
+       outside of the defalias.
+       (hashcash-point-at-eol): Ditto.
+
+2003-03-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-idna.el: Update.
+
+2003-03-11  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * hashcash.el (hashcash-version, hashcash-insert-payment): patch
+       from Paul Foley
+
+2003-03-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-idna.el (gnus-idna-to-ascii-rhs-1): Narrow to
+       head (otherwise forwarded mail break havoc).
+
+2003-03-07  Teodor Zlatanov  <tzz@bwh.harvard.edu>
+
+       * hashcash.el: New version from Paul Foley with better variable
+       names, executable-find support, and no errors in GNU Emacs
+       (hashcash-version): return nil when invoked with a
+       nil token
+
+2003-02-21  Simon Josefsson  <jas@extundo.com>
+
+       * hashcash.el (hashcash-point-at-bol):
+       (hashcash-point-at-eol): Defalias.
+       (hashcash-generate-payment):
+       (mail-check-payment): Use it.
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * hashcash.el: New version from Paul Foley with new
+       mail-check-payment function.
+
+2002-06-22  Simon Josefsson  <jas@extundo.com>
+
+       * hashcash.el: New file.
+       (hashcash-default-payment, hashcash-payment-alist, hashcash):
+       Defcustom.
+       (hashcash-generate-payment): Update to recent hashcode command
+       line syntax.
+       (hashcash-insert-payment): Use X-Hashcode:.
+       (mail-add-payment): Also look at Newsgroups.
+       (top-level): Add provide and EOF comment.
+       (mail-add-payment): Autoload.
+       (hashcash-insert-payment): s/Hashcode/Hashcash/
+       (mail-add-payment): Doc fix.
+
+2002-05-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-mdrtn.el (gnus-moderated-groups): Removed (require 'gnus-load).
+
+2002-04-24  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * ucs-tables.el (featurep): Barf on XEmacs.
+
+2002-03-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * ucs-tables.el: Copy from Emacs 21.
+       
+2002-03-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * xml.el: Sync with Emacs 21.
+
+2002-01-25  Josh Huber  <huber@alum.wpi.edu>
+
+       * gpg.el (gpg-command-decrypt): Enable the status-fd command line
+       option to gpg when decrypting so `mml2015-mailcrypt-decrypt' can
+       parse and display the output.
+
+2002-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-mdrtn.el (gnus-moderation-cancel-article): Insert an extra
+       newline.
+
+2001-12-26  Florian Weimer  <fw@deneb.enyo.de>
+
+       * gpg.el (gpg-command-default-alist): Using gpg-2comp is no longer
+       the default.
+
+2001-12-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog: changed buffer-file-coding-system back to
+       coding. (oops)
+
+2001-12-17  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog: changed coding to buffer-file-coding-system
+
+2001-11-22  Simon Josefsson  <jas@extundo.com>
+
+       * sha1.el: Removed. (A FSF copyrighted sha1-el.el file is in
+       ../lisp/).
+
+2001-10-30 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * canlock.el, hex-util.el, sha1-el.el: Move to lisp.
+
+2001-10-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el: (canlock-base64-encode-function): Removed.
+       (canlock-mmencode-program): Removed.
+       (canlock-mmencode-args-for-encoding): Removed.
+       (canlock-openssl-program): Renamed from `canlock-ssleay-program'.
+       (canlock-openssl-args): Renamed from `canlock-ssleay-args'.
+       (canlock-load-hook): Removed.
+       (canlock-base64-encode-string-with-mmencode): Removed.
+       (canlock-sha1-with-openssl): Renamed from
+       `canlock-sha1-with-ssleay'.
+       (canlock-hex-string-to-int): Removed.
+       (canlock-fetch-fields): Don't use `mapcar'.
+       (canlock-fetch-id-for-key): Don't use Cancel header if there is no
+       cancel command.
+       (gnus-summary-canlock-verify): Removed.
+       (wl-summary-canlock-verify): Removed.
+       (canlock-mew-summary-display): Removed.
+       (mew-summary-canlock-verify): Removed.
+       (mh-summary-canlock-verify): Removed.
+       (vm-summary-canlock-verify): Removed.
+       (cmail-summary-canlock-verify): Removed.
+       (rmail-summary-canlock-verify): Removed.
+
+2001-10-25  Simon Josefsson  <jas@extundo.com>
+
+       * canlock.el (canlock-password, canlock-password-for-verify) 
+       (canlock-force-insert-header): Defcustom.
+
+2001-10-17  Simon Josefsson  <jas@extundo.com>
+
+       * canlock.el (sha1-binary): Autoload `sha1-binary'.
+       (canlock-sha1-function): Use it.
+       (canlock-sha1-function-for-verify): Ditto.
+
+       * sha1-el.el: New file.
+
+       * hex-util.el: Ditto.
+
+2001-08-24 16:09:14  Fabien Penso  <penso@linuxfr.org>
+
+       * gpg.el (gpg-command-sign-detached): Doc fix.
+
+2001-08-07  Andreas Jaeger  <aj@suse.de>
+
+       * gpg.el (gpg-passphrase-forget): Don't cache
+       gpg-passphrase-timer.
+       (gpg-passphrase-store): Check if gpg-passphrase-timer is
+       initialized already.
+       
+2001-07-30 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Andreas Fuchs <asf@void.at>
+
+       * gpg.el (gpg-command-verify): --status-fd 1
+       (gpg-unabbrev-trust-alist): New.
+
+2001-01-18  Colin Marquardt <colin.marquardt@usa.alcatel.com>
+
+       * gpg.el (gpg-make-temp-file): Error info.
+
+2001-01-13 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (gpg-build-arg-list): Use copy-sequence.
+
+2000-12-19 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (defalias): Use eval-and-compile.
+       (gpg-command-all-arglist): Suggest by Jeff Senn <senn@maya.com>.
+
+2000-12-15 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (gpg-command-alist): Alist may not be defined.
+
+2000-12-14 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (gpg-make-temp-file): Don't check file-modes of M$Windows.
+
+2000-12-14 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (gpg-passphrase-store): Don't activate timer if it is live.
+
+2000-11-30 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el: (gpg-make-temp-file): Use expand-file-name.
+       (gpg-point-at-eol): New function.
+       (gpg-call-process): Use it.
+       (gpg-key-list-keys-parse-line): Ditto.
+       (gpg-with-passphrase-env): edebug-form-spec.
+       (gpg-with-temp-files): Ditto.
+       (gpg-show-result): Ditto.
+
+2000-11-08  Bj\e,Av\e(Brn Torkelsson  <torkel@hpc2n.umu.se>
+
+       * gpg.el: In Xemacs it is called point-at-eol, not
+       line-end-position
+
+       * gpg.el (gpg-key-lessp): use string-lessp instead of
+       compare-strings (not available on XEmacs)
+       
+2000-11-16  Simon Josefsson  <sj@extundo.com>
+
+       * gpg.el (gpg-command-verify-cleartext): New variable.
+       (gpg-verify-cleartext): New function.
+       
+2000-10-31 17:32:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el (gpg-verify): The last argument of apply is a list.
+       (gpg-encrypt): Add passphrase as a parameter.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/contrib/README b/contrib/README
new file mode 100644 (file)
index 0000000..7c3c3fc
--- /dev/null
@@ -0,0 +1,59 @@
+The files in this directory are not (yet) part of the Gnus
+distribution proper.  They may later become part of the distribution,
+or they may disappear altogether.
+
+Please note that it is not good to just add this directory to
+load-path: a number of files in this directory will become part of
+more recent Emacs versions, so that you might be running obsolete
+libraries with all kinds of ill effects.
+
+The suggested method for installation is to copy those files that you
+need to a directory which is in load-path.
+
+Here is an overview of the files:
+
+base64.el
+
+        As of Emacs 21, base64 encoding and decoding is available
+        natively.  So this file appears to be needed for Emacs 20
+        only.
+
+gpg-ring.el
+gpg.el
+
+hashcash.el
+
+md5.el
+
+       MD5 encoding is part of Emacs as of Emacs 21.2.  Hence, this
+       file is not needed for those Emacs versions.
+
+one-line-cookie.diff
+
+ssl.el
+
+ucs-tables.el
+
+       This file provides improved Unicode functionality.  It defines
+       functions unify-8859-on-encoding-mode and
+       unify-8859-on-decoding-mode which unify the Latin-N charsets.
+       Without unify-8859-on-encoding-mode, composing a Latin-9 reply
+       to a Latin-1 posting, say, will produce a multipart posting (a
+       Latin-1 part and a Latin-9 part), or perhaps UTF-8.  With
+       unify-8859-on-encoding-mode, the outgoing posting can be all
+       Latin-1 or all Latin-9 in most cases.
+
+       It is harmless to turn on unify-8859-on-encoding-mode, but
+       unify-8859-on-decoding-mode may unexpectedly change files in
+       certain situations.  (If the file contains different Latin-N
+       charsets which should not be unified.)
+
+       This is part of Emacs 21.3 and later, which also turns on
+       unify-8859-on-encoding-mode by default.
+
+vcard.el
+
+xml.el
+
+       This is used for parsing RSS feeds.  Part of Emacs 21.3 and
+       later.
diff --git a/contrib/base64.el b/contrib/base64.el
new file mode 100644 (file)
index 0000000..572a5d3
--- /dev/null
@@ -0,0 +1,278 @@
+;;; base64.el,v --- Base64 encoding functions
+;; Author: Kyle E. Jones
+;; Created: 1997/03/12 14:37:09
+;; Version: 1.6
+;; Keywords: extensions
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Copyright (C) 1997 Kyle E. Jones
+;;;
+;;; This file is not part of GNU Emacs, but the same permissions apply.
+;;;
+;;; GNU Emacs is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Emacs is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;;; Boston, MA 02111-1307, USA.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile (require 'cl))
+
+;; For non-MULE
+(if (not (fboundp 'char-int))
+    (defalias 'char-int 'identity))
+
+(defvar base64-alphabet
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
+
+(defvar base64-decoder-program nil
+  "*Non-nil value should be a string that names a MIME base64 decoder.
+The program should expect to read base64 data on its standard
+input and write the converted data to its standard output.")
+
+(defvar base64-decoder-switches nil
+  "*List of command line flags passed to the command named by
+base64-decoder-program.")
+
+(defvar base64-encoder-program nil
+  "*Non-nil value should be a string that names a MIME base64 encoder.
+The program should expect arbitrary data on its standard
+input and write base64 data to its standard output.")
+
+(defvar base64-encoder-switches nil
+  "*List of command line flags passed to the command named by
+base64-encoder-program.")
+
+(defconst base64-alphabet-decoding-alist
+  '(
+    ( ?A . 00) ( ?B . 01) ( ?C . 02) ( ?D . 03) ( ?E . 04) ( ?F . 05)
+    ( ?G . 06) ( ?H . 07) ( ?I . 08) ( ?J . 09) ( ?K . 10) ( ?L . 11)
+    ( ?M . 12) ( ?N . 13) ( ?O . 14) ( ?P . 15) ( ?Q . 16) ( ?R . 17)
+    ( ?S . 18) ( ?T . 19) ( ?U . 20) ( ?V . 21) ( ?W . 22) ( ?X . 23)
+    ( ?Y . 24) ( ?Z . 25) ( ?a . 26) ( ?b . 27) ( ?c . 28) ( ?d . 29)
+    ( ?e . 30) ( ?f . 31) ( ?g . 32) ( ?h . 33) ( ?i . 34) ( ?j . 35)
+    ( ?k . 36) ( ?l . 37) ( ?m . 38) ( ?n . 39) ( ?o . 40) ( ?p . 41)
+    ( ?q . 42) ( ?r . 43) ( ?s . 44) ( ?t . 45) ( ?u . 46) ( ?v . 47)
+    ( ?w . 48) ( ?x . 49) ( ?y . 50) ( ?z . 51) ( ?0 . 52) ( ?1 . 53)
+    ( ?2 . 54) ( ?3 . 55) ( ?4 . 56) ( ?5 . 57) ( ?6 . 58) ( ?7 . 59)
+    ( ?8 . 60) ( ?9 . 61) ( ?+ . 62) ( ?/ . 63)
+    ))
+
+(defvar base64-alphabet-decoding-vector
+  (let ((v (make-vector 123 nil))
+       (p base64-alphabet-decoding-alist))
+    (while p
+      (aset v (car (car p)) (cdr (car p)))
+      (setq p (cdr p)))
+    v))
+
+(defvar base64-binary-coding-system 'binary)
+
+(defun base64-run-command-on-region (start end output-buffer command
+                                          &rest arg-list)
+  (let ((tempfile nil) status errstring default-process-coding-system 
+       (coding-system-for-write base64-binary-coding-system)
+       (coding-system-for-read base64-binary-coding-system))
+    (unwind-protect
+       (progn
+         (setq tempfile (make-temp-name "base64"))
+         (setq status
+               (apply 'call-process-region
+                      start end command nil
+                      (list output-buffer tempfile)
+                      nil arg-list))
+         (cond ((equal status 0) t)
+               ((zerop (save-excursion
+                         (set-buffer (find-file-noselect tempfile))
+                         (buffer-size)))
+                t)
+               (t (save-excursion
+                    (set-buffer (find-file-noselect tempfile))
+                    (setq errstring (buffer-string))
+                    (kill-buffer nil)
+                    (cons status errstring)))))
+      (ignore-errors
+       (delete-file tempfile)))))
+
+(if (featurep 'xemacs)
+    (defalias 'base64-insert-char 'insert-char)
+  (defun base64-insert-char (char &optional count ignored buffer)
+    (if (or (null buffer) (eq buffer (current-buffer)))
+       (insert-char char count)
+      (with-current-buffer buffer
+       (insert-char char count))))
+  (setq base64-binary-coding-system 'no-conversion))
+
+(defun base64-decode-region (start end)
+  (interactive "r")
+  ;;(message "Decoding base64...")
+  (let ((work-buffer nil)
+       (done nil)
+       (counter 0)
+       (bits 0)
+       (lim 0) inputpos
+       (non-data-chars (concat "^=" base64-alphabet)))
+    (unwind-protect
+       (save-excursion
+         (setq work-buffer (generate-new-buffer " *base64-work*"))
+         (buffer-disable-undo work-buffer)
+         (if base64-decoder-program
+             (let* ((binary-process-output t) ; any text already has CRLFs
+                    (status (apply 'base64-run-command-on-region
+                                   start end work-buffer
+                                   base64-decoder-program
+                                   base64-decoder-switches)))
+               (if (not (eq status t))
+                   (error "%s" (cdr status))))
+           (goto-char start)
+           (skip-chars-forward non-data-chars end)
+           (while (not done)
+             (setq inputpos (point))
+             (cond
+              ((> (skip-chars-forward base64-alphabet end) 0)
+               (setq lim (point))
+               (while (< inputpos lim)
+                 (setq bits (+ bits
+                               (aref base64-alphabet-decoding-vector
+                                     (char-int (char-after inputpos)))))
+                 (setq counter (1+ counter)
+                       inputpos (1+ inputpos))
+                 (cond ((= counter 4)
+                        (base64-insert-char (lsh bits -16) 1 nil work-buffer)
+                        (base64-insert-char (logand (lsh bits -8) 255) 1 nil
+                                            work-buffer)
+                        (base64-insert-char (logand bits 255) 1 nil
+                                            work-buffer)
+                        (setq bits 0 counter 0))
+                       (t (setq bits (lsh bits 6)))))))
+             (cond
+              ((or (= (point) end)
+                   (eq (char-after (point)) ?=))
+               (if (and (= (point) end) (> counter 1))
+                   (message 
+                    "at least %d bits missing at end of base64 encoding"
+                    (* (- 4 counter) 6)))
+               (setq done t)
+               (cond ((= counter 1)
+                      (error "at least 2 bits missing at end of base64 encoding"))
+                     ((= counter 2)
+                      (base64-insert-char (lsh bits -10) 1 nil work-buffer))
+                     ((= counter 3)
+                      (base64-insert-char (lsh bits -16) 1 nil work-buffer)
+                      (base64-insert-char (logand (lsh bits -8) 255)
+                                          1 nil work-buffer))
+                     ((= counter 0) t)))
+              (t (skip-chars-forward non-data-chars end)))))
+         (or (markerp end) (setq end (set-marker (make-marker) end)))
+         (goto-char start)
+         (insert-buffer-substring work-buffer)
+         (delete-region (point) end))
+      (and work-buffer (kill-buffer work-buffer))))
+  ;;(message "Decoding base64... done")
+  )
+
+(defun base64-encode-region (start end &optional no-line-break)
+  (interactive "r")
+  (message "Encoding base64...")
+  (let ((work-buffer nil)
+       (counter 0)
+       (cols 0)
+       (bits 0)
+       (alphabet base64-alphabet)
+       inputpos)
+    (unwind-protect
+       (save-excursion
+         (setq work-buffer (generate-new-buffer " *base64-work*"))
+         (buffer-disable-undo work-buffer)
+         (if base64-encoder-program
+             (let ((status (apply 'base64-run-command-on-region
+                                  start end work-buffer
+                                  base64-encoder-program
+                                  base64-encoder-switches)))
+               (if (not (eq status t))
+                   (error "%s" (cdr status))))
+           (setq inputpos start)
+           (while (< inputpos end)
+             (setq bits (+ bits (char-int (char-after inputpos))))
+             (setq counter (1+ counter))
+             (cond ((= counter 3)
+                    (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil
+                                        work-buffer)
+                    (base64-insert-char
+                     (aref alphabet (logand (lsh bits -12) 63))
+                     1 nil work-buffer)
+                    (base64-insert-char
+                     (aref alphabet (logand (lsh bits -6) 63))
+                     1 nil work-buffer)
+                    (base64-insert-char
+                     (aref alphabet (logand bits 63))
+                     1 nil work-buffer)
+                    (setq cols (+ cols 4))
+                    (cond ((and (= cols 72)
+                                (not no-line-break))
+                           (base64-insert-char ?\n 1 nil work-buffer)
+                           (setq cols 0)))
+                    (setq bits 0 counter 0))
+                   (t (setq bits (lsh bits 8))))
+             (setq inputpos (1+ inputpos)))
+           ;; write out any remaining bits with appropriate padding
+           (if (= counter 0)
+               nil
+             (setq bits (lsh bits (- 16 (* 8 counter))))
+             (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil
+                                 work-buffer)
+             (base64-insert-char (aref alphabet (logand (lsh bits -12) 63))
+                                 1 nil work-buffer)
+             (if (= counter 1)
+                 (base64-insert-char ?= 2 nil work-buffer)
+               (base64-insert-char (aref alphabet (logand (lsh bits -6) 63))
+                                   1 nil work-buffer)
+               (base64-insert-char ?= 1 nil work-buffer)))
+           (if (and (> cols 0)
+                    (not no-line-break))
+               (base64-insert-char ?\n 1 nil work-buffer)))
+         (or (markerp end) (setq end (set-marker (make-marker) end)))
+         (goto-char start)
+         (insert-buffer-substring work-buffer)
+         (delete-region (point) end))
+      (and work-buffer (kill-buffer work-buffer))))
+  (message "Encoding base64... done"))
+
+(defun base64-encode (string &optional no-line-break)
+  (save-excursion
+    (set-buffer (get-buffer-create " *base64-encode*"))
+    (erase-buffer)
+    (insert string)
+    (base64-encode-region (point-min) (point-max) no-line-break)
+    (skip-chars-backward " \t\r\n")
+    (delete-region (point-max) (point))
+    (prog1
+       (buffer-string)
+      (kill-buffer (current-buffer)))))
+
+(defun base64-decode (string)
+  (save-excursion
+    (set-buffer (get-buffer-create " *base64-decode*"))
+    (erase-buffer)
+    (insert string)
+    (base64-decode-region (point-min) (point-max))
+    (goto-char (point-max))
+    (skip-chars-backward " \t\r\n")
+    (delete-region (point-max) (point))
+    (prog1
+       (buffer-string)
+      (kill-buffer (current-buffer)))))
+
+(defalias 'base64-decode-string 'base64-decode)
+(defalias 'base64-encode-string 'base64-encode)
+
+(provide 'base64)
diff --git a/contrib/cus-dep.el b/contrib/cus-dep.el
new file mode 100644 (file)
index 0000000..8b689bf
--- /dev/null
@@ -0,0 +1,171 @@
+;;; cus-dep.el --- Find customization dependencies.
+;;
+;; Copyright (C) 1997 Free Software Foundation, Inc.
+;;
+;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
+;; Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'cl)
+(require 'widget)
+(require 'cus-face)
+(require 'autoload)
+
+(defun custom-make-dependencies ()
+  "Batch function to extract custom dependencies from .el files.
+Usage: emacs -batch -l ./cus-dep.el -f custom-make-dependencies DIRS"
+  (let ((enable-local-eval nil)
+       (all-subdirs command-line-args-left)
+       (start-directory default-directory))
+    (get-buffer-create " cus-dep temp")
+    (set-buffer " cus-dep temp")
+    (while all-subdirs
+      (message "Directory %s" (car all-subdirs))
+      (let ((files (directory-files (car all-subdirs) nil "\\`[^=].*\\.el\\'"))
+           (default-directory default-directory)
+           file
+           is-autoloaded)
+       (cd (car all-subdirs))
+       (while files
+         (setq file (car files)
+               files (cdr files))
+         (when (file-exists-p file)
+           (erase-buffer)
+           (insert-file-contents file)
+           (goto-char (point-min))
+           (string-match "\\`\\(.*\\)\\.el\\'" file)
+           (let ((name (file-name-nondirectory (match-string 1 file))))
+             (condition-case nil
+                 (while (re-search-forward "^(defcustom\\|^(defface\\|^(defgroup"
+                                           nil t)
+                   (setq is-autoloaded nil)
+                   (beginning-of-line)
+                   (save-excursion
+                     (forward-line -1)
+                     (if (looking-at generate-autoload-cookie)
+                         (setq is-autoloaded t)))
+                   (let ((expr (read (current-buffer))))
+                     (condition-case nil
+                         (progn
+                           (eval expr)
+                           (put (nth 1 expr) 'custom-autoloaded is-autoloaded)
+                           (put (nth 1 expr) 'custom-where name))
+                       (error nil))))
+               (error nil)))))
+       (setq all-subdirs (cdr all-subdirs)))))
+  (message "Generating cus-load.el...")
+  (find-file "cus-load.el")
+  (erase-buffer)
+  (insert "\
+;;; cus-load.el --- automatically extracted custom dependencies
+;;
+;;; Code:
+
+")
+  (mapatoms (lambda (symbol)
+             (let ((members (get symbol 'custom-group))
+                   item where found)
+               (when members
+                 (while members
+                   (setq item (car (car members))
+                         members (cdr members)
+                         where (get item 'custom-where))
+                   (unless (or (null where)
+                               (member where found))
+                     (if found
+                         (insert " ")
+                       (insert "(put '" (symbol-name symbol) 
+                               " 'custom-loads '("))
+                     (prin1 where (current-buffer))
+                     (push where found)))
+                 (when found
+                   (insert "))\n"))))))
+  (insert "\
+;;; These are for handling :version.  We need to have a minimum of
+;;; information so `custom-changed-variables' could do its job.  
+;;; For both groups and variables we have to set `custom-version'.
+;;; For variables we also set the `standard-value' and for groups
+;;; `group-documentation' (which is shown in the customize buffer), so
+;;; we don't have to load the file containing the group.
+
+;;; `custom-versions-load-alist' is an alist that has as car a version
+;;; number and as elts the files that have variables that contain that
+;;; version. These files should be loaded before showing the
+;;; customization buffer that `customize-changed-options' generates.
+
+
+;;; This macro is used so we don't modify the information about
+;;; variables and groups if it's already set. (We don't know when
+;;; cus-load.el is going to be loaded and at that time some of the
+;;; files might be loaded and some others might not).
+(defmacro custom-put-if-not (symbol propname value)
+  `(unless (get ,symbol ,propname)
+     (put ,symbol ,propname ,value)))
+
+")
+  (let ((version-alist nil))
+    (mapatoms (lambda (symbol)
+               (let ((version (get symbol 'custom-version))
+                     where)
+                 (when version 
+                   (setq where (get symbol 'custom-where))
+                   (when (and where 
+                              ;; Don't bother to do anything if it's
+                              ;; autoloaded because we will have all
+                              ;; this info when emacs is running
+                              ;; anyway.
+                              (not (get symbol 'custom-autoloaded)))
+                     (insert "(custom-put-if-not '" (symbol-name symbol) 
+                             " 'custom-version ")
+                     (prin1 version (current-buffer))
+                     (insert ")\n")
+                     (insert "(custom-put-if-not '" (symbol-name symbol))
+                     (if (get symbol 'standard-value)
+                         ;; This means it's a variable
+                         (progn
+                           (insert " 'standard-value t)\n")
+                           (if (assoc version version-alist)
+                               (unless 
+                                   (member where 
+                                           (cdr (assoc version version-alist)))
+                                 (push where (cdr (assoc version version-alist))))
+                             (push (cons version (list where)) version-alist)))
+                       ;; This is a group
+                       (insert " 'group-documentation ")
+                       (prin1 (get symbol 'group-documentation) (current-buffer))
+                       (insert ")\n")))))))
+
+    (insert "\n(defvar custom-versions-load-alist "
+           (if version-alist "'" ""))
+    (prin1 version-alist (current-buffer))
+    (insert "\n \"For internal use by custom.\")\n"))
+    
+  (insert "\
+
+\(provide 'cus-load)
+
+;;; cus-load.el ends here\n")
+  (let ((kept-new-versions 10000000))
+    (save-buffer))
+  (message "Generating cus-load.el...done")
+  (kill-emacs))
+
+;;; cus-dep.el ends here
diff --git a/contrib/gnus-idna.el b/contrib/gnus-idna.el
new file mode 100644 (file)
index 0000000..15c47b6
--- /dev/null
@@ -0,0 +1,154 @@
+;;; gnus-idna.el --- Internationalized domain names support for Gnus.
+
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson
+;; Keywords: news, mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package implement crude support for internationalized domain
+;; names in Gnus.
+
+;; Theory of Operation:
+
+;; RFC 2822 RHS's inside the From:, To:, and CC: headers are encoded
+;; using IDNA ToASCII() when you send mail using Message.  The hook
+;; used is message-send-hook.
+;;
+;; For incoming articles, when QP in headers are decoded (i.e., when
+;; gnus-article-decode-hook is invoked), it searches for "xn--"
+;; prefixes and decode them if they are found inside (heuristically
+;; determined) RHS in From:, To: and Cc:, using IDNA ToUnicode().
+
+;; Usage:
+
+;; You need to install GNU Libidn (0.1.11 or later) and make sure the
+;; idna.el installed by it is found by emacs.
+
+;; If you use an older Gnus, you may need to put the following in your
+;; init scripts too, but keep in mind that most older Gnuses either
+;; doesn't have these hooks or are buggy in other regards so it
+;; doesn't work anyway.  (The window of Gnus versions that this works
+;; on is a few weeks during the Oort CVS in winter 2003.)  Update to a
+;; recent Gnus instead, then you don't have to do anything.
+
+;; (add-hook 'message-send-hook 'message-idna-to-ascii-rhs)
+;; (add-hook 'gnus-article-decode-hook 'gnus-idna-to-unicode-rhs 'append)
+
+;; Revision history:
+
+;; 2003-02-26 Initial release
+;;
+;; 2003-03-19 Cleanup. Fixes a bug that may corrupt outgoing mail if
+;;            it contains From:, To: or Cc: headers in the body.
+
+;;; Code:
+
+(require 'gnus)
+(require 'gnus-util)
+(require 'rfc822)
+(autoload 'idna-to-ascii "idna")
+(autoload 'idna-to-unicode "idna")
+
+(defcustom message-use-idna 'ask
+  "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+  :type '(choice (const :tag "Ask" ask)
+                (const :tag "Never" nil)
+                (const :tag "Always" t)))
+
+(defun message-idna-inside-rhs-p ()
+  "Return t iff point is inside a RHS (heuristically).
+Only works properly if header contains mailbox-list or address-list.
+I.e., calling it on a Subject: header is useless."
+  (if (re-search-backward
+       "[\\\n\r\t ]" (save-excursion (search-backward "@" nil t)) t)
+      ;; whitespace between @ and point
+      nil
+    (let ((dquote 1) (paren 1))
+      (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
+       (incf dquote))
+      (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
+       (incf paren))
+      (and (= (% dquote 2) 1) (= (% paren 2) 1)))))
+
+(defun message-idna-to-ascii-rhs-1 (header)
+  "Interactively potentially IDNA encode domain names in HEADER."
+  (let (rhs ace start end startpos endpos)
+    (goto-char (point-min))
+    (setq start (re-search-forward (concat "^" header) nil t)
+         end (or (save-excursion (re-search-forward "^[ \t]" nil t))
+                 (point-max)))
+    (when (and start end)
+      (while (re-search-forward "@\\([^ \t\r\n>]+\\)" end t)
+       (setq rhs (match-string-no-properties 1)
+             startpos (match-beginning 1)
+             endpos (match-end 1))
+       (when (save-match-data
+               (and (message-idna-inside-rhs-p)
+                    (setq ace (idna-to-ascii rhs))
+                    (not (string= rhs ace))
+                    (if (eq message-use-idna 'ask)
+                        (unwind-protect
+                            (progn
+                              (replace-highlight startpos endpos)
+                              (y-or-n-p
+                               (format "Replace with `%s'? " ace)))
+                          (message "")
+                          (replace-dehighlight))
+                      message-use-idna)))
+         (replace-match (concat "@" ace)))))))
+
+;;;###autoload
+(defun message-idna-to-ascii-rhs ()
+  "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
+See `message-idna-encode'."
+  (interactive)
+  (when (condition-case nil (require 'idna) (file-error))
+    (save-excursion
+      (save-restriction
+       (message-narrow-to-head)
+       (message-idna-to-ascii-rhs-1 "From")
+       (message-idna-to-ascii-rhs-1 "To")
+       (message-idna-to-ascii-rhs-1 "Cc")))))
+
+;;;###autoload
+(defun gnus-idna-to-unicode-rhs ()
+  "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer."
+  (when (condition-case nil (require 'idna) (file-error))
+    (let ((inhibit-point-motion-hooks t)
+         buffer-read-only)
+      (article-narrow-to-head)
+      (goto-char (point-min))
+      (while (re-search-forward "\\(xn--.*\\)[ \t\n\r,>]" nil t)
+       (let (ace unicode)
+         (when (save-match-data
+                 (and (setq ace (match-string 1))
+                      (save-excursion (and (re-search-backward "^[^ \t]" nil t)
+                                           (looking-at "From\\|To\\|Cc")))
+                      (save-excursion (backward-char)
+                                      (message-idna-inside-rhs-p))
+                      (setq unicode (idna-to-unicode ace))))
+           (unless (string= ace unicode)
+             (replace-match unicode nil nil nil 1))))))))
+
+(provide 'gnus-idna)
+
+;; gnus-idna.el ends here
diff --git a/contrib/gpg-ring.el b/contrib/gpg-ring.el
new file mode 100644 (file)
index 0000000..dd223bf
--- /dev/null
@@ -0,0 +1,481 @@
+;;; gpg-ring.el --- Major mode for editing GnuPG key rings.
+
+;; Copyright (C) 2000 RUS-CERT, University Of Stuttgart
+
+;; Author: Florian Weimer <Florian.Weimer@RUS.Uni-Stuttgart.DE>
+;; Maintainer: Florian Weimer <Florian.Weimer@RUS.Uni-Stuttgart.DE>
+;; Keywords: crypto
+;; Created: 2000-04-28
+
+;; This file is NOT (yet?) part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+
+\f
+;;; Code:
+
+(require 'gpg)
+(eval-when-compile (require 'cl))
+
+;;;; Customization:
+
+;;; Customization: Groups:
+
+(defgroup gpg-ring nil
+  "GNU Privacy Guard user interface."
+  :tag "GnuPG user interface"
+  :group 'gpg)
+
+;;; Customization: Variables:
+
+(defface gpg-ring-key-invalid-face 
+  '((((class color))
+     (:foreground "yellow" :background "red"))
+    (t (:bold t :italic t :underline t)))
+  "Face for strings indicating key invalidity."
+  :group 'gpg-ring)
+
+(defface gpg-ring-uncertain-validity-face
+  '((((class color)) (:foreground "red"))
+    (t (:bold t)))
+  "Face for strings indicating uncertain validity."
+  :group 'gpg-ring)
+
+(defface gpg-ring-full-validity-face
+  '((((class color)) (:foreground "ForestGreen" :bold t))
+    (t (:bold t)))
+  "Face for strings indicating key invalidity."
+  :group 'gpg-ring)
+
+(defvar gpg-ring-mode-hook nil
+  "Normal hook run when entering GnuPG ring mode.")
+
+;;; Constants
+
+(defconst gpg-ring-algo-alist
+  '((rsa . "RSA")
+    (rsa-encrypt-only . "RSA-E")
+    (rsa-sign-only . "RSA-S")
+    (elgamal-encrypt-only . "ELG-E")
+    (dsa . "DSA")
+    (elgamal . "ELG-E"))
+  "Alist mapping algorithm IDs to algorithm abbreviations.")
+    
+(defconst gpg-ring-trust-alist
+  '((not-known       "???" gpg-ring-uncertain-validity-face)
+    (disabled        "DIS" gpg-ring-key-invalid-face)
+    (revoked         "REV" gpg-ring-key-invalid-face)
+    (expired         "EXP" gpg-ring-key-invalid-face)
+    (trust-undefined "QES" gpg-ring-uncertain-validity-face)
+    (trust-none      "NON" gpg-ring-uncertain-validity-face)
+    (trust-marginal  "MAR")
+    (trust-full      "FUL" gpg-ring-full-validity-face)
+    (trust-ultimate  "ULT" gpg-ring-full-validity-face))
+  "Alist mapping trust IDs to trust abbrevs and faces.")
+
+(defvar gpg-ring-mode-map
+  (let ((map (make-keymap)))
+    (suppress-keymap map t)
+    map)
+  "Keymap for `gpg-ring-mode'.")
+
+(define-key gpg-ring-mode-map "0" 'delete-window)
+(define-key gpg-ring-mode-map "1" 'delete-other-windows)
+(define-key gpg-ring-mode-map "M" 'gpg-ring-mark-process-all)
+(define-key gpg-ring-mode-map "U" 'gpg-ring-unmark-all)
+(define-key gpg-ring-mode-map "a" 'gpg-ring-toggle-show-unusable)
+(define-key gpg-ring-mode-map "d" 'gpg-ring-mark-delete)
+(define-key gpg-ring-mode-map "f" 'gpg-ring-update-key)
+(define-key gpg-ring-mode-map "g" 'gpg-ring-update)
+(define-key gpg-ring-mode-map "i" 'gpg-ring-show-key)
+(define-key gpg-ring-mode-map "l" 'gpg-ring-toggle-show-all-ids)
+(define-key gpg-ring-mode-map "m" 'gpg-ring-mark-process)
+(define-key gpg-ring-mode-map "n" 'gpg-ring-next-record)
+(define-key gpg-ring-mode-map "p" 'gpg-ring-previous-record)
+(define-key gpg-ring-mode-map "q" 'gpg-ring-quit)
+(define-key gpg-ring-mode-map "u" 'gpg-ring-unmark)
+(define-key gpg-ring-mode-map "x" 'gpg-ring-extract-keys)
+(define-key gpg-ring-mode-map "X" 'gpg-ring-extract-keys-to-kill)
+
+(define-key gpg-ring-mode-map "\C-c\C-c" 'gpg-ring-action)
+
+;;; Internal functions:
+
+(defvar gpg-ring-key-list
+  nil
+  "List of keys in the key list buffer.")
+(make-variable-buffer-local 'gpg-ring-key-list)
+
+(defvar gpg-ring-update-funcs
+  nil
+  "List of functions called to obtain the key list.")
+(make-variable-buffer-local 'gpg-ring-update-funcs)
+
+(defvar gpg-ring-show-unusable
+  nil
+  "If t, show expired, revoked and disabled keys, too.")
+(make-variable-buffer-local 'gpg-ring-show-unusable)
+
+(defvar gpg-ring-show-all-ids
+  nil
+  "If t, show all user IDs.  If nil, show only the primary user ID.")
+(make-variable-buffer-local 'gpg-ring-show-all-ids)
+
+(defvar gpg-ring-marks-alist
+  nil
+  "Alist of (UNIQUE-ID MARK KEY).
+UNIQUE-ID is a unique key ID from GnuPG.  MARK is either `?D'
+(marked for deletion), or `?*' (marked for processing).")
+(make-variable-buffer-local 'gpg-ring-marks-alist)
+
+(defvar gpg-ring-action
+  nil
+  "Function to call when `gpg-ring-action' is invoked.
+A list of the keys which are marked for processing is passed as argument.")
+(make-variable-buffer-local 'gpg-ring-action)
+
+(defun gpg-ring-mode ()
+  "Mode for editing GnuPG key rings.
+\\{gpg-ring-mode-map}
+Turning on gpg-ring-mode runs `gpg-ring-mode-hook'."
+  (interactive)
+  (kill-all-local-variables)
+  (buffer-disable-undo)
+  (setq truncate-lines t)
+  (setq buffer-read-only t)
+  (use-local-map gpg-ring-mode-map)
+  (setq mode-name "Key Ring")
+  (setq major-mode 'gpg-ring-mode)
+  (run-hooks 'gpg-ring-mode-hook))
+
+
+(defmacro gpg-ring-record-start (&optional pos)
+  "Return buffer position of start of record containing POS."
+  `(get-text-property (or ,pos (point)) 'gpg-record-start))
+                                        
+(defun gpg-ring-current-key (&optional pos)
+  "Return GnuPG key at POS, or at point if ommitted."
+  (or (get-text-property (or pos (point)) 'gpg-key)
+      (error "No record on current line")))
+
+(defun gpg-ring-goto-record (pos)
+  "Go to record starting at POS.
+Position point after the marks at the beginning of a record."
+  (goto-char pos)
+  (forward-char 2))
+
+(defun gpg-ring-next-record ()
+  "Advances point to the start of the next record."
+  (interactive)
+  (let ((start (next-single-property-change 
+               (point) 'gpg-record-start nil (point-max))))
+    ;; Don't advance to the last line of the buffer.
+    (when (/= start (point-max))
+       (gpg-ring-goto-record start))))
+
+(defun gpg-ring-previous-record ()
+  "Advances point to the start of the previous record."
+  (interactive)
+  ;; The last line of the buffer doesn't contain a record.
+  (let ((start (gpg-ring-record-start)))
+    (if start
+       (gpg-ring-goto-record (previous-single-property-change 
+                                   start 'gpg-record-start nil (point-min)))
+      (gpg-ring-goto-record
+       (gpg-ring-record-start (1- (point-max)))))))
+      
+(defun gpg-ring-set-mark (&optional pos mark)
+  "Set MARK on record at POS, or at point if POS is omitted.
+If MARK is omitted, clear it."
+  (save-excursion
+    (let* ((start (gpg-ring-record-start pos))
+          (key (gpg-ring-current-key start))
+          (id (gpg-key-unique-id key))
+          (entry (assoc id gpg-ring-marks-alist))
+          buffer-read-only)
+      (goto-char start)
+      ;; Replace the mark character.
+      (subst-char-in-region (point) (1+ (point)) (char-after) 
+                           (or mark ? ))
+      ;; Store the mark in alist.
+      (if entry
+         (setcdr entry (if mark (list mark key)))
+       (when mark
+         (push (list id mark key) gpg-ring-marks-alist))))))
+
+(defun gpg-ring-marked-keys (&optional only-marked mark)
+  "Return list of key specs which have MARK.
+If no marks are present and ONLY-MARKED is not nil, return singleton
+list with key of the current record.  If MARK is omitted, `?*' is
+used."
+  (let ((the-marker (or mark ?*))
+       (marks gpg-ring-marks-alist)
+       key-list)
+    (while marks
+      (let ((mark (pop marks)))
+       ;; If this entry has got the right mark ...
+       (when (equal (nth 1 mark) the-marker)
+         ;; ... rember the key spec.
+         (push (nth 2 mark) key-list))))
+    (or key-list (if (not only-marked) (list (gpg-ring-current-key))))))
+
+(defun gpg-ring-mark-process ()
+  "Mark record at point for processing."
+  (interactive)
+  (gpg-ring-set-mark nil ?*)
+  (gpg-ring-next-record))
+
+(defun gpg-ring-mark-delete ()
+  "Mark record at point for processing."
+  (interactive)
+  (gpg-ring-set-mark nil ?D)
+  (gpg-ring-next-record))
+
+(defun gpg-ring-unmark ()
+  "Mark record at point for processing."
+  (interactive)
+  (gpg-ring-set-mark)
+  (gpg-ring-next-record))
+
+(defun gpg-ring-mark-process-all ()
+  "Put process mark on all records."
+  (interactive)
+  (setq gpg-ring-marks-alist 
+       (mapcar (lambda (key)
+                 (list (gpg-key-unique-id key) ?* key))
+               gpg-ring-key-list))
+  (gpg-ring-regenerate))
+
+(defun gpg-ring-unmark-all ()
+  "Remove all record marks."
+  (interactive)
+  (setq gpg-ring-marks-alist nil)
+  (gpg-ring-regenerate))
+
+(defun gpg-ring-toggle-show-unusable ()
+  "Toggle value if `gpg-ring-show-unusable'."
+  (interactive)
+  (setq gpg-ring-show-unusable (not gpg-ring-show-unusable))
+  (gpg-ring-regenerate))
+  
+(defun gpg-ring-toggle-show-all-ids ()
+  "Toggle value of `gpg-ring-show-all-ids'."
+  (interactive)
+  (setq gpg-ring-show-all-ids (not gpg-ring-show-all-ids))
+  (gpg-ring-regenerate))
+
+(defvar gpg-ring-output-buffer-name "*GnuPG Output*"
+  "Name buffer to which output from GnuPG is sent.")
+
+(defmacro gpg-ring-with-output-buffer (&rest body)
+  "Erase GnuPG output buffer, evaluate BODY in it, and display it."
+  `(with-current-buffer (get-buffer-create gpg-ring-output-buffer-name)
+     (erase-buffer)
+     (setq truncate-lines t)
+     ,@body
+     (goto-char (point-min))
+     (display-buffer gpg-ring-output-buffer-name)))
+
+(defun gpg-ring-quit ()
+  "Bury key list buffer and kill GnuPG output buffer."
+  (interactive)
+  (let ((output (get-buffer gpg-ring-output-buffer-name)))
+    (when output
+      (kill-buffer output)))
+  (when (eq 'gpg-ring-mode major-mode)
+    (bury-buffer)))
+
+(defun gpg-ring-show-key ()
+  "Show information for current key."
+  (interactive)
+  (let ((keys (gpg-ring-marked-keys)))
+    (gpg-ring-with-output-buffer
+     (gpg-key-insert-information (gpg-key-unique-id-list keys)))))
+
+(defun gpg-ring-extract-keys ()
+  "Export currently selected public keys in ASCII armor."
+  (interactive)
+  (let ((keys (gpg-ring-marked-keys)))
+    (gpg-ring-with-output-buffer
+     (gpg-key-insert-public-key (gpg-key-unique-id-list keys)))))
+
+(defun gpg-ring-extract-keys-to-kill ()
+  "Export currently selected public keys in ASCII armor to kill ring."
+  (interactive)
+  (let ((keys (gpg-ring-marked-keys)))
+    (with-temp-buffer
+      (gpg-key-insert-public-key (gpg-key-unique-id-list keys))
+      (copy-region-as-kill (point-min) (point-max)))))
+
+(defun gpg-ring-update-key ()
+  "Fetch key information from key server."
+  (interactive)
+  (let ((keys (gpg-ring-marked-keys)))
+    (gpg-ring-with-output-buffer
+     (gpg-key-retrieve (gpg-key-unique-id-list keys)))))
+
+(defun gpg-ring-insert-key-stat (key)
+  (let* ((validity (gpg-key-validity key))
+        (validity-entry (assq validity gpg-ring-trust-alist))
+        (trust (gpg-key-trust key))
+        (trust-entry (assq trust gpg-ring-trust-alist)))
+    ;; Insert abbrev for key status.
+    (let ((start (point)))
+      (insert (nth 1 validity-entry))
+      ;; Change face if necessary.
+      (when (nth 2 validity-entry)
+       (add-text-properties start (point) 
+                            (list 'face (nth 2 validity-entry)))))
+    ;; Trust, key ID, length, algorithm, creation date.
+    (insert (format "/%s %-8s/%4d/%-5s created %s"
+                   (nth 1 trust-entry)
+                   (gpg-short-key-id key)
+                   (gpg-key-length key) 
+                   (cdr (assq (gpg-key-algorithm key) gpg-ring-algo-alist))
+                   (gpg-key-creation-date key)))
+    ;; Expire date.
+    (when (gpg-key-expire-date key)
+      (insert ", ")
+      (let ((start (point))
+           (expired (eq 'expired validity))
+           (notice (concat )))
+       (insert (if expired "EXPIRED" "expires")
+               " " (gpg-key-expire-date key))
+       (when expired
+         (add-text-properties start (point) 
+                              '(face gpg-ring-key-invalid-face)))))))
+
+(defun gpg-ring-insert-key (key &optional mark)
+  "Inserts description for KEY into current buffer before point."
+  (let ((start (point)))
+    (insert (if mark mark " ")
+            " " (gpg-key-primary-user-id key) "\n"
+           "    ")
+    (gpg-ring-insert-key-stat key)
+    (insert "\n")
+    (when gpg-ring-show-all-ids
+      (let ((uids (gpg-key-user-ids key)))
+       (while uids
+         (insert "     ID " (pop uids) "\n"))))
+    (add-text-properties start (point)
+                        (list 'gpg-record-start start
+                              'gpg-key key))))
+
+(defun gpg-ring-regenerate ()
+  "Regenerate the key list buffer from stored data."
+  (interactive)
+  (let* ((key-list gpg-ring-key-list)
+        ;; Record position of point.
+        (old-record (if (eobp)         ; No record on last line.
+                        nil 
+                      (gpg-key-unique-id (gpg-ring-current-key))))
+        (old-pos (if old-record (- (point) (gpg-ring-record-start))))
+        found new-pos new-pos-offset buffer-read-only new-marks)
+    ;; Replace buffer contents with new data.
+    (erase-buffer)
+    (while key-list
+      (let* ((key (pop key-list))
+            (id (gpg-key-unique-id key))
+            (mark (assoc id gpg-ring-marks-alist)))
+       (when (or gpg-ring-show-unusable
+                 (not (memq (gpg-key-validity key) 
+                            '(disabled revoked expired))))
+         ;; Check if point was in this record.
+         (when (and old-record 
+                    (string-equal old-record id))
+           (setq new-pos (point))
+           (setq new-pos-offset (+ new-pos old-pos)))
+         ;; Check if this record was marked.
+         (if (nth 1 mark)
+             (progn
+               (push mark new-marks)
+               (gpg-ring-insert-key key (nth 1 mark)))
+           (gpg-ring-insert-key key)))))
+    ;; Replace mark alist with the new one (which does not contain
+    ;; marks for records which vanished during this update).
+    (setq gpg-ring-marks-alist new-marks)
+    ;; Restore point.
+    (if (not old-record)
+       ;; We were at the end of the buffer before.
+       (goto-char (point-max))
+      (if new-pos
+         (if (and (< new-pos-offset (point-max))
+                  (equal old-record (gpg-key-unique-id 
+                                     (gpg-ring-current-key new-pos-offset))))
+             ;; Record is there, with offset.
+             (goto-char new-pos-offset)
+           ;; Record is there, but not offset.
+           (goto-char new-pos))
+       ;; Record is not there.
+       (goto-char (point-min))))))
+
+(defun gpg-ring-update ()
+  "Update the key list buffer with new data."
+  (interactive)
+  (let ((funcs gpg-ring-update-funcs)
+       old)
+    ;; Merge the sorted lists obtained by calling elements of
+    ;; `gpg-ring-update-funcs'.
+    (while funcs 
+      (let ((additional (funcall (pop funcs)))
+           new)
+       (while (and additional old)
+         (if (gpg-key-lessp (car additional) (car old))
+             (push (pop additional) new)
+           (if (gpg-key-lessp (car old) (car additional))
+               (push (pop old) new)
+             ;; Keys are perhaps equal.  Always Add old key.
+             (push (pop old) new)
+             ;; If new key is equal, drop it, otherwise add it as well.
+             (if (string-equal (gpg-key-unique-id (car old))
+                               (gpg-key-unique-id (car additional)))
+                 (pop additional)
+               (push (pop additional) new)))))
+       ;; Store new list as old one for next round.
+       (setq old (nconc (nreverse new) old additional))))
+    ;; Store the list in the buffer.
+    (setq gpg-ring-key-list old))
+  (gpg-ring-regenerate))
+
+(defun gpg-ring-action ()
+  "Perform the action associated with this buffer."
+  (interactive)
+  (if gpg-ring-action
+      (funcall gpg-ring-action (gpg-ring-marked-keys))
+    (error "No action for this buffer specified")))
+     
+;;;###autoload
+(defun gpg-ring-keys (&optional key-list-funcs action)
+  (interactive)
+  (let ((buffer (get-buffer-create "*GnuPG Key List*")))
+    (with-current-buffer buffer
+      (gpg-ring-mode)
+      (setq gpg-ring-action action)
+      (setq gpg-ring-update-funcs key-list-funcs key-list-funcs)
+      (gpg-ring-update)
+      (goto-char (point-min)))
+    (switch-to-buffer buffer)))
+
+;;;###autoload
+(defun gpg-ring-public (key-spec)
+  "List public keys matching keys KEY-SPEC."
+  (interactive "sList public keys containing: ")
+  (gpg-ring-keys  `((lambda () (gpg-key-list-keys ,key-spec)))))
+
+(provide 'gpg-ring)
+
+;;; gpg-ring.el ends here
diff --git a/contrib/gpg.el b/contrib/gpg.el
new file mode 100644 (file)
index 0000000..9362788
--- /dev/null
@@ -0,0 +1,1322 @@
+;;; gpg.el --- Interface to GNU Privacy Guard
+
+;; Copyright (C) 2000 RUS-CERT, University Of Stuttgart
+
+;; Author: Florian Weimer <Florian.Weimer@RUS.Uni-Stuttgart.DE>
+;; Maintainer: Florian Weimer <Florian.Weimer@RUS.Uni-Stuttgart.DE>
+;; Keywords: crypto
+;; Created: 2000-04-15
+
+;; This file is NOT (yet?) part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA
+;; ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA
+;;
+;; This code is not well-tested.  BE CAREFUL!
+;; 
+;; ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA
+;; ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA ALPHA
+
+;; Implemented features which can be tested:
+;;
+;; * Customization for all flavors of PGP is possible.
+;; * The main operations (verify, decrypt, sign, encrypt, sign &
+;;   encrypt) are implemented.
+;; * Optionally, Gero Treuner's gpg-2comp script is supported, 
+;;   to generate data which is compatible with PGP 2.6.3.
+
+;; Customizing external programs 
+;; =============================
+
+;; The customization are very similar to those of others programs,
+;; only the C-ish "%" constructs have been replaced by more Lisp-like
+;; syntax.
+;;
+;; First, you have to adjust the default executable paths
+;; (`gpg-command-default-alist', customization group `gpg-options',
+;; "Controlling GnuPG invocation.").  After that, you should
+;; change the configuration options which control how specific
+;; command line flags are built (`gpg-command-flag-sign-with-key',
+;; (`gpg-command-flag-recipient').  The elements of these lists are
+;; concatenated without spaces, and a new argument is only started
+;; where indicated.  The `gpg-command-flag-recipient' list is special:
+;; it consists of two parts, the first one remains at the beginning
+;; of the argument, the second one is repeated for each recipient.
+;; Finally, `gpg-command-passphrase-env' has to be changed if there's
+;; no command line flag to force the external program to read the data
+;; from standard input before the message.
+;;
+;; In customization group `gpg-commands', "Controlling GnuPG
+;; invocation.", you have to supply the actual syntax for external
+;; program calls.  Each variable consists of a pair of a program
+;; specification (if a Lisp symbol is given here, it is translated
+;; via `gpg-command-default-alist') and a list of program arguments
+;; with placeholders.  Please read the documentation of each variable
+;; before making your adjustments and try to match the given
+;; requirements as closely as possible!
+;;
+;; The `gpg-commands-key' group, "GnuPG Key Management Commands.",
+;; specifies key management commands.  The syntax of these variables
+;; is like those in the `gpg-commands' group.  Note that the output
+;; format of some of these external programs has to match very close
+;; that of GnuPG.  Additional tools (Thomas Roessler's "pgpring.c")
+;; are available if your favorite implementation of OpenPGP cannot
+;; output the this format.
+
+;; Security considerations 
+;; =======================
+
+;; On a typical multiuser UNIX system, the memory image of the
+;; Emacs process is not locked, therefore it can be swapped to disk
+;; at any time.  As a result, the passphrase might show up in the
+;; swap space (even if you don't use the passphrase cache, i.e. if
+;; `gpg-passphrase-timeout' is 0).  If someone is able to run `gdb' or
+;; another debugger on your Emacs process, he might be able to recover
+;; the passphrase as well.  Unfortunately, nothing can be done in
+;; order to prevent this at the moment.
+;;
+;; BE CAREFUL: If you use the passphrase cache feature, the passphrase
+;; is stored in the variable `gpg-passphrase' -- and it is NOT
+;; encrypted in any way.  (This is a conceptual problem because the
+;; nature of the passphrase cache requires that Emacs is able to
+;; decrypt automatically, so only a very weak protection could be
+;; applied anyway.)
+;;
+;; In addition, if you use an unpatched Emacs 20 (and earlier
+;; versions), passwords show up in the output of the `view-lossage'
+;; function (bound to `C-h l' by default).
+
+\f
+;;; Code:
+
+(require 'timer)
+(eval-when-compile (require 'cl))
+
+(eval-and-compile 
+  (defalias 'gpg-point-at-eol
+    (if (fboundp 'point-at-eol)
+       'point-at-eol
+      'line-end-position)))
+
+;;;; Customization:
+
+;;; Customization: Groups:
+
+(defgroup gpg nil
+  "GNU Privacy Guard interface."
+  :tag "GnuPG"
+  :group 'processes)
+
+(defgroup gpg-options nil
+  "Controlling GnuPG invocation."
+  :tag "GnuPG Options"
+  :group 'gpg)
+
+(defgroup gpg-commands nil
+  "Primary GnuPG Operations."
+  :tag "GnuPG Commands"
+  :group 'gpg)
+
+(defgroup gpg-commands-key nil
+  "Commands for GnuPG key management."
+  :tag "GnuPG Key Commands"
+  :group 'gpg-commands)
+
+;;; Customization: Widgets:
+
+(if (get 'alist 'widget-type)
+    (define-widget 'gpg-command-alist 'alist
+      "An association list for GnuPG command names."
+      :key-type '(symbol :tag   "Abbreviation")
+      :value-type '(string :tag "Program name")
+      :convert-widget 'widget-alist-convert-widget
+      :tag "Alist")
+    (define-widget 'gpg-command-alist 'repeat
+      "An association list for GnuPG command names."
+      :args '((cons :format "%v"
+                   (symbol :tag   "Abbreviation")
+                   (string :tag "Program name")))
+      :tag "Alist"))
+
+(define-widget 'gpg-command-program 'choice
+  "Widget for entering the name of a program (mostly the GnuPG binary)."
+  :tag "Program"
+  :args '((const :tag "Default GnuPG program."
+                :value gpg)
+         (const :tag "GnuPG compatibility wrapper."
+                :value gpg-2comp)
+         (const :tag "Disabled"
+                :value nil)
+         (string :tag "Custom program" :format "%v")))
+
+(define-widget 'gpg-command-sign-options 'cons
+  "Widget for entering signing options."
+  :args '(gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert armor option here if necessary."
+                  :value armor)
+           (const :tag "Insert text mode option here if necessary."
+                  :value textmode)
+           (const :tag "Insert the sign with key option here if necessary."
+                  :value sign-with-key)
+           (string :format "%v")))))
+
+(define-widget 'gpg-command-key-options 'cons
+  "Widget for entering key command options."
+  :args '(gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert key ID here." 
+                  :value key-id)
+           (string :format "%v")))))
+
+;;; Customization: Variables:
+
+;;; Customization: Variables: Paths and Flags:
+
+(defcustom gpg-passphrase-timeout
+  0
+  "Timeout (in seconds) for the passphrase cache.
+The passphrase cache is cleared after is hasn't been used for this
+many seconds.  The values 0 means that the passphrase is not cached at
+all."
+  :tag "Passphrase Timeout"
+  :type 'number
+  :group 'gpg-options)
+
+(defcustom gpg-default-key-id
+  nil
+  "Default key/user ID used for signatures."
+  :tag "Default Key ID"
+  :type '(choice
+         (const :tag "Use GnuPG default." :value nil)
+         (string))
+  :group 'gpg-options)
+
+(defcustom gpg-temp-directory 
+  (expand-file-name "~/tmp")
+  "Directory for temporary files.
+If you are running Emacs 20, this directory must have mode 0700."
+  :tag "Temp directory"
+  :type 'string
+  :group 'gpg-options)
+
+(defcustom gpg-command-default-alist 
+  '((gpg . "gpg")
+    (gpg-2comp . "gpg"))
+  "Default paths for some GnuPG-related programs.
+Modify this variable if you have to change the paths to the
+executables required by the GnuPG interface.  You can enter \"gpg-2comp\"
+for `gpg-2comp' if you have obtained this script, in order to gain
+PGP 2.6.x compatibility."
+  :tag "GnuPG programs"
+  :type 'gpg-command-alist
+  :group 'gpg-options)
+
+(defcustom gpg-command-all-arglist
+  nil
+  "List of arguments to add to all GPG commands."
+  :tag "All command args"
+  :group 'gpg-options)
+
+(defcustom gpg-command-flag-textmode "--textmode"
+  "The flag to indicate canonical text mode to GnuPG."
+  :tag "Text mode flag"
+  :type 'string
+  :group 'gpg-options)
+
+(defcustom gpg-command-flag-armor "--armor"
+  "The flag to request ASCII-armoring output from GnuPG."
+  :tag "Armor flag"
+  :type 'string
+  :group 'gpg-options)
+
+(defcustom gpg-command-flag-sign-with-key '("--local-user=" sign-with-key)
+  "String to include to specify the signing key ID.
+The elements are concatenated (without spaces) to form a command line
+option."
+  :tag "Sign with key flag"
+  :type '(repeat :tag "Argument parts"
+         (choice :format "%[Type%] %v"
+          (const :tag "Start next argument." :value next-argument)
+          (const :tag "Insert signing key ID here." :value sign-with-key)
+          (string)))
+  :group 'gpg-options)
+
+(defcustom gpg-command-flag-recipient
+  '(nil . ("-r" next-argument recipient next-argument))
+  "Format of a recipient specification.
+The elements are concatenated (without spaces) to form a command line
+option.  The second part is repeated for each recipient."
+  :tag "Recipients Flag"
+  :type '(cons
+         (repeat :tag "Common prefix"
+          (choice :format "%[Type%] %v"
+           (const :tag "Start next argument." :value next-argument)
+           (string)))
+         (repeat :tag "For each recipient"
+          (choice :format "%[Type%] %v"
+           (const :tag "Start next argument." :value next-argument)
+           (const :tag "Insert recipient key ID here." :value recipient)
+           (string))))
+  :group 'gpg-options)
+
+(defcustom gpg-command-passphrase-env
+  nil
+  "Environment variable to set when a passphrase is required, or nil.
+If an operation is invoked which requires a passphrase, this
+environment variable is set before calling the external program to
+indicate that it should read the passphrase from standard input."
+  :tag "Passphrase environment"
+  :type '(choice
+         (const :tag "Disabled" :value nil)
+         (cons
+          (string :tag "Variable")
+          (string :tag "Value")))
+  :group 'gpg-options)
+
+;;; Customization: Variables: GnuPG Commands:
+
+(defcustom gpg-command-verify
+  '(gpg . ("--status-fd" "1" "--batch" "--verbose" "--verify" signature-file message-file))
+  "Command to verify a detached signature.
+The invoked program has to read the signed message and the signature
+from the given files.  It should write human-readable information to
+standard output and/or standard error.  The program shall not convert
+charsets or line endings; the input data shall be treated as binary."
+  :tag "Verify Command"
+  :type '(cons 
+         gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert name of file containing the message here." 
+                  :value message-file)
+           (const :tag "Insert name of file containing the signature here."
+                  :value signature-file)
+           (string :format "%v"))))
+  :group 'gpg-commands)
+
+(defcustom gpg-command-verify-cleartext
+  '(gpg . ("--status-fd" "1" "--batch" "--verbose" "--verify" message-file))
+  "Command to verify a message.
+The invoked program has to read the signed message from the given
+file.  It should write human-readable information to standard output
+and/or standard error.  The program shall not convert charsets or line
+endings; the input data shall be treated as binary."
+  :tag "Cleartext Verify Command"
+  :type '(cons 
+         gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert name of file containing the message here." 
+                  :value message-file)
+           (string :format "%v"))))
+  :group 'gpg-commands)
+
+(defcustom gpg-command-decrypt
+  '(gpg . ("--status-fd" "2" "--decrypt" "--batch" "--passphrase-fd=0"))
+  "Command to decrypt a message.
+The invoked program has to read the passphrase from standard
+input, followed by the encrypted message.  It writes the decrypted
+message to standard output, and human-readable diagnostic messages to
+standard error."
+  :tag "Decrypt Command"
+  :type '(cons
+         gpg-command-program
+         (repeat
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert name of file containing the message here." 
+                  :value message-file)
+           (string :format "%v"))))
+  :group 'gpg-commands)
+
+(defcustom gpg-command-sign-cleartext
+  '(gpg-2comp . ("--batch" "--passphrase-fd=0" "--output=-"
+                armor textmode  "--clearsign"
+                sign-with-key))
+  "Command to create a \"clearsign\" text file.  
+The invoked program has to read the passphrase from standard input,
+followed by the message to sign.  It should write the ASCII-amored
+signed text message to standard output, and diagnostic messages to
+standard error."
+  :tag "Clearsign Command"
+  :type 'gpg-command-sign-options
+  :group 'gpg-commands)
+
+(defcustom gpg-command-sign-detached
+  '(gpg-2comp . ("--batch" "--passphrase-fd=0" "--output=-"
+                armor textmode "--detach-sign" 
+                sign-with-key))
+  "Command to create a detached signature. 
+The invoked program has to read the passphrase from standard input,
+followed by the message to sign.  It should write the ASCII-amored
+detached signature to standard output, and diagnostic messages to
+standard error.  The program shall not convert charsets or line
+endings; the input data shall be treated as binary."
+  :tag "Sign Detached Command"
+  :type 'gpg-command-sign-options
+  :group 'gpg-commands)
+
+(defcustom gpg-command-sign-encrypt
+  '(gpg-2comp . ("--batch" "--passphrase-fd=0" "--output=-"
+                armor textmode  "--always-trust" sign-with-key recipients
+                 "--sign" "--encrypt" plaintext-file))
+  "Command to sign and encrypt a file.
+The invoked program has to read the passphrase from standard input,
+followed by the message to sign and encrypt if there is no
+`plaintext-file' placeholder.  It should write the ASCII-amored
+encrypted message to standard output, and diagnostic messages to
+standard error."
+  :tag "Sign And Encrypt Command"
+  :type '(cons 
+         gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert the `sign with key' option here if necessary."
+                  :value sign-with-key)
+           (const :tag "Insert list of recipients here."
+                  :value recipients)
+           (const :tag "Insert here name of file with plaintext."
+                  :value plaintext-file)
+           (string :format "%v"))))
+  :group 'gpg-commands)
+
+(defcustom gpg-command-encrypt
+  '(gpg-2comp . ("--batch" "--output=-" armor textmode "--always-trust" 
+                "--encrypt" recipients plaintext-file))
+  "Command to encrypt a file.  
+The invoked program has to read the message to encrypt from standard
+input or from the plaintext file (if the `plaintext-file' placeholder
+is present).  It should write the ASCII-amored encrypted message to
+standard output, and diagnostic messages to standard error."
+  :type '(cons 
+         gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert list of recipients here."
+                  :value recipients)
+           (const :tag "Insert here name of file with plaintext."
+                  :value plaintext-file)
+           (string :format "%v"))))
+  :group 'gpg-commands)
+
+;;; Customization: Variables: Key Management Commands:
+
+(defcustom gpg-command-key-import
+  '(gpg . ("--import" "--verbose" message-file))
+  "Command to import a public key from a file."
+  :tag "Import Command"
+  :type '(cons 
+         gpg-command-program
+         (repeat 
+          :tag "Arguments"
+          (choice 
+           :format "%[Type%] %v"
+           (const :tag "Insert name of file containing the key here." 
+                  :value message-file)
+           (string :format "%v"))))
+  :group 'gpg-commands-key)
+
+(defcustom gpg-command-key-export
+  '(gpg . ("--no-verbose" "--armor" "--export" key-id))
+  "Command to export a public key from the key ring.
+The key should be written to standard output using ASCII armor."
+  :tag "Export Command"
+  :type 'gpg-command-key-options
+  :group 'gpg-commands-key)
+
+(defcustom gpg-command-key-verify
+  '(gpg . ("--no-verbose" "--batch" "--fingerprint" "--check-sigs" key-id))
+  "Command to verify a public key."
+  :tag "Verification Command"
+  :type 'gpg-command-key-options
+  :group 'gpg-commands-key)
+
+(defcustom gpg-command-key-public-ring
+  '(gpg . ("--no-verbose" "--batch" "--with-colons" "--list-keys" key-id))
+  "Command to list the contents of the public key ring."
+  :tag "List Public Key Ring Command"
+  :type 'gpg-command-key-options
+  :group 'gpg-commands-key)
+
+(defcustom gpg-command-key-secret-ring
+  '(gpg . ("--no-verbose" "--batch" "--with-colons" 
+          "--list-secret-keys" key-id))
+  "Command to list the contents of the secret key ring."
+  :tag "List Secret Key Ring Command"
+  :type 'gpg-command-key-options
+  :group 'gpg-commands-key)
+
+(defcustom gpg-command-key-retrieve 
+  '(gpg . ("--batch" "--recv-keys" key-id))
+  "Command to retrieve public keys."
+  :tag "Retrieve Keys Command"
+  :type 'gpg-command-key-options
+  :group 'gpg-commands-key)
+
+\f
+;;;; Helper functions for GnuPG invocation:
+
+;;; Build the GnuPG command line:
+
+(defun gpg-build-argument (template substitutions &optional pass-start)
+  "Build command line argument(s) by substituting placeholders.
+TEMPLATE is a list of strings and symbols.  The placeholder symbols in
+it are replaced by SUBSTITUTIONS, the elements between
+`next-argument' symbols are concatenated without spaces and are
+returned in a list.
+
+SUBSTITIONS is a list of (SYMBOL . SEXP) pairs, where SEXP is either
+a string (which is inserted literally), a list of strings (which are
+inserted as well), or nil, which means to insert nothing.
+
+If PASS-START is t, `next-argument' is also inserted into the result,
+and symbols without a proper substitution are retained in the output,
+otherwise, an untranslated symbol results in an error.
+
+This function does not handle empty arguments reliably."
+  (let ((current-arg "")
+       (arglist nil))
+    (while template
+      (let* ((templ (pop template))
+            (repl (assoc templ substitutions))
+            (new (if repl (cdr repl) templ)))
+       (cond
+        ((eq templ 'next-argument)
+         ;; If the current argument is not empty, start a new one.
+         (unless (equal current-arg "")
+           (setq arglist (nconc arglist 
+                                (if pass-start
+                                    (list current-arg 'next-argument)
+                                  (list current-arg))))
+           (setq current-arg "")))
+        ((null new) nil)               ; Drop it.
+        ((and (not (stringp templ)) (null repl))
+         ;; Retain an untranslated symbol in the output if
+         ;; `pass-start' is true.
+         (unless pass-start
+           (error "No replacement for `%s'" templ))
+         (setq arglist (nconc arglist (list current-arg templ)))
+         (setq current-arg ""))
+        (t
+         (unless (listp new)
+           (setq new (list new)))
+         (setq current-arg (concat current-arg 
+                                   (apply 'concat new)))))))
+    (unless (equal current-arg "")
+      (setq arglist (nconc arglist (list current-arg))))
+    arglist))
+
+(defun gpg-build-arg-list (template substitutions)
+  "Build command line by substituting placeholders.
+TEMPLATE is a list of strings and symbols.  The placeholder symbols in
+it are replaced by SUBSTITUTIONS.
+
+SUBSTITIONS is a list of (SYMBOL . SEXP) pairs, where SEXP is either a
+string (which is inserted literally), a list of strings (which are
+inserted as well), or nil, which means to insert nothing."
+  (let ((arglist (copy-sequence gpg-command-all-arglist)))
+    (while template
+      (let* ((templ (pop template))
+            (repl (assoc templ substitutions))
+            (new (if repl (cdr repl) templ)))
+       (cond
+        ((and (symbolp templ) (null repl))
+         (error "No replacement for `%s'" templ))
+        ((null new) nil)               ; Drop it.
+        (t
+         (unless (listp new)
+           (setq new (list new)))
+         (setq arglist (nconc arglist new))))))
+    arglist))
+
+(defun gpg-build-flag-recipients-one (recipient)
+  "Build argument for one RECIPIENT."
+  (gpg-build-argument (cdr gpg-command-flag-recipient)
+                     `((recipient . ,recipient)) t))
+
+(defun gpg-build-flag-recipients (recipients)
+  "Build list of RECIPIENTS using `gpg-command-flag-recipient'."
+  (gpg-build-argument
+   (apply 'append (car gpg-command-flag-recipient)
+                 (mapcar 'gpg-build-flag-recipients-one
+                         recipients))
+   nil))
+
+(defun gpg-read-recipients ()
+  "Query the user for several recipients."
+  (let ((go t) 
+       recipients r)
+    (while go
+      (setq r (read-string "Enter recipient ID [RET when no more]: "))
+      (if (equal r "")
+         (setq go nil)
+       (setq recipients (nconc recipients (list r)))))
+    recipients))
+    
+(defun gpg-build-flag-sign-with-key (key)
+  "Build sign with key flag using `gpg-command-flag-sign-with-key'."
+  (let ((k (if key key 
+            (if gpg-default-key-id gpg-default-key-id
+              nil))))
+    (if k
+       (gpg-build-argument gpg-command-flag-sign-with-key
+                           (list (cons 'sign-with-key k)))
+      nil)))
+
+(defmacro gpg-with-passphrase-env (&rest body)
+  "Adjust the process environment and evaluate BODY.
+During the evaluation of the body forms, the process environment is
+adjust according to `gpg-command-passphrase-env'."
+  (let ((env-value (make-symbol "env-value")))
+    `(let ((,env-value))
+       (unwind-protect
+          (progn
+            (when gpg-command-passphrase-env
+              (setq ,env-value (getenv (car gpg-command-passphrase-env)))
+              (setenv (car gpg-command-passphrase-env) 
+                      (cdr gpg-command-passphrase-env)))
+            ,@body)
+        (when gpg-command-passphrase-env
+          ;; This will clear the variable if it wasn't set before.
+          (setenv (car gpg-command-passphrase-env) ,env-value))))))
+(put 'gpg-with-passphrase-env 'lisp-indent-function 0)
+(put 'gpg-with-passphrase-env 'edebug-form-spec '(body))
+
+;;; Temporary files:
+
+(defun gpg-make-temp-file ()
+  "Create a temporary file in a safe way"
+  (let ((name  ;; User may use "~/"
+        (expand-file-name "gnupg" gpg-temp-directory)))
+    (if (fboundp 'make-temp-file)
+       ;; If we've got make-temp-file, we are on the save side.
+       (make-temp-file name)
+      ;; make-temp-name doesn't create the file, and an ordinary
+      ;; write-file operation is prone to nasty symlink attacks if the
+      ;; temporary file resides in a world-writable directory.
+      (unless (or (memq system-type '(windows-nt cygwin32 win32 w32 mswindows))
+                 (eq (file-modes gpg-temp-directory) 448)) ; mode 0700
+       (error "Directory for temporary files (%s) must have mode 0700" gpg-temp-directory))
+      (setq name (make-temp-name name))
+      (let ((mode (default-file-modes)))
+       (unwind-protect
+           (progn
+             (set-default-file-modes 384) ; mode 0600
+             (with-temp-file name))
+         (set-default-file-modes mode)))
+      name)))
+
+(defvar gpg-temp-files nil
+  "List of temporary files used by the GnuPG interface.
+Do not set this variable.  Call `gpg-with-temp-files' if you need
+temporary files.")
+
+(defun gpg-with-temp-files-create (count)
+  "Do not call this function.  Used internally by `gpg-with-temp-files'."
+  (while (> count 0)
+    (setq gpg-temp-files (cons (gpg-make-temp-file) gpg-temp-files))
+    (setq count (1- count))))
+
+(defun gpg-with-temp-files-delete ()
+  "Do not call this function.  Used internally by `gpg-with-temp-files'."
+  (while gpg-temp-files
+    (let ((file (pop gpg-temp-files)))
+      (condition-case nil
+         (delete-file file)
+       (error nil)))))
+
+(defmacro gpg-with-temp-files (count &rest body)
+  "Create COUNT temporary files, USE them, and delete them.
+The function USE is called with the names of all temporary files as
+arguments."
+  `(let ((gpg-temp-files))
+      (unwind-protect
+         (progn
+           ;; Create the temporary files.
+           (gpg-with-temp-files-create ,count)
+           ,@body)
+       (gpg-with-temp-files-delete))))
+(put 'gpg-with-temp-files 'lisp-indent-function 1)
+(put 'gpg-with-temp-files 'edebug-form-spec '(body))
+
+;;;  Making subprocesses:
+
+(defun gpg-exec-path (option)
+  "Return the program name for OPTION.
+OPTION is of the form (PROGRAM . ARGLIST).  This functions returns
+PROGRAM, but takes default values into account."
+  (let* ((prg (car option))
+        (path (assq prg gpg-command-default-alist)))
+    (cond
+     (path (if (null (cdr path))
+              (error "Command `%s' is not available" prg)
+            (cdr path)))
+     ((null prg) (error "Command is disabled"))
+     (t prg))))
+
+(defun gpg-call-process (cmd args stdin stdout stderr &optional passphrase)
+  "Invoke external program CMD with ARGS on buffer STDIN.
+Standard output is insert before point in STDOUT, standard error in
+STDERR.  If PASSPHRASE is given, send it before STDIN.  PASSPHRASE
+should not end with a line feed (\"\\n\").
+
+If `stdin-file' is present in ARGS, it is replaced by the name of a
+temporary file.  Before invoking CMD, the contents of STDIN is written
+to this file."
+  (gpg-with-temp-files 2
+   (let* ((coding-system-for-read 'no-conversion)
+         (coding-system-for-write 'no-conversion)
+         (have-stdin-file (memq 'stdin-file args))
+         (stdin-file (nth 0 gpg-temp-files))
+         (stderr-file (nth 1 gpg-temp-files))
+         (cpr-args `(,cmd 
+                     nil               ; don't delete
+                     (,stdout ,stderr-file)
+                     nil               ; don't display
+                     ;; Replace `stdin-file'.
+                     ,@(gpg-build-arg-list 
+                         args (list (cons 'stdin-file stdin-file)))))
+         res)
+     (when have-stdin-file
+       (with-temp-file stdin-file
+        (buffer-disable-undo)
+        (insert-buffer-substring stdin)))
+     (setq res
+          (if passphrase
+              (with-temp-buffer
+                (buffer-disable-undo)
+                (insert passphrase "\n")
+                (unless have-stdin-file
+                  (apply 'insert-buffer-substring 
+                         (if (listp stdin) stdin (list stdin))))
+                (apply 'call-process-region (point-min) (point-max) cpr-args)
+                ;; Wipe out passphrase.
+                (goto-char (point-min))
+                (translate-region (point) (gpg-point-at-eol)
+                                  (make-string 256 ? )))
+            (if (listp stdin)
+                (with-current-buffer (car stdin)
+                  (apply 'call-process-region 
+                         (cadr stdin)
+                         (if have-stdin-file (cadr stdin) (caddr stdin))
+                         cpr-args))
+              (with-current-buffer stdin
+                (apply 'call-process-region 
+                       (point-min) 
+                       (if have-stdin-file (point-min) (point-max))
+                       cpr-args)))))
+     (with-current-buffer stderr
+       (insert-file-contents-literally stderr-file))
+     (if (or (stringp res) (> res 0))
+        ;; Signal or abnormal exit.
+        (with-current-buffer stderr
+          (goto-char (point-max))
+          (insert (format "\nCommand exit status: %s\n" res))
+          nil)
+       t))))
+
+(defvar gpg-result-buffer nil
+  "The result of a GnuPG operation is stored in this buffer.
+Never set this variable directly, use `gpg-show-result' instead.")
+
+(defun gpg-show-result-buffer (always-show result)
+  "Called by `gpg-show-results' to actually show the buffer."
+  (with-current-buffer gpg-result-buffer
+    ;; Only proceed if the buffer is non-empty.
+    (when (and (/= (point-min) (point-max))
+              (or always-show (not result)))
+      (save-window-excursion
+       (display-buffer (current-buffer))
+       (unless (y-or-n-p "Continue? ")
+         (error "GnuPG operation aborted"))))))
+
+(defmacro gpg-show-result (always-show &rest body)
+  "Show GnuPG result to user for confirmation.
+This macro binds `gpg-result-buffer' to a temporary buffer and
+evaluates BODY, like `progn'.  If BODY evaluates to `nil' (or
+`always-show' is not nil), the user is asked for confirmation."
+  `(let ((gpg-result-buffer (get-buffer-create 
+                        (generate-new-buffer-name "*GnuPG Output*"))))
+     (unwind-protect
+        (gpg-show-result-buffer ,always-show (progn ,@body))
+       (kill-buffer gpg-result-buffer))))
+(put 'gpg-show-result 'lisp-indent-function 1)
+(put 'gpg-show-result 'edebug-form-spec '(body))
+
+;;; Passphrase handling:
+
+(defvar gpg-passphrase-timer
+  (timer-create)
+  "This timer will clear the passphrase cache periodically.")
+
+(defvar gpg-passphrase
+  nil
+  "The (unencrypted) passphrase cache.")
+
+(defun gpg-passphrase-clear-string (str)
+  "Erases STR by overwriting all characters."
+  (let ((pos 0)
+       (len (length str)))
+    (while (< pos len)
+      (aset str pos ? )
+      (incf pos))))
+
+;;;###autoload
+(defun gpg-passphrase-forget ()
+  "Forget stored passphrase."
+  (interactive)
+  (when gpg-passphrase
+    (cancel-timer gpg-passphrase-timer)
+    (setq gpg-passphrase-timer nil)
+    (gpg-passphrase-clear-string gpg-passphrase)
+    (setq gpg-passphrase nil)))
+
+(defun gpg-passphrase-store (passphrase)
+  "Store PASSPHRASE in cache.
+Updates the timeout for clearing the cache to `gpg-passphrase-timeout'."
+  (unless (equal gpg-passphrase-timeout 0)
+    (if (null gpg-passphrase-timer)
+       (setq gpg-passphrase-timer (timer-create)))
+    (timer-set-time gpg-passphrase-timer 
+                   (timer-relative-time (current-time) 
+                                        gpg-passphrase-timeout))
+    (timer-set-function gpg-passphrase-timer 'gpg-passphrase-forget)
+    (unless (and (fboundp 'itimer-live-p)
+                (itimer-live-p gpg-passphrase-timer))
+      (timer-activate gpg-passphrase-timer))
+    (setq gpg-passphrase passphrase))
+  passphrase)
+
+(defun gpg-passphrase-read ()
+  "Read a passphrase and remember it for some time."
+  (interactive)
+  (if gpg-passphrase
+      ;; This reinitializes the timer.
+      (gpg-passphrase-store gpg-passphrase)
+    (let ((pp (read-passwd "Enter passphrase: ")))
+      (gpg-passphrase-store pp))))
+
+\f
+;;;; Main operations:
+
+;;;###autoload
+(defun gpg-verify (message signature result)
+  "Verify buffer MESSAGE against detached SIGNATURE buffer.
+Returns t if everything worked out well, nil otherwise.  Consult
+buffer RESULT for details."
+  (interactive "bBuffer containing message: \nbBuffer containing signature: \nbBuffor for result: ")
+  (gpg-with-temp-files 2
+    (let* ((sig-file    (nth 0 gpg-temp-files))
+          (msg-file    (nth 1 gpg-temp-files))
+          (cmd (gpg-exec-path gpg-command-verify))
+          (args (gpg-build-arg-list (cdr gpg-command-verify)
+                                    `((signature-file . ,sig-file)
+                                      (message-file . ,msg-file))))
+          res)
+      (with-temp-file sig-file 
+       (buffer-disable-undo)
+       (apply 'insert-buffer-substring (if (listp signature)
+                                           signature
+                                         (list signature))))
+      (with-temp-file msg-file 
+       (buffer-disable-undo)
+       (apply 'insert-buffer-substring (if (listp message)
+                                           message
+                                         (list message))))
+      (setq res (apply 'call-process-region 
+                      (point-min) (point-min) ; no data
+                      cmd
+                      nil              ; don't delete
+                      result
+                      nil              ; don't display
+                      args))
+      (if (or (stringp res) (> res 0))
+         ;; Signal or abnormal exit.
+         (with-current-buffer result
+           (insert (format "\nCommand exit status: %s\n" res))
+           nil)
+       t))))
+
+;;;###autoload
+(defun gpg-verify-cleartext (message result)
+  "Verify message in buffer MESSAGE.
+Returns t if everything worked out well, nil otherwise.  Consult
+buffer RESULT for details.
+
+NOTE: Use of this function is deprecated."
+  (interactive "bBuffer containing message: \nbBuffor for result: ")
+  (gpg-with-temp-files 1
+    (let* ((msg-file    (nth 0 gpg-temp-files))
+          (cmd (gpg-exec-path gpg-command-verify-cleartext))
+          (args (gpg-build-arg-list (cdr gpg-command-verify-cleartext)
+                                    `((message-file . ,msg-file))))
+          res)
+      (with-temp-file msg-file 
+       (buffer-disable-undo)
+       (apply 'insert-buffer-substring (if (listp message)
+                                           message
+                                         (list message))))
+      (setq res (apply 'call-process-region
+                      (point-min) (point-min) ; no data
+                      cmd
+                      nil              ; don't delete
+                      result
+                      nil              ; don't display
+                      args))
+      (if (or (stringp res) (> res 0))
+         ;; Signal or abnormal exit.
+         (with-current-buffer result
+           (insert (format "\nCommand exit status: %s\n" res))
+           nil)
+       t))))
+
+;;;###autoload
+(defun gpg-decrypt (ciphertext plaintext result &optional passphrase)
+  "Decrypt buffer CIPHERTEXT to buffer PLAINTEXT.
+Returns t if everything worked out well, nil otherwise.  Consult
+buffer RESULT for details.  Reads a missing PASSPHRASE using
+`gpg-passphrase-read'."
+  (interactive "bBuffer containing ciphertext: \nbBuffer for plaintext: \nbBuffor for decryption status: ")
+  (gpg-call-process (gpg-exec-path gpg-command-decrypt)
+                   (gpg-build-arg-list (cdr gpg-command-decrypt) nil)
+                   ciphertext plaintext result
+                   (if passphrase passphrase (gpg-passphrase-read)))
+  (when passphrase
+    (gpg-passphrase-clear-string passphrase)))
+
+;;;###autoload
+(defun gpg-sign-cleartext
+  (plaintext signed-text result &optional passphrase sign-with-key)
+  "Sign buffer PLAINTEXT, and store PLAINTEXT with signature in
+SIGNED-TEXT.
+Reads a missing PASSPHRASE using `gpg-passphrase-read'.  Uses key ID
+SIGN-WITH-KEY if given, otherwise the default key ID.  Returns t if
+everything worked out well, nil otherwise.  Consult buffer RESULT for
+details.
+
+NOTE: Use of this function is deprecated."
+  (interactive "bBuffer containing plaintext: \nbBuffer for text with signature: \nbBuffer for status information: ")
+  (let ((subst (list (cons 'sign-with-key 
+                          (gpg-build-flag-sign-with-key sign-with-key))
+                    (cons 'armor gpg-command-flag-armor)
+                    (cons 'textmode gpg-command-flag-textmode))))
+    (gpg-call-process (gpg-exec-path gpg-command-sign-cleartext)
+                     (gpg-build-arg-list (cdr gpg-command-sign-cleartext) 
+                                         subst)
+                     plaintext signed-text result
+                     (if passphrase passphrase (gpg-passphrase-read))))
+  (when passphrase
+    (gpg-passphrase-clear-string passphrase)))
+
+;;;###autoload
+(defun gpg-sign-detached
+  (plaintext signature result &optional passphrase sign-with-key
+   armor textmode)
+  "Sign buffer PLAINTEXT, and store SIGNATURE in that buffer.
+Reads a missing PASSPHRASE using `gpg-passphrase-read'.  Uses key ID
+SIGN-WITH-KEY if given, otherwise the default key ID.  Returns t if
+everything worked out well, nil otherwise.  Consult buffer RESULT for
+details.  ARMOR the result and activate canonical TEXTMODE if
+requested."
+  (interactive "bBuffer containing plaintext: \nbBuffer for text with signature: \nbBuffer for status information: ")
+  (let ((subst (list (cons 'sign-with-key 
+                          (gpg-build-flag-sign-with-key sign-with-key))
+                    (cons 'armor (if armor gpg-command-flag-armor))
+                    (cons 'textmode (if armor gpg-command-flag-textmode)))))
+    (gpg-call-process (gpg-exec-path gpg-command-sign-detached)
+                     (gpg-build-arg-list (cdr gpg-command-sign-detached)
+                                         subst)
+                     plaintext signature result
+                     (if passphrase passphrase (gpg-passphrase-read))))
+  (when passphrase
+    (gpg-passphrase-clear-string passphrase)))
+
+
+;;;###autoload
+(defun gpg-sign-encrypt
+  (plaintext ciphertext result recipients &optional passphrase sign-with-key
+   armor textmode)
+  "Sign buffer PLAINTEXT, and store SIGNATURE in that buffer.
+RECIPIENTS is a list of key IDs used for encryption.  This function
+reads a missing PASSPHRASE using `gpg-passphrase-read', and uses key
+ID SIGN-WITH-KEY for the signature if given, otherwise the default key
+ID.  Returns t if everything worked out well, nil otherwise.  Consult
+buffer RESULT for details.  ARMOR the result and activate canonical
+TEXTMODE if requested."
+  (interactive (list
+               (read-buffer "Buffer containing plaintext: " nil t)
+               (read-buffer "Buffer for ciphertext: " nil t)
+               (read-buffer "Buffer for status informationt: " nil t)
+               (gpg-read-recipients)))
+    (let ((subst `((sign-with-key . ,(gpg-build-flag-sign-with-key 
+                                     sign-with-key))
+                  (plaintext-file . stdin-file)
+                  (recipients . ,(gpg-build-flag-recipients recipients))
+                  (armor ,(if armor gpg-command-flag-armor))
+                  (textmode ,(if armor gpg-command-flag-textmode)))))
+      (gpg-call-process (gpg-exec-path gpg-command-sign-encrypt)
+                       (gpg-build-arg-list (cdr gpg-command-sign-encrypt) 
+                                           subst)
+                       plaintext ciphertext result
+                       (if passphrase passphrase (gpg-passphrase-read))))
+  (when passphrase
+    (gpg-passphrase-clear-string passphrase)))
+
+
+;;;###autoload
+(defun gpg-encrypt
+  (plaintext ciphertext result recipients &optional passphrase armor textmode)
+  "Encrypt buffer PLAINTEXT, and store CIPHERTEXT in that buffer.
+RECIPIENTS is a list of key IDs used for encryption.  Returns t if
+everything worked out well, nil otherwise.  Consult buffer RESULT for
+details.  ARMOR the result and activate canonical
+TEXTMODE if requested."
+  (interactive (list
+               (read-buffer "Buffer containing plaintext: " nil t)
+               (read-buffer "Buffer for ciphertext: " nil t)
+               (read-buffer "Buffer for status informationt: " nil t)
+               (gpg-read-recipients)))
+  (let ((subst `((plaintext-file . stdin-file)
+                (recipients . ,(gpg-build-flag-recipients recipients))
+                (armor ,(if armor gpg-command-flag-armor))
+                (textmode ,(if armor gpg-command-flag-textmode)))))
+    (gpg-call-process (gpg-exec-path gpg-command-encrypt)
+                     (gpg-build-arg-list (cdr gpg-command-encrypt) subst)
+                     plaintext ciphertext result nil))
+  (when passphrase
+    (gpg-passphrase-clear-string passphrase)))
+
+\f
+;;;; Key management
+
+;;; ADT: OpenPGP Key
+
+(defun gpg-key-make (user-id key-id unique-id length algorithm
+                    creation-date expire-date validity trust)
+  "Create a new key object (for internal use only)."
+  (vector 
+       ;;  0   1      2         3      4        
+       user-id key-id unique-id length algorithm
+       ;; 5          6           7        8
+       creation-date expire-date validity trust))
+
+
+(defun gpg-key-p (key)
+  "Return t if KEY is a key specification."
+  (and (arrayp key) (equal (length key) 9) key))
+
+(defmacro gpg-key-primary-user-id (key)
+  "The primary user ID for KEY (human-readable).
+DO NOT USE this ID for selecting recipients.  It is probably not
+unique."
+  (list 'car (list 'aref key 0)))
+
+(defmacro gpg-key-user-ids (key)
+  "A list of additional user IDs for KEY (human-readable).
+DO NOT USE these IDs for selecting recipients.  They are probably not
+unique."
+  (list 'cdr (list 'aref key 0)))
+
+(defmacro gpg-key-id (key)
+  "The key ID of KEY.
+DO NOT USE this ID for selecting recipients.  It is not guaranteed to
+be unique."
+  (list 'aref key 1))
+
+(defun gpg-short-key-id (key)
+  "The short key ID of KEY."
+  (let* ((id (gpg-key-id key))
+        (len (length id)))
+    (if (> len 8)
+       (substring id (- len 8))
+      id)))
+
+(defmacro gpg-key-unique-id (key)
+  "A non-standard ID of KEY which is only valid locally.
+This ID can be used to specify recipients in a safe manner.  Note,
+even this ID might not be unique unless GnuPG is used."
+  (list 'aref key 2))
+
+(defmacro gpg-key-unique-id-list (key-list)
+  "Like `gpg-key-unique-id', but operate on a list."
+  `(mapcar (lambda (key) (gpg-key-unique-id key)) 
+          ,key-list))
+
+(defmacro gpg-key-length (key)
+  "Returns the key length."
+  (list 'aref key 3))
+
+(defmacro gpg-key-algorithm (key)
+  "The encryption algorithm used by KEY.
+One of the symbols `rsa', `rsa-encrypt', `rsa-sign', `elgamal',
+`elgamal-encrypt', `dsa'."
+  (list 'aref key 4))
+
+(defmacro gpg-key-creation-date (key)
+  "A string with the creation date of KEY in ISO format."
+  (list 'aref key 5))
+
+(defmacro gpg-key-expire-date (key)
+  "A string with the expiration date of KEY in ISO format."
+  (list 'aref key 6))
+
+(defmacro gpg-key-validity (key)
+  "The calculated validity of KEY.  
+One of the symbols `not-known', `disabled', `revoked', `expired',
+`undefined', `trust-none', `trust-marginal', `trust-full',
+`trust-ultimate' (see the GnuPG documentation for details)."
+ (list 'aref key 7))
+
+(defmacro gpg-key-trust (key)
+  "The assigned trust for KEY.  
+One of the symbols `not-known', `undefined', `trust-none',
+`trust-marginal', `trust-full' (see the GnuPG
+documentation for details)."
+  (list 'aref key 8))
+
+(defun gpg-key-lessp (a b)
+  "Returns t if primary user ID of A is less than B."
+  (string-lessp (gpg-key-primary-user-id a) (gpg-key-primary-user-id b) ))
+
+;;; Accessing the key database:
+
+;; Internal functions:
+
+(defmacro gpg-key-list-keys-skip-field ()
+  '(search-forward ":" eol 'move))
+
+(defmacro gpg-key-list-keys-get-field ()
+  '(buffer-substring (point) (if (gpg-key-list-keys-skip-field) 
+                                (1- (point)) 
+                              eol)))
+(defmacro gpg-key-list-keys-string-field ()
+  '(gpg-key-list-keys-get-field))
+
+(defmacro gpg-key-list-keys-read-field ()
+  (let ((field (make-symbol "field")))
+    `(let ((,field (gpg-key-list-keys-get-field)))
+       (if (equal (length ,field) 0)
+          nil
+        (read ,field)))))
+
+(defun gpg-key-list-keys-parse-line ()
+  "Parse the line in the current buffer and return a vector of fields."
+  (let* ((eol (gpg-point-at-eol))
+        (v (if (eolp)
+               nil
+             (vector
+              (gpg-key-list-keys-read-field) ; type
+              (gpg-key-list-keys-get-field) ; trust
+              (gpg-key-list-keys-read-field) ; key length
+              (gpg-key-list-keys-read-field) ; algorithm
+              (gpg-key-list-keys-get-field) ; key ID
+              (gpg-key-list-keys-get-field) ; creation data
+              (gpg-key-list-keys-get-field) ; expire
+              (gpg-key-list-keys-get-field) ; unique (local) ID
+              (gpg-key-list-keys-get-field) ; ownertrust
+              (gpg-key-list-keys-string-field) ; user ID
+              ))))
+    (if (eolp)
+       (when v
+         (forward-char 1))
+      (error "Too many fields in GnuPG key database"))
+    v))
+
+(defconst gpg-pubkey-algo-alist
+  '((1 . rsa)
+    (2 . rsa-encrypt-only)
+    (3 . rsa-sign-only)
+    (16 . elgamal-encrypt-only)
+    (17 . dsa)
+    (20 . elgamal))
+  "Alist mapping OpenPGP public key algorithm numbers to symbols.")
+
+(defconst gpg-trust-alist
+  '((?- . not-known)
+    (?o . not-known)
+    (?d . disabled)
+    (?r . revoked)
+    (?e . expired)
+    (?q . trust-undefined)
+    (?n . trust-none)
+    (?m . trust-marginal)
+    (?f . trust-full)
+    (?u . trust-ultimate))
+  "Alist mapping GnuPG trust value short forms to long symbols.")
+
+(defconst gpg-unabbrev-trust-alist
+  '(("TRUST_UNDEFINED" . trust-undefined)
+    ("TRUST_NEVER"     . trust-none)
+    ("TRUST_MARGINAL"  . trust-marginal)
+    ("TRUST_FULLY"     . trust-full)
+    ("TRUST_ULTIMATE"  . trust-ultimate))
+  "Alist mapping capitalized GnuPG trust values to long symbols.")
+
+(defmacro gpg-key-list-keys-in-buffer-store ()
+  '(when primary-user-id
+     (sort user-id 'string-lessp)
+     (push (gpg-key-make (cons primary-user-id  user-id)
+                        key-id unique-id key-length
+                        algorithm creation-date 
+                        expire-date validity trust)
+          key-list)))
+
+(defun gpg-key-list-keys-in-buffer (&optional buffer)
+  "Return a list of keys for BUFFER.
+If BUFFER is omitted, use current buffer."
+  (with-current-buffer (if buffer buffer (current-buffer))
+    (goto-char (point-min))
+    ;; Skip key ring filename written by GnuPG.
+    (search-forward "\n---------------------------\n" nil t)
+    ;; Loop over all lines in buffer and analyze them.
+    (let (primary-user-id user-id key-id unique-id ; current key components
+          key-length algorithm creation-date expire-date validity trust
+         line                          ; fields in current line
+         key-list)                     ; keys gather so far
+    
+      (while (setq line (gpg-key-list-keys-parse-line))
+       (cond
+        ;; Public or secret key.
+        ((memq (aref line 0) '(pub sec))
+         ;; Store previous key, if any.
+         (gpg-key-list-keys-in-buffer-store)
+         ;; Record field values.
+         (setq primary-user-id (aref line 9))
+         (setq user-id nil)
+         (setq key-id (aref line 4)) 
+         ;; We use the key ID if no unique ID is available.
+         (setq unique-id (if (> (length (aref line 7)) 0)
+                             (concat "#" (aref line 7))
+                           (concat "0x" key-id)))
+         (setq key-length (aref line 2))
+         (setq algorithm (assq (aref line 3) gpg-pubkey-algo-alist))
+         (if algorithm
+             (setq algorithm (cdr algorithm))
+           (error "Unknown algorithm %s" (aref line 3)))
+         (setq creation-date (if (> (length (aref line 5)) 0)
+                                 (aref line 5)))
+         (setq expire-date (if (> (length (aref line 6)) 0)
+                               (aref line 6)))
+         (setq validity (assq (aref (aref line 1) 0) gpg-trust-alist))
+         (if validity
+             (setq validity (cdr validity))
+           (error "Unknown validity specification %S" (aref line 1)))
+         (setq trust (assq (aref (aref line 8) 0) gpg-trust-alist))
+         (if trust
+             (setq trust (cdr trust))
+           (error "Unknown trust specification %S" (aref line 8))))
+       
+        ;; Additional user ID
+        ((eq 'uid (aref line 0))
+         (setq user-id (cons (aref line 9) user-id)))
+        
+        ;; Subkeys are ignored for now.
+        ((memq (aref line 0) '(sub ssb))
+         t)
+        (t (error "Unknown record type %S" (aref line 0)))))
+
+      ;; Store the key retrieved last.
+      (gpg-key-list-keys-in-buffer-store)
+      ;; Sort the keys according to the primary user ID.
+      (sort key-list 'gpg-key-lessp))))
+
+(defun gpg-key-list-keyspec (command &optional keyspec stderr ignore-error)
+  "Insert the output of COMMAND before point in current buffer."
+  (let* ((cmd (gpg-exec-path command))
+        (key (if (equal keyspec "") nil keyspec))
+        (args (gpg-build-arg-list (cdr command) `((key-id . ,key))))
+        exit-status)
+    (setq exit-status 
+         (apply 'call-process-region 
+                (point-min) (point-min) ; no data
+                cmd
+                nil                    ; don't delete
+                (if stderr t '(t nil))
+                nil                    ; don't display
+                args))
+    (unless (or ignore-error (equal exit-status 0))
+      (error "GnuPG command exited unsuccessfully"))))
+  
+  
+(defun gpg-key-list-keyspec-parse (command &optional keyspec)
+  "Return a list of keys matching KEYSPEC.
+COMMAND is used to obtain the key list.  The usual substring search
+for keys is performed."
+  (with-temp-buffer 
+    (buffer-disable-undo)
+    (gpg-key-list-keyspec command keyspec)
+    (gpg-key-list-keys-in-buffer)))
+
+;;;###autoload
+(defun gpg-key-list-keys (&optional keyspec)
+  "A list of public keys matching KEYSPEC.
+The usual substring search for keys is performed."
+  (gpg-key-list-keyspec-parse gpg-command-key-public-ring keyspec))
+
+;;;###autoload
+(defun gpg-key-list-secret-keys (&optional keyspec)
+  "A list of secret keys matching KEYSPEC.
+The usual substring search for keys is performed."
+  (gpg-key-list-keyspec-parse gpg-command-key-secret-ring keyspec))
+
+;;;###autoload
+(defun gpg-key-insert-public-key (key)
+  "Inserts the public key(s) matching KEYSPEC.
+The ASCII-armored key is inserted before point into current buffer."
+  (gpg-key-list-keyspec gpg-command-key-export key))
+
+;;;###autoload
+(defun gpg-key-insert-information (key)
+  "Insert human-readable information (including fingerprint) on KEY.
+Insertion takes place in current buffer before point."
+  (gpg-key-list-keyspec gpg-command-key-verify key))
+
+;;;###autoload
+(defun gpg-key-retrieve (key)
+  "Fetch KEY from default key server.
+KEY is a key ID or a list of key IDs.  Status information about this
+operation is inserted into the current buffer before point."
+  (gpg-key-list-keyspec gpg-command-key-retrieve key t t))
+
+;;;###autoload
+(defun gpg-key-add-to-ring (key result)
+  "Adds key in buffer KEY to the GnuPG key ring.
+Human-readable information on the RESULT is stored in buffer RESULT
+before point.")
+
+(provide 'gpg)
+
+;;; gpg.el ends here
diff --git a/contrib/hashcash.el b/contrib/hashcash.el
new file mode 100644 (file)
index 0000000..84dfcae
--- /dev/null
@@ -0,0 +1,207 @@
+;;; hashcash.el --- Add hashcash payments to email
+
+;; Copyright (C) 2003 Free Software Foundation
+;; Copyright (C) 1997--2002 Paul E. Foley
+
+;; Maintainer: Paul Foley <mycroft@actrix.gen.nz>
+;; Keywords: mail, hashcash
+
+;; Released under the GNU General Public License
+;;   (http://www.gnu.org/licenses/gpl.html)
+
+;;; Commentary:
+
+;; The hashcash binary is at http://www.cypherspace.org/hashcash/
+;;
+;; Call mail-add-payment to add a hashcash payment to a mail message
+;; in the current buffer.
+;;
+;; To automatically add payments to all outgoing mail:
+;;    (add-hook 'message-send-hook 'mail-add-payment)
+
+;;; Code:
+
+(eval-and-compile
+ (autoload 'executable-find "executable"))
+
+(defcustom hashcash-default-payment 0
+  "*The default number of bits to pay to unknown users.
+If this is zero, no payment header will be generated.
+See `hashcash-payment-alist'."
+  :type 'integer)
+
+(defcustom hashcash-payment-alist '()
+  "*An association list mapping email addresses to payment amounts.
+Elements may consist of (ADDR AMOUNT) or (ADDR STRING AMOUNT), where
+ADDR is the email address of the intended recipient and AMOUNT is
+the value of hashcash payment to be made to that user.  STRING, if
+present, is the string to be hashed; if not present ADDR will be used.")
+
+(defcustom hashcash-default-accept-payment 10
+  "*The default minimum number of bits to accept on incoming payments."
+  :type 'integer)
+
+(defcustom hashcash-accept-resources `((,user-mail-address nil))
+  "*An association list mapping hashcash resources to payment amounts.
+Resources named here are to be accepted in incoming payments.  If the
+corresponding AMOUNT is NIL, the value of `hashcash-default-accept-payment'
+is used instead.")
+
+(defcustom hashcash-path (executable-find "hashcash")
+  "*The path to the hashcash binary.")
+
+(defcustom hashcash-double-spend-database "hashcash.db"
+  "*The path to the double-spending database.")
+
+(defcustom hashcash-in-news nil
+  "*Specifies whether or not hashcash payments should be made to newsgroups."
+  :type 'boolean)
+
+(require 'mail-utils)
+
+(eval-and-compile
+ (if (fboundp 'point-at-bol)
+     (defalias 'hashcash-point-at-bol 'point-at-bol)
+   (defalias 'hashcash-point-at-bol 'line-beginning-position))
+
+ (if (fboundp 'point-at-eol)
+     (defalias 'hashcash-point-at-eol 'point-at-eol)
+   (defalias 'hashcash-point-at-eol 'line-end-position)))
+
+(defun hashcash-strip-quoted-names (addr)
+  (setq addr (mail-strip-quoted-names addr))
+  (if (and addr (string-match "\\`\\([^+@]+\\)\\+[^@]*\\(@.+\\)" addr))
+      (concat (match-string 1 addr) (match-string 2 addr))
+    addr))
+
+(defun hashcash-payment-required (addr)
+  "Return the hashcash payment value required for the given address."
+  (let ((val (assoc addr hashcash-payment-alist)))
+    (or (nth 2 val) (nth 1 val) hashcash-default-payment)))
+
+(defun hashcash-payment-to (addr)
+  "Return the string with which hashcash payments should collide."
+  (let ((val (assoc addr hashcash-payment-alist)))
+    (or (nth 1 val) (nth 0 val) addr)))
+
+(defun hashcash-generate-payment (str val)
+  "Generate a hashcash payment by finding a VAL-bit collison on STR."
+  (if (> val 0)
+      (save-excursion
+       (set-buffer (get-buffer-create " *hashcash*"))
+       (erase-buffer)
+       (call-process hashcash-path nil t nil
+                     "-m" "-q" "-b" (number-to-string val) str)
+       (goto-char (point-min))
+       (buffer-substring (hashcash-point-at-bol) (hashcash-point-at-eol)))
+    nil))
+
+(defun hashcash-check-payment (token str val)
+  "Check the validity of a hashcash payment."
+  (zerop (call-process hashcash-path nil nil nil "-c"
+                      "-d" "-f" hashcash-double-spend-database
+                      "-b" (number-to-string val)
+                      "-r" str
+                      token)))
+
+(defun hashcash-version (token)
+  "Find the format version of a hashcash token."
+  ;; Version 1.2 looks like n:yymmdd:rrrrr:xxxxxxxxxxxxxxxx
+  ;;   This carries its own version number embedded in the token,
+  ;;   so no further format number changes should be necessary
+  ;;   in the X-Payment header.
+  ;;
+  ;; Version 1.1 looks like yymmdd:rrrrr:xxxxxxxxxxxxxxxx
+  ;;   You need to upgrade your hashcash binary.
+  ;;
+  ;; Version 1.0 looked like nnnnnrrrrrxxxxxxxxxxxxxxxx
+  ;;   This is no longer supported.
+  (cond ((equal (aref token 1) ?:) 1.2)
+       ((equal (aref token 6) ?:) 1.1)
+       (t (error "Unknown hashcash format version"))))
+
+;;;###autoload
+(defun hashcash-insert-payment (arg)
+  "Insert X-Payment and X-Hashcash headers with a payment for ARG"
+  (interactive "sPay to: ")
+  (let ((pay (hashcash-generate-payment (hashcash-payment-to arg)
+                                       (hashcash-payment-required arg))))
+    (when pay
+;      (insert-before-markers "X-Payment: hashcash "
+;                           (number-to-string (hashcash-version pay)) " "
+;                           pay "\n")
+      (insert-before-markers "X-Hashcash: " pay "\n"))))
+
+;;;###autoload
+(defun hashcash-verify-payment (token &optional resource amount)
+  "Verify a hashcash payment"
+  (let ((key (if (< (hashcash-version token) 1.2)
+                (nth 1 (split-string token ":"))
+                (nth 2 (split-string token ":")))))
+    (cond ((null resource)
+          (let ((elt (assoc key hashcash-accept-resources)))
+            (and elt (hashcash-check-payment token (car elt)
+                       (or (cadr elt) hashcash-default-accept-payment)))))
+         ((equal token key)
+          (hashcash-check-payment token resource
+                               (or amount hashcash-default-accept-payment)))
+         (t nil))))
+
+;;;###autoload
+(defun mail-add-payment (&optional arg)
+  "Add X-Payment: and X-Hashcash: headers with a hashcash payment
+for each recipient address.  Prefix arg sets default payment temporarily."
+  (interactive "P")
+  (let ((hashcash-default-payment (if arg (prefix-numeric-value arg)
+                                   hashcash-default-payment))
+       (addrlist nil))
+    (save-excursion
+      (save-restriction
+       (goto-char (point-min))
+       (search-forward mail-header-separator)
+       (beginning-of-line)
+       (narrow-to-region (point-min) (point))
+       (let ((to (hashcash-strip-quoted-names (mail-fetch-field "To" nil t)))
+             (cc (hashcash-strip-quoted-names (mail-fetch-field "Cc" nil t)))
+             (ng (hashcash-strip-quoted-names (mail-fetch-field "Newsgroups"
+                                                                nil t))))
+         (when to
+           (setq addrlist (split-string to ",[ \t\n]*")))
+         (when cc
+           (setq addrlist (nconc addrlist (split-string cc ",[ \t\n]*"))))
+         (when (and hashcash-in-news ng)
+           (setq addrlist (nconc addrlist (split-string ng ",[ \t\n]*")))))
+       (when addrlist
+         (mapcar #'hashcash-insert-payment addrlist))))) ; mapc
+  t)
+
+;;;###autoload
+(defun mail-check-payment (&optional arg)
+  "Look for a valid X-Payment: or X-Hashcash: header.
+Prefix arg sets default accept amount temporarily."
+  (interactive "P")
+  (let ((hashcash-default-accept-payment (if arg (prefix-numeric-value arg)
+                                          hashcash-default-accept-payment))
+       (version (hashcash-version (hashcash-generate-payment "x" 1))))
+    (save-excursion
+      (goto-char (point-min))
+      (search-forward "\n\n")
+      (beginning-of-line)
+      (let ((end (point))
+           (ok nil))
+       (goto-char (point-min))
+       (while (and (not ok) (search-forward "X-Payment: hashcash " end t))
+         (let ((value (split-string
+                         (buffer-substring (point) (hashcash-point-at-eol))
+                         " ")))
+           (when (equal (car value) (number-to-string version))
+             (setq ok (hashcash-verify-payment (cadr value))))))
+       (goto-char (point-min))
+       (while (and (not ok) (search-forward "X-Hashcash: " end t))
+         (setq ok (hashcash-verify-payment
+                   (buffer-substring (point) (hashcash-point-at-eol)))))
+       (when ok
+         (message "Payment valid"))
+       ok))))
+
+(provide 'hashcash)
diff --git a/contrib/md5.el b/contrib/md5.el
new file mode 100644 (file)
index 0000000..a036819
--- /dev/null
@@ -0,0 +1,409 @@
+;;; md5.el -- MD5 Message Digest Algorithm
+;;; Gareth Rees <gdr11@cl.cam.ac.uk>
+
+;; LCD Archive Entry:
+;; md5|Gareth Rees|gdr11@cl.cam.ac.uk|
+;; MD5 cryptographic message digest algorithm|
+;; 13-Nov-95|1.0|~/misc/md5.el.Z|
+
+;;; Details: ------------------------------------------------------------------
+
+;; This is a direct translation into Emacs LISP of the reference C
+;; implementation of the MD5 Message-Digest Algorithm written by RSA
+;; Data Security, Inc.
+;;
+;; The algorithm takes a message (that is, a string of bytes) and
+;; computes a 16-byte checksum or "digest" for the message.  This digest
+;; is supposed to be cryptographically strong in the sense that if you
+;; are given a 16-byte digest D, then there is no easier way to
+;; construct a message whose digest is D than to exhaustively search the
+;; space of messages.  However, the robustness of the algorithm has not
+;; been proven, and a similar algorithm (MD4) was shown to be unsound,
+;; so treat with caution!
+;;
+;; The C algorithm uses 32-bit integers; because GNU Emacs
+;; implementations provide 28-bit integers (with 24-bit integers on
+;; versions prior to 19.29), the code represents a 32-bit integer as the
+;; cons of two 16-bit integers.  The most significant word is stored in
+;; the car and the least significant in the cdr.  The algorithm requires
+;; at least 17 bits of integer representation in order to represent the
+;; carry from a 16-bit addition.
+
+;;; Usage: --------------------------------------------------------------------
+
+;; To compute the MD5 Message Digest for a message M (represented as a
+;; string or as a vector of bytes), call
+;;
+;;   (md5-encode M)
+;;
+;; which returns the message digest as a vector of 16 bytes.  If you
+;; need to supply the message in pieces M1, M2, ... Mn, then call
+;;
+;;   (md5-init)
+;;   (md5-update M1)
+;;   (md5-update M2)
+;;   ...
+;;   (md5-update Mn)
+;;   (md5-final)
+
+;;; Copyright and licence: ----------------------------------------------------
+
+;; Copyright (C) 1995 by Gareth Rees
+;; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
+;;
+;; md5.el is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by the
+;; Free Software Foundation; either version 2, or (at your option) any
+;; later version.
+;;
+;; md5.el is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+;; for more details.
+;;
+;; The original copyright notice is given below, as required by the
+;; licence for the original code.  This code is distributed under *both*
+;; RSA's original licence and the GNU General Public Licence.  (There
+;; should be no problems, as the former is more liberal than the
+;; latter).
+
+;;; Original copyright notice: ------------------------------------------------
+
+;; Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.
+;;
+;; License to copy and use this software is granted provided that it is
+;; identified as the "RSA Data Security, Inc. MD5 Message- Digest
+;; Algorithm" in all material mentioning or referencing this software or
+;; this function.
+;;
+;; License is also granted to make and use derivative works provided
+;; that such works are identified as "derived from the RSA Data
+;; Security, Inc. MD5 Message-Digest Algorithm" in all material
+;; mentioning or referencing the derived work.
+;;
+;; RSA Data Security, Inc. makes no representations concerning either
+;; the merchantability of this software or the suitability of this
+;; software for any particular purpose.  It is provided "as is" without
+;; express or implied warranty of any kind.
+;;
+;; These notices must be retained in any copies of any part of this
+;; documentation and/or software.
+
+;;; Code:
+
+(defvar md5-program "md5sum"
+  "*Program that reads a message on its standard input and writes an
+MD5 digest on its output.")
+
+(defvar md5-maximum-internal-length 4096
+  "*The maximum size of a piece of data that should use the MD5 routines
+written in lisp.  If a message exceeds this, it will be run through an
+external filter for processing.  Also see the `md5-program' variable.
+This variable has no effect if you call the md5-init|update|final
+functions - only used by the `md5' function's simpler interface.")
+
+(defvar md5-bits (make-vector 4 0)
+  "Number of bits handled, modulo 2^64.
+Represented as four 16-bit numbers, least significant first.")
+(defvar md5-buffer (make-vector 4 '(0 . 0))
+  "Scratch buffer (four 32-bit integers).")
+(defvar md5-input (make-vector 64 0)
+  "Input buffer (64 bytes).")
+
+(defun md5-unhex (x)
+  (if (> x ?9)
+      (if (>= x ?a)
+         (+ 10 (- x ?a))
+       (+ 10 (- x ?A)))
+    (- x ?0)))
+
+(defun md5-encode (message)
+  "Encodes MESSAGE using the MD5 message digest algorithm.
+MESSAGE must be a string or an array of bytes.
+Returns a vector of 16 bytes containing the message digest."
+  (if (<= (length message) md5-maximum-internal-length)
+      (progn
+       (md5-init)
+       (md5-update message)
+       (md5-final))
+    (save-excursion
+      (set-buffer (get-buffer-create " *md5-work*"))
+      (erase-buffer)
+      (insert message)
+      (call-process-region (point-min) (point-max)
+                          (or shell-file-name "/bin/sh")
+                          t (current-buffer) nil
+                          "-c" md5-program)
+      ;; MD5 digest is 32 chars long
+      ;; mddriver adds a newline to make neaten output for tty
+      ;; viewing, make sure we leave it behind.
+      (let ((data (buffer-substring (point-min) (+ (point-min) 32)))
+           (vec (make-vector 16 0))
+           (ctr 0))
+       (while (< ctr 16)
+         (aset vec ctr (+ (* 16 (md5-unhex (aref data (* ctr 2))))
+                          (md5-unhex (aref data (1+ (* ctr 2))))))
+         (setq ctr (1+ ctr)))))))
+
+(defsubst md5-add (x y)
+  "Return 32-bit sum of 32-bit integers X and Y."
+  (let ((m (+ (car x) (car y)))
+        (l (+ (cdr x) (cdr y))))
+    (cons (logand 65535 (+ m (lsh l -16))) (logand l 65535))))
+
+;; FF, GG, HH and II are basic MD5 functions, providing transformations
+;; for rounds 1, 2, 3 and 4 respectively.  Each function follows this
+;; pattern of computation (where ROTATE(x,y) means rotate 32-bit value x
+;; by y bits to the left):
+;;
+;;   FF(a,b,c,d,x,s,ac) = ROTATE(a + F(b,c,d) + x + ac,s) + b
+;;
+;; so we use the macro `md5-make-step' to construct each one.  The
+;; helper functions F, G, H and I operate on 16-bit numbers; the full
+;; operation splits its inputs, operates on the halves separately and
+;; then puts the results together.
+
+(defsubst md5-F (x y z) (logior (logand x y) (logand (lognot x) z)))
+(defsubst md5-G (x y z) (logior (logand x z) (logand y (lognot z))))
+(defsubst md5-H (x y z) (logxor x y z))
+(defsubst md5-I (x y z) (logxor y (logior x (logand 65535 (lognot z)))))
+
+(defmacro md5-make-step (name func)
+  (`
+   (defun (, name) (a b c d x s ac)
+     (let*
+         ((m1 (+ (car a) ((, func) (car b) (car c) (car d)) (car x) (car ac)))
+          (l1 (+ (cdr a) ((, func) (cdr b) (cdr c) (cdr d)) (cdr x) (cdr ac)))
+          (m2 (logand 65535 (+ m1 (lsh l1 -16))))
+          (l2 (logand 65535 l1))
+          (m3 (logand 65535 (if (> s 15)
+                                (+ (lsh m2 (- s 32)) (lsh l2 (- s 16)))
+                              (+ (lsh m2 s) (lsh l2 (- s 16))))))
+          (l3 (logand 65535 (if (> s 15)
+                                (+ (lsh l2 (- s 32)) (lsh m2 (- s 16)))
+                              (+ (lsh l2 s) (lsh m2 (- s 16)))))))
+       (md5-add (cons m3 l3) b)))))
+
+(md5-make-step md5-FF md5-F)
+(md5-make-step md5-GG md5-G)
+(md5-make-step md5-HH md5-H)
+(md5-make-step md5-II md5-I)
+
+(defun md5-init ()
+  "Initialise the state of the message-digest routines."
+  (aset md5-bits 0 0)
+  (aset md5-bits 1 0)
+  (aset md5-bits 2 0)
+  (aset md5-bits 3 0)
+  (aset md5-buffer 0 '(26437 .  8961))
+  (aset md5-buffer 1 '(61389 . 43913))
+  (aset md5-buffer 2 '(39098 . 56574))
+  (aset md5-buffer 3 '( 4146 . 21622)))
+
+(defun md5-update (string)
+  "Update the current MD5 state with STRING (an array of bytes)."
+  (let ((len (length string))
+        (i 0)
+        (j 0))
+    (while (< i len)
+      ;; Compute number of bytes modulo 64
+      (setq j (% (/ (aref md5-bits 0) 8) 64))
+
+      ;; Store this byte (truncating to 8 bits to be sure)
+      (aset md5-input j (logand 255 (aref string i)))
+
+      ;; Update number of bits by 8 (modulo 2^64)
+      (let ((c 8) (k 0))
+        (while (and (> c 0) (< k 4))
+          (let ((b (aref md5-bits k)))
+            (aset md5-bits k (logand 65535 (+ b c)))
+            (setq c (if (> b (- 65535 c)) 1 0)
+                  k (1+ k)))))
+
+      ;; Increment number of bytes processed
+      (setq i (1+ i))
+
+      ;; When 64 bytes accumulated, pack them into sixteen 32-bit
+      ;; integers in the array `in' and then tranform them.
+      (if (= j 63)
+          (let ((in (make-vector 16 (cons 0 0)))
+                (k 0)
+                (kk 0))
+            (while (< k 16)
+              (aset in k (md5-pack md5-input kk))
+              (setq k (+ k 1) kk (+ kk 4)))
+            (md5-transform in))))))
+
+(defun md5-pack (array i)
+  "Pack the four bytes at ARRAY reference I to I+3 into a 32-bit integer."
+  (cons (+ (lsh (aref array (+ i 3)) 8) (aref array (+ i 2)))
+        (+ (lsh (aref array (+ i 1)) 8) (aref array (+ i 0)))))
+
+(defun md5-byte (array n b)
+  "Unpack byte B (0 to 3) from Nth member of ARRAY of 32-bit integers."
+  (let ((e (aref array n)))
+    (cond ((eq b 0) (logand 255 (cdr e)))
+          ((eq b 1) (lsh (cdr e) -8))
+          ((eq b 2) (logand 255 (car e)))
+          ((eq b 3) (lsh (car e) -8)))))
+
+(defun md5-final ()
+  (let ((in (make-vector 16 (cons 0 0)))
+        (j 0)
+        (digest (make-vector 16 0))
+        (padding))
+
+    ;; Save the number of bits in the message
+    (aset in 14 (cons (aref md5-bits 1) (aref md5-bits 0)))
+    (aset in 15 (cons (aref md5-bits 3) (aref md5-bits 2)))
+
+    ;; Compute number of bytes modulo 64
+    (setq j (% (/ (aref md5-bits 0) 8) 64))
+
+    ;; Pad out computation to 56 bytes modulo 64
+    (setq padding (make-vector (if (< j 56) (- 56 j) (- 120 j)) 0))
+    (aset padding 0 128)
+    (md5-update padding)
+
+    ;; Append length in bits and transform
+    (let ((k 0) (kk 0))
+      (while (< k 14)
+        (aset in k (md5-pack md5-input kk))
+        (setq k (+ k 1) kk (+ kk 4))))
+    (md5-transform in)
+
+    ;; Store the results in the digest
+    (let ((k 0) (kk 0))
+      (while (< k 4)
+        (aset digest (+ kk 0) (md5-byte md5-buffer k 0))
+        (aset digest (+ kk 1) (md5-byte md5-buffer k 1))
+        (aset digest (+ kk 2) (md5-byte md5-buffer k 2))
+        (aset digest (+ kk 3) (md5-byte md5-buffer k 3))
+        (setq k (+ k 1) kk (+ kk 4))))
+
+    ;; Return digest
+    digest))
+
+;; It says in the RSA source, "Note that if the Mysterious Constants are
+;; arranged backwards in little-endian order and decrypted with the DES
+;; they produce OCCULT MESSAGES!"  Security through obscurity?
+
+(defun md5-transform (in)
+  "Basic MD5 step. Transform md5-buffer based on array IN."
+  (let ((a (aref md5-buffer 0))
+        (b (aref md5-buffer 1))
+        (c (aref md5-buffer 2))
+        (d (aref md5-buffer 3)))
+    (setq
+     a (md5-FF a b c d (aref in  0)  7 '(55146 . 42104))
+     d (md5-FF d a b c (aref in  1) 12 '(59591 . 46934))
+     c (md5-FF c d a b (aref in  2) 17 '( 9248 . 28891))
+     b (md5-FF b c d a (aref in  3) 22 '(49597 . 52974))
+     a (md5-FF a b c d (aref in  4)  7 '(62844 .  4015))
+     d (md5-FF d a b c (aref in  5) 12 '(18311 . 50730))
+     c (md5-FF c d a b (aref in  6) 17 '(43056 . 17939))
+     b (md5-FF b c d a (aref in  7) 22 '(64838 . 38145))
+     a (md5-FF a b c d (aref in  8)  7 '(27008 . 39128))
+     d (md5-FF d a b c (aref in  9) 12 '(35652 . 63407))
+     c (md5-FF c d a b (aref in 10) 17 '(65535 . 23473))
+     b (md5-FF b c d a (aref in 11) 22 '(35164 . 55230))
+     a (md5-FF a b c d (aref in 12)  7 '(27536 .  4386))
+     d (md5-FF d a b c (aref in 13) 12 '(64920 . 29075))
+     c (md5-FF c d a b (aref in 14) 17 '(42617 . 17294))
+     b (md5-FF b c d a (aref in 15) 22 '(18868 .  2081))
+     a (md5-GG a b c d (aref in  1)  5 '(63006 .  9570))
+     d (md5-GG d a b c (aref in  6)  9 '(49216 . 45888))
+     c (md5-GG c d a b (aref in 11) 14 '( 9822 . 23121))
+     b (md5-GG b c d a (aref in  0) 20 '(59830 . 51114))
+     a (md5-GG a b c d (aref in  5)  5 '(54831 .  4189))
+     d (md5-GG d a b c (aref in 10)  9 '(  580 .  5203))
+     c (md5-GG c d a b (aref in 15) 14 '(55457 . 59009))
+     b (md5-GG b c d a (aref in  4) 20 '(59347 . 64456))
+     a (md5-GG a b c d (aref in  9)  5 '( 8673 . 52710))
+     d (md5-GG d a b c (aref in 14)  9 '(49975 .  2006))
+     c (md5-GG c d a b (aref in  3) 14 '(62677 .  3463))
+     b (md5-GG b c d a (aref in  8) 20 '(17754 .  5357))
+     a (md5-GG a b c d (aref in 13)  5 '(43491 . 59653))
+     d (md5-GG d a b c (aref in  2)  9 '(64751 . 41976))
+     c (md5-GG c d a b (aref in  7) 14 '(26479 .   729))
+     b (md5-GG b c d a (aref in 12) 20 '(36138 . 19594))
+     a (md5-HH a b c d (aref in  5)  4 '(65530 . 14658))
+     d (md5-HH d a b c (aref in  8) 11 '(34673 . 63105))
+     c (md5-HH c d a b (aref in 11) 16 '(28061 . 24866))
+     b (md5-HH b c d a (aref in 14) 23 '(64997 . 14348))
+     a (md5-HH a b c d (aref in  1)  4 '(42174 . 59972))
+     d (md5-HH d a b c (aref in  4) 11 '(19422 . 53161))
+     c (md5-HH c d a b (aref in  7) 16 '(63163 . 19296))
+     b (md5-HH b c d a (aref in 10) 23 '(48831 . 48240))
+     a (md5-HH a b c d (aref in 13)  4 '(10395 . 32454))
+     d (md5-HH d a b c (aref in  0) 11 '(60065 . 10234))
+     c (md5-HH c d a b (aref in  3) 16 '(54511 . 12421))
+     b (md5-HH b c d a (aref in  6) 23 '( 1160 .  7429))
+     a (md5-HH a b c d (aref in  9)  4 '(55764 . 53305))
+     d (md5-HH d a b c (aref in 12) 11 '(59099 . 39397))
+     c (md5-HH c d a b (aref in 15) 16 '( 8098 . 31992))
+     b (md5-HH b c d a (aref in  2) 23 '(50348 . 22117))
+     a (md5-II a b c d (aref in  0)  6 '(62505 .  8772))
+     d (md5-II d a b c (aref in  7) 10 '(17194 . 65431))
+     c (md5-II c d a b (aref in 14) 15 '(43924 .  9127))
+     b (md5-II b c d a (aref in  5) 21 '(64659 . 41017))
+     a (md5-II a b c d (aref in 12)  6 '(25947 . 22979))
+     d (md5-II d a b c (aref in  3) 10 '(36620 . 52370))
+     c (md5-II c d a b (aref in 10) 15 '(65519 . 62589))
+     b (md5-II b c d a (aref in  1) 21 '(34180 . 24017))
+     a (md5-II a b c d (aref in  8)  6 '(28584 . 32335))
+     d (md5-II d a b c (aref in 15) 10 '(65068 . 59104))
+     c (md5-II c d a b (aref in  6) 15 '(41729 . 17172))
+     b (md5-II b c d a (aref in 13) 21 '(19976 .  4513))
+     a (md5-II a b c d (aref in  4)  6 '(63315 . 32386))
+     d (md5-II d a b c (aref in 11) 10 '(48442 . 62005))
+     c (md5-II c d a b (aref in  2) 15 '(10967 . 53947))
+     b (md5-II b c d a (aref in  9) 21 '(60294 . 54161)))
+
+    (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a))
+    (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b))
+    (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c))
+    (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Here begins the merger with the XEmacs API and the md5.el from the URL
+;;; package.  Courtesy wmperry@spry.com
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun md5 (object &optional start end)
+  "Return the MD5 (a secure message digest algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments START and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+  (let ((buffer nil))
+    (unwind-protect
+       (save-excursion
+         (setq buffer (generate-new-buffer " *md5-work*"))
+         (set-buffer buffer)
+         (cond
+          ((bufferp object)
+           (insert-buffer-substring object start end))
+          ((stringp object)
+           (insert (if (or start end)
+                       (substring object start end)
+                     object)))
+          (t nil))
+         (prog1
+             (if (<= (point-max) md5-maximum-internal-length)
+                 (mapconcat
+                  (function (lambda (node) (format "%02x" node)))
+                  (md5-encode (buffer-string))
+                  "")
+               (call-process-region (point-min) (point-max)
+                                    (or shell-file-name "/bin/sh")
+                                    t buffer nil
+                                    "-c" md5-program)
+               ;; MD5 digest is 32 chars long
+               ;; mddriver adds a newline to make neaten output for tty
+               ;; viewing, make sure we leave it behind.
+               (buffer-substring (point-min) (+ (point-min) 32)))
+           (kill-buffer buffer)))
+      (and buffer (kill-buffer buffer) nil))))
+
+(provide 'md5)
+
+;;; md5.el ends here
diff --git a/contrib/nnir.el b/contrib/nnir.el
new file mode 100644 (file)
index 0000000..0a2347b
--- /dev/null
@@ -0,0 +1,1559 @@
+;;; nnir.el --- search mail with various search engines -*- coding: iso-8859-1 -*-
+;; Copyright (C) 1998 Kai Großjohann
+
+;; Author: Kai Großjohann <grossjohann@ls6.cs.uni-dortmund.de>
+;; Keywords: news, mail, searching, ir, glimpse, wais, hyrex
+
+;; This file is not part of GNU Emacs.
+
+;; This is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The most recent version of this can always be fetched from the Gnus
+;; CVS repository.  See http://www.gnus.org/ for more information.
+
+;; This code is still in the development stage but I'd like other
+;; people to have a look at it.  Please do not hesitate to contact me
+;; with your ideas.
+
+;; What does it do?  Well, it allows you to index your mail using some
+;; search engine (freeWAIS-sf, Glimpse and others -- see later),
+;; then type `G G' in the Group buffer and issue a query to the search
+;; engine.  You will then get a buffer which shows all articles
+;; matching the query, sorted by Retrieval Status Value (score).
+
+;; When looking at the retrieval result (in the Summary buffer) you
+;; can type `G T' (aka M-x gnus-summary-nnir-goto-thread RET) on an
+;; article.  You will be teleported into the group this article came
+;; from, showing the thread this article is part of.  (See below for
+;; restrictions.)
+
+;; The Lisp installation is simple: just put this file on your
+;; load-path, byte-compile it, and load it from ~/.gnus or something.
+;; This will install a new command `G G' in your Group buffer for
+;; searching your mail.  Note that you also need to configure a number
+;; of variables, as described below.
+
+;; Restrictions:
+;;
+;; * If you don't use HyREX as your search engine, this expects that
+;;   you use nnml or another one-file-per-message backend, because the
+;;   others doesn't support nnfolder.
+;; * It can only search the mail backend's which are supported by one
+;;   search engine, because of different query languages.
+;; * There are restrictions to the Glimpse setup.
+;; * There are restrictions to the Wais setup.
+;; * There are restrictions to the imap setup.
+;; * gnus-summary-nnir-goto-thread: Fetches whole group first, before
+;;   limiting to the right articles.  This is much too slow, of
+;;   course.  May issue a query for number of articles to fetch; you
+;;   must accept the default of all articles at this point or things
+;;   may break.
+
+;; The Lisp setup involves setting a few variables and setting up the
+;; search engine. You can define the variables in the server definition
+;; like this :
+;;   (setq gnus-secondary-select-methods '(
+;;       (nnimap "" (nnimap-address "localhost")
+;;                  (nnir-search-engine hyrex)
+;;                  (nnir-hyrex-additional-switches ("-d" "ddl-nnimap.xml"))
+;;       )))
+;; Or you can define the global ones. The variables set in the mailer-
+;; definition will be used first.
+;; The variable to set is `nnir-search-engine'.  Choose one of the engines
+;; listed in `nnir-engines'.  (Actually `nnir-engines' is an alist,
+;; type `C-h v nnir-engines RET' for more information; this includes
+;; examples for setting `nnir-search-engine', too.)
+;;
+;; The variable nnir-mail-backend isn't used anymore.
+;;
+
+;; You must also set up a search engine.  I'll tell you about the two
+;; search engines currently supported:
+
+;; 1. freeWAIS-sf
+;;
+;; As always with freeWAIS-sf, you need a so-called `format file'.  I
+;; use the following file:
+;;
+;; ,-----
+;; | # Kai's format file for freeWAIS-sf for indexing mails.
+;; | # Each mail is in a file, much like the MH format.
+;; |
+;; | # Document separator should never match -- each file is a document.
+;; | record-sep: /^@this regex should never match@$/
+;; |
+;; | # Searchable fields specification.
+;; |
+;; | region: /^[sS]ubject:/ /^[sS]ubject: */
+;; |         subject "Subject header" stemming TEXT BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^([tT][oO]|[cC][cC]):/ /^([tT][oO]|[cC][cC]): */
+;; |         to "To and Cc headers" SOUNDEX BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^[fF][rR][oO][mM]:/ /^[fF][rR][oO][mM]: */
+;; |         from "From header" SOUNDEX BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^$/
+;; |         stemming TEXT GLOBAL
+;; | end: /^@this regex should never match@$/
+;; `-----
+;;
+;; 1998-07-22: waisindex would dump core on me for large articles with
+;; the above settings.  I used /^$/ as the end regex for the global
+;; field.  That seemed to work okay.
+
+;; There is a Perl module called `WAIS.pm' which is available from
+;; CPAN as well as ls6-ftp.cs.uni-dortmund.de:/pub/wais/Perl.  This
+;; module comes with a nifty tool called `makedb', which I use for
+;; indexing.  Here's my `makedb.conf':
+;;
+;; ,-----
+;; | # Config file for makedb
+;; |
+;; | # Global options
+;; | waisindex = /usr/local/bin/waisindex
+;; | wais_opt  = -stem -t fields
+;; | # `-stem' option necessary when `stemming' is specified for the
+;; | # global field in the *.fmt file
+;; |
+;; | # Own variables
+;; | homedir = /home/kai
+;; |
+;; | # The mail database.
+;; | database        = mail
+;; | files           = `find $homedir/Mail -name \*[0-9] -print`
+;; | dbdir           = $homedir/.wais
+;; | limit           = 100
+;; `-----
+;;
+;; The Lisp setup involves the `nnir-wais-*' variables.  The most
+;; difficult to understand variable is probably
+;; `nnir-wais-remove-prefix'.  Here's what it does: the output of
+;; `waissearch' basically contains the file name and the (full)
+;; directory name.  As Gnus works with group names rather than
+;; directory names, the directory name is transformed into a group
+;; name as follows: first, a prefix is removed from the (full)
+;; directory name, then all `/' are replaced with `.'.  The variable
+;; `nnir-wais-remove-prefix' should contain a regex matching exactly
+;; this prefix.  It defaults to `$HOME/Mail/' (note the trailing
+;; slash).
+
+;; 2. Glimpse
+;;
+;; The code expects you to have one Glimpse index which contains all
+;; your mail files.  The Lisp setup involves setting the
+;; `nnir-glimpse-*' variables.  The most difficult to understand
+;; variable is probably `nnir-glimpse-remove-prefix', it corresponds
+;; to `nnir-wais-remove-prefix', see above.  The `nnir-glimpse-home'
+;; variable should be set to the value of the `-H' option which allows
+;; one to search this Glimpse index.  I have indexed my whole home
+;; directory with Glimpse, so I assume a default of `$HOME'.
+
+;; 3. Namazu
+;;
+;; The Namazu backend requires you to have one directory containing all
+;; index files, this is controlled by the `nnir-namazu-index-directory'
+;; variable.  To function the `nnir-namazu-remove-prefix' variable must
+;; also be correct, see the documentation for `nnir-wais-remove-prefix'
+;; above.
+;;
+;; It is particularly important not to pass any any switches to namazu
+;; that will change the output format.  Good switches to use include
+;; `--sort', `--ascending', `--early' and `--late'.  Refer to the Namazu
+;; documentation for further information on valid switches.
+;;
+;; To index my mail with the `mknmz' program I use the following
+;; configuration file:
+;;
+;; ,----
+;; | package conf;  # Don't remove this line!
+;; |
+;; | # Paths which will not be indexed. Don't use `^' or `$' anchors.
+;; | $EXCLUDE_PATH = "spam|sent";
+;; |
+;; | # Header fields which should be searchable. case-insensitive
+;; | $REMAIN_HEADER = "from|date|message-id|subject";
+;; |
+;; | # Searchable fields. case-insensitive
+;; | $SEARCH_FIELD = "from|date|message-id|subject";
+;; |
+;; | # The max length of a word.
+;; | $WORD_LENG_MAX = 128;
+;; |
+;; | # The max length of a field.
+;; | $MAX_FIELD_LENGTH = 256;
+;; `----
+;;
+;; My mail is stored in the directories ~/Mail/mail/, ~/Mail/lists/ and
+;; ~/Mail/archive/, so to index them I go to the directory set in
+;; `nnir-namazu-index-directory' and issue the following command.
+;;
+;;      mknmz --mailnews ~/Mail/archive/ ~/Mail/mail/ ~/Mail/lists/
+;;
+;; For maximum searching efficiency I have a cron job set to run this
+;; command every four hours.
+
+;; 4. HyREX
+;;
+;; The HyREX backend requires you to have one directory from where all
+;; your relative paths are to, if you use them. This directory must be
+;; set in the `nnir-hyrex-index-directory' variable, which defaults to
+;; your home directory. You must also pass the base, class and
+;; directory options or simply your dll to the `nnir-hyrex-programm' by
+;; setting the `nnir-hyrex-additional-switches' variable accordently.
+;; To function the `nnir-hyrex-remove-prefix' variable must also be
+;; correct, see the documentation for `nnir-wais-remove-prefix' above.
+
+;; Developer information:
+
+;; I have tried to make the code expandable.  Basically, it is divided
+;; into two layers.  The upper layer is somewhat like the `nnvirtual'
+;; or `nnkiboze' backends: given a specification of what articles to
+;; show from another backend, it creates a group containing exactly
+;; those articles.  The lower layer issues a query to a search engine
+;; and produces such a specification of what articles to show from the
+;; other backend.
+
+;; The interface between the two layers consists of the single
+;; function `nnir-run-query', which just selects the appropriate
+;; function for the search engine one is using.  The input to
+;; `nnir-run-query' is a string, representing the query as input by
+;; the user.  The output of `nnir-run-query' is supposed to be a
+;; vector, each element of which should in turn be a three-element
+;; vector.  The first element should be full group name of the article,
+;; the second element should be the article number, and the third
+;; element should be the Retrieval Status Value (RSV) as returned from
+;; the search engine.  An RSV is the score assigned to the document by
+;; the search engine.  For Boolean search engines like Glimpse, the
+;; RSV is always 1000 (or 1 or 100, or whatever you like).
+
+;; The sorting order of the articles in the summary buffer created by
+;; nnir is based on the order of the articles in the above mentioned
+;; vector, so that's where you can do the sorting you'd like.  Maybe
+;; it would be nice to have a way of displaying the search result
+;; sorted differently?
+
+;; So what do you need to do when you want to add another search
+;; engine?  You write a function that executes the query.  Temporary
+;; data from the search engine can be put in `nnir-tmp-buffer'.  This
+;; function should return the list of articles as a vector, as
+;; described above.  Then, you need to register this backend in
+;; `nnir-engines'.  Then, users can choose the backend by setting
+;; `nnir-search-engine'.
+
+;; Todo, or future ideas:
+
+;; * Make it so that Glimpse can also be called without `-F'.
+;;
+;; * It should be possible to restrict search to certain groups.
+;;
+;; * There is currently no error checking.
+;;
+;; * The summary buffer display is currently really ugly, with all the
+;;   added information in the subjects.  How could I make this
+;;   prettier?
+;;
+;; * A function which can be called from an nnir summary buffer which
+;;   teleports you into the group the current article came from and
+;;   shows you the whole thread this article is part of.
+;;   Implementation suggestions?
+;;   (1998-07-24: There is now a preliminary implementation, but
+;;   it is much too slow and quite fragile.)
+;;
+;; * Support other mail backends.  In particular, probably quite a few
+;;   people use nnfolder.  How would one go about searching nnfolders
+;;   and producing the right data needed?  The group name and the RSV
+;;   are simple, but what about the article number?
+;;   - The article number is encoded in the `X-Gnus-Article-Number'
+;;     header of each mail.
+;;   - The HyREX engine supports nnfolder.
+;;
+;; * Support compressed mail files.  Probably, just stripping off the
+;;   `.gz' or `.Z' file name extension is sufficient.
+;;
+;; * Support a find/grep combination.
+;;
+;; * At least for imap, the query is performed twice.
+;;
+
+;; Have you got other ideas?
+
+;;; Setup Code:
+
+(defconst nnir-version "$Id: nnir.el,v 1.1.6.1 2004-01-04 23:51:01 yamaoka Exp $"
+  "Version of NNIR.")
+
+(require 'cl)
+(require 'nnoo)
+(require 'gnus-group)
+(require 'gnus-sum)
+(eval-and-compile
+  (require 'gnus-util))
+(eval-when-compile
+  (require 'nnimap)
+  (autoload 'read-kbd-macro "edmacro" nil t))
+
+(nnoo-declare nnir)
+(nnoo-define-basics nnir)
+
+(gnus-declare-backend "nnir" 'mail)
+
+(defvar nnir-imap-search-field "TEXT"
+  "The IMAP search item when doing an nnir search")
+
+(defvar nnir-imap-search-arguments
+  '(("Whole message" . "TEXT")
+    ("Subject" . "SUBJECT")
+    ("To" . "TO")
+    ("From" . "FROM")
+    (nil . "HEADER \"%s\""))
+  "Mapping from user readable strings to IMAP search items for use in nnir")
+
+(defvar nnir-imap-search-argument-history ()
+  "The history for querying search options in nnir")
+
+;;; Developer Extension Variable:
+
+(defvar nnir-engines
+  `((glimpse nnir-run-glimpse
+             ((group . "Group spec: ")))
+    (wais    nnir-run-waissearch
+             ())
+    (excite  nnir-run-excite-search
+            ())
+    (imap    nnir-run-imap
+             ((criteria 
+              "Search in: "                      ; Prompt
+              ,nnir-imap-search-arguments        ; alist for completing
+              nil                                ; no filtering
+              nil                                ; allow any user input
+              nil                                ; initial value
+              nnir-imap-search-argument-history  ; the history to use
+              ,nnir-imap-search-field            ; default
+              )))
+    (swish++ nnir-run-swish++
+             ((group . "Group spec: ")))
+    (swish-e nnir-run-swish-e
+             ((group . "Group spec: ")))
+    (namazu  nnir-run-namazu
+             ())
+    (hyrex   nnir-run-hyrex
+            ((group . "Group spec: "))))
+  "Alist of supported search engines.
+Each element in the alist is a three-element list (ENGINE FUNCTION ARGS).
+ENGINE is a symbol designating the searching engine.  FUNCTION is also
+a symbol, giving the function that does the search.  The third element
+ARGS is a list of cons pairs (PARAM . PROMPT).  When issuing a query,
+the FUNCTION will issue a query for each of the PARAMs, using PROMPT.
+
+The value of `nnir-search-engine' must be one of the ENGINE symbols.
+For example, use the following line for searching using freeWAIS-sf:
+    (setq nnir-search-engine 'wais)
+Use the following line if you read your mail via IMAP and your IMAP
+server supports searching:
+    (setq nnir-search-engine 'imap)
+Note that you have to set additional variables for most backends.  For
+example, the `wais' backend needs the variables `nnir-wais-program',
+`nnir-wais-database' and `nnir-wais-remove-prefix'.
+
+Add an entry here when adding a new search engine.")
+
+;;; User Customizable Variables:
+
+(defgroup nnir nil
+  "Search nnmh and nnml groups in Gnus with Glimpse, freeWAIS-sf, or EWS.")
+
+;; Mail backend.
+
+;; TODO:
+;; If `nil', use server parameters to find out which server to search. CCC
+;;
+(defcustom nnir-mail-backend '(nnml "")
+  "*Specifies which backend should be searched.
+More precisely, this is used to determine from which backend to fetch the
+messages found.
+
+This must be equal to an existing server, so maybe it is best to use
+something like the following:
+    (setq nnir-mail-backend (nth 0 gnus-secondary-select-methods))
+The above line works fine if the mail backend you want to search is
+the first element of gnus-secondary-select-methods (`nth' starts counting
+at zero)."
+  :type '(sexp)
+  :group 'nnir)
+
+;; Search engine to use.
+
+(defcustom nnir-search-engine 'wais
+  "*The search engine to use.  Must be a symbol.
+See `nnir-engines' for a list of supported engines, and for example
+settings of `nnir-search-engine'."
+  :type '(sexp)
+  :group 'nnir)
+
+;; Glimpse engine.
+
+(defcustom nnir-glimpse-program "glimpse"
+  "*Name of Glimpse executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-home (getenv "HOME")
+  "*Value of `-H' glimpse option.
+`~' and environment variables must be expanded, see the functions
+`expand-file-name' and `substitute-in-file-name'."
+  :type '(directory)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by Glimpse
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+For example, suppose that Glimpse returns file names such as
+\"/home/john/Mail/mail/misc/42\".  For this example, use the following
+setting:  (setq nnir-glimpse-remove-prefix \"/home/john/Mail/\")
+Note the trailing slash.  Removing this prefix gives \"mail/misc/42\".
+`nnir' knows to remove the \"/42\" and to replace \"/\" with \".\" to
+arrive at the correct group name, \"mail.misc\"."
+  :type '(regexp)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-additional-switches '("-i")
+  "*A list of strings, to be given as additional arguments to glimpse.
+The switches `-H', `-W', `-l' and `-y' are always used -- calling
+glimpse without them does not make sense in our situation.
+Suggested elements to put here are `-i' and `-w'.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-glimpse-additional-switches \"-i -w\") ; wrong!
+Instead, use this:
+    (setq nnir-glimpse-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+;; freeWAIS-sf.
+
+(defcustom nnir-wais-program "waissearch"
+  "*Name of waissearch executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-wais-database (expand-file-name "~/.wais/mail")
+  "*Name of Wais database containing the mail.
+
+Note that this should be a file name without extension.  For example,
+if you have a file /home/john/.wais/mail.fmt, use this:
+    (setq nnir-wais-database \"/home/john/.wais/mail\")
+The string given here is passed to `waissearch -d' as-is."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-wais-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each directory name returned by waissearch
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is similar to `nnir-glimpse-remove-prefix', only for Wais,
+not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; EWS (Excite for Web Servers) engine.
+
+(defcustom nnir-excite-aquery-program "aquery.pl"
+  "*Name of the EWS query program.  Should be `aquery.pl' or a path to same."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-excite-collection "Mail"
+  "*Name of the EWS collection to search."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-excite-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by EWS
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for EWS, not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; Swish++.  Next three variables Copyright (C) 2000, 2001 Christoph
+;; Conrad <christoph.conrad@gmx.de>.
+;; Swish++ home page: http://homepage.mac.com/pauljlucas/software/swish/
+
+(defcustom nnir-swish++-configuration-file
+  (expand-file-name "~/Mail/swish++.conf")
+  "*Configuration file for swish++."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-swish++-program "search"
+  "*Name of swish++ search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-swish++-additional-switches '()
+  "*A list of strings, to be given as additional arguments to swish++.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-swish++-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-swish++-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-swish++-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by swish++
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for swish++, not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; Swish-E.  Next three variables Copyright (C) 2000 Christoph Conrad
+;; <christoph.conrad@gmx.de>.
+;; URL: http://sunsite.berkeley.edu/SWISH-E/
+;; New version: http://www.boe.es/swish-e
+
+(defcustom nnir-swish-e-index-file
+  (expand-file-name "~/Mail/index.swish-e")
+  "*Index file for swish-e.
+This could be a server parameter."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-swish-e-program "swish-e"
+  "*Name of swish-e search executable.
+This cannot be a server parameter."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-swish-e-additional-switches '()
+  "*A list of strings, to be given as additional arguments to swish-e.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-swish-e-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-swish-e-additional-switches '(\"-i\" \"-w\"))
+
+This could be a server parameter."
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-swish-e-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by swish-e
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for swish-e, not Glimpse.
+
+This could be a server parameter."
+  :type '(regexp)
+  :group 'nnir)
+
+;; HyREX engine, see <URL:http://ls6-www.cs.uni-dortmund.de/>
+
+(defcustom nnir-hyrex-program "nnir-search"
+  "*Name of the nnir-search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-hyrex-additional-switches '()
+  "*A list of strings, to be given as additional arguments for nnir-search.
+Note that this should be a list. Ie, do NOT use the following:
+    (setq nnir-hyrex-additional-switches \"-ddl ddl.xml -c nnir\") ; wrong !
+Instead, use this:
+    (setq nnir-hyrex-additional-switches '(\"-ddl\" \"ddl.xml\" \"-c\" \"nnir\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-hyrex-index-directory (getenv "HOME")
+  "*Index directory for HyREX."
+  :type '(directory)
+  :group 'nnir)
+
+(defcustom nnir-hyrex-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by HyREX
+in order to get a group name (albeit with / instead of .).
+
+For example, suppose that HyREX returns file names such as
+\"/home/john/Mail/mail/misc/42\".  For this example, use the following
+setting:  (setq nnir-hyrex-remove-prefix \"/home/john/Mail/\")
+Note the trailing slash.  Removing this prefix gives \"mail/misc/42\".
+`nnir' knows to remove the \"/42\" and to replace \"/\" with \".\" to
+arrive at the correct group name, \"mail.misc\"."
+  :type '(directory)
+  :group 'nnir)
+
+;; Namazu engine, see <URL:http://ww.namazu.org/>
+
+(defcustom nnir-namazu-program "namazu"
+  "*Name of Namazu search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-namazu-index-directory (expand-file-name "~/Mail/namazu/")
+  "*Index directory for Namazu."
+  :type '(directory)
+  :group 'nnir)
+
+(defcustom nnir-namazu-additional-switches '()
+  "*A list of strings, to be given as additional arguments to namazu.
+The switches `-q', `-a', and `-s' are always used, very few other switches
+make any sense in this context.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-namazu-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-namazu-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-namazu-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by Namazu
+in order to get a group name (albeit with / instead of .).
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for Namazu, not Glimpse."
+  :type '(directory)
+  :group 'nnir)
+
+;;; Internal Variables:
+
+(defvar nnir-current-query nil
+  "Internal: stores current query (= group name).")
+
+(defvar nnir-current-server nil
+  "Internal: stores current server (does it ever change?).")
+
+(defvar nnir-current-group-marked nil
+  "Internal: stores current list of process-marked groups.")
+
+(defvar nnir-artlist nil
+  "Internal: stores search result.")
+
+(defvar nnir-tmp-buffer " *nnir*"
+  "Internal: temporary buffer.")
+
+;;; Code:
+
+;; Gnus glue.
+
+(defun gnus-group-make-nnir-group (extra-parms query)
+  "Create an nnir group.  Asks for query."
+  (interactive "P\nsQuery: ")
+  (setq nnir-current-query nil
+       nnir-current-server nil
+       nnir-current-group-marked nil
+       nnir-artlist nil)
+  (let ((parms nil))
+    (if extra-parms
+        (setq parms (nnir-read-parms query))
+      (setq parms (list (cons 'query query))))
+    (gnus-group-read-ephemeral-group
+     (concat "nnir:" (prin1-to-string parms)) '(nnir "") t
+     (cons (current-buffer)
+           gnus-current-window-configuration)
+     nil)))
+
+;; Emacs 19 compatibility?
+(or (fboundp 'kbd) (defalias 'kbd 'read-kbd-macro))
+
+(defun nnir-group-mode-hook ()
+  (define-key gnus-group-mode-map
+    (if (fboundp 'read-kbd-macro)
+        (kbd "G G")
+      "GG")                             ; XEmacs 19 compat
+    'gnus-group-make-nnir-group))
+(add-hook 'gnus-group-mode-hook 'nnir-group-mode-hook)
+
+
+
+;; Summary mode commands.
+
+(defun gnus-summary-nnir-goto-thread ()
+  "Only applies to nnir groups.  Go to group this article came from
+and show thread that contains this article."
+  (interactive)
+  (unless (eq 'nnir (car (gnus-find-method-for-group gnus-newsgroup-name)))
+    (error "Can't execute this command unless in nnir group."))
+  (let* ((cur (gnus-summary-article-number))
+         (group (nnir-artlist-artitem-group nnir-artlist cur))
+         (backend-number (nnir-artlist-artitem-number nnir-artlist cur))
+        server backend-group)
+    (setq server (nnir-group-server group))
+    (setq backend-group (gnus-group-real-name group))
+    (gnus-group-read-ephemeral-group
+     backend-group
+     (gnus-server-to-method server)
+     t                                  ; activate
+     (cons (current-buffer)
+           'summary)                    ; window config
+     nil
+     (list backend-number))
+    (gnus-summary-limit (list backend-number))
+    (gnus-summary-refer-thread)))
+
+(if (fboundp 'eval-after-load)
+    (eval-after-load "gnus-sum"
+      '(define-key gnus-summary-goto-map
+         "T" 'gnus-summary-nnir-goto-thread))
+  (add-hook 'gnus-summary-mode-hook
+            (function (lambda ()
+                        (define-key gnus-summary-goto-map
+                          "T" 'gnus-summary-nnir-goto-thread)))))
+
+
+
+;; Gnus backend interface functions.
+
+(deffoo nnir-open-server (server &optional definitions)
+  ;; Just set the server variables appropriately.
+  (nnoo-change-server 'nnir server definitions))
+
+(deffoo nnir-request-group (group &optional server fast)
+  "GROUP is the query string."
+  (nnir-possibly-change-server server)
+  ;; Check for cache and return that if appropriate.
+  (if (and (equal group nnir-current-query)
+           (equal gnus-group-marked nnir-current-group-marked)
+           (or (null server)
+               (equal server nnir-current-server)))
+      nnir-artlist
+    ;; Cache miss.
+    (setq nnir-artlist (nnir-run-query group)))
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (if (zerop (length nnir-artlist))
+       (progn
+         (setq nnir-current-query nil
+               nnir-current-server nil
+               nnir-current-group-marked nil
+               nnir-artlist nil)
+         (nnheader-report 'nnir "Search produced empty results."))
+      ;; Remember data for cache.
+      (setq nnir-current-query group)
+      (when server (setq nnir-current-server server))
+      (setq nnir-current-group-marked gnus-group-marked)
+      (nnheader-insert "211 %d %d %d %s\n"
+                      (nnir-artlist-length nnir-artlist) ; total #
+                      1              ; first #
+                      (nnir-artlist-length nnir-artlist) ; last #
+                      group))))     ; group name
+
+(deffoo nnir-retrieve-headers (articles &optional group server fetch-old)
+  (save-excursion
+    (let ((artlist (copy-sequence articles))
+          (idx 1)
+          (art nil)
+          (artitem nil)
+          (artgroup nil) (artno nil)
+          (artrsv nil)
+          (artfullgroup nil)
+          (novitem nil)
+          (novdata nil)
+          (foo nil)
+         server)
+      (while (not (null artlist))
+        (setq art (car artlist))
+        (or (numberp art)
+            (nnheader-report
+             'nnir
+             "nnir-retrieve-headers doesn't grok message ids: %s"
+             art))
+        (setq artitem (nnir-artlist-article nnir-artlist art))
+        (setq artrsv (nnir-artitem-rsv artitem))
+        (setq artfullgroup (nnir-artitem-group artitem))
+        (setq artno (nnir-artitem-number artitem))
+        (setq artgroup (gnus-group-real-name artfullgroup))
+       (setq server (nnir-group-server artfullgroup))
+        ;; retrieve NOV or HEAD data for this article, transform into
+        ;; NOV data and prepend to `novdata'
+        (set-buffer nntp-server-buffer)
+       (nnir-possibly-change-server server)
+        (case (setq foo (gnus-retrieve-headers (list artno) artfullgroup nil))
+          (nov
+           (goto-char (point-min))
+           (setq novitem (nnheader-parse-nov))
+           (unless novitem
+             (pop-to-buffer nntp-server-buffer)
+             (error
+              "nnheader-parse-nov returned nil for article %s in group %s"
+              artno artfullgroup)))
+          (headers
+           (goto-char (point-min))
+           (setq novitem (nnheader-parse-head))
+           (unless novitem
+             (pop-to-buffer nntp-server-buffer)
+             (error
+              "nnheader-parse-head returned nil for article %s in group %s"
+              artno artfullgroup)))
+          (t (nnheader-report 'nnir "Don't support header type %s." foo)))
+       ;; replace article number in original group with article number
+        ;; in nnir group
+        (mail-header-set-number novitem idx)
+        (mail-header-set-from novitem
+                              (mail-header-from novitem))
+        (mail-header-set-subject
+         novitem
+         (format "[%d: %s/%d] %s"
+                 artrsv artgroup artno
+                 (mail-header-subject novitem)))
+        ;;-(mail-header-set-extra novitem nil)
+        (push novitem novdata)
+        (setq artlist (cdr artlist))
+        (setq idx (1+ idx)))
+      (setq novdata (nreverse novdata))
+      (set-buffer nntp-server-buffer) (erase-buffer)
+      (mapcar 'nnheader-insert-nov novdata)
+      'nov)))
+
+(deffoo nnir-request-article (article
+                              &optional group server to-buffer)
+  (save-excursion
+    (let* ((artitem (nnir-artlist-article nnir-artlist
+                                          article))
+           (artfullgroup (nnir-artitem-group artitem))
+           (artno (nnir-artitem-number artitem))
+           ;; Bug?
+           ;; Why must we bind nntp-server-buffer here?  It won't
+           ;; work if `buf' is used, say.  (Of course, the set-buffer
+           ;; line below must then be updated, too.)
+           (nntp-server-buffer (or to-buffer nntp-server-buffer)))
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (message "Requesting article %d from group %s"
+               artno artfullgroup)
+      (gnus-request-article artno artfullgroup nntp-server-buffer)
+      (cons artfullgroup artno))))
+
+
+(nnoo-define-skeleton nnir)
+
+;;; Search Engine Interfaces:
+
+;; Glimpse interface.
+(defun nnir-run-glimpse (query server &optional group)
+  "Run given query against glimpse.  Returns a vector of (group name, file name)
+pairs (also vectors, actually)."
+  (save-excursion
+    (let ((artlist nil)
+          (groupspec (cdr (assq 'group query)))
+          (qstring (cdr (assq 'query query)))
+         (prefix (nnir-read-server-parm 'nnir-glimps-remove-prefix server))
+         artno dirnam)
+      (when (and group groupspec)
+        (error (concat "It does not make sense to use a group spec"
+                       " with process-marked groups.")))
+      (when group
+        (setq groupspec (gnus-group-real-name group)))
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (if groupspec
+          (message "Doing glimpse query %s on %s..." query groupspec)
+        (message "Doing glimpse query %s..." query))
+      (let* ((cp-list
+              `( ,nnir-glimpse-program
+                 nil                    ; input from /dev/null
+                 t                      ; output
+                 nil                    ; don't redisplay
+                 "-H" ,(nnir-read-server-parm 'nnir-glimpse-home server) ; search home dir
+                 "-W"                   ; match pattern in file
+                 "-l" "-y"              ; misc options
+                 ,@(nnir-read-server-parm 'nnir-glimpse-additional-switches server)
+                 "-F" ,prefix           ; restrict output to mail
+                 ,qstring               ; the query, in glimpse format
+                ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-glimpse-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run glimpse: %s" exitstatus)
+          ;; Glimpse failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+      (when groupspec
+        (keep-lines groupspec))
+      (if groupspec
+          (message "Doing glimpse query %s on %s...done" query groupspec)
+        (message "Doing glimpse query %s...done" query))
+      (sit-for 0)
+      ;; remove superfluous stuff from glimpse output
+      (goto-char (point-min))
+      (delete-non-matching-lines "/[0-9]+$")
+      ;;(delete-matching-lines "\\.overview~?$")
+      (goto-char (point-min))
+      (while (re-search-forward (concat "^" prefix "\\(.+\\)" "/\\([0-9]\\)+$") nil t)
+       ;; replace / with . in group names
+        (setq dirnam (substitute ?. ?/ (match-string 1))
+             artno  (match-string 2))
+       (push (vector (nnir-group-full-name dirnam server)
+                     (string-to-int artno)) artlist))
+
+      (sort* artlist
+             (function (lambda (x y)
+                         (if (string-lessp (nnir-artitem-group x)
+                                           (nnir-artitem-group y))
+                             t
+                           (< (nnir-artitem-number x)
+                              (nnir-artitem-number y))))))
+      )))
+
+;; freeWAIS-sf interface.
+(defun nnir-run-waissearch (query server &optional group)
+  "Run given query agains waissearch.  Returns vector of (group name, file name)
+pairs (also vectors, actually)."
+  (when group
+    (error "The freeWAIS-sf backend cannot search specific groups."))
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         (prefix (nnir-read-server-parm 'nnir-wais-remove-prefix server))
+          (artlist nil)
+          (score nil) (artno nil) (dirnam nil) (group nil))
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (message "Doing WAIS query %s..." query)
+      (call-process nnir-wais-program
+                    nil                 ; input from /dev/null
+                    t                   ; output to current buffer
+                    nil                 ; don't redisplay
+                    "-d" (nnir-read-server-parm 'nnir-wais-database server) ; database to search
+                    qstring)
+      (message "Massaging waissearch output...")
+      ;; remove superfluous lines
+      (keep-lines "Score:")
+      ;; extract data from result lines
+      (goto-char (point-min))
+      (while (re-search-forward
+              "Score: +\\([0-9]+\\).*'\\([0-9]+\\) +\\([^']+\\)/'" nil t)
+        (setq score (match-string 1)
+              artno (match-string 2)
+              dirnam (match-string 3))
+        (unless (string-match prefix dirnam)
+          (nnheader-report 'nnir "Dir name %s doesn't contain prefix %s"
+                           dirnam prefix))
+        (setq group (substitute ?. ?/ (replace-match "" t t dirnam)))
+        (push (vector (nnir-group-full-name group server)
+                      (string-to-int artno)
+                      (string-to-int score))
+              artlist))
+      (message "Massaging waissearch output...done")
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; EWS (Excite for Web Servers) interface
+(defun nnir-run-excite-search (query server &optional group)
+  "Run a given query against EWS.  Returns vector of (group name, file name)
+pairs (also vectors, actually)."
+  (when group
+    (error "Searching specific groups not implemented for EWS."))
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         (prefix (nnir-read-server-parm 'nnir-excite-remove-prefix server))
+         artlist group article-num article)
+      (setq nnir-current-query query)
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (message "Doing EWS query %s..." qstring)
+      (call-process nnir-excite-aquery-program
+                   nil                 ; input from /dev/null
+                   t                   ; output to current buffer
+                   nil                 ; don't redisplay
+                   (nnir-read-server-parm 'nnir-excite-collection server)
+                   (if (string= (substring qstring 0 1) "(")
+                       qstring
+                     (format "(concept %s)" qstring)))
+      (message "Gathering query output...")
+
+      (goto-char (point-min))
+      (while (re-search-forward
+             "^[0-9]+\\s-[0-9]+\\s-[0-9]+\\s-\\(\\S-*\\)" nil t)
+       (setq article (match-string 1))
+       (unless (string-match
+                (concat "^" (regexp-quote prefix)
+                        "\\(.*\\)/\\([0-9]+\\)") article)
+         (nnheader-report 'nnir "Dir name %s doesn't contain prefix %s"
+                          article prefix))
+       (setq group (substitute ?. ?/ (match-string 1 article)))
+       (setq group (nnir-group-full-name group server))
+       (setq article-num (match-string 2 article))
+       (setq artlist (vconcat artlist (vector (vector group
+                                                      (string-to-int article-num)
+                                                      1000)))))
+      (message "Gathering query output...done")
+      artlist)))
+
+;; IMAP interface.  The following function is Copyright (C) 1998 Simon
+;; Josefsson <jas@pdc.kth.se>.
+;; todo:
+;; nnir invokes this two (2) times???!
+;; we should not use nnimap at all but open our own server connection
+;; we should not LIST * but use nnimap-list-pattern from defs
+;; send queries as literals
+;; handle errors
+
+(defun nnir-run-imap (query srv &optional group-option)
+  (require 'imap)
+  (require 'nnimap)
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         (server (cadr (gnus-server-to-method srv)))
+         (group (or group-option (gnus-group-group-name)))
+         (defs (caddr (gnus-server-to-method srv)))
+         (criteria (or (cdr (assq 'criteria query))
+                       nnir-imap-search-field))
+         artlist buf)
+      (message "Opening server %s" server)
+      (condition-case ()
+         (when (nnimap-open-server server defs) ;; xxx
+           (setq buf nnimap-server-buffer) ;; xxx
+           (message "Searching %s..." group)
+            (let ((arts 0)
+                  (mbx (gnus-group-real-name group)))
+              (when (imap-mailbox-select mbx nil buf)
+                (mapcar
+                 (lambda (artnum)
+                   (push (vector group artnum 1) artlist)
+                   (setq arts (1+ arts)))
+                 (imap-search (concat criteria " \"" qstring "\"") buf))
+                (message "Searching %s... %d matches" mbx arts)))
+            (message "Searching %s...done" group))
+        (quit nil))
+      (reverse artlist))))
+
+;; Swish++ interface.  The following function is Copyright (C) 2000,
+;; 2001 Christoph Conrad <christoph.conrad@gmx.de>.
+;; -cc- Todo
+;; Search by
+;; - group
+;; Sort by
+;; - rank (default)
+;; - article number
+;; - file size
+;; - group
+(defun nnir-run-swish++ (query server &optional group)
+  "Run given query against swish++.
+Returns a vector of (group name, file name) pairs (also vectors,
+actually).
+
+Tested with swish++ 4.7 on GNU/Linux and with with swish++ 5.0b2 on
+Windows NT 4.0."
+
+  (when group
+    (error "The swish++ backend cannot search specific groups."))
+
+  (save-excursion
+    (let ( (qstring (cdr (assq 'query query)))
+          (groupspec (cdr (assq 'group query)))
+          (prefix (nnir-read-server-parm 'nnir-swish++-remove-prefix server))
+           (artlist nil)
+           (score nil) (artno nil) (dirnam nil) (group nil) )
+
+      (when (equal "" qstring)
+        (error "swish++: You didn't enter anything."))
+
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+
+      (if groupspec
+          (message "Doing swish++ query %s on %s..." qstring groupspec)
+        (message "Doing swish++ query %s..." qstring))
+
+      (let* ((cp-list `( ,nnir-swish++-program
+                         nil            ; input from /dev/null
+                         t              ; output
+                         nil            ; don't redisplay
+                         "--config-file" ,(nnir-read-server-parm 'nnir-swish++-configuration-file server)
+                         ,@(nnir-read-server-parm 'nnir-swish++-additional-switches server)
+                         ,qstring       ; the query, in swish++ format
+                         ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-swish++-program
+                         (mapconcat 'identity (cddddr cp-list) " ")) ;; ???
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run swish++: %s" exitstatus)
+          ;; swish++ failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; The results are output in the format of:
+      ;; V 4.7 Linux
+      ;; rank relative-path-name file-size file-title
+      ;; V 5.0b2:
+      ;; rank relative-path-name file-size topic??
+      ;; where rank is an integer from 1 to 100.
+      (goto-char (point-min))
+      (while (re-search-forward
+              "\\(^[0-9]+\\) \\([^ ]+\\) [0-9]+ \\(.*\\)$" nil t)
+        (setq score (match-string 1)
+              artno (file-name-nondirectory (match-string 2))
+              dirnam (file-name-directory (match-string 2)))
+
+        ;; don't match directories
+        (when (string-match "^[0-9]+$" artno)
+          (when (not (null dirnam))
+
+           ;; maybe limit results to matching groups.
+           (when (or (not groupspec)
+                     (string-match groupspec dirnam))
+
+             ;; remove nnir-swish++-remove-prefix from beginning of dirname
+             (when (string-match (concat "^" prefix)
+                                 dirnam)
+               (setq dirnam (replace-match "" t t dirnam)))
+
+             (setq dirnam (substring dirnam 0 -1))
+             ;; eliminate all ".", "/", "\" from beginning. Always matches.
+             (string-match "^[./\\]*\\(.*\\)$" dirnam)
+             ;; "/" -> "."
+             (setq group (substitute ?. ?/ (match-string 1 dirnam)))
+             ;; "\\" -> "."
+             (setq group (substitute ?. ?\\ group))
+
+             (push (vector (nnir-group-full-name group server)
+                           (string-to-int artno)
+                           (string-to-int score))
+                   artlist)))))
+
+      (message "Massaging swish++ output...done")
+
+      ;; Sort by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; Swish-E interface.  The following function is Copyright (C) 2000,
+;; 2001 by Christoph Conrad <christoph.conrad@gmx.de>.
+(defun nnir-run-swish-e (query server &optional group)
+  "Run given query against swish-e.
+Returns a vector of (group name, file name) pairs (also vectors,
+actually).
+
+Tested with swish-e-2.0.1 on Windows NT 4.0."
+
+  ;; swish-e crashes with empty parameter to "-w" on commandline...
+  (when group
+    (error "The swish-e backend cannot search specific groups."))
+
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         (prefix
+          (or (nnir-read-server-parm 'nnir-swish-e-remove-prefix server)
+              (error "Missing parameter `nnir-swish-e-remove-prefix'")))
+         (artlist nil)
+         (score nil) (artno nil) (dirnam nil) (group nil) )
+
+      (when (equal "" qstring)
+        (error "swish-e: You didn't enter anything."))
+
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+
+      (message "Doing swish-e query %s..." query)
+      (let* ((index-file
+             (or (nnir-read-server-parm
+                  'nnir-swish-e-index-file server)
+                 (error "Missing parameter `nnir-swish-e-index-file'")))
+            (additional-switches
+             (nnir-read-server-parm
+              'nnir-swish++-additional-switches server))
+            (cp-list `(,nnir-swish-e-program
+                       nil             ; input from /dev/null
+                       t               ; output
+                       nil             ; don't redisplay
+                       "-f" ,index-file
+                       ,@additional-switches
+                       "-w"
+                       ,qstring        ; the query, in swish-e format
+                       ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-swish-e-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run swish-e: %s" exitstatus)
+          ;; swish-e failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; The results are output in the format of:
+      ;; rank path-name file-title file-size
+      (goto-char (point-min))
+      (while (re-search-forward
+              "\\(^[0-9]+\\) \\([^ ]+\\) \"\\([^\"]+\\)\" [0-9]+$" nil t)
+        (setq score (match-string 1)
+              artno (match-string 3)
+              dirnam (file-name-directory (match-string 2)))
+
+        ;; don't match directories
+        (when (string-match "^[0-9]+$" artno)
+          (when (not (null dirnam))
+
+           ;; remove nnir-swish-e-remove-prefix from beginning of dirname
+            (when (string-match (concat "^" prefix) dirnam)
+              (setq dirnam (replace-match "" t t dirnam)))
+
+            (setq dirnam (substring dirnam 0 -1))
+           ;; eliminate all ".", "/", "\" from beginning. Always matches.
+            (string-match "^[./\\]*\\(.*\\)$" dirnam)
+            ;; "/" -> "."
+            (setq group (substitute ?. ?/ (match-string 1 dirnam)))
+            ;; Windows "\\" -> "."
+            (setq group (substitute ?. ?\\ group))
+
+            (push (vector (nnir-group-full-name group server)
+                          (string-to-int artno)
+                          (string-to-int score))
+                  artlist))))
+
+      (message "Massaging swish-e output...done")
+
+      ;; Sort by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; HyREX interface
+(defun nnir-run-hyrex (query server &optional group)
+  (save-excursion
+    (let ((artlist nil)
+          (groupspec (cdr (assq 'group query)))
+          (qstring (cdr (assq 'query query)))
+         (prefix (nnir-read-server-parm 'nnir-hyrex-remove-prefix server))
+         score artno dirnam)
+      (when (and group groupspec)
+        (error (concat "It does not make sense to use a group spec"
+                       " with process-marked groups.")))
+      (when group
+        (setq groupspec (gnus-group-real-name group)))
+      (when (and group (not (equal group (nnir-group-full-name groupspec server))))
+       (message "%s vs. %s" group (nnir-group-full-name groupspec server))
+       (error "Server with groupspec doesn't match group !"))
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (if groupspec
+          (message "Doing hyrex-search query %s on %s..." query groupspec)
+        (message "Doing hyrex-search query %s..." query))
+      (let* ((cp-list
+             `( ,nnir-hyrex-program
+                nil                    ; input from /dev/null
+                t                      ; output
+                nil                    ; don't redisplay
+                "-i",(nnir-read-server-parm 'nnir-hyrex-index-directory server) ; index directory
+                ,@(nnir-read-server-parm 'nnir-hyrex-additional-switches server)
+                ,qstring          ; the query, in hyrex-search format
+                ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-hyrex-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run hyrex-search: %s" exitstatus)
+          ;; nnir-search failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer)))) ;; FIXME: Dont clear buffer !
+      (if groupspec
+          (message "Doing hyrex-search query \"%s\" on %s...done" qstring groupspec)
+        (message "Doing hyrex-search query \"%s\"...done" qstring))
+      (sit-for 0)
+      ;; nnir-search returns:
+      ;;   for nnml/nnfolder: "filename mailid weigth"
+      ;;   for nnimap:        "group mailid weigth"
+      (goto-char (point-min))
+      (delete-non-matching-lines "^\\S + [0-9]+ [0-9]+$")
+      ;; HyREX couldn't search directly in groups -- so filter out here.
+      (when groupspec
+       (keep-lines groupspec))
+      ;; extract data from result lines
+      (goto-char (point-min))
+      (while (re-search-forward
+             "\\(\\S +\\) \\([0-9]+\\) \\([0-9]+\\)" nil t)
+       (setq dirnam (match-string 1)
+             artno (match-string 2)
+             score (match-string 3))
+       (when (string-match prefix dirnam)
+         (setq dirnam (replace-match "" t t dirnam)))
+       (push (vector (nnir-group-full-name (substitute ?. ?/ dirnam) server)
+                     (string-to-int artno)
+                     (string-to-int score))
+             artlist))
+      (message "Massaging hyrex-search output...done.")
+      (apply 'vector
+            (sort* artlist
+                   (function (lambda (x y)
+                               (if (string-lessp (nnir-artitem-group x)
+                                                 (nnir-artitem-group y))
+                                   t
+                                 (< (nnir-artitem-number x)
+                                    (nnir-artitem-number y)))))))
+      )))
+
+;; Namazu interface
+(defun nnir-run-namazu (query server &optional group)
+  "Run given query against Namazu.  Returns a vector of (group name, file name)
+pairs (also vectors, actually).
+
+Tested with Namazu 2.0.6 on a GNU/Linux system."
+  (when group
+    (error "The Namazu backend cannot search specific groups"))
+  (save-excursion
+    (let (
+          (artlist nil)
+          (qstring (cdr (assq 'query query)))
+         (prefix (nnir-read-server-parm 'nnir-namazu-remove-prefix server))
+          (score nil)
+          (group nil)
+          (article nil)
+         (process-environment (copy-sequence process-environment))
+          )
+      (setenv "LC_MESSAGES" "C")
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (let* ((cp-list
+              `( ,nnir-namazu-program
+                 nil                   ; input from /dev/null
+                 t                     ; output
+                 nil                   ; don't redisplay
+                 "-q"                  ; don't be verbose
+                 "-a"                  ; show all matches
+                 "-s"                  ; use short format
+                 ,@(nnir-read-server-parm 'nnir-namazu-additional-switches server)
+                 ,qstring              ; the query, in namazu format
+                 ,(nnir-read-server-parm 'nnir-namazu-index-directory server) ; index directory
+                 ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-namazu-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run namazu: %s" exitstatus)
+          ;; Namazu failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; Namazu output looks something like this:
+      ;; 2. Re: Gnus agent expire broken (score: 55)
+      ;; /home/henrik/Mail/mail/sent/1310 (4,138 bytes)
+
+      (goto-char (point-min))
+      (while (re-search-forward
+              "^\\([0-9]+\\.\\).*\\((score: \\([0-9]+\\)\\))\n\\([^ ]+\\)"
+              nil t)
+        (setq score (match-string 3)
+              group (file-name-directory (match-string 4))
+              article (file-name-nondirectory (match-string 4)))
+
+        ;; make sure article and group is sane
+        (when (and (string-match "^[0-9]+$" article)
+                   (not (null group)))
+          (when (string-match (concat "^" prefix) group)
+            (setq group (replace-match "" t t group)))
+
+          ;; remove trailing slash from groupname
+          (setq group (substring group 0 -1))
+
+          ;; stuff results into artlist vector
+          (push (vector (nnir-group-full-name (substitute ?. ?/ group) server)
+                        (string-to-int article)
+                        (string-to-int score)) artlist)))
+
+      ;; sort artlist by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;;; Util Code:
+
+(defun nnir-read-parms (query)
+  "Reads additional search parameters according to `nnir-engines'."
+  (let ((parmspec (caddr (assoc nnir-search-engine nnir-engines))))
+    (cons (cons 'query query)
+          (mapcar 'nnir-read-parm parmspec))))
+
+(defun nnir-read-parm (parmspec)
+  "Reads a single search parameter.
+`parmspec' is a cons cell, the car is a symbol, the cdr is a prompt."
+  (let ((sym (car parmspec))
+        (prompt (cdr parmspec)))
+    (if (listp prompt)
+       (let* ((result (apply 'completing-read prompt))
+              (mapping (or (assoc result nnir-imap-search-arguments)
+                           (assoc nil nnir-imap-search-arguments))))
+         (cons sym (format (cdr mapping) result)))
+      (cons sym (read-string prompt)))))
+
+(defun nnir-run-query (query)
+  "Invoke appropriate search engine function (see `nnir-engines').
+If some groups were process-marked, run the query for each of the groups
+and concat the results."
+  (let ((q (car (read-from-string query))))
+    (if gnus-group-marked
+       (apply 'vconcat
+              (mapcar (lambda (x)
+                        (let ((server (nnir-group-server x))
+                              search-func)
+                          (setq search-func (cadr
+                                             (assoc
+                                              (nnir-read-server-parm 'nnir-search-engine server) nnir-engines)))
+                          (if search-func
+                              (funcall search-func q server x)
+                            nil)))
+                      gnus-group-marked)
+              )
+      (apply 'vconcat
+            (mapcar (lambda (x)
+                      (if (and (equal (cadr x) 'ok) (not (equal (cadar x) "-ephemeral")))
+                          (let ((server (format "%s:%s" (caar x) (cadar x)))
+                                search-func)
+                            (setq search-func (cadr
+                                               (assoc
+                                                (nnir-read-server-parm 'nnir-search-engine server) nnir-engines)))
+                            (if search-func
+                                (funcall search-func q server nil)
+                              nil))
+                        nil))
+                    gnus-opened-servers)
+            ))
+    ))
+
+(defun nnir-read-server-parm (key server)
+  "Returns the parameter value of for the given server, where server is of
+form 'backend:name'."
+  (let ((method (gnus-server-to-method server)))
+    (cond ((and method (assq key (cddr method)))
+          (nth 1 (assq key (cddr method))))
+         ((and nnir-mail-backend
+               (gnus-method-equal method nnir-mail-backend))
+          (symbol-value key))
+         ((null nnir-mail-backend)
+          (symbol-value key))
+         (t nil))))
+;;     (if method
+;;       (if (assq key (cddr method))
+;;       (nth 1 (assq key (cddr method)))
+;;     (symbol-value key))
+;;       (symbol-value key))
+;;     ))
+
+(defmacro nnir-group-server (group)
+  "Returns the server for a foreign newsgroup in the format as gnus-server-to-method needs it. Compare to gnus-group-real-prefix and gnus-group-real-name."
+  `(let ((gname ,group))
+    (if (string-match "^\\([^:]+\\):" gname)
+       (setq gname (match-string 1 gname))
+      nil)
+    (if (string-match "^\\([^+]+\\)\\+\\(.+\\)$" gname)
+       (format "%s:%s" (match-string 1 gname) (match-string 2 gname))
+      (concat gname ":"))
+    ))
+
+(defun nnir-group-full-name (shortname server)
+  "For the given group name, return a full Gnus group name.
+The Gnus backend/server information is added."
+  (gnus-group-prefixed-name shortname (gnus-server-to-method server)))
+
+(defun nnir-possibly-change-server (server)
+  (unless (and server (nnir-server-opened server))
+    (nnir-open-server server)))
+
+
+;; Data type article list.
+
+(defun nnir-artlist-length (artlist)
+  "Returns number of articles in artlist."
+  (length artlist))
+
+(defun nnir-artlist-article (artlist n)
+  "Returns from ARTLIST the Nth artitem (counting starting at 1)."
+  (elt artlist (1- n)))
+
+(defun nnir-artitem-group (artitem)
+  "Returns the group from the ARTITEM."
+  (elt artitem 0))
+
+(defun nnir-artlist-artitem-group (artlist n)
+  "Returns from ARTLIST the group of the Nth artitem (counting from 1)."
+  (nnir-artitem-group (nnir-artlist-article artlist n)))
+
+(defun nnir-artitem-number (artitem)
+  "Returns the number from the ARTITEM."
+  (elt artitem 1))
+
+(defun nnir-artlist-artitem-number (artlist n)
+  "Returns from ARTLIST the number of the Nth artitem (counting from 1)."
+  (nnir-artitem-number (nnir-artlist-article artlist n)))
+
+(defun nnir-artitem-rsv (artitem)
+  "Returns the Retrieval Status Value (RSV, score) from the ARTITEM."
+  (elt artitem 2))
+
+(defun nnir-artlist-artitem-rsv (artlist n)
+  "Returns from ARTLIST the Retrieval Status Value of the Nth artitem
+(counting from 1)."
+  (nnir-artitem-rsv (nnir-artlist-article artlist n)))
+
+;; unused?
+(defun nnir-artlist-groups (artlist)
+  "Returns a list of all groups in the given ARTLIST."
+  (let ((res nil)
+        (with-dups nil))
+    ;; from each artitem, extract group component
+    (setq with-dups (mapcar 'nnir-artitem-group artlist))
+    ;; remove duplicates from above
+    (mapcar (function (lambda (x) (add-to-list 'res x)))
+            with-dups)
+    res))
+
+
+;; The end.
+(provide 'nnir)
diff --git a/contrib/one-line-cookie.diff b/contrib/one-line-cookie.diff
new file mode 100644 (file)
index 0000000..1cab64a
--- /dev/null
@@ -0,0 +1,28 @@
+Index: url-cookie.el
+===================================================================
+RCS file: /gd/gnu/anoncvsroot/url/lisp/url-cookie.el,v
+retrieving revision 1.1.1.1
+diff -u -r1.1.1.1 url-cookie.el
+--- url-cookie.el      1999/11/26 12:11:47     1.1.1.1
++++ url-cookie.el      1999/12/10 06:53:05
+@@ -255,6 +255,10 @@
+               (setq retval (cons cur retval))))))
+     retval))
++(defvar url-cookie-multiple-line t
++  "If nil, use one line cookie.
++Some web servers, such as hotmail, only accept one line cookie.")
++
+ ;;;###autolaod
+ (defun url-cookie-generate-header-lines (host path secure)
+   (let* ((cookies (url-cookie-retrieve host path secure))
+@@ -272,7 +276,8 @@
+       (setq cur (car cookies)
+           cookies (cdr cookies)
+           chunk (format "%s=%s" (url-cookie-name cur) (url-cookie-value cur))
+-          retval (if (< 80 (+ (length retval) (length chunk) 4))
++          retval (if (and url-cookie-multiple-line
++                      (< 80 (+ (length retval) (length chunk) 4)))
+                      (concat retval "\r\nCookie: " chunk)
+                    (if retval
+                        (concat retval "; " chunk)
diff --git a/contrib/passwd.el b/contrib/passwd.el
new file mode 100644 (file)
index 0000000..0257469
--- /dev/null
@@ -0,0 +1,386 @@
+;;; passwd.el --- Prompting for passwords semi-securely
+
+;; Copyright (C) 1994 Free Software Foundation, Inc.
+;; Keywords: comm, extensions
+
+;; Author: Jamie Zawinski <jwz@netscape.com>
+
+;; This file is part of XEmacs.
+
+;; XEmacs is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; XEmacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;;; Synched up with: Not in FSF.
+
+;; You should have received a copy of the GNU General Public License
+;; along with XEmacs; see the file COPYING.  If not, write to the Free
+;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;; Change Log:
+;;
+;;  Sun Jun 12 04:19:30 1994 by sandy on ibm550.sissa.it
+;;    Added support for password histories and (provide 'passwd)
+;;    (jwz says: this "history" thing is completely undocumented, you loser!)
+;; 2-Jan-95 (mon); 4:13 AM by jwz@netscape.com
+;;    Fixed Sandy's extreme keymap bogosity.  Made it invert the screen when
+;;    reading securely (this could be better; maybe use red text or something
+;;    instead...)
+;; 9-Jul-95 (fri); 4:55 AM by jwz@netscape.com
+;;    Made it work with XEmacs 19.12.
+;; 7-Jul-95 by cthomp@cs.uiuc.edu
+;;    Added variable to control inverting frame when keyboard grabbed
+
+;;; Code:
+
+(defvar passwd-invert-frame-when-keyboard-grabbed t
+  "*If non-nil swap the foreground and background colors of all faces.
+This is done while the keyboard is grabbed in order to give a visual
+clue that a grab is in effect.")
+
+(defvar passwd-echo ?.
+  "*The character which should be echoed when typing a password,
+or nil, meaning echo nothing.")
+
+(defvar read-passwd-map
+  (let ((i 0)
+       (s (make-string 1 0))
+       map)
+    (cond ((fboundp 'set-keymap-parent)
+          (setq map (make-keymap))
+          (set-keymap-parent map minibuffer-local-map))
+         (t  ; v18/FSFmacs compatibility
+          (setq map (copy-keymap minibuffer-local-map))))
+    (if (fboundp 'set-keymap-name)
+       (set-keymap-name map 'read-passwd-map))
+
+    (while (< i 127)
+      (aset s 0 i)
+      (or (and (boundp 'meta-prefix-char) (eq i meta-prefix-char))
+         (define-key map s 'self-insert-command))
+      (setq i (1+ i)))
+
+    (define-key map "\C-g" 'keyboard-quit)
+    (define-key map "\C-h" 'delete-backward-char)
+    (define-key map "\r" 'exit-minibuffer)
+    (define-key map "\n" 'exit-minibuffer)
+    (define-key map "\C-u" 'passwd-erase-buffer)
+    (define-key map "\C-q" 'quoted-insert)
+    (define-key map "\177" 'delete-backward-char)
+    (define-key map "\M-n" 'passwd-next-history-element)
+    (define-key map "\M-p" 'passwd-previous-history-element)
+    map)
+  "Keymap used for reading passwords in the minibuffer.
+The \"bindings\" in this map are not real commands; only a limited
+number of commands are understood.  The important bindings are:
+\\<read-passwd-map>
+       \\[passwd-erase-buffer] Erase all input.
+       \\[quoted-insert]       Insert the next character literally.
+       \\[delete-backward-char]        Delete the previous character.
+       \\[exit-minibuffer]     Accept what you have typed.
+       \\[keyboard-quit]       Abort the command.
+
+All other characters insert themselves (but do not echo.)")
+
+;;; internal variables
+
+(defvar passwd-history nil)
+(defvar passwd-history-posn 0)
+
+;;;###autoload
+(defun read-passwd (prompt &optional confirm default)
+  "Prompts for a password in the minibuffer, and returns it as a string.
+If PROMPT may be a prompt string or an alist of elements 
+'\(prompt . default\).
+If optional arg CONFIRM is true, then ask the user to type the password
+again to confirm that they typed it correctly.
+If optional arg DEFAULT is provided, then it is a string to insert as
+the default choice (it is not, of course, displayed.)
+
+If running under X, the keyboard will be grabbed (with XGrabKeyboard())
+to reduce the possibility that evesdropping is occuring.
+
+When reading a password, all keys self-insert, except for:
+\\<read-passwd-map>
+       \\[read-passwd-erase-line]      Erase the entire line.
+       \\[quoted-insert]       Insert the next character literally.
+       \\[delete-backward-char]        Delete the previous character.
+       \\[exit-minibuffer]     Accept what you have typed.
+       \\[keyboard-quit]       Abort the command.
+
+The returned value is always a newly-created string.  No additional copies
+of the password remain after this function has returned.
+
+NOTE: unless great care is taken, the typed password will exist in plaintext
+form in the running image for an arbitrarily long time.  Priveleged users may
+be able to extract it from memory.  If emacs crashes, it may appear in the
+resultant core file.
+
+Some steps you can take to prevent the password from being copied around:
+
+ - as soon as you are done with the returned string, destroy it with
+   (fillarray string 0).  The same goes for any default passwords
+   or password histories.
+
+ - do not copy the string, as with concat or substring - if you do, be
+   sure to keep track of and destroy all copies.
+
+ - do not insert the password into a buffer - if you do, be sure to 
+   overwrite the buffer text before killing it, as with the functions 
+   `passwd-erase-buffer' or `passwd-kill-buffer'.  Note that deleting
+   the text from the buffer does NOT necessarily remove the text from
+   memory.
+
+ - be careful of the undo history - if you insert the password into a 
+   buffer which has undo recording turned on, the password will be 
+   copied onto the undo list, and thus recoverable.
+
+ - do not pass it as an argument to a shell command - anyone will be
+   able to see it if they run `ps' at the right time.
+
+Note that the password will be temporarily recoverable with the `view-lossage'
+command.  This data will not be overwritten until another hundred or so 
+characters are typed.  There's not currently a way around this."
+
+  (save-excursion
+    (let ((input (get-buffer-create " *password*"))
+         (passwd-history-posn 0)
+         passwd-history)
+      (if (listp prompt)
+         (setq passwd-history prompt
+               default (cdr (car passwd-history))))
+      (set-buffer input)
+      (buffer-disable-undo input)
+      (use-local-map read-passwd-map)
+      (unwind-protect
+         (progn
+           (if (passwd-grab-keyboard)
+               (passwd-secure-display))
+           (read-passwd-1 input prompt nil default)
+           (set-buffer input)
+
+           (if (not confirm)
+               (buffer-string)
+             (let ((ok nil)
+                   passwd)
+               (while (not ok)
+                 (set-buffer input)
+                 (setq passwd (buffer-string))
+                 (read-passwd-1 input prompt "[Retype to confirm]")
+                 (if (passwd-compare-string-to-buffer passwd input)
+                     (setq ok t)
+                   (fillarray passwd 0)
+                   (setq passwd nil)
+                   (beep)
+                   (read-passwd-1 input prompt "[Mismatch. Start over]")
+                   ))
+               passwd)))
+       ;; protected
+       (passwd-ungrab-keyboard)
+       (passwd-insecure-display)
+       (passwd-kill-buffer input)
+       (if (fboundp 'clear-message) ;XEmacs
+           (clear-message)
+         (message ""))
+       ))))
+
+
+(defun read-passwd-1 (buffer prompt &optional prompt2 default)
+  (set-buffer buffer)
+  (passwd-erase-buffer)
+  (if default (insert default))
+  (catch 'exit ; exit-minibuffer throws here
+    (while t
+      (set-buffer buffer)
+      (let* ((minibuffer-completion-table nil)
+            (cursor-in-echo-area t)
+            (echo-keystrokes 0)
+            (key (passwd-read-key-sequence
+                  (concat (if (listp prompt)
+                              (car (nth passwd-history-posn passwd-history))
+                            prompt)
+                          prompt2
+                          (if passwd-echo
+                              (make-string (buffer-size) passwd-echo)))))
+            (binding (key-binding key)))
+       (setq prompt2 nil)
+       (set-buffer buffer)             ; just in case...
+       (if (fboundp 'event-to-character) ;; lemacs
+           (setq last-command-event (aref key (1- (length key)))
+                 last-command-char (event-to-character last-command-event))
+         ;; v18/FSFmacs compatibility
+         (setq last-command-char (aref key (1- (length key)))))
+       (setq this-command binding)
+       (condition-case c
+           (command-execute binding)
+         (error
+          (beep)
+          (if (fboundp 'display-error)
+              (display-error c t)
+            ;; v18/FSFmacs compatibility
+            (message (concat (or (get (car-safe c) 'error-message) "???")
+                             (if (cdr-safe c) ": ")
+                             (mapconcat 
+                              (function (lambda (x) (format "%s" x)))
+                              (cdr-safe c) ", "))))
+          (sit-for 2)))
+       ))))
+
+(defun passwd-previous-history-element (n)
+  (interactive "p")
+  (or passwd-history
+      (error "Password history is empty."))
+  (let ((l (length passwd-history)))
+    (setq passwd-history-posn
+         (% (+ n passwd-history-posn) l))
+    (if (< passwd-history-posn 0)
+       (setq passwd-history-posn (+ passwd-history-posn l))))
+  (let ((obuff (current-buffer))) ; want to move point in passwd buffer
+    (unwind-protect
+       (progn
+         (set-buffer " *password*")
+         (passwd-erase-buffer)
+         (insert (cdr (nth passwd-history-posn passwd-history))))
+      (set-buffer obuff))))
+
+(defun passwd-next-history-element (n)
+  (interactive "p")
+  (passwd-previous-history-element (- n)))
+
+(defun passwd-erase-buffer ()
+  ;; First erase the buffer, which will simply enlarge the gap.
+  ;; Then insert null characters until the gap is filled with them
+  ;; to prevent the old text from being visible in core files or kmem.
+  ;; (Actually use 3x the size of the buffer just to be safe - a longer
+  ;; passwd might have been typed and backspaced over.)
+  (interactive)
+  (widen)
+  (let ((s (* (buffer-size) 3)))
+    (erase-buffer)
+    (while (> s 0)
+      (insert ?\000)
+      (setq s (1- s)))
+    (erase-buffer)))
+
+(defun passwd-kill-buffer (buffer)
+  (save-excursion
+    (set-buffer buffer)
+    (buffer-disable-undo buffer)
+    (passwd-erase-buffer)
+    (set-buffer-modified-p nil))
+  (kill-buffer buffer))
+
+
+(defun passwd-compare-string-to-buffer (string buffer)
+  ;; same as (equal string (buffer-string)) but with no dangerous consing.
+  (save-excursion
+    (set-buffer buffer)
+    (goto-char (point-min))
+    (let ((L (length string))
+         (i 0))
+      (if (/= L (- (point-max) (point-min)))
+         nil
+       (while (not (eobp))
+         (if (/= (following-char) (aref string i))
+             (goto-char (point-max))
+           (setq i (1+ i))
+           (forward-char)))
+       (= (point) (+ i (point-min)))))))
+
+
+(defvar passwd-face-data nil)
+(defun passwd-secure-display ()
+  ;; Inverts the screen - used to indicate secure input, like xterm.
+  (cond
+   ((and passwd-invert-frame-when-keyboard-grabbed
+        (fboundp 'set-face-foreground))
+    (setq passwd-face-data
+         (delq nil (mapcar (function
+                            (lambda (face)
+                              (let ((fg (face-foreground face))
+                                    (bg (face-background face)))
+                                (if (or fg bg)
+                                    (if (fboundp 'color-name)
+                                        (list face
+                                              (color-name fg)
+                                              (color-name bg))
+                                      (list face fg bg))
+                                  nil))))
+                           (if (fboundp 'list-faces)
+                               (list-faces) ; lemacs
+                             (face-list)    ; FSFmacs
+                             ))))
+    (let ((rest passwd-face-data))
+      (while rest
+       (set-face-foreground (nth 0 (car rest)) (nth 2 (car rest)))
+       (set-face-background (nth 0 (car rest)) (nth 1 (car rest)))
+       (setq rest (cdr rest))))))
+  nil)
+
+(defun passwd-insecure-display ()
+  ;; Undoes the effect of `passwd-secure-display'.
+  (cond
+   (passwd-invert-frame-when-keyboard-grabbed
+    (while passwd-face-data
+      (set-face-foreground (nth 0 (car passwd-face-data))
+                          (nth 1 (car passwd-face-data)))
+      (set-face-background (nth 0 (car passwd-face-data))
+                          (nth 2 (car passwd-face-data)))
+      (setq passwd-face-data (cdr passwd-face-data)))
+    nil)))
+
+(defun passwd-grab-keyboard ()
+  (cond ((not (and (fboundp 'x-grab-keyboard) ; lemacs 19.10+
+                  (eq 'x (if (fboundp 'frame-type)
+                             (frame-type (selected-frame))
+                           (live-screen-p (selected-screen))))))
+        nil)
+       ((x-grab-keyboard)
+        t)
+       (t
+        (message "Unable to grab keyboard - waiting a second...")
+        (sleep-for 1)
+        (cond ((x-grab-keyboard)
+               (message "Keyboard grabbed on second try.")
+               t)
+              (t
+               (beep)
+               (message "WARNING: keyboard is insecure (unable to grab!)")
+               (sleep-for 3)
+               nil)))))
+
+(defun passwd-ungrab-keyboard ()
+  (if (and (fboundp 'x-ungrab-keyboard) ; lemacs 19.10+
+          (eq 'x (if (fboundp 'frame-type)
+                     (frame-type (selected-frame))
+                   (live-screen-p (selected-screen)))))
+      (x-ungrab-keyboard)))
+
+;; v18 compatibility
+(or (fboundp 'buffer-disable-undo)
+    (fset 'buffer-disable-undo 'buffer-flush-undo))
+
+;; read-key-sequence echoes the key sequence in Emacs 18.
+(defun passwd-read-key-sequence (prompt)
+  (let ((inhibit-quit t)
+       str)
+    (while (or (null str) (keymapp (key-binding str)))
+      (if (fboundp 'display-message)
+         (display-message 'prompt prompt)
+       (message prompt))
+      (setq str (concat str (char-to-string (read-char)))))
+    (setq quit-flag nil)
+    str))
+
+(or (string-match "^18" emacs-version)
+    (fset 'passwd-read-key-sequence 'read-key-sequence))
+
+(provide 'passwd)
+
+;;; passwd.el ends here
diff --git a/contrib/regexp-opt.el b/contrib/regexp-opt.el
new file mode 100644 (file)
index 0000000..589f1b7
--- /dev/null
@@ -0,0 +1,238 @@
+;;; regexp-opt.el --- generate efficient regexps to match strings.
+
+;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
+;; Keywords: strings, regexps
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The "opt" in "regexp-opt" stands for "optim\\(al\\|i\\(se\\|ze\\)\\)".
+;;
+;; This package generates a regexp from a given list of strings (which matches
+;; one of those strings) so that the regexp generated by:
+;;
+;; (regexp-opt strings)
+;;
+;; is equivalent to, but more efficient than, the regexp generated by:
+;;
+;; (mapconcat 'regexp-quote strings "\\|")
+;;
+;; For example:
+;;
+;; (let ((strings '("cond" "if" "when" "unless" "while"
+;;                 "let" "let*" "progn" "prog1" "prog2"
+;;                 "save-restriction" "save-excursion" "save-window-excursion"
+;;                 "save-current-buffer" "save-match-data"
+;;                 "catch" "throw" "unwind-protect" "condition-case")))
+;;   (concat "(" (regexp-opt strings t) "\\>"))
+;;  => "(\\(c\\(atch\\|ond\\(ition-case\\)?\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(current-buffer\\|excursion\\|match-data\\|restriction\\|window-excursion\\)\\|throw\\|un\\(less\\|wind-protect\\)\\|wh\\(en\\|ile\\)\\)\\>"
+;;
+;; Searching using the above example `regexp-opt' regexp takes approximately
+;; two-thirds of the time taken using the equivalent `mapconcat' regexp.
+
+;; Since this package was written to produce efficient regexps, not regexps
+;; efficiently, it is probably not a good idea to in-line too many calls in
+;; your code, unless you use the following trick with `eval-when-compile':
+;;
+;; (defvar definition-regexp
+;;   (eval-when-compile
+;;     (concat "^("
+;;             (regexp-opt '("defun" "defsubst" "defmacro" "defalias"
+;;                           "defvar" "defconst") t)
+;;             "\\>")))
+;;
+;; The `byte-compile' code will be as if you had defined the variable thus:
+;;
+;; (defvar definition-regexp
+;;   "^(\\(def\\(alias\\|const\\|macro\\|subst\\|un\\|var\\)\\)\\>")
+;;
+;; Note that if you use this trick for all instances of `regexp-opt' and
+;; `regexp-opt-depth' in your code, regexp-opt.el would only have to be loaded
+;; at compile time.  But note also that using this trick means that should
+;; regexp-opt.el be changed, perhaps to fix a bug or to add a feature to
+;; improve the efficiency of `regexp-opt' regexps, you would have to recompile
+;; your code for such changes to have effect in your code.
+
+;; Originally written for font-lock.el, from an idea from Stig's hl319.el, with
+;; thanks for ideas also to Michael Ernst, Bob Glickstein and Dan Nicolaescu.
+;; Please don't tell me that it doesn't produce optimal regexps; I know that
+;; already.  For example, the above explanation for the meaning of "opt" would
+;; be more efficient as "optim\\(al\\|i[sz]e\\)", but this requires complex
+;; forward looking.  But (ideas or) code to improve things (are) is welcome.
+\f
+;;; Code:
+
+;;;###autoload
+(defun regexp-opt (strings &optional paren)
+  "Return a regexp to match a string in STRINGS.
+Each string should be unique in STRINGS and should not contain any regexps,
+quoted or not.  If optional PAREN is non-nil, ensure that the returned regexp
+is enclosed by at least one regexp grouping construct.
+The returned regexp is typically more efficient than the equivalent regexp:
+
+ (let ((open-paren (if PAREN \"\\\\(\" \"\")) (close-paren (if PAREN \"\\\\)\" \"\")))
+   (concat open-paren (mapconcat 'regexp-quote STRINGS \"\\\\|\") close-paren))
+
+but typically contains more regexp grouping constructs.
+Use `regexp-opt-depth' to count them."
+  (save-match-data
+    ;; Recurse on the sorted list.
+    (let ((max-lisp-eval-depth (* 1024 1024))
+         (completion-ignore-case nil))
+      (regexp-opt-group (sort (copy-sequence strings) 'string-lessp) paren))))
+
+;;;###autoload
+(defun regexp-opt-depth (regexp)
+  "Return the depth of REGEXP.
+This means the number of regexp grouping constructs (parenthesised expressions)
+in REGEXP."
+  (save-match-data
+    ;; Hack to signal an error if REGEXP does not have balanced parentheses.
+    (string-match regexp "")
+    ;; Count the number of open parentheses in REGEXP.
+    (let ((count 0) start)
+      (while (string-match "\\\\(" regexp start)
+       (setq count (1+ count) start (match-end 0)))
+      count)))
+\f
+;;; Workhorse functions.
+
+(eval-when-compile
+  (require 'cl))
+
+(unless (fboundp 'make-bool-vector)
+  (defalias 'make-bool-vector 'make-vector))
+
+(defun regexp-opt-group (strings &optional paren lax)
+  ;;
+  ;; Return a regexp to match a string in STRINGS.
+  ;; If PAREN non-nil, output regexp parentheses around returned regexp.
+  ;; If LAX non-nil, don't output parentheses if it doesn't require them.
+  ;; Merges keywords to avoid backtracking in Emacs' regexp matcher.
+  ;;
+  ;; The basic idea is to find the shortest common prefix, remove it and
+  ;; recurse.  If there is no prefix, we divide the list into two so that (at
+  ;; least) one half will have at least a one-character common prefix.
+  ;;
+  ;; Also we delay the addition of grouping parenthesis as long as possible
+  ;; until we're sure we need them, and try to remove one-character sequences
+  ;; so we can use character sets rather than grouping parenthesis.
+  ;;
+  (let* ((open-group (if paren "\\(" ""))
+        (close-group (if paren "\\)" ""))
+        (open-charset (if lax "" open-group))
+        (close-charset (if lax "" close-group)))
+    (cond
+     ;;
+     ;; If there is only one string, just return it.
+     ((= (length strings) 1)
+      (if (= (length (car strings)) 1)
+         (concat open-charset (regexp-quote (car strings)) close-charset)
+       (concat open-group (regexp-quote (car strings)) close-group)))
+     ;;
+     ;; If there is an empty string, remove it and recurse on the rest.
+     ((= (length (car strings)) 0)
+      (concat open-charset
+             (regexp-opt-group (cdr strings) t t) "?"
+             close-charset))
+     ;;
+     ;; If all are one-character strings, just return a character set.
+     ((= (length strings) (apply '+ (mapcar 'length strings)))
+      (concat open-charset
+             (regexp-opt-charset strings)
+             close-charset))
+     ;;
+     ;; We have a list of different length strings.
+     (t
+      (let ((prefix (try-completion "" (mapcar 'list strings)))
+           (letters (let ((completion-regexp-list '("^.$")))
+                      (all-completions "" (mapcar 'list strings)))))
+       (cond
+        ;;
+        ;; If there is a common prefix, remove it and recurse on the suffixes.
+        ((> (length prefix) 0)
+         (let* ((length (length prefix))
+                (suffixes (mapcar (lambda (s) (substring s length)) strings)))
+           (concat open-group
+                   (regexp-quote prefix) (regexp-opt-group suffixes t t)
+                   close-group)))
+        ;;
+        ;; If there are several one-character strings, remove them and recurse
+        ;; on the rest (first so the final regexp finds the longest match).
+        ((> (length letters) 1)
+         (let ((rest (let ((completion-regexp-list '("^..+$")))
+                       (all-completions "" (mapcar 'list strings)))))
+           (concat open-group
+                   (regexp-opt-group rest) "\\|" (regexp-opt-charset letters)
+                   close-group)))
+        ;;
+        ;; Otherwise, divide the list into those that start with a particular
+        ;; letter and those that do not, and recurse on them.
+        (t
+         (let* ((char (substring (car strings) 0 1))
+                (half1 (all-completions char (mapcar 'list strings)))
+                (half2 (nthcdr (length half1) strings)))
+           (concat open-group
+                   (regexp-opt-group half1) "\\|" (regexp-opt-group half2)
+                   close-group)))))))))
+
+(defun regexp-opt-charset (chars)
+  ;;
+  ;; Return a regexp to match a character in CHARS.
+  ;;
+  ;; The basic idea is to find character ranges.  Also we take care in the
+  ;; position of character set meta characters in the character set regexp.
+  ;;
+  (let* ((charwidth 256)                               ; Yeah, right.
+        (charmap (make-bool-vector charwidth nil))
+        (charset "")
+        (bracket "") (dash "") (caret ""))
+    ;;
+    ;; Make a character map but extract character set meta characters.
+    (dolist (char (mapcar 'string-to-char chars))
+      (case char
+       (?\]
+        (setq bracket "]"))
+       (?^
+        (setq caret "^"))
+       (?-
+        (setq dash "-"))
+       (otherwise
+        (aset charmap char t))))
+    ;;
+    ;; Make a character set from the map using ranges where applicable.
+    (dotimes (char charwidth)
+      (let ((start char))
+       (while (and (< char charwidth) (aref charmap char))
+         (incf char))
+       (cond ((> char (+ start 3))
+              (setq charset (format "%s%c-%c" charset start (1- char))))
+             ((> char start)
+              (setq charset (format "%s%c" charset (setq char start)))))))
+    ;;
+    ;; Make sure a caret is not first and a dash is first or last.
+    (if (and (string-equal charset "") (string-equal bracket ""))
+       (concat "[" dash caret "]")
+      (concat "[" bracket charset caret dash "]"))))
+
+(provide 'regexp-opt)
+
+;;; regexp-opt.el ends here
diff --git a/contrib/ssl.el b/contrib/ssl.el
new file mode 100644 (file)
index 0000000..fcb2509
--- /dev/null
@@ -0,0 +1,201 @@
+;;; ssl.el,v --- ssl functions for emacsen without them builtin
+;; Author: #Author: zsh #
+;; Created: #Date: 2001/07/13 19:31:09 #
+;; Version: #Revision: 1.2 #
+;; Keywords: comm
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Copyright (c) 1995, 1996 by William M. Perry <wmperry@cs.indiana.edu>
+;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Emacs.
+;;;
+;;; GNU Emacs is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Emacs is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;;; Boston, MA 02111-1307, USA.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when-compile (require 'cl))
+(require 'base64)
+
+(eval-and-compile
+  (condition-case ()
+      (require 'custom)
+    (error nil))
+  (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
+      nil ;; We've got what we needed
+    ;; We have the old custom-library, hack around it!
+    (defmacro defgroup (&rest args)
+      nil)
+    (defmacro defcustom (var value doc &rest args) 
+      (` (defvar (, var) (, value) (, doc))))))
+
+(defgroup ssl nil
+  "Support for `Secure Sockets Layer' encryption."
+  :group 'comm)
+  
+(defcustom ssl-certificate-directory "~/.w3/certs/"
+  "*Directory to store CA certificates in"
+  :group 'ssl
+  :type 'directory)
+
+(defcustom ssl-rehash-program-name "c_rehash"
+  "*Program to run after adding a cert to a directory .
+Run with one argument, the directory name."
+  :group 'ssl
+  :type 'string)
+
+(defcustom ssl-view-certificate-program-name "x509"
+  "*The program to run to provide a human-readable view of a certificate."
+  :group 'ssl
+  :type 'string)
+
+(defcustom ssl-view-certificate-program-arguments '("-text" "-inform" "DER")
+  "*Arguments that should be passed to the certificate viewing program.
+The certificate is piped to it.
+Maybe a way of passing a file should be implemented"
+  :group 'ssl
+  :type 'list)
+
+(defcustom ssl-certificate-directory-style 'ssleay
+  "*Style of cert database to use, the only valid value right now is `ssleay'.
+This means a directory of pem encoded certificates with hash symlinks."
+  :group 'ssl
+  :type '(choice (const :tag "SSLeay" :value ssleay)
+                (const :tag "OpenSSL" :value openssl)))
+
+(defcustom ssl-certificate-verification-policy 0
+  "*How far up the certificate chain we should verify."
+  :group 'ssl
+  :type '(choice (const :tag "No verification" :value 0)
+                (const :tag "Verification required" :value 1)
+                (const :tag "Reject connection if verification fails" :value 3)
+                (const :tag "SSL_VERIFY_CLIENT_ONCE" :value 5)))
+
+(defcustom ssl-program-name "openssl"
+  "*The program to run in a subprocess to open an SSL connection."
+  :group 'ssl
+  :type 'string)
+
+(defcustom ssl-program-arguments
+  '("s_client"
+    "-quiet"
+    "-host" host
+    "-port" service
+    "-verify" (int-to-string ssl-certificate-verification-policy)
+    "-CApath" ssl-certificate-directory
+    )
+  "*Arguments that should be passed to the program `ssl-program-name'.
+This should be used if your SSL program needs command line switches to
+specify any behaviour (certificate file locations, etc).
+The special symbols 'host and 'port may be used in the list of arguments
+and will be replaced with the hostname and service/port that will be connected
+to."
+  :group 'ssl
+  :type 'list)
+
+(defun ssl-certificate-information (der)
+  "Return an assoc list of information about a certificate in DER format."
+  (let ((certificate (concat "-----BEGIN CERTIFICATE-----\n"
+                            (base64-encode-string der)
+                            "\n-----END CERTIFICATE-----\n"))
+       (exit-code 0))
+    (save-excursion
+      (set-buffer (get-buffer-create " *openssl*"))
+      (erase-buffer)
+      (insert certificate)
+      (setq exit-code (condition-case ()
+                         (call-process-region (point-min) (point-max)
+                                              ssl-program-name
+                                              t (list (current-buffer) nil) t
+                                              "x509"
+                                              "-subject" ; Print the subject DN
+                                              "-issuer" ; Print the issuer DN
+                                              "-dates" ; Both before and after dates
+                                              "-serial" ; print out serial number
+                                              "-noout" ; Don't spit out the certificate
+                                              )
+                       (error -1)))
+      (if (/= exit-code 0)
+         nil
+       (let ((vals nil))
+         (goto-char (point-min))
+         (while (re-search-forward "^\\([^=\n\r]+\\)\\s *=\\s *\\(.*\\)" nil t)
+           (push (cons (match-string 1) (match-string 2)) vals))
+         vals)))))
+  
+(defun ssl-accept-ca-certificate ()
+  "Ask if the user is willing to accept a new CA certificate. The buffer-name
+should be the intended name of the certificate, and the buffer should probably
+be in DER encoding"
+  ;; TODO, check if it is really new or if we already know it
+  (let* ((process-connection-type nil)
+        (tmpbuf (generate-new-buffer "X509 CA Certificate Information"))
+        (response (save-excursion
+                    (and (eq 0 
+                             (apply 'call-process-region
+                                    (point-min) (point-max) 
+                                    ssl-view-certificate-program-name 
+                                    nil tmpbuf t
+                                    ssl-view-certificate-program-arguments))
+                         (switch-to-buffer tmpbuf)
+                         (goto-char (point-min))
+                         (or (recenter) t)
+                         (yes-or-no-p
+                          "Accept this CA to vouch for secure server identities? ")
+                         (kill-buffer tmpbuf)))))
+    (if (not response)
+       nil
+      (if (not (file-directory-p ssl-certificate-directory))
+         (make-directory ssl-certificate-directory))
+      (case ssl-certificate-directory-style
+       (ssleay
+        (base64-encode-region (point-min) (point-max))
+        (goto-char (point-min))
+        (insert "-----BEGIN CERTIFICATE-----\n")
+        (goto-char (point-max))
+        (insert "-----END CERTIFICATE-----\n")
+        (let ((f (expand-file-name
+                  (concat (file-name-sans-extension (buffer-name)) ".pem")
+                  ssl-certificate-directory)))
+          (write-file f)
+          (call-process ssl-rehash-program-name
+                        nil nil nil
+                        (expand-file-name ssl-certificate-directory))))))))
+
+(defun open-ssl-stream (name buffer host service)
+  "Open a SSL connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer-name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+  (if (integerp service) (setq service (int-to-string service)))
+  (let* ((process-connection-type nil)
+        (port service)
+        (proc (eval
+               (`
+                (start-process name buffer ssl-program-name
+                               (,@ ssl-program-arguments))))))
+    (process-kill-without-query proc)
+    proc))
+
+(provide 'ssl)
diff --git a/contrib/starttls.el b/contrib/starttls.el
new file mode 100644 (file)
index 0000000..95db27f
--- /dev/null
@@ -0,0 +1,227 @@
+;;; starttls.el --- STARTTLS support via wrapper around GNU TLS
+
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: comm, tls, gnutls, ssl
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package implements a simple wrapper around the GNU TLS command
+;; line application "gnutls-cli" to make Emacs support STARTTLS.  It
+;; is backwards compatible (same API functions) with the "starttls.el"
+;; that is part of Emacs 21 written by Daiki Ueno <ueno@unixuser.org>.
+;; (That version used an external program "starttls" that isn't widely
+;; installed, and was based on OpenSSL.)
+
+;; This package require GNUTLS 0.9.90 (released 2003-10-08) or later.
+
+;; Usage is similar to `open-network-stream'.  Evaluating the following:
+;;
+;; (progn
+;;   (setq tmp (open-starttls-stream "test" (current-buffer) "mail.example.com" 143))
+;;   (process-send-string tmp ". starttls\n")
+;;   (sit-for 4)
+;;   (message "STARTTLS output:\n%s" (negotiate-starttls tmp))
+;;   (process-send-string tmp ". capability\n"))
+;;
+;; in, e.g., the *scratch* buffer, yields the following output:
+;;
+;; * OK imap.example.com Cyrus IMAP4 v2.1.15 server ready\r
+;; . OK Begin TLS negotiation now\r
+;; * CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA ...
+;; . OK Completed\r
+;; nil
+;;
+;; And the message buffer contains:
+;;
+;; STARTTLS output:
+;; *** Starting TLS handshake
+;; - Server's trusted authorities:
+;;    [0]: O=Sendmail,OU=Sendmail Server,CN=imap.example.com,EMAIL=admin@imap.example.com
+;; - Certificate type: X.509
+;;  - Got a certificate list of 1 certificates.
+;;
+;;  - Certificate[0] info:
+;;  # The hostname in the certificate matches 'imap.example.com'.
+;;  # valid since: Wed Aug 28 12:47:00 CEST 2002
+;;  # expires at: Thu Aug 28 12:47:00 CEST 2003
+;;  # serial number: 00
+;;  # fingerprint: 06 3f 25 cb 44 aa 5c 1e 79 d7 63 86 f8 b1 9a cf
+;;  # version: #3
+;;  # public key algorithm: RSA
+;;  #   Modulus: 1024 bits
+;;  # Subject's DN: O=Sendmail,OU=Sendmail Server,CN=imap.example.com,EMAIL=admin@imap.example.com
+;;  # Issuer's DN: O=Sendmail,OU=Sendmail Server,CN=imap.example.com,EMAIL=admin@imap.example.com
+;;
+;;
+;; - Peer's certificate issuer is unknown
+;; - Peer's certificate is NOT trusted
+;; - Version: TLS 1.0
+;; - Key Exchange: RSA
+;; - Cipher: ARCFOUR 128
+;; - MAC: SHA
+;; - Compression: NULL
+
+;; Revision history:
+;;
+;; 2003-09-20: Added to Gnus CVS.
+;; 2003-10-02: Minor fixes.
+;; 2003-11-15: Cleanup, and posted to gnu.emacs.sources.
+;; 2003-11-28: Fixes variable name conflicts, various other fixes, posted g.e.s.
+
+;;; Code:
+
+(defgroup starttls nil
+  "Negotiated Transport Layer Security (STARTTLS) parameters."
+  :group 'comm)
+
+(defcustom starttls-file-name "gnutls-cli"
+  "Name of the program to run in a subprocess to open an STARTTLS connection.
+The program should read input on stdin, write output to stdout,
+and initiate TLS negotiation when receiving the SIGALRM signal.
+Also see `starttls-connect', `starttls-failure', and
+`starttls-success' for what the program should output after
+initial connection and successful negotiation respectively."
+  :type 'string
+  :group 'starttls)
+
+(defcustom starttls-extra-arguments nil
+  "List of extra arguments to `starttls-file-name'.
+E.g., (\"--protocols\" \"ssl3\")."
+  :type '(repeat string)
+  :group 'starttls)
+
+(defcustom starttls-process-connection-type nil
+  "*Value for `process-connection-type' to use when starting STARTTLS process."
+  :type 'boolean
+  :group 'starttls)
+
+(defcustom starttls-connect "- Simple Client Mode:\n\n"
+  "*Regular expression indicating successful connection.
+The default is what GNUTLS's \"gnutls-cli\" outputs."
+  ;; GNUTLS cli.c:main() print this string when it is starting to run
+  ;; in the application read/write phase.  If the logic, or the string
+  ;; itself, is modified, this must be updated.
+  :type 'regexp
+  :group 'starttls)
+
+(defcustom starttls-failure "*** Handshake has failed"
+  "*Regular expression indicating failed TLS handshake.
+The default is what GNUTLS's \"gnutls-cli\" outputs."
+  ;; GNUTLS cli.c:do_handshake() print this string on failure.  If the
+  ;; logic, or the string itself, is modified, this must be updated.
+  :type 'regexp
+  :group 'starttls)
+
+(defcustom starttls-success "- Compression: "
+  "*Regular expression indicating completed TLS handshakes.
+The default is what GNUTLS's \"gnutls-cli\" outputs."
+  ;; GNUTLS cli.c:do_handshake() calls, on success,
+  ;; common.c:print_info(), that unconditionally print this string
+  ;; last.  If that logic, or the string itself, is modified, this
+  ;; must be updated.
+  :type 'regexp
+  :group 'starttls)
+
+(defun negotiate-starttls (process)
+  "Negotiate TLS on process opened by `open-starttls-stream'.
+This should typically only be done once.  It typically return a
+multi-line informational message with information about the
+handshake, or NIL on failure."
+  (let (buffer info old-max done-ok done-bad)
+    (if (null (setq buffer (process-buffer process)))
+       ;; XXX How to remove/extract the TLS negotiation junk?
+       (signal-process (process-id process) 'SIGALRM)
+      (with-current-buffer buffer
+       (save-excursion
+         (setq old-max (goto-char (point-max)))
+         (signal-process (process-id process) 'SIGALRM)
+         (while (and (processp process)
+                     (eq (process-status process) 'run)
+                     (save-excursion
+                       (goto-char old-max)
+                       (not (or (setq done-ok (re-search-forward
+                                               starttls-success nil t))
+                                (setq done-bad (re-search-forward
+                                                starttls-failure nil t))))))
+           (accept-process-output process 1 100)
+           (sit-for 0.1))
+         (setq info (buffer-substring-no-properties old-max (point-max)))
+         (delete-region old-max (point-max))
+         (if (or (and done-ok (not done-bad))
+                 ;; Prevent mitm that fake success msg after failure msg.
+                 (and done-ok done-bad (< done-ok done-bad)))
+             info
+           (message "STARTTLS negotiation failed: %s" info)
+           nil))))))
+
+(defun open-starttls-stream (name buffer host service)
+  "Open a TLS connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer-name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+  (message "Opening STARTTLS connection to `%s'..." host)
+  (let* (done
+        (old-max (with-current-buffer buffer (point-max)))
+        (process-connection-type starttls-process-connection-type)
+        (process (apply #'start-process name buffer
+                        starttls-file-name "-s" host
+                        "-p" (if (integerp service)
+                                 (int-to-string service)
+                               service)
+                        starttls-extra-arguments)))
+    (process-kill-without-query process)
+    (while (and (processp process)
+               (eq (process-status process) 'run)
+               (save-excursion
+                 (set-buffer buffer)
+                 (goto-char old-max)
+                 (not (setq done (re-search-forward
+                                  starttls-connect nil t)))))
+      (accept-process-output process 0 100)
+      (sit-for 0.1))
+    (if done
+       (with-current-buffer buffer
+         (delete-region old-max done))
+      (delete-process process)
+      (setq process nil))
+    (message "Opening STARTTLS connection to `%s'...%s"
+            host (if done "done" "failed"))
+    process))
+
+;; Compatibility with starttls.el by Daiki Ueno <ueno@unixuser.org>:
+(defvaralias 'starttls-program 'starttls-file-name)
+(make-obsolete-variable 'starttls-program 'starttls-file-name)
+(defvaralias 'starttls-extra-args 'starttls-extra-arguments)
+(make-obsolete-variable 'starttls-extra-args 'starttls-extra-arguments)
+(defalias 'starttls-open-stream 'open-starttls-stream)
+(defalias 'starttls-negotiate 'negotiate-starttls)
+
+(provide 'starttls)
+
+;;; starttls.el ends here
diff --git a/contrib/timer.el b/contrib/timer.el
new file mode 100644 (file)
index 0000000..70d9940
--- /dev/null
@@ -0,0 +1,308 @@
+;;; timer.el --- run a function with args at some time in future.
+
+;; Copyright (C) 1996 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package gives you the capability to run Emacs Lisp commands at
+;; specified times in the future, either as one-shots or periodically.
+
+;;; Code:
+
+(require 'itimer)
+
+(fset 'timer-create 'make-itimer)
+
+(fset 'timerp 'itimerp)
+
+;(defvar timer-idle-list nil
+;  "List of active idle-time timers in order of increasing time")
+(defvaralias 'timer-idle-list 'itimer-list)
+(defvaralias 'timer-list 'itimer-list)
+
+
+(defun timer-set-time (timer time &optional delta)
+  "Set the trigger time of TIMER to TIME.
+TIME must be in the internal format returned by, e.g., `current-time'.
+If optional third argument DELTA is a non-zero integer, make the timer
+fire repeatedly that many seconds apart."
+  (set-itimer-value timer (itimer-time-difference time (current-time)))
+  (and delta (check-nonnegative-number delta))
+  (and delta (set-itimer-restart timer delta))
+  timer)
+
+(defun timer-set-idle-time (timer secs &optional repeat)
+  "Set the trigger idle time of TIMER to SECS.
+If optional third argument REPEAT is non-nil, make the timer
+fire each time Emacs is idle for that many seconds."
+  (set-itimer-is-idle timer t)
+  (set-itimer-value timer secs)
+  (when repeat
+    (set-itimer-restart timer secs))
+  timer)
+
+(defun timer-relative-time (time secs &optional usecs)
+  "Advance TIME by SECS seconds and optionally USECS microseconds.
+SECS may be a fraction."
+  (let ((high (car time))
+       (low (if (consp (cdr time)) (nth 1 time) (cdr time)))
+       (micro (if (numberp (car-safe (cdr-safe (cdr time))))
+                  (nth 2 time)
+                0)))
+    ;; Add
+    (if usecs (setq micro (+ micro usecs)))
+    (if (floatp secs)
+       (setq micro (+ micro (floor (* 1000000 (- secs (floor secs)))))))
+    (setq low (+ low (floor secs)))
+
+    ;; Normalize
+    (setq low (+ low (/ micro 1000000)))
+    (setq micro (mod micro 1000000))
+    (setq high (+ high (/ low 65536)))
+    (setq low (logand low 65535))
+
+    (list high low (and (/= micro 0) micro))))
+
+(defun timer-inc-time (timer secs &optional usecs)
+  "Increment the time set in TIMER by SECS seconds and USECS microseconds.
+SECS may be a fraction."
+  (let ((time (itimer-value timer)))
+    (setq time (+ time secs (if (and usecs (fboundp 'lisp-float-type))
+                               (/ usecs (float 1000000))
+                             0)))
+    (set-itimer-value timer time)))
+
+(defun timer-set-time-with-usecs (timer time usecs &optional delta)
+  "Set the trigger time of TIMER to TIME.
+TIME must be in the internal format returned by, e.g., `current-time'.
+If optional third argument DELTA is a non-zero integer, make the timer
+fire repeatedly that many seconds apart."
+  (let ((list (list nil nil nil)))
+    (setcar list (car time))
+    (setcar (nthcdr 1 list) (if (consp (cdr time))
+                               (car (cdr time))
+                             (cdr time)))
+    (setcar (nthcdr 2 list) usecs)
+    (set-itimer-value timer (itimer-time-difference list (current-time)))
+    (set-itimer-restart timer delta)
+    timer))
+
+(defun timer-set-function (timer function &optional args)
+  "Make TIMER call FUNCTION with optional ARGS when triggering."
+  (set-itimer-function timer function)
+  (set-itimer-function-arguments timer args)
+  (set-itimer-uses-arguments timer t)
+  timer)
+\f
+(defun timer-activate (timer)
+  "Put TIMER on the list of active timers."
+  (activate-itimer timer))
+
+(defun timer-activate-when-idle (timer)
+  "Arrange to activate TIMER whenever Emacs is next idle."
+  (set-itimer-is-idle timer t)
+  ;(set-itimer-uses-arguments timer nil)
+  ;(unless (memq timer timer-idle-list)
+    ;(setq timer-idle-list (cons timer timer-idle-list)))
+  (activate-itimer timer))
+
+;; can't do this, different kind of timer
+;;(defalias 'disable-timeout 'cancel-timer)
+
+(defun cancel-timer (timer)
+  "Remove TIMER from the list of active timers."
+  ;(setq timer-idle-list (delq timer timer-idle-list))
+  (delete-itimer timer))
+
+(defun cancel-function-timers (function)
+  "Cancel all timers scheduled by `run-at-time' which would run FUNCTION."
+  (interactive "aCancel timers of function: ")
+  (let ((p itimer-list))
+    (while p
+      (if (eq function (itimer-function p))
+         (progn
+           (setq p (cdr p))
+           (delete-itimer (car p)))
+       (setq p (cdr p))))))
+\f
+;;;###autoload
+(defun run-at-time (time repeat function &rest args)
+  "Perform an action after a delay of SECS seconds.
+Repeat the action every REPEAT seconds, if REPEAT is non-nil.
+TIME should be a string like \"11:23pm\", nil meaning now, a number of seconds
+from now, or a value from `encode-time'.
+REPEAT may be an integer or floating point number.
+The action is to call FUNCTION with arguments ARGS.
+
+This function returns a timer object which you can use in `cancel-timer'."
+  (interactive "sRun at time: \nNRepeat interval: \naFunction: ")
+
+  ;; Special case: nil means "now" and is useful when repeating.
+  (if (null time)
+      (setq time (current-time)))
+
+  ;; Handle numbers as relative times in seconds.
+  (if (numberp time)
+      (setq time (timer-relative-time (current-time) time)))
+
+  ;; Handle relative times like "2 hours and 35 minutes"
+  (if (stringp time)
+      (let ((secs (timer-duration time)))
+       (if secs
+           (setq time (timer-relative-time (current-time) secs)))))
+
+  ;; Handle "11:23pm" and the like.  Interpret it as meaning today
+  ;; which admittedly is rather stupid if we have passed that time
+  ;; already.  (Though only Emacs hackers hack Emacs at that time.)
+  (if (stringp time)
+      (progn
+       (require 'diary-lib)
+       (let ((hhmm (diary-entry-time time))
+             (now (decode-time)))
+         (if (>= hhmm 0)
+             (setq time
+                   (encode-time 0 (% hhmm 100) (/ hhmm 100) (nth 3 now)
+                                (nth 4 now) (nth 5 now) (nth 8 now)))))))
+
+  (or (consp time)
+      (error "Invalid time format"))
+
+  (or (null repeat)
+      (numberp repeat)
+      (error "Invalid repetition interval"))
+
+  (let ((timer (timer-create)))
+    (timer-set-time timer time repeat)
+    (timer-set-function timer function args)
+    (timer-activate timer)
+    timer))
+
+;;;###autoload
+(defun run-with-timer (secs repeat function &rest args)
+  "Perform an action after a delay of SECS seconds.
+Repeat the action every REPEAT seconds, if REPEAT is non-nil.
+SECS and REPEAT may be integers or floating point numbers.
+The action is to call FUNCTION with arguments ARGS.
+
+This function returns a timer object which you can use in `cancel-timer'."
+  (interactive "sRun after delay (seconds): \nNRepeat interval: \naFunction: ")
+  (apply 'run-at-time secs repeat function args))
+
+;;;###autoload
+(defun run-with-idle-timer (secs repeat function &rest args)
+  "Perform an action the next time Emacs is idle for SECS seconds.
+If REPEAT is non-nil, do this each time Emacs is idle for SECS seconds.
+SECS may be an integer or a floating point number.
+The action is to call FUNCTION with arguments ARGS.
+
+This function returns a timer object which you can use in `cancel-timer'."
+  (interactive
+   (list (read-from-minibuffer "Run after idle (seconds): " nil nil t)
+        (y-or-n-p "Repeat each time Emacs is idle? ")
+        (intern (completing-read "Function: " obarray 'fboundp t))))
+  (let ((timer (timer-create)))
+    (timer-set-function timer function args)
+    (timer-set-idle-time timer secs repeat)
+    (timer-activate-when-idle timer)
+    timer))
+\f
+(defun with-timeout-handler (tag)
+  (throw tag 'timeout))
+
+;;;###autoload (put 'with-timeout 'lisp-indent-function 1)
+
+;;;###autoload
+(defmacro with-timeout (list &rest body)
+  "Run BODY, but if it doesn't finish in SECONDS seconds, give up.
+If we give up, we run the TIMEOUT-FORMS and return the value of the last one.
+The call should look like:
+ (with-timeout (SECONDS TIMEOUT-FORMS...) BODY...)
+The timeout is checked whenever Emacs waits for some kind of external
+event \(such as keyboard input, input from subprocesses, or a certain time);
+if the program loops without waiting in any way, the timeout will not
+be detected."
+  (let ((seconds (car list))
+       (timeout-forms (cdr list)))
+    `(let ((with-timeout-tag (cons nil nil))
+          with-timeout-value with-timeout-timer)
+       (if (catch with-timeout-tag
+            (progn
+              (setq with-timeout-timer
+                    (run-with-timer ,seconds nil
+                                     'with-timeout-handler
+                                     with-timeout-tag))
+              (setq with-timeout-value (progn . ,body))
+              nil))
+          (progn . ,timeout-forms)
+        (cancel-timer with-timeout-timer)
+        with-timeout-value))))
+
+(defun y-or-n-p-with-timeout (prompt seconds default-value)
+  "Like (y-or-n-p PROMPT), with a timeout.
+If the user does not answer after SECONDS seconds, return DEFAULT-VALUE."
+  (with-timeout (seconds default-value)
+    (y-or-n-p prompt)))
+\f
+(defvar timer-duration-words
+  (list (cons "microsec" 0.000001)
+       (cons "microsecond" 0.000001)
+        (cons "millisec" 0.001)
+       (cons "millisecond" 0.001)
+        (cons "sec" 1)
+       (cons "second" 1)
+       (cons "min" 60)
+       (cons "minute" 60)
+       (cons "hour" (* 60 60))
+       (cons "day" (* 24 60 60))
+       (cons "week" (* 7 24 60 60))
+       (cons "fortnight" (* 14 24 60 60))
+       (cons "month" (* 30 24 60 60))    ; Approximation
+       (cons "year" (* 365.25 24 60 60)) ; Approximation
+       )
+  "Alist mapping temporal words to durations in seconds")
+
+(defun timer-duration (string)
+  "Return number of seconds specified by STRING, or nil if parsing fails."
+  (let ((secs 0)
+       (start 0)
+       (case-fold-search t))
+    (while (string-match
+           "[ \t]*\\([0-9.]+\\)?[ \t]*\\([a-z]+[a-rt-z]\\)s?[ \t]*"
+           string start)
+      (let ((count (if (match-beginning 1)
+                      (string-to-number (match-string 1 string))
+                    1))
+           (itemsize (cdr (assoc (match-string 2 string)
+                                 timer-duration-words))))
+       (if itemsize
+           (setq start (match-end 0)
+                 secs (+ secs (* count itemsize)))
+         (setq secs nil
+               start (length string)))))
+    (if (= start (length string))
+       secs
+      (if (string-match "\\`[0-9.]+\\'" string)
+         (string-to-number string)))))
+\f
+(provide 'timer)
+
+;;; timer.el ends here
diff --git a/contrib/ucs-tables.el b/contrib/ucs-tables.el
new file mode 100644 (file)
index 0000000..0255053
--- /dev/null
@@ -0,0 +1,2479 @@
+;;; ucs-tables.el --- translation to, from and via Unicode  -*- coding: iso-2022-7bit -*-
+
+;; Copyright (C) 2001  Free Software Foundation, Inc.
+
+;; Author: Dave Love <fx@gnu.org>
+;; Keywords: i18n
+
+;; This file is part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file provides tables mapping between Unicode numbers and
+;; emacs-mule characters from the iso-8859 charsets (and others).  It
+;; also provides some auxiliary functions.
+
+;; These tables are used to construct other mappings between the Mule
+;; iso8859 charsets and the emacs-unicode charsets and a table that
+;; unifies iso8859 characters using a single charset as far as
+;; possible.  These tables are used by latin1-disp.el to display some
+;; Unicode characters without a Unicode font and by utf-8.el to unify
+;; Latin-N as far as possible on encoding.
+
+;; More drastically, they can be used to unify 8859 into Latin-1 plus
+;; mule-unicode-0100-24ff on decoding, with the corresponding
+;; adjustments on encoding; see `ucs-unify-8859'.  Be wary of using
+;; unification when, for instance, editing Lisp files such as this one
+;; which are supposed to contain distinct 8859 charsets.  Also, it can
+;; make reading and writing of emacs-mule and iso-2022-based encodings
+;; not idempotent.
+
+;; Global minor modes are provided to unify on encoding and decoding.
+
+;; The translation table `ucs-mule-to-mule-unicode' is populated.
+;; This is used by the `mule-utf-8' coding system to encode extra
+;; characters.
+
+;; Command `ucs-insert' is convenient for inserting a given Unicode.
+;; (See also the `ucs' input method.)
+
+;;; Code:
+
+(when (featurep 'xemacs)
+  (error "This file cannot be used with XEmacs.  For XEmacs, use latin-unity instead"))
+
+;;; Define tables, to be populated later.
+
+(defvar ucs-mule-8859-to-ucs-table (make-translation-table)
+  "Translation table from Emacs ISO-8859 characters to Unicode.
+This maps Emacs characters from the non-Latin-1
+...-iso8859-... charsets to their Unicode code points.  This is a
+many-to-one mapping.")
+
+(defvar ucs-mule-8859-to-mule-unicode (make-translation-table)
+  "Translation table from Emacs ISO-8859 characters to Mule Unicode.
+This maps Emacs characters from the non-Latin-1
+...-iso8859-... charsets to characters from the
+mule-unicode-... charsets.  This is a many-to-one mapping.  The
+characters translated to are suitable for encoding using the
+`mule-utf-8' coding system.")
+
+;; (defvar ucs-ucs-to-mule-8859-table (make-translation-table)
+;;   "Translation table from Unicode to Emacs ISO-8859 characters.
+;; This maps Unicode code points to corresponding Emacs characters from
+;; the ...-iso8859-... charsets.  This is made a one-to-one mapping where
+;; the same character occurs in more than one set by preferring the Emacs
+;; iso-8859-N character with lowest N.")
+
+;; (defvar ucs-mule-unicode-to-mule-8859 (make-translation-table)
+;;   "Translation table from Mule Unicode to Emacs ISO-8859 characters.
+;; This maps non-Latin-1 Emacs characters from the
+;; mule-unicode-... charsets used by the `mule-utf-8' coding system to
+;; characters from the ...-iso8859-... charsets.  This is made a
+;; one-to-one mapping where the same character occurs in more than one
+;; set by preferring the Emacs iso-8859-N character with lowest N.")
+
+(defvar ucs-8859-1-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-2.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-2-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-2.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-3-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-3.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-4-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-4.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-5-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-5.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-7-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-7.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-8-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-8.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-9-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-9.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-14-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-14.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+(defvar ucs-8859-15-encode-table nil
+  "Used as `translation-table-for-encode' for iso-8859-15.
+Translates from the iso8859 charsets and `mule-unicode-0100-24ff'.")
+
+;; Probably defined by utf-8.el.
+(defvar ucs-mule-to-mule-unicode (make-translation-table))
+(unless (get 'ucs-mule-to-mule-unicode 'translation-table)
+  (define-translation-table 'ucs-mule-to-mule-unicode ucs-mule-to-mule-unicode))
+;;; Set up the tables.
+
+;; Most of these tables were derived from ones in Mule-UCS.
+
+;; There doesn't seem to be a need to make these let bindings into
+;; defvars, so we'll let the data get GC'ed.
+(let ((ucs-8859-2-alist
+       '((?\\e,B \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,B!\e(B . ?\x0104) ;; LATIN CAPITAL LETTER A WITH OGONEK
+        (?\\e,B"\e(B . ?\x02D8) ;; BREVE
+        (?\\e,B#\e(B . ?\x0141) ;; LATIN CAPITAL LETTER L WITH STROKE
+        (?\\e,B$\e(B . ?\x00A4) ;; CURRENCY SIGN
+        (?\\e,B%\e(B . ?\x013D) ;; LATIN CAPITAL LETTER L WITH CARON
+        (?\\e,B&\e(B . ?\x015A) ;; LATIN CAPITAL LETTER S WITH ACUTE
+        (?\\e,B'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,B(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,B)\e(B . ?\x0160) ;; LATIN CAPITAL LETTER S WITH CARON
+        (?\\e,B*\e(B . ?\x015E) ;; LATIN CAPITAL LETTER S WITH CEDILLA
+        (?\\e,B+\e(B . ?\x0164) ;; LATIN CAPITAL LETTER T WITH CARON
+        (?\\e,B,\e(B . ?\x0179) ;; LATIN CAPITAL LETTER Z WITH ACUTE
+        (?\\e,B-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,B.\e(B . ?\x017D) ;; LATIN CAPITAL LETTER Z WITH CARON
+        (?\\e,B/\e(B . ?\x017B) ;; LATIN CAPITAL LETTER Z WITH DOT ABOVE
+        (?\\e,B0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,B1\e(B . ?\x0105) ;; LATIN SMALL LETTER A WITH OGONEK
+        (?\\e,B2\e(B . ?\x02DB) ;; OGONEK
+        (?\\e,B3\e(B . ?\x0142) ;; LATIN SMALL LETTER L WITH STROKE
+        (?\\e,B4\e(B . ?\x00B4) ;; ACUTE ACCENT
+        (?\\e,B5\e(B . ?\x013E) ;; LATIN SMALL LETTER L WITH CARON
+        (?\\e,B6\e(B . ?\x015B) ;; LATIN SMALL LETTER S WITH ACUTE
+        (?\\e,B7\e(B . ?\x02C7) ;; CARON
+        (?\\e,B8\e(B . ?\x00B8) ;; CEDILLA
+        (?\\e,B9\e(B . ?\x0161) ;; LATIN SMALL LETTER S WITH CARON
+        (?\\e,B:\e(B . ?\x015F) ;; LATIN SMALL LETTER S WITH CEDILLA
+        (?\\e,B;\e(B . ?\x0165) ;; LATIN SMALL LETTER T WITH CARON
+        (?\\e,B<\e(B . ?\x017A) ;; LATIN SMALL LETTER Z WITH ACUTE
+        (?\\e,B=\e(B . ?\x02DD) ;; DOUBLE ACUTE ACCENT
+        (?\\e,B>\e(B . ?\x017E) ;; LATIN SMALL LETTER Z WITH CARON
+        (?\\e,B?\e(B . ?\x017C) ;; LATIN SMALL LETTER Z WITH DOT ABOVE
+        (?\\e,B@\e(B . ?\x0154) ;; LATIN CAPITAL LETTER R WITH ACUTE
+        (?\\e,BA\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,BB\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,BC\e(B . ?\x0102) ;; LATIN CAPITAL LETTER A WITH BREVE
+        (?\\e,BD\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,BE\e(B . ?\x0139) ;; LATIN CAPITAL LETTER L WITH ACUTE
+        (?\\e,BF\e(B . ?\x0106) ;; LATIN CAPITAL LETTER C WITH ACUTE
+        (?\\e,BG\e(B . ?\x00C7) ;; LATIN CAPITAL LETTER C WITH CEDILLA
+        (?\\e,BH\e(B . ?\x010C) ;; LATIN CAPITAL LETTER C WITH CARON
+        (?\\e,BI\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,BJ\e(B . ?\x0118) ;; LATIN CAPITAL LETTER E WITH OGONEK
+        (?\\e,BK\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,BL\e(B . ?\x011A) ;; LATIN CAPITAL LETTER E WITH CARON
+        (?\\e,BM\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,BN\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,BO\e(B . ?\x010E) ;; LATIN CAPITAL LETTER D WITH CARON
+        (?\\e,BP\e(B . ?\x0110) ;; LATIN CAPITAL LETTER D WITH STROKE
+        (?\\e,BQ\e(B . ?\x0143) ;; LATIN CAPITAL LETTER N WITH ACUTE
+        (?\\e,BR\e(B . ?\x0147) ;; LATIN CAPITAL LETTER N WITH CARON
+        (?\\e,BS\e(B . ?\x00D3) ;; LATIN CAPITAL LETTER O WITH ACUTE
+        (?\\e,BT\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,BU\e(B . ?\x0150) ;; LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+        (?\\e,BV\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,BW\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,BX\e(B . ?\x0158) ;; LATIN CAPITAL LETTER R WITH CARON
+        (?\\e,BY\e(B . ?\x016E) ;; LATIN CAPITAL LETTER U WITH RING ABOVE
+        (?\\e,BZ\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,B[\e(B . ?\x0170) ;; LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+        (?\\e,B\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,B]\e(B . ?\x00DD) ;; LATIN CAPITAL LETTER Y WITH ACUTE
+        (?\\e,B^\e(B . ?\x0162) ;; LATIN CAPITAL LETTER T WITH CEDILLA
+        (?\\e,B_\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,B`\e(B . ?\x0155) ;; LATIN SMALL LETTER R WITH ACUTE
+        (?\\e,Ba\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,Bb\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,Bc\e(B . ?\x0103) ;; LATIN SMALL LETTER A WITH BREVE
+        (?\\e,Bd\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,Be\e(B . ?\x013A) ;; LATIN SMALL LETTER L WITH ACUTE
+        (?\\e,Bf\e(B . ?\x0107) ;; LATIN SMALL LETTER C WITH ACUTE
+        (?\\e,Bg\e(B . ?\x00E7) ;; LATIN SMALL LETTER C WITH CEDILLA
+        (?\\e,Bh\e(B . ?\x010D) ;; LATIN SMALL LETTER C WITH CARON
+        (?\\e,Bi\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,Bj\e(B . ?\x0119) ;; LATIN SMALL LETTER E WITH OGONEK
+        (?\\e,Bk\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,Bl\e(B . ?\x011B) ;; LATIN SMALL LETTER E WITH CARON
+        (?\\e,Bm\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,Bn\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,Bo\e(B . ?\x010F) ;; LATIN SMALL LETTER D WITH CARON
+        (?\\e,Bp\e(B . ?\x0111) ;; LATIN SMALL LETTER D WITH STROKE
+        (?\\e,Bq\e(B . ?\x0144) ;; LATIN SMALL LETTER N WITH ACUTE
+        (?\\e,Br\e(B . ?\x0148) ;; LATIN SMALL LETTER N WITH CARON
+        (?\\e,Bs\e(B . ?\x00F3) ;; LATIN SMALL LETTER O WITH ACUTE
+        (?\\e,Bt\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,Bu\e(B . ?\x0151) ;; LATIN SMALL LETTER O WITH DOUBLE ACUTE
+        (?\\e,Bv\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,Bw\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,Bx\e(B . ?\x0159) ;; LATIN SMALL LETTER R WITH CARON
+        (?\\e,By\e(B . ?\x016F) ;; LATIN SMALL LETTER U WITH RING ABOVE
+        (?\\e,Bz\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,B{\e(B . ?\x0171) ;; LATIN SMALL LETTER U WITH DOUBLE ACUTE
+        (?\\e,B|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,B}\e(B . ?\x00FD) ;; LATIN SMALL LETTER Y WITH ACUTE
+        (?\\e,B~\e(B . ?\x0163) ;; LATIN SMALL LETTER T WITH CEDILLA
+        (?\\e,B\7f\e(B . ?\x02D9) ;; DOT ABOVE
+        ))
+
+      (ucs-8859-3-alist
+       '((?\\e,C \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,C!\e(B . ?\x0126) ;; LATIN CAPITAL LETTER H WITH STROKE
+        (?\\e,C"\e(B . ?\x02D8) ;; BREVE
+        (?\\e,C#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,C$\e(B . ?\x00A4) ;; CURRENCY SIGN
+        (?\\e,C&\e(B . ?\x0124) ;; LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+        (?\\e,C'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,C(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,C)\e(B . ?\x0130) ;; LATIN CAPITAL LETTER I WITH DOT ABOVE
+        (?\\e,C*\e(B . ?\x015E) ;; LATIN CAPITAL LETTER S WITH CEDILLA
+        (?\\e,C+\e(B . ?\x011E) ;; LATIN CAPITAL LETTER G WITH BREVE
+        (?\\e,C,\e(B . ?\x0134) ;; LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+        (?\\e,C-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,C/\e(B . ?\x017B) ;; LATIN CAPITAL LETTER Z WITH DOT ABOVE
+        (?\\e,C0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,C1\e(B . ?\x0127) ;; LATIN SMALL LETTER H WITH STROKE
+        (?\\e,C2\e(B . ?\x00B2) ;; SUPERSCRIPT TWO
+        (?\\e,C3\e(B . ?\x00B3) ;; SUPERSCRIPT THREE
+        (?\\e,C4\e(B . ?\x00B4) ;; ACUTE ACCENT
+        (?\\e,C5\e(B . ?\x00B5) ;; MICRO SIGN
+        (?\\e,C6\e(B . ?\x0125) ;; LATIN SMALL LETTER H WITH CIRCUMFLEX
+        (?\\e,C7\e(B . ?\x00B7) ;; MIDDLE DOT
+        (?\\e,C8\e(B . ?\x00B8) ;; CEDILLA
+        (?\\e,C9\e(B . ?\x0131) ;; LATIN SMALL LETTER DOTLESS I
+        (?\\e,C:\e(B . ?\x015F) ;; LATIN SMALL LETTER S WITH CEDILLA
+        (?\\e,C;\e(B . ?\x011F) ;; LATIN SMALL LETTER G WITH BREVE
+        (?\\e,C<\e(B . ?\x0135) ;; LATIN SMALL LETTER J WITH CIRCUMFLEX
+        (?\\e,C=\e(B . ?\x00BD) ;; VULGAR FRACTION ONE HALF
+        (?\\e,C?\e(B . ?\x017C) ;; LATIN SMALL LETTER Z WITH DOT ABOVE
+        (?\\e,C@\e(B . ?\x00C0) ;; LATIN CAPITAL LETTER A WITH GRAVE
+        (?\\e,CA\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,CB\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,CD\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,CE\e(B . ?\x010A) ;; LATIN CAPITAL LETTER C WITH DOT ABOVE
+        (?\\e,CF\e(B . ?\x0108) ;; LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+        (?\\e,CG\e(B . ?\x00C7) ;; LATIN CAPITAL LETTER C WITH CEDILLA
+        (?\\e,CH\e(B . ?\x00C8) ;; LATIN CAPITAL LETTER E WITH GRAVE
+        (?\\e,CI\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,CJ\e(B . ?\x00CA) ;; LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+        (?\\e,CK\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,CL\e(B . ?\x00CC) ;; LATIN CAPITAL LETTER I WITH GRAVE
+        (?\\e,CM\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,CN\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,CO\e(B . ?\x00CF) ;; LATIN CAPITAL LETTER I WITH DIAERESIS
+        (?\\e,CQ\e(B . ?\x00D1) ;; LATIN CAPITAL LETTER N WITH TILDE
+        (?\\e,CR\e(B . ?\x00D2) ;; LATIN CAPITAL LETTER O WITH GRAVE
+        (?\\e,CS\e(B . ?\x00D3) ;; LATIN CAPITAL LETTER O WITH ACUTE
+        (?\\e,CT\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,CU\e(B . ?\x0120) ;; LATIN CAPITAL LETTER G WITH DOT ABOVE
+        (?\\e,CV\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,CW\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,CX\e(B . ?\x011C) ;; LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+        (?\\e,CY\e(B . ?\x00D9) ;; LATIN CAPITAL LETTER U WITH GRAVE
+        (?\\e,CZ\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,C[\e(B . ?\x00DB) ;; LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        (?\\e,C\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,C]\e(B . ?\x016C) ;; LATIN CAPITAL LETTER U WITH BREVE
+        (?\\e,C^\e(B . ?\x015C) ;; LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+        (?\\e,C_\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,C`\e(B . ?\x00E0) ;; LATIN SMALL LETTER A WITH GRAVE
+        (?\\e,Ca\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,Cb\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,Cd\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,Ce\e(B . ?\x010B) ;; LATIN SMALL LETTER C WITH DOT ABOVE
+        (?\\e,Cf\e(B . ?\x0109) ;; LATIN SMALL LETTER C WITH CIRCUMFLEX
+        (?\\e,Cg\e(B . ?\x00E7) ;; LATIN SMALL LETTER C WITH CEDILLA
+        (?\\e,Ch\e(B . ?\x00E8) ;; LATIN SMALL LETTER E WITH GRAVE
+        (?\\e,Ci\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,Cj\e(B . ?\x00EA) ;; LATIN SMALL LETTER E WITH CIRCUMFLEX
+        (?\\e,Ck\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,Cl\e(B . ?\x00EC) ;; LATIN SMALL LETTER I WITH GRAVE
+        (?\\e,Cm\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,Cn\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,Co\e(B . ?\x00EF) ;; LATIN SMALL LETTER I WITH DIAERESIS
+        (?\\e,Cq\e(B . ?\x00F1) ;; LATIN SMALL LETTER N WITH TILDE
+        (?\\e,Cr\e(B . ?\x00F2) ;; LATIN SMALL LETTER O WITH GRAVE
+        (?\\e,Cs\e(B . ?\x00F3) ;; LATIN SMALL LETTER O WITH ACUTE
+        (?\\e,Ct\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,Cu\e(B . ?\x0121) ;; LATIN SMALL LETTER G WITH DOT ABOVE
+        (?\\e,Cv\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,Cw\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,Cx\e(B . ?\x011D) ;; LATIN SMALL LETTER G WITH CIRCUMFLEX
+        (?\\e,Cy\e(B . ?\x00F9) ;; LATIN SMALL LETTER U WITH GRAVE
+        (?\\e,Cz\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,C{\e(B . ?\x00FB) ;; LATIN SMALL LETTER U WITH CIRCUMFLEX
+        (?\\e,C|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,C}\e(B . ?\x016D) ;; LATIN SMALL LETTER U WITH BREVE
+        (?\\e,C~\e(B . ?\x015D) ;; LATIN SMALL LETTER S WITH CIRCUMFLEX
+        (?\\e,C\7f\e(B . ?\x02D9) ;; DOT ABOVE
+        ))
+
+      (ucs-8859-4-alist
+       '((?\\e,D \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,D!\e(B . ?\x0104) ;; LATIN CAPITAL LETTER A WITH OGONEK
+        (?\\e,D"\e(B . ?\x0138) ;; LATIN SMALL LETTER KRA
+        (?\\e,D#\e(B . ?\x0156) ;; LATIN CAPITAL LETTER R WITH CEDILLA
+        (?\\e,D$\e(B . ?\x00A4) ;; CURRENCY SIGN
+        (?\\e,D%\e(B . ?\x0128) ;; LATIN CAPITAL LETTER I WITH TILDE
+        (?\\e,D&\e(B . ?\x013B) ;; LATIN CAPITAL LETTER L WITH CEDILLA
+        (?\\e,D'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,D(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,D)\e(B . ?\x0160) ;; LATIN CAPITAL LETTER S WITH CARON
+        (?\\e,D*\e(B . ?\x0112) ;; LATIN CAPITAL LETTER E WITH MACRON
+        (?\\e,D+\e(B . ?\x0122) ;; LATIN CAPITAL LETTER G WITH CEDILLA
+        (?\\e,D,\e(B . ?\x0166) ;; LATIN CAPITAL LETTER T WITH STROKE
+        (?\\e,D-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,D.\e(B . ?\x017D) ;; LATIN CAPITAL LETTER Z WITH CARON
+        (?\\e,D/\e(B . ?\x00AF) ;; MACRON
+        (?\\e,D0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,D1\e(B . ?\x0105) ;; LATIN SMALL LETTER A WITH OGONEK
+        (?\\e,D2\e(B . ?\x02DB) ;; OGONEK
+        (?\\e,D3\e(B . ?\x0157) ;; LATIN SMALL LETTER R WITH CEDILLA
+        (?\\e,D4\e(B . ?\x00B4) ;; ACUTE ACCENT
+        (?\\e,D5\e(B . ?\x0129) ;; LATIN SMALL LETTER I WITH TILDE
+        (?\\e,D6\e(B . ?\x013C) ;; LATIN SMALL LETTER L WITH CEDILLA
+        (?\\e,D7\e(B . ?\x02C7) ;; CARON
+        (?\\e,D8\e(B . ?\x00B8) ;; CEDILLA
+        (?\\e,D9\e(B . ?\x0161) ;; LATIN SMALL LETTER S WITH CARON
+        (?\\e,D:\e(B . ?\x0113) ;; LATIN SMALL LETTER E WITH MACRON
+        (?\\e,D;\e(B . ?\x0123) ;; LATIN SMALL LETTER G WITH CEDILLA
+        (?\\e,D<\e(B . ?\x0167) ;; LATIN SMALL LETTER T WITH STROKE
+        (?\\e,D=\e(B . ?\x014A) ;; LATIN CAPITAL LETTER ENG
+        (?\\e,D>\e(B . ?\x017E) ;; LATIN SMALL LETTER Z WITH CARON
+        (?\\e,D?\e(B . ?\x014B) ;; LATIN SMALL LETTER ENG
+        (?\\e,D@\e(B . ?\x0100) ;; LATIN CAPITAL LETTER A WITH MACRON
+        (?\\e,DA\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,DB\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,DC\e(B . ?\x00C3) ;; LATIN CAPITAL LETTER A WITH TILDE
+        (?\\e,DD\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,DE\e(B . ?\x00C5) ;; LATIN CAPITAL LETTER A WITH RING ABOVE
+        (?\\e,DF\e(B . ?\x00C6) ;; LATIN CAPITAL LETTER AE
+        (?\\e,DG\e(B . ?\x012E) ;; LATIN CAPITAL LETTER I WITH OGONEK
+        (?\\e,DH\e(B . ?\x010C) ;; LATIN CAPITAL LETTER C WITH CARON
+        (?\\e,DI\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,DJ\e(B . ?\x0118) ;; LATIN CAPITAL LETTER E WITH OGONEK
+        (?\\e,DK\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,DL\e(B . ?\x0116) ;; LATIN CAPITAL LETTER E WITH DOT ABOVE
+        (?\\e,DM\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,DN\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,DO\e(B . ?\x012A) ;; LATIN CAPITAL LETTER I WITH MACRON
+        (?\\e,DP\e(B . ?\x0110) ;; LATIN CAPITAL LETTER D WITH STROKE
+        (?\\e,DQ\e(B . ?\x0145) ;; LATIN CAPITAL LETTER N WITH CEDILLA
+        (?\\e,DR\e(B . ?\x014C) ;; LATIN CAPITAL LETTER O WITH MACRON
+        (?\\e,DS\e(B . ?\x0136) ;; LATIN CAPITAL LETTER K WITH CEDILLA
+        (?\\e,DT\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,DU\e(B . ?\x00D5) ;; LATIN CAPITAL LETTER O WITH TILDE
+        (?\\e,DV\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,DW\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,DX\e(B . ?\x00D8) ;; LATIN CAPITAL LETTER O WITH STROKE
+        (?\\e,DY\e(B . ?\x0172) ;; LATIN CAPITAL LETTER U WITH OGONEK
+        (?\\e,DZ\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,D[\e(B . ?\x00DB) ;; LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        (?\\e,D\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,D]\e(B . ?\x0168) ;; LATIN CAPITAL LETTER U WITH TILDE
+        (?\\e,D^\e(B . ?\x016A) ;; LATIN CAPITAL LETTER U WITH MACRON
+        (?\\e,D_\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,D`\e(B . ?\x0101) ;; LATIN SMALL LETTER A WITH MACRON
+        (?\\e,Da\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,Db\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,Dc\e(B . ?\x00E3) ;; LATIN SMALL LETTER A WITH TILDE
+        (?\\e,Dd\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,De\e(B . ?\x00E5) ;; LATIN SMALL LETTER A WITH RING ABOVE
+        (?\\e,Df\e(B . ?\x00E6) ;; LATIN SMALL LETTER AE
+        (?\\e,Dg\e(B . ?\x012F) ;; LATIN SMALL LETTER I WITH OGONEK
+        (?\\e,Dh\e(B . ?\x010D) ;; LATIN SMALL LETTER C WITH CARON
+        (?\\e,Di\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,Dj\e(B . ?\x0119) ;; LATIN SMALL LETTER E WITH OGONEK
+        (?\\e,Dk\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,Dl\e(B . ?\x0117) ;; LATIN SMALL LETTER E WITH DOT ABOVE
+        (?\\e,Dm\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,Dn\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,Do\e(B . ?\x012B) ;; LATIN SMALL LETTER I WITH MACRON
+        (?\\e,Dp\e(B . ?\x0111) ;; LATIN SMALL LETTER D WITH STROKE
+        (?\\e,Dq\e(B . ?\x0146) ;; LATIN SMALL LETTER N WITH CEDILLA
+        (?\\e,Dr\e(B . ?\x014D) ;; LATIN SMALL LETTER O WITH MACRON
+        (?\\e,Ds\e(B . ?\x0137) ;; LATIN SMALL LETTER K WITH CEDILLA
+        (?\\e,Dt\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,Du\e(B . ?\x00F5) ;; LATIN SMALL LETTER O WITH TILDE
+        (?\\e,Dv\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,Dw\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,Dx\e(B . ?\x00F8) ;; LATIN SMALL LETTER O WITH STROKE
+        (?\\e,Dy\e(B . ?\x0173) ;; LATIN SMALL LETTER U WITH OGONEK
+        (?\\e,Dz\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,D{\e(B . ?\x00FB) ;; LATIN SMALL LETTER U WITH CIRCUMFLEX
+        (?\\e,D|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,D}\e(B . ?\x0169) ;; LATIN SMALL LETTER U WITH TILDE
+        (?\\e,D~\e(B . ?\x016B) ;; LATIN SMALL LETTER U WITH MACRON
+        (?\\e,D\7f\e(B . ?\x02D9) ;; DOT ABOVE
+        ))
+
+      (ucs-8859-5-alist
+       '((?\\e,L \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,L!\e(B . ?\x0401) ;; CYRILLIC CAPITAL LETTER IO
+        (?\\e,L"\e(B . ?\x0402) ;; CYRILLIC CAPITAL LETTER DJE
+        (?\\e,L#\e(B . ?\x0403) ;; CYRILLIC CAPITAL LETTER GJE
+        (?\\e,L$\e(B . ?\x0404) ;; CYRILLIC CAPITAL LETTER UKRAINIAN IE
+        (?\\e,L%\e(B . ?\x0405) ;; CYRILLIC CAPITAL LETTER DZE
+        (?\\e,L&\e(B . ?\x0406) ;; CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+        (?\\e,L'\e(B . ?\x0407) ;; CYRILLIC CAPITAL LETTER YI
+        (?\\e,L(\e(B . ?\x0408) ;; CYRILLIC CAPITAL LETTER JE
+        (?\\e,L)\e(B . ?\x0409) ;; CYRILLIC CAPITAL LETTER LJE
+        (?\\e,L*\e(B . ?\x040A) ;; CYRILLIC CAPITAL LETTER NJE
+        (?\\e,L+\e(B . ?\x040B) ;; CYRILLIC CAPITAL LETTER TSHE
+        (?\\e,L,\e(B . ?\x040C) ;; CYRILLIC CAPITAL LETTER KJE
+        (?\\e,L-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,L.\e(B . ?\x040E) ;; CYRILLIC CAPITAL LETTER SHORT U
+        (?\\e,L/\e(B . ?\x040F) ;; CYRILLIC CAPITAL LETTER DZHE
+        (?\\e,L0\e(B . ?\x0410) ;; CYRILLIC CAPITAL LETTER A
+        (?\\e,L1\e(B . ?\x0411) ;; CYRILLIC CAPITAL LETTER BE
+        (?\\e,L2\e(B . ?\x0412) ;; CYRILLIC CAPITAL LETTER VE
+        (?\\e,L3\e(B . ?\x0413) ;; CYRILLIC CAPITAL LETTER GHE
+        (?\\e,L4\e(B . ?\x0414) ;; CYRILLIC CAPITAL LETTER DE
+        (?\\e,L5\e(B . ?\x0415) ;; CYRILLIC CAPITAL LETTER IE
+        (?\\e,L6\e(B . ?\x0416) ;; CYRILLIC CAPITAL LETTER ZHE
+        (?\\e,L7\e(B . ?\x0417) ;; CYRILLIC CAPITAL LETTER ZE
+        (?\\e,L8\e(B . ?\x0418) ;; CYRILLIC CAPITAL LETTER I
+        (?\\e,L9\e(B . ?\x0419) ;; CYRILLIC CAPITAL LETTER SHORT I
+        (?\\e,L:\e(B . ?\x041A) ;; CYRILLIC CAPITAL LETTER KA
+        (?\\e,L;\e(B . ?\x041B) ;; CYRILLIC CAPITAL LETTER EL
+        (?\\e,L<\e(B . ?\x041C) ;; CYRILLIC CAPITAL LETTER EM
+        (?\\e,L=\e(B . ?\x041D) ;; CYRILLIC CAPITAL LETTER EN
+        (?\\e,L>\e(B . ?\x041E) ;; CYRILLIC CAPITAL LETTER O
+        (?\\e,L?\e(B . ?\x041F) ;; CYRILLIC CAPITAL LETTER PE
+        (?\\e,L@\e(B . ?\x0420) ;; CYRILLIC CAPITAL LETTER ER
+        (?\\e,LA\e(B . ?\x0421) ;; CYRILLIC CAPITAL LETTER ES
+        (?\\e,LB\e(B . ?\x0422) ;; CYRILLIC CAPITAL LETTER TE
+        (?\\e,LC\e(B . ?\x0423) ;; CYRILLIC CAPITAL LETTER U
+        (?\\e,LD\e(B . ?\x0424) ;; CYRILLIC CAPITAL LETTER EF
+        (?\\e,LE\e(B . ?\x0425) ;; CYRILLIC CAPITAL LETTER HA
+        (?\\e,LF\e(B . ?\x0426) ;; CYRILLIC CAPITAL LETTER TSE
+        (?\\e,LG\e(B . ?\x0427) ;; CYRILLIC CAPITAL LETTER CHE
+        (?\\e,LH\e(B . ?\x0428) ;; CYRILLIC CAPITAL LETTER SHA
+        (?\\e,LI\e(B . ?\x0429) ;; CYRILLIC CAPITAL LETTER SHCHA
+        (?\\e,LJ\e(B . ?\x042A) ;; CYRILLIC CAPITAL LETTER HARD SIGN
+        (?\\e,LK\e(B . ?\x042B) ;; CYRILLIC CAPITAL LETTER YERU
+        (?\\e,LL\e(B . ?\x042C) ;; CYRILLIC CAPITAL LETTER SOFT SIGN
+        (?\\e,LM\e(B . ?\x042D) ;; CYRILLIC CAPITAL LETTER E
+        (?\\e,LN\e(B . ?\x042E) ;; CYRILLIC CAPITAL LETTER YU
+        (?\\e,LO\e(B . ?\x042F) ;; CYRILLIC CAPITAL LETTER YA
+        (?\\e,LP\e(B . ?\x0430) ;; CYRILLIC SMALL LETTER A
+        (?\\e,LQ\e(B . ?\x0431) ;; CYRILLIC SMALL LETTER BE
+        (?\\e,LR\e(B . ?\x0432) ;; CYRILLIC SMALL LETTER VE
+        (?\\e,LS\e(B . ?\x0433) ;; CYRILLIC SMALL LETTER GHE
+        (?\\e,LT\e(B . ?\x0434) ;; CYRILLIC SMALL LETTER DE
+        (?\\e,LU\e(B . ?\x0435) ;; CYRILLIC SMALL LETTER IE
+        (?\\e,LV\e(B . ?\x0436) ;; CYRILLIC SMALL LETTER ZHE
+        (?\\e,LW\e(B . ?\x0437) ;; CYRILLIC SMALL LETTER ZE
+        (?\\e,LX\e(B . ?\x0438) ;; CYRILLIC SMALL LETTER I
+        (?\\e,LY\e(B . ?\x0439) ;; CYRILLIC SMALL LETTER SHORT I
+        (?\\e,LZ\e(B . ?\x043A) ;; CYRILLIC SMALL LETTER KA
+        (?\\e,L[\e(B . ?\x043B) ;; CYRILLIC SMALL LETTER EL
+        (?\\e,L\\e(B . ?\x043C) ;; CYRILLIC SMALL LETTER EM
+        (?\\e,L]\e(B . ?\x043D) ;; CYRILLIC SMALL LETTER EN
+        (?\\e,L^\e(B . ?\x043E) ;; CYRILLIC SMALL LETTER O
+        (?\\e,L_\e(B . ?\x043F) ;; CYRILLIC SMALL LETTER PE
+        (?\\e,L`\e(B . ?\x0440) ;; CYRILLIC SMALL LETTER ER
+        (?\\e,La\e(B . ?\x0441) ;; CYRILLIC SMALL LETTER ES
+        (?\\e,Lb\e(B . ?\x0442) ;; CYRILLIC SMALL LETTER TE
+        (?\\e,Lc\e(B . ?\x0443) ;; CYRILLIC SMALL LETTER U
+        (?\\e,Ld\e(B . ?\x0444) ;; CYRILLIC SMALL LETTER EF
+        (?\\e,Le\e(B . ?\x0445) ;; CYRILLIC SMALL LETTER HA
+        (?\\e,Lf\e(B . ?\x0446) ;; CYRILLIC SMALL LETTER TSE
+        (?\\e,Lg\e(B . ?\x0447) ;; CYRILLIC SMALL LETTER CHE
+        (?\\e,Lh\e(B . ?\x0448) ;; CYRILLIC SMALL LETTER SHA
+        (?\\e,Li\e(B . ?\x0449) ;; CYRILLIC SMALL LETTER SHCHA
+        (?\\e,Lj\e(B . ?\x044A) ;; CYRILLIC SMALL LETTER HARD SIGN
+        (?\\e,Lk\e(B . ?\x044B) ;; CYRILLIC SMALL LETTER YERU
+        (?\\e,Ll\e(B . ?\x044C) ;; CYRILLIC SMALL LETTER SOFT SIGN
+        (?\\e,Lm\e(B . ?\x044D) ;; CYRILLIC SMALL LETTER E
+        (?\\e,Ln\e(B . ?\x044E) ;; CYRILLIC SMALL LETTER YU
+        (?\\e,Lo\e(B . ?\x044F) ;; CYRILLIC SMALL LETTER YA
+        (?\\e,Lp\e(B . ?\x2116) ;; NUMERO SIGN
+        (?\\e,Lq\e(B . ?\x0451) ;; CYRILLIC SMALL LETTER IO
+        (?\\e,Lr\e(B . ?\x0452) ;; CYRILLIC SMALL LETTER DJE
+        (?\\e,Ls\e(B . ?\x0453) ;; CYRILLIC SMALL LETTER GJE
+        (?\\e,Lt\e(B . ?\x0454) ;; CYRILLIC SMALL LETTER UKRAINIAN IE
+        (?\\e,Lu\e(B . ?\x0455) ;; CYRILLIC SMALL LETTER DZE
+        (?\\e,Lv\e(B . ?\x0456) ;; CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+        (?\\e,Lw\e(B . ?\x0457) ;; CYRILLIC SMALL LETTER YI
+        (?\\e,Lx\e(B . ?\x0458) ;; CYRILLIC SMALL LETTER JE
+        (?\\e,Ly\e(B . ?\x0459) ;; CYRILLIC SMALL LETTER LJE
+        (?\\e,Lz\e(B . ?\x045A) ;; CYRILLIC SMALL LETTER NJE
+        (?\\e,L{\e(B . ?\x045B) ;; CYRILLIC SMALL LETTER TSHE
+        (?\\e,L|\e(B . ?\x045C) ;; CYRILLIC SMALL LETTER KJE
+        (?\\e,L}\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,L~\e(B . ?\x045E) ;; CYRILLIC SMALL LETTER SHORT U
+        (?\\e,L\7f\e(B . ?\x045F) ;; CYRILLIC SMALL LETTER DZHE
+        ))
+
+      ;; Arabic probably isn't so useful in the absence of Arabic
+      ;; language support.
+      (ucs-8859-6-alist
+       '((?\e,G \e(B . ?\x00A0)  ;; NO-BREAK SPACE
+        (?\e,G$\e(B . ?\x00A4)   ;; CURRENCY SIGN
+        (?\e,G,\e(B . ?\x060C)   ;; ARABIC COMMA
+        (?\e,G-\e(B . ?\x00AD)   ;; SOFT HYPHEN
+        (?\e,G;\e(B . ?\x061B)   ;; ARABIC SEMICOLON
+        (?\e,G?\e(B . ?\x061F)   ;; ARABIC QUESTION MARK
+        (?\e,GA\e(B . ?\x0621)   ;; ARABIC LETTER HAMZA
+        (?\e,GB\e(B . ?\x0622)   ;; ARABIC LETTER ALEF WITH MADDA ABOVE
+        (?\e,GC\e(B . ?\x0623)   ;; ARABIC LETTER ALEF WITH HAMZA ABOVE
+        (?\e,GD\e(B . ?\x0624)   ;; ARABIC LETTER WAW WITH HAMZA ABOVE
+        (?\e,GE\e(B . ?\x0625)   ;; ARABIC LETTER ALEF WITH HAMZA BELOW
+        (?\e,GF\e(B . ?\x0626)   ;; ARABIC LETTER YEH WITH HAMZA ABOVE
+        (?\e,GG\e(B . ?\x0627)   ;; ARABIC LETTER ALEF
+        (?\e,GH\e(B . ?\x0628)   ;; ARABIC LETTER BEH
+        (?\e,GI\e(B . ?\x0629)   ;; ARABIC LETTER TEH MARBUTA
+        (?\e,GJ\e(B . ?\x062A)   ;; ARABIC LETTER TEH
+        (?\e,GK\e(B . ?\x062B)   ;; ARABIC LETTER THEH
+        (?\e,GL\e(B . ?\x062C)   ;; ARABIC LETTER JEEM
+        (?\e,GM\e(B . ?\x062D)   ;; ARABIC LETTER HAH
+        (?\e,GN\e(B . ?\x062E)   ;; ARABIC LETTER KHAH
+        (?\e,GO\e(B . ?\x062F)   ;; ARABIC LETTER DAL
+        (?\e,GP\e(B . ?\x0630)   ;; ARABIC LETTER THAL
+        (?\e,GQ\e(B . ?\x0631)   ;; ARABIC LETTER REH
+        (?\e,GR\e(B . ?\x0632)   ;; ARABIC LETTER ZAIN
+        (?\e,GS\e(B . ?\x0633)   ;; ARABIC LETTER SEEN
+        (?\e,GT\e(B . ?\x0634)   ;; ARABIC LETTER SHEEN
+        (?\e,GU\e(B . ?\x0635)   ;; ARABIC LETTER SAD
+        (?\e,GV\e(B . ?\x0636)   ;; ARABIC LETTER DAD
+        (?\e,GW\e(B . ?\x0637)   ;; ARABIC LETTER TAH
+        (?\e,GX\e(B . ?\x0638)   ;; ARABIC LETTER ZAH
+        (?\e,GY\e(B . ?\x0639)   ;; ARABIC LETTER AIN
+        (?\e,GZ\e(B . ?\x063A)   ;; ARABIC LETTER GHAIN
+        (?\e,G`\e(B . ?\x0640)   ;; ARABIC TATWEEL
+        (?\e,Ga\e(B . ?\x0641)   ;; ARABIC LETTER FEH
+        (?\e,Gb\e(B . ?\x0642)   ;; ARABIC LETTER QAF
+        (?\e,Gc\e(B . ?\x0643)   ;; ARABIC LETTER KAF
+        (?\e,Gd\e(B . ?\x0644)   ;; ARABIC LETTER LAM
+        (?\e,Ge\e(B . ?\x0645)   ;; ARABIC LETTER MEEM
+        (?\e,Gf\e(B . ?\x0646)   ;; ARABIC LETTER NOON
+        (?\e,Gg\e(B . ?\x0647)   ;; ARABIC LETTER HEH
+        (?\e,Gh\e(B . ?\x0648)   ;; ARABIC LETTER WAW
+        (?\e,Gi\e(B . ?\x0649)   ;; ARABIC LETTER ALEF MAKSURA
+        (?\e,Gj\e(B . ?\x064A)   ;; ARABIC LETTER YEH
+        (?\e,Gk\e(B . ?\x064B)   ;; ARABIC FATHATAN
+        (?\e,Gl\e(B . ?\x064C)   ;; ARABIC DAMMATAN
+        (?\e,Gm\e(B . ?\x064D)   ;; ARABIC KASRATAN
+        (?\e,Gn\e(B . ?\x064E)   ;; ARABIC FATHA
+        (?\e,Go\e(B . ?\x064F)   ;; ARABIC DAMMA
+        (?\e,Gp\e(B . ?\x0650)   ;; ARABIC KASRA
+        (?\e,Gq\e(B . ?\x0651)   ;; ARABIC SHADDA
+        (?\e,Gr\e(B . ?\x0652)   ;; ARABIC SUKUN
+        ))
+
+      (ucs-8859-7-alist
+       '((?\\e,F \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,F!\e(B . ?\x2018) ;; LEFT SINGLE QUOTATION MARK
+        (?\\e,F"\e(B . ?\x2019) ;; RIGHT SINGLE QUOTATION MARK
+        (?\\e,F#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,F&\e(B . ?\x00A6) ;; BROKEN BAR
+        (?\\e,F'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,F(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,F)\e(B . ?\x00A9) ;; COPYRIGHT SIGN
+        (?\\e,F+\e(B . ?\x00AB) ;; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,F,\e(B . ?\x00AC) ;; NOT SIGN
+        (?\\e,F-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,F/\e(B . ?\x2015) ;; HORIZONTAL BAR
+        (?\\e,F0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,F1\e(B . ?\x00B1) ;; PLUS-MINUS SIGN
+        (?\\e,F2\e(B . ?\x00B2) ;; SUPERSCRIPT TWO
+        (?\\e,F3\e(B . ?\x00B3) ;; SUPERSCRIPT THREE
+        (?\\e,F4\e(B . ?\x0384) ;; GREEK TONOS
+        (?\\e,F5\e(B . ?\x0385) ;; GREEK DIALYTIKA TONOS
+        (?\\e,F6\e(B . ?\x0386) ;; GREEK CAPITAL LETTER ALPHA WITH TONOS
+        (?\\e,F7\e(B . ?\x00B7) ;; MIDDLE DOT
+        (?\\e,F8\e(B . ?\x0388) ;; GREEK CAPITAL LETTER EPSILON WITH TONOS
+        (?\\e,F9\e(B . ?\x0389) ;; GREEK CAPITAL LETTER ETA WITH TONOS
+        (?\\e,F:\e(B . ?\x038A) ;; GREEK CAPITAL LETTER IOTA WITH TONOS
+        (?\\e,F;\e(B . ?\x00BB) ;; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,F<\e(B . ?\x038C) ;; GREEK CAPITAL LETTER OMICRON WITH TONOS
+        (?\\e,F=\e(B . ?\x00BD) ;; VULGAR FRACTION ONE HALF
+        (?\\e,F>\e(B . ?\x038E) ;; GREEK CAPITAL LETTER UPSILON WITH TONOS
+        (?\\e,F?\e(B . ?\x038F) ;; GREEK CAPITAL LETTER OMEGA WITH TONOS
+        (?\\e,F@\e(B . ?\x0390) ;; GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+        (?\\e,FA\e(B . ?\x0391) ;; GREEK CAPITAL LETTER ALPHA
+        (?\\e,FB\e(B . ?\x0392) ;; GREEK CAPITAL LETTER BETA
+        (?\\e,FC\e(B . ?\x0393) ;; GREEK CAPITAL LETTER GAMMA
+        (?\\e,FD\e(B . ?\x0394) ;; GREEK CAPITAL LETTER DELTA
+        (?\\e,FE\e(B . ?\x0395) ;; GREEK CAPITAL LETTER EPSILON
+        (?\\e,FF\e(B . ?\x0396) ;; GREEK CAPITAL LETTER ZETA
+        (?\\e,FG\e(B . ?\x0397) ;; GREEK CAPITAL LETTER ETA
+        (?\\e,FH\e(B . ?\x0398) ;; GREEK CAPITAL LETTER THETA
+        (?\\e,FI\e(B . ?\x0399) ;; GREEK CAPITAL LETTER IOTA
+        (?\\e,FJ\e(B . ?\x039A) ;; GREEK CAPITAL LETTER KAPPA
+        (?\\e,FK\e(B . ?\x039B) ;; GREEK CAPITAL LETTER LAMDA
+        (?\\e,FL\e(B . ?\x039C) ;; GREEK CAPITAL LETTER MU
+        (?\\e,FM\e(B . ?\x039D) ;; GREEK CAPITAL LETTER NU
+        (?\\e,FN\e(B . ?\x039E) ;; GREEK CAPITAL LETTER XI
+        (?\\e,FO\e(B . ?\x039F) ;; GREEK CAPITAL LETTER OMICRON
+        (?\\e,FP\e(B . ?\x03A0) ;; GREEK CAPITAL LETTER PI
+        (?\\e,FQ\e(B . ?\x03A1) ;; GREEK CAPITAL LETTER RHO
+        (?\\e,FS\e(B . ?\x03A3) ;; GREEK CAPITAL LETTER SIGMA
+        (?\\e,FT\e(B . ?\x03A4) ;; GREEK CAPITAL LETTER TAU
+        (?\\e,FU\e(B . ?\x03A5) ;; GREEK CAPITAL LETTER UPSILON
+        (?\\e,FV\e(B . ?\x03A6) ;; GREEK CAPITAL LETTER PHI
+        (?\\e,FW\e(B . ?\x03A7) ;; GREEK CAPITAL LETTER CHI
+        (?\\e,FX\e(B . ?\x03A8) ;; GREEK CAPITAL LETTER PSI
+        (?\\e,FY\e(B . ?\x03A9) ;; GREEK CAPITAL LETTER OMEGA
+        (?\\e,FZ\e(B . ?\x03AA) ;; GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+        (?\\e,F[\e(B . ?\x03AB) ;; GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+        (?\\e,F\\e(B . ?\x03AC) ;; GREEK SMALL LETTER ALPHA WITH TONOS
+        (?\\e,F]\e(B . ?\x03AD) ;; GREEK SMALL LETTER EPSILON WITH TONOS
+        (?\\e,F^\e(B . ?\x03AE) ;; GREEK SMALL LETTER ETA WITH TONOS
+        (?\\e,F_\e(B . ?\x03AF) ;; GREEK SMALL LETTER IOTA WITH TONOS
+        (?\\e,F`\e(B . ?\x03B0) ;; GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+        (?\\e,Fa\e(B . ?\x03B1) ;; GREEK SMALL LETTER ALPHA
+        (?\\e,Fb\e(B . ?\x03B2) ;; GREEK SMALL LETTER BETA
+        (?\\e,Fc\e(B . ?\x03B3) ;; GREEK SMALL LETTER GAMMA
+        (?\\e,Fd\e(B . ?\x03B4) ;; GREEK SMALL LETTER DELTA
+        (?\\e,Fe\e(B . ?\x03B5) ;; GREEK SMALL LETTER EPSILON
+        (?\\e,Ff\e(B . ?\x03B6) ;; GREEK SMALL LETTER ZETA
+        (?\\e,Fg\e(B . ?\x03B7) ;; GREEK SMALL LETTER ETA
+        (?\\e,Fh\e(B . ?\x03B8) ;; GREEK SMALL LETTER THETA
+        (?\\e,Fi\e(B . ?\x03B9) ;; GREEK SMALL LETTER IOTA
+        (?\\e,Fj\e(B . ?\x03BA) ;; GREEK SMALL LETTER KAPPA
+        (?\\e,Fk\e(B . ?\x03BB) ;; GREEK SMALL LETTER LAMDA
+        (?\\e,Fl\e(B . ?\x03BC) ;; GREEK SMALL LETTER MU
+        (?\\e,Fm\e(B . ?\x03BD) ;; GREEK SMALL LETTER NU
+        (?\\e,Fn\e(B . ?\x03BE) ;; GREEK SMALL LETTER XI
+        (?\\e,Fo\e(B . ?\x03BF) ;; GREEK SMALL LETTER OMICRON
+        (?\\e,Fp\e(B . ?\x03C0) ;; GREEK SMALL LETTER PI
+        (?\\e,Fq\e(B . ?\x03C1) ;; GREEK SMALL LETTER RHO
+        (?\\e,Fr\e(B . ?\x03C2) ;; GREEK SMALL LETTER FINAL SIGMA
+        (?\\e,Fs\e(B . ?\x03C3) ;; GREEK SMALL LETTER SIGMA
+        (?\\e,Ft\e(B . ?\x03C4) ;; GREEK SMALL LETTER TAU
+        (?\\e,Fu\e(B . ?\x03C5) ;; GREEK SMALL LETTER UPSILON
+        (?\\e,Fv\e(B . ?\x03C6) ;; GREEK SMALL LETTER PHI
+        (?\\e,Fw\e(B . ?\x03C7) ;; GREEK SMALL LETTER CHI
+        (?\\e,Fx\e(B . ?\x03C8) ;; GREEK SMALL LETTER PSI
+        (?\\e,Fy\e(B . ?\x03C9) ;; GREEK SMALL LETTER OMEGA
+        (?\\e,Fz\e(B . ?\x03CA) ;; GREEK SMALL LETTER IOTA WITH DIALYTIKA
+        (?\\e,F{\e(B . ?\x03CB) ;; GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+        (?\\e,F|\e(B . ?\x03CC) ;; GREEK SMALL LETTER OMICRON WITH TONOS
+        (?\\e,F}\e(B . ?\x03CD) ;; GREEK SMALL LETTER UPSILON WITH TONOS
+        (?\\e,F~\e(B . ?\x03CE) ;; GREEK SMALL LETTER OMEGA WITH TONOS
+        ))
+
+      (ucs-8859-8-alist
+       '((?\\e,H \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,H"\e(B . ?\x00A2) ;; CENT SIGN
+        (?\\e,H#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,H$\e(B . ?\x00A4) ;; CURRENCY SIGN
+        (?\\e,H%\e(B . ?\x00A5) ;; YEN SIGN
+        (?\\e,H&\e(B . ?\x00A6) ;; BROKEN BAR
+        (?\\e,H'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,H(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,H)\e(B . ?\x00A9) ;; COPYRIGHT SIGN
+        (?\\e,H*\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,H+\e(B . ?\x00AB) ;; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,H,\e(B . ?\x00AC) ;; NOT SIGN
+        (?\\e,H-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,H.\e(B . ?\x00AE) ;; REGISTERED SIGN
+        (?\\e,H/\e(B . ?\x00AF) ;; MACRON
+        (?\\e,H0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,H1\e(B . ?\x00B1) ;; PLUS-MINUS SIGN
+        (?\\e,H2\e(B . ?\x00B2) ;; SUPERSCRIPT TWO
+        (?\\e,H3\e(B . ?\x00B3) ;; SUPERSCRIPT THREE
+        (?\\e,H4\e(B . ?\x00B4) ;; ACUTE ACCENT
+        (?\\e,H5\e(B . ?\x00B5) ;; MICRO SIGN
+        (?\\e,H6\e(B . ?\x00B6) ;; PILCROW SIGN
+        (?\\e,H7\e(B . ?\x00B7) ;; MIDDLE DOT
+        (?\\e,H8\e(B . ?\x00B8) ;; CEDILLA
+        (?\\e,H9\e(B . ?\x00B9) ;; SUPERSCRIPT ONE
+        (?\\e,H:\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,H;\e(B . ?\x00BB) ;; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,H<\e(B . ?\x00BC) ;; VULGAR FRACTION ONE QUARTER
+        (?\\e,H=\e(B . ?\x00BD) ;; VULGAR FRACTION ONE HALF
+        (?\\e,H>\e(B . ?\x00BE) ;; VULGAR FRACTION THREE QUARTERS
+        ;; These are commented out since the current 8859-8 standard
+        ;; does not yet define these codepoints, although there are
+        ;; drafts which do).
+;       (?\\e,H@\e(B . ?\x05B0) ;; HEBREW POINT SHEVA
+;       (?\\e,HA\e(B . ?\x05B1) ;; HEBREW POINT HATAF SEGOL
+;       (?\\e,HB\e(B . ?\x05B2) ;; HEBREW POINT HATAF PATAH
+;       (?\\e,HC\e(B . ?\x05B3) ;; HEBREW POINT HATAF QAMATS
+;       (?\\e,HD\e(B . ?\x05B4) ;; HEBREW POINT HIRIQ
+;       (?\\e,HE\e(B . ?\x05B5) ;; HEBREW POINT TSERE
+;       (?\\e,HF\e(B . ?\x05B6) ;; HEBREW POINT SEGOL
+;       (?\\e,HG\e(B . ?\x05B7) ;; HEBREW POINT PATAH
+;       (?\\e,HH\e(B . ?\x05B8) ;; HEBREW POINT QAMATS
+;       (?\\e,HI\e(B . ?\x05B9) ;; HEBREW POINT HOLAM
+;       (?\\e,HK\e(B . ?\x05BB) ;; HEBREW POINT QUBUTS
+;       (?\\e,HL\e(B . ?\x05BC) ;; HEBREW POINT DAGESH
+;       (?\\e,HM\e(B . ?\x05BD) ;; HEBREW POINT METEG
+;       (?\\e,HN\e(B . ?\x05BE) ;; HEBREW POINT MAQAF
+;       (?\\e,HO\e(B . ?\x05BF) ;; HEBREW POINT RAFE
+;       (?\\e,HP\e(B . ?\x05C0) ;; HEBREW PUNCTUATION PASEQ
+;       (?\\e,HQ\e(B . ?\x05C1) ;; HEBREW POINT SHIN DOT
+;       (?\\e,HR\e(B . ?\x05C2) ;; HEBREW POINT SIN DOT
+;       (?\\e,HS\e(B . ?\x05C3) ;; HEBREW PUNCTUATION SOF PASUQ
+        (?\\e,H[\e(B . ?\x202D) ;; LEFT-TO-RIGHT OVERRIDE
+        (?\\e,H\\e(B . ?\x202E) ;; RIGHT-TO-LEFT OVERRIDE
+        (?\\e,H]\e(B . ?\x202C) ;; POP DIRECTIONAL FORMATTING
+        (?\\e,H_\e(B . ?\x2017) ;; DOUBLE LOW LINE
+        (?\\e,H`\e(B . ?\x05D0) ;; HEBREW LETTER ALEF
+        (?\\e,Ha\e(B . ?\x05D1) ;; HEBREW LETTER BET
+        (?\\e,Hb\e(B . ?\x05D2) ;; HEBREW LETTER GIMEL
+        (?\\e,Hc\e(B . ?\x05D3) ;; HEBREW LETTER DALET
+        (?\\e,Hd\e(B . ?\x05D4) ;; HEBREW LETTER HE
+        (?\\e,He\e(B . ?\x05D5) ;; HEBREW LETTER VAV
+        (?\\e,Hf\e(B . ?\x05D6) ;; HEBREW LETTER ZAYIN
+        (?\\e,Hg\e(B . ?\x05D7) ;; HEBREW LETTER HET
+        (?\\e,Hh\e(B . ?\x05D8) ;; HEBREW LETTER TET
+        (?\\e,Hi\e(B . ?\x05D9) ;; HEBREW LETTER YOD
+        (?\\e,Hj\e(B . ?\x05DA) ;; HEBREW LETTER FINAL KAF
+        (?\\e,Hk\e(B . ?\x05DB) ;; HEBREW LETTER KAF
+        (?\\e,Hl\e(B . ?\x05DC) ;; HEBREW LETTER LAMED
+        (?\\e,Hm\e(B . ?\x05DD) ;; HEBREW LETTER FINAL MEM
+        (?\\e,Hn\e(B . ?\x05DE) ;; HEBREW LETTER MEM
+        (?\\e,Ho\e(B . ?\x05DF) ;; HEBREW LETTER FINAL NUN
+        (?\\e,Hp\e(B . ?\x05E0) ;; HEBREW LETTER NUN
+        (?\\e,Hq\e(B . ?\x05E1) ;; HEBREW LETTER SAMEKH
+        (?\\e,Hr\e(B . ?\x05E2) ;; HEBREW LETTER AYIN
+        (?\\e,Hs\e(B . ?\x05E3) ;; HEBREW LETTER FINAL PE
+        (?\\e,Ht\e(B . ?\x05E4) ;; HEBREW LETTER PE
+        (?\\e,Hu\e(B . ?\x05E5) ;; HEBREW LETTER FINAL TSADI
+        (?\\e,Hv\e(B . ?\x05E6) ;; HEBREW LETTER TSADI
+        (?\\e,Hw\e(B . ?\x05E7) ;; HEBREW LETTER QOF
+        (?\\e,Hx\e(B . ?\x05E8) ;; HEBREW LETTER RESH
+        (?\\e,Hy\e(B . ?\x05E9) ;; HEBREW LETTER SHIN
+        (?\\e,Hz\e(B . ?\x05EA) ;; HEBREW LETTER TAV
+        (?\\e,H{\e(B . ?\x202A) ;; LEFT-TO-RIGHT EMBEDDING
+        (?\\e,H|\e(B . ?\x202B) ;; RIGHT-TO-LEFT EMBEDDING
+        (?\\e,H}\e(B . ?\x200E) ;; LEFT-TO-RIGHT MARK
+        (?\\e,H~\e(B . ?\x200F) ;; RIGHT-TO-LEFT MARK
+        ))
+
+      (ucs-8859-9-alist
+       '((?\\e,M \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,M!\e(B . ?\x00A1) ;; INVERTED EXCLAMATION MARK
+        (?\\e,M"\e(B . ?\x00A2) ;; CENT SIGN
+        (?\\e,M#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,M$\e(B . ?\x00A4) ;; CURRENCY SIGN
+        (?\\e,M%\e(B . ?\x00A5) ;; YEN SIGN
+        (?\\e,M&\e(B . ?\x00A6) ;; BROKEN BAR
+        (?\\e,M'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,M(\e(B . ?\x00A8) ;; DIAERESIS
+        (?\\e,M)\e(B . ?\x00A9) ;; COPYRIGHT SIGN
+        (?\\e,M*\e(B . ?\x00AA) ;; FEMININE ORDINAL INDICATOR
+        (?\\e,M+\e(B . ?\x00AB) ;; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,M,\e(B . ?\x00AC) ;; NOT SIGN
+        (?\\e,M-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,M.\e(B . ?\x00AE) ;; REGISTERED SIGN
+        (?\\e,M/\e(B . ?\x00AF) ;; MACRON
+        (?\\e,M0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,M1\e(B . ?\x00B1) ;; PLUS-MINUS SIGN
+        (?\\e,M2\e(B . ?\x00B2) ;; SUPERSCRIPT TWO
+        (?\\e,M3\e(B . ?\x00B3) ;; SUPERSCRIPT THREE
+        (?\\e,M4\e(B . ?\x00B4) ;; ACUTE ACCENT
+        (?\\e,M5\e(B . ?\x00B5) ;; MICRO SIGN
+        (?\\e,M6\e(B . ?\x00B6) ;; PILCROW SIGN
+        (?\\e,M7\e(B . ?\x00B7) ;; MIDDLE DOT
+        (?\\e,M8\e(B . ?\x00B8) ;; CEDILLA
+        (?\\e,M9\e(B . ?\x00B9) ;; SUPERSCRIPT ONE
+        (?\\e,M:\e(B . ?\x00BA) ;; MASCULINE ORDINAL INDICATOR
+        (?\\e,M;\e(B . ?\x00BB) ;; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,M<\e(B . ?\x00BC) ;; VULGAR FRACTION ONE QUARTER
+        (?\\e,M=\e(B . ?\x00BD) ;; VULGAR FRACTION ONE HALF
+        (?\\e,M>\e(B . ?\x00BE) ;; VULGAR FRACTION THREE QUARTERS
+        (?\\e,M?\e(B . ?\x00BF) ;; INVERTED QUESTION MARK
+        (?\\e,M@\e(B . ?\x00C0) ;; LATIN CAPITAL LETTER A WITH GRAVE
+        (?\\e,MA\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,MB\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,MC\e(B . ?\x00C3) ;; LATIN CAPITAL LETTER A WITH TILDE
+        (?\\e,MD\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,ME\e(B . ?\x00C5) ;; LATIN CAPITAL LETTER A WITH RING ABOVE
+        (?\\e,MF\e(B . ?\x00C6) ;; LATIN CAPITAL LETTER AE
+        (?\\e,MG\e(B . ?\x00C7) ;; LATIN CAPITAL LETTER C WITH CEDILLA
+        (?\\e,MH\e(B . ?\x00C8) ;; LATIN CAPITAL LETTER E WITH GRAVE
+        (?\\e,MI\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,MJ\e(B . ?\x00CA) ;; LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+        (?\\e,MK\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,ML\e(B . ?\x00CC) ;; LATIN CAPITAL LETTER I WITH GRAVE
+        (?\\e,MM\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,MN\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,MO\e(B . ?\x00CF) ;; LATIN CAPITAL LETTER I WITH DIAERESIS
+        (?\\e,MP\e(B . ?\x011E) ;; LATIN CAPITAL LETTER G WITH BREVE
+        (?\\e,MQ\e(B . ?\x00D1) ;; LATIN CAPITAL LETTER N WITH TILDE
+        (?\\e,MR\e(B . ?\x00D2) ;; LATIN CAPITAL LETTER O WITH GRAVE
+        (?\\e,MS\e(B . ?\x00D3) ;; LATIN CAPITAL LETTER O WITH ACUTE
+        (?\\e,MT\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,MU\e(B . ?\x00D5) ;; LATIN CAPITAL LETTER O WITH TILDE
+        (?\\e,MV\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,MW\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,MX\e(B . ?\x00D8) ;; LATIN CAPITAL LETTER O WITH STROKE
+        (?\\e,MY\e(B . ?\x00D9) ;; LATIN CAPITAL LETTER U WITH GRAVE
+        (?\\e,MZ\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,M[\e(B . ?\x00DB) ;; LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        (?\\e,M\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,M]\e(B . ?\x0130) ;; LATIN CAPITAL LETTER I WITH DOT ABOVE
+        (?\\e,M^\e(B . ?\x015E) ;; LATIN CAPITAL LETTER S WITH CEDILLA
+        (?\\e,M_\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,M`\e(B . ?\x00E0) ;; LATIN SMALL LETTER A WITH GRAVE
+        (?\\e,Ma\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,Mb\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,Mc\e(B . ?\x00E3) ;; LATIN SMALL LETTER A WITH TILDE
+        (?\\e,Md\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,Me\e(B . ?\x00E5) ;; LATIN SMALL LETTER A WITH RING ABOVE
+        (?\\e,Mf\e(B . ?\x00E6) ;; LATIN SMALL LETTER AE
+        (?\\e,Mg\e(B . ?\x00E7) ;; LATIN SMALL LETTER C WITH CEDILLA
+        (?\\e,Mh\e(B . ?\x00E8) ;; LATIN SMALL LETTER E WITH GRAVE
+        (?\\e,Mi\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,Mj\e(B . ?\x00EA) ;; LATIN SMALL LETTER E WITH CIRCUMFLEX
+        (?\\e,Mk\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,Ml\e(B . ?\x00EC) ;; LATIN SMALL LETTER I WITH GRAVE
+        (?\\e,Mm\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,Mn\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,Mo\e(B . ?\x00EF) ;; LATIN SMALL LETTER I WITH DIAERESIS
+        (?\\e,Mp\e(B . ?\x011F) ;; LATIN SMALL LETTER G WITH BREVE
+        (?\\e,Mq\e(B . ?\x00F1) ;; LATIN SMALL LETTER N WITH TILDE
+        (?\\e,Mr\e(B . ?\x00F2) ;; LATIN SMALL LETTER O WITH GRAVE
+        (?\\e,Ms\e(B . ?\x00F3) ;; LATIN SMALL LETTER O WITH ACUTE
+        (?\\e,Mt\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,Mu\e(B . ?\x00F5) ;; LATIN SMALL LETTER O WITH TILDE
+        (?\\e,Mv\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,Mw\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,Mx\e(B . ?\x00F8) ;; LATIN SMALL LETTER O WITH STROKE
+        (?\\e,My\e(B . ?\x00F9) ;; LATIN SMALL LETTER U WITH GRAVE
+        (?\\e,Mz\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,M{\e(B . ?\x00FB) ;; LATIN SMALL LETTER U WITH CIRCUMFLEX
+        (?\\e,M|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,M}\e(B . ?\x0131) ;; LATIN SMALL LETTER DOTLESS I
+        (?\\e,M~\e(B . ?\x015F) ;; LATIN SMALL LETTER S WITH CEDILLA
+        (?\\e,M\7f\e(B . ?\x00FF) ;; LATIN SMALL LETTER Y WITH DIAERESIS
+        ))
+
+      (ucs-8859-14-alist
+       '((?\\e,_ \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,_!\e(B . ?\x1E02) ;; LATIN CAPITAL LETTER B WITH DOT ABOVE
+        (?\\e,_"\e(B . ?\x1E03) ;; LATIN SMALL LETTER B WITH DOT ABOVE
+        (?\\e,_#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,_$\e(B . ?\x010A) ;; LATIN CAPITAL LETTER C WITH DOT ABOVE
+        (?\\e,_%\e(B . ?\x010B) ;; LATIN SMALL LETTER C WITH DOT ABOVE
+        (?\\e,_&\e(B . ?\x1E0A) ;; LATIN CAPITAL LETTER D WITH DOT ABOVE
+        (?\\e,_'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,_(\e(B . ?\x1E80) ;; LATIN CAPITAL LETTER W WITH GRAVE
+        (?\\e,_)\e(B . ?\x00A9) ;; COPYRIGHT SIGN
+        (?\\e,_*\e(B . ?\x1E82) ;; LATIN CAPITAL LETTER W WITH ACUTE
+        (?\\e,_+\e(B . ?\x1E0B) ;; LATIN SMALL LETTER D WITH DOT ABOVE
+        (?\\e,_,\e(B . ?\x1EF2) ;; LATIN CAPITAL LETTER Y WITH GRAVE
+        (?\\e,_-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,_.\e(B . ?\x00AE) ;; REGISTERED SIGN
+        (?\\e,_/\e(B . ?\x0178) ;; LATIN CAPITAL LETTER Y WITH DIAERESIS
+        (?\\e,_0\e(B . ?\x1E1E) ;; LATIN CAPITAL LETTER F WITH DOT ABOVE
+        (?\\e,_1\e(B . ?\x1E1F) ;; LATIN SMALL LETTER F WITH DOT ABOVE
+        (?\\e,_2\e(B . ?\x0120) ;; LATIN CAPITAL LETTER G WITH DOT ABOVE
+        (?\\e,_3\e(B . ?\x0121) ;; LATIN SMALL LETTER G WITH DOT ABOVE
+        (?\\e,_4\e(B . ?\x1E40) ;; LATIN CAPITAL LETTER M WITH DOT ABOVE
+        (?\\e,_5\e(B . ?\x1E41) ;; LATIN SMALL LETTER M WITH DOT ABOVE
+        (?\\e,_6\e(B . ?\x00B6) ;; PILCROW SIGN
+        (?\\e,_7\e(B . ?\x1E56) ;; LATIN CAPITAL LETTER P WITH DOT ABOVE
+        (?\\e,_8\e(B . ?\x1E81) ;; LATIN SMALL LETTER W WITH GRAVE
+        (?\\e,_9\e(B . ?\x1E57) ;; LATIN SMALL LETTER P WITH DOT ABOVE
+        (?\\e,_:\e(B . ?\x1E83) ;; LATIN SMALL LETTER W WITH ACUTE
+        (?\\e,_;\e(B . ?\x1E60) ;; LATIN CAPITAL LETTER S WITH DOT ABOVE
+        (?\\e,_<\e(B . ?\x1EF3) ;; LATIN SMALL LETTER Y WITH GRAVE
+        (?\\e,_=\e(B . ?\x1E84) ;; LATIN CAPITAL LETTER W WITH DIAERESIS
+        (?\\e,_>\e(B . ?\x1E85) ;; LATIN SMALL LETTER W WITH DIAERESIS
+        (?\\e,_?\e(B . ?\x1E61) ;; LATIN SMALL LETTER S WITH DOT ABOVE
+        (?\\e,_@\e(B . ?\x00C0) ;; LATIN CAPITAL LETTER A WITH GRAVE
+        (?\\e,_A\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,_B\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,_C\e(B . ?\x00C3) ;; LATIN CAPITAL LETTER A WITH TILDE
+        (?\\e,_D\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,_E\e(B . ?\x00C5) ;; LATIN CAPITAL LETTER A WITH RING ABOVE
+        (?\\e,_F\e(B . ?\x00C6) ;; LATIN CAPITAL LETTER AE
+        (?\\e,_G\e(B . ?\x00C7) ;; LATIN CAPITAL LETTER C WITH CEDILLA
+        (?\\e,_H\e(B . ?\x00C8) ;; LATIN CAPITAL LETTER E WITH GRAVE
+        (?\\e,_I\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,_J\e(B . ?\x00CA) ;; LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+        (?\\e,_K\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,_L\e(B . ?\x00CC) ;; LATIN CAPITAL LETTER I WITH GRAVE
+        (?\\e,_M\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,_N\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,_O\e(B . ?\x00CF) ;; LATIN CAPITAL LETTER I WITH DIAERESIS
+        (?\\e,_P\e(B . ?\x0174) ;; LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+        (?\\e,_Q\e(B . ?\x00D1) ;; LATIN CAPITAL LETTER N WITH TILDE
+        (?\\e,_R\e(B . ?\x00D2) ;; LATIN CAPITAL LETTER O WITH GRAVE
+        (?\\e,_S\e(B . ?\x00D3) ;; LATIN CAPITAL LETTER O WITH ACUTE
+        (?\\e,_T\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,_U\e(B . ?\x00D5) ;; LATIN CAPITAL LETTER O WITH TILDE
+        (?\\e,_V\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,_W\e(B . ?\x1E6A) ;; LATIN CAPITAL LETTER T WITH DOT ABOVE
+        (?\\e,_X\e(B . ?\x00D8) ;; LATIN CAPITAL LETTER O WITH STROKE
+        (?\\e,_Y\e(B . ?\x00D9) ;; LATIN CAPITAL LETTER U WITH GRAVE
+        (?\\e,_Z\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,_[\e(B . ?\x00DB) ;; LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        (?\\e,_\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,_]\e(B . ?\x00DD) ;; LATIN CAPITAL LETTER Y WITH ACUTE
+        (?\\e,_^\e(B . ?\x0176) ;; LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+        (?\\e,__\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,_`\e(B . ?\x00E0) ;; LATIN SMALL LETTER A WITH GRAVE
+        (?\\e,_a\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,_b\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,_c\e(B . ?\x00E3) ;; LATIN SMALL LETTER A WITH TILDE
+        (?\\e,_d\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,_e\e(B . ?\x00E5) ;; LATIN SMALL LETTER A WITH RING ABOVE
+        (?\\e,_f\e(B . ?\x00E6) ;; LATIN SMALL LETTER AE
+        (?\\e,_g\e(B . ?\x00E7) ;; LATIN SMALL LETTER C WITH CEDILLA
+        (?\\e,_h\e(B . ?\x00E8) ;; LATIN SMALL LETTER E WITH GRAVE
+        (?\\e,_i\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,_j\e(B . ?\x00EA) ;; LATIN SMALL LETTER E WITH CIRCUMFLEX
+        (?\\e,_k\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,_l\e(B . ?\x00EC) ;; LATIN SMALL LETTER I WITH GRAVE
+        (?\\e,_m\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,_n\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,_o\e(B . ?\x00EF) ;; LATIN SMALL LETTER I WITH DIAERESIS
+        (?\\e,_p\e(B . ?\x0175) ;; LATIN SMALL LETTER W WITH CIRCUMFLEX
+        (?\\e,_q\e(B . ?\x00F1) ;; LATIN SMALL LETTER N WITH TILDE
+        (?\\e,_r\e(B . ?\x00F2) ;; LATIN SMALL LETTER O WITH GRAVE
+        (?\\e,_s\e(B . ?\x00F3) ;; LATIN SMALL LETTER O WITH ACUTE
+        (?\\e,_t\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,_u\e(B . ?\x00F5) ;; LATIN SMALL LETTER O WITH TILDE
+        (?\\e,_v\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,_w\e(B . ?\x1E6B) ;; LATIN SMALL LETTER T WITH DOT ABOVE
+        (?\\e,_x\e(B . ?\x00F8) ;; LATIN SMALL LETTER O WITH STROKE
+        (?\\e,_y\e(B . ?\x00F9) ;; LATIN SMALL LETTER U WITH GRAVE
+        (?\\e,_z\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,_{\e(B . ?\x00FB) ;; LATIN SMALL LETTER U WITH CIRCUMFLEX
+        (?\\e,_|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,_}\e(B . ?\x00FD) ;; LATIN SMALL LETTER Y WITH ACUTE
+        (?\\e,_~\e(B . ?\x0177) ;; LATIN SMALL LETTER Y WITH CIRCUMFLEX
+        (?\\e,_\7f\e(B . ?\x00FF) ;; LATIN SMALL LETTER Y WITH DIAERESIS
+        ))
+
+      (ucs-8859-15-alist
+       '((?\\e,b \e(B . ?\x00A0) ;; NO-BREAK SPACE
+        (?\\e,b!\e(B . ?\x00A1) ;; INVERTED EXCLAMATION MARK
+        (?\\e,b"\e(B . ?\x00A2) ;; CENT SIGN
+        (?\\e,b#\e(B . ?\x00A3) ;; POUND SIGN
+        (?\\e,b$\e(B . ?\x20AC) ;; EURO SIGN
+        (?\\e,b%\e(B . ?\x00A5) ;; YEN SIGN
+        (?\\e,b&\e(B . ?\x0160) ;; LATIN CAPITAL LETTER S WITH CARON
+        (?\\e,b'\e(B . ?\x00A7) ;; SECTION SIGN
+        (?\\e,b(\e(B . ?\x0161) ;; LATIN SMALL LETTER S WITH CARON
+        (?\\e,b)\e(B . ?\x00A9) ;; COPYRIGHT SIGN
+        (?\\e,b*\e(B . ?\x00AA) ;; FEMININE ORDINAL INDICATOR
+        (?\\e,b+\e(B . ?\x00AB) ;; LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,b,\e(B . ?\x00AC) ;; NOT SIGN
+        (?\\e,b-\e(B . ?\x00AD) ;; SOFT HYPHEN
+        (?\\e,b.\e(B . ?\x00AE) ;; REGISTERED SIGN
+        (?\\e,b/\e(B . ?\x00AF) ;; MACRON
+        (?\\e,b0\e(B . ?\x00B0) ;; DEGREE SIGN
+        (?\\e,b1\e(B . ?\x00B1) ;; PLUS-MINUS SIGN
+        (?\\e,b2\e(B . ?\x00B2) ;; SUPERSCRIPT TWO
+        (?\\e,b3\e(B . ?\x00B3) ;; SUPERSCRIPT THREE
+        (?\\e,b4\e(B . ?\x017D) ;; LATIN CAPITAL LETTER Z WITH CARON
+        (?\\e,b5\e(B . ?\x00B5) ;; MICRO SIGN
+        (?\\e,b6\e(B . ?\x00B6) ;; PILCROW SIGN
+        (?\\e,b7\e(B . ?\x00B7) ;; MIDDLE DOT
+        (?\\e,b8\e(B . ?\x017E) ;; LATIN SMALL LETTER Z WITH CARON
+        (?\\e,b9\e(B . ?\x00B9) ;; SUPERSCRIPT ONE
+        (?\\e,b:\e(B . ?\x00BA) ;; MASCULINE ORDINAL INDICATOR
+        (?\\e,b;\e(B . ?\x00BB) ;; RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+        (?\\e,b<\e(B . ?\x0152) ;; LATIN CAPITAL LIGATURE OE
+        (?\\e,b=\e(B . ?\x0153) ;; LATIN SMALL LIGATURE OE
+        (?\\e,b>\e(B . ?\x0178) ;; LATIN CAPITAL LETTER Y WITH DIAERESIS
+        (?\\e,b?\e(B . ?\x00BF) ;; INVERTED QUESTION MARK
+        (?\\e,b@\e(B . ?\x00C0) ;; LATIN CAPITAL LETTER A WITH GRAVE
+        (?\\e,bA\e(B . ?\x00C1) ;; LATIN CAPITAL LETTER A WITH ACUTE
+        (?\\e,bB\e(B . ?\x00C2) ;; LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+        (?\\e,bC\e(B . ?\x00C3) ;; LATIN CAPITAL LETTER A WITH TILDE
+        (?\\e,bD\e(B . ?\x00C4) ;; LATIN CAPITAL LETTER A WITH DIAERESIS
+        (?\\e,bE\e(B . ?\x00C5) ;; LATIN CAPITAL LETTER A WITH RING ABOVE
+        (?\\e,bF\e(B . ?\x00C6) ;; LATIN CAPITAL LETTER AE
+        (?\\e,bG\e(B . ?\x00C7) ;; LATIN CAPITAL LETTER C WITH CEDILLA
+        (?\\e,bH\e(B . ?\x00C8) ;; LATIN CAPITAL LETTER E WITH GRAVE
+        (?\\e,bI\e(B . ?\x00C9) ;; LATIN CAPITAL LETTER E WITH ACUTE
+        (?\\e,bJ\e(B . ?\x00CA) ;; LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+        (?\\e,bK\e(B . ?\x00CB) ;; LATIN CAPITAL LETTER E WITH DIAERESIS
+        (?\\e,bL\e(B . ?\x00CC) ;; LATIN CAPITAL LETTER I WITH GRAVE
+        (?\\e,bM\e(B . ?\x00CD) ;; LATIN CAPITAL LETTER I WITH ACUTE
+        (?\\e,bN\e(B . ?\x00CE) ;; LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        (?\\e,bO\e(B . ?\x00CF) ;; LATIN CAPITAL LETTER I WITH DIAERESIS
+        (?\\e,bP\e(B . ?\x00D0) ;; LATIN CAPITAL LETTER ETH
+        (?\\e,bQ\e(B . ?\x00D1) ;; LATIN CAPITAL LETTER N WITH TILDE
+        (?\\e,bR\e(B . ?\x00D2) ;; LATIN CAPITAL LETTER O WITH GRAVE
+        (?\\e,bS\e(B . ?\x00D3) ;; LATIN CAPITAL LETTER O WITH ACUTE
+        (?\\e,bT\e(B . ?\x00D4) ;; LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+        (?\\e,bU\e(B . ?\x00D5) ;; LATIN CAPITAL LETTER O WITH TILDE
+        (?\\e,bV\e(B . ?\x00D6) ;; LATIN CAPITAL LETTER O WITH DIAERESIS
+        (?\\e,bW\e(B . ?\x00D7) ;; MULTIPLICATION SIGN
+        (?\\e,bX\e(B . ?\x00D8) ;; LATIN CAPITAL LETTER O WITH STROKE
+        (?\\e,bY\e(B . ?\x00D9) ;; LATIN CAPITAL LETTER U WITH GRAVE
+        (?\\e,bZ\e(B . ?\x00DA) ;; LATIN CAPITAL LETTER U WITH ACUTE
+        (?\\e,b[\e(B . ?\x00DB) ;; LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+        (?\\e,b\\e(B . ?\x00DC) ;; LATIN CAPITAL LETTER U WITH DIAERESIS
+        (?\\e,b]\e(B . ?\x00DD) ;; LATIN CAPITAL LETTER Y WITH ACUTE
+        (?\\e,b^\e(B . ?\x00DE) ;; LATIN CAPITAL LETTER THORN
+        (?\\e,b_\e(B . ?\x00DF) ;; LATIN SMALL LETTER SHARP S
+        (?\\e,b`\e(B . ?\x00E0) ;; LATIN SMALL LETTER A WITH GRAVE
+        (?\\e,ba\e(B . ?\x00E1) ;; LATIN SMALL LETTER A WITH ACUTE
+        (?\\e,bb\e(B . ?\x00E2) ;; LATIN SMALL LETTER A WITH CIRCUMFLEX
+        (?\\e,bc\e(B . ?\x00E3) ;; LATIN SMALL LETTER A WITH TILDE
+        (?\\e,bd\e(B . ?\x00E4) ;; LATIN SMALL LETTER A WITH DIAERESIS
+        (?\\e,be\e(B . ?\x00E5) ;; LATIN SMALL LETTER A WITH RING ABOVE
+        (?\\e,bf\e(B . ?\x00E6) ;; LATIN SMALL LETTER AE
+        (?\\e,bg\e(B . ?\x00E7) ;; LATIN SMALL LETTER C WITH CEDILLA
+        (?\\e,bh\e(B . ?\x00E8) ;; LATIN SMALL LETTER E WITH GRAVE
+        (?\\e,bi\e(B . ?\x00E9) ;; LATIN SMALL LETTER E WITH ACUTE
+        (?\\e,bj\e(B . ?\x00EA) ;; LATIN SMALL LETTER E WITH CIRCUMFLEX
+        (?\\e,bk\e(B . ?\x00EB) ;; LATIN SMALL LETTER E WITH DIAERESIS
+        (?\\e,bl\e(B . ?\x00EC) ;; LATIN SMALL LETTER I WITH GRAVE
+        (?\\e,bm\e(B . ?\x00ED) ;; LATIN SMALL LETTER I WITH ACUTE
+        (?\\e,bn\e(B . ?\x00EE) ;; LATIN SMALL LETTER I WITH CIRCUMFLEX
+        (?\\e,bo\e(B . ?\x00EF) ;; LATIN SMALL LETTER I WITH DIAERESIS
+        (?\\e,bp\e(B . ?\x00F0) ;; LATIN SMALL LETTER ETH
+        (?\\e,bq\e(B . ?\x00F1) ;; LATIN SMALL LETTER N WITH TILDE
+        (?\\e,br\e(B . ?\x00F2) ;; LATIN SMALL LETTER O WITH GRAVE
+        (?\\e,bs\e(B . ?\x00F3) ;; LATIN SMALL LETTER O WITH ACUTE
+        (?\\e,bt\e(B . ?\x00F4) ;; LATIN SMALL LETTER O WITH CIRCUMFLEX
+        (?\\e,bu\e(B . ?\x00F5) ;; LATIN SMALL LETTER O WITH TILDE
+        (?\\e,bv\e(B . ?\x00F6) ;; LATIN SMALL LETTER O WITH DIAERESIS
+        (?\\e,bw\e(B . ?\x00F7) ;; DIVISION SIGN
+        (?\\e,bx\e(B . ?\x00F8) ;; LATIN SMALL LETTER O WITH STROKE
+        (?\\e,by\e(B . ?\x00F9) ;; LATIN SMALL LETTER U WITH GRAVE
+        (?\\e,bz\e(B . ?\x00FA) ;; LATIN SMALL LETTER U WITH ACUTE
+        (?\\e,b{\e(B . ?\x00FB) ;; LATIN SMALL LETTER U WITH CIRCUMFLEX
+        (?\\e,b|\e(B . ?\x00FC) ;; LATIN SMALL LETTER U WITH DIAERESIS
+        (?\\e,b}\e(B . ?\x00FD) ;; LATIN SMALL LETTER Y WITH ACUTE
+        (?\\e,b~\e(B . ?\x00FE) ;; LATIN SMALL LETTER THORN
+        (?\\e,b\7f\e(B . ?\x00FF) ;; LATIN SMALL LETTER Y WITH DIAERESIS
+        ))
+
+      (ucs-8859-1-alist
+       (let ((i 160)
+            l)
+        (while (< i 256)
+          (push (cons (make-char 'latin-iso8859-1 (- i 128)) i)
+                l)
+          (setq i (1+ i)))
+        (nreverse l)))
+      
+;;       (case-table (standard-case-table))
+;;       (syntax-table (standard-syntax-table))
+      )
+
+  ;; Convert the lists to the basic char tables.
+  (dolist (n (list 15 14 9 8 7 5 4 3 2 1))
+    (let ((alist (symbol-value (intern (format "ucs-8859-%d-alist" n)))))
+      (dolist (pair alist)
+       (let ((mule (car pair))
+             (uc (cdr pair))
+             (mu (decode-char 'ucs (cdr pair))))
+         (aset ucs-mule-8859-to-ucs-table mule uc)
+         ;;      (aset ucs-ucs-to-mule-8859-table uc mule)
+         ;;      (aset ucs-mule-unicode-to-mule-8859 mu mule)
+         (aset ucs-mule-8859-to-mule-unicode mule mu)
+         (aset ucs-mule-to-mule-unicode mule mu)))
+;; I think this is actually done OK in characters.el.
+;; Probably things like accents shouldn't have word syntax, but the
+;; Latin-N syntax tables currently aren't consistent for such
+;; characters anyhow.
+;;      ;; Make the mule-unicode characters inherit syntax and case info
+;;      ;; if they don't already have it.
+;;      (dolist (pair alist)
+;;     (let ((mule (car pair))
+;;           (uc (cdr pair))
+;;           (mu (decode-char 'ucs (cdr pair))))
+;;       (let ((syntax (aref syntax-table mule)))
+;;         (if (eq mule (downcase mule))
+;;             (if (eq mule (upcase mule)) ; non-letter or uncased letter
+;;                 (progn
+;;                   (if (= 4 (car syntax)) ; left delim
+;;                       (progn
+;;                         (aset syntax-table
+;;                               mu
+;;                               (cons 4 (aref ucs-mule-8859-to-mule-unicode
+;;                                             (cdr syntax))))
+;;                         (aset syntax-table
+;;                               (aref ucs-mule-8859-to-mule-unicode
+;;                                     (cdr syntax))
+;;                               (cons 5 mu)))
+;;                     (aset syntax-table mu syntax))
+;;                   (aset case-table mu mu)))
+;;           ;; Upper case letter
+;;           (let ((lower (aref ucs-mule-8859-to-mule-unicode
+;;                              (aref case-table mule))))
+;;             (aset case-table mu lower)
+;;             (aset case-table lower lower)
+;;             (modify-syntax-entry lower "w   " syntax-table)
+;;             (modify-syntax-entry mu "w   " syntax-table))))))
+      ))
+  ;; Derive tables that can be used as per-coding-system
+  ;; `translation-table-for-encode's.
+  (dolist (n (list 15 14 9 8 7 5 4 3 2 1))
+    (let* ((alist (symbol-value (intern (format "ucs-8859-%d-alist" n))))
+          (encode-translator (set (intern (format "ucs-8859-%d-encode-table"
+                                                  n))
+                                  (make-translation-table)))
+          elt)
+      ;; Start with the mule-unicode component.
+      (dolist (pair alist)
+       (let ((mule (car pair))
+             (mu (decode-char 'ucs (cdr pair))))
+         (aset encode-translator mu mule)))
+      ;; Find characters from other 8859 sets which map to the same
+      ;; unicode as some character in this set.
+      (map-char-table (lambda (k v)
+                       (if (and (setq elt (rassq v alist))
+                                (not (assq k alist)))
+                           (aset encode-translator k (car elt))))
+                     ucs-mule-8859-to-ucs-table))))
+
+;; Register for use in CCL.
+(define-translation-table 'ucs-mule-8859-to-mule-unicode
+  ucs-mule-8859-to-mule-unicode)
+
+;; Fixme: Make this reversible, which means frobbing
+;; `char-coding-system-table' directly to remove what we added -- see
+;; codepages.el.  Also make it a user option.
+(defun ucs-unify-8859 (&optional encode-only)
+  "Set up translation tables for unifying characters from ISO 8859.
+
+On decoding, non-ASCII characters are mapped into the `iso-latin-1'
+and `mule-unicode-0100-24ff' charsets.  On encoding, these are mapped
+back appropriate for the coding system.
+
+With prefix arg, do unification on encoding only, i.e. don't unify
+everything on input operations."
+  (interactive "P")
+  (unless encode-only
+    ;; Unify 8859 on decoding.  (Non-CCL coding systems only.)
+    (set-char-table-parent standard-translation-table-for-decode
+                          ucs-mule-8859-to-mule-unicode))
+  ;; Adjust the 8859 coding systems to fragment the unified characters
+  ;; on encoding.
+  (dolist (n '(1 2 3 4 5 7 8 9 14 15))
+    (let* ((coding-system
+           (coding-system-base (intern (format "iso-8859-%d" n))))
+          (table (symbol-value
+                  (intern (format "ucs-8859-%d-encode-table" n))))
+          (safe (coding-system-get coding-system 'safe-chars)))
+      ;; Actually, the coding system's safe-chars are not normally
+      ;; used after they've been registered, but we might as well
+      ;; record them.  Setting the parent here is a convenience.
+      (set-char-table-parent safe table)
+      ;; Update the table of what encodes to what.
+      (register-char-codings coding-system table)
+      (coding-system-put coding-system 'translation-table-for-encode table)))
+
+;;; The following works for the bundled coding systems, but it's
+;;; better to use the Unicode-based ones and make it irrelevant.
+
+;;;   ;; Update the Cyrillic special cases.
+;;;   ;; `translation-table-for-encode' doesn't work for CCL coding
+;;;   ;; systems, and `standard-translation-table-for-decode' isn't
+;;;   ;; applied.
+;;;   (let ((table (get 'cyrillic-koi8-r-encode-table 'translation-table)))
+;;;     (map-char-table
+;;;      (lambda (k v)
+;;;        (aset table
+;;;         (or (aref ucs-8859-5-encode-table k)
+;;;             k)
+;;;         v))
+;;;      table)
+;;;     (register-char-codings 'cyrillic-koi8 table))
+;;;   (let ((table (get 'cyrillic-koi8-r-nonascii-translation-table
+;;;                'translation-table)))
+;;;     (map-char-table
+;;;      (lambda (k v)
+;;;        (if v (aset table k (or (aref ucs-mule-8859-to-mule-unicode v)
+;;;                           v))))
+;;;      table))
+;;;   ;; Redefine this, since the orginal only translated 8859-5.
+;;;   (define-ccl-program ccl-encode-koi8
+;;;     `(1
+;;;       ((loop
+;;;    (read-multibyte-character r0 r1)
+;;;    (translate-character cyrillic-koi8-r-encode-table r0 r1)
+;;;    (write-repeat r1))))
+;;;     "CCL program to encode KOI8.")
+;;;   (let ((table (get 'cyrillic-alternativnyj-encode-table 'translation-table)))
+;;;     (map-char-table
+;;;      (lambda (k v)
+;;;        (aset table
+;;;         (or (aref ucs-8859-5-encode-table k)
+;;;             k)
+;;;         v))
+;;;      table)
+;;;     (register-char-codings 'cyrillic-alternativnyj table))
+;;;   (let ((table (get 'cyrillic-alternativnyj-nonascii-translation-table
+;;;                'translation-table)))
+;;;     (map-char-table
+;;;      (lambda (k v)
+;;;        (if v (aset table
+;;;               k
+;;;               (or (aref ucs-mule-8859-to-mule-unicode v)
+;;;                   v))))
+;;;      table))
+  )
+
+(defun ucs-fragment-8859 (&optional encode-only)
+  "Undo the unification done by `ucs-unify-8859'.
+With prefix arg, undo unification on encoding only, i.e. don't undo
+unification on input operations."
+  (interactive "P")
+  ;; Maybe fix decoding.
+  (unless encode-only
+    ;; Unify 8859 on decoding.  (Non-CCL coding systems only.)
+    (set-char-table-parent standard-translation-table-for-decode nil))
+  ;; Fix encoding.  For each charset, remove the entries in
+  ;; `char-coding-system-table' added to its safe-chars table (as its
+  ;; parent).
+  (dolist (n '(1 2 3 4 5 7 8 9 14 15))
+    (let* ((coding-system
+           (coding-system-base (intern (format "iso-8859-%d" n))))
+          (table (symbol-value
+                  (intern (format "ucs-8859-%d-encode-table" n))))
+          (safe (coding-system-get coding-system 'safe-chars)))
+      (map-char-table
+       (lambda (key val)
+        (if (and (>= key 128) val)
+            (let ((codings (aref char-coding-system-table key)))
+              (aset char-coding-system-table key
+                    (delq coding-system codings)))))
+       (char-table-parent safe))
+      (set-char-table-parent safe nil)
+      (coding-system-put coding-system 'translation-table-for-encode nil))))
+
+;;;###autoload
+(define-minor-mode unify-8859-on-encoding-mode
+  "Set up translation tables for unifying ISO 8859 characters on encoding.
+
+The ISO 8859 characters sets overlap, e.g. 8859-1 (Latin-1) and
+8859-15 (Latin-9) differ only in a few characters.  Emacs normally
+distinguishes equivalent characters from those ISO-8859 character sets
+which are built in to Emacs.  This behaviour is essentially inherited
+from the European-originated international standards.  Treating them
+equivalently, by translating to and from a single representation is
+called `unification'.  (The `utf-8' coding system treats the
+characters of European scripts in a unified manner.)
+
+In this mode, on encoding -- i.e. output operations -- non-ASCII
+characters from the built-in ISO 8859 and `mule-unicode-0100-24ff'
+charsets are handled automatically by the coding system used if it can
+represent them.  Thus, say, an e-acute from the Latin-1 charset (the
+unified representation) in a buffer saved as Latin-9 will be encoded
+directly to a byte value 233.  By default, in contrast, you would be
+prompted for a general coding system to use for saving the file, which
+can cope with separate Latin-1 and Latin-9 representations of e-acute.
+
+See also command `unify-8859-on-decoding-mode'."
+  :group 'mule
+  :global t
+  :version 21.3                                ; who knows...?
+  :init-value nil
+  (if unify-8859-on-encoding-mode
+      (ucs-unify-8859 t)
+    (ucs-fragment-8859 t)))
+
+;;;###autoload
+(define-minor-mode unify-8859-on-decoding-mode
+  "Set up translation table for unifying ISO 8859 characters on decoding.
+On decoding -- i.e. input operations -- non-ASCII characters from the
+built-in ISO 8859 charsets are unified by mapping them into the
+`iso-latin-1' and `mule-unicode-0100-24ff' charsets.
+
+This sets the parent of `standard-translation-table-for-decode'.
+
+See also command `unify-8859-on-encoding-mode'."
+  :group 'mule
+  :global t
+  :version 21.3                                ; who knows...?
+  :init-value nil
+  (if unify-8859-on-decoding-mode
+      (set-char-table-parent standard-translation-table-for-decode
+                            ucs-mule-8859-to-mule-unicode)
+    (set-char-table-parent standard-translation-table-for-decode nil)))
+
+(defun ucs-insert (arg)
+  "Insert the Emacs character representation of the given Unicode.
+Interactively, prompts for a hex string giving the code."
+  (interactive "sUnicode (hex): ")
+  (insert (decode-char 'ucs (if (integerp arg)
+                               arg
+                             (string-to-number arg 16)))))
+
+;;; Dealing with non-8859 character sets.
+
+;; We only set up translation on encoding to utf-8.  Also translation
+;; tables ucs-CS-encode-table are constructed for some coding systems
+;; CS which could be used as `translation-table-for-encode', currently
+;; for indian-is13194, lao, thai, tibetan-iso-8bit and
+;; vietnamese-viscii.
+
+;; The alists here cover both coding systems (external charsets), like
+;; VISCII, and individual Emacs charsets, like `ipa'.
+(let ((vietnamese-viscii
+       '((?\e,1!\e(B . ?\e$,1o/\e(B)
+        (?\e,1"\e(B . ?\e$,1o1\e(B)
+        (?\e,1#\e(B . ?\e$,1o7\e(B)
+        (?\e,1$\e(B . ?\e$,1o%\e(B)
+        (?\e,1%\e(B . ?\e$,1o'\e(B)
+        (?\e,1&\e(B . ?\e$,1o)\e(B)
+        (?\e,1'\e(B . ?\e$,1o-\e(B)
+        (?\e,1(\e(B . ?\e$,1o=\e(B)
+        (?\e,1)\e(B . ?\e$,1o9\e(B)
+        (?\e,1*\e(B . ?\e$,1o?\e(B)
+        (?\e,1+\e(B . ?\e$,1oA\e(B)
+        (?\e,1,\e(B . ?\e$,1oC\e(B)
+        (?\e,1-\e(B . ?\e$,1oE\e(B)
+        (?\e,1.\e(B . ?\e$,1oG\e(B)
+        (?\e,1/\e(B . ?\e$,1oQ\e(B)
+        (?\e,10\e(B . ?\e$,1oS\e(B)
+        (?\e,11\e(B . ?\e$,1oU\e(B)
+        (?\e,12\e(B . ?\e$,1oW\e(B)
+        (?\e,15\e(B . ?\e$,1oY\e(B)
+        (?\e,16\e(B . ?\e$,1o]\e(B)
+        (?\e,17\e(B . ?\e$,1o_\e(B)
+        (?\e,18\e(B . ?\e$,1oK\e(B)
+        (?\e,1=\e(B . ?\e$,1!a\e(B)
+        (?\e,1>\e(B . ?\e$,1o[\e(B)
+        (?\e,1F\e(B . ?\e$,1o3\e(B)
+        (?\e,1G\e(B . ?\e$,1o5\e(B)
+        (?\e,1O\e(B . ?\e$,1os\e(B)
+        (?\e,1Q\e(B . ?\e$,1oi\e(B)
+        (?\e,1U\e(B . ?\e$,1o!\e(B)
+        (?\e,1V\e(B . ?\e$,1ow\e(B)
+        (?\e,1W\e(B . ?\e$,1ok\e(B)
+        (?\e,1X\e(B . ?\e$,1om\e(B)
+        (?\e,1[\e(B . ?\e$,1oy\e(B)
+        (?\e,1\\e(B . ?\e$,1ou\e(B)
+        (?\e,1^\e(B . ?\e$,1oa\e(B)
+        (?\e,1_\e(B . ?\e$,1!p\e(B)
+        (?\e,1`\e(B . ?\e,A`\e(B)
+        (?\e,1a\e(B . ?\e,Aa\e(B)
+        (?\e,1b\e(B . ?\e,Ab\e(B)
+        (?\e,1c\e(B . ?\e,Ac\e(B)
+        (?\e,1d\e(B . ?\e$,1o#\e(B)
+        (?\e,1e\e(B . ?\e$,1 #\e(B)
+        (?\e,1f\e(B . ?\e$,1oo\e(B)
+        (?\e,1g\e(B . ?\e$,1o+\e(B)
+        (?\e,1h\e(B . ?\e,Ah\e(B)
+        (?\e,1i\e(B . ?\e,Ai\e(B)
+        (?\e,1j\e(B . ?\e,Aj\e(B)
+        (?\e,1k\e(B . ?\e$,1o;\e(B)
+        (?\e,1l\e(B . ?\e,Al\e(B)
+        (?\e,1m\e(B . ?\e,Am\e(B)
+        (?\e,1n\e(B . ?\e$,1 I\e(B)
+        (?\e,1o\e(B . ?\e$,1oI\e(B)
+        (?\e,1p\e(B . ?\e$,1 1\e(B)
+        (?\e,1q\e(B . ?\e$,1oq\e(B)
+        (?\e,1r\e(B . ?\e,Ar\e(B)
+        (?\e,1s\e(B . ?\e,As\e(B)
+        (?\e,1t\e(B . ?\e,At\e(B)
+        (?\e,1u\e(B . ?\e,Au\e(B)
+        (?\e,1v\e(B . ?\e$,1oO\e(B)
+        (?\e,1w\e(B . ?\e$,1oM\e(B)
+        (?\e,1x\e(B . ?\e$,1oe\e(B)
+        (?\e,1y\e(B . ?\e,Ay\e(B)
+        (?\e,1z\e(B . ?\e,Az\e(B)
+        (?\e,1{\e(B . ?\e$,1!)\e(B)
+        (?\e,1|\e(B . ?\e$,1og\e(B)
+        (?\e,1}\e(B . ?\e,A}\e(B)
+        (?\e,1~\e(B . ?\e$,1oc\e(B)
+
+        (?\e,2!\e(B . ?\e$,1o.\e(B)
+        (?\e,2"\e(B . ?\e$,1o0\e(B)
+        (?\e,2#\e(B . ?\e$,1o6\e(B)
+        (?\e,2$\e(B . ?\e$,1o$\e(B)
+        (?\e,2%\e(B . ?\e$,1o&\e(B)
+        (?\e,2&\e(B . ?\e$,1o(\e(B)
+        (?\e,2'\e(B . ?\e$,1o,\e(B)
+        (?\e,2(\e(B . ?\e$,1o<\e(B)
+        (?\e,2)\e(B . ?\e$,1o8\e(B)
+        (?\e,2*\e(B . ?\e$,1o>\e(B)
+        (?\e,2+\e(B . ?\e$,1o@\e(B)
+        (?\e,2,\e(B . ?\e$,1oB\e(B)
+        (?\e,2-\e(B . ?\e$,1oD\e(B)
+        (?\e,2.\e(B . ?\e$,1oF\e(B)
+        (?\e,2/\e(B . ?\e$,1oP\e(B)
+        (?\e,20\e(B . ?\e$,1oR\e(B)
+        (?\e,21\e(B . ?\e$,1oT\e(B)
+        (?\e,22\e(B . ?\e$,1oV\e(B)
+        (?\e,25\e(B . ?\e$,1oX\e(B)
+        (?\e,26\e(B . ?\e$,1o\\e(B)
+        (?\e,27\e(B . ?\e$,1o^\e(B)
+        (?\e,28\e(B . ?\e$,1oJ\e(B)
+        (?\e,2=\e(B . ?\e$,1!`\e(B)
+        (?\e,2>\e(B . ?\e$,1oZ\e(B)
+        (?\e,2F\e(B . ?\e$,1o2\e(B)
+        (?\e,2G\e(B . ?\e$,1o4\e(B)
+        (?\e,2O\e(B . ?\e$,1or\e(B)
+        (?\e,2Q\e(B . ?\e$,1oh\e(B)
+        (?\e,2U\e(B . ?\e$,1o \e(B)
+        (?\e,2V\e(B . ?\e$,1ov\e(B)
+        (?\e,2W\e(B . ?\e$,1oj\e(B)
+        (?\e,2X\e(B . ?\e$,1ol\e(B)
+        (?\e,2[\e(B . ?\e$,1ox\e(B)
+        (?\e,2\\e(B . ?\e$,1ot\e(B)
+        (?\e,2^\e(B . ?\e$,1o`\e(B)
+        (?\e,2_\e(B . ?\e$,1!o\e(B)
+        (?\e,2`\e(B . ?\e,A@\e(B)
+        (?\e,2a\e(B . ?\e,AA\e(B)
+        (?\e,2b\e(B . ?\e,AB\e(B)
+        (?\e,2c\e(B . ?\e,AC\e(B)
+        (?\e,2d\e(B . ?\e$,1o"\e(B)
+        (?\e,2e\e(B . ?\e$,1 "\e(B)
+        (?\e,2f\e(B . ?\e$,1on\e(B)
+        (?\e,2g\e(B . ?\e$,1o*\e(B)
+        (?\e,2h\e(B . ?\e,AH\e(B)
+        (?\e,2i\e(B . ?\e,AI\e(B)
+        (?\e,2j\e(B . ?\e,AJ\e(B)
+        (?\e,2k\e(B . ?\e$,1o:\e(B)
+        (?\e,2l\e(B . ?\e,AL\e(B)
+        (?\e,2m\e(B . ?\e,AM\e(B)
+        (?\e,2n\e(B . ?\e$,1 H\e(B)
+        (?\e,2o\e(B . ?\e$,1oH\e(B)
+        (?\e,2p\e(B . ?\e$,1 0\e(B)
+        (?\e,2q\e(B . ?\e$,1op\e(B)
+        (?\e,2r\e(B . ?\e,AR\e(B)
+        (?\e,2s\e(B . ?\e,AS\e(B)
+        (?\e,2t\e(B . ?\e,AT\e(B)
+        (?\e,2u\e(B . ?\e,AU\e(B)
+        (?\e,2v\e(B . ?\e$,1oN\e(B)
+        (?\e,2w\e(B . ?\e$,1oL\e(B)
+        (?\e,2x\e(B . ?\e$,1od\e(B)
+        (?\e,2y\e(B . ?\e,AY\e(B)
+        (?\e,2z\e(B . ?\e,AZ\e(B)
+        (?\e,2{\e(B . ?\e$,1!(\e(B)
+        (?\e,2|\e(B . ?\e$,1of\e(B)
+        (?\e,2}\e(B . ?\e,A]\e(B)
+        (?\e,2~\e(B . ?\e$,1ob\e(B)))
+
+      (thai-tis620
+       '((?\e,T!\e(B . ?\e$,1Ba\e(B)
+        (?\e,T"\e(B . ?\e$,1Bb\e(B)
+        (?\e,T#\e(B . ?\e$,1Bc\e(B)
+        (?\e,T$\e(B . ?\e$,1Bd\e(B)
+        (?\e,T%\e(B . ?\e$,1Be\e(B)
+        (?\e,T&\e(B . ?\e$,1Bf\e(B)
+        (?\e,T'\e(B . ?\e$,1Bg\e(B)
+        (?\e,T(\e(B . ?\e$,1Bh\e(B)
+        (?\e,T)\e(B . ?\e$,1Bi\e(B)
+        (?\e,T*\e(B . ?\e$,1Bj\e(B)
+        (?\e,T+\e(B . ?\e$,1Bk\e(B)
+        (?\e,T,\e(B . ?\e$,1Bl\e(B)
+        (?\e,T-\e(B . ?\e$,1Bm\e(B)
+        (?\e,T.\e(B . ?\e$,1Bn\e(B)
+        (?\e,T/\e(B . ?\e$,1Bo\e(B)
+        (?\e,T0\e(B . ?\e$,1Bp\e(B)
+        (?\e,T1\e(B . ?\e$,1Bq\e(B)
+        (?\e,T2\e(B . ?\e$,1Br\e(B)
+        (?\e,T3\e(B . ?\e$,1Bs\e(B)
+        (?\e,T4\e(B . ?\e$,1Bt\e(B)
+        (?\e,T5\e(B . ?\e$,1Bu\e(B)
+        (?\e,T6\e(B . ?\e$,1Bv\e(B)
+        (?\e,T7\e(B . ?\e$,1Bw\e(B)
+        (?\e,T8\e(B . ?\e$,1Bx\e(B)
+        (?\e,T9\e(B . ?\e$,1By\e(B)
+        (?\e,T:\e(B . ?\e$,1Bz\e(B)
+        (?\e,T;\e(B . ?\e$,1B{\e(B)
+        (?\e,T<\e(B . ?\e$,1B|\e(B)
+        (?\e,T=\e(B . ?\e$,1B}\e(B)
+        (?\e,T>\e(B . ?\e$,1B~\e(B)
+        (?\e,T?\e(B . ?\e$,1B\7f\e(B)
+        (?\e,T@\e(B . ?\e$,1C \e(B)
+        (?\e,TA\e(B . ?\e$,1C!\e(B)
+        (?\e,TB\e(B . ?\e$,1C"\e(B)
+        (?\e,TC\e(B . ?\e$,1C#\e(B)
+        (?\e,TD\e(B . ?\e$,1C$\e(B)
+        (?\e,TE\e(B . ?\e$,1C%\e(B)
+        (?\e,TF\e(B . ?\e$,1C&\e(B)
+        (?\e,TG\e(B . ?\e$,1C'\e(B)
+        (?\e,TH\e(B . ?\e$,1C(\e(B)
+        (?\e,TI\e(B . ?\e$,1C)\e(B)
+        (?\e,TJ\e(B . ?\e$,1C*\e(B)
+        (?\e,TK\e(B . ?\e$,1C+\e(B)
+        (?\e,TL\e(B . ?\e$,1C,\e(B)
+        (?\e,TM\e(B . ?\e$,1C-\e(B)
+        (?\e,TN\e(B . ?\e$,1C.\e(B)
+        (?\e,TO\e(B . ?\e$,1C/\e(B)
+        (?\e,TP\e(B . ?\e$,1C0\e(B)
+        (?\e,TQ\e(B . ?\e$,1C1\e(B)
+        (?\e,TR\e(B . ?\e$,1C2\e(B)
+        (?\e,TS\e(B . ?\e$,1C3\e(B)
+        (?\e,TT\e(B . ?\e$,1C4\e(B)
+        (?\e,TU\e(B . ?\e$,1C5\e(B)
+        (?\e,TV\e(B . ?\e$,1C6\e(B)
+        (?\e,TW\e(B . ?\e$,1C7\e(B)
+        (?\e,TX\e(B . ?\e$,1C8\e(B)
+        (?\e,TY\e(B . ?\e$,1C9\e(B)
+        (?\e,TZ\e(B . ?\e$,1C:\e(B)
+        (?\e,T_\e(B . ?\e$,1C?\e(B)
+        (?\e,T`\e(B . ?\e$,1C@\e(B)
+        (?\e,Ta\e(B . ?\e$,1CA\e(B)
+        (?\e,Tb\e(B . ?\e$,1CB\e(B)
+        (?\e,Tc\e(B . ?\e$,1CC\e(B)
+        (?\e,Td\e(B . ?\e$,1CD\e(B)
+        (?\e,Te\e(B . ?\e$,1CE\e(B)
+        (?\e,Tf\e(B . ?\e$,1CF\e(B)
+        (?\e,Tg\e(B . ?\e$,1CG\e(B)
+        (?\e,Th\e(B . ?\e$,1CH\e(B)
+        (?\e,Ti\e(B . ?\e$,1CI\e(B)
+        (?\e,Tj\e(B . ?\e$,1CJ\e(B)
+        (?\e,Tk\e(B . ?\e$,1CK\e(B)
+        (?\e,Tl\e(B . ?\e$,1CL\e(B)
+        (?\e,Tm\e(B . ?\e$,1CM\e(B)
+        (?\e,Tn\e(B . ?\e$,1CN\e(B)
+        (?\e,To\e(B . ?\e$,1CO\e(B)
+        (?\e,Tp\e(B . ?\e$,1CP\e(B)
+        (?\e,Tq\e(B . ?\e$,1CQ\e(B)
+        (?\e,Tr\e(B . ?\e$,1CR\e(B)
+        (?\e,Ts\e(B . ?\e$,1CS\e(B)
+        (?\e,Tt\e(B . ?\e$,1CT\e(B)
+        (?\e,Tu\e(B . ?\e$,1CU\e(B)
+        (?\e,Tv\e(B . ?\e$,1CV\e(B)
+        (?\e,Tw\e(B . ?\e$,1CW\e(B)
+        (?\e,Tx\e(B . ?\e$,1CX\e(B)
+        (?\e,Ty\e(B . ?\e$,1CY\e(B)
+        (?\e,Tz\e(B . ?\e$,1CZ\e(B)
+        (?\e,T{\e(B . ?\e$,1C[\e(B)))
+
+      (tibetan-iso-8bit
+       '((?\e$(7!0\e(B . ?\e$,1E@\e(B)
+        (?\e$(7!1\e(B . ?\e$,1EA\e(B)
+        (?\e$(7!2\e(B . ?\e$,1EB\e(B)
+        (?\e$(7!3\e(B . ?\e$,1EC\e(B)
+        (?\e$(7!4\e(B . ?\e$,1ED\e(B)
+        (?\e$(7!5\e(B . ?\e$,1EE\e(B)
+        (?\e$(7!6\e(B . ?\e$,1EF\e(B)
+        (?\e$(7!7\e(B . ?\e$,1EG\e(B)
+        (?\e$(7!8\e(B . ?\e$,1EH\e(B)
+        (?\e$(7!9\e(B . ?\e$,1EI\e(B)
+        (?\e$(7!:\e(B . ?\e$,1EJ\e(B)
+        (?\e$(7!;\e(B . ?\e$,1EK\e(B)
+        (?\e$(7!<\e(B . ?\e$,1EL\e(B)
+        (?\e$(7!=\e(B . ?\e$,1EM\e(B)
+        (?\e$(7!>\e(B . ?\e$,1EN\e(B)
+        (?\e$(7!?\e(B . ?\e$,1EO\e(B)
+        (?\e$(7!@\e(B . ?\e$,1EP\e(B)
+        (?\e$(7!A\e(B . ?\e$,1EQ\e(B)
+        (?\e$(7!B\e(B . ?\e$,1ER\e(B)
+        (?\e$(7!C\e(B . ?\e$,1ES\e(B)
+        (?\e$(7!D\e(B . ?\e$,1ET\e(B)
+        (?\e$(7!E\e(B . ?\e$,1EU\e(B)
+        (?\e$(7!F\e(B . ?\e$,1EV\e(B)
+        (?\e$(7!G\e(B . ?\e$,1EW\e(B)
+        (?\e$(7!H\e(B . ?\e$,1EX\e(B)
+        (?\e$(7!I\e(B . ?\e$,1EY\e(B)
+        (?\e$(7!J\e(B . ?\e$,1EZ\e(B)
+        (?\e$(7!K\e(B . ?\e$,1E[\e(B)
+        (?\e$(7!L\e(B . ?\e$,1E\\e(B)
+        (?\e$(7!M\e(B . ?\e$,1E]\e(B)
+        (?\e$(7!N\e(B . ?\e$,1E^\e(B)
+        (?\e$(7!O\e(B . ?\e$,1E_\e(B)
+        (?\e$(7!P\e(B . ?\e$,1E`\e(B)
+        (?\e$(7!Q\e(B . ?\e$,1Ea\e(B)
+        (?\e$(7!R\e(B . ?\e$,1Eb\e(B)
+        (?\e$(7!S\e(B . ?\e$,1Ec\e(B)
+        (?\e$(7!T\e(B . ?\e$,1Ed\e(B)
+        (?\e$(7!U\e(B . ?\e$,1Ee\e(B)
+        (?\e$(7!V\e(B . ?\e$,1Ef\e(B)
+        (?\e$(7!W\e(B . ?\e$,1Eg\e(B)
+        (?\e$(7!X\e(B . ?\e$,1Eh\e(B)
+        (?\e$(7!Y\e(B . ?\e$,1Ei\e(B)
+        (?\e$(7!Z\e(B . ?\e$,1Ej\e(B)
+        (?\e$(7![\e(B . ?\e$,1Ek\e(B)
+        (?\e$(7!\\e(B . ?\e$,1El\e(B)
+        (?\e$(7!]\e(B . ?\e$,1Em\e(B)
+        (?\e$(7!^\e(B . ?\e$,1En\e(B)
+        (?\e$(7!_\e(B . ?\e$,1Eo\e(B)
+        (?\e$(7!`\e(B . ?\e$,1Ep\e(B)
+        (?\e$(7!a\e(B . ?\e$,1Eq\e(B)
+        (?\e$(7!b\e(B . ?\e$,1Er\e(B)
+        (?\e$(7!c\e(B . ?\e$,1Es\e(B)
+        (?\e$(7!d\e(B . ?\e$,1Et\e(B)
+        (?\e$(7!e\e(B . ?\e$,1Eu\e(B)
+        (?\e$(7!f\e(B . ?\e$,1Ev\e(B)
+        (?\e$(7!g\e(B . ?\e$,1Ew\e(B)
+        (?\e$(7!h\e(B . ?\e$,1Ex\e(B)
+        (?\e$(7!i\e(B . ?\e$,1Ey\e(B)
+        (?\e$(7!j\e(B . ?\e$,1Ez\e(B)
+        (?\e$(7!k\e(B . ?\e$,1E{\e(B)
+        (?\e$(7!l\e(B . ?\e$,1E|\e(B)
+        (?\e$(7!m\e(B . ?\e$,1E}\e(B)
+        (?\e$(7!n\e(B . ?\e$,1E~\e(B)
+        (?\e$(7!o\e(B . ?\e$,1E\7f\e(B)
+        (?\e$(7"!\e(B . ?\e$,1F \e(B)
+        (?\e$(7""\e(B . ?\e$,1F!\e(B)
+        (?\e$(7"#\e(B . ?\e$,1F"\e(B)
+        (?\e$(7"$\e(B . ?\e$,1F#\e(B)
+        (?\e$(7"%\e(B . ?\e$,1F$\e(B)
+        (?\e$(7"&\e(B . ?\e$,1F%\e(B)
+        (?\e$(7"'\e(B . ?\e$,1F&\e(B)
+        (?\e$(7"(\e(B . ?\e$,1F'\e(B)
+        (?\e$(7"*\e(B . ?\e$,1F)\e(B)
+        (?\e$(7"+\e(B . ?\e$,1F*\e(B)
+        (?\e$(7",\e(B . ?\e$,1F+\e(B)
+        (?\e$(7"-\e(B . ?\e$,1F,\e(B)
+        (?\e$(7".\e(B . ?\e$,1F-\e(B)
+        (?\e$(7"/\e(B . ?\e$,1F.\e(B)
+        (?\e$(7"0\e(B . ?\e$,1F/\e(B)
+        (?\e$(7"1\e(B . ?\e$,1F0\e(B)
+        (?\e$(7"2\e(B . ?\e$,1F1\e(B)
+        (?\e$(7"3\e(B . ?\e$,1F2\e(B)
+        (?\e$(7"4\e(B . ?\e$,1F3\e(B)
+        (?\e$(7"5\e(B . ?\e$,1F4\e(B)
+        (?\e$(7"6\e(B . ?\e$,1F5\e(B)
+        (?\e$(7"7\e(B . ?\e$,1F6\e(B)
+        (?\e$(7"8\e(B . ?\e$,1F7\e(B)
+        (?\e$(7"9\e(B . ?\e$,1F8\e(B)
+        (?\e$(7":\e(B . ?\e$,1F9\e(B)
+        (?\e$(7";\e(B . ?\e$,1F:\e(B)
+        (?\e$(7"<\e(B . ?\e$,1F;\e(B)
+        (?\e$(7"=\e(B . ?\e$,1F<\e(B)
+        (?\e$(7">\e(B . ?\e$,1F=\e(B)
+        (?\e$(7"?\e(B . ?\e$,1F>\e(B)
+        (?\e$(7"@\e(B . ?\e$,1F?\e(B)
+        (?\e$(7"A\e(B . ?\e$,1F@\e(B)
+        (?\e$(7"B\e(B . ?\e$,1FA\e(B)
+        (?\e$(7"C\e(B . ?\e$,1FB\e(B)
+        (?\e$(7"D\e(B . ?\e$,1FC\e(B)
+        (?\e$(7"E\e(B . ?\e$,1FD\e(B)
+        (?\e$(7"F\e(B . ?\e$,1FE\e(B)
+        (?\e$(7"G\e(B . ?\e$,1FF\e(B)
+        (?\e$(7"H\e(B . ?\e$,1FG\e(B)
+        (?\e$(7"I\e(B . ?\e$,1FH\e(B)
+        (?\e$(7"J\e(B . ?\e$,1FI\e(B)
+        (?\e$(7"K\e(B . ?\e$,1FJ\e(B)
+        (?\e$(7"R\e(B . ?\e$,1FQ\e(B)
+        (?\e$(7"S\e(B . ?\e$,1FR\e(B)
+        (?\e$(7"T\e(B . ?\e$,1FS\e(B)
+        (?\e$(7"U\e(B . ?\e$,1FT\e(B)
+        (?\e$(7"V\e(B . ?\e$,1FU\e(B)
+        (?\e$(7"W\e(B . ?\e$,1FV\e(B)
+        (?\e$(7"X\e(B . ?\e$,1FW\e(B)
+        (?\e$(7"Y\e(B . ?\e$,1FX\e(B)
+        (?\e$(7"Z\e(B . ?\e$,1FY\e(B)
+        (?\e$(7"[\e(B . ?\e$,1FZ\e(B)
+        (?\e$(7"\\e(B . ?\e$,1F[\e(B)
+        (?\e$(7"]\e(B . ?\e$,1F\\e(B)
+        (?\e$(7"^\e(B . ?\e$,1F]\e(B)
+        (?\e$(7"_\e(B . ?\e$,1F^\e(B)
+        (?\e$(7"`\e(B . ?\e$,1F_\e(B)
+        (?\e$(7"a\e(B . ?\e$,1F`\e(B)
+        (?\e$(7"b\e(B . ?\e$,1Fa\e(B)
+        (?\e$(7"c\e(B . ?\e$,1Fb\e(B)
+        (?\e$(7"d\e(B . ?\e$,1Fc\e(B)
+        (?\e$(7"e\e(B . ?\e$,1Fd\e(B)
+        (?\e$(7"f\e(B . ?\e$,1Fe\e(B)
+        (?\e$(7"g\e(B . ?\e$,1Ff\e(B)
+        (?\e$(7"h\e(B . ?\e$,1Fg\e(B)
+        (?\e$(7"i\e(B . ?\e$,1Fh\e(B)
+        (?\e$(7"j\e(B . ?\e$,1Fi\e(B)
+        (?\e$(7"k\e(B . ?\e$,1Fj\e(B)
+        (?\e$(7"l\e(B . ?\e$,1Fk\e(B)
+        (?\e$(7#!\e(B . ?\e$,1Fp\e(B)
+        (?\e$(7#"\e(B . ?\e$,1Fq\e(B)
+        (?\e$(7##\e(B . ?\e$,1Fr\e(B)
+        (?\e$(7#$\e(B . ?\e$,1Fs\e(B)
+        (?\e$(7#%\e(B . ?\e$,1Ft\e(B)
+        (?\e$(7#&\e(B . ?\e$,1Fu\e(B)
+        (?\e$(7#'\e(B . ?\e$,1Fv\e(B)
+        (?\e$(7#(\e(B . ?\e$,1Fw\e(B)
+        (?\e$(7#*\e(B . ?\e$,1Fy\e(B)
+        (?\e$(7#+\e(B . ?\e$,1Fz\e(B)
+        (?\e$(7#,\e(B . ?\e$,1F{\e(B)
+        (?\e$(7#-\e(B . ?\e$,1F|\e(B)
+        (?\e$(7#.\e(B . ?\e$,1F}\e(B)
+        (?\e$(7#/\e(B . ?\e$,1F~\e(B)
+        (?\e$(7#0\e(B . ?\e$,1F\7f\e(B)
+        (?\e$(7#1\e(B . ?\e$,1G \e(B)
+        (?\e$(7#2\e(B . ?\e$,1G!\e(B)
+        (?\e$(7#3\e(B . ?\e$,1G"\e(B)
+        (?\e$(7#4\e(B . ?\e$,1G#\e(B)
+        (?\e$(7#5\e(B . ?\e$,1G$\e(B)
+        (?\e$(7#6\e(B . ?\e$,1G%\e(B)
+        (?\e$(7#7\e(B . ?\e$,1G&\e(B)
+        (?\e$(7#8\e(B . ?\e$,1G'\e(B)
+        (?\e$(7#9\e(B . ?\e$,1G(\e(B)
+        (?\e$(7#:\e(B . ?\e$,1G)\e(B)
+        (?\e$(7#;\e(B . ?\e$,1G*\e(B)
+        (?\e$(7#<\e(B . ?\e$,1G+\e(B)
+        (?\e$(7#=\e(B . ?\e$,1G,\e(B)
+        (?\e$(7#>\e(B . ?\e$,1G-\e(B)
+        (?\e$(7#?\e(B . ?\e$,1G.\e(B)
+        (?\e$(7#@\e(B . ?\e$,1G/\e(B)
+        (?\e$(7#A\e(B . ?\e$,1G0\e(B)
+        (?\e$(7#B\e(B . ?\e$,1G1\e(B)
+        (?\e$(7#C\e(B . ?\e$,1G2\e(B)
+        (?\e$(7#D\e(B . ?\e$,1G3\e(B)
+        (?\e$(7#E\e(B . ?\e$,1G4\e(B)
+        (?\e$(7#F\e(B . ?\e$,1G5\e(B)
+        (?\e$(7#G\e(B . ?\e$,1G6\e(B)
+        (?\e$(7#H\e(B . ?\e$,1G7\e(B)
+        (?\e$(7#I\e(B . ?\e$,1G8\e(B)
+        (?\e$(7#J\e(B . ?\e$,1G9\e(B)
+        (?\e$(7#K\e(B . ?\e$,1G:\e(B)
+        (?\e$(7#L\e(B . ?\e$,1G;\e(B)
+        (?\e$(7#M\e(B . ?\e$,1G<\e(B)
+        (?\e$(7#O\e(B . ?\e$,1G>\e(B)
+        (?\e$(7#P\e(B . ?\e$,1G?\e(B)
+        (?\e$(7#Q\e(B . ?\e$,1G@\e(B)
+        (?\e$(7#R\e(B . ?\e$,1GA\e(B)
+        (?\e$(7#S\e(B . ?\e$,1GB\e(B)
+        (?\e$(7#T\e(B . ?\e$,1GC\e(B)
+        (?\e$(7#U\e(B . ?\e$,1GD\e(B)
+        (?\e$(7#V\e(B . ?\e$,1GE\e(B)
+        (?\e$(7#W\e(B . ?\e$,1GF\e(B)
+        (?\e$(7#X\e(B . ?\e$,1GG\e(B)
+        (?\e$(7#Y\e(B . ?\e$,1GH\e(B)
+        (?\e$(7#Z\e(B . ?\e$,1GI\e(B)
+        (?\e$(7#[\e(B . ?\e$,1GJ\e(B)
+        (?\e$(7#\\e(B . ?\e$,1GK\e(B)
+        (?\e$(7#]\e(B . ?\e$,1GL\e(B)
+        (?\e$(7#`\e(B . ?\e$,1GO\e(B)))
+
+      (ipa
+       '((?\e,0 \e(B . ?i)
+        (?\e,0!\e(B . ?\e$,1#j\e(B)
+        (?\e,0"\e(B . ?e)
+        (?\e,0#\e(B . ?\e$,1#[\e(B)
+        (?\e,0$\e(B . ?\e,Af\e(B)
+        (?\e,0%\e(B . ?a)
+        (?\e,0&\e(B . ?\e$,1#h\e(B)
+        (?\e,0'\e(B . ?\e$,1#Y\e(B)
+        (?\e,0(\e(B . ?\e$,1#P\e(B)
+        (?\e,0)\e(B . ?\e$,1#o\e(B)
+        (?\e,0*\e(B . ?\e$,1#d\e(B)
+        (?\e,0+\e(B . ?\e$,1$,\e(B)
+        (?\e,0,\e(B . ?\e$,1#Q\e(B)
+        (?\e,0-\e(B . ?y)
+        (?\e,0.\e(B . ?\e$,1$/\e(B)
+        (?\e,0/\e(B . ?\e,Ax\e(B)
+        (?\e,00\e(B . ?\e$,1 s\e(B)
+        (?\e,01\e(B . ?\e$,1#v\e(B)
+        (?\e,02\e(B . ?\e$,1$)\e(B)
+        (?\e,03\e(B . ?\e$,1#u\e(B)
+        (?\e,04\e(B . ?u)
+        (?\e,05\e(B . ?\e$,1$*\e(B)
+        (?\e,06\e(B . ?o)
+        (?\e,07\e(B . ?\e$,1#T\e(B)
+        (?\e,08\e(B . ?\e$,1#R\e(B)
+        (?\e,0:\e(B . ?\e$,1#Z\e(B)
+        (?\e,0@\e(B . ?p)
+        (?\e,0A\e(B . ?b)
+        (?\e,0B\e(B . ?t)
+        (?\e,0C\e(B . ?d)
+        (?\e,0D\e(B . ?k)
+        (?\e,0E\e(B . ?g)
+        (?\e,0F\e(B . ?f)
+        (?\e,0G\e(B . ?v)
+        (?\e,0H\e(B . ?\e$,1'8\e(B)
+        (?\e,0I\e(B . ?\e,Ap\e(B)
+        (?\e,0J\e(B . ?s)
+        (?\e,0K\e(B . ?z)
+        (?\e,0L\e(B . ?\e$,1$#\e(B)
+        (?\e,0M\e(B . ?\e$,1$2\e(B)
+        (?\e,0N\e(B . ?\e,Ag\e(B)
+        (?\e,0O\e(B . ?x)
+        (?\e,0P\e(B . ?\e$,1$!\e(B)
+        (?\e,0Q\e(B . ?h)
+        (?\e,0R\e(B . ?m)
+        (?\e,0S\e(B . ?n)
+        (?\e,0T\e(B . ?\e$,1#r\e(B)
+        (?\e,0U\e(B . ?\e$,1 k\e(B)
+        (?\e,0V\e(B . ?r)
+        (?\e,0W\e(B . ?\e$,1$ \e(B)
+        (?\e,0X\e(B . ?\e$,1#y\e(B)
+        (?\e,0Y\e(B . ?j)
+        (?\e,0Z\e(B . ?l)
+        (?\e,0[\e(B . ?\e$,1$.\e(B)
+        (?\e,0\\e(B . ?\e$,1$?\e(B)
+        (?\e,0]\e(B . ?\e$,1#e\e(B)
+        (?\e,0^\e(B . ?w)
+        (?\e,0_\e(B . ?\e$,1$-\e(B)
+        (?\e,0p\e(B . ?\e$,1$h\e(B)
+        (?\e,0q\e(B . ?\e$,1$l\e(B)
+        (?\e,0r\e(B . ?\e$,1$p\e(B)))
+
+      (ethiopic
+       '((?\e$(3!!\e(B . ?\e$,1M@\e(B)
+        (?\e$(3!"\e(B . ?\e$,1MA\e(B)
+        (?\e$(3!#\e(B . ?\e$,1MB\e(B)
+        (?\e$(3!$\e(B . ?\e$,1MC\e(B)
+        (?\e$(3!%\e(B . ?\e$,1MD\e(B)
+        (?\e$(3!&\e(B . ?\e$,1ME\e(B)
+        (?\e$(3!'\e(B . ?\e$,1MF\e(B)
+        (?\e$(3!)\e(B . ?\e$,1MH\e(B)
+        (?\e$(3!*\e(B . ?\e$,1MI\e(B)
+        (?\e$(3!+\e(B . ?\e$,1MJ\e(B)
+        (?\e$(3!,\e(B . ?\e$,1MK\e(B)
+        (?\e$(3!-\e(B . ?\e$,1ML\e(B)
+        (?\e$(3!.\e(B . ?\e$,1MM\e(B)
+        (?\e$(3!/\e(B . ?\e$,1MN\e(B)
+        (?\e$(3!0\e(B . ?\e$,1MO\e(B)
+        (?\e$(3!1\e(B . ?\e$,1MP\e(B)
+        (?\e$(3!2\e(B . ?\e$,1MQ\e(B)
+        (?\e$(3!3\e(B . ?\e$,1MR\e(B)
+        (?\e$(3!4\e(B . ?\e$,1MS\e(B)
+        (?\e$(3!5\e(B . ?\e$,1MT\e(B)
+        (?\e$(3!6\e(B . ?\e$,1MU\e(B)
+        (?\e$(3!7\e(B . ?\e$,1MV\e(B)
+        (?\e$(3!8\e(B . ?\e$,1MW\e(B)
+        (?\e$(3!9\e(B . ?\e$,1MX\e(B)
+        (?\e$(3!:\e(B . ?\e$,1MY\e(B)
+        (?\e$(3!;\e(B . ?\e$,1MZ\e(B)
+        (?\e$(3!<\e(B . ?\e$,1M[\e(B)
+        (?\e$(3!=\e(B . ?\e$,1M\\e(B)
+        (?\e$(3!>\e(B . ?\e$,1M]\e(B)
+        (?\e$(3!?\e(B . ?\e$,1M^\e(B)
+        (?\e$(3!@\e(B . ?\e$,1M_\e(B)
+        (?\e$(3!A\e(B . ?\e$,1M`\e(B)
+        (?\e$(3!B\e(B . ?\e$,1Ma\e(B)
+        (?\e$(3!C\e(B . ?\e$,1Mb\e(B)
+        (?\e$(3!D\e(B . ?\e$,1Mc\e(B)
+        (?\e$(3!E\e(B . ?\e$,1Md\e(B)
+        (?\e$(3!F\e(B . ?\e$,1Me\e(B)
+        (?\e$(3!G\e(B . ?\e$,1Mf\e(B)
+        (?\e$(3!H\e(B . ?\e$,1Mg\e(B)
+        (?\e$(3!I\e(B . ?\e$,1Mh\e(B)
+        (?\e$(3!J\e(B . ?\e$,1Mi\e(B)
+        (?\e$(3!K\e(B . ?\e$,1Mj\e(B)
+        (?\e$(3!L\e(B . ?\e$,1Mk\e(B)
+        (?\e$(3!M\e(B . ?\e$,1Ml\e(B)
+        (?\e$(3!N\e(B . ?\e$,1Mm\e(B)
+        (?\e$(3!O\e(B . ?\e$,1Mn\e(B)
+        (?\e$(3!P\e(B . ?\e$,1Mo\e(B)
+        (?\e$(3!Q\e(B . ?\e$,1Mp\e(B)
+        (?\e$(3!R\e(B . ?\e$,1Mq\e(B)
+        (?\e$(3!S\e(B . ?\e$,1Mr\e(B)
+        (?\e$(3!T\e(B . ?\e$,1Ms\e(B)
+        (?\e$(3!U\e(B . ?\e$,1Mt\e(B)
+        (?\e$(3!V\e(B . ?\e$,1Mu\e(B)
+        (?\e$(3!W\e(B . ?\e$,1Mv\e(B)
+        (?\e$(3!X\e(B . ?\e$,1Mw\e(B)
+        (?\e$(3!Y\e(B . ?\e$,1Mx\e(B)
+        (?\e$(3!Z\e(B . ?\e$,1My\e(B)
+        (?\e$(3![\e(B . ?\e$,1Mz\e(B)
+        (?\e$(3!\\e(B . ?\e$,1M{\e(B)
+        (?\e$(3!]\e(B . ?\e$,1M|\e(B)
+        (?\e$(3!^\e(B . ?\e$,1M}\e(B)
+        (?\e$(3!_\e(B . ?\e$,1M~\e(B)
+        (?\e$(3!`\e(B . ?\e$,1M\7f\e(B)
+        (?\e$(3!a\e(B . ?\e$,1N \e(B)
+        (?\e$(3!b\e(B . ?\e$,1N!\e(B)
+        (?\e$(3!c\e(B . ?\e$,1N"\e(B)
+        (?\e$(3!d\e(B . ?\e$,1N#\e(B)
+        (?\e$(3!e\e(B . ?\e$,1N$\e(B)
+        (?\e$(3!f\e(B . ?\e$,1N%\e(B)
+        (?\e$(3!g\e(B . ?\e$,1N&\e(B)
+        (?\e$(3!i\e(B . ?\e$,1N(\e(B)
+        (?\e$(3!k\e(B . ?\e$,1N*\e(B)
+        (?\e$(3!l\e(B . ?\e$,1N+\e(B)
+        (?\e$(3!m\e(B . ?\e$,1N,\e(B)
+        (?\e$(3!n\e(B . ?\e$,1N-\e(B)
+        (?\e$(3!q\e(B . ?\e$,1N0\e(B)
+        (?\e$(3!r\e(B . ?\e$,1N1\e(B)
+        (?\e$(3!s\e(B . ?\e$,1N2\e(B)
+        (?\e$(3!t\e(B . ?\e$,1N3\e(B)
+        (?\e$(3!u\e(B . ?\e$,1N4\e(B)
+        (?\e$(3!v\e(B . ?\e$,1N5\e(B)
+        (?\e$(3!w\e(B . ?\e$,1N6\e(B)
+        (?\e$(3!y\e(B . ?\e$,1N8\e(B)
+        (?\e$(3!{\e(B . ?\e$,1N:\e(B)
+        (?\e$(3!|\e(B . ?\e$,1N;\e(B)
+        (?\e$(3!}\e(B . ?\e$,1N<\e(B)
+        (?\e$(3!~\e(B . ?\e$,1N=\e(B)
+        (?\e$(3"#\e(B . ?\e$,1N@\e(B)
+        (?\e$(3"$\e(B . ?\e$,1NA\e(B)
+        (?\e$(3"%\e(B . ?\e$,1NB\e(B)
+        (?\e$(3"&\e(B . ?\e$,1NC\e(B)
+        (?\e$(3"'\e(B . ?\e$,1ND\e(B)
+        (?\e$(3"(\e(B . ?\e$,1NE\e(B)
+        (?\e$(3")\e(B . ?\e$,1NF\e(B)
+        (?\e$(3"*\e(B . ?\e$,1NG\e(B)
+        (?\e$(3"+\e(B . ?\e$,1NH\e(B)
+        (?\e$(3",\e(B . ?\e$,1NI\e(B)
+        (?\e$(3"-\e(B . ?\e$,1NJ\e(B)
+        (?\e$(3".\e(B . ?\e$,1NK\e(B)
+        (?\e$(3"/\e(B . ?\e$,1NL\e(B)
+        (?\e$(3"0\e(B . ?\e$,1NM\e(B)
+        (?\e$(3"1\e(B . ?\e$,1NN\e(B)
+        (?\e$(3"2\e(B . ?\e$,1NO\e(B)
+        (?\e$(3"3\e(B . ?\e$,1NP\e(B)
+        (?\e$(3"4\e(B . ?\e$,1NQ\e(B)
+        (?\e$(3"5\e(B . ?\e$,1NR\e(B)
+        (?\e$(3"6\e(B . ?\e$,1NS\e(B)
+        (?\e$(3"7\e(B . ?\e$,1NT\e(B)
+        (?\e$(3"8\e(B . ?\e$,1NU\e(B)
+        (?\e$(3"9\e(B . ?\e$,1NV\e(B)
+        (?\e$(3":\e(B . ?\e$,1NW\e(B)
+        (?\e$(3";\e(B . ?\e$,1NX\e(B)
+        (?\e$(3"<\e(B . ?\e$,1NY\e(B)
+        (?\e$(3"=\e(B . ?\e$,1NZ\e(B)
+        (?\e$(3">\e(B . ?\e$,1N[\e(B)
+        (?\e$(3"?\e(B . ?\e$,1N\\e(B)
+        (?\e$(3"@\e(B . ?\e$,1N]\e(B)
+        (?\e$(3"A\e(B . ?\e$,1N^\e(B)
+        (?\e$(3"B\e(B . ?\e$,1N_\e(B)
+        (?\e$(3"C\e(B . ?\e$,1N`\e(B)
+        (?\e$(3"D\e(B . ?\e$,1Na\e(B)
+        (?\e$(3"E\e(B . ?\e$,1Nb\e(B)
+        (?\e$(3"F\e(B . ?\e$,1Nc\e(B)
+        (?\e$(3"G\e(B . ?\e$,1Nd\e(B)
+        (?\e$(3"H\e(B . ?\e$,1Ne\e(B)
+        (?\e$(3"I\e(B . ?\e$,1Nf\e(B)
+        (?\e$(3"K\e(B . ?\e$,1Nh\e(B)
+        (?\e$(3"M\e(B . ?\e$,1Nj\e(B)
+        (?\e$(3"N\e(B . ?\e$,1Nk\e(B)
+        (?\e$(3"O\e(B . ?\e$,1Nl\e(B)
+        (?\e$(3"P\e(B . ?\e$,1Nm\e(B)
+        (?\e$(3"S\e(B . ?\e$,1Np\e(B)
+        (?\e$(3"T\e(B . ?\e$,1Nq\e(B)
+        (?\e$(3"U\e(B . ?\e$,1Nr\e(B)
+        (?\e$(3"V\e(B . ?\e$,1Ns\e(B)
+        (?\e$(3"W\e(B . ?\e$,1Nt\e(B)
+        (?\e$(3"X\e(B . ?\e$,1Nu\e(B)
+        (?\e$(3"Y\e(B . ?\e$,1Nv\e(B)
+        (?\e$(3"Z\e(B . ?\e$,1Nw\e(B)
+        (?\e$(3"[\e(B . ?\e$,1Nx\e(B)
+        (?\e$(3"\\e(B . ?\e$,1Ny\e(B)
+        (?\e$(3"]\e(B . ?\e$,1Nz\e(B)
+        (?\e$(3"^\e(B . ?\e$,1N{\e(B)
+        (?\e$(3"_\e(B . ?\e$,1N|\e(B)
+        (?\e$(3"`\e(B . ?\e$,1N}\e(B)
+        (?\e$(3"a\e(B . ?\e$,1N~\e(B)
+        (?\e$(3"b\e(B . ?\e$,1N\7f\e(B)
+        (?\e$(3"c\e(B . ?\e$,1O \e(B)
+        (?\e$(3"d\e(B . ?\e$,1O!\e(B)
+        (?\e$(3"e\e(B . ?\e$,1O"\e(B)
+        (?\e$(3"f\e(B . ?\e$,1O#\e(B)
+        (?\e$(3"g\e(B . ?\e$,1O$\e(B)
+        (?\e$(3"h\e(B . ?\e$,1O%\e(B)
+        (?\e$(3"i\e(B . ?\e$,1O&\e(B)
+        (?\e$(3"j\e(B . ?\e$,1O'\e(B)
+        (?\e$(3"k\e(B . ?\e$,1O(\e(B)
+        (?\e$(3"l\e(B . ?\e$,1O)\e(B)
+        (?\e$(3"m\e(B . ?\e$,1O*\e(B)
+        (?\e$(3"n\e(B . ?\e$,1O+\e(B)
+        (?\e$(3"o\e(B . ?\e$,1O,\e(B)
+        (?\e$(3"p\e(B . ?\e$,1O-\e(B)
+        (?\e$(3"q\e(B . ?\e$,1O.\e(B)
+        (?\e$(3"s\e(B . ?\e$,1O0\e(B)
+        (?\e$(3"u\e(B . ?\e$,1O2\e(B)
+        (?\e$(3"v\e(B . ?\e$,1O3\e(B)
+        (?\e$(3"w\e(B . ?\e$,1O4\e(B)
+        (?\e$(3"x\e(B . ?\e$,1O5\e(B)
+        (?\e$(3"{\e(B . ?\e$,1O8\e(B)
+        (?\e$(3"|\e(B . ?\e$,1O9\e(B)
+        (?\e$(3"}\e(B . ?\e$,1O:\e(B)
+        (?\e$(3"~\e(B . ?\e$,1O;\e(B)
+        (?\e$(3#!\e(B . ?\e$,1O<\e(B)
+        (?\e$(3#"\e(B . ?\e$,1O=\e(B)
+        (?\e$(3##\e(B . ?\e$,1O>\e(B)
+        (?\e$(3#%\e(B . ?\e$,1O@\e(B)
+        (?\e$(3#'\e(B . ?\e$,1OB\e(B)
+        (?\e$(3#(\e(B . ?\e$,1OC\e(B)
+        (?\e$(3#)\e(B . ?\e$,1OD\e(B)
+        (?\e$(3#*\e(B . ?\e$,1OE\e(B)
+        (?\e$(3#-\e(B . ?\e$,1OH\e(B)
+        (?\e$(3#.\e(B . ?\e$,1OI\e(B)
+        (?\e$(3#/\e(B . ?\e$,1OJ\e(B)
+        (?\e$(3#0\e(B . ?\e$,1OK\e(B)
+        (?\e$(3#1\e(B . ?\e$,1OL\e(B)
+        (?\e$(3#2\e(B . ?\e$,1OM\e(B)
+        (?\e$(3#3\e(B . ?\e$,1ON\e(B)
+        (?\e$(3#5\e(B . ?\e$,1OP\e(B)
+        (?\e$(3#6\e(B . ?\e$,1OQ\e(B)
+        (?\e$(3#7\e(B . ?\e$,1OR\e(B)
+        (?\e$(3#8\e(B . ?\e$,1OS\e(B)
+        (?\e$(3#9\e(B . ?\e$,1OT\e(B)
+        (?\e$(3#:\e(B . ?\e$,1OU\e(B)
+        (?\e$(3#;\e(B . ?\e$,1OV\e(B)
+        (?\e$(3#=\e(B . ?\e$,1OX\e(B)
+        (?\e$(3#>\e(B . ?\e$,1OY\e(B)
+        (?\e$(3#?\e(B . ?\e$,1OZ\e(B)
+        (?\e$(3#@\e(B . ?\e$,1O[\e(B)
+        (?\e$(3#A\e(B . ?\e$,1O\\e(B)
+        (?\e$(3#B\e(B . ?\e$,1O]\e(B)
+        (?\e$(3#C\e(B . ?\e$,1O^\e(B)
+        (?\e$(3#D\e(B . ?\e$,1O_\e(B)
+        (?\e$(3#E\e(B . ?\e$,1O`\e(B)
+        (?\e$(3#F\e(B . ?\e$,1Oa\e(B)
+        (?\e$(3#G\e(B . ?\e$,1Ob\e(B)
+        (?\e$(3#H\e(B . ?\e$,1Oc\e(B)
+        (?\e$(3#I\e(B . ?\e$,1Od\e(B)
+        (?\e$(3#J\e(B . ?\e$,1Oe\e(B)
+        (?\e$(3#K\e(B . ?\e$,1Of\e(B)
+        (?\e$(3#L\e(B . ?\e$,1Og\e(B)
+        (?\e$(3#M\e(B . ?\e$,1Oh\e(B)
+        (?\e$(3#N\e(B . ?\e$,1Oi\e(B)
+        (?\e$(3#O\e(B . ?\e$,1Oj\e(B)
+        (?\e$(3#P\e(B . ?\e$,1Ok\e(B)
+        (?\e$(3#Q\e(B . ?\e$,1Ol\e(B)
+        (?\e$(3#R\e(B . ?\e$,1Om\e(B)
+        (?\e$(3#S\e(B . ?\e$,1On\e(B)
+        (?\e$(3#U\e(B . ?\e$,1Op\e(B)
+        (?\e$(3#V\e(B . ?\e$,1Oq\e(B)
+        (?\e$(3#W\e(B . ?\e$,1Or\e(B)
+        (?\e$(3#X\e(B . ?\e$,1Os\e(B)
+        (?\e$(3#Y\e(B . ?\e$,1Ot\e(B)
+        (?\e$(3#Z\e(B . ?\e$,1Ou\e(B)
+        (?\e$(3#[\e(B . ?\e$,1Ov\e(B)
+        (?\e$(3#\\e(B . ?\e$,1Ow\e(B)
+        (?\e$(3#]\e(B . ?\e$,1Ox\e(B)
+        (?\e$(3#^\e(B . ?\e$,1Oy\e(B)
+        (?\e$(3#_\e(B . ?\e$,1Oz\e(B)
+        (?\e$(3#`\e(B . ?\e$,1O{\e(B)
+        (?\e$(3#a\e(B . ?\e$,1O|\e(B)
+        (?\e$(3#b\e(B . ?\e$,1O}\e(B)
+        (?\e$(3#c\e(B . ?\e$,1O~\e(B)
+        (?\e$(3#d\e(B . ?\e$,1O\7f\e(B)
+        (?\e$(3#e\e(B . ?\e$,1P \e(B)
+        (?\e$(3#f\e(B . ?\e$,1P!\e(B)
+        (?\e$(3#g\e(B . ?\e$,1P"\e(B)
+        (?\e$(3#h\e(B . ?\e$,1P#\e(B)
+        (?\e$(3#i\e(B . ?\e$,1P$\e(B)
+        (?\e$(3#j\e(B . ?\e$,1P%\e(B)
+        (?\e$(3#k\e(B . ?\e$,1P&\e(B)
+        (?\e$(3#l\e(B . ?\e$,1P'\e(B)
+        (?\e$(3#m\e(B . ?\e$,1P(\e(B)
+        (?\e$(3#n\e(B . ?\e$,1P)\e(B)
+        (?\e$(3#o\e(B . ?\e$,1P*\e(B)
+        (?\e$(3#p\e(B . ?\e$,1P+\e(B)
+        (?\e$(3#q\e(B . ?\e$,1P,\e(B)
+        (?\e$(3#r\e(B . ?\e$,1P-\e(B)
+        (?\e$(3#s\e(B . ?\e$,1P.\e(B)
+        (?\e$(3#u\e(B . ?\e$,1P0\e(B)
+        (?\e$(3#w\e(B . ?\e$,1P2\e(B)
+        (?\e$(3#x\e(B . ?\e$,1P3\e(B)
+        (?\e$(3#y\e(B . ?\e$,1P4\e(B)
+        (?\e$(3#z\e(B . ?\e$,1P5\e(B)
+        (?\e$(3#}\e(B . ?\e$,1P8\e(B)
+        (?\e$(3#~\e(B . ?\e$,1P9\e(B)
+        (?\e$(3$!\e(B . ?\e$,1P:\e(B)
+        (?\e$(3$"\e(B . ?\e$,1P;\e(B)
+        (?\e$(3$#\e(B . ?\e$,1P<\e(B)
+        (?\e$(3$$\e(B . ?\e$,1P=\e(B)
+        (?\e$(3$%\e(B . ?\e$,1P>\e(B)
+        (?\e$(3$'\e(B . ?\e$,1P@\e(B)
+        (?\e$(3$(\e(B . ?\e$,1PA\e(B)
+        (?\e$(3$)\e(B . ?\e$,1PB\e(B)
+        (?\e$(3$*\e(B . ?\e$,1PC\e(B)
+        (?\e$(3$+\e(B . ?\e$,1PD\e(B)
+        (?\e$(3$,\e(B . ?\e$,1PE\e(B)
+        (?\e$(3$-\e(B . ?\e$,1PF\e(B)
+        (?\e$(3$.\e(B . ?\e$,1PG\e(B)
+        (?\e$(3$/\e(B . ?\e$,1PH\e(B)
+        (?\e$(3$0\e(B . ?\e$,1PI\e(B)
+        (?\e$(3$1\e(B . ?\e$,1PJ\e(B)
+        (?\e$(3$2\e(B . ?\e$,1PK\e(B)
+        (?\e$(3$3\e(B . ?\e$,1PL\e(B)
+        (?\e$(3$4\e(B . ?\e$,1PM\e(B)
+        (?\e$(3$5\e(B . ?\e$,1PN\e(B)
+        (?\e$(3$6\e(B . ?\e$,1PO\e(B)
+        (?\e$(3$7\e(B . ?\e$,1PP\e(B)
+        (?\e$(3$8\e(B . ?\e$,1PQ\e(B)
+        (?\e$(3$9\e(B . ?\e$,1PR\e(B)
+        (?\e$(3$:\e(B . ?\e$,1PS\e(B)
+        (?\e$(3$;\e(B . ?\e$,1PT\e(B)
+        (?\e$(3$<\e(B . ?\e$,1PU\e(B)
+        (?\e$(3$=\e(B . ?\e$,1PV\e(B)
+        (?\e$(3$>\e(B . ?\e$,1PW\e(B)
+        (?\e$(3$?\e(B . ?\e$,1PX\e(B)
+        (?\e$(3$@\e(B . ?\e$,1PY\e(B)
+        (?\e$(3$A\e(B . ?\e$,1PZ\e(B)
+        (?\e$(3$B\e(B . ?\e$,1P[\e(B)
+        (?\e$(3$C\e(B . ?\e$,1P\\e(B)
+        (?\e$(3$D\e(B . ?\e$,1P]\e(B)
+        (?\e$(3$E\e(B . ?\e$,1P^\e(B)
+        (?\e$(3$F\e(B . ?\e$,1P_\e(B)
+        (?\e$(3$G\e(B . ?\e$,1P`\e(B)
+        (?\e$(3$H\e(B . ?\e$,1Pa\e(B)
+        (?\e$(3$I\e(B . ?\e$,1Pb\e(B)
+        (?\e$(3$J\e(B . ?\e$,1Pc\e(B)
+        (?\e$(3$K\e(B . ?\e$,1Pd\e(B)
+        (?\e$(3$L\e(B . ?\e$,1Pe\e(B)
+        (?\e$(3$M\e(B . ?\e$,1Pf\e(B)
+        (?\e$(3$O\e(B . ?\e$,1Ph\e(B)
+        (?\e$(3$P\e(B . ?\e$,1Pi\e(B)
+        (?\e$(3$Q\e(B . ?\e$,1Pj\e(B)
+        (?\e$(3$R\e(B . ?\e$,1Pk\e(B)
+        (?\e$(3$S\e(B . ?\e$,1Pl\e(B)
+        (?\e$(3$T\e(B . ?\e$,1Pm\e(B)
+        (?\e$(3$U\e(B . ?\e$,1Pn\e(B)
+        (?\e$(3$V\e(B . ?\e$,1Po\e(B)
+        (?\e$(3$W\e(B . ?\e$,1Pp\e(B)
+        (?\e$(3$X\e(B . ?\e$,1Pq\e(B)
+        (?\e$(3$Y\e(B . ?\e$,1Pr\e(B)
+        (?\e$(3$Z\e(B . ?\e$,1Ps\e(B)
+        (?\e$(3$[\e(B . ?\e$,1Pt\e(B)
+        (?\e$(3$\\e(B . ?\e$,1Pu\e(B)
+        (?\e$(3$]\e(B . ?\e$,1Pv\e(B)
+        (?\e$(3$^\e(B . ?\e$,1Pw\e(B)
+        (?\e$(3$_\e(B . ?\e$,1Px\e(B)
+        (?\e$(3$`\e(B . ?\e$,1Py\e(B)
+        (?\e$(3$a\e(B . ?\e$,1Pz\e(B)
+        (?\e$(3$h\e(B . ?\e$,1Q!\e(B)
+        (?\e$(3$i\e(B . ?\e$,1Q"\e(B)
+        (?\e$(3$j\e(B . ?\e$,1Q#\e(B)
+        (?\e$(3$k\e(B . ?\e$,1Q$\e(B)
+        (?\e$(3$l\e(B . ?\e$,1Q%\e(B)
+        (?\e$(3$m\e(B . ?\e$,1Q&\e(B)
+        (?\e$(3$n\e(B . ?\e$,1Q'\e(B)
+        (?\e$(3$o\e(B . ?\e$,1Q(\e(B)
+        (?\e$(3$p\e(B . ?\e$,1Q)\e(B)
+        (?\e$(3$q\e(B . ?\e$,1Q*\e(B)
+        (?\e$(3$r\e(B . ?\e$,1Q+\e(B)
+        (?\e$(3$s\e(B . ?\e$,1Q,\e(B)
+        (?\e$(3$t\e(B . ?\e$,1Q-\e(B)
+        (?\e$(3$u\e(B . ?\e$,1Q.\e(B)
+        (?\e$(3$v\e(B . ?\e$,1Q/\e(B)
+        (?\e$(3$w\e(B . ?\e$,1Q0\e(B)
+        (?\e$(3$x\e(B . ?\e$,1Q1\e(B)
+        (?\e$(3$y\e(B . ?\e$,1Q2\e(B)
+        (?\e$(3$z\e(B . ?\e$,1Q3\e(B)
+        (?\e$(3${\e(B . ?\e$,1Q4\e(B)
+        (?\e$(3$|\e(B . ?\e$,1Q5\e(B)
+        (?\e$(3$}\e(B . ?\e$,1Q6\e(B)
+        (?\e$(3$~\e(B . ?\e$,1Q7\e(B)
+        (?\e$(3%!\e(B . ?\e$,1Q8\e(B)
+        (?\e$(3%"\e(B . ?\e$,1Q9\e(B)
+        (?\e$(3%#\e(B . ?\e$,1Q:\e(B)
+        (?\e$(3%$\e(B . ?\e$,1Q;\e(B)
+        (?\e$(3%%\e(B . ?\e$,1Q<\e(B)))
+
+      (indian-is13194
+       '((?\e(5!\e(B . ?\e$,15A\e(B)
+        (?\e(5"\e(B . ?\e$,15B\e(B)
+        (?\e(5#\e(B . ?\e$,15C\e(B)
+        (?\e(5$\e(B . ?\e$,15E\e(B)
+        (?\e(5%\e(B . ?\e$,15F\e(B)
+        (?\e(5&\e(B . ?\e$,15G\e(B)
+        (?\e(5'\e(B . ?\e$,15H\e(B)
+        (?\e(5(\e(B . ?\e$,15I\e(B)
+        (?\e(5)\e(B . ?\e$,15J\e(B)
+        (?\e(5*\e(B . ?\e$,15K\e(B)
+        (?\e(5+\e(B . ?\e$,15N\e(B)
+        (?\e(5,\e(B . ?\e$,15O\e(B)
+        (?\e(5-\e(B . ?\e$,15P\e(B)
+        (?\e(5.\e(B . ?\e$,15M\e(B)
+        (?\e(5/\e(B . ?\e$,15R\e(B)
+        (?\e(50\e(B . ?\e$,15S\e(B)
+        (?\e(51\e(B . ?\e$,15T\e(B)
+        (?\e(52\e(B . ?\e$,15M\e(B)
+        (?\e(53\e(B . ?\e$,15U\e(B)
+        (?\e(54\e(B . ?\e$,15V\e(B)
+        (?\e(55\e(B . ?\e$,15W\e(B)
+        (?\e(56\e(B . ?\e$,15X\e(B)
+        (?\e(57\e(B . ?\e$,15Y\e(B)
+        (?\e(58\e(B . ?\e$,15Z\e(B)
+        (?\e(59\e(B . ?\e$,15[\e(B)
+        (?\e(5:\e(B . ?\e$,15\\e(B)
+        (?\e(5;\e(B . ?\e$,15]\e(B)
+        (?\e(5<\e(B . ?\e$,15^\e(B)
+        (?\e(5=\e(B . ?\e$,15_\e(B)
+        (?\e(5>\e(B . ?\e$,15`\e(B)
+        (?\e(5?\e(B . ?\e$,15a\e(B)
+        (?\e(5@\e(B . ?\e$,15b\e(B)
+        (?\e(5A\e(B . ?\e$,15c\e(B)
+        (?\e(5B\e(B . ?\e$,15d\e(B)
+        (?\e(5C\e(B . ?\e$,15e\e(B)
+        (?\e(5D\e(B . ?\e$,15f\e(B)
+        (?\e(5E\e(B . ?\e$,15g\e(B)
+        (?\e(5F\e(B . ?\e$,15h\e(B)
+        (?\e(5G\e(B . ?\e$,15i\e(B)
+        (?\e(5H\e(B . ?\e$,15j\e(B)
+        (?\e(5I\e(B . ?\e$,15k\e(B)
+        (?\e(5J\e(B . ?\e$,15l\e(B)
+        (?\e(5K\e(B . ?\e$,15m\e(B)
+        (?\e(5L\e(B . ?\e$,15n\e(B)
+        (?\e(5M\e(B . ?\e$,15o\e(B)
+        (?\e(5N\e(B . ?\e$,16?\e(B)
+        (?\e(5O\e(B . ?\e$,15p\e(B)
+        (?\e(5P\e(B . ?\e$,15q\e(B)
+        (?\e(5Q\e(B . ?\e$,15r\e(B)
+        (?\e(5R\e(B . ?\e$,15s\e(B)
+        (?\e(5S\e(B . ?\e$,15t\e(B)
+        (?\e(5T\e(B . ?\e$,15u\e(B)
+        (?\e(5U\e(B . ?\e$,15v\e(B)
+        (?\e(5V\e(B . ?\e$,15w\e(B)
+        (?\e(5W\e(B . ?\e$,15x\e(B)
+        (?\e(5X\e(B . ?\e$,15y\e(B)
+        (?\e(5Z\e(B . ?\e$,15~\e(B)
+        (?\e(5[\e(B . ?\e$,15\7f\e(B)
+        (?\e(5\\e(B . ?\e$,16 \e(B)
+        (?\e(5]\e(B . ?\e$,16!\e(B)
+        (?\e(5^\e(B . ?\e$,16"\e(B)
+        (?\e(5_\e(B . ?\e$,16#\e(B)
+        (?\e(5`\e(B . ?\e$,16&\e(B)
+        (?\e(5a\e(B . ?\e$,16'\e(B)
+        (?\e(5b\e(B . ?\e$,16(\e(B)
+        (?\e(5c\e(B . ?\e$,16%\e(B)
+        (?\e(5d\e(B . ?\e$,16*\e(B)
+        (?\e(5e\e(B . ?\e$,16+\e(B)
+        (?\e(5f\e(B . ?\e$,16,\e(B)
+        (?\e(5g\e(B . ?\e$,16)\e(B)
+        (?\e(5h\e(B . ?\e$,16-\e(B)
+        (?\e(5i\e(B . ?\e$,15|\e(B)
+        (?\e(5j\e(B . ?\e$,16D\e(B)
+        (?\e(5q\e(B . ?\e$,16F\e(B)
+        (?\e(5r\e(B . ?\e$,16G\e(B)
+        (?\e(5s\e(B . ?\e$,16H\e(B)
+        (?\e(5t\e(B . ?\e$,16I\e(B)
+        (?\e(5u\e(B . ?\e$,16J\e(B)
+        (?\e(5v\e(B . ?\e$,16K\e(B)
+        (?\e(5w\e(B . ?\e$,16L\e(B)
+        (?\e(5x\e(B . ?\e$,16M\e(B)
+        (?\e(5y\e(B . ?\e$,16N\e(B)
+        (?\e(5z\e(B . ?\e$,16O\e(B)))
+
+      (katakana-jisx0201
+       '((?\e(I!\e(B . ?\e$,3sa\e(B)
+        (?\\e(I"\e(B . ?\\e$,3sb\e(B)
+        (?\\e(I#\e(B . ?\\e$,3sc\e(B)
+        (?\e(I$\e(B . ?\e$,3sd\e(B)
+        (?\e(I%\e(B . ?\e$,3se\e(B)
+        (?\e(I&\e(B . ?\e$,3sf\e(B)
+        (?\e(I'\e(B . ?\e$,3sg\e(B)
+        (?\e(I(\e(B . ?\e$,3sh\e(B)
+        (?\e(I)\e(B . ?\e$,3si\e(B)
+        (?\e(I*\e(B . ?\e$,3sj\e(B)
+        (?\e(I+\e(B . ?\e$,3sk\e(B)
+        (?\e(I,\e(B . ?\e$,3sl\e(B)
+        (?\e(I-\e(B . ?\e$,3sm\e(B)
+        (?\e(I.\e(B . ?\e$,3sn\e(B)
+        (?\e(I/\e(B . ?\e$,3so\e(B)
+        (?\e(I0\e(B . ?\e$,3sp\e(B)
+        (?\e(I1\e(B . ?\e$,3sq\e(B)
+        (?\e(I2\e(B . ?\e$,3sr\e(B)
+        (?\e(I3\e(B . ?\e$,3ss\e(B)
+        (?\e(I4\e(B . ?\e$,3st\e(B)
+        (?\e(I5\e(B . ?\e$,3su\e(B)
+        (?\e(I6\e(B . ?\e$,3sv\e(B)
+        (?\e(I7\e(B . ?\e$,3sw\e(B)
+        (?\e(I8\e(B . ?\e$,3sx\e(B)
+        (?\e(I9\e(B . ?\e$,3sy\e(B)
+        (?\e(I:\e(B . ?\e$,3sz\e(B)
+        (?\e(I;\e(B . ?\e$,3s{\e(B)
+        (?\e(I<\e(B . ?\e$,3s|\e(B)
+        (?\e(I=\e(B . ?\e$,3s}\e(B)
+        (?\e(I>\e(B . ?\e$,3s~\e(B)
+        (?\e(I?\e(B . ?\e$,3s\7f\e(B)
+        (?\e(I@\e(B . ?\e$,3t \e(B)
+        (?\e(IA\e(B . ?\e$,3t!\e(B)
+        (?\e(IB\e(B . ?\e$,3t"\e(B)
+        (?\e(IC\e(B . ?\e$,3t#\e(B)
+        (?\e(ID\e(B . ?\e$,3t$\e(B)
+        (?\e(IE\e(B . ?\e$,3t%\e(B)
+        (?\e(IF\e(B . ?\e$,3t&\e(B)
+        (?\e(IG\e(B . ?\e$,3t'\e(B)
+        (?\e(IH\e(B . ?\e$,3t(\e(B)
+        (?\e(II\e(B . ?\e$,3t)\e(B)
+        (?\e(IJ\e(B . ?\e$,3t*\e(B)
+        (?\e(IK\e(B . ?\e$,3t+\e(B)
+        (?\e(IL\e(B . ?\e$,3t,\e(B)
+        (?\e(IM\e(B . ?\e$,3t-\e(B)
+        (?\e(IN\e(B . ?\e$,3t.\e(B)
+        (?\e(IO\e(B . ?\e$,3t/\e(B)
+        (?\e(IP\e(B . ?\e$,3t0\e(B)
+        (?\e(IQ\e(B . ?\e$,3t1\e(B)
+        (?\e(IR\e(B . ?\e$,3t2\e(B)
+        (?\e(IS\e(B . ?\e$,3t3\e(B)
+        (?\e(IT\e(B . ?\e$,3t4\e(B)
+        (?\e(IU\e(B . ?\e$,3t5\e(B)
+        (?\e(IV\e(B . ?\e$,3t6\e(B)
+        (?\e(IW\e(B . ?\e$,3t7\e(B)
+        (?\e(IX\e(B . ?\e$,3t8\e(B)
+        (?\e(IY\e(B . ?\e$,3t9\e(B)
+        (?\e(IZ\e(B . ?\e$,3t:\e(B)
+        (?\e(I[\e(B . ?\e$,3t;\e(B)
+        (?\e(I\\e(B . ?\e$,3t<\e(B)
+        (?\e(I]\e(B . ?\e$,3t=\e(B)
+        (?\e(I^\e(B . ?\e$,3t>\e(B)
+        (?\e(I_\e(B . ?\e$,3t?\e(B)))
+
+      (chinese-sisheng
+       '((?\e(0!\e(B . ?\e$,1 !\e(B)
+        (?\e(0"\e(B . ?\e,Aa\e(B)
+        (?\e(0#\e(B . ?\e$,1".\e(B)
+        (?\e(0$\e(B . ?\e,A`\e(B)
+        (?\e(0%\e(B . ?\e$,1 3\e(B)
+        (?\e(0&\e(B . ?\e,Ai\e(B)
+        (?\e(0'\e(B . ?\e$,1 ;\e(B)
+        (?\e(0(\e(B . ?\e,Ah\e(B)
+        (?\e(0)\e(B . ?\e$,1 K\e(B)
+        (?\e(0*\e(B . ?\e,Am\e(B)
+        (?\e(0+\e(B . ?\e$,1"0\e(B)
+        (?\e(0,\e(B . ?\e,Al\e(B)
+        (?\e(0-\e(B . ?\e$,1 m\e(B)
+        (?\e(0.\e(B . ?\e,As\e(B)
+        (?\e(0/\e(B . ?\e$,1"2\e(B)
+        (?\e(00\e(B . ?\e,Ar\e(B)
+        (?\e(01\e(B . ?\e$,1!+\e(B)
+        (?\e(02\e(B . ?\e,Az\e(B)
+        (?\e(03\e(B . ?\e$,1"4\e(B)
+        (?\e(04\e(B . ?\e,Ay\e(B)
+        (?\e(05\e(B . ?\e$,1"6\e(B)
+        (?\e(06\e(B . ?\e$,1"8\e(B)
+        (?\e(07\e(B . ?\e$,1":\e(B)
+        (?\e(08\e(B . ?\e$,1"<\e(B)
+        (?\e(09\e(B . ?\e,A|\e(B)
+        (?\e(0:\e(B . ?\e,Aj\e(B)
+        (?\e(0<\e(B . ?\e$,1m\7f\e(B)
+        (?\e(0=\e(B . ?\e$,1 d\e(B)
+        (?\e(0>\e(B . ?\e$,1 h\e(B)
+        (?\e(0?\e(B . ?\e$,1"Y\e(B)
+        (?\e(0A\e(B . ?\e$,1$i\e(B)
+        (?\e(0B\e(B . ?\e$,1$j\e(B)
+        (?\e(0C\e(B . ?\e$,1$g\e(B)
+        (?\e(0D\e(B . ?\e$,1$k\e(B)
+        (?\e(0E\e(B . ?\e$,2@%\e(B)
+        (?\e(0F\e(B . ?\e$,2@&\e(B)
+        (?\e(0G\e(B . ?\e$,2@'\e(B)
+        (?\e(0H\e(B . ?\e$,2@(\e(B)
+        (?\e(0I\e(B . ?\e$,2@)\e(B)
+        (?\e(0J\e(B . ?\e$,2@*\e(B)
+        (?\e(0K\e(B . ?\e$,2@+\e(B)
+        (?\e(0L\e(B . ?\e$,2@,\e(B)
+        (?\e(0M\e(B . ?\e$,2@-\e(B)
+        (?\e(0N\e(B . ?\e$,2@.\e(B)
+        (?\e(0O\e(B . ?\e$,2@/\e(B)
+        (?\e(0P\e(B . ?\e$,2@0\e(B)
+        (?\e(0Q\e(B . ?\e$,2@1\e(B)
+        (?\e(0R\e(B . ?\e$,2@2\e(B)
+        (?\e(0S\e(B . ?\e$,2@3\e(B)
+        (?\e(0T\e(B . ?\e$,2@4\e(B)
+        (?\e(0U\e(B . ?\e$,2@5\e(B)
+        (?\e(0V\e(B . ?\e$,2@6\e(B)
+        (?\e(0W\e(B . ?\e$,2@7\e(B)
+        (?\e(0X\e(B . ?\e$,2@8\e(B)
+        (?\e(0Y\e(B . ?\e$,2@9\e(B)
+        (?\e(0Z\e(B . ?\e$,2@:\e(B)
+        (?\e(0[\e(B . ?\e$,2@;\e(B)
+        (?\e(0\\e(B . ?\e$,2@<\e(B)
+        (?\e(0]\e(B . ?\e$,2@=\e(B)
+        (?\e(0^\e(B . ?\e$,2@>\e(B)
+        (?\e(0_\e(B . ?\e$,2@?\e(B)
+        (?\e(0`\e(B . ?\e$,2@@\e(B)
+        (?\e(0a\e(B . ?\e$,2@A\e(B)
+        (?\e(0b\e(B . ?\e$,2@B\e(B)
+        (?\e(0c\e(B . ?\e$,2@C\e(B)
+        (?\e(0d\e(B . ?\e$,2@D\e(B)
+        (?\e(0e\e(B . ?\e$,2@E\e(B)
+        (?\e(0f\e(B . ?\e$,2@F\e(B)
+        (?\e(0g\e(B . ?\e$,2@G\e(B)
+        (?\e(0h\e(B . ?\e$,2@H\e(B)
+        (?\e(0i\e(B . ?\e$,2@I\e(B)))
+
+      (lao
+       '((?\e(1!\e(B . ?\e$,1D!\e(B)
+        (?\e(1"\e(B . ?\e$,1D"\e(B)
+        (?\e(1$\e(B . ?\e$,1D$\e(B)
+        (?\e(1'\e(B . ?\e$,1D'\e(B)
+        (?\e(1(\e(B . ?\e$,1D(\e(B)
+        (?\e(1*\e(B . ?\e$,1D*\e(B)
+        (?\e(1-\e(B . ?\e$,1D-\e(B)
+        (?\e(14\e(B . ?\e$,1D4\e(B)
+        (?\e(15\e(B . ?\e$,1D5\e(B)
+        (?\e(16\e(B . ?\e$,1D6\e(B)
+        (?\e(17\e(B . ?\e$,1D7\e(B)
+        (?\e(19\e(B . ?\e$,1D9\e(B)
+        (?\e(1:\e(B . ?\e$,1D:\e(B)
+        (?\e(1;\e(B . ?\e$,1D;\e(B)
+        (?\e(1<\e(B . ?\e$,1D<\e(B)
+        (?\e(1=\e(B . ?\e$,1D=\e(B)
+        (?\e(1>\e(B . ?\e$,1D>\e(B)
+        (?\e(1?\e(B . ?\e$,1D?\e(B)
+        (?\e(1A\e(B . ?\e$,1DA\e(B)
+        (?\e(1B\e(B . ?\e$,1DB\e(B)
+        (?\e(1C\e(B . ?\e$,1DC\e(B)
+        (?\e(1E\e(B . ?\e$,1DE\e(B)
+        (?\e(1G\e(B . ?\e$,1DG\e(B)
+        (?\e(1J\e(B . ?\e$,1DJ\e(B)
+        (?\e(1K\e(B . ?\e$,1DK\e(B)
+        (?\e(1M\e(B . ?\e$,1DM\e(B)
+        (?\e(1N\e(B . ?\e$,1DN\e(B)
+        (?\e(1O\e(B . ?\e$,1DO\e(B)
+        (?\e(1P\e(B . ?\e$,1DP\e(B)
+        (?\e(1Q\e(B . ?\e$,1DQ\e(B)
+        (?\e(1R\e(B . ?\e$,1DR\e(B)
+        (?\e(1S\e(B . ?\e$,1DS\e(B)
+        (?\e(1T\e(B . ?\e$,1DT\e(B)
+        (?\e(1U\e(B . ?\e$,1DU\e(B)
+        (?\e(1V\e(B . ?\e$,1DV\e(B)
+        (?\e(1W\e(B . ?\e$,1DW\e(B)
+        (?\e(1X\e(B . ?\e$,1DX\e(B)
+        (?\e(1Y\e(B . ?\e$,1DY\e(B)
+        (?\e(1[\e(B . ?\e$,1D[\e(B)
+        (?\e(1\\e(B . ?\e$,1D\\e(B)
+        (?\e(1]\e(B . ?\e$,1D]\e(B)
+        (?\e(1`\e(B . ?\e$,1D`\e(B)
+        (?\e(1a\e(B . ?\e$,1Da\e(B)
+        (?\e(1b\e(B . ?\e$,1Db\e(B)
+        (?\e(1c\e(B . ?\e$,1Dc\e(B)
+        (?\e(1d\e(B . ?\e$,1Dd\e(B)
+        (?\e(1f\e(B . ?\e$,1Df\e(B)
+        (?\e(1h\e(B . ?\e$,1Dh\e(B)
+        (?\e(1i\e(B . ?\e$,1Di\e(B)
+        (?\e(1j\e(B . ?\e$,1Dj\e(B)
+        (?\e(1k\e(B . ?\e$,1Dk\e(B)
+        (?\e(1l\e(B . ?\e$,1Dl\e(B)
+        (?\e(1m\e(B . ?\e$,1Dm\e(B)
+        (?\e(1p\e(B . ?\e$,1Dp\e(B)
+        (?\e(1q\e(B . ?\e$,1Dq\e(B)
+        (?\e(1r\e(B . ?\e$,1Dr\e(B)
+        (?\e(1s\e(B . ?\e$,1Ds\e(B)
+        (?\e(1t\e(B . ?\e$,1Dt\e(B)
+        (?\e(1u\e(B . ?\e$,1Du\e(B)
+        (?\e(1v\e(B . ?\e$,1Dv\e(B)
+        (?\e(1w\e(B . ?\e$,1Dw\e(B)
+        (?\e(1x\e(B . ?\e$,1Dx\e(B)
+        (?\e(1y\e(B . ?\e$,1Dy\e(B)
+        (?\e(1|\e(B . ?\e$,1D|\e(B)
+        (?\e(1}\e(B . ?\e$,1D}\e(B))))
+  (let ((table (make-char-table 'safe-chars))
+       safe-charsets)
+    (dolist (cs '(vietnamese-viscii lao chinese-sisheng ipa
+                 katakana-jisx0201 thai-tis620 tibetan-iso-8bit
+                 indian-is13194 ethiopic))
+      ;; These tables could be used as translation-table-for-encode by
+      ;; the relevant coding systems.
+      (let ((encode-translator
+            (if (coding-system-p cs)
+                (set (intern (format "ucs-%s-encode-table" cs))
+                     (make-translation-table)))))
+       (dolist (pair (symbol-value cs))
+         (aset ucs-mule-to-mule-unicode (car pair) (cdr pair))
+         (if encode-translator
+             (aset encode-translator (cdr pair) (car pair))))
+       (if (charsetp cs)
+           (push cs safe-charsets)
+         (setq safe-charsets
+               (append (delq 'ascii (coding-system-get cs 'safe-charsets))
+                       safe-charsets)))))
+    (dolist (c safe-charsets)
+      (aset table (make-char c) t))
+    (coding-system-put 'mule-utf-8 'safe-charsets
+                      (append (coding-system-get 'mule-utf-8 'safe-charsets)
+                              safe-charsets))
+    (register-char-codings 'mule-utf-8 table)))
+
+(provide 'ucs-tables)
+
+;;; ucs-tables.el ends here
diff --git a/contrib/vcard.el b/contrib/vcard.el
new file mode 100644 (file)
index 0000000..22f032c
--- /dev/null
@@ -0,0 +1,308 @@
+;;; vcard.el --- vcard parsing and display routines
+
+;; Copyright (C) 1997 Noah S. Friedman
+
+;; Author: Noah Friedman <friedman@splode.com>
+;; Maintainer: friedman@splode.com
+;; Keywords: extensions
+;; Created: 1997-09-27
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, you can either send email to this
+;; program's maintainer or write to: The Free Software Foundation,
+;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The display routines here are just an example.  The primitives in the
+;; first section can be used to construct other vcard formatters.
+
+;;; Code:
+
+(defvar vcard-standard-filters '(vcard-filter-html)
+  "*Standard list of filters to apply to parsed vcard data.
+These filters are applied sequentially to vcard data records when
+the function `vcard-standard-filter' is supplied as the second argument to
+`vcard-parse-string'.")
+
+(defun vcard-parse-string (raw &optional filter)
+  "Parse RAW vcard data as a string, and return an alist representing data.
+
+If the optional function FILTER is specified, apply that filter to the
+data record of each key before splitting fields.  Filters should accept
+two arguments: the key and the data.  They are expected to operate on
+\(and return\) a modified data value.
+
+Vcard data is normally in the form
+
+    begin:        vcard
+    key1:         field
+    key2;subkey1: field
+    key2;subkey2: field1;field2;field3
+    end:          vcard
+
+\(Whitespace after the colon separating the key and field is optional.\)
+If supplied to this function an alist of the form
+
+    ((\"key1\" \"field\")
+     (\"key2\"
+      (\"subkey2\" \"field1\" \"field2\" \"field3\")
+      (\"subkey1\" \"field\")))
+
+would be returned."
+  (save-match-data
+    (let ((raw-pos 0)
+          (vcard-data nil)
+          key data)
+      (string-match "^[ \t]*begin:[ \t]*vcard[ \t]*[\r\n]+" raw raw-pos)
+      (setq raw-pos (match-end 0))
+      (while (and (< raw-pos (length raw))
+                  (string-match
+                   "^[ \t]*\\([^:]+\\):[ \t]*\\(.*\\)[ \t]*[\n\r]+"
+                   raw raw-pos))
+        (setq key (vcard-matching-substring 1 raw))
+        (setq data (vcard-matching-substring 2 raw))
+        (setq raw-pos (match-end 0))
+        (cond
+         ((string= key "end")
+          (setq raw-pos (length raw)))
+         (t
+          (and filter
+               (setq data (funcall filter key data)))
+          (setq vcard-data
+                (vcard-set-alist-slot vcard-data
+                                      (vcard-split-string key ";")
+                                      (vcard-split-string data ";"))))))
+      (nreverse vcard-data))))
+
+(defun vcard-ref (key vcard-data)
+  "Return the vcard data associated with KEY in VCARD-DATA.
+Key may be a list of nested keys or a single string of colon-separated
+keys."
+  (cond ((listp key)
+         (vcard-alist-assoc key vcard-data))
+        ((and (stringp key)
+              (save-match-data
+                (string-match ";" key)))
+         (vcard-alist-assoc (vcard-split-string key ";") vcard-data))
+        ((stringp key)
+         (cdr (assoc key vcard-data)))))
+
+\f
+;;; Vcard data filters.
+
+;; These receive both the key and data, but are expected to operate on (and
+;; return) just the data.
+;;
+;; There is probably no overwhelming need for this, except that some lusers
+;; put HTML in their vcards under the misguided notion that it's a standard
+;; feature of vcards just because Netscape supports this feature.  (Or
+;; perhaps those lusers just don't care that their vcards look like shit in
+;; every other MUA).
+;;
+;; On the other hand, perhaps someone will devise some other use for these
+;; filters, such as noticing common phone number formats and re-formatting
+;; them to fit personal preferences.
+
+(defun vcard-filter-apply-filter-list (filter-list key data)
+  (while filter-list
+    (setq data (funcall (car filter-list) key data))
+    (setq filter-list (cdr filter-list)))
+  data)
+
+(defun vcard-standard-filter (key data)
+  (vcard-filter-apply-filter-list vcard-standard-filters key data))
+
+(defun vcard-filter-html (key data)
+  (save-match-data
+    (while (string-match "<[^<>\n]+>" data)
+      (setq data (concat (substring data 0 (match-beginning 0))
+                         (substring data (match-end 0)))))
+    data))
+
+\f
+;;; Utility routines.
+
+;; This does most of the dirty work of key lookup for vcard-ref.
+(defun vcard-alist-assoc (keys alist)
+  (while (and keys alist)
+    (setq alist (cdr (assoc (car keys) alist)))
+    (setq keys (cdr keys)))
+  alist)
+
+;; In ALIST, set KEY-LIST's value to VALUE, and return new value of ALIST.
+;; KEY-LIST should be a list of nested keys, if ALIST is an alist of alists.
+;; If any key is not present in an alist, the key and value pair will be
+;; inserted into the parent alist.
+(defun vcard-set-alist-slot (alist key-list value)
+  (let* ((key (car key-list))
+         (elt (assoc key alist)))
+    (setq key-list (cdr key-list))
+    (cond ((and (cdr elt) key-list)
+           (vcard-set-alist-slot (cdr elt) key-list value))
+          ((and elt key-list)
+           (setcdr elt (vcard-set-alist-slot nil key-list value)))
+          (elt (setcdr elt value))
+          (t
+           (let ((new))
+             (setq key-list (nreverse (cons key key-list)))
+             (while key-list
+               (if new
+                   (setq new (cons (car key-list) (cons new nil)))
+                 (setq new (cons (car key-list) value)))
+               (setq key-list (cdr key-list)))
+
+             (cond ((null alist)
+                    (setq alist (cons new nil)))
+                   (t
+                    (setcdr alist (cons (car alist) (cdr alist)))
+                    (setcar alist new))))))
+    alist))
+
+;; Return substring matched by last search.
+;; N specifies which match data pair to use
+;; Value is nil if there is no Nth match.
+;; If STRING is not specified, the current buffer is used.
+(defun vcard-matching-substring (n &optional string)
+  (if (match-beginning n)
+      (if string
+         (substring string (match-beginning n) (match-end n))
+       (buffer-substring (match-beginning n) (match-end n)))))
+
+;; Split STRING at occurences of SEPARATOR.  Return a list of substrings.
+;; SEPARATOR can be any regexp, but anything matching the separator will
+;; never appear in any of the returned substrings.
+(defun vcard-split-string (string separator)
+  (let* ((list nil)
+         (pos 0))
+    (save-match-data
+      (while (string-match separator string pos)
+        (setq list (cons (substring string pos (match-beginning 0)) list))
+        (setq pos (match-end 0)))
+      (nreverse (cons (substring string pos) list)))))
+
+(defun vcard-flatten (l)
+  (if (consp l)
+      (apply 'nconc (mapcar 'vcard-flatten l))
+    (list l)))
+
+\f
+;;; Sample formatting routines.
+
+(defun vcard-format-box (vcard-data)
+  "Like `vcard-format-string', but put an ascii box around text."
+  (let* ((lines (vcard-format-lines vcard-data))
+         (len (vcard-format-max-length lines))
+         (edge (concat "\n+" (make-string (+ len 2) ?-) "+\n"))
+         (line-fmt (format "| %%-%ds |" len))
+         (formatted-lines
+          (mapconcat (function (lambda (s) (format line-fmt s))) lines "\n")))
+    (if (string= formatted-lines "")
+        formatted-lines
+      (concat edge formatted-lines edge))))
+
+(defun vcard-format-string (vcard-data)
+  "Format VCARD-DATA into a string suitable for presentation.
+VCARD-DATA should be a parsed vcard alist.  The result is a string
+with formatted vcard information which can be inserted into a mime
+presentation buffer."
+  (mapconcat 'identity (vcard-format-lines vcard-data) "\n"))
+
+(defun vcard-format-lines (vcard-data)
+  (let* ((name  (vcard-format-get-name      vcard-data))
+         (title (vcard-format-ref "title"   vcard-data))
+         (org   (vcard-format-ref "org"     vcard-data))
+         (addr  (vcard-format-get-address   vcard-data))
+         (tel   (vcard-format-get-telephone vcard-data))
+         (lines (delete nil (vcard-flatten (list name title org addr))))
+         (col-template (format "%%-%ds%%s"
+                               (vcard-format-offset lines tel)))
+         (l lines))
+    (while tel
+      (setcar l (format col-template (car l) (car tel)))
+      ;; If we stripped away too many nil slots from l, add empty strings
+      ;; back in so setcar above will work on next iteration.
+      (and (cdr tel)
+           (null (cdr l))
+           (setcdr l (cons "" nil)))
+      (setq l (cdr l))
+      (setq tel (cdr tel)))
+    lines))
+
+
+(defun vcard-format-get-name (vcard-data)
+  (let ((name (vcard-format-ref "fn" vcard-data))
+        (email (or (vcard-format-ref '("email" "internet") vcard-data)
+                   (vcard-format-ref "email" vcard-data))))
+    (if email
+        (format "%s <%s>" name email)
+      name)))
+
+(defun vcard-format-get-address (vcard-data)
+  (let* ((addr-raw (or (vcard-format-ref '("adr" "dom") vcard-data)
+                       (vcard-format-ref "adr" vcard-data)))
+         (addr (if (consp addr-raw)
+                   addr-raw
+                 (list addr-raw)))
+         (street (delete "" (list (nth 0 addr) (nth 1 addr) (nth 2 addr))))
+         (city-list (delete "" (nthcdr 3 addr)))
+         (city (cond ((null (car city-list)) nil)
+                     ((cdr city-list)
+                      (format "%s, %s"
+                              (car city-list)
+                              (mapconcat 'identity (cdr city-list) " ")))
+                     (t (car city-list)))))
+    (delete nil
+            (if city
+                (append street (list city))
+              street))))
+
+(defun vcard-format-get-telephone (vcard-data)
+  (delete nil
+          (mapcar (function (lambda (x)
+                              (let ((result (vcard-format-ref (car x)
+                                                              vcard-data)))
+                                (and result
+                                     (concat (cdr x) result)))))
+                  '((("tel" "work") . "Work: ")
+                    (("tel" "home") . "Home: ")
+                    (("tel" "fax")  . "Fax:  ")))))
+
+(defun vcard-format-ref (key vcard-data)
+  (setq key (vcard-ref key vcard-data))
+  (or (cdr key)
+      (setq key (car key)))
+  (and (stringp key)
+       (string= key "")
+       (setq key nil))
+  key)
+
+(defun vcard-format-offset (row1 row2 &optional maxwidth)
+  (or maxwidth (setq maxwidth (frame-width)))
+  (let ((max1 (vcard-format-max-length row1))
+        (max2 (vcard-format-max-length row2)))
+    (+ max1 (min 5 (max 1 (- maxwidth (+ max1 max2)))))))
+
+(defun vcard-format-max-length (strings)
+  (let ((maxlen 0)
+        (len 0))
+    (while strings
+      (setq len (length (car strings)))
+      (setq strings (cdr strings))
+      (and (> len maxlen)
+           (setq maxlen len)))
+    maxlen))
+
+(provide 'vcard)
+
+;;; vcard.el ends here
diff --git a/contrib/xml.el b/contrib/xml.el
new file mode 100644 (file)
index 0000000..a495721
--- /dev/null
@@ -0,0 +1,501 @@
+;;; xml.el --- XML parser
+
+;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+;; Author: Emmanuel Briot  <briot@gnat.com>
+;; Maintainer: Emmanuel Briot <briot@gnat.com>
+;; Keywords: xml
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file contains a full XML parser. It parses a file, and returns a list
+;; that can be used internally by any other lisp file.
+;; See some example in todo.el
+
+;;; FILE FORMAT
+
+;; It does not parse the DTD, if present in the XML file, but knows how to
+;; ignore it. The XML file is assumed to be well-formed. In case of error, the
+;; parsing stops and the XML file is shown where the parsing stopped.
+;;
+;; It also knows how to ignore comments, as well as the special ?xml? tag
+;; in the XML file.
+;;
+;; The XML file should have the following format:
+;;    <node1 attr1="name1" attr2="name2" ...>value
+;;       <node2 attr3="name3" attr4="name4">value2</node2>
+;;       <node3 attr5="name5" attr6="name6">value3</node3>
+;;    </node1>
+;; Of course, the name of the nodes and attributes can be anything. There can
+;; be any number of attributes (or none), as well as any number of children
+;; below the nodes.
+;;
+;; There can be only top level node, but with any number of children below.
+
+;;; LIST FORMAT
+
+;; The functions `xml-parse-file' and `xml-parse-tag' return a list with
+;; the following format:
+;;
+;;    xml-list   ::= (node node ...)
+;;    node       ::= (tag_name attribute-list . child_node_list)
+;;    child_node_list ::= child_node child_node ...
+;;    child_node ::= node | string
+;;    tag_name   ::= string
+;;    attribute_list ::= (("attribute" . "value") ("attribute" . "value") ...)
+;;                       | nil
+;;    string     ::= "..."
+;;
+;; Some macros are provided to ease the parsing of this list
+
+;;; Code:
+
+;;*******************************************************************
+;;**
+;;**  Macros to parse the list
+;;**
+;;*******************************************************************
+
+(defsubst xml-node-name (node)
+  "Return the tag associated with NODE.
+The tag is a lower-case symbol."
+  (car node))
+
+(defsubst xml-node-attributes (node)
+  "Return the list of attributes of NODE.
+The list can be nil."
+  (nth 1 node))
+
+(defsubst xml-node-children (node)
+  "Return the list of children of NODE.
+This is a list of nodes, and it can be nil."
+  (cddr node))
+
+(defun xml-get-children (node child-name)
+  "Return the children of NODE whose tag is CHILD-NAME.
+CHILD-NAME should be a lower case symbol."
+  (let ((match ()))
+    (dolist (child (xml-node-children node))
+      (if child
+         (if (equal (xml-node-name child) child-name)
+             (push child match))))
+    (nreverse match)))
+
+(defun xml-get-attribute (node attribute)
+  "Get from NODE the value of ATTRIBUTE.
+An empty string is returned if the attribute was not found."
+  (if (xml-node-attributes node)
+      (let ((value (assoc attribute (xml-node-attributes node))))
+       (if value
+           (cdr value)
+         ""))
+    ""))
+
+;;*******************************************************************
+;;**
+;;**  Creating the list
+;;**
+;;*******************************************************************
+
+(defun xml-parse-file (file &optional parse-dtd)
+  "Parse the well-formed XML FILE.
+If FILE is already edited, this will keep the buffer alive.
+Returns the top node with all its children.
+If PARSE-DTD is non-nil, the DTD is parsed rather than skipped."
+  (let ((keep))
+    (if (get-file-buffer file)
+       (progn
+         (set-buffer (get-file-buffer file))
+         (setq keep (point)))
+      (find-file file))
+    
+    (let ((xml (xml-parse-region (point-min)
+                                (point-max)
+                                (current-buffer)
+                                parse-dtd)))
+      (if keep
+         (goto-char keep)
+       (kill-buffer (current-buffer)))
+      xml)))
+
+(defun xml-parse-region (beg end &optional buffer parse-dtd)
+  "Parse the region from BEG to END in BUFFER.
+If BUFFER is nil, it defaults to the current buffer.
+Returns the XML list for the region, or raises an error if the region
+is not a well-formed XML file.
+If PARSE-DTD is non-nil, the DTD is parsed rather than skipped,
+and returned as the first element of the list"
+  (let (xml result dtd)
+    (save-excursion
+      (if buffer
+         (set-buffer buffer))
+      (goto-char beg)
+      (while (< (point) end)
+       (if (search-forward "<" end t)
+           (progn
+             (forward-char -1)
+             (if (null xml)
+                 (progn
+                   (setq result (xml-parse-tag end parse-dtd))
+                   (cond
+                    ((null result))
+                    ((listp (car result))
+                     (setq dtd (car result))
+                     (add-to-list 'xml (cdr result)))
+                    (t
+                     (add-to-list 'xml result))))
+
+               ;;  translation of rule [1] of XML specifications
+               (error "XML files can have only one toplevel tag")))
+         (goto-char end)))
+      (if parse-dtd
+         (cons dtd (reverse xml))
+       (reverse xml)))))
+
+
+(defun xml-parse-tag (end &optional parse-dtd)
+  "Parse the tag that is just in front of point.
+The end tag must be found before the position END in the current buffer.
+If PARSE-DTD is non-nil, the DTD of the document, if any, is parsed and
+returned as the first element in the list.
+Returns one of:
+   - a list : the matching node
+   - nil    : the point is not looking at a tag.
+   - a cons cell: the first element is the DTD, the second is the node"
+  (cond
+   ;; Processing instructions (like the <?xml version="1.0"?> tag at the
+   ;; beginning of a document)
+   ((looking-at "<\\?")
+    (search-forward "?>" end)
+    (skip-chars-forward " \t\n")
+    (xml-parse-tag end))
+   ;;  Character data (CDATA) sections, in which no tag should be interpreted
+   ((looking-at "<!\\[CDATA\\[")
+    (let ((pos (match-end 0)))
+      (unless (search-forward "]]>" end t)
+       (error "CDATA section does not end anywhere in the document"))
+      (buffer-substring-no-properties pos (match-beginning 0))))
+   ;;  DTD for the document
+   ((looking-at "<!DOCTYPE")
+    (let (dtd)
+      (if parse-dtd
+         (setq dtd (xml-parse-dtd end))
+       (xml-skip-dtd end))
+      (skip-chars-forward " \t\n")
+      (if dtd
+         (cons dtd (xml-parse-tag end))
+       (xml-parse-tag end))))
+   ;;  skip comments
+   ((looking-at "<!--")
+    (search-forward "-->" end)
+    nil)
+   ;;  end tag
+   ((looking-at "</")
+    '())
+   ;;  opening tag
+   ((looking-at "<\\([^/> \t\n]+\\)")
+    (goto-char (match-end 1))
+    (let* ((case-fold-search nil) ;; XML is case-sensitive.
+          (node-name (match-string 1))
+          ;; Parse the attribute list.
+          (children (list (xml-parse-attlist end) (intern node-name)))
+          pos)
+
+      ;; is this an empty element ?
+      (if (looking-at "/>")
+         (progn
+           (forward-char 2)
+           (nreverse (cons '("") children)))
+
+       ;; is this a valid start tag ?
+       (if (eq (char-after) ?>)
+           (progn
+             (forward-char 1)
+             ;;  Now check that we have the right end-tag. Note that this
+             ;;  one might contain spaces after the tag name
+             (while (not (looking-at (concat "</" node-name "[ \t\n]*>")))
+               (cond
+                ((looking-at "</")
+                 (error (concat
+                         "XML: invalid syntax -- invalid end tag (expecting "
+                         node-name
+                         ") at pos " (number-to-string (point)))))
+                ((= (char-after) ?<)
+                 (let ((tag (xml-parse-tag end)))
+                   (when tag
+                     (push tag children))))
+                (t
+                 (setq pos (point))
+                 (search-forward "<" end)
+                 (forward-char -1)
+                 (let ((string (buffer-substring-no-properties pos (point)))
+                       (pos 0))
+                   
+                   ;; Clean up the string (no newline characters)
+                   ;; Not done, since as per XML specifications, the XML processor
+                   ;; should always pass the whole string to the application.
+                   ;;      (while (string-match "\\s +" string pos)
+                   ;;        (setq string (replace-match " " t t string))
+                   ;;        (setq pos (1+ (match-beginning 0))))
+
+                   (setq string (xml-substitute-special string))
+                   (setq children
+                         (if (stringp (car children))
+                             ;; The two strings were separated by a comment.
+                             (cons (concat (car children) string)
+                                   (cdr children))
+                           (cons string children)))))))
+             (goto-char (match-end 0))
+             (if (> (point) end)
+                 (error "XML: End tag for %s not found before end of region"
+                        node-name))
+             (nreverse children))
+
+         ;;  This was an invalid start tag
+         (error "XML: Invalid attribute list")
+         ))))
+   (t ;; This is not a tag.
+    (error "XML: Invalid character"))
+   ))
+
+(defun xml-parse-attlist (end)
+  "Return the attribute-list that point is looking at.
+The search for attributes end at the position END in the current buffer.
+Leaves the point on the first non-blank character after the tag."
+  (let ((attlist ())
+       name)
+    (skip-chars-forward " \t\n")
+    (while (looking-at "\\([a-zA-Z_:][-a-zA-Z0-9._:]*\\)[ \t\n]*=[ \t\n]*")
+      (setq name (intern (match-string 1)))
+      (goto-char (match-end 0))
+
+      ;; Do we have a string between quotes (or double-quotes),
+      ;;  or a simple word ?
+      (unless (looking-at "\"\\([^\"]*\\)\"")
+       (unless (looking-at "'\\([^']*\\)'")
+         (error "XML: Attribute values must be given between quotes")))
+
+      ;; Each attribute must be unique within a given element
+      (if (assoc name attlist)
+         (error "XML: each attribute must be unique within an element"))
+      
+      (push (cons name (match-string-no-properties 1)) attlist)
+      (goto-char (match-end 0))
+      (skip-chars-forward " \t\n")
+      (if (> (point) end)
+         (error "XML: end of attribute list not found before end of region"))
+      )
+    (nreverse attlist)))
+
+;;*******************************************************************
+;;**
+;;**  The DTD (document type declaration)
+;;**  The following functions know how to skip or parse the DTD of
+;;**  a document
+;;**
+;;*******************************************************************
+
+(defun xml-skip-dtd (end)
+  "Skip the DTD that point is looking at.
+The DTD must end before the position END in the current buffer.
+The point must be just before the starting tag of the DTD.
+This follows the rule [28] in the XML specifications."
+  (forward-char (length "<!DOCTYPE"))
+  (if (looking-at "[ \t\n]*>")
+      (error "XML: invalid DTD (excepting name of the document)"))
+  (condition-case nil
+      (progn
+       (forward-word 1)  ;; name of the document
+       (skip-chars-forward " \t\n")
+       (if (looking-at "\\[")
+           (re-search-forward "\\][ \t\n]*>" end)
+         (search-forward ">" end)))
+    (error (error "XML: No end to the DTD"))))
+
+(defun xml-parse-dtd (end)
+  "Parse the DTD that point is looking at.
+The DTD must end before the position END in the current buffer."
+  (forward-char (length "<!DOCTYPE"))
+  (skip-chars-forward " \t\n")
+  (if (looking-at ">")
+      (error "XML: invalid DTD (excepting name of the document)"))
+  
+  ;;  Get the name of the document
+  (looking-at "\\sw+")
+  (let ((dtd (list (match-string-no-properties 0) 'dtd))
+       type element end-pos)
+    (goto-char (match-end 0))
+
+    (skip-chars-forward " \t\n")
+
+    ;;  External DTDs => don't know how to handle them yet
+    (if (looking-at "SYSTEM")
+       (error "XML: Don't know how to handle external DTDs"))
+    
+    (if (not (= (char-after) ?\[))
+       (error "XML: Unknown declaration in the DTD"))
+
+    ;;  Parse the rest of the DTD
+    (forward-char 1)
+    (while (and (not (looking-at "[ \t\n]*\\]"))
+               (<= (point) end))
+      (cond
+
+       ;;  Translation of rule [45] of XML specifications
+       ((looking-at
+        "[\t \n]*<!ELEMENT[ \t\n]+\\([a-zA-Z0-9.%;]+\\)[ \t\n]+\\([^>]+\\)>")
+
+       (setq element (intern (match-string-no-properties 1))
+             type    (match-string-no-properties 2))
+       (setq end-pos (match-end 0))
+       
+       ;;  Translation of rule [46] of XML specifications
+       (cond
+        ((string-match "^EMPTY[ \t\n]*$" type)     ;; empty declaration
+         (setq type 'empty))
+        ((string-match "^ANY[ \t\n]*$" type)       ;; any type of contents
+         (setq type 'any))
+        ((string-match "^(\\(.*\\))[ \t\n]*$" type) ;; children ([47])
+         (setq type (xml-parse-elem-type (match-string-no-properties 1 type))))
+        ((string-match "^%[^;]+;[ \t\n]*$" type)   ;; substitution
+         nil)
+        (t
+         (error "XML: Invalid element type in the DTD")))
+
+       ;;  rule [45]: the element declaration must be unique
+       (if (assoc element dtd)
+           (error "XML: elements declaration must be unique in a DTD (<%s>)"
+                  (symbol-name element)))
+       
+       ;;  Store the element in the DTD
+       (push (list element type) dtd)
+       (goto-char end-pos))
+
+
+       (t
+       (error "XML: Invalid DTD item"))
+       )
+      )
+
+    ;;  Skip the end of the DTD
+    (search-forward ">" end)
+    (nreverse dtd)))
+
+
+(defun xml-parse-elem-type (string)
+  "Convert a STRING for an element type into an elisp structure."
+
+  (let (elem modifier)
+    (if (string-match "(\\([^)]+\\))\\([+*?]?\\)" string)
+       (progn
+         (setq elem     (match-string 1 string)
+               modifier (match-string 2 string))
+         (if (string-match "|" elem)
+             (setq elem (cons 'choice
+                              (mapcar 'xml-parse-elem-type
+                                      (split-string elem "|"))))
+           (if (string-match "," elem)
+               (setq elem (cons 'seq
+                                (mapcar 'xml-parse-elem-type
+                                        (split-string elem ","))))
+             )))
+      (if (string-match "[ \t\n]*\\([^+*?]+\\)\\([+*?]?\\)" string)
+         (setq elem     (match-string 1 string)
+               modifier (match-string 2 string))))
+
+    (if (and (stringp elem) (string= elem "#PCDATA"))
+       (setq elem 'pcdata))
+    
+    (cond
+     ((string= modifier "+")
+      (list '+ elem))
+     ((string= modifier "*")
+      (list '* elem))
+     ((string= modifier "?")
+      (list '? elem))
+     (t
+      elem))))
+
+
+;;*******************************************************************
+;;**
+;;**  Substituting special XML sequences
+;;**
+;;*******************************************************************
+
+(defun xml-substitute-special (string)
+  "Return STRING, after subsituting special XML sequences."
+  (while (string-match "&amp;" string)
+    (setq string (replace-match "&"  t nil string)))
+  (while (string-match "&lt;" string)
+    (setq string (replace-match "<"  t nil string)))
+  (while (string-match "&gt;" string)
+    (setq string (replace-match ">"  t nil string)))
+  (while (string-match "&apos;" string)
+    (setq string (replace-match "'"  t nil string)))
+  (while (string-match "&quot;" string)
+    (setq string (replace-match "\"" t nil string)))
+  string)
+
+;;*******************************************************************
+;;**
+;;**  Printing a tree.
+;;**  This function is intended mainly for debugging purposes.
+;;**
+;;*******************************************************************
+
+(defun xml-debug-print (xml)
+  (dolist (node xml)
+    (xml-debug-print-internal node "")))
+
+(defun xml-debug-print-internal (xml indent-string)
+  "Outputs the XML tree in the current buffer.
+The first line indented with INDENT-STRING."
+  (let ((tree xml)
+       attlist)
+    (insert indent-string "<" (symbol-name (xml-node-name tree)))
+    
+    ;;  output the attribute list
+    (setq attlist (xml-node-attributes tree))
+    (while attlist
+      (insert " ")
+      (insert (symbol-name (caar attlist)) "=\"" (cdar attlist) "\"")
+      (setq attlist (cdr attlist)))
+    
+    (insert ">")
+    
+    (setq tree (xml-node-children tree))
+
+    ;;  output the children
+    (dolist (node tree)
+      (cond
+       ((listp node)
+       (insert "\n")
+       (xml-debug-print-internal node (concat indent-string "  ")))
+       ((stringp node) (insert node))
+       (t
+       (error "Invalid XML tree"))))
+
+    (insert "\n" indent-string
+           "</" (symbol-name (xml-node-name xml)) ">")))
+
+(provide 'xml)
+
+;;; xml.el ends here
diff --git a/etc/Makefile.in b/etc/Makefile.in
new file mode 100644 (file)
index 0000000..8ef7da1
--- /dev/null
@@ -0,0 +1,60 @@
+datadir = @datadir@
+infodir = @infodir@
+prefix = @prefix@
+srcdir = @srcdir@
+subdir = etc
+top_srcdir = @top_srcdir@
+lispdir = @lispdir@
+etcdir = @etcdir@
+
+VPATH=$(srcdir)
+EMACS=@EMACS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+SHELL = /bin/sh
+
+all: 
+
+install: 
+       $(SHELL) $(top_srcdir)/mkinstalldirs $(etcdir)
+       cd $(srcdir) \
+       && for p in gnus-tut.txt; do \
+         echo " $(INSTALL_DATA) $$p $(etcdir)/$$p"; \
+         $(INSTALL_DATA) $$p $(etcdir)/$$p; \
+       done
+       $(SHELL) $(top_srcdir)/mkinstalldirs $(etcdir)/gnus
+       cd $(srcdir) \
+       && for p in gnus/*.xpm gnus/*.pbm gnus/*.xbm gnus/x-splash; do \
+         echo " $(INSTALL_DATA) $$p $(etcdir)/$$p"; \
+         $(INSTALL_DATA) $$p $(etcdir)/$$p; \
+       done
+       $(SHELL) $(top_srcdir)/mkinstalldirs $(etcdir)/smilies
+       cd $(srcdir) \
+       && for p in smilies/*.pbm smilies/*.xpm; do \
+         echo " $(INSTALL_DATA) $$p $(etcdir)/$$p"; \
+         $(INSTALL_DATA) $$p $(etcdir)/$$p; \
+       done
+
+uninstall: 
+       rm -f $(etcdir)/gnus-tut.txt
+       cd $(srcdir) \
+       && for p in gnus/*.xpm gnus/*.pbm gnus/*.xbm gnus/x-splash; do \
+         rm -f "$(etcdir)/$$p"; \
+       done
+       rmdir $(etcdir)/gnus 2> /dev/null || true
+       cd $(srcdir) \
+       && for p in smilies/*.pbm smilies/*.xpm; do \
+         rm -f "$(etcdir)/$$p"; \
+       done
+       rmdir $(etcdir)/smilies 2> /dev/null || true
+
+Makefile: $(srcdir)/Makefile.in ../config.status
+       cd .. \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+distclean:
+       rm -f *~ Makefile
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
index 94e9500..62d0d01 100644 (file)
@@ -22,7 +22,8 @@ people started.
 Gnus is a rewrite of GNUS 4.1, written by Masanobu Umeda.  The rewrite
 was done by moi, yours truly, your humble servant, Lars Magne
 Ingebrigtsen.  If you have a WWW browser, you can investigate to your
-heart's delight at <URL:http://www.ifi.uio.no/~larsi/larsi.html>.
+heart's delight at <URL:http://www.gnus.org/> and
+<URL:http://quimby.gnus.org/lmi/>.
 
 ;; Copyright (C) 1995 Free Software Foundation, Inc.
 
@@ -194,7 +195,7 @@ which are both faster and more accurated.
 
 There is absolutely no chance, whatsoever, of getting Gnus to work
 with Emacs 18.  It won't even work on Emacsen older than Emacs
-19.30/XEmacs 19.13.  Upgrade your Emacs or die.
+20.7/XEmacs 21.1.  Upgrade your Emacs or die.
 
        
 From lars Thu Feb 23 23:20:38 1995
@@ -222,7 +223,7 @@ want this is beyond me, but here goes:
 
 Create the group by saying
 
-`M-a my.virtual.newsgroup<RET>nnvirtual<RET>^rec\.aquaria\.*<RET>'
+`G V my.virtual.newsgroup<RET>nnvirtual<RET>^rec\.aquaria\.*<RET>'
 
 This will create the group "nnvirtual:my.virtual.newsgroup", which
 will collect all articles from all the groups in the "rec.aquaria"
@@ -292,3 +293,26 @@ If you have any questions on usage, the "ding@ifi.uio.no" mailing list
 is where to post the questions.
 
 
+From fschmitt Sat Mar 22 18:13:00 2003
+From: faq@my.gnus.org (Gnus FAQ team)
+Date: Sat Mar 22 18:13:00 2003
+Subject: Gnus FAQ (Frequently Asked Questions)
+Message-ID: <lars-doc9@eyesore.no>
+
+The Gnus FAQ is distributed within the Gnus manual.  The home page of
+the Gnus FAQ is <URL:http://my.gnus.org/FAQ/>, where you can find the
+most recent version in HTML various other formats.
+
+To browse the FAQ now, put the cursor at the end of the following line
+and press `C-x C-e':
+
+  (info "(gnus)Frequently Asked Questions")
+
+On older XEmacs version, use:
+
+  (Info-goto-node "(gnus)Frequently Asked Questions")
+  
+Or simply use RET or the middle mouse button, if the above is displayed
+as a clickable button.
+
+
diff --git a/etc/gnus/bar.xbm b/etc/gnus/bar.xbm
new file mode 100644 (file)
index 0000000..e61300a
--- /dev/null
@@ -0,0 +1,7 @@
+#define noname_width 6
+#define noname_height 48
+static char noname_bits[] = {
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,
+ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,
+ 0x0c,0x0c,0x0c};
diff --git a/etc/gnus/bar.xpm b/etc/gnus/bar.xpm
new file mode 100644 (file)
index 0000000..2985065
--- /dev/null
@@ -0,0 +1,54 @@
+/* XPM */
+static char * picon-bar_xpm[] = {
+"6 48 2 1",
+"      c white s background",
+".     c black",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  "};
diff --git a/etc/gnus/catchup.pbm b/etc/gnus/catchup.pbm
new file mode 100644 (file)
index 0000000..3fc571b
Binary files /dev/null and b/etc/gnus/catchup.pbm differ
diff --git a/etc/gnus/catchup.xpm b/etc/gnus/catchup.xpm
new file mode 100644 (file)
index 0000000..cba8497
--- /dev/null
@@ -0,0 +1,33 @@
+/* XPM */
+static char * catchup_xpm[] = {
+"24 24 6 1",
+"      c None",
+".     c #FFFFFFFFFFFF",
+"X     c #E1E1E0E0E0E0",
+"o     c #A5A5A5A59595",
+"O     c #999999999999",
+"+     c #000000000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"            .           ",
+"         .  .X          ",
+"       ...  .oX  .      ",
+"     ..oooX.oXo  .X     ",
+"    .oooXXXX..oXXoXX    ",
+"    .oXXXX.XoX.oXooX    ",
+"     X...X.X.XX.XoXX    ",
+"     Xo..X.XXX.XXXX     ",
+"   . Xo.oXX..XXXXXX     ",
+"OOOOXoXXXXXo.XXXXX++OOOO",
+"OOOOOX..X.XXXXXXXX++OOOO",
+"OOOOOX..XXXXXXXXX++OOOOO",
+"OOOOOOXXXXXXXXX+++OOOOOO",
+"OOOOOOOOOXXXX++++OOOOOOO",
+"OOOOOOOOO+++++OOOOOOOOOO",
+"OOOOOOOOOO+OOOOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOOOOOOOO"};
diff --git a/etc/gnus/cu-exit.pbm b/etc/gnus/cu-exit.pbm
new file mode 100644 (file)
index 0000000..210869c
Binary files /dev/null and b/etc/gnus/cu-exit.pbm differ
diff --git a/etc/gnus/cu-exit.xpm b/etc/gnus/cu-exit.xpm
new file mode 100644 (file)
index 0000000..1723622
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * cu_exit_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"           .....        ",
+"        .. .XXX.        ",
+"      ..X..XXXX...      ",
+"     .XXXX.XXXX.X...    ",
+"    ..XXXX.XXX.XXX..    ",
+"     .XXX..........     ",
+"     .XXX.XXX.XXX..     ",
+"      .XX.XXX.XXX.      ",
+"      .XX.XXX.XX..      ",
+"      ............      ",
+"       .X.X.X.X..       ",
+"ooooooo..........ooooooo",
+"ooooooo.X.X.X.X.oooooooo",
+"ooooooo.........oooooooo",
+"ooooooo..X...X..oooooooo",
+"ooooooo...X.X...oooooooo",
+"ooooooo........ooooooooo",
+"ooooooooo.....oooooooooo",
+"oooooooooooooooooooooooo"};
diff --git a/etc/gnus/describe-group.pbm b/etc/gnus/describe-group.pbm
new file mode 100644 (file)
index 0000000..de7bf11
Binary files /dev/null and b/etc/gnus/describe-group.pbm differ
diff --git a/etc/gnus/describe-group.xpm b/etc/gnus/describe-group.xpm
new file mode 100644 (file)
index 0000000..b4a6f42
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * describe_group_xpm[] = {
+"24 24 5 1",
+".     c None",
+"      c #000000000000",
+"o     c #FFFFF5F5ACAC",
+"+     c #E1E1E0E0E0E0",
+"@     c #C7C7C6C6C6C6",
+"........................",
+"........................",
+".................oooo...",
+" .. .. .. .. .. oo oo o.",
+"..............oooooooooo",
+".............ooooooooooo",
+" .. .. .. .. oo oo oo oo",
+"............oooooooooooo",
+"............oooooooooooo",
+" .. .. .. .. oo oo oo oo",
+"............oooooooooooo",
+"............oooooooooooo",
+" .. .. .. .. oo oo oo oo",
+"............oooooooooooo",
+".....    ...oooooooooooo",
+" ..   ++  .. .o oo oo oo",
+"...  @@@+  ....ooooooooo",
+"...     @  ....oooooooo.",
+" .         . .. .. .. ..",
+".         ..............",
+"        ................",
+"       .. .. .. .. .. ..",
+"      ..................",
+"    ...................."};
diff --git a/etc/gnus/exit-gnus.pbm b/etc/gnus/exit-gnus.pbm
new file mode 100644 (file)
index 0000000..32ad0e0
Binary files /dev/null and b/etc/gnus/exit-gnus.pbm differ
diff --git a/etc/gnus/exit-gnus.xpm b/etc/gnus/exit-gnus.xpm
new file mode 100644 (file)
index 0000000..534f3c2
--- /dev/null
@@ -0,0 +1,33 @@
+/* XPM */
+static char * exit_gnus_xpm[] = {
+"24 24 6 1",
+"      c None",
+".     c #8686ADAD7D7D",
+"X     c #919187876969",
+"o     c #C2C2B9B99C9C",
+"O     c #A8A8F0F0ECEC",
+"+     c #EFEFEFEFEFEF",
+"                        ",
+"     ....  .            ",
+"        .. .. .         ",
+"  .............         ",
+"   . . . ....           ",
+"     .............      ",
+"  .............. ..     ",
+"  . . ..........  .     ",
+"      .XXXX... ..       ",
+"       o.XXX. . ..      ",
+"      oo.X. ..  ...     ",
+"     ooX. . ...         ",
+"     oXo.     ..        ",
+"    ooX      . .        ",
+"    ooX                 ",
+"OOOOoXXOOOOOOOOOOOOOOOOO",
+"OOOoXoXOOOOOOOOOOOOOOOOO",
+"OOOooXXOOOO+OOOOOOOOOOOO",
+"O+OoooXOO+OOO+OO+OOO+OOO",
+"OXXoXoXoXOO++O++OO++OO+O",
+"XXXXXXXXXXXX+OOOOOOOOOOO",
+"XXXXXXXXXXXXXX+O++OO++OO",
+"XXXXXXXXXXXXXXXXOOOOOOOO",
+"O++O++++O+OO++OOOO++OOO+"};
diff --git a/etc/gnus/exit-summ.pbm b/etc/gnus/exit-summ.pbm
new file mode 100644 (file)
index 0000000..d019231
Binary files /dev/null and b/etc/gnus/exit-summ.pbm differ
diff --git a/etc/gnus/exit-summ.xpm b/etc/gnus/exit-summ.xpm
new file mode 100644 (file)
index 0000000..5234ccb
--- /dev/null
@@ -0,0 +1,30 @@
+/* XPM */
+static char * exit_summ_xpm[] = {
+"24 24 3 1",
+".     c None",
+"      c #000000000000",
+"X     c #E1E1E0E0E0E0",
+" .. .. .. .. .. .. .. ..",
+"........................",
+"........................",
+" .. ..             .. ..",
+"......  XXXX       .....",
+"......  XXXXXXX    .....",
+" .. .. XX XX XX    .. ..",
+"...... XXXXXXXX    .....",
+"......  XXXXXXX    .....",
+" .. ..  X XX       .. ..",
+"......  XXXX       .....",
+"......  XXXX       .....",
+" .. ..  X XXXXX    .. ..",
+"......  XXXXXXX    .....",
+"...... XXXXX XX    .....",
+" .. ..  X XXXXX    .. ..",
+"......  XXXXX      .....",
+"......  X          .....",
+" .. . .            .. ..",
+"........................",
+"........................",
+" .. .. .. .. .. .. .. ..",
+"........................",
+"........................"};
diff --git a/etc/gnus/followup.pbm b/etc/gnus/followup.pbm
new file mode 100644 (file)
index 0000000..61be114
Binary files /dev/null and b/etc/gnus/followup.pbm differ
diff --git a/etc/gnus/followup.xpm b/etc/gnus/followup.xpm
new file mode 100644 (file)
index 0000000..444895a
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * followup_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #A5A5A5A59595",
+"X     c #C7C7C6C6C6C6",
+"o     c #E1E1E0E0E0E0",
+"                        ",
+"          .             ",
+"        ..X.            ",
+"      ..XXX.            ",
+"    ..XXXXXo.           ",
+" ...XXXXXXooo.  .       ",
+" .o.XXXXXooooo..X.      ",
+" .oo.XXXoooo..XXX.      ",
+" .oo..Xooo..XXXXXo.     ",
+" .oo.XX...XXXXXXooo.    ",
+" .o.Xoo.o.XXXXXoooo.    ",
+"  .XXoo.oo.XXXoooooo.   ",
+"  .Xooo.oo..XXooooooo.  ",
+"   .ooo.oo.XXooooooooo. ",
+"   .ooo.o.XoooooooooooX.",
+"    .ooo.XXoooooooooooo.",
+"    .ooo.Xoooooooooooo. ",
+"     .ooo.ooooooooooo.  ",
+"     .oo..oooooooooo.   ",
+"      ..  .ooooooo..    ",
+"          .oooooo.      ",
+"           .ooo..       ",
+"           .oo.         ",
+"            ..          "};
diff --git a/etc/gnus/fuwo.pbm b/etc/gnus/fuwo.pbm
new file mode 100644 (file)
index 0000000..b81af10
Binary files /dev/null and b/etc/gnus/fuwo.pbm differ
diff --git a/etc/gnus/fuwo.xpm b/etc/gnus/fuwo.xpm
new file mode 100644 (file)
index 0000000..362cbc5
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * fuwo_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #A5A5A5A59595",
+"X     c #C7C7C6C6C6C6",
+"o     c #E1E1E0E0E0E0",
+"                        ",
+"          .             ",
+"        .. .            ",
+"      ..   .            ",
+"    ..      .           ",
+" ...         .  .       ",
+" . .          ..X.      ",
+" .  .       ..XXX.      ",
+" .  ..    ..XXXXXo.     ",
+" .  .  ...XXXXXXooo.    ",
+" . .X  .o.XXXXXoooo.    ",
+"  .XX  .oo.XXXoooooo.   ",
+"  .X   .oo..XXooooooo.  ",
+"   .   .oo.XXooooooooo. ",
+"   .   .o.XoooooooooooX.",
+"    .   .XXoooooooooooo.",
+"    .   .Xoooooooooooo. ",
+"     .   .ooooooooooo.  ",
+"     .  ..oooooooooo.   ",
+"      ..  .ooooooo..    ",
+"          .oooooo.      ",
+"           .ooo..       ",
+"           .oo.         ",
+"            ..          "};
diff --git a/etc/gnus/get-news.pbm b/etc/gnus/get-news.pbm
new file mode 100644 (file)
index 0000000..c008071
Binary files /dev/null and b/etc/gnus/get-news.pbm differ
diff --git a/etc/gnus/get-news.xpm b/etc/gnus/get-news.xpm
new file mode 100644 (file)
index 0000000..d7e7b4a
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * get_news_xpm[] = {
+"24 24 4 1",
+".     c None",
+"X     c #A5A5A5A59595",
+"o     c #E1E1E0E0E0E0",
+"O     c #C7C7C6C6C6C6",
+"........................",
+"........................",
+"........................",
+".....XXX................",
+"...XXoooXXXXX...........",
+"XXXoooooXXoooX.XXX......",
+"XoXooXXXooooXXXoooX.....",
+"XooXoXoXooXXXoooooX.....",
+"XooXXXooXoXoXooooooX....",
+"XooXOXooXXXooXooooooX...",
+"XoXOOXooXOXooXXooooooX..",
+"OXOOOXoXOOXooXoooooooX..",
+"OXOooOXOOOXoXOooooooooX.",
+".OXooOXOooOXOOooooooooX.",
+".OXoooOXooOXOooooooooooX",
+"..OXooOXoooOXooooooooooX",
+"..OXooOOXooOXooooooooooX",
+"...OXooOXoooOXoooooooXXX",
+"...OXooXOXooOXooooooXOO.",
+"....OXXOOXooXOXoooXXO...",
+".....OO..OXXOOXooXOO....",
+"..........OO..OXXO......",
+"...............OO.......",
+"........................"};
diff --git a/etc/gnus/gnntg.pbm b/etc/gnus/gnntg.pbm
new file mode 100644 (file)
index 0000000..2f5e526
Binary files /dev/null and b/etc/gnus/gnntg.pbm differ
diff --git a/etc/gnus/gnntg.xpm b/etc/gnus/gnntg.xpm
new file mode 100644 (file)
index 0000000..21bc5f1
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * gnntg_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #C7C7C6C6C6C6",
+"                        ",
+" .......                ",
+" .XXXXX.                ",
+" .XXXXX.       ...      ",
+" .XXXXX...    .ooo.     ",
+" .XXXXX....  ..ooo..    ",
+" .XXXXX..o.. ..ooo..    ",
+" .XXXXX...o.. ..o..     ",
+" .XXXXX. ..o........    ",
+" .XXXXX.  ..oooooooo.   ",
+" .......   .oooooooo..  ",
+"            .ooooo..o.  ",
+"             .oooo..o.  ",
+"             .oooo..o.  ",
+"             .oooo..o.  ",
+"             .oooo..o.  ",
+"             .........  ",
+"            ......oo.   ",
+"            .ooooo...   ",
+"            .oo..o...   ",
+"            .oo..o..    ",
+"            ........    ",
+"            .... ...    ",
+"            ...  ...    "};
diff --git a/etc/gnus/gnus-group-catchup-current-up.xbm b/etc/gnus/gnus-group-catchup-current-up.xbm
new file mode 100644 (file)
index 0000000..f801fea
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x20,0x40,0x10,0x20,0x0a,0x15,0x85,0x0a,0x20,0x20,0x28,0x50,0x8a,0x8a,0x02,
+ 0x05,0x10,0x5e,0x54,0xa8,0xa5,0x35,0x01,0x7a,0x00,0x33,0x54,0x95,0xaa,0xaa,
+ 0x02,0xcc,0xfe,0x17,0xa8,0xd8,0x01,0xac,0xfa,0x4f,0x3d,0xf8,0x05,0x30,0x22,
+ 0x80,0xf6,0x60,0x2b,0xfc,0x8f,0x20,0x11,0x82,0xca,0x60,0x1a,0x2a,0x6e,0x28,
+ 0x08,0x85,0x42,0x68,0xfa,0x11,0x28,0xc8,0x04,0x8b,0xe2,0xb7,0x06,0x21,0x14,
+ 0xd4,0x1a,0x11,0x31,0x04,0x31,0x56,0x6d,0xdc,0x58,0xea,0xc7,0x28,0x64,0x66,
+ 0x60,0xa9,0x57,0x72,0x90,0x49,0xc8,0xec,0x5f,0x99,0xa6,0x7f,0x95,0x52,0xaa,
+ 0x64,0x22,0xbf,0x49,0x2a,0xa9,0x7e,0x92,0x52,0x55,0x55,0x54,0x49,0x4a,0xa4,
+ 0x49,0xaa,0xa4,0x4a,0x2a,0x49,0x2a,0x25};
diff --git a/etc/gnus/gnus-group-catchup-current-up.xpm b/etc/gnus/gnus-group-catchup-current-up.xpm
new file mode 100644 (file)
index 0000000..0504f9d
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"         ....                   ",
+"        .XXXX.             .... ",
+"        .XXXX.            .XXXX.",
+"         .XXX.            .XXXX.",
+" .........XX.              .XXX.",
+".ooooooooo..       .........XX. ",
+".o....ooooo...... .ooooooooo..  ",
+"X.   .ooooooooo.X..o....ooooo.  ",
+"X.   .oooo........X.   .ooooo.  ",
+".   .oooo.       .X.   .ooooo.  ",
+"    .oooo.       ..   .oooo.o.  ",
+"   .oooo.             .oooo.o.  ",
+"   ......            .ooooo.oo..",
+"  .ooooo.            ...... ..X.",
+"  .ooooo.           .ooooo.   ..",
+" .o..ooo.           ..oooo.     ",
+".ooo..ooo.XXXXXXXXX.o..ooo.XXXXX",
+"ooo.XX.oo.XXX......ooo..ooo.XXXX",
+"oo.XXX.oo.XXX..oooooo.XX.oo.XXXX",
+"..XXXX.oo.XXX..ooooo.XXX.oo.XXXX",
+"XXXXXXX.oo.XX.......XXX .oo.XXXX",
+"XXXXXXX.....X..XXXXXXXXXX.oo.XXX",
+"XXXXXXXXXXXXX.XXXXXXXXXXX.....XX",
+"XXXXXXXXXXXXXXXXXXXXXXXXX......X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/etc/gnus/gnus-group-catchup-current.xbm b/etc/gnus/gnus-group-catchup-current.xbm
new file mode 100644 (file)
index 0000000..2218640
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x84,0x20,0x00,0x04,0x21,0x88,0x54,0x51,0x84,0x22,0x02,0x04,0x51,0x88,0xa0,
+ 0x42,0x04,0x1f,0x0a,0x28,0x51,0x75,0xa1,0x7a,0x04,0x23,0x04,0xcc,0xa1,0x76,
+ 0xa9,0xa6,0xfe,0x1b,0x00,0xd8,0x01,0x0c,0xfd,0x5f,0x3d,0xf8,0x05,0x30,0x26,
+ 0x80,0xf7,0x60,0x33,0xfc,0xdb,0x20,0x11,0x22,0x8e,0x20,0x14,0x8a,0x66,0x68,
+ 0x09,0x45,0x48,0x28,0xfc,0x11,0x21,0xc8,0x04,0x45,0xf4,0xf7,0x06,0x89,0x10,
+ 0xc4,0x1a,0x23,0x35,0x2c,0x31,0xaa,0x6c,0x54,0x58,0xea,0xc7,0x48,0x64,0x66,
+ 0xa0,0x99,0x57,0x72,0x50,0x59,0xc8,0xec,0x2f,0x49,0xa6,0x7f,0xaa,0x52,0xaa,
+ 0x64,0x49,0xbf,0x49,0x2a,0xa5,0x7e,0x92,0xa4,0x14,0x55,0xa9,0x52,0xaa,0x92,
+ 0x4a,0xa5,0x24,0x25,0xa5,0x94,0xaa,0xa8};
diff --git a/etc/gnus/gnus-group-catchup-current.xpm b/etc/gnus/gnus-group-catchup-current.xpm
new file mode 100644 (file)
index 0000000..bea4643
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"         ....                   ",
+"        .XXXX.             .... ",
+"        .XXXX.            .XXXX.",
+"         .XXX.            .XXXX.",
+" .........XX.              .XXX.",
+".ooooooooo..       .........XX. ",
+".o....ooooo...... .ooooooooo..  ",
+"X.   .ooooooooo.X..o....ooooo.  ",
+"X.   .oooo........X.   .ooooo.  ",
+".   .oooo.       .X.   .ooooo.  ",
+"    .oooo.       ..   .oooo.o.  ",
+"   .oooo.             .oooo.o.  ",
+"   ......            .ooooo.oo..",
+"  .ooooo.            ...... ..X.",
+"  .ooooo.           .ooooo.   ..",
+" .o..ooo.           ..oooo.     ",
+".ooo..ooo.XXXXXXXXX.o..ooo.XXXXX",
+"ooo.XX.oo.XXX......ooo..ooo.XXXX",
+"oo.XXX.oo.XXX..oooooo.XX.oo.XXXX",
+"..XXXX.oo.XXX..ooooo.XXX.oo.XXXX",
+"XXXXXXX.oo.XX.......XXX .oo.XXXX",
+"XXXXXXX.....X..XXXXXXXXXX.oo.XXX",
+"XXXXXXXXXXXXX.XXXXXXXXXXX.....XX",
+"XXXXXXXXXXXXXXXXXXXXXXXXX......X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/etc/gnus/gnus-group-describe-group-up.xbm b/etc/gnus/gnus-group-describe-group-up.xbm
new file mode 100644 (file)
index 0000000..0054d63
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x55,0xb5,0x55,0xb5,0xaa,0x12,0xa9,0x12,0x12,0x55,0x12,0x65,0xa9,0xa4,0x4a,
+ 0x10,0x55,0x9b,0x15,0xc1,0x55,0x51,0x09,0x00,0x92,0x4a,0x02,0x00,0xa9,0x24,
+ 0x01,0x00,0x55,0x5b,0x11,0x11,0x92,0xa4,0x00,0x00,0x2a,0x49,0x00,0x00,0x49,
+ 0x55,0x00,0x00,0x35,0x55,0x11,0x11,0xaa,0xaa,0x00,0x00,0x92,0x44,0x00,0x00,
+ 0xa5,0x32,0x00,0x00,0x55,0x55,0x11,0x11,0x29,0x55,0x01,0x00,0xaa,0x24,0x01,
+ 0x00,0x92,0x97,0x00,0x00,0x75,0xba,0x13,0x11,0x2a,0x51,0x04,0x00,0xb2,0xaa,
+ 0x0a,0x40,0x59,0x75,0x25,0x40,0xb5,0x3d,0x59,0xb5,0xfa,0x77,0xa5,0x2a,0xae,
+ 0x9a,0x2a,0x49,0xd6,0x5f,0x49,0xa5,0xf7,0x57,0x35,0x55,0x7d,0x29,0x95,0x2a,
+ 0x7e,0x55,0xa9,0x54,0x5f,0x92,0x94,0x92};
diff --git a/etc/gnus/gnus-group-describe-group-up.xpm b/etc/gnus/gnus-group-describe-group-up.xpm
new file mode 100644 (file)
index 0000000..e0ffde7
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-describe-group_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #999999999999 s backgroundToolBarColor",
+"X     c #FFFFFFFFFFFF",
+"o     c #BFBFBFBFBFBF",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".......................XXXXX....",
+" ... ... ... ... ... XXX XXXXX..",
+"....................XXXXXXXXXXX.",
+"...................XXXXXXXXXXXXX",
+"..................XXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+".................XXXXXXXXXXXXXXX",
+".................XXXXXXXXXXXXXXX",
+".......    .......XXXXXXXXXXXXXX",
+" ... . oooo  ... ..X XXX XXX XXX",
+"..... o...oo .......XXXXXXXXXXX.",
+".... .o....o. .......XXXXXXXXX..",
+".... o . ...  .........XXXXX....",
+" ...  o .. .  .. ... ... ... ...",
+"...  o   . .  ..................",
+"..  X . . .  ...................",
+".  o .   .  ....................",
+"   o       . ... ... ... ... ...",
+" o     .........................",
+"o .   ...o......................",
+"     ..........................."};
diff --git a/etc/gnus/gnus-group-exit-up.xbm b/etc/gnus/gnus-group-exit-up.xbm
new file mode 100644 (file)
index 0000000..c03e1fa
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x00,0x40,0x00,0x00,0x30,0x30,0x00,0x00,0x68,0x38,0x00,0x38,0x60,0x48,
+ 0x00,0xd4,0x91,0xde,0x07,0x68,0xcf,0xb7,0x1a,0x80,0xb4,0x6e,0x05,0x00,0xe2,
+ 0x07,0x00,0x00,0xde,0x1d,0x00,0xe0,0xfd,0x77,0x00,0xb0,0x6a,0xf3,0x00,0x20,
+ 0x9c,0xa5,0x03,0x00,0xaa,0x86,0x02,0x00,0x65,0x06,0x02,0xab,0x6f,0xaf,0x59,
+ 0x80,0x62,0x0c,0x00,0xaa,0xab,0xba,0x4a,0x40,0x21,0x10,0x10,0xea,0x45,0x4a,
+ 0x42,0x40,0x89,0x90,0x28,0xd2,0x21,0x02,0x82,0xa4,0x8a,0x44,0x20,0xf0,0x10,
+ 0x10,0x85,0xa4,0x04,0x4a,0x20,0xe2,0x22,0x80,0x80,0xbc,0x4b,0x09,0x2a,0xee,
+ 0x8e,0x32,0x80,0xeb,0x73,0x85,0x28,0x56,0xaa,0xb5,0x02,0xff,0xff,0x85,0x48,
+ 0x08,0x94,0x11,0x01,0x42,0x02,0x48,0x54};
diff --git a/etc/gnus/gnus-group-exit-up.xpm b/etc/gnus/gnus-group-exit-up.xpm
new file mode 100644 (file)
index 0000000..1b8982f
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-exit-gnus_xpm[] = {
+"32 32 4 1",
+"      c #FFFFFFFFFFFF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #BFBFBFBFBFBF",
+"                      .         ",
+"            ..      ..          ",
+"           . ..    ...          ",
+"   ...       ..    .  .         ",
+"  . . ...   .  . .... .....     ",
+"   . .. ....  ..... .. . . ..   ",
+"       .  . .. . ... .. . .     ",
+"         .   ......             ",
+"         .... ... ...           ",
+"     .... ......... ...         ",
+"    .. . . .X.. ..  ....        ",
+"     .    .X.  .. .  . ...      ",
+"         .X. . . ..    . .      ",
+"        .X.  ..  ..      .      ",
+".. . . ..X.. .. .... . ..  .. . ",
+"ooooooo.X.ooo..ooo..oo ooooooooo",
+"oooo oo.X.ooo.ooooo..oooooooo oo",
+"o oooo.X.ooooooo ooo.ooooooooooo",
+"oooooo.X.ooooooooooooooo ooooooo",
+"ooo oo.X.ooo ooooooooooooooooooo",
+"oooooo.X.oooooooooo  oooooo  ooo",
+"ooooo.X.ooooooooooooooo  ooooooo",
+"o ooo.X.oooooo ooooooooooooooooo",
+"ooooo.X.oooo  o  ooooooooo ooooo",
+"ooooo.X.ooooooooooo oooo  o  ooo",
+"oo....X...ooooooo  o  oooooooooo",
+"o..XX...XX..ooo.o.oo.oo oooooooo",
+".XX.XX..X.XX...ooo.oo  o  oooooo",
+"X.XX.XXXXXXXXXX..oooo.o.oooooo o",
+".................o.o oo.oooo  o ",
+"oooooo ooo.oo oo.o  .  ooooooooo",
+"oooo  o  oo  o  oooooooooooooooo"};
diff --git a/etc/gnus/gnus-group-get-new-news-this-group-up.xbm b/etc/gnus/gnus-group-get-new-news-this-group-up.xbm
new file mode 100644 (file)
index 0000000..2f354f4
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x20,0x00,0x40,0x88,0xff,0x57,0x15,0x22,0x02,0x0c,0xa0,0x88,0x02,0xa4,0x0a,
+ 0x22,0x02,0x04,0xf0,0x84,0x03,0x54,0xdd,0x21,0x02,0x1e,0x14,0x97,0x02,0x66,
+ 0xcd,0x02,0x02,0x7c,0x14,0x2b,0x03,0x9c,0xad,0x41,0x02,0x54,0xb1,0x0a,0x02,
+ 0x2c,0xff,0x47,0x02,0xe4,0x14,0x2d,0xff,0x4f,0xa5,0x0a,0x48,0xa0,0x4a,0xb4,
+ 0x12,0x0a,0x51,0x1b,0x40,0xa1,0x96,0x36,0x2a,0x10,0x4a,0x56,0x80,0x4a,0x57,
+ 0x1b,0x55,0x00,0x92,0x52,0x00,0x55,0x26,0x17,0xa9,0x00,0xab,0x5a,0x04,0x2a,
+ 0xfe,0x1f,0x41,0x41,0xcb,0x48,0x14,0x14,0x95,0x2f,0x82,0x42,0x53,0x09,0x28,
+ 0x08,0xa5,0xaf,0x84,0xa2,0x75,0x06,0x12,0x04,0xd3,0x54,0x40,0x51,0xdf,0x0f,
+ 0x0a,0x82,0xae,0x23,0xa0,0x28,0x8a,0x4a};
diff --git a/etc/gnus/gnus-group-get-new-news-this-group-up.xpm b/etc/gnus/gnus-group-get-new-news-this-group-up.xpm
new file mode 100644 (file)
index 0000000..918fd2e
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-get-new-news-this-group_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" ..........                     ",
+" .XXXXXXXX.                     ",
+" .XXXXXXXX.                     ",
+" .XXXXXXXX.         ....        ",
+" .XXXXXXXX.        .oooo.       ",
+" .XXXXXXX....     .oooooo.      ",
+" .XXXXXXX..  .    .oooooo.      ",
+" .XXXXXXXX...o.   .oooooo.      ",
+" .XXXXXXXX..ooo.   .oooo.       ",
+" .XXXXXXXX. .ooo.   .oo.        ",
+" .XXXXXXXX.  .ooo.....o....     ",
+" .XXXXXXXX.   .oooooooooooo.    ",
+" ..........   .oooooooooooo.    ",
+"               .oooooooooooo.   ",
+"                .oooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 ............   ",
+"                .oooooo.   .    ",
+"                .ooooooo.. .    ",
+"                .ooooooo.  .    ",
+"                .oooo.oo...     ",
+"                .oooo.oooo.     ",
+"                .ooo. .ooo.     ",
+"                ..... .....     ",
+"                 .o.   .o.      ",
+"                 .o.   .o.      "};
diff --git a/etc/gnus/gnus-group-get-new-news-up.xbm b/etc/gnus/gnus-group-get-new-news-up.xbm
new file mode 100644 (file)
index 0000000..bea7a56
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x81,0x00,0x08,0xff,0x2b,0xa8,0x42,0x01,0x42,0x05,0x14,0x01,0x16,0x50,
+ 0x41,0x01,0xa2,0x7a,0x0a,0x01,0x0a,0xcc,0x40,0x01,0xaf,0x92,0x15,0x01,0x13,
+ 0x56,0x43,0x01,0xbe,0x2a,0x09,0x01,0x6e,0xcc,0x52,0x01,0xca,0x69,0x80,0x01,
+ 0x32,0xdf,0x2b,0x01,0x66,0x55,0x85,0xff,0x33,0xa9,0x2e,0x24,0xc9,0x92,0x88,
+ 0x09,0x82,0x4a,0x2e,0xa0,0x28,0xfd,0xf9,0x14,0x42,0x07,0x8d,0x42,0x08,0x85,
+ 0x8d,0x20,0x52,0x87,0x85,0x8a,0x80,0x45,0x86,0x20,0x2a,0xc7,0x82,0x8a,0x00,
+ 0xe7,0x82,0x41,0xd4,0x15,0x81,0x14,0x81,0xe6,0x81,0x81,0xa8,0x3d,0xff,0x14,
+ 0x82,0xfa,0x02,0x42,0xd1,0x52,0x57,0x08,0x8a,0xad,0x82,0xa2,0xa0,0xef,0x2b,
+ 0x04,0x05,0x55,0x81,0x51,0x50,0xc7,0x2b};
diff --git a/etc/gnus/gnus-group-get-new-news-up.xpm b/etc/gnus/gnus-group-get-new-news-up.xpm
new file mode 100644 (file)
index 0000000..d324784
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-get-new-news_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"..........                      ",
+".XXXXXXXX.                      ",
+".XXXXXXXX.                      ",
+".XXXXXXXX.         ....         ",
+".XXXXXXXX.        .oooo.        ",
+".XXXXXXX....     .oooooo.       ",
+".XXXXXXX..  .    .oooooo.       ",
+".XXXXXXXX...o.   .oooooo.       ",
+".XXXXXXXX..ooo.   .oooo.        ",
+".XXXXXXXX. .ooo.   .oo.         ",
+".XXXXXXXX.  .ooo.....o....      ",
+".XXXXXXXX.   .oooooooooooo.     ",
+"..........   .oooooooooooo.     ",
+"              .oooooooooooo.    ",
+"               .ooooooooooo.    ",
+"                .o.......oo.....",
+"                .o.XXXXX.oo.XXX.",
+"                .o.XXXX.ooo.XXX.",
+"                .o.XXXX.oo.XXXX.",
+"                .o.XXX.ooo.XXXX.",
+"                .o.XXX.oo.XXXXX.",
+"                ...XX...o.XXXXX.",
+"               .oo.X.   .XXXXXX.",
+"               .oo.XX.. .XXXXXX.",
+"               .oo....  ........",
+"               .oooo.o..o.      ",
+"               .oooo.oooo.      ",
+"               .ooo. .ooo.      ",
+"               ..... .....      ",
+"                .o.   .o.       ",
+"                .o.   .o.       "};
diff --git a/etc/gnus/gnus-group-kill-group-up.xbm b/etc/gnus/gnus-group-kill-group-up.xbm
new file mode 100644 (file)
index 0000000..8c3526d
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x04,0x20,0x20,0x54,0xa1,0x0a,0x4a,0x02,0x0a,0x50,0x01,0xa0,0x40,0x05,
+ 0x54,0xca,0xff,0x7f,0x00,0x50,0x00,0x60,0x55,0x42,0x00,0xa0,0x80,0x68,0xc0,
+ 0x21,0x2b,0x42,0xe0,0xe3,0x83,0x50,0xb0,0x06,0x2a,0x4a,0xf0,0x07,0x42,0x60,
+ 0x70,0x07,0x16,0x42,0xe0,0x03,0x42,0x68,0x40,0x01,0x2a,0x42,0x40,0x01,0x82,
+ 0x50,0xc8,0x05,0x2a,0x4a,0x0c,0x0c,0x82,0x60,0x30,0x03,0x2a,0x4a,0xc0,0x00,
+ 0x82,0x40,0xc0,0x00,0x2a,0x6a,0x30,0x03,0x42,0x41,0x0c,0x0c,0x16,0x54,0x08,
+ 0x04,0x22,0x41,0x00,0x00,0x4a,0x54,0x00,0x00,0x02,0x41,0x00,0x00,0x56,0x54,
+ 0x00,0x00,0x02,0x42,0x00,0x00,0x52,0xe8,0xff,0xff,0x0b,0x04,0x84,0x00,0x42,
+ 0x52,0x11,0xaa,0x28,0x00,0xa4,0x04,0x04};
diff --git a/etc/gnus/gnus-group-kill-group-up.xpm b/etc/gnus/gnus-group-kill-group-up.xpm
new file mode 100644 (file)
index 0000000..e728bf5
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-killfile_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXXXXXXXX..         ",
+"      .XXXXXXXXXXXXXX.X.        ",
+"      .XXXXXXX...XXXX.XX.       ",
+"      .XXXXXX.....XXX.....      ",
+"      .XXXXX..X.X..XXXXXX.      ",
+"      .XXXXX.......XXXXXX.      ",
+"      .XXXXX...X...XXXXXX.      ",
+"      .XXXXXX.....XXXXXXX.      ",
+"      .XXXXXXX.X.XXXXXXXX.      ",
+"      .XXXXXXX.X.XXXXXXXX.      ",
+"      .XXXX.XX...X.XXXXXX.      ",
+"      .XXX..XXXXXX..XXXXX.      ",
+"      .XXXXX..XX..XXXXXXX.      ",
+"      .XXXXXXX..XXXXXXXXX.      ",
+"      .XXXXXXX..XXXXXXXXX.      ",
+"      .XXXXX..XX..XXXXXXX.      ",
+"      .XXX..XXXXXX..XXXXX.      ",
+"      .XXXX.XXXXXX.XXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-group-subscribe-up.xbm b/etc/gnus/gnus-group-subscribe-up.xbm
new file mode 100644 (file)
index 0000000..98819e5
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x04,0x00,0x40,0x22,0x51,0x55,0x15,0x88,0x04,0x00,0x20,0x22,0xa0,0xaa,
+ 0x4a,0xc4,0xff,0x3f,0x00,0x61,0x80,0x60,0x55,0x54,0x8a,0xa0,0x80,0x42,0x84,
+ 0x20,0x2b,0x68,0x8a,0xe0,0x83,0x42,0x80,0x00,0x2a,0xd4,0xff,0x00,0x42,0x41,
+ 0x80,0x00,0x16,0x54,0x8a,0x00,0x42,0x41,0x84,0x00,0x2a,0x54,0x8a,0x00,0x82,
+ 0x41,0x80,0x00,0x2a,0xd4,0xff,0x00,0x82,0x42,0x80,0x00,0x2a,0x68,0x8a,0x00,
+ 0x82,0x44,0x84,0x00,0x2a,0x52,0x8a,0x00,0x42,0x40,0x80,0x00,0x16,0xea,0xff,
+ 0x00,0x22,0x40,0x80,0x00,0x4a,0x4a,0x80,0x00,0x02,0x61,0x80,0x00,0x56,0x44,
+ 0x80,0x00,0x02,0x51,0x80,0x00,0x52,0xc4,0xff,0xff,0x0b,0xa1,0x04,0x00,0x42,
+ 0x14,0xa8,0xaa,0x88,0x82,0x02,0x00,0x22};
diff --git a/etc/gnus/gnus-group-subscribe-up.xpm b/etc/gnus/gnus-group-subscribe-up.xpm
new file mode 100644 (file)
index 0000000..15f7d43
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-unsubscribe_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXX.XXXXX..         ",
+"      .XX.X.XXX.XXXXX.X.        ",
+"      .XXX.XXXX.XXXXX.XX.       ",
+"      .XX.X.XXX.XXXXX.....      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-group-unsubscribe-up.xbm b/etc/gnus/gnus-group-unsubscribe-up.xbm
new file mode 100644 (file)
index 0000000..9edc6b8
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x04,0x00,0x40,0x22,0x51,0x55,0x15,0x88,0x04,0x00,0x20,0x22,0xa0,0xaa,
+ 0x4a,0xc4,0xff,0x3f,0x00,0x61,0x80,0x60,0x55,0x54,0xa0,0xa0,0x80,0x42,0x90,
+ 0x20,0x2b,0x68,0x8a,0xe0,0x83,0x42,0x84,0x00,0x2a,0xd4,0xff,0x00,0x42,0x41,
+ 0x80,0x00,0x16,0x54,0xa0,0x00,0x42,0x41,0x90,0x00,0x2a,0x54,0x8a,0x00,0x82,
+ 0x41,0x84,0x00,0x2a,0xd4,0xff,0x00,0x82,0x42,0x80,0x00,0x2a,0x68,0xa0,0x00,
+ 0x82,0x44,0x90,0x00,0x2a,0x52,0x8a,0x00,0x42,0x40,0x84,0x00,0x16,0xea,0xff,
+ 0x00,0x22,0x40,0x80,0x00,0x4a,0x4a,0x80,0x00,0x02,0x61,0x80,0x00,0x56,0x44,
+ 0x80,0x00,0x02,0x51,0x80,0x00,0x52,0xc4,0xff,0xff,0x0b,0xa1,0x04,0x00,0x42,
+ 0x14,0xa8,0xaa,0x88,0x82,0x02,0x00,0x22};
diff --git a/etc/gnus/gnus-group-unsubscribe-up.xpm b/etc/gnus/gnus-group-unsubscribe-up.xpm
new file mode 100644 (file)
index 0000000..7c7ce5b
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-subscribe_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXX.XXXXX..         ",
+"      .XXXXXX.X.XXXXX.X.        ",
+"      .XXXXX.XX.XXXXX.XX.       ",
+"      .XX.X.XXX.XXXXX.....      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXX.X.XXXXXXXXX.      ",
+"      .XXXXX.XX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXX.X.XXXXXXXXX.      ",
+"      .XXXXX.XX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-pointer.xbm b/etc/gnus/gnus-pointer.xbm
new file mode 100644 (file)
index 0000000..94e9154
--- /dev/null
@@ -0,0 +1,6 @@
+#define noname_width 18
+#define noname_height 13
+static char noname_bits[] = {
+ 0x00,0x00,0x00,0xc0,0x0c,0x00,0xe0,0x1f,0x00,0x92,0x39,0x00,0x0e,0x71,0x02,
+ 0x46,0xe0,0x03,0x20,0xc0,0x01,0x00,0x08,0x00,0x10,0x0d,0x00,0xc4,0x08,0x00,
+ 0x78,0x08,0x00,0x18,0x89,0x00,0x00,0x08,0x00};
diff --git a/etc/gnus/gnus-pointer.xpm b/etc/gnus/gnus-pointer.xpm
new file mode 100644 (file)
index 0000000..c47443d
--- /dev/null
@@ -0,0 +1,22 @@
+/* XPM */
+static char *gnus-pointer[] = {
+/* width height num_colors chars_per_pixel */
+"    18    13        2            1",
+/* colors */
+". c #0000ff",
+"# c None s None",
+/* pixels */
+"##################",
+"######..##..######",
+"#####........#####",
+"#.##.##..##...####",
+"#...####.###...##.",
+"#..###.######.....",
+"#####.########...#",
+"###########.######",
+"####.###.#..######",
+"######..###.######",
+"###....####.######",
+"###..######.######",
+"###########.######"
+};
\ No newline at end of file
diff --git a/etc/gnus/gnus-summary-caesar-message-up.xbm b/etc/gnus/gnus-summary-caesar-message-up.xbm
new file mode 100644 (file)
index 0000000..0de8759
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x40,0x40,0x10,0x01,0x15,0x15,0x45,0x50,0x40,0x40,0x08,0x05,0x14,0x14,0xa2,
+ 0x50,0xe2,0xff,0x3f,0x82,0x48,0x00,0xe0,0x28,0x62,0xe6,0xb8,0x82,0x48,0x29,
+ 0x25,0x29,0x62,0xa9,0xe4,0x83,0x48,0x2f,0x05,0x2a,0x42,0xe9,0x38,0x42,0x60,
+ 0x00,0x00,0x16,0x4a,0x82,0x10,0x22,0x50,0x00,0x00,0x4a,0x42,0xcb,0x1c,0x02,
+ 0x68,0x2b,0x25,0x56,0x42,0x2d,0x1d,0x02,0x50,0x2d,0x05,0x52,0x4a,0xc9,0x04,
+ 0x0a,0x40,0x00,0x00,0x42,0x6a,0x18,0x00,0x16,0x41,0x3c,0x00,0x42,0x54,0xe6,
+ 0x3f,0x0a,0x41,0xe6,0x3f,0x52,0x54,0x3c,0x2a,0x06,0x42,0x18,0x2a,0x42,0x68,
+ 0x00,0x08,0x2a,0x44,0x00,0x00,0x06,0xd2,0xff,0xff,0x53,0x20,0x84,0x20,0x04,
+ 0x8a,0x10,0x8a,0xa8,0x20,0x4a,0x21,0x02};
diff --git a/etc/gnus/gnus-summary-caesar-message-up.xpm b/etc/gnus/gnus-summary-caesar-message-up.xpm
new file mode 100644 (file)
index 0000000..6f56aa9
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-rot13_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXXXXXXXX..         ",
+"      .XX..XX...XXX...X.        ",
+"      .X.XX.X.XX.X.XX.XX.       ",
+"      .X.XX.X.X.XX.XX.....      ",
+"      .X....X.XX.X.XXXXXX.      ",
+"      .X.XX.X...XXX...XXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XX.XXXXX.XXXX.XXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .X..X.XX..XX...XXXX.      ",
+"      .X..X.X.XX.X.XX.XXX.      ",
+"      .X.X..X.XX.X...XXXX.      ",
+"      .X.X..X.XX.X.XXXXXX.      ",
+"      .X.XX.XX..XX.XXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXX..XXXXXXXXXXXX.      ",
+"      .XXX....XXXXXXXXXXX.      ",
+"      .XX..XX.........XXX.      ",
+"      .XX..XX.........XXX.      ",
+"      .XXX....XXX.X.X.XXX.      ",
+"      .XXXX..XXXX.X.X.XXX.      ",
+"      .XXXXXXXXXXXX.XXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-cancel-article-up.xbm b/etc/gnus/gnus-summary-cancel-article-up.xbm
new file mode 100644 (file)
index 0000000..e8d8d68
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x11,0x11,0x01,0x11,0x54,0x4a,0xa9,0x52,0x82,0x10,0x04,0x08,0x28,0x24,0xa1,
+ 0x42,0x91,0x91,0x0f,0x19,0x25,0xaa,0xa9,0x44,0x88,0x60,0x18,0x11,0x42,0x1c,
+ 0x56,0x44,0x19,0x07,0x97,0x31,0x44,0x01,0x23,0x0a,0x12,0x81,0x60,0x50,0x80,
+ 0x02,0x42,0x05,0x3b,0x05,0x78,0x59,0x00,0x0a,0x56,0x12,0xaa,0xf4,0x05,0x41,
+ 0x00,0x54,0x51,0x10,0x5b,0x51,0x95,0x55,0x10,0x15,0x00,0x11,0x42,0x40,0x55,
+ 0x44,0x10,0x2a,0x00,0x21,0x5b,0x91,0x5b,0x95,0x80,0x24,0x00,0x21,0x12,0x92,
+ 0x2a,0x14,0x44,0x01,0x80,0x42,0x11,0xb5,0x35,0x19,0x54,0x11,0x08,0x42,0x02,
+ 0x44,0xa1,0x08,0xa8,0x22,0x14,0x52,0x11,0x99,0x51,0x11,0x4a,0x22,0x14,0x4a,
+ 0x20,0x89,0x42,0x10,0x15,0x40,0x20,0x45};
diff --git a/etc/gnus/gnus-summary-cancel-article-up.xpm b/etc/gnus/gnus-summary-cancel-article-up.xpm
new file mode 100644 (file)
index 0000000..fa7c639
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-cancel-post_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+" ... ... ... ... ....... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ...    .... ... ...",
+"...............  XX ............",
+".............  XXXX  ...........",
+"...........  XXXX  X ...........",
+" ... ....  XXXXX   X ... ... ...",
+"........ XXXXXXX  XXX ..........",
+"........ XXXXXX oXXXX ..........",
+"........o XXXXXXXoXXXX .........",
+" ... ...oo XXXXXXXX    . ... ...",
+".........oo XXXXX  oooo.........",
+"..........oo     o..............",
+"..........ooooooo...............",
+" ... ... ... oo. ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................"};
diff --git a/etc/gnus/gnus-summary-catchup-and-exit-up.xbm b/etc/gnus/gnus-summary-catchup-and-exit-up.xbm
new file mode 100644 (file)
index 0000000..4adec42
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x81,0x00,0x04,0x42,0x28,0x52,0x51,0x14,0x85,0x08,0x04,0x81,0x20,0x42,
+ 0x49,0x14,0x8a,0x08,0x20,0x41,0x21,0x52,0x15,0x14,0x44,0x00,0x40,0x41,0x91,
+ 0xbf,0x2a,0x14,0xda,0x10,0x80,0x81,0x94,0x90,0x2a,0x14,0x73,0xf0,0x80,0xe1,
+ 0x60,0x90,0x2b,0xc4,0x60,0x08,0x43,0xa2,0xf0,0x0f,0x15,0x88,0x11,0xfc,0x21,
+ 0xd2,0x11,0x8c,0x4a,0x80,0x12,0x84,0x00,0xd5,0x13,0x84,0x55,0x00,0x17,0x74,
+ 0x80,0x54,0xfb,0xcf,0x2a,0x02,0x9a,0x24,0x40,0x54,0x9f,0xbc,0x36,0xa9,0xf4,
+ 0x77,0x49,0x94,0x96,0x94,0xa4,0x25,0x95,0x35,0x15,0xa9,0xfe,0xbf,0xa4,0x92,
+ 0xdc,0x5c,0x29,0x4a,0x9e,0x3d,0x95,0xaa,0xfe,0x4f,0x52,0x24,0xf9,0xaf,0x4a,
+ 0xa9,0x52,0x91,0x94,0x25,0x29,0x55,0x52};
diff --git a/etc/gnus/gnus-summary-catchup-and-exit-up.xpm b/etc/gnus/gnus-summary-catchup-and-exit-up.xpm
new file mode 100644 (file)
index 0000000..a5d8ba6
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"               ......           ",
+"           ..  .XXXX.           ",
+"          .X.  .XXXX.           ",
+"        ..XX...XXXXX....        ",
+"      ..XXXXX..XXXXX.XX...      ",
+"      ..XXXXX..XXXX.XXXX..      ",
+"       .XXXX........XXXX.       ",
+"       ..XXX.XXXXX.......       ",
+"       ..XXX.XXXXX..XXX.        ",
+"       .X.XX.XXXXX.XXXX.        ",
+"       ...XX.XXXXX.XXXX.        ",
+"        ...X.XXXXX.X...         ",
+"         .X.........XX.         ",
+"         .  .XX.XX.XX.          ",
+"ooooooooo....XX.XX....oooooooooo",
+"oooooooooo. .......  .oooooooooo",
+"oooooooooo.X.XX.X .X.ooooooooooo",
+"oooooooooo. .X .  . .ooooooooooo",
+"oooooooooo...........ooooooooooo",
+"oooooooooo...X..XX...ooooooooooo",
+"oooooooooo...X ..X...ooooooooooo",
+"oooooooooo..........oooooooooooo",
+"oooooooooooo.......ooooooooooooo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/etc/gnus/gnus-summary-catchup-up.xbm b/etc/gnus/gnus-summary-catchup-up.xbm
new file mode 100644 (file)
index 0000000..ca093e1
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x11,0x91,0x11,0x95,0x54,0x25,0x54,0x21,0x02,0x90,0x00,0x84,0xa0,0x0a,0x54,
+ 0x29,0x1b,0xb1,0x11,0x91,0x40,0x0a,0x4a,0x25,0x8a,0xa0,0x20,0x88,0x20,0x14,
+ 0x0e,0x22,0x9b,0x51,0xb7,0x99,0x20,0x14,0x0b,0x02,0x42,0xc1,0x22,0x28,0x14,
+ 0x92,0x48,0x45,0x51,0x19,0x11,0x11,0x14,0x42,0xaa,0x54,0x42,0x88,0x00,0x02,
+ 0x90,0x72,0xaa,0x56,0x15,0x71,0x11,0x17,0x42,0x3a,0x49,0x4b,0x28,0x49,0xa4,
+ 0x22,0x04,0x30,0x02,0x09,0xb1,0xdb,0x59,0xb5,0x15,0xa0,0xd3,0xff,0x40,0x05,
+ 0xbf,0x02,0x2a,0xd3,0x08,0x54,0x91,0x53,0x77,0x7f,0xc8,0xa9,0xd4,0x8a,0x62,
+ 0x22,0x86,0x35,0xc8,0x5b,0x4b,0x67,0x93,0xfd,0x91,0x39,0x24,0x18,0xff,0x7a,
+ 0x90,0x46,0xc5,0xcf,0x25,0x94,0x21,0xf1};
diff --git a/etc/gnus/gnus-summary-catchup-up.xpm b/etc/gnus/gnus-summary-catchup-up.xpm
new file mode 100644 (file)
index 0000000..9de9baf
--- /dev/null
@@ -0,0 +1,37 @@
+/* XPM */
+static char * icon-catchup2_xpm[] = {
+"32 32 2 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".................  .............",
+" ... ... ... ...   . ... ... ...",
+"................  ..............",
+"............... ................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".............  ..........  .....",
+" ... ... ...   . ... ...   . ...",
+"............  ..........  ......",
+"........... ........... ........",
+"............  .......... .......",
+" ... ... ... . . ... ... ... ...",
+"...............  .....          ",
+"................      ... ......",
+"........  ..... ... ...... .....",
+" ... ..   .. . . . .  .. .     .",
+".......  .... .... ... .. . ... ",
+"...... ...... ... .....  ... ...",
+"......    .. .... ......   .. ..",
+" ... ... .       ... ..  ..   ..",
+"........... ....      . ....   .",
+".......... ..... .....      .. .",
+".......... ..... ....... ...    "};
diff --git a/etc/gnus/gnus-summary-exit-up.xbm b/etc/gnus/gnus-summary-exit-up.xbm
new file mode 100644 (file)
index 0000000..4d55755
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x19,0x51,0x91,0x11,0x82,0x14,0x2a,0x48,0x28,0x42,0x40,0x25,0x82,0x10,0x15,
+ 0x00,0x59,0xfa,0xff,0x5b,0x12,0x4b,0xfe,0x21,0x40,0x21,0xf1,0x93,0x2a,0x0b,
+ 0xf8,0x05,0x91,0xb5,0xf2,0x31,0x24,0x01,0xf1,0x4b,0x12,0x54,0xfa,0x01,0x80,
+ 0x83,0xf0,0x55,0x5b,0x35,0xf2,0x11,0x00,0x8b,0xfe,0x4b,0x2a,0x21,0xf7,0x21,
+ 0x80,0x0b,0xf6,0x13,0x5b,0xb5,0xf4,0x59,0x10,0x03,0xf1,0x01,0x42,0x2b,0xf4,
+ 0x55,0x90,0x40,0xf3,0x03,0x13,0x1a,0xf8,0x59,0xa8,0x83,0xf2,0x11,0x02,0x2b,
+ 0x5c,0x43,0x50,0xe3,0xee,0x10,0x93,0xfc,0x55,0x5b,0x48,0x92,0x92,0x00,0x22,
+ 0x49,0x48,0xaa,0x08,0x00,0x84,0x00,0xb5,0xbb,0x31,0x5b,0x01,0x00,0x0a,0x00,
+ 0x54,0x25,0x51,0x55,0x01,0x48,0x04,0x00};
diff --git a/etc/gnus/gnus-summary-exit-up.xpm b/etc/gnus/gnus-summary-exit-up.xpm
new file mode 100644 (file)
index 0000000..d1ab26a
--- /dev/null
@@ -0,0 +1,37 @@
+/* XPM */
+static char * icon-exit-summary_xpm[] = {
+"32 32 2 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ......              ... ...",
+"........  .......        .......",
+"........ ...........     .......",
+"........  ..........     .......",
+" ... ... ... .......     ... ...",
+"................ ...     .......",
+"....................     .......",
+"........  ..........     .......",
+" ... ... ... .......     ... ...",
+"........  .......  .     .......",
+"........ .......   .     .......",
+"........  .......  .     .......",
+" ... ... ... .......     ... ...",
+"........  ..........     .......",
+"........ ...........     .......",
+"................ ...     .......",
+" ... ....... .......     ... ...",
+"........  ..........     .......",
+"........  ........   . . .......",
+"........ ....   . . . . ........",
+" ... .. ..       . . . . ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................"};
diff --git a/etc/gnus/gnus-summary-followup-up.xbm b/etc/gnus/gnus-summary-followup-up.xbm
new file mode 100644 (file)
index 0000000..c6ba686
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x00,0x40,0x08,0xb6,0x76,0x37,0x63,0x20,0x02,0x00,0x04,0x8a,0x48,0x55,
+ 0x51,0x10,0x22,0x0e,0x82,0xa6,0xaa,0xa9,0x36,0x12,0x62,0x38,0x20,0xa0,0x18,
+ 0x96,0x4a,0x0a,0x07,0x17,0x00,0xa2,0x01,0xa3,0x76,0x6a,0x80,0x60,0x00,0x60,
+ 0x00,0x40,0x55,0x52,0x00,0x40,0x00,0xa6,0x00,0x80,0x6b,0x90,0xe1,0x80,0x04,
+ 0x24,0x9a,0x00,0x51,0x82,0x86,0x01,0x85,0xaa,0x61,0x01,0x32,0x60,0x70,0x01,
+ 0x42,0x1d,0x30,0x02,0x14,0x04,0x08,0x02,0x4c,0x06,0x00,0x02,0x28,0x06,0x00,
+ 0x04,0xac,0x08,0x00,0x08,0x0b,0x0a,0x00,0xc8,0x22,0x12,0x00,0x70,0x6a,0x1a,
+ 0x00,0x10,0x01,0x20,0x00,0x60,0x52,0x32,0x00,0x20,0x08,0x46,0x00,0x40,0x63,
+ 0x50,0x00,0x40,0x04,0x85,0x00,0x80,0x52};
diff --git a/etc/gnus/gnus-summary-followup-up.xpm b/etc/gnus/gnus-summary-followup-up.xpm
new file mode 100644 (file)
index 0000000..3cee12e
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-followup_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"        .XXXX...XXXXXXX.        ",
+"         .X..XX.XXXXXXXX.       ",
+"         ..XXXX..XXXXXXX.       ",
+" .     ..XXXX..X.XXXXXXXX.   .  ",
+"     ..XXXXX...X.XXXXXXXX.      ",
+"   ..XXXXXXX..XXX.XXXXXXXX.     ",
+"  .XXXXXXXX.XXXXX.XXXXXXXX.     ",
+" ..XXXXXXXXXXXXXX.XXXXXXXXX. .  ",
+"  .XXXXXXXXXXXXXXX.XXXXXXX..    ",
+"   .XXXXXXXXXXXXXXX.XXXX..      ",
+"   .XXXXXXXXXXXXXXX.XX..        ",
+" .  .XXXXXXXXXXXXXXX..   .   .  ",
+"    .XXXXXXXXXXXXXXX.           ",
+"     .XXXXXXXXXXXXXXX.          ",
+"     .XXXXXXXXXXXXXXX.          ",
+" .    .XXXXXXXXXXXXXXX.  .   .  ",
+"      .XXXXXXXXXXXXXXX.         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/etc/gnus/gnus-summary-followup-with-original-up.xbm b/etc/gnus/gnus-summary-followup-with-original-up.xbm
new file mode 100644 (file)
index 0000000..a0e6dfe
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x04,0x40,0x10,0x00,0xa3,0x36,0xa6,0x76,0x54,0x40,0x11,0x02,0x01,0x2a,0x88,
+ 0x48,0x54,0x81,0x22,0x22,0x22,0x6a,0xaa,0x2a,0x4a,0x02,0x21,0xa0,0x90,0x50,
+ 0x8e,0x0a,0x02,0x0a,0x27,0x50,0xb2,0xa2,0xab,0x26,0x42,0xaa,0x00,0x92,0x94,
+ 0x00,0xaa,0x20,0x00,0xaa,0x00,0x85,0xb6,0x22,0x76,0x32,0x20,0xea,0x80,0x44,
+ 0x8a,0x98,0x2a,0x11,0x10,0x87,0x00,0x44,0xa6,0x71,0x6b,0x33,0x60,0xcc,0x22,
+ 0x44,0x1d,0xe3,0x0a,0x11,0xc8,0xe0,0x24,0x44,0x3e,0x90,0x6c,0x2b,0x08,0x00,
+ 0x09,0xa0,0x06,0x00,0x49,0x0a,0x04,0x00,0x92,0x50,0x0b,0x00,0x32,0x26,0x0c,
+ 0x00,0xa4,0x90,0x11,0x00,0x24,0x24,0x14,0x00,0xc8,0x82,0x22,0x00,0x48,0x32,
+ 0x2a,0x00,0x90,0x42,0x50,0x00,0x90,0x28};
diff --git a/etc/gnus/gnus-summary-followup-with-original-up.xpm b/etc/gnus/gnus-summary-followup-with-original-up.xpm
new file mode 100644 (file)
index 0000000..baffb6b
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-followup-w-orig_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                 ..             ",
+"                ...             ",
+" .   .   .   .  ..   .   .   .  ",
+"               .                ",
+"                                ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"             ..                 ",
+"           ..XX.                ",
+"         ..XXXX.                ",
+" .     ..XXX...X.    .   .   .  ",
+"     ..XXX..XX..X.              ",
+"   ..XXX..XXX...X.              ",
+"   .XX..XXXXX...XX.             ",
+" . ...XXXXXX.XX.XX.  .   .   .  ",
+"   .XXXXXXXXXXXX.XX.            ",
+"  .XXXXXXXXXXXXX.XX.            ",
+"  .XXXXXXXXXXXXXX.XX.           ",
+" . .XXXXXXXXXXXXX.XX.    .   .  ",
+"   .XXXXXXXXXXXXXX.XX.          ",
+"    .XXXXXXXXXXXXX.XX.          ",
+"    .XXXXXXXXXXXXXX.XX.         ",
+" .   .XXXXXXXXXXXXX.XX.  .   .  ",
+"     .XXXXXXXXXXXXXX.XX.        ",
+"      .XXXXXXXXXXXXX.XX.        "};
diff --git a/etc/gnus/gnus-summary-mail-copy-up.xbm b/etc/gnus/gnus-summary-mail-copy-up.xbm
new file mode 100644 (file)
index 0000000..a1eea6b
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x20,0x20,0x40,0xaa,0x8a,0x0a,0x15,0xfe,0xff,0xff,0x27,0x0e,0x00,0x80,
+ 0x4d,0x32,0x00,0x60,0x04,0xc2,0x00,0x18,0x54,0x02,0x03,0x06,0x04,0x03,0x8c,
+ 0x01,0x54,0x02,0x74,0x02,0x04,0x02,0x03,0x0c,0x54,0x82,0x00,0x10,0x84,0xf2,
+ 0xff,0xff,0x3f,0x52,0x00,0x00,0x6c,0x9b,0x01,0x00,0x23,0x16,0x06,0xc0,0x60,
+ 0x1e,0x18,0x30,0x20,0x14,0x60,0x0c,0xa0,0x11,0xa0,0x0b,0x20,0x14,0x10,0x30,
+ 0x60,0x11,0x0c,0x40,0x20,0x14,0x02,0x80,0xa0,0x12,0x01,0x00,0x23,0xd8,0x00,
+ 0x00,0x64,0x32,0x00,0x00,0x38,0xf8,0xff,0xff,0xbf,0x02,0x00,0x40,0x24,0x54,
+ 0x55,0x15,0x11,0x01,0x00,0x40,0x44,0x54,0x55,0x15,0x11,0x01,0x00,0x40,0x44,
+ 0x54,0x55,0x05,0x11,0x02,0x00,0x50,0x44};
diff --git a/etc/gnus/gnus-summary-mail-copy-up.xpm b/etc/gnus/gnus-summary-mail-copy-up.xpm
new file mode 100644 (file)
index 0000000..e73e6d5
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-copy_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+" ..........................     ",
+" ...XXXXXXXXXXXXXXXXXXX..X.     ",
+" .XX..XXXXXXXXXXXXXXX..XXX.     ",
+" .XXXX..XXXXXXXXXXX..XXXXX.     ",
+" .XXXXXX..XXXXXXX..XXXXXXX.     ",
+" .XXXXXXXX..XXX..XXXXXXXXX.     ",
+" .XXXXXXXX.X...XX.XXXXXXXX.     ",
+" .XXXXXX..XXXXXXXX..XXXXXX.     ",
+" .XXXXX.XXXXXXXXXXXX.XXXXX.     ",
+" .XX..........................  ",
+" .XX.X.XXXXXXXXXXXXXXXXXXX..X.  ",
+" .X..XX..XXXXXXXXXXXXXXX..XXX.  ",
+" ..X.XXXX..XXXXXXXXXXX..XXXXX.  ",
+" ....XXXXXX..XXXXXXX..XXXXXXX.  ",
+"    .XXXXXXXX..XXX..XXXXXXXXX.  ",
+"    .XXXXXXXX.X...X.XXXXXXXXX.  ",
+"    .XXXXXXX.XXXXXXX..XXXXXXX.  ",
+"    .XXXXX..XXXXXXXXXX.XXXXXX.  ",
+"    .XXXX.XXXXXXXXXXXXX.XXXXX.  ",
+"    .XXX.XXXXXXXXXXXXXXX..XXX.  ",
+"    .X..XXXXXXXXXXXXXXXXXX.XX.  ",
+"    ..XXXXXXXXXXXXXXXXXXXXX...  ",
+"    ..........................  ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-delete-up.xbm b/etc/gnus/gnus-summary-mail-delete-up.xbm
new file mode 100644 (file)
index 0000000..9d1c637
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x00,0x80,0x00,0xa2,0xaa,0x2a,0x54,0x08,0x00,0x40,0x81,0xf2,0xab,0x2a,
+ 0x28,0x5c,0x03,0x80,0x82,0x2d,0x56,0xf5,0x28,0x84,0x06,0x98,0x8b,0x5d,0x5e,
+ 0xe7,0x2c,0x1c,0x1f,0x1f,0xba,0xf1,0xf3,0xa7,0xc9,0x44,0xa8,0x90,0x88,0xf1,
+ 0xf3,0x8b,0x08,0x1c,0x5f,0x7f,0x09,0xad,0x1e,0xff,0x08,0x04,0x46,0x08,0x04,
+ 0xae,0x26,0x06,0x04,0x18,0x8b,0x02,0x06,0xfa,0x23,0xc1,0x01,0x20,0x88,0x38,
+ 0x00,0x95,0x62,0x07,0x80,0x40,0xe4,0x00,0x40,0x14,0xd1,0x00,0x20,0x42,0x44,
+ 0x03,0x60,0x10,0x11,0x05,0x10,0x4a,0x44,0x1c,0xa8,0x00,0x11,0x61,0x0c,0x2a,
+ 0x42,0xa4,0x25,0x81,0x14,0x09,0x42,0x14,0x20,0x50,0x15,0xa1,0x4a,0x05,0x40,
+ 0x04,0x00,0xa8,0x0a,0x51,0x55,0x05,0x50};
diff --git a/etc/gnus/gnus-summary-mail-delete-up.xpm b/etc/gnus/gnus-summary-mail-delete-up.xpm
new file mode 100644 (file)
index 0000000..932d8f2
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-mail-delete_xpm[] = {
+"32 32 4 1",
+"      c #BEBEBEBEBEBE s backgroundToolBarColor",
+"X     c #000000000000",
+"o     c #E7E7E7E7E7E7",
+"O     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"    XXXXX                       ",
+"   XX   XX                      ",
+"  XX     XX          XXX        ",
+"  X       X        XXooXX  X    ",
+"  XX     XXX     XXooXX   XX    ",
+"   XX   XXXXX   XXXXX    XOXXX  ",
+"    XXXXX   XXXXXX      XOOXOOXX",
+"             XOX       XOOOXOOOX",
+"    XXXXX   XXXXXX     XOOOXOOOO",
+"   XX   XXXXX   XXXXXX  XOOXOOOO",
+"  XX     XXX     XXXXXXXOOOXOOOO",
+"  X       X        XOOOOOOXOOOOO",
+"  XX     XX       XOOOOOOOXOOOOO",
+"   XX   XX       XOOOOOOOXXOOOOO",
+"    XXXXX       XOOOOOXXXOOOOOOO",
+"               XOOOXXXOOOOOOOOOO",
+"              XOXXXOOOOOOOOOOOOX",
+"             XXXOOOOOOOOOOOOOOX ",
+"              XXOOOOOOOOOOOOOX  ",
+"                XXOOOOOOOOOOOX  ",
+"                  XOOOOOOOOOX   ",
+"                   XXOOOOOOX    ",
+"                     XXOOOX     ",
+"                       XXOX     ",
+"                         X      ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-forward-up.xbm b/etc/gnus/gnus-summary-mail-forward-up.xbm
new file mode 100644 (file)
index 0000000..1b66f5b
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x10,0x42,0x80,0x20,0x84,0x10,0x2a,0x14,0x3a,0xa5,0x40,0x41,0x64,0x08,0x14,
+ 0x28,0xd6,0xa0,0x62,0x85,0x80,0x15,0xe8,0x20,0xca,0x41,0x39,0x8b,0xb0,0x2a,
+ 0x24,0x22,0xd2,0x86,0x12,0x86,0x58,0x24,0x11,0x2c,0xd2,0x8c,0x08,0x98,0x34,
+ 0x75,0x08,0x10,0x30,0x14,0x08,0x60,0x8a,0x0e,0x04,0x20,0x10,0x05,0xfc,0x7f,
+ 0x45,0x02,0x02,0x60,0x10,0x01,0x03,0x18,0xca,0xe0,0x01,0x44,0x20,0x3e,0x00,
+ 0x0a,0xf4,0x21,0x00,0x53,0x32,0x20,0x80,0x80,0x10,0x10,0x40,0x2a,0x2a,0x10,
+ 0xb0,0x80,0x60,0x10,0x28,0x2a,0xea,0x10,0x84,0x40,0x81,0x10,0x2a,0x14,0x94,
+ 0x11,0x41,0x21,0x21,0xca,0x2a,0x48,0x84,0xac,0x80,0x02,0x21,0x3d,0x54,0x50,
+ 0x14,0x84,0x00,0x05,0x42,0x21,0xaa,0x50};
diff --git a/etc/gnus/gnus-summary-mail-forward-up.xpm b/etc/gnus/gnus-summary-mail-forward-up.xpm
new file mode 100644 (file)
index 0000000..19db803
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-forward_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"   ...                          ",
+"  .   .                         ",
+"  .   .               .         ",
+"       .             ...        ",
+"      ...          ...XX.       ",
+"     . . .        .XX.XXX.      ",
+"    .  .  .      .XX.XXXX..     ",
+"    . .   .     .XXX.XXXXX..    ",
+"    . .   .    .XXX.XXXXXXX.    ",
+"    ..    .  ..XXXX.XXXXXXXX.   ",
+"    .     . .XXXXXX.XXXXXXXXX.  ",
+"         . .XXXXXX.XXXXXXXXXX.  ",
+"          .XXXXXXX............. ",
+"         .XXXXXXX.XXXXXXXXXXX.  ",
+"        .XXXXXXX..XXXXXXXXX..   ",
+"      ..XXXXX....XXXXXXXXX.     ",
+"     .XXX.....XXXXXXXXXXX.      ",
+"     ....XXXX.XXXXXXXXXX.       ",
+"    ..XXXXXXX.XXXXXXXXX.        ",
+"    .XXXXXXX.XXXXXXXXX.         ",
+"     .XXXXXX.XXXXXXX..          ",
+"     ..XXXXX.XXXXXX.            ",
+"      ..XXXX.XXXXX.             ",
+"       .XXXX.XXXX.              ",
+"        .XXX.XXX.               ",
+"         .X.XX..                ",
+"          ..X.                  ",
+"          ...                   ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-get-up.xbm b/etc/gnus/gnus-summary-mail-get-up.xbm
new file mode 100644 (file)
index 0000000..0d0e212
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x48,0x00,0x11,0x02,0x12,0x54,0x84,0x50,0x40,0x81,0x50,0x82,0x2a,0x28,0x0a,
+ 0x28,0x80,0x42,0xa0,0x82,0xaa,0x13,0x3d,0x28,0x40,0x46,0xd4,0x42,0xb5,0x28,
+ 0x86,0x10,0x50,0xda,0x51,0x47,0x99,0xb0,0x09,0x13,0x14,0x50,0x01,0x45,0x21,
+ 0x18,0x82,0x21,0x74,0x4c,0xc7,0x94,0x81,0x13,0x78,0x02,0x94,0x44,0x05,0x29,
+ 0xf1,0xff,0xff,0x7f,0x74,0x00,0x00,0x2c,0x91,0x01,0x00,0x23,0x14,0x06,0xc0,
+ 0xa0,0x11,0x18,0x30,0x20,0x14,0x60,0x0c,0x60,0x12,0x90,0x0b,0x20,0x18,0x0c,
+ 0x30,0xa0,0x12,0x02,0x40,0x20,0x18,0x01,0x80,0xa0,0xd2,0x00,0x00,0x23,0x38,
+ 0x00,0x00,0x64,0x12,0x00,0x00,0x38,0xf8,0xff,0xff,0xbf,0x02,0x00,0x00,0x20,
+ 0xa8,0xaa,0xaa,0x8a,0x05,0x00,0x40,0x20};
diff --git a/etc/gnus/gnus-summary-mail-get-up.xpm b/etc/gnus/gnus-summary-mail-get-up.xpm
new file mode 100644 (file)
index 0000000..ffdb84c
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-get_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"       ...         ...          ",
+"      .   .       .   .         ",
+"     .     .     .     .        ",
+"    .       . . .       ..      ",
+"    .       .. ..       ..      ",
+"    .XXXXXXX.   .XXXXXXX.       ",
+"     .XXXXX.     .XXXXX.        ",
+"     ..XXX..     ..XXX..        ",
+"       ...         ...          ",
+"                                ",
+"    ..........................  ",
+"    ...XXXXXXXXXXXXXXXXXXX..X.  ",
+"    .XX..XXXXXXXXXXXXXXX..XXX.  ",
+"    .XXXX..XXXXXXXXXXX..XXXXX.  ",
+"    .XXXXXX..XXXXXXX..XXXXXXX.  ",
+"    .XXXXXXXX..XXX..XXXXXXXXX.  ",
+"    .XXXXXXX.XX...X.XXXXXXXXX.  ",
+"    .XXXXX..XXXXXXXX..XXXXXXX.  ",
+"    .XXXX.XXXXXXXXXXXX.XXXXXX.  ",
+"    .XXX.XXXXXXXXXXXXXX.XXXXX.  ",
+"    .X..XXXXXXXXXXXXXXXX..XXX.  ",
+"    ..XXXXXXXXXXXXXXXXXXXX.XX.  ",
+"    .XXXXXXXXXXXXXXXXXXXXXX...  ",
+"    ..........................  ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-originate-up.xbm b/etc/gnus/gnus-summary-mail-originate-up.xbm
new file mode 100644 (file)
index 0000000..6d25e12
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x04,0x42,0x08,0x10,0xa1,0x10,0x42,0x05,0x14,0xa2,0xff,0xaf,0x01,0x89,0x00,
+ 0x14,0x54,0xa4,0x00,0x64,0x02,0xc1,0x00,0x3c,0xf8,0xff,0x1f,0xa0,0x6d,0x10,
+ 0x68,0x20,0xf8,0xff,0x1f,0x60,0x12,0x84,0x00,0x20,0x48,0xd1,0x00,0xa0,0x02,
+ 0x88,0xfc,0x21,0xfc,0xff,0x00,0x60,0x1e,0x80,0x6c,0x21,0x64,0x80,0x00,0xa0,
+ 0x86,0x81,0x00,0x20,0x04,0x86,0x00,0x60,0x05,0x98,0x00,0x20,0x04,0xe4,0x00,
+ 0xa0,0x06,0x83,0x80,0x25,0x84,0x80,0x00,0x60,0x46,0x80,0x00,0x20,0x34,0x80,
+ 0x00,0xa0,0x0d,0x80,0xff,0x3f,0x04,0x00,0x00,0x2e,0xfe,0xff,0xff,0x4f,0x48,
+ 0x92,0x44,0x12,0x92,0x08,0x11,0x44,0x00,0x21,0x44,0x11,0x55,0x48,0x21,0x44,
+ 0x80,0x02,0x8a,0x10,0x2a,0xa8,0x40,0x44};
diff --git a/etc/gnus/gnus-summary-mail-originate-up.xpm b/etc/gnus/gnus-summary-mail-originate-up.xpm
new file mode 100644 (file)
index 0000000..8ba8bc2
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-originate_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"               .............    ",
+"               .XXXXXXXXXX.X.   ",
+"               .XXXXXXXXXX.XX.  ",
+"               .XXXXXXXXXX....  ",
+"   ..................XXXXXXXX.  ",
+"   .X. X X X X X X .X..XXXXXX.  ",
+"   ..................XXXXXXXX.  ",
+"               .XXXXXXXXXXXXX.  ",
+"               .XXXXXXXXXXXXX.  ",
+"               .XX.......XXXX.  ",
+"  ..............XXXXXXXXXXXXX.  ",
+"  ...XXXXXXXXXX.XX..X..X.XXXX.  ",
+"  .XX..XXXXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXXX..XXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXXXXX..XXXX.XXXXXXXXXXXXX.  ",
+"  .XXXXXXXX..XX.XXXXXXXXXXXXX.  ",
+"  .XXXXXXX.XX...XXXXXXXXXXXXX.  ",
+"  .XXXXX..XXXXX.XXXXXXX..X.XX.  ",
+"  .XXXX.XXXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXX.XXXXXXXX.XXXXXXXXXXXXX.  ",
+"  .X..XXXXXXXXX.XXXXXXXXXXXXX.  ",
+"  ..XXXXXXXXXXX...............  ",
+"  .XXXXXXXXXXXXXXXXXXXXXX...    ",
+"  ..........................    ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-reply-up.xbm b/etc/gnus/gnus-summary-mail-reply-up.xbm
new file mode 100644 (file)
index 0000000..e16ec66
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x40,0x40,0x20,0xaa,0x2a,0x7a,0x0a,0x00,0x80,0x88,0x51,0xaa,0x2a,0x06,
+ 0x06,0x00,0xc0,0x05,0x58,0xaa,0x3a,0x12,0x08,0x00,0x0c,0x11,0x2c,0xaa,0x03,
+ 0x09,0x42,0xc0,0x80,0x04,0x06,0x35,0x40,0x04,0x57,0x98,0x49,0x80,0x18,0x3a,
+ 0x20,0x41,0x56,0xc8,0x10,0xc1,0x11,0x0c,0x93,0x60,0x50,0x0a,0x1c,0x18,0x90,
+ 0x08,0x30,0x06,0x30,0x0a,0xc8,0x05,0x90,0x08,0x06,0x18,0x30,0x0a,0x01,0x20,
+ 0x10,0x88,0x00,0x40,0x50,0x6a,0x00,0x80,0x11,0x19,0x00,0x00,0x52,0x0c,0x00,
+ 0x00,0x1c,0xf9,0xff,0xff,0x5f,0x44,0x44,0x44,0x24,0x11,0x11,0x11,0x09,0x44,
+ 0x44,0x44,0xa0,0x11,0x11,0x11,0x15,0x44,0x44,0x44,0x40,0x11,0x11,0x91,0x14,
+ 0x44,0x44,0x04,0xa2,0x11,0x22,0xa2,0x08};
diff --git a/etc/gnus/gnus-summary-mail-reply-up.xpm b/etc/gnus/gnus-summary-mail-reply-up.xpm
new file mode 100644 (file)
index 0000000..20fe672
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-reply_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                    ...         ",
+"                   .XXX..       ",
+"                  .XXXXXX..     ",
+"              ... .XXXXXXXX.    ",
+"            ..XXX.XX.XXXXXX.    ",
+"          ..XXXX.XXX.XXXXX.     ",
+"        ..XXXXXX.XX.XXXXX.      ",
+"      ..XXXXXXX.XX.XXXXXX.      ",
+"     .XXXXXXXX.XXX.XXXXX...     ",
+"   ..XX..XX.XX.XXXXXXXX.XXX..   ",
+"   ...XXXXXXX.XX.XXXXX.XX..X.   ",
+"   .XX..XXXX.XXX.XXXXX...XXX.   ",
+"   .XXXX..XX.XX.XXXXX..XXXXX.   ",
+"   .XXXXXX...XXXXXX..XXXXXXX.   ",
+"   .XXXXXXXX..XXX..XXXXXXXXX.   ",
+"   .XXXXXXX.XX...X.XXXXXXXXX.   ",
+"   .XXXXX..XXXXXXXX..XXXXXXX.   ",
+"   .XXXX.XXXXXXXXXXXX.XXXXXX.   ",
+"   .XXX.XXXXXXXXXXXXXX.XXXXX.   ",
+"   .X..XXXXXXXXXXXXXXXX..XXX.   ",
+"   ..XXXXXXXXXXXXXXXXXXXX.XX.   ",
+"   .XXXXXXXXXXXXXXXXXXXXXX...   ",
+"   ..........................   ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-mail-save-up.xbm b/etc/gnus/gnus-summary-mail-save-up.xbm
new file mode 100644 (file)
index 0000000..0601dfb
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x10,0x10,0x00,0x55,0x45,0x45,0x55,0x00,0x10,0x08,0x00,0xd4,0xff,0xff,
+ 0x7f,0x82,0x03,0x00,0xf0,0xd0,0x0c,0x00,0x4c,0x82,0x30,0x00,0x43,0xd4,0xc0,
+ 0xc0,0x40,0x80,0x80,0x33,0xc0,0xaa,0x60,0xcc,0x40,0xc0,0x10,0x00,0x41,0x95,
+ 0x08,0x00,0x46,0xc0,0x06,0x00,0xd8,0xfe,0xff,0x0f,0x60,0x2c,0x00,0x0b,0x40,
+ 0x35,0x10,0xfd,0x7f,0x2c,0x02,0x2b,0x49,0x35,0x40,0x4d,0x12,0xac,0x00,0x0b,
+ 0xa0,0x35,0x00,0xad,0x0a,0x2c,0x24,0x09,0x90,0x2d,0x00,0x5d,0x25,0xf4,0xff,
+ 0x0b,0x80,0xa6,0x55,0xad,0x2a,0x4c,0xaa,0x08,0x40,0xf5,0xff,0x5d,0x15,0x6c,
+ 0x35,0x0b,0x20,0x66,0x37,0xab,0x4a,0x6c,0x2d,0x0d,0x00,0xb9,0x35,0x4b,0x55,
+ 0xf4,0xff,0x1f,0x80,0x01,0x40,0x80,0x2a};
diff --git a/etc/gnus/gnus-summary-mail-save-up.xpm b/etc/gnus/gnus-summary-mail-save-up.xpm
new file mode 100644 (file)
index 0000000..fd4824b
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-mail_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"       ........................ ",
+"       ...XXXXXXXXXXXXXXXXXX... ",
+"       .XX..XXXXXXXXXXXXXX..XX. ",
+"       .XXXX..XXXXXXXXXX..XXXX. ",
+"       .XXXXXX..XXXXXX..XXXXXX. ",
+"       .XXXXXXX...XX..XXXXXXXX. ",
+"       .XXXXX..XXX..XX..XXXXXX. ",
+"       .XXXX.XXXXXXXXXXX.XXXXX. ",
+"       .XXX.XXXXXXXXXXXXX..XXX. ",
+"       .X..XXXXXXXXXXXXXXXX..X. ",
+"  ..................XXXXXXXXX.. ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXXXX. ",
+"  .oo.OOOOOOOOOO.oo............ ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo............oo.            ",
+"  .oooooooooooooooo.            ",
+"  .oooooooooooooooo.            ",
+"  .oo............oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-next-unread-up.xbm b/etc/gnus/gnus-summary-next-unread-up.xbm
new file mode 100644 (file)
index 0000000..a6c17a9
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x10,0x20,0x00,0xa3,0x66,0xab,0x76,0x14,0x11,0x04,0x02,0x41,0x04,0xa1,
+ 0x48,0x14,0x51,0x1e,0x22,0x62,0xa6,0xa9,0x2a,0x0a,0x71,0x18,0xa0,0x40,0x18,
+ 0xb6,0x0a,0x8a,0x06,0x17,0x50,0xb2,0x01,0x63,0x27,0x62,0x80,0x20,0x90,0x50,
+ 0x00,0x40,0x25,0x4a,0x00,0x40,0x80,0xe2,0x00,0x80,0x36,0x12,0xe1,0x80,0x41,
+ 0x84,0x9a,0x00,0x29,0x10,0x87,0x01,0x85,0xa6,0x61,0x01,0x32,0x62,0x70,0x01,
+ 0x42,0x18,0x30,0x02,0x14,0x06,0x08,0x02,0x4c,0x06,0x00,0x02,0x28,0x04,0x00,
+ 0x04,0xac,0xca,0x07,0x7c,0x0b,0x68,0x0d,0xea,0x20,0x1b,0x12,0x93,0x6b,0xb4,
+ 0x54,0x29,0x03,0x91,0xba,0x95,0x51,0x74,0x19,0x53,0x0b,0x6a,0x0a,0xd6,0x62,
+ 0xe0,0x07,0x7c,0x09,0x8a,0x00,0x80,0x42};
diff --git a/etc/gnus/gnus-summary-next-unread-up.xpm b/etc/gnus/gnus-summary-next-unread-up.xpm
new file mode 100644 (file)
index 0000000..e525816
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-next-unread_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"        .XXXX...XXXXXXX.        ",
+"         .X..XX.XXXXXXXX.       ",
+"         ..XXXX..XXXXXXX.       ",
+" .     ..XXXX..X.XXXXXXXX.   .  ",
+"     ..XXXXX...X.XXXXXXXX.      ",
+"   ..XXXXXXX..XXX.XXXXXXXX.     ",
+"  .XXXXXXXX.XXXXX.XXXXXXXX.     ",
+" ..XXXXXXXXXXXXXX.XXXXXXXXX. .  ",
+"  .XXXXXXXXXXXXXXX.XXXXXXX..    ",
+"   .XX.....XXXXXXX.....X..      ",
+"   .X.ooooo.XXXXX.oooo..        ",
+" .  .oXooooo.XXX.oXooooo..   .  ",
+"    .ooooooo.X.X.ooooooo.       ",
+"    .ooooooo..X..ooooooo.       ",
+"    ..oooooo.XXX.ooooooo.       ",
+" .   ..oooo.XXXXX.oooo.. .   .  ",
+"      .....XXXXXXX.....         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/etc/gnus/gnus-summary-post-news-up.xbm b/etc/gnus/gnus-summary-post-news-up.xbm
new file mode 100644 (file)
index 0000000..8eb4c33
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x10,0x10,0x01,0x6b,0xa7,0x66,0x72,0x04,0x10,0x02,0x05,0xa1,0x8a,0x50,
+ 0x48,0x04,0x20,0x8f,0x20,0x72,0xab,0x39,0x2b,0x02,0x64,0x58,0xa4,0x50,0x19,
+ 0x16,0x01,0x0a,0x06,0x57,0x54,0xe2,0x01,0x23,0x23,0x72,0x80,0x20,0x94,0x44,
+ 0x00,0x40,0x01,0x50,0x00,0xc0,0x54,0xa6,0x00,0x80,0x22,0x92,0x00,0x80,0x4a,
+ 0x40,0x01,0x00,0x11,0x8a,0x01,0x00,0x45,0x32,0x02,0x00,0x2a,0x42,0x02,0x00,
+ 0xa2,0x10,0x05,0x00,0x0c,0x4a,0x06,0x00,0x24,0x22,0x0a,0x00,0x68,0xaa,0x0c,
+ 0x00,0x0c,0x00,0x11,0x80,0x53,0x2a,0x14,0x40,0x05,0x22,0x23,0x70,0x62,0x92,
+ 0x34,0x0e,0x09,0x24,0xc0,0x4b,0x52,0x80,0x0a,0x21,0x80,0x6b,0x62,0xaa,0x36,
+ 0x04,0x15,0x01,0x42,0x51,0x80,0xa8,0x28};
diff --git a/etc/gnus/gnus-summary-post-news-up.xpm b/etc/gnus/gnus-summary-post-news-up.xpm
new file mode 100644 (file)
index 0000000..46be7c1
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-post_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"       .XXXXXXXXXXXXXXX.        ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+" .   .   .XXXXXXXXXXXXXXX.   .  ",
+"         .XXXXXXXXXXXXXXX.      ",
+"          .XXXXXXXXXXXXXXX.     ",
+"          .XXXXXXXXXXXXXXX.     ",
+" .   .   . .XXXXXXXXXXXXXXX. .  ",
+"           .XXXXXXXXXXXXXX..    ",
+"            .XXXXXXXXXX...      ",
+"            .XXXXXXXXX.         ",
+" .   .   .   .XXXXXX..   .   .  ",
+"             .XXX...            ",
+"              ....              ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-prev-unread-up.xbm b/etc/gnus/gnus-summary-prev-unread-up.xbm
new file mode 100644 (file)
index 0000000..6cf240e
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x08,0x08,0x40,0x20,0x23,0x63,0x2b,0x2b,0x54,0x14,0x24,0xa4,0x01,0x02,0x09,
+ 0x01,0x54,0xa9,0x2e,0x2a,0x22,0xa2,0xa9,0x62,0x4a,0x6a,0x18,0x12,0x90,0x18,
+ 0xb6,0x04,0x02,0x06,0x17,0x50,0xea,0x01,0x63,0x2b,0x64,0x80,0x20,0x44,0x51,
+ 0x00,0x40,0x21,0x44,0x00,0x40,0x8a,0xe2,0x00,0xc0,0x22,0x0a,0xe1,0xc0,0x2f,
+ 0xd0,0x9f,0x20,0x4d,0x42,0x87,0xb1,0x1a,0xea,0x61,0x15,0x72,0x60,0x70,0xbb,
+ 0x14,0x1d,0x30,0xb1,0x5a,0x04,0x08,0x22,0x0d,0x06,0x00,0xc2,0x6f,0x06,0x00,
+ 0x84,0x20,0x08,0x00,0x64,0x0a,0x0a,0x00,0x58,0x50,0x12,0x00,0x10,0x27,0x1a,
+ 0x00,0x50,0x90,0x20,0x00,0xa0,0x24,0x32,0x00,0x20,0x82,0x26,0x00,0xc0,0x32,
+ 0x40,0x00,0x40,0x44,0xaa,0x00,0x80,0x11};
diff --git a/etc/gnus/gnus-summary-prev-unread-up.xpm b/etc/gnus/gnus-summary-prev-unread-up.xpm
new file mode 100644 (file)
index 0000000..b2088fb
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-prev-unread_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXX.  .   .  ",
+"        .XXXX...XXXXXX.....     ",
+"       ...o..XX.XXXXX.oooo..    ",
+"      .oo..XXXX..XXX.oXooooo.   ",
+" .   .o..XXXX..X.X.X.ooooooo..  ",
+"     ..XXXXX...X..X..ooooooo.   ",
+"   ..XXXXXXX..XX.XXX.ooooooo.   ",
+"  .XXXXXXXX.XXXXX.XXX.oooo..    ",
+" ..XXXXXXXXXXXXXX.XXXX.....  .  ",
+"  .XXXXXXXXXXXXXXX.XXXX.        ",
+"   .XXXXXXXXXXXXXX.XX..         ",
+"   .XXXXXXXXXXXXXXX..           ",
+" .  .XXXXXXXXXXXXXXX.    .   .  ",
+"    .XXXXXXXXXXXXXXX.           ",
+"     .XXXXXXXXXXXXXXX.          ",
+"     .XXXXXXXXXXXXXXX.          ",
+" .   .XXXXXXXXXXXXXXXX.  .   .  ",
+"      .XXXXXXXXXXXXXXX.         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/etc/gnus/gnus-summary-reply-up.xbm b/etc/gnus/gnus-summary-reply-up.xbm
new file mode 100644 (file)
index 0000000..61dad9a
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x10,0x00,0x11,0x88,0x45,0x55,0x84,0x22,0x08,0x80,0x10,0x88,0x42,0x55,0xa4,
+ 0x22,0x28,0x00,0x01,0x84,0x05,0x55,0x5a,0x21,0x50,0x00,0x35,0x8a,0x09,0xf5,
+ 0xc2,0x20,0x24,0x18,0x81,0x85,0x01,0x87,0x00,0x2a,0xd4,0x41,0x00,0x43,0x61,
+ 0x40,0x80,0x17,0x1c,0x20,0x80,0x58,0xb5,0x1a,0xc0,0x3f,0x0c,0x08,0x60,0xb0,
+ 0x75,0x08,0xb0,0x2e,0x84,0x04,0xb8,0xa1,0x06,0x03,0x4c,0x20,0x04,0x0c,0x36,
+ 0x60,0x06,0x10,0x0f,0x20,0x06,0x70,0x07,0x60,0x05,0xc8,0x09,0xa0,0x04,0x04,
+ 0x10,0xa0,0x06,0x02,0x20,0x60,0x85,0x01,0xc0,0xa0,0x44,0x00,0x00,0x61,0x25,
+ 0x00,0x00,0x22,0x1e,0x00,0x00,0xbc,0x0e,0x00,0x00,0x70,0xfd,0xff,0xff,0x3f,
+ 0x94,0x52,0x55,0x55,0x4a,0x29,0x22,0xa2};
diff --git a/etc/gnus/gnus-summary-reply-up.xpm b/etc/gnus/gnus-summary-reply-up.xpm
new file mode 100644 (file)
index 0000000..255f7a1
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-follow-up_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                   .            ",
+"                  .X..          ",
+"             ... .XXXX.         ",
+"           ..XXX.XXXXXX..       ",
+"         ..XXXX.XXXXXXXXX.      ",
+"       ..XXXXX.XXXXXXXXX..      ",
+"     ..XXXXXXX.XXXXXXXX....     ",
+"   ..XXXXXXXX.XXXXXXXXX.oXX..   ",
+"  .X..X.X.X..XXXXXXXXX..o...o.  ",
+"  ..XXXXXXX.XXXXXXXXX..ooXXX..  ",
+"  .X...XXXX.XXXXXXXX..ooX...X.  ",
+"  .XXXX.XX.XXXXXXXX..oX..XXXX.  ",
+"  .XXXXX..XXXXXXXX..oX.XXXXXX.  ",
+"  .XXXXXXX..XXXXX..X..XXXXXXX.  ",
+"oo.XXXXXXXXX.XXX....XXXXXXXXX.oo",
+"oo.XXXXXXXXX...X...XXXXXXXXXX.oo",
+"oo.XXXXXXXX.XX...XX.XXXXXXXXX.oo",
+"oo.XXXXXXX.XXXXXXXXX.XXXXXXXX.oo",
+"oo.XXXXXX.XXXXXXXXXXX.XXXXXXX.oo",
+"oo.XXXX..XXXXXXXXXXXXX..XXXXX.oo",
+"oo.XXX.XXXXXXXXXXXXXXXXX.XXXX.oo",
+"oo.XX.XXXXXXXXXXXXXXXXXXX.XXX.oo",
+"oo...XXXXXXXXXXXXXXXXXXXXX....oo",
+"oo..XXXXXXXXXXXXXXXXXXXXXXXX..oo",
+"oo............................oo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/etc/gnus/gnus-summary-reply-with-original-up.xbm b/etc/gnus/gnus-summary-reply-with-original-up.xbm
new file mode 100644 (file)
index 0000000..37b0d73
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x08,0x00,0x20,0xaa,0x82,0xaa,0x4a,0x00,0x54,0x00,0x00,0xaa,0x02,0x54,
+ 0x55,0x00,0xa8,0x07,0x00,0x54,0x85,0x5a,0x55,0x02,0x50,0x32,0x80,0x50,0x25,
+ 0xc2,0x2a,0x02,0x18,0x81,0x41,0x54,0x17,0x01,0x17,0x80,0x09,0xc1,0x23,0x75,
+ 0x04,0x3d,0x4f,0x18,0xc3,0x83,0x18,0x85,0x40,0xc0,0x61,0x4c,0x7c,0x60,0x30,
+ 0xf6,0x23,0xb0,0x6e,0x84,0x20,0x98,0x21,0x05,0x13,0x5c,0x20,0x04,0x1c,0x36,
+ 0x60,0x06,0x30,0x0f,0x60,0x06,0x70,0x07,0xa0,0x05,0xc8,0x09,0x20,0x06,0x04,
+ 0x10,0x60,0x04,0x02,0x20,0xa0,0x85,0x01,0xc0,0x20,0x46,0x00,0x00,0xa1,0x24,
+ 0x00,0x00,0x62,0x1e,0x00,0x00,0x7c,0x0d,0x00,0x00,0xb0,0xfc,0xff,0xff,0x3f,
+ 0x55,0x55,0x4a,0x55,0x24,0x89,0x52,0xa2};
diff --git a/etc/gnus/gnus-summary-reply-with-original-up.xpm b/etc/gnus/gnus-summary-reply-with-original-up.xpm
new file mode 100644 (file)
index 0000000..1135bfa
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-follow-up-incl_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                ...             ",
+"               .X.X.            ",
+"              .XX.XX..          ",
+"             .XXX.XXXX.         ",
+"           ..XXX.XXXXXX..       ",
+"         ..X.XXX.XXXXXXX..      ",
+"       ..XX.XXXX.XXXXX....      ",
+"     ..XXX.XXXXX.X....XX...     ",
+"   ..XXX..XXXX....XXXXX.oXX..   ",
+"  .XXXX.XXXXXX.XXXXXXX..oXXXo.  ",
+"  ..XX.XXX.....XXXXXX..ooXXX..  ",
+"  .X......XXX.XXXXXX..ooX...X.  ",
+"  .XXXX.XXXXX.XXXXX..oX..XXXX.  ",
+"  .XXXXX..XX.XXXXX..oX.XXXXXX.  ",
+"  .XXXXXXX...XXXX..X..XXXXXXX.  ",
+"oo.XXXXXXXXX..XX....XXXXXXXXX.oo",
+"oo.XXXXXXXXX...X...XXXXXXXXXX.oo",
+"oo.XXXXXXXX.XX...XX.XXXXXXXXX.oo",
+"oo.XXXXXXX.XXXXXXXXX.XXXXXXXX.oo",
+"oo.XXXXXX.XXXXXXXXXXX.XXXXXXX.oo",
+"oo.XXXX..XXXXXXXXXXXXX..XXXXX.oo",
+"oo.XXX.XXXXXXXXXXXXXXXXX.XXXX.oo",
+"oo.XX.XXXXXXXXXXXXXXXXXXX.XXX.oo",
+"oo...XXXXXXXXXXXXXXXXXXXXX....oo",
+"oo..XXXXXXXXXXXXXXXXXXXXXXXX..oo",
+"oo............................oo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/etc/gnus/gnus-summary-save-article-file-up.xbm b/etc/gnus/gnus-summary-save-article-file-up.xbm
new file mode 100644 (file)
index 0000000..a14e003
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x20,0x08,0x08,0x82,0x8a,0x82,0xa2,0x20,0x20,0x14,0x04,0x15,0x14,0xfd,0xff,
+ 0x43,0x42,0x04,0x00,0x0d,0x10,0x05,0x00,0x49,0x22,0x06,0x00,0x31,0x88,0x04,
+ 0x00,0x1f,0x22,0x06,0x00,0x50,0x88,0x04,0x00,0x10,0x22,0x04,0x00,0xb0,0x88,
+ 0x06,0x00,0x10,0x22,0x04,0x00,0x50,0xfc,0xff,0x0f,0x10,0x36,0x00,0x0b,0xb0,
+ 0x2c,0x02,0x0d,0x10,0x34,0x10,0x0b,0x50,0x2d,0x00,0x0b,0x10,0x34,0x41,0x0d,
+ 0xb0,0x2d,0x08,0x09,0x10,0x34,0x00,0x0b,0x50,0x2d,0x01,0x0d,0x10,0xf4,0xff,
+ 0x0b,0xb0,0xad,0xda,0x0a,0x10,0x44,0x22,0x0d,0x50,0xf6,0xff,0xf9,0x1f,0x6c,
+ 0x3b,0x4b,0x52,0xb5,0x2d,0x1d,0x08,0x6c,0x35,0x4b,0xa1,0x6a,0x3b,0x29,0x14,
+ 0xf8,0xff,0x8f,0x40,0x02,0x40,0x2a,0x15};
diff --git a/etc/gnus/gnus-summary-save-article-file-up.xpm b/etc/gnus/gnus-summary-save-article-file-up.xpm
new file mode 100644 (file)
index 0000000..ea30122
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-text_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"          ................      ",
+"          .XXXXXXXXXXXXX.X.     ",
+"          .XXXXXXXXXXXXX.XX.    ",
+"          .XXXXXXXXXXXXX.XXX.   ",
+"          .XXXXXXXXXXXXX.....   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"  ..................XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo............oo.XXXXXXXX.   ",
+"  .oooooooooooooooo.XXXXXXXX.   ",
+"  .oooooooooooooooo.XXXXXXXX.   ",
+"  .oo............oo..........   ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/etc/gnus/gnus-summary-save-article-up.xbm b/etc/gnus/gnus-summary-save-article-up.xbm
new file mode 100644 (file)
index 0000000..94e51d1
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x10,0x81,0x04,0x01,0x45,0x28,0x40,0x50,0x88,0x42,0x15,0x05,0xa2,0xff,0xff,
+ 0x7f,0x88,0x03,0x00,0xf0,0xa2,0x0c,0x00,0x4c,0x88,0x30,0x00,0x43,0xc5,0xc0,
+ 0xc0,0x40,0x90,0x80,0x33,0xc0,0xa4,0x60,0xcc,0x40,0x82,0x10,0x00,0x41,0xd0,
+ 0x08,0x00,0x46,0x82,0x06,0x00,0xd8,0xfc,0xff,0x0f,0x60,0x2e,0x00,0x0d,0x40,
+ 0x34,0x02,0xfb,0x7f,0x36,0x10,0x0d,0x91,0xac,0x00,0x4b,0x24,0x34,0x00,0x2d,
+ 0x81,0x2d,0x48,0x4b,0x28,0x34,0x02,0x0d,0x85,0x2d,0x00,0xab,0x20,0xf4,0xff,
+ 0x0d,0x8a,0xa6,0xaa,0xaa,0x20,0x4c,0x55,0x0a,0x85,0xf5,0xff,0x5b,0x20,0x6c,
+ 0x35,0x8d,0x8a,0xad,0x36,0x2b,0x20,0xf4,0x2a,0x89,0x8a,0x6a,0x3b,0x5d,0x20,
+ 0xf8,0xff,0x0f,0x85,0x02,0x40,0xa2,0x20};
diff --git a/etc/gnus/gnus-summary-save-article-up.xpm b/etc/gnus/gnus-summary-save-article-up.xpm
new file mode 100644 (file)
index 0000000..fd4824b
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-mail_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"       ........................ ",
+"       ...XXXXXXXXXXXXXXXXXX... ",
+"       .XX..XXXXXXXXXXXXXX..XX. ",
+"       .XXXX..XXXXXXXXXX..XXXX. ",
+"       .XXXXXX..XXXXXX..XXXXXX. ",
+"       .XXXXXXX...XX..XXXXXXXX. ",
+"       .XXXXX..XXX..XX..XXXXXX. ",
+"       .XXXX.XXXXXXXXXXX.XXXXX. ",
+"       .XXX.XXXXXXXXXXXXX..XXX. ",
+"       .X..XXXXXXXXXXXXXXXX..X. ",
+"  ..................XXXXXXXXX.. ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXXXX. ",
+"  .oo.OOOOOOOOOO.oo............ ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo............oo.            ",
+"  .oooooooooooooooo.            ",
+"  .oooooooooooooooo.            ",
+"  .oo............oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/etc/gnus/gnus-uu-decode-uu-up.xbm b/etc/gnus/gnus-uu-decode-uu-up.xbm
new file mode 100644 (file)
index 0000000..705eb76
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x00,0x08,0x10,0x01,0xaa,0x42,0x45,0x54,0x00,0x14,0x10,0x01,0x55,0x41,0x45,
+ 0x50,0x00,0x0a,0x88,0x0a,0xaa,0xa0,0x22,0x40,0x80,0xff,0xff,0x17,0xaa,0x95,
+ 0x54,0x43,0x80,0x2a,0xa5,0x0a,0xaa,0xfd,0x7f,0x53,0xc0,0x06,0x40,0x06,0x94,
+ 0x04,0x40,0x43,0xc2,0x05,0xc0,0x2a,0x90,0x86,0xc0,0x06,0xa2,0x64,0x4b,0x53,
+ 0x88,0x96,0x44,0x06,0xd2,0x45,0xc0,0x52,0x84,0x25,0xc1,0x06,0x90,0xe6,0x41,
+ 0x53,0x8a,0x05,0x42,0x06,0xa0,0x06,0xc4,0x52,0x95,0x04,0xc0,0x06,0xc0,0x05,
+ 0x40,0x53,0x94,0x06,0x40,0x06,0xa2,0x05,0xc0,0x52,0x88,0xfc,0xff,0x06,0xa2,
+ 0x95,0x12,0x53,0x88,0x4a,0xa9,0x06,0xa2,0xff,0xff,0x53,0x90,0x10,0x00,0x04,
+ 0x42,0x42,0x55,0x50,0x14,0x28,0x80,0x0a};
diff --git a/etc/gnus/gnus-uu-decode-uu-up.xpm b/etc/gnus/gnus-uu-decode-uu-up.xpm
new file mode 100644 (file)
index 0000000..568315c
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-decode-view_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"       ...................      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XX.............XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.oooo.oooooo.XX.      ",
+"       .XX.oo..o..o.oo.XX.      ",
+"       .XX.o.oo.oo.ooo.XX.      ",
+"       .XX.ooo.ooooooo.XX.      ",
+"       .XX.oo.oo.ooooo.XX.      ",
+"       .XX.oo....ooooo.XX.      ",
+"       .XX.oooooo.oooo.XX.      ",
+"       .XX.ooooooo.ooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.............XX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       ...................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/etc/gnus/gnus-uu-post-news-up.xbm b/etc/gnus/gnus-uu-post-news-up.xbm
new file mode 100644 (file)
index 0000000..e0528e9
--- /dev/null
@@ -0,0 +1,12 @@
+#define noname_width 32
+#define noname_height 32
+static char noname_bits[] = {
+ 0x11,0x11,0x19,0x51,0x4a,0x95,0x82,0x14,0x20,0x40,0x29,0x42,0x0a,0xd5,0x86,
+ 0x10,0x31,0x31,0x3b,0x53,0x08,0x9d,0xe8,0x10,0xa2,0x43,0x82,0x4b,0x88,0xff,
+ 0xff,0x03,0xb3,0xaa,0x54,0xbb,0x88,0x55,0xaa,0x02,0xa2,0xfc,0x7f,0x4b,0x88,
+ 0x06,0xc0,0x12,0xb1,0x05,0x40,0x56,0x8a,0x05,0x40,0x03,0xd0,0x86,0xc0,0xaa,
+ 0x85,0x64,0x4b,0x06,0xb1,0x95,0xc4,0x32,0x8a,0x46,0x40,0x4b,0xd0,0x24,0x41,
+ 0x03,0x84,0xe6,0xc1,0x56,0xd9,0x05,0x42,0x12,0x82,0x04,0x44,0x4b,0x94,0x07,
+ 0xc0,0x22,0xc1,0x04,0x40,0x16,0x95,0x05,0xc0,0x52,0xa0,0x06,0x40,0x13,0x8a,
+ 0xfd,0xff,0x46,0xd0,0x94,0x52,0x12,0x93,0x29,0xa5,0x5a,0xa4,0xff,0xff,0x03,
+ 0x10,0x02,0x08,0x55,0x85,0xa8,0xa2,0x00};
diff --git a/etc/gnus/gnus-uu-post-news-up.xpm b/etc/gnus/gnus-uu-post-news-up.xpm
new file mode 100644 (file)
index 0000000..f4a7e3a
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-post-pic_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................ ...............",
+"..............  .  .............",
+" ... ... ...  .. ..  ... ... ...",
+"..........  .........  .........",
+"........  .............  .......",
+".......                   ......",
+" ... .. XXXXXXXXXXXXXXXXX .. ...",
+"....... XXXXXXXXXXXXXXXXX ......",
+"....... XX             XX ......",
+"....... XX ooooooooooo XX ......",
+" ... .. XX ooooooooooo XX .. ...",
+"....... XX ooooooooooo XX ......",
+"....... XX oooo oooooo XX ......",
+"....... XX oo  o  o oo XX ......",
+" ... .. XX o oo oo ooo XX .. ...",
+"....... XX ooo ooooooo XX ......",
+"....... XX oo oo ooooo XX ......",
+"....... XX oo    ooooo XX ......",
+" ... .. XX oooooo oooo XX .. ...",
+"....... XX ooooooo ooo XX ......",
+"....... XX ooooooooooo XX ......",
+"....... XX ooooooooooo XX ......",
+" ... .. XX ooooooooooo XX .. ...",
+"....... XX ooooooooooo XX ......",
+"....... XX             XX ......",
+"....... XXXXXXXXXXXXXXXXX ......",
+" ... .. XXXXXXXXXXXXXXXXX .. ...",
+".......                   ......",
+"................................",
+"................................"};
diff --git a/etc/gnus/gnus.xbm b/etc/gnus/gnus.xbm
new file mode 100644 (file)
index 0000000..58d1ac8
--- /dev/null
@@ -0,0 +1,622 @@
+#define noname_width 271
+#define noname_height 273
+static char noname_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x49,0xe0,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0xaa,0x8a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x41,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0x52,0x16,0xfe,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0x49,0x05,
+ 0xf9,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0x95,0xaa,0x58,0xf4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xa5,0x54,0x26,0xe1,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x54,0x49,0x49,0xe4,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x2a,0xa5,
+ 0x2a,0xd1,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x52,0x95,0x54,0xc4,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,
+ 0x24,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x57,0x29,0xa9,0x92,0x11,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x57,0xd5,0xfa,0xff,0xff,0xab,0xea,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x4a,0x55,0x2a,0x41,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x25,0x29,0xe5,0xff,0xff,0x95,0xa4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0xa4,
+ 0x24,0xa5,0x14,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4a,0xa5,0xd4,0xff,
+ 0x3f,0x52,0xa9,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x29,0x55,0x55,0x55,0x41,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xa9,0x54,0xea,0xff,0xdf,0x2a,0x55,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x4a,0x49,0x12,0x7e,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x55,0xa5,0x92,0xff,0x23,0xa5,0x4a,0xd6,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,0xa4,0x94,0xaa,0x42,
+ 0x7d,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0x2a,0xa9,0xff,0xad,0x92,0x24,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,
+ 0x95,0x52,0x52,0x29,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x52,0x49,0x55,
+ 0xfe,0x91,0x54,0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x49,0x29,0x55,0x25,0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x95,0xaa,0x92,0x7e,0x55,0x55,0xa9,0x4a,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,0x50,0x95,0xaa,0x24,0x7e,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x57,0x2a,0x95,0x54,0x79,0x95,0x92,0x92,0x94,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb9,0x62,0x29,0x49,
+ 0x85,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x49,0x49,0x95,0xba,0xa4,0x54,
+ 0xaa,0x52,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,
+ 0x1a,0xf8,0xa7,0xaa,0x22,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x52,
+ 0x2a,0x75,0x55,0xa5,0x24,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xbf,0x5a,0xfd,0x57,0x92,0x94,0x7e,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x4a,0x4a,0x55,0x49,0x89,0x92,0x94,0xaa,0x94,0xf4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xfc,0x2f,0x55,0x05,0x7c,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x55,0xa9,0x4a,0x55,0x2a,0x55,0x55,0x55,0x55,0xe5,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x4e,0xfd,0x5f,
+ 0x29,0xa5,0x7c,0xff,0xff,0xff,0xff,0xff,0xff,0xa4,0x54,0x52,0x4a,0x55,0xa9,
+ 0xa4,0x24,0xa5,0x94,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x2f,0x1d,0xfe,0x3f,0x95,0x04,0x7c,0xff,0xfd,0xff,0xff,0xff,0x3f,0x49,0xa5,
+ 0x54,0xa9,0xa4,0x92,0x4a,0x49,0x4a,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x44,0xfe,0x5f,0xa9,0x52,0x7d,0xff,0xe5,0xff,0xff,
+ 0xff,0x5f,0x55,0x92,0x2a,0x95,0x52,0x4a,0x52,0xaa,0x52,0x4a,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x16,0xff,0xbf,0x4a,0x05,0x7c,
+ 0xff,0xd9,0xff,0xff,0xff,0x5f,0x95,0x42,0xa5,0x52,0x95,0xaa,0xaa,0xaa,0x94,
+ 0x54,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x43,0xfe,
+ 0xbf,0x54,0x52,0x7d,0x7f,0x25,0xff,0xff,0xff,0xa7,0xa4,0x28,0x92,0x54,0x4a,
+ 0xa5,0x4a,0x92,0xaa,0x4a,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xab,0x12,0xfe,0x7f,0xa5,0x02,0x7c,0x7f,0x55,0xfd,0xff,0xff,0x95,0x2a,
+ 0x82,0x54,0xa5,0x54,0x2a,0xa9,0x2a,0xa5,0x52,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x27,0x4b,0xff,0xff,0x4a,0x29,0x7d,0xff,0x92,0xfe,
+ 0xff,0xff,0x55,0x92,0x20,0xa8,0x94,0x2a,0xa5,0x94,0x52,0x29,0xa9,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,0x01,0xff,0x7f,0x52,0x42,
+ 0x7c,0xff,0x25,0xf9,0xff,0x7f,0xaa,0x02,0x8a,0x40,0x29,0x49,0x09,0x41,0x4a,
+ 0x55,0x25,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,
+ 0xff,0xff,0x95,0x12,0x7d,0xff,0xa9,0xfa,0xff,0x7f,0x25,0xa9,0x20,0x2a,0xa5,
+ 0xaa,0x42,0x92,0x54,0x92,0x54,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xaf,0x83,0xff,0xff,0xa9,0x42,0x7e,0xff,0xaa,0xf4,0xff,0xaf,0x54,
+ 0x01,0x82,0x80,0xaa,0x54,0x14,0x08,0xa2,0xaa,0x4a,0xd2,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xef,0xcf,0xd7,0xff,0xff,0x52,0x12,0x7f,0xff,0x4a,
+ 0xea,0xff,0x57,0x92,0xaa,0x28,0x24,0x29,0x25,0x81,0x82,0x08,0x49,0x52,0x55,
+ 0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xdf,0xef,0xe7,0xff,0xff,0x2a,
+ 0x05,0x7e,0xff,0x55,0xd5,0xff,0xa5,0x2a,0x00,0x8e,0x10,0x4a,0x89,0x24,0x28,
+ 0xa0,0xaa,0x2a,0x49,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xe7,0xff,
+ 0xef,0xff,0xff,0xa5,0x50,0x7e,0xff,0x25,0xe5,0xff,0x2a,0xa5,0x52,0x7f,0x85,
+ 0x54,0x35,0x08,0x82,0x0a,0x55,0x95,0xaa,0xfc,0xff,0xff,0xff,0xcf,0xff,0xff,
+ 0xff,0xff,0xd7,0xff,0xff,0xff,0x7f,0x52,0x85,0x7e,0xff,0xab,0x94,0x1e,0x55,
+ 0x2a,0xc8,0xff,0x10,0x90,0x92,0xa0,0x08,0x20,0x24,0x52,0x25,0xfd,0xff,0xff,
+ 0xff,0xef,0xff,0xff,0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0x94,0x10,0x7e,0xff,
+ 0x93,0xaa,0x6a,0x49,0x49,0xf2,0xff,0x85,0x52,0x09,0x0a,0xa2,0x4a,0x92,0x29,
+ 0xa9,0xf2,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0x7f,
+ 0x55,0x25,0x7f,0xff,0x55,0x49,0x49,0x95,0x0a,0xf9,0xff,0x17,0x48,0x26,0x50,
+ 0x08,0x00,0xa9,0x4a,0x95,0xfa,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xf2,
+ 0xff,0xff,0xff,0xff,0x92,0x80,0x7e,0xff,0xa7,0x54,0xaa,0xa4,0x52,0xfc,0xff,
+ 0xaf,0x42,0x89,0xfa,0xbf,0x54,0x20,0xa9,0xa4,0xd4,0xff,0xff,0xff,0xcb,0xff,
+ 0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,0x54,0x29,0x7f,0xff,0x4b,0xa5,0x92,
+ 0x2a,0x01,0xff,0xff,0x1f,0xa8,0x22,0xff,0xff,0x01,0xa5,0x2a,0x55,0xa9,0xff,
+ 0xff,0xff,0xd4,0xff,0xff,0xff,0x7f,0xfa,0xff,0xff,0xff,0x7f,0xa5,0x04,0x7f,
+ 0xff,0x57,0x2a,0x55,0xa9,0x54,0xfe,0xff,0x3f,0x05,0x89,0xff,0xff,0x5f,0x48,
+ 0x92,0x2a,0x95,0xff,0xff,0xff,0xea,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,0xff,
+ 0x7f,0x2a,0x91,0x7f,0xff,0xa9,0x54,0x4a,0x52,0x02,0xff,0xff,0xff,0x50,0xd1,
+ 0xff,0xff,0x1f,0x81,0xaa,0xa4,0x52,0xfe,0xff,0x3f,0xe9,0xff,0xff,0xff,0x7f,
+ 0x1d,0xff,0xff,0xff,0xff,0x54,0x41,0x7f,0xff,0x93,0x92,0x52,0x95,0xc8,0xff,
+ 0xff,0xff,0x8b,0xc4,0xff,0xff,0x7f,0x24,0xa5,0x2a,0x49,0xf9,0xff,0x7f,0xd5,
+ 0xff,0xff,0xff,0xbf,0x4a,0xff,0xff,0xff,0xff,0x4a,0x14,0x7f,0xff,0x28,0xa5,
+ 0x94,0x2a,0xa0,0xff,0xff,0x7f,0x22,0xf0,0xff,0xff,0x7f,0x12,0x94,0xa4,0xaa,
+ 0xea,0xff,0xaf,0xea,0xff,0xff,0xff,0x5f,0x8e,0xff,0xff,0xff,0x7f,0xa9,0x40,
+ 0x7f,0xff,0x48,0x55,0x55,0x12,0xca,0xff,0xff,0xff,0x0a,0xf5,0xff,0xff,0xff,
+ 0x80,0x52,0x95,0x54,0xaa,0xfe,0x55,0xc4,0xff,0xff,0xff,0x5f,0xa5,0xff,0xff,
+ 0xff,0xff,0x94,0x14,0x7f,0xff,0x52,0x2a,0xa9,0x4a,0xe1,0xff,0xff,0xbf,0x24,
+ 0xf0,0xff,0xff,0xff,0x0b,0x28,0xa9,0x92,0x24,0x55,0x49,0xe5,0xd7,0xff,0xff,
+ 0xa7,0x8a,0xff,0xff,0xff,0x7f,0xa5,0xc0,0x7f,0xff,0x50,0x49,0x95,0x04,0xf8,
+ 0xff,0xff,0x5f,0x1f,0xfd,0xff,0xff,0xff,0x47,0x45,0x55,0xaa,0xaa,0x4a,0xaa,
+ 0xea,0xaf,0xff,0xff,0x2b,0xc3,0xff,0xff,0xff,0x7f,0x55,0x94,0x7f,0x7f,0x4a,
+ 0x55,0x52,0x51,0xfe,0xff,0xff,0x5f,0x4e,0xf8,0xff,0xff,0xff,0x1f,0x50,0x92,
+ 0x52,0x49,0xa9,0x92,0xe4,0xd3,0xff,0xff,0x4b,0xd5,0xff,0xff,0xff,0xff,0x94,
+ 0xc0,0x7f,0x3f,0xa0,0xa4,0xaa,0x04,0xfe,0xff,0xff,0xa7,0x1d,0xfd,0xff,0xff,
+ 0xff,0x9f,0x84,0xaa,0x4a,0xaa,0x24,0x55,0xf2,0x2b,0xff,0x7f,0xa9,0xc1,0xff,
+ 0xff,0xff,0x7f,0x4a,0x95,0x7f,0xbf,0x2a,0x95,0x24,0x50,0xff,0xff,0xff,0x97,
+ 0x5e,0xfe,0xff,0xff,0xff,0x3f,0x92,0x24,0x95,0x92,0xaa,0xa4,0xf2,0xcb,0xff,
+ 0x5f,0xd5,0xe5,0xff,0xff,0xff,0xff,0x52,0x80,0x7f,0x3f,0xa0,0x52,0x15,0x85,
+ 0xff,0xff,0xff,0xd7,0x38,0xfe,0xff,0xff,0xff,0xff,0x20,0xaa,0x52,0x55,0x55,
+ 0x55,0xf9,0x29,0xfd,0xab,0xa4,0xf0,0xff,0xff,0xff,0x7f,0x29,0xa9,0x7f,0xff,
+ 0x42,0x25,0x49,0xe8,0xff,0xff,0xff,0x69,0x7a,0xff,0xff,0xff,0xff,0xff,0x82,
+ 0x52,0xaa,0x24,0x89,0x4a,0xf8,0x55,0x2a,0x49,0x95,0xf5,0xff,0xff,0xff,0xbf,
+ 0x2a,0xc4,0x7f,0x7f,0x90,0x54,0x15,0xe2,0xff,0xff,0xff,0x25,0xbc,0xff,0xff,
+ 0xff,0xff,0xff,0x29,0x48,0x49,0xaa,0xaa,0xa4,0xfa,0x95,0x92,0x54,0x52,0xf0,
+ 0xff,0xff,0xff,0xbf,0x4a,0xd1,0x7f,0xff,0x05,0xaa,0x40,0xf8,0xff,0xff,0x7f,
+ 0xaa,0xfc,0xff,0xff,0xff,0xff,0xff,0x43,0xa9,0xaa,0x4a,0x52,0xa9,0xf8,0xa4,
+ 0xaa,0x52,0x95,0xfc,0xff,0xff,0xff,0x7f,0x52,0xc0,0x7f,0xff,0xa1,0x00,0x24,
+ 0xfa,0xff,0xff,0xff,0x0a,0xfe,0xff,0xff,0xff,0xff,0xff,0x17,0x92,0x24,0xa5,
+ 0x2a,0x55,0xfe,0xaa,0xa4,0x2a,0x29,0xf9,0xff,0xff,0xff,0xbf,0x2a,0xea,0x7f,
+ 0xff,0x05,0x92,0x90,0xfc,0xff,0xff,0xbf,0xa4,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0xa0,0xaa,0x54,0x49,0x25,0x7c,0x49,0x95,0xa4,0x12,0xfc,0xff,0xff,0xff,
+ 0x7f,0x8a,0xe0,0x7f,0xff,0xa3,0x04,0x05,0xfe,0xff,0xff,0xbf,0x06,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x1f,0x49,0x95,0x52,0xaa,0x12,0x7f,0x55,0x52,0x55,0x0a,
+ 0xfd,0xff,0xff,0xff,0x3f,0x29,0xe8,0x7f,0xff,0x0f,0x50,0x50,0xff,0xff,0xff,
+ 0x5f,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x04,0xa9,0x4a,0x25,0x45,0x3e,
+ 0xa9,0x2a,0xa9,0xa2,0xfc,0xff,0xff,0xff,0x7f,0x55,0xe1,0x7f,0xff,0x27,0x05,
+ 0xc4,0xff,0xff,0xff,0x9f,0x91,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x41,0x4a,
+ 0x29,0xa9,0x12,0x5e,0x95,0x94,0x4a,0x0a,0xfe,0xff,0xff,0xff,0xbf,0x12,0xf4,
+ 0x7f,0xff,0x8f,0x50,0xf1,0xff,0xff,0xff,0xa7,0xc2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x14,0x92,0xaa,0x4a,0xa2,0xbf,0xa4,0x52,0x95,0x22,0xff,0xff,0xff,
+ 0xff,0x3f,0x45,0xf2,0x7f,0xff,0x3f,0x04,0xf4,0xff,0xff,0xff,0xd7,0xe8,0xff,
+ 0xff,0xff,0xff,0x5f,0xff,0xff,0x83,0xa8,0x94,0x54,0x09,0x2f,0x55,0x4a,0x52,
+ 0x49,0xff,0xff,0xff,0xff,0x5f,0x99,0xf0,0x7f,0xff,0x7f,0x51,0xfc,0xff,0xff,
+ 0xff,0x6b,0xf1,0xff,0xff,0xff,0xff,0x5f,0xfd,0xff,0x2b,0x2a,0xa9,0x12,0x20,
+ 0x5f,0xa9,0xaa,0x54,0x00,0xff,0xff,0xff,0xff,0x5f,0x15,0xf2,0x7f,0xff,0xff,
+ 0x8f,0xff,0xff,0xff,0xff,0x2b,0xfc,0xff,0xff,0xff,0xff,0x2f,0xfd,0xff,0x87,
+ 0xa0,0x4a,0xaa,0x8a,0x9f,0x4a,0x52,0x15,0xa9,0xff,0xff,0xff,0xff,0x5f,0x8a,
+ 0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xf8,0xff,0xff,0xff,0xff,
+ 0x57,0xf2,0xff,0x2f,0x82,0x52,0x05,0xd0,0x2f,0x95,0x4a,0x49,0x84,0xff,0xff,
+ 0xff,0xff,0xbf,0x24,0xf8,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x12,0xfd,
+ 0xff,0xff,0xff,0xff,0x4b,0xd5,0xff,0x9f,0x28,0x54,0x48,0xc5,0xbf,0x52,0x55,
+ 0x0a,0xe1,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfa,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x1a,0xfe,0xff,0xff,0xff,0xff,0x57,0xa9,0xff,0x3f,0x82,0x00,0x21,
+ 0xf0,0x5f,0x2a,0x49,0x21,0xc4,0xff,0xff,0xff,0xff,0xaf,0x1a,0xfd,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0x85,0xff,0xff,0xff,0xff,0xff,0x29,0xa5,0xff,
+ 0xff,0x24,0x52,0x88,0xfc,0xbf,0x92,0x2a,0x09,0xf1,0xff,0xff,0xff,0xff,0x9f,
+ 0x4c,0xfc,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x15,0xff,0xff,0xff,0x7f,
+ 0xff,0xa5,0x4a,0xff,0xff,0x90,0x08,0x01,0xfe,0x3f,0x55,0x52,0x24,0xf4,0xff,
+ 0xff,0xff,0xff,0xaf,0x02,0xfd,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xc6,
+ 0xff,0xff,0xff,0xbf,0xfe,0x95,0x54,0xff,0xff,0x05,0x42,0xa8,0xfe,0xbf,0xa4,
+ 0x2a,0x41,0xf9,0xff,0xff,0xff,0xff,0x5f,0x55,0xfc,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4f,0xd0,0xff,0xff,0xff,0xbf,0x7c,0xaa,0x92,0xfc,0xff,0x53,0x08,
+ 0x01,0xff,0x1f,0x4a,0x01,0x04,0xfc,0xff,0xff,0xff,0xff,0x27,0x05,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xc5,0xff,0xff,0xff,0x4f,0xbf,0x52,0xaa,
+ 0xfe,0xff,0x07,0x42,0xea,0xff,0xbf,0x50,0x54,0x51,0xff,0xff,0xff,0xff,0xff,
+ 0x97,0x56,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xf0,0xff,0xff,0xff,
+ 0x2f,0x7f,0xa5,0x54,0xfd,0xff,0x3f,0x09,0xe0,0xff,0x1f,0x02,0x01,0x04,0xff,
+ 0xff,0xff,0xff,0xff,0xaf,0x02,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0xf5,0xff,0xff,0xff,0xab,0x9f,0x94,0x92,0xfc,0xff,0xff,0x40,0xfd,0xff,0x9f,
+ 0x48,0x48,0xa1,0xff,0xff,0xff,0xff,0xff,0xa7,0x56,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x6b,0xf8,0xff,0xff,0xff,0xa4,0x5f,0xa9,0x2a,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0x3f,0x22,0x21,0xc4,0xff,0xff,0xff,0xff,0xff,0x2f,0x03,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0xfa,0xff,0xff,0x7f,0xd5,0x2f,0xa5,
+ 0xa4,0xfa,0xff,0xff,0xff,0xff,0xff,0xbf,0x08,0x08,0xf9,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x4a,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x94,0xfc,0xff,0xff,
+ 0x7f,0x69,0xac,0x2a,0x55,0xf9,0xff,0xff,0xff,0xff,0xff,0x7f,0xa2,0x22,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0x21,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x15,0xfe,0xff,0xff,0x9f,0x2a,0x95,0x94,0x92,0xf4,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x08,0x88,0xfe,0xff,0xff,0xff,0xff,0xff,0x57,0x8b,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xa9,0xfe,0xff,0xff,0x5f,0x52,0xbc,0x52,0x55,0xf5,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x21,0x21,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xa1,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x7f,0x0d,0xff,0xff,0xff,0x57,0x15,0x3f,
+ 0x55,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xc8,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xd7,0x89,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xbf,0xd6,0xff,0xff,
+ 0xff,0x4b,0x45,0x3f,0x49,0xaa,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xf9,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xc9,0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0x81,0xff,0xff,0xff,0x29,0x11,0x5f,0x28,0x55,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xc8,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0xd6,0xff,0xff,0x7f,0xaa,0xc2,0x0f,0x55,0x49,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa5,
+ 0xe2,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x9f,0xe1,0xff,0xff,0xbf,0x4a,0xd1,
+ 0x5f,0x48,0xa5,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xe9,0xe0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x27,0xf4,0xff,
+ 0xff,0xbf,0x94,0xc4,0x07,0x91,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xea,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0xf1,0xff,0xff,0x9f,0x52,0xe0,0x4b,0x44,0x52,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6a,0xe0,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xab,0x2a,0xf5,0x0f,0x51,0xa5,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x69,0xe5,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x55,0xf8,0xff,0xff,0x95,0x14,
+ 0xf0,0x5f,0x84,0x54,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x75,0xf0,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x13,0xfd,
+ 0xff,0xff,0xa5,0x42,0xf9,0x7f,0x91,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xb2,0xfa,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0x54,0xfe,0xff,0x7f,0x52,0x12,0xfa,0xff,0x20,0xa5,0xe4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x34,0xf8,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x25,0xff,0xff,0xaf,0xaa,0x48,0xfc,0xff,0x0b,
+ 0x29,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xb5,0xf8,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0x52,0xff,0xff,0x2f,0x49,
+ 0x02,0xfe,0xff,0x43,0xaa,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x3a,0xfa,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x4a,
+ 0xff,0xff,0xa5,0x2a,0xa9,0xff,0xff,0x17,0x25,0xe9,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x9a,0xfc,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0x2a,0xff,0x7f,0x95,0x54,0x80,0xff,0xff,0x07,0xa9,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x1d,0xfc,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x3f,0xa9,0xfe,0x7f,0xa9,0x12,0xe5,0xff,0xff,
+ 0x5f,0x4a,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x5f,0xad,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0x95,0xea,0x97,0x54,
+ 0x4a,0xf0,0xff,0xff,0x1f,0xa8,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x5f,0x0e,0xfe,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,
+ 0x52,0x55,0xa9,0x92,0x02,0xfd,0xff,0xff,0x5f,0x53,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x5e,0xfe,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xbf,0x2a,0x49,0x4a,0x55,0x49,0xfc,0xff,0xff,0x3f,0x94,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x0f,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,0xa5,0xaa,0x92,0xa4,0x20,0xff,0xff,
+ 0xff,0xbf,0xa4,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x57,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x52,0x52,0xaa,
+ 0x2a,0x0a,0xff,0xff,0xff,0x7f,0x54,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x07,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xa7,0x94,0x4a,0x55,0x4a,0xa0,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x57,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x2f,0x55,0xa9,0x92,0x12,0xe9,0xff,0xff,0xff,0x7f,0x24,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x87,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0xa5,0x4a,0xaa,0x44,0xf4,0xff,
+ 0xff,0xff,0xff,0x55,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0xab,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xab,0x94,0xa4,
+ 0x92,0x12,0xf9,0xff,0xff,0xff,0xff,0xa8,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xab,0x83,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x47,0xa9,0x2a,0x55,0x40,0xfc,0xff,0xff,0xff,0xff,0x25,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,0xff,0xd7,0x97,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0x33,0x55,0xa9,0x24,0x15,0xfe,0xff,0xff,0xff,0xff,
+ 0x95,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,
+ 0x93,0xc3,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x25,0xa5,0x2a,0x40,0xff,
+ 0xff,0xff,0xff,0xff,0xa9,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xff,
+ 0xff,0xff,0xff,0xff,0xe7,0xd5,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4b,0x92,
+ 0x54,0x92,0xd4,0xff,0xff,0xff,0xff,0xff,0x55,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xe9,0xff,0xff,0xff,0xff,0xff,0xd5,0xc1,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0x97,0xaa,0x4a,0x05,0xe2,0xff,0xff,0xff,0xff,0xff,0x25,0xf1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xfd,0xff,0xff,0xff,0xff,0xd5,0xea,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0x57,0x55,0x25,0xa1,0xf0,0xff,0xff,0xff,0xff,
+ 0xff,0x95,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe8,0xfa,0xff,0xff,0xff,
+ 0xff,0xea,0xe0,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xa7,0x24,0x59,0x04,0xfa,
+ 0xff,0xff,0xff,0xff,0xff,0xa9,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe2,
+ 0xfd,0xff,0xff,0xff,0xff,0xc9,0xe9,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x4f,
+ 0x52,0x05,0xa1,0xfc,0xff,0xff,0xff,0xff,0xff,0xa5,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x70,0xf9,0xff,0xff,0xff,0xff,0x74,0xe2,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0x47,0x95,0x92,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0xf8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xe2,0xfa,0xff,0xff,0xff,0xff,0x72,0xe8,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x97,0xaa,0x20,0xd0,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xb8,0xfc,0xff,0xff,
+ 0xff,0xff,0xea,0xe2,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x07,0x04,0x82,0xc2,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x29,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x71,0xfd,0xff,0xff,0xff,0x7f,0x2a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0x4f,0x91,0x28,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0xfc,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x1f,0x54,0xfe,0xff,0xff,0xff,0x7f,0x75,0xf2,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0x27,0x44,0x82,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0x29,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xb8,0xfc,0xff,0xff,0xff,0xbf,0x14,
+ 0xf1,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x0f,0x11,0x20,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x55,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x9a,0xfe,0xff,
+ 0xff,0xff,0x7f,0x5a,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x5f,0x40,0x85,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x4f,0x2d,0xfd,0xff,0xff,0xff,0x9f,0x12,0xf9,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0x3f,0x14,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0xa6,0xfe,0xff,0xff,0xff,0x5f,0x4d,0xfa,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0x40,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x09,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x4b,0xfe,0xff,0xff,0xff,0xbf,
+ 0x2c,0xf8,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x43,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x57,0xff,
+ 0xff,0xff,0xff,0x5f,0x0a,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xd5,0xa9,0xff,0xff,0xff,0xff,0xaf,0x5a,0xfc,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa3,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x81,0x95,0xff,0xff,0xff,0xff,0x9f,0x06,0xfd,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xca,0xa5,0xff,0xff,0xff,0xff,
+ 0x2f,0x95,0xfc,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xea,
+ 0xff,0xff,0xff,0xff,0xaf,0x26,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xf5,0xf4,0xff,0xff,0xff,0xff,0xaf,0x86,0xfe,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x70,0xe5,0xff,0xff,0xff,0xff,0x4f,0x2e,0xfe,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xb2,0xfa,0xff,0xff,0xff,
+ 0xff,0x57,0x83,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf3,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x78,
+ 0xf2,0xff,0xff,0xff,0xff,0xa7,0x22,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x5f,0x5d,0xfd,0xff,0xff,0xff,0xff,0x97,0x87,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x3c,0xfd,0xff,0xff,0xff,0xff,0x53,0xa3,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xac,0xfe,0xff,0xff,
+ 0xff,0xff,0x57,0x95,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,
+ 0x9e,0xfe,0xff,0xff,0xff,0xff,0x97,0x81,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x57,0xfe,0xff,0xff,0xff,0xff,0xa9,0xa5,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0xaf,0xff,0xff,0xff,0xff,0xff,0x4b,
+ 0x89,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0x93,0xff,0xff,
+ 0xff,0xff,0xff,0x95,0xa2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x83,0xab,0xff,0xff,0xff,0xff,0xff,0xd3,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,
+ 0xff,0xff,0xff,0xff,0xe9,0xa5,0xff,0xff,0xff,0xff,0xff,0xa5,0xe1,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xd5,0xff,0xff,0xff,0xff,0xff,
+ 0xd5,0xc8,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xea,0xea,0xff,
+ 0xff,0xff,0xff,0xff,0x14,0xc1,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,
+ 0xff,0xe0,0xe4,0xff,0xff,0xff,0xff,0xff,0x65,0xe8,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,
+ 0xff,0xff,0xff,0xff,0x3f,0x72,0xe9,0xff,0xff,0xff,0xff,0xff,0x6a,0xe1,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xbf,0xb8,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0x52,0xea,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0x1f,0x7a,0xf5,
+ 0xff,0xff,0xff,0xff,0x7f,0x2a,0xe0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,0xff,0xff,0xff,
+ 0xff,0x8f,0x58,0xfa,0xff,0xff,0xff,0xff,0x7f,0x25,0xf5,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xb5,0xff,0xff,0xdf,0xff,0x57,0x5e,0xfd,0xff,0xff,0xff,0xff,0xff,0x34,0xe0,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xca,0xff,0xff,0x8f,0xff,0x07,0xac,0xfc,0xff,0xff,0xff,
+ 0xff,0x7f,0x2a,0xf5,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd4,0xff,0xff,0x57,0xff,0x2b,0x2d,
+ 0xfd,0xff,0xff,0xff,0xff,0xff,0xb2,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd2,0xff,0xff,
+ 0x07,0xff,0x43,0x4a,0xff,0xff,0xff,0xff,0xff,0xbf,0x2a,0xf8,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x3f,0xc5,0xff,0xff,0x2b,0xfe,0x08,0xab,0xfe,0xff,0xff,0xff,0xff,0x7f,0xaa,
+ 0xf2,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xea,0xff,0xff,0x83,0x36,0x20,0x55,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x15,0xf0,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xc2,0xff,0xff,0x48,0x4a,0x85,
+ 0x49,0xff,0xff,0xff,0xff,0xff,0x7f,0x59,0xfa,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xf5,0xff,
+ 0x7f,0x10,0x29,0x50,0xa5,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xf9,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0xe4,0xff,0x7f,0x05,0x95,0x42,0xd5,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0x35,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0xea,0xff,0xbf,0xa0,0x24,0xa8,0xd4,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0x19,0xf9,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x27,0xe5,0xff,0x3f,0x92,0xaa,
+ 0x50,0xe9,0xff,0xff,0xff,0xff,0xff,0x9f,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa9,0xe2,
+ 0xff,0x9f,0xa0,0xaa,0x2a,0xf5,0xff,0xff,0xff,0xff,0xff,0x5f,0x1a,0xf9,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xf8,0xff,0x5f,0x4a,0x92,0x4a,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x4a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xf2,0xff,0x1f,0x20,0x49,0xa5,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0x1a,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0xf8,0xff,0x47,0xa9,
+ 0x2a,0x29,0xf9,0xff,0xff,0xff,0xff,0xff,0xbf,0x0a,0xfc,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf2,0xff,0x17,0x92,0xaa,0xaa,0xfe,0xff,0xff,0xff,0xff,0xff,0x9f,0xac,0xfe,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf8,0xff,0x43,0xa8,0x24,0x25,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xaf,0x0a,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xfa,0xff,0x91,0x54,0xaa,0x52,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2f,0x4d,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x45,0xfc,0xff,0x03,
+ 0x92,0x52,0xaa,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x06,0xfc,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,
+ 0x12,0xfe,0xff,0x50,0xaa,0x2a,0x95,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0xa5,
+ 0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x44,0xff,0xff,0x0a,0x25,0xa5,0xa4,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x97,0x06,0xfc,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2b,0x15,0xff,0xff,0x40,0xa9,0x92,0xea,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x55,0xfd,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xa1,0xff,0x7f,
+ 0x92,0x4a,0xaa,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x06,0xfc,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x95,0x8a,0xff,0x3f,0x84,0x54,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x25,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x52,0xe0,0xff,0xbf,0x50,0xa9,0x4a,0xf2,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x8e,0xfe,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa9,0xea,0xff,0x3f,0x24,0x95,0x54,
+ 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x23,0xfe,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x4a,0xf0,0xff,
+ 0x9f,0x50,0x69,0x49,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x8b,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xa5,0xf4,0xff,0x0f,0x2d,0x75,0xaa,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaf,0x03,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x14,0xfa,0xff,0x2f,0xa8,0xfa,0x25,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xaa,0xfc,0xff,0x0f,0x4d,0xfd,
+ 0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0x83,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x12,0xfc,
+ 0xff,0x27,0x92,0xfe,0xcb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x97,0x0a,0xff,0xff,0x83,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xef,0xc7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xab,0x24,0xff,0xff,0x2b,0xaa,0xfe,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xe7,0xef,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0x05,0x95,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x82,
+ 0xff,0xff,0x51,0xa9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xa9,0xe8,0xff,0xff,0x85,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0x52,0xc1,0xff,0xff,0x90,0xd5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x4d,0xe8,0xff,0xff,0xa5,
+ 0xe4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x51,
+ 0xf2,0xff,0x7f,0x40,0xd5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x3f,0x95,0xf8,0xff,0x7f,0xa9,0xea,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x15,0xfa,0xff,0x3f,0xa4,0xf4,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xa4,0xfc,0xff,0x7f,
+ 0x71,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,
+ 0x15,0xfe,0xff,0x3f,0x94,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xa7,0x0a,0xff,0xff,0x1f,0x79,0xf2,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xa4,0xff,0xff,0x5f,0x8c,0xfa,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x82,0xff,0xff,
+ 0x1f,0x5c,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xa4,0x92,0xff,0xff,0xbf,0x56,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9a,0xc4,0xff,0xff,0x0f,0x2e,0xfd,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa2,0xf0,0xff,0xff,0xaf,0xa7,0xfe,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x55,0xe4,0xff,
+ 0xff,0x0f,0x57,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xbf,0x54,0xf2,0xff,0xff,0x9f,0x4b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x9f,0x92,0xf8,0xff,0xff,0xc7,0xab,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x15,0xfe,0xff,0xff,0x97,0xd7,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xa7,0x94,0xfc,
+ 0xff,0xff,0xc7,0xe3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x2f,0x05,0xfe,0xff,0xff,0xcf,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x53,0xa9,0xff,0xff,0xff,0xd3,0xeb,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x05,0xff,0xff,0xff,0xe3,
+ 0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0xc2,
+ 0xff,0xff,0xff,0xeb,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x95,0xc8,0xff,0xff,0xff,0xf3,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xd2,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xaa,0xe0,0xff,0xff,0xff,
+ 0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x49,
+ 0xf8,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x9f,0x2a,0xf5,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x4a,0xf8,0xff,0xff,0xff,0xff,0xfc,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x14,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x97,
+ 0x4a,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xab,0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x95,0x52,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0x85,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x54,0xa2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x4a,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xa5,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x94,0xe4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x5f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0x12,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4f,0x54,0xfa,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0x0a,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x53,0x45,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x97,0x14,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x4b,0x45,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x54,0x82,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x4a,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x52,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x55,0xe8,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,
+ 0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x55,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0x24,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x15,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,
+ 0x49,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x2f,0x95,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0x01,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0xd5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x57,0x81,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x97,0xd4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaf,0xe0,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x93,0xf4,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x57,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2b,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x89,0xfc,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x05,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x49,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x22,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x89,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xe5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xe9,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x9f,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x6f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f};
diff --git a/etc/gnus/gnus.xpm b/etc/gnus/gnus.xpm
new file mode 100644 (file)
index 0000000..b6ee4d0
--- /dev/null
@@ -0,0 +1,284 @@
+/* XPM */
+static char *gnus[] = {
+/* width height num_colors chars_per_pixel */
+"   271   273        3            1",
+/* colors */
+". s thing c #bf9900",
+"# s shadow c #ffcc00",
+"a s None c None",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............#######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........................#######aaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................######aaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................######aaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............................#######aaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................aaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................aaaaaaaaaaaaaaaa....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................########aaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......................aaaaaaaaaaaaaa........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.................................#######aaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................aaaaaaaaaaa............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................########aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................aaaaaaaaa..............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................aaaaaaa................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................aaaaa..................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......######.......................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................aaaa...................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#######aa....................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................aa.....................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaa.................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................a......................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaa................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaa...............#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaa...............#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaa..............#######aaaaa",
+"aaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaa..............#######aaaaa",
+"aaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa.............#######aaaaa",
+"aaaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............####....................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaa............########aaaaa",
+"aaaaaaa.........aaaaaaaaaaaaaaaaaaaaaaaaaaa.............########...................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaa.............############..................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaaa..........aaaaaaaaaaaaaaaaaaaaaa.............##############..................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaaa...........aaaaaaaaaaaaaaaaaaaa............##################.......................##########................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaa..........########aaaaa",
+"aaaaaaaa............aaaaaaaaaaaaaaaaaa............####################....................###############..............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaa............aaaaaaaaaaaaaaaa..............#####################.................#####################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa..aaaaa###aaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaa.............aaaaaaaaaaaaaa..............#######################...............#######################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa..aaaaa##aaaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaaa.............aaaaaaaaaaa...............##########aa#############.............#########################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaaa.............aaaaaaaaa................#########aaaaaaa###########............##########################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa................aaaa..................#######aaaaaaaaaa###########..........############################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa.....................................######aaaaaaaaaaaaa###########.........#############################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa....................................######aaaaaaaaaaaaaaaa#########........###############################.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaaa.................................#######aaaaaaaaaaaaaaaaaa#########.......#######aaaaaaaaaaa##############..........................aaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaaa................................#######aaaaaaaaaaaaaaaaaaaa########......#####aaaaaaaaaaaaaaaaa############..........................aaaaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaaa...............................########aaaaaaaaaaaaaaaaaaaaa########....#####aaaaaaaaaaaaaaaaaaaaa##########..........................aaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaa#..............................########aaaaaaaaaaaaaaaaaaaaaaaa#.####...#####aaaaaaaaaaaaaaaaaaaaaaa##########...........................aaaaaaaaaaaaaaaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaa#.............................########aaaaaaaaaaaaaaaaaaaaaaaaa...###..######aaaaaaaaaaaaaaaaaaaaaaaa##########...........................aaaaaaaaaaaaaaaaaaa......a#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###...........................#########aaaaaaaaaaaaaaaaaaaaaaaa....##########aaaaaaaaaaaaaaaaaaaaaaaaaa##########............................aaaaaaaaaaaaaaa........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###..........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....#########aaaaaaaaaaaaaaaaaaaaaaaaaaaa##########...............................aaaaaaaa...........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###.........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....a#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaa##########................................................##aaaaaa...aaaaaaaaaaaaaaaaaaaaa......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaaa####........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....aaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...............................................##aaaaaa....aaaaaaaaaaaaaaaaaaa.......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaaa####.......................########aaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########..............................................##aaaaa.....aaaaaaaaaaaaaaaaaa.......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa######....................#########aaaaaaaaaaaaaaaaaaaaaaaaaa.....a#aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########............................................##aaaaaa......aaaaaaaaaaaaaaa.........a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa######...................#########aaaaaaaaaaaaaaaaaaaaaaaaaa......##aaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...........................................##aaaaa.......aaaaaaaaaaaaa..........aa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa#######.................#########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a###aaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.........................................###aaaaa.........aaaaaaa..............a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........########aaaaaaaa",
+"aaaaaaa#######...............#########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########........................................##aaaaa...............................a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaa########............##########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.......................................##aaaaa...............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaaa##########.......###########aaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.....................................###aaaaa..............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaaaa##########################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########....................................##aaaaa...............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........########aaaaaaaaa",
+"aaaaaaaaa#########################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########..................................###aaaaa..............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaa#######################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...............................####aaaaa..............................######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaaa#####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.............................#####aaaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaaa###################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...........................######aaaa..............................######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......########aaaaaaaaaa",
+"aaaaaaaaaaaa#################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.........................######aaaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaaa",
+"aaaaaaaaaaaaa###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaa#########.......................#######aaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaa#########....................#########aaaa............................########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaaaaaaaaaaaaa#########..................#########aaaaa..........................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........aaaaaaaaaaaaaaa###########.............###########aaaaa.........................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............aaaaaaaaaaaaaaa##############....###############aaaaaaa.......................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............aaaaaaaaaaaaaaa##############################aaaaaaaaa.....................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaa############################aaaaaaaaaaa...................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa................aaaaaaaaaaaaaaaa##########################aaaaaaaaaaaa#................#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaa.................aaaaaaaaaaaaaaaa########################aaaaaaaaaaaaa##..............#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaa...................aaaaaaaaaaaaaaaa######################aaaaaaaaaaaaa#####.........###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaa....................aaaaaaaaaaaaaaaaa###################aaaaaaaaaaaaaaa########..##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaa....................aaaaaaaaaaaaaaaaaaa################aaaaaaaaaaaaaaaa###########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaa......................aaaaaaaaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaa##########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa........a###a.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaa........a####a.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaa........a#####aaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaa#.....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaa##....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaa..........######aaaaa#####..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaa...........#####aaaaa#######..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaaa...........#####aaaaaa#######..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaaa...........######aaaaa#########.................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaa...........######aaaaa###########................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaa##########...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......####aaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaaaa#########...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaaaaaaa########..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......###aaaaaaaaaaaaaaaaaaaaa............#########aaaaaaaaaaaaa#######..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......###aaaaaaaaaaaaaaaaaaa.............#########aaaaaaaaaaaaaaa#######.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaaaa.............#########aaaaaaaaaaaaaaaaa######.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaa..............#########aaaaaaaaaaaaaaaaaaa#####.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaa...............#########aaaaaaaaaaaaaaaaaaaa#####.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaa...............#########aaaaaaaaaaaaaaaaaaaaaa#####............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaa..................########aaaaaaaaaaaaaaaaaaaaaaaaa####............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................................########aaaaaaaaaaaaaaaaaaaaaaaaaa####...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....................................########aaaaaaaaaaaaaaaaaaaaaaaaaaaa###...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaa####..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#...................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##................#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.......##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###............##############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#......###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####.........###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#......###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######..###################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#....####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#...####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#aaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaa#######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#aaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaa#######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#aaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaa########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#aaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaa########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#aaaaaaaaaaaaaaaaaaaa#######aaaaaaa#########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......##aaaaaaaaaaaaaaaaaaa########a..aa##########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........##aaaaaaaaaaaaaaaaaa#########....##########a........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaaa#########......#########........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#aaaaaaaaaaaaaaaaaa#########......########a........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........##aaaaaaaaaaaaaaaaa#########.......#######.........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........##aaaaaaaaaaaaaaaaa########.........#####.........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........###aaaaaaaaaaaaaaaa########........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........###aaaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........###aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........####aaaaaaaaaaaaaaa#########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa#######........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaa#######.........a..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa#######a........aaa............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa#######........aaaaa..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaa#######a.......aaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa######a........aaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaa#######........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaa#######a......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaa#####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaa####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaa#####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaa####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaa####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaa###aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaa####aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaa####aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaa###aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaa###aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaa####aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaa###aaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaa###aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+};
+
diff --git a/etc/gnus/important.xpm b/etc/gnus/important.xpm
new file mode 100644 (file)
index 0000000..e972fac
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char *magick[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 2  1",
+"! c red",
+"w c Gray75",
+/* pixels */
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwww!!!wwwwwwwwwwww",
+"wwwwwwwww!!!wwwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwww!!!!!!!wwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwwww!!!wwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwww!!!wwwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwww!!!!!wwwwwwwwwww",
+"wwwwwwwww!!!wwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww"
+};
diff --git a/etc/gnus/kill-group.pbm b/etc/gnus/kill-group.pbm
new file mode 100644 (file)
index 0000000..5083144
Binary files /dev/null and b/etc/gnus/kill-group.pbm differ
diff --git a/etc/gnus/kill-group.xpm b/etc/gnus/kill-group.xpm
new file mode 100644 (file)
index 0000000..1ee4fa4
--- /dev/null
@@ -0,0 +1,30 @@
+/* XPM */
+static char * kill_group_xpm[] = {
+"24 24 3 1",
+".     c None",
+"o     c #000000000000",
+"+     c #9A9A6C6C4E4E",
+"o..o..o..o..o..o..o..o..",
+"........................",
+"........................",
+"o..o..o..o..o..o..o..o..",
+"........................",
+"........................",
+"o..o..o..o..++.o..o..o..",
+".......++..++++.........",
+"........++.+++..........",
+"o..o..o.+++++..o..o..o..",
+".........+++............",
+".........++++...........",
+"o..o..o.++++++.o..o..o..",
+"........++.++++.........",
+".......++...++++........",
+"o..o...+.o...++o..o..o..",
+"........................",
+"........................",
+"o..o..o..o..o..o..o..o..",
+"........................",
+"........................",
+"o..o..o..o..o..o..o..o..",
+"........................",
+"........................"};
diff --git a/etc/gnus/mail-reply.pbm b/etc/gnus/mail-reply.pbm
new file mode 100644 (file)
index 0000000..9ca7659
Binary files /dev/null and b/etc/gnus/mail-reply.pbm differ
diff --git a/etc/gnus/mail-reply.xpm b/etc/gnus/mail-reply.xpm
new file mode 100644 (file)
index 0000000..a87f784
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * mail_reply_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #000000000000",
+"X     c #E1E1E0E0E0E0",
+"O     c #FFFFFFFFFFFF",
+"o     c #C7C7C6C6C6C6",
+"               ..       ",
+"               .X.      ",
+"              ..XX.     ",
+"         ......XoXX..   ",
+"       ...OOO.XooXXX.   ",
+"      ..OOOO.XooXXX.    ",
+"   ...OOOOO.XooXXX...   ",
+"  ..OOOOOO.XXooXX.OO..  ",
+"  ...OOOO.oooXXX......  ",
+"  .O...O.oXooXXX...OO.  ",
+"  .OOO...oXoXX...OOOO.  ",
+"  .OOOOO...X...OOOOOO.  ",
+"  .OOOOO.O...OO.OOOOO.  ",
+"  .OOO..OOOOOOOO..OOO.  ",
+"  .OO.OOOOOOOOOOOO.OO.  ",
+"  .O.OOOOOOOOOOOOOO.O.  ",
+"  ..OOOOOOOOOOOOOOOO..  ",
+"  ....................  ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};
diff --git a/etc/gnus/next-ur.pbm b/etc/gnus/next-ur.pbm
new file mode 100644 (file)
index 0000000..678bbb0
Binary files /dev/null and b/etc/gnus/next-ur.pbm differ
diff --git a/etc/gnus/next-ur.xpm b/etc/gnus/next-ur.xpm
new file mode 100644 (file)
index 0000000..bea1328
--- /dev/null
@@ -0,0 +1,35 @@
+/* XPM */
+static char * next_ur_xpm[] = {
+"24 24 8 1",
+".     c None",
+"      c #000000000000",
+"X     c #A5A5A5A59595",
+"o     c #C7C7C6C6C6C6",
+"O     c #FFFF00000000",
+"+     c #9A9A6C6C4E4E",
+"@     c #E1E1E0E0E0E0",
+"#     c #FFFFFFFFFFFF",
+" .. .. .. .. .. .. .. ..",
+"........................",
+"............X...........",
+" .. .. .. .XXX. .. .. ..",
+".........XXooOX.........",
+".......XXooo+O@X........",
+" .. XXXoooo++@@@X. .. ..",
+"....X@Xoooooo@@@X.......",
+"....X@@Xooo@@@@@@X......",
+" .. X@@XXoo@@@@@@@X.. ..",
+"....X@@Xoo@@@@@@@@@X....",
+"....X@Xo@@@XX@@@@@@oX...",
+" .. oXoo@XXooO@@@@@@X ..",
+"....oXoXXooo+OX@@@@Xo...",
+"....XXXoooo++@@X@@Xo....",
+" .. X@Xoooooo@@@XX .. ..",
+"....X@@Xooo@@@@@@X......",
+"....X@@XXoo@@@@@@@X.....",
+" .. X@@Xoo@@@@@@@@@X. ..",
+"....X@Xo@  @@@@@@@  X...",
+"... oXoo ## @@ @@ ## ...",
+" .. oXo ####  @  #### ..",
+".....oX #### @@@ #### ..",
+".....oX@ ## @@@@X ## ..."};
diff --git a/etc/gnus/oort.xface b/etc/gnus/oort.xface
new file mode 100644 (file)
index 0000000..6444b55
--- /dev/null
@@ -0,0 +1,3 @@
+X-Face: $BP*2z+\?fNM."!*~JsIgw(Y]n?WG!KMc;^jL$SLrt@X4%uMguO/$3HO<5@43P@[~'kE'fG
+ #YdP[sb6IJ5|Sm[z#9sI|)iJ})U5;Rt-?jI3i24zoJmonTV}kTVOm/5wMCnc3P~d#+BF1c&N6mdF{u
+ CE+<;lN!v~JRyR"q0d5<\y]faXpTC4,wpQ{=<==?LRA`}3qqIgr
diff --git a/etc/gnus/post.pbm b/etc/gnus/post.pbm
new file mode 100644 (file)
index 0000000..577d623
Binary files /dev/null and b/etc/gnus/post.pbm differ
diff --git a/etc/gnus/post.xpm b/etc/gnus/post.xpm
new file mode 100644 (file)
index 0000000..7a3eaa5
--- /dev/null
@@ -0,0 +1,35 @@
+/* XPM */
+static char * post_xpm[] = {
+"24 24 8 1",
+".     c None",
+"      c #434343434343",
+"X     c #A5A5A5A59595",
+"O     c #000000000000",
+"+     c #C7C7C6C6C6C6",
+"@     c #FFFF00000000",
+"#     c #9A9A6C6C4E4E",
+"$     c #E1E1E0E0E0E0",
+"O..O..O..O..O..O..O..O..",
+"........................",
+"............X...........",
+"O..O..O..O.XXX.O..O..O..",
+".........XX++@X.........",
+".......XX+++#@$X........",
+"O..OXXX++++##$$$X.O..O..",
+"....X$X++++++$$$X.......",
+"....X$$X+++$$$$$$X......",
+"O..OX$$XX++$$$$$$$X..O..",
+"....X$$X++$$$$$$$$$X....",
+"....X$X+$$$$$$$$$$$+X...",
+"O..O+X++$$$$$$$$$$$$XO..",
+"....+X+$$$$$$$$$$$$X+...",
+".....+X$$$$$$$$$$$X+....",
+"O..O.+X$$$$$$$$$XXO..O..",
+"......+X$$$$$$$X++......",
+"......+X$$$$$XX+........",
+"O..O..O+X$$$X++O..O..O..",
+".......+X$$X++..........",
+"........+XX+............",
+"O..O..O..O+.O..O..O..O..",
+"........................",
+"........................"};
diff --git a/etc/gnus/prev-ur.pbm b/etc/gnus/prev-ur.pbm
new file mode 100644 (file)
index 0000000..4938919
Binary files /dev/null and b/etc/gnus/prev-ur.pbm differ
diff --git a/etc/gnus/prev-ur.xpm b/etc/gnus/prev-ur.xpm
new file mode 100644 (file)
index 0000000..8013133
--- /dev/null
@@ -0,0 +1,35 @@
+/* XPM */
+static char * prev_ur_xpm[] = {
+"24 24 8 1",
+".     c None",
+"      c #000000000000",
+"X     c #A5A5A5A59595",
+"o     c #C7C7C6C6C6C6",
+"O     c #FFFF00000000",
+"+     c #9A9A6C6C4E4E",
+"@     c #E1E1E0E0E0E0",
+"#     c #FFFFFFFFFFFF",
+" .. .. .. .. .. .. .. ..",
+"........................",
+"............X...........",
+" .. .. .. .XXX. .. .. ..",
+".........XXooOX.........",
+".......XXooo+O@X........",
+" .. XXXoooo++@@@X. .. ..",
+"....X@Xoooooo@@@X.......",
+"....X@@Xooo@@@@@@X......",
+" .. X@@XXoo@@@@@@@X.. ..",
+"....X@@Xo  @@@@@@  X....",
+"....X@Xo ## X  @ ## X...",
+" .. oXo #XXXoO@ ####  ..",
+"....oXoXXooo+OX #### ...",
+"....XXXoooo++@@X ## ....",
+" .. X@Xoooooo@@@X  .. ..",
+"....X@@Xooo@@@@@@X......",
+"....X@@XXoo@@@@@@@X.....",
+" .. X@@Xoo@@@@@@@@@X. ..",
+"....X@Xo@@@@@@@@@@@@X...",
+"... oXoo@@@@@@@@@@@@X...",
+" .. oXo@@@@@@@@@@@@X....",
+".....oX@@@@@@@@@@@X.....",
+".....oX@@@@@@@@@@X......"};
diff --git a/etc/gnus/preview.xbm b/etc/gnus/preview.xbm
new file mode 100644 (file)
index 0000000..a42e153
--- /dev/null
@@ -0,0 +1,10 @@
+#define preview_width 24
+#define preview_height 24
+static char preview_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xc0,0x03,0x00,0x3e,0x06,0xf0,0x03,0x04,0x08,0x00,0x0a,0x78,0x00,0x09,
+ 0x88,0xf9,0x08,0x10,0xc6,0x10,0x10,0x3a,0x13,0x10,0x06,0x15,0x20,0x02,0x29,
+ 0x20,0x02,0x31,0x20,0xad,0x0f,0x40,0xf9,0x03,0xc0,0xb8,0x07,0x80,0x07,0x0e,
+ 0x80,0x01,0x1c,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,
+ 0x00,0x00,0x39,0x00,0x00,0x00,0x08,0xc0,0x12,0x42,0x00,0x00,0x00,0x00,0x38,
+ 0x82,0x18,0x08,0x00,0x00,0x00 };
diff --git a/etc/gnus/preview.xpm b/etc/gnus/preview.xpm
new file mode 100644 (file)
index 0000000..f5743f9
--- /dev/null
@@ -0,0 +1,33 @@
+/* XPM */
+static char *prev1[]={
+"24 24 6 1",
+". c None",
+"# c #000000",
+"d c #46463e",
+"a c #676663",
+"c c #a8a7a3",
+"b c #ebeae4",
+"........................",
+"........................",
+"........................",
+"........................",
+"........................",
+"..............####......",
+".........#####abbc#.....",
+"....#####acbbbbbbc#.....",
+"...#acbbbbbbbbbbacc#....",
+"...#baabbbbbbbbcacb#....",
+"...#cbcaabbd##dacbb#....",
+"....#bbbccdcbbcdabbc#...",
+"....#bbbbdccaaccdacb#...",
+"....#cbbb#abbbbb#bac#...",
+".....#bbb#cbbbbc#bbac#..",
+".....#bbbdcbbbbddbbc##..",
+".....#cbccdcbbd#####....",
+"......#babbd##dd##......",
+"......#acbc###.####.....",
+"......#aa##......###....",
+".......##.........###...",
+"...................##...",
+"........................",
+"........................"};
diff --git a/etc/gnus/receipt.xpm b/etc/gnus/receipt.xpm
new file mode 100644 (file)
index 0000000..18caaf1
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * receipt_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #FFFFFFFFFFFF",
+"X     c #676766666363",
+"o     c #FFFF00000000",
+"O     c #AEAE3E3E4848",
+"                        ",
+"                        ",
+"                   ..   ",
+"                    .   ",
+"                     .  ",
+"                     .  ",
+"                   ..   ",
+"           Xooo  ..     ",
+"      Xoooooooo..       ",
+" Xoooooooooooooo  ...   ",
+" oooooooooooOOoo .      ",
+" ooooooooooOOOOo.       ",
+"  oooooooooOO...o       ",
+"  ooooooooooOOooo       ",
+"  ooooooooooooooo       ",
+"   ooooooooooooooo      ",
+"   oooooooooooooo       ",
+"   ooooooooooo          ",
+"    ooooooo             ",
+"    oooo                ",
+"    oo                  ",
+"                        ",
+"                        ",
+"                        "};
diff --git a/etc/gnus/reply-wo.pbm b/etc/gnus/reply-wo.pbm
new file mode 100644 (file)
index 0000000..def54da
Binary files /dev/null and b/etc/gnus/reply-wo.pbm differ
diff --git a/etc/gnus/reply-wo.xpm b/etc/gnus/reply-wo.xpm
new file mode 100644 (file)
index 0000000..370678a
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * reply_wo_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #000000000000",
+"X     c #E1E1E0E0E0E0",
+"O     c #FFFFFFFFFFFF",
+"                        ",
+"                        ",
+"                        ",
+"           ....         ",
+"          ..X....       ",
+"         ..XX.XX..      ",
+"       .O.XX.XXXX..     ",
+"     ..O.XXX.XXXX...    ",
+"    .OO.XXXX.X.......   ",
+"   .OO.XXXX...XXX.OO..  ",
+" ..OO.XX....XXXX.OOOO.. ",
+" .......XX.XXXX.OOO.... ",
+" .OOO.XXX.XXXX.OO..OOO. ",
+" .OOOO....XXX....OOOOO. ",
+" .OOOOOOO..XX..OOOOOOO. ",
+" .OOOOOOO......OOOOOOO. ",
+" .OOOOOO.OO..O..OOOOOO. ",
+" .OOOOO.OOOOOOOO.OOOOO. ",
+" .OOOO.OOOOOOOOOO.OOOO. ",
+" .OOO.OOOOOOOOOOOO.OOO. ",
+" .O..OOOOOOOOOOOOOO..O. ",
+" ..OOOOOOOOOOOOOOOOOO.. ",
+" ...................... ",
+"                        "};
diff --git a/etc/gnus/reply.pbm b/etc/gnus/reply.pbm
new file mode 100644 (file)
index 0000000..ee181e6
Binary files /dev/null and b/etc/gnus/reply.pbm differ
diff --git a/etc/gnus/reply.xpm b/etc/gnus/reply.xpm
new file mode 100644 (file)
index 0000000..a458848
--- /dev/null
@@ -0,0 +1,31 @@
+/* XPM */
+static char * reply_xpm[] = {
+"24 24 4 1",
+"      c None",
+".     c #000000000000",
+"X     c #E1E1E0E0E0E0",
+"O     c #FFFFFFFFFFFF",
+"                        ",
+"                        ",
+"                        ",
+"           ....         ",
+"          ..XXX..       ",
+"         ..XXXXX..      ",
+"       .O.XXXXXXX..     ",
+"     ..O.XXXXXXXXX..    ",
+"    .OO.XXXXXXXXXX...   ",
+"   .OO.XXXXXXXXXX.OO..  ",
+" ..OO.XXXXXXXXXX.OOOO.. ",
+" .....XXXXXXXXX.OOO.... ",
+" .OOO.XXXXXXXX.OO..OOO. ",
+" .OOOO...XXXXX...OOOOO. ",
+" .OOOOOOO..XX..OOOOOOO. ",
+" .OOOOOOO......OOOOOOO. ",
+" .OOOOOO.OO..O..OOOOOO. ",
+" .OOOOO.OOOOOOOO.OOOOO. ",
+" .OOOO.OOOOOOOOOO.OOOO. ",
+" .OOO.OOOOOOOOOOOO.OOO. ",
+" .O..OOOOOOOOOOOOOO..O. ",
+" ..OOOOOOOOOOOOOOOOOO.. ",
+" ...................... ",
+"                        "};
diff --git a/etc/gnus/rot13.pbm b/etc/gnus/rot13.pbm
new file mode 100644 (file)
index 0000000..104246c
Binary files /dev/null and b/etc/gnus/rot13.pbm differ
diff --git a/etc/gnus/rot13.xpm b/etc/gnus/rot13.xpm
new file mode 100644 (file)
index 0000000..6e2d7ac
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * rot13_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #A5A5A5A59595",
+"X     c #C7C7C6C6C6C6",
+"o     c #E1E1E0E0E0E0",
+"O     c #919187876969",
+"                        ",
+"                        ",
+"                        ",
+"             .          ",
+"           ..X.         ",
+"         ..XXX.         ",
+"       ..XXXXXo.        ",
+"    ...XXXXXXooo.       ",
+"    .o.XXXXXoooo.       ",
+"    .oo.XXXooOooo.      ",
+"    .oo..XXoOXOOoo.     ",
+"    .oo.XXoOXooOXoo.    ",
+"    .o.XoooOOXXOXooX.   ",
+"     .XXooOOXOOXoooo.   ",
+"     .XooOOOooooooo.    ",
+"      .oOOXOXooooo.     ",
+"      .oOOXoooooo.      ",
+"       .oOOXooo..       ",
+"       .oooooo.         ",
+"        .ooo..          ",
+"        .oo.            ",
+"         ..             ",
+"                        ",
+"                        "};
diff --git a/etc/gnus/save-aif.pbm b/etc/gnus/save-aif.pbm
new file mode 100644 (file)
index 0000000..15829c2
Binary files /dev/null and b/etc/gnus/save-aif.pbm differ
diff --git a/etc/gnus/save-aif.xpm b/etc/gnus/save-aif.xpm
new file mode 100644 (file)
index 0000000..f0325ac
--- /dev/null
@@ -0,0 +1,33 @@
+/* XPM */
+static char * save_aif_xpm[] = {
+"24 24 6 1",
+"      c None",
+".     c #999999999999",
+"X     c #E1E1E0E0E0E0",
+"o     c #C7C7C6C6C6C6",
+"O     c #000000000000",
+"+     c #FFFFFFFFFFFF",
+"                        ",
+"                        ",
+"       .............    ",
+"       .XXXXXXXXXX.X..  ",
+"       .XXXXXXXXXX.XX.  ",
+"       .XXXXXXXXXX....  ",
+"       .XXXXXXXXXXooo.  ",
+"       .XXXXXXXXXXXXX.  ",
+"       .XXXXXXXXXXXXX.  ",
+"       .XXXXXXXXXXXXX.  ",
+" OOOOOOOOOOOOOOXXXXXX.  ",
+" O..O+++++++O.OXXXXXX.  ",
+" O..O+++++++O.OXXXXXX.  ",
+" O..O+++++++O.OXXXXXX.  ",
+" O..O+++++++O.OXXXXXX.  ",
+" O..O+++++++O.OXXXXXX.  ",
+" O..OOOOOOOOO.OXXXXXX.  ",
+" O............OXXXXXX.  ",
+" O............OXXXXXX.  ",
+" O..OOOOOOOOO.O.......  ",
+" O..OoooooO++.O         ",
+" O..OoooooO++.O         ",
+"  O.OoooooO++.O         ",
+"   OOOOOOOOOOOO         "};
diff --git a/etc/gnus/save-art.pbm b/etc/gnus/save-art.pbm
new file mode 100644 (file)
index 0000000..68fe0cb
Binary files /dev/null and b/etc/gnus/save-art.pbm differ
diff --git a/etc/gnus/save-art.xpm b/etc/gnus/save-art.xpm
new file mode 100644 (file)
index 0000000..fe9726f
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * save_art_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #C7C7C6C6C6C6",
+"                        ",
+"                        ",
+"     .................. ",
+"     ...XXXXXXXXXXXXX.. ",
+"     .XX..XXXXXXXXX..X. ",
+"     .XXXX..XXXXX..XXX. ",
+"     .XXXXX......XXXXX. ",
+"     .XXX..XX..XX..XXX. ",
+"     .XX..XXXXXXXX..XX. ",
+"     ...XXXXXXXXXXXX... ",
+" ..............XXXXXXX. ",
+" .oo.XXXXXXX.o......... ",
+" .oo.XXXXXXX.o.         ",
+" .oo.XXXXXXX.o.         ",
+" .oo.XXXXXXX.o.         ",
+" .oo.XXXXXXX.o.         ",
+" .oo.........o.         ",
+" .oooooooooooo.         ",
+" .oooooooooooo.         ",
+" .oo.........o.         ",
+" .oo.OOOOO.XXo.         ",
+" .oo.OOOOO.XXo.         ",
+"  .o.OOOOO.XXo.         ",
+"   ............         "};
diff --git a/etc/gnus/subscribe.pbm b/etc/gnus/subscribe.pbm
new file mode 100644 (file)
index 0000000..fe6b392
Binary files /dev/null and b/etc/gnus/subscribe.pbm differ
diff --git a/etc/gnus/subscribe.xpm b/etc/gnus/subscribe.xpm
new file mode 100644 (file)
index 0000000..ff193a9
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * subscribe_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #A5A5A5A59595",
+"X     c #E1E1E0E0E0E0",
+"o     c #C7C7C6C6C6C6",
+"O     c #8686ADAD7D7D",
+"                        ",
+"                        ",
+"                        ",
+"     ...                ",
+"   ..XXX.....           ",
+"...XXXXX..XXX. ...      ",
+".X.XX...XXXX...XXX.     ",
+".XX.X.X.XX...XXXXX.     ",
+".XX...XX.X.X.XXXXXX.    ",
+".XX.o.XX...XX.XXXXXX.   ",
+".X.oo.XX.o.XX..XXXXXX.  ",
+"o.ooo.X.oo.XX.XXXOXXX.  ",
+"o.oXXo.ooo.X.oXXOXXXXX. ",
+" o.XXo.oXXo.ooXXOXXXXX. ",
+" o.XXXo.XXo.oXXXOXXXXXX.",
+"  o.XXo.XXXo.XOOOOXXXXX.",
+"  o.XXoo.XXo.XXXOOXXXXX.",
+"   o.XXo.XXXo.XXXXXXX...",
+"   o.XX.o.XXo.XXXXXX.oo ",
+"    o..oo.XX.o.XXX..o   ",
+"     oo  o..oo.XX.oo    ",
+"          oo  o..o      ",
+"               oo       ",
+"                        "};
diff --git a/etc/gnus/unimportant.xpm b/etc/gnus/unimportant.xpm
new file mode 100644 (file)
index 0000000..4298224
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char *magick[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 2  1",
+"! c blue",
+"w c Gray75",
+/* pixels */
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"ww!!!wwwwww!!!wwwwww!!!w",
+"www!!!wwwww!!!wwwww!!!ww",
+"wwww!!!wwww!!!wwww!!!www",
+"wwwww!!!www!!!www!!!wwww",
+"wwwwww!!!ww!!!ww!!!wwwww",
+"wwwwwww!!!w!!!w!!!wwwwww",
+"wwwwwwww!!!!!!!!!wwwwwww",
+"wwwwwwwww!!!!!!!wwwwwwww",
+"wwwwwwwwww!!!!!wwwwwwwww",
+"wwwwwwwwwww!!!wwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww",
+"wwwwwwwwwwwwwwwwwwwwwwww"
+};
diff --git a/etc/gnus/unsubscribe.pbm b/etc/gnus/unsubscribe.pbm
new file mode 100644 (file)
index 0000000..7d869fb
Binary files /dev/null and b/etc/gnus/unsubscribe.pbm differ
diff --git a/etc/gnus/unsubscribe.xpm b/etc/gnus/unsubscribe.xpm
new file mode 100644 (file)
index 0000000..a91180d
--- /dev/null
@@ -0,0 +1,32 @@
+/* XPM */
+static char * unsubscribe_xpm[] = {
+"24 24 5 1",
+"      c None",
+".     c #A5A5A5A59595",
+"X     c #E1E1E0E0E0E0",
+"o     c #C7C7C6C6C6C6",
+"O     c #FFFF00000000",
+"                        ",
+"                        ",
+"                        ",
+"     ...                ",
+"   ..XXX.....           ",
+"...XXXXX..XXX. ...      ",
+".X.XX...XXXX...XXX.     ",
+".XX.X.X.XX...XXXXX.     ",
+".XX...XX.X.X.XXXXXX.    ",
+".XX.o.XX...XX.XXXXXX.   ",
+".X.oo.XX.o.XX..XXXXXX.  ",
+"o.ooo.X.oo.XX.XXXXXXX.  ",
+"o.oXXo.ooo.X.oXXXXXXXX. ",
+" o.XXo.oXXo.ooXXOXXXXX. ",
+" o.XXXo.XXo.oXXXOXXXXXX.",
+"  o.XXo.XXXo.XOOOXXXXXX.",
+"  o.XXoo.XXo.XoOOOXXXXX.",
+"   o.XXo.XXXo.XOoOXXX...",
+"   o.XX.o.XXo.XOXoXX.oo ",
+"    o..oo.XX.o.oXX..o   ",
+"     oo  o..oo.XX.oo    ",
+"          oo  o..o      ",
+"               oo       ",
+"                        "};
diff --git a/etc/gnus/uu-decode.pbm b/etc/gnus/uu-decode.pbm
new file mode 100644 (file)
index 0000000..2b7fada
Binary files /dev/null and b/etc/gnus/uu-decode.pbm differ
diff --git a/etc/gnus/uu-decode.xpm b/etc/gnus/uu-decode.xpm
new file mode 100644 (file)
index 0000000..b9d940c
--- /dev/null
@@ -0,0 +1,36 @@
+/* XPM */
+static char * uu_decode_xpm[] = {
+"24 24 9 1",
+"      c None",
+".     c #919187876969",
+"X     c #C2C2B9B99C9C",
+"o     c #868686868686",
+"O     c #8F8F8F8F8F8F",
+"+     c #000000000000",
+"@     c #4C4C4C4C4C4C",
+"#     c #E9E9EFEFE8E8",
+"$     c #8686ADAD7D7D",
+"                        ",
+"                        ",
+"                        ",
+"    ..............      ",
+"    X.o.........O.++    ",
+"    XX++++++++++..++    ",
+"    XX@########+..++    ",
+"    XX@########+..++    ",
+"    XX@$#$$$#$#+..++    ",
+"    XX@#$$$$$$#+..++    ",
+"    XX@##$#####+..++    ",
+"    XX@##$#$$##+..++    ",
+"    XX@##$#$$##+..++    ",
+"    XX@##$$#$$#+..++    ",
+"    XX@######$#+..++    ",
+"    XX@########+..++    ",
+"    XX@########+..++    ",
+"    XX.@@@@@@@@@..++    ",
+"    X.XXXXXXXXXX..++    ",
+"    .XXXXXXXXXXXX.++    ",
+"     +++++++++++++++    ",
+"     +++++++++++++++    ",
+"                        ",
+"                        "};
diff --git a/etc/gnus/uu-post.pbm b/etc/gnus/uu-post.pbm
new file mode 100644 (file)
index 0000000..a5face7
Binary files /dev/null and b/etc/gnus/uu-post.pbm differ
diff --git a/etc/gnus/uu-post.xpm b/etc/gnus/uu-post.xpm
new file mode 100644 (file)
index 0000000..7c4204c
--- /dev/null
@@ -0,0 +1,35 @@
+/* XPM */
+static char * uu_post_xpm[] = {
+"24 24 8 1",
+".     c None",
+"X     c #000000000000",
+"+     c #C2C2B9B99C9C",
+"@     c #919187876969",
+"#     c #868686868686",
+"%     c #4C4C4C4C4C4C",
+"&     c #E9E9EFEFE8E8",
+"*     c #8686ADAD7D7D",
+"X..X..X..X.XX..X..X..X..",
+"..........X.X...........",
+".........X...X..........",
+"X..X..X.XX..X.XX..X..X..",
+".......X.......X........",
+"......X.........X.......",
+"X..X+X@@@@@@@@@@@XX..X..",
+"....+@@@@@@@@@@@@@......",
+"....++XXXXXXXXXX@@......",
+"X..X++%&&&&&&&&X@@X..X..",
+"....++%&&&&&&&&X@@......",
+"....++%*&***&*&X@@......",
+"X..X++%&******&X@@X..X..",
+"....++%&&*&&&&&X@@......",
+"....++%&&*&**&&X@@......",
+"X..X++%&&*&**&&X@@X..X..",
+"....++%&&**&**&X@@......",
+"....++%&&&&&&*&X@@......",
+"X..X++%&&&&&&&&X@@X..X..",
+"....++%&&&&&&&&X@@......",
+"....++@%%%%%%%%%@@......",
+"X..X+@++++++++++@@X..X..",
+"....+++++++++++++@......",
+"........................"};
diff --git a/etc/gnus/x-splash b/etc/gnus/x-splash
new file mode 100644 (file)
index 0000000..cbd1c2c
Binary files /dev/null and b/etc/gnus/x-splash differ
diff --git a/etc/smilies/blink.pbm b/etc/smilies/blink.pbm
new file mode 100644 (file)
index 0000000..6c7531b
Binary files /dev/null and b/etc/smilies/blink.pbm differ
diff --git a/etc/smilies/blink.xpm b/etc/smilies/blink.xpm
new file mode 100644 (file)
index 0000000..5035122
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * blink_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".+++++++..++.",
+".+++++++..++.",
+".++...++++++.",
+".+++++++++++.",
+".++++++++.++.",
+".++.+++++.++.",
+".+++.....+++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/braindamaged.xpm b/etc/smilies/braindamaged.xpm
new file mode 100644 (file)
index 0000000..25bd3e7
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * mad_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".++...++++++.",
+".++.+.+...++.",
+".++...+.+.++.",
+".++++++...++.",
+".+.+++++++.+.",
+".+.+++++++.+.",
+".++.+++++.++.",
+".+++.....+++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/cry.xpm b/etc/smilies/cry.xpm
new file mode 100644 (file)
index 0000000..8d8558d
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * cry_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++++++++.++.",
+".+++++++.+.+.",
+".+++++++.+.+.",
+".++++++++..+.",
+".+++.....+++.",
+".++.+++++.++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/dead.xpm b/etc/smilies/dead.xpm
new file mode 100644 (file)
index 0000000..56463a7
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * dead_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++.+.+.+.++.",
+".+++.+++.+++.",
+".++.+.+.+.++.",
+".+++++++++++.",
+".+++++++++++.",
+".+.+++++++.+.",
+".++.......++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/evil.xpm b/etc/smilies/evil.xpm
new file mode 100644 (file)
index 0000000..c364ac3
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * diabolic_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".++.+++++.++.",
+".++..+++..++.",
+".++...+...++.",
+".+++++++++++.",
+".+.+++++++.+.",
+".++.+++++.++.",
+".+++.+++.+++.",
+".++++...++++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/forced.xpm b/etc/smilies/forced.xpm
new file mode 100644 (file)
index 0000000..43ba8d2
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * forced_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+".+++++++++++.",
+".+.+++++++.+.",
+".+.+++++++.+.",
+".+.........+.",
+".+++++++++++.",
+" ...+++++... ",
+"   .......   "};
diff --git a/etc/smilies/frown.pbm b/etc/smilies/frown.pbm
new file mode 100644 (file)
index 0000000..f51ea4f
Binary files /dev/null and b/etc/smilies/frown.pbm differ
diff --git a/etc/smilies/frown.xpm b/etc/smilies/frown.xpm
new file mode 100644 (file)
index 0000000..25ca99d
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * frown_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".++..+++..++.",
+".++++.+.++++.",
+".+...+++...+.",
+".+...+++...+.",
+".+++++++++++.",
+".+++.....+++.",
+".++.+++++.++.",
+".++.+++++.++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/grin.xpm b/etc/smilies/grin.xpm
new file mode 100644 (file)
index 0000000..292cb11
--- /dev/null
@@ -0,0 +1,21 @@
+/* XPM */
+static char * grin_xpm[] = {
+"13 14 4 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"@     c #FFFFFF",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+".+.........+.",
+".+.@@@@@@@.+.",
+".++.@@@@@.++.",
+".+++.....+++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/indifferent.xpm b/etc/smilies/indifferent.xpm
new file mode 100644 (file)
index 0000000..6395238
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * indifferent_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+".+++++++++++.",
+".+++++++++++.",
+".++.......++.",
+".+++++++++++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/reverse-smile.xpm b/etc/smilies/reverse-smile.xpm
new file mode 100644 (file)
index 0000000..56db090
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * reverse_smile_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++.....+++.",
+".++.+++++.++.",
+".++.+++++.++.",
+".+++++++++++.",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/sad.pbm b/etc/smilies/sad.pbm
new file mode 100644 (file)
index 0000000..892e343
Binary files /dev/null and b/etc/smilies/sad.pbm differ
diff --git a/etc/smilies/sad.xpm b/etc/smilies/sad.xpm
new file mode 100644 (file)
index 0000000..b0acef4
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * sad_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+".+++++++++++.",
+".+++.....+++.",
+".++.+++++.++.",
+".++.+++++.++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/smile.pbm b/etc/smilies/smile.pbm
new file mode 100644 (file)
index 0000000..f64e883
Binary files /dev/null and b/etc/smilies/smile.pbm differ
diff --git a/etc/smilies/smile.xpm b/etc/smilies/smile.xpm
new file mode 100644 (file)
index 0000000..374d240
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * smile_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".++..+++..++.",
+".++..+++..++.",
+".+++++++++++.",
+".+++++++++++.",
+".++.+++++.++.",
+".++.+++++.++.",
+".+++.....+++.",
+" .+++++++++. ",
+"  ..+++++..  ",
+"   .......   "};
diff --git a/etc/smilies/wry.pbm b/etc/smilies/wry.pbm
new file mode 100644 (file)
index 0000000..5fa5e9f
Binary files /dev/null and b/etc/smilies/wry.pbm differ
diff --git a/etc/smilies/wry.xpm b/etc/smilies/wry.xpm
new file mode 100644 (file)
index 0000000..8cd8ded
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * wry_xpm[] = {
+"13 14 3 1",
+"      c None",
+".     c #000000",
+"+     c #FFDD00",
+"   .......   ",
+"  ..+++++..  ",
+" .+++++++++. ",
+".+++++++++++.",
+".+++++++..++.",
+".++..+++..++.",
+".++..+++++++.",
+".+++++++++++.",
+".+++++++...+.",
+".+++++...+++.",
+".++++..+++++.",
+" .+++.+++++. ",
+"  ..+++++..  ",
+"   .......   "};
index 9bafbe5..f2f699f 100644 (file)
-Sat Feb 28 08:27:20 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2004-01-04 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus.el: Quassia Gnus v0.34 is released.
+       * gnus.el: Gnus v5.10.6 is released.
 
-Sat Feb 28 08:17:37 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2004-01-04  Kai Grossjohann  <kai@emptydomain.de>
 
-       * gnus.el: Quassia Gnus v0.33 is released.
+       * gnus-sum.el (gnus-summary-print-article): Doc fix.
 
-Sat Feb 28 08:10:27 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2004-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-picon.el (gnus-picons-display-x-face): `buf' -- unbound
-       var. 
+       * gnus.el (gnus-version-number): Bump.
 
-Sat Feb 28 08:03:23 1998  François Pinard  <pinard@iro.umontreal.ca>
+2004-01-04 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus: configure'd.
+       * gnus.el: Gnus v5.10.5 is released.
 
-Sat Feb 28 07:43:00 1998  Nelson Jose dos Santos Ferreira  <Nelson.Ferreira@inesc.pt>
+2004-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * nnsoup.el (nnsoup-store-reply): Fix double sep error.
+       * gnus-fun.el (gnus-face-from-file): Message 9.
 
-Sat Feb 28 07:01:17 1998  Lasse Rasinen  <lrasinen@iki.fi>
+2004-01-03  Romain FRANCOISE  <romain@orebokech.com>
 
-       * gnus-start.el (gnus-ask-server-for-new-groups): Message more. 
+       * gnus-fun.el (gnus-face-from-file): Use gnus-message.
 
-Fri Feb 27 13:26:34 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2004-01-03  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * message.el (message-resend): Allow arbitrary Also's.
+       * gnus-art.el (gnus-button-mid-or-mail-heuristic): Treat Gmane
+       addresses specially.  Fix returned value and messages.
 
-1998-02-27  Dave Love  <d.love@dl.ac.uk>
+       * mm-decode.el (mm-enable-external): New variable.
+       (mm-display-part): Use it.
+       (mm-display-external): Fix message in case of nil handle.
 
-       * gnus-sum.el (gnus-simplify-subject-functions): Fix
-       customization, doc.
+       * Update copyright for several files.
 
-1998-02-25  Dave Love  <d.love@dl.ac.uk>
+       * spam-report.el (spam-report-gmane): Adjust verbosity.
+       Delete trailing whitespace.  Update copyright.
 
-       * gnus-art.el (gnus-article-x-face-command): Replace leading `{'.
+       * spam.el: Fix many (but not all) checkdoc complaints.
+       Delete trailing whitespace.
 
-Mon Feb 23 18:26:48 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-header-synonyms): Defcustom.
+       (message-get-reply-headers): Catch `Original-To'.
+       (message-carefully-insert-headers): Added comment.
 
-       * gnus-agent.el (gnus-plugged): New command and keystroke.
+       * gnus-sum.el (gnus-summary-make-menu-bar): Improved "Washing" menu.
 
-       * gnus-ems.el (gnus-ems-redefine): Define
-       'gnus-summary-set-display-table as a function that takes no
-       params. 
+2004-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.el (gnus-interactive): Don't use gnus-sum macros.
-       (gnus-valid-select-methods): Include nnlistserv.
+       * gnus-sum.el (gnus-select-newsgroup): Use cat.
 
-       * gnus.el: Autoloaded things to make byte-comp silent.
+       * gnus-agent.el (gnus-agent-cat-enable-undownloaded-faces): New
+       cat. 
 
-Mon Feb 23 18:06:47 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus.el (gnus-user-agent): Moved here.
 
-       * gnus.el: Quassia Gnus v0.32 is released.
+       * gnus-msg.el (gnus-user-agent): Moved from here.
 
-Mon Feb 23 17:48:42 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.el (gnus-version-number): Bump.
 
-       * gnus-cite.el (gnus-article-hide-citation-maybe): Wrong
-       interactive specs.
-       (gnus-cite-toggle): Maybe parse.
+2004-01-03 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-Mon Feb 23 05:26:11 1998  Rui-Tao Dong ~{6-HpLN~}  <rdong@internetmci.com>
+       * gnus.el: Gnus v5.10.4 is released.
 
-       * nnweb.el (nnweb-type-definition): Fixed.
+2004-01-02  Reiner Steib  <Reiner.Steib@gmx.de>
 
-Sun Feb 22 18:10:53 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.el (gnus-mode-line-buffer-identification): Show version in
+       help-echo.
+       (gnus-read-group): Allow most group names.  Changed warning.
 
-       * gnus-agent.el (gnus-agent-group-path): Translate right chars.
-       (gnus-agent-toggle-plugged): Allow proper closing.
+2004-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-srvr.el (gnus-browse-read-group): Allow entering
-       non-ephemeral groups.
+       * gnus-dired.el (gnus-dired-mode-map): Change keymaps.
 
-Sun Feb 22 04:21:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2004-01-02  Arne J\e,Ax\e(Brgensen  <arne@arnested.dk>
 
-       * gnus.el: Quassia Gnus v0.31 is released.
+       * smime.el (smime-crl-check): Doc fix.
 
-Sun Feb 22 02:09:35 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2004-01-02  Edwin Steiner  <edwin.steiner@gmx.net>
 
-       * gnus-sum.el (gnus-summary-highlight): Give undownloaded marks a
-       better face.
+       * gnus-nocem.el (gnus-nocem-enter-article): Use the real group
+       hashtb (tiny patch).
 
-       * gnus-score.el (gnus-score-set): Take optional "warn".
-       (gnus-summary-score-entry): Use it.
+2004-01-02  Kai Grossjohann  <kai@emptydomain.de>
 
-       * gnus.el: Removed spurious * in defcustoms.
+       * nnml.el (nnml-save-mail): Grok compressed articles.  From
+       Michael Albinus <Michael.Albinus@alcatel.de>.
 
-       * gnus-score.el (gnus-score-load-file): Reverse logic.
+2004-01-02  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-cite.el (gnus-article-hide-citation): Use markers to make
-       things work when wrapping.
+       * spam.el (spam-ham-copy-or-move-routine): use spam-list-articles
+       (spam-list-articles): rewritten to only check a mark once per
+       invocation
 
-       * gnus-sum.el (gnus-summary-exit): Stop prefetch.
+2004-01-01  Simon Josefsson  <jas@extundo.com>
 
-Sat Feb 21 02:12:42 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mml-sec.el (mml-default-encrypt-method)
+       (mml-default-sign-method): Defcustom.
 
-       * gnus-sum.el (gnus-get-newsgroup-headers): Buggy regexp.
+2003-12-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sat Feb 21 00:51:22 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * mml.el (mml-generate-mime-1): Remove extra ).
 
-       * gnus.el: Quassia Gnus v0.30 is released.
+       * gnus-group.el (gnus-group-set-current-level): Signal errors on
+       topic lines.
+       (gnus-group-set-current-level): Fix fix.
 
-Sat Feb 21 00:09:14 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-31  Jeremy Maitin-Shepard  <jbms@attbi.com>
 
-       * gnus-sum.el (gnus-summary-mark-article): Don't do anything if
-       the mark doesn't change.
+       * mml.el (mml-generate-mime-1): Use mml-compute-boundary (tiny
+       change). 
 
-       * gnus-art.el (gnus-article-prepare): Don't enter article into
-       cache. 
+2003-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-sum.el (gnus-summary-reparent-thread): Don't mark as read.
-       (gnus-summary-mark-article): Don't do cache things here.
+       * gnus-group.el: Removed `(when t ...)' around `gnus-define-keys'.
+       (gnus-group-group-map): Added `gnus-group-read-ephemeral-group'
+       (already in previous commit inadvertently).
+       (gnus-group-make-menu-bar): Added `gnus-group-read-ephemeral-group'.
+       (gnus-group-read-ephemeral-group): Made interactive.
 
-       * gnus-util.el (gnus-parse-netrc): Skip past macdefs.
+       * gnus-score.el (gnus-score-find-trace): Added comment on sync
+       with `gnus-score-edit-file-at-point'.
 
-Fri Feb 20 22:56:22 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-logic.el (gnus-score-advanced): Ditto.
 
-       * gnus-srvr.el (gnus-browse-unsubscribe-group): Wouldn't allow
-       unsubscription. 
+       * gnus-score.el (gnus-score-edit-file-at-point): Fix for
+       advanced scoring.
 
-       * gnus-sum.el (gnus-summary-insert-subject): Allow inserting
-       articles outside limits.
+2003-12-30  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-start.el (gnus-dribble-enter): Update mode line.
+       * gnus-score.el (gnus-score-edit-file-at-point): Use
+       gnus-point-at-*, for portability.
 
-       * gnus-srvr.el (gnus-browse-unsubscribe-group): Allow
-       unsubscription. 
+2003-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-picon.el (gnus-article-display-picons): Check that the
-       extents are live first.
+       * gnus-art.el (gnus-treat-body-boundary): Fix doc-string and
+       custom type.
+       (gnus-button-mid-or-mail-regexp): Don't be too restrictive.
+       Suggested by Felix Wiemann <Felix.Wiemann@gmx.net>.
+       (gnus-button-alist): Added "M-x ... RET" and "mid:" buttons.
+       Added comments about relevant RFCs.
 
-Thu Feb 19 15:13:44 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el (gnus-summary-mode): Untabify doc-string.
+       (gnus-summary-goto-article): Allow `%40'.
+       (gnus-summary-refer-article): Convert `%40' to `@'.
 
-       * gnus-group.el (gnus-useful-groups): Include gnus-bug.
+2003-12-30  Simon Josefsson  <jas@extundo.com>
 
-Thu Feb 19 02:28:17 1998  Jens-Ulrik Holger Petersen  <petersen@kurims.kyoto-u.ac.jp>
+       * smime.el (smime-crl-check): New.
+       (smime-verify-region): Use it.  From Arne J\e,Ax\e(Brgensen
+       <arne@arnested.dk> in <87llpk9v5q.fsf@seamus.arnested.dk> (tiny
+       change).
 
-       * gnus.el (gnus-group-history): Defined twice.
+2003-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-Thu Feb 19 01:58:47 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-score.el (gnus-score-edit-file-at-point): Consider the
+       whole match element.  From Karl Pfl\e,Ad\e(Bsterer <sigurd@12move.de>.
+       (gnus-score-find-trace): Use it.  Added `f' and `t' commands,
+       added quick help.  With some suggestions from Karl Pfl\e,Ad\e(Bsterer
+       <sigurd@12move.de>.
 
-       * gnus-sum.el (gnus-get-newsgroup-headers): Just use the header
-       value. 
-       (gnus-summary-exit): Set global vars.
+       * gnus-util.el (gnus-emacs-version): Added doc-string.
 
-Tue Feb 17 07:17:49 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mml.el (mml-minibuffer-read-disposition): New function.
+       (mml-attach-file): Use it.
+       (mml-preview): Added MIME preview to gnus-buffers.
 
-       * gnus-sum.el (gnus-summary-stop-page-breaking): Mark page as no
-       longer broken.
-       (gnus-summary-exit): Purge the real name.
+2003-12-30  Jesper Harder  <harder@ifa.au.dk>
 
-Tue Feb 17 07:00:43 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add ellipses.
 
-       * gnus.el: Quassia Gnus v0.29 is released.
+2003-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Tue Feb 17 06:15:03 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-start.el (gnus-get-unread-articles): Inline gnus-server-get-method.
+       (gnus-get-unread-articles): Cache methods.
+       (gnus-get-unread-articles-in-group): Indent.
 
-       * nnmail.el (nnmail-purge-split-history): List of alists, not
-       alist. 
+       * gnus.el (gnus-version-number): Bump.
+       (gnus-secondary-method-p): Extend servers to methods before comparing.
+       (gnus-secondary-method-p): Revert.
 
-Mon Feb 16 20:22:04 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-12-30 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus.el: Quassia Gnus v0.28 is released.
+       * gnus.el: Gnus v5.10.3 is released.
 
-1998-02-16  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-29  Simon Josefsson  <jas@extundo.com>
 
-       * message.el (message-dont-send): Make sure the article really is
-       saved. 
+       * gnus-agent.el (gnus-agentize): Improve auto-agentizing logic.
+       Suggested by Steinar Bang <sb@dod.no>.
+       (gnus-agent-auto-agentize-methods): Customize.
 
-       * nnmail.el (nnmail-purge-split-history): Alist; not a list of
-       alists. 
+2003-12-29  Kevin Greiner <kgreiner@xpediantsolutions.com>
+       * gnus.el (gnus-server-to-method): Fixed bug in 2003-12-22
+       check-in.
 
-1998-02-16  Hrvoje Niksic  <hniksic@srce.hr>
+2003-12-28  Adrian Lanz  <lanz@fowi.ethz.ch>
 
-       * message.el (message-kill-to-signature): Do the right thing when
-       there is no signature.
+       * mail-source.el (mail-source-fetch-imap): Prevent storing of
+       identical entries for imap mail sources, when retrieving mail
+       messages from an imap server within the same Gnus session several
+       times (tiny change).
 
-1998-02-16  Hrvoje Niksic  <hniksic@srce.hr>
+2003-12-28  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el (message-elide-elipsis): Add type and group.
-       (message-elide-region): Docfix.
+       * mm-view.el (mm-text-html-washer-alist): Use
+       mm-inline-wash-with-stdin for w3m-standalone.
 
-1998-02-16  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-decode.el (mm-text-html-renderer): Add w3m-standalone.
 
-       * gnus-util.el (gnus-run-hooks): Use unwind-protect instead of
-       save-excursion. 
+       * mml1991.el (mml1991-pgg-encrypt): Decode according to CTE before
+       encrypting.
 
-1998-02-16  Per Abrahamsen  <abraham@dina.kvl.dk>
+2003-12-28  Jesper Harder  <harder@ifa.au.dk>
 
-       * nntp.el (nntp-authinforc-file): Customized.
+       * mml1991.el (mml1991-pgg-sign): Use unibyte when re-encoding.
+       From Ivan Boldyrev <boldyrev@uiggm.nsc.ru> (tiny change).
 
-Mon Feb 16 03:18:33 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-26  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-nocem.el (gnus-nocem-unwanted-article-p): Don't look if the
-       hashtable doesn't exist.
+       * dgnushack.el: Add an advice to byte-optimize-form-code-walker to
+       avoid the warning ``...called for effect'' for the pop form when
+       running Emacs 21.3.
 
-       * gnus-start.el (gnus-ask-server-for-new-groups): Make sure the
-       killed groups hashtable exists.
+2003-12-26  Jesper Harder  <harder@ifa.au.dk>
 
-Sun Feb 15 23:02:11 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-bodies.el (mm-body-encoding): Don't use 7bit if the body
+       contains "^From " and mm-use-ultra-safe-encoding is true.
 
-       * nntp.el (nntp-authinforc-file): Changed name and default.
-       (nntp-send-authinfo): Use it.
+2003-12-25  Jesper Harder  <harder@ifa.au.dk>
 
-Sun Feb 15 19:50:10 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * mml1991.el (mml1991-pgg-sign): Encode and decode according to
+       CTE header.  Don't insert gpg output as unibyte.
 
-       * gnus.el: Quassia Gnus v0.27 is released.
+2003-12-25  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sun Feb 15 19:41:14 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * lpath.el: Remove display-time-event-handler and open-ssl-stream;
+       add delete-extent for Emacs; rearrange bindings assuming w3 may
+       not be available and XEmacs without the file-coding feature may be
+       used.
 
-       * gnus.el (gnus-ephemeral-servers): New variable.
-       * gnus-srvr.el (gnus-server-prepare): Use it.
-       * gnus-group.el (gnus-group-read-ephemeral-group): Ditto.
+2003-12-24  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sun Feb 15 19:35:11 1998  Kurt Swanson  <kurt@dna.lth.se>
+       * dgnushack.el (dgnushack-compile): Increase the value for
+       max-specpdl-size when compiling Gnus with Emacs 20.
 
-       * gnus-art.el (gnus-article-read-summary-keys): Go to top on
-       some. 
+2003-12-22  Kevin Greiner <kgreiner@xpediantsolutions.com>
+       * gnus-int.el (gnus-open-server): Fixed the server status such
+       that an agentized server, when opened offline, has a status of
+       offline.  Also fixes bug whereby the agent's backend was called
+       twice to open each server.
 
-Sun Feb 15 19:26:21 1998  SeokChan LEE  <chan@xfer.kren.nm.kr>
+       * gnus-start.el (gnus-get-unread-articles-in-group): Autoload
+       gnus-agent-possibly-alter-active rather than inline to resolve
+       compiler warnings.
 
-       * message.el (message-ignored-supersedes-headers): Fix.
+       * gnus.el (gnus-server-to-method): Added fallback of iterating
+       over gnus-newsrc-alist to resolve names of foreign servers.
+       Should fix recent agent bug.
 
-Sun Feb 15 18:39:15 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-22  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-salt.el (gnus-tree-close): Start killing buffer again.
+       * gnus-score.el (gnus-summary-lower-score)
+       (gnus-summary-increase-score): Mention symbolic prefix in the
+       doc-string.  Suggested by Karl Pfl\e,Ad\e(Bsterer <sigurd@12move.de>.
 
-       * gnus-sum.el (gnus-mark-article-as-read): Return t.
+2003-12-21  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-art.el (gnus-article-edit-mode): Run text mode hook.
+       * gnus-agent.el (gnus-agent-read-agentview): Use
+       car-less-than-car.
 
-Sun Feb 15 17:31:19 1998  Roland Roberts  <rroberts@muller.com>
+2003-12-20  Artem Chuprina <ran@ran.pp.ru>  (tiny change)
 
-       * gnus-sum.el (gnus-nov-parse-line): Would bug out on bogus
-       References headers.
+       * message.el (message-yank-buffer): Bind message-reply-buffer to
+       a buffer rather than a string.
 
-Sun Feb 15 14:23:51 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-19  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-art.el (gnus-article-current-summary): New variable.
-       (gnus-article-mode): Make it local.
+       * gnus-msg.el (gnus-summary-followup): Correct documentation.
 
-       * gnus-score.el (gnus-summary-increase-score): Find the right
-       global score file.
+2003-12-18  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-start.el (gnus-setup-news): Don't find new newsgroups
-       unless plugged.
+       * gnus-msg.el (gnus-inews-add-send-actions): `yanked' can be a
+       list of lists.  Reported by Dmitri Paduchikh <paduch@imm.uran.ru>.
 
-       * message.el (message-mode): Set font-lock things before running
-       mode hook.
+2003-12-18  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-agent.el (gnus-agent-group-path): Respect long file names. 
+       * mm-url.el (mm-url-insert-file-contents-external)
+       (mm-url-insert-file-contents): Added doc-strings.  Autoload.
 
-Sat Feb 14 21:31:25 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-18  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-sum.el (gnus-summary-goto-last-article): Force jumping to
-       articles outside limit.
+       * gnus-cus.el (defvar): defvar
+       gnus-agent-cat-disable-undownloaded-faces.
 
-       * gnus-agent.el (gnus-agent-toggle-plugged): un/plug before hook. 
+2003-12-17  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Feb 14 21:08:03 1998  Kim-Minh Kaplan  <KimMinh.Kaplan@utopia.eunet.fr>
+       * message.el (message-forward-subject-name-subject): Use
+       gnus-extract-address-components instead of
+       mail-header-parse-address because it may be called with non-ascii
+       text.
 
-       * gnus-xmas.el (gnus-xmas-article-display-xface): t t would make
-       faces disappear.
+2003-12-16  Per Abrahamsen  <abraham@dina.kvl.dk>
 
-Sat Feb 14 20:52:34 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nnmail.el (nnmail-split-fancy): The widget now supports
+       restrictions.
 
-       * nntp.el (nntp-netrc-file): New variable.
+2003-12-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Feb 14 19:28:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * nnheader.el (nnheader-find-etc-directory): Find the newest one.
 
-       * gnus.el: Quassia Gnus v0.26 is released.
+2003-12-16  Simon Josefsson  <jas@extundo.com>
 
-Sat Feb 14 18:40:55 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * sha1-el.el (autoload): Don't use ignore-errors.
+       (sha1-use-external): Use condition-case.  Suggested by Katsumi
+       Yamaoka <yamaoka@jpl.org>.
 
-       * gnus-agent.el (gnus-agent-directory): Translate file chars. 
+2003-12-15  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-sum.el (gnus-summary-print-article): Don't display all
-       headers.
-       (gnus-summary-edit-parameters): New command and keystroke.
+       * nnmail.el (nnmail-split-fancy): Make it customizable with Emacs
+       20 as well.
 
-       * gnus-group.el (gnus-group-rename-group): Mark dribble.
+2003-12-15  Simon Josefsson  <jas@extundo.com>
 
-Sat Feb 14 18:39:45 1998  Fred Oberhauser  <foberhauser@psipenta.de>
+       * sha1-el.el (autoload): Ignore errors for
+       executable-find. (XEmacs ecrypto does not require sh-script where
+       executable.el is located.)
+       (sha1-use-external): Likewise.
 
-       * nnmail.el (nnmail-process-babyl-mail-format): Fix point
-       movement. 
+       * sha1-el.el (sha1): Add defgroup.
+       (sha1-maximum-internal-length, sha1-program, sha1-use-external)
+       (sha1-program): Use 'sha1sum' from GNU CoreUtils instead of OpenSSL.
+       (sha1): Autoload.
 
-Sat Feb 14 18:31:39 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nndraft.el (nndraft-request-move-article): Copy definition of
+       nnmh-request-move-article instead of calling it, because the nnmh
+       version uses nnmh-request-article which isn't the same as the
+       nndraft version.
 
-       * gnus.el (gnus-group-get-parameter): Dix fix.
+2003-12-13  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Sat Feb 14 18:29:12 1998  Kim-Minh Kaplan  <KimMinh.Kaplan@utopia.eunet.fr>
+       * spam.el: added some gnus-registry autoloads
+       (spam-split-symbolic-return): makes spam-split return 'spam
+       instead of the value of spam-split-group when spam is detected
+       (spam-split-symbolic-return-positive): makes spam-split return
+       'ham instead of nil when ham is detected
+       (spam-autodetect-recheck-messages): tells spam.el whether it
+       should recheck all messages in a group, or only the unseen ones
+       (spam-split-last-successful-check): spam-split will set this to
+       the last successful check; this was seen as a cleaner approach
+       than returning a cell like '(spam spam-use-bogofilter)
+       (spam-list-of-checks): documentation appended
+       (spam-split): accomodate the spam-split-symbolic-return and
+       spam-split-symbolic-return-positive variables
+       (spam-find-spam): new function called when the summary is built
+       (spam-log-registered-p): checks if a ham or spam registration has
+       already been done for an article
+       (spam-check-regex-headers, spam-check-blackholes, spam-check-BBDB)
+       (spam-check-ifile, spam-check-stat, spam-check-whitelist)
+       (spam-check-blacklist, spam-check-bogofilter-headers)
+       (spam-check-spamoracle): respect the spam-split-symbolic-return
+       and spam-split-symbolic-return-positive variables
+       (spam-initialize): add spam-find-spam to gnus-summary-prepare-hook
+       (spam-unload-hook): remove spam-find-spam from
+       gnus-summary-prepare-hook
 
-       * gnus-picon.el: Updated documentation.
+       * gnus.el (spam-autodetect, spam-autodetect-methods): new
+       configuration items for spam autodetection
 
-Sat Feb 14 18:26:53 1998  Joev Dubach  <dubach@dcepea.harvard.edu>
+2003-12-12  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * nntp.el (nntp-send-authinfo-from-file): Doc fix.
+       * gnus-draft.el (gnus-draft-mode-map): Bind `e' to
+       `gnus-draft-edit-message'.  We still have `B w' for
+       `gnus-summary-edit-article'.
 
-Sun Jan 11 23:44:12 1998  Ken Raeburn  <raeburn@cygnus.com>
+2003-12-12  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * nnagent.el (nnagent-request-update-info): New no-op fn.
+       * nnheaderxm.el (nnheader-xmas-run-at-time): Use a simple function
+       definition if there is not a bug in start-itimer.
 
-Sat Feb 14 17:41:44 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * pgg.el (pgg-run-at-time): Ditto.
 
-       * gnus-srvr.el (gnus-browse-unsubscribe-group): Wouldn't allow
-       subscription of visited groups.
+2003-12-11  Kevin Greiner <kgreiner@xpediantsolutions.com>
 
-       * gnus-util.el (gnus-run-hooks): New function.
-       Use it everywhere.
+       * gnus-agent.el (gnus-agent-possibly-alter-active): New Function.
+       (gnus-agent-regenerate-group): When necessary, alter the group's
+       active range to include articles newly recognized as being
+       downloaded.
+       (gnus-agent-regenerate): Removed code that updated the agent's
+       active file as the new gnus-agent-possibly-alter-active function
+       obsolesced it.
 
-       * nntp.el (nntp-authinfo-password): New variable.
-       (nntp-send-authinfo): Cache authinfo password.
+       * gnus-cus.el (gnus-agent-customize-category): Added missing
+       agent-disable-undownloaded-faces parameter.
+       
+       * gnus-start.el (gnus-activate-group): Backed out my 2003-11-29
+       patch as it was too late at adjusting the active range.
+       (gnus-get-unread-articles-in-group): Added call to new
+       gnus-agent-possibly-alter-active to adjust the active range.
 
-       * gnus-sum.el (gnus-summary-mark-article-as-unread): Don't do
-       anything if the mark doesn't change.
+2003-12-10  Jesper Harder  <harder@ifa.au.dk>
 
-1998-01-17  Simon Josefsson  <jas@pdc.kth.se>
+       * message.el (message-get-reply-headers): Narrow to headers.
 
-       * gnus-sum.el (gnus-summary-work-articles): change buffer
-       before looking at marked articles
-       (gnus-summary-work-articles): better check of marked articles
-       
-Sat Feb 14 15:10:36 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-10  Teodor Zlatanov  <tzz@lifelogs.com> 
 
-       * nntp.el (nntp-send-authinfo): Use new .netrc functionality.
+       * spam.el (spam-disable-spam-split-during-ham-respool): new
+       variable.  From lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Ba\e(Broly)
+       (spam-ham-copy-or-move-routine): respect
+       spam-disable-spam-split-during-ham-respool.  From
+       lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Ba\e(Broly)
+       (spam-split-disabled): new variable.  From
+       lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Ba\e(Broly)
+       (spam-split): respect spam-split-disabled.  From
+       lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Ba\e(Broly)
 
-       * gnus-util.el (gnus-netrc-syntax-table): New variable.
-       (gnus-parse-netrc): New function.
-       (gnus-netrc-machine): Ditto.
-       (gnus-netrc-get): Ditto.
+2003-12-10  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-draft.el (gnus-draft-make-menu-bar): Added deletion.
+       * nnheaderxm.el (nnheader-xmas-run-at-time): Make it work
+       correctly for the first argument.
 
-       * gnus.el (gnus-expert-user): Dix fox.
+       * pgg.el (pgg-run-at-time): New function.
+       (pgg-add-passphrase-cache): Use it.
 
-       * nnmail.el (nnmail-article-group): Remove duplicates from split. 
+2003-12-10  Simon Josefsson  <jas@extundo.com>
 
-       * message.el (message-check-news-header-syntax): Check more on
-       Message-ID. 
+       * pgg-parse.el (pgg-decode-packets): Rewrite to handle corrupt
+       input.
+       (pgg-decode-armor-region): Don't parse packet if decoding fail.
 
-       * nnmh.el: Don't call nnmail-activate.
+2003-12-09  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus.el: User-variabelize all custom vars.
+       * spam.el (spam-check-bogofilter): run in the correct buffer.
+       From lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Ba\e(Broly).
+       (spam-bogofilter-database-directory): correct customization
+       group.  From Xavier Maillard <zedek@gnu-rox.org>.
 
-Fri Feb 13 22:40:39 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-12-09  Per Abrahamsen  <abraham@dina.kvl.dk>
 
-       * gnus.el: Quassia Gnus v0.25 is released.
+       * nnmail.el (nnmail-lazy, nnmail-split-fancy): New widgets.
+       (nnmail-split-fancy): Use it.
 
-Fri Feb 13 19:01:19 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-08  Joel Ray Holveck <joelh@piquan.org>  (tiny change)
 
-       * nndoc.el (nndoc-type-alist): Allow blank lines to separate
-       headers from bodies.
+       * gnus-sum.el (gnus-summary-save-parts-1): Consider the "name"
+       parameter of Content-Type.
 
-       * gnus-art.el (gnus-article-edit): Restore Date header.
+2003-12-08  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-async.el (gnus-asynch-obarray): New variable.
-       (gnus-async-prefetched-article-entry): Use it.
-       (gnus-async-set-buffer): Use it.
+       * gnus-util.el: Revert 2003-12-03 change, instead, provide the
+       compiler macro for rmail-select-summary if rmail is not available,
+       and bind rmail-summary-displayed and rmail-maybe-display-summary
+       in order to silence the compiler even if tm is not available.
 
-       * nnmh.el (nnmh-active-number): Create parent dirs.
+2003-12-08  Simon Josefsson  <jas@extundo.com>
 
-       * nntp.el (nntp-last-command): New variable.
-       (nntp-handle-authinfo): New function.
+       * flow-fill.el (fill-flowed-encode-tests, fill-flowed-test): Add.
 
-       * gnus-sum.el (gnus-summary-exit): Call purging function.
+2003-12-08  Jesper Harder  <harder@ifa.au.dk>
 
-Fri Feb 13 18:59:16 1998  François Pinard  <pinard@iro.umontreal.ca>
+       * gnus-msg.el (gnus-extended-version): Bind float-output-format to
+       nil.
 
-       * nnmail.el (nnmail-get-new-mail): Don't clear split-history.
-       (nnmail-purge-split-history): New function.
+2003-12-08  Simon Josefsson  <jas@extundo.com>
 
-Fri Feb 13 18:36:16 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mml-smime.el (mml-smime-sign): Replace CRLF with LF in OpenSSL
+       output.  Reported by Arne J\e,Ax\e(Brgensen <arne@arnested.dk>.
 
-       * nntp.el (nntp-telnet-shell-prompt): Renamed.
+2003-12-07  Simon Josefsson  <jas@extundo.com>
 
-Fri Feb 13 18:35:23 1998  Sam Falkner  <samf@channelpoint.com>
+       * pgg-gpg.el (pgg-gpg-recipient-arg): Add.
+       (pgg-gpg-encrypt-region): Use it.  Tiny patch from Lloyd Zusman
+       <ljz@asfast.com>.
+       (pgg-gpg-recipient-argument): Doc fix.  Renamed fro p-g-r-a.
+       (pgg-gpg-encrypt-region): Update.
 
-       * nntp.el (nntp-open-telnet-envuser): New variable.
+2003-12-07  Jesper Harder  <harder@ifa.au.dk>
 
-Fri Feb 13 18:29:23 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * spam.el (spam-check-spamoracle, spam-spamoracle-learn): Don't
+       use = or zerop to test the return value of call-process, because
+       it can be a string.
 
-       * message.el (message-send-mail-function): Added smtpmail-send-it.
+       * mail-source.el (mail-source-fetch-with-program): do.
 
-1998-02-11  Dave Love  <d.love@dl.ac.uk>
+       * mailcap.el (mailcap-viewer-passes-test): do.
 
-       * gnus-art.el (gnus-button-url): Don't lose in Emacs 20 with
-       browse-url-browser-function an alist, not a function.
-       (gnus-button-embedded-url): Likewise.
+       * gnus-uu.el (gnus-uu-treat-archive, gnus-uu-post-encode-mime)
+       (gnus-uu-post-encode-file): do.
 
-Fri Feb 13 17:10:31 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-soup.el (gnus-soup-pack, gnus-soup-unpack-packet): do.
 
-       * gnus-cite.el (gnus-cite-localize): New function.
-       (gnus-cite-close): Renamed.
-       (gnus-cite-parse-maybe): Use it.
+       * message.el (message-fix-before-sending): Fix detection of
+       non-printables.  Don't replace unencodable utf-8.
 
-       * gnus-sum.el (gnus-summary-move-article): Move back to summary
-       buffer. 
+2003-12-05  Jesper Harder  <harder@ifa.au.dk>
 
-       * nnfolder.el (nnfolder-request-accept-article): Save excursion.
-       (nnfolder-request-move-article): Ditto.
+       * mm-url.el (mm-url-predefined-programs): Add user-agent for wget.
+       (mm-url-insert-file-contents-external): Signal an error if program
+       fails.
 
-       * nntp.el (nntp-find-connection): Don't message.
+2003-12-04  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Fri Feb 13 14:51:56 1998  MORIOKA Tomohiko  <steve@xemacs.org>
+       * spam-report.el (spam-report-gmane): iterate over articles
+       instead of a single one; remove interactive usage
 
-       * message.el (message-send-mail-with-qmail): Fix.
+2003-12-03  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-1998-02-13  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * dns.el: Fix misplaced eval-when-compile.
 
-       * gnus-draft.el (gnus-draft-make-menu-bar): Added missing commands.
+       * gnus-util.el: Require alist and provide tm-view when compiling
+       with XEmacs.
 
-1998-01-06  Per Abrahamsen  <abraham@dina.kvl.dk>
+2003-12-03  Steve Youngs  <sryoungs@bigpond.net.au>
 
-       * gnus/gnus-cus.el (gnus-score-parameters): Make `files' and
-       `exclude-files' widgets inline.
+       * gnus-xmas.el: Add autoloads for macros defined in gnus.el.
+       From Jerry James <james@xemacs.org>.
 
-Fri Feb 13 12:46:23 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-util.el: Get rmail definitions when compiling.
+       From Jerry James <james@xemacs.org>.
 
-       * gnus-sum.el (gnus-article-mark): Dox dox.
+       * dns.el: Require gnus-xmas at compile time instead of trying to
+       autoload `gnus-xmas-open-network-stream' because it wasn't picking
+       up the macro.
+       From Jerry James <james@xemacs.org>.
 
-Wed Feb 11 15:05:03 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-12-01  Kevin Greiner <kgreiner@xpediantsolutions.com>
+       * gnus-agent.el (gnus-agent-consider-all-articles): Updated
+       docstring.
+       (gnus-predicate-implies-unread, gnus-predicate-implies-unread-1):
+       Fixed implementation such that the predicate `true' no longer
+       evaluates to t.
 
-       * gnus.el: Quassia Gnus v0.24 is released.
+2003-12-01  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Tue Feb 10 21:59:53 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * spam.el (spam-check-bogofilter): check the bogofilter headers
+       AFTER the save-excursion scope is over.  From Adrian Lanz
+       <lanz@fowi.ethz.ch>.
+       (spam-fetch-field-message-id-fast): doc fix
 
-       * gnus-agent.el (gnus-agent-fetch-session): Reversed reversal.
+2003-12-01  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-topic.el (gnus-topic-rename): Check whether the new name
-       exists. 
+       * gnus-agent.el (gnus-agent-expire-days): Doc fix.
 
-Tue Feb 10 21:39:47 1998  dave edmondson  <dme@sco.com>
+2003-11-30  Simon Josefsson  <jas@extundo.com>
 
-       * message.el (message-font-lock-keywords): Allow : as a citation
-       ending. 
+       * gnus-agent.el (gnus-agent-expire-group-1): Bind message-log-max
+       when messaging "X % completed" to inhibit logging them to the
+       message buffer.
+       (gnus-agent-expire-group-1): Mention group name in messages.
+       (gnus-agent-expire-group-1): Only print a message for an article
+       when there actually was something done to it.
 
-Tue Feb 10 20:09:02 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-util.el (mm-enable-multibyte): Call set-buffer-multibyte with
+       'to argument.  Fixes something or other in Emacs 22, and is
+       backwards compatible.  From Kenichi Handa <handa@m17n.org>.
 
-       * message.el (message-send): Removed dead code.
+       * gnus-agent.el (gnus-agent-expire-unagentized-dirs): Custom fix.
 
-Mon Feb  9 17:02:09 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-11-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-covered-methods): Remove nil methods. 
+
+2003-11-29  Kevin Greiner <kgreiner@xpediantsolutions.com>
+       * gnus-start.el (gnus-activate-group): The active range of the
+       group must include the articles known to the agent.
+
+       * gnus.el (gnus-agent-method-p): Accept a server name as the
+       method being tested.
+
+2003-11-29  Alexander Kreuzer <alex@freesources.org>  (tiny change)
+
+       * nnrss.el (nnrss-check-group): Set xml when nnrss-use-local is t.
 
-       * message.el (message-fill-header): Fill to column 990.
+2003-11-29  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-score.el (gnus-score-load-file): Exclude all excluded
-       files. 
+       * gnus-group.el (gnus-group-make-menu-bar): Add
+       gnus-group-make-rss-group.
+
+2003-11-28  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el: Added custom-manual links to all variables that have
+       an index entry in the message manual.
+       (message-generate-headers-first): Fixed doc-string.
+
+2003-11-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-summary-yank-message): Don't bind
+       gnus-display-mime-function to nil so that non-ascii text is
+       decoded and attachments are not shown.
+
+       * message.el (message-cite-original-without-signature): Replace
+       the value of message-reply-headers with the yanked article since
+       it may be a different article from the original.
+       (message-cite-original): Ditto.
+
+2003-11-25  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-blacklist-ignored-regexes): new variable, so
+       blacklisting can ignore certain regular expressions (e.g. the
+       user's e-mail address)
+       (spam-bogofilter-spam-strong-switch,
+       spam-bogofilter-ham-strong-switch): options used when articles are
+       already registered as the opposite classification
+       (spam-old-ham-articles, spam-old-spam-articles): lists of ham and
+       spam articles, generated when a summary buffer is entered, and
+       consulted when it's exited so we know what articles are changing
+       state from spam to ham or vice-versa
+       (spam-xor): everyone needs a little convenience
+       (spam-list-of-processors): lookup table for old-style spam/ham
+       exits processors
+       (spam-group-processor-p): support old-style and new-style spam/ham
+       exit processors
+       (spam-group-processor-multiple-p): handle new-style spam/ham exit
+       processors
+       (spam-summary-prepare): use spam-old-{ham,spam}-articles; change
+       logic to iterate over list of processors instead of manual
+       individual lookup, unregister any articles that change from ham to
+       spam or vice-versa in the course of the summary buffer usage; use
+       the new spam-register-routine
+       (spam-ham-copy-routine, spam-ham-move-routine,
+       spam-mark-spam-as-expired-and-move-routine): check that the list
+       of groups is not nil, because apply doesn't like to apply a
+       function across nil
+       (spam-registration-functions): variable for looking up spam/ham
+       registration/unregistration functions based on a spam-use-* symbol
+       (spam-classification-valid-p, spam-process-type-valid-p)
+       (spam-registration-check-valid-p)
+       (spam-unregistration-check-valid-p): convenience functions
+       (spam-registration-function, spam-unregistration-function): look
+       up the registration/unregistration function based on a
+       classification and the check (spam-use-* symbol)
+       (spam-list-articles): generate list of spam/ham articles from a
+       given list of articles
+       (spam-register-routine): do the heavy work of registering and
+       unregistering articles, using all the articles in the group or
+       specific ones as needed
+       (spam-generic-register-routine): removed, no longer used
+       (spam-log-unregistration-needed-p, spam-log-undo-registration):
+       handle article registration/unregistration with a given spam/ham
+       processor and group
+       (BBDB, ifile, spam-stat, blacklists, whitelists, spam-report,
+       bogofilter, spamoracle): rewrite registration/unregistration
+       functions to take a list of articles and the unregister option.
+       Much hilarity ensues.
+       (spam-initialize): spam-stat-maybe-{save,load} already respect spam-use-stat
+       (spam-stat-register-ham-routine, spam-stat-register-spam-routine):
+       don't load and save unnecessarily
+
+       * spam-stat.el (spam-stat-dirty): new variable, set when the stats
+       database is modified
+       (spam-stat-buffer-is-spam, spam-stat-buffer-is-non-spam)
+       (spam-stat-buffer-change-to-spam, spam-stat-to-hash-table)
+       (spam-stat-buffer-change-to-non-spam): set spam-stat-dirty when
+       needed
+       (spam-stat-save): respect spam-stat-dirty, unless the force
+       parameter is specified
+       (spam-stat-load): clear spam-stat-dirty
+
+       * gnus.el (gnus-install-group-spam-parameters): marked the
+       old-style exit processors as obsolete in the docs, added the
+       new-style exit processors while the old ones are still allowed
+
+
+2003-11-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (article-hide-boring-headers): Don't hide Reply-To
+       unless its list of addresses is identical to From.
+
+2003-11-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (mapc): Add the compiler macro for Emacs 20.
+
+2003-11-24  Kevin Greiner <kgreiner@xpediantsolutions.com>
+       * gnus-srvr.el (gnus-server-insert-server-line): The server names
+       used in gnus-agent are different (for example, the native server
+       uses the alias "native") from the names in gnus-srvr.
+       Compensating by adding a second text property storing the name
+       expected by gnus-agent.
+       (gnus-server-named-server): New function.
+       * gnus-agent.el (gnus-agent-remove-server, gnus-agent-add-server):
+       No longer expect an argument as it was ignored anyway.  Uses the
+       new gnus-server-named-server function to get gnus-agent compatible
+       names from the server buffer.
+
+2003-11-20  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus.el (gnus-agent-covered-methods): Documented use of
+       named servers, not methods, to identity agentized groups.
+       Users may now change their server configurations without having
+       the server become "unagentized".
+       (gnus-agent-covered-methods): Removed from gnus-variable-list to
+       avoid storing two copies of gnus-agent-covered-methods, one in
+       .newsrc.eld and the other in agent/lib/servers.
+       (gnus-server-to-method): Do not cache server for the nil method.
+       (gnus-method-to-server): New function.  Associate named server
+       with all, even foreign, methods.
+       (gnus-agent-method-p, gnus-agent-method-p-cache): Incorporated
+       simple last-response cache to offset performance lose of having to
+       always convert methods to named servers.
+       * gnus-agent.el (gnus-agent-expire-days): Removed obsolete
+       documentation.
+       (gnus-agentize, gnus-agent-add-server, gnus-agent-remove-server):
+       Modified to support new definition of gnus-agent-covered-method.
+       (gnus-agent-read-servers): Rewritten to convert old method data
+       into server names.
+       (gnus-agent-read-servers-validate)
+       (gnus-agent-read-servers-validate-native): New functions.
+       (gnus-agent-write-servers): No longer use gnus-method-simplify as
+       it failed to simplify foreign methods.
+       (gnus-agent-close-connections, gnus-agent-synchronize-flags)
+       (gnus-agent-possibly-synchronize-flags, gnus-agent-fetch-session)
+       (gnus-agent-regenerate): Uses new gnus-agent-covered-methods
+       function as gnus-agent-covered-methods variable no longer provides
+       methods.
+       (gnus-agent-covered-methods): New function
+       (gnus-agent-expire-group, gnus-agent-expire): Final message will,
+       if gnus-verbose is greater than 4, report statistics of NOV
+       entries and files deleted as well as total bytes recovered.
+       (gnus-agent-expire-done-message): New function
+       (gnus-agent-unread-articles): Bug fix.  No longer drops last
+       unread article onto read list.
+       (gnus-agent-regenerate-group): Changed prompt to use typical
+       style.
+       (gnus-agent-group-covered-p): Rewrote to internally use
+       gnus-agent-method-p.
+       * gnus-int.el (gnus-start-news-server): Partially convert old
+       gnus-agent-covered-methods to new format so that gnus-open-server
+       functions correctly.
+       * gnus-srvr.el (gnus-server-insert-server-line): Replaced
+       gnus-agent-covered-methods with gnus-agent-method-p.
+       * gnus-start.el (gnus-clear-system): Added
+       gnus-agent-covered-methods to compensate for removing it from
+       gnus-variable-list.
+       (gnus-setup-news): Complete conversion of old
+       gnus-agent-covered-methods to new format so that secondary and
+       foreign servers can be correctly opened.
+
+2003-11-20  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-copy-or-move-routine): add respooling
+       support, not working well yet
+
+       * gnus.el (ham-process-destination): make 'respool option the
+       only one, so it can't be chosen together with other groups
+
+2003-11-19  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-registry-track-extra): make it a set of
+       choices instead of a boolean
+       (gnus-registry-track-subject-p, gnus-registry-track-sender-p):
+       new convenience functions
+       (gnus-registry-split-fancy-with-parent): use convenience
+       functions, also don't return extra tracking info if sender or
+       subject is found in more than one groups
+       (gnus-registry-add-group): use new convenience functions to
+       decide if sender and subject should be tracked
+
+       * gnus.el (ham-process-destination): add 'respool option,
+       unused by spam.el yet
+
+2003-11-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-score.el (gnus-decay-score): Return a surely smaller value
+       than the argument in XEmacs.
+
+2003-11-18  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-insert-to): Don't use `gnus-message'.
+       (message-header-synonyms): New variable.
+       (message-carefully-insert-headers): Use it (check for synonyms).
+       Added doc-string.  From Sam Steingold <sds@gnu.org>.
+
+2003-11-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * html2text.el (html2text-remove-tags): Remove the tag in a
+       simpler way to avoid inflooping.
+
+2003-11-17  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-gssapi-auth-p): Don't check capability (some
+       servers remove AUTH=GSSAPI from capability response returned after
+       successful authentication).
+
+2003-11-16  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.el (gnus-getenv-nntpserver): Fix regexp and simplify.
+       Reported by Artem Chuprina <ran@ran.pp.ru>.
+
+2003-11-14  Simon Josefsson  <jas@extundo.com>
+
+       * mm-util.el (mm-charset-synonym-alist): Map BIG5-HKSCS to BIG5
+       when it isn't available.
+
+2003-11-13  Alex Schroeder  <alex@gnu.org>
+
+       * nnrss.el (nnrss-check-group): Use dc:contributor if neither
+       rss:author nor dc:creator is provided.
 
-Mon Feb  9 16:55:41 1998  jari aalto  <jari.aalto@poboxes.com>
+2003-11-13  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-art.el (gnus-article-time-format): Extended variable. 
+       * mm-decode.el (mm-dissect-buffer): Save start="<id>" value
+       contained in Content-Type header of multipart/related messages.
 
-Mon Feb  9 16:27:59 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-view.el (mm-w3m-cid-retrieve-1): New function.
+       (mm-w3m-cid-retrieve): Use it.
 
-       * gnus-art.el (article-make-date-line): Make 8601 Dates.
-       (article-date-iso8601): New command and keystroke.
+       * mml.el (mml-generate-mime-1): Add start="<id>" to Content-Type.
+       (mml-insert-mime-headers): Insert Content-ID header.
+       (mml-insert-mml-markup): Insert start="<id>" value.
 
-Sun Feb  8 21:19:15 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-11-12  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * message.el (message-ignored-mail-headers): Remove Xrefs.
+       * nnml.el (nnml-request-accept-article): pass sender to
+       nnmail-cache-insert
 
-       * nndoc.el (nndoc-open-document-hook): New variable.
+       * nnmh.el (nnmh-request-accept-article): pass sender to
+       nnmail-cache-insert 
 
-Sun Feb  8 21:01:33 1998  Istvan Marko  <istvan@cmdmail.amd.com>
+       * nnmbox.el (nnmbox-request-accept-article): pass sender to
+       nnmail-cache-insert 
 
-       * gnus-agent.el (gnus-unplugged): Typo fix.
+       * nnfolder.el (nnfolder-request-accept-article): pass sender to
+       nnmail-cache-insert 
 
-Sun Feb  8 18:34:31 1998  Kurt Swanson  <kurt@dna.lth.se>
+       * nnbabyl.el (nnbabyl-request-accept-article): pass sender to
+       nnmail-cache-insert 
 
-       * gnus-score.el (gnus-score-thread-simplify): New variable.
+       * nnmail.el (nnmail-cache-insert): accept sender parameter and
+       pass it to the nnmail-spool-hook
 
-Sun Feb  8 18:31:35 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-registry.el (gnus-registry-track-extra): clarify doc
+       (gnus-registry-action): add sender lexical var and pass it to
+       gnus-registry-add-group
+       (gnus-registry-spool-action): take a sender parameter, pass to
+       gnus-registry-add-group
+       (gnus-registry-split-fancy-with-parent): trace by sender in
+       addition to subject
+       (gnus-registry-fetch-sender-fast): new function
+       (gnus-registry-add-group): accept sender parameter
 
-       * gnus-uu.el (gnus-uu-post-encode-mime): Call mmencode with
-       correct params.
+2003-11-11  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Sun Feb  8 18:13:58 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * spam.el (spam-ham-copy-routine, spam-ham-move-routine)
+       (spam-mark-spam-as-expired-and-move-routine): allow for the
+       groups to be a list of a single item
 
-       * gnus.el: Quassia Gnus v0.23 is released.
+       * gnus.el (gnus-install-group-spam-parameters):
+       ham-process-destination and spam-process-destination allow lists now
 
-Sun Feb  8 17:20:40 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-11-10  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-group.el (gnus-update-group-mark-positions): Bind `topic'. 
+       * message.el (message-insert-to): Do error out when the user
+       requested no Cc.  Don't insert empty To.  Can be added to
+       `message-setup-hook' now.  From Sam Steingold <sds@gnu.org>.
+       (message-mode-field-menu): Moved some entries, added
+       `message-insert-wide-reply'.
+       (message-change-subject): Fixed comment.
 
-       * message.el (message-expand-group): Added doc string.
+2003-11-10  Simon Josefsson  <jas@extundo.com>
 
-       * nntp.el (nntp-wait-for): Don't change limit until after
-       accepting output.
+       * pgg-def.el (pgg-encrypt-for-me): Change default from nil to t.
 
-Sun Feb  8 16:44:36 1998  Richard Hoskins  <rmh@interlaced.net>
+2003-11-09  Simon Josefsson  <jas@extundo.com>
 
-       * message.el (message-kill-to-signature): Don't kill the
-       delimiter. 
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Cache passphrase under hex
+       key id too (for decryption).
+       (pgg-gpg-sign-region): Likewise.
 
-Sun Feb  8 16:15:33 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-11-09  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-sum.el (gnus-summary-prepared-hook): New hook.
-       (gnus-summary-read-group-1): Use it.
+       * pgg-gpg.el (pgg-gpg-all-secret-keys): New variable.
+       (pgg-gpg-lookup-all-secret-keys): New function.
+       (pgg-gpg-select-matching-key): Likewise.
+       (pgg-gpg-decrypt-region): Use new functions.  From Satyaki Das
+       <satyakid@stanford.edu>.
+
+2003-11-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * nnmail.el (nnmail-cache-insert): make sure that the
+       nnmail-spool-hook is called with a valid newsgroup name (though
+       it may be wrong)
+
+       * gnus.el (gnus-group-real-prefix): return nil if group is not a
+       string, instead of triggering an error
+
+2003-11-06  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.el (gnus-group-guess-full-name-from-command-method): new function
+
+       * gnus-registry.el (gnus-registry-fetch-group): use long names if
+       requested 
+       (gnus-registry-split-fancy-with-parent): when long names are in
+       use, strip the name if we're in the native server, or else return nothing
+       (gnus-registry-spool-action, gnus-registry-action): use
+       gnus-group-guess-full-name-from-command-method instead of
+       gnus-group-guess-full-name
+
+       * spam.el (spam-mark-spam-as-expired-and-move-routine)
+       (spam-ham-copy-or-move-routine): prevent article deletions or
+       moves unless the backend allows it
+
+       * gnus.el (gnus-install-group-spam-parameters): fixed parameters
+       to list spamoracle as well, suggested by Jean-Marc Lasgouttes
+       <Jean-Marc.Lasgouttes@inria.fr>
+
+       * spam.el (spam-spamoracle): doc change, suggested by Jean-Marc
+       Lasgouttes <Jean-Marc.Lasgouttes@inria.fr>
+
+2003-11-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-score.el (gnus-decay-score): Protect against arithmetic
+       errors.  Tiny patch from Norbert Koch <viteno@xemacs.org>.
+
+2003-10-31  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el
+       (spam-log-processing-to-registry): improved message and comments
+       (spam-log-unregistration-needed-p): new function
+       (spam-ifile-register-spam-routine)
+       (spam-ifile-register-ham-routine, spam-stat-register-spam-routine)
+       (spam-stat-register-ham-routine)
+       (spam-blacklist-register-routine)
+       (spam-whitelist-register-routine)
+       (spam-bogofilter-register-spam-routine)
+       (spam-bogofilter-register-ham-routine)
+       (spam-spamoracle-learn-ham, spam-spamoracle-learn-spam): change
+       spam-log-processing-to-registry invocations appropriately
+
+2003-10-31  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-kerberos4-open): Ignore output from ATHENA imtest.
+       Tiny patch from Derek Atkins <warlord@MIT.EDU>.
+       (imap-process-connection-type): Improve docstring.  Suggested by
+       Derek Atkins <warlord@MIT.EDU>.
+
+2003-10-31  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (autoload): autoload the gnus-registry functions we'll
+       need
+       (spam-log-to-registry): new variable for interfacing with the
+       gnus-registry
+       (spam-install-hooks): variable had the wrong customization group
+       (spam-fetch-field-message-id-fast): convenience function for fetch
+       a message ID quickly
+       (spam-log-processing-to-registry): new function
+       (spam-ifile-register-spam-routine)
+       (spam-ifile-register-ham-routine, spam-stat-register-spam-routine)
+       (spam-stat-register-ham-routine)
+       (spam-blacklist-register-routine)
+       (spam-whitelist-register-routine)
+       (spam-bogofilter-register-spam-routine)
+       (spam-bogofilter-register-ham-routine)
+       (spam-spamoracle-learn-ham, spam-spamoracle-learn-spam): add
+       spam-log-processing-to-registry invocations
+
+       * gnus-registry.el: fixed docs in the preface to mention
+       gnus-registry-initialize
+       (gnus-registry-store-extra): remove cached extra entry
+       information when new extra entry is stored
+
+2003-10-29  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-forward-make-body-plain): Fix ARG=1 mode
+       after separating m-f-m-b.
+
+2003-10-29  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-forward-make-body-plain): Remove ignored
+       headers.  Tiny patch from Andre Srinivasan <andre@e2open.com>.
+       (message-forward-make-body-plain): Fix ARG=1.
+
+2003-10-28  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-forward-subject-name-subject)
+       (message-forward-subject-author-subject): Decode non-ASCII
+       newsgroup names.
+       (autoload): Autoload gnus-group-decoded-name.
+
+2003-10-27  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-gpg.el (pgg-gpg-possibly-cache-passphrase): New optional
+       parameter key, overrides the key id used to store passphrase
+       under (uses true key id from gpg output if nil).
+       (pgg-gpg-encrypt-region): Search for passphrase using user suplied
+       string STR, instead of (pgg-lookup-key STR t).
+       (pgg-gpg-encrypt-region): Store passphrase under user suplied
+       string, instead of real key id taken from gpg output.
+       (pgg-gpg-decrypt-region): Likewise.
+       (pgg-gpg-sign-region): Likewise.
+       * pgg.el (pgg-decrypt-region): Don't set pgg-default-user-id.
+
+2003-10-27  Romain FRANCOISE  <romain@orebokech.com>
+
+       * gnus-art.el (gnus-article-goto-prev-page): Doc fix. 
+
+2003-10-27  Simon Josefsson  <jas@extundo.com>
+
+       * mm-bodies.el (mm-body-encoding): Don't use QP when message body
+       only consists of short lines and ASCII, when
+       mm-use-ultra-safe-encoding.  Refer to 'About foo' thread in
+       gnus-bug, e.g. <ilullrg4k7p.fsf@extundo.com>, for more discussion.
+       This make it possible to pipe the raw RFC 822 message into 'gpg'
+       and have the signature work.  Potential problem: what if message
+       contain data that would be dash-escaped by OpenPGP
+       implementations? Then PGP 2.x might not be able to parse the raw
+       RFC 822 message correctly.  If that problem is worth fixing, it
+       should be fixed by detecting the situation, instead of applying QP
+       to everything.  Based on discussion with "John A. Martin"
+       <jam@jamux.com>.
+
+2003-10-27  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-mark-spam-as-expired-and-move-routine)
+       (spam-ham-copy-or-move-routine): don't ask when deleting copied
+       articles, and use move instead of copy when possible
+       (spam-split): added the option of specifying a string as a
+       spam-split parameter; such a string will override
+       spam-split-group temporarily.
+
+       * nnmail.el (nnmail-cache-insert): protect from nil message IDs,
+       but should we do something else?
+
+       * gnus-registry.el (gnus-registry-spool-action): protect from nil
+       message IDs
+
+2003-10-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-button-alist): Allow & in mailto URLs.
+       (gnus-header-button-alist): Likewise.
+       (gnus-url-mailto): Handle ?to parameters.  Replace \r\n with \n.
+       Reverse parameter list to use same order as in the URL.  Reported
+       by f95-msv@f.kth.se (M\e,Ae\e(Brten Svantesson).
+
+2003-10-25  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-move-spam-nonspam-groups-only): documentation fix
+       for the variable
+
+2003-10-25  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * Makefile.in (clean-some): Remove auto-autoloads.* and
+       custom-load.* as well.
+       (distclean): Ditto.
+
+       * dgnushack.el (dgnushack-make-load): Add a local vars section to
+       the dummy gnus-load.el.
+
+2003-10-24  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-copy-or-move-routine): do not delete if copy
+       is t, also don't intepret the list of groups as a list of lists
+       (spam-mark-spam-as-expired-and-move-routine)
+       (spam-ham-copy-or-move-routine): delete articles only if 1 or
+       more groups were specified (and "copy" was not specified for
+       spam-ham-copy-or-move-routine) (fixed twice)
+
+2003-10-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nndoc.el (nndoc-guess-type): Reverse the sort order.  Suggested
+       by ARISAWA Akihiro <ari@mbf.ocn.ne.jp>.
+       (nndoc-dissect-buffer): Don't miss even-numbered articles.
+
+2003-10-24  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * dgnushack.el (dgnushack-gnus-load-file): Set to
+       "auto-autoloads.el" if building with XEmacs.
+       (dgnushack-cus-load-file): Set to "custom-load.el" if building
+       with XEmacs.
+       (dgnushack-make-cus-load): We don't delete the resulting file if
+       building with XEmacs so byte-compile it.
+       (dgnushack-make-load): When building with XEmacs do nothing except
+       byte-compile the autoload file and create a dummy gnus-load.el
+       file. 
+
+2003-10-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-make-fqdn): Bind case-fold-search.
+       Suggested by Christopher Richards <richards@CS.Princeton.EDU>.
+
+2003-10-23  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.el (spam-process-destination, ham-process-destination):
+       allow multiple groups as a choice
 
-       * message.el (message-cite-original-without-signature): New
+       * spam.el (spam-check-blackholes): remove "[IP address]"
+       requirement, now just "IP address" is enough for detection for
+       blackhole checking
+       (spam-check-blackholes): oops, the dots were not escaped
+       (spam-mark-spam-as-expired-and-move-routine): added multiple group
+       support (multiple copies, then delete)
+       (spam-ham-copy-routine): new function
+       (spam-ham-move-routine): new function
+       (spam-ham-copy-or-move-routine): new function (used to be
+       spam-ham-move-routine), handle multiple groups
+       (spam-summary-prepare-exit): call the new functions
+
+2003-10-23  Simon Josefsson  <jas@extundo.com>
+
+       * flow-fill.el (fill-flowed-encode, fill-flowed): Autoload.
+
+2003-10-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-emphasis-strikethru): Use the :strike-through
+       attribute in Emacs.
+
+2003-10-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-bounce): Don't erase except bounced header.
+
+2003-10-21  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-reverse-ip-string): new function to reverse an IP
+       address in a string
+       (spam-check-blackholes): use spam-reverse-ip-string
+
+2003-10-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-narrow-to-page): Clear as well as set the
+       value for gnus-page-broken.
+
+       * gnus-sum.el (gnus-summary-beginning-of-article): Use
+       gnus-break-pages instead of gnus-page-broken.
+       (gnus-summary-end-of-article): Use gnus-break-pages instead of
+       gnus-page-broken; narrow to the end of a page beforehand.
+       (gnus-summary-toggle-header): Use gnus-break-pages instead of
+       gnus-page-broken; remove delimiter buttons unless gnus-break-pages
+       is non-nil.
+
+2003-10-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picon-transform-address): Protect against
+       errors. 
+
+2003-10-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (nnspool-rejected-article-hook): Remove defvar.
+       (xemacs-codename): Move defvar to gnus-util.el.
+
+       * gnus-util.el (xemacs-codename): Defvar when compiling.
+
+2003-10-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * spam-report.el (spam-report-url-ping-plain): Include a
+       User-Agent. 
+
+       * gnus-msg.el (gnus-extended-version): Use it.
+
+       * gnus-util.el (gnus-emacs-version): Separated out into own
        function. 
-       (message-cite-function): Added to custom.
 
-1998-01-13  Per Abrahamsen  <abraham@dina.kvl.dk>
+2003-10-19  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus/message.el (message-cite-original): Don't quote signature.
+       * message.el (message-mode-field-menu): Added
+       message-generate-unsubscribed-mail-followup-to.
+       (message-forward-subject-fwd): Avoid double "Fwd: "
+       (message-change-subject): Added comment.
 
-Sun Feb  8 15:50:20 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-group.el (gnus-group-unsubscribe-group): Protest against
-       empty group names.
+       * gnus-sum.el (gnus-nov-parse-line): Remove condition-cases.
 
-Mon Feb  2 18:56:22 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mml.el (mml-insert-mime): Quote mml.
 
-       * gnus-draft.el (gnus-draft-setup): Associate with drafts group.
+2003-10-19  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * message.el (message-header-format-alist): Fill references.
+       * gnus-sum.el (gnus-remove-odd-characters): Use
+       mm-subst-char-in-string instead of subst-char-in-string.
+       (gnus-summary-refer-article): Use gnus-replace-in-string instead
+       of replace-regexp-in-string.
 
-       * gnus-agent.el (gnus-category-read): Changed default.
-       (gnus-agent-handle-level): New variable.
-       (gnus-agent-fetch-session): Use it.
+2003-10-19  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-art.el (article-strip-all-blank-lines): New command and
-       keystroke. 
+       * gnus-uu.el (gnus-uu-uustrip-article): Really strip directory
+       from file name.
 
-Sun Feb  1 18:00:54 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-18  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-msg.el (gnus-inews-reject-message): Removed function.
-       (gnus-sent-message-ids-file): Removed.
-       (gnus-sent-message-ids-length): Ditto.
+       * gnus-sum.el (gnus-summary-save-parts-last-directory): Default
+       to mm-default-directory.
+       (gnus-summary-save-parts-1): Use mm-file-name-rewrite-functions.
 
-       * gnus-xmas.el (gnus-xmas-summary-set-display-table): Ditto.
+2003-10-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-sum.el (gnus-simplify-subject-fuzzy): Respect
-       `gnus-simplify-ignored-prefixes'.
-       (gnus-summary-set-display-table): Keep TAB.
+       * pop3.el (pop3-read-response): Check whether the process is
+       alive. 
 
-Thu Jan 15 22:47:38 1998   <Use-Author-Address-Header@[127.1]>
+       * gnus-sum.el (gnus-summary-refer-article): Strip spaces.
 
-       * gnus-art.el (gnus-request-article-this-buffer): Put it into the
-       backlog. 
+       * rfc2047.el (rfc2047-encode-region): Do error out on invalid
+       strings. 
 
-Mon Jan 12 23:30:59 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nntp.el (nntp-retrieve-headers-with-xover): Get error messages
+       right. 
 
-       * gnus-sum.el (gnus-get-newsgroup-headers): Use the longest ID.
+       * gnus-agent.el (gnus-agent-read-servers): Remove sit-for.
 
-       * nnheader.el (nnheader-parse-head): Ditto.
+       * gnus-art.el (article-treat-dumbquotes): Doc fix.
 
-Thu Jan  8 09:47:18 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-field-value): New function.
+       (message-insert-disposition-notification-to): Use Reply-To, too.
 
-       * gnus-start.el (gnus-1): Use gnus-alive-p.
+       * imap.el (imap-mailbox-status): Upcase STATUS commands. 
 
-Tue Jan  6 11:53:09 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el (gnus-remove-odd-characters): New function.
+       (gnus-nov-parse-line): Use it.
 
-       * gnus-art.el (gnus-article-prepare): Bind coding systems.
+2003-10-18  Matt Swift  <swift@alum.mit.edu>
 
-Tue Jan  6 07:45:39 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * mm-decode.el (mm-inline-media-tests): Recognize pjpeg as jpeg. 
 
-       * gnus.el: Quassia Gnus v0.22 is released.
+2003-10-18  Romain FRANCOISE  <romain@orebokech.com>
 
-Tue Jan  6 07:32:02 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-forward-make-body): does both
+       m-f-make-body-mml and m-f-make-body-plain, resulting in a strange
+       message buffer.
 
-       * message.el (message-kill-to-signature): Don't use mark.
+2003-10-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Tue Jan  6 07:30:46 1998  Russ Allbery  <rra@stanford.edu>
+       * gnus-art.el (gnus-narrow-to-page): Only break page if it's
+       broken.
 
-       * message.el (message-kill-to-signature): New command and keystroke.
+       * nnrss.el (nnrss-find-rss-via-syndic8): Return nil if xml-rpc
+       isn't available.
 
-Tue Jan  6 06:39:29 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-hidden-headers): Doc fix.
 
-       * gnus-sum.el (gnus-summary-print-article): New defaults for
-       headers and stuff.
+2003-10-18  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-agent.el (gnus-agent-batch): New command.
+       * gnus-msg.el (gnus-summary-resend-message-edit): Avoid error when
+       fields aren't found.
 
-       * nnoo.el (nnoo-execute): Copy vars from parent into child.
-       (nnoo-parent-function): Ditto.
+2003-10-18  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-draft.el (gnus-draft-setup): Removed message.
+       * message.el (message-forward-make-body-plain)
+       (message-forward-make-body-mime, message-forward-make-body-mml)
+       (message-forward-make-body-digest-plain)
+       (message-forward-make-body-digest-mime)
+       (message-forward-make-body-digest): New, derived from
+       message-forward-make-body.
+       (message-forward-make-body): Use them.
+       (message-forward-show-mml): New default 'best.
+       (message-forward-make-body): Support it.
 
-       * gnus-start.el (gnus-read-descriptions-file): Naked muleism.
+2003-10-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Mon Jan  5 05:20:16 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-art.el (gnus-article-mode): Set gnus-page-broken to nil.
+       (gnus-article-prepare): Don't set to t.
+       (gnus-narrow-to-page): Set to t if we break.
 
-       * nnml.el (nnml-generate-nov-databases-1): Fix lower bound on
-       empty groups.
+2003-06-11  Daniel N\e,Ai\e(Bri  <dne@mayonnaise.net>
 
-Sun Jan  4 14:38:36 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * message.el (message-resend): Generate Resent-Message-ID header.
 
-       * gnus.el: Quassia Gnus v0.21 is released.
+2003-10-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sun Jan  4 14:28:35 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus-art.el (gnus-article-next-page): Don't go to the next line
+       before checking end-of-buffer.
+       (gnus-mime-delete-part): Don't insert parts twice.
 
-       * gnus.el: Quassia Gnus v0.20 is released.
+2003-10-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-1997-12-10  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * gnus-art.el (article-update-date-lapsed): Make sure point
+       doesn't move around (much).
 
-       * gnus/gnus-msg.el (gnus-inews-insert-mime-headers): Added
-       documentation. 
-       (gnus-inews-insert-mime-headers): Made it work with Emacs MULE.
-       (gnus-inews-insert-mime-headers): Added as option to
-       `message-header-hook'. 
+2003-07-28  Vasily Korytov  <deskpot@myrealbox.com>
 
-1997-12-22  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * mail-source.el (mail-source-keyword-map): List "cur" before
+       "new" for maildirs.
 
-       * gnus/gnus-art.el (gnus-button-alist): Assume msg-id after "in
-       message". 
+2003-10-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-1997-12-22  Simon Josefsson  <jas@faun.nada.kth.se>
+       * gnus-sum.el (gnus-summary-enter-digest-group): ogroup, nor
+       group. 
 
-       * nnmail.el (nnmail-get-new-mail): Make nnmail-tmp-directory
+       * gnus-msg.el (gnus-inews-insert-archive-gcc): Use the parent
+       name for gcc-self.
+       (gnus-inews-insert-archive-gcc): Paren mistake.
 
-1997-12-28  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * gnus-sum.el (gnus-summary-enter-digest-group): Add
+       parent-group. 
 
-       * gnus/gnus-group.el (gnus-group-fetch-faq): Convert `.' in group
-       name to `/'.
+       * gnus-art.el (gnus-ignored-headers): Add more headers.
 
-Sun Jan  4 13:35:14 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * rfc2047.el (rfc2047-encode): See which encoding is shorter --
+       base64 or QP.
 
-       * nndraft.el (nndraft-request-associate-buffer): Open the damn
-       server first.  Sheesh.
+       * nnmail.el (nnmail-article-group): Default to "bogus".
 
-       * gnus-draft.el (gnus-draft-send): Bind message-send-hook to nil. 
+       * mail-source.el (mail-source-delete-incoming): Change to nil.
 
-       * gnus-sum.el (gnus-summary-catchup): Don't nix out downloadable. 
-       (gnus-summary-highlight): Highlight down/un as unread.
+2003-10-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sun Jan  4 13:27:31 1998  Kim-Minh Kaplan  <KimMinh.Kaplan@utopia.eunet.fr>
+       * mail-source.el (mail-source-fetch-imap): Fix mismatched parens.
 
-       * gnus-start.el (gnus-strip-killed-list): Fix syntax.
+2003-10-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sun Jan  4 13:18:04 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mail-source.el (defvar): Add post/pre/scripts.
+       (mail-source-fetch-imap): Use them.
 
-       * nnsoup.el (nnsoup-store-reply): Bind mail-header-separator to
-       "". 
+       * nndraft.el (nndraft-request-move-article): Fix infinite
+       recursion. 
 
-       * gnus-xmas.el (gnus-xmas-agent-server-menu-add): New.
+       * gnus-group.el (gnus-group-mark-regexp): Jump to groups.
 
-       * nnoo.el (nnoo-change-server): Get the right values.
+2003-10-16  Ed L. Cashin  <ecashin@uga.edu>
 
-1998-01-04  Aki Vehtari  <Aki.Vehtari@hut.fi>
+       * imap.el (imap-interactive-login): Set imap-password to nil if
+       login fails.
 
-       * gnus-art.el (gnus-signature-limit): Add default values for
-       choices suggested by Per Abrahamsen <abraham@dina.kvl.dk>.
-       (gnus-prompt-before-saving): Add :value t for sexp tag.
-       (gnus-split-methods): Add default values for choices.
+2003-10-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-score.el (gnus-home-score-file): Add non-nil default for
-       function.
-       (gnus-home-adapt-file): Ditto.
+       * message.el (message-inserted-headers): New variable.
+       (message-mode): Make local.
+       (message-mode): Set all the local action variables to nil.      
 
-       * gnus-sum.el (gnus-move-split-methods): Add default values for
-       choices.
+2003-10-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * nnmail.el (nnmail-list-identifiers): Add default values for
-       choices suggested by Per Abrahamsen <abraham@dina.kvl.dk>.
+       * mm-decode.el (mm-inline-text-html-with-images): Doc fix.
+       (mm-w3m-safe-url-regexp): Doc fix.
 
-Sun Jan  4 11:31:42 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-10-12  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus.el: Quassia Gnus v0.19 is released.
+       * gnus-sum.el (gnus-summary-respool-query): Don't narrow to head,
+       it's done by nnmail-article-group.
 
-Sun Jan  4 10:42:53 1998  Felix Lee  <flee@teleport.com>
+       * gnus-uu.el (gnus-uu-grab-articles): Fix misplaced parens.
+       From Mark Hood <markhood@speakeasy.net> (tiny change)
 
-       * nntp.el (nntp-open-rlogin): Use a list of parameters.
+2003-10-10  Jesper Harder  <harder@ifa.au.dk>
 
-Sun Jan  4 10:25:05 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-decode.el (mm-file-name-delete-gotchas): Avoid infloop in
+       XEmacs.
 
-       * gnus-agent.el (gnus-agent-fetch-groups): New command.
+2003-10-10  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-sum.el (gnus-summary-print-article): Changed order of
-       parameters.
+       * spam.el (spam-initialize): new function, does the spam-face
+       update and all the hooks, replaces spam-install-hooks-function
 
-Sun Jan  4 10:24:07 1998  Michael R. Cook  <mcook@cognex.com>
+       * gnus-registry.el (gnus-registry-initialize): new autoloaded
+       function to explicitly initialize the registry
 
-       * gnus-sum.el (gnus-summary-print-article): Use process/prefix.
+2003-10-10  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sun Jan  4 05:29:38 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-decode.el (mm-w3m-safe-url-regexp): Doc fix.
 
-       * gnus-uu.el: Changed spurious defconsts to defvars.
+       * mm-view.el (mm-w3m-mode-map): Doc fix.
+       (mm-inline-text-html-render-with-w3m): Add a comment.
 
-       * nnmail.el (nnmail-get-spool-files): Quote group name.
+2003-10-10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-agent.el (gnus-agent-fetch-group-1): Fetch ticked articles.
-       (gnus-agent-fetch-group-1): Never mind.
+       * gnus-group.el: Remove superfluous eval-when-compiles.
 
-Sat Dec 20 22:33:17 1997  Pete Ware  <ware@cis.ohio-state.edu>
+2003-10-10  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el (message-rename-buffer): Check for nil dirs.
+       * gnus-group.el (gnus-group-suspend): Reset gnus-backlog-articles.
 
-Fri Dec 19 21:45:59 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * nnml.el (nnml-request-create-group): Check for files.
+       * dns.el (query-dns): Don't error out on malformed resolv files.
 
-Fri Dec 19 21:39:43 1997  Hrvoje Niksic  <hniksic@srce.hr>
+2003-10-06  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el (message-mode): Fixed font-lock.
+       * gnus.el (gnus-group-faq-directory): Update .tw entry.  From
+       Albert Chun-Chieh Huang <mr894348@cs.nthu.edu.tw>
 
-Fri Dec 19 21:26:08 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-03  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-cache.el (gnus-cache-read-active): Check for empty files. 
+       * spam.el (spam-check-blackholes): exit the loop if matches are
+       found (idea from Adrian Lanz <lanz@fowi.ethz.ch>)
+       (spam-check-bogofilter-headers, spam-check-blackholes, spam-check-BBDB)
+       (spam-from-listed-p): use nnmail-fetch-field instead of message-fetch-field
+       
 
-Sun Dec 14 11:46:50 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-03  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-uu.el (gnus-uu-save-article): Quote all lines beginning
-       with a dash.
+       * mm-decode.el (mm-attachment-file-modes): Change the default
+       value into 384 from ?\600 which doesn't mean an integer in XEmacs.
 
-1997-12-10  SL Baur  <steve@altair.xemacs.org>
+2003-10-03  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-start.el (gnus-read-descriptions-file): Really bind and gag 
-       Mule.
+       * mm-decode.el (mm-file-name-delete-control)
+       (mm-file-name-delete-gotchas): New functions.
+       (mm-file-name-rewrite-functions): Use them.
+       (mm-attachment-file-modes): New option.
+       (mm-save-part-to-file): Use it.
 
-Fri Dec  5 15:15:05 1997  Danny Siu  <dsiu@adobe.com>
+2003-10-02  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * nndoc.el (nndoc-babyl-body-begin): quote the regexp for the
-       string "*** EOOH ***" properly.
-       (nndoc-babyl-head-begin): Same as above.
+       * spam.el (spam-install-hooks-function): Added Autoload cookie.
 
-Sun Dec 14 11:11:22 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-10-02  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-uu.el (gnus-uu-pre-uudecode-hook): New hook.
+       * pgg-def.el (pgg-default-keyserver-address): Change to
+       subkeys.pgp.net.  From Michael Shields <shields@msrl.com>
 
-       * gnus-sum.el (gnus-summary-read-group-1): Set mode line after
-       configuring. 
+2003-10-01  Simon Josefsson  <jas@extundo.com>
 
-Sun Dec 14 11:03:26 1997  Wes Hardaker  <wjhardaker@ucdavis.edu>
+       * message.el (message-idna-to-ascii-rhs-1): RHS can be terminated
+       by ',', as in 'foo@example.org, bar@example.org'.
 
-       * gnus-score.el (gnus-adaptive-word-minimum): New variable.
-       (gnus-score-adaptive): Use it.
+2003-10-01  Jesper Harder  <harder@ifa.au.dk>
 
-Sun Dec 14 09:19:18 1997  Roland B. Roberts  <roberts@panix.com>
+       * message.el (message-send): Fix reversed logic of supersedes
+       check.
 
-       * gnus-group.el: Fixed hardcoded levels.
+2003-09-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-Sat Dec  6 17:40:33 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus-art.el (gnus-article-view-part-as-charset): Doc fix,
+       suggested by Norbert Koch <viteno@xemacs.org>.
 
-       * gnus.el: Quassia Gnus v0.18 is released.
+2003-09-29  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Dec  6 17:27:04 1997  Kim-Minh Kaplan  <KimMinh.Kaplan@Utopia.EUnet.fr>
+       * gnus-topic.el (gnus-topic-goto-missing-topic): Revert 2003-02-09
+       change in order to correct the position where an invisible topic
+       (because gnus-topic-display-empty-topics is nil) may be inserted.
 
-       * gnus-picon.el (gnus-picons-remove): Race condition.
+2003-09-22  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Dec  6 17:23:26 1997  Christian von Roques  <roques@scalar.pond.sub.org>
+       * message.el (message-ignored-supersedes-headers): Add X-Payment.
 
-       * gnus-start.el (gnus-read-descriptions-file): Fix
-       enable-multibyte-characters. 
+2003-09-20  Jesper Harder  <harder@ifa.au.dk>
 
-1997-12-05  Dave Love  <d.love@dl.ac.uk>
+       * rfc2047.el (rfc2047-encode): Limit line length to 76 characters.
 
-       * gnus-nocem.el (gnus-nocem-message-wanted-p): Fix paren typpo.
-       (gnus-nocem-issuers): Allow sexp alternative in :type for alists.
+2003-09-20  Simon Josefsson  <jas@extundo.com>
 
-1997-12-05  Dave Love  <d.love@dl.ac.uk>
+       * tls.el (tls-process-connection-type): Doc fix.
 
-       * gnus-art.el (gnus-visible-headers): Add X-sent:.
+       * imap.el (imap-starttls-open): Rewrite, should support both old
+       starttls.el and new starttls.el that uses GNUTLS.
 
-Sat Dec  6 17:16:28 1997  Lars Balker Rasmussen  <lbr@mjolner.dk>
+2003-09-18  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-art.el (article-make-date-line): Don't add extra newlines. 
+       * gnus-art.el (gnus-treat-display-x-face): Use set-default instead
+       of custom-set-default which isn't available in old XEmacsen.
 
-1997-11-27  MORIOKA Tomohiko  <morioka@jaist.ac.jp>
+2003-09-17  Jesper Harder  <harder@ifa.au.dk>
 
-       * nnmail.el (nnmail-file-coding-system): Use `raw-text' in
-       default.
+       * gnus-msg.el (gnus-summary-resend-message-edit): Don't convert
+       to MML.  MIME -> MML -> MIME does not work for PGP/MIME.
 
-       * nnheader.el (nnheader-file-coding-system): Use `raw-text' in
-       default.
+       * message.el (message-bounce, message-forward-show-mml): do.
+       
+2003-09-13  Jesper Harder  <harder@ifa.au.dk>
 
-Sat Dec  6 17:04:40 1997  Kim-Minh Kaplan  <KimMinh.Kaplan@utopia.eunet.fr>
+       * rfc2047.el (rfc2047-charset-encoding-alist): Add viscii.
+       (rfc2047-encode): Add factors for big5, gb2312 and euc-kr.
 
-       * nnml.el (nnml-parse-head): Out-of-bounds fix.
+       * nnweb.el (nnweb-google-parse-1): Fix parsing.
 
-       * nndraft.el (nndraft-request-associate-buffer): Get proper file
-       name. 
+2003-09-12  Jesper Harder  <harder@ifa.au.dk>
 
-Sat Dec  6 15:35:37 1997  Gary D. Foster  <Gary.Foster@Corp.Sun.COM>
+       * gnus-group.el (gnus-group-fetch-control): ISC changed
+       compression from .Z to .gz.
 
-       * gnus-group.el: Added backspace.
+       * rfc2047.el (rfc2047-header-encoding-alist): Add "Approved" to
+       address-mime.
 
-Thu Nov 27 19:56:59 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-09-11  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-agent.el (gnus-summary-set-agent-mark): Remove marks
-       properly. 
+       * rfc2047.el (rfc2047-encode): Restrict encoded-words to 75
+       characters.
 
-1997-11-27  Christoph Wedler  <wedler@fmi.uni-passau.de>
+2003-09-10  Jesper Harder  <harder@ifa.au.dk>
 
-       * smiley.el (smiley-buffer): Provide `help-echo'.
+       * gnus.el (gnus-group-charter-alist): Update.
 
-Thu Nov 27 17:33:45 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-09-10  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-util.el (gnus-output-to-rmail): Always save buffer.
+       * spam-report.el: use mm-url.el functions for external URL
+       loading when the built-in HTTP GET is insufficient (e.g. proxies
+       are in the way).  From Eric Knauel
+       <knauel@informatik.uni-tuebingen.de>.
+       (spam-report-url-ping-function): new option, defaults to the
+       built-in HTTP GET (spam-report-url-ping-plain)
+       (spam-report-url-ping): calls spam-report-url-ping-function now
+       (spam-report-url-ping-plain): new function, does what
+       spam-report-url-ping used to do
+       (spam-report-url-ping-mm-url): function that delegates to
+       mm-url.el (autoloaded)
 
-       * nntp.el (nntp-close-server): Don't sleep for me, Argentina.
-       (nntp-request-close): You neither.
+2003-09-08  Teodor Zlatanov  <tzz@lifelogs.com>
 
-1997-11-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * gnus-registry.el (gnus-registry-delete-id): function to
+       completely delete an ID, including all the cache hashtables
+       (gnus-registry-delete-group): use gnus-registry-delete-id
+       (gnus-registry-simplify-subject): only run if the argument is a
+       string, return nil otherwise
 
-       * message.el (message-header-lines): New widget.
-       (message-default-headers): Use it.
-       (message-default-mail-headers): Use it.
-       (message-default-news-headers): Use it.
+2003-09-07  Jesper Harder  <harder@ifa.au.dk>
 
-1997-11-24  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+       * gnus-msg.el (gnus-summary-resend-bounced-mail): Docstring fix.
 
-       * gnus-start.el (gnus-read-descriptions-file): Add missing quote.
+2003-09-05  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Wed Nov 26 18:19:29 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-registry.el (gnus-registry-split-fancy-with-parent): yet
+       another error *sigh*
 
-       * nnweb.el (nnweb-type-definition): Rescued dejanewsold.
+       * gnus-registry.el (gnus-registry-fetch-extra-entry): don't use
+       puthash unless gnus-registry-entry-caching is on
+       (gnus-registry-split-fancy-with-parent): misplaced parenthesis
+       made everything a part of the 'else'
+       (gnus-registry-save): used 'entry-caching' instead of 'caching'
 
-       * gnus-mh.el (gnus-summary-save-in-folder): Reverted to old
-       version. 
+2003-09-05  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-sum.el (gnus-kill-or-deaden-summary): Save excursion.
+       * gnus-art.el (gnus-button-alist): Improve Info regexp.
 
-       * gnus.el: Only require gnus-load in Emacsen 19.
+2003-09-04  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-start.el (gnus-setup-news): Always push archive server.
+       * gnus-registry.el: added brief explanation of basics
+       (gnus-registry-track-extra): new variable for tracking of message
+       subjects
+       (gnus-registry-entry-caching): caching parameter, used for extra
+       data
+       (gnus-registry-minimum-subject-length): minimum subject length
+       before it's considered when tracing subjects
+       (gnus-registry-save): accomodate extra data entry caching
+       (gnus-registry-action): change function name, add the subject and
+       pass it to gnus-registry-add-group
+       (gnus-registry-spool-action): change function name, add the
+       subject and pass it to gnus-registry-add-group
+       (gnus-registry-split-fancy-with-parent): add subject tracking
+       (gnus-registry-register-message-ids): pass subject to
+       gnus-registry-add-group
+       (gnus-registry-simplify-subject)
+       (gnus-registry-fetch-simplified-message-subject-fast): new
+       functions
+       (gnus-registry-fetch-extra, gnus-registry-fetch-extra-entry): add
+       extra data entry caching
+       (gnus-registry-add-group): handle the extra subject parameter
+       (gnus-registry-install-hooks, gnus-registry-unload-hook): fix the
+       gnus-register-* function names
 
-       * gnus-sum.el (gnus-read-header): Would bug out on sparse
-       articles. 
+       * nnmail.el (nnmail-cache-insert): add subject parameter, pass it
+       on to the nnmail-spool-hook
 
-Wed Nov 26 17:50:41 1997  Kurt Swanson  <kurt@dna.lth.se>
+       * nnbabyl.el (nnbabyl-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-       * gnus-ems.el (gnus-mule-cite-add-face): Work.
+       * nndiary.el (nndiary-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-Wed Nov 26 17:40:57 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * nnfolder.el (nnfolder-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-       * gnus.el: Quassia Gnus v0.17 is released.
+       * nnimap.el (nnimap-split-articles): added subject to
+       nnmail-cache-insert call
+       (nnimap-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-Wed Nov 26 16:04:25 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nnmbox.el (nnmbox-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-       * gnus-sum.el (gnus-summary-move-article): Don't work on canceled
-       articles. 
+       * nnmh.el (nnmh-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-       * gnus-start.el (gnus-subscribe-hierarchical-interactive): Use
-       `read-char-exclusive'. 
+       * nnml.el (nnml-request-accept-article): added subject to
+       nnmail-cache-insert call
 
-       * gnus-sum.el (gnus-summary-mode): Localize
-       gnus-summary-dummy-line-format. 
+2003-09-04  Jesper Harder  <harder@ifa.au.dk>
 
-       * nnml.el (nnml-open-nov): Check that the file exists before
-       inserting it. 
+       * gnus-art.el (gnus-button-handle-info-url)
+       (gnus-button-handle-info-url-gnome)
+       (gnus-button-handle-info-url-kde, gnus-button-alist): Handle GNOME
+       and KDE style Info URLs.
 
-       * gnus-art.el (article-date-ut): Insert a newline if needed.
+       * gnus-util.el (gnus-url-unhex-string): Don't replace "+" with " ".
 
-       * gnus-score.el (gnus-score-edit-current-scores): Protect against
-       nil score files.
+2003-09-02  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-start.el (gnus-newsrc-parse-options): Be more correct --
-       match only hierarchies.
-       (gnus-gnus-to-quick-newsrc-format): Changed warning.
+       * rfc2047.el (rfc2047-fold-region): Don't fold at the beginning
+       of the field.
 
-Wed Nov 26 15:47:40 1997  Greg Klanderman  <greg@alphatech.com>
+2003-09-01  Simon Josefsson  <jas@extundo.com>
 
-       * messagexmas.el (message-xmas-maybe-fontify): New definition.
+       * mml.el (mml-insert-mime-headers-always): New variable.
+       (mml-insert-mime-headers): Use it.  Based on (tiny) patch from
+       Lars Balker Rasmussen <lars@balker.org>.
 
-Wed Nov 26 15:43:53 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-08-30  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-start.el (gnus-setup-news): Protect against nil
-       gnus-message-archive-method. 
+       * mail-source.el (mail-source-fetch-imap): Pass correct buffer to
+       imap-open, reverts 2003-03-17 change.  Reverse remove before
+       calling gnus-compress-sequence.  From Gaute Strokkenes
+       <gs234@srcf.ucam.org> (tiny change).
 
-1997-11-26  Christoph Wedler  <wedler@fmi.uni-passau.de>
+2003-08-29  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-art.el (gnus-article-edit-done): Update headers "Lines:",
-       "Content-Length:" and "X-Content-Length:" when present.
+       * gnus-group.el (gnus-group-delete-group): Doc fix.  Suggested by
+       Jochen K\e,A|\e(Bpper <jochen@jochen-kuepper.de>.
 
-Wed Nov 26 15:08:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-08-29  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * nnmail.el (nnmail-process-unix-mail-format): Pop to the right
-       buffer on error.
-       (nnmail-process-mmdf-mail-format): Ditto.
+       * gnus-art.el (article-display-x-face): Make it possible to set
+       the gnus-article-x-face-command variable to the lambda form.
 
-Wed Nov 26 13:54:04 1997  Joe Reiss  <jreiss@sprynet.com>
+2003-08-27  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-art.el (gnus-summary-save-in-rmail): Return the name of the
-       file.
+       * mm-decode.el (mm-remove-part): Try to kill external displayers
+       cleanly first (if it refuses, C-g aborts loop and kill process
+       unconditionally).  Also make sure process is dead before we remove
+       the files it may be using.  Reported by David Coe
+       <davidc@debian.org>.
+
+2003-08-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-cache.el (gnus-cache-generate-active): Fix bug in
+       replacement.  From Vagn Johansen <v@johansen.mail.dk> (tiny
+       change).
+
+2003-08-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el: Don't use defvaralias.
+       (gnus-treat-display-x-face): Warn if the obsolete variable
+       `gnus-treat-display-xface' exists.
+
+2003-08-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-treat-display-face): Fix typo.
+       (gnus-treat-display-xface): Rename to gnus-treat-display-x-face
+       (reported by Jochen K\e,A|\e(Bpper <jochen@jochen-kuepper.de>)
+
+2003-08-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-header-button-alist, gnus-button-alist): Fix
+       type.
+
+2003-08-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-make-forward-subject-function): Fix
+       customize mismatch.
+
+       * gnus.el (gnus-message-archive-method): do.
+
+2003-08-20  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.el (gnus-read-group): Offer to continue only if the invalid
+       char is `/' and add more information for the user.
+
+       * gnus-art.el (gnus-button-alist): Add `+' (gnus-button-handle-man).
+       (gnus-header-button-alist): Added `In-Reply-To'.
+
+       * nnimap.el (nnimap-open-connection): Allow different user names
+       on the same server (and in the same authinfo file).
+
+2003-08-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sieve.el (gnus-sieve-crosspost): Fix type.
+
+       * message.el (message-make-forward-subject-function): Add
+       message-forward-subject-name-subject to choices.
+
+       * gnus-art.el (gnus-article-edit-done, gnus-article-edit-exit):
+       Redisplay article after editing.
+
+2003-08-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.el (gnus-read-group): Added check to ask confirmation if
+       Group name contains invalid character. You can use '/' in IMAP,
+       but not in filenames. G m cannot know what the user is creating,
+       so let user decide. See thread m2oeysiev3.fsf@naima.lensflare.org.
+       Tiny patch from letters@hotpop.com (Jari Aalto+mail.linux).
+
+2003-08-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-score.el (gnus-summary-score-effect): Fix interactive use.
+
+2003-08-10  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-draft.el (gnus-draft-send-all-messages): ask if all drafts
+       should be sent unless gnus-expert-user is on
+
+2003-08-09  Jesper Harder  <harder@ifa.au.dk>
+
+       * pgg-gpg.el (pgg-gpg-extra-args): Fix customization type.
+
+2003-08-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Bind
+       default-enable-multibyte-characters to nil.
+
+2003-08-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el (canlock-password): Fix customization type.
+       (canlock-password-for-verify): Ditto.
+       * deuglify.el (gnus-outlook-deuglify-unwrap-min): Ditto.
+       (gnus-outlook-deuglify-unwrap-max): Ditto.
+       (gnus-outlook-deuglify-unwrap-stop-chars): Ditto.
+       * gnus-sum.el (gnus-sum-thread-tree-root): Ditto.
+       (gnus-sum-thread-tree-false-root): Ditto.
+       (gnus-sum-thread-tree-single-indent): Ditto.
+       * message.el (message-archive-note): Ditto.
+       (message-subscribed-address-file): Ditto.
+       (message-user-fqdn): Ditto.
+       * spam-report.el (spam-report-gmane-regex): Ditto.
+       * spam.el (spam-blackhole-good-server-regex): Ditto.
+
+       * gnus-start.el (gnus-save-killed-list): Fix last change.
+       * message.el (message-courtesy-message): Ditto.
+
+2003-08-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-header-face-alist): Revert previous change.
+       (gnus-header-newsgroups-face): Explain that it's only used for
+       crossposts.
+
+2003-08-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-registry.el (gnus-registry-max-entries): Fix customization
+       type.
+       * gnus-score.el (gnus-adaptive-word-length-limit): Ditto.
+       * gnus.el (gnus-refer-article-method): Ditto.
+       * message.el (message-courtesy-message): Ditto.
+
+2003-08-06  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-header-face-alist): Fix "Newsgroups" entry.
+       From Chunyu Wang <spr@db.cs.hit.edu.cn> (tiny patch)
+
+2003-08-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-save-killed-list): Fix customization type.
+       * gnus-sum.el (gnus-thread-hide-subtree): Ditto.
+       * gnus.el (gnus-use-long-file-name): Ditto.
+
+2003-08-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-group.el (gnus-group-rename-group): Don't allow renaming to
+       an existing name.
+
+       * gnus-sum.el (gnus-summary-highlight): Add uncached to docstring.
+
+       * nnmail.el (nnmail-large-newsgroup): Docstring fix.
+
+       * nntp.el (nntp-large-newsgroup): do.
+
+       * nnspool.el (nnspool-large-newsgroup): do.
+
+       * gnus-cus.el (gnus-group-parameters): Typo.
+
+2003-07-31  Simon Josefsson  <jas@extundo.com>
+
+       * mml-sec.el (mml-signencrypt-style-alist): Use separate S/MIME
+       method by default (revert partial 2003-07-10 patch).
+
+2003-07-28  Dave Love  <fx@gnu.org>
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el: Require cl when compiling.
+
+2003-07-26  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-registry-install): add an initial
+       registry read to the loading when gnus-registry-install is set
+
+2003-07-26  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * flow-fill.el (fill-flowed): Empty lines separate paragraphs
+       even if the preceding line ends with a soft break.  Tiny patch
+       from Mark Thomas <swoon@bellatlantic.net>.
+
+2003-07-25  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-regex-body, spam-regex-body-spam) 
+       (spam-regex-body-ham): new variables, default to nil/empty/empty
+       (spam-install-hooks): added spam-use-regex-body to list or
+       pre-install conditions
+       (spam-list-of-checks): added spam-use-regex-body and
+       spam-check-regex-body to list of checks
+       (spam-list-of-statistical-checks): added spam-use-regex-body to
+       list of statistical checks
+       (spam-check-regex-body): invokes spam-check-regex-headers with
+       appropriate variable masking
+       (spam-check-regex-headers): changes to print "body" or "header"
+       where appropriate
+
+2003-07-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * smime.el (smime-ask-passphrase): Use read-passwd rather than
+       comint-read-noecho.  The former is more secure.
+
+2003-07-24  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-registry-cache-whitespace): make "adding
+       whitespace" message level 5 instead of 4
+       (gnus-registry-clean-empty-function): new function to remove empty
+       registry entries
+       (gnus-registry-clean-empty): new variable to enable cleaning the
+       registry when saving it by calling gnus-registry-clean-empty-function
+
+       * spam.el (spam-summary-prepare-exit): use spam-process-ham-in-spam-groups
+       (spam-process-ham-in-spam-groups): new variable
+
+2003-07-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * pgg-gpg.el (pgg-gpg-process-region): Add "--yes" to options.
+
+       * pgg-gpg.el, pgg-pgp.el, pgg-pgp5.el, pgg.el: Reapply changes
+       from 2003-04-03 to fix security problem.  See
+       http://www.debian.org/security/2003/dsa-339
+
+2003-07-23  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.el (gnus-install-group-spam-parameters): add the
+       gnus-ticked-mark to the possible choices of ham marks
+
+       * spam.el (spam-process-ham-in-nonham-groups): new variable
+       (spam-summary-prepare-exit): use spam-process-ham-in-nonham-groups
+
+2003-07-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * rfc2047.el (rfc2047-header-encoding-alist): Add Mail-Followup-To
+       and Mail-Copies-To to address-mime.
+       (rfc2047-narrow-to-field): Use rfc2047-point-at-bol.
+
+2003-07-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-util.el (mm-coding-system-priorities): Docstring improvement.
 
-Wed Nov 26 13:50:01 1997  Alastair Burt <alastair.burt@dfki.de>
+2003-07-17  Jesper Harder  <harder@ifa.au.dk>
 
-       * smiley.el: Balloon help, etc.
+       * gnus-sum.el (gnus-thread-latest-date): Move condition-case to
+       the right place.
 
-Wed Nov 26 13:45:35 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-07-14  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-util.el (gnus-kill-all-overlays): Remove check for XEmacs. 
+       * mail-source.el (mail-source-fetch-imap): Don't assume
+       imap-error-text returns something.
 
-1997-09-30  Dave Love  <d.love@dl.ac.uk>
+2003-07-12  Nevin Kapur  <kapur@mts.jhu.edu>
 
-       * message.el: Don't require rmail.
+       * nnimap.el (nnimap-request-newgroups): Use the pattern in
+       nnimap-list-pattern instead of "*".
 
-Wed Nov 26 13:37:50 1997  Kurt Swanson  <kurt@dna.lth.se>
+2003-07-10  Simon Josefsson  <jas@extundo.com>
 
-       * gnus-group.el (gnus-group-setup-buffer): set-buffer.
+       * mml-sec.el (mml-signencrypt-style-alist): Use "combined" by
+       default.  Improve docstring.
 
-Wed Nov 26 13:31:54 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-07-10  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * gnus-score.el (gnus-score-load-file): Don't create empty score
-       files when doing decays.
+       * imap.el (imap-arrival-filter): Fix test for missing process
+       buffer.
+
+2003-07-09  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+       From Gaute B Strokkenes <gs234@cam.ac.uk> (tiny patch).
+
+       * imap.el (imap-wait-for-tag): Clarify comment.  Use timeout zero
+       for second, after-process-has-died, accept-process-output.
+       (imap-arrival-filter): If PROC has no buffer, do nothing.
+
+2003-07-09  Jesper Harder  <harder@ifa.au.dk>
 
-Wed Nov 26 13:28:04 1997  Renaud Rioboo  <rioboo@calfor.lip6.fr>
+       * flow-fill.el: Docstring and message fixes.
 
-       * nnmail.el (nnmail-move-inbox): Only bind default-directory when
-       calling external function.
+       * deuglify.el: do.
 
-Wed Nov 26 13:03:45 1997  IWAMURO Motonori  <iwa@mmp.fujitsu.co.jp>
+       * gnus-int.el: do.
 
-       * gnus-kill.el (gnus-batch-score): Newsrc thinko.
+       * gnus-msg.el: do.
 
-Wed Nov 26 10:31:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-util.el: do.
 
-       * nnheader.el (nnheader-parse-head): Would break on Message-ID's
-       that spanned several lines.
+       * gnus-draft.el: do.
 
-       * gnus-util.el (gnus-date-iso8601): Didn't pick out the date
-       header. 
+       * gnus-start.el: do.
 
-       * gnus-demon.el (gnus-demon-scan-mail): Clean inboxes.
+       * gnus.el: do.
 
-1997-11-25  Christoph Wedler  <wedler@fmi.uni-passau.de>
+       * gnus-group.el: do.
 
-       * gnus-picon.el (gnus-picons-x-face-sentinel): Would bug out in
-       headers with two X-Face lines.
+       * gnus-art.el: do.
 
-Wed Nov 26 08:54:26 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el: do.
 
-       * gnus-sum.el (gnus-summary-update-info): Would use wrong group
-       name. 
+       * mail-source.el (mail-source-movemail): Handle non-numerical
+       return values.
 
-1997-11-26  Hrvoje Niksic  <hniksic@srce.hr>
+2003-07-08  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-spec.el (gnus-compile): Avoid multiple `c*addr's.
-       (gnus-compile): Require `bytecomp'.
+       * mailcap.el (mailcap-parse-args-syntax-table)
+       (mailcap-viewer-passes-test): Docstring fix.
 
-1997-11-25  Hrvoje Niksic  <hniksic@srce.hr>
+       * mm-bodies.el (mm-long-lines-p): Docstring fix.
 
-       * gnus-util.el (gnus-prin1): Bind `print-readably' to t.
+       * mm-decode.el (mm-w3m-safe-url-regexp, mm-verify-option)
+       (mm-decrypt-option, mm-handle-set-external-undisplayer)
+       (mm-file-name-replace-whitespace): Docstring fix.
 
-       * gnus-xmas.el (gnus-xmas-kill-all-overlays): New function.
-       (gnus-xmas-define): Use it.
+       * mm-uu.el (mm-uu-emacs-sources-regexp): Docstring fix.
+       (mm-uu-pgp-signed-test): Fix message.
 
-       * gnus-art.el (gnus-stop-date-timer): Use `nnheader-cancel-timer'.
+       * mml.el (mml-tweak-sexp-alist): Docstring fix.
+       (mml-parse-1, mml-insert-mime-headers): Fix message.
 
-       * message.el (message-header-lines): Specify format.
+       * message.el (message-archive-header)
+       (message-subscribed-address-functions)
+       (message-subscribed-addresses, message-subscribed-regexps)
+       (message-canlock-generate)
+       (message-generate-new-buffer-clone-locals): Docstring fixes.
 
-       * gnus-xmas.el (gnus-xmas-move-overlay): Use BUFFER.
-       (gnus-byte-code): Use `indirect-function'.
+2003-07-07  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * gnus-cite.el (gnus-cite-add-face): Would assign free variable.
+       * imap.el (imap-wait-for-tag): After the process has died, look
+       for more output still pending.  From Gaute B Strokkenes
+       <gs234@cam.ac.uk> (tiny patch).
 
-Wed Nov 26 08:31:28 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-07-07  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-art.el (gnus-stop-date-timer): Cancel instead of delete. 
-       (gnus-start-date-timer): Use the numerical prefix.
+       * spam.el (spam-bogofilter-score): redisplay article normally
+       after spam-bogofilter-score is called
 
-Tue Nov 25 20:03:34 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-07-06  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-draft.el (gnus-group-send-drafts): Activate group first.
+       * message.el (message-send-mail-with-sendmail): Handle
+       non-numeric return values.
 
-Tue Nov 25 19:57:55 1997  Dan Christensen  <jdc@chow.mat.jhu.edu>
+       * gnus-sum.el (gnus-print-buffer): Apply emphasis.
+       From Michael Piotrowski <mxp@dynalabs.de> (tiny change).
 
-       * gnus-group.el (gnus-group-process-prefix): Skip topics.
+       * gnus-start.el (gnus-clear-system): Revert change from
+       2003-06-19.
 
-Tue Nov 25 19:54:00 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-07-04  Dave Love  <fx@gnu.org>
 
-       * gnus-move.el (gnus-move-group-to-server): Protect agains
-       nil-ness. 
+       * rfc2047.el (rfc2047-q-encode-region): Exclude especials from
+       characters not encoded, and make the list more legible.
 
-Tue Nov 25 19:03:38 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-07-04  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus.el: Quassia Gnus v0.16 is released.
+       * message.el (message-make-from): Revert change from 2002-01-08.
 
-Tue Nov 25 16:05:01 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-sum.el (gnus-read-header): Remove thread entry before
-       rebuilding. 
+       * nnheader.el (nnheader-init-server-buffer): Don't add
+       nntp-server-buffer to list of Gnus buffers.
 
-       * gnus-cite.el (gnus-cite-add-face): Keep track of all overlays.
+2003-06-25  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-art.el (article-update-date-lapsed): New function.
-       (gnus-start-date-timer): New command.
-       (article-date-ut): Put the face in the right place.
-       (article-date-ut): Would move around.
+       * spam.el (spam-parse-list): prevent empty ("") strings
 
-       * gnus-group.el (gnus-group-read-ephemeral-group): Accept server
-       names. 
+2003-06-24  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-srvr.el (gnus-browse-foreign-server): Use proper server
-       names. 
+       * spam.el (spam-parse-list): use gnus-extract-address-components
+       instead of ietf-drums-parse-addresses
+       (spam-from-listed-p): let* was unnecessary
 
-       * gnus.el (gnus-group-prefixed-name): Give the right result for
+2003-06-24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-ems.el (gnus-put-image): Mark the right text segment with
+       gnus-image-category. 
+
+       * gnus-srvr.el (gnus-browse-unsubscribe-group): Strip prefix from
        native groups.
 
-       * nnheader.el (nnheader-directory-files): New function.
+       * gnus-topic.el (gnus-group-prepare-topics): Update topic line
+       format specs.
 
-       * nnmh.el (nnmh-request-list-1): Reversed check.
+       * gnus-picon.el: Written by moi, moi, moi.
 
-       * nnfolder.el (nnfolder-delete-mail): Would skip backwards one
-       line too much.
+       * gnus-group.el (gnus-group-kill-group): Clean up.
 
-Tue Nov 25 14:44:02 1997  SeokChan LEE  <chan@xfer.kren.nm.kr>
+2003-06-23  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * message.el (message-ignored-supersedes-headers): Typo.
+       * spam.el (spam-from-listed-p, spam-parse-list): use
+       ietf-drums-parse-addresses to extract the address portion of the
+       whitelist/blacklist file if it looks like an address can be found
 
-Mon Nov 24 18:46:37 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-06-23  Didier Verna  <didier@xemacs.org>
 
-       * gnus.el: Quassia Gnus v0.15 is released.
+       * gnus-ems.el (gnus-put-image): New argument CATEGORY. Add it as a
+       text property.
+       (gnus-remove-image): New argument CATEGORY. Only remove if
+       category matches.
+       * gnus-xmas.el (gnus-xmas-put-image):
+       (gnus-xmas-remove-image): Ditto, with extents.
+       * gnus-art.el (gnus-delete-images): Pass CATEGORY argument to
+       gnus-[xmas-]remove-image.
+       (article-display-face): Don't always act as a toggle. Call
+       `gnus-put-image' with CATEGORY argument.
+       (article-display-x-face): Call `gnus-put-image' with CATEGORY
+       argument.
+       * smiley.el (smiley-region): Ditto.
+       * gnus-fun.el (gnus-display-x-face-in-from): Ditto.
+       * gnus-picon.el (gnus-picon-insert-glyph): Ditto.
+       (gnus-treat-mail-picon): Don't always act as a toggle.
+       * gnus-picon.el (gnus-treat-newsgroups-picon): Ditto.
 
-Mon Nov 24 18:07:21 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-23  Didier Verna  <didier@xemacs.org>
 
-       * gnus-ems.el: Also check major version names.
+       * gnus-art.el (article-display-face): Check for existence of the
+       original article buffer before switching to it.
 
-1997-10-05  SL Baur  <steve@altair.xemacs.org>
+2003-06-20  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el (require 'rmail): Put guard around.
-       * nnbabyl.el (require 'rmail): Ditto.
+       * mm-util.el (mm-append-to-file): Say "Appended to".  Suggested by
+       Dan Jacobson <jidanni@jidanni.org>.
 
-Mon Nov 24 17:36:00 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-view.el (mm-inline-message): Bind
+       gnus-original-article-buffer to the buffer in the mml handle
+       holding the message.
 
-       * message.el (message-reply): Respect Mail-Copies-To even when
-       `to-address'. 
+2003-06-20  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Mon Nov 24 17:32:47 1997  Thor Kristoffersen  <thor@unik.no>
+       * message.el (sender, from): No need to bind them.
 
-       * nntp.el (nntp-request-close): Sleep one second.
+2003-06-19  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Mon Nov 24 16:18:19 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * spam.el (spam-enter-list): search-forward specified wrong
 
-       * gnus-sum.el (gnus-summary-read-group-1): Update marks when not
-       entering group.
+2003-06-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-start.el (gnus-setup-news): Get correct value of archive
-       server. 
+       * gnus-art.el: Comment fix.
 
-Wed Oct  8 20:29:35 1997  Robert Bihlmeyer  <robbe@orcus.priv.at>
+2003-06-20  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el (message-make-organization): Don't let the
-       environment variable override a user-set organization.
+       * gnus-msg.el (gnus-configure-posting-styles): Remove unused
+       variable.  From Jan Rychter <jan@rychter.com>.
 
-Mon Nov 24 14:09:00 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * spam.el (spam-spamoracle-learn): insert-string is obsolete.
 
-       * nnml.el (nnml-open-nov): Don't use find-file.
+2003-06-19  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-sum.el (gnus-last-newsgroup-variables-set): New variable.
-       (gnus-set-global-variables): Don't do to much; gets run off of
-       pre-command-hook. 
-       Got rid of gnus-set-global-variables throughout.
-       (gnus-summary-exit): Update adaptive scoring here.
-       (gnus-summary-isearch-article): Widen.
+       * spam.el (spam-enter-list): do not enter duplicate addresses into
+       the whitelist/blacklist
 
-       * nnml.el (nnml-parse-head): Work in empty buffers.
+2003-06-19  Jesper Harder  <harder@ifa.au.dk>
 
-1997-10-14  Hrvoje Niksic  <hniksic@srce.hr>
+       * nnheader.el (nnheader-init-server-buffer): Add
+       nntp-server-buffer to gnus-buffers.
 
-       * gnus-xmas.el (gnus-xmas-group-startup-message): Check for image
-       formats correctly.
-       (gnus-xmas-modeline-glyph): Ditto.
+       * gnus-start.el (gnus-clear-system): Now we don't need to kill
+       nntp-server-buffer separately.
 
-Mon Nov 24 13:58:12 1997  Hrvoje Niksic  <hniksic@srce.hr>
+2003-06-18  Didier Verna  <didier@xemacs.org>
 
-       * gnus-spec.el (gnus-compile): Work under XEmacs.
+       * gnus-art.el (article-display-face): Correctly toggle between
+       display and hiding. Handle multiple Face headers.
 
-Mon Nov 24 07:15:45 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-17  Dave Love  <fx@gnu.org>
 
-       * nnoo.el (nnoo-change-server): Push the right parent packend onto
-       the alist.
+       * nnimap.el: Require cl when compiling.
 
-Sun Nov 23 16:21:41 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * message.el (message-fix-before-sending): Reinstate nullifying
+       the invisible text property.
+       (sender, from): Defvar when compiling.
+       (message-is-yours-p): Remove autoload cookie.
 
-       * gnus.el: Quassia Gnus v0.14 is released.
+2003-06-17  Reiner Steib  <Reiner.Steib@gmx.de>
 
-Sun Nov 23 14:04:07 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-util.el (gnus-extract-address-components): Added
+       doc-string.
 
-       * gnus-start.el (gnus-read-descriptions-file): Make sure Mule is
-       bound.  And gagged.
+2003-06-16  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * message.el (message-send-mail-with-mh): Use
-       `mh-new-draft-name'. 
+       * nnml.el (nnml-current-group-article-to-file-alist): Don't read
+       overview when using compressed files.  From Michael Albinus
+       <Michael.Albinus@alcatel.de>.
 
-       * nnfolder.el (nnfolder-read-folder): Save new buffers.
+2003-06-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * gnus-sum.el (gnus-summary-make-menu-bar): Removed "write to
-       file". 
+       * gnus-sum.el (gnus-summary-refer-parent-article): Extract
+       Message-ID from In-Reply-To header.
 
-       * gnus-util.el (gnus-byte-code): Use indirect-function.
+2003-06-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * nntp.el (nntp-open-telnet): Also accept 201.
+       * message.el (message-is-yours-p): Narrow to head; extract from
+       and sender by itself.
+       (message-cancel-news, message-supersede): Remove useless things.
 
-       * gnus-sum.el (gnus-summary-reparent-thread): Update thread.
+2003-06-15  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-score.el (gnus-all-score-files): Don't do anything unless
-       GROUP. 
+       * gnus-sum.el (gnus-summary-force-verify-and-decrypt): Bind
+       `gnus-article-emulate-mime'.
 
-       * nnmail.el (nnmail-split-it): Save-excursion.
-       (nnmail-group-pathname): Translate file chars.
+2003-06-15  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+       From Tommi Vainikainen <thv+gnus@iki.fi>.
 
-Sun Nov 23 13:41:10 1997  Gunnar Horrigmo  <horrigmo@online.no>
+       * message.el (message-is-yours-p): New function.  Separated common
+       code from message-cancel-news and message-supersede.  Added
+       matching code which uses message-alternative-emails regexp as last
+       resort.
+       (message-cancel-news, message-supersede): Use message-is-yours-p.
 
-       * gnus-sum.el (gnus-summary-exit): Don't skip if group
-       disappeared. 
+2003-06-13  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-Sun Nov 23 13:32:55 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nnimap.el (nnimap-split-articles): Narrow the right buffer to
+       the headers.  From Niklas Morberg <niklas.morberg@axis.com>.
 
-       * nnfolder.el (nnfolder-normalize-buffer): New function.
-       (nnfolder-save-mail): Use it.
-       (nnfolder-request-replace-article): Ditto.
+2003-06-12  Dave Love  <fx@gnu.org>
 
-1997-11-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+       * nnheader.el (nnheader-functionp): Deleted.
 
-       * message.el (message-header-lines): New widget.
-       (message-default-headers): Use it.
-       (message-default-mail-headers): Use it.
-       (message-default-news-headers): Use it.
+       * nnmail.el (nnmail-split-fancy-syntax-table): Define all in
+       defvar.
+       (nnmail-version): Deleted.
+       (nnmail-check-duplication, nnmail-expiry-target-group): Don't use
+       nnheader-functionp.
 
-Sun Nov 23 12:44:38 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-10  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-win.el (gnus-remove-some-windows): Also delete dead summary
-       windows.
+       * spam.el (spam-check-bogofilter-headers): fix for when the score
+       is requested but the message is not spam
 
-       * gnus-score.el (gnus-score-adaptive): Check whether functions are
-       bound.
+2003-06-09  Teodor Zlatanov  <tzz@lifelogs.com>
+       From Eric
+       <knauel@informatik.uni-tuebingen.de>
 
-Sun Nov 23 12:15:00 1997  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+       * spam.el (spam-use-spamoracle): new variable
+       (spam-install-hooks): add spamoracle to the list of conditions
+       for activation of spam-install-hooks
+       (spam-spamoracle): new variable customization group
+       (spam-spamoracle, spam-spamoracle): new variables
+       (spam-group-spam-processor-spamoracle-p)
+       (spam-group-ham-processor-spamoracle-p): new functions
+       (spam-summary-prepare-exit): added spamoracle ham/spam exit processing
+       (spam-list-of-checks, spam-list-of-statistical-checks): add
+       spam-use-spamoracle
+       (spam-check-spamoracle, spam-spamoracle-learn)
+       (spam-spamoracle-learn-ham, spam-spamoracle-learn-spam): new functions
 
-       * gnus-sum.el (gnus-summary-limit-include-thread): Interactive
-       fix. 
+       * gnus.el (gnus-group-spam-exit-processor-spamoracle)
+       (gnus-group-ham-exit-processor-spamoracle): new variables for SpamOracle
+       (spam-process, ham-process): added spamoracle spam/ham processors
 
-Sun Nov 23 07:06:58 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-08  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-sum.el (gnus-summary-reparent-thread): Insert Message-ID in
-       proper place.
+       * message.el (message-beginning-of-line): Docstring improvement.
+       Suggested by Michael R. Wolf <MichaelRunningWolf@att.net>
 
-Sat Nov 22 18:30:33 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-cus.el (gnus-group-parameters): Add visible.
+       * gnus-sum.el (gnus-summary-make-menu-bar): Removed ["Add buttons"
+       gnus-summary-display-buttonized t]
 
-Sat Nov 22 18:19:39 1997  Kim-Minh Kaplan  <kkaplan@lpthe.jussieu.fr>
+2003-06-07  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * message.el (message-setup): Add a newline, if necessary.
+       * nnmail.el (nnmail-split-fancy-match-partial-words): Doc string
+       fix.  Reported by Johan Bockg\e,Ae\e(Brd <bojohan+news@dd.chalmers.se>.
 
-Sat Nov 22 18:04:34 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-07  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-mh.el (gnus-summary-save-in-folder): Fix for default.
+       * message.el (message-beginning-of-line): Docstring improvement.
 
-Sat Nov 22 18:01:26 1997  Didier Verna  <verna@inf.enst.fr>
+2003-06-06  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-sum.el (gnus-summary-remove-bookmark): Interactive spec. 
+       * gnus-srvr.el (gnus-browse-foreign-server): Parse garbage NNTP
+       groups correctly.
 
-Mon Nov 17 23:50:51 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-06-06  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+       From Benjamin Rutt <rutt+news@cis.ohio-state.edu>.
 
-       * gnus-art.el (article-display-x-face): Fold case.
+       * message.el (message-fetch-field): Augment documentation to state
+       the narrowed-to-headers restriction.
+       (message-change-subject, message-reduce-to-to-cc)
+       (message-generate-unsubscribed-mail-followup-to)
+       (message-insert-importance-high, message-insert-importance-low)
+       (message-insert-or-toggle-importance)
+       (message-insert-disposition-notification-to): Narrow to headers
+       before calling message-fetch-field or message-remove-header.
 
-Thu Nov 13 22:57:23 1997  Kenichi Handa  <handa@etl.go.jp>
+2003-06-06  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus/gnus-start.el (gnus-read-descriptions-file): Decode
-       description if necessary.
+       * gnus-registry.el (gnus-registry-trim): fix for when
+       gnus-registry-max-entries is nil
 
-       * gnus/nntp.el (nntp-coding-system-for-read): Set default value to
-       binary.
-       (nntp-coding-system-for-write): Likewise.
+2003-06-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Thu Nov 13 22:30:19 1997  seokchan lee  <chan@xfer.kren.nm.kr>
+       * qp.el (quoted-printable-decode-region): Don't error out on
+       malformed text.
 
-       * message.el (message-ignored-supersedes-headers): Ignore more
-       headers. 
+2003-06-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Thu Nov 13 22:28:13 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * rfc2047.el (rfc2047-encode-region): Don't error out on invalid
+       strings.
 
-       * message.el (message-separator-face): Lightened up.
-       (message-header-other-face): Ditto.
+2003-06-04  Jesper Harder  <harder@ifa.au.dk>
 
-Thu Nov 13 22:22:11 1997  jari aalto  <jari.aalto@poboxes.com>
+       * mml1991.el (mml1991-pgg-sign): Insert pgg output as unibyte.
+       From: Ivan Boldyrev <boldyrev+nospam@cgitftp.uiggm.nsc.ru> (tiny
+       change)
 
-       * nnmail.el (nnmail-process-mmdf-mail-format): Pop to buffer.
+2003-06-03  Dave Love  <fx@gnu.org>
 
-Thu Nov 13 22:09:39 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-soup.el (gnus-soup-send-packet): Don't use
+       message-functionp.
 
-       * gnus-start.el (gnus-start-draft-setup): Always create group.
+       * gnus.el (gnus-agent-cache): Doc fix.
+       (gnus-other-frame): Quote lambda used as hook.
 
-       * gnus-agent.el (gnus-agent-fetch-headers): Translate file chars.
+       * message.el: Doc fixes.
+       (message-functionp): Deleted.  Callers changed.
+       (message-fix-before-sending): Highlight with overlays.  Clarify
+       `illegible text' messages.
+       (rmail-enable-mime-composing, gnus-message-group-art): Defvar when
+       compiling.
+       (gnus-find-method-for-group, nnvirtual-find-group-art): Autoload.
 
-Thu Nov  6 20:43:05 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-06-03  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * gnus.el: Quassia Gnus v0.13 is released.
+       * nnmail.el (nnmail-split-fancy-match-partial-words): New user
+       option.
+       (nnmail-split-it): Obey it.  Don't let-bind regexp twice.
 
-Thu Nov  6 20:30:14 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-fetch-field): Mention narrow-to-headers
+       requirement.
 
-       * nnlistserv.el: New backend.
+2003-06-03  Jesper Harder  <harder@ifa.au.dk>
 
-Thu Nov  6 01:53:51 1997  Stefan Waldherr  <swa@cs.cmu.edu>
+       * gnus-xmas.el (gnus-xmas-create-image): Use
+       insert-file-contents-literally.  From: Eric Eide
+       <eeide@cs.utah.edu>
 
-       * nnweb.el (nnweb-dejanewsold-search): New function.
+2003-06-02  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Thu Nov  6 01:52:43 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-registry.el (gnus-registry-fetch-group): always return the
+       short name of the group
 
-       * gnus-topic.el (gnus-topic-change-level): Really delete multiple
-       instances. 
+2003-06-02  Jesper Harder  <harder@ifa.au.dk>
 
-Wed Nov  5 14:04:54 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-cus.el (defvar): Silence byte-compiler warnings.
 
-       * gnus-topic.el (gnus-topic-update-topic-line): Possibly fix nil
-       numbers. 
+       * gnus-sum.el (gnus-get-newsgroup-headers): Unfold headers.
 
-       * gnus-sum.el (gnus-summary-show-article): New command and
-       keystroke. 
+2003-05-31  Jesper Harder  <harder@ifa.au.dk>
 
-Tue Nov  4 06:29:58 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-art.el (article-unsplit-urls): Use gnus-treat-article
+       rather than gnus-display-mime-function.
 
-       * gnus-score.el (gnus-score-adaptive): Use the home score file.
+2003-05-30  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Sat Oct 25 05:52:22 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-registry.el (gnus-registry-use-long-group-names): new variable
+       (gnus-registry-add-group): use it
+       (gnus-registry-trim-articles-without-groups): new variable
+       (gnus-registry-delete-group): use it
+       (gnus-registry-unload-hook): uninstall all the hooks
 
-       * gnus-art.el (gnus-article-save): Hide headers in the right
-       buffer.
+       * spam.el (spam-install-hooks-function, spam-unload-hook): new
+       functions so users that load spam.el for customization don't get
+       all the hooks installed
+       (spam-install-hooks): new variable, set to t by default if user
+       has one of the spam-use-* variables set
 
-       * gnus-picon.el (gnus-picons-xbm-face): New face.
+       * spam-stat.el (spam-stat-install-hooks, spam-stat-unload-hook): new
+       functions so users that load spam-stat.el for customization don't get
+       all the hooks installed
 
-Sat Oct 25 00:39:42 1997  Lars Balker Rasmussen  <lbr@mjolner.dk>
+2003-05-30  Dave Love  <fx@gnu.org>
 
-       * gnus-art.el (gnus-article-fill-paragraph): New command and
-       keystroke. 
+       * rfc2047.el (rfc2047-decode): Don't use
+       mm-with-unibyte-current-buffer.
 
-1997-10-16  Colin Rafferty  <craffert@ml.com>
+       * qp.el (quoted-printable-decode-string): Use
+       mm-with-unibyte-buffer.
 
-       * message.el (message-make-fqdn): Made certain that user-mail is
-                 not nil.
+2003-05-29  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Sat Oct 25 00:18:32 1997  David S. Goldberg  <dsg@linus.mitre.org>
+       * gnus-registry.el (gnus-registry-save): allow forced saving even
+       when registry is not dirty.  Use gnus-registry-trim to shorten the
+       gnus-registry-alist.
+       (gnus-registry-max-entries): new variable
+       (gnus-registry-trim): new function, trim gnus-registry-alist to
+       size gnus-registry-max-entries, sorting by entry mtime so the
+       newest entries stick around
 
-       * gnus-art.el (article-hide-boring-headers): Use many-to.
+       * gnus-start.el (gnus-gnus-to-quick-newsrc-format): instead of
+       just one specific variable, allow a list of specific variables
 
-Fri Oct 24 23:48:39 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-28  Dave Love  <fx@gnu.org>
 
-       * gnus-picon.el (gnus-picons-display-pairs): Don't add two bars.
-       (gnus-picons-try-face): Set the foreground color on the bar.
-       (gnus-picons-group-exluded-groups): New variable.
-       (gnus-group-display-picons): Use it.
+       * rfc2047.el (rfc2047-encode-region): Skip ASCII at beginning and
+       end of region.
 
-Mon Oct 13 00:01:35 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-28  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-agent.el (gnus-agent-group-path): Translate file chars.
-       (gnus-agent-batch-fetch): New command.
-       (gnus-agent-fetch-group): Message.
+       * lpath.el: Add put-char-table and get-char-table.
 
-Sun Oct 12 23:54:55 1997  ISO-2022-JP  <ichikawa@hv.epson.co.jp>
+2003-05-28  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-agent.el (gnus-agent-article-file-coding-system): New
-       variable. 
+       * gnus-registry.el (gnus-registry-dirty): flag for modified registry
+       (gnus-registry-save, gnus-registry-read)
+       (gnus-registry-store-extra, gnus-registry-clear): use it (note
+       that gnus-registry-store-extra is invoked for all modifications to
+       set the mtime, so gnus-registry-dirty only needs to be set there)
 
-Sun Oct 12 16:46:11 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-23  Simon Josefsson  <jas@extundo.com>
 
-       * dgnushack.el (lpath): Reversed.
+       * mml1991.el (mml1991-pgg-sign): Use mml-sender instead of
+       message-sender.
 
-       * gnus-msg.el (gnus-summary-cancel-article): Use sym prefix.
+       * gnus-art.el (gnus-use-idna): Check if idna-program is installed.
 
-       * gnus-art.el (article-translate-characters): New function.
-       (article-treat-dumbquotes): New command and keystroke.
+       * message.el (message-use-idna): Ditto.
 
-Sun Oct  5 20:09:31 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-20  Dave Love  <fx@gnu.org>
 
-       * gnus-art.el (gnus-button-alist): No ' and " in News:.
+       * rfc2047.el (rfc2047-q-encoding-alist): Deleted.
+       (rfc2047-q-encode-region): Don't use it.
+       (rfc2047-encode-message-header) <(eq method 'mime)>: Bind
+       rfc2047-encoding-type to `mime'.
+       (rfc2047-encode-string, rfc2047-encode): Doc fix.
 
-       * gnus-msg.el (gnus-inews-insert-archive-gcc): Comp warn.
+2003-05-20  Jesper Harder  <harder@ifa.au.dk>
 
-Sat Oct  4 00:53:55 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * message.el (message-send-mail): Don't insert a courtesy copy
+       notice in base64 encoded messages.
 
-       * gnus.el: Quassia Gnus v0.12 is released.
+2003-05-16  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Oct  4 00:16:39 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el (gnus-summary-move-article): Don't copy expirable
+       marks if the destination group is not auto-expirable.
 
-       * gnus.el (gnus-plugged): Moved here.
+2003-05-14  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-       * nnmail.el (nnmail-delete-incoming): Changed default to nil.
+       * dgnushack.el (assq-delete-all): Removed the compiler macro.
 
-       * gnus-int.el (gnus-request-scan): Don't do anything if
-       unplugged. 
+2003-05-14  Kevin Greiner <kgreiner@xpediantsolutions.com>
 
-Fri Oct  3 21:09:19 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-agent.el (gnus-agentize): Updated documentation to match
+       usage.
+       (gnus-agent-expire-group-1): Do not skip over a group when the
+       force argument is set.
+       * gnus.el (gnus-agent): Updated documentation to reflect that
+       gnus-agent now defaults to t.
 
-       * gnus-art.el (gnus-ignored-headers): Doc fix.
+2003-05-14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-demon.el (gnus-demon-add-nntp-close-connection): New
-       function. 
-       (gnus-demon-nntp-close-connection): Ditto.
+       * gnus.el (gnus-version-number): Bump.
 
-       * nntp.el (nntp-last-command-time): New variable.
-       (nntp-retrieve-data): Use it.
+2003-05-14 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * message.el (message-news-p): Messages with Posted-To aren't
-       news. 
-       (message-mode): Heed message-yank-prefix when filling.
+       * gnus.el: Gnus v5.10.2 is released.
 
-       * nndraft.el (nndraft-request-restore-buffer): Remove Xrefs and
-       Lines headers.
+2003-05-14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * nntp.el (nntp-encode-text): Encode according to RFC977.
+       * mail-source.el (mail-source-delete-incoming): Changed to t.
 
-Wed Oct  1 18:27:26 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * rfc2047.el (rfc2047-syntax-table): Funcall.
 
-       * gnus-msg.el (gnus-inews-insert-archive-gcc): gcc-self didn't
-       work if `gnus-message-archive-method' was nil.
+       * lpath.el ((featurep 'xemacs)): Added set-char-table-range.
+       ((featurep 'xemacs)): No, don't.
 
-       * nnmail.el (nnmail-article-group): Allow \\1 substitution.
+       * rfc2047.el (rfc2047-encodable-p): Use the header charset.
 
-Sat Sep 27 12:57:44 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el (gnus-summary-reselect-current-group): Supply
+       leave-hidden.
 
-       * gnus-salt.el (gnus-pick-mouse-pick-region): Use it.
+2003-05-14  Jonathan Kamens  <jik@kamens.brookline.ma.us>
 
-       * gnus-xmas.el (gnus-xmas-window-edges): New function.
+       * gnus-sum.el (gnus-summary-exit): Added `leave-hidden'.  (Tiny
+       patch.)
 
-       * gnus-score.el (gnus-score-edit-current-scores): Don't select
-       window. 
+2003-05-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sat Sep 27 12:52:31 1997  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+       * gnus-registry.el (gnus-registry-store-extra-entry): Use
+       gnus-assq-delete-all.
 
-       * messcompat.el ((boundp 'mail-mode-hook)): Check.
+       * gnus-xmas.el (gnus-xmas-assq-delete-all): New function.
 
-Sat Sep 27 09:22:15 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-ignored-bounced-headers): Add Delivered-To.
 
-       * nndraft.el (nndraft-possibly-change-group): Always open server.
+       * gnus-sum.el (gnus-summary-find-next): Indent.
+       (gnus-summary-find-prev): Ditto.
+       (gnus-summary-catchup): Doc fix.
+       (gnus-summary-mark-current-read-and-unread-as-read): New function.
+       (gnus-summary-catchup): Really mark after point.
 
-       * gnus-sum.el (gnus-summary-pop-article): Force.
+       * gnus-util.el (gnus-user-date): Use %d instead of %m.
+       (gnus-user-date): Use floating point time so that we don't get
+       overflows.
 
-       * gnus-art.el (gnus-article-prepare): Push the article onto the
-       history. 
+       * gnus-sum.el (gnus-summary-local-variables): Clean up.
 
-       * gnus-sum.el (gnus-summary-pop-article): Pop to the right
-       article. 
+       * gnus-fun.el (gnus-display-x-face-in-from): Don't use centering
+       since none of the other image things do.
 
-       * gnus-demon.el (gnus-demon-scan-news): Save excursion.
+2003-05-13  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Sep 27 09:06:55 1997  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+       * dgnushack.el (assq-delete-all): New compiler macro for Emacs 20.
 
-       * gnus-cache.el (gnus-summary-limit-include-cached): New command
-       and keystroke.
+2003-05-12  Katsumi Yamaoka  <yamaoka@jpl.org>
 
-Sat Sep 27 06:45:58 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * lpath.el: Fbind find-coding-system.
 
-       * gnus-uu.el (gnus-uu-invert-processable): Make interactive.
+       * dgnushack.el (dgnushack-make-load): Remove redundant format call
+       in message.  Suggested by Yoichi NAKAYAMA <yoichi@geiin.org>.
+       * pop3.el (pop3-movemail): Ditto.
 
-Sat Sep 27 06:43:38 1997  Kim-Minh Kaplan  <kimminh.kaplan@utopia.eunet.fr>
+2003-05-12  Colin Marquardt <c.marquardt@alcatel.de>  (tiny change)
 
-       * gnus-picon.el: Doc fixes.
+       * gnus.el (gnus-agent): Docstring fix.
 
-1997-09-23  Hrvoje Niksic  <hniksic@srce.hr>
+2003-05-12  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus.el: Removed definition of `custom-face-lookup'.
+       * gnus-registry.el (gnus-registry-install): new variable
+       (gnus-registry-fetch-extra, gnus-registry-fetch-extra-entry)
+       (gnus-registry-store-extra-entry, gnus-registry-delete-group)
+       (gnus-registry-add-group): add a modification timestamp to each entry
+       (gnus-registry-install-hooks): new function
 
-Sat Sep 27 05:36:11 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-12  Kevin Greiner <kgreiner@xpediantsolutions.com>
 
-       * nndraft.el: Would block nnmh.
+       * gnus-agent.el (gnus-agent-cat-name): Eval macro while compiling.
+       (gnus-agent-cat-disable-undownloaded-faces): New function.
+       Accessor for new agent property
+       'agent-disable-undownloaded-faces'.
+       gnus-cus.el (gnus-agent-parameters): Added
+       agent-disable-undownloaded-faces and corrected documentation.
+       (gnus-agent-cat-prepare-category-field,
+       gnus-agent-customize-category): Changed to avoid creating free
+       references to each field's symbol.
+       gnus-sum.el (gnus-summary-use-undownloaded-faces): New local variable.
+       (gnus-select-newgroup): Initialize it.
+       (gnus-summary-highlight-line): Use it.
 
-       * gnus-sum.el (gnus-mark-article-as-unread): Don't allow marking
-       negative articles.
+2003-05-12  Dave Love  <fx@gnu.org>
 
-       * gnus-group.el (gnus-fetch-group): Use `gnus-no-server'.
+       * mm-util.el (mm-read-charset): Deleted.
+       (mm-coding-system-mime-charset): New.
+       (mm-read-coding-system, mm-mule-charset-to-mime-charset)
+       (mm-charset-to-coding-system, mm-mime-charset)
+       (mm-find-mime-charset-region): Use it.
+       (mm-default-multibyte-p): Fix non-mule case.
 
-       * gnus-agent.el (gnus-agent-with-fetch): Moved.
+       * rfc2047.el (rfc2047-point-at-bol, rfc2047-point-at-bol): Eval
+       and compile.
+       (rfc2047-syntax-table): Fix building table to work in Emacs 22.
+       (rfc2047-unfold-region): Delete unused var `leading'.
 
-       * gnus-sum.el (gnus-nov-read-integer): Really skip to next field.
+2003-05-12  Simon Josefsson  <jas@extundo.com>
 
-Sat Sep 27 04:32:45 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * pgg.el (pgg-temp-buffer-show-function): Reuse existing visible
+       output window if one is available.  Tiny patch from Ville Skytt\e,Ad\e(B
+       <scop@xemacs.org>.
 
-       * gnus.el: Quassia Gnus v0.11 is released.
+2003-05-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sat Sep 27 03:50:12 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-agent.el (gnus-agent-expire-unagentized-dirs): Added
+       space.
 
-       * message.el (message-send): Post without asking.
-       (message-mode): Modify paragraphs-start and paragraph-separate. 
-       (message-newline-and-reformat): New command and keystroke.
+2003-05-11  Jesper Harder  <harder@ifa.au.dk>
 
-Thu Sep 25 00:13:41 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-sum.el (gnus-summary-enter-digest-group): Don't do article
+       washing etc.
+       (gnus-handle-ephemeral-exit): Don't reload article after exiting.
 
-       * nnmail.el (nnmail-activate): Init server buffer.
+       * nndoc.el (nndoc-type-alist): `mime-digest' should be before
+       `mime-parts'.
 
-Wed Sep 24 04:11:59 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-10  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-draft.el (gnus-draft-setup): Inexplicable binding problem
-       worked around.
+       * gnus-cite.el (gnus-article-hide-citation-maybe): Make toggling
+       work.  Update mode-line.
 
-       * nnsoup.el (nnsoup-always-save): Renamed.
+2003-05-10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Wed Sep 24 04:11:02 1997  Nelson Jose dos Santos Ferreira  <Nelson.Ferreira@inesc.pt>
+       * gnus.el (gnus-logo-color-alist): Added no colours.
 
-       * nnsoup.el (nnsoup-commit-reply-now): New variable.
-       (nnsoup-store-reply): Use it.
+2003-05-09  Dave Love  <fx@gnu.org>
 
-Wed Sep 24 02:30:44 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * utf7.el (mm-util): Require.
+       (utf7-direct-encoding-chars, utf7-imap-direct-encoding-chars):
+       Defconst, not defvar.
+       (utf7-utf-16-coding-system): New.
+       (utf7-encode-internal): Hoist concat out of loop.
+       (utf7-fragment-encode): Use mm-with-unibyte-current-buffer.
+       (utf7-get-u16char-converter) [utf7-utf-16-coding-system]: New
+       case.
+       (utf7-latin1-u16-char-converter): Encode the region.
+       (utf7-u16-latin1-char-converter): Decode the region.
+       (utf7-encode, utf7-decode): Fix multibyteness.
 
-       * gnus-ems.el (gnus-deactivate-mark): New alias.
+       * mm-bodies.el (mm-body-7-or-8): Don't special-case mule.
+       (mm-encode-body): Use mm-read-coding-system, not mm-read-charset.
+       (mm-uu-yenc-decode-function): Defvar when compiling.
+       (mm-encode-body, mm-decode-body): Doc fix.
 
-Tue Sep 23 07:56:07 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-09  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus.el: Win-away!
+       * gnus-registry.el (gnus-registry-unregistered-group-regex):
+       removed in favor of the group/topic/global variables
+       (gnus-registry-register-message-ids): fixed test to omit
+       gnus-registry-unregistered-group-regex
 
-       * gnus-msg.el (gnus-setup-message): Don't trust make-symbol.
+       * gnus.el (gnus-variable-list): removed gnus-registry-alist and
+       gnus-registry-headers-alist from the list
+       (gnus-registry-headers-alist): removed
+       (registry-ignore): new parameter, with accompanying
+       gnus-registry-ignored-groups global variable
 
-Tue Sep 23 07:45:11 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus-start.el (gnus-clear-system): no need to clear the
+       registry, we can do it ourselves
+       (gnus-gnus-to-quick-newsrc-format): extra parameters so it can be
+       used by gnus-registry.el
 
-       * gnus.el: Quassia Gnus v0.10 is released.
+       * gnus-registry.el (gnus-registry-cache-file): new file variable
+       (gnus-registry-cache-read, gnus-registry-cache-save): new
+       functions
+       (gnus-registry-cache-whitespace): new function.  From Dan
+       Christensen <jdc@chow.mat.jhu.edu>
+       (gnus-registry-save, gnus-registry-read): use the new
+       gnus-registry-cache-{read|save} functions, and change the name
+       from gnus-registry-translate-{from|to}-alist
+       (gnus-registry-clear): fixed so it doesn't refer to old function name
 
-Tue Sep 23 01:41:04 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-09  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-sum.el (gnus-read-all-headers): New function.
-       (gnus-select-newsgroup): Use it.
-       (gnus-summary-refer-thread): Ditto.
-       (gnus-refer-thread-limit): New variable.
-       (gnus-summary-refer-thread): Use it.
+       * gnus-picon.el (gnus-picon-transform-address): Parse the encoded
+       address.
 
-       * gnus-nocem.el (gnus-nocem-message-wanted-p): New function.
-       (gnus-nocem-check-article): Use it.
-       (gnus-nocem-issuers): Dox ofx.
+2003-05-08  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * dgnushack.el (dgnushack-compile): Check for cus-edit.
+       * gnus-start.el (gnus-clear-system): added gnus-registry-alist to
+       the list of cleared variables
 
-       * message.el (message-included-forward-headers): Include Mime
-       headers. 
-       (message-send): Allow posting without confirming from Agent.
+       * gnus-registry.el (gnus-registry-split-fancy-with-parent):
+       nnmail-split-fancy-with-parent-ignore-groups can be a single regex
+       in addition to a list of regexes.
 
-Mon Sep 22 05:43:14 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * spam.el (spam-use-regex-headers): docstring fix.  From Niklas
+       Morberg <niklas.morberg@axis.com>
 
-       * dgnushack.el (byte-compile-warnings): Don't warn about obsolete
-       variables. 
+2003-05-08  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * gnus-sum.el (gnus-summary-refer-thread): New command and
-       keystroke. 
-       (gnus-summary-limit-include-thread): New command and keystroke. 
-       (gnus-summary-articles-in-thread): New function.
-       (gnus-articles-in-thread): Renamed.
+       * gnus-sum.el (gnus-summary-next-page): Mention
+       `gnus-article-skip-boring' in docstring.
 
-Sun Sep 21 23:54:50 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-05-08  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus.el: Quassia Gnus v0.9 is released.
+       * rfc2231.el (rfc2231-parse-string): "=" should have whitespace
+       syntax here.
 
-Sun Sep 21 23:38:46 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * ietf-drums.el (ietf-drums-syntax-table): "=" should not have
+       whitespace syntax class when parsing email addresses.
 
-       * gnus.el (gnus-splash-face): ForestGreen everywhere.
+       * message.el (message-forward-subject-name-subject): Don't use
+       mail-decode-encoded-word-string before parsing from.
 
-       * gnus-sum.el (gnus-simplify-subject-fully): Use new variable.
-       (gnus-general-simplify-subject): Ditto.
+2003-05-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Sun Sep 21 23:34:13 1997  Kurt Swanson  <kurt@dna.lth.se>
+       * message.el (message-setup-1): Setup alternative email before
+       generate-headers.
 
-       * gnus-sum.el (gnus-simplify-subject-functions): New variable.
-       (gnus-simplify-whitespace): New function.
+       (message-forward-subject-name-subject): Fix the case when the
+       field "from" doesn't exist.
 
-       * gnus-util.el (gnus-map-function): New function.
+2003-05-07  Dave Love  <fx@gnu.org>
 
-Sun Sep 21 23:22:04 1997  Michelangelo Grigni  <mic@mathcs.emory.edu>
+       * rfc2047.el (rfc2047-encode-region): Skip \n as whitespace.
 
-       * gnus-score.el (gnus-score-regexp-bad-p): New function.
+       * mm-util.el (mm-find-mime-charset-region): Expurgate utf-16 from
+       possible values.
 
-Sun Sep 21 00:14:40 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-07  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-score.el (gnus-summary-lower-score): Use sym pref.
-       (gnus-summary-increase-score): Use it.
+       * message.el (message-kill-to-signature): Fix.
 
-       * gnus.el (gnus-current-prefix-symbol): New variable.
-       (gnus-current-prefix-symbols): New variable.
+2003-05-06  Jesper Harder  <harder@ifa.au.dk>
 
-       * gnus-score.el (gnus-summary-increase-score): Take symbolic
-       prefix. 
+       * gnus-sum.el (gnus-auto-goto-ignores): Docstring fix.
 
-       * gnus.el (gnus-interactive): Removed.
-       (gnus-interactive): Renamed from gnus-interactive-1.
-       (gnus-symbolic-argument): New command.
+       * gnus-art.el (gnus-mime-display-multipart-as-mixed)
+       (gnus-mime-display-multipart-related-as-mixed)
+       (gnus-button-mid-or-mail-heuristic-alist): do.
 
-       * gnus-draft.el (gnus-draft-send-message): Disable message
-       checks. 
-       (gnus-draft-send): Ditto.
-       (gnus-draft-setup): Don't save buffer.
+2003-05-05  Dave Love  <fx@gnu.org>
 
-       * dgnushack.el (dgnushack-compile): Warn people about Custom.
+       * mm-util.el (mm-default-multibyte-p): New.
+       (mm-coding-system-p): Maybe use find-coding-systems.
 
-       * gnus-group.el (gnus-group-iterate): Use gensymmed variables.
+2003-05-04  Dave Love  <fx@gnu.org>
 
-       * pop3.el (pop3-md5): `with-temp-buffer' doesn't exist in Emacs
-       19.34. 
+       * rfc2047.el (with-syntax-table): Define if necessary.
+       (rfc2047-syntax-table): Fix last change for XEmacs.
+       (rfc2047-parse-and-decode): Revert last change.
 
-       * nneething.el (nneething-directory): Defvarred.
+2003-05-03  Jesper Harder  <harder@ifa.au.dk>
 
-       * message.el: Autoloaded nndraft things.
-       (message-set-auto-save-file-name): Use it.
+       * gnus.el: Don't test for `mm-guess-mime-charset'.
 
-       * dgnushack.el (dgnushack-compile): Warn about things.
+       * mm-util.el (mm-guess-mime-charset): Remove.  Not used any more.
 
-       * gnus-art.el: Autoload w3-region.
+       * gnus.el (gnus-default-charset): Set default value to
+       `undecided'.
 
-       * gnus-vm.el (gnus-summary-save-in-vm): Simplified.
+       * gnus-art.el (article-decode-charset): Don't supply 4th arg to
+       mm-decode-body.
 
-       * gnus.el: Changed `compiled-function-p' to `byte-code-function-p'
-       throughout.
+       * mm-bodies.el (mm-decode-coding-region-safely): Remove.
+       (mm-decode-body): Don't use mm-decode-coding-region-safely.
 
-       * gnus-sum.el (gnus-summary-edit-article): Supply additional
-       param. 
+2003-05-03  Vasily Korytov <deskpot@despammed.com>  (tiny change)
 
-       * gnus-group.el (gnus-group-iterate): Undo bogus change.
+       * gnus-util.el (gnus-multiple-choice): Add ", ?".
 
-       * gnus-agent.el (gnus-agentize): Just call gnus-open-agent
-       directly. 
+2003-05-03  Dave Love  <fx@gnu.org>
 
-       * gnus.el (gnus-interactive): New macro.
-       (gnus-interactive-1): New function.
+       * rfc2047.el (rfc2047-syntax-table): Don't call make-char-table
+       with 2 args.
+       (rfc2047-decode-string): Don't set the buffer multibyte before
+       calling buffer-string.
 
-       * gnus-sum.el (gnus-fetch-old-headers): Allow `invisible'.
-       (gnus-cut-thread): Use it.
-       (gnus-cut-threads): Ditto.
-       (gnus-summary-initial-limit): Ditto.
-       (gnus-summary-limit-children): Ditto.
+       * mm-encode.el (mm-long-lines-p): Autoload.
+       (mm-encode-content-transfer-encoding): Doc fix.  Don't make buffer
+       unibyte.  Signal error on unknown encoding.
+       (mm-encode-buffer, mm-qp-or-base64): Doc fix.
 
-       * gnus-art.el (gnus-article-edit-done): Accept a prefix arg.
-       (gnus-boring-article-headers): Allow `long-to' param.
-       (article-hide-boring-headers): Use it.
+       * rfc2047.el (rfc2047-point-at-bol, rfc2047-point-at-eol): New.
+       Callers of gnus- versions changed to use them.
+       (rfc2047-header-encoding-alist): Add `address-mime' part.  Doc
+       fixes.
+       (rfc2047-encoding-type): New.
+       (rfc2047-encode-message-header): Use mm-charset-to-coding-system.
+       Don't include header name field in encoding.  Add `address-mime'
+       case and bind rfc2047-encoding-type for `mime' case.
+       (rfc2047-encodable-p): Deleted.
+       (rfc2047-syntax-table): New.
+       (rfc2047-encode-region, rfc2047-encode): Rewritten to take account
+       of rfc2047 rules with respect to rfc2822 tokens and to do encoding
+       in place rather than by passing strings.
+       (rfc2047-encode-string): Doc fix.
+       (rfc2047-q-encode-region): Don't use
+       mm-with-unibyte-current-buffer.
+       (rfc2047-encoded-word-regexp): eval-and-compile.
+       (rfc2047-decode-region): Avoid concatenation in loop.
+       (rfc2047-parse-and-decode): Remove useless disjunction.
 
-       * gnus-sum.el (gnus-summary-edit-article-done): Accept a
-       no-highlight param.
+2003-05-02  Dave Love  <fx@gnu.org>
 
-       * nntp.el (nntp-rlogin-program): New variable.
-       (nntp-open-rlogin): Use it.
+       * rfc2047.el (rfc2047-q-encode-region, rfc2047-decode): Use
+       mm-with-unibyte-current-buffer.
+       (ietf-drums, gnus-util): don't require.
 
-       * nnvirtual.el (nnvirtual-request-post): New function.
+       * sieve.el (sieve-manage-mode-menu): Define before use.
 
-       * gnus-msg.el (gnus-message-group-art): New variable.
+       * mml-smime.el (message-narrow-to-headers): Autoload.
 
-       * gnus-draft.el (gnus-draft-setup): Don't use message-setup.
+       * mm-util.el (mm-coding-system-p): Don't override nil from
+       coding-system-p.
+       (mm-mule4-p, mm-disable-multibyte-mule4)
+       (mm-with-unibyte-current-buffer-mule4): Deleted.
+       (mm-multibyte-p): Use defun, not defalias.
+       (mm-make-temp-file): Moved to group at top of file.
+       (mm-point-at-eol, mm-point-at-bol): New.
 
-       * nndraft.el (nndraft): Allow editing articles.
+       * gnus-cite.el (gnus-art): Require.
 
-       * gnus-ems.el (gnus-x-splash): Ditto.
+       * gnus-ems.el (gnus-get-buffer-create)
+       (nnheader-find-etc-directory, message-text-with-property):
+       Autoload.
+       (gnus-tmp-unread, gnus-tmp-replied, gnus-tmp-score-char)
+       (gnus-tmp-indentation, gnus-tmp-opening-bracket, gnus-tmp-lines)
+       (gnus-tmp-name, gnus-tmp-closing-bracket, gnus-tmp-subject-or-nil)
+       (gnus-check-before-posting): Only defvar when compiling.
 
-       * gnus.el (gnus-splash-face): Darker face.
+       * gnus-int.el (gnus-agent-expire): Autoload, don't defun.
 
-       * gnus-draft.el (gnus-draft-setup): Clobbered variables.
+       * gnus-util.el (rmail-default-rmail-file, mm-text-coding-system):
+       Defvar when compiling.
+       (gnus-output-to-rmail): Require mm-util.
 
-Sat Sep 20 23:23:49 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * mail-source.el (mail-source-callback): Use mm-make-temp-file.
+       (mail-source-make-complex-temp-name): Deleted.
 
-       * gnus.el: Quassia Gnus v0.8 is released.
+       * message.el (message-use-idna): Use mm-coding-system-p.
+       (message-tokenize-header, message-make-organization)
+       (message-make-from):  Use with-temp-buffer.
+       (message-set-work-buffer): Deleted.
+       (message-fill-paragraph): Use `if' not `and' for compiler warning.
+       (message-check-news-header-syntax): Remove useless lambda.
+       (message-forward-make-body): Use mm-disable-multibyte,
+       mm-with-unibyte-current-buffer, mm-enable-multibyte.
+       (message-replace-chars-in-string): Deleted.
 
-Sat Sep 20 20:41:16 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * mm-extern.el (mm-extern-local-file): Use mm-disable-multibyte.
+       (mm-extern-url): Use mm-with-unibyte-current-buffer,
+       mm-disable-multibyte.
+       (mm-extern-anon-ftp): Use mm-disable-multibyte.
 
-       * gnus-start.el (gnus-setup-news-hook): New hook.
+       * mml1991.el (mml1991-mailcrypt-encrypt, mml1991-gpg-encrypt): Use
+       mm-with-unibyte-current-buffer.
 
-       * gnus-agent.el (gnus-agentize): Really set up queue group.
-       (gnus-open-agent): Setup queue here.
+       * mml2015.el (mml): Require.
+       (mml2015-mailcrypt-encrypt, mml2015-gpg-encrypt): Use
+       mm-with-unibyte-current-buffer.
 
-Sat Sep 20 20:23:07 1997  Matt Simmons  <simmonmt@acm.org>
+       * nnheader.el (gnus-util): Require.
 
-       * message.el (message-set-auto-save-file-name): Make things work
-       without drafts.
+       * nntp.el (format-spec, format-spec-make, open-tls-stream):
+       Autoload.
 
-Sat Sep 20 18:32:02 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * rfc2231.el (mail-header-remove-comments, mm-encode-body)
+       (mail-header-remove-whitespace): Autoload.
 
-       * nnmh.el (nnmh-request-list-1): Check for links to ".".
+       * sieve-manage.el (starttls-negotiate): Autoload.
 
-       * nndraft.el (nndraft-possibly-change-group): New function.
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-agent.el (gnus-agent-queue-setup): New function.
+       * nnrss.el (nnrss-find-rss-via-syndic8): Indent.
 
-Thu Sep 18 04:54:59 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-05-01  Mark A. Hershberger  <mah@everybody.org>
 
-       * gnus.el: Quassia Gnus v0.7 is released.
+       * nnrss.el (nnrss-find-rss-via-syndic8): Don't error out.
 
-Thu Sep 18 03:33:54 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-msg.el (gnus-setup-message): Slap a progn around forms.
+       * gnus.el (gnus-version-number): Bump.
 
-       * nndraft.el (nndraft-articles): Make sure directory exists. 
+2003-05-01  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * message.el (message-mode): Don't delete article.
+       * spam-report.el (spam-report-gmane-regex): docstring fix.  From
+       Jon Ericson <Jon.Ericson@jpl.nasa.gov> (tiny change)
 
-       * nnmh.el (nnmh-request-accept-article): Don't save when
-       noinsert. 
+       * gnus.el (gnus-install-group-spam-parameters): docstring fix.
+       From Jon Ericson <Jon.Ericson@jpl.nasa.gov> (tiny change)
 
-Wed Sep 17 03:37:59 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-registry.el (gnus-registry-fetch-extra)
+       (gnus-registry-store-extra, gnus-registry-group-count): new functions
+       (gnus-registry-fetch-group, gnus-registry-delete-group)
+       (gnus-registry-add-group): changed to work with extra data element
+       if present
 
-       * nndraft.el (nndraft-directory): Changed defaults.
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus-agent.el (gnus-agent-fetch-session): Bind command method.
+       * gnus.el: Gnus v5.10.1 is released.
 
-Wed Sep 17 03:28:36 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus.el: Quassia Gnus v0.6 is released.
+       * gnus.el: Oort Gnus v0.24 is released.
 
-1997-08-17  SL Baur  <steve@altair.xemacs.org>
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * dgnushack.el (dgnushack-compile): Ignore .el files beginning
-       with an `=' character.
+       * dgnushack.el (when): Check whether defadvice is fbound.
 
-Wed Sep 17 02:30:04 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-01  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus-sum.el (gnus-build-sparse-threads): Allow display of looped
-       References.
+       * gnus-registry.el (gnus-registry-unregistered-group-regex): new variable
+       (gnus-registry-register-message-ids): use it
 
-       * gnus-agent.el (gnus-agent-fetch-group-1): Separated out into
-       function. 
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * message.el (message-delete-not-region): New command and
-       keystroke. 
+       * gnus.el (gnus-version-number): Bump.
 
-Tue Sep 16 00:58:26 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.el: Update copyright for several files.
 
-       * nndraft.el (nndraft-directory): Changed value.
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * message.el (message-kill-buffer): Disassociate draft.
-       (message-mode): Use kill hook to disassociate.
-       (message-disassociate-draft): Double-check.
+       * gnus.el: Oort Gnus v0.23 is released.
 
-       * gnus-agent.el (gnus-agentize): Don't set twice.
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-art.el (gnus-article-prepare): Go to the right line before
-       marking. 
+       * spam-stat.el (spam-stat-test-directory): Compare against zero.
 
-       * gnus-start.el: Renamed the drafts group.
+2003-05-01  Trey Jackson <tjackson@ichips.intel.com>  (tiny change)
 
-       * gnus-agent.el (gnus-agent-lib-file): Changed name of directory.
+       * spam-stat.el (spam-stat-test-directory): Skip 0 length files.
 
-       * gnus-draft.el (gnus-draft-mode): Simplify.
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Tue Sep 16 00:18:11 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * message.el (message-forward-subject-name-subject): Decode
+       string when forwarding.
 
-       * gnus.el: Quassia Gnus v0.5 is released.
+2003-05-01  Oystein Viggen  <oysteivi@tihlde.org>
 
-Mon Sep 15 00:53:50 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * dgnushack.el (when): Add defadvice.
 
-       * gnus-sum.el (gnus-alter-header-function): New variable.
-       (gnus-nov-parse-line): Use it.
-       (gnus-get-newsgroup-headers): Ditto.
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-draft.el (gnus-group-send-drafts): Don't send when
-       unplugged. 
+       * gnus.el (gnus-version-number): Bump.
 
-       * gnus-sum.el (gnus-summary-read-group): Don't show-all when
-       skipping groups.
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus-start.el (gnus-start-draft-setup): Changed name.
+       * gnus.el: Oort Gnus v0.22 is released.
 
-Mon Sep 15 00:40:09 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus.el: Quassia Gnus v0.4 is released.
+       * gnus.el: Oort Gnus v0.21 is released.
 
-Mon Sep 15 00:19:07 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus-sum.el (gnus-summary-goto-article): Accept Message-ID's.
+       * gnus.el (gnus-version-number): Bump.
 
-Sun Sep 14 21:41:35 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-05-01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
 
-       * gnus-sum.el (gnus-group-make-articles-read): No params.
+       * gnus.el: Oort Gnus v0.20 is released.
 
-       * nndraft.el (nndraft-status-string): Fix.
+2003-05-01  Vasily Korytov  <deskpot@despammed.com>
 
-       * gnus-draft.el (gnus-group-send-drafts): New command.
+       * gnus-dired.el (gnus-dired-mode-map): Move to C-c C-l.
 
-       * gnus-sum.el (gnus-compute-read-articles): Separated.
-       (gnus-update-read-articles): Allow computation.
+2003-04-30  Mark A. Hershberger  <mah@everybody.org>
 
-       * nndraft.el (nndraft-articles): New function.
+       * mm-url.el (mm-url-insert-file-contents): set url-current-object
+       in the case where mm-url-use-external is set.
 
-       * message.el (message-send): Disabled test.
+       * nnrss.el (nnrss-request-article): Change the messages created to
+       multipart/alternative.  Hopefully fixes a problem interaction with
+       w3m.
+       (nnrss-find-rss-via-syndic8): Better handling if xml-rpc.el isn't
+       around.
 
-Sun Sep 14 21:17:34 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.el: Quassia Gnus v0.3 is released.
+       * message.el (message-check-news-header-syntax): Alter "posting"
+       message.
 
-Sun Sep 14 01:51:45 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * nnrss.el (nnrss-node-text): Don't use char classes.
 
-       * gnus-agent.el (gnus-agent-short-article): New variables.
+2003-05-01  David Z. Maze  <dmaze@mit.edu>
 
-       * message.el (message-set-auto-save-file-name): Use drafts.
+       * nnrss.el (nnrss-find-rss-via-syndic8): Have an `error' branch
+       in condition-case.
 
-       * nndraft.el (nndraft-request-expire-articles): Use it.
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * nnmh.el (nnmh-deletable-article-p): Change.
-       (nnmh-allow-delete-final): New variable.
+       * message.el (message-required-headers): Remove In-Reply-To.
 
-       * gnus-msg.el (gnus-summary-send-draft): Removed.
+       * gnus-int.el (gnus-open-server): Revert changes.
 
-       * gnus.el (gnus-article-mark-lists): Save unsendable marks.
+2003-04-30  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
 
-       * gnus-sum.el (gnus-newsgroup-unsendable): New variable.
+       * gnus-int.el (gnus-open-server): Try to open unagentized servers
+       even when unplugged.
 
-       * gnus-draft.el: New file.
+2003-04-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus-sum.el (gnus-unsendable-mark): New variable.
+       * gnus-art.el (gnus-button-prefer-mid-or-mail): Fixed typo in
+       doc-string.
 
-       * nndraft.el (nndraft-execute-nnmh-command): Cleanup.
+2003-05-01  Steve Youngs  <youngs@xemacs.org>
 
-       * message.el (message-send-news): Use `gnus-request-post'.
+       * lpath.el: Add a section for non-Mule XEmacsen.
+       fbind `find-charset-string' and `coding-system-base' in that
+       section.
 
-       * gnus-agent.el (gnus-agentize): New command.
+       * gnus-util.el (gnus-completing-read-maybe-default): New.
+       (gnus-completing-read): Use it.
 
-       * gnus-bcklg.el (gnus-backlog-remove-article): Remove the ident
-       from the list.
+       * mm-view.el (mm-view-pkcs7-decrypt): Ditto.
 
-Sun Sep 14 00:26:47 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+       * gnus-art.el (gnus-read-string): New.
+       (gnus-summary-pipe-to-muttprint): Use it.
 
-       * gnus.el: Quassia Gnus v0.2 is released.
+       * gnus-xmas.el (gnus-xmas-open-network-stream): New.
 
-Sun Sep 14 00:24:52 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * dns.el (dns-make-network-process): Use it.
 
-       * gnus-score.el (gnus-score-headers): Make sure the summary buffer
-       exists.
+       Take care of some differences between XEmacs 21.1 and newer
+       versions of XEmacs.
+
+2003-04-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-registry-split-fancy-with-parent): added
+       diagnostic message
+       (gnus-registry-grep-in-list): don't run when word is nil
+       (gnus-registry-fetch-message-id-fast): new function
+       (gnus-registry-delete-group, gnus-registry-add-group): make sure
+       the id and group are not nil
+       (gnus-registry-register-message-ids): new function
+       (gnus-register-action): optimized logical flow
+       (gnus-summary-prepare-hook): added gnus-registry-register-message-ids
+
+2003-04-30  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * gnus-delay.el (gnus-delay-article): Call
+       `gnus-agent-queue-setup' to create the delay group.
+
+       * gnus-agent.el (gnus-agent-queue-setup): Support optional arg
+       for the (queue) group name.
+
+2003-04-30  Simon Josefsson  <jas@extundo.com>
+
+       * mm-util.el (mm-charset-to-coding-system): Use user specified
+       charset unless coding-system-get is fboundp.
+
+2003-04-30  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-cat-defaccessor, gnus-agent-cat-name):
+       Wrapped in eval-when-compile.
+       (gnus-agent-mode): Bind gnus-agent-go-online to nil as you
+       shouldn't be asked twice to go online with each server.
+       (gnus-agent-get-undownloaded-list, gnus-agent-fetch-articles,
+       gnus-agent-crosspost, gnus-agent-flush-cache,
+       gnus-agent-fetch-session, gnus-agent-unread-articles,
+       gnus-agent-uncached-articles, gnus-agent-regenerate-group,
+       gnus-agent-group-covered-p): Expanded pop macros used for
+       effect. Avoids compilation warning in emacs 21.3.
+
+       * gnus-int.el (gnus-open-server): Restructured to only open
+       nnagent when gnus-plugged is nil.
+
+2003-04-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Fbind string-to-multibyte.
+
+2003-04-30  Steve Youngs  <youngs@xemacs.org>
+
+       * dgnushack.el: Add some missing autoloads for XEmacs 21.1.
+
+2003-04-29  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-registry-fetch-group): faster
+       (gnus-registry-delete-group): new function
+       (gnus-registry-add-group): new function
+       (gnus-register-spool-action): use it
+       (gnus-register-action): use it
+       (gnus-registry-translate-from-alist)
+       (gnus-registry-translate-to-alist): remove the headers registry
+       for now
+
+2003-04-29  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-alist): Fixed CTAN regexp.
+
+2003-04-29  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam-report.el (spam-report-gmane): gnus-summary-article-number
+       is not necessary, just use the function parameter
+
+2003-04-29  Karl Pflysterer  <sigurd@12move.de>
+
+       * spam-stat.el (spam-stat-save): No longer font-locks the file
+       when saving
+
+2003-04-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el: Bind mail-header-separator when compiling (XEmacs
+       provides it in mail-lib/auto-autoloads.el).
+
+2003-04-29  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-pgg-sign): Use mml-sender instead of
+       message-sender.
+
+       * mml.el (mml-generate-mime-1): Set mml-sender too.
+
+2003-04-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-display-while-building): Docstring fix.
+
+       * mm-url.el (mm-url-use-external): do.
+
+2003-04-29  Simon Josefsson  <jas@extundo.com>
+
+       * canlock.el (mail-fetch-field): Autoload it (fix xemacs compile
+       warnings).
+
+       * sieve-mode.el (c-mode): Ditto.
+
+       * pgg.el (run-at-time): Ditto.
+
+       * mm-url.el (require): Require timer when compiling for
+       with-timeout macro (fix xemacs compile warnings).
+
+2003-04-28  Dave Love  <fx@gnu.org>
+
+       * gnus-util.el (nnheader): Don't require.
+       (Nnheader-narrow-to-headers, nnheader-replace-chars-in-string):
+       Autoload.
+
+       * spam.el: Require cl when compiling.
+
+       * dns.el: Require cl when compiling.
+
+2003-04-28  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-goto-next-page)
+       (gnus-article-goto-prev-page): Revert 2003-02-12 change to make
+       gnus-pick-mode work.
+
+2003-04-28  Steve Youngs  <youngs@xemacs.org>
+
+       * Makefile.in (FLAGS): Use @FLAGS@.
+
+2003-04-27  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-mime-display-multipart-as-mixed)
+       (gnus-mime-display-multipart-alternative-as-mixed)
+       (gnus-mime-display-multipart-related-as-mixed): Added doc-strings,
+       allow customization.
+
+2003-04-27  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * dgnushack.el (dgnushack-compile-verbosely): New function.  Not
+       currently called (See source for explanation).
+
+2003-04-27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-catchup): Don't mark ticked messages.
+       (gnus-summary-mark-read-and-unread-as-read): Take an optional
+       mark.
+
+       * gnus.el (gnus-version-number): Bump.
+
+2003-04-27 06:47:31 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.19 is released.
+
+2003-04-27  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-registry.el (gnus-register-spool-action): Replaced literal
+       carriage-return character with its escape sequence.
+
+2003-04-27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-catchup-from-here): Doc fix.
+
+       * nnrss.el (nnrss-node-text): Use only one
+       gnus-replace-in-string.
+
+       * gnus.el: Remove gnus-functionp throughout.
+
+       * gnus-util.el (gnus-functionp): Removed.
+
+       * gnus-msg.el (gnus-summary-wide-reply-with-original): Doc fix.
+
+       * message.el (message-required-headers): Add In-Reply-To.
+
+2003-04-27  Marshall T. Vandegrift  <vandem2@rpi.edu>
+
+       * gnus-fun.el (gnus-face-from-file): Bind coding-system-for-read
+       to binary.
+
+2003-04-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * mml.el (mml-preview): do.
+
+       * message.el (message-mode): do.
+
+       * gnus-undo.el (gnus-undo-mode): do.
+
+       * gnus-topic.el (gnus-topic-mode): do.
+
+       * gnus-sum.el (gnus-summary-mode, gnus-summary-edit-article): do.
+
+       * gnus-msg.el (gnus-setup-message)
+       (gnus-inews-add-send-actions, gnus-configure-posting-styles): do.
+
+       * gnus-gl.el (gnus-grouplens-mode): do.
+
+       * gnus-art.el (gnus-mime-save-part-and-strip)
+       (gnus-mime-delete-part): Use it.
+
+       * gnus-util.el (gnus-make-local-hook): New function.
+
+2003-04-25  Simon Josefsson  <jas@extundo.com>
+
+       * nnrss.el (nnrss-node-text): Don't use a star.
+       (nnrss-node-text): Use g-r-i-s, not g-r-r-i-s which doesn't exist.
+
+2003-04-24  Dave Love  <fx@gnu.org>
+
+       * mm-encode.el (mm-long-lines-p): Autoload.
+       (mm-encode-content-transfer-encoding): Don't try to make buffer
+       unibyte before decoding.  Don't ignore errors for base64 encoding.
+
+       * qp.el (quoted-printable-decode-region): Use mm-insert-byte.
+       Signal error on malformed text, as for base64.
+       (quoted-printable-encode-region): DTRT in Emacs 22.
+
+       * mm-util.el (mm-make-temp-file, mm-insert-byte): New.
+       (mm-auto-save-coding-system): Consider utf-8-emacs.
+       (mm-mime-mule-charset-alist, mm-mule-charset-to-mime-charset)
+       (mm-charset-to-coding-system, mm-mime-charset)
+       (mm-find-mime-charset-region): Check for :mime-charset coding
+       systems property.
+
+       * mml-sec.el (mml2015, mml1991): Don't require.
+       (mml2015-sign, mml2015-encrypt, mml1991-sign, mml1991-encrypt)
+       (message-goto-body, mml-insert-tag): Autoload.
+
+       * mm-decode.el (mm-tmp-directory): Re-write to help avoid warnings.
+
+       * gnus-start.el (message-make-date): Autoload rather than
+       requiring message.
+
+       * gnus-group.el (gnus-group-name-charset-group-alist): Use
+       mm-coding-system-p.
+       (gnus-cache-active-altered): Defvar when compiling.
+       (gnus-group-delete-group): Re-write to help avoid warnings.
+
+       * gnus-art.el (gnus-use-idna): Use mm-coding-system-p.
+
+       * pgg.el: Split eval-when-compile forms.
+
+2003-04-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-group.el (gnus-large-ephemeral-newsgroup)
+       (gnus-fetch-old-ephemeral-headers): News variables.
+       (gnus-group-read-ephemeral-group): Use them.
+
+2003-04-24  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.el (sieve-upload): Don't use replace-regexp-in-string.
+
+       * nnrss.el (nnrss-node-text): Ditto.
+
+2003-04-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-inews-do-gcc): Make sure the obsolete variable
+       gnus-inews-mark-gcc-as-read exists.
+
+2003-04-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sieve.el (gnus-sieve-generate): Rewrite regexp search so it
+       doesn't exceed the regexp stack space.
+
+2003-04-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-msg.el (gnus-inews-mark-gcc-as-read): Don't defvar it.
+
+       * gnus-art.el (gnus-article-hide-pgp-hook): do.
+
+2003-04-23  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * mml.el (mml-preview): Bind `=', RET, and mouse-2.
+
+2003-04-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-decode-body): Don't override supplied charset.
+
+2003-04-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (merge, copy-list): Remove compiler macros.
+       (butlast): Add a compiler macro.
+
+2003-04-22  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-util.el (gnus-merge): Added "type" argument to match CL
+       merge and gnus-sum.el's expectations.
+
+2003-04-21  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-url-regexp): Added nntp.
+
+       * message.el (message-generate-headers-first): Default to
+       '(references).
+
+       * gnus-art.el (gnus-mime-delete-part): Require confirmation.
+
+2003-04-21  Jesper Harder  <harder@ifa.au.dk>
+
+       * smime.el (smime-decrypt-region): Insert From header.
+
+2003-04-21  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * gnus-fun.el (gnus-face-from-file, gnus-convert-png-to-face):
+       Max length of header is 726, not 740.  From Gaute B Strokkenes
+       <gs234@cam.ac.uk>.
+
+2003-04-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * nndb.el, mml1991.el: Fix license template.
+
+2003-04-20  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-articles): Don't download body unless
+       required.
+
+       * imap.el (imap-gssapi-open, imap-ssl-open): Erase buffer before
+       starting process, like imap-kerberos4-open does.
+
+       * mml-smime.el, rfc1843.el, dig.el, smime.el, uudecode.el: Fix
+       license template.
+
+       * mml-sec.el: Fix license template.
+
+       * gnus-sieve.el, sieve.el, sieve-manage.el, sieve-mode.el: Fix
+       license template.
+
+       * pgg-def.el, pgg.el, pgg-gpg.el, pgg-parse.el, pgg-pgp5.el,
+       pgg-pgp.el: Fix license template.
+
+2003-04-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-delete-article): Improve docstring.
+
+2003-04-19  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-move-spam-nonspam-groups-only): dumb typo fix
+
+2003-04-18  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-split): allow a particular check as a parameter,
+       e.g. (: spam-split 'spam-use-bogofilter)
+       (spam-mark-only-unseen-as-spam): new parameter, see doc
+       (spam-mark-junk-as-spam-routine): use
+       spam-mark-only-unseen-as-spam, simplify routine to take advantage
+       of gnus-newsgroup-unread as well as gnus-newsgroup-unseen
+
+2003-04-17  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.el (gnus-group-short-name, gnus-group-prefixed-p): new functions
+       (gnus-group-guess-full-name): don't prefix the group twice
+
+       * nnmail.el (nnmail-split-fancy-with-parent): docstring fix
+
+       * gnus-registry.el (gnus-registry-clear)
+       (gnus-registry-fetch-group, gnus-registry-grep-in-list)
+       (gnus-registry-split-fancy-with-parent): new functions
+       (gnus-register-spool-action, gnus-register-action): simplified the format
+       (gnus-registry): new customization group
+       (gnus-registry-unfollowed-groups): new variable
+
+2003-04-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-button-alist): Add nntp: urls.
+       (gnus-header-button-alist): Ditto.
+
+2003-04-17  Dave Love  <fx@gnu.org>
+
+       * gnus-util.el (gnus-string-equal): Revert last change.
+
+2003-04-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-browse-make-menu-bar): Fix typo.
+
+2003-04-17  Mike Woolley  <mike@ariel.co.uk>
+
+       * gnus-sum.el (gnus-sum-thread-tree-false-root): New variable.
+
+2003-04-15  Michael Shields  <shields@msrl.com>
+
+       * gnus-art.el (article-hide-boring-headers): Hide Reply-To: if
+       the broken-reply-to group parameter is set.  Idea from Vasily
+       Korytov <deskpot@myrealbox.com>.
+
+2003-04-17  Steve Youngs  <youngs@xemacs.org>
+
+       * dgnushack.el: 'setenv' is in env.el for XEmacsen <= 21.4, but in
+       process.el in XEmacsen >= 21.5.
+
+2003-04-17  Steve Youngs  <youngs@xemacs.org>
+
+       * dgnushack.el: Add a whole swag of autoloads and defaliases to
+       satisfy the byte-compiler when building with XEmacs.
+
+       * lpath.el (maybe-bind): Add 'w3-meta-content-type-charset-regexp'
+       and 'w3-meta-charset-content-type-regexp' in XEmacs.  The upstream
+       W3 doesn't have these.
+
+       * mailcap.el: Maybe require 'lpr in XEmacs.
+
+2003-04-16  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-pgg-sign): Bind pgg-default-user-id to MML
+       sender tag, if available.
+
+2003-04-16  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-registry.el (gnus-register-action)
+       (gnus-register-spool-action, hashtable-to-alist)
+       (gnus-registry-translate-from-alist, alist-to-hashtable)
+       (gnus-registry-translate-to-alist, gnus-registry-headers-hashtb):
+       new variables and function fixes
+
+       * gnus.el (gnus-registry-headers-alist): new variable to hold
+       article header data
+       (gnus-variable-list): save gnus-registry-headers-alist
+
+       * spam-report.el (Module): new module for spam reporting
+
+       * gnus.el (spam-process): added
+       gnus-group-spam-exit-processor-report-gmane to the list of choices
+       (gnus-install-group-spam-parameters): defined new spam exit processor
+
+       * spam.el (autoload): autoload spam-report-gmane when needed
+       (spam-report-gmane-register-routine): glue for spam-report.el
+       (spam-group-spam-processor-report-gmane-p): glue for the
+       gnus-group-spam-exit-processor-report-gmane spam processor
+       (spam-summary-prepare-exit): check the report-gmane spam processor
+       and run spam-report-gmane-register-routine if it's active
+
+       From John Wiegley <johnw@gnu.org>
+
+       * spam.el (spam-bogofilter-score): check bogofilter headers before
+       checking bogofilter itself
+
+2003-04-16  Dave Love  <fx@gnu.org>
+
+       * gnus-agent.el: Wrap defsetf in eval-when-compile.
+       (gnus-agent-cat-defaccessor): Don't use gensym.
+
+       * mml1991.el: Require cl, mm-util when compiling.
+       (quoted-printable-decode-region, quoted-printable-encode-region):
+       Autoload.
+
+       * pgg.el: Require cl when compiling.
+
+       * nnmail.el (gnus): Require.
+
+       * gnus-util.el: Move provide to end.
+       (gnus-string-equal): Maybe use compare-strings.
+       (gnus-merge): New.
+
+       * gnus-sum.el (gnus-summary-prepare-threads): Don't use copy-list.
+       (gnus-summary-insert-articles): Use gnus-merge.
+
+       * gnus-fun.el: Require cl and mm-util when compiling.
+
+       * gnus-diary.el (gnus-diary-delay-format-french)
+       (gnus-diary-delay-format-english): Don't use setf with nthcdr.
+
+       * nndiary.el (nndiary-compute-reminders): Don't use setf with
+       nthcdr.
+
+2003-04-16  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-make-cat): Added optional parameter to
+       specify a predicate other than false.
+       (gnus-category-read): Use the new feature to create a 'default'
+       category with a 'short' predicate.
+
+2003-04-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-unique-id): Comment change.
+
+       * gnus-art.el (gnus-article-next-page-1): New function.
+       (gnus-article-next-page): Use it.
+
+2003-04-15  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-split): added save-restriction to save-excursion
+
+2003-04-15  Reiner Steib  <Reiner.Steib@gmx.de>
+       From Julien Avarre <julien@avarre.com>
+
+       * gnus-fun.el: Fixed autoload cookie.
+
+2003-04-15  Paul Jarc  <prj@po.cwru.edu>
+       From Remi Letot  <remi.letot@easynet.be>
+
+       * nnmaildir.el (nnmaildir-request-scan): Use gnus-remove-if
+       instead of remove-if.
+
+2003-04-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-summary-news-other-window): Use delq and
+       copy-sequence instead of remove which is a cl run-time function in
+       Emacs 20.
+
+2003-04-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-msg.el (gnus-summary-news-other-window): Make a buffer
+       local copy of gnus-discouraged-post-methods with the current
+       method removed.
+
+2003-04-14  Simon Josefsson  <jas@extundo.com>
+
+       * mailcap.el (mailcap-mime-data): Add application/pgp-keys.
+
+2003-04-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * mm-util.el (mm-sort-coding-systems-predicate): Convert elements
+       of `mm-coding-system-priorities' to base coding system.
+
+       * gnus-sum.el: Added coding cookie ("middle dot" in
+       gnus-summary-morse-message).
+
+2003-04-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (article-fill-long-lines)
+       (article-verify-x-pgp-sig, article-decode-group-name)
+       (gnus-mime-button-menu): Split >80 character lines.
+
+2003-04-13  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-local-variables): Use defvar since
+       we're let-binding it.
+
+       * nnmbox.el (nnmbox-mbox-buffer): It's not a constant.
+
+2003-04-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-hide-headers): Don't do intangible.
+
+       * gnus.el (gnus-group-prefixed-name): Comment out the test for
+       colon.
+
+       * gnus-srvr.el (gnus-browse-read-group): Don't give the real name
+       to the ephemeral entry, but the prefixed name.
+
+       * gnus.el (gnus-group-prefixed-name): Clean up.
+
+2003-04-13  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-group-pathname): Bind
+       gnus-command-method so that gnus-agent-directory will always
+       return a valid directory.
+       * gnus-cache.el (gnus-cache-enter-article): Remove article from
+       gnus-newsgroup-undownloaded so that the summary will display the
+       article as downloaded.
+       (gnus-cache-remove-article): If the article isn't in the agent,
+       remove it from gnus-newsgroup-undownloaded so that the summary
+       will display the article as undownloaded.
+
+2003-04-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bump.
+
+2003-04-13 01:12:01 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.18 is released.
+
+2003-04-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el (gnus-draft-send): Add message-hidden-headers.
+
+2003-04-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-next-page): Use
+       gnus-article-over-scroll.
+       (gnus-article-over-scroll): New variable.
+
+       * message.el (message-newline-and-reformat): Place a boundary
+       before filling.
+       (message-make-forward-subject-function): Changed default to
+       message-forward-subject-name-subject.
+       (message-forward-subject-name-subject): New function.
+
+       * nnimap.el (nnimap-split-fancy): Ditto.
+
+       * gnus-sum.el (gnus-summary-line-message-size): Ditto.
+
+       * gnus-cus.el (gnus-group-parameters): Removed "which see".
+
+       * mml.el (mml-minibuffer-read-file): Bind
+       completion-ignored-extensions to nil.
+
+       * message.el (message-fix-before-sending): Comment fix.
+       (message-fix-before-sending): Make hidden headers visible.
+       (message-hide-headers): Bind after-change-functions to nil.
+       (message-forbidden-properties): Put invisible and intangible
+       back.
+       (message-strip-forbidden-properties): Ignore message-hidden text.
+
+       * gnus-msg.el: Hide headers.
+
+       * message.el (message-hidden-headers): New variable.
+       (message-hide-headers): New function.
+       (message-hide-header-p): New function.
+       (message-hide-header-p): Change logic.
+       (message-forbidden-properties): Remove intangible nil invisible
+       nil.
+       (message-hide-headers): Narrow to headers.
+
+       * lpath.el (featurep): Bind Info-directory, Info-menu.
+
+2003-04-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-body-charset-encoding-alist): UTF-16 *must* be
+       encoded.
+       (mm-encode-body): Don't corrupt UTF-16.
+       (mm-body-encoding): Pay attention to mm-body-charset-encoding-alist.
+
+2003-04-10  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Articles in
+       the CACHE are now detected and handled the same as an article
+       downloaded into the agent.
+       (gnus-agent-group-path): Modified to match nnmail-group-pathname
+       so that the agent front-end and back-end (nnagent) always use the
+       same directory.
+       (gnus-agent-group-pathname): New function. Wrapper for
+       nnmail-group-pathname.
+       (gnus-agent-expire-unagentized-dirs): New variable.  May be
+       customized to disable gnus-agent-expire-unagentized-dirs.
+       (gnus-agent-expire-unagentized-dirs): Expand gnus-agent-directory
+       as the directories in gnus-agent-expire-current-dirs were
+       expanded.
+
+2003-04-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Disable "Encrypt
+       body" entry in read only groups.
+
+2003-04-09  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Disable "Import file"
+       and "Create article" items in non-editable groups.
+
+2003-04-09  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-write-active): Added option of
+       replacing, rather than updating, the agent's active file.  Do NOT
+       use the fully qualified group name as gnus-active-to-gnus-format
+       blindly prefixes group names with server names.
+       (gnus-agent-save-group-info): Merge BOTH min/max of current active
+       range, was just merging min, with specified active range.
+       (gnus-agent-expire): Save agent's active ranges after
+       expiring all groups.
+       (gnus-agent-expire-group-1): Update min of agent's active range to
+       min article currently fetched.
+       (gnus-agent-expire-unagentized-dirs): Avoid asking to delete the
+       same ancestor multiple times.
+
+       * gnus-async.el (gnus-asynchronous): Moved defcustom of
+       gnus-asynchronous away from defgroup of gnus-asynchronous.  This
+       seems to fix an intermittant error in which loading gnus-async
+       fails to define gnus-asynchronous (the variable).
+
+       * gnus-sum.el: Concur with Steve Young, 5th argument to 'load' is
+       non-essential.  Removed on all platforms.
+       (gnus-select-newsgroup): When the agent is active, expand the
+       group's active range to include fetched articles that are no
+       longer in the server's active range.
+
+       * gnus-util.el (gnus-with-output-to-file): Removed all of the
+       print-* bindings as they should be handled by the function doing
+       the printing.
+
+2003-04-09  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-uu.el (mm-uu-copy-to-buffer): buffer-file-coding-system
+       might be unbound in non-MULE XEmacsen.
+
+2003-04-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-uu.el (mm-uu-diff-groups-regexp, mm-uu-type-alist)
+       (mm-uu-diff-extract, mm-uu-diff-test): New functionality:
+       recognize diffs.
+
+       * mm-bodies.el (mm-decode-body): Use the supplied charset
+       unconditionally if `code-pages' hasn't been loaded.
+
+2003-04-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (article-verify-x-pgp-sig): Don't use
+       `insert-buffer', the docstring says "This function is meant for
+       the user to run interactively.  Don't call it from programs!"
+
+       * mm-extern.el (mm-extern-mail-server): do.
+
+       * mml1991.el (mml1991-mailcrypt-sign, mml1991-mailcrypt-sign)
+       (mml1991-gpg-sign, mml1991-gpg-encrypt, mml1991-pgg-sign)
+       (mml1991-pgg-encrypt): do.
+
+       * pgg.el (pgg-decrypt-region): do.
+
+       * mm-view.el (mm-view-pkcs7-decrypt): do.
+
+       * mml-smime.el (mml-smime-verify): do.
+
+       * mml.el (mml-insert-mime, mml-preview): do.
+
+       * mml2015.el (mml2015-gpg-decrypt-1, mml2015-gpg-sign)
+       (mml2015-gpg-encrypt, mml2015-pgg-clear-decrypt)
+       (mml2015-pgg-encrypt): do.
+
+2003-04-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-bodies.el (mm-decode-body): Silence XEmacs when compiling.
+
+2003-04-06  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-uu.el (mm-uu-copy-to-buffer): Copy
+       `buffer-file-coding-system' to the new buffer.
+       (mm-uu-pgp-signed-extract-1): Don't copy
+       `buffer-file-coding-system' here.
+
+       * mm-bodies.el (mm-decode-body): last-coding-system-used doesn't
+       exist in XEmacs.
+       (mm-decode-body): Add missing quote.
+
+       * mm-uu.el (mm-uu-pgp-signed-extract-1): Set
+       buffer-file-coding-system.
+
+       * mm-bodies.el (mm-decode-body): Set buffer-file-coding-system to
+       last-coding-system-used.
+
+       * mml2015.el (mml2015-pgg-clear-verify): Encode the text
+       according to buffer-file-coding-system.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Revert previous change.
+
+       * pgg-pgp.el (pgg-pgp-process-region, pgg-pgp-verify-region)
+       (pgg-pgp-snarf-keys-region): do.
+
+       * pgg-pgp5.el (pgg-pgp5-verify-region)
+       (pgg-pgp5-snarf-keys-region, pgg-pgp5-process-region): do.
+
+       * pgg.el (pgg-make-temp-file, pgg-temporary-file-directory): do.
+
+2003-04-05  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-split): (save-excursion) around (widen)
+       (spam-ham-move-routine): Use spam-group-ham-mark-p, not
+       spam-group-spam-mark-p (from Michael Shields <shields@msrl.com>)
+
+2003-04-05  Steve Youngs  <youngs@xemacs.org>
+
+       * gnus-sum.el: XEmacs doesn't support the 5th arg to 'load', so
+       don't use it when loading gnus-sum.el if we're in XEmacs.
+
+2003-04-05  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bound
+       print-escape-nonascii to fix more characters in compiled format
+       specs.
+
+2003-04-05  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-audio.el (gnus-audio-au-player, gnus-audio-wav-player):
+       Fix customization type.
+
+2003-04-04  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bound
+       print-quoted, print-readably, print-escape-multibyte, and
+       print-level to match original behavior of gnus-prin1.  This should
+       repair the format of .newsrc.eld when using compiled format specs.
+
+2003-04-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-group.el (tool-bar-map): defvar it.
+
+       * gnus-art.el (tool-bar-map): do.
+
+       * gnus-sum.el (tool-bar-map): do.
+
+2003-04-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * earcon.el (earcon-regexp-alist): catmeow is a wav file.
+
+2003-04-03  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-ctan-directory-regexp): Changed meaning
+       and value.
+       (gnus-button-alist): Use it.
+
+2003-04-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * pgg-gpg.el (pgg-gpg-process-region): do.
+
+       * pgg-pgp.el (pgg-pgp-process-region, pgg-pgp-verify-region)
+       (pgg-pgp-snarf-keys-region): do.
+
+       * pgg-pgp5.el (pgg-pgp5-verify-region)
+       (pgg-pgp5-snarf-keys-region, pgg-pgp5-process-region): Use it.
+
+       * pgg.el (pgg-make-temp-file): New function. `make-temp-name' is
+       unsafe.
+       (pgg-temporary-file-directory): Remove.
+
+2003-04-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Fbind Info-directory and Info-menu.
+
+2003-04-02  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-util.el (gnus-message): Added doc-string.
+
+       * gnus-score.el (gnus-score-find-trace): Changed behavior of `q'.
+       (gnus-score-edit-file-at-point): Goto first match when using `e'.
+
+2003-04-01  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-ctan-directory-regexp): New variable.
+       (gnus-button-alist): Use it.  Changed CTAN and "setq" entries.
+
+2003-04-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-via-rlogin-command-switches): Doc fix.
+       (nntp-open-via-rlogin-and-telnet): Disable the telnet linemode.
+
+2003-03-31  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bound
+       print-escape-newlines to print escape sequences rather than
+       literal newline characters.
+
+2003-03-31  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-valid-fqdn-regexp): Use
+       `message-valid-fqdn-regexp' for initialization.
+       (gnus-button-handle-info-url): Renamed and extended version of
+       `gnus-button-handle-info'.
+       (gnus-button-message-level): Renamed from `gnus-button-mail-level'
+       (gnus-button-handle-symbol, gnus-button-handle-library)
+       (gnus-button-handle-info-keystrokes): New functions.
+       (gnus-button-browse-level): New variable.
+       (gnus-button-alist): Use them.  Added levels.
+       (gnus-header-button-alist): Added levels.
+
+2003-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bump.
+
+2003-03-31 20:08:19 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.17 is released.
+
+2003-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-unload): Removed.
+
+       * pop3.el (pop3-read-response): Use
+       nnheader-accept-process-output.
+       (pop3-retr): Ditto.
+
+       * mm-view.el (mm-text-html-renderer-alist): Add -nolist to Lynx.
+       (mm-text-html-washer-alist): Ditto.
+
+2003-03-31  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-gssapi-program): Also try GNU SASL.
+       (imap-gssapi-open): Accept GNU SASL greeting.
+       (imap-read-timeout): New.
+       (imap-wait-for-tag): Use it.
+
+2003-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nntp.el (nntp-accept-process-output): Use new function.
+
+       * nnheader.el (nnheader-read-timeout): New variable.
+       (nnheader-accept-process-output): New function.
+
+       * nntp.el (nntp-read-timeout): Removed.
+
+       * gnus-sum.el (gnus-summary-prepare-threads): Add comment.
+
+2003-03-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-cache.el (gnus-cache-braid-nov): Revoke last change.
+
+2003-03-30  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-idna-inside-rhs-p): Narrow to header before
+       searching.
+
+       * gnus-art.el (article-decode-idna-rhs): More restrictive regexp.
+
+2003-03-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-process-mmdf-mail-format): Indent.
+
+2003-03-28  Vasily Korytov  <deskpot@myrealbox.com>
+
+       * message.el (message-make-in-reply-to): Use
+       mail-extract-address-components to determine sender's
+       name/address.
+
+2003-03-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nndoc.el (nndoc-type-alist): Move mime-parts further ahead.
+
+       * gnus-registry.el (gnus-registry-translate-to-alist): Make a
+       valid lambda.
+       (gnus-registry-translate-from-alist): Ditto.
+
+       * gnus-start.el (gnus-gnus-to-quick-newsrc-format): Bind
+       print-length to nil.
+
+       * gnus-sum.el (gnus-summary-highlight-line-0): Indent.
+
+       * gnus-fun.el (gnus-fun-ppm-change-string): New function.
+       (gnus-grab-cam-face): Use it.
+
+2003-03-28  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-set-mark)
+       (nnmaildir-close-group): Allow each mark directory in a group to
+       have its own inode for mark files, to accommodate AFS.
+
+2003-03-28  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-start.el (gnus-read-newsrc-el-hook): new hook called by
+       gnus-read-newsrc-el-file
+       (gnus-read-newsrc-el-file): call the gnus-read-newsrc-el-hook
+
+       * gnus-registry.el (gnus-registry-translate-to-alist)
+       (gnus-registry-translate-from-alist, alist-to-hashtable)
+       (hashtable-to-alist): new functions
+       (gnus-register-spool-action): add a spool item to the registry
+
+       * gnus.el (gnus-variable-list): added gnus-registry-alist to the
+       list of saved variables
+       (gnus-registry-alist): new variable
+
+2003-03-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (article-decode-group-name): Be correct instead of
+       smart.
+
+2003-03-27  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lpath.el: Bind url-current-object for Emacs; bind
+       gnus-agent-expire-current-dirs for XEmacs; fbind open-ssl-stream
+       for both Emacsen.
+
+2003-03-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-article-loose-mime)
+       (gnus-article-emulate-mime): Move to gnus-article-mime customize
+       group.
+
+       * gnus-msg.el (gnus-mailing-list-groups): Fix customize type and
+       doc string.
+
+2003-03-26  Kevin Ryde <user42@zip.com.au>
+
+       * gnus-sum.el (gnus-summary-find-for-reselect): Renamed from
+       gnus-summary-find-uncancelled, skip temporary articles inserted by
+       "refer" functions.
+
+2003-03-26  Vasily Korytov  <deskpot@myrealbox.com>
+
+       * smiley.el (smiley-buffer): New function.
+
+2003-03-26  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Replaced
+       gnus-summary-update-line (which updated the article's face) with
+       gnus-summary-update-download-mark (which updates the article's
+       face by calling gnus-summary-update-line AND updates the download
+       mark to show that the article was fetched).
+
+2003-03-23  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-expire-unagentized-dirs): Provides
+       option of deleting agent directories for groups/servers that are
+       not currently agentized.
+       (gnus-agent-expire): Use gnus-agent-expire-unagentized-dirs.
+
+       * gnus-int.el (gnus-open-server): Report backend errors in
+       condition handler.
+
+2003-03-23  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-idna-to-ascii-rhs-1): Don't continue outside
+       header.
+
+       * rfc2047.el (rfc2047-header-encoding-alist): Make Followup-To
+       same as Newsgroups.
+
+       * nntp.el (nntp-open-connection-function): Mention
+       nntp-open-tls-stream.
+       (nntp-open-tls-stream): New function.
+
+       * tls.el: New file.
+
+       * nnimap.el (nnimap-server-port, nnimap-stream): Say TLS/SSL
+       instead of SSL.
+       (nnimap-stream): Add other streams, link to imap variables.
+       (nnimap-authenticator): Add other authenticator, link to imap
+       variables.
+
+       * imap.el: Autoload open-tls-stream.
+       (imap-streams): Add tls in front of ssl.
+       (imap-stream-alist): Add tls.
+       (imap-default-tls-port): New variable.
+       (imap-tls-p, imap-tls-open): New functions.
+
+2003-03-22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el (mm-url-insert-file-contents): parse url only if
+       results is a list.
+
+2003-03-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-imap): Revert.
+
+2003-03-22  Svend Tollak Munkejord  <stm@bacchus.pvv.org>
+
+       * deuglify.el (gnus-outlook-repair-attribution-outlook): Use a
+       less strict regexp.
+
+2003-03-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-imap): Use buffer name for
+       more imap function.
+
+2003-03-21  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (article-decode-group-name): Replace Newsgroups and
+       Followup-To data inline.
+
+2003-03-21  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-treat-display-xface): Don't enable if
+       icontopbm isn't available.
+
+2003-03-21  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-int.el (gnus-open-server): Catch errors in backend's
+       open-server method.  Returns nil rather than crashing startup.
+
+       * gnus-sum.el (eval-when-compile): Modified to resolve
+       compile-time warnings.
+
+       * gnus-uu.el (gnus-uu-mark-series): Added informative msg.
+       Reports length of series so that the user can compare N with a
+       subject that should, if the entire series is present, contain
+       '(.../N)'.
+       (gnus-uu-delete-work-dir): Avoid hanging when O/S forbids deletion
+       of temp file (Win-XP may leave the temp file locked when the
+       uudecode process fails).
+
+2003-03-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-split-line): Ignore error.
+
+       * lpath.el (split-line): Avoid split-line warning message.
+
+2003-03-20  Kim F. Storm  <storm@cua.dk>
+
+       * message.el (message-split-line): New function.
+       (message-mode-map): Remap split-line to message-split-line.
+
+2003-03-20  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * message.el (message-make-overlay): Defalias it to make-overlay.
+       (message-delete-overlay): Defalias it to delete-overlay.
+       (message-overlay-put): Defalias it to overlay-put.
+       (message-idna-to-ascii-rhs-1): Use them.
+
+       * messagexmas.el (message-xmas-redefine): Defalias some overlay
+       functions to extent functions.
+
+2003-03-20  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-check-news-header-syntax): Fixed regexp.
+
+2003-03-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2231.el (rfc2231-decode-encoded-string): Downcase charset.
+
+       * mm-url.el (mm-url-insert): Move url-current-object stuff into
+       mm-url-insert-file-contents.
+
+       * nnrss.el (nnrss-fetch): Fetch the local stuff.
+       (nnrss-check-group): Use it.
+
+2003-03-20 Mark A. Hershberger  <mah@everybody.org>
+
+       * nnrss.el: Primitive XML Name-space support.  This means that RSS
+       feeds like Kevin Burton's[1] can now be read in Gnus.
+
+       Implemented support for Mark Pilgrim's RSS Autodiscovery.[2] This
+       means that if you want to read the RSS feed for example.com, all
+       you have to do is hit "G R http://www.example.com/ RET" and
+       nnrss.el will find and the feed listed on the site or (if you have
+       loaded xml-rpc.el) look it up on syndic8.com.
+
+       Marked the message as HTML (by adding a Content-Type header) so
+       that Gnus will render it as html if the user wants that.
+
+       Implemented the ability to save nnrss-group-alist so that any new
+       feeds the you subscribe to will be found the next time you start
+       up.
+
+       Implemented support for RSS 2.0 elements (author, pubDate).
+
+       Prefer for <content:encoded> over <description> where both
+       elements exist.
+
+       * mm-url.el (mm-url-insert): Set url-current-object.
+
+       * gnus-group.el (gnus-group-make-rss-group): New function.
+
+2003-03-20  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * message.el (message-idna-to-ascii-rhs-1): Don't use replace-*
+       for highlight overlays.
+
+2003-03-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-cache.el (gnus-cache-braid-nov): Test if a line looks like
+       a NOV.
+
+2003-03-20  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-use-idna): Disable if UTF-8 unavailable.
+       (message-idna-to-ascii-rhs): Use it.
+
+       * gnus-art.el (gnus-use-idna): Disable if UTF-8 unavailable.
+
+2003-03-19  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-group-ham-mark-p, spam-group-spam-mark-p)
+       (spam-group-ham-marks, spam-group-spam-marks): new functions
+       (spam-spam-marks, spam-ham-marks): removed in favor of the
+       spam-marks and ham-marks parameters
+       (spam-generic-register-routine, spam-ham-move-routine): use the
+       new spam-group-{spam,ham}-mark-p functions
+
+       * gnus.el (spam-marks, ham-marks): new group parameters with
+       default values same as the old spam-spam-marks and spam-ham-marks
+
+2003-03-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-article-decode-hook): Add IDNA.
+       (gnus-use-idna): New variable.
+       (article-decode-idna-rhs): New function.
+
+       * message.el (message-use-idna): New variable.
+       (message-mode-field-menu): Add entry for IDNA.
+       (message-idna-inside-rhs-p, message-idna-to-ascii-rhs-1)
+       (message-idna-to-ascii-rhs): New function.
+       (message-generate-headers): Invoke IDNA code.
+
+2003-03-19  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--system-name): New function.
+       (nnmaildir-request-accept-article): Use it.
+
+2003-03-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-util.el (gnus-byte-compile): Make it work silently as the
+       gnus-compile function does.
+
+       * gnus-sum.el (gnus-summary-highlight-line-0): Revoke the last
+       bogus change.
+
+2003-03-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-util.el (mm-mule-charset-to-mime-charset): Test if
+       sort-coding-systems is defined.
+
+2003-03-18  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-open-server, nnmaildir-request-scan)
+       (nnmaildir-request-create-group, nnmaildir-request-delete-group):
+       Replace create-directory with target-prefix.
+
+2003-03-18  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-decode-coding-region-safely): Don't use
+       find-charset-string which is slooow in XEmacs.
+
+2003-03-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-summary-highlight-line-0): Silence the byte-
+       compiler under XEmacs.
+
+2003-03-18  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-treat-highlight-signature): Make the default
+       work for multipart/signed where the message text isn't `last'.
+
+2003-03-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.el (mm-setup-w3m): Set w3m-display-inline-images to
+       the value of mm-inline-text-html-with-images.
+       (mm-inline-text-html-render-with-w3m): Don't bind
+       w3m-display-inline-images.
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Don't bind
+       w3m-display-inline-images.
+
+       * lpath.el: Bind w3m-display-inline-images; bind mm-w3m-mode-map
+       regardless of an Emacs flavor.
+
+2003-03-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bump.
+
+2003-03-18 00:38:22 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.16 is released.
+
+2003-03-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * lpath.el (featurep): Bind mm-w3m-mode-map.
+
+2003-03-17  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmail.el (nnmail-cache-primary-mail-backend): Not all
+       'respool-able backends define a global nnchoke-get-new-mail
+       variable.
+
+2003-03-17  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-mime-delete-part): New function.
+       (gnus-mime-action-alist, gnus-mime-button-commands): Use it.
+
+2003-03-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-check-news-header-syntax): Don't push
+       groups twice onto list of unknown groups.
+
+       * nndoc.el (nndoc-type-alist): Move exim-bounce a bit further
+       back.
+
+       * nnheader.el (nnheader-find-etc-directory): Doc fix.
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Don't restore window
+       config unless the summary buffer exists.
+
+       * gnus-sum.el (gnus-summary-next-group): Semi-exit group first to
+       that target group is computed correctly when articles are marked
+       as read by Xref handling.
+
+       * mail-source.el (mail-source-fetch-imap): Pass buffer-name to
+       imap-open.
+
+       * message.el (message-send-mail): Add courtesy string to Bcc's,
+       too.
+
+       * gnus-cite.el (gnus-cited-line-p): New function.
+
+2003-03-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-decode-body): Add new optional parameter,
+       force, to use the supplied charset unconditionally.
+
+       * gnus-art.el (article-decode-charset): Use it.
+
+2003-03-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-decode-coding-region-safely): New function.
+       (mm-decode-body): Use it.
+
+       * rfc2047.el (rfc2047-decode-region): do.
+       (rfc2047-decode-string): Guess coding system if the default is
+       invalid.
+
+2003-03-12  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-update-info): Pretend missing
+       articles are marked 'read, so we get correct article counts.
+
+2003-03-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-insert-mime-button): Exclude a newline from
+       the button.
+       (gnus-insert-prev-page-button): Ditto.
+       (gnus-insert-next-page-button): Ditto.
+       (gnus-insert-mime-security-button): Ditto.
+
+       * mm-view.el (mm-inline-image-emacs): Open the bottom of an image
+       one line.  Suggested by Greg Klanderman <gak@klanderman.net>.
+       (mm-inline-image-xemacs): Ditto.
+
+2003-03-12  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--parse-filename, nnmaildir--sort-files,
+       nnmaildir--scan, nnmaildir-request-accept-article): Changes for
+       the recent filename uniqueness discussion.
+
+2003-03-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.el (mm-inline-image-emacs): Make it delete an excessive
+       newline next time.
+       (mm-inline-image-xemacs): Ditto.
+
+2003-03-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-agent.el (gnus-agent-synchronize-flags-server): Don't use
+       kill-line.
+
+2003-03-09  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-msg.el (gnus-inews-insert-archive-gcc): Don't use
+       kill-line.
+
+2003-03-09  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetched-hook): New variable.  Just
+       fixing the code to match the documentation.
+       (gnus-agent-fetch-selected-article): Replaced
+       gnus-summary-update-article-line with gnus-summary-update-line as
+       the former did not correctly recalculate the thread indentation.
+       (gnus-agent-find-parameter): The agent-predicate, if not found
+       anywhere else, defaults to the value of gnus-agent-predicate.
+       (gnus-agent-fetch-session): Fixed typo; now executes
+       gnus-agent-fetched-hook rather than the undocumented
+       gnus-agent-fetch-hook.
+       (gnus-agent-fetch-group-1): Removed part of 2003-03-06 fix.  The
+       default agent predicate is now provided by
+       gnus-agent-find-parameter.
+       (gnus-agent-message): New macro.  This macro avoids potentially
+       costly parameter evaluation when the message's level is too high
+       to display.
+       (gnus-agent-expire-group-1): Disabled undo tracking in temp
+       overview buffer. Uses new gnus-agent-message macro to reduce
+       overhead of optional messages. Reversed message levels to
+       emphasize percent completion messages.  Detailed messages of
+       little use except when debugging code.
+
+2003-03-08  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-move-routine): use
+       spam-mark-ham-unread-before-move-from-spam-group
+       (spam-mark-ham-unread-before-move-from-spam-group): new variable
+
+2003-03-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: load nnimap.el when compiling
+       (spam-setup-widening): use
+       nnimap-split-download-body-default instead of
+       nnimap-split-download-body which is a user-customizable variable
+
+2003-03-07  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-download-body-default): New, holds
+       default for n-s-d-b.
+       (nnimap-split-download-body): Add new setting (symbol default),
+       which uses contents of n-s-d-b-d, and made it the default.
+
+2003-03-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-hashcash): new variable
+       (spam-list-of-checks): added spam-use-hashcash with associated
+       spam-check-hashcash
+       (spam-check-hashcash): new function, installed iff hashcash.el is
+       loaded
+       (spam-setup-widening): don't use (return)
+
+2003-03-06  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Added default
+       predicate of `false' to avoid an error when a group defines no
+       predicate. Fixed typo that disabled agent scoring (i.e. the
+       low/high predicates should now work).
+
+2003-03-06  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: add spam-maybe-spam-stat-load to
+       gnus-get-top-new-news-hook, remove it from gnus-get-new-news-hook
+       (spam-bogofilter-register-with-bogofilter): use
+       spam-bogofilter-spam-switch and spam-bogofilter-ham-switch
+       (spam-bogofilter-spam-switch, spam-bogofilter-ham-switch): new
+       custom variables to replace "-s" and "-n"
+
+       * gnus-group.el (gnus-group-get-new-news): call the new
+       gnus-get-top-new-news-hook hook
+
+       * gnus-start.el (gnus-get-top-new-news-hook): new hook, run ONLY
+       by gnus-get-new-news, NOT by gnus-group-get-new-news-this-group
+
+2003-03-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-uu.el (mm-uu-pgp-encrypted-test): Fix message.
+
+2003-03-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-cus.el (gnus-group-customize): Don't use delete-if which is
+       a cl run-time function.
+
+2003-03-06  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Added missing binding
+       on gnus-agent-short-article.
+       (gnus-category-read): Replaced CL function mapcar* with new macro:
+       gnus-mapcar.
+       * gnus-util.el (gnus-mapcar): New macro.  Generalizes mapcar to
+       support functions that accept multiple parameters.  A separate
+       sequence must be provided for each parameter in the function.
+       Iteration stops when the end of the shortest list is reached.
+
+2003-03-06  Jesper Harder  <harder@ifa.au.dk>
+
+       * nnimap.el (nnimap-request-accept-article): Use delete-region.
+
+       * html2text.el (html2text-clean-dtdd, html2text-delete-tags)
+       (html2text-delete-single-tag, html2text-clean-anchor)
+       (html2text-remove-tags): Use delete-region.
+       (html2text-fix-paragraphs): Simplify.
+
+       * mml1991.el (mml1991-mailcrypt-sign, mml1991-mailcrypt-encrypt)
+       (mml1991-gpg-sign, mml1991-gpg-encrypt, mml1991-pgg-sign)
+       (mml1991-pgg-encrypt, mml1991-pgg-encrypt): Use delete-region, not
+       kill-region.
+
+2003-03-04  John Paul Wallington  <jpw@gnu.org>
+
+       * gnus-agent.el (gnus-agent-enable-expiration)
+       (gnus-agent-article-alist, gnus-agent-article-alist)
+       (gnus-agent-cat-defaccessor): Doc fixes.
+
+2003-03-04  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-function-implies-unread-1): Grok
+       byte-compiled functions.
+
+2003-03-04  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-sum.el (gnus-auto-goto-ignores): New variable. Provides
+       customization between new maneuvering (which permits selecting
+       undownloaded articles) and old maneuvering (which skipped over
+       undownloaded articles) behaviors.
+       (gnus-summary-find-next): Pass through the unread and subject
+       parameters when calling gnus-summary-find-prev.
+       (gnus-summary-find-next,gnus-summary-find-prev): Apply
+       gnus-auto-goto-ignores to filter out unacceptable articles.
+
+2003-03-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * mail-source.el (mail-source-read-passwd): Remove. `read-passwd'
+       exists in all supported Emacs versions, so we don't need this
+       compatibility function.
+       (mail-source-fetch-pop, mail-source-check-pop)
+       (mail-source-fetch-webmail): Use read-passwd.
+
+       * nntp.el (nntp-send-authinfo, nntp-send-nosy-authinfo)
+       (nntp-open-telnet, nntp-open-via-telnet-and-telnet): Use
+       read-passwd.
+
+       * nnwarchive.el (nnwarchive-open-server): Use read-passwd.
+
+       * imap.el (imap-read-passwd): Remove.
+       (imap-interactive-login): Use read-passwd.
+
+       * canlock.el (canlock-read-passwd): Remove.
+       (canlock-insert-header, canlock-verify): Use read-passwd.
+
+       * sieve-manage.el (sieve-manage-read-passwd): Remove.
+       (sieve-manage-interactive-login): Use read-passwd.
+
+       * pop3.el (pop3-read-passwd): Remove.
+       (pop3-movemail, pop3-get-message-count, pop3-apop): Use
+       read-passwd.
+
+       * pgg.el (pgg-read-passphrase): Simplify.
+
+2003-03-04  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-mode): Fixed the mode line reports
+       'plugged' when actually 'unplugged' bug.
+       (gnus-category-read): Ignore nil values when converting an
+       old-format category so that the new-format category will default
+       those attributes to the global variables.
+
+2003-03-03  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * mail-source.el (mail-source-delete-old-incoming-confirm): Fixed
+       doc-string.
+
+2003-03-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * nnrss.el (nnrss-decode-entities-unibyte-string): Use `buffer-string'.
+       * nndoc.el (nndoc-dissect-mime-parts-sub): do.
+       * nndb.el (nndb-request-accept-article, nndb-status-message): do.
+       * mm-url.el (mm-url-decode-entities-string): do.
+       * mml1991.el (mml1991-mailcrypt-sign, mml1991-gpg-sign): do.
+       * mm-decode.el (mm-find-raw-part-by-type): do.
+       * message.el (message-send-mail-partially)
+       (message-send-mail-with-sendmail): do.
+       * gnus-uu.el (gnus-uu-save-article, gnus-uu-reginize-string): do.
+       * gnus-kill.el (gnus-pp-gnus-kill): do.
+       * gnus-art.el (gnus-article-treat-unfold-headers)
+       (gnus-article-encrypt-body): do.
+
+2003-02-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * mail-source.el (mail-source-delete-incoming): Allow integer value.
+       (mail-source-delete-old-incoming-confirm): New variable.
+       (mail-source-delete-old-incoming): Use it.  New function.
+       (mail-source-callback): Call `mail-source-delete-old-incoming' if
+       `mail-source-delete-incoming' is a nonnegative integer.
+
+2003-03-03  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-msg.el (gnus-extended-version): Fix for 'emacs-gnus-config.
+       (gnus-user-agent): Fixed typo.
+
+2003-03-03  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-enable-expiration): Fixed documentation.
+       (gnus-agent-expire-group-1): Removed invalid (interactive) specifier.
+
+2003-03-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-fetch-articles): Fix nil message.
+       (gnus-agent-fetch-session): Allow debugging to take place.
+
+2003-03-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-highlight-selected-summary)
+       (gnus-article-get-xrefs, gnus-summary-show-thread): Use
+       `gnus-point-at-bol' and `gnus-point-at-eol' instead of
+       `(progn (beginning-of-line) (point))'.  It's shorter, faster,
+       and makes it clear that we don't need the side effect.
+       * gnus-util.el (gnus-delete-line): do.
+       * gnus-xmas.el (gnus-group-add-icon): do.
+       * nnmail.el (nnmail-article-group, nnmail-cache-fetch-group): do.
+       * nntp.el (nntp-send-authinfo-from-file): do.
+       * nnml.el (nnml-header-value): do.
+       * nnheader.el (nnheader-insert-references): do.
+       * gnus-cite.el (gnus-article-highlight-citation)
+       (gnus-cite-parse): do.
+       * gnus-score.el (gnus-score-followup): do.
+       * gnus-draft.el (gnus-draft-send): do.
+       * gnus-group.el (gnus-group-highlight-line): do.
+       * gnus-cache.el (gnus-cache-braid-nov): do.
+       * nnfolder.el (nnfolder-retrieve-headers)
+       (nnfolder-request-article): do.
+       * gnus-art.el (article-hide-boring-headers)
+       (gnus-article-hide-header): do.
+
+       * nnheader.el (nnheader-find-nov-line): Use gnus-delete-line.
+       * nnml.el (nnml-request-replace-article): do.
+       * nnmbox.el (nnmbox-request-move-article, nnmbox-delete-mail): do.
+       * nnfolder.el (nnfolder-request-move-article): do.
+       * gnus-cache.el (gnus-cache-possibly-remove-article): do.
+       * gnus-art.el (gnus-mm-display-part): do.
+
+       * gnus-art.el (gnus-article-goto-part): Use gnus-goto-char.
+
+2003-03-02  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * nntp.el (nntp-possibly-change-group): Avoid calling
+       process-buffer on nil (Which happened when you lost your
+       connection while fetching); instead signal a "Server Closed
+       Connection" error.
+
+2003-03-02  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-enable-expiration): New
+       variable. Either ENABLE or DISABLE.  Sets default behavior for
+       selecting which groups are expired.
+       (gnus-agent-cat-set-property, gnus-agent-cat-defaccessor,
+       gnus-agent-set-cat-groups): Provides abstract interface for
+       accessing agent category.  Category now implemented by an alist.
+       (gnus-agent-add-group, gnus-agent-remove-group,
+       gnus-category-insert-line, gnus-category-edit-predicate,
+       gnus-category-edit-score, gnus-category-edit-groups,
+       gnus-category-copy, gnus-category-add, gnus-group-category): Use
+       new agent category abstraction.
+       (gnus-agent-find-parameter): New function. Search for agent
+       configuration parameter first in the group's parameters, then its
+       topics (if any), and then the group's category.  If not found
+       anywhere, use the original defined constants.
+       (gnus-agent-fetch-headers, gnus-agent-fetch-group-1): Use new
+       gnus-agent-find-parameter.
+       (gnus-agent-fetch-headers, gnus-agent-uncached-articles): Clearing
+       gnus-agent-cache now blocks retrieving headers and articles from
+       the local cache.  Fetched content is still added to the cache
+       before being returned.
+       (gnus-agent-fetch-session): Use error-message-string to generate
+       displayed error message.
+       (gnus-agent-customize-category): New Command. 'e' in category
+       buffer opens category customization buffer.
+       (gnus-category-read): Reads either positional or alist format;
+       returns alist format.
+       (gnus-category-write): Writes category file compatible with
+       current, and previous, versions of gnus-agent.
+       (gnus-category-make-function, gnus-category-make-function-1):
+       Corrected documentation; parameter is predicate NOT category.
+       (gnus-predicate-implies-unread): Now works in more cases per the
+       todo comment.
+       (gnus-function-implies-unread-1): New function. Supports
+       gnus-predicate-implies-unread.
+       (gnus-agent-expire-group): Command now provides default of group
+       under point.
+       (gnus-agent-expire-group-1): Obeys new agent-enable-expiration and
+       agent-days-until-old parameters. No longer supports
+       gnus-agent-expire-days being set to an alist.
+       (gnus-agent-request-article): Now performs its own checks of
+       gnus-agent, gnus-agent-cache, and gnus-plugged rather than
+       assuming that the caller will do them correctly.
+       (): Added one-time hook to gnus-group-prepare-hook.  Detects when
+       gnus-agent-expire-days is set to an alist.  Converts said alist
+       into group parameter so that gnus-agent-expire-days will not be
+       needed.
+       * gnus-art.el (gnus-request-article-this-buffer): Conditional
+       checks surrounding gnus-agent-request-article removed; now
+       performed by gnus-agent-request-article.
+       * gnus-cus.el (gnus-agent-parameters): New variable. List of
+       customizable group/topic parameters that regulate the agent.
+       (gnus-group-customize): Uses gnus-agent-parameters.  Replaced
+       kill-buffer with gnus-kill-buffer to remove the killed buffer from
+       the list of gnus buffers.
+       (gnus-trim-whitespace): Removes leading and trailing whitespace
+       from multiline strings.
+       (gnus-agent-cat-prepare-category-field,
+       gnus-agent-customize-category): Constructs a category
+       customization buffer.
+       * gnus-int.el (gnus-retrieve-headers,
+       gnus-request-expire-articles): No longer checks gnus-agent-cache
+       as it is handled internally by the agent.
+       (gnus-request-head, gnus-request-body): Conditional checks
+       surrounding gnus-agent-request-article removed; now performed by
+       gnus-agent-request-article.
+
+       * gnus-start.el (): Added defvar statements to resolve compilation
+       warnings.
+       (gnus-long-file-names): New function. Isolates platform dependent
+       msdos-long-file-names.
+       (gnus-save-startup-file-via-temp-buffer): New variable. Provides
+       option of writing directly to file.  Avoids memory exhausted
+       errors when .newsrc.eld is huge.
+       (gnus-save-newsrc-file): Uses new
+       gnus-save-startup-file-via-temp-buffer.
+       (gnus-gnus-to-quick-newsrc-format): Rewritten to write to
+       standard-output.
+       (gnus-display-time-event-handler): Changed to alias from a defun
+       to avoid a compile-time warning when display-time-event-handler is
+       not defined.
+       * gnus-util.el (gnus-with-output-to-file): New macro. Binds
+       standard-output such that prin1 and princ will write directly to a
+       file.
+
+       * gnus.el (gnus-agent-cache): Expanded documentation.
+       (gnus-summary-high-undownloaded-face): Removed second bold keyword
+       so that this face is actually bold.
+
+       * nnkiboze.el (nnkiboze-request-article): Only use the cache when
+       gnus-use-cache has been set.
+
+2003-03-02  Jesper Harder  <harder@ifa.au.dk>
+
+       * nnvirtual.el (nnvirtual-update-xref-header): Simplify.
+
+2003-03-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-refer-article): Be more permissive.
+
+2003-03-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * spam.el: Fix typo.
+
+2003-03-01  Satyaki Das  <satyaki@theforce.stanford.edu>
+       (Trivial patch.)
+
+       * pgg-gpg.el (pgg-gpg-process-region): Insert process status into
+       errors-buffer. This produces a nicer error message in case of
+       problems.
+
+2003-03-01  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-maybe-spam-stat-load, spam-maybe-spam-stat-load):
+       load stats iff spam-use-stat is on
+
+       * spam.el: add spam-maybe-spam-stat-load to gnus-startup hook,
+       also use spam-maybe-spam-stat-load and spam-maybe-spam-stat-save
+       instead of spam-stat-load and spam-stat-save in the
+       gnus-get-new-news-hook and gnus-save-newsrc-hook, respectively
+
+2003-03-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Ignore errors from enriched-decode.
+
+2003-03-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-make-fqdn): Protect against nil user-mail.
+
+2003-02-28  Vasily Korytov <deskpot@myrealbox.com>
+
+       * gnus-art.el (gnus-boring-article-headers): New values:
+       'to-list and 'cc-list.
+
+2003-02-28  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-setup-widening): new function to set
+       nnimap-split-download-body, we add it to gnus-get-new-news-hook
+       (spam-list-of-statistical-checks): list of statistical splitter
+       checks
+       (spam-split): added a widen call when a statistical check is
+       enabled
+
+2003-02-28  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-msg.el (gnus-user-agent): Changed default to
+       'emacs-gnus-type, renamed 'full.
+
+2003-02-28  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-accept-article): Don't use
+       mail-header-unfold-field.
+
+2003-02-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * imap.el (imap-ssl-open): Don't depend on ssl.el.
+       * nntp.el (nntp-open-ssl-stream): Don't depend on ssl.el.
+
+2003-02-26  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: add spam-stat-load to gnus-get-new-news-hook
+       (spam-split): remove spam-stat-load call
+
+2003-02-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Run
+       gnus-article-decode-hook instead of calling a-decode-encoded-words
+       directly (the latter is run as part of the former).
+
+2003-02-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-expire-group): Remove debug.
+
+2003-02-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-sendmail-envelope-from): New option.
+       (message-sendmail-envelope-from): New function.
+       (message-send-mail-with-sendmail): Use it.
+
+2003-02-25  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-mid-or-mail-heuristic-alist): Added
+       compensation for TDMA addresses.
+
+2003-02-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-msg.el (gnus-user-agent): New variable.
+       (gnus-version-expose-system): Removed.  Obsoleted by
+       `gnus-user-agent'.
+       (gnus-extended-version): Use `gnus-user-agent'.
+
+2003-02-24  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-stat-register-spam-routine,
+       spam-stat-register-ham-routine): remove spam-stat-save
+       (spam-stat hook): add spam-stat-save to the gnus-save-newsrc-hook
+
+2003-02-24  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-group.el (gnus-topic-mode-p): Fixed free variable
+       reference.
+
+2003-02-24  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * nnheader.el (nnheader-find-nov-line): Changed midpoint
+       calculation to avoid integer overflow.
+
+2003-02-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-start.el (gnus-backup-startup-file): Fixed custom type.
+
+2003-02-24  Ted Zlatanov <tzz@lifelogs.com>
+       * spam.el: disabled spam-get-article-as-filename
+
+       From Michael Shields  <shields@msrl.com>
+
+       * gnus-group.el (gnus-group-is-exiting-without-update-p): New.
+       * gnus-sum.el (gnus-summary-exit-no-update): Use it.
+       * gnus-sum.el (gnus-summary-expire-articles): Use it.
+       * spam.el (spam-summary-prepare-exit): Use it.
+       * gnus.el (gnus-install-group-spam-parameters): New.
+       * spam.el (spam-group-ham-processor-copy-p): New.
+       * spam.el (spam-summary-prepare-exit): Support for ham copying.
+       * spam.el (spam-mark-spam-as-expired-and-move-routine): Fix bug
+       that would cause the current message to be moved if the group had
+       no spam.
+       * spam.el (spam-ham-move-routine): New `copy' argument.
+
+2003-02-24  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+       From Martin Thornquist <martint@ifi.uio.no>
+
+       * gnus-topic.el (gnus-topic-select-group): Select last group if
+       after last group.
+       * gnus-group.el (gnus-group-select-group): Ditto.
+
+2003-02-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (popup-menu): Compiler macro for Emacs 20.
+       (gnus-article-refer-article): Use gnus-point-at-(b|e)ol instead of
+       point-at-(b|e)ol which aren't available in Emacs 20.
+
+       * gnus-registry.el (puthash): Alias to cl-puthash for Emacs 20.
+
+2003-02-23  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-start.el (gnus-activate-group): Re-enabled the catch error
+       clause of the condition-case statement.  Errors connecting to a
+       server no longer terminate gnus.
+
+       * gnus-agent.el (gnus-agent-toggle-plugged): Renamed parameter to
+       make its use obvious.  Added no-nothing case to avoid
+       opening(closing) servers when already open(closed).
+       (gnus-agent-while-plugged): Added macro to facilitate internal use
+       of gnus-agent-toggle-plugged.
+       (gnus-agent-fetch-group): Use new gnus-agent-while-plugged to
+       temporarily open servers.
+       (gnus-agent-get-undownloaded-list): Sort list of article numbers
+       as sorting gnus-newsgroup-headers is wrong.
+       (gnus-agent-summary-fetch-group): Use new gnus-agent-while-plugged
+       to temporarily open servers. Corrected logic to handle setting
+       gnus-agent-mark-unread-after-downloaded.
+       (gnus-agent-fetch-articles): Now handles headers with missing
+       article sizes and/or missing article lengths.  Now clears the
+       message buffer when finished.
+       (gnus-agent-fetch-group-1): Position point before calling
+       gnus-summary-set-agent-mark.
+       (gnus-get-predicate): Corrected description, parameter is
+       predicate not category.
+       (gnus-agent-expire-group): Adapted the gnus-agent-expire-* code to
+       provide a separate single group expiration function.
+       (gnus-agent-regenerate-group): Now clears the message buffer when
+       finished.
+
+2003-02-23  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.el (gnus-agent-target-move-group-header): New variable.
+       * gnus-draft.el (gnus-draft-send): If special header
+       "X-Gnus-Agent-Target-Move-Group" is present, do like Gcc into
+       that group, instead of performing the regular sending functions.
+
+2003-02-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-xmas.el (gnus-xmas-mime-button-menu): Accept a prefix arg.
+
+2003-02-20  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-user-fqdn, message-valid-fqdn-regexp): New
+       variables.
+       (message-make-fqdn): Use it.  Improved validity check.
+
+2003-02-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-user-mail-address): Check whether
+       user-mail-address looks valid.
+
+       * gnus-msg.el (gnus-mailing-list-followup-to): New function.
+
+       * gnus-util.el (gnus-fetch-original-field): New function.
+
+2003-02-23  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * message.el (message-mode): \\(...\\) around additional
+       paragraph-separate alternative.
+
+2003-02-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-mime-button-commands): Add ellipsis.
+       (gnus-mime-button-menu): Define MIME popup menu with easy-menu to
+       display key bindings.
+       (gnus-mime-button-menu): Rewrite.
+
+2003-02-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-button-url-regexp): Removed `.
+
+2003-02-23  Max Froumentin  <mf@w3.org>
+
+       * gnus-art.el (gnus-button-url-regexp): Remove `, enter '.
+
+2003-02-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-action-on-part): Require a match
+       interactively.
+
+       * gnus-start.el (gnus-save-newsrc-file): Use
+       gnus-backup-startup-file.
+       (gnus-backup-startup-file): New variable.
+
+2003-02-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-summary-buffer-name): Moved function here.
+
+       * gnus-draft.el (defun): Remove debug.
+
+2003-02-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-refer-article): Skip method if we
+       can't open server.
+
+2003-02-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el (defun): Configure posting styles.
+
+       * gnus-start.el (gnus-get-unread-articles-in-group): Make sure
+       the entry for the group exists before we alter it.
+
+2003-02-22  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * message.el (message-mode): MML tags separate paragraphs.  Small
+       change from David S Goldberg <david.goldberg6@verizon.net>.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Sort
+       `gnus-newsgroup-headers'.
+
+       * gnus-art.el (gnus-article-refer-article): Grok more message id
+       formats.  From Karl Pfl\e,Ad\e(Bsterer <sigurd@12move.de>.
+
+2003-02-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-decode.el (mm-path-name-rewrite-functions): Doc fix: don't
+       use "path name".
+
+2003-02-21  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-sum.el (gnus-summary-move-article)
+       (gnus-summary-expire-articles): send data header for article, not
+       just article ID
+
+       * gnus-registry.el (gnus-registry-hashtb, gnus-register-action)
+       (gnus-register-spool-action): added hashtable of message ID keys
+       with message motion data
+
+2003-02-21  Florian Weimer  <fw@deneb.enyo.de>
+       From Reiner Steib  <Reiner.Steib@gmx.de>.
+
+       * gnus-art.el (gnus-button-mid-or-mail-heuristic-alist): New
+       variable, used in `gnus-button-mid-or-mail-heuristic'.
+       (gnus-button-mid-or-mail-heuristic): New function derived from
+       Florian Weimer's Perl script.
+       (gnus-button-handle-mid-or-mail): Allow a function instead of
+       'guess.
+       (gnus-button-guessed-mid-regexp): Removed.
+
+2003-02-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-resend): Bind message-setup-hook to nil;
+       remove X-Draft-From header.
+
+2003-02-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-simplify-subject-fully, gnus-subject-equal)
+       (gnus-newsgroup-undownloaded)
+       (gnus-summary-save-parts-default-mime, gnus-auto-select-next):
+       Doc fixes.
+
+2003-02-17  John Paul Wallington  <jpw@gnu.org>
+
+       * gnus.el (gnus-shell-command-separator, gnus-email-address)
+       (gnus-default-charset, gnus-other-frame-parameters): Doc fixes.
+
+2003-02-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-spec.el (gnus-xmas-format): Use insert instead of
+       insert-string which is obsolete in Emacs 21.4.
+
+       * message.el (message-cross-post-followup-to-header): do.
+
+       * spam.el (spam-ifile-register-with-ifile)
+       (spam-stat-register-spam-routine)
+       (spam-stat-register-ham-routine)
+       (spam-bogofilter-register-with-bogofilter): do.
+
+       * mailcap.el (mailcap-mime-data): Fix typo.
+
+       * gnus-topic.el (gnus-topic-make-menu-bar): Add ellipsis.
+
+2003-02-19  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-cite.el (gnus-cite-unsightly-citation-regexp)
+       (gnus-cite-parse): Renamed `gnus-unsightly-citation-regexp' to
+       `gnus-cite-unsightly-citation-regexp'.
+
+2003-02-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-copy-article-buffer): Copy an article header
+       even if there's just a header.
+
+2003-02-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-fix-before-sending): Fix highlighting of
+       illegible and invisible text.
+
+       * gnus-util.el (gnus-multiple-choice): Separate choices with
+       ",\e,A \e(B".  Suggested by Dan Jacobson <jidanni@dman.ddts.net>.
+
+2003-02-18  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Use gnus-kill-buffer.
+
+2003-02-18  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-move-routine)
+       (spam-mark-spam-as-expired-and-move-routine): use
+       gnus-summary-kill-process-mark and gnus-summary-yank-process-mark
+       around process-mark manipulation on the group
+
+2003-02-17  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add MIME/Multipart
+       submenu.
+
+2003-02-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch): Reverse the return value of
+       the continuation question.
+
+2003-02-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nndraft.el (nndraft-request-move-article): Bind
+       nnmh-allow-delete-final to t.
+
+2003-02-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-uu-filename): Fix use of character constant.
+
+2003-02-11  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * nntp.el (nntp-accept-process-output): Don't use point-max to get
+       the buffer's size.
+
+2003-01-31  Joe Buehler  <jhpb@draco.hekimian.com>
+
+       * nnheader.el: Added cygwin to system-type comparisons.
+
+2003-01-27  Juanma Barranquero  <lektu@terra.es>
+
+       * imap.el (imap-mailbox-status): Fix typo.
+
+2003-02-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-prepare): Don't set agent mark if
+       online.
+
+2003-02-14  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-group-make-menu-bar): Include all
+       commands.
+       * gnus-sum.el: Small change from Frank Weinberg
+       <frank@usenet-rundfahrt.de>:
+       (gnus-auto-center-group): New variable.
+       (gnus-summary-read-group-1): Use it.
+       (gnus-summary-next-group): Fix docstring.
+
+2003-02-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-util.el (gnus-faces-at): Simplify.
+
+2003-02-13  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-move-routine)
+       (spam-mark-spam-as-expired-and-move-routine): made the article
+       move conditional, so it's not called even if there's nothing to move
+
+2003-02-13  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * message.el (message-unix-mail-delimiter): Accept any whitespace
+       after the email address and before the date; do not require the
+       space character.  From Kurt B. Kaiser <kbk@shore.net>.
+
+2003-02-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-only-boring-p): Make sure that the
+       gnus-article-boring-faces variable is bound; use gnus-faces-at.
+
+       * gnus-util.el (gnus-faces-at): New macro.
+
+2003-02-13  Michael Shields  <shields@msrl.com>
+
+       * gnus-cite.el
+       (gnus-cite-attribution-suffix, gnus-cite-parse):
+       Better handling for Microsoft citation styles.
+       (gnus-unsightly-citation-regexp): New.
+
+2003-02-12  Michael Shields  <shields@msrl.com>
+
+       * gnus-art.el (article-strip-banner): Strip both per-group and
+       per-user-address banners.
+       (article-really-strip-banner): New.
+
+2003-02-12  Michael Shields  <shields@msrl.com>
+
+       * gnus-sum.el (gnus-article-goto-next-page,
+       gnus-article-goto-prev-page): Call gnus-summary-*-page, instead of
+       relying on the summary bindings of `n' and `p'.
+
+2003-02-12  Michael Shields  <shields@msrl.com>
+
+       * gnus-art.el (gnus-article-only-boring-p): New.
+       (gnus-article-skip-boring): New.
+       * gnus-cite.el (gnus-article-boring-faces): New.
+       * gnus-sum.el (gnus-summary-next-page): Use
+       gnus-article-only-boring-p.
+
+2003-02-12  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-mark-spam-as-expired-and-move-routine)
+       (spam-ham-move-routine): unmark all articles before marking those
+       of interest and calling gnus-summary-move-article
+
+2003-02-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.el (gnus-kill-buffer): Move to gnus.el because it's
+       logically the complement of gnus-get-buffer-create and
+       gnus-add-buffer.
+
+       * gnus-util.el (gnus-kill-buffer): do.
+
+       * nnmail.el: Autoload gnus-kill-buffer.
+
+2003-02-11  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-summary-set-agent-mark): Added call to
+       gnus-summary-goto-subject as gnus-summary-update-mark operates on
+       the current LINE.
+       (gnus-agent-summary-fetch-group): Minimized the number of times
+       that the article is updated in the buffer.
+
+2003-02-11  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-move-routine): use the process-mark instead of
+       gnus-current-article when moving articles
+       (spam-mark-spam-as-expired-and-move-routine): ditto, use the process-mark
+
+2003-02-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-expire-articles): Recursive.
+       (gnus-topic-catchup-articles): Ditto.
+       (gnus-topic-mark-topic): Reverse recursive logic.
+
+2003-02-11  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-refer-thread): Handle case where
+       gnus-refer-thread-limit is t.
+
+2003-02-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-util.el (mm-mule-charset-to-mime-charset): Use
+       sort-coding-systems to prefer utf-8 over utf-16.
+
+2003-02-09  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-expire-days):
+       gnus-request-move-article depends on gnus-agent-expire to clean up
+       the cache after moving the article.  Therefore, g-a-e-d can NOT
+       default to nil or can gnus-agent-expire be disabled by doing so.
+       If you don't want to run gnus-agent-expire, don't call it.
+       (gnus-agent-expire): The broken test to disable gnus-agent-expire
+       when g-a-e-d was NOT nil was removed.
+       (gnus-agent-article-name): Removed unnecessary input test as
+       article IDs are always strings.
+       (gnus-agent-regenerate-group): Added check to protect against
+       servers that generate absurdly long article IDs.  Valid IDs are
+       less than 10 digits to avoid overflow errors.  Fixed logic error
+       when ensuring that the final article ID is present in the new
+       alist.
+
+2003-02-09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-goto-missing-topic): Just move to the
+       next line after finding the parent.
+
+2003-02-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bumped.
+
+2003-02-08 23:23:27 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.15 is released.
+
+2003-02-08  Michael Welsh Duggan  <md5i@cs.cmu.edu>
+
+       * nnmail.el (nnmail-split-it): If a message ends up matching the
+         same mailbox more than once, it will cause duplicates to appear
+         in the mailbox.
+
+2003-02-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-select-article): Remove blink removal
+       code that only worked under Emacs.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Don't blink.  From Satyaki
+       Das <satyaki@chicory.stanford.edu>.
+
+2003-02-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-refer-article): Use
+       gnus-replace-in-string.
+
+       * gnus-util.el (gnus-map-function): Remove unneeded let-binding.
+       (gnus-remove-duplicates): do.
+
+2003-02-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-int.el (gnus-internal-registry-spool-current-method): new variable
+       (gnus-request-scan): set
+       gnus-internal-registry-spool-current-method to gnus-command-method
+       before a request-scan operation
+
+       * gnus-registry.el (regtest-nnmail): use
+       gnus-internal-registry-spool-current-method
+
+2003-02-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch): Typo fix.
+
+2003-02-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * nnmail.el (nnmail-spool-hook): new hook
+       (nnmail-cache-insert): call nnmail-spool-hook
+
+       * gnus-registry.el: new file with examples of using the hooks
+
+       * gnus.el (gnus-registry): added registry customization group
+       (gnus-group-prefixed-name): improve function to return full group
+       name optionally
+       (gnus-group-guess-prefixed-name): shortcut to
+       gnus-group-prefixed-name, using just the group name
+       (gnus-group-full-name): always get a group's full name
+       (gnus-group-guess-full-name): shortcut, using just the group name
+
+       * gnus-sum.el (gnus-summary-article-move-hook)
+       (gnus-summary-article-delete-hook)
+       (gnus-summary-article-expire-hook): new hooks
+       (gnus-summary-move-article, gnus-summary-expire-articles)
+       (gnus-summary-delete-article): invoke the new hooks
+
+2003-02-07  Frank Weinberg  <frank@usenet-rundfahrt.de>
+
+       * gnus-art.el (gnus-article-refer-article): Strip leading "news:"
+       from message-ID
+
+2003-02-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-util.el (gnus-run-hooks): Use save-current-buffer.
+
+2003-02-07  John Paul Wallington  <jpw@gnu.org>
+
+       * mm-util.el (mm-delete-duplicates, mm-append-to-file)
+       (mm-write-region, mm-detect-coding-region): Doc fixes.
+
+2003-02-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch): Ignore errors.
+       (mail-source-ignore-errors): New variable.
+
+       * gnus-sum.el (gnus-summary-refer-thread): Don't re-fetch current
+       articles.
+
+       * gnus-msg.el (gnus-version-expose-system): Change default.
+
+2003-02-07  Vasily Korytov  <deskpot@myrealbox.com>
+
+       * gnus-msg.el (gnus-version-expose-system): New variable.
+
+2003-02-07  Simon Josefsson  <jas@extundo.com>
+
+       * mml-sec.el (mml-unsecure-message): Don't use kill-region.  Tiny
+       patch from deskpot@myrealbox.com (Vasily Korytov).
+
+2003-02-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-display-face): Get the Face header from
+       the current buffer.
+
+2003-02-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-mime-view-part-internally): Bind
+       buffer-read-only to nil.
+
+2003-02-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-agent.el (gnus-agent-expire-1,2): Pass the dir argument
+       from g-a-e-1 to g-a-e-2.
+
+2003-02-05  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-BBDB): no need to regexp-quote the argument
+       of bbdb-search-simple, use spam-use-BBDB-exclusive
+       (spam-check-whitelist): use spam-use-whitelist-exclusive
+       (spam-use-whitelist-exclusive): new variable affecting
+       spam-use-whitelist
+       (spam-use-BBDB-exclusive): new variable affecting spam-use-BBDB
+
+2003-02-05  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-agent.el (gnus-agent-expire-days): Change default to nil.
+       (gnus-agent-expire): Don't expire if g-a-e-d is nil.
+       (gnus-agent-expire): Move most code into gnus-agent-expire-1.
+       (gnus-agent-expire-1): New.
+       (gnus-agent-expire-1): Move code into gnus-agent-expire-2.
+       (gnus-agent-expire-2): New.
+
+2003-02-05  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-util.el (gnus-delete-if): Rename to gnus-remove-if.
+       "delete-if" is misleading because it isn't actually destructive.
+
+       * gnus-topic.el (gnus-group-prepare-topics): Use new name.
+
+       * nnmail.el (nnmail-purge-split-history): do.
+
+       * gnus-win.el (gnus-get-buffer-window): do.
+
+       * gnus-sum.el (gnus-simplify-whitespace): Remove unnecessary
+       let-binding.
+       (gnus-simplify-all-whitespace): do.
+
+2003-02-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-delay.el (gnus-delay-article): Fix binding of the
+       nndraft:delayed group.
+
+2003-02-04  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.el (spam group parameters): change 'other to 'const in
+       the group parameter definitions to soothe XEmacs
+
+2003-02-04  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-delay.el (gnus-delay-article): Really create
+       nndraft:delayed group if it doesn't exist.
+
+2003-02-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-search-article): Speed up by
+       disabling various visual features while searching.
+       (gnus-summary-recenter): Test gnus-auto-center-summary first.
+
+2003-02-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * spam.el (spam-list-of-checks): Don't quote nil and t in
+       docstrings.  From the elisp manual:
+
+          When a documentation string refers to a Lisp symbol, write
+          it [..] with single-quotes around it.  [..] There are two
+          exceptions: write t and nil without single-quotes.
+
+       * messcompat.el (message-from-style): do.
+
+       * message.el (message-send-mail): do.
+
+       * gnus-util.el (gnus-use-byte-compile): do.
+
+       * gnus-score.el (gnus-score-lower-thread): do.
+
+       * gnus-int.el (gnus-server-unopen-status): do.
+
+       * gnus.el (gnus-define-group-parameter, gnus-large-newsgroup)
+       (large-newsgroup-initial, gnus-install-group-spam-parameters): do.
+
+       * gnus-cus.el (gnus-group-customize, gnus-score-parameters)
+       (gnus-group-parameters): do.
+
+       * gnus-art.el (gnus-article-mime-match-handle-function): do.
+
+       * mm-decode.el (mm-text-html-renderer): do.
+
+2003-02-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nnheader.el (nnheader-directory-separator-character): Change the
+       way to compute the dafault value.
+
+2003-02-02  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-button-handle-describe-key): Implement it.
+       (gnus-button-alist): Fix regexp for describe-key.
+       (gnus-button-handle-describe-function)
+       (gnus-button-handle-describe-variable)
+       (gnus-button-handle-apropos, gnus-button-handle-apropos-command)
+       (gnus-button-handle-apropos-variable)
+       (gnus-button-handle-apropos-documentation): Docstring fix.
+
+       * gnus-util.el (gnus-kill-buffer): Use get-buffer.
+
+2003-02-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el (gnus-group-send-queue): Bind gnus-posting-styles
+       to nil.
+
+       * nnmail.el: Removed gnus-util autoload.
+
+       * gnus.el: Use gnus-prin1-to-string throughout.
+
+       * gnus-util.el (gnus-prin1-to-string): Bind print-length and
+       print-level.
+
+       * gnus-art.el (article-display-x-face): Removed grey x-face stuff.
+       (gnus-treat-display-grey-xface): Removed.
+
+       * gnus-fun.el (gnus-grab-cam-face): New.
+       (gnus-convert-image-to-gray-x-face): Removed.
+       (gnus-convert-gray-x-face-to-xpm): removed.
+       (gnus-convert-gray-x-face-region): Removed.
+       (gnus-grab-gray-x-face): Removed.
+
+       * nnmail.el (nnmail-expiry-wait-function): Doc indent.
+
+2003-01-31  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-util.el (gnus-kill-buffer): Functions in gnus-util
+       shouldn't depend on the rest of Gnus, so test if gnus-buffers is
+       bound.
+
+       * nnmail.el (nnmail-cache-close): Use gnus-kill-buffer.
+
+2003-01-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-cite.el (gnus-cite-reply-regexp, gnus-cite-always-check):
+       Remove -- these are bogus options which are never used.
+
+2003-01-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-mode): Use summary tool bar.
+
+2003-01-27  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-blackholes)
+       (spam-blackhole-good-server-regex): new variable to skip some IPs
+       when checking blackholes; use it
+       (spam-check-bogofilter-headers)
+       (spam-bogofilter-bogosity-positive-spam-header): new variable, in
+       case more X-Bogosity is used than just "Yes/No"
+       (spam-ham-move-routine): semi-fixed, only first article is
+       properly moved now
+
+2003-01-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-util.el (gnus-kill-buffer): Remove buffer from gnus-buffers
+       as well.
+
+       * gnus-sum.el (gnus-select-newsgroup): Use gnus-kill-buffer.
+
+       * gnus-score.el (gnus-score-headers, gnus-score-find-bnews): do.
+
+       * gnus-start.el (gnus-save-newsrc-file, gnus-clear-system): do.
+
+       * gnus-bcklg.el (gnus-backlog-shutdown): do.
+
+       * gnus-srvr.el (gnus-server-exit, gnus-browse-exit): do.
+
+2003-01-26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-face-encode): New function.
+       (gnus-convert-png-to-face): Use it.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Added M-& to marks.
+
+2003-01-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-decode.el (mm-dissection-list): Remove.
+       (mm-dissect-singlepart): Don't push to mm-dissection-list, it's
+       only used in mm-remove-all-parts.
+       (mm-remove-all-parts): Remove it, it's never called.
+
+2003-01-25  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-make-group): Report errors.
+
+       * nnimap.el (nnimap-request-create-group): Ditto.
+
+       * sieve-manage.el (sieve-manage-is-okno): Parse literal strings.
+
+       * sieve.el (sieve-upload): Fix error printing.
+
+       * mm-encode.el (mm-qp-or-base64): Always QP iff
+       mm-use-ultra-safe-encoding and cleartext PGP.
+
+       * gnus-sum.el (gnus-summary-select-article): Inhibit
+       redisplay (mainly for secured messages).
+
+       * nnmail.el (nnmail-article-group): Copy body too (but don't
+       process it).
+
+2003-01-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-setup-buffer): Reset
+       gnus-button-marker-list.
+
+2003-01-25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nntp.el (nntp-read-timeout): Default to using a second delay
+       under Microsoft Windows.
+
+2003-01-24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el (nnheader-directory-separator-character): New
+       variable.
+
+2003-01-24  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-max-fetch-size)
+       (gnus-agent-article-alist, gnus-agent-get-undownloaded-list)
+       (gnus-agent-catchup, gnus-agent-summary-fetch-group)
+       (gnus-agent-fetch-articles, gnus-agent-backup-overview-buffer)
+       (gnus-agent-flush-cache, gnus-agent-fetch-headers)
+       (gnus-agent-braid-nov, gnus-agent-load-alist)
+       (gnus-agent-article-alist-save-format)
+       (gnus-agent-read-agentview, gnus-agent-save-alist)
+       (gnus-agent-fetch-group-1, gnus-agent-expire)
+       (gnus-agent-uncached-articles, gnus-agent-retrieve-headers)
+       (gnus-agent-regenerate-group): Reformat to keep under eighty
+       columns.  Reword docstrings so that first line is under eighty
+       chars and a complete sentence.  Still need to work on the rear
+       end of the file, in particular gnus-agent-expire.
+
+2003-01-24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agentize): Indent.
+
+       * gnus.el (gnus-version-number): Bumped.
+
+2003-01-24 20:32:44 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.14 is released.
+
+2003-01-24  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-sum.el (gnus-summary-prepare-threads): Reset state for %B
+       before beginning.  Tiny patch from Mark Thomas
+       <swoon@bellatlantic.net>.
+
+2003-01-24  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-blackholes, spam-split)
+       (spam-mark-junk-as-spam-routine, spam-summary-prepare-exit): added
+       gnus-message calls to show to users what spam.el is doing
+
+2003-01-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-msg.el (gnus-message-replysign)
+       (gnus-message-replyencrypt): Fix typo.
+
+2003-01-24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-security-show-details): Toggle showing
+       details.
+
+2003-01-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-press-button): let* -> let.
+       (gnus-mime-security-show-details): Cleaned up.
+       (gnus-mime-security-press-button): Save excursion.
+       (gnus-insert-mime-security-button): Clean up.
+
+       * gnus-sum.el (gnus-summary-force-verify-and-decrypt): Doc fix.
+
+       * gnus-async.el (gnus-async-wait-for-article): Don't use a
+       timeout.
+
+       * nntp.el (nntp-accept-process-output): Removed timeout.
+       (nntp-read-timeout): New variable.
+       (nntp-accept-process-output): Use it.
+
+       * gnus-sum.el (gnus-data-find-list): Remove *.
+
+2003-01-23  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-sum.el (gnus-summary-first-subject): Fixed bug that I
+       introduced on 2002-01-22.
+       (gnus-summary-first-unseen-or-unread-subject): Ditto.
+
+2003-01-23  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-regex-headers, spam-list-of-checks)
+       (spam-regex-headers-spam, spam-regex-headers-ham): added spam/ham
+       checks of incoming mail based on simple header regexp matching
+
+2003-01-22  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus-sum.el (gnus-spam-mark): set to `$'
+
+2003-01-22  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Now computes
+       gnus-newsgroup-unfetched, the list of articles whose headers have
+       not been fetched from the server.
+
+       * gnus-sum.el (gnus-summary-find-next): Removed undownloaded
+       parameter as it never worked due to a bug.  Added check to prevent
+       selection of any article in the gnus-newsgroup-unfetched list.
+       (gnus-summary-find-prev): Added check to prevent selection of any
+       article in the gnus-newsgroup-unfetched list.
+       (gnus-summary-first-subject): Documented API. Modified
+       implementation so that constraints are handled independently.
+       Added check to prevent selection of any article in the
+       gnus-newsgroup-unfetched list.
+       (gnus-summary-first-unseen-subject): Updated parameters in
+       gnus-summary-first-subject call to match new API.
+       (gnus-summary-first-unseen-or-unread-subject): Ditto.
+       (gnus-summary-catchup): Do not mark unfetched articles as read.
+
+2003-01-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-treat-strip-pgp, gnus-article-hide-pgp-hook):
+       make-obsolete-variable allows only two arguments in XEmacs and
+       Emacs 20.
+
+       * gnus-sum.el (gnus-summary-wash-hide-map): Remove
+       gnus-article-hide-pgp.
+       (gnus-summary-make-menu-bar): do.
+
+       * gnus-art.el (gnus-treat-strip-pgp): Make obsolete.
+       (gnus-treatment-function-alist): Remove gnus-treat-strip-pgp and
+       gnus-article-hide-pgp.
+       (article-hide-pgp): Remove.
+       (gnus-article-hide): Remove gnus-article-hide-pgp.
+
+       * gnus.el: Remove gnus-article-hide-pgp
+
+2003-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-required-headers): Doc fix.
+
+2003-01-21  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-group-ham-processor-bogofilter-p): fixed bug
+       (spam-ifile-register-ham-routine, spam-ifile-ham-category): new
+       option to make ifile a purely binary classifier
+
+2003-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml-sec.el (mml-secure-sign-pgpauto): Renamed.
+       (mml-secure-encrypt-pgpmime): Removed double.
+
+       * gnus-sum.el (gnus-summary-mark-article-as-replied): Added
+       debugging statements.
+
+2003-01-21  Andreas Fuchs  <asf@void.at>
+
+       * mml-sec.el (mml-sign-alist): Added pgpauto.
+
+2003-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bumped version number.
+
+2003-01-21 07:15:41 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.13 is released.
+
+2003-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-button-url-regexp): Removed |.
+
+       * message.el (message-send-hook): Doc fix.
+
+       * gnus-win.el (gnus-buffer-configuration): Display article
+       instead of article-copy when `reply'.
+
+2003-01-21  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.el (gnus-format): Change customize group to gnus.
+       (gnus-cache): Add link.
+       (gnus-group-charter-alist): Fix docstring.
+
+2003-01-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * mailcap.el (mailcap-print-command): lpr-command might be
+       unbound in XEmacs.
+
+2003-01-18  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-regenerate-group): Added interactive form.
+
+       * gnus-sum.el (gnus-summary-update-article-line): Fixed
+       calculation of net characters added for use in the gnus-data
+       structure.
+
+2003-01-18  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * nnmail.el (nnmail-process-unix-mail-format): Improve error
+       message.  Suggested by Jari Aalto.
+
+2003-01-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-followup-with-original): Clean up.
+       (gnus-article-reply-with-original): Ditto.
+
+       * gnus-sum.el (gnus-summary-catchup): Make sure downloadable,
+       read articles don't become unread.
+
+2003-01-17  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-fun.el (gnus-x-face-from-file):
+       (gnus-face-from-file): Suggest image format in minibuffer prompt.
+
+       * gnus-fun.el (gnus-convert-image-to-x-face-command)
+       (gnus-convert-image-to-face-command): Doc fix.
+
+2003-01-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-convert-face-to-png): Protect against errors.
+
+2003-01-17  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-mime-print-part): Use mm-save-part-to-file to
+       avoid encoding problems.
+
+       * mailcap.el (mailcap-ps-command): New variable.
+       (mailcap-mime-data): Add print entry where applicable.  Use
+       pdftotext on a tty.
+
+2003-01-16  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-alter-header-function): Add type and group.
+
+2003-01-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-fun.el (gnus-convert-image-to-x-face-command)
+       (gnus-convert-image-to-face-command, gnus-x-face-from-file)
+       (gnus-face-from-file): Doc fix; don't mention image format.
+
+2003-01-16  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-get-article-as-filename): new function (unused for now)
+       (spam-get-article-as-buffer): new function
+       (spam-get-article-as-string): use spam-get-article-as-buffer
+       (spam-summary-prepare-exit): fixed bug, noticed by Malcolm Purvis
+
+2003-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el: Don't use `path'.
+       From the GNU coding standards:
+
+           Please do not use the term ``pathname'' that is used in Unix
+           documentation; use ``file name'' (two words) instead.  We use
+           the term ``path'' only for search paths, which are lists of
+           directory names.
+
+       * nnsoup.el (nnsoup-file-name): Ditto.
+
+       * nnmail.el (nnmail-pathname-coding-system): Ditto.
+       (nnmail-group-pathname): Ditto.
+
+       * nnimap.el (nnimap-group-overview-filename): Ditto.
+
+       * nnheader.el (nnheader-pathname-coding-system): Ditto.
+       (nnheader-group-pathname): Ditto.
+
+       * nnfolder.el (nnfolder-group-pathname): Ditto.
+
+       * gnus.el (gnus-home-directory): Ditto.
+
+       * gnus-group.el (gnus-group-icon-list): Ditto.
+
+2003-01-16  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-mime-print-part): Use mm-handle-media-type.
+
+       * message.el (message-mode-menu): Use it.
+       (message-mode-menu): Deactivate "Yank Original" if there's no
+       reply buffer.
+
+       * messagexmas.el (message-xmas-redefine): Redefine in XEmacs.
+
+       * message.el (message-mark-active-p): New function.
+
+2003-01-15  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-bogofilter-headers, spam-bogofilter-header)
+       (spam-bogofilter-database-directory): new variables
+       (spam-check-bogofilter-headers, spam-check-bogofilter)
+       (spam-bogofilter-register-with-bogofilter)
+       (spam-bogofilter-register-spam-routine)
+       (spam-bogofilter-register-ham-routine)
+       (spam-group-ham-processor-bogofilter-p): new functions for the new
+       Bogofilter interface
+       (spam-summary-prepare-exit): use the new Bogofilter functions
+       (spam-list-of-checks): added spam-use-bogofilter-headers
+       (spam-bogofilter-score): rewrote function
+       (spam-check-bogofilter): optional score parameter, uses
+       spam-check-bogofilter-headers better
+       (spam-check-bogofilter-headers): optional score parameter
+
+       * gnus.el (gnus-install-group-spam-parameters): new variable, t by
+       default, in the gnus-start customization group.  Used to disable
+       the spam-*/ham-* parameters.
+       (gnus-group-ham-exit-processor-bogofilter): new ham processor
+
+2003-01-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-xmas.el (gnus-xmas-redefine): Use region-exists-p in
+       XEmacs.
+
+       * gnus-ems.el (gnus-mark-active-p): do.
+
+2003-01-15  Kevin Ryde  <user42@zip.com.au>
+
+       * gnus.texi (Using MIME): Mention auto-compression-mode with
+       gnus-mime-copy-part.
+
+2003-01-15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send): Don't warn about duplicates when
+       superseding.
+
+2003-01-15  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-download-body): New variable.
+       (nnimap-split-articles): Use it.
+
+2003-01-14  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): This data
+       integrity checker was incorrectly flagging, and removing, articles
+       whose article number was negative.
+       (gnus-agent-fetch-group-1): When executed in the group's summary
+       buffer, refresh each downloaded line to update the status flag and
+       font.  Preserve the value of gnus-newsgroup-headers so that
+       gnus-agent-fetch-articles can split the requests by size.
+       (gnus-agent-expire): Corrected day calculation for when
+       gnus-agent-expire-days contains a list.
+
+2003-01-14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-audio.el (gnus-audio-au-player): Use executable-find.
+
+2003-01-13  Jhair Tocancipa Triana <jhair_tocancipa@@gmx.net>
+
+       * gnus-audio.el (gnus-audio-au-player, gnus-audio-wav-player): Use
+         /usr/bin/play as default player.
+         (gnus-audio-play): Added ARG-DESCRIPTOR to prompt for a file to play.
+
+2003-01-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Allow a list of
+       articles to be marked as well.
+
+2003-01-14  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Include the
+       fictious headers generated by nnagent (ie. Undownloaded Article
+       ####) in the list of articles that have not been downloaded.
+
+       * gnus-int.el (): Added require declarations to resolve
+       compile-time warnings.
+       (gnus-open-server): If the server status is set to offline,
+       recursively execute gnus-open-server to open the offline backend
+       (e.g. nnagent).
+
+2003-01-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (gnus-article-reply-with-original): Use
+       gnus-mark-active-p.
+       (gnus-article-followup-with-original): do.
+
+2003-01-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-sum.el: Removed `(when t ...)' around `gnus-define-keys'.
+
+2003-01-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-score.el (gnus-score-edit-file-at-point): New function.
+       (gnus-score-find-trace): Bind it to `e' key.  Added `q' for quit.
+
+2003-01-13  Romain FRANCOISE  <romain@orebokech.com>
+
+       * gnus-fun.el (gnus-x-face-from-file): Quote file name.
+       (gnus-face-from-file): Ditto.
+
+2003-01-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-articles-to-read): Don't just apply
+       gnus-alter-articles-to-read-function to the unread articles.
+
+2003-01-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * deuglify.el (gnus-article-outlook-unwrap-lines)
+       (gnus-article-outlook-repair-attribution)
+       (gnus-article-outlook-rearrange-citation): New function names,
+       renamed from "gnus-outlook-" to "gnus-article-outlook-".  Changed
+       doc-string.
+
+       * gnus-sum.el (gnus-summary-mode-map): Use new function names,
+       removed `W k' key binding (use `W Y f' instead).
+       (gnus-summary-make-menu-bar): Use new function names.
+
+2003-01-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-fun.el (gnus-random-x-face): Doc fix.
+       (gnus-insert-random-x-face-header): New function.
+
+2003-01-13  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Deactivate items if
+       mark is not active.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Comment.
+
+       * gnus-ems.el (gnus-mark-active-p): New function.
+
+       * gnus-group.el (gnus-topic-mode-p): New function.
+       (gnus-group-make-menu-bar): Show more key bindings in topic mode.
+       Deactivate items if mark is not active.
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bumped version.
+       (gnus-summary-line-format): Doc fix.
+
+2003-01-12 22:02:49 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.12 is released.
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-sources): Removed autoload to make it
+       compile under XEmacs.
+
+2003-01-12  Raymond Scholz  <ray-2003@zonix.de>
+
+       * gnus-msg.el (gnus-confirm-mail-reply-to-news):  May be a
+       regexp or a function too.
+       (gnus-confirm-treat-mail-like-news): New variable.  Ask for
+       confirmation even if the original article is mail.
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Get the right
+       articles to be marked when not yanking.
+
+2003-01-12  Fran\e,Ag\e(Bois-David Collin  <Francois-David.Collin@curie.fr>
+
+       * mm-decode.el (mm-get-part): Use mm-with-unibyte-current-buffer.
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-face-from-file): Autoload.
+
+       * gnus-cite.el (gnus-cite-delete-overlays): Protect against more
+       errors.
+
+2003-01-12  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.el (sieve-upload-and-bury): New.  Suggested by
+       kai.grossjohann@uni-duisburg.de (Kai Gro\e,A_\e(Bjohann).
+
+       * sieve-mode.el (sieve-mode-map): Bind s-u-a-b to C-c C-c.
+       Suggested by kai.grossjohann@uni-duisburg.de (Kai Gro\e,A_\e(Bjohann).
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-ignored-headers): Don't include the ^ and :
+       in every string.
+
+       * gnus.el (gnus-version-number): Bumped version number.
+
+2003-01-12 13:46:20 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.11 is released.
+
+2003-01-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-fetch-reply-field): Narrow to headers.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Don't try to mark GCC's as read
+       if Gnus isn't alive.
+
+2003-01-11  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Remove downloadable
+       marks from articles that are already stored in the agent.
+       (gnus-agent-backup-overview-buffer): New debug tool.  Creates a
+       backup copy of an invalid .overview file for later analysis.
+
+2003-01-12  Gregorio Gervasio, Jr.  <gtgj@pacbell.net>
+
+       * gnus-sum.el (gnus-summary-exit): Reverse change to make group
+       exit work with two frames.
+
+2003-01-11  Fran\e,Ag\e(Bois-David Collin  <Francois-David.Collin@wanadoo.fr>
+
+       * message.el (message-forward-make-body): Use mule4.
+
+2003-01-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-mode-map): Move wide-reply command.
+
+2003-01-10  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * deuglify.el (gnus-outlook-deuglify-attrib-verb-regexp): Added
+       castellano.
+       (gnus-outlook-display-hook): New variable.
+       (gnus-outlook-display-article-buffer): New function.
+       (gnus-outlook-unwrap-lines, gnus-outlook-repair-attribution)
+       (gnus-outlook-deuglify-article): Made them interactive and added
+       optional arg.  Use `g-o-d-a-b'.
+       (gnus-article-outlook-deuglify-article): Use `g-o-d-a-b'.
+
+       * gnus-sum.el: Added autoloads.
+       (gnus-summary-mode-map): Added gnus-summary-wash-deuglify-map.
+       (gnus-summary-make-menu-bar): Added "(Outlook) Deuglify" menu.
+
+2003-01-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-display-mime): Use the mime emulation
+       variable.
+
+       * gnus-sum.el (gnus-article-emulate-mime): New variable.
+
+       * gnus-start.el (gnus-read-newsrc-el-file): Make sure that the
+       newsrc-alist is initialized properly.
+
+       * mail-source.el (mail-sources): Autoload.
+
+       * gnus-sum.el (gnus-summary-make-false-root-always): Default to
+       nil.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Make sure we don't
+       insert two newlines.
+
+       * message.el (message-check-news-header-syntax): Compute the
+       header length correctly.
+
+2003-01-10  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-expire): Do not remove article from
+       alist when keeping fetched article file.
+       (gnus-agent-retrieve-headers): When parsing response for article
+       numbers, use the same algorithm as gnus-agent-braid-nov to protect
+       against garbage in the server's response.
+
+       * gnus-int.el (gnus-request-expire-articles,
+       gnus-request-move-article): Only expire when the group's server
+       has been agentized.
+
+2003-01-10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cite.el (gnus-cite-delete-overlays): Protect against
+       errors when deleting overlays.
+
+       * gnus-score.el (gnus-score-followup): Allow tracing.
+
+       * gnus-art.el (gnus-treat-display-face): New variable.
+       (article-display-face): New command.
+
+       * gnus-fun.el (gnus-face-from-file): New function.
+       (gnus-convert-face-to-png): Ditto.
+
+       * gnus-art.el (gnus-ignored-headers): Added Face.
+
+2003-01-10  Simon Josefsson  <jas@extundo.com>
+
+       * nndraft.el (nndraft-request-group): Avoid crash in
+       directory-files when draft directory doesn't exists.
+
+       * gnus-sum.el (gnus-select-article-hook): Add :option.
+
+2003-01-10  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-stat): new variable
+       (spam-group-spam-processor-stat-p)
+       (spam-group-ham-processor-stat-p): new convenience functions
+       (spam-summary-prepare-exit): add spam/ham processors to sequence
+       (spam-list-of-checks): add spam-use-stat to list of checks
+       (spam-split): conditionally load the spam-stat tables
+       (spam-stat-register-spam-routine, spam-stat-register-ham-routine,
+       spam-check-ifile): new functions
+
+       * spam-stat.el (spam-stat): typo fix
+       (spam-stat-install-hooks): new variable
+       (spam-stat-split-fancy-spam-group): added documentation clarification
+       (spam-stat-split-fancy-spam-threshhold): new variable
+       (spam-stat-install-hooks): make hooks conditional
+       (spam-stat-split-fancy): use spam-stat-split-fancy-spam-threshhold
+
+       * gnus.el (gnus-group-ham-exit-processor-stat, spam-process): add
+       spam-stat ham/spam processor symbols
+
+2003-01-10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-read-newsrc-el-file): Make sure the .eld
+       file exists.
+
+2003-01-10  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-read-group-1): Don't select first
+       undownloaded/downloadable only when unplugged.
+
+2003-01-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Optimize inner loop.
+
+2003-01-09  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-ifile): fixed call-process-region to use the
+       db parameter only if it's set
+       (spam-ifile-register-with-ifile): ditto
+
+2003-01-09  Alex Schroeder  <alex@emacswiki.org>
+
+       * spam-stat.el (spam-stat-save): Set spam-stat-ngood and
+       spam-stat-nbad before creating the hash table.
+       (spam-stat-reset): Set spam-stat-ngood and spam-stat-nbad to 0.
+       Changed copyright statement to FSF.
+
+2003-01-09  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-catchup): Do not mark cached nor
+       processable articles as read.
+       (gnus-agent-summary-fetch-series): Remove processable and
+       downloadable marks on all downloaded articles in the series.
+
+       * nntp.el (nntp-report): Throw error after reporting the problem.
+       (nntp-accept-process-output): Corrected error check to report an
+       error when the process is nil.
+
+2003-01-09  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-tool-bar-map): Add preview.
+
+2003-01-09  Jesper Harder  <harder@ifa.au.dk>
+
+       * mml.el (mml-preview): Get rid of MIME handles and buffers after
+       previewing.
+
+2003-01-08  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--grp-add-art): Fix wrong-type-argument
+       bug when the (n+1)th article to be added to a group has a smaller
+       number than the n articles already added.
+
+2003-01-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-mode-field-menu): Use backquote.
+
+2003-01-08  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: fixed the BBDB autoloads again, using
+       bbdb-search-simple now (which is not a macro, thank god)
+
+       * lpath.el (bbdb-search): removed function from maybe-fbind list
+
+       * gnus.el (ham-process-destination): added new parameter for
+       destination of ham articles found in spam groups at summary exit
+
+       * spam.el (spam-get-ifile-database-parameter): use spam-ifile-database-path
+       (spam-check-ifile, spam-ifile-register-with-ifile): use spam-get-ifile-database-parameter
+       (spam-ifile-database-path): added new parameter for ifile's database
+       (spam-move-spam-nonspam-groups-only): new parameter to determine
+       if spam should be moved from all groups or only some
+       (spam-summary-prepare-exit): fixed logic to use
+       spam-move-spam-nonspam-groups-only when deciding to invoke
+       spam-mark-spam-as-expired-and-move-routine; always invoke that
+       routine after the spam has been expired-or-moved in case there's
+       some spam left over; use spam-ham-move-routine in spam groups
+       (spam-ham-move-routine): new function to move ham articles to the
+       ham-process-destinations group parameter
+
+2003-01-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-spec.el (gnus-parse-complex-format): %~ => ~*.
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Use
+       gnus-summary-update-article-line.
+
+2003-01-08  Simon Josefsson  <jas@extundo.com>
+
+       * nnmail.el (nnmail-expiry-target-group): Request group, create it
+       not successful.
+
+2003-01-08  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el (bbdb-records): Fbind it for both Emacs and XEmacs.
+
+2003-01-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-ifile): fixed the spam-ifile-all-categories
+       logic, finally
+
+2003-01-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-spec.el (gnus-parse-format): %C is a complex format.
+       (gnus-parse-format): Change to %~.
+
+       * message.el (message-generate-headers): Don't generate optional
+       empty headers.
+
+2003-01-07  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-cross-post-default)
+       (message-cross-post-note-function, message-shoot-gnksa-feet)
+       (message-strip-subject-trailing-was, message-change-subject)
+       (message-mark-insert-file, message-cross-post-followup-to)
+       (message-cross-post-followup-to, message-mode-map)
+       (message-generate-unsubscribed-mail-followup-to)
+       (message-make-mail-followup-to): Minor changes to doc-strings and
+       error messages.  Updated copyright line.
+
+       * message.el (message-make-mail-followup-to,
+       message-generate-unsubscribed-mail-followup-to): New function
+       names.  Renamed functions: "-mft" -> "-mail-followup-to".
+       (message-make-mft, message-gen-unsubscribed-mft): Removed function
+       names.
+
+       * mml.el (mml-preview-insert-mail-followup-to): New function name.
+       (mml-preview-insert-mft): Removed function name.
+       (mml-preview): Use new function names.
+
+       * gnus-art.el (gnus-article-edit-mode-map): Use new function names.
+
+       * message.el (message-mode-field-menu): Moved header related
+       commands from "Message" to "Field" menu.
+
+2003-01-07  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-generate-headers-first): Added customization
+       if variable is a list.
+
+2003-01-07  Michael Shields  <shields@msrl.com>
+
+       * gnus-art.el (gnus-article-next-page): Correctly handle the case
+       where the last line of the article is the last line of the window.
+
+2003-01-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-debug): Use ignore-errors.
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Use
+       `gnus-summary-update-line'.
+
+2003-01-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-unbuttonized-mime-types)
+       (gnus-buttonized-mime-types): Doc fix.
+
+2003-01-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-decode.el (mm-inline-media-tests): .xpm is 'x-xpixmap'.
+
+2003-01-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-group-alist): Add and clear up.
+
+2003-01-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: removed unnecessary condition-case for loading bbdb-com.el
+
+       * lpath.el (bbdb-search): added BBDB functions for a better way to
+       fix missing functions
+
+       * spam.el (spam-check-ifile): if should be an unless
+
+       * spam.el: define 'ignore alias for spam-BBDB-register-routine,
+       spam-enter-ham-BBDB, and bbdb-create-internal initially to hush up warnings
+       (spam-ifile-all-categories): doc string fixed to be less than 80 chars
+
+2003-01-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Added
+       gnus-summary-refer-thread to thread menu.
+
+2003-01-07  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): When fetching within a
+       summary buffer, articles that cannot be fetched are marked as
+       canceled.
+
+       * nntp.el (nntp-with-open-group): The quit signal handler must
+       propagate the quit signal to the next outer handler so that the
+       caller knows that the request aborted abnormally.
+
+2003-01-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-check-ifile, spam-ifile-register-with-ifile)
+       (spam-ifile-register-spam-routine)
+       (spam-ifile-register-ham-routine): added ifile functionality that
+       does not use ifile-gnus.el to classify and register articles
+       (spam-get-article-as-string): convenience function
+       (spam-summary-prepare-exit): added ifile spam and ham registration
+       (spam-ifile-all-categories, spam-ifile-spam-category)
+       (spam-ifile-path, spam-ifile): added customization options
+
+       * gnus.el (gnus-group-ham-exit-processor-ifile): added ifile ham
+       exit processor
+       (spam-process): added gnus-group-ham-exit-processor-ifile to the
+       list of choices
+
+2003-01-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-followup): Also score immediate
+       followups.
+
+2003-01-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnweb.el (nnweb-asynchronous-p): Changed to nil.
+
+2003-01-07  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-mode-menu): Fix receipt balloon help.
+
+2003-01-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-msg.el (gnus-group-post-news): Don't assume that "" will
+       always be interpreted as news.
+
+2003-01-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sieve.el (gnus-sieve-script): Use the crosspost argument to
+       gnus-sieve-script, instead of the global variable
+       gnus-sieve-crosspost.  One-line patch from Steinar Bang
+       <sb@dod.no>.
+
+2003-01-06  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus.el: Renamed gnus-summary-*-uncached-face as
+       gnus-summary-*-undownloaded-face to avoid confusing the agent with
+       the cache.
+
+       * gnus-sum.el: Ditto.
+
+2003-01-06  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-group): Modified to permit execution
+       in either the group or summary buffer.
+       New command "JS", in summary buffer, will fetch articles per the
+       group's category, predicate, and processable flags.
+       (gnus-agent-summary-fetch-series): Rewritten to call
+       gnus-agent-session-fetch-group once with all articles in the
+       series.
+       (gnus-agent-summary-fetch-group): Fixed bug and modified code to
+       return list of fetched articles.
+       (gnus-agent-fetch-articles): Split fetch list into sublists such
+       that the article buffer is only slightly larger than
+       gnus-agent-max-fetch-size.  Added unwind-protect to ensure that
+       the group's article alist is saved.
+       (gnus-agent-fetch-headers): The 'killed' and 'cached' marks no
+       longer result in the agent trying to fetch an article.
+       (gnus-agent-fetch-group-1): Can now be called in either the group
+       or summary buffer.  Removed the max-fetch-size code that I added
+       on 2002-12-13 as that capability is now part of
+       gnus-agent-fetch-articles.  Added code to update summary buffer.
+       When called in the group buffer, articles that can not be fetched
+       are AUTOMATICALLY MARKED AS READ.
+
+       * gnus-sum.el (): Modified eval-when-compile to minimize
+       misleading compilation warnings.
+       (gnus-update-summary-mark-positions): Changed code to use
+       gnus-undownloaded-mark rather than gnus-downloaded-mark.
+
+       * nnheader.el (nnheader-insert-nov-file): Do not try to insert an
+       empty file as the parser assumes that the file isn't empty.
+
+       * nntp.el (nntp-send-string): The process-send-string call can,
+       because it performs I/O on the process, change the process' state
+       from open to closed.  If this happens, call nntp-report
+       immediately to report the broken connection.
+       (nntp-report): Rewritten to avoid needing a global variable to
+       determine the appropriate course of action.  Instead, two function
+       implementations are provided and the nntp-report function value is
+       bound to the appropriate implementation.
+       (nntp-retrieve-data): Moved nntp-report call to end of implementation.
+       (nntp-with-open-group): Now binds nntp-report's function cell
+       rather than binding gnus-with-open-group-first-pass.  Added a
+       condition-case to detect a quit during a nntp command.  When the
+       quit occurs, the current connection is closed as a fetch articles
+       request could have several megabytes queued up for reading.
+       (nntp-retrieve-headers): Bind articles to itself.  If
+       nntp-with-open-group repeats this command, I must have access to
+       the original list of articles.
+       (nntp-retrieve-groups): Ditto for groups.
+       (nntp-retrieve-articles): Ditto for articles.
+       (*): Replaced nntp-possibly-change-group calls to
+       nntp-with-open-group forms in all, but one, occurrance.
+       (nntp-accept-process-output): Bug fix. Detect when called with
+       null process.
+
+2003-01-06  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-util.el (mm-find-mime-charset-region): Don't do Latin-9 hack
+       if we don't need to.
+       (mm-iso-8859-x-to-15-region): Fix misplaced parenthesis.
+
+2003-01-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-make-web-group): Pass the select
+       method on to group-create.
+       (gnus-group-line-format-alist): %U is an integer.
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Don't update
+       ephemeral groups.
+       (gnus-summary-read-group-1): Ditto.
+       (gnus-group-make-articles-read): Ditto.
+
+       * mm-url.el (mm-url-program): Doc fix.
+
+       * message.el (message-mode-map): Rebound
+       message-insert-wide-reply.
+
+2003-01-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-xmas.el (gnus-xmas-group-startup-message): Bind the oort
+       color as `gnus-group-startup-message' does.
+
+2003-01-05  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: fixed line lengths to 80 chars or less
+
+       * gnus-sum.el (gnus-read-mark-p): added the spam-mark as a
+       "not-read" mark
+       (gnus-summary-mark-forward): added the spam-mark to the list of
+       marks not to be marked as "read" when viewed
+
+2003-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-inews-make-draft): Quote article-reply.
+
+       * gnus-group.el (gnus-number-of-unseen-articles-in-group):
+       Protect against unactive groups.
+
+       * message.el (message-check-news-header-syntax): Check long
+       header lines.
+       (message-check-news-header-syntax): Update `start'.
+
+       * gnus-group.el (gnus-group-expire-articles): Doc fix.
+       (gnus-group-line-format): %U.
+       (gnus-group-line-format-alist): ?U.
+       (gnus-number-of-unseen-articles-in-group): New function.
+
+       * nntp.el (nntp-accept-process-output): Use a 0.1 second timeout.
+
+       * gnus.el (gnus-version-number): Bump version number.
+
+2003-01-05 01:53:30 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.10 is released.
+
+2003-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Fix version number.
+
+2003-01-05 01:40:09 Lars Magne Ingebrigtsen <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.08 is released.
+
+2003-01-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-util.el: Add mm-string-make-unibyte.
+
+       * gnus-group.el (gnus-group-jump-to-group): Make it work for
+       UTF-8 groups.
+
+2003-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-variable-list): Write gnus-format-specs last.
+
+       * gnus-sum.el (gnus-summary-goto-subjects): Fix typo.
+
+2003-01-04  Kevin Ryde  <user42@zip.com.au>
+
+       * gnus-art.el (gnus-mime-jka-compr-maybe-uncompress): New
+       function.
+
+2003-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-exit): Bind gnus-group-is-exiting-p.
+       (gnus-summary-read-group-1): Update group line.
+       (gnus-summary-exit-no-update): Update group on exit.
+
+       * gnus-group.el (gnus-group-line-format): Add %*.
+       (gnus-group-line-format-alist): Ditto.
+       (gnus-group-insert-group-line): Set it.
+       (gnus-group-is-exiting-p): New variable.
+       (gnus-group-insert-group-line): Use it.
+
+2003-01-03  Teodor Zlatanov  <tzz@beld.net>
+
+       * spam.el (spam-enter-ham-BBDB, spam-BBDB-register-routine):
+       enable BBDB ham processing
+       (spam-blacklist-register-routine): enable blacklist spam processing
+       (spam-whitelist-register-routine): enable whitelist ham processing
+       (spam-fetch-field-from-fast): fast fetching of the "from" field
+       from (gnus-data-list)
+       (spam-summary-prepare-exit): works completely now
+       (spam-use-blacklist): oops, should be nil by default
+       (spam-summary-prepare-exit): spam-use-PROCESSOR is only for
+       split processing now; before it was for summary exit as
+       well but that's done with the spam-contents and spam-process
+       parameters now
+
+2003-01-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * mml.el (mml-insert-tag): Don't quote non-ASCII unibyte
+       characters.
+
+2003-01-02  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-group-spam-contents-p, spam-group-ham-contents-p)
+       (spam-group-processor-p, spam-group-processor-bogofilter-p)
+       (spam-group-processor-ifile-p, spam-group-processor-blacklist-p)
+       (spam-group-processor-whitelist-p, spam-group-processor-BBDB-p)
+       (spam-mark-spam-as-expired-and-move-routine)
+       (spam-generic-register-routine, spam-BBDB-register-routine)
+       (spam-ifile-register-routine, spam-blacklist-register-routine)
+       (spam-whitelist-register-routine): new functions
+       (spam-summary-prepare-exit): added summary exit processing (expire
+       or move) of spam-marked articles for spam groups; added slots for
+       all the spam-*-register-routine functions
+
+2003-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * pop3.el (pop3-retr): Wait 500 msecs.
+       (pop3-read-response): Ditto.
+
+       * gnus-msg.el (gnus-setup-message): Get the evaliation order
+       right.
+       (gnus-inews-make-draft): New function.
+       (gnus-setup-message): Use it.
+
+       * message.el (message-required-headers): Add From.
+
+2003-01-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Trivial patch from Norbert Koch <nk@viteno.net>.
+
+       * gnus-msg.el (gnus-gcc-externalize-attachments): Fix typo.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-generate-headers): Let header formatters do
+       their work.
+
+2003-01-02  Raymond Scholz  <ray-2003@zonix.de>
+
+       * deuglify.el (gnus-article-outlook-deuglify-article):
+       Rehighlight, reapply treatments and call
+       `gnus-article-prepare-hook'.  Suggested by Niels Olof Bouvin.
+       (gnus-outlook-repair-attribution-block): Recognize cited
+       attributions.  Suggested by Niklas Morberg.
+
+2003-01-02  Pete Kazmier  <pete@kazmier.com>
+
+       * gnus-art.el (gnus-treat-predicate): Check condition first.
+
+2003-01-02  Jesper Harder  <harder@ifa.au.dk>
+
+       * lpath.el: Add url-http-file-exists-p.
+
+       * gnus-group.el (gnus-group-fetch-charter): Use
+       http://TLH.news-admin.org/charters/GROUPNAME as a fallback.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-draft-headers): Also generate From to get a
+       nicer draft buffer summary.
+
+       * gnus-xmas.el (gnus-xmas-read-event-char): Take an optional
+       parameter.
+
+       * gnus-art.el (article-wash-html): Clean up.
+       (article-wash-html): Typo fix.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Clean up.
+       (gnus-summary-mail-forward): To many lists of lists.
+
+       * gnus-art.el (article-wash-html): Clean up.
+
+2003-01-02  pete-temp  <pete-temp-12-29-2002@kazmier.com>
+
+       * gnus-art.el (gnus-treat-wash-html): New variable.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-check-news-header-syntax): Allow posting.
+       (message-check-news-header-syntax): Fix logic for sure, this
+       time.
+
+2003-01-02  Matthieu Moy  <Matthieu.Moy@imag.fr>
+
+       * message.el (message-check-news-header-syntax): Check syntax of
+       continuation headers.
+
+2003-01-02  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-url-regexp,
+       (gnus-button-mid-or-mail-regexp, gnus-button-alist,
+       (gnus-header-button-alist): Regexps are case insensitive here.
+
+2003-01-02  Simon Josefsson  <jas@extundo.com>
+
+       * dig.el (query-dig): Doc fix.
+
+2003-01-02  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Update whole
+       summary buffer line, not just the download mark.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-goto-subjects): New function.
+       (gnus-summary-insert-dormant-articles): New command and
+       keystroke.
+
+       * gnus-cache.el (gnus-summary-insert-cached-articles): Use new
+       function for mass insertion of subjects.
+
+       * nndraft.el (nndraft-generate-headers): Don't move point.
+
+       * gnus.el (nnheader): Require nnheader.
+
+       * nndraft.el (nndraft-request-associate-buffer): Use
+       make-local-variable.
+
+2003-01-02  Michael Shields  <shields@msrl.com>
+
+       * nndraft.el (nndraft-request-associate-buffer): Make
+       write-contents-hooks buffer-local before setting it.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-group-parameter-value): Take an extra param.
+       (gnus-group-fast-parameter): Let group param results be nil.
+
+       * gnus-art.el (gnus-article-forward-header): New function.
+       (article-date-ut): Use it to remove continuation date headers.
+
+       * gnus-sum.el (gnus-summary-walk-group-buffer): Supply prompt to
+       read-event.
+       (gnus-summary-remove-bookmark): Clean up.
+       (gnus-summary-set-bookmark): Clean up.
+
+       * gnus-util.el (gnus-read-event-char): Take an optional prompt.
+
+       * gnus.el (gnus-group-startup-message): Bind data-directory to
+       the Gnus etc directory.
+
+2003-01-01  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-summary-prepare-exit): added slots for spam- and
+       ham-processing of articles; use the new
+       spam-group-(spam|ham)-contents-p functions
+       (spam-group-spam-contents-p, spam-group-ham-contents-p): new
+       convenience functions
+       (spam-mark-junk-as-spam-routine): use the new
+       spam-group-spam-contents-p function
+
+       * gnus.el (spam-process, spam-contents, spam-process-destination):
+       added new parameters with corresponding global variables
+       (gnus-group-spam-exit-processor-ifile,
+       gnus-group-spam-exit-processor-bogofilter,
+       gnus-group-spam-exit-processor-blacklist,
+       gnus-group-spam-exit-processor-whitelist,
+       gnus-group-spam-exit-processor-BBDB,
+       gnus-group-spam-classification-spam,
+       gnus-group-spam-classification-ham): added new symbols for the
+       spam-process and spam-contents parameters
+
+       * spam.el (spam-ham-marks, spam-spam-marks): changed list
+       customization and list itself to store mark symbol rather than
+       mark character.
+       (spam-bogofilter-register-routine): added logic to generate mark
+       values list from spam-ham-marks and spam-spam-marks, so (member)
+       would work.
+
+2003-01-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-cross-post-followup-to): Fix comment.
+
+2003-01-01  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-ham-marks, spam-spam-marks): changed list
+       customization and list itself to store mark symbol rather than
+       mark character.
+       (spam-bogofilter-register-routine): added logic to generate mark
+       values list from spam-ham-marks and spam-spam-marks, so (member)
+       would work.
+
+2003-01-01  Raymond Scholz  <ray-2002@zonix.de>
+
+       * message.el (message-signature-insert-empty-line): New variable.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el: Renamed functions and variables: "xpost" ->
+       "cross-post", "-fup2" -> "-followup-to".
+       (message-cross-post-old-target, message-cross-post-default,
+       message-cross-post-note, message-followup-to-note,
+       message-cross-post-note-function): New variables names.
+       (message-xpost-old-target, message-xpost-default,
+       message-xpost-note, message-fup2-note,
+       message-xpost-note-function): Removed variable names.
+       (message-cross-post-followup-to-header,
+       message-cross-post-insert-note, message-cross-post-followup-to):
+       New function names.
+       (message-xpost-fup2-header, message-xpost-insert-note,
+       message-xpost-fup2): Removed function names.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-send-mail): Added message-cleanup-headers to
+       prevent newlines in headers.
+
+2003-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * dns.el (dns-make-network-process): Comment.
+
+       * gnus-sum.el (gnus-summary-display-while-building): Default to
+       nil.
+
+2003-01-01  Wes Hardaker  <wes@hardakers.net>
+
+       * gnus-sum.el (gnus-summary-display-while-building): New
+       variable.
+
+2003-01-01  Raymond Scholz  <ray-2003@zonix.de>
+
+       * deuglify.el (gnus-outlook-rearrange-article): Kill overlays
+       before rearranging the article.
+
+2003-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nndraft.el (nndraft-generate-headers): New function.
+       (nndraft-request-associate-buffer): Use it to write headers on
+       buffer save.
+
+       * message.el (message-generate-headers): Let the function be a
+       lambda form.
+       (message-draft-headers): New variable.
+
+       * gnus-msg.el (gnus-inews-make-draft-meta-information): New
+       function.
+       (gnus-setup-message): Use it.
+
+       * message.el (message-generate-headers-first): Doc fix.
+       (message-setup-1): Use new function for getting which headers to
+       generate.
+       (message-headers-to-generate): New function.
+
+2003-01-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-save-alist): Make directory.
+
+2002-12-31  Reiner Steib  <4uce.02.r.steib@gmx.net>
+
+       * gnus-sum.el (gnus-summary-limit-to-age): Make prompt string
+       mention negatives.
+
+2002-12-31  Raymond Scholz  <ray-2002@zonix.de>
+
+       * deuglify.el (gnus-outlook-rearrange-article): Use
+       `transpose-regions' instead of tempering the kill-ring.
+       (gnus-article-outlook-deuglify-article): Rehighlight article
+       instead of a complete redisplay.
+
+2002-12-31  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el: most defvars are defcustoms now
+
+       patches from Michael Shields  <shields@msrl.com>
+
+       * spam.el (spam-bogofilter-articles): Select the article
+       body using gnus-summary-show-article t instead of
+       gnus-summary-select-article; this presents the raw text
+       without running any hooks.
+
+       * spam.el (spam-bogofilter-articles): Use message-remove-header
+       to remove headers; the old way incorrectly removed just the first
+       line of folded headers.
+
+2002-12-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-load): Replace `ding-file' with `file'.
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-load): New function.
+       (gnus-read-newsrc-el-file): Use it.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-art.el (gnus-button-valid-fqdn-regexp): New variable.
+       (gnus-button-handle-apropos-documentation): New function.
+       (gnus-button-handle-ctan): New function.
+       (gnus-button-alist): Use them.  Improve some regexps.
+       (gnus-button-prefer-mid-or-mail): Addition to doc-string.
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-subscribed-p): New function.
+       (message-send-mail): Use it.
+       * mml.el (mml-preview-insert-mft): New function.
+       (mml-preview): Use it.
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-thread-latest-date): Protect against errors
+       when sorting by date.
+
+       * gnus-art.el (gnus-article-edit-mode): New variable.
+       (gnus-article-setup-buffer): Warn user about discarding edits.
+
+       * gnus-sum.el (gnus-summary-pipe-output): Clean up.
+       (gnus-summary-pipe-output): Take a symbolic prefix to save all
+       headers.
+
+       * mm-uu.el (mm-uu-configure-list): Default to (shar . disabled).
+
+2002-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.el (message-completion-alist): Added "Mail-Followup-To"
+       and "Mail-Copies-To".
+
+2002-07-21  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus-group.el: Add key bindings for
+       gnus-group-sort-groups-by-real-name and
+       gnus-group-sort-selected-groups-by-real-name.
+
+2002-07-21  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Sorting Groups): Add key bindings for
+       gnus-group-sort-groups-by-real-name and
+       gnus-group-sort-selected-groups-by-real-name.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-use-dig): new variable for blackhole checking
+       through dig.el
+       (spam-check-blackholes): added dig.el checking functionality and
+       more verbose reporting; query-dig is autoloaded from dig.el
+       (spam-use-blackholes): disabled by default
+       (spam-blackhole-servers): removed rbl.maps.vix.com from the
+       blackhole servers list
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-required-headers): New variable.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * dig.el (query-dig): new function
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * flow-fill.el (fill-flowed): Don't infloop on too long fill
+       prefixes.
+
+       * dns.el (query-dns): Protect against errors.
+
+       * gnus-msg.el (gnus-article-yanked-articles): New variable.
+       (gnus-inews-add-send-actions): Mark all answered messages as
+       answered.
+
+2002-08-10  Jari Aalto  <jari.aalto@poboxes.com>
+
+       * nnmail.el (nnmail-split-it): Added tracing to
+       `:' split rule
+
+2002-08-13  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * mm-decode.el (mm-mailcap-command): Remove the quotes around '%s'
+       and "%s" so we don't overquote them.
+
+2002-08-13  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * (mm-display-external): Display the actual command that has been
+       executed in the echo area.
+
+2002-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-display-missing-topic): Bind entry.
+
+       * message.el (message-with-reply-buffer): New macro.
+       (message-fetch-reply-field): Use it.
+       (message-insert-wide-reply): New command and keystroke.
+       (message-carefully-insert-headers): New function.
+       (message-insert-to): Use new function.
+
+       * gnus-topic.el (gnus-topic-display-missing-topic): New function.
+       (gnus-topic-goto-missing-group): Use it.
+
+       * message.el (message-required-news-headers): Removed Lines.
+       (message-reply): Don't insert References first.
+       (message-followup): Ditto.
+       (message-make-references): New function.
+       (message-followup): Set message-reply-headers before generating
+       the buffer stuff.
+
+2002-12-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * mml.el (mml-generate-mime-1): Reverse the order of
+       encoding/flowing.
+
+2002-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-expiry-target-group): Mark articles as read
+       after moving them.
+
+       * gnus-sum.el (gnus-summary-dummy-line-format): Update format to
+       fit with newer standard format.
+       (gnus-summary-make-false-root-always): New variable.
+       (gnus-gather-threads-by-subject): Use it.
+
+       * message.el (message-get-reply-headers): Take an address list
+       optional argument.
+
+2002-12-28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-keep-backlog): Change default to 20.
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): Start from
+       start.
+       (gnus-agent-check-overview-buffer): Remove negative article
+       numbers.
+
+       * nnmail.el (nnmail-split-fancy-with-parent-ignore-groups): Doc fix.
+       (nnmail-cache-ignore-groups): Doc fix.
+
+       * nnimap.el (nnimap-debug): Made into a flag and defcustomed.
+       (nnimap-debug-buffer): New variable.
+       (nnimap-debug): Use it.
+
+2002-12-28  Lars Magne Ingebrigtsen  <kgreiner@xpediantsolutions.com>
+
+       * gnus.el (gnus-summary-high-uncached-face): New color scheme.
+
+2002-12-28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): Sort lines if
+       they aren't already sorted.
+
+2002-12-28  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-mode-menu): Add ellipses to menu items
+       expecting user interaction.
+       (message-mode-field-menu): do.
+
+2002-12-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-highlight-line): Don't bind `list' --
+       it isn't used any more.
+
+2002-12-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * binhex.el (binhex-decoder-program): Fix docstring.
+
+2002-12-21  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * mm-decode.el (mm-mailcap-command): Do not backslash-quote
+       special chars if the mailcap file uses single quotes around %s.
+       From Laurent Martelli <laurent@bearteam.org>.
+
+2002-12-19  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-int.el (gnus-request-update-info): nnchoke-r-u-i might not
+       return the info object.
+
+2002-12-18  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-int.el (gnus-request-update-info): Artificially add
+       (1 . (1- min)) to the read range, in case the backend doesn't
+       store marks for nonexistent articles.
+
+2002-12-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * binhex.el (binhex-insert-char): Eval-and-compile.
+
+2002-12-17  Jesper Harder  <harder@ifa.au.dk>
+
+       * lpath.el: Add tool-bar-local-item-from-menu.
+
+       * message.el (message-tool-bar-local-item-from-menu): New function.
+       (message-tool-bar-map): Use it.
+
+2002-12-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-uu.el (gnus-uu-digest-headers): Mention nil value in docstring.
+
+       * gnus-art.el (gnus-article-header-rank): Last header in
+       gnus-sorted-header-list should have higher rank than non-members.
+
+2002-12-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-close-agent): Don't blank out the list of
+       covered methods.
+
+2002-12-12  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * nntp.el (nntp-with-open-group-first-pass): Do not wrap in
+       eval-when-compile.  Suggested by Kevin Greiner.
+
+2002-12-13  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-max-fetch-size): New, defcustom.
+       (gnus-agent-fetch-headers): Initialize gnus-agent-overview-buffer
+       even though no headers may have been fetched
+       (gnus-agent-fetch-group-1, and perhaps others, require this
+       behavior).
+       (gnus-agent-fetch-group-1): Fetch articles in chucks so that the
+       server buffer is constrained by gnus-agent-max-fetch-size.
+       Multiple chunks in the same group may perform arbitrarily large
+       updates.
+
+2002-12-12  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Added call to
+       gnus-summary-update-download-mark to update the article in the
+       summary.
+
+2002-12-11  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus.el (gnus-summary-high-uncached-face,
+       gnus-summary-normal-uncached-face, gnus-summary-low-uncached-face)
+       New faces.
+
+       * gnus-agent.el (gnus-agent-downloaded-article-face): REMOVED.  I
+       added this on 2002-11-23 but it just wasn't working out as
+       intended.  The idea isn't entirely dead, three new faces
+       gnus-summary-*-uncached-face are being added to gnus.el to provide
+       the basis for an improved implementation.
+       (gnus-agent-read-servers): Undo the change made on 2002-11-23. The
+       proper file to open is lib/servers.
+       (gnus-summary-set-agent-mark): Expanded documentation.  Unmarking
+       (i.e. removing the article from gnus-newsgroup-downloadable) will
+       now restore the article's default mark rather than simply setting
+       no mark.
+       (gnus-agent-get-undownloaded-list): Corrected documentation.
+       Added code to set new summary local variable,
+       gnus-newsgroup-agentized.  Reworked impl so that it doesn't create
+       a temporary list.  No longer sets gnus-newsgroup-downloadable.
+       (gnus-agent-summary-fetch-group): Keep gnus-newsgroup-undownloaded
+       up to date.  Call new gnus-summary-update-download-mark to keep
+       summary buffer up-to-date.
+       (gnus-agent-fetch-selected-article): Keep
+       gnus-newsgroup-undownloaded up to date.
+       (gnus-agent-fetch-articles): Return list of articles that were
+       successfully fetched.
+       (gnus-agent-check-overview-buffer): No more thingatpt.
+       (gnus-agent-expire): No longer deletes NOV entries of unread
+       articles.
+       (gnus-agent-unread-articles): New function.
+       (gnus-agent-regenerate-group): The article number must be
+       terminated by a tab character.  Added more messages to report
+       repairs.  Inhibit quits while writing changes so it is now safe
+       have to quit regeneration.  Renamed gnus-tmp-downloaded back to
+       downloaded to 1) resolve the unbound references and 2) avoid
+       confusing this list with the gnus-tmp-downloaded in gnus-sum.el
+
+       * gnus-art.el (gnus-article-prepare): The agent
+       downloaded/undownloaded mark is no longer stored as the article's
+       mark.
+
+       * gnus-salt.el (gnus-tree-highlight-node): Added uncached as
+       gnus-summary-highlight may use it.  Added downloaded as
+       gnus-summary-highlight was using it.
+
+       * gnus-sum.el (gnus-undownloaded-mark): Changed from ?@ to ?- as
+       the download mark now follows Kai's +/- convention.
+       (gnus-downloaded-mark): Added ?+ mark.
+       (gnus-summary-highlight): Added rules to select
+       gnus-summary-high-uncached-face,
+       gnus-summary-normal-uncached-face, and
+       gnus-summary-low-uncached-face.  Removed the
+       gnus-agent-downloaded-article-face.
+       (gnus-summary-line-format-alist): Implemented the download flag
+       format (?O) as named in the manual.  This implementation displays
+       either gnus-undownloaded-mark, gnus-downloaded-mark, or
+       gnus-no-mark.
+       (gnus-newsgroup-agentized): New local variable that identifies
+       which groups are agentized.  While the agent is now on by default,
+       you don't have to agentize every server that you use.
+       (gnus-update-summary-mark-positions): Completed support for the
+       download type of mark.
+       (gnus-summary-insert-line): Added undownloaded to the parameters.
+       (gnus-summary-prepare-threads): Set gnus-tmp-downloaded for
+       reference by the gnus-summary-line-format-spec.
+
+       * nntp.el (nntp-with-open-group): This macro handles dropped or
+       broken connections by opening a new connection and repeating the
+       failed command.
+       (nntp-retrieve-headers-with-xover): Some NNTP servers respond to
+       XOVER commands preceeding the active articles with the nov entry
+       of the first available article.  When gnus connected to such a
+       server, the unexpected nov entry would result in duplicate lines
+       in the agent's overview file.  This patch fixes the duplicate
+       lines problem and improves performance by skipping over all
+       articles IDs that preceed the first nov entry in the server's
+       reply.
+
+2002-12-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-tmp-downloaded): New internal variable.
+       (gnus-summary-highlight): Use it instead of `downloaded'.
+       (gnus-summary-highlight-line): Ditto.
+
+       * gnus-agent.el (gnus-agent-regenerate-group): Ditto.
+
+2002-12-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-variable-list): Add gnus-agent-covered-methods.
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): Remove debug
+       calls.
+
+       * gnus-sum.el (gnus-summary-highlight-line): Don't set the
+       downloaded variable if we're in an uncovered group.
+
+       * gnus-agent.el (gnus-agent-downloaded-article-face): Change the
+       font to soemthing less noticeable.
+       (gnus-agent-group-covered-p): New function.
+
+2002-12-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-braid-nov): Remove corrupted lines.
+       Because of an unknown bug, the group buffer is saved in .overview
+       file.
+
+2002-12-09  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * nntp.el (nntp-send-command): Braino in last commit.  Replace
+       `and' with `or'.
+
+2002-12-08  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * nntp.el (nntp-send-command): Assume that echo does not happen
+       when nntp-open-connection-function is nntp-open-network-stream.
+       Suggested by Sebastian D.B. Krause <krause@my.gnus.org>.
+
+2002-12-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-retrieve-headers-1): Update the parser.
+
+2002-12-06  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-group): bugfix: don't erase
+       nntp-server-buffer if we aren't going to write to it.
+
+2002-12-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Trivial patch from Itai Zukerman <zukerman@math-hat.com>.
+
+       * mm-decode.el (mm-w3m-safe-url-regexp): Fix parenthesis.
+
+2002-12-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * rfc2047.el (rfc2047-decode-region): Remove newlines between
+       decoded words.
+
+2002-12-03  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.el (fboundp): After loading mm-util, make sure it was the
+       right one.
+
+2002-11-29  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-art.el (gnus-inhibit-mime-unbuttonizing): Moved here from
+       gnus-sum.  Made into a user option.
+
+       * gnus-sum.el (gnus-simplify-ignored-prefixes)
+       (gnus-summary-mark-article-as-unread)
+
+2002-11-29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * time-date.el (date-to-time): Typo.
+
+       * parse-time.el: Typo.
+
+       * nnsoup.el (nnsoup-retrieve-headers): Typo.
+
+       * nnmail.el (nnmail-split, nnmail-process-unix-mail-format): Typos.
+
+       * nnimap.el:
+       (nnimap-split-rule, nnimap-find-minmax-uid): Typos.
+
+       * mm-encode.el (mm-safer-encoding): Typo.
+
+       * messcompat.el: Typo.
+
+       * message.el (message-face-alist): Typo.
+
+       * imap.el (imap-interactive-login, imap-open): Typos.
+
+       * ietf-drums.el (ietf-drums-text-token, ietf-drums-qtext-token): Typos.
+
+       * gnus.el: Typo.
+
+       * gnus-win.el (gnus-configure-frame): Typo.
+
+       * gnus-util.el (gnus-atomic-progn-assign): Typo.
+
+       * gnus-topic.el (gnus-topic-sort-topics): Typo.
+
+       * gnus-sum.el (gnus-summary-article-number)
+       (gnus-summary-read-group-1, gnus-summary-mark-article)
+       (gnus-summary-fetch-faq, gnus-refer-article-methods): Typos.
+
+       * gnus-mule.el (gnus-mule-add-group): Typo.
+
+       * gnus-mlspl.el (gnus-group-split-fancy): Typo.
+
+       * gnus-group.el (gnus-group-fetch-faq): Typo.
+
+       * gnus-art.el (gnus-decode-header-methods): Typo.
+
+       * flow-fill.el: Typo.
+
+2002-11-19  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * binhex.el (binhex-decode-region): Don't hardcode point-min == 1.
+
+2002-11-29  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-sum.el (gnus-simplify-ignored-prefixes)
+       (gnus-summary-mark-article-as-unread)
+       (gnus-mark-article-as-unread, gnus-summary-highlight-line):
+       Reformatting to avoid long lines.
+       (gnus-inhibit-mime-unbuttonizing): Moved to gnus-art.
+
+2002-11-28  Daiki Ueno  <ueno@unixuser.org>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Article numbers should
+       be accessed through `mail-header-number'.
+
+2002-11-27  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus-sum.el (gnus-summary-insert-old-articles): No longer passes
+       compressed range to gnus-summary-insert-articles.
+
+2002-11-26  Kevin Ryde <user42@zip.com.au>
+
+       * gnus-art.el (gnus-mime-copy-part): Look for filename
+       parameter under content-disposition, not content-type.
+
+       * gnus-sum.el (gnus-summary-find-uncancelled): New function.
+       (gnus-summary-reselect-current-group): Use it.
+
+2002-11-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-uncached-articles): if
+       gnus-agent-load-alist fails, return ARTICLES.
+
+       * nnrss.el (nnrss-group-alist): Update the link of Jabber.
+
+2002-11-26  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-sum.el (gnus-summary-insert-old-articles): Remove
+       superfluous function call.
+       (gnus-summary-catchup-all, gnus-summary-catchup-all-and-exit):
+       Add warning to docstring.
+
+2002-11-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-agent.el: Autoload number-at-point instead.
+       (gnus-agent-check-overview-buffer): No warning for deactivate-mark.
+
+2002-11-26  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): Explicitly
+       require thingatpt (for number-at-point) and protect against
+       deactivate-mark being unbound (on XEmacs).
+
+2002-11-25  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-check-overview-buffer): Make debugger
+       print message on entry.
+
+       From Kevin Greiner <kgreiner@xpediantsolutions.com>.
+
+       * gnus-range.el (gnus-range-difference): New function.
+       * gnus-sum.el (gnus-summary-insert-old-articles): Use it.
+
+2002-11-24  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-sum.el (gnus-summary-insert-old-articles): Use
+       gnus-remove-from-range instead of gnus-range-difference which
+       doesn't exist.
+
+2002-11-23  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+       From Kevin Greiner <kgreiner@xpediantsolutions.com>.
+
+       * gnus-agent.el (gnus-agent-downloaded-article-face): New face,
+       used for showing which articles have been downloaded.
+       (gnus-agent-article-alist): Format change.  Add documentation.
+       (gnus-agent-summary-mode-map): New keybinding `J s' for fetching
+       process-marked articles.
+       (gnus-agent-summary-fetch-series): Command for `J s'.  Articles
+       in the series are individually fetched to minimize lose of
+       content due to an error/quit.
+       (gnus-agent-synchronize-flags-server, gnus-agent-add-server): Use
+       gnus-message instead of message.
+       (gnus-agent-read-servers): Use file lib/methods instead of
+       lib/servers.  TODO: Why?
+       (gnus-summary-set-agent-mark): Adapt to new agent-alist format.
+       (gnus-agent-get-undownloaded-list): Remove articles that appear to
+       come from the agent.  This means that they are not downloaded.
+       (gnus-agent-fetch-selected-article): Don't use history.
+       (gnus-agent-save-history, gnus-agent-enter-history)
+       (gnus-agent-article-in-history-p, gnus-agent-history-path):
+       Removed function; history is not used anymore.
+       (gnus-agent-fetch-articles): Fix handling of crossposted articles.
+       (gnus-agent-crosspost): Started rewrite then realized that a typo
+       in gnus-agent-fetch-articles ensures that this function is never
+       called.  This will need to be fixed later.
+       (gnus-agent-check-overview-buffer): Some sanity checks on the
+       agent overview buffer.  This is a safety net used during
+       development.
+       (gnus-agent-flush-cache): The gnus-agent-article-alist format has
+       changed, write a number to the file indicating this.
+       (gnus-agent-fetch-headers): Rewrite to respect
+       gnus-agent-consider-all-articles without relying on the
+       `.fetched' files.  Make it fast.
+       (gnus-agent-braid-nov): Change resulting from
+       gnus-agent-fetch-headers change.
+       (gnus-agent-load-alist, gnus-agent-save-alist): Don't use
+       `.fetched' files.
+       (gnus-agent-read-agentview): New function, used by
+       gnus-agent-load-alist.
+       (gnus-agent-load-fetched-headers): Remove.
+       (gnus-agent-save-alist): Rewrite to accomodate new format.
+       (gnus-agent-fetch-group-1): Make sure list of articles is in the
+       same order as in gnus-newsgroup-headers.
+       (gnus-agent-expire): Document and implement extra args ARTICLES,
+       GROUP, FORCE.  Do not restrict usage.
+       (gnus-agent-uncached-articles): New function.
+       (gnus-agent-retrieve-headers): Use it.
+       (gnus-agent-regenerate-group): No longer needs to be called from
+       gnus-agent-regenerate.  Individual groups may be regenerated. The
+       regeneration code now fixes duplicate, and mis-ordered, NOV entries.
+       The article fetch dates are validated in the article alist.  The
+       article alist is pruned of entries that do not reference existing
+       NOV entries.  All changes are computed then applied with
+       inhibit-quit bound to t.  As a result, it is now safe to quit out of
+       regeneration.  The optional clean parameter has been replaced with
+       an optional reread parameter.  Clean is no longer necessary as
+       regeneration gets the appropriate setting from
+       gnus-agent-consider-all-articles.  The new reread parameter will
+       result in fetched, or all, articles being marked as unread.
+       (gnus-agent-regenerate): Removed code to regenerate the history
+       file as it is no longer used.
+
+       * gnus-start.el (gnus-make-ascending-articles-unread): New
+       function, for efficient mass-marking.
+
+       * gnus-sum.el (gnus-summary-highlight): Use new face for
+       downloaded articles.
+       (gnus-article-mark): Prefer to indicate read/unread status over
+       downloaded status.
+       (gnus-summary-highlight-line-0): New function, maybe rehighlights
+       line.
+       (gnus-summary-highlight-line): Use new face for downloaded
+       articles.
+       (gnus-summary-insert-old-articles): Improved performance by
+       replacing the initial LIST of older articles with a compressed
+       RANGE of older articles.  Some servers appear to lie about
+       their active range so the original list could contain millions
+       of article numbers.  The range is not expanded into a list
+       until the optional ALL parameter has been applied.
+
+2002-11-18  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-category-mode): Typo in doc string.
+
+2002-11-21  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el:
+       added patch from Andreas Fuchs <asf@void.at> to prevent apply errors
+
+       * spam.el: added `M s t' and `M s x' key mappings
+
+2002-11-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-morse-message): Narrow to body.
+
+2002-11-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-morse-message): Load
+       morse.el (unmorse-region not autoloaded in Emacs 20 nor XEmacs).
+       (unmorse-region): Autoload it instead.
+
+2002-11-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-morse-message): New function.
+       (gnus-summary-wash-map): Bind to `W m'.
+       (gnus-summary-make-menu-bar): Add.
+
+       * nnimap.el (nnimap-request-expire-articles): Compress sequence
+       before storing \Deleted mark on expired articles.
+
+2002-11-17  Shenghuo Zhu <zsh@cs.rochester.edu>
+       Trivial patch from Markus Rost <rost@math.ohio-state.edu>
+
+       * gnus-sum.el (gnus-summary-goto-unread): Doc fix - escape open
+       parens in column 0.
+
+2002-11-17  Juanma Barranquero  <lektu@terra.es>
+
+       * nnweb.el (nnweb-google-create-mapping): Fix typo.
+
+       * nnlistserv.el (nnlistserv-kk-create-mapping): Likewise.
+
+       * gnus-nocem.el (gnus-nocem-liberal-fetch): Likewise.
+
+2002-11-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-set-auto-save-file-name): Use
+       make-directory, to avoid the dependence on gnus-util.
+
+2002-11-16  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-callback-callback-function):
+       (nnimap-callback-buffer): Removed, these cannot be global but must
+       be embedded into the callback.
+       (nnimap-make-callback): New.  Embedd article number, callback and
+       buffer in function.
+       (nnimap-callback, nnimap-request-article-part): Update.
+
+2002-11-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mml.el (mml-preview): Bind message-this-is-mail if it is mail.
+
+2002-11-13  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.el (gnus-summary-line-format): Document %C.
+
+2002-11-11  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.el (pgg-encrypt, pgg-decrypt, pgg-sign, pgg-verify): Display
+       output when called interactively.
+
+2002-11-08  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-edit-exit): Kill local variables.
+
+       * message.el (message-draft-coding-system): Improve comment; use
+       mm-auto-save-coding-system for the default value.
+
+       * nndraft.el (nndraft-request-article): Revert to the state before
+       2002-10-29; regexp-quote mail-header-separator.
+
+2002-11-06  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-draft.el (gnus-draft-setup): Set gnus-message-group-art to
+       allow editing of drafts from an nnvirtual group.
+
+2002-11-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nndraft.el (nndraft-request-article): Replace emacs-mule with
+       mm-auto-save-coding-system.
+
+       * message.el (message-draft-coding-system): Default to
+       iso-2022-7bit.
+
+       * mm-util.el (mm-auto-save-coding-system): Undo last change to
+       restore the default value to emacs-mule or escape-quoted.
+
+2002-11-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-encrypt-body): Inhibit encrypting of
+       a delayed or a queued article as well as a draft.
+
+       * gnus-sum.el (gnus-summary-edit-article): Inhibit editing of a
+       delayed or a queued article in the raw format; treat a delayed
+       article as a raw article as well as a draft.
+       (gnus-summary-setup-default-charset): Clear gnus-newsgroup-charset
+       for the delayed group.
+
+       * nndraft.el (nndraft-request-article): Ignore auto save files for
+       a delayed or a queued article; don't bother to decode a queued
+       article; don't bind nnmail-file-coding-system for a queued article.
+
+       * nnmail.el (nnmail-split-fancy-with-parent): Ignore the delayed
+       and the queue group.
+
+2002-11-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-group.el (gnus-group-delete-group):
+       gnus-cache-active-hashtb might be void.
+
+2002-11-02  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Makes PGG respect the
+       setting of the default user ID.  From Raymond Scholz
+       <ray-2002@zonix.de>.
+
+2002-11-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-bodies.el (mm-body-encoding): Don't return 8bit for 7bit
+       charset.
+
+2002-10-31  Ted Zlatanov <tzz@lifelogs.com>
+       From Alex Schroeder <alex@emacswiki.org>
+       * spam-stat.el (spam-stat-process-directory): add dir to message
+       (spam-stat-reduce-size): No longer remove words
+       with values close to 0.5, because the default value is 0.2.
+
+2002-10-31  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-util.el (gnus-user-date-format-alist): Clarify and correct
+       documentation.
+
+2002-10-28  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-fetched-headers)
+       (gnus-agent-load-fetched-headers)
+       (gnus-agent-save-fetched-headers): Remove variable and two
+       functions.  Kevin Greiner's version of gnus-agent-fetch-headers
+       works better.
+       (gnus-agent-fetch-headers): New implementation from Kevin
+       Greiner.  Uses gnus-agent-article-alist to store information
+       about fetched messages which aren't on the server anymore.  The
+       trick is to return a list of considered messages to the caller,
+       but to only fetch those which haven't been fetched yet.
+
+2002-10-30  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-def.el (pgg-passphrase-cache-expiry): New, defcustom.
+
+       * pgg.el (pgg-passphrase-cache-expiry): Removed.
+
+2002-10-30  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * mm-view.el (mm-w3m-local-map-property): Make it work with older
+       versions of emacs-w3m than 1.3.3.
+
+       * lpath.el: Bind w3m-minor-mode-map.
+
+       * mm-view.el (mm-w3m-mode-command-alist)
+       (mm-w3m-mode-dont-bind-keys, mm-w3m-mode-ignored-keys): Removed.
+       (mm-w3m-mode-map): Undefined for Emacs21 and XEmacs.
+       (mm-setup-w3m): Simplified.
+       (mm-w3m-local-map-property): New function.
+       (mm-inline-text-html-render-with-w3m): Use it.
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Use
+       mm-w3m-local-map-property.
+
+2002-10-29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-util.el (mm-auto-save-coding-system): Default to
+       iso-2022-7bit.
+
+       * nndraft.el (nndraft-request-article): Decode an article using
+       the coding-system emacs-mule if it seems to have been saved using
+       emacs-mule.
+       (nndraft-request-replace-article): Use message-draft-coding-system
+       instead of mm-auto-save-coding-system for the draft or delayed
+       group.
+
+2002-10-28  Josh  <huber@alum.wpi.edu>
+
+       * mml.el (mml-mode-map): Fixed keybindings for mml-secure-*
+       functions.
+
+2002-10-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From mah@everybody.org (Mark A. Hershberger).
+
+       * mm-url.el (mm-url-insert-file-contents): Make it return the same
+       type values ("url" size) regardless of the values of
+       mm-url-use-external.
+
+2002-10-26  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * nnimap.el (nnimap-request-article-part): Try harder to show
+       group name in debugging message.
+
+2002-10-25  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-save-fetched-headers): Create
+       directory if it doesn't exist.
+       (gnus-agent-fetch-headers): Remove old cruft that tried to
+       abstain from downloading articles more than once if
+       gnus-agent-consider-all-articles was true.  This is now done
+       properly via the .fetched files.
+
+2002-10-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nndraft.el (nndraft-request-article): Treat delayed articles
+       like drafts.
+
+2002-10-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-agent.el (gnus-agent-load-alist): Fix parenthesis.
+
+2002-10-24  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-save-alist, gnus-agent-load-alist):
+       Remove unused optional arg DIR and corresponding code.
+
+       * nnimap.el (nnimap-request-article-part): Include group name in
+       debugging output.
+
+2002-10-24  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Add some comments.
+
+2002-10-23  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus-agent.el (gnus-agent-fetched-headers): New variable,
+       contains range of headers that have been fetched by the agent
+       already.  Compare gnus-agent-article-alist.
+       (gnus-agent-file-header-cache): Like
+       gnus-agent-file-loading-cache, but for gnus-agent-fetched-headers.
+       (gnus-agent-fetch-headers): Improve comment.  Revert to old
+       seen/recent logic.
+       Remember which headers have been fetched before and don't fetch
+       them again the next time round.
+       (gnus-agent-load-fetched-headers)
+       (gnus-agent-save-fetched-headers): New functions, for remembering
+       which headers have been fetched before.
+
+2002-10-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Remove useless bindings.
+
+2002-10-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-execute-command): Disable visual
+       features while searching.
+
+2002-10-22  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * pgg.el (pgg-snarf-keys): Do not refer unbinded local variables.
+
+2002-10-22  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.el (pgg-encrypt, pgg-decrypt, pgg-sign, pgg-verify)
+       (pgg-snarf-keys): Add.
+
+2002-10-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Fbind bbdb-records.
+
+       * spam.el: Don't autoload bbdb-records.
+
+2002-10-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * spam.el: Set autoload for bbdb-records after loading bbdb-com to
+       prevent inf-loop.
+
+2002-10-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el: Removed some test lines.
+       More test.
+
+2002-10-21  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Remove articles that
+       are known to be downloaded already.
+
+2002-10-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-text-html-renderer-alist): Add w3m-standalone.
+       (mm-text-html-washer-alist): Ditto.
+
+2002-10-19  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * nnheader.el (nnheader-remove-body): Fix an error of detecting
+       boundary between headers and body.
+       * nnml.el (nnml-parse-head): Ditto.
+
+2002-10-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-generate-active): Ignore any bogus
+       entries.
+
+       * gnus-group.el (gnus-fetch-group): Allow an optional
+       specification of the articles to select.
+
+       * gnus-srvr.el (gnus-server-prepare): Removed superfluous cdr.
+
+2002-10-20  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): After fetching
+       headers from the group, update variable `articles' to contain
+       only those numbers where headers exist.  (When fetching all
+       articles in a group, Gnus creates lots of numbers where there is
+       no articles.)
+
+2002-10-20  Steve Youngs  <youngs@xemacs.org>
+
+       * pgg-parse.el (pgg-parse-public-key-algorithm-alist): XEmacs
+       doesn't have the 'alist custom type, use cons cells instead.
+       (pgg-parse-symmetric-key-algorithm-alist): Ditto.
+       (pgg-parse-hash-algorithm-alist): Ditto.
+       (pgg-parse-compression-algorithm-alist): Ditto.
+       (pgg-parse-signature-type-alist): Ditto.
+
+       * pgg-gpg.el (pgg-gpg-extra-args): Fix custom mismatch.
+
+       * pgg-pgp5.el (pgg-pgp5-extra-args): Ditto.
+
+       * pgg-pgp.el (pgg-pgp-extra-args): Ditto.
+
+2002-10-19  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-open-server): Check imap-state in IMAP server
+       buffer.
+
+2002-10-18  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-spec.el (gnus-make-format-preserve-properties)
+       (gnus-xmas-format, gnus-parse-simple-format): Preserve text
+       properties also on XEmacs.  `gnus-xmas-format' is like format but
+       preserves text properties on XEmacs (though it only understands
+       simple format specs).  The variable
+       `gnus-make-format-preserve-properties' controls whether the
+       function is used, and is checked in `gnus-parse-simple-format'.
+       Patch by Paul Moore <gustav@morpheus.demon.co.uk>.
+
+       * gnus-agent.el (gnus-agent-fetch-articles): More debugging
+       output.
+       (gnus-agent-consider-all-articles): New variable.
+       (gnus-agent-get-undownloaded-list): Comment that marks todo item.
+       (gnus-agent-fetch-headers): Depending on
+       gnus-agent-consider-all-articles, maybe get all articles.
+       (gnus-category-predicate-alist, gnus-agent-read-p): New predicate
+       `read'.
+       (gnus-predicate-imples-unread): New function.
+       (gnus-agent-fetch-headers): Optimize to call
+       gnus-list-of-unread-articles if that is sufficient.
+       Check unseen and recent instead of seen and recent.
+       (gnus-agent-fetch-headers): Abstain from calling
+       gnus-list-range-intersection if range (a . b) would have (> a b).
+
+2002-10-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-send-mail): Make it possible to perform
+       edebug-defun.
+
+2002-10-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-button-man-handler): Change default to
+       `manual-entry' (defined in both emacsen).
+       (gnus-button-man-handler): Remove emacsen difference and use
+       `manual-entry'.
+
+2002-10-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * spam.el: Wrap autoload settings for bbdb-records,
+       executable-find and ifile-spam-filter with eval-and-compile.
+       (spam-display-buffer-contents): Remove.
+       (spam-bogofilter-score): Merge spam-display-buffer-contents.
+
+2002-10-17  Ted Zlatanov  <tzz@lifelogs.com>
+
+       * spam.el (spam-display-buffer-contents): New function.
+       (spam-bogofilter-score): use spam-display-buffer-contents, patch
+       from Katsumi Yamaoka <yamaoka@jpl.org>.
+
+2002-10-17  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * nnheader.el (nnheader-parse-naked-head): New function.
+       (nnheader-parse-head): Use the above function, in order to handle
+       continuation lines properly.
+       (nnheader-remove-body): New function.
+       (nnheader-remove-cr-followed-by-lf): New function.
+       (nnheader-ms-strip-cr): Use the above function.
+
+       * gnus-agent.el (gnus-agent-regenerate-group): Call
+       `nnheader-remove-body'; use `nnheader-parse-naked-head' instead of
+       `nnheader-parse-head'.
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
+
+       * gnus-msg.el (gnus-inews-yank-articles): Do not unfold
+       continuation lines by itself; call `nnheader-parse-naked-head'
+       instead of `nnheader-parse-head'.
+       * nndiary.el (nndiary-parse-head): Ditto.
+       * nnfolder.el (nnfolder-parse-head): Ditto.
+       * nnimap.el (nnimap-retrieve-headers-progress): Ditto.
+       * nnmaildir.el (nnmaildir--update-nov): Ditto.
+       * nnml.el (nnml-parse-head): Ditto.
+
+2002-10-17  Steve Youngs  <youngs@xemacs.org>
+
+       * gnus-art.el (gnus-button-man-handler): Add 'manual-entry' for
+       XEmacs, default to it if featurep 'xemacs.
+
+2002-10-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * spam-stat.el: Check for the existence of hash functions instead
+       of the Emacs version to decide whether to load cl.  Suggested by
+       Kai Gro\e,A_\e(Bjohann.
+
+2002-10-15  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Open history
+       if it isn't open yet.
+
+2002-10-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-group.el: Require mm-url only when compiling.
+       (gnus-group-fetch-charter): Require mm-url.
+
+       * spam-stat.el: Require cl for the functions gethash,
+       hash-table-count, make-hash-table and mapc for Emacs 20.
+       (puthash): Alias to cl-puthash for Emacs 20.
+       (with-syntax-table): New macro for Emacs 20.
+
+2002-10-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-spec.el (gnus-pad-form): Use gnus-string-width-function.
+
+2002-10-11  Ted Zlatanov <tzz@lifelogs.com>
+
+       * spam.el (spam-check-ifile): added ifile as a spam checking
+       backend, and spam-use-ifle as the variable to toggle that check.
+
+2002-10-12  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-beginning-of-line): New variable.
+       (message-beginning-of-line): Use it.
+
+2002-10-11  Ted Zlatanov <tzz@lifelogs.com>
+
+       * spam.el: more compilation fixes for BBDB
+
+       * spam-stat.el added code from Alex Schroeder <alex@gnu.org>
+       (spam-stat-reduce-size): Interactive.
+       (spam-stat-reset): New function.
+       (spam-stat-save): Interactive.
+
+2002-10-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el: Autoload gnus-delay-initialize.
+
+       * message.el: Autoload gnus-delay-article.
+
+2002-10-11  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-spec.el (gnus-balloon-face-function): Use the help-echo
+       text property in Emacs.
+
+2002-10-11  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-pgg-decrypt, mml2015-pgg-clear-decrypt)
+       (mml2015-pgg-verify, mml2015-pgg-clear-verify): Remove CR.
+
+       * mml1991.el (mml1991-pgg-sign): Remove CR.
+
+2002-10-10  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-pgg-decrypt): Set gnus details even when
+       decrypt failed.
+       (mml2015-trust-boundaries-alist): Removed.
+       (mml2015-gpg-extract-signature-details): Don't use it.
+       (mml2015-unabbrev-trust-alist): New.
+       (mml2015-gpg-extract-signature-details): Use it.
+
+2002-10-10  Ted Zlatanov <tzz@lifelogs.com>
+
+       * spam.el: compilation fixes, spam-check-bbdb function is nil if no
+       BBDB installed
+
+       * spam-stat.el: added code from Alex Schroeder <alex@gnu.org> to do
+       statistical analysis of spam in Lisp only
+
+2002-10-10  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-open-server): Re-open server if it isn't in
+       auth, selected or examine state.
+
+       * pgg-gpg.el (pgg-gpg-verify-region): Filter out stuff into output
+       buffer and error buffer depending on type of information.
+
+       * mml2015.el (mml2015-gpg-extract-signature-details): Parse
+       --status-fd stuff even if gpg.el is not used (revert earlier
+       change).
+       (mml2015-pgg-{clear-,}verify): Store both output and errors as
+       gnus details.
+       (mml2015-pgg-{clear-,}verify): Extract signature info from errors
+       buffer.
+
+       * pgg.el (pgg-verify-region): Use it.
+
+       * pgg-def.el (pgg-query-keyserver): New variable.
+
+       * pgg.el (pgg-decrypt-region): Bind pgg-default-user-id to
+       key-identifier in packet.  Is this a good idea?
+
+       * mml.el (mml-mode-map): Add security commands that operates on
+       MIME parts.
+       (mml-menu): And menu items for them.
+
+       * mml1991.el (mml1991-pgg-encrypt): Remove headers.
+
+       * mml.el (mml-parse-1): Support sender in #secure tags.
+
+       * mml1991.el (mml1991-pgg-sign): Only use message-sender if it is
+       defined.
+
+       * mml-sec.el (mml-smime-encrypt-buffer): Warn about combined signing.
+       (mml-pgp-encrypt-buffer): Support combined signing.
+
+       * mml1991.el (mml1991-mailcrypt-encrypt): Support combined signing.
+       (mml1991-gpg-encrypt): Ditto.
+       (mml1991-pgg-encrypt): Ditto.
+       (mml1991-encrypt): Pass sign parameter.
+
+       * mml-sec.el (mml-signencrypt-style-alist): Defcustom.
+       (mml-signencrypt-style): Mention the variable.
+
+2002-10-09  Simon Josefsson  <jas@extundo.com>
+
+       * mml1991.el (mml1991-pgg-sign): Bind pgg-default-user-id, not
+       pgg-gpg-user-id.
+
+       * pgg.el (pgg-insert-url-with-w3): Ignore errors.
+       (pgg-fetch-key-function): Nil if w3 is not installed.
+
+2002-10-08  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Bind
+       gnus-agent-current-history.
+
+2002-10-06  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-parse-status): Don't use read to read token.
+
+2002-10-05  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-fetch-selected-article): Do nothing
+       for methods not covered by the agent, and when unplugged.
+
+2002-10-05  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Query passphrase when
+       signing.
+
+       * gnus-agent.el (gnus-agent-read-servers): If getting method from
+       a named server fails, ignore the server.
+
+       * mml1991.el (mml1991-pgg-sign): Do QP.
+
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Make signencrypt really
+       work.
+
+2002-10-04  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Make signencrypt work.
+
+       * pgg-pgp.el (pgg-pgp-verify-region): Inline
+       binary-write-decoded-region from MEL.
+
+       * pgg.el (pgg-encrypt-region): Support sign.
+
+       * pgg-gpg.el (pgg-gpg-encrypt-region): Ditto.
+
+       * mml2015.el (mml2015-pgg-encrypt): Ditto.
+
+       * pgg.el, pgg-def.el, pgg-parse.el, pgg-gpg.el, pgg-pgp5.el,
+       pgg-pgp6.el: Moved from ../pgg/.  Modifications compared to EMIKO
+       branch where PGG was taken from in the ChangeLog entries below.
+
+2002-10-01  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-pgp.el: Don't require mel.  Don't use luna.
+       (pgg-scheme-pgp-instance, pgg-make-scheme-pgp): Remove.
+       (pgg-pgp-process-region): Use expand-file-name instead of concat.
+       (pgg-pgp-process-region): Don't use binary-funcall.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Don't use binary-funcall.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use expand-file-name
+       instead of concat.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region): Ditto.
+
+2002-09-29  Simon Josefsson  <jas@extundo.com>
+
+       * pgg-parse.el (pgg-char-int, pgg-string-as-unibyte): Prevent byte
+       compile warnings.
+
+       * pgg.el (pgg-decrypt-region): Don't parse packet.
+
+       * pgg.el, pgg-gpg.el, pgg-pgp5.el: Don't depend on luna.el.
+
+2002-09-29  Daiki Ueno <ueno@unixuser.org>
+
+       * pgg.el: Remove dependency on calist.el.
+
+2002-09-28  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.el (pgg-temporary-file-directory): New variable.
+       (pgg-verify-region): Don't assume set-buffer-multibyte exists.
+
+       * pgg-pgp5.el (pgg-pgp5-process-region, pgg-scheme-verify-region)
+       (pgg-scheme-snarf-keys-region): Use pgg-temporary-file-directory.
+
+       * pgg-parse.el (pgg-char-int): Defalias.
+       (pgg-format-key-identifier, pgg-byte-after, pgg-read-byte)
+       (pgg-read-bytes, pgg-read-body): Use it.
+       (pgg-decode-packets): Don't use MEL, use base64-*.
+       (pgg-parse-armor): Don't assume set-buffer-multibyte exists.
+       (pgg-string-as-unibyte): Defalias.
+       (pgg-parse-armor-region): Use it.
+
+       * pgg-gpg.el (pgg-gpg-process-region): Use
+       pgg-temporary-file-directory.
+
+       * luna.el: Don't def-edebug.
+
+       * pgg-pgp5.el (pgg-scheme-verify-region): Inline
+       binary-write-decoded-region from MEL.
+
+       * pgg-pgp5.el, pgg-gpg.el: Don't require mel.
+
+       * alist.el, calist.el: Don't require product/APEL.
+
+       * pgg-parse.el (top-level): Remove dependency on static.el,
+       pccl.el, mel.el.
+       (pgg-parse-crc24, pgg-parse-crc24-string): Only define if
+       `define-ccl-program' is boundp, instead of using broken.
+
+2002-10-01  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-required-mail-headers): Remove Lines:.
+
+2002-10-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Jesper Harder.
+
+       * gnus-group.el (gnus-group-fetch-charter,
+       gnus-group-fetch-control): Prompt for group if given a prefix
+       argument.
+       * gnus-sum.el (t): Add gnus-group-fetch-charter and
+       gnus-group-fetch-control to summary key map and menu.
+
+2002-10-03  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--group-maxnum-art): fix maximum article
+       number when there are no articles.
+
+2002-10-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-summary-fetch-group): Optional prefix
+       arg ALL means to fetch all articles, not only downloadable ones.
+       (gnus-agent-fetch-selected-article): New function for
+       gnus-select-article-hook or gnus-mark-article-hook.
+
+2002-10-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From Peter von der Ahe <nospam2159@daimi.au.dk>.
+
+       * gnus-ems.el (gnus-x-splash): Set coding-system-for-read to
+       raw-text.
+
+2002-09-30  Ted Zlatanov <tzz@lifelogs.com>
+
+       * spam.el: merged changes from pinard@iro.umontreal.ca (Fran\e,Ag\e(Bois
+       Pinard).
+       Major revamp of the code, documentation is in comments in the file
+       for now.
+
+2002-09-30  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-pgg-clear-verify): Verifying in a unibyte
+       buffer seem to be needed?
+
+2002-09-29  Simon Josefsson  <jas@extundo.com>
+
+       * mml1991.el (pgg-output-buffer, pgg-errors-buffer): Prevent byte
+       compile warnings.
+
+       * mml1991.el (mml1991-function-alist): Add pgg.
+       (mml1991-pgg-sign, mml1991-pgg-encrypt): New functions.
+       (mml1991-pgg-encrypt): Fix recipients querying.
+
+2002-09-28  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (autoload): Autoload correct files.  Trivial patch
+       from dme@dme.org.
+       (mml2015-pgg-decrypt, mml2015-pgg-verify): Make sure either nil or
+       handle is returned.
+
+2002-09-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-fixup-nnimap-unread-after-getting-new-news):
+       Protect against non-existent of `nnimap-mailbox-info'.
+
+2002-09-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-start.el (gnus-fixup-nnimap-unread-after-getting-new-news): New.
+       (gnus-setup-news-hook): Use it.
+       (gnus-after-getting-new-news-hook): Ditto.
+
+       * nnimap.el (nnimap-fixup-unread-after-getting-new-news): Remove.
+
+2002-09-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From Mats Lidell <matsl@contactor.se>.
+
+       * gnus-art.el (gnus-article-mode-syntax-table): Replace "-" to " ".
+
+2002-09-27  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * gnus-sum.el (gnus-nov-parse-line): When an error is signaled in
+       the part to decode encoded words, use raw words instead of decoded
+       words.
+
+2002-09-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnimap.el (nnimap-update-unseen): Use gnus-gethash-safe.
+
+       * mm-view.el (mm-w3m-mode-ignored-keys): New variable.
+       (mm-setup-w3m): Use it.
+
+2002-09-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-article-mode-syntax-table): Make M-. work in
+       article buffers.
+
+       * nnimap.el (nnimap-fixup-unread-after-getting-new-news): Autoload
+       it just in case.
+       (nnimap-update-unseen): New function; update unseen count in
+       `n-m-info'.
+       (nnimap-close-group): Call it.
+
+       * gnus-start.el (gnus-setup-news-hook): Add n-f-u-a-g-n-n.
+       (gnus-after-getting-new-news-hook): Ditto.
+
+       * nnimap.el (nnimap-retrieve-groups): Move the quick mail check
+       message into verboselevel 9.  Change slow mail check message.
+       (nnimap-retrieve-groups): Use prefixed names in n-mailbox-info.
+       (nnimap-fixup-unread-after-getting-new-news): New function, to be
+       used as a hook after getting new mail.
+
+2002-09-26  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-parse-resp-text-code): The UNSEEN value in
+       SELECT/EXAMINE is first unseen article, not number of unseen
+       articles.  Make them distinct by renaming the former to
+       `first-unseen' instead of `unseen'.
+
+       * nnimap.el (nnimap-retrieve-groups): Get uidvalidity and unseen
+       too.
+       (nnimap-retrieve-groups): Don't used cached data if uidvalidity
+       changed.
+       (nnimap-retrieve-groups): Store uidvalidity and unseen data too.
+
+       * gnus-int.el (gnus-server-unopen-status): Defcustom.
+
+       * mml-sec.el (mml-signencrypt-style): Docstring to font-lock
+       better.
+
+       * mml2015.el (mml2015-pgg-decrypt): Only add security information
+       if dissecting resulting buffer actually had any information.
+
+2002-09-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-group.el (gnus-group-sort-by-method): Remove `symbol-name'
+       because the function `string<' allows symbols.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Ditto.
+
+2002-09-25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-forward-make-body): Revert an early change
+       because 8-bit utf-8 emails.
+
+2002-09-25  Bj\e,Av\e(Brn Torkelsson  <torkel@acc.umu.se>
+
+       * gnus-agent.el (gnus-category-line-format): Doc fixes (mostly added
+       links to Info)
+       * gnus-art.el (gnus-treat-highlight-signature):
+       * gnus-art.el (gnus-treat-buttonize):
+       * gnus-art.el (gnus-treat-buttonize-head):
+       * gnus-art.el (gnus-treat-emphasize):
+       * gnus-art.el (gnus-treat-strip-cr):
+       * gnus-art.el (gnus-treat-unsplit-urls):
+       * gnus-art.el (gnus-treat-leading-whitespace):
+       * gnus-art.el (gnus-treat-hide-headers):
+       * gnus-art.el (gnus-treat-hide-boring-headers):
+       * gnus-art.el (gnus-treat-hide-signature):
+       * gnus-art.el (gnus-treat-fill-article):
+       * gnus-art.el (gnus-treat-hide-citation):
+       * gnus-art.el (gnus-treat-hide-citation-maybe):
+       * gnus-art.el (gnus-treat-strip-list-identifiers):
+       * gnus-art.el (gnus-treat-strip-pgp):
+       * gnus-art.el (gnus-treat-strip-pem):
+       * gnus-art.el (gnus-treat-strip-banner):
+       * gnus-art.el (gnus-treat-highlight-headers):
+       * gnus-art.el (gnus-treat-highlight-citation):
+       * gnus-art.el (gnus-treat-date-ut):
+       * gnus-art.el (gnus-treat-date-local):
+       * gnus-art.el (gnus-treat-date-english):
+       * gnus-art.el (gnus-treat-date-lapsed):
+       * gnus-art.el (gnus-treat-date-original):
+       * gnus-art.el (gnus-treat-date-iso8601):
+       * gnus-art.el (gnus-treat-date-user-defined):
+       * gnus-art.el (gnus-treat-strip-headers-in-body):
+       * gnus-art.el (gnus-treat-strip-trailing-blank-lines):
+       * gnus-art.el (gnus-treat-strip-leading-blank-lines):
+       * gnus-art.el (gnus-treat-strip-multiple-blank-lines):
+       * gnus-art.el (gnus-treat-unfold-headers):
+       * gnus-art.el (gnus-treat-fold-headers):
+       * gnus-art.el (gnus-treat-fold-newsgroups):
+       * gnus-art.el (gnus-treat-overstrike):
+       * gnus-art.el (gnus-treat-display-xface):
+       * gnus-art.el (gnus-treat-display-smileys):
+       * gnus-art.el (gnus-treat-from-picon):
+       * gnus-art.el (gnus-treat-mail-picon):
+       * gnus-art.el (gnus-treat-newsgroups-picon):
+       * gnus-art.el (gnus-treat-body-boundary):
+       * gnus-art.el (gnus-treat-capitalize-sentences):
+       * gnus-art.el (gnus-treat-fill-long-lines):
+       * gnus-art.el (gnus-treat-play-sounds):
+       * gnus-art.el (gnus-treat-translate):
+       * gnus-art.el (gnus-treat-x-pgp-sig):
+       * gnus-art.el (gnus-mime-button-line-format):
+       * gnus-art.el (gnus-button-man-level):
+       * gnus-art.el (gnus-button-emacs-level):
+       * gnus-cus.el (gnus-group-parameters):
+       * gnus-gl.el (bbb-build-mid-scores-alist):
+       * gnus-group.el (gnus-group-line-format):
+       * gnus-mlspl.el (gnus-group-split-setup):
+       * gnus-mlspl.el (gnus-group-split):
+       * gnus-msg.el (gnus-mailing-list-groups):
+       * gnus-msg.el (gnus-posting-styles):
+       * gnus-nocem.el (gnus-nocem-issuers):
+       * gnus-score.el (gnus-score-regexp-bad-p):
+       * gnus-srvr.el (gnus-server-line-format):
+       * gnus-topic.el (gnus-topic-line-format):
+       * gnus.el (gnus-summary-line-format):
+       * mail-source.el (mail-sources):
+       * message.el (message-subscribed-address-file):
+       * nnmail.el (nnmail-split-fancy):
+
+2002-09-24  Evgeny Roubinchtein  <zhenya@freeshell.org>
+
+       * mail-source.el(mail-source-run-script): use `functionp' to test
+       whether the argument `script' is in fact a function.
+       (mail-sources): adjust the defcustom to allow users to specify a
+       function or a string as the value of the `:prescript' and
+       `:postscript' arguments of the `file' and `pop3' mail sources.
+
+2002-09-25  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--grp-add-art): fix minimum article
+       number when article 1 does not exist.
+
+2002-09-25  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (gnus-button-handle-apropos-variable): Fall back to
+       apropos if apropos-variable does not exist.
+       (gnus-button-guessed-mid-regexp)
+       (gnus-button-handle-describe-prefix, gnus-button-alist): Better
+       regexes.  From Reiner Steib.
+       (gnus-button-handle-describe-function)
+       (gnus-button-handle-describe-variable): Doc fix.  From Reiner Steib.
+       (gnus-button-handle-describe-key, gnus-button-handle-apropos)
+       (gnus-button-handle-apropos-command): Doc fix.  From Reiner Steib.
+
+2002-09-25  Mark A. Hershberger  <mah@everybody.org>
+       Trivial patch.
+
+       * nnrss.el (nnrss-save-server-data): Save nnrss-group-alist in
+       the file.
+
+2002-09-24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-1): Create nndraft:queue, nndraft:drafts.
+
+2002-09-24  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (top-level): Require mm-util for mm-make-temp-file.
+       (mml2015-use): Prefer PGG if installed.
+       (mml2015-function-alist): Add PGG wrappers.
+       (mml2015-gpg-extract-signature-details): Check mml2015-use too.
+       (mml2015-gpg-extract-signature-details): PGG strips "gpg: "
+       prefix, make regexp optionally skip it.
+       (mml2015-pgg-decrypt, mml2015-pgg-clear-decrypt)
+       (mml2015-pgg-verify, mml2015-pgg-clear-verify, mml2015-pgg-sign)
+       (mml2015-pgg-encrypt): New functions.
+       (defvar, autoload): Prevent byte-compile warnings.
+
+2002-09-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From TSUCHIYA Masatoshi <tsuchiya@namazu.org>.
+
+       * gnus-art.el (article-strip-banner): Check for the existence of
+       from header.
+
+2002-09-23  Kai Gro\e,b_\e(Bjohann  <grossjoh@ls6.informatik.uni-dortmund.de>
+
+       * gnus-art.el (gnus-button-guessed-mid-regexp): Improved regexp.
+       (gnus-button-alist): Improved regexp for
+       gnus-button-handle-mid-or-mail (false positives), fixed
+       gnus-button-handle-man entries.
+       From Reiner Steib.
+
+2002-09-23  Paul Jarc  <prj@po.cwru.edu>
+       From Josh Huber.
+
+       * nnmaildir.el (nnmaildir--update-nov): fix wrong-type error when
+       nnmail-extra-headers is non-nil.
+
+2002-09-23  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el: Store article numbers persistently.  General
+       revision.
+       (nnmaildir-request-expire-articles): handle 'immediate and 'never
+       for nnmail-expiry-wait; delete instead of moving if 'force is
+       given.
+
+2002-09-23  Simon Josefsson  <jas@extundo.com>
+       Trivial fix from beaker@iavmb.pl (Krzysztof J\e,Bj\e(Bdruczyk).
+
+       * smime.el (smime-sign-buffer): Get key and extra certs.
+       (smime-get-key-with-certs-by-email): Utility function.
+
+2002-09-21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Trivial patch from Micha Wiedenmann <mw-u1@gmx.de>
+
+       * gnus-soup.el (gnus-soup-add-article): Mark as read only when the
+       article exists.
+
+2002-09-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-next-group): Switch to the summary buffer.
+
+2002-09-20  Kai Gro\e,b_\e(Bjohann  <grossjoh@ls6.informatik.uni-dortmund.de>
+       From Reiner Steib.
+
+       * gnus-art.el (gnus-button-handle-custom,
+       gnus-button-handle-mid-or-mail,
+       gnus-button-handle-describe-{function,variable,key},
+       gnus-button-handle-apropos{,command,variable}): New functions.
+       (gnus-button-prefer-mid-or-mail,gnus-button-guessed-mid-regexp,
+       gnus-button-{man,emacs,mail}-level): New variables.
+       (gnus-button-alist): Use the above to buttonize emacs and mail
+       related links.
+
+2002-09-18  Juanma Barranquero  <lektu@terra.es>
+
+       * gnus-int.el (gnus-status-message): Fix spacing.
+
+       * imap.el (imap-continuation): Fix typos.
+
+2002-09-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Sort results.
+
+       * gnus-art.el (gnus-article-reply-with-original): Correct
+       with-current-buffer scope.
+
+       * message.el (message-completion-alist): Add Reply-To, From, etc.
+
+2002-09-18  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-request-expire-articles): Make flag setting
+       conditional.  From Nevin Kapur <nevin@jhu.edu>.
+
+2002-09-17  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-expiry-target): Don't search for which
+       articles exists here.
+       (nnimap-request-expire-articles): Do it here instead.  Only expire
+       when articles are found.  Suggested by Nevin Kapur
+       <nevin@jhu.edu>.
+
+2002-09-17  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Reiner Steib <reiner.steib@gmx.de>.
+
+       * message.el (message-strip-subject-trailing-was)
+       (message-change-subject, message-add-archive-header)
+       (message-xpost-fup2-header, message-xpost-insert-note)
+       (message-xpost-fup2, message-reduce-to-to-cc): New functions
+       adopted from message-utils.el.  Add functions to the keymap, mode
+       describtion and menu.
+       (message-change-subject,message-xpost-fup2): Signal error if
+       current header is empty.
+       (message-xpost-insert-note): Changed insert position.
+       (message-archive-note): Ensure to insert note in message body (not
+       in head).
+       (message-archive-header, message-archive-note)
+       (message-xpost-default, message-xpost-note, message-fup2-note)
+       (message-xpost-note-function): New variables adopted from
+       message-utils.el.  Changed some doc-strings.
+       (message-mark-insert-{begin,end}): Rename from
+       message-{begin,end}-inserted-text-mark (message-utils.el), changed
+       values.
+       (message-subject-trailing-was-query)
+       (message-subject-trailing-was-ask-regexp)
+       (message-subject-trailing-was-regexp): New variables.
+       (message-to-list-only): Added doc-string and menu entry.
+
+       * message-utils.el: Removed.  Functions are now in message.el.
+
+2002-09-16  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-reply-with-original,
+       gnus-article-followup-with-original): Switch to
+       gnus-summary-buffer before reply/followup.
+
+2002-09-15  John Paul Wallington  <jpw@shootybangbang.com>
+
+       * gnus-sum.el (gnus-summary-toggle-header): The article window may
+       not exist. Toggle it anyway.
+
+2002-09-13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-copy-article-buffer): Bind mail-header-separator.
+
+       * gnus-art.el (article-fill-long-lines): Fill-paragraph properly.
+       Trivial patch from Urban Engberg <ue@ccieurope.com>.
+
+       * rfc2047.el (message-posting-charset): Defvar it.
+       (rfc2047-charset-encoding-alist): Use B for iso-8859-7 and
+       iso-8859-8. Fix doc.  Suggested by Dave Love <fx@gnu.org>.
+
+       * mail-source.el (mail-source-fetch): Hide password.
+
+       * gnus-sum.el (gnus-summary-next-group): Semi-exit only when needed.
+
+2002-09-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From John Paul Wallington <jpw@shootybangbang.com>.
+
+       * gnus.el (gnus-visual, gnus-meta): Fix typo.
+
+2002-09-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-address-banner-alist): Doc fix.
+
+2002-09-11  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-expiry-target): Only expiry-target existing articles.
+       (nnimap-split-rule): Doc fix.
+       (nnimap-request-expire-articles): Cleanup code.
+
+2002-09-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From TSUCHIYA Masatoshi <tsuchiya@namazu.org>.
+
+       * gnus-art.el (gnus-article-address-banner-alist): New option.
+       (article-strip-banner): Refer the above option to split banners of
+       free mail servers, when no group parameter is specified.
+
+2002-09-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-wait-for-string): Check for a process in the
+       current buffer instead of `nntp-server-buffer'.
+
+2002-09-09  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-button-man-handler): New variable.
+       (gnus-button-alist): Use g-b-handle-man.
+       (gnus-button-handle-man): New, call g-b-man-handler.
+
+2002-09-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-button-alist): Buttonize man page links.
+
+2002-09-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-dumbquotes-map): Add \230.
+
+2002-09-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-browse-make-menu-bar): Add "d".
+
+       * gnus-sum.el (gnus-summary-limit-to-unseen): New command and
+       keystroke.
+
+       * gnus-srvr.el (gnus-browse-describe-group): New command and
+       keystroke.
+
+2002-09-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-treat-body-boundary): Don't quote a
+       value for gnus-decoration property.
+
+2002-09-06  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-cache-fetch-group): Don't return "" (empty
+       string) as group name in case we have a CRLF in the file.
+
+2002-09-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * rfc1843.el (rfc1843-decode-loosely): Move to mime customization
+       group.
+       (rfc1843-decode-hzp): do.
+       (rfc1843-newsgroups-regexp): do.
+
+2002-09-04  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-canlock-generate): Make sure sha1 doesn't
+       call external programs.
+
+2002-09-03  Simon Josefsson  <jas@extundo.com>
+
+       * nntp.el (nntp-wait-for-string): Dont infloop if process died.
+
+       * gnus-agent.el (gnus-agent-batch): Add doc.
+
+2002-09-03  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-msg.el (gnus-summary-handle-replysign): Change the order we
+       check for signed and encrypted parts.
+       * mml.el (mml-parse-1): Correct small typo which preventing
+       setting recipients in a secure tag.
+
+2002-09-03  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-util.el (mm-coding-system-priorities): Default to a list of
+       iso-2022-jp and others for the Japanese environment.
+
+2002-09-03  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-util.el (gnus-frame-or-window-display-name): Exclude
+       invalid display names.
+
+2002-08-30  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-fetch-control): Fix typo in last
+       commit.  From Reiner Steib <4uce.02.r.steib@gmx.net>.
+
+2002-08-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.el (gnus-group-charter-alist): New option.
+       (gnus-group-fetch-control-use-browse-url): New option.
+
+       * gnus-group.el (gnus-group-fetch-charter): New function.
+       (gnus-group-fetch-control): New function.
+       Add them to the keymap and menu. Require mm-url.
+
+2002-08-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-mlspl.el (gnus-group-split-fancy): Doc fix.
+       From Alex Schroeder <alex@emacswiki.org>.
+
+2002-08-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-group.el (gnus-group-make-menu-bar): Add ellipses to menu
+       items expecting user interaction.
+
+       * gnus-topic.el (gnus-topic-make-menu-bar): do.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): do.
+
+       * gnus-srvr.el (gnus-server-make-menu-bar): do.
+
+       * mml.el (mml-menu): do.
+
+2002-08-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mail-source.el (mail-source-touch-pop): New function.
+
+       * message.el (message-smtpmail-send-it): New function.
+       (message-send-mail-function): Add it for a candidate.
+
+2002-08-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (posting-charset-alist): Use
+       gnus-define-group-parameter instead of defcustom.
+       (gnus-put-message): Handle SPC in GCC.
+       (gnus-inews-insert-gcc): Ditto.
+       (gnus-inews-insert-archive-gcc): Ditto.
+
+2002-08-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-agent.el (gnus-agent-auto-agentize-methods): New variable.
+       (gnus-agentize): Auto agentize all nntp and nnimap groups.
+       (gnus-agent-possibly-save-gcc): Autoload.
+       Suggested by (KOSEKI Yoshinori) <kose@meadowy.org>.
+
+2002-08-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (gnus-other-frame-function): New user option.
+       (gnus-other-frame): Use it; add a doc-string; make it work with
+       the gnuclient program.
+
+       * gnus-util.el (gnus-frame-or-window-display-name): New function.
+
+       * lpath.el: Fbind `frame-parameter', `make-frame-on-display',
+       `device-connection' and `dfw-device'.
+
+2002-08-22  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (gnus-emphasis-alist): Strikethru had a lot of false
+       positives, make it stricter.  From Jochen Hein (trivial change).
+
+2002-08-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (gnus-other-frame): Trivial fix.
+
+2002-08-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (gnus-other-frame-parameters): New user option.
+       (gnus-other-frame-object): New variable.
+       (gnus-other-frame): Make it search for existing Gnus frame; don't
+       read new news; delete frame on exit.
+
+       * gnus-util.el (gnus-select-frame-set-input-focus): New function.
+
+       * lpath.el: Fbind w32-focus-frame and x-focus-frame.
+
+2002-08-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+       From \e$B>.4X\e(B \e$B5HB'\e(B (KOSEKI Yoshinori) <kose@meadowy.org>.
+
+       * message.el (message-set-auto-save-file-name): Add support for
+       the Cygwin Emacs; the system-type is `cygwin'.
+       * nnheader.el (nnheader-file-name-translation-alist): Ditto.
+
+2002-08-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-button-url-regexp): Use POSIX regexp if possible.
+
+       * nnmh.el (nnmh-request-list-1): Use %.0f instead of %d to
+       avoid arithmetic errors.
+
+2002-08-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el: Don't fbind `gnus-article-replace-with-quoted-text'.
+
+2002-08-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-ignored-supersedes-headers): Add X-Hashcash.
+       (message-ignored-resent-headers): Add envelope From.
+
+2002-08-18  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.el (gnus-summary-line-format): Document %k specifier.
+
+2002-08-17  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-summary-line-message-size): New function.
+       (gnus-summary-line-format-alist): Use it.
+
+2002-08-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (article-make-date-line): Refer to the value for
+       `gnus-article-time-format' in the summary buffer.
+
+       * message.el (message-cite-prefix-regexp): Exclude ":" and "\e,A;\e(B".
+
+2002-08-14  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-button-alist): Use ' not ` for default value
+       quoting.
+       (gnus-button-alist): Fix doc.
+       (gnus-header-button-alist): Use ' not ` for default value quoting.
+       (gnus-header-button-alist): Don't inline gnus-button-url-regexp,
+       rationale similar to 2002-05-01 change.
+       (gnus-article-add-buttons-to-head): Evaluate expression.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add MIME button option.
+
+2002-08-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-font-lock-keywords): Refer to the value for
+       `message-cite-prefix-regexp' dynamically.
+
+2002-08-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-decode-header-methods): Doc fix.
+
+2002-08-12  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-shell-open): Allow non-list `imap-shell-program'.
+       (imap-shell-open): Skip initial junk before IMAP greeting.
+
+2002-08-11  Simon Josefsson  <jas@extundo.com>
+
+       * message-utils.el (message-xpost-default,
+       message-xpost-fup2-header, message-xpost-fup2): Fixed
+       Typos.  Trivial changes from Reiner Steib
+       <4uce.02.r.steib@gmx.net>.
+
+2002-08-09  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-canlock-password): Set
+       canlock-password-for-verify to newly generated canlock-password.
+       When Emacs is restarted, Custom makes sure this is set, but during
+       the same session we must set it manually.
+
+2002-08-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * yenc.el: New file.
+
+       * mm-uu.el (mm-uu-yenc-decode-function): New variable.
+       (mm-uu-type-alist): Add yenc.
+       (mm-uu-yenc-filename): New function.
+       (mm-uu-yenc-extract): New function.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Add yenc.
+
+2002-08-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (merge): Don't use coerce.
+
+2002-05-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * mailcap.el (mailcap-mime-data): Test window-system rather than
+       mm-device-type.
+       (mailcap-mime-data): Call xdvi and gv with "-safer".
+
+       * mm-util.el: Don't define mm-device-type.
+
+2002-08-05  Simon Josefsson  <jas@extundo.com>
+
+       * mm-util.el (mm-coding-system-priorities): coding-system type not
+       supported everywhere.
+
+2002-08-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bumped version number.
+
+2002-08-04 01:48:57 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.07 is released.
+
+2002-08-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-thread-sort-functions): Doc fix.
+       (gnus-article-sort-functions): Doc fix.
+       (t): New keystroke.
+       (gnus-article-sort-by-random): New function.
+       (gnus-thread-sort-by-random): New function.
+
+2002-08-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-logic.el (gnus-advanced-integer): Swap arguments in
+       funcall.  From Scott A Crosby <scrosby@cs.rice.edu>.
+
+2002-07-31  Danny Siu  <dsiu@adobe.com>
+
+       * nnimap.el (nnimap-split-articles): do not call nnmail-fetch-field
+       when splitting malformed messages without message-id
+
+2002-07-28  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Niklas Morberg <niklas.morberg@axis.com>.
+
+       * nnweb.el (nnweb-type, nnweb-type-definition)
+       (nnweb-gmane-create-mapping, nnweb-gmane-wash-article)
+       (nnweb-gmane-search, nnweb-gmane-identity): Added gmane
+       functionality.
+       * nnweb.el: Removed old non-functioning search engines.
+
+2002-07-27  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-forward-make-body): Don't use
+       `message-forward-ignored-headers' when doing a "raw" followup (it
+       is important to preserve e.g. CTE).
+
+       * flow-fill.el (fill-flowed): Disable filladapt-mode.
+
+       * gnus-sieve.el (gnus-sieve-guess-rule-for-article): Don't
+       regexp-quote, Cyrus Sieve is fixed.
+
+       * sieve-manage.el (sieve-manage-deletescript): New function.
+
+       * sieve.el (sieve-manage-mode-map): Fix down-mouse-2 and down-mouse-3.
+       (sieve-manage-mode): Fix menubar.
+       (sieve-activate): Change some messages.
+       (sieve-deactivate-all): New function.
+       (sieve-deactivate): New alias.
+       (sieve-remove): New function.
+       (sieve-help): Fix help.
+       All suggested by Ned Ludd.
+
+2002-07-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-decode.el (mm-inline-text-html-with-images): Doc fix.
+       (mm-w3m-safe-url-regexp): New user option.
+
+       * mm-view.el (mm-inline-text-html-render-with-w3m): Use
+       `mm-w3m-safe-url-regexp' to bind `w3m-safe-url-regexp'.
+
+2002-07-23  Karl Kleinpaste  <karl@charcoal.com>
+
+       * gnus-sum.el (gnus-summary-delete-article): Force
+       nnmail-expiry-target to 'delete, so that absolute deletion
+       happens when absolute deletion is requested.
+
+2002-07-21  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Nevin Kapur <nevin@jhu.edu>.
+
+       * nnmail.el (nnmail-fancy-expiry-target): Treat nonexisting
+       headers as empty headers.
+
+2002-07-21  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Jochen Hein <jochen@jochen.org>.
+
+       * gnus-art.el (gnus-emphasis-alist): Add strikethrough and
+       correct typo.
+       (gnus-emphasis-strikethru): New face.
+
+2002-07-20  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Jason Merrill <jason@redhat.com>.
+
+       * nnfolder.el (nnfolder-retrieve-headers): Avoid searching the
+       entire file for each of a sequence of missing articles.
+
+       * gnus-salt.el (gnus-binary-display-article): Respect an existing
+       value for gnus-view-pseudos.
+
+       * gnus-sum.el (gnus-summary-insert-new-articles): Count down to
+       avoid nreverse.
+
+2002-07-14  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Ted Zlatanov <teodor.zlatanov@divine.com>.
+
+       * gnus-sum.el (gnus-auto-expirable-marks): Remove `spam'.
+       (gnus-summary-mode-line-format-alist): Add %h for number of
+       spams.
+       (gnus-newsgroup-spam-marked): New variable.
+       (gnus-summary-local-variables): Add gnus-newsgroup-spam-marked.
+       (gnus-article-read-p, gnus-article-mark)
+       (gnus-set-global-variables, gnus-set-global-variables)
+       (gnus-article-marked-p, gnus-summary-mark-article-as-read)
+       (gnus-summary-mark-article-as-unread)
+       (gnus-summary-mark-article-as-unread, gnus-summary-mark-article)
+       (gnus-mark-article-as-read, gnus-mark-article-as-unread)
+       (gnus-mark-article-as-unread, gnus-summary-catchup): Grok spam.
+
+2002-07-10  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-to-groups): Allow group string to be a
+       function.  From KANEMATSU Daiji <kdaiji@bea.com>.
+
+2002-07-09  Nevin Kapur  <nevin@jhu.edu>
+
+       * gnus-sum.el (gnus-summary-delete-article): Respect group
+       parameters while expiring.
+
+2002-07-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (article-make-date-line): Fix string.  From Henrik
+       Enberg.
+
+2002-07-08  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (article-unsplit-urls): Only display MIME when this
+       function is called interactively.  From Niklas Morberg.
+
+2002-07-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-indent, gnus-topic-unindent): Change
+       cdaar to cdar and car.
+
+       * nnsoup.el (nnsoup-retrieve-headers, nnsoup-request-type)
+       (nnsoup-read-active-file, nnsoup-article-to-area): Ditto.
+
+2002-07-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Show headers anyway;
+       don't break a narrowed article.
+
+       * nntp.el (nntp-via-rlogin-command-switches): Doc fix.
+       (nntp-open-via-rlogin-and-telnet): Ditto.
+
+2002-07-02  Didier Verna  <didier@xemacs.org>
+
+       * nnmail.el (nnmail-split-methods): fix custom type.
+
+2002-07-02  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (article-unsplit-urls): Keep URL buttonized after
+       unsplitting.  From Niklas Morberg <niklas.morberg@axis.com>.
+
+2002-07-01  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-msg.el (gnus-summary-resend-default-address): New user option.
+       (gnus-summary-resend-message): Use it.
+
+2002-06-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-via-rlogin-command-switches): New variable.
+       (nntp-open-via-rlogin-and-telnet): Re-revert; use the var above.
+
+2002-06-28  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-font-lock-keywords): Don't fontify
+       headers in the message body, only in the header.
+       (message-font-lock-make-header-matcher): New function, used by
+       message-font-lock-keywords.
+       From Katsumi Yamaoka <yamaoka@jpl.org>.
+
+2002-06-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-open-via-rlogin-and-telnet): Revert last change.
+
+2002-06-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-open-via-rlogin-and-telnet): Hide commandline args.
+
+2002-06-26  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-font-lock-keywords): Revert 2002-06-22
+       change.
+
+2002-06-24  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-font-lock-keywords): Put colon in header
+       name match.
+
+2002-06-22  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-font-lock-keywords): Don't use header faces
+       in the body.  Thanks to Stefan Monnier for the hint on the
+       implementation.
+
+2002-05-09  Miles Bader  <miles@gnu.org>
+
+       * gnus-cite.el (gnus-cite-blank-line-after-header): New variable.
+       (gnus-article-hide-citation): Respect it.
+
+2002-04-12  Juanma Barranquero  <lektu@terra.es>
+
+       * pop3.el (pop3-open-server): Fix typo.
+
+2002-06-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus.el (gnus-find-subscribed-addresses): Use add-to-list
+       instead of push to ignore duplicate to-(list|address) values.
+       * nnmail.el (nnmail-cache-ignore-groups): New.
+       * nnmail.el (nnmail-cache-insert): Obey nnmail-cache-ignore-groups
+
+2002-06-18  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-send-queue): Delete the delay header
+       before sending.  Suggested by Jan Rychter.
+
+2002-06-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (remove): New compiler macro.
+       (last, coerce, subseq): Remove compiler macros for those built-in
+       or unused functions.
+
+2002-06-17  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-start.el (gnus-clear-system, gnus-read-newsrc-file): Make
+       sure to write byte-compiled versions of gnus-*-format-alist to
+       .newsrc.eld.  From Simon Josefsson.
+
+2002-06-16  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-agent.el (gnus-agent-read-servers)
+       (gnus-agent-write-servers): Put server name (string like
+       "nnchoke:frumple") in the file instead of a server specification
+       (Lisp expression like (nnchoke "frumple" ...parameters...)).
+       From Bj\e,Ax\e(Brn Mork <bmork@dod.no>.
+
+2002-06-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-cache-remove-article): n is &optional.  From
+       Reiner Steib <4uce.02.r.steib@gmx.net>.
+
+2002-06-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-file-name-translation-alist): Set the
+       default value for MS Windows systems.
+
+       * gnus-ems.el (nnheader-file-name-translation-alist): Removed.
+
+2002-06-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-beginning-of-line): Keep the region active
+       in XEmacs.  Suggested by TAKAHASHI Kaoru <kaoru@kaisei.org>.
+
+2002-06-13  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-msg.el (gnus-summary-followup): Use g-s-handle-replysign.
+       * gnus-msg.el (gnus-summary-reply): Ditto.
+       * gnus-msg.el (gnus-summary-handle-replysign): New.
+
+2002-06-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-send-mail-with-sendmail): Kill errbuf even
+       if sending failed.
+
+2002-06-11  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-start.el (gnus-dribble-enter): Don't call set-window-point anymore
+       * mml2015.el (mml2015-mailcrypt-encrypt): Accept optional argument
+       to sign while encrypting.
+
+2002-06-11  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-int.el (gnus-request-move-article): Agent expire article if
+       successfuly moved.
+
+       * nnweb.el (nnweb-google-create-mapping): Honors the value of
+       nnweb-max-hits.  From Niklas Morberg <niklas.morberg@axis.com>.
+
+2002-06-10  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-int.el (gnus-request-expire-articles): Fix last change?
+
+2002-06-09  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-delete-article): Don't agent expire here.
+
+       * gnus-int.el (gnus-request-expire-articles): Do it here instead.
+
+2002-06-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * flow-fill.el (fill-flowed): Ignore errors.
+
+2002-06-06  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-send-mail-with-sendmail): Improve error message.
+
+2002-06-06  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-interactive): Change default from nil to t.
+       Better to be safe than to be fast.
+
+2002-06-05  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-send-mail-with-sendmail): Check return value
+       from call-process-region.
+
+2002-06-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (gnus-group-mail, gnus-group-news)
+       (gnus-group-post-news, gnus-summary-mail-other-window)
+       (gnus-summary-news-other-window, gnus-summary-post-news): Bind
+       gnus-article-copy to nil, thereby inhibiting the `header' posting
+       style match to use data from last viewed article.
+       Suggested by Hrvoje Niksic.
+
+2002-06-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * spam.el (spam-point-at-eol): New alias.
+       (spam-parse-whitelist): Use it.
+
+2002-06-03  Simon Josefsson  <jas@extundo.com>
+
+       * nnmail.el (nnmail-mail-splitting-decodes): New variable.
+       (nnmail-article-group): Use it.
+
+2002-05-30  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-msg.el (gnus-inews-yank-articles): Merge split header lines
+       so that code reading them won't be surprised.  From Jesper Harder
+       <harder@ifa.au.dk>.
+
+2002-05-29  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-delete-article): Agent expire deleted
+       articles.
+
+       * gnus.el (gnus-agent-cache): Doc fix.
+       (gnus-agent): Change default to t.
+
+       * gnus-agent.el (gnus-agent-expire): Make it accept optional
+       ARTICLES, GROUP and FORCE parameters.
+
+2002-05-28  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-line-format): Doc fix.
+
+2002-05-28  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-msg.el (gnus-inews-yank-articles): Unfold headers of
+       original article before yanking.  From Jesper Harder
+       <harder@ifa.au.dk>.
+
+2002-05-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-menu-split): New function.
+       (gnus-summary-make-menu-bar): Split charset submenu.
+       (gnus-summary-menu-maxlen): New variable.
+       (gnus-summary-menu-split): Use it.
+
+2002-05-25  Simon Josefsson  <jas@extundo.com>
+
+       * mml.el (mml-preview): Generate some headers.
+
+       * gnus.el (gnus-large-newsgroup): Fix :type.
+
+       * nnimap.el (nnimap-nov-is-evil): Change default to t (because the
+       Agent cache NOV's by default now).
+       (nnimap-nov-is-evil): Make it default to `gnus-agent' instead.
+
+2002-05-18  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-dependencies-add-header): Avoid one unecessary
+       call to gnus-parent-id when we check for References loops.
+       (gnus-summary-prepare-threads): Avoid simplifying every Subject
+       twice by saving the simplified subject string in simp-subject.
+
+2002-05-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (gnus-confirm-mail-reply-to-news): Typo.  Trivial
+       change from Benjamin Rutt <rutt+news@cis.ohio-state.edu>.
+
+       * nnweb.el (nnweb-type): Remove dejanewsold.  Trivial change from
+       Niklas Morberg <niklas.morberg@axis.com>.
+
+2002-05-22  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.el (sieve-change-region): Define it before it is used.
+
+       * gnus-msg.el (gnus-confirm-mail-reply-to-news)
+       (gnus-summary-reply): Ask for confirmation when replying to news.
+       Defaults to not ask.  From Benjamin Rutt
+       <rutt+news@cis.ohio-state.edu>.
+
+       * nnimap.el (nnimap-nov-is-evil): Improve doc.
+
+2002-05-21  Simon Josefsson  <jas@extundo.com>
+
+       * sieve-mode.el (sieve-manage): Fix autoloads.
+
+       * sieve-manage.el (sieve-manage-cram-md5-auth): Just send the SASL
+       name (makes it work with recent Cyrus timsieved).
+
+2002-05-20  Jason  <jbaker@cs.utah.edu>
+       Trivial patch.
+
+       * gnus-art.el (gnus-request-article-this-buffer): Try
+       reconnecting if you don't get the message.
+
+2002-05-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-enter-digest-group): Only get
+       Reply-To headers from the headers.
+
+2002-05-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-url.el (mm-url-insert): Remove junk message.
+
+2002-05-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-list): Parse new html.
+       (nnslashdot-use-front-page): New variable.
+       (nnslashdot-request-list): Use it.
+
+       * mm-url.el (mm-url-timeout): New variable.
+       (mm-url-retries): Ditto.
+       (mm-url-insert): Use it.
+
+2002-05-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-simplify-all-whitespace): New function.
+       (gnus-simplify-subject-functions): Mention g-s-a-w.
+
+2002-05-15  Josh Huber  <huber@alum.wpi.edu>
+
+       * nnbabyl.el (nnbabyl-request-accept-article): Pass group to
+       nnmail-cache-insert.
+       * nndiary.el (nndiary-request-accept-article): Ditto.
+       * nnfolder.el (nnfolder-request-accept-article): Ditto.
+       * nnimap.el (nnimap-request-accept-article): Ditto.
+       * nnmail.el (nnmail-process-unix-mail-format): Ditto.
+       * nnmail.el (nnmail-check-duplication): Ditto. (from gnus-art)
+       * nnmbox.el (nnmbox-request-accept-article): Ditto.
+       * nnmh.el (nnmh-request-accept-article): Ditto.
+       * nnmail.el (nnmail-cache-insert): Change group to required,
+       removed code which tried to figure out the group.
+
+2002-05-13  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml.el (mml-generate-mime-1): Fix mml generation for signed only
+       messages. From Hans de Graaff <hans@degraaff.org>.
+       * nnml.el (nnml-request-accept-article): Pass in the group name to
+       nnmail-cache-insert, since it's available.
+
+2002-05-10  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-mime-digest-type-p): Set proper file-end.
+
+2002-05-08  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Florian Weimer <fw@deneb.enyo.de>.
+
+       * gnus.el (subscribed): New group parameter.
+       (gnus-find-subscribed-addresses): Use it.
+
+2002-05-08  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml-sec.el (mml-signencrypt-style-alist): Rename.  Also, changed
+       the default for pgpmime to support pgp v2.
+       * mml-sec.el (mml-signencrypt-style): New accessor function to
+       allow users to get/set the signencrypt style more easily without
+       frobbing the alist directly.
+       * mml.el (mml-generate-mime-1): Use accessor function.
+
+2002-05-08  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (gnus-article-mode-syntax-table): Specify matching
+       parenthesis for "<" and ">".  Suggested by Andreas Schwab
+       <schwab@suse.de>.
+
+2002-05-07  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-cache-insert): Prefer group-art over group
+       when intuiting the group the message is written to.  From Josh
+       Huber <huber@alum.wpi.edu>.
+
+2002-05-06  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-topic.el (gnus-group-topic-parameters): Work when group
+       buffer doesn't show group.  From Matt Armstrong <matt@lickey.com>.
+
+2002-05-06  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml2015.el (mml2015-gpg-encrypt): Changed name of optional
+       argument, and fixed compiler warning. (added autoload for
+       gpg-encrypt).
+
+2002-05-04  Simon Josefsson  <jas@extundo.com>
+
+       * mml1991.el (mml1991-function-alist): Doc fix.
+
+       * mml.el (mml-preview): Bind gnus-newsrc-hashtb temporarily if it
+       doesn't exist (for previewing messages without having Gnus
+       started).
+
+       * mm-util.el (mm-coding-system-priorities): Defcustom.
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Defcustom.
+
+2002-05-01  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-msg.el (gnus-message-replysignencrypted): enabled by
+       default.
+       * mml-sec.el:
+       * mml-sec.el (mml-signencrypt-style): New.
+       * mml-sec.el (mml-pgpmime-encrypt-buffer): Accept optional
+       argument `sign'.
+       * mml-sec.el (mml-secure-message-encrypt-pgp): Changed default to
+       signencrypt.
+       * mml-sec.el (mml-secure-message-encrypt-pgpmime): Ditto.
+       * mml.el (mml-generate-mime-1): Changed logic so a part which is
+       both signed & encryped is processed in one operation. (rather than
+       two separate ops: sign, then encrypt)
+       * mml2015.el (mml2015-gpg-extract-signature-details): Give some
+       indication if a message is signed by an expired key.
+       * mml2015.el (mml2015-gpg-encrypt): Accept optional argument which
+       enables combined sign & encrypt operation. (this was always on
+       before).
+       * mml2015.el (mml2015-encrypt): Accept optional argument `sign'.
+
+2002-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-retrieve-groups): Use separate data for each
+       server.
+       (nnimap-mailbox-info): defvar instead of defvoo.
+
+2002-05-01 20:09:21 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.06 is released.
+
+2002-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * lpath.el: Bind url-package-version.
+
+2002-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * nnfolder.el (nnfolder-request-delete-group): Figure out nov/mrk
+       filename before deleting the group itself, because the presence of
+       a group filename decides if long filenames are used or not.
+
+       * gnus-art.el (gnus-button-alist): Don't inline
+       gnus-button-url-regexp.  This makes it possible to change g-b-u-r
+       without also modifying g-button-alist.
+       (gnus-button-alist): Fix type to allow variable as well as regexp.
+       (gnus-article-add-buttons): Evaluate regexp.  Strings evaluate to
+       themselves, variables to its contents.
+       (gnus-button-entry): Ditto.
+
+2002-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-parse-resp-text-code, imap-parse-status): Treat
+       UIDNEXT as a string.
+
+       * nnimap.el (nnimap-string-lessp-numerical): New function.
+       (nnimap-retrieve-groups): Compare UIDNEXT as strings instead of
+       integers.
+
+2002-04-29  Simon Josefsson  <jas@extundo.com>
+
+       * nnmail.el (nnmail-cache-insert): Accept optional group
+       parameter.
+
+       * nnimap.el (nnimap-retrieve-groups): Don't send STATUS when
+       n-r-g-a is disabled.
+
+2002-04-29  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-fancy): Fix doc.
+       (nnimap-split-fancy): Fix doc.
+
+       * nnimap.el (nnimap-retrieve-groups-asynchronous): New variable.
+       (nnimap-mailbox-info): New internal variable.
+       (nnimap-retrieve-groups): Implement faster new mail check.
+
+       * nnimap.el (nnimap-split-articles): Support
+       nnmail-cache-accepted-message-ids.
+       (nnimap-request-accept-article): Ditto.
+
+       * imap.el (imap-mailbox-status-asynch): New command.
+
+2002-04-29  Nevin Kapur  <nevin@jhu.edu>
+
+       * gnus.el (gnus-find-subscribed-addresses): Return nil when there
+       are no subscribed mail groups.
+       - Strip quoted names when comparing addresses
+
+2002-04-28  Jesper Harder  <harder@ifa.au.dk>
+
+       * mm-decode.el (mm-text-html-renderer): Change customize type to
+       const.
+
+       * gnus-msg.el (gnus-discouraged-post-methods): Fix typo.
+       (gnus-debug-exclude-variables): do.
+
+2002-04-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-article-mail): Use gnus-msg-mail instead.
+       Trivial change from Karl Pfl\e,Ad\e(Bsterer <sigurd@12move.de>.
+
+2002-04-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dns.el (dns-make-network-process): New macro.
+       (query-dns): Use it.
+
+2002-04-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-summary-reply): Remove unbound variable
+       article-buffer.
+
+       * mm-url.el (mm-url-package-name): New variable.
+       (mm-url-package-version): New variable.
+       (mm-url-insert-file-contents): Bind url-package-name and
+       url-package-version here.
+       * nnrss.el (nnrss-insert-w3): Move the bindings.
+
+       * nnrss.el (nnrss-insert-w3): Bind url-package-name and
+       url-package-version. Trivial change from Andrew J Cosgriff
+       <ajc@polydistortion.net>
+
+       * mm-decode.el (mm-save-part): Fill in file name when GUI saving
+       attachments. Trivial change from Peter 'Luna' Runestig
+       <peter@runestig.com>.
+
+2002-04-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * nnkiboze.el (nnkiboze-request-scan): Call
+       nnkiboze-possibly-change-group.
+       (nnkiboze-generate-group): Use mm-with-unibyte to avoid encoding
+       problems.
+       (nnkiboze-generate-group): Set newsrc to the *highest* article
+       number kibozed, not the lowest.
+
+2002-04-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-art.el (article-unsplit-urls): Allow trailing SPC.
+
+2002-04-24  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Dan Christensen <jdc+news@uwo.ca>.
+
+       * nndoc.el (nndoc-type-alist, nndoc-lanl-gov-announce-type-p)
+       (nndoc-transform-lanl-gov-announce, nndoc-generate-lanl-gov-head):
+       Recognize math postings.  Extract Date (now ignores "(15kb)").
+       Extract email address using gnus-extract-address-components
+       instead of just taking the first word.  Create Date and From
+       headers for message which are missing these headers.  Get rid
+       of spurious \\ lines (purely cosmetic).  Extend body-end and
+       file-end regexps, to exclude more garbage from the message.
+       Make URL rephrasing regexp more flexible, to match current
+       format.
+
+2002-04-23  Simon Josefsson  <jas@extundo.com>
+
+       * netrc.el: New file, functions copied from gnus-util.el by Ted
+       Zlatanov <tzz@lifelogs.com>.
+
+       * gnus-util.el: Require netrc.
+       (gnus-netrc-get, gnus-netrc-machine, gnus-parse-netrc): Aliased to
+       new code in netrc.el.
+
+2002-04-23  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-msg.el (gnus-summary-resend-message-edit): Remove
+       message-ignored-resent-headers, too.  From Matthieu Moy
+       <Matthieu.Moy@imag.fr>.
+
+2002-04-22  Bj\e,Av\e(Brn Torkelsson  <torkel@acc.umu.se>
+
+       * gnus-srvr.el (gnus-server-browse-in-group-buffer): it is a
+       boolean not a string
+       * gnus-group.el (gnus-group-line-format): add description of %C
+       * gnus-group.el (gnus-group-line-format-alist): add gnus-tmp-comment
+         as %C
+       * gnus-group.el (gnus-group-insert-group-line): add gnus-tmp-comment
+
+2002-04-22  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-scan): typo: set
+       nnmaildir-get-new-mail, not nnmaildir-new-mail.  Don't call
+       nnmail-get-new-mail for 'find-new-groups.
+
+2002-04-21  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-update-info,
+       nnmaildir-request-group, nnmaildir-retrieve-groups): remove
+       unnecessary calls to nnmaildir-request-scan.
+
+2002-04-20  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-msg.el:
+       * gnus-msg.el (gnus-message-replysign): New.
+       * gnus-msg.el (gnus-message-replyencrypt): New.
+       * gnus-msg.el (gnus-message-replysignencrypted): New.
+       * gnus-msg.el (gnus-summary-reply): Use the three new variables
+       (above) to automatically encrypt/sign to encrypted/signed
+       messages.
+       * message.el:
+       * message.el (message-mode-map): Add keybinding for
+       `message-to-list-only'
+       * message.el (message-mode): Add description for
+       `message-to-list-only'
+       * message.el (message-to-list-only): New.
+       * message.el (message-make-mft): Changed to use the cl loop macro,
+       and added optional flag to return only the matched list. (for use
+       in new message-to-list-only function)
+
+2002-04-20  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-msg.el:
+       * gnus-msg.el (gnus-message-replysign):
+       * gnus-msg.el (gnus-replysign): New.
+       * gnus-msg.el (gnus-replyencrypt): New.
+       * gnus-msg.el (gnus-replysignencrypted): New.
+       * gnus-msg.el (gnus-summary-reply):
+       * message.el:
+       * message.el (message-mode-map):
+       * message.el (message-mode):
+       * message.el (message-to-list-only): New.
+       * message.el (message-make-mft):
+
+2002-04-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-configure-windows-hook): Fix typo.
+
+2002-04-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * message.el (message-gen-unsubscribed-mft): accept a prefix
+       argument so CC can be included with C-u C-c C-f C-a
+
+2002-04-17  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Ted Zlatanov <teodor.zlatanov@divine.com>.
+
+       * spam.el (spam-whitelist, spam-blacklist, spam-enter-whitelist):
+       Improve docstring.
+       (spam-enter-blacklist): New command.
+
+       * gnus-sum.el (gnus-spam-mark): New mark.
+       (gnus-auto-expirable-marks): Add gnus-spam-mark.
+       (gnus-summary-make-tool-bar): Correct conditional.
+       (gnus-summary-limit-to-unread): Add gnus-spam-mark.
+       (gnus-summary-mark-as-spam): New command.
+
+2002-04-13  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml-sec.el (mml-secure-message): changed to support arbritrary
+       modes.
+       * mml-sec.el (mml-secure-message-encrypt-(smime|pgp|pgpmime)):
+       changed to support "signencrypt" mode.
+       * mml.el (mml-parse-1): changed to support different secure modes
+       more easily. (for signencrypt)
+
+2002-04-11  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * gnus-sum.el (gnus-update-summary-mark-positions)
+       (gnus-summary-toggle-header):
+       * gnus-uu.el (gnus-uu-binhex-article, gnus-uu-reginize-string)
+       (gnus-uu-expand-numbers, gnus-uu-post-make-mime)
+       (gnus-uu-post-encoded):
+       * nnfolder.el (nnfolder-possibly-change-group):
+       * nnimap.el (nnimap-retrieve-headers):
+       * nnmbox.el (nnmbox-create-mbox): Don't assume point-min == 1.
+
+2002-04-08  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * nnml.el (nnml-save-nov, nnml-generate-nov-file):
+       * pop3.el (pop3-md5): Don't hardcode point-min == 1.
+
+2002-04-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-srvr.el (gnus-server-set-info): Clear
+       `gnus-server-method-cache' when `gnus-server-alist' is changed.
+       From Daiki Ueno <ueno@unixuser.org>.
+
+2002-04-11  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-force-verify-and-decrypt): Force
+       viewing of security buttons.  Thanks to Nicolas Kowalski
+       <Nicolas.Kowalski@imag.fr>.
+
+       * smime.el (smime-CA-directory): Fix doc.  Thanks to Arne
+       J\e,Ax\e(Brgensen <arne+usenet@daimi.au.dk>.
+       (smime-sign-buffer): Work in XEmacs.  Thanks to Nicolas Kowalski
+       <Nicolas.Kowalski@imag.fr>.
+       (smime-decrypt-buffer): Ditto.
+
+2002-04-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-prepare): Place point on the emtpy
+       header line.
+
+2002-04-11  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-refer-article-method): Change `dejanews' to `google'.
+
+2002-04-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-delete-marked-with): Fix typo.
+
+2002-04-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text-html-render-with-w3): Don't ignore
+       errors when debug.
+
+2002-04-07  Josh Huber  <huber@alum.wpi.edu>
+
+       * message.el (message-make-mft): Changed MFT code from using
+       message-recipients (which included Bcc) to use only the To and CC
+       headers.
+
+2002-04-05  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (gnus-treat-from-picon): Add to gnus-picon group and
+       add link.
+       (gnus-treat-mail-picon): Ditto.
+       (gnus-treat-newsgroups-picon): Ditto.
+       (gnus-picon-databases): Fix custom type.
+       (gnus-picon-databases): Add link.
+       (gnus-article-x-face-command): Add to gnus-picon group.
+
+2002-04-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.el (message-buffer-naming-style): Remove.
+
+2002-04-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-make-tool-bar): Load tool-bar first.
+
+       * message.el (message-tool-bar-map): Ditto.
+
+       * gnus-sum.el (gnus-summary-make-tool-bar): Ditto.
+
+2002-04-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-mail-archive-article): Fix typo.
+
+2002-04-01  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el: fixed some buggy invocations of nnmaildir--pgname.
+
+2002-03-31  Andrew Cohen  <cohen@andy.bu.edu>
+       Trivial patch.
+
+       * dns.el: open-network-stream under XEmacs does udp.
+
+2002-03-31  Lars Magne Ingebrigtsen  <larsi@quimbies.gnus.org>
+
+       * spam.el (spam-enter-whitelist): New function.
+       (spam-parse-whitelist): Ditto.
+       (spam-refresh-list-cache): Ditto.
+       (spam-address-whitelisted-p): New function.
+
+       * dns.el (query-dns): Use TCP when make-network-process isn't
+       available.
+       (dns-servers): New variable.
+       (dns-parse-resolv-conf): New function.
+       (query-dns): Use it.
+
+       * spam.el: New file.
+
+       * dns.el (query-dns): Test.
+
+2002-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * lpath.el (featurep): Bind make-network-process.
+
+2002-03-31  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el: Use defstruct.  Use a single copy of
+       nnmail-extra-headers to save memory.  Store server's group name
+       prefix instead of each group's prefixed name.
+       * nnnil.el (nnnil-retrieve-headers, nnnil-request-list): Erase
+       nntp-server-buffer.
+
+2002-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * dns.el: New file.
+
+2002-03-28  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-dummy-line-format):
+       * gnus.el (gnus-summary-line-format): Fixing links to Info.
+       Trivial change from Bj\e,Av\e(Brn Torkelsson <torkel@pdc.kth.se>.
+
+2002-03-29  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-summary-move-article)
+       (gnus-summary-copy-article): Mention `gnus-move-split-methods' in
+       the doc string.
+
+2002-03-28  Simon Josefsson  <jas@extundo.com>
+
+       * mml-sec.el (mml-secure-message): Search after
+       mail-header-separator from top of message.
+
+2002-03-28  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el: Cosmetic changes.
+       (nnmaildir--with-nntp-buffer, nnmaildir--with-work-buffer,
+       nnmaildir--with-nov-buffer, nnmaildir--with-move-buffer,
+       nnmaildir--group-ls): New macros/functions.  Use them.
+       (nnmaildir--unlink): Evalutate argument only once.
+
+2002-03-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-sum.el (gnus-summary-highlight): Use `eq' when comparing
+       symbols.
+       (gnus-summary-highlight-line): Use `gnus-point-at-bol' and
+       `gnus-point-at-eol'.
+
+2002-03-27  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--subdir, nnmaildir--nov-dir,
+       nnmaildir--marks-dir): New macros.  Use them.
+       Use inhibit-quit for atomicity instead of in-memory journaling.
+       (nnmaildir--edit-prep): New function.
+       (Local Variables): Use it.
+
+2002-03-26  Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk)
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Fix typo.
+
+2002-03-25  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-mode): Fix doc.
+
+2002-03-25  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-subject-re-regexp): Skip Re[42]: junk.  From
+       Matthieu Moy <Matthieu.Moy@imag.fr>.
+
+2002-03-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * mml-sec.el (mml-unsecure-message): Add docstring.
+
+2002-03-23  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-large-newsgroup): Fix doc, allow non-numeric
+       value.
+       Trivial change from andre@slamdunknetworks.com
+
+2002-03-22  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml.el (mml-mode-map): Added a keybinding for
+       `mml-unsecure-message'.  Also, added a menu entry for said
+       function in the Attachments menu.
+
+2002-03-22  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el (canlock-version): Remove.
+       (canlock-sha1-with-openssl): Don't use `canlock-string-as-unibyte'
+       here; simplify \x insertions.
+       (canlock-sha1): New function, always return a unibyte string.
+       (canlock-make-cancel-key): Use `canlock-sha1'; simplify truncation
+       of a password.
+       (canlock-insert-header): Use `canlock-sha1'.
+       (canlock-verify): Ditto.
+
+2002-03-21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-fix-before-sending): Add an option that
+       ignores illegible text.
+       Trivial change from Mark Milhollan <mlm@attglobal.net>
+
+       * message.el (message-font-lock-keywords): Support multi-line MML
+       tags.
+
+       * gnus-sum.el (gnus-print-buffer): Remove gnus-decoration.
+       Trivial change from lorentey@elte.hu (L\e,Bu\e(Brentey K\e,Aa\e(Broly)
+
+2002-03-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Use intern'ed function
+       symbols for "View as different encoding" submenu.
+
+2002-03-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add "View as different
+       encoding" submenu.
+
+2002-03-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-process-prefix): Make sure there is a mark.
+
+2002-03-19  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-sum-thread-tree-root)
+       (gnus-sum-thread-tree-single-indent)
+       (gnus-sum-thread-tree-vertical, gnus-sum-thread-tree-indent)
+       (gnus-sum-thread-tree-leaf-with-other)
+       (gnus-sum-thread-tree-single-leaf): Make customizable.
+
+2002-03-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-util.el (gnus-extract-address-components): Don't break on
+       names such as James "Kibo" Parry.  From Francis Litterio
+       <franl@world.std.com>.
+
+2002-03-13  Simon Josefsson  <jas@extundo.com>
+
+       * pop3.el (pop3-open-server): Revert multibyte change.  From
+       Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk).
+
+       * message.el (message-send-mail-with-qmail): Make it work.  From
+       Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk).
+
+2002-03-13  Josh Huber  <huber@alum.wpi.edu>
+
+       * message.el (message-make-mft): Set case-fold-search while
+       generating the MFT.  Also, a little cleanup in the MFT code.
+
+2002-03-12  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-qmail-inject-args): May be function.
+       (message-send-mail-with-qmail): Call function if m-q-i-a is
+       function.  From fn@hungry.org (Faried Nawaz).
+
+2002-03-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-abbrevs-loaded): Remove.
+       (mailabbrev): Require it.
+
+       * nnslashdot.el (nnslashdot-request-article): Remove IFRAME.
+
+2002-03-12  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * pop3.el (pop3-open-server): Set process buffer unibyte.
+
+2002-03-10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-subscribe-to-mailing-list): New function.
+
+2002-03-10  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-request-article): Remove javascript
+       too.
+
+2002-03-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-save-parts-default-mime): Remove
+       duplication.
+       (gnus-summary-save-parts-type-history): Ditto.
+       (gnus-summary-save-parts-last-directory): Ditto.
+       Trivial change from andre@slamdunknetworks.com
+
+2002-03-09  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-start.el (gnus-auto-subscribed-groups): Include nnmaildir.
+
+2002-03-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-request-article): Use "<!-- no ad 6
+       -->" as the end of the first article.
+
+       * gnus-msg.el (gnus-summary-resend-message-edit): New function.
+       From Matthieu Moy <Matthieu.Moy@imag.fr>
+
+       * message.el (message-add-action): Use add-to-list.
+       (message-delete-action): New function.
+
+       * nndoc.el (nndoc-mail-in-mail-type-p): Break a long regexp into
+       pieces.
+
+2002-03-05  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnnil.el: New file.
+       * gnus.el (gnus-valid-select-methods): Include nnnil.
+
+2002-03-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-syntax-checks): Because canlock is
+       supported, we disable sender syntax check.
+       (message-shoot-gnksa-feet): Add cancel-messages option doc.
+
+       * gnus-draft.el (gnus-draft-send): If interactive, use its default
+       value of message-syntax-checks.
+
+       * qp.el (quoted-printable-decode-region): Doc addition.
+       From: Eli Zaretskii <eliz@is.elta.co.il>
+
+       * mail-source.el (make-source-make-complex-temp-name): Use
+       make-temp-file.
+
+       * mm-util.el (mm-make-temp-file): New function.
+       * nneething.el (nneething-file-name): Use it.
+       * mml-smime.el (mml-smime-encrypt): Ditto.
+       * mm-view.el (mm-inline-wash-with-file): Ditto.
+       * mm-decode.el (mm-display-external, mm-create-image-xemacs): Ditto.
+       * gnus-uu.el (gnus-uu-decode-binhex, gnus-uu-decode-binhex-view)
+       (gnus-uu-digest-mail-forward, gnus-uu-initialize): Ditto.
+       * gnus-start.el (gnus-slave-save-newsrc): Ditto.
+       * gnus-fun.el (gnus-convert-image-to-gray-x-face): Ditto.
+       * gnus-art.el (gnus-mime-print-part): Ditto.
+
+2002-03-04  Paul Jarc  <prj@po.cwru.edu>
+
+       * message.el (nnmaildir-article-number-to-base-name): New
+       function.
+       (nnmaildir-base-name-to-article-number): New function.
+
+2002-03-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * smime.el (smime-make-temp-file): Don't quote
+       `temporary-file-directory'.
+
+2002-03-04  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-sign-region): Rename argument keyfiles to
+       keyfile. You only sign something with one key.
+       (smime-sign-buffer): Better completing-read prompt.
+       (smime-decrypt-buffer): Ditto.
+
+       * smime.el (smime-make-temp-file): Make it work under XEmacs.
+
+       * mm-view.el (mm-view-pkcs7-decrypt): Better prompt for
+       completing-read.
+       (mm-view-pkcs7-decrypt): CRLF->LF.
+
+2002-03-04  Paul Jarc  <prj@po.cwru.edu>
+
+       * message.el (message-hierarchical-addresses): New variable.
+       (message-get-reply-headers): Use it.
+       From Ted Zlatanov <teodor.zlatanov@divine.com>
+
+2002-03-03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mode): If buffer-file-name, don't set auto
+       save file name.
+       Trivial change from Geoff Greene <ggreene@wpi.edu>
+
+2002-03-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-multiple-choice): Use message. XEmacs only
+       takes one argument in read-char.
+
+       * message.el (message-fix-before-sending): Forward a char.
+       Check mmu-multibyte-p, add control-1.
+
+2002-03-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-read-init-file): Ditto.
+
+       * gnus-agent.el (gnus-agent-fetch-session): Ditto.
+
+       * dgnushack.el (dgnushack-make-load): Ditto.
+
+       * mail-source.el (mail-source-fetch): Extract the right error
+       code.
+
+       * message.el (message-fix-before-sending): Check illegible text.
+
+       * gnus-util.el (gnus-multiple-choice): New function.
+
+       * gnus-kill.el (gnus-score-insert-help): Removed, because it is
+       also defined in gnus-score.el.
+
+2002-03-01  Paul Jarc  <prj@po.cwru.edu>
+
+       * message.el (message-get-reply-headers): downcase email addresses
+       for comaparisons for duplicate removal.
+
+2002-03-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-view-pkcs7-verify): New function. A bogus
+       implementation of PKCS#7, which just allows users read the
+       message.
+       (mm-view-pkcs7): Use it.
+
+2002-02-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (large-newsgroup-initial): New parameter.
+
+       * gnus-sum.el (gnus-articles-to-read): Use large-newsgroup-initial.
+       (gnus-summary-insert-old-articles): Ditto.
+
+2002-02-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-articles-to-read): `gnus-large-newsgroup' is
+       used as the default answer of the question, "How many articles?".
+       From TSUCHIYA Masatoshi <tsuchiya@namazu.org>
+
+       * nnagent.el (nnagent-retrieve-headers): Remove articles with
+       small numbers.
+
+2002-02-24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * deuglify.el: Fix comments.
+
+2002-02-23  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * html2text.el (html2text-clean-anchor): If there is no HREF,
+       insert nothing.
+
+       * mml.el (mml-generate-mime-1): Add cdr.
+       From: andre@slamdunknetworks.com
+
+       * mm-view.el (mm-text-html-renderer-alist): Add html2text.
+       (mm-text-html-washer-alist): Ditto.
+
+       * mm-decode.el (mm-text-html-renderer): Add html2text.
+
+       * html2text.el: Face lift.
+
+       * html2text.el: New file from Joakim Hove <hove@phys.ntnu.no>.
+
+2002-02-22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el: Add gnus-article-outlook-deuglify-article.
+
+       * deuglify.el: Change copy right. Add autoload. Add coding-system.
+
+       * deuglify.el: New file. The original file name is
+       gnus-outlook-deuglify.el from Raymond Scholz <rscholz@zonix.de>.
+
+       * mm-decode.el (mm-display-external): Use
+       mm-file-name-rewrite-functions.  From <andre@slamdunknetworks.com>
+
+2002-02-22  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-list): Report the highest
+       article number, not the total number of articles.
+
+2002-02-21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el: Move uu key map here.
+       (gnus-summary-make-menu-bar): Add gnus-summary-save-parts.
+
+2002-02-21  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-expire-articles): Use
+       nnmail-expiry-wait* if expire-age parameter is not set.
+
+2002-02-21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-sort-groups-by-real-name): New
+       function.
+       (gnus-group-sort-selected-groups-by-real-name): New function.
+       (gnus-group-make-menu-bar): Add sort by real name.
+
+       * gnus-sum.el (gnus-dependencies-add-header): If replaced, don't
+       rebuild.
+       (gnus-summary-edit-article-done): Gnus-get-newsgroup-headers takes
+       nil as dependencies as well.
+
+2002-02-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-dissect-mime-parts-sub): Fix MIME-Version header
+       for mime-parts.
+
+       * gnus-art.el (gnus-article-edit-done): Widen the buffer.
+
+       * gnus-group.el (gnus-group-name-decode): Don't test
+       multibyte-string, because it breaks XEmacs.
+       From: TSUCHIYA Masatoshi <tsuchiya@pine.kuee.kyoto-u.ac.jp>
+
+       * message.el (message-send-mail): Be talkative.
+
+       * mm-decode.el (mm-inlined-types): Add application/x-emacs-lisp.
+       (mm-automatic-display): Ditto.
+
+       * mailcap.el (mailcap-mime-data): Ditto.
+       From: Reiner Steib <4uce.02.r.steib@gmx.net>
+
+2002-02-20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * many files: Remove trailing whitespaces, replace spc+tab with
+       tab, replace leading whitespaces with tabs.
+
+2002-02-19  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Fix handling of
+       articles with no body and no blank line after the header.
+
+2002-02-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-multipart): Consider the case of empty
+       parts.
+
+       * ietf-drums.el (ietf-drums-syntax-table): Modify syntax of
+       non-ascii chars.
+
+       * rfc2231.el (rfc2231-parse-string): Support non-ascii chars.
+
+       * gnus-art.el (gnus-article-wash-html-with-w3): Remove
+       w3-delay-image-loads.
+       * mm-view.el (mm-inline-text-html-render-with-w3): Ditto.
+       (mm-w3-prepare-buffer): Ditto.
+
+       * mail-source.el (mail-source-fetch-directory): Run scripts.
+
+2002-02-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-respond-to-confirmation): Do the right thing
+       for Majordomo confirmations.
+
+2002-02-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-respond-to-confirmation): New command.
+
+2002-02-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Clean up.
+
+2002-02-18  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-util.el (gnus-parent-id): Ignore trailing whitespace in the
+       References header field.  From Mark Thomas <mthomas@cmu.edu>.
+
+2002-02-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-render-with-file): With unibyte buffer.
+       (mm-inline-render-with-stdin): Ditto.
+       (mm-inline-render-with-function): Ditto.
+       (mm-inline-wash-with-file): Bind coding-system-for-write.
+       (mm-inline-wash-with-stdin): Ditto.
+
+2002-02-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       Suggested by Felix Natter <fnatter@gmx.net>
+
+       * gnus-art.el (gnus-mime-view-part-externally): Rename from
+       gnus-mime-externalize-view.
+       (gnus-mime-view-part-internally): Rename from
+       gnus-mime-internalize-view.
+       (gnus-article-view-part-externally): Rename from
+       gnus-article-externalize-part.
+       (gnus-mime-action-alist): Change correspondingly.
+       (gnus-mime-button-commands): Ditto.
+       (gnus-mime-action-alist): Remove duplication.
+
+       * gnus-sum.el (gnus-summary-mime-map): Change correspondingly.
+
+2002-02-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-buffer): Add loose-mime parameter.
+
+       * gnus-art.el (gnus-display-mime): Use it.
+
+       * mm-partial.el (mm-partial-find-parts): Use it.
+
+       * gnus-sum.el (gnus-article-loose-mime): Rename from
+       gnus-article-no-strict-mime.
+       (gnus-summary-save-parts): Use it.
+
+2002-02-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Remove unused
+       local variable.
+
+       * gnus-art.el (article-display-x-face): Don't sort multiple
+       X-Faces.
+
+2002-02-18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Improved to speed
+       up.  Suggested by Yuuichi Teranishi <teranisi@gohome.org>.
+
+       * gnus-art.el (article-display-x-face): Sort gray X-Faces.
+
+2002-02-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       Some ideas is inspired by code from Hrvoje Niksic
+       <hniksic@arsdigita.com>
+
+       * gnus-art.el (gnus-article-wash-function): Set the default to
+       nil, so that we use mm-text-html-renderer instead.
+       (article-wash-html): Use mm-text-html-renderer.
+
+       * mm-decode.el (mm-inline-media-tests): Use mm-inline-text-*.
+       (mm-text-html-renderer): New variable.
+       (mm-inline-text-html-renderer): Set the default to nil, so that we
+       use mm-text-html-renderer instead.
+
+       * mm-view.el (mm-inline-text-html): New function.
+       (mm-text-html-renderer-alist): New variable.
+       (mm-inline-text-vcard): New function.
+       (mm-inline-text): Split.
+       (mm-links-remove-leading-blank): New function.
+       (mm-inline-render-with-file): New function.
+       (mm-inline-render-with-stdin): New function.
+       (mm-inline-render-with-function): New function.
+       (mm-text-html-washer-alist): New variable.
+       (mm-inline-wash-with-file): New function.
+       (mm-inline-wash-with-stdin): New function.
+
+2002-02-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message-utils.el: Fix installation doc.
+       From: Reiner Steib <4uce.02.r.steib@gmx.net>
+
+2002-02-16  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-discouraged-post-methods): New variable.
+       (gnus-post-method): Use it.
+       (gnus-summary-cancel-article): Find the correct post-method.
+
+       * gnus-soup.el (gnus-soup-send-packet): Via ... using ...
+       * message.el (message-send-news): Ditto.
+       Suggested by Lloyd Zusman <ljz@asfast.com> and IPmonger
+       <ipmonger@delamancha.org>
+
+       * gnus.el (gnus-select-method): Fix doc.
+       (gnus-server-string): Use 'using nntp'.
+
+       * gnus-agent.el (gnus-slave-unplugged): New command.
+       From: Felix Natter <fnatter@gmx.net>
+
+2002-02-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-edit-done): Kill-all-local-variables.
+       Call edit-done-function first, then change the window
+       configuration.
+       (gnus-article-edit-mode-map): Add message key bindings. Add menu.
+       (gnus-article-edit-mode): mml-mode.
+
+       * gnus-util.el (gnus-byte-compile): Work around a bug in XEmacs
+       21.4. Suggested by Russ Allbery <rra@stanford.edu> .
+
+       * message-utils.el: Adopt the file.
+
+       * message-utils.el: New file.
+       From Holger Schauer <Holger.Schauer@gmx.de>
+
+2002-02-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-move-article): Select-article only
+       when gnus-move-split-methods is non-nil. And we don't render or
+       mark the article.
+
+       * gnus-fun.el (gnus-shell-command-to-string): New function.
+       (gnus-shell-command-on-region): New function.
+       (gnus-random-x-face): Use them.
+       (gnus-x-face-from-file): Ditto.
+       (gnus-convert-image-to-gray-x-face): Ditto.
+       (gnus-convert-gray-x-face-to-xpm): Ditto.
+       (gnus-convert-image-to-x-face-command): Don't use 2>/dev/null.
+
+2002-02-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-treat-display-xface): Don't use
+       `shell-command-to-string' when compiling.
+       (gnus-treat-display-grey-xface): Ditto.
+
+2002-02-13  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--article-count): If the group is
+       completely empty, report minimum article number as 1 instead of 0.
+
+2002-02-13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-get-predicate): Use nconc.
+
+       * gnus-sum.el (gnus-summary-display-make-predicate): Use
+       gnus-summary-display-cache as cache.
+
+       * nndoc.el (nndoc-type-alist): Add mail-in-mail type.
+       (nndoc-mail-in-mail-type-p): New function.
+       (nndoc-mail-in-mail-article-begin): New function.
+
+2002-02-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-mime-data): Use enriched-decode.
+
+       * gnus-cite.el (gnus-article-fill-cited-article): Bind
+       use-hard-newlines to nil.
+
+       * gnus-xmas.el (gnus-xmas-image-type-available-p): Assume that
+       image is not available if window-system is not available.
+
+       * gnus-sum.el (gnus-summary-display-make-predicate): Add unread.
+
+2002-02-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-article-unpropagated-mark-lists): Don't propagate
+       bookmark, because update-mark doesn't handle it correctly.
+
+2002-02-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-soup.el (gnus-soup-send-packet): Send news and mail
+       directly instead of calling message-send-mail.
+
+       * gnus-start.el (gnus-read-descriptions-file): Use
+       gnus-default-charset.
+
+       * mm-util.el (mm-guess-mime-charset): New function.
+
+       * gnus.el (gnus-default-charset): Use it.
+       (gnus-group-charset-alist): Remove .*, Let gnus-default-charset be
+       the default.
+
+2002-02-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-treat-display-grey-xface): New variable.
+       (article-display-x-face): Use it.  Disable grey xface, if
+       uncompface is not found.
+
+       * message.el (message-mode): Don't enable multibyte on an indirect
+       buffer.
+
+       * nnrss.el (nnrss-content-function): New variable.
+       (nnrss-request-article): Use it.
+
+2002-02-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: Add article-unsplit-urls.
+       * gnus-sum.el: Ditto.
+       * gnus-art.el (gnus-treat-strip-cr): New variable.
+       (gnus-treatment-function-alist): Use it.
+       (article-unsplit-urls): New function.
+       (gnus-article-make-menu-bar): Use it.
+       From: Michael Cook <michael.cook@cisco.com>
+
+2002-02-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-braid-nov): Find the first article to
+       copy.
+
+2002-02-07  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus-util.el (gnus-split-references): Allow (broken) Message-IDs
+       with internal whitespace.
+       (gnus-parent-id): Ditto.
+
+2002-02-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-treat-body-boundary): Add
+       gnus-decoration property.
+       * gnus-msg.el (gnus-copy-article-buffer): Remove gnus-decoration.
+
+       * message.el (message-mode): Set local-abbrev-table.
+       From Matt Armstrong <matt@lickey.com>.
+
+       * gnus-art.el (gnus-article-treat-unfold-headers): Don't remove
+       too many spaces.
+
+       * rfc2047.el (rfc2047-unfold-region): Ditto.
+       (rfc2047-decode-region): Don't unfold. Let
+       gnus-article-treat-unfold-headers do it.
+
+       * gnus-sum.el (gnus-dependencies-add-header): Fix typo.
+       From: Jesper Harder <harder@ifa.au.dk>
+
+2002-02-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-posting-styles): Add x-face-file.
+       (gnus-configure-posting-styles): Use it.
+       (gnus-configure-posting-styles): Remove trailing newspaces.
+
+2002-02-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-articles-to-read): Fetch all if the predicate
+       is non-nil.
+
+       * mm-util.el (mm-use-find-coding-systems-region): Add doc.
+
+       * gnus.el (gnus-server-to-method): Switch position with
+       gnus-server-get-method.
+       (gnus-agent): Add doc.
+
+       * gnus-sum.el (gnus-article-no-strict-mime): New variable.
+       (gnus-summary-save-parts): Use it.
+
+       * gnus-art.el (gnus-display-mime): Use it.
+       * mm-partial.el (mm-partial-find-parts): Use it.
+
+       * nnweb.el (nnweb-google-parse-1): Use a correct format of date.
+
+       * gnus-agent.el (gnus-agent-summary-make-menu-bar): Fix typo.
+       From Stefan Reich\e,Av\e(Br <xsteve@riic.at>.
+
+       * nnagent.el (nnagent-request-expire-articles): Don't delete
+       files.
+
+2002-02-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-gen-unsubscribed-mft): New function.
+       From Sriram Karra <karra@cs.utah.edu>.
+
+       * gnus.el (gnus-article-unpropagated-mark-lists): Backslash the
+       open parenthesis.
+
+       * mm-view.el (mm-w3-prepare-buffer): Bind url-gateway-unplugged.
+       (mm-inline-text-html-render-with-w3): Ditto.
+       * gnus-art.el (gnus-article-wash-html-with-w3): Ditto.
+       Suggested by Dave Love  <d.love@dl.ac.uk>.
+
+       * mm-url.el (mm-url-load-url): Require w3-vars for old versions.
+
+       * nntp.el (nntp-send-command-and-decode): Check PROCESS.
+       * nntp.el (nntp-send-command): Ditto.
+       * nntp.el (nntp-send-command-nodelete): Ditto.
+
+2002-02-04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el (mm-url-load-url): New function.
+       (mm-url-insert-file-contents): Use it.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Use gnus-article-charset.
+
+       * message.el (message-forward-make-body): Correctly copy
+       forward-buffer.
+
+       * rfc2047.el (rfc2047-decode-region): Don't decode us-ascii characters.
+
+2002-02-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-article-followup-with-original): Mark with
+       force, prevent errors when following up from article buffer.
+       (gnus-article-reply-with-original): Ditto.
+
+       * binhex.el (binhex-decoder-switches): Fix doc.  From
+       Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk).
+
+2002-02-04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-treatment-function-alist): Move hide-citation,
+       highlight-citation after emphasize.
+
+2002-02-04  Simon Josefsson  <jas@extundo.com>
+
+       * nnfolder.el (nnfolder-open-marks):
+
+       * nnml.el (nnml-open-marks): Message when done.  From David
+       Edmondson <dme@sun.com>.
+
+2002-02-03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * imap.el (imap-anonymous-auth): Fix typo.
+       From: Steinar Bang <sb@dod.no>
+
+       * gnus-cache.el (gnus-cache-braid-nov): Use set-buffer instead of
+       save-excursion.
+       (gnus-cache-braid-heads): Ditto.
+
+       * gnus-agent.el (gnus-agent-copy-nov-line): Move to the correct
+       line, because there are extra articles in the overview buffer.
+
+       * nntp.el (nntp-retrieve-groups): Check whether BUF is live.
+
+       * message.el (message-forward-rmail-make-body): Directly use
+       rmail-msg-restore-non-pruned-header to avoid calling
+       vertical-motion.
+
+2002-02-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-summary-insert-cached-articles):
+       (gnus-summary-limit-include-cached): gnus-newsgroup-cached is sorted.
+
+       * gnus-group.el (gnus-group-mark-article-read): Nreverse
+       gnus-newsgroups-unselected.
+
+       * gnus-agent.el (gnus-summary-set-agent-mark): Use
+       gnus-add-to-sorted-list.
+
+       * gnus-sum.el (gnus-summary-update-info): gnus-newsgroup-unreads
+       gnus-newsgroup-unselected are sorted. Use gnus-sorted-union.
+       (gnus-build-all-threads): Use gnus-add-to-sorted-list.
+       (gnus-update-read-articles): UNREAD is sorted.
+       (gnus-newsgroup-unreads, gnus-newsgroup-unselected)
+       (gnus-newsgroup-marked, gnus-newsgroup-cached)
+       (gnus-newsgroup-expirable, gnus-newsgroup-downloadable)
+       (gnus-newsgroup-dormant): Require sorted.
+
+       * gnus-dired.el (gnus-dired-find-file-mailcap): Correctly handle
+       directories.
+       (gnus-dired-print): New function.
+
+       * gnus-art.el (gnus-mime-print-part): Add argument filename. Call
+       ps-despool.
+
+2002-02-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-dired.el (turn-on-gnus-dired-mode): Autoload.  Make defun.
+
+2002-02-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-1): Call gnus-agentize if gnus-agent is
+       t. This makes gnus-agent customizable without putting
+       gnus-agentize into .gnus.
+
+       * gnus.el (gnus-agent): Make it customizable.
+
+       * gnus-dired.el: New file.
+       From Benjamin Rutt <brutt@bloomington.in.us>
+
+       * gnus-cache.el (gnus-cache-articles-in-group): Remove from active
+       if no article.
+       (gnus-cache-possibly-remove-article): Ditto.
+       (gnus-cache-possibly-enter-article): Use gnus-add-to-sorted-list.
+
+2002-02-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-int.el (gnus-request-accept-article): Use gnus-get-function.
+
+2002-02-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.el (mm-w3m-mode-dont-bind-keys): New variable.
+       (mm-setup-w3m): Don't bind keys listed in the above.
+
+2002-02-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.el (mm-inline-text-html-render-with-w3m): Bind
+       `w3m-safe-url-regexp' with nil if `mm-inline-text-html-with-images'
+       is non-nil; bind `w3m-force-redisplay' with nil.
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Ditto.
+
+       * mm-decode.el (mm-inline-text-html-with-images): Supplement docs.
+
+2002-01-31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-replace-article): Unfold. Don't
+       use mail-header-unfold-field.
+
+       * gnus-cache.el (gnus-summary-insert-cached-articles): Use
+       gnus-summary-limit.
+
+       * gnus-range.el (gnus-add-to-sorted-list): New function.
+       * gnus-sum.el (gnus-mark-article-as-read): Use it.
+       (gnus-mark-article-as-unread): Ditto.
+       (gnus-summary-mark-article-as-unread): Ditto.
+       (gnus-build-get-header): Ditto.
+       (gnus-summary-prepare-threads): Ditto.
+       (gnus-summary-insert-pseudos): Ditto.
+       (gnus-articles-to-read): Use gnus-sorted-union and gnus-sorted-nunion.
+       (gnus-summary-insert-new-articles): Use gnus-sorted-nunion.
+       (gnus-summary-insert-old-articles): Ditto.
+
+       * gnus-msg.el (gnus-posting-styles): Add new format of header.
+       (gnus-configure-posting-styles): Support the new format.
+
+       * mail-source.el (mail-source-bind, mail-source-bind-common): Set
+       edebug-form-spec to (sexp body).
+       Suggested by Joe Wells <jbw@izanami.cee.hw.ac.uk>.
+
+       * message.el (message-reply-headers): Add doc.
+
+2002-01-30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-delete-group): Nix the entry in
+       gnus-cache-active-hashtb.
+
+       * gnus-agent.el (gnus-agent-mark-unread-afer-downloaded): New variable.
+       (gnus-agent-summary-fetch-group): Use it.
+
+       * gnus-msg.el (gnus-debug-files): New variable.
+       (gnus-debug-exclude-variables): New variable.
+       (gnus-debug): Use them.
+
+       * gnus-range.el (gnus-range-length): Don't use gnus-uncompress-range.
+
+2002-01-30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cite-prefix-regexp): Use text-mode-syntax-table.
+       (message-mode-syntax-table): Move back the previous position.
+
+       * nnagent.el (nnagent-retrieve-headers): Use gnus-sorted-difference.
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Use
+       gnus-sorted-difference.
+
+       * nnsoup.el (nnsoup-request-expire-articles): Use
+       gnus-sorted-difference.
+
+       * nnheader.el: Autoload gnus-sorted-difference.
+
+       * nnfolder.el (nnfolder-request-expire-articles): Use
+       gnus-sorted-difference.
+
+       * gnus-cache.el (gnus-cache-retrieve-headers): Use
+       gnus-sorted-difference.
+
+       * gnus-range.el: Autoload cookies.
+       (gnus-sorted-difference): New function.
+       (gnus-sorted-ndifference): New function.
+       (gnus-sorted-nintersection): Rename from
+       gnus-set-sorted-intersection.
+       (gnus-sorted-nunion): Rename from gnus-set-sorted-union.
+       (gnus-list-range-difference): Rename from
+       gnus-inverse-list-range-intersection.
+       (gnus-inverse-list-range-intersection): Use defalias.
+
+       * gnus-sum.el (gnus-select-newsgroup): Use gnus-sorted-difference,
+       gnus-sorted-ndifference, and gnus-sorted-nintersection.
+       (gnus-articles-to-read): Use gnus-sorted-difference.
+       (gnus-summary-limit-mark-excluded-as-read): Use
+       gnus-sorted-intersection and gnus-sorted-ndifference.
+       (gnus-list-of-read-articles): Use gnus-list-range-difference.
+       (gnus-summary-insert-articles): Use gnus-sorted-difference.
+
+       * gnus-sum.el (gnus-summary-update-info): Use gnus-sorted-union.
+
+2002-01-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Add keymap
+       property to the buffer for using emacs-w3m command keys.
+
+       * mm-decode.el (mm-inline-text-html-with-w3m-keymap): New user
+       option.
+
+       * mm-view.el (mm-w3m-mode-map): New variable.
+       (mm-w3m-mode-command-alist): New variable.
+       (mm-w3m-minor-mode): Removed.
+       (mm-setup-w3m): Setup `mm-w3m-mode-map'; don't add minor mode.
+       (mm-inline-text-html-render-with-w3m): Add keymap property to the
+       buffer for using emacs-w3m command keys.
+
+2002-01-29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mode-syntax-table): Move forward.
+       (message-cite-prefix-regexp): Auto detect non word constituents.
+       (message-cite-prefix-regexp): Don't use with-syntax-table.
+
+       * gnus-sum.el (gnus-summary-update-info): Use
+       gnus-list-range-intersection.
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Use
+       gnus-list-range-intersection.
+
+       * gnus-range.el (gnus-range-normalize): Use correct predicate.
+       (gnus-list-range-intersection): Use it.
+       (gnus-inverse-list-range-intersection): Ditto.
+       (gnus-sorted-intersection): Add doc.
+       (gnus-set-sorted-intersection): Add doc.
+       (gnus-sorted-union): New function.
+       (gnus-set-sorted-union): New function.
+
+       * gnus-range.el (gnus-list-range-intersection): Correct the logic.
+       (gnus-inverse-list-range-intersection): Ditto.
+
+2002-01-29  Karl Kleinpaste  <karl@charcoal.com>
+
+       * mm-uu.el (mm-uu-type-alist): Add optional leading `0'.
+
+       * gnus-uu.el (gnus-uu-shar-name-marker): Add optional leading `0'
+       and permit `:' and `\' in order to handle full Windows pathnames.
+       (gnus-uu-begin-string): Add optional leading `0'.  Leading `0' is
+       technically not correct per standard, but seems to have common use.
+
+2002-01-29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-uu.el (gnus-uu-expand-numbers): Ignore errors when
+       replacing numbers.
+
+2002-01-28  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-followup-with-original): Use (mark).
+
+       * gnus-score.el (gnus-score-insert-help): Move to (point-min).
+       Don't split when the window is small, e.g. when a small *BBDB*
+       window is the lowest one.
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Use
+       nnheader-find-nov-line to speed up. Use nreverse, because it is
+       sorted. Use nnheader-insert-nov-file.
+
+2002-01-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-decode.el (mm-inline-text-html-with-images): New user option.
+
+       * mm-view.el (mm-inline-text-html-render-with-w3m): Bind the value
+       of `w3m-display-inline-images' with the value of
+       `mm-inline-text-html-with-images'.
+       From: TSUCHIYA Masatoshi <tsuchiya@namazu.org>.
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Ditto.
+
+2002-01-27  Richard M. Stallman  <rms@gnu.org>
+
+       * time-date.el: Add autoload cookies.  Many doc fixes.
+       (time-add): New function.
+       (time-subtract): Renamed from subtract-time.
+       (subtract-time): New alias for time-subtract.
+
+2002-01-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Replace w3m to
+       emacs-w3m in doc-string.
+
+       * lpath.el: Bind `w3m-cid-retrieve-function-alist' and
+       `w3m-current-buffer'.
+
+2002-01-27  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Handle cid: URLs.
+
+       * mm-view.el (mm-setup-w3m): Add `mm-w3m-cid-retrieve' to
+       `w3m-cid-retrieve-function-alist' for `gnus-article-mode'.
+       (mm-w3m-cid-retrieve): New function.
+       (mm-inline-text-html-render-with-w3m): Handle cid: URLs.
+
+2002-01-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-articles): Don't save empty articles.
+
+2002-01-27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-cache-file-contents): Don't use equalp.
+
+2002-01-26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el (nnheader-insert-nov-file): Increased cutoff to
+       32K.
+
+       * gnus-sum.el (gnus-summary-expire-articles): Clean up.
+
+       * nnmail.el (nnmail-article-group): Decode headers before running
+       split rules over them.
+       (nnmail-mail-splitting-charset): New variable.
+
+       * smiley.el: Replaced with smiley-ems.el.
+
+2002-01-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el (mm-url-predefined-programs): Add w3m.
+       (mm-url-program): Ditto.
+
+2002-01-26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnml.el (nnml-use-compressed-files): New variable.
+       (nnml-filenames-are-evil): Removed.
+       (nnml-current-group-article-to-file-alist): Don't use.
+       (nnml-update-file-alist): Inhibit.
+       (nnml-article-to-file): Use new var.
+
+2002-01-26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-parse-without-error): Add edebug-form-spec.
+
+       * nnagent.el (nnagent-retrieve-headers): loop until eobp.
+
+2002-01-26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-load-alist): Use new caching
+       function.
+
+       * gnus-util.el (gnus-cache-file-contents): New function.
+
+       * gnus-agent.el (gnus-agent-file-loading-cache): New variable.
+       (gnus-agent-load-alist): Use it.
+
+       * nnagent.el (nnagent-retrieve-headers): Use optimized function.
+
+       * nnheader.el (nnheader-insert-nov-file): New function.
+
+       * gnus-util.el (gnus-parse-without-error): Correct the loop.
+
+       * gnus-sum.el (gnus-dependencies-add-header): Use in-reply-to if
+       there are no references.
+       (gnus-extract-message-id-from-in-reply-to): New function.
+       (gnus-nov-parse-line): Use in-reply-to if there are no
+       references.
+
+2002-01-25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnagent.el (nnagent-retrieve-headers): Use new macro.
+
+       * gnus-util.el (gnus-parse-without-error): New macro.
+
+2002-01-25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-wash-html-with-w3m): Call w3m-region.
+       (gnus-article-wash-function): use locate-library to decide which
+       to use.
+
+2002-01-25  Simon Josefsson  <jas@extundo.com>
+
+       * pop3.el (pop3-munge-message-separator): Work if no date.
+       Trivial patch from Marius Vollmer <mvo@zagadka.ping.de>.
+
+2002-01-25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-save-alist): Fix.
+
+       * nnagent.el (nnagent-retrieve-headers): Must have cut too much by
+       mistake.  Reinstated lost code.
+
+2002-01-25  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml2015.el (mml2015-mailcrypt-decrypt): Display a signature if
+       one exists in the case of an encrypted message with an internal
+       signature.
+
+2002-01-25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-save-alist): Optimized.
+
+2002-01-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el: Commented out the experimental code.
+
+2002-01-25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-range.el (gnus-inverse-list-range-intersection): Off-by-one
+       error.
+
+       * gnus.el (gnus-server-to-method): Made into subst.
+       (gnus-server-method-cache): New variable.
+       (gnus-server-to-method): Use it.
+       (gnus-group-method-cache): New variable.
+       (gnus-find-method-for-group-1): Renamed.
+       (gnus-find-method-for-group): New function.
+       (gnus-group-method-cache): Removed.
+
+       * gnus-sum.el (gnus-compute-unseen-list): Use new optimized
+       function.
+
+       * gnus-range.el (gnus-members-of-range): New function.
+       (gnus-list-range-intersection): Renamed.
+       (gnus-inverse-list-range-intersection): New function.
+
+       * gnus-sum.el (gnus-compute-unseen-list): Made into own function.
+
+       * nnagent.el (nnagent-retrieve-headers): New implementation.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): New, faster
+       implementation.
+
+2002-01-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Fbind `w3m-charset-to-coding-system'; bind
+       `w3m-meta-content-type-charset-regexp'.
+
+       * mm-view.el (mm-inline-text-html-render-with-w3m): Decode
+       charset-encoded html contents.
+
+2002-01-24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-request-article): Make sure it is not
+       an empty file.
+
+       * nnweb.el (url): Ignore errors when request url.
+
+       * nnrss.el: Clean up the comments.
+
+2002-01-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Fbind `w3m-region'; bind `w3m-mode-map'.
+
+       * mm-decode.el (mm-inline-text-html-renderer): New user option.
+       (mm-inline-media-tests): Test whether the value of
+       `mm-inline-text-html-renderer' is a function for text/html.
+
+       * mm-view.el (mm-inline-text-html-render-with-w3): New function
+       separated from `mm-inline-text'.
+       (mm-w3m-minor-mode): New variable.
+       (mm-w3m-setup): New variable.
+       (mm-setup-w3m): New function.
+       (mm-inline-text-html-render-with-w3m): New function.
+       (mm-inline-text): Funcall `mm-inline-text-html-renderer' for
+       text/html.
+
+2002-01-23  Paul Jarc  <prj@po.cwru.edu>
+
+       * lpath.el: fbind make-symbolic-link and unix-sync for nnmaildir.
+
+2002-01-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-xmas.el (gnus-xmas-redefine): Quote `gnus-completing-read'
+       and `gnus-xmas-completing-read'.
+
+2002-01-19  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * nneething.el (nneething-message-id-number): Abolished.
+       (nneething-encode-file-name): Not encode numerical characters.
+       (nneething-make-head): `nneething-message-id-number' is not
+       used to generate message IDs.
+
+2002-01-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-emphasis-alist): Include !? as sentence-ending
+       characters.
+
+2002-01-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-xmas.el (gnus-xmas-completing-read): New function.
+       (gnus-xmas-redefine): Redefine conditionally.
+
+2002-01-22  Josh Huber  <huber@alum.wpi.edu>
+
+       * mml.el (mml-parse-1): Fixed usage of recipients in the secure
+       tag.
+
+2002-01-22  Josh Huber  <huber@alum.wpi.edu>
+
+       * message.el (message-font-lock-keywords): Added the secure tag.
+       * mml-sec.el: Added functions to generate/modify/remove the secure
+       tag while in message mode.
+       * mml-sec.el (mml-secure-message): New.
+       * mml-sec.el (mml-unsecure-message): New.
+       * mml-sec.el (mml-secure-message-sign-smime): New.
+       * mml-sec.el (mml-secure-message-sign-pgp): New.
+       * mml-sec.el (mml-secure-message-sign-pgpmime): New.
+       * mml-sec.el (mml-secure-message-encrypt-smime): New.
+       * mml-sec.el (mml-secure-message-encrypt-pgp): New.
+       * mml-sec.el (mml-secure-message-encrypt-pgpmime): New.
+       * mml.el (mml-parse-1): Added code to recognise the secure tag and
+       convert it to either a part or multipart depending on if there are
+       other parts in the message.
+       * mml.el (mml-mode-map): Changed default sign/encrypt keybindings
+       to use the secure tag, rather than the part tag.
+       * mml.el (mml-preview): Added a save-excursion to keep cursor
+       position after doing an MML preview.
+
+2002-01-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el (nnheader-parse-overview-file): New function.
+       (nnheader-write-overview-file): New function.
+
+2002-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-group-fast-parameter): Check better if expansion
+       in wanted.
+
+       * nnweb.el (nnweb-type-definition): Clean up.
+
+2002-01-21  Alastair Burt  <burt@dfki.de>
+       Trivial patch.
+
+       * gnus-art.el (gnus-mm-display-part): Make sure that the summary
+       buffer exists before jumping to it.
+
+2002-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-wash-html-with-w3): Made into own
+       function.
+       (article-wash-html): Use it.
+       (gnus-article-wash-function): New variable.
+       (gnus-article-wash-html-with-w3m): New function.
+
+2002-01-20  Bj\e,Av\e(Brn Torkelsson  <torkel@acc.umu.se>
+
+       * dgnushack.el (dgnushack-compile): Compile smiley-ems for
+       XEmacs.
+
+2002-01-20  John H. Palmieri  <palmieri@math.washington.edu>
+
+       * gnus-fun.el (gnus-convert-image-to-gray-x-face): More standard
+       command line.
+
+2002-01-21  Simon Josefsson  <jas@extundo.com>
+
+       * canlock.el (base64-encode-string): Autoload it from base64.
+       (canlock-make-cancel-key): Base64 encode unibyte string.
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnfolder.el (nnfolder-request-accept-article): Unfold
+       x-from-line.
+       (nnfolder-request-replace-article): Ditto.
+
+2002-01-20  Nevin Kapur  <nevin@jhu.edu>
+
+       * gnus-group.el (gnus-group-best-unread-group): Use the right
+       positioning function.
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * smiley-ems.el (smiley-region): Use new function.
+       (smiley-update-cache): Use general image functions.
+       (smiley-region): Use general functions.
+
+       * gnus-util.el (gnus-graphic-display-p): New function.
+
+       * nnmail.el (nnmail-article-group): Allow outputting traces of
+       non-strings.
+
+       * nndoc.el (nndoc-type-alist): Rules for exim bounces.
+       (nndoc-exim-bounce-type-p): New function.
+
+       * message.el (message-dont-send): Doc fix.
+
+       * gnus-util.el (gnus-completing-read): Remove
+       inherit-input-method.
+
+       * gnus-art.el (gnus-treat-smiley): Doc fix.
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Ignore seen and recent
+       articles.
+
+2002-01-19  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-gssapi-open): Don't wait for logout to complete.
+       (imap-kerberos4-open): Ditto.
+       (imap-open): Set port correctly, don't set auth.
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-version-number): Bump version number.
+
+2002-01-20 05:33:30 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.05 is released.
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnkiboze.el (nnkiboze-generate-group): Make sure the directory
+       exists.
+
+       * gnus-spec.el (gnus-string-width-function): New function.
+       (gnus-tilde-cut-form): Use it.
+       (gnus-tilde-max-form): Ditto.
+       (gnus-use-correct-string-widths): Default to (featurep 'xemacs).
+       (gnus-substring-function): Use it.
+       (gnus-tilde-cut-form): Ditto.
+       (gnus-substring-function): New function.
+
+       * message.el (message-check-news-header-syntax): New message.
+
+       * gnus.el (gnus-slave-no-server): Doc fix.
+
+       * gnus-spec.el (gnus-use-correct-string-widths): Default to t.
+
+2002-01-15  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-adjust-marked-articles): Fix the record for
+       `seen' if it looks like (seen NUM1 . NUM2).  It should be
+       (seen (NUM1 . NUM2)).
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-catchup-articles): Update article
+       number in closed topics.
+
+2002-01-19  Daniel Pittman  <daniel@rimspace.net>
+
+       * gnus-sum.el (gnus-summary-first-unseen-or-unread-subject): New
+       functions.
+
+2002-01-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-group-find-parameter): Clean up.
+
+       * gnus-sum.el (gnus-summary-goto-subject): Error on non-numerical
+       articles.
+
+       * gnus-util.el (gnus-completing-read-with-default): Renamed.
+
+       * nnmail.el (nnmail-article-group): Clean up.
+
+2002-01-19  Paul Stodghill  <stodghil@cs.cornell.edu>
+
+       * gnus-agent.el (gnus-category-name): Intern the category name.
+
+2002-01-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-move-group): Use gnus-topic-history.
+
+       * gnus-util.el (gnus-completing-read): New function.
+
+2002-01-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-add-wash-type): Use add-to-list.
+
+       * smiley-ems.el (smiley-region): Register smiley.
+       (smiley-toggle-buffer): Rewrite the function.
+       (smiley-active): Removed.
+
+2002-01-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-util.el (gnus-parent-id): Optimize null n case.  From
+       Jesper Harder <harder@ifa.au.dk>.
+
+2002-01-18  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * gnus-art.el (gnus-request-article-this-buffer): Call
+       `nneething-get-file-name' to extract the file name from the
+       message id.
+
+       * nneething.el (nneething-encode-file-name): New function.
+       (nneething-decode-file-name): Ditto.
+       (nneething-get-file-name): Ditto.
+       (nneething-make-head): Encode the file name and encapsulate it
+       into the field of the message id.
+
+2002-01-18  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-request-update-info): Don't erase flags that isn't
+       stored in .marks.
+
+       * nnfolder.el (nnfolder-request-update-info): Ditto.
+
+2002-01-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-url-parse-query-string): Allow new line in value.
+
+2002-01-18  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-starttls-p): Don't check for binary.
+       (imap-gssapi-auth-p): Ditto.
+       (imap-kerberos4-auth-p): Ditto.
+       (imap-open): Change logic.  Iterate through all possible streams,
+       instead of bailing out after first failure.  Move authenticator
+       decision to `imap-authenticate'.
+       (imap-authenticate): Change logic, now finds the authenticator to
+       use, was previously in `imap-open'.
+       (imap-open): Return nil on failure.
+       (imap-open): Setup temp buffer correctly.
+       (imap-open): Return buffer only on success.
+       (imap-interactive-login, imap-interactive-login): Tell the user
+       which stream/authenticator is used for the queried
+       username/password.
+       (imap-open, imap-authenticate): Set variables.
+       (imap-gssapi-auth-p, imap-kerberos4-auth-p): Fix typo.
+       (imap-open): Don't assume how `with-temp-buffer' is implemented.
+
+2002-01-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-grab-cam-x-face): New function.
+
+2002-01-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-emphasis-alist): Allow matching "*this*.)".
+
+2002-01-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-toggle-group-plugged): New function.
+       (gnus-agent-group-mode-map): Bind it to "Jo".
+       (gnus-agent-group-make-menu-bar): Add it into menu bar.
+
+2002-01-17  Karl Kleinpaste  <karl@charcoal.com>
+
+       * gnus-xmas.el (gnus-group-toolbar): Add .newsrc save button.
+       (gnus-summary-mail-toolbar): Add mail article deletion button.
+
+       * smiley.el (smiley-deformed-regexp-alist): Eliminate noseless
+       false positives for lines of "^^^^".
+
+       * gnus-picon.el (gnus-picon-find-face): faces database is all
+       lowercase.
+
+2002-01-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Use correct buffer.
+       (gnus-agent-braid-nov): Switch back to nntp-server-buffer. Remove
+       duplications.
+       (gnus-agent-batch): Bind gnus-agent-confirmation-function.
+
+2002-01-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-initial-limit): Inline
+       gnus-summary-limit-children.
+       (gnus-summary-initial-limit): Don't limit if
+       gnus-newsgroup-display is nil.
+       (gnus-summary-initial-limit): No, don't.
+
+       * gnus-util.el
+       (gnus-put-text-property-excluding-characters-with-faces): Inline
+       gnus-put-text-property.
+
+       * gnus-spec.el (gnus-default-format-specs): New variable.
+
+       * gnus-start.el (gnus-read-newsrc-file): Don't clear
+       gnus-format-specs.
+       (gnus-read-newsrc-el-file): Default to gnus-default-format-specs.
+
+       * gnus-spec.el (gnus-update-format-specifications): Really check
+       the Gnus version of the .newsrc.eld file.
+       (gnus-format-specs): Save the new default summary format.
+
+       * gnus-util.el (gnus-parent-id): Check whether references is empty
+       before splitting.
+
+       * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): Inline some
+       functions.
+       (gnus-gather-threads-by-references): Inline
+       `gnus-split-references'.
+
+       * gnus-spec.el (gnus-summary-line-format-spec): New, optimized
+       default value of gnus-summary-line-format-spec.
+
+2002-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-retrieve-headers-1): A better error
+       message.
+       (nnslashdot-request-list): Ditto.
+       (nnslashdot-sid-strip): Removed.
+
+2002-01-15  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-close-asynchronous): Enable.
+       (nnimap-close-group): Expunge.
+
+2002-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-user-date-format-alist): Typo.
+       From: Frank Schmitt <usereplyto@Frank-Schmitt.net>
+
+2002-01-15  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * nneething.el (nneething-request-article): Set
+       `nnmail-file-coding-system' to `binary' locally, in order to read
+       files without any conversion.
+
+2002-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Use
+       nnheader-file-coding-system and nnmail-active-file-coding-system.
+       (gnus-agent-regenerate-group): Ditto.
+       (gnus-agent-regenerate): Ditto.
+       (gnus-agent-write-active): Ditto.
+       Suggested by Katsumi Yamaoka <yamaoka@jpl.org>
+
+2002-01-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-button-alist): Don't highlight <URL:.
+       Suggested by Ian Fitchet <ian.fitchet@lunanbay.com>
+
+2002-01-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: We don't need gnus-article-show-all-headers.
+
+       * gnus-art.el (article-show-all, gnus-article-show-all-header):
+       Ditto.
+
+       * gnus-sum.el (gnus-summary-select-article): Don't call
+       show-all-headers, because hidden headers are not hidden text any
+       more.
+
+2002-01-13  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-newline-and-reformat): Use `newline' instead
+       of inserting \n, so that the newline is marked as hard.
+
+       * gnus-spec.el (gnus-pad-form): Don't evaluate EL multiple times.
+       From Jesper Harder <harder@ifa.au.dk>.
+
+2002-01-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * imap.el (imap-close): Keep going if quit.
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Erase
+       nntp-server-buffer.
+
+2002-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-display-inline-fontify): Require font-lock to
+       avoid unbinding shadowed variables.
+
+       * gnus-art.el (gnus-picon-databases): Moved here.
+       (gnus-picons-installed-p): Moved here.
+       (gnus-article-reply-with-original): Use `mark'.
+
+       * gnus.el (gnus-picon): Moved here and renamed.
+
+       * gnus-art.el (gnus-treat-from-picon): Only be on if picons are
+       installed.
+       (gnus-treat-mail-picon): Ditto.
+       (gnus-treat-newsgroups-picon): Ditto.
+
+       * gnus-picon.el (gnus-picons-installed-p): New function.
+
+2002-01-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-go-online): Fix doc.
+
+2002-01-12  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-need-unselect-to-notice-new-mail)
+       (nnimap-before-find-minmax-bugworkaround): Use it.
+       (nnimap-find-minmax-uid): Don't reselect current mailbox.
+       (nnimap-dont-close): New variable.
+       (nnimap-close-group): Use it.
+
+2002-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-reply-with-original): Use
+       `mark-active'.
+
+       * gnus-msg.el (gnus-summary-reply): Don't bug out on regions.
+
+       * gnus-logic.el (gnus-advanced-score-rule): Thinko fix.
+       (gnus-score-advanced): Clean up.
+       (gnus-score-advanced): Accept a multiple of the score.
+
+2002-01-12  Simon Josefsson  <jas@extundo.com>
+
+       * flow-fill.el (fill-flowed-display-column)
+       (fill-flowed-encode-columnq): New variables.  Suggested by
+       Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro\e,b_\e(Bjohann).
+       (fill-flowed-encode, fill-flowed): Use them.
+
+       * message.el (message-send-news, message-send-mail): Use
+       m-b-s-n-p-e-h-n.
+
+       * mml.el (autoload): Autoload fill-flowed-encode.
+       (mml-buffer-substring-no-properties-except-hard-newlines): New
+       function.
+       (mml-read-part): Use it.
+       (mml-generate-mime-1): Encode format=flowed if appropriate.
+       (mml-insert-mime-headers): Insert format=flowed.
+
+       * flow-fill.el (fill-flowed-encode): New function.
+       (fill-flowed): Bind fill-column to window width.
+
+2002-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-buffer-name): Return the dead name if
+       it exists.
+       (gnus-summary-setup-buffer): Wake up dead summary buffers.
+       (gnus-summary-buffer-name): Don't return the dead name after all.
+       (gnus-summary-setup-buffer): Kill the dead buffer.
+
+       * gnus-art.el (gnus-article-followup-with-original): Store the
+       value of the mark before deactivating it.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Fake it.
+       From: Karl Kleinpaste <karl@charcoal.com>
+
+       * gnus-art.el (article-display-x-face): Ditto.
+       (gnus-article-reply-with-original): Use gnus-region-active-p.
+       (gnus-article-followup-with-original): Ditto.
+
+       * gnus-sum.el (gnus-summary-read-group-1): Don't select
+       downloadable article either.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-display-x-face): Insert From:.
+
+       * gnus-sum.el (gnus-summary-move-article): Don't draw the
+       article. Bind gnus-display-mime-function and
+       gnus-article-prepare-hook.
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): Load agentview.
+       (gnus-agent-toggle-plugged): Use gnus-agent-go-online. Move
+       gnus-agent-possibly-synchronize-flags to the last.
+       (gnus-agent-go-online): New function. New variable.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-regenerate-group): Add clean option.
+       (gnus-agent-regenerate): Ditto.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-ignored-news-headers)
+       (message-ignored-mail-headers): Add X-Gnus-Agent-Meta-Information:.
+       Suggested by ARISAWA Akihiro <ari@atesoft.advantest.co.jp>
+
+       * gnus.el (gnus-gethash-safe): New macro.
+
+       * gnus-agent.el (gnus-agent-regenerate-history): New function.
+       (gnus-agent-regenerate): Show messages.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-regenerate-group): New function.
+       (gnus-agent-regenerate): New function.
+       (gnus-agent-save-alist): Sort.
+       (gnus-agent-copy-nov-line): Test eobp.
+       (gnus-agent-retrieve-headers): Erase buffer.
+
+2002-01-10  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-to-coding-system): Change charset to cs.
+       From: Torsten Hilbrich <email@myrkr.in-berlin.de>
+
+       * gnus.el (gnus-agent-covered-methods): Move here.
+       (gnus-online): New function.
+       (gnus-agent-method-p): Move here.
+
+       * nnagent.el (nnagent-retrieve-headers): Check whether arts is
+       nil. Remove articles-alist.
+
+       * gnus-start.el (gnus-get-unread-articles): Check online.
+       (gnus-groups-to-gnus-format): Ditto.
+       (gnus-active-to-gnus-format): Ditto.
+
+       * gnus-agent.el (gnus-agent-get-function): Use it.
+       (gnus-agent-get-undownloaded-list): Ditto.
+       (gnus-agent-fetch-session): Only fetch online methods.
+
+       * gnus-srvr.el (gnus-server-make-menu-bar): Add offline.
+       (gnus-server-mode-map): Ditto.
+       (gnus-server-offline-face): New face.
+       (gnus-server-offline-face): New variable.
+       (gnus-server-font-lock-keywords): Add offline.
+       (gnus-server-insert-server-line): Ditto.
+       (gnus-server-offline-server): New function.
+
+       * gnus-int.el (gnus-open-server): Turn to offline.
+       (gnus-server-unopen-status): New variable.
+
+2002-01-10  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnkiboze.el (nnkiboze-request-article): Use
+       gnus-agent-request-article.
+
+       * nnagent.el (nnagent-retrieve-headers): Don't use nnml
+       function. Insert undownloaded NOV.
+
+       * gnus-agent.el (gnus-agent-retrieve-headers): New function.
+       (gnus-agent-request-article): New function.
+
+       * gnus.el (gnus-agent-cache): New variable.
+
+       * gnus-int.el (gnus-retrieve-headers): Use
+       gnus-agent-retrieve-headers.
+       (gnus-request-head): Use gnus-agent-request-article.
+       (gnus-request-body): Ditto.
+
+       * gnus-art.el (gnus-request-article-this-buffer): Use
+       gnus-agent-request-article.
+
+       * gnus-sum.el (gnus-summary-read-group-1): Don't show the first
+       article if it is undownloaded.
+
+2002-01-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-spec.el (gnus-spec-tab): Deal with wide characters.
+
+2002-01-09  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el (canlock-string-as-unibyte): New macro.
+       (canlock-sha1-with-openssl): Return a unibyte string.
+       (canlock-make-cancel-key): Treat Message-ID as a unibyte string.
+
+2002-01-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-expand-group-parameters): Match \N or \& only.
+
+2002-01-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Add
+       application/x-emacs-lisp.
+
+       * gnus-msg.el (gnus-bug): Use application/emacs-lisp.
+
+       * nntp.el (nntp-request-article): Add group parameter.
+       (nntp-request-head): Ditto.
+       (nntp-find-group-and-number): Add parameter group. Figure out
+       number if the status line doesn't give (e.g. quimby.gnus.org).
+
+2002-01-08  Simon Josefsson  <jas@extundo.com>
+
+       * mml.el (mml-generate-mime-1): Set recipient correctly.
+
+2002-01-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-read-from-minibuffer): Add parameter
+       initial-contents.
+       * gnus-msg.el (gnus-summary-resend-message): Use it.
+
+       * gnus-group.el (gnus-group-read-ephemeral-group): Restore the old
+       behavior of quit-config.
+
+       * message.el (message-make-from): Don't quote fullname.
+       From: Bj\e,Ax\e(Brn Mork <bmork@dod.no>
+
+       * gnus-group.el (gnus-group-suspend): Don't kill message buffers.
+       From: <andre@slamdunknetworks.com>
+
+2002-01-07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-mark-article-read): Typo. Increase n.
+
+       * gnus-art.el (gnus-header-button-alist): Handle mailto.
+
+       * mml.el (mml-preview): Bind gnus-original-article-buffer because
+       article-decode-group-name uses it.  Bind gnus-article-prepare-hook
+       because bbdb may use it.
+
+2002-01-07  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * nneething.el (nneething-request-article): When a non-text file
+       is converted to an article, its data is encoded in base64.  Call
+       `nneething-make-head' with options to specify MIME types.
+       (nneething-make-head): Add optional arguments to specify MIME
+       types.
+
+2002-01-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Fake a "From: "
+       header if there is not.
+
+       * gnus-xmas.el (gnus-xmas-put-image): Insert " " if bobp.
+
+       * gnus-msg.el (gnus-gcc-mark-as-read): New variable.
+       (gnus-inews-mark-gcc-as-read): Obsolete variable.
+       (gnus-inews-do-gcc): Use them.
+
+       * gnus-group.el (gnus-group-mark-article-read): Put holes into
+       gnus-newsgroup-unselected.
+
+2002-01-06  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-ssl-open, imap-ssl-open, imap-parse-fetch): Use
+       condition-case, not ignore-errors.
+
+2002-01-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-insert-old-articles): Bind
+       gnus-fetch-old-headers.
+
+       * gnus-art.el (article-display-x-face): Use the current buffer
+       unless `W f'. Otherwise, X-Face may be shown in the header of a
+       forwarded part.
+       (gnus-treatment-function-alist): Treat xface before hiding
+       headers.
+
+2002-01-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-read-ephemeral-group): Fix
+       parameters.
+
+2002-01-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-multibyte-p): Define conditionally when load.
+       (mm-guess-charset): New function.
+       (mm-charset-after): Use it.
+       (mm-detect-coding-region): New function.
+       (mm-detect-mime-charset-region): New function.
+
+       * gnus-sum.el (gnus-summary-show-article): Use
+       mm-detect-coding-region.
+
+2002-01-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-make-fqdn): Be less violent.
+
+       * gnus.el (gnus-logo-color-style): Compute custom form
+       automatically.
+
+       * gnus-sum.el (gnus-summary-enter-digest-group): Feed the adaptive
+       score file of the parent to the document group.
+
+       * gnus-group.el (gnus-group-read-ephemeral-group): Add an optional
+       parameters parameter.
+
+       * gnus-score.el (gnus-score-load-file): Clean up.
+
+2002-01-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-thread-sort-by-most-recent-number): Fix typo.
+       From: Damien Wyart <damien.wyart@free.fr>
+
+       * gnus-util.el (gnus-local-map-property): In Emacs 21, use keymap.
+
+2002-01-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-select-group-hook): Typo.
+
+       * rfc2047.el (rfc2047-decode-string): Return immediately if there
+       is no quoted-printable-encoded STRING.
+       From: Jesper Harder <harder@ifa.au.dk>
+
+       (rfc2047-decode-string): Decode it.
+
+2002-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-logo-color-alist): Added more colors from Luis.
+
+2002-01-05  Keiichi Suzuki  <keiichi@nanap.org>
+       Trivial patch.
+
+       * nntp.el (nntp-possibly-change-group): Erase contents of nntp
+       buffer to get rid of junk line.
+
+2002-01-05  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-mode-map): Bind message-goto-from to C-c C-f
+       C-o.
+       (message-mode-map): Bind message-insert-or-toggle-importance to
+       C-c C-u.
+       (message-mode-map): Bind message-disposition-notification-to to
+       C-c M-n.
+       (message-mode-menu): Add m-d-n-t.
+       (message-mode-field-menu): Add m-goto-from.
+       (message-mode): Doc fix.
+       (message-goto-from): New function.
+       (message-insert-disposition-notification-to): New function.
+       (message-tool-bar-map): Add receipt button.
+
+2002-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-thread-latest-date): New function.
+       (gnus-thread-sort-by-most-recent-number): Renamed.
+       (gnus-thread-sort-functions): Doc fix.
+       (gnus-select-group-hook): Don't use setq on a hook.
+       (gnus-thread-latest-date): Use date, not number
+
+       * gnus-agent.el (gnus-agent-expire-days): Doc fix.
+       (gnus-agent-expire): Allow regexp of expire-days.
+
+       * gnus-art.el (gnus-article-reply-with-original): Deactivate
+       region.
+       (gnus-article-followup-with-original): Ditto.
+
+       * gnus-sum.el (gnus-thread-highest-number): Doc fix.
+
+       * gnus-art.el (gnus-mime-display-alternative): Use
+       gnus-local-map-property.
+       (gnus-mime-display-alternative): Ditto.
+       (gnus-insert-mime-security-button): Ditto.
+       (gnus-insert-next-page-button): Ditto.
+       (gnus-button-prev-page): Take optional args.
+       (gnus-insert-prev-page-button): widget-convert.
+
+       * gnus-util.el (gnus-local-map-property): New function.
+
+       * gnus-art.el (gnus-prev-page-map): Use parent map.
+       (gnus-next-page-map): Ditto.
+
+       * gnus-spec.el (gnus-parse-format): Clean up.
+       (gnus-parse-format): Do complex formatting for %=.
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Add the string
+       "X-Face: " to the data in the built-in scenario.
+
+       * gnus-spec.el (gnus-parse-simple-format): Use gnus-pad-form.
+       (gnus-correct-pad-form): Renamed.
+       (gnus-tilde-max-form): Clean up.
+       (gnus-pad-form): Use gnus-use-correct-string-widths.
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Use native xface
+       support if that is available.
+
+       * gnus-sum.el (gnus-thread-highest-number): New function.
+       (gnus-thread-sort-by-most-recent-thread): New function.
+       (gnus-thread-sort-functions): Doc fix.
+
+2002-01-04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-select-article): Disable multibyte in
+       all cases.
+       (gnus-summary-mode): Enable it in all cases.
+       (gnus-summary-display-article): Ditto.
+       (gnus-summary-edit-article): Ditto.
+
+       * gnus-ems.el (gnus-put-image): Really return glyph.
+
+       * gnus-art.el (gnus-article-x-face-command): Fix :type.
+       (gnus-treat-smiley): Don't take "P" in the interactive form.
+
+2002-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * compface.el (uncompface): XEmacs and Emacs have differing
+       capabilities.
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Use face.
+
+       * gnus-ems.el (gnus-article-xface-ring-internal): Removed.
+       (gnus-article-xface-ring-size): Removed.
+       (gnus-article-display-xface): Removed.
+       (gnus-remove-image): Cleaned up.
+
+       * gnus-xmas.el (gnus-xmas-create-image): Convert pbm to xbm.
+       (gnus-xmas-create-image): Take pbm files.
+       (gnus-x-face): Removed.
+       (gnus-xmas-article-display-xface): Removed.
+
+       * gnus-fun.el (gnus-display-x-face-in-from): Bind
+       default-enable-multibyte-characters.
+
+       * compface.el (uncompface): Doc fix.
+
+       * gnus-art.el (gnus-article-x-face-command): Use
+       gnus-display-x-face-in-from.
+
+       * gnus-xmas.el (gnus-xmas-put-image): Return the image.
+
+       * gnus-ems.el (gnus-put-image): Return the image.
+
+       * gnus-fun.el (gnus-display-x-face-in-from): New function.
+       (gnus-x-face): Moved here.
+
+2002-01-04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-put-image): Don't insert SPC or make
+       invisible if string is nil.
+       (gnus-xmas-article-display-xface): Use it.
+
+       * gnus-ems.el (gnus-put-image): Explicitly use SPC, and add text
+       property when string is nil.
+       (gnus-article-display-xface): Use it.
+
+2002-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-display-x-face): Check whether valid grey
+       face was returned.
+       (article-display-x-face): Place image in the right spot.
+
+       * gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Get rid of
+       stderr.
+       (gnus-convert-gray-x-face-to-xpm): Check whether output is valid.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-xmas.el (gnus-xmas-create-image): Take optional
+       parameters.
+       (gnus-xmas-put-image): Allow non-strings to be passed.
+
+       * gnus-art.el (article-display-x-face): Use optional parameters.
+
+       * gnus-ems.el (gnus-create-image): Take optional parameters.
+
+       * gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Use uncompface.
+
+       * compface.el (compface-xbm-p): Removed.
+
+       * gnus-ems.el (gnus-article-compface-xbm): Removed.
+       (gnus-article-display-xface): Use compface.
+
+       * compface.el: New file.
+
+       * gnus-fun.el (gnus-convert-pbm-to-x-face-command): Remove quotes.
+       (gnus-convert-image-to-x-face-command): Ditto.
+       (gnus-random-x-face): Quote argument.
+       (gnus-x-face-from-file): Ditto.
+
+2002-01-03  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-request-expire-articles): evaluate
+       the expire-group parameter once per article rather than once
+       per group; bind `nnmaildir-article-file-name' and `article'
+       for convenience.  Leave article alone when expire-group
+       specifies the current group.
+       (nnmaildir--update-nov): be more concurrency-friendly with
+       temp file names.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-read-init-file): Cleaned up.
+
+2002-01-03  Dave Love  <d.love@dl.ac.uk>
+
+       * gnus-start.el (gnus-startup-file-coding-system): Removed.
+       (gnus-read-init-file): Don't use it.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-fetch-session): Run hook.
+
+2002-01-03  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-start.el (gnus-read-init-file): Don't force coding system
+       for ~/.gnus.  From Dave Love <fx@gnu.org>.
+
+2002-01-03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-send-buffer): Use mm-with-unibyte-current-buffer.
+       * nnspool.el (nnspool-request-post): Ditto.
+
+       * mm-util.el (mm-use-find-coding-systems-region): New variable.
+       (mm-find-mime-charset-region): Use it.
+
+2002-01-03  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-summary-line-format): Added :link.
+       * gnus-topic.el (gnus-topic-line-format): Ditto.
+       * gnus-sum.el (gnus-summary-dummy-line-format): Ditto.
+       * gnus-srvr.el (gnus-server-line-format): Ditto.
+       * gnus-group.el (gnus-group-line-format): Ditto.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Use correct syntax for
+       :keys, it works on both Emacsen.
+
+2002-01-03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-to-coding-system): Don't setq charset.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-summary-send-map): Fix binding for very-wide.
+
+2002-01-03  Reiner Steib  <reiner.steib@gmx.de>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Menu bar entries for
+       very wide reply.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picon-transform-address): Cache stuff.
+       (gnus-picon-cache): New variable.
+       (gnus-picon-transform-newsgroups): Cache stuff.
+
+       * gnus-art.el (gnus-article-reply-with-original): New command.
+       (gnus-article-followup-with-original): New command.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Take optional BEG and
+       END parameters.
+       (gnus-summary-followup): Take a list of list of articles.
+       (gnus-inews-yank-articles): Allow lists of article/regions.
+
+       * gnus-art.el (gnus-article-read-summary-keys): `R' and `F' are no
+       longer the usual commands.
+
+       * gnus-fun.el (gnus-convert-image-to-gray-x-face): Use pnmnoraw.
+       (gnus-convert-gray-x-face-to-xpm): Don't use six parameters to
+       shell-command-on-region.
+
+2002-01-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-picon.el (gnus-picon-transform-newsgroups): Fix for the case
+         "Newsgroups: rec.music.beatles.moderated, rec.music.beatles".
+
+2002-01-03  Steve Youngs  <youngs@xemacs.org>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): XEmacs doesn't
+       understand ':keys', wrap it in an featurep 'xemacs.
+
+2002-01-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ems.el (gnus-article-display-xface): Show xface in the
+       order of headers (Actually, it is called in a reversed order). Add
+       'gnus-image-text-deletable property.
+       (gnus-remove-image): Remove text with such a property.
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Don't use
+       gnus-put-image.
+
+       * gnus-art.el (gnus-article-treat-fold-newsgroups): Replace ", *"
+       with ", "
+
+2002-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el (gnus-convert-gray-x-face-to-xpm): Renamed.
+
+       * gnus-art.el (gnus-ignored-headers): Hide all X-Faces.
+       (article-display-x-face): Display grey X-Faces.
+
+       * gnus-fun.el (gnus-convert-gray-x-face-region): New function.
+       (gnus-convert-gray-x-face-to-ppm): Ditto.
+       (gnus-convert-image-to-gray-x-face): Ditto.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add a :keys to
+       gnus-summary-show-raw-article.
+
+2002-01-02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       Display picons in XEmacs without showing text.
+
+       * gnus-xmas.el (gnus-xmas-create-image): Don't use
+       mm-create-image-xemacs to create xbm glyph, because it deletes
+       temporary files.
+       (gnus-xmas-put-image): Use end-glyph. Make text invisible.
+       (gnus-xmas-remove-image): Make text visible, remove glyph.
+
+       * gnus-picon.el (gnus-picon-transform-newsgroups)
+       (gnus-picon-transform-address): Insert spec backward, due to the
+       incompatibility of gnus-xmas-put-image.
+
+2002-01-02  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * gnus-fun.el (gnus-convert-pbm-to-x-face-command): Doc fix.
+
+2002-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Doc fix.
+
+       * gnus-art.el: Doc fix.
+
+       * gnus-agent.el: Doc fix.
+
+2002-01-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-diary.el, gnus-delay.el: Fix copyright lines.
+
+2002-01-01  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir--update-nov): automatically parse
+       NOV data out of the message again if nnmail-extra-headers has
+       changed.
+
+2002-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-fun.el: New file.
+       (gnus-convert-image-to-x-face-command): New variable.
+       (gnus-insert-x-face): New function.
+       (gnus-random-x-face): Renamed.
+       (gnus-x-face-from-file): Renamed.
+
+       * gnus-art.el (gnus-body-boundary-delimiter): Changed default to
+       "_".
+       (gnus-body-boundary-delimiter): Typo fix.
+
+2002-01-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-article-treat-body-boundary): Handle nil.
+       (gnus-body-boundary-delimiter): Fix type.
+
+2002-01-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-treat-buttonize, gnus-treat-buttonize-head)
+       (gnus-treat-emphasize, gnus-treat-strip-cr)
+       (gnus-treat-leading-whitespace, gnus-treat-hide-headers)
+       (gnus-treat-hide-boring-headers, gnus-treat-hide-signature)
+       (gnus-treat-fill-article, gnus-treat-hide-citation)
+       (gnus-treat-hide-citation-maybe)
+       (gnus-treat-strip-list-identifiers, gnus-treat-strip-pgp)
+       (gnus-treat-strip-pem, gnus-treat-strip-banner)
+       (gnus-treat-highlight-headers, gnus-treat-highlight-citation)
+       (gnus-treat-date-ut, gnus-treat-date-local)
+       (gnus-treat-date-english, gnus-treat-date-lapsed)
+       (gnus-treat-date-original, gnus-treat-date-iso8601)
+       (gnus-treat-date-user-defined, gnus-treat-strip-headers-in-body)
+       (gnus-treat-strip-trailing-blank-lines)
+       (gnus-treat-strip-leading-blank-lines)
+       (gnus-treat-strip-multiple-blank-lines)
+       (gnus-treat-unfold-headers, gnus-treat-fold-headers)
+       (gnus-treat-fold-newsgroups, gnus-treat-overstrike)
+       (gnus-treat-display-xface, gnus-treat-display-smileys)
+       (gnus-treat-from-picon, gnus-treat-mail-picon)
+       (gnus-treat-newsgroups-picon, gnus-treat-body-boundary)
+       (gnus-treat-capitalize-sentences, gnus-treat-fill-long-lines)
+       (gnus-treat-play-sounds, gnus-treat-translate)
+       (gnus-treat-x-pgp-sig): Doc fix, add link to manual.
+
+       * gnus-art.el (gnus-body-boundary-delimiter): New variable.
+       (gnus-article-treat-body-boundary): Use it.
+
+       * message.el (message-mode): Fix doc.
+       (message-mode-menu): Fix names.
+
+2002-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-first-subject): Really go to unseen
+       articles.
+
+       * gnus-picon.el (gnus-picon-find-face): Search MISC for all types.
+       (gnus-picon-transform-address): Search for unknown faces as well.
+       (gnus-picon-find-face): Don't search "news" for MISC.
+       (gnus-picon-user-directories): Changed default back to exclude
+       "unknown".
+
+       * gnus-sum.el (gnus-summary-hide-all-threads): Reversed logic.
+
+       * gnus-picon.el (gnus-picon-find-face): Search through all
+       databases.
+       (gnus-picon-find-face): New implementation.
+
+       * gnus-topic.el (gnus-topic-goto-previous-topic): New command and
+       keystroke.
+       (gnus-topic-goto-next-topic): Ditto.
+
+       * gnus.el (gnus-summary-line-format): Changed default.
+
+       * nnmail.el (nnmail-extra-headers): Change default.
+
+       * gnus-sum.el (gnus-extra-headers): Change default.
+
+       * message.el (message-news-other-window): Changed "news" to
+       "posting".
+       (message-news-other-frame): Ditto.
+       (message-do-send-housekeeping): Ditto.
+
+       * gnus-sum.el (gnus-summary-maybe-hide-threads): Use predicate
+       function.
+       (gnus-article-unread-p): New function.
+       (gnus-article-unseen-p): New function.
+       (gnus-dead-summary-mode-map): Typo.
+
+       * gnus-util.el (gnus-make-predicate): New function.
+       (gnus-make-predicate-1): New function.
+
+       * gnus-sum.el: New function.
+       (gnus-map-articles): New function.
+
+       * gnus-art.el (gnus-treat-fold-headers): New variable.
+       (gnus-article-treat-fold-headers): New command and keystroke.
+
+       * gnus-sum.el (gnus-dead-summary-mode-map): Clean up.
+       (gnus-dead-summary-mode-map): Bind q to bury-buffer.
+
+2002-01-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-fcc-externalize-attachments): New variable.
+       (message-do-fcc): Use it.
+
+       * gnus-msg.el (gnus-gcc-externalize-attachments): New variable.
+       (gnus-inews-do-gcc): Use it.
+
+       * mml.el (mml-tweak-sexp-alist): New variable.
+       (mml-externalize-attachments): New variable.
+       (mml-tweak-part): Use mml-tweak-sexp-alist.
+       (mml-tweak-externalize-attachments): New function.
+
+2002-01-01  Steve Youngs  <youngs@xemacs.org>
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Uncomment
+       'set-glyph-face' so x-face back/foreground can be set.
+
+2001-12-31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-fix-before-sending): Fix a typo.
+
+2002-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-smiley): Renamed command.
+       (gnus-article-remove-images): New command and keystroke.
+
+       * gnus-sum.el (gnus-summary-toggle-smiley): Removed.
+
+       * smiley-ems.el (gnus-smiley-display): Removed.
+
+       * gnus.el (gnus-version-number): Update version.
+
+       * message.el (message-text-with-property): Renamed and moved
+       here.
+       (message-fix-before-sending): Highlight invisible text and place
+       point there.
+
+2002-01-01 02:32:53 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.04 is released.
+
+2002-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-delay.el (gnus-delay-send-queue): Renamed.
+
+       * gnus-art.el (gnus-ignored-headers): More headers,
+
+       * ietf-drums.el (ietf-drums-parse-addresses): Use `error' instead
+       of `scan-error', since XEmacs doesn't seem to support that.
+
+2001-12-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-best-unread-article): Take a prefix
+       arg.
+       (gnus-summary-best-unread-subject): Ditto.
+       (gnus-summary-best-unread-subject): No, don't.
+       (gnus-summary-better-unread-subject): New command.
+
+       * gnus-xmas.el (gnus-xmas-put-image): Insert the string itself.
+
+       * lpath.el ((featurep 'xemacs)): fbind url function.
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Use data, not
+       buffer.
+       (gnus-xmas-remove-image): Implementation that does something.
+       (gnus-xmas-article-display-xface): Mark images properly.
+
+       * gnus-art.el (gnus-mime-print-part): Use mm-temp-directory.
+
+2001-12-31  Florian Weimer  <fw@deneb.enyo.de>
+
+       * gnus.el (gnus): Warn if trying to run Gnus un-byte-compiled.
+
+2001-12-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-line-format): Added %O to the default
+       value.
+
+       * gnus-util.el (gnus-text-with-property): The smallest point is
+       point-min.
+
+       * smiley-ems.el (smiley-region): Return images.
+       (gnus-smiley-display): Allow toggling.
+       (smiley-region): Use text properties, not overlays.
+
+       * gnus-xmas.el (gnus-xmas-remove-image): New function, not
+       implemented yet.
+
+       * smiley-ems.el (smiley-update-cache): Check for valid types.
+
+       * gnus-art.el (gnus-with-article-buffer): New macro.
+
+       * gnus-picon.el (gnus-picon-transform-newsgroups): Keep the
+       strings as well as the glyphs.
+       (gnus-picon-transform-address): Ditto.
+       (gnus-picon-insert-glyph): Ditto.
+       (gnus-picon-transform-newsgroups): Toggle.
+       (gnus-picon-transform-address): Toggle.
+
+       * gnus-ems.el (gnus-remove-image): New function.
+       (gnus-put-image): Take an optional string.
+
+       * gnus-util.el (gnus-text-with-property): New function.
+
+       * gnus-art.el (gnus-delete-images): New function.
+
+       * gnus-ems.el (gnus-article-display-xface): Mark and store image.
+
+       * gnus-art.el (gnus-article-wash-status-entry): Renamed.
+       (gnus-article-wash-status): Use it.
+       (gnus-signature-toggle): Clean up.
+       (gnus-add-wash-status): New function.
+       (gnus-delete-wash-status): New function.
+       (gnus-article-hide-text-type): Use them throughout.
+       (gnus-add-image): New function.
+
+       * gnus-ems.el (gnus-article-display-xface): Use new interface.
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Use new
+       interface.
+
+       * gnus-art.el (article-display-x-face): Cleaned up.
+
+       * rfc2047.el (rfc2047-field-value): New function.
+
+       * mail-parse.el (mail-header-field-value): New alias.
+
+       * gnus-art.el (gnus-mime-print-part): Fix typos.
+
+       * smiley-ems.el (gnus-smiley-file-types): New variable.
+       (smiley-update-cache): Use it.
+       (smiley-regexp-alist): Suffix-less smiley names.
+       (smiley-regexp-alist): Added more smileys.
+
+       * gnus-sum.el (gnus-print-buffer): Made into own function.
+       (gnus-summary-print-article): Use it.
+
+       * mailcap.el (mailcap-mime-info): Actually return the bit that we
+       looked for when REQUEST is a string.
+
+       * gnus-art.el (gnus-mime-button-commands): Add printing
+       keystroke.
+       (gnus-mime-copy-part): Doc fix.
+       (gnus-mime-print-part): New command.
+
+2001-12-31  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-parse-fetch): Notice empty flags responses.  From
+       Nic Ferrier <nferrier@tf1.tapsellferrier.co.uk>.
+
+2001-12-30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-picon.el (gnus-treat-from-picon): Autoload.
+       (picon): Fix doc.
+
+       * gnus-win.el (gnus-window-to-buffer): gnus-picon-buffer-name no
+       longer exists. Remove those codes.
+       * gnus.el (gnus-use-picons): Ditto.
+
+2001-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-treat-fold-newsgroups): Don't
+       infloop.
+
+       * gnus-sum.el (t): New `W D' map.
+
+       * gnus-art.el (gnus-treat-fold-newsgroups): New variable.
+       (gnus-article-treat-body-boundary): Clean up.
+       (gnus-body-boundary-face): Removed.
+       (gnus-article-goto-header): Moved here.
+       (gnus-article-goto-header): Allow better regexps.
+       (gnus-article-treat-fold-newsgroups): New command.
+
+       * gnus-sum.el (gnus-summary-move-article): We have to select an
+       article to give `gnus-read-move-group-name' an opportunity to
+       suggest an appropriate default.
+
+       * rfc2047.el (rfc2047-fold-line): New function.
+       (rfc2047-unfold-line): Ditto.
+       (rfc2047-fold-region): Don't fold just after the header name.
+
+       * mail-parse.el (mail-header-fold-line): New alias.
+       (mail-header-unfold-line): Ditto.
+
+       * gnus-art.el (gnus-body-boundary-face): Renamed.
+       (gnus-article-treat-body-boundary): Use it.
+       (gnus-article-treat-body-boundary): Use an invisible header and a
+       line of underline characters.
+
+2001-12-30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * ietf-drums.el (ietf-drums-parse-addresses): Recover from errors.
+
+       * gnus-picon.el (gnus-picon-transform-address): Skip bad addresses.
+       (gnus-picon-split-address): New function.
+       (gnus-picon-find-face): Use it.
+       (gnus-picon-transform-address): Use it. Set first to t for each
+       address.
+
+       * gnus-art.el (gnus-with-article-headers): Move to here. Define
+       the macro then use it.
+       (gnus-treatment-function-alist): Treat picons earlier.
+
+2001-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-body-separator-face): New variable.
+       (gnus-article-treat-body-boundary): Use a blank, colored line.
+
+       * gnus-picon.el (gnus-picon-find-face): Look into misc/MISC as
+       well.
+
+       * gnus-art.el (gnus-treat-body-boundary): New variable.
+       (gnus-article-treat-unfold-headers): Use helper macro.
+       (gnus-article-treat-body-boundary): New command.
+
+       * gnus.el (gnus-logo-color-style): Change the default color.
+       (gnus-splash-face): Gray, gray.
+
+       * gnus-xmas.el (gnus-xmas-group-startup-message): Use general
+       colors.
+
+       * gnus.el (gnus-logo-color-alist): Moved here and renamed.
+       (gnus-logo-color-style): Ditto.
+       (gnus-logo-colors): Ditto.
+
+       * gnus-picon.el (gnus-picon-create-glyph): Cache glyphs.
+
+       * gnus-art.el (gnus-treat-newsgroups-picon): New variable.
+
+       * gnus-picon.el (gnus-treat-newsgroups-picon): New function.
+       (gnus-picon-transform-newsgroups): New function.
+
+       * ietf-drums.el (ietf-drums-parse-addresses): Accept a nil
+       string.
+
+       * gnus-picon.el (gnus-treat-mail-picon): Renamed.
+
+       * gnus-art.el (gnus-treat-cc-picon): New variable.
+       (gnus-treat-mail-picon): Renamed.
+
+       * gnus-picon.el: New implementation.
+       (gnus-picon-find-face): Renamed.
+       (gnus-treat-from-picon): Use it.
+       (gnus-picon-transform-address): Renamed.
+       (gnus-treat-from-picon): Use it.
+       (gnus-picon-create-glyph): Renamed.
+       (gnus-picon-transform-address): Use it.
+       (gnus-treat-cc-picon): New command.
+
+       * mm-decode.el (mm-create-image-xemacs): Separated out into
+       function.
+       (mm-get-image): Use it.
+
+       * gnus-art.el (gnus-treat-display-picons): Simplify.
+       (gnus-treat-from-picon): Renamed.
+
+       * gnus-ems.el (gnus-create-image): New function.
+       (gnus-put-image): New function.
+
+       * gnus-art.el (gnus-article-treat-unfold-headers): Doc fix.
+       (gnus-with-article-headers): New macro.
+       (gnus-article-goto-header): New function.
+
+       * gnus-xmas.el (gnus-image-type-available-p): New function.
+
+       * gnus-ems.el (gnus-image-type-available-p): New function.
+
+2001-12-30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-check-group): Find the correct tag, because
+       xml.el is changed.
+
+2001-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-treat-unfold-headers): Only fold when
+       lines are shorter than the window width.
+       (gnus-ignored-headers): More headers.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-unfold-lines): New variable.
+       (gnus-treat-unfold-headers): Renamed.
+       (gnus-article-treat-unfold-headers): New command and keystroke.
+
+       * rfc2047.el (rfc2047-encode-message-header): Clean up.
+
+       * gnus-int.el (gnus-open-server): Mark quit-ed server as denied.
+
+2001-12-29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * sha1-el.el (sha1-use-external): New variable.
+       (sha1-region): Use it.
+       (sha1-string): Ditto.
+
+       * dgnushack.el (dgnushack-compile): Compile gnus-picon for Emacs.
+       * gnus-picon.el: Less warnings when compile.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-news-directories): Removed obsolete
+       alias.
+       (gnus-picons-database): Default to list.
+       (gnus-picons-lookup-internal): Use it.
+
+       * nnmail.el (nnmail-article-group): Default nnmail-split-methods
+       to "bogus".
+
+       * gnus-win.el (gnus-configure-windows-hook): New hook.
+
+2001-12-29  Sascha L\e,A|\e(Bdecke  <sascha@meta-x.de>
+
+       * gnus-win.el (gnus-configure-windows): Minimize tree buffer.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-update-marks): Don't uncompress the seen
+       lists.
+       (gnus-select-newsgroup): Don't append; push.
+       (gnus-adjust-marked-articles): Remove obsolete ranges from
+       `seen'.
+       (gnus-update-marks): Clean up.
+       (gnus-select-newsgroup): Don't stomp gnus-newsgroup-seen.
+
+2001-12-29  Frank Schmitt  <usereplyto@Frank-Schmitt.net>
+
+       * gnus-sum.el (gnus-summary-limit-to-age): Allow negative days.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-auto-select-subject): New variable.
+       (gnus-summary-best-unread-subject): New function.
+       (gnus-summary-best-unread-article): Use it.
+       (gnus-summary-first-unseen-subject): New function and command.
+
+       * gnus-art.el (gnus-treatment-function-alist): Emphasize after
+       other treatments.
+
+       * gnus-util.el (gnus-put-overlay-excluding-newlines): New
+       function.
+
+       * gnus-art.el (gnus-article-show-hidden-text): Remove the type
+       from the list of hidden types.
+
+       * mm-view.el (mm-inline-text): Ditto.
+       (mm-inline-text): Ditto.
+       (mm-w3-prepare-buffer): Ditto.
+
+       * gnus-art.el (article-wash-html): Inhibit more remote fetching.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-ignored-headers): Added more headers.
+
+2001-12-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Compute the prefix
+       once.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-server-browse-in-group-buffer): Doc fix.
+
+2001-12-28  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Fix typo.  From
+       Jesper Harder <harder@ifa.au.dk>.
+
+2001-12-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-select-newsgroup): Make
+       `gnus-newsgroup-unseen' sorted.  Make `gnus-newsgroup-unseen'
+       contain all articles (instead of none) when no seen marks have
+       been set for the group.
+       (gnus-update-marks): Use `gnus-range-add' on a uncompressed list
+       instead, it seems to result in shorter ranges.
+
+2001-12-26 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-iso-8859-x-to-15-region): Use
+       insert-before-markers.
+       From Jesper Harder <harder@ifa.au.dk>
+
+2001-12-26  Paul Jarc  <prj@po.cwru.edu>
+
+       * nnmaildir.el (nnmaildir-save-mail): create the destination
+       groups if they do not exist.
+
+2001-12-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el (canlock-sha1-with-openssl): Remove unused variable.
+
+2001-12-22 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-read-ephemeral-group): Call
+       gnus-group-real-name.
+
+       * gnus-sum.el (gnus-decode-encoded-word-methods): Backslash paren.
+       (gnus-newsgroup-variables): Ditto.
+
+       * gnus.el (gnus-group-prefixed-name): If group name is prefixed,
+       return it.
+
+2001-12-21  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.el (gnus-valid-select-methods): Include nnmaildir.
+       * nnmaildir.el (top-level): Add commentary.
+       (nnmaildir-version): Indicate that nnmaildir is now a standard
+       part of Gnus, not separately released.
+
+2001-12-21 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el, gnus-picon.el, gnus-sieve.el, gnus-sum.el:
+       * gnus-xmas.el, imap.el, mailcap.el, mm-util.el, nnfolder.el:
+       * nnheader.el, nnmail.el: Nil/NIL vs. nil.
+       From  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+2001-12-20 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmaildir.el: Copyright changes. Require cl only at compile time.
+
+2001-12-20  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (top-level): Don't require cl.  Suggested by ShengHuo
+       ZHU <zsh@cs.rochester.edu>.
+       (nnimap-close-group): Don't quote KEYLIST items.  Suggested by
+       Brian P Templeton <bpt@tunes.org>.
+
+2001-12-19 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmaildir.el: New file.
+       From Paul Jarc <prj@po.cwru.edu>.
+
+2001-12-19 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-type-alist): Move forward to the end.
+
+2001-12-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (gnus-find-subscribed-addresses): Replace `mapc' with
+       `dolist'.
+
+2001-12-19 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-frames-on-display-list): New function.
+       (gnus-get-buffer-window): Use it.
+
+2001-12-19 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-mail-archive-xover): Fix the regexp.
+
+2001-12-18 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-get-buffer-window): Use gnus-delete-if.
+
+2001-12-18 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+          From Harald Meland <Harald.Meland@usit.uio.no>
+
+       * gnus-win.el (gnus-get-buffer-window): New function.
+       (gnus-all-windows-visible-p): Use it.
+
+       * gnus-util.el (gnus-horizontal-recenter)
+       (gnus-horizontal-recenter, gnus-horizontal-recenter)
+       (gnus-horizontal-recenter, gnus-set-window-start): Use it.
+
+       * gnus-score.el (gnus-score-insert-help): Use it.
+
+       * gnus-salt.el (gnus-tree-recenter, gnus-generate-tree)
+       (gnus-generate-tree, gnus-highlight-selected-tree)
+       (gnus-highlight-selected-tree, gnus-tree-highlight-article): Use
+       it.
+
+       * gnus-art.el (gnus-article-set-window-start)
+       (gnus-mm-display-part, gnus-request-article-this-buffer)
+       (gnus-button-next-page, gnus-button-prev-page)
+       (gnus-article-button-next-page, gnus-article-button-prev-page):
+       Use it.
+
+2001-12-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog, ChangeLog.1, nnwfm.el, smiley.el:
+       * gnus-cite.el, gnus-delay.el, gnus-spec.el, message.el:
+       * mml1991.el, nnultimate.el: Removed buffer-file-coding-system tag.
+
+2001-12-18 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * ChangeLog,  ChangeLog.1, nnwfm.el,  gnus-smiley.el:
+       * gnus-cite.el, gnus-delay.el, gnus-spec.el, message.el:
+       * mml1991.el, nnultimate.el: Add `coding'.
+
+2001-12-17  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog: changed coding to buffer-file-coding-system
+       * ChangeLog.1: same
+       * nnwfm.el: same
+       * gnus-smiley.el: same
+       * gnus-cite.el: moved -*- magic cookie -*- to Local Variables
+       * gnus-delay.el: same
+       * gnus-spec.el: same
+       * message.el: same
+       * mml1991.el: same
+       * nnultimate.el: same
+
+2001-12-16  Simon Josefsson  <jas@extundo.com>
+       Inspired by code by Dirk Meyer <dischi@tzi.de>.
+
+       * gnus-sum.el (gnus-summary-muttprint-program): New variable.
+       (gnus-summary-save-map): Add muttprint.
+       (gnus-summary-make-menu-bar): Ditto.
+       (gnus-summary-muttprint): New function.
+
+       * gnus-art.el (gnus-summary-pipe-to-muttprint): New function.
+
+2001-12-14 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * uudecode.el (uudecode-decode-region-internal): Speedup by using
+       temporary list instead of buffer.
+
+       * mm-url.el (executable-find): autoload.
+
+2001-12-12  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * gnus-mlspl.el (gnus-group-split-fancy): Doc fix (add reference
+       to variable, follow doc-string conventions).
+
+2001-12-13  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus-cus.el (gnus-extra-topic-parameters): added topic parameter
+       subscribe-level
+       * gnus-topic.el (gnus-subscribe-topics): use it.
+
+2001-12-13 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Forward all marked
+       messages. (A small patch with indentation)
+       From Sean Neakums <sneakums@zork.net>.
+
+       * gnus-uu.el (gnus-uu-grab-articles): Set gnus-current-article to
+       nil after shooting down the gnus-original-article-buffer.
+
+2001-12-13 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * uudecode.el (uudecode-use-external): New variable.
+       (uudecode-decode-region): Automatically detect external program.
+
+       * binhex.el (binhex-use-external): New variable.
+       (binhex-decode-region-internal): New function.
+       (binhex-decode-region): Automatically detect external program.
+
+       * mm-uu.el (mm-uu-decode-function,mm-uu-binhex-decode-function):
+       Use them.
+
+2001-12-12  Simon Josefsson  <jas@extundo.com>
+
+       * nnvirtual.el (nnvirtual-always-rescan)
+       (nnvirtual-component-regexp): Fix doc.
+
+       * nnoo.el (defvoo): Add doc to defvoo variables.
+
+       * nnml.el (nnml-directory, nnml-active-file)
+       (nnml-newsgroups-file, nnml-get-new-mail, nnml-nov-is-evil)
+       (nnml-marks-is-evil, nnml-filenames-are-evil)
+       (nnml-prepare-save-mail-hook, nnml-inhibit-expiry): Fix doc.
+
+       * nnmh.el (nnmh-directory, nnmh-get-new-mail)
+       (nnmh-prepare-save-mail-hook, nnmh-be-safe): Fix doc.
+       (nnmh-possibly-change-directory): Use `nnheader-report' instead of
+       `error'.
+
+       * nnmbox.el (nnmbox-mbox-file, nnmbox-active-file)
+       (nnmbox-get-new-mail, nnmbox-prepare-save-mail-hook):
+
+       * nnfolder.el (nnfolder-directory, nnfolder-active-file)
+       (nnfolder-newsgroups-file, nnfolder-get-new-mail)
+       (nnfolder-save-buffer-hook, nnfolder-inhibit-expiry)
+       (nnfolder-nov-is-evil, nnfolder-marks-is-evil): Fix doc.
+
+       * nnbabyl.el (nnbabyl-mbox-file, nnbabyl-active-file)
+       (nnbabyl-get-new-mail, nnbabyl-prepare-save-mail-hook): Fix doc.
+
+       * imap.el, nnimap.el: Fix indentation.
+
+       * gnus-sieve.el (gnus-sieve-article-add-rule): Autoload it.
+
+2001-12-12  Didier Verna  <didier@xemacs.org>
+
+       * gnus-msg.el (gnus-group-news): New function.
+       * gnus-group.el (gnus-group-mode-map): bind it to `i'.
+       * gnus-group.el (gnus-group-make-menu-bar): add a menu item for it.
+       * gnus-salt.el (gnus-carpal-group-buffer-buttons): add a button
+       for it.
+       * gnus-msg.el (gnus-summary-news-other-window): New function.
+       * gnus-msg.el ((gnus-summary-send-map "S" gnus-summary-mode-map)):
+       bind it to `i'.
+       * gnus-sum.el (gnus-summary-mode-map): bind it to `i'.
+       * gnus-sum.el (gnus-summary-make-menu-bar): add a menu item for it.
+       * gnus-salt.el (gnus-carpal-summary-buffer-buttons): add a button
+       for it (called with a prefix).
+       * gnus-msg.el (gnus-configure-posting-styles): add an optional
+       group-name argument.
+       * gnus-msg.el (gnus-setup-message): use it.
+
+2001-12-12 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): Fix doc.
+
+2001-12-10 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mime-to-mml): Remove Content-Disposition too.
+
+2001-12-09 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-buffer-name): Decode group name.
+       * gnus-group.el (gnus-group-name-decode): Decode unibyte
+       strings only.
+       From TSUCHIYA Masatoshi <tsuchiya@namazu.org>
+
+2001-12-08  Nevin Kapur  <nevin@jhu.edu>
+
+       * nnmail.el (nnmail-fancy-expiry-targets): New variable.
+       (nnmail-fancy-expiry-target): Use it.
+       Suggestions from Simon Josefsson <jas@extundo.com>.
+
+2001-12-07 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): Recount lines if not exist.
+
+2001-12-07 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwfm.el (nnwfm-create-mapping): Use gnus-url-unhex-string.
+
+       * gnus-util.el (gnus-url-unhex-string): Move here.
+
+2001-12-07 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-decode-entities-unibyte-string): Use
+       mm-url-decode-entities-nbsp.
+
+       * nnlistserv.el, nnultimate.el, nnwarchive.el, nnweb.el:
+       * webmail.el, nnwfm.el: Use mm-url.
+
+       * mm-url.el (mm-url-fetch-form): Move from nnweb.
+       (mm-url-remove-markup): Move from nnweb.
+       (mm-url-fetch-simple): Move from webmail.
+
+       * nnslashdot.el (nnslashdot-request-post): Use mm-url-fetch-form.
+
+2001-12-07 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-print-truncate-and-quote): New function.
+       (gnus-summary-print-article): Use it.
+
+       * gnus-util.el (gnus-replace-in-string): Typo.
+
+2001-12-06 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-replace-in-string): Removed.
+
+       * gnus-util.el (gnus-replace-in-string): New function.
+       (gnus-mode-string-quote): Use it.
+
+       * nnrss.el (nnrss-format-string): Use gnus-replace-in-string.
+       * nnwfm.el (nnwfm-create-mapping): Ditto.
+
+2001-12-06 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-compile): nnrss.el and
+       nnslashdot.el don't depend on nnweb, url, w3.
+
+       * nnrss.el: Use mm-url.
+
+2001-12-06 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el (mm-url-insert-file-contents): Support file:.
+
+2001-12-05 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el: Lower case for the description line. Sync from the
+       Emacs CVS.
+
+2001-12-05 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-find-new-groups): Fix doc.
+       From:  Stefan Monnier  <monnier@cs.yale.edu>
+
+2001-12-05  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-view.wl (mm-inline-text): Decode a charset-encoded rich text.
+
+2001-12-04 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el: Require executable.
+       Suggested by Katsumi Yamaoka <yamaoka@jpl.org>.
+
+2001-12-03 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * pop3.el (pop3-munge-message-separator): Only use valid date.
+       Trivial patch from Michael Welsh Duggan <md5i@cs.cmu.edu>.
+
+       * Makefile.in: gnus-load.elc may not be generated.
+
+2001-12-03 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-url.el: New file.
+       * nnslashdot.el: Use it.
+       * mm-extern.el (mm-extern-url): Use it.
+
+2001-12-01 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-save-article): Nix
+       gnus-display-mime-function and gnus-article-prepare-hook.
+
+       * gnus-spec.el (gnus-parse-complex-format): Properly handle %C at
+       the beginning of lines.
+       (gnus-complex-form-to-spec): Ditto.
+
+2001-12-01 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-make-mft): Fix the m-s-a-file regexp.
+       From Paul Jarc <prj@po.cwru.edu>.
+
+2001-11-30 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el: New variable message-subscribed-address-file;
+       use it in message-make-mft.  From Paul Jarc <prj@po.cwru.edu>.
+
+2001-11-30 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-tab-body-function): Set to nil.
+       (message-tab): Use text-mode-map or global-map.
+       Suggested by Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>.
+
+2001-11-30  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Use gnus-range-add
+       instead of gnus-union, for speed.  Suggested by Christoph Conrad
+       <christoph.conrad@gmx.de>.
+       (gnus-agent-fetch-group-1): Add verbose message.
+
+2001-11-29 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-write-active): Make sure sym is a cons
+       of integers.
+
+2001-11-29  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-newgroups-header-regexp)
+       (message-completion-alist, message-tab-body-function): Use
+       defcustom rather than defvar.
+       (message-tab): Mention `message-tab-body-function' in doc.
+       Suggested by Karl Eichwalder.
+
+2001-11-28 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-uu.el (gnus-uu-save-article): Use #part instead of #mml.
+
+2001-11-28 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-find-nov-line): Don't use macro
+       gnus-delete-line.
+
+       * gnus-group.el (gnus-group-name-decode): Defun instead of defsubst.
+       (gnus-group-name-charset): Ditto.
+
+       * gnus-util.el (gnus-buffer-live-p): Ditto.
+
+2001-11-28 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * sieve-manage.el (sieve-manage-stream-alist): Backslash before
+       open parenthesis in doc.
+       (sieve-manage-authenticator-alist): Typo in doc.
+       * imap.el (imap-authenticator-alist): Typo in doc.
+       (imap-stream-alist): Backslash.
+
+       * gnus-sum.el (gnus-summary-limit-to-author): Missing arguments.
+         Thanks to david.goldberg6@verizon.net (David S. Goldberg)
+
+2001-11-27 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-mode): Add LOCAL for add-hook.
+
+       * message.el (message-mode): make-local-hook is harmless in Emacs 21.
+
+       * gnus-msg.el (gnus-configure-posting-styles): use
+       make-local-hook. Add LOCAL for add-hook.
+
+2001-11-27  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-mode): Use `make-local-hook' unless
+       obsolete.
+       Patch by Katsumi Yamaoka <yamaoka@jpl.org>.
+
+2001-11-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * canlock.el: Remove sha1.el and base64.el stuff.
+
+2001-11-26  Didier Verna  <didier@xemacs.org>
+
+       * nnmbox.el (nnmbox-create-mbox): create the mbox file directory
+       if needed.
+
+2001-11-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-tamago-not-in-use-p): New function.
+       (message-strip-forbidden-properties): Use it.
+
+2001-11-26  Didier Verna  <didier@xemacs.org>
+
+       * gnus-start.el (gnus-check-first-time-used): only check for
+       existence of .el[d] files.
+
+2001-11-25 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-coding-system-priorities): Add backslash in the doc.
+
+       * message.el (message-setup-1): Clean up mc-*.
+
+2001-11-25 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-directory-sep-char-regexp): New variable.
+       * gnus-score.el (gnus-score-find-bnews): Use it.
+
+       * gnus-sum.el (gnus-summary-limit-to-subject): An exclusion version.
+       (gnus-summary-limit-to-author): Ditto.
+       (gnus-summary-limit-to-extra): Ditto.
+       (gnus-summary-find-matching): Support not-matching argument.
+
+2001-11-25  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-wash-subject): Use `insert' rather than
+       `insert-string', which is deprecated.
+
+2001-11-24  Simon Josefsson  <jas@extundo.com>
+
+       * mm-encode.el (mm-encode-content-transfer-encoding): Fix error
+       message. (Gnus does not "default" to using 8bit for the message,
+       it default to use 8bit encoding and the user-supplied CTE
+       value. Calling this behaviour "treating it as 8bit" is perhaps
+       better.)
+
+       * mm-bodies.el (mm-body-encoding): Intern encoding if needed
+       (compare mm-charset-to-coding-system).
+
+2001-11-23 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * canlock.el (canlock-sha1-with-openssl): Use unibyte
+       buffer. Correctly decode hex.
+
+2001-11-21 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-category-insert-line): Convert category
+       names to strings.
+
+2001-11-20 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (sha1): eval-and-compile.
+
+2001-11-20  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-allow-no-recipients): New variable.
+       (message-send): Use it, customize the prompting when posting to
+       Gcc/Fcc alone.  From prj@po.cwru.edu (Paul Jarc).
+
+2001-11-20 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-coding-system-priorities): New variable.
+       (mm-sort-coding-systems-predicate): New function.
+       (mm-find-mime-charset-region): Resort coding systems if needed.
+       Suggested by Katsumi Yamaoka <yamaoka@jpl.org>.
+
+2001-11-20  Didier Verna  <didier@xemacs.org>
+
+       * gnus-group.el (gnus-group-make-help-group): new optional
+       argument to control the error behavior.
+       * gnus-start.el (gnus-check-first-time-used): use it to avoid
+       erroring.
+
+2001-11-19  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-mode-map): Use C-c C-f C-i for Importance:
+       instead of C-c C-u.  Suggested by Per Abrahamsen
+       <abraham@dina.kvl.dk>.
+
+2001-11-18 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-read-folder): Use group instead of
+       nnfolder-current-group.
+       Suggested by Lorentey Karoly <lorentey@elte.hu>.
+
+2001-11-17  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-send): Ask user if Fcc/Gcc should be
+       performed when no other sender was specified.
+       Suggested by prj@po.cwru.edu (Paul Jarc).
+
+2001-11-17  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-mode, message-mode-map): Use C-c C-u for
+       Importance: instead of C-c C-p (used by SC).
+
+2001-11-16  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-insert-importance-high)
+       (message-insert-importance-low): Save point.
+
+       * mail-source.el (mail-source-fetch-imap): Fix BODY.PEEK return
+       value.
+
+2001-11-16  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-strip-special-text-properties): New option.
+       (message-strip-forbidden-properties): Obey it.
+
+2001-11-14  Sam Steingold  <sds@gnu.org>
+
+       * gnus-score.el: Fixed some doc strings to properly quote symbols.
+
+2001-11-15  Simon Josefsson  <jas@extundo.com>
+
+       Support "Importance:" header in Message.
+
+       * message.el (message-mode-map): Bind C-c C-p to
+       `message-insert-or-toggle-importance'
+       (message-mode-menu): Add message-insert-importance-{high,low}.
+       (message-insert-importance-high, message-insert-importance-low)
+       (message-insert-or-toggle-importance): New functions.
+       (message-tool-bar-map): Add {un,}important.
+       (message-mode): Doc fix.
+
+2001-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-tool-bar-map): Fix attach toolbar tooltip.
+
+       * mml.el (mml-menu): Fix toolbar tooltip.
+
+2001-11-15 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-save-marks): gnus-prin1 takes one argument.
+       * nnml.el (nnml-save-marks): Ditto.
+
+       * gnus-sum.el (gnus-newsgroup-variables): Fix doc.
+
+2001-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-save-marks):
+       * nnfolder.el (nnfolder-save-marks): Use `gnus-prin1'.
+       Suggested by Istvan Marko <mi-gnus@imarko.dhs.org>.
+
+2001-11-15  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (gnus-article-wash-status-strings): Use
+       `copy-sequence', not `copy-seq'.
+
+2001-11-15  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (gnus-article-wash-status-strings): New constant.
+       (gnus-gnus-article-wash-status-entry): New function.
+       (gnus-article-wash-status): Use it.
+
+2001-11-13 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml1991.el: Add coding header.
+
+2001-11-12  Simon Josefsson  <jas@extundo.com>
+
+       * mml1991.el (mml1991-use, mml1991-function-alist): New variables.
+       (mml1991-gpg-sign, mml1991-gpg-encrypt): Renamed, from
+       `mml1991-sign' and `mml1991-encrypt'.
+       (mml1991-encrypt, mml1991-sign): New glue functions.
+       (mml1991-mailcrypt-sign, mml1991-mailcrypt-encrypt): New functions.
+
+       * mml.el (mml-mode-map): `C-c RET o' map for PGP.
+       (mml-menu): Add PGP to menu.
+
+       * mml-sec.el (top-level): Require mml1991.  Don't require smime.
+       (mml-sign-alist, mml-encrypt-alist): Add "pgp".
+       (mml-pgp-sign-buffer, mml-pgp-encrypt-buffer)
+       (mml-secure-sign-pgp, mml-secure-encrypt-pgp): New glue functions.
+
+       * mml2015.el: Mention RFC 3156.
+
+       * mml1991.el: New file.  From Sascha L\e,A|\e(Bdecke <sascha@meta-x.de>.
+
+2001-11-12 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-auto-subscribed-groups): Use ^nnml.
+
+       * gnus-sum.el (gnus-summary-move-article): Use number-to-string.
+         From <Michael.Cook@cisco.com>
+
+2001-11-11  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (top-level): Autoload sha1.
+       (message-canlock-generate): Use sha1 instead of md5 (sha1 used by
+       canlock, no need to require two different hash algs).  Suggested
+       by Ferenc Wagner <wferi@bolyai1.elte.hu>.
+
+2001-11-09  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.el (gnus-local-domain): Fix doc.  From Pavel Jan\e,Am\e(Bk
+       <Pavel@Janik.cz>.
+
+2001-11-09  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-point-in-header-p): New function.
+       (message-do-auto-fill): Use it.
+       (message-beginning-of-line): New function.  Goes to beginning of
+       header value (i.e., end of header name), or to beginning of line
+       if already at beginning of value.  Behaves like
+       `beginning-of-line' when in message body.
+       (message-mode-map): Bind it.
+
+2001-11-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (gnus-posting-styles): Add doc.
+
+2001-11-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sieve.el (gnus-sieve-generate): Don't invoke sieve-mode.
+
+       * sieve-mode.el (sieve-control-commands-face)
+       (sieve-control-commands-face, sieve-action-commands-face)
+       (sieve-test-commands-face, sieve-tagged-arguments-face): New
+       faces.
+       (sieve-font-lock-keywords): Use them.
+       (sieve-mode): Only set font-lock-defaults in emacs.
+
+       * gnus-art.el (gnus-default-article-saver): Add
+       gnus-summary-save-body-in-file.
+       (gnus-summary-write-to-file): Fix doc.
+
+2001-11-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-art.el (gnus-treat-highlight-signature): Add cross
+       reference to the correct chapter in the manual.
+
+       * mml.el (mml-mode): Add cross reference to Emacs MIME manual.
+       Suggested by "Golubev I. N." <gin@mo.msk.ru>.
+
+2001-11-07 06:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-preview): Bind mail-header-separator.
+
+2001-11-07  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el: Always require canlock.
+       (message-ignored-supersedes-headers): Include Cancel-Lock and
+       Cancel-Key.
+       (message-insert-canlock): Don't require canlock.
+       (message-cancel-news): Don't check whether canlock is available.
+       (message-supersede): Support cancel-locks.
+
+       * gnus-art.el: Don't autoload canlock.
+
+2001-11-06 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-imap): ASYNC param.
+       From: <andre@slamdunknetworks.com>
+
+2001-11-06 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * many files: Fix copyright lines.
+
+2001-11-05 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Use mm-with-unibyte-current-buffer.
+       Suggested by Dave Love  <fx@gnu.org>.
+
+2001-11-04 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-kill-buffer): Remove auto-save file after
+       confirm.
+
+       * message.el (message-send-mail): Call message-generate-headers
+       once.  Suggested by Matt Armstrong <matt@lickey.com>.
+
+       * gnus-topic.el (gnus-topic-rename): Initial-input.
+       Suggested by Katsuhiro Hermit Endo <hermit@koka-in.org>.
+
+2001-11-03  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-forbidden-properties): New constant.
+       (message-strip-forbidden-properties): New function.
+       (message-mode): Activate it.
+
+2001-11-02 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-iso-8859-15-compatible): Fix doc.
+       (mm-hack-charsets): Fix doc.
+
+2001-11-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-int.el (gnus-check-server): Message "...done" when done.
+
+       * imap.el (imap-close): Don't message (imap-send-command-wait
+       returns if the connection is dropped).
+       (imap-wait-for-tag): Nix out message only when necessary.
+
+       * gnus-sieve.el (gnus-sieve-script): Use "stop" instead of "elsif"
+       for non-crossposting.
+       (gnus-sieve-crosspost): Default to t to be consistent with other
+       parts of Gnus.
+
+2001-11-01 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-iso-8859-15-compatible): Add inconvertible chars.
+       (mm-iso-8859-x-to-15-table): Ditto.
+       (mm-iso-8859-x-to-15-region): Ditto.
+       (mm-find-mime-charset-region): Ditto.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-close-asynchronous): New variable.
+       (nnimap-close-group): Use it.
+       (nnimap-expunge): Don't use it.
+
+       * imap.el (imap-callbacks): New variable.
+       (imap-remassoc): Copied from `gnus-remassoc'.
+       (imap-add-callback): New function.
+       (imap-mailbox-expunge, imap-mailbox-close): Support asynchronous
+       behaviour.
+       (imap-parse-response): Call the callback.
+
+       * message.el (message-insert-canlock): New variable.
+       (message-canlock-generate, message-canlock-password)
+       (message-insert-canlock): New functions.
+       (message-send-news): Call `message-insert-canlock'.
+       (top-level): Require canlock when compiling.
+       (message-insert-canlock): Require canlock before we need it.
+
+2001-11-01 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-copy-article-buffer): Copy sequence.
+
+2001-11-01 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-make-load): A workaround for
+       custom-add-loads bug in some versions of XEmacs.
+
+2001-11-01 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-synonym-alist): Revert (some).
+
+2001-11-01 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-iso-8859-x-to-15-region): New function.
+       (mm-hack-charsets): New variable.
+       (mm-iso-8859-15-compatible): New variable.
+       (mm-iso-8859-x-to-15-table): New variable.
+       (mm-find-mime-charset-region): Add parameter hack-charsets.
+
+       * mm-bodies.el (mm-encode-body): Use it.
+       * mml.el (mml-parse-1): Ditto.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-make-menu-bar): Add Sieve.
+
+2001-11-01 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-to-coding-system): Return nil, if charset
+       is nil.
+
+2001-11-01 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * smiley-ems.el (smiley-update-cache): Auto detect file type.
+
+       * message.el (message-forward-rmail-make-body): Use
+       save-window-excursion.
+       (message-encode-message-body): Search with noerror.
+       (message-setup-1): Convert compose-mail send-actions to
+       message-send-actions.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.el: Don't require easy-mmode. Suggested by Katsumi Yamaoka
+       <yamaoka@jpl.org>.
+
+2001-10-31 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * sieve-manage.el (sieve-string-bytes): No complain.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-mode-map): Bind "D u" to
+       `gnus-sieve-update' and "D g" to `gnus-sieve-generate'. (Functions
+       has autoload cookies, so no `require' should be necessary.)
+
+       * sieve.el, sieve-mode.el, sieve-manage.el, gnus-sieve.el: New
+       files.
+
+2001-10-31  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cus.el (gnus-group-parameters): Support integer `display'
+       parameter.
+
+       * gnus-sum.el (gnus-select-newsgroup): If group parameter
+       `display' is a number (and C-u wasn't used to enter group), only
+       fetch that number of articles.
+
+2001-10-31  Matt Armstrong  <matt@lickey.com>
+
+       * gnus.el (gnus-find-subscribed-addresses): Doc fix:
+       not-subscribed -> subscribed.
+
+2001-10-31 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From: Josh Huber <huber@alum.wpi.edu>
+
+       * message.el (message-subscribed-address-functions): New variable.
+       (message-subscribed-addresses): New variable.
+       (message-subscribed-regexps): New variable.
+       (message-goto-mail-followup-to): New function.
+       (message-send-mail): Add Mail-Followup-To.
+       (message-make-mft): New function.
+
+       * gnus.el (gnus-find-subscribed-addresses): New function.
+
+2001-10-31 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch): If debug, don't regain signals.
+       (mail-source-fetch-pop): Ditto.
+       (mail-source-check-pop): Ditto.
+
+       * gnus-start.el (gnus-read-init-file): Ditto.
+       (gnus-activate-group): Ditto.
+       (gnus-read-newsrc-el-file): Ditto.
+
+2001-10-30 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-get-reply-headers): Make sure there is ", ".
+
+       * mm-util.el (mm-mime-mule-charset-alist): Move down and call
+       mm-coding-system-p. Don't correct it only in XEmacs.
+       (mm-charset-to-coding-system): Use mm-coding-system-p and
+       mm-get-coding-system-list.
+       (mm-emacs-mule, mm-mule4-p): New variables.
+       (mm-enable-multibyte, mm-disable-multibyte,
+       mm-enable-multibyte-mule4, mm-disable-multibyte-mule4,
+       mm-with-unibyte-current-buffer,
+       mm-with-unibyte-current-buffer-mule4): Use them.
+       (mm-find-mime-charset-region): Treat iso-2022-jp.
+
+       From  Dave Love  <fx@gnu.org>:
+
+       * mm-util.el (mm-mime-mule-charset-alist): Make it correct by
+       construction.
+       (mm-charset-synonym-alist): Remove windows-125[02].  Make other
+       entries conditional on not having a coding system defined for
+       them.
+       (mm-mule-charset-to-mime-charset): Use
+       find-coding-systems-for-charsets if defined.
+       (mm-charset-to-coding-system): Don't use
+       mm-get-coding-system-list.  Look in mm-charset-synonym-alist
+       later.  Add last resort search of coding systems.
+       (mm-enable-multibyte-mule4, mm-disable-multibyte-mule4)
+       (mm-with-unibyte-current-buffer-mule4): Just treat Mule 5 like
+       Mule 4.
+       (mm-find-mime-charset-region): Re-write.
+       (mm-with-unibyte-current-buffer): Restore buffer as well as
+       multibyteness.
+
+2001-10-30 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * canlock.el, sha1-el.el, hex-util.el: Move from contrib
+       directory. Thanks to Katsumi Yamaoka <yamaoka@jpl.org> and Shuhei
+       KOBAYASHI <shuhei@aqua.ocn.ne.jp>.
+
+2001-10-30 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-display-x-face): Nix buffer-read-only
+       again.
+
+       * mml2015.el (mml2015-gpg-verify): Convert <LF> to <CR><LF>.
+
+2001-10-30 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-spec.el (gnus-parse-simple-format): Use
+         buffer-substring-no-properties.
+
+2001-10-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (article-verify-cancel-lock): New function.
+
+       * nnheader.el (nntp-process-response): New variable.
+       (nnheader-init-server-buffer): Make `nntp-process-response'
+       buffer-local in `nntp-server-buffer'.
+
+       * nntp.el (nntp-prepare-post-hook): New hook.
+       (nntp-wait-for): Save a server's ID in `nntp-process-response'.
+       (nntp-async-trigger): Ditto.
+       (nntp-request-post): Insert a server's ID if there's no Message-ID
+       header; run `nntp-prepare-post-hook'.
+
+2001-10-30 04:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-group-name): Use nnmail-fetch-field
+       instead.
+
+       * message.el (message-forward-subject-author-subject): Don't use
+       message-news-p, which widens the buffer.
+       (message-forward-make-body): New function.
+       (message-forward): Use it.
+       (message-insinuate-rmail): New function.
+       (message-forward-rmail-make-body): New function.
+
+2001-10-30 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-extern.el (mm-extern): Provide it.
+
+       * mm-partial.el (mm-partial): Provide it.
+
+2001-10-28 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-setup-message): Call post-command-hook.
+
+2001-10-29  Simon Josefsson  <jas@extundo.com>
+
+       * mml.el (mml-preview): Bind message-this-is-news if it is
+       news. From Jesper Harder <harder@myrealbox.com>.
+
+2001-10-28  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-group-make-articles-read): Inline group.
+
+2001-10-29  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * smiley-ems.el (smiley-regexp-alist): Add support for sad and
+       ironic smilies.
+
+2001-10-27  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-indent-citation): Don't add trailing
+       whitespace when citing text.
+
+       * gnus.el (gnus-group-faq-directory): Fix.  From Jesper Harder
+       <harder@ifa.au.dk>.
+
+2001-10-26 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-possibly-change-server): Create nnweb-hashtb if
+       not available.
+       (nnweb-request-scan): Nix nnweb-hashtb if ephemeral.
+       (nnweb-type-definition): Add google as alias of dejanews.
+       (nnweb-google-parse-1): Forward 1 line.
+
+2001-10-26  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Doc fix: add pointer to
+       variable `message-forward-ignored-headers'.
+
+2001-10-24  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-expand-group-parameter): New function.
+       (gnus-expand-group-parameters): Call it.
+       (gnus-group-fast-parameter): New function.
+       (gnus-group-find-parameter): Call it.
+
+2001-10-23  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-news-group-p): Rewrote.  Now accepts a header
+       vector (it didn't before because of a bug).
+       * gnus-msg.el (gnus-post-news): Use header vector directly, if
+       available.  Before it converted it to an article number.
+
+       This makes followup to news articles with negative numbers in
+       nnvirtual groups use news instead of mail.
+
+2001-10-23  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (post-method): Use `native' instead of `nil'.
+
+       * gnus-msg.el (gnus-post-method): Ditto.
+
+2001-10-23  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-define-group-parameter): Grammar fix.
+
+2001-10-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (gnus-extended-version): Include
+       system-configuration.
+       Suggested by Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro\e,b_\e(Bjohann).
+
+2001-10-22  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (post-method): Customization fix: `native' is not a
+       valid value.
+       * gnus-msg.el (gnus-post-method): Doc and customization fix:
+       `native' is not a valid value.
+
+2001-10-21  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap): Defgroup
+       (nnimap-strict-function, nnimap-strict-function-match): New
+       widget, from Per Abrahamsen  <abraham@dina.kvl.dk>.
+       (nnimap-split-crosspost, nnimap-split-inbox)
+       (nnimap-split-rule, nnimap-split-predicate)
+       (nnimap-split-predicate): Defcustom.
+       (nnimap-split-inbox, nnimap-expunge-search-string)
+       (nnimap-importantize-dormant): Remove "*" from doc.
+
+2001-10-20  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-summary-limit-to-score): Prompt for score if
+       not supplied via prefix arg.  From Lisp, make arg mandatory.
+       Suggested by Frank Schmitt.
+
+2001-10-20  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-do-auto-fill): Avoid calling
+       'rfc822-goto-eoh'.
+
+2001-10-20  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Paul Jarc <prj@po.cwru.edu>.
+
+       * message.el (message-get-reply-headers): Restructure the logic
+       and add comments.  From Paul Jarc <prj@po.cwru.edu>.
+
+2001-10-20  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-cancel-news): Support cancel-locks.
+       Suggested by Per Abrahamsson.
+
+       * nnml.el (nnml-marks-changed-p): Use `equal' when comparing
+       conses.  From David Z Maze <dmaze@MIT.EDU>.
+
+       * nnfolder.el (nnfolder-marks-changed-p): Ditto.
+
+2001-10-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * mm-decode.el (mm-default-directory): Fix customize type.
+
+       * message.el (message-setup-fill-variables): Kludge to use
+       normal-auto-fill-function even if auto fill is already activated.
+
+2001-10-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-do-auto-fill): New version that does not
+       rely on text properties, by Simon Josefsson <jas@extundo.com>.
+       (message-setup-1): Removed the `message-field' property.
+
+       * gnus-draft.el (gnus-draft-edit-message): Removed the
+       `message-field' property.
+
+2001-10-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-draft.el (gnus-draft-edit-message): Change `field' to
+       `message-field'.  The `field' property has a special significance in
+       Emacs 21.
+
+       * message.el (message-send, message-setup-1): Ditto.
+
+2001-10-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-group-make-articles-read): Call g-r-set-mark
+       when undoing.
+
+2001-10-18  Simon Josefsson  <jas@extundo.com>
+       From Frank Schmitt <usereplyto@Frank-Schmitt.net>
+
+       * gnus-sum.el (gnus-summary-limit-to-display-predicate): Fix typo.
+       (gnus-summary-make-menu-bar): Ditto.
+
+2001-10-17  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-expiry-target): Make sure it is back to the
+       server. Suggested by ShengHuo ZHU <zsh@cs.rochester.edu>.
+
+2001-10-17 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-line-format-alist): user-date entry.
+       * gnus-util.el (gnus-user-date): New function.
+       From Frank Schmitt <usenet@Frank-Schmitt.net>.
+
+2001-10-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-check-news-header-syntax): Special case
+       nnvirtual groups.
+
+       * gnus-sum.el (gnus-summary-respool-default-method): Changed
+       customize type to `symbol'.
+
+2001-10-17 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-spec.el (gnus-parse-simple-format): Support extended spec
+       %&foo;.
+       (gnus-parse-simple-format): Support user extended spec too.
+       %u&foo; invokes gnus-user-format-function-foo.
+
+2001-10-17 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnml.el (nnml-request-expire-articles): Make sure it is back to
+       the server.
+       * nnmbox.el (nnmbox-request-expire-articles): Ditto.
+       * nnfolder.el (nnfolder-request-expire-articles): Ditto.
+       * nnbabyl.el (nnbabyl-request-expire-articles): Ditto.
+       * nndiary.el (nndiary-request-expire-articles): Ditto.
+       (nndiary-schedule): Defsubst it before use it.
+       (nndiary-error): eval-and-compile.
+
+2001-10-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-msg.el (gnus-post-method): Changed two instances of
+       `active' to `current' and one `null' to `not'.
+
+2001-10-16  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Katsumi Yamaoka <yamaoka@jpl.org>.
+
+       * message.el (message-setup-fill-variables): Use
+       `normal-auto-fill-function' instead of `auto-fill-function'.
+
+2001-10-16  Simon Josefsson  <jas@extundo.com>
+
+       * mml2015.el (mml2015-fix-micalg): Fix for Mutt-bug.
+       (mml2015-gpg-decrypt-1): Decanonicalize decrypted MIME
+       body. (Mailcrypt seem to do this, but gpg.el doesn't.)
+
+2001-10-16  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       Patch by Oliver Scholz <oscholz@my.gnus.org>.
+
+       * gnus-draft.el (gnus-draft-edit-message): Add text property
+       `field' with value `header' to message headers.
+       * message.el (message-setup-1): Really add text property to all of
+       the header, not just part of it.
+
+2001-09-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-sort-by-server): Use it.
+
+       * gnus.el (gnus-method-to-full-server-name): New, bogus function.
+
+       * gnus-topic.el (gnus-topic-sort-groups-by-server): New command
+       and keystroke.
+
+2001-10-14  Simon Josefsson  <jas@extundo.com>
+
+       * dig.el: Doc fix.
+
+       * smime.el: Doc fix.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Port header encoded-word
+       charset magic from message.el.
+
+2001-10-12  Simon Josefsson  <jas@extundo.com>
+       Suggested by david.goldberg6@verizon.net (David S. Goldberg)
+
+       * gnus-cite.el (gnus-article-toggle-cited-text): Don't remove
+       'cite from g-a-wash-types.
+       (gnus-cite-toggle): Ditto.  Add 'cite.  Set modeline.
+       (gnus-article-hide-citation): Fix.
+
+       * gnus-cite.el (gnus-article-hide-citation): Add `c' mode line
+       character.
+       (gnus-article-toggle-cited-text): Toggle `c' mode line character.
+
+       * gnus-art.el (gnus-treat-hide-citation-maybe): Remove duplicate
+       definition.
+       (gnus-signature-toggle): Toggle `s' mode line character.
+
+       * gnus-art.el (article-emphasize): Set `g-a-wash-types' after
+       doing stuff that clears it.
+
+2001-10-12  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-summary-limit-include-cached): Rewrite.
+       From Eric Marsden <emarsden@laas.fr>.
+
+2001-10-12 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-do-auto-fill): Use gnus-point-at-bol.
+       (autoload): Add some autoloads.
+
+2001-10-12  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       Suggested by Oliver Scholz <epameinondas@gmx.de>.
+
+       * message.el (message-do-auto-fill): New function.  Like
+       `do-auto-fill' but don't fill when in the message header.
+       (message-setup-1): Put a text property on the message header.
+       (message-setup-fill-variables): Use `message-do-auto-fill'.
+
+2001-10-10 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially): Insert an empty line
+       first, because of the change of message-make-lines.
+
+2001-10-10  Florian Weimer  <fw@deneb.enyo.de>
+
+       * mm-util.el (mm-charset-synonym-alist): If Emacs doesn't support
+       iso-8859-15, make it an alias for iso-8859-1.
+
+2001-10-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-send-news): Don't modify the value of
+       `message-syntax-checks' if it is not a list (possibly it is
+       `dont-check-for-anything-just-trust-me').
+
+2001-10-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-group.el (gnus-group-name-charset-group-alist): Use
+       `find-coding-system' for XEmacs to check whether the coding-system
+       `utf-8' is available.
+
+2001-10-09 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-compile): Detect mh-e and xml.
+
+2001-10-09  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-send-news): Oops, missed case with no
+       "Followup-To" header...
+
+2001-10-09  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-send-news): Allow
+       `gnus-group-name-charset-group-alist' to affect encoding of the
+       "Newsgroups" and "Followup-To" headers.
+
+2001-10-07 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (install-el): Depend on gnus-load.el.
+
+2001-10-07 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (install-el): Use -f.
+       From: Amos Gouaux <amos+lists.ding@utdallas.edu>
+
+2001-10-07  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-send-news): Don't encode Followups-To when
+       `gnus-group-name-charset-group-alist is' ".*".  [Yuck]
+
+       * gnus-util.el (gnus-decode-newsgroups): No space in newsgroup
+       header.
+
+       * gnus-art.el (article-decode-group-name): Also decode
+       "Followup-To".
+
+       * rfc2047.el (rfc2047-encode-message-header): Encode without
+       asking for null methods.
+
+       * gnus-group.el (gnus-group-name-charset-group-alist): Make utf-8
+       default charset for newsgroup names in accordance with USEFOR.
+
+       * gnus-group.el (gnus-group-name-charset-method-alist,
+       gnus-group-name-charset-group-alist): Removed "*" from doc
+       strings, "*" should not be used for complex variables.
+
+2001-10-06  Simon Josefsson  <jas@extundo.com>
+
+       Support UTF-8 group names better.
+
+       * message.el (message-check-news-header-syntax): Encode group
+       names before comparison.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Run all
+       `gnus-article-decode-hook's except `article-decode-charset'
+       instead of hardcoding call to one of them.
+
+       * gnus-art.el (gnus-article-decode-hook): Add
+       `article-decode-group-name'.
+       (article-decode-group-name): New function, use `g-d-n'.
+
+       * gnus-group.el (gnus-group-insert-group-line): Decode
+       gnus-tmp-group using `g-d-n'.
+
+       * gnus-util.el (gnus-decode-newsgroups): New function.
+
+2001-10-06  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Fixed bug non-nil
+       `gnus-group-name-charset-group-alist'.
+
+2001-10-06 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Install el in install. Add uninstall.
+
+2001-10-05  Simon Josefsson  <jas@extundo.com>
+
+       * nnheader.el (gnus-verbose-backends, gnus-nov-is-evil): Custom.
+
+       * gnus-sum.el (gnus-summary-move-article): Also activate new groups.
+
+       * nnfolder.el (nnfolder-normalize-buffer): Don't insert \n\n in
+       empty folders.
+
+       * gnus-sum.el (gnus-select-newsgroup): Don't enable `display'
+       limiting if read-all (C-u RET) was used.
+
+2001-10-04  Simon Josefsson  <jas@extundo.com>
+
+       * mail-source.el (mail-source-movemail-program): New variable.
+       (mail-source-movemail): Use it.  Suggested by Taylor Hutt
+       <thutt@thutt.vmware.com>.
+
+2001-10-03  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): New param.
+       (gnus-summary-line-format-alist): Fix param.
+
+2001-10-02  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-request-move-article): Use imap.el directly,
+       don't go through `nnimap-request-expire-articles' to delete the
+       article.  Thanks to prj@po.cwru.edu (Paul Jarc).
+
+2001-10-02 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-write-active): The min in the
+       agent/active may be larger than that in the server/active.
+
+2001-10-01  Simon Josefsson  <jas@extundo.com>
+
+       * mail-source.el (mail-source-fetch-imap): Use BODY.PEEK if server
+       is IMAP4rev1.
+
+       * nnml.el (gnus-article-unpropagatable-p): Autoload gnus-sum.
+
+       * nnfolder.el: Ditto.
+
+2001-09-30  Dan Christensen  <jdc@uwo.ca>
+
+       * gnus-sum.el (gnus-summary-extract-address-component): New function.
+       (gnus-summary-from-or-to-or-newsgroups): Optimize.
+
+2001-09-29  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-mode-map): Keybinding for `gnus-delay-article'.
+       (message-mode-menu): Menu item for same.
+
+       * gnus-group.el (gnus-group-make-menu-bar): Menu item for sending
+       delayed articles.
+
+       * gnus-delay.el (gnus-delay-send-drafts): Do nothing if
+       nndraft:delayed does not exist.
+       (gnus-delay-initialize): Don't set up keymap, that's done from
+       message.el now.
+       (gnus-delay, gnus-delay-group, gnus-delay-header)
+       (gnus-delay-default-delay, gnus-delay-default-hour): Customize.
+
+2001-09-29  Simon Josefsson  <jas@extundo.com>
+
+       * mm-util.el (mm-mime-mule-charset-alist): Encode mule-utf-8 as
+       utf-8, not eight-bit-control.
+
+       * imap.el (imap-shell-host, imap-default-user, imap-use-utf7)
+       (imap-log, imap-debug): Custom.
+       (imap-log-buffer, imap-debug-buffer): New constants.
+       (imap-kerberos4-open, imap-gssapi-open, imap-ssl-open)
+       (imap-network-open, imap-shell-open, imap-starttls-open)
+       (imap-send-command-1, imap-send-command, imap-arrival-filter)
+       (imap-debug): Use imap-*-buffer.
+
+       * nndoc.el (nndoc-article-type): Add mailman.
+       (nndoc-type-alist): Ditto.
+       (nndoc-mailman-type-p): New function.
+
+2001-09-28 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-article-x-face-command): Merge it into
+       gnus-art.el.
+
+2001-09-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-topic.el (gnus-topic-mode-map): Add catchup.
+       (gnus-topic-catchup-articles): New function. Suggested by Robin
+       S. Socha <robin-dated-1001857693.185e29@socha.net>.
+
+2001-09-27 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Gerd M\e,Av\e(Bllmann <gerd@gnu.org>.
+
+       * gnus-ems.el (gnus-article-display-xface): Insert xface after
+       previous ones.
+
+2001-09-27 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Daiki Ueno  <ueno@unixuser.org>
+
+       * gnus-sum.el (gnus-summary-show-article): The arglist of
+       detect-coding-region is incompatible.
+
+2001-09-26 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Katsuhiro Hermit Endo <hermit@koka-in.org>
+
+       * gnus-group.el (gnus-group-delete-group): Typo.
+
+2001-09-26  Simon Josefsson  <jas@extundo.com>
+
+       * nnmail.el (nnmail-expiry-target-group): Add doc warning.
+
+       * nnimap.el (nnimap-expiry-target): Use temp buffer.
+
+2001-09-26 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cus.el (gnus-group-parameters): Display as sexp.
+
+2001-09-22  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-open-marks): Remove unpropagatable marks.
+
+       * nnfolder.el (nnfolder-open-marks): Ditto.
+
+       * gnus-sum.el (gnus-article-unpropagatable-p): New function.
+       (gnus-update-marks): Use it.
+       (gnus-update-marks): Use `gnus-article-mark-to-type' instead of
+       hardcoded list.
+
+       * gnus.el (gnus-article-special-mark-lists): Add killed.
+       (gnus-article-unpropagated-mark-lists): New constant.
+
+2001-09-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-mode-hook): Add gnus-pick-mode as
+       custom option.
+
+2001-09-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-draft.el (gnus-draft-setup): Add mark in backend as well.
+
+2001-09-23 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-button-mailto): Hack save-selected-window-window.
+
+2001-09-22  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-group.el (gnus-group-sort-function): Fix customize type to
+       accept lists of functions.
+
+2001-09-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-catchup): Update expire marks in
+       backend.  Also, if ALL also set expire marks on tick/dormant.
+
+2001-09-20  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-tab-body-function): New variable.
+       * message.el (message-tab): Use it.
+
+2001-09-19  Sam Steingold  <sds@gnu.org>
+
+       * gnus-win.el (gnus-buffer-configuration): Respect
+       `gnus-bug-create-help-buffer'.
+
+2001-09-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-spec.el (gnus-correct-pad-form): Re-revert.
+       (gnus-parse-simple-format): Re-revert.
+
+2001-09-16  Katsuhiro Hermit Endo  <hermit@koka-in.org>
+       Trivial patch.
+
+       * gnus-spec.el (gnus-parse-complex-format): Don't fold search
+       case.  (Thanks to Daiki Ueno <ueno@unixuser.org>.)
+
+2001-09-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-spec.el (gnus-correct-pad-form): Remove until papers are
+       signed.
+       (gnus-parse-simple-format): Don't use it.
+
+2001-09-17  Miles Bader  <miles@gnu.org>
+
+       * gnus-srvr.el (gnus-server-insert-server-line): Don't let an
+       error querying a backend abort the whole process.
+
+2001-09-17 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-server-mode): Fix bogus fontification.
+       From Gerd M\e,Av\e(Bllmann <gerd@gnu.org>.
+
+2001-09-17  Didier Verna  <didier@xemacs.org>
+
+       * nndiary.el: version 0.2-b14.
+       * gnus-diary.el (gnus-diary-check-message): fix `read-string'
+       compatibility problem with XEmacs 21.1.
+
+2001-09-15  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-line-format): Document %c.
+
+       * nnml.el (nnml-parse-head): Handle CRLF files.
+       (nnml-generate-nov-file): Ditto.
+       (nnml-retrieve-headers): Ditto.
+
+2001-09-15  Michael Welsh Duggan  <md5i@cs.cmu.edu>
+
+       * gnus-spec.el (gnus-parse-format): Don't treat %c as %C.
+
+2001-09-13  Martin Kretzschmar  <Martin.Kretzschmar@inf.tu-dresden.de>
+
+       * gnus-spec.el (gnus-correct-substring): Still stopped one
+       character before we wanted (never included last character).
+       (gnus-tilde-max-form, gnus-tilde-cut-form) Made readable again,
+       add missing "," (once per function)
+
+2001-09-14  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-start.el (gnus-group-mode-hook): Moved from gnus-group
+       (otherwise e.g. gnus-agentize in .gnus overrides the customized
+       default before gnus-group is loaded and the variable set.)
+
+       * nnimap.el (nnimap-request-set-mark): Do not store bookmark,
+       killed or unsent marks.
+
+       * gnus-draft.el (gnus-draft-setup): Don't set mark when there
+       isn't an article to set it on (e.g. when you `a' in a group).
+
+2001-09-12  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * mm-util.el (mm-charset-synonym-alist): add windows-1250 so we
+       can read e-mails from Microsoft Outlook users not using ISO
+       8859-2 character set.
+
+2001-09-12 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-diary.el: Minor modifications to avoid warnings.
+       (gnus-summary-misc-menu): defvar.
+       (gnus-diary-check-message): Use gnus-point-at-eol.
+       (gnus-diary-kill-entire-line): eval-and-compile.
+
+2001-09-12  Didier Verna  <didier@xemacs.org>
+
+       * nndiary.el: new version (0.2-b13).
+       * nndiary.el (nndiary-mail-sources): doc update.
+       * nndiary.el (nndiary-split-methods): ditto.
+       * nndiary.el (nndiary-request-accept-article-hooks): New.
+       * nndiary.el (nndiary-request-accept-article): use it, check
+       message validity.
+       * nndiary.el (nndiary-get-new-mail): changed default to nil.
+       * nndiary.el (nndiary-schedule): fix bug (misplaced
+       condition-case): it didn't return nil on error.
+       * gnus-diary.el: new version.
+       * gnus-diary.el (gnus-diary-summary-line-format): removed %I.
+       * gnus-diary.el (gnus-diary-header-value-history): New.
+       * gnus-diary.el (gnus-diary-narrow-to-headers): New.
+       * gnus-diary.el (gnus-diary-add-header): New.
+       * gnus-diary.el (gnus-diary-check-message): New.
+       * gnus-diary.el (message-mode-map): bind the above to `C-c D c'.
+       * gnus-diary.el (gnus-article-edit-mode-map): ditto.
+
+2001-09-10 TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+       * gnus-sum.el (gnus-select-newsgroup): Make
+       `gnus-current-select-method' buffer-local.
+
+       * gnus-art.el (gnus-request-article-this-buffer): Refer
+       `gnus-current-select-method' in the current summary buffer.
+
+2001-09-10  Simon Josefsson  <jas@extundo.com>
+       From Daniel Pittman <daniel@rimspace.net>
+
+       * gnus-spec.el (gnus-correct-pad-form): Fix.
+
+2001-09-09  Simon Josefsson  <jas@extundo.com>
+
+       * mm-decode.el (mm-inline-media-tests): Add
+       application/x-emacs-lisp.
+       (mm-attachment-override-types): Add
+       application/{x-,}pkcs7-signature.
+
+       * gnus-srvr.el (gnus-server-mode-hook, gnus-server-exit-hook)
+       (gnus-server-line-format, gnus-server-mode-line-format)
+       (gnus-server-browse-in-group-buffer): Customize.
+
+2001-09-08 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnml.el (nnml-marks-changed-p): Typo.
+       (nnml-save-marks, nnml-open-marks): Use gnus-sethash.
+       (nnml-marks-changed-p): Use gnus-gethash.
+       (nnml-marks-modtime): Use gnus-make-hashtable.
+
+       * nnfolder.el (nnfolder-marks-changed-p): Typo.
+       (nnfolder-request-expire-articles, nnfolder-save-marks)
+       (nnfolder-open-marks): Typo.
+       (nnfolder-save-marks, nnfolder-open-marks): Use gnus-sethash.
+       (nnfolder-marks-changed-p): Use gnus-gethash.
+       (nnfolder-marks-modtime): Use gnus-make-hashtable.
+
+2001-09-08  Simon Josefsson  <jas@extundo.com>
+
+       * nnfolder.el (nnfolder-marks-modtime): New variable.
+       (nnfolder-marks-changed-p): New function.
+       (nnfolder-save-marks, nnfolder-open-marks): Save modtime.
+       (nnfolder-request-update-info): Don't update if marks didn't change.
+
+       * nnml.el (nnml-marks-modtime): New variable.
+       (nnml-marks-changed-p): New function.
+       (nnml-save-marks, nnml-open-marks): Save modtime.
+       (nnml-request-update-info): Don't update if marks didn't change.
+
+       * gnus-agent.el (gnus-agent-any-covered-gcc)
+       (gnus-agent-add-server, gnus-agent-remove-server): Use
+       gnus-agent-method-p.
+
+       * gnus-art.el (gnus-buttonized-mime-types): New variable.
+       (gnus-unbuttonized-mime-type-p): Use it.
+
+       * gnus-agent.el (gnus-agent-fetch-group): If online, actually
+       fetch group.
+
+2001-09-08  Simon Josefsson  <jas@extundo.com>
+       From Daniel Pittman <daniel@rimspace.net>
+
+       * gnus-spec.el (gnus-correct-pad-form): New function.
+       (gnus-parse-simple-format): Use it.
+
+2001-09-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-group-sort-groups): Unmark all groups.
+       (gnus-group-sort-selected-groups): Ditto.  Suggested by Harry
+       Putnam <reader@newsguy.com>.
+       (gnus-group-sort-selected-groups): Touch dribble file.
+
+2001-09-07 Raja R Harinath  <harinath@cs.umn.edu>
+
+       * nnml.el (nnml-filenames-are-evil): New variable.
+       (nnml-article-to-file-alist): Rename to ...
+       (nnml-current-group-article-to-file-alist): ... this.
+       Respect `nnml-filenames-are-evil'.
+       (nnml-active-number): Update.
+       (nnml-update-file-alist): Update.
+       (nnml-request-article): Use nnheader-article-to-file-alist.
+       (nnml-request-rename-group): Likewise.
+
+2001-09-06  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-summary-insert-line): Fix.
+
+2001-09-06  Bj\e,Av\e(Brn Torkelsson  <torkel@acc.umu.se>
+
+       * gnus-sum.el: Bind g-s-t-s to "W g".
+       * gnus-sum.el (gnus-summary-make-menu-bar): Add g-s-t-s.
+       * gnus-sum.el (gnus-summary-toggle-smiley): New function. Toggles
+       display of graphical smilies.
+
+2001-09-07 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-setup-news): A typo.
+       From Bill White <billw@wolfram.com>.
+
+2001-09-06  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-insert-line): Insert forwarded, recent
+       and unseen marks.
+
+2001-09-05  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-split-fancy): Document `junk'.
+
+2001-09-04  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-search): Don't error if server is broken.
+
+2001-09-02  Benjamin Rutt  <brutt@bloomington.in.us>
+
+       * nnmbox.el (nnmbox-find-article): Fix infinite loop when
+       searching for an article that isn't in the mbox.
+
+2001-09-02 23:12:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-retrieve-headers-1): Get references
+       right, and get all the comments.
+
+2001-09-02  Simon Josefsson  <jas@extundo.com>
+       Suggested by Dan Christensen <jdc+news@uwo.ca>
+
+       * nnfolder.el (nnfolder-request-update-info): Fix message.
+
+       * nnml.el (nnml-request-update-info): Ditto.
+
+2001-09-01  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-request-expire-articles): Also bind
+       `nnml-current-group' and `nnml-article-file-alist' when using
+       expiry-target. (Otherwise nnml will be in a inconsistent internal
+       state causing all kind of problems.)
+       (nnml-request-expire-articles): If `nnml-article-to-file' or
+       `file-attributes' failes, return article as un-expirable instead
+       of treating it as expired.
+
+2001-08-31  Sam Steingold  <sds@gnu.org>
+
+       * imap.el (imap-mailbox-examine, imap-mailbox-examine-1): Fix a
+       typo: `exmine' --> `examine'.
+
+2001-08-30 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-forward-type-p): It is not a digest.
+
+2001-08-30 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnml.el (nnml-check-directory-twice): Remove.
+       (nnml-retrieve-headers): Ditto.
+       (nnml-article-to-file): Use nnheader-directory-files-is-safe.
+
+2001-08-30  Andrew Innes  <andrewi@gnu.org>
+
+       * nnheader.el (nnheader-directory-files-is-safe): No need to read
+       directory twice on Windows, or on GNU Emacs-21.
+
+2001-08-30  Andrew Innes  <andrewi@gnu.org>
+
+       * nnml.el (nnml-request-article): Use nnml-article-to-file-alist.
+       (nnml-request-rename-group): Ditto.
+       (nnml-active-number): Ditto.
+       (nnml-request-create-group): Use nnml-directory-articles.
+       (nnml-request-expire-articles): Use nnml-directory-articles, which
+       gets list from nov database if available.
+       (nnml-get-nov-buffer): New function.
+       (nnml-open-nov): Use it.
+       (nnml-update-file-alist): Use nnml-article-to-file-alist, which
+       gets alist from nov database if available.
+       (nnml-directory-articles): New function.
+       (nnml-article-to-file-alist): New function.
+
+2001-08-30  Andrew Innes  <andrewi@gnu.org>
+
+       * mm-decode.el (mm-display-external): Use `name' as filename, if
+       `filename' attribute is not present.
+
+2001-08-30  Andrew Innes  <andrewi@gnu.org>
+
+       * mail-source.el (mail-source-flash): New defcustom.
+       (mail-source-new-mail-p): Ring visible bell if appropriate.
+       (mail-source-start-idle-timer): Use unwind-protect to ensure idle
+       timer is cleared even if mail check signals an error.
+
+2001-08-29 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-move-article): Only update marks of
+       type 'list.
+
+2001-08-29 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * flow-fill.el (fill-flowed): eol might be point-max.
+
+2001-08-27  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-request-update-info): Fix message.
+       (nnml-open-marks): Ditto.
+
+       * nnfolder.el (nnfolder-request-update-info):
+       (nnfolder-open-marks): Fix message.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+
+       * nnfolder.el (nnfolder-save-marks): Don't create directory named
+       after group in ~/.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+       From Andreas Jaeger  <aj@suse.de>
+
+       * nnfolder.el (nnfolder-open-marks): Fix typo.
+       * nnml.el (nnml-open-marks): Likewise.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+
+       Make nnfolder groups self-contained as far as marks are concerned.
+
+       * nnfolder.el (nnfolder-marks-directory, nnfolder-marks-is-evil)
+       (nnfolder-marks, nnfolder-marks-file-suffix): New variables.
+       (nnfolder-open-server): Make marks directory.
+       (nnfolder-request-delete-group): Delete marks file.
+       (nnfolder-request-delete-group): Check of nov/marks file exist
+       before deleting.
+       (nnfolder-request-rename-group): Rename marks file.
+       (nnfolder-request-rename-group): Only rename nov/mark if they exists.
+       (nnfolder-request-set-mark, nnfolder-request-update-info)
+       (nnfolder-group-marks-pathname, nnfolder-save-marks)
+       (nnfolder-open-marks): New functions.
+       (top-level): Require gnus.
+
+2001-08-25 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-type-definition): Use google raw file.
+       (nnweb-google-parse-1): Ditto.
+       (nnweb-google-identity): Ditto.
+       (nnweb-reference-wash-article): Move nnweb-decode-entities here.
+       (nnweb-altavista-wash-article): Ditto.
+       (nnweb-request-article): Remove nnweb-decode-entities.
+
+       * nnml.el: Require 'gnus.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-marks-is-evil): Add doc.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-save-marks): Wrap saving marks in a
+       condition-case, to allow user to start Gnus if saving marks failed
+       for some reason.
+
+2001-08-24 16:05:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-spec.el (gnus-compile): Don't compile gnus-version.
+
+       * gnus-group.el (gnus-update-group-mark-positions): Bind
+       gnus-group-update-hook to nil.
+
+2001-08-24 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Force as multibyte string.
+
+2001-08-24 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-insert-line)
+       (gnus-summary-prepare-threads): gnus-tmp-lines should be a string.
+       From Martin Kretzschmar <Martin.Kretzschmar@inf.tu-dresden.de>
+
+       * gnus-spec.el (gnus-correct-substring): Take optional END.
+
+       * nnrss.el (nnrss-request-article): Remove \n.
+       (nnrss-retrieve-headers): Lines number is -1.
+
+2001-08-24  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-group.el (gnus-info-clear-data): Call
+       nnfoo-request-set-mark to propagate marks.  Fix bug:
+       `gnus-group-update-line' doesn't update read range unless we call
+       `gnus-get-unread-articles-in-group' first.
+
+       * nnimap.el (nnimap-request-set-mark): Don't propagate seen flags
+       to server.
+
+2001-08-23 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-create-info-command): Return an interactive
+       function.
+
+2001-08-23 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * gnus-spec.el (gnus-parse-complex-format): Use equal.
+
+2001-08-23 18:43:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-select-newsgroup): Use it.
+
+       * gnus-util.el (gnus-not-ignore): New function.
+
+       * lpath.el (featurep): Don't fbind char-int.
+
+       * gnus-util.el (gnus-create-info-command): New function.
+
+       * gnus-group.el (gnus-group-edit-group): Make C-c C-i go to the
+       right node.
+
+       * gnus-sum.el (gnus-select-newsgroup): Clean up.
+       (gnus-summary-limit-children): Use 'identity instead of `all'.
+       (gnus-summary-limit-to-display-predicate): New command and
+       keystroke.
+
+2001-08-23 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-group-alist): Use fm-releases.rdf.
+
+       * gnus-spec.el (gnus-format-specs): Miss a right parenthesis.
+
+2001-08-23 18:43:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-spec.el: Add the Gnus version.
+       (gnus-update-format-specifications): If the Gnus version changes,
+       nix out the format spec cache.
+
+       * gnus.el (gnus-continuum-version): Made into a command and
+       optionalize the VERSION.
+
+       * gnus-spec.el (gnus-parse-complex-format): Remove %C specs from
+       the start of the lines.
+
+2001-08-22 00:06:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-visual-p): Define function before use of
+       function.
+
+2001-08-21 23:28:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-adjust-marked-articles): Use new variable.
+       (gnus-article-mark-to-type): New function.
+       (gnus-update-missing-marks): Only update marks of type 'list.
+
+       * gnus.el (gnus-article-special-mark-lists): New variable.
+
+2001-08-21 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-limit-children): Check 'all.
+       (gnus-select-newsgroup): Still use 'all.
+       (gnus-summary-initial-limit): Comparing with 'all.
+
+2001-08-20 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-activate-group): If dont-check, don't update
+       active.
+
+2001-08-20 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-retrieve-headers-1): Replace
+       nnslashdot-*-retrieve-headers.
+       (nnslashdot-request-article): Fix for slashcode 2.2.
+       (nnslashdot-make-tuple): New function.
+       (nnslashdot-read-groups): Use it.
+
+2001-08-20 01:34:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-expand-group-parameters): Don't alter the variable
+       list.
+
+       * gnus-sum.el (gnus-summary-move-article): Don't select article.
+
+2001-08-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-msg.el (gnus-inews-do-gcc): If archive server can't be
+       opened, error instead of continuing (and exploding later).
+
+2001-08-20 01:34:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-expand-group-parameters): Return the parameter
+       list.
+
+       * gnus-sum.el (gnus-summary-show-article): Doc fix.
+       (gnus-summary-show-article): Guess at charset if required.
+
+       * gnus-spec.el (gnus-correct-substring): Stopped one character
+       before we wanted.
+
+2001-08-19  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * earcon.el (earcon-auto-play): Remove unused option.
+
+2001-08-19 16:14:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-headers): Move the "Scoring..."
+       message down in levels, since it happens very fast.
+
+       * smiley-ems.el (smiley-update-cache): Respect the symbol version
+       of smiley-regexp-alist.
+
+       * mm-view.el (mm-inline-text): Ignore vcard errors.
+
+       * gnus-art.el (gnus-ignored-headers): Added more junk headers.
+
+       * gnus-score.el (gnus-all-score-files): Use append instead of
+       nconc.
+
+       * gnus.el (gnus-splash-face): Doc fix.
+
+       * mm-decode.el (mm-mailcap-command): Use
+       mm-path-name-rewrite-functions.
+       (mm-path-name-rewrite-functions): New variable.
+
+       * gnus-spec.el (gnus-parse-complex-format): React to ?=.
+       (gnus-complex-form-to-spec): Insert tab.
+       (gnus-spec-tab): New function.
+
+       * gnus-sum.el (gnus-select-newsgroup): Set the marks before
+       entering the group.
+
+       * gnus-spec.el (gnus-complex-form-to-spec): Insert Lisp to match
+       the positional spec.
+       (gnus-parse-complex-format): React to %C.
+
+       * gnus-ems.el (gnus-char-width): Moved here.
+
+       * gnus-sum.el (gnus-select-newsgroup): Set
+       gnus-newsgroup-articles.
+       (gnus-unseen-mark): New variable.
+       (gnus-newsgroup-unseen): Ditto.
+       (gnus-newsgroup-seen): Ditto.
+       (gnus-adjust-marked-articles): Use them.
+       (gnus-update-marks): Use them.
+       (gnus-summary-update-secondary-mark): Display.
+       (gnus-summary-prepare-threads): Display.
+
+       * gnus-msg.el (gnus-inews-group-method): Use and return the
+       method, not the server.
+
+2001-08-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-srvr.el (gnus-server-agent-face): New.
+       (gnus-server-agent-face): New.
+       (gnus-server-mode): Turn on font-lock-mode.
+
+       * gnus.el (gnus-server-visual): Add defgroup.
+
+2001-08-19  Simon Josefsson  <jas@extundo.com>
+       From Joe Casadonte <jcasadonte@northbound-train.com>
+
+       * gnus-srvr.el (gnus-server-opened-face, gnus-server-closed-face,
+       gnus-server-denied-face): New.
+       (gnus-server-opened-face, gnus-server-closed-face,
+       gnus-server-denied-face): New.
+       (gnus-server-font-lock-keywords): Add.
+
+2001-08-19  Simon Josefsson  <jas@extundo.com>
+
+       * nnml.el (nnml-request-set-mark): Return nil.
+       (nnml-save-marks): Use nnml-possibly-create-directory.
+       (nnml-open-marks): Only work in temp buffer when inserting/reading
+       .marks file.
+
+2001-08-18 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-expand-group-parameters): Fix.
+
+       * gnus-spec.el (gnus-char-width): New function.
+       (gnus-correct-substring, gnus-correct-length): Use it.
+
+       * message.el (message-required-mail-headers): Fix doc.
+
+2001-08-18 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-group-make-articles-read): gnus-request-set-mark.
+
+       * mm-decode.el (mm-save-part-to-file): Insert the handle.
+
+2001-08-18 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers):
+       slashdot 2.2 (not fully fixed yet).
+       (nnslashdot-request-article): Ditto.
+
+2001-08-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-util.el (gnus-remassoc, gnus-update-alist-soft): Moved from
+       nnimap.
+
+       * nnimap.el (nnimap-remassoc, nnimap-update-alist-soft): Moved to
+       gnus-util.
+       (nnimap-request-update-info-internal): Use new functions.
+
+       * nnml.el (nnml-request-set-mark, nnml-request-update-info): Use
+       new functions.
+
+2001-08-18  Simon Josefsson  <jas@extundo.com>
+
+       Make nnml groups self-contained as far as marks are concerned.
+
+       * nnml.el (nnml-request-delete-group): Delete marks file.
+       (nnml-request-rename-group): Move marks file.
+       (nnml-marks-file-name, nnml-marks-is-evil, nnml-marks): New server
+       variables.
+       (nnml-request-set-mark, nnml-request-update-info): New server
+       functions.
+       (nnml-save-marks, nnml-open-marks): New functions.
+
+2001-08-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-sum.el (gnus-summary-move-article): Use `add' instead of
+       `set' when setting marks.
+
+2001-08-17 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-info-find-node): Take an argument.
+
+       * gnus-art.el (gnus-button-handle-info): New function.
+       (gnus-url-unhex-string): Replace "+" with " ".
+
+2001-08-17 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-check-news-header-syntax): Check bad From.
+
+2001-08-18 00:14:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-spec.el (gnus-correct-length): New function.
+       (gnus-correct-substring): New function.
+       (gnus-tilde-max-form): Use it.
+
+2001-08-17  Nevin Kapur  <nevin@jhu.edu>
+
+       * nnmh.el: Docstring changes as below.
+
+       * nnml.el: Docstring changes as below.
+
+       * nnbabyl.el: Docstring changes as below.
+
+       * nnmbox.el: Docstring changes as below.
+
+       * nnfolder.el: Added docstrings identifying each virtual server
+       parameter.
+
+2001-08-18  Simon Josefsson  <jas@extundo.com>
+
+       * mml.el (mml-menu): Collapse Attach, Insert and Security submenu.
+
+2001-08-17  Bj\e,Av\e(Brn Torkelsson  <torkel@acc.kth.se>
+
+       * message.el: rename "Abort Message" to "Postpone Message".
+       Remove "Attach file as MIME" from Message menu, it's already in
+       the MIME menu.
+
+2001-08-17 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * smime.el (smime-point-at-eol): eval-and-compile.
+       (smime-make-temp-file): New function.
+       (smime-sign-region, smime-encrypt-region, smime-decrypt-region):
+       Use it.
+
+2001-08-17 10:41:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-fetch-group): Go online if offline.
+       (gnus-agent-summary-fetch-group): New command and keystroke.
+
+       * gnus-art.el (gnus-insert-mime-button): Tiny clean-up.
+       (gnus-mime-display-security): Make it respect
+       gnus-unbuttonized-mime-type-p.
+
+       * gnus-sum.el (gnus-articles-to-read): Comments.
+       (gnus-article-marked-p): New function.
+       (gnus-summary-display-make-predicate): New function.
+       (gnus-select-newsgroup): Use them.
+
+       * mm-decode.el (mm-save-part-to-file): Made it not error.
+
+2001-08-17  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-wait-for-tag): If process-status isn't open or
+       run, return nil instead of sit-for looping.
+
+2001-08-17 10:41:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * lpath.el (featurep): fbind xml-parse-region.
+
+       * gnus.el (gnus-message-archive-method): Default to "archive".
+       (gnus-message-archive-method): Doc fix.
+       (gnus-parameters-get-parameter): Cleaned up.
+       (gnus-expand-group-parameter): New function.
+
+       * gnus-start.el (gnus-setup-news): Push the archive server only
+       the server list.
+
+       * mml.el (mml-menu): Changed name to "Attachments".
+
+       * mm-decode.el (mm-destroy-postponed-undisplay-list): Only message
+       when there is something to detroy.
+
+2001-05-21 17:11:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-server-browse-in-group-buffer): Default to
+       nil.
+
+2001-08-15  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-article): Allow "01:23" time spec,
+       which specifies a time today or tomorrow.
+
+2001-08-15  Simon Josefsson  <jas@extundo.com>
+       From Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk)
+
+       * gnus-agent.el (gnus-agent-make-mode-line-string)
+       (gnus-agent-toggle-plugged): Use new API.
+
+2001-08-14  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-send-drafts): Fix check whether
+       deadline has expired.
+
+2001-08-12  Simon Josefsson  <jas@extundo.com>
+       Suggested by Kai.Grossjohann@CS.Uni-Dortmund.DE
+
+       Support `recent' mark indicating newly arrived messages (to
+       separate from old but unread messages).
+
+       * nnimap.el (nnimap-retrieve-groups): Push dummy article into
+       `nnmail-split-history' if recent is > 0.
+       (nnimap-request-update-info-internal): Update `recent' marks.
+       (nnimap-request-set-mark): Never set `recent' marks.
+       (nnimap-mark-to-predicate-alist, nnimap-mark-to-flag-alist): Add
+       recent.
+
+       * gnus-sum.el (gnus-recent-mark): New mark.
+       (gnus-newsgroup-recent): New variable.
+       (gnus-summary-local-variables): Add gnus-newsgroup-recent.
+       (gnus-summary-prepare-threads): Mark recent articles.
+       (gnus-summary-add-mark): Support recent.
+       (gnus-summary-update-secondary-mark): Support recent.
+
+       * gnus.el (gnus-article-mark-lists): Add recent.
+
+2001-08-12  Simon Josefsson  <jas@extundo.com>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Returns
+       whether successful decoding took place.  Add doc.
+
+2001-08-12  Simon Josefsson  <jas@extundo.com>
+       Suggested by Per Abrahamsen <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-summary-line-format, gnus-parameters):
+       * gnus-gl.el (gnus-summary-grouplens-line-format):
+       * gnus-salt.el (gnus-summary-pick-line-format):
+       * gnus-spec.el (gnus-format-specs): %n is 23 chars.
+
+2001-08-11 09:40:00  Karl Kleinpaste  <karl@charcoal.com>
+       Committed by Kai Gro\e,b_\e(Bjohann.
+
+       * gnus-score.el (gnus-score-string): Fix `match' regexp
+       for `extra' header case.
+
+2001-08-10 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmbox.el (nnmbox-read-mbox): No warning.
+
+2001-08-10 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-article-type): Fix doc.
+       (nndoc-generate-article-function): New variable.
+       (nndoc-dissection-function): New variable.
+       (nndoc-type-alist): Add oe-dbx.
+       (nndoc-oe-dbx-type-p): New function.
+       (nndoc-oe-dbx-dissection): New function.
+       (nndoc-oe-dbx-generate-article): New function.
+
+2001-08-11  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-send-drafts): Cleaner way to check
+       whether deadline has been reached.  Patch from Dan Nicolaescu
+       <dann@godzilla.ics.uci.edu>.
+
+2001-08-10 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el (turn-on-gnus-mailing-list-mode): Use
+       gnus-group-find-parameter. Suggested by Janne Rinta-Manty
+       <rintaman@cs.Helsinki.FI>.
+
+       * mail-source.el (mail-source-movemail): The error buffer is
+       modified, but nothing in it.
+
+2001-08-10 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-bogus-system-names): New variable.
+       (message-make-fqdn): Use it.
+
+2001-08-09 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndraft.el (nndraft-request-group): Use
+       nndraft-auto-save-file-name.
+
+2001-08-09  Simon Josefsson  <jas@extundo.com>
+
+       * mm-view.el (mm-view-pkcs7-decrypt): Operate in current buffer.
+       Don't ask whether to decrypt.  Just leave result in buffer (don't
+       call mm).
+
+       * mm-decode.el (mm-dissect-buffer): Possibly verify/decrypt single
+       parts as well.
+       (mm-inline-media-tests): Ignore application/{x-,}pkcs7-mime.
+       (mm-possibly-verify-or-decrypt): Support application/{x-,}pkcs7-mime.
+
+2001-08-09  Simon Josefsson  <jas@extundo.com>
+
+       * mm-decode.el (mm-insert-part): Return decoding success status.
+       (mm-save-part-to-file): Error if decoding failed.
+
+2001-08-09 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-tab): Use indent-relative.
+       (message-mode): Don't bind indent-line-function to indent-relative.
+
+2001-08-09  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-get-reply-headers): Fix string. Suggested by
+       Christoph Conrad <cc@cli.de>.
+
+2001-08-08 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-tab): Use the current value of
+       indent-line-function.
+       (message-mode): Bind indent-line-function to indent-relative.
+
+2001-08-08  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-gssapi-auth-p, imap-kerberos4-auth-p): Also check
+       whether `imtest' is installed.
+
+2001-08-04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Trivial patch from Nuutti Kotivuori  <nuutti.kotivuori@smarttrust.com>
+
+       * gnus-sum.el (gnus-summary-show-article): Call
+       gnus-summary-update-secondary-secondary-mark.
+       * gnus-sum.el (gnus-summary-edit-article-done): Ditto.
+       * gnus-sum.el (gnus-summary-reparent-thread): Ditto.
+
+2001-08-07 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Misc -> Gnus.
+
+       * gnus-group.el (gnus-group-make-menu-bar): Ditto.
+
+       * mm-uu.el (mm-uu-dissect): Autoload. From Gerd M\e,Av\e(Bllmann
+       <gerd@gnu.org>.
+
+       * gnus-art.el (gnus-output-to-file): Bind file-name-coding-system.
+
+       * gnus-util.el (gnus-output-to-rmail): Ditto.
+       (gnus-output-to-mail): Ditto.
+
+       * nnmail.el (nnmail-pathname-coding-system): Set default to nil.
+
+2001-08-06  Florian Weimer  <fw@deneb.enyo.de>
+
+       * message.el (message-indent-citation): Use
+       `message-yank-cited-prefix' for empty lines.
+
+2001-08-05  Florian Weimer  <fw@deneb.enyo.de>
+
+       * message.el (message-indent-citation): Quote only lines starting
+       with ">" using `message-yank-cited-prefix'.
+
+2001-08-05  Nuutti Kotivuori  <nuutti.kotivuori@smarttrust.com>
+       Trivial patch.
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Use
+       gnus-cache-fully-p.
+
+2001-08-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-cache-possibly-update-active): Create active
+       file if it doesn't exist (by calling gnus-cache-read-active).
+
+2001-08-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Revert.
+       (gnus-cache-passively-or-fully-p): Removed.
+       (gnus-cache-fully-p): Fix it.
+
+       * mm-view.el (mm-pkcs7-signed-magic): Support more ASN.1 lengths.
+
+2001-08-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-cache-fully-p)
+       (gnus-cache-passively-or-fully-p): New functions.
+       (gnus-cache-possibly-enter-article): Cosmetic change, use
+       `g-c-p-o-f-p'.
+       (gnus-cache-possibly-enter-article): Use `g-c-p-u-a'; last change
+       was bogus (`g-c-p-a-a' does not change active info, just change
+       the functions parameters).
+       (gnus-cache-possibly-remove-articles-1): Make sure articles are
+       not removed in groups that match `gnus-uncacheable-groups'.
+
+       Reported and modifications based on discussions with Nuutti
+       Kotivuori <nuutti.kotivuori@smarttrust.com>.
+
+2001-08-04  Simon Josefsson  <jas@extundo.com>
+       Trivial patch from Nuutti Kotivuori  <nuutti.kotivuori@smarttrust.com>
+
+       * gnus-cache.el (gnus-cache-possibly-update-active): New function;
+       calls `gnus-cache-update-active' if bounds has been extended.
+
+2001-08-04 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-security-verify-or-decrypt): Insert
+       before remove.
+       (gnus-mime-security-show-details): Ditto.
+
+2001-08-04  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-split-fancy-with-parent): Correct `mapconcat'
+       syntax.  Protect string-match against nil string and regexp.
+
+2001-08-03 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-charset-region): Remove control-1.
+
+2001-08-03 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-readable-p): Emacs 20 takes one argument.
+
+2001-08-04  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-sign-region, smime-encrypt-region): Fix details
+       buffer.  Delete MIME-Version header.
+
+2001-08-03  Simon Josefsson  <jas@extundo.com>
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): The article
+       that is entered does not necessarily have the highest article
+       number in the group, so use `gnus-cache-possibly-alter-active'
+       instead of `gnus-cache-update-active'.
+
+2001-08-03 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-gpg-extract-signature-details): Don't barf.
+
+2001-08-03  Simon Josefsson  <jas@extundo.com>
+
+       * mml.el (mml-menu): Rename from MML to Mime. Collapse Security
+       menu.
+
+2001-08-02  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (post-method): New group parameter.  It also provides
+       the user option `gnus-post-method-alist' and the internal function
+       `gnus-parameter-post-method'.
+
+       * gnus-msg.el (gnus-post-method): Bind the value of
+       `gnus-post-method' to the group parameter if it is defined.
+
+2001-08-02  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-extra-arguments): Removed.
+       (smime-call-openssl-region): Don't use it.
+
+2001-08-02  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-sign-region): Handle stderr.
+       (smime-encrypt-region): Ditto.
+
+       * mm-view.el (mm-pkcs7-signed-magic): Make it a regexp.  Don't
+       match the ASN.1 length bytes.
+       (mm-pkcs7-enveloped-magic): Ditto.
+       (mm-view-pkcs7-get-type): Don't regexp quote.
+
+2001-08-01 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Andreas Fuchs <asf@void.at>
+
+       * mml2015.el (mml2015-trust-boundaries-alist): Typo.
+
+2001-08-01 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-header-button-alist): References regexp.
+
+2001-08-01  Gerd Moellmann  <gerd@gnu.org>
+
+       * mm-view.el (autoload): Don't autoload `diff-mode' if it's
+       already fboundp.  Add INTERACTIVE arg to autoload form.
+
+2001-08-01 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-init): Add as gnus buffer.
+
+       * nnmail.el (nnmail-cache-open): Ditto.
+
+2001-07-31 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-button-fetch-group): Fix the regexp.
+
+2001-07-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-msg.el (gnus-post-method): Refer to `gnus-parameters'.
+
+2001-07-31 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Originally from Pavel Jan\e,Am\e(Bk <Pavel@Janik.cz>
+
+       * gnus-agent.el (gnus-agent-make-mode-line-string): New function.
+       (gnus-agent-toggle-plugged): Use it.
+
+2001-07-31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-startup-file-coding-system): Revert to binary.
+       (gnus-ding-file-coding-system): New variable.
+       (gnus-read-newsrc-el-file, gnus-save-newsrc-file)
+       (gnus-slave-save-newsrc): Use it.
+
+2001-07-31  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-initialize): Use standard define-key
+       syntax.
+
+2001-07-30 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Originally from Andreas Fuchs <asf@void.at>
+
+       * mml2015.el (mml2015-trust-boundaries-alist): New variable.
+       (mml2015-gpg-pretty-print-fpr): New function.
+       (mml2015-gpg-extract-signature-details): More details, rename from
+       `m-g-e-from'.
+       (mml2015-gpg-verify): Use them.
+       (mml2015-gpg-clear-verify): Use them.
+
+2001-07-31  Simon Josefsson  <jas@extundo.com>
+
+       * mml-smime.el (mml-smime-sign, mml-smime-encrypt): Goto end of
+       buffer when done.
+
+2001-07-30  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-call-openssl-region): Revert previous change,
+       just pass on buf to `call-process-region'.
+       (smime-verify-region): Doc fix.  Don't message stuff.  Use
+       `smime-new-details-buffer'.  Inserts error messages into buffer.
+       (smime-noverify-region): Ditto.
+       (smime-decrypt-region): Ditto.  Handles stderr separately.
+       (smime-verify-buffer, smime-noverify-buffer)
+       (smime-decrypt-buffer): Doc fix.
+       (smime-new-details-buffer): New function.
+       (smime-pkcs7-region, smime-pkcs7-certificates-region)
+       (smime-pkcs7-email-region): Use `smime-new-details-buffer'.
+       (smime-sign-region, smime-encrypt-region): Don't use
+       `insert-buffer'.
+
+       * mml-smime.el (mml-smime-verify): Fix security button strings.
+
+2001-07-30 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-save-part-and-strip): Save
+       gnus-article-mime-handles.
+
+2001-07-29  Simon Josefsson  <jas@extundo.com>
+
+       * mail-source.el (top-level): Require message for message-directory.
+       (mail-source-directory): Change default to message-directory.
+
+       * smime.el (smime-keys, smime-CA-directory, smime-CA-file)
+       (smime-certificate-directory, smime-openssl-program)
+       (smime-encrypt-cipher, smime-dns-server): Fix doc (leading "*").
+       (smime-extra-arguments): New variable.
+       (smime-dns-server): Fix customize group.
+       (smime-call-openssl-region): Use `smime-extra-arguments'.
+
+2001-07-29  Simon Josefsson  <jas@extundo.com>
+       From Vladimir Volovich <vvv@vsu.ru>
+
+       * smime.el (smime-call-openssl-region): Ignore stderr.
+
+2001-07-29  Simon Josefsson  <jas@extundo.com>
+       From Christoph Conrad <christoph.conrad@gmx.de>
+
+       * gnus-agent.el (gnus-agent-save-group-info): Don't destroy active
+       file.
+
+2001-07-29  Simon Josefsson  <jas@extundo.com>
+
+       * mm-view.el (mm-view-pkcs7-decrypt): Adhere to `mm-decrypt-option'.
+
+       Support S/MIME decryption.
+
+       * mm-decode.el (mm-inline-media-tests):
+       (mm-inlined-types):
+       (mm-automatic-display):
+       (mm-attachment-override-types): Add application/{x-,}pkcs7-mime.
+
+       * mm-view.el (mm-pkcs7-signed-magic):
+       (mm-pkcs7-enveloped-magic): New variables.
+       (mm-view-pkcs7-get-type): New function; identify PKCS#7 type.
+       (mm-view-pkcs7): New function; mm viewer for PKCS#7 blobs.
+       (mm-view-pkcs7-decrypt): New function; mm viewer for encrypted
+       PKCS#7 blobs.
+
+       * smime.el (smime-decrypt-region): Expand keyfile.
+
+2001-07-29  Simon Josefsson  <jas@extundo.com>
+
+       * nntp.el (nntp-open-ssl-stream): Don't mess with internal
+       `ssl.el' variables.
+
+       * gnus-agent.el (gnus-agent-save-group-info): Delete everything
+       but line instead of narrowing to it, because `nnmail-parse-active'
+       calls widen.  Thanks to Christoph Conrad
+       <christoph.conrad@gmx.de>.
+
+2001-07-29  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.el (gnus-summary-line-format): Mention `gnus-sum-thread-*'
+       for %B spec.
+
+       * gnus-sum.el (gnus-summary-prepare-threads): If
+       gnus-sum-thread-tree-root is nil, use subject instead.
+       (gnus-sum-thread-tree-root, gnus-sum-thread-tree-single-indent)
+       (gnus-sum-thread-tree-vertical, gnus-sum-thread-tree-indent)
+       (gnus-sum-thread-tree-leaf-with-other)
+       (gnus-sum-thread-tree-single-leaf): Documentation.
+       (gnus-sum-thread-tree-single-indent): Allow nil.
+
+2001-07-28 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-fill-paragraph): Do nothing if the user
+       wants filladapt-mode.
+
+2001-07-27 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-image-type-from-buffer): New function.
+       (mm-get-image): Use it.
+
+2001-07-27 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-large-newsgroup): Add doc, "If it is nil, ..."
+
+       * gnus-art.el (gnus-mime-view-all-parts): buffer-read-only covers
+       mm-display-parts too.
+
+2001-07-27 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-accept-article): Bind
+       nntp-server-buffer.
+
+       * nnmail.el (nnmail-parse-active): Read from buffer instead of
+       nntp-server-buffer.
+
+2001-07-27 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-check-news-header-syntax): Use
+       message-post-method.
+       (message-send-news): Bind message-post-method.
+
+2001-07-27 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-tweak-type-alist): New variable.
+       (mml-tweak-function-alist): New variable.
+       (mml-tweak-part): New function.
+       (mml-generate-mime-1): Use it.
+
+2001-07-26 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-accept-article): Replace
+       nnfolder-request-list.
+
+2001-07-27  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-open-server): Set nnimap-server-buffer if
+       nnoo-change-server failed to do it.
+
+2001-07-26 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-parameters): Make it customizable.
+
+2001-07-26 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mm-display-part): Narrow to point if eobp.
+
+       * message.el (message-set-auto-save-file-name): More
+       poor-system-types.
+
+       * mailcap.el (mailcap-parse-mimetypes): poor-system-types.
+
+       * gnus-ems.el (nnheader-file-name-translation-alist): M$Windows-NT
+       supports +.
+
+2001-07-26 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-readable-p): New function.
+       (mm-inline-media-tests): Fix the default testers.
+
+2001-07-26  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-version): Bump version number.
+
+2001-07-26 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Steven E. Harris <seh@speakeasy.org>
+
+       * nnheader.el (nnheader-translate-file-chars): cygwin32 is running
+       in M$Windows too.
+
+2001-07-26  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-send-drafts): Don't `error'.
+
+2001-07-25 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-bcklg.el (gnus-backlog-shutdown): Make interactive.
+
+       * mm-decode.el (mm-get-image): Guess then use the type.
+
+       * gnus-art.el (gnus-mime-view-part-as-type): Don't copy cache.
+
+2001-07-25 12:54:00  Danny Siu  <dsiu@adobe.com>
+
+       * gnus-sum.el (gnus-summary-prepare-threads): Shouldn't do tree
+       display (%B) for threads if threading is off.
+
+2001-07-25 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Henrik Enberg <henrik@enberg.org>
+
+       * gnus-msg.el: Customization patch.
+
+2001-07-25 22:22:22  Raymond Scholz  <rscholz@zonix.de>
+
+       * nnmail.el (nnmail-split-fancy-with-parent-ignore-groups): New
+       variable.
+       (nnmail-split-fancy-with-parent): Ignore certain groups.
+
+2001-07-25 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-byte-compile): New function.
+       (gnus-use-byte-compile): New variable.
+       (gnus-make-sort-function): Use it.
+
+       * nnmail.el (nnmail-get-new-mail): Use it.
+
+       * gnus-agent.el (gnus-category-make-function): Simple function or
+       compiled function.
+       (gnus-agent-fetch-group-1): Don't use (caaddr predicate).
+
+       * gnus-gl.el (bbb-build-rate-command): Remove quote before lambda.
+       * gnus-topic.el (gnus-topic-sort-topics-1): Ditto.
+       (gnus-topic-sort-topics-1): Use gnus-byte-compile.
+
+       * message.el (message-check-news-header-syntax): Remove quote.
+
+2001-07-24 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-use-mail-followup-to): `t' is not a
+       documented value.
+
+2001-07-24 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-display-arrow): Test fboundp.
+
+2001-07-24 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-encode.el (mm-encode-buffer): Don't use 7bit encoding if
+       there are long lines.
+
+2001-07-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (copy-list): New compiler macro.
+
+2001-07-24 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-bounce): If no Return-Path, the whole
+       content is considered as the original message.
+
+       * nnml.el (nnml-check-directory-twice): New variable.
+       (nnml-article-to-file): Use it.
+       (nnml-retrieve-headers): Hack it.
+
+2001-07-24 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-buffer-configuration): New configure.
+
+       * gnus-art.el (gnus-mm-display-part): Don't select-window if it is
+       not alive.
+
+       * mm-decode.el (mm-remove-part): Don't murder the current window (nil).
+       (mm-display-external): Use display-term configure.
+
+2001-07-24  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-default-hour): New variable.
+       (gnus-delay-article): Allow specific date in YYYY-MM-DD format.
+
+2001-07-23 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Karl Kleinpaste <karl@charcoal.com>
+
+       * gnus-sum.el (gnus-summary-line-format-alist): Add %B.
+       (gnus-summary-prepare-threads): Ditto.
+
+       * gnus.el (gnus-summary-line-format): Add %B.
+
+2001-07-23 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-articles-to-read): Use gnus-group-decoded-name.
+
+       * mm-util.el (mm-string-as-multibyte): New function.
+
+       * nnmh.el (nnmh-request-list-1): Encode, not decode!
+
+2001-07-23 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-universal-coding-system): New variable.
+
+       * gnus-start.el (gnus-startup-file-coding-system): Use it.
+
+       * score-mode.el (score-mode-coding-system): Use it.
+
+2001-07-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-setup-news): Call
+       `gnus-check-bogus-newsgroups' just after the native server is
+       opened.
+
+2001-07-23  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-do-request-post): Util function to be used by
+       `nnchoke-request-post' for all nnmail-derived backends.
+
+       * nnml.el (nnml-request-post): Use it.
+
+       * gnus.el (gnus-valid-select-methods): nnml is a post-mail
+       backend, for it groks nnml-request-post.
+
+       * gnus-group.el (gnus-group-highlight, gnus-group-highlight-line):
+       Treat `mail-post' backends like `mail' backends, not like `news'
+       backends.
+
+2001-07-22 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-setup-message): make-local-hook.
+
+2001-07-22  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el (gnus-delay-article): Fix `read-string' for
+       XEmacs.  Allow more units.  Submitted by Karl Kleinpaste
+       <karl@charcoal.com>, slightly changed by Kai.
+
+       * message.el (message-check-news-header-syntax): When checking
+       whether the groups exist, check the right server based on
+       `gnus-post-method'.
+
+2001-07-21  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-delay.el: New file.
+
+2001-07-21 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-read-coding-system): Take two arguments.
+
+       * gnus-sum.el (gnus-summary-show-article): Use
+       mm-read-coding-system.
+
+       * gnus-art.el (article-de-quoted-unreadable):
+       (article-de-base64-unreadable, article-wash-html):
+       (gnus-mime-inline-part, gnus-mime-view-part-as-charset): Ditto.
+
+2001-07-21  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnml.el (nnml-request-post): New function.  Can be used for
+       annotations in nnml groups.
+
+2001-07-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-request-newgroups): Use UTC date for NEWGROUPS
+       command.
+
+       * gnus-start.el (gnus-find-new-newsgroups): Use
+       `message-make-date' instead of `current-time-string'.
+       (gnus-ask-server-for-new-groups): Ditto.
+       (gnus-check-first-time-used): Ditto.
+
+2001-07-20 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-home-score-file): nnheader-translate-file-chars.
+
+2001-07-18  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-shorten-references): Change `maxcount' and
+       `cut' to obey USEFOR draft 5.
+
+2001-07-12  Colin Walters  <walters@cis.ohio-state.edu>
+
+       * gnus-sum.el (gnus-summary-display-arrow): New variable.
+       (gnus-summary-set-article-display-arrow): New function.
+       (gnus-summary-goto-subject): Use it.
+
+2001-07-18 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-import-article): Insert date if
+       doesn't exist.
+
+2001-07-18 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-content-type-parameters): New variable.
+       (mml-content-disposition-parameters): New variable.
+       (mml-insert-mime-headers): Use them.
+       (mml-parse-1): Accept charset.
+
+2001-07-17 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-select-group): Doc fix.
+
+       * gnus-eform.el (gnus-edit-form-done): Return nil if end-of-file.
+
+2001-07-17  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (dgnushack-make-auto-load): Advise `make-autoload'
+       to handle `define-derived-mode'.
+
+2001-07-16 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From:  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * message.el (message-mode): Use define-derived-mode.
+       (message-tab): message-completion-alist.
+
+       * imap.el (imap-interactive-login): Use make-local-variable.
+       (imap-open): Ditto.
+       (imap-authenticate): Ditto.
+
+       * gnus-msg.el (gnus-setup-message): Change-major-mode-hook.
+
+       * gnus-art.el (gnus-article-edit-mode): Use define-derived-mode.
+
+2001-07-16  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-citation-line-function): Refer to
+       gnus-cite-attribution-suffix.
+
+2001-07-15  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * gnus-art.el,...: Error convention changes.
+
+2001-07-13 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-rebuild-thread): Count hidden lines too.
+
+2001-07-13 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-read-group-data): Nuke emacs-lisp-mode-hook.
+       (nnrss-read-server-data): Ditto.
+
+2001-07-13 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-setup.el (gnus-use-installed-gnus): Typo.
+       * Cleanup files.
+       From Pavel@Janik.cz (Pavel Jan\e,Am\e(Bk).
+
+2001-07-13 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-summary-line-format): Add %o.
+
+       * gnus-sum.el (gnus-summary-pipe-output): Don't configure as pipe
+       unless shell outputs something.
+
+2001-07-13 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-boring-article-headers): Better doc.
+       (article-hide-headers): Better regexp.
+       Suggested by Matt Swift <swift@alum.mit.edu>.
+
+       * nnheader.el (nnheader-max-head-length): Better doc.
+       (nnheader-header-value): Skip spaces.
+       (nnheader-parse-head): Remove space.
+       Suggested by Matt Swift <swift@alum.mit.edu>.
+
+       * gnus-sum.el (gnus-summary-show-raw-article): New function.
+       (gnus-get-newsgroup-headers): Remove space.
+
+2001-07-12 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-msg-treat-broken-reply-to): Add force.
+       (gnus-summary-reply): Use it.
+       (gnus-summary-reply-broken-reply-to): New function.
+       (gnus-msg-force-broken-reply-to): New function.
+
+       * mm-view.el (mm-inline-text): Showing as text/plain when error.
+
+2001-07-12 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-setup): Restore gnus-newsgroup-name.
+
+2001-07-12 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-external-terminal-program): New variable.
+       (mm-display-external): Use it. Use term to display when no
+       window-system.
+
+2001-07-12  Bj\e,Av\e(Brn Torkelsson  <torkel@hpc2n.umu.se>
+
+       * gnus-srvr.el (gnus-browse-make-menu-bar): Changed one of the
+       Browse->Next entries to Browse->Prev
+
+2001-07-11 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-do-gcc): Don't test gnus-alive-p.
+
+2001-07-11 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Use base64
+       for the default encoding.
+
+       * nnrss.el (nnrss-url-field): New field.
+       (nnrss-request-article): Add newsgroups.
+
+       * nnfolder.el (nnfolder-read-folder): Force to use a multibyte buffer.
+
+2001-07-11 04:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndraft.el (nndraft-request-restore-buffer): Don't remove Date.
+
+       * gnus-draft.el (gnus-draft-edit-message): Remove Date here.
+       (gnus-draft-setup): Remove backlog.
+
+2001-07-10  Pavel Jan\e,Am\e(Bk  <Pavel@Janik.cz>
+
+       * gnus-logic.el, gnus-srvr.el, gnus-vm.el, nnheaderxm.el, nnoo.el:
+       Cleanup.
+
+2001-07-09 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-bug): Erase buffer.
+
+       * nnfolder.el (nnfolder-possibly-change-group): Don't create group.
+
+2001-07-09 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-attachment-override-p): Fix typo.
+
+2001-03-19 05:28:00  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-kill.el (gnus-execute): Work with the extra headers.
+       * gnus-sum.el (gnus-summary-execute-command): Ditto.
+
+2001-07-09 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): w3-coding-system-for-mime-charset
+       may not defined. From: Raja R Harinath <harinath@cs.umn.edu>.
+
+       * message.el (message-send-mail-real-function): New variable.
+       (message-send-mail-partially, message-send-mail):
+
+       * nngateway.el (nngateway-request-post): Use it.
+
+       * gnus-agent.el (gnus-agentize): Use it.
+
+       * nnsoup.el (nnsoup-old-functions, nnsoup-set-variables)
+       (nnsoup-revert-variables): Use it.
+
+2001-07-09  Colin Walters  <walters@cis.ohio-state.edu>
+
+       * mm-decode.el (mm-inline-media-tests): Default to displaying as
+       text/plain if the type doesn't match any other media types.
+       (mm-inlined-types): Doc fix.
+       (mm-display-inline): Revert previous change (now handled by a
+       default type in `mm-inline-media-tests'.
+       (mm-inlinable-p): Revive.
+       (mm-display-part): Call `mm-inlinable-p'.
+       (mm-attachment-override-p): Ditto.
+       (mm-inlined-p): Doc fix.
+
+       * gnus-art.el (gnus-mime-display-single): Call `mm-inlinable-p' as
+       well as `mm-inlined-p'.
+
+2001-07-09 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-send-command, nntp-send-command-nodelete):
+       (nntp-send-command-and-decode): Use gnus-point-at-bol.
+
+2001-07-09 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From  Paul Jarc <prj@po.cwru.edu>
+
+       * message.el (message-use-mail-followup-to): New variable.
+       (message-get-reply-headers): Use it.
+
+2001-07-04  Gerd Moellmann  <gerd@gnu.org>
+
+       * nnheader.el (nnheader-init-server-buffer): Make sure the
+       *nntpd* buffer is made multibyte instead of a random buffer.
+
+2001-07-09 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-get-newsgroup-headers-xover): Get headers only
+       when it returns headers.
+
+2001-07-07  Simon Josefsson  <jas@extundo.com>
+
+       * rfc2047.el (rfc2047-encode-message-header): Skip header when
+       trying to fold. Thanks to Colin Walters
+       <walters@cis.ohio-state.edu>
+
+2001-07-06  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-parse-address-list, imap-parse-flag-list)
+       (imap-parse-body-extension, imap-parse-body-ext, imap-parse-body):
+       Add information in `assert's.
+
+       * nnimap.el (nnimap-possibly-change-group): Ignore uidvalidity
+       changes. (From nnimaps' point of view, `nnimap-verify-uidvalidity'
+       and `nnimap-group-overview-filename', should handle all
+       change-of-uidvalidity related issues.  But there may be other
+       problems.)
+
+2001-07-05  Colin Walters  <walters@cis.ohio-state.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Don't include the
+       header name when folding.
+
+2001-07-05  Colin Walters  <walters@cis.ohio-state.edu>
+
+       * mm-decode.el (mm-inlined-types): Document relationship with
+       `mm-inline-media-tests'.
+       (mm-display-inline): Default to displaying as plain text if no
+       inlining handler is available.
+       (mm-inlinable-p): Remove.
+       (mm-inlined-p): Don't call `mm-inlinable-p'.
+       (mm-automatic-display-p): Ditto.
+       (mm-attachment-override-p): Ditto.
+
+2001-07-04  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-importantize-dormant): New variable.
+       (nnimap-request-update-info-internal): Use it.
+       (nnimap-request-set-mark): Ditto.
+
+2001-07-04  Didier Verna  <didier@lrde.epita.fr>
+
+       * nntp.el (nntp-send-command): don't pass a buffer argument to
+       `point'. Only XEmacs accepts this.
+       * nntp.el (nntp-send-command-nodelete): ditto.
+       * nntp.el (nntp-send-command-and-decode): ditto.
+
+2001-07-04  Didier Verna  <didier@lrde.epita.fr>
+
+       * nntp.el (nntp-open-connection-function): doc update.
+       * nntp.el (nntp-pre-command): New.
+       * nntp.el (nntp-via-rlogin-command): New.
+       * nntp.el (nntp-via-telnet-command): New.
+       * nntp.el (nntp-via-telnet-switches): New.
+       * nntp.el (nntp-via-user-name): New.
+       * nntp.el (nntp-via-user-password): New.
+       * nntp.el (nntp-via-address): New.
+       * nntp.el (nntp-via-envuser): New.
+       * nntp.el (nntp-via-shell-prompt): New.
+       * nntp.el (nntp-open-telnet-stream): New.
+       * nntp.el (nntp-open-via-rlogin-and-telnet): New.
+       * nntp.el (nntp-open-via-telnet-and-telnet): New.
+       * nntp.el (nntp-wait-for): check for possibly echo'ed commands.
+       * nntp.el (nntp-send-command): ditto.
+       * nntp.el (nntp-send-command-nodelete): ditto.
+       * nntp.el (nntp-send-command-and-decode): ditto.
+
+2001-06-30  YAGI Tatsuya  <yagi@is.titech.ac.jp>
+       Trivial patch.
+
+       * gnus-start.el (gnus-check-first-time-used): Use `if' instead of
+       `when'.
+
+2001-07-03  Simon Josefsson  <jas@extundo.com>
+       From Nuutti Kotivuori <nuutti.kotivuori@smarttrust.com>
+
+       * flow-fill.el (fill-flowed): Use (1+ (point-at-eol)) instead.
+
+2001-07-03  Simon Josefsson  <jas@extundo.com>
+
+       * flow-fill.el (fill-flowed): If `fill-region' inserts empty line,
+       remove it (workaround XEmacs `fill-region' bug).
+
+2001-07-01  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-date-days-ago): Defeat locale.
+
+2001-06-28 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-format-error): New function.
+       (mml2015-mailcrypt-decrypt, mml2015-mailcrypt-clear-decrypt)
+       (mml2015-mailcrypt-verify, mml2015-gpg-clear-verify)
+       (mml2015-mailcrypt-clear-verify, mml2015-gpg-verify): Use it.
+
+2001-06-26 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-retrieve-headers): The description may not exist.
+       Suggested by Christoph Conrad <C.Conrad@cli.de>.
+
+       * gnus-sum.el (gnus-summary-set-local-parameters): Don't override
+       group variables.
+
+2001-06-25 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-write-groups): Use gnus-prin1.
+
+       * nnrss.el (nnrss-save-server-data): Bind print-level and print-length.
+       (nnrss-save-group-data): Ditto.
+
+       * gnus-agent.el (gnus-agent-save-alist): Ditto.
+
+2001-06-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-do-send-housekeeping): Narrow to headers.
+
+2001-06-24  Simon Josefsson  <jas@extundo.com>
+
+       * rfc2047.el (rfc2047-fold-region): The check to skip WSP
+       insertion when breaking lines looked for " \t" instead of "[ \t]".
+       (rfc2047-encode-message-header): Fold lines even if
+       no QP encoding is done.
+
+2001-06-23  Simon Josefsson  <jas@extundo.com>
+       From Samuel Tardieu <sam@inf.enst.fr>
+
+       * smime.el (smime-keys): Support additional certificates.
+       (smime-make-certfiles): New function.
+       (smime-sign-region): Use previous variables.
+       (smime-get-certfiles): New function.
+       (smime-sign-buffer): Use it.
+       (smime-verify-region): Support both CAfile and CApath.
+
+2001-06-23  Simon Josefsson  <jas@extundo.com>
+
+       * smime.el (smime-decrypt-region): Perhaps work.
+
+2001-06-22 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-copy-article-buffer): Typo.
+
+2001-04-06  Ralph Schleicher  <rs@nunatak.allgaeu.org>
+
+       * mm-decode.el (mm-save-part): Rewrite file name.
+       (mm-file-name-rewrite-functions): New variable.
+       (mm-file-name-delete-whitespace): New function.
+       (mm-file-name-trim-whitespace): New function.
+       (mm-file-name-collapse-whitespace): New function.
+       (mm-file-name-replace-whitespace): New variable and function.
+
+2001-06-22  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-make-date): Workaround locale for weekdays.
+
+2001-06-21 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-goto-body): Return nil if not found. (revert!)
+
+2001-06-21 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Fremlin <chief@bandits.org>
+
+       * message.el (message-goto-body): Some messages have no header.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Use it.
+
+2001-06-21  Ralph Schleicher  <rs@nunatak.allgaeu.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Date fix.
+
+2001-06-21 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-make-date): Add week day.
+       Suggested by Jason R. Mastaler <jason@mastaler.com>.
+
+2001-06-19  Simon Josefsson  <jas@extundo.com>
+
+       * message.el (message-yank-prefix): Doc fix.
+       (message-yank-cited-prefix): Ditto.
+       (message-delete-not-region): Keep citation prefix on first line,
+       if possible and appropriate.
+
+2001-06-19  Simon Josefsson  <jas@extundo.com>
+
+       * imap.el (imap-process-connection-type): New variable.
+       (imap-kerberos4-open, imap-gssapi-open): Use it.  This makes
+       recent `imtest's work completely (no line length issues), while
+       making making old `imtest's unusable.  Thanks to NAGY Andras
+       <nagya@inf.elte.hu> for his work.
+
+2000-12-30  NAGY Andras  <nagya@inf.elte.hu>
+
+       * imap.el (imap-ssl-program): Add -quiet to shut up
+       OpenSSL/SSLeay's internal debug talk.
+
+2001-06-19  Matt Armstrong  <matt@lickey.com>
+
+       * imap.el (imap-parse-flag-list): Workaround bug in Courier IMAP
+       server.
+
+2001-06-19 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-article-buffer): New variable.
+       (nnmail-split-incoming): Use it.
+
+2001-06-15  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * qp.el (quoted-printable-decode-region): If called interactively,
+       use coding-system-for-read.
+
+2001-06-16 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-check-news-header-syntax): Check Reply-To.
+
+2001-06-16 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-parse-1): Use message options.
+
+       * message.el (message-do-fcc): Don't do anything if there is no
+       FCC.
+
+2001-06-16  Simon Josefsson  <jas@extundo.com>
+
+       * nnimap.el (nnimap-split-articles): Support 'junk to-groups.
+       (nnimap-expunge-search-string): New variable.
+       (nnimap-request-expire-articles): Use it.
+
+2001-06-15 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-with-qmail): wrong exit status is
+       100 not 1. Reported by Paul Jarc <prj@po.cwru.edu>.
+
+2001-06-15 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-strip-multiple-blank-lines): Use
+       delete-region instead of replace-match.
+
+2001-06-14 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-google-parse-1): Fix Google content regexp.
+       (nnweb-google-wash-article): Ditto.
+
+2001-06-14 Ferenc Wagner  <wferi@bolyai1.elte.hu>
+
+       * nnweb.el (nnweb-google-parse-1): Fix Google url regexp.
+
+2001-06-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.el (gnus-define-group-parameter): Don't quote the defcustom
+       specs.
+
+2001-06-13 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-email-address): Move it here.
+
+       * gnus-art.el (article-de-quoted-unreadable): Read charset if
+       requested.
+       (article-de-base64-unreadable): Ditto.
+       (article-wash-html): Ditto.
+
+2001-06-12 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-options-set-recipient): Don't add ", "
+       unless necessary. Suggested by Josh Huber <huber@alum.wpi.edu>.
+
+2001-06-12 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-group-alist): Use |fr| instead of [fr].
+
+2001-06-12 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-plain-save-name): Use file-relative-name.
+       From Marc Lefranc <Marc.Lefranc@univ-lille1.fr>.
+
+       * nnrss.el (nnrss-node-text): Node might be nil.
+
+2001-06-11 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-uu.el (gnus-uu-save-article): Use mml tag instead of
+       part. From Katsumi Yamaoka <yamaoka@jpl.org>.
+
+       * nnrss.el (nnrss-group-alist): More items.
+
+2001-06-09 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-node-text): Use cddr instead xml-node-children.
+
+2001-06-03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Trivial patch from Dale Hagglund  <rdh@best.com>
+
+       * gnus-mlspl.el (gnus-group-split-fancy): Fix generation of split
+       restrict clauses.
+
+2001-06-07 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       From Benjamin Rutt <brutt+news@bloomington.in.us>
+
+       * message.el (message-wide-reply-confirm-recipients): New variable.
+
+2001-06-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Trivial patch from Mark Thomas  <mthomas@edrc.cmu.edu>
+
+       * nnmail.el (nnmail-fix-eudora-headers): Change the In-Reply-To
+       fix so it works with XEmacs.
+
+2001-06-07 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-retrieve-headers): Support description as extra
+       headers.
+
+2001-06-07 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el: Fix a few bugs.
+
+2001-06-05  Simon Josefsson  <jas@extundo.com>
+
+       * mm-decode.el (mm-handle-set-external-undisplayer): Don't
+       generate compiler warnings.  From Alex Schroeder <alex@gnu.org>.
+
+2001-06-04  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * mm-decode.el (mm-pipe-part): Bind coding-system-for-write to
+       binary so that we don't transmit ISO 2022 garbage to the process.
+       This is needed under XEmacs.
+
+2001-06-03  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-ssl-open): Require ssl. (Otherwise ssl.el is
+       autoloaded incorrectly below because ssl-program-* is bound.)
+       Thanks to Amos Gouaux for report.
+
+2001-06-02  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-kerberos4-open):
+       (imap-gssapi-open):
+       (imap-ssl-open):
+       (imap-network-open):
+       (imap-shell-open):
+       (imap-starttls-open): Set buffer to workaround spurious
+       `accept-process-output' buffer changes.  Thanks to Mats Lidell
+       <Mats.Lidell@contactor.se> for report and partial patch and Jake
+       Colman <colman@ppllc.com> for report.
+
+2001-05-31 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-catchup): New argument.
+       (gnus-summary-catchup-from-here): New function.
+
+2001-05-30  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * mm-view.el (mm-inline-image-xemacs): Insert newline, then move
+       back, then insert glyph.  (Before, the glyph was inserted first,
+       then the newline.)  This works around a behavior in XEmacs where
+       it is not possible to insert a character after a glyph which is at
+       the end of a buffer.  Patch by Lloyd Zusman <ljz@asfast.com>.
+
+2001-05-28  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       From Jaap-Henk Hoepman (jhh@xs4all.nl).
+
+       * mm-decode.el (mm-keep-viewer-alive-types): New variable.
+       (mm-keep-viewer-alive-p, mm-handle-set-external-undisplayer,
+       mm-destroy-postponed-undisplay-list): New functions.
+       (mm-display-external): Use them.
+
+2001-05-27  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-salt.el (gnus-tree-highlight-node): Bind `default-high' and
+       `default-low' when evaluating `gnus-summary-highlight'.
+       From Raja R Harinath <harinath@cs.umn.edu>.
+
+2001-05-27  Simon Josefsson  <simon@josefsson.org>
+
+       * message.el (message-yank-cited-prefix): New variable.
+       (message-indent-citation): Use it.
+
+       * mml2015.el (mml2015-mailcrypt-verify): Store gpg stderr output
+       as details.
+       (mml2015-mailcrypt-clear-verify): Ditto.
+
+2001-05-24  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+       From Nevin Kapur <nevin@jhu.edu>.
+
+       * gnus-sum.el (gnus-summary-default-high-score,
+       gnus-summary-default-low-score): New variables.
+       (gnus-summary-highlight): Use them.
+
+2001-05-16  Didier Verna  <didier@lrde.epita.fr>
+
+       * message.el (message-mail): pass the 'send-actions argument to
+       `message-setup'.
+
+2001-05-16  Simon Josefsson  <simon@josefsson.org>
+       From Raymond Scholz <ray-2001@zonix.de>
+
+       * gnus-art.el (gnus-mime-view-part-as-charset):
+       (gnus-mime-internalize-part): Doc fixes.
+
+2001-05-11  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-start.el (gnus-ignored-newsgroups): Also ignore NNTP type
+       status lines without any text ("^215$").
+
+2001-05-06 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-check-group): Reverse.
+
+2001-05-07  Simon Josefsson  <simon@josefsson.org>
+
+       * message.el (message-get-reply-headers):
+       (message-followup): Fix typo, suggested by David Green
+       <dgreen@uab.edu>
+
+2001-05-05 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-request-expire-articles): Fix.
+
+       * nnrss.el (nnrss-open-server): Read server data when it is called.
+       (nnrss-request-expire-articles): Fix.
+
+2001-05-05 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-do-send-housekeeping): mail-abbrevs may
+       rename buffer behind Gnus.
+
+2001-05-04 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-check-group): Use nnheader-translate-file-chars.
+       (nnrss-group-alist): Add more resources.
+       (nnrss-check-group): Ignore errors.
+
+2001-05-04 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-request-expire-articles): Correct the return value.
+
+       * nnslashdot.el (nnslashdot-request-list): Add time.
+       (nnslashdot-request-expire-articles): New function.
+
+       * gnus-start.el (gnus-check-bogus-newsgroups): Remove bogus
+       secondary methods too.
+
+2001-05-03 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-use-followup-to): Set default value to t.
+
+2001-05-03  Florian Weimer  <fw@deneb.enyo.de>
+
+       * message.el (message-dont-reply-to-names): Fix documentation.
+       (message-get-reply-headers): Use Mail-Followup-To only for wide
+       replies.
+
+2001-05-03 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-request-expire-articles): Calculate # of days
+       correctly.
+       (nnrss-check-group): Use time.
+
+2001-05-01 19:21:19 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.03 is released.
+
+2001-05-01 19:06:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-topic-article-to-article): Use the
+       group.
+
+2001-04-24 19:50:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-server-insert-server-line): Add a space.
+
+2001-04-15 14:55:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Return all
+       available headers.
+
+       * gnus-sum.el (gnus-read-all-available-headers): New variable.
+       (gnus-get-newsgroup-headers-xover): Use it.
+
+2001-04-14 15:47:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Clean up.
+
+2001-04-30 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-groups): Use throw instead of error.
+
+2001-04-29 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el (nnrss-insert-w3): Use cache before I figure out how to
+       disable it.
+
+       * gnus.el (gnus-info-nodes): Remove a few The's.
+
+2001-04-29 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-movemail): Call-process may return a
+       signal description string.
+
+       * gnus-start.el (gnus-read-newsrc-el-file):
+       gnus-newsrc-file-version may be nil.
+
+       * nnmail.el (nnmail-get-new-mail): Use the exact file only.
+       Suggested by Michael Sperber [Mr. Preprocessor]
+       <sperber@informatik.uni-tuebingen.de>.
+
+2001-04-25  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * mm-uu.el (mm-uu-configure-list): Fixed customize type.
+
+2001-04-24  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * mm-view.el (mm-display-inline-fontify): Allow XEmacs to fully
+       fontify HANDLE.
+
+2001-04-18  Simon Josefsson  <simon@josefsson.org>
+
+       * smime.el (smime-ask-passphrase): Rework to return value.
+       (smime-sign-region): Rework to bind value and use it.
+       (smime-decrypt-region): Ditto.
+
+2001-04-18  Simon Josefsson  <simon@josefsson.org>
+       Trivial patch from Mathias Herberts  <Mathias.Herberts@iroise.net>
+
+       * smime.el (smime-ask-passphrase): New function.
+       (smime-sign-region): Use it.
+       (smime-encrypt-cipher): New variable.
+       (smime-decrypt-region): Ditto.
+
+2001-04-12  Jason Merrill  <jason_merrill@redhat.com>
+       Committed by Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-shell-open): Erase the buffer *after* copying it into
+       the log.
+
+2001-04-14 01:14:42 Lars Magne Ingebrigtsen  <lars@ingebrigtsen.no>
+
+       * gnus.el: Oort Gnus v0.02 is released.
+
+2001-04-14 00:48:42  Lars Magne Ingebrigtsen  <larsi@quimby.gnus.org>
+
+       * gnus.el: Oort Gnus v0.01 is released.
+
+2001-04-13 22:01:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-highlight): Highlight read
+       undownloaded articles as read articles.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Clean up.
+       (gnus-agent-get-undownloaded-list): Mark all undownloaded
+       articles, even read ones, as such.
+
+       * gnus-sum.el (gnus-summary-find-matching): Clean up.
+       (gnus-find-matching-articles): New function.
+       (gnus-summary-limit-include-matching-articles): New command.
+       (gnus-summary-limit-include-thread): Include articles that have
+       matching subjects.
+       (gnus-offer-save-summaries): Clean up.
+
+2001-04-13  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-split-fancy-with-parent): Add docstring.
+
+2001-04-12 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Jason Merrill <jason_merrill@redhat.com>
+
+       * gnus-sum.el (gnus-summary-insert-new-articles): Reverse the articles.
+
+2001-04-10 08:01:15  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-post-news): Fill the Newsgroups header by the
+       newsgroup names when the original article is a news message.
+
+2001-04-12 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cite-prefix-regexp): Use POSIX regexp if
+       supported. Suggest by Jim Meyering <jim@meyering.net>.
+
+2001-04-02  Nevin Kapur  <nevin@jhu.edu>
+       Committed by Kai Gro\e,b_\e(Bjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>.
+
+       * nnmail.el (nnmail-split-it): Added check for .* at the end of
+       regexp in nnmail-split-fancy.
+
+2001-04-10  Simon Josefsson  <simon@josefsson.org>
+
+       * message.el (message-options-set-recipient): Look at Cc and Bcc too.
+
+2001-04-10  Colin Marquardt  <colin@marquardt-home.de>
+
+       * message.el (message-send-mail): Improve the interaction with the
+       user.
+
+2001-04-10  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-message-copy): Work around buggy servers that
+       doesn't send TRYCREATE tags.
+
+2001-04-09 01:15:54  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-read-newsrc-el-file): Work with Semi-gnusae.
+
+2001-04-05 21:43:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-update-summary-mark-positions): Use a valid
+       date.
+
+2001-04-04 16:13:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-quit): Check that the dribble buffer
+       lives.
+
+2001-04-02 00:40:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-parse-news-url): New function.
+       (gnus-button-handle-news): New function.
+       (gnus-button-alist): Point to new functions.
+
+       * gnus-group.el (gnus-group-quit): Only mark buffer in non-empty.
+
+       * gnus-start.el (gnus-read-newsrc-el-file): Nix out
+       gnus-format-specs.
+
+       * message.el (message-check-news-header-syntax): Question even
+       when Gnus doesn't know the group names.
+       (message-send-news): Clean up.
+
+       * gnus-start.el (gnus-dribble-read-file): Say whether Gnus was
+       exited on purpose without saving.
+
+       * gnus-group.el (gnus-group-quit): Mark the dribble file as `Q'.
+
+2001-04-01 00:37:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-orphans): Clean up.
+
+       * gnus-win.el (gnus-remove-some-windows): Leave one Gnus window.
+
+       * gnus-sum.el (gnus-summary-exit): Kill the summary buffer a bit
+       later.
+
+       * gnus-start.el (gnus-close-all-servers): Find the right items to
+       close.
+
+       * qp.el (quoted-printable-decode-region): Just message
+       malformation; don't quit.
+
+2001-03-31 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Gerd Moellmann <gerd@gnu.org>.
+
+       * gnus.el (gnus-interactive): A typo.
+
+2001-03-26  Juanma Barranquero  <lektu@uol.com.br>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-delete-alist): Declare it as an alias of
+       `assq-delete-all', if that function exists; otherwise use the old
+       definition. Documentation changed to match the one in
+       `assq-delete-all'.
+
+2001-04-01 00:37:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-close-all-servers): New function.
+
+       * gnus-srvr.el (gnus-server-close-all-servers): Clean up.
+       (gnus-server-remove-denials): Clean up.
+
+       * gnus-sum.el (gnus-summary-sort-by-original): New command and
+       keystroke.
+
+2001-03-31 02:56:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-news): Message where we are sending.
+       (message-send-mail): Ditto.
+
+       * gnus.el (gnus-server-string): New function.
+
+       * gnus-sum.el (gnus-summary-up-thread): Doc fix.
+
+       * mm-decode.el (mm-default-directory): Customized.
+       (mm-tmp-directory): Ditto.
+
+       * gnus-sum.el (gnus-summary-catchup-and-exit): Doc fix.
+       (gnus-get-newsgroup-headers): Return -1 for articles without Lines
+       or Chars.
+       (gnus-summary-line-format-alist): ?l is now a string.
+       (gnus-summary-prepare-threads): Output ? for unknown lines.
+       (gnus-summary-insert-line): Ditto.
+       (gnus-summary-print-article): Unbalanced parentheses.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Check group to allow it to find
+       out whether new stuff has arrived.
+
+2001-03-31 02:14:38  Alan Shutko  <ats@acm.org>
+
+       * gnus-sum.el: Let printing work on ttys on Emacs.
+
+2001-03-31 01:11:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-post-news): Add an empty Newsgroups header
+       when forcing news.
+
+       * gnus-sum.el (gnus-summary-mark-article-as-replied): Make into a
+       command.
+
+2001-03-31 01:04:54  Francis Litterio  <franl@world.std.com>
+
+       * message.el (message-set-auto-save-file-name): Don't use
+       asterisks under nt.
+
+2001-03-31 00:03:42  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-inews-insert-draft-meta-information): Allow
+       lists of articles.
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Mark as forwarded.
+
+       * gnus-msg.el (gnus-put-message): Clean up.
+       (gnus-summary-reply): Mark all replied-to articles as replied to.
+       (gnus-inews-add-send-actions): Also mark as forwarded.
+       (gnus-summary-mail-forward): Mark as forwarded.
+
+       * gnus-sum.el (gnus-summary-mark-article-as-replied): Take a list
+       of articles.
+       (gnus-summary-mark-article-as-forwarded): Ditto.
+
+       * gnus-msg.el (gnus-summary-resend-message): Mark article as
+       forwarded.
+       (gnus-summary-mail-forward): Clean up.
+
+       * gnus.el (gnus-article-mark-lists): Added forward.
+
+       * gnus-sum.el (gnus-forwarded-mark): New variable.
+       (gnus-summary-prepare-threads): Use it.
+       (gnus-summary-update-secondary-mark): Ditto.
+       (gnus-newsgroup-forwarded): New variable.
+
+2001-03-30 23:13:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-summary-reply): Allow very wide replies.
+       (gnus-summary-very-wide-reply): New command and keystroke.
+       (gnus-summary-very-wide-reply-with-original): Ditto.
+
+       * gnus-score.el (gnus-adaptive-word-length-limit): New variable.
+       (gnus-score-adaptive): Use it.
+
+       * gnus-start.el (gnus-get-unread-articles): Clean up.
+
+2001-03-21 20:00:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Work for other
+       boards.
+
+2001-03-21  Didier Verna  <didier@lrde.epita.fr>
+
+       * gnus-start.el (gnus-subscribe-newsgroup-hooks): New.
+       * gnus-start.el (gnus-subscribe-newsgroup): use it.
+
+2001-03-15 09:47:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Understand
+       long-form month names.
+
+2001-03-18 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-all-headers):
+       gnus-article-show-all-headers is broken. Use
+       gnus-summary-toggle-header instead.
+
+       * mml2015.el (mml2015-gpg-extract-from): No error.
+
+2001-03-18 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Bj\e,Ax\e(Brn Mork <bmork@dod.no>.
+
+       * mml2015.el (mml2015-gpg-extract-from): New function.
+       (mml2015-gpg-verify): Use it.
+       (mml2015-gpg-clear-verify): Use it.
+
+2001-03-17 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-setup-fill-variables): Use
+       fill-paragraph-function.
+       (message-fill-paragraph): Take an argument.
+       (message-newline-and-reformat): Take another argument.
+
+2001-03-16 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (rmail-output): It is in rmailout.el not rmail.el.
+
+2001-03-16 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-forward): local-variable-p takes an extra
+       argument in XEmacs.
+
+2001-03-16  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-dont-use-nov-p): Renamed from
+       `nnimap-use-nov-p' (it really tested the negative).
+       (nnimap-retrieve-headers): Use it.
+
+2001-03-11  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-generate-headers-first): Update doc.
+
+2001-03-10  Matthias Wiehl  <mwiehl@gmx.de>
+       Trivial patch.
+
+       * gnus.el (gnus-summary-line-format): Typo.
+
+2001-03-11  Simon Josefsson  <simon@josefsson.org>
+
+       * mailcap.el (mailcap-mime-data): Add application/sieve.
+       (mailcap-mime-extensions): Add .siv, .xls.
+
+2001-03-14 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Christoph Conrad <christoph.conrad@gmx.de>
+
+       * gnus-score.el (gnus-summary-lower-thread): Typo.
+
+2001-03-14 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-forward-decoded-p): New variable.
+       (message-forward-subject-author-subject): Use it.
+       (message-make-forward-subject): Use it.
+       (message-forward): Use it.
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Use it.
+
+       * mm-util.el, message.el, rfc2047.el, gnus-sum.el, gnus-score.el:
+       Sync with Emacs 21 (tag EMACS_PRETEST_21_0_100).
+
+;;Has been fixed -- zsh.
+;;2001-03-05  Dave Love  <fx@gnu.org>
+;;
+;;     * mm-util.el (mm-mime-mule-charset-alist): Fix utf-8 case.
+;;     Move it after definition of mm-coding-system-p.
+;;
+2001-03-01  Dave Love  <fx@gnu.org>
+
+       * mm-util.el (mm-inhibit-file-name-handlers): Add
+       image-file-handler.
+
+2001-02-11  Dave Love  <fx@gnu.org>
+
+       * message.el (message-signature-file): Fix doc, :type.
+
+2001-02-08  Dave Love  <fx@gnu.org>
+
+       * rfc2047.el (rfc2047-fold-region): Don't forward-char at EOB.
+       (message-posting-charset): Defvar when compiling again.
+       (rfc2047-encodable-p): Require message.
+
+       * gnus-sum.el (gnus-alter-articles-to-read-function):
+       * gnus-score.el (gnus-score-after-write-file-function): Fix :type.
+
+2001-03-08 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnrss.el: New file.
+
+2001-03-08 02:41:36  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-unfold-region): Fix arg of
+       `skip-chars-forward'.
+
+2001-03-07 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndraft.el (nndraft-request-group): Restore auto save files if
+       the original files do not exist.
+
+2001-03-07 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-find-bnews): Print messages on illegal
+       SCORE paths.
+
+       * mm-decode.el (mm-dissect-buffer): Call
+       mail-extract-address-components only if necessary.
+
+2001-03-06 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-find-bnews): Maybe there is no
+       directory part.
+       (gnus-score-search-global-directories): Use file-directory-p.
+
+       * gnus-score.el (gnus-score-score-files-1): Use
+       gnus-kill-files-directory.
+       From Adrian Aichner <adrian@xemacs.org>.
+
+2001-03-05 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (charset): Move here from gnus-sum.el.
+
+2001-03-04 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-preview): Disable local map.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Make
+       gnus-article-post-menu here.
+
+       * gnus-art.el (gnus-article-make-menu-bar): Make summary-menu bar
+       if it has not been made.
+
+2001-03-02 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-describe-key): Map key to event.
+       (gnus-article-describe-key-briefly): Ditto
+
+2001-03-01 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-limit-include-expunged): Fix.
+
+2001-03-01 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Katsumi Yamaoka <yamaoka@jpl.org>.
+
+       * dgnushack.el (coerce, merge, subseq): defmacro.
+
+2001-03-01 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el (nndraft-request-group): Move it here from nndraft.el.
+       A fake defalias in nndraft.el results a not-activated bug in
+       uncompiled versions.
+
+2001-02-26 11:27:27  Paul Jarc  <prj@po.cwru.edu>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-split-references): Handle malformed References:.
+
+2001-02-26 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-mime-part-status): 1 part.
+
+2001-02-25 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From NAGY Andras <nagya@inf.elte.hu>.
+
+       * gnus.el (gnus-parameters): Typo.
+
+2001-02-24 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-read-method): Remove redundancy.
+
+2001-02-23 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-backslash-url): New variable.
+       (nnslashdot-request-list): Use it.
+
+2001-02-23 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnml.el (nnml-generate-active-info): Fix the case when there is
+       no file.
+
+       * gnus-sum.el (gnus-summary-import-article): Display it. Enable edit.
+       (gnus-summary-create-article): New function.
+
+       * gnus-group.el (gnus-group-mark-article-read): New function.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Use it.
+
+       * gnus-art.el (gnus-article-edit-article): Set modified-p nil.
+
+2001-02-23 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-edit-done): Don't use
+       gnus-article-edit-exit.
+       (gnus-article-edit-exit): Confirm and insert original-article-buffer.
+
+       * gnus.el (gnus-parameters): New variable.
+       Suggested by NAGY Andras <nagya@inf.elte.hu>.
+       (gnus-parameters-get-parameter): New function.
+       (gnus-group-find-parameter): Use it.
+
+2001-02-23  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-msg.el (gnus-post-method): Fix documentation to reflect
+       change of default value to `current'.
+
+2001-02-23 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nneething.el (nneething-get-head): Insert unreadable file too.
+
+2001-02-22 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-insert-articles): Remove fetched headers.
+
+       * webmail.el (webmail-type-definition): Deja is bought by google.
+
+2001-02-22 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-fetch-headers): New function.
+       (gnus-select-newsgroup): Use it.
+       (gnus-summary-insert-articles): New function.
+       (gnus-summary-insert-old-articles): New function.
+       (gnus-summary-insert-new-articles): New function.
+
+       * gnus-group.el (gnus-group-prepare-flat-list-dead): Use decoded-name.
+       (gnus-group-list-active): Ditto.
+       * gnus-sum.el (gnus-set-mode-line): Ditto.
+       (gnus-summary-read-group-1): Ditto.
+
+2001-02-21 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-get-new-news-this-topic): Redraw the
+       current topic.
+
+2001-02-21 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * smiley.el (gnus-smiley-display): Don't do widening.
+
+       * smiley-ems.el (gnus-smiley-display): Don't do widening. Smiley
+       within body.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Activate group anyway.
+
+       * gnus-art.el (gnus-mime-display-multipart-alternative-as-mixed):
+       New variable.
+       (gnus-mime-display-multipart-related-as-mixed): New variable.
+       (gnus-mime-display-part): Use them.
+
+2001-02-20 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-setup-news): Allow gnus-group-line-format to be
+       something special.
+
+2001-02-20 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-request-group): Set nnweb-group anyway.
+       (nnweb-request-article): Call reference if exists.
+       (nnweb-type-definition): Dejanews is bought by google.com.
+       Beta!
+
+2001-02-19 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-reminder): "Confirm to exit?"
+
+2001-02-19  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-thread-sort-functions): Doc fix.  Refer to
+       gnus-article-sort-functions.
+       (gnus-article-sort-functions): Doc fix.  Refer to
+       gnus-thread-sort-functions.
+
+2001-02-18 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Paul Jarc <prj@po.cwru.edu>.
+
+       * message.el (message-get-reply-headers): More fixes.
+
+2001-02-17  Paul Jarc  <prj@po.cwru.edu>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-get-reply-headers): Fix bug with
+       Mail-Followup-To/to-address interaction.
+
+2001-02-17 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Match header in
+       gnus-article-copy.
+
+2001-02-16 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-do-send-housekeeping): Rename to a better
+       name.
+
+2001-02-16 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cancel-news): Check article first, then ask
+       yes or no.
+
+2001-02-16 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-type-alist): Add emacs-sources.
+
+2001-02-16 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-range.el (gnus-range-normalize): New function.
+
+2001-02-15  NAGY Andras  <nagya@inf.elte.hu>
+
+       * imap.el (imap-gssapi-open): Set imap-c-l-s-first.
+
+2001-02-14 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-server-regenerate-server): Use gnus-get-function.
+
+       * nnagent.el (nnagent-request-regenerate): New function.
+
+       * nnfolder.el (nnfolder-request-regenerate): New deffoo.
+
+       * nnml.el (nnml-generate-nov-databases): Accept argument
+       server. Don't open server if it is opened.
+       (nnml-request-regenerate): Use it. Change to deffoo.
+
+2001-02-14  Katsumi Yamaoka  <yamaoka@jpl.org>
+       Committed by ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-define-group-parameter): Fix.
+
+2001-02-14 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-define-group-parameter): Improved.
+
+       * gnus-sum.el (charset): Define parameter.
+       (ignored-charsets): Ditto.
+       (gnus-summary-setup-default-charset): Use them.
+
+       * gnus-start.el (gnus-read-descriptions-file): Use them.
+
+       * gnus-cus.el (gnus-group-parameters): Remove them.
+
+2001-02-14 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-print-article): Redo highlight.
+
+2001-02-13 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-read-group-1): Remove
+       gnus-summary-set-local-parameters.
+       (gnus-summary-setup-buffer): Put it here.
+
+2001-02-13 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (to-address): Define parameter.
+       (to-list): Ditto.
+       * gnus-art.el (article-hide-boring-headers): Use them.
+       * gnus-msg.el (gnus-post-news): Ditto.
+       * gnus-cus.el (gnus-group-parameters): Remove them.
+
+2001-02-13 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-reminder): New function.
+
+       * gnus-art.el (gnus-sender-save-name): New function.
+
+2001-02-13 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-mime-charset): Error message.
+
+2001-02-13 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-check-news-body-syntax): Don't check mml lines.
+
+2001-02-12 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-subscribe-topics): Return nil if not
+       subscribe.
+
+       * gnus-start.el (gnus-call-subscribe-functions): New function.
+       (gnus-find-new-newsgroups): Use it.
+       (gnus-ask-server-for-new-groups): Use it.
+       (gnus-check-first-time-used): Use it.
+       (gnus-subscribe-newsgroup-method): Grok a list of functions.
+       (gnus-subscribe-options-newsgroup-method): Ditto.
+       (gnus-subscribe-hierarchically): Return gnus-subscribe-newsgroup's
+       return .
+
+2001-02-12  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-cus.el (gnus-score-customize): Doc fix.
+
+2001-02-11  Jesper Harder  <harder@ifa.au.dk>
+
+       * dgnushack.el (my-getenv): Typo.
+
+2001-02-11 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-make-load): Don't autoload smiley functions.
+
+2001-02-11 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-suspend): Offer save summaries.
+
+       * gnus-art.el (gnus-treat-leading-whitespace): New variable.
+       (gnus-treatment-function-alist): Use it.
+       (article-remove-leading-whitespace): New function.
+       (gnus-article-make-menu-bar): Use it.
+
+       * gnus-sum.el (gnus-summary-wash-empty-map): Add
+       remove-leading-whitespace.
+       (gnus-summary-wash-map): Bind strip-headers-in-body to `W a',
+       because of conflict.
+
+2001-02-09 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Hack generating gnus-load.el.
+       * dgnushack.el: Ditto.
+       * gnus-load.el: Remove it.
+
+2001-02-09 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el : Add URLDIR.
+
+       * Makefile.in (EMACS_COMP): Ditto.
+
+2001-02-09 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cus.el (gnus-score-customize): Error on no score file.
+
+2001-02-09 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-merge-handles): New function.
+
+       * mm-view.el (mm-inline-message): Use it.
+       (mm-view-message): Ditto.
+
+       * mm-partial.el (mm-inline-partial): Ditto.
+
+       * mm-extern.el (mm-inline-external-body): Ditto.
+
+       * gnus-art.el (gnus-mime-view-part): Ditto.
+       (gnus-mime-view-part-as-type): Ditto.
+       (gnus-mime-save-part-and-strip): Prevent users to strip in some
+       cases.
+
+2001-02-08 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cancel-news): Allow to shoot foot.
+       (message-supersede): Ditto.
+
+2001-02-08  Tommi Vainikainen  <thv@iki.fi>
+       Trivial patch.
+
+       * gnus-sum.el (gnus-simplify-subject-re): Use
+       message-subject-re-regexp.
+
+2001-02-08 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-expiry-target-group): Bind
+       nnmail-cache-accepted-message-ids to nil.
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Use binary
+       coding system.
+
+2001-02-07 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encode-region): Make sure characters are
+       between 00 and FF.  Don't check charset.
+
+       * mm-encode.el (mm-encode-content-transfer-encoding): Use unibyte
+       in Emacs 20.
+       * rfc2047.el (rfc2047-q-encode-region): Ditto.
+
+2001-02-07 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-make-forward-subject): Argument decoded.
+       (message-forward): Use it when digest.
+
+       * gnus-uu.el (gnus-uu-grab-articles): Shoot down original article
+       buffer.
+
+2001-02-07  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-generate-headers-first): Doc fix.
+
+2001-02-07 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-make-date-line): Error proof.
+
+2001-02-06 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-listing-limit): New variable.
+       (gnus-group-prepare-flat-list-dead): Use old trick to speed up.
+
+       * gnus-topic.el (gnus-group-prepare-topics): Use gnus-killed-hashtb.
+
+2001-02-06 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-newline-and-reformat): Special case for
+       breaking at BOL.
+
+2001-02-06  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-uu.el (gnus-uu-save-article): Make the topics summary a
+       message/rfc822.
+
+2001-02-06 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-encode-message-body): Don't insert
+       Content-Type if it is inside a mail.
+
+2001-02-06 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-article-menu-add): Add
+       gnus-article-commands-menu.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Don't share menu bar
+       in Emacs.
+
+       * gnus-start.el (gnus-read-descriptions-file): Use
+       gnus-group-name-charset and gnus-group-charset-alist.
+
+2001-02-04 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-mark-as-processable): Understand
+       active region.
+
+       * gnus-start.el (gnus-group-change-level): Remove from both
+       gnus-zombie-list and gnus-killed-list.
+
+2001-02-04 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-subscribe-options-newsgroup-method): Add
+       gnus-subscribe-topics.
+
+       * gnus-cus.el (gnus-extra-topic-parameters): Fix doc.
+
+2001-02-04 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-make-menu-bar): Make
+       gnus-article-post-menu.
+
+       * gnus-xmas.el (gnus-xmas-article-menu-add): Add post menu.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Use t if XEmacs.
+
+       * gnus-group.el (gnus-group-make-menu-bar): Ditto.
+
+       * message.el (message-mode-menu): Ditto.
+
+       * gnus-art.el (defvar): eval-when-compile.
+
+2001-02-02 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agentize): Fix doc.
+
+2001-02-02  Karl Kleinpaste  <karl@charcoal.com>
+
+       * mml.el (mml-preview): Bind `q'.
+
+2001-02-02 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-mime-mule-charset-alist): non-Mule case.
+
+2001-01-31  Dave Love  <fx@gnu.org>
+
+       * mm-util.el (mm-mime-mule-charset-alist)
+       (mm-find-mime-charset-region): Consider mule-utf-8.
+
+2001-01-31  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el (gnus-article-x-face-command)
+       (gnus-treat-display-xface, gnus-treat-display-smileys): Add
+       :version.
+
+2001-01-26  Dave Love  <fx@gnu.org>
+
+       * mm-util.el (mm-multibyte-string-p): New.
+
+;;     * qp.el: Remove un-logged bogus changes from 2000-12-20.
+;;     (quoted-printable-encode-region): Doc fix.  Don't call
+;;     string-as-multibyte on class.  Clarify line-folding.
+       (quoted-printable-encode-string): Make temp buffer inherit
+       string's multibyteness.
+
+2001-01-23  Gerd Moellmann  <gerd@gnu.org>
+
+       * nnheader.el (toplevel): Don't require `gnus-util' at
+       compile-time; this creates a circular dependency, and prevents
+       a bootstrap.
+
+2001-01-22  Andreas Schwab  <schwab@suse.de>
+
+       * nnheader.el (gnus-delete-line): Autoload it as a macro.
+
+2001-01-31 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-remove-list-identifiers): Use consp.
+
+       * gnus-art.el (article-hide-list-identifiers): Ditto.
+
+       * gnus-sum.el (gnus-summary-remove-list-identifiers): Ditto.
+
+2001-01-31 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-remove-list-identifiers): Similar.
+
+       * gnus-art.el (article-hide-list-identifiers): Similar.
+
+2001-01-31  Karl Kleinpaste  <karl@charcoal.com>
+
+       * nnmail.el (nnmail-remove-list-identifiers): Improved.
+
+2001-01-31 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-summary-score-entry): match may be an integer.
+
+2001-01-30 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-string-equal): New function.
+
+       * gnus-art.el (article-hide-boring-headers): Use it.
+
+2001-01-27  Karl Kleinpaste  <karl@charcoal.com>
+
+       * gnus-art.el (gnus-article-banner-alist): eGroups new banner.
+
+2001-01-27 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-msg-mail): Support switch-action.
+
+2001-01-26 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-summary-save-in-pipe): Prompt for saving
+       command if there is not last-saver.
+
+2001-01-24 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-open-connection): 201 is possible.
+
+2001-01-24 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode): MIME charset is not coding system.
+       (rfc2047-charset-encoding-alist): Add big5.
+
+2001-01-24 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-add-server): Redraw the line.
+       (gnus-agent-remove-server): Ditto.
+       (autoload): gnus-server-update-server.
+
+       * gnus-srvr.el (gnus-server-line-format): Add %a.
+       (gnus-server-line-format-alist): Add gnus-tmp-agent.
+       (gnus-server-insert-server-line): Use it.
+
+2001-01-24 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-mime-mule-charset-alist): Preferred MIME names
+       GB2312 and Big5.
+
+2001-01-24  Simon Josefsson  <sj@extundo.com>
+
+       * mail-source.el (mail-sources): Add :program specifier to IMAP
+       mail source.
+       (mail-source-fetch-imap): Map :program to `imap-shell-program'.
+
+2001-01-24 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-lower-thread): Fix a doc typo.
+
+2001-01-24 12:22:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nntp.el (nntp-wait-for): Return the success code.
+       (nntp-open-connection): Use it.
+
+2001-01-11 11:49:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-int.el (gnus-check-server): Allow breaking the opening.
+
+2001-01-23 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-print-article): Remove process mark.
+
+2001-01-22 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-print-article): Take one prefix
+       argument. Allow to print several articles in one file.
+
+2001-01-21 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-type-definition): netaddress changes.
+
+2001-01-21 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: Fix copyright. Remove trailing spaces.
+
+       * message.el (message-forward): Use mule4.
+
+2001-01-20 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-string-as-unibyte): New function.
+
+       * message.el (message-forward): Use it.
+
+2001-01-19 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cite-original-without-signature): Don't peel
+       off the blank line.
+       (message-get-reply-headers): Add Cc if it is not in follow-to.
+
+2001-01-20  Simon Josefsson  <sj@extundo.com>
+
+       * mm-decode.el (mm-handle-multipart-from): Add.
+       (mm-dissect-buffer): Save From: header value.
+       (mm-security-from): Remove.
+       (mm-possibly-verify-or-decrypt): Don't set mm-security-from.
+
+       * mml-smime.el (mml-smime-verify): Use `mm-handle-multipart-from'
+       instead of `mml-security-from'.  Protect null from value.
+
+2001-01-20  Simon Josefsson  <sj@extundo.com>
+
+       * mailcap.el (mailcap-mime-data): Run `gnumeric' on
+       application/vnd.ms-excel attachments.
+
+2001-01-19  Simon Josefsson  <sj@extundo.com>
+
+       * gnus-art.el (gnus-button-alist): Add `?=' to mailto URL regexp.
+
+2001-01-19 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-ignored-mail-headers): Ditto.
+
+2001-01-19  Simon Josefsson  <sj@extundo.com>
+
+       * message.el (message-ignored-news-headers): Only search beginning
+       of line.
+
+2001-01-19  ShengHuo Zhu  <zsh@cs.rochester.edu>
+       Trivial patch from Alberto Lusiani  <a.lusiani@noemail.org>
+
+       * message.el (message-send-mail): Content-Type may not be there.
+
+2001-01-18 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ems.el (gnus-article-display-xface): Add BUFFER.
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Ditto.
+
+       * gnus-art.el (article-display-x-face): Insert X-Face if there is
+       not.
+
+2001-01-18 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-read-group-1): Don't test dead
+       non-native groups.
+
+2001-01-18 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-yank-original): Understand
+       universal-argument.
+
+2001-01-18 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-boring-article-headers): Add to-address.
+       (article-hide-boring-headers): Ditto.
+
+       * mm-view.el (mm-inline-message): Insert a newline unless bolp.
+
+2001-01-18 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-fold-region): Don't insert LWSP if there is
+       one.
+
+2001-01-16  Simon Josefsson  <simon@josefsson.org>
+
+       * message.el (message-make-in-reply-to): Add comment to message-id
+       (old syntax, see 2000-08-02 change).
+
+2001-01-16 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-url-mailto): Use gnus-msg-mail.
+       (gnus-button-mailto): Setup message. Moved to gnus-msg.el.
+       (gnus-button-reply): Ditto.
+
+2001-01-16  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (article-display-x-face): Fix.
+
+2001-01-15 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-display-x-face): Use
+       gnus-original-article-buffer.
+
+2001-01-15  Jack Twilley  <jmt@tbe.net>
+
+       * message.el (message-add-header): Move to point-max.
+
+2001-01-15  Simon Josefsson  <simon@josefsson.org>
+
+       * smime.el (smime-CA-directory, smime-CA-file): Change default to
+       nil, improve documentation.
+       (smime-certificate-directory): Comment out false hints (until it
+       is implemented).
+
+       * mml-smime.el (mml-smime-sign): Place user in customize buffer if
+       there aren't any keys.
+       (mml-smime-verify): If smime-CA-{file,directory} set, also try to
+       verify certificate.  Default is changed to only check integrity.
+       Improved security status texts.  If a certificate doesn't contain
+       a email address, don't fail.
+
+       * smime.el (smime-noverify-region):
+       (smime-noverify-buffer): New functions.  Verifies integrity only.
+
+2001-01-12 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-sort-by-score): Reverse order.
+
+2001-01-12 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-configure-windows): switch-to-buffer in XEmacs.
+       (gnus-remove-some-windows): Ditto.
+
+2001-01-12 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-make-date-line): 11th.
+
+2001-01-11 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-gpg-encrypt): Remove CR.
+       (mml2015-gpg-sign): Ditto.
+
+2001-01-10 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: Sync with EMACS_PRETEST_21_0_95.
+       * gnus.el (gnus-default-posting-charset): Bogus. Removed.
+
+2001-01-08  Dave Love  <fx@gnu.org>
+
+       * mm-encode.el (mm-qp-or-base64): Don't base64 for the sake of a
+       single character.
+
+       * mm-util.el (mm-mime-mule-charset-alist): Add Latin-{8,9}.
+
+       * message.el: Doc and message fixes.
+       (message-send-rename-function)
+       (message-make-forward-subject-function)
+       (message-send-mail-function, message-reply-to-function)
+       (message-wide-reply-to-function, message-followup-to-function)
+       (message-distribution-function, message-auto-save-directory): Fix
+       :type.
+
+       * gnus/mml.el (mml-parse-1): Frob mml-confirmation-set when
+       proceeding after warnings.  Amend multipart warning message.
+
+2001-01-04  Dave Love  <fx@gnu.org>
+
+       * gnus-util.el (nnmail-pathname-coding-system): Defvar when
+       compiling.
+       (gnus-make-directory): Require nnmail.
+
+       * mm-decode.el (mm-inline-media-tests): Add
+       image/x-portable-bitmap.
+       (mm-get-image): Grok pbm.
+
+2001-01-10  Paul Stevenson  <p.stevenson@surrey.ac.uk>
+
+       * nnvirtual.el (nnvirtual-request-expire-articles): delq nil.
+
+2001-01-09  Didier Verna  <didier@xemacs.org>
+
+       * dgnushack.el (dgnushack-compile): give a dummy value to
+       `gnus-xmas-glyph-directory' for the time of compilation.
+       * gnus-agent.el: moved some XEmacs specific hook add-ons from
+       `gnus-xmas-[re]define' to avoid loosing user custom settings.
+       * gnus-art.el: ditto.
+       * gnus-group.el: ditto.
+       * gnus-salt.el: ditto.
+       * gnus-sum.el: ditto.
+       * gnus-topic.el: ditto.
+       * gnus-xmas.el (gnus-xmas-define): see above.
+       * gnus-xmas.el (gnus-xmas-redefine): see above.
+       * gnus-xmas.el (gnus-xmas-glyph-directory): generate a
+       non-continuable error when the directory can't be found.
+
+2001-01-09 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-interactively-view-part): Don't copy-sequence
+       handle.
+       * gnus-art.el (gnus-mime-view-part): Copy it.
+       (gnus-mime-view-part-as-type): Add into gnus-article-mime-handles.
+
+2001-01-09  Michael Downes  <mjd@ams.org>
+
+       * gnus-sum.el (gnus-summary-read-group-1): More useful message.
+
+2001-01-08 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-get-new-mail): Find group only if file is not
+       orig-file. Use ',source.
+
+2001-01-08 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-modeline-glyph):
+       (gnus-xmas-group-startup-message):
+       Detect gnus-xmas-glyph-directory when it is nil.
+
+2001-01-08 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * pop3.el (pop3-get-message-count): Andrew Innes
+       <andrewi@gnu.org>'s patch of 1999-12-01 was not fully committed.
+
+2001-01-05 06:49:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-fetch-session): Say what we quit.
+
+       * time-date.el (time-to-number-of-days): New function.
+
+2001-01-04 11:06:14  Gregory Chernov  <greg@visiontech-dml.com>
+       Trivial patch.
+
+       * nnslashdot.el (nnslashdot-request-list): Always get the right
+       sid.
+
+2001-01-05 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-minibuffer-local-map): New keymap.
+       (message-read-from-minibuffer): Use it.
+       * gnus-msg.el (gnus-summary-resend-message): Use it
+
+2001-01-04 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-display-time-event-handler): New function.
+       (gnus-after-getting-new-news-hook): Use it.
+
+2001-01-03 07:26:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-ignored-mail-headers): Add draft header.
+
+2001-01-02 06:28:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-expire-articles): Don't save
+       excursion.
+
+       * nnslashdot.el (nnslashdot-request-list): Get the right year.
+
+2001-01-01 00:52:44  Ed L. Cashin  <ecashin@coe.uga.edu>
+       A revoked patch.
+
+       * gnus-sum.el (gnus-summary-expire-articles): Save excursion.
+
+2000-12-31 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-decode-region): Don't backward-char.
+
+2000-12-31 03:57:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el: Mark articles as replied.
+
+       * gnus-sum.el (gnus-summary-add-mark): New function.
+
+       * gnus-group.el (gnus-add-mark): New function.
+
+       * gnus-sum.el (gnus-summary-buffer-name): New function.
+       (gnus-summary-setup-buffer): Use it.
+
+       * gnus-draft.el: Set things up with the right post method and
+       stuff.
+
+       * message.el (message-ignored-news-headers): Remove X-Draft-From.
+
+       * gnus-msg.el (gnus-inews-insert-draft-meta-information): New function.
+
+       * gnus.el (gnus-draft-meta-information-header): New variable.
+
+2000-12-30 00:17:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treatment-function-alist): Move the date
+       functions before the header sorting functions.
+
+       * mm-uu.el (mm-uu-pgp-signed-extract-1): Unquote "- " quotes.
+
+       * dgnushack.el (dgnushack-compile): Message whether there is w3.
+       Don't (push "/usr/share/emacs/site-lisp" load-path).
+
+       * gnus-cite.el (gnus-article-fill-cited-article): Don't add space
+       to empty fill prefixes.
+
+2000-12-30 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-open-connection): Kill pbuffer if process is nil.
+       Suggested by Christoph Conrad <christoph.conrad@gmx.de>.
+
+2000-12-30 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (autoload): Autoload gnus-sorted-intersection.
+
+       * nnml.el (autoload): Move to nnheader.el.
+
+       * nnfolder.el (nnfolder-existing-articles): Reversed, i.e. sorted.
+       (nnfolder-request-expire-articles): Use gnus-sorted-intersection.
+       (nnfolder-retrieve-headers): Use intersection. Suggested by Jonas
+       Kvarnstr\e,Av\e(Bm <jonkv@ida.liu.se>.
+
+2000-12-30 00:17:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-make-date-line): Get the hours right.
+       (gnus-ignored-headers): More hiding.
+
+       * nnmail.el (nnmail-expiry-wait): Not an integer.
+
+       * message.el (message-goto-body): Only expand abbrev when called
+       interactively.
+       (message-make-lines): Use it.
+
+2000-12-29 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-yank-articles): Reparse headers.
+
+2000-12-30 00:17:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-limit-include-expunged): Really
+       include the expunged articles.
+
+       * gnus-group.el (gnus-group-sort-by-server): New function.
+
+       * gnus.el (gnus-method-to-server-name): New function.
+       (gnus-group-prefixed-name): Use it.
+
+       * gnus-group.el (gnus-group-sort-function): Doc fix.
+       (gnus-group-sort-groups-by-server): New command.
+
+2000-12-29 13:25:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-date-english): New variable.
+       (article-date-english): New command.
+       (gnus-english-month-names): New variable.
+       (article-make-date-line): Do 'english.
+
+       * gnus-cite.el (gnus-article-fill-cited-article): Add a space
+       after the fill prefix.
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Removed "Enter
+       score...".
+
+       * gnus-art.el (gnus-ignored-headers): Hide more headers.
+
+       * message.el (message-mode-map): Bind comment-region.
+
+       * gnus-art.el (gnus-mime-display-part): Let w3 display
+       multipart/related.
+
+       * mm-bodies.el (mm-long-lines-p): New function.
+       (mm-body-encoding): Use it.
+       (mm-body-encoding): Encode articles with lines longer than 1000
+       characters.
+
+2000-12-29 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-enable-multibyte): Use
+       default-enable-multibyte-characters.
+       (mm-enable-multibyte-mule4): Ditto.
+       (mm-disable-multibyte): Test XEmacs.
+       (mm-disable-multibyte-mule4): Ditto.
+       (mm-with-unibyte-current-buffer): Simplified.
+       (mm-with-unibyte-current-buffer-mule4): Ditto.
+
+2000-12-28 19:44:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheaderxm.el (nnheader-string-as-multibyte): New alias.
+
+       * nnheader.el (nnheader-string-as-multibyte): New alias.
+
+       * mm-view.el (mm-inline-text): Warn when bugging out in w3.
+
+       * gnus-uu.el (gnus-message-process-mark): New function.
+       (gnus-uu-mark-by-regexp): Use it.
+       (gnus-new-processable): New function.
+
+2000-12-28 19:21:57  Inge Frick  <inge@nada.kth.se>
+        Trivial patch.
+
+       * gnus-sum.el (gnus-no-mark): New variable.
+
+2000-11-01 01:12:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnwfm.el (nnwfm-create-mapping): Remove quote marks and
+       backslashes.
+
+2000-12-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-banner-alist): Remove duplicate
+       definition.
+
+2000-12-25 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-compile): elc is in the current directory.
+
+       * qp.el (quoted-printable-encode-region): Don't check multibyte in
+       XEmacs.
+
+2000-12-25  Lloyd Zusman  <ljz@asfast.com>
+       Trivial patch.
+
+       * mml.el (mml-read-tag): Save tag location.
+
+2000-12-25  Simon Josefsson  <simon@josefsson.org>
+
+       * starttls.el: Sync with Emacs 21.
+
+2000-12-24 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mail): Support yank-action.
+
+       * message.el (message-setup): Revoke the last change.
+
+2000-12-24 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-setup): Use cons. Suggested by Johan Vromans
+       <jvromans@squirrel.nl>.
+
+2000-12-24  Simon Josefsson  <sj@extundo.com>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Preserve
+       mailing list junk at end of part.
+
+2000-12-23  Simon Josefsson  <sj@extundo.com>
+
+       * nnimap.el (nnimap-expiry-target): New function.
+       (nnimap-request-expire-articles): Use it.
+
+2000-12-22 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-group-parameters-more): New variable.
+       * gnus-cus.el (gnus-group-customize): Use it.
+
+       * gnus.el (gnus-define-group-parameter): New macro.
+       (auto-expire): Use it
+       (total-expire): Use it.
+       * gnus-art.el (banner): Use it.
+
+       * mml.el (mml-parse): save-excursion. Suggested by Lloyd Zusman
+       <ljz@asfast.com>.
+
+2000-12-22 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-create-topic): Use list.
+
+       * gnus-vm.el (gnus-summary-save-article-vm): Require gnus-art
+       before binding gnus-default-article-saver.
+
+       * gnus-sum.el (gnus-summary-save-article):
+       (gnus-summary-pipe-output):
+       (gnus-summary-save-article-mail):
+       (gnus-summary-save-article-rmail):
+       (gnus-summary-save-article-file):
+       (gnus-summary-write-article-file):
+       (gnus-summary-save-article-body-file): Ditto.
+
+       * gnus-mh.el (gnus-summary-save-article-folder): Ditto.
+
+2000-12-22 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-security-button-map):
+       (gnus-mime-button-map): Add parent.
+
+2000-12-22 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * messagexmas.el (message-xmas-redefine): New function.
+
+       * message.el: Use it.
+
+       * gnus-art.el (gnus-article-check-hidden-text): Return t.
+
+       * gnus-util.el (gnus-remove-text-properties-when): Return t.
+
+2000-12-22 03:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-multipart): Avoid errors owing to
+       malformatted messages.
+
+2000-12-22 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-image-load-path): New function.
+
+       * gnus-group.el (gnus-group-make-tool-bar): Use it.
+
+       * gnus-sum.el (gnus-summary-make-tool-bar): Use it.
+
+       * message.el (message-tool-bar-map): Use it.
+
+       * Makefile.in (install-el): New rule.
+
+2000-12-21  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (article-treat-dumbquotes): Quote \.
+
+2000-12-21 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-treat-emphasize): Don't treat emphasis if
+       Emacs 20 runs on a terminal.
+
+2000-12-21 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-bug): Revert to save-excursion.
+
+       * mml.el (gnus-add-minor-mode): Autoload.
+
+       * message.el (message-forward): Save-restriction.
+
+2000-12-21  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (article-treat-dumbquotes): More doc, provided by
+       Paul Stevenson <p.stevenson@surrey.ac.uk>
+
+2000-12-21 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el (gnus-mailing-list-mode-map): Use C-c C-n prefix.
+
+       * mml.el (gnus-ems): Don't require.
+
+       * gnus.el (gnus-decode-rfc1522): Removed.
+       (gnus-set-text-properties): Define.
+
+2000-12-21 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-*): handle may be nil.
+
+       * gnus-sum.el (gnus-summary-mode): Turn on gnus-mailing-list-mode.
+
+       * gnus.el (gnus-group-remove-excess-properties): Not defined
+       in gnus-xmas.
+
+2000-12-20 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mail-user-agent): Add :version.
+
+2000-12-21  Miles Bader  <miles@gnu.org>
+
+       * message.el (message-mode): Set `comment-start' to the  yank prefix.
+
+2000-12-20 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mail-user-agent): New variable.
+       (message-setup): Renamed to message-setup-1. Support
+       mail-user-agent.
+       (message-mail-user-agent): New function.
+       (message-mail): Use it.
+       (message-reply): Use it.
+       (message-resend): Use it.
+       (message-mail-other-window): Use it.
+       (message-mail-other-frame): Use it.
+
+       * gnus-msg.el (gnus-bug): Support mail-user-agent.
+
+2000-12-20 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-tool-bar-map): Simplify.
+       (message-narrow-to-head-1): New function.
+       (message-narrow-to-head): Use it.
+       (message-reply): Ditto.
+       (message-cancel-news): Ditto.
+       (message-supersede): Ditto.
+       (message-make-forward-subject): Ditto.
+       (message-bounce): Ditto.
+
+2000-12-20 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * uudecode.el (uudecode-decode-region-external): make-temp-file
+       may not be defined.
+
+       * binhex.el (defalias): eval-and-compile.
+
+       * message.el (message-tool-bar-map): New function.
+       (message-mode): Use it.
+
+2000-12-20 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-find-connection): Remove the entry.
+       (nntp-retrieve-groups): (gnus-buffer-live-p buf).
+
+2000-12-20 05:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Use original buffer.
+
+       * message.el (message-forward): Copy buffer in unibyte mode.
+
+2000-12-20 04:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-make-forward-subject): Don't widen. Decode.
+       (message-forward): Don't decode subject.
+
+2000-12-20  Christoph Conrad  <C.Conrad@cli.de>
+
+       * qp.el (quoted-printable-encode-region): Upcase QP.
+
+2000-12-20 03:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-possibly-verify-or-decrypt): Use
+       mail-extract-a-c instead. Don't depend on Gnus.
+
+       * mml.el (gnus-ems): Require it.
+
+       * gnus-msg.el (gnus-summary-mail-forward):
+
+       * message.el (message-forward):  Move mime-to-mml here.
+
+2000-12-20 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el, gnus-sum.el, message.el: Add :help unless Emacs.
+       * gnus-art.el (gnus-insert-mime-button): Simplify.
+       (gnus-mime-display-alternative): Ditto.
+       (gnus-insert-mime-security-button): Ditto.
+
+2000-12-20 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-add-text-properties-when): In XEmacs,
+       text-property-not-all doesn't return nil when start=mark(end).
+       (gnus-remove-text-properties-when): Ditto.
+
+2000-12-20 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-group-change-level): Remove group from
+       gnus-active-hashtb if real killed.
+
+2000-12-19 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-insert-mime-button): Emacs20 needs local-map.
+       (gnus-mime-display-alternative): Ditto.
+       (gnus-insert-mime-security-button): Ditto.
+
+2000-12-19 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-group-change-level): Don't add it into
+       killed-list if it was killed.
+
+2000-12-19 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmbox.el (nnmbox-file-coding-system): Use binary.
+       (nnmbox-active-file-coding-system): Ditto.
+
+       * gnus-cus.el (gnus-group-parameters): Add posting-style.
+
+2000-12-19 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-version):
+       (gnus-version-number): Set to Oort Gnus 0.01.
+
+       * gnus-art.el (gnus-mime-security-button-map):
+       (gnus-insert-mime-security-button): Fix for Emacs21.
+
+2000-12-19 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el, gnus-sum.el, message.el: Comment out :help in
+       easymenu, because XEmacs doesn't understand :help.
+
+       * mm-uu.el: Require binhex.
+
+2000-12-19 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: Merged. Emacs21 CVS tag is zsh-merge-ognus-1.
+
+2000-12-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-synonym-alist): Fix a typo.
+
+2000-12-18  Gerd Moellmann  <gerd@gnu.org>
+
+       * *.xpm, *.pbm: Convert icons icons to size 24x24.
+
+2000-12-18  Dave Love  <fx@gnu.org>
+
+       * gnus-msg.el (news-setup, news-reply-mode): Don't autoload
+       (unused).
+
+2000-12-13  Miles Bader  <miles@gnu.org>
+
+       * smiley-ems.el (smiley-region): Bind `inhibit-point-motion-hooks'
+       to t, so that we don't get stuck while trying to smilefy
+       intangible text.
+
+2000-12-12  Gerd Moellmann  <gerd@gnu.org>
+
+       * smiley-ems.el (smiley-regexp-alist): Make regexps match
+       at the end of the buffer.
+       (smiley-region): In the loop, move to the end of the submatch
+       matching the smiley instead of using the end of the match
+       of the whole regexp.
+
+2000-12-12  Eli Zaretskii  <eliz@is.elta.co.il>
+
+       * message.el (message-mode): Doc fix.
+
+2000-12-12  Gerd Moellmann  <gerd@gnu.org>
+
+       * smiley-ems.el (smiley-region): Doc fix.
+
+2000-12-11  Miles Bader  <miles@gnu.org>
+
+       * gnus-sum.el (gnus-summary-recenter): When trying to keep the
+       bottom line visible, check to see if it's partially obscured, and
+       if so, either scroll one more line to make it fully visible, or
+       revert to showing the second line from the top.
+
+2000-12-07  Dave Love  <fx@gnu.org>
+
+       * mailcap.el (mailcap-download-directory)
+       * gnus-audio.el (gnus-audio-directory)
+       * smiley-ems.el (smiley-data-directory): Fix :type.
+
+2000-11-30  Dave Love  <fx@gnu.org>
+
+       * message.el (message-auto-save-directory): Use
+       file-name-as-directory.
+       (message-set-auto-save-file-name): Create
+       message-auto-save-directory if necessary.
+       (message-replace-chars-in-string): Removed -- unused.
+       (message-mail-alias-type): Customize.
+       (message-headers): Remove duplicate defgroup.
+
+2000-11-29  Dave Love  <fx@gnu.org>
+
+       * qp.el (quoted-printable-decode-region): Use error, not message
+       to report malformed text (like base64).  Amend message.
+
+2000-11-29  Miles Bader  <miles@gnu.org>
+
+       * message.el (message-header-lines): Fontify tag.
+
+2000-11-27  Dave Love  <fx@gnu.org>
+
+       * nnlistserv.el: Ignore errors when requiring nnweb and avoid a
+       compiler warning.
+
+;2000-11-26  Dave Love  <fx@gnu.org>
+;
+;      * mm-uu.el (mm-uu-configure-list): Fix typo in :type.
+;
+2000-11-23  Dave Love  <fx@gnu.org>
+
+       * uu-post.pbm, uu-decode.pbm: new files from XPMs.
+
+       * mm-uu.el (uudecode): Require.
+       (uudecode-decode-region, uudecode-decode-region-external): Don't
+       autoload.
+       (mm-uu-copy-to-buffer): Doc fix.
+       (mm-uu-decode-function, mm-uu-binhex-decode-function): Doc, custom
+       type fix.
+
+       * mailcap.el: Doc fixes.
+       (mailcap-mime-data): Various adjustments.
+       (mailcap): New group.
+       (mailcap-download-directory): Customize.
+       (mailcap-generate-unique-filename, mailcap-binary-suffixes)
+       (mailcap-temporary-directory): Deleted (unused).
+       (mailcap-unescape-mime-test): Simplify slightly.
+       (mailcap-viewer-passes-test): Use functionp.
+       (mailcap-command-p): Aliased to executable-find.
+
+       * rfc2047.el (rfc2047-encode-message-header): Don't encode if
+       default-enable-multibyte-characters is nil.
+
+2000-11-22  Gerd Moellmann  <gerd@gnu.org>
+
+       * gnus-group.el (gnus-group-make-tool-bar): Fix a paren typo.
+
+2000-11-21  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el (gnus-mime-button-map): Don't inherit from
+       gnus-article-mode-map.
+;      (gnus-mime-button-menu): Use mouse-set-point.
+       (gnus-insert-mime-button, gnus-mime-display-alternative)
+       (gnus-mime-display-alternative): Don't use local-map property.
+
+2000-11-17  Dave Love  <fx@gnu.org>
+
+       * uudecode.el (uudecode-insert-char): Fix bogus feature test.
+       (uudecode-decode-region-external): Doc fix.  Use with-temp-buffer
+       and make-temp-file.
+       (uudecode-decode-region): Doc fix.
+
+2000-11-14  Dave Love  <fx@gnu.org>
+
+       * cu-exit.pbm, exit-summ.pbm, followup.pbm, fuwo.pbm:
+       * mail-reply.pbm, next-ur.pbm, post.pbm, prev-ur.pbm:
+       * reply-wo.pbm, reply.pbm, rot13.pbm, save-aif.pbm, save-art.pbm:
+       New files, derived from the XPMs.
+
+2000-11-10  Dave Love  <fx@gnu.org>
+
+       * gnus-agent.el (gnus-agent-confirmation-function): Add :version.
+       (gnus-agent-lib-file, gnus-agent-load-alist)
+       (gnus-agent-save-alist, gnus-agent-article-name): Use
+       expand-file-name.
+
+       * gnus-group.el (gnus-group-name-charset-method-alist): Add
+       :version.
+       (nnkiboze-score-file): Defvar when compiling.
+
+       * gnus-start.el (gnus-read-newsrc-file): Add :version.
+
+       * gnus-art.el (gnus-article-banner-alist)
+       (gnus-emphasize-whitespace-regexp, gnus-ignored-mime-types)
+       (gnus-article-date-lapsed-new-header)
+       (gnus-article-mime-match-handle-function, gnus-mime-action-alist)
+       (gnus-treat-strip-list-identifiers, gnus-treat-date-iso8601)
+       (gnus-treat-strip-headers-in-body)
+       (gnus-treat-capitalize-sentences, gnus-treat-play-sounds)
+       (gnus-treat-translate): Add :version.
+       (gnus-article-mime-part-function): Fix defcustom.
+
+       * nnmail.el (nnmail-expiry-target)
+       (nnmail-scan-directory-mail-source-once, nnmail-extra-headers)
+       (nnmail-split-header-length-limit): Add :version.
+
+       * gnus-sum.el (gnus-auto-expirable-marks)
+       (gnus-inhibit-user-auto-expire, gnus-list-identifiers)
+       (gnus-extra-headers, gnus-ignored-from-addresses)
+       (gnus-newsgroup-ignored-charsets)
+       (gnus-group-highlight-words-alist)
+       (gnus-summary-show-article-charset-alist): Add :version.
+
+       * catchup.pbm, describe-group.pbm, exit-gnus.pbm, get-news.pbm:
+       gnntg.pbm, kill-group.pbm, subscribe.pbm, unsubscribe.pbm: New
+       files, converted from the XPMs.
+
+       * gnus-cache.el (gnus-cache-active-file): Don't use
+       file-name-as-directory on directory.
+       (gnus-cache-file-name): Use expand-file-name, not concat.  Don't
+       use file-name-as-directory on directory.
+
+       * time-date.el (timezone-make-date-arpa-standard): Autoload.
+       (date-to-time): Use it.
+
+;      * message.el (message-mode) <adaptive-fill-regexp>:
+;      <adaptive-fill-first-line-regexp>: Use [:alnum:] in regexp range.
+;      (message-newline-and-reformat): Likewise.
+       (message-forward-as-mime, message-forward-ignored-headers)
+       (message-buffer-naming-style, message-default-charset)
+       (message-dont-reply-to-names, message-send-mail-partially-limit):
+       Add :version.
+
+       * mm-util.el: Doc fixes.
+       (mm-mime-charset): Don't use the raw result of
+       mm-preferred-coding-system.
+       (mm-with-unibyte-buffer, mm-with-unibyte-current-buffer)
+       (mm-with-unibyte): Simplify.
+
+       * gnus-int.el (gnus-start-news-server): Use expand-file-name, not
+       concat.
+
+       * pop3.el (pop3-version): Deleted.
+       (pop3-make-date): New function, avoiding message-make-date.
+       (pop3-munge-message-separator): Use it.
+
+2000-11-09  Dave Love  <fx@gnu.org>
+
+       * gnus-group.el (gnus-group-make-directory-group)
+       (gnus-group-fetch-faq): Use expand-file-name.
+       (gnus-group-fetch-faq): Simplify completing-read form.
+
+       * mm-bodies.el (mm-encode-body): Use mm-multibyte-p, don't just
+       test for Mule.
+
+       * message.el (tool-bar-map): Defvar when compiling.
+
+       * gnus-setup.el (running-xemacs, gnus-use-installed-tm)
+       (gnus-tm-lisp-directory): Deleted.
+       (gnus-use-installed-mailcrypt, gnus-emacs-lisp-directory): Use
+       (featurep 'xemacs).
+       (gnus-gnus-lisp-directory, gnus-mailcrypt-lisp-directory)
+       (gnus-mailcrypt-lisp-directory, gnus-bbdb-lisp-directory): Remove
+       version numbers from file names.
+
+2000-11-08  Dave Love  <fx@gnu.org>
+
+       * mm-view.el: Use featurep for XEmacs test.
+       (mm-inline-message): Test for `remove-specifier'; don't use
+       condition-case.
+
+       * mm-bodies.el (mm-encode-body): Use mm-multibyte-p.
+
+       * gnus-score.el (gnus-score-load-file): Use expand-file-name.
+       (gnus-score-find-bnews): Don't concat "".
+
+       * cu-exit.xpm, prev-ur.xpm, next-ur.xpm, post.xpm, fuwo.xpm:
+       * followup.xpm, uu-post.xpm, uu-decode.xpm, mail-reply.xpm:
+       * reply.xpm, reply-wo.xpm, rot13.xpm, save-aif.xpm, save-art.xpm:
+       * exit-summ.xpm: New files, renamed from icons by Luis Fernandes.
+
+       * gnus-sum.el: Put some defvars in eval-when-compile.
+       (gnus-summary-mode-hook): Add :options.
+       (gnus-summary-make-menu-bar): Add some :help, used by tool bar.
+       (gnus-summary-tool-bar-map): New variable.
+       (gnus-summary-make-tool-bar): New function.
+       (gnus-summary-mode): Put kill-all-local-variables first.
+
+       * gnus-group.el (gnus-group-toolbar-map): New variable.
+       (gnus-group-make-tool-bar): Rewritten.
+       (gnus-group-mode): Put kill-all-local-variables first.
+
+       * rfc2047.el: Require gnus-util.
+
+       * nnml.el (gnus-sorted-intersection): Autoload.
+
+       * nnheader.el: Wrap subst-char-in-string def in eval-and-compile.
+       Put some defvars in eval-when-compile.
+       (gnus-intersection, gnus-sorted-complement):  Autoload.
+
+       * imap.el (imap-point-at-eol): New, replacing gnus-point-at-eol.
+
+       * mm-encode.el (mm-body-7-or-8): Autoload.
+
+       * mm-decode.el (mm-insert-inline): Autoload.
+
+       * mml.el:
+       * message.el: Put some defvars in eval-when-compile.
+
+       * gnus-msg.el: Put some defvars in eval-when-compile.
+       (gnus-msg-mail): Move after gnus-setup-message.
+
+       * smiley-ems.el (smiley-data-directory, smiley-regexp-alist): Doc fix.
+
+2000-11-07  Dave Love  <fx@gnu.org>
+
+       * gnus-util.el (nnheader): Don't require message (recursive
+       autoload).
+
+       * uudecode.el: Avoid compiler warnings.
+
+       * rfc2047.el: (rfc2047-fold-region): Use gnus-point-at-bol.
+       (rfc2047-charset-encoding-alist): Add iso-8859-1[45].
+
+2000-11-06  Dave Love  <fx@gnu.org>
+
+       * gnus-salt.el (gnus-binary-mode): Fix call to gnus-add-minor-mode.
+
+       * uudecode.el: Use (featurep 'xemacs).  Require cl when compiling.
+       (uudecode-char-int): New alias, replacing char-int.
+       (uudecode-decode-region): Don't call buffer-disable-undo.
+
+;      * mm-uu.el (mm-uu-configure): Unquote lambda.
+;      (mm-uu-configure-list): Doc fix.
+;
+;      * earcon.el (running-xemacs): Don't define.
+;
+;2000-11-03  Stefan Monnier  <monnier@cs.yale.edu>
+;
+;      * message.el (message-font-lock-keywords): Match a final newline
+;      to help font-lock's multiline support.
+;
+2000-11-03  Dave Love  <fx@gnu.org>
+
+       * gnus-nocem.el (gnus-nocem-check-article-limit): Default to 500.
+
+       * mm-partial.el (mm-inline-partial): Space-prefix temp buffer
+       name.
+
+       * gnus-cus.el (gnus-group-parameters) <gcc-self>: Fix custom type.
+       <banner>: Fix custom type, doc.
+
+       * mm-decode.el (mm-display-external): Space-prefix temp buffer
+       name.  Don't disable undo explicitly.
+
+;2000-11-02  Dave Love  <fx@gnu.org>
+;
+;      * message.el (message-font-lock-keywords): Use [:alpha:] for
+;      cite-prefix.
+
+2000-11-01  Dave Love  <fx@gnu.org>
+
+       * rfc2047.el (base64): Require unconditionally.
+       (message-posting-charset): Defvar when compiling.
+       (rfc2047-encode-message-header, rfc2047-encodable-p): Require
+       message.
+
+       * gnus-sum.el (nnoo): Require.
+       (mm-uu-dissect): Autoload.
+
+       * mml.el (mml-parse-1): Clarify message.
+       (mml-minibuffer-read-type): Use mailcap-mime-types.
+
+2000-11-01  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * mml.el: Fix a typo in the requiring of CL.
+
+2000-11-01  Dave Love  <fx@gnu.org>
+
+       * utf7.el: Require cl when compiling.
+
+       * binhex.el: Use (featurep 'xemacs).
+       (binhex-char-int): New alias, replacing char-int.  Change callers.
+       (binhex-decode-region): Simplify work buffer code.
+       (binhex-decode-region-external): Use expand-file-name, not concat.
+
+2000-10-30  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el: Fix 2000-10-27 change properly.
+
+2000-10-28  Miles Bader  <miles@gnu.org>
+
+       * gnus-art.el (gnus-read-save-file-name): Remove extraneous paren.
+
+2000-10-27  Dave Love  <fx@gnu.org>
+
+       * gnus-group.el (gnus-group-make-menu-bar): Add some :help
+       strings.
+       (gnus-group-make-tool-bar): New function.
+       (gnus-group-mode): Use it.
+
+       * message.el (message-mode-menu): Add some :help strings.
+       (message-mode) [message-tool-bar-map]: Define tool-bar-map.
+       (featurep): Use (featurep 'xemacs).  Install tool bar for Emacs.
+
+       * catchup.xpm, exit-gnus.xpm, gnntg.xpm, subscribe.xpm:
+       * describe-group.xpm, get-news.xpm, kill-group.xpm:
+       * unsubscribe.xpm: New files.  Renamed icons from Luis Fernandes.
+
+       * mm-decode.el (mm-valid-and-fit-image-p): Don't test
+       display-graphic-p here.
+
+2000-10-27  Miles Bader  <miles@lsi.nec.co.jp>
+
+       * gnus-ems.el (gnus-ems-redefine): Use (featurep 'xemacs) instead
+       of the `gnus-xemacs' variable, as the latter has been removed.
+       * gnus-start.el (gnus-1, gnus-read-descriptions-file): Likewise.
+       * gnus-art.el (gnus-treat-display-xface)
+       (gnus-treat-display-smileys, gnus-treat-display-picons)
+       (gnus-article-read-summary-keys): Likewise.
+
+2000-10-26  Dave Love  <fx@gnu.org>
+
+       (defvar): Use rmail-spool-directory unconditionally.
+
+2000-10-18  Dave Love  <fx@gnu.org>
+
+       * mm-bodies.el (mm-uu-decode-function)
+       (mm-uu-binhex-decode-function): Defvar when compiling.
+
+       * gnus-nocem.el (gnus-nocem-issuers): Update.
+       (gnus-nocem-check-from): New option.
+       (gnus-nocem-scan-groups): Use it.
+       (gnus-nocem-check-article): Bind gnus-newsgroup-name.
+       (gnus-nocem-check-article-limit): Add :version.
+
+2000-10-16  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * ietf-drums.el (mm-util): Require CL when compiling.
+
+2000-10-15  Dave Love  <fx@gnu.org>
+
+       * qp.el: Require mm-util.
+
+2000-10-13  Dave Love  <fx@gnu.org>
+
+       * qp.el (quoted-printable-decode-region): Avoid invalid
+       coding-systems.
+
+2000-10-12  Gerd Moellmann  <gerd@gnu.org>
+
+       * mm-bodies.el: Don't require `mm-uu' at compile-time; it leads
+       to a recursive load.
+
+2000-10-12  Dave Love  <fx@gnu.org>
+
+       * mm-util.el (mm-charset-synonym-alist): Add windows-1252.
+
+       * gnus.el (gnus-group-startup-message): Check for PBM image.
+
+2000-10-09  Dave Love  <fx@gnu.org>
+
+       * mail-source.el (mail-source-fetch-imap): Bind
+       default-enable-multibyte-characters rather than using
+       mm-disable-multibyte.
+
+2000-10-05  Dave Love  <fx@gnu.org>
+
+       * qp.el (mm-decode-coding-region, mm-encode-coding-region):
+       Autoload.
+       (quoted-printable-decode-region):  Rename arg which confused
+       charset with coding-system.  Don't use nonascii-insert-offset.
+       Coding-system encode the region initially.  Don't recognize `=='
+       as valid QP.  Coding-system decode the region finally.
+       (quoted-printable-decode-string): Rename arg which confused
+       charset with coding-system.
+
+       * mm-bodies.el: Require mm-uu, Don't require qp, uudecode.
+       (mm-encode-body): Apply mm-charset-to-coding-system to arg of
+       mm-encode-coding-region.
+       (mm-decode-body, mm-decode-string): Rename variables which
+       confused charset with coding-system.
+       (binhex-decode-region): Don't autoload.
+       (mm-body-encoding): Require message.
+       (mm-decode-content-transfer-encoding): Require mm-uu in relevant
+       cond branches.
+
+       * gnus-art.el (article-de-quoted-unreadable)
+       (article-de-base64-unreadable): Fold search case
+       rather than downcasing string.  Apply mm-charset-to-coding-system
+       to arg of quoted-printable-decode-region.
+
+2000-10-04  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el: Don't turn off compiler warnings in local vars.
+       Require ring when compiling.
+       (gnus-article-compface-xbm): New variable.
+
+2000-10-04  Dave Love  <fx@gnu.org>
+
+       * smiley-ems.el (smiley-regexp-alist, smiley-update-cache): Use
+       pbm images.
+
+       * frown.pbm, smile.pbm, wry.pbm: New files.
+
+       * frown.xbm, smile.xbm, wry.xbm: Deleted.
+
+2000-10-03  Dave Love  <fx@gnu.org>
+
+       * mail-source.el (mail-sources): Revert to nil.
+
+       * nnmail.el (nnmail-spool-file): Revert to `((file))'.
+
+       * qp.el: Don't require mm-util.
+       (quoted-printable-decode-region): Rewritten.
+       (quoted-printable-decode-string, quoted-printable-encode-region):
+       Doc fix.
+       (quoted-printable-encode-region): Barf on multibyte characters.
+       Maybe make the class multibyte.  Upcase chars, not formatted
+       strings.  Allow mm-use-ultra-safe-encoding to be unbound.
+       (quoted-printable-encode-string): Don't use
+       mm-with-unibyte-buffer.
+
+2000-09-29  Gerd Moellmann  <gerd@gnu.org>
+
+       * smiley-ems.el (smiley-update-cache):  Use `:ascent center'.
+
+2000-09-21  Dave Love  <fx@gnu.org>
+
+       * smiley-ems.el (smiley-region): Test if display-graphic-p bound
+       (for Emacs 20).  Tidy somewhat.
+
+2000-09-21  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el (gnus-article-display-xface): Use unibyte for the
+       image processing.  Rationalize logic somewhat.
+
+2000-09-20  Dave Love  <fx@gnu.org>
+
+       * gnus-start.el (gnus-1) <gnus-simple-splash>: Don't test for X
+       specifically.
+
+       * gnus.el (gnus-version-number): Avoid some redundant
+       autoloads.
+
+2000-09-20  Gerd Moellmann  <gerd@gnu.org>
+
+       * gnus-ems.el (gnus-article-display-xface): Don't convert PBM
+       to XBM; we always have PBM support.
+
+2000-09-14  Dave Love  <fx@gnu.org>
+
+       * gnus.el (gnus-charset):
+       * mm-decode.el (mime-display):
+       * imap.el (imap) <defgroup>: Add :version.
+
+2000-09-13  Gerd Moellmann  <gerd@gnu.org>
+
+       * parse-time.el: Fix author's mail address.
+
+       * earcon.el, flow-fill.el, gnus-cite.el, gnus-gl.el, gnus-ml.el:
+       * gnus-mlspl.el, gnus-nocem.el, gnus-range.el, gnus-salt.el:
+       * gnus-setup.el, gnus-soup.el, gnus-undo.el, gnus-vm.el:
+       * messcompat.el, nnbabyl.el, nndir.el, nneething.el:
+       * nngateway.el, nnheaderxm.el, nnkiboze.el, nnlistserv.el:
+       * nnmbox.el, nnmh.el, nnoo.el, nnsoup.el, nnspool.el, rfc2045.el:
+       * rfc2231.el, uudecode.el: Fix copyright notice.
+
+       * nnweb.el (toplevel): To make the file bootstrap in Emacs,
+       require `w3' at load-time only if not running in batch mode.
+
+2000-12-19 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el: Before merge with Emacs21.
+
+2000-12-19  Raymond Scholz  <ray-2000@zonix.de>
+
+       * gnus-art.el (gnus-article-dumbquotes-map): Add EUR symbol.
+
+2000-12-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * mml.el (mml-mode-map): Change mml prefix from `M-m' to `C-c C-m'
+       to avoid conflict with the standard `back-to-indentation'
+       binding.
+
+2000-12-17 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-extern.el (mm-inline-external-body): g-a-m-h may be a handle.
+
+       * mm-util.el (mm-enable-multibyte-mule4): Test charsetp.
+       (mm-disable-multibyte-mule4): Ditto.
+       (mm-with-unibyte-current-buffer-mule4): Ditto.
+
+2000-12-15 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * pop3.el (pop3-movemail): Use binary.
+       (pop3-movemail-file-coding-system): Removed.
+
+2000-12-14 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-synonym-alist): Add cn-gb.
+
+2000-12-13 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnspool.el (nnspool-lib-dir): Check whether /usr/lib/news/active
+       exists.
+
+2000-12-13 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-post-method): Use backend name when the
+       address is "".
+
+2000-12-08 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-verify-x-pgp-sig): Don't test
+       mm-verify-option.
+       (gnus-treat-x-pgp-sig): Default value.
+       (gnus-ignored-headers): Redundant.
+
+2000-12-04 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-configure-frame): Save selected window.
+
+2000-02-15  Andrew Innes  <andrewi@gnu.org>
+
+       * nnmbox.el: Require gnus-range.
+       (nnmbox-group-building-active-articles): New variable.
+       (nnmbox-group-active-articles): New variable; this is a cache of
+       all active articles by group and number.
+       (nnmbox-in-header-p): New function.
+       (nnmbox-find-article): New function.
+       (nnmbox-record-active-article): New function.
+       (nnmbox-record-deleted-article): New function.
+       (nnmbox-is-article-active-p): New function.
+       (nnmbox-retrieve-headers): Use nnmbox-find-article.
+       (nnmbox-request-article): Ditto.  Also supply extra arg to
+       nnmbox-article-group-number.
+       (nnmbox-request-expire-articles): Ditto.
+       (nnmbox-request-move-article): Ditto.
+       (nnmbox-request-replace-article): Ditto.
+       (nnmbox-request-rename-group): Rename group entry in active
+       article cache.
+       (nnmbox-delete-mail): Update active article cache, unless article
+       is being replaced.
+       (nnmbox-possibly-change-newsgroup): Call nnmbox-read-mbox, rather
+       than partially duplicating it.
+       (nnmbox-article-group-number): Add extra `this-line' arg, to
+       handle articles belonging to multiple groups.
+       (nnmbox-save-mail): Update active article cache.
+       (nnmbox-read-mbox): Build active article cache when loading mbox.
+       Also do some repair work, if we find articles that are missing the
+       appropriate X-Gnus-Newsgroup lines in the header.  We can usually
+       reconstruct these from Xref info.
+
+2000-12-04 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-report-new-mail): Use
+       nnheader-run-at-time.
+
+2000-02-15  Andrew Innes  <andrewi@gnu.org>
+
+       * mail-source.el (mail-source-fetch-pop): Clear pop password when
+       an error is thrown, and then rethrow the error.
+       (mail-source-check-pop): Ditto.
+       (mail-source-start-idle-timer): Prevent multiple pop checks
+       running if the check takes a long time.
+
+2000-12-04 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-msg-mail): COMPOSEFUNC should return t if
+       succeed.
+
+2000-12-04 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-configure-windows): Make sure
+       nntp-server-buffer is live.
+       (gnus-remove-some-windows): switch-to-buffer -> set-buffer.
+
+2000-11-21  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * gnus-win.el (gnus-configure-windows): switch-to-buffer -> set-buffer.
+
+2000-12-04  Andreas Jaeger  <aj@suse.de>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Fix typos in description.
+
+2000-12-03 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-fix-micalg): Alg might be nil.
+
+2000-12-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Trivial patch from Christopher Splinter  <chris@splinter.inka.de>
+
+       * gnus-sum.el (gnus-summary-limit-to-age): Fix typo.
+
+2000-12-01  Simon Josefsson  <sj@extundo.com>
+
+       * mml-smime.el (mml-smime-verify): Fix address parsing.
+
+2000-12-01  Simon Josefsson  <sj@extundo.com>
+
+       * mml-smime.el (mml-smime-verify): Don't modify MM buffer.  Handle
+       more than one certificate inside PKCS#7 blob.  Better security
+       information (clamed / actual sender, openssl output, certificates
+       inside message).
+
+       * smime.el (smime-verify-region): Output to /dev/null.
+       (smime-buffer-as-string-region): Don't parse empty lines.
+
+2000-11-30 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-security-button-line-format-alist): Add
+       ?d and ?D.
+       (gnus-mime-security-show-details-inline): New variable.
+       (gnus-mime-security-show-details): Use them.
+       (gnus-insert-mime-security-button): Ditto.
+
+       * mml2015.el (mml2015-gpg-verify): Set details when succeed.
+       Suggest by Michael Duggan (md5i@cs.cmu.edu).
+       (mml2015-gpg-clear-verify): Ditto.
+       (mml2015-gpg-decrypt-1): Ditto.
+       (mml2015-use): Prefer 'gpg.
+
+2000-11-30 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-add-text-properties-when): New function.
+       (gnus-remove-text-properties-when): Ditto.
+
+       * gnus-cite.el (gnus-article-hide-citation): Use them.
+       (gnus-article-toggle-cited-text): Use them.
+
+       * gnus-art.el (gnus-signature-toggle): Use them.
+       (gnus-article-show-hidden-text): Ditto.
+       (gnus-article-hide-text): Ditto.
+
+2000-11-30 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-charset-region): Remove eight-bit-*.
+
+2000-11-30  Simon Josefsson  <sj@extundo.com>
+
+       * smime.el (smime-point-at-eol): New alias.
+       (smime-buffer-as-string-region): Use it.
+
+2000-11-29 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndraft.el (nndraft-request-restore-buffer): Remove Date field.
+
+2000-11-29 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-expire-articles): expiry-target.
+
+       * nnbabyl.el (nnbabyl-request-expire-articles): Ditto.
+
+       * nnmbox.el (nnmbox-request-expire-articles): Ditto.
+
+2000-11-22  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+       * nnmh.el (nnmh-request-expire-articles): Implemented
+       expiry-target for nnmh backend.
+
+2000-11-30  Simon Josefsson  <sj@extundo.com>
+
+       * mm-decode.el (mm-security-from): New variable.
+       (mm-possibly-verify-or-decrypt): Use it rather than `from'.
+
+       * mml-smime.el (mml-smime-verify): Use `mm-security-from' rather
+       than `from'.
+
+2000-11-30  Simon Josefsson  <sj@extundo.com>
+
+       * mml-smime.el (mml-smime-verify): Verify that certificate mail
+       address match sender address.
+
+       * mm-decode.el (mm-possibly-verify-or-decrypt): Bind sender address.
+
+       * smime.el (smime-verify-region): Don't copy buffer.
+       (smime-decrypt-buffer): Use expand-file-name on keyfile.
+       (smime-pkcs7-region): New function.
+       (smime-pkcs7-certificates-region): Ditto.
+       (smime-pkcs7-email-region): Ditto.
+       (smime-buffer-as-string-region): Ditto.
+
+       * gnus-art.el (gnus-mime-security-show-details): Goto beginning of
+       buffer.
+
+2000-11-23  Jens Krinke  <j.krinke@gmx.de>
+
+       * smime.el (smime-decrypt-region): Fix keyfile argument.
+
+2000-11-29 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-cache-accepted-message-ids): Add doc.
+
+2000-11-28 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-shoot-gnksa-feet): New variable.
+       (message-gnksa-enable-p): New function.
+       (message-send): Use it.
+       (message-check-news-body-syntax): Ditto.
+
+2000-11-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.el (message-make-message-id): Remove the redundancy.
+
+2000-11-22 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-setup): Discourage using mc-install-*-mode.
+
+       * gnus-setup.el (gnus-use-mailcrypt): Don't hook mail-crypt.
+
+2000-11-22 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cite.el (gnus-cite-parse): Guess citation length.
+
+2000-11-22 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el (gnus-mailing-list-insinuate): New function.
+
+2000-11-22 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el (gnus-mailing-list-archive): Find the real url.
+
+2000-11-22 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-article-display-xface): Use
+       insert-buffer-substring.
+
+       * message.el (message-send-mail): Use buffer-substring-no-properties.
+       (message-send-news): Ditto.
+
+2000-11-22  David Edmondson  <dme@dme.org>
+
+       * imap.el (imap-wait-for-tag): Message read info.
+
+2000-11-21 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-encrypt): Ensure the part is encrypted.
+       (mml2015-mailcrypt-encrypt): Use unibyte-buffer.
+       (mml2015-gpg-encrypt): Ditto.
+
+2000-11-21 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-verify-option): Default value.
+
+       * mml-sec.el (mml-secure-part): Error message.
+
+2000-11-20 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el (gnus-mailing-list-archive): Use browse-url.
+
+2000-11-20 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-make-menu-bar): Use easy-menu-add.
+
+2000-11-20 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-describe-key): Use prompt.
+       (gnus-article-describe-key-briefly): Ditto.
+
+2000-11-20 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-expire): Ignore corrupted history.
+
+2000-11-20 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-describe-key): New function.
+       (gnus-article-describe-key-briefly): New function.
+
+2000-11-19 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-decrypt-option): Doc typo.
+
+       * gnus-art.el (gnus-article-read-summary-keys): lookup-key may
+       return a number.
+
+2000-11-19 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-newline-and-reformat): Typo.
+
+2000-11-19 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-verify-x-pgp-sig): Check whether
+       original-article-buffer exists.
+
+       * rfc2047.el (rfc2047-q-encoding-alist): Match Resent-.
+       (rfc2047-header-encoding-alist): Addresses are different from text.
+       (rfc2047-encode-message-header): Ditto.
+       (rfc2047-dissect-region): Extra parameter.
+       (rfc2047-encode-region): Ditto.
+       (rfc2047-encode-string): Ditto.
+
+2000-11-19 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-pgp-encrypted-extract-1): New function.
+       (mm-uu-pgp-encrypted-extract): Use it.
+       (mm-uu-pgp-signed-extract-1): New function.
+       (mm-uu-pgp-signed-extract): Use it.
+
+       * gnus-art.el (gnus-mime-display-security): New function.
+       (gnus-mime-display-part): Use it.
+       (gnus-mime-security-verify-or-decrypt): New function.
+       (gnus-mime-security-press-button): New function.
+       (gnus-insert-mime-security-button): Use it.
+
+       * mm-decode.el (mm-possibly-verify-or-decrypt): Use mm-h-m-c-p.
+       (mm-find-raw-part-by-type): Ditto.
+       (mm-verify-function-alist): Add x-gnus-pgp-signature handle.
+       (mm-decrypt-function-alist): Add x-gnus-pgp-encrypted handle.
+       (mm-destroy-parts): Kill nested multibyte buffer.
+
+       * mml2015.el (mml2015-mailcrypt-verify): Use mm-h-m-c-p.
+       (mml2015-gpg-verify): Ditto.
+
+2000-11-18  Simon Josefsson  <sj@extundo.com>
+
+       * mml2015.el (mml2015-mailcrypt-clear-verify): New function.
+       (mml2015-function-alist): Use it.
+
+       * mml-sec.el (mml-sign-alist): Update names.
+       (mml-encrypt-alist): Ditto.
+       (mml-secure-part-smime-sign): Moved to mml-smime.el
+       as `mml-smime-sign-query'.
+       (mml-secure-part-smime-encrypt-by-file): Moved to mml-smime.el as
+       `mml-smime-get-file-cert'.
+       (mml-secure-part-smime-encrypt-by-dns): Moved to mml-smime.el as
+       `mml-smime-get-dns-cert'.
+       (mml-secure-part-smime-encrypt): Moved to mml-smime.el as
+       `mml-smime-encrypt-query'.
+       (mml-smime-sign-buffer): Use mml-smime-sign.
+       (mml-smime-encrypt-buffer): Use mml-smime-encrypt.
+
+       * mml-smime.el (mml-smime-sign): New function.
+       (mml-smime-encrypt):
+       (mml-smime-sign-query):
+       (mml-smime-get-file-cert):
+       (mml-smime-get-dns-cert):
+       (mml-smime-encrypt-query): Moved from mml-sec.el.
+
+2000-11-16  Simon Josefsson  <sj@extundo.com>
+
+       * mml2015.el (mml2015-gpg-clear-verify): New function.
+       (mml2015-function-alist): Add it.
+
+2000-11-17 14:21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-setup-fill-variables): Use
+       message-cite-prefix-regexp.
+       (message-newline-and-reformat): Check the end of citation, leading
+       WSP, break in the cite prefix.
+       (message-fill-paragraph): New function.
+
+2000-11-17 13:44  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Shut up.
+
+2000-11-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): No longer allow
+       raw 8-bit in headers in dk.* newsgroups.
+
+2000-11-17 08:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-newline-and-reformat): Match extra WSPs.
+
+2000-11-16 23:31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Ignore ascii.
+
+2000-11-16 Justin Sheehy  <justin@iago.org>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Fix menu items.
+
+2000-11-16 17:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-cite-prefix-regexp): Prefix should not end
+       at space.
+
+2000-11-15 18:09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mode-syntax-table): Add - as a word
+       constituent as in articles.
+       (message-setup-fill-variables): Add -_. as supercite-style prefix.
+       * gnus-art.el (gnus-article-mode-syntax-table): Remove ?-.
+       * gnus-cite.el (gnus-cite-parse): Match from the beginning of line.
+
+2000-11-15 13:21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-do-gcc): Expire the article.
+
+2000-11-12  David Edmondson  <dme@dme.org>
+
+       * message.el (message-font-lock-keywords): use
+       message-cite-prefix-regexp.
+
+2000-11-15  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-group.el (gnus-group-jump-to-group-prompt): New variable by
+       Stein Arild Str\e,Ax\e(Bmme.
+       (gnus-group-jump-to-group): Use it.
+       (gnus-group-jump-to-group-prompt): Customize.
+
+2000-11-14 10:32:42  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-possible-viewers): Match the entire string.
+
+2000-11-14 10:20:56  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-verify): replace-match is
+       incompatible.
+       (mml2015-mailcrypt-sign): Ditto.
+
+2000-11-14 10:12:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-do-gcc): Update summary data when the
+       group is open.
+
+2000-11-14 00:48:52  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-bcklg.el (gnus-backlog-enter-article): Don't enter
+       nnvirtual articles.
+       (gnus-backlog-request-article): Don't request nnvirtual articles.
+
+2000-11-13 22:08:09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-sign): Remove "-" escape.
+       * mml.el (mml-generate-mime-1): Save cont. skip multipart attributes.
+
+2000-11-13 20:43:37  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-get-part): Don't call mm-insert-part.
+       * mml.el (mml-generate-mime-1): Use charset attribute.
+       * mm-bodies.el (mm-encode-body): Add parameter charset.
+       * mm-util.el (mm-mime-charset): Show error when find 8-bit characters.
+
+2000-11-13 16:09:09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-decrypt): Handle quit.
+       (mml2015-mailcrypt-clear-decrypt): Ditto.
+       (mml2015-mailcrypt-verify): Ditto.
+       (mml2015-mailcrypt-clear-verify): Ditto.
+       (mml2015-gpg-verify): Ditto.
+
+2000-11-13 15:29:58  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * smime.el (smime-openssl-program): Test the existence of openssl.
+       * mml-smime.el: Require mm-decode.
+       (mml-smime-verify-test): New function.
+       * mm-decode.el (mm-verify-function-alist): Use it.
+
+2000-11-13 09:50:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-repair-multipart): Fix Mime-Version
+       anyway.
+
+2000-11-13  Simon Josefsson  <sj@extundo.com>
+
+       * mm-uu.el (mm-uu-pgp-signed-extract): Explain why clear
+       verification doesn't work.
+
+2000-11-12 23:36:45  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-mark-gcc-as-read): New variable.
+       (gnus-inews-do-gcc): Use it.
+
+2000-11-12 21:35:04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2231.el (rfc2231-encode-string): Insert semi-colon and
+       leading space.
+       * mm-extern.el (mm-inline-external-body): Report error when no
+       access-type.
+
+2000-11-12 19:48:30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-select-newsgroup): Change the error message.
+
+2000-11-12 11:53:18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-button-menu): Use select-window.
+
+2000-11-12 09:47:54  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-part): Display multipart/related
+       as multipart/mixed.
+
+2000-11-12  David Edmondson  <dme@dme.org>
+
+       * message.el (message-cite-prefix-regexp): moved from gnus-cite.el
+       and replace `.' with `\w' to allow for different syntax tables
+       (from Vladimir Volovich).
+       * message.el (message-newline-and-reformat): use
+       `message-cite-prefix-regexp'.
+       * gnus-cite.el (gnus-supercite-regexp): use
+       `message-cite-prefix-regexp'.
+       * gnus-cite.el (gnus-cite-parse): use
+       `message-cite-prefix-regexp'.
+
+2000-11-12 08:52:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-verify): Replace armors with
+       PGP SIGNATURE.  Escape leading "-"'s.
+       (mml2015-mailcrypt-sign): Replace armors with PGP MESSAGE.
+
+2000-11-11 15:55:35  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-type-alist): Stricter shar regexp.
+
+2000-11-11  Simon Josefsson  <sj@extundo.com>
+
+       * mml2015.el (mml2015-gpg-verify): Set "OK" security status.
+
+       * smime.el (smime-details-buffer): New variable.
+       (smime-sign-region):
+       (smime-encrypt-region):
+       (smime-verify-region):
+       (smime-decrypt-region): Copy OpenSSL output to the buffer.
+
+       * mml-smime.el (mml-smime-verify): Support security info.
+
+2000-11-10 17:11:22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-verify-option): Set default to nil.
+       (mm-decrypt-option): Ditto.
+       * gnus-art.el (article-verify-x-pgp-sig): New function.
+
+2000-11-10 09:01:25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-alternative): Show button if no
+       preferred part.
+
+2000-11-07  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-move-split-methods): Say that
+       `gnus-split-methods' uses file names, whereas this uses group
+       names.  (Report from Nevin Kapur)
+
+2000-11-10 01:23:20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-partial.el (mm-inline-partial): Insert MIME-Version.
+
+2000-11-09 17:02:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-directory-files-is-safe): New variable.
+       (nnheader-directory-articles): Use it.
+       (nnheader-article-to-file-alist): Ditto.
+
+2000-11-09 16:20:37  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-pad-base64): New function.
+       (rfc2047-decode): Use it.
+
+2000-11-09 08:53:04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Bind the original
+       select method.
+
+2000-11-08 19:58:58  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-gpg-decrypt-1):
+       (mml2015-gpg-verify): buffer-string has no argument in Emacs.
+
+2000-11-08 16:37:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-cache-generate-nov-databases): Reopen cache.
+
+2000-11-08 08:38:30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * pop3.el (pop3-munge-message-separator): A message may have an
+       empty body.
+
+2000-11-07 18:02:26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-type-alist): Don't test pgp stuff.
+       (mm-uu-pgp-encrypted-extract): Clean mml2015 buffer.
+       (mm-uu-pgp-signed-extract): Use coding-system.
+
+2000-11-07 14:33:19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-part): Show MIME security button.
+       (gnus-insert-mime-security-button): New function.
+       * mm-decode.el (mm-possibly-verify-or-decrypt): Add security info.
+       * mml2015.el:  Add security info when verify or decrypt.
+       * mm-uu.el (mm-uu-pgp-signed-extract): Use multipart.
+       (mm-uu-pgp-encrypted-extract): Ditto.
+
+2000-11-07 08:49:36  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-parts): New function.
+       * gnus-art.el (gnus-mime-view-all-parts): Use it. Remove parts first.
+
+2000-02-02  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
+
+       * gnus-mlspl.el: Documentation tweaks.
+
+2000-11-06 22:06:44  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-possibly-verify-or-decrypt): Fix.
+       * gnus-art.el (gnus-article-encrypt-body): Rename and support prefix
+       argument.
+
+2000-11-06 19:10:14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2231.el (rfc2231-encode-string): Use us-ascii if charset is nil.
+
+2000-11-06 18:17:53  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-encrypt): New function.
+       (gnus-article-encrypt-protocol-alist): New variable.
+       (gnus-article-encrypt-protocol): New variable.
+       * mml2015.el (mml2015-self-encrypt): New function.
+       (mml2015-mailcrypt-encrypt): Set mc-pgp-always-sign.
+
+2000-11-06 16:02:52  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-gpg-key-skip-to-last): New function.
+       (mm-uu-pgp-key-extract): Use application/pgp-keys, don't snarf,
+       let mailcap do it.
+       * mml2015.el: Remove snarf code.
+       * mm-decode.el: Remove snarf code.
+
+2000-11-06 14:03:10  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-insert-mml-markup): Ignore internal stuff.
+       (mml-insert-mime): Understand gnus-decoded.
+       (mime-to-mml): New parameter handles.
+       * gnus-art.el (gnus-mime-save-part-and-strip): Use it.
+       * gnus-sum.el (gnus-summary-edit-article): Add argument `3'.
+
+2000-11-06 13:51:37  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mime-security): New group.
+       (mm-verify-function-alist): Add test function.
+       (mm-decrypt-function-alist): Ditto.
+       (mm-snarf-option): Set default value as nil.
+       (mm-find-part-by-type): Recursive parameter.
+       (mm-possibly-verify-or-decrypt): Support draft-ietf-openpgp-multsig.
+       * mml2015.el: Support draft-ietf-openpgp-multsig.
+
+2000-11-06 13:01:27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-view-part-as-charset): New function.
+       (gnus-article-view-part-as-charset): New function.
+
+2000-11-05 22:34:07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-verify-option): Default value.
+       (mm-possibly-verify-or-decrypt): Dealing with broken messages.
+
+2000-11-05 15:06:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnvirtual.el (nnvirtual-request-expire-articles): Uncompress range.
+
+2000-11-05  Simon Josefsson  <sj@extundo.com>
+
+       * mml-smime.el (mml-smime-verify): Work in original multipart
+       buffert.
+
+       * mm-decode.el (mm-handle-multipart-original-buffer): New macro.
+       (mm-handle-multipart-ctl-parameter): Ditto.
+       (mm-alist-to-plist): New function.
+       (mm-dissect-buffer): Store CTL parameters and copy original buffer
+       for multiparts.
+       (mm-destroy-parts): Destroy multipart buffert.
+       (mm-remove-part): Ditto.
+
+       * mml-smime.el (mml-smime-sign): Not used.
+       (mml-smime-encrypt): Ditto.
+
+       * mm-decode.el (mml-smime-verify): Autoload mml-smime.
+
+       Verify S/MIME signature support.
+
+       * mm-decode.el (mm-inline-media-tests): Add
+       application/{x-,}pkcs7-signature.
+       (mm-inlined-types): Ditto.
+       (mm-automatic-display): Ditto.
+       (mm-verify-function-alist): Ditto.  Add name of method.
+       (mm-decrypt-function-alist): Add name of method.
+       (mm-find-part-by-type): Add documentation.
+       (mm-possibly-verify-or-decrypt): Use new format of
+       mm-{verify,decrypt}-function-alist.  Use method names.
+
+       * mml-smime.el (mml-smime-verify): New function.
+
+2000-11-04 20:38:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Move point to the end of inserted text.
+
+2000-11-04 19:07:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-function-alist): Clear verify and decrypt.
+       * mm-uu.el: Reorganized.  Add gnatsweb, pgp-signed, pgp-encrypted.
+       * mm-decode.el (mm-snarf-option): New variable.
+
+2000-11-04 13:08:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-subst-char-in-string): New function.
+       (mm-replace-chars-in-string): Use it.
+       * message.el (message-replace-chars-in-string): Use it.
+       * nnheader.el (nnheader-replace-chars-in-string): Use it.
+       * gnus-mh.el (mh-lib-progs): Shut up.
+
+2000-11-04  ShengHuo Zhu  <zsh@cs.rochester.edu>
+
+       * base64.el, md5.el: Moved to contrib directory.
+
+2000-11-04 11:13:56  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-search-article-forward): Don't move
+       the last article when search.
+
+2000-11-04 10:34:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-pathname-coding-system): Default iso-8859-1.
+       * nnmail.el (nnmail-pathname-coding-system): Ditto.
+
+2000-09-29  David Edmondson  <dme@thus.net>
+
+       * message.el (message-newline-and-reformat): Typo.
+
+2000-11-04 10:11:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2231.el (rfc2231-decode-encoded-string): Test mm-multibyte-p.
+
+2000-11-04 09:53:42  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-decode-text): Delete bogus status lines.
+
+2000-11-03  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * message.el (message-font-lock-keywords): Match a final newline
+       to help font-lock's multiline support.
+
+2000-11-04 09:11:44  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnoo.el (nnoo-set): New function.
+
+2000-11-04  ShengHuo Zhu  <zsh@cs.rochester.edu>
+
+       * gpg.el, gpg-ring.el: Moved to contrib directory.
+
+2000-11-04  Simon Josefsson  <sj@extundo.com>
+
+       * nnimap.el (nnimap-split-inbox): Typo.
+
+2000-11-03 10:46:44  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-msg-mail): Move it backwards.
+
+2000-11-03  Simon Josefsson  <sj@extundo.com>
+
+       * rfc2231.el (rfc2231-parse-qp-string): New function.
+       (require): rfc2047.
+
+       * mail-parse.el (mail-header-parse-content-type):
+       (mail-header-parse-content-disposition): Support invalid QP
+       encoded strings, by using `rfc2231-parse-qp-string'.
+
+2000-11-03 08:58:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2231.el (rfc2231-parse-string): Decode when there is no number.
+       (rfc2231-decode-encoded-string): Typo "> X 1".
+       (rfc2231-encode-string): Insert the name of charset.
+       * mail-parse.el (mail-header-encode-parameter): Use RFC2231.
+
+2000-11-02 23:35:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-save-part): Return the filename.
+       * gnus-sum.el (gnus-summary-edit-article): Remove a hack.
+       * gnus-art.el (gnus-mime-save-part-and-strip): New function.
+       (gnus-mime-action-alist): Use it.
+       (gnus-mime-button-commands): Use it.
+       * mm-extern.el (mm-extern-local-file): Error when the file is gone.
+       (mm-inline-external-body): unwind-protect.
+
+2000-11-02 21:08:49  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-insert-mime-button): Show url.
+
+2000-11-02 19:51:19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Support external url.
+       * nnwarchive.el (nnwarchive-mail-archive-article): Use external url.
+
+2000-11-02 16:53:32  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-partial.el (mm-inline-partial): Buffer name with a leading space.
+       * mm-decode.el (mm-display-external): Ditto.
+       * mm-extern.el: New file.
+       * mm-decode.el (mm-inline-media-tests): Hook it up.
+       (mm-inlined-types): Inline message/external-body.
+
+2000-11-02  Simon Josefsson  <sj@extundo.com>
+
+       * gnus-art.el (gnus-visible-headers): Add Mail-Followup-To.
+
+       * message.el (message-get-reply-headers): Better handling when
+       Mail-Followup-To is very large.
+
+2000-11-02 13:27:56  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-uu.el (gnus-uu-post-news): Comment out the redundancy.
+       * gnus-art.el (gnus-article-edit-done):
+       * gnus-sum.el (gnus-summary-edit-article-done): Move line
+       counting code here.
+       * gnus-msg.el (gnus-setup-message): Remove a hack.
+
+2000-11-02 09:33:01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-newsgroup-variables): New variable.
+       (gnus-summary-mode): Make them local variables.
+       (gnus-set-global-variables): Globalize them.
+       (gnus-summary-exit): Kill them.
+
+2000-11-02  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * rfc2047.el (rfc2047-encoded-word-regexp): Allow empty encoded
+       word.
+
+2000-11-01 10:07:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-part): Add to signed or encrypted.
+       gnus-article-wash-types.
+       * gnus-art.el (gnus-article-wash-status): Use them.
+
+2000-11-01 08:54:11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-read-tag): Remove spaces and LF.
+
+2000-11-01 08:01:03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-encrypt): Use from and sign parameters.
+       * mml.el (mml-generate-mime-1): Add sender and recipients attributes.
+
+2000-11-01 07:39:24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-force-verify-and-decrypt): New function.
+
+2000-10-31 22:06:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-article-charset): New variable.
+       (gnus-summary-display-article): Set it.
+       * gnus-msg.el (gnus-copy-article-buffer): Use it.
+       * gnus-art.el (gnus-article-mode): Make it local variable.
+
+2000-11-01 01:12:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-create-mapping): Use nreverse.
+
+2000-10-31 23:45:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnwfm.el: New file.
+
+       * nnweb.el (nnweb-replace-in-string): New function.
+
+2000-10-31 17:32:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el: Wrap gpg.el.
+       * gpg.el (gpg-verify): The last argument of apply is a list.
+       (gpg-encrypt): Add passphrase as a parameter.
+
+2000-10-31 17:28:45  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gpg.el: New file.
+       * gpg-ring.el: New file.
+
+2000-10-31 11:44:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): Fix the summary line.
+
+2000-10-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-summary-insert-line): Work with quoted
+       double-quote characters.
+       (gnus-summary-prepare-threads): Ditto.
+
+2000-10-31 08:36:03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-single): Forward line -1.
+       * mml.el (mml-read-tag): Don't skip the leading space.
+       * lpath.el (font-lock-set-defaults): Shut up.
+
+2000-10-31 00:04:35  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el: Fix doc. Remove bogus mml2015-setup.
+
+2000-10-30 23:37:07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encode-region): Replace leading - when
+       ultra safe.
+       * mml.el (mml-generate-mime-postprocess-function): Removed.
+       (mml-postprocess-alist): Removed.
+       (mml-generate-mime-1): Use ultra-safe when sign.
+       * mml2015.el (mml2015-fix-micalg): Uppercase.
+       (mml2015-verify): Insert LF.
+       (mml2015-mailcrypt-sign): Downcase; search backward.
+
+2000-10-16 11:36:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-forum-table-p): Be a bit more
+       restrictive.
+       (nnultimate-table-regexp): New variable.
+       (nnultimate-forum-table-p): Use it.
+
+2000-10-30  Ed L Cashin  <ecashin@coe.uga.edu>
+       Trivial patch.
+
+       * gnus-sum.el (gnus-summary-expire-articles): Save point.
+
+2000-10-30 08:52:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml-sec.el (mml-pgpmime-sign-buffer): Use mml2015-sign.
+       (mml-pgpmime-encrypt-buffer): Use mml2015-encrypt.
+
+2000-10-30 08:38:12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el: Shut up.
+
+2000-10-30 08:17:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-server-browse-hashtb): Removed.
+       * gnus-group.el (gnus-group-prepare-flat-list-dead): Use gnus-active.
+       (gnus-group-insert-group-line-info): Use simplified method.
+       * gnus-srvr.el (gnus-browse-foreign-server): Use gnus-set-active.
+
+2000-10-30 01:52:40  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-union): Renamed from gnus-agent-union, and
+       moved here.
+       * gnus-agent.el (gnus-agent-fetch-headers): Use it.
+       * gnus-group.el (gnus-group-prepare-flat): Use it.
+       * gnus-topic.el (gnus-group-prepare-topics): Use it.
+
+2000-10-30 01:23:49  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-mode): Show menu in XEmacs.
+
+2000-10-30 00:49:33  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-server-browse-in-group-buffer): New variable.
+       (gnus-server-read-server-in-server-buffer): New function.
+       (gnus-browse-foreign-server): Browse in group buffer.
+       * gnus-group.el (gnus-group-prepare-flat): List group not in list.
+       (gnus-group-prepare-flat-list-dead): Use gnus-group-insert-group-line.
+       * gnus-topic.el (gnus-group-prepare-topics): Ditto.
+       * gnus.el (gnus-server-browse-hashtb): New variable.
+
+2000-10-29 22:31:40  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-open-nov): Use group.
+
+2000-10-29 17:23:15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el: Add NOV. Set version to 2.0.
+       (nnfolder-nov-is-evil): If non-nil, nnfolder acts like 1.0.
+
+2000-10-29 10:35:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el (mml2015-mailcrypt-sign): Use mc-sign-generic.
+
+2000-10-29 09:42:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Show level mark.
+       (gnus-browse-unsubscribe-group): Unsubscribed is not killed.
+
+2000-10-29 08:28:58  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-read-folder): Don't goto point-min.
+
+2000-10-28 19:11:01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-verify-function-alist): New variable.
+       (mm-verify-option): New variable.
+       (mm-decrypt-function-alist): Ditto.
+       (mm-decrypt-option): Ditto.
+       (mm-find-raw-part-by-type): New function.
+       (mm-possibly-verify-or-decrypt): New function.
+       (mm-dissect-multipart): Use it.
+       * mml2015.el (mml2015-fix-micalg): New function.
+       (mml2015-decrypt): Use new interface.
+       (mml2015-verify):  Use new interface.
+       (mml2015-setup): Make it bogus.
+
+2000-10-28 16:54:45  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-postprocess-function): Set to
+       mml-postprocess.
+       (autoload): Autoload mml2015 and mml-smime.
+       (mml-postprocess-alist): Use mml2015-sign and mml2015-encrypt.
+       * mml2015.el (mml2015-encrypt): New function.
+       (mml2015-sign): New function.
+       (mml2015-encrypt-function): New variable.
+       (mml2015-sign-function): New variable.
+       (mml2015-mailcrypt-encrypt): Use message-recipients.
+       (mml2015-setup): Don't set mml-generate-mime-postprocess-function.
+       * mml-smime.el (mml-smime-setup): Ditto.
+
+2000-10-28  Simon Josefsson  <sj@extundo.com>
+
+       * imap.el (imap-parse-resp-text-code): Workaround bug in Stalker
+       Communigate Pro 3.3.1 server.
+
+       * mml-sec.el (mml-smime-encrypt-buffer): Support certfiles stored
+       in buffers.
+       (mml-secure-dns-server): Removed.
+       (mml-secure-part-smime-encrypt-by-dns): Use DIG interface.  Don't
+       write certificates to files.
+
+       * smime.el (smime-dns-server): New variable.
+       (smime-mail-to-domain):
+       (smime-cert-by-dns): New functions.
+
+       * dig.el: New file.
 
-Sat Sep 13 23:35:28 1997  Greg Stark  <gsstark@mit.edu>
+2000-10-28 10:09:41  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus-ems.el (gnus-x-splash): New function.
+       * message.el (message-options): New variable.
+       (message-options-set-recipient): New function.
+       (message-send): Use them.
+       * gnus-int.el (gnus-request-replace-article): Use them.
+       (gnus-request-accept-article): Ditto.
+       * mml.el (mml-preview): Use them.
+       * gnus-sum.el (gnus-summary-edit-article): Use them.
 
-Sat Sep 13 22:46:16 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.el (message-options-get): New function.
+       (message-options-get): New function.
+       * rfc2047.el (rfc2047-encode-message-header): Use them.
+       * mm-bodies.el (mm-encode-body): Use them.
 
-       * gnus-start.el (gnus-1): Use it.
+2000-10-28  Simon Josefsson  <sj@extundo.com>
 
-       * gnus-ems.el (gnus-decode-coding-string): New alias.
+       * nnimap.el (nnimap-retrieve-which-headers):
+       (nnimap-request-article-part): Quote message-id.
 
-       * message.el (message-unix-mail-delimiter): Dox fox.
+       * smime.el (smime-CA-directory): Rename from `smime-CAs'.
+       (smime-CA-file): New variable.
+       (smime-call-openssl-region): Don't error.
+       (smime-sign-region): Return result value.
+       (smime-encrypt-region): Ditto.
+       (smime-verify-region): New function.
+       (smime-decrypt-region): Ditto.
+       (smime-verify-buffer): Ditto.
+       (smime-decrypt-buffer): Ditto.
 
-       * nnmh.el (nnmh-request-list-1): Don't use coding system.
+       * mml.el: Require mml-sec.
+       (mml-generate-mime-1): Support "sign" and "encrypt" MML tags.
+       (mml-mode-map): Add "sign" and "encrypt" maps.
+       (mml-menu): Add security menu.
+       (mml-preview): Use generate-new-buffer.
 
-       * gnus-sum.el (gnus-summary-catchup): Reverse logic.
+       * mml-sec.el: New file.
 
-Sat Sep 13 21:21:38 1997  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+2000-10-28 03:43:03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-find-part-by-type): Move it here.
+       * mml.el (mml-postprocess): Move it here.
+       (mml-postprocess-alist): Move it here. Merge them.
+
+2000-10-28 03:38:39  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Make sure no
+       unencoded stuff in the header.
+
+2000-10-28 02:40:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-listed-groups): New variable.
+       (gnus-group-list-option): New variable.
+       (gnus-group-list-limit-map): New keymap.
+       (gnus-group-list-flush-map): New keymap.
+       (gnus-group-list-plus-map): New keymap.
+       (gnus-group-prepare-logic): New function.
+       (gnus-group-prepare-flat): Merge with
+       gnus-group-prepare-flat-predicate. Use gnus-group-listed-groups.
+       (gnus-group-prepare-flat-list-dead): Ditto.
+       (gnus-group-list-matching): Use gnus-group-prepare-function.
+       (gnus-group-list-dormant): Ditto.
+       (gnus-group-list-cached): Ditto.
+       (gnus-group-listed-groups): New function.
+       (gnus-group-list-limit): New function.
+       (gnus-group-list-flush): New function.
+       (gnus-group-list-plus): New function.
+       * gnus-topic.el (gnus-group-prepare-topics): Accept predicate.
+       (gnus-topic-prepare-topic): Ditto.
+
+2000-10-27  Paul Jarc  <prj@po.cwru.edu>
+
+       * message.el (message-insert-to, message-get-reply-headers):
+       (message-reply, message-followup): Mail-{Followup,Reply}-To.
+
+2000-10-27 19:45:58  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml2015.el: New file.
+       * smime.el: New file.
+       * mml-smime.el: New file.
+
+2000-10-27 19:42:12  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.el: Quassia Gnus v0.1 is released.
+       * ChangeLog: Moved to ChangeLog.1.
+
+    Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/lisp/ChangeLog.1 b/lisp/ChangeLog.1
new file mode 100644 (file)
index 0000000..c88d229
--- /dev/null
@@ -0,0 +1,10104 @@
+2000-10-27  Jason Rumney  <jasonr@gnu.org>
+
+       * gnus-art.el (gnus-signature-face): Use italic on any frame that
+       supports it.
+
+2000-10-27 14:19:53  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-mlspl.el: Require cl when compiling.
+       * messagexmas.el: Ditto.
+       * mm-util.el: Ditto.
+       * rfc2047.el: Ditto.
+       * rfc2231.el: Ditto.
+       * smiley-ems.el: Ditto.
+       * uudecode.el: Ditto.
+       
+       * smiley-ems.el (smiley-region): Use mapcar.
+
+2000-10-27 Stefan Monnier <monnier@cs.yale.edu>
+
+       * ietf-drums.el: Require cl when compiling.
+
+2000-10-27  Dave Love  <fx@gnu.org>
+
+       * mm-decode.el (mm-valid-and-fit-image-p): Don't test
+       window-system here.
+
+       * gnus-art.el (gnus-article-x-face-command): Check
+       gnus-article-compface-xbm.
+       (gnus-treat-display-xface): Check for uncompface.
+
+       * nnheader.el (nnheader-translate-file-chars): Only kludge things
+       under Doze with XEmacs.
+
+2000-10-26  Simon Josefsson  <sj@extundo.com>
+
+       * mail-source.el (mail-sources): IMAP predicate is a string.
+       (mail-sources): Add default values for IMAP mailbox, predicate and
+       fetchflag.
+
+2000-10-26  Dave Love  <fx@gnu.org>
+
+       * flow-fill.el: Require cl when compiling.
+
+       * mail-source.el: Require imap when compiling and defvar
+       display-time-mail-function.  Require mm-util.
+       (nnheader-cancel-timer): Autoload.
+       (mail-source-imap-authenticators, mail-source-imap-streams): New
+       variables.
+       (mail-sources): Use them.
+
+2000-10-25 20:13:02  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-viewer-completion-map): New.
+       (mm-interactively-view-part): Use it.
+
+2000-10-25 18:51:12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-q-encode-region): Don't break if a QP-word
+       could be fitted in one line.
+
+2000-10-25  Dirk Meyer <dischi@tzi.de>
+
+       * gnus-demon.el (gnus-demon-time-to-step): theHour was set to
+       seconds instead of hour.
+
+2000-10-25  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * mail-source.el (mail-sources): Better `:type'.
+
+2000-10-24 18:31:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-request-article-this-buffer):
+       gnus-refer-article-method might be a single method.
+       * gnus-sum.el (gnus-refer-article-methods): The second could be 
+       a named method.
+
+2000-10-23  Simon Josefsson  <simon@josefsson.org>
+
+       * flow-fill.el (fill-flowed): Don't flow "-- " lines.
+       (fill-flowed): Make "quote-depth wins" rule work when first line
+       is at level 0.
+
+2000-10-21 11:23:21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-multibyte-p): Test (featurep 'xemacs).
+
+2000-10-21 10:54:57  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-mime-total-parts): New function.
+       (gnus-mm-display-part): Use it.
+       (gnus-mime-display-single): Ditto.
+       (gnus-mime-display-alternative): Ditto.
+
+2000-10-21 09:38:27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-parse-mailcaps): Don't use parse-colon-path,
+       because they are files, not directories.
+       (mailcap-parse-mimetypes): Ditto.
+
+2000-10-20 19:55:59  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): Check validity of charset.
+
+2000-10-18  Dave Love  <fx@gnu.org>
+
+       * mail-source.el (mm-util): Require.
+       (defvar): Use rmail-spool-directory unconditionally.
+
+       * gnus-nocem.el (gnus-nocem-issuers): Update.
+       (gnus-nocem-check-from): New option.
+       (gnus-nocem-scan-groups): Use it.
+       (gnus-nocem-check-article): Bind gnus-newsgroup-name.
+
+2000-10-18  Miles Bader  <miles@lsi.nec.co.jp>
+
+       * gnus-nocem.el (gnus-nocem-check-article-limit): New variable.
+       (gnus-nocem-scan-groups): Obey `gnus-nocem-check-article-limit'.
+
+2000-10-18  Simon Josefsson  <simon@josefsson.org>
+
+       * nnheader.el (nnheader-parse-head): Try both "from:" and "from: ".
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Ditto.
+
+2000-10-17  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Search for "from:"
+       instead of "from: " for rfc822 compliance.
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Ditto. Insert SPC.
+
+       * nnheader.el (nnheader-parse-head): Ditto.
+
+2000-10-13  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * mail-source.el (mail-source-keyword-map): Use
+       `rmail-spool-directory' as a default directory for the `file'
+       source, if the variable is defined.  Fall back to hardcoded
+       "/usr/spool/mail/", as before.  Suggestion by Steven E. Harris
+       <seh@speakeasy.org>.
+
+2000-10-13 12:01:15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially): Replace the header
+        delimiter with a blank line.
+
+2000-10-13  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el (gnus-get-split-value): Use first match only (Ed L
+       Cashin <ecashin@coe.uga.edu>).
+
+2000-10-13 10:52:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ems.el (gnus-article-compface-xbm): Ignore errors.
+
+2000-10-11  John Wiegley  <johnw@gnu.org>
+
+       * gnus-topic.el (gnus-topic-mode): Use `setq' to clear
+       `gnus-group-change-level-function', instead of `remove-hook',
+       because it's not a hook!
+
+       * gnus-mlspl.el (gnus-group-split-update): Check the value of
+       `nnmail-crosspost', and use it to set the `no-crosspost'
+       argument when calling `gnus-group-split-fancy'.  Otherwise, it
+       assumes that cross-posting is always OK, no matter what
+       `nmail-crosspost' is set to.
+       (gnus-group-split-fancy): The argument order in the
+       second-to-last `push' call was wrong, but since `no-crosspost'
+       was always nil, it was never being triggered.
+
+       * gnus-art.el (gnus-treat-hide-citation-maybe): Added this
+       variable to correspond with `gnus-article-hide-citation-maybe'.
+       (gnus-treatment-function-alist): Added entry for the above
+       correlation.
+
+2000-10-12 08:26:30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte-current-buffer): Revert to old.
+       (mm-with-unibyte-current-buffer-mule4): New function.
+       * qp.el (quoted-printable-encode-region): Use it.
+       * rfc2047.el (rfc2047-decode): Ditto.
+       * webmail.el (webmail-init): Revert to use mm-disable-multibyte.
+
+2000-10-10 08:44:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-fold-region): "=?=" is not a break point.
+
+2000-10-10 00:00:28  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-init): Use mm-disable-multibyte-mule4.
+
+2000-10-09 22:50:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * base64.el (base64-decode-region): Just give a message if the end
+       is not sane.
+
+2000-10-09 20:09:11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Move fold into
+       encode-region.
+       (rfc2047-dissect-region): Rewrite.
+       (rfc2047-encode-region): Rewrite.
+       (rfc2047-fold-region): Fold any line longer than 76.
+       (rfc2047-unfold-region): New function.
+       (rfc2047-decode-region): Use it.
+       (rfc2047-q-encode-region): Don't break at bob.
+
+2000-10-09 17:12:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-open-connection): Kill process buffer when quit.
+       (nntp-connection-timeout): Add a note. SIGALRM is ignored in both
+       FSF Emacs 20 and XEmacs 21.
+       * gnus-agent.el (gnus-agent-fetch-session): Catch quit.
+
+2000-10-09  Dave Love  <fx@gnu.org>
+
+       * gnus-audio.el: Don't require cl.
+       (gnus-audio): New custom group.
+       (gnus-audio-inline-sound): Change to work with Emacs.
+       (gnus-audio-directory, gnus-audio-directory) 
+       (gnus-audio-au-player):  Customize.
+       (gnus-audio-play): Try external player if play-sound-file fails.
+       Use file-name-extension, not string-match.
+
+       * gnus-art.el (article-de-quoted-unreadable)
+       (article-de-base64-unreadable): Fold search case rather than
+       downcasing string.  Apply mm-charset-to-coding-system to arg of
+       quoted-printable-decode-region.
+       (gnus-article-dumbquotes-map): Fix dashes.
+       (gnus-button-mailto, gnus-button-embedded-url): Doc fix.
+       (gnus-button-reply): Just alias it.
+
+2000-10-09  Stefan Monnier  <monnier@cs.yale.edu>
+
+       * mm-encode.el: Require CL.  At least, for `incf'.
+
+       * nnfolder.el (nnfolder-ignore-active-file): Typos.
+
+       * gnus-mh.el (gnus-summary-save-in-folder): Obey mh-lib-progs.
+
+       * gnus-kill.el (gnus-kill): Typo.
+
+2000-10-09  Gerd Moellmann  <gerd@gnu.org>
+
+       * smiley-ems.el (smiley-update-cache):  Use `:ascent center'.
+
+2000-10-09  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-group-overview-filename): Create directory for
+       newfile (when use long filenames is nil).  Copy+delete file if
+       rename didn't work.
+       (nnimap-group-overview-filename): `rename-file' and `copy-file'
+       doesn't return anything useful, use ignore-errors instead.
+
+2000-10-08 13:05:11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-compile): Delete old elc files first.
+
+2000-10-08 10:59:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ems.el (gnus-kill-all-overlays): Move here.
+       * gnus-util.el (gnus-kill-all-overlays): Move out.
+       * gnus-sum.el (gnus-cache-write-active): Auto load.
+       * lpath.el: Shut up.
+       * nnweb.el (nnweb-url-retrieve-asynch): url-retrieve is 
+       asynchronous in Exp version.
+
+2000-10-08 08:57:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el, gnus-ems.el, gnus-start.el: Remove gnus-xemacs.
+       * gnus-ems.el: Autoload smiley.
+       * gnus-art.el (gnus-treat-display-smileys): Default value in Emacs 21.
+
+2000-10-08 08:45:48  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-display-article): Enable multibyte.
+       (gnus-summary-select-article): Don't enable multibyte here.
+       (gnus-summary-goto-article): Ditto.
+
+2000-10-08 Christoph Conrad <christoph.conrad@gmx.de>
+
+       * gnus-draft.el (gnus-draft-send-message): Typo.
+
+2000-10-08  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-verify-uidvalidity): Delete overview file when
+       uid validity changes.
+       (nnimap-group-overview-filename): Store uidvalidity in filenames.
+       Rename old files into new format.
+
+2000-10-07 15:49:39  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-enable-multibyte-mule4): New.
+       (mm-disable-multibyte-mule4): New.
+       * gnus-sum.el (gnus-summary-mode): Use it.
+       (gnus-summary-select-article): Ditto.
+       (gnus-summary-goto-article): Use enable multibyte.
+       * rfc2047.el (rfc2047-decode): Use unibyte.
+
+2000-10-07 15:42:59  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-logic.el (gnus-advanced-string): Use "" if nil.
+
+2000-10-07 10:31:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-q-encode-region): Better calculation of
+       break point.
+       (rfc2047-fold-region): Don't break the first non-LWSP characters.
+
+2000-10-07 09:18:53  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-agent-fetching): New variable.
+       * gnus-agent.el (gnus-agent-with-fetch): Bind it.
+       * gnus-score.el (gnus-score-body): Don't score body when
+       agent-fetching.
+       (gnus-score-followup): Don't score followup either. 
+
+2000-10-07 08:19:17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el: Define dynamic variables in eval-when-compile.
+       * message.el (message-sending-message): New variable.
+       (message-send): Use it.
+       * gnus-draft.el (gnus-draft-send-message): Ditto.
+       (gnus-group-send-drafts): Ditto.
+
+2000-10-06  Dave Love  <fx@gnu.org>
+
+       * gnus-audio.el: Don't require cl.
+       (gnus-audio): New custom group.
+       (gnus-audio-inline-sound): Change to work with Emacs.
+       (gnus-audio-directory, gnus-audio-directory) 
+       (gnus-audio-au-player):  Customize.
+       (gnus-audio-play): Try external player if play-sound-file fails.
+       Use file-name-extension, not string-match.
+
+2000-10-06 17:38:03  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-prepare): Configure it again.
+
+2000-10-06 15:11:07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-default-charset): Default value for non-Mule
+       Emacsen.
+
+2000-10-06 14:28:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-alternative-emails): New.
+       (message-use-alternative-email-as-from): New.
+       (message-setup): Use them.
+
+2000-10-06 13:46:47  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * base64.el, dgnushack.el, gnus-spec.el, messagexmas.el
+       * gnus-xmas.el, nnheaderxm.el, nndraft.el: Use defalias.
+
+       * gnus-xmas.el (gnus-xmas-define): Defalias gnus-overlay-buffer,
+       gnus-overlay-start.
+       * gnus.el: Ditto.
+       * gnus-art.el (gnus-insert-mime-button): Use them.
+
+2000-10-06 10:01:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte-current-buffer): Don't set unibyte
+       if eight-bit-control is a charset, e.g. Mule 5.0 in Emacs 21.
+
+2000-10-06 09:38:54  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encode-region): Use
+       mm-with-unibyte-current-buffer within narrowed region.
+
+2000-10-06 08:56:33  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-type-definition): Fix my-deja open url.
+
+2000-10-06 Emerick Rogul <emerick@csa.bu.edu>
+
+       * message.el (message-setup-fill-variables): New variable.
+       (message-mode): Use it.
+
+2000-10-05  Dave Love  <fx@gnu.org>
+
+       * rfc2047.el (rfc2047-fold-region): Use gnus-point-at-bol.
+       (rfc2047-charset-encoding-alist): Add iso-8859-1[45].
+
+       * binhex.el: Use defalias, not fset.
+
+       * rfc1843.el: Require cl when compiling.
+
+2000-10-05 12:25:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Score-param could be nil.
+
+2000-10-05 11:43:25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-region): Merge only if regions are
+       adjacent.
+
+2000-10-05 09:41:33  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-multibyte-p): In XEmacs, it is (feature 'mule).
+       (mm-find-charset-region): Merge conditions, delete ascii.
+       (mm-charset-after): Rewrite.
+       * mm-bodies.el (mm-encode-body): Use it.
+
+2000-10-05 09:04:32  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-list): Fix.
+
+2000-10-05  Stefan Monnier <monnier+gnu/emacs@rum.cs.yale.edu>
+
+       * nnimap.el (require): cl.
+
+2000-10-04 15:24:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-prepare): Configure windows before
+       gnus-article-prepare-display is called.  Otherwise, BBDB's popup
+       window might be overrided.
+
+2000-10-04  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el (gnus-article-display-xface)
+       [gnus-article-compface-xbm]: Fix.
+       (gnus-x-splash): Bind width, height.
+
+2000-10-04 11:45:04  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): Use prefix argument only
+       when it is called interactively.
+
+2000-10-03 21:20:31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-action-alist): New variable.
+       (gnus-mime-action-on-part): Use it.
+       (gnus-mime-button-commands): Add command ".".
+
+2000-10-03 20:37:42  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): Support prefix argument.
+
+2000-10-03  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * lpath.el: "." is in the load-path because dgnushack.el.
+
+2000-10-03  Bjorn Torkelsson  <torkel@hpc2n.umu.se>
+
+       * uudecode.el: xemacs cleanup (use featurep ' xemacs)
+
+       * nnheader.el: ditto
+
+       * mm-util.el: ditto
+
+       * message.el: ditto
+
+       * binhex.el: ditto
+
+       * gnus-audio.el: removed unnecessary xemacs test
+
+       * earcon.el: ditto
+       
+2000-10-03 19:55:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnweb.el (nnweb-decode-entities): Work for non-character
+       entities. 
+
+2000-09-26 09:20:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Message the quit parts.
+
+2000-10-03 08:08:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-maildir): Don't insert
+       newlines.
+
+2000-10-02 20:14:27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * dgnushack.el (dgnushack-compile): Don't compile dgnushack.el,
+       lpath.el. Don't compile base64.el if there is builtin base64.
+
+2000-10-02  Bj\e,Av\e(Brn Torkelsson  <torkel@hpc2n.umu.se>
+
+       * base64.el (Repository): Use featurep for XEmacs test.
+
+2000-10-02 17:38:12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-data): Don't ignore quit.
+
+2000-10-02 14:43:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-banner-alist): New variable.
+       (article-strip-banner): Use it.
+       * gnus-cus.el (gnus-group-parameters): Allow symbol.
+
+2000-10-02  Dave Love  <fx@gnu.org>
+
+       * smiley-ems.el: New file.
+
+       * gnus-ems.el (gnus-smiley-display): Autoload.
+       (mouse-set-point, set-face-foreground, set-face-background)
+       (x-popup-menu): Don't clobber these.
+       (gnus-article-compface-xbm): New variable.
+       (gnus-article-display-xface): Move graphic test.  Use unibyte.
+       Obey gnus-article-compface-xbm.  Use pbm, not xbm.
+
+       * mml.el (require): Fix typo.
+       (mml-parse-1): Modify unknown encoding prompt.
+
+       * mail-source.el (mail-sources): Revert to nil.
+
+       * nnmail.el (nnmail-spool-file): Revert previous change.
+
+       * gnus.el: Don't require custom, message.
+       (gnus-message-archive-method): Wrap initializer in progn and
+       require message here.
+
+2000-10-02  Gerd Moellmann  <gerd@gnu.org>
+
+       * gnus.el (gnus-mode-line-buffer-identification) [Emacs]: Change
+       image's :ascent to 80.  That gives a mode-line which is approx.
+       as tall as the normal one.
+
+2000-10-02 08:04:48  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-list): Fix.
+
+2000-10-01 20:55:53  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       Don't postpone GCC if none of GCC methods is agent-covered.  This
+       fix presumes that the post-method must be agent-covered if any Gcc
+       method is agent-covered.
+
+       * gnus-msg.el (gnus-inews-group-method): New function.
+       (gnus-inews-do-gcc): Use it.
+       * gnus-agent.el (gnus-agent-any-covered-gcc): New function.
+       (gnus-agent-possibly-save-gcc): Use it.
+       (gnus-agent-possibly-do-gcc): Ditto.
+
+2000-10-01 17:08:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-mime-types): Use mailcap-mime-data.
+       * mml.el (mml-minibuffer-read-type): Use mailcap-mime-types.
+
+2000-10-01 13:07:21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-netscape-open, webmail-hotmail-article,
+       webmail-hotmail-list): Update.
+
+2000-10-01 08:36:09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-report-new-mail): Use
+       nnheader-cancel-timer.
+
+2000-10-01 08:35:38  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el (overlay-*): Shut up.
+       * dgnushack.el: Two implementations of smiley.
+
+2000-10-01 08:32:42  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ml.el: Usage.
+       (gnus-mailing-list-archive, gnus-mailing-list-owner,
+       gnus-mailing-list-post, gnus-mailing-list-unsubscribe,
+       gnus-mailing-list-subscribe, gnus-mailing-list-help): Bind list-*.
+       (gnus-mailing-list-menu): Define it.
+       (turn-on-gnus-mailing-list-mode, gnus-mailing-list-mode): Autoload.
+       
+       * gnus-xmas.el (gnus-xmas-mailing-list-menu-add): Move here.
+
+2000-09-30 18:52:51  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-my-deja-*): Rewrite.
+
+2000-09-30  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-request-accept-article): Remove \n's from
+       From_ lines.
+
+2000-08-05  Simon Josefsson <simon@josefsson.org>
+
+       Make GCC to remote groups work when unplugged
+       (postpone GCC until message is actually sent).
+
+       * gnus-draft.el (gnus-draft-send): Call `gnus-agent-restore-gcc'.
+
+       * gnus-agent.el (gnus-agent-possibly-do-gcc): 
+       (gnus-agent-restore-gcc): 
+       (gnus-agent-possibly-save-gcc): New functions.
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Use
+       `gnus-agent-possibly-do-gcc' if Agentized.
+       (gnus-inews-add-send-actions): Add `gnus-agent-possibly-save-gcc'
+       to `message-header-hook'.
+
+       * gnus.el (gnus-agent-gcc-header): New variable.
+
+2000-07-13  Simon Josefsson <simon@josefsson.org>
+
+       Asks the user to synch flags with server when you plug in.
+
+       * gnus-agent.el (gnus-agent-synchronize-flags): New variable.
+       (gnus-agent-possibly-synchronize-flags-server): New function, use it.
+       (gnus-agent-toggle-plugged): Call it.
+       (gnus-agent-synchronize-flags): Renamed from `gnus-agent-synchronize'.
+       (gnus-agent-group-mode-map): `g-a-s' -> `g-a-s-flags'.
+       (gnus-agent-possibly-synchronize-flags): New function.
+       (gnus-agent-possibly-synchronize-flags-server): New function.
+
+2000-09-30  Simon Josefsson  <simon@josefsson.org>
+
+       * starttls.el: New file, by Daiki Ueno.
+
+2000-08-02  Stanislav Shalunov <shalunov@internet2.edu>
+
+       * message.el (message-make-in-reply-to): In-Reply-To is message-id
+       (see DRUMS).
+       
+2000-09-29  Simon Josefsson  <simon@josefsson.org>
+
+       * nntp.el (nntp-async-trigger): Fix authinfo in asynchronous
+       prefetch.
+
+2000-08-09 10:21:20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nntp.el (nntp-open-telnet): Wait for the telnet prompt before
+       sending a command; allow the rtelnet prompt as well.
+
+2000-09-29  Simon Josefsson  <simon@josefsson.org>
+
+       * message.el (message-send): Make sure error is signalled if no
+       send method is specified.
+
+2000-09-29  Florian Weimer  <fw@deneb.enyo.de>
+
+       * qp.el (quoted-printable-encode-region): Wrap with
+       `mm-with-unibyte-current-buffer'.
+
+2000-09-29 12:12:49  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Reimplement Mike
+         McEwan's proposal.
+       
+2000-09-29 12:06:40  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el: Revoke Mike McEwan's 1998-09-05 patch due to
+       the GNU assignment issue.
+
+2000-09-29 09:56:34  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-dissect-mime-parts-sub): Correctly mark body-begin.
+
+2000-09-29 09:14:08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-enter-digest-group): Decode to-address.
+
+2000-09-28  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-art.el (article-strip-banner): Use
+       gnus-group-find-parameter rather than gnus-group-get-parameter, to
+       allow inheritance on the banner.
+       From elkin@tverd.astro.spbu.ru.
+
+2000-09-26  Richard M. Alderson III <alderson@netcom2.netcom.com> 
+
+       * gnus-art.el (gnus-read-save-file-name): expand-file-name.
+
+2000-09-26  Dave Love  <fx@gnu.org>
+
+       * gnus-draft.el: Don't require gnus-agent.
+
+       * mm-view.el: Use featurep for XEmacs test.
+       (mm-inline-message): Test for `remove-specifier'; don't use
+       condition-case.
+
+2000-09-24  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-request-accept-article): Remove From[^:] lines.
+
+       * gnus-group.el (gnus-group-nnimap-edit-acl): Check if server
+       support ACL's.
+
+       * nnimap.el (nnimap-acl-get): Check capability.
+
+       * mail-source.el (mail-source-imap-file-coding-system): New variable.
+       (mail-source-fetch-imap): Use it.
+
+       * rfc2104.el (rfc2104-hexstring-to-bitstring): New function.
+       (rfc2104-hash): Use it.
+
+       * imap.el (imap-starttls-p): Check for starttls binary.
+       (imap-starttls-open): More verbose.
+       (imap-gssapi-auth): Ditto.
+       (imap-kerberos4-auth): Ditto.
+       (imap-cram-md5-auth): Ditto.
+       (imap-login-auth): Ditto.
+       (imap-anonymous-auth): Ditto.
+       (imap-digest-md5-auth): Ditto.
+       (imap-open): Ditto.
+       (imap-digest-md5-p): Check capability first.
+
+2000-09-24  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-parse-flag-list): Correctly parse empty lists.
+       (imap-login-p): Support LOGINDISABLED.
+
+2000-09-23  Simon Josefsson  <jas@nada.kth.se>
+
+       * rfc2104.el: Add SHA-1 example.
+
+2000-09-22  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-parse-body): Work around bug in Sun SIMS.
+
+2000-09-21 21:54:48  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Bind nnkiboze-score-file.
+
+2000-09-21 16:15:25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-use-all-scores): New variable.
+       (gnus-all-score-files): Use it.
+       * nnkiboze.el (nnkiboze-generate-group): Use it. Inhibit list groups.
+       (nnkiboze-enter-nov): Fix it when there is no xref.
+       (nnkiboze-generate-groups): List groups.
+       * gnus-group.el (gnus-group-make-kiboze-group): Use 
+       nnkiboze-score-file.
+       
+       * nnkiboze.el (nnkiboze-request-article): Use
+       gnus-cache-request-article.
+       * gnus-group.el (gnus-group-make-kiboze-group): Fix prompt.
+
+2000-07-16 Dmitry Bely <dbely@mail.ru>
+
+       * nnheader.el (nnheader-translate-file-chars): Path splitting on NT.
+
+2000-09-20 18:33:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-find-bnews): Use directory-sep-char.
+
+2000-09-20 17:37:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-default-charset): Set default value in
+       non-MULE XEmacsen as iso-8859-1.
+
+2000-09-20 12:02:24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-demon.el: Use (featurep 'xemacs).
+       * gnus-agent.el: timer vs. itimer.
+       * mail-source.el: Ditto.
+
+2000-09-19 10:24:57  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-make-kiboze-group): Makedir.
+       * nnheader.el (nnheader-parse-nov): Remove Xref in mail-header-xref.
+       * gnus-sum.el (gnus-nov-parse-line): Ditto.
+       * nnkiboze.el (nnkiboze-file-coding-system): New.
+       (nnkiboze-retrieve-headers): Use it.
+       (nnkiboze-request-group): Ditto.
+       (nnkiboze-close-group): Ditto.
+       (nnkiboze-generate-group): Ditto.
+       (nnkiboze-enter-nov): Insert first Xref properly.
+
+2000-09-19  Dave Love  <fx@gnu.org>
+
+       * nnmail.el (nnmail-cache-accepted-message-ids): Default to nil.
+       (nnmail-get-new-mail): Test `sources' in top-level conditional.
+
+       * mail-source.el (mail-sources): Change default to '((file)).
+       Add useful custom type.
+
+2000-09-18  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-util.el (gnus-time-iso8601): Correct doc string (four digit
+       year).
+       (gnus-date-iso8601): Ditto.
+
+2000-09-18 09:05:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-imap): Disable multibyte.
+
+2000-09-17 01:13:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-q-encoding-alist): Remove = and _ from the
+       pattern. Avoid using 8 bit chars.
+       * qp.el (quoted-printable-encode-region): Avoid using 8 bit chars.
+
+2000-09-16 15:57:42  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * smiley.el (smiley-buffer-ems, smiley-create-glyph-ems,
+       smiley-toggle-extent-ems, smiley-toggle-extents-ems,
+       smiley-toggle-buffer-ems): New functions for Emacs 21. Toggle
+       functions are not implemented yet.
+       
+       * dgnushack.el (dgnushack-compile): Remove smiley.el and 
+       x-overlay.el from the FSF Emacs black list.
+
+2000-09-15 21:10:20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-inlined-types): Add application/emacs-lisp.
+       (mm-inline-media-tests): Ditto.
+       (mm-automatic-display): Ditto.
+       * mm-view.el (mm-display-inline-fontify): Generalize from 
+       mm-display-patch-inline. 
+       (mm-display-patch-inline): Use it.
+       (mm-display-elisp-inline): Ditto.
+       
+2000-09-15 14:03:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-find-groups): Add recursive parameter.
+       (gnus-topic-unmark-topic): Ditto.
+       (gnus-topic-mark-topic): Ditto.
+       (gnus-topic-get-new-news-this-topic): Use it.
+
+2000-09-15 09:01:40  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-treat-display-xface): By default, Emacs 21
+       display xface.
+
+2000-08-23 02:54:46  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-group.el (gnus-group-rename-group): Inhibit renaming of
+       zombie or killed groups.
+       
+2000-09-15 00:09:56  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-preview): Reinsert unibyte content. 
+       (mml-parse-1): Remove with-unibyte-current-buffer.
+       (mml-generate-mime-1): Ditto.
+       * gnus-msg.el (gnus-summary-mail-forward): Ditto.
+       * message.el (message-forward): Ditto.
+
+2000-09-14 23:13:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-de-quoted-unreadable): Guess charset from
+       original article buffer.
+       (article-de-base64-unreadable): Ditto.
+       (article-wash-html): Ditto.
+
+2000-09-14 18:55:30  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Disable multibyte
+       unless forward-show-mml.
+
+2000-09-14 14:48:57  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-save-parts-type-history): New.
+       (gnus-summary-save-parts-last-directory): New.
+       (gnus-summary-save-parts): Save history.
+
+2000-09-14 Ben Gertzfield <che@debian.org>
+
+       * gnus-sum.el (gnus-summary-save-parts-default-mime): New
+       variable.
+       (gnus-summary-save-parts): Use it.
+
+2000-09-14 11:31:28  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-setup-buffer): Clean handle-alist.
+       * gnus-sum.el (gnus-summary-exit): Ditto.
+       (gnus-summary-exit-no-update): Ditto.
+       (gnus-summary-show-article): Ditto.
+
+2000-09-14 08:42:48  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-dissect-mime-parts-sub): Remove
+       Content-Disposition.
+
+2000-09-13 23:58:40  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Hotmail updated. Add X-Gnus-Webmail.
+
+2000-09-13 21:41:25  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-setup-buffer): Set
+       gnus-article-mime-handles to nil.
+       * gnus-sum.el (gnus-summary-exit): Ditto.
+       (gnus-summary-exit-no-update): Ditto.
+       (gnus-summary-show-article): Ditto.
+       (gnus-summary-save-parts): Use gnus-article-mime-handles if
+       dissected.
+       * mm-partial.el (mm-partial-find-parts): Remove redundancy.
+
+2000-09-13 16:59:33  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-sort): Sort loose threads too.
+       (gnus-sort-threads-1): New function. Sort threads recursively.
+       (gnus-sort-threads): Use it.
+       (gnus-sort-gathered-threads): Doc fix.
+
+2000-09-13  Dave Love  <fx@gnu.org>
+
+       * gnus-salt.el (gnus-binary-mode): Fix call to gnus-add-minor-mode.
+
+       * gnus-ems.el (gnus-ems-redefine): Don't alias
+       gnus-summary-set-display-table.
+
+       * message.el (message-user-agent): Don't wrap ignore-errors around
+       it.
+
+       * mm-encode.el (mm-insert-multipart-headers): Avoid redundant
+       `format'.
+       (mm-content-transfer-encoding): Don't use cadar.
+
+       * uudecode.el (uudecode-decoder-program) 
+       (uudecode-decoder-switches): Customize.
+
+       * gnus-score.el (gnus-home-score-file): Improve custom type.
+
+       * gnus-cus.el (gnus-custom-mode): Conditionally set local
+       variables for Emacs 21.
+       (gnus-group-customize): Disable undo while laying out the buffer.
+
+2000-09-13 09:38:26  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-write-active-file): Bind
+       coding-system-for-write.
+
+2000-09-13 09:14:57  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-get-new-mail): Don't test nnmail-spool-file.
+       
+       * gnus-cache.el (gnus-jog-cache): Temporarily disable mail-sources.
+       * gnus-kill.el (gnus-batch-score): Ditto.
+       * gnus-move.el (gnus-change-server): Ditto.
+       * nnkiboze.el (nnkiboze-generate-groups): Ditto.
+
+2000-09-12  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-sum.el (gnus-update-read-articles): Undo
+       `gnus-request-set-mark' operation.
+
+2000-09-11  Dave Love  <fx@gnu.org>
+
+       * Changelog: Use iso-2022 coding.
+
+       * gnus-msg.el (gnus-msg-mail): New function.
+       (gnus-user-agent): New mail agent.
+
+2000-09-10  Dave Love  <fx@gnu.org>
+
+       * message.el: Require mail-abbrevs for XEmacs for a problem with
+       keybinding despite the autoloads for it.
+
+2000-09-08  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-kerberos4-open): Erase more (fixes race condition?).
+
+       * nnimap.el (nnimap-request-update-info-internal): Remove tick
+       marks from dormant articles. (See nnimap-request-set-mark.)
+       (nnimap-retrieve-headers-progress): Demule.
+       (nnimap-open-server): Call nnoo-change-server twice, once for
+       getting the nnimap-server-buffer and once for letting n-c-s set
+       the variables in that buffer.
+
+2000-09-08  David Edmondson <dme@dme.org>
+
+       * gnus.el (gnus-short-group-name): Guess separator.
+
+2000-09-07  Tadashi Watanabe  <watanabe@sigmaitec.co.jp>
+
+       * smiley.el (smiley-buffer, smiley-create-glyph): Work with GTK
+       XEmacs as well.
+
+2000-09-06  Francis Litterio <franl-removethis@world.omitthis.std.com>
+
+       * gnus-group.el (gnus-group-insert-group-line): Fix.
+
+2000-09-04  Dave Love  <fx@gnu.org>
+
+       * mm-decode.el (mime-display) <defgroup>: Add `multimedia' group.
+       (mm-get-image): Avoid the losing `make-glyph' from W3.
+
+2000-09-03  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-sum.el (gnus-summary-delete-article): Check server.
+
+2000-09-01  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-parse-flag-list): Rewrite.
+
+       * nnimap.el (nnimap-retrieve-headers-from-file): Ignore errors.
+
+       * imap.el (imap-parse-flag-list): Hack.
+
+2000-08-29  Dave Love  <fx@gnu.org>
+
+       * gnus-mlspl.el (gnus-group-split-fancy): Eschew mapcon.
+
+       * dgnushack.el (mapcon, union): Remove compiler macros.
+
+       * gnus-agent.el (gnus-agent-union): new function.
+       (gnus-agent-fetch-headers): Use it.
+
+       * gnus.el (gnus-group-startup-message): Specify foreground and
+       background for xpm image.  Centre image vertically.
+       From Katsumi Yamaoka <yamaoka@jpl.org> with mods.
+
+2000-08-24 23:49:23  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail): Narrow-to-headers.
+
+2000-08-24  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el (gnus-insert-mime-button): Fix help-echo for Emacs
+       21.
+
+2000-08-23  Dave Love  <fx@gnu.org>
+
+       * dgnushack.el: Remove `member-if' compiler macro.
+
+2000-08-21  Dave Love  <fx@gnu.org>
+
+       * nnimap.el (nnimap-request-newgroups): Eschew member-if.
+
+2000-08-21 10:09:47  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-hide-topic): Use find-topology if
+       permanent is used.
+       (gnus-topic-show-topic): Read topic when to show permanent hidden
+       topic.
+       (gnus-topic-remove-topic): Revert to the old behavior, not using
+       hide.
+
+2000-08-21  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el (gnus-add-minor-mode): Add &rest arg.
+       (gnus-xemacs): Use featurep.
+
+       * mm-util.el (mm-read-charset): Maybe use builtin.
+       (mm-replace-chars-in-string): Maybe use subst-char-in-string.
+       (mm-multibyte-p, mm-with-unibyte-current-buffer)
+       (mm-with-unibyte): Use featurep, not string-match.
+       (mm-with-unibyte-buffer): Simplify.
+       (mm-quote-arg): Maybe use shell-quote-argument.
+
+       * mml.el (mml-make-string): Deleted (unused).
+
+       * gnus.el (gnus-mode-line-buffer-identification): Supply
+       definition for Emacs 21.
+
+       * gnus-salt.el: Small doc fixes.
+       (gnus-pick-mode, gnus-binary-mode): Supply a toggle-func arg to
+       gnus-add-minor-mode.
+
+       * gnus-topic.el (gnus-topic-mode): Supply a toggle-func arg to
+       gnus-add-minor-mode.
+
+2000-08-20  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-before-find-minmax-bugworkaround): New
+       function, thanks to Lloyd Zusman for debugging.
+       (nnimap-request-group): 
+       (nnimap-request-list): 
+       (nnimap-retrieve-groups): 
+       (nnimap-request-newgroups): Use it.
+
+       * nnimap.el (nnimap-request-article-part): Less verbose.
+
+2000-08-19  Andreas Jaeger  <aj@suse.de>
+
+       * lpath.el ((string-match "XEmacs" emacs-version)): Remove
+       subst-char-in-string since we test elsewhere whether it's bound.
+       
+2000-08-18  Dave Love  <fx@gnu.org>
+
+       * gnus-score.el (gnus-score-find-score-files-function): Fix doc,
+       custom type.
+
+       * gnus-xmas.el (gnus-group-icon-create-glyph): Don't test
+       gnus-group-running-xemacs.
+
+       * nnheader.el (nnheader-replace-chars-in-string): Use
+       subst-char-in-string if available.
+
+       * gnus-art.el (gnus-read-save-file-name, gnus-plain-save-name) 
+       (gnus-request-article-this-buffer): Use expand-file-name.
+       (gnus-mime-view-part-as-type): Simplify interactive spec.
+       (gnus-mime-button-map): Define it all in defvar.
+
+2000-08-17  Dave Love  <fx@gnu.org>
+
+       * gnus-group.el (gnus-group-running-xemacs): Deleted.
+
+       * gnus-demon.el (gnus-demon): Bind use-dialog-box and
+       last-nonmenu-event.
+
+       * uudecode.el (char-int): Use defalias, not fset.
+
+       * score-mode.el: Don't require easymenu.  Require mm-util.
+       (score-mode-coding-system): Use mm-auto-save-coding-system.
+
+       * nneething.el (nneething-create-mapping): Don't use cadar & al.
+       (nneething-file-name): Use expand-file-name, not concat.
+
+2000-08-16 13:05:46  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers):
+       Failure proof for email addresses.
+       (nnslashdot-sane-retrieve-headers): Ditto.
+
+2000-08-14 20:08:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Only insert courtesy message
+       when text/plain.
+
+2000-08-14 19:55:04  Jesper Harder  <jesper_harder@hotmail.com>
+
+       * message.el (message-cancel-news): Copy the From header from the
+       original article.
+
+2000-08-14 19:52:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-async.el (gnus-asynchronous): Removed.
+
+2000-08-14 16:12:11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-maildir): Use MMDF mail
+       format.
+
+2000-08-14 19:12:22  Rod Whitby  <list.ding@rwhitby.net>
+
+       * nnmail.el (nnmail-expiry-target-group): Fixed.
+
+2000-08-14  Rod Whitby <list.ding@rwhitby.net>
+
+       * nnmail.el (nnmail-expiry-target-group): Fix the call to
+       gnus-request-accept-article so that body encoding is *not* done.
+       Encoding is not done on incoming mail, so why should it be done on
+       expired mail?
+
+
+2000-08-14  Rod Whitby <list.ding@rwhitby.net>
+
+       * nnml.el (nnml-request-expire-articles): Fix the calls to
+       nnml-request-article (the filename was being passed instead of the
+       article number) and nnmail-expiry-target-group
+       (nnml-current-directory is changed by nnml-request-accept-article,
+       causing it to be incorrect for the next article to be expired).
+
+2000-08-14  Rod Whitby <list.ding@rwhitby.net>
+
+       * gnus-sum.el (gnus-summary-expire-articles): Fix the handling of
+       expiry-target group parameters. 
+
+2000-08-13 18:53:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-select-group): Touch the dribble
+       buffer.
+       (gnus-topic-hide-topic): Take a PERMANENT parameter.
+       (gnus-topic-show-topic): Ditto.
+
+       * gnus-dup.el (gnus-dup-suppress-articles): Do auto-expiry.
+
+2000-08-12 21:48:00  John H. Palmieri  <palmieri@math.washington.edu>
+
+       * mail-source.el (mail-source-incoming-file-prefix): New
+       variable. 
+
+2000-08-12 20:29:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-check-first-time-used): Clean up a bit.
+
+       * mailcap.el (mailcap-maybe-eval): Be even more warning.
+
+2000-08-11  Florian Weimer  <fw@deneb.enyo.de>
+
+       * message.el (message-syntax-checks): New check quotin-style: 
+       Text must be written below quoted text.
+       (message-check-news-body-syntax): Check it.
+
+2000-08-11  Simon Josefsson  <simon@josefsson.org>
+
+       * imap.el (imap-authenticator-alist): Fix typo.
+       (imap-gssapi-open): Copy krb4 fixes for modern imtest's, thanks to
+       Jonas Oberg for debugging.
+
+2000-08-11  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-async.el (gnus-asynchronous): Disable by default.
+
+2000-08-10 20:22:09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Bind fill-column.
+
+       * nnvirtual.el (nnvirtual-request-expire-articles): Return the
+       list of unexpired articles.
+
+       * gnus-group.el (gnus-group-expire-articles-1): Return the list of
+       un-expired articles. 
+
+       * gnus-sum.el (gnus-summary-reparent-thread): Narrow to the
+       headers. 
+
+       * gnus-topic.el (gnus-topic-kill-group): Move up one line so that
+       we update the right topic.. 
+
+       * mm-decode.el (mm-display-external): Put point at start. 
+
+2000-08-10  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-expiry-target): More explicit documentation.
+
+       * gnus-cus.el (gnus-group-parameters): Add parameter `expiry-wait'.
+
+2000-08-09  Simon Josefsson <simon@josefsson.org>
+
+       * imap.el (imap-parse-body):
+       (imap-parse-string-list): Add bug workarounds for Stalker
+       Communigate Pro 3.0 server.
+       (imap-body-lines): Remove bogus comment.
+
+       * imap.el (imap-range-to-message-set): Move from nnimap.el.
+
+       * nnimap.el (nnimap-retrieve-which-headers):
+       (nnimap-retrieve-headers-from-server):
+       (nnimap-request-set-mark):
+       (nnimap-request-expire-articles): Use `i-r-t-m-set' instead.
+
+2000-08-08 00:53:41  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-dont-reply-to-names):
+       rmail-dont-reply-to-names may not be defined.
+
+2000-08-07 09:37:01  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-iterate): Uncompiled function should 
+       not use pop.
+
+2000-07-19  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el: Defalias some dummy funcs to `ignore'.
+       (gnus-x-splash): Use expand-file-name.  Remove redundant facep
+       check.
+       (gnus-article-display-xface): Special-case for dark backgrounds.
+
+2000-07-19  Kim-Minh Kaplan <kmkaplan@galaxy.fr>
+
+       * imap.el (imap-calculate-literal-size-first): New variable.
+       (imap-local-variables): Add it.
+       (imap-kerberos4-open): Set it.
+       (imap-send-command): Use it.
+
+2000-07-17 14:18:16  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-mimetypes-parsed-p): New variable.
+       (mailcap-parse-mimetypes): Use it.
+       (mailcap-extension-to-mime): Parse mimetype.
+       (mailcap-mime-types): Ditto.
+       * mml.el (mml-minibuffer-read-type): Ditto.
+
+2000-07-16 18:25:07  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-type-alist): Add outlook.
+       (nndoc-outlook-type-p): New function.
+       (nndoc-outlook-article-begin): Ditto.
+
+2000-07-16  Daiki Ueno  <ueno@unixuser.org>
+
+       * gnus-sum.el (gnus-restore-hidden-threads-configuration): Save
+       excursion.
+
+2000-07-15  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-cus.el (gnus-group-parameters, banner): Type is regexp.
+
+       * imap.el (imap): 
+       (imap-kerberos4-program): 
+       (imap-gssapi-program): 
+       (imap-ssl-program): Customization.
+       (imap-shell-program): 
+       (imap-shell-host): New variables.
+       (imap-streams): 
+       (imap-stream-alist): Add shell.
+       (imap-shell-p): 
+       (imap-shell-open): New functions.
+       (imap-open): Don't call authenticator if preauth.
+       (imap-authenticate): Return t if already authenticated.
+
+2000-07-14  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus.el (gnus-invalid-group-regexp): New variable.
+       (gnus-read-group): Use it.
+
+2000-07-14 12:40:51  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): mark-below, 
+       expunge-below and orphan-score are "group variables".
+
+2000-07-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-srvr.el (gnus-browse-read-group): Don't pass fully
+       qualified group names to `gnus-group-read-ephemeral-group'.
+
+2000-07-13 07:40:39  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (srcdir): Define it before use it.
+
+2000-07-12 19:37:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el: `W t' is toggle-header in info.
+
+2000-07-12 16:50:06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Fbind subst-char-in-string.
+
+2000-07-12 15:48:29  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Use W3DIR and lispdir.
+       * dgnushack.el: Ditto.
+
+2000-07-12 10:12:31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-de-base64-unreadable): Typo.
+
+2000-07-12  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-agent.el (require): Require timer.
+
+2000-07-11 18:29:50  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-bounce): Call mime-to-mml.
+
+2000-07-11 18:00:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-close): New function.
+
+2000-07-04 23:23:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers): Get the
+       right line number for the article.
+
+2000-07-10 22:41:58  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers): Save point.
+       * webmail.el (webmail-fetch): Bind 
+       url-http-silence-on-insecure-redirection.
+
+2000-07-10 11:43:22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers): Use
+       unibyte.
+       (nnslashdot-sane-retrieve-headers): Ditto.
+       (nnslashdot-request-article): Ditto.
+
+2000-07-10 11:12:32  William M. Perry <wmperry@aventail.com>
+
+       * mailcap.el (mailcap-parse-mimetype-file): 
+
+2000-07-07 23:46:22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-insert): Stricter test.
+       * webmail.el (webmail-refresh-redirect): Ditto.
+
+2000-07-06 14:17:48  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-multipart): Match the EOL of boundary.
+
+2000-07-05 21:19:22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-insert-nov): Remove EOLs of all fields.
+
+2000-07-05  Dave Love  <fx@gnu.org>
+
+       * utf7.el: Doc and header fixes.
+
+       * gnus-sum.el: Doc fixes.
+
+       * gnus-util.el (gnus-point-at-eol, gnus-point-at-bol): Use
+       defalias, not fset.
+
+       * flow-fill.el (fill-flowed-point-at-eol)
+       (fill-flowed-point-at-bol): Use defalias, not fset.
+
+       * gnus-art.el: Don't alias article-mime-decode-quoted-printable.
+       (gnus-Plain-save-name): Delete -- apparently bogus.
+
+2000-07-03 00:12:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnsoup.el: Use expand-file-name throughout.
+
+2000-07-03 00:07:51  Kjetil Torgrim Homme  <kjetilho@ifi.uio.no>
+
+       * nnmail.el (nnmail-read-incoming-hook): New example.
+
+2000-07-02 23:17:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Check whether the text has already
+       been decoded.
+
+2000-07-04 15:17:05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-sid-strip): To strip or not to strip?
+
+2000-07-03  Stainless Steel Rat <ratinox@peorth.gweep.net>
+
+       * gnus-sum.el (gnus-recenter): Fix horizontal recenter.
+
+2000-07-03  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-sum.el (gnus-update-marks): Don't propagate download and
+       unsend flags.
+
+2000-07-03  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-open-connection): Don't look up virtual server
+       name in authinfo (.authinfo now support ports, no need for the
+       hack).
+       (nnimap-split-find-rule): Fix.
+       (nnimap-open-connection): Look for nnimap-server-address in authinfo.
+
+2000-07-03  Paul Stodghill <stodghil@CS.Cornell.EDU>
+
+       * message.el (message-unquote-tokens): Remove all quotes.
+
+2000-07-03 00:29:08  Julien Gilles  <julien.gilles@bcv01y01.vz.cit.alcatel.fr>
+
+       * gnus-ml.el: New file. 
+
+2000-07-02 16:11:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-request-close): New function.
+
+       * gnus-start.el (gnus-clear-system): Clear nnmail-split-history. 
+
+2000-06-18  Norbert Koch  <norbert@s.netic.de>
+
+       * Makefile.in: Better support for xemacs builds
+
+Sun Jul  2 15:11:35 2000  Lars Magne Ingebrigtsen  <lmi@quimbies.gnus.org>
+
+       * gnus.el: Gnus v5.8.7 is released.
+
+2000-05-19 06:32:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-insert-part): Characters doubly decoded.
+
+2000-07-01 10:23:08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-do-fcc): Encode MIME.
+
+2000-06-28 13:52:57  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Fbind image-size.
+
+2000-06-28  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-split-rule): Update doc with extended syntax.
+       (nnimap-assoc-match): New function.
+       (nnimap-split-find-rule): Support extended syntax.
+
+2000-06-28  Simon Josefsson  <simon@josefsson.org>
+
+       * nnimap.el (nnimap-open-connection): Use port stuff.
+
+       * gnus-util.el (gnus-netrc-machine): Add defaultport parameter,
+       document port and defaultport.
+
+2000-06-27  Paul Stodghill <stodghil@CS.Cornell.EDU>
+
+       * gnus-agent.el (gnus-agent-synchronize): Kill flags buffer.
+
+2000-06-26  Dave Love  <fx@gnu.org>
+
+       * mm-decode.el (mm-image-fit-p): Use `image-size' in Emacs. 
+
+       * message.el: Remove unnecessary `require'ments.  Defvar
+       gnus-list-identifiers when compiling.  Don't try to autoload
+       variable `gnus-list-identifiers'.  Autoload
+       gnus-group-name-charset.
+       (message-fetch-field): Don't assume `format' removes text
+       properties.
+       (message-strip-list-identifiers, message-reply, message-followup):
+       Require gnus-sum.
+       (message-mode): Tidy XEmacs conditionals.
+       (message-replace-chars-in-string): Use subst-char-in-string when
+       available.
+
+       * gnus-xmas.el (gnus-xmas-define) <match-string-no-properties>:
+       Define if necessary.
+
+       * gnus-art.el (gnus-article-edit-exit): Don't assume `format'
+       removes text properties.
+
+       * gnus-srvr.el (gnus-browse-group-name): Likewise.
+
+       * gnus-msg.el (gnus-copy-article-buffer):  Likewise.
+
+       * gnus-score.el (gnus-summary-score-entry): Likewise.
+
+2000-06-26 11:18:57  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nnimap.el (nnimap-request-post): Fix parenthesis.
+
+2000-06-26  Paul Stodghill <stodghil@CS.Cornell.EDU>
+
+       * message.el (message-unquote-tokens): New function.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Unquote gcc tokens.
+
+       * nnimap.el (nnimap-request-post): Ditto.
+
+2000-06-21  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.el (gnus-asynchronous): Removed (defined in gnus-async.el).
+
+       * nnimap.el (nnimap-callback): Update for IMAP4rev1 servers (see
+       patch commited 2000-04-02).
+
+2000-06-20  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el (imap-mailbox-examine-1): New function.
+       (imap-message-copyuid-1):
+       (imap-message-appenduid-1): Use it, instead of
+       `imap-mailbox-examine' which would utf-7 encode mailbox name
+       twice.
+
+2000-06-19  Dave Love  <fx@gnu.org>
+
+       * mm-uu.el Don't require message.  Require cl when compiling.
+
+2000-06-17 18:58:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-local-variables): gnus-orphan-score is
+       a local variable.
+       * gnus-sum.el (gnus-orphan-score): Move here.
+
+2000-06-10 09:33:36  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-forward): Remove show-mml condition.
+       (message-forward-ignored-headers): Remove X-Gnus headers.
+
+2000-06-08  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus-cus.el (gnus-extra-group-parameters): Add uidvalidity.
+
+2000-06-08 12:34:26  Urban Engberg <ue@ccieurope.com>
+
+       * gnus-demon.el (gnus-demon-scan-mail): Bind nnmail-fetched-sources.
+
+2000-06-08 12:27:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-syntax-checks): Add type.
+
+2000-06-07  Dave Love  <fx@gnu.org>
+
+       * mm-view.el (mm-inline-image-emacs): Don't specify string for
+       put-image.
+       (mm-inline-image): Defalias, not fset.
+
+       * gnus.el (gnus-group-startup-message): Don't specify string for
+       insert-image.
+
+       * gnus-ems.el (gnus-add-minor-mode): Make it an alias if
+       add-minor-mode is available.
+       (gnus-article-display-xface): Don't specify string for
+       insert-image.
+
+2000-06-06 13:28:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-remove-topic): Set hidden.
+       (gnus-topic-insert-topic-line): Use shownp.
+       (gnus-topic-hide-topic): Don't use hidden.
+       (gnus-topic-show-topic): Don't use hidden.
+
+2000-06-05 22:25:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Bind coding
+       system.
+       * gnus-soup.el (gnus-soup-write-prefixes): Ditto.
+       * gnus-start.el (gnus-slave-save-newsrc): Ditto.
+       * gnus-util.el (gnus-output-to-rmail): Ditto.
+       (gnus-output-to-mail): Ditto.
+       (gnus-write-buffer): Ditto.
+       * gnus-uu.el (gnus-uu-save-article): Ditto.
+
+2000-06-04 15:05:16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-read-from-minibuffer): Typo.
+
+2000-06-03 13:36:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-charset): Override non-MIME forward
+       charset.
+
+2000-06-02 12:04:26  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-quote-region): Correct the regexp.
+       * gnus-msg.el (gnus-summary-reply): mml-quote it.
+
+2000-06-02 11:57:15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-forward): Insert raw text.
+       * mml.el (mml-parse-1): Get raw text in unibyte mode.
+       (mml-generate-mime-1): Insert raw text in unibyte mode.
+
+2000-06-01  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * mm-bodies.el (mm-body-encoding): Always encoded if
+       `mm-use-ultra-safe-encoding' is set.
+
+2000-05-31 14:50:52  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (ange-ftp-name-format): Typo.
+
+2000-05-30  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-start.el (gnus-get-unread-articles): If
+       `gnus-activate-group' and/or `gnus-check-server' return nil, don't
+       try to do anything on that server.
+       
+2000-05-25  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-group.el (gnus-group-nnimap-edit-acl): Help text updated
+       from latest draft.
+
+2000-05-08  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-group.el (gnus-group-expire-articles-1): Make sure server
+       is open.
+
+2000-05-24  Dave Love  <fx@gnu.org>
+
+       * mml.el (mml-parse-file-name): Fix ange-ftp part.
+
+2000-05-22  Didier Verna  <didier@lrde.epita.fr>
+
+       * gnus.el (gnus-redefine-select-method-widget): new function, call
+       it once. Add an "other" entry for unknown but editable backend
+       name symbols.
+       * gnus-start.el (gnus-declare-backend): use it.
+
+2000-05-19  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el (gnus-article-next-page): Revert last change.
+
+2000-05-19 09:56:07  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-open-history): Open history in binary mode.
+
+2000-05-19  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el (gnus-mime-externalize-part): Bind mm-inlined-types,
+       not mm-inline-large-images.
+
+2000-05-19 01:45:40  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-parse-1): Don't test multiple-charsets within mml tag.
+
+2000-05-18  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el: Use defalias, not fset.
+       (gnus-article-x-face-command): Don't test for xbm.
+       (gnus-article-next-page): Redisplay before testing point in window.
+
+2000-05-17 21:16:54  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-mode-map): Add M-SPACE.
+       * mml.el (mml-mode-map): Comment out mml-narrow-to-part.
+
+2000-05-17 21:13:38 Jim Davidson <jdavidson@acm.org>
+
+       * gnus-sum.el (gnus-summary-save-article-rmail): Use
+       gnus-summary-save-in-rmail.
+       * message.el (message-output): Ditto.
+
+2000-05-17 22:37:25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-emphasize-whitespace-regexp): Doc fix.
+
+2000-05-17 14:03:49  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Encode if the method
+       is a charset.
+       * message.el (message-send-news): Check group name charset.
+       * gnus-msg.el (gnus-post-news): Decode group name.
+       (gnus-inews-do-gcc): Encode group name.
+
+2000-05-17 10:16:32  Karl Kleinpaste <karl@charcoal.com>
+
+       * gnus-art.el (gnus-emphasize-whitespace-regexp): New variable.
+       * gnus-util.el (gnus-put-text-property-excluding-newlines): Use it.
+
+2000-05-17 02:25:11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-mark-line-p): New function.
+       (gnus-group-goto-group): New parameter.
+       (gnus-group-remove-mark): Use it.
+       * gnus-topic.el (gnus-topic-move-group): Ditto.
+       (gnus-topic-remove-group): Ditto.
+
+2000-05-17 00:49:09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-list-dormant): New function.
+
+2000-05-16 23:20:42  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-synchronize): Use
+       nnheader-insert-file-contents.
+       (gnus-agent-save-active-1): Ditto.
+       (gnus-agent-write-active): Ditto.
+       (gnus-agent-expire): Ditto.
+       * gnus-cache.el (gnus-cache-read-active): Ditto.
+       * gnus-start.el (gnus-master-read-slave-newsrc): Ditto.
+       * gnus-sum.el (gnus-summary-import-article): Ditto.
+
+       * gnus-agent.el (gnus-agent-write-servers): Bind coding-system.
+       (gnus-agent-save-group-info): Ditto.
+       (gnus-agent-save-alist): Ditto.
+       * gnus-util.el (gnus-make-directory): Ditto.
+
+       * gnus-agent.el (gnus-agent-save-group-info): Disable multibyte.
+
+2000-05-16 21:13:24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-preprocess-function): New variable.
+       (mml-generate-mime-postprocess-function): New variable.
+       (mml-generate-mime-1): Use them.
+
+2000-05-16 18:15:24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-apropos): Group name charset.
+       * gnus-sum.el (gnus-set-mode-line): Ditto.
+       * gnus-group.el (gnus-group-decoded-name): New function.
+       (gnus-group-edit-group): Use it.
+       * gnus-cus.el (gnus-group-customize): Use it.
+
+2000-05-16 17:55:57  Karl Kleinpaste <karl@charcoal.com>
+
+       * gnus-util.el (gnus-put-text-property-excluding-newlines): Improve.
+
+2000-05-16 16:22:17  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-name-charset-method-alist): New variable.
+       (gnus-group-name-charset-group-alist): Ditto.
+       (gnus-group-name-charset): New function.
+       (gnus-group-name-decode): New function.
+       (gnus-group-insert-group-line): Use them.
+       (gnus-group-prepare-flat-list-dead): Ditto.
+       (gnus-group-list-active): Ditto.
+       (gnus-group-describe-all-groups): Ditto.
+       (gnus-group-prepare-flat-list-dead-predicate): Ditto.
+       * gnus-srvr.el: (gnus-browse-foreign-server): Decode group name and
+       add gnus-group property.
+       (gnus-browse-group-name): Read gnus-group property.
+
+2000-05-16 15:27:08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-possibly-change-group): Use
+       file-name-coding-system instead of pathname-coding-system.
+       * nnmail.el (nnmail-find-file): Ditto.
+       (nnmail-write-region): Ditto.
+       * nnmh.el (nnmh-retrieve-headers): Ditto.
+       (nnmh-request-article): Ditto.
+       (nnmh-request-group): Ditto.
+       (nnmh-request-list): Ditto.
+       (nnmh-possibly-change-directory): Ditto.
+       (nnmh-active-number): Ditto.
+       * nnml.el (nnml-possibly-change-directory): Ditto.
+       (nnml-request-list): Ditto.
+       (nnml-request-article): Ditto.
+       (nnml-retrieve-headers): Ditto.
+
+2000-05-16  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-request-accept-article): Don't unselect
+       mailbox if no mailbox is selected.
+
+2000-05-15  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (gnus-button-url-regexp): Revert earlier change.
+       Recognize domain names starting with `www.' as starting an URL.
+
+2000-05-15 09:46:47  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-maildir): Insert "From ".
+       (mail-source-keyword-map): Add "subdirs" for maildir.
+
+2000-05-14 16:19:28  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-scan-directory-mail-source-once): New variable.
+       (nnmail-get-new-mail): Use it.
+       * gnus-start.el (gnus-get-unread-articles): Ditto.
+
+2000-05-14 14:02:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-edit-article): Better support for
+       nndraft:drafts.
+       * nndraft.el (nndraft-request-replace-article): New function,
+       bind nnmail-file-coding-system.
+
+2000-05-14  Dave Love  <fx@gnu.org>
+
+       * nnheader.el: Replace uses of `fset' with `defalias'.
+       (jka-compr-compression-info-list): Only defvar when compiling.
+
+2000-05-14 12:30:28  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-netaddress-article): Refresh redirect.
+
+2000-05-13 20:41:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): w3 might not recognize utf-8.
+
+2000-05-13 16:49:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Translate &nbsp; to SP.
+
+2000-05-13 13:00:17  Robin S. Socha <robin@socha.net>
+
+       * message.el (message-bounce): Doc typo.
+
+2000-05-13 12:25:21  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-soup.el (gnus-soup-encoding-type): u is USENET news format.
+       (gnus-soup-store): Ditto.
+       (gnus-soup-send-packet): Ditto.
+       * nnsoup.el (nnsoup-replies-format-type): Ditto.
+       (nnsoup-dissect-buffer): Ditto.
+       (nnsoup-narrow-to-article): Ditto.
+       (nnsoup-make-active): Ditto
+
+2000-05-13 12:03:29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-mode): Two parameters for local-variable-p.
+
+2000-05-13 00:54:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-strip-list-identifiers): New function.
+       (message-reply): Use it and use message-strip-subject-re.
+       (message-followup): Ditto.
+       * gnus-art.el (article-hide-list-identifiers): Remove more.
+       * gnus-sum.el (gnus-summary-remove-list-identifiers): Ditto.
+
+2000-05-12 22:28:54  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Bind
+       mail-parset-charset and use non-numeric argument.
+
+2000-05-12 20:54:11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-buffer-list): New variable.
+       (mml-generate-new-buffer): New function.
+       (mml-destroy-buffers): Ditto.
+       (mml-insert-mime): Use them.
+       * gnus-msg.el (gnus-setup-message): mml-buffer leaks.
+       * gnus-sum.el (gnus-summary-edit-article): Ditto.
+       * message.el (message-mode): Ditto.
+       * gnus-uu.el (gnus-uu-digest-headers): Keep MIME headers.
+       (gnus-uu-save-article): Support show-as-mml.
+       * message.el (message-forward): Ditto.
+
+2000-05-12 15:15:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-type-alist): mime-digest head-begin.
+       (nndoc-mime-digest-type-p): Locate article head precisely.
+       * mml.el (mml-generate-default-type): New variable.
+       (mml-generate-mime-1): Use it.
+       (mml-insert-mime-headers): Use it.
+       * gnus-uu.el (gnus-uu-digest-buffer): New variable.
+       (gnus-uu-digest-mail-forward): Use it and call message-forward
+       with argument digest.
+       (gnus-uu-save-article): Support message-forward-as-mime.
+       * message.el (message-forward): Add parameter digest.
+       * mm-decode.el (mm-dissect-default-type): New variable.
+       (mm-dissect-buffer): Use it.
+
+2000-05-11 11:08:03  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-parse-singlepart-with-multiple-charsets): Set space,
+       newline and paragraph to nil when got a non-ascii character. Test
+       paragraph before newline.
+
+2000-05-10 12:17:58  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encode-region): Bind tab-width to 1. Set
+       limit to 76.
+
+2000-05-10 09:11:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-sid-strip): New function.
+       (nnslashdot-threaded-retrieve-headers): New format.
+       (nnslashdot-sane-retrieve-headers): Ditto.
+       (nnslashdot-request-article): Ditto.
+       (nnslashdot-threaded-retrieve-headers): Thread properly.
+       (nnslashdot-request-article): Be more lenient.
+       (nnslashdot-threaded-retrieve-headers): Regexp search.
+
+2000-05-09 13:23:50  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-with-article): Define it before use it.
+
+2000-05-08 22:34:19  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-supersede): Use mime-to-mml.
+       * mm-decode.el (mm-insert-part): Test the buffer if no encoding.
+
+2000-05-08 22:34:24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-group.el (gnus-group-list-cached): Don't use
+       `subst-char-in-string'.
+
+2000-05-08  Dave Love  <fx@gnu.org>
+
+       * pop3.el (pop3-open-server): Fix creating name of trace buffer.
+
+2000-05-08 01:07:47  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-interactively-view-part): Append %s if the
+       method is a single word.
+       * nnwarchive.el (nnwarchive-type-definition): Typo.
+
+2000-05-07 17:24:01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-prepare-flat-list-dead-predicate): New
+       function.
+       (gnus-group-prepare-flat-predicate): Use it.
+       (gnus-group-list-cached): List dead groups.
+
+2000-05-07 10:50:02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-charset): Don't decode message with
+       format.
+
+2000-05-07  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * mailcap.el (mailcap-maybe-eval): Honor user request not to
+       evaluate the Lisp code.
+
+2000-05-06 17:40:20  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-wash-html): New function.
+       (gnus-article-wash-html): Bind.
+       (gnus-article-make-menu-bar): Menu item.
+       * gnus-sum.el (gnus-summary-wash-map): Bind 'h'.
+       (gnus-summary-make-menu-bar): Menu item.
+       * gnus.el: Autoload.
+
+2000-05-06  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * gnus-uu.el (gnus-uu-unshar-warning): New variable.
+       (gnus-uu-unshar-article): Use it.
+
+       * mailcap.el (mailcap-maybe-eval-warning): New variable.
+       (mailcap-maybe-eval): Use it.
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): Speling mistake
+       in docstring.
+
+       * mml.el (mml-generate-mime-1): Small comment.
+
+2000-05-05 12:27:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-de-base64-unreadable): New function.
+       (gnus-article-de-base64-unreadable): Bind.
+       (gnus-article-make-menu-bar): Menu item.
+       * gnus-sum.el (gnus-summary-wash-map): Bind '6' and 'Z'.
+       (gnus-summary-make-menu-bar): Menu item.
+       * gnus.el: Autoload.
+
+2000-05-05 10:32:27  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): Remove en/disable multibyte.
+       (gnus-summary-select-article): Add en/disable multibyte.
+
+2000-05-05 02:47:23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-edit-article): Enable multibyte.
+       (gnus-summary-edit-article): New feature: editing raw articles.
+
+2000-05-05 00:30:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-region): Insert a space before encoding.
+       Emacs MULE can not encode adjacent iso-2022-jp and cn-gb-2312.
+       * gnus-msg.el (gnus-summary-mail-forward): Use unibyte buffer.
+       Emacs MULE can not copy some 8bit characters in multibyte buffers.
+       * mm-decode.el (mm-insert-part): Ditto.
+
+2000-05-04 17:49:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-type-alist): Extend forward regexp.
+       (nndoc-forward-type-p): Ditto.
+
+2000-05-04 17:13:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte-current-buffer): Set the default
+       value of enable-multibyte-characters.
+
+2000-05-04 10:31:24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-show-article): En/disable multibyte.
+
+2000-05-03  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el (gnus-article-xface-ring-internal)
+       (gnus-article-xface-ring-size): New variable.
+       (gnus-article-display-xface): Use them to cache data.  Don't try
+       to use XPM.  Set up binary coding for PBM's sake.
+
+2000-05-03 14:23:38  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-inews-do-gcc): Set mail-parse-charset.
+       * gnus-int.el (gnus-request-accept-article): Ditto.
+       (gnus-request-replace-article): Ditto.
+       * mm-util.el (mm-mime-mule-charset-alist): Add a fake mule-charset.
+
+2000-05-03 14:11:23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode): Test the validity of coding-system.
+
+2000-05-03 11:35:15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Encode field by
+       field.
+       * mml.el (mml-to-mime): Use message-default-charset.
+       (mml-preview): Narrow to headers.
+       * message.el (message-send-mail): Use message-default-charset.
+       (message-send-news): Narrow to headers;
+       use message-default-charset.
+
+2000-05-03 08:09:14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): A better junk
+       detect.
+       * mml.el (mml-parse-singlepart-with-multiple-charsets): Save
+       restriction.
+       (mml-parse-1): Warning message.
+       (mml-preview): Disable multibyte.
+
+2000-05-03  Dave Love  <fx@gnu.org>
+
+       * gnus.el (gnus-group-startup-message): Add newline before image.
+
+2000-05-02 21:34:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode-message-header): Check the coding-system.
+       * message.el (message-send-mail): Use unibyte-buffer.
+       (message-send-mail): Ditto.
+
+Mon May  1 15:09:46 2000  Lars Magne Ingebrigtsen  <lmi@quimbies.gnus.org>
+
+       * gnus.el: Gnus v5.8.6 is released.
+
+2000-05-01 07:45:43  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-parse-1): Set no-markup-p and warn to nil.
+
+2000-04-28 21:14:21  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-q-encoding-alist): Encode HTAB.
+
+2000-04-28 16:37:09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially): Use forward-line.
+
+2000-04-28 16:01:09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-button-menu): Use call-interactively.
+
+2000-04-28 15:30:17  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Ignore 0x1b.
+       (mml-insert-mime): No markup only for text/plain.
+       (mime-to-mml): Remove MIME headers.
+
+2000-04-28 14:23:14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-preview): Set gnus-newsgroup-charset.
+       * rfc2047.el (rfc2047-encode-message-header): Encode non-ascii
+       as 8-bit.
+       * lpath.el: Fbind image functions.
+
+2000-04-28  Dave Love  <fx@gnu.org>
+
+       * gnus.el (gnus-group-startup-message): Maybe use image in Emacs
+       21.
+
+       * mailcap.el (mailcap-parse-mailcaps): Revert last change to
+       search order.  Use parse-colon-path and remove some redundancy.
+       Doc fix.
+       (mailcap-parse-mimetypes): Code consistently with
+       mailcap-parse-mailcaps.  Doc fix.
+
+       * gnus-start.el (gnus-unload): Iterate over `features', not
+       `load-history'.
+
+2000-04-28 09:52:21  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-parse-1): Don't create blank parts.
+       (mml-read-part): Fix mml tag.
+       (mml-insert-mime): Convert message/rfc822.
+       (mml-insert-mml-markup): Add mmlp parameter.
+
+2000-04-28 01:16:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially): Remove CTE.
+
+2000-04-28 00:31:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Fbind put-image for XEmacs.
+       * mm-view.el (mm-inline-image): Fset it.
+
+2000-04-27 23:23:37  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndoc.el (nndoc-type-alist): Change forward regexp.
+
+2000-04-27 21:57:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially-limit): Change the
+       default value.
+
+2000-04-27 21:53:32  Erik Toubro Nielsen <erik@ifad.dk>
+
+       * gnus-util.el (gnus-extract-address-components): Name might be
+       "".
+
+2000-04-27 20:32:06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-summary-mail-forward): Use ARG.
+       (gnus-summary-post-forward): Ditto.
+       * message.el (message-forward-show-mml): New variable.
+       (message-forward): Use it.
+       * mml.el (mml-parse-1): Add tag mml.
+       (mml-read-part): Ditto.
+       (mml-generate-mime): Support reentance.
+       (mml-generate-mime-1): Support mml tag.
+
+2000-04-27  Dave Love  <fx@gnu.org>
+
+       * gnus-art.el: Don't bother to require custom, browse-url.
+       (gnus-article-x-face-command): Include gnus-article-display-xface.
+
+       * gnus-ems.el: Assume only (X)Emacs 20+.  Simplify XEmacs checks.
+       Use defalias, not fset.
+       (gnus-article-display-xface): New function.
+
+       * mm-view.el (mm-inline-image-emacs): Use put-image, remove-images.
+
+       * mm-decode.el: Small doc fixes.  Require cl when compiling.
+       (mm-xemacs-p): Deleted.
+       (mm-get-image-emacs, mm-get-image-xemacs): Deleted.
+       (mm-get-image): Amalgamate Emacs and XEmacs code here; for Emacs,
+       use create-image and don't special-case xbm.
+       (mm-valid-image-format-p): Use display-graphic-p.
+
+2000-04-27 15:27:54  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-send-mail-partially-limit): New variable.
+       (message-send-mail-partially): New function.
+       (message-send-mail): Use it.
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Remove
+       all blank lines inside of base64.
+       * mm-partial.el (mm-inline-partial): Add an option. Remove tail
+       blank lines.
+
+2000-04-27 10:03:36  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-insert-tag): Match more special characters.
+
+2000-04-27 09:06:29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-bug): Avoid attaching the external buffer.
+
+2000-04-27 00:58:43  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-inline-media-tests): Add message/partial.
+       (mm-inlined-types): Ditto.
+       * mm-partial.el: New file.
+
+2000-04-27  Dave Love  <fx@gnu.org>
+
+       * mailcap.el (mailcap-mime-data): Fix octet-stream syntax -- might
+       matter in Emacs 21.
+
+2000-04-26  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * mm-bodies.el (mm-encode-body): Remove reference to
+       mm-default-charset in comment.
+
+2000-04-24 00:56:00  Bj\e,Av\e(Brn Torkelsson  <torkel@hpc2n.umu.se>
+
+       * rfc2047.el (rfc2047-encode-message-header): Fixing typo.
+
+2000-04-26 12:27:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-send): Move gnus-draft-setup inside of
+       let.
+
+2000-04-26 12:26:10  Pavel Janik ml. <Pavel.Janik@inet.cz>
+
+       * gnus-draft.el (gnus-draft-setup): Fix comments.
+
+2000-04-26 10:06:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmbox.el (nnmbox-create-mbox): Use nnmbox-file-coding-system,
+       if nnmbox-file-coding-system-for-write is nil.
+
+2000-04-26 02:17:44  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Just remove the
+       header if nil.
+
+2000-04-26 00:23:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Insert directly if decoded.
+       * mml.el (autoload): Typo.
+
+2000-04-25 22:46:36  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-preview): Set up posting-charset.
+       * gnus-msg.el (gnus-group-posting-charset-alist): Add koi8-r.
+
+2000-04-25 21:23:54  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Fix yahoo mail.
+
+2000-04-25 20:12:17  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-dissect-region): Don't include LWS ahead of
+       word if not necessary.
+       (rfc2047-encode-region): Put space between encoded words.
+
+2000-04-24 21:11:48  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-netrc-machine): Another default to nntp.
+
+2000-04-24 18:14:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-setup): Restore mml only when
+       required.
+       (gnus-draft-edit-message): Require restoration.
+
+2000-04-24 16:51:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-score.el (gnus-score-headers): Copy gnus-newsgrou-scored
+       back.
+
+2000-04-24 16:01:15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-treat-article): Make sure that the summary
+       buffer is live.
+
+2000-04-24 15:42:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-parse-mailcaps): Reorder.
+       (mailcap-parse-mailcap): Backwards parsing.
+       (mailcap-possible-viewers): Remove nreverse.
+       (mailcap-mime-info): Ditto.
+       (mailcap-add-mailcap-entry): Keep alternative viewer.
+
+Mon Apr 24 21:12:06 2000  Lars Magne Ingebrigtsen  <lmi@quimbies.gnus.org>
+
+       * gnus.el: Gnus v5.8.5 is released.
+
+2000-04-24 16:29:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-header-encoding-alist): Doc fix.
+
+       * gnus-util.el (gnus-netrc-machine): Default to nntp.
+
+       * mml.el (mml-generate-mime-1): Force 8bit on message/rfc822.
+
+2000-04-23 23:27:25  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-message): Disable prepare-hook.
+
+2000-04-23 00:32:32  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Fix copyright statements.
+
+       * gnus-sum.el (gnus-alter-articles-to-read-function): New
+       variable.
+       (gnus-articles-to-read): Use it.
+
+       * message.el (message-get-reply-headers): Bind free variable.
+
+2000-04-23 01:14:28  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-get-reply-headers): Fix to-address.
+
+2000-04-22 22:51:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Hotmail fix. Add a debug function.
+
+2000-04-23 00:32:32  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (t): M-down and M-up.
+
+2000-04-22 20:22:03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus-sum.el: Doc fix.
+
+2000-04-22 10:25:56  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-egroups-article): Remove < and >.
+
+2000-04-22 14:25:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnweb.el (nnweb-dejanews-create-mapping): Remove the context
+       string.
+       (nnweb-request-group): Don't scan twice.
+       (nnweb-request-scan): Don't nix out the hashtb.
+
+       * message.el (message-get-reply-headers): Return a value.
+
+2000-04-22 14:12:41  David Aspinwall  <aspinwall@TimesTen.com>
+
+       * gnus-art.el (gnus-button-url-regexp): New value to match naked
+       urls.
+
+2000-04-22 01:23:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cache.el (gnus-summary-insert-cached-articles): Reverse the
+       order messages are inserted.
+
+       * mml.el (mml-generate-mime-1): rfc2047-encode the heads of
+       message/rfc822 parts.
+
+       * gnus-art.el (gnus-article-read-summary-keys): Check for
+       numerical values.
+
+       * message.el (message-get-headers): Made into own function.
+       (message-reply): Use it.
+       (message-get-reply-headers): Renamed.
+       (message-widen-reply): New command.
+
+2000-04-21 20:52:09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-data): Report the error and return nil.
+
+2000-04-21 19:38:43  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Don't remove
+       non-base64 text at the end if not found.
+
+2000-03-01  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-read-move-group-name):
+       (gnus-summary-move-article): Use `gnus-group-method' to find out
+       what method the manually entered group belong to.
+       `gnus-group-name-to-method' doesn't return any method parameters
+       and `gnus-find-method-for-group' uses `gnus-group-name-to-method'
+       for new groups so they wouldn't work.
+
+2000-04-21 22:27:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Allow nil values to
+       override.
+
+2000-04-21 21:58:20  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnmail.el (nnmail-cache-insert): Does some stuff that is
+       probably good to do, or something.  I dunno.  I just write these
+       ChangeLog entries, and my name is Lars.
+
+1999-12-06  Hrvoje Niksic  <hniksic@iskon.hr>
+
+       * message.el (message-caesar-region): Use translate-region.
+
+2000-04-21 21:20:32  Mike Fabian  <mike.fabian@gmx.de>
+
+       * gnus-group.el (gnus-group-catchup-current): Doc fix.
+
+2000-04-21 20:36:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-setup-buffer): Don't kill local
+       variables, because that makes Emacs flash.
+
+       * gnus-group.el (gnus-group-insert-group-line): Don't call
+       gnus-group-add-icon unconditionally.
+
+       * gnus-xmas.el (gnus-group-add-icon): Moved here.
+
+       * gnus-group.el (gnus-group-glyph-directory): Don't depend on
+       xmas.
+       (gnus-group-glyph-directory): Removed.
+
+2000-04-21 20:26:23  Jaap-Henk Hoepman  <hoepman@cs.utwente.nl>
+
+       * gnus-msg.el (gnus-inews-insert-archive-gcc): Don't do stuff if
+       gnus-newsgroup-name is "".
+
+2000-04-21  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * mm-util.el (mm-mime-mule-charset-alist): Add support for UTF-8
+       in conjunction with MULE-UCS.
+
+1999-12-13  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * rfc2047.el (rfc2047-fold-region): Don't use the same break twice.
+
+1999-12-14 04:14:44  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * dgnushack.el (last, mapcon, member-if, union): New compiler
+       macros for emulating cl functions.
+
+1999-12-21  Jan Vroonhof  <vroonhof@math.ethz.ch>
+
+       * message.el (message-shorten-references): Only cater to broken
+       INN for news. This caters for broken smtpd.
+
+2000-04-21 18:20:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-info): Use the first match; not the
+       last.
+
+       * gnus-agent.el (gnus-category-kill): Save the category list.
+
+2000-04-21 16:41:50  Chris Brierley  <brierley@pobox.com>
+
+       * gnus-sum.el (gnus-summary-move-article): Do something or other.
+
+2000-04-21 16:07:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-add-icon): Fixed indentation.
+
+2000-04-21 16:07:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-add-icon): Fixed indentation.
+
+2000-04-21 10:43:16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-prepare-flat-predicate): New function.
+       (gnus-group-list-cached): Use it.
+
+2000-04-21 16:07:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Update all the copyright notices.
+
+2000-04-21 15:38:06  Vladimir Volovich  <vvv@vvv.vsu.ru>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Remove
+       non-base64 text at the end.
+
+2000-04-21 15:21:30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mm-bodies.el (mm-body-charset-encoding-alist): defcustomized.
+
+2000-04-21 15:15:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el: Don't autoload cancel-function-timers.
+
+       * message.el (message-fetch-field): Fold case.
+
+2000-04-21 15:11:09  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-forward-before-signature): New variable.
+
+2000-04-21 15:10:31  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
+
+       * gnus-mlspl.el: Fix stuff.
+
+2000-04-21 14:41:09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-update-article-line): Don't hide
+       subjects when unthreaded.
+
+2000-04-21 14:11:39  David S. Goldberg  <dsg@mitre.org>
+
+       * gnus-art.el (gnus-boring-article-headers): Work on long CCs as
+       well.
+
+2000-04-21 14:06:43  Rui Zhu  <sprache@iname.com>
+
+       * gnus-art.el (gnus-article-mode): Fix variable name.
+
+2000-04-21 13:54:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el: Fix autoload.
+
+       * flow-fill.el (flow-fill): Fix provide.
+
+       * gnus-draft.el (gnus-draft-send): Bind message-setup-hook to
+       nil.
+
+2000-04-20 22:24:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-win.el (gnus-configure-windows): Revert to switch-to-buffer.
+
+2000-04-21 05:22:18  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+        * gnus-util.el (gnus-netrc-machine): Didn't work.
+
+2000-04-20 21:22:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-setup): Restore to mml.
+
+2000-04-21 01:24:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * flow-fill.el: Renamed from fill-flowed.
+
+       * message.el (message-forward-ignored-headers): Default to
+       removing CTE.
+
+2000-04-21 00:48:48    <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.el (message-mode): Don't fill headers.
+
+2000-04-20 23:12:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-pipe-buffer-body): Use shell
+
+2000-02-21  Yoshiki Hayashi  <yoshiki@xemacs.org>
+
+       * nnvirtual.el (nnvirtual-request-article):
+       Bind gnus-override-method to nil.
+       (nnvirtual-request-update-mark): Don't update mark when
+       article is not there.
+
+2000-04-20 16:35:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Check forwarded message.
+
+2000-04-20 21:17:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-parse-netrc): Allow "port".
+       (gnus-netrc-machine): Take a port param.
+       (gnus-netrc-machine):
+
+       * gnus-art.el (gnus-request-article-this-buffer): Allow
+       re-selecting referenced articles.
+
+       * message.el (message-cancel-news): Allow editing.
+       (message-cancel-message): Add newline.
+
+2000-04-20 21:03:54  William M. Perry  <wmperry@aventail.com>
+
+       * mm-view.el (mm-inline-image-emacs): New function.
+
+2000-04-20 20:44:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-delete-incoming): Change default in
+       cvs.
+
+2000-04-20 20:43:34  Kim-Minh Kaplan  <kmkaplan@vocatex.fr>
+
+       * gnus-art.el (gnus-mime-view-part-as-type-internal): New
+       function.
+
+2000-04-20 14:45:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnml.el (nnml-request-expire-articles): Use it.
+
+       * nnmail.el (nnmail-expiry-target): New variable.
+       (nnmail-expiry-target-group): New function.
+
+2000-04-20 02:36:31  Emerick Rogul  <emerick@cs.bu.edu>
+
+       * message.el (message-forward): Add non-MIME separators.
+
+2000-04-20 02:25:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-generate-headers): Respect the syntax check
+       spec.
+
+       * gnus-sum.el (gnus-remove-thread-1): Show thread.
+       (gnus-remove-thread): Don't show all threads.
+
+Thu Apr 20 01:39:25 2000  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v5.8.4 is released.
+
+2000-04-19  Dave Love  <fx@gnu.org>
+
+       * mailcap.el (mailcap-parse-mimetypes): Add ...mime.types.
+
+2000-04-18 12:28:24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-type-definition): New egroups html.
+       (nnwarchive-egroups-*): Ditto.
+       (nnwarchive-url): Unibyte buffer and single line cookie.
+
+2000-04-14 18:50:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-char-or-char-int-p): New alias.
+       * nnweb.el (nnweb-decode-entities): Check the validity of numeric
+       entities.
+
+2000-04-10   Daiki Ueno  <ueno@unixuser.org>
+
+        * lisp/imap.el (imap-body-lines): Check Content-Type: of the
+        article case insensitively.
+
+2000-04-10 20:35:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-webmail): Use the default
+       password provided in mail-sources; use webmail:subtype:user as
+       the key.
+
+2000-04-10 20:35:46  John Wiegley <johnw@gnu.org>
+
+       * mail-source.el (mail-source-fetch-webmail): Use
+       mail-source-password-cache.
+
+2000-04-09 18:13:47  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Add netscape mail and fix HotMail mail.
+
+2000-04-08  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el (imap-kerberos4-open): Work with recent `imtest's.
+
+2000-04-02  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-request-article): Use BODY.PEEK[] instead of
+       RFC822.PEEK if server support IMAP4rev1.
+       (nnimap-request-body): Use BODY.PEEK[TEXT] instead of
+       RFC822.TEXT.PEEK if server support IMAP4rev1.
+       (nnimap-request-head): Use BODY.PEEK[HEADER] instead of
+       RFC822.HEADER if server support IMAP4rev1.
+       (nnimap-request-article-part): Support bodydetail in response
+       data.
+
+2000-03-11  Simon Josefsson  <jas@pdc.kth.se>
+
+       * fill-flowed.el: New file.
+
+       * mm-decode.el (mm-dissect-singlepart): Create a MIME handle for
+       text/plain parts with `format' parameters.
+
+       * mm-view.el (autoload): Autoload fill-flowed.
+       (mm-inline-text): For "plain" parts with a format=flowed
+       parameter, call `fill-flowed'.
+
+2000-03-21 10:32:44  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-list): Fudge new-style
+       slashdot ids.
+
+2000-03-20 00:12:42  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-list): Use the new slashdot
+       format.
+
+2000-03-16  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el: GSSAPI support, support kerberos 4 with Cyrus v1.6.x
+       `imtest' too.
+       (imap-kerberos4-program): Renamed from `imap-imtest-program'.
+       (imap-gssapi-program): New variable.
+       (imap-streams): Add gssapi.
+       (imap-stream-alist): Ditto.
+       (imap-authenticators): Ditto.
+       (imap-authenticator-alist): Ditto.
+       (imap-kerberos4-stream-p): Rename from `imap-kerberos4s-p'.
+       (imap-kerberos4-open): Loop over imtest programs, support Cyrus
+       1.6.x `imtest' syntax.
+       (imap-gssapi-stream-p): New function.
+       (imap-gssapi-open): Ditto.
+       (imap-gssapi-auth-p): Ditto.
+       (imap-gssapi-auth): Ditto.
+       (imap-kerberos4-auth-p): Renamed from `imap-kerberos4a-p'.
+       (imap-send-command): Use buffer-local `imap-client-eol' value.
+
+       * nnimap.el (nnimap-retrieve-headers-progress): Fold continuation
+       lines and turn TAB into SPC before parsing.
+
+2000-03-15  Simon Josefsson <jas@pdc.kth.se>
+
+       * nnheader.el (nnheader-group-pathname): Make sure to return a
+       directory.
+       * nnmail.el (nnmail-group-pathname): Ditto.
+
+2000-02-08  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * nnmail.el (nnmail-fix-eudora-headers): Fix `In-Reply-To' too, it
+       might split in the middle of a message-id.
+
+2000-03-13 13:51:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-srvr.el (gnus-server-kill-server): Offer to kill all the
+       groups from the server.
+
+       * gnus-sum.el (gnus-summary-save-parts): Fix interactive spec.
+       (gnus-summary-toggle-header): Update the wash status.
+
+       * gnus-uu.el ((gnus-uu-extract-map "X" gnus-summary-mode-map)):
+       Moved here.
+
+       * gnus-agent.el (gnus-agent-save-group-info): Respect old
+       setting.
+
+       * nnmail.el (nnmail-get-active): Use it.
+       (nnmail-parse-active): New function.
+
+       * mm-view.el (mm-inline-text): Support the new version of
+       vcard.el.
+
+       * gnus-sum.el (gnus-summary-move-article): Only delete article
+       when moving junk.
+       (gnus-deaden-summary): Bury the buffer.
+
+       * nnmail.el (nnmail-group-pathname): Ditto.
+
+       * nnheader.el (nnheader-group-pathname): Use expand-file-name.
+
+2000-03-13 20:23:06  Christoph Rohland  <hans-christoph.rohland@sap.com>
+
+       * rfc2047.el (rfc2047-encode-message-header): Encode no matter
+       whether Mule.
+
+2000-03-10 14:57:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Protect against unloaded Gnus.
+
+       * gnus-topic.el (gnus-topic-update-topic-line): Don't update the
+       parent.
+       (gnus-topic-update-topic-line): Yes, do.
+       (gnus-topic-goto-missing-group): Tally the correct number of
+       unread articles before inserting the topic line.
+
+2000-03-01 09:55:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Ignore errors.
+
+2000-02-13 13:53:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-dissect-buffer): Ditto.
+
+       * gnus-art.el (article-decode-charset): Strip CTE.
+
+       * ietf-drums.el (ietf-drums-strip): New function.
+
+       * gnus-sum.el (gnus-summary-move-article): Don't use the prefix
+       when prompting in read-only groups.
+
+2000-02-23  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el (imap-send-command): Change EOL-chars when
+       `imap-client-eol' differs from default, not only for kerberos4.
+       (imap-mailbox-status): Get encoded mailbox's status.
+
+2000-02-19  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mail-source.el (mail-source-fetch-imap): Copy `imap-password'
+       into `mail-source-password-cache'.
+
+2000-02-17  Florian Weimer  <fw@deneb.cygnus.argh.org>
+
+       * mm-util.el (mm-mime-charset): Check for presence of
+       `coding-system-get' and `get-charset-property' (recent XEmacs has
+       the former, but not the latter).
+
+2000-01-28  Dave Love  <fx@gnu.org>
+
+       * message.el (message-check-news-header-syntax): Fix typo
+       `newsgroyps'.
+       (message-talkative-question): Put temp buffer in fundamental-mode.
+       (message-recover): Use fundamental-mode in the right buffer.
+
+       * nnmail.el (nnmail-split-history): Use fundamental-mode in the
+       right buffer.
+
+2000-01-26 12:01:18  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-decode-region): Add charset parameter.
+       (quoted-printable-decode-string): Ditto.
+
+       * gnus-art.el (article-de-quoted-unreadable): Use it.
+
+2000-01-21  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-split-predicate): New variable.
+       (nnimap-split-articles): Use it.
+
+2000-01-20  Simon Josefsson  <jas@pdc.kth.se>
+
+       * utf7.el: Change email address.
+
+2000-01-18 22:03:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-catchup): Purge split history.
+
+2000-01-14 02:43:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-generate-active): Support extended group name.
+       (nnmail-get-active): Ditto.
+
+2000-01-13 15:16:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-write-active): Since no prefix in
+       group names, don't remove anything.
+
+2000-01-13 15:10:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-my-deja-open): My-deja changes.
+
+2000-01-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-retrieve-headers-progress): Create xref field.
+
+2000-01-10 23:35:33  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Translate full path.
+
+2000-01-09 22:52:35  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.el (gnus-other-frame): Fix typo.
+
+1999-06-25  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+       * gnus-cus.el (gnus-group-customize): Fix typo.
+
+2000-01-08 08:36:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnweb.el (nnweb-insert): Simplified.
+
+2000-01-06 18:32:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-mode-map): "e" is
+       gnus-summary-edit-article.
+
+2000-01-06 18:25:37  Jari Aalto  <jari.aalto@poboxes.com>
+
+       * mailcap.el (mailcap-mime-extensions): Add .diff.
+
+2000-01-06 00:06:40 Kim-Minh Kaplan <kmkaplan@vocatex.fr>
+
+        * mm-decode.el (mm-mailcap-command): handle "%%" and the case where
+        there is no "%s" in the method.
+
+2000-01-08 21:01:04  Kim-Minh Kaplan <kmkaplan@vocatex.fr>
+
+       * gnus-sum.el (gnus-summary-select-article): Return 'old.
+
+2000-01-06 13:41:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnfolder.el (nnfolder-read-folder): Use nnfolder-save-buffer.
+
+       * gnus.el: Really always pop up a new frame.
+
+       * parse-time.el (parse-time-rules): Allow 100-110 to be
+       2000-2010.
+
+       * time-date.el (date-to-time): Don't use timezone.
+
+2000-01-06  Dave Love  <fx@gnu.org>
+
+       * time-date.el: Add keywords.
+       (date-to-time): Add autoload cookie.  Canonicalize with
+       timezone-make-date-arpa-standard.
+       (time-to-seconds): Avoid caddr.
+       (safe-date-to-time): Add autoload cookie.
+
+       * base64.el: Require cl when compiling.
+
+2000-01-05  BrYan P. Johnson  <beej@mindspring.net>
+
+       * gnus-group.el (gnus-group-line-format-alist): Added %E for
+       eyecandy.
+       (gnus-group-insert-group-line): Now groks %E and inserts icon in
+       group line using gnus-group-add-icon.
+       (gnus-group-icons): Added customize group.
+       (gnus-group-icon-list): Added variable.
+       (gnus-group-glyph-directory): Added variable.
+       (gnus-group-icon-cache): Added variable.
+       (gnus-group-running-xemacs): Added variable.
+       (gnus-group-add-icon): Added function. Add an icon to the current
+       line according to gnus-group-icon-list.
+       (gnus-group-icon-create-glyph): Added function.
+
+2000-01-05 17:31:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-select-article): Return whether we
+       selected something new.
+       (gnus-summary-search-article): Start searching at the window
+       point.
+
+       * gnus-group.el (gnus-fetch-group): Complete over
+       gnus-active-hashtb.
+
+Wed Jan  5 17:06:41 2000  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v5.8.3 is released.
+
+2000-01-05 15:56:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-preserve-marks): New variable.
+       (gnus-summary-move-article): Use it.
+       (gnus-group-charset-alist): Added more entries.
+
+2000-01-03 01:18:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-override-types): Removed duplicate.
+
+       * gnus-uu.el (gnus-uu-mark-over): Use gnus-summary-default-score
+       as the default score.
+
+       * gnus-score.el (gnus-score-delta-default): Changed name.
+
+2000-01-04  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el (imap-parse-literal):
+       (imap-parse-flag-list): Don't care about props.
+       (imap-parse-string): Handle quoted characters.
+
+2000-01-02 08:37:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-goto-unread): Doc fix.
+       (gnus-summary-mark-article): Doc fix.
+       (gnus-summary-mark-forward): Doc fix.
+       (t): Changed keystroke for gnus-summary-customize-parameters.
+
+       * gnus-art.el (gnus-article-mode-map): Use gnus-article-edit for
+       "e".
+       (gnus-article-mode-map): No, don't.
+
+       * gnus-sum.el (gnus-summary-next-subject): Don't show the thread
+       of the final article.
+
+       * mm-decode.el (mm-interactively-view-part): Error on no method.
+
+2000-01-02 06:10:32  Stefan Monnier  <monnier+gnu/emacs@tequila.cs.yale.edu>
+
+       * gnus-score.el (gnus-score-insert-help): Something.
+
+       * gnus-art.el (gnus-button-alist): Exclude < from <URL:
+
+       * gnus-win.el (gnus-configure-frame): Ditto.
+
+       * gnus-mh.el (gnus-summary-save-in-folder): Use
+       with-current-buffer.
+
+2000-01-02 05:00:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnwarchive.el: Changed file perms.
+
+1999-12-19 21:42:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-delete-groups): New command.
+       (gnus-group-delete-group): Extra no-prompt parameters.
+
+1999-12-14 10:18:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-article): Translate <br> into
+       <p>.
+
+1999-12-28 12:20:18  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-article): Don't insert message id.
+
+1999-12-28  Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro\e,A_\e(Bjohann)
+
+       * nnimap.el (nnimap-split-fancy): New variable.
+       (nnimap-split-fancy): New function.
+
+1999-12-28  Simon Josefsson  <jas@pdc.kth.se>
+
+       (nnimap-split-rule): Document symbol value.
+
+1999-12-28  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-retrieve-headers-progress): Let
+       `nnheader-parse-head' parse article.
+       (nnimap-retrieve-headers-from-server): Don't request ENVELOPE,
+       request headers needed by `nnheader-parse-head'.
+
+1999-12-23  Florian Weimer  <fw@s.netic.de>
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): Correct default
+       value (crosspostings are handled), improve documentation.
+
+       * smiley.el: Declare file coding system as iso-8859-1.
+
+       * nnultimate.el: Dito.
+
+       * message.el: Dito.
+
+       * gnus-cite.el: Dito.
+
+       * gnus-spec.el: Dito.
+
+1999-12-21  Florian Weimer  <fw@s.netic.de>
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): New layout.
+       (gnus-setup-message): No longer make `message-posting-charset'
+       buffer-local.
+       (gnus-setup-posting-charset): Reflect the new layout of
+       `gnus-group-posting-charset-alist' and `message-posting-charset'.
+
+       * message.el (message-send-mail): Bind `message-this-is-mail' and
+       `message-posting-charset'.
+       (message-send-news): Dito, and honour new layout of
+       `message-posting-charset'.
+       (message-encode-message-body): Ignore `message-posting-charset'.
+
+       * mm-bodies.el (mm-body-encoding): Consider
+       `message-posting-charset' when deciding whether to use 8bit.
+
+       * rfc2047.el (rfc2047-encode-message-header): Back out change.
+       (rfc2047-encodable-p): Now solely for headers; use
+       `message-posting-charset'.
+
+1999-12-20 14:10:39  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-type-definition): Set default value.
+
+1999-12-19 22:49:13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnagent.el (nnagent-server-opened): Optional.
+       (nnagent-status-message): Optional.
+
+1999-12-19  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-cite.el (gnus-article-toggle-cited-text): Restore beg and
+       end (referenced by instructions in
+       `gnus-cited-opened-text-button-line-format-alist').
+
+1999-12-18  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el (imap-starttls-open): Typo.
+
+1999-12-18 16:43:37  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-after): Non-MULE case.
+       * mail-prsvr.el (mail-parse-mule-charset): New variable.
+       * rfc2047.el (rfc2047-dissect-region): Bind it.
+
+1999-12-18  Florian Weimer  <fw@s.netic.de>
+
+       * mml.el (mml-generate-multipart-alist): Correct default value.
+
+       * mm-encode.el (mm-use-ultra-safe-encoding): New variable.
+       (mm-safer-encoding): New function.
+       (mm-content-transfer-encoding): Use both.
+
+       * mm-bodies.el (mm-body-encoding): Use mm-use-ultra-safe-encoding.
+       * qp.el (quoted-printable-encode-region): Dito.
+
+1999-12-18 14:08:48  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-article): Snarf the raw file.
+
+1999-12-18 14:08:12  Victor S. Miller  <victor@idaccr.org>
+
+       * webmail.el (webmail-hotmail-list): raw=0.
+
+1999-12-18 11:14:51  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-enter-history): Back-compatible in
+       group name.
+
+1999-12-18 11:02:00  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-expire): Convert to symbol if stringp.
+
+1999-12-18  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el: Don't autoload digest-md5.
+       (imap-starttls-open): Bind coding-system-for-{read,write}.
+       (imap-starttls-p): Check if we can find starttls.el.
+       (imap-digest-md5-p): Check if we can find digest-md5.el.
+
+1999-12-17   Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+
+       * base64.el (base64-encode-string): Accept 2nd argument
+       `no-line-break'.
+
+       * imap.el: Require `digest-md5' when compiling; add autoload
+       settings for `digest-md5-parse-digest-challenge',
+       `digest-md5-digest-response', `starttls-open-stream' and
+       `starttls-negotiate'.
+       (imap-authenticators): Add `digest-md5'.
+       (imap-authenticator-alist): Setup for `digest-md5'.
+       (imap-digest-md5-p): New function.
+       (imap-digest-md5-auth): New function.
+       (imap-stream-alist): Add STARTTLS entry.
+       (imap-starttls-p): New function.
+       (imap-starttls-open): New function.
+
+1999-12-18 01:08:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-enter-history): Bad group name.
+
+1999-12-17 19:36:47  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-dissect-region): Use mapcar instead of
+       string-to-x function.
+
+1999-12-17 13:08:54  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-fold-region): Fold a line more than once.
+
+1999-12-17 11:54:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Enhance hotmail-snarf.
+
+1999-12-17 10:38:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-dissect-region): Rewrite.
+
+1999-12-16 22:59:22  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-list): Search no-error.
+
+1999-12-15 22:07:15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el: Support nov-is-evil.
+       * gnus-bcklg.el (gnus-backlog-request-article): Buffer is optional.
+       Set it if non-nil.
+       * gnus-agent.el (gnus-agent-fetch-articles): Use it.
+
+1999-12-15 08:55:19  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnagent.el (nnagent-server-opened): Redefine.
+       (nnagent-status-message): Ditto.
+
+1999-12-14 23:37:44  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc1843.el (rfc1843-decode-region): Use
+       buffer-substring-no-properties.
+       * gnus-art.el (article-decode-HZ): New function.
+
+1999-12-14 22:07:26  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-translate-file-chars): Only in full path.
+
+1999-12-14 16:21:45  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-charset-region): mail-parse-charset is a
+       MIME charset not a MULE charset.
+
+1999-12-14 15:08:03  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-ems.el: Translate more ugly characters.
+       * nnheader.el (nnheader-translate-file-chars): Don't translate
+       the second ':'.
+
+1999-12-14 10:40:33  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-request-article-this-buffer): Use all refer
+       method if cannot find the article.
+
+1999-12-14 01:13:50  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-request-article-this-buffer): Don't use refer
+       method if overrided.
+
+1999-12-13 23:38:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-webmail): Parameter
+       dontexpunge.
+
+1999-12-13 23:31:17  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Support my-deja. Better error report.
+
+1999-12-13 18:59:33  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-date-to-date): Error proof when input
+       is bad.
+       * gnus-sum.el (gnus-list-of-unread-articles): When (car read)
+       is not 1.
+
+1999-12-13 18:22:08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-request-article): A space.
+
+1999-12-13 17:20:25  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnagent.el: Support different backend with same name.
+
+1999-12-13 13:14:42  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnslashdot.el (nnslashdot-threaded-retrieve-headers): Support
+       archived group.
+       (nnslashdot-sane-retrieve-headers): Ditto.
+       (nnslashdot-request-article): Ditto.
+
+1999-12-13 11:41:32  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-insert): Narrow to point.
+
+1999-12-13 10:59:42  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-insert): Follow refresh url.
+       * nnslashdot.el: Use it.
+
+1999-12-13 10:39:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-decode-entities): Decode numerical entities.
+       (nnweb-decode-entities-string): New function.
+
+       * nnwarchive.el (nnwarchive-decode-entities-string): Rename to
+       nnweb-* and move to nnweb.el.
+       * nnwarchive.el: Use nnweb-decode-entities, etc.
+       * webmail.el: Ditto.
+
+       * nnslashdot.el: Use nnweb-decode-entities-string.
+       (nnslashdot-decode-entities): Remove.
+
+1999-12-13 10:40:56  Eric Marsden <emarsden@mail.dotcom.fr>
+
+       * nnslashdot.el: Decode entities.
+
+1999-12-12  Dave Love  <fx@gnu.org>
+
+       * gnus-agent.el (gnus-category-edit-groups)
+       (gnus-category-edit-score, gnus-category-edit-predicate): Replace
+       expansion of setf, fixed.
+
+1999-12-12 12:50:30  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el: Revoke last Dave Love's patch, because of
+       incompatibility of XEmacs.
+
+1999-12-12 12:27:03  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el: Change headers.
+       * rfc1843.el: Ditto.
+       * uudecode.el: Ditto.
+
+1999-12-07  Dave Love  <fx@gnu.org>
+
+       * gnus-agent.el (gnus-category-edit-predicate)
+       (gnus-category-edit-score, gnus-category-edit-score): Expand setf
+       inside backquote to avoid it at runtime.
+
+1999-12-07  Dave Love  <fx@gnu.org>
+
+       * binhex.el: Require cl when compiling.
+
+1999-12-04  Dave Love  <fx@gnu.org>
+
+       * gnus-cus.el (gnus-group-parameters): Allow nil for banner.
+
+1999-12-04  Dave Love  <fx@gnu.org>
+
+       * mm-util.el (mm-delete-duplicates): New function.
+       (mm-write-region): Use it.
+
+       * mml.el (mml-minibuffer-read-type): Use mm-delete-duplicates.
+
+       * mailcap.el (mailcap-mime-types): Require mm-util.  Use
+       mm-delete-duplicates.
+
+       * imap.el (imap-open, imap-debug): Avoid mapc.
+
+       * nnvirtual.el (nnvirtual-create-mapping): Likewise.
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Avoid copy-list.
+       (gnus-multi-decode-encoded-word-string): Avoid mapc.
+
+       * gnus-start.el (gnus-site-init-file): Avoid ignore-errors at
+       runtime.
+
+       * gnus.el (gnus-select-method): Likewise.
+
+       * nnheader.el (nnheader-nov-read-integer): Likewise.
+
+       * mm-view.el (mm-inline-message): Require cl when compiling.
+       Avoid ignore-errors at runtime.
+       (mm-inline-text): Avoid mapc.
+
+1999-12-12 10:36:51  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-charset): Widen is bad.
+
+1999-12-12 10:17:42  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-after): `charset-after' may not be defined.
+
+1999-12-12  Florian Weimer  <fw@s.netic.de>
+
+       * rfc2047.el (rfc2047-encodable-p): New parameter header used to
+       indicate that only US-ASCII is permitted.
+       (rfc2047-encode-message-header): Use it.  Now, Gnus should never
+       use unencoded 8-bit characters in message headers.
+
+1999-12-12 03:08:15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * ietf-drums.el (ietf-drums-narrow-to-header): Make it work with
+       CRLF.
+
+1999-12-11 14:42:26  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Require url-cookie.
+
+1999-12-11 14:21:23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-make-caesar-translation-table): A
+       new function to make modified caesar table.
+       (nnwarchive-from-r13): Use it.
+       (nnwarchive-mail-archive-article): Improved.
+
+1999-12-11 12:30:20  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-url): Use mm-with-unibyte-current-buffer.
+
+1999-12-10 16:22:24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-request-article): Return cons.
+
+1999-12-10 16:06:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-setup-default-charset): Typo.
+
+1999-12-10 12:14:04  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte): New macro.
+       * nnweb.el (nnweb-init): Use it.
+
+1999-12-09 20:39:49  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-charset-after): New function.
+       (mm-find-mime-charset-region): Set charsets after
+       delete-duplicates and use find-coding-systems-region.
+       (mm-find-charset-region): Remove composition.
+
+       * mm-bodies.el (mm-encode-body): Use mm-charset-after.
+
+       * mml.el (mml-parse-singlepart-with-multiple-charsets): Ditto.
+
+1999-12-09 17:47:56  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-mime-charset-region): Revoke last change.
+       * mml.el (mml-confirmation-set): New variable.
+       (mml-parse-1): Ask user to confirm.
+
+1999-12-09  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-start.el (gnus-get-unread-articles): Make sure all methods
+       are scanned when we have directory mail-sources (the mail source
+       is modified in that case, so we must scan it for all
+       groups/methods).
+
+1999-12-09 12:05:28  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnml.el (nnml-request-move-article): Save nnml-current-directory
+       and nnml-article-file-alist.
+
+1999-12-09 10:20:07  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-get-new-news-this-group): Binding
+       nnmail-fetched-sources.
+
+1999-12-09 10:19:01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-charset-region): Use the last charset.
+
+1999-12-08  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-select-method): Made the option list prettier.
+
+1999-12-08  Florian Weimer  <fw@s.netic.de>
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): Use iso-8859-1
+       for the `de' newsgroups hierarchy, as it is common practice there.
+
+
+1999-12-07 16:17:12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-mail-archive-article): Fix
+       buffer-string arguments. Fix references.
+
+1999-12-07 15:04:18  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-confirmation-function): New variable.
+       (gnus-agent-batch-fetch): Use it.
+       (gnus-agent-fetch-session): Use it.
+
+1999-12-07 12:32:43  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-mime-charset-region): Delete nil.
+
+1999-12-07 11:45:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-find-charset-region): Don't capitalize.  Delete
+       nil.
+
+1999-12-07  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * nnslashdot.el (nnslashdot-request-list): There were two
+       top-level body-forms.  Put a `progn' around them.
+
+       * gnus.el (gnus-select-method): Use `condition-case'
+       instead of `ignore-errors', since cl may not be loaded when the
+       form is evaluated.
+
+1999-12-06 23:57:47  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el: Support www.mail-archive.com.
+
+1999-12-06 23:55:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-get-new-mail): Remove fetched sources before
+       do anything.
+
+1999-12-06  Simon Josefsson  <jas@pdc.kth.se>
+
+       * utf7.el: New file, written by Jon K Hellan.
+
+       * imap.el (imap-use-utf7): Renamed from `imap-utf7-p', change
+       default to t.
+
+1999-12-06 04:40:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-delete-group): New function.
+
+       * gnus-sum.el (gnus-summary-refer-article): Work for lists with
+       current.
+       (gnus-refer-article-methods): New function.
+       (gnus-summary-refer-article): Use it.
+
+1999-11-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-retrieve-groups): Return active format.
+
+       * nnimap.el (nnimap-replace-in-string): Removed.
+       (nnimap-request-list):
+       (nnimap-retrieve-groups):
+       (nnimap-request-newgroups): Quote group instead of escaping SPC.
+
+1999-12-05  Simon Josefsson  <jas@pdc.kth.se>
+
+       * imap.el: Use format-spec for ssl program.
+       * imap.el (imap-ssl-arguments): Removed.
+       (imap-ssl-open-{1,2}): Removed.
+
+1999-12-04  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-start.el (gnus-site-init-file): Use `condition-case'
+       instead of `ignore-errors', since cl may not be loaded when the
+       form is evaluated.
+
+1999-12-04 11:34:22  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-8bit-char-regexps): Removed.
+       (mm-7bit-chars): New variable.
+       (mm-body-7-or-8): Use it in both cases.
+
+1999-12-04  Michael Welsh Duggan  <md5i@cs.cmu.edu>
+
+       * gnus-start.el (gnus-site-init-file): Don't use cl macros in
+         defcustom definitions.
+
+1999-12-04  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mm-decode.el (mm-display-part): Let mm-display-external return
+       inline or external.
+       (mm-display-external): For copiousoutput methods, insert output in
+       buffer.
+
+1999-12-04 03:29:13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-headers-with-xover): Goto the end of
+       buffer.
+
+1999-12-04 08:31:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-audio.el: An M too far.
+
+       * gnus-msg.el (gnus-setup-message): One backtick too many.
+
+       * gnus-art.el (gnus-mime-view-part-as-type): mailcap-mime-types is
+       a function, not a variable.
+
+1999-12-04 08:14:08  Max Froumentin  <masmef@maths.bath.ac.uk>
+
+       * gnus-score.el (gnus-score-body): Widen before requesting.
+
+1999-12-04 08:06:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-prepare-flat): Comment fix.
+
+1999-12-04 03:01:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-fetch-webmail): Bind
+       mail-source-string.
+
+1999-12-04 07:18:23  Matt Swift  <swift@alum.mit.edu>
+
+       * gnus-uu.el (gnus-uu-mark-by-regexp): Doc fix.
+       (gnus-uu-unmark-by-regexp): Ditto.
+
+       * gnus-group.el (gnus-group-catchup-current): Would bug out on
+       dead groups.
+
+1999-12-04 01:34:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-setup-message): Allow the charset setting to
+       do their real thing.
+
+       * nnmh.el (nnmh-be-safe): Doc fix.
+
+       * gnus-sum.el (gnus-summary-exit): Write cache active file.
+
+       * nntp.el (nntp-retrieve-headers-with-xover): Make sure the entire
+       status line has arrived before we count it.
+
+       * mailcap.el (mailcap-mime-data): Removed save-file from audio/*.
+
+       * gnus-sum.el (gnus-thread-header): Fixed after indent.
+       Whitespace problems.
+
+       * gnus-win.el (gnus-configure-windows): Error fix.
+
+       * gnus-demon.el (gnus-demon-add-nntp-close-connection): Add the
+       right function.
+
+       * gnus.el: Fixed all the doc strings to match the FSF convetions.
+       Indent all functions.  Fix all comments to match the comment
+       conventions.  Double-space after full stop.
+
+1999-12-04 01:14:55  YAMAMOTO Kouji  <kouji@pobox.com>
+
+       * nnmail.el (nnmail-split-it): I redefined nnmail-split-fancy's
+       value to divide received mails into my favorite groups and I met
+       an error.  It takes place if the length of a element "VALUE" in
+       nnmail-split-fancy is less than two.
+
+1999-10-10  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * mml.el (mml-insert-part): New function.
+
+1999-09-29 04:48:14  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * lpath.el: Add `sc-cite-regexp'.
+
+1999-12-02  Dave Love  <fx@gnu.org>
+
+       * mm-decode.el: Customize.
+
+1999-12-03  Dave Love  <fx@gnu.org>
+
+       * nnslashdot.el, nnultimate.el: Don't lose at compile time when
+       the W3 stuff isn't available.
+
+1999-12-03  Dave Love  <fx@gnu.org>
+
+       * imap.el, mailcap.el, nnvirtual.el, rfc2104.el: Don't require cl
+       at runtime.
+
+1999-12-04 00:47:35  Dan Christensen  <jdc@jhu.edu>
+
+       * gnus-score.el (gnus-score-headers): Fix orphan scoring.
+
+1999-12-01  Andrew Innes  <andrewi@gnu.org>
+
+       * nnmbox.el (nnmbox-read-mbox): Count messages correctly, and
+       don't be fooled by "From nobody" lines added by respooling.
+
+       * pop3.el (pop3-movemail): Write crashbox in binary.
+       (pop3-get-message-count): New function.
+
+       * mail-source.el (mail-source-primary-source): New variable.
+       (mail-source-report-new-mail-interval): New variable.
+       (mail-source-idle-time-delay): New variable.
+       (mail-source-new-mail-available): New internal variable.
+       (mail-source-fetch-pop): Clear new mail flag, when mail from
+       primary source has been fetched.
+       (mail-source-check-pop): New function.
+       (mail-source-new-mail-p): New function.
+       (mail-source-start-idle-timer): New function.
+       (mail-source-report-new-mail): New function.
+       (mail-source-report-new-mail): New internal variable.
+       (mail-source-report-new-mail-timer): New internal variable.
+       (mail-source-report-new-mail-idle-timer): New internal variables.
+
+1999-12-04 00:39:34  Andreas Schwab  <schwab@suse.de>
+
+       * gnus-cus.el (gnus-group-customize): Customize fix.
+
+1999-12-04 00:38:24  Andrea Arcangeli  <andrea@suse.de>
+
+       * message.el (message-send-mail-with-sendmail): Use
+       message-make-address.
+
+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.
+
+1999-12-01 14:28:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * dgnushack.el (dgnushack-compile): No webmail under Emacs.
+
+       * gnus-sum.el (gnus-summary-refer-article): Wrong interactive
+       spec.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Eval `eval'.
+       (gnus-configure-posting-styles): No, don't.
+       (gnus-configure-posting-styles): Allow overriding files.
+
+       * gnus-art.el (gnus-header-button-alist): Use browse-url
+       directly.
+
+       * mm-decode.el (mm-inline-media-tests): Check feature vcard.
+
+       * gnus-msg.el (gnus-summary-yank-message): New command and
+       keystroke.
+
+       * message.el (message-yank-buffer): New command.
+       (message-buffers): New function.
+
+       * gnus-sum.el (gnus-summary-catchup-and-goto-next-group): Select
+       next group in a more normal fasion.
+
+       * mml.el (mml-boundary-function): New variable.
+       (mml-compute-boundary): Use it.
+
+       * nnmh.el (nnmh-active-number): Skip past files that have buffers
+       that exist for them.
+
+       * gnus-async.el (gnus-async-prefetch-next): Cancel timers.
+       (gnus-async-timer): New variable.
+
+1999-11-30 02:07:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-request-list): Be more lenient with
+       root addresses.
+
+1999-11-28 20:22:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treatment-function-alist): Do
+       gnus-treat-capitalize-sentences.
+
+1999-11-30 09:07:53  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el (webmail-hotmail-article): Hotmail changes the
+       format.
+
+1999-11-29  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mm-decode.el (mm-display-external): For `copiousoutput' methods,
+       switch to buffer after calling program.
+       (mm-display-external): Use `shell-command-switch' instead of "-c".
+
+1999-11-27 15:21:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-possibly-change-server): Don't always
+       read groups file.
+
+       * nnslashdot.el (nnslashdot-request-article): Convert <br><br> to
+       <p>.
+
+1999-11-24 20:18:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-mode): Doc fix.
+
+1999-11-24 09:25:00  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-emphasize): Check group variable.
+       * rfc1843.el (rfc1843-decode-article-body): Ditto.
+
+1999-11-24 00:11:27  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-save-part-to-file): Inhibit jka-compr for any
+       type.
+
+1999-11-23 17:21:05  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Support www.netaddress.com, i.e. usa.net.
+
+1999-11-23  Hrvoje Niksic  <hniksic@iskon.hr>
+
+       * mml.el (mml-quote-region): Insert ! after the hash.
+
+1999-11-23 05:08:23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-warchive-address-history): Change to
+       nil.
+
+1999-11-23 02:33:13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * webmail.el: Support mail.yahoo.com.
+
+       * mail-source.el (mail-source-fetch-webmail): Add password check.
+       (mail-source-keyword-map): Use `subtype'.
+
+1999-11-22 04:35:43  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-keyword-map): Add webmail.
+       (mail-source-fetcher-alist): Ditto.
+       (mail-source-fetch-webmail): New function.
+       * webmail.el: New file.
+
+1999-11-21 12:20:02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el (nnwarchive-request-group): Print 0 if it is nil.
+
+1999-11-21 12:19:11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-parse-mailcap): Don't skip double semicolon.
+
+1999-11-20 12:54:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-request-list): Add fetch-time slot.
+       (nnultimate-prune-days): New function.
+       (nnultimate-create-mapping): Use it.
+       (nnultimate-request-group): Only fetch the groups list if it has
+       not been done before.
+       (nnultimate-retrieve-headers): Don't write groups.
+       (nnultimate-create-mapping): Off-by-one error.
+
+1999-11-19 12:17:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-sane-retrieve-headers): Fix to match
+       threaded subjects.
+
+1999-11-20 02:22:52  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el: Lots of changes make agent happy.
+
+1999-11-19 21:37:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-get-unread-articles): Assert group is in
+       hashtb.
+
+1999-11-19 19:53:08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-external): Write region with binary
+       mode.
+
+1999-11-18 14:52:05  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnweb.el (nnweb-dejanews-create-mapping): Bind `text'.
+
+1999-11-18 14:35:01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Use fake charset `gnus-decoded'.
+       (mm-uu-test): Now it is in restricted region.
+
+       * gnus-art.el (article-decode-charset): Don't mm-uu-test.
+
+       * mm-view.el (mm-view-message): Fix buffer leak.
+       (mm-inline-message): Support 'gnus-decoded.
+
+       * mm-bodies.el (mm-decode-body): Ditto.
+
+       * rfc2047.el (rfc2047-decode-region): Ditto.
+
+1999-11-18  Matthias Andree  <ma@dt.e-technik.uni-dortmund.de>
+
+       * imap.el (require): Added autoload for base64-encode-string.
+
+1999-11-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.el (gnus-refer-article-method): Made list value
+       customizable.
+
+1999-11-17 13:09:37  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-recenter): set-window-start with
+       NOFORCE in Emacs case.
+
+1999-11-17 13:04:01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-request-article-this-buffer): Set
+       gnus-newsgroup-name.
+
+1999-11-16 23:53:22  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-summary-recenter): set-window-start with
+       NOFORCE.
+
+1999-11-17  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-start.el (gnus-get-unread-articles): Check server before
+       scanning.
+
+1999-11-16 10:01:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-valid-select-methods): nnslashdot is news.
+
+       * nnslashdot.el (nnslashdot-login-name): New variable.
+       (nnslashdot-password): Ditto.
+       (nnslashdot-request-post): New function.
+
+       * gnus-art.el (gnus-treat-buttonize): More testing.
+
+       * mm-encode.el: Another CVS test.
+
+       * gnus-art.el (gnus-treat-emphasize): Change default.
+       (gnus-treat-buttonize): Ditto.
+       (gnus-treat-buttonize): This is a test.
+
+       * gnus-sum.el (gnus-build-old-threads): Bind mail-parse-charset.
+       (gnus-build-sparse-threads): Ditto.
+       (gnus-build-all-threads): Ditto.
+
+       * nnheader.el (make-full-mail-header): Make into a subst.
+
+       * dgnushack.el (dgnushack-compile): Skip all w3-dependent files
+       unless w3 is supplied.
+
+       * gnus.el (gnus-refer-article-method): Doc fix.
+
+       * gnus-sum.el: Do not accept a prefix.
+       (gnus-summary-refer-article): Accept a list of select methods.
+
+1999-11-15 21:28:40  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Change `^  *' to `\t'.
+
+1999-11-11  Matt Pharr  <mmp@graphics.stanford.edu>
+
+       * message.el (message-forward): Pay attention to prefix argument
+       again and forward all headers when it is set, regardless of the
+       value of message-forward-ignored-headers.
+
+1999-11-15 20:44:50  William M. Perry  <wmperry@aventail.com>
+
+       * dgnushack.el (dgnushack-compile): Vpath file.
+
+       * Makefile.in (SHELL): VPATH support.
+
+1999-11-15 20:37:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-ems.el: Check for cygwin32.
+
+1999-11-14 18:15:28  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-external): Use 'non-viewer.
+
+1999-11-14 15:21:06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * base64.el (base64-encode-string): An alias for base64-encode for
+       compatibility.
+
+1999-11-14 01:58:18  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-groups): Erase nntp-sever-buffer before
+       nntp-inhibit-erase.
+
+1999-11-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-start.el (gnus-get-unread-articles): Use
+       nnfoo-retrieve-groups to find new news, if available.
+       (gnus-read-active-file-2): New function.
+       (gnus-get-unread-articles): Use it.
+       (gnus-read-active-file-1): Ditto.
+
+1999-11-13 17:59:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-find-mime-charset-region): Make sure
+       find-coding-systems-for-charsets is fbound.
+
+       * gnus-ems.el: Typo fix.
+
+1999-11-13  Florian Weimer  <fw@s.netic.de>
+
+       * mm-util.el (mm-find-mime-charset-region): Use UTF-8 if
+       it's available and makes sense.
+
+1999-11-12 19:56:23  Fabrice POPINEAU <Fabrice.Popineau@supelec.fr>
+
+       * gnus-score.el (gnus-score-save): Translate score file.
+
+1999-11-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mail-source.el (mail-source-keyword-map): For IMAP mail source,
+       added fetchflag and dontexpunge keywords.
+       (mail-source-fetch-imap): Use them.
+
+1999-11-12  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-start.el (gnus-level-subscribed, gnus-level-unsubscribed,
+       gnus-level-zombie, gnus-level-killed): Changed from `defcustom' to
+       `defconst'.
+
+       * gnus-cus.el (gnus-group-parameters): Changed from `defcustom' to
+       `defconst'.
+       Mention that it is both for group and topic parameters.
+       (gnus-extra-topic-parameters): New constant, including `subscribe'
+       parameter.
+       (gnus-extra-group-parameters): New constant.
+       (gnus-group-customize): Use them.
+
+       * gnus.el (gnus-select-method): Added default value and tag.
+       (gnus-refer-article-method): Added `DejaNews' customization option.
+
+1999-11-12 05:04:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-int.el (gnus-server-opened): Ignore denied servers.
+
+       * gnus-ems.el (gnus-mule-max-width-function): New backquote
+       syntax.
+
+       * nndoc.el (nndoc-mime-digest-type-p): Reinstated.
+
+       * nnslashdot.el (nnslashdot-group-number): Changed default.
+
+       * nnweb.el (nnweb-dejanews-create-mapping): Work with new deja.
+       (nnweb-dejanews-wash-article): Removed.
+       (nnweb-type-definition): Fetch by id.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Don't insert unless
+       we mean it.
+
+       * nnslashdot.el (nnslashdot-group-number): Doc fix.
+       (nnslashdot-request-list): Use Ultramode as well.
+       (nnslashdot-date-to-date): Be more lenient.
+       (nnslashdot-threaded): New function.
+
+1999-11-11 17:40:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-internalize-part): Doc fix.
+
+1999-11-11 14:32:48  Steinar Bang  <sb@metis.no>
+
+       * nnweb.el (nnweb-type-definition): /=dnc
+
+1999-11-11 10:58:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Work with american
+       dates.
+       (nnultimate-retrieve-headers): Wrong ordering.
+
+1999-11-11 07:31:51  Matt Pharr  <mmp@graphics.stanford.edu>
+
+       * message.el (message-forward-as-mime): New variable.
+
+1999-11-11 05:24:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-dd-mmm): Beware buggy dates.
+
+1999-11-10 16:50:01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mail-source.el (mail-source-movemail-and-remove): New function.
+       (mail-source-keyword-map): Add `function' for `maildir'.
+       (mail-source-fetch-maildir): Use it.
+
+1999-11-10 13:48:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnwarchive.el: New file.
+       * gnus-group.el (gnus-group-make-warchive-group): New function.
+       * gnus.el (gnus-valid-select-methods): Add `nnwarchive'.
+
+1999-11-10 12:13:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-retrieve-headers): Work for multi-page
+       subjects.
+
+1999-11-10 11:33:23  Rajappa Iyer  <rajappa@mindspring.com>
+
+       * gnus-salt.el (gnus-pick-article-or-thread): Don't move point.
+
+1999-11-10 05:22:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnultimate.el (nnultimate-open-server): Do address.
+       (nnultimate-forum-table-p): New function.
+
+       * nnweb.el (nnweb-insert-html): Renamed.
+       (nnweb-insert): New function.
+
+       * nnultimate.el (nnultimate-insert-html): New function.
+
+       * nnslashdot.el (nnslashdot-retrieve-headers): Don't do anything
+       if nov is evil.
+       (nnslashdot-retrieve-headers): use the sane version instead.
+
+1999-11-09 00:13:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-request-article): Fold case.
+
+       * nnultimate.el: New file.
+
+       * nnslashdot.el (nnslashdot-retrieve-headers): Skip the article
+       unless wanted.
+
+       * gnus-start.el (gnus-active-to-gnus-format): Catch errors.
+       (gnus-read-active-file-1): Separated into own function.
+       (gnus-read-active-file): Catch quits.
+
+       * nnslashdot.el (nnslashdot-request-article): Search better on
+       first article.
+       (nnslashdot-request-list): Fold case.
+       (nnslashdot-retrieve-headers): Ditto.
+
+1999-11-08 05:33:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Autoload gnus-subscribe-topics.
+
+1999-11-07 22:56:46  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-save-group-info): Remove backslash
+       before dot.
+       * gnus-util.el (gnus-write-active-file): Ditto.
+
+1999-11-07 22:31:10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-replace-duplicate-chars-in-string): New
+       function.
+       * gnus-cache.el (gnus-cache-file-name): Use it.
+       * gnus-agent.el (gnus-agent-group-path): Use it.
+       * nnmail.el (nnmail-group-pathname): Use it.
+
+1999-11-07 21:07:55  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-start.el (gnus-active-to-gnus-format): Don't insert backslash
+       if cooked.
+       * gnus-util.el (gnus-write-active-file): Write cooked active file.
+       * gnus-agent.el (gnus-agent-save-group-info): Ditto.
+       * gnus.el (gnus-short-group-name): "..." proof.
+
+1999-11-07 20:03:16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Keep using `read' to
+       support nnslashdot.
+
+1999-11-08 00:06:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el (nnslashdot-retrieve-headers): Don't fetch too
+       many articles.
+       (nnslashdot-generate-active): New function.
+       (nnslashdot-request-newgroups): Use it.
+
+       * gnus-start.el (gnus-active-to-gnus-format): Intern strings group
+       names.
+
+       * nnslashdot.el (nnslashdot-request-newgroups): New function.
+       (nnslashdot-request-list): Not moderated.
+
+1999-11-07  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el (nnimap-open-server): Remove error signal if
+       nnimap-server-buffer is nil (the check should've been `boundp').
+
+       * imap.el (imap-log):
+       * nnimap.el (nnimap-debug): Disable debugging by default.
+
+1999-11-07 01:17:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-subscribe-newsgroup-method): Doc fix.
+
+       * gnus-topic.el (gnus-subscribe-topic): New function.
+
+       * nnslashdot.el (nnslashdot-request-list): Give out extended group
+       names.
+
+       * gnus-start.el (gnus-ignored-newsgroups): Disregard bogus chars
+       if starting with a quote.
+
+1999-11-07 13:06:11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Support backslash in
+       group name.
+
+1999-11-07 01:17:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnslashdot.el: New file.
+
+       * nnheader.el (nnheader-insert-header): New function.
+
+       * gnus-art.el (gnus-mime-internalize-part): Bind
+       mm-inlined-types.
+
+       * nndraft.el (nndraft-request-expire-articles): Do all the backup
+       files.
+
+1999-10-29  David S. Goldberg  <dsg@mitre.org>
+
+       * emacs-mime.texi (Customization): Document mm-inline-override-types
+
+1999-10-29  David S. Goldberg  <dsg@mitre.org>
+
+       * emacs-mime.texi (Customization): Document mm-inline-override-types
+
+1999-10-29  David S. Goldberg  <dsg@mitre.org>
+
+       * emacs-mime.texi (Customization): Document mm-inline-override-types
+
+1999-10-26  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * smiley.el (gnus-smiley-display): Use `smiley-toggle-buffer'.
+       (smiley-toggle-buffer): New function.
+       (smiley-buffer): Don't quote the function.
+       (smiley-toggle-extents): Ditto.
+
+1999-11-07 01:00:32  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-goto-missing-topic): Work even in
+       empty buffers.
+
+1999-11-06 23:16:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-mode-map): Use the summary article
+       edit.
+
+1999-11-06 22:56:49  Jens-Ulrik Petersen  <Jens-Ulrik.Petersen@nokia.com>
+
+       * gnus-group.el (gnus-group-read-ephemeral-group): Doc fix.
+
+1999-11-06 21:40:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-uu.el (gnus-uu-mark-thread): Don't move point around.
+
+1999-10-07  Katsumi Yamaoka <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-treat-predicate): Examine whether the argument
+       is list or not before condition.
+
+1999-10-07  Yoshiki Hayashi <t90553@mail.ecc.u-tokyo.ac.jp>
+
+       * gnus-art.el (gnus-treat-predicate): Work for (typep "something").
+
+1999-11-06 19:18:14  Kevin the Bandicoot  <user42@zip.com.au>
+
+       * gnus-art.el (gnus-emphasis-alist): New value.
+
+1999-11-06 13:57:13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Use both `read' and
+       `buffer-substring'.
+
+1999-11-06 04:24:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-date-ut): Keep the updated timer.
+       (gnus-emphasis-underline-italic): Doc fix.
+
+       * gnus-msg.el (gnus-post-method): Doc fix.
+       (gnus-post-method): Change default.
+
+1999-11-06 04:12:13  Francisco Solsona  <flsc@hp.fciencias.unam.mx>
+
+       * message.el (message-newline-and-reformat): Improvements.
+
+1999-11-06 03:51:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-newline-and-reformat): Don't insert too many
+       newlines.
+       (message-newline-and-reformat): Work even if not sc.
+
+       * mm-view.el (mm-inline-message): Insert a delimiter at the end.
+
+       * mm-decode.el (mm-inline-media-tests): Only if diff mode.
+
+1999-11-06 03:48:02  Toby Speight  <Toby.Speight@streapadair.freeserve.co.uk>
+
+       * mm-view.el (mm-display-patch-inline): New function.
+
+1999-11-06 03:47:54  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * mm-view.el (mm-display-patch-inline): New function.
+
+1999-11-06 02:17:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-read-move-group-name): Subscribe to the
+       group.
+
+       * message.el (message-forward): Narrow to the right header.
+
+       * gnus-sum.el (gnus-summary-limit-to-age): Protect against bogus
+       dates.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Use the
+       user-full-name function.
+
+       * mm-bodies.el (mm-body-encoding): Use the choosing function.
+       (mm-body-charset-encoding-alist): Default to nil.
+
+       * message.el (message-elide-ellipsis): Fix typo.
+       (message-elide-region): Ditto.
+       (message-elide-region): Don't insert a newline first.
+
+1999-11-05 20:28:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-cut-thread): Also cut for numberp
+       gnus-fetch-old-headers.
+       (gnus-cut-threads): Ditto.
+       (gnus-summary-initial-limit): Ditto.
+       (gnus-summary-limit-children): Ditto.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Allow `header'
+       matches.
+
+1999-11-06  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-art.el (article-decode-encoded-words):
+       (gnus-mime-display-single): Don't assume gnus-summary-buffer is
+       live.
+
+       * gnus.el (gnus-read-method): Add methods from
+       `gnus-opened-servers' to completion. Map entered method/address
+       into existing methods if possible.
+
+       * gnus-group.el (gnus-group-make-group): Simplify method.
+
+       * gnus-srvr.el (gnus-browse-unsubscribe-group): Simplify method.
+
+        * mml.el (mml-preview): Remove mail-header-separator before
+        encoding.
+
+1999-11-05 20:28:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-read-from-minibuffer): New function.
+
+Fri Nov  5 19:10:02 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.98 is released.
+
+1999-11-05 01:27:49  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-expire): Remove bad line in NOV.
+
+1999-11-04 22:20:35  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-generate-mime-1): Read attached binary file in
+       binary mode.
+
+1999-11-03 16:08:56  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Fix arg bug.
+
+1999-11-03 15:27:38  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-viewer-lessp): Fix bug.
+
+1999-11-02 17:28:33  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-search-article): Fix loop search bug.
+
+1999-10-31 21:24:59  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-mime-match-handle-first): New function.
+       (gnus-article-mime-match-handle-function): New variable.
+       (gnus-article-view-part): Make `b' customizable.
+
+1999-10-29 14:30:07  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-article-get-xrefs): Test eobp.
+
+1999-09-27  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-decode.el (mm-attachment-override-types): Exclude text/plain.
+
+1999-10-26 23:27:44  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-buffer): CTE may come without CTL.
+
+1999-10-26 21:44:05  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Use
+       `buffer-substring' instead of `read'.
+
+1999-10-23  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnimap.el, imap.el, rfc2104.el: New files.
+
+       * gnus.el (gnus-valid-select-methods): Add nnimap.
+
+       * gnus-group.el (gnus-group-group-map): Add
+       gnus-group-nnimap-edit-acl, gnus-group-nnimap-expunge.
+       (gnus-group-nnimap-expunge): New function.
+       (gnus-group-nnimap-edit-acl): New function.
+
+       * gnus-agent.el (gnus-agent-group-mode-map): Add
+       gnus-agent-synchronize.
+       (gnus-agent-synchronize): New function.
+       (gnus-agent-fetch-group-1): Check if server is open.
+
+       * nnagent.el (nnagent-request-set-mark): Save marks.
+
+       * mail-source.el (mail-source-keyword-map): New imap mail-source.
+       (mail-source-fetcher-alist): Map to imap fetcher function.
+       (mail-source-fetch-imap): New function.
+
+       * gnus-art.el (article-hide-pgp): Hide all headers, not just
+       Hash:.
+
+1999-10-22 11:03:00  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-topic.el (gnus-topic-sort-topics-1): New function.
+       (gnus-topic-sort-topics): New function.
+       (gnus-topic-make-menu-bar): Add sort-topics.
+       (gnus-topic-move): New function.
+       (gnus-topic-move-group): Move the topic if no group selected.
+
+1999-10-13 21:31:50  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-setup-buffer): Fix buffer leak.
+
+1999-10-13 12:52:18  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-message): Fix leaving group bug.
+
+1999-10-07 17:59:49  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-post-method): Use normal method if current is
+       not available.
+
+1999-10-07 17:09:34  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-insert-xref): Dealing with empty articles.
+       (nnmail-insert-lines): Ditto.
+
+1999-10-07  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-insert-newsgroup-line): Insert a blank
+       line.
+
+       * message.el (message-unsent-separator): One more separator.
+
+1999-10-06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-move-article): For empty article,
+       search till (point-max).
+       (nnfolder-retrieve-headers): Ditto.
+       (nnfolder-request-accept-article): Ditto.
+       (nnfolder-save-mail): Ditto.
+       (nnfolder-insert-newsgroup-line): Ditto.
+
+1999-10-05  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encode-region): Check eobp.
+
+1999-10-03  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-retrieve-headers-with-xover): Fix hanging problem.
+
+1999-10-02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nntp.el (nntp-send-xover-command): Wait for nothing if not
+       wait-for-reply.
+
+1999-09-29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-forward-begin-line): Change the regexp.
+       (mm-uu-forward-end-line): Ditto.
+
+1999-09-29  Didier Verna  <verna@inf.enst.fr>
+
+       * binhex.el (binhex-decode-region): don't consider the value of
+       `enable-multibyte-characters' in XEmacs.
+
+       * gnus-start.el (gnus-read-descriptions-file): ditto.
+
+       * mm-util.el (mm-multibyte-p): ditto.
+       (mm-with-unibyte-buffer): ditto.
+       (mm-find-charset-region): use `mm-multibyte-p'.
+
+       * mm-bodies.el (mm-decode-body): ditto.
+       (mm-decode-string): ditto.
+
+       * lpath.el ((string-match "XEmacs" emacs-version)): Don't define
+       `enable-multibyte-characters' in XEmacs.
+
+1999-09-29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-binary-coding-system): Try binary first.
+
+1999-09-14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc1843.el (rfc1843-decode-article-body): Don't decode twice.
+
+1999-09-10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-make-date-line): Add time-zone in iso8601
+       format.
+       (article-date-ut): Find correct insert position.
+
+1999-09-03  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Do not dissect quoted-printable
+       forwarded message.
+
+1999-09-27 20:33:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-topic.el (gnus-topic-find-groups): Work for unactivated
+       groups.
+
+       * message.el (message-resend): Use message mode when prompting.
+
+       * gnus-art.el (article-hide-headers): Mark wash.
+       (article-emphasize): Ditto.
+
+1999-09-27 19:52:14  Vladimir Volovich  <vvv@vvv.vsu.ru>
+
+       * message.el (message-newline-and-reformat): Work for SC.
+
+1999-09-27 19:38:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): 2047 in de.*.
+
+       * gnus-sum.el (gnus-newsgroup-ignored-charsets): Add x-unknown.
+
+1999-10-20  David S. Goldberg  <dsg@mitre.org>
+
+       * mm-decode.el mm-inline-override-types: New variable
+
+       * mm-decode.el (mm-inline-override-p): New function
+
+       * mm-decode.el (mm-inlined-p): Use it
+
+1999-10-20  David S. Goldberg  <dsg@mitre.org>
+
+       * mm-decode.el mm-inline-override-types: New variable
+
+       * mm-decode.el (mm-inline-override-p): New function
+
+       * mm-decode.el (mm-inlined-p): Use it
+
+Mon Sep 27 15:18:05 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.97 is released.
+
+1999-09-01  Brendan Kehoe  <brendan@zen.org>
+
+       * gnus-sum.el (gnus-summary-catchup-and-goto-next-group): Use
+       gnus-summary-next-group, not gnus-summary-next-article.  Only give
+       3 args.
+
+1999-09-25 08:07:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Look in the group
+       buffer for params.
+
+       * gnus-xmas.el (gnus-xmas-summary-recenter): Display one more
+       line.
+
+       * message.el (message-forward-ignored-headers): New variable.
+
+       * gnus-art.el (gnus-article-prepare-display): Nix out
+       gnus-article-wash-types.
+
+       * gnus-agent.el (gnus-agent-create-buffer): New function.
+       (gnus-agent-fetch-group-1): Use it.
+       (gnus-agent-start-fetch): Ditto.
+
+       * gnus-sum.el (gnus-summary-exit): Don't use
+       `gnus-use-adaptive-scoring'.
+
+       * mail-source.el (mail-source-fetch-pop): Only store password when
+       successful.
+
+       * gnus-nocem.el (gnus-nocem-scan-groups): Message better.
+
+1999-09-24 18:43:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-reply): Use it.
+       (message-dont-reply-to-names): New variable.
+
+       * nntp.el (nntp-open-telnet): Don't erase-buffer.
+
+       * mm-util.el (mm-preferred-coding-system): Typo fix.
+
+       * message.el (message-bounce): Work for non-MIME.
+
+       * gnus.el (gnus-short-group-name): Short the right parts of the
+       name.
+
+1999-09-24 18:17:48  Johan Kullstam  <kullstam@ne.mediaone.net>
+
+       * mm-encode.el (mm-qp-or-base64): New version.
+
+1999-09-10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-make-date-line): Fix time-zone bug.
+
+1999-09-09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-article-add-buttons): Don't delete markers out
+       of restricted region.
+       (gnus-mime-display-single): Set beg at correct point.
+
+1999-09-09  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-process-maildir-mail-format): Typo.
+
+1999-09-09  Jens-Ulrik Petersen <jens-ulrik.petersen@nokia.com>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Let
+       `gnus-posting-styles' have its say in posting-style: local
+       variable `styles' is already bound to `gnus-posting-styles' so
+       don't rebind it to nil.
+
+1999-09-24 18:10:56  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * gnus-score.el (gnus-summary-increase-score): Allow editing of
+       Message-ID.
+
+1999-09-08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-encode.el (mm-encode-content-transfer-encoding): Fold
+       quoted-printable-encode-region.
+
+       * qp.el (quoted-printable-encode-region): Assume charset
+       encoded. Fold every line in the region.
+
+1999-09-02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Read the first line
+       of active file.
+
+1999-09-01  Didier Verna  <verna@inf.enst.fr>
+
+       * message.el (message-mode): allows whitespaces between multiple
+       instances of the fill character ">".
+
+1999-09-24 18:02:50  Kim-Minh Kaplan  <kmkaplan@vocatex.fr>
+
+       * mm-encode.el (mm-qp-or-base64): Fix.
+
+1999-09-01 12:18:01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+        * message.el (message-send): Too much and.
+
+1999-09-24 17:58:07  Andreas Schwab  <schwab@suse.de>
+
+       * gnus-art.el (gnus-mime-view-part-as-type): Renamed.
+
+1999-08-28 12:44:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-headers): Work for nil scores.
+
+1999-08-27 20:46:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cache.el (gnus-cache-write-active): Write full names.
+
+       * gnus-util.el (gnus-write-active-file): Accept full name.
+
+       * mm-decode.el (mm-inlinable-p): Use string-match on the types.
+       (mm-assoc-string-match): New function.
+       (mm-display-inline): Use it.
+
+       * gnus-group.el (gnus-group-set-info): Work for nil group params.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Allow eval.
+
+1999-08-27 19:08:10  Florian Weimer  <fw@s.netic.de>
+
+       * mml.el (mml-generate-multipart-alist): New variable.
+
+1999-08-27 15:30:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-predicate): Work for (not 5).
+
+1999-08-27  Peter von der Ahe <pahe@daimi.au.dk>
+
+       * message.el (message-send): More helpful error message if sending
+       fails
+
+1999-09-06  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * gnus-score.el (gnus-summary-increase-score): "Lars" was broken
+       in newer emacsen, where ?r isn't equal 114.
+
+Fri Aug 27 13:17:48 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.96 is released.
+
+1999-08-17  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-start.el (gnus-groups-to-gnus-format): Only use agent
+       to get active info if method is covered by agent, otherwise
+       active info is lost.
+
+1999-08-17  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-summary-move-article): Report backend errors.
+
+1999-08-09  Dave Love  <fx@gnu.org>
+
+       * mm-util.el: Use `defalias', not `fset' for dummy functions.
+
+1999-08-09  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-art.el (gnus-ignored-headers): Remove "X-Pgp-*"
+          (already matched by "^X-Pgp"), removed duplicate
+          X-Mailing-List, added several new junk headers.
+
+1999-08-01  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-art.el (article-decode-charset): Don't assume
+       gnus-summary-buffer is live.
+
+1999-08-27 15:07:43  Paul Flinders  <paul@dawa.demon.co.uk>
+
+       * smiley.el (smiley-deformed-regexp-alist): Fix % smileys.
+
+1999-08-27 15:02:58  Florian Weimer  <fw@s.netic.de>
+
+       * gnus-score.el (gnus-home-score-file): Work with absolute path
+       names.
+
+1999-07-17  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-articles-to-read): Return cached articles if
+       nothing else in the group.
+
+1999-07-16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-bcklg.el (gnus-backlog-enter-article): Check the size of
+       the article.
+
+1999-07-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Fix for base64 message.
+
+1999-07-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-forward-end-line): Support forwarded message
+       from mutt.
+
+1999-07-14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Delete
+       whitespace.
+
+1999-07-14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-text-coding-system-for-write): New variable.
+       (mm-append-to-file): New function.
+       (mm-write-region): New function.
+
+       * gnus-art.el (gnus-output-to-file): Use it.
+       * gnus-util.el (gnus-output-to-rmail): Ditto.
+       (gnus-output-to-mail): Ditto.
+       * gnus-uu.el (gnus-uu-binhex-article): Ditto.
+
+1999-07-14  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-find-file): Use mm-auto-mode-alist.
+
+       * nnheader.el (nnheader-insert-file-contents): Revert and use
+       mm-insert-file-contents.
+       (nnheader-find-file-noselect): Use mm-auto-mode-alist.
+       (nnheader-auto-mode-alist): Removed.
+
+       * mm-util.el (mm-inhibit-file-name-handlers): New variable.
+       (mm-insert-file-contents): Add a new parameter for inserting
+       compressed file literally.
+
+       * mml.el (mml-generate-mime-1): Insert non-text literally.
+
+       * gnus.el: Change most mm-insert-file-contents back to nnheader.
+
+1999-07-13  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (gnus-unbuttonized-mime-types): Fix docstring.
+
+1999-08-27 14:53:42  Oleg S. Tihonov  <ost@benetnash.ffke-campus.mipt.ru>
+
+       * gnus-sum.el (gnus-group-charset-alist): Default fido7 to
+       koi8-r.
+
+1999-07-11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-insert-mime): Decode text.
+       (mml-to-mime): Narrow to headers-or-head.
+
+1999-07-11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Check
+       w3-meta-content-type-charset-regexp.
+
+1999-07-10  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Search topics for
+       predicate.
+
+1999-07-10  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+        * gnus-mlspl.el: Documentation fixes.
+
+1999-08-27 14:42:14  Rui Zhu  <sprache@iname.com>
+
+       * gnus-sum.el (gnus-summary-limit-to-age): Prompt better.
+
+1999-08-27 14:40:52  Michael Cook  <cook@sightpath.com>
+
+       * gnus-art.el (gnus-article-setup-buffer): Kill all local
+       variables.
+
+1999-08-27 14:39:34  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * nnmail.el (nnmail-get-new-mail): "Done".
+
+1999-08-27 14:38:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-kill-all-zombies): Only prompt when
+       interactive.
+
+1999-07-12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-charset): Fix broken CT.
+
+1999-07-12  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Recreate agent
+       overview buffer if it is killed.
+
+1999-08-27 14:26:03  Eric Marsden  <emarsden@mail.dotcom.fr>
+
+       * gnus-art.el (article-babel): New version.
+
+1999-08-27 14:22:39  Jon Kv  <jonkv@ida.liu.se>
+
+       * nnfolder.el (nnfolder-request-list-newsgroups): Faster expiry.
+
+1999-07-10  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus.texi (More Threading): Document new variable
+       `gnus-sort-gathered-threads-function'.
+
+1999-07-10  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus.texi (More Threading): Document new variable
+       `gnus-sort-gathered-threads-function'.
+
+1999-07-11  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Delete file after
+       usage.
+
+1999-07-10  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-running-xemacs): Removed.
+       (mm-coding-system-p): New function.
+       (mm-binary-coding-system): Safe guess.
+       (mm-text-coding-system): Ditto.
+       (mm-auto-save-coding-system): Ditto.
+
+1999-07-11 11:02:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-encode.el (mm-qp-or-base64): Also consider control chars.
+       (mm-qp-or-base64): Reversed logic.
+
+       * mm-decode.el (mm-save-part-to-file): Let coding system be
+       binary.
+
+1999-07-15  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Allow 'agent-score' to
+       be set in topic parameters.
+
+1999-07-10  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-sum.el (gnus-sort-gathered-threads-function): New variable.
+       (gnus-sort-gathered-threads): Allow the user to specify the
+       function to use when sorting gathered threads.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Don't
+       mark cached articles as `undownloaded'.
+
+Tue Jul 20 02:39:56 1999  Peter von der Ahe  <peter@ahe.dk>
+
+       * gnus-sum.el (gnus-summary-exit): Allow gnus-use-adaptive-scoring
+       to have buffer local values.
+
+1999-07-25  Matt Pharr  <mmp@graphics.stanford.edu>
+
+       * gnus-group.el (gnus-group-make-doc-group): Notice when user
+       types 'g' for 'guess group type.
+
+1999-07-30  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nnmail.el (nnmail-remove-list-identifiers): Remove whitespace
+       after each regexp in nnmail-list-identifiers, not just after last
+       one.
+
+       * gnus-sum.el (gnus-list-identifiers): New variable.
+       (gnus-summary-remove-list-identifiers): New function.
+       (gnus-select-newsgroup): Use it.
+       (gnus-summary-wash-hide-map): Bind
+       `gnus-article-hide-list-identifiers' to W W l.
+       (gnus-summary-make-menu-bar): Add list-identifiers command.
+
+       * gnus-art.el (gnus-treat-strip-list-identifiers): New variable.
+       (gnus-treatment-function-alist): Add variable.
+       (article-hide-list-identifiers): New function.
+       (mapcar): Add function.
+       (gnus-article-hide): Use it.
+
+Fri Jul  9 22:21:16 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.95 is released.
+
+1999-07-09 21:46:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-mailcap-command): New function.
+       (mm-display-external): Use it.
+
+       * gnus-art.el (article-make-date-line): Work for India.
+
+       * mm-encode.el (mm-qp-or-base64): Typo.
+
+       * gnus-topic.el (gnus-topic-goto-topic): Made into command.
+
+Fri Jul  9 19:28:29 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.94 is released.
+
+1999-07-09 21:19:23  Stainless Steel Rat  <ratinox@peorth.gweep.net>
+
+       * pop3.el: New version.
+
+1999-07-09 20:01:44  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-encode.el (mm-qp-or-base64): New function.
+       (mm-content-transfer-encoding): Use it.
+
+       * gnus-util.el (gnus-parse-netrc): Allow quoted names.
+
+1999-07-08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-external): Fix typo and use 'non-viewer.
+
+       * mailcap.el (mailcap-mailcap-entry-passes-test): Add needsterminal.
+
+1999-07-09 18:52:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-view-part-as-media): New command and
+       keystroke.
+
+       * mailcap.el (mailcap-mime-types): New function.
+
+       * nnmh.el (nnmh-request-group): Update nnmh-group-alist.
+
+       * message.el (message-goto-eoh): Really go to the end.
+
+1999-07-09 18:40:23  Puneet Goel  <puneet@computer.org>
+
+       * message.el (message-make-date): Do the right thing in with
+       sub-hour time zones.
+
+1999-07-09 18:36:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-make-menu-bar): Removed double bug
+       report.
+
+1999-07-08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-request-rename-group): Create directory.
+
+1999-07-08  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mailcap.el (mailcap-parse-mailcap): Skip \;.
+       (mailcap-parse-mailcap-extras): Fix "nonterminal;" and empty name,
+       and use t as default value.
+
+Wed Jul  7 18:40:30 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Don't assume
+       gnus-summary-buffer is live.
+
+1999-07-09 17:44:03  Robert Pluim  <rpluim@nortelnetworks.com>
+
+       * mm-util.el (mm-enable-multibyte): Check whether var bound.
+
+1999-07-09 17:31:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-bounce): Do MIME bounces MIMEy.
+
+       * gnus-sum.el (gnus-summary-read-group-1): Update mark positions.
+
+1999-07-08 08:41:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-extensions): Changed patch to
+       text/x-patch.
+
+       * mm-decode.el (mm-display-external): Wrong placement of paren.
+
+Wed Jul  7 13:09:51 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.93 is released.
+
+1999-07-08  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+        * gnus-cus.el (gnus-group-parameters): New entries for
+        gnus-group-split.
+
+        * gnus-mlspl.el: Renamed functions and variables so as to
+        start with gnus-group-split.
+        * gnus.el: Adjust autoload entries.
+
+1999-07-07 ??:??:??  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * gnus-mlspl.el: Removed trailing t from comment and provide.
+       Renamed functions and variables to start with gnus-mlsplit.
+       Added autoload comments.
+       * gnus.el: Added autoload entries.
+
+1999-07-06 05:37:46  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * nnmail.el (nnmail-split-it): Search the regexp multiple times,
+       so that matches excluded by RESTRICTs do not cause the whole split
+       to be ignored.  This also fixes a long-standing bug in which a
+       split with \N substitutions wouldn't cause cross-posting as
+       expected.
+
+       * nnmail.el (nnmail-split-fancy): Document RESTRICT clauses.
+       (nnmail-split-it): Implement them.
+
+       * nnmail.el (nnmail-split-fancy): Document ! splits.
+
+1999-07-07 10:41:11  Stainless Steel Rat  <ratinox@peorth.gweep.net>
+
+       * pop3.el: New version.
+
+1999-07-05  Simon Josefsson
+
+        * gnus-srvr.el (gnus-browse-foreign-server): Use read.
+
+1999-07-07 10:37:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-display-alternative): Do treatment.
+
+1999-07-06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-write-active-file): Use real name.
+
+       * gnus-agent.el (gnus-agent-expire): Update active file
+       method by method.
+
+1999-07-06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nndraft.el (nndraft-request-article): Use difference
+       coding-systems for queue and drafts.
+
+       * gnus-sum.el (gnus-summary-setup-default-charset): Special-case
+       nndraft:drafts.
+
+       * mm-util.el (mm-auto-save-coding-system): New coding system.
+
+       * message.el (message-draft-coding-system): Use it.
+
+1999-07-06  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el: More customizable and less aggressive.
+
+1999-07-07 07:53:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-groups-to-gnus-format): Only gnus-active
+       when plugged.
+
+       * mml.el (mml-generate-mime-1): Don't insert nofile files.
+       (mml-insert-mml-markup): Accept a nofile.
+       (mml-insert-mime): Insert nofile.
+
+       * gnus-art.el (gnus-treat-strip-blank-lines): Removed.
+
+       * mm-decode.el (mm-handle-media-type): New function.
+       (mm-handle-media-supertype): New function.
+       (mm-handle-media-subtype): New function.
+       Use new functions throughout. "/"))
+
+1999-05-18 03:03:50  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-treat-predicate): Typo.
+
+1999-07-07 06:21:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-summary-score-entry): Made un-interactive.
+
+1999-07-06 17:57:16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-date-ut): UT!  Default it!
+
+Tue Jul  6 10:59:24 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.92 is released.
+
+1999-07-06 12:30:59  Johannes Weinert  <Johannes.Weinert@Informatik.Uni-Oldenburg.DE>
+
+       * gnus-sum.el (gnus-summary-catchup-and-exit): Doc fix.
+
+1999-07-06 07:41:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nntp.el (nntp-retrieve-groups): Don't do anything when not
+       connected.
+
+       * gnus-start.el (gnus-active-to-gnus-format): Only save active
+       when plugged.
+
+       * mm-view.el (mm-inline-message): Ignore remove-spec.
+
+       * gnus-agent.el (gnus-agent-write-active): Check whether orig sym
+       is bound.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Rename From_ lines.
+
+       * nndoc.el (nndoc-guess-type): Remove blank lines at the start.
+
+       * nnfolder.el (nnfolder-read-folder): Remove blank lines at the
+       start.
+
+       * message.el (message-fill-yanked-message): Remove `t' arg.
+
+       * gnus-group.el (gnus-group-kill-group): Message killing of
+       groups.
+
+       * mm-util.el (mm-preferred-coding-system): New function.
+       (mm-mime-charset): Use it.
+
+       * mml.el (mml-generate-mime-1): Charset-encode message parts.
+
+1999-07-06 07:03:31  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * gnus-mlsplt.el: New file.
+
+1999-07-06 05:47:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-Media-tests): Changed from forms to
+       functions.
+       (mm-attachment-override-p): Take a handle instead of a type.
+       (mm-inlined-p): Ditto.
+       (mm-automatic-display-p): Ditto,
+       (mm-inlinable-p): Ditto.
+
+       * nndraft.el (nndraft-request-expire-articles): Delete backup
+       files.
+
+       * mailcap.el (mailcap-parse-mailcap): Regexp-quote stuff.
+
+       * gnus-sum.el (gnus-summary-limit-to-extra): Typo.
+
+1999-07-06 05:37:46  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+       * nnmail.el (nnmail-split-it): Allow .*.
+
+1999-07-05 05:04:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-large-images-p): Renamed.
+
+       * gnus-art.el (article-date-ut): Always look in the current buffer
+       for the Date header.
+
+       * mml.el (mml-validate): New command.
+
+       * mailcap.el (mailcap-possible-viewers): Revert to string-match
+       since we are dealing with regexps.
+
+Sun Jul  4 06:31:01 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.91 is released.
+
+1999-07-04 04:35:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-save-active-1): New function.
+       (gnus-agent-save-active): use it.
+       (gnus-agent-save-groups): Ditto.
+
+       * gnus-cache.el (gnus-cache-write-active): Use it.
+
+       * gnus-agent.el (gnus-agent-write-active): Use it.
+
+       * gnus-util.el (gnus-write-active-file): New function.
+
+       * gnus-agent.el (gnus-agent-write-active): New function to keep
+       lower boundaries and canceled groups.
+       (gnus-agent-save-groups): Use it.
+       (gnus-agent-save-active): Use it.
+       (gnus-agent-save-group-info): Only write active files.
+       (gnus-agent-expire): Update active file.
+
+       * mm-decode.el (mm-inlinable-part-p): Removed.
+       (mm-user-display-methods): Default to nil.
+       (mm-user-display-methods): Removed.
+       (add-mime-display-method): Removed.
+       (mm-automatic-display): Renamed.
+       (mm-automatic-display-p): Use it.
+       (mm-inlined-types): New variable.
+       (mm-inlined-p): New function.
+
+       * message.el (message-reply): Bind message-this-is-mail.
+
+1999-07-03 13:16:31  Michael Klingbeil  <mklingbeil@knuut.de>
+
+       * smiley.el (smiley-buffer): Fix for NT.
+
+1999-07-03 11:26:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-encode.el (mm-encode-buffer): Check whether we have 7bit.
+
+       * message.el (message-check-news-header-syntax): Protect against
+       nil froms.
+
+       * mm-util.el (mm-auto-mode-alist): New.
+
+       * mml.el (mml-generate-mime-1): Ditto.
+
+       * gnus.el: Use mm-insert-file-contents throughout instead of
+       nnheader.
+
+       * mm-util.el (mm-insert-file-contents): New function.
+
+Sat Jul  3 07:35:35 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.90 is released.
+
+1999-07-03 09:31:10  Sven Fischer  <herpes@kawo2.rwth-aachen.de>
+
+       * mailcap.el (mailcap-possible-viewers): Use string=.
+
+1999-07-01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-forward-begin-line): New variable.
+       (mm-uu-forward-end-line): New variable.
+       (mm-uu-begin-line): Handle forwarded message.
+       (mm-uu-identifier-alist): Ditto.
+       (mm-uu-dissect): Ditto.
+
+1999-06-29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * lpath.el: Two free variables.
+
+1999-07-02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnheader.el (nnheader-file-coding-system): Use raw-text.
+       * gnus-agent.el (gnus-agent-file-coding-system): Ditto.
+       * gnus-cache.el (gnus-cache-coding-system): Ditto.
+
+       * nnfolder.el (nnfolder-file-coding-system): Use mm-text-coding-system.
+       (nnfolder-file-coding-system-for-write): New variable.
+       (nnfolder-active-file-coding-system): New variable.
+       (nnfolder-active-file-coding-system-for-write): New variable.
+       (nnfolder-save-active): New function.
+       (nnfolder-save-buffer): Use them.
+       (nnfolder-possibly-change-group): Ditto.
+       (nnfolder-request-list-newsgroups): Ditto.
+       (nnfolder-request-create-group): Ditto.
+       (nnfolder-request-expire-articles): Ditto.
+       (nnfolder-request-move-article): Ditto.
+       (nnfolder-request-accept-article): Ditto.
+       (nnfolder-request-delete-group): Ditto.
+       (nnfolder-request-rename-group): Ditto.
+       (nnfolder-possibly-change-folder): Ditto.
+       (nnfolder-read-folder): Ditto.
+       (nnfolder-request-list): Remove pathname-coding-system.
+       (nnfolder-possibly-change-group): Use nnmail-pathname-coding-system.
+
+       * nnmail.el (nnmail-file-coding-system): Use raw-text.
+       (nnmail-file-coding-system-1): Removed.
+       (nnmail-find-file): Use nnmail-pathname-coding-system.
+       (nnmail-write-region): Ditto.
+
+       * nnmbox.el (nnmbox-file-coding-system): New variable.
+       (nnmbox-file-coding-system-for-write): New variable.
+       (nnmbox-active-file-coding-system): New variable.
+       (nnmbox-active-file-coding-system-for-write): New variable.
+       (nnmbox-save-buffer): New function.
+       (nnmbox-save-active): New function.
+       (nnmbox-request-scan): Use them.
+       (nnmbox-request-expire-articles): Ditto.
+       (nnmbox-request-move-article): Ditto.
+       (nnmbox-request-accept-article): Ditto.
+       (nnmbox-request-replace-article): Ditto.
+       (nnmbox-request-delete-group): Ditto.
+       (nnmbox-request-rename-group): Ditto.
+       (nnmbox-request-create-group): Ditto.
+
+       * mm-util.el (mm-text-coding-system): raw-text or -dos.
+       (mm-running-ntemacs): Removed.
+
+       * nnml.el (nnml-file-coding-system): Use nnmail-file-coding-system.
+
+1999-07-02  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnfolder.el (nnfolder-read-folder): Use nnheader-file-coding-system.
+
+1999-07-01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * qp.el (quoted-printable-encoding-characters): Support lower case.
+
+1999-07-01  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode): Fold before B-encoding.
+       (rfc2047-b-encode-region): Encode line by line.
+
+1999-07-03 09:20:16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-find-mime-charset-region): Fix.
+
+1999-06-30  KOSEKI Yoshinori  <kose@yk.NetLaputa.ne.jp>
+
+       * mm-util.el (mm-mime-mule-charset-alist): Fix iso-2022-jp(-2) bug.
+       (mm-find-mime-charset-region): Ditto.
+
+1999-07-03 09:15:35  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-summary-move-article): Fix something or
+       other.
+
+1999-06-29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-newsgroup-ephemeral-charset): New variable.
+       (gnus-newsgroup-ephemeral-ignored-charsets): New variable.
+       (gnus-summary-enter-digest-group): Use them.
+       (gnus-summary-setup-default-charset): Ditto.
+
+1999-06-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * base64.el (base64-run-command-on-region): Use unibyte buffer.
+
+1999-06-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-msg.el (gnus-configure-posting-styles): Fix bug when
+          gnus-newsgroup-name is nil.
+
+1999-06-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-encode): Chop the tail newline.
+
+1999-06-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-emphasize): Use correct
+       gnus-article-emphasis-alist.
+
+1999-06-15  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Fix text/html bug.
+
+Mon Jun 28 17:54:01 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.89 is released.
+
+1999-06-24  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-file-coding-system-1): For NTEmacs in Windows.
+       * message.el (message-draft-coding-system): Ditto.
+       * mm-util.el (mm-running-ntemacs): Ditto.
+
+1999-06-23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-summary-recenter): A blank line may
+       cause problem.
+
+1999-06-23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Ignore error in w3-region.
+
+1999-06-23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el: require mm-decode.
+
+1999-06-23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-display-mime): Treat as head only if necessary.
+
+1999-06-23  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-image): Fix image undisplayer.
+
+1999-06-22  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mml.el (mml-insert-multipart): Error in compeling-read.
+       (mml-insert-tag): Match tags.
+
+1999-06-19  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-cache-braid-nov): Fix coding-system bug.
+       (gnus-cache-braid-heads): Ditto.
+       (gnus-cache-retrieve-headers): Ditto.
+
+1999-06-16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-draft.el (gnus-draft-send): Fix encoding bug.
+
+1999-06-16 10:17:29  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-art.el (gnus-article-read-summary-keys): Convert key events
+       to string under XEmacs.
+
+1999-06-28 19:34:03  Petersen Jens-Ulrik  <jens-ulrik.petersen@nokia.com>
+
+       * gnus-start.el (gnus-find-new-newsgroups): Doc fix.
+
+1999-06-22  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-message): Fix message view bug.
+       * gnus-art.el (gnus-article-prepare): Ditto.
+
+1999-06-16  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Fetch headers.
+
+Tue Jun 15 04:13:01 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.88 is released.
+
+1999-06-15 04:13:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-save-parts): Destroy handles after
+       usage.
+
+       * nnmail.el (nnmail-get-new-mail): Save info.
+
+Mon Jun 14 01:15:59 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.87 is released.
+
+1999-06-14 02:46:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-file): Use prescript-delay.
+       (mail-source-run-script): New function.
+       (mail-source-fetch-pop): Use it.
+
+1999-06-13 09:52:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-setup-highlight-words): Moved here.
+
+Sun Jun 13 07:30:40 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.86 is released.
+
+1999-06-13 08:51:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-translate): New variable.
+       (gnus-treat-predicate): Accept a list of regexps.
+       (gnus-article-treat-custom): Allow a list of regexps.
+
+1999-06-09  Markus Rost  <markus.rost@mathematik.uni-regensburg.de>
+
+       * gnus/gnus-group.el (gnus-permanently-visible-groups): Fix custom
+       type.
+
+1999-06-13 05:15:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-babel): Narrow a bit.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Was too slow.
+
+1999-06-12  Simon Josefsson  <jas@pdc.kth.se>
+
+        (gnus-agent-get-undownloaded-list): Operate on all articles, not
+        only unread ones.
+        (gnus-agent-fetch-headers): Fetch headers from unread and marked
+        articles, not only unread ones.
+
+1999-06-13 03:01:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-limit-to-extra): New command and
+       keystroke.
+
+       * gnus-art.el (gnus-article-x-face-command): Ditto.
+
+       * gnus-uu.el (gnus-uu-default-view-rules): Default to "display".
+
+       * gnus.el (gnus-method-simplify): Accept server names.
+
+1999-06-13 02:36:15  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (article-babel-prompt): New function.
+       (article-babel): New command.
+
+1999-06-13 01:01:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-part-wrapper): Go to part.
+
+       * mml.el (mml-generate-mime-1): Don't insert literally.
+
+       * gnus-util.el (gnus-parse-netrc): Skip lines with #'s.
+       (gnus-netrc-syntax-table): Removed.
+       (gnus-parse-netrc): Don't use syntax table; just use whitespace.
+
+Wed May  5 13:51:13 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Fix charset for text/html.
+
+Wed May  5 01:15:08 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-draft-coding-system): Use emacs-mule-dos.
+
+1999-06-12 07:29:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-split-incoming): Return the number of split
+       mails.
+       (nnmail-process-babyl-mail-format): Ditto.
+       (nnmail-process-unix-mail-format): Ditto.
+       (nnmail-process-mmdf-mail-format): Ditto.
+       (nnmail-process-maildir-mail-format): Ditto.
+
+       * mail-source.el (mail-source-callback): Return the number from
+       the callback.
+
+       * message.el (message-send-mail): Generate Lines.
+
+       * mail-source.el (mail-source-call-script): New function.
+       (mail-source-call-script): New function.
+
+Sun May  2 02:00:27 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-setup-highlight-words): New function.
+       (gnus-select-newsgroup): Use it.
+       (gnus-group-highlight-words-alist): New variable.
+       (gnus-newsgroup-emphasis-alist): New variable.
+       (gnus-summary-local-variables):  Use it.
+       * lpath.el: Use it.
+       * gnus-art.el (article-emphasize): Use it.
+       (gnus-emphasis-highlight-words): New face.
+       * gnus-cus.el (gnus-group-parameters): New parameter.
+
+Sun May  2 01:00:02 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Remove
+       parameter `headers'.
+       (gnus-cache-enter-article): Ditto.
+       (gnus-cache-update-article): Ditto.
+       * gnus-sum.el (gnus-summary-move-article): Ditto.
+       (gnus-summary-mark-article-as-unread): Ditto.
+       (gnus-summary-mark-article): Ditto.
+
+1999-06-12 03:59:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-message-insert-stylings): Removed.
+       (gnus-posting-style-alist): Removed.
+       (gnus-message-style-insertions): Ditto.
+       (gnus-configure-posting-styles): Reimplementation.
+
+       * mail-source.el (mail-source-fetch): Error the message.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Do mml and encoding.
+
+Sat Jun 12 00:19:57 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.85 is released.
+
+1999-04-20  Michael Cook  <cook@sightpath.com>
+
+       * gnus-cite.el (gnus-cite-attribution-prefix): Tweak for MS
+         Outlook citation regex.
+
+1999-06-12 02:09:49  Lars Magne Ingebrigtsen  <pinard@iro.umontreal.ca>
+
+       * nndoc.el (nndoc-mime-parts-type-p): Accept space before
+       semicolon.
+
+1999-05-24  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-range.el (gnus-remove-from-range): Document range1
+       modification, protect range2.
+
+1999-05-24  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-marks): Protect lists from
+       gnus-remove-from-range, don't sort twice.
+
+1999-05-21  Simon Josefsson  <jas@pdc.kth.se>
+
+        * gnus-start.el (gnus-read-descriptions-file): Protect if no
+        function in backend.
+
+1999-05-15  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-valid-move-group-p): Check for a
+       request-accept-article function in the backend instead of using
+       the 'respool capability.
+
+1999-04-18  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Handle
+       spurious whitespace at eob.
+
+1999-06-12 02:02:06  Adrian Aichner  <aichner@ecf.teradyne.com>
+
+       * nnmail.el (nnmail-get-new-mail): Check right variable.
+
+1999-06-12 01:57:39  Karl Kleinpaste  <karl@justresearch.com>
+
+       * mailcap.el (mailcap-mime-data): Fix rfc822.
+
+1999-06-11 23:48:50  TOZAWA Akihiko  <miles@is.s.u-tokyo.ac.jp>
+
+       * nndoc.el (nndoc-nsmail-type-p): New function.
+       (nndoc-type-alist): Recognize nsmail.
+
+1999-05-12  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-art.el (gnus-treatment-function-alist): Display `x-face'
+       *before* `article-hide-headers' deletes the information.
+
+1999-05-22 00:26:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-save-parts): New command and
+       keystroke.
+       (gnus-summary-save-parts-1): New function.
+       (gnus-summary-iterate): Buggy.
+
+       * mm-decode.el (mm-save-part-to-file): Made into own function.
+
+1999-05-11 05:53:16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-set-info): Resist nils.
+
+1999-05-04 19:26:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-data): Ditto.
+
+       * gnus-uu.el (gnus-uu-default-view-rules): Ditto.
+
+       * gnus-art.el (gnus-article-x-face-command): Default to ee.
+
+1999-05-02  Gareth Jones  <gdj1@gdjones.demon.co.uk>
+
+       * gnus-art.el (article-make-date-line): Put X-Sent below Date if
+       gnus-article-date-lapsed-new-header is t.
+
+Sat May  1 20:27:43 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.84 is released.
+
+1999-05-01 22:23:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-bug-message): Mime change.
+
+1999-04-22  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-marks): Process null mark lists.
+
+1999-04-21  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Recognize
+       `x-uue'.
+
+1999-03-04  Aaron M. Ucko  <amu@mit.edu>
+
+       * mail-source.el (mail-source-fetch-pop): Only prompt for password
+       when authentication is 'password.
+
+1999-05-01 22:17:55    <pinard@iro.umontreal.ca>
+
+       * gnus-win.el (gnus-configure-windows): Accept a setting.
+
+1999-04-21 20:51:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-quote-arg): Moved here.
+
+       * mm-decode.el (mm-quote-arg): Quote more chars.
+
+1999-04-18 20:12:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el (nnheader-parse-head): Message-ID in In-Reply-To
+       with newlines would create buggy .nov files.
+
+       * gnus-art.el (gnus-article-date-lapsed-new-header): Default to nil.
+
+       * qp.el (quoted-printable-encode-region): Encode whitespace at the
+       end of lines.
+
+       * message.el (message-mode): Doc fix.
+
+       * gnus-art.el (article-hide-headers): Delete the hidden headers.
+
+       * gnus-msg.el (gnus-setup-posting-charset): Default group to "".
+
+       * gnus-art.el (article-date-ut): Rewrite.
+
+       * mm-decode.el (mm-preferred-alternative-precedence): Reverse the
+       order.
+
+       * gnus-msg.el (gnus-message-insert-stylings): Remove duplicate
+       headers.
+
+       * gnus-art.el (gnus-article-date-lapsed-new-header): Doc fix.
+
+1999-04-18  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-art.el (gnus-article-date-lapsed-new-header): new variable.
+       (article-date-ut): use it.
+
+1999-04-18 20:06:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-pop): Call script
+       asynchronously.
+
+Sun Apr 18 12:40:04 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.83 is released.
+
+1999-04-18 10:55:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el (gnus-draft-mode): Use mml minor mode.
+
+       * gnus-cite.el (gnus-dissect-cited-text): Off-by-one error.
+
+       * gnus-uu.el (gnus-uu-mark-thread): Save hidden threads.
+
+       * gnus-art.el (gnus-mime-inline-part): Don't do a charset param.
+
+       * gnus-msg.el (gnus-bug): Use application/x-emacs-lisp.
+
+       * message.el (message-generate-headers): Accept continuation
+       headers.
+
+1999-04-18 10:48:57  Renaud Rioboo  <Renaud.Rioboo@lip6.fr>
+
+       * gnus-demon.el (gnus-demon-time-to-step): Not strings.
+
+1999-04-18 08:21:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treatment-function-alist): use
+       maybe-hide-headers.
+
+       * message.el (message-inhibit-body-encoding): Typo.
+       (message-resend): Inhibit encoding.
+
+       * gnus-sum.el (gnus-summary-toggle-header): Decode rfc2047.
+
+       * gnus-art.el (article-remove-cr): Use re-search.
+
+       * rfc2231.el (rfc2231-parse-string): Allow broken elm MIME
+       headers.
+
+       * mm-decode.el (mm-quote-arg): Quote '.
+
+       * gnus-ems.el (gnus-x-splash): Would place splash wrongly.
+
+       * mm-decode.el (mm-insert-part): Use multibyte for text.
+
+       * gnus-start.el (gnus-read-newsrc-file): New variable.
+       (gnus-read-newsrc-file): Use it.
+
+1999-04-17 18:51:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnvirtual.el (nnvirtual-request-expire-articles): New function.
+
+       * gnus-group.el (gnus-group-expire-articles-1): Made into own
+       function.
+
+Sat Apr 17 16:41:30 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.82 is released.
+
+1999-04-15  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-sum.el (gnus-group-charset-alist): Include Croatian groups
+       for iso8859-2.
+
+1999-04-17 18:23:50  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-charset-synonym-alist): Remove iso-2022-jp-2 from
+       synonym alist.
+
+1999-04-17 18:03:38  Adam P. Jenkins  <ajenkins@netway.com>
+
+       * gnus-sum.el (gnus-summary-local-variables): Mark as global.
+
+1999-04-17 18:02:05  Ettore Perazzoli  <ettore@comm2000.it>
+
+       * mail-source.el (mail-source-fetch): Ask before bugging out.
+
+1999-03-19  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * uudecode.el (uudecode-decode-region-external): Don't assume
+       uudecode-temporary-file-directory ends with a slash.
+
+1999-03-18  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-marks):
+       (gnus-update-read-articles):
+       (gnus-summary-expire-articles): Check server.
+
+1999-03-16  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mml.el (mml-preview): New function.
+
+1999-04-17 17:10:21  William M. Perry  <wmperry@aventail.com>
+
+       * mail-source.el (mail-source-fetch-file): Return the right
+       value.
+
+1999-04-17 07:52:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-parameter): New function.
+       (mml-insert-parameter-string): New function.
+
+       * nnmail.el (nnmail-get-new-mail): Say how many new articles.
+
+       * gnus-art.el (gnus-mime-multipart-functions): New variable.
+       (gnus-mime-display-part): Use it.
+
+       * mm-decode.el (mm-alternative-precedence): Removed.
+       (mm-discouraged-alternatives): New variable.
+       (mm-preferred-alternative-precedence): New function.
+
+       * nnmail.el (nnmail-get-new-mail): Use mail-sources.
+
+       * mail-source.el (mail-sources): New variable.
+
+       * gnus-art.el (article-remove-cr): Remove several trailing CRs.
+
+       * mm-decode.el (mm-valid-image-format-p): New function.
+       (mm-inline-media-tests): Use it.
+       (mm-valid-and-fit-image-p): New function.
+
+       * gnus-agent.el (gnus-agent-fetch-groups): Error when unplugged.
+       (gnus-agent-fetch-group): Ditto.
+
+1999-04-12  Didier Verna  <verna@inf.enst.fr>
+
+       * nnmail.el (nnmail-article-group): in case of a group name
+       containing "\\n" constructs, be sure to pass the expanded value to
+       nn*-save-mail.
+
+Sat Apr 17 05:40:45 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.81 is released.
+
+1999-04-16 15:54:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-get-split-value): Reverse result.
+
+1999-04-03 00:17:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el (gnus-always-read-dribble-file): Doc fix.
+
+1999-04-02 15:33:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-tag): Insert concluding part.
+
+       * message.el (message-send-mail): Encode later.
+       (message-send-news): Ditto.
+
+       * nnfolder.el: Don't use mail delim.
+
+1999-03-28 19:14:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cus.el (gnus-group-customize): Put point at min.
+
+       * mm-view.el (mm-inline-text): Allow toggling html.
+
+1999-03-28 17:11:15  William M. Perry  <wmperry@aventail.com>
+
+       * mail-source.el: Added prescript and postscript to file.
+
+1999-03-28 13:46:00  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el: Reverted.
+
+       * gnus-msg.el (gnus-setup-posting-charset): Didn't work.
+       (gnus-setup-posting-charset): Did work.
+
+1999-03-28 13:19:50  Jae-you Chung  <jay@pllab.kaist.ac.kr>
+
+       * gnus.el (gnus-short-group-name): Use
+       gnus-group-uncollapsed-levels.
+
+1999-03-28 13:11:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cite.el (gnus-dissect-cited-text): Don't remove overlays.
+
+1999-03-26 13:18:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-strip-headers-in-body): New variable.
+       (article-strip-headers-from-body): New command and keystroke.
+
+1999-03-14 16:09:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-pop): Check for symbol first.
+
+       * nnheader.el (nnheader-insert-file-contents): Bind
+       enable-local-eval to nil.
+       (nnheader-find-file-noselect): Ditto.
+
+       * nnmail.el (nnmail-article-group): Don't remove long lines.
+       (nnmail-remove-long-lines): New function.
+       (nnmail-split-header-length-limit): Removed.
+
+       * mml.el (mml-generate-mime-1): Use unibyte buffers.
+
+       * gnus-group.el (gnus-group-kill-all-zombies): Query user.
+
+1999-03-06 07:20:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-generic-mark): New function.
+
+       * nnmail.el (nnmail-split-header-length-limit): Increased.
+       (nnmail-article-group): Allow nil.
+
+       * gnus-cite.el (gnus-cite-parse-wrapper): Inhibit point-motion.
+
+       * nndoc.el (nndoc-generate-mime-parts-head): Insert real headers
+       first.
+
+       * mml.el (mml-minibuffer-read-type): Include types from
+       mailcap-mime-data.
+
+       * nndraft.el (nndraft-request-article): Would clobber Japanese.
+
+1999-03-05  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mml.el (mml-insert-tag): New function.
+       (mml-read-file): Renamed to mml-minibuffer-read-file to avoid
+       confusion with functions like `mml-read-tag'.
+       (mml-read-type): Ditto with `mml-minibuffer-read-type'.
+       (mml-minibuffer-read-description): Ditto with
+       `mml-minibuffer-read-description'.
+       (mml-attach-buffer): New function.
+       (mml-mode-map): New entry for /.
+       (mml-minibuffer-read-type): Accept DEFAULT.
+
+       * mml.el (mml-quote-region): Narrow the region.
+
+       * message.el (message-mode-menu): message-mime-attach-file is now
+       mml-attach-file.
+
+1999-03-05 21:24:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treatment-function-alist): Do emphasis earlier.
+
+1999-03-05 21:08:10  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * mml.el (mml-attach-buffer): New command.
+
+1999-02-27  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-marks): Call gnus-remove-from-range
+       with a proper range. Compress range.
+
+       * gnus-range.el (gnus-remove-from-range): Protect arguments.
+
+1999-03-05 20:59:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-get-image): Create a temporary file for xbms.
+
+1999-03-04 04:20:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-x-face-file-name): Removed.
+       (gnus-picons-convert-x-face): Removed.
+       (gnus-picons-article-display-x-face): Removed.
+       (gnus-picons-x-face-sentinel): Ditto.
+       (gnus-picons-display-x-face): Ditto.
+
+Thu Mar  4 01:38:00 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.80 is released.
+
+1999-03-02 16:04:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mm-display-part): Narrow to the part itself.
+
+       * gnus-sum.el (gnus-with-article): Moved here.
+
+       * mail-source.el (mail-source-fetch-pop): Ask for password even
+       when program.
+
+1999-02-28 13:16:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-bug): Add description.
+
+       * mml.el (mml-insert-mml-markup): Insert disposition.
+
+       * message.el (message-send-mail): Always encode mail headers.
+
+       * smiley.el (gnus-smiley-display): Goto body.
+
+1999-02-28 13:15:47  Petr Konecny  <pekon@informatics.muni.cz>
+
+       * smiley.el (gnus-smiley-display): Don't search to blank line.
+
+1999-02-28 00:38:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-article): Only run the highlight stuff
+       when requested.
+
+       * nnmail.el (nnmail-current-spool): Removed.
+
+       * gnus-salt.el (gnus-tree-inhibit): New varible.
+
+       * gnus.el (mm-util): Required.
+
+1999-02-27 23:44:52  paul stevenson  <spaul@mail.phy.ornl.gov>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Narrow to head first.
+
+1999-02-27 17:17:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-bind): Doc fix.
+
+1999-02-26 20:35:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-mode): Doc fix.
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Use 8bit
+       encoding.
+
+       * gnus.el (gnus-methods-equal-p): Moved here.
+
+       * mail-source.el: pop at 110.
+
+       * pop3.el (pop3-movemail): Use write-region instead of
+       append-to-file to avoid excessive messaging.
+
+1999-02-27  lantz moore  <lmoore@contigo.com>
+
+       * nnmail.el (nnmail-get-new-mail): honor suffix for spool-files of
+       type directory.
+
+1999-03-04  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * gnus-art.el (article-hide-boring-headers): Field names must not
+       contain whitespace.
+
+Fri Feb 26 18:54:16 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.79 is released.
+
+1999-02-26 18:11:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cite.el (gnus-cite-toggle): Don't remove highlighting.
+
+       * mml.el (mml-mode): Don't use add-minor-mode.
+
+       * message.el (messgage-inhibit-body-encoding): New variable.
+       (message-encode-message-body): Use it.
+
+Fri Feb 26 17:00:25 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.78 is released.
+
+1999-02-26 07:45:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-mode): Switch on MML mode.
+
+       * mml.el: Included commands and functions.
+       (mml-mode-map): New keymap.
+
+       * message.el: Removed the insertion commands and functions.
+
+       * gnus-ems.el (gnus-mule-cite-add-face): Removed.
+
+       * gnus-sum.el (gnus-summary-sort-by-chars): New command and
+       keystroke.
+
+       * gnus-art.el (gnus-narrow-to-page): Revert.
+
+       * gnus-cite.el (gnus-cite-delete-overlays): New function.
+       (gnus-cite-parse-maybe): Always reparse.
+
+       * message.el (message-encode-message-body): Don't insert
+       "multipart warning".
+
+       * gnus-art.el (gnus-article-treat-head-custom): New variable.
+
+1999-02-25  Miles Bader  <miles@ccs.mt.nec.co.jp>
+
+       * mail-source.el (mail-source-fetch-pop): Return 1 for success.
+
+       * nnmail.el: Require mm-util.
+
+1999-02-26 07:39:33  Justin Sheehy  <justin@linus.mitre.org>
+
+       * nnmail.el (nnmail-get-new-mail): Only get mail for the one
+       group.
+
+1999-02-26 07:38:08  SeokChan LEE  <chan@smoky-blue.com>
+
+       * mm-bodies.el (mm-body-charset-encoding-alist): Add euc-kr.
+
+1999-02-21  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-msg.el (gnus-extended-version): Better regexp.
+
+1999-02-25  Didier Verna  <verna@inf.enst.fr>
+
+       * nnmail.el (nnmail-split-it): new syntax: `(! FUNC SPLIT)'. FUNC
+       is called with the result of SPLIT and should return a new split.
+
+        * gnus.texi: update the doc.
+
+1999-02-23  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-picon.el (gnus-picons-display-bar-p): when picons are
+       displayed in the article buffer, output bars if
+       `gnus-picons-display-article-move-p'.
+
+1999-02-20  Aaron M. Ucko  <amu@mit.edu>
+
+       * mail-source.el (mail-source-fetch-pop): Typo.
+
+1999-02-26 07:15:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Save restriction.
+
+1999-02-23 03:07:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-cite.el (gnus-cite-parse-wrapper): Always parse.
+
+1999-02-21 11:11:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-buffer): New function.
+
+       * message.el (message-forward): Insert the buffer in the buffer.
+
+Sun Feb 21 01:20:50 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-message): Insert part in narrowed region.
+
+Sat Feb 20 23:09:40 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-toggle-header): Save restriction.
+
+Sat Feb 20 21:34:28 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.77 is released.
+
+1999-02-20 17:32:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-displaying-mime): New variable.
+       (article-narrow-to-head): New function.
+
+       * mail-source.el (mail-source-fetch-pop): Include pre/postscript.
+       Default to pop instead of pop3.
+
+1999-02-19 16:16:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-hide-pgp): Goto body.
+
+       * gnus-uu.el (gnus-uu-digest-mail-forward): Don't kill buffer.
+
+       * gnus-cite.el: Don't use goto-line.
+
+       * gnus-art.el (gnus-article-treat-html): Removed.
+       (gnus-treat-article): Save restriction.
+
+1999-02-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-send-mail): Don't untabify.
+       (message-mode): Don't use tabs for indentation.
+
+1999-02-19 14:54:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Don't untabify.
+
+       * nnml.el (nnml-save-mail): Typo fix.
+
+1999-02-19  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * message.el (message-cite-function): Add
+       `message-cite-original-without-signature' customization option.
+
+1999-02-18  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * nnmail.el (nnmail-fix-eudora-headers): Mark as option to
+       `nnmail-prepare-incoming-header-hook'.
+
+1999-02-19 14:41:43  Justin Sheehy  <justin@linus.mitre.org>
+
+       * gnus-util.el (gnus-make-sort-function-1): Typo fix.
+
+1999-02-19 14:40:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-get-new-news): Require nnmail.
+
+1999-02-18  Michael Cook  <cook@sightpath.com>
+
+       * Recognize Microsoft Outlook's cite attribution conventions.
+
+1999-02-19 14:33:11  James H. Cloos, Jr.  <cloos@jhcloos.com>
+
+       * gnus-sum.el: Bind M.
+
+1999-02-19 14:31:29  Neil Crellin  <neilc@wallaby.cc>
+
+       * mail-source.el (mail-source-fetch-pop): Bind pop3-port.
+
+1999-02-15  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-picon.el (gnus-group-display-picons): ensures that
+       `article-goto-body' really goes to the article body.
+
+1999-02-19 12:57:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Bind url-standalone-mode.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Create unique names.
+
+       * mm-view.el (mm-view-message): Enable multibyte.
+
+1999-02-11 18:37:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-get-new-mail): Message later.
+
+       * mm-util.el (mm-find-charset-region): Revert to checking
+       multibyte.
+
+1999-02-11  Matt Pharr  <mmp@graphics.stanford.edu>
+
+      * gnus-msg.el (gnus-bug): Encode environment info as a MIME
+      attachment.
+
+Thu Feb 11 04:58:51 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.76 is released.
+
+1999-02-06  Felix Lee  <flee@cygnus.com>
+
+       * gnus.el (gnus-group-change-level-function): Typo.
+
+1999-02-11 05:47:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-nov-skip-field): Removed.
+       (gnus-nov-field): Ditto.
+       (gnus-nov-parse-extra): Ditto.
+       (gnus-nov-read-integer): Ditto.
+
+1999-02-05 09:44:20  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nnheader.el (nnheader-nov-read-message-id): New macro.
+       (nnheader-parse-nov): Use it.
+
+       * gnus-sum.el (gnus-nov-read-message-id): New macro.
+       (gnus-nov-parse-line): Use it; use `(eobp)' instead of
+       `(eq (char-after) ?\n)'.
+
+1999-02-11 05:16:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-other-frame): Always pop up a new frame.
+
+Wed Feb 10 01:03:43 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-range.el (gnus-range-add): Rewrite.
+
+1999-02-02 18:12:00  Carsten Leonhardt  <leo@arioch.oche.de>
+
+       * nnmail.el (nnmail-split-incoming): Added detection of maildir
+       format.
+       (nnmail-process-maildir-mail-format): New function.
+
+       * mail-source.el (mail-source-fetch-maildir): New function.
+       (mail-source-keyword-map): Add default for maildir method.
+       (mail-source-fetcher-alist): Changed "qmail" to "maildir".
+
+1999-02-10 02:29:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetcher-alist): Remove apop.
+
+       * nndoc.el (nndoc-type-alist): Remove MIME-digest.
+       (nndoc-mime-digest-type-p): Removed.
+
+1999-02-09 15:25:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-read-summary-keys): Set the point
+       where it is supposed to be.
+       (gnus-treat-play-sounds): New variable.
+
+       * gnus-sum.el (gnus-newsgroup-ignored-charsets): New variable.
+
+       * gnus-art.el (article-display-x-face): Narrow to head.
+       (gnus-article-washed-types): New variable.
+       (article-hide-pgp): Is not a toggle.
+       (gnus-article-hide-text-type): Save types.
+       (article-decode-charset): Use it.
+
+       * nnmail.el (nnmail-get-new-mail): Ignore procmail.
+
+       * message.el (message-forward-start-separator): Removed.
+       (message-forward-end-separator): Removed.
+       (message-signature-before-forwarded-message): Removed.
+       (message-included-forward-headers): Removed.
+       (message-check-news-body-syntax): Don't check forward.
+       (message-forward): Use MIME.
+
+       * nnvirtual.el (nnvirtual-request-article): Bind
+       gnus-article-decode-hook to nil.
+
+1999-02-06 16:55:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-parse-singlepart-with-multiple-charsets): Check for
+       us-ascii.
+
+1999-02-04 00:00:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * format-spec.el (format-spec): Be more robust.
+
+       * message.el (message-encode-message-body): Default
+       mail-parse-charset to mail-parse-charset.
+
+       * gnus-sum.el (gnus-summary-edit-article-done): Don't encode.
+       (gnus-summary-edit-article): Bind mail-parse-charset.
+
+       * mml.el (mml-read-tag): Ignore white space after end of tag.
+
+       * message.el (message-goto-body): Also work in separatorless
+       articles.
+
+       * mml.el (mml-translate-from-mime): New function.
+       (mml-insert-mime): Ditto.
+       (mml-to-mime): New function.
+       (mime-to-mml): New name.
+
+       * gnus-sum.el (gnus-summary-edit-article): Always select raw
+       article.
+
+       * gnus-group.el (gnus-group-catchup-current): Unmark groups.
+
+       * gnus-sum.el (gnus-summary-setup-default-charset): Don't
+       special-case nndraft groups.
+
+1999-02-03 16:44:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Bind charset.
+       (gnus-get-newsgroup-headers): Already bound.
+
+       * message.el (message-encode-message-body): Use posting charset.
+
+       * mm-bodies.el (mm-encode-body): Use MIME charsets.
+       (mm-body-encoding): Do CTE.
+       (mm-body-7-or-8): New function.
+
+       * mm-util.el (mm-mime-charset): Always fall back on alist.
+       (mm-mime-mule-charset-alist): Include katakana-jisx0201.
+       (mm-mime-mule-charset-alist): Add arabic-*-column.
+       (mm-find-mime-charset-region): New function.
+
+       * format-spec.el (format-spec-make): New function.
+
+       * mail-source.el (format-spec): Required.
+       (mail-source-fetch-with-program): Removed.
+       (mail-source-fetch-with-program): New function.
+
+       * format-spec.el: New file.
+
+1999-02-03 16:00:41  Tatsuya Ichikawa  <ichikawa@hv.epson.co.jp>
+
+       * mail-source.el (mail-source-fetch-with-program): Take optional
+       parameter.
+
+1999-02-03 00:31:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-start.el: Ignore some groups.
+       (gnus-setup-news): Bind nnmail-fetched-sources.
+
+       * message.el (message-send-mail): Remove all tabs.
+
+       * mm-util.el (mm-find-charset-region): Just check whether
+       find-charset-region is defined.
+
+1999-02-02 23:35:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-group-get-new-news): Use
+       nnmail-fetched-sources.
+
+       * nnmail.el (nnmail-fetched-sources): New variable.
+       (nnmail-get-new-mail): Use it.
+
+       * mail-source.el (mail-source-fetched-sources): New variable.
+       (mail-source-fetch): Use it.
+
+1999-02-02 23:20:20  Mark W. Eichin  <eichin@thok.org>
+
+       * gnus.el (gnus-getenv-nntpserver): if the file that
+       gnus-nntpserver-file names has a trailing newline, the
+       string-match will always match, and thus the file will never be
+       read.  (^ matches start of "line", \\` matches start of "buffer",
+       which is what was intended...)
+
+1999-02-02 23:17:40  Kim-Minh Kaplan  <kmkaplan@western.fr>
+
+       * gnus-picon.el (gnus-picons-parse-filenames): Quote group names.
+
+1999-01-28 04:15:46  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-start.el (gnus-read-active-file): Eliminate duplicated
+       select methods.
+
+1999-01-27  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-range.el (gnus-remove-from-range): Sort second argument.
+
+1999-02-02 10:55:23  Scott Hofmann  <shofmann@mindspring.com>
+
+       * nntp.el: Use mail-source-read-passwd instead of nnmail-read-passwd.
+
+Mon Feb  1 23:23:03 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-cus.el (gnus-group-parameters): Charset as symbol, and fix
+       a typo.
+       * gnus-sum.el (gnus-summary-setup-default-charset): Set nndraft's
+       charset to nil.
+       * gnus-agent.el (gnus-agent-queue-setup): Remove charset setting.
+       * gnus-start.el (gnus-start-draft-setup): Ditto.
+
+1999-02-02 22:13:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-directory): Use the predicate.
+       (mail-source-value): Don't do variables.
+
+       * nnmail.el (nnmail-get-new-mail): Set the predicate.
+
+       * gnus-sum.el (gnus-summary-toggle-header): Fix, and bound to t.
+
+1999-02-01  Michael Cook  <cook@sightpath.com>
+
+       * Defenestrate spurious ?a.
+
+1999-02-02 21:59:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-pop): Instead use
+       :authentication.
+
+1999-02-01  Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+
+       * lisp/mail-source.el : Support APOP authentication scheme.
+
+1999-02-02 21:56:14  Tatsuya Ichikawa  <t-ichi@niagara.shiojiri.ne.jp>
+
+       * pop3.el (pop3-movemail): Return t.
+
+1999-02-02 21:48:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-fold-region): New function.
+       (rfc2047-encode-message-header): Use it.
+
+1999-02-02 21:07:27  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * gnus-sum.el (gnus-group-charset-alist): Add more.
+
+Mon Feb  1 21:18:00 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.75 is released.
+
+1999-02-01 21:54:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-display-x-face): Don't narrow to head.
+
+1999-02-01 21:48:39  Michael Cook  <cook@sightpath.com>
+
+       * gnus-cite.el (gnus-cited-lines-visible): Accept a cons.
+
+1999-02-01 20:59:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-fetch-directory): Ignore
+       directories.
+
+       * gnus-cus.el (gnus-group-parameters): Addition.
+
+       * gnus-art.el (article-strip-banner): Do symbolic banners.
+       (article-strip-banner): New keystroke.
+
+1999-02-01 20:54:32  Michael Cook  <cook@sightpath.com>
+
+       * gnus-art.el (article-strip-banner): New command.
+
+1999-02-01 20:53:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-strip-banners): New variable.
+
+1999-01-28 05:34:56  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mail-source.el (mail-source-read-passwd): Use `read-passwd' if it
+       has been exist.
+
+Thu Jan 28 01:38:34 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-draft-coding-system): Check coding-system.
+       * mm-util.el (mm-text-coding-system): Ditto.
+
+1999-01-28 12:11:31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * mail-source.el (mail-source-fetch-pop): Save excursion.
+
+1999-01-28 08:14:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-movemail-args): Not constant.
+       (mail-source-movemail-args): Removed.
+       (mail-source-fetch-with-program): New function.
+       (mail-source-fetch-pop): Use program and function.
+       (mail-source-movemail-program): Removed.
+
+       * gnus-art.el (gnus-treat-date-iso8601): New variable.
+       (gnus-treat-date-user-defined): New variable.
+
+1999-01-28 08:07:12  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * nnmail.el (nnmail-fix-eudora-headers): New function.
+
+1999-01-28 08:05:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-encode-body): Use mail-parse-charset.
+
+1999-01-27 08:06:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * smiley.el (smiley-deformed-regexp-alist): Removed =>.
+       (smiley-nosey-regexp-alist): Ditto.
+
+       * gnus-art.el (gnus-treatment-function-alist): Do
+       gnus-article-add-buttons-to-head later.
+       (gnus-treat-capitalize-sentences): New variable.
+       (article-capitalize-sentences): New command and keystroke.
+
+       * gnus-group.el (gnus-group-catchup-current): Do group.
+
+       * message.el (message-default-charset): Add group.
+
+Wed Jan 27 05:24:53 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.74 is released.
+
+1999-01-27 05:56:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-fill-long-lines): Renamed.
+       (article-fill-long-lines): New keystroke.
+
+1999-01-26 06:35:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-setup-posting-charset): Check for group.
+
+       * gnus-group.el (gnus-group-catchup-current): Skip groups now
+       displayed.
+       (gnus-group-catchup-current): Be more robus.
+
+       * gnus-sum.el (gnus-summary-select-article): Reselect for showing
+       headers.
+
+1999-01-25  Dave Love  <fx@gnu.org>
+
+       * message.el (message-mode-menu): Add message-mime-attach-file.
+       (message-mode): Doc fix.
+
+1999-01-26 05:24:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-check-duplication): Insert the mail source
+       string.
+
+       * mail-source.el (mail-source-fetch-pop): Bind mail-source-string.
+       (mail-source-fetch-directory): Ditto.
+       (mail-source-fetch-file): Ditto.
+       (mail-source-string): New variable.
+
+       * gnus-start.el (gnus-get-unread-articles): Nix out groups over
+       the level.
+
+       * rfc2047.el (rfc2047-encodable-p): Convert to MIME charsets
+       before handling.
+
+       * mm-util.el (mm-mime-charset): Use the parameters.
+       (mm-mime-charset): Removed region paremeters.
+
+       * nnmail.el (nnmail-get-new-mail): Don't message the entire
+       source.
+
+1999-01-25 12:05:16  Lloyd Zusman  <ljz@asfast.com>
+
+       * nnmail.el (nnmail-get-split-group): Quote right.
+
+1999-01-25 05:55:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-source.el (mail-source-movemail): Would kill an arbitrary
+       buffer.
+
+1999-01-24 03:02:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-group.el (gnus-clear-inboxes-moved): Removed.
+       (gnus-group-mode): Don't hook.
+
+       * mail-source.el (mail-source-bind): Doc fix.
+       (mail-source-bind): Take only one param.
+
+       * gnus-art.el (gnus-treat-highlight-signature): typep.
+
+       * mail-source.el (mail-source-movemail): Ignore empty file.
+       (mail-source-callback): Check before deleting.
+
+       * message.el (message-mime-attach-file): Include name.
+
+1999-01-23 17:01:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-read-charset): Return a symbol.
+
+       * mm-view.el (mm-inline-text): Insert signature separator.
+
+       * gnus-art.el (gnus-treat-predicate): New function.
+       (gnus-treat-article): Allow all types to be checked.
+
+       * gnus-util.el (gnus-or): New function.
+       (gnus-and): Ditto.
+
+       * gnus-art.el (gnus-mime-display-single): Use override.
+
+       * mm-decode.el (mm-attachment-override-types): New variable.
+       (mm-attachment-override-p): New function.
+
+       * gnus-picon.el (gnus-group-display-picons): Don't go backward.
+
+1999-01-23 16:45:06  Andrew J. Cosgriff  <ajc@bing.wattle.id.au>
+
+       * mm-view.el (mm-inline-text): Do vcards.
+
+Sat Jan 23 14:23:27 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.73 is released.
+
+1999-01-23 11:38:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-spool-file): Changed to use mail-source.
+       (nnmail-crash-box, nnmail-use-procmail, nnmail-procmail-directory,
+       nnmail-procmail-suffix, nnmail-resplit-incoming): Removed.
+       (nnmail-movemail-program): Removed.
+       (nnmail-movemail-args): Removed.
+       (nnmail-pop-password-required): Ditto.
+       (nnmail-tmp-directory): Ditto.
+       (nnmail-delete-incoming): Removed.
+       (nnmail-pop-password, nnmail-moved-inboxes,
+       nnmail-internal-password, nnmail-move-inbox): Removed.
+       (nnmail-read-passwd): Ditto.
+       (nnmail-get-spool-files): Removed.
+       (nnmail-resplit-incoming): Reinstated.
+
+       * mail-source.el: New file.
+
+1999-01-23 09:08:31  James H. Cloos, Jr.  <cloos@jhcloos.com>
+
+       * gnus-art.el (gnus-article-mode-map): Bind backspace.
+
+1999-01-23 09:05:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-make-date-line): Fix iso8601 display.
+
+1999-01-20 02:53:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treat-display-smileys): Check xpm.
+
+       * gnus-picon.el (gnus-group-display-picons): Goto body.
+
+       * gnus.el: Indented all functions; broke long lines; changed all
+       instances of illegal/legal to invalid/valid.  Yes, I'm bored.
+
+Wed Jan 20 00:50:53 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.72 is released.
+
+1999-01-20 01:39:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Cleaned up trailing whitespace.
+
+       * mm-util.el (mm-read-charset): Work.
+
+1999-01-17  Matt Armstrong  <mattdav+matt@best.com>
+
+       * gnus-score.el (gnus-score-find-bnews): Match regexp on the
+       nnheader-translate-file-chars'd group name.
+
+1999-01-20 01:30:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Fold case.
+
+1999-01-20 01:28:16  Alexei V. Barantsev  <barancev@ispras.ru>
+
+       * gnus-xmas.el (gnus-xmas-modeline-glyph): Backquote.
+
+1999-01-20 00:46:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-add): New function.
+
+1999-01-18 09:40:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-goto-body-goes-to-point-min-p): New variable.
+       (article-goto-body): Use it.
+       (gnus-treat-article): Ditto.
+
+       * gnus-agent.el (gnus-agent-get-undownloaded-list): Remove the
+       downloaded articles from the downloadeble list.
+
+1999-01-16 17:31:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Bind
+       mail-parse-charset.
+
+       * mm-util.el (mm-charset-synonym-alist): New variable.
+       (mm-charset-to-coding-system): Use it.
+       (mm-charset-coding-system-alist): Removed.
+       (mm-charset-to-coding-system): Don't use it.
+       (mm-find-charset-region): Use mail-parse-charset.
+
+       * gnus-art.el (gnus-treatment-function-alist): Use
+       gnus-article-display-picons.
+       (gnus-treat-display-xface): Only do if we have xface feature.
+       (gnus-part-display-hook): New function.
+       (gnus-treat-article): Use it.
+       (gnus-treat-article): Use gnus-visual.
+
+       * gnus-msg.el (gnus-setup-posting-charset): Check elem.
+
+       * gnus-art.el (gnus-mm-display-part): Fix the MIME button after
+       displaying.
+
+       * mm-decode.el (mm-insert-part): Use insert-buffer-substring.
+
+       * gnus-score.el (gnus-score-find-bnews): Protect against invalid
+       regexp file names.
+
+Sat Jan 16 03:15:57 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.71 is released.
+
+1999-01-16 00:13:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-image): Don't add a dot.
+
+       * gnus-art.el (gnus-treat-article): New function.
+
+       * gnus.el (gnus-article-display-hook): Removed.
+
+       * gnus-art.el (gnus-article-treat-custom): New variable.
+
+       * gnus-start.el (gnus-ignored-newsgroups-has-to-p): Removed.
+
+       * gnus-msg.el (gnus-setup-posting-charset): Allow variables and
+       functions.
+
+       * message.el (message-posting-charset): New variable.
+       (message-send-mail): Use it.
+
+       * gnus-msg.el (gnus-group-posting-charset-alist): Moved here.
+       (gnus-setup-posting-charset): New function.
+       (gnus-setup-message): Use it.
+
+       * message.el (message-encode-message-body): Just look for
+       Content-Type before inserting a new one.
+
+1999-01-15 23:08:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-default-charset): Removed.
+
+       * mail-prsvr.el: New file.
+       (mail-parse-charset): New variable.
+
+       * gnus-sum.el (gnus-newsgroup-charset): Changed name.
+       Changed name.
+
+       * gnus.el (gnus-charset): New group.
+
+       * nnmail.el (nnmail-pathname-coding-system): Default to binary.
+
+       * gnus-sum.el (gnus-default-charset): Default to nil.
+       (gnus-newsgroup-iso-8859-1-forced-regexp): Removed.
+       (gnus-newsgroup-iso-8859-1-forced): Removed.
+
+       * mm-util.el (mm-known-charsets): Removed.
+       (mm-default-coding-system): Removed.
+       (mm-default-charset): Removed.
+       (mm-read-charset): New function.
+
+       * message.el (message-default-charset): Removed.
+
+       * rfc2047.el (rfc2047-default-charset): Default to nil.
+
+       * mm-util.el (mm-charset-iso-8859-1-forced): Removed.
+
+Fri Jan 15 20:50:38 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.70 is released.
+
+1999-01-15 00:06:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-save-part): Use mm-get-part.
+       (mm-insert-part): New function.
+       (mm-get-part): Use it.
+       (mm-get-image): Ditto.
+       (mm-display-external): Ditto.
+
+       * mm-view.el (mm-inline-text): Ditto.
+
+       * gnus-move.el (gnus-move-group-to-server): Protect against nil
+       ranges.
+
+       * mm-decode.el (mm-display-external): Save the buffer.
+       (mm-remove-part): Kill it.
+
+       * qp.el (quoted-printable-decode-region): Do the right thing at eobp.
+
+       * nnagent.el (nnagent-request-set-mark): Defined stub.
+
+1999-01-14 23:05:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-load-score-alist): Bind
+       coding-system-for-read.
+
+       * gnus-sum.el (gnus-summary-exit): Do adaptive scoring before
+       prepare-exit-hook.
+
+       * mm-view.el (mm-setup-w3): Require w3.
+
+1999-01-13  Kiyokazu SUTO  <suto@merry.xmath.ous.ac.jp>
+
+       * lisp/nnspool.el (nnspool-retrieve-headers): Protect against empty
+       body.
+
+1999-01-14 21:17:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-encode.el: Ditto.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Message the
+       error.
+
+       * mailcap.el (mailcap-mime-data): SAFER ps.
+
+       * message.el (message-encode-message-body): Always insert a
+       Content-Type header.
+
+       * mm-decode.el (mm-inline-media-tests): Default all text/* to be
+       shown inline.
+
+       * mm-view.el (mm-inline-text): Handle all sorts of text.
+
+       * mailcap.el (mailcap-mime-data): non-viewer for viewers that
+       don't view.
+
+       * mm-decode.el (mm-display-external): Use it.
+
+       * gnus-art.el (gnus-visible-headers): Added bcc, gcc, fcc.
+
+       * mm-decode.el (mm-save-part): Removed double code.
+
+1999-01-12  Dave Love  <fx@gnu.org>
+
+       * mm-decode.el (mm-save-part): Avoid doubly-compressed
+       application/octet-stream .gz & al files with jka-compr.
+
+1999-01-12  Dave Love  <fx@gnu.org>
+
+       * gnus-ems.el (gnus-down-mouse-3): New variable.
+       * gnus-art.el (gnus-mime-button-map): Use it.
+       (gnus-mime-button-menu): Set the clicked-on buffer initially.
+
+1999-01-13 19:41:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-data): Added ImageMagic and ee.
+
+1999-01-12 17:34:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-kill-buffer): Don't kill article
+       buffers.
+
+       * gnus-sum.el (gnus-summary-exit): Destroy all MIME.
+
+       * gnus-cache.el (gnus-cache-read-active): Reversed check.
+
+1999-01-12 17:18:25  Matt Armstrong  <matta@geoworks.com>
+
+       * mml.el (mml-parameter-string): Strip directory component.
+
+1999-01-12 17:02:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-use-demon): Removed.
+
+1999-01-12 05:53:23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * nnmail.el (nnmail-article-group): Don't infloop.
+
+1999-01-11  Colin Rafferty  <colin@xemacs.org>
+
+       * gnus-art.el (article-update-date-lapsed): Made it work with
+       picons, and make it update on all visible frames.
+       (article-date-ut): Get summary-buffer's current-headers.
+
+1999-01-12 07:20:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-setup-buffer): Don't set major mode.
+       (gnus-picons-setup-p): New variable.
+
+1999-01-11 02:13:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-split-header-length-limit): Lowered to 512.
+
+1999-01-04 12:58:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Don't use run-hooks.
+       (gnus-summary-exit-no-update): Use mapcar.
+
+1999-01-02 14:36:32  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-agent.el (gnus-category-write): Make directory.
+
+1998-09-26 19:39:31 Simon Josefsson <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-read-articles):
+       (gnus-update-marks): Request backend update of mark.
+
+1999-01-03 15:29:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-body-encoding): Use mm-find.
+
+1999-01-03 15:28:27  Kim-Minh Kaplan  <kmkaplan@western.fr>
+
+       * gnus-picon.el (gnus-article-display-picons): Fix.
+
+Sun Jan  3 13:32:02 1999  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.69 is released.
+
+1999-01-03 06:45:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-setup-buffer): Run the hook.
+
+       * gnus-agent.el (gnus-agent-remove-group): New command and
+       keystroke.
+
+       * rfc2047.el (rfc2047-decode-region): Check for us-ascii.
+
+1999-01-02 14:12:41  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-agent.el (gnus-agent-write-servers): Make directory.
+
+1998-12-26 02:38:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Bind current id.
+
+       * mm-decode.el (mm-handle-id): New macro.
+       (mm-make-handle): Accept id.
+       (mm-dissect-singlepart): Use it.
+
+1998-12-23  Matt Pharr  <mmp@graphics.stanford.edu>
+
+      * message.el (message-cite-original-without-signature): Use
+      message-signature-separator when searching for signature in
+      message-cite-original-without-signature.
+
+1998-12-24 16:25:38  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.el (gnus-server-to-method): Check named methods.
+
+1998-12-24 03:27:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-view-message): Goto point-min.
+
+       * nnmail.el (nnmail-article-group): Don't delete lines, only
+       shorten them.
+
+       * gnus-msg.el (gnus-configure-posting-styles): Also do nil
+       values.
+
+       * nnheader.el (nnheader-temp-directory): New variable.
+       (nnheader-temp-directory): Removed.
+
+1998-12-22  Jack Vinson  <jvinson@chevax.ecs.umass.edu>
+
+       * mailcap.el (mailcap-parse-mailcaps): Add "~/.mailcaps" to the
+       list of files to check for mailcap entries under windows-nt.
+
+1998-12-24 03:02:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-maybe-hide-headers): Check whether the
+       summary buffer exists.
+
+1998-12-22  Aaron M. Ucko  <amu@mit.edu>
+
+       * nnsoup.el (nnsoup-store-reply): Remove code to deal with
+       irrelevant Sun sendmail bug.
+       (nnsoup-store-reply): Stop mucking with mail-header-separator.
+
+       * message.el (message-send-news): Bind mail-header-separator to
+       "" when asking backend to post.
+
+1998-12-22  Karl Kleinpaste  <karl@justresearch.com>
+
+       * mm-uu.el (mm-dissect-disposition): New variable.
+       (mm-uu-dissect): Use it.
+
+1998-12-21 21:34:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Bind url-current-object.
+
+1998-12-06 03:05:41  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-range.el (gnus-remove-from-range): Rewrite.
+
+1998-12-09  SL Baur  <steve@altair.xemacs.org>
+
+       * gnus-picon.el (annotations): Remove bogus require 'xpm.
+
+1998-12-18  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * message.el (message-encode-message-body): Insert `MIME-Version'
+       instead of `Mime-Version'.
+
+1998-12-04  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * message.el (message-insert-mime-part): Add the attachment
+       disposition.
+       (message-insert-mime-part): Make TYPE and DESCRIPTION optional.
+       (message-mime-query-type): New function.
+       (message-mime-query-description): Ditto.
+       (message-mime-query-file): Ditto.
+       (message-insert-mime-part): Use them.
+       (message-mime-insert-external): Use the new stuff.
+
+1998-12-19 23:02:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-split-header-length-limit): New variable.
+
+       * mm-decode.el (mm-dissect-buffer): Check syntax.
+
+       * rfc2231.el (rfc2231-parse-string): Remove check for syntax.
+
+       * rfc2047.el (rfc2047-encodable-p): Use mm-find-charset-region.
+       (rfc2047-dissect-region): Ditto.
+
+1998-12-17 18:36:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-view-message): Decode charset.
+
+1998-12-16 16:01:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2231.el (rfc2231-parse-string): Ignore syntactically invalid
+       CT headers.
+
+Wed Dec 16 01:44:40 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Use
+       mm-uu-*-function.
+       * mm-uu.el (mm-uu-dissect): Use x-uuencode.
+
+1998-12-16 10:20:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Do MML first.
+       (message-send-news): Ditto.
+
+1998-12-15 20:57:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-face): New face.
+       (gnus-picons-try-face): Use it.
+
+Tue Dec 15 19:17:43 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.68 is released.
+
+Tue Dec 15 18:28:24 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.67 is released.
+
+Tue Dec 15 17:31:44 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.66 is released.
+
+1998-12-13 11:00:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-insert-mime-button): Decode description.
+
+Sat Dec  5 16:50:49 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (article-decode-encoded-words): Rollback to 0.55.
+       (gnus-decode-header-methods): Ditto.
+       (gnus-decode-with-mail-decode-encoded-word-region): Ditto.
+
+1998-12-13 10:04:39  Lloyd Zusman  <ljz@asfast.com>
+
+       * gnus-xmas.el (gnus-xmas-summary-recenter): Allow numbers.
+
+1998-12-13 09:32:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-mime-headers): Encode description.
+
+       * nnfolder.el (nnfolder-request-expire-articles): Go to the date
+       line.
+
+       * gnus-sum.el (gnus-default-charset): Doc fix.
+
+Wed Dec  9 15:18:39 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-part): Forward a line.
+
+Wed Dec  9 13:30:29 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-running-ntemacs): New variable.
+       (mm-text-coding-system): Ditto.
+       * nnmail.el (nnmail-incoming-coding-system): Ditto.
+       (nnmail-split-incoming): Use nnmail-incoming-coding-system.
+
+1998-12-13 08:52:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-network-display-internal): Don't set
+       buffer.
+
+       * message.el (message-insert-headers): New command and keystroke.
+
+1998-12-07 23:42:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-media-tests): Recognize x-xbitmap.
+       (mm-get-image): Ditto.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Only for
+       base64, uudecode and binhex.
+
+Sun Dec  6 21:58:31 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Replace CRLF
+       in text/plain.
+       * mm-uu.el (mm-uu-dissect): Use inline.
+
+1998-12-07 23:19:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-view-message): New function.
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Changed to
+       qp.
+
+1998-12-07  Karl Kleinpaste  <karl@justresearch.com>
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Add an
+       entry for message/rfc822 as 8bit.
+
+1998-12-07 23:16:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-extensions): Add patch.
+
+1998-12-05  Dale Hagglund  <rdh@best.com>
+
+       * gnus-sum.el (gnus-summary-display-buttonized): Use prefix
+       argument to force all multipart/* to look like multipart/mixed.
+
+       * gnus-art.el (gnus-mime-display-multipart-as-mixed): New
+       variable.
+       (gnus-mime-display-part): Use it.
+
+1998-12-07 22:46:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-draft.el (gnus-draft-send): Only disable checks for
+       non-interactive use.
+       (gnus-draft-send-message): Use it.
+
+Sun Dec  6 19:36:53 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.65 is released.
+
+1998-12-06 20:11:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-prepare-display): Don't init w3.
+
+       * mm-view.el (mm-inline-text): Bind url-standalone-mode here.
+
+Sat Dec  5 18:35:42 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.64 is released.
+
+1998-12-05 18:51:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-setup-w3): Don't load.
+
+       * gnus-msg.el (gnus-setup-message): Set group name.
+       (gnus-group-mail): Avoid leaking local vars.
+
+       * message.el (message-attach-file): Renamed.
+       (message-mime-attach-file): Renamed again.
+
+1998-12-05  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (article-decode-encoded-words): Bind
+       rfc2047-default-charset here.
+
+       * gnus-art.el (gnus-insert-mime-button): Nix slashes in file name.
+
+1998-12-05 18:33:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-picon.el (gnus-picons-setup-buffer): Run picons hook.
+       (gnus-picons-setup-hook): New hook.
+
+1998-12-05  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * mailcap.el (mailcap-mime-data): Remove "*" from documentation
+       string.
+       (mailcap-mime-extensions): Ditto.  Made first sentense fit a
+       line.
+
+1998-12-05 17:11:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-prepare-display): Setup w3.
+       (gnus-mime-view-part): Ditto.
+       (gnus-mime-inline-part): Dotii.
+       (gnus-mime-externalize-part): Daddo.
+       (gnus-mime-internalize-part): Tutti frutti.
+       (gnus-widget-press-button): Da da do.
+
+       * mm-view.el (mm-setup-w3): Require url-vars.
+
+Fri Dec  4 12:13:12 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-draft-coding-system): Fix for XEmacs-NT.
+       * mm-util.el (mm-find-charset-region): Ditto.
+
+1998-12-05 16:30:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send): Don't encode here.
+       (message-send-mail): But here.
+       (message-send-news): And here.
+
+1998-12-04 15:29:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-message-insert-stylings): Don't insert twice.
+
+Fri Dec  4 04:09:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.63 is released.
+
+1998-12-04 04:59:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-base-boundary): Shorten.
+
+       * message.el (message-insert-mime-part): Use default.
+
+       * gnus-art.el (gnus-insert-mime-button): Bind gnus-tmp-type-long.
+
+1998-12-03  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-art.el (gnus-mime-display-alternative): Use (*) for radio
+       buttons, not [*].
+
+1998-12-04  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (gnus-insert-mime-button): Do proper help-echo.
+
+1998-12-04 04:48:37  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (gnus-insert-mime-button): Fix.
+
+1998-12-03  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * message.el (message-insert-mime-part): Nicify prompts.
+       (message-insert-mime-part): Really delete duplicates.
+       (message-insert-mime-part): Check against common errors.
+       (message-insert-mime-part): Fix docstring.
+
+1998-12-04 04:41:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-internalize-part): Bugged out.
+
+1998-12-03  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (gnus-mime-button-line-format): Nicify.
+       (gnus-insert-mime-button): Modify accordingly.
+
+1998-12-04 01:50:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-display-mime): Set window point.
+
+       * mm-decode.el (mm-display-external): Only decode when not
+       saving.
+       (mm-alternative-precedence): Prefer multiparts.
+       (mm-inline-media-tests): Inline multiparts.
+
+       * gnus-picon.el (gnus-picons-next-job-internal): Do bar if asked.
+       Ignore errors when requiring url.
+
+       * mml.el (mml-quote-region): New command.
+
+       * message.el (message-cite-original): Use it.
+       (message-cite-original-without-signature): Ditto.
+
+Thu Dec  3 12:53:58 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.62 is released.
+
+1998-12-03 13:38:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-view-all-parts): Work with multiparts.
+
+1998-12-03  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-view.el (mm-inline-text): Use `point-min-marker' and
+       `point-max-marker'.
+
+1998-12-03 13:22:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-extensions): Use image/xpm for xpms.
+
+       * gnus-art.el (gnus-mime-display-single): Check for attachment
+       before other tests.
+
+1998-12-03  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-msg.el (gnus-configure-posting-styles): find a
+       posting-style entry in the group parameters, if any, and honor it
+       at the end.
+
+1998-12-03 13:03:37  Felix Lee  <flee@teleport.com>
+
+       * nntp.el (nntp-after-change-function): Fix.
+
+1998-12-03 12:44:30  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * mml.el (mml-generate-mime-1): Insert literally.
+
+1998-12-03 00:23:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-mime-headers): Removed debug.
+
+1998-12-02 22:22:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-show-article): Destroy parts when
+       prefixed.
+
+       * mm-encode.el (mm-content-transfer-encoding-defaults): Default
+       application/emacs-lisp to 8bit.
+
+1998-12-03  Dale Hagglund  <rdh@best.com>
+
+       * mm-decode.el (mm-quote-arg): Add quoting of '()', '<>', and '|'.
+
+Wed Dec  2 20:24:27 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.61 is released.
+
+1998-12-02 21:12:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-parse-1): Skipped parts.
+       (mml-insert-mime-headers): Nil is a list.
+       (mml-generate-mime-1): Don't insert literally.
+       (mml-read-tag): Drop text props.
+       (mml-read-part): Ditto.
+       (mml-parse-singlepart-with-multiple-charsets): Ditto.
+
+Wed Dec  2 20:07:16 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.60 is released.
+
+1998-12-02 20:11:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-parse-1): Don't throw contents away.
+
+1998-12-02  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mml.el (mml-compute-boundary-1): Regexp-quote the boundary.
+
+1998-12-02 18:42:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-parse-singlepart-with-multiple-charsets): New
+       function.
+       (mml-parse-1): Use it.
+
+Tue Dec  1 23:04:25 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-decode-with-mail-decode-encoded-word-region):
+       Use gnus-newsgroup-default-charset.
+       (article-decode-encoded-words): Remove charset codes.
+       * gnus-sum.el (gnus-newsgroup-default-charset): Use
+       gnus-default-charset.
+
+1998-12-02 03:14:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Don't encode here.
+       (message-send-news): Nor here.
+       (message-send): ... but here instead.
+
+       * gnus-picon.el (gnus-picons-display-article-move-p): Changed
+       default to nil.
+       (gnus-article-display-picons): Replace From line.
+       (gnus-group-display-picons): Replace Newsgroups line.
+       (gnus-picons-display-glyph): Set baseline.
+       (gnus-group-display-picons): Piconize the entire Newsgroups line.
+       (gnus-picons-xbm-face): Revert to old, standard colors.
+
+       * message.el (message-fetch-field): Remove text props.
+
+       * gnus-art.el (gnus-article-normalized-header-length): New
+       variable.
+       (article-normalize-headers): New command and keystroke.
+
+       * gnus-picon.el (gnus-picons-xbm-face): Changed colors.
+
+Wed Dec  2 01:43:48 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.59 is released.
+
+1998-12-02 01:38:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-insert-mime-headers): Beep at multiple charsets.
+
+       * gnus-art.el (gnus-mime-copy-part): Set buffer-file-name.
+
+1998-11-30  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mml.el (mml-generate-mime-1): Handle unquoting end-tags.
+
+1998-12-02 00:15:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-all-images-fit): New variable.
+       (mm-image-fit-p): Use it.
+
+       * gnus-art.el (gnus-mime-display-single): Use it.
+       (gnus-mime-internalize-part): New command and keystroke.
+
+       * mm-decode.el (mm-user-automatic-external-display): New
+       variable.
+       (mm-automatic-external-display-p): New function.
+
+       * gnus-picon.el (gnus-picons-xbm-face): Default to sensible
+       colors.
+
+1998-12-01 23:52:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-repair-multipart): Reselect article.
+
+       * gnus-art.el (gnus-with-article): Work in the original article
+       buffer.
+       (gnus-with-article): Work in read-only groups.
+
+Tue Dec  1 00:15:36 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-string): Return original string if not
+       decode.
+
+Mon Nov 30 23:38:02 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Use mm-make-handle.
+
+1998-12-01 01:53:49  Francois Pinard  <pinard@iro.umontreal.ca>
+
+       * nndoc.el (nndoc-mime-parts-type-p): Do related.
+
+Tue Dec  1 00:46:20 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.58 is released.
+
+1998-11-30  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-decode.el (mm-get-image): Return a glyph, not an image
+       specifier.
+
+1998-11-29  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * rfc2047.el (rfc2047-decode): Bind mm-default-charset.
+
+1998-12-01 01:23:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-parse.el (rfc2045): Required.
+
+1998-12-01 00:59:53  William M. Perry  <wmperry@aventail.com>
+
+       * mm-view.el (mm-inline-text): Remove props.
+
+1998-12-01 00:18:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-setup-w3): Protect url-misc.
+
+       * message.el (message-ignored-resent-headers): Remove
+       Gnus-Warning.
+
+       * mml.el (mml-insert-mime-headers): Use encoding.
+       (mml-parameter-string): Ditto.
+
+       * rfc2045.el: New file.
+       (rfc2045-encode-string): New function.
+
+1998-11-30 23:11:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mail-parse.el (mail-header-encode-parameter): New function.
+
+       * rfc2231.el (rfc2231-encode-string): New function.
+
+Mon Nov 30 13:52:50 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-string): New function.
+       * mm-view.el (mm-inline-text): Use mm-decode-string.
+
+Mon Nov 30 21:57:00 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.57 is released.
+
+1998-11-23  Felix Lee  <flee@cygnus.com>
+
+       * nntp.el (nntp-async-needs-kluge): new setting.
+       (nntp-async-timer): new var.
+       (nntp-async-process-list): new var.
+       (nntp-async-kluge): new function.
+       (nntp-async-timer-handler): new function.
+       (nntp-async-wait): new function.
+       (nntp-async-stop): new function.
+       (nntp-after-change-function): renamed, and split apart.
+       (nntp-async-trigger): new function.
+       (nntp-do-callback): new function.
+       (nntp-accept-process-output): add optional timeout arg.
+
+       * gnus-async.el (gnus-async-request-fetched-article): fixed.
+       (gnus-async-wait-for-article): new function.
+       (gnus-async-with-semaphore): s/asynch/async/.
+
+1998-11-30 16:54:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-with-article): Don't encode.
+       (gnus-insert-mime-button): Fall back on filename from C-D.
+       (gnus-mime-display-single): Have dots right on text/plain
+       attachments.
+
+       * mm-decode.el (mm-dissect-buffer): Respect Content-Disposition in
+       broken parts.
+
+       * gnus-art.el (gnus-with-article): Flush cache and backlog.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Also do
+       binhex.
+
+       * gnus-sum.el (gnus-summary-reparent-thread): Use new macro.
+       (gnus-summary-repair-multipart): New command and keystroke.
+
+       * gnus-art.el (gnus-with-article-buffer): New macro.
+
+Sun Nov 29 23:51:57 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): Do not get part when
+       undisplay the part.
+
+1998-11-30 03:38:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-make-sort-function-1): Allow lambdas.
+
+       * mml.el (mml-read-part): Partition right.
+
+       * mm-decode.el (mm-handle-set-cache): New macro.
+       (mm-handle-cache): Ditto.
+       (mm-make-handle): Ditto.
+       (mm-dissect-singlepart): Use it.
+       (mm-get-image): Use the cache.
+
+1998-11-29 23:44:44  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-display-mixed): Rewrite.
+       (gnus-mime-display-single): Don't insert lines between parts.
+
+Sun Nov 29 04:55:40 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * nnmail.el (nnmail-file-coding-system-1): New variable.
+       * nnfolder.el (nnfolder-file-coding-system): Ditto.
+       (nnfolder-read-folder): Use nnfolder-file-coding-system.
+       * nnml.el (nnml-file-coding-system): New variable.
+       (nnml-request-article): Use nnml-file-coding-system.
+
+Sun Nov 29 15:12:52 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.56 is released.
+
+1998-11-29 00:52:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-display-part): New function.
+       (gnus-mime-display-mixed): Use it.
+
+       * mm-view.el (mm-setup-w3): Don't register.
+
+       * message.el (message-cite-original): Cite parts.
+
+1998-11-28 23:51:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-parameter-string): New function.
+       (mml-insert-mime-headers): Separated into new function.
+
+1998-11-28  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mml.el (mml-make-boundary): Use `make-string'.
+
+1998-11-27  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * binhex.el (binhex-insert-char): Ditto.
+
+       * base64.el (base64-insert-char): Ditto.
+
+       * uudecode.el (uudecode-insert-char): Code correctly.
+
+1998-11-28 01:08:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-generate-mime): Don't generate multiparts for
+       empties.
+
+       * gnus-art.el (gnus-display-mime): Save excursion.
+
+       * message.el (message-remove-first-header): New function.
+       (message-encode-message-body): Use it.
+
+Fri Nov 27 12:26:10 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.55 is released.
+
+1998-11-27 12:38:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-setup-w3): New function.
+
+       * mm-decode.el (mm-content-id-get-contents): New function.
+       (mm-content-id-get-type): Ditto.
+       (mm-content-id-get-encoding): Ditto.
+       (mm-get-handle-by-content-id): Removed.
+
+1998-11-25  Colin Rafferty  <colin@xemacs.org>
+
+       * message.el (message-generate-new-buffers): Fix tag.
+
+1998-11-25 10:43:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-buffer-name): Check for unique first.
+
+       * gnus-art.el (gnus-unbuttonized-mime-type-p): use
+       gnus-inhibit-mime-unbuttonizing.
+
+       * gnus-sum.el (t): Bind M-t.
+       (gnus-inhibit-unbuttonizing): New variable.
+       (gnus-summary-toggle-display-buttonized): New command.
+
+       * gnus-art.el (gnus-display-mime): Select article window.
+       (article-strip-trailing-space): New command and keystroke.
+
+       * nneething.el (nneething-include-files): New variable.
+       (nneething-create-mapping): Use it.
+
+       * nntp.el (nntp-possibly-change-group): Use nntp-send-command.
+
+       * nnvirtual.el (nnvirtual-request-update-mark): Only yodate
+       ayto-expirable marks.
+
+1998-11-24 21:00:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-view-all-parts): Set buffer.
+
+       * gnus-sum.el (gnus-summary-display-buttonized): Don't pass on
+       ARG.
+
+       * gnus-art.el (gnus-article-mode-line-format): Doc fix.
+
+Tue Nov 24 14:57:41 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-binary-coding-system): New variable.
+       (mm-with-unibyte-buffer): Use mm-binary-coding-system.
+       * mm-decode.el (mm-display-external): Ditto.
+
+Tue Nov 24 10:43:06 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.54 is released.
+
+1998-11-24 11:21:32  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus-sum.el (gnus-newsgroup-default-charset-alist): Note fj.
+
+1998-11-24 11:14:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-save-part): Unquote.
+
+1998-11-24 11:14:39  Matt Armstrong  <matta@geoworks.com>
+
+       * mm-decode.el (mm-save-part): Bind coding system for write.
+
+1998-11-24 10:42:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-mode-line-format): New default.
+       (gnus-article-mime-part-status): New function.
+
+       * message.el (message-send-news): Check the body syntax before
+       encoding.
+
+       * gnus-art.el (gnus-unbuttonized-mime-type): New function.
+       (gnus-mime-display-single): Use it.
+       (gnus-mime-display-alternative): Ditto.
+
+       * mm-decode.el: Check for whether we are running under a term.
+
+1998-11-22 08:12:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-preferred-alternative): Default to first
+       alternative.
+       (mm-preferred-alternative): No, we dont.
+
+Tue Nov 24 03:01:48 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-display-external): Use binary instead of
+       no-conversion.
+       * gnus-agent.el (gnus-agent-file-coding-system): Ditto.
+       * nnheader.el (nnheader-file-coding-system): Ditto.
+       * mm-util.el (mm-with-unibyte-buffer): Use binary instead of nil.
+
+Mon Nov 23 01:51:57 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-newsgroup-setup-default-charset): Use group
+       name without method.
+
+Mon Nov 23 01:26:40 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-newsgroup-default-charset): Rename
+       coding-system -> default-charset.
+       (gnus-newsgroup-default-charset-alist): Ditto.
+       (gnus-summary-local-variables): Ditto.
+       (gnus-set-global-variables): Ditto.
+       (gnus-get-newsgroup-headers): Ditto.
+       (gnus-summary-from-or-to-or-newsgroups): Ditto.
+       (gnus-get-newsgroup-headers-xover): Ditto.
+       (gnus-newsgroup-setup-default-charset): Ditto.
+       (article-decode-mime-words): Ditto.
+       (article-decode-charset): Ditto.
+       (article-decode-encoded-words): Ditto.
+       (article-de-quoted-unreadable): Ditto.
+       (gnus-mime-view-all-parts): Ditto.
+       (gnus-mime-externalize-part): Ditto.
+       (gnus-mm-display-part): Ditto.
+       (gnus-mime-display-single): Ditto.
+       (gnus-mime-display-alternative): Ditto.
+       * lpath.el : Ditto.
+
+Mon Nov 23 00:54:33 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * rfc2047.el (rfc2047-decode-region): Do not decode nil charset.
+       * gnus-art.el (article-decode-charset): Overlay
+       rfc2047-default-charset.
+       * message.el (message-draft-coding-system): New variable.
+       (message-set-auto-save-file-name): Use message-draft-coding-system.
+       * nndraft.el (nndraft-request-article): Ditto.
+       * gnus-start.el (gnus-start-draft-setup): Set charset nil.
+       * gnus-agent.el (gnus-agent-queue-setup): Ditto.
+
+Sun Nov 22 04:42:22 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-test): New function.
+       (mm-uu-dissect): Inherit charset and cte from head.
+       * gnus-art.el (article-decode-charset): Use mm-uu-test.
+
+Sat Nov 21 09:57:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.53 is released.
+
+1998-11-21 05:54:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-get-image): New function.
+       (mm-image-fit-p): New function.
+
+       * gnus-xmas.el (gnus-xmas-annotation-in-region-p): Ditto.
+
+       * gnus-util.el (gnus-annotation-in-region-p): New definition.
+
+       * gnus-art.el (gnus-article-insert-newline): New function.
+       (article-goto-body): New function.
+
+1998-11-20 10:34:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-display-single): Insert blank line before
+       buttons.
+
+       * gnus-sum.el (gnus-summary-display-buttonized): New command and
+       keystroke.
+
+       * gnus-art.el (gnus-mime-display-single): Don't insert a blank
+       line between parts.
+
+       * message.el (message-remove-header): Go to end if wanted.
+
+1998-11-20  Karl Kleinpaste  <karl@justresearch.com>
+
+       * gnus-art.el (gnus-mime-display-alternative): Avoid window
+       movement with save-window-excursion.
+
+Fri Nov 20 03:50:30 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): Use argument as charset.
+
+Fri Nov 20 03:37:53 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-bodies.el (mm-decode-body): Remove buffer-file-coding-system.
+
+Fri Nov 20 01:20:38 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): Use
+       gnus-newsgroup-coding-system.
+       (gnus-get-newsgroup-headers): Ditto.
+       (gnus-get-newsgroup-headers-xover): Ditto.
+       (gnus-set-global-variables): Ditto.
+       * gnus-art.el (article-decode-mime-words): Ditto.
+       (article-decode-charset): Ditto.
+       (article-decode-encoded-words): Ditto.
+       (article-de-quoted-unreadable): Ditto.
+       (gnus-mime-view-all-parts): Ditto.
+       (gnus-mime-externalize-part): Ditto.
+       (gnus-mm-display-part): Ditto.
+       (gnus-mime-display-alternative): Ditto.
+       (gnus-mime-display-single): Ditto.
+       * mm-view.el (mm-inline-text): Use default coding system.
+
+Fri Nov 20 00:54:37 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-newsgroup-coding-system-alist): New variable.
+       (gnus-newsgroup-iso-8859-1-forced-regexp): New variable.
+       (gnus-newsgroup-coding-system): New local variable.
+       (gnus-newsgroup-iso-8859-1-forced): New local variable.
+       (gnus-summary-local-variables): Add two new local variables.
+       (gnus-newsgroup-setup-coding-system): New function.
+       (gnus-select-newsgroup): Setup coding system.
+       * lpath.el: Add two new variables.
+       * mm-util.el (mm-charset-iso-8859-1-forced): New variable.
+       (mm-charset-to-coding-system): Use mm-charset-iso-8859-1-forced.
+       * gnus-cus.el (gnus-group-parameters): Customizable
+       iso-8859-1-forced.
+
+Fri Nov 20 05:30:26 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.52 is released.
+
+1998-11-20 04:32:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-encode-message-header): Encode the default
+       encoding.
+
+       * gnus-art.el (gnus-mime-display-single): Insert buttons for
+       undisplayed text types.
+
+       * mm-decode.el (mm-automatic-display-p): Only prefer inlinable
+       types.
+
+1998-11-19  Felix Lee  <flee@cygnus.com>
+
+       * nntp.el (nntp-after-change-function-callback): recover from C-g.
+
+1998-11-19  Felix Lee  <flee@cygnus.com>
+
+       * gnus-async.el (gnus-asynch-obarray): rename to
+       gnus-async-hashtb, and don't buffer-local it.
+
+       (gnus-async-article-callback): new function.
+       (gnus-make-async-article-function): use it.
+
+       (gnus-async-current-prefetch-group): new var.
+       (gnus-async-current-prefetch-article): new var.
+       (gnus-async-request-fetched-article): are we fetching it already?
+
+       (gnus-async-delete-prefected-entry): s/prefected/prefetched/
+
+1998-11-20 02:49:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-show-article): Require.
+
+       * message.el: Provide before hooks.
+       (message-send-news): Do MIME before headers.
+
+       * gnus-art.el (gnus-article-check-buffer): New function.
+       (gnus-article-read-summary-keys): Use it.
+
+       * mm-decode.el (mm-user-automatic-display): Display all inline
+       images.
+
+       * gnus-art.el (gnus-mime-display-single): Don't buttonize so
+       much.
+       (gnus-unbuttonized-mime-types): New variable.
+
+1998-11-19 06:29:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-inhibit-user-auto-expire): Changed to t.
+
+       * mm-decode.el (mm-quote-arg): Quote semicolons.
+
+       * gnus-art.el (gnus-mime-display-single): Don't display
+       attachments.
+       (gnus-mime-externalize-part): New command and keystroke.
+
+       * mm-decode.el (mm-dissect-buffer): Pass on the description info.
+       (mm-alternative-precedence): Changed order.
+
+1998-11-07 17:41:47  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.el (gnus-method-simplify): New function.
+       (gnus-native-method-p): New function.
+       (gnus-secondary-method-p): Use gnus-method-equal.
+
+       * gnus-start.el (gnus-group-change-level): Shorten select method.
+
+Thu Nov 19 04:48:42 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.51 is released.
+
+1998-11-19 04:02:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Applied patches from 5.6.45.
+
+       * gnus-score.el (gnus-score-find-trace): Print complete file
+       paths.
+       (gnus-score-find-trace): Truncate lines.
+
+       * gnus.el (gnus-message-archive-group): Allow function.
+
+       * message.el (message-encode-message-body): Remove Mime-Version
+       before inserting.
+
+       * gnus-cus.el (gnus-group-customize): Optional topic.
+
+       * gnus-sum.el (gnus-summary-customize-parameters): New command and
+       keystroke.
+
+Wed Nov 18 13:46:08 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-encode-message-body): Rewrite.
+
+1998-11-18 07:37:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-base-boundary): New variable.
+       (mml-make-boundary): New function.
+
+       * gnus-cache.el (gnus-cache-coding-system): New variable.
+       (gnus-cache-request-article): Use it.
+
+       * message.el (message-insert-mime-part): Delete duplicates.
+
+Wed Nov 18 11:52:19 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-alternative): Set end of
+       multipart and display even when nothing is preferred.
+
+Wed Nov 18 05:06:44 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.50 is released.
+
+1998-11-18 04:42:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-media-tests): Check that device-type is
+       fbound.
+
+       * gnus-sum.el (gnus-summary-sort): Didn't do reverse.
+
+1998-11-07 23:39:48  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.el (gnus-similar-server-opened): Compare backend.
+
+1998-11-08 03:37:42  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-topic.el (gnus-topic-expire-articles): New function.
+       (gnus-topic-mode-map): Bind it.
+
+       * gnus.texi (Topic Commands): New expiry command. Reordered.
+
+1998-11-10  Miles Bader  <miles@ccs.mt.nec.co.jp>
+
+       * gnus-sum.el
+       (gnus-auto-expirable-marks): New variable.
+       (gnus-inhibit-user-auto-expire): New variable.
+       (gnus-summary-mark-article-as-read, gnus-summary-mark-article):
+       When looking to see if we should expire instead, check
+       gnus-auto-expirable-marks instead of using a hard-wired list.
+       (gnus-summary-mark-as-read-forward,
+       gnus-summary-mark-as-read-backward):
+       Pass gnus-inhibit-user-auto-expire for the no-expire argument to
+       gnus-summary-mark-forward, instead of `t'.
+
+1998-11-18 03:30:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-compute-boundary): New function.
+       (mml-compute-boundary-1): New function.
+       (mml-generate-mime-1): Use it.
+
+1998-11-18  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mml.el (mml-generate-mime-1): Always precede closing boundary
+       with newline.
+
+1998-11-18 02:36:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-generate-mime-1): Do right boundaries when several
+       multiparts.
+
+       * mm-decode.el (mm-user-automatic-display): Default to inline
+       jpeg.
+
+       * mml.el (mml-generate-mime-1): Encode non-text parts.
+
+Wed Nov 18 02:22:23 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.49 is released.
+
+1998-11-18 00:37:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-view.el (mm-inline-text): Require w3-vars.
+
+       * gnus-setup.el (gnus-use-tm): Removed.
+
+       * gnus-art.el (gnus-article-goto-part): Don't beep.
+       (gnus-article-view-part): Check return value.
+       (gnus-mime-display-alternative): Don't display when there is
+       nothing to display.
+
+       * mml.el (mml-generate-mime-1): Don't use a unibyte buffer.
+       (mml-generate-mime-1): Use unibyte for binaries.
+
+       * gnus-art.el (gnus-display-mime): Call
+       gnus-article-mime-part-function.
+       (gnus-mime-part-function): New function.
+       (gnus-article-mime-part-function): New function.
+
+       * mml.el (mml-generate-mime-1): Don't insert so many newlines.
+
+1998-11-16 06:44:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mml.el (mml-generate-mime-1): Do it in unibyte buffers.
+
+       * message.el (message-font-lock-keywords): Highlight MML.
+       (message-mml-face): New font.
+
+Mon Nov 16 23:34:12 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-display-mime): Clean up even when no handles.
+       (gnus-mm-display-part): Do not select-window if the article window
+       is not found.
+
+Mon Nov 16 02:26:40 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-move-article): Use no-encode for B m.
+
+Mon Nov 16 02:00:05 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.48 is released.
+
+1998-11-15 23:18:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-encode-body): Disbabled for nonmule.
+
+       * mm-util.el (mm-find-charset-region): Bogus change for non-Mule.
+
+       * message.el (message-cite-original-without-signature): Ditto.
+       (message-cite-original): Quote parts.
+
+Sun Nov 15 22:01:55 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.47 is released.
+
+1998-11-15 20:11:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Insert MIME warning.
+
+       * mml.el (mml-read-tag): Look for #tag.
+
+       * mm-util.el (mm-find-charset-region): Check whether
+       enable-multibyte-characters is bound.
+
+Sun Nov 15 02:01:31 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.46 is released.
+
+1998-11-15 01:54:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Insert headers at the
+       right spot.
+
+Sun Nov 15 01:13:41 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.45 is released.
+
+1998-11-15 00:28:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nndraft.el (nndraft-save-mime-part): Removed.
+       (nndraft-get-mime-part): Ditto.
+
+       * message.el (message-format-mime-old): Removed.
+       (message-encode-message-body): Removed.
+       (message-encode-message-body): Renamed.
+
+1998-11-14 18:27:19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Translate \r's.
+
+       * message.el (message-format-mime): Check message-mime-part.
+
+       * mm-encode.el (mm-mime-file-types): Removed.
+       (mm-default-file-encoding): New definition.
+
+Sat Nov 14 01:29:39 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-image): Use mm-insert-inline.
+       * gnus-art.el (gnus-mm-display-part): Go to correct position.
+
+Sat Nov 14 05:47:57 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.44 is released.
+
+1998-11-14 03:59:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-format-mime): New function.
+
+       * nndraft.el (nndraft-save-mime-part): New function.
+       (nndraft-get-mime-part): New function.
+
+       * mm-encode.el (mm-default-file-encoding): New function.
+       (mm-content-transfer-encoding): New function.
+       (mm-encode-buffer): New function.
+
+       * message.el: New command.
+       (message-mime-part): New variable.
+       (message-insert-mime-part): New command.
+
+       * mm-encode.el (mm-encode-content-transfer-encoding): New
+       function.
+
+       * mm-util.el (mm-content-transfer-encoding-defaults): New
+       variable.
+       (mm-mime-file-types): Taken from TM.
+
+Sat Nov 14 01:51:06 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.43 is released.
+
+1998-11-07  Karl Kleinpaste  <karl@jprc.com>
+
+       * gnus-cus.el (gnus-score-customize): Add "Extra" element.
+       * gnus-score.el (gnus-score-default-header): Ditto.
+       (gnus-header-index): Ditto.
+       (gnus-summary-increase-score): Ditto, & process "extra" requests.
+       (gnus-summary-header): Handle extra headers.
+       (gnus-summary-score-entry): Ditto, & provide new score element.
+       (gnus-summary-score-effect): Ditto.
+       (gnus-score-string): Avoid "extra" string sort, & modify match in
+       "extra" case.
+       * gnus-sum.el (gnus-make-score-map): Add "extra" element.
+
+1998-11-13 20:30:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-resend): Bind message-required-mail-headers
+       to nil.
+
+       * mm-view.el (mm-inline-text): Bind w3-strict-width.
+
+       * nngateway.el (require): Require cl.
+
+       * gnus-art.el (gnus-button-alist): Exclude more chars from news:
+       things.
+
+Wed Nov 11 02:15:06 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Create directory even
+       when no articles.
+
+1998-11-13 19:25:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-ignored-resent-headers): Remove X-Gnus.
+
+1998-11-10  Colin Rafferty  <colin@xemacs.org>
+
+       * gnus-sum.el (gnus-ignored-from-addresses): Only quote
+       user-mail-address if non-nil.
+
+1998-11-13 18:50:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-make-sort-function): Do `reverse'.
+       (gnus-make-sort-function-1): Ditto.
+
+       * gnus-art.el (gnus-mm-display-part): Switch to mm in right
+       window.
+
+1998-11-12 22:31:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-with-unibyte-buffer): Ditto.
+
+       * binhex.el (binhex-decode-region): Quote.
+
+1998-11-10 05:32:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-decode-charset): Don't downcase charset.
+
+       * gnus-sum.el (gnus-get-newsgroup-headers-xover): Translate CR's.
+
+Sun Nov  8 23:17:24 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.42 is released.
+
+Sun Nov  8 02:36:33 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-display-mime): Add id for alternative part.
+
+1998-11-08 02:24:47  Simon Josefsson  <jas@pdc.kth.se>
+
+       * nntp.el (nntp-send-mode-reader): Revert.
+
+Sun Nov  8 00:45:13 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-articles): Use with-temp-buffer.
+
+Sat Nov  7 23:07:24 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.el (message-make-date): Fix for negative time zones.
+
+Sun Nov  8 01:00:16 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.41 is released.
+
+1998-11-08 00:52:38  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mm-decode.el (mm-dissect-multipart): Quote regexp.
+
+1998-10-29  Sudish Joseph  <sj@eng.mindspring.net>
+
+       * gnus.el (gnus-short-group-name): When shortening foreign select
+       methods, do not scan for plusses beyond the first colon.
+
+1998-11-07  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-save-group-info): Cater for group info
+       lines where `group' is the last thing on the line.
+
+1998-11-08 00:35:09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-view-part): Do alternative.
+       (gnus-mime-display-alternative): Insert marker.
+
+1998-11-07 14:33:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-dissect-multipart): Quote regexp.
+
+       * nnmail.el (nnmail-expired-article-p): Protect against bogus
+       dates.
+
+       * gnus-cus.el (gnus-topic): Required.
+
+       * nnheader.el (nnheader-parse-nov): Parse extra.
+       (nnheader-nov-parse-extra): New macro.
+
+1998-10-31 12:33:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-view-part): Internal move.
+
+1998-10-28  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus-cus-new.el (gnus-custom-topic): New free variable.
+       (gnus-group-customize): Support editing topic parameters.
+
+1998-10-29 12:09:20  Karl Kleinpaste  <karl@jprc.com>
+
+       * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): Add
+       indicators.
+
+1998-10-29 11:31:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mm-display-part): Return.
+       (gnus-article-view-part): Only go if external.
+       (gnus-article-dumbquotes-map): Do 205.
+
+       * mm-decode.el (mm-display-part): Return what was done.
+
+       * message.el (message-buffer-naming-style): New variable.
+       (message-generate-new-buffers): Extended.
+       (message-buffer-naming-style): Removed.
+       (message-buffer-name): Use it.
+       (message-do-send-housekeeping): Rename new styling.
+
+       * gnus-sum.el (gnus-summary-recenter): Allow
+       gnus-auto-center-summary to be a number.
+
+Wed Nov  4 02:24:39 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * pop3.el (pop3-open-server): Use "binary" instead of
+       "no-conversion".
+
+Sun Nov  1 01:26:42 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-srvr.el (gnus-browse-foreign-server): Set
+       gnus-browse-current-method to the result of gnus-server-to-method.
+
+Thu Oct 29 01:47:44 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-util.el (gnus-pull): Another optional argument.
+       * nnweb.el (nnweb-request-delete-group): Delete from
+       nnweb-group-alist and update active file.
+
+Thu Oct 29 01:05:08 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-group.el (gnus-group-make-group): Accept group of new
+       method.
+
+Wed Oct 28 02:19:16 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Update dribble.
+
+Tue Oct 27 11:59:31 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-view.el (mm-inline-text): Postion of html portion.
+
+1998-10-29 10:26:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nntp.el (nntp-list-active-group): Waited for short strings.
+       (nntp-send-mode-reader): Ditto.
+       (nntp-open-connection): Ditto.
+
+       * gnus-int.el (gnus-request-group-articles): New function.
+
+       * nntp.el (nntp-request-listgroup): New function.
+       (nntp-request-group-articles): Renamed.
+
+1998-10-27 10:37:52  Karl Kleinpaste  <karl@jprc.com>
+
+       * nnheader.el (nnheader-parse-nov): Supply extra.
+
+1998-10-26 23:03:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-button-push): Don't go to
+       gnus-article-buffer.
+
+       * mm-view.el (mm-inline-image): Add a newline.
+
+       * gnus-start.el (gnus-check-first-time-used): Check more.
+
+1998-10-26 23:03:29  Francois Felix Ingrand  <felix@laas.fr>
+
+       * gnus-start.el (gnus-check-first-time-used): Check current.
+
+1998-10-26 22:07:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-find-charset-region): New function.
+
+       * ietf-drums.el (ietf-drums-narrow-to-header): Work when no header.
+
+       * gnus-art.el (gnus-mime-button-menu): Fix.
+
+1998-10-26 22:07:43  Michael Welsh Duggan  <md5i@cs.cmu.edu>
+
+       * gnus-art.el (gnus-mime-button-menu): New definition.
+
+1998-10-26 01:46:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-decode-charset): Downcase charset.
+       (article-decode-charset): Pass on type.
+       (article-decode-charset): Check nil charsets.
+       (article-remove-cr): Translate CR to LF.
+       (gnus-ignored-mime-types): Default to nil.
+
+       * nnheader.el (nnheader-insert-nov): Work when not Xref.
+
+       * gnus-sum.el (gnus-ignored-from-addresses): Default to
+       user-mail-address.
+       (gnus-nov-parse-extra): Didn't return right thing.
+
+1998-10-25 23:25:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-xmas.el: Use compiled-function-p.
+
+Mon Oct 26 14:37:19 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-copy-Yo-buffer): Make it works when no header.
+
+Sun Oct 25 23:11:44 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.40 is released.
+
+1998-10-25 21:41:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-mark-forward): Show thread.
+
+       * gnus-start.el (gnus-check-first-time-used): Ignore dribble.
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Bind name.
+
+       * nnml.el (nnml-possibly-create-directory): Check before making.
+
+1998-10-25 19:43:08  Kai Grossjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * nnheader.el (nnheader-insert-nov): Don't infloop.
+
+1998-10-25 19:26:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-set-mode-line): Check that the spec has been
+       set up.
+
+1998-10-25 19:22:03  Joerg Lenneis  <lenneis@statrix2.wu-wien.ac.at>
+
+       * nneething.el (nneething-file-name): New definition.
+
+1998-10-25 17:56:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-treatment-function-alist): Fix.
+       (gnus-summary-save-in-rmail): Use gnus-output-to-rmail.
+
+       * nndoc.el (nndoc-dissect-mime-parts-sub): Recognize first part.
+
+Sun Oct 25 06:23:13 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.39 is released.
+
+1998-10-25 00:34:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-ignored-mime-types): New variable.
+       (gnus-mime-display-single): Use it.
+       (gnus-treatment-function-alist): New variable.
+
+       * gnus.el (gnus-mime): New group.
+
+       * gnus-art.el (gnus-mime-display-alternative): Don't destroy
+       things for other parts.
+       (gnus-mime-display-alternative): Place point.
+
+       * gnus.el: autoload gnus-uu-post-news.
+
+       * mailcap.el (mailcap-mailcap-entry-passes-test): Also check
+       needsterm/DISPLAY.
+
+       * mm-decode.el (mm-display-part): Default to inline text/.*
+       parts.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Default to
+       8bit.
+
+       * gnus-art.el (gnus-mime-copy-part): Use normal-mode.
+       (gnus-mime-display-single): Inline all text parts.
+       (gnus-article-narrow-to-signature): Removed mime:: stubs.
+
+1998-10-24 21:38:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnml.el (nnml-possibly-create-directory): Rewrite.
+       (nnml-request-create-group): Change to right server.
+
+       * gnus-xmas.el (gnus-xmas-define): Use byte-code-function-p.
+
+       * gnus-sum.el (gnus-set-mode-line): Use truncate-string-to-width.
+
+       * gnus.el: rmail-output-to-rmail-file autoload.
+
+       * gnus-util.el (gnus-output-to-rmail): Didn't work if not in
+       Gnus.
+
+       * nnheader.el (nnheader-parse-head): Checked wrong variable.
+
+       * gnus-sum.el (gnus-summary-update-mark): Ignore nil'd marks.
+
+Tue Oct 20 23:37:43 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-mixed): Multipart in
+       mixed part.
+
+Tue Oct 20 23:36:43 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-exit): Use mm-destroy-parts.
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Ditto.
+
+Tue Oct 20 16:22:51 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Create pseudo multipart head.
+
+1998-10-24 20:51:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-valid-move-group-p): Make sure group has a
+       value.
+
+       * gnus-art.el (gnus-article-hidden-text-p): Return nil when not
+       hidden.
+
+       * gnus-spec.el (gnus-update-format-specifications): Use the
+       article mode line spec.
+
+       * gnus-art.el (gnus-insert-mime-button): Put right type.
+       (gnus-insert-prev-page-button): Ditto.
+       (gnus-insert-next-page-button): Dutti.
+
+       * pop3.el: New version installed.
+
+Sat Oct 24 16:48:51 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Delete the begining spurious newline
+       and display last part.
+
+Sat Oct 24 20:31:55 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.38 is released.
+
+1998-10-24 07:54:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-mime-decode-quoted-printable-buffer):
+       Removed.
+       (article-de-quoted-unreadable): Narrow to default.
+
+       * qp.el (quoted-printable-encode-region): Encode before QP-ing.
+
+       * gnus-art.el (article-decode-charset): Decode even when broken
+       MIME.
+
+       * gnus-sum.el (gnus-summary-from-or-to-or-newsgroups): Return
+       name.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Delete headers.
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Use
+       nnheader.
+
+       * nnmail.el (nnmail-extra-headers): New variable.
+
+       * nnheader.el (nnheader-insert-nov): Insert extra.
+
+       * gnus.el (gnus-summary-line-format): Doc fix.
+
+       * gnus-sum.el (gnus-get-newsgroup-headers): Parse extra.
+       (gnus-nov-parse-line): Ditto.
+       (gnus-nov-parse-extra): New macro.
+       (gnus-header): New function.
+       (gnus-update-summary-mark-positions): Change.
+       (gnus-ignored-from-addresses): New variable.
+       (gnus-summary-insert-from-or-to): New function.
+
+       * gnus.el (gnus-extra-headers): New variable.
+
+       * nnheader.el (make-mail-header): Expand.
+       (mail-header-extra): New macro.
+       (mail-header-set-extra): Ditto.
+       (make-full-mail-header): Expand.
+
+Sat Oct 24 07:41:42 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.37 is released.
+
+1998-10-24 07:29:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-decode-body): Check for multibyticity.
+
+       * mm-util.el (mm-enable-multibyte): Don't always switch multibyte
+       on.
+
+1998-10-22  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-spec.el (gnus-balloon-face-function): new function
+       (gnus-parse-format): understand the %< %> specifiers
+       (gnus-parse-complex-format): ditto.
+
+1998-10-24 06:31:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Changed following-char to char-after throughout.
+
+1998-10-22 04:05:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-display-external): Protect more and message.
+
+Wed Oct 21 03:26:30 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-xmas.el (gnus-xmas-article-push-button): Go to the
+       position.
+
+Tue Oct 20 23:37:43 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-display-mixed): Multipart in
+       mixed part.
+
+Tue Oct 20 23:36:43 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-exit): Use mm-destroy-parts.
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Ditto.
+
+Tue Oct 20 16:22:51 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el (mm-uu-dissect): Create pseudo multipart head.
+
+1998-10-21  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * mailcap.el (mailcap-save-binary-file): Use unwind-protect.
+
+       * mm-decode.el (mm-display-external): Set undisplayer to mm
+       buffer, not the current buffer; use unwind-protect.
+
+1998-10-21 00:07:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-exit): Destroy parts.
+       (gnus-summary-exit-no-update): Ditto.
+
+1998-10-20 22:02:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-media-tests): Look for w3.
+
+       * mailcap.el (mailcap-mime-data): Inline html.
+
+Tue Oct 20 20:25:03 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.36 is released.
+
+1998-10-20 18:13:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-translate-strings):
+       (gnus-article-dumbquotes-map): Don't dot.
+
+       * pop3.el (pop3-open-server): Set point right.
+
+       * mm-decode.el (mm-dissect-multipart): Dissect hierarchically.
+       (mm-dissect-buffer): Ditto.
+       (mm-destroy-part): Ignore non-handles.
+       (mm-remove-part): Ditto.
+       (mm-destroy-parts): New function.
+       (mm-remove-parts): Ditto.
+
+       * gnus-art.el (gnus-mm-display-part): Don't move point.
+
+Tue Oct 20 02:16:36 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-uu.el : New file.
+
+       * gnus-art.el (gnus-display-mime): Dissect uu stuffs.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Encoding as
+       a function.
+
+1998-10-20 00:35:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-display-external): Check before selecting.
+
+Sat Sep 26 02:03:00 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-multi-decode-encoded-word-string): Rewrite.
+
+       * gnus-sum.el (gnus-decode-encoded-word-methods): New variable.
+
+       * gnus-sum.el (gnus-decode-encoded-word-methods-cache): New
+       variable.
+
+       * gnus-sum.el (gnus-encoded-word-method-alist): Deleted.
+
+       * gnus-art.el (gnus-decode-header-methods): New variable.
+
+       * gnus-art.el (gnus-decode-header-methods-cache): New variable.
+
+       * gnus-art.el (gnus-multi-decode-header): New function.
+
+Tue Oct 20 00:24:16 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.35 is released.
+
+1998-10-20 00:00:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * uudecode.el (uudecode-decode-region-external): Insert
+       literally.
+
+       * gnus-xmas.el (gnus-xmas-mime-button-menu): Moved here.
+
+       * mm-bodies.el (mm-decode-body): Optional encoding.
+
+1998-10-19 23:57:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-ems.el (gnus-mouse-3): New variable.
+
+       * binhex.el (binhex-decode-region-external): Don't use -internally.
+
+1998-10-16 14:54:02  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mailcap.el (mailcap-parse-mailcaps): Only open regular
+       files.
+
+1998-09-26 22:28:01  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-group.el (gnus-add-marked-articles): Request backend update
+       of flags.
+
+1998-09-26 19:39:31  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-update-read-articles):
+       (gnus-update-marks): Request backend update of mark.
+
+1998-09-26 19:33:58  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (Optional Backend Functions): New item,
+       nnchoke-request-set-mark.
+
+1998-09-26 16:27:27  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-range.el (gnus-remove-from-range): Don't add stuff in
+          list to range.
+
+1998-10-19 23:45:13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus-sum.el (gnus-summary-exit-no-update): Don't expire.
+
+1998-10-14  SL Baur  <steve@altair.xemacs.org>
+
+       * gnus-sum.el: Move gnus-save-hidden-threads above where it is
+       first used.
+
+1998-10-10  SL Baur  <steve@altair.xemacs.org>
+
+       * mm-view.el: Require mm-decode for macros.
+
+       * mm-decode.el (mm-handle-type): Move macro declarations above the
+       place where they are used.
+
+Sun Oct 18 13:59:07 1998  Kurt Swanson  <ksw@dna.lth.se>
+
+        * gnus-msg.el (gnus-summary-mail-forward): Erase old forward
+        buffer.
+
+1998-10-19 23:38:11  Katsumi Yamaoka  <yamaoka@ga.sony.co.jp>
+
+       * nnagent.el (nnagent-open-server): Error message.
+
+1998-10-19 23:35:08  Joerg Lenneis  <lenneis@statrix2.wu-wien.ac.at>
+
+       * nnheader.el (nnheader-article-p): Recognize lower-case headers.
+
+1998-10-19  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * score-mode.el (gnus-score-mode-map): Ditto.
+
+       * message.el (message-mode-map): Ditto.
+
+       * gnus-uu.el (gnus-uu-post-news): Ditto.
+
+       * gnus-kill.el (gnus-kill-file-mode-map): Ditto.
+
+       * gnus-eform.el (gnus-edit-form-mode-map): Ditto.
+
+       * gnus-art.el (gnus-article-edit-mode-map): Use
+       `set-keymap-parent' rather than `copy-keymap'.
+
+1998-10-18  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (gnus-mime-button-commands): New variable.
+       (gnus-mime-button-map): Initialize it from
+       `gnus-mime-button-commands'.
+       (gnus-mime-button-menu): New function.
+       (gnus-insert-mime-button): Use `gnus-mime-button-map'.
+
+1998-10-11  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * message.el (message-insert-to): Make `nobody' and `poster'
+       synonymous to `never' and `always' in Mail-Copies-To.
+       (message-reply): Ditto.
+       (message-followup): Ditto.
+
+1998-10-19 23:17:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-data): Save sound.
+
+1998-09-24  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * message.el (message-ignored-supersedes-headers): Include
+       `NNTP-Posting-Date'.
+
+1998-10-19 01:25:27  Jonas Steverud  <d4jonas@dtek.chalmers.se>
+
+       * gnus-art.el (gnus-article-dumbquotes-table): New variable.
+
+1998-10-19 00:50:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Use
+       uudecode.
+
+1998-10-18 18:20:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-display-external): Don't switch on save.
+
+1998-10-18 18:14:06  Andy Piper  <andyp@parallax.co.uk>
+
+       * nnmail.el (nnmail-movemail-args): New variable.
+
+1998-10-18 00:17:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-translate-strings):
+
+1998-10-17 22:51:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-view-part): Use it.
+       (gnus-mm-display-part): New function.
+       (article-de-quoted-unreadable): Yse mm-default-coding-system.
+
+       * mm-decode.el (mm-handle-displayed-p): New function.
+
+       * gnus-art.el (gnus-mime-copy-part): Create better names.
+       (gnus-mime-button-line-format): Include dots spec.
+
+1998-10-15  Matt Pharr  <mmp@graphics.stanford.edu>
+
+      * gnus-msg.el (gnus-summary-mail-forward): Erase contents of old
+      forward buffer first.
+
+1998-10-17 21:16:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-set-window-start): New function.
+
+       * message.el (message-send): Don't check changed.
+
+1998-10-12 15:26:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-setup-buffer): Set params.
+
+       * mm-decode.el (mm-user-display-methods): Inline
+       "message/delivery-status".
+
+1998-10-11 07:06:38  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-auto-save-directory): Rename.
+       (message-mode): Dof fix.
+
+       * gnus-art.el (gnus-summary-save-in-pipe): Default to "cat".
+       (gnus-summary-save-in-pipe): No, check gnus-last-shell-command.
+
+       * nndoc.el (nndoc-mime-parts-type-p): Be a bit more forgiving.
+
+       * message.el (message-make-date): Avoid locale.
+
+       * gnus-art.el (gnus-article-edit-done): Allow update before doing
+       cache.
+
+       * mm-decode.el (mm-display-inline): Goto point-min.
+
+       * gnus-art.el (gnus-article-prepare-display): Not read-only.
+
+       * mm-decode.el (mm-display-external): Reverse before sorting.
+
+       * gnus-draft.el (gnus-draft-send): Allow mail.
+
+1998-10-10 -SL Baur  <steve@altair.xemacs.org>
+
+       * message.el (message-check): Move message-check macro above where
+       it is first used.
+
+       * gnus-art.el (article-hide-pgp): Hide the PGP 5/GNUPG Hash: line.
+
+1998-10-11 06:45:37  Lloyd Zusman  <ljz@asfast.com>
+
+       * gnus-sum.el (gnus-summary-make-menu-bar): Fix.
+
+Sun Oct 11 02:28:40 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.34 is released.
+
+1998-10-11 02:15:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inline-media-tests): delivery-status.
+
+       * mm-view.el (mm-inline-text): Provide default.
+
+1998-10-11 01:01:37  Lloyd Zusman  <ljz@asfast.com>
+
+       * mailcap.el (mailcap-possible-viewers): Fix nils.
+
+1998-10-11 00:03:37  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-edit-exit): Don't do updates.
+       (article-update-date-lapsed): Record the buffer.
+       (article-update-date-lapsed): Do all windows that display article
+       buffers.
+
+       * nnml.el (nnml-generate-nov-databases-1): Ditto.
+
+       * gnus-score.el (gnus-score-score-files-1): Ignore dotted files.
+
+       * gnus-art.el (gnus-insert-mime-button): Mark buttons as
+       annoations.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Decode properly.
+
+1998-10-10 22:07:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-category-add): Change default category to
+       'false.
+
+       * nnvirtual.el (nnvirtual-update-read-and-marked): Don't nix out
+       scores.
+
+       * gnus-draft.el (gnus-draft-send): Check server more.
+
+       * gnus-art.el (gnus-article-view-part): New command and keystroke.
+       (gnus-article-goto-part): New function.
+
+       * mm-view.el (mm-inline-text): Insert richtext properly.
+
+       * gnus-art.el (gnus-insert-mime-button): Store handle in alist.
+
+1998-10-03 15:04:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * parse-time.el (parse-time-rules): Accept dates far into the past
+       and the future, and parse single-digit numbers as years.
+
+1998-10-02 04:46:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-display-external): Chop off directories.
+
+1998-10-01 07:33:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * uudecode.el (uu-decode-region-external): Use
+       insert-file-contents-literally.
+
+       * gnus-cache.el (gnus-cache-generate-active): Translate _ to :.
+
+1998-10-01 07:02:11  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * uudecode.el: New file.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Do
+       x-uuencode.
+
+1998-10-01 05:19:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-display-alternative): Set faces.
+
+       * message.el (message-fetch-field): Unfold properly.
+
+       * mm-bodies.el (mm-decode-content-transfer-encoding): Replace CRLF
+       in text/plain.
+
+1998-09-30 05:47:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-first-unread-subject): New command.
+       (gnus-auto-select-first): Removed.
+       (gnus-auto-select-first): Extended.
+       (gnus-summary-read-group-1): Use new value.
+
+1998-09-29 13:21:06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-fix-before-sending): Space.
+
+       * nnmail.el (nnmail-find-file): Don't erase.
+
+Wed Sep 30 23:49:03 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-agent.el (gnus-agent-fetch-headers): Do not decode headers.
+
+Wed Sep 30 23:46:29 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-soup.el (gnus-soup-add-article): Do not decode headers.
+
+Wed Sep 30 23:44:08 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-soup.el (gnus-soup-pack-packet): Pack only if necesary.
+
+Sat Sep 26 03:04:18 1998  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * mm-util.el (mm-with-unibyte-buffer): Make it work in XEmacs
+       20.4.
+
+1998-09-29 11:35:09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-view-all-parts): New command and
+       keystroke.
+
+       * mm-decode.el (mm-display-external): Translate slashes.
+
+       * nnmail.el (nnmail-find-file): Restrict auto-mode-alist.
+
+       * nndraft.el (nndraft-retrieve-headers): Don't copy so much.
+
+       * mm-decode.el (mm-quote-arg): Quote spaces.
+       (mm-display-external): Quote args.
+
+1998-09-24 22:27:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-inlinable-part-p): New function.
+
+1998-09-25 22:28:01  Simon Josefsson  <jas@pdc.kth.se>
+
+       * mm-util.el (mm-disable-multibyte): New function.
+
+Thu Sep 24 20:28:31 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.33 is released.
+
+1998-09-24 18:47:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-insert-mime-button): Get buffer size.
+
+       * mm-decode.el (mm-display-external): Don't switch for externals.
+       (mm-dissect-multipart): Don't include end-sep.
+
+       * mm-util.el (mm-get-coding-system-list): New function.
+       (mm-coding-system-list): New variable.
+
+Thu Sep 24 02:08:10 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * gnus-cus.el (gnus-group-parameters): Add charset as a parameter
+
+Thu Sep 24 02:05:48 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * gnus-cus.el (gnus-group-customize): Use variable as cons not as
+       group
+
+Thu Sep 24 01:41:03 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * base64.el (base64-run-command-on-region): External base64
+       decoder do not use coding system
+
+Thu Sep 24 01:39:44 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-interactively-view-part): Typo.
+
+Thu Sep 24 01:37:30 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-multipart): Display last part when the
+       article has no close-delimiter
+
+Thu Sep 24 01:28:54 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * mm-decode.el (mm-dissect-buffer): Display parts which have no
+       content-type.
+
+Thu Sep 24 01:23:57 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-display-mime): Typo.
+
+Thu Sep 24 02:29:57 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.32 is released.
+
+1998-09-24 00:27:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-kill.el (gnus-batch-score): Protect against errors.
+
+       * gnus-art.el: Protect against broken headers.
+
+       * mm-decode.el (mm-display-external): Respect needsterm.
+       (mm-display-external): Create buffer for external commands.
+
+1998-09-23 22:04:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mailcap.el (mailcap-mime-info): Return the proper viewer.
+
+       * mm-decode.el (mm-display-external): Use file name.
+
+1998-09-22  Markus Rost  <markus.rost@mathematik.uni-regensburg.de>
+
+       * gnus-util.el (gnus-output-to-rmail):  adjust to
+          `rmail-output-to-rmail-file'
+
+1998-09-23 20:07:00  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-output-to-rmail): Reinstated function.
+
+       * gnus-sum.el (gnus-select-newsgroup): Set global variables before
+       headers.
+
+       * gnus-art.el (article-decode-charset): Fold case.
+
+1998-09-17 15:49:10  Simon Josefsson  <jas@pdc.kth.se>
+
+        * mailcap.el (mailcap-save-binary-file): Goto point-min.
+
+1998-09-23 19:48:52  Aaron M. Ucko  <amu@mit.edu>
+
+       * nnmail.el (nnmail-check-duplication): Enter into duplicate list
+       after being stored.
+
+Tue Sep 15 16:15:16 1998  Kurt Swanson  <ksw@dna.lth.se>
+
+       * gnus-salt.el (gnus-pick-setup-message): Return from whence ye
+       come.
+
+1998-09-23 19:42:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-xmas.el (wid-edit): Required.
+
+       * gnus-ems.el (gnus-widget-button-keymap): New variable.
+
+Sun Sep 20 00:27:55 1998  ZHU Shenghuo  <zsh@cs.rochester.edu>
+
+       * gnus-art.el (gnus-mime-inline-part): remove part if necessary
+
+1998-09-23 19:30:52  Matt Armstrong  <matta@geoworks.com>
+
+       * gnus-art.el (article-decode-charset): Narrow to the correct
+       region.
+
+       * mm-bodies.el: Fix autoload.
+
+1998-09-22 18:35:12  Lee Willis  <lee@gbdirect.co.uk>
+
+       * gnus-art.el (gnus-mime-button-line-format): Doc fix.
+
+1998-09-22 14:53:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-decode): Use rfc2047-default-charset.
+
+1998-09-19 13:58:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-insert-mime-button): Specify keymap.
+       (gnus-article-add-button): Ditto.
+
+       * gnus-sum.el (gnus-summary-insert-pseudos): Use mm.
+
+       * gnus-art.el (gnus-article-prepare-display): Make article mode.
+       (gnus-article-prepare-display): Bind url-standalone-mode.
+
+       * mm-decode.el (mm-remove-part): Also delete directory.
+       (mm-display-external): Create a private sub-dir.
+
+       * mailcap.el (mailcap-binary-suffixes): New variable.
+       (mailcap-command-p): Use it.
+
+1998-09-16 10:38:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmbox.el (nnmbox-request-group): Change server.
+       (nnmbox-possibly-change-newsgroup): Enable multibyte.
+
+       * message.el (message-encode-message-body): Don't stomp MIME
+       headers.
+
+       * gnus-sum.el (gnus-summary-edit-article-done): Don't encode
+       unless useful.
+       (gnus-summary-exit): Check for a live article buffer.
+       (gnus-summary-exit-no-update): Ditto.
+
+       * gnus-int.el (gnus-request-replace-article): Accept no-encode
+       param.
+
+       * gnus-sum.el (gnus-article-decoded-p): New variable.
+
+       * mm-decode.el (mm-display-external): Use no-conv.
+
+       * rfc2047.el (rfc2047-q-encode-region): Bound properly.
+       (rfc2047-charset-encoding-alist): Use B encoding for koi8-r.
+
+       * gnus-art.el (gnus-article-mode-map): Bind button2 to
+       mouse-click.
+
+1998-09-15 14:38:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-agent.el (gnus-agent-expire): Protect against nil infos.
+
+Mon Sep 14 18:55:38 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.31 is released.
+
+1998-09-14 15:12:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-exit): Destroy MIME.
+
+       * mm-decode.el (mm-display-part): Accept no-default.
+
+       * gnus-art.el (gnus-insert-mime-button): buffer-size doesn't take
+       a parameter.
+
+       * gnus-sum.el (gnus-summary-insert-line): Don't exclude faces.
+       (gnus-summary-prepare-threads): Ditto.
+
+       * gnus.el (gnus-article-mode-map): Make sparse keymap.
+
+       * gnus-art.el (gnus-mime-button-line-format-alist): Allow a %d spec.
+       (gnus-mime-button-line-format): Doc fix.
+       (gnus-insert-mime-button): Use it.
+       (gnus-article-add-button): Use widget-convert-button.
+
+       * gnus.el ((featurep 'gnus-xmas)): Defalias gnus-decode-rfc1522 to
+       ignore.
+
+       * mm-decode.el (mm-alternative-precedence): Ditto.
+
+1998-09-14 15:12:49  Conrad Sauerwald  <conrad@stack.nl>
+
+       * mm-decode.el (mm-user-automatic-display): Use enriched.
+
+1998-09-14 15:09:12  Paul Fisher  <rao@gnu.org>
+
+       * mm-decode.el (mm-dissect-multipart): Have the part start on the
+       right place.
+
+1998-09-14 14:33:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-inews-add-send-actions): Mark silently.
+
+       * gnus-art.el (article-update-date-lapsed): Only update header if
+       buffer is dispalyed in frame.
+       (gnus-article-prepare-display): New function.
+       (gnus-article-prepare): Use it.
+
+1998-09-14 08:16:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-inline-part): New command and keystroke.
+
+       * mm-view.el (mm-insert-inline): New function.
+
+       * mm-decode.el (mm-pipe-part): Bugged.
+
+       * gnus-agent.el (gnus-agent-send-mail): Don't encode.
+
+       * mm-bodies.el (mm-encode-body): Move over the body.
+
+       * nnmbox.el (nnmbox-read-mbox): Enable multibyte.
+
+       * rfc2047.el (rfc2047-q-encode-region): Would bug out.
+
+1998-09-13  Francois Pinard  <pinard@iro.umontreal.ca>
+
+       * nndoc.el: Make nndoc-dissection-alist simpler for MIME, adjust all
+          related functions.  Handle message/rfc822 parts.  Display subject on
+          multipart summary lines.  Display name on sub-parts when available.
+
+1998-09-14 07:36:38  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * mailcap.el (mailcap-command-p): New version.
+
+1998-09-13  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-expire): Stop expiry barfing on killed
+       groups.
+
+1998-09-13 18:34:06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-make-date): Remove weekday name.
+
+       * mm-decode.el (mm-dissect-buffer): Protect against broken
+       headers.
+
+       * mailcap.el (mailcap-command-in-path-p): New function.
+       (mailcap-command-p): Renamed.
+
+1998-09-13 17:58:47  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * rfc2047.el (eval): Autoload.
+
+1998-09-13 12:22:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-decode-encoded-word-functions): New variable.
+       (gnus-multi-decode-encoded-word-string): New function.
+       (gnus-encoded-word-method-alist): New variable.
+       (gnus-decode-encoded-word-functions): Removed.
+
+1998-09-13  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-int.el (gnus-request-replace-article): Replace
+       message-narrow-to-headers with message-narrow-to-head
+
+1998-09-13 12:05:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * drums.el (drums-quote-string): Reversed match.
+
+       * message.el (message-make-date): Use weekday name.
+
+Sun Sep 11 10:27:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.30 is released.
+
+1998-09-13 08:00:41  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-decode-encoded-words): Use it.
+       (gnus-decode-header-function): New variable.
+
+       * gnus-sum.el (gnus-nov-parse-line): Use it.
+       (gnus-decode-encoded-word-function): New variable.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Decode the right
+       buffer.
+
+       * gnus-art.el (gnus-insert-mime-button): Use widget.
+       (gnus-widget-press-button): New function.
+       (gnus-article-prev-button): Removed.
+       (gnus-article-next-button): Ditto.
+       (gnus-article-add-button): Ditto.
+
+       * gnus.el (gnus-article-mode-map): Inherit from widget.
+       (gnus-article-mode-map): No, don't.
+
+       * mm-decode.el (mm-dissect-buffer): Store Content-ID things.
+       (mm-content-id-alist): New variable.
+       (mm-get-content-id): New function.
+
+       * gnus-art.el (gnus-request-article-this-buffer): Only decode
+       articles if we are fetching to the article buffer.
+
+1998-09-13 07:58:59  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus-sum.el (gnus-summary-move-article): Don't decode accepting
+       articles.
+
+1998-09-13 07:23:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-mime-charset): Try to use safe-charsets.
+       (mm-default-mime-charset): New variable.
+
+       * rfc2047.el (rfc2047-dissect-region): Dissect using tspecials.
+
+       * drums.el (drums-quote-string): Reversed test.
+
+1998-09-12 14:29:21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-insert-rfc822-headers): Possibly not quote
+       string.
+
+       * drums.el (drums-quote-string): New function.
+
+       * rfc2047.el (rfc2047-encode-message-header): Goto point-min.
+       (rfc2047-b-encode-region): Chop lines.
+       (rfc2047-q-encode-region): Ditto.
+
+Sat Sep 12 13:27:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.29 is released.
+
+1998-09-12 12:46:30  Istvan Marko  <imarko@pacificnet.net>
+
+       * mm-decode.el (mm-save-part): Message right.
+
+1998-09-12 11:30:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * drums.el (drums-parse-address): Returned a list instead of a
+       string.
+       (drums-remove-whitespace): Skip comments.
+       (drums-parse-addresses): Didn't work.
+
+Sat Sep 12 09:17:30 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.28 is released.
+
+1998-09-12 04:57:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-mime-button-map): Use the article keymap as a
+       starting point.
+       (article-decode-encoded-words): Rename.
+
+       * message.el (message-narrow-to-headers-or-head): New function.
+
+       * gnus-int.el (gnus-request-accept-article): Narrow to the right
+       region.
+
+       * message.el (message-send-news): Encode body after checking
+       syntax.
+
+       * gnus-art.el (gnus-mime-button-line-format): Allow descriptions.
+
+       * mm-decode.el (mm-save-part): Use Content-Disposition filename.
+
+       * gnus-art.el (gnus-display-mime): Respect disposition.
+
+       * mm-decode.el (mm-preferred-alternative): Respect disposition.
+
+       * gnus-art.el (article-strip-multiple-blank-lines): Don't delete
+       text with annotations.
+
+       * message.el (message-make-date): Fix sign for negative time
+       zones.
+
+       * mm-view.el (mm-inline-image): Insert a space at the end of the
+       image.
+
+       * mail-parse.el: New file.
+
+       * rfc2231.el: New file.
+
+       * drums.el (drums-content-type-get): Removed.
+       (drums-parse-content-type): Ditto.
+
+       * mailcap.el (mailcap-mime-data): Use symbols instead of strings.
+
+Fri Sep 11 18:23:34 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.27 is released.
+
+1998-09-11 12:42:07  Lars Magne Ingebrigtsen- <larsi@gnus.org>
+
+       * mm-decode.el (mm-alternative-precedence): New variable.
+       (mm-preferred-alternative): New function.
+
+       * gnus-art.el (gnus-mime-copy-part): New command.
+
+       * mm-decode.el (mm-get-part): New function.
+
+       * mm-view.el: New file.
+
+       * mm-decode.el (mm-dissect-buffer): Downcase cte.
+       (mm-display-part): Default to mailcap-save-binary-file.
+
+Fri Sep 11 12:32:50 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.26 is released.
+
+1998-09-11 08:25:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el (mm-interactively-view-part): New function.
+
+       * gnus-art.el (gnus-mime-view-part): New command.
+
+       * mm-decode.el (mm-last-shell-command): New variable.
+
+       * mailcap.el (mailcap-mime-info): Allow returning all matches.
+
+       * mm-decode.el (mm-save-part): New function.
+
+       * gnus-art.el (article-decode-charset): Protect against buggy
+       content-types.
+       (gnus-mime-pipe-part): New command.
+       (gnus-mime-save-part): New command.
+       (gnus-mime-button-map): New keymap.
+       (gnus-mime-button-line-format): New variable.
+       (gnus-insert-mime-button): New function.
+       (gnus-display-mime): Use it.
+
+       * gnus-util.el (gnus-dd-mmm): Removed length spec.
+
+       * mm-decode.el (mm-inline-text): Decode charsets.
+
+       * gnus-art.el (gnus-article-save): Comment fix.
+
+       * gnus-int.el (gnus-start-news-server): When in batch, don't
+       prompt.
+
+       * gnus-cache.el (gnus-cache-possibly-enter-article): Don't
+       decode.
+
+       * mm-decode.el (mm-inline-media-tests): Add audio.
+       (mm-inline-audio): New function.
+
+1998-09-11 08:19:22  Katsumi Yamaoka  <yamaoka@ga.sony.co.jp>
+
+       * gnus-art.el (article-make-date-line): Didn't work.
+
+       * parse-time.el (parse-time-string): One too many nils.
+
+Fri Sep 11 08:09:40 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.25 is released.
+
+1998-09-11 07:38:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-remove-trailing-blank-lines): Don't remove
+       annotations.
+
+       * gnus.el ((featurep 'gnus-xmas)): New
+       'gnus-annotation-in-region-p alias.
+
+1998-09-10 06:20:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-with-unibyte-buffer): New function.
+
+       * gnus-uu.el (gnus-quote-arg-for-sh-or-csh): Renamed.
+
+       * mm-decode.el (mm-inline-media-tests): New variable.
+
+       * gnus-sum.el (gnus-summary-exit): Destroy handles.
+
+       * gnus-art.el (gnus-article-mime-handles): New variable.
+
+       * drums.el (drums-narrow-to-header): New function.
+
+       * gnus-art.el (article-decode-charset): Use it.
+
+       * drums.el (drums-content-type-get): New function.
+
+       * mm-util.el (mm-content-type-charset): Removed.
+
+       * drums.el (drums-syntax-table): @ is word.
+       (drums-parse-content-type): New function.
+
+       * parse-time.el (parse-time-rules): Parse "Wed, 29 Apr 98 0:26:01
+       EDT" times.
+
+       * gnus-util.el (gnus-date-get-time): Use safe date.
+
+       * gnus-sum.el (gnus-show-mime): Removed.
+       (gnus-summary-toggle-mime): Removed.
+
+       * gnus-art.el (gnus-strict-mime): Removed.
+       (gnus-article-prepare): Don't do MIME.
+       (gnus-decode-encoded-word-method): Removed.
+       (gnus-show-mime-method): Removed.
+
+Thu Sep 10 04:03:29 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.24 is released.
+
+1998-09-10 01:58:24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-sum.el (gnus-summary-show-article): Don't decode chars if
+       PREFIX.
+
+       * parse-time.el (parse-time-rules): Accept times that look like
+       "h:mm".
+
+       * message.el (message-make-date): Use zone properly.
+
+       * gnus.el: Autoload gnus-batch.
+
+       * gnus-art.el (article-de-quoted-unreadable): Do not do
+       gnus-article-decode-rfc1522.
+
+       * gnus-msg.el (gnus-inews-do-gcc): Use it.
+
+       * gnus-int.el (gnus-request-accept-article): Accept a no-encode
+       param.
+
+       * message.el (message-encode-message-body): Check for us-ascii.
+
+       * gnus-msg.el (gnus-extended-version): Move Gnus version comments
+       to the left.
+
+1998-09-09 13:18:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (article-decode-charset): Rename.
+
+Wed Sep  9 12:25:48 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.23 is released.
+
+1998-09-09 12:14:47  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-parent-id): Ditto.
+       (gnus-put-text-property-excluding-newlines): Ditto.
+
+       * gnus-sum.el (gnus-dependencies-add-header): Make into subst.
+
+1998-09-08  Karl Kleinpaste  <karl@jprc.com>
+
+       * message.el (message-generate-headers): Generate User-Agent
+       instead of X-Mailer & X-Newsreader.
+
+       * gnus-msg.el (gnus-extended-version): Reformat for USEFOR
+       User-Agent header format.
+
+Tue Sep  8 22:38:27 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.22 is released.
+
+1998-09-08 22:36:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-multibyte-p): Typo.
+
+Tue Sep  8 22:25:53 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.21 is released.
+
+1998-09-08  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus-art.el (article-treat-dumbquotes): Handle \224 correctly.
+
+1998-09-08 22:18:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el (mm-multibyte-p): New function.
+
+Tue Sep  8 21:43:03 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.20 is released.
+
+1998-09-08 11:40:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-decode-region): Only decode when in
+       multibyte.
+
+       * nnheader.el (nnheader-pathname-coding-system): Changed to binary.
+
+       * gnus-int.el (gnus-request-replace-article): Encode.
+       (gnus-request-accept-article): Encode.
+
+       * gnus-art.el (gnus-request-article-this-buffer): Decode charsets
+       here.
+
+       * gnus.el (gnus-article-display-hook): Take the charset functions
+       out.
+
+       * time-date.el (safe-date-to-time): New function.
+
+       * gnus-util.el (gnus-dd-mmm): Protect against bogus dates.
+
+Tue Sep  8 07:09:28 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.19 is released.
+
+1998-09-08 04:51:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * base64.el (base64-encode-region): Accept no-line-break.
+
+       * mm-util.el (mm-mime-charset): New function.
+
+       * gnus-draft.el (gnus-draft-edit-message): Delete article.
+
+Tue Sep  8 04:29:23 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.18 is released.
+
+1998-09-08 02:21:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-and-exit): Return t on success.
+       (message-make-date): Make a proper time zone.
+
+       * gnus-draft.el (gnus-draft-send): Only remove article if the
+       sending is successful.
+
+       * drums.el (drums-get-comment): Return the last comment.
+       (drums-parse-address): Parse old-style From headers.
+
+1998-09-07  SL Baur  <steve@altair.xemacs.org>
+
+       * gnus-sum.el (gnus-data-compute-positions): Move below
+       `gnus-save-hidden-threads' so the former is correctly detected as
+       a macro.
+
+1998-09-06  Dave Love  <fx@gnu.org>
+
+       * gnus/nnweb.el (require): Wrap requirement of w3 and url in
+       ignore-errors too, eval'd when compile.  Require w3 stuff at load
+       time for nicer failure if it's not available.
+
+1998-09-08 00:38:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * time-date.el (time-to-seconds): Renamed.
+
+       * parse-time.el (parse-time-string): Downcase before handling.
+       (parse-time-rules): Times without seconds have 0 seconds.
+
+       * rfc2047.el (rfc2047-encode-region): New version.
+       (rfc2047-dissect-region): New function.
+
+1998-09-07 01:08:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-make-date): Use symbolic zone.
+
+1998-09-06 23:23:06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * time-date.el (parse-time): Always use parse-time.
+
+       * parse-time.el (parse-time-syntax): Use vectors.
+
+Sun Sep  6 21:19:26 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.17 is released.
+
+1998-09-06 05:45:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * time-date.el: Renamed from "date".
+
+       * gnus.el: Removed all timezone dependencies.
+
+       * score-mode.el: Removed.
+       (gnus-score-edit-insert-date): Use date.
+
+       * date.el (float-to-time): New function.
+
+       * nnspool.el (nnspool-seconds-since-epoch): Removed.
+
+       * date.el (time-to-float): New function.
+
+       * message.el (message-make-date): Use format-time-string.
+       (message-make-expires): Use make-date.
+
+       * gnus-xmas.el (gnus-xmas-seconds-since-epoch): Removed.
+
+       * gnus-util.el (gnus-dd-mmm): Use date.
+       (gnus-sortable-date): Ditto.
+
+       * message.el (message-make-date): Take an optional time.
+
+       * gnus: Applied patches from 5.6.43.
+
+       * date.el (if): Use parse-time.
+
+       * gnus-score.el (gnus-summary-score-entry): Make into a command
+       again.
+
+       * gnus-group.el (gnus-group-get-new-news-this-group): Only call if
+       gnus-agent.
+
+       * gnus.el (gnus-agent-meta-information-header): Moved here.
+
+1998-09-05  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-scoreable-headers): New variable.
+       (gnus-agent-fetch-group-1): Score article headers using normal
+       group score files if the download score rule of a category/group
+       is `file'.
+       (gnus-agent-fetch-group-1): Don't parse the entire .overview when
+       deciding what articles to download.
+       (gnus-agent-fetch-group-1): Don't push headers through scoring and
+       predicate processing if predicate is `true' or `false'.
+
+1998-09-06 01:56:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-score.el (gnus-score-load-score-alist): Bind coding system.
+
+       * gnus-art.el (gnus-article-setup-buffer): Enable multibyte.
+
+       * score-mode.el (score-mode-coding-system): New variable.
+       (gnus-score-edit-exit): Use it.
+
+1998-09-04  Jason R Mastaler  <jason@4b.org>
+
+       * drums.el: Corrected typo.
+
+1998-09-05 23:24:43  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * mm-bodies.el (mm-body-encoding): Faster version.
+
+1998-09-05 22:23:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-decode-charset): Only decode text
+       things.
+
+       * message.el (message-output): Use rmail.
+
+       * rfc2047.el (rfc2047-encoded-word-regexp): Allow spaces in the
+       word part.
+
+       * mm-util.el (mm-charset-to-coding-system): Use
+       rfc2047-default-charset.
+       (mm-known-charsets): New variable.
+
+       * message.el (message-caesar-region): Bugged out.
+
+1998-09-06  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus-agent.el (gnus-agent-fetch-group-1): Allow lists when
+       specifying `agent-predicate' in a group's parameters.
+
+Sat Sep  5 21:55:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.16 is released.
+
+1998-09-05 17:30:11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnmail.el (nnmail-expired-article-p): Use predicate.
+
+       * date.el (time-less-p): Renamed.
+
+       * gnus-art.el (gnus-article-decode-charset): Really fetch headers
+       from the headers.
+
+       * rfc2047.el (rfc2047-decode-region): Use the mm decoding
+       functions.
+
+       * gnus-group.el (gnus-group-sort-selected-flat): Didn't work at
+       all.
+       (gnus-group-sort-selected-groups-by-alphabet): Changed interface
+       to all functions.
+
+Sat Sep  5 01:45:52 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.15 is released.
+
+1998-09-05 00:21:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * date.el: New file.
+
+       * gnus-util.el (gnus-encode-date): Removed.
+       (gnus-time-less): Ditto.
+
+       * nnmail.el (nnmail-date-to-time): Removed.
+       (nnmail-time-less): Ditto.
+       (nnmail-days-to-time): Ditto.
+       (nnmail-time-since): Ditto.
+
+       * drums.el: New file.
+
+1998-09-04 00:25:52  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Encode headers with
+       body encoding.
+
+       * rfc2047.el (rfc2047-default-charset): Renamed.
+       (rfc2047-encodable-p): Use it.
+
+       * base64.el (mm-util): Required.
+
+1998-09-03 16:28:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-post-method): Peel off real info from opened
+       servers.
+
+       * gnus-util.el (gnus-output-to-rmail): Removed.
+
+       * gnus-art.el (gnus-summary-save-in-rmail): Use
+       gnus-output-to-rmailrmail-output-to-rmail-file.
+
+       * rfc2047.el (rfc2047-decode-region): Fold case.
+       (rfc2047-decode): Use decode-string.
+
+       * mm-util.el: Provide mm-char-int.
+
+Thu Sep  3 15:23:22 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.14 is released.
+
+1998-09-03 15:08:30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-body-encoding): Go through the buffer to make
+       sure we have 7bit.
+
+1998-09-02 14:38:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-msg.el (gnus-post-method): Use opened servers, and remove
+       ducplicates.
+       (gnus-inews-insert-mime-headers): Removed.
+
+       * message.el (message-caesar-region): Protect against MULE chars.
+
+1998-09-02 00:36:23  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+
+       * mm-util.el (if): fset the right function.
+
+1998-09-02 00:31:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-decode-charset): Use real
+       read-coding-system.
+
+1998-09-01 17:58:40  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-decode-body): Protect against malformed
+       base64.
+       (mm-decode-body): Check that buffer-file-coding-system is
+       non-nil.
+
+Tue Sep  1 10:29:33 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.13 is released.
+
+1998-09-01 09:14:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-util.el (gnus-strip-whitespace): Already defined.
+       Removed.
+
+       * gnus-art.el (gnus-article-decode-charset): Strip whitespace.
+
+       * gnus-util.el (gnus-strip-whitespace): New function.
+
+       * mm-util.el (mm-content-type-charset): Downcase.
+
+1998-08-31 23:04:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-decode-charset): Accept a prefix.
+       (gnus-article-decode-charset): Don't fetch all headers.
+
+       * mm-util.el (mm-read-coding-system): New function.
+
+       * mm-bodies.el (mm-decode-body): Check the right charset.
+
+       * gnus-sum.el (gnus-summary-mode-line-format): Ditto.
+
+       * gnus-art.el (gnus-article-mode-line-format): Use short group
+       format.
+
+Mon Aug 31 23:03:13 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.12 is released.
+
+1998-08-31 22:39:36  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-bodies.el (mm-decode-body): Don't do charset unless MULE.
+
+       * gnus-art.el (gnus-article-decode-charset): Supply cte.
+       (gnus-article-decode-charset): Always run.
+
+       * mm-bodies.el (mm-decode-body): Decode cte.
+
+Mon Aug 31 22:14:50 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.11 is released.
+
+1998-08-31 14:27:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-encode-message-body): Ditto.
+
+       * gnus-art.el (gnus-article-decode-mime-words): New command and
+       keystroke.
+       (gnus-article-decode-charset): Ditto.
+       (gnus-article-decode-charset): Only work under MULE.
+
+       * mm-util.el (mm-content-type-charset): New function.
+
+       * nnmail.el (nnmail-delete-incoming): Changed to nil.
+
+       * message.el (message-send-mail): Insert MIME headers.
+       (message-check-news-body-syntax): Don't warn for escape sequences.
+       (message-check-news-body-syntax): Insert MIME headers.
+
+       * mm-bodies.el (mm-body-encoding): New function.
+
+       * message.el (message-encode-message-body): New function.
+
+       * mm-bodies.el: New file.
+
+       * mm-util.el (mm-narrow-to-head): New function.
+
+       * rfc2047.el (rfc2047-encode): Use it.
+
+       * mm-util.el: Provide mm-encode-coding-region.
+
+       * gnus-sum.el (gnus-summary-mode): Enable multibyte.
+
+       * gnus-util.el (gnus-set-work-buffer): Enable multibyte.
+
+       * mm-util.el (mm-enable-multibyte): New function.
+
+       * message.el (message-set-work-buffer): Set multibyte.
+
+       * gnus.el (gnus-continuum-version): Be valid forever and ever.
+
+       * gnus-util.el (gnus-point-at-eol): Removed.
+       (gnus-point-at-bol): Ditto.
+
+       * base64.el (base64-decode-region): Commented out messaging.
+
+1998-08-31  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus-msg.el (gnus-group-mail): make it behave like
+       gnus-group-post-news with regards to the prefix (this enables the
+       use of posting styles).
+
+1998-08-31 12:53:32  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el (gnus-article-display-hook): Added
+       gnus-article-decode-rfc1522 to hook.
+
+Mon Aug 31 12:43:46 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.10 is released.
+
+1998-08-31 11:45:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnfolder.el (nnfolder-delete-mail): Narrow to mail and allow
+       hook to be run.
+
+1998-08-30 17:59:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * rfc2047.el (rfc2047-encodable-p): Use find-charset-region.
+
+       * mm-util.el (mm-charsets-in-region): Removed.
+
+       * rfc2047.el: Renamed file.
+
+       * gnus-msg.el (gnus-copy-article-buffer): Multibyte.
+
+       * message.el (message-mode): Set multibyte.
+
+       * mm-util.el (mm-charsets-in-region): Copied here.
+
+       * gnus-util.el: Removed gnus-truncate-string.
+
+       * gnus-art.el (gnus-article-decode-mime-words): Use 1522.
+
+       * rfc1522.el (rfc1522-unencoded-charsets): New variable.
+       (rfc1522-encodable-p): New function.
+       (rfc1522-encode-message-header): Use it.
+
+Sun Aug 30 17:46:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.9 is released.
+
+1998-08-30 16:13:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-util.el: Shadow encode-coding-string.
+
+       * base64.el (base64-encode-region): Don't add newline.
+
+       * rfc1522.el (rfc1522-narrow-to-field): Copied here.
+
+       * mm-util.el: New file.
+
+       * mm-decode.el: Somewhat depleted.
+       * mm-encode.el: Ditto.
+
+       * rfc1522.el: New file.
+
+       * mm-util.el (mm-replace-chars-in-string): Copied here.
+
+       * mm-encode.el (mm-q-encode-region): New function.
+
+       * qp.el (quoted-printable-encode-region): Take an optional CLASS
+       param.
+
+       * mm-encode.el (mm-encode-word-region): Downcase.
+
+Sun Aug 30 15:28:01 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.8 is released.
+
+1998-08-30 12:23:03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.el (message-send-mail): Encode headers.
+
+       * qp.el (quoted-printable-encode-region): Encode 8-bit words.
+       (quoted-printable-encode-region): Upcase.
+
+       * message.el (message-default-charset): New variable.
+
+       * qp.el (quoted-printable-encode-region): Optional param FOLD.
+
+       * message.el (message-narrow-to-field): Changed name.
+
+       * mm-encode.el: New file.
+
+       * message.el (message-narrow-to-header): New function.
+
+       * gnus-art.el (gnus-article-decode-mime-words): Place point in the
+       right buffer.
+
+Sun Aug 30 12:15:54 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.7 is released.
+
+1998-08-30 01:26:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.el: Remove autoload for
+       gnus-article-mime-decode-quoted-printable.
+
+       * mm-decode.el (mm-charset-to-coding-system): Allow iso-8859-1 to
+       be decoded in non-MULE Emacsen.
+
+       * gnus-xmas.el (gnus-xmas-logo-color-alist): More brown.
+
+1998-08-29  SL Baur  <steve@altair.xemacs.org>
+
+       * gnus-xmas.el (gnus-xmas-logo-color-alist): Try shades of brown.
+
+1998-08-30 01:04:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * mm-decode.el: Check for coding-system-list.
+
+Sun Aug 30 00:59:15 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.6 is released.
+
+1998-08-30 00:36:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * nnheader.el (fboundp): Protect code-coding-string.
+
+       * gnus-art.el (gnus-article-mode): Check that set-buffer-multibyte
+       is available.
+
+Sat Aug 29 23:24:31 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Pterodactyl Gnus v0.5 is released.
+
+1998-08-29 22:38:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-mode): Make article buffer multibyte.
+       (gnus-hack-decode-rfc1522): Removed.
+
+       * mm-decode.el (mm-charset-coding-system-alist): Check better.
+
+Sat Aug 29 22:20:39 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Gnus v0.4 is released.
+
+1998-08-29 20:53:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus-art.el (gnus-article-decode-mime-words): New command and
+       keystroke.
+
+       * qp.el (quoted-printable-decode-region): Don't use hexl.
+
+       * gnus-xmas.el (gnus-xmas-logo-color-style): Changed to dino.
+
+       * gnus-sum.el (gnus-parse-headers-hook): Default to nil.
+       (gnus-structured-field-decoder): Removed.
+       (gnus-unstructured-field-decoder): Ditto.
+
+       * mm-decode.el: New file.
+
+       * qp.el: New file.
+
+       * gnus-art.el (article-mime-decode-quoted-printable): Removed.
+
+       * gnus-ems.el (fboundp): Removed gnus-split-string.
+
+       * gnus.el (gnus-splash-face): Doc fix.
+
+       * gnus-ems.el (fboundp): Don't bind mail-file-babyl-p.
+
+       * gnus-art.el (article-mime-decode-quoted-printable): Don't use
+       hexl.
+
+       * nnheader.el (nnheader-temp-write): Removed.
+
+Sat Aug 29 20:34:17 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Gnus v0.3 is released.
+
+Sat Aug 29 19:32:06 1998  Lars Magne Ingebrigtsen  <larsi@menja.ifi.uio.no>
+
+       * gnus.el: Gnus v0.2 is released.
+
+    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+  Copying and distribution of this file, with or without modification,
+  are permitted provided the copyright notice and this notice are preserved.
+       
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/lisp/Makefile b/lisp/Makefile
deleted file mode 100644 (file)
index b949400..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-SHELL = /bin/sh
-EMACS=emacs
-FLAGS=-batch -q -no-site-file -l ./dgnushack.el
-
-total:
-       rm -f *.elc ; $(EMACS) $(FLAGS) -f dgnushack-compile
-
-all:
-       rm -f *.elc ; $(EMACS) $(FLAGS) -f dgnushack-compile
-
-clever:
-       $(EMACS) $(FLAGS) -f dgnushack-compile
-
-some:
-       $(EMACS) $(FLAGS) -f dgnushack-compile
-
-tags:
-       etags *.el
-
-separately:
-       rm -f *.elc ; for i in *.el; do $(EMACS) $(FLAGS) -f batch-byte-compile $$i; done
-
-pot:
-       xpot -drgnus -r`cat ./version` *.el > rgnus.pot
-
-gnus-load.el: 
-       echo ";;; gnus-load.el --- automatically extracted custom dependencies" > gnus-load.el
-       echo ";;" >> gnus-load.el
-       echo ";;; Code:" >> gnus-load.el
-       echo >> gnus-load.el
-       $(EMACS)  $(FLAGS) -l ./dgnushack.el -l cus-edit.el *.el \
-               -f custom-make-dependencies >> gnus-load.el
-       echo >> gnus-load.el
-       echo "(provide 'gnus-load)" >> gnus-load.el
-       echo >> gnus-load.el
-       echo ";;; gnus-load.el ends here" >> gnus-load.el
-
-distclean:
-       rm -f *.orig *.rej *.elc *~
-
index 6045356..cd5408e 100644 (file)
@@ -5,28 +5,83 @@ srcdir = @srcdir@
 subdir = lisp
 top_srcdir = @top_srcdir@
 
-EMACS = emacs
-FLAGS = -batch -q -no-site-file -l ./dgnushack.el
+EMACS = @EMACS@
+FLAGS = @FLAGS@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 SHELL = /bin/sh
 VPATH = @srcdir@
+PACKAGEDIR = @PACKAGEDIR@
+W3DIR = @W3@
+URLDIR = @URL@
+EMACS_COMP = URLDIR=$(URLDIR) W3DIR=$(W3DIR) lispdir=$(lispdir) srcdir=$(srcdir) $(EMACS) $(FLAGS)
+GNUS_PRODUCT_NAME = @GNUS_PRODUCT_NAME@
+EXPORTING_FILES = $(EMACS_COMP) -f dgnushack-exporting-files 2>/dev/null
 
-total:
-       rm -f *.elc ; $(EMACS) $(FLAGS) -f dgnushack-compile
+# We should never use `COMMAND && ...' form, use `if COMMAND then ...'
+# form instead.  Because, as far as we know, FreeBSD's native make will
+# be discontinued if COMMAND returns a non-zero exit status.
 
-all:
-       rm -f *.elc ; $(EMACS) $(FLAGS) -f dgnushack-compile
+all total: clean-some gnus-load.el
+       $(EMACS_COMP) -f dgnushack-compile
 
-clever:
-       $(EMACS) $(FLAGS) -f dgnushack-compile
+clean-some:
+       rm -f *.elc gnus-load.el auto-autoloads.* custom-load.*
 
-some:
-       $(EMACS) $(FLAGS) -f dgnushack-compile
+warn: clean-some gnus-load.el
+       $(EMACS_COMP) --eval '(dgnushack-compile t)' 2>&1 | egrep -v "variable G|inhibit-point-motion-hooks|coding-system|temp-results|variable gnus|variable nn|scroll-in-place|deactivate-mark|filladapt-mode|byte-code-function-p|print-quoted|ps-right-header|ps-left-header|article-inhibit|print-escape|ssl-program-arguments|message-log-max"
 
-install: clever
+# The "clever" rule is unsafe, since redefined macros are loaded from
+# .elc files, and not the .el file.
+clever some l: gnus-load.el
+       @if test -f $(srcdir)/gnus.elc; then \
+         echo \
+           "checking whether the all elc files should be recompiled..."; \
+         RM_ELC=nil; \
+         if test `$(EMACS) -batch -q -no-site-file \
+               -eval '(prin1 (featurep (quote xemacs)))' \
+               2>/dev/null` = t; then \
+           if test ! -f $(srcdir)/gnus-xmas.elc; then RM_ELC=t; fi; \
+         else \
+           if test -f $(srcdir)/gnus-xmas.elc; then RM_ELC=t; fi; \
+         fi; \
+         if test $$RM_ELC = t; then \
+           echo " => maybe yes;" \
+               "rm -f *.elc auto-autoloads.el custom-load.el"; \
+           rm -f *.elc auto-autoloads.el custom-load.el; \
+         else \
+           echo " => maybe unnecessary"; \
+         fi; \
+       fi
+       $(EMACS_COMP) -f dgnushack-compile
+
+install: clever install-without-compiling
+
+install-without-compiling:
        $(SHELL) $(top_srcdir)/mkinstalldirs $(lispdir)
-       for p in *.elc; do \
+       @for p in `$(EXPORTING_FILES)`; do \
+         echo " $(INSTALL_DATA) $$p $(lispdir)/$$p"; \
+         $(INSTALL_DATA) $$p $(lispdir)/$$p; \
+         if test -f $$p"c"; then \
+           echo " $(INSTALL_DATA) $$p""c"" $(lispdir)/$$p""c"; \
+           $(INSTALL_DATA) $$p"c" $(lispdir)/$$p"c"; \
+         fi; \
+       done
+
+# Rule for XEmacs package.
+install-package-manifest:
+       $(EMACS_COMP) -f dgnushack-install-package-manifest \
+               $(PACKAGEDIR) $(GNUS_PRODUCT_NAME)
+
+remove-extra-files-in-package:
+       $(EMACS_COMP) -f dgnushack-remove-extra-files-in-package \
+               $(PACKAGEDIR) $(GNUS_PRODUCT_NAME)
+#
+
+install-el:
+       $(SHELL) $(top_srcdir)/mkinstalldirs $(lispdir)
+       cd $(srcdir) \
+       && for p in *.el; do \
          echo " $(INSTALL_DATA) $$p $(lispdir)/$$p"; \
          $(INSTALL_DATA) $$p $(lispdir)/$$p; \
        done
@@ -41,19 +96,16 @@ pot:
        xpot -drgnus -r`cat ./version` *.el > rgnus.pot
 
 gnus-load.el:
-       echo ";;; gnus-load.el --- automatically extracted custom dependencies" > gnus-load.el
-       echo ";;" >> gnus-load.el
-       echo ";;; Code:" >> gnus-load.el
-       echo >> gnus-load.el
-       $(EMACS)  $(FLAGS) -l ./dgnushack.el -l cus-edit.el *.el \
-               -f custom-make-dependencies >> gnus-load.el
-       echo >> gnus-load.el
-       echo "(provide 'gnus-load)" >> gnus-load.el
-       echo >> gnus-load.el
-       echo ";;; gnus-load.el ends here" >> gnus-load.el
-
-distclean:
-       rm -f *.orig *.rej *.elc *~ Makefile
+       $(EMACS_COMP) -f dgnushack-make-cus-load $(srcdir)
+       $(EMACS_COMP) -f dgnushack-make-auto-load $(srcdir)
+       $(EMACS_COMP) -f dgnushack-make-load
+
+clean:
+       rm -f *.orig *.rej *.elc *~ \
+               auto-autoloads.el custom-load.el gnus-load.el dgnuskwds.el
+
+distclean: clean
+       rm -f Makefile dgnuspath.el
 
 Makefile: $(srcdir)/Makefile.in ../config.status
        cd .. \
diff --git a/lisp/base64.el b/lisp/base64.el
new file mode 100644 (file)
index 0000000..26415a2
--- /dev/null
@@ -0,0 +1,54 @@
+;;; base64.el --- Base64 encoding functions using MEL
+;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+;; Author: T-gnus development team
+;; Keywords: extensions
+
+;; This file is part of T-gnus.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-and-compile
+  (defun base64-autoload-functionp (object)
+    (if (functionp object)
+       (let ((def object))
+         (while (and (symbolp def) (fboundp def))
+           (setq def (symbol-function def)))
+         (eq (car-safe def) 'autoload))))
+
+  (if (base64-autoload-functionp 'base64-decode-string)
+      (fmakunbound 'base64-decode-string))
+  (if (base64-autoload-functionp 'base64-decode-region)
+      (fmakunbound 'base64-decode-region))
+  (if (base64-autoload-functionp 'base64-encode-string)
+      (fmakunbound 'base64-encode-string))
+  (if (base64-autoload-functionp 'base64-encode-region)
+      (fmakunbound 'base64-encode-region))
+
+  (require 'mel)
+
+  (mel-find-function 'mime-decode-string "base64")
+  (mel-find-function 'mime-decode-region "base64")
+  (mel-find-function 'mime-encode-string "base64")
+  (mel-find-function 'mime-encode-region "base64"))
+
+(provide 'base64)
+
+;;; base64.el ends here
diff --git a/lisp/binhex.el b/lisp/binhex.el
new file mode 100644 (file)
index 0000000..7622881
--- /dev/null
@@ -0,0 +1,327 @@
+;;; binhex.el --- elisp native binhex decode
+;; Copyright (c) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: binhex news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'path-util)
+
+(eval-and-compile
+  (defalias 'binhex-char-int
+    (if (fboundp 'char-int)
+       'char-int
+      'identity)))
+
+(defcustom binhex-decoder-program "hexbin"
+  "*Non-nil value should be a string that names a binhex decoder.
+The program should expect to read binhex data on its standard
+input and write the converted data to its standard output."
+  :type 'string
+  :group 'gnus-extract)
+
+(defcustom binhex-decoder-switches '("-d")
+  "*List of command line flags passed to the command `binhex-decoder-program'."
+  :group 'gnus-extract
+  :type '(repeat string))
+
+(defcustom binhex-use-external
+  (exec-installed-p binhex-decoder-program)
+  "*Use external binhex program."
+  :group 'gnus-extract
+  :type 'boolean)
+
+(defconst binhex-alphabet-decoding-alist
+  '(( ?\! . 0) ( ?\" . 1) ( ?\# . 2) ( ?\$ . 3) ( ?\% . 4) ( ?\& . 5)
+    ( ?\' . 6) ( ?\( . 7) ( ?\) . 8) ( ?\* . 9) ( ?\+ . 10) ( ?\, . 11)
+    ( ?\- . 12) ( ?0 . 13) ( ?1 . 14) ( ?2 . 15) ( ?3 . 16) ( ?4 . 17)
+    ( ?5 . 18) ( ?6 . 19) ( ?8 . 20) ( ?9 . 21) ( ?@ . 22) ( ?A . 23)
+    ( ?B . 24) ( ?C . 25) ( ?D . 26) ( ?E . 27) ( ?F . 28) ( ?G . 29)
+    ( ?H . 30) ( ?I . 31) ( ?J . 32) ( ?K . 33) ( ?L . 34) ( ?M . 35)
+    ( ?N . 36) ( ?P . 37) ( ?Q . 38) ( ?R . 39) ( ?S . 40) ( ?T . 41)
+    ( ?U . 42) ( ?V . 43) ( ?X . 44) ( ?Y . 45) ( ?Z . 46) ( ?\[ . 47)
+    ( ?\` . 48) ( ?a . 49) ( ?b . 50) ( ?c . 51) ( ?d . 52) ( ?e . 53)
+    ( ?f . 54) ( ?h . 55) ( ?i . 56) ( ?j . 57) ( ?k . 58) ( ?l . 59)
+    ( ?m . 60) ( ?p . 61) ( ?q . 62) ( ?r . 63)))
+
+(defun binhex-char-map (char)
+  (cdr (assq char binhex-alphabet-decoding-alist)))
+
+;;;###autoload
+(defconst binhex-begin-line
+  "^:...............................................................$")
+(defconst binhex-body-line
+  "^[^:]...............................................................$")
+(defconst binhex-end-line ":$")
+
+(defvar binhex-temporary-file-directory
+  (cond ((fboundp 'temp-directory) (temp-directory))
+       ((boundp 'temporary-file-directory) temporary-file-directory)
+       ("/tmp/")))
+
+(eval-and-compile
+  (defalias 'binhex-insert-char
+    (if (featurep 'xemacs)
+       'insert-char
+      (lambda (char &optional count ignored buffer)
+       "Insert COUNT copies of CHARACTER into BUFFER."
+       (if (or (null buffer) (eq buffer (current-buffer)))
+           (insert-char char count)
+         (with-current-buffer buffer
+           (insert-char char count)))))))
+
+(defvar binhex-crc-table
+  [0  4129  8258  12387  16516  20645  24774  28903
+      33032  37161  41290  45419  49548  53677  57806  61935
+      4657  528  12915  8786  21173  17044  29431  25302
+      37689  33560  45947  41818  54205  50076  62463  58334
+      9314  13379  1056  5121  25830  29895  17572  21637
+      42346  46411  34088  38153  58862  62927  50604  54669
+      13907  9842  5649  1584  30423  26358  22165  18100
+      46939  42874  38681  34616  63455  59390  55197  51132
+      18628  22757  26758  30887  2112  6241  10242  14371
+      51660  55789  59790  63919  35144  39273  43274  47403
+      23285  19156  31415  27286  6769  2640  14899  10770
+      56317  52188  64447  60318  39801  35672  47931  43802
+      27814  31879  19684  23749  11298  15363  3168  7233
+      60846  64911  52716  56781  44330  48395  36200  40265
+      32407  28342  24277  20212  15891  11826  7761  3696
+      65439  61374  57309  53244  48923  44858  40793  36728
+      37256  33193  45514  41451  53516  49453  61774  57711
+      4224  161  12482  8419  20484  16421  28742  24679
+      33721  37784  41979  46042  49981  54044  58239  62302
+      689  4752  8947  13010  16949  21012  25207  29270
+      46570  42443  38312  34185  62830  58703  54572  50445
+      13538  9411  5280  1153  29798  25671  21540  17413
+      42971  47098  34713  38840  59231  63358  50973  55100
+      9939  14066  1681  5808  26199  30326  17941  22068
+      55628  51565  63758  59695  39368  35305  47498  43435
+      22596  18533  30726  26663  6336  2273  14466  10403
+      52093  56156  60223  64286  35833  39896  43963  48026
+      19061  23124  27191  31254  2801  6864  10931  14994
+      64814  60687  56684  52557  48554  44427  40424  36297
+      31782  27655  23652  19525  15522  11395  7392  3265
+      61215  65342  53085  57212  44955  49082  36825  40952
+      28183  32310  20053  24180  11923  16050  3793  7920])
+
+(defun binhex-update-crc (crc char &optional count)
+  (if (null count) (setq count 1))
+  (while (> count 0)
+    (setq crc (logxor (logand (lsh crc 8) 65280)
+                     (aref binhex-crc-table
+                           (logxor (logand (lsh crc -8) 255)
+                                   char)))
+         count (1- count)))
+  crc)
+
+(defun binhex-verify-crc (buffer start end)
+  (with-current-buffer buffer
+    (let ((pos start) (crc 0) (last (- end 2)))
+      (while (< pos last)
+       (setq crc (binhex-update-crc crc (char-after pos))
+             pos (1+ pos)))
+      (if (= crc (binhex-string-big-endian (buffer-substring last end)))
+         nil
+       (error "CRC error")))))
+
+(defun binhex-string-big-endian (string)
+  (let ((ret 0) (i 0) (len (length string)))
+    (while (< i len)
+      (setq ret (+ (lsh ret 8) (binhex-char-int (aref string i)))
+           i (1+ i)))
+    ret))
+
+(defun binhex-string-little-endian (string)
+  (let ((ret 0) (i 0) (shift 0) (len (length string)))
+    (while (< i len)
+      (setq ret (+ ret (lsh (binhex-char-int (aref string i)) shift))
+           i (1+ i)
+           shift (+ shift 8)))
+    ret))
+
+(defun binhex-header (buffer)
+  (with-current-buffer buffer
+    (let ((pos (point-min)) len)
+      (vector
+       (prog1
+          (setq len (binhex-char-int (char-after pos)))
+        (setq pos (1+ pos)))
+       (buffer-substring pos (setq pos (+ pos len)))
+       (prog1
+          (setq len (binhex-char-int (char-after pos)))
+        (setq pos (1+ pos)))
+       (buffer-substring pos (setq pos (+ pos 4)))
+       (buffer-substring pos (setq pos (+ pos 4)))
+       (binhex-string-big-endian
+       (buffer-substring pos (setq pos (+ pos 2))))
+       (binhex-string-big-endian
+       (buffer-substring pos (setq pos (+ pos 4))))
+       (binhex-string-big-endian
+       (buffer-substring pos (setq pos (+ pos 4))))))))
+
+(defvar binhex-last-char)
+(defvar binhex-repeat)
+
+(defun binhex-push-char (char &optional count ignored buffer)
+  (cond
+   (binhex-repeat
+    (if (eq char 0)
+       (binhex-insert-char (setq binhex-last-char 144) 1
+                           ignored buffer)
+      (binhex-insert-char binhex-last-char (- char 1)
+                         ignored buffer)
+      (setq binhex-last-char nil))
+    (setq binhex-repeat nil))
+   ((= char 144)
+    (setq binhex-repeat t))
+   (t
+    (binhex-insert-char (setq binhex-last-char char) 1 ignored buffer))))
+
+;;;###autoload
+(defun binhex-decode-region-internal (start end &optional header-only)
+  "Binhex decode region between START and END without using an external program.
+If HEADER-ONLY is non-nil only decode header and return filename."
+  (interactive "r")
+  (let ((work-buffer nil)
+       (counter 0)
+       (bits 0) (tmp t)
+       (lim 0) inputpos
+       (non-data-chars " \t\n\r:")
+       file-name-length data-fork-start
+       header
+       binhex-last-char binhex-repeat)
+    (unwind-protect
+       (save-excursion
+         (goto-char start)
+         (when (re-search-forward binhex-begin-line end t)
+           (let (default-enable-multibyte-characters)
+             (setq work-buffer (generate-new-buffer " *binhex-work*")))
+           (beginning-of-line)
+           (setq bits 0 counter 0)
+           (while tmp
+             (skip-chars-forward non-data-chars end)
+             (setq inputpos (point))
+             (end-of-line)
+             (setq lim (point))
+             (while (and (< inputpos lim)
+                         (setq tmp (binhex-char-map (char-after inputpos))))
+               (setq bits (+ bits tmp)
+                     counter (1+ counter)
+                     inputpos (1+ inputpos))
+               (cond ((= counter 4)
+                      (binhex-push-char (lsh bits -16) 1 nil work-buffer)
+                      (binhex-push-char (logand (lsh bits -8) 255) 1 nil
+                                        work-buffer)
+                      (binhex-push-char (logand bits 255) 1 nil
+                                        work-buffer)
+                      (setq bits 0 counter 0))
+                     (t (setq bits (lsh bits 6)))))
+             (if (null file-name-length)
+                 (with-current-buffer work-buffer
+                   (setq file-name-length (char-after (point-min))
+                         data-fork-start (+ (point-min)
+                                            file-name-length 22))))
+             (if (and (null header)
+                      (with-current-buffer work-buffer
+                        (>= (buffer-size) data-fork-start)))
+                 (progn
+                   (binhex-verify-crc work-buffer
+                                      (point-min) data-fork-start)
+                   (setq header (binhex-header work-buffer))
+                   (if header-only (setq tmp nil counter 0))))
+             (setq tmp (and tmp (not (eq inputpos end)))))
+           (cond
+            ((= counter 3)
+             (binhex-push-char (logand (lsh bits -16) 255) 1 nil
+                               work-buffer)
+             (binhex-push-char (logand (lsh bits -8) 255) 1 nil
+                               work-buffer))
+            ((= counter 2)
+             (binhex-push-char (logand (lsh bits -10) 255) 1 nil
+                               work-buffer))))
+         (if header-only nil
+           (binhex-verify-crc work-buffer
+                              data-fork-start
+                              (+ data-fork-start (aref header 6) 2))
+           (or (markerp end) (setq end (set-marker (make-marker) end)))
+           (goto-char start)
+           (insert-buffer-substring work-buffer
+                                    data-fork-start (+ data-fork-start
+                                                       (aref header 6)))
+           (delete-region (point) end)))
+      (and work-buffer (kill-buffer work-buffer)))
+    (if header (aref header 1))))
+
+;;;###autoload
+(defun binhex-decode-region-external (start end)
+  "Binhex decode region between START and END using external decoder."
+  (interactive "r")
+  (let ((cbuf (current-buffer)) firstline work-buffer status
+       (file-name (expand-file-name
+                   (concat (binhex-decode-region-internal start end t)
+                           ".data")
+                   binhex-temporary-file-directory)))
+    (save-excursion
+      (goto-char start)
+      (when (re-search-forward binhex-begin-line nil t)
+       (let ((cdir default-directory) default-process-coding-system)
+         (unwind-protect
+             (progn
+               (set-buffer (setq work-buffer
+                                 (generate-new-buffer " *binhex-work*")))
+               (buffer-disable-undo work-buffer)
+               (insert-buffer-substring cbuf firstline end)
+               (cd binhex-temporary-file-directory)
+               (apply 'call-process-region
+                      (point-min)
+                      (point-max)
+                      binhex-decoder-program
+                      nil
+                      nil
+                      nil
+                      binhex-decoder-switches))
+           (cd cdir) (set-buffer cbuf)))
+       (if (and file-name (file-exists-p file-name))
+           (progn
+             (goto-char start)
+             (delete-region start end)
+             (let (format-alist)
+               (insert-file-contents-literally file-name)))
+         (error "Can not binhex")))
+      (and work-buffer (kill-buffer work-buffer))
+      (ignore-errors
+       (if file-name (delete-file file-name))))))
+
+;;;###autoload
+(defun binhex-decode-region (start end)
+  "Binhex decode region between START and END."
+  (interactive "r")
+  (if binhex-use-external
+      (binhex-decode-region-external start end)
+    (binhex-decode-region-internal start end)))
+
+(provide 'binhex)
+
+;;; binhex.el ends here
diff --git a/lisp/canlock-om.el b/lisp/canlock-om.el
new file mode 100644 (file)
index 0000000..831b7f5
--- /dev/null
@@ -0,0 +1,215 @@
+;;; canlock-om.el --- Mule 2 specific functions for canlock
+;; Copyright (C) 2001 Katsumi Yamaoka
+
+;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: mule, cancel-lock
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This program is used to make canlock.el work with Mule 2.3 based on
+;; Emacs 19.34.  See README.ja in the canlock distribution for details.
+
+;;; Code:
+
+(eval-and-compile
+  (cond ((and (boundp 'emacs-major-version)
+             (> emacs-major-version 19))
+        (error "\
+Error: You should never use canlock-om.el(c) for this environment"))
+       ((and (boundp 'MULE)
+             (boundp 'emacs-major-version)
+             (= emacs-major-version 19)
+             (>= emacs-minor-version 29)))
+       (t
+        (error "Error: Canlock does not support this version of Emacs"))))
+
+(eval-when-compile
+  (require 'cl))
+
+(require 'custom)
+(eval-and-compile
+  (unless (fboundp 'custom-declare-variable)
+    (error "Error: Canlock requires new custom")))
+
+(eval-when-compile
+  (unless (fboundp 'byte-compile-file-form-custom-declare-variable)
+    (defun byte-compile-file-form-custom-declare-variable (form)
+      ;; Bind defcustom'ed variables.
+      (if (memq 'free-vars byte-compile-warnings)
+         (setq byte-compile-bound-variables
+               (cons (nth 1 (nth 1 form)) byte-compile-bound-variables)))
+      (if (memq ':version (nthcdr 4 form))
+         ;; Make the variable uncustomizable.
+         `(defvar ,(nth 1 (nth 1 form)) ,(nth 1 (nth 2 form))
+            ,(substring (nth 3 form)
+                        (if (string-match "^[\t *]+" (nth 3 form))
+                            (match-end 0)
+                          0)))
+       ;; Ignore unsupported keyword(s).
+       (if (memq ':set-after (nthcdr 4 form))
+           (let ((newform (list (car form) (nth 1 form)
+                                (nth 2 form) (nth 3 form)))
+                 (args (nthcdr 4 form)))
+             (while args
+               (or (eq (car args) ':set-after)
+                   (setq newform (nconc newform (list (car args)
+                                                      (car (cdr args))))))
+               (setq args (cdr (cdr args))))
+             newform)
+         form)))
+    (put 'custom-declare-variable 'byte-hunk-handler
+        'byte-compile-file-form-custom-declare-variable))
+
+  (define-compiler-macro with-temp-buffer (&whole form &rest forms)
+    (let ((def (if (fboundp 'with-temp-buffer)
+                  (symbol-function 'with-temp-buffer))))
+      (if (and def
+              (consp def)
+              (or (eq (car def) 'macro)
+                  (and (eq (car def) 'autoload)
+                       (memq (nth 4 def) '(macro t)))))
+         form
+       ;; The function definition is imported from APEL.
+       `(let ((obuffer (current-buffer))
+              (buffer (generate-new-buffer " *temp*")))
+          (unwind-protect
+              (progn
+                (set-buffer buffer)
+                ,@forms)
+            (if (buffer-name buffer)
+                (kill-buffer buffer))
+            (if (buffer-live-p obuffer)
+                (set-buffer obuffer))))))))
+
+(autoload 'base64-encode "base64")
+
+(defcustom canlock-base64-encode-function 'base64-encode-string
+  "Function to call to base64 encode a string."
+  :type '(radio (function-item base64-encode-string)
+               (function-item base64-encode)
+               (function-item canlock-base64-encode-string-with-mmencode)
+               (function :tag "Other"))
+  :group 'canlock)
+
+(defcustom canlock-mmencode-program "mmencode"
+  "Name of mmencode program."
+  :type 'string
+  :group 'canlock)
+
+(defcustom canlock-mmencode-args-for-encoding nil
+  "Arguments passed to mmencode program for encoding."
+  :type 'sexp
+  :group 'canlock)
+
+(defun canlock-base64-encode-string-with-mmencode (string)
+  "Base64 encode a string using mmencode."
+  (with-temp-buffer
+    (setq mc-flag nil)
+    (insert string)
+    (let ((default-process-coding-system (cons *iso-2022-jp*dos *noconv*))
+         program-coding-system-alist selective-display)
+      (apply 'call-process-region (point-min) (point-max)
+            canlock-mmencode-program t t nil
+            canlock-mmencode-args-for-encoding))
+    (goto-char (point-max))
+    (skip-chars-backward "\n")
+    (buffer-substring (point-min) (point))))
+
+;; The following macros will only be used to byte-compile canlock.el.
+(eval-when-compile
+  (define-compiler-macro base64-encode-string
+    (&whole form string &optional no-line-break)
+    (if (and (string-equal (buffer-name) " *Compiler Input*")
+            (string-equal ";;; canlock.el"
+                          (buffer-substring (point-min)
+                                            (min (+ (point-min) 14)
+                                                 (point-max)))))
+       (if no-line-break
+           `(let ((string ,string))
+              (if ,no-line-break
+                  (with-temp-buffer
+                    (insert (funcall canlock-base64-encode-function string))
+                    (goto-char (point-min))
+                    (while (search-forward "\n" nil t)
+                      (delete-char -1))
+                    (buffer-string))
+                (funcall canlock-base64-encode-function string)))
+         `(funcall canlock-base64-encode-function ,string))
+      form))
+
+  (define-compiler-macro split-string (&whole form string &optional pattern)
+    (if (and (string-equal (buffer-name) " *Compiler Input*")
+            (string-equal ";;; canlock.el"
+                          (buffer-substring (point-min)
+                                            (min (+ (point-min) 14)
+                                                 (point-max)))))
+       ;; The function definition is imported from APEL.
+       (if pattern
+           `(let ((string ,string)
+                  (pattern ,pattern)
+                  (start 0)
+                  parts)
+              (while (string-match pattern string start)
+                (setq parts (cons (substring string
+                                             start (match-beginning 0))
+                                  parts)
+                      start (match-end 0)))
+              (nreverse (cons (substring string start) parts)))
+         `(let ((string ,string)
+                (start 0)
+                parts)
+            (while (string-match "[ \f\t\n\r\v]+" string start)
+              (setq parts (cons (substring string
+                                           start (match-beginning 0))
+                                parts)
+                    start (match-end 0)))
+            (nreverse (cons (substring string start) parts))))
+      form)))
+
+;; The following variables might not be bound if the old version of
+;; canlock.el(c) exists.
+(eval-when-compile
+  (defvar canlock-openssl-args)
+  (defvar canlock-openssl-program))
+
+(defun canlock-om-sha1-with-openssl (message)
+  "Make a SHA-1 digest of MESSAGE using OpenSSL."
+  (with-temp-buffer
+    (setq mc-flag nil)
+    (insert message)
+    (let ((default-process-coding-system (cons *iso-2022-jp*dos *noconv*))
+         program-coding-system-alist selective-display)
+      (apply 'call-process-region (point-min) (point-max)
+            canlock-openssl-program t t nil canlock-openssl-args))
+    (goto-char (point-min))
+    (insert "\"")
+    (while (re-search-forward "\\([0-9A-Fa-f][0-9A-Fa-f]\\)" nil t)
+      (replace-match "\\\\x\\1"))
+    (insert "\"")
+    (goto-char (point-min))
+    (read (current-buffer))))
+
+;; Override the original function.
+(eval-after-load "canlock"
+  '(defalias 'canlock-sha1-with-openssl 'canlock-om-sha1-with-openssl))
+
+(provide 'canlock-om)
+
+(require 'canlock)
+
+;;; canlock-om.el ends here
diff --git a/lisp/canlock.el b/lisp/canlock.el
new file mode 100644 (file)
index 0000000..55b2e59
--- /dev/null
@@ -0,0 +1,313 @@
+;;; canlock.el --- functions for Cancel-Lock feature
+
+;; Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: news, cancel-lock, hmac, sha1, rfc2104
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Canlock is a library for generating and verifying Cancel-Lock and/or
+;; Cancel-Key header in news articles.  This is used to protect articles
+;; from rogue cancel, supersede or replace attacks.  The method is based
+;; on draft-ietf-usefor-cancel-lock-01.txt which was released on November
+;; 3rd 1998.  For instance, you can add Cancel-Lock (and possibly Cancel-
+;; Key) header in a news article by using a hook which will be evaluated
+;; just before sending an article as follows:
+;;
+;; (add-hook '*e**a*e-header-hook 'canlock-insert-header t)
+;;
+;; Verifying Cancel-Lock is mainly a function of news servers, however,
+;; you can verify your own article using the command `canlock-verify' in
+;; the (raw) article buffer.  You will be prompted for the password for
+;; each time if the option `canlock-password' or `canlock-password-for-
+;; verify' is nil.  Note that setting these options is a bit unsafe.
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl))
+
+(autoload 'sha1-binary "sha1-el")
+(autoload 'base64-encode-string "base64")
+(autoload 'mail-fetch-field "mail-utils")
+(defvar mail-header-separator)
+
+(defgroup canlock nil
+  "The Cancel-Lock feature."
+  :group 'applications)
+
+(defcustom canlock-sha1-function 'sha1-binary
+  "Function to call to make a SHA-1 message digest."
+  :type '(radio (function-item sha1-binary)
+               (function-item canlock-sha1-with-openssl)
+               (function :tag "Other"))
+  :group 'canlock)
+
+(defcustom canlock-sha1-function-for-verify canlock-sha1-function
+  "Function to call to make a SHA-1 message digest for verifying."
+  :type '(radio (function-item sha1-binary)
+               (function-item canlock-sha1-with-openssl)
+               (function :tag "Other"))
+  :group 'canlock)
+
+(defcustom canlock-openssl-program "openssl"
+  "Name of OpenSSL program."
+  :type 'string
+  :group 'canlock)
+
+(defcustom canlock-openssl-args '("sha1")
+  "Arguments passed to the OpenSSL program."
+  :type 'sexp
+  :group 'canlock)
+
+(defcustom canlock-ignore-errors nil
+  "If non-nil, ignore any error signals."
+  :type 'boolean
+  :group 'canlock)
+
+(defcustom canlock-password nil
+  "Password to use when signing a Cancel-Lock or a Cancel-Key header."
+  :type '(radio (const :format "Not specified " nil)
+               (string :tag "Password" :size 0))
+  :group 'canlock)
+
+(defcustom canlock-password-for-verify canlock-password
+  "Password to use when verifying a Cancel-Lock or a Cancel-Key header."
+  :type '(radio (const :format "Not specified " nil)
+               (string :tag "Password" :size 0))
+  :group 'canlock)
+
+(defcustom canlock-force-insert-header nil
+  "If non-nil, insert a Cancel-Lock or a Cancel-Key header even if the
+buffer does not look like a news message."
+  :type 'boolean
+  :group 'canlock)
+
+(defun canlock-sha1-with-openssl (message)
+  "Make a SHA-1 digest of MESSAGE using OpenSSL."
+  (let (default-enable-multibyte-characters)
+    (with-temp-buffer
+      (let ((coding-system-for-read 'binary)
+           (coding-system-for-write 'binary)
+           selective-display
+           (case-fold-search t))
+       (insert message)
+       (apply 'call-process-region (point-min) (point-max)
+              canlock-openssl-program t t nil canlock-openssl-args)
+       (goto-char (point-min))
+       (insert "\"")
+       (while (re-search-forward "\\([0-9a-f][0-9a-f]\\)" nil t)
+         (replace-match "\\\\x\\1"))
+       (insert "\"")
+       (goto-char (point-min))
+       (read (current-buffer))))))
+
+(eval-when-compile
+  (defmacro canlock-string-as-unibyte (string)
+    "Return a unibyte string with the same individual bytes as STRING."
+    (if (fboundp 'string-as-unibyte)
+       (list 'string-as-unibyte string)
+      string)))
+
+(defun canlock-sha1 (message)
+  "Make a SHA-1 digest of MESSAGE as a unibyte string of length 20 bytes."
+  (canlock-string-as-unibyte (funcall canlock-sha1-function message)))
+
+(defun canlock-make-cancel-key (message-id password)
+  "Make a Cancel-Key header."
+  (when (> (length password) 20)
+    (setq password (canlock-sha1 password)))
+  (setq password (concat password (make-string (- 64 (length password)) 0)))
+  (let ((ipad (mapconcat (lambda (byte)
+                          (char-to-string (logxor 54 byte)))
+                        password ""))
+       (opad (mapconcat (lambda (byte)
+                          (char-to-string (logxor 92 byte)))
+                        password "")))
+    (base64-encode-string
+     (canlock-sha1
+      (concat opad
+             (canlock-sha1
+              (concat ipad (canlock-string-as-unibyte message-id))))))))
+
+(defun canlock-narrow-to-header ()
+  "Narrow the buffer to the head of the message."
+  (let (case-fold-search)
+    (narrow-to-region
+     (goto-char (point-min))
+     (goto-char (if (re-search-forward
+                    (format "^$\\|^%s$"
+                            (regexp-quote mail-header-separator))
+                    nil t)
+                   (match-beginning 0)
+                 (point-max))))))
+
+(defun canlock-delete-headers ()
+  "Delete Cancel-Key or Cancel-Lock headers in the narrowed buffer."
+  (let ((case-fold-search t))
+    (goto-char (point-min))
+    (while (re-search-forward "^Cancel-\\(Key\\|Lock\\):" nil t)
+      (delete-region (match-beginning 0)
+                    (if (re-search-forward "^[^\t ]" nil t)
+                        (goto-char (match-beginning 0))
+                      (point-max))))))
+
+(defun canlock-fetch-fields (&optional key)
+  "Return a list of the values of Cancel-Lock header.
+If KEY is non-nil, look for a Cancel-Key header instead.  The buffer
+is expected to be narrowed to just the headers of the message."
+  (let ((field (mail-fetch-field (if key "Cancel-Key" "Cancel-Lock")))
+       fields rest
+       (case-fold-search t))
+    (when field
+      (setq fields (split-string field "[\t\n\r ,]+"))
+      (while fields
+       (when (string-match "^sha1:" (setq field (pop fields)))
+         (push (substring field 5) rest)))
+      (nreverse rest))))
+
+(defun canlock-fetch-id-for-key ()
+  "Return a Message-ID in Cancel, Supersedes or Replaces header.
+The buffer is expected to be narrowed to just the headers of the
+message."
+  (or (let ((cancel (mail-fetch-field "Control")))
+       (and cancel
+            (string-match "^cancel[\t ]+\\(<[^\t\n @<>]+@[^\t\n @<>]+>\\)"
+                          cancel)
+            (match-string 1 cancel)))
+      (mail-fetch-field "Supersedes")
+      (mail-fetch-field "Replaces")))
+
+;;;###autoload
+(defun canlock-insert-header (&optional id-for-key id-for-lock password)
+  "Insert a Cancel-Key and/or a Cancel-Lock header if possible."
+  (let (news control key-for-key key-for-lock)
+    (save-excursion
+      (save-restriction
+       (canlock-narrow-to-header)
+       (when (setq news (or canlock-force-insert-header
+                            (mail-fetch-field "Newsgroups")))
+         (unless id-for-key
+           (setq id-for-key (canlock-fetch-id-for-key)))
+         (if (and (setq control (mail-fetch-field "Control"))
+                  (string-match
+                   "^cancel[\t ]+\\(<[^\t\n @<>]+@[^\t\n @<>]+>\\)"
+                   control))
+             (setq id-for-lock nil)
+           (unless id-for-lock
+             (setq id-for-lock (mail-fetch-field "Message-ID"))))
+         (canlock-delete-headers)
+         (goto-char (point-max))))
+      (when news
+       (if (not (or id-for-key id-for-lock))
+           (message "There are no Message-ID(s)")
+         (unless password
+           (setq password (or canlock-password
+                              (read-passwd
+                               "Password for Canlock: "))))
+         (if (or (not (stringp password)) (zerop (length password)))
+             (message "Password for Canlock is bad")
+           (setq key-for-key (when id-for-key
+                               (canlock-make-cancel-key
+                                id-for-key password))
+                 key-for-lock (when id-for-lock
+                                (canlock-make-cancel-key
+                                 id-for-lock password)))
+           (if (not (or key-for-key key-for-lock))
+               (message "Couldn't insert Canlock header")
+             (when key-for-key
+               (insert "Cancel-Key: sha1:" key-for-key "\n"))
+             (when key-for-lock
+               (insert "Cancel-Lock: sha1:"
+                       (base64-encode-string (canlock-sha1 key-for-lock))
+                       "\n")))))))))
+
+;;;###autoload
+(defun canlock-verify (&optional buffer)
+  "Verify Cancel-Lock or Cancel-Key in BUFFER.
+If BUFFER is nil, the current buffer is assumed.  Signal an error if
+it fails.  You can modify the behavior of this function to return non-
+nil instead of to signal an error by setting the option
+`canlock-ignore-errors' to non-nil."
+  (interactive)
+  (let ((canlock-sha1-function (or canlock-sha1-function-for-verify
+                                  canlock-sha1-function))
+       keys locks errmsg id-for-key id-for-lock password
+       key-for-key key-for-lock match)
+    (save-excursion
+      (when buffer
+       (set-buffer buffer))
+      (save-restriction
+       (widen)
+       (canlock-narrow-to-header)
+       (setq keys (canlock-fetch-fields 'key)
+             locks (canlock-fetch-fields))
+       (if (not (or keys locks))
+           (setq errmsg
+                 "There are neither Cancel-Lock nor Cancel-Key headers")
+         (setq id-for-key (canlock-fetch-id-for-key)
+               id-for-lock (mail-fetch-field "Message-ID"))
+         (or id-for-key id-for-lock
+             (setq errmsg "There are no Message-ID(s)")))))
+
+    (if errmsg
+       (if canlock-ignore-errors
+           errmsg
+         (error "%s" errmsg))
+
+      (setq password (or canlock-password-for-verify
+                        (read-passwd "Password for Canlock: ")))
+      (if (or (not (stringp password)) (zerop (length password)))
+         (progn
+           (setq errmsg "Password for Canlock is bad")
+           (if canlock-ignore-errors
+               errmsg
+             (error "%s" errmsg)))
+
+       (when keys
+         (when id-for-key
+           (setq key-for-key (canlock-make-cancel-key id-for-key password))
+           (while (and keys (not match))
+             (setq match (string-equal key-for-key (pop keys)))))
+         (setq keys (if match "good" "bad")))
+       (setq match nil)
+
+       (when locks
+         (when id-for-lock
+           (setq key-for-lock
+                 (base64-encode-string
+                  (canlock-sha1 (canlock-make-cancel-key id-for-lock
+                                                         password))))
+           (when (and locks (not match))
+             (setq match (string-equal key-for-lock (pop locks)))))
+         (setq locks (if match "good" "bad")))
+
+       (prog1
+           (when (member "bad" (list keys locks))
+             "bad")
+         (cond ((and keys locks)
+                (message "Cancel-Key is %s, Cancel-Lock is %s" keys locks))
+               (locks
+                (message "Cancel-Lock is %s" locks))
+               (keys
+                (message "Cancel-Key is %s" keys))))))))
+
+(provide 'canlock)
+
+;;; canlock.el ends here
diff --git a/lisp/compface.el b/lisp/compface.el
new file mode 100644 (file)
index 0000000..185f949
--- /dev/null
@@ -0,0 +1,57 @@
+;;; compface.el --- functions for converting X-Face headers
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+;;;###
+(defun uncompface (face)
+  "Convert FACE to pbm.
+Requires the external programs `uncompface', and `icontopbm'.  On a
+GNU/Linux system these might be in packages with names like `compface'
+or `faces-xface' and `netpbm' or `libgr-progs', for instance."
+  (with-temp-buffer
+    (insert face)
+    (and (eq 0 (apply 'call-process-region (point-min) (point-max)
+                     "uncompface"
+                     'delete '(t nil) nil))
+        (progn
+          (goto-char (point-min))
+          (insert "/* Width=48, Height=48 */\n")
+          ;; I just can't get "icontopbm" to work correctly on its
+          ;; own in XEmacs.  And Emacs doesn't understand un-raw pbm
+          ;; files.
+          (if (not (featurep 'xemacs))
+              (eq 0 (call-process-region (point-min) (point-max)
+                                         "icontopbm"
+                                         'delete '(t nil)))
+            (shell-command-on-region (point-min) (point-max)
+                                     "icontopbm | pnmnoraw"
+                                     (current-buffer) t)
+            t))
+        (buffer-string))))
+
+(provide 'compface)
+
+;;; compface.el ends here
diff --git a/lisp/deuglify.el b/lisp/deuglify.el
new file mode 100644 (file)
index 0000000..ef10ac4
--- /dev/null
@@ -0,0 +1,471 @@
+;;; deuglify.el --- deuglify broken Outlook (Express) articles
+
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002 Raymond Scholz
+
+;; Author: Raymond Scholz <rscholz@zonix.de>
+;;         Thomas Steffen (unwrapping algorithm,
+;;                         based on an idea of Stefan Monnier)
+;; Keywords: mail, news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file enables Gnus to repair broken citations produced by
+;; common user agents like MS Outlook (Express).  It may repair
+;; articles of other user agents too.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; Outlook sometimes wraps cited lines before sending a message as
+;; seen in this example:
+;;
+;; Example #1
+;; ----------
+;;
+;; John Doe wrote:
+;;
+;; > This sentence no verb.  This sentence no verb.  This sentence
+;; no
+;; > verb.  This sentence no verb.  This sentence no verb.  This
+;; > sentence no verb.
+;;
+;; The function `gnus-article-outlook-unwrap-lines' tries to recognize those
+;; erroneously wrapped lines and will unwrap them.  I.e. putting the
+;; wrapped parts ("no" in this example) back where they belong (at the
+;; end of the cited line above).
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Note that some people not only use broken user agents but also
+;; practice a bad citation style by omitting blank lines between the
+;; cited text and their own text.
+;:
+;; Example #2
+;; ----------
+;;
+;; John Doe wrote:
+;;
+;; > This sentence no verb.  This sentence no verb.  This sentence no
+;; You forgot in all your sentences.
+;; > verb.  This sentence no verb.  This sentence no verb.  This
+;; > sentence no verb.
+;;
+;; Unwrapping "You forgot in all your sentences." would be illegal as
+;; this part wasn't intended to be cited text.
+;; `gnus-article-outlook-unwrap-lines' will only unwrap lines if the resulting
+;; citation line will be of a certain maximum length.  You can control
+;; this by adjusting `gnus-outlook-deuglify-unwrap-max'.  Also
+;; unwrapping will only be done if the line above the (possibly)
+;; wrapped line has a minimum length of `gnus-outlook-deuglify-unwrap-min'.
+;;
+;; Furthermore no unwrapping will be undertaken if the last character
+;; is one of the chars specified in
+;; `gnus-outlook-deuglify-unwrap-stop-chars'.  Setting this to ".?!"
+;; inhibits unwrapping if the cited line ends with a full stop,
+;; question mark or exclamation mark.  Note that this variable
+;; defaults to `nil', triggering a few false positives but generally
+;; giving you better results.
+;;
+;; Unwrapping works on every level of citation.  Thus you will be able
+;; repair broken citations of broken user agents citing broken
+;; citations of broken user agents citing broken citations...
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Citations are commonly introduced with an attribution line
+;; indicating who wrote the cited text.  Outlook adds superfluous
+;; information that can be found in the header of the message to this
+;; line and often wraps it.
+;;
+;; If that weren't enough, lots of people write their own text above
+;; the cited text and cite the complete original article below.
+;;
+;; Example #3
+;; ----------
+;;
+;; Hey, John.  There's no in all your sentences!
+;;
+;; John Doe <john.doe@some.domain> wrote in message
+;; news:a87usw8$dklsssa$2@some.news.server...
+;; > This sentence no verb.  This sentence no verb.  This sentence
+;; no
+;; > verb.  This sentence no verb.  This sentence no verb.  This
+;; > sentence no verb.
+;; >
+;; > Bye, John
+;;
+;; Repairing the attribution line will be done by function
+;; `gnus-article-outlook-repair-attribution which calls other function that
+;; try to recognize and repair broken attribution lines.  See variable
+;; `gnus-outlook-deuglify-attrib-cut-regexp' for stuff that should be
+;; cut off from the beginning of an attribution line and variable
+;; `gnus-outlook-deuglify-attrib-verb-regexp' for the verbs that are
+;; required to be found in an attribution line.  These function return
+;; the point where the repaired attribution line starts.
+;;
+;; Rearranging the article so that the cited text appears above the
+;; new text will be done by function
+;; `gnus-article-outlook-rearrange-citation'.  This function calls
+;; `gnus-article-outlook-repair-attribution to find and repair an attribution
+;; line.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Well, and that's what the message will look like after applying
+;; deuglification:
+;;
+;; Example #3 (deuglified)
+;; -----------------------
+;;
+;; John Doe <john.doe@some.domain> wrote:
+;;
+;; > This sentence no verb.  This sentence no verb.  This sentence no
+;; > verb.  This sentence no verb.  This sentence no verb.  This
+;; > sentence no verb.
+;; >
+;; > Bye, John
+;;
+;; Hey, John.  There's no in all your sentences!
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Usage
+;; -----
+;;
+;; Press `W k' in the Summary Buffer.
+;;
+;; Non recommended usage :-)
+;; ---------------------
+;;
+;; To automatically invoke deuglification on every article you read,
+;; put something like that in your .gnus:
+;;
+;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-unwrap-lines)
+;;
+;; or _one_ of the following lines:
+;;
+;; ;; repair broken attribution lines
+;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-repair-attribution)
+;;
+;; ;; repair broken attribution lines and citations
+;; (add-hook 'gnus-article-decode-hook 'gnus-article-outlook-rearrange-citation)
+;;
+;; Note that there always may be some false positives, so I suggest
+;; using the manual invocation.  After deuglification you may want to
+;; refill the whole article using `W w'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Limitations
+;; -----------
+;;
+;; As I said before there may (or will) be a few false positives on
+;; unwrapping cited lines with `gnus-article-outlook-unwrap-lines'.
+;;
+;; `gnus-article-outlook-repair-attribution will only fix the first
+;; attribution line found in the article.  Furthermore it fixed to
+;; certain kinds of attributions.  And there may be horribly many
+;; false positives, vanishing lines and so on -- so don't trust your
+;; eyes.  Again I recommend manual invocation.
+;;
+;; `gnus-article-outlook-rearrange-citation' carries all the limitations of
+;; `gnus-article-outlook-repair-attribution.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; See ChangeLog for other changes.
+;;
+;; Revision 1.5  2002/01/27 14:39:17  rscholz
+;; * New variable `gnus-outlook-deuglify-no-wrap-chars' to inhibit
+;;   unwrapping if one these chars is first in the possibly wrapped line.
+;; * Improved rearranging of the article.
+;; * New function `gnus-outlook-repair-attribution-block' for repairing
+;;   those big "Original Message (following some headers)" attributions.
+;;
+;; Revision 1.4  2002/01/03 14:05:00  rscholz
+;; Renamed `gnus-outlook-deuglify-article' to
+;; `gnus-article-outlook-deuglify-article'.
+;; Made it easier to deuglify the article while being in Gnus' Article
+;; Edit Mode.  (suggested by Phil Nitschke)
+;;
+;;
+;; Revision 1.3  2002/01/02 23:35:54  rscholz
+;; Fix a bug that caused succeeding long attribution lines to be
+;; unwrapped.  Minor doc fixes and regular expression tuning.
+;;
+;; Revision 1.2  2001/12/30 20:14:34  rscholz
+;; Clean up source.
+;;
+;; Revision 1.1  2001/12/30 20:13:32  rscholz
+;; Initial revision
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Code:
+
+(require 'gnus-art)
+(require 'gnus-sum)
+
+(defconst gnus-outlook-deuglify-version "1.5 Gnus version"
+  "Version of gnus-outlook-deuglify.")
+
+;;; User Customizable Variables:
+
+(defgroup gnus-outlook-deuglify nil
+  "Deuglify articles generated by broken user agents like MS Outlook (Express).")
+
+;;;###autoload
+(defcustom gnus-outlook-deuglify-unwrap-min 45
+  "Minimum length of the cited line above the (possibly) wrapped line."
+  :type 'integer
+  :group 'gnus-outlook-deuglify)
+
+;;;###autoload
+(defcustom gnus-outlook-deuglify-unwrap-max 95
+  "Maximum length of the cited line after unwrapping."
+  :type 'integer
+  :group 'gnus-outlook-deuglify)
+
+(defcustom gnus-outlook-deuglify-cite-marks ">|#%"
+  "Characters that indicate cited lines."
+  :type 'string
+  :group 'gnus-outlook-deuglify)
+
+(defcustom gnus-outlook-deuglify-unwrap-stop-chars nil ;; ".?!" or nil
+  "Characters that inhibit unwrapping if they are the last one on the cited line above the possible wrapped line."
+  :type '(radio (const :format "None  " nil)
+               (string :size 0 :value ".?!"))
+  :group 'gnus-outlook-deuglify)
+
+(defcustom gnus-outlook-deuglify-no-wrap-chars "`"
+  "Characters that inhibit unwrapping if they are the first one in the possibly wrapped line."
+  :type 'string
+  :group 'gnus-outlook-deuglify)
+
+(defcustom  gnus-outlook-deuglify-attrib-cut-regexp
+  "\\(On \\|Am \\)?\\(Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun\\),[^,]+, "
+  "Regular expression matching the beginning of an attribution line that should be cut off."
+  :type 'string
+  :group 'gnus-outlook-deuglify)
+
+(defcustom gnus-outlook-deuglify-attrib-verb-regexp
+  "wrote\\|writes\\|says\\|schrieb\\|schreibt\\|meinte\\|skrev\\|a Ã©crit\\|schreef\\|escribió"
+  "Regular expression matching the verb used in an attribution line."
+  :type 'string
+  :group 'gnus-outlook-deuglify)
+
+(defcustom  gnus-outlook-deuglify-attrib-end-regexp
+  ": *\\|\\.\\.\\."
+  "Regular expression matching the end of an attribution line."
+  :type 'string
+  :group 'gnus-outlook-deuglify)
+
+;;;###autoload
+(defcustom gnus-outlook-display-hook nil
+  "A hook called after an deuglified article has been prepared.
+It is run after `gnus-article-prepare-hook'."
+  :type 'hook
+  :group 'gnus-outlook-deuglify)
+
+;; Functions
+
+(defun gnus-outlook-display-article-buffer ()
+  "Redisplay current buffer or article buffer."
+  (with-current-buffer (or gnus-article-buffer (current-buffer))
+    ;; "Emulate" `gnus-article-prepare-display' without calling
+    ;; it. Calling `gnus-article-prepare-display' on an already
+    ;; prepared article removes all MIME parts.  I'm unsure whether
+    ;; this is a bug or not.
+    (gnus-article-highlight t)
+    (gnus-treat-article nil)
+    (gnus-run-hooks 'gnus-article-prepare-hook
+                   'gnus-outlook-display-hook)))
+
+;;;###autoload
+(defun gnus-article-outlook-unwrap-lines (&optional nodisplay)
+  "Unwrap lines that appear to be wrapped citation lines.
+You can control what lines will be unwrapped by frobbing
+`gnus-outlook-deuglify-unwrap-min' and `gnus-outlook-deuglify-unwrap-max',
+indicating the minimum and maximum length of an unwrapped citation line.  If
+NODISPLAY is non-nil, don't redisplay the article buffer."
+  (interactive "P")
+  (save-excursion
+    (let ((case-fold-search nil)
+         (inhibit-read-only t)
+         (cite-marks gnus-outlook-deuglify-cite-marks)
+         (no-wrap gnus-outlook-deuglify-no-wrap-chars)
+         (stop-chars gnus-outlook-deuglify-unwrap-stop-chars))
+      (gnus-with-article-buffer
+       (article-goto-body)
+       (while (re-search-forward
+               (concat
+                "^\\([ \t" cite-marks "]*\\)"
+                "\\([" cite-marks "].*[^\n " stop-chars "]\\)[ \t]?\n"
+                "\\1\\([^\n " cite-marks no-wrap "]+.*\\)$")
+              nil t)
+         (let ((len12 (- (match-end 2) (match-beginning 1)))
+             (len3 (- (match-end 3) (match-beginning 3))))
+           (if (and (> len12 gnus-outlook-deuglify-unwrap-min)
+                    (< (+ len12 len3) gnus-outlook-deuglify-unwrap-max))
+               (progn
+                 (replace-match "\\1\\2 \\3")
+                 (goto-char (match-beginning 0)))))))))
+  (unless nodisplay (gnus-outlook-display-article-buffer)))
+
+(defun gnus-outlook-rearrange-article (attr-start)
+  "Put the text from ATTR-START to the end of buffer at the top of the article buffer."
+  (save-excursion
+    (let ((inhibit-read-only t)
+         (cite-marks gnus-outlook-deuglify-cite-marks))
+      (gnus-with-article-buffer
+       (article-goto-body)
+       ;; article does not start with attribution
+       (unless (= (point) attr-start)
+         (gnus-kill-all-overlays)
+         (let ((cur (point))
+               ;; before signature or end of buffer
+               (to (if (gnus-article-search-signature)
+                       (point)
+                     (point-max))))
+           ;; handle the case where the full quote is below the
+           ;; signature
+           (if (< to attr-start)
+               (setq to (point-max)))
+           (transpose-regions cur attr-start attr-start to)))))))
+
+;; John Doe <john.doe@some.domain> wrote in message
+;; news:a87usw8$dklsssa$2@some.news.server...
+
+(defun gnus-outlook-repair-attribution-outlook ()
+  "Repair a broken attribution line (Outlook)."
+  (save-excursion
+    (let ((case-fold-search nil)
+         (inhibit-read-only t)
+         (cite-marks gnus-outlook-deuglify-cite-marks))
+      (gnus-with-article-buffer
+       (article-goto-body)
+       (if (re-search-forward
+            (concat "^\\([^" cite-marks "].+\\)"
+                    "\\(" gnus-outlook-deuglify-attrib-verb-regexp "\\)"
+                    "\\(.*\n?[^\n" cite-marks "].*\\)?"
+                    "\\(" gnus-outlook-deuglify-attrib-end-regexp "\\)$")
+            nil t)
+           (progn
+             (gnus-kill-all-overlays)
+             (replace-match "\\1\\2\\4")
+             (match-beginning 0)))))))
+
+
+;; ----- Original Message -----
+;; From: "John Doe" <john.doe@some.domain>
+;; To: "Doe Foundation" <info@doefnd.org>
+;; Sent: Monday, November 19, 2001 12:13 PM
+;; Subject: More Doenuts
+
+(defun gnus-outlook-repair-attribution-block ()
+  "Repair a big broken attribution block."
+  (save-excursion
+    (let ((case-fold-search nil)
+         (inhibit-read-only t)
+         (cite-marks gnus-outlook-deuglify-cite-marks))
+      (gnus-with-article-buffer
+       (article-goto-body)
+       (if (re-search-forward
+            (concat "^[" cite-marks " \t]*--* ?[^-]+ [^-]+ ?--*\\s *\n"
+                    "[^\n:]+:[ \t]*\\([^\n]+\\)\n"
+                    "\\([^\n:]+:[ \t]*[^\n]+\n\\)+")
+            nil t)
+           (progn
+             (gnus-kill-all-overlays)
+             (replace-match "\\1 wrote:\n")
+             (match-beginning 0)))))))
+
+;; On Wed, 16 Jan 2002 23:23:30 +0100, John Doe <john.doe@some.domain> wrote:
+
+(defun gnus-outlook-repair-attribution-other ()
+  "Repair a broken attribution line (other user agents than Outlook)."
+  (save-excursion
+    (let ((case-fold-search nil)
+         (inhibit-read-only t)
+         (cite-marks gnus-outlook-deuglify-cite-marks))
+      (gnus-with-article-buffer
+       (article-goto-body)
+       (if (re-search-forward
+            (concat "^\\("gnus-outlook-deuglify-attrib-cut-regexp"\\)?"
+                    "\\([^" cite-marks "].+\\)\n\\([^\n" cite-marks "].*\\)?"
+                    "\\(" gnus-outlook-deuglify-attrib-verb-regexp "\\).*"
+                    "\\(" gnus-outlook-deuglify-attrib-end-regexp "\\)$")
+            nil t)
+           (progn
+             (gnus-kill-all-overlays)
+             (replace-match "\\4 \\5\\6\\7")
+             (match-beginning 0)))))))
+
+;;;###autoload
+(defun gnus-article-outlook-repair-attribution (&optional nodisplay)
+  "Repair a broken attribution line.
+If NODISPLAY is non-nil, don't redisplay the article buffer."
+  (interactive "P")
+  (let ((attrib-start
+        (or
+         (gnus-outlook-repair-attribution-other)
+         (gnus-outlook-repair-attribution-block)
+         (gnus-outlook-repair-attribution-outlook))))
+    (unless nodisplay (gnus-outlook-display-article-buffer))
+    attrib-start))
+
+(defun gnus-article-outlook-rearrange-citation (&optional nodisplay)
+  "Repair broken citations.
+If NODISPLAY is non-nil, don't redisplay the article buffer."
+  (interactive "P")
+  (let ((attrib-start (gnus-article-outlook-repair-attribution 'nodisplay)))
+    ;; rearrange citations if an attribution line has been recognized
+    (if attrib-start
+       (gnus-outlook-rearrange-article attrib-start)))
+  (unless nodisplay (gnus-outlook-display-article-buffer)))
+
+;;;###autoload
+(defun gnus-outlook-deuglify-article (&optional nodisplay)
+  "Full deuglify of broken Outlook (Express) articles.
+Treat dumbquotes, unwrap lines, repair attribution and rearrange citation.  If
+NODISPLAY is non-nil, don't redisplay the article buffer."
+  (interactive "P")
+  ;; apply treatment of dumb quotes
+  (gnus-article-treat-dumbquotes)
+  ;; repair wrapped cited lines
+  (gnus-article-outlook-unwrap-lines 'nodisplay)
+  ;; repair attribution line and rearrange citation.
+  (gnus-article-outlook-rearrange-citation 'nodisplay)
+  (unless nodisplay (gnus-outlook-display-article-buffer)))
+
+;;;###autoload
+(defun gnus-article-outlook-deuglify-article ()
+  "Deuglify broken Outlook (Express) articles and redisplay."
+  (interactive)
+  (gnus-outlook-deuglify-article nil))
+
+(provide 'deuglify)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; deuglify.el ends here
index 264ac6b..97670f4 100644 (file)
@@ -1,7 +1,9 @@
 ;;; dgnushack.el --- a hack to set the load path for byte-compiling
-;; Copyright (C) 1994,95,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Version: 4.19
 ;; Keywords: news, path
 
 
 ;;; Code:
 
-(fset 'facep 'ignore)
+;; Set coding priority of Shift-JIS to the bottom.
+(if (featurep 'xemacs)
+    (defalias 'set-coding-priority 'ignore)
+  (defalias 'coding-priority-list 'ignore)
+  (defalias 'set-coding-priority-list 'ignore))
+(cond ((and (featurep 'xemacs) (featurep 'mule))
+       (if (memq 'shift-jis (coding-priority-list))
+          (set-coding-priority-list
+           (append (delq 'shift-jis (coding-priority-list)) '(shift-jis)))))
+      ((boundp 'MULE)
+       (put '*coding-category-sjis* 'priority (length *predefined-category*)))
+      ((featurep 'mule)
+       (if (memq 'coding-category-sjis coding-category-list)
+          (set-coding-priority
+           (append (delq 'coding-category-sjis
+                         (copy-sequence coding-category-list))
+                   '(coding-category-sjis))))))
+
+(defalias 'facep 'ignore)
 
 (require 'cl)
+
+(unless (and
+        ;; `dolist' might not be available because of ``-no-autoloads''.
+        (fboundp 'dolist)
+        ;; It may have been defined in egg.el.
+        (dolist (var nil t)))
+  (load "cl-macs" nil t))
+
+(defvar srcdir (or (getenv "srcdir") "."))
+
+(defvar dgnushack-w3-directory (let ((w3dir (getenv "W3DIR")))
+                                (unless (zerop (length w3dir))
+                                  (file-name-as-directory w3dir))))
+
+(let ((urldir (getenv "URLDIR")))
+  (unless (zerop (length urldir))
+    (setq urldir (file-name-as-directory urldir))
+    (push (file-name-as-directory urldir) load-path))
+  (when (and dgnushack-w3-directory
+            (not (string-equal urldir dgnushack-w3-directory)))
+    (push dgnushack-w3-directory load-path)))
+
+;; If we are building w3 in a different directory than the source
+;; directory, we must read *.el from source directory and write *.elc
+;; into the building directory.  For that, we define this function
+;; before loading bytecomp.  Bytecomp doesn't overwrite this function.
+(defun byte-compile-dest-file (filename)
+  "Convert an Emacs Lisp source file name to a compiled file name.
+ In addition, remove directory name part from FILENAME."
+  (setq filename (byte-compiler-base-file-name filename))
+  (setq filename (file-name-sans-versions filename))
+  (setq filename (file-name-nondirectory filename))
+  (if (memq system-type '(win32 w32 mswindows windows-nt))
+      (setq filename (downcase filename)))
+  (cond ((eq system-type 'vax-vms)
+        (concat (substring filename 0 (string-match ";" filename)) "c"))
+       ((string-match emacs-lisp-file-regexp filename)
+        (concat (substring filename 0 (match-beginning 0)) ".elc"))
+       (t (concat filename ".elc"))))
+
 (require 'bytecomp)
-(push "~/lisp/custom" load-path)
-(push "." load-path)
-(load "./lpath.el")
+;; To avoid having defsubsts and inlines happen.
+;(if (featurep 'xemacs)
+;    (require 'byte-optimize)
+;  (require 'byte-opt))
+;(defun byte-optimize-inline-handler (form)
+;  "byte-optimize-handler for the `inline' special-form."
+;  (cons 'progn (cdr form)))
+;(defalias 'byte-compile-file-form-defsubst 'byte-compile-file-form-defun)
+
+(when (and (not (featurep 'xemacs))
+          (= emacs-major-version 21)
+          (= emacs-minor-version 3)
+          (condition-case code
+              (let ((byte-compile-error-on-warn t))
+                (byte-optimize-form (quote (pop x)) t)
+                nil)
+            (error (string-match "called for effect"
+                                 (error-message-string code)))))
+  (defadvice byte-optimize-form-code-walker (around silence-warn-for-pop
+                                                   (form for-effect)
+                                                   activate)
+    "Silence the warning \"...called for effect\" for the `pop' form.
+It is effective only when the `pop' macro is defined by cl.el rather
+than subr.el."
+    (let (tmp)
+      (if (and (eq (car-safe form) 'car)
+              for-effect
+              (setq tmp (get 'car 'side-effect-free))
+              (not byte-compile-delete-errors)
+              (not (eq tmp 'error-free))
+              (eq (car-safe (cadr form)) 'prog1)
+              (let ((var (cadr (cadr form)))
+                    (last (nth 2 (cadr form))))
+                (and (symbolp var)
+                     (null (nthcdr 3 (cadr form)))
+                     (eq (car-safe last) 'setq)
+                     (eq (cadr last) var)
+                     (eq (car-safe (nth 2 last)) 'cdr)
+                     (eq (cadr (nth 2 last)) var))))
+         (progn
+           (put 'car 'side-effect-free 'error-free)
+           (unwind-protect
+               ad-do-it
+             (put 'car 'side-effect-free tmp)))
+       ad-do-it))))
+
+(when (boundp 'MULE)
+  (let (current-load-list)
+    ;; Make the function to be silent at compile-time.
+    (defun locate-library (library &optional nosuffix)
+      "Show the full path name of Emacs library LIBRARY.
+This command searches the directories in `load-path' like `M-x load-library'
+to find the file that `M-x load-library RET LIBRARY RET' would load.
+Optional second arg NOSUFFIX non-nil means don't add suffixes `.elc' or `.el'
+to the specified name LIBRARY (a la calling `load' instead of `load-library')."
+      (interactive "sLocate library: ")
+      (catch 'answer
+       (mapcar
+        '(lambda (dir)
+           (mapcar
+            '(lambda (suf)
+               (let ((try (expand-file-name (concat library suf) dir)))
+                 (and (file-readable-p try)
+                      (null (file-directory-p try))
+                      (progn
+                        (or noninteractive
+                            (message "Library is file %s" try))
+                        (throw 'answer try)))))
+            (if nosuffix '("") '(".elc" ".el" ""))))
+        load-path)
+       (or noninteractive
+           (message "No library %s in search path" library))
+       nil))
+    (byte-compile 'locate-library)))
+
+(setq max-specpdl-size 3000)
+
+(when (equal
+       (cadr
+       (byte-optimize-form
+        '(and
+          (< 0 1)
+          (message "The subform `(< 0 1)' should be optimized to t"))
+        'for-effect))
+       '(< 0 1))
+  (defadvice byte-optimize-form-code-walker
+    (around fix-bug-in-and/or-forms (form for-effect) activate)
+    "Fix a bug in the optimizing and/or forms.
+It has already been fixed in XEmacs since 1999-12-06."
+    (if (and for-effect (memq (car-safe form) '(and or)))
+       (let ((fn (car form))
+             (backwards (reverse (cdr form))))
+         (while (and backwards
+                     (null (setcar backwards
+                                   (byte-optimize-form (car backwards) t))))
+           (setq backwards (cdr backwards)))
+         (if (and (cdr form) (null backwards))
+             (byte-compile-log
+              "  all subforms of %s called for effect; deleted" form))
+         (when backwards
+           (setcdr backwards
+                   (mapcar 'byte-optimize-form (cdr backwards))))
+         (setq ad-return-value (cons fn (nreverse backwards))))
+      ad-do-it)))
+
+(condition-case nil
+    (char-after)
+  (wrong-number-of-arguments
+   ;; Optimize byte code for `char-after'.
+   (put 'char-after 'byte-optimizer 'byte-optimize-char-after)
+   (defun byte-optimize-char-after (form)
+     (if (null (cdr form))
+        '(char-after (point))
+       form))))
+
+(condition-case nil
+    (char-before)
+  (wrong-number-of-arguments
+   ;; Optimize byte code for `char-before'.
+   (put 'char-before 'byte-optimizer 'byte-optimize-char-before)
+   (defun byte-optimize-char-before (form)
+     (if (null (cdr form))
+        '(char-before (point))
+       form))))
+
+(load (expand-file-name "dgnuspath.el" srcdir) nil nil t)
+
+(condition-case err
+    (load "~/.lpath.el" t nil t)
+  (error (message "Error in \"~/.lpath.el\" file: %s" err)))
+
+;; Don't load path-util until `char-after' and `char-before' have been
+;; optimized because it requires `poe' and then modify the functions.
+
+;; If the APEL modules are installed under the non-standard directory,
+;; for example "/var/home/john/lisp/apel-VERSION/", you should add that
+;; name using the configure option "--with-addpath=".
+;; And also the directory where the EMU modules are installed, for
+;; example "/usr/local/share/mule/19.34/site-lisp/", it should be
+;; included in the standard `load-path' or added by the configure
+;; option "--with-addpath=".
+(let ((path (or (locate-library "path-util")
+               (locate-library "apel/path-util")));; backward compat.
+      parent lpath)
+  (if path
+      (progn
+       (when (string-match "/$" (setq path (file-name-directory path)))
+         (setq path (substring path 0 (match-beginning 0))))
+       ;; path == "/var/home/john/lisp/apel-VERSION"
+       (when (string-match "/$" (setq parent (file-name-directory path)))
+         (setq parent (substring path 0 (match-beginning 0))))
+       ;; parent == "/var/home/john/lisp"
+       (if (setq lpath (or (member path load-path)
+                           (member (file-name-as-directory path) load-path)))
+           (unless (or (member parent load-path)
+                       (member (file-name-as-directory parent) load-path))
+             (push parent (cdr lpath)))
+         (push path load-path)
+         (unless (or (member parent load-path)
+                     (member (file-name-as-directory parent) load-path))
+           (push parent (cdr load-path))))
+       (require 'advice)
+       (require 'path-util))
+    (error "
+APEL modules are not found in %s.
+Try to re-configure with --with-addpath=APEL_PATH and run make again.
+"
+          load-path)))
+
+(unless (locate-library "mel")
+  (add-path "flim"))
+(unless (module-installed-p 'mel)
+  ;; FLIM 1.14 may have installed in two "flim" subdirectories.
+  (push (expand-file-name "flim"
+                         (file-name-directory (get-latest-path "^apel$" t)))
+       load-path)
+  (unless (module-installed-p 'mel)
+    (error "
+FLIM modules does not found in %s.
+Try to re-configure with --with-addpath=FLIM_PATH and run make again.
+"
+          load-path)))
+(add-path "semi")
+
+(push srcdir load-path)
+(load (expand-file-name "lpath.el" srcdir) nil t t)
+
+(load (expand-file-name "gnus-clfns.el" srcdir) nil t t)
+
+(when (boundp 'MULE)
+  ;; Bind the function `base64-encode-string' before loading canlock.
+  ;; Since canlock will bind it as an autoloaded function, it causes
+  ;; damage to define the function by MEL.
+  (load (expand-file-name "base64.el" srcdir) nil t t)
+  ;; Load special macros for compiling canlock.el.
+  (load (expand-file-name "canlock-om.el" srcdir) nil t t))
+
+(require 'custom)
+
+;; Bind functions defined by `defun-maybe'.
+(put 'defun-maybe 'byte-hunk-handler 'byte-compile-file-form-defun-maybe)
+(defun byte-compile-file-form-defun-maybe (form)
+  (if (and (not (fboundp (nth 1 form)))
+          (memq 'unresolved byte-compile-warnings))
+      (setq byte-compile-function-environment
+           (cons (cons (nth 1 form)
+                       (cons 'lambda (cdr (cdr form))))
+                 byte-compile-function-environment)))
+  form)
+
+(condition-case nil
+    :symbol-for-testing-whether-colon-keyword-is-available-or-not
+  (void-variable
+   (defun dgnushack-bind-colon-keywords ()
+     "Bind all the colon keywords for old Emacsen."
+     (let ((cache (expand-file-name "dgnuskwds.el" srcdir))
+          (makefile (expand-file-name "Makefile" srcdir))
+          (buffer (get-buffer-create " *colon keywords*"))
+          keywords ignores files file dirs dir form elem make-backup-files)
+       (save-excursion
+        (set-buffer buffer)
+        (let (buffer-file-format
+              format-alist
+              insert-file-contents-post-hook
+              insert-file-contents-pre-hook
+              jam-zcat-filename-list
+              jka-compr-compression-info-list)
+          (if (and (file-exists-p cache)
+                   (file-exists-p makefile)
+                   (file-newer-than-file-p cache makefile))
+              (progn
+                (insert-file-contents cache nil nil nil t)
+                (setq keywords (read buffer)))
+            (setq
+             ignores
+             '(:symbol-for-testing-whether-colon-keyword-is-available-or-not
+               ;; The following keywords will be bound by CUSTOM.
+               :get :group :initialize :link :load :options :prefix
+               :require :set :tag :type)
+             files (list (locate-library "semi-def")
+                         (locate-library "mailcap")
+                         (locate-library "mime-def")
+                         (locate-library "path-util")
+                         (locate-library "poem"))
+             dirs (list (file-name-as-directory (expand-file-name srcdir))))
+            (while files
+              (when (setq file (pop files))
+                (setq dir (file-name-directory file))
+                (unless (member dir dirs)
+                  (push dir dirs))))
+            (message "Searching for all the colon keywords in:")
+            (while dirs
+              (setq dir (pop dirs))
+              (message " %s..." dir)
+              (setq files (directory-files dir t
+                                           "\\.el\\(\\.gz\\|\\.bz2\\)?$"))
+              (while files
+                (setq file (pop files))
+                (if (string-match "\\(\\.gz$\\)\\|\\.bz2$" file)
+                    (let ((temp (expand-file-name "dgnustemp.el" srcdir)))
+                      (when
+                          (let* ((binary (if (boundp 'MULE)
+                                             '*noconv*
+                                           'binary))
+                                 (coding-system-for-read binary)
+                                 (coding-system-for-write binary)
+                                 (input-coding-system binary)
+                                 (output-coding-system binary)
+                                 (default-process-coding-system
+                                   (cons binary binary))
+                                 call-process-hook)
+                            (insert-file-contents file nil nil nil t)
+                            (when
+                                (condition-case code
+                                    (progn
+                                      (if (match-beginning 1)
+                                          (call-process-region
+                                           (point-min) (point-max)
+                                           "gzip" t buffer nil "-cd")
+                                        (call-process-region
+                                         (point-min) (point-max)
+                                         "bzip2" t buffer nil "-d"))
+                                      t)
+                                  (error
+                                   (erase-buffer)
+                                   (message "In file %s: %s" file code)
+                                   nil))
+                              (write-region (point-min) (point-max) temp
+                                            nil 'silent)
+                              t))
+                        (unwind-protect
+                            (insert-file-contents temp nil nil nil t)
+                          (delete-file temp))))
+                  (insert-file-contents file nil nil nil t))
+                (while (setq form (condition-case nil
+                                      (read buffer)
+                                    (error nil)))
+                  (when (listp form)
+                    (while form
+                      (setq elem (car-safe form)
+                            form (cdr-safe form))
+                      (unless (memq (car-safe elem)
+                                    '(defcustom defface defgroup
+                                      define-widget quote))
+                        (while (consp elem)
+                          (push (car elem) form)
+                          (setq elem (cdr elem)))
+                        (when (and elem
+                                   (symbolp elem)
+                                   (not (eq ': elem))
+                                   (eq ?: (aref (symbol-name elem) 0))
+                                   (not (memq elem ignores))
+                                   (not (memq elem keywords)))
+                          (push elem keywords))))))))
+            (setq keywords (sort keywords
+                                 (lambda (a b)
+                                   (string-lessp (symbol-name a)
+                                                 (symbol-name b)))))
+            (erase-buffer)
+            (insert (format "%s" keywords))
+            (write-region (point-min) (point) cache nil 'silent)
+            (message
+             "The following colon keywords will be bound at run-time:\n %s"
+             keywords))))
+       (kill-buffer buffer)
+       (defconst dgnushack-colon-keywords keywords)
+       (while keywords
+        (set (car keywords) (car keywords))
+        (setq keywords (cdr keywords)))))
+   (byte-compile 'dgnushack-bind-colon-keywords)
+   (dgnushack-bind-colon-keywords)))
+
+(when (boundp 'MULE)
+  (setq :version ':version
+       :set-after ':set-after)
+  (require 'custom)
+  (defadvice custom-handle-keyword
+    (around dont-signal-an-error-even-if-unsupported-keyword-is-given
+           activate)
+    "Don't signal an error even if unsupported keyword is given."
+    (if (not (memq (ad-get-arg 1) '(:version :set-after)))
+       ad-do-it)))
+
+(when (boundp 'MULE)
+  (put 'custom-declare-face 'byte-optimizer
+       'byte-optimize-ignore-unsupported-custom-keywords)
+  (put 'custom-declare-group 'byte-optimizer
+       'byte-optimize-ignore-unsupported-custom-keywords)
+  (defun byte-optimize-ignore-unsupported-custom-keywords (form)
+    (if (or (memq ':version (nthcdr 4 form))
+           (memq ':set-after (nthcdr 4 form)))
+       (let ((newform (list (car form) (nth 1 form)
+                            (nth 2 form) (nth 3 form)))
+             (args (nthcdr 4 form)))
+         (while args
+           (or (memq (car args) '(:version :set-after))
+               (setq newform (nconc newform (list (car args)
+                                                  (car (cdr args))))))
+           (setq args (cdr (cdr args))))
+         newform)
+      form))
+
+  (put 'custom-declare-variable 'byte-hunk-handler
+       'byte-compile-file-form-custom-declare-variable)
+  (defun byte-compile-file-form-custom-declare-variable (form)
+    ;; Bind defcustom'ed variables.
+    (if (memq 'free-vars byte-compile-warnings)
+       (setq byte-compile-bound-variables
+             (cons (nth 1 (nth 1 form)) byte-compile-bound-variables)))
+    (if (memq ':version (nthcdr 4 form))
+       ;; Make the variable uncustomizable.
+       `(defvar ,(nth 1 (nth 1 form)) ,(nth 1 (nth 2 form))
+          ,(substring (nth 3 form) (if (string-match "^[\t *]+" (nth 3 form))
+                                       (match-end 0)
+                                     0)))
+      ;; Ignore unsupported keyword(s).
+      (if (memq ':set-after (nthcdr 4 form))
+         (let ((newform (list (car form) (nth 1 form)
+                              (nth 2 form) (nth 3 form)))
+               (args (nthcdr 4 form)))
+           (while args
+             (or (eq (car args) ':set-after)
+                 (setq newform (nconc newform (list (car args)
+                                                    (car (cdr args))))))
+             (setq args (cdr (cdr args))))
+           newform)
+       form)))
+
+  (defadvice byte-compile-inline-expand (around ignore-built-in-functions
+                                               (form) activate)
+    "Ignore built-in functions."
+    (let* ((name (car form))
+          (fn (and (fboundp name)
+                   (symbol-function name))))
+      (if (subrp fn)
+         ;; Give up on inlining.
+         (setq ad-return-value form)
+       ad-do-it))))
+
+;; Unknown variables and functions.
+(unless (boundp 'buffer-file-coding-system)
+  (defvar buffer-file-coding-system (symbol-value 'file-coding-system)))
+(unless (featurep 'xemacs)
+  (defalias 'Custom-make-dependencies 'ignore)
+  (defalias 'update-autoloads-from-directory 'ignore))
 
 (defalias 'device-sound-enabled-p 'ignore)
 (defalias 'play-sound-file 'ignore)
 (defalias 'define-mail-user-agent 'ignore)
 
 (eval-and-compile
-  (unless (string-match "XEmacs" emacs-version)
-    (fset 'get-popup-menu-response 'ignore)
-    (fset 'event-object 'ignore)
-    (fset 'x-defined-colors 'ignore)
-    (fset 'read-color 'ignore)))
+  (when (featurep 'xemacs)
+    ;; XEmacs 21.1 needs some extra hand holding
+    (when (eq emacs-minor-version 1)
+      (autoload 'custom-declare-face "cus-face" nil t)
+      (autoload 'cl-compile-time-init "cl-macs" nil t)
+      (autoload 'defadvice "advice" nil nil 'macro))
+    (unless (fboundp 'defadvice)
+      (autoload 'defadvice "advice" nil nil 'macro))
+    (autoload 'Info-directory "info" nil t)
+    (autoload 'Info-menu "info" nil t)
+    (autoload 'annotations-at "annotations")
+    (autoload 'apropos "apropos" nil t)
+    (autoload 'apropos-command "apropos" nil t)
+    (autoload 'bbdb-complete-name "bbdb-com" nil t)
+    (autoload 'browse-url "browse-url" nil t)
+    (autoload 'customize-apropos "cus-edit" nil t)
+    (autoload 'customize-save-variable "cus-edit" nil t)
+    (autoload 'customize-variable "cus-edit" nil t)
+    (autoload 'delete-annotation "annotations")
+    (autoload 'dolist "cl-macs" nil nil 'macro)
+    (autoload 'enriched-decode "enriched")
+    (autoload 'info "info" nil t)
+    (autoload 'make-annotation "annotations")
+    (autoload 'make-display-table "disp-table")
+    (autoload 'pp "pp")
+    (autoload 'ps-despool "ps-print" nil t)
+    (autoload 'ps-spool-buffer "ps-print" nil t)
+    (autoload 'ps-spool-buffer-with-faces "ps-print" nil t)
+    (autoload 'read-passwd "passwd")
+    (autoload 'regexp-opt "regexp-opt")
+    (autoload 'reporter-submit-bug-report "reporter")
+    (if (emacs-version>= 21 5)
+       (autoload 'setenv "process" nil t)
+      (autoload 'setenv "env" nil t))
+    (autoload 'smtpmail-send-it "smtpmail")
+    (autoload 'sort-numeric-fields "sort" nil t)
+    (autoload 'sort-subr "sort")
+    (autoload 'trace-function-background "trace" nil t)
+    (autoload 'w3-do-setup "w3")
+    (autoload 'w3-prepare-buffer "w3-display")
+    (autoload 'w3-region "w3-display" nil t)
+    (defalias 'frame-char-height 'frame-height)
+    (defalias 'frame-char-width 'frame-width)
+    (defalias 'frame-parameter 'frame-property)
+    (defalias 'make-overlay 'ignore)
+    (defalias 'overlay-end 'ignore)
+    (defalias 'overlay-get 'ignore)
+    (defalias 'overlay-put 'ignore)
+    (defalias 'overlay-start 'ignore)
+    (defalias 'overlays-in 'ignore)
+    (defalias 'replace-dehighlight 'ignore)
+    (defalias 'replace-highlight 'ignore)
+    (defalias 'run-with-idle-timer 'ignore)
+    (defalias 'w3-coding-system-for-mime-charset 'ignore)))
+
+;; T-gnus stuff.
+(eval-and-compile
+  (when (featurep 'xemacs)
+    (autoload 'c-mode "cc-mode" nil t)
+    (autoload 'font-lock-mode "font-lock" nil t)
+    (autoload 'read-kbd-macro "edmacro" nil t)
+    (autoload 'turn-on-font-lock "font-lock" nil t))
+  (autoload 'nnheader-detect-coding-region "nnheader")
+  (autoload 'std11-extract-addresses-components "nnheader")
+  (autoload 'std11-fold-region "nnheader")
+  (autoload 'std11-narrow-to-field "nnheader")
+  (autoload 'std11-unfold-region "nnheader"))
+
+(defconst dgnushack-unexporting-files
+  (append '("dgnushack.el" "dgnuspath.el" "dgnuskwds.el" "lpath.el")
+         (unless (or (condition-case code
+                         (require 'w3-parse)
+                       (error
+                        (message "No w3: %s%s, retrying..."
+                                 (error-message-string code)
+                                 (if (setq code (locate-library "w3-parse"))
+                                     (concat " (" code ")")
+                                   ""))
+                        nil))
+                     ;; Maybe mis-configured Makefile is used (e.g.
+                     ;; configured for FSFmacs but XEmacs is running).
+                     (let ((lp (delete dgnushack-w3-directory
+                                       (copy-sequence load-path))))
+                       (if (let ((load-path lp))
+                             (condition-case nil
+                                 (require 'w3-parse)
+                               (error nil)))
+                           ;; If success, fix `load-path' for compiling.
+                           (progn
+                             (setq load-path lp)
+                             (message " => fixed; W3DIR=%s"
+                                      (file-name-directory
+                                       (locate-library "w3-parse")))
+                             t)
+                         (message " => ignored")
+                         nil)))
+           '("nnultimate.el" "webmail.el" "nnwfm.el"))
+         (condition-case code
+             (progn (require 'mh-e) nil)
+           (error
+            (message "No mh-e: %s%s (ignored)"
+                     (error-message-string code)
+                     (if (setq code (locate-library "mh-e"))
+                         (concat " (" code ")")
+                       ""))
+            '("gnus-mh.el")))
+         (condition-case code
+             (progn (require 'xml) nil)
+           (error
+            (message "No xml: %s%s (ignored)"
+                     (error-message-string code)
+                     (if (setq code (locate-library "xml"))
+                         (concat " (" code ")")
+                       ""))
+            '("nnrss.el")))
+         (condition-case code
+             (progn (require 'bbdb) nil)
+           (error
+            (message "No bbdb: %s%s (ignored)"
+                     (error-message-string code)
+                     (if (setq code (locate-library "bbdb"))
+                         (concat " (" code ")")
+                       ""))
+            '("gnus-bbdb.el")))
+         (unless (featurep 'xemacs)
+           '("gnus-xmas.el" "messagexmas.el" "nnheaderxm.el"))
+         (when (and (not (featurep 'xemacs))
+                    (<= emacs-major-version 20))
+           '("smiley.el"))
+         (when (and (fboundp 'base64-decode-string)
+                    (subrp (symbol-function 'base64-decode-string)))
+           '("base64.el"))
+         (when (and (fboundp 'md5) (subrp (symbol-function 'md5)))
+           '("md5.el"))
+         (unless (boundp 'MULE)
+           '("canlock-om.el"))
+         (when (featurep 'xemacs)
+           '("gnus-load.el")))
+  "Files which will not be installed.")
+
+(defconst dgnushack-exporting-files
+  (let ((files (directory-files srcdir nil "^[^=].*\\.el$" t)))
+    (dolist (file dgnushack-unexporting-files)
+      (setq files (delete file files)))
+    (sort files 'string-lessp))
+  "Files which will be compiled and installed.")
+
+(defun dgnushack-exporting-files ()
+  "Print name of files which will be installed."
+  (princ (mapconcat 'identity dgnushack-exporting-files " ")))
+
+(defconst dgnushack-dont-compile-files
+  '("gnus-load.el"
+    "mm-bodies.el" "mm-decode.el" "mm-encode.el" "mm-extern.el"
+    "mm-partial.el" "mm-url.el" "mm-uu.el" "mm-view.el" "mml-sec.el"
+    "mml-smime.el" "mml.el" "mml1991.el" "mml2015.el")
+  "Files which should not be byte-compiled.")
 
-(setq byte-compile-warnings
-      '(free-vars unresolved callargs redefine))
+(defun dgnushack-compile-verbosely ()
+  "Call dgnushack-compile with warnings ENABLED.  If you are compiling
+patches to gnus, you should consider modifying make.bat to call
+dgnushack-compile-verbosely.  All other users should continue to use
+dgnushack-compile."
+  (dgnushack-compile t))
 
-(defun dgnushack-compile ()
+(defun dgnushack-compile (&optional warn)
   ;;(setq byte-compile-dynamic t)
+  (when (and (not (featurep 'xemacs))
+            (< emacs-major-version 21))
+    (setq max-specpdl-size 1200))
+  (unless warn
+    (setq byte-compile-warnings
+         '(free-vars unresolved callargs redefine)))
   (unless (locate-library "cus-edit")
     (error "You do not seem to have Custom installed.
 Fetch it from <URL:http://www.dina.kvl.dk/~abraham/custom/>.
@@ -61,21 +685,31 @@ You also then need to add the following to the lisp/dgnushack.el file:
      (push \"~/lisp/custom\" load-path)
 
 Modify to suit your needs."))
-  (let ((files (directory-files "." nil "^[^=].*\\.el$"))
-       (xemacs (string-match "XEmacs" emacs-version))
+
+  ;; Show `load-path'.
+  (message "load-path=(\"%s\")"
+          (mapconcat 'identity load-path "\"\n           \""))
+
+  (dolist (file dgnushack-exporting-files)
+    (setq file (expand-file-name file srcdir))
+    (when (and (file-exists-p
+               (setq elc (concat (file-name-nondirectory file) "c")))
+              (file-newer-than-file-p file elc))
+      (delete-file elc)))
+
+  ;; Avoid barfing (from gnus-xmas) because the etc directory is not yet
+  ;; installed.
+  (when (featurep 'xemacs)
+    (setq gnus-xmas-glyph-directory "dummy"))
+
+  (let ((files dgnushack-exporting-files)
        ;;(byte-compile-generate-call-tree t)
        file elc)
-    (condition-case ()
-       (require 'w3-forms)
-      (error (setq files (delete "nnweb.el" (delete "nnlistserv.el" files)))))
     (while (setq file (pop files))
-      (when (or (and (not xemacs)
-                    (not (member file '("gnus-xmas.el" "gnus-picon.el"
-                                        "messagexmas.el" "nnheaderxm.el"
-                                        "smiley.el" "x-overlay.el"))))
-               (and xemacs
-                    (not (member file '("md5.el")))))
-       (when (or (not (file-exists-p (setq elc (concat file "c"))))
+      (unless (member file dgnushack-dont-compile-files)
+       (setq file (expand-file-name file srcdir))
+       (when (or (not (file-exists-p
+                       (setq elc (concat (file-name-nondirectory file) "c"))))
                  (file-newer-than-file-p file elc))
          (ignore-errors
            (byte-compile-file file)))))))
@@ -84,5 +718,222 @@ Modify to suit your needs."))
   (require 'gnus)
   (byte-recompile-directory "." 0))
 
-;;; dgnushack.el ends here
+(defvar dgnushack-gnus-load-file
+  (if (featurep 'xemacs)
+      (expand-file-name "auto-autoloads.el" srcdir)
+    (expand-file-name "gnus-load.el" srcdir)))
+
+(defvar        dgnushack-cus-load-file
+  (if (featurep 'xemacs)
+      (expand-file-name "custom-load.el" srcdir)
+    (expand-file-name "cus-load.el" srcdir)))
+
+(defun dgnushack-make-cus-load ()
+  (when (condition-case nil
+           (load "cus-dep")
+         (error
+          (when (boundp 'MULE)
+            (if (file-exists-p "../contrib/cus-dep.el")
+                ;; Use cus-dep.el of the version of Emacs 20.7.
+                (load-file "../contrib/cus-dep.el")
+              (error "\
+You need contrib/cus-dep.el to build T-gnus with Mule 2.3@19.34; exiting.")))))
+    (let ((cusload-base-file dgnushack-cus-load-file))
+      (if (fboundp 'custom-make-dependencies)
+         (custom-make-dependencies)
+       (Custom-make-dependencies))
+      (when (featurep 'xemacs)
+       (message "Compiling %s..." dgnushack-cus-load-file)
+       (byte-compile-file dgnushack-cus-load-file)))))
 
+(defun dgnushack-make-auto-load ()
+  (require 'autoload)
+  (unless (make-autoload '(define-derived-mode child parent name
+                           "docstring" body)
+                        "file")
+    (defadvice make-autoload (around handle-define-derived-mode activate)
+      "Handle `define-derived-mode'."
+      (if (eq (car-safe (ad-get-arg 0)) 'define-derived-mode)
+         (setq ad-return-value
+               (list 'autoload
+                     (list 'quote (nth 1 (ad-get-arg 0)))
+                     (ad-get-arg 1)
+                     (nth 4 (ad-get-arg 0))
+                     t nil))
+       ad-do-it))
+    (put 'define-derived-mode 'doc-string-elt 3))
+  (let ((generated-autoload-file dgnushack-gnus-load-file)
+       (make-backup-files nil)
+       (autoload-package-name "gnus"))
+    (if (featurep 'xemacs)
+       (if (file-exists-p generated-autoload-file)
+           (delete-file generated-autoload-file))
+      (with-temp-file generated-autoload-file
+       (insert ?\014)))
+    (if (featurep 'xemacs)
+       (let ((si:message (symbol-function 'message)))
+         (defun message (fmt &rest args)
+           (cond ((and (string-equal "Generating autoloads for %s..." fmt)
+                       (file-exists-p (file-name-nondirectory (car args))))
+                  (funcall si:message
+                           fmt (file-name-nondirectory (car args))))
+                 ((string-equal "No autoloads found in %s" fmt))
+                 ((string-equal "Generating autoloads for %s...done" fmt))
+                 (t (apply si:message fmt args))))
+         (unwind-protect
+             (batch-update-autoloads)
+           (fset 'message si:message)))
+      (batch-update-autoloads))))
+
+(defun dgnushack-make-load ()
+  (unless (featurep 'xemacs)
+    (message "Generating %s..." dgnushack-gnus-load-file)
+    (with-temp-file dgnushack-gnus-load-file
+      (insert-file-contents dgnushack-cus-load-file)
+      (delete-file dgnushack-cus-load-file)
+      (goto-char (point-min))
+      (search-forward ";;; Code:")
+      (forward-line)
+      (delete-region (point-min) (point))
+      (insert "\
+;;; gnus-load.el --- automatically extracted custom dependencies and autoload
+;;
+;;; Code:
+")
+      (goto-char (point-max))
+      (if (search-backward "custom-versions-load-alist" nil t)
+         (forward-line -1)
+       (forward-line -1)
+       (while (eq (char-after) ?\;)
+         (forward-line -1))
+       (forward-line))
+      (delete-region (point) (point-max))
+      (insert "\n")
+      ;; smiley-* are duplicated. Remove them all.
+      (let ((point (point)))
+       (insert-file-contents dgnushack-gnus-load-file)
+       (goto-char point)
+       (while (search-forward "smiley-" nil t)
+         (beginning-of-line)
+         (if (looking-at "(autoload ")
+             (delete-region (point) (progn (forward-sexp) (point)))
+           (forward-line))))
+      ;;
+      (goto-char (point-max))
+      (when (search-backward "\n(provide " nil t)
+       (forward-line -1)
+       (delete-region (point) (point-max)))
+      (insert "\
+
+\(provide 'gnus-load)
+
+;;; Local Variables:
+;;; version-control: never
+;;; no-byte-compile: t
+;;; no-update-autoloads: t
+;;; End:
+;;; gnus-load.el ends here
+")
+      ))
+  (message "Compiling %s..." dgnushack-gnus-load-file)
+  (byte-compile-file dgnushack-gnus-load-file)
+  (when (featurep 'xemacs)
+    (message "Creating dummy gnus-load.el...")
+    (with-temp-file (expand-file-name "gnus-load.el")
+      (insert "\
+
+\(provide 'gnus-load)
+
+;;; Local Variables:
+;;; version-control: never
+;;; no-byte-compile: t
+;;; no-update-autoloads: t
+;;; End:
+;;; gnus-load.el ends here"))))
+
+\f
+(defconst dgnushack-info-file-regexp-en
+  (let ((names '("gnus" "message" "emacs-mime"))
+       regexp name)
+    (while (setq name (pop names))
+      (setq regexp (concat regexp "^" name "\\.info\\(-[0-9]+\\)?$"
+                          (when names "\\|"))))
+    regexp)
+  "Regexp matching English info files.")
+
+(defconst dgnushack-info-file-regexp-ja
+  (let ((names '("gnus-ja" "message-ja"))
+       regexp name)
+    (while (setq name (pop names))
+      (setq regexp (concat regexp "^" name "\\.info\\(-[0-9]+\\)?$"
+                          (when names "\\|"))))
+    regexp)
+  "Regexp matching Japanese info files.")
+
+(defun dgnushack-remove-extra-files-in-package ()
+  "Remove extra files in the lisp directory of the XEmacs package."
+  (let ((lisp-dir (expand-file-name (concat "lisp/"
+                                           ;; GNUS_PRODUCT_NAME
+                                           (cadr command-line-args-left)
+                                           "/")
+                                   ;; PACKAGEDIR
+                                   (car command-line-args-left))))
+    (setq command-line-args-left nil)
+    (when (file-directory-p lisp-dir)
+      (let (files)
+       (dolist (file dgnushack-exporting-files)
+         (setq files (nconc files (list file (concat file "c")))))
+       (dolist (file (directory-files lisp-dir nil nil t t))
+         (unless (member file files)
+           (setq file (expand-file-name file lisp-dir))
+           (message "Removing %s..." file)
+           (condition-case nil
+               (delete-file file)
+             (error nil))))))))
+
+(defun dgnushack-install-package-manifest ()
+  "Install MANIFEST file as an XEmacs package."
+  (let* ((package-dir (pop command-line-args-left))
+        (product-name (pop command-line-args-left))
+        (pkginfo-dir (expand-file-name "pkginfo" package-dir))
+        (name (expand-file-name (concat "MANIFEST." product-name)
+                                pkginfo-dir))
+        make-backup-files)
+    (unless (file-directory-p pkginfo-dir)
+      (message "Creating directory %s/..." pkginfo-dir)
+      (make-directory pkginfo-dir))
+    (message "Generating %s..." name)
+    (with-temp-file name
+      (insert "pkginfo/MANIFEST." product-name "\n")
+      (let ((lisp-dir (concat "lisp/" product-name "/"))
+           (files (sort (directory-files "." nil "\\.elc?$" t) 'string-lessp))
+           file)
+       (while (setq file (pop files))
+         (unless (member file dgnushack-unexporting-files)
+           (insert lisp-dir file "\n")))
+       (setq files
+             (sort (directory-files "../texi/" nil
+                                    (concat dgnushack-info-file-regexp-en
+                                            "\\|"
+                                            dgnushack-info-file-regexp-ja)
+                                    t)
+                   'string-lessp))
+       (while (setq file (pop files))
+         (insert "info/" file "\n"))))))
+
+\f
+(define-compiler-macro describe-key-briefly (&whole form key &optional insert)
+  (if (condition-case nil
+         (progn
+           (describe-key-briefly '((())) nil)
+           t)
+       (wrong-number-of-arguments nil);; Old Emacsen.
+       (error t))
+      form
+    (if insert
+       `(if ,insert
+            (insert (funcall 'describe-key-briefly ,key))
+          (funcall 'describe-key-briefly ,key))
+      `(funcall 'describe-key-briefly ,key))))
+
+;;; dgnushack.el ends here
diff --git a/lisp/dgnuspath.el.in b/lisp/dgnuspath.el.in
new file mode 100644 (file)
index 0000000..3ee338f
--- /dev/null
@@ -0,0 +1,18 @@
+;; -*- Emacs-Lisp -*-
+(let ((addpath
+       "@ADDITIONAL_LOAD_PATH@"
+       )
+      path paths)
+  (while (string-match "[^\0-\37:]+" addpath)
+    (setq path (file-name-as-directory
+               (expand-file-name (match-string 0 addpath)))
+         addpath (substring addpath (match-end 0)))
+    (if (string-match "apel/$" path)
+       (progn
+         (if (file-directory-p path)
+             (setq paths (nconc paths (list path))))
+         (setq path (substring path 0 (match-beginning 0)))))
+    (if (file-directory-p path)
+       (setq paths (nconc paths (list path)))))
+  (or (null paths)
+      (setq load-path (nconc paths load-path))))
diff --git a/lisp/dig.el b/lisp/dig.el
new file mode 100644 (file)
index 0000000..e71d6db
--- /dev/null
@@ -0,0 +1,188 @@
+;;; dig.el --- Domain Name System dig interface
+;; Copyright (c) 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: DNS BIND dig
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This provide an interface for "dig".
+;;
+;; For interactive use, try M-x dig and type a hostname.  Use `q' to quit
+;; dig buffer.
+;;
+;; For use in elisp programs, call `dig-invoke' and use
+;; `dig-extract-rr' to extract resource records.
+
+;;; Release history:
+
+;; 2000-10-28  posted on gnu.emacs.sources
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defgroup dig nil
+  "Dig configuration.")
+
+(defcustom dig-program "dig"
+  "Name of dig (domain information groper) binary."
+  :type 'file
+  :group 'dig)
+
+(defcustom dig-dns-server nil
+  "DNS server to query.
+If nil, use system defaults."
+  :type '(choice (const :tag "System defaults")
+                string)
+  :group 'dig)
+
+(defcustom dig-font-lock-keywords
+  '(("^;; [A-Z]+ SECTION:" 0 font-lock-keyword-face)
+    ("^;;.*" 0 font-lock-comment-face)
+    ("^; <<>>.*" 0 font-lock-type-face)
+    ("^;.*" 0 font-lock-function-name-face))
+  "Default expressions to highlight in dig mode."
+  :type 'sexp
+  :group 'dig)
+
+(defun dig-invoke (domain &optional
+                         query-type query-class query-option
+                         dig-option server)
+  "Call dig with given arguments and return buffer containing output.
+DOMAIN is a string with a DNS domain. QUERY-TYPE is an optional string
+with a DNS type. QUERY-CLASS is an optional string with a DNS class.
+QUERY-OPTION is an optional string with dig \"query options\".
+DIG-OPTIONS is an optional string with parameters for the dig program.
+SERVER is an optional string with a domain name server to query.
+
+Dig is an external program found in the BIND name server distribution,
+and is a commonly available debugging tool."
+  (let (buf cmdline)
+    (setq buf (generate-new-buffer "*dig output*"))
+    (if dig-option (push dig-option cmdline))
+    (if query-option (push query-option cmdline))
+    (if query-class (push query-class cmdline))
+    (if query-type (push query-type cmdline))
+    (push domain cmdline)
+    (if server (push (concat "@" server) cmdline)
+      (if dig-dns-server (push (concat "@" dig-dns-server) cmdline)))
+    (apply 'call-process dig-program nil buf nil cmdline)
+    buf))
+
+(defun dig-extract-rr (domain &optional type class)
+  "Extract resource records for DOMAIN, TYPE and CLASS from buffer.
+Buffer should contain output generated by `dig-invoke'."
+  (save-excursion
+    (goto-char (point-min))
+    (if (re-search-forward
+        (concat domain "\\.?[\t ]+[0-9wWdDhHmMsS]+[\t ]+"
+                (upcase (or class "IN")) "[\t ]+" (upcase (or type "A")))
+        nil t)
+       (let (b e)
+         (end-of-line)
+         (setq e (point))
+         (beginning-of-line)
+         (setq b (point))
+         (when (search-forward " (" e t)
+           (search-forward " )"))
+         (end-of-line)
+         (setq e (point))
+         (buffer-substring b e))
+      (and (re-search-forward (concat domain "\\.?[\t ]+[0-9wWdDhHmMsS]+[\t ]+"
+                                     (upcase (or class "IN"))
+                                     "[\t ]+CNAME[\t ]+\\(.*\\)$") nil t)
+          (dig-extract-rr (match-string 1) type class)))))
+
+(defun dig-rr-get-pkix-cert (rr)
+  (let (b e str)
+    (string-match "[^\t ]+[\t ]+[0-9wWdDhHmMsS]+[\t ]+IN[\t ]+CERT[\t ]+\\(1\\|PKIX\\)[\t ]+[0-9]+[\t ]+[0-9]+[\t ]+(?" rr)
+    (setq b (match-end 0))
+    (string-match ")" rr)
+    (setq e (match-beginning 0))
+    (setq str (substring rr b e))
+    (while (string-match "[\t \n\r]" str)
+      (setq str (replace-match "" nil nil str)))
+    str))
+
+;; XEmacs does it like this.  For Emacs, we have to set the
+;; `font-lock-defaults' buffer-local variable.
+(put 'dig-mode 'font-lock-defaults '(dig-font-lock-keywords t))
+
+(put 'dig-mode 'mode-class 'special)
+
+(defvar dig-mode-map nil)
+(unless dig-mode-map
+  (setq dig-mode-map (make-sparse-keymap))
+  (suppress-keymap dig-mode-map)
+
+  (define-key dig-mode-map "q" 'dig-exit))
+
+(defun dig-mode ()
+  "Major mode for displaying dig output."
+  (interactive)
+  (kill-all-local-variables)
+  (setq mode-name "dig")
+  (setq major-mode 'dig-mode)
+  (use-local-map dig-mode-map)
+  (buffer-disable-undo)
+  (unless (featurep 'xemacs)
+    (set (make-local-variable 'font-lock-defaults)
+        '(dig-font-lock-keywords t)))
+  (when (featurep 'font-lock)
+    (font-lock-set-defaults)))
+
+(defun dig-exit ()
+  "Quit dig output buffer."
+  (interactive)
+  (kill-buffer (current-buffer)))
+
+(defun dig (domain &optional
+                  query-type query-class query-option dig-option server)
+  "Query addresses of a DOMAIN using dig, by calling `dig-invoke'.
+Optional arguments are passed to `dig-invoke'."
+  (interactive "sHost: ")
+  (switch-to-buffer
+   (dig-invoke domain query-type query-class query-option dig-option server))
+  (goto-char (point-min))
+  (and (search-forward ";; ANSWER SECTION:" nil t)
+       (forward-line))
+  (dig-mode)
+  (setq buffer-read-only t)
+  (set-buffer-modified-p nil))
+
+;; named for consistency with query-dns in dns.el
+(defun query-dig (domain &optional
+                        query-type query-class query-option dig-option server)
+  "Query addresses of a DOMAIN using dig.
+It works by calling `dig-invoke' and `dig-extract-rr'.  Optional
+arguments are passed to `dig-invoke' and `dig-extract-rr'.  Returns
+nil for domain/class/type queries that results in no data."
+(let ((buffer (dig-invoke domain query-type query-class
+                         query-option dig-option server)))
+  (when buffer
+    (switch-to-buffer buffer)
+    (let ((digger (dig-extract-rr domain query-type query-class)))
+      (kill-buffer buffer)
+      digger))))
+
+(provide 'dig)
+
+;;; dig.el ends here
diff --git a/lisp/dns.el b/lisp/dns.el
new file mode 100644 (file)
index 0000000..f21bb99
--- /dev/null
@@ -0,0 +1,360 @@
+;;; dns.el --- Domain Name Service lookups
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: network
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'mm-util)
+
+(defvar dns-timeout 5
+  "How many seconds to wait when doing DNS queries.")
+
+(defvar dns-servers nil
+  "Which DNS servers to query.
+If nil, /etc/resolv.conf will be consulted.")
+
+;;; Internal code:
+
+(defvar dns-query-types
+  '((A 1)
+    (NS 2)
+    (MD 3)
+    (MF 4)
+    (CNAME 5)
+    (SOA 6)
+    (MB 7)
+    (MG 8)
+    (MR 9)
+    (NULL 10)
+    (WKS 11)
+    (PRT 12)
+    (HINFO 13)
+    (MINFO 14)
+    (MX 15)
+    (TXT 16)
+    (AXFR 252)
+    (MAILB 253)
+    (MAILA 254)
+    (* 255))
+  "Names of query types and their values.")
+
+(defvar dns-classes
+  '((IN 1)
+    (CS 2)
+    (CH 3)
+    (HS 4))
+  "Classes of queries.")
+
+(defun dns-write-bytes (value &optional length)
+  (let (bytes)
+    (dotimes (i (or length 1))
+      (push (% value 256) bytes)
+      (setq value (/ value 256)))
+    (dolist (byte bytes)
+      (insert byte))))
+
+(defun dns-read-bytes (length)
+  (let ((value 0))
+    (dotimes (i length)
+      (setq value (logior (* value 256) (following-char)))
+      (forward-char 1))
+    value))
+
+(defun dns-get (type spec)
+  (cadr (assq type spec)))
+
+(defun dns-inverse-get (value spec)
+  (let ((found nil))
+    (while (and (not found)
+               spec)
+      (if (eq value (cadr (car spec)))
+         (setq found (caar spec))
+       (pop spec)))
+    found))
+
+(defun dns-write-name (name)
+  (dolist (part (split-string name "\\."))
+    (dns-write-bytes (length part))
+    (insert part))
+  (dns-write-bytes 0))
+
+(defun dns-read-string-name (string buffer)
+  (mm-with-unibyte-buffer
+    (insert string)
+    (goto-char (point-min))
+    (dns-read-name buffer)))
+
+(defun dns-read-name (&optional buffer)
+  (let ((ended nil)
+       (name nil)
+       length)
+    (while (not ended)
+      (setq length (dns-read-bytes 1))
+      (if (= 192 (logand length (lsh 3 6)))
+         (let ((offset (+ (* (logand 63 length) 256)
+                          (dns-read-bytes 1))))
+           (save-excursion
+             (when buffer
+               (set-buffer buffer))
+             (goto-char (1+ offset))
+             (setq ended (dns-read-name buffer))))
+       (if (zerop length)
+           (setq ended t)
+         (push (buffer-substring (point)
+                                 (progn (forward-char length) (point)))
+               name))))
+    (if (stringp ended)
+       (if (null name)
+           ended
+         (concat (mapconcat 'identity (nreverse name) ".") "." ended))
+      (mapconcat 'identity (nreverse name) "."))))
+
+(defun dns-write (spec &optional tcp-p)
+  "Write a DNS packet according to SPEC.
+If TCP-P, the first two bytes of the package with be the length field."
+  (with-temp-buffer
+    (dns-write-bytes (dns-get 'id spec) 2)
+    (dns-write-bytes
+     (logior
+      (lsh (if (dns-get 'response-p spec) 1 0) -7)
+      (lsh
+       (cond
+       ((eq (dns-get 'opcode spec) 'query) 0)
+       ((eq (dns-get 'opcode spec) 'inverse-query) 1)
+       ((eq (dns-get 'opcode spec) 'status) 2)
+       (t (error "No such opcode: %s" (dns-get 'opcode spec))))
+       -3)
+      (lsh (if (dns-get 'authoritative-p spec) 1 0) -2)
+      (lsh (if (dns-get 'truncated-p spec) 1 0) -1)
+      (lsh (if (dns-get 'recursion-desired-p spec) 1 0) 0)))
+    (dns-write-bytes
+     (cond 
+      ((eq (dns-get 'response-code spec) 'no-error) 0)
+      ((eq (dns-get 'response-code spec) 'format-error) 1)
+      ((eq (dns-get 'response-code spec) 'server-failure) 2)
+      ((eq (dns-get 'response-code spec) 'name-error) 3)
+      ((eq (dns-get 'response-code spec) 'not-implemented) 4)
+      ((eq (dns-get 'response-code spec) 'refused) 5)
+      (t 0)))
+    (dns-write-bytes (length (dns-get 'queries spec)) 2)
+    (dns-write-bytes (length (dns-get 'answers spec)) 2)
+    (dns-write-bytes (length (dns-get 'authorities spec)) 2)
+    (dns-write-bytes (length (dns-get 'additionals spec)) 2)
+    (dolist (query (dns-get 'queries spec))
+      (dns-write-name (car query))
+      (dns-write-bytes (cadr (assq (or (dns-get 'type query) 'A)
+                                  dns-query-types)) 2)
+      (dns-write-bytes (cadr (assq (or (dns-get 'class query) 'IN)
+                                  dns-classes)) 2))
+    (dolist (slot '(answers authorities additionals))
+      (dolist (resource (dns-get slot spec))
+       (dns-write-name (car resource))
+      (dns-write-bytes (cadr (assq (dns-get 'type resource) dns-query-types))
+                      2)
+      (dns-write-bytes (cadr (assq (dns-get 'class resource) dns-classes))
+                      2)
+      (dns-write-bytes (dns-get 'ttl resource) 4)
+      (dns-write-bytes (length (dns-get 'data resource)) 2)
+      (insert (dns-get 'data resource))))
+    (when tcp-p
+      (goto-char (point-min))
+      (dns-write-bytes (buffer-size) 2))
+    (buffer-string)))
+
+(defun dns-read (packet)
+  (mm-with-unibyte-buffer
+    (let ((spec nil)
+         queries answers authorities additionals)
+      (insert packet)
+      (goto-char (point-min))
+      (push (list 'id (dns-read-bytes 2)) spec)
+      (let ((byte (dns-read-bytes 1)))
+       (push (list 'response-p (if (zerop (logand byte (lsh 1 7))) nil t))
+             spec)
+       (let ((opcode (logand byte (lsh 7 3))))
+         (push (list 'opcode
+                     (cond ((eq opcode 0) 'query)
+                           ((eq opcode 1) 'inverse-query)
+                           ((eq opcode 2) 'status)))
+               spec))
+       (push (list 'authoritative-p (if (zerop (logand byte (lsh 1 2)))
+                                        nil t)) spec)
+       (push (list 'truncated-p (if (zerop (logand byte (lsh 1 2))) nil t))
+             spec)
+       (push (list 'recursion-desired-p
+                   (if (zerop (logand byte (lsh 1 0))) nil t)) spec))
+      (let ((rc (logand (dns-read-bytes 1) 15)))
+       (push (list 'response-code
+                   (cond
+                    ((eq rc 0) 'no-error)
+                    ((eq rc 1) 'format-error)
+                    ((eq rc 2) 'server-failure)
+                    ((eq rc 3) 'name-error)
+                    ((eq rc 4) 'not-implemented)
+                    ((eq rc 5) 'refused)))
+             spec))
+      (setq queries (dns-read-bytes 2))
+      (setq answers (dns-read-bytes 2))
+      (setq authorities (dns-read-bytes 2))
+      (setq additionals (dns-read-bytes 2))
+      (let ((qs nil))
+       (dotimes (i queries)
+         (push (list (dns-read-name)
+                     (list 'type (dns-inverse-get (dns-read-bytes 2)
+                                                  dns-query-types))
+                     (list 'class (dns-inverse-get (dns-read-bytes 2)
+                                                   dns-classes)))
+               qs))
+       (push (list 'queries qs) spec))
+    (dolist (slot '(answers authorities additionals))
+      (let ((qs nil)
+           type)
+       (dotimes (i (symbol-value slot))
+         (push (list (dns-read-name)
+                     (list 'type
+                           (setq type (dns-inverse-get (dns-read-bytes 2)
+                                                       dns-query-types)))
+                     (list 'class (dns-inverse-get (dns-read-bytes 2)
+                                                   dns-classes))
+                     (list 'ttl (dns-read-bytes 4))
+                     (let ((length (dns-read-bytes 2)))
+                       (list 'data
+                             (dns-read-type
+                              (buffer-substring
+                               (point)
+                               (progn (forward-char length) (point)))
+                              type))))
+               qs))
+       (push (list slot qs) spec)))
+    (nreverse spec))))
+
+(defun dns-read-type (string type)
+  (let ((buffer (current-buffer))
+       (point (point)))
+    (prog1
+       (mm-with-unibyte-buffer
+         (insert string)
+         (goto-char (point-min))
+         (cond
+          ((eq type 'A)
+           (let ((bytes nil))
+             (dotimes (i 4)
+               (push (dns-read-bytes 1) bytes))
+             (mapconcat 'number-to-string (nreverse bytes) ".")))
+          ((eq type 'NS)
+           (dns-read-string-name string buffer))
+          ((eq type 'CNAME)
+           (dns-read-string-name string buffer))
+          (t string)))
+      (goto-char point))))
+
+(defun dns-parse-resolv-conf ()
+  (when (file-exists-p "/etc/resolv.conf")
+    (with-temp-buffer
+      (insert-file-contents "/etc/resolv.conf")
+      (goto-char (point-min))
+      (while (re-search-forward "^nameserver[\t ]+\\([^ \t\n]+\\)" nil t)
+       (push (match-string 1) dns-servers))
+      (setq dns-servers (nreverse dns-servers)))))
+
+;;; Interface functions.
+(eval-when-compile
+  (when (featurep 'xemacs)
+    (require 'gnus-xmas)))
+
+(defmacro dns-make-network-process (server)
+  (if (featurep 'xemacs)
+      `(let ((coding-system-for-read 'binary)
+            (coding-system-for-write 'binary))
+        (gnus-xmas-open-network-stream "dns" (current-buffer)
+                                       ,server "domain" 'udp))
+    `(let ((server ,server)
+          (coding-system-for-read 'binary)
+          (coding-system-for-write 'binary)
+          (default-process-coding-system '(binary . binary))
+          program-coding-system-alist)
+       (if (fboundp 'make-network-process)
+          (make-network-process
+           :name "dns"
+           :coding 'binary
+           :buffer (current-buffer)
+           :host server
+           :service "domain"
+           :type 'datagram)
+        ;; Older versions of Emacs doesn't have
+        ;; `make-network-process', so we fall back on opening a TCP
+        ;; connection to the DNS server.
+        (open-network-stream "dns" (current-buffer) server "domain")))))
+
+(defun query-dns (name &optional type fullp)
+  "Query a DNS server for NAME of TYPE.
+If FULLP, return the entire record returned."
+  (setq type (or type 'A))
+  (unless dns-servers
+    (dns-parse-resolv-conf))
+
+  (if (not dns-servers)
+      (message "No DNS server configuration found")
+    (mm-with-unibyte-buffer
+      (let ((process (condition-case ()
+                        (dns-make-network-process (car dns-servers))
+                      (error
+                       (message "dns: Got an error while trying to talk to %s"
+                                (car dns-servers))
+                       nil)))
+           (tcp-p (and (not (fboundp 'make-network-process))
+                       (not (featurep 'xemacs))))
+           (step 100)
+           (times (* dns-timeout 1000))
+           (id (random 65000)))
+       (when process
+         (process-send-string
+          process
+          (dns-write `((id ,id)
+                       (opcode query)
+                       (queries ((,name (type ,type))))
+                       (recursion-desired-p t))
+                     tcp-p))
+         (while (and (zerop (buffer-size))
+                     (> times 0))
+           (accept-process-output process 0 step)
+           (decf times step))
+         (ignore-errors
+           (delete-process process))
+         (when tcp-p
+           (goto-char (point-min))
+           (delete-region (point) (+ (point) 2)))
+         (unless (zerop (buffer-size))
+           (let ((result (dns-read (buffer-string))))
+             (if fullp
+                 result
+               (let ((answer (car (dns-get 'answers result))))
+                 (when (eq type (dns-get 'type answer))
+                   (dns-get 'data answer)))))))))))
+
+(provide 'dns)
+
+;;; dns.el ends here
index 4302182..e9691e1 100644 (file)
@@ -1,7 +1,11 @@
 ;;; earcon.el --- Sound effects for messages
-;; Copyright (C) 1996 Free Software Foundation
+
+;; Copyright (C) 1996, 2000, 2001, 2003 Free Software Foundation
 
 ;; Author: Steven L. Baur <steve@miranova.com>
+
+;; This file is part of GNU Emacs.
+
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
@@ -22,9 +26,6 @@
 
 ;;; Code:
 
-(if (null (boundp 'running-xemacs))
-    (defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version)))
-
 (eval-when-compile (require 'cl))
 (require 'gnus)
 (require 'gnus-audio)
   "Turn ** sounds ** into noise."
   :group 'gnus-visual)
 
-(defcustom earcon-auto-play nil
-  "*When True, automatically play sounds as well as buttonize them."
-  :type 'boolean
-  :group 'earcon)
-
 (defcustom earcon-prefix "**"
   "*String denoting the start of an earcon."
   :type 'string
@@ -54,7 +50,7 @@
     ("evil[ \t]+laugh" 1 "Evil_Laugh.au")
     ("gag\\|puke" 1 "Puke.au")
     ("snicker" 1 "Snicker.au")
-    ("meow" 1 "catmeow.au")
+    ("meow" 1 "catmeow.wav")
     ("sob\\|boohoo" 1 "cry.wav")
     ("drum[ \t]*roll" 1 "drumroll.au")
     ("blast" 1 "explosion.au")
@@ -74,8 +70,6 @@
 (defvar earcon-button-marker-list nil)
 (make-variable-buffer-local 'earcon-button-marker-list)
 
-
-
 ;;; FIXME!! clone of code from gnus-vis.el FIXME!!
 (defun earcon-article-push-button (event)
   "Check text under the mouse pointer for a callback function.
@@ -84,7 +78,7 @@ call it with the value of the `earcon-data' text property."
   (interactive "e")
   (set-buffer (window-buffer (posn-window (event-start event))))
   (let* ((pos (posn-point (event-start event)))
-         (data (get-text-property pos 'earcon-data))
+        (data (get-text-property pos 'earcon-data))
         (fun (get-text-property pos 'earcon-callback)))
     (if fun (funcall fun data))))
 
@@ -156,7 +150,6 @@ If N is negative, move backward instead."
        (setq entry nil)))
     entry))
 
-
 (defun earcon-button-push (marker)
   ;; Push button starting at MARKER.
   (save-excursion
diff --git a/lisp/flow-fill.el b/lisp/flow-fill.el
new file mode 100644 (file)
index 0000000..f72bf5b
--- /dev/null
@@ -0,0 +1,220 @@
+;;; flow-fill.el --- interprete RFC2646 "flowed" text
+
+;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <jas@pdc.kth.se>
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This implement decoding of RFC2646 formatted text, including the
+;; quoted-depth wins rules.
+
+;; Theory of operation: search for lines ending with SPC, save quote
+;; length of line, remove SPC and concatenate line with the following
+;; line if quote length of following line matches current line.
+
+;; When no further concatenations are possible, we've found a
+;; paragraph and we let `fill-region' fill the long line into several
+;; lines with the quote prefix as `fill-prefix'.
+
+;; Todo: implement basic `fill-region' (Emacs and XEmacs
+;;       implementations differ..)
+
+;;; History:
+
+;; 2000-02-17  posted on ding mailing list
+;; 2000-02-19  use `point-at-{b,e}ol' in XEmacs
+;; 2000-03-11  no compile warnings for point-at-bol stuff
+;; 2000-03-26  committed to gnus cvs
+;; 2000-10-23  don't flow "-- " lines, make "quote-depth wins" rule
+;;             work when first line is at level 0.
+;; 2002-01-12  probably incomplete encoding support
+;; 2003-12-08  started working on test harness.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defcustom fill-flowed-display-column 'fill-column
+  "Column beyond which format=flowed lines are wrapped, when displayed.
+This can be a Lisp expression or an integer."
+  :type '(choice (const :tag "Standard `fill-column'" fill-column)
+                (const :tag "Fit Window" (- (window-width) 5))
+                (sexp)
+                (integer)))
+
+(defcustom fill-flowed-encode-column 66
+  "Column beyond which format=flowed lines are wrapped, in outgoing messages.
+This can be a Lisp expression or an integer.
+RFC 2646 suggests 66 characters for readability."
+  :type '(choice (const :tag "Standard fill-column" fill-column)
+                (const :tag "RFC 2646 default (66)" 66)
+                (sexp)
+                (integer)))
+
+(eval-and-compile
+  (defalias 'fill-flowed-point-at-bol
+    (if (fboundp 'point-at-bol)
+       'point-at-bol
+      'line-beginning-position))
+
+  (defalias 'fill-flowed-point-at-eol
+    (if (fboundp 'point-at-eol)
+       'point-at-eol
+      'line-end-position)))
+
+;;;###autoload
+(defun fill-flowed-encode (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    ;; No point in doing this unless hard newlines is used.
+    (when use-hard-newlines
+      (let ((start (point-min)) end)
+       ;; Go through each paragraph, filling it and adding SPC
+       ;; as the last character on each line.
+       (while (setq end (text-property-any start (point-max) 'hard 't))
+         (let ((fill-column (eval fill-flowed-encode-column)))
+           (fill-region start end t 'nosqueeze 'to-eop))
+         (goto-char start)
+         ;; `fill-region' probably distorted end.
+         (setq end (text-property-any start (point-max) 'hard 't))
+         (while (and (< (point) end)
+                     (re-search-forward "$" (1- end) t))
+           (insert " ")
+           (setq end (1+ end))
+           (forward-char))
+         (goto-char (setq start (1+ end)))))
+      t)))
+
+;;;###autoload
+(defun fill-flowed (&optional buffer)
+  (save-excursion
+    (set-buffer (or (current-buffer) buffer))
+    (goto-char (point-min))
+    (while (re-search-forward " $" nil t)
+      (when (save-excursion
+             (beginning-of-line)
+             (looking-at "^\\(>*\\)\\( ?\\)"))
+       (let ((quote (match-string 1))
+             sig)
+         (if (string= quote "")
+             (setq quote nil))
+         (when (and quote (string= (match-string 2) ""))
+           (save-excursion
+             ;; insert SP after quote for pleasant reading of quoted lines
+             (beginning-of-line)
+             (when (> (skip-chars-forward ">") 0)
+               (insert " "))))
+         ;; XXX slightly buggy handling of "-- "
+         (while (and (save-excursion
+                       (ignore-errors (backward-char 3))
+                       (setq sig (looking-at "-- "))
+                       (looking-at "[^-][^-] "))
+                     (save-excursion
+                       (unless (eobp)
+                         (forward-char 1)
+                         (looking-at (format "^\\(%s\\)\\([^>\n\r]\\)"
+                                             (or quote " ?"))))))
+           (save-excursion
+             (replace-match (if (string= (match-string 2) " ")
+                                "" "\\2")))
+           (backward-delete-char -1)
+           (end-of-line))
+         (unless sig
+           (condition-case nil
+               (let ((fill-prefix (when quote (concat quote " ")))
+                     (fill-column (eval fill-flowed-display-column))
+                     filladapt-mode)
+                 (fill-region (fill-flowed-point-at-bol)
+                              (min (1+ (fill-flowed-point-at-eol))
+                                   (point-max))
+                              'left 'nosqueeze))
+             (error
+              (forward-line 1)
+              nil))))))))
+
+;; Test vectors.
+
+(eval-when-compile
+  (defvar show-trailing-whitespace))
+
+(defvar fill-flowed-encode-tests
+  '(
+    ;; The syntax of each list element is:
+    ;; (INPUT . EXPECTED-OUTPUT)
+    ("> Thou villainous ill-breeding spongy dizzy-eyed 
+> reeky elf-skinned pigeon-egg! 
+>> Thou artless swag-bellied milk-livered 
+>> dismal-dreaming idle-headed scut!
+>>> Thou errant folly-fallen spleeny reeling-ripe 
+>>> unmuzzled ratsbane!
+>>>> Henceforth, the coding style is to be strictly 
+>>>> enforced, including the use of only upper case.
+>>>>> I've noticed a lack of adherence to the coding 
+>>>>> styles, of late.
+>>>>>> Any complaints?
+" . "> Thou villainous ill-breeding spongy dizzy-eyed reeky elf-skinned
+> pigeon-egg! 
+>> Thou artless swag-bellied milk-livered dismal-dreaming idle-headed
+>> scut!
+>>> Thou errant folly-fallen spleeny reeling-ripe unmuzzled ratsbane!
+>>>> Henceforth, the coding style is to be strictly enforced,
+>>>> including the use of only upper case.
+>>>>> I've noticed a lack of adherence to the coding styles, of late.
+>>>>>> Any complaints?
+")
+;    ("
+;> foo
+;> 
+;> 
+;> bar
+;" . "
+;> foo bar
+;")
+    ))
+
+(defun fill-flowed-test ()
+  (interactive "")
+  (switch-to-buffer (get-buffer-create "*Format=Flowed test output*"))
+  (erase-buffer)
+  (setq show-trailing-whitespace t)
+  (dolist (test fill-flowed-encode-tests)
+    (let (start output)
+      (insert "***** BEGIN TEST INPUT *****\n")
+      (insert (car test))
+      (insert "***** END TEST INPUT *****\n\n")
+      (insert "***** BEGIN TEST OUTPUT *****\n")
+      (setq start (point))
+      (insert (car test))
+      (save-restriction
+       (narrow-to-region start (point))
+       (fill-flowed))
+      (setq output (buffer-substring start (point-max)))
+      (insert "***** END TEST OUTPUT *****\n")
+      (unless (string= output (cdr test))
+       (insert "\n***** BEGIN TEST EXPECTED OUTPUT *****\n")
+       (insert (cdr test))
+       (insert "***** END TEST EXPECTED OUTPUT *****\n"))
+      (insert "\n\n")))
+  (goto-char (point-max)))
+
+(provide 'flow-fill)
+
+;;; flow-fill.el ends here
diff --git a/lisp/format-spec.el b/lisp/format-spec.el
new file mode 100644 (file)
index 0000000..6cd39ed
--- /dev/null
@@ -0,0 +1,71 @@
+;;; format-spec.el --- functions for formatting arbitrary formatting strings
+;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: tools
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defun format-spec (format specification)
+  "Return a string based on FORMAT and SPECIFICATION.
+FORMAT is a string containing `format'-like specs like \"bash %u %k\",
+while SPECIFICATION is an alist mapping from format spec characters
+to values."
+  (with-temp-buffer
+    (insert format)
+    (goto-char (point-min))
+    (while (search-forward "%" nil t)
+      (cond
+       ;; Quoted percent sign.
+       ((eq (char-after) ?%)
+       (delete-char 1))
+       ;; Valid format spec.
+       ((looking-at "\\([-0-9.]*\\)\\([a-zA-Z]\\)")
+       (let* ((num (match-string 1))
+              (spec (string-to-char (match-string 2)))
+              (val (cdr (assq spec specification))))
+         (delete-region (1- (match-beginning 0)) (match-end 0))
+         (unless val
+           (error "Invalid format character: %s" spec))
+         (insert (format (concat "%" num "s") val))))
+       ;; Signal an error on bogus format strings.
+       (t
+       (error "Invalid format string"))))
+    (buffer-string)))
+
+(defun format-spec-make (&rest pairs)
+  "Return an alist suitable for use in `format-spec' based on PAIRS.
+PAIRS is a list where every other element is a character and a value,
+starting with a character."
+  (let (alist)
+    (while pairs
+      (unless (cdr pairs)
+       (error "Invalid list of pairs"))
+      (push (cons (car pairs) (cadr pairs)) alist)
+      (setq pairs (cddr pairs)))
+    (nreverse alist)))
+
+(provide 'format-spec)
+
+;;; format-spec.el ends here
index f8f353d..4b2eea2 100644 (file)
@@ -1,7 +1,9 @@
-;;; gnus-agent.el --- unplugged support for Gnus
-;; Copyright (C) 1997,98 Free Software Foundation, Inc.
+;;; gnus-agent.el --- unplugged support for Semi-gnus
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'gnus)
 (require 'gnus-cache)
+(require 'nnmail)
 (require 'nnvirtual)
 (require 'gnus-sum)
-(eval-when-compile (require 'cl))
+(require 'gnus-score)
+(require 'gnus-srvr)
+(require 'gnus-util)
+(eval-when-compile
+  (if (featurep 'xemacs)
+      (require 'itimer)
+    (require 'timer))
+  (require 'gnus-group))
+
+(eval-and-compile
+  (autoload 'gnus-server-update-server "gnus-srvr")
+  (autoload 'gnus-agent-customize-category "gnus-cus")
+)
 
 (defcustom gnus-agent-directory (nnheader-concat gnus-directory "agent/")
   "Where the Gnus agent will store its files."
   :group 'gnus-agent
   :type 'hook)
 
+(defcustom gnus-agent-fetched-hook nil
+  "Hook run when finished fetching articles."
+  :group 'gnus-agent
+  :type 'hook)
+
 (defcustom gnus-agent-handle-level gnus-level-subscribed
   "Groups on levels higher than this variable will be ignored by the Agent."
   :group 'gnus-agent
   :type 'integer)
 
+(defcustom gnus-agent-expire-days 7
+  "Read articles older than this will be expired.
+If you wish to disable Agent expiring, see `gnus-agent-enable-expiration'."
+  :group 'gnus-agent
+  :type '(number :tag "days"))
+
+(defcustom gnus-agent-expire-all nil
+  "If non-nil, also expire unread, ticked and dormant articles.
+If nil, only read articles will be expired."
+  :group 'gnus-agent
+  :type 'boolean)
+
+(defcustom gnus-agent-group-mode-hook nil
+  "Hook run in Agent group minor modes."
+  :group 'gnus-agent
+  :type 'hook)
+
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+  (add-hook 'gnus-agent-group-mode-hook 'gnus-xmas-agent-group-menu-add))
+
+(defcustom gnus-agent-summary-mode-hook nil
+  "Hook run in Agent summary minor modes."
+  :group 'gnus-agent
+  :type 'hook)
+
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+  (add-hook 'gnus-agent-summary-mode-hook 'gnus-xmas-agent-summary-menu-add))
+
+(defcustom gnus-agent-server-mode-hook nil
+  "Hook run in Agent summary minor modes."
+  :group 'gnus-agent
+  :type 'hook)
+
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+  (add-hook 'gnus-agent-server-mode-hook 'gnus-xmas-agent-server-menu-add))
+
+(defcustom gnus-agent-confirmation-function 'y-or-n-p
+  "Function to confirm when error happens."
+  :version "21.1"
+  :group 'gnus-agent
+  :type 'function)
+
+(defcustom gnus-agent-large-newsgroup nil
+  "*The number of articles which indicates a large newsgroup.
+If the number of unread articles exceeds it, The number of articles to be
+fetched will be limited to it. If not a positive integer, never consider it."
+  :group 'gnus-agent
+  :type '(choice (const nil)
+                (integer :tag "Number")))
+
+(defcustom gnus-agent-synchronize-flags 'ask
+  "Indicate if flags are synchronized when you plug in.
+If this is `ask' the hook will query the user."
+  :version "21.1"
+  :type '(choice (const :tag "Always" t)
+                (const :tag "Never" nil)
+                (const :tag "Ask" ask))
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-go-online 'ask
+  "Indicate if offline servers go online when you plug in.
+If this is `ask' the hook will query the user."
+  :version "21.1"
+  :type '(choice (const :tag "Always" t)
+                (const :tag "Never" nil)
+                (const :tag "Ask" ask))
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-mark-unread-after-downloaded t
+  "Indicate whether to mark articles unread after downloaded."
+  :version "21.1"
+  :type 'boolean
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-download-marks '(download)
+  "Marks for downloading."
+  :version "21.1"
+  :type '(repeat (symbol :tag "Mark"))
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-consider-all-articles nil
+  "When non-`nil', the agent will let the agent predicate decide
+whether articles need to be downloaded or not, for all articles.  When
+`nil', the default, the agent will only let the predicate decide
+whether unread articles are downloaded or not.  If you enable this,
+groups with large active ranges may open slower and you may also want
+to look into the agent expiry settings to block the expiration of
+read articles as they would just be downloaded again."
+  :version "21.4"
+  :type 'boolean
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-max-fetch-size 10000000 ;; 10 Mb
+  "Chunk size for `gnus-agent-fetch-session'.
+The function will split its article fetches into chunks smaller than
+this limit."
+  :group 'gnus-agent
+  :type 'integer)
+
+(defcustom gnus-agent-enable-expiration 'ENABLE
+  "The default expiration state for each group.
+When set to ENABLE, the default, `gnus-agent-expire' will expire old
+contents from a group's local storage.  This value may be overridden
+to disable expiration in specific categories, topics, and groups.  Of
+course, you could change gnus-agent-enable-expiration to DISABLE then
+enable expiration per categories, topics, and groups."
+  :group 'gnus-agent
+  :type '(radio (const :format "Enable " ENABLE)
+                (const :format "Disable " DISABLE)))
+
+(defcustom gnus-agent-expire-unagentized-dirs t
+  "*Whether expiration should expire in unagentized directories.
+Have gnus-agent-expire scan the directories under
+\(gnus-agent-directory) for groups that are no longer agentized.
+When found, offer to remove them."
+  :type 'boolean
+  :group 'gnus-agent)
+
+(defcustom gnus-agent-auto-agentize-methods '(nntp nnimap)
+  "Initially, all servers from these methods are agentized.
+The user may remove or add servers using the Server buffer.
+See Info node `(gnus)Server Buffer'."
+  :type '(repeat symbol)
+  :group 'gnus-agent)
+
 ;;; Internal variables
 
 (defvar gnus-agent-history-buffers nil)
 (defvar gnus-agent-buffer-alist nil)
-(defvar gnus-agent-article-alist nil)
+(defvar gnus-agent-article-alist nil
+  "An assoc list identifying the articles whose headers have been fetched.  
+If successfully fetched, these headers will be stored in the group's overview
+file.  The key of each assoc pair is the article ID, the value of each assoc
+pair is a flag indicating whether the identified article has been downloaded
+\(gnus-agent-fetch-articles sets the value to the day of the download).
+NOTES:
+1) The last element of this list can not be expired as some 
+   routines (for example, get-agent-fetch-headers) use the last
+   value to track which articles have had their headers retrieved.
+2) The function `gnus-agent-regenerate' may destructively modify the value.")
 (defvar gnus-agent-group-alist nil)
-(defvar gnus-agent-covered-methods nil)
 (defvar gnus-category-alist nil)
 (defvar gnus-agent-current-history nil)
 (defvar gnus-agent-overview-buffer nil)
 (defvar gnus-agent-spam-hashtb nil)
 (defvar gnus-agent-file-name nil)
 (defvar gnus-agent-send-mail-function nil)
-(defvar gnus-agent-article-file-coding-system 'no-conversion)
+(defvar gnus-agent-file-coding-system 'raw-text)
+(defvar gnus-agent-file-loading-cache nil)
+(defvar gnus-agent-file-header-cache nil)
 
 ;; Dynamic variables
 (defvar gnus-headers)
   (setq gnus-agent t)
   (gnus-agent-read-servers)
   (gnus-category-read)
-  (setq gnus-agent-overview-buffer
-       (get-buffer-create " *Gnus agent overview*"))
+  (gnus-agent-create-buffer)
   (add-hook 'gnus-group-mode-hook 'gnus-agent-mode)
   (add-hook 'gnus-summary-mode-hook 'gnus-agent-mode)
   (add-hook 'gnus-server-mode-hook 'gnus-agent-mode))
 
+(defun gnus-agent-create-buffer ()
+  (if (gnus-buffer-live-p gnus-agent-overview-buffer)
+      t
+    (setq gnus-agent-overview-buffer
+         (gnus-get-buffer-create " *Gnus agent overview*"))
+    (with-current-buffer gnus-agent-overview-buffer
+      (set-buffer-multibyte t))
+    nil))
+
 (gnus-add-shutdown 'gnus-close-agent 'gnus)
 
 (defun gnus-close-agent ()
-  (setq gnus-agent-covered-methods nil
-       gnus-category-predicate-cache nil
+  (setq gnus-category-predicate-cache nil
        gnus-category-group-cache nil
        gnus-agent-spam-hashtb nil)
   (gnus-kill-buffer gnus-agent-overview-buffer))
 
 (defun gnus-agent-read-file (file)
   "Load FILE and do a `read' there."
-  (nnheader-temp-write nil
+  (with-temp-buffer
     (ignore-errors
-      (insert-file-contents file)
+      (nnheader-insert-file-contents file)
       (goto-char (point-min))
       (read (current-buffer)))))
 
            (cadr gnus-command-method))))
 
 (defsubst gnus-agent-directory ()
-  "Path of the Gnus agent directory."
+  "The name of the Gnus agent directory."
   (nnheader-concat gnus-agent-directory
                   (nnheader-translate-file-chars (gnus-agent-method)) "/"))
 
 (defun gnus-agent-lib-file (file)
-  "The full path of the Gnus agent library FILE."
-  (concat (gnus-agent-directory) "agent.lib/" file))
+  "The full name of the Gnus agent library FILE."
+  (expand-file-name file
+                   (file-name-as-directory
+                    (expand-file-name "agent.lib" (gnus-agent-directory)))))
+
+(defun gnus-agent-cat-set-property (category property value)
+  (if value
+      (setcdr (or (assq property category)
+              (let ((cell (cons property nil)))
+                    (setcdr category (cons cell (cdr category)))
+                    cell)) value)
+    (let ((category category))
+      (while (cond ((eq property (caadr category))
+                    (setcdr category (cddr category))
+                    nil)
+                   (t
+                    (setq category (cdr category)))))))
+  category)
+
+(eval-when-compile
+  (defmacro gnus-agent-cat-defaccessor (name prop-name)
+    "Define accessor and setter methods for manipulating a list of the form
+\(NAME (PROPERTY1 VALUE1) ... (PROPERTY_N VALUE_N)).
+Given the call (gnus-agent-cat-defaccessor func PROPERTY1), the list may be
+manipulated as follows:
+  (func LIST): Returns VALUE1
+  (setf (func LIST) NEW_VALUE1): Replaces VALUE1 with NEW_VALUE1."
+    `(progn (defmacro ,name (category)
+              (list (quote cdr) (list (quote assq)
+                                      (quote (quote ,prop-name)) category)))
+
+            (define-setf-method ,name (category)
+              (let* ((--category--temp-- (make-symbol "--category--"))
+                     (--value--temp-- (make-symbol "--value--")))
+                (list (list --category--temp--) ; temporary-variables
+                      (list category)   ; value-forms
+                      (list --value--temp--) ; store-variables
+                      (let* ((category --category--temp--) ; store-form
+                             (value --value--temp--))
+                        (list (quote gnus-agent-cat-set-property)
+                              category
+                              (quote (quote ,prop-name))
+                              value))
+                      (list (quote ,name) --category--temp--) ; access-form
+                      )))))
+  )
+
+(defmacro gnus-agent-cat-name (category)
+  `(car ,category))
+
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-days-until-old             agent-days-until-old)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-enable-expiration          agent-enable-expiration)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-groups                     agent-groups)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-high-score                 agent-high-score)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-length-when-long           agent-length-when-long)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-length-when-short          agent-length-when-short)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-low-score                  agent-low-score)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-predicate                  agent-predicate)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-score-file                 agent-score-file)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-disable-undownloaded-faces agent-disable-undownloaded-faces)
+(gnus-agent-cat-defaccessor
+ gnus-agent-cat-enable-undownloaded-faces agent-enable-undownloaded-faces)
+
+(eval-when-compile
+  (defsetf gnus-agent-cat-groups (category) (groups)
+    (list 'gnus-agent-set-cat-groups category groups)))
+
+(defun gnus-agent-set-cat-groups (category groups)
+  (unless (eq groups 'ignore)
+    (let ((new-g groups)
+          (old-g (gnus-agent-cat-groups category)))
+      (cond ((eq new-g old-g)
+             ;; gnus-agent-add-group is fiddling with the group
+             ;; list. Still, Im done.
+             nil
+             )
+            ((eq new-g (cdr old-g))
+             ;; gnus-agent-add-group is fiddling with the group list
+             (setcdr (or (assq 'agent-groups category)
+                         (let ((cell (cons 'agent-groups nil)))
+                           (setcdr category (cons cell (cdr category)))
+                           cell)) new-g))
+            (t
+             (let ((groups groups))
+               (while groups
+                 (let* ((group        (pop groups))
+                        (old-category (gnus-group-category group)))
+                   (if (eq category old-category)
+                       nil
+                     (setf (gnus-agent-cat-groups old-category)
+                           (delete group (gnus-agent-cat-groups
+                                          old-category))))))
+               ;; Purge cache as preceeding loop invalidated it.
+               (setq gnus-category-group-cache nil))
+
+             (setcdr (or (assq 'agent-groups category)
+                         (let ((cell (cons 'agent-groups nil)))
+                           (setcdr category (cons cell (cdr category)))
+                           cell)) groups))))))
+
+(defsubst gnus-agent-cat-make (name &optional default-agent-predicate)
+  (list name `(agent-predicate . ,(or default-agent-predicate 'false))))
 
 ;;; Fetching setup functions.
 
 (defun gnus-agent-start-fetch ()
   "Initialize data structures for efficient fetching."
-  (gnus-agent-open-history)
-  (setq gnus-agent-current-history (gnus-agent-history-buffer)))
+  (gnus-agent-create-buffer))
 
 (defun gnus-agent-stop-fetch ()
   "Save all data structures and clean up."
-  (gnus-agent-save-history)
-  (gnus-agent-close-history)
   (setq gnus-agent-spam-hashtb nil)
   (save-excursion
     (set-buffer nntp-server-buffer)
 (defmacro gnus-agent-with-fetch (&rest forms)
   "Do FORMS safely."
   `(unwind-protect
-       (progn
+       (let ((gnus-agent-fetching t))
         (gnus-agent-start-fetch)
         ,@forms)
      (gnus-agent-stop-fetch)))
 (put 'gnus-agent-with-fetch 'lisp-indent-function 0)
 (put 'gnus-agent-with-fetch 'edebug-form-spec '(body))
 
+(defmacro gnus-agent-append-to-list (tail value)
+  `(setq ,tail (setcdr ,tail (cons ,value nil))))
+
+(defmacro gnus-agent-message (level &rest args)
+  `(if (<= ,level gnus-verbose)
+       (message ,@args)))
+
 ;;;
 ;;; Mode infestation
 ;;;
       (push (cons mode (symbol-value (intern (format "gnus-agent-%s-mode-map"
                                                     buffer))))
            minor-mode-map-alist))
-    (gnus-agent-toggle-plugged gnus-plugged)
-    (gnus-run-hooks 'gnus-agent-mode-hook)))
+    (when (eq major-mode 'gnus-group-mode)
+      (let ((init-plugged gnus-plugged)
+            (gnus-agent-go-online nil))
+        ;; g-a-t-p does nothing when gnus-plugged isn't changed.
+        ;; Therefore, make certain that the current value does not
+        ;; match the desired initial value.
+        (setq gnus-plugged :unknown)
+        (gnus-agent-toggle-plugged init-plugged)))
+    (gnus-run-hooks 'gnus-agent-mode-hook
+                   (intern (format "gnus-agent-%s-mode-hook" buffer)))))
 
 (defvar gnus-agent-group-mode-map (make-sparse-keymap))
 (gnus-define-keys gnus-agent-group-mode-map
   "Jc" gnus-enter-category-buffer
   "Jj" gnus-agent-toggle-plugged
   "Js" gnus-agent-fetch-session
-  "JS" gnus-group-send-drafts
-  "Ja" gnus-agent-add-group)
+  "JY" gnus-agent-synchronize-flags
+  "JS" gnus-group-send-queue
+  "Ja" gnus-agent-add-group
+  "Jr" gnus-agent-remove-group
+  "Jo" gnus-agent-toggle-group-plugged)
 
 (defun gnus-agent-group-make-menu-bar ()
   (unless (boundp 'gnus-agent-group-menu)
      gnus-agent-group-menu gnus-agent-group-mode-map ""
      '("Agent"
        ["Toggle plugged" gnus-agent-toggle-plugged t]
+       ["Toggle group plugged" gnus-agent-toggle-group-plugged t]
        ["List categories" gnus-enter-category-buffer t]
-       ["Send drafts" gnus-group-send-drafts gnus-plugged]
+       ["Add (current) group to category" gnus-agent-add-group t]
+       ["Remove (current) group from category" gnus-agent-remove-group t]
+       ["Send queue" gnus-group-send-queue gnus-plugged]
        ("Fetch"
        ["All" gnus-agent-fetch-session gnus-plugged]
-       ["Group" gnus-agent-fetch-group gnus-plugged])))))
+       ["Group" gnus-agent-fetch-group gnus-plugged])
+       ["Synchronize flags" gnus-agent-synchronize-flags t]
+       ))))
 
 (defvar gnus-agent-summary-mode-map (make-sparse-keymap))
 (gnus-define-keys gnus-agent-summary-mode-map
   "Jj" gnus-agent-toggle-plugged
+  "Ju" gnus-agent-summary-fetch-group
+  "JS" gnus-agent-fetch-group
+  "Js" gnus-agent-summary-fetch-series
   "J#" gnus-agent-mark-article
   "J\M-#" gnus-agent-unmark-article
   "@" gnus-agent-toggle-mark
        ["Mark as downloadable" gnus-agent-mark-article t]
        ["Unmark as downloadable" gnus-agent-unmark-article t]
        ["Toggle mark" gnus-agent-toggle-mark t]
+       ["Fetch downloadable" gnus-agent-summary-fetch-group t]
        ["Catchup undownloaded" gnus-agent-catchup t]))))
 
 (defvar gnus-agent-server-mode-map (make-sparse-keymap))
        ["Add" gnus-agent-add-server t]
        ["Remove" gnus-agent-remove-server t]))))
 
-(defun gnus-agent-toggle-plugged (plugged)
+(defun gnus-agent-make-mode-line-string (string mouse-button mouse-func)
+  (if (and (fboundp 'propertize)
+          (fboundp 'make-mode-line-mouse-map))
+      (propertize string 'local-map
+                 (make-mode-line-mouse-map mouse-button mouse-func))
+    string))
+
+(defun gnus-agent-toggle-plugged (set-to)
   "Toggle whether Gnus is unplugged or not."
   (interactive (list (not gnus-plugged)))
-  (if plugged
-      (progn
-       (setq gnus-plugged plugged)
-       (gnus-run-hooks 'gnus-agent-plugged-hook)
-       (setcar (cdr gnus-agent-mode-status) " Plugged"))
-    (gnus-agent-close-connections)
-    (setq gnus-plugged plugged)
-    (gnus-run-hooks 'gnus-agent-unplugged-hook)
-    (setcar (cdr gnus-agent-mode-status) " Unplugged"))
+  (cond ((eq set-to gnus-plugged)
+         nil)
+        (set-to
+         (setq gnus-plugged set-to)
+         (gnus-run-hooks 'gnus-agent-plugged-hook)
+         (setcar (cdr gnus-agent-mode-status)
+                 (gnus-agent-make-mode-line-string " Plugged"
+                                                   'mouse-2
+                                                   'gnus-agent-toggle-plugged))
+         (gnus-agent-go-online gnus-agent-go-online)
+         (gnus-agent-possibly-synchronize-flags))
+        (t
+         (gnus-agent-close-connections)
+         (setq gnus-plugged set-to)
+         (gnus-run-hooks 'gnus-agent-unplugged-hook)
+         (setcar (cdr gnus-agent-mode-status)
+                 (gnus-agent-make-mode-line-string " Unplugged"
+                                                   'mouse-2
+                                                   'gnus-agent-toggle-plugged))))
+  (force-mode-line-update)
   (set-buffer-modified-p t))
 
+(defmacro gnus-agent-while-plugged (&rest body)
+  `(let ((original-gnus-plugged gnus-plugged))
+    (unwind-protect
+        (progn (gnus-agent-toggle-plugged t)
+               ,@body)
+      (gnus-agent-toggle-plugged original-gnus-plugged))))
+
+(put 'gnus-agent-while-plugged 'lisp-indent-function 0)
+(put 'gnus-agent-while-plugged 'edebug-form-spec '(body))
+
 (defun gnus-agent-close-connections ()
   "Close all methods covered by the Gnus agent."
-  (let ((methods gnus-agent-covered-methods))
+  (let ((methods (gnus-agent-covered-methods)))
     (while methods
       (gnus-close-server (pop methods)))))
 
   (gnus))
 
 ;;;###autoload
+(defun gnus-slave-unplugged (&optional arg)
+  "Read news as a slave unplugged."
+  (interactive "P")
+  (setq gnus-plugged nil)
+  (gnus arg nil 'slave))
+
+;;;###autoload
 (defun gnus-agentize ()
   "Allow Gnus to be an offline newsreader.
-The normal usage of this command is to put the following as the
-last form in your `.gnus.el' file:
 
-\(gnus-agentize)
+The gnus-agentize function is now called internally by gnus when
+gnus-agent is set.  If you wish to avoid calling gnus-agentize,
+customize gnus-agent to nil.
 
-This will modify the `gnus-before-startup-hook', `gnus-post-method',
-and `message-send-mail-function' variables, and install the Gnus
-agent minor mode in all Gnus buffers."
+This will modify the `gnus-setup-news-hook', and
+`message-send-mail-real-function' variables, and install the Gnus agent
+minor mode in all Gnus buffers."
   (interactive)
   (gnus-open-agent)
   (add-hook 'gnus-setup-news-hook 'gnus-agent-queue-setup)
-  (unless gnus-agent-send-mail-function 
-    (setq gnus-agent-send-mail-function message-send-mail-function
-         message-send-mail-function 'gnus-agent-send-mail))
-  (unless gnus-agent-covered-methods
-    (setq gnus-agent-covered-methods (list gnus-select-method))))
-
-(defun gnus-agent-queue-setup ()
-  "Make sure the queue group exists."
-  (unless (gnus-gethash "nndraft:queue" gnus-newsrc-hashtb)
-    (gnus-request-create-group "queue" '(nndraft ""))
+  (unless gnus-agent-send-mail-function
+    (setq gnus-agent-send-mail-function
+         (or message-send-mail-real-function
+             message-send-mail-function)
+         message-send-mail-real-function 'gnus-agent-send-mail))
+
+  ;; If the servers file doesn't exist, auto-agentize some servers and
+  ;; save the servers file so this auto-agentizing isn't invoked
+  ;; again.
+  (unless (file-exists-p (nnheader-concat gnus-agent-directory "lib/servers"))
+    (gnus-message 3 "First time agent user, agentizing remote groups...")
+    (mapc
+     (lambda (server-or-method)
+       (let ((method (gnus-server-to-method server-or-method)))
+        (when (memq (car method)
+                    gnus-agent-auto-agentize-methods)
+          (push (gnus-method-to-server method)
+                gnus-agent-covered-methods)
+          (setq gnus-agent-method-p-cache nil))))
+     (cons gnus-select-method gnus-secondary-select-methods))
+    (gnus-agent-write-servers)))
+
+(defun gnus-agent-queue-setup (&optional group-name)
+  "Make sure the queue group exists.
+Optional arg GROUP-NAME allows to specify another group."
+  (unless (gnus-gethash (format "nndraft:%s" (or group-name "queue"))
+                       gnus-newsrc-hashtb)
+    (gnus-request-create-group (or group-name "queue") '(nndraft ""))
     (let ((gnus-level-default-subscribed 1))
-      (gnus-subscribe-group "nndraft:queue" nil '(nndraft "")))
+      (gnus-subscribe-group (format "nndraft:%s" (or group-name "queue"))
+                           nil '(nndraft "")))
     (gnus-group-set-parameter
-     "nndraft:queue" 'gnus-dummy '((gnus-draft-mode)))))
+     (format "nndraft:%s" (or group-name "queue"))
+     'gnus-dummy '((gnus-draft-mode)))))
 
 (defun gnus-agent-send-mail ()
   (if gnus-plugged
@@ -303,26 +661,83 @@ agent minor mode in all Gnus buffers."
     (re-search-forward
      (concat "^" (regexp-quote mail-header-separator) "\n"))
     (replace-match "\n")
-    (gnus-request-accept-article "nndraft:queue")))
+    (gnus-agent-insert-meta-information 'mail)
+    (gnus-request-accept-article "nndraft:queue" nil t t)))
+
+(defun gnus-agent-insert-meta-information (type &optional method)
+  "Insert meta-information into the message that says how it's to be posted.
+TYPE can be either `mail' or `news'.  If the latter, then METHOD can
+be a select method."
+  (save-excursion
+    (message-remove-header gnus-agent-meta-information-header)
+    (goto-char (point-min))
+    (insert gnus-agent-meta-information-header ": "
+           (symbol-name type) " " (format "%S" method)
+           "\n")
+    (forward-char -1)
+    (while (search-backward "\n" nil t)
+      (replace-match "\\n" t t))))
+
+(defun gnus-agent-restore-gcc ()
+  "Restore GCC field from saved header."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward (concat gnus-agent-gcc-header ":") nil t)
+      (replace-match "Gcc:" 'fixedcase))))
+
+(defun gnus-agent-any-covered-gcc ()
+  (save-restriction
+    (message-narrow-to-headers)
+    (let* ((gcc (mail-fetch-field "gcc" nil t))
+          (methods (and gcc
+                        (mapcar 'gnus-inews-group-method
+                                (message-unquote-tokens
+                                 (message-tokenize-header
+                                  gcc " ,")))))
+          covered)
+      (while (and (not covered) methods)
+       (setq covered (gnus-agent-method-p (car methods))
+             methods (cdr methods)))
+      covered)))
+
+;;;###autoload
+(defun gnus-agent-possibly-save-gcc ()
+  "Save GCC if Gnus is unplugged."
+  (when (and (not gnus-plugged) (gnus-agent-any-covered-gcc))
+    (save-excursion
+      (goto-char (point-min))
+      (let ((case-fold-search t))
+       (while (re-search-forward "^gcc:" nil t)
+         (replace-match (concat gnus-agent-gcc-header ":") 'fixedcase))))))
+
+(defun gnus-agent-possibly-do-gcc ()
+  "Do GCC if Gnus is plugged."
+  (when (or gnus-plugged (not (gnus-agent-any-covered-gcc)))
+    (gnus-inews-do-gcc)))
 
 ;;;
 ;;; Group mode commands
 ;;;
 
 (defun gnus-agent-fetch-groups (n)
-  "Put all new articles in the current groups into the agent."
+  "Put all new articles in the current groups into the Agent."
   (interactive "P")
+  (unless gnus-plugged
+    (error "Groups can't be fetched when Gnus is unplugged"))
   (gnus-group-iterate n 'gnus-agent-fetch-group))
 
-(defun gnus-agent-fetch-group (group)
-  "Put all new articles in GROUP into the agent."
+(defun gnus-agent-fetch-group (&optional group)
+  "Put all new articles in GROUP into the Agent."
   (interactive (list (gnus-group-group-name)))
+  (setq group (or group gnus-newsgroup-name))
   (unless group
     (error "No group on the current line"))
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (gnus-agent-with-fetch
-      (gnus-agent-fetch-group-1 group gnus-command-method)
-      (gnus-message 5 "Fetching %s...done" group))))
+
+  (gnus-agent-while-plugged
+    (let ((gnus-command-method (gnus-find-method-for-group group)))
+      (gnus-agent-with-fetch
+        (gnus-agent-fetch-group-1 group gnus-command-method)
+        (gnus-message 5 "Fetching %s...done" group)))))
 
 (defun gnus-agent-add-group (category arg)
   "Add the current group to an agent category."
@@ -339,51 +754,157 @@ agent minor mode in all Gnus buffers."
        c groups)
     (gnus-group-iterate arg
       (lambda (group)
-       (when (cadddr (setq c (gnus-group-category group)))
-         (setf (cadddr c) (delete group (cadddr c))))
+       (when (gnus-agent-cat-groups (setq c (gnus-group-category group)))
+         (setf (gnus-agent-cat-groups c)
+                (delete group (gnus-agent-cat-groups c))))
        (push group groups)))
-    (setf (cadddr cat) (nconc (cadddr cat) groups))
+    (setf (gnus-agent-cat-groups cat)
+          (nconc (gnus-agent-cat-groups cat) groups))
+    (gnus-category-write)))
+
+(defun gnus-agent-remove-group (arg)
+  "Remove the current group from its agent category, if any."
+  (interactive "P")
+  (let (c)
+    (gnus-group-iterate arg
+      (lambda (group)
+       (when (gnus-agent-cat-groups (setq c (gnus-group-category group)))
+         (setf (gnus-agent-cat-groups c)
+                (delete group (gnus-agent-cat-groups c))))))
     (gnus-category-write)))
 
+(defun gnus-agent-synchronize-flags ()
+  "Synchronize unplugged flags with servers."
+  (interactive)
+  (save-excursion
+    (dolist (gnus-command-method (gnus-agent-covered-methods))
+      (when (file-exists-p (gnus-agent-lib-file "flags"))
+       (gnus-agent-synchronize-flags-server gnus-command-method)))))
+
+(defun gnus-agent-possibly-synchronize-flags ()
+  "Synchronize flags according to `gnus-agent-synchronize-flags'."
+  (interactive)
+  (save-excursion
+    (dolist (gnus-command-method (gnus-agent-covered-methods))
+      (when (file-exists-p (gnus-agent-lib-file "flags"))
+       (gnus-agent-possibly-synchronize-flags-server gnus-command-method)))))
+
+(defun gnus-agent-synchronize-flags-server (method)
+  "Synchronize flags set when unplugged for server."
+  (let ((gnus-command-method method))
+    (when (file-exists-p (gnus-agent-lib-file "flags"))
+      (set-buffer (get-buffer-create " *Gnus Agent flag synchronize*"))
+      (erase-buffer)
+      (nnheader-insert-file-contents (gnus-agent-lib-file "flags"))
+      (if (null (gnus-check-server gnus-command-method))
+         (gnus-message 1 "Couldn't open server %s" (nth 1 gnus-command-method))
+       (while (not (eobp))
+         (if (null (eval (read (current-buffer))))
+             (gnus-delete-line)
+           (write-file (gnus-agent-lib-file "flags"))
+           (error "Couldn't set flags from file %s"
+                  (gnus-agent-lib-file "flags"))))
+       (delete-file (gnus-agent-lib-file "flags")))
+      (kill-buffer nil))))
+
+(defun gnus-agent-possibly-synchronize-flags-server (method)
+  "Synchronize flags for server according to `gnus-agent-synchronize-flags'."
+  (when (or (and gnus-agent-synchronize-flags
+                (not (eq gnus-agent-synchronize-flags 'ask)))
+           (and (eq gnus-agent-synchronize-flags 'ask)
+                (gnus-y-or-n-p (format "Synchronize flags on server `%s'? "
+                                       (cadr method)))))
+    (gnus-agent-synchronize-flags-server method)))
+
 ;;;
 ;;; Server mode commands
 ;;;
 
-(defun gnus-agent-add-server (server)
+(defun gnus-agent-add-server ()
   "Enroll SERVER in the agent program."
-  (interactive (list (gnus-server-server-name)))
-  (unless server
-    (error "No server on the current line"))
-  (let ((method (gnus-server-get-method nil (gnus-server-server-name))))
-    (when (member method gnus-agent-covered-methods)
+  (interactive)
+  (let* ((server       (gnus-server-server-name))
+         (named-server (gnus-server-named-server))
+         (method       (and server
+                            (gnus-server-get-method nil server))))
+    (unless server
+      (error "No server on the current line"))
+
+    (when (gnus-agent-method-p method)
       (error "Server already in the agent program"))
-    (push method gnus-agent-covered-methods)
+
+    (push named-server gnus-agent-covered-methods)
+
+    (setq gnus-agent-method-p-cache nil)
+    (gnus-server-update-server server)
     (gnus-agent-write-servers)
-    (message "Entered %s into the agent" server)))
+    (gnus-message 1 "Entered %s into the Agent" server)))
 
-(defun gnus-agent-remove-server (server)
+(defun gnus-agent-remove-server ()
   "Remove SERVER from the agent program."
-  (interactive (list (gnus-server-server-name)))
-  (unless server
-    (error "No server on the current line"))
-  (let ((method (gnus-server-get-method nil (gnus-server-server-name))))
-    (unless (member method gnus-agent-covered-methods)
+  (interactive)
+  (let* ((server       (gnus-server-server-name))
+         (named-server (gnus-server-named-server)))
+    (unless server
+      (error "No server on the current line"))
+
+    (unless (member named-server gnus-agent-covered-methods)
       (error "Server not in the agent program"))
-    (setq gnus-agent-covered-methods
-         (delete method gnus-agent-covered-methods))
+
+    (setq gnus-agent-covered-methods 
+          (delete named-server gnus-agent-covered-methods)
+          gnus-agent-method-p-cache nil)
+
+    (gnus-server-update-server server)
     (gnus-agent-write-servers)
-    (message "Removed %s from the agent" server)))
+    (gnus-message 1 "Removed %s from the agent" server)))
 
 (defun gnus-agent-read-servers ()
   "Read the alist of covered servers."
+  (setq gnus-agent-covered-methods 
+        (gnus-agent-read-file
+         (nnheader-concat gnus-agent-directory "lib/servers"))
+        gnus-agent-method-p-cache nil)
+
+  ;; I am called so early in start-up that I can not validate server
+  ;; names.  When that is the case, I skip the validation.  That is
+  ;; alright as the gnus startup code calls the validate methods
+  ;; directly.
+  (if gnus-server-alist
+      (gnus-agent-read-servers-validate)))
+
+(defun gnus-agent-read-servers-validate ()
+  (mapcar (lambda (server-or-method)
+            (let* ((server (if (stringp server-or-method)
+                               server-or-method
+                             (gnus-method-to-server server-or-method)))
+                   (method (gnus-server-to-method server)))
+              (if method
+                  (unless (member server gnus-agent-covered-methods)
+                    (push server gnus-agent-covered-methods)
+                    (setq gnus-agent-method-p-cache nil))
+                (gnus-message 1 "Ignoring disappeared server `%s'" server))))
+          (prog1 gnus-agent-covered-methods
+            (setq gnus-agent-covered-methods nil))))
+
+(defun gnus-agent-read-servers-validate-native (native-method)
   (setq gnus-agent-covered-methods
-       (gnus-agent-read-file
-        (nnheader-concat gnus-agent-directory "lib/servers"))))
+        (mapcar (lambda (method)
+                  (if (or (not method)
+                          (equal method native-method))
+                      "native"
+                    method)) gnus-agent-covered-methods)))
 
 (defun gnus-agent-write-servers ()
   "Write the alist of covered servers."
-  (nnheader-temp-write (nnheader-concat gnus-agent-directory "lib/servers")
-    (prin1 gnus-agent-covered-methods (current-buffer))))
+  (gnus-make-directory (nnheader-concat gnus-agent-directory "lib"))
+  (let ((coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
+    (with-temp-file (nnheader-concat gnus-agent-directory "lib/servers")
+      (prin1 gnus-agent-covered-methods
+            (current-buffer)))))
 
 ;;;
 ;;; Summary commands
@@ -425,87 +946,328 @@ the actual number of articles toggled is returned."
   (gnus-agent-mark-article n 'toggle))
 
 (defun gnus-summary-set-agent-mark (article &optional unmark)
-  "Mark ARTICLE as downloadable."
-  (let ((unmark (if (and (not (null unmark)) (not (eq t unmark)))
-                   (memq article gnus-newsgroup-downloadable)
-                 unmark)))
-    (if unmark
-       (progn
-         (setq gnus-newsgroup-downloadable
-               (delq article gnus-newsgroup-downloadable))
-         (push article gnus-newsgroup-undownloaded))
-      (setq gnus-newsgroup-undownloaded
-           (delq article gnus-newsgroup-undownloaded))
-      (push article gnus-newsgroup-downloadable))
-    (gnus-summary-update-mark
-     (if unmark gnus-undownloaded-mark gnus-downloadable-mark)
-     'unread)))
+  "Mark ARTICLE as downloadable.  If UNMARK is nil, article is marked.
+When UNMARK is t, the article is unmarked.  For any other value, the
+article's mark is toggled."
+  (let ((unmark (cond ((eq nil unmark)
+                      nil)
+                     ((eq t unmark)
+                      t)
+                     (t
+                      (memq article gnus-newsgroup-downloadable)))))
+    (when (gnus-summary-goto-subject article nil t)
+      (gnus-summary-update-mark
+       (if unmark
+           (progn
+             (setq gnus-newsgroup-downloadable
+                   (delq article gnus-newsgroup-downloadable))
+             (gnus-article-mark article))
+         (progn
+           (setq gnus-newsgroup-downloadable
+                 (gnus-add-to-sorted-list gnus-newsgroup-downloadable article))
+           gnus-downloadable-mark)
+         )
+       'unread))))
 
 (defun gnus-agent-get-undownloaded-list ()
-  "Mark all unfetched articles as read."
+  "Construct list of articles that have not been downloaded."
   (let ((gnus-command-method (gnus-find-method-for-group gnus-newsgroup-name)))
-    (when (and (not gnus-plugged)
-              (gnus-agent-method-p gnus-command-method))
-      (gnus-agent-load-alist gnus-newsgroup-name)
-      (let ((articles gnus-newsgroup-unreads)
-           article)
-       (while (setq article (pop articles))
-         (unless (or (cdr (assq article gnus-agent-article-alist))
-                 (memq article gnus-newsgroup-downloadable))
-           (push article gnus-newsgroup-undownloaded)))))))
+    (when (set (make-local-variable 'gnus-newsgroup-agentized)
+               (gnus-agent-method-p gnus-command-method))
+      (let* ((alist (gnus-agent-load-alist gnus-newsgroup-name))
+             (headers (sort (mapcar (lambda (h)
+                                      (mail-header-number h))
+                                    gnus-newsgroup-headers) '<))
+             (cached (and gnus-use-cache gnus-newsgroup-cached))
+             (undownloaded (list nil))
+             (tail-undownloaded undownloaded)
+             (unfetched (list nil))
+             (tail-unfetched unfetched))
+       (while (and alist headers)
+         (let ((a (caar alist))
+               (h (car headers)))
+           (cond ((< a h)
+                  ;; Ignore IDs in the alist that are not being
+                  ;; displayed in the summary.
+                  (setq alist (cdr alist)))
+                 ((> a h)
+                   ;; Headers that are not in the alist should be
+                   ;; fictious (see nnagent-retrieve-headers); they
+                   ;; imply that this article isn't in the agent.
+                  (gnus-agent-append-to-list tail-undownloaded h)
+                  (gnus-agent-append-to-list tail-unfetched    h)
+                   (setq headers (cdr headers))) 
+                 ((cdar alist)
+                  (setq alist (cdr alist))
+                  (setq headers (cdr headers))
+                  nil                  ; ignore already downloaded
+                  )
+                 (t
+                  (setq alist (cdr alist))
+                  (setq headers (cdr headers))
+                   
+                   ;; This article isn't in the agent.  Check to see
+                   ;; if it is in the cache.  If it is, it's been
+                   ;; downloaded.
+                   (while (and cached (< (car cached) a))
+                     (setq cached (cdr cached)))
+                   (unless (equal a (car cached))
+                     (gnus-agent-append-to-list tail-undownloaded a))))))
+
+       (while headers
+          (let ((num (pop headers)))
+            (gnus-agent-append-to-list tail-undownloaded num)
+            (gnus-agent-append-to-list tail-unfetched    num)))
+
+       (setq gnus-newsgroup-undownloaded (cdr undownloaded)
+              gnus-newsgroup-unfetched    (cdr unfetched))))))
 
 (defun gnus-agent-catchup ()
-  "Mark all undownloaded articles as read."
+  "Mark as read all unhandled articles.
+An article is unhandled if it is neither cached, nor downloaded, nor
+downloadable."
   (interactive)
   (save-excursion
-    (while gnus-newsgroup-undownloaded
-      (gnus-summary-mark-article
-       (pop gnus-newsgroup-undownloaded) gnus-catchup-mark)))
-  (gnus-summary-position-point))
+    (let ((articles gnus-newsgroup-undownloaded))
+      (when (or gnus-newsgroup-downloadable
+                gnus-newsgroup-cached)
+        (setq articles (gnus-sorted-ndifference
+                       (gnus-sorted-ndifference
+                        (gnus-copy-sequence articles)
+                        gnus-newsgroup-downloadable)
+                       gnus-newsgroup-cached)))
+
+      (while articles
+        (gnus-summary-mark-article
+         (pop articles) gnus-catchup-mark)))
+    (gnus-summary-position-point)))
+
+(defun gnus-agent-summary-fetch-series ()
+  (interactive)
+  (when gnus-newsgroup-processable
+    (setq gnus-newsgroup-downloadable
+          (let* ((dl gnus-newsgroup-downloadable)
+                 (gnus-newsgroup-downloadable
+                 (sort (gnus-copy-sequence gnus-newsgroup-processable) '<))
+                 (fetched-articles (gnus-agent-summary-fetch-group)))
+            ;; The preceeding call to (gnus-agent-summary-fetch-group)
+            ;; updated gnus-newsgroup-downloadable to remove each
+            ;; article successfully fetched.
+
+            ;; For each article that I processed, remove its
+            ;; processable mark IF the article is no longer
+            ;; downloadable (i.e. it's already downloaded)
+            (dolist (article gnus-newsgroup-processable)
+              (unless (memq article gnus-newsgroup-downloadable)
+                (gnus-summary-remove-process-mark article)))
+            (gnus-sorted-ndifference dl fetched-articles)))))
+
+(defun gnus-agent-summary-fetch-group (&optional all)
+  "Fetch the downloadable articles in the group.
+Optional arg ALL, if non-nil, means to fetch all articles."
+  (interactive "P")
+  (let ((articles
+        (if all gnus-newsgroup-articles
+          gnus-newsgroup-downloadable))
+       (gnus-command-method (gnus-find-method-for-group gnus-newsgroup-name))
+        fetched-articles)
+    (gnus-agent-while-plugged
+      (unless articles
+        (error "No articles to download"))
+      (gnus-agent-with-fetch
+        (setq gnus-newsgroup-undownloaded
+              (gnus-sorted-ndifference
+               gnus-newsgroup-undownloaded
+               (setq fetched-articles
+                     (gnus-agent-fetch-articles
+                      gnus-newsgroup-name articles)))))
+      (save-excursion
+        (dolist (article articles)
+          (let ((was-marked-downloadable 
+                 (memq article gnus-newsgroup-downloadable)))
+            (cond (gnus-agent-mark-unread-after-downloaded
+                   (setq gnus-newsgroup-downloadable
+                         (delq article gnus-newsgroup-downloadable))
+
+                   ;; The downloadable mark is implemented as a
+                   ;; type of read mark.  Therefore, marking the
+                   ;; article as unread is sufficient to clear
+                   ;; its downloadable flag.  
+                   (gnus-summary-mark-article article gnus-unread-mark))
+                  (was-marked-downloadable
+                   (gnus-summary-set-agent-mark article t)))
+            (when (gnus-summary-goto-subject article nil t)
+              (gnus-summary-update-download-mark article))))))
+    fetched-articles))
+
+(defun gnus-agent-fetch-selected-article ()
+  "Fetch the current article as it is selected.
+This can be added to `gnus-select-article-hook' or
+`gnus-mark-article-hook'."
+  (let ((gnus-command-method gnus-current-select-method))
+    (when (and gnus-plugged (gnus-agent-method-p gnus-command-method))
+      (when (gnus-agent-fetch-articles
+             gnus-newsgroup-name
+            (list gnus-current-article))
+       (setq gnus-newsgroup-undownloaded
+             (delq gnus-current-article gnus-newsgroup-undownloaded))
+        (gnus-summary-update-download-mark gnus-current-article)))))
 
 ;;;
 ;;; Internal functions
 ;;;
 
+;;; NOTES:
+;;; The agent's active range is defined as follows:
+;;;  If the agent has no record of the group, use the actual active
+;;;    range.
+;;;  If the agent has a record, set the agent's active range to
+;;;    include the max limit of the actual active range.
+;;;  When expiring, update the min limit to match the smallest of the
+;;;    min article not expired or the min actual active range.
+
 (defun gnus-agent-save-active (method)
+  (gnus-agent-save-active-1 method 'gnus-active-to-gnus-format))
+
+(defun gnus-agent-save-active-1 (method function)
   (when (gnus-agent-method-p method)
     (let* ((gnus-command-method method)
+          (new (gnus-make-hashtable (count-lines (point-min) (point-max))))
           (file (gnus-agent-lib-file "active")))
-      (gnus-make-directory (file-name-directory file))
-      (let ((coding-system-for-write gnus-agent-article-file-coding-system))
-       (write-region (point-min) (point-max) file nil 'silent))
-      (when (file-exists-p (gnus-agent-lib-file "groups"))
-       (delete-file (gnus-agent-lib-file "groups"))))))
+      (funcall function nil new)
+      (gnus-agent-write-active file new)
+      (erase-buffer)
+      (nnheader-insert-file-contents file))))
+
+(defun gnus-agent-write-active (file new &optional literal-replacement)
+  (let ((old new))
+    (when (and (not literal-replacement)
+               (file-exists-p file))
+      (setq old (gnus-make-hashtable (count-lines (point-min) (point-max))))
+      (with-temp-buffer
+        (nnheader-insert-file-contents file)
+        (gnus-active-to-gnus-format nil old))
+      ;; Iterate over the current active groups, the current active
+      ;; range may expand, but NOT CONTRACT, the agent's active range.
+      (mapatoms
+       (lambda (nsym)
+         (let ((new-active (and nsym (boundp nsym) (symbol-value nsym))))
+           (when new-active
+             (let* ((osym       (intern (symbol-name nsym) old))
+                    (old-active (and (boundp osym) (symbol-value osym))))
+               (if old-active
+                   (let ((new-min (car new-active))
+                         (old-min (car old-active))
+                         (new-max (cdr new-active))
+                         (old-max (cdr old-active)))
+                     (if (and (integerp new-min)
+                              (< new-min old-min))
+                         (setcar old-active new-min))
+                     (if (and (integerp new-max)
+                              (> new-max old-max))
+                         (setcdr old-active new-max)))
+                 (set osym new-active))))))
+       new))
+    (gnus-make-directory (file-name-directory file))
+    (let ((nnmail-active-file-coding-system gnus-agent-file-coding-system))
+      ;; The hashtable contains real names of groups.  However, do NOT
+      ;; add the foreign server prefix as gnus-active-to-gnus-format
+      ;; will add it while reading the file.
+      (gnus-write-active-file file old nil))))
+
+(defun gnus-agent-possibly-alter-active (group active)
+  "Possibly expand a group's active range to include articles
+downloaded into the agent."
+
+;; I can't use the agent's active file here as there is no practical
+;; mechanism to update the active ranges in that file as the oldest
+;; articles are removed from the agent.
+  (let* ((gnus-command-method (or gnus-command-method
+                                  (gnus-find-method-for-group group)))
+         (alist (gnus-agent-load-alist group)))
+
+    (let ((new-min (or (caar gnus-agent-article-alist)
+                       (car active)))
+          (new-max (or (caar (last gnus-agent-article-alist))
+                       (cdr active))))
+
+        (when (< new-min (car active))
+          (setcar active new-min))
+        (when (> new-max (cdr active))
+          (setcdr active new-max)))))
 
 (defun gnus-agent-save-groups (method)
-  (let* ((gnus-command-method method)
-        (file (gnus-agent-lib-file "groups")))
-    (gnus-make-directory (file-name-directory file))
-    (write-region (point-min) (point-max) file nil 'silent))
-    (when (file-exists-p (gnus-agent-lib-file "active"))
-      (delete-file (gnus-agent-lib-file "active"))))
+  (gnus-agent-save-active-1 method 'gnus-groups-to-gnus-format))
+
+(defun gnus-agent-save-group-info (method group active)
+  (when (gnus-agent-method-p method)
+    (let* ((gnus-command-method method)
+          (coding-system-for-write nnheader-file-coding-system)
+          (output-coding-system nnheader-file-coding-system)
+          (file-name-coding-system nnmail-pathname-coding-system)
+          (pathname-coding-system nnmail-pathname-coding-system)
+          (file (gnus-agent-lib-file "active"))
+          oactive-min oactive-max)
+      (gnus-make-directory (file-name-directory file))
+      (with-temp-file file
+       ;; Emacs got problem to match non-ASCII group in multibyte buffer.
+       (set-buffer-multibyte nil)
+       (when (file-exists-p file)
+         (nnheader-insert-file-contents file)
+
+          (goto-char (point-min))
+          (when (re-search-forward
+                 (concat "^" (regexp-quote group) " ") nil t)
+            (save-excursion
+              (setq oactive-max (read (current-buffer)) ;; max
+                    oactive-min (read (current-buffer)))) ;; min
+            (gnus-delete-line)))
+       (insert (format "%S %d %d y\n" (intern group)
+                       (max (or oactive-max (cdr active)) (cdr active))
+                        (min (or oactive-min (car active)) (car active))))
+       (goto-char (point-max))
+       (while (search-backward "\\." nil t)
+         (delete-char 1))))))
 
 (defun gnus-agent-group-path (group)
-  "Translate GROUP into a path."
-  (if nnmail-use-long-file-names
+  "Translate GROUP into a file name."
+
+  ;; NOTE: This is what nnmail-group-pathname does as of Apr 2003.
+  ;; The two methods must be kept synchronized, which is why
+  ;; gnus-agent-group-pathname was added.
+
+  (setq group
+        (nnheader-translate-file-chars
+         (nnheader-replace-duplicate-chars-in-string
+          (nnheader-replace-chars-in-string 
+           (gnus-group-real-name group)
+           ?/ ?_)
+          ?. ?_)))
+  (if (or nnmail-use-long-file-names
+          (file-directory-p (expand-file-name group (gnus-agent-directory))))
       group
-    (nnheader-replace-chars-in-string
-     (nnheader-translate-file-chars group)
-     ?. ?/)))
-
-\f
-
-(defun gnus-agent-method-p (method)
-  "Say whether METHOD is covered by the agent."
-  (member method gnus-agent-covered-methods))
+    (mm-encode-coding-string
+     (nnheader-replace-chars-in-string group ?. ?/)
+     nnmail-pathname-coding-system)))
+
+(defun gnus-agent-group-pathname (group)
+  "Translate GROUP into a file name."
+  ;; nnagent uses nnmail-group-pathname to read articles while
+  ;; unplugged.  The agent must, therefore, use the same directory
+  ;; while plugged.
+  (let ((gnus-command-method (or gnus-command-method
+                                 (gnus-find-method-for-group group))))
+    (nnmail-group-pathname (gnus-group-real-name group) (gnus-agent-directory))))
 
 (defun gnus-agent-get-function (method)
-  (if (and (not gnus-plugged)
-          (gnus-agent-method-p method))
-      (progn
-       (require 'nnagent)
-       'nnagent)
-    (car method)))
+  (if (gnus-online method)
+      (car method)
+    (require 'nnagent)
+    'nnagent))
+
+(defun gnus-agent-covered-methods ()
+  "Return the subset of methods that are covered by the agent."
+  (delq nil (mapcar #'gnus-server-to-method gnus-agent-covered-methods)))
 
 ;;; History functions
 
@@ -515,24 +1277,18 @@ the actual number of articles toggled is returned."
 (defun gnus-agent-open-history ()
   (save-excursion
     (push (cons (gnus-agent-method)
-               (set-buffer (get-buffer-create
+               (set-buffer (gnus-get-buffer-create
                             (format " *Gnus agent %s history*"
                                     (gnus-agent-method)))))
          gnus-agent-history-buffers)
+    (set-buffer-multibyte nil) ;; everything is binary
     (erase-buffer)
     (insert "\n")
     (let ((file (gnus-agent-lib-file "history")))
       (when (file-exists-p file)
-       (insert-file file))
+       (nnheader-insert-file-contents file))
       (set (make-local-variable 'gnus-agent-file-name) file))))
 
-(defun gnus-agent-save-history ()
-  (save-excursion
-    (set-buffer gnus-agent-current-history)
-    (gnus-make-directory (file-name-directory gnus-agent-file-name))
-    (write-region (1+ (point-min)) (point-max)
-                 gnus-agent-file-name nil 'silent)))
-
 (defun gnus-agent-close-history ()
   (when (gnus-buffer-live-p gnus-agent-current-history)
     (kill-buffer gnus-agent-current-history)
@@ -540,109 +1296,144 @@ the actual number of articles toggled is returned."
          (delq (assoc (gnus-agent-method) gnus-agent-history-buffers)
                gnus-agent-history-buffers))))
 
-(defun gnus-agent-enter-history (id group-arts date)
-  (save-excursion
-    (set-buffer gnus-agent-current-history)
-    (goto-char (point-max))
-    (insert id "\t" (number-to-string date) "\t")
-    (while group-arts
-      (insert (caar group-arts) "/" (number-to-string (cdr (pop group-arts)))
-             " "))
-    (insert "\n")))
-
-(defun gnus-agent-article-in-history-p (id)
-  (save-excursion
-    (set-buffer (gnus-agent-history-buffer))
-    (goto-char (point-min))
-    (search-forward (concat "\n" id "\t") nil t)))
-
-(defun gnus-agent-history-path (id)
-  (save-excursion
-    (set-buffer (gnus-agent-history-buffer))
-    (goto-char (point-min))
-    (when (search-forward (concat "\n" id "\t") nil t)
-      (let ((method (gnus-agent-method)))
-       (let (paths group)
-         (while (not (numberp (setq group (read (current-buffer)))))
-           (push (concat method "/" group) paths))
-         (nreverse paths))))))
-
 ;;;
 ;;; Fetching
 ;;;
 
 (defun gnus-agent-fetch-articles (group articles)
-  "Fetch ARTICLES from GROUP and put them into the agent."
+  "Fetch ARTICLES from GROUP and put them into the Agent."
   (when articles
-    ;; Prune off articles that we have already fetched.
-    (while (and articles
-               (cdr (assq (car articles) gnus-agent-article-alist)))
-      (pop articles))
-    (let ((arts articles))
-      (while (cdr arts)
-       (if (cdr (assq (cadr arts) gnus-agent-article-alist))
-           (setcdr arts (cddr arts))
-         (setq arts (cdr arts)))))
-    (when articles
-      (let ((dir (concat
-                 (gnus-agent-directory)
-                 (gnus-agent-group-path group) "/"))
-           (date (gnus-time-to-day (current-time)))
-           (case-fold-search t)
-           pos alists crosses id elem)
-       (gnus-make-directory dir)
-       (gnus-message 7 "Fetching articles for %s..." group)
-       ;; Fetch the articles from the backend.
-       (if (gnus-check-backend-function 'retrieve-articles group)
-           (setq pos (gnus-retrieve-articles articles group))
-         (nnheader-temp-write nil
-           (let ((buf (current-buffer))
-                 article)
-             (while (setq article (pop articles))
-               (when (gnus-request-article article group)
-                 (goto-char (point-max))
-                 (push (cons article (point)) pos)
-                 (insert-buffer-substring nntp-server-buffer)))
-             (copy-to-buffer nntp-server-buffer (point-min) (point-max))
-             (setq pos (nreverse pos)))))
-       ;; Then save these articles into the agent.
-       (save-excursion
-         (set-buffer nntp-server-buffer)
-         (while pos
-           (narrow-to-region (cdar pos) (or (cdadr pos) (point-max)))
-           (goto-char (point-min))
-           (when (search-forward "\n\n" nil t)
-             (when (search-backward "\nXrefs: " nil t)
-               ;; Handle crossposting.
-               (skip-chars-forward "^ ")
-               (skip-chars-forward " ")
-               (setq crosses nil)
-               (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) +")
-                 (push (cons (buffer-substring (match-beginning 1)
-                                               (match-end 1))
-                             (buffer-substring (match-beginning 2)
-                                               (match-end 2)))
-                       crosses)
-                 (goto-char (match-end 0)))
-               (gnus-agent-crosspost crosses (caar pos))))
-           (goto-char (point-min))
-           (if (not (re-search-forward "^Message-ID: *<\\([^>\n]+\\)>" nil t))
-               (setq id "No-Message-ID-in-article")
-             (setq id (buffer-substring (match-beginning 1) (match-end 1))))
-           (let ((coding-system-for-write
-                  gnus-agent-article-file-coding-system))
-             (write-region (point-min) (point-max)
-                           (concat dir (number-to-string (caar pos)))
-                           nil 'silent))
-           (when (setq elem (assq (caar pos) gnus-agent-article-alist))
-             (setcdr elem t))
-           (gnus-agent-enter-history
-            id (or crosses (list (cons group (caar pos)))) date)
-           (widen)
-           (pop pos)))
-       (gnus-agent-save-alist group)))))
-
-(defun gnus-agent-crosspost (crosses article)
+    (gnus-agent-load-alist group)
+    (let* ((alist   gnus-agent-article-alist)
+           (headers (if (< (length articles) 2) nil gnus-newsgroup-headers))
+           (selected-sets (list nil))
+           (current-set-size 0)
+           article
+           header-number)
+      ;; Check each article
+      (while (setq article (pop articles))
+        ;; Skip alist entries preceeding this article
+        (while (> article (or (caar alist) (1+ article)))
+          (setq alist (cdr alist)))
+
+        ;; Prune off articles that we have already fetched.
+        (unless (and (eq article (caar alist))
+                     (cdar alist))
+          ;; Skip headers preceeding this article
+          (while (> article 
+                    (setq header-number
+                          (let* ((header (car headers)))
+                            (if header
+                                (mail-header-number header)
+                              (1+ article)))))
+            (setq headers (cdr headers)))
+
+          ;; Add this article to the current set
+          (setcar selected-sets (cons article (car selected-sets)))
+
+          ;; Update the set size, when the set is too large start a
+          ;; new one.  I do this after adding the article as I want at
+          ;; least one article in each set.
+          (when (< gnus-agent-max-fetch-size
+                   (setq current-set-size
+                        (+ current-set-size
+                           (if (= header-number article)
+                                (let ((char-size (mail-header-chars
+                                                  (car headers))))
+                                  (if (<= char-size 0)
+                                      ;; The char size was missing/invalid,
+                                      ;; assume a worst-case situation of
+                                      ;; 65 char/line.  If the line count
+                                      ;; is missing, arbitrarily assume a
+                                      ;; size of 1000 characters.
+                                    (max (* 65 (mail-header-lines
+                                                (car headers)))
+                                         1000)
+                                    char-size))
+                             0))))
+            (setcar selected-sets (nreverse (car selected-sets)))
+            (setq selected-sets (cons nil selected-sets)
+                  current-set-size 0))))
+
+      (when (or (cdr selected-sets) (car selected-sets))
+        (let* ((fetched-articles (list nil))
+               (tail-fetched-articles fetched-articles)
+               (dir (gnus-agent-group-pathname group))
+               (date (time-to-days (current-time)))
+               (case-fold-search t)
+               pos crosses id)
+
+          (setcar selected-sets (nreverse (car selected-sets)))
+          (setq selected-sets (nreverse selected-sets))
+
+          (gnus-make-directory dir)
+          (gnus-message 7 "Fetching articles for %s..." group)
+
+          (unwind-protect
+              (while (setq articles (pop selected-sets))
+                ;; Fetch the articles from the backend.
+                (if (gnus-check-backend-function 'retrieve-articles group)
+                    (setq pos (gnus-retrieve-articles articles group))
+                  (with-temp-buffer
+                    (let (article)
+                      (while (setq article (pop articles))
+                        (gnus-message 10 "Fetching article %s for %s..."
+                                      article group)
+                        (when (or
+                               (gnus-backlog-request-article group article
+                                                             nntp-server-buffer)
+                               (gnus-request-article article group))
+                          (goto-char (point-max))
+                          (push (cons article (point)) pos)
+                          (insert-buffer-substring nntp-server-buffer)))
+                      (copy-to-buffer
+                      nntp-server-buffer (point-min) (point-max))
+                      (setq pos (nreverse pos)))))
+                ;; Then save these articles into the Agent.
+                (save-excursion
+                  (set-buffer nntp-server-buffer)
+                  (while pos
+                    (narrow-to-region (cdar pos) (or (cdadr pos) (point-max)))
+                    (goto-char (point-min))
+                    (unless (eobp) ;; Don't save empty articles.
+                      (when (search-forward "\n\n" nil t)
+                        (when (search-backward "\nXrefs: " nil t)
+                          ;; Handle cross posting.
+                          (goto-char (match-end 0)) ; move to end of header name
+                          (skip-chars-forward "^ ") ; skip server name
+                          (skip-chars-forward " ")
+                          (setq crosses nil)
+                          (while (looking-at "\\([^: \n]+\\):\\([0-9]+\\) *")
+                            (push (cons (buffer-substring (match-beginning 1)
+                                                          (match-end 1))
+                                        (string-to-int
+                                        (buffer-substring (match-beginning 2)
+                                                          (match-end 2))))
+                                  crosses)
+                            (goto-char (match-end 0)))
+                          (gnus-agent-crosspost crosses (caar pos) date)))
+                      (goto-char (point-min))
+                      (if (not (re-search-forward
+                                "^Message-ID: *<\\([^>\n]+\\)>" nil t))
+                          (setq id "No-Message-ID-in-article")
+                        (setq id (buffer-substring
+                                 (match-beginning 1) (match-end 1))))
+                     (write-region-as-coding-system
+                      gnus-agent-file-coding-system (point-min) (point-max)
+                      (concat dir (number-to-string (caar pos))) nil 'silent)
+
+                      (gnus-agent-append-to-list
+                      tail-fetched-articles (caar pos)))
+                    (widen)
+                    (setq pos (cdr pos)))))
+
+            (gnus-agent-save-alist group (cdr fetched-articles) date)
+            (gnus-message 7 ""))
+          (cdr fetched-articles))))))
+
+(defun gnus-agent-crosspost (crosses article &optional date)
+  (setq date (or date t))
+
   (let (gnus-agent-article-alist group alist beg end)
     (save-excursion
       (set-buffer gnus-agent-overview-buffer)
@@ -655,144 +1446,431 @@ the actual number of articles toggled is returned."
       (unless (setq alist (assoc group gnus-agent-group-alist))
        (push (setq alist (list group (gnus-agent-load-alist (caar crosses))))
              gnus-agent-group-alist))
-      (setcdr alist (cons (cons (cdar crosses) t) (cdr alist)))
+      (setcdr alist (cons (cons (cdar crosses) date) (cdr alist)))
       (save-excursion
-       (set-buffer (get-buffer-create (format " *Gnus agent overview %s*"
-                                              group)))
+       (set-buffer (gnus-get-buffer-create (format " *Gnus agent overview %s*"
+                                                   group)))
        (when (= (point-max) (point-min))
          (push (cons group (current-buffer)) gnus-agent-buffer-alist)
          (ignore-errors
-           (insert-file-contents
+           (nnheader-insert-file-contents
             (gnus-agent-article-name ".overview" group))))
        (nnheader-find-nov-line (string-to-number (cdar crosses)))
        (insert (string-to-number (cdar crosses)))
-       (insert-buffer-substring gnus-agent-overview-buffer beg end))
-      (pop crosses))))
+       (insert-buffer-substring gnus-agent-overview-buffer beg end)
+        (gnus-agent-check-overview-buffer))
+      (setq crosses (cdr crosses)))))
+
+(defun gnus-agent-backup-overview-buffer ()
+  (when gnus-newsgroup-name
+    (let ((root (gnus-agent-article-name ".overview" gnus-newsgroup-name))
+          (cnt 0)
+          name)
+      (while (file-exists-p
+             (setq name (concat root "~"
+                                (int-to-string (setq cnt (1+ cnt))) "~"))))
+      (write-region (point-min) (point-max) name nil 'no-msg)
+      (gnus-message 1 "Created backup copy of overview in %s." name)))
+  t)
+
+(defun gnus-agent-check-overview-buffer (&optional buffer)
+  "Check the overview file given for sanity.
+In particular, checks that the file is sorted by article number
+and that there are no duplicates."
+  (let ((prev-num -1)
+        (backed-up nil))
+    (save-excursion
+      (when buffer
+       (set-buffer buffer))
+      (save-restriction
+       (widen)
+       (goto-char (point-min))
+
+       (while (< (point) (point-max))
+         (let ((p (point))
+               (cur (condition-case nil
+                        (read (current-buffer))
+                      (error nil))))
+           (cond
+            ((or (not (integerp cur))
+                 (not (eq (char-after) ?\t)))
+              (or backed-up
+                  (setq backed-up (gnus-agent-backup-overview-buffer)))
+             (gnus-message 1
+                           "Overview buffer contains garbage '%s'."
+                           (buffer-substring
+                            p (gnus-point-at-eol))))
+            ((= cur prev-num)
+             (or backed-up
+                  (setq backed-up (gnus-agent-backup-overview-buffer)))
+              (gnus-message 1
+                           "Duplicate overview line for %d" cur)
+             (delete-region (point) (progn (forward-line 1) (point))))
+            ((< cur prev-num)
+             (or backed-up
+                  (setq backed-up (gnus-agent-backup-overview-buffer)))
+              (gnus-message 1 "Overview buffer not sorted!")
+             (sort-numeric-fields 1 (point-min) (point-max))
+             (goto-char (point-min))
+             (setq prev-num -1))
+            (t
+             (setq prev-num cur)))
+           (forward-line 1)))))))
 
 (defun gnus-agent-flush-cache ()
   (save-excursion
     (while gnus-agent-buffer-alist
       (set-buffer (cdar gnus-agent-buffer-alist))
-      (write-region (point-min) (point-max)
-                   (gnus-agent-article-name ".overview"
-                                            (caar gnus-agent-buffer-alist))
-                    nil 'silent)
-      (pop gnus-agent-buffer-alist))
+      (write-region-as-coding-system
+       gnus-agent-file-coding-system
+       (point-min) (point-max)
+       (gnus-agent-article-name ".overview"
+                               (caar gnus-agent-buffer-alist))
+       nil 'silent)
+      (setq gnus-agent-buffer-alist (cdr gnus-agent-buffer-alist)))
     (while gnus-agent-group-alist
-      (nnheader-temp-write (caar gnus-agent-group-alist)
+      (with-temp-file (gnus-agent-article-name
+                      ".agentview" (caar gnus-agent-group-alist))
        (princ (cdar gnus-agent-group-alist))
+       (insert "\n")
+        (princ 1 (current-buffer))
        (insert "\n"))
-      (pop gnus-agent-group-alist))))
+      (setq gnus-agent-group-alist (cdr gnus-agent-group-alist)))))
+
+(defun gnus-agent-find-parameter (group symbol)
+  "Search for GROUPs SYMBOL in the group's parameters, the group's
+topic parameters, the group's category, or the customizable
+variables.  Returns the first non-nil value found."
+  (or (gnus-group-find-parameter group symbol t)
+      (gnus-group-parameter-value (cdr (gnus-group-category group)) symbol t)
+      (symbol-value
+       (cdr
+        (assq symbol
+              '((agent-short-article . gnus-agent-short-article)
+                (agent-long-article . gnus-agent-long-article)
+                (agent-low-score . gnus-agent-low-score)
+                (agent-high-score . gnus-agent-high-score)
+                (agent-days-until-old . gnus-agent-expire-days)
+                (agent-enable-expiration
+                 . gnus-agent-enable-expiration)
+                (agent-predicate . gnus-agent-predicate)))))))
+
+(defun gnus-agent-fetch-headers (group &optional force)
+  "Fetch interesting headers into the agent.  The group's overview
+file will be updated to include the headers while a list of available
+article numbers will be returned."
+  (let* ((fetch-all (and gnus-agent-consider-all-articles
+                         ;; Do not fetch all headers if the predicate
+                         ;; implies that we only consider unread articles.
+                         (not (gnus-predicate-implies-unread
+                               (gnus-agent-find-parameter group
+                                                          'agent-predicate)))))
+         (articles (if fetch-all
+                       (gnus-uncompress-range (gnus-active group))
+                     (gnus-list-of-unread-articles group)))
+         (gnus-decode-encoded-word-function 'identity)
+         (file (gnus-agent-article-name ".overview" group)))
+    ;; Check whether the number of articles is not too large.
+    (when (and (integerp gnus-agent-large-newsgroup)
+              (> gnus-agent-large-newsgroup 0))
+      (setq articles (nthcdr (max (- (length articles)
+                                    gnus-agent-large-newsgroup)
+                                 0)
+                            articles)))
+    (unless fetch-all
+      ;; Add articles with marks to the list of article headers we want to
+      ;; fetch.  Don't fetch articles solely on the basis of a recent or seen
+      ;; mark, but do fetch recent or seen articles if they have other, more
+      ;; interesting marks.  (We have to fetch articles with boring marks
+      ;; because otherwise the agent will remove their marks.)
+      (dolist (arts (gnus-info-marks (gnus-get-info group)))
+        (unless (memq (car arts) '(seen recent killed cache))
+          (setq articles (gnus-range-add articles (cdr arts)))))
+      (setq articles (sort (gnus-uncompress-sequence articles) '<)))
+
+    ;; At this point, I have the list of articles to consider for
+    ;; fetching.  This is the list that I'll return to my caller. Some
+    ;; of these articles may have already been fetched.  That's OK as
+    ;; the fetch article code will filter those out.  Internally, I'll
+    ;; filter this list to just those articles whose headers need to
+    ;; be fetched.
+    (let ((articles articles))
+      ;; Remove known articles.
+      (when (and (or gnus-agent-cache
+                     (not gnus-plugged))
+                 (gnus-agent-load-alist group))
+        ;; Remove articles marked as downloaded.
+        (if fetch-all
+            ;; I want to fetch all headers in the active range.
+            ;; Therefore, exclude only those headers that are in the
+            ;; article alist.
+            ;; NOTE: This is probably NOT what I want to do after
+            ;; agent expiration in this group.
+            (setq articles (gnus-agent-uncached-articles articles group))
+
+          ;; I want to only fetch those headers that have never been
+          ;; fetched.  Therefore, exclude all headers that are, or
+          ;; WERE, in the article alist.
+          (let ((low (1+ (caar (last gnus-agent-article-alist))))
+                (high (cdr (gnus-active group))))
+            ;; Low can be greater than High when the same group is
+            ;; fetched twice in the same session {The first fetch will
+            ;; fill the article alist such that (last
+            ;; gnus-agent-article-alist) equals (cdr (gnus-active
+            ;; group))}.  The addition of one(the 1+ above) then
+            ;; forces Low to be greater than High.  When this happens,
+            ;; gnus-list-range-intersection returns nil which
+            ;; indicates that no headers need to be fetched. -- Kevin
+            (setq articles (gnus-list-range-intersection
+                            articles (list (cons low high)))))))
+
+      (gnus-message
+       10 "gnus-agent-fetch-headers: undownloaded articles are '%s'"
+       (gnus-compress-sequence articles t))
 
-(defun gnus-agent-fetch-headers (group articles &optional force)
-  (gnus-agent-load-alist group)
-  ;; Find out what headers we need to retrieve.
-  (when articles
-    (while (and articles
-               (assq (car articles) gnus-agent-article-alist))
-      (pop articles))
-    (let ((arts articles))
-      (while (cdr arts)
-       (if (assq (cadr arts) gnus-agent-article-alist)
-           (setcdr arts (cddr arts))
-         (setq arts (cdr arts)))))
-    ;; Fetch them.
-    (when articles
-      (gnus-message 7 "Fetching headers for %s..." group)
       (save-excursion
-       (set-buffer nntp-server-buffer)
-       (unless (eq 'nov (gnus-retrieve-headers articles group))
-         (nnvirtual-convert-headers))
-       ;; Save these headers for later processing.
-       (copy-to-buffer gnus-agent-overview-buffer (point-min) (point-max))
-       (let (file)
-         (when (file-exists-p
-                (setq file (gnus-agent-article-name ".overview" group)))
-           (gnus-agent-braid-nov group articles file))
-         (gnus-make-directory (nnheader-translate-file-chars
-                               (file-name-directory file)))
-         (write-region (point-min) (point-max) file nil 'silent)
-         (gnus-agent-save-alist group articles nil))
-       t))))
+        (set-buffer nntp-server-buffer)
+
+        (if articles
+            (progn
+              (gnus-message 7 "Fetching headers for %s..." group)
+
+              ;; Fetch them.
+              (gnus-make-directory (nnheader-translate-file-chars
+                                    (file-name-directory file) t))
+
+              (unless (eq 'nov (gnus-retrieve-headers articles group))
+                (nnvirtual-convert-headers))
+              (gnus-agent-check-overview-buffer)
+              ;; Move these headers to the overview buffer so that
+              ;; gnus-agent-braid-nov can merge them with the contents
+              ;; of FILE.
+              (copy-to-buffer
+              gnus-agent-overview-buffer (point-min) (point-max))
+              (when (file-exists-p file)
+                (gnus-agent-braid-nov group articles file))
+             (gnus-agent-check-overview-buffer)
+             (write-region-as-coding-system
+              gnus-agent-file-coding-system
+              (point-min) (point-max) file nil 'silent)
+              (gnus-agent-save-alist group articles nil)
+              articles)
+          (ignore-errors
+            (erase-buffer)
+            (nnheader-insert-file-contents file)))))
+    articles))
 
 (defsubst gnus-agent-copy-nov-line (article)
-  (let (b e)
+  (let (art b e)
     (set-buffer gnus-agent-overview-buffer)
-    (setq b (point))
-    (if (eq article (read (current-buffer)))
-       (setq e (progn (forward-line 1) (point)))
-      (setq e b))
-    (set-buffer nntp-server-buffer)
-    (insert-buffer-substring gnus-agent-overview-buffer b e)))
+    (while (and (not (eobp))
+               (< (setq art (read (current-buffer))) article))
+      (forward-line 1))
+    (beginning-of-line)
+    (if (or (eobp)
+           (not (eq article art)))
+       (set-buffer nntp-server-buffer)
+      (setq b (point))
+      (setq e (progn (forward-line 1) (point)))
+      (set-buffer nntp-server-buffer)
+      (insert-buffer-substring gnus-agent-overview-buffer b e))))
 
 (defun gnus-agent-braid-nov (group articles file)
-  (let (beg end)
+  "Merge agent overview data with given file.
+Takes headers for ARTICLES from `gnus-agent-overview-buffer' and the given
+FILE and places the combined headers into `nntp-server-buffer'."
+  (let (start last)
     (set-buffer gnus-agent-overview-buffer)
     (goto-char (point-min))
     (set-buffer nntp-server-buffer)
     (erase-buffer)
-    (insert-file-contents file)
-    (goto-char (point-min))
-    (if (or (= (point-min) (point-max))
-           (progn
-             (forward-line -1)
-             (< (read (current-buffer)) (car articles))))
-       ;; We have only headers that are after the older headers,
-       ;; so we just append them.
-       (progn
-         (goto-char (point-max))
-         (insert-buffer-substring gnus-agent-overview-buffer))
+    (nnheader-insert-file-contents file)
+    (goto-char (point-max))
+    (forward-line -1)
+    (unless (looking-at "[0-9]+\t")
+      ;; Remove corrupted lines
+      (gnus-message
+       1 "Overview %s is corrupted. Removing corrupted lines..." file)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (if (looking-at "[0-9]+\t")
+           (forward-line 1)
+         (delete-region (point) (progn (forward-line 1) (point)))))
+      (forward-line -1))
+    (unless (or (= (point-min) (point-max))
+               (< (setq last (read (current-buffer))) (car articles)))
       ;; We do it the hard way.
-      (nnheader-find-nov-line (car articles))
-      (gnus-agent-copy-nov-line (car articles))
-      (pop articles)
-      (while (and articles
-                 (not (eobp)))
-       (while (and (not (eobp))
-                   (< (read (current-buffer)) (car articles)))
-         (forward-line 1))
+      (when (nnheader-find-nov-line (car articles))
+        ;; Replacing existing NOV entry
+        (delete-region (point) (progn (forward-line 1) (point))))
+      (gnus-agent-copy-nov-line (pop articles))
+
+      (ignore-errors
+        (while articles
+          (while (let ((art (read (current-buffer))))
+                   (cond ((< art (car articles))
+                          (forward-line 1)
+                          t)
+                         ((= art (car articles))
+                          (beginning-of-line)
+                          (delete-region
+                          (point) (progn (forward-line 1) (point)))
+                          nil)
+                         (t
+                          (beginning-of-line)
+                          nil))))
+
+         (gnus-agent-copy-nov-line (pop articles)))))
+
+    ;; Copy the rest lines
+    (set-buffer nntp-server-buffer)
+    (goto-char (point-max))
+    (when articles
+      (when last
+       (set-buffer gnus-agent-overview-buffer)
+       (ignore-errors
+          (while (<= (read (current-buffer)) last)
+            (forward-line 1)))
        (beginning-of-line)
-       (unless (eobp)
-         (gnus-agent-copy-nov-line (car articles))
-         (setq articles (cdr articles))))
-      (when articles
-       (let (b e)
-         (set-buffer gnus-agent-overview-buffer)
-         (setq b (point)
-               e (point-max))
-         (set-buffer nntp-server-buffer)
-         (insert-buffer-substring gnus-agent-overview-buffer b e))))))
-
-(defun gnus-agent-load-alist (group &optional dir)
+       (setq start (point))
+       (set-buffer nntp-server-buffer))
+      (insert-buffer-substring gnus-agent-overview-buffer start))))
+
+;; Keeps the compiler from warning about the free variable in
+;; gnus-agent-read-agentview.
+(eval-when-compile
+  (defvar gnus-agent-read-agentview))
+
+(defun gnus-agent-load-alist (group)
   "Load the article-state alist for GROUP."
-  (setq gnus-agent-article-alist
-       (gnus-agent-read-file
-        (if dir
-            (concat dir ".agentview")
-          (gnus-agent-article-name ".agentview" group)))))
+  ;; Bind free variable that's used in `gnus-agent-read-agentview'.
+  (let ((gnus-agent-read-agentview group))
+    (setq gnus-agent-article-alist
+          (gnus-cache-file-contents
+           (gnus-agent-article-name ".agentview" group)
+           'gnus-agent-file-loading-cache
+           'gnus-agent-read-agentview))))
+
+;; Save format may be either 1 or 2.  Two is the new, compressed
+;; format that is still being tested.  Format 1 is uncompressed but
+;; known to be reliable.
+(defconst gnus-agent-article-alist-save-format 2)
+
+(defun gnus-agent-read-agentview (file)
+  "Load FILE and do a `read' there."
+  (with-temp-buffer
+    (ignore-errors
+      (nnheader-insert-file-contents file)
+      (goto-char (point-min))
+      (let ((alist (read (current-buffer)))
+            (version (condition-case nil (read (current-buffer))
+                       (end-of-file 0)))
+            changed-version)
+
+        (cond
+        ((= version 0)
+         (let ((inhibit-quit t)
+               entry)
+           (gnus-agent-open-history)
+           (set-buffer (gnus-agent-history-buffer))
+           (goto-char (point-min))
+           (while (not (eobp))
+             (if (and (looking-at
+                       "[^\t\n]+\t\\([0-9]+\\)\t\\([^ \n]+\\) \\([0-9]+\\)")
+                      (string= (match-string 2)
+                               gnus-agent-read-agentview)
+                      (setq entry (assoc (string-to-number (match-string 3)) alist)))
+                 (setcdr entry (string-to-number (match-string 1))))
+             (forward-line 1))
+           (gnus-agent-close-history)
+           (setq changed-version t)))
+        ((= version 1)
+         (setq changed-version (not (= 1 gnus-agent-article-alist-save-format))))
+        ((= version 2)
+         (let (uncomp)
+           (mapcar
+            (lambda (comp-list)
+              (let ((state (car comp-list))
+                    (sequence (gnus-uncompress-sequence
+                               (cdr comp-list))))
+                (mapcar (lambda (article-id)
+                          (setq uncomp (cons (cons article-id state) uncomp)))
+                        sequence)))
+            alist)
+           (setq alist (sort uncomp 'car-less-than-car)))))
+        (when changed-version
+          (let ((gnus-agent-article-alist alist))
+            (gnus-agent-save-alist gnus-agent-read-agentview)))
+        alist))))
 
 (defun gnus-agent-save-alist (group &optional articles state dir)
-  "Load the article-state alist for GROUP."
-  (nnheader-temp-write (if dir
-                          (concat dir ".agentview")
-                        (gnus-agent-article-name ".agentview" group))
-    (princ (setq gnus-agent-article-alist
-                (nconc gnus-agent-article-alist
-                       (mapcar (lambda (article) (cons article state))
-                               articles)))
-          (current-buffer))
-    (insert "\n")))
+  "Save the article-state alist for GROUP."
+  (let* ((file-name-coding-system nnmail-pathname-coding-system)
+        (pathname-coding-system nnmail-pathname-coding-system)
+        (prev (cons nil gnus-agent-article-alist))
+        (all prev)
+        print-level print-length item article)
+    (while (setq article (pop articles))
+      (while (and (cdr prev)
+                  (< (caadr prev) article))
+       (setq prev (cdr prev)))
+      (cond
+       ((not (cdr prev))
+       (setcdr prev (list (cons article state))))
+       ((> (caadr prev) article)
+       (setcdr prev (cons (cons article state) (cdr prev))))
+       ((= (caadr prev) article)
+       (setcdr (cadr prev) state)))
+      (setq prev (cdr prev)))
+    (setq gnus-agent-article-alist (cdr all))
+    (if dir
+       (gnus-make-directory dir)
+      (gnus-make-directory (gnus-agent-article-name "" group)))
+    (with-temp-file (if dir
+                       (expand-file-name ".agentview" dir)
+                     (gnus-agent-article-name ".agentview" group))
+      (cond ((eq gnus-agent-article-alist-save-format 1)
+             (princ gnus-agent-article-alist (current-buffer)))
+            ((eq gnus-agent-article-alist-save-format 2)
+             (let ((compressed nil))
+               (mapcar (lambda (pair)
+                         (let* ((article-id (car pair))
+                                (day-of-download (cdr pair))
+                                (comp-list (assq day-of-download compressed)))
+                           (if comp-list
+                               (setcdr comp-list
+                                      (cons article-id (cdr comp-list)))
+                             (setq compressed
+                                  (cons (list day-of-download article-id)
+                                        compressed)))
+                           nil)) gnus-agent-article-alist)
+               (mapcar (lambda (comp-list)
+                        (setcdr comp-list
+                                (gnus-compress-sequence
+                                 (nreverse (cdr comp-list)))))
+                      compressed)
+               (princ compressed (current-buffer)))))
+      (insert "\n")
+      (princ gnus-agent-article-alist-save-format (current-buffer))
+      (insert "\n"))))
 
 (defun gnus-agent-article-name (article group)
-  (concat (gnus-agent-directory) (gnus-agent-group-path group) "/"
-         (if (stringp article) article (string-to-number article))))
+  (expand-file-name article
+                   (file-name-as-directory
+                     (gnus-agent-group-pathname group))))
+
+(defun gnus-agent-batch-confirmation (msg)
+  "Show error message and return t."
+  (gnus-message 1 msg)
+  t)
 
 ;;;###autoload
 (defun gnus-agent-batch-fetch ()
   "Start Gnus and fetch session."
   (interactive)
   (gnus)
-  (gnus-agent-fetch-session)
+  (let ((gnus-agent-confirmation-function 'gnus-agent-batch-confirmation))
+    (gnus-agent-fetch-session))
   (gnus-group-exit))
 
 (defun gnus-agent-fetch-session ()
@@ -802,63 +1880,226 @@ the actual number of articles toggled is returned."
     (error "No servers are covered by the Gnus agent"))
   (unless gnus-plugged
     (error "Can't fetch articles while Gnus is unplugged"))
-  (let ((methods gnus-agent-covered-methods)
+  (let ((methods (gnus-agent-covered-methods))
        groups group gnus-command-method)
     (save-excursion
       (while methods
-       (setq gnus-command-method (car methods)
-             groups (gnus-groups-from-server (pop methods)))
-       (gnus-agent-with-fetch
-         (while (setq group (pop groups))
-           (when (<= (gnus-group-level group) gnus-agent-handle-level)
-             (gnus-agent-fetch-group-1 group gnus-command-method)))))
+       (setq gnus-command-method (car methods))
+       (when (and (or (gnus-server-opened gnus-command-method)
+                      (gnus-open-server gnus-command-method))
+                  (gnus-online gnus-command-method))
+         (setq groups (gnus-groups-from-server (car methods)))
+         (gnus-agent-with-fetch
+           (while (setq group (pop groups))
+             (when (<= (gnus-group-level group)
+                       gnus-agent-handle-level)
+               (if (or debug-on-error debug-on-quit)
+                   (gnus-agent-fetch-group-1
+                    group gnus-command-method)
+                 (condition-case err
+                     (gnus-agent-fetch-group-1
+                      group gnus-command-method)
+                   (error
+                    (unless (funcall gnus-agent-confirmation-function
+                                     (format "Error %s.  Continue? "
+                                             (error-message-string err)))
+                      (error "Cannot fetch articles into the Gnus agent")))
+                   (quit
+                    (unless (funcall gnus-agent-confirmation-function
+                                     (format
+                                      "Quit fetching session %s.  Continue? "
+                                      (error-message-string err)))
+                      (signal 'quit
+                              "Cannot fetch articles into the Gnus agent")))))))))
+       (setq methods (cdr methods)))
+      (gnus-run-hooks 'gnus-agent-fetched-hook)
       (gnus-message 6 "Finished fetching articles into the Gnus agent"))))
 
 (defun gnus-agent-fetch-group-1 (group method)
   "Fetch GROUP."
   (let ((gnus-command-method method)
-       gnus-newsgroup-dependencies gnus-newsgroup-headers
-       gnus-newsgroup-scored gnus-headers gnus-score
-       gnus-use-cache articles score arts
-       category predicate info marks score-param)
+       (gnus-newsgroup-name group)
+       (gnus-newsgroup-dependencies gnus-newsgroup-dependencies)
+        (gnus-newsgroup-headers gnus-newsgroup-headers)
+       (gnus-newsgroup-scored gnus-newsgroup-scored)
+       (gnus-use-cache gnus-use-cache)
+       (gnus-summary-expunge-below gnus-summary-expunge-below)
+       (gnus-summary-mark-below gnus-summary-mark-below)
+       (gnus-orphan-score gnus-orphan-score)
+       ;; Maybe some other gnus-summary local variables should also
+       ;; be put here.
+
+        gnus-headers
+        gnus-score
+        articles arts
+       category predicate info marks score-param
+       )
+    (unless (gnus-check-group group)
+      (error "Can't open server for %s" group))
+
     ;; Fetch headers.
-    (when (and (setq articles (gnus-list-of-unread-articles group))
-              (gnus-agent-fetch-headers group articles))
-      ;; Parse them and see which articles we want to fetch.
-      (setq gnus-newsgroup-dependencies
-           (make-vector (length articles) 0))
-      (setq gnus-newsgroup-headers
-           (gnus-get-newsgroup-headers-xover articles nil nil group))
-      (setq category (gnus-group-category group))
-      (setq predicate
-           (gnus-get-predicate 
-            (or (gnus-group-get-parameter group 'agent-predicate)
-                (cadr category))))
-      (setq score-param
-           (or (gnus-group-get-parameter group 'agent-score)
-               (caddr category)))
-      (when score-param
-       (gnus-score-headers (list (list score-param))))
-      (setq arts nil)
-      (while (setq gnus-headers (pop gnus-newsgroup-headers))
-       (setq gnus-score
-             (or (cdr (assq (mail-header-number gnus-headers)
-                            gnus-newsgroup-scored))
-                 gnus-summary-default-score))
-       (when (funcall predicate)
-         (push (mail-header-number gnus-headers)
-               arts)))
-      ;; Fetch the articles.
-      (when arts
-       (gnus-agent-fetch-articles group arts)))
-    ;; Perhaps we have some additional articles to fetch.
-    (setq arts (assq 'download (gnus-info-marks
-                               (setq info (gnus-get-info group)))))
-    (when (cdr arts)
-      (gnus-agent-fetch-articles
-       group (gnus-uncompress-range (cdr arts)))
-      (setq marks (delq arts (gnus-info-marks info)))
-      (gnus-info-set-marks info marks))))
+    (when (or gnus-newsgroup-active
+              (gnus-active group)
+              (gnus-activate-group group))
+      (let ((marked-articles gnus-newsgroup-downloadable))
+        ;; Identify the articles marked for download
+        (unless gnus-newsgroup-active
+         ;; The variable gnus-newsgroup-active was selected as I need
+         ;; a gnus-summary local variable that is NOT bound to any
+         ;; value (its global value should default to nil).
+          (dolist (mark gnus-agent-download-marks)
+            (let ((arts (cdr (assq mark (gnus-info-marks
+                                         (setq info (gnus-get-info group)))))))
+              (when arts
+                (setq marked-articles (nconc (gnus-uncompress-range arts)
+                                             marked-articles))
+                ))))
+        (setq marked-articles (sort marked-articles '<))
+
+        ;; Fetch any new articles from the server
+        (setq articles (gnus-agent-fetch-headers group))
+
+        ;; Merge new articles with marked
+        (setq articles (sort (append marked-articles articles) '<))
+
+        (when articles
+          ;; Parse them and see which articles we want to fetch.
+          (setq gnus-newsgroup-dependencies
+                (or gnus-newsgroup-dependencies
+                    (make-vector (length articles) 0)))
+          (setq gnus-newsgroup-headers
+                (or gnus-newsgroup-headers
+                    (gnus-get-newsgroup-headers-xover articles nil nil
+                                                      group)))
+          ;; `gnus-agent-overview-buffer' may be killed for
+          ;; timeout reason.  If so, recreate it.
+          (gnus-agent-create-buffer)
+
+          ;; Figure out how to select articles in this group
+          (setq category (gnus-group-category group))
+
+          (setq predicate
+                (gnus-get-predicate
+                 (gnus-agent-find-parameter group 'agent-predicate)))
+
+          ;; If the selection predicate requires scoring, score each header
+          (unless (memq predicate '(gnus-agent-true gnus-agent-false))
+            (let ((score-param
+                   (gnus-agent-find-parameter group 'agent-score-file)))
+              ;; Translate score-param into real one
+              (cond
+               ((not score-param))
+               ((eq score-param 'file)
+                (setq score-param (gnus-all-score-files group)))
+               ((stringp (car score-param)))
+               (t
+                (setq score-param (list (list score-param)))))
+              (when score-param
+                (gnus-score-headers score-param))))
+
+          (unless (and (eq predicate 'gnus-agent-false)
+                       (not marked-articles))
+            (let ((arts (list nil)))
+              (let ((arts-tail arts)
+                    (alist (gnus-agent-load-alist group))
+                    (marked-articles marked-articles)
+                    (gnus-newsgroup-headers gnus-newsgroup-headers))
+                (while (setq gnus-headers (pop gnus-newsgroup-headers))
+                  (let ((num (mail-header-number gnus-headers)))
+                    ;; Determine if this article is already in the cache
+                    (while (and alist
+                                (> num (caar alist)))
+                      (setq alist (cdr alist)))
+
+                    (unless (and (eq num (caar alist))
+                                 (cdar alist))
+
+                      ;; Determine if this article was marked for download.
+                      (while (and marked-articles
+                                  (> num (car marked-articles)))
+                        (setq marked-articles
+                              (cdr marked-articles)))
+
+                      ;; When this article is marked, or selected by the
+                      ;; predicate, add it to the download list
+                      (when (or (eq num (car marked-articles))
+                                (let ((gnus-score
+                                       (or (cdr
+                                           (assq num gnus-newsgroup-scored))
+                                           gnus-summary-default-score))
+                                      (gnus-agent-long-article
+                                       (gnus-agent-find-parameter
+                                        group 'agent-long-article))
+                                      (gnus-agent-short-article
+                                       (gnus-agent-find-parameter
+                                        group 'agent-short-article))
+                                      (gnus-agent-low-score
+                                       (gnus-agent-find-parameter
+                                        group 'agent-low-score))
+                                      (gnus-agent-high-score
+                                       (gnus-agent-find-parameter
+                                        group 'agent-high-score))
+                                      (gnus-agent-expire-days
+                                       (gnus-agent-find-parameter
+                                        group 'agent-days-until-old)))
+                                  (funcall predicate)))
+                        (gnus-agent-append-to-list arts-tail num))))))
+
+              (let (fetched-articles)
+                ;; Fetch all selected articles
+                (setq gnus-newsgroup-undownloaded
+                      (gnus-sorted-ndifference
+                      gnus-newsgroup-undownloaded
+                      (setq fetched-articles
+                            (if (cdr arts)
+                                (gnus-agent-fetch-articles group (cdr arts))
+                              nil))))
+
+                (let ((unfetched-articles
+                      (gnus-sorted-ndifference (cdr arts) fetched-articles)))
+                  (if gnus-newsgroup-active
+                      ;; Update the summary buffer
+                      (progn
+                        (dolist (article marked-articles)
+                          (gnus-summary-set-agent-mark article t))
+                        (dolist (article fetched-articles)
+                          (if gnus-agent-mark-unread-after-downloaded
+                              (gnus-summary-mark-article
+                              article gnus-unread-mark))
+                          (when (gnus-summary-goto-subject article nil t)
+                            (gnus-summary-update-download-mark article)))
+                        (dolist (article unfetched-articles)
+                          (gnus-summary-mark-article
+                          article gnus-canceled-mark)))
+
+                    ;; Update the group buffer.
+
+                    ;; When some, or all, of the marked articles came
+                    ;; from the download mark.  Remove that mark.  I
+                    ;; didn't do this earlier as I only want to remove
+                    ;; the marks after the fetch is completed.
+
+                    (dolist (mark gnus-agent-download-marks)
+                      (when (eq mark 'download)
+                        (let ((marked-arts
+                              (assq mark (gnus-info-marks
+                                          (setq info (gnus-get-info group))))))
+                          (when (cdr marked-arts)
+                            (setq marks
+                                 (delq marked-arts (gnus-info-marks info)))
+                            (gnus-info-set-marks info marks)))))
+                    (let ((read (gnus-info-read
+                                (or info (setq info (gnus-get-info group))))))
+                      (gnus-info-set-read
+                      info (gnus-add-to-range read unfetched-articles)))
+
+                    (gnus-group-update-group group t)
+                    (sit-for 0)
+
+                    (gnus-dribble-enter
+                     (concat "(gnus-group-set-info '"
+                             (gnus-prin1-to-string info)
+                             ")"))))))))))))
 
 ;;;
 ;;; Agent Category Mode
@@ -868,11 +2109,21 @@ the actual number of articles toggled is returned."
   "Hook run in `gnus-category-mode' buffers.")
 
 (defvar gnus-category-line-format "     %(%20c%): %g\n"
-  "Format of category lines.")
+  "Format of category lines.
+
+Valid specifiers include:
+%c  Topic name (string)
+%g  The number of groups in the topic (integer)
+
+General format specifiers can also be used.  See Info node
+`(gnus)Formatting Variables'.")
 
 (defvar gnus-category-mode-line-format "Gnus: %%b"
   "The format specification for the category mode line.")
 
+(defvar gnus-agent-predicate 'false
+  "The selection predicate used when no other source is available.")
+
 (defvar gnus-agent-short-article 100
   "Articles that have fewer lines than this are short.")
 
@@ -891,8 +2142,8 @@ the actual number of articles toggled is returned."
 (defvar gnus-category-buffer "*Agent Category*")
 
 (defvar gnus-category-line-format-alist
-  `((?c name ?s)
-    (?g groups ?d)))
+  `((?c gnus-tmp-name ?s)
+    (?g gnus-tmp-groups ?d)))
 
 (defvar gnus-category-mode-line-format-alist
   `((?u user-defined ?s)))
@@ -912,6 +2163,7 @@ the actual number of articles toggled is returned."
     "k" gnus-category-kill
     "c" gnus-category-copy
     "a" gnus-category-add
+    "e" gnus-agent-customize-category
     "p" gnus-category-edit-predicate
     "g" gnus-category-edit-groups
     "s" gnus-category-edit-score
@@ -932,6 +2184,7 @@ the actual number of articles toggled is returned."
        ["Add" gnus-category-add t]
        ["Kill" gnus-category-kill t]
        ["Copy" gnus-category-copy t]
+       ["Edit category" gnus-agent-customize-category t]
        ["Edit predicate" gnus-category-edit-predicate t]
        ["Edit score" gnus-category-edit-score t]
        ["Edit groups" gnus-category-edit-groups t]
@@ -945,7 +2198,7 @@ the actual number of articles toggled is returned."
 All normal editing commands are switched off.
 \\<gnus-category-mode-map>
 For more in-depth information on this mode, read the manual
-(`\\[gnus-info-find-node]').
+\(`\\[gnus-info-find-node]').
 
 The following commands are available:
 
@@ -960,7 +2213,7 @@ The following commands are available:
   (gnus-set-default-directory)
   (setq mode-line-process nil)
   (use-local-map gnus-category-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq truncate-lines t)
   (setq buffer-read-only t)
   (gnus-run-hooks 'gnus-category-mode-hook))
@@ -968,15 +2221,15 @@ The following commands are available:
 (defalias 'gnus-category-position-point 'gnus-goto-colon)
 
 (defun gnus-category-insert-line (category)
-  (let* ((name (car category))
-        (groups (length (cadddr category))))
+  (let* ((gnus-tmp-name (format "%s" (car category)))
+        (gnus-tmp-groups (length (gnus-agent-cat-groups category))))
     (beginning-of-line)
     (gnus-add-text-properties
      (point)
      (prog1 (1+ (point))
        ;; Insert the text.
        (eval gnus-category-line-format-spec))
-     (list 'gnus-category name))))
+     (list 'gnus-category gnus-tmp-name))))
 
 (defun gnus-enter-category-buffer ()
   "Go to the Category buffer."
@@ -988,8 +2241,7 @@ The following commands are available:
 (defun gnus-category-setup-buffer ()
   (unless (get-buffer gnus-category-buffer)
     (save-excursion
-      (set-buffer (get-buffer-create gnus-category-buffer))
-      (gnus-add-current-to-buffer-list)
+      (set-buffer (gnus-get-buffer-create gnus-category-buffer))
       (gnus-category-mode))))
 
 (defun gnus-category-prepare ()
@@ -1004,21 +2256,58 @@ The following commands are available:
     (gnus-category-position-point)))
 
 (defun gnus-category-name ()
-  (or (get-text-property (gnus-point-at-bol) 'gnus-category)
+  (or (intern (get-text-property (gnus-point-at-bol) 'gnus-category))
       (error "No category on the current line")))
 
 (defun gnus-category-read ()
   "Read the category alist."
   (setq gnus-category-alist
-       (or (gnus-agent-read-file
-            (nnheader-concat gnus-agent-directory "lib/categories"))
-           (list (list 'default 'short nil nil)))))
-    
+        (or
+         (with-temp-buffer
+           (ignore-errors
+            (nnheader-insert-file-contents (nnheader-concat gnus-agent-directory "lib/categories"))
+            (goto-char (point-min))
+            ;; This code isn't temp, it will be needed so long as
+            ;; anyone may be migrating from an older version.
+
+            ;; Once we're certain that people will not revert to an
+            ;; earlier version, we can take out the old-list code in
+            ;; gnus-category-write.
+            (let* ((old-list (read (current-buffer)))
+                   (new-list (ignore-errors (read (current-buffer)))))
+              (if new-list
+                  new-list
+                ;; Convert from a positional list to an alist.
+                (mapcar
+                 (lambda (c)
+                   (setcdr c
+                           (delq nil
+                                 (gnus-mapcar
+                                  (lambda (valu symb)
+                                    (if valu
+                                        (cons symb valu)))
+                                  (cdr c)
+                                  '(agent-predicate agent-score-file agent-groups))))
+                   c)
+                 old-list)))))
+         (list (gnus-agent-cat-make 'default 'short)))))
+
 (defun gnus-category-write ()
   "Write the category alist."
   (setq gnus-category-predicate-cache nil
        gnus-category-group-cache nil)
-  (nnheader-temp-write (nnheader-concat gnus-agent-directory "lib/categories")
+  (gnus-make-directory (nnheader-concat gnus-agent-directory "lib"))
+  (with-temp-file (nnheader-concat gnus-agent-directory "lib/categories")
+    ;; This prin1 is temporary.  It exists so that people can revert
+    ;; to an earlier version of gnus-agent.
+    (prin1 (mapcar (lambda (c)
+              (list (car c)
+                    (cdr (assoc 'agent-predicate c))
+                    (cdr (assoc 'agent-score-file c))
+                    (cdr (assoc 'agent-groups c))))
+                   gnus-category-alist)
+           (current-buffer))
+    (newline)
     (prin1 gnus-category-alist (current-buffer))))
 
 (defun gnus-category-edit-predicate (category)
@@ -1026,21 +2315,34 @@ The following commands are available:
   (interactive (list (gnus-category-name)))
   (let ((info (assq category gnus-category-alist)))
     (gnus-edit-form
-     (cadr info) (format "Editing the predicate for category %s" category)
+     (gnus-agent-cat-predicate info)
+     (format "Editing the select predicate for category %s" category)
      `(lambda (predicate)
-       (setf (cadr (assq ',category gnus-category-alist)) predicate)
+        ;; Avoid run-time execution of setf form
+        ;; (setf (gnus-agent-cat-predicate (assq ',category gnus-category-alist))
+        ;;       predicate)
+        ;; use its expansion instead:
+        (gnus-agent-cat-set-property (assq ',category gnus-category-alist)
+                                     'agent-predicate predicate)
+
        (gnus-category-write)
        (gnus-category-list)))))
-  
+
 (defun gnus-category-edit-score (category)
   "Edit the score expression for CATEGORY."
   (interactive (list (gnus-category-name)))
   (let ((info (assq category gnus-category-alist)))
     (gnus-edit-form
-     (caddr info)
+     (gnus-agent-cat-score-file info)
      (format "Editing the score expression for category %s" category)
-     `(lambda (groups)
-       (setf (caddr (assq ',category gnus-category-alist)) groups)
+     `(lambda (score-file)
+        ;; Avoid run-time execution of setf form
+        ;; (setf (gnus-agent-cat-score-file (assq ',category gnus-category-alist))
+        ;;       score-file)
+        ;; use its expansion instead:
+        (gnus-agent-cat-set-property (assq ',category gnus-category-alist)
+                                     'agent-score-file score-file)
+
        (gnus-category-write)
        (gnus-category-list)))))
 
@@ -1049,9 +2351,16 @@ The following commands are available:
   (interactive (list (gnus-category-name)))
   (let ((info (assq category gnus-category-alist)))
     (gnus-edit-form
-     (cadddr info) (format "Editing the group list for category %s" category)
+     (gnus-agent-cat-groups info)
+     (format "Editing the group list for category %s" category)
      `(lambda (groups)
-       (setf (cadddr (assq ',category gnus-category-alist)) groups)
+        ;; Avoid run-time execution of setf form
+        ;; (setf (gnus-agent-cat-groups (assq ',category gnus-category-alist))
+        ;;       groups)
+        ;; use its expansion instead:
+        (gnus-agent-set-cat-groups (assq ',category gnus-category-alist)
+                                   groups)
+
        (gnus-category-write)
        (gnus-category-list)))))
 
@@ -1061,15 +2370,17 @@ The following commands are available:
   (let ((info (assq category gnus-category-alist))
        (buffer-read-only nil))
     (gnus-delete-line)
-    (gnus-category-write)
-    (setq gnus-category-alist (delq info gnus-category-alist))))
+    (setq gnus-category-alist (delq info gnus-category-alist))
+    (gnus-category-write)))
 
 (defun gnus-category-copy (category to)
   "Copy the current category."
   (interactive (list (gnus-category-name) (intern (read-string "New name: "))))
   (let ((info (assq category gnus-category-alist)))
-    (push (list to (gnus-copy-sequence (cadr info))
-               (gnus-copy-sequence (caddr info)) nil)
+    (push (let ((newcat (gnus-copy-sequence info)))
+            (setf (gnus-agent-cat-name newcat) to)
+            (setf (gnus-agent-cat-groups newcat) nil)
+            newcat)
          gnus-category-alist)
     (gnus-category-write)
     (gnus-category-list)))
@@ -1079,7 +2390,7 @@ The following commands are available:
   (interactive "SCategory name: ")
   (when (assq category gnus-category-alist)
     (error "Category %s already exists" category))
-  (push (list category 'true nil nil)
+  (push (gnus-agent-cat-make category)
        gnus-category-alist)
   (gnus-category-write)
   (gnus-category-list))
@@ -1104,6 +2415,7 @@ The following commands are available:
     (long . gnus-agent-long-p)
     (low . gnus-agent-low-scored-p)
     (high . gnus-agent-high-scored-p)
+    (read . gnus-agent-read-p)
     (true . gnus-agent-true)
     (false . gnus-agent-false))
   "Mapping from short score predicate symbols to predicate functions.")
@@ -1133,11 +2445,20 @@ The following commands are available:
 
 (defun gnus-agent-high-scored-p ()
   "Say whether an article has a high score or not."
-  (> gnus-score gnus-agent-low-score))
+  (> gnus-score gnus-agent-high-score))
+
+(defun gnus-agent-read-p ()
+  "Say whether an article is read or not."
+  (gnus-member-of-range (mail-header-number gnus-headers)
+                       (gnus-info-read (gnus-get-info gnus-newsgroup-name))))
 
-(defun gnus-category-make-function (cat)
-  "Make a function from category CAT."
-  `(lambda () ,(gnus-category-make-function-1 cat)))
+(defun gnus-category-make-function (predicate)
+  "Make a function from PREDICATE."
+  (let ((func (gnus-category-make-function-1 predicate)))
+    (if (and (= (length func) 1)
+            (symbolp (car func)))
+       (car func)
+      (gnus-byte-compile `(lambda () ,func)))))
 
 (defun gnus-agent-true ()
   "Return t."
@@ -1146,34 +2467,92 @@ The following commands are available:
 (defun gnus-agent-false ()
   "Return nil."
   nil)
-  
-(defun gnus-category-make-function-1 (cat)
-  "Make a function from category CAT."
+
+(defun gnus-category-make-function-1 (predicate)
+  "Make a function from PREDICATE."
   (cond
    ;; Functions are just returned as is.
-   ((or (symbolp cat)
-       (gnus-functionp cat))
-    `(,(or (cdr (assq cat gnus-category-predicate-alist))
-          cat)))
-   ;; More complex category.
-   ((consp cat)
+   ((or (symbolp predicate)
+       (functionp predicate))
+    `(,(or (cdr (assq predicate gnus-category-predicate-alist))
+          predicate)))
+   ;; More complex predicate.
+   ((consp predicate)
     `(,(cond
-       ((memq (car cat) '(& and))
+       ((memq (car predicate) '(& and))
         'and)
-       ((memq (car cat) '(| or))
+       ((memq (car predicate) '(| or))
         'or)
-       ((memq (car cat) gnus-category-not)
+       ((memq (car predicate) gnus-category-not)
         'not))
-      ,@(mapcar 'gnus-category-make-function-1 (cdr cat))))
+      ,@(mapcar 'gnus-category-make-function-1 (cdr predicate))))
    (t
-    (error "Unknown category type: %s" cat))))
+    (error "Unknown predicate type: %s" predicate))))
 
 (defun gnus-get-predicate (predicate)
-  "Return the predicate for CATEGORY."
+  "Return the function implementing PREDICATE."
   (or (cdr (assoc predicate gnus-category-predicate-cache))
-      (cdar (push (cons predicate
-                       (gnus-category-make-function predicate))
-                 gnus-category-predicate-cache))))
+      (let ((func (gnus-category-make-function predicate)))
+       (setq gnus-category-predicate-cache
+             (nconc gnus-category-predicate-cache
+                    (list (cons predicate func))))
+       func)))
+
+(defun gnus-predicate-implies-unread (predicate)
+  "Say whether PREDICATE implies unread articles only.
+It is okay to miss some cases, but there must be no false positives.
+That is, if this predicate returns true, then indeed the predicate must
+return only unread articles."
+  (eq t (gnus-function-implies-unread-1 
+         (gnus-category-make-function-1 predicate))))
+
+(defun gnus-function-implies-unread-1 (function)
+  "Recursively evaluate a predicate function to determine whether it can select
+any read articles.  Returns t if the function is known to never
+return read articles, nil when it is known to always return read
+articles, and t_nil when the function may return both read and unread
+articles."
+  (let ((func (car function))
+        (args (mapcar 'gnus-function-implies-unread-1 (cdr function))))
+    (cond ((eq func 'and)
+           (cond ((memq t args) ; if any argument returns only unread articles
+                  ;; then that argument constrains the result to only unread articles.
+                  t)
+                 ((memq 't_nil args) ; if any argument is indeterminate
+                  ;; then the result is indeterminate
+                  't_nil)))
+          ((eq func 'or)
+           (cond ((memq nil args) ; if any argument returns read articles
+                  ;; then that argument ensures that the results includes read articles.
+                  nil)
+                 ((memq 't_nil args) ; if any argument is indeterminate
+                  ;; then that argument ensures that the results are indeterminate
+                  't_nil)
+                 (t ; if all arguments return only unread articles
+                  ;; then the result returns only unread articles
+                  t)))
+          ((eq func 'not)
+           (cond ((eq (car args) 't_nil) ; if the argument is indeterminate
+                  ; then the result is indeterminate
+                  (car args))
+                 (t ; otherwise
+                  ; toggle the result to be the opposite of the argument
+                  (not (car args)))))
+          ((eq func 'gnus-agent-read-p)
+           nil) ; The read predicate NEVER returns unread articles
+          ((eq func 'gnus-agent-false)
+           t) ; The false predicate returns t as the empty set excludes all read articles
+          ((eq func 'gnus-agent-true)
+           nil) ; The true predicate ALWAYS returns read articles
+          ((catch 'found-match
+             (let ((alist gnus-category-predicate-alist))
+               (while alist
+                 (if (eq func (cdar alist))
+                     (throw 'found-match t)
+                   (setq alist (cdr alist))))))
+           't_nil) ; All other predicates return read and unread articles
+          (t
+           (error "Unknown predicate function: %s" function)))))
 
 (defun gnus-group-category (group)
   "Return the category GROUP belongs to."
@@ -1182,107 +2561,1079 @@ The following commands are available:
     (let ((cs gnus-category-alist)
          groups cat)
       (while (setq cat (pop cs))
-       (setq groups (cadddr cat))
+       (setq groups (gnus-agent-cat-groups cat))
        (while groups
          (gnus-sethash (pop groups) cat gnus-category-group-cache)))))
   (or (gnus-gethash group gnus-category-group-cache)
       (assq 'default gnus-category-alist)))
 
-(defun gnus-agent-expire ()
-  "Expire all old articles."
+(defun gnus-agent-expire-group (group &optional articles force)
+  "Expire all old articles in GROUP.
+If you want to force expiring of certain articles, this function can
+take ARTICLES, and FORCE parameters as well.
+
+The articles on which the expiration process runs are selected as follows:
+  if ARTICLES is null, all read and unmarked articles.
+  if ARTICLES is t, all articles.
+  if ARTICLES is a list, just those articles.
+FORCE is equivalent to setting the expiration predicates to true."
+  (interactive
+   (list (let ((def (or (gnus-group-group-name)
+                        gnus-newsgroup-name)))
+           (let ((select (read-string (if def
+                                          (concat "Group Name ("
+                                                  def "): ")
+                                        "Group Name: "))))
+             (if (and (equal "" select)
+                      def)
+                 def
+               select)))))
+
+  (if (not group)
+      (gnus-agent-expire articles group force)
+    (let ( ;; Bind gnus-agent-expire-stats to enable tracking of
+          ;; expiration statistics of this single group
+          (gnus-agent-expire-stats (list 0 0 0.0)))
+      (if (or (not (eq articles t))
+              (yes-or-no-p
+               (concat "Are you sure that you want to "
+                       "expire all articles in " group ".")))
+          (let ((gnus-command-method (gnus-find-method-for-group group))
+                (overview (gnus-get-buffer-create " *expire overview*"))
+                orig)
+            (unwind-protect
+                (let ((active-file (gnus-agent-lib-file "active")))
+                  (when (file-exists-p active-file)
+                    (with-temp-buffer
+                      (nnheader-insert-file-contents active-file)
+                      (gnus-active-to-gnus-format
+                       gnus-command-method
+                       (setq orig (gnus-make-hashtable
+                                   (count-lines (point-min) (point-max))))))
+                    (save-excursion
+                      (gnus-agent-expire-group-1
+                       group overview (gnus-gethash-safe group orig)
+                       articles force))
+                    (gnus-agent-write-active active-file orig t)))
+              (kill-buffer overview))))
+      (gnus-message 4 (gnus-agent-expire-done-message)))))
+
+(defun gnus-agent-expire-group-1 (group overview active articles force)
+  ;; Internal function - requires caller to have set
+  ;; gnus-command-method, initialized overview buffer, and to have
+  ;; provided a non-nil active
+
+  (let ((dir (gnus-agent-group-pathname group)))
+    (when (boundp 'gnus-agent-expire-current-dirs)
+      (set 'gnus-agent-expire-current-dirs 
+           (cons dir 
+                 (symbol-value 'gnus-agent-expire-current-dirs))))
+
+    (if (and (not force)
+             (eq 'DISABLE (gnus-agent-find-parameter group 
+                                                     'agent-enable-expiration)))
+        (gnus-message 5 "Expiry skipping over %s" group)
+      (gnus-message 5 "Expiring articles in %s" group)
+      (gnus-agent-load-alist group)
+      (let* ((stats (if (boundp 'gnus-agent-expire-stats)
+                        ;; Use the list provided by my caller
+                        (symbol-value 'gnus-agent-expire-stats)
+                      ;; otherwise use my own temporary list
+                      (list 0 0 0.0)))
+             (info (gnus-get-info group))
+             (alist gnus-agent-article-alist)
+             (day (- (time-to-days (current-time))
+                     (gnus-agent-find-parameter group 'agent-days-until-old)))
+             (specials (if (and alist
+                                (not force))
+                           ;; This could be a bit of a problem.  I need to
+                           ;; keep the last article to avoid refetching
+                           ;; headers when using nntp in the backend.  At
+                           ;; the same time, if someone uses a backend
+                           ;; that supports article moving then I may have
+                           ;; to remove the last article to complete the
+                           ;; move.  Right now, I'm going to assume that
+                           ;; FORCE overrides specials.
+                           (list (caar (last alist)))))
+             (unreads ;; Articles that are excluded from the
+              ;; expiration process
+              (cond (gnus-agent-expire-all
+                     ;; All articles are marked read by global decree
+                     nil)
+                    ((eq articles t)
+                     ;; All articles are marked read by function
+                     ;; parameter
+                     nil)
+                    ((not articles)
+                     ;; Unread articles are marked protected from
+                     ;; expiration Don't call
+                     ;; gnus-list-of-unread-articles as it returns
+                     ;; articles that have not been fetched into the
+                     ;; agent.
+                     (ignore-errors
+                       (gnus-agent-unread-articles group)))
+                    (t
+                     ;; All articles EXCEPT those named by the caller
+                     ;; are protected from expiration
+                     (gnus-sorted-difference
+                      (gnus-uncompress-range
+                       (cons (caar alist)
+                             (caar (last alist))))
+                      (sort articles '<)))))
+             (marked ;; More articles that are excluded from the
+              ;; expiration process
+              (cond (gnus-agent-expire-all
+                     ;; All articles are unmarked by global decree
+                     nil)
+                    ((eq articles t)
+                     ;; All articles are unmarked by function
+                     ;; parameter
+                     nil)
+                    (articles
+                     ;; All articles may as well be unmarked as the
+                     ;; unreads list already names the articles we are
+                     ;; going to keep
+                     nil)
+                    (t
+                     ;; Ticked and/or dormant articles are excluded
+                     ;; from expiration
+                     (nconc
+                      (gnus-uncompress-range
+                       (cdr (assq 'tick (gnus-info-marks info))))
+                      (gnus-uncompress-range
+                       (cdr (assq 'dormant
+                                  (gnus-info-marks info))))))))
+             (nov-file (concat dir ".overview"))
+             (cnt 0)
+             (completed -1)
+             dlist
+             type)
+
+        ;; The normal article alist contains elements that look like
+        ;; (article# .  fetch_date) I need to combine other
+        ;; information with this list.  For example, a flag indicating
+        ;; that a particular article MUST BE KEPT.  To do this, I'm
+        ;; going to transform the elements to look like (article#
+        ;; fetch_date keep_flag NOV_entry_marker) Later, I'll reverse
+        ;; the process to generate the expired article alist.
+
+        ;; Convert the alist elements to (article# fetch_date nil
+        ;; nil).
+        (setq dlist (mapcar (lambda (e)
+                              (list (car e) (cdr e) nil nil)) alist))
+
+        ;; Convert the keep lists to elements that look like (article#
+        ;; nil keep_flag nil) then append it to the expanded dlist
+        ;; These statements are sorted by ascending precidence of the
+        ;; keep_flag.
+        (setq dlist (nconc dlist
+                           (mapcar (lambda (e)
+                                     (list e nil 'unread  nil))
+                                   unreads)))
+        (setq dlist (nconc dlist
+                           (mapcar (lambda (e)
+                                     (list e nil 'marked  nil))
+                                   marked)))
+        (setq dlist (nconc dlist
+                           (mapcar (lambda (e)
+                                     (list e nil 'special nil))
+                                   specials)))
+
+        (set-buffer overview)
+        (erase-buffer)
+        (buffer-disable-undo)
+        (when (file-exists-p nov-file)
+          (gnus-message 7 "gnus-agent-expire: Loading overview...")
+          (nnheader-insert-file-contents nov-file)
+          (goto-char (point-min))
+
+          (let (p)
+            (while (< (setq p (point)) (point-max))
+              (condition-case nil
+                  ;; If I successfully read an integer (the plus zero
+                  ;; ensures a numeric type), prepend a marker entry
+                  ;; to the list
+                  (push (list (+ 0 (read (current-buffer))) nil nil
+                              (set-marker (make-marker) p))
+                        dlist)
+                (error
+                 (gnus-message 1 "gnus-agent-expire: read error \
+occurred when reading expression at %s in %s.  Skipping to next \
+line." (point) nov-file)))
+              ;; Whether I succeeded, or failed, it doesn't matter.
+              ;; Move to the next line then try again.
+              (forward-line 1)))
+
+          (gnus-message
+           7 "gnus-agent-expire: Loading overview... Done"))
+        (set-buffer-modified-p nil)
+
+        ;; At this point, all of the information is in dlist.  The
+        ;; only problem is that much of it is spread across multiple
+        ;; entries.  Sort then MERGE!!
+        (gnus-message 7 "gnus-agent-expire: Sorting entries... ")
+        ;; If two entries have the same article-number then sort by
+        ;; ascending keep_flag.
+        (let ((special 0)
+              (marked 1)
+              (unread 2))
+          (setq dlist
+                (sort dlist
+                      (lambda (a b)
+                        (cond ((< (nth 0 a) (nth 0 b))
+                               t)
+                              ((> (nth 0 a) (nth 0 b))
+                               nil)
+                              (t
+                               (let ((a (or (symbol-value (nth 2 a))
+                                            3))
+                                     (b (or (symbol-value (nth 2 b))
+                                            3)))
+                                 (<= a b))))))))
+        (gnus-message 7 "gnus-agent-expire: Sorting entries... Done")
+        (gnus-message 7 "gnus-agent-expire: Merging entries... ")
+        (let ((dlist dlist))
+          (while (cdr dlist)            ; I'm not at the end-of-list
+            (if (eq (caar dlist) (caadr dlist))
+                (let ((first (cdr (car dlist)))
+                      (secnd (cdr (cadr dlist))))
+                  (setcar first (or (car first)
+                                    (car secnd))) ; fetch_date
+                  (setq first (cdr first)
+                        secnd (cdr secnd))
+                  (setcar first (or (car first)
+                                    (car secnd))) ; Keep_flag
+                  (setq first (cdr first)
+                        secnd (cdr secnd))
+                  (setcar first (or (car first)
+                                    (car secnd))) ; NOV_entry_marker
+
+                  (setcdr dlist (cddr dlist)))
+              (setq dlist (cdr dlist)))))
+        (gnus-message 7 "gnus-agent-expire: Merging entries... Done")
+
+        (let* ((len (float (length dlist)))
+               (alist (list nil))
+               (tail-alist alist))
+          (while dlist
+            (let ((new-completed (truncate (* 100.0
+                                              (/ (setq cnt (1+ cnt))
+                                                 len))))
+                 message-log-max)
+              (when (> new-completed completed)
+                (setq completed new-completed)
+                (gnus-message 7 "%3d%% completed..."  completed)))
+            (let* ((entry          (car dlist))
+                   (article-number (nth 0 entry))
+                   (fetch-date     (nth 1 entry))
+                   (keep           (nth 2 entry))
+                   (marker         (nth 3 entry)))
+
+              (cond
+               ;; Kept articles are unread, marked, or special.
+               (keep
+                (gnus-agent-message 10
+                                    "gnus-agent-expire: %s:%d: Kept %s article%s."
+                                    group article-number keep (if fetch-date " and file" ""))
+                (when fetch-date
+                  (unless (file-exists-p
+                           (concat dir (number-to-string
+                                        article-number)))
+                    (setf (nth 1 entry) nil)
+                    (gnus-agent-message 3 "gnus-agent-expire cleared \
+download flag on %s:%d as the cached article file is missing."
+                                        group (caar dlist)))
+                  (unless marker
+                    (gnus-message 1 "gnus-agent-expire detected a \
+missing NOV entry.  Run gnus-agent-regenerate-group to restore it.")))
+                (gnus-agent-append-to-list
+                 tail-alist
+                 (cons article-number fetch-date)))
+
+               ;; The following articles are READ, UNMARKED, and
+               ;; ORDINARY.  See if they can be EXPIRED!!!
+               ((setq type
+                      (cond
+                       ((not (integerp fetch-date))
+                        'read) ;; never fetched article (may expire
+                       ;; right now)
+                       ((not (file-exists-p
+                              (concat dir (number-to-string
+                                           article-number))))
+                        (setf (nth 1 entry) nil)
+                        'externally-expired) ;; Can't find the cached
+                       ;; article.  Handle case
+                       ;; as though this article
+                       ;; was never fetched.
+
+                       ;; We now have the arrival day, so we see
+                       ;; whether it's old enough to be expired.
+                       ((< fetch-date day)
+                        'expired)
+                       (force
+                        'forced)))
+
+                ;; I found some reason to expire this entry.
+
+                (let ((actions nil))
+                  (when (memq type '(forced expired))
+                    (ignore-errors      ; Just being paranoid.
+                      (let ((file-name (concat dir (number-to-string
+                                                article-number))))
+                        (incf (nth 2 stats) (nth 7 (file-attributes file-name)))
+                        (incf (nth 1 stats))
+                        (delete-file file-name))
+                      (push "expired cached article" actions))
+                    (setf (nth 1 entry) nil)
+                    )
+
+                  (when marker
+                    (push "NOV entry removed" actions)
+                    (goto-char marker)
+
+                    (incf (nth 0 stats))
+
+                    (let ((from (gnus-point-at-bol))
+                          (to (progn (forward-line 1) (point))))
+                      (incf (nth 2 stats) (- to from))
+                      (delete-region from to)))
+
+                  ;; If considering all articles is set, I can only
+                  ;; expire article IDs that are no longer in the
+                  ;; active range (That is, articles that preceed the
+                  ;; first article in the new alist).
+                  (if (and gnus-agent-consider-all-articles
+                           (>= article-number (car active)))
+                      ;; I have to keep this ID in the alist
+                      (gnus-agent-append-to-list
+                       tail-alist (cons article-number fetch-date))
+                    (push (format "Removed %s article number from \
+article alist" type) actions))
+
+                 (when actions
+                   (gnus-agent-message 8 "gnus-agent-expire: %s:%d: %s"
+                                       group article-number
+                                       (mapconcat 'identity actions ", ")))))
+               (t
+                (gnus-agent-message
+                 10 "gnus-agent-expire: %s:%d: Article kept as \
+expiration tests failed." group article-number)
+                (gnus-agent-append-to-list
+                 tail-alist (cons article-number fetch-date)))
+               )
+
+              ;; Clean up markers as I want to recycle this buffer
+              ;; over several groups.
+              (when marker
+                (set-marker marker nil))
+
+              (setq dlist (cdr dlist))))
+
+          (setq alist (cdr alist))
+
+          (let ((inhibit-quit t))
+            (unless (equal alist gnus-agent-article-alist)
+              (setq gnus-agent-article-alist alist)
+              (gnus-agent-save-alist group)
+
+              ;; The active list changed, set the agent's active range
+              ;; to match the beginning of the list.
+              (if alist
+                  (setcar active (caar alist))))
+
+            (when (buffer-modified-p)
+             (gnus-make-directory dir)
+             (write-region-as-coding-system gnus-agent-file-coding-system
+                                            (point-min) (point-max) nov-file
+                                            nil 'silent)
+             ;; clear the modified flag as that I'm not confused by
+             ;; its status on the next pass through this routine.
+             (set-buffer-modified-p nil))
+
+            (when (eq articles t)
+              (gnus-summary-update-info))))))))
+
+(defun gnus-agent-expire (&optional articles group force)
+  "Expire all old articles.
+If you want to force expiring of certain articles, this function can
+take ARTICLES, GROUP and FORCE parameters as well.
+
+The articles on which the expiration process runs are selected as follows:
+  if ARTICLES is null, all read and unmarked articles.
+  if ARTICLES is t, all articles.
+  if ARTICLES is a list, just those articles.
+Setting GROUP will limit expiration to that group.
+FORCE is equivalent to setting the expiration predicates to true."
   (interactive)
-  (let ((methods gnus-agent-covered-methods)
-       (alist (cdr gnus-newsrc-alist))
-       gnus-command-method ofiles info method file group)
-    (while (setq gnus-command-method (pop methods))
-      (setq ofiles (nconc ofiles (gnus-agent-expire-directory
-                                 (gnus-agent-directory)))))
-    (while (setq info (pop alist))
-      (when (and (gnus-agent-method-p
-                 (setq gnus-command-method
-                       (gnus-find-method-for-group
-                        (setq group (gnus-info-group info)))))
-                (member
-                 (setq file
-                       (concat
-                        (gnus-agent-directory)
-                        (gnus-agent-group-path group) "/.overview"))
-                 ofiles))
-       (setq ofiles (delete file ofiles))
-       (gnus-agent-expire-group file group)))
-    (while ofiles
-      (gnus-agent-expire-group (pop ofiles)))))
-
-(defun gnus-agent-expire-directory (dir)
-  "Expire all groups in DIR recursively."
-  (when (file-directory-p dir)
-    (let ((files (directory-files dir t))
-         file ofiles)
-      (while (setq file (pop files))
-       (cond
-        ((member (file-name-nondirectory file) '("." ".."))
-         ;; Do nothing.
-         )
-        ((file-directory-p file)
-         ;; Recurse.
-         (setq ofiles (nconc ofiles (gnus-agent-expire-directory file))))
-        ((string-match "\\.overview$" file)
-         ;; Expire group.
-         (push file ofiles))))
-      ofiles)))
-
-(defun gnus-agent-expire-group (overview &optional group)
-  "Expire articles in OVERVIEW."
-  (gnus-message 5 "Expiring %s..." overview)
-  (let ((odate (- (gnus-time-to-day (current-time)) 4))
-       (dir (file-name-directory overview))
-       (info (when group (gnus-get-info group)))
-       headers article file point unreads)
-    (gnus-agent-load-alist nil dir)
-    (when info
-      (setq unreads
-           (nconc
-            (gnus-list-of-unread-articles group)
-            (gnus-uncompress-range
-             (cdr (assq 'tick (gnus-info-marks info))))
-            (gnus-uncompress-range
-             (cdr (assq 'dormant (gnus-info-marks info)))))))
-    (nnheader-temp-write overview
-      (insert-file-contents overview)
-      (goto-char (point-min))
-      (while (not (eobp))
-       (setq point (point))
-       (condition-case ()
-           (setq headers (inline (nnheader-parse-nov)))
-         (error
-          (goto-char point)
-          (gnus-delete-line)
-          (setq headers nil)))
-       (when headers
-         (unless (memq (setq article (mail-header-number headers)) unreads)
-           (if (not (< (inline
-                         (gnus-time-to-day
-                          (inline (nnmail-date-to-time
-                                   (mail-header-date headers)))))
-                       odate))
-               (forward-line 1)              
-             (gnus-delete-line)
-             (setq gnus-agent-article-alist
-                   (delq (assq article gnus-agent-article-alist)
-                         gnus-agent-article-alist))
-             (when (file-exists-p
-                    (setq file (concat dir (number-to-string article))))
-               (delete-file file))))))
-      (gnus-agent-save-alist nil nil nil dir))))
+  
+  (if group
+      (gnus-agent-expire-group group articles force)
+    (if (or (not (eq articles t))
+            (yes-or-no-p "Are you sure that you want to expire all \
+articles in every agentized group."))
+        (let ((methods (gnus-agent-covered-methods))
+              ;; Bind gnus-agent-expire-current-dirs to enable tracking
+              ;; of agent directories.
+              (gnus-agent-expire-current-dirs nil)
+              ;; Bind gnus-agent-expire-stats to enable tracking of
+              ;; expiration statistics across all groups
+              (gnus-agent-expire-stats (list 0 0 0.0))
+              gnus-command-method overview orig)
+          (setq overview (gnus-get-buffer-create " *expire overview*"))
+          (unwind-protect
+              (while (setq gnus-command-method (pop methods))
+                (let ((active-file (gnus-agent-lib-file "active")))
+                  (when (file-exists-p active-file)
+                    (with-temp-buffer
+                      (nnheader-insert-file-contents active-file)
+                      (gnus-active-to-gnus-format
+                       gnus-command-method
+                       (setq orig (gnus-make-hashtable
+                                   (count-lines (point-min) (point-max))))))
+                    (dolist (expiring-group (gnus-groups-from-server
+                                             gnus-command-method))
+                      (let* ((active
+                              (gnus-gethash-safe expiring-group orig)))
+                                        
+                        (when active
+                          (save-excursion
+                            (gnus-agent-expire-group-1
+                             expiring-group overview active articles force)))))
+                    (gnus-agent-write-active active-file orig t))))
+            (kill-buffer overview))
+          (gnus-agent-expire-unagentized-dirs)
+          (gnus-message 4 (gnus-agent-expire-done-message))))))
+
+(defun gnus-agent-expire-done-message ()
+  (if (and (> gnus-verbose 4)
+           (boundp 'gnus-agent-expire-stats))
+      (let* ((stats (symbol-value 'gnus-agent-expire-stats))
+             (size (nth 2 stats))
+            (units '(B KB MB GB)))
+        (while (and (> size 1024.0)
+                    (cdr units))
+          (setq size (/ size 1024.0)
+                units (cdr units)))
+
+        (format "Expiry recovered %d NOV entries, deleted %d files,\
+ and freed %f %s." 
+                (nth 0 stats) 
+                (nth 1 stats) 
+                size (car units)))
+    "Expiry...done"))
+
+(defun gnus-agent-expire-unagentized-dirs ()
+  (when (and gnus-agent-expire-unagentized-dirs
+             (boundp 'gnus-agent-expire-current-dirs))
+    (let* ((keep (gnus-make-hashtable))
+          ;; Formally bind gnus-agent-expire-current-dirs so that the
+          ;; compiler will not complain about free references.
+          (gnus-agent-expire-current-dirs
+           (symbol-value 'gnus-agent-expire-current-dirs))
+           dir)
+
+      (gnus-sethash gnus-agent-directory t keep)
+      (while gnus-agent-expire-current-dirs
+       (setq dir (pop gnus-agent-expire-current-dirs))
+       (when (and (stringp dir)
+                  (file-directory-p dir))
+         (while (not (gnus-gethash dir keep))
+           (gnus-sethash dir t keep)
+           (setq dir (file-name-directory (directory-file-name dir))))))
+
+      (let* (to-remove
+             checker
+             (checker
+              (function
+               (lambda (d)
+                 "Given a directory, check it and its subdirectories for 
+              membership in the keep hash.  If it isn't found, add 
+              it to to-remove." 
+                 (let ((files (directory-files d))
+                       file)
+                   (while (setq file (pop files))
+                     (cond ((equal file ".") ; Ignore self
+                            nil)
+                           ((equal file "..") ; Ignore parent
+                            nil)
+                           ((equal file ".overview") 
+                            ;; Directory must contain .overview to be
+                            ;; agent's cache of a group.
+                            (let ((d (file-name-as-directory d))
+                                  r)
+                              ;; Search ancestor's for last directory NOT
+                              ;; found in keep hash.
+                              (while (not (gnus-gethash
+                                           (setq d (file-name-directory d)) keep))
+                                (setq r d
+                                      d (directory-file-name d)))
+                              ;; if ANY ancestor was NOT in keep hash and
+                              ;; it it's already in to-remove, add it to
+                              ;; to-remove.                          
+                              (if (and r
+                                       (not (member r to-remove)))
+                                  (push r to-remove))))
+                           ((file-directory-p (setq file (nnheader-concat d file)))
+                            (funcall checker file)))))))))
+        (funcall checker (expand-file-name gnus-agent-directory))
+
+        (when (and to-remove
+                   (or gnus-expert-user
+                       (gnus-y-or-n-p
+                        "gnus-agent-expire has identified local directories that are\
+ not currently required by any agentized group.         Do you wish to consider\
+ deleting them?")))
+          (while to-remove
+            (let ((dir (pop to-remove)))
+              (if (gnus-y-or-n-p (format "Delete %s? " dir))
+                  (let* (delete-recursive
+                         (delete-recursive
+                          (function
+                           (lambda (f-or-d)
+                             (ignore-errors
+                               (if (file-directory-p f-or-d)
+                                   (condition-case nil
+                                       (delete-directory f-or-d)
+                                     (file-error
+                                      (mapcar (lambda (f)
+                                                (or (member f '("." ".."))
+                                                    (funcall delete-recursive
+                                                             (nnheader-concat
+                                                              f-or-d f))))
+                                              (directory-files f-or-d))
+                                      (delete-directory f-or-d)))
+                                 (delete-file f-or-d)))))))
+                    (funcall delete-recursive dir))))))))))
 
 ;;;###autoload
 (defun gnus-agent-batch ()
+  "Start Gnus, send queue and fetch session."
   (interactive)
   (let ((init-file-user "")
        (gnus-always-read-dribble-file t))
     (gnus))
-  (gnus-group-send-drafts)
-  (gnus-agent-fetch-session))
+  (let ((gnus-agent-confirmation-function 'gnus-agent-batch-confirmation))
+    (gnus-group-send-queue)
+    (gnus-agent-fetch-session)))
+
+(defun gnus-agent-unread-articles (group)
+  (let* ((read (gnus-info-read (gnus-get-info group)))
+        (known (gnus-agent-load-alist group))
+        (unread (list nil))
+        (tail-unread unread))
+    (while (and known read)
+      (let ((candidate (car (pop known))))
+       (while (let* ((range (car read))
+                     (min   (if (numberp range) range (car range)))
+                     (max   (if (numberp range) range (cdr range))))
+                (cond ((or (not min)
+                           (< candidate min))
+                       (gnus-agent-append-to-list tail-unread candidate)
+                       nil)
+                      ((> candidate max)
+                       (setq read (cdr read))
+                        ;; return t so that I always loop one more
+                        ;; time.  If I just iterated off the end of
+                        ;; read, min will become nil and the current
+                        ;; candidate will be added to the unread list.
+                        t))))))
+    (while known
+      (gnus-agent-append-to-list tail-unread (car (pop known))))
+    (cdr unread)))
+
+(defun gnus-agent-uncached-articles (articles group &optional cached-header)
+  "Restrict ARTICLES to numbers already fetched.
+Returns a sublist of ARTICLES that excludes thos article ids in GROUP
+that have already been fetched.
+If CACHED-HEADER is nil, articles are only excluded if the article itself
+has been fetched."
+
+  ;; Logically equivalent to: (gnus-sorted-difference articles (mapcar
+  ;; 'car gnus-agent-article-alist))
+
+  ;; Functionally, I don't need to construct a temp list using mapcar.
+
+  (if (and (or gnus-agent-cache (not gnus-plugged))
+           (gnus-agent-load-alist group))
+    (let* ((ref gnus-agent-article-alist)
+           (arts articles)
+           (uncached (list nil))
+           (tail-uncached uncached))
+      (while (and ref arts)
+        (let ((v1 (car arts))
+              (v2 (caar ref)))
+          (cond ((< v1 v2) ; v1 does not appear in the reference list
+                (gnus-agent-append-to-list tail-uncached v1)
+                 (setq arts (cdr arts)))
+                ((= v1 v2)
+                 (unless (or cached-header (cdar ref)) ; v1 is already cached
+                  (gnus-agent-append-to-list tail-uncached v1))
+                 (setq arts (cdr arts))
+                 (setq ref (cdr ref)))
+                (t ; reference article (v2) preceeds the list being filtered
+                 (setq ref (cdr ref))))))
+      (while arts
+       (gnus-agent-append-to-list tail-uncached (pop arts)))
+      (cdr uncached))
+    ;; if gnus-agent-load-alist fails, no articles are cached.
+    articles))
+
+(defun gnus-agent-retrieve-headers (articles group &optional fetch-old)
+  (save-excursion
+    (gnus-agent-create-buffer)
+    (let ((gnus-decode-encoded-word-function 'identity)
+         (file (gnus-agent-article-name ".overview" group))
+         cached-articles uncached-articles)
+      (gnus-make-directory (nnheader-translate-file-chars
+                           (file-name-directory file) t))
+
+      ;; Populate temp buffer with known headers
+      (when (file-exists-p file)
+       (with-current-buffer gnus-agent-overview-buffer
+         (erase-buffer)
+         (let ((nnheader-file-coding-system
+                gnus-agent-file-coding-system))
+           (nnheader-insert-nov-file file (car articles)))))
+
+      (if (setq uncached-articles (gnus-agent-uncached-articles articles group
+                                                                t))
+         (progn
+            ;; Populate nntp-server-buffer with uncached headers
+           (set-buffer nntp-server-buffer)
+           (erase-buffer)
+            (cond ((not (eq 'nov (let (gnus-agent) ; Turn off agent
+                                   (gnus-retrieve-headers
+                                    uncached-articles group fetch-old))))
+                   (nnvirtual-convert-headers))
+                  ((eq 'nntp (car gnus-current-select-method))
+                   ;; The author of gnus-get-newsgroup-headers-xover
+                   ;; reports that the XOVER command is commonly
+                   ;; unreliable. The problem is that recently
+                   ;; posted articles may not be entered into the
+                   ;; NOV database in time to respond to my XOVER
+                   ;; query.
+                   ;;
+                   ;; I'm going to use his assumption that the NOV
+                   ;; database is updated in order of ascending
+                   ;; article ID.  Therefore, a response containing
+                   ;; article ID N implies that all articles from 1
+                   ;; to N-1 are up-to-date.  Therefore, missing
+                   ;; articles in that range have expired.
+
+                   (set-buffer nntp-server-buffer)
+                   (let* ((fetched-articles (list nil))
+                          (tail-fetched-articles fetched-articles)
+                          (min (cond ((numberp fetch-old)
+                                      (max 1 (- (car articles) fetch-old)))
+                                     (fetch-old
+                                      1)
+                                     (t
+                                      (car articles))))
+                          (max (car (last articles))))
+
+                     ;; Get the list of articles that were fetched
+                     (goto-char (point-min))
+                     (let ((pm (point-max)))
+                       (while (< (point) pm)
+                         (when (looking-at "[0-9]+\t")
+                           (gnus-agent-append-to-list
+                            tail-fetched-articles
+                            (read (current-buffer))))
+                         (forward-line 1)))
+
+                     ;; Clip this list to the headers that will
+                     ;; actually be returned
+                     (setq fetched-articles (gnus-list-range-intersection
+                                             (cdr fetched-articles)
+                                             (cons min max)))
+
+                     ;; Clip the uncached articles list to exclude
+                     ;; IDs after the last FETCHED header.  The
+                     ;; excluded IDs may be fetchable using HEAD.
+                     (if (car tail-fetched-articles)
+                         (setq uncached-articles
+                               (gnus-list-range-intersection
+                                uncached-articles
+                                (cons (car uncached-articles)
+                                      (car tail-fetched-articles)))))
+
+                     ;; Create the list of articles that were
+                     ;; "successfully" fetched.  Success, in this
+                     ;; case, means that the ID should not be
+                     ;; fetched again.  In the case of an expired
+                     ;; article, the header will not be fetched.
+                     (setq uncached-articles
+                           (gnus-sorted-nunion fetched-articles
+                                               uncached-articles))
+                     )))
+
+            ;; Erase the temp buffer
+           (set-buffer gnus-agent-overview-buffer)
+           (erase-buffer)
+
+            ;; Copy the nntp-server-buffer to the temp buffer
+           (set-buffer nntp-server-buffer)
+           (copy-to-buffer gnus-agent-overview-buffer (point-min) (point-max))
+
+            ;; Merge the temp buffer with the known headers (found on
+            ;; disk in FILE) into the nntp-server-buffer
+           (when (and uncached-articles (file-exists-p file))
+             (gnus-agent-braid-nov group uncached-articles file))
+
+            ;; Save the new set of known headers to FILE
+           (set-buffer nntp-server-buffer)
+           (gnus-agent-check-overview-buffer)
+           (write-region-as-coding-system
+            gnus-agent-file-coding-system
+            (point-min) (point-max) file nil 'silent)
+
+            ;; Update the group's article alist to include the newly
+            ;; fetched articles.
+           (gnus-agent-load-alist group)
+           (gnus-agent-save-alist group uncached-articles nil)
+            )
+
+        ;; Copy the temp buffer to the nntp-server-buffer
+        (set-buffer nntp-server-buffer)
+       (erase-buffer)
+       (insert-buffer-substring gnus-agent-overview-buffer)))
+
+    (if (and fetch-old
+            (not (numberp fetch-old)))
+       t                               ; Don't remove anything.
+      (nnheader-nov-delete-outside-range
+       (if fetch-old (max 1 (- (car articles) fetch-old))
+        (car articles))
+       (car (last articles)))
+      t)
+
+    'nov))
+
+(defun gnus-agent-request-article (article group)
+  "Retrieve ARTICLE in GROUP from the agent cache."
+  (when (and gnus-agent
+             (or gnus-agent-cache
+                 (not gnus-plugged))
+             (numberp article))
+    (let* ((gnus-command-method (gnus-find-method-for-group group))
+           (file (gnus-agent-article-name (number-to-string article) group))
+           (buffer-read-only nil))
+      (when (and (file-exists-p file)
+                 (> (nth 7 (file-attributes file)) 0))
+        (erase-buffer)
+        (gnus-kill-all-overlays)
+       (insert-file-contents-as-coding-system gnus-cache-coding-system file)
+        t))))
+
+(defun gnus-agent-regenerate-group (group &optional reread)
+  "Regenerate GROUP.
+If REREAD is t, all articles in the .overview are marked as unread.
+If REREAD is not nil, downloaded articles are marked as unread."
+  (interactive
+   (list (let ((def (or (gnus-group-group-name)
+                        gnus-newsgroup-name)))
+           (let ((select (read-string (if def
+                                          (concat "Group Name ("
+                                                  def "): ")
+                                        "Group Name: "))))
+             (if (and (equal "" select)
+                      def)
+                 def
+               select)))
+         (catch 'mark
+           (while (let ((c (read-char-exclusive 
+                            "Mark as unread: (n)one / (a)ll / all (d)ownloaded articles? (n)"
+                            )))
+                    (cond ((or (eq c ?\r) (eq c ?n) (eq c ?N))
+                           (throw 'mark nil))
+                          ((or (eq c ?a) (eq c ?A))
+                           (throw 'mark t))
+                          ((or (eq c ?d) (eq c ?D))
+                           (throw 'mark 'some)))
+                    (message "Ignoring unexpected input")
+                    (sit-for 1)
+                    t)))))
+
+  (when group
+      (gnus-message 5 "Regenerating in %s" group)
+      (let* ((gnus-command-method (or gnus-command-method
+                                      (gnus-find-method-for-group group)))
+             (file (gnus-agent-article-name ".overview" group))
+             (dir (file-name-directory file))
+             point
+             (downloaded (if (file-exists-p dir)
+                             (sort (mapcar (lambda (name) (string-to-int name))
+                                           (directory-files dir nil "^[0-9]+$" t))
+                                   '>)
+                           (progn (gnus-make-directory dir) nil)))
+             dl nov-arts
+             alist header
+             regenerated)
+
+        (mm-with-unibyte-buffer
+          (if (file-exists-p file)
+              (let ((nnheader-file-coding-system
+                     gnus-agent-file-coding-system))
+                (nnheader-insert-file-contents file)))
+          (set-buffer-modified-p nil)
+
+          ;; Load the article IDs found in the overview file.  As a
+          ;; side-effect, validate the file contents.
+          (let ((load t))
+            (while load
+              (setq load nil)
+              (goto-char (point-min))
+              (while (< (point) (point-max))
+                (cond ((and (looking-at "[0-9]+\t")
+                            (<= (- (match-end 0) (match-beginning 0)) 9))
+                       (push (read (current-buffer)) nov-arts)
+                       (forward-line 1)
+                       (let ((l1 (car nov-arts))
+                             (l2 (cadr nov-arts)))
+                         (cond ((not l2)
+                                nil)
+                               ((< l1 l2)
+                                (gnus-message 3 "gnus-agent-regenerate-group: NOV\
+ entries are NOT in ascending order.")
+                                ;; Don't sort now as I haven't verified
+                                ;; that every line begins with a number
+                                (setq load t))
+                               ((= l1 l2)
+                                (forward-line -1)
+                                (gnus-message 4 "gnus-agent-regenerate-group: NOV\
+ entries contained duplicate of article %s.     Duplicate deleted." l1)
+                                (gnus-delete-line)
+                                (setq nov-arts (cdr nov-arts))))))
+                      (t
+                       (gnus-message 1 "gnus-agent-regenerate-group: NOV\
+ entries contained line that did not begin with an article number.  Deleted\
+ line.")
+                       (gnus-delete-line))))
+              (if load
+                  (progn
+                    (gnus-message 5 "gnus-agent-regenerate-group: Sorting NOV\
+ entries into ascending order.")
+                    (sort-numeric-fields 1 (point-min) (point-max))
+                    (setq nov-arts nil)))))
+          (gnus-agent-check-overview-buffer)
+
+          ;; Construct a new article alist whose nodes match every header
+          ;; in the .overview file.  As a side-effect, missing headers are
+          ;; reconstructed from the downloaded article file.
+          (while (or downloaded nov-arts)
+            (cond ((and downloaded
+                        (or (not nov-arts)
+                            (> (car downloaded) (car nov-arts))))
+                   ;; This entry is missing from the overview file
+                   (gnus-message 3 "Regenerating NOV %s %d..." group
+                                 (car downloaded))
+                   (let ((file (concat dir (number-to-string (car downloaded)))))
+                     (mm-with-unibyte-buffer
+                       (nnheader-insert-file-contents file)
+                       (nnheader-remove-body)
+                       (setq header (nnheader-parse-naked-head)))
+                     (mail-header-set-number header (car downloaded))
+                     (if nov-arts
+                         (let ((key (concat "^" (int-to-string (car nov-arts))
+                                            "\t")))
+                           (or (re-search-backward key nil t)
+                               (re-search-forward key))
+                           (forward-line 1))
+                       (goto-char (point-min)))
+                     (nnheader-insert-nov header))
+                   (setq nov-arts (cons (car downloaded) nov-arts)))
+                  ((eq (car downloaded) (car nov-arts))
+                   ;; This entry in the overview has been downloaded
+                   (push (cons (car downloaded)
+                               (time-to-days
+                                (nth 5 (file-attributes
+                                        (concat dir (number-to-string
+                                                     (car downloaded))))))) alist)
+                   (setq downloaded (cdr downloaded))
+                   (setq nov-arts (cdr nov-arts)))
+                  (t
+                   ;; This entry in the overview has not been downloaded
+                   (push (cons (car nov-arts) nil) alist)
+                   (setq nov-arts (cdr nov-arts)))))
+
+          ;; When gnus-agent-consider-all-articles is set,
+          ;; gnus-agent-regenerate-group should NOT remove article IDs from
+          ;; the alist.  Those IDs serve as markers to indicate that an
+          ;; attempt has been made to fetch that article's header.
+
+          ;; When gnus-agent-consider-all-articles is NOT set,
+          ;; gnus-agent-regenerate-group can remove the article ID of every
+          ;; article (with the exception of the last ID in the list - it's
+          ;; special) that no longer appears in the overview.  In this
+          ;; situtation, the last article ID in the list implies that it,
+          ;; and every article ID preceeding it, have been fetched from the
+          ;; server.
+
+          (if gnus-agent-consider-all-articles
+              ;; Restore all article IDs that were not found in the overview file.
+              (let* ((n (cons nil alist))
+                     (merged n)
+                     (o (gnus-agent-load-alist group)))
+                (while o
+                  (let ((nID (caadr n))
+                        (oID (caar o)))
+                    (cond ((not nID)
+                           (setq n (setcdr n (list (list oID))))
+                           (setq o (cdr o)))
+                          ((< oID nID)
+                           (setcdr n (cons (list oID) (cdr n)))
+                           (setq o (cdr o)))
+                          ((= oID nID)
+                           (setq o (cdr o))
+                           (setq n (cdr n)))
+                          (t
+                           (setq n (cdr n))))))
+                (setq alist (cdr merged)))
+            ;; Restore the last article ID if it is not already in the new alist
+            (let ((n (last alist))
+                  (o (last (gnus-agent-load-alist group))))
+              (cond ((not o)
+                     nil)
+                    ((not n)
+                     (push (cons (caar o) nil) alist))
+                    ((< (caar n) (caar o))
+                     (setcdr n (list (car o)))))))
+
+          (let ((inhibit-quit t))
+            (if (setq regenerated (buffer-modified-p))
+               (write-region-as-coding-system
+                gnus-agent-file-coding-system
+                (point-min) (point-max) file nil 'silent))
+
+            (setq regenerated (or regenerated
+                                  (and reread gnus-agent-article-alist)
+                                  (not (equal alist gnus-agent-article-alist))))
+
+            (setq gnus-agent-article-alist alist)
+
+            (when regenerated
+              (gnus-agent-save-alist group)
+       
+              ;; I have to alter the group's active range NOW as
+              ;; gnus-make-ascending-articles-unread will use it to
+              ;; recalculate the number of unread articles in the group
+
+              (let ((group (gnus-group-real-name group))
+                    (group-active (gnus-active group)))
+                (when group-active
+                  (let ((new-min (or (caar gnus-agent-article-alist)
+                                     (car group-active)))
+                        (new-max (or (caar (last gnus-agent-article-alist))
+                                     (cdr group-active))))
+
+                    (when (< new-min (car group-active))
+                      (setcar group-active new-min))
+             
+                    (when (> new-max (cdr group-active))
+                      (setcdr group-active new-max))))))))
+
+        (when (and reread gnus-agent-article-alist)
+          (gnus-make-ascending-articles-unread
+           group
+           (delq nil (mapcar (function (lambda (c)
+                                         (cond ((eq reread t)
+                                                (car c))
+                                               ((cdr c)
+                                                (car c)))))
+                             gnus-agent-article-alist)))
+
+          (when (gnus-buffer-live-p gnus-group-buffer)
+            (gnus-group-update-group group t)
+            (sit-for 0)))
+
+        (gnus-message 5 nil)
+        regenerated)))
+
+;;;###autoload
+(defun gnus-agent-regenerate (&optional clean reread)
+  "Regenerate all agent covered files.
+If CLEAN, obsolete (ignore)."
+  (interactive "P")
+  (let (regenerated)
+    (gnus-message 4 "Regenerating Gnus agent files...")
+    (dolist (gnus-command-method (gnus-agent-covered-methods))
+        (dolist (group (gnus-groups-from-server gnus-command-method))
+          (setq regenerated (or (gnus-agent-regenerate-group group reread)
+                                regenerated))))
+    (gnus-message 4 "Regenerating Gnus agent files...done")
+
+    regenerated))
+
+(defun gnus-agent-go-online (&optional force)
+  "Switch servers into online status."
+  (interactive (list t))
+  (dolist (server gnus-opened-servers)
+    (when (eq (nth 1 server) 'offline)
+      (if (if (eq force 'ask)
+             (gnus-y-or-n-p
+              (format "Switch %s:%s into online status? "
+                      (caar server) (cadar server)))
+           force)
+         (setcar (nthcdr 1 server) 'close)))))
+
+(defun gnus-agent-toggle-group-plugged (group)
+  "Toggle the status of the server of the current group."
+  (interactive (list (gnus-group-group-name)))
+  (let* ((method (gnus-find-method-for-group group))
+        (status (cadr (assoc method gnus-opened-servers))))
+    (if (eq status 'offline)
+       (gnus-server-set-status method 'closed)
+      (gnus-close-server method)
+      (gnus-server-set-status method 'offline))
+    (message "Turn %s:%s from %s to %s." (car method) (cadr method)
+            (if (eq status 'offline) 'offline 'online)
+            (if (eq status 'offline) 'online 'offline))))
+
+(defun gnus-agent-group-covered-p (group)
+  (gnus-agent-method-p (gnus-group-method group)))
+
+(add-hook 'gnus-group-prepare-hook
+          (lambda ()
+            'gnus-agent-do-once
+
+            (when (listp gnus-agent-expire-days)
+              (beep)
+              (beep)
+              (gnus-message 1 "WARNING: gnus-agent-expire-days no longer\
+ supports being set to a list.")(sleep-for 3)
+              (gnus-message 1 "Change your configuration to set it to an\
+ integer.")(sleep-for 3)
+              (gnus-message 1 "I am now setting group parameters on each\
+ group to match the configuration that the list offered.")
+
+              (save-excursion
+                (let ((groups (gnus-group-listed-groups)))
+                  (while groups
+                    (let* ((group (pop groups))
+                           (days gnus-agent-expire-days)
+                           (day (catch 'found
+                                  (while days
+                                    (when (eq 0 (string-match
+                                                 (caar days)
+                                                 group))
+                                      (throw 'found (cadar days)))
+                                    (setq days (cdr days)))
+                                  nil)))
+                      (when day
+                        (gnus-group-set-parameter group 'agent-days-until-old
+                                                  day))))))
+
+              (let ((h gnus-group-prepare-hook))
+                (while h
+                  (let ((func (pop h)))
+                    (when (and (listp func)
+                               (eq (cadr (caddr func)) 'gnus-agent-do-once))
+                      (remove-hook 'gnus-group-prepare-hook func)
+                      (setq h nil)))))
+
+              (gnus-message 1 "I have finished setting group parameters on\
+ each group. You may now customize your groups and/or topics to control the\
+ agent."))))
 
 (provide 'gnus-agent)
 
index 215423d..549117a 100644 (file)
@@ -1,8 +1,11 @@
-;;; gnus-art.el --- article mode commands for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;;; gnus-art.el --- article mode commands for Semi-gnus
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile
+  (require 'cl)
+  (require 'static)
+  (defvar tool-bar-map))
 
-(require 'custom)
+(require 'path-util)
 (require 'gnus)
 (require 'gnus-sum)
 (require 'gnus-spec)
 (require 'gnus-int)
-(require 'browse-url)
+(require 'gnus-win)
+(require 'alist)
+(require 'mime-view)
+(when (static-if (featurep 'xemacs)
+         (console-on-window-system-p)
+       window-system)
+  (require 'mime-image))
+(require 'wid-edit)
+
+;; Avoid byte-compile warnings.
+(eval-when-compile
+  (require 'mm-bodies)
+  (require 'mail-parse)
+  (require 'mm-decode)
+  (require 'mm-view)
+  (require 'mm-uu))
+
+(require 'message)
+
+(autoload 'gnus-msg-mail "gnus-msg" nil t)
+(autoload 'gnus-button-mailto "gnus-msg")
+(autoload 'gnus-button-reply "gnus-msg" nil t)
 
 (defgroup gnus-article nil
   "Article display."
   :link '(custom-manual "(gnus)The Article Buffer")
   :group 'gnus)
 
+(defgroup gnus-article-treat nil
+  "Treating article parts."
+  :link '(custom-manual "(gnus)Article Hiding")
+  :group 'gnus-article)
+
 (defgroup gnus-article-hiding nil
   "Hiding article parts."
   :link '(custom-manual "(gnus)Article Hiding")
   :group 'gnus-article)
 
 (defcustom gnus-ignored-headers
-  '("^Path:" "^Posting-Version:" "^Article-I.D.:" "^Expires:"
-    "^Date-Received:" "^References:" "^Control:" "^Xref:" "^Lines:"
-    "^Posted:" "^Relay-Version:" "^Message-ID:" "^Nf-ID:" "^Nf-From:"
-    "^Approved:" "^Sender:" "^Received:" "^Mail-from:")
+  (mapcar
+   (lambda (header)
+     (concat "^" header ":"))
+   '("Path" "Expires" "Date-Received" "References" "Xref" "Lines"
+     "Relay-Version" "Message-ID" "Approved" "Sender" "Received"
+     "X-UIDL" "MIME-Version" "Return-Path" "In-Reply-To"
+     "Content-Type" "Content-Transfer-Encoding" "X-WebTV-Signature"
+     "X-MimeOLE" "X-MSMail-Priority" "X-Priority" "X-Loop"
+     "X-Authentication-Warning" "X-MIME-Autoconverted" "X-Face"
+     "X-Attribution" "X-Originating-IP" "Delivered-To"
+     "NNTP-[-A-Za-z]+" "Distribution" "X-no-archive" "X-Trace"
+     "X-Complaints-To" "X-NNTP-Posting-Host" "X-Orig.*"
+     "Abuse-Reports-To" "Cache-Post-Path" "X-Article-Creation-Date"
+     "X-Poster" "X-Mail2News-Path" "X-Server-Date" "X-Cache"
+     "Originator" "X-Problems-To" "X-Auth-User" "X-Post-Time"
+     "X-Admin" "X-UID" "Resent-[-A-Za-z]+" "X-Mailing-List"
+     "Precedence" "Original-[-A-Za-z]+" "X-filename" "X-Orcpt"
+     "Old-Received" "X-Pgp" "X-Auth" "X-From-Line"
+     "X-Gnus-Article-Number" "X-Majordomo" "X-Url" "X-Sender"
+     "MBOX-Line" "Priority" "X400-[-A-Za-z]+"
+     "Status" "X-Gnus-Mail-Source" "Cancel-Lock"
+     "X-FTN" "X-EXP32-SerialNo" "Encoding" "Importance"
+     "Autoforwarded" "Original-Encoded-Information-Types" "X-Ya-Pop3"
+     "X-Face-Version" "X-Vms-To" "X-ML-NAME" "X-ML-COUNT"
+     "Mailing-List" "X-finfo" "X-md5sum" "X-md5sum-Origin"
+     "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-Received" "Content-length" "X-precedence"
+     "X-Authenticated-User" "X-Comment" "X-Report" "X-Abuse-Info"
+     "X-HTTP-Proxy" "X-Mydeja-Info" "X-Copyright" "X-No-Markup"
+     "X-Abuse-Info" "X-From_" "X-Accept-Language" "Errors-To"
+     "X-BeenThere" "X-Mailman-Version" "List-Help" "List-Post"
+     "List-Subscribe" "List-Id" "List-Unsubscribe" "List-Archive"
+     "X-Content-length" "X-Posting-Agent" "Original-Received"
+     "X-Request-PGP" "X-Fingerprint" "X-WRIEnvto" "X-WRIEnvfrom"
+     "X-Virus-Scanned" "X-Delivery-Agent" "Posted-Date" "X-Gateway"
+     "X-Local-Origin" "X-Local-Destination" "X-UserInfo1"
+     "X-Received-Date" "X-Hashcash" "Face" "X-DMCA-Notifications"
+     "X-Abuse-and-DMCA-Info" "X-Postfilter" "X-Gpg-.*" "X-Disclaimer"))
   "*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."
@@ -104,7 +173,7 @@ If `gnus-visible-headers' is non-nil, this variable will be ignored."
   :group 'gnus-article-hiding)
 
 (defcustom gnus-visible-headers
-  "From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-From:\\|X-Sent:"
+  "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^[BGF]?Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Mail-Followup-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-From:\\|^X-Sent:"
   "*All headers that do not match this regexp will be hidden.
 This variable can also be a list of regexp of headers to remain visible.
 If this variable is non-nil, `gnus-ignored-headers' will be ignored."
@@ -128,15 +197,37 @@ this list."
 
 (defcustom gnus-boring-article-headers '(empty followup-to reply-to)
   "Headers that are only to be displayed if they have interesting data.
-Possible values in this list are `empty', `newsgroups', `followup-to',
-`reply-to', `date', `long-to', and `many-to'."
+Possible values in this list are:
+
+  'empty       Headers with no content.
+  'newsgroups  Newsgroup identical to Gnus group.
+  'to-address  To identical to To-address.
+  'to-list     To identical to To-list.
+  'cc-list     CC identical to To-list.
+  'followup-to Followup-to identical to Newsgroups.
+  'reply-to    Reply-to identical to From.
+  'date        Date less than four days old.
+  'long-to     To and/or Cc longer than 1024 characters.
+  'many-to     Multiple To and/or Cc."
   :type '(set (const :tag "Headers with no content." empty)
-             (const :tag "Newsgroups with only one group." newsgroups)
-             (const :tag "Followup-to identical to newsgroups." followup-to)
-             (const :tag "Reply-to identical to from." reply-to)
+             (const :tag "Newsgroups identical to Gnus group." newsgroups)
+             (const :tag "To identical to To-address." to-address)
+             (const :tag "To identical to To-list." to-list)
+             (const :tag "CC identical to To-list." cc-list)
+             (const :tag "Followup-to identical to Newsgroups." followup-to)
+             (const :tag "Reply-to identical to From." reply-to)
              (const :tag "Date less than four days old." date)
-             (const :tag "Very long To header." long-to)
-             (const :tag "Multiple To headers." many-to))
+             (const :tag "To and/or Cc longer than 1024 characters." long-to)
+             (const :tag "Multiple To and/or Cc headers." many-to))
+  :group 'gnus-article-hiding)
+
+(defcustom gnus-article-skip-boring nil
+  "Skip over text that is not worth reading.
+By default, if you set this t, then Gnus will display citations and
+signatures, but will never scroll down to show you a page consisting
+only of boring text.  Boring text is controlled by
+`gnus-article-boring-faces'."
+  :type 'boolean
   :group 'gnus-article-hiding)
 
 (defcustom gnus-signature-separator '("^-- $" "^-- *$")
@@ -148,7 +239,7 @@ the end of the buffer."
   :group 'gnus-article-signature)
 
 (defcustom gnus-signature-limit nil
-   "Provide a limit to what is considered a signature.
+  "Provide a limit to what is considered a signature.
 If it is a number, no signature may not be longer (in characters) than
 that number.  If it is a floating point number, no signature may be
 longer (in lines) than that number.  If it is a function, the function
@@ -166,12 +257,54 @@ regexp.  If it matches, the text in question is not a signature."
   :type 'sexp
   :group 'gnus-article-hiding)
 
+;; Fixme: This isn't the right thing for mixed graphical and non-graphical
+;; frames in a session.
 (defcustom gnus-article-x-face-command
-  "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
+  (cond
+   (noninteractive
+    'ignore)
+   ((featurep 'xemacs)
+    (if (or (gnus-image-type-available-p 'xface)
+           (gnus-image-type-available-p 'pbm))
+       'gnus-display-x-face-in-from
+      "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | ee -"))
+   ((and (fboundp 'image-type-available-p)
+        (module-installed-p 'x-face-e21))
+    'x-face-decode-message-header)
+   ((gnus-image-type-available-p 'pbm)
+    'gnus-display-x-face-in-from)
+   ((and window-system
+        (module-installed-p 'x-face-mule))
+    'x-face-mule-gnus-article-display-x-face)
+   (t
+    "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | \
+display -"))
   "*String or function to be executed to display an X-Face header.
 If it is a string, the command will be executed in a sub-shell
 asynchronously.         The compressed face will be piped to this command."
-  :type 'string                                ;Leave function case to Lisp.
+  :type `(choice
+         ,@(let (x-face-e21 x-face-mule)
+             (if (featurep 'xemacs)
+                 nil
+               (setq x-face-e21 (module-installed-p 'x-face-e21)
+                     x-face-mule (module-installed-p 'x-face-mule)))
+             (delq nil
+                   (list
+                    'string
+                    (if (or (gnus-image-type-available-p 'xface)
+                            (gnus-image-type-available-p 'pbm))
+                        '(function-item gnus-display-x-face-in-from))
+                    (if (and x-face-e21
+                             (fboundp 'image-type-available-p))
+                        '(function-item
+                          :tag "x-face-decode-message-header (x-face-e21)"
+                          x-face-decode-message-header))
+                    (if x-face-mule
+                        '(function-item
+                          x-face-mule-gnus-article-display-x-face))
+                    'function))))
+  ;;:version "21.1"
+  :group 'gnus-picon
   :group 'gnus-article-washing)
 
 (defcustom gnus-article-x-face-too-ugly nil
@@ -179,25 +312,76 @@ asynchronously.    The compressed face will be piped to this command."
   :type '(choice regexp (const nil))
   :group 'gnus-article-washing)
 
+(defcustom gnus-article-banner-alist nil
+  "Banner alist for stripping.
+For example,
+     ((egroups . \"^[ \\t\\n]*-------------------+\\\\( \\\\(e\\\\|Yahoo! \\\\)Groups Sponsor -+\\\\)?....\\n\\\\(.+\\n\\\\)+\"))"
+  :version "21.1"
+  :type '(repeat (cons symbol regexp))
+  :group 'gnus-article-washing)
+
+(gnus-define-group-parameter
+ banner
+ :variable-document
+ "Alist of regexps (to match group names) and banner."
+ :variable-group gnus-article-washing
+ :parameter-type
+ '(choice :tag "Banner"
+         :value nil
+         (const :tag "Remove signature" signature)
+         (symbol :tag "Item in `gnus-article-banner-alist'" none)
+         regexp
+         (const :tag "None" nil))
+ :parameter-document
+ "If non-nil, specify how to remove `banners' from articles.
+
+Symbol `signature' means to remove signatures delimited by
+`gnus-signature-separator'.  Any other symbol is used to look up a
+regular expression to match the banner in `gnus-article-banner-alist'.
+A string is used as a regular expression to match the banner
+directly.")
+
+(defcustom gnus-article-address-banner-alist nil
+  "Alist of mail addresses and banners.
+Each element has the form (ADDRESS . BANNER), where ADDRESS is a regexp
+to match a mail address in the From: header, BANNER is one of a symbol
+`signature', an item in `gnus-article-banner-alist', a regexp and nil.
+If ADDRESS matches author's mail address, it will remove things like
+advertisements.  For example:
+
+\((\"@yoo-hoo\\\\.co\\\\.jp\\\\'\" . \"\\n_+\\nDo You Yoo-hoo!\\\\?\\n.*\\n.*\\n\"))
+"
+  :type '(repeat
+         (cons
+          (regexp :tag "Address")
+          (choice :tag "Banner" :value nil
+                  (const :tag "Remove signature" signature)
+                  (symbol :tag "Item in `gnus-article-banner-alist'" none)
+                  regexp
+                  (const :tag "None" nil))))
+  :group 'gnus-article-washing)
+
 (defcustom gnus-emphasis-alist
   (let ((format
-        "\\(\\s-\\|^\\|[-\"]\\|\\s(\\|\\s)\\)\\(%s\\(\\w+\\(\\s-+\\w+\\)*[.,]?\\)%s\\)\\(\\s-\\|[-?!.,;:\"]\\|\\s(\\|\\s)\\)")
+        "\\(\\s-\\|^\\|\\=\\|[-\"]\\|\\s(\\)\\(%s\\(\\w+\\(\\s-+\\w+\\)*[.,]?\\)%s\\)\\(\\([-,.;:!?\"]\\|\\s)\\)+\\s-\\|[?!.]\\s-\\|\\s)\\|\\s-\\)")
        (types
-        '(("_" "_" underline)
+        '(("\\*" "\\*" bold)
+          ("_" "_" underline)
           ("/" "/" italic)
-          ("\\*" "\\*" bold)
           ("_/" "/_" underline-italic)
           ("_\\*" "\\*_" underline-bold)
           ("\\*/" "/\\*" bold-italic)
           ("_\\*/" "/\\*_" underline-bold-italic))))
-    `(("\\(\\s-\\|^\\)\\(_\\(\\(\\w\\|_[^_]\\)+\\)_\\)\\(\\s-\\|[?!.,;]\\)"
-       2 3 gnus-emphasis-underline)
-      ,@(mapcar
+    `(,@(mapcar
         (lambda (spec)
           (list
-           (format format (car spec) (cadr spec))
-           2 3 (intern (format "gnus-emphasis-%s" (caddr spec)))))
-        types)))
+           (format format (car spec) (car (cdr spec)))
+           2 3 (intern (format "gnus-emphasis-%s" (nth 2 spec)))))
+        types)
+       ("\\(\\s-\\|^\\)\\(-\\(\\(\\w\\|-[^-]\\)+\\)-\\)\\(\\s-\\|[?!.,;]\\)"
+        2 3 gnus-emphasis-strikethru)
+       ("\\(\\s-\\|^\\)\\(_\\(\\(\\w\\|_[^_]\\)+\\)_\\)\\(\\s-\\|[?!.,;]\\)"
+        2 3 gnus-emphasis-underline)))
   "*Alist that says how to fontify certain phrases.
 Each item looks like this:
 
@@ -215,6 +399,15 @@ is the face used for highlighting."
                       face))
   :group 'gnus-article-emphasis)
 
+(defcustom gnus-emphasize-whitespace-regexp "^[ \t]+\\|[ \t]*\n"
+  "A regexp to describe whitespace which should not be emphasized.
+Typical values are \"^[ \\t]+\\\\|[ \\t]*\\n\" and \"[ \\t]+\\\\|[ \\t]*\\n\".
+The former avoids underlining of leading and trailing whitespace,
+and the latter avoids underlining any whitespace at all."
+  :version "21.1"
+  :group 'gnus-article-emphasis
+  :type 'regexp)
+
 (defface gnus-emphasis-bold '((t (:bold t)))
   "Face used for displaying strong emphasized text (*word*)."
   :group 'gnus-article-emphasis)
@@ -232,7 +425,7 @@ is the face used for highlighting."
   :group 'gnus-article-emphasis)
 
 (defface gnus-emphasis-underline-italic '((t (:italic t :underline t)))
-  "Face used for displaying underlined italic emphasized text (_*word*_)."
+  "Face used for displaying underlined italic emphasized text (_/word/_)."
   :group 'gnus-article-emphasis)
 
 (defface gnus-emphasis-bold-italic '((t (:bold t :italic t)))
@@ -242,7 +435,18 @@ is the face used for highlighting."
 (defface gnus-emphasis-underline-bold-italic
   '((t (:bold t :italic t :underline t)))
   "Face used for displaying underlined bold italic emphasized text.
-Esample: (_/*word*/_)."
+Example: (_/*word*/_)."
+  :group 'gnus-article-emphasis)
+
+(defface gnus-emphasis-strikethru (if (featurep 'xemacs)
+                                     '((t (:strikethru t)))
+                                   '((t (:strike-through t))))
+  "Face used for displaying strike-through text (-word-)."
+  :group 'gnus-article-emphasis)
+
+(defface gnus-emphasis-highlight-words
+  '((t (:background "black" :foreground "yellow")))
+  "Face used for displaying highlighted words."
   :group 'gnus-article-emphasis)
 
 (defcustom gnus-article-time-format "%a, %b %d %Y %T %Z"
@@ -257,8 +461,6 @@ be fed to `format-time-string'."
   :group 'gnus-article-washing)
 
 (eval-and-compile
-  (autoload 'hexl-hex-string-to-integer "hexl")
-  (autoload 'timezone-make-date-arpa-standard "timezone")
   (autoload 'mail-extract-address-components "mail-extr"))
 
 (defcustom gnus-save-all-headers t
@@ -298,6 +500,7 @@ Gnus provides the following functions:
 * gnus-summary-save-in-mail (Unix mail format)
 * gnus-summary-save-in-folder (MH folder)
 * gnus-summary-save-in-file (article format)
+* gnus-summary-save-body-in-file (article body)
 * gnus-summary-save-in-vm (use VM's folder format)
 * gnus-summary-write-to-file (article format -- overwrite)."
   :group 'gnus-article-saving
@@ -305,6 +508,7 @@ Gnus provides the following functions:
                (function-item gnus-summary-save-in-mail)
                (function-item gnus-summary-save-in-folder)
                (function-item gnus-summary-save-in-file)
+               (function-item gnus-summary-save-body-in-file)
                (function-item gnus-summary-save-in-vm)
                (function-item gnus-summary-write-to-file)))
 
@@ -360,19 +564,16 @@ be used as possible file names."
                         (cons :value ("" "") regexp (repeat string))
                         (sexp :value nil))))
 
-(defcustom gnus-strict-mime t
-  "*If nil, MIME-decode even if there is no Mime-Version header."
-  :group 'gnus-article-mime
-  :type 'boolean)
-
-(defcustom gnus-show-mime-method 'metamail-buffer
-  "Function to process a MIME message.
+(defcustom gnus-article-display-method-for-mime
+  'gnus-article-display-mime-message
+  "Function to display a MIME message.
 The function is called from the article buffer."
   :group 'gnus-article-mime
   :type 'function)
 
-(defcustom gnus-decode-encoded-word-method 'gnus-article-de-quoted-unreadable
-  "*Function to decode MIME encoded words.
+(defcustom gnus-article-display-method-for-traditional
+  'gnus-article-display-traditional-message
+  "*Function to display a traditional message.
 The function is called from the article buffer."
   :group 'gnus-article-mime
   :type 'function)
@@ -384,9 +585,14 @@ beginning of a line."
   :type 'regexp
   :group 'gnus-article-various)
 
-(defcustom gnus-article-mode-line-format "Gnus: %%b %S"
+(defcustom gnus-article-mode-line-format "Gnus: %g [%w] %S%m"
   "*The format specification for the article mode line.
-See `gnus-summary-mode-line-format' for a closer description."
+See `gnus-summary-mode-line-format' for a closer description.
+
+The following additional specs are available:
+
+%w  The article washing status.
+%m  The number of MIME parts in the article."
   :type 'string
   :group 'gnus-article-various)
 
@@ -395,21 +601,25 @@ See `gnus-summary-mode-line-format' for a closer description."
   :type 'hook
   :group 'gnus-article-various)
 
+(when (featurep 'xemacs)
+  ;; Extracted from gnus-xmas-define in order to preserve user settings
+  (when (fboundp 'turn-off-scroll-in-place)
+    (add-hook 'gnus-article-mode-hook 'turn-off-scroll-in-place))
+  ;; Extracted from gnus-xmas-redefine in order to preserve user settings
+  (add-hook 'gnus-article-mode-hook 'gnus-xmas-article-menu-add))
+
 (defcustom gnus-article-menu-hook nil
   "*Hook run after the creation of the article mode menu."
   :type 'hook
   :group 'gnus-article-various)
 
 (defcustom gnus-article-prepare-hook nil
-  "*A hook called after an article has been prepared in the article buffer.
-If you want to run a special decoding program like nkf, use this hook."
+  "*A hook called after an article has been prepared in the article buffer."
   :type 'hook
   :group 'gnus-article-various)
 
-(defcustom gnus-article-hide-pgp-hook nil
-  "*A hook called after successfully hiding a PGP signature."
-  :type 'hook
-  :group 'gnus-article-various)
+(make-obsolete-variable 'gnus-article-hide-pgp-hook
+                       "This variable is obsolete in Gnus 5.10.")
 
 (defcustom gnus-article-button-face 'bold
   "Face used for highlighting buttons in the article buffer.
@@ -435,7 +645,7 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
   :group 'gnus-article-signature)
 
 (defface gnus-signature-face
-  '((((type x))
+  '((t
      (:italic t)))
   "Face used for highlighting a signature in the article buffer."
   :group 'gnus-article-highlight
@@ -444,12 +654,12 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
 (defface gnus-header-from-face
   '((((class color)
       (background dark))
-     (:foreground "spring green" :bold t))
+     (:foreground "spring green"))
     (((class color)
       (background light))
-     (:foreground "red3" :bold t))
+     (:foreground "red3"))
     (t
-     (:bold t :italic t)))
+     (:italic t)))
   "Face used for displaying from headers."
   :group 'gnus-article-headers
   :group 'gnus-article-highlight)
@@ -457,10 +667,10 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
 (defface gnus-header-subject-face
   '((((class color)
       (background dark))
-     (:foreground "SeaGreen3" :bold t))
+     (:foreground "SeaGreen3"))
     (((class color)
       (background light))
-     (:foreground "red4" :bold t))
+     (:foreground "red4"))
     (t
      (:bold t :italic t)))
   "Face used for displaying subject headers."
@@ -470,13 +680,15 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
 (defface gnus-header-newsgroups-face
   '((((class color)
       (background dark))
-     (:foreground "yellow" :bold t :italic t))
+     (:foreground "yellow" :italic t))
     (((class color)
       (background light))
-     (:foreground "MidnightBlue" :bold t :italic t))
+     (:foreground "MidnightBlue" :italic t))
     (t
-     (:bold t :italic t)))
-  "Face used for displaying newsgroups headers."
+     (:italic t)))
+  "Face used for displaying newsgroups headers.
+In the default setup this face is only used for crossposted
+articles."
   :group 'gnus-article-headers
   :group 'gnus-article-highlight)
 
@@ -501,7 +713,8 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
       (background light))
      (:foreground "indianred4" :italic t))
     (t
-     (:italic t)))  "Face used for displaying header content."
+     (:italic t)))
+  "Face used for displaying header content."
   :group 'gnus-article-headers
   :group 'gnus-article-highlight)
 
@@ -510,17 +723,17 @@ Obsolete; use the face `gnus-signature-face' for customizations instead."
     ("Subject" nil gnus-header-subject-face)
     ("Newsgroups:.*," nil gnus-header-newsgroups-face)
     ("" gnus-header-name-face gnus-header-content-face))
-  "*Controls highlighting of article header.
+  "*Controls highlighting of article headers.
 
 An alist of the form (HEADER NAME CONTENT).
 
-HEADER is a regular expression which should match the name of an
-header header and NAME and CONTENT are either face names or nil.
+HEADER is a regular expression which should match the name of a
+header and NAME and CONTENT are either face names or nil.
 
 The name of each header field will be displayed using the face
-specified by the first element in the list where HEADER match the
-header name and NAME is non-nil.  Similarly, the content will be
-displayed by the first non-nil matching CONTENT face."
+specified by the first element in the list where HEADER matches
+the header name and NAME is non-nil.  Similarly, the content will
+be displayed by the first non-nil matching CONTENT face."
   :group 'gnus-article-headers
   :group 'gnus-article-highlight
   :type '(repeat (list (regexp :tag "Header")
@@ -531,16 +744,815 @@ displayed by the first non-nil matching CONTENT face."
                               (item :tag "skip" nil)
                               (face :value default)))))
 
+(defcustom gnus-article-decode-hook
+  '(article-decode-group-name article-decode-idna-rhs)
+  "*Hook run to decode charsets in articles."
+  :group 'gnus-article-headers
+  :type 'hook)
+
+(defcustom gnus-display-mime-function 'gnus-display-mime
+  "Function to display MIME articles."
+  :group 'gnus-article-mime
+  :type 'function)
+
+(defvar gnus-decode-header-function 'mail-decode-encoded-word-region
+  "Function used to decode headers.")
+
+(defvar gnus-article-dumbquotes-map
+  '(("\200" "EUR")
+    ("\202" ",")
+    ("\203" "f")
+    ("\204" ",,")
+    ("\205" "...")
+    ("\213" "<")
+    ("\214" "OE")
+    ("\221" "`")
+    ("\222" "'")
+    ("\223" "``")
+    ("\224" "\"")
+    ("\225" "*")
+    ("\226" "-")
+    ("\227" "--")
+    ("\230" "~")
+    ("\231" "(TM)")
+    ("\233" ">")
+    ("\234" "oe")
+    ("\264" "'"))
+  "Table for MS-to-Latin1 translation.")
+
+(defcustom gnus-ignored-mime-types nil
+  "List of MIME types that should be ignored by Gnus."
+  :version "21.1"
+  :group 'gnus-article-mime
+  :type '(repeat regexp))
+
+(defcustom gnus-unbuttonized-mime-types '(".*/.*")
+  "List of MIME types that should not be given buttons when rendered inline.
+See also `gnus-buttonized-mime-types' which may override this variable.
+This variable is only used when `gnus-inhibit-mime-unbuttonizing' is nil."
+  :version "21.1"
+  :group 'gnus-article-mime
+  :type '(repeat regexp))
+
+(defcustom gnus-buttonized-mime-types nil
+  "List of MIME types that should be given buttons when rendered inline.
+If set, this variable overrides `gnus-unbuttonized-mime-types'.
+To see e.g. security buttons you could set this to
+`(\"multipart/signed\")'.
+This variable is only used when `gnus-inhibit-mime-unbuttonizing' is nil."
+  :version "21.1"
+  :group 'gnus-article-mime
+  :type '(repeat regexp))
+
+(defcustom gnus-inhibit-mime-unbuttonizing nil
+  "If non-nil, all MIME parts get buttons.
+When nil (the default value), then some MIME parts do not get buttons,
+as described by the variables `gnus-buttonized-mime-types' and
+`gnus-unbuttonized-mime-types'."
+  :version "21.3"
+  :type 'boolean)
+
+(defcustom gnus-body-boundary-delimiter "_"
+  "String used to delimit header and body.
+This variable is used by `gnus-article-treat-body-boundary' which can
+be controlled by `gnus-treat-body-boundary'."
+  :group 'gnus-article-various
+  :type '(choice (item :tag "None" :value nil)
+                string))
+
+(defcustom gnus-picon-databases '("/usr/lib/picon" "/usr/local/faces")
+  "Defines the location of the faces database.
+For information on obtaining this database of pretty pictures, please
+see http://www.cs.indiana.edu/picons/ftp/index.html"
+  :type '(repeat directory)
+  :link '(url-link :tag "download"
+                  "http://www.cs.indiana.edu/picons/ftp/index.html")
+  :link '(custom-manual "(gnus)Picons")
+  :group 'gnus-picon)
+
+(defun gnus-picons-installed-p ()
+  "Say whether picons are installed on your machine."
+  (let ((installed nil))
+    (dolist (database gnus-picon-databases)
+      (when (file-exists-p database)
+       (setq installed t)))
+    installed))
+
+(defcustom gnus-article-mime-part-function nil
+  "Function called with a MIME handle as the argument.
+This is meant for people who want to do something automatic based
+on parts -- for instance, adding Vcard info to a database."
+  :group 'gnus-article-mime
+  :type 'function)
+
+(defcustom gnus-mime-multipart-functions nil
+  "An alist of MIME types to functions to display them."
+  :version "21.1"
+  :group 'gnus-article-mime
+  :type 'alist)
+
+(defcustom gnus-article-date-lapsed-new-header nil
+  "Whether the X-Sent and Date headers can coexist.
+When using `gnus-treat-date-lapsed', the \"X-Sent:\" header will
+either replace the old \"Date:\" header (if this variable is nil), or
+be added below it (otherwise)."
+  :version "21.1"
+  :group 'gnus-article-headers
+  :type 'boolean)
+
+(defcustom gnus-article-mime-match-handle-function 'undisplayed-alternative
+  "Function called with a MIME handle as the argument.
+This is meant for people who want to view first matched part.
+For `undisplayed-alternative' (default), the first undisplayed
+part or alternative part is used.  For `undisplayed', the first
+undisplayed part is used.  For a function, the first part which
+the function return t is used.  For nil, the first part is
+used."
+  :version "21.1"
+  :group 'gnus-article-mime
+  :type '(choice
+         (item :tag "first" :value nil)
+         (item :tag "undisplayed" :value undisplayed)
+         (item :tag "undisplayed or alternative"
+               :value undisplayed-alternative)
+         (function)))
+
+(defcustom gnus-mime-action-alist
+  '(("save to file" . gnus-mime-save-part)
+    ("save and strip" . gnus-mime-save-part-and-strip)
+    ("delete part" . gnus-mime-delete-part)
+    ("display as text" . gnus-mime-inline-part)
+    ("view the part" . gnus-mime-view-part)
+    ("pipe to command" . gnus-mime-pipe-part)
+    ("toggle display" . gnus-article-press-button)
+    ("toggle display" . gnus-article-view-part-as-charset)
+    ("view as type" . gnus-mime-view-part-as-type)
+    ("view internally" . gnus-mime-view-part-internally)
+    ("view externally" . gnus-mime-view-part-externally))
+  "An alist of actions that run on the MIME attachment."
+  :group 'gnus-article-mime
+  :type '(repeat (cons (string :tag "name")
+                      (function))))
+
+;;;
+;;; The treatment variables
+;;;
+
+(defvar gnus-part-display-hook nil
+  "Hook called on parts that are to receive treatment.")
+
+(defvar gnus-article-treat-custom
+  '(choice (const :tag "Off" nil)
+          (const :tag "On" t)
+          (const :tag "Header" head)
+          (const :tag "Last" last)
+          (const :tag "Mime" mime)
+          (integer :tag "Less")
+          (repeat :tag "Groups" regexp)
+          (sexp :tag "Predicate")))
+
+(defvar gnus-article-treat-head-custom
+  '(choice (const :tag "Off" nil)
+          (const :tag "Header" head)))
+
+(defvar gnus-article-treat-types '("text/plain")
+  "Parts to treat.")
+
+(defvar gnus-inhibit-treatment nil
+  "Whether to inhibit treatment.")
+
+(defcustom gnus-treat-highlight-signature '(or t (typep "text/x-vcard"))
+  "Highlight the signature.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles'."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-highlight-signature 'highlight t)
+
+(defcustom gnus-treat-buttonize 100000
+  "Add buttons.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles'."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-buttonize 'highlight t)
+
+(defcustom gnus-treat-buttonize-head 'head
+  "Add buttons to the head.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-buttonize-head 'highlight t)
+
+(defcustom gnus-treat-emphasize
+  (and (or window-system
+          (featurep 'xemacs)
+          (>= (string-to-number emacs-version) 21))
+       50000)
+  "Emphasize text.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-emphasize 'highlight t)
+
+(defcustom gnus-treat-strip-cr nil
+  "Remove carriage returns.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-unsplit-urls nil
+  "Remove newlines from within URLs.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-leading-whitespace nil
+  "Remove leading whitespace in headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-hide-headers 'head
+  "Hide headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-hide-boring-headers nil
+  "Hide boring headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-hide-signature nil
+  "Hide the signature.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-fill-article nil
+  "Fill the article.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-hide-citation nil
+  "Hide cited text.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-hide-citation-maybe nil
+  "Hide cited text.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-strip-list-identifiers 'head
+  "Strip list identifiers from `gnus-list-identifiers`.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(make-obsolete-variable 'gnus-treat-strip-pgp
+                       "This option is obsolete in Gnus 5.10.")
+
+(defcustom gnus-treat-strip-pem nil
+  "Strip PEM signatures.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-strip-banner t
+  "Strip banners from articles.
+The banner to be stripped is specified in the `banner' group parameter.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-highlight-headers 'head
+  "Highlight the headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-highlight-headers 'highlight t)
+
+(defcustom gnus-treat-highlight-citation t
+  "Highlight cited text.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-highlight-citation 'highlight t)
+
+(defcustom gnus-treat-date-ut nil
+  "Display the Date in UT (GMT).
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-local nil
+  "Display the Date in the local timezone.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-english nil
+  "Display the Date in a format that can be read aloud in English.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-lapsed nil
+  "Display the Date header in a way that says how much time has elapsed.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-original nil
+  "Display the date in the original timezone.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-iso8601 nil
+  "Display the date in the ISO8601 format.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-date-user-defined nil
+  "Display the date in a user-defined format.
+The format is defined by the `gnus-article-time-format' variable.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-strip-headers-in-body t
+  "Strip the X-No-Archive header line from the beginning of the body.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-strip-trailing-blank-lines nil
+  "Strip trailing blank lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-strip-leading-blank-lines nil
+  "Strip leading blank lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-strip-multiple-blank-lines nil
+  "Strip multiple blank lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-unfold-headers 'head
+  "Unfold folded header lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-fold-headers nil
+  "Fold headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-fold-newsgroups 'head
+  "Fold the Newsgroups and Followup-To headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-overstrike t
+  "Treat overstrike highlighting.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-overstrike 'highlight t)
+
+(make-obsolete-variable 'gnus-treat-display-xface
+                       'gnus-treat-display-x-face)
+
+(defcustom gnus-treat-display-x-face
+  (and (not noninteractive)
+       (or (memq gnus-article-x-face-command
+                '(x-face-decode-message-header
+                  x-face-mule-gnus-article-display-x-face))
+          (and (fboundp 'image-type-available-p)
+               (image-type-available-p 'xbm)
+               (string-match "^0x" (shell-command-to-string "uncompface"))
+               (executable-find "icontopbm"))
+          (and (featurep 'xemacs)
+               (featurep 'xface)))
+       'head)
+  "Display X-Face headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)X-Face' for details."
+  :group 'gnus-article-treat
+  ;;:version "21.1"
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)X-Face")
+  :type gnus-article-treat-head-custom
+  :set (lambda (symbol value)
+        (set-default
+         symbol
+         (cond ((or (boundp symbol) (get symbol 'saved-value))
+                value)
+               ((boundp 'gnus-treat-display-xface)
+                (message "\
+** gnus-treat-display-xface is an obsolete variable;\
+ use gnus-treat-display-x-face instead")
+                (default-value 'gnus-treat-display-xface))
+               ((get 'gnus-treat-display-xface 'saved-value)
+                (message "\
+** gnus-treat-display-xface is an obsolete variable;\
+ use gnus-treat-display-x-face instead")
+                (eval (car (get 'gnus-treat-display-xface 'saved-value))))
+               (t
+                value)))))
+(put 'gnus-treat-display-x-face 'highlight t)
+
+(defcustom gnus-article-should-use-smiley-mule
+  (not (or (featurep 'xemacs)
+          (gnus-image-type-available-p 'xpm)
+          (gnus-image-type-available-p 'pbm)))
+  "If non-nil, gnus uses `smiley-mule' for displaying smileys rather than
+`smiley'.  It defaults to t when Emacs 20 or earlier is running.
+`smiley-mule' is boundled in BITMAP-MULE package.  You can set it to t
+even if you are using Emacs 21+.  It has no effect on XEmacs."
+  :group 'gnus-article-various
+  :type 'boolean
+  :get (lambda (symbol)
+        (and (not noninteractive)
+             (default-value symbol)
+             (not (featurep 'xemacs))
+             (module-installed-p 'smiley-mule)
+             t))
+  :set (lambda (symbol value)
+        (set-default symbol (and (not noninteractive)
+                                 value
+                                 (not (featurep 'xemacs))
+                                 (module-installed-p 'smiley-mule)
+                                 t))))
+
+(defvar gnus-article-smiley-mule-loaded-p nil
+  "Internal variable used to say whether `smiley-mule' is loaded (whether
+smiley functions are not overridden by `smiley').")
+
+(defcustom gnus-treat-display-face
+  (and (not noninteractive)
+       ;; x-face-e21 handles both X-Face and Face headers.
+       (not (and (eq gnus-article-x-face-command 'x-face-decode-message-header)
+                (module-installed-p 'x-face-e21)))
+       (or (and (fboundp 'image-type-available-p)
+               (image-type-available-p 'png))
+          (and (featurep 'xemacs)
+               (featurep 'png)))
+       'head)
+  "Display Face headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)X-Face' for details."
+  :group 'gnus-article-treat
+  :version "21.1"
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)X-Face")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-display-face 'highlight t)
+
+(defcustom gnus-treat-display-smileys
+  (if (and (not noninteractive)
+          (or (and (featurep 'xemacs)
+                   (featurep 'xpm))
+              (gnus-image-type-available-p 'xpm)
+              (gnus-image-type-available-p 'pbm)
+              (and (not (featurep 'xemacs))
+                   window-system
+                   (module-installed-p 'smiley-mule))))
+      t
+    nil)
+  "Display smileys.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)Smileys' for details."
+  :group 'gnus-article-treat
+  ;;:version "21.1"
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)Smileys")
+  :type gnus-article-treat-custom)
+(put 'gnus-treat-display-smileys 'highlight t)
+
+(defcustom gnus-treat-from-picon
+  (if (and (gnus-image-type-available-p 'xpm)
+          (gnus-picons-installed-p))
+      'head nil)
+  "Display picons in the From header.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)Picons' for details."
+  :group 'gnus-article-treat
+  :group 'gnus-picon
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)Picons")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-from-picon 'highlight t)
+
+(defcustom gnus-treat-mail-picon
+  (if (and (gnus-image-type-available-p 'xpm)
+          (gnus-picons-installed-p))
+      'head nil)
+  "Display picons in To and Cc headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)Picons' for details."
+  :group 'gnus-article-treat
+  :group 'gnus-picon
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)Picons")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-mail-picon 'highlight t)
+
+(defcustom gnus-treat-newsgroups-picon
+  (if (and (gnus-image-type-available-p 'xpm)
+          (gnus-picons-installed-p))
+      'head nil)
+  "Display picons in the Newsgroups and Followup-To headers.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' and Info node
+`(gnus)Picons' for details."
+  :group 'gnus-article-treat
+  :group 'gnus-picon
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :link '(custom-manual "(gnus)Picons")
+  :type gnus-article-treat-head-custom)
+(put 'gnus-treat-newsgroups-picon 'highlight t)
+
+(defcustom gnus-treat-body-boundary
+  (if (or gnus-treat-newsgroups-picon
+         gnus-treat-mail-picon
+         gnus-treat-from-picon)
+      'head nil)
+  "Draw a boundary at the end of the headers.
+Valid values are nil and `head'.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-head-custom)
+
+(defcustom gnus-treat-capitalize-sentences nil
+  "Capitalize sentence-starting words.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-wash-html nil
+  "Format as HTML.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-fill-long-lines nil
+  "Fill long lines.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-play-sounds nil
+  "Play sounds.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-decode-article-as-default-mime-charset nil
+  "Decode an article as `default-mime-charset'.  For instance, if you want to
+attempt to decode an article even if the value of `gnus-show-mime' is nil,
+you could set this variable to something like: nil for don't decode, t for
+decode the body, '(or header t) for the whole article, etc."
+  :group 'gnus-article-treat
+  :type '(radio (const :tag "Off" nil)
+               (const :tag "Decode body" t)
+               (const :tag "Decode all" (or head t))))
+
+(defcustom gnus-treat-translate nil
+  "Translate articles from one language to another.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :version "21.1"
+  :group 'gnus-article-treat
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-x-pgp-sig nil
+  "Verify X-PGP-Sig.
+To automatically treat X-PGP-Sig, set it to head.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :group 'mime-security
+  :type gnus-article-treat-custom)
+
+(defcustom gnus-treat-monafy nil
+  "Display body part with mona font.
+Valid values are nil, t, `head', `last', an integer or a predicate.
+See Info node `(gnus)Customizing Articles' for details."
+  :group 'gnus-article-treat
+  :group 'mime-security
+  :link '(custom-manual "(gnus)Customizing Articles")
+  :type gnus-article-treat-custom)
+
+(defvar gnus-article-encrypt-protocol-alist
+  '(("PGP" . mml2015-self-encrypt)))
+
+;; Set to nil if more than one protocol added to
+;; gnus-article-encrypt-protocol-alist.
+(defcustom gnus-article-encrypt-protocol "PGP"
+  "The protocol used for encrypt articles.
+It is a string, such as \"PGP\". If nil, ask user."
+  :type 'string
+  :group 'mime-security)
+
+(defvar gnus-article-wash-function nil
+  "Function used for converting HTML into text.")
+
+(defcustom gnus-use-idna (and (condition-case nil (require 'idna) (file-error))
+                             (mm-coding-system-p 'utf-8)
+                             (executable-find idna-program))
+  "Whether IDNA decoding of headers is used when viewing messages.
+This requires GNU Libidn, and by default only enabled if it is found."
+  :group 'gnus-article-headers
+  :type 'boolean)
+
+(defcustom gnus-article-over-scroll nil
+  "If non-nil, allow scrolling the article buffer even when there no more text."
+  :group 'gnus-article
+  :type 'boolean)
+
 ;;; Internal variables
 
+(defvar gnus-english-month-names
+  '("January" "February" "March" "April" "May" "June" "July" "August"
+    "September" "October" "November" "December"))
+
+(defvar article-goto-body-goes-to-point-min-p nil)
+(defvar gnus-article-wash-types nil)
+(defvar gnus-article-emphasis-alist nil)
+(defvar gnus-article-image-alist nil)
+
+(defvar gnus-article-mime-handle-alist-1 nil)
+(defvar gnus-treatment-function-alist
+  '((gnus-treat-decode-article-as-default-mime-charset
+     gnus-article-decode-article-as-default-mime-charset)
+    (gnus-treat-x-pgp-sig gnus-article-verify-x-pgp-sig)
+    (gnus-treat-monafy gnus-article-monafy)
+    (gnus-treat-strip-banner gnus-article-strip-banner)
+    (gnus-treat-strip-headers-in-body gnus-article-strip-headers-in-body)
+    (gnus-treat-buttonize gnus-article-add-buttons)
+    (gnus-treat-fill-article gnus-article-fill-cited-article)
+    (gnus-treat-fill-long-lines gnus-article-fill-long-lines)
+    (gnus-treat-strip-cr gnus-article-remove-cr)
+    (gnus-treat-unsplit-urls gnus-article-unsplit-urls)
+    (gnus-treat-date-ut gnus-article-date-ut)
+    (gnus-treat-date-local gnus-article-date-local)
+    (gnus-treat-date-english gnus-article-date-english)
+    (gnus-treat-date-lapsed gnus-article-date-lapsed)
+    (gnus-treat-date-original gnus-article-date-original)
+    (gnus-treat-date-user-defined gnus-article-date-user)
+    (gnus-treat-date-iso8601 gnus-article-date-iso8601)
+    (gnus-treat-display-face gnus-article-display-face)
+    (gnus-treat-hide-headers gnus-article-maybe-hide-headers)
+    (gnus-treat-hide-boring-headers gnus-article-hide-boring-headers)
+    (gnus-treat-hide-signature gnus-article-hide-signature)
+    (gnus-treat-strip-list-identifiers gnus-article-hide-list-identifiers)
+    (gnus-treat-leading-whitespace gnus-article-remove-leading-whitespace)
+    (gnus-treat-strip-pem gnus-article-hide-pem)
+    (gnus-treat-from-picon gnus-treat-from-picon)
+    (gnus-treat-mail-picon gnus-treat-mail-picon)
+    (gnus-treat-newsgroups-picon gnus-treat-newsgroups-picon)
+    (gnus-treat-highlight-headers gnus-article-highlight-headers)
+    (gnus-treat-highlight-signature gnus-article-highlight-signature)
+    (gnus-treat-strip-trailing-blank-lines
+     gnus-article-remove-trailing-blank-lines)
+    (gnus-treat-strip-leading-blank-lines
+     gnus-article-strip-leading-blank-lines)
+    (gnus-treat-strip-multiple-blank-lines
+     gnus-article-strip-multiple-blank-lines)
+    (gnus-treat-overstrike gnus-article-treat-overstrike)
+    (gnus-treat-unfold-headers gnus-article-treat-unfold-headers)
+    (gnus-treat-fold-headers gnus-article-treat-fold-headers)
+    ;; Displaying X-Face should be done after unfolding headers
+    ;; to protect bitmap lines.
+    (gnus-treat-display-x-face gnus-article-display-x-face)
+    (gnus-treat-fold-newsgroups gnus-article-treat-fold-newsgroups)
+    (gnus-treat-buttonize-head gnus-article-add-buttons-to-head)
+    (gnus-treat-display-smileys gnus-treat-smiley)
+    (gnus-treat-capitalize-sentences gnus-article-capitalize-sentences)
+    (gnus-treat-wash-html gnus-article-wash-html)
+    (gnus-treat-emphasize gnus-article-emphasize)
+    (gnus-treat-hide-citation gnus-article-hide-citation)
+    (gnus-treat-hide-citation-maybe gnus-article-hide-citation-maybe)
+    (gnus-treat-highlight-citation gnus-article-highlight-citation)
+    (gnus-treat-body-boundary gnus-article-treat-body-boundary)
+    (gnus-treat-play-sounds gnus-earcon-display)))
+
+(defvar gnus-article-mime-handle-alist nil)
 (defvar article-lapsed-timer nil)
 (defvar gnus-article-current-summary nil)
 
 (defvar gnus-article-mode-syntax-table
   (let ((table (copy-syntax-table text-mode-syntax-table)))
-    (modify-syntax-entry ?- "w" table)
-    (modify-syntax-entry ?> ")" table)
-    (modify-syntax-entry ?< "(" table)
+    ;; This causes the citation match run O(2^n).
+    ;; (modify-syntax-entry ?- "w" table)
+    (modify-syntax-entry ?> ")<" table)
+    (modify-syntax-entry ?< "(>" table)
+    ;; make M-. in article buffers work for `foo' strings
+    (modify-syntax-entry ?' " " table)
+    (modify-syntax-entry ?` " " table)
     table)
   "Syntax table used in article mode buffers.
 Initialized from `text-mode-syntax-table.")
@@ -548,16 +1560,45 @@ Initialized from `text-mode-syntax-table.")
 (defvar gnus-save-article-buffer nil)
 
 (defvar gnus-article-mode-line-format-alist
-  (nconc '((?w (gnus-article-wash-status) ?s))
+  (nconc '((?w (gnus-article-wash-status) ?s)
+          (?m (gnus-article-mime-part-status) ?s))
         gnus-summary-mode-line-format-alist))
 
 (defvar gnus-number-of-articles-to-be-saved nil)
 
 (defvar gnus-inhibit-hiding nil)
 
+;;; Macros for dealing with the article buffer.
+
+(defmacro gnus-with-article-headers (&rest forms)
+  `(save-excursion
+     (set-buffer gnus-article-buffer)
+     (save-restriction
+       (let ((buffer-read-only nil)
+            (inhibit-point-motion-hooks t)
+            (case-fold-search t))
+        (article-narrow-to-head)
+        ,@forms))))
+
+(put 'gnus-with-article-headers 'lisp-indent-function 0)
+(put 'gnus-with-article-headers 'edebug-form-spec '(body))
+
+(defmacro gnus-with-article-buffer (&rest forms)
+  `(save-excursion
+     (set-buffer gnus-article-buffer)
+     (let ((buffer-read-only nil))
+       ,@forms)))
+
+(put 'gnus-with-article-buffer 'lisp-indent-function 0)
+(put 'gnus-with-article-buffer 'edebug-form-spec '(body))
+
+(defun gnus-article-goto-header (header)
+  "Go to HEADER, which is a regular expression."
+  (re-search-forward (concat "^\\(" header "\\):") nil t))
+
 (defsubst gnus-article-hide-text (b e props)
   "Set text PROPS on the B to E region, extending `intangible' 1 past B."
-  (add-text-properties b e props)
+  (gnus-add-text-properties-when 'article-type nil b e props)
   (when (memq 'intangible props)
     (put-text-property
      (max (1- b) (point-min))
@@ -572,11 +1613,13 @@ Initialized from `text-mode-syntax-table.")
 
 (defun gnus-article-hide-text-type (b e type)
   "Hide text of TYPE between B and E."
+  (gnus-add-wash-type type)
   (gnus-article-hide-text
    b e (cons 'article-type (cons type gnus-hidden-properties))))
 
 (defun gnus-article-unhide-text-type (b e type)
-  "Hide text of TYPE between B and E."
+  "Unhide text of TYPE between B and E."
+  (gnus-delete-wash-type type)
   (remove-text-properties
    b e (cons 'article-type (cons type gnus-hidden-properties)))
   (when (memq 'intangible gnus-hidden-properties)
@@ -616,30 +1659,29 @@ Initialized from `text-mode-syntax-table.")
 (defsubst gnus-article-header-rank ()
   "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
   (let ((list gnus-sorted-header-list)
-       (i 0))
+       (i 1))
     (while list
-      (when (looking-at (car list))
-       (setq list nil))
-      (setq list (cdr list))
-      (incf i))
-    i))
+      (if (looking-at (car list))
+         (setq list nil)
+       (setq list (cdr list))
+       (incf i)))
+      i))
 
 (defun article-hide-headers (&optional arg delete)
-  "Toggle whether to hide unwanted headers and possibly sort them as well.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
+  "Hide unwanted headers and possibly sort them as well."
   (interactive (gnus-article-hidden-arg))
-  (current-buffer)
+  ;; Lars said that this function might be inhibited.
   (if (gnus-article-check-hidden-text 'headers arg)
-      ;; Show boring headers as well.
-      (gnus-article-show-hidden-text 'boring-headers)
-    ;; This function might be inhibited.
+      (progn
+       ;; Show boring headers as well.
+       (gnus-article-show-hidden-text 'boring-headers)
+       (when (eq 1 (point-min))
+         (set-window-start (get-buffer-window (current-buffer)) 1)))
     (unless gnus-inhibit-hiding
       (save-excursion
        (save-restriction
-         (let ((buffer-read-only nil)
-               (props (nconc (list 'article-type 'headers)
-                             gnus-hidden-properties))
+         (let ((inhibit-read-only t)
+               (case-fold-search t)
                (max (1+ (length gnus-sorted-header-list)))
                (ignored (when (not gnus-visible-headers)
                           (cond ((stringp gnus-ignored-headers)
@@ -654,29 +1696,24 @@ always hide."
                             (listp gnus-visible-headers))
                        (mapconcat 'identity gnus-visible-headers "\\|"))))
                (inhibit-point-motion-hooks t)
-               want-list beg)
+               beg)
            ;; First we narrow to just the headers.
-           (widen)
-           (goto-char (point-min))
+           (article-narrow-to-head)
            ;; Hide any "From " lines at the beginning of (mail) articles.
            (while (looking-at "From ")
              (forward-line 1))
            (unless (bobp)
              (if delete
                  (delete-region (point-min) (point))
-               (gnus-article-hide-text (point-min) (point) props)))
+               (gnus-article-hide-text (point-min) (point)
+                                       (nconc (list 'article-type 'headers)
+                                              gnus-hidden-properties))))
            ;; Then treat the rest of the header lines.
-           (narrow-to-region
-            (point)
-            (if (search-forward "\n\n" nil t) ; if there's a body
-                (progn (forward-line -1) (point))
-              (point-max)))
            ;; Then we use the two regular expressions
            ;; `gnus-ignored-headers' and `gnus-visible-headers' to
            ;; select which header lines is to remain visible in the
            ;; article buffer.
-           (goto-char (point-min))
-           (while (re-search-forward "^[^ \t]*:" nil t)
+           (while (re-search-forward "^[^ \t:]*:" nil t)
              (beginning-of-line)
              ;; Mark the rank of the header.
              (put-text-property
@@ -690,13 +1727,15 @@ always hide."
            (message-sort-headers-1)
            (when (setq beg (text-property-any
                             (point-min) (point-max) 'message-rank (+ 2 max)))
-             ;; We make the unwanted headers invisible.
+             ;; We delete or make invisible the unwanted headers.
+             (gnus-add-wash-type 'headers)
              (if delete
-                 (delete-region beg (point-max))
-               ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
-               (gnus-article-hide-text-type beg (point-max) 'headers))
-             ;; Work around XEmacs lossage.
-             (put-text-property (point-min) beg 'invisible nil))))))))
+                 (progn
+                   (add-text-properties
+                    (point-min) (+ 5 (point-min))
+                    '(article-type headers dummy-invisible t))
+                   (delete-region beg (point-max)))
+               (gnus-article-hide-text-type beg (point-max) 'headers)))))))))
 
 (defun article-hide-boring-headers (&optional arg)
   "Toggle hiding of headers that aren't very interesting.
@@ -711,17 +1750,17 @@ always hide."
              (list gnus-boring-article-headers)
              (inhibit-point-motion-hooks t)
              elem)
-         (nnheader-narrow-to-headers)
+         (article-narrow-to-head)
          (while list
            (setq elem (pop list))
            (goto-char (point-min))
            (cond
             ;; Hide empty headers.
             ((eq elem 'empty)
-             (while (re-search-forward "^[^:]+:[ \t]*\n[^ \t]" nil t)
+             (while (re-search-forward "^[^: \t]+:[ \t]*\n[^ \t]" nil t)
                (forward-line -1)
                (gnus-article-hide-text-type
-                (progn (beginning-of-line) (point))
+                (gnus-point-at-bol)
                 (progn
                   (end-of-line)
                   (if (re-search-forward "^[^ \t]" nil t)
@@ -730,38 +1769,93 @@ always hide."
                 'boring-headers)))
             ;; Hide boring Newsgroups header.
             ((eq elem 'newsgroups)
-             (when (equal (gnus-fetch-field "newsgroups")
-                          (gnus-group-real-name
-                           (if (boundp 'gnus-newsgroup-name)
-                               gnus-newsgroup-name
-                             "")))
+             (when (gnus-string-equal
+                    (gnus-fetch-field "newsgroups")
+                    (gnus-group-real-name
+                     (if (boundp 'gnus-newsgroup-name)
+                         gnus-newsgroup-name
+                       "")))
                (gnus-article-hide-header "newsgroups")))
+            ((eq elem 'to-address)
+             (let ((to (message-fetch-field "to"))
+                   (to-address
+                    (gnus-parameter-to-address
+                     (if (boundp 'gnus-newsgroup-name)
+                         gnus-newsgroup-name ""))))
+               (when (and to to-address
+                          (ignore-errors
+                            (gnus-string-equal
+                             ;; only one address in To
+                             (nth 1 (mail-extract-address-components to))
+                             to-address)))
+                 (gnus-article-hide-header "to"))))
+            ((eq elem 'to-list)
+             (let ((to (message-fetch-field "to"))
+                   (to-list
+                    (gnus-parameter-to-list
+                     (if (boundp 'gnus-newsgroup-name)
+                         gnus-newsgroup-name ""))))
+               (when (and to to-list
+                          (ignore-errors
+                            (gnus-string-equal
+                             ;; only one address in To
+                             (nth 1 (mail-extract-address-components to))
+                             to-list)))
+                 (gnus-article-hide-header "to"))))
+            ((eq elem 'cc-list)
+             (let ((cc (message-fetch-field "cc"))
+                   (to-list
+                    (gnus-parameter-to-list
+                     (if (boundp 'gnus-newsgroup-name)
+                         gnus-newsgroup-name ""))))
+               (when (and cc to-list
+                          (ignore-errors
+                            (gnus-string-equal
+                             ;; only one address in CC
+                             (nth 1 (mail-extract-address-components cc))
+                             to-list)))
+                 (gnus-article-hide-header "cc"))))
             ((eq elem 'followup-to)
-             (when (equal (message-fetch-field "followup-to")
-                          (message-fetch-field "newsgroups"))
+             (when (gnus-string-equal
+                    (message-fetch-field "followup-to")
+                    (message-fetch-field "newsgroups"))
                (gnus-article-hide-header "followup-to")))
             ((eq elem 'reply-to)
-             (let ((from (message-fetch-field "from"))
-                   (reply-to (message-fetch-field "reply-to")))
-               (when (and
+             (if (gnus-group-find-parameter
+                  gnus-newsgroup-name 'broken-reply-to)
+                 (gnus-article-hide-header "reply-to")
+               (let ((from (message-fetch-field "from"))
+                     (reply-to (message-fetch-field "reply-to")))
+                 (when
+                     (and
                       from reply-to
                       (ignore-errors
                         (equal
-                         (nth 1 (mail-extract-address-components from))
-                         (nth 1 (mail-extract-address-components reply-to)))))
-                 (gnus-article-hide-header "reply-to"))))
+                         (sort (mapcar
+                                (lambda (x) (downcase (cadr x)))
+                                (mail-extract-address-components from t))
+                               'string<)
+                         (sort (mapcar
+                                (lambda (x) (downcase (cadr x)))
+                                (mail-extract-address-components reply-to t))
+                               'string<))))
+                   (gnus-article-hide-header "reply-to")))))
             ((eq elem 'date)
              (let ((date (message-fetch-field "date")))
                (when (and date
-                          (< (gnus-days-between (current-time-string) date)
+                          (< (days-between (current-time-string) date)
                              4))
                  (gnus-article-hide-header "date"))))
             ((eq elem 'long-to)
-             (let ((to (message-fetch-field "to")))
+             (let ((to (message-fetch-field "to"))
+                   (cc (message-fetch-field "cc")))
                (when (> (length to) 1024)
-                 (gnus-article-hide-header "to"))))
+                 (gnus-article-hide-header "to"))
+               (when (> (length cc) 1024)
+                 (gnus-article-hide-header "cc"))))
             ((eq elem 'many-to)
-             (let ((to-count 0))
+             (let ((to-count 0)
+                   (cc-count 0))
                (goto-char (point-min))
                (while (re-search-forward "^to:" nil t)
                  (setq to-count (1+ to-count)))
@@ -773,14 +1867,26 @@ always hide."
                      (forward-line -1)
                      (narrow-to-region (point) (point-max))
                      (gnus-article-hide-header "to"))
-                   (setq to-count (1- to-count)))))))))))))
+                   (setq to-count (1- to-count))))
+               (goto-char (point-min))
+               (while (re-search-forward "^cc:" nil t)
+                 (setq cc-count (1+ cc-count)))
+               (when (> cc-count 1)
+                 (while (> cc-count 0)
+                   (goto-char (point-min))
+                   (save-restriction
+                     (re-search-forward "^cc:" nil nil cc-count)
+                     (forward-line -1)
+                     (narrow-to-region (point) (point-max))
+                     (gnus-article-hide-header "cc"))
+                   (setq cc-count (1- cc-count)))))))))))))
 
 (defun gnus-article-hide-header (header)
   (save-excursion
     (goto-char (point-min))
     (when (re-search-forward (concat "^" header ":") nil t)
       (gnus-article-hide-text-type
-       (progn (beginning-of-line) (point))
+       (gnus-point-at-bol)
        (progn
         (end-of-line)
         (if (re-search-forward "^[^ \t]" nil t)
@@ -788,18 +1894,56 @@ always hide."
           (point-max)))
        'boring-headers))))
 
+(defvar gnus-article-normalized-header-length 40
+  "Length of normalized headers.")
+
+(defun article-normalize-headers ()
+  "Make all header lines 40 characters long."
+  (interactive)
+  (let ((buffer-read-only nil)
+       column)
+    (save-excursion
+      (save-restriction
+       (article-narrow-to-head)
+       (while (not (eobp))
+         (cond
+          ((< (setq column (- (gnus-point-at-eol) (point)))
+              gnus-article-normalized-header-length)
+           (end-of-line)
+           (insert (make-string
+                    (- gnus-article-normalized-header-length column)
+                    ? )))
+          ((> column gnus-article-normalized-header-length)
+           (gnus-put-text-property
+            (progn
+              (forward-char gnus-article-normalized-header-length)
+              (point))
+            (gnus-point-at-eol)
+            'invisible t))
+          (t
+           ;; Do nothing.
+           ))
+         (forward-line 1))))))
+
 (defun article-treat-dumbquotes ()
-  "Translate M******** sm*rtq**t*s into proper text."
+  "Translate M****s*** sm*rtq**t*s and other symbols into proper text.
+Note that this function guesses whether a character is a sm*rtq**t* or
+not, so it should only be used interactively.
+
+Sm*rtq**t*s are M****s***'s unilateral extension to the
+iso-8859-1 character map in an attempt to provide more quoting
+characters.  If you see something like \\222 or \\264 where
+you're expecting some kind of apostrophe or quotation mark, then
+try this wash."
   (interactive)
-  (article-translate-characters "\221\222\223\223" "`'\"\""))
+  (article-translate-strings gnus-article-dumbquotes-map))
 
 (defun article-translate-characters (from to)
   "Translate all characters in the body of the article according to FROM and TO.
 FROM is a string of characters to translate from; to is a string of
 characters to translate to."
   (save-excursion
-    (goto-char (point-min))
-    (when (search-forward "\n\n" nil t)
+    (when (article-goto-body)
       (let ((buffer-read-only nil)
            (x (make-string 225 ?x))
            (i -1))
@@ -811,59 +1955,185 @@ characters to translate to."
          (incf i))
        (translate-region (point) (point-max) x)))))
 
+(defun article-translate-strings (map)
+  "Translate all string in the body of the article according to MAP.
+MAP is an alist where the elements are on the form (\"from\" \"to\")."
+  (save-excursion
+    (when (article-goto-body)
+      (let ((buffer-read-only nil)
+           elem)
+       (while (setq elem (pop map))
+         (save-excursion
+           (while (search-forward (car elem) nil t)
+             (replace-match (cadr elem)))))))))
+
 (defun article-treat-overstrike ()
   "Translate overstrikes into bold text."
   (interactive)
   (save-excursion
-    (goto-char (point-min))
-    (when (search-forward "\n\n" nil t)
+    (when (article-goto-body)
       (let ((buffer-read-only nil))
        (while (search-forward "\b" nil t)
-         (let ((next (following-char))
-               (previous (char-after (- (point) 2))))
+         (let ((next (char-after))
+               start end previous)
+           (backward-char 2)
+           (setq start (point)
+                 previous (char-after))
+           (forward-char 3)
+           (setq end (point))
+           (backward-char)
            ;; We do the boldification/underlining by hiding the
            ;; overstrikes and putting the proper text property
            ;; on the letters.
            (cond
             ((eq next previous)
-             (gnus-article-hide-text-type (- (point) 2) (point) 'overstrike)
-             (put-text-property (point) (1+ (point)) 'face 'bold))
+             (gnus-article-hide-text-type start (point) 'overstrike)
+             (put-text-property (point) end 'face 'bold))
             ((eq next ?_)
              (gnus-article-hide-text-type
               (1- (point)) (1+ (point)) 'overstrike)
              (put-text-property
-              (- (point) 2) (1- (point)) 'face 'underline))
+              start (1- (point)) 'face 'underline))
             ((eq previous ?_)
-             (gnus-article-hide-text-type (- (point) 2) (point) 'overstrike)
+             (gnus-article-hide-text-type start (point) 'overstrike)
              (put-text-property
-              (point) (1+ (point)) 'face 'underline)))))))))
+              (point) end 'face 'underline)))))))))
+
+(defun gnus-article-treat-unfold-headers ()
+  "Unfold folded message headers.
+Only the headers that fit into the current window width will be
+unfolded."
+  (interactive)
+  (gnus-with-article-headers
+    (let (length)
+      (while (not (eobp))
+       (save-restriction
+         (mail-header-narrow-to-field)
+         (let ((header (buffer-string)))
+           (with-temp-buffer
+             (insert header)
+             (goto-char (point-min))
+             (while (re-search-forward "\n[\t ]" nil t)
+               (replace-match " " t t)))
+           (setq length (- (point-max) (point-min) 1)))
+         (when (< length (window-width))
+           (while (re-search-forward "\n[\t ]" nil t)
+             (replace-match " " t t)))
+         (goto-char (point-max)))))))
+
+(defun gnus-article-treat-fold-headers ()
+  "Fold message headers."
+  (interactive)
+  (gnus-with-article-headers
+    (while (not (eobp))
+      (save-restriction
+       (mail-header-narrow-to-field)
+       (mail-header-fold-field)
+       (goto-char (point-max))))))
 
-(defun article-fill ()
-  "Format too long lines."
+(defun gnus-treat-smiley ()
+  "Toggle display of textual emoticons (\"smileys\") as small graphical icons."
+  (interactive)
+  (unless (featurep 'xemacs)
+    (when (and (>= emacs-major-version 21)
+              (not gnus-article-should-use-smiley-mule)
+              gnus-article-smiley-mule-loaded-p)
+      (load "smiley" nil t)
+      (setq gnus-article-smiley-mule-loaded-p nil))
+    (when (and gnus-article-should-use-smiley-mule
+              (not gnus-article-smiley-mule-loaded-p))
+      (load "smiley-mule" nil t)
+      (setq gnus-article-smiley-mule-loaded-p t)))
+  (gnus-with-article-buffer
+    (if (memq 'smiley gnus-article-wash-types)
+       (gnus-delete-images 'smiley)
+      (article-goto-body)
+      (let ((images (smiley-region (point) (point-max))))
+       (when images
+         (gnus-add-wash-type 'smiley)
+         (dolist (image images)
+           (gnus-add-image 'smiley image)))))))
+
+(defun gnus-article-remove-images ()
+  "Remove all images from the article buffer."
+  (interactive)
+  (gnus-with-article-buffer
+    (dolist (elem gnus-article-image-alist)
+      (gnus-delete-images (car elem)))))
+
+(defun gnus-article-treat-fold-newsgroups ()
+  "Unfold folded message headers.
+Only the headers that fit into the current window width will be
+unfolded."
+  (interactive)
+  (gnus-with-article-headers
+    (while (gnus-article-goto-header "newsgroups\\|followup-to")
+      (save-restriction
+       (mail-header-narrow-to-field)
+       (while (re-search-forward ", *" nil t)
+         (replace-match ", " t t))
+       (mail-header-fold-field)
+       (goto-char (point-max))))))
+
+(defun gnus-article-treat-body-boundary ()
+  "Place a boundary line at the end of the headers."
+  (interactive)
+  (when (and gnus-body-boundary-delimiter
+            (> (length gnus-body-boundary-delimiter) 0))
+    (gnus-with-article-headers
+      (goto-char (point-max))
+      (let ((start (point)))
+       (insert "X-Boundary: ")
+       (gnus-add-text-properties start (point) '(invisible t intangible t))
+       (insert (let (str)
+                 (while (>= (1- (window-width)) (length str))
+                   (setq str (concat str gnus-body-boundary-delimiter)))
+                 (substring str 0 (1- (window-width))))
+               "\n")
+       (gnus-put-text-property start (point) 'gnus-decoration 'header)))))
+
+(defun article-fill-long-lines ()
+  "Fill lines that are wider than the window width."
   (interactive)
   (save-excursion
-    (let ((buffer-read-only nil))
-      (widen)
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (end-of-line 1)
-      (let ((paragraph-start "^[>|#:<;* ]*[ \t]*$")
-           (adaptive-fill-regexp "[ \t]*\\([|#:<;>*]+ *\\)?")
-           (adaptive-fill-mode t))
-       (while (not (eobp))
-         (and (>= (current-column) (min fill-column (window-width)))
-              (/= (preceding-char) ?:)
-              (fill-paragraph nil))
-         (end-of-line 2))))))
+    (let ((buffer-read-only nil)
+         (width (window-width (get-buffer-window (current-buffer)))))
+      (save-restriction
+       (article-goto-body)
+       (let ((adaptive-fill-mode nil)) ;Why?  -sm
+         (while (not (eobp))
+           (end-of-line)
+           (when (>= (current-column) (min fill-column width))
+             (narrow-to-region (min (1+ (point)) (point-max))
+                               (gnus-point-at-bol))
+             (let ((goback (point-marker)))
+               (fill-paragraph nil)
+               (goto-char (marker-position goback)))
+             (widen))
+           (forward-line 1)))))))
+
+(defun article-capitalize-sentences ()
+  "Capitalize the first word in each sentence."
+  (interactive)
+  (save-excursion
+    (let ((buffer-read-only nil)
+         (paragraph-start "^[\n\^L]"))
+      (article-goto-body)
+      (while (not (eobp))
+       (capitalize-word 1)
+       (forward-sentence)))))
 
 (defun article-remove-cr ()
-  "Remove carriage returns from an article."
+  "Remove trailing CRs and then translate remaining CRs into LFs."
   (interactive)
   (save-excursion
     (let ((buffer-read-only nil))
       (goto-char (point-min))
+      (while (re-search-forward "\r+$" nil t)
+       (replace-match "" t t))
+      (goto-char (point-min))
       (while (search-forward "\r" nil t)
-       (replace-match "" t t)))))
+       (replace-match "\n" t t)))))
 
 (defun article-remove-trailing-blank-lines ()
   "Remove all trailing blank lines from the article."
@@ -875,169 +2145,417 @@ characters to translate to."
        (point)
        (progn
         (while (and (not (bobp))
-                    (looking-at "^[ \t]*$"))
+                    (looking-at "^[ \t]*$")
+                    (not (gnus-annotation-in-region-p
+                          (point) (gnus-point-at-eol))))
           (forward-line -1))
         (forward-line 1)
         (point))))))
 
+(defun article-display-face ()
+  "Display any Face headers in the header."
+  (interactive)
+  (let ((wash-face-p buffer-read-only))
+    (gnus-with-article-headers
+      ;; When displaying parts, this function can be called several times on
+      ;; the same article, without any intended toggle semantic (as typing `W
+      ;; D d' would have). So face deletion must occur only when we come from
+      ;; an interactive command, that is when the *Article* buffer is
+      ;; read-only.
+      (if (and wash-face-p (memq 'face gnus-article-wash-types))
+         (gnus-delete-images 'face)
+       (let (face faces)
+         (save-excursion
+           (when (and wash-face-p
+                      (progn
+                        (goto-char (point-min))
+                        (not (re-search-forward "^Face:[\t ]*" nil t)))
+                      (gnus-buffer-live-p gnus-original-article-buffer))
+             (set-buffer gnus-original-article-buffer))
+           (save-restriction
+             (mail-narrow-to-head)
+             (while (gnus-article-goto-header "Face")
+               (push (mail-header-field-value) faces))))
+         (while (setq face (pop faces))
+           (let ((png (gnus-convert-face-to-png face))
+                 image)
+             (when png
+               (setq image (gnus-create-image png 'png t))
+               (gnus-article-goto-header "from")
+               (when (bobp)
+                 (insert "From: [no `from' set]\n")
+                 (forward-char -17))
+               (gnus-add-wash-type 'face)
+               (gnus-add-image 'face image)
+               (gnus-put-image image nil 'face))))))
+      )))
+
 (defun article-display-x-face (&optional force)
   "Look for an X-Face header and display it if present."
   (interactive (list 'force))
+  (let ((wash-face-p buffer-read-only))        ;; When type `W f'
+    (gnus-with-article-headers
+      ;; Delete the old process, if any.
+      (when (process-status "article-x-face")
+       (delete-process "article-x-face"))
+      ;; See the comment in `article-display-face'.
+      (if (and wash-face-p (memq 'xface gnus-article-wash-types))
+         ;; We have already displayed X-Faces, so we remove them
+         ;; instead.
+         (gnus-delete-images 'xface)
+       ;; Display X-Faces.
+       (let (x-faces from face)
+         (save-excursion
+           (when (and wash-face-p
+                      (progn
+                        (goto-char (point-min))
+                        (not (re-search-forward
+                              "^X-Face\\(-[0-9]+\\)?:[\t ]*" nil t)))
+                      (gnus-buffer-live-p gnus-original-article-buffer))
+             ;; If type `W f', use gnus-original-article-buffer,
+             ;; otherwise use the current buffer because displaying
+             ;; RFC822 parts calls this function too.
+             (set-buffer gnus-original-article-buffer))
+           (save-restriction
+             (mail-narrow-to-head)
+             (while (gnus-article-goto-header "X-Face")
+               (push (mail-header-field-value) x-faces))
+             (setq from (message-fetch-field "from"))))
+         ;; Sending multiple EOFs to xv doesn't work, so we only do a
+         ;; single external face.
+         (when (stringp gnus-article-x-face-command)
+           (setq x-faces (list (car x-faces))))
+         (while (and (setq face (pop x-faces))
+                     gnus-article-x-face-command
+                     (or force
+                         ;; Check whether this face is censored.
+                         (not gnus-article-x-face-too-ugly)
+                         (and gnus-article-x-face-too-ugly from
+                              (not (string-match gnus-article-x-face-too-ugly
+                                                 from)))))
+           ;; We display the face.
+           (cond ((stringp gnus-article-x-face-command)
+                  ;; The command is a string, so we interpret the command
+                  ;; as a, well, command, and fork it off.
+                  (let ((process-connection-type nil))
+                    (process-kill-without-query
+                     (start-process
+                      "article-x-face" nil shell-file-name
+                      shell-command-switch gnus-article-x-face-command))
+                    (with-temp-buffer
+                      (insert face)
+                      (process-send-region "article-x-face"
+                                           (point-min) (point-max)))
+                    (process-send-eof "article-x-face")))
+                 ((functionp gnus-article-x-face-command)
+                  ;; The command is a lisp function, so we call it.
+                  (funcall gnus-article-x-face-command face))
+                 (t
+                  (error "%s is not a function"
+                         gnus-article-x-face-command)))))))))
+
+(defun article-decode-mime-words ()
+  "Decode all MIME-encoded words in the article."
+  (interactive)
   (save-excursion
-    ;; Delete the old process, if any.
-    (when (process-status "article-x-face")
-      (delete-process "article-x-face"))
+    (set-buffer gnus-article-buffer)
     (let ((inhibit-point-motion-hooks t)
-         (case-fold-search t)
-         from)
+         buffer-read-only
+         (mail-parse-charset gnus-newsgroup-charset)
+         (mail-parse-ignored-charsets
+          (save-excursion (set-buffer gnus-summary-buffer)
+                          gnus-newsgroup-ignored-charsets)))
+      (mail-decode-encoded-word-region (point-min) (point-max)))))
+
+(defun article-decode-charset (&optional prompt)
+  "Decode charset-encoded text in the article.
+If PROMPT (the prefix), prompt for a coding system to use."
+  (interactive "P")
+  (let ((inhibit-point-motion-hooks t) (case-fold-search t)
+       buffer-read-only
+       (mail-parse-charset gnus-newsgroup-charset)
+       (mail-parse-ignored-charsets
+        (save-excursion (condition-case nil
+                            (set-buffer gnus-summary-buffer)
+                          (error))
+                        gnus-newsgroup-ignored-charsets))
+       ct cte ctl charset format)
+    (save-excursion
+      (save-restriction
+       (article-narrow-to-head)
+       (setq ct (message-fetch-field "Content-Type" t)
+             cte (message-fetch-field "Content-Transfer-Encoding" t)
+             ctl (and ct (ignore-errors
+                           (mail-header-parse-content-type ct)))
+             charset (cond
+                      (prompt
+                       (mm-read-coding-system "Charset to decode: "))
+                      (ctl
+                       (mail-content-type-get ctl 'charset)))
+             format (and ctl (mail-content-type-get ctl 'format)))
+       (when cte
+         (setq cte (mail-header-strip cte)))
+       (if (and ctl (not (string-match "/" (car ctl))))
+           (setq ctl nil))
+       (goto-char (point-max)))
+      (forward-line 1)
+      (save-restriction
+       (narrow-to-region (point) (point-max))
+       (when (and (eq mail-parse-charset 'gnus-decoded)
+                  (eq (mm-body-7-or-8) '8bit))
+         ;; The text code could have been decoded.
+         (setq charset mail-parse-charset))
+       (when (and (or (not ctl)
+                      (equal (car ctl) "text/plain"))
+                  (not format)) ;; article with format will decode later.
+         (mm-decode-body
+          charset (and cte (intern (downcase
+                                    (gnus-strip-whitespace cte))))
+          (car ctl)))))))
+
+(defun article-decode-encoded-words ()
+  "Remove encoded-word encoding from headers."
+  (let (buffer-read-only)
+    (let ((charset (save-excursion
+                    (set-buffer gnus-summary-buffer)
+                    default-mime-charset)))
+      (mime-decode-header-in-buffer charset))))
+
+(defun article-decode-group-name ()
+  "Decode group names in `Newsgroups:'."
+  (let ((inhibit-point-motion-hooks t)
+       buffer-read-only
+       (method (gnus-find-method-for-group gnus-newsgroup-name)))
+    (when (and (or gnus-group-name-charset-method-alist
+                  gnus-group-name-charset-group-alist)
+              (gnus-buffer-live-p gnus-original-article-buffer))
       (save-restriction
-       (nnheader-narrow-to-headers)
-       (setq from (message-fetch-field "from"))
+       (article-narrow-to-head)
+       (with-current-buffer gnus-original-article-buffer
+         (goto-char (point-min)))
+       (while (re-search-forward
+               "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" nil t)
+         (replace-match (save-match-data
+                          (gnus-decode-newsgroups
+                           ;; XXX how to use data in article buffer?
+                           (with-current-buffer gnus-original-article-buffer
+                             (re-search-forward
+                              "^Newsgroups:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+                              nil t)
+                             (match-string 1))
+                           gnus-newsgroup-name method))
+                        t t nil 1))
        (goto-char (point-min))
-       (while (and gnus-article-x-face-command
-                   (or force
-                       ;; Check whether this face is censored.
-                       (not gnus-article-x-face-too-ugly)
-                       (and gnus-article-x-face-too-ugly from
-                            (not (string-match gnus-article-x-face-too-ugly
-                                               from))))
-                   ;; Has to be present.
-                   (re-search-forward "^X-Face: " nil t))
-         ;; We now have the area of the buffer where the X-Face is stored.
-         (save-excursion
-           (let ((beg (point))
-                 (end (1- (re-search-forward "^\\($\\|[^ \t]\\)" nil t))))
-             ;; We display the face.
-             (if (symbolp gnus-article-x-face-command)
-                 ;; The command is a lisp function, so we call it.
-                 (if (gnus-functionp gnus-article-x-face-command)
-                     (funcall gnus-article-x-face-command beg end)
-                   (error "%s is not a function" gnus-article-x-face-command))
-               ;; The command is a string, so we interpret the command
-               ;; as a, well, command, and fork it off.
-               (let ((process-connection-type nil))
-                 (process-kill-without-query
-                  (start-process
-                   "article-x-face" nil shell-file-name shell-command-switch
-                   gnus-article-x-face-command))
-                 (process-send-region "article-x-face" beg end)
-                 (process-send-eof "article-x-face"))))))))))
-
-(defun gnus-hack-decode-rfc1522 ()
-  "Emergency hack function for avoiding problems when decoding."
-  (let ((buffer-read-only nil))
-    (goto-char (point-min))
-    ;; Remove encoded TABs.
-    (while (search-forward "=09" nil t)
-      (replace-match " " t t))
-    ;; Remove encoded newlines.
-    (goto-char (point-min))
-    (while (search-forward "=10" nil t)
-      (replace-match " " t t))))
-
-(defalias 'gnus-decode-rfc1522 'article-decode-rfc1522)
-(defalias 'gnus-article-decode-rfc1522 'article-decode-rfc1522)
-(defun article-decode-rfc1522 ()
-  "Hack to remove QP encoding from headers."
-  (let ((case-fold-search t)
-       (inhibit-point-motion-hooks t)
-       (buffer-read-only nil)
-       string)
+       (with-current-buffer gnus-original-article-buffer
+         (goto-char (point-min)))
+       (while (re-search-forward
+               "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]" nil t)
+         (replace-match (save-match-data
+                          (gnus-decode-newsgroups
+                           ;; XXX how to use data in article buffer?
+                           (with-current-buffer gnus-original-article-buffer
+                             (re-search-forward
+                              "^Followup-To:\\(\\(.\\|\n[\t ]\\)*\\)\n[^\t ]"
+                              nil t)
+                             (match-string 1))
+                           gnus-newsgroup-name method))
+                        t t nil 1))))))
+
+(autoload 'idna-to-unicode "idna")
+
+(defun article-decode-idna-rhs ()
+  "Decode IDNA strings in RHS in From:, To: and Cc: headers in current buffer."
+  (when gnus-use-idna
     (save-restriction
-      (narrow-to-region
-       (goto-char (point-min))
-       (or (search-forward "\n\n" nil t) (point-max)))
+      (let ((inhibit-point-motion-hooks t)
+           buffer-read-only)
+       (article-narrow-to-head)
+       (goto-char (point-min))
+       (while (re-search-forward "\\(xn--[-A-Za-z0-9.]*\\)[ \t\n\r,>]" nil t)
+         (let (ace unicode)
+           (when (save-match-data
+                   (and (setq ace (match-string 1))
+                        (save-excursion
+                          (and (re-search-backward "^[^ \t]" nil t)
+                               (looking-at "From\\|To\\|Cc")))
+                        (save-excursion (backward-char)
+                                        (message-idna-inside-rhs-p))
+                        (setq unicode (idna-to-unicode ace))))
+             (unless (string= ace unicode)
+               (replace-match unicode nil nil nil 1)))))))))
+
+(defun article-de-quoted-unreadable (&optional force read-charset)
+  "Translate a quoted-printable-encoded article.
+If FORCE, decode the article whether it is marked as quoted-printable
+or not.
+If READ-CHARSET, ask for a coding system."
+  (interactive (list 'force current-prefix-arg))
+  (save-excursion
+    (let ((buffer-read-only nil) type charset)
+      (if (gnus-buffer-live-p gnus-original-article-buffer)
+         (with-current-buffer gnus-original-article-buffer
+           (setq type
+                 (gnus-fetch-field "content-transfer-encoding"))
+           (let* ((ct (gnus-fetch-field "content-type"))
+                  (ctl (and ct
+                            (ignore-errors
+                              (mail-header-parse-content-type ct)))))
+             (setq charset (and ctl
+                                (mail-content-type-get ctl 'charset)))
+             (if (stringp charset)
+                 (setq charset (intern (downcase charset)))))))
+      (if read-charset
+         (setq charset (mm-read-coding-system "Charset: " charset)))
+      (unless charset
+       (setq charset gnus-newsgroup-charset))
+      (when (or force
+               (and type (let ((case-fold-search t))
+                           (string-match "quoted-printable" type))))
+       (article-goto-body)
+       (quoted-printable-decode-region
+        (point) (point-max) (mm-charset-to-coding-system charset))))))
+
+(defun article-de-base64-unreadable (&optional force read-charset)
+  "Translate a base64 article.
+If FORCE, decode the article whether it is marked as base64 not.
+If READ-CHARSET, ask for a coding system."
+  (interactive (list 'force current-prefix-arg))
+  (save-excursion
+    (let ((buffer-read-only nil) type charset)
+      (if (gnus-buffer-live-p gnus-original-article-buffer)
+         (with-current-buffer gnus-original-article-buffer
+           (setq type
+                 (gnus-fetch-field "content-transfer-encoding"))
+           (let* ((ct (gnus-fetch-field "content-type"))
+                  (ctl (and ct
+                            (ignore-errors
+                              (mail-header-parse-content-type ct)))))
+             (setq charset (and ctl
+                                (mail-content-type-get ctl 'charset)))
+             (if (stringp charset)
+                 (setq charset (intern (downcase charset)))))))
+      (if read-charset
+         (setq charset (mm-read-coding-system "Charset: " charset)))
+      (unless charset
+       (setq charset gnus-newsgroup-charset))
+      (when (or force
+               (and type (let ((case-fold-search t))
+                           (string-match "base64" type))))
+       (article-goto-body)
+       (save-restriction
+         (narrow-to-region (point) (point-max))
+         (base64-decode-region (point-min) (point-max))
+         (mm-decode-coding-region
+          (point-min) (point-max) (mm-charset-to-coding-system charset)))))))
+
+(eval-when-compile
+  (require 'rfc1843))
+
+(defun article-decode-HZ ()
+  "Translate a HZ-encoded article."
+  (interactive)
+  (require 'rfc1843)
+  (save-excursion
+    (let ((buffer-read-only nil))
+      (rfc1843-decode-region (point-min) (point-max)))))
+
+(defun article-unsplit-urls ()
+  "Remove the newlines that some other mailers insert into URLs."
+  (interactive)
+  (save-excursion
+    (let ((buffer-read-only nil))
       (goto-char (point-min))
       (while (re-search-forward
-             "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
-       (setq string (match-string 1))
-       (save-restriction
-         (narrow-to-region (match-beginning 0) (match-end 0))
-         (delete-region (point-min) (point-max))
-         (insert string)
-         (article-mime-decode-quoted-printable
-          (goto-char (point-min)) (point-max))
-         (subst-char-in-region (point-min) (point-max) ?_ ? )
-         (goto-char (point-max)))
-       (goto-char (point-min))))))
+             "^\\(\\(https?\\|ftp\\)://\\S-+\\) *\n\\(\\S-+\\)" nil t)
+       (replace-match "\\1\\3" t)))
+    (when (interactive-p)
+      (gnus-treat-article nil))))
 
-(defun article-de-quoted-unreadable (&optional force)
-  "Do a naive translation of a quoted-printable-encoded article.
-This is in no way, shape or form meant as a replacement for real MIME
-processing, but is simply a stop-gap measure until MIME support is
-written.
-If FORCE, decode the article whether it is marked as quoted-printable
-or not."
-  (interactive (list 'force))
+
+(defun article-wash-html (&optional read-charset)
+  "Format an HTML article.
+If READ-CHARSET, ask for a coding system."
+  (interactive "P")
   (save-excursion
-    (let ((case-fold-search t)
-         (buffer-read-only nil)
-         (type (gnus-fetch-field "content-transfer-encoding")))
-      (gnus-article-decode-rfc1522)
-      (when (or force
-               (and type (string-match "quoted-printable" (downcase type))))
-       (goto-char (point-min))
-       (search-forward "\n\n" nil 'move)
-       (article-mime-decode-quoted-printable (point) (point-max))))))
-
-(defun article-mime-decode-quoted-printable-buffer ()
-  "Decode Quoted-Printable in the current buffer."
-  (article-mime-decode-quoted-printable (point-min) (point-max)))
-
-(defun article-mime-decode-quoted-printable (from to)
-  "Decode Quoted-Printable in the region between FROM and TO."
-  (interactive "r")
-  (goto-char from)
-  (while (search-forward "=" to t)
-    (cond ((eq (following-char) ?\n)
-          (delete-char -1)
-          (delete-char 1))
-         ((looking-at "[0-9A-F][0-9A-F]")
-          (subst-char-in-region
-           (1- (point)) (point) ?=
-           (hexl-hex-string-to-integer
-            (buffer-substring (point) (+ 2 (point)))))
-          (delete-char 2))
-         ((looking-at "=")
-          (delete-char 1))
-         ((gnus-message 3 "Malformed MIME quoted-printable message")))))
-
-(defun article-hide-pgp (&optional arg)
-  "Toggle hiding of any PGP headers and signatures in the current article.
-If given a negative prefix, always show; if given a positive prefix,
-always hide."
-  (interactive (gnus-article-hidden-arg))
-  (unless (gnus-article-check-hidden-text 'pgp arg)
-    (save-excursion
-      (let ((inhibit-point-motion-hooks t)
-           buffer-read-only beg end)
-       (widen)
-       (goto-char (point-min))
-       ;; Hide the "header".
-       (when (search-forward "\n-----BEGIN PGP SIGNED MESSAGE-----\n" nil t)
-         (gnus-article-hide-text-type (1+ (match-beginning 0))
-                                      (match-end 0) 'pgp)
-         (setq beg (point))
-         ;; Hide the actual signature.
-         (and (search-forward "\n-----BEGIN PGP SIGNATURE-----\n" nil t)
-              (setq end (1+ (match-beginning 0)))
-              (gnus-article-hide-text-type
-               end
-               (if (search-forward "\n-----END PGP SIGNATURE-----\n" nil t)
-                   (match-end 0)
-                 ;; Perhaps we shouldn't hide to the end of the buffer
-                 ;; if there is no end to the signature?
-                 (point-max))
-               'pgp))
-         ;; Hide "- " PGP quotation markers.
-         (when (and beg end)
-           (narrow-to-region beg end)
-           (goto-char (point-min))
-           (while (re-search-forward "^- " nil t)
-             (gnus-article-hide-text-type
-              (match-beginning 0) (match-end 0) 'pgp))
-           (widen))
-         (gnus-run-hooks 'gnus-article-hide-pgp-hook))))))
+    (let ((buffer-read-only nil)
+         charset)
+      (when (gnus-buffer-live-p gnus-original-article-buffer)
+       (with-current-buffer gnus-original-article-buffer
+         (let* ((ct (gnus-fetch-field "content-type"))
+                (ctl (and ct
+                          (ignore-errors
+                            (mail-header-parse-content-type ct)))))
+           (setq charset (and ctl
+                              (mail-content-type-get ctl 'charset)))
+           (when (stringp charset)
+             (setq charset (intern (downcase charset)))))))
+      (when read-charset
+       (setq charset (mm-read-coding-system "Charset: " charset)))
+      (unless charset
+       (setq charset gnus-newsgroup-charset))
+      (article-goto-body)
+      (save-window-excursion
+       (save-restriction
+         (narrow-to-region (point) (point-max))
+         (let* ((func (or gnus-article-wash-function mm-text-html-renderer))
+                (entry (assq func mm-text-html-washer-alist)))
+           (when entry
+             (setq func (cdr entry)))
+           (cond
+            ((functionp func)
+             (funcall func))
+            (t
+             (apply (car func) (cdr func))))))))))
+
+(defun gnus-article-wash-html-with-w3 ()
+  "Wash the current buffer with w3."
+  (mm-setup-w3)
+  (let ((w3-strict-width (window-width))
+       (url-standalone-mode t)
+       (url-gateway-unplugged t)
+       (w3-honor-stylesheets nil))
+    (condition-case ()
+       (w3-region (point-min) (point-max))
+      (error))))
+
+(defun gnus-article-wash-html-with-w3m ()
+  "Wash the current buffer with emacs-w3m."
+  (mm-setup-w3m)
+  (save-restriction
+    (narrow-to-region (point) (point-max))
+    (let ((w3m-safe-url-regexp (if mm-inline-text-html-with-images
+                                  nil
+                                "\\`cid:"))
+         w3m-force-redisplay)
+      (w3m-region (point-min) (point-max)))
+    (when mm-inline-text-html-with-w3m-keymap
+      (add-text-properties
+       (point-min) (point-max)
+       (nconc (mm-w3m-local-map-property)
+             '(mm-inline-text-html-with-w3m t))))))
+
+(defun article-hide-list-identifiers ()
+  "Remove list identifies from the Subject header.
+The `gnus-list-identifiers' variable specifies what to do."
+  (interactive)
+  (let ((inhibit-point-motion-hooks t)
+       (regexp (if (consp gnus-list-identifiers)
+                   (mapconcat 'identity gnus-list-identifiers " *\\|")
+                 gnus-list-identifiers))
+       buffer-read-only)
+    (when regexp
+      (save-excursion
+       (save-restriction
+         (article-narrow-to-head)
+         (goto-char (point-min))
+         (while (re-search-forward
+                 (concat "^Subject: +\\(R[Ee]: +\\)*\\(" regexp " *\\)")
+                 nil t)
+           (delete-region (match-beginning 2) (match-end 0))
+           (beginning-of-line))
+         (when (re-search-forward
+                "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" nil t)
+           (delete-region (match-beginning 1) (match-end 1))))))))
 
 (defun article-hide-pem (&optional arg)
   "Toggle hiding of any PEM headers and signatures in the current article.
@@ -1047,38 +2565,125 @@ always hide."
   (unless (gnus-article-check-hidden-text 'pem arg)
     (save-excursion
       (let (buffer-read-only end)
-       (widen)
        (goto-char (point-min))
-       ;; hide the horrendously ugly "header".
-       (and (search-forward "\n-----BEGIN PRIVACY-ENHANCED MESSAGE-----\n"
-                            nil
-                            t)
-            (setq end (1+ (match-beginning 0)))
-            (gnus-article-hide-text-type
-             end
-             (if (search-forward "\n\n" nil t)
-                 (match-end 0)
-               (point-max))
-             'pem))
-       ;; hide the trailer as well
-       (and (search-forward "\n-----END PRIVACY-ENHANCED MESSAGE-----\n"
-                            nil
-                            t)
-            (gnus-article-hide-text-type
-             (match-beginning 0) (match-end 0) 'pem))))))
+       ;; Hide the horrendously ugly "header".
+       (when (and (search-forward
+                   "\n-----BEGIN PRIVACY-ENHANCED MESSAGE-----\n"
+                   nil t)
+                  (setq end (1+ (match-beginning 0))))
+         (gnus-add-wash-type 'pem)
+         (gnus-article-hide-text-type
+          end
+          (if (search-forward "\n\n" nil t)
+              (match-end 0)
+            (point-max))
+          'pem)
+         ;; Hide the trailer as well
+         (when (search-forward "\n-----END PRIVACY-ENHANCED MESSAGE-----\n"
+                               nil t)
+           (gnus-article-hide-text-type
+            (match-beginning 0) (match-end 0) 'pem)))))))
+
+(defun article-strip-banner ()
+  "Strip the banners specified by the `banner' group parameter and by
+`gnus-article-address-banner-alist'."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (let ((inhibit-point-motion-hooks t))
+       (when (gnus-parameter-banner gnus-newsgroup-name)
+         (article-really-strip-banner
+          (gnus-parameter-banner gnus-newsgroup-name)))
+       (when gnus-article-address-banner-alist
+         (article-really-strip-banner
+          (let ((from (save-restriction
+                        (widen)
+                        (article-narrow-to-head)
+                        (mail-fetch-field "from"))))
+            (when (and from
+                       (setq from
+                             (caar (mail-header-parse-addresses from))))
+              (catch 'found
+                (dolist (pair gnus-article-address-banner-alist)
+                  (when (string-match (car pair) from)
+                    (throw 'found (cdr pair)))))))))))))
+
+(defun article-really-strip-banner (banner)
+  "Strip the banner specified by the argument."
+  (save-excursion
+    (save-restriction
+      (let ((inhibit-point-motion-hooks t)
+           (gnus-signature-limit nil)
+           buffer-read-only)
+       (article-goto-body)
+       (cond
+        ((eq banner 'signature)
+         (when (gnus-article-narrow-to-signature)
+           (widen)
+           (forward-line -1)
+           (delete-region (point) (point-max))))
+        ((symbolp banner)
+         (if (setq banner (cdr (assq banner gnus-article-banner-alist)))
+             (while (re-search-forward banner nil t)
+               (delete-region (match-beginning 0) (match-end 0)))))
+        ((stringp banner)
+         (while (re-search-forward banner nil t)
+           (delete-region (match-beginning 0) (match-end 0)))))))))
+
+(defun article-babel ()
+  "Translate article using an online translation service."
+  (interactive)
+  (require 'babel)
+  (save-excursion
+    (set-buffer gnus-article-buffer)
+    (when (article-goto-body)
+      (let* ((buffer-read-only nil)
+            (start (point))
+            (end (point-max))
+            (orig (buffer-substring start end))
+            (trans (babel-as-string orig)))
+       (save-restriction
+         (narrow-to-region start end)
+         (delete-region start end)
+         (insert trans))))))
 
 (defun article-hide-signature (&optional arg)
   "Hide the signature in the current article.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
   (interactive (gnus-article-hidden-arg))
-  (unless (gnus-article-check-hidden-text 'signature arg)
-    (save-excursion
-      (save-restriction
-       (let ((buffer-read-only nil))
-         (when (gnus-article-narrow-to-signature)
-           (gnus-article-hide-text-type
-            (point-min) (point-max) 'signature)))))))
+  (save-excursion
+    (save-restriction
+      (if (interactive-p)
+         (progn
+           (widen)
+           (article-goto-body))
+       (goto-char (point-min)))
+      (unless (gnus-article-check-hidden-text 'signature arg)
+       (let ((buffer-read-only nil)
+             (button (point)))
+         (while (setq button (text-property-any button (point-max)
+                                                'gnus-callback
+                                                'gnus-signature-toggle))
+           (setq button (text-property-not-all button (point-max)
+                                               'gnus-callback
+                                               'gnus-signature-toggle))
+           (when (and button (not (eobp)))
+             (gnus-article-hide-text-type
+              (1+ button)
+              (next-single-property-change (1+ button) 'mime-view-entity
+                                           nil (point-max))
+              'signature)))))))
+  (gnus-set-mode-line 'article))
+
+(defun article-strip-headers-in-body ()
+  "Strip offensive headers from bodies."
+  (interactive)
+  (save-excursion
+    (article-goto-body)
+    (let ((case-fold-search t))
+      (when (looking-at "x-no-archive:")
+       (gnus-delete-line)))))
 
 (defun article-strip-leading-blank-lines ()
   "Remove all blank lines from the beginning of the article."
@@ -1086,12 +2691,35 @@ always hide."
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          buffer-read-only)
-      (goto-char (point-min))
-      (when (search-forward "\n\n" nil t)
+      (when (article-goto-body)
        (while (and (not (eobp))
                    (looking-at "[ \t]*$"))
          (gnus-delete-line))))))
 
+(defun article-narrow-to-head ()
+  "Narrow the buffer to the head of the message.
+Point is left at the beginning of the narrowed-to region."
+  (narrow-to-region
+   (goto-char (point-min))
+   (if (search-forward "\n\n" nil 1)
+       (1- (point))
+     (point-max)))
+  (goto-char (point-min)))
+
+(defun article-goto-body ()
+  "Place point at the start of the body."
+  (goto-char (point-min))
+  (cond
+   ;; This variable is only bound when dealing with separate
+   ;; MIME body parts.
+   (article-goto-body-goes-to-point-min-p
+    t)
+   ((search-forward "\n\n" nil t)
+    t)
+   (t
+    (goto-char (point-max))
+    nil)))
+
 (defun article-strip-multiple-blank-lines ()
   "Replace consecutive blank lines with one empty line."
   (interactive)
@@ -1099,15 +2727,17 @@ always hide."
     (let ((inhibit-point-motion-hooks t)
          buffer-read-only)
       ;; First make all blank lines empty.
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
+      (article-goto-body)
       (while (re-search-forward "^[ \t]+$" nil t)
-       (replace-match "" nil t))
+       (unless (gnus-annotation-in-region-p
+                (match-beginning 0) (match-end 0))
+         (replace-match "" nil t)))
       ;; Then replace multiple empty lines with a single empty line.
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (while (re-search-forward "\n\n\n+" nil t)
-       (replace-match "\n\n" t t)))))
+      (article-goto-body)
+      (while (re-search-forward "\n\n\\(\n+\\)" nil t)
+       (unless (gnus-annotation-in-region-p
+                (match-beginning 0) (match-end 0))
+         (delete-region (match-beginning 1) (match-end 1)))))))
 
 (defun article-strip-leading-space ()
   "Remove all white space from the beginning of the lines in the article."
@@ -1115,11 +2745,20 @@ always hide."
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          buffer-read-only)
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
+      (article-goto-body)
       (while (re-search-forward "^[ \t]+" nil t)
        (replace-match "" t t)))))
 
+(defun article-strip-trailing-space ()
+  "Remove all white space from the end of the lines in the article."
+  (interactive)
+  (save-excursion
+    (let ((inhibit-point-motion-hooks t)
+         buffer-read-only)
+      (article-goto-body)
+      (while (re-search-forward "[ \t]+$" nil t)
+       (replace-match "" t t)))))
+
 (defun article-strip-blank-lines ()
   "Strip leading, trailing and multiple blank lines."
   (interactive)
@@ -1133,47 +2772,35 @@ always hide."
   (save-excursion
     (let ((inhibit-point-motion-hooks t)
          buffer-read-only)
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
+      (article-goto-body)
       (while (re-search-forward "^[ \t]*\n" nil t)
        (replace-match "" t t)))))
 
-(defvar mime::preview/content-list)
-(defvar mime::preview-content-info/point-min)
 (defun gnus-article-narrow-to-signature ()
   "Narrow to the signature; return t if a signature is found, else nil."
-  (widen)
-  (when (and (boundp 'mime::preview/content-list)
-            mime::preview/content-list)
-    ;; We have a MIMEish article, so we use the MIME data to narrow.
-    (let ((pcinfo (car (last mime::preview/content-list))))
-      (ignore-errors
-       (narrow-to-region
-        (funcall (intern "mime::preview-content-info/point-min") pcinfo)
-        (point-max)))))
-
-  (when (gnus-article-search-signature)
-    (forward-line 1)
-    ;; Check whether we have some limits to what we consider
-    ;; to be a signature.
-    (let ((limits (if (listp gnus-signature-limit) gnus-signature-limit
-                   (list gnus-signature-limit)))
-         limit limited)
-      (while (setq limit (pop limits))
-       (if (or (and (integerp limit)
-                    (< (- (point-max) (point)) limit))
-               (and (floatp limit)
-                    (< (count-lines (point) (point-max)) limit))
-               (and (gnus-functionp limit)
-                    (funcall limit))
-               (and (stringp limit)
-                    (not (re-search-forward limit nil t))))
-           ()                          ; This limit did not succeed.
-         (setq limited t
-               limits nil)))
-      (unless limited
-       (narrow-to-region (point) (point-max))
-       t))))
+  (let ((inhibit-point-motion-hooks t))
+    (when (gnus-article-search-signature)
+      (forward-line 1)
+      ;; Check whether we have some limits to what we consider
+      ;; to be a signature.
+      (let ((limits (if (listp gnus-signature-limit) gnus-signature-limit
+                     (list gnus-signature-limit)))
+           limit limited)
+       (while (setq limit (pop limits))
+         (if (or (and (integerp limit)
+                      (< (- (point-max) (point)) limit))
+                 (and (floatp limit)
+                      (< (count-lines (point) (point-max)) limit))
+                 (and (functionp limit)
+                      (funcall limit))
+                 (and (stringp limit)
+                      (not (re-search-forward limit nil t))))
+             ()                        ; This limit did not succeed.
+           (setq limited t
+                 limits nil)))
+       (unless limited
+         (narrow-to-region (point) (point-max))
+         t)))))
 
 (defun gnus-article-search-signature ()
   "Search the current buffer for the signature separator.
@@ -1191,38 +2818,6 @@ Put point at the beginning of the signature separator."
       (goto-char cur)
       nil)))
 
-(eval-and-compile
-  (autoload 'w3-display "w3-parse")
-  (autoload 'w3-do-setup "w3" "" t)
-  (autoload 'w3-region "w3-display" "" t))
-
-(defun gnus-article-treat-html ()
-  "Render HTML."
-  (interactive)
-  (let ((cbuf (current-buffer)))
-    (set-buffer gnus-article-buffer)
-    (let (buf buffer-read-only b e)
-      (w3-do-setup)
-      (goto-char (point-min))
-      (narrow-to-region
-       (if (search-forward "\n\n" nil t)
-          (setq b (point))
-        (point-max))
-       (setq e (point-max)))
-      (nnheader-temp-write nil
-       (insert-buffer-substring gnus-article-buffer b e)
-       (require 'url)
-       (save-window-excursion
-         (w3-region (point-min) (point-max))
-         (setq buf (buffer-substring-no-properties (point-min) (point-max)))))
-      (when buf
-       (delete-region (point-min) (point-max))
-       (insert buf))
-      (widen)
-      (goto-char (point-min))
-      (set-window-start (get-buffer-window (current-buffer)) (point-min))
-      (set-buffer cbuf))))
-
 (defun gnus-article-hidden-arg ()
   "Return the current prefix arg as a number, or 0 if no prefix."
   (list (if current-prefix-arg
@@ -1231,53 +2826,48 @@ Put point at the beginning of the signature separator."
 
 (defun gnus-article-check-hidden-text (type arg)
   "Return nil if hiding is necessary.
-Arg can be nil or a number.  Nil and positive means hide, negative
+Arg can be nil or a number.  nil and positive means hide, negative
 means show, 0 means toggle."
   (save-excursion
     (save-restriction
-      (widen)
       (let ((hide (gnus-article-hidden-text-p type)))
        (cond
         ((or (null arg)
              (> arg 0))
          nil)
         ((< arg 0)
-         (gnus-article-show-hidden-text type))
+         (gnus-article-show-hidden-text type)
+         t)
         (t
          (if (eq hide 'hidden)
-             (gnus-article-show-hidden-text type)
+             (progn
+               (gnus-article-show-hidden-text type)
+               t)
            nil)))))))
 
 (defun gnus-article-hidden-text-p (type)
   "Say whether the current buffer contains hidden text of type TYPE."
-  (let ((start (point-min))
-       (pos (text-property-any (point-min) (point-max) 'article-type type)))
+  (let ((pos (text-property-any (point-min) (point-max) 'article-type type)))
     (while (and pos
-               (not (get-text-property pos 'invisible)))
+               (not (get-text-property pos 'invisible))
+               (not (get-text-property pos 'dummy-invisible)))
       (setq pos
            (text-property-any (1+ pos) (point-max) 'article-type type)))
     (if pos
        'hidden
-      'shown)))
+      nil)))
 
-(defun gnus-article-show-hidden-text (type &optional hide)
+(defun gnus-article-show-hidden-text (type &optional dummy)
   "Show all hidden text of type TYPE.
-If HIDE, hide the text instead."
-  (save-excursion
-    (let ((buffer-read-only nil)
-         (inhibit-point-motion-hooks t)
-         (end (point-min))
-         beg)
-      (while (setq beg (text-property-any end (point-max) 'article-type type))
-       (goto-char beg)
-       (setq end (or
-                  (text-property-not-all beg (point-max) 'article-type type)
-                  (point-max)))
-       (if hide
-           (gnus-article-hide-text beg end gnus-hidden-properties)
-         (gnus-article-unhide-text beg end))
-       (goto-char end))
-      t)))
+Originally it is hide instead of DUMMY."
+  (let ((buffer-read-only nil)
+       (inhibit-point-motion-hooks t))
+    (gnus-remove-text-properties-when
+     'article-type type
+     (point-min) (point-max)
+     (cons 'article-type (cons type
+                              gnus-hidden-properties)))
+    (gnus-delete-wash-type type)))
 
 (defconst article-time-units
   `((year . ,(* 365.25 24 60 60))
@@ -1288,153 +2878,221 @@ If HIDE, hide the text instead."
     (second . 1))
   "Mapping from time units to seconds.")
 
+(defun gnus-article-forward-header ()
+  "Move point to the start of the next header.
+If the current header is a continuation header, this can be several
+lines forward."
+  (let ((ended nil))
+    (while (not ended)
+      (forward-line 1)
+      (if (looking-at "[ \t]+[^ \t]")
+         (forward-line 1)
+       (setq ended t)))))
+
 (defun article-date-ut (&optional type highlight header)
   "Convert DATE date to universal time in the current article.
 If TYPE is `local', convert to local time; if it is `lapsed', output
-how much time has lapsed since DATE."
+how much time has lapsed since DATE.  For `lapsed', the value of
+`gnus-article-date-lapsed-new-header' says whether the \"X-Sent:\" header
+should replace the \"Date:\" one, or should be added below it."
   (interactive (list 'ut t))
   (let* ((header (or header
-                    (mail-header-date gnus-current-headers)
+                    (and (eq 1 (point-min))
+                         (mail-header-date (save-excursion
+                                             (set-buffer gnus-summary-buffer)
+                                             gnus-current-headers)))
                     (message-fetch-field "date")
                     ""))
         (date (if (vectorp header) (mail-header-date header)
                 header))
-        (date-regexp "^Date:[ \t]\\|^X-Sent:[ \t]")
         (inhibit-point-motion-hooks t)
-        bface eface newline)
+        bface eface date-pos)
     (when (and date (not (string= date "")))
       (save-excursion
        (save-restriction
-         (nnheader-narrow-to-headers)
+         (article-narrow-to-head)
+         (when (or (and (eq type 'lapsed)
+                        gnus-article-date-lapsed-new-header
+                        ;; Attempt to get the face of X-Sent first.
+                        (re-search-forward "^X-Sent:[ \t]" nil t))
+                   (re-search-forward "^Date:[ \t]" nil t)
+                   ;; If Date is missing, try again for X-Sent.
+                   (re-search-forward "^X-Sent:[ \t]" nil t))
+           (setq bface (get-text-property (gnus-point-at-bol) 'face)
+                 date (or (get-text-property (gnus-point-at-bol)
+                                             'original-date)
+                          date)
+                 eface (get-text-property (1- (gnus-point-at-eol))
+                                          'face)))
          (let ((buffer-read-only nil))
+           ;; Delete any old X-Sent headers.
+           (when (setq date-pos
+                       (text-property-any (point-min) (point-max)
+                                          'article-date-lapsed t))
+             (goto-char (setq date-pos (set-marker (make-marker) date-pos)))
+             (delete-region (match-beginning 0)
+                            (progn (forward-line 1) (point))))
+           (goto-char (point-min))
            ;; Delete any old Date headers.
-           (if (re-search-forward date-regexp nil t)
+           (while (re-search-forward "^Date:[ \t]" nil t)
+             (unless date-pos
+               (setq date-pos (match-beginning 0)))
+             (unless (and (eq type 'lapsed)
+                          gnus-article-date-lapsed-new-header)
+               (delete-region (match-beginning 0)
+                              (progn (message-next-header) (point)))))
+           (if date-pos
                (progn
-                 (setq bface (get-text-property (gnus-point-at-bol) 'face)
-                       eface (get-text-property (1- (gnus-point-at-eol))
-                                                'face))
-                 (delete-region (progn (beginning-of-line) (point))
-                                (progn (end-of-line) (point)))
-                 (beginning-of-line))
-             (goto-char (point-max))
-             (setq newline t))
+                 (goto-char date-pos)
+                 (unless (bolp)
+                   ;; Possibly, Date has been deleted.
+                   (insert "\n"))
+                 (when (and (eq type 'lapsed)
+                            gnus-article-date-lapsed-new-header
+                            (looking-at "Date:"))
+                   (forward-line 1)))
+             (goto-char (point-min)))
            (insert (article-make-date-line date type))
+           (when (eq type 'lapsed)
+             (put-text-property (gnus-point-at-bol) (point)
+                                'article-date-lapsed t))
+           (insert "\n")
+           (forward-line -1)
            ;; Do highlighting.
-           (beginning-of-line)
            (when (looking-at "\\([^:]+\\): *\\(.*\\)$")
              (put-text-property (match-beginning 1) (1+ (match-end 1))
+                                'original-date date)
+             (put-text-property (match-beginning 1) (1+ (match-end 1))
                                 'face bface)
              (put-text-property (match-beginning 2) (match-end 2)
-                                'face eface))
-           (when newline
-             (end-of-line)
-             (insert "\n"))))))))
+                                'face eface))))))))
 
 (defun article-make-date-line (date type)
   "Return a DATE line of TYPE."
-  (cond
-   ;; Convert to the local timezone.  We have to slap a
-   ;; `condition-case' round the calls to the timezone
-   ;; functions since they aren't particularly resistant to
-   ;; buggy dates.
-   ((eq type 'local)
-    (concat "Date: " (condition-case ()
-                        (timezone-make-date-arpa-standard date)
-                      (error date))))
-   ;; Convert to Universal Time.
-   ((eq type 'ut)
-    (concat "Date: "
-           (condition-case ()
-               (timezone-make-date-arpa-standard date nil "UT")
-             (error date))))
-   ;; Get the original date from the article.
-   ((eq type 'original)
-    (concat "Date: " date))
-   ;; Let the user define the format.
-   ((eq type 'user)
-    (if (gnus-functionp gnus-article-time-format)
-       (funcall
-        gnus-article-time-format
-        (ignore-errors
-          (gnus-encode-date
-           (timezone-make-date-arpa-standard
-            date nil "UT"))))
-      (concat
-       "Date: "
-       (format-time-string gnus-article-time-format
-                          (ignore-errors
-                            (gnus-encode-date
-                             (timezone-make-date-arpa-standard
-                              date nil "UT")))))))
-   ;; ISO 8601.
-   ((eq type 'iso8601)
-    (concat
-     "Date: "
-     (format-time-string "%Y%M%DT%h%m%s"
-                        (ignore-errors
-                          (gnus-encode-date
-                           (timezone-make-date-arpa-standard
-                            date nil "UT"))))))
-   ;; Do an X-Sent lapsed format.
-   ((eq type 'lapsed)
-    ;; If the date is seriously mangled, the timezone functions are
-    ;; liable to bug out, so we ignore all errors.
-    (let* ((now (current-time))
-          (real-time
-           (ignore-errors
-             (gnus-time-minus
-              (gnus-encode-date
-               (timezone-make-date-arpa-standard
-                (current-time-string now)
-                (current-time-zone now) "UT"))
-              (gnus-encode-date
-               (timezone-make-date-arpa-standard
-                date nil "UT")))))
-          (real-sec (and real-time
-                         (+ (* (float (car real-time)) 65536)
-                            (cadr real-time))))
-          (sec (and real-time (abs real-sec)))
-          num prev)
-      (cond
-       ((null real-time)
-       "X-Sent: Unknown")
-       ((zerop sec)
-       "X-Sent: Now")
-       (t
-       (concat
-        "X-Sent: "
-        ;; This is a bit convoluted, but basically we go
-        ;; through the time units for years, weeks, etc,
-        ;; and divide things to see whether that results
-        ;; in positive answers.
-        (mapconcat
-         (lambda (unit)
-           (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
-               ;; The (remaining) seconds are too few to
-               ;; be divided into this time unit.
-               ""
-             ;; It's big enough, so we output it.
-             (setq sec (- sec (* num (cdr unit))))
-             (prog1
-                 (concat (if prev ", " "") (int-to-string
-                                            (floor num))
-                         " " (symbol-name (car unit))
-                         (if (> num 1) "s" ""))
-               (setq prev t))))
-         article-time-units "")
-        ;; If dates are odd, then it might appear like the
-        ;; article was sent in the future.
-        (if (> real-sec 0)
-            " ago"
-          " in the future"))))))
-   (t
-    (error "Unknown conversion type: %s" type))))
+  (unless (memq type '(local ut original user iso8601 lapsed english))
+    (error "Unknown conversion type: %s" type))
+  (condition-case ()
+      (let ((time (date-to-time date)))
+       (cond
+        ;; Convert to the local timezone.
+        ((eq type 'local)
+         (let ((tz (car (current-time-zone time))))
+           (format "Date: %s %s%02d%02d" (current-time-string time)
+                   (if (> tz 0) "+" "-") (/ (abs tz) 3600)
+                   (/ (% (abs tz) 3600) 60))))
+        ;; Convert to Universal Time.
+        ((eq type 'ut)
+         (concat "Date: "
+                 (current-time-string
+                  (let* ((e (parse-time-string date))
+                         (tm (apply 'encode-time e))
+                         (ms (car tm))
+                         (ls (- (cadr tm) (car (current-time-zone time)))))
+                    (cond ((< ls 0) (list (1- ms) (+ ls 65536)))
+                          ((> ls 65535) (list (1+ ms) (- ls 65536)))
+                          (t (list ms ls)))))
+                 " UT"))
+        ;; Get the original date from the article.
+        ((eq type 'original)
+         (concat "Date: " (if (string-match "\n+$" date)
+                              (substring date 0 (match-beginning 0))
+                            date)))
+        ;; Let the user define the format.
+        ((eq type 'user)
+         (let ((format (or (condition-case nil
+                               (with-current-buffer gnus-summary-buffer
+                                 gnus-article-time-format)
+                             (error nil))
+                           gnus-article-time-format)))
+           (if (functionp format)
+               (funcall format time)
+             (concat "Date: " (format-time-string format time)))))
+        ;; ISO 8601.
+        ((eq type 'iso8601)
+         (let ((tz (car (current-time-zone time))))
+           (concat
+            "Date: "
+            (format-time-string "%Y%m%dT%H%M%S" time)
+            (format "%s%02d%02d"
+                    (if (> tz 0) "+" "-") (/ (abs tz) 3600)
+                    (/ (% (abs tz) 3600) 60)))))
+        ;; Do an X-Sent lapsed format.
+        ((eq type 'lapsed)
+         ;; If the date is seriously mangled, the timezone functions are
+         ;; liable to bug out, so we ignore all errors.
+         (let* ((now (current-time))
+                (real-time (subtract-time now time))
+                (real-sec (and real-time
+                               (+ (* (float (car real-time)) 65536)
+                                  (cadr real-time))))
+                (sec (and real-time (abs real-sec)))
+                num prev)
+           (cond
+            ((null real-time)
+             "X-Sent: Unknown")
+            ((zerop sec)
+             "X-Sent: Now")
+            (t
+             (concat
+              "X-Sent: "
+              ;; This is a bit convoluted, but basically we go
+              ;; through the time units for years, weeks, etc,
+              ;; and divide things to see whether that results
+              ;; in positive answers.
+              (mapconcat
+               (lambda (unit)
+                 (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
+                     ;; The (remaining) seconds are too few to
+                     ;; be divided into this time unit.
+                     ""
+                   ;; It's big enough, so we output it.
+                   (setq sec (- sec (* num (cdr unit))))
+                   (prog1
+                       (concat (if prev ", " "") (int-to-string
+                                                  (floor num))
+                               " " (symbol-name (car unit))
+                               (if (> num 1) "s" ""))
+                     (setq prev t))))
+               article-time-units "")
+              ;; If dates are odd, then it might appear like the
+              ;; article was sent in the future.
+              (if (> real-sec 0)
+                  " ago"
+                " in the future"))))))
+        ;; Display the date in proper English
+        ((eq type 'english)
+         (let ((dtime (decode-time time)))
+           (concat
+            "Date: the "
+            (number-to-string (nth 3 dtime))
+            (let ((digit (% (nth 3 dtime) 10)))
+              (cond
+               ((memq (nth 3 dtime) '(11 12 13)) "th")
+               ((= digit 1) "st")
+               ((= digit 2) "nd")
+               ((= digit 3) "rd")
+               (t "th")))
+            " of "
+            (nth (1- (nth 4 dtime)) gnus-english-month-names)
+            " "
+            (number-to-string (nth 5 dtime))
+            " at "
+            (format "%02d" (nth 2 dtime))
+            ":"
+            (format "%02d" (nth 1 dtime)))))))
+    (error
+     (format "Date: %s (from T-gnus)" date))))
 
 (defun article-date-local (&optional highlight)
   "Convert the current article date to the local timezone."
   (interactive (list t))
   (article-date-ut 'local highlight))
 
+(defun article-date-english (&optional highlight)
+  "Convert the current article date to something that is proper English."
+  (interactive (list t))
+  (article-date-ut 'english highlight))
+
 (defun article-date-original (&optional highlight)
   "Convert the current article date to what it was originally.
 This is only useful if you have used some other date conversion
@@ -1449,13 +3107,20 @@ function and want to see what the date was before converting."
 
 (defun article-update-date-lapsed ()
   "Function to be run from a timer to update the lapsed time line."
-  (save-excursion
-    (ignore-errors
-      (when (gnus-buffer-live-p gnus-article-buffer)
-       (set-buffer gnus-article-buffer)
-       (goto-char (point-min))
-       (when (re-search-forward "^X-Sent:" nil t)
-         (article-date-lapsed t))))))
+  (let (deactivate-mark)
+    (save-excursion
+      (ignore-errors
+       (walk-windows
+        (lambda (w)
+          (set-buffer (window-buffer w))
+          (when (eq major-mode 'gnus-article-mode)
+            (let ((mark (point-marker)))
+              (goto-char (point-min))
+              (when (re-search-forward "^X-Sent:" nil t)
+                (article-date-lapsed t))
+              (goto-char (marker-position mark))
+              (move-marker mark nil))))
+        nil 'visible)))))
 
 (defun gnus-start-date-timer (&optional n)
   "Start a timer to update the X-Sent header in the article buffers.
@@ -1465,7 +3130,7 @@ is to run."
   (unless n
     (setq n 1))
   (gnus-stop-date-timer)
-  (setq article-lapsed-timer 
+  (setq article-lapsed-timer
        (nnheader-run-at-time 1 n 'article-update-date-lapsed)))
 
 (defun gnus-stop-date-timer ()
@@ -1486,25 +3151,53 @@ This format is defined by the `gnus-article-time-format' variable."
   (interactive (list t))
   (article-date-ut 'iso8601 highlight))
 
-(defun article-show-all ()
-  "Show all hidden text in the article buffer."
+;; (defun article-show-all ()
+;;   "Show all hidden text in the article buffer."
+;;   (interactive)
+;;   (save-excursion
+;;     (widen)
+;;     (let ((buffer-read-only nil))
+;;       (gnus-article-unhide-text (point-min) (point-max))
+;;       (gnus-remove-text-with-property 'gnus-prev)
+;;       (gnus-remove-text-with-property 'gnus-next))))
+
+(defun article-show-all-headers ()
+  "Show all hidden headers in the article buffer."
   (interactive)
   (save-excursion
-    (let ((buffer-read-only nil))
-      (gnus-article-unhide-text (point-min) (point-max)))))
+    (save-restriction
+      (widen)
+      (article-narrow-to-head)
+      (let ((buffer-read-only nil))
+       (gnus-article-unhide-text (point-min) (point-max))))))
+
+(defun article-remove-leading-whitespace ()
+  "Remove excessive whitespace from all headers."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (let ((buffer-read-only nil))
+       (article-narrow-to-head)
+       (goto-char (point-min))
+       (while (re-search-forward "^[^ :]+: \\([ \t]+\\)" nil t)
+         (delete-region (match-beginning 1) (match-end 1)))))))
 
 (defun article-emphasize (&optional arg)
   "Emphasize text according to `gnus-emphasis-alist'."
   (interactive (gnus-article-hidden-arg))
   (unless (gnus-article-check-hidden-text 'emphasis arg)
     (save-excursion
-      (let ((alist gnus-emphasis-alist)
+      (let ((alist (or
+                   (condition-case nil
+                       (with-current-buffer gnus-summary-buffer
+                         gnus-article-emphasis-alist)
+                     (error))
+                   gnus-emphasis-alist))
            (buffer-read-only nil)
            (props (append '(article-type emphasis)
                           gnus-hidden-properties))
            regexp elem beg invisible visible face)
-       (goto-char (point-min))
-       (search-forward "\n\n" nil t)
+       (article-goto-body)
        (setq beg (point))
        (while (setq elem (pop alist))
          (goto-char beg)
@@ -1513,17 +3206,39 @@ This format is defined by the `gnus-article-time-format' variable."
                visible (nth 2 elem)
                face (nth 3 elem))
          (while (re-search-forward regexp nil t)
-           (when (and (match-beginning visible) (match-beginning invisible))
-             (gnus-article-hide-text
-              (match-beginning invisible) (match-end invisible) props)
-             (gnus-article-unhide-text-type
-              (match-beginning visible) (match-end visible) 'emphasis)
-             (gnus-put-text-property-excluding-newlines
-              (match-beginning visible) (match-end visible) 'face face)
-             (goto-char (match-end invisible)))))))))
-
-(defvar gnus-summary-article-menu)
-(defvar gnus-summary-post-menu)
+           (when (and (match-beginning visible) (match-beginning invisible))
+             (gnus-article-hide-text
+              (match-beginning invisible) (match-end invisible) props)
+             (gnus-article-unhide-text-type
+              (match-beginning visible) (match-end visible) 'emphasis)
+             (gnus-put-overlay-excluding-newlines
+              (match-beginning visible) (match-end visible) 'face face)
+             (gnus-add-wash-type 'emphasis)
+             (goto-char (match-end invisible)))))))))
+
+(defun gnus-article-setup-highlight-words (&optional highlight-words)
+  "Setup newsgroup emphasis alist."
+  (unless gnus-article-emphasis-alist
+    (let ((name (and gnus-newsgroup-name
+                    (gnus-group-real-name gnus-newsgroup-name))))
+      (make-local-variable 'gnus-article-emphasis-alist)
+      (setq gnus-article-emphasis-alist
+           (nconc
+            (let ((alist gnus-group-highlight-words-alist) elem highlight)
+              (while (setq elem (pop alist))
+                (when (and name (string-match (car elem) name))
+                  (setq alist nil
+                        highlight (copy-sequence (cdr elem)))))
+              highlight)
+            (copy-sequence highlight-words)
+            (if gnus-newsgroup-name
+                (copy-sequence (gnus-group-find-parameter
+                                gnus-newsgroup-name 'highlight-words t)))
+            gnus-emphasis-alist)))))
+
+(eval-when-compile
+  (defvar gnus-summary-article-menu)
+  (defvar gnus-summary-post-menu))
 
 ;;; Saving functions.
 
@@ -1541,7 +3256,7 @@ This format is defined by the `gnus-article-time-format' variable."
     (if (not gnus-default-article-saver)
        (error "No default saver is defined")
       ;; !!! Magic!  The saving functions all save
-      ;; `gnus-original-article-buffer' (or so they think), but we
+      ;; `gnus-save-article-buffer' (or so they think), but we
       ;; bind that variable to our save-buffer.
       (set-buffer gnus-article-buffer)
       (let* ((gnus-save-article-buffer save-buffer)
@@ -1561,76 +3276,78 @@ This format is defined by the `gnus-article-time-format' variable."
   (let ((default-name
          (funcall function group headers (symbol-value variable)))
        result)
-    (setq
-     result
-     (cond
-      ((eq filename 'default)
-       default-name)
-      ((eq filename t)
-       default-name)
-      (filename filename)
-      (t
-       (let* ((split-name (gnus-get-split-value gnus-split-methods))
-             (prompt
-              (format prompt
-                      (if (and gnus-number-of-articles-to-be-saved
-                               (> gnus-number-of-articles-to-be-saved 1))
-                          (format "these %d articles"
-                                  gnus-number-of-articles-to-be-saved)
-                        "this article")))
-             (file
-              ;; Let the split methods have their say.
-              (cond
-               ;; No split name was found.
-               ((null split-name)
-                (read-file-name
-                 (concat prompt " (default "
-                         (file-name-nondirectory default-name) ") ")
-                 (file-name-directory default-name)
-                 default-name))
-               ;; A single group name is returned.
-               ((stringp split-name)
-                (setq default-name
-                      (funcall function split-name headers
-                               (symbol-value variable)))
-                (read-file-name
-                 (concat prompt " (default "
-                         (file-name-nondirectory default-name) ") ")
-                 (file-name-directory default-name)
-                 default-name))
-               ;; A single split name was found
-               ((= 1 (length split-name))
-                (let* ((name (expand-file-name
-                              (car split-name) gnus-article-save-directory))
-                       (dir (cond ((file-directory-p name)
-                                   (file-name-as-directory name))
-                                  ((file-exists-p name) name)
-                                  (t gnus-article-save-directory))))
-                  (read-file-name
-                   (concat prompt " (default " name ") ")
-                   dir name)))
-               ;; A list of splits was found.
-               (t
-                (setq split-name (nreverse split-name))
-                (let (result)
-                  (let ((file-name-history
-                         (nconc split-name file-name-history)))
-                    (setq result
-                          (expand-file-name
-                           (read-file-name
-                            (concat prompt " (`M-p' for defaults) ")
-                            gnus-article-save-directory
-                            (car split-name))
-                           gnus-article-save-directory)))
-                  (car (push result file-name-history)))))))
-        ;; Create the directory.
-        (gnus-make-directory (file-name-directory file))
-        ;; If we have read a directory, we append the default file name.
-        (when (file-directory-p file)
-          (setq file (concat (file-name-as-directory file)
-                             (file-name-nondirectory default-name))))
-        ;; Possibly translate some characters.
-        (nnheader-translate-file-chars file)))))
+    (setq result
+         (expand-file-name
+          (cond
+           ((eq filename 'default)
+            default-name)
+           ((eq filename t)
+            default-name)
+           (filename filename)
+           (t
+            (let* ((split-name (gnus-get-split-value gnus-split-methods))
+                   (prompt
+                    (format prompt
+                            (if (and gnus-number-of-articles-to-be-saved
+                                     (> gnus-number-of-articles-to-be-saved 1))
+                                (format "these %d articles"
+                                        gnus-number-of-articles-to-be-saved)
+                              "this article")))
+                   (file
+                    ;; Let the split methods have their say.
+                    (cond
+                     ;; No split name was found.
+                     ((null split-name)
+                      (read-file-name
+                       (concat prompt " (default "
+                               (file-name-nondirectory default-name) ") ")
+                       (file-name-directory default-name)
+                       default-name))
+                     ;; A single group name is returned.
+                     ((stringp split-name)
+                      (setq default-name
+                            (funcall function split-name headers
+                                     (symbol-value variable)))
+                      (read-file-name
+                       (concat prompt " (default "
+                               (file-name-nondirectory default-name) ") ")
+                       (file-name-directory default-name)
+                       default-name))
+                     ;; A single split name was found
+                     ((= 1 (length split-name))
+                      (let* ((name (expand-file-name
+                                    (car split-name)
+                                    gnus-article-save-directory))
+                             (dir (cond ((file-directory-p name)
+                                         (file-name-as-directory name))
+                                        ((file-exists-p name) name)
+                                        (t gnus-article-save-directory))))
+                        (read-file-name
+                         (concat prompt " (default " name ") ")
+                         dir name)))
+                     ;; A list of splits was found.
+                     (t
+                      (setq split-name (nreverse split-name))
+                      (let (result)
+                        (let ((file-name-history
+                               (nconc split-name file-name-history)))
+                          (setq result
+                                (expand-file-name
+                                 (read-file-name
+                                  (concat prompt " (`M-p' for defaults) ")
+                                  gnus-article-save-directory
+                                  (car split-name))
+                                 gnus-article-save-directory)))
+                        (car (push result file-name-history)))))))
+              ;; Create the directory.
+              (gnus-make-directory (file-name-directory file))
+              ;; If we have read a directory, we append the default file name.
+              (when (file-directory-p file)
+                (setq file (expand-file-name (file-name-nondirectory
+                                              default-name)
+                                             (file-name-as-directory file))))
+              ;; Possibly translate some characters.
+              (nnheader-translate-file-chars file))))))
     (gnus-make-directory (file-name-directory result))
     (set variable result)))
 
@@ -1650,7 +3367,6 @@ This format is defined by the `gnus-article-time-format' variable."
   "Append this article to Rmail file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in rmail file:" filename
                  gnus-rmail-save-name gnus-newsgroup-name
@@ -1666,7 +3382,6 @@ Directory to save to is default to `gnus-article-save-directory'."
   "Append this article to Unix mail file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in Unix mail file:" filename
                  gnus-mail-save-name gnus-newsgroup-name
@@ -1676,8 +3391,9 @@ Directory to save to is default to `gnus-article-save-directory'."
       (save-restriction
        (widen)
        (if (and (file-readable-p filename)
+                (file-regular-p filename)
                 (mail-file-babyl-p filename))
-           (gnus-output-to-rmail filename t)
+           (rmail-output-to-rmail-file filename t)
          (gnus-output-to-mail filename)))))
   filename)
 
@@ -1685,7 +3401,6 @@ Directory to save to is default to `gnus-article-save-directory'."
   "Append this article to file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s in file:" filename
                  gnus-file-save-name gnus-newsgroup-name
@@ -1701,17 +3416,15 @@ Directory to save to is default to `gnus-article-save-directory'."
   filename)
 
 (defun gnus-summary-write-to-file (&optional filename)
-  "Write this article to a file.
+  "Write this article to a file, overwriting it if the file exists.
 Optional argument FILENAME specifies file name.
 The directory to save in defaults to `gnus-article-save-directory'."
-  (interactive)
   (gnus-summary-save-in-file nil t))
 
 (defun gnus-summary-save-body-in-file (&optional filename)
   "Append this article body to a file.
 Optional argument FILENAME specifies file name.
 The directory to save in defaults to `gnus-article-save-directory'."
-  (interactive)
   (setq filename (gnus-read-save-file-name
                  "Save %s body in file:" filename
                  gnus-file-save-name gnus-newsgroup-name
@@ -1720,19 +3433,19 @@ The directory to save in defaults to `gnus-article-save-directory'."
     (save-excursion
       (save-restriction
        (widen)
-       (goto-char (point-min))
-       (when (search-forward "\n\n" nil t)
+       (when (article-goto-body)
          (narrow-to-region (point) (point-max)))
        (gnus-output-to-file filename))))
   filename)
 
 (defun gnus-summary-save-in-pipe (&optional command)
   "Pipe this article to subprocess."
-  (interactive)
   (setq command
-       (cond ((eq command 'default)
+       (cond ((and (eq command 'default)
+                   gnus-last-shell-command)
               gnus-last-shell-command)
-             (command command)
+             ((stringp command)
+              command)
              (t (read-string
                  (format
                   "Shell command on %s: "
@@ -1743,13 +3456,30 @@ The directory to save in defaults to `gnus-article-save-directory'."
                     "this article"))
                  gnus-last-shell-command))))
   (when (string-equal command "")
-    (setq command gnus-last-shell-command))
+    (if gnus-last-shell-command
+       (setq command gnus-last-shell-command)
+      (error "A command is required")))
   (gnus-eval-in-buffer-window gnus-article-buffer
     (save-restriction
       (widen)
       (shell-command-on-region (point-min) (point-max) command nil)))
   (setq gnus-last-shell-command command))
 
+(defmacro gnus-read-string (prompt &optional initial-contents history
+                           default-value)
+  "Like `read-string' but allow for older XEmacsen that don't have the 5th arg."
+  (if (and (featurep 'xemacs)
+          (< emacs-minor-version 2))
+      `(read-string ,prompt ,initial-contents ,history)
+    `(read-string ,prompt ,initial-contents ,history ,default-value)))
+
+(defun gnus-summary-pipe-to-muttprint (&optional command)
+  "Pipe this article to muttprint."
+  (setq command (gnus-read-string
+                "Print using command: " gnus-summary-muttprint-program
+                nil gnus-summary-muttprint-program))
+  (gnus-summary-save-in-pipe command))
+
 ;;; Article file names when saving.
 
 (defun gnus-capitalize-newsgroup (newsgroup)
@@ -1794,17 +3524,6 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        default
       (or last-file default))))
 
-(defun gnus-Plain-save-name (newsgroup headers &optional last-file)
-  "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
-If variable `gnus-use-long-file-name' is non-nil, it is
-~/News/News.group.  Otherwise, it is like ~/News/news/group/news."
-  (or last-file
-      (expand-file-name
-       (if (gnus-use-long-file-name 'not-save)
-          (gnus-capitalize-newsgroup newsgroup)
-        (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
-       gnus-article-save-directory)))
-
 (defun gnus-plain-save-name (newsgroup headers &optional last-file)
   "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
 If variable `gnus-use-long-file-name' is non-nil, it is
@@ -1813,9 +3532,115 @@ If variable `gnus-use-long-file-name' is non-nil, it is
       (expand-file-name
        (if (gnus-use-long-file-name 'not-save)
           newsgroup
-        (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
+        (file-relative-name
+         (expand-file-name "news" (gnus-newsgroup-directory-form newsgroup))
+         default-directory))
        gnus-article-save-directory)))
 
+(defun gnus-sender-save-name (newsgroup headers &optional last-file)
+  "Generate file name from sender."
+  (let ((from (mail-header-from headers)))
+    (expand-file-name
+     (if (and from (string-match "\\([^ <]+\\)@" from))
+        (match-string 1 from)
+       "nobody")
+     gnus-article-save-directory)))
+
+(defun article-verify-x-pgp-sig ()
+  "Verify X-PGP-Sig."
+  (interactive)
+  (if (gnus-buffer-live-p gnus-original-article-buffer)
+      (let ((sig (with-current-buffer gnus-original-article-buffer
+                  (gnus-fetch-field "X-PGP-Sig")))
+           items info headers)
+       (when (and sig
+                  mml2015-use
+                  (mml2015-clear-verify-function))
+         (with-temp-buffer
+           (insert-buffer-substring gnus-original-article-buffer)
+           (setq items (split-string sig))
+           (message-narrow-to-head)
+           (let ((inhibit-point-motion-hooks t)
+                 (case-fold-search t))
+             ;; Don't verify multiple headers.
+             (setq headers (mapconcat (lambda (header)
+                                        (concat header ": "
+                                                (mail-fetch-field header)
+                                                "\n"))
+                                      (split-string (nth 1 items) ",") "")))
+           (delete-region (point-min) (point-max))
+           (insert "-----BEGIN PGP SIGNED MESSAGE-----\n\n")
+           (insert "X-Signed-Headers: " (nth 1 items) "\n")
+           (insert headers)
+           (widen)
+           (forward-line)
+           (while (not (eobp))
+             (if (looking-at "^-")
+                 (insert "- "))
+             (forward-line))
+           (insert "\n-----BEGIN PGP SIGNATURE-----\n")
+           (insert "Version: " (car items) "\n\n")
+           (insert (mapconcat 'identity (cddr items) "\n"))
+           (insert "\n-----END PGP SIGNATURE-----\n")
+           (let ((mm-security-handle (list (format "multipart/signed"))))
+             (mml2015-clean-buffer)
+             (let ((coding-system-for-write (or gnus-newsgroup-charset
+                                                'iso-8859-1)))
+               (funcall (mml2015-clear-verify-function)))
+             (setq info
+                   (or (mm-handle-multipart-ctl-parameter
+                        mm-security-handle 'gnus-details)
+                       (mm-handle-multipart-ctl-parameter
+                        mm-security-handle 'gnus-info)))))
+         (when info
+           (let (buffer-read-only bface eface)
+             (save-restriction
+               (message-narrow-to-head)
+               (goto-char (point-max))
+               (forward-line -1)
+               (setq bface (get-text-property (gnus-point-at-bol) 'face)
+                     eface (get-text-property (1- (gnus-point-at-eol)) 'face))
+               (message-remove-header "X-Gnus-PGP-Verify")
+               (if (re-search-forward "^X-PGP-Sig:" nil t)
+                   (forward-line)
+                 (goto-char (point-max)))
+               (narrow-to-region (point) (point))
+               (insert "X-Gnus-PGP-Verify: " info "\n")
+               (goto-char (point-min))
+               (forward-line)
+               (while (not (eobp))
+                 (if (not (looking-at "^[ \t]"))
+                     (insert " "))
+                 (forward-line))
+               ;; Do highlighting.
+               (goto-char (point-min))
+               (when (looking-at "\\([^:]+\\): *")
+                 (put-text-property (match-beginning 1) (1+ (match-end 1))
+                                    'face bface)
+                 (put-text-property (match-end 0) (point-max)
+                                    'face eface)))))))))
+
+(defun article-verify-cancel-lock ()
+  "Verify Cancel-Lock header."
+  (interactive)
+  (if (gnus-buffer-live-p gnus-original-article-buffer)
+      (canlock-verify gnus-original-article-buffer)))
+
+(defun article-monafy ()
+  "Display body part with mona font."
+  (interactive)
+  (unless (if (featurep 'xemacs)
+             (find-face 'gnus-mona-face)
+           (facep 'gnus-mona-face))
+    (require 'navi2ch-mona)
+    (set-face-font (make-face 'gnus-mona-face) navi2ch-mona-font))
+  (save-excursion
+    (let ((buffer-read-only nil))
+      (article-goto-body)
+      (gnus-overlay-put
+       (gnus-make-overlay (point) (point-max))
+       'face 'gnus-mona-face))))
+
 (eval-and-compile
   (mapcar
    (lambda (func)
@@ -1825,43 +3650,62 @@ If variable `gnus-use-long-file-name' is non-nil, it is
                 gfunc (cdr func))
         (setq afunc func
               gfunc (intern (format "gnus-%s" func))))
-       (fset gfunc
-            (if (not (fboundp afunc))
-                nil
-              `(lambda (&optional interactive &rest args)
-                 ,(documentation afunc t)
-                 (interactive (list t))
-                 (save-excursion
-                   (set-buffer gnus-article-buffer)
-                   (if interactive
-                       (call-interactively ',afunc)
-                     (apply ',afunc args))))))))
+       (defalias gfunc
+        (when (fboundp afunc)
+          `(lambda (&optional interactive &rest args)
+             ,(documentation afunc t)
+             (interactive (list t))
+             (save-excursion
+               (set-buffer gnus-article-buffer)
+               (if interactive
+                   (call-interactively ',afunc)
+                 (apply ',afunc args))))))))
    '(article-hide-headers
+     article-verify-x-pgp-sig
+     article-verify-cancel-lock
+     article-monafy
      article-hide-boring-headers
      article-treat-overstrike
-     (article-fill . gnus-article-word-wrap)
+     article-fill-long-lines
+     article-capitalize-sentences
      article-remove-cr
+     article-remove-leading-whitespace
      article-display-x-face
+     article-display-face
      article-de-quoted-unreadable
-     article-mime-decode-quoted-printable
-     article-hide-pgp
+     article-de-base64-unreadable
+     article-decode-HZ
+     article-wash-html
+     article-unsplit-urls
+     article-hide-list-identifiers
+     article-strip-banner
+     article-babel
      article-hide-pem
      article-hide-signature
+     article-strip-headers-in-body
      article-remove-trailing-blank-lines
      article-strip-leading-blank-lines
      article-strip-multiple-blank-lines
      article-strip-leading-space
+     article-strip-trailing-space
      article-strip-blank-lines
      article-strip-all-blank-lines
      article-date-local
+     article-date-english
      article-date-iso8601
      article-date-original
      article-date-ut
+     article-decode-mime-words
+     article-decode-charset
+     article-decode-encoded-words
      article-date-user
      article-date-lapsed
      article-emphasize
      article-treat-dumbquotes
-     (article-show-all . gnus-article-show-all-headers))))
+     article-normalize-headers
+     (article-show-all-headers . gnus-article-show-all-headers)
+;;      (article-show-all . gnus-article-show-all)
+     )))
 \f
 ;;;
 ;;; Gnus article mode
@@ -1873,20 +3717,21 @@ If variable `gnus-use-long-file-name' is non-nil, it is
   " " gnus-article-goto-next-page
   "\177" gnus-article-goto-prev-page
   [delete] gnus-article-goto-prev-page
+  [backspace] gnus-article-goto-prev-page
   "\C-c^" gnus-article-refer-article
   "h" gnus-article-show-summary
   "s" gnus-article-show-summary
   "\C-c\C-m" gnus-article-mail
   "?" gnus-article-describe-briefly
-  gnus-mouse-2 gnus-article-push-button
-  "\r" gnus-article-press-button
-  "\t" gnus-article-next-button
-  "\M-\t" gnus-article-prev-button
-  "e" gnus-article-edit
+  "e" gnus-summary-edit-article
   "<" beginning-of-buffer
   ">" end-of-buffer
   "\C-c\C-i" gnus-info-find-node
   "\C-c\C-b" gnus-bug
+  "R" gnus-article-reply-with-original
+  "F" gnus-article-followup-with-original
+  "\C-hk" gnus-article-describe-key
+  "\C-hc" gnus-article-describe-key-briefly
 
   "\C-d" gnus-article-read-summary-keys
   "\M-*" gnus-article-read-summary-keys
@@ -1894,10 +3739,25 @@ If variable `gnus-use-long-file-name' is non-nil, it is
   "\M-^" gnus-article-read-summary-keys
   "\M-g" gnus-article-read-summary-keys)
 
-(substitute-key-definition
- 'undefined 'gnus-article-read-summary-keys gnus-article-mode-map)
+;; Define almost undefined keys to `gnus-article-read-summary-keys'.
+(let (keys)
+  (let ((key 32))
+    (while (<= key 127)
+      (push (char-to-string key) keys)
+      (incf key))
+    (dolist (elem (accessible-keymaps gnus-summary-mode-map))
+      (setq key (car elem))
+      (when (and (> (length key) 0)
+                (not (eq 'menu-bar (aref key 0)))
+                (symbolp (lookup-key gnus-summary-mode-map key)))
+       (push key keys))))
+  (dolist (key keys)
+    (unless (lookup-key gnus-article-mode-map key)
+      (define-key gnus-article-mode-map key 'gnus-article-read-summary-keys))))
 
 (defun gnus-article-make-menu-bar ()
+  (unless (boundp 'gnus-article-commands-menu)
+    (gnus-summary-make-menu-bar))
   (gnus-turn-off-edit-menu 'article)
   (unless (boundp 'gnus-article-article-menu)
     (easy-menu-define
@@ -1907,26 +3767,26 @@ If variable `gnus-use-long-file-name' is non-nil, it is
        ["Scroll backwards" gnus-article-goto-prev-page t]
        ["Show summary" gnus-article-show-summary t]
        ["Fetch Message-ID at point" gnus-article-refer-article t]
-       ["Mail to address at point" gnus-article-mail t]))
+       ["Mail to address at point" gnus-article-mail t]
+       ["Send a bug report" gnus-bug t]))
 
     (easy-menu-define
      gnus-article-treatment-menu gnus-article-mode-map ""
+     ;; Fixme: this should use :active (and maybe :visible).
      '("Treatment"
        ["Hide headers" gnus-article-hide-headers t]
        ["Hide signature" gnus-article-hide-signature t]
        ["Hide citation" gnus-article-hide-citation t]
        ["Treat overstrike" gnus-article-treat-overstrike t]
        ["Remove carriage return" gnus-article-remove-cr t]
-       ["Remove quoted-unreadable" gnus-article-de-quoted-unreadable t]))
+       ["Remove leading whitespace" gnus-article-remove-leading-whitespace t]
+       ["Treat html" gnus-article-wash-html t]
+       ["Remove newlines from within URLs" gnus-article-unsplit-urls t]
+       ["Decode HZ" gnus-article-decode-HZ t]))
 
-    (when nil
-      (when (boundp 'gnus-summary-article-menu)
-       (define-key gnus-article-mode-map [menu-bar commands]
-         (cons "Commands" gnus-summary-article-menu))))
+    ;; Note "Commands" menu is defined in gnus-sum.el for consistency
 
-    (when (boundp 'gnus-summary-post-menu)
-      (define-key gnus-article-mode-map [menu-bar post]
-       (cons "Post" gnus-summary-post-menu)))
+    ;; Note "Post" menu is defined in gnus-sum.el for consistency
 
     (gnus-run-hooks 'gnus-article-menu-hook)))
 
@@ -1946,9 +3806,6 @@ commands:
 \\[gnus-article-describe-briefly]\t Describe the current mode briefly
 \\[gnus-info-find-node]\t Go to the Gnus info node"
   (interactive)
-  (when (gnus-visual-p 'article-menu 'menu)
-    (gnus-article-make-menu-bar))
-  (kill-all-local-variables)
   (gnus-simplify-mode-line)
   (setq mode-name "Article")
   (setq major-mode 'gnus-article-mode)
@@ -1956,13 +3813,24 @@ commands:
   (unless (assq 'gnus-show-mime minor-mode-alist)
     (push (list 'gnus-show-mime " MIME") minor-mode-alist))
   (use-local-map gnus-article-mode-map)
+  (when (gnus-visual-p 'article-menu 'menu)
+    (gnus-article-make-menu-bar)
+    (when gnus-summary-tool-bar-map
+      (set (make-local-variable 'tool-bar-map) gnus-summary-tool-bar-map)))
   (gnus-update-format-specifications nil 'article-mode)
   (set (make-local-variable 'page-delimiter) gnus-page-delimiter)
   (set (make-local-variable 'gnus-page-broken) nil)
-  (set (make-local-variable 'gnus-button-marker-list) nil)
-  (set (make-local-variable 'gnus-article-current-summary) nil)
+  (make-local-variable 'gnus-button-marker-list)
+  (make-local-variable 'gnus-article-current-summary)
+  (make-local-variable 'gnus-article-mime-handles)
+  (make-local-variable 'gnus-article-decoded-p)
+  (make-local-variable 'gnus-article-mime-handle-alist)
+  (make-local-variable 'gnus-article-wash-types)
+  (make-local-variable 'gnus-article-image-alist)
+  (make-local-variable 'gnus-article-charset)
+  (make-local-variable 'gnus-article-ignored-charsets)
   (gnus-set-default-directory)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq buffer-read-only t)
   (set-syntax-table gnus-article-mode-syntax-table)
   (gnus-run-hooks 'gnus-article-mode-hook))
@@ -1977,6 +3845,7 @@ commands:
                         (substring name (match-end 0))))))
     (setq gnus-article-buffer name)
     (setq gnus-original-article-buffer original)
+    (setq gnus-article-mime-handle-alist nil)
     ;; This might be a variable local to the summary buffer.
     (unless gnus-single-article-buffer
       (save-excursion
@@ -1984,34 +3853,41 @@ commands:
        (setq gnus-article-buffer name)
        (setq gnus-original-article-buffer original)
        (gnus-set-global-variables)))
+    (gnus-article-setup-highlight-words)
     ;; Init original article buffer.
     (save-excursion
-      (set-buffer (get-buffer-create gnus-original-article-buffer))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (gnus-get-buffer-create gnus-original-article-buffer))
+      (set-buffer-multibyte t)
       (setq major-mode 'gnus-original-article-mode)
-      (gnus-add-current-to-buffer-list)
       (make-local-variable 'gnus-original-article))
     (if (get-buffer name)
        (save-excursion
          (set-buffer name)
-         (buffer-disable-undo (current-buffer))
+         (when (and gnus-article-edit-mode
+                    (buffer-modified-p)
+                    (not
+                     (y-or-n-p "Article mode edit in progress; discard? ")))
+           (error "Action aborted"))
+         (set (make-local-variable 'gnus-article-edit-mode) nil)
+         (buffer-disable-undo)
          (setq buffer-read-only t)
-         (gnus-add-current-to-buffer-list)
+         ;; This list just keeps growing if we don't reset it.
+         (setq gnus-button-marker-list nil)
          (unless (eq major-mode 'gnus-article-mode)
            (gnus-article-mode))
          (current-buffer))
       (save-excursion
-       (set-buffer (get-buffer-create name))
-       (gnus-add-current-to-buffer-list)
+       (set-buffer (gnus-get-buffer-create name))
        (gnus-article-mode)
        (make-local-variable 'gnus-summary-buffer)
+       (gnus-summary-set-local-parameters gnus-newsgroup-name)
        (current-buffer)))))
 
 ;; Set article window start at LINE, where LINE is the number of lines
 ;; from the head of the article.
 (defun gnus-article-set-window-start (&optional line)
   (set-window-start
-   (get-buffer-window gnus-article-buffer t)
+   (gnus-get-buffer-window gnus-article-buffer t)
    (save-excursion
      (set-buffer gnus-article-buffer)
      (goto-char (point-min))
@@ -2022,6 +3898,66 @@ commands:
        (forward-line line)
        (point)))))
 
+;;; @@ article filters
+;;;
+
+(defun gnus-article-display-mime-message ()
+  "Article display method for MIME message."
+  ;; called from `gnus-original-article-buffer'.
+  (let (charset all-headers)
+    (with-current-buffer gnus-summary-buffer
+      (setq charset default-mime-charset
+           all-headers gnus-have-all-headers))
+    (make-local-variable 'default-mime-charset)
+    (setq default-mime-charset charset)
+    (with-current-buffer (get-buffer-create gnus-article-buffer)
+      (make-local-variable 'default-mime-charset)
+      (setq default-mime-charset charset))
+    (mime-display-message mime-message-structure
+                         gnus-article-buffer nil gnus-article-mode-map)
+    (when all-headers
+      (gnus-article-hide-headers nil -1)))
+  (run-hooks 'gnus-mime-article-prepare-hook))
+
+(defun gnus-article-display-traditional-message ()
+  "Article display method for traditional message."
+  (set-buffer gnus-article-buffer)
+  (let (buffer-read-only)
+    (erase-buffer)
+    (insert-buffer-substring gnus-original-article-buffer)))
+
+(defun gnus-article-make-full-mail-header (&optional number charset)
+  "Create a new mail header structure in a raw article buffer."
+  (unless (and number charset)
+    (save-current-buffer
+      (set-buffer gnus-summary-buffer)
+      (unless number
+       (setq number (or (cdr gnus-article-current) 0)))
+      (unless charset
+       (setq charset (or default-mime-charset 'x-ctext)))))
+  (goto-char (point-min))
+  (let ((header-end (if (search-forward "\n\n" nil t)
+                       (1- (point))
+                     (goto-char (point-max))))
+       (chars (- (point-max) (point)))
+       (lines (count-lines (point) (point-max)))
+       (default-mime-charset charset)
+       xref)
+    (narrow-to-region (point-min) header-end)
+    (setq xref (std11-fetch-field "xref"))
+    (prog1
+       (make-full-mail-header
+        number
+        (std11-fetch-field "subject")
+        (std11-fetch-field "from")
+        (std11-fetch-field "date")
+        (std11-fetch-field "message-id")
+        (std11-fetch-field "references")
+        chars
+        lines
+        (when xref (concat "Xref: " xref)))
+      (widen))))
+
 (defun gnus-article-prepare (article &optional all-headers header)
   "Prepare ARTICLE in article mode buffer.
 ARTICLE should either be an article number or a Message-ID.
@@ -2032,14 +3968,9 @@ If ALL-HEADERS is non-nil, no headers are hidden."
     (unless (eq major-mode 'gnus-summary-mode)
       (set-buffer gnus-summary-buffer))
     (setq gnus-summary-buffer (current-buffer))
-    ;; Make sure the connection to the server is alive.
-    (unless (gnus-server-opened
-            (gnus-find-method-for-group gnus-newsgroup-name))
-      (gnus-check-server (gnus-find-method-for-group gnus-newsgroup-name))
-      (gnus-request-group gnus-newsgroup-name t))
     (let* ((gnus-article (if header (mail-header-number header) article))
           (summary-buffer (current-buffer))
-          (internal-hook gnus-article-internal-prepare-hook)
+          (gnus-tmp-internal-hook gnus-article-internal-prepare-hook)
           (group gnus-newsgroup-name)
           result)
       (save-excursion
@@ -2060,11 +3991,17 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                      (cons gnus-newsgroup-name article))
                (set-buffer gnus-summary-buffer)
                (setq gnus-current-article article)
-               (gnus-summary-mark-article article gnus-canceled-mark))
-             (unless (memq article gnus-newsgroup-sparse)
-               (gnus-error
-                1 "No such article (may have expired or been canceled)")))
-         (if (or (eq result 'pseudo) (eq result 'nneething))
+               (if (and (memq article gnus-newsgroup-undownloaded)
+                        (not (gnus-online (gnus-find-method-for-group
+                                           gnus-newsgroup-name))))
+                   (progn
+                     (gnus-summary-set-agent-mark article)
+                     (message "Message marked for downloading"))
+                 (gnus-summary-mark-article article gnus-canceled-mark)
+                 (unless (memq article gnus-newsgroup-sparse)
+                   (gnus-error 1 "No such article (may have expired or been canceled)")))))
+         (if (or (eq result 'pseudo)
+                 (eq result 'nneething))
              (progn
                (save-excursion
                  (set-buffer summary-buffer)
@@ -2077,7 +4014,9 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                      (gnus-configure-windows 'summary)
                    (gnus-configure-windows 'article))
                  (gnus-set-global-variables))
-               (gnus-set-mode-line 'article))
+               (let ((gnus-article-mime-handle-alist-1
+                      gnus-article-mime-handle-alist))
+                 (gnus-set-mode-line 'article)))
            ;; The result from the `request' was an actual article -
            ;; or at least some text that is now displayed in the
            ;; article buffer.
@@ -2097,86 +4036,1283 @@ If ALL-HEADERS is non-nil, no headers are hidden."
                (unless (vectorp gnus-current-headers)
                  (setq gnus-current-headers nil))
                (gnus-summary-goto-subject gnus-current-article)
-               (gnus-summary-show-thread)
+               (when (gnus-summary-show-thread)
+                 ;; If the summary buffer really was folded, the
+                 ;; previous goto may not actually have gone to
+                 ;; the right article, but the thread root instead.
+                 ;; So we go again.
+                 (gnus-summary-goto-subject gnus-current-article))
                (gnus-run-hooks 'gnus-mark-article-hook)
                (gnus-set-mode-line 'summary)
                (when (gnus-visual-p 'article-highlight 'highlight)
                  (gnus-run-hooks 'gnus-visual-mark-article-hook))
                ;; Set the global newsgroup variables here.
-               ;; Suggested by Jim Sisolak
-               ;; <sisolak@trans4.neep.wisc.edu>.
                (gnus-set-global-variables)
                (setq gnus-have-all-headers
                      (or all-headers gnus-show-all-headers))))
+           (save-excursion
+             (gnus-configure-windows 'article))
            (when (or (numberp article)
                      (stringp article))
-             ;; Hooks for getting information from the article.
-             ;; This hook must be called before being narrowed.
-             (let (buffer-read-only)
-               (gnus-run-hooks 'internal-hook)
-               (gnus-run-hooks 'gnus-article-prepare-hook)
-               ;; Decode MIME message.
-               (when gnus-show-mime
-                 (if (or (not gnus-strict-mime)
-                         (gnus-fetch-field "Mime-Version"))
-                     (let ((coding-system-for-write 'binary)
-                           (coding-system-for-read 'binary))
-                       (funcall gnus-show-mime-method))
-                   (funcall gnus-decode-encoded-word-method)))
-               ;; Perform the article display hooks.
-               (gnus-run-hooks 'gnus-article-display-hook))
+             (gnus-article-prepare-display)
              ;; Do page break.
              (goto-char (point-min))
-             (setq gnus-page-broken
-                   (when gnus-break-pages
-                     (gnus-narrow-to-page)
-                     t)))
-           (gnus-set-mode-line 'article)
+             (when gnus-break-pages
+               (gnus-narrow-to-page)))
+           (let ((gnus-article-mime-handle-alist-1
+                  gnus-article-mime-handle-alist))
+             (gnus-set-mode-line 'article))
+           (article-goto-body)
+           (unless (bobp)
+             (forward-line -1))
+           (set-window-point (get-buffer-window (current-buffer)) (point))
            (gnus-configure-windows 'article)
-           (goto-char (point-min))
            t))))))
 
+(defun gnus-article-prepare-mime-display (&optional number)
+  (goto-char (point-min))
+  (when (re-search-forward "^[^\t ]+:" nil t)
+    (goto-char (match-beginning 0)))
+  (let ((entity (if (eq 1 (point-min))
+                   (get-text-property 1 'mime-view-entity)
+                 (get-text-property (point) 'mime-view-entity)))
+       last-entity child-entity next type)
+    (setq child-entity (mime-entity-children entity))
+    (if child-entity
+       (setq last-entity (nth (1- (length child-entity))
+                              child-entity))
+      (setq last-entity entity))
+    (save-restriction
+      (narrow-to-region (point)
+                       (if (search-forward "\n\n" nil t)
+                           (point)
+                         (point-max)))
+      (gnus-treat-article 'head)
+      (put-text-property (point-min) (point-max) 'article-treated-header t)
+      (goto-char (point-max)))
+    (while (and (not (eobp)) entity)
+      (setq next (set-marker
+                 (make-marker)
+                 (next-single-property-change (point) 'mime-view-entity
+                                              nil (point-max))))
+      (let ((types (mime-entity-content-type entity)))
+       (while (eq 'multipart (mime-content-type-primary-type types))
+         (setq entity (car (mime-entity-children entity))
+               types (mime-entity-content-type entity)))
+       (when types
+         (setq type (format "%s/%s"
+                            (mime-content-type-primary-type types)
+                            (mime-content-type-subtype types)))))
+      (if (string-equal type "message/rfc822")
+         (progn
+           (setq next (point))
+           (let ((children (mime-entity-children entity))
+                 last-children)
+             (when children
+               (setq last-children (nth (1- (length children)) children))
+               (while
+                   (and
+                    (not (eq last-children
+                             (get-text-property next 'mime-view-entity)))
+                    (setq next
+                          (next-single-property-change next
+                                                       'mime-view-entity
+                                                       nil (point-max)))))))
+           (setq next (next-single-property-change next 'mime-view-entity
+                                                   nil (point-max)))
+           (save-restriction
+             (narrow-to-region (point) next)
+             (gnus-article-prepare-mime-display)
+             (goto-char (point-max)))
+           (setq entity (get-text-property (point) 'mime-view-entity)))
+       (save-restriction
+         (narrow-to-region (point) next)
+         ;; Kludge. We have to count true number, but for now,
+         ;; part number is here only to achieve `last'.
+         (gnus-treat-article nil 1
+                             (if (eq entity last-entity)
+                                 1 2)
+                             type)
+         (goto-char (point-max)))
+       (setq entity (get-text-property next 'mime-view-entity))))))
+
+;;;###autoload
+(defun gnus-article-prepare-display ()
+  "Make the current buffer look like a nice article."
+  (let ((gnus-article-buffer (current-buffer))
+       buffer-read-only)
+    (unless (eq major-mode 'gnus-article-mode)
+      (gnus-article-mode))
+    (setq buffer-read-only nil
+         gnus-button-marker-list nil
+         gnus-article-wash-types nil
+         gnus-article-image-alist nil)
+    (save-restriction
+      (widen)
+      (static-if (featurep 'xemacs)
+         (map-extents (lambda (extent maparg) (delete-extent extent)))
+       (let ((lists (overlay-lists)))
+         (dolist (overlay (nconc (car lists) (cdr lists)))
+           (delete-overlay overlay)))))
+    (gnus-run-hooks 'gnus-tmp-internal-hook))
+  (let ((show-mime (unless (member gnus-newsgroup-name '("nndraft:delayed"
+                                                        "nndraft:drafts"))
+                    gnus-show-mime))
+       (inhibit-read-only t))
+    (set-buffer gnus-original-article-buffer)
+    ;; Display message.
+    (setq mime-message-structure gnus-current-headers)
+    (mime-buffer-entity-set-buffer-internal mime-message-structure
+                                           gnus-original-article-buffer)
+    (mime-entity-set-representation-type-internal mime-message-structure
+                                                 'mime-buffer-entity)
+    (luna-send mime-message-structure 'initialize-instance
+              mime-message-structure)
+    (if show-mime
+       (let (mime-display-header-hook mime-display-text/plain-hook)
+         (funcall gnus-article-display-method-for-mime))
+      (funcall gnus-article-display-method-for-traditional))
+    ;; Call the treatment functions.
+    (save-restriction
+      (widen)
+      (if show-mime
+         (gnus-article-prepare-mime-display)
+       (narrow-to-region (goto-char (point-min))
+                         (if (search-forward "\n\n" nil t)
+                             (point)
+                           (point-max)))
+       (gnus-treat-article 'head)
+       (put-text-property (point-min) (point-max) 'article-treated-header t)
+       (goto-char (point-max))
+       (widen)
+       (narrow-to-region (point) (point-max))
+       (gnus-treat-article nil))
+      (put-text-property (point-min) (point-max) 'read-only nil)))
+  (gnus-run-hooks 'gnus-article-prepare-hook))
+
+(defun gnus-article-decode-article-as-default-mime-charset ()
+  "Decode an article as `default-mime-charset'.  It won't work if the
+value of the variable `gnus-show-mime' is non-nil."
+  (unless (or gnus-show-mime
+             (member gnus-newsgroup-name '("nndraft:delayed"
+                                           "nndraft:drafts")))
+    (set (make-local-variable 'default-mime-charset)
+        (with-current-buffer gnus-summary-buffer
+          default-mime-charset))
+    (decode-mime-charset-region (point-min) (point-max)
+                               default-mime-charset)))
+
+;;;
+;;; Gnus MIME viewing functions
+;;;
+
+(defvar gnus-mime-button-line-format "%{%([%p. %d%T]%)%}%e\n"
+  "Format of the MIME buttons.
+
+Valid specifiers include:
+%t  The MIME type
+%T  MIME type, along with additional info
+%n  The `name' parameter
+%d  The description, if any
+%l  The length of the encoded part
+%p  The part identifier number
+%e  Dots if the part isn't displayed
+
+General format specifiers can also be used.  See Info node
+`(gnus)Formatting Variables'.")
+
+(defvar gnus-mime-button-line-format-alist
+  '((?t gnus-tmp-type ?s)
+    (?T gnus-tmp-type-long ?s)
+    (?n gnus-tmp-name ?s)
+    (?d gnus-tmp-description ?s)
+    (?p gnus-tmp-id ?s)
+    (?l gnus-tmp-length ?d)
+    (?e gnus-tmp-dots ?s)))
+
+(defvar gnus-mime-button-commands
+  '((gnus-article-press-button "\r" "Toggle Display")
+    (gnus-mime-view-part "v" "View Interactively...")
+    (gnus-mime-view-part-as-type "t" "View As Type...")
+    (gnus-mime-view-part-as-charset "C" "View As charset...")
+    (gnus-mime-save-part "o" "Save...")
+    (gnus-mime-save-part-and-strip "\C-o" "Save and Strip")
+    (gnus-mime-delete-part "d" "Delete part")
+    (gnus-mime-copy-part "c" "View As Text, In Other Buffer")
+    (gnus-mime-inline-part "i" "View As Text, In This Buffer")
+    (gnus-mime-view-part-internally "E" "View Internally")
+    (gnus-mime-view-part-externally "e" "View Externally")
+    (gnus-mime-print-part "p" "Print")
+    (gnus-mime-pipe-part "|" "Pipe To Command...")
+    (gnus-mime-action-on-part "." "Take action on the part...")))
+
+(defun gnus-article-mime-part-status ()
+  (with-current-buffer gnus-article-buffer
+    (let ((entity (get-text-property (point-min) 'mime-view-entity))
+         children)
+      (if (and entity
+              (setq children (mime-entity-children entity))
+              (setq children (length children)))
+         (if (eq 1 children)
+             " (1 part)"
+           (format " (%d parts)" children))
+       ""))))
+
+(defvar gnus-mime-button-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= (string-to-number emacs-version) 21)
+      ;; XEmacs doesn't care.
+      (set-keymap-parent map gnus-article-mode-map))
+    (define-key map gnus-mouse-2 'gnus-article-push-button)
+    (define-key map gnus-down-mouse-3 'gnus-mime-button-menu)
+    (dolist (c gnus-mime-button-commands)
+      (define-key map (cadr c) (car c)))
+    map))
+
+(easy-menu-define
+  gnus-mime-button-menu gnus-mime-button-map "MIME button menu."
+  `("MIME Part"
+    ,@(mapcar (lambda (c)
+               (vector (caddr c) (car c) :enable t))
+             gnus-mime-button-commands)))
+
+(eval-when-compile
+  (define-compiler-macro popup-menu (&whole form
+                                           menu &optional position prefix)
+    (if (and (fboundp 'popup-menu)
+            (not (memq 'popup-menu (assoc "lmenu" load-history))))
+       form
+      ;; Gnus is probably running under Emacs 20.
+      `(let* ((menu (cdr ,menu))
+             (response (x-popup-menu
+                        t (list (car menu)
+                                (cons "" (mapcar (lambda (c)
+                                                   (cons (caddr c) (car c)))
+                                                 (cdr menu)))))))
+        (if response
+            (call-interactively (nth 3 (assq response menu))))))))
+
+(defun gnus-mime-button-menu (event prefix)
+ "Construct a context-sensitive menu of MIME commands."
+ (interactive "e\nP")
+ (save-window-excursion
+   (let ((pos (event-start event)))
+     (select-window (posn-window pos))
+     (goto-char (posn-point pos))
+     (gnus-article-check-buffer)
+     (popup-menu gnus-mime-button-menu nil prefix))))
+
+(defun gnus-mime-view-all-parts (&optional handles)
+  "View all the MIME parts."
+  (interactive)
+  (save-current-buffer
+    (set-buffer gnus-article-buffer)
+    (let ((handles (or handles gnus-article-mime-handles))
+         (mail-parse-charset gnus-newsgroup-charset)
+         (mail-parse-ignored-charsets
+          (with-current-buffer gnus-summary-buffer
+            gnus-newsgroup-ignored-charsets)))
+      (when handles
+       (mm-remove-parts handles)
+       (goto-char (point-min))
+       (or (search-forward "\n\n") (goto-char (point-max)))
+       (let (buffer-read-only)
+         (delete-region (point) (point-max))
+         (mm-display-parts handles))))))
+
+(defun gnus-mime-save-part-and-strip ()
+  "Save the MIME part under point then replace it with an external body."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let* ((data (get-text-property (point) 'gnus-data))
+        file param
+        (handles gnus-article-mime-handles))
+    (if (mm-multiple-handles gnus-article-mime-handles)
+       (error "This function is not implemented"))
+    (setq file (and data (mm-save-part data)))
+    (when file
+      (with-current-buffer (mm-handle-buffer data)
+       (erase-buffer)
+       (insert "Content-Type: " (mm-handle-media-type data))
+       (mml-insert-parameter-string (cdr (mm-handle-type data))
+                                    '(charset))
+       (insert "\n")
+       (insert "Content-ID: " (message-make-message-id) "\n")
+       (insert "Content-Transfer-Encoding: binary\n")
+       (insert "\n"))
+      (setcdr data
+             (cdr (mm-make-handle nil
+                                  `("message/external-body"
+                                    (access-type . "LOCAL-FILE")
+                                    (name . ,file)))))
+      (set-buffer gnus-summary-buffer)
+      (gnus-article-edit-article
+       `(lambda ()
+         (erase-buffer)
+         (let ((mail-parse-charset (or gnus-article-charset
+                                       ',gnus-newsgroup-charset))
+               (mail-parse-ignored-charsets
+                (or gnus-article-ignored-charsets
+                    ',gnus-newsgroup-ignored-charsets))
+               (mbl mml-buffer-list))
+           (setq mml-buffer-list nil)
+           (insert-buffer gnus-original-article-buffer)
+           (mime-to-mml ',handles)
+           (setq gnus-article-mime-handles nil)
+           (let ((mbl1 mml-buffer-list))
+             (setq mml-buffer-list mbl)
+             (set (make-local-variable 'mml-buffer-list) mbl1))
+           (gnus-make-local-hook 'kill-buffer-hook)
+           (add-hook 'kill-buffer-hook 'mml-destroy-buffers t t)))
+       `(lambda (no-highlight)
+         (let ((mail-parse-charset (or gnus-article-charset
+                                       ',gnus-newsgroup-charset))
+               (message-options message-options)
+               (message-options-set-recipient)
+               (mail-parse-ignored-charsets
+                (or gnus-article-ignored-charsets
+                    ',gnus-newsgroup-ignored-charsets)))
+           (mml-to-mime)
+           (mml-destroy-buffers)
+           (remove-hook 'kill-buffer-hook
+                        'mml-destroy-buffers t)
+           (kill-local-variable 'mml-buffer-list))
+         (gnus-summary-edit-article-done
+          ,(or (mail-header-references gnus-current-headers) "")
+          ,(gnus-group-read-only-p)
+          ,gnus-summary-buffer no-highlight))))))
+
+(defun gnus-mime-delete-part ()
+  "Delete the MIME part under point.
+Replace it with some information about the removed part."
+  (interactive)
+  (gnus-article-check-buffer)
+  (unless (and gnus-novice-user
+              (not (gnus-yes-or-no-p
+                    "Really delete attachment forever? ")))
+    (let* ((data (get-text-property (point) 'gnus-data))
+          (handles gnus-article-mime-handles)
+          (none "(none)")
+          (description
+           (or
+            (mail-decode-encoded-word-string (or (mm-handle-description data)
+                                                 none))))
+          (filename
+           (or (mail-content-type-get (mm-handle-disposition data) 'filename)
+               none))
+          (type (mm-handle-media-type data)))
+      (if (mm-multiple-handles gnus-article-mime-handles)
+         (error "This function is not implemented"))
+      (with-current-buffer (mm-handle-buffer data)
+       (let ((bsize (format "%s" (buffer-size))))
+         (erase-buffer)
+         (insert
+          (concat
+           ",----\n"
+           "| The following attachment has been deleted:\n"
+           "|\n"
+           "| Type:           " type "\n"
+           "| Filename:       " filename "\n"
+           "| Size (encoded): " bsize " Byte\n"
+           "| Description:    " description "\n"
+           "`----\n"))
+         (setcdr data
+                 (cdr (mm-make-handle
+                       nil `("text/plain") nil nil
+                       (list "attachment")
+                       (format "Deleted attachment (%s bytes)" bsize))))))
+      (set-buffer gnus-summary-buffer)
+      ;; FIXME: maybe some of the following code (borrowed from
+      ;; `gnus-mime-save-part-and-strip') isn't necessary?
+      (gnus-article-edit-article
+       `(lambda ()
+         (erase-buffer)
+         (let ((mail-parse-charset (or gnus-article-charset
+                                       ',gnus-newsgroup-charset))
+               (mail-parse-ignored-charsets
+                (or gnus-article-ignored-charsets
+                    ',gnus-newsgroup-ignored-charsets))
+               (mbl mml-buffer-list))
+           (setq mml-buffer-list nil)
+           (insert-buffer gnus-original-article-buffer)
+           (mime-to-mml ',handles)
+           (setq gnus-article-mime-handles nil)
+           (let ((mbl1 mml-buffer-list))
+             (setq mml-buffer-list mbl)
+             (set (make-local-variable 'mml-buffer-list) mbl1))
+           (gnus-make-local-hook 'kill-buffer-hook)
+           (add-hook 'kill-buffer-hook 'mml-destroy-buffers t t)))
+       `(lambda (no-highlight)
+         (let ((mail-parse-charset (or gnus-article-charset
+                                       ',gnus-newsgroup-charset))
+               (message-options message-options)
+               (message-options-set-recipient)
+               (mail-parse-ignored-charsets
+                (or gnus-article-ignored-charsets
+                    ',gnus-newsgroup-ignored-charsets)))
+           (mml-to-mime)
+           (mml-destroy-buffers)
+           (remove-hook 'kill-buffer-hook
+                        'mml-destroy-buffers t)
+           (kill-local-variable 'mml-buffer-list))
+         (gnus-summary-edit-article-done
+          ,(or (mail-header-references gnus-current-headers) "")
+          ,(gnus-group-read-only-p)
+          ,gnus-summary-buffer no-highlight)))))
+  ;; Not in `gnus-mime-save-part-and-strip':
+  (gnus-article-edit-done)
+  (gnus-summary-expand-window)
+  (gnus-summary-show-article))
+
+(defun gnus-mime-save-part ()
+  "Save the MIME part under point."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (when data
+      (mm-save-part data))))
+
+(defun gnus-mime-pipe-part ()
+  "Pipe the MIME part under point to a process."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (when data
+      (mm-pipe-part data))))
+
+(defun gnus-mime-view-part ()
+  "Interactively choose a viewing method for the MIME part under point."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let ((data (get-text-property (point) 'gnus-data)))
+    (when data
+      (setq gnus-article-mime-handles
+           (mm-merge-handles
+            gnus-article-mime-handles (setq data (copy-sequence data))))
+      (mm-interactively-view-part data))))
+
+(defun gnus-mime-view-part-as-type-internal ()
+  (gnus-article-check-buffer)
+  (let* ((name (mail-content-type-get
+               (mm-handle-type (get-text-property (point) 'gnus-data))
+               'name))
+        (def-type (and name (mm-default-file-encoding name))))
+    (and def-type (cons def-type 0))))
+
+(defun gnus-mime-view-part-as-type (&optional mime-type)
+  "Choose a MIME media type, and view the part as such."
+  (interactive)
+  (unless mime-type
+    (setq mime-type (completing-read
+                    "View as MIME type: "
+                    (mapcar #'list (mailcap-mime-types))
+                    nil nil
+                    (gnus-mime-view-part-as-type-internal))))
+  (gnus-article-check-buffer)
+  (let ((handle (get-text-property (point) 'gnus-data)))
+    (when handle
+      (setq handle
+           (mm-make-handle (mm-handle-buffer handle)
+                           (cons mime-type (cdr (mm-handle-type handle)))
+                           (mm-handle-encoding handle)
+                           (mm-handle-undisplayer handle)
+                           (mm-handle-disposition handle)
+                           (mm-handle-description handle)
+                           nil
+                           (mm-handle-id handle)))
+      (setq gnus-article-mime-handles
+           (mm-merge-handles gnus-article-mime-handles handle))
+      (gnus-mm-display-part handle))))
+
+(eval-when-compile
+  (require 'jka-compr))
+
+;; jka-compr.el uses a "sh -c" to direct stderr to err-file, but these days
+;; emacs can do that itself.
+;;
+(defun gnus-mime-jka-compr-maybe-uncompress ()
+  "Uncompress the current buffer if `auto-compression-mode' is enabled.
+The uncompress method used is derived from `buffer-file-name'."
+  (when (and (fboundp 'jka-compr-installed-p)
+             (jka-compr-installed-p))
+    (let ((info (jka-compr-get-compression-info buffer-file-name)))
+      (when info
+        (let ((basename (file-name-nondirectory buffer-file-name))
+              (args     (jka-compr-info-uncompress-args    info))
+              (prog     (jka-compr-info-uncompress-program info))
+              (message  (jka-compr-info-uncompress-message info))
+              (err-file (jka-compr-make-temp-name)))
+          (if message
+              (message "%s %s..." message basename))
+          (unwind-protect
+              (unless (memq (apply 'call-process-region
+                                   (point-min) (point-max)
+                                   prog
+                                   t (list t err-file) nil
+                                   args)
+                            jka-compr-acceptable-retval-list)
+                (jka-compr-error prog args basename message err-file))
+            (jka-compr-delete-temp-file err-file)))))))
+
+(defun gnus-mime-copy-part (&optional handle)
+  "Put the MIME part under point into a new buffer.
+If `auto-compression-mode' is enabled, compressed files like .gz and .bz2
+are decompressed."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        (contents (and handle (mm-get-part handle)))
+        (base (and handle
+                   (file-name-nondirectory
+                    (or
+                     (mail-content-type-get (mm-handle-type handle) 'name)
+                     (mail-content-type-get (mm-handle-disposition handle)
+                                            'filename)
+                     "*decoded*"))))
+        (buffer (and base (generate-new-buffer base))))
+    (when contents
+      (switch-to-buffer buffer)
+      (insert contents)
+      ;; We do it this way to make `normal-mode' set the appropriate mode.
+      (unwind-protect
+         (progn
+           (setq buffer-file-name (expand-file-name base))
+           (gnus-mime-jka-compr-maybe-uncompress)
+           (normal-mode))
+       (setq buffer-file-name nil))
+      (goto-char (point-min)))))
+
+(defun gnus-mime-print-part (&optional handle filename)
+  "Print the MIME part under point."
+  (interactive (list nil (ps-print-preprint current-prefix-arg)))
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        (contents (and handle (mm-get-part handle)))
+        (file (mm-make-temp-file (expand-file-name "mm." mm-tmp-directory)))
+        (printer (mailcap-mime-info (mm-handle-media-type handle) "print")))
+    (when contents
+       (if printer
+           (unwind-protect
+               (progn
+                 (mm-save-part-to-file handle file)
+                 (call-process shell-file-name nil
+                               (generate-new-buffer " *mm*")
+                               nil
+                               shell-command-switch
+                               (mm-mailcap-command
+                                printer file (mm-handle-type handle))))
+             (delete-file file))
+         (with-temp-buffer
+           (insert contents)
+           (gnus-print-buffer))
+         (ps-despool filename)))))
+
+(defun gnus-mime-inline-part (&optional handle arg)
+  "Insert the MIME part under point into the current buffer."
+  (interactive (list nil current-prefix-arg))
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        contents charset
+        (b (point))
+        buffer-read-only)
+    (when handle
+      (if (and (not arg) (mm-handle-undisplayer handle))
+         (mm-remove-part handle)
+       (setq contents (mm-get-part handle))
+       (cond
+        ((not arg)
+         (setq charset (or (mail-content-type-get
+                            (mm-handle-type handle) 'charset)
+                           gnus-newsgroup-charset)))
+        ((numberp arg)
+         (if (mm-handle-undisplayer handle)
+             (mm-remove-part handle))
+         (setq charset
+               (or (cdr (assq arg
+                              gnus-summary-show-article-charset-alist))
+                   (mm-read-coding-system "Charset: ")))))
+       (forward-line 2)
+       (mm-insert-inline handle
+                         (if (and charset
+                                  (setq charset (mm-charset-to-coding-system
+                                                 charset))
+                                  (not (eq charset 'ascii)))
+                             (mm-decode-coding-string contents charset)
+                           contents))
+       (goto-char b)))))
+
+(defun gnus-mime-view-part-as-charset (&optional handle arg)
+  "Insert the MIME part under point into the current buffer using the
+specified charset."
+  (interactive (list nil current-prefix-arg))
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        contents charset
+        (b (point))
+        buffer-read-only)
+    (when handle
+      (if (mm-handle-undisplayer handle)
+         (mm-remove-part handle))
+      (let ((gnus-newsgroup-charset
+            (or (cdr (assq arg
+                           gnus-summary-show-article-charset-alist))
+                (mm-read-coding-system "Charset: ")))
+           (gnus-newsgroup-ignored-charsets 'gnus-all))
+       (gnus-article-press-button)))))
+
+(defun gnus-mime-view-part-externally (&optional handle)
+  "View the MIME part under point with an external viewer."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        (mm-user-display-methods nil)
+        (mm-inlined-types nil)
+        (mail-parse-charset gnus-newsgroup-charset)
+        (mail-parse-ignored-charsets
+         (save-excursion (set-buffer gnus-summary-buffer)
+                         gnus-newsgroup-ignored-charsets)))
+    (when handle
+      (if (mm-handle-undisplayer handle)
+         (mm-remove-part handle)
+       (mm-display-part handle)))))
+
+(defun gnus-mime-view-part-internally (&optional handle)
+  "View the MIME part under point with an internal viewer.
+If no internal viewer is available, use an external viewer."
+  (interactive)
+  (gnus-article-check-buffer)
+  (let* ((handle (or handle (get-text-property (point) 'gnus-data)))
+        (mm-inlined-types '(".*"))
+        (mm-inline-large-images t)
+        (mail-parse-charset gnus-newsgroup-charset)
+        (mail-parse-ignored-charsets
+         (save-excursion (set-buffer gnus-summary-buffer)
+                         gnus-newsgroup-ignored-charsets))
+        buffer-read-only)
+    (when handle
+      (if (mm-handle-undisplayer handle)
+         (mm-remove-part handle)
+       (mm-display-part handle)))))
+
+(defun gnus-mime-action-on-part (&optional action)
+  "Do something with the MIME attachment at \(point\)."
+  (interactive
+   (list (completing-read "Action: " gnus-mime-action-alist nil t)))
+  (gnus-article-check-buffer)
+  (let ((action-pair (assoc action gnus-mime-action-alist)))
+    (if action-pair
+       (funcall (cdr action-pair)))))
+
+(defun gnus-article-part-wrapper (n function)
+  (save-current-buffer
+    (set-buffer gnus-article-buffer)
+    (when (> n (length gnus-article-mime-handle-alist))
+      (error "No such part"))
+    (gnus-article-goto-part n)
+    (let ((handle (cdr (assq n gnus-article-mime-handle-alist))))
+      (funcall function handle))))
+
+(defun gnus-article-pipe-part (n)
+  "Pipe MIME part N, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'mm-pipe-part))
+
+(defun gnus-article-save-part (n)
+  "Save MIME part N, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'mm-save-part))
+
+(defun gnus-article-interactively-view-part (n)
+  "View MIME part N interactively, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'mm-interactively-view-part))
+
+(defun gnus-article-copy-part (n)
+  "Copy MIME part N, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'gnus-mime-copy-part))
+
+(defun gnus-article-view-part-as-charset (n)
+  "View MIME part N using a specified charset.
+N is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'gnus-mime-view-part-as-charset))
+
+(defun gnus-article-view-part-externally (n)
+  "View MIME part N externally, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'gnus-mime-view-part-externally))
+
+(defun gnus-article-inline-part (n)
+  "Inline MIME part N, which is the numerical prefix."
+  (interactive "p")
+  (gnus-article-part-wrapper n 'gnus-mime-inline-part))
+
+(defun gnus-article-mime-match-handle-first (condition)
+  (if condition
+      (let ((alist gnus-article-mime-handle-alist) ihandle n)
+       (while (setq ihandle (pop alist))
+         (if (and (cond
+                   ((functionp condition)
+                    (funcall condition (cdr ihandle)))
+                   ((eq condition 'undisplayed)
+                    (not (or (mm-handle-undisplayer (cdr ihandle))
+                             (equal (mm-handle-media-type (cdr ihandle))
+                                    "multipart/alternative"))))
+                   ((eq condition 'undisplayed-alternative)
+                    (not (mm-handle-undisplayer (cdr ihandle))))
+                   (t t))
+                  (gnus-article-goto-part (car ihandle))
+                  (or (not n) (< (car ihandle) n)))
+             (setq n (car ihandle))))
+       (or n 1))
+    1))
+
+(defun gnus-article-view-part (&optional n)
+  "View MIME part N, which is the numerical prefix."
+  (interactive "P")
+  (save-current-buffer
+    (set-buffer gnus-article-buffer)
+    (or (numberp n) (setq n (gnus-article-mime-match-handle-first
+                            gnus-article-mime-match-handle-function)))
+    (when (> n (length gnus-article-mime-handle-alist))
+      (error "No such part"))
+    (let ((handle (cdr (assq n gnus-article-mime-handle-alist))))
+      (when (gnus-article-goto-part n)
+       (if (equal (car handle) "multipart/alternative")
+           (gnus-article-press-button)
+         (when (eq (gnus-mm-display-part handle) 'internal)
+           (gnus-set-window-start)))))))
+
+(defsubst gnus-article-mime-total-parts ()
+  (if (bufferp (car gnus-article-mime-handles))
+      1 ;; single part
+    (1- (length gnus-article-mime-handles))))
+
+(defun gnus-mm-display-part (handle)
+  "Display HANDLE and fix MIME button."
+  (let ((id (get-text-property (point) 'gnus-part))
+       (point (point))
+       buffer-read-only)
+    (forward-line 1)
+    (prog1
+       (let ((window (selected-window))
+             (mail-parse-charset gnus-newsgroup-charset)
+             (mail-parse-ignored-charsets
+              (if (gnus-buffer-live-p gnus-summary-buffer)
+                  (save-excursion
+                    (set-buffer gnus-summary-buffer)
+                    gnus-newsgroup-ignored-charsets)
+                nil)))
+         (save-excursion
+           (unwind-protect
+               (let ((win (gnus-get-buffer-window (current-buffer) t))
+                     (beg (point)))
+                 (when win
+                   (select-window win))
+                 (goto-char point)
+                 (forward-line)
+                 (if (mm-handle-displayed-p handle)
+                     ;; This will remove the part.
+                     (mm-display-part handle)
+                   (save-restriction
+                     (narrow-to-region (point)
+                                       (if (eobp) (point) (1+ (point))))
+                     (mm-display-part handle)
+                     ;; We narrow to the part itself and
+                     ;; then call the treatment functions.
+                     (goto-char (point-min))
+                     (forward-line 1)
+                     (narrow-to-region (point) (point-max))
+                     (gnus-treat-article
+                      nil id
+                      (gnus-article-mime-total-parts)
+                      (mm-handle-media-type handle)))))
+             (if (window-live-p window)
+                 (select-window window)))))
+      (goto-char point)
+      (gnus-delete-line)
+      (gnus-insert-mime-button
+       handle id (list (mm-handle-displayed-p handle)))
+      (goto-char point))))
+
+(defun gnus-article-goto-part (n)
+  "Go to MIME part N."
+  (gnus-goto-char (text-property-any (point-min) (point-max) 'gnus-part n)))
+
+(defun gnus-insert-mime-button (handle gnus-tmp-id &optional displayed)
+  (let ((gnus-tmp-name
+        (or (mail-content-type-get (mm-handle-type handle) 'name)
+            (mail-content-type-get (mm-handle-disposition handle) 'filename)
+            (mail-content-type-get (mm-handle-type handle) 'url)
+            ""))
+       (gnus-tmp-type (mm-handle-media-type handle))
+       (gnus-tmp-description
+        (mail-decode-encoded-word-string (or (mm-handle-description handle)
+                                             "")))
+       (gnus-tmp-dots
+        (if (if displayed (car displayed)
+              (mm-handle-displayed-p handle))
+            "" "..."))
+       (gnus-tmp-length (with-current-buffer (mm-handle-buffer handle)
+                          (buffer-size)))
+       gnus-tmp-type-long b e)
+    (when (string-match ".*/" gnus-tmp-name)
+      (setq gnus-tmp-name (replace-match "" t t gnus-tmp-name)))
+    (setq gnus-tmp-type-long (concat gnus-tmp-type
+                                    (and (not (equal gnus-tmp-name ""))
+                                         (concat "; " gnus-tmp-name))))
+    (unless (equal gnus-tmp-description "")
+      (setq gnus-tmp-type-long (concat " --- " gnus-tmp-type-long)))
+    (unless (bolp)
+      (insert "\n"))
+    (setq b (point))
+    (gnus-eval-format
+     gnus-mime-button-line-format gnus-mime-button-line-format-alist
+     `(,@(gnus-local-map-property gnus-mime-button-map)
+        gnus-callback gnus-mm-display-part
+        gnus-part ,gnus-tmp-id
+        article-type annotation
+        gnus-data ,handle))
+    (setq e (if (bolp)
+               ;; Exclude a newline.
+               (1- (point))
+             (point)))
+    (widget-convert-button
+     'link b e
+     :mime-handle handle
+     :action 'gnus-widget-press-button
+     :button-keymap gnus-mime-button-map
+     :help-echo
+     (lambda (widget/window &optional overlay pos)
+       ;; Needed to properly clear the message due to a bug in
+       ;; wid-edit (XEmacs only).
+       (if (boundp 'help-echo-owns-message)
+          (setq help-echo-owns-message t))
+       (format
+       "%S: %s the MIME part; %S: more options"
+       (aref gnus-mouse-2 0)
+       ;; XEmacs will get a single widget arg; Emacs 21 will get
+       ;; window, overlay, position.
+       (if (mm-handle-displayed-p
+            (if overlay
+                (with-current-buffer (gnus-overlay-buffer overlay)
+                  (widget-get (widget-at (gnus-overlay-start overlay))
+                              :mime-handle))
+              (widget-get widget/window :mime-handle)))
+           "hide" "show")
+       (aref gnus-down-mouse-3 0))))))
+
+(defun gnus-widget-press-button (elems el)
+  (goto-char (widget-get elems :from))
+  (gnus-article-press-button))
+
+(defvar gnus-displaying-mime nil)
+
+(defun gnus-display-mime (&optional ihandles)
+  "Display the MIME parts."
+  (save-excursion
+    (save-selected-window
+      (let ((window (get-buffer-window gnus-article-buffer))
+           (point (point)))
+       (when window
+         (select-window window)
+         ;; We have to do this since selecting the window
+         ;; may change the point.  So we set the window point.
+         (set-window-point window point)))
+      (let* ((handles (or ihandles
+                         (mm-dissect-buffer nil gnus-article-loose-mime)
+                         (and gnus-article-emulate-mime
+                              (mm-uu-dissect))))
+            buffer-read-only handle name type b e display)
+       (when (and (not ihandles)
+                  (not gnus-displaying-mime))
+         ;; Top-level call; we clean up.
+         (when gnus-article-mime-handles
+           (mm-destroy-parts gnus-article-mime-handles)
+           (setq gnus-article-mime-handle-alist nil));; A trick.
+         (setq gnus-article-mime-handles handles)
+         ;; We allow users to glean info from the handles.
+         (when gnus-article-mime-part-function
+           (gnus-mime-part-function handles)))
+       (if (and handles
+                (or (not (stringp (car handles)))
+                    (cdr handles)))
+           (progn
+             (when (and (not ihandles)
+                        (not gnus-displaying-mime))
+               ;; Clean up for mime parts.
+               (article-goto-body)
+               (delete-region (point) (point-max)))
+             (let ((gnus-displaying-mime t))
+               (gnus-mime-display-part handles)))
+         (save-restriction
+           (article-goto-body)
+           (narrow-to-region (point) (point-max))
+           (gnus-treat-article nil 1 1)
+           (widen)))
+       (unless ihandles
+         ;; Highlight the headers.
+         (save-excursion
+           (save-restriction
+             (article-goto-body)
+             (narrow-to-region (point-min) (point))
+             (gnus-treat-article 'head))))))))
+
+(defcustom gnus-mime-display-multipart-as-mixed nil
+  "Display \"multipart\" parts as  \"multipart/mixed\".
+
+If t, it overrides nil values of
+`gnus-mime-display-multipart-alternative-as-mixed' and
+`gnus-mime-display-multipart-related-as-mixed'."
+  :group 'gnus-article-mime
+  :type 'boolean)
+
+(defcustom gnus-mime-display-multipart-alternative-as-mixed nil
+  "Display \"multipart/alternative\" parts as  \"multipart/mixed\"."
+  :group 'gnus-article-mime
+  :type 'boolean)
+
+(defcustom gnus-mime-display-multipart-related-as-mixed nil
+  "Display \"multipart/related\" parts as  \"multipart/mixed\".
+
+If displaying \"text/html\" is discouraged \(see
+`mm-discouraged-alternatives'\) images or other material inside a
+\"multipart/related\" part might be overlooked when this variable is nil."
+  :group 'gnus-article-mime
+  :type 'boolean)
+
+(defun gnus-mime-display-part (handle)
+  (cond
+   ;; Single part.
+   ((not (stringp (car handle)))
+    (gnus-mime-display-single handle))
+   ;; User-defined multipart
+   ((cdr (assoc (car handle) gnus-mime-multipart-functions))
+    (funcall (cdr (assoc (car handle) gnus-mime-multipart-functions))
+            handle))
+   ;; multipart/alternative
+   ((and (equal (car handle) "multipart/alternative")
+        (not (or gnus-mime-display-multipart-as-mixed
+                 gnus-mime-display-multipart-alternative-as-mixed)))
+    (let ((id (1+ (length gnus-article-mime-handle-alist))))
+      (push (cons id handle) gnus-article-mime-handle-alist)
+      (gnus-mime-display-alternative (cdr handle) nil nil id)))
+   ;; multipart/related
+   ((and (equal (car handle) "multipart/related")
+        (not (or gnus-mime-display-multipart-as-mixed
+                 gnus-mime-display-multipart-related-as-mixed)))
+    ;;;!!!We should find the start part, but we just default
+    ;;;!!!to the first part.
+    ;;(gnus-mime-display-part (cadr handle))
+    ;;;!!! Most multipart/related is an HTML message plus images.
+    ;;;!!! Unfortunately we are unable to let W3 display those
+    ;;;!!! included images, so we just display it as a mixed multipart.
+    ;;(gnus-mime-display-mixed (cdr handle))
+    ;;;!!! No, w3 can display everything just fine.
+    (gnus-mime-display-part (cadr handle)))
+   ((equal (car handle) "multipart/signed")
+    (gnus-add-wash-type 'signed)
+    (gnus-mime-display-security handle))
+   ((equal (car handle) "multipart/encrypted")
+    (gnus-add-wash-type 'encrypted)
+    (gnus-mime-display-security handle))
+   ;; Other multiparts are handled like multipart/mixed.
+   (t
+    (gnus-mime-display-mixed (cdr handle)))))
+
+(defun gnus-mime-part-function (handles)
+  (if (stringp (car handles))
+      (mapcar 'gnus-mime-part-function (cdr handles))
+    (funcall gnus-article-mime-part-function handles)))
+
+(defun gnus-mime-display-mixed (handles)
+  (mapcar 'gnus-mime-display-part handles))
+
+(defun gnus-mime-display-single (handle)
+  (let ((type (mm-handle-media-type handle))
+       (ignored gnus-ignored-mime-types)
+       (not-attachment t)
+       (move nil)
+       display text)
+    (catch 'ignored
+      (progn
+       (while ignored
+         (when (string-match (pop ignored) type)
+           (throw 'ignored nil)))
+       (if (and (setq not-attachment
+                      (and (not (mm-inline-override-p handle))
+                           (or (not (mm-handle-disposition handle))
+                               (equal (car (mm-handle-disposition handle))
+                                      "inline")
+                               (mm-attachment-override-p handle))))
+                (mm-automatic-display-p handle)
+                (or (and
+                     (mm-inlinable-p handle)
+                     (mm-inlined-p handle))
+                    (mm-automatic-external-display-p type)))
+           (setq display t)
+         (when (equal (mm-handle-media-supertype handle) "text")
+           (setq text t)))
+       (let ((id (1+ (length gnus-article-mime-handle-alist)))
+             beg)
+         (push (cons id handle) gnus-article-mime-handle-alist)
+         (when (or (not display)
+                   (not (gnus-unbuttonized-mime-type-p type)))
+           ;(gnus-article-insert-newline)
+           (gnus-insert-mime-button
+            handle id (list (or display (and not-attachment text))))
+           (gnus-article-insert-newline)
+           ;(gnus-article-insert-newline)
+           ;; Remember modify the number of forward lines.
+           (setq move t))
+         (setq beg (point))
+         (cond
+          (display
+           (when move
+             (forward-line -1)
+             (setq beg (point)))
+           (let ((mail-parse-charset gnus-newsgroup-charset)
+                 (mail-parse-ignored-charsets
+                  (save-excursion (condition-case ()
+                                      (set-buffer gnus-summary-buffer)
+                                    (error))
+                                  gnus-newsgroup-ignored-charsets)))
+             (mm-display-part handle t))
+           (goto-char (point-max)))
+          ((and text not-attachment)
+           (when move
+             (forward-line -1)
+             (setq beg (point)))
+           (gnus-article-insert-newline)
+           (mm-insert-inline handle (mm-get-part handle))
+           (goto-char (point-max))))
+         ;; Do highlighting.
+         (save-excursion
+           (save-restriction
+             (narrow-to-region beg (point))
+             (gnus-treat-article
+              nil id
+              (gnus-article-mime-total-parts)
+              (mm-handle-media-type handle)))))))))
+
+(defun gnus-unbuttonized-mime-type-p (type)
+  "Say whether TYPE is to be unbuttonized."
+  (unless gnus-inhibit-mime-unbuttonizing
+    (when (catch 'found
+           (let ((types gnus-unbuttonized-mime-types))
+             (while types
+               (when (string-match (pop types) type)
+                 (throw 'found t)))))
+      (not (catch 'found
+            (let ((types gnus-buttonized-mime-types))
+              (while types
+                (when (string-match (pop types) type)
+                  (throw 'found t)))))))))
+
+(defun gnus-article-insert-newline ()
+  "Insert a newline, but mark it as undeletable."
+  (gnus-put-text-property
+   (point) (progn (insert "\n") (point)) 'gnus-undeletable t))
+
+(defun gnus-mime-display-alternative (handles &optional preferred ibegend id)
+  (let* ((preferred (or preferred (mm-preferred-alternative handles)))
+        (ihandles handles)
+        (point (point))
+        handle buffer-read-only from props begend not-pref)
+    (save-window-excursion
+      (save-restriction
+       (when ibegend
+         (narrow-to-region (car ibegend)
+                           (or (cdr ibegend)
+                               (progn
+                                 (goto-char (car ibegend))
+                                 (forward-line 2)
+                                 (point))))
+         (delete-region (point-min) (point-max))
+         (mm-remove-parts handles))
+       (setq begend (list (point-marker)))
+       ;; Do the toggle.
+       (unless (setq not-pref (cadr (member preferred ihandles)))
+         (setq not-pref (car ihandles)))
+       (when (or ibegend
+                 (not preferred)
+                 (not (gnus-unbuttonized-mime-type-p
+                       "multipart/alternative")))
+         (gnus-add-text-properties
+          (setq from (point))
+          (progn
+            (insert (format "%d.  " id))
+            (point))
+          `(gnus-callback
+            (lambda (handles)
+              (unless ,(not ibegend)
+                (setq gnus-article-mime-handle-alist
+                      ',gnus-article-mime-handle-alist))
+              (gnus-mime-display-alternative
+               ',ihandles ',not-pref ',begend ,id))
+            ,@(gnus-local-map-property gnus-mime-button-map)
+            ,gnus-mouse-face-prop ,gnus-article-mouse-face
+            face ,gnus-article-button-face
+            gnus-part ,id
+            gnus-data ,handle))
+         (widget-convert-button 'link from (point)
+                                :action 'gnus-widget-press-button
+                                :button-keymap gnus-widget-button-keymap)
+         ;; Do the handles
+         (while (setq handle (pop handles))
+           (gnus-add-text-properties
+            (setq from (point))
+            (progn
+              (insert (format "(%c) %-18s"
+                              (if (equal handle preferred) ?* ? )
+                              (mm-handle-media-type handle)))
+              (point))
+            `(gnus-callback
+              (lambda (handles)
+                (unless ,(not ibegend)
+                  (setq gnus-article-mime-handle-alist
+                        ',gnus-article-mime-handle-alist))
+                (gnus-mime-display-alternative
+                 ',ihandles ',handle ',begend ,id))
+              ,@(gnus-local-map-property gnus-mime-button-map)
+              ,gnus-mouse-face-prop ,gnus-article-mouse-face
+              face ,gnus-article-button-face
+              gnus-part ,id
+              gnus-data ,handle))
+           (widget-convert-button 'link from (point)
+                                  :action 'gnus-widget-press-button
+                                  :button-keymap gnus-widget-button-keymap)
+           (insert "  "))
+         (insert "\n\n"))
+       (when preferred
+         (if (stringp (car preferred))
+             (gnus-display-mime preferred)
+           (let ((mail-parse-charset gnus-newsgroup-charset)
+                 (mail-parse-ignored-charsets
+                  (save-excursion (set-buffer gnus-summary-buffer)
+                                  gnus-newsgroup-ignored-charsets)))
+             (mm-display-part preferred)
+             ;; Do highlighting.
+             (save-excursion
+               (save-restriction
+                 (narrow-to-region (car begend) (point-max))
+                 (gnus-treat-article
+                  nil (length gnus-article-mime-handle-alist)
+                  (gnus-article-mime-total-parts)
+                  (mm-handle-media-type handle))))))
+         (goto-char (point-max))
+         (setcdr begend (point-marker)))))
+    (when ibegend
+      (goto-char point))))
+
+(defconst gnus-article-wash-status-strings
+  (let ((alist '((cite "c" "Possible hidden citation text"
+                      " " "All citation text visible")
+                (headers "h" "Hidden headers"
+                         " " "All headers visible.")
+                (pgp "p" "Encrypted or signed message status hidden"
+                     " " "No hidden encryption nor digital signature status")
+                (signature "s" "Signature has been hidden"
+                           " " "Signature is visible")
+                (overstrike "o" "Overstrike (^H) characters applied"
+                            " " "No overstrike characters applied")
+                (gnus-show-mime "m" "Mime processing is activated"
+                                " " "Mime processing is not activated")
+                (emphasis "e" "/*_Emphasis_*/ characters applied"
+                          " " "No /*_emphasis_*/ characters applied")))
+       result)
+    (dolist (entry alist result)
+      (let ((key (nth 0 entry))
+           (on (copy-sequence (nth 1 entry)))
+           (on-help (nth 2 entry))
+           (off (copy-sequence (nth 3 entry)))
+           (off-help (nth 4 entry)))
+       (put-text-property 0 1 'help-echo on-help on)
+       (put-text-property 0 1 'help-echo off-help off)
+       (push (list key on off) result))))
+  "Alist of strings describing wash status in the mode line.
+Each entry has the form (KEY ON OF), where the KEY is a symbol
+representing the particular washing function, ON is the string to use
+in the article mode line when the washing function is active, and OFF
+is the string to use when it is inactive.")
+
+(defun gnus-article-wash-status-entry (key value)
+  (let ((entry (assoc key gnus-article-wash-status-strings)))
+    (if value (nth 1 entry) (nth 2 entry))))
+
 (defun gnus-article-wash-status ()
   "Return a string which display status of article washing."
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (let ((cite (gnus-article-hidden-text-p 'cite))
-         (headers (gnus-article-hidden-text-p 'headers))
-         (boring (gnus-article-hidden-text-p 'boring-headers))
-         (pgp (gnus-article-hidden-text-p 'pgp))
-         (pem (gnus-article-hidden-text-p 'pem))
-         (signature (gnus-article-hidden-text-p 'signature))
-         (overstrike (gnus-article-hidden-text-p 'overstrike))
-         (emphasis (gnus-article-hidden-text-p 'emphasis))
-         (mime gnus-show-mime))
-      (format "%c%c%c%c%c%c%c"
-             (if cite ?c ? )
-             (if (or headers boring) ?h ? )
-             (if (or pgp pem) ?p ? )
-             (if signature ?s ? )
-             (if overstrike ?o ? )
-             (if mime ?m ? )
-             (if emphasis ?e ? )))))
-
-(defun gnus-article-hide-headers-if-wanted ()
+    (let ((cite (memq 'cite gnus-article-wash-types))
+         (headers (memq 'headers gnus-article-wash-types))
+         (boring (memq 'boring-headers gnus-article-wash-types))
+         (pgp (memq 'pgp gnus-article-wash-types))
+         (pem (memq 'pem gnus-article-wash-types))
+         (signed (memq 'signed gnus-article-wash-types))
+         (encrypted (memq 'encrypted gnus-article-wash-types))
+         (signature (memq 'signature gnus-article-wash-types))
+         (overstrike (memq 'overstrike gnus-article-wash-types))
+         (emphasis (memq 'emphasis gnus-article-wash-types)))
+      (concat
+       (gnus-article-wash-status-entry 'cite cite)
+       (gnus-article-wash-status-entry 'headers (or headers boring))
+       (gnus-article-wash-status-entry 'pgp (or pgp pem signed encrypted))
+       (gnus-article-wash-status-entry 'signature signature)
+       (gnus-article-wash-status-entry 'overstrike overstrike)
+       (gnus-article-wash-status-entry 'gnus-show-mime gnus-show-mime)
+       (gnus-article-wash-status-entry 'emphasis emphasis)))))
+
+(defun gnus-add-wash-type (type)
+  "Add a washing of TYPE to the current status."
+  (add-to-list 'gnus-article-wash-types type))
+
+(defun gnus-delete-wash-type (type)
+  "Add a washing of TYPE to the current status."
+  (setq gnus-article-wash-types (delq type gnus-article-wash-types)))
+
+(defun gnus-add-image (category image)
+  "Add IMAGE of CATEGORY to the list of displayed images."
+  (let ((entry (assq category gnus-article-image-alist)))
+    (unless entry
+      (setq entry (list category))
+      (push entry gnus-article-image-alist))
+    (nconc entry (list image))))
+
+(defun gnus-delete-images (category)
+  "Delete all images in CATEGORY."
+  (let ((entry (assq category gnus-article-image-alist)))
+    (dolist (image (cdr entry))
+      (gnus-remove-image image category))
+    (setq gnus-article-image-alist (delq entry gnus-article-image-alist))
+    (gnus-delete-wash-type category)))
+
+(defalias 'gnus-article-hide-headers-if-wanted 'gnus-article-maybe-hide-headers)
+
+(defun gnus-article-maybe-hide-headers ()
   "Hide unwanted headers if `gnus-have-all-headers' is nil.
 Provided for backwards compatibility."
-  (or (save-excursion (set-buffer gnus-summary-buffer) gnus-have-all-headers)
-      gnus-inhibit-hiding
-      (gnus-article-hide-headers)))
+  (when (and (or (not (gnus-buffer-live-p gnus-summary-buffer))
+                (not (save-excursion (set-buffer gnus-summary-buffer)
+                                     gnus-have-all-headers)))
+            (not gnus-inhibit-hiding))
+    (gnus-article-hide-headers)))
 
 ;;; Article savers.
 
 (defun gnus-output-to-file (file-name)
   "Append the current article to a file named FILE-NAME."
   (let ((artbuf (current-buffer)))
-    (nnheader-temp-write nil
+    (with-temp-buffer
       (insert-buffer-substring artbuf)
       ;; Append newline at end of the buffer as separator, and then
       ;; save it to file.
       (goto-char (point-max))
       (insert "\n")
-      (append-to-file (point-min) (point-max) file-name)
+      (let ((file-name-coding-system nnmail-pathname-coding-system)
+           (pathname-coding-system nnmail-pathname-coding-system))
+       (write-region-as-binary (point-min) (point-max) file-name 'append))
       t)))
 
 (defun gnus-narrow-to-page (&optional arg)
@@ -2193,27 +5329,32 @@ If given a numerical ARG, move forward ARG pages."
       (let ((buffer-read-only nil))
        (gnus-remove-text-with-property 'gnus-prev)
        (gnus-remove-text-with-property 'gnus-next)))
-    (when
+    (if
        (cond ((< arg 0)
               (re-search-backward page-delimiter nil 'move (1+ (abs arg))))
              ((> arg 0)
               (re-search-forward page-delimiter nil 'move arg)))
-      (goto-char (match-end 0)))
-    (narrow-to-region
-     (point)
-     (if (re-search-forward page-delimiter nil 'move)
-        (match-beginning 0)
-       (point)))
-    (when (and (gnus-visual-p 'page-marker)
-              (not (= (point-min) 1)))
+       (goto-char (match-end 0))
       (save-excursion
        (goto-char (point-min))
-       (gnus-insert-prev-page-button)))
-    (when (and (gnus-visual-p 'page-marker)
-              (< (+ (point-max) 2) (buffer-size)))
-      (save-excursion
-       (goto-char (point-max))
-       (gnus-insert-next-page-button)))))
+       (setq gnus-page-broken
+             (and (re-search-forward page-delimiter nil t) t))))
+    (when gnus-page-broken
+      (narrow-to-region
+       (point)
+       (if (re-search-forward page-delimiter nil 'move)
+          (match-beginning 0)
+        (point)))
+      (when (and (gnus-visual-p 'page-marker)
+                (not (= (point-min) 1)))
+       (save-excursion
+         (goto-char (point-min))
+         (gnus-insert-prev-page-button)))
+      (when (and (gnus-visual-p 'page-marker)
+                (< (+ (point-max) 2) (buffer-size)))
+       (save-excursion
+         (goto-char (point-max))
+         (gnus-insert-next-page-button))))))
 
 ;; Article mode commands
 
@@ -2224,12 +5365,28 @@ If given a numerical ARG, move forward ARG pages."
     (goto-char (point-min))
     (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))))
 
+
 (defun gnus-article-goto-prev-page ()
-  "Show the next page of the article."
+  "Show the previous page of the article."
   (interactive)
-  (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?p))
+  (if (bobp)
+      (gnus-article-read-summary-keys nil (gnus-character-to-event ?p))
     (gnus-article-prev-page nil)))
 
+;; This is cleaner but currently breaks `gnus-pick-mode':
+;;
+;; (defun gnus-article-goto-next-page ()
+;;   "Show the next page of the article."
+;;   (interactive)
+;;   (gnus-eval-in-buffer-window gnus-summary-buffer
+;;     (gnus-summary-next-page)))
+;;
+;; (defun gnus-article-goto-prev-page ()
+;;   "Show the next page of the article."
+;;   (interactive)
+;;   (gnus-eval-in-buffer-window gnus-summary-buffer
+;;     (gnus-summary-prev-page)))
+
 (defun gnus-article-next-page (&optional lines)
   "Show the next page of the current article.
 If end of article, return non-nil.  Otherwise return nil.
@@ -2239,25 +5396,32 @@ Argument LINES specifies lines to be scrolled up."
   (if (save-excursion
        (end-of-line)
        (and (pos-visible-in-window-p)  ;Not continuation line.
-            (eobp)))
+            (>= (1+ (point)) (point-max)))) ;Allow for trailing newline.
       ;; Nothing in this page.
       (if (or (not gnus-page-broken)
              (save-excursion
                (save-restriction
-                 (widen) (forward-line 1) (eobp)))) ;Real end-of-buffer?
-         t                             ;Nothing more.
+                 (widen)
+                 (eobp)))) ;Real end-of-buffer?
+         (progn
+           (when gnus-article-over-scroll
+             (gnus-article-next-page-1 lines))
+           t)                  ;Nothing more.
        (gnus-narrow-to-page 1)         ;Go to next page.
        nil)
     ;; More in this page.
-    (let ((scroll-in-place nil))
-      (condition-case ()
-         (scroll-up lines)
-       (end-of-buffer
-        ;; Long lines may cause an end-of-buffer error.
-        (goto-char (point-max)))))
-    (move-to-window-line 0)
+    (gnus-article-next-page-1 lines)
     nil))
 
+(defun gnus-article-next-page-1 (lines)
+  (let ((scroll-in-place nil))
+    (condition-case ()
+       (scroll-up lines)
+      (end-of-buffer
+       ;; Long lines may cause an end-of-buffer error.
+       (goto-char (point-max)))))
+  (move-to-window-line 0))
+
 (defun gnus-article-prev-page (&optional lines)
   "Show previous page of current article.
 Argument LINES specifies lines to be scrolled down."
@@ -2278,17 +5442,33 @@ Argument LINES specifies lines to be scrolled down."
             (goto-char (point-min))))
        (move-to-window-line 0)))))
 
+(defun gnus-article-only-boring-p ()
+  "Decide whether there is only boring text remaining in the article.
+Something \"interesting\" is a word of at least two letters that does
+not have a face in `gnus-article-boring-faces'."
+  (when (and gnus-article-skip-boring
+            (boundp 'gnus-article-boring-faces)
+            (symbol-value 'gnus-article-boring-faces))
+    (save-excursion
+      (catch 'only-boring
+       (while (re-search-forward "\\b\\w\\w" nil t)
+         (forward-char -1)
+         (when (not (gnus-intersection
+                     (gnus-faces-at (point))
+                     (symbol-value 'gnus-article-boring-faces)))
+           (throw 'only-boring nil)))
+       (throw 'only-boring t)))))
+
 (defun gnus-article-refer-article ()
   "Read article specified by message-id around point."
   (interactive)
-  (let ((point (point)))
-    (search-forward ">" nil t)         ;Move point to end of "<....>".
-    (if (re-search-backward "\\(<[^<> \t\n]+>\\)" nil t)
-       (let ((message-id (match-string 1)))
-         (goto-char point)
+  (save-excursion
+    (re-search-backward "[ \t]\\|^" (gnus-point-at-bol) t)
+    (re-search-forward "<?news:<?\\|<" (gnus-point-at-eol) t)
+    (if (re-search-forward "[^@ ]+@[^ \t>]+" (gnus-point-at-eol) t)
+       (let ((msg-id (concat "<" (match-string 0) ">")))
          (set-buffer gnus-summary-buffer)
-         (gnus-summary-refer-article message-id))
-      (goto-char (point))
+         (gnus-summary-refer-article msg-id))
       (error "No references around point"))))
 
 (defun gnus-article-show-summary ()
@@ -2298,13 +5478,13 @@ Argument LINES specifies lines to be scrolled down."
       (error "There is no summary buffer for this article buffer")
     (gnus-article-set-globals)
     (gnus-configure-windows 'article)
-    (gnus-summary-goto-subject gnus-current-article)))
+    (gnus-summary-goto-subject gnus-current-article)
+    (gnus-summary-position-point)))
 
 (defun gnus-article-describe-briefly ()
   "Describe article mode commands briefly."
   (interactive)
-  (gnus-message 6
-               (substitute-command-keys "\\<gnus-article-mode-map>\\[gnus-article-goto-next-page]:Next page     \\[gnus-article-goto-prev-page]:Prev page  \\[gnus-article-show-summary]:Show summary  \\[gnus-info-find-node]:Run Info  \\[gnus-article-describe-briefly]:This help")))
+  (gnus-message 6 (substitute-command-keys "\\<gnus-article-mode-map>\\[gnus-article-goto-next-page]:Next page  \\[gnus-article-goto-prev-page]:Prev page  \\[gnus-article-show-summary]:Show summary  \\[gnus-info-find-node]:Run Info  \\[gnus-article-describe-briefly]:This help")))
 
 (defun gnus-article-summary-command ()
   "Execute the last keystroke in the summary buffer."
@@ -2327,25 +5507,33 @@ Argument LINES specifies lines to be scrolled down."
     (setq func (lookup-key (current-local-map) (this-command-keys)))
     (call-interactively func)))
 
+(defun gnus-article-check-buffer ()
+  "Beep if not in an article buffer."
+  (unless (eq (get-buffer gnus-article-buffer) (current-buffer))
+    (error "Command invoked outside of a Gnus article buffer")))
+
 (defun gnus-article-read-summary-keys (&optional arg key not-restore-window)
   "Read a summary buffer key sequence and execute it from the article buffer."
   (interactive "P")
+  (gnus-article-check-buffer)
   (let ((nosaves
-        '("q" "Q"  "c" "r" "R" "\C-c\C-f" "m"  "a" "f" "F"
-          "Zc" "ZC" "ZE" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
+        '("q" "Q"  "c" "r" "\C-c\C-f" "m"  "a" "f"
+          "Zc" "ZC" "ZE" "ZJ" "ZQ" "ZZ" "Zn" "ZR" "ZG" "ZN" "ZP"
           "=" "^" "\M-^" "|"))
        (nosave-but-article
         '("A\r"))
        (nosave-in-article
         '("\C-d"))
-        (up-to-top
-         '("n" "Gn" "p" "Gp"))
-       keys)
+       (up-to-top
+        '("n" "Gn" "p" "Gp"))
+       keys new-sum-point)
     (save-excursion
       (set-buffer gnus-article-current-summary)
       (let (gnus-pick-mode)
        (push (or key last-command-event) unread-command-events)
-       (setq keys (read-key-sequence nil))))
+       (setq keys (static-if (featurep 'xemacs)
+                      (events-to-keys (read-key-sequence nil))
+                    (read-key-sequence nil)))))
     (message "")
 
     (if (or (member keys nosaves)
@@ -2357,63 +5545,164 @@ Argument LINES specifies lines to be scrolled down."
            ;; We disable the pick minor mode commands.
            (let (gnus-pick-mode)
              (setq func (lookup-key (current-local-map) keys))))
-         (if (not func)
+         (if (or (not func)
+                 (numberp func))
              (ding)
            (unless (member keys nosave-in-article)
              (set-buffer gnus-article-current-summary))
-           (call-interactively func))
+           (call-interactively func)
+           (setq new-sum-point (point)))
          (when (member keys nosave-but-article)
            (pop-to-buffer gnus-article-buffer 'norecord)))
       ;; These commands should restore window configuration.
       (let ((obuf (current-buffer))
            (owin (current-window-configuration))
            (opoint (point))
-           func in-buffer)
+           (summary gnus-article-current-summary)
+           func in-buffer selected)
        (if not-restore-window
-           (pop-to-buffer gnus-article-current-summary 'norecord)
-         (switch-to-buffer gnus-article-current-summary 'norecord))
+           (pop-to-buffer summary 'norecord)
+         (switch-to-buffer summary 'norecord))
        (setq in-buffer (current-buffer))
        ;; We disable the pick minor mode commands.
-       (if (setq func (let (gnus-pick-mode)
-                        (lookup-key (current-local-map) keys)))
-           (call-interactively func)
-         (ding))
-       (when (eq in-buffer (current-buffer))
-         (set-buffer obuf)
-         (unless not-restore-window
-           (set-window-configuration owin))
-          (unless (member keys up-to-top)
-            (set-window-point (get-buffer-window (current-buffer))
-                              opoint)))))))
+       (if (and (setq func (let (gnus-pick-mode)
+                             (lookup-key (current-local-map) keys)))
+                (functionp func))
+           (progn
+             (call-interactively func)
+             (setq new-sum-point (point))
+             (when (eq in-buffer (current-buffer))
+               (setq selected (gnus-summary-select-article))
+               (set-buffer obuf)
+               (unless not-restore-window
+                 (set-window-configuration owin))
+               (when (eq selected 'old)
+                 (article-goto-body)
+                 (set-window-start (get-buffer-window (current-buffer))
+                                   1)
+                 (set-window-point (get-buffer-window (current-buffer))
+                                   (point)))
+               (let ((win (get-buffer-window gnus-article-current-summary)))
+                 (when win
+                   (set-window-point win new-sum-point))))    )
+         (switch-to-buffer gnus-article-buffer)
+         (ding))))))
+
+(defun gnus-article-describe-key (key)
+  "Display documentation of the function invoked by KEY.  KEY is a string."
+  (interactive "kDescribe key: ")
+  (gnus-article-check-buffer)
+  (if (eq (key-binding key) 'gnus-article-read-summary-keys)
+      (save-excursion
+       (set-buffer gnus-article-current-summary)
+       (let (gnus-pick-mode)
+         (if (featurep 'xemacs)
+             (progn
+               (push (elt key 0) unread-command-events)
+               (setq key (events-to-keys
+                          (read-key-sequence "Describe key: "))))
+           (setq unread-command-events
+                 (mapcar
+                  (lambda (x) (if (>= x 128) (list 'meta (- x 128)) x))
+                  key))
+           (setq key (read-key-sequence "Describe key: "))))
+       (describe-key key))
+    (describe-key key)))
+
+(defun gnus-article-describe-key-briefly (key &optional insert)
+  "Display documentation of the function invoked by KEY.  KEY is a string."
+  (interactive "kDescribe key: \nP")
+  (gnus-article-check-buffer)
+  (if (eq (key-binding key) 'gnus-article-read-summary-keys)
+      (save-excursion
+       (set-buffer gnus-article-current-summary)
+       (let (gnus-pick-mode)
+         (if (featurep 'xemacs)
+             (progn
+               (push (elt key 0) unread-command-events)
+               (setq key (events-to-keys
+                          (read-key-sequence "Describe key: "))))
+           (setq unread-command-events
+                 (mapcar
+                  (lambda (x) (if (>= x 128) (list 'meta (- x 128)) x))
+                  key))
+           (setq key (read-key-sequence "Describe key: "))))
+       (describe-key-briefly key insert))
+    (describe-key-briefly key insert)))
+
+(defun gnus-article-reply-with-original (&optional wide)
+  "Start composing a reply mail to the current message.
+The text in the region will be yanked.  If the region isn't active,
+the entire article will be yanked."
+  (interactive "P")
+  (let ((article (cdr gnus-article-current))
+       contents)
+    (if (not (gnus-mark-active-p))
+       (with-current-buffer gnus-summary-buffer
+         (gnus-summary-reply (list (list article)) wide))
+      (setq contents (buffer-substring (point) (mark t)))
+      ;; Deactivate active regions.
+      (when (and (boundp 'transient-mark-mode)
+                transient-mark-mode)
+       (setq mark-active nil))
+      (with-current-buffer gnus-summary-buffer
+       (gnus-summary-reply
+        (list (list article contents)) wide)))))
+
+(defun gnus-article-followup-with-original ()
+  "Compose a followup to the current article.
+The text in the region will be yanked.  If the region isn't active,
+the entire article will be yanked."
+  (interactive)
+  (let ((article (cdr gnus-article-current))
+       contents)
+      (if (not (gnus-mark-active-p))
+         (with-current-buffer gnus-summary-buffer
+           (gnus-summary-followup (list (list article))))
+       (setq contents (buffer-substring (point) (mark t)))
+       ;; Deactivate active regions.
+       (when (and (boundp 'transient-mark-mode)
+                  transient-mark-mode)
+         (setq mark-active nil))
+       (with-current-buffer gnus-summary-buffer
+         (gnus-summary-followup
+          (list (list article contents)))))))
 
 (defun gnus-article-hide (&optional arg force)
   "Hide all the gruft in the current article.
-This means that PGP stuff, signatures, cited text and (some)
-headers will be hidden.
+This means that signatures, cited text and (some) headers will be
+hidden.
 If given a prefix, show the hidden text instead."
   (interactive (append (gnus-article-hidden-arg) (list 'force)))
   (gnus-article-hide-headers arg)
-  (gnus-article-hide-pgp arg)
+  (gnus-article-hide-list-identifiers arg)
   (gnus-article-hide-citation-maybe arg force)
   (gnus-article-hide-signature arg))
 
 (defun gnus-article-maybe-highlight ()
-  "Do some article highlighting if `article-visual' is non-nil."
+  "Do some article highlighting if article highlighting is requested."
   (when (gnus-visual-p 'article-highlight 'highlight)
     (gnus-article-highlight-some)))
 
+(defun gnus-check-group-server ()
+  ;; Make sure the connection to the server is alive.
+  (unless (gnus-server-opened
+          (gnus-find-method-for-group gnus-newsgroup-name))
+    (gnus-check-server (gnus-find-method-for-group gnus-newsgroup-name))
+    (gnus-request-group gnus-newsgroup-name t)))
+
+(eval-when-compile
+  (autoload 'nneething-get-file-name "nneething"))
+
 (defun gnus-request-article-this-buffer (article group)
   "Get an article and insert it into this buffer."
-  (let (do-update-line)
+  (let (do-update-line sparse-header)
     (prog1
        (save-excursion
          (erase-buffer)
          (gnus-kill-all-overlays)
          (setq group (or group gnus-newsgroup-name))
 
-         ;; Open server if it has closed.
-         (gnus-check-server (gnus-find-method-for-group group))
-
          ;; Using `gnus-request-article' directly will insert the article into
          ;; `nntp-server-buffer' - so we'll save some time by not having to
          ;; copy it from the server buffer into the article buffer.
@@ -2421,8 +5710,7 @@ If given a prefix, show the hidden text instead."
          ;; We only request an article by message-id when we do not have the
          ;; headers for it, so we'll have to get those.
          (when (stringp article)
-           (let ((gnus-override-method gnus-refer-article-method))
-             (gnus-read-header article)))
+           (gnus-read-header article))
 
          ;; If the article number is negative, that means that this article
          ;; doesn't belong in this newsgroup (possibly), so we find its
@@ -2430,7 +5718,7 @@ If given a prefix, show the hidden text instead."
          (when (and (numberp article)
                     gnus-summary-buffer
                     (get-buffer gnus-summary-buffer)
-                    (buffer-name (get-buffer gnus-summary-buffer)))
+                    (gnus-buffer-exists-p gnus-summary-buffer))
            (save-excursion
              (set-buffer gnus-summary-buffer)
              (let ((header (gnus-summary-article-header article)))
@@ -2440,8 +5728,7 @@ If given a prefix, show the hidden text instead."
                    ;; This is a sparse gap article.
                    (setq do-update-line article)
                    (setq article (mail-header-id header))
-                   (let ((gnus-override-method gnus-refer-article-method))
-                     (gnus-read-header article))
+                   (setq sparse-header (gnus-read-header article))
                    (setq gnus-newsgroup-sparse
                          (delq article gnus-newsgroup-sparse)))
                   ((vectorp header)
@@ -2454,11 +5741,12 @@ If given a prefix, show the hidden text instead."
 
                (let ((method (gnus-find-method-for-group
                               gnus-newsgroup-name)))
-                 (if (not (eq (car method) 'nneething))
-                     ()
-                   (let ((dir (concat (file-name-as-directory (nth 1 method))
-                                      (mail-header-subject header))))
-                     (when (file-directory-p dir)
+                 (when (and (eq (car method) 'nneething)
+                            (vectorp header))
+                   (let ((dir (nneething-get-file-name
+                               (mail-header-id header))))
+                     (when (and (stringp dir)
+                                (file-directory-p dir))
                        (setq article 'nneething)
                        (gnus-group-enter-directory dir))))))))
 
@@ -2467,7 +5755,7 @@ If given a prefix, show the hidden text instead."
           ((and (numberp article)
                 gnus-summary-buffer
                 (get-buffer gnus-summary-buffer)
-                (buffer-name (get-buffer gnus-summary-buffer))
+                (gnus-buffer-exists-p gnus-summary-buffer)
                 (eq (cdr (save-excursion
                            (set-buffer gnus-summary-buffer)
                            (assq article gnus-newsgroup-reads)))
@@ -2497,26 +5785,58 @@ If given a prefix, show the hidden text instead."
                 (numberp article)
                 (gnus-cache-request-article article group))
            'article)
+          ;; Check the agent cache.
+          ((gnus-agent-request-article article group)
+           'article)
           ;; Get the article and put into the article buffer.
-          ((or (stringp article) (numberp article))
-           (let ((gnus-override-method
-                  (and (stringp article) gnus-refer-article-method))
+          ((or (stringp article)
+               (numberp article))
+           (let ((gnus-override-method gnus-override-method)
+                 (methods (and (stringp article)
+                               gnus-refer-article-method))
+                 (backend (car (gnus-find-method-for-group
+                                gnus-newsgroup-name)))
+                 result
                  (buffer-read-only nil))
-             (erase-buffer)
-             (gnus-kill-all-overlays)
-             (when (gnus-request-article article group (current-buffer))
-               (when (numberp article)
-                 (gnus-async-prefetch-next group article gnus-summary-buffer)
-                 (when gnus-keep-backlog
-                   (gnus-backlog-enter-article
-                    group article (current-buffer))))
-               'article)))
+             (if (or (not (listp methods))
+                     (and (symbolp (car methods))
+                          (assq (car methods) nnoo-definition-alist)))
+                 (setq methods (list methods)))
+             (when (and (null gnus-override-method)
+                        methods)
+               (setq gnus-override-method (pop methods)))
+             (while (not result)
+               (when (eq gnus-override-method 'current)
+                 (setq gnus-override-method
+                       (with-current-buffer gnus-summary-buffer
+                         gnus-current-select-method)))
+               (erase-buffer)
+               (gnus-kill-all-overlays)
+               (let ((gnus-newsgroup-name group))
+                 (gnus-check-group-server))
+               (cond
+                ((gnus-request-article article group (current-buffer))
+                 (when (numberp article)
+                   (gnus-async-prefetch-next group article
+                                             gnus-summary-buffer)
+                   (when gnus-keep-backlog
+                     (gnus-backlog-enter-article
+                      group article (current-buffer))))
+                 (setq result 'article))
+                (methods
+                 (setq gnus-override-method (pop methods)))
+                ((not (string-match "^400 "
+                                    (nnheader-get-report backend)))
+                 ;; If we get 400 server disconnect, reconnect and
+                 ;; retry; otherwise, assume the article has expired.
+                 (setq result 'done))))
+             (and (eq result 'article) 'article)))
           ;; It was a pseudo.
           (t article)))
 
       ;; Associate this article with the current summary buffer.
       (setq gnus-article-current-summary gnus-summary-buffer)
-      
+
       ;; Take the article from the original article buffer
       ;; and place it in the buffer it's supposed to be in.
       (when (and (get-buffer gnus-article-buffer)
@@ -2524,16 +5844,20 @@ If given a prefix, show the hidden text instead."
                        (buffer-name (get-buffer gnus-article-buffer))))
        (save-excursion
          (if (get-buffer gnus-original-article-buffer)
-             (set-buffer (get-buffer gnus-original-article-buffer))
-           (set-buffer (get-buffer-create gnus-original-article-buffer))
-           (buffer-disable-undo (current-buffer))
+             (set-buffer gnus-original-article-buffer)
+           (set-buffer (gnus-get-buffer-create gnus-original-article-buffer))
+           (buffer-disable-undo)
            (setq major-mode 'gnus-original-article-mode)
-           (setq buffer-read-only t)
-           (gnus-add-current-to-buffer-list))
+           (setq buffer-read-only t))
          (let (buffer-read-only)
            (erase-buffer)
            (insert-buffer-substring gnus-article-buffer))
-         (setq gnus-original-article (cons group article))))
+         (setq gnus-original-article (cons group article)))
+
+       ;; Decode charsets.
+       (run-hooks 'gnus-article-decode-hook)
+       ;; Mark article as decoded or not.
+       (setq gnus-article-decoded-p gnus-article-decode-hook))
 
       ;; Update sparse articles.
       (when (and do-update-line
@@ -2541,9 +5865,9 @@ If given a prefix, show the hidden text instead."
                     (stringp article)))
        (let ((buf (current-buffer)))
          (set-buffer gnus-summary-buffer)
-         (gnus-summary-update-article do-update-line)
+         (gnus-summary-update-article do-update-line sparse-header)
          (gnus-summary-goto-subject do-update-line nil t)
-         (set-window-point (get-buffer-window (current-buffer) t)
+         (set-window-point (gnus-get-buffer-window (current-buffer) t)
                            (point))
          (set-buffer buf))))))
 
@@ -2556,37 +5880,95 @@ If given a prefix, show the hidden text instead."
   :group 'gnus-article-various
   :type 'hook)
 
+(defcustom gnus-article-edit-article-setup-function
+  'gnus-article-mime-edit-article-setup
+  "Function called to setup an editing article buffer."
+  :group 'gnus-article-various
+  :type 'function)
+
 (defvar gnus-article-edit-done-function nil)
 
 (defvar gnus-article-edit-mode-map nil)
+(defvar gnus-article-edit-mode nil)
 
+;; Should we be using derived.el for this?
 (unless gnus-article-edit-mode-map
-  (setq gnus-article-edit-mode-map (copy-keymap text-mode-map))
+  (setq gnus-article-edit-mode-map (make-keymap))
+  (set-keymap-parent gnus-article-edit-mode-map text-mode-map)
 
   (gnus-define-keys gnus-article-edit-mode-map
+    "\C-c?"    describe-mode
     "\C-c\C-c" gnus-article-edit-done
-    "\C-c\C-k" gnus-article-edit-exit)
+    "\C-c\C-k" gnus-article-edit-exit
+    "\C-c\C-f\C-t" message-goto-to
+    "\C-c\C-f\C-o" message-goto-from
+    "\C-c\C-f\C-b" message-goto-bcc
+    ;;"\C-c\C-f\C-w" message-goto-fcc
+    "\C-c\C-f\C-c" message-goto-cc
+    "\C-c\C-f\C-s" message-goto-subject
+    "\C-c\C-f\C-r" message-goto-reply-to
+    "\C-c\C-f\C-n" message-goto-newsgroups
+    "\C-c\C-f\C-d" message-goto-distribution
+    "\C-c\C-f\C-f" message-goto-followup-to
+    "\C-c\C-f\C-m" message-goto-mail-followup-to
+    "\C-c\C-f\C-k" message-goto-keywords
+    "\C-c\C-f\C-u" message-goto-summary
+    "\C-c\C-f\C-i" message-insert-or-toggle-importance
+    "\C-c\C-f\C-a" message-generate-unsubscribed-mail-followup-to
+    "\C-c\C-b" message-goto-body
+    "\C-c\C-i" message-goto-signature
+
+    "\C-c\C-t" message-insert-to
+    "\C-c\C-n" message-insert-newsgroups
+    "\C-c\C-o" message-sort-headers
+    "\C-c\C-e" message-elide-region
+    "\C-c\C-v" message-delete-not-region
+    "\C-c\C-z" message-kill-to-signature
+    "\M-\r" message-newline-and-reformat
+    "\C-c\C-a" mml-attach-file
+    "\C-a" message-beginning-of-line
+    "\t" message-tab
+    "\M-;" comment-region)
 
   (gnus-define-keys (gnus-article-edit-wash-map
                     "\C-c\C-w" gnus-article-edit-mode-map)
     "f" gnus-article-edit-full-stops))
 
-(defun gnus-article-edit-mode ()
+(easy-menu-define
+  gnus-article-edit-mode-field-menu gnus-article-edit-mode-map ""
+  '("Field"
+    ["Fetch To" message-insert-to t]
+    ["Fetch Newsgroups" message-insert-newsgroups t]
+    "----"
+    ["To" message-goto-to t]
+    ["From" message-goto-from t]
+    ["Subject" message-goto-subject t]
+    ["Cc" message-goto-cc t]
+    ["Reply-To" message-goto-reply-to t]
+    ["Summary" message-goto-summary t]
+    ["Keywords" message-goto-keywords t]
+    ["Newsgroups" message-goto-newsgroups t]
+    ["Followup-To" message-goto-followup-to t]
+    ["Mail-Followup-To" message-goto-mail-followup-to t]
+    ["Distribution" message-goto-distribution t]
+    ["Body" message-goto-body t]
+    ["Signature" message-goto-signature t]))
+
+(define-derived-mode gnus-article-edit-mode text-mode "Article Edit"
   "Major mode for editing articles.
 This is an extended text-mode.
 
 \\{gnus-article-edit-mode-map}"
-  (interactive)
-  (kill-all-local-variables)
-  (setq major-mode 'gnus-article-edit-mode)
-  (setq mode-name "Article Edit")
-  (use-local-map gnus-article-edit-mode-map)
   (make-local-variable 'gnus-article-edit-done-function)
   (make-local-variable 'gnus-prev-winconf)
+  (set (make-local-variable 'font-lock-defaults)
+       '(message-font-lock-keywords t))
+  (set (make-local-variable 'mail-header-separator) "")
+  (set (make-local-variable 'gnus-article-edit-mode) t)
+  (easy-menu-add message-mode-field-menu message-mode-map)
   (setq buffer-read-only nil)
   (buffer-enable-undo)
-  (widen)
-  (gnus-run-hooks 'text-mode-hook 'gnus-article-edit-mode-hook))
+  (widen))
 
 (defun gnus-article-edit (&optional force)
   "Edit the current article.
@@ -2599,90 +5981,83 @@ groups."
     (error "The current newsgroup does not support article editing"))
   (gnus-article-date-original)
   (gnus-article-edit-article
+   'ignore
    `(lambda (no-highlight)
+      'ignore
       (gnus-summary-edit-article-done
        ,(or (mail-header-references gnus-current-headers) "")
        ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight))))
 
-(defun gnus-article-edit-article (exit-func)
+(defun gnus-article-edit-article (start-func exit-func)
   "Start editing the contents of the current article buffer."
   (let ((winconf (current-window-configuration)))
     (set-buffer gnus-article-buffer)
     (gnus-article-edit-mode)
-    (gnus-set-text-properties (point-min) (point-max) nil)
+    (funcall start-func)
+    (set-buffer-modified-p nil)
     (gnus-configure-windows 'edit-article)
     (setq gnus-article-edit-done-function exit-func)
     (setq gnus-prev-winconf winconf)
-    (gnus-message 6 "C-c C-c to end edits")))
+    (when gnus-article-edit-article-setup-function
+      (funcall gnus-article-edit-article-setup-function))
+    (gnus-message 6 "C-c C-c to end edits; C-c C-k to exit")))
 
 (defun gnus-article-edit-done (&optional arg)
   "Update the article edits and exit."
   (interactive "P")
-  (save-excursion
-    (save-restriction
-      (widen)
-      (goto-char (point-min))
-      (when (search-forward "\n\n" nil 1)
-       (let ((lines (count-lines (point) (point-max)))
-             (length (- (point-max) (point)))
-             (case-fold-search t)
-             (body (copy-marker (point))))
-         (goto-char (point-min))
-         (when (re-search-forward "^content-length:[ \t]\\([0-9]+\\)" body t)
-           (delete-region (match-beginning 1) (match-end 1))
-           (insert (number-to-string length)))
-         (goto-char (point-min))
-         (when (re-search-forward
-                "^x-content-length:[ \t]\\([0-9]+\\)" body t)
-           (delete-region (match-beginning 1) (match-end 1))
-           (insert (number-to-string length)))
-         (goto-char (point-min))
-         (when (re-search-forward "^lines:[ \t]\\([0-9]+\\)" body t)
-           (delete-region (match-beginning 1) (match-end 1))
-           (insert (number-to-string lines)))))))
   (let ((func gnus-article-edit-done-function)
        (buf (current-buffer))
-       (start (window-start)))
-    (gnus-article-edit-exit)
+       (start (window-start))
+       (p (point))
+       (winconf gnus-prev-winconf))
+    (remove-hook 'gnus-article-mode-hook
+                'gnus-article-mime-edit-article-unwind)
+    (widen) ;; Widen it in case that users narrowed the buffer.
+    (funcall func arg)
+    (set-buffer buf)
+    ;; The cache and backlog have to be flushed somewhat.
+    (when gnus-keep-backlog
+      (gnus-backlog-remove-article
+       (car gnus-article-current) (cdr gnus-article-current)))
+    ;; Flush original article as well.
     (save-excursion
-      (set-buffer buf)
-      (let ((buffer-read-only nil))
-       (funcall func arg)))
+      (when (get-buffer gnus-original-article-buffer)
+       (set-buffer gnus-original-article-buffer)
+       (setq gnus-original-article nil)))
+    (when gnus-use-cache
+      (gnus-cache-update-article
+       (car gnus-article-current) (cdr gnus-article-current)))
+    ;; We remove all text props from the article buffer.
+    (kill-all-local-variables)
+    (gnus-set-text-properties (point-min) (point-max) nil)
+    (gnus-article-mode)
+    (set-window-configuration winconf)
     (set-buffer buf)
     (set-window-start (get-buffer-window buf) start)
-    (set-window-point (get-buffer-window buf) (point))))
+    (set-window-point (get-buffer-window buf) (point)))
+  (gnus-summary-show-article))
 
 (defun gnus-article-edit-exit ()
   "Exit the article editing without updating."
   (interactive)
-  ;; We remove all text props from the article buffer.
-  (let ((buf (format "%s" (buffer-string)))
-       (curbuf (current-buffer))
-       (p (point))
-       (window-start (window-start)))
-    (erase-buffer)
-    (insert buf)
-    (let ((winconf gnus-prev-winconf))
-      (gnus-article-mode)
-      ;; The cache and backlog have to be flushed somewhat.
-      (when gnus-use-cache
-       (gnus-cache-update-article
-        (car gnus-article-current) (cdr gnus-article-current)))
-      (when gnus-keep-backlog
-       (gnus-backlog-remove-article
-        (car gnus-article-current) (cdr gnus-article-current)))
-      ;; Flush original article as well.
-      (save-excursion
-       (when (get-buffer gnus-original-article-buffer)
-         (set-buffer gnus-original-article-buffer)
-         (setq gnus-original-article nil)))
-      (set-window-configuration winconf)
-      ;; Tippy-toe some to make sure that point remains where it was.
-      (let ((buf (current-buffer)))
-       (set-buffer curbuf)
-       (set-window-start (get-buffer-window (current-buffer)) window-start)
-       (goto-char p)
-       (set-buffer buf)))))
+  (when (or (not (buffer-modified-p))
+           (yes-or-no-p "Article modified; kill anyway? "))
+    (let ((curbuf (current-buffer))
+         (p (point))
+         (window-start (window-start)))
+      (erase-buffer)
+      (if (gnus-buffer-live-p gnus-original-article-buffer)
+         (insert-buffer-substring gnus-original-article-buffer))
+      (let ((winconf gnus-prev-winconf))
+       (kill-all-local-variables)
+       (gnus-article-mode)
+       (set-window-configuration winconf)
+       ;; Tippy-toe some to make sure that point remains where it was.
+       (save-current-buffer
+         (set-buffer curbuf)
+         (set-window-start (get-buffer-window (current-buffer)) window-start)
+         (goto-char p))))
+    (gnus-summary-show-article)))
 
 (defun gnus-article-edit-full-stops ()
   "Interactively repair spacing at end of sentences."
@@ -2694,6 +6069,120 @@ groups."
       (query-replace-regexp "\\([.!?][])}]* \\)\\([[({A-Z]\\)" "\\1 \\2"))))
 
 ;;;
+;;; Article editing with MIME-Edit
+;;;
+
+(defcustom gnus-article-mime-edit-article-setup-hook nil
+  "Hook run after setting up a MIME editing article buffer."
+  :group 'gnus-article-various
+  :type 'hook)
+
+(defun gnus-article-mime-edit-article-unwind ()
+  "Unwind `gnus-article-buffer' if article editing was given up."
+  (remove-hook 'gnus-article-mode-hook 'gnus-article-mime-edit-article-unwind)
+  (when (featurep 'font-lock)
+    (setq font-lock-defaults nil)
+    (font-lock-mode -1))
+  (when mime-edit-mode-flag
+    (mime-edit-exit 'nomime 'no-error)
+    (message "")))
+
+(defun gnus-article-mime-edit-article-setup ()
+  "Convert current buffer to MIME-Edit buffer and turn on MIME-Edit mode
+after replacing with the original article."
+  (setq gnus-show-mime t)
+  (setq gnus-article-edit-done-function
+       `(lambda (&rest args)
+          (when mime-edit-mode-flag
+            (let (mime-edit-insert-user-agent-field)
+              (mime-edit-exit))
+            (message ""))
+          (goto-char (point-min))
+          (let (case-fold-search)
+            (when (re-search-forward
+                   (format "^%s$" (regexp-quote mail-header-separator))
+                   nil t)
+              (replace-match "")))
+          (apply ,gnus-article-edit-done-function args)
+          (insert
+           (prog1
+               (buffer-substring-no-properties (point-min) (point-max))
+             (set-buffer (get-buffer-create gnus-original-article-buffer))
+             (erase-buffer)))
+          (setq gnus-current-headers (gnus-article-make-full-mail-header))
+          (set-buffer gnus-article-buffer)
+          (gnus-article-prepare-display)))
+  (substitute-key-definition 'gnus-article-edit-done
+                            'gnus-article-mime-edit-done
+                            gnus-article-edit-mode-map)
+  (substitute-key-definition 'gnus-article-edit-exit
+                            'gnus-article-mime-edit-exit
+                            gnus-article-edit-mode-map)
+  (erase-buffer)
+  (insert-buffer-substring gnus-original-article-buffer)
+  (unless (member (with-current-buffer gnus-summary-buffer
+                   gnus-newsgroup-name)
+                 '("nndraft:delayed" "nndraft:drafts"))
+    (let ((ofn (symbol-function 'mime-edit-decode-single-part-in-buffer)))
+      (fset 'mime-edit-decode-single-part-in-buffer
+           (lambda (&rest args)
+             (if (let ((content-type (car args)))
+                   (and (eq 'message (mime-content-type-primary-type
+                                      content-type))
+                        (eq 'rfc822 (mime-content-type-subtype
+                                     content-type))))
+                 (setcar (cdr args) 'not-decode-text))
+             (apply ofn args)))
+      (unwind-protect
+         (mime-edit-again)
+       (fset 'mime-edit-decode-single-part-in-buffer ofn))))
+  (when (featurep 'font-lock)
+    (set (make-local-variable 'font-lock-defaults)
+        '(message-font-lock-keywords t))
+    (font-lock-set-defaults)
+    (turn-on-font-lock))
+  (set-buffer-modified-p nil)
+  (delete-other-windows)
+  (add-hook 'gnus-article-mode-hook 'gnus-article-mime-edit-article-unwind)
+  (gnus-run-hooks 'gnus-article-mime-edit-article-setup-hook))
+
+(defun gnus-article-mime-edit-done (&optional arg)
+  "Update the article MIME edits and exit."
+  (interactive "P")
+  (when (featurep 'font-lock)
+    (setq font-lock-defaults nil)
+    (font-lock-mode -1))
+  (let ((inhibit-read-only t))
+    (gnus-article-edit-done arg)))
+
+(defun gnus-article-mime-edit-exit ()
+  "Exit the article MIME editing without updating."
+  (interactive)
+  (when (or (not (buffer-modified-p))
+           (yes-or-no-p "Article modified; kill anyway? "))
+    (when (featurep 'font-lock)
+      (setq font-lock-defaults nil)
+      (font-lock-mode -1))
+    (when mime-edit-mode-flag
+      (let (mime-edit-insert-user-agent-field)
+       (mime-edit-exit))
+      (message ""))
+    (goto-char (point-min))
+    (let (case-fold-search)
+      (when (re-search-forward
+            (format "^%s$" (regexp-quote mail-header-separator)) nil t)
+       (replace-match "")))
+    (let ((winconf gnus-prev-winconf))
+      (insert (prog1
+                 (buffer-substring-no-properties (point-min) (point-max))
+               (set-buffer (get-buffer-create gnus-original-article-buffer))
+               (erase-buffer)))
+      (setq gnus-current-headers (gnus-article-make-full-mail-header))
+      (set-buffer gnus-article-buffer)
+      (gnus-article-prepare-display)
+      (set-window-configuration winconf))))
+
+;;;
 ;;; Article highlights
 ;;;
 
@@ -2701,32 +6190,496 @@ groups."
 
 ;;; Internal Variables:
 
-(defcustom gnus-button-url-regexp "\\b\\(s?https?\\|ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?\\([-a-zA-Z0-9_=!?#$@~`%&*+|\\/:;.,]\\|\\w\\)+\\([-a-zA-Z0-9_=#$@~`%&*+|\\/]\\|\\w\\)"
+(defcustom gnus-button-url-regexp
+  (if (string-match "[[:digit:]]" "1") ;; support POSIX?
+      "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|nntp\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?[-a-z0-9_=!?#$@~%&*+\\/:;.,[:word:]]+[-a-z0-9_=#$@~%&*+\\/[:word:]]\\)"
+    "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|nntp\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)\\(//[-a-z0-9_.]+:[0-9]*\\)?\\([-a-z0-9_=!?#$@~%&*+\\/:;.,]\\|\\w\\)+\\([-a-z0-9_=#$@~%&*+\\/]\\|\\w\\)\\)")
   "Regular expression that matches URLs."
   :group 'gnus-article-buttons
   :type 'regexp)
 
+(defcustom gnus-button-valid-fqdn-regexp
+  message-valid-fqdn-regexp
+  "Regular expression that matches a valid FQDN."
+  :group 'gnus-article-buttons
+  :type 'regexp)
+
+(defcustom gnus-button-man-handler 'manual-entry
+  "Function to use for displaying man pages.
+The function must take at least one argument with a string naming the
+man page."
+  :type '(choice (function-item :tag "Man" manual-entry)
+                (function-item :tag "Woman" woman)
+                (function :tag "Other"))
+  :group 'gnus-article-buttons)
+
+(defcustom gnus-ctan-url "http://tug.ctan.org/tex-archive/"
+  "Top directory of a CTAN \(Comprehensive TeX Archive Network\) archive.
+If the default site is too slow, try to find a CTAN mirror, see
+<URL:http://tug.ctan.org/tex-archive/CTAN.sites?action=/index.html>.  See also
+the variable `gnus-button-handle-ctan'."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type '(choice (const "http://www.tex.ac.uk/tex-archive/")
+                (const "http://tug.ctan.org/tex-archive/")
+                (const "http://www.dante.de/CTAN/")
+                (string :tag "Other")))
+
+(defcustom gnus-button-ctan-handler 'browse-url
+  "Function to use for displaying CTAN links.
+The function must take one argument, the string naming the URL."
+  :type '(choice (function-item :tag "Browse Url" browse-url)
+                (function :tag "Other"))
+  :group 'gnus-article-buttons)
+
+(defcustom gnus-button-handle-ctan-bogus-regexp "^/?tex-archive/\\|^/"
+  "Bogus strings removed from CTAN URLs."
+  :group 'gnus-article-buttons
+  :type '(choice (const "^/?tex-archive/\\|/")
+                (regexp :tag "Other")))
+
+(defcustom gnus-button-ctan-directory-regexp
+  (concat
+   "\\("; Cannot use `\(?: ... \)' (compatibility with Emacs 20).
+   "biblio\\|digests\\|dviware\\|fonts\\|graphics\\|help\\|"
+   "indexing\\|info\\|language\\|macros\\|support\\|systems\\|"
+   "tds\\|tools\\|usergrps\\|web\\|nonfree\\|obsolete"
+   "\\)")
+  "Regular expression for ctan directories.
+It should match all directories in the top level of `gnus-ctan-url'."
+  :group 'gnus-article-buttons
+  :type 'regexp)
+
+(defcustom gnus-button-mid-or-mail-regexp
+  (concat "\\b\\(<?[a-z0-9$%(*-=?[_][^<>\")!;:,{}\n\t ]*@"
+         ;; Felix Wiemann in <87oeuomcz9.fsf@news2.ososo.de>
+         gnus-button-valid-fqdn-regexp
+         ">?\\)\\b")
+  "Regular expression that matches a message ID or a mail address."
+  :group 'gnus-article-buttons
+  :type 'regexp)
+
+(defcustom gnus-button-prefer-mid-or-mail 'gnus-button-mid-or-mail-heuristic
+  "What to do when the button on a string as \"foo123@bar.invalid\" is pushed.
+Strings like this can be either a message ID or a mail address.  If it is one
+of the symbols `mid' or `mail', Gnus will always assume that the string is a
+message ID or a mail address, respectively.  If this variable is set to the
+symbol `ask', always query the user what do do.  If it is a function, this
+function will be called with the string as it's only argument.  The function
+must return `mid', `mail', `invalid' or `ask'."
+  :group 'gnus-article-buttons
+  :type '(choice (function-item :tag "Heuristic function"
+                               gnus-button-mid-or-mail-heuristic)
+                (const ask)
+                (const mid)
+                (const mail)))
+
+(defcustom gnus-button-mid-or-mail-heuristic-alist
+  '((-10.0 . ".+\\$.+@")
+    (-10.0 . "#")
+    (-10.0 . "\\*")
+    (-5.0  . "\\+[^+]*\\+.*@") ;; # two plus signs
+    (-5.0  . "@[Nn][Ee][Ww][Ss]") ;; /\@news/i
+    (-5.0  . "@.*[Dd][Ii][Aa][Ll][Uu][Pp]") ;; /\@.*dialup/i;
+    (-1.0  . "^[^a-z]+@")
+    ;;
+    (-5.0  . "\\.[0-9][0-9]+.*@") ;; "\.[0-9]{2,}.*\@"
+    (-5.0  . "[a-z].*[A-Z].*[a-z].*[A-Z].*@") ;; "([a-z].*[A-Z].*){2,}\@"
+    (-3.0  . "[A-Z][A-Z][a-z][a-z].*@")
+    (-5.0  . "\\...?.?@") ;; (-5.0 . "\..{1,3}\@")
+    ;;
+    (-2.0  . "^[0-9]")
+    (-1.0  . "^[0-9][0-9]")
+    ;;
+    ;; -3.0 /^[0-9][0-9a-fA-F]{2,2}/;
+    (-3.0  . "^[0-9][0-9a-fA-F][0-9a-fA-F][^0-9a-fA-F]")
+    ;; -5.0 /^[0-9][0-9a-fA-F]{3,3}/;
+    (-5.0  . "^[0-9][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][^0-9a-fA-F]")
+    ;;
+    (-3.0  .  "[0-9][0-9][0-9][0-9][0-9][^0-9].*@") ;; "[0-9]{5,}.*\@"
+    (-3.0  .  "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][^0-9].*@")
+    ;;       "[0-9]{8,}.*\@"
+    (-3.0
+     . "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].*@")
+    ;; "[0-9]{12,}.*\@"
+    ;; compensation for TDMA dated mail addresses:
+    (25.0  . "-dated-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]+.*@")
+    ;;
+    (-20.0 . "\\.fsf@")        ;; Gnus
+    (-20.0 . "^slrn")
+    (-20.0 . "^Pine")
+    (-20.0 . "_-_") ;; Subject change in thread
+    ;;
+    (-20.0 . "\\.ln@") ;; leafnode
+    (-30.0 . "@ID-[0-9]+\\.[a-zA-Z]+\\.dfncis\\.de")
+    (-30.0 . "@4[Aa][Xx]\\.com") ;; Forte Agent
+    ;;
+    ;; (5.0 . "") ;; $local_part_len <= 7
+    (10.0  . "^[^0-9]+@")
+    (3.0   . "^[^0-9]+[0-9][0-9]?[0-9]?@")
+    ;;      ^[^0-9]+[0-9]{1,3}\@ digits only at end of local part
+    (3.0   . "\@stud")
+    ;;
+    (2.0   . "[a-z][a-z][._-][A-Z][a-z].*@")
+    ;;
+    (0.5   . "^[A-Z][a-z]")
+    (0.5   . "^[A-Z][a-z][a-z]")
+    (1.5   . "^[A-Z][a-z][A-Z][a-z][^a-z]") ;; ^[A-Z][a-z]{3,3}
+    (2.0   . "^[A-Z][a-z][A-Z][a-z][a-z][^a-z]")) ;; ^[A-Z][a-z]{4,4}
+  "An alist of \(RATE . REGEXP\) pairs for `gnus-button-mid-or-mail-heuristic'.
+
+A negative RATE indicates a message IDs, whereas a positive indicates a mail
+address.  The REGEXP is processed with `case-fold-search' set to nil."
+  :group 'gnus-article-buttons
+  :type '(repeat (cons (number :tag "Rate")
+                      (regexp :tag "Regexp"))))
+
+(defun gnus-button-mid-or-mail-heuristic (mid-or-mail)
+  "Guess whether MID-OR-MAIL is a message ID or a mail address.
+Returns `mid' if MID-OR-MAIL is a message IDs, `mail' if it's a mail
+address, `ask' if unsure and `invalid' if the string is invalid."
+  (let ((case-fold-search nil)
+       (list gnus-button-mid-or-mail-heuristic-alist)
+       (result 0) rate regexp lpartlen elem)
+    (setq lpartlen
+         (length (gnus-replace-in-string mid-or-mail "^\\(.*\\)@.*$" "\\1")))
+    (gnus-message 8 "`%s', length of local part=`%s'." mid-or-mail lpartlen)
+    ;; Certain special cases...
+    (when (string-match
+          (concat
+           "^0[0-9]+-[0-9][0-9][0-9][0-9]@t-online\\.de$\\|"
+           "^[0-9]+\\.[0-9]+@compuserve\\|"
+           "@public\\.gmane\\.org")
+          mid-or-mail)
+      (gnus-message 8 "`%s' is a known mail address." mid-or-mail)
+      (setq result 'mail))
+    (when (string-match "@.*@\\| " mid-or-mail)
+      (gnus-message 8 "`%s' is invalid." mid-or-mail)
+      (setq result 'invalid))
+    ;; Nothing more to do, if result is not a number here...
+    (when (numberp result)
+      (while list
+       (setq elem (car list)
+             rate (car elem)
+             regexp (cdr elem)
+             list (cdr list))
+       (when (string-match regexp mid-or-mail)
+         (setq result (+ result rate))
+         (gnus-message
+          9 "`%s' matched `%s', rate `%s', result `%s'."
+          mid-or-mail regexp rate result)))
+      (when (<= lpartlen 7)
+       (setq result (+ result 5.0))
+       (gnus-message 9 "`%s' matched (<= lpartlen 7), result `%s'."
+                     mid-or-mail result))
+      (when (>= lpartlen 12)
+       (gnus-message 9 "`%s' matched (>= lpartlen 12)" mid-or-mail)
+       (cond
+        ((string-match "[0-9][^0-9]+[0-9].*@" mid-or-mail)
+         ;; Long local part should contain realname if e-mail address,
+         ;; too many digits: message-id.
+         ;; $score -= 5.0 + 0.1 * $local_part_len;
+         (setq rate (* -1.0 (+ 5.0 (* 0.1 lpartlen))))
+         (setq result (+ result rate))
+         (gnus-message
+          9 "Many digits in `%s', rate `%s', result `%s'."
+          mid-or-mail rate result))
+        ((string-match "[^aeiouy][^aeiouy][^aeiouy][^aeiouy]+.*\@"
+                       mid-or-mail)
+         ;; Too few vowels [^aeiouy]{4,}.*\@
+         (setq result (+ result -5.0))
+         (gnus-message
+          9 "Few vowels in `%s', rate `%s', result `%s'."
+          mid-or-mail -5.0 result))
+        (t
+         (setq result (+ result 5.0))
+         (gnus-message
+          9 "`%s', rate `%s', result `%s'." mid-or-mail 5.0 result)))))
+    (gnus-message 8 "`%s': Final rate is `%s'." mid-or-mail result)
+    ;; Maybe we should make this a customizable alist: (condition . 'result)
+    (cond
+     ((symbolp result) result)
+     ;; Now convert number into proper results:
+     ((< result -10.0) 'mid)
+     ((> result  10.0) 'mail)
+     (t 'ask))))
+
+(defun gnus-button-handle-mid-or-mail (mid-or-mail)
+  (let* ((pref gnus-button-prefer-mid-or-mail) guessed
+        (url-mid (concat "news" ":" mid-or-mail))
+        (url-mailto (concat "mailto" ":" mid-or-mail)))
+    (gnus-message 9 "mid-or-mail=%s" mid-or-mail)
+    (when (fboundp pref)
+      (setq guessed
+           ;; get rid of surrounding angles...
+           (funcall pref
+                    (gnus-replace-in-string mid-or-mail "^<\\|>$" "")))
+      (if (or (eq 'mid guessed) (eq 'mail guessed))
+         (setq pref guessed)
+       (setq pref 'ask)))
+    (if (eq pref 'ask)
+       (save-window-excursion
+         (if (y-or-n-p (concat "Is <" mid-or-mail "> a mail address? "))
+             (setq pref 'mail)
+           (setq pref 'mid))))
+    (cond ((eq pref 'mid)
+          (gnus-message 8 "calling `gnus-button-handle-news' %s" url-mid)
+          (gnus-button-handle-news url-mid))
+         ((eq pref 'mail)
+          (gnus-message 8 "calling `gnus-url-mailto'  %s" url-mailto)
+          (gnus-url-mailto url-mailto))
+         (t (gnus-message 3 "Invalid string.")))))
+
+(defun gnus-button-handle-custom (url)
+  "Follow a Custom URL."
+  (customize-apropos (gnus-url-unhex-string url)))
+
+(defvar gnus-button-handle-describe-prefix "^\\(C-h\\|<?[Ff]1>?\\)")
+
+;; FIXME: Maybe we should merge some of the functions that do quite similar
+;; stuff?
+
+(defun gnus-button-handle-describe-function (url)
+  "Call `describe-function' when pushing the corresponding URL button."
+  (describe-function
+   (intern
+    (gnus-replace-in-string url gnus-button-handle-describe-prefix ""))))
+
+(defun gnus-button-handle-describe-variable (url)
+  "Call `describe-variable' when pushing the corresponding URL button."
+  (describe-variable
+   (intern
+    (gnus-replace-in-string url gnus-button-handle-describe-prefix ""))))
+
+(defun gnus-button-handle-symbol (url)
+"Display help on variable or function.
+Calls `describe-variable' or `describe-function'."
+  (let ((sym (intern url)))
+    (cond
+     ((fboundp sym) (describe-function sym))
+     ((boundp sym) (describe-variable sym))
+     (t (gnus-message 3 "`%s' is not a known function of variable." url)))))
+
+(defun gnus-button-handle-describe-key (url)
+  "Call `describe-key' when pushing the corresponding URL button."
+  (let* ((key-string
+         (gnus-replace-in-string url gnus-button-handle-describe-prefix ""))
+        (keys (ignore-errors (eval `(kbd ,key-string)))))
+    (if keys
+       (describe-key keys)
+      (gnus-message 3 "Invalid key sequence in button: %s" key-string))))
+
+(defun gnus-button-handle-apropos (url)
+  "Call `apropos' when pushing the corresponding URL button."
+  (apropos (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
+
+(defun gnus-button-handle-apropos-command (url)
+  "Call `apropos' when pushing the corresponding URL button."
+  (apropos-command
+   (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
+
+(defun gnus-button-handle-apropos-variable (url)
+  "Call `apropos' when pushing the corresponding URL button."
+  (funcall
+   (if (fboundp 'apropos-variable) 'apropos-variable 'apropos)
+   (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
+
+(defun gnus-button-handle-apropos-documentation (url)
+  "Call `apropos' when pushing the corresponding URL button."
+  (funcall
+   (if (fboundp 'apropos-documentation) 'apropos-documentation 'apropos)
+   (gnus-replace-in-string url gnus-button-handle-describe-prefix "")))
+
+(defun gnus-button-handle-library (url)
+  "Call `locate-library' when pushing the corresponding URL button."
+  (gnus-message 9 "url=`%s'" url)
+  (let* ((lib (locate-library url))
+        (file (gnus-replace-in-string (or lib "") "\.elc" ".el")))
+    (if (not lib)
+       (gnus-message 1 "Cannot locale library `%s'." url)
+      (find-file-read-only file))))
+
+(defun gnus-button-handle-ctan (url)
+  "Call `browse-url' when pushing a CTAN URL button."
+  (funcall
+   gnus-button-ctan-handler
+   (concat
+    gnus-ctan-url
+    (gnus-replace-in-string url gnus-button-handle-ctan-bogus-regexp ""))))
+
+(defcustom gnus-button-tex-level 5
+  "*Integer that says how many TeX-related buttons Gnus will show.
+The higher the number, the more buttons will appear and the more false
+positives are possible.  Note that you can set this variable local to
+specific groups.  Setting it higher in TeX groups is probably a good idea.
+See Info node `(gnus)Group Parameters' and the variable `gnus-parameters' on
+how to set variables in specific groups."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type 'integer)
+
+(defcustom gnus-button-man-level 5
+  "*Integer that says how many man-related buttons Gnus will show.
+The higher the number, the more buttons will appear and the more false
+positives are possible.  Note that you can set this variable local to
+specific groups.  Setting it higher in Unix groups is probably a good idea.
+See Info node `(gnus)Group Parameters' and the variable `gnus-parameters' on
+how to set variables in specific groups."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type 'integer)
+
+(defcustom gnus-button-emacs-level 5
+  "*Integer that says how many emacs-related buttons Gnus will show.
+The higher the number, the more buttons will appear and the more false
+positives are possible.  Note that you can set this variable local to
+specific groups.  Setting it higher in Emacs or Gnus related groups is
+probably a good idea.  See Info node `(gnus)Group Parameters' and the variable
+`gnus-parameters' on how to set variables in specific groups."
+  :group 'gnus-article-buttons
+  :link '(custom-manual "(gnus)Group Parameters")
+  :type 'integer)
+
+(defcustom gnus-button-message-level 5
+  "*Integer that says how many buttons for news or mail messages will appear.
+The higher the number, the more buttons will appear and the more false
+positives are possible."
+  ;; mail addresses, MIDs, URLs for news, ...
+  :group 'gnus-article-buttons
+  :type 'integer)
+
+(defcustom gnus-button-browse-level 5
+  "*Integer that says how many buttons for browsing will appear.
+The higher the number, the more buttons will appear and the more false
+positives are possible."
+  ;; stuff handled by `browse-url' or `gnus-button-embedded-url'
+  :group 'gnus-article-buttons
+  :type 'integer)
+
 (defcustom gnus-button-alist
-  `(("<\\(url: ?\\)?news:\\([^>\n\t ]*@[^>\n\t ]*\\)>" 0 t
-     gnus-button-message-id 2)
-    ("\\bnews:\\([^>\n\t ]*@[^>\n\t ]*\\)" 0 t gnus-button-message-id 1)
-    ("\\(\\b<\\(url: ?\\)?news:\\(//\\)?\\([^>\n\t ]*\\)>\\)" 1 t
-     gnus-button-fetch-group 4)
-    ("\\bnews:\\(//\\)?\\([^'\">\n\t ]+\\)" 0 t gnus-button-fetch-group 2)
-    ("\\bin\\( +article\\| +message\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2
-     t gnus-button-message-id 3)
-    ("\\(<URL: *\\)mailto: *\\([^> \n\t]+\\)>" 0 t gnus-url-mailto 2)
-    ("\\bmailto:\\([^ \n\t]+\\)" 0 t gnus-url-mailto 1)
-    ;; This is how URLs _should_ be embedded in text...
-    ("<URL: *\\([^>]*\\)>" 0 t gnus-button-embedded-url 1)
+  '(("<\\(url:[>\n\t ]*?\\)?\\(nntp\\|news\\):[>\n\t ]*\\([^>\n\t ]*@[^>\n\t ]*\\)>"
+     0 (>= gnus-button-message-level 0) gnus-button-handle-news 3)
+    ("\\b\\(nntp\\|news\\):\\([^>\n\t ]*@[^>)!;:,\n\t ]*\\)" 0 t
+     gnus-button-handle-news 2)
+    ("\\(\\b<\\(url:[>\n\t ]*\\)?\\(nntp\\|news\\):[>\n\t ]*\\(//\\)?\\([^>\n\t ]*\\)>\\)"
+     1 (>= gnus-button-message-level 0) gnus-button-fetch-group 5)
+    ("\\b\\(nntp\\|news\\):\\(//\\)?\\([^'\">\n\t ]+\\)"
+     0 (>= gnus-button-message-level 0) gnus-button-fetch-group 3)
+    ;; RFC 2392 (Don't allow `/' in domain part --> CID)
+    ("\\bmid:\\(//\\)?\\([^'\">\n\t ]+@[^'\">\n\t /]+\\)"
+     0 (>= gnus-button-message-level 0) gnus-button-message-id 2)
+    ("\\bin\\( +article\\| +message\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)"
+     2 (>= gnus-button-message-level 0) gnus-button-message-id 3)
+    ("\\(<URL: *\\)mailto: *\\([^> \n\t]+\\)>"
+     0 (>= gnus-button-message-level 0) gnus-url-mailto 2)
+    ;; RFC 2368 (The mailto URL scheme)
+    ("mailto:\\([-a-z.@_+0-9%=?&]+\\)"
+     0 (>= gnus-button-message-level 0) gnus-url-mailto 1)
+    ("\\bmailto:\\([^ \n\t]+\\)"
+     0 (>= gnus-button-message-level 0) gnus-url-mailto 1)
+    ;; CTAN
+    ((concat "\\bCTAN:[ \t\n]?[^>)!;:,'\n\t ]*\\("
+            gnus-button-ctan-directory-regexp
+            "[^][>)!;:,'\n\t ]+\\)")
+     0 (>= gnus-button-tex-level 1) gnus-button-handle-ctan 1)
+    ((concat "\\btex-archive/\\("
+            gnus-button-ctan-directory-regexp
+            "/[-_.a-z0-9/]+[-_./a-z0-9]+[/a-z0-9]\\)")
+     1 (>= gnus-button-tex-level 6) gnus-button-handle-ctan 1)
+    ((concat
+      "\\b\\("
+      gnus-button-ctan-directory-regexp
+      "/[-_.a-z0-9]+/[-_./a-z0-9]+[/a-z0-9]\\)")
+     1 (>= gnus-button-tex-level 8) gnus-button-handle-ctan 1)
+    ;; This is info (home-grown style) <info://foo/bar+baz>
+    ("\\binfo://\\([^'\">\n\t ]+\\)"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-info-url 1)
+    ;; Info GNOME style <info:foo#bar_baz>
+    ("\\binfo:\\([^('\n\t\r \"><][^'\n\t\r \"><]*\\)"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-info-url-gnome 1)
+    ;; Info KDE style <info:(foo)bar baz>
+    ("<\\(info:\\(([^)]+)[^>\n\r]*\\)\\)>"
+     1 (>= gnus-button-emacs-level 1) gnus-button-handle-info-url-kde 2)
+    ("\\((Info-goto-node\\|(info\\)[ \t\n]*\\(\"[^\"]*\"\\))" 0
+     (>= gnus-button-emacs-level 1) gnus-button-handle-info-url 2)
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+i[ \t\n]+d?[ \t\n]?m[ \t\n]+\\([^ ]+ ?[^ ]+\\)[ \t\n]+RET"
+     ;; Info links like `C-h i d m CC Mode RET'
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-info-keystrokes 2)
+    ;; This is custom
+    ("\\bcustom:\\(//\\)?\\([^'\">\n\t ]+\\)"
+     0 (>= gnus-button-emacs-level 5) gnus-button-handle-custom 2)
+    ("M-x[ \t\n]customize-[^ ]+[ \t\n]RET[ \t\n]\\([^ ]+\\)[ \t\n]RET" 0
+     (>= gnus-button-emacs-level 1) gnus-button-handle-custom 1)
+    ;; Emacs help commands
+    ("M-x[ \t\n]+apropos[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     ;; regexp doesn't match arguments containing ` '.
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos 1)
+    ("M-x[ \t\n]+apropos-command[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-command 1)
+    ("M-x[ \t\n]+apropos-variable[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-variable 1)
+    ("M-x[ \t\n]+apropos-documentation[ \t\n]+RET[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-apropos-documentation 1)
+    ;; The following entries may lead to many false positives so don't enable
+    ;; them by default (use a high button level):
+    ("/\\([a-z][-a-z0-9]+\\.el\\)\\>"
+     1 (>= gnus-button-emacs-level 8) gnus-button-handle-library 1)
+    ("`\\([a-z][-a-z0-9]+\\.el\\)'"
+     1 (>= gnus-button-emacs-level 8) gnus-button-handle-library 1)
+    ("`\\([a-z][a-z0-9]+-[a-z]+-[-a-z]+\\|\\(gnus\\|message\\)-[-a-z]+\\)'"
+     0 (>= gnus-button-emacs-level 8) gnus-button-handle-symbol 1)
+    ("`\\([a-z][a-z0-9]+-[a-z]+\\)'"
+     0 (>= gnus-button-emacs-level 9) gnus-button-handle-symbol 1)
+    ("(setq[ \t\n]+\\([a-z][a-z0-9]+-[-a-z0-9]+\\)[ \t\n]+.+)"
+     1 (>= gnus-button-emacs-level 7) gnus-button-handle-describe-variable 1)
+    ("\\bM-x[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     1 (>= gnus-button-emacs-level 7) gnus-button-handle-describe-function 1)
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+f[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-function 2)
+    ("\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+v[ \t\n]+\\([^ \t\n]+\\)[ \t\n]+RET"
+     0 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-variable 2)
+    ("`\\(\\b\\(C-h\\|<?[Ff]1>?\\)[ \t\n]+k[ \t\n]+\\([^']+\\)\\)'"
+     ;; Unlike the other regexps we really have to require quoting
+     ;; here to determine where it ends.
+     1 (>= gnus-button-emacs-level 1) gnus-button-handle-describe-key 3)
+    ;; This is how URLs _should_ be embedded in text (RFC 1738, RFC 2396)...
+    ("<URL: *\\([^<>]*\\)>"
+     1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1)
+    ;; RFC 2396 (2.4.3., delims) ...
+    ("\"URL: *\\([^\"]*\\)\""
+     1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1)
+    ;; RFC 2396 (2.4.3., delims) ...
+    ("\"URL: *\\([^\"]*\\)\""
+     1 (>= gnus-button-browse-level 0) gnus-button-embedded-url 1)
     ;; Raw URLs.
-    (,gnus-button-url-regexp 0 t gnus-button-url 0))
+    (gnus-button-url-regexp
+     0 (>= gnus-button-browse-level 0) browse-url 0)
+    ;; man pages
+    ("\\b\\([a-z][a-z]+\\)([1-9])\\W"
+     0 (and (>= gnus-button-man-level 1) (< gnus-button-man-level 3))
+     gnus-button-handle-man 1)
+    ;; more man pages: resolv.conf(5), iso_8859-1(7), xterm(1x)
+    ("\\b\\([a-z][-_.a-z0-9]+\\)([1-9])\\W"
+     0 (and (>= gnus-button-man-level 3) (< gnus-button-man-level 5))
+     gnus-button-handle-man 1)
+    ;; even more: Apache::PerlRun(3pm), PDL::IO::FastRaw(3pm),
+    ;; SoWWWAnchor(3iv), XSelectInput(3X11), X(1), X(7)
+    ("\\b\\([a-z][-+_.:a-z0-9]+\\)([1-9][X1a-z]*)\\W\\|\\b\\(X\\)([1-9])\\W"
+     0 (>= gnus-button-man-level 5) gnus-button-handle-man 1)
+    ;; MID or mail: To avoid too many false positives we don't try to catch
+    ;; all kind of allowed MIDs or mail addresses.  Domain part must contain
+    ;; at least one dot.  TLD must contain two or three chars or be a know TLD
+    ;; (info|name|...).  Put this entry near the _end_ of `gnus-button-alist'
+    ;; so that non-ambiguous entries (see above) match first.
+    (gnus-button-mid-or-mail-regexp
+     0 (>= gnus-button-message-level 5) gnus-button-handle-mid-or-mail 1))
   "*Alist of regexps matching buttons in article bodies.
 
 Each entry has the form (REGEXP BUTTON FORM CALLBACK PAR...), where
-REGEXP: is the string matching text around the button,
+REGEXP: is the string (case insensitive) matching text around the button (can
+also be Lisp expression evaluating to a string),
 BUTTON: is the number of the regexp grouping actually matching the button,
-FORM: is a lisp expression which must eval to true for the button to
+FORM: is a Lisp expression which must eval to true for the button to
 be added,
 CALLBACK: is the function to call when the user push this button, and each
 PAR: is a number of a regexp grouping whose text will be passed to CALLBACK.
@@ -2734,7 +6687,7 @@ PAR: is a number of a regexp grouping whose text will be passed to CALLBACK.
 CALLBACK can also be a variable, in that case the value of that
 variable it the real callback function."
   :group 'gnus-article-buttons
-  :type '(repeat (list regexp
+  :type '(repeat (list (choice regexp variable sexp)
                       (integer :tag "Button")
                       (sexp :tag "Form")
                       (function :tag "Callback")
@@ -2743,16 +6696,22 @@ variable it the real callback function."
                               (integer :tag "Regexp group")))))
 
 (defcustom gnus-header-button-alist
-  `(("^\\(References\\|Message-I[Dd]\\):" "<[^>]+>"
-     0 t gnus-button-message-id 0)
-    ("^\\(From\\|Reply-To\\):" ": *\\(.+\\)$" 1 t gnus-button-reply 1)
+  '(("^\\(References\\|Message-I[Dd]\\|^In-Reply-To\\):" "<[^<>]+>"
+     0 (>= gnus-button-message-level 0) gnus-button-message-id 0)
+    ("^\\(From\\|Reply-To\\):" ": *\\(.+\\)$"
+     1 (>= gnus-button-message-level 0) gnus-button-reply 1)
     ("^\\(Cc\\|To\\):" "[^ \t\n<>,()\"]+@[^ \t\n<>,()\"]+"
-     0 t gnus-button-mailto 0)
-    ("^X-[Uu][Rr][Ll]:" ,gnus-button-url-regexp 0 t gnus-button-url 0)
-    ("^Subject:" ,gnus-button-url-regexp 0 t gnus-button-url 0)
-    ("^[^:]+:" ,gnus-button-url-regexp 0 t gnus-button-url 0)
-    ("^[^:]+:" "\\(<\\(url: \\)?news:\\([^>\n ]*\\)>\\)" 1 t
-     gnus-button-message-id 3))
+     0 (>= gnus-button-message-level 0) gnus-button-mailto 0)
+    ("^X-[Uu][Rr][Ll]:" gnus-button-url-regexp
+     0 (>= gnus-button-browse-level 0) browse-url 0)
+    ("^Subject:" gnus-button-url-regexp
+     0 (>= gnus-button-browse-level 0) browse-url 0)
+    ("^[^:]+:" gnus-button-url-regexp
+     0 (>= gnus-button-browse-level 0) browse-url 0)
+    ("^[^:]+:" "\\bmailto:\\([-a-z.@_+0-9%=?&]+\\)"
+     0 (>= gnus-button-message-level 0) gnus-url-mailto 1)
+    ("^[^:]+:" "\\(<\\(url: \\)?\\(nntp\\|news\\):\\([^>\n ]*\\)>\\)"
+     1 (>= gnus-button-message-level 0) gnus-button-message-id 4))
   "*Alist of headers and regexps to match buttons in article heads.
 
 This alist is very similar to `gnus-button-alist', except that each
@@ -2765,7 +6724,7 @@ HEADER is a regexp to match a header.  For a fuller explanation, see
   :group 'gnus-article-buttons
   :group 'gnus-article-headers
   :type '(repeat (list (regexp :tag "Header")
-                      regexp
+                      (choice regexp variable)
                       (integer :tag "Button")
                       (sexp :tag "Form")
                       (function :tag "Callback")
@@ -2789,8 +6748,9 @@ call it with the value of the `gnus-data' text property."
   (interactive "e")
   (set-buffer (window-buffer (posn-window (event-start event))))
   (let* ((pos (posn-point (event-start event)))
-         (data (get-text-property pos 'gnus-data))
+        (data (get-text-property pos 'gnus-data))
         (fun (get-text-property pos 'gnus-callback)))
+    (goto-char pos)
     (when fun
       (funcall fun data))))
 
@@ -2799,8 +6759,8 @@ call it with the value of the `gnus-data' text property."
 If the text at point has a `gnus-callback' property,
 call it with the value of the `gnus-data' text property."
   (interactive)
-  (let* ((data (get-text-property (point) 'gnus-data))
-        (fun (get-text-property (point) 'gnus-callback)))
+  (let ((data (get-text-property (point) 'gnus-data))
+       (fun (get-text-property (point) 'gnus-callback)))
     (when fun
       (funcall fun data))))
 
@@ -2872,7 +6832,7 @@ do the highlighting.  See the documentation for those functions."
            (case-fold-search t)
            (inhibit-point-motion-hooks t)
            entry regexp header-face field-face from hpoints fpoints)
-       (message-narrow-to-head)
+       (article-narrow-to-head)
        (while (setq entry (pop alist))
          (goto-char (point-min))
          (setq regexp (concat "^\\("
@@ -2905,21 +6865,28 @@ do the highlighting.  See the documentation for those functions."
 It does this by highlighting everything after
 `gnus-signature-separator' using `gnus-signature-face'."
   (interactive)
+  (when gnus-signature-face
+    (save-excursion
+      (set-buffer gnus-article-buffer)
+      (let ((buffer-read-only nil)
+           (inhibit-point-motion-hooks t))
+       (save-restriction
+         (when (gnus-article-narrow-to-signature)
+           (gnus-overlay-put (gnus-make-overlay (point-min) (point-max))
+                             'face gnus-signature-face)))))))
+
+(defun gnus-article-buttonize-signature ()
+  "Add button to the signature."
+  (interactive)
   (save-excursion
     (set-buffer gnus-article-buffer)
     (let ((buffer-read-only nil)
          (inhibit-point-motion-hooks t))
-      (save-restriction
-       (when (and gnus-signature-face
-                  (gnus-article-narrow-to-signature))
-         (gnus-overlay-put (gnus-make-overlay (point-min) (point-max))
-                           'face gnus-signature-face)
-         (widen)
-         (gnus-article-search-signature)
-         (let ((start (match-beginning 0))
-               (end (set-marker (make-marker) (1+ (match-end 0)))))
-           (gnus-article-add-button start (1- end) 'gnus-signature-toggle
-                                    end)))))))
+      (when (gnus-article-search-signature)
+       (gnus-article-add-button (match-beginning 0) (match-end 0)
+                                'gnus-signature-toggle
+                                (set-marker (make-marker)
+                                            (1+ (match-end 0))))))))
 
 (defun gnus-button-in-region-p (b e prop)
   "Say whether PROP exists in the region."
@@ -2938,21 +6905,22 @@ specified by `gnus-button-alist'."
          (alist gnus-button-alist)
          beg entry regexp)
       ;; Remove all old markers.
-      (let (marker entry)
+      (let (marker entry new-list)
        (while (setq marker (pop gnus-button-marker-list))
-         (goto-char marker)
-         (when (setq entry (gnus-button-entry))
-           (put-text-property (match-beginning (nth 1 entry))
-                              (match-end (nth 1 entry))
-                              'gnus-callback nil))
-         (set-marker marker nil)))
+         (if (or (< marker (point-min)) (>= marker (point-max)))
+             (push marker new-list)
+           (goto-char marker)
+           (when (setq entry (gnus-button-entry))
+             (put-text-property (match-beginning (nth 1 entry))
+                                (match-end (nth 1 entry))
+                                'gnus-callback nil))
+           (set-marker marker nil)))
+       (setq gnus-button-marker-list new-list))
       ;; We skip the headers.
-      (goto-char (point-min))
-      (unless (search-forward "\n\n" nil t)
-       (goto-char (point-max)))
+      (article-goto-body)
       (setq beg (point))
       (while (setq entry (pop alist))
-       (setq regexp (car entry))
+       (setq regexp (eval (car entry)))
        (goto-char beg)
        (while (re-search-forward regexp nil t)
          (let* ((start (and entry (match-beginning (nth 1 entry))))
@@ -2975,38 +6943,38 @@ specified by `gnus-button-alist'."
   (interactive)
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (let ((buffer-read-only nil)
-         (inhibit-point-motion-hooks t)
-         (case-fold-search t)
-         (alist gnus-header-button-alist)
-         entry beg end)
-      (nnheader-narrow-to-headers)
-      (while alist
-       ;; Each alist entry.
-       (setq entry (car alist)
-             alist (cdr alist))
-       (goto-char (point-min))
-       (while (re-search-forward (car entry) nil t)
-         ;; Each header matching the entry.
-         (setq beg (match-beginning 0))
-         (setq end (or (and (re-search-forward "^[^ \t]" nil t)
-                            (match-beginning 0))
-                       (point-max)))
-         (goto-char beg)
-         (while (re-search-forward (nth 1 entry) end t)
-           ;; Each match within a header.
-           (let* ((entry (cdr entry))
-                  (start (match-beginning (nth 1 entry)))
-                  (end (match-end (nth 1 entry)))
-                  (form (nth 2 entry)))
-             (goto-char (match-end 0))
-             (when (eval form)
-               (gnus-article-add-button
-                start end (nth 3 entry)
-                (buffer-substring (match-beginning (nth 4 entry))
-                                  (match-end (nth 4 entry)))))))
-         (goto-char end))))
-    (widen)))
+    (save-restriction
+      (let ((buffer-read-only nil)
+           (inhibit-point-motion-hooks t)
+           (case-fold-search t)
+           (alist gnus-header-button-alist)
+           entry beg end)
+       (article-narrow-to-head)
+       (while alist
+         ;; Each alist entry.
+         (setq entry (car alist)
+               alist (cdr alist))
+         (goto-char (point-min))
+         (while (re-search-forward (car entry) nil t)
+           ;; Each header matching the entry.
+           (setq beg (match-beginning 0))
+           (setq end (or (and (re-search-forward "^[^ \t]" nil t)
+                              (match-beginning 0))
+                         (point-max)))
+           (goto-char beg)
+           (while (re-search-forward (eval (nth 1 entry)) end t)
+             ;; Each match within a header.
+             (let* ((entry (cdr entry))
+                    (start (match-beginning (nth 1 entry)))
+                    (end (match-end (nth 1 entry)))
+                    (form (nth 2 entry)))
+               (goto-char (match-end 0))
+               (when (eval form)
+                 (gnus-article-add-button
+                  start end (nth 3 entry)
+                  (buffer-substring (match-beginning (nth 4 entry))
+                                    (match-end (nth 4 entry)))))))
+           (goto-char end)))))))
 
 ;;; External functions:
 
@@ -3020,7 +6988,11 @@ specified by `gnus-button-alist'."
    (nconc (and gnus-article-mouse-face
               (list gnus-mouse-face-prop gnus-article-mouse-face))
          (list 'gnus-callback fun)
-         (and data (list 'gnus-data data)))))
+         (and data (list 'gnus-data data))))
+  (widget-convert-button 'link from to :action 'gnus-widget-press-button
+                        ;; Quote `:button-keymap' for Mule 2.3
+                        ;; but it won't work.
+                        ':button-keymap gnus-widget-button-keymap))
 
 ;;; Internal functions:
 
@@ -3033,10 +7005,23 @@ specified by `gnus-button-alist'."
   (save-excursion
     (set-buffer gnus-article-buffer)
     (let ((buffer-read-only nil)
-         (inhibit-point-motion-hooks t))
-      (if (get-text-property end 'invisible)
-         (gnus-article-unhide-text end (point-max))
-       (gnus-article-hide-text end (point-max) gnus-hidden-properties)))))
+         (inhibit-point-motion-hooks t)
+         (limit (next-single-property-change end 'mime-view-entity
+                                             nil (point-max))))
+      (if (text-property-any end limit 'article-type 'signature)
+         (progn
+           (gnus-delete-wash-type 'signature)
+           (gnus-remove-text-properties-when
+            'article-type 'signature end limit
+            (cons 'article-type (cons 'signature
+                                      gnus-hidden-properties))))
+       (gnus-add-wash-type 'signature)
+       (gnus-add-text-properties-when
+        'article-type nil end limit
+        (cons 'article-type (cons 'signature
+                                  gnus-hidden-properties)))))
+    (let ((gnus-article-mime-handle-alist-1 gnus-article-mime-handle-alist))
+      (gnus-set-mode-line 'article))))
 
 (defun gnus-button-entry ()
   ;; Return the first entry in `gnus-button-alist' matching this place.
@@ -3044,7 +7029,7 @@ specified by `gnus-button-alist'."
        (entry nil))
     (while alist
       (setq entry (pop alist))
-      (if (looking-at (car entry))
+      (if (looking-at (eval (car entry)))
          (setq alist nil)
        (setq entry nil)))
     entry))
@@ -3052,7 +7037,6 @@ specified by `gnus-button-alist'."
 (defun gnus-button-push (marker)
   ;; Push button starting at MARKER.
   (save-excursion
-    (set-buffer gnus-article-buffer)
     (goto-char marker)
     (let* ((entry (gnus-button-entry))
           (inhibit-point-motion-hooks t)
@@ -3073,6 +7057,90 @@ specified by `gnus-button-alist'."
        (gnus-message 1 "You must define `%S' to use this button"
                      (cons fun args)))))))
 
+(defun gnus-parse-news-url (url)
+  (let (scheme server group message-id articles)
+    (with-temp-buffer
+      (insert url)
+      (goto-char (point-min))
+      (when (looking-at "\\([A-Za-z]+\\):")
+       (setq scheme (match-string 1))
+       (goto-char (match-end 0)))
+      (when (looking-at "//\\([^/]+\\)/")
+       (setq server (match-string 1))
+       (goto-char (match-end 0)))
+
+      (cond
+       ((looking-at "\\(.*@.*\\)")
+       (setq message-id (match-string 1)))
+       ((looking-at "\\([^/]+\\)/\\([-0-9]+\\)")
+       (setq group (match-string 1)
+             articles (split-string (match-string 2) "-")))
+       ((looking-at "\\([^/]+\\)/?")
+       (setq group (match-string 1)))
+       (t
+       (error "Unknown news URL syntax"))))
+    (list scheme server group message-id articles)))
+
+(defun gnus-button-handle-news (url)
+  "Fetch a news URL."
+  (destructuring-bind (scheme server group message-id articles)
+      (gnus-parse-news-url url)
+    (cond
+     (message-id
+      (save-excursion
+       (set-buffer gnus-summary-buffer)
+       (if server
+           (let ((gnus-refer-article-method (list (list 'nntp server))))
+             (gnus-summary-refer-article message-id))
+         (gnus-summary-refer-article message-id))))
+     (group
+      (gnus-button-fetch-group url)))))
+
+(defun gnus-button-handle-man (url)
+  "Fetch a man page."
+  (funcall gnus-button-man-handler url))
+
+(defun gnus-button-handle-info-url (url)
+  "Fetch an info URL."
+  (setq url (mm-subst-char-in-string ?+ ?\  url))
+  (cond
+   ((string-match "^\\([^:/]+\\)?/\\(.*\\)" url)
+    (gnus-info-find-node
+     (concat "(" (or (gnus-url-unhex-string (match-string 1 url))
+                    "Gnus")
+            ")" (gnus-url-unhex-string (match-string 2 url)))))
+   ((string-match "([^)\"]+)[^\"]+" url)
+    (setq url
+         (gnus-replace-in-string
+          (gnus-replace-in-string url "[\n\t ]+" " ") "\"" ""))
+    (gnus-info-find-node url))
+   (t (error "Can't parse %s" url))))
+
+(defun gnus-button-handle-info-url-gnome (url)
+  "Fetch GNOME style info URL."
+  (setq url (mm-subst-char-in-string ?_ ?\  url))
+  (if (string-match "\\([^#]+\\)#?\\(.*\\)" url)
+      (gnus-info-find-node
+       (concat "("
+              (gnus-url-unhex-string 
+                (match-string 1 url))
+              ")"
+              (or (gnus-url-unhex-string 
+                   (match-string 2 url))
+                  "Top")))
+    (error "Can't parse %s" url)))
+
+(defun gnus-button-handle-info-url-kde (url)
+  "Fetch KDE style info URL."
+  (gnus-info-find-node (gnus-url-unhex-string url)))
+
+(defun gnus-button-handle-info-keystrokes (url)
+  "Call `info' when pushing the corresponding URL button."
+  ;; For links like `C-h i d m gnus RET', `C-h i d m CC Mode RET'.
+  (info)
+  (Info-directory)
+  (Info-menu url))
+
 (defun gnus-button-message-id (message-id)
   "Fetch MESSAGE-ID."
   (save-excursion
@@ -3084,8 +7152,10 @@ specified by `gnus-button-alist'."
   (if (not (string-match "[:/]" address))
       ;; This is just a simple group url.
       (gnus-group-read-ephemeral-group address gnus-select-method)
-    (if (not (string-match "^\\([^:/]+\\)\\(:\\([^/]+\\)/\\)?\\(.*\\)$"
-                          address))
+    (if (not
+        (string-match
+         "^\\([^:/]+\\)\\(:\\([^/]+\\)\\)?/\\([^/]+\\)\\(/\\([0-9]+\\)\\)?"
+         address))
        (error "Can't parse %s" address)
       (gnus-group-read-ephemeral-group
        (match-string 4 address)
@@ -3093,166 +7163,141 @@ specified by `gnus-button-alist'."
              (nntp-address ,(match-string 1 address))
              (nntp-port-number ,(if (match-end 3)
                                     (match-string 3 address)
-                                  "nntp")))))))
-
-(defun gnus-split-string (string pattern)
-  "Return a list of substrings of STRING which are separated by PATTERN."
-  (let (parts (start 0))
-    (while (string-match pattern string start)
-      (setq parts (cons (substring string start (match-beginning 0)) parts)
-           start (match-end 0)))
-    (nreverse (cons (substring string start) parts))))
+                                  "nntp")))
+       nil nil nil
+       (and (match-end 6) (list (string-to-int (match-string 6 address))))))))
 
 (defun gnus-url-parse-query-string (query &optional downcase)
   (let (retval pairs cur key val)
-    (setq pairs (gnus-split-string query "&"))
+    (setq pairs (split-string query "&"))
     (while pairs
       (setq cur (car pairs)
-            pairs (cdr pairs))
+           pairs (cdr pairs))
       (if (not (string-match "=" cur))
-          nil                           ; Grace
-        (setq key (gnus-url-unhex-string (substring cur 0 (match-beginning 0)))
-              val (gnus-url-unhex-string (substring cur (match-end 0) nil)))
-        (if downcase
-            (setq key (downcase key)))
-        (setq cur (assoc key retval))
-        (if cur
-            (setcdr cur (cons val (cdr cur)))
-          (setq retval (cons (list key val) retval)))))
+         nil                           ; Grace
+       (setq key (gnus-url-unhex-string (substring cur 0 (match-beginning 0)))
+             val (gnus-url-unhex-string (substring cur (match-end 0) nil) t))
+       (if downcase
+           (setq key (downcase key)))
+       (setq cur (assoc key retval))
+       (if cur
+           (setcdr cur (cons val (cdr cur)))
+         (setq retval (cons (list key val) retval)))))
     retval))
 
-(defun gnus-url-unhex (x)
-  (if (> x ?9)
-      (if (>= x ?a)
-          (+ 10 (- x ?a))
-        (+ 10 (- x ?A)))
-    (- x ?0)))
-
-(defun gnus-url-unhex-string (str &optional allow-newlines)
-  "Remove %XXX embedded spaces, etc in a url.
-If optional second argument ALLOW-NEWLINES is non-nil, then allow the
-decoding of carriage returns and line feeds in the string, which is normally
-forbidden in URL encoding."
-  (setq str (or str ""))
-  (let ((tmp "")
-        (case-fold-search t))
-    (while (string-match "%[0-9a-f][0-9a-f]" str)
-      (let* ((start (match-beginning 0))
-             (ch1 (gnus-url-unhex (elt str (+ start 1))))
-             (code (+ (* 16 ch1)
-                      (gnus-url-unhex (elt str (+ start 2))))))
-        (setq tmp (concat
-                   tmp (substring str 0 start)
-                   (cond
-                    (allow-newlines
-                     (char-to-string code))
-                    ((or (= code ?\n) (= code ?\r))
-                     " ")
-                    (t (char-to-string code))))
-              str (substring str (match-end 0)))))
-    (setq tmp (concat tmp str))
-    tmp))
-
 (defun gnus-url-mailto (url)
   ;; Send mail to someone
   (when (string-match "mailto:/*\\(.*\\)" url)
     (setq url (substring url (match-beginning 1) nil)))
-  (let (to args source-url subject func)
-    (if (string-match (regexp-quote "?") url)
-        (setq to (gnus-url-unhex-string (substring url 0 (match-beginning 0)))
-              args (gnus-url-parse-query-string
-                    (substring url (match-end 0) nil) t))
-      (setq to (gnus-url-unhex-string url)))
-    (setq args (cons (list "to" to) args)
-          subject (cdr-safe (assoc "subject" args)))
-    (message-mail)
+  (let (to args subject func)
+    (setq args (gnus-url-parse-query-string
+               (if (string-match "^\\?" url)
+                   (substring url 1)
+                 (if (string-match "^\\([^?]+\\)\\?\\(.*\\)" url)
+                     (concat "to=" (match-string 1 url) "&"
+                             (match-string 2 url))
+                   (concat "to=" url)))
+               t)
+         subject (cdr-safe (assoc "subject" args)))
+    (gnus-msg-mail)
     (while args
       (setq func (intern-soft (concat "message-goto-" (downcase (caar args)))))
       (if (fboundp func)
-          (funcall func)
-        (message-position-on-field (caar args)))
-      (insert (mapconcat 'identity (cdar args) ", "))
+         (funcall func)
+       (message-position-on-field (caar args)))
+      (insert (gnus-replace-in-string
+              (mapconcat 'identity (reverse (cdar args)) ", ")
+              "\r\n" "\n" t))
       (setq args (cdr args)))
     (if subject
-        (message-goto-body)
+       (message-goto-body)
       (message-goto-subject))))
 
-(defun gnus-button-mailto (address)
-  ;; Mail to ADDRESS.
-  (set-buffer (gnus-copy-article-buffer))
-  (message-reply address))
-
-(defun gnus-button-reply (address)
-  ;; Reply to ADDRESS.
-  (message-reply address))
-
-(defun gnus-button-url (address)
-  "Browse ADDRESS."
-  ;; In Emacs 20, `browse-url-browser-function' may be an alist.
-  (if (listp browse-url-browser-function)
-      (browse-url address)
-    (funcall browse-url-browser-function address)))
-
 (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))))
+  "Activate ADDRESS with `browse-url'."
+  (browse-url (gnus-strip-whitespace address)))
 
 ;;; Next/prev buttons in the article buffer.
 
 (defvar gnus-next-page-line-format "%{%(Next page...%)%}\n")
 (defvar gnus-prev-page-line-format "%{%(Previous page...%)%}\n")
 
-(defvar gnus-prev-page-map nil)
-(unless gnus-prev-page-map
-  (setq gnus-prev-page-map (make-sparse-keymap))
-  (define-key gnus-prev-page-map gnus-mouse-2 'gnus-button-prev-page)
-  (define-key gnus-prev-page-map "\r" 'gnus-button-prev-page))
+(defvar gnus-prev-page-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= emacs-major-version 21)
+      ;; XEmacs doesn't care.
+      (set-keymap-parent map gnus-article-mode-map))
+    (define-key map gnus-mouse-2 'gnus-button-prev-page)
+    (define-key map "\r" 'gnus-button-prev-page)
+    map))
 
 (defun gnus-insert-prev-page-button ()
-  (let ((buffer-read-only nil))
+  (let ((b (point))
+       (buffer-read-only nil)
+       (situation (get-text-property (point-min) 'mime-view-situation)))
     (gnus-eval-format
      gnus-prev-page-line-format nil
-     `(gnus-prev t local-map ,gnus-prev-page-map
-                gnus-callback gnus-article-button-prev-page))))
-
-(defvar gnus-next-page-map nil)
-(unless gnus-next-page-map
-  (setq gnus-next-page-map (make-keymap))
-  (suppress-keymap gnus-prev-page-map)
-  (define-key gnus-next-page-map gnus-mouse-2 'gnus-button-next-page)
-  (define-key gnus-next-page-map "\r" 'gnus-button-next-page))
-
-(defun gnus-button-next-page ()
+     `(,@(gnus-local-map-property gnus-prev-page-map)
+        gnus-prev t
+        gnus-callback gnus-article-button-prev-page
+        article-type annotation
+        mime-view-situation ,situation))
+    (widget-convert-button
+     'link b (if (bolp)
+                ;; Exclude a newline.
+                (1- (point))
+              (point))
+     :action 'gnus-button-prev-page
+     :button-keymap gnus-prev-page-map)))
+
+(defvar gnus-next-page-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= emacs-major-version 21)
+      ;; XEmacs doesn't care.
+      (set-keymap-parent map gnus-article-mode-map))
+    (define-key map gnus-mouse-2 'gnus-button-next-page)
+    (define-key map "\r" 'gnus-button-next-page)
+    map))
+
+(defun gnus-button-next-page (&optional args more-args)
   "Go to the next page."
   (interactive)
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
     (select-window win)))
 
-(defun gnus-button-prev-page ()
+(defun gnus-button-prev-page (&optional args more-args)
   "Go to the prev page."
   (interactive)
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
     (select-window win)))
 
 (defun gnus-insert-next-page-button ()
-  (let ((buffer-read-only nil))
+  (let ((b (point))
+       (buffer-read-only nil)
+       (situation (get-text-property (point-min) 'mime-view-situation)))
     (gnus-eval-format gnus-next-page-line-format nil
-                     `(gnus-next t local-map ,gnus-next-page-map
-                                 gnus-callback
-                                 gnus-article-button-next-page))))
+                     `(,@(gnus-local-map-property gnus-next-page-map)
+                         gnus-next t
+                         gnus-callback gnus-article-button-next-page
+                         article-type annotation
+                         mime-view-situation ,situation))
+    (widget-convert-button
+     'link b (if (bolp)
+                ;; Exclude a newline.
+                (1- (point))
+              (point))
+     :action 'gnus-button-next-page
+     :button-keymap gnus-next-page-map)))
 
 (defun gnus-article-button-next-page (arg)
   "Go to the next page."
   (interactive "P")
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-next-page)
     (select-window win)))
 
@@ -3260,10 +7305,430 @@ forbidden in URL encoding."
   "Go to the prev page."
   (interactive "P")
   (let ((win (selected-window)))
-    (select-window (get-buffer-window gnus-article-buffer t))
+    (select-window (gnus-get-buffer-window gnus-article-buffer t))
     (gnus-article-prev-page)
     (select-window win)))
 
+(defvar gnus-decode-header-methods
+  '(mail-decode-encoded-word-region)
+  "List of methods used to decode headers.
+
+This variable is a list of FUNCTION or (REGEXP . FUNCTION).  If item
+is FUNCTION, FUNCTION will be apply to all newsgroups.  If item is a
+\(REGEXP . FUNCTION), FUNCTION will be only apply to the newsgroups
+whose names match REGEXP.
+
+For example:
+\((\"chinese\" . gnus-decode-encoded-word-region-by-guess)
+ mail-decode-encoded-word-region
+ (\"chinese\" . rfc1843-decode-region))
+")
+
+(defvar gnus-decode-header-methods-cache nil)
+
+(defun gnus-multi-decode-header (start end)
+  "Apply the functions from `gnus-encoded-word-methods' that match."
+  (unless (and gnus-decode-header-methods-cache
+              (eq gnus-newsgroup-name
+                  (car gnus-decode-header-methods-cache)))
+    (setq gnus-decode-header-methods-cache (list gnus-newsgroup-name))
+    (mapcar (lambda (x)
+             (if (symbolp x)
+                 (nconc gnus-decode-header-methods-cache (list x))
+               (if (and gnus-newsgroup-name
+                        (string-match (car x) gnus-newsgroup-name))
+                   (nconc gnus-decode-header-methods-cache
+                          (list (cdr x))))))
+           gnus-decode-header-methods))
+  (let ((xlist gnus-decode-header-methods-cache))
+    (pop xlist)
+    (save-restriction
+      (narrow-to-region start end)
+      (while xlist
+       (funcall (pop xlist) (point-min) (point-max))))))
+
+;;;
+;;; Treatment top-level handling.
+;;;
+
+(defun gnus-treat-article (condition &optional part-number total-parts type)
+  (let ((length (- (point-max) (point-min)))
+       (alist gnus-treatment-function-alist)
+       (article-goto-body-goes-to-point-min-p t)
+       (treated-type
+        (or (not type)
+            (catch 'found
+              (let ((list gnus-article-treat-types))
+                (while list
+                  (when (string-match (pop list) type)
+                    (throw 'found t)))))))
+       (highlightp (gnus-visual-p 'article-highlight 'highlight))
+       (entity (static-unless (featurep 'xemacs)
+                 (when (eq 'head condition)
+                   (get-text-property (point-min) 'mime-view-entity))))
+       val elem buttonized)
+    (gnus-run-hooks 'gnus-part-display-hook)
+    (unless gnus-inhibit-treatment
+      (dolist (elem alist)
+       (setq val
+             (save-excursion
+               (when (gnus-buffer-live-p gnus-summary-buffer)
+                 (set-buffer gnus-summary-buffer))
+               (symbol-value (car elem))))
+       (when (and (or (consp val)
+                      treated-type)
+                  (gnus-treat-predicate val)
+                  (or (not (get (car elem) 'highlight))
+                      highlightp))
+         (when (and (not buttonized)
+                    (memq (car elem)
+                          '(gnus-treat-hide-signature
+                            gnus-treat-highlight-signature)))
+           (gnus-article-buttonize-signature)
+           (setq buttonized t))
+         (save-restriction
+           (funcall (cadr elem)))))
+      ;; FSF Emacsen does not inherit the existing text properties
+      ;; in the new text, so we should do it for `mime-view-entity'.
+      (static-unless (featurep 'xemacs)
+       (when entity
+         (put-text-property (point-min) (point-max)
+                            'mime-view-entity entity))))))
+
+;; Dynamic variables.
+(eval-when-compile
+  (defvar part-number)
+  (defvar total-parts)
+  (defvar type)
+  (defvar condition)
+  (defvar length))
+
+(defun gnus-treat-predicate (val)
+  (cond
+   ((null val)
+    nil)
+   ((and (listp val)
+        (stringp (car val)))
+    (apply 'gnus-or (mapcar `(lambda (s)
+                              (string-match s ,(or gnus-newsgroup-name "")))
+                           val)))
+   ((listp val)
+    (let ((pred (pop val)))
+      (cond
+       ((eq pred 'or)
+       (apply 'gnus-or (mapcar 'gnus-treat-predicate val)))
+       ((eq pred 'and)
+       (apply 'gnus-and (mapcar 'gnus-treat-predicate val)))
+       ((eq pred 'not)
+       (not (gnus-treat-predicate (car val))))
+       ((eq pred 'typep)
+       (equal (car val) type))
+       (t
+       (error "%S is not a valid predicate" pred)))))
+   ((eq val 'mime)
+    gnus-show-mime)
+   (condition
+    (eq condition val))
+   ((eq val t)
+    t)
+   ((eq val 'head)
+    nil)
+   ((eq val 'last)
+    (eq part-number total-parts))
+   ((numberp val)
+    (< length val))
+   (t
+    (error "%S is not a valid value" val))))
+
+(defun gnus-article-encrypt-body (protocol &optional n)
+  "Encrypt the article body."
+  (interactive
+   (list
+    (or gnus-article-encrypt-protocol
+       (completing-read "Encrypt protocol: "
+                        gnus-article-encrypt-protocol-alist
+                        nil t))
+    current-prefix-arg))
+  (let ((func (cdr (assoc protocol gnus-article-encrypt-protocol-alist))))
+    (unless func
+      (error (format "Can't find the encrypt protocol %s" protocol)))
+    (if (member gnus-newsgroup-name '("nndraft:delayed"
+                                     "nndraft:drafts"
+                                     "nndraft:queue"))
+       (error "Can't encrypt the article in group %s"
+              gnus-newsgroup-name))
+    (gnus-summary-iterate n
+      (save-excursion
+       (set-buffer gnus-summary-buffer)
+       (let ((mail-parse-charset gnus-newsgroup-charset)
+             (mail-parse-ignored-charsets gnus-newsgroup-ignored-charsets)
+             (summary-buffer gnus-summary-buffer)
+             references point)
+         (gnus-set-global-variables)
+         (when (gnus-group-read-only-p)
+           (error "The current newsgroup does not support article encrypt"))
+         (gnus-summary-show-article t)
+         (setq references
+               (or (mail-header-references gnus-current-headers) ""))
+         (set-buffer gnus-article-buffer)
+         (let* ((buffer-read-only nil)
+                (headers
+                 (mapcar (lambda (field)
+                           (and (save-restriction
+                                  (message-narrow-to-head)
+                                  (goto-char (point-min))
+                                  (search-forward field nil t))
+                                (prog2
+                                    (message-narrow-to-field)
+                                    (buffer-string)
+                                  (delete-region (point-min) (point-max))
+                                  (widen))))
+                         '("Content-Type:" "Content-Transfer-Encoding:"
+                           "Content-Disposition:"))))
+           (message-narrow-to-head)
+           (message-remove-header "MIME-Version")
+           (goto-char (point-max))
+           (setq point (point))
+           (insert (apply 'concat headers))
+           (widen)
+           (narrow-to-region point (point-max))
+           (let ((message-options message-options))
+             (message-options-set 'message-sender user-mail-address)
+             (message-options-set 'message-recipients user-mail-address)
+             (message-options-set 'message-sign-encrypt 'not)
+             (funcall func))
+           (goto-char (point-min))
+           (insert "MIME-Version: 1.0\n")
+           (widen)
+           (gnus-summary-edit-article-done
+            references nil summary-buffer t))
+         (when gnus-keep-backlog
+           (gnus-backlog-remove-article
+            (car gnus-article-current) (cdr gnus-article-current)))
+         (save-excursion
+           (when (get-buffer gnus-original-article-buffer)
+             (set-buffer gnus-original-article-buffer)
+             (setq gnus-original-article nil)))
+         (when gnus-use-cache
+           (gnus-cache-update-article
+            (car gnus-article-current) (cdr gnus-article-current))))))))
+
+(defvar gnus-mime-security-button-line-format "%{%([[%t:%i]%D]%)%}\n"
+  "The following specs can be used:
+%t  The security MIME type
+%i  Additional info
+%d  Details
+%D  Details if button is pressed")
+
+(defvar gnus-mime-security-button-end-line-format "%{%([[End of %t]%D]%)%}\n"
+  "The following specs can be used:
+%t  The security MIME type
+%i  Additional info
+%d  Details
+%D  Details if button is pressed")
+
+(defvar gnus-mime-security-button-line-format-alist
+  '((?t gnus-tmp-type ?s)
+    (?i gnus-tmp-info ?s)
+    (?d gnus-tmp-details ?s)
+    (?D gnus-tmp-pressed-details ?s)))
+
+(defvar gnus-mime-security-button-map
+  (let ((map (make-sparse-keymap)))
+    (unless (>= (string-to-number emacs-version) 21)
+      (set-keymap-parent map gnus-article-mode-map))
+    (define-key map gnus-mouse-2 'gnus-article-push-button)
+    (define-key map "\r" 'gnus-article-press-button)
+    map))
+
+(defvar gnus-mime-security-details-buffer nil)
+
+(defvar gnus-mime-security-button-pressed nil)
+
+(defvar gnus-mime-security-show-details-inline t
+  "If non-nil, show details in the article buffer.")
+
+(defun gnus-mime-security-verify-or-decrypt (handle)
+  (mm-remove-parts (cdr handle))
+  (let ((region (mm-handle-multipart-ctl-parameter handle 'gnus-region))
+       point buffer-read-only)
+    (if region
+       (goto-char (car region)))
+    (save-restriction
+      (narrow-to-region (point) (point))
+      (with-current-buffer (mm-handle-multipart-original-buffer handle)
+       (let* ((mm-verify-option 'known)
+              (mm-decrypt-option 'known)
+              (nparts (mm-possibly-verify-or-decrypt (cdr handle) handle)))
+         (unless (eq nparts (cdr handle))
+           (mm-destroy-parts (cdr handle))
+           (setcdr handle nparts))))
+      (setq point (point))
+      (gnus-mime-display-security handle)
+      (goto-char (point-max)))
+    (when region
+      (delete-region (point) (cdr region))
+      (set-marker (car region) nil)
+      (set-marker (cdr region) nil))
+    (goto-char point)))
+
+(defun gnus-mime-security-show-details (handle)
+  (let ((details (mm-handle-multipart-ctl-parameter handle 'gnus-details)))
+    (if (not details)
+       (gnus-message 5 "No details.")
+      (if gnus-mime-security-show-details-inline
+         (let ((gnus-mime-security-button-pressed
+                (not (get-text-property (point) 'gnus-mime-details)))
+               (gnus-mime-security-button-line-format
+                (get-text-property (point) 'gnus-line-format))
+               buffer-read-only)
+           (forward-char -1)
+           (while (eq (get-text-property (point) 'gnus-line-format)
+                      gnus-mime-security-button-line-format)
+             (forward-char -1))
+           (forward-char)
+           (save-restriction
+             (narrow-to-region (point) (point))
+             (gnus-insert-mime-security-button handle))
+           (delete-region (point)
+                          (or (text-property-not-all
+                               (point) (point-max)
+                               'gnus-line-format
+                               gnus-mime-security-button-line-format)
+                              (point-max))))
+       ;; Not inlined.
+       (if (gnus-buffer-live-p gnus-mime-security-details-buffer)
+           (with-current-buffer gnus-mime-security-details-buffer
+             (erase-buffer)
+             t)
+         (setq gnus-mime-security-details-buffer
+               (gnus-get-buffer-create "*MIME Security Details*")))
+       (with-current-buffer gnus-mime-security-details-buffer
+         (insert details)
+         (goto-char (point-min)))
+       (pop-to-buffer gnus-mime-security-details-buffer)))))
+
+(defun gnus-mime-security-press-button (handle)
+  (save-excursion
+    (if (mm-handle-multipart-ctl-parameter handle 'gnus-info)
+       (gnus-mime-security-show-details handle)
+      (gnus-mime-security-verify-or-decrypt handle))))
+
+(defun gnus-insert-mime-security-button (handle &optional displayed)
+  (let* ((protocol (mm-handle-multipart-ctl-parameter handle 'protocol))
+        (gnus-tmp-type
+         (concat
+          (or (nth 2 (assoc protocol mm-verify-function-alist))
+              (nth 2 (assoc protocol mm-decrypt-function-alist))
+              "Unknown")
+          (if (equal (car handle) "multipart/signed")
+              " Signed" " Encrypted")
+          " Part"))
+        (gnus-tmp-info
+         (or (mm-handle-multipart-ctl-parameter handle 'gnus-info)
+             "Undecided"))
+        (gnus-tmp-details
+         (mm-handle-multipart-ctl-parameter handle 'gnus-details))
+        gnus-tmp-pressed-details
+        b e)
+    (setq gnus-tmp-details
+         (if gnus-tmp-details
+             (concat "\n" gnus-tmp-details)
+           ""))
+    (setq gnus-tmp-pressed-details
+         (if gnus-mime-security-button-pressed gnus-tmp-details ""))
+    (unless (bolp)
+      (insert "\n"))
+    (setq b (point))
+    (gnus-eval-format
+     gnus-mime-security-button-line-format
+     gnus-mime-security-button-line-format-alist
+     `(,@(gnus-local-map-property gnus-mime-security-button-map)
+        gnus-callback gnus-mime-security-press-button
+        gnus-line-format ,gnus-mime-security-button-line-format
+        gnus-mime-details ,gnus-mime-security-button-pressed
+        article-type annotation
+        gnus-data ,handle))
+    (setq e (if (bolp)
+               ;; Exclude a newline.
+               (1- (point))
+             (point)))
+    (widget-convert-button
+     'link b e
+     :mime-handle handle
+     :action 'gnus-widget-press-button
+     :button-keymap gnus-mime-security-button-map
+     :help-echo
+     (lambda (widget/window &optional overlay pos)
+       ;; Needed to properly clear the message due to a bug in
+       ;; wid-edit (XEmacs only).
+       (when (boundp 'help-echo-owns-message)
+        (setq help-echo-owns-message t))
+       (format
+       "%S: show detail"
+       (aref gnus-mouse-2 0))))))
+
+(defun gnus-mime-display-security (handle)
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (unless (gnus-unbuttonized-mime-type-p (car handle))
+      (gnus-insert-mime-security-button handle))
+    (gnus-mime-display-mixed (cdr handle))
+    (unless (bolp)
+      (insert "\n"))
+    (unless (gnus-unbuttonized-mime-type-p (car handle))
+      (let ((gnus-mime-security-button-line-format
+            gnus-mime-security-button-end-line-format))
+       (gnus-insert-mime-security-button handle)))
+    (mm-set-handle-multipart-parameter
+     handle 'gnus-region
+     (cons (set-marker (make-marker) (point-min))
+          (set-marker (make-marker) (point-max))))))
+
+
+;;; @ for mime-view
+;;;
+
+(defun gnus-article-header-presentation-method (entity situation)
+  (mime-insert-header entity)
+  (article-decode-group-name))
+
+(set-alist 'mime-header-presentation-method-alist
+          'gnus-original-article-mode
+          #'gnus-article-header-presentation-method)
+
+(defun gnus-mime-preview-quitting-method ()
+  (mime-preview-kill-buffer)
+  (delete-other-windows)
+  (gnus-article-show-summary)
+  (gnus-summary-select-article gnus-show-all-headers t))
+
+(set-alist 'mime-preview-quitting-method-alist
+          'gnus-original-article-mode #'gnus-mime-preview-quitting-method)
+
+(set-alist 'mime-preview-following-method-alist
+          'gnus-original-article-mode #'gnus-following-method)
+
+(set-alist 'mime-preview-over-to-previous-method-alist
+          'gnus-original-article-mode
+          (lambda ()
+            (if (> (point-min) 1)
+                (gnus-article-prev-page)
+              (gnus-article-read-summary-keys
+               nil (gnus-character-to-event ?P)))))
+
+(set-alist 'mime-preview-over-to-next-method-alist
+          'gnus-original-article-mode'
+          (lambda ()
+            (if (< (point-max) (buffer-size))
+                (gnus-article-next-page)
+              (gnus-article-read-summary-keys
+               nil (gnus-character-to-event ?N)))))
+
+
+;;; @ end
+;;;
+
 (gnus-ems-redefine)
 
 (provide 'gnus-art)
index c703caa..f3a43c9 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-async.el --- asynchronous support for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
   "Support for asynchronous operations."
   :group 'gnus)
 
-(defcustom gnus-asynchronous t
-  "*If nil, inhibit all Gnus asynchronicity.
-If non-nil, let the other asynch variables be heeded."
-  :group 'gnus-asynchronous
-  :type 'boolean)
-
 (defcustom gnus-use-article-prefetch 30
   "*If non-nil, prefetch articles in groups that allow this.
 If a number, prefetch only that many articles forward;
@@ -50,6 +45,12 @@ if t, prefetch as many articles as possible."
                 (const :tag "all" t)
                 (integer :tag "some" 0)))
 
+(defcustom gnus-asynchronous nil
+  "*If nil, inhibit all Gnus asynchronicity.
+If non-nil, let the other asynch variables be heeded."
+  :group 'gnus-asynchronous
+  :type 'boolean)
+
 (defcustom gnus-prefetched-article-deletion-strategy '(read exit)
   "List of symbols that say when to remove articles from the prefetch buffer.
 Possible values in this list are `read', which means that
@@ -77,7 +78,10 @@ It should return non-nil if the article is to be prefetched."
 (defvar gnus-async-article-alist nil)
 (defvar gnus-async-article-semaphore '(nil))
 (defvar gnus-async-fetch-list nil)
-(defvar gnus-asynch-obarray nil)
+(defvar gnus-async-hashtb nil)
+(defvar gnus-async-current-prefetch-group nil)
+(defvar gnus-async-current-prefetch-article nil)
+(defvar gnus-async-timer nil)
 
 (defvar gnus-async-prefetch-headers-buffer " *Async Prefetch Headers*")
 (defvar gnus-async-header-prefetched nil)
@@ -106,8 +110,8 @@ It should return non-nil if the article is to be prefetched."
         ,@forms)
      (gnus-async-release-semaphore 'gnus-async-article-semaphore)))
 
-(put 'gnus-asynch-with-semaphore 'lisp-indent-function 0)
-(put 'gnus-asynch-with-semaphore 'edebug-form-spec '(body))
+(put 'gnus-async-with-semaphore 'lisp-indent-function 0)
+(put 'gnus-async-with-semaphore 'edebug-form-spec '(body))
 
 ;;;
 ;;; Article prefetch
@@ -117,14 +121,14 @@ It should return non-nil if the article is to be prefetched."
 (defun gnus-async-close ()
   (gnus-kill-buffer gnus-async-prefetch-article-buffer)
   (gnus-kill-buffer gnus-async-prefetch-headers-buffer)
-  (setq gnus-async-article-alist nil
+  (setq gnus-async-hashtb nil
+       gnus-async-article-alist nil
        gnus-async-header-prefetched nil))
 
 (defun gnus-async-set-buffer ()
   (nnheader-set-temp-buffer gnus-async-prefetch-article-buffer t)
-  (unless gnus-asynch-obarray
-    (set (make-local-variable 'gnus-asynch-obarray)
-        (gnus-make-hashtable 1023))))
+  (unless gnus-async-hashtb
+    (setq gnus-async-hashtb (gnus-make-hashtable 1023))))
 
 (defun gnus-async-halt-prefetch ()
   "Stop prefetching."
@@ -144,49 +148,54 @@ It should return non-nil if the article is to be prefetched."
              ;; do this, which leads to slightly slower article
              ;; buffer display.
              (gnus-async-prefetch-article group next summary)
-           (run-with-idle-timer
-            0.1 nil 'gnus-async-prefetch-article group next summary)))))))
+           (when gnus-async-timer
+             (ignore-errors
+               (nnheader-cancel-timer 'gnus-async-timer)))
+           (setq gnus-async-timer
+                 (run-with-idle-timer
+                  0.1 nil 'gnus-async-prefetch-article
+                  group next summary))))))))
 
 (defun gnus-async-prefetch-article (group article summary &optional next)
   "Possibly prefetch several articles starting with ARTICLE."
   (if (not (gnus-buffer-live-p summary))
       (gnus-async-with-semaphore
-       (setq gnus-async-fetch-list nil))
+       (setq gnus-async-fetch-list nil))
     (when (and gnus-asynchronous
               (gnus-alive-p))
       (when next
        (gnus-async-with-semaphore
-        (pop gnus-async-fetch-list)))
+         (pop gnus-async-fetch-list)))
       (let ((do-fetch next)
-           (do-message t)) ;(eq major-mode 'gnus-summary-mode)))
+           (do-message t))             ;(eq major-mode 'gnus-summary-mode)))
        (when (and (gnus-group-asynchronous-p group)
                   (gnus-buffer-live-p summary)
                   (or (not next)
                       gnus-async-fetch-list))
          (gnus-async-with-semaphore
-          (unless next
-            (setq do-fetch (not gnus-async-fetch-list))
-            ;; Nix out any outstanding requests.
-            (setq gnus-async-fetch-list nil)
-            ;; Fill in the new list.
-            (let ((n gnus-use-article-prefetch)
-                  (data (gnus-data-find-list article))
-                  d)
-              (while (and (setq d (pop data))
-                          (if (numberp n)
-                              (natnump (decf n))
-                            n))
-                (unless (or (gnus-async-prefetched-article-entry
-                             group (setq article (gnus-data-number d)))
-                            (not (natnump article))
-                            (not (funcall gnus-async-prefetch-article-p d)))
-                  ;; Not already fetched -- so we add it to the list.
-                  (push article gnus-async-fetch-list)))
-              (setq gnus-async-fetch-list
-                    (nreverse gnus-async-fetch-list))))
-
-          (when do-fetch
-            (setq article (car gnus-async-fetch-list))))
+           (unless next
+             (setq do-fetch (not gnus-async-fetch-list))
+             ;; Nix out any outstanding requests.
+             (setq gnus-async-fetch-list nil)
+             ;; Fill in the new list.
+             (let ((n gnus-use-article-prefetch)
+                   (data (gnus-data-find-list article))
+                   d)
+               (while (and (setq d (pop data))
+                           (if (numberp n)
+                               (natnump (decf n))
+                             n))
+                 (unless (or (gnus-async-prefetched-article-entry
+                              group (setq article (gnus-data-number d)))
+                             (not (natnump article))
+                             (not (funcall gnus-async-prefetch-article-p d)))
+                   ;; Not already fetched -- so we add it to the list.
+                   (push article gnus-async-fetch-list)))
+               (setq gnus-async-fetch-list
+                     (nreverse gnus-async-fetch-list))))
+
+           (when do-fetch
+             (setq article (car gnus-async-fetch-list))))
 
          (when (and do-fetch article)
            ;; We want to fetch some more articles.
@@ -204,24 +213,33 @@ It should return non-nil if the article is to be prefetched."
                  (when do-message
                    (gnus-message 9 "Prefetching article %d in group %s"
                                  article group))
+                 (setq gnus-async-current-prefetch-group group)
+                 (setq gnus-async-current-prefetch-article article)
                  (gnus-request-article article group))))))))))
 
 (defun gnus-make-async-article-function (group article mark summary next)
   "Return a callback function."
   `(lambda (arg)
-     (save-excursion
-       (when arg
-        (gnus-async-set-buffer)
-        (gnus-async-with-semaphore
-         (push (list ',(intern (format "%s-%d" group article)
-                               gnus-asynch-obarray)
-                     ,mark (set-marker (make-marker) (point-max))
-                     ,group ,article)
-               gnus-async-article-alist)))
-       (if (not (gnus-buffer-live-p ,summary))
-          (gnus-async-with-semaphore
-           (setq gnus-async-fetch-list nil))
-        (gnus-async-prefetch-article ,group ,next ,summary t)))))
+     (gnus-async-article-callback arg ,group ,article ,mark ,summary ,next)))
+
+(defun gnus-async-article-callback (arg group article mark summary next)
+  "Function called when an async article is done being fetched."
+  (save-excursion
+    (setq gnus-async-current-prefetch-article nil)
+    (when arg
+      (gnus-async-set-buffer)
+      (gnus-async-with-semaphore
+       (setq
+        gnus-async-article-alist
+        (cons (list (intern (format "%s-%d" group article)
+                            gnus-async-hashtb)
+                    mark (set-marker (make-marker) (point-max))
+                    group article)
+              gnus-async-article-alist))))
+    (if (not (gnus-buffer-live-p summary))
+       (gnus-async-with-semaphore
+         (setq gnus-async-fetch-list nil))
+      (gnus-async-prefetch-article group next summary t))))
 
 (defun gnus-async-unread-p (data)
   "Return non-nil if DATA represents an unread article."
@@ -230,6 +248,9 @@ It should return non-nil if the article is to be prefetched."
 (defun gnus-async-request-fetched-article (group article buffer)
   "See whether we have ARTICLE from GROUP and put it in BUFFER."
   (when (numberp article)
+    (when (and (equal group gnus-async-current-prefetch-group)
+              (eq article gnus-async-current-prefetch-article))
+      (gnus-async-wait-for-article article))
     (let ((entry (gnus-async-prefetched-article-entry group article)))
       (when entry
        (save-excursion
@@ -237,18 +258,49 @@ It should return non-nil if the article is to be prefetched."
          (copy-to-buffer buffer (cadr entry) (caddr entry))
          ;; Remove the read article from the prefetch buffer.
          (when (memq 'read gnus-prefetched-article-deletion-strategy)
-           (gnus-async-delete-prefected-entry entry))
+           (gnus-async-delete-prefetched-entry entry))
          t)))))
 
-(defun gnus-async-delete-prefected-entry (entry)
+(defun gnus-async-wait-for-article (article)
+  "Wait until ARTICLE is no longer the currently-being-fetched article."
+  (save-excursion
+    (gnus-async-set-buffer)
+    (let ((proc (nntp-find-connection (current-buffer)))
+         (nntp-server-buffer (current-buffer))
+         (nntp-have-messaged nil)
+         (tries 0))
+      (condition-case nil
+         ;; FIXME: we could stop waiting after some
+         ;; timeout, but this is the wrong place to do it.
+         ;; rather than checking time-spent-waiting, we
+         ;; should check time-since-last-output, which
+         ;; needs to be done in nntp.el.
+         (while (eq article gnus-async-current-prefetch-article)
+           (incf tries)
+           (when (nntp-accept-process-output proc)
+             (setq tries 0))
+           (when (and (not nntp-have-messaged)
+                      (= tries 3))
+             (gnus-message 5 "Waiting for async article...")
+             (setq nntp-have-messaged t)))
+       (quit
+        ;; if the user interrupted on a slow/hung connection,
+        ;; do something friendly.
+        (when (> tries 3)
+          (setq gnus-async-current-prefetch-article nil))
+        (signal 'quit nil)))
+      (when nntp-have-messaged
+       (gnus-message 5 "")))))
+
+(defun gnus-async-delete-prefetched-entry (entry)
   "Delete ENTRY from buffer and alist."
   (ignore-errors
     (delete-region (cadr entry) (caddr entry))
     (set-marker (cadr entry) nil)
     (set-marker (caddr entry) nil))
   (gnus-async-with-semaphore
-   (setq gnus-async-article-alist
-        (delq entry gnus-async-article-alist))))
+    (setq gnus-async-article-alist
+         (delq entry gnus-async-article-alist))))
 
 (defun gnus-async-prefetch-remove-group (group)
   "Remove all articles belonging to GROUP from the prefetch buffer."
@@ -259,7 +311,7 @@ It should return non-nil if the article is to be prefetched."
        (gnus-async-set-buffer)
        (while alist
          (when (equal group (nth 3 (car alist)))
-           (gnus-async-delete-prefected-entry (car alist)))
+           (gnus-async-delete-prefetched-entry (car alist)))
          (pop alist))))))
 
 (defun gnus-async-prefetched-article-entry (group article)
@@ -267,7 +319,7 @@ It should return non-nil if the article is to be prefetched."
   (let ((entry (save-excursion
                 (gnus-async-set-buffer)
                 (assq (intern (format "%s-%d" group article)
-                              gnus-asynch-obarray)
+                              gnus-async-hashtb)
                       gnus-async-article-alist))))
     ;; Perhaps something has emptied the buffer?
     (if (and entry
index f3bb686..62a6b86 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-audio.el --- Sound effects for Gnus
-;; Copyright (C) 1996 Free Software Foundation
+;; Copyright (C) 1996, 2000, 2003 Free Software Foundation
 
 ;; Author: Steven L. Baur <steve@miranova.com>
+;; Keywords: news, mail, multimedia
 
 ;; This file is part of GNU Emacs.
 
 ;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
+
 ;; This file provides access to sound effects in Gnus.
-;; Prerelease:  This file is partially stripped to support earcons.el
-;; You can safely ignore most of it until Red Gnus.  **Evil Laugh**
-;;; Code:
+;; This file is partially stripped to support earcons.el.
 
-(when (null (boundp 'running-xemacs))
-  (defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version)))
+;;; Code:
 
 (require 'nnheader)
-(eval-when-compile (require 'cl))
 
-(defvar gnus-audio-inline-sound
-  (and (fboundp 'device-sound-enabled-p)
-       (device-sound-enabled-p))
-  "When t, we will not spawn a subprocess to play sounds.")
+(require 'path-util)
 
-(defvar gnus-audio-directory (nnheader-find-etc-directory "sounds")
-  "The directory containing the Sound Files.")
+(defgroup gnus-audio nil
+  "Playing sound in Gnus."
+  :version "21.1"
+  :group 'gnus-visual
+  :group 'multimedia)
 
-(defvar gnus-audio-au-player "/usr/bin/showaudio"
-  "Executable program for playing sun AU format sound files.")
-
-(defvar gnus-audio-wav-player "/usr/local/bin/play"
-  "Executable program for playing WAV files.")
+(defvar gnus-audio-inline-sound
+  (or (if (fboundp 'device-sound-enabled-p)
+         (device-sound-enabled-p))     ; XEmacs
+      (fboundp 'play-sound))           ; Emacs 21
+  "Non-nil means try to play sounds without using an external program.")
+
+(defcustom gnus-audio-directory (nnheader-find-etc-directory "sounds")
+  "The directory containing the Sound Files."
+  :type '(choice directory (const nil))
+  :group 'gnus-audio)
+
+(defcustom gnus-audio-au-player (exec-installed-p "play")
+  "Executable program for playing sun AU format sound files."
+  :group 'gnus-audio
+  :type '(choice file (const nil)))
+
+(defcustom gnus-audio-wav-player (exec-installed-p "play")
+  "Executable program for playing WAV files."
+  :group 'gnus-audio
+  :type '(choice file (const nil)))
 
 ;;; The following isn't implemented yet.  Wait for Millennium Gnus.
-;(defvar gnus-audio-effects-enabled t
-;  "When t, Gnus will use sound effects.")
-;(defvar gnus-audio-enable-hooks nil
-;  "Functions run when enabling sound effects.")
-;(defvar gnus-audio-disable-hooks nil
-;  "Functions run when disabling sound effects.")
-;(defvar gnus-audio-theme-song nil
-;  "Theme song for Gnus.")
-;(defvar gnus-audio-enter-group nil
-;  "Sound effect played when selecting a group.")
-;(defvar gnus-audio-exit-group nil
-;  "Sound effect played when exiting a group.")
-;(defvar gnus-audio-score-group nil
-;  "Sound effect played when scoring a group.")
-;(defvar gnus-audio-busy-sound nil
-;  "Sound effect played when going into a ... sequence.")
+;;(defvar gnus-audio-effects-enabled t
+;;  "When t, Gnus will use sound effects.")
+;;(defvar gnus-audio-enable-hooks nil
+;;  "Functions run when enabling sound effects.")
+;;(defvar gnus-audio-disable-hooks nil
+;;  "Functions run when disabling sound effects.")
+;;(defvar gnus-audio-theme-song nil
+;;  "Theme song for Gnus.")
+;;(defvar gnus-audio-enter-group nil
+;;  "Sound effect played when selecting a group.")
+;;(defvar gnus-audio-exit-group nil
+;;  "Sound effect played when exiting a group.")
+;;(defvar gnus-audio-score-group nil
+;;  "Sound effect played when scoring a group.")
+;;(defvar gnus-audio-busy-sound nil
+;;  "Sound effect played when going into a ... sequence.")
 
 
 ;;;###autoload
-                                       ;(defun gnus-audio-enable-sound ()
-;  "Enable Sound Effects for Gnus."
-;  (interactive)
-;  (setq gnus-audio-effects-enabled t)
-;  (gnus-run-hooks gnus-audio-enable-hooks))
+;;(defun gnus-audio-enable-sound ()
+;;  "Enable Sound Effects for Gnus."
+;;  (interactive)
+;;  (setq gnus-audio-effects-enabled t)
+;;  (gnus-run-hooks gnus-audio-enable-hooks))
 
 ;;;###autoload
                                        ;(defun gnus-audio-disable-sound ()
-;  "Disable Sound Effects for Gnus."
-;  (interactive)
-;  (setq gnus-audio-effects-enabled nil)
-;  (gnus-run-hooks gnus-audio-disable-hooks))
+;;  "Disable Sound Effects for Gnus."
+;;  (interactive)
+;;  (setq gnus-audio-effects-enabled nil)
+;;  (gnus-run-hooks gnus-audio-disable-hooks))
 
 ;;;###autoload
 (defun gnus-audio-play (file)
-  "Play a sound through the speaker."
-  (interactive)
+  "Play a sound FILE through the speaker."
+  (interactive "fSound file name: ")
   (let ((sound-file (if (file-exists-p file)
                        file
-                     (concat gnus-audio-directory file))))
+                     (expand-file-name file gnus-audio-directory))))
     (when (file-exists-p sound-file)
-      (if gnus-audio-inline-sound
-         (play-sound-file sound-file)
-       (cond ((string-match "\\.wav$" sound-file)
-              (call-process gnus-audio-wav-player
-                            sound-file
-                            0
-                            nil
-                            sound-file))
-             ((string-match "\\.au$" sound-file)
-              (call-process gnus-audio-au-player
-                            sound-file
-                            0
-                            nil
-                            sound-file)))))))
+      (cond ((and gnus-audio-inline-sound
+                 (condition-case nil
+                     ;; Even if we have audio, we may fail with the
+                     ;; wrong sort of sound file.
+                     (progn (play-sound-file sound-file)
+                            t)
+                   (error nil))))
+           ;; If we don't have built-in sound, or playing it failed,
+           ;; try with external program.
+           ((equal "wav" (file-name-extension sound-file))
+            (call-process gnus-audio-wav-player
+                          sound-file
+                          0
+                          nil
+                          sound-file))
+           ((equal "au" (file-name-extension sound-file))
+            (call-process gnus-audio-au-player
+                          sound-file
+                          0
+                          nil
+                          sound-file))))))
 
 
 ;;; The following isn't implemented yet, wait for Red Gnus
-                                       ;(defun gnus-audio-startrek-sounds ()
-;  "Enable sounds from Star Trek the original series."
-;  (interactive)
-;  (setq gnus-audio-busy-sound "working.au")
-;  (setq gnus-audio-enter-group "bulkhead_door.au")
-;  (setq gnus-audio-exit-group "bulkhead_door.au")
-;  (setq gnus-audio-score-group "ST_laser.au")
-;  (setq gnus-audio-theme-song "startrek.au")
-;  (add-hook 'gnus-select-group-hook 'gnus-audio-startrek-select-group)
-;  (add-hook 'gnus-exit-group-hook 'gnus-audio-startrek-exit-group))
+;;(defun gnus-audio-startrek-sounds ()
+;;  "Enable sounds from Star Trek the original series."
+;;  (interactive)
+;;  (setq gnus-audio-busy-sound "working.au")
+;;  (setq gnus-audio-enter-group "bulkhead_door.au")
+;;  (setq gnus-audio-exit-group "bulkhead_door.au")
+;;  (setq gnus-audio-score-group "ST_laser.au")
+;;  (setq gnus-audio-theme-song "startrek.au")
+;;  (add-hook 'gnus-select-group-hook 'gnus-audio-startrek-select-group)
+;;  (add-hook 'gnus-exit-group-hook 'gnus-audio-startrek-exit-group))
 ;;;***
 
 (defvar gnus-startup-jingle "Tuxedomoon.Jingle4.au"
diff --git a/lisp/gnus-bbdb.el b/lisp/gnus-bbdb.el
new file mode 100644 (file)
index 0000000..35dd546
--- /dev/null
@@ -0,0 +1,678 @@
+;; gnus-bbdb.el --- Interface to T-gnus
+
+;; Copyright (c) 1991,1992,1993 Jamie Zawinski <jwz@netscape.com>.
+;; Copyright (C) 1995,1996,1997 Shuhei KOBAYASHI
+;; Copyright (C) 1997,1998 MORIOKA Tomohiko
+;; Copyright (C) 1998,1999 Keiichi Suzuki <keiichi@nanap.org>
+
+;; Author: Keiichi Suzuki <keiichi@nanap.org>
+;; Author: Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+;; Keywords: BBDB, MIME, multimedia, multilingual, mail, news
+
+;; This file is part of T-gnus.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'bbdb)
+(require 'bbdb-com)
+(require 'gnus)
+(require 'std11)
+(eval-when-compile
+  (defvar bbdb-pop-up-elided-display)  ; default unbound.
+  (require 'gnus-win)
+  (require 'cl))
+
+(defvar gnus-bbdb/decode-field-body-function 'nnheader-decode-field-body
+  "*Field body decoder.")
+
+(defmacro gnus-bbdb/decode-field-body (field-body field-name)
+  `(or (and (functionp gnus-bbdb/decode-field-body-function)
+           (funcall gnus-bbdb/decode-field-body-function
+                    ,field-body ,field-name))
+       ,field-body))
+
+(defvar gnus-bbdb/extract-message-sender-function
+  'gnus-bbdb/extract-message-sender)
+
+(defun gnus-bbdb/extract-message-sender ()
+  (let ((from (mime-entity-fetch-field gnus-current-headers "from"))
+       to)
+    (when from
+      (setq from (gnus-bbdb/extract-address-components
+                 (gnus-bbdb/decode-field-body from 'From)))
+      (if (and (car (cdr from))
+              (string-match (bbdb-user-mail-names) (car (cdr from)))
+              ;; if logged-in user sent this, use recipients.
+              (setq to (mime-entity-fetch-field gnus-current-headers "to")))
+         (gnus-bbdb/extract-address-components
+          (gnus-bbdb/decode-field-body to 'To))
+       from))))
+
+;;;###autoload
+(defun gnus-bbdb/update-record (&optional offer-to-create)
+  "Return the record corresponding to the current GNUS message, creating
+or modifying it as necessary.  A record will be created if
+bbdb/news-auto-create-p is non-nil, or if OFFER-TO-CREATE is true and
+the user confirms the creation."
+  (if bbdb-use-pop-up
+      (gnus-bbdb/pop-up-bbdb-buffer offer-to-create)
+    (let ((message-key
+          (intern (mail-header-id gnus-current-headers)))
+         record sender)
+      (or (and (setq record (bbdb-message-cache-lookup message-key))
+              (if (listp record)
+                  (nth 1 record)
+                record))
+         (when (setq sender
+                     (funcall gnus-bbdb/extract-message-sender-function))
+           (save-excursion
+             (setq record (bbdb-annotate-message-sender
+                           sender t
+                           (or (bbdb-invoke-hook-for-value
+                                bbdb/news-auto-create-p)
+                               offer-to-create)
+                           offer-to-create)))
+           (when record
+             ;; XXX: BBDB 2.3x not only redefines
+             ;; `bbdb-encache-message' as a macro but also the inherent
+             ;; semantics of message caching functions is changed, so
+             ;; the following calls are much the same here.
+             (if (functionp 'bbdb-encache-message)
+                 (car (bbdb-encache-message message-key (list record)))
+               (bbdb-encache-message message-key record))))))))
+
+;;;###autoload
+(defun gnus-bbdb/annotate-sender (string &optional replace)
+  "Add a line to the end of the Notes field of the BBDB record
+corresponding to the sender of this message.  If REPLACE is non-nil,
+replace the existing notes entry (if any)."
+  (interactive (list (if bbdb-readonly-p
+                        (error "The Insidious Big Brother Database is read-only.")
+                      (read-string "Comments: "))))
+  (bbdb-annotate-notes (gnus-bbdb/update-record t) string 'notes replace))
+
+(defun gnus-bbdb/edit-notes (&optional arg)
+  "Edit the notes field or (with a prefix arg) a user-defined field
+of the BBDB record corresponding to the sender of this message."
+  (interactive "P")
+  (let ((record (or (gnus-bbdb/update-record t) (error ""))))
+    (bbdb-display-records (list record))
+    (if arg
+       (bbdb-record-edit-property record nil t)
+      (bbdb-record-edit-notes record t))))
+
+;;;###autoload
+(defun gnus-bbdb/show-sender ()
+  "Display the contents of the BBDB for the sender of this message.
+This buffer will be in bbdb-mode, with associated keybindings."
+  (interactive)
+  (let ((record (gnus-bbdb/update-record t)))
+    (if record
+       (bbdb-display-records (list record))
+      (error "unperson"))))
+
+
+(defun gnus-bbdb/pop-up-bbdb-buffer (&optional offer-to-create)
+  "Make the *BBDB* buffer be displayed along with the GNUS windows,
+displaying the record corresponding to the sender of the current message."
+  (let* ((bbdb-gag-messages t)
+        (bbdb-electric-p nil)
+        (record
+         (let (bbdb-use-pop-up)
+           (gnus-bbdb/update-record offer-to-create)))
+        (bbdb-display-layout
+         (cond ((boundp 'bbdb-pop-up-display-layout)
+                (symbol-value 'bbdb-pop-up-display-layout))
+               ((boundp 'bbdb-pop-up-elided-display)
+                (symbol-value 'bbdb-pop-up-elided-display))))
+        (bbdb-elided-display bbdb-display-layout))
+    (save-current-buffer
+      ;; display the bbdb buffer iff there is a record for this article.
+      (cond
+       (record
+       (bbdb-pop-up-bbdb-buffer
+        (lambda (w)
+          (with-current-buffer (window-buffer w)
+            (memq major-mode
+                  '(mime-view-mode gnus-article-mode)))))
+       (bbdb-display-records (list record)))
+       ((and (not bbdb-inside-electric-display)
+            (get-buffer-window bbdb-buffer-name))
+       (delete-other-windows)
+       (if (assq 'article gnus-buffer-configuration)
+           (gnus-configure-windows 'article)
+         (gnus-configure-windows 'SelectArticle))
+       (let ((w (get-buffer-window gnus-summary-buffer)))
+         (if w (select-window w))))))
+    record))
+
+;;;###autoload
+(defun gnus-bbdb/split-mail (header-field bbdb-field
+                                         &optional regexp group)
+  "Mail split method for `nnmail-split-fancy'.
+HEADER-FIELD is a regexp or list of regexps as mail header field name
+for gathering mail addresses.  If HEADER-FIELD is a string, then it's
+used for just matching pattern.  If HEADER-FIELD is a list of strings,
+then these strings have priorities in the order.
+
+BBDB-FIELD is field name of BBDB.
+Optional argument REGEXP is regexp string for matching BBDB-FIELD value.
+If REGEXP is nil or not specified, then all BBDB-FIELD value is matched.
+
+If GROUP is nil or not specified, then BBDB-FIELD value is returned as
+group name.  If GROUP is a symbol `&', then list of all matching group's
+BBDB-FIELD values is returned.  Otherwise, GROUP is returned."
+  (if (listp header-field)
+      (if (eq group '&)
+         (gnus-bbdb/split-mail (mapconcat 'identity header-field "\\|")
+                               bbdb-field regexp group)
+       (let (rest)
+         (while (and header-field
+                     (null (setq rest (gnus-bbdb/split-mail
+                                       (car header-field) bbdb-field
+                                       regexp group))))
+           (setq header-field (cdr header-field)))
+         rest))
+    (let ((pat (concat "^\\(" header-field "\\):[ \t]"))
+         header-values)
+      (goto-char (point-min))
+      (while (re-search-forward pat nil t)
+       (setq header-values (cons (buffer-substring (point)
+                                                   (std11-field-end))
+                                 header-values)))
+      (let ((address-regexp
+            (with-temp-buffer
+              (let (lal)
+                (while header-values
+                  (setq lal (std11-parse-addresses-string
+                             (pop header-values)))
+                  (while lal
+                    (gnus-bbdb/insert-address-regexp (pop lal)))))
+              (buffer-string))))
+       (unless (zerop (length address-regexp))
+         (gnus-bbdb/split-mail-1 address-regexp bbdb-field regexp group))))))
+
+(defun gnus-bbdb/insert-address-regexp (address)
+  "Insert string of address part from parsed ADDRESS of RFC 822."
+  (cond ((eq (car address) 'group)
+        (setq address (cdr address))
+        (while address
+          (gnus-bbdb/insert-address-regexp (pop address))))
+       ((eq (car address) 'mailbox)
+        (unless (eq (point) (point-min))
+          (insert "\\|"))
+        (let ((addr (nth 1 address)))
+          (insert (regexp-quote (std11-addr-to-string
+                                 (if (eq (car addr) 'phrase-route-addr)
+                                     (nth 2 addr)
+                                   (cdr addr)))))))))
+
+(defun gnus-bbdb/split-mail-1 (address-regexp bbdb-field regexp group)
+  (let ((records (bbdb-search (bbdb-records) nil nil address-regexp))
+       prop rest)
+    (or regexp (setq regexp ""))
+    (catch 'done
+      (cond
+       ((eq group '&)
+       (while records
+         (when (and (setq prop (bbdb-record-getprop (car records) bbdb-field))
+                    (string-match regexp prop)
+                    (not (member prop rest)))
+           (setq rest (cons prop rest)))
+         (setq records (cdr records)))
+       (throw 'done (when rest (cons '& rest))))
+       (t
+       (while records
+         (when (or (null bbdb-field)
+                   (and (setq prop (bbdb-record-getprop (car records)
+                                                        bbdb-field))
+                        (string-match regexp prop)))
+           (throw 'done (or group prop)))
+         (setq records (cdr records))))))))
+
+;;
+;; Announcing BBDB entries in the summary buffer
+;;
+
+(defcustom gnus-bbdb/lines-and-from-length 18
+  "*The number of characters used to display From: info in Gnus, if you have
+set gnus-optional-headers to 'gnus-bbdb/lines-and-from."
+  :group 'bbdb-mua-specific-gnus
+  :type 'integer)
+
+(defcustom gnus-bbdb/summary-mark-known-posters t
+  "*If t, mark messages created by people with records in the BBDB.
+In GNUS, this marking will take place in the subject list (assuming
+`gnus-optional-headers' contains `gnus-bbdb/lines-and-from').  In Gnus, the
+marking will take place in the Summary buffer if the format code defined by
+`gnus-bbdb/summary-user-format-letter' is used in `gnus-summary-line-format'.
+This variable has no effect on the marking controlled by
+`gnus-bbdb/summary-in-bbdb-format-letter'."
+  :group 'bbdb-mua-specific-gnus
+  :type '(choice (const :tag "Mark known posters" t)
+                (const :tag "Do not mark known posters" nil)))
+(static-when (and (fboundp 'defvaralias)
+                 (subrp (symbol-function 'defvaralias)))
+  (defvaralias 'gnus-bbdb/mark-known-posters
+    'gnus-bbdb/summary-mark-known-posters))
+
+(defcustom gnus-bbdb/summary-known-poster-mark "+"
+  "This is the default character to prefix author names with if
+gnus-bbdb/summary-mark-known-posters is t.  If the poster's record has
+an entry in the field named by bbdb-message-marker-field, then that will
+be used instead."
+  :group 'bbdb-mua-specific-gnus
+  :type 'character)
+
+(defcustom gnus-bbdb/summary-show-bbdb-names t
+  "*If both this variable and `gnus-bbdb/summary-prefer-real-names' are true,
+then for messages from authors who are in your database, the name
+displayed will be the primary name in the database, rather than the
+one in the From line of the message.  This doesn't affect the names of
+people who aren't in the database, of course.  (`gnus-optional-headers'
+must be `gnus-bbdb/lines-and-from' for GNUS users.)"
+  :group 'bbdb-mua-specific-gnus
+  :type 'boolean)
+(static-when (and (fboundp 'defvaralias)
+                 (subrp (symbol-function 'defvaralias)))
+  (defvaralias 'gnus-bbdb/header-show-bbdb-names
+    'gnus-bbdb/summary-show-bbdb-names))
+
+(defcustom gnus-bbdb/summary-prefer-bbdb-data t
+  "If t, then for posters who are in our BBDB, replace the information
+provided in the From header with data from the BBDB."
+  :group 'bbdb-mua-specific-gnus
+  :type 'boolean)
+
+(defcustom gnus-bbdb/summary-prefer-real-names t
+  "If t, then display the poster's name from the BBDB if we have one,
+otherwise display his/her primary net address if we have one.  If it
+is set to the symbol bbdb, then real names will be used from the BBDB
+if present, otherwise the net address in the post will be used.  If
+gnus-bbdb/summary-prefer-bbdb-data is nil, then this has no effect.
+See `gnus-bbdb/lines-and-from' for GNUS users, or
+`gnus-bbdb/summary-user-format-letter' for Gnus users."
+  :group 'bbdb-mua-specific-gnus
+  :type '(choice (const :tag "Prefer real names" t)
+                (const :tag "Prefer network addresses" nil)))
+(static-when (and (fboundp 'defvaralias)
+                 (subrp (symbol-function 'defvaralias)))
+  (defvaralias 'gnus-bbdb/header-prefer-real-names
+    'gnus-bbdb/summary-prefer-real-names))
+
+(defcustom gnus-bbdb/summary-user-format-letter "B"
+  "This is the gnus-user-format-function- that will be used to insert
+the information from the BBDB in the summary buffer (using
+`gnus-bbdb/summary-get-author').  This format code is meant to replace
+codes that insert sender names or addresses (like %A or %n). Unless
+you've alread got other code using user format B, you might as well
+stick with the default.  Additionally, if the value of this variable
+is nil, no format function will be installed for
+`gnus-bbdb/summary-get-author'.  See also
+`gnus-bbdb/summary-in-bbdb-format-letter', which installs a format
+code for `gnus-bbdb/summary-author-in-bbdb'"
+  :group 'bbdb-mua-specific-gnus
+  :type 'character)
+
+(defcustom gnus-bbdb/summary-in-bbdb-format-letter "b"
+  "This is the gnus-user-format-function- that will be used to insert
+`gnus-bbdb/summary-known-poster-mark' (using
+`gnus-bbdb/summary-author-in-bbdb') if the poster is in the BBDB, and
+\" \" if not.  If the value of this variable is nil, no format code
+will be installed for `gnus-bbdb/summary-author-in-bbdb'.  See also
+`gnus-bbdb/summary-user-format-letter', which installs a format code
+for `gnus-bbdb/summary-get-author'."
+  :group 'bbdb-mua-specific-gnus
+  :type 'character)
+
+(defcustom bbdb-message-marker-field 'mark-char
+  "*The field whose value will be used to mark messages by this user in Gnus."
+  :group 'bbdb-mua-specific-gnus
+  :type 'symbol)
+
+;;;###autoload
+(defun gnus-bbdb/lines-and-from (header)
+  "Useful as the value of gnus-optional-headers in *GNUS* (not Gnus).
+NOTE: This variable no longer seems to be present in Gnus.  It seems
+to have been replaced by `message-default-headers', which only takes
+strings.  In the future this should change."
+  (let* ((length gnus-bbdb/lines-and-from-length)
+        (lines (mail-header-lines header))
+        (from (mail-header-from header))
+        (data (and (or gnus-bbdb/summary-mark-known-posters
+                       gnus-bbdb/summary-show-bbdb-names)
+                   (condition-case ()
+                       (gnus-bbdb/extract-address-components from)
+                     (error nil))))
+        (name (car data))
+        (net (car (cdr data)))
+        (record (and data
+                     (bbdb-search-simple
+                      name
+                      (if (and net bbdb-canonicalize-net-hook)
+                          (bbdb-canonicalize-address net)
+                        net))))
+        string L)
+
+    (if (and record name (member (downcase name) (bbdb-record-net record)))
+       ;; bogon!
+       (setq record nil))
+
+    (setq name
+         (or (and gnus-bbdb/summary-prefer-bbdb-data
+                  (or (and gnus-bbdb/summary-prefer-real-names
+                           (and record (bbdb-record-name record)))
+                      (and record (bbdb-record-net record)
+                           (nth 0 (bbdb-record-net record)))))
+             (and gnus-bbdb/summary-prefer-real-names
+                  (or (and (equal gnus-bbdb/summary-prefer-real-names 'bbdb)
+                           net)
+                      name))
+             net from "**UNKNOWN**"))
+    ;; GNUS can't cope with extra square-brackets appearing in the summary.
+    (if (and name (string-match "[][]" name))
+       (progn (setq name (copy-sequence name))
+              (while (string-match "[][]" name)
+                (aset name (match-beginning 0) ? ))))
+    (setq string (format "%s%3d:%s"
+                        (if (and record gnus-bbdb/summary-mark-known-posters)
+                            (or (bbdb-record-getprop
+                                 record bbdb-message-marker-field)
+                                "*")
+                          " ")
+                        lines (or name from))
+         L (length string))
+    (cond ((> L length) (substring string 0 length))
+         ((< L length) (concat string (make-string (- length L) ? )))
+         (t string))))
+
+(defun gnus-bbdb/summary-get-author (header)
+  "Given a Gnus message header, returns the appropriate piece of
+information to identify the author in a Gnus summary line, depending on
+the settings of the various configuration variables.  See the
+documentation for the following variables for more details:
+  `gnus-bbdb/summary-mark-known-posters'
+  `gnus-bbdb/summary-known-poster-mark'
+  `gnus-bbdb/summary-prefer-bbdb-data'
+  `gnus-bbdb/summary-prefer-real-names'
+This function is meant to be used with the user function defined in
+  `gnus-bbdb/summary-user-format-letter'"
+  (let* ((from (mail-header-from header))
+        (data (and gnus-bbdb/summary-show-bbdb-names
+                   (condition-case ()
+                       (gnus-bbdb/extract-address-components from)
+                     (error nil))))
+        (name (car data))
+        (net (car (cdr data)))
+        (record (and data
+                     (bbdb-search-simple
+                      name
+                      (if (and net bbdb-canonicalize-net-hook)
+                          (bbdb-canonicalize-address net)
+                        net)))))
+    (if (and record name (member (downcase name) (bbdb-record-net record)))
+       ;; bogon!
+       (setq record nil))
+    (setq name
+         (or (and gnus-bbdb/summary-prefer-bbdb-data
+                  (or (and gnus-bbdb/summary-prefer-real-names
+                           (and record (bbdb-record-name record)))
+                      (and record (bbdb-record-net record)
+                           (nth 0 (bbdb-record-net record)))))
+             (and gnus-bbdb/summary-prefer-real-names
+                  (or (and (equal gnus-bbdb/summary-prefer-real-names 'bbdb)
+                           net)
+                      name))
+             net from "**UNKNOWN**"))
+    (format "%s%s"
+           (or (and record gnus-bbdb/summary-mark-known-posters
+                    (or (bbdb-record-getprop
+                         record bbdb-message-marker-field)
+                        gnus-bbdb/summary-known-poster-mark))
+               " ")
+           name)))
+
+;; DEBUG: (gnus-bbdb/summary-author-in-bbdb "From: simmonmt@acm.org")
+(defun gnus-bbdb/summary-author-in-bbdb (header)
+  "Given a Gnus message header, returns a mark if the poster is in the BBDB, \" \" otherwise.  The mark itself is the value of the field indicated by `bbdb-message-marker-field' (`mark-char' by default) if the indicated field is in the poster's record, and `gnus-bbdb/summary-known-poster-mark' otherwise."
+  (let* ((from (mail-header-from header))
+        (data (condition-case ()
+                  (gnus-bbdb/extract-address-components from)
+                (error nil)))
+        (name (car data))
+        (net (cadr data))
+        record)
+    (if (and data
+            (setq record
+                  (bbdb-search-simple
+                   name (if (and net bbdb-canonicalize-net-hook)
+                            (bbdb-canonicalize-address net)
+                          net))))
+       (or (bbdb-record-getprop
+            record bbdb-message-marker-field)
+           gnus-bbdb/summary-known-poster-mark) " ")))
+
+;;
+;; Scoring
+;;
+
+(defcustom gnus-bbdb/score-field 'gnus-score
+  "This variable contains the name of the BBDB field which should be
+checked for a score to add to the net addresses in the same record."
+  :group 'bbdb-mua-specific-gnus-scoring
+  :type 'symbol)
+
+(defcustom gnus-bbdb/score-default nil
+  "If this is set, then every net address in the BBDB that does not have
+an associated score field will be assigned this score.  A value of nil
+implies a default score of zero."
+  :group 'bbdb-mua-specific-gnus-scoring
+  :type '(choice (const :tag "Do not assign default score")
+                (integer :tag "Assign this default score" 0)))
+
+(defvar gnus-bbdb/score-default-internal nil
+  "Internal variable for detecting changes to
+`gnus-bbdb/score-default'.  You should not set this variable directly -
+set `gnus-bbdb/score-default' instead.")
+
+(defvar gnus-bbdb/score-alist nil
+  "The text version of the scoring structure returned by
+gnus-bbdb/score.  This is built automatically from the BBDB.")
+
+(defvar gnus-bbdb/score-rebuild-alist t
+  "Set to t to rebuild gnus-bbdb/score-alist on the next call to
+gnus-bbdb/score.  This will be set automatically if you change a BBDB
+record which contains a gnus-score field.")
+
+(defun gnus-bbdb/score-invalidate-alist (rec)
+  "This function is called through bbdb-after-change-hook, and sets
+gnus-bbdb/score-rebuild-alist to t if the changed record contains a
+gnus-score field."
+  (if (bbdb-record-getprop rec gnus-bbdb/score-field)
+      (setq gnus-bbdb/score-rebuild-alist t)))
+
+;;;###autoload
+(defun gnus-bbdb/score (group)
+  "This returns a score alist for GNUS.  A score pair will be made for
+every member of the net field in records which also have a gnus-score
+field.  This allows the BBDB to serve as a supplemental global score
+file, with the advantage that it can keep up with multiple and changing
+addresses better than the traditionally static global scorefile."
+  (list (list
+        (condition-case nil
+            (read (gnus-bbdb/score-as-text group))
+          (error (setq gnus-bbdb/score-rebuild-alist t)
+                 (message "Problem building BBDB score table.")
+                 (ding) (sit-for 2)
+                 nil)))))
+
+(defun gnus-bbdb/score-as-text (group)
+  "Returns a SCORE file format string built from the BBDB."
+  (cond ((or (cond ((/= (or gnus-bbdb/score-default 0)
+                       (or gnus-bbdb/score-default-internal 0))
+                   (setq gnus-bbdb/score-default-internal
+                         gnus-bbdb/score-default)
+                   t))
+            (not gnus-bbdb/score-alist)
+            gnus-bbdb/score-rebuild-alist)
+        (setq gnus-bbdb/score-rebuild-alist nil)
+        (setq gnus-bbdb/score-alist
+              (concat "((touched nil) (\"from\"\n"
+                      (mapconcat
+                       (lambda (rec)
+                         (let ((score (or (bbdb-record-getprop
+                                           rec
+                                           gnus-bbdb/score-field)
+                                          gnus-bbdb/score-default))
+                               (net (bbdb-record-net rec)))
+                           (if (not (and score net)) nil
+                             (mapconcat
+                              (lambda (addr)
+                                (concat "(\"" addr "\" " score ")\n"))
+                              net ""))))
+                       (bbdb-records) "")
+                      "))"))))
+  gnus-bbdb/score-alist)
+
+(defun gnus-bbdb/extract-field-value-init ()
+  (function gnus-bbdb/extract-field-value))
+
+(defun gnus-bbdb/extract-field-value (field-name)
+  "Given the name of a field (like \"Subject\") this returns the value of
+that field in the current message, or nil.  This works whether you're in
+Semi-gnus, Rmail, or VM.  This works on multi-line fields, but if more than
+one field of the same name is present, only the last is returned.  It is
+expected that the current buffer has a message in it, and (point) is at the
+beginning of the message headers."
+  ;; we can't special-case VM here to use its cache, because the cache has
+  ;; divided real-names from addresses; the actual From: and Subject: fields
+  ;; exist only in the message.
+  (let (value)
+    (when (setq value (mime-entity-fetch-field
+                      gnus-current-headers field-name))
+      (gnus-bbdb/decode-field-body value field-name))))
+
+;;; @ mail-extr
+;;;
+
+(defvar gnus-bbdb/canonicalize-full-name-methods
+  '(gnus-bbdb/canonicalize-dots
+    gnus-bbdb/canonicalize-spaces))
+
+(defun gnus-bbdb/extract-address-components (str)
+  (let* ((ret     (std11-extract-address-components str))
+        (phrase  (car ret))
+        (address (car (cdr ret)))
+        (methods gnus-bbdb/canonicalize-full-name-methods))
+    (while (and phrase methods)
+      (setq phrase  (funcall (car methods) phrase)
+           methods (cdr methods)))
+    (if (string= address "") (setq address nil))
+    (if (string= phrase "") (setq phrase nil))
+    (when (or phrase address)
+      (list phrase address))))
+
+;;; @ full-name canonicalization methods
+;;;
+
+(defun gnus-bbdb/canonicalize-spaces (str)
+  (let (dest)
+    (while (string-match "\\s +" str)
+      (setq dest (cons (substring str 0 (match-beginning 0)) dest))
+      (setq str (substring str (match-end 0))))
+    (or (string= str "")
+       (setq dest (cons str dest)))
+    (setq dest (nreverse dest))
+    (mapconcat 'identity dest " ")))
+
+(defun gnus-bbdb/canonicalize-dots (str)
+  (let (dest)
+    (while (string-match "\\." str)
+      (setq dest (cons (substring str 0 (match-end 0)) dest))
+      (setq str (substring str (match-end 0))))
+    (or (string= str "")
+       (setq dest (cons str dest)))
+    (setq dest (nreverse dest))
+    (mapconcat 'identity dest " ")))
+
+;;
+;; Insinuation
+;;
+
+;;;###autoload
+(defun gnus-bbdb-insinuate ()
+  "Call this function to hook BBDB into Semi-gnus."
+;;  (setq gnus-optional-headers 'gnus-bbdb/lines-and-from)
+  (when (boundp 'bbdb-extract-field-value-function-list)
+    (add-to-list 'bbdb-extract-field-value-function-list
+                'gnus-bbdb/extract-field-value-init))
+  (add-hook 'gnus-article-prepare-hook 'gnus-bbdb/update-record)
+  (add-hook 'gnus-summary-exit-hook 'bbdb-flush-all-caches)
+  (add-hook 'gnus-save-newsrc-hook 'bbdb-offer-save)
+  (define-key gnus-summary-mode-map ":" 'gnus-bbdb/show-sender)
+  (define-key gnus-summary-mode-map ";" 'gnus-bbdb/edit-notes)
+
+  ;; Set up user field for use in gnus-summary-line-format
+  (let ((get-author-user-fun (intern
+                             (concat "gnus-user-format-function-"
+                                     gnus-bbdb/summary-user-format-letter)))
+       (in-bbdb-user-fun (intern
+                          (concat "gnus-user-format-function-"
+                                  gnus-bbdb/summary-in-bbdb-format-letter))))
+                                       ; The big one - whole name
+    (cond (gnus-bbdb/summary-user-format-letter
+          (if (and (fboundp get-author-user-fun)
+                   (not (eq (symbol-function get-author-user-fun)
+                            'gnus-bbdb/summary-get-author)))
+              (bbdb-warn
+               (format "`gnus-user-format-function-%s' already seems to be in use.
+Please redefine `gnus-bbdb/summary-user-format-letter' to a different letter."
+                       gnus-bbdb/summary-user-format-letter))
+            (fset get-author-user-fun 'gnus-bbdb/summary-get-author))))
+
+    ; One tick.  One tick only, please
+    (cond (gnus-bbdb/summary-in-bbdb-format-letter
+          (if (and (fboundp in-bbdb-user-fun)
+                   (not (eq (symbol-function in-bbdb-user-fun)
+                            'gnus-bbdb/summary-author-in-bbdb)))
+              (bbdb-warn
+               (format "`gnus-user-format-function-%s' already seems to be in use.
+Redefine `gnus-bbdb/summary-in-bbdb-format-letter' to a different letter."
+                       gnus-bbdb/summary-in-bbdb-format-letter))
+            (fset in-bbdb-user-fun 'gnus-bbdb/summary-author-in-bbdb)))))
+
+  ;; Scoring
+  (add-hook 'bbdb-after-change-hook 'gnus-bbdb/score-invalidate-alist)
+;  (setq gnus-score-find-score-files-function
+;      (if (boundp 'gnus-score-find-score-files-function)
+;          (cond ((functionp gnus-score-find-score-files-function)
+;                 (list gnus-score-find-score-files-function
+;                       'gnus-bbdb/score))
+;                ((listp gnus-score-find-score-files-function)
+;                 (append gnus-score-find-score-files-function
+;                         'gnus-bbdb/score))
+;                (t 'gnus-bbdb/score))
+;        'gnus-bbdb/score))
+  )
+
+;;;###autoload
+(defun gnus-bbdb-insinuate-message ()
+  "Call this function to hook BBDB into message-mode."
+  (define-key message-mode-map "\M-\t" 'bbdb-complete-name))
+
+(provide 'gnus-bbdb)
index 457770f..c2b0cc3 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-bcklg.el --- backlog functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
   "Return the backlog buffer."
   (or (get-buffer gnus-backlog-buffer)
       (save-excursion
-       (set-buffer (get-buffer-create gnus-backlog-buffer))
-       (buffer-disable-undo (current-buffer))
+       (set-buffer (gnus-get-buffer-create gnus-backlog-buffer))
+       (buffer-disable-undo)
        (setq buffer-read-only t)
-       (gnus-add-current-to-buffer-list)
        (get-buffer gnus-backlog-buffer))))
 
 (defun gnus-backlog-setup ()
 
 (defun gnus-backlog-shutdown ()
   "Clear all backlog variables and buffers."
+  (interactive)
   (when (get-buffer gnus-backlog-buffer)
-    (kill-buffer gnus-backlog-buffer))
+    (gnus-kill-buffer gnus-backlog-buffer))
   (setq gnus-backlog-hashtb nil
        gnus-backlog-articles nil))
 
 (defun gnus-backlog-enter-article (group number buffer)
-  (gnus-backlog-setup)
-  (let ((ident (intern (concat group ":" (int-to-string number))
-                      gnus-backlog-hashtb))
-       b)
-    (if (memq ident gnus-backlog-articles)
-       ()                              ; It's already kept.
-      ;; Remove the oldest article, if necessary.
-      (and (numberp gnus-keep-backlog)
-          (>= (length gnus-backlog-articles) gnus-keep-backlog)
-          (gnus-backlog-remove-oldest-article))
-      (push ident gnus-backlog-articles)
-      ;; Insert the new article.
-      (save-excursion
-       (set-buffer (gnus-backlog-buffer))
-       (let (buffer-read-only)
-         (goto-char (point-max))
-         (unless (bolp)
-           (insert "\n"))
-         (setq b (point))
-         (insert-buffer-substring buffer)
-         ;; Tag the beginning of the article with the ident.
-         (gnus-put-text-property b (1+ b) 'gnus-backlog ident))))))
+  (when (and (numberp number)
+            (not (string-match "^nnvirtual" group)))
+    (gnus-backlog-setup)
+    (let ((ident (intern (concat group ":" (int-to-string number))
+                        gnus-backlog-hashtb))
+         b)
+      (if (memq ident gnus-backlog-articles)
+         ()                            ; It's already kept.
+       ;; Remove the oldest article, if necessary.
+       (and (numberp gnus-keep-backlog)
+            (>= (length gnus-backlog-articles) gnus-keep-backlog)
+            (gnus-backlog-remove-oldest-article))
+       (push ident gnus-backlog-articles)
+       ;; Insert the new article.
+       (save-excursion
+         (set-buffer (gnus-backlog-buffer))
+         (let (buffer-read-only)
+           (goto-char (point-max))
+           (unless (bolp)
+             (insert "\n"))
+           (setq b (point))
+           (insert-buffer-substring buffer)
+           ;; Tag the beginning of the article with the ident.
+           (if (> (point-max) b)
+               (gnus-put-text-property b (1+ b) 'gnus-backlog ident)
+             (gnus-error 3 "Article %d is blank" number))))))))
 
 (defun gnus-backlog-remove-oldest-article ()
   (save-excursion
              t))
          (setq gnus-backlog-articles (delq ident gnus-backlog-articles)))))))
 
-(defun gnus-backlog-request-article (group number buffer)
-  (when (numberp number)
+(defun gnus-backlog-request-article (group number &optional buffer)
+  (when (and (numberp number)
+            (not (string-match "^nnvirtual" group)))
     (gnus-backlog-setup)
     (let ((ident (intern (concat group ":" (int-to-string number))
                         gnus-backlog-hashtb))
            (setq end
                  (next-single-property-change
                   (1+ beg) 'gnus-backlog (current-buffer) (point-max)))))
-       (let ((buffer-read-only nil))
-         (erase-buffer)
-         (insert-buffer-substring gnus-backlog-buffer beg end)
-         t)))))
+       (save-excursion
+         (and buffer (set-buffer buffer))
+         (let ((buffer-read-only nil))
+           (erase-buffer)
+           (insert-buffer-substring gnus-backlog-buffer beg end)))
+       t))))
 
 (provide 'gnus-bcklg)
 
index 3078158..0484732 100644 (file)
@@ -1,7 +1,10 @@
 ;;; gnus-cache.el --- cache interface for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
 
 (require 'gnus)
 (require 'gnus-int)
 (require 'gnus-range)
 (require 'gnus-start)
 (eval-when-compile
+  (if (not (fboundp 'gnus-agent-load-alist))
+      (defun gnus-agent-load-alist (group)))
   (require 'gnus-sum))
 
-(defgroup gnus-cache nil
-  "Cache interface."
-  :group 'gnus)
-
-(defcustom gnus-cache-directory
-  (nnheader-concat gnus-directory "cache/")
-  "*The directory where cached articles will be stored."
-  :group 'gnus-cache
-  :type 'directory)
-
 (defcustom gnus-cache-active-file
-  (concat (file-name-as-directory gnus-cache-directory) "active")
+  (expand-file-name "active" gnus-cache-directory)
   "*The cache active file."
   :group 'gnus-cache
   :type 'file)
   :group 'gnus-cache
   :type '(set (const ticked) (const dormant) (const unread) (const read)))
 
+(defcustom gnus-cacheable-groups nil
+  "*Groups that match this regexp will be cached.
+
+If you only want to cache your nntp groups, you could set this
+variable to \"^nntp\".
+
+If a group matches both gnus-cacheable-groups and gnus-uncacheable-groups
+it's not cached."
+  :group 'gnus-cache
+  :type '(choice (const :tag "off" nil)
+                regexp))
+
 (defcustom gnus-uncacheable-groups nil
   "*Groups that match this regexp will not be cached.
 
 If you want to avoid caching your nnml groups, you could set this
-variable to \"^nnml\"."
+variable to \"^nnml\".
+
+If a group matches both gnus-cacheable-groups and gnus-uncacheable-groups
+it's not cached."
   :group 'gnus-cache
   :type '(choice (const :tag "off" nil)
                 regexp))
 
+(defvar gnus-cache-overview-coding-system 'raw-text
+  "Coding system used on Gnus cache files.")
+
+(defvar gnus-cache-coding-system 'raw-text
+  "Coding system used on Gnus cache files.")
+
 \f
 
 ;;; Internal variables.
@@ -77,6 +94,7 @@ variable to \"^nnml\"."
 (defvar gnus-cache-buffer nil)
 (defvar gnus-cache-active-hashtb nil)
 (defvar gnus-cache-active-altered nil)
+(defvar gnus-cache-write-file-coding-system 'raw-text)
 
 (eval-and-compile
   (autoload 'nnml-generate-nov-databases-1 "nnml")
@@ -116,7 +134,8 @@ variable to \"^nnml\"."
          (set-buffer buffer)
          (if (> (buffer-size) 0)
              ;; Non-empty overview, write it to a file.
-             (gnus-write-buffer overview-file)
+             (gnus-write-buffer-as-coding-system
+              gnus-cache-overview-coding-system overview-file)
            ;; Empty overview file, remove it
            (when (file-exists-p overview-file)
              (delete-file overview-file))
@@ -135,38 +154,40 @@ variable to \"^nnml\"."
   (group article headers ticked dormant unread &optional force)
   (when (and (or force (not (eq gnus-use-cache 'passive)))
             (numberp article)
-            (> article 0)
-            (vectorp headers))         ; This might be a dummy article.
-    ;; If this is a virtual group, we find the real group.
-    (when (gnus-virtual-group-p group)
-      (let ((result (nnvirtual-find-group-art
-                    (gnus-group-real-name group) article)))
-       (setq group (car result)
-             headers (copy-sequence headers))
-       (mail-header-set-number headers (cdr result))))
-    (let ((number (mail-header-number headers))
-         file dir)
+            (> article 0)              ; This might be a dummy article.
+            (vectorp headers))
+    (let ((number article) file)
+      ;; If this is a virtual group, we find the real group.
+      (when (gnus-virtual-group-p group)
+       (let ((result (nnvirtual-find-group-art
+                      (gnus-group-real-name group) article)))
+         (setq group (car result)
+               number (cdr result))))
       (when (and number
                 (> number 0)           ; Reffed article.
                 (or force
-                    (and (or (not gnus-uncacheable-groups)
-                             (not (string-match
-                                   gnus-uncacheable-groups group)))
+                    (and (gnus-cache-fully-p group)
                          (gnus-cache-member-of-class
                           gnus-cache-enter-articles ticked dormant unread)))
                 (not (file-exists-p (setq file (gnus-cache-file-name
                                                 group number)))))
        ;; Possibly create the cache directory.
-       (gnus-make-directory (setq dir (file-name-directory file)))
+       (gnus-make-directory (file-name-directory file))
        ;; Save the article in the cache.
        (if (file-exists-p file)
            t                           ; The article already is saved.
          (save-excursion
            (set-buffer nntp-server-buffer)
-           (let ((gnus-use-cache nil))
+           (require 'gnus-art)
+           (let ((gnus-use-cache nil)
+                 (gnus-article-decode-hook nil))
              (gnus-request-article-this-buffer number group))
            (when (> (buffer-size) 0)
-             (gnus-write-buffer file)
+             (gnus-write-buffer-as-coding-system
+              gnus-cache-write-file-coding-system file)
+             (nnheader-remove-body)
+             (setq headers (nnheader-parse-naked-head))
+             (mail-header-set-number headers number)
              (gnus-cache-change-buffer group)
              (set-buffer (cdr gnus-cache-buffer))
              (goto-char (point-max))
@@ -188,21 +209,12 @@ variable to \"^nnml\"."
                    (beginning-of-line))
                (forward-line 1))
              (beginning-of-line)
-             ;; [number subject from date id references chars lines xref]
-             (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n"
-                             (mail-header-number headers)
-                             (mail-header-subject headers)
-                             (mail-header-from headers)
-                             (mail-header-date headers)
-                             (mail-header-id headers)
-                             (or (mail-header-references headers) "")
-                             (or (mail-header-chars headers) "")
-                             (or (mail-header-lines headers) "")
-                             (or (mail-header-xref headers) "")))
+             (nnheader-insert-nov headers)
              ;; Update the active info.
              (set-buffer gnus-summary-buffer)
-             (gnus-cache-update-active group number)
-             (push article gnus-newsgroup-cached)
+             (gnus-cache-possibly-update-active group (cons number number))
+             (setq gnus-newsgroup-cached
+                   (gnus-add-to-sorted-list gnus-newsgroup-cached article))
              (gnus-summary-update-secondary-mark article))
            t))))))
 
@@ -227,7 +239,7 @@ variable to \"^nnml\"."
 
 (defun gnus-cache-possibly-remove-articles-1 ()
   "Possibly remove some of the removable articles."
-  (unless (eq gnus-use-cache 'passive)
+  (when (gnus-cache-fully-p gnus-newsgroup-name)
     (let ((articles gnus-cache-removable-articles)
          (cache-articles gnus-newsgroup-cached)
          article)
@@ -252,7 +264,8 @@ variable to \"^nnml\"."
     (when (file-exists-p file)
       (erase-buffer)
       (gnus-kill-all-overlays)
-      (insert-file-contents file)
+      (let ((nnheader-file-coding-system gnus-cache-coding-system))
+       (nnheader-insert-file-contents file))
       t)))
 
 (defun gnus-cache-possibly-alter-active (group active)
@@ -274,9 +287,7 @@ variable to \"^nnml\"."
        ;; the normal way.
        (let ((gnus-use-cache nil))
          (gnus-retrieve-headers articles group fetch-old))
-      (let ((uncached-articles (gnus-sorted-intersection
-                               (gnus-sorted-complement articles cached)
-                               articles))
+      (let ((uncached-articles (gnus-sorted-difference articles cached))
            (cache-file (gnus-cache-file-name group ".overview"))
            type)
        ;; We first retrieve all the headers that we don't have in
@@ -298,7 +309,9 @@ variable to \"^nnml\"."
            ;; unsuccessful), so we use the cached headers exclusively.
            (set-buffer nntp-server-buffer)
            (erase-buffer)
-           (insert-file-contents cache-file)
+           (let ((nnheader-file-coding-system
+                  gnus-cache-overview-coding-system))
+             (nnheader-insert-file-contents cache-file))
            'nov)
           ((eq type 'nov)
            ;; We have both cached and uncached NOV headers, so we
@@ -319,20 +332,22 @@ Returns the list of articles entered."
   (let ((articles (gnus-summary-work-articles n))
        article out)
     (while (setq article (pop articles))
+      (gnus-summary-remove-process-mark article)
       (if (natnump article)
          (when (gnus-cache-possibly-enter-article
                 gnus-newsgroup-name article
                 (gnus-summary-article-header article)
                 nil nil nil t)
+            (setq gnus-newsgroup-undownloaded (delq article gnus-newsgroup-undownloaded))
            (push article out))
        (gnus-message 2 "Can't cache article %d" article))
-      (gnus-summary-remove-process-mark article)
+      (gnus-summary-update-download-mark article)
       (gnus-summary-update-secondary-mark article))
     (gnus-summary-next-subject 1)
     (gnus-summary-position-point)
     (nreverse out)))
 
-(defun gnus-cache-remove-article (n)
+(defun gnus-cache-remove-article (&optional n)
   "Remove the next N articles from the cache.
 If not given a prefix, use the process marked articles instead.
 Returns the list of articles removed."
@@ -342,9 +357,16 @@ Returns the list of articles removed."
        article out)
     (while articles
       (setq article (pop articles))
+      (gnus-summary-remove-process-mark article)
       (when (gnus-cache-possibly-remove-article article nil nil nil t)
+        (when gnus-newsgroup-agentized
+          (let ((alist (gnus-agent-load-alist gnus-newsgroup-name)))
+            (unless (cdr (assoc article alist))
+              (setq gnus-newsgroup-undownloaded
+                    (gnus-add-to-sorted-list 
+                     gnus-newsgroup-undownloaded article)))))
        (push article out))
-      (gnus-summary-remove-process-mark article)
+      (gnus-summary-update-download-mark article)
       (gnus-summary-update-secondary-mark article))
     (gnus-summary-next-subject 1)
     (gnus-summary-position-point)
@@ -357,15 +379,20 @@ Returns the list of articles removed."
 (defun gnus-summary-insert-cached-articles ()
   "Insert all the articles cached for this group into the current buffer."
   (interactive)
-  (let ((cached gnus-newsgroup-cached)
-       (gnus-verbose (max 6 gnus-verbose)))
-    (unless cached
-      (gnus-message 3 "No cached articles for this group"))
-    (while cached
-      (gnus-summary-goto-subject (pop cached) t))))
+  (let ((gnus-verbose (max 6 gnus-verbose)))
+    (if (not gnus-newsgroup-cached)
+       (gnus-message 3 "No cached articles for this group")
+      (gnus-summary-goto-subjects gnus-newsgroup-cached))))
 
-(defalias 'gnus-summary-limit-include-cached
-  'gnus-summary-insert-cached-articles)
+(defun gnus-summary-limit-include-cached ()
+  "Limit the summary buffer to articles that are cached."
+  (interactive)
+  (let ((gnus-verbose (max 6 gnus-verbose)))
+    (if gnus-newsgroup-cached
+       (progn
+         (gnus-summary-limit gnus-newsgroup-cached)
+         (gnus-summary-position-point))
+      (gnus-message 3 "No cached articles for this group"))))
 
 ;;; Internal functions.
 
@@ -381,8 +408,8 @@ Returns the list of articles removed."
     (save-excursion
       (setq gnus-cache-buffer
            (cons group
-                 (set-buffer (get-buffer-create " *gnus-cache-overview*"))))
-      (buffer-disable-undo (current-buffer))
+                 (set-buffer (gnus-get-buffer-create
+                              " *gnus-cache-overview*"))))
       ;; Insert the contents of this group's cache overview.
       (erase-buffer)
       (let ((file (gnus-cache-file-name group ".overview")))
@@ -400,20 +427,27 @@ Returns the list of articles removed."
       (and (not unread) (not ticked) (not dormant) (memq 'read class))))
 
 (defun gnus-cache-file-name (group article)
-  (concat (file-name-as-directory gnus-cache-directory)
-         (file-name-as-directory
-          (nnheader-translate-file-chars
-           (if (gnus-use-long-file-name 'not-cache)
-               group
-             (let ((group (nnheader-replace-chars-in-string group ?/ ?_)))
-               ;; Translate the first colon into a slash.
-               (when (string-match ":" group)
-                 (aset group (match-beginning 0) ?/))
-               (nnheader-replace-chars-in-string group ?. ?/)))))
-         (if (stringp article) article (int-to-string article))))
+  (expand-file-name
+   (if (stringp article) article (int-to-string article))
+   (file-name-as-directory
+    (expand-file-name
+     (nnheader-translate-file-chars
+      (if (gnus-use-long-file-name 'not-cache)
+         group
+       (let ((group (nnheader-replace-duplicate-chars-in-string
+                     (nnheader-replace-chars-in-string group ?/ ?_)
+                     ?. ?_)))
+         ;; Translate the first colon into a slash.
+         (when (string-match ":" group)
+           (setq group (concat (substring group 0 (match-beginning 0))
+                               "/" (substring group (match-end 0)))))
+         (nnheader-replace-chars-in-string group ?. ?/)))
+      t)
+     gnus-cache-directory))))
 
 (defun gnus-cache-update-article (group article)
   "If ARTICLE is in the cache, remove it and re-enter it."
+  (gnus-cache-change-buffer group)
   (when (gnus-cache-possibly-remove-article article nil nil nil t)
     (let ((gnus-use-cache nil))
       (gnus-cache-possibly-enter-article
@@ -444,10 +478,11 @@ Returns the list of articles removed."
        (when (or (looking-at (concat (int-to-string number) "\t"))
                  (search-forward (concat "\n" (int-to-string number) "\t")
                                  (point-max) t))
-         (delete-region (progn (beginning-of-line) (point))
-                        (progn (forward-line 1) (point)))))
-      (setq gnus-newsgroup-cached
-           (delq article gnus-newsgroup-cached))
+         (gnus-delete-line)))
+      (unless (setq gnus-newsgroup-cached
+                   (delq article gnus-newsgroup-cached))
+       (gnus-sethash gnus-newsgroup-name nil gnus-cache-active-hashtb)
+       (setq gnus-cache-active-altered t))
       (gnus-summary-update-secondary-mark article)
       t)))
 
@@ -461,20 +496,25 @@ Returns the list of articles removed."
                          (directory-files dir nil "^[0-9]+$" t))
                  '<))
       ;; Update the cache active file, just to synch more.
-      (when articles
-       (gnus-cache-update-active group (car articles) t)
-       (gnus-cache-update-active group (car (last articles))))
+      (if articles
+         (progn
+           (gnus-cache-update-active group (car articles) t)
+           (gnus-cache-update-active group (car (last articles))))
+       (when (gnus-gethash group gnus-cache-active-hashtb)
+         (gnus-sethash group nil gnus-cache-active-hashtb)
+         (setq gnus-cache-active-altered t)))
       articles)))
 
 (defun gnus-cache-braid-nov (group cached &optional file)
-  (let ((cache-buf (get-buffer-create " *gnus-cache*"))
+  (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*"))
        beg end)
     (gnus-cache-save-buffers)
     (save-excursion
       (set-buffer cache-buf)
-      (buffer-disable-undo (current-buffer))
       (erase-buffer)
-      (insert-file-contents (or file (gnus-cache-file-name group ".overview")))
+      (let ((nnheader-file-coding-system gnus-cache-overview-coding-system))
+       (nnheader-insert-file-contents
+        (or file (gnus-cache-file-name group ".overview"))))
       (goto-char (point-min))
       (insert "\n")
       (goto-char (point-min)))
@@ -485,13 +525,13 @@ Returns the list of articles removed."
                  (< (read (current-buffer)) (car cached)))
        (forward-line 1))
       (beginning-of-line)
-      (save-excursion
-       (set-buffer cache-buf)
-       (if (search-forward (concat "\n" (int-to-string (car cached)) "\t")
-                           nil t)
-           (setq beg (progn (beginning-of-line) (point))
-                 end (progn (end-of-line) (point)))
-         (setq beg nil)))
+      (set-buffer cache-buf)
+      (if (search-forward (concat "\n" (int-to-string (car cached)) "\t")
+                         nil t)
+         (setq beg (gnus-point-at-bol)
+               end (progn (end-of-line) (point)))
+       (setq beg nil))
+      (set-buffer nntp-server-buffer)
       (when beg
        (insert-buffer-substring cache-buf beg end)
        (insert "\n"))
@@ -499,10 +539,9 @@ Returns the list of articles removed."
     (kill-buffer cache-buf)))
 
 (defun gnus-cache-braid-heads (group cached)
-  (let ((cache-buf (get-buffer-create " *gnus-cache*")))
+  (let ((cache-buf (gnus-get-buffer-create " *gnus-cache*")))
     (save-excursion
       (set-buffer cache-buf)
-      (buffer-disable-undo (current-buffer))
       (erase-buffer))
     (set-buffer nntp-server-buffer)
     (goto-char (point-min))
@@ -517,7 +556,9 @@ Returns the list of articles removed."
       (save-excursion
        (set-buffer cache-buf)
        (erase-buffer)
-       (insert-file-contents (gnus-cache-file-name group (car cached)))
+       (let ((nnheader-file-coding-system gnus-cache-coding-system))
+         (nnheader-insert-file-contents
+          (gnus-cache-file-name group (car cached))))
        (goto-char (point-min))
        (insert "220 ")
        (princ (car cached) (current-buffer))
@@ -540,6 +581,7 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache"
   (let ((gnus-mark-article-hook nil)
        (gnus-expert-user t)
        (nnmail-spool-file nil)
+       (mail-sources nil)
        (gnus-use-dribble-file nil)
        (gnus-novice-user nil)
        (gnus-large-newsgroup nil))
@@ -561,14 +603,14 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache"
   "Read the cache active file."
   (gnus-make-directory gnus-cache-directory)
   (if (or (not (file-exists-p gnus-cache-active-file))
-         (not (zerop (nth 7 (file-attributes gnus-cache-active-file))))
+         (zerop (nth 7 (file-attributes gnus-cache-active-file)))
          force)
       ;; There is no active file, so we generate one.
       (gnus-cache-generate-active)
     ;; We simply read the active file.
     (save-excursion
       (gnus-set-work-buffer)
-      (insert-file-contents gnus-cache-active-file)
+      (nnheader-insert-file-contents gnus-cache-active-file)
       (gnus-active-to-gnus-format
        nil (setq gnus-cache-active-hashtb
                 (gnus-make-hashtable
@@ -580,17 +622,28 @@ $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache"
   (when (or force
            (and gnus-cache-active-hashtb
                 gnus-cache-active-altered))
-    (nnheader-temp-write gnus-cache-active-file
-      (mapatoms
-       (lambda (sym)
-        (when (and sym (boundp sym))
-          (insert (format "%s %d %d y\n"
-                          (symbol-name sym) (cdr (symbol-value sym))
-                          (car (symbol-value sym))))))
-       gnus-cache-active-hashtb))
+    (gnus-write-active-file gnus-cache-active-file gnus-cache-active-hashtb t)
     ;; Mark the active hashtb as unaltered.
     (setq gnus-cache-active-altered nil)))
 
+(defun gnus-cache-possibly-update-active (group active)
+  "Update active info bounds of GROUP with ACTIVE if necessary.
+The update is performed if ACTIVE contains a higher or lower bound
+than the current."
+  (let ((lower t) (higher t))
+    (if gnus-cache-active-hashtb
+       (let ((cache-active (gnus-gethash group gnus-cache-active-hashtb)))
+         (when cache-active
+           (unless (< (car active) (car cache-active))
+             (setq lower nil))
+           (unless (> (cdr active) (cdr cache-active))
+             (setq higher nil))))
+      (gnus-cache-read-active))
+    (when lower
+      (gnus-cache-update-active group (car active) t))
+    (when higher
+      (gnus-cache-update-active group (cdr active)))))
+
 (defun gnus-cache-update-active (group number &optional low)
   "Update the upper bound of the active info of GROUP to NUMBER.
 If LOW, update the lower bound instead."
@@ -616,8 +669,9 @@ If LOW, update the lower bound instead."
          (if top
              ""
            (string-match
-            (concat "^" (file-name-as-directory
-                         (expand-file-name gnus-cache-directory)))
+            (concat "^" (regexp-quote
+                         (file-name-as-directory
+                          (expand-file-name gnus-cache-directory))))
             (directory-file-name directory))
            (nnheader-replace-chars-in-string
             (substring (directory-file-name directory) (match-end 0))
@@ -626,6 +680,8 @@ If LOW, update the lower bound instead."
     (when top
       (gnus-message 5 "Generating the cache active file...")
       (setq gnus-cache-active-hashtb (gnus-make-hashtable 123)))
+    (when (string-match "^\\(nn[^_]+\\)_" group)
+      (setq group (replace-match "\\1:" t nil group)))
     ;; Separate articles from all other files and directories.
     (while files
       (if (string-match "^[0-9]+$" (file-name-nondirectory (car files)))
@@ -638,7 +694,7 @@ If LOW, update the lower bound instead."
     ;; Go through all the other files.
     (while alphs
       (when (and (file-directory-p (car alphs))
-                (not (string-match "^\\.\\.?$"
+                (not (string-match "^\\."
                                    (file-name-nondirectory (car alphs)))))
        ;; We descend directories.
        (gnus-cache-generate-active (car alphs)))
@@ -654,13 +710,27 @@ If LOW, update the lower bound instead."
   (interactive (list gnus-cache-directory))
   (gnus-cache-close)
   (let ((nnml-generate-active-function 'identity))
-    (nnml-generate-nov-databases-1 dir)))
+    (nnml-generate-nov-databases-1 dir))
+  (gnus-cache-open))
 
 (defun gnus-cache-move-cache (dir)
   "Move the cache tree to somewhere else."
   (interactive "FMove the cache tree to: ")
   (rename-file gnus-cache-directory dir))
 
+(defun gnus-cache-fully-p (&optional group)
+  "Returns non-nil if the cache should be fully used.
+If GROUP is non-nil, also cater to `gnus-cacheable-groups' and
+`gnus-uncacheable-groups'."
+  (and gnus-use-cache
+       (not (eq gnus-use-cache 'passive))
+       (if (null group)
+          t
+        (and (or (not gnus-cacheable-groups)
+                 (string-match gnus-cacheable-groups group))
+             (or (not gnus-uncacheable-groups)
+                 (not (string-match gnus-uncacheable-groups group)))))))
+
 (provide 'gnus-cache)
 
 ;;; gnus-cache.el ends here
index 4230388..779163a 100644 (file)
@@ -1,8 +1,9 @@
 ;;; gnus-cite.el --- parse citations in articles for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;; Keywords: news, mail
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Per Abhiddenware
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
 
 (require 'gnus)
-(require 'gnus-art)
 (require 'gnus-range)
+(require 'gnus-art)
+(require 'message)     ; for message-cite-prefix-regexp
 
 ;;; Customization:
 
   :link '(custom-manual "(gnus)Article Highlighting")
   :group 'gnus-article)
 
-(defcustom gnus-cite-reply-regexp
-  "^\\(Subject: Re\\|In-Reply-To\\|References\\):"
-  "*If headers match this regexp it is reasonable to believe that
-article has citations."
+(defcustom gnus-cited-opened-text-button-line-format "%(%{[-]%}%)\n"
+  "Format of opened cited text buttons."
   :group 'gnus-cite
   :type 'string)
 
-(defcustom gnus-cite-always-check nil
-  "Check article always for citations. Set it t to check all articles."
-  :group 'gnus-cite
-  :type '(choice (const :tag "no" nil)
-                 (const :tag "yes" t)))
-
-(defcustom gnus-cited-text-button-line-format "%(%{[...]%}%)\n"
-  "Format of cited text buttons."
+(defcustom gnus-cited-closed-text-button-line-format "%(%{[+]%}%)\n"
+  "Format of closed cited text buttons."
   :group 'gnus-cite
   :type 'string)
 
 (defcustom gnus-cited-lines-visible nil
-  "The number of lines of hidden cited text to remain visible."
+  "The number of lines of hidden cited text to remain visible.
+Or a pair (cons) of numbers which are the number of lines at the top
+and bottom of the text, respectively, to remain visible."
   :group 'gnus-cite
   :type '(choice (const :tag "none" nil)
-                integer))
+                integer
+                (cons :tag "Top and Bottom" integer integer)))
 
 (defcustom gnus-cite-parse-max-size 25000
   "Maximum article size (in bytes) where parsing citations is allowed.
@@ -70,19 +68,13 @@ Set it to nil to parse all articles."
   :type '(choice (const :tag "all" nil)
                 integer))
 
-(defcustom gnus-cite-prefix-regexp
-  "^[]>|:}+ ]*[]>|:}+]\\(.*>\\)?\\|^.*>"
-  "*Regexp matching the longest possible citation prefix on a line."
-  :group 'gnus-cite
-  :type 'regexp)
-
 (defcustom gnus-cite-max-prefix 20
   "Maximum possible length for a citation prefix."
   :group 'gnus-cite
   :type 'integer)
 
 (defcustom gnus-supercite-regexp
-  (concat "^\\(" gnus-cite-prefix-regexp "\\)? *"
+  (concat "^\\(" message-cite-prefix-regexp "\\)? *"
          ">>>>> +\"\\([^\"\n]+\\)\" +==")
   "*Regexp matching normal Supercite attribution lines.
 The first grouping must match prefixes added by other packages."
@@ -100,21 +92,44 @@ The first regexp group should match the Supercite attribution."
   :group 'gnus-cite
   :type 'integer)
 
-(defcustom gnus-cite-attribution-prefix 
-  "In article\\|in <\\|On \\(Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun\\),"
+;; Some Microsoft products put in a citation that extends to the
+;; remainder of the message:
+;;
+;;     -----Original Message-----
+;;     From: ...
+;;     To: ...
+;;     Sent: ...   [date, in non-RFC-2822 format]
+;;     Subject: ...
+;;
+;;     Cited message, with no prefixes
+;;
+;; The four headers are always the same.  But note they are prone to
+;; folding without additional indentation.
+;;
+;; Others use "----- Original Message -----" instead, and properly quote
+;; the body using "> ".  This style is handled without special cases.
+
+(defcustom gnus-cite-attribution-prefix
+  "In article\\|in <\\|On \\(Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun\\),\\|----- ?Original Message ?-----"
   "*Regexp matching the beginning of an attribution line."
   :group 'gnus-cite
   :type 'regexp)
 
 (defcustom gnus-cite-attribution-suffix
-  "\\(\\(wrote\\|writes\\|said\\|says\\|>\\)\\(:\\|\\.\\.\\.\\)\\)[ \t]*$"
+  "\\(\\(wrote\\|writes\\|said\\|says\\|>\\)\\(:\\|\\.\\.\\.\\)\\|----- ?Original Message ?-----\\)[ \t]*$"
   "*Regexp matching the end of an attribution line.
 The text matching the first grouping will be used as a button."
   :group 'gnus-cite
   :type 'regexp)
 
+(defcustom gnus-cite-unsightly-citation-regexp
+  "^-----Original Message-----\nFrom: \\(.+\n\\)+\n"
+  "Regexp matching Microsoft-type rest-of-message citations."
+  :group 'gnus-cite
+  :type 'regexp)
+
 (defface gnus-cite-attribution-face '((t
-                                      (:underline t)))
+                                      (:italic t)))
   "Face used for attribution lines.")
 
 (defcustom gnus-cite-attribution-face 'gnus-cite-attribution-face
@@ -235,8 +250,8 @@ It is merged with the face for the cited text belonging to the attribution."
 
 (defcustom gnus-cite-face-list
   '(gnus-cite-face-1 gnus-cite-face-2 gnus-cite-face-3 gnus-cite-face-4
-    gnus-cite-face-5 gnus-cite-face-6 gnus-cite-face-7 gnus-cite-face-8
-    gnus-cite-face-9 gnus-cite-face-10 gnus-cite-face-11)
+                    gnus-cite-face-5 gnus-cite-face-6 gnus-cite-face-7 gnus-cite-face-8
+                    gnus-cite-face-9 gnus-cite-face-10 gnus-cite-face-11)
   "*List of faces used for highlighting citations.
 
 When there are citations from multiple articles in the same message,
@@ -255,6 +270,22 @@ This should make it easier to see who wrote what."
   :group 'gnus-cite
   :type 'integer)
 
+(defcustom gnus-cite-blank-line-after-header t
+  "If non-nil, put a blank line between the citation header and the button."
+  :group 'gnus-cite
+  :type 'boolean)
+
+;; This has to go here because its default value depends on
+;; gnus-cite-face-list.
+(defcustom gnus-article-boring-faces (cons 'gnus-signature-face
+                                          gnus-cite-face-list)
+  "List of faces that are not worth reading.
+If an article has more pages below the one you are looking at, but
+nothing on those pages is a word of at least three letters that is not
+in a boring face, then the pages will be skipped."
+  :type '(repeat face)
+  :group 'gnus-article-hiding)
+
 ;;; Internal Variables:
 
 (defvar gnus-cite-article nil)
@@ -281,11 +312,16 @@ This should make it easier to see who wrote what."
 ;; PREFIX: Is the citation prefix of the attribution line(s), and
 ;; TAG: Is a Supercite tag, if any.
 
-(defvar gnus-cited-text-button-line-format-alist
+(defvar gnus-cited-opened-text-button-line-format-alist
   `((?b (marker-position beg) ?d)
     (?e (marker-position end) ?d)
+    (?n (count-lines beg end) ?d)
     (?l (- end beg) ?d)))
-(defvar gnus-cited-text-button-line-format-spec nil)
+(defvar gnus-cited-opened-text-button-line-format-spec nil)
+(defvar gnus-cited-closed-text-button-line-format-alist
+  gnus-cited-opened-text-button-line-format-alist)
+(defvar gnus-cited-closed-text-button-line-format-spec nil)
+
 
 ;;; Commands:
 
@@ -297,7 +333,7 @@ Attribution lines are highlighted with the same face as the
 corresponding citation merged with `gnus-cite-attribution-face'.
 
 Text is considered cited if at least `gnus-cite-minimum-match-count'
-lines matches `gnus-cite-prefix-regexp' with the same prefix.
+lines matches `message-cite-prefix-regexp' with the same prefix.
 
 Lines matching `gnus-cite-attribution-suffix' and perhaps
 `gnus-cite-attribution-prefix' are considered attribution lines."
@@ -335,9 +371,10 @@ Lines matching `gnus-cite-attribution-suffix' and perhaps
              skip (gnus-cite-find-prefix number)
              face (cdr (assoc prefix face-alist)))
        ;; Add attribution button.
-       (goto-line number)
+       (goto-char (point-min))
+       (forward-line (1- number))
        (when (re-search-forward gnus-cite-attribution-suffix
-                                (save-excursion (end-of-line 1) (point))
+                                (gnus-point-at-eol)
                                 t)
          (gnus-article-add-button (match-beginning 1) (match-end 1)
                                   'gnus-cite-toggle prefix))
@@ -357,7 +394,7 @@ Lines matching `gnus-cite-attribution-suffix' and perhaps
   "Dissect the article buffer looking for cited text."
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (gnus-cite-parse-maybe)
+    (gnus-cite-parse-maybe nil t)
     (let ((alist gnus-cite-prefix-alist)
          prefix numbers number marks m)
       ;; Loop through citation prefixes.
@@ -376,8 +413,7 @@ Lines matching `gnus-cite-attribution-suffix' and perhaps
          (forward-line (1- number))
          (push (cons (point-marker) prefix) marks)))
       ;; Skip to the beginning of the body.
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
+      (article-goto-body)
       (push (cons (point-marker) "") marks)
       ;; Find the end of the body.
       (goto-char (point-max))
@@ -427,11 +463,13 @@ If WIDTH (the numerical prefix), use that text width when filling."
          (fill-column (if width (prefix-numeric-value width) fill-column)))
       (save-restriction
        (while (cdr marks)
-         (widen)
          (narrow-to-region (caar marks) (caadr marks))
          (let ((adaptive-fill-regexp
                 (concat "^" (regexp-quote (cdar marks)) " *"))
-               (fill-prefix (cdar marks)))
+               (fill-prefix
+                (if (string= (cdar marks) "") ""
+                  (concat (cdar marks) " ")))
+               use-hard-newlines)
            (fill-region (point-min) (point-max)))
          (set-marker (caar marks) nil)
          (setq marks (cdr marks)))
@@ -450,22 +488,29 @@ See the documentation for `gnus-article-highlight-citation'.
 If given a negative prefix, always show; if given a positive prefix,
 always hide."
   (interactive (append (gnus-article-hidden-arg) (list 'force)))
-  (gnus-set-format 'cited-text-button t)
+  (gnus-set-format 'cited-opened-text-button t)
+  (gnus-set-format 'cited-closed-text-button t)
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (cond
-     ((gnus-article-check-hidden-text 'cite arg)
-      t)
-     ((gnus-article-text-type-exists-p 'cite)
-      (let ((buffer-read-only nil))
-       (gnus-article-hide-text-of-type 'cite)))
-     (t
-      (let ((buffer-read-only nil)
-           (marks (gnus-dissect-cited-text))
-           (inhibit-point-motion-hooks t)
-           (props (nconc (list 'article-type 'cite)
-                         gnus-hidden-properties))
-           beg end)
+    (let ((buffer-read-only nil)
+         marks
+         (inhibit-point-motion-hooks t)
+         (props (nconc (list 'article-type 'cite)
+                       gnus-hidden-properties))
+         (point (point-min))
+         found beg end start)
+      (while (setq point
+                  (text-property-any point (point-max)
+                                     'gnus-callback
+                                     'gnus-article-toggle-cited-text))
+       (setq found t)
+       (goto-char point)
+       (gnus-article-toggle-cited-text
+        (get-text-property point 'gnus-data) arg)
+       (forward-line 1)
+       (setq point (point)))
+      (unless found
+       (setq marks (gnus-dissect-cited-text))
        (while marks
          (setq beg nil
                end nil)
@@ -480,39 +525,90 @@ always hide."
          ;; Skip past lines we want to leave visible.
          (when (and beg end gnus-cited-lines-visible)
            (goto-char beg)
-           (forward-line gnus-cited-lines-visible)
+           (forward-line (if (consp gnus-cited-lines-visible)
+                             (car gnus-cited-lines-visible)
+                           gnus-cited-lines-visible))
            (if (>= (point) end)
                (setq beg nil)
-             (setq beg (point-marker))))
+             (setq beg (point-marker))
+             (when (consp gnus-cited-lines-visible)
+               (goto-char end)
+               (forward-line (- (cdr gnus-cited-lines-visible)))
+               (if (<= (point) beg)
+                   (setq beg nil)
+                 (setq end (point-marker))))))
          (when (and beg end)
-           (gnus-add-text-properties beg end props)
+           (gnus-add-wash-type 'cite)
+           ;; We use markers for the end-points to facilitate later
+           ;; wrapping and mangling of text.
+           (setq beg (set-marker (make-marker) beg)
+                 end (set-marker (make-marker) end))
+           (gnus-add-text-properties-when 'article-type nil beg end props)
            (goto-char beg)
-           (unless (save-excursion (search-backward "\n\n" nil t))
+           (when (and gnus-cite-blank-line-after-header
+                      (not (save-excursion (search-backward "\n\n" nil t))))
              (insert "\n"))
            (put-text-property
-            (point)
+            (setq start (point-marker))
             (progn
               (gnus-article-add-button
                (point)
-               (progn (eval gnus-cited-text-button-line-format-spec) (point))
+               (progn (eval gnus-cited-closed-text-button-line-format-spec)
+                      (point))
                `gnus-article-toggle-cited-text
-               ;; We use markers for the end-points to facilitate later
-               ;; wrapping and mangling of text.
-               (cons (set-marker (make-marker) beg)
-                     (set-marker (make-marker) end)))
+               (list (cons beg end) start))
               (point))
             'article-type 'annotation)
-           (set-marker beg (point)))))))))
-
-(defun gnus-article-toggle-cited-text (region)
-  "Toggle hiding the text in REGION."
-  (let (buffer-read-only)
-    (funcall 
-     (if (text-property-any
-         (car region) (1- (cdr region))
-         (car gnus-hidden-properties) (cadr gnus-hidden-properties))
-        'remove-text-properties 'gnus-add-text-properties)
-     (car region) (cdr region) gnus-hidden-properties)))
+           (set-marker beg (point))))))))
+
+(defun gnus-article-toggle-cited-text (args &optional arg)
+  "Toggle hiding the text in REGION.
+ARG can be nil or a number.  Positive means hide, negative
+means show, nil means toggle."
+  (let* ((region (car args))
+        (beg (car region))
+        (end (cdr region))
+        (start (cadr args))
+        (hidden
+         (text-property-any beg (1- end) 'article-type 'cite))
+        (inhibit-point-motion-hooks t)
+        buffer-read-only)
+    (when (or (null arg)
+             (zerop arg)
+             (and (> arg 0) (not hidden))
+             (and (< arg 0) hidden))
+      (if hidden
+         (progn
+           ;; Can't remove 'cite from g-a-wash-types here because
+           ;; multiple citations may be hidden -jas
+           (gnus-remove-text-properties-when
+            'article-type 'cite beg end
+            (cons 'article-type (cons 'cite
+                                      gnus-hidden-properties))))
+       (gnus-add-wash-type 'cite)
+       (gnus-add-text-properties-when
+        'article-type nil beg end
+        (cons 'article-type (cons 'cite
+                                  gnus-hidden-properties))))
+      (let ((gnus-article-mime-handle-alist-1 gnus-article-mime-handle-alist))
+       (gnus-set-mode-line 'article))
+      (save-excursion
+       (goto-char start)
+       (gnus-delete-line)
+       (put-text-property
+        (point)
+        (progn
+          (gnus-article-add-button
+           (point)
+           (progn (eval
+                   (if hidden
+                       gnus-cited-opened-text-button-line-format-spec
+                     gnus-cited-closed-text-button-line-format-spec))
+                  (point))
+           `gnus-article-toggle-cited-text
+           args)
+          (point))
+        'article-type 'annotation)))))
 
 (defun gnus-article-hide-citation-maybe (&optional arg force)
   "Toggle hiding of cited text that has an attribution line.
@@ -524,41 +620,44 @@ cited text with attributions.  When called interactively, these two
 variables are ignored.
 See also the documentation for `gnus-article-highlight-citation'."
   (interactive (append (gnus-article-hidden-arg) '(force)))
-  (unless (gnus-article-check-hidden-text 'cite arg)
-    (save-excursion
-      (set-buffer gnus-article-buffer)
-      (gnus-cite-parse-maybe force)
-      (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (let ((start (point))
-           (atts gnus-cite-attribution-alist)
-           (buffer-read-only nil)
-           (inhibit-point-motion-hooks t)
-           (hiden 0)
-           total)
-       (goto-char (point-max))
-       (gnus-article-search-signature)
-       (setq total (count-lines start (point)))
-       (while atts
-         (setq hiden (+ hiden (length (cdr (assoc (cdar atts)
-                                                  gnus-cite-prefix-alist))))
-               atts (cdr atts)))
-       (when (or force
-                 (and (> (* 100 hiden) (* gnus-cite-hide-percentage total))
-                      (> hiden gnus-cite-hide-absolute)))
-         (setq atts gnus-cite-attribution-alist)
+  (with-current-buffer gnus-article-buffer
+    (gnus-delete-wash-type 'cite)
+    (unless (gnus-article-check-hidden-text 'cite arg)
+      (save-excursion
+       (gnus-cite-parse-maybe force)
+       (article-goto-body)
+       (let ((start (point))
+             (atts gnus-cite-attribution-alist)
+             (buffer-read-only nil)
+             (inhibit-point-motion-hooks t)
+             (hidden 0)
+             total)
+         (goto-char (point-max))
+         (gnus-article-search-signature)
+         (setq total (count-lines start (point)))
          (while atts
-           (setq total (cdr (assoc (cdar atts) gnus-cite-prefix-alist))
-                 atts (cdr atts))
-           (while total
-             (setq hiden (car total)
-                   total (cdr total))
-             (goto-line hiden)
-             (unless (assq hiden gnus-cite-attribution-alist)
-               (gnus-add-text-properties
-                (point) (progn (forward-line 1) (point))
-                (nconc (list 'article-type 'cite)
-                       gnus-hidden-properties))))))))))
+           (setq hidden (+ hidden (length (cdr (assoc (cdar atts)
+                                                      gnus-cite-prefix-alist))))
+                 atts (cdr atts)))
+         (when (or force
+                   (and (> (* 100 hidden) (* gnus-cite-hide-percentage total))
+                        (> hidden gnus-cite-hide-absolute)))
+           (gnus-add-wash-type 'cite)
+           (setq atts gnus-cite-attribution-alist)
+           (while atts
+             (setq total (cdr (assoc (cdar atts) gnus-cite-prefix-alist))
+                   atts (cdr atts))
+             (while total
+               (setq hidden (car total)
+                     total (cdr total))
+               (goto-char (point-min))
+               (forward-line (1- hidden))
+               (unless (assq hidden gnus-cite-attribution-alist)
+                 (gnus-add-text-properties
+                  (point) (progn (forward-line 1) (point))
+                  (nconc (list 'article-type 'cite)
+                         gnus-hidden-properties)))))))))
+    (gnus-set-mode-line 'article)))
 
 (defun gnus-article-hide-citation-in-followups ()
   "Hide cited text in non-root articles."
@@ -573,45 +672,44 @@ See also the documentation for `gnus-article-highlight-citation'."
 
 ;;; Internal functions:
 
-(defun gnus-cite-parse-maybe (&optional force)
-  ;; Parse if the buffer has changes since last time.
-  (if (and (not force)
-          (equal gnus-cite-article gnus-article-current))
+(defun gnus-cite-parse-maybe (&optional force no-overlay)
+  "Always parse the buffer."
+  (gnus-cite-localize)
+  ;;Reset parser information.
+  (setq gnus-cite-prefix-alist nil
+       gnus-cite-attribution-alist nil
+       gnus-cite-loose-prefix-alist nil
+       gnus-cite-loose-attribution-alist nil)
+  (unless no-overlay
+    (gnus-cite-delete-overlays))
+  ;; Parse if not too large.
+  (if (and gnus-cite-parse-max-size
+          (> (buffer-size) gnus-cite-parse-max-size))
       ()
-    (gnus-cite-localize)
-    ;;Reset parser information.
-    (setq gnus-cite-prefix-alist nil
-         gnus-cite-attribution-alist nil
-         gnus-cite-loose-prefix-alist nil
-         gnus-cite-loose-attribution-alist nil)
-    (while gnus-cite-overlay-list
-      (gnus-delete-overlay (pop gnus-cite-overlay-list)))
-    ;; Parse if not too large.
-    (if (and (not force)
-            gnus-cite-parse-max-size
-            (> (buffer-size) gnus-cite-parse-max-size))
-       ()
-      (setq gnus-cite-article (cons (car gnus-article-current)
-                                   (cdr gnus-article-current)))
-      (gnus-cite-parse-wrapper))))
+    (setq gnus-cite-article (cons (car gnus-article-current)
+                                 (cdr gnus-article-current)))
+    (gnus-cite-parse-wrapper)))
+
+(defun gnus-cite-delete-overlays ()
+  (dolist (overlay gnus-cite-overlay-list)
+    (ignore-errors
+      (when (or (not (gnus-overlay-end overlay))
+               (and (>= (gnus-overlay-end overlay) (point-min))
+                    (<= (gnus-overlay-end overlay) (point-max))))
+       (setq gnus-cite-overlay-list (delete overlay gnus-cite-overlay-list))
+       (ignore-errors
+         (gnus-delete-overlay overlay))))))
 
 (defun gnus-cite-parse-wrapper ()
-  ;; Wrap chopped gnus-cite-parse
-  (goto-char (point-min))
-  (unless (search-forward "\n\n" nil t)
-    (goto-char (point-max)))
-  (save-excursion
-    (gnus-cite-parse-attributions))
-  ;; Try to avoid check citation if there is no reason to believe
-  ;; that article has citations
-  (if (or gnus-cite-always-check
-         (save-excursion
-           (re-search-backward gnus-cite-reply-regexp nil t))
-         gnus-cite-loose-attribution-alist)
-      (progn (save-excursion
-              (gnus-cite-parse))
-            (save-excursion
-              (gnus-cite-connect-attributions)))))
+  ;; Wrap chopped gnus-cite-parse.
+  (article-goto-body)
+  (let ((inhibit-point-motion-hooks t))
+    (save-excursion
+      (gnus-cite-parse-attributions))
+    (save-excursion
+      (gnus-cite-parse))
+    (save-excursion
+      (gnus-cite-connect-attributions))))
 
 (defun gnus-cite-parse ()
   ;; Parse and connect citation prefixes and attribution lines.
@@ -623,23 +721,26 @@ See also the documentation for `gnus-article-highlight-citation'."
               (goto-char (point-max))
               (gnus-article-search-signature)
               (point)))
-       alist entry start begin end numbers prefix)
+       (prefix-regexp (concat "^\\(" message-cite-prefix-regexp "\\)"))
+       alist entry start begin end numbers prefix guess-limit mc-flag)
     ;; Get all potential prefixes in `alist'.
     (while (< (point) max)
       ;; Each line.
       (setq begin (point)
-           end (progn (beginning-of-line 2) (point))
+           guess-limit (progn (skip-chars-forward "^> \t\r\n") (point))
+           end (gnus-point-at-bol 2)
            start end)
       (goto-char begin)
       ;; Ignore standard Supercite attribution prefix.
-      (when (looking-at gnus-supercite-regexp)
+      (when (and (< guess-limit (+ begin gnus-cite-max-prefix))
+                (looking-at gnus-supercite-regexp))
        (if (match-end 1)
            (setq end (1+ (match-end 1)))
          (setq end (1+ begin))))
       ;; Ignore very long prefixes.
-      (when (> end (+ (point) gnus-cite-max-prefix))
-       (setq end (+ (point) gnus-cite-max-prefix)))
-      (while (re-search-forward gnus-cite-prefix-regexp (1- end) t)
+      (when (> end (+ begin gnus-cite-max-prefix))
+       (setq end (+ begin gnus-cite-max-prefix)))
+      (while (re-search-forward prefix-regexp (1- end) t)
        ;; Each prefix.
        (setq end (match-end 0)
              prefix (buffer-substring begin end))
@@ -651,9 +752,19 @@ See also the documentation for `gnus-article-highlight-citation'."
        (goto-char begin))
       (goto-char start)
       (setq line (1+ line)))
+    ;; Horrible special case for some Microsoft mailers.
+    (goto-char (point-min))
+    (when (re-search-forward gnus-cite-unsightly-citation-regexp max t)
+      (setq begin (count-lines (point-min) (point)))
+      (setq end (count-lines (point-min) max))
+      (setq entry nil)
+      (while (< begin end)
+       (push begin entry)
+       (setq begin (1+ begin)))
+      (push (cons "" entry) alist))
     ;; We got all the potential prefixes.  Now create
     ;; `gnus-cite-prefix-alist' containing the oldest prefix for each
-    ;; line that appears at least gnus-cite-minimum-match-count
+    ;; line that appears at least `gnus-cite-minimum-match-count'
     ;; times.  First sort them by length.  Longer is older.
     (setq alist (sort alist (lambda (a b)
                              (> (length (car a)) (length (car b))))))
@@ -866,9 +977,14 @@ See also the documentation for `gnus-article-highlight-citation'."
   (when face
     (let ((inhibit-point-motion-hooks t)
          from to overlay)
-      (goto-line number)
-      (unless (eobp)                   ; Sometimes things become confused.
-       (forward-char (length prefix))
+      (goto-char (point-min))
+      (when (zerop (forward-line (1- number)))
+       (static-if (or (featurep 'xemacs)
+                      (and (eq emacs-major-version 20)
+                           (>= emacs-minor-version 3))
+                      (>= emacs-major-version 21))
+           (forward-char (length prefix))
+         (move-to-column (string-width prefix)))
        (skip-chars-forward " \t")
        (setq from (point))
        (end-of-line 1)
@@ -882,7 +998,7 @@ See also the documentation for `gnus-article-highlight-citation'."
 (defun gnus-cite-toggle (prefix)
   (save-excursion
     (set-buffer gnus-article-buffer)
-    (gnus-cite-parse-maybe)
+    (gnus-cite-parse-maybe nil t)
     (let ((buffer-read-only nil)
          (numbers (cdr (assoc prefix gnus-cite-prefix-alist)))
          (inhibit-point-motion-hooks t)
@@ -890,16 +1006,23 @@ See also the documentation for `gnus-article-highlight-citation'."
       (while numbers
        (setq number (car numbers)
              numbers (cdr numbers))
-       (goto-line number)
+       (goto-char (point-min))
+       (forward-line (1- number))
        (cond ((get-text-property (point) 'invisible)
+              ;; Can't remove 'cite from g-a-wash-types here because
+              ;; multiple citations may be hidden -jas
               (remove-text-properties (point) (progn (forward-line 1) (point))
                                       gnus-hidden-properties))
              ((assq number gnus-cite-attribution-alist))
              (t
+              (gnus-add-wash-type 'cite)
               (gnus-add-text-properties
                (point) (progn (forward-line 1) (point))
                (nconc (list 'article-type 'cite)
-                      gnus-hidden-properties))))))))
+                      gnus-hidden-properties))))
+       (let ((gnus-article-mime-handle-alist-1
+              gnus-article-mime-handle-alist))
+         (gnus-set-mode-line 'article))))))
 
 (defun gnus-cite-find-prefix (line)
   ;; Return citation prefix for LINE.
@@ -922,8 +1045,23 @@ See also the documentation for `gnus-article-highlight-citation'."
     (while vars
       (make-local-variable (pop vars)))))
 
+(defun gnus-cited-line-p ()
+  "Say whether the current line is a cited line."
+  (save-excursion
+    (beginning-of-line)
+    (let ((found nil))
+      (dolist (prefix (mapcar 'car gnus-cite-prefix-alist))
+       (when (string= (buffer-substring (point) (+ (length prefix) (point)))
+                      prefix)
+         (setq found t)))
+      found)))
+
 (gnus-ems-redefine)
 
 (provide 'gnus-cite)
 
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
 ;;; gnus-cite.el ends here
diff --git a/lisp/gnus-clfns.el b/lisp/gnus-clfns.el
new file mode 100644 (file)
index 0000000..db33634
--- /dev/null
@@ -0,0 +1,432 @@
+;;; gnus-clfns.el --- compiler macros for emulating cl functions
+
+;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Kastsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: cl, compile
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This module is for mainly avoiding cl runtime functions in FSF
+;; Emacsen.  Function should also be defined as an ordinary function
+;; if it will not be provided in cl.
+
+;;; Code:
+
+(if (featurep 'xemacs)
+    nil
+  (eval-when-compile (require 'cl))
+  (require 'pym)
+
+  (define-compiler-macro butlast (&whole form x &optional n)
+    (if (>= emacs-major-version 21)
+       form
+      (if n
+         `(let ((x ,x)
+                (n ,n))
+            (if (and n (<= n 0))
+                x
+              (let ((m (length x)))
+                (or n (setq n 1))
+                (and (< n m)
+                     (progn
+                       (if (> n 0)
+                           (progn
+                             (setq x (copy-sequence x))
+                             (setcdr (nthcdr (- (1- m) n) x) nil)))
+                       x)))))
+       `(let* ((x ,x)
+               (m (length x)))
+          (and (< 1 m)
+               (progn
+                 (setq x (copy-sequence x))
+                 (setcdr (nthcdr (- m 2) x) nil)
+                 x))))))
+
+;;  (define-compiler-macro coerce (&whole form x type)
+;;    (if (and (fboundp 'coerce)
+;;          (subrp (symbol-function 'coerce)))
+;;     form
+;;      `(let ((x ,x)
+;;          (type ,type))
+;;      (cond ((eq type 'list) (if (listp x) x (append x nil)))
+;;            ((eq type 'vector) (if (vectorp x) x (vconcat x)))
+;;            ((eq type 'string) (if (stringp x) x (concat x)))
+;;            ((eq type 'array) (if (arrayp x) x (vconcat x)))
+;;            ((and (eq type 'character) (stringp x) (= (length x) 1))
+;;             (aref x 0))
+;;            ((and (eq type 'character) (symbolp x)
+;;                  (= (length (symbol-name x)) 1))
+;;             (aref (symbol-name x) 0))
+;;            ((eq type 'float) (float x))
+;;            ((typep x type) x)
+;;            (t (error "Can't coerce %s to type %s" x type))))))
+
+;;  (define-compiler-macro copy-list (&whole form list)
+;;    (if (and (fboundp 'copy-list)
+;;          (subrp (symbol-function 'copy-list)))
+;;     form
+;;      `(let ((list ,list))
+;;      (if (consp list)
+;;          (let ((res nil))
+;;            (while (consp list) (push (pop list) res))
+;;            (prog1 (nreverse res) (setcdr res list)))
+;;        (car list)))))
+
+  (define-compiler-macro last (&whole form x &optional n)
+    (if (>= emacs-major-version 20)
+       form
+      (if n
+         `(let* ((x ,x)
+                 (n ,n)
+                 (m 0)
+                 (p x))
+            (while (consp p)
+              (incf m)
+              (pop p))
+            (if (<= n 0)
+                p
+              (if (< n m)
+                  (nthcdr (- m n) x)
+                x)))
+       `(let ((x ,x))
+          (while (consp (cdr x))
+            (pop x))
+          x))))
+
+  (define-compiler-macro mapc (&whole form fn seq &rest rest)
+    (if (>= emacs-major-version 21)
+       form
+      (if rest
+         `(let* ((fn ,fn)
+                 (seq ,seq)
+                 (args (list seq ,@rest))
+                 (m (apply (function min) (mapcar (function length) args)))
+                 (n 0))
+            (while (< n m)
+              (apply fn (mapcar (function (lambda (arg) (nth n arg))) args))
+              (setq n (1+ n)))
+            seq)
+       `(let ((seq ,seq))
+          (mapcar ,fn seq)
+          seq))))
+
+;;  (define-compiler-macro merge (&whole form type seq1 seq2 pred &rest keys)
+;;    (if (and (fboundp 'merge)
+;;          (subrp (symbol-function 'merge)))
+;;     form
+;;      `(let ((type ,type)
+;;          (seq1 ,seq1)
+;;          (seq2 ,seq2)
+;;          (pred ,pred))
+;;      (or (listp seq1) (setq seq1 (append seq1 nil)))
+;;      (or (listp seq2) (setq seq2 (append seq2 nil)))
+;;      (let ((res nil))
+;;        (while (and seq1 seq2)
+;;          (if (funcall pred (car seq2) (car seq1))
+;;              (push (pop seq2) res)
+;;            (push (pop seq1) res)))
+;;        (coerce (nconc (nreverse res) seq1 seq2) type)))))
+
+;;  (define-compiler-macro string (&whole form &rest args)
+;;    (if (>= emacs-major-version 20)
+;;     form
+;;      (list 'concat (cons 'list args))))
+
+;;  (defun-maybe string (&rest args)
+;;    "Concatenate all the argument characters and make the result a string."
+;;    (concat args))
+
+  (define-compiler-macro string-to-list (&whole form string)
+    (cond ((fboundp 'string-to-list)
+          form)
+         ((fboundp 'string-to-char-list)
+          (list 'string-to-char-list string))
+         (t
+          `(let* ((str ,string)
+                  (len (length str))
+                  (idx 0)
+                  c l)
+             (while (< idx len)
+               (setq c (sref str idx))
+               (setq idx (+ idx (char-bytes c)))
+               (setq l (cons c l)))
+             (nreverse l)))))
+
+  ;; 92.7.2 by K.Handa (imported from Mule 2.3)
+  (defun-maybe string-to-list (str)
+    (let ((len (length str))
+         (idx 0)
+         c l)
+      (while (< idx len)
+       (setq c (sref str idx))
+       (setq idx (+ idx (char-bytes c)))
+       (setq l (cons c l)))
+      (nreverse l)))
+
+;;  (define-compiler-macro subseq (&whole form seq start &optional end)
+;;    (if (and (fboundp 'subseq)
+;;          (subrp (symbol-function 'subseq)))
+;;     form
+;;      (if end
+;;       `(let ((seq ,seq)
+;;              (start ,start)
+;;              (end ,end))
+;;          (if (stringp seq)
+;;              (substring seq start end)
+;;            (let (len)
+;;              (if (< end 0)
+;;                  (setq end (+ end (setq len (length seq)))))
+;;              (if (< start 0)
+;;                  (setq start (+ start (or len (setq len (length seq))))))
+;;              (cond ((listp seq)
+;;                     (if (> start 0)
+;;                         (setq seq (nthcdr start seq)))
+;;                     (let ((res nil))
+;;                       (while (>= (setq end (1- end)) start)
+;;                         (push (pop seq) res))
+;;                       (nreverse res)))
+;;                    (t
+;;                     (let ((res (make-vector (max (- end start) 0) nil))
+;;                           (i 0))
+;;                       (while (< start end)
+;;                         (aset res i (aref seq start))
+;;                         (setq i (1+ i)
+;;                               start (1+ start)))
+;;                       res))))))
+;;     `(let ((seq ,seq)
+;;            (start ,start))
+;;        (if (stringp seq)
+;;            (substring seq start)
+;;          (let (len)
+;;            (if (< start 0)
+;;                (setq start (+ start (or len (setq len (length seq))))))
+;;            (cond ((listp seq)
+;;                   (if (> start 0)
+;;                       (setq seq (nthcdr start seq)))
+;;                   (copy-sequence seq))
+;;                  (t
+;;                   (let* ((end (or len (length seq)))
+;;                          (res (make-vector (max (- end start) 0) nil))
+;;                          (i 0))
+;;                     (while (< start end)
+;;                       (aset res i (aref seq start))
+;;                       (setq i (1+ i)
+;;                             start (1+ start)))
+;;                     res)))))))))
+  )
+
+;; A tool for the developers.
+
+(defvar cl-run-time-functions
+  '(Values
+    Values-list acons assoc-if assoc-if-not build-klist butlast ceiling*
+    coerce common-lisp-indent-function compiler-macroexpand concatenate
+    copy-list count count-if count-if-not delete* delete-duplicates delete-if
+    delete-if-not duplicate-symbols-p elt-satisfies-test-p equalp evenp every
+    extract-from-klist fill find find-if find-if-not floatp-safe floor* gcd
+    gensym gentemp get-setf-method getf hash-table-count hash-table-p
+    intersection isqrt keyword-argument-supplied-p keyword-of keywordp last
+    lcm ldiff lisp-indent-259 lisp-indent-do lisp-indent-function-lambda-hack
+    lisp-indent-report-bad-format lisp-indent-tagbody list-length
+    make-hash-table make-random-state map mapc mapcan mapcar* mapcon mapl
+    maplist member-if member-if-not merge mismatch mod* nbutlast nintersection
+    notany notevery nreconc nset-difference nset-exclusive-or nsublis nsubst
+    nsubst-if nsubst-if-not nsubstitute nsubstitute-if nsubstitute-if-not
+    nunion oddp pair-with-newsyms pairlis position position-if position-if-not
+    proclaim random* random-state-p rassoc* rassoc-if rassoc-if-not
+    reassemble-argslists reduce rem* remove remove* remove-duplicates
+    remove-if remove-if-not remq replace revappend round* safe-idiv search
+    set-difference set-exclusive-or setelt setnth setnthcdr signum some sort*
+    stable-sort sublis subseq subsetp subst subst-if subst-if-not substitute
+    substitute-if substitute-if-not tailp tree-equal truncate* union
+    unzip-lists zip-lists)
+  "A list of CL run-time functions.  Some functions were built-in, nowadays.")
+
+;;;###autoload
+(defun find-cl-run-time-functions (file-or-directory arg)
+  "Find CL run-time functions in the FILE-OR-DIRECTORY.  You can alter
+the behavior of this command with the prefix ARG as described below.
+
+By default, it searches for all the CL run-time functions listed in
+ the variable `cl-run-time-functions'.
+With 1 or 3 \\[universal-argument]'s, the built-in functions in this Emacs\
+ will not be
+ reported.
+With 2 or 3 \\[universal-argument]'s, just the symbols will also be reported.
+
+You can use the `digit-argument' 1, 2 or 3 instead of\
+ \\[universal-argument]'s."
+  (interactive (list (read-file-name "Find CL run-time functions in: "
+                                    nil default-directory t)
+                    current-prefix-arg))
+  (unless (interactive-p)
+    (error "You should invoke `M-x find-cl-run-time-functions' interactively"))
+  (let ((report-symbols (member arg '((16) (64) 2 3)))
+       files clfns working file lines form forms fns fn newform buffer
+       window scroll
+       buffer-file-format format-alist
+       insert-file-contents-post-hook insert-file-contents-pre-hook)
+    (cond ((file-directory-p file-or-directory)
+          (setq files (directory-files file-or-directory t "\\.el$"))
+          (dolist (file files)
+            (unless (file-exists-p file)
+              (setq files (delete file files))))
+          (unless files
+            (message "No files found in: %s" file-or-directory))
+          files)
+         ((file-exists-p file-or-directory)
+          (setq files (list file-or-directory)))
+         (t
+          (message "No such file or directory: %s" file-or-directory)))
+    (when files
+      (if (member arg '((4) (64) 1 3))
+         (dolist (fn cl-run-time-functions)
+           (unless (and (fboundp fn)
+                        (subrp (symbol-function fn)))
+             (push fn clfns)))
+       (setq clfns cl-run-time-functions))
+      (set-buffer (setq working
+                       (get-buffer-create
+                        " *Searching for CL run-time functions*")))
+      (let (emacs-lisp-mode-hook)
+       (emacs-lisp-mode))
+      (while files
+       (setq file (pop files)
+             lines (list nil nil))
+       (message "Searching for CL run-time functions in: %s..."
+                (file-name-nondirectory file))
+       (insert-file-contents file nil nil nil t)
+       ;; XEmacs moves point to the beginning of the buffer after
+       ;; inserting a file, FSFmacs doesn't so if the fifth argument
+       ;; of `insert-file-contents' is specified.
+       (goto-char (point-min))
+       ;;
+       (while (progn
+                (while (and (looking-at "[\t\v\f\r ]*\\(;.*\\)?$")
+                            (zerop (forward-line 1))))
+                (not (eobp)))
+         (setcar lines (if (bolp)
+                           (1+ (count-lines (point-min) (point)))
+                         (count-lines (point-min) (point))))
+         (when (consp;; Ignore stand-alone symbols, strings, etc.
+                (setq form (condition-case nil
+                               (read working)
+                             (error nil))))
+           (setcdr lines (list (count-lines (point-min) (point))))
+           (setq forms (list form)
+                 fns nil)
+           (while forms
+             (setq form (pop forms))
+             (when (consp form)
+               (setq fn (pop form))
+               (cond ((memq fn '(apply mapatoms mapcar mapconcat
+                                       mapextent symbol-function))
+                      (if (consp (car form))
+                          (when (memq (caar form) '(\` backquote quote))
+                            (setcar form (cdar form)))
+                        (setq form (cdr form))))
+                     ((memq fn '(\` backquote quote))
+                      (if report-symbols
+                          (progn
+                            (setq form (car form)
+                                  newform nil)
+                            (while form
+                              (push (list (or (car-safe form) form))
+                                    newform)
+                              (setq form (cdr-safe form)))
+                            (setq form (nreverse newform)))
+                        (setq form nil)))
+                     ((memq fn '(defadvice
+                                  defmacro defsubst defun
+                                  defmacro-maybe defmacro-maybe-cond
+                                  defsubst-maybe defun-maybe
+                                  defun-maybe-cond))
+                      (setq form (cddr form)))
+                     ((memq fn '(defalias lambda fset))
+                      (setq form (cdr form)))
+                     ((eq fn 'define-compiler-macro)
+                      (setq form nil))
+                     ((eq fn 'dolist)
+                      (setcar form (cadar form)))
+                     ((memq fn '(let let*))
+                      (setq form
+                            (append
+                             (delq nil
+                                   (mapcar
+                                    (lambda (element)
+                                      (when (and (consp element)
+                                                 (consp (cadr element)))
+                                        (cadr element)))
+                                    (car form)))
+                             (cdr form))))
+                     ((eq fn 'sort)
+                      (when (and (consp (cadr form))
+                                 (memq (caadr form) '(\` backquote quote)))
+                        (setcdr form (list (cdadr form)))))
+                     ((and (memq fn clfns)
+                           (listp form))
+                      (push fn fns)))
+               (when (listp form)
+                 (setq forms (append form forms)))))
+           (when fns
+             (if buffer
+                 (set-buffer buffer)
+               (display-buffer
+                (setq buffer (get-buffer-create
+                              (concat "*CL run-time functions in: "
+                                      file-or-directory "*"))))
+               (set-buffer buffer)
+               (erase-buffer)
+               (setq window (get-buffer-window buffer t)
+                     scroll (- 2 (window-height window))
+                     fill-column (max 16 (- (window-width window) 2))
+                     fill-prefix "               "))
+             (when file
+               (insert file "\n")
+               (setq file nil))
+             (narrow-to-region
+              (point)
+              (progn
+                (insert fill-prefix
+                        (mapconcat (lambda (fn) (format "%s" fn))
+                                   (nreverse fns) " ")
+                        "\n")
+                (point)))
+             (fill-region (point-min) (point-max))
+             (goto-char (point-min))
+             (widen)
+             (delete-char 14)
+             (insert (format "%5d - %5d:" (car lines) (cadr lines)))
+             (goto-char (point-max))
+             (forward-line scroll)
+             (set-window-start window (point))
+             (goto-char (point-max))
+             (sit-for 0)
+             (set-buffer working)))))
+      (kill-buffer working)
+      (if buffer
+         (message "Done")
+       (message "No CL run-time functions found in: %s"
+                file-or-directory)))))
+
+(provide 'gnus-clfns)
+
+;;; gnus-clfns.el ends here
index 4416895..7ebcce2 100644 (file)
@@ -1,6 +1,7 @@
 ;;; gnus-cus.el --- customization commands for Gnus
 ;;
-;; Copyright (C) 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: news
 ;;; Code:
 
 (require 'wid-edit)
+(require 'gnus)
+(require 'gnus-agent)
 (require 'gnus-score)
+(require 'gnus-topic)
+(require 'gnus-art)
 
 ;;; Widgets:
 
-;; There should be special validation for this.
-(define-widget 'gnus-email-address 'string
-  "An email address")
-
 (defun gnus-custom-mode ()
   "Major mode for editing Gnus customization buffers.
 
@@ -51,33 +52,68 @@ if that value is non-nil."
   (setq major-mode 'gnus-custom-mode
        mode-name "Gnus Customize")
   (use-local-map widget-keymap)
+  ;; Emacs 21 stuff:
+  (when (and (facep 'custom-button-face)
+            (facep 'custom-button-pressed-face))
+    (set (make-local-variable 'widget-button-face)
+        'custom-button-face)
+    (set (make-local-variable 'widget-button-pressed-face)
+        'custom-button-pressed-face)
+    (set (make-local-variable 'widget-mouse-face)
+        'custom-button-pressed-face))
+  (when (and (boundp 'custom-raised-buttons)
+            (symbol-value 'custom-raised-buttons))
+    (set (make-local-variable 'widget-push-button-prefix) "")
+    (set (make-local-variable 'widget-push-button-suffix) "")
+    (set (make-local-variable 'widget-link-prefix) "")
+    (set (make-local-variable 'widget-link-suffix) ""))
   (gnus-run-hooks 'gnus-custom-mode-hook))
 
 ;;; Group Customization:
 
 (defconst gnus-group-parameters
-  '((to-address (gnus-email-address :tag "To Address") "\
-This will be used when doing followups and posts.
-
-This is primarily useful in mail groups that represent closed
-mailing lists--mailing lists where it's expected that everybody that
-writes to the mailing list is subscribed to it.  Since using this
-parameter ensures that the mail only goes to the mailing list itself,
-it means that members won't receive two copies of your followups.
-
-Using `to-address' will actually work whether the group is foreign or
-not.  Let's say there's a group on the server that is called
-`fa.4ad-l'.  This is a real newsgroup, but the server has gotten the
-articles from a mail-to-news gateway.  Posting directly to this group
-is therefore impossible--you have to send mail to the mailing list
-address instead.")
-
-    (to-list (gnus-email-address :tag "To List") "\
-This address will be used when doing a `a' in the group.
-
-It is totally ignored when doing a followup--except that if it is
-present in a news group, you'll get mail group semantics when doing
-`f'.")
+  '((extra-aliases (choice
+                   :tag "Extra Aliases"
+                   (list
+                    :tag "List"
+                    (editable-list
+                     :inline t
+                     (gnus-email-address :tag "Address")))
+                   (gnus-email-address :tag "Address")) "\
+Store messages posted from or to this address in this group.
+
+You must be using gnus-group-split for this to work.  The VALUE of the
+nnmail-split-fancy SPLIT generated for this group will match these
+addresses.")
+
+    (split-regexp (regexp :tag "gnus-group-split Regular Expression") "\
+Like gnus-group-split Address, but expects a regular expression.")
+
+    (split-exclude (list :tag "gnus-group-split Restricts"
+                        (editable-list
+                         :inline t (regexp :tag "Restrict"))) "\
+Regular expression that cancels gnus-group-split matches.
+
+Each entry is added to the nnmail-split-fancy SPLIT as a separate
+RESTRICT clause.")
+
+    (split-spec (choice :tag "gnus-group-split Overrider"
+                       (sexp :tag "Fancy Split")
+                       (const :tag "Catch All" catch-all)
+                       (const :tag "Ignore" nil)) "\
+Override all other gnus-group-split fields.
+
+In `Fancy Split', you can enter any nnmail-split-fancy SPLIT.  Note
+that the name of this group won't be automatically assumed, you have
+to add it to the SPLITs yourself.  This means you can use such splits
+to split messages to other groups too.
+
+If you select `Catch All', this group will get postings for any
+messages not matched in any other group.  It overrides the variable
+gnus-group-split-default-catch-all-group.
+
+Selecting `Ignore' forces no SPLIT to be generated for this group,
+disabling all other gnus-group-split fields.")
 
     (broken-reply-to (const :tag "Broken Reply To" t) "\
 Ignore `Reply-To' headers in this group.
@@ -87,31 +123,22 @@ listserv has inserted `Reply-To' headers that point back to the
 listserv itself.  This is broken behavior.  So there!")
 
     (to-group (string :tag "To Group") "\
-All posts will be send to the specified group.")
+All posts will be sent to the specified group.")
 
     (gcc-self (choice :tag  "GCC"
                      :value t
-                     (const t)
+                     (const :tag "To current group" t)
                      (const none)
                      (string :format "%v" :hide-front-space t)) "\
 Specify default value for GCC header.
 
-If this symbol is present in the group parameter list and set to `t',
-new composed messages will be `Gcc''d to the current group. If it is
+If this symbol is present in the group parameter list and set to t,
+new composed messages will be `Gcc''d to the current group.  If it is
 present and set to `none', no `Gcc:' header will be generated, if it
 is present and a string, this string will be inserted literally as a
 `gcc' header (this symbol takes precedence over any default `Gcc'
 rules as described later).")
 
-    (auto-expire (const :tag "Automatic Expire" t) "\
-All articles that are read will be marked as expirable.")
-
-    (total-expire (const :tag "Total Expire" t) "\
-All read articles will be put through the expiry process
-
-This happens even if they are not marked as expirable.
-Use with caution.")
-
     (expiry-wait (choice :tag  "Expire Wait"
                         :value never
                         (const never)
@@ -121,10 +148,19 @@ Use with caution.")
 When to expire.
 
 Overrides any `nnmail-expiry-wait' and `nnmail-expiry-wait-function'
-when expiring expirable messages. The value can either be a number of
+when expiring expirable messages.  The value can either be a number of
 days (not necessarily an integer) or the symbols `never' or
 `immediate'.")
 
+    (expiry-target (choice :tag "Expiry Target"
+                          :value delete
+                          (const delete)
+                          (function :format "%v" nnmail-)
+                          string) "\
+Where expired messages end up.
+
+Overrides `nnmail-expiry-target'.")
+
     (score-file (file :tag "Score File") "\
 Make the specified file into the current score file.
 This means that all score commands you issue will end up in this file.")
@@ -144,60 +180,220 @@ you to put the admin address somewhere convenient.")
     (display (choice :tag "Display"
                     :value default
                     (const all)
-                    (const default)) "\
+                    (integer)
+                    (const default)
+                    (sexp  :tag "Other")) "\
 Which articles to display on entering the group.
 
 `all'
      Display all articles, both read and unread.
 
+`integer'
+     Display the last NUMBER articles in the group.  This is the same as
+     entering the group with C-u NUMBER.
+
 `default'
      Display the default visible articles, which normally includes
-     unread and ticked articles.")
+     unread and ticked articles.
+
+`Other'
+     Display the articles that satisfy the S-expression. The S-expression
+     should be in an array form.")
 
     (comment (string :tag  "Comment") "\
 An arbitrary comment on the group.")
 
     (visible (const :tag "Permanently visible" t) "\
-Always display this group, even when there are no unread articles
-in it.."))
-  "Alist of valid group parameters.
+Always display this group, even when there are no unread articles in it.")
+
+    (highlight-words
+     (choice :tag "Highlight words"
+            :value nil
+            (repeat (list (regexp :tag "Highlight regexp")
+                          (number :tag "Group for entire word" 0)
+                          (number :tag "Group for displayed part" 0)
+                          (symbol :tag "Face"
+                                  gnus-emphasis-highlight-words))))
+     "highlight regexps.
+See `gnus-emphasis-alist'.")
+
+    (posting-style
+     (choice :tag "Posting style"
+            :value nil
+            (repeat (list
+                     (choice :tag "Type"
+                             :value nil
+                             (const signature)
+                             (const signature-file)
+                             (const organization)
+                             (const address)
+                             (const name)
+                             (const body)
+                             (const import))
+                     (string :format "%v"))))
+     "post style.
+See `gnus-posting-styles'."))
+  "Alist of valid group or topic parameters.
+
+Each entry has the form (NAME TYPE DOC), where NAME is the parameter
+itself (a symbol), TYPE is the parameters type (a sexp widget), and
+DOC is a documentation string for the parameter.")
+
+(defconst gnus-extra-topic-parameters
+  '((subscribe (regexp :tag "Subscribe") "\
+If `gnus-subscribe-newsgroup-method' or
+`gnus-subscribe-options-newsgroup-method' is set to
+`gnus-subscribe-topics', new groups that matches this regexp will
+automatically be subscribed to this topic")
+    (subscribe-level (integer :tag "Subscribe Level" :value 1) "\
+If this topic parameter is set, when new groups are subscribed
+automatically under this topic (via the `subscribe' topic parameter)
+assign this level to the group, rather than the default level
+set in `gnus-level-default-subscribed'"))
+  "Alist of topic parameters that are not also group parameters.
+
+Each entry has the form (NAME TYPE DOC), where NAME is the parameter
+itself (a symbol), TYPE is the parameters type (a sexp widget), and
+DOC is a documentation string for the parameter.")
+
+(defconst gnus-extra-group-parameters
+  '((uidvalidity (string :tag "IMAP uidvalidity") "\
+Server-assigned value attached to IMAP groups, used to maintain consistency."))
+  "Alist of group parameters that are not also topic parameters.
 
 Each entry has the form (NAME TYPE DOC), where NAME is the parameter
 itself (a symbol), TYPE is the parameters type (a sexp widget), and
 DOC is a documentation string for the parameter.")
 
+(eval-and-compile
+  (defconst gnus-agent-parameters
+    '((agent-predicate
+       (sexp :tag "Selection Predicate" :value false)
+       "Predicate used to automatically select articles for downloading."
+       gnus-agent-cat-predicate)
+      (agent-score
+       (choice :tag "Score File" :value nil
+               (const file :tag "Use group's score files")
+               (repeat (list (string :format "%v" :tag "File name"))))
+       "Which score files to use when using score to select articles to fetch.
+
+    `nil'
+         All articles will be scored to zero (0).
+
+    `file'
+         The group's score files will be used to score the articles.
+
+    `List'
+         A list of score file names."
+       gnus-agent-cat-score-file)
+      (agent-short-article
+       (integer :tag "Max Length of Short Article" :value "")
+       "The SHORT predicate will evaluate to true when the article is
+shorter than this length."  gnus-agent-cat-length-when-short)
+      (agent-long-article
+       (integer :tag "Min Length of Long Article" :value "")
+       "The LONG predicate will evaluate to true when the article is
+longer than this length."  gnus-agent-cat-length-when-long)
+      (agent-low-score
+       (integer :tag "Low Score Limit" :value "")
+       "The LOW predicate will evaluate to true when the article scores
+lower than this limit."  gnus-agent-cat-low-score)
+      (agent-high-score
+       (integer :tag "High Score Limit" :value "")
+       "The HIGH predicate will evaluate to true when the article scores
+higher than this limit."  gnus-agent-cat-high-score)
+      (agent-days-until-old
+       (integer :tag "Days Until Old" :value "")
+       "The OLD predicate will evaluate to true when the fetched article
+has been stored locally for at least this many days."
+       gnus-agent-cat-days-until-old)
+      (agent-enable-expiration
+       (radio :tag "Expire in this Group or Topic" :value nil
+              (const :format "Enable " ENABLE)
+              (const :format "Disable " DISABLE))
+       "\nEnable, or disable, agent expiration in this group or topic."
+       gnus-agent-cat-enable-expiration)
+      (agent-disable-undownloaded-faces
+       (boolean :tag "Disable Agent Faces")
+       "Have the summary buffer ignore the agent's undownloaded faces.
+These faces, when used, act as a warning that an article has not been
+fetched into either the agent nor the cache.  This is of most use to
+users who use the agent as a cache (i.e. they only operate on articles
+that have been downloaded).  Disable to display normal article faces
+even when the article hasn't been downloaded."
+       gnus-agent-cat-disable-undownloaded-faces))
+    "Alist of group parameters that are not also topic parameters.
+
+Each entry has the form (NAME TYPE DOC ACCESSOR), where NAME is the
+parameter itself (a symbol), TYPE is the parameters type (a sexp
+widget), DOC is a documentation string for the parameter, and ACCESSOR
+is a function (symbol) that extracts the current value from the
+category."))
+
 (defvar gnus-custom-params)
 (defvar gnus-custom-method)
 (defvar gnus-custom-group)
+(defvar gnus-custom-topic)
 
-(defun gnus-group-customize (group &optional part)
-  "Edit the group on the current line."
-  (interactive (list (gnus-group-group-name)))
-  (let ((part (or part 'info))
-       info
+(defun gnus-group-customize (group &optional topic)
+  "Edit the group or topic on the current line."
+  (interactive (list (gnus-group-group-name) (gnus-group-topic-name)))
+  (let (info
        (types (mapcar (lambda (entry)
                         `(cons :format "%v%h\n"
                                :doc ,(nth 2 entry)
                                (const :format "" ,(nth 0 entry))
                                ,(nth 1 entry)))
-                      gnus-group-parameters)))
-    (unless group
+                      (append (reverse gnus-group-parameters-more)
+                              gnus-group-parameters
+                              (if group
+                                  gnus-extra-group-parameters
+                                gnus-extra-topic-parameters))))
+       (agent (mapcar (lambda (entry)
+                         (let ((type (nth 1 entry))
+                               vcons)
+                           (if (listp type)
+                               (setq type (copy-sequence type)))
+
+                           (setq vcons (cdr (memq :value type)))
+
+                           (if (symbolp (car vcons))
+                               (condition-case nil
+                                   (setcar vcons (symbol-value (car vcons)))
+                                 (error)))
+                           `(cons :format "%v%h\n"
+                                  :doc ,(nth 2 entry)
+                                  (const :format "" ,(nth 0 entry))
+                                  ,type)))
+                      (if gnus-agent
+                           gnus-agent-parameters))))
+    (unless (or group topic)
       (error "No group on current line"))
-    (unless (setq info (gnus-get-info group))
+    (when (and group topic)
+      (error "Both a group an topic on current line"))
+    (unless (or topic (setq info (gnus-get-info group)))
       (error "Killed group; can't be edited"))
     ;; Ready.
-    (kill-buffer (get-buffer-create "*Gnus Customize*"))
-    (switch-to-buffer (get-buffer-create "*Gnus Customize*"))
+    (gnus-kill-buffer (gnus-get-buffer-create "*Gnus Customize*"))
+    (switch-to-buffer (gnus-get-buffer-create "*Gnus Customize*"))
     (gnus-custom-mode)
     (make-local-variable 'gnus-custom-group)
     (setq gnus-custom-group group)
+    (make-local-variable 'gnus-custom-topic)
+    (setq gnus-custom-topic topic)
+    (buffer-disable-undo)
     (widget-insert "Customize the ")
-    (widget-create 'info-link
-                  :help-echo "Push me to learn more."
-                  :tag "group parameters"
-                  "(gnus)Group Parameters")
+    (if group
+       (widget-create 'info-link
+                      :help-echo "Push me to learn more."
+                      :tag "group parameters"
+                      "(gnus)Group Parameters")
+      (widget-create 'info-link
+                    :help-echo "Push me to learn more."
+                    :tag  "topic parameters"
+                    "(gnus)Topic Parameters"))
     (widget-insert " for <")
-    (widget-insert group)
+    (widget-insert (gnus-group-decoded-name (or group topic)))
     (widget-insert "> and press ")
     (widget-create 'push-button
                   :tag "done"
@@ -205,62 +401,100 @@ DOC is a documentation string for the parameter.")
                   :action 'gnus-group-customize-done)
     (widget-insert ".\n\n")
     (make-local-variable 'gnus-custom-params)
-    (setq gnus-custom-params
-         (widget-create 'group
-                        :value (gnus-info-params info)
-                        `(set :inline t
-                              :greedy t
-                              :tag "Parameters"
-                              :format "%t:\n%h%v"
-                              :doc "\
-These special paramerters are recognized by Gnus.
-Check the [ ] for the parameters you want to apply to this group, then
-edit the value to suit your taste."
-                              ,@types)
-                        '(repeat :inline t
-                                 :tag "Variables"
-                                 :format "%t:\n%h%v%i\n\n"
-                                 :doc "\
+
+    (let ((values (if group
+                     (gnus-info-params info)
+                   (gnus-topic-parameters topic))))
+
+      ;; The parameters in values may contain duplicates.  This is
+      ;; normally OK as assq returns the first. However, right here
+      ;; every duplicate ends up being displayed.  So, rather than
+      ;; display them, remove them from the list.
+
+      (let ((tmp (setq values (gnus-copy-sequence values)))
+           elem)
+       (while (cdr tmp)
+         (while (setq elem (assq (caar tmp) (cdr tmp)))
+           (delq elem tmp))
+         (setq tmp (cdr tmp))))
+
+      (setq gnus-custom-params
+            (apply 'widget-create 'group
+                   :value values
+                   (delq nil
+                         (list `(set :inline t
+                                     :greedy t
+                                     :tag "Parameters"
+                                     :format "%t:\n%h%v"
+                                     :doc "\
+These special parameters are recognized by Gnus.
+Check the [ ] for the parameters you want to apply to this group or
+to the groups in this topic, then edit the value to suit your taste."
+                                     ,@types)
+                               (when gnus-agent
+                                 `(set :inline t
+                                       :greedy t
+                                       :tag "Agent Parameters"
+                                       :format "%t:\n%h%v"
+                                       :doc "\ These agent parameters are
+recognized by Gnus.  They control article selection and expiration for
+use in the unplugged cache.  Check the [ ] for the parameters you want
+to apply to this group or to the groups in this topic, then edit the
+value to suit your taste.
+
+For those interested, group parameters override topic parameters while
+topic parameters override agent category parameters.  Underlying
+category parameters are the customizable variables."  ,@agent))
+                               '(repeat :inline t
+                                        :tag "Variables"
+                                        :format "%t:\n%h%v%i\n\n"
+                                        :doc "\
 Set variables local to the group you are entering.
 
 If you want to turn threading off in `news.answers', you could put
 `(gnus-show-threads nil)' in the group parameters of that group.
 `gnus-show-threads' will be made into a local variable in the summary
-buffer you enter, and the form `nil' will be `eval'ed there.
+buffer you enter, and the form nil will be `eval'ed there.
 
 This can also be used as a group-specific hook function, if you'd
 like.  If you want to hear a beep when you enter a group, you could
 put something like `(dummy-variable (ding))' in the parameters of that
 group.  `dummy-variable' will be set to the result of the `(ding)'
 form, but who cares?"
-                                 (group :value (nil nil)
-                                        (symbol :tag "Variable")
-                                        (sexp :tag
-                                              "Value")))
-
-                        '(repeat :inline t
-                                 :tag "Unknown entries"
-                                 sexp)))
-    (widget-insert "\n\nYou can also edit the ")
-    (widget-create 'info-link
-                  :tag "select method"
-                  :help-echo "Push me to learn more about select methods."
-                  "(gnus)Select Methods")
-    (widget-insert " for the group.\n")
-    (setq gnus-custom-method
-         (widget-create 'sexp
-                        :tag "Method"
-                        :value (gnus-info-method info)))
+                                        (list :format "%v" :value (nil nil)
+                                              (symbol :tag "Variable")
+                                              (sexp :tag
+                                                    "Value")))
+
+                               '(repeat :inline t
+                                        :tag "Unknown entries"
+                                        sexp))))))
+    (when group
+      (widget-insert "\n\nYou can also edit the ")
+      (widget-create 'info-link
+                    :tag "select method"
+                    :help-echo "Push me to learn more about select methods."
+                    "(gnus)Select Methods")
+      (widget-insert " for the group.\n")
+      (setq gnus-custom-method
+           (widget-create 'sexp
+                          :tag "Method"
+                          :value (gnus-info-method info))))
     (use-local-map widget-keymap)
-    (widget-setup)))
+    (widget-setup)
+    (buffer-enable-undo)
+    (goto-char (point-min))))
 
 (defun gnus-group-customize-done (&rest ignore)
   "Apply changes and bury the buffer."
   (interactive)
-  (gnus-group-edit-group-done 'params gnus-custom-group
-                             (widget-value gnus-custom-params))
-  (gnus-group-edit-group-done 'method gnus-custom-group
-                             (widget-value gnus-custom-method))
+  (if gnus-custom-topic
+      (gnus-topic-set-parameters gnus-custom-topic
+                                (widget-value gnus-custom-params))
+    (gnus-group-edit-group-done 'params gnus-custom-group
+                               (widget-value gnus-custom-params))
+    (gnus-group-edit-group-done 'method gnus-custom-group
+                               (widget-value gnus-custom-method)))
   (bury-buffer))
 
 ;;; Score Customization:
@@ -333,15 +567,15 @@ by ordinary scoring rules.")
                   (sexp :format "%v"
                         :hide-front-space t)) "\
 This entry controls the adaptive scoring.
-If it is `t', the default adaptive scoring rules will be used.  If it
+If it is t, the default adaptive scoring rules will be used.  If it
 is `ignore', no adaptive scoring will be performed on this group.  If
 it is a list, this list will be used as the adaptive scoring rules.
-If it isn't present, or is something other than `t' or `ignore', the
+If it isn't present, or is something other than t or `ignore', the
 default adaptive scoring rules will be used.  If you want to use
 adaptive scoring on most groups, you'd set `gnus-use-adaptive-scoring'
-to `t', and insert an `(adapt ignore)' in the groups where you do not
+to t, and insert an `(adapt ignore)' in the groups where you do not
 want adaptive scoring.  If you only want adaptive scoring in a few
-groups, you'd set `gnus-use-adaptive-scoring' to `nil', and insert
+groups, you'd set `gnus-use-adaptive-scoring' to nil, and insert
 `(adapt t)' in the score files of the groups where you want it.")
 
     (adapt-file (file :tag "Adapt-file") "\
@@ -376,9 +610,9 @@ documentation string for the parameter.")
         (item `(const :format "" :value ,(downcase tag)))
         (match '(string :tag "Match"))
         (score '(choice :tag "Score"
-                       (const :tag "default" nil)
-                       (integer :format "%v"
-                                :hide-front-space t)))
+                        (const :tag "default" nil)
+                        (integer :format "%v"
+                                 :hide-front-space t)))
         (expire '(choice :tag "Expire"
                          (const :tag "off" nil)
                          (integer :format "%v"
@@ -449,9 +683,9 @@ each score entry has four elements:
         (item `(const :format "" :value ,(downcase tag)))
         (match '(integer :tag "Match"))
         (score '(choice :tag "Score"
-                       (const :tag "default" nil)
-                       (integer :format "%v"
-                                :hide-front-space t)))
+                        (const :tag "default" nil)
+                        (integer :format "%v"
+                                 :hide-front-space t)))
         (expire '(choice :tag "Expire"
                          (const :tag "off" nil)
                          (integer :format "%v"
@@ -486,9 +720,9 @@ each score entry has four elements:
         (item `(const :format "" :value ,(downcase tag)))
         (match '(string :tag "Match"))
         (score '(choice :tag "Score"
-                       (const :tag "default" nil)
-                       (integer :format "%v"
-                                :hide-front-space t)))
+                        (const :tag "default" nil)
+                        (integer :format "%v"
+                                 :hide-front-space t)))
         (expire '(choice :tag "Expire"
                          (const :tag "off" nil)
                          (integer :format "%v"
@@ -534,18 +768,23 @@ eh?")))
 (defvar gnus-custom-score-alist)
 
 (defun gnus-score-customize (file)
-  "Customize score file FILE."
+  "Customize score file FILE.
+When called interactively, FILE defaults to the current score file.
+This can be changed using the `\\[gnus-score-change-score-file]' command."
   (interactive (list gnus-current-score-file))
+  (unless file
+    (error (format "No score file for %s"
+                  (gnus-group-decoded-name gnus-newsgroup-name))))
   (let ((scores (gnus-score-load file))
        (types (mapcar (lambda (entry)
-                `(group :format "%v%h\n"
-                        :doc ,(nth 2 entry)
-                        (const :format "" ,(nth 0 entry))
-                        ,(nth 1 entry)))
-              gnus-score-parameters)))
+                        `(group :format "%v%h\n"
+                                :doc ,(nth 2 entry)
+                                (const :format "" ,(nth 0 entry))
+                                ,(nth 1 entry)))
+                      gnus-score-parameters)))
     ;; Ready.
-    (kill-buffer (get-buffer-create "*Gnus Customize*"))
-    (switch-to-buffer (get-buffer-create "*Gnus Customize*"))
+    (kill-buffer (gnus-get-buffer-create "*Gnus Customize*"))
+    (switch-to-buffer (gnus-get-buffer-create "*Gnus Customize*"))
     (gnus-custom-mode)
     (make-local-variable 'gnus-custom-score-alist)
     (setq gnus-custom-score-alist scores)
@@ -581,6 +820,7 @@ if you do all your changes will be lost.  ")
                                     (gnus-score-string :tag "Subject")
                                     (gnus-score-string :tag "References")
                                     (gnus-score-string :tag "Xref")
+                                    (gnus-score-string :tag "Extra")
                                     (gnus-score-string :tag "Message-ID")
                                     (gnus-score-integer :tag "Lines")
                                     (gnus-score-integer :tag "Chars")
@@ -646,9 +886,176 @@ articles in the thread.
     (gnus-score-set 'touched '(t) alist))
   (bury-buffer))
 
+(eval-when-compile
+  (defvar category-fields nil)
+  (defvar gnus-agent-cat-name)
+  (defvar gnus-agent-cat-score-file)
+  (defvar gnus-agent-cat-length-when-short)
+  (defvar gnus-agent-cat-length-when-long)
+  (defvar gnus-agent-cat-low-score)
+  (defvar gnus-agent-cat-high-score)
+  (defvar gnus-agent-cat-enable-expiration)
+  (defvar gnus-agent-cat-days-until-old)
+  (defvar gnus-agent-cat-predicate)
+  (defvar gnus-agent-cat-groups)
+  (defvar gnus-agent-cat-disable-undownloaded-faces)
+)
+
+(defun gnus-trim-whitespace (s)
+  (when (string-match "\\`[ \n\t]+" s)
+    (setq s (substring s (match-end 0))))
+  (when (string-match "[ \n\t]+\\'" s)
+    (setq s (substring s 0 (match-beginning 0))))
+  s)
+
+(defmacro gnus-agent-cat-prepare-category-field (parameter)
+  (let* ((entry (assq parameter gnus-agent-parameters))
+         (field (nth 3 entry)))
+    `(let* ((type (copy-sequence
+                   (nth 1 (assq ',parameter gnus-agent-parameters))))
+            (val (,field info))
+            (deflt (if (,field defaults)
+                       (concat " [" (gnus-trim-whitespace
+                                     (pp-to-string (,field defaults))) "]")))
+            symb)
+
+       (if (eq (car type) 'radio)
+           (let* ((rtype (nreverse type))
+                  (rt rtype))
+             (while (listp (or (cadr rt) 'not-list))
+               (setq rt (cdr rt)))
+
+             (setcdr rt (cons '(const :format "Inherit " nil) (cdr rt)))
+             (setq type (nreverse rtype))))
+
+       (if deflt
+           (let ((tag (cdr (memq :tag type))))
+             (if (string-match "\n" deflt)
+                 (progn (while (progn (setq deflt (replace-match "\n " t t
+                                                                 deflt))
+                                      (string-match "\n" deflt (match-end 0))))
+                        (setq deflt (concat "\n" deflt))))
+
+             (setcar tag (concat (car tag) deflt))))
+
+       (widget-insert "\n")
+
+       (setq val (if val
+                     (widget-create type :value val)
+                   (widget-create type))
+             symb (set (make-local-variable ',field) val))
+
+       (widget-put symb :default val)
+       (widget-put symb :accessor ',field)
+       (push symb category-fields))))
+
+(defun gnus-agent-customize-category (category)
+  "Edit the CATEGORY."
+  (interactive (list (gnus-category-name)))
+  (let ((info (assq category gnus-category-alist))
+        (defaults (list nil '(agent-predicate . false)
+                        (cons 'agent-enable-expiration
+                              gnus-agent-enable-expiration)
+                        '(agent-days-until-old . 7)
+                        (cons 'agent-length-when-short
+                              gnus-agent-short-article)
+                        (cons 'agent-length-when-long gnus-agent-long-article)
+                        (cons 'agent-low-score gnus-agent-low-score)
+                        (cons 'agent-high-score gnus-agent-high-score))))
+
+    (let ((old (get-buffer "*Gnus Agent Category Customize*")))
+      (when old
+        (gnus-kill-buffer old)))
+    (switch-to-buffer (gnus-get-buffer-create
+                       "*Gnus Agent Category Customize*"))
+
+    (let ((inhibit-read-only t))
+      (gnus-custom-mode)
+      (buffer-disable-undo)
+
+      (let* ((name (gnus-agent-cat-name info)))
+        (widget-insert "Customize the Agent Category '")
+        (widget-insert (symbol-name name))
+        (widget-insert "' and press ")
+        (widget-create
+         'push-button
+         :notify
+         '(lambda (&rest ignore)
+            (let* ((info (assq gnus-agent-cat-name gnus-category-alist))
+                   (widgets category-fields))
+              (while widgets
+                (let* ((widget (pop widgets))
+                       (value (ignore-errors (widget-value widget))))
+                  (eval `(setf (,(widget-get widget :accessor) ',info)
+                               ',value)))))
+            (gnus-category-write)
+            (gnus-kill-buffer (current-buffer))
+            (when (get-buffer gnus-category-buffer)
+              (switch-to-buffer (get-buffer gnus-category-buffer))
+              (gnus-category-list)))
+                       "Done")
+        (widget-insert
+         "\n    Note: Empty fields default to the customizable global\
+ variables.\n\n")
+
+        (set (make-local-variable 'gnus-agent-cat-name)
+             name))
+
+      (set (make-local-variable 'category-fields) nil)
+      (gnus-agent-cat-prepare-category-field agent-predicate)
+
+      (gnus-agent-cat-prepare-category-field agent-score)
+      (gnus-agent-cat-prepare-category-field agent-short-article)
+      (gnus-agent-cat-prepare-category-field agent-long-article)
+      (gnus-agent-cat-prepare-category-field agent-low-score)
+      (gnus-agent-cat-prepare-category-field agent-high-score)
+
+      ;; The group list is NOT handled with
+      ;; gnus-agent-cat-prepare-category-field as I don't want the
+      ;; group list to appear when customizing a topic.
+      (widget-insert "\n")
+      
+      (let ((symb 
+             (set 
+              (make-local-variable 'gnus-agent-cat-groups)
+              (widget-create
+               `(choice
+                 :format "%[Select Member Groups%]\n%v" :value ignore
+                 (const :menu-tag "do not change" :tag "" :value ignore)
+                 (checklist :entry-format "%b %v"
+                            :menu-tag "display group selectors"
+                            :greedy t
+                            :value
+                            ,(delq nil
+                                   (mapcar
+                                    (lambda (newsrc)
+                                      (car (member
+                                            (gnus-info-group newsrc)
+                                            (gnus-agent-cat-groups info))))
+                                    (cdr gnus-newsrc-alist)))
+                            ,@(mapcar (lambda (newsrc)
+                                        `(const ,(gnus-info-group newsrc)))
+                                      (cdr gnus-newsrc-alist))))))))
+
+      (widget-put symb :default (gnus-agent-cat-groups info))
+      (widget-put symb :accessor 'gnus-agent-cat-groups)
+      (push symb category-fields))
+
+      (widget-insert "\nExpiration Settings ")
+
+      (gnus-agent-cat-prepare-category-field agent-enable-expiration)
+      (gnus-agent-cat-prepare-category-field agent-days-until-old)
+
+      (widget-insert "\nVisual Settings ")
+
+      (gnus-agent-cat-prepare-category-field agent-disable-undownloaded-faces)
+
+      (use-local-map widget-keymap)
+      (widget-setup)
+      (buffer-enable-undo))))
+
 ;;; The End:
 
 (provide 'gnus-cus)
 
 ;;; gnus-cus.el ends here
-
diff --git a/lisp/gnus-delay.el b/lisp/gnus-delay.el
new file mode 100644 (file)
index 0000000..cc212fa
--- /dev/null
@@ -0,0 +1,195 @@
+;;; gnus-delay.el --- Delayed posting of articles
+
+;; Copyright (C) 2001, 2002, 2003  Free Software Foundation, Inc.
+
+;; Author: Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+;; Keywords: mail, news, extensions
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Provide delayed posting of articles.
+
+;;; Todo:
+
+;; * `gnus-delay-send-queue' barfs when group does not exist.
+;; * Integrate gnus-delay.el into the rest of Gnus automatically.  How
+;;   should this be done?  Basically, we need to do what
+;;   `gnus-delay-initialize' does.  But in which files?
+
+;;; Code:
+
+(require 'nndraft)
+(require 'gnus-draft)
+
+;;;###autoload
+(defgroup gnus-delay nil
+  "Arrange for sending postings later."
+  :group 'gnus)
+
+(defcustom gnus-delay-group "delayed"
+  "Group name for storing delayed articles."
+  :type 'string
+  :group 'gnus-delay)
+
+(defcustom gnus-delay-header "X-Gnus-Delayed"
+  "Header name for storing info about delayed articles."
+  :type 'string
+  :group 'gnus-delay)
+
+(defcustom gnus-delay-default-delay "3d"
+  "*Default length of delay."
+  :type 'string
+  :group 'gnus-delay)
+
+(defcustom gnus-delay-default-hour 8
+  "*If deadline is given as date, then assume this time of day."
+  :type 'integer
+  :group 'gnus-delay)
+
+;;;###autoload
+(defun gnus-delay-article (delay)
+  "Delay this article by some time.
+DELAY is a string, giving the length of the time.  Possible values are:
+
+* <digits><units> for <units> in minutes (`m'), hours (`h'), days (`d'),
+  weeks (`w'), months (`M'), or years (`Y');
+
+* YYYY-MM-DD for a specific date.  The time of day is given by the
+  variable `gnus-delay-default-hour', minute and second are zero.
+
+* hh:mm for a specific time.  Use 24h format.  If it is later than this
+  time, then the deadline is tomorrow, else today."
+  (interactive
+   (list (read-string
+         "Target date (YYYY-MM-DD) or length of delay (units in [mhdwMY]): "
+         gnus-delay-default-delay)))
+  (let (num unit days year month day hour minute deadline)
+    (cond ((string-match
+           "\\([0-9][0-9][0-9]?[0-9]?\\)-\\([0-9]+\\)-\\([0-9]+\\)"
+           delay)
+          (setq year  (string-to-number (match-string 1 delay))
+                month (string-to-number (match-string 2 delay))
+                day   (string-to-number (match-string 3 delay)))
+          (setq deadline
+                (message-make-date
+                 (encode-time 0 0      ; second and minute
+                              gnus-delay-default-hour
+                              day month year))))
+         ((string-match "\\([0-9]+\\):\\([0-9]+\\)" delay)
+          (setq hour   (string-to-number (match-string 1 delay))
+                minute (string-to-number (match-string 2 delay)))
+          ;; Use current time, except...
+          (setq deadline (apply 'vector (decode-time (current-time))))
+          ;; ... for minute and hour.
+          (aset deadline 1 minute)
+          (aset deadline 2 hour)
+          ;; Convert to seconds.
+          (setq deadline (time-to-seconds (apply 'encode-time
+                                                 (append deadline nil))))
+          ;; If this time has passed already, add a day.
+          (when (< deadline (time-to-seconds (current-time)))
+            (setq deadline (+ 3600 deadline))) ;3600 secs/day
+          ;; Convert seconds to date header.
+          (setq deadline (message-make-date
+                          (seconds-to-time deadline))))
+         ((string-match "\\([0-9]+\\)\\s-*\\([mhdwMY]\\)" delay)
+          (setq num (match-string 1 delay))
+          (setq unit (match-string 2 delay))
+          ;; Start from seconds, then multiply into needed units.
+          (setq num (string-to-number num))
+          (cond ((string= unit "Y")
+                 (setq delay (* num 60 60 24 365)))
+                ((string= unit "M")
+                 (setq delay (* num 60 60 24 30)))
+                ((string= unit "w")
+                 (setq delay (* num 60 60 24 7)))
+                ((string= unit "d")
+                 (setq delay (* num 60 60 24)))
+                ((string= unit "h")
+                 (setq delay (* num 60 60)))
+                (t
+                 (setq delay (* num 60))))
+          (setq deadline (message-make-date
+                          (seconds-to-time (+ (time-to-seconds (current-time))
+                                              delay)))))
+         (t (error "Malformed delay `%s'" delay)))
+    (message-add-header (format "%s: %s" gnus-delay-header deadline)))
+  (set-buffer-modified-p t)
+  ;; If group does not exist, create it.
+  (let ((group (format "nndraft:%s" gnus-delay-group)))
+    (gnus-agent-queue-setup gnus-delay-group))
+  (message-disassociate-draft)
+  (nndraft-request-associate-buffer gnus-delay-group)
+  (save-buffer 0)
+  (kill-buffer (current-buffer))
+  (message-do-actions message-postpone-actions))
+
+;;;###autoload
+(defun gnus-delay-send-queue ()
+  "Send all the delayed messages that are due now."
+  (interactive)
+  (save-excursion
+    (let* ((group (format "nndraft:%s" gnus-delay-group))
+          (message-send-hook (copy-sequence message-send-hook))
+          articles
+          article deadline)
+      (when (gnus-gethash group gnus-newsrc-hashtb)
+       (gnus-activate-group group)
+       (add-hook 'message-send-hook
+                 '(lambda ()
+                    (message-remove-header gnus-delay-header)))
+       (setq articles (nndraft-articles))
+       (while (setq article (pop articles))
+         (gnus-request-head article group)
+         (set-buffer nntp-server-buffer)
+         (goto-char (point-min))
+         (if (re-search-forward
+              (concat "^" (regexp-quote gnus-delay-header) ":\\s-+")
+              nil t)
+             (progn
+               (setq deadline (nnheader-header-value))
+               (setq deadline (apply 'encode-time
+                                     (parse-time-string deadline)))
+               (setq deadline (time-since deadline))
+               (when (and (>= (nth 0 deadline) 0)
+                          (>= (nth 1 deadline) 0))
+                 (message "Sending delayed article %d" article)
+                 (gnus-draft-send article group)
+                 (message "Sending delayed article %d...done" article)))
+           (message "Delay header missing for article %d" article)))))))
+
+;;;###autoload
+(defun gnus-delay-initialize (&optional no-keymap no-check)
+  "Initialize the gnus-delay package.
+This sets up a key binding in `message-mode' to delay a message.
+This tells Gnus to look for delayed messages after getting new news.
+
+The optional arg NO-KEYMAP is ignored.
+Checking delayed messages is skipped if optional arg NO-CHECK is non-nil."
+  (unless no-check
+    (add-hook 'gnus-get-new-news-hook 'gnus-delay-send-queue)))
+
+(provide 'gnus-delay)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; gnus-delay.el ends here
index f3968ea..3d943b6 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-demon.el --- daemonic Gnus behaviour
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003
+;;      Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -32,8 +34,9 @@
 (require 'nnheader)
 (require 'nntp)
 (require 'nnmail)
+(require 'gnus-util)
 (eval-and-compile
-  (if (string-match "XEmacs" (emacs-version))
+  (if (featurep 'xemacs)
       (require 'itimer)
     (require 'timer)))
 
@@ -81,10 +84,6 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
 (defvar gnus-inhibit-demon nil
   "*If non-nil, no daemonic function will be run.")
 
-(eval-and-compile
-  (autoload 'timezone-parse-date "timezone")
-  (autoload 'timezone-make-arpa-date "timezone"))
-
 ;;; Functions.
 
 (defun gnus-demon-add-handler (function time idle)
@@ -97,9 +96,7 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
 
 (defun gnus-demon-remove-handler (function &optional no-init)
   "Remove the handler FUNCTION from the list of handlers."
-  (setq gnus-demon-handlers
-       (delq (assq function gnus-demon-handlers)
-             gnus-demon-handlers))
+  (gnus-pull function gnus-demon-handlers)
   (unless no-init
     (gnus-demon-init)))
 
@@ -120,8 +117,7 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
                   (nth 2 handler)))
           gnus-demon-handlers))
     (setq gnus-demon-idle-time 0)
-    (setq gnus-demon-idle-has-been-called nil)
-    (setq gnus-use-demon t)))
+    (setq gnus-demon-idle-has-been-called nil)))
 
 (gnus-add-shutdown 'gnus-demon-cancel 'gnus)
 
@@ -131,7 +127,6 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
   (when gnus-demon-timer
     (nnheader-cancel-timer gnus-demon-timer))
   (setq gnus-demon-timer nil
-       gnus-use-demon nil
        gnus-demon-idle-has-been-called nil)
   (condition-case ()
       (nnheader-cancel-function-timers 'gnus-demon)
@@ -155,32 +150,32 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
   (if (not (stringp time))
       time
     (let* ((now (current-time))
-           ;; obtain NOW as discrete components -- make a vector for speed
-           (nowParts (apply 'vector (decode-time now)))
-           ;; obtain THEN as discrete components
-           (thenParts (timezone-parse-time time))
-           (thenHour (string-to-int (elt thenParts 0)))
-           (thenMin (string-to-int (elt thenParts 1)))
-           ;; convert time as elements into number of seconds since EPOCH.
-           (then (encode-time 0
-                              thenMin
-                              thenHour
-                              ;; If THEN is earlier than NOW, make it
-                              ;; same time tomorrow. Doc for encode-time
-                              ;; says that this is OK.
-                              (+ (elt nowParts 3)
-                                 (if (or (< thenHour (elt nowParts 2))
-                                         (and (= thenHour (elt nowParts 2))
-                                              (<= thenMin (elt nowParts 1))))
-                                     1 0))
-                              (elt nowParts 4)
-                              (elt nowParts 5)
-                              (elt nowParts 6)
-                              (elt nowParts 7)
-                              (elt nowParts 8)))
-           ;; calculate number of seconds between NOW and THEN
-           (diff (+ (* 65536 (- (car then) (car now)))
-                    (- (cadr then) (cadr now)))))
+          ;; obtain NOW as discrete components -- make a vector for speed
+          (nowParts (decode-time now))
+          ;; obtain THEN as discrete components
+          (thenParts (parse-time-string time))
+          (thenHour (elt thenParts 2))
+          (thenMin (elt thenParts 1))
+          ;; convert time as elements into number of seconds since EPOCH.
+          (then (encode-time 0
+                             thenMin
+                             thenHour
+                             ;; If THEN is earlier than NOW, make it
+                             ;; same time tomorrow.  Doc for encode-time
+                             ;; says that this is OK.
+                             (+ (elt nowParts 3)
+                                (if (or (< thenHour (elt nowParts 2))
+                                        (and (= thenHour (elt nowParts 2))
+                                             (<= thenMin (elt nowParts 1))))
+                                    1 0))
+                             (elt nowParts 4)
+                             (elt nowParts 5)
+                             (elt nowParts 6)
+                             (elt nowParts 7)
+                             (elt nowParts 8)))
+          ;; calculate number of seconds between NOW and THEN
+          (diff (+ (* 65536 (- (car then) (car now)))
+                   (- (cadr then) (cadr now)))))
       ;; return number of timesteps in the number of seconds
       (round (/ diff gnus-demon-timestep)))))
 
@@ -198,6 +193,10 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
     ;; sufficiently ripe.
     (let ((handlers gnus-demon-handler-state)
          (gnus-inhibit-demon t)
+         ;; Try to avoid dialog boxes, e.g. by Mailcrypt.
+         ;; Unfortunately, Emacs 20's `message-or-box...' doesn't
+         ;; obey `use-dialog-box'.
+         use-dialog-box (last-nonmenu-event 10)
          handler time idle)
       (while handlers
        (setq handler (pop handlers))
@@ -265,12 +264,11 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
   "Add daemonic nntp server disconnection to Gnus.
 If no commands have gone out via nntp during the last five
 minutes, the connection is closed."
-  (gnus-demon-add-handler 'gnus-demon-close-connections 5 nil))
+  (gnus-demon-add-handler 'gnus-demon-nntp-close-connections 5 nil))
 
 (defun gnus-demon-nntp-close-connection ()
   (save-window-excursion
-    (when (nnmail-time-less '(0 300)
-                           (nnmail-time-since nntp-last-command-time))
+    (when (time-less-p '(0 300) (time-since nntp-last-command-time))
       (nntp-close-server))))
 
 (defun gnus-demon-add-scanmail ()
@@ -280,8 +278,8 @@ minutes, the connection is closed."
 (defun gnus-demon-scan-mail ()
   (save-window-excursion
     (let ((servers gnus-opened-servers)
-         server)
-      (gnus-clear-inboxes-moved)
+         server
+         (nnmail-fetched-sources (list t)))
       (while (setq server (car (pop servers)))
        (and (gnus-check-backend-function 'request-scan (car server))
             (or (gnus-server-opened server)
diff --git a/lisp/gnus-diary.el b/lisp/gnus-diary.el
new file mode 100644 (file)
index 0000000..dafb8c3
--- /dev/null
@@ -0,0 +1,469 @@
+;;; gnus-diary.el --- Wrapper around the NNDiary Gnus backend
+
+;; Copyright (c) 2001, 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001 Didier Verna.
+
+;; Author:        Didier Verna <didier@xemacs.org>
+;; Maintainer:    Didier Verna <didier@xemacs.org>
+;; Created:       Tue Jul 20 10:42:55 1999
+;; Keywords:      calendar mail news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2 of the License,
+;; or (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;; Commentary:
+
+;; Contents management by FCM version 0.1.
+
+;; Description:
+;; ===========
+
+;; Gnus-Diary is a wrapper around the NNDiary Gnus backend.  It is here to
+;; make your nndiary-user life easier in different ways.  So, you don't have
+;; to use it if you don't want to.  But, really, you should.
+
+;; Gnus-Diary offers the following features on top of the NNDiary backend:
+
+;;  - A nice summary line format:
+;;    Displaying diary messages in standard summary line format (usually
+;;    something like "<From Joe>: <Subject>") is pretty useless.  Most of the
+;;    time, you're the one who wrote the message, and you mostly want to see
+;;    the event's date.  Gnus-Diary offers you a nice summary line format
+;;    which will do this.  By default, a summary line will appear like this:
+;;
+;;     <Event Date>: <Subject> <Remaining time>
+;;
+;;   for example, here's how Joe's birthday is displayed in my
+;;   "nndiary:birhdays" summary buffer (the message is expirable, but will
+;;   never be deleted, as it specifies a regular event):
+;;
+;;   E  Sat, Sep 22 01, 12:00: Joe's birthday (in 6 months, 1 week)
+
+;;  - More article sorting functions:
+;;    Gnus-Diary adds a new sorting function called
+;;    `gnus-summary-sort-by-schedule'.  This function lets you organize your
+;;    diary summary buffers from the closest event to the farthest one.
+
+;;  - Automatic generation of diary group parameters:
+;;    When you create a new diary group, or visit one, Gnus-Diary checks your
+;;    group parameters, and if needed, sets the summary line format to the
+;;    diary-specific value, adds the diary-specific sorting functions, and
+;;    also adds the different `X-Diary-*' headers to the group's
+;;    posting-style.  It is then easier to send a diary message, because if
+;;    you use `C-u a' or `C-u m' on a diary group to prepare a message, these
+;;    headers will be inserted automatically (but not filled with proper
+;;    values yet).
+
+;;  - An interactive mail-to-diary convertion function:
+;;    The function `gnus-diary-check-message' ensures that the current message
+;;    contains all the required diary headers, and prompts you for values /
+;;    correction if needed.  This function is hooked in the nndiary backend so
+;;    that moving an article to an nndiary group will trigger it
+;;    automatically.  It is also bound to `C-c D c' in message-mode and
+;;    article-edit-mode in order to ease the process of converting a usual
+;;    mail to a diary one.  This function takes a prefix argument which will
+;;    force prompting of all diary headers, regardless of their
+;;    presence/validity.  That way, you can very easily reschedule a diary
+;;    message for instance.
+
+
+;; Usage:
+;; =====
+
+;; 0/ Don't use any `gnus-user-format-function-[d|D]'.  Gnus-Diary provides
+;;    both of these (sorry if you used them before).
+;; 1/ Add '(require 'gnus-diary) to your gnusrc file.
+;; 2/ Customize your gnus-diary options to suit your needs.
+
+
+
+;; Bugs / Todo:
+;; ===========
+
+
+;;; Code:
+
+(require 'nndiary)
+(require 'message)
+(require 'gnus-art)
+
+(defgroup gnus-diary nil
+  "Utilities on top of the nndiary backend for Gnus.")
+
+(defcustom gnus-diary-summary-line-format "%U%R%z %uD: %(%s%) (%ud)\n"
+  "*Summary line format for nndiary groups."
+  :type 'string
+  :group 'gnus-diary
+  :group 'gnus-summary-format)
+
+(defcustom gnus-diary-time-format "%a, %b %e %y, %H:%M"
+  "*Time format to display appointements in nndiary summary buffers.
+Please refer to `format-time-string' for information on possible values."
+  :type 'string
+  :group 'gnus-diary)
+
+(defcustom gnus-diary-delay-format-function 'gnus-diary-delay-format-english
+  "*Function called to format a diary delay string.
+It is passed two arguments.  The first one is non nil if the delay is in
+the past.  The second one is of the form ((NUM . UNIT) ...) where NUM is
+an integer and UNIT is one of 'year 'month 'week 'day 'hour or 'minute.
+It should return strings like \"In 2 months, 3 weeks\", \"3 hours,
+1 minute ago\" and so on.
+
+There are currently two built-in format functions:
+`gnus-diary-delay-format-english' (the default)
+`gnus-diary-delay-format-french'"
+  :type '(choice (const  :tag "english" gnus-diary-delay-format-english)
+                (const  :tag "french"  gnus-diary-delay-format-french)
+                (symbol :tag "other"))
+  :group 'gnus-diary)
+
+(defconst gnus-diary-version nndiary-version
+  "Current Diary backend version.")
+
+
+;; Compatibility functions ==================================================
+
+(eval-and-compile
+  (if (fboundp 'kill-entire-line)
+      (defalias 'gnus-diary-kill-entire-line 'kill-entire-line)
+    (defun gnus-diary-kill-entire-line ()
+      (beginning-of-line)
+      (let ((kill-whole-line t))
+       (kill-line)))))
+
+
+;; Summary line format ======================================================
+
+(defun gnus-diary-delay-format-french (past delay)
+  (if (null delay)
+      "maintenant!"
+    ;; Keep only a precision of two degrees
+    (and (> (length delay) 1) (setcdr (cdr delay) nil))
+    (concat (if past "il y a " "dans ")
+           (let ((str "")
+                 del)
+             (while (setq del (pop delay))
+               (setq str (concat str
+                                 (int-to-string (car del)) " "
+                                 (cond ((eq (cdr del) 'year)
+                                        "an")
+                                       ((eq (cdr del) 'month)
+                                        "mois")
+                                       ((eq (cdr del) 'week)
+                                        "semaine")
+                                       ((eq (cdr del) 'day)
+                                        "jour")
+                                       ((eq (cdr del) 'hour)
+                                        "heure")
+                                       ((eq (cdr del) 'minute)
+                                        "minute"))
+                                 (unless (or (eq (cdr del) 'month)
+                                             (= (car del) 1))
+                                   "s")
+                                 (if delay ", "))))
+             str))))
+
+
+(defun gnus-diary-delay-format-english (past delay)
+  (if (null delay)
+      "now!"
+    ;; Keep only a precision of two degrees
+    (and (> (length delay) 1) (setcdr (cdr delay) nil))
+    (concat (unless past "in ")
+           (let ((str "")
+                 del)
+             (while (setq del (pop delay))
+               (setq str (concat str
+                                 (int-to-string (car del)) " "
+                                 (symbol-name (cdr del))
+                                 (and (> (car del) 1) "s")
+                                 (if delay ", "))))
+             str)
+           (and past " ago"))))
+
+
+(defun gnus-diary-header-schedule (headers)
+  ;; Same as `nndiary-schedule', but given a set of headers HEADERS
+  (mapcar
+   (lambda (elt)
+     (let ((head (cdr (assoc (intern (format "X-Diary-%s" (car elt)))
+                            headers))))
+       (when head
+        (nndiary-parse-schedule-value head (cadr elt) (caddr elt)))))
+   nndiary-headers))
+
+;; #### NOTE: Gnus sometimes gives me a HEADER not corresponding to any
+;; message, with all fields set to nil here. I don't know what it is for, and
+;; I just ignore it.
+(defun gnus-user-format-function-d (header)
+  ;; Returns an aproximative delay string for the next occurence of this
+  ;; message. The delay is given only in the first non zero unit.
+  ;; Code partly stolen from article-make-date-line
+  (let* ((extras (mail-header-extra header))
+        (sched (gnus-diary-header-schedule extras))
+        (occur (nndiary-next-occurence sched (current-time)))
+        (now (current-time))
+        (real-time (subtract-time occur now)))
+    (if (null real-time)
+       "?????"
+      (let* ((sec (+ (* (float (car real-time)) 65536) (cadr real-time)))
+            (past (< sec 0))
+            delay)
+       (and past (setq sec (- sec)))
+       (unless (zerop sec)
+         ;; This is a bit convoluted, but basically we go through the time
+         ;; units for years, weeks, etc, and divide things to see whether
+         ;; that results in positive answers.
+         (let ((units `((year . ,(* 365.25 24 3600))
+                        (month . ,(* 31 24 3600))
+                        (week . ,(* 7 24 3600))
+                        (day . ,(* 24 3600))
+                        (hour . 3600)
+                        (minute . 60)))
+               unit num)
+           (while (setq unit (pop units))
+             (unless (zerop (setq num (ffloor (/ sec (cdr unit)))))
+               (setq delay (append delay `((,(floor num) . ,(car unit))))))
+             (setq sec (- sec (* num (cdr unit)))))))
+       (funcall gnus-diary-delay-format-function past delay)))
+    ))
+
+;; #### NOTE: Gnus sometimes gives me a HEADER not corresponding to any
+;; message, with all fields set to nil here. I don't know what it is for, and
+;; I just ignore it.
+(defun gnus-user-format-function-D (header)
+  ;; Returns a formatted time string for the next occurence of this message.
+  (let* ((extras (mail-header-extra header))
+        (sched (gnus-diary-header-schedule extras))
+        (occur (nndiary-next-occurence sched (current-time))))
+    (format-time-string gnus-diary-time-format occur)))
+
+
+;; Article sorting functions ================================================
+
+(defun gnus-article-sort-by-schedule (h1 h2)
+  (let* ((now (current-time))
+        (e1 (mail-header-extra h1))
+        (e2 (mail-header-extra h2))
+        (s1 (gnus-diary-header-schedule e1))
+        (s2 (gnus-diary-header-schedule e2))
+        (o1 (nndiary-next-occurence s1 now))
+        (o2 (nndiary-next-occurence s2 now)))
+    (if (and (= (car o1) (car o2)) (= (cadr o1) (cadr o2)))
+       (< (mail-header-number h1) (mail-header-number h2))
+      (time-less-p o1 o2))))
+
+
+(defun gnus-thread-sort-by-schedule (h1 h2)
+  (gnus-article-sort-by-schedule (gnus-thread-header h1)
+                                (gnus-thread-header h2)))
+
+(defun gnus-summary-sort-by-schedule (&optional reverse)
+  "Sort nndiary summary buffers by schedule of appointements.
+Optional prefix (or REVERSE argument) means sort in reverse order."
+  (interactive "P")
+  (gnus-summary-sort 'schedule reverse))
+
+(defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning.
+;; The function `easy-menu-add-item' is not available under Emacs
+;; versions prior to 20.3.  Could anyone try to emulate it?
+(if (eval-when-compile
+      (require 'easymenu)
+      (or (fboundp 'easy-menu-add-item)
+         (progn
+           (defalias 'easy-menu-add-item 'ignore)
+           nil)))
+(add-hook 'gnus-summary-menu-hook
+         (lambda ()
+           (easy-menu-add-item gnus-summary-misc-menu
+                               '("Sort")
+                               ["Sort by schedule"
+                                gnus-summary-sort-by-schedule
+                                (eq (car (gnus-find-method-for-group
+                                          gnus-newsgroup-name))
+                                    'nndiary)]
+                               "Sort by number")))
+  )
+
+
+
+;; Group parameters autosetting =============================================
+
+(defun gnus-diary-update-group-parameters (group)
+  ;; Ensure that nndiary groups have convenient group parameters:
+  ;; - a posting style containing X-Diary headers
+  ;; - a nice summary line format
+  ;; - NNDiary specific sorting by schedule functions
+  ;; In general, try not to mess with what the user might have modified.
+  (let ((posting-style (gnus-group-get-parameter group 'posting-style t)))
+    ;; Posting style:
+    (mapcar (lambda (elt)
+             (let ((header (format "X-Diary-%s" (car elt))))
+               (unless (assoc header posting-style)
+                 (setq posting-style (append posting-style
+                                             `((,header "*")))))
+               ))
+           nndiary-headers)
+    (gnus-group-set-parameter group 'posting-style posting-style)
+    ;; Summary line format:
+    (unless (gnus-group-get-parameter group 'gnus-summary-line-format t)
+      (gnus-group-set-parameter group 'gnus-summary-line-format
+                               `(,gnus-diary-summary-line-format)))
+    ;; Sorting by schedule:
+    (unless (gnus-group-get-parameter group 'gnus-article-sort-functions)
+      (gnus-group-set-parameter group 'gnus-article-sort-functions
+                               '((append gnus-article-sort-functions
+                                         (list
+                                          'gnus-article-sort-by-schedule)))))
+    (unless (gnus-group-get-parameter group 'gnus-thread-sort-functions)
+      (gnus-group-set-parameter group 'gnus-thread-sort-functions
+                               '((append gnus-thread-sort-functions
+                                         (list
+                                          'gnus-thread-sort-by-schedule)))))
+    ))
+
+;; Called when a group is subscribed. This is needed because groups created
+;; because of mail splitting are *not* created with the backend function.
+;; Thus, `nndiary-request-create-group-hooks' is inoperative.
+(defun gnus-diary-maybe-update-group-parameters (group)
+  (when (eq (car (gnus-find-method-for-group group)) 'nndiary)
+    (gnus-diary-update-group-parameters group)))
+
+(add-hook 'nndiary-request-create-group-hooks
+         'gnus-diary-update-group-parameters)
+;; Now that we have `gnus-subscribe-newsgroup-hooks', this is not needed
+;; anymore. Maybe I should remove this completely.
+(add-hook 'nndiary-request-update-info-hooks
+         'gnus-diary-update-group-parameters)
+(add-hook 'gnus-subscribe-newsgroup-hooks
+         'gnus-diary-maybe-update-group-parameters)
+
+
+;; Diary Message Checking ===================================================
+
+(defvar gnus-diary-header-value-history nil
+  ;; History variable for header value prompting
+  )
+
+(defun gnus-diary-narrow-to-headers ()
+  "Narrow the current buffer to the header part.
+Point is left at the beginning of the region.
+The buffer is assumed to contain a message, but the format is unknown."
+  (cond ((eq major-mode 'message-mode)
+        (message-narrow-to-headers))
+       (t
+        (goto-char (point-min))
+        (when (search-forward "\n\n" nil t)
+          (narrow-to-region (point-min) (- (point) 1))
+          (goto-char (point-min))))
+       ))
+
+(defun gnus-diary-add-header (str)
+  "Add a header to the current buffer.
+The buffer is assumed to contain a message, but the format is unknown."
+  (cond ((eq major-mode 'message-mode)
+        (message-add-header str))
+       (t
+        (save-restriction
+          (gnus-diary-narrow-to-headers)
+          (goto-char (point-max))
+          (if (string-match "\n$" str)
+              (insert str)
+            (insert str ?\n))))
+       ))
+
+(defun gnus-diary-check-message (arg)
+  "Ensure that the current message is a valid for NNDiary.
+This function checks that all NNDiary required headers are present and
+valid, and prompts for values / correction otherwise.
+
+If ARG (or prefix) is non-nil, force prompting for all fields."
+  (interactive "P")
+  (save-excursion
+    (mapcar
+     (lambda (head)
+       (let ((header (concat "X-Diary-" (car head)))
+            (ask arg)
+            value invalid)
+        ;; First, try to find the header, and checks for validity:
+        (save-restriction
+          (gnus-diary-narrow-to-headers)
+          (when (re-search-forward (concat "^" header ":") nil t)
+            (unless (eq (char-after) ? )
+              (insert " "))
+            (setq value (buffer-substring (point) (gnus-point-at-eol)))
+            (and (string-match "[ \t]*\\([^ \t]+\\)[ \t]*" value)
+                 (setq value (match-string 1 value)))
+            (condition-case ()
+                (nndiary-parse-schedule-value value
+                                              (nth 1 head) (nth 2 head))
+              (t
+               (setq invalid t)))
+            ;; #### NOTE: this (along with the `gnus-diary-add-header'
+            ;; function) could be rewritten in a better way, in particular
+            ;; not to blindly remove an already present header and reinsert
+            ;; it somewhere else afterwards.
+            (when (or ask invalid)
+              (gnus-diary-kill-entire-line))
+            ))
+        ;; Now, loop until a valid value is provided:
+        (while (or ask (not value) invalid)
+          (let ((prompt (concat (and invalid
+                                     (prog1 "(current value invalid) "
+                                       (beep)))
+                                header ": ")))
+            (setq value
+                  (if (listp (nth 1 head))
+                      (completing-read prompt (cons '("*" nil) (nth 1 head))
+                                       nil t value
+                                       gnus-diary-header-value-history)
+                    (read-string prompt value
+                                 gnus-diary-header-value-history))))
+          (setq ask nil)
+          (setq invalid nil)
+          (condition-case ()
+              (nndiary-parse-schedule-value value
+                                            (nth 1 head) (nth 2 head))
+            (t
+             (setq invalid t))))
+        (gnus-diary-add-header (concat header ": " value))
+        ))
+     nndiary-headers)
+    ))
+
+(add-hook 'nndiary-request-accept-article-hooks
+         (lambda () (gnus-diary-check-message nil)))
+
+(define-key message-mode-map "\C-cDc" 'gnus-diary-check-message)
+(define-key gnus-article-edit-mode-map "\C-cDc" 'gnus-diary-check-message)
+
+
+;; The end ==================================================================
+
+(defun gnus-diary-version ()
+  "Current Diary backend version."
+  (interactive)
+  (message "NNDiary version %s" nndiary-version))
+
+(define-key message-mode-map "\C-cDv" 'gnus-diary-version)
+(define-key gnus-article-edit-mode-map "\C-cDv" 'gnus-diary-version)
+
+
+(provide 'gnus-diary)
+
+;;; gnus-diary.el ends here
diff --git a/lisp/gnus-dired.el b/lisp/gnus-dired.el
new file mode 100644 (file)
index 0000000..1fa657f
--- /dev/null
@@ -0,0 +1,206 @@
+;;; gnus-dired.el --- utility functions where gnus and dired meet
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
+
+;; Authors: Benjamin Rutt <brutt@bloomington.in.us>,
+;;          Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: mail, news, extensions
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package provides utility functions for intersections of gnus
+;; and dired.  To enable the gnus-dired-mode minor mode which will
+;; have the effect of installing keybindings in dired-mode, place the
+;; following in your ~/.gnus:
+
+;; (require 'gnus-dired) ;, isn't needed due to autoload cookies
+;; (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
+
+;; Note that if you visit dired buffers before your ~/.gnus file has
+;; been read, those dired buffers won't have the keybindings in
+;; effect.  To get around that problem, you may want to add the above
+;; statements to your ~/.emacs instead.
+
+;;; Code:
+
+(require 'dired)
+(require 'gnus-ems)
+(require 'gnus-msg)
+(require 'gnus-util)
+(require 'message)
+(require 'mm-encode)
+(require 'mml)
+
+(defvar gnus-dired-mode nil
+  "Minor mode for intersections of gnus and dired.")
+
+(defvar gnus-dired-mode-map nil)
+
+(unless gnus-dired-mode-map
+  (setq gnus-dired-mode-map (make-sparse-keymap))
+
+  (gnus-define-keys gnus-dired-mode-map
+    "\C-c\C-m\C-a" gnus-dired-attach
+    "\C-c\C-m\C-l" gnus-dired-find-file-mailcap
+    "\C-c\C-m\C-p" gnus-dired-print))
+
+(defun gnus-dired-mode (&optional arg)
+  "Minor mode for intersections of gnus and dired.
+
+\\{gnus-dired-mode-map}"
+  (interactive "P")
+  (when (eq major-mode 'dired-mode)
+    (set (make-local-variable 'gnus-dired-mode)
+        (if (null arg) (not gnus-dired-mode)
+          (> (prefix-numeric-value arg) 0)))
+    (when gnus-dired-mode
+      (gnus-add-minor-mode 'gnus-dired-mode "" gnus-dired-mode-map)
+      (gnus-run-hooks 'gnus-dired-mode-hook))))
+
+;;;###autoload
+(defun turn-on-gnus-dired-mode ()
+  "Convenience method to turn on gnus-dired-mode."
+  (gnus-dired-mode 1))
+
+;; Method to attach files to a gnus composition.
+(defun gnus-dired-attach (files-to-attach)
+  "Attach dired's marked files to a gnus message composition.
+If called non-interactively, FILES-TO-ATTACH should be a list of
+filenames."
+  (interactive
+   (list
+    (delq nil
+         (mapcar
+          ;; don't attach directories
+          (lambda (f) (if (file-directory-p f) nil f))
+          (nreverse (dired-map-over-marks (dired-get-filename) nil))))))
+  (let ((destination nil)
+       (files-str nil)
+       (bufs nil))
+    ;; warn if user tries to attach without any files marked
+    (if (null files-to-attach)
+       (error "No files to attach")
+      (setq files-str
+           (mapconcat
+            (lambda (f) (file-name-nondirectory f))
+            files-to-attach ", "))
+      (setq bufs (message-buffers))
+
+      ;; set up destination message buffer
+      (if (and bufs
+              (y-or-n-p "Attach files to existing message buffer? "))
+         (setq destination
+               (if (= (length bufs) 1)
+                   (get-buffer (car bufs))
+                 (completing-read "Attach to which message buffer: "
+                                  (mapcar
+                                   (lambda (b)
+                                     (cons b (get-buffer b)))
+                                   bufs)
+                                  nil t)))
+       ;; setup a new gnus message buffer
+       (gnus-setup-message 'message (message-mail))
+       (setq destination (current-buffer)))
+
+      ;; set buffer to destination buffer, and attach files
+      (set-buffer destination)
+      (goto-char (point-max))          ;attach at end of buffer
+      (while files-to-attach
+       (mml-attach-file (car files-to-attach)
+                        (or (mm-default-file-encoding (car files-to-attach))
+                            "application/octet-stream") nil)
+       (setq files-to-attach (cdr files-to-attach)))
+      (message "Attached file(s) %s" files-str))))
+
+(autoload 'mailcap-parse-mailcaps "mailcap" "" t)
+
+(defun gnus-dired-find-file-mailcap (&optional file-name arg)
+  "In dired, visit FILE-NAME according to the mailcap file.
+If ARG is non-nil, open it in a new buffer."
+  (interactive (list
+               (file-name-sans-versions (dired-get-filename) t)
+               current-prefix-arg))
+  (mailcap-parse-mailcaps)
+  (if (file-exists-p file-name)
+      (let (mime-type method)
+       (if (and (not arg)
+                (not (file-directory-p file-name))
+                (string-match "\\.[^\\.]+$" file-name)
+                (setq mime-type
+                      (mailcap-extension-to-mime
+                       (match-string 0 file-name)))
+                (stringp
+                 (setq method
+                       (cdr (assoc 'viewer
+                                   (car (mailcap-mime-info mime-type
+                                                           'all)))))))
+           (let ((view-command (mm-mailcap-command method file-name nil)))
+             (message "viewing via %s" view-command)
+             (start-process "*display*"
+                            nil
+                            shell-file-name
+                            shell-command-switch
+                            view-command))
+         (find-file file-name)))
+    (if (file-symlink-p file-name)
+       (error "File is a symlink to a nonexistent target")
+      (error "File no longer exists; type `g' to update Dired buffer"))))
+
+(defun gnus-dired-print (&optional file-name print-to)
+  "In dired, print FILE-NAME according to the mailcap file.
+
+If there is no print command, print in a PostScript image. If the
+optional argument PRINT-TO is nil, send the image to the printer. If
+PRINT-TO is a string, save the PostScript image in a file with that
+name.  If PRINT-TO is a number, prompt the user for the name of the
+file to save in."
+  (interactive (list
+               (file-name-sans-versions (dired-get-filename) t)
+               (ps-print-preprint current-prefix-arg)))
+  (mailcap-parse-mailcaps)
+  (cond
+   ((file-directory-p file-name)
+    (error "Can't print a directory"))
+   ((file-exists-p file-name)
+    (let (mime-type method)
+      (if (and (string-match "\\.[^\\.]+$" file-name)
+              (setq mime-type
+                    (mailcap-extension-to-mime
+                     (match-string 0 file-name)))
+              (stringp
+               (setq method (mailcap-mime-info mime-type "print"))))
+         (call-process shell-file-name nil
+                       (generate-new-buffer " *mm*")
+                       nil
+                       shell-command-switch
+                       (mm-mailcap-command method file-name mime-type))
+       (with-temp-buffer
+         (insert-file-contents file-name)
+         (gnus-print-buffer))
+       (ps-despool print-to))))
+   ((file-symlink-p file-name)
+     (error "File is a symlink to a nonexistent target"))
+    (t
+     (error "File no longer exists; type `g' to update Dired buffer"))))
+
+(provide 'gnus-dired)
+
+;;; gnus-dired.el ends here
index cb3c145..a0774ef 100644 (file)
@@ -1,8 +1,11 @@
-;;; gnus-draft.el --- draft message support for Gnus
-;; Copyright (C) 1997,98 Free Software Foundation, Inc.
+;;; gnus-draft.el --- draft message support for Semi-gnus
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtgnus-run-hooks
-;; Keywords: news
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;; Keywords: mail, news, MIME, offline
 
 ;; This file is part of GNU Emacs.
 
@@ -30,6 +33,7 @@
 (require 'message)
 (require 'gnus-msg)
 (require 'nndraft)
+(require 'gnus-agent)
 (eval-when-compile (require 'cl))
 
 ;;; Draft minor mode
@@ -44,6 +48,7 @@
 
   (gnus-define-keys gnus-draft-mode-map
     "Dt" gnus-draft-toggle-sending
+    "e"  gnus-draft-edit-message ;; Use `B w' for `gnus-summary-edit-article'
     "De" gnus-draft-edit-message
     "Ds" gnus-draft-send-message
     "DS" gnus-draft-send-all-messages))
@@ -66,8 +71,8 @@
   (interactive "P")
   (when (eq major-mode 'gnus-summary-mode)
     (when (set (make-local-variable 'gnus-draft-mode)
-                 (if (null arg) (not gnus-draft-mode)
-                   (> (prefix-numeric-value arg) 0)))
+              (if (null arg) (not gnus-draft-mode)
+                (> (prefix-numeric-value arg) 0)))
       ;; Set up the menu.
       (when (gnus-visual-p 'draft-menu 'menu)
        (gnus-draft-make-menu-bar))
 (defun gnus-draft-edit-message ()
   "Enter a mail/post buffer to edit and send the draft."
   (interactive)
-  (let ((article (gnus-summary-article-number)))
+  (let ((article (gnus-summary-article-number))
+       (group gnus-newsgroup-name))
     (gnus-summary-mark-as-read article gnus-canceled-mark)
-    (gnus-draft-setup article gnus-newsgroup-name)
+    (gnus-draft-setup article group t)
+    (set-buffer-modified-p t)
+    (save-excursion
+      (save-restriction
+       (message-narrow-to-headers)
+       (message-remove-header "date")))
+    (save-buffer)
+    (let ((gnus-verbose-backends nil))
+      (gnus-request-expire-articles (list article) group t))
     (push
      `((lambda ()
-        (when (buffer-name (get-buffer ,gnus-summary-buffer))
+        (when (gnus-buffer-exists-p ,gnus-summary-buffer)
           (save-excursion
-            (set-buffer (get-buffer ,gnus-summary-buffer))
+            (set-buffer ,gnus-summary-buffer)
             (gnus-cache-possibly-remove-article ,article nil nil nil t)))))
      message-send-actions)))
 
 (defun gnus-draft-send-message (&optional n)
   "Send the current draft."
   (interactive "P")
-  (let ((articles (gnus-summary-work-articles n))
-       article)
+  (let* ((articles (gnus-summary-work-articles n))
+        (total (length articles))
+        article)
     (while (setq article (pop articles))
       (gnus-summary-remove-process-mark article)
       (unless (memq article gnus-newsgroup-unsendable)
-       (gnus-draft-send article gnus-newsgroup-name)
+       (let ((message-sending-message
+              (format "Sending message %d of %d..."
+                      (- total (length articles)) total)))
+         (gnus-draft-send article gnus-newsgroup-name t))
        (gnus-summary-mark-article article gnus-canceled-mark)))))
 
-(defun gnus-draft-send (article &optional group)
+(defun gnus-draft-send (article &optional group interactive)
   "Send message ARTICLE."
-  (gnus-draft-setup article (or group "nndraft:queue"))
-  (let ((message-syntax-checks 'dont-check-for-anything-just-trust-me)
-       message-send-hook)
-    (message-send-and-exit)))
+  (let ((message-syntax-checks (if interactive message-syntax-checks
+                                'dont-check-for-anything-just-trust-me))
+       (message-hidden-headers nil)
+       (message-inhibit-body-encoding (or (not group)
+                                          (equal group "nndraft:queue")
+                                          message-inhibit-body-encoding))
+       (message-send-hook (and group (not (equal group "nndraft:queue"))
+                               message-send-hook))
+       (message-setup-hook (and group (not (equal group "nndraft:queue"))
+                                message-setup-hook))
+       type method move-to)
+    (gnus-draft-setup article (or group "nndraft:queue"))
+    ;; We read the meta-information that says how and where
+    ;; this message is to be sent.
+    (save-restriction
+      (message-narrow-to-head)
+      (when (re-search-forward
+            (concat "^" (regexp-quote gnus-agent-target-move-group-header)
+                    ":") nil t)
+       (skip-syntax-forward "-")
+       (setq move-to (buffer-substring (point) (gnus-point-at-eol)))
+       (message-remove-header gnus-agent-target-move-group-header))
+      (goto-char (point-min))
+      (when (re-search-forward
+            (concat "^" (regexp-quote gnus-agent-meta-information-header) ":")
+            nil t)
+       (setq type (ignore-errors (read (current-buffer)))
+             method (ignore-errors (read (current-buffer))))
+       (message-remove-header gnus-agent-meta-information-header)))
+    ;; Let Agent restore any GCC lines and have message.el perform them.
+    (gnus-agent-restore-gcc)
+    ;; Then we send it.  If we have no meta-information, we just send
+    ;; it and let Message figure out how.
+    (when (and (or (null method)
+                  (gnus-server-opened method)
+                  (gnus-open-server method))
+              (if type
+                  (let ((message-this-is-news (eq type 'news))
+                        (message-this-is-mail (eq type 'mail))
+                        (gnus-post-method method)
+                        (message-post-method method))
+                    (if move-to
+                        (gnus-inews-do-gcc move-to)
+                      (message-send-and-exit)))
+                (if move-to
+                    (gnus-inews-do-gcc move-to)
+                  (message-send-and-exit))))
+      (let ((gnus-verbose-backends nil))
+       (gnus-request-expire-articles
+        (list article) (or group "nndraft:queue") t)))))
 
 (defun gnus-draft-send-all-messages ()
   "Send all the sendable drafts."
   (interactive)
-  (gnus-uu-mark-buffer)
-  (gnus-draft-send-message))
+  (when (or
+        gnus-expert-user
+        (gnus-y-or-n-p
+         "Send all drafts? "))
+    (gnus-uu-mark-buffer)
+    (gnus-draft-send-message)))
 
-(defun gnus-group-send-drafts ()
+(defun gnus-group-send-queue ()
   "Send all sendable articles from the queue group."
   (interactive)
   (gnus-activate-group "nndraft:queue")
   (save-excursion
-    (let ((articles (nndraft-articles))
-         (unsendable (gnus-uncompress-range
-                      (cdr (assq 'unsend
-                                 (gnus-info-marks
-                                  (gnus-get-info "nndraft:queue"))))))
-         article)
+    (let* ((articles (nndraft-articles))
+          (unsendable (gnus-uncompress-range
+                       (cdr (assq 'unsend
+                                  (gnus-info-marks
+                                   (gnus-get-info "nndraft:queue"))))))
+          (gnus-posting-styles nil)
+          (total (length articles))
+          article)
       (while (setq article (pop articles))
        (unless (memq article unsendable)
-         (gnus-draft-send article))))))
+         (let ((message-sending-message
+                (format "Sending message %d of %d..."
+                        (- total (length articles)) total)))
+           (gnus-draft-send article)))))))
+
+;;;###autoload
+(defun gnus-draft-reminder ()
+  "Reminder user if there are unsent drafts."
+  (interactive)
+  (if (gnus-alive-p)
+      (let (active)
+       (catch 'continue
+         (dolist (group '("nndraft:drafts" "nndraft:queue"))
+           (setq active (gnus-activate-group group))
+           (if (and active (>= (cdr active) (car active)))
+               (if (y-or-n-p "There are unsent drafts.  Confirm to exit? ")
+                   (throw 'continue t)
+                 (error "Stop!"))))))))
 
 ;;; Utility functions
 
+(defcustom gnus-draft-decoding-function
+  #'mime-edit-decode-message-in-buffer
+  "*Function called to decode the message from network representation."
+  :group 'gnus-agent
+  :type 'function)
+
 ;;;!!!If this is byte-compiled, it fails miserably.
-;;;!!!I have no idea why.
-
-(progn
-(defun gnus-draft-setup (narticle group)
-  (gnus-setup-message 'forward
-    (let ((article narticle))
-      (message-mail)
-      (erase-buffer)
-      (if (not (gnus-request-restore-buffer article group))
-         (error "Couldn't restore the article")
-       ;; Insert the separator.
-       (goto-char (point-min))
-       (search-forward "\n\n")
-       (forward-char -1)
-       (insert mail-header-separator)
-       (forward-line 1)
-       (message-set-auto-save-file-name))))))
+;;;!!!This is because `gnus-setup-message' uses uninterned symbols.
+;;;!!!This has been fixed in recent versions of Emacs and XEmacs,
+;;;!!!but for the time being, we'll just run this tiny function uncompiled.
+
+(defun gnus-draft-setup (narticle group &optional restore)
+  (let (ga)
+    (gnus-setup-message 'forward
+      (let ((article narticle))
+       (message-mail)
+       (erase-buffer)
+       (if (not (gnus-request-restore-buffer article group))
+           (error "Couldn't restore the article")
+         (when (and restore
+                    (equal group "nndraft:queue"))
+           (funcall gnus-draft-decoding-function))
+         ;; Insert the separator.
+         (goto-char (point-min))
+         (search-forward "\n\n")
+         (forward-char -1)
+         (insert mail-header-separator)
+         (forward-line 1)
+         (setq ga (message-fetch-field gnus-draft-meta-information-header))
+         (message-set-auto-save-file-name))))
+    (gnus-backlog-remove-article group narticle)
+    (when (and ga
+              (ignore-errors (setq ga (car (read-from-string ga)))))
+      (setq gnus-newsgroup-name
+           (if (equal (car ga) "") nil (car ga)))
+      (gnus-configure-posting-styles)
+      (setq gnus-message-group-art (cons gnus-newsgroup-name (cadr ga)))
+      (setq message-post-method
+           `(lambda (arg)
+              (gnus-post-method arg ,(car ga))))
+      (unless (equal (cadr ga) "")
+       (message-add-action
+        `(progn
+           (gnus-add-mark ,(car ga) 'replied ,(cadr ga))
+           (gnus-request-set-mark ,(car ga) (list (list (list ,(cadr ga))
+                                                        'add '(reply)))))
+        'send)))))
 
 (defun gnus-draft-article-sendable-p (article)
   "Say whether ARTICLE is sendable."
index 3fd5795..a2b5544 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-dup.el --- suppression of duplicate articles in Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -98,7 +99,7 @@ seen in the same session."
   "Save the duplicate suppression list."
   (when (and gnus-save-duplicate-list
             gnus-dup-list-dirty)
-    (nnheader-temp-write gnus-duplicate-file
+    (with-temp-file gnus-duplicate-file
       (gnus-prin1 `(setq gnus-dup-list ',gnus-dup-list))))
   (setq gnus-dup-list-dirty nil))
 
@@ -112,7 +113,7 @@ seen in the same session."
     (gnus-dup-open))
   (setq gnus-dup-list-dirty t)         ; mark list for saving
   (let ((data gnus-newsgroup-data)
-       datum msgid)
+       datum msgid)
     ;; Enter the Message-IDs of all read articles into the list
     ;; and hash table.
     (while (setq datum (pop data))
@@ -120,11 +121,11 @@ seen in the same session."
                 (> (gnus-data-number datum) 0)
                 (not (memq (gnus-data-number datum) gnus-newsgroup-unreads))
                 (not (= (gnus-data-mark datum) gnus-canceled-mark))
-                (setq msgid (mail-header-id (gnus-data-header datum)))
-                (not (nnheader-fake-message-id-p msgid))
-                (not (intern-soft msgid gnus-dup-hashtb)))
+                (setq msgid (mail-header-id (gnus-data-header datum)))
+                (not (nnheader-fake-message-id-p msgid))
+                (not (intern-soft msgid gnus-dup-hashtb)))
        (push msgid gnus-dup-list)
-       (intern msgid gnus-dup-hashtb))))
+       (intern msgid gnus-dup-hashtb))))
   ;; Chop off excess Message-IDs from the list.
   (let ((end (nthcdr gnus-duplicate-list-length gnus-dup-list)))
     (when end
@@ -136,6 +137,8 @@ seen in the same session."
     (gnus-dup-open))
   (gnus-message 6 "Suppressing duplicates...")
   (let ((headers gnus-newsgroup-headers)
+       (auto (and gnus-newsgroup-auto-expire
+                  (memq gnus-duplicate-mark gnus-auto-expirable-marks)))
        number header)
     (while (setq header (pop headers))
       (when (and (intern-soft (mail-header-id header) gnus-dup-hashtb)
@@ -143,8 +146,10 @@ seen in the same session."
        (setq gnus-newsgroup-unreads
              (delq (setq number (mail-header-number header))
                    gnus-newsgroup-unreads))
-       (push (cons number gnus-duplicate-mark)
-             gnus-newsgroup-reads))))
+       (if (not auto)
+           (push (cons number gnus-duplicate-mark) gnus-newsgroup-reads)
+         (push number gnus-newsgroup-expirable)
+         (push (cons number gnus-expirable-mark) gnus-newsgroup-reads)))))
   (gnus-message 6 "Suppressing duplicates...done"))
 
 (defun gnus-dup-unsuppress-article (article)
index 7cb3f7c..042f8c3 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-eform.el --- a mode for editing forms for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Internal variables
 
-(defvar gnus-edit-form-done-function nil)
 (defvar gnus-edit-form-buffer "*Gnus edit form*")
+(defvar gnus-edit-form-done-function nil)
 
 (defvar gnus-edit-form-mode-map nil)
 (unless gnus-edit-form-mode-map
-  (setq gnus-edit-form-mode-map (copy-keymap emacs-lisp-mode-map))
+  (setq gnus-edit-form-mode-map (make-sparse-keymap))
+  (set-keymap-parent gnus-edit-form-mode-map emacs-lisp-mode-map)
   (gnus-define-keys gnus-edit-form-mode-map
     "\C-c\C-c" gnus-edit-form-done
     "\C-c\C-k" gnus-edit-form-exit))
@@ -88,9 +90,8 @@ It is a slightly enhanced emacs-lisp-mode.
 Call EXIT-FUNC on exit.  Display DOCUMENTATION in the beginning
 of the buffer."
   (let ((winconf (current-window-configuration)))
-    (set-buffer (get-buffer-create gnus-edit-form-buffer))
+    (set-buffer (gnus-get-buffer-create gnus-edit-form-buffer))
     (gnus-configure-windows 'edit-form)
-    (gnus-add-current-to-buffer-list)
     (gnus-edit-form-mode)
     (setq gnus-prev-winconf winconf)
     (setq gnus-edit-form-done-function exit-func)
@@ -113,7 +114,9 @@ of the buffer."
   "Update changes and kill the current buffer."
   (interactive)
   (goto-char (point-min))
-  (let ((form (read (current-buffer)))
+  (let ((form (condition-case nil
+                 (read (current-buffer))
+               (end-of-file nil)))
        (func gnus-edit-form-done-function))
     (gnus-edit-form-exit)
     (funcall func form)))
index d7e8fb8..d2dde41 100644 (file)
@@ -1,7 +1,9 @@
-;;; gnus-ems.el --- functions for making Gnus work under different Emacsen
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;;; gnus-ems.el --- functions for making Semi-gnus work under different Emacsen
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         Tatsuya Ichikawa <t-ichi@niagara.shiojiri.ne.jp>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile
+  (require 'cl)
+  (require 'ring))
 
 ;;; Function aliases later to be redefined for XEmacs usage.
 
-(defvar gnus-xemacs (string-match "XEmacs\\|Lucid" emacs-version)
-  "Non-nil if running under XEmacs.")
-
 (defvar gnus-mouse-2 [mouse-2])
+(defvar gnus-down-mouse-3 [down-mouse-3])
 (defvar gnus-down-mouse-2 [down-mouse-2])
+(defvar gnus-widget-button-keymap nil)
 (defvar gnus-mode-line-modified
-  (if (or gnus-xemacs
+  (if (or (featurep 'xemacs)
          (< emacs-major-version 20))
       '("--**-" . "-----")
     '("**" "--")))
 (eval-and-compile
   (autoload 'gnus-xmas-define "gnus-xmas")
   (autoload 'gnus-xmas-redefine "gnus-xmas")
-  (autoload 'appt-select-lowest-window "appt"))
-
-(or (fboundp 'mail-file-babyl-p)
-    (fset 'mail-file-babyl-p 'rmail-file-p))
+  (autoload 'appt-select-lowest-window "appt")
+  (autoload 'gnus-get-buffer-create "gnus")
+  (autoload 'nnheader-find-etc-directory "nnheader"))
+
+(if (or (featurep 'xemacs)
+       (>= emacs-major-version 21))
+    (autoload 'smiley-region "smiley")
+  (autoload 'smiley-region "smiley-mule"))
+
+;; Fixme: shouldn't require message
+(autoload 'message-text-with-property "message")
+
+(defun gnus-kill-all-overlays ()
+  "Delete all overlays in the current buffer."
+  (let* ((overlayss (overlay-lists))
+        (buffer-read-only nil)
+        (overlays (delq nil (nconc (car overlayss) (cdr overlayss)))))
+    (while overlays
+      (delete-overlay (pop overlays)))))
 
 ;;; Mule functions.
 
-(defun gnus-mule-cite-add-face (number prefix face)
-  ;; At line NUMBER, ignore PREFIX and add FACE to the rest of the line.
-  (when face
-    (let ((inhibit-point-motion-hooks t)
-         from to)
-      (goto-line number)
-      (unless (eobp)            ; Sometimes things become confused (broken).
-        (if (boundp 'MULE)
-            (forward-char (chars-in-string prefix))
-          (forward-char (length prefix)))
-        (skip-chars-forward " \t")
-        (setq from (point))
-        (end-of-line 1)
-        (skip-chars-backward " \t")
-        (setq to (point))
-        (when (< from to)
-          (push (setq overlay (gnus-make-overlay from to))
-                gnus-cite-overlay-list)
-          (gnus-overlay-put (gnus-make-overlay from to) 'face face))))))
-
-(defun gnus-mule-max-width-function (el max-width)
-  (` (let* ((val (eval (, el)))
-           (valstr (if (numberp val)
-                       (int-to-string val) val)))
-       (if (> (length valstr) (, max-width))
-          (truncate-string valstr (, max-width))
-        valstr))))
-
-(defun gnus-encode-coding-string (string system)
-  string)
-
-(defun gnus-decode-coding-string (string system)
-  string)
-
-(eval-and-compile
-  (if (string-match "XEmacs\\|Lucid" emacs-version)
-      nil
-
-    (defvar gnus-mouse-face-prop 'mouse-face
-      "Property used for highlighting mouse regions."))
-
-  (cond
-   ((string-match "XEmacs\\|Lucid" emacs-version)
-    (gnus-xmas-define))
-
-   ((or (not (boundp 'emacs-minor-version))
-       (and (< emacs-major-version 20)
-            (< emacs-minor-version 30)))
-    ;; Remove the `intangible' prop.
-    (let ((props (and (boundp 'gnus-hidden-properties)
-                     gnus-hidden-properties)))
-      (while (and props (not (eq (car (cdr props)) 'intangible)))
-       (setq props (cdr props)))
-      (when props
-       (setcdr props (cdr (cdr (cdr props))))))
-    (unless (fboundp 'buffer-substring-no-properties)
-      (defun buffer-substring-no-properties (beg end)
-       (format "%s" (buffer-substring beg end)))))
-
-   ((boundp 'MULE)
-    (provide 'gnusutil))))
-
 (eval-and-compile
-  (cond
-   ((not window-system)
-    (defun gnus-dummy-func (&rest args))
-    (let ((funcs '(mouse-set-point set-face-foreground
-                                  set-face-background x-popup-menu)))
-      (while funcs
-       (unless (fboundp (car funcs))
-         (fset (car funcs) 'gnus-dummy-func))
-       (setq funcs (cdr funcs))))))
-  (unless (fboundp 'file-regular-p)
-    (defun file-regular-p (file)
-      (and (not (file-directory-p file))
-          (not (file-symlink-p file))
-          (file-exists-p file))))
-  (unless (fboundp 'face-list)
-    (defun face-list (&rest args))))
+  (defalias 'gnus-char-width
+    (if (fboundp 'char-width)
+       'char-width
+      (lambda (ch) 1)))) ;; A simple hack.
 
 (eval-and-compile
-  (let ((case-fold-search t))
-    (cond
-     ((string-match "windows-nt\\|os/2\\|emx" (format "%s" system-type))
-      (setq nnheader-file-name-translation-alist
-           (append nnheader-file-name-translation-alist
-                   '((?: . ?_)
-                     (?+ . ?-))))))))
-
-(defvar gnus-tmp-unread)
-(defvar gnus-tmp-replied)
-(defvar gnus-tmp-score-char)
-(defvar gnus-tmp-indentation)
-(defvar gnus-tmp-opening-bracket)
-(defvar gnus-tmp-lines)
-(defvar gnus-tmp-name)
-(defvar gnus-tmp-closing-bracket)
-(defvar gnus-tmp-subject-or-nil)
+  (if (featurep 'xemacs)
+      (gnus-xmas-define)
+    (defvar gnus-mouse-face-prop 'mouse-face
+      "Property used for highlighting mouse regions.")))
+
+(eval-when-compile
+  (defvar gnus-tmp-unread)
+  (defvar gnus-tmp-replied)
+  (defvar gnus-tmp-score-char)
+  (defvar gnus-tmp-indentation)
+  (defvar gnus-tmp-opening-bracket)
+  (defvar gnus-tmp-lines)
+  (defvar gnus-tmp-name)
+  (defvar gnus-tmp-closing-bracket)
+  (defvar gnus-tmp-subject-or-nil)
+  (defvar gnus-check-before-posting)
+  (defvar gnus-mouse-face)
+  (defvar gnus-group-buffer))
 
 (defun gnus-ems-redefine ()
   (cond
-   ((string-match "XEmacs\\|Lucid" emacs-version)
+   ((featurep 'xemacs)
     (gnus-xmas-redefine))
 
    ((featurep 'mule)
     ;; Mule and new Emacs definitions
 
     ;; [Note] Now there are three kinds of mule implementations,
-    ;; original MULE, XEmacs/mule and beta version of Emacs including
-    ;; some mule features. Unfortunately these API are different. In
-    ;; particular, Emacs (including original MULE) and XEmacs are
-    ;; quite different.
+    ;; original MULE, XEmacs/mule and Emacs 20+ including
+    ;; MULE features.  Unfortunately these APIs are different.  In
+    ;; particular, Emacs (including original Mule) and XEmacs are
+    ;; quite different.  However, this version of Gnus doesn't support
+    ;; anything other than XEmacs 20+ and Emacs 20.3+.
+
     ;; Predicates to check are following:
-    ;; (boundp 'MULE) is t only if MULE (original; anything older than
+    ;; (boundp 'MULE) is t only if Mule (original; anything older than
     ;;                     Mule 2.3) is running.
-    ;; (featurep 'mule) is t when every mule variants are running.
-
-    ;; These implementations may be able to share between original
-    ;; MULE and beta version of new Emacs. In addition, it is able to
-    ;; detect XEmacs/mule by (featurep 'mule) and to check variable
-    ;; `emacs-version'. In this case, implementation for XEmacs/mule
-    ;; may be able to share between XEmacs and XEmacs/mule.
+    ;; (featurep 'mule) is t when other mule variants are running.
 
-    (defalias 'gnus-truncate-string 'truncate-string)
+    ;; It is possible to detect XEmacs/mule by (featurep 'mule) and
+    ;; (featurep 'xemacs).  In this case, the implementation for
+    ;; XEmacs/mule may be shareable between XEmacs and XEmacs/mule.
 
     (defvar gnus-summary-display-table nil
       "Display table used in summary mode buffers.")
-    (fset 'gnus-cite-add-face 'gnus-mule-cite-add-face)
-    (fset 'gnus-max-width-function 'gnus-mule-max-width-function)
-    (fset 'gnus-summary-set-display-table (lambda ()))
-    (fset 'gnus-encode-coding-string 'encode-coding-string)
-    (fset 'gnus-decode-coding-string 'decode-coding-string)
-    
+
+    (defalias 'gnus-summary-set-display-table (lambda ()))
+
+    (if (fboundp 'truncate-string-to-width)
+       (fset 'gnus-truncate-string 'truncate-string-to-width)
+      (fset 'gnus-truncate-string 'truncate-string))
+
     (when (boundp 'gnus-check-before-posting)
       (setq gnus-check-before-posting
            (delq 'long-lines
                  (delq 'control-chars gnus-check-before-posting))))
-
-    (defun gnus-summary-line-format-spec ()
-      (insert gnus-tmp-unread gnus-tmp-replied
-             gnus-tmp-score-char gnus-tmp-indentation)
-      (put-text-property
-       (point)
-       (progn
-        (insert
-         gnus-tmp-opening-bracket
-         (format "%4d: %-20s"
-                 gnus-tmp-lines
-                 (if (> (length gnus-tmp-name) 20)
-                     (truncate-string gnus-tmp-name 20)
-                   gnus-tmp-name))
-         gnus-tmp-closing-bracket)
-        (point))
-       gnus-mouse-face-prop gnus-mouse-face)
-      (insert " " gnus-tmp-subject-or-nil "\n"))
-    )))
+    ))
+  (when (featurep 'mule)
+    (defun gnus-tilde-max-form (el max-width)
+      "Return a form that limits EL to MAX-WIDTH."
+      (let ((max (abs max-width)))
+       (if (symbolp el)
+           (if (< max-width 0)
+               `(let ((width (string-width ,el)))
+                  (gnus-truncate-string ,el width (- width ,max)))
+             `(gnus-truncate-string ,el ,max))
+         (if (< max-width 0)
+             `(let* ((val (eval ,el))
+                     (width (string-width val)))
+                (gnus-truncate-string val width (- width ,max)))
+           `(let ((val (eval ,el)))
+              (gnus-truncate-string val ,max))))))
+
+    (defun gnus-tilde-cut-form (el cut-width)
+      "Return a form that cuts CUT-WIDTH off of EL."
+      (let ((cut (abs cut-width)))
+       (if (symbolp el)
+           (if (< cut-width 0)
+               `(gnus-truncate-string ,el (- (string-width ,el) ,cut))
+             `(gnus-truncate-string ,el (string-width ,el) ,cut))
+         (if (< cut-width 0)
+             `(let ((val (eval ,el)))
+                (gnus-truncate-string val (- (string-width val) ,cut)))
+           `(let ((val (eval ,el)))
+              (gnus-truncate-string val (string-width val) ,cut))))))
+    ))
 
 (defun gnus-region-active-p ()
   "Say whether the region is active."
        (boundp 'mark-active)
        mark-active))
 
-(defun gnus-add-minor-mode (mode name map)
-  (if (fboundp 'add-minor-mode)
-      (add-minor-mode mode name map)
+(defun gnus-mark-active-p ()
+  "Non-nil means the mark and region are currently active in this buffer."
+  mark-active) ; aliased to region-exists-p in XEmacs.
+
+(if (fboundp 'add-minor-mode)
+    (defalias 'gnus-add-minor-mode 'add-minor-mode)
+  (defun gnus-add-minor-mode (mode name map &rest rest)
+    (set (make-local-variable mode) t)
     (unless (assq mode minor-mode-alist)
       (push `(,mode ,name) minor-mode-alist))
     (unless (assq mode minor-mode-map-alist)
   (let ((dir (nnheader-find-etc-directory "gnus"))
        pixmap file height beg i)
     (save-excursion
-      (switch-to-buffer (get-buffer-create gnus-group-buffer))
-      (let ((buffer-read-only nil))
+      (switch-to-buffer (gnus-get-buffer-create gnus-group-buffer))
+      (let ((buffer-read-only nil)
+           width height)
        (erase-buffer)
        (when (and dir
-                  (file-exists-p (setq file (concat dir "x-splash"))))
-         (nnheader-temp-write nil
-           (insert-file-contents file)
-           (goto-char (point-min))
-           (ignore-errors
-             (setq pixmap (read (current-buffer))))))
+                  (file-exists-p (setq file
+                                       (expand-file-name "x-splash" dir))))
+         (let ((coding-system-for-read 'raw-text)
+               default-enable-multibyte-characters)
+           (with-temp-buffer
+             (insert-file-contents-as-binary file)
+             (goto-char (point-min))
+             (ignore-errors
+               (setq pixmap (read (current-buffer)))))))
        (when pixmap
-         (erase-buffer)
-         (unless (facep 'gnus-splash)
-           (make-face 'gnus-splash))
+         (make-face 'gnus-splash)
          (setq height (/ (car pixmap) (frame-char-height))
                width (/ (cadr pixmap) (frame-char-width)))
-         (set-face-foreground 'gnus-splash "ForestGreen")
+         (set-face-foreground 'gnus-splash "Brown")
          (set-face-stipple 'gnus-splash pixmap)
          (insert-char ?\n (* (/ (window-height) 2 height) height))
          (setq i height)
          (while (> i 0)
-           (insert-char ?  (* (+ (/ (window-width) 2 width) 1) width))
+           (insert-char ?\  (* (/ (window-width) 2 width) width))
            (setq beg (point))
-           (insert-char ?  width)
+           (insert-char ?\  width)
            (set-text-properties beg (point) '(face gnus-splash))
-           (insert "\n")
+           (insert ?\n)
            (decf i))
          (goto-char (point-min))
          (sit-for 0))))))
 
-(provide 'gnus-ems)
+;;; Image functions.
+
+(defun gnus-image-type-available-p (type)
+  (and (fboundp 'image-type-available-p)
+       (image-type-available-p type)))
+
+(defun gnus-create-image (file &optional type data-p &rest props)
+  (let ((face (plist-get props :face)))
+    (when face
+      (setq props (plist-put props :foreground (face-foreground face)))
+      (setq props (plist-put props :background (face-background face))))
+    (apply 'create-image file type data-p props)))
+
+(defun gnus-put-image (glyph &optional string category)
+  (let ((point (point)))
+    (insert-image glyph (or string " "))
+    (put-text-property point (point) 'gnus-image-category category)
+    (unless string
+      (put-text-property (1- (point)) (point)
+                        'gnus-image-text-deletable t))
+    glyph))
+
+(defun gnus-remove-image (image &optional category)
+  (dolist (position (message-text-with-property 'display))
+    (when (and (equal (get-text-property position 'display) image)
+              (equal (get-text-property position 'gnus-image-category)
+                     category))
+      (put-text-property position (1+ position) 'display nil)
+      (when (get-text-property position 'gnus-image-text-deletable)
+       (delete-region position (1+ position))))))
+
+(defun-maybe assoc-ignore-case (key alist)
+  "Like `assoc', but assumes KEY is a string and ignores case when comparing."
+  (setq key (downcase key))
+  (let (element)
+    (while (and alist (not element))
+      (if (equal key (downcase (car (car alist))))
+         (setq element (car alist)))
+      (setq alist (cdr alist)))
+    element))
+
+\f
+;;; Language support staffs.
+
+(defvar-maybe current-language-environment "English"
+  "The language environment.")
+
+(defvar-maybe language-info-alist nil
+  "Alist of language environment definitions.")
+
+(defun-maybe get-language-info (lang-env key)
+  "Return information listed under KEY for language environment LANG-ENV."
+  (if (symbolp lang-env)
+      (setq lang-env (symbol-name lang-env)))
+  (let ((lang-slot (assoc-ignore-case lang-env language-info-alist)))
+    (if lang-slot
+       (cdr (assq key (cdr lang-slot))))))
+
+(defun-maybe set-language-info (lang-env key info)
+  "Modify part of the definition of language environment LANG-ENV."
+  (if (symbolp lang-env)
+      (setq lang-env (symbol-name lang-env)))
+  (let (lang-slot key-slot)
+    (setq lang-slot (assoc lang-env language-info-alist))
+    (if (null lang-slot)               ; If no slot for the language, add it.
+       (setq lang-slot (list lang-env)
+             language-info-alist (cons lang-slot language-info-alist)))
+    (setq key-slot (assq key lang-slot))
+    (if (null key-slot)                        ; If no slot for the key, add it.
+       (progn
+         (setq key-slot (list key))
+         (setcdr lang-slot (cons key-slot (cdr lang-slot)))))
+    (setcdr key-slot info)))
 
-;; Local Variables:
-;; byte-compile-warnings: '(redefine callargs)
-;; End:
+(provide 'gnus-ems)
 
 ;;; gnus-ems.el ends here
diff --git a/lisp/gnus-fun.el b/lisp/gnus-fun.el
new file mode 100644 (file)
index 0000000..b293d4e
--- /dev/null
@@ -0,0 +1,251 @@
+;;; gnus-fun.el --- various frivolous extension functions to Gnus
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)
+  (require 'mm-util))
+
+(defcustom gnus-x-face-directory (expand-file-name "x-faces" gnus-directory)
+  "*Directory where X-Face PBM files are stored."
+  :group 'gnus-fun
+  :type 'directory)
+
+(defcustom gnus-convert-pbm-to-x-face-command "pbmtoxbm %s | compface"
+  "Command for converting a PBM to an X-Face."
+  :group 'gnus-fun
+  :type 'string)
+
+(defcustom gnus-convert-image-to-x-face-command "giftopnm %s | ppmnorm | pnmscale -width 48 -height 48 | ppmtopgm | pgmtopbm | pbmtoxbm | compface"
+  "Command for converting an image to an X-Face.
+By default it takes a GIF filename and output the X-Face header data
+on stdout."
+  :group 'gnus-fun
+  :type 'string)
+
+(defcustom gnus-convert-image-to-face-command "djpeg %s | ppmnorm | pnmscale -width 48 -height 48 | ppmquant %d | pnmtopng"
+  "Command for converting an image to an Face.
+By default it takes a JPEG filename and output the Face header data
+on stdout."
+  :group 'gnus-fun
+  :type 'string)
+
+(defun gnus-shell-command-to-string (command)
+  "Like `shell-command-to-string' except not mingling ERROR."
+  (with-output-to-string
+    (call-process shell-file-name nil (list standard-output nil)
+                 nil shell-command-switch command)))
+
+(defun gnus-shell-command-on-region (start end command)
+  "A simplified `shell-command-on-region'.
+Output to the current buffer, replace text, and don't mingle error."
+  (call-process-region start end shell-file-name t
+                      (list (current-buffer) nil)
+                      nil shell-command-switch command))
+
+;;;###autoload
+(defun gnus-random-x-face ()
+  "Return X-Face header data chosen randomly from `gnus-x-face-directory'."
+  (interactive)
+  (when (file-exists-p gnus-x-face-directory)
+    (let* ((files (directory-files gnus-x-face-directory t "\\.pbm$"))
+          (file (nth (random (length files)) files)))
+      (when file
+       (gnus-shell-command-to-string
+        (format gnus-convert-pbm-to-x-face-command
+                (shell-quote-argument file)))))))
+
+;;;###autoload
+(defun gnus-insert-random-x-face-header ()
+  "Insert a random X-Face header from `gnus-x-face-directory'."
+  (interactive)
+  (let ((data (gnus-random-x-face)))
+    (save-excursion
+      (message-goto-eoh)
+      (if data
+         (insert "X-Face: " data)
+       (message
+        "No face returned by `gnus-random-x-face'.  Does %s/*.pbm exist?"
+        gnus-x-face-directory)))))
+
+;;;###autoload
+(defun gnus-x-face-from-file (file)
+  "Insert an X-Face header based on an image file."
+  (interactive "fImage file name (by default GIF): ")
+  (when (file-exists-p file)
+    (gnus-shell-command-to-string
+     (format gnus-convert-image-to-x-face-command
+            (shell-quote-argument (expand-file-name file))))))
+
+;;;###autoload
+(defun gnus-face-from-file (file)
+  "Return an Face header based on an image file."
+  (interactive "fImage file name (by default JPEG): ")
+  (when (file-exists-p file)
+    (let ((done nil)
+         (attempt "")
+         (quant 16))
+      (while (and (not done)
+                 (> quant 1))
+       (setq attempt
+             (let ((coding-system-for-read 'binary))
+               (gnus-shell-command-to-string
+                (format gnus-convert-image-to-face-command
+                        (shell-quote-argument (expand-file-name file))
+                        quant))))
+       (if (> (length attempt) 726)
+           (progn
+             (setq quant (- quant 2))
+             (gnus-message 9 "Length %d; trying quant %d"
+                           (length attempt) quant))
+         (setq done t)))
+      (if done
+         (mm-with-unibyte-buffer
+           (insert attempt)
+           (gnus-face-encode))
+       nil))))
+
+(defun gnus-face-encode ()
+  (let ((step 72))
+    (base64-encode-region (point-min) (point-max))
+    (goto-char (point-min))
+    (while (search-forward "\n" nil t)
+      (replace-match ""))
+    (goto-char (point-min))
+    (while (> (- (point-max) (point))
+             step)
+      (forward-char step)
+      (insert "\n ")
+      (setq step 76))
+    (buffer-string)))
+
+;;;###autoload
+(defun gnus-convert-face-to-png (face)
+  "Convert FACE (which is base64-encoded) to a PNG.
+The PNG is returned as a string."
+  (mm-with-unibyte-buffer
+    (insert face)
+    (ignore-errors
+      (base64-decode-region (point-min) (point-max)))
+    (buffer-string)))
+
+;;;###autoload
+(defun gnus-convert-png-to-face (file)
+  "Convert FILE to a Face.
+FILE should be a PNG file that's 48x48 and smaller than or equal to
+726 bytes."
+  (mm-with-unibyte-buffer
+    (insert-file-contents file)
+    (when (> (buffer-size) 726)
+      (error "The file is %d bytes long, which is too long"
+            (buffer-size)))
+    (gnus-face-encode)))
+
+(defface gnus-x-face '((t (:foreground "black" :background "white")))
+  "Face to show X-Face.
+The colors from this face are used as the foreground and background
+colors of the displayed X-Faces."
+  :group 'gnus-article-headers)
+
+(defun gnus-display-x-face-in-from (data)
+  "Display the X-Face DATA in the From header."
+  (let ((default-enable-multibyte-characters nil)
+       pbm)
+    (when (or (gnus-image-type-available-p 'xface)
+             (and (gnus-image-type-available-p 'pbm)
+                  (setq pbm (uncompface data))))
+      (save-excursion
+       (save-restriction
+         (article-narrow-to-head)
+         (gnus-article-goto-header "from")
+         (when (bobp)
+           (insert "From: [no `from' set]\n")
+           (forward-char -17))
+         (gnus-add-image
+          'xface
+          (gnus-put-image
+           (if (gnus-image-type-available-p 'xface)
+               (gnus-create-image
+                (concat "X-Face: " data)
+                'xface t :face 'gnus-x-face)
+             (gnus-create-image
+              pbm 'pbm t :face 'gnus-x-face)) nil 'xface))
+         (gnus-add-wash-type 'xface))))))
+
+(defun gnus-grab-cam-x-face ()
+  "Grab a picture off the camera and make it into an X-Face."
+  (interactive)
+  (shell-command "xawtv-remote snap ppm")
+  (let ((file nil))
+    (while (null (setq file (directory-files "/tftpboot/sparky/tmp"
+                                            t "snap.*ppm")))
+      (sleep-for 1))
+    (setq file (car file))
+    (with-temp-buffer
+      (shell-command
+       (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | ppmnorm 2>/dev/null | pnmscale -width 48 | ppmtopgm | pgmtopbm -threshold -value 0.92 | pbmtoxbm | compface"
+              file)
+       (current-buffer))
+      ;;(sleep-for 3)
+      (delete-file file)
+      (buffer-string))))
+
+(defun gnus-grab-cam-face ()
+  "Grab a picture off the camera and make it into an X-Face."
+  (interactive)
+  (shell-command "xawtv-remote snap ppm")
+  (let ((file nil)
+       result)
+    (while (null (setq file (directory-files "/tftpboot/sparky/tmp"
+                                            t "snap.*ppm")))
+      (sleep-for 1))
+    (setq file (car file))
+    (shell-command
+     (format "pnmcut -left 110 -top 30 -width 144 -height 144 '%s' | pnmscale -width 48 -height 48 | ppmtopgm > /tmp/gnus.face.ppm"
+            file))
+    (let ((gnus-convert-image-to-face-command
+          (format "cat '%%s' | ppmquant %%d | ppmchange %s | pnmtopng"
+                  (gnus-fun-ppm-change-string))))
+      (setq result (gnus-face-from-file "/tmp/gnus.face.ppm")))
+    (delete-file file)
+    ;;(delete-file "/tmp/gnus.face.ppm")
+    result))
+
+(defun gnus-fun-ppm-change-string ()
+  (let* ((possibilites '("%02x0000" "00%02x00" "0000%02x"
+                       "%02x%02x00" "00%02x%02x" "%02x00%02x"))
+        (format (concat "'#%02x%02x%02x' '#"
+                        (nth (random 6) possibilites)
+                        "'"))
+        (values nil))
+  (dotimes (i 255)
+    (push (format format i i i i i i)
+         values))
+  (mapconcat 'identity values " ")))
+
+(provide 'gnus-fun)
+
+;;; gnus-fun.el ends here
index 7d1b7de..7a989e6 100644 (file)
@@ -1,5 +1,7 @@
 ;;; gnus-gl.el --- an interface to GroupLens for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;     Free Software Foundation, Inc.
 
 ;; Author: Brad Miller <bmiller@cs.umn.edu>
 ;; Keywords: news, score
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defvar gnus-summary-grouplens-line-format
-  "%U\%R\%z%l%I\%(%[%4L: %-20,20n%]%) %s\n"
+  "%U\%R\%z%l%I\%(%[%4L: %-23,23n%]%) %s\n"
   "*The line format spec in summary GroupLens mode buffers.")
 
 (defvar grouplens-pseudonym ""
 This pseudonym is obtained during the registration process")
 
 (defvar grouplens-bbb-host "grouplens.cs.umn.edu"
-  "Host where the bbbd is running" )
+  "Host where the bbbd is running.")
 
 (defvar grouplens-bbb-port 9000
-  "Port where the bbbd is listening" )
+  "Port where the bbbd is listening.")
 
 (defvar grouplens-newsgroups
   '("comp.groupware" "comp.human-factors" "comp.lang.c++"
@@ -194,19 +196,19 @@ GroupLens scores can be combined with gnus scores in one of three ways.
 ;;;; Program global variables
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defvar grouplens-bbb-token nil
-  "Current session token number")
+  "Current session token number.")
 
 (defvar grouplens-bbb-process nil
-  "Process Id of current bbbd network stream process")
+  "Process Id of current bbbd network stream process.")
 
 (defvar grouplens-bbb-buffer nil
-  "Buffer associated with the BBBD process")
+  "Buffer associated with the BBBD process.")
 
 (defvar grouplens-rating-alist nil
-  "Current set of  message-id rating pairs")
+  "Current set of  message-id rating pairs.")
 
 (defvar grouplens-current-hashtable nil
-  "A hashtable to hold predictions from the BBB")
+  "A hashtable to hold predictions from the BBB.")
 
 (defvar grouplens-current-group nil)
 
@@ -234,7 +236,7 @@ If this times out we give up and assume that something has died..." )
 (defun bbb-connect-to-bbbd (host port)
   (unless grouplens-bbb-buffer
     (setq grouplens-bbb-buffer
-         (get-buffer-create (format " *BBBD trace: %s*" host)))
+         (gnus-get-buffer-create (format " *BBBD trace: %s*" host)))
     (save-excursion
       (set-buffer grouplens-bbb-buffer)
       (make-local-variable 'bbb-read-point)
@@ -257,7 +259,8 @@ If this times out we give up and assume that something has died..." )
   (catch 'done
     (condition-case error
        (setq grouplens-bbb-process
-             (open-network-stream "BBBD" grouplens-bbb-buffer host port))
+             (open-network-stream-as-binary
+              "BBBD" grouplens-bbb-buffer host port))
       (error (gnus-message 3 "Error: Failed to connect to BBB")
             nil))
     (and (null grouplens-bbb-process)
@@ -299,7 +302,7 @@ If this times out we give up and assume that something has died..." )
 ;;;;       Login Functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun bbb-login ()
-  "return the token number if login is successful, otherwise return nil"
+  "return the token number if login is successful, otherwise return nil."
   (interactive)
   (setq grouplens-bbb-token nil)
   (if (not (equal grouplens-pseudonym ""))
@@ -312,7 +315,7 @@ If this times out we give up and assume that something has died..." )
                                (concat "login " grouplens-pseudonym))
              (if (bbb-read-response bbb-process)
                  (setq grouplens-bbb-token (bbb-extract-token-number))
-             (gnus-message 3 "Error: GroupLens login failed")))))
+               (gnus-message 3 "Error: GroupLens login failed")))))
     (gnus-message 3 "Error: you must set a pseudonym"))
   grouplens-bbb-token)
 
@@ -324,7 +327,7 @@ If this times out we give up and assume that something has died..." )
 (gnus-add-shutdown 'bbb-logout 'gnus)
 
 (defun bbb-logout ()
-  "logout of bbb session"
+  "logout of bbb session."
   (when grouplens-bbb-token
     (let ((bbb-process
           (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port)))
@@ -339,9 +342,8 @@ If this times out we give up and assume that something has died..." )
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defun bbb-build-mid-scores-alist (groupname)
-  "this function can be called as part of the function to return the
-list of score files to use.  See the gnus variable
-gnus-score-find-score-files-function.
+  "this function can be called as part of the function to return the list of score files to use.
+See the gnus variable `gnus-score-find-score-files-function'.
 
 *Note:*  If you want to use grouplens scores along with calculated scores,
 you should see the offset and scale variables.  At this point, I don't
@@ -407,7 +409,7 @@ recommend using both scores and grouplens predictions together."
                pred (bbb-get-pred))
          (push `(,mid ,pred nil s) resp)
          (gnus-sethash mid (list pred (bbb-get-confl) (bbb-get-confh))
-                     grouplens-current-hashtable)
+                       grouplens-current-hashtable)
          (forward-line 1)
          t)
         ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\)")
@@ -509,11 +511,11 @@ recommend using both scores and grouplens predictions together."
       ;; Return an empty string
       ""
     (let* ((rate-string (make-string 12 ?\ ))
-           (mid (mail-header-id header))
-           (hashent (gnus-gethash mid grouplens-current-hashtable))
-           (pred (or (nth 0 hashent) 0))
-           (low (nth 1 hashent))
-           (high (nth 2 hashent)))
+          (mid (mail-header-id header))
+          (hashent (gnus-gethash mid grouplens-current-hashtable))
+          (pred (or (nth 0 hashent) 0))
+          (low (nth 1 hashent))
+          (high (nth 2 hashent)))
       ;; Init rate-string
       (aset rate-string 0 ?|)
       (aset rate-string 11 ?|)
@@ -631,10 +633,10 @@ recommend using both scores and grouplens predictions together."
 
 (defun bbb-build-rate-command (rate-alist)
   (concat "putratings " grouplens-bbb-token " " grouplens-current-group " \r\n"
-         (mapconcat '(lambda (this)    ; form (mid . (score . time))
-                       (concat (car this)
-                               " :rating=" (cadr this) ".00"
-                               " :time=" (cddr this)))
+         (mapconcat (lambda (this)     ; form (mid . (score . time))
+                      (concat (car this)
+                              " :rating=" (cadr this) ".00"
+                              " :time=" (cddr this)))
                     rate-alist "\r\n")
          "\r\n.\r\n"))
 
@@ -669,9 +671,8 @@ recommend using both scores and grouplens predictions together."
   (gnus-summary-best-unread-article))
 
 (defun grouplens-summary-catchup-and-exit (rating)
-  "Mark all articles not marked as unread in this newsgroup as read,
-    then exit.   If prefix argument ALL is non-nil, all articles are
-    marked as read."
+  "Mark all articles not marked as unread in this newsgroup as read, then exit.
+If prefix argument ALL is non-nil, all articles are marked as read."
   (interactive "P")
   (when rating
     (bbb-summary-rate-article rating))
@@ -748,7 +749,7 @@ recommend using both scores and grouplens predictions together."
 (defconst gnus-gl-version "gnus-gl.el 2.50")
 (defconst gnus-gl-maintainer-address "grouplens-bug@cs.umn.edu")
 (defun gnus-gl-submit-bug-report ()
-  "Submit via mail a bug report on gnus-gl"
+  "Submit via mail a bug report on gnus-gl."
   (interactive)
   (require 'reporter)
   (reporter-submit-bug-report gnus-gl-maintainer-address
@@ -765,9 +766,9 @@ recommend using both scores and grouplens predictions together."
                              'gnus-gl-get-trace))
 
 (defun gnus-gl-get-trace ()
-  "Insert the contents of the BBBD trace buffer"
+  "Insert the contents of the BBBD trace buffer."
   (when grouplens-bbb-buffer
-    (insert-buffer grouplens-bbb-buffer)))
+    (insert-buffer-substring grouplens-bbb-buffer)))
 
 ;;
 ;; GroupLens minor mode
@@ -781,12 +782,12 @@ recommend using both scores and grouplens predictions together."
 (unless gnus-grouplens-mode-map
   (setq gnus-grouplens-mode-map (make-keymap))
   (gnus-define-keys
-   gnus-grouplens-mode-map
-   "n" grouplens-next-unread-article
-   "r" bbb-summary-rate-article
-   "k" grouplens-score-thread
-   "c" grouplens-summary-catchup-and-exit
-   "," grouplens-best-unread-article))
+      gnus-grouplens-mode-map
+    "n" grouplens-next-unread-article
+    "r" bbb-summary-rate-article
+    "k" grouplens-score-thread
+    "c" grouplens-summary-catchup-and-exit
+    "," grouplens-best-unread-article))
 
 (defun gnus-grouplens-make-menu-bar ()
   (unless (boundp 'gnus-grouplens-menu)
@@ -810,9 +811,9 @@ recommend using both scores and grouplens predictions together."
          (if (null arg) (not gnus-grouplens-mode)
            (> (prefix-numeric-value arg) 0)))
     (when gnus-grouplens-mode
-      (make-local-hook 'gnus-select-article-hook)
+      (gnus-make-local-hook 'gnus-select-article-hook)
       (add-hook 'gnus-select-article-hook 'grouplens-do-time nil 'local)
-      (make-local-hook 'gnus-exit-group-hook)
+      (gnus-make-local-hook 'gnus-exit-group-hook)
       (add-hook 'gnus-exit-group-hook 'bbb-exit-group nil 'local)
       (make-local-variable 'gnus-score-find-score-files-function)
 
index d85c820..e934383 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-group.el --- group mode commands for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -25,7 +26,9 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile
+  (require 'cl)
+  (defvar tool-bar-map))
 
 (require 'gnus)
 (require 'gnus-start)
 (require 'gnus-range)
 (require 'gnus-win)
 (require 'gnus-undo)
+(require 'time-date)
+(require 'gnus-ems)
+
+(eval-when-compile (require 'mm-url))
 
 (defcustom gnus-group-archive-directory
   "*ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
@@ -48,7 +55,7 @@
   :group 'gnus-group-foreign
   :type 'directory)
 
-(defcustom gnus-no-groups-message "No news is no news"
+(defcustom gnus-no-groups-message "No gnus is bad news"
   "*Message displayed by Gnus when no groups are available."
   :group 'gnus-start
   :type 'string)
@@ -89,7 +96,7 @@ unread articles in the groups.
 
 If nil, no groups are permanently visible."
   :group 'gnus-group-listing
-  :type 'regexp)
+  :type '(choice regexp (const nil)))
 
 (defcustom gnus-list-groups-with-ticked-articles t
   "*If non-nil, list groups that have only ticked articles.
@@ -115,24 +122,30 @@ This function will be called with group info entries as the arguments
 for the groups to be sorted.  Pre-made functions include
 `gnus-group-sort-by-alphabet', `gnus-group-sort-by-real-name',
 `gnus-group-sort-by-unread', `gnus-group-sort-by-level',
-`gnus-group-sort-by-score', `gnus-group-sort-by-method', and
-`gnus-group-sort-by-rank'.
+`gnus-group-sort-by-score', `gnus-group-sort-by-method',
+`gnus-group-sort-by-server', and `gnus-group-sort-by-rank'.
 
 This variable can also be a list of sorting functions. In that case,
 the most significant sort function should be the last function in the
 list."
   :group 'gnus-group-listing
   :link '(custom-manual "(gnus)Sorting Groups")
-  :type '(radio (function-item gnus-group-sort-by-alphabet)
-               (function-item gnus-group-sort-by-real-name)
-               (function-item gnus-group-sort-by-unread)
-               (function-item gnus-group-sort-by-level)
-               (function-item gnus-group-sort-by-score)
-               (function-item gnus-group-sort-by-method)
-               (function-item gnus-group-sort-by-rank)
-               (function :tag "other" nil)))
-
-(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y: %(%g%)%l\n"
+  :type '(repeat :value-to-internal (lambda (widget value)
+                                     (if (listp value) value (list value)))
+                :match (lambda (widget value)
+                         (or (symbolp value)
+                             (widget-editable-list-match widget value)))
+                (choice (function-item gnus-group-sort-by-alphabet)
+                        (function-item gnus-group-sort-by-real-name)
+                        (function-item gnus-group-sort-by-unread)
+                        (function-item gnus-group-sort-by-level)
+                        (function-item gnus-group-sort-by-score)
+                        (function-item gnus-group-sort-by-method)
+                        (function-item gnus-group-sort-by-server)
+                        (function-item gnus-group-sort-by-rank)
+                        (function :tag "other" nil))))
+
+(defcustom gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%g%)%l %O\n"
   "*Format of group lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -145,30 +158,33 @@ with some simple extensions.
 %i    Number of ticked and dormant (integer)
 %T    Number of ticked articles (integer)
 %R    Number of read articles (integer)
+%U    Number of unseen articles (integer)
 %t    Estimated total number of articles (integer)
 %y    Number of unread, unticked articles (integer)
 %G    Group name (string)
 %g    Qualified group name (string)
+%c    Short (collapsed) group name.  See `gnus-group-uncollapsed-levels'.
+%C    Group comment (string)
 %D    Group description (string)
 %s    Select method (string)
 %o    Moderated group (char, \"m\")
 %p    Process mark (char)
+%B    Whether a summary buffer for the group is open (char, \"*\")
 %O    Moderated group (string, \"(m)\" or \"\")
 %P    Topic indentation (string)
 %m    Whether there is new(ish) mail in the group (char, \"%\")
+%w    Number of new(ish) mails in the group (integer)
 %l    Whether there are GroupLens predictions for this group (string)
 %n    Select from where (string)
 %z    A string that look like `<%s:%n>' if a foreign select method is used
 %d    The date the group was last entered.
+%E    Icon as defined by `gnus-group-icon-list'.
 %u    User defined specifier.  The next character in the format string should
       be a letter.  Gnus will call the function gnus-user-format-function-X,
-      where X is the letter following %u.  The function will be passed the
-      current header as argument.  The function should return a string, which
-      will be inserted into the buffer just like information from any other
-      group specifier.
-
-Text between %( and %) will be highlighted with `gnus-mouse-face' when
-the mouse point move inside the area.  There can only be one such area.
+      where X is the letter following %u.  The function will be passed a
+      single dummy parameter as argument.  The function should return a
+      string, which will be inserted into the buffer just like information
+      from any other group specifier.
 
 Note that this format specification is not always respected.  For
 reasons of efficiency, when listing killed groups, this specification
@@ -180,7 +196,11 @@ If you use %o or %O, reading the active file will be slower and quite
 a bit of extra memory will be used.  %D will also worsen performance.
 Also note that if you change the format specification to include any
 of these specs, you must probably re-start Gnus to see them go into
-effect."
+effect.
+
+General format specifiers can also be used.
+See Info node `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :group 'gnus-group-visual
   :type 'string)
 
@@ -195,11 +215,10 @@ with some simple extensions:
   :group 'gnus-group-visual
   :type 'string)
 
-(defcustom gnus-group-mode-hook nil
-  "Hook for Gnus group mode."
-  :group 'gnus-group-various
-  :options '(gnus-topic-mode)
-  :type 'hook)
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+  (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
+  (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar))
 
 (defcustom gnus-group-menu-hook nil
   "Hook run after the creation of the group mode menu."
@@ -285,40 +304,52 @@ variable."
                       (sexp :tag "Method"))))
 
 (defcustom gnus-group-highlight
-  '(;; News.
-    ((and (= unread 0) (not mailp) (eq level 1)) .
-     gnus-group-news-1-empty-face)
-    ((and (not mailp) (eq level 1)) .
-     gnus-group-news-1-face)
-    ((and (= unread 0) (not mailp) (eq level 2)) .
-     gnus-group-news-2-empty-face)
-    ((and (not mailp) (eq level 2)) .
-     gnus-group-news-2-face)
-    ((and (= unread 0) (not mailp) (eq level 3)) .
-     gnus-group-news-3-empty-face)
-    ((and (not mailp) (eq level 3)) .
-     gnus-group-news-3-face)
-    ((and (= unread 0) (not mailp)) .
-     gnus-group-news-low-empty-face)
-    ((and (not mailp)) .
-     gnus-group-news-low-face)
-    ;; Mail.
-    ((and (= unread 0) (eq level 1)) .
+  '(;; Mail.
+    ((and mailp (= unread 0) (eq level 1)) .
      gnus-group-mail-1-empty-face)
-    ((eq level 1) .
+    ((and mailp (eq level 1)) .
      gnus-group-mail-1-face)
-    ((and (= unread 0) (eq level 2)) .
+    ((and mailp (= unread 0) (eq level 2)) .
      gnus-group-mail-2-empty-face)
-    ((eq level 2) .
+    ((and mailp (eq level 2)) .
      gnus-group-mail-2-face)
-    ((and (= unread 0) (eq level 3)) .
+    ((and mailp (= unread 0) (eq level 3)) .
      gnus-group-mail-3-empty-face)
-    ((eq level 3) .
+    ((and mailp (eq level 3)) .
      gnus-group-mail-3-face)
-    ((= unread 0) .
+    ((and mailp (= unread 0)) .
      gnus-group-mail-low-empty-face)
+    ((and mailp) .
+     gnus-group-mail-low-face)
+    ;; News.
+    ((and (= unread 0) (eq level 1)) .
+     gnus-group-news-1-empty-face)
+    ((and (eq level 1)) .
+     gnus-group-news-1-face)
+    ((and (= unread 0) (eq level 2)) .
+     gnus-group-news-2-empty-face)
+    ((and (eq level 2)) .
+     gnus-group-news-2-face)
+    ((and (= unread 0) (eq level 3)) .
+     gnus-group-news-3-empty-face)
+    ((and (eq level 3)) .
+     gnus-group-news-3-face)
+    ((and (= unread 0) (eq level 4)) .
+     gnus-group-news-4-empty-face)
+    ((and (eq level 4)) .
+     gnus-group-news-4-face)
+    ((and (= unread 0) (eq level 5)) .
+     gnus-group-news-5-empty-face)
+    ((and (eq level 5)) .
+     gnus-group-news-5-face)
+    ((and (= unread 0) (eq level 6)) .
+     gnus-group-news-6-empty-face)
+    ((and (eq level 6)) .
+     gnus-group-news-6-face)
+    ((and (= unread 0)) .
+     gnus-group-news-low-empty-face)
     (t .
-     gnus-group-mail-low-face))
+       gnus-group-news-low-face))
   "*Controls the highlighting of group buffer lines.
 
 Below is a list of `Form'/`Face' pairs.  When deciding how a a
@@ -347,8 +378,76 @@ ticked: The number of ticked articles."
   :group 'gnus-group-visual
   :type 'character)
 
+(defgroup gnus-group-icons nil
+  "Add Icons to your group buffer.  "
+  :group 'gnus-group-visual)
+
+(defcustom gnus-group-icon-list
+  nil
+  "*Controls the insertion of icons into group buffer lines.
+
+Below is a list of `Form'/`File' pairs.  When deciding how a
+particular group line should be displayed, each form is evaluated.
+The icon from the file field after the first true form is used.  You
+can change how those group lines are displayed by editing the file
+field.  The File will either be found in the
+`gnus-group-glyph-directory' or by designating absolute name of the
+file.
+
+It is also possible to change and add form fields, but currently that
+requires an understanding of Lisp expressions.  Hopefully this will
+change in a future release.  For now, you can use the following
+variables in the Lisp expression:
+
+group: The name of the group.
+unread: The number of unread articles in the group.
+method: The select method used.
+mailp: Whether it's a mail group or not.
+newsp: Whether it's a news group or not
+level: The level of the group.
+score: The score of the group.
+ticked: The number of ticked articles."
+  :group 'gnus-group-icons
+  :type '(repeat (cons (sexp :tag "Form") file)))
+
+(defcustom gnus-group-name-charset-method-alist nil
+  "Alist of method and the charset for group names.
+
+For example:
+    (((nntp \"news.com.cn\") . cn-gb-2312))"
+  :version "21.1"
+  :group 'gnus-charset
+  :type '(repeat (cons (sexp :tag "Method") (symbol :tag "Charset"))))
+
+(defcustom gnus-group-name-charset-group-alist
+  (if (mm-coding-system-p 'utf-8)
+      '(("[^\000-\177]" . utf-8))
+    nil)
+  "Alist of group regexp and the charset for group names.
+
+For example:
+    ((\"\\.com\\.cn:\" . cn-gb-2312))"
+  :group 'gnus-charset
+  :type '(repeat (cons (regexp :tag "Group") (symbol :tag "Charset"))))
+
+(defcustom gnus-group-jump-to-group-prompt nil
+  "Default prompt for `gnus-group-jump-to-group'.
+If non-nil, the value should be a string, e.g. \"nnml:\",
+in which case `gnus-group-jump-to-group' offers \"Group: nnml:\"
+in the minibuffer prompt."
+  :group 'gnus-group-various
+  :type '(choice (string :tag "Prompt string")
+                (const :tag "Empty" nil)))
+
+(defvar gnus-group-listing-limit 1000
+  "*A limit of the number of groups when listing.
+If the number of groups is larger than the limit, list them in a
+simple manner.")
+
 ;;; Internal variables
 
+(defvar gnus-group-is-exiting-p nil)
+(defvar gnus-group-is-exiting-without-update-p nil)
 (defvar gnus-group-sort-alist-function 'gnus-group-sort-flat
   "Function for sorting the group buffer.")
 
@@ -375,6 +474,7 @@ ticked: The number of ticked articles."
                   (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
              (t number)) ?s)
     (?R gnus-tmp-number-of-read ?s)
+    (?U (gnus-number-of-unseen-articles-in-group gnus-tmp-group) ?d)
     (?t gnus-tmp-number-total ?d)
     (?y gnus-tmp-number-of-unread ?s)
     (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
@@ -384,6 +484,7 @@ ticked: The number of ticked articles."
     (?g gnus-tmp-group ?s)
     (?G gnus-tmp-qualified-group ?s)
     (?c (gnus-short-group-name gnus-tmp-group) ?s)
+    (?C gnus-tmp-comment ?s)
     (?D gnus-tmp-newsgroup-description ?s)
     (?o gnus-tmp-moderated ?c)
     (?O gnus-tmp-moderated-string ?s)
@@ -391,9 +492,18 @@ ticked: The number of ticked articles."
     (?s gnus-tmp-news-server ?s)
     (?n gnus-tmp-news-method ?s)
     (?P gnus-group-indentation ?s)
+    (?E gnus-tmp-group-icon ?s)
+    (?B gnus-tmp-summary-live ?c)
     (?l gnus-tmp-grouplens ?s)
     (?z gnus-tmp-news-method-string ?s)
     (?m (gnus-group-new-mail gnus-tmp-group) ?c)
+    (?w (if (gnus-news-group-p gnus-tmp-group)
+           ""
+         (int-to-string
+          (length
+           (nnmail-new-mail-numbers (gnus-group-real-name gnus-tmp-group))
+           )))
+       ?s)
     (?d (gnus-group-timestamp-string gnus-tmp-group) ?s)
     (?u gnus-tmp-user-defined ?s)))
 
@@ -413,162 +523,227 @@ ticked: The number of ticked articles."
 
 (defvar gnus-group-list-mode nil)
 
+
+(defvar gnus-group-icon-cache nil)
+
+(defvar gnus-group-listed-groups nil)
+(defvar gnus-group-list-option nil)
+
 ;;;
 ;;; Gnus group mode
 ;;;
 
 (put 'gnus-group-mode 'mode-class 'special)
 
-(when t
-  (gnus-define-keys gnus-group-mode-map
-    " " gnus-group-read-group
-    "=" gnus-group-select-group
-    "\r" gnus-group-select-group
-    "\M-\r" gnus-group-quick-select-group
-    [(meta control return)] gnus-group-select-group-ephemerally
-    "j" gnus-group-jump-to-group
-    "n" gnus-group-next-unread-group
-    "p" gnus-group-prev-unread-group
-    "\177" gnus-group-prev-unread-group
-    [delete] gnus-group-prev-unread-group
-    [backspace] gnus-group-prev-unread-group
-    "N" gnus-group-next-group
-    "P" gnus-group-prev-group
-    "\M-n" gnus-group-next-unread-group-same-level
-    "\M-p" gnus-group-prev-unread-group-same-level
-    "," gnus-group-best-unread-group
-    "." gnus-group-first-unread-group
-    "u" gnus-group-unsubscribe-current-group
-    "U" gnus-group-unsubscribe-group
-    "c" gnus-group-catchup-current
-    "C" gnus-group-catchup-current-all
-    "\M-c" gnus-group-clear-data
-    "l" gnus-group-list-groups
-    "L" gnus-group-list-all-groups
-    "m" gnus-group-mail
-    "g" gnus-group-get-new-news
-    "\M-g" gnus-group-get-new-news-this-group
-    "R" gnus-group-restart
-    "r" gnus-group-read-init-file
-    "B" gnus-group-browse-foreign-server
-    "b" gnus-group-check-bogus-groups
-    "F" gnus-group-find-new-groups
-    "\C-c\C-d" gnus-group-describe-group
-    "\M-d" gnus-group-describe-all-groups
-    "\C-c\C-a" gnus-group-apropos
-    "\C-c\M-\C-a" gnus-group-description-apropos
-    "a" gnus-group-post-news
-    "\ek" gnus-group-edit-local-kill
-    "\eK" gnus-group-edit-global-kill
-    "\C-k" gnus-group-kill-group
-    "\C-y" gnus-group-yank-group
-    "\C-w" gnus-group-kill-region
-    "\C-x\C-t" gnus-group-transpose-groups
-    "\C-c\C-l" gnus-group-list-killed
-    "\C-c\C-x" gnus-group-expire-articles
-    "\C-c\M-\C-x" gnus-group-expire-all-groups
-    "V" gnus-version
-    "s" gnus-group-save-newsrc
-    "z" gnus-group-suspend
-    "q" gnus-group-exit
-    "Q" gnus-group-quit
-    "?" gnus-group-describe-briefly
-    "\C-c\C-i" gnus-info-find-node
-    "\M-e" gnus-group-edit-group-method
-    "^" gnus-group-enter-server-mode
-    gnus-mouse-2 gnus-mouse-pick-group
-    "<" beginning-of-buffer
-    ">" end-of-buffer
-    "\C-c\C-b" gnus-bug
-    "\C-c\C-s" gnus-group-sort-groups
-    "t" gnus-topic-mode
-    "\C-c\M-g" gnus-activate-all-groups
-    "\M-&" gnus-group-universal-argument
-    "#" gnus-group-mark-group
-    "\M-#" gnus-group-unmark-group)
-
-  (gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map)
-    "m" gnus-group-mark-group
-    "u" gnus-group-unmark-group
-    "w" gnus-group-mark-region
-    "b" gnus-group-mark-buffer
-    "r" gnus-group-mark-regexp
-    "U" gnus-group-unmark-all-groups)
-
-  (gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map)
-    "d" gnus-group-make-directory-group
-    "h" gnus-group-make-help-group
-    "u" gnus-group-make-useful-group
-    "a" gnus-group-make-archive-group
-    "k" gnus-group-make-kiboze-group
-    "m" gnus-group-make-group
-    "E" gnus-group-edit-group
-    "e" gnus-group-edit-group-method
-    "p" gnus-group-edit-group-parameters
-    "v" gnus-group-add-to-virtual
-    "V" gnus-group-make-empty-virtual
-    "D" gnus-group-enter-directory
-    "f" gnus-group-make-doc-group
-    "w" gnus-group-make-web-group
-    "r" gnus-group-rename-group
-    "c" gnus-group-customize
-    "\177" gnus-group-delete-group
-    [delete] gnus-group-delete-group)
-
-  (gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
-    "b" gnus-group-brew-soup
-    "w" gnus-soup-save-areas
-    "s" gnus-soup-send-replies
-    "p" gnus-soup-pack-packet
-    "r" nnsoup-pack-replies)
-
-  (gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map)
-    "s" gnus-group-sort-groups
-    "a" gnus-group-sort-groups-by-alphabet
-    "u" gnus-group-sort-groups-by-unread
-    "l" gnus-group-sort-groups-by-level
-    "v" gnus-group-sort-groups-by-score
-    "r" gnus-group-sort-groups-by-rank
-    "m" gnus-group-sort-groups-by-method)
-
-  (gnus-define-keys (gnus-group-sort-selected-map "P" gnus-group-group-map)
-    "s" gnus-group-sort-selected-groups
-    "a" gnus-group-sort-selected-groups-by-alphabet
-    "u" gnus-group-sort-selected-groups-by-unread
-    "l" gnus-group-sort-selected-groups-by-level
-    "v" gnus-group-sort-selected-groups-by-score
-    "r" gnus-group-sort-selected-groups-by-rank
-    "m" gnus-group-sort-selected-groups-by-method)
-
-  (gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
-    "k" gnus-group-list-killed
-    "z" gnus-group-list-zombies
-    "s" gnus-group-list-groups
-    "u" gnus-group-list-all-groups
-    "A" gnus-group-list-active
-    "a" gnus-group-apropos
-    "d" gnus-group-description-apropos
-    "m" gnus-group-list-matching
-    "M" gnus-group-list-all-matching
-    "l" gnus-group-list-level)
-
-  (gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
-    "f" gnus-score-flush-cache)
-
-  (gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
-    "d" gnus-group-describe-group
-    "f" gnus-group-fetch-faq
-    "v" gnus-version)
-
-  (gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map)
-    "l" gnus-group-set-current-level
-    "t" gnus-group-unsubscribe-current-group
-    "s" gnus-group-unsubscribe-group
-    "k" gnus-group-kill-group
-    "y" gnus-group-yank-group
-    "w" gnus-group-kill-region
-    "\C-k" gnus-group-kill-level
-    "z" gnus-group-kill-all-zombies))
+(gnus-define-keys gnus-group-mode-map
+  " " gnus-group-read-group
+  "=" gnus-group-select-group
+  "\r" gnus-group-select-group
+  "\M-\r" gnus-group-quick-select-group
+  "\M- " gnus-group-visible-select-group
+  [(meta control return)] gnus-group-select-group-ephemerally
+  "j" gnus-group-jump-to-group
+  "n" gnus-group-next-unread-group
+  "p" gnus-group-prev-unread-group
+  "\177" gnus-group-prev-unread-group
+  [delete] gnus-group-prev-unread-group
+  [backspace] gnus-group-prev-unread-group
+  "N" gnus-group-next-group
+  "P" gnus-group-prev-group
+  "\M-n" gnus-group-next-unread-group-same-level
+  "\M-p" gnus-group-prev-unread-group-same-level
+  "," gnus-group-best-unread-group
+  "." gnus-group-first-unread-group
+  "u" gnus-group-unsubscribe-current-group
+  "U" gnus-group-unsubscribe-group
+  "c" gnus-group-catchup-current
+  "C" gnus-group-catchup-current-all
+  "\M-c" gnus-group-clear-data
+  "l" gnus-group-list-groups
+  "L" gnus-group-list-all-groups
+  "m" gnus-group-mail
+  "i" gnus-group-news
+  "g" gnus-group-get-new-news
+  "\M-g" gnus-group-get-new-news-this-group
+  "R" gnus-group-restart
+  "r" gnus-group-read-init-file
+  "B" gnus-group-browse-foreign-server
+  "b" gnus-group-check-bogus-groups
+  "F" gnus-group-find-new-groups
+  "\C-c\C-d" gnus-group-describe-group
+  "\M-d" gnus-group-describe-all-groups
+  "\C-c\C-a" gnus-group-apropos
+  "\C-c\M-\C-a" gnus-group-description-apropos
+  "a" gnus-group-post-news
+  "\ek" gnus-group-edit-local-kill
+  "\eK" gnus-group-edit-global-kill
+  "\C-k" gnus-group-kill-group
+  "\C-y" gnus-group-yank-group
+  "\C-w" gnus-group-kill-region
+  "\C-x\C-t" gnus-group-transpose-groups
+  "\C-c\C-l" gnus-group-list-killed
+  "\C-c\C-x" gnus-group-expire-articles
+  "\C-c\M-\C-x" gnus-group-expire-all-groups
+  "V" gnus-version
+  "s" gnus-group-save-newsrc
+  "z" gnus-group-suspend
+  "q" gnus-group-exit
+  "Q" gnus-group-quit
+  "?" gnus-group-describe-briefly
+  "\C-c\C-i" gnus-info-find-node
+  "\M-e" gnus-group-edit-group-method
+  "^" gnus-group-enter-server-mode
+  gnus-mouse-2 gnus-mouse-pick-group
+  "<" beginning-of-buffer
+  ">" end-of-buffer
+  "\C-c\C-b" gnus-bug
+  "\C-c\C-n" gnus-namazu-search
+  "\C-c\C-s" gnus-group-sort-groups
+  "t" gnus-topic-mode
+  "\C-c\M-g" gnus-activate-all-groups
+  "\M-&" gnus-group-universal-argument
+  "#" gnus-group-mark-group
+  "\M-#" gnus-group-unmark-group)
+
+(gnus-define-keys (gnus-group-mark-map "M" gnus-group-mode-map)
+  "m" gnus-group-mark-group
+  "u" gnus-group-unmark-group
+  "w" gnus-group-mark-region
+  "b" gnus-group-mark-buffer
+  "r" gnus-group-mark-regexp
+  "U" gnus-group-unmark-all-groups)
+
+(gnus-define-keys (gnus-group-sieve-map "D" gnus-group-mode-map)
+  "u" gnus-sieve-update
+  "g" gnus-sieve-generate)
+
+(gnus-define-keys (gnus-group-group-map "G" gnus-group-mode-map)
+  "d" gnus-group-make-directory-group
+  "h" gnus-group-make-help-group
+  "u" gnus-group-make-useful-group
+  "a" gnus-group-make-archive-group
+  "k" gnus-group-make-kiboze-group
+  "l" gnus-group-nnimap-edit-acl
+  "m" gnus-group-make-group
+  "n" gnus-group-make-shimbun-group
+  "E" gnus-group-edit-group
+  "e" gnus-group-edit-group-method
+  "p" gnus-group-edit-group-parameters
+  "v" gnus-group-add-to-virtual
+  "V" gnus-group-make-empty-virtual
+  "D" gnus-group-enter-directory
+  "f" gnus-group-make-doc-group
+  "G" gnus-group-make-nnir-group
+  "w" gnus-group-make-web-group
+  "M" gnus-group-read-ephemeral-group
+  "r" gnus-group-rename-group
+  "R" gnus-group-make-rss-group
+  "c" gnus-group-customize
+  "x" gnus-group-nnimap-expunge
+  "\177" gnus-group-delete-group
+  [delete] gnus-group-delete-group)
+
+(gnus-define-keys (gnus-group-soup-map "s" gnus-group-group-map)
+  "b" gnus-group-brew-soup
+  "w" gnus-soup-save-areas
+  "s" gnus-soup-send-replies
+  "p" gnus-soup-pack-packet
+  "r" nnsoup-pack-replies)
+
+(gnus-define-keys (gnus-group-sort-map "S" gnus-group-group-map)
+  "s" gnus-group-sort-groups
+  "a" gnus-group-sort-groups-by-alphabet
+  "u" gnus-group-sort-groups-by-unread
+  "l" gnus-group-sort-groups-by-level
+  "v" gnus-group-sort-groups-by-score
+  "r" gnus-group-sort-groups-by-rank
+  "m" gnus-group-sort-groups-by-method
+  "n" gnus-group-sort-groups-by-real-name)
+
+(gnus-define-keys (gnus-group-sort-selected-map "P" gnus-group-group-map)
+  "s" gnus-group-sort-selected-groups
+  "a" gnus-group-sort-selected-groups-by-alphabet
+  "u" gnus-group-sort-selected-groups-by-unread
+  "l" gnus-group-sort-selected-groups-by-level
+  "v" gnus-group-sort-selected-groups-by-score
+  "r" gnus-group-sort-selected-groups-by-rank
+  "m" gnus-group-sort-selected-groups-by-method
+  "n" gnus-group-sort-selected-groups-by-real-name)
+
+(gnus-define-keys (gnus-group-list-map "A" gnus-group-mode-map)
+  "k" gnus-group-list-killed
+  "z" gnus-group-list-zombies
+  "s" gnus-group-list-groups
+  "u" gnus-group-list-all-groups
+  "A" gnus-group-list-active
+  "a" gnus-group-apropos
+  "d" gnus-group-description-apropos
+  "m" gnus-group-list-matching
+  "M" gnus-group-list-all-matching
+  "l" gnus-group-list-level
+  "c" gnus-group-list-cached
+  "?" gnus-group-list-dormant)
+
+(gnus-define-keys (gnus-group-list-limit-map "/" gnus-group-list-map)
+  "k"  gnus-group-list-limit
+  "z"  gnus-group-list-limit
+  "s"  gnus-group-list-limit
+  "u"  gnus-group-list-limit
+  "A"  gnus-group-list-limit
+  "m"  gnus-group-list-limit
+  "M"  gnus-group-list-limit
+  "l"  gnus-group-list-limit
+  "c"  gnus-group-list-limit
+  "?"  gnus-group-list-limit)
+
+(gnus-define-keys (gnus-group-list-flush-map "f" gnus-group-list-map)
+  "k"  gnus-group-list-flush
+  "z"  gnus-group-list-flush
+  "s"  gnus-group-list-flush
+  "u"  gnus-group-list-flush
+  "A"  gnus-group-list-flush
+  "m"  gnus-group-list-flush
+  "M"  gnus-group-list-flush
+  "l"  gnus-group-list-flush
+  "c"  gnus-group-list-flush
+  "?"  gnus-group-list-flush)
+
+(gnus-define-keys (gnus-group-list-plus-map "p" gnus-group-list-map)
+  "k"  gnus-group-list-plus
+  "z"  gnus-group-list-plus
+  "s"  gnus-group-list-plus
+  "u"  gnus-group-list-plus
+  "A"  gnus-group-list-plus
+  "m"  gnus-group-list-plus
+  "M"  gnus-group-list-plus
+  "l"  gnus-group-list-plus
+  "c"  gnus-group-list-plus
+  "?"  gnus-group-list-plus)
+
+(gnus-define-keys (gnus-group-score-map "W" gnus-group-mode-map)
+  "f" gnus-score-flush-cache)
+
+(gnus-define-keys (gnus-group-help-map "H" gnus-group-mode-map)
+  "c" gnus-group-fetch-charter
+  "C" gnus-group-fetch-control
+  "d" gnus-group-describe-group
+  "f" gnus-group-fetch-faq
+  "v" gnus-version)
+
+(gnus-define-keys (gnus-group-sub-map "S" gnus-group-mode-map)
+  "l" gnus-group-set-current-level
+  "t" gnus-group-unsubscribe-current-group
+  "s" gnus-group-unsubscribe-group
+  "k" gnus-group-kill-group
+  "y" gnus-group-yank-group
+  "w" gnus-group-kill-region
+  "\C-k" gnus-group-kill-level
+  "z" gnus-group-kill-all-zombies)
+
+(defun gnus-topic-mode-p ()
+  "Return non-nil in `gnus-topic-mode'."
+  (and (boundp 'gnus-topic-mode)
+       (symbol-value 'gnus-topic-mode)))
 
 (defun gnus-group-make-menu-bar ()
   (gnus-turn-off-edit-menu 'group)
@@ -576,36 +751,77 @@ ticked: The number of ticked articles."
 
     (easy-menu-define
      gnus-group-reading-menu gnus-group-mode-map ""
-     '("Group"
-       ["Read" gnus-group-read-group (gnus-group-group-name)]
-       ["Select" gnus-group-select-group (gnus-group-group-name)]
+     `("Group"
+       ["Read" gnus-group-read-group
+       :included (not (gnus-topic-mode-p))
+       :active (gnus-group-group-name)]
+       ["Read " gnus-topic-read-group
+       :included (gnus-topic-mode-p)]
+       ["Select" gnus-group-select-group
+       :included (not (gnus-topic-mode-p))
+       :active (gnus-group-group-name)]
+       ["Select " gnus-topic-select-group
+       :included (gnus-topic-mode-p)]
        ["See old articles" (gnus-group-select-group 'all)
        :keys "C-u SPC" :active (gnus-group-group-name)]
-       ["Catch up" gnus-group-catchup-current (gnus-group-group-name)]
+       ["Catch up" gnus-group-catchup-current
+       :included (not (gnus-topic-mode-p))
+       :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Mark unread articles in the current group as read"))]
+       ["Catch up " gnus-topic-catchup-articles
+       :included (gnus-topic-mode-p)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Mark unread articles in the current group or topic as read"))]
        ["Catch up all articles" gnus-group-catchup-current-all
        (gnus-group-group-name)]
        ["Check for new articles" gnus-group-get-new-news-this-group
-       (gnus-group-group-name)]
+       :included (not (gnus-topic-mode-p))
+       :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Check for new messages in current group"))]
+       ["Check for new articles " gnus-topic-get-new-news-this-topic
+       :included (gnus-topic-mode-p)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Check for new messages in current group or topic"))]
        ["Toggle subscription" gnus-group-unsubscribe-current-group
        (gnus-group-group-name)]
-       ["Kill" gnus-group-kill-group (gnus-group-group-name)]
+       ["Kill" gnus-group-kill-group :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Kill (remove) current group"))]
        ["Yank" gnus-group-yank-group gnus-list-of-killed-groups]
-       ["Describe" gnus-group-describe-group (gnus-group-group-name)]
+       ["Describe" gnus-group-describe-group :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Display description of the current group"))]
        ["Fetch FAQ" gnus-group-fetch-faq (gnus-group-group-name)]
+       ["Fetch charter" gnus-group-fetch-charter
+       :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Display the charter of the current group"))]
+       ["Fetch control message" gnus-group-fetch-control
+       :active (gnus-group-group-name)
+       ,@(if (featurep 'xemacs) nil
+           '(:help "Display the archived control message for the current group"))]
        ;; Actually one should check, if any of the marked groups gives t for
        ;; (gnus-check-backend-function 'request-expire-articles ...)
        ["Expire articles" gnus-group-expire-articles
-       (or (and (gnus-group-group-name)
-                (gnus-check-backend-function
-                 'request-expire-articles
-                 (gnus-group-group-name))) gnus-group-marked)]
-       ["Set group level" gnus-group-set-current-level
+       :included (not (gnus-topic-mode-p))
+       :active (or (and (gnus-group-group-name)
+                        (gnus-check-backend-function
+                         'request-expire-articles
+                         (gnus-group-group-name))) gnus-group-marked)]
+       ["Expire articles " gnus-topic-expire-articles
+       :included (gnus-topic-mode-p)]
+       ["Set group level..." gnus-group-set-current-level
        (gnus-group-group-name)]
        ["Select quick" gnus-group-quick-select-group (gnus-group-group-name)]
        ["Customize" gnus-group-customize (gnus-group-group-name)]
        ("Edit"
        ["Parameters" gnus-group-edit-group-parameters
-        (gnus-group-group-name)]
+        :included (not (gnus-topic-mode-p))
+        :active (gnus-group-group-name)]
+       ["Parameters " gnus-topic-edit-parameters
+        :included (gnus-topic-mode-p)]
        ["Select method" gnus-group-edit-group-method
         (gnus-group-group-name)]
        ["Info" gnus-group-edit-group (gnus-group-group-name)]
@@ -626,7 +842,9 @@ ticked: The number of ticked articles."
        ["Group and description apropos..." gnus-group-description-apropos t]
        ["List groups matching..." gnus-group-list-matching t]
        ["List all groups matching..." gnus-group-list-all-matching t]
-       ["List active file" gnus-group-list-active t])
+       ["List active file" gnus-group-list-active t]
+       ["List groups with cached" gnus-group-list-cached t]
+       ["List groups with dormant" gnus-group-list-dormant t])
        ("Sort"
        ["Default sort" gnus-group-sort-groups t]
        ["Sort by method" gnus-group-sort-groups-by-method t]
@@ -634,22 +852,25 @@ ticked: The number of ticked articles."
        ["Sort by score" gnus-group-sort-groups-by-score t]
        ["Sort by level" gnus-group-sort-groups-by-level t]
        ["Sort by unread" gnus-group-sort-groups-by-unread t]
-       ["Sort by name" gnus-group-sort-groups-by-alphabet t])
+       ["Sort by name" gnus-group-sort-groups-by-alphabet t]
+       ["Sort by real name" gnus-group-sort-groups-by-real-name t])
        ("Sort process/prefixed"
        ["Default sort" gnus-group-sort-selected-groups
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by method" gnus-group-sort-selected-groups-by-method
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by rank" gnus-group-sort-selected-groups-by-rank
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by score" gnus-group-sort-selected-groups-by-score
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by level" gnus-group-sort-selected-groups-by-level
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by unread" gnus-group-sort-selected-groups-by-unread
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))]
+        (not (gnus-topic-mode-p))]
        ["Sort by name" gnus-group-sort-selected-groups-by-alphabet
-        (or (not (boundp 'gnus-topic-mode)) (not gnus-topic-mode))])
+        (not (gnus-topic-mode-p))]
+       ["Sort by real name" gnus-group-sort-selected-groups-by-real-name
+        (not (gnus-topic-mode-p))])
        ("Mark"
        ["Mark group" gnus-group-mark-group
         (and (gnus-group-group-name)
@@ -659,27 +880,30 @@ ticked: The number of ticked articles."
              (memq (gnus-group-group-name) gnus-group-marked))]
        ["Unmark all" gnus-group-unmark-all-groups gnus-group-marked]
        ["Mark regexp..." gnus-group-mark-regexp t]
-       ["Mark region" gnus-group-mark-region t]
+       ["Mark region" gnus-group-mark-region :active (gnus-mark-active-p)]
        ["Mark buffer" gnus-group-mark-buffer t]
        ["Execute command" gnus-group-universal-argument
         (or gnus-group-marked (gnus-group-group-name))])
        ("Subscribe"
-       ["Subscribe to a group" gnus-group-unsubscribe-group t]
-       ["Kill all newsgroups in region" gnus-group-kill-region t]
+       ["Subscribe to a group..." gnus-group-unsubscribe-group t]
+       ["Kill all newsgroups in region" gnus-group-kill-region
+        :active (gnus-mark-active-p)]
        ["Kill all zombie groups" gnus-group-kill-all-zombies
         gnus-zombie-list]
        ["Kill all groups on level..." gnus-group-kill-level t])
        ("Foreign groups"
-       ["Make a foreign group" gnus-group-make-group t]
-       ["Add a directory group" gnus-group-make-directory-group t]
+       ["Make a foreign group..." gnus-group-make-group t]
+       ["Make a shimbun group..." gnus-group-make-shimbun-group t]
+       ["Add a directory group..." gnus-group-make-directory-group t]
        ["Add the help group" gnus-group-make-help-group t]
        ["Add the archive group" gnus-group-make-archive-group t]
-       ["Make a doc group" gnus-group-make-doc-group t]
-       ["Make a web group" gnus-group-make-web-group t]
-       ["Make a kiboze group" gnus-group-make-kiboze-group t]
-       ["Make a virtual group" gnus-group-make-empty-virtual t]
-       ["Add a group to a virtual" gnus-group-add-to-virtual t]
-       ["Rename group" gnus-group-rename-group
+       ["Make a doc group..." gnus-group-make-doc-group t]
+       ["Make a web group..." gnus-group-make-web-group t]
+       ["Make a kiboze group..." gnus-group-make-kiboze-group t]
+       ["Make a virtual group..." gnus-group-make-empty-virtual t]
+       ["Add a group to a virtual..." gnus-group-add-to-virtual t]
+       ["Make an RSS group..." gnus-group-make-rss-group t]
+       ["Rename group..." gnus-group-rename-group
         (gnus-check-backend-function
          'request-rename-group (gnus-group-group-name))]
        ["Delete group" gnus-group-delete-group
@@ -693,9 +917,12 @@ ticked: The number of ticked articles."
        ["Next unread same level" gnus-group-next-unread-group-same-level t]
        ["Previous unread same level"
         gnus-group-prev-unread-group-same-level t]
-       ["Jump to group" gnus-group-jump-to-group t]
+       ["Jump to group..." gnus-group-jump-to-group t]
        ["First unread group" gnus-group-first-unread-group t]
        ["Best unread group" gnus-group-best-unread-group t])
+       ("Sieve"
+       ["Generate" gnus-sieve-generate t]
+       ["Generate and update" gnus-sieve-update t])
        ["Delete bogus groups" gnus-group-check-bogus-groups t]
        ["Find new newsgroups" gnus-group-find-new-groups t]
        ["Transpose" gnus-group-transpose-groups
@@ -704,22 +931,29 @@ ticked: The number of ticked articles."
 
     (easy-menu-define
      gnus-group-misc-menu gnus-group-mode-map ""
-     '("Misc"
+     `("Gnus"
        ("SOUP"
        ["Pack replies" nnsoup-pack-replies (fboundp 'nnsoup-request-group)]
        ["Send replies" gnus-soup-send-replies
         (fboundp 'gnus-soup-pack-packet)]
        ["Pack packet" gnus-soup-pack-packet (fboundp 'gnus-soup-pack-packet)]
        ["Save areas" gnus-soup-save-areas (fboundp 'gnus-soup-pack-packet)]
-       ["Brew SOUP" gnus-soup-brew-soup (fboundp 'gnus-soup-pack-packet)])
-       ["Send a bug report" gnus-bug t]
+       ["Brew SOUP" gnus-group-brew-soup (fboundp 'gnus-soup-pack-packet)])
        ["Send a mail" gnus-group-mail t]
-       ["Post an article..." gnus-group-post-news t]
-       ["Check for new news" gnus-group-get-new-news t]
+       ["Send a message (mail or news)" gnus-group-post-news t]
+       ["Create a local message" gnus-group-news t]
+       ["Check for new news" gnus-group-get-new-news
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Get newly arrived articles"))
+       ]
+       ["Send queued messages" gnus-delay-send-queue
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Send all messages that are scheduled to be sent now"))
+       ]
        ["Activate all groups" gnus-activate-all-groups t]
        ["Restart Gnus" gnus-group-restart t]
        ["Read init file" gnus-group-read-init-file t]
-       ["Browse foreign server" gnus-group-browse-foreign-server t]
+       ["Browse foreign server..." gnus-group-browse-foreign-server t]
        ["Enter server buffer" gnus-group-enter-server-mode t]
        ["Expire all expirable articles" gnus-group-expire-all-groups t]
        ["Generate any kiboze groups" nnkiboze-generate-groups t]
@@ -730,11 +964,45 @@ ticked: The number of ticked articles."
        ["Read manual" gnus-info-find-node t]
        ["Flush score cache" gnus-score-flush-cache t]
        ["Toggle topics" gnus-topic-mode t]
-       ["Exit from Gnus" gnus-group-exit t]
+       ["Send a bug report" gnus-bug t]
+       ["Exit from Gnus" gnus-group-exit
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Quit reading news"))]
        ["Exit without saving" gnus-group-quit t]))
 
     (gnus-run-hooks 'gnus-group-menu-hook)))
 
+(defvar gnus-group-toolbar-map nil)
+
+;; Emacs 21 tool bar.  Should be no-op otherwise.
+(defun gnus-group-make-tool-bar ()
+  (if (and
+       (condition-case nil (require 'tool-bar) (error nil))
+       (fboundp 'tool-bar-add-item-from-menu)
+       (default-value 'tool-bar-mode)
+       (not gnus-group-toolbar-map))
+      (setq gnus-group-toolbar-map
+           (let ((tool-bar-map (make-sparse-keymap))
+                 (load-path (mm-image-load-path)))
+             (tool-bar-add-item-from-menu
+              'gnus-group-get-new-news "get-news" gnus-group-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-group-get-new-news-this-group "gnntg" gnus-group-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-group-catchup-current "catchup" gnus-group-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-group-describe-group "describe-group" gnus-group-mode-map)
+             (tool-bar-add-item "subscribe" 'gnus-group-subscribe 'subscribe
+                                :help "Subscribe to the current group")
+             (tool-bar-add-item "unsubscribe" 'gnus-group-unsubscribe
+                                'unsubscribe
+                                :help "Unsubscribe from the current group")
+             (tool-bar-add-item-from-menu
+              'gnus-group-exit "exit-gnus" gnus-group-mode-map)
+             tool-bar-map)))
+  (if gnus-group-toolbar-map
+      (set (make-local-variable 'tool-bar-map) gnus-group-toolbar-map)))
+
 (defun gnus-group-mode ()
   "Major mode for reading news.
 
@@ -753,30 +1021,32 @@ The following commands are available:
 
 \\{gnus-group-mode-map}"
   (interactive)
-  (when (gnus-visual-p 'group-menu 'menu)
-    (gnus-group-make-menu-bar))
   (kill-all-local-variables)
+  (when (gnus-visual-p 'group-menu 'menu)
+    (gnus-group-make-menu-bar)
+    (gnus-group-make-tool-bar))
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-group-mode)
   (setq mode-name "Group")
   (gnus-group-set-mode-line)
   (setq mode-line-process nil)
   (use-local-map gnus-group-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq truncate-lines t)
   (setq buffer-read-only t)
   (gnus-set-default-directory)
   (gnus-update-format-specifications nil 'group 'group-mode)
   (gnus-update-group-mark-positions)
-  (make-local-hook 'post-command-hook)
-  (add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
   (when gnus-use-undo
     (gnus-undo-mode 1))
+  (when gnus-slave
+    (gnus-slave-mode))
   (gnus-run-hooks 'gnus-group-mode-hook))
 
 (defun gnus-update-group-mark-positions ()
   (save-excursion
-    (let ((gnus-process-mark 128)
+    (let ((gnus-process-mark ?\200)
+         (gnus-group-update-hook nil)
          (gnus-group-marked '("dummy.group"))
          (gnus-active-hashtb (make-vector 10 0))
          (topic ""))
@@ -788,9 +1058,6 @@ The following commands are available:
            (list (cons 'process (and (search-forward "\200" nil t)
                                      (- (point) 2))))))))
 
-(defun gnus-clear-inboxes-moved ()
-  (setq nnmail-moved-inboxes nil))
-
 (defun gnus-mouse-pick-group (e)
   "Enter the group under the mouse pointer."
   (interactive "e")
@@ -815,13 +1082,65 @@ The following commands are available:
     (or level gnus-group-default-list-level gnus-level-subscribed))))
 
 (defun gnus-group-setup-buffer ()
-  (set-buffer (get-buffer-create gnus-group-buffer))
+  (set-buffer (gnus-get-buffer-create gnus-group-buffer))
   (unless (eq major-mode 'gnus-group-mode)
-    (gnus-add-current-to-buffer-list)
     (gnus-group-mode)
     (when gnus-carpal
       (gnus-carpal-setup-buffer 'group))))
 
+(defun gnus-group-name-charset (method group)
+  (if (null method)
+      (setq method (gnus-find-method-for-group group)))
+  (let ((item (assoc method gnus-group-name-charset-method-alist))
+       (alist gnus-group-name-charset-group-alist)
+       result)
+    (if item
+       (cdr item)
+      (while (setq item (pop alist))
+       (if (string-match (car item) group)
+           (setq alist nil
+                 result (cdr item))))
+      result)))
+
+(defun gnus-group-name-decode (string charset)
+  ;; Fixme: Don't decode in unibyte mode.
+  (if (and string charset (featurep 'mule))
+      (decode-coding-string string charset)
+    string))
+
+(defun gnus-group-decoded-name (string)
+  (let ((charset (gnus-group-name-charset nil string)))
+    (gnus-group-name-decode string charset)))
+
+(defun gnus-group-name-encode (string charset)
+  (if (and string charset (featurep 'mule))
+      (encode-coding-string string charset)
+    string))
+
+(defun gnus-group-encoded-name (string)
+  (let ((charset (gnus-group-name-charset nil string)))
+    (gnus-group-name-encode string charset)))
+
+(defun gnus-group-completing-read-group-name
+  (prompt table &optional predicate require-match initial-contents history)
+  (if (vectorp table)
+      (mapatoms
+       (lambda (group)
+        (push (list (gnus-group-decoded-name (symbol-name group))) table))
+       (prog1
+          table
+        (setq table nil)))
+    (dolist (entry (prog1
+                      table
+                    (setq table nil)))
+      (push (list (gnus-group-decoded-name (car entry))) table)))
+  (gnus-group-encoded-name
+   (completing-read
+    prompt table predicate
+    require-match
+    initial-contents
+    history)))
+
 (defun gnus-group-list-groups (&optional level unread lowest)
   "List newsgroups with level LEVEL or lower that have unread articles.
 Default is all subscribed groups.
@@ -836,8 +1155,6 @@ Also see the `gnus-group-use-permanent-levels' variable."
            (gnus-group-default-level nil t)
            gnus-group-default-list-level
            gnus-level-subscribed))))
-  ;; Just do this here, for no particular good reason.
-  (gnus-clear-inboxes-moved)
   (unless level
     (setq level (car gnus-group-list-mode)
          unread (cdr gnus-group-list-mode)))
@@ -897,18 +1214,35 @@ If ALL (the prefix), also list groups that have no unread articles."
   (interactive "nList groups on level: \nP")
   (gnus-group-list-groups level all level))
 
-(defun gnus-group-prepare-flat (level &optional all lowest regexp)
+(defun gnus-group-prepare-logic (group test)
+  (or (and gnus-group-listed-groups
+          (null gnus-group-list-option)
+          (member group gnus-group-listed-groups))
+      (cond
+       ((null gnus-group-listed-groups) test)
+       ((null gnus-group-list-option) test)
+       (t (and (member group gnus-group-listed-groups)
+              (if (eq gnus-group-list-option 'flush)
+                  (not test)
+                test))))))
+
+(defun gnus-group-prepare-flat (level &optional predicate lowest regexp)
   "List all newsgroups with unread articles of level LEVEL or lower.
-If ALL is non-nil, list groups that have no unread articles.
+If PREDICATE is a function, list groups that the function returns non-nil;
+if it is t, list groups that have no unread articles.
 If LOWEST is non-nil, list all newsgroups of level LOWEST or higher.
-If REGEXP, only list groups matching REGEXP."
+If REGEXP is a function, list dead groups that the function returns non-nil;
+if it is a string, only list groups matching REGEXP."
   (set-buffer gnus-group-buffer)
   (let ((buffer-read-only nil)
        (newsrc (cdr gnus-newsrc-alist))
        (lowest (or lowest 1))
+       (not-in-list (and gnus-group-listed-groups
+                         (copy-sequence gnus-group-listed-groups)))
        info clevel unread group params)
     (erase-buffer)
-    (when (< lowest gnus-level-zombie)
+    (when (or (< lowest gnus-level-zombie)
+             gnus-group-listed-groups)
       ;; List living groups.
       (while newsrc
        (setq info (car newsrc)
@@ -916,41 +1250,60 @@ If REGEXP, only list groups matching REGEXP."
              params (gnus-info-params info)
              newsrc (cdr newsrc)
              unread (car (gnus-gethash group gnus-newsrc-hashtb)))
-       (and unread                     ; This group might be bogus
-            (or (not regexp)
-                (string-match regexp group))
-            (<= (setq clevel (gnus-info-level info)) level)
-            (>= clevel lowest)
-            (or all                    ; We list all groups?
-                (if (eq unread t)      ; Unactivated?
-                    gnus-group-list-inactive-groups ; We list unactivated
-                  (> unread 0))        ; We list groups with unread articles
-                (and gnus-list-groups-with-ticked-articles
-                     (cdr (assq 'tick (gnus-info-marks info))))
+       (when not-in-list
+         (setq not-in-list (delete group not-in-list)))
+       (when (gnus-group-prepare-logic
+              group
+              (and unread              ; This group might be unchecked
+                   (or (not (stringp regexp))
+                       (string-match regexp group))
+                   (<= (setq clevel (gnus-info-level info)) level)
+                   (>= clevel lowest)
+                   (cond
+                    ((functionp predicate)
+                     (funcall predicate info))
+                    (predicate t)      ; We list all groups?
+                    (t
+                     (or
+                      (if (eq unread t) ; Unactivated?
+                          gnus-group-list-inactive-groups
+                                       ; We list unactivated
+                        (> unread 0))
+                                       ; We list groups with unread articles
+                      (and gnus-list-groups-with-ticked-articles
+                           (cdr (assq 'tick (gnus-info-marks info))))
                                        ; And groups with tickeds
-                ;; Check for permanent visibility.
-                (and gnus-permanently-visible-groups
-                     (string-match gnus-permanently-visible-groups
-                                   group))
-                (memq 'visible params)
-                (cdr (assq 'visible params)))
-            (gnus-group-insert-group-line
-             group (gnus-info-level info)
-             (gnus-info-marks info) unread (gnus-info-method info)))))
+                      ;; Check for permanent visibility.
+                      (and gnus-permanently-visible-groups
+                           (string-match gnus-permanently-visible-groups
+                                         group))
+                      (memq 'visible params)
+                      (cdr (assq 'visible params)))))))
+         (gnus-group-insert-group-line
+          group (gnus-info-level info)
+          (gnus-info-marks info) unread (gnus-info-method info)))))
 
     ;; List dead groups.
-    (and (>= level gnus-level-zombie) (<= lowest gnus-level-zombie)
-        (gnus-group-prepare-flat-list-dead
-         (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
-         gnus-level-zombie ?Z
-         regexp))
-    (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)
-        (gnus-group-prepare-flat-list-dead
-         (setq gnus-killed-list (sort gnus-killed-list 'string<))
-         gnus-level-killed ?K regexp))
+    (when (or gnus-group-listed-groups
+             (and (>= level gnus-level-zombie)
+                  (<= lowest gnus-level-zombie)))
+      (gnus-group-prepare-flat-list-dead
+       (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
+       gnus-level-zombie ?Z
+       regexp))
+    (when not-in-list
+      (dolist (group gnus-zombie-list)
+       (setq not-in-list (delete group not-in-list))))
+    (when (or gnus-group-listed-groups
+             (and (>= level gnus-level-killed) (<= lowest gnus-level-killed)))
+      (gnus-group-prepare-flat-list-dead
+       (gnus-union
+       not-in-list
+       (setq gnus-killed-list (sort gnus-killed-list 'string<)))
+       gnus-level-killed ?K regexp))
 
     (gnus-group-set-mode-line)
-    (setq gnus-group-list-mode (cons level all))
+    (setq gnus-group-list-mode (cons level predicate))
     (gnus-run-hooks 'gnus-group-prepare-hook)
     t))
 
@@ -959,27 +1312,38 @@ If REGEXP, only list groups matching REGEXP."
   ;; suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.  It does
   ;; this by ignoring the group format specification altogether.
   (let (group)
-    (if regexp
-       ;; This loop is used when listing groups that match some
-       ;; regexp.
+    (if (> (length groups) gnus-group-listing-limit)
        (while groups
          (setq group (pop groups))
-         (when (string-match regexp group)
+         (when (gnus-group-prepare-logic
+                group
+                (or (not regexp)
+                    (and (stringp regexp) (string-match regexp group))
+                    (and (functionp regexp) (funcall regexp group))))
            (gnus-add-text-properties
             (point) (prog1 (1+ (point))
-                      (insert " " mark "     *: " group "\n"))
+                      (insert " " mark "     *: "
+                              (gnus-group-decoded-name group)
+                              "\n"))
             (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
                   'gnus-unread t
                   'gnus-level level))))
-      ;; This loop is used when listing all groups.
       (while groups
-       (gnus-add-text-properties
-        (point) (prog1 (1+ (point))
-                  (insert " " mark "     *: "
-                          (setq group (pop groups)) "\n"))
-        (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
-              'gnus-unread t
-              'gnus-level level))))))
+       (setq group (pop groups))
+       (when (gnus-group-prepare-logic
+              group
+              (or (not regexp)
+                  (and (stringp regexp) (string-match regexp group))
+                  (and (functionp regexp) (funcall regexp group))))
+         (gnus-group-insert-group-line
+          group level nil
+          (let ((active (gnus-active group)))
+            (if active
+                (if (zerop (cdr active))
+                    0
+                  (- (1+ (cdr active)) (car active)))
+              nil))
+          (gnus-method-simplify (gnus-find-method-for-group group))))))))
 
 (defun gnus-group-update-group-line ()
   "Update the current line in the group buffer."
@@ -1022,13 +1386,29 @@ If REGEXP, only list groups matching REGEXP."
               0
             (- (1+ (cdr active)) (car active)))
         nil)
-       nil))))
+       (gnus-method-simplify (gnus-find-method-for-group group))))))
+
+(defun gnus-number-of-unseen-articles-in-group (group)
+  (let* ((info (nth 2 (gnus-group-entry group)))
+        (marked (gnus-info-marks info))
+        (seen (cdr (assq 'seen marked)))
+        (active (gnus-active group)))
+    (if (not active)
+       0
+      (length (gnus-uncompress-range
+              (gnus-range-difference
+               (gnus-range-difference (list active) (gnus-info-read info))
+               seen))))))
 
 (defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level
                                                    gnus-tmp-marked number
                                                    gnus-tmp-method)
   "Insert a group line in the group buffer."
-  (let* ((gnus-tmp-active (gnus-active gnus-tmp-group))
+  (let* ((gnus-tmp-method
+         (gnus-server-get-method gnus-tmp-group gnus-tmp-method))
+        (group-name-charset (gnus-group-name-charset gnus-tmp-method
+                                                     gnus-tmp-group))
+        (gnus-tmp-active (gnus-active gnus-tmp-group))
         (gnus-tmp-number-total
          (if gnus-tmp-active
              (1+ (- (cdr gnus-tmp-active) (car gnus-tmp-active)))
@@ -1045,10 +1425,17 @@ If REGEXP, only list groups matching REGEXP."
                ((<= gnus-tmp-level gnus-level-unsubscribed) ?U)
                ((= gnus-tmp-level gnus-level-zombie) ?Z)
                (t ?K)))
-        (gnus-tmp-qualified-group (gnus-group-real-name gnus-tmp-group))
+        (gnus-tmp-qualified-group
+         (gnus-group-name-decode (gnus-group-real-name gnus-tmp-group)
+                                 group-name-charset))
+        (gnus-tmp-comment
+         (or (gnus-group-get-parameter gnus-tmp-group 'comment t)
+             gnus-tmp-group))
         (gnus-tmp-newsgroup-description
          (if gnus-description-hashtb
-             (or (gnus-gethash gnus-tmp-group gnus-description-hashtb) "")
+             (or (gnus-group-name-decode
+                  (gnus-gethash gnus-tmp-group gnus-description-hashtb)
+                  group-name-charset) "")
            ""))
         (gnus-tmp-moderated
          (if (and gnus-moderated-hashtb
@@ -1056,8 +1443,7 @@ If REGEXP, only list groups matching REGEXP."
              ?m ? ))
         (gnus-tmp-moderated-string
          (if (eq gnus-tmp-moderated ?m) "(m)" ""))
-        (gnus-tmp-method
-         (gnus-server-get-method gnus-tmp-group gnus-tmp-method)) ;
+        (gnus-tmp-group-icon "==&&==")
         (gnus-tmp-news-server (or (cadr gnus-tmp-method) ""))
         (gnus-tmp-news-method (or (car gnus-tmp-method) ""))
         (gnus-tmp-news-method-string
@@ -1069,6 +1455,11 @@ If REGEXP, only list groups matching REGEXP."
                   (zerop number)
                   (cdr (assq 'tick gnus-tmp-marked)))
              ?* ? ))
+        (gnus-tmp-summary-live
+         (if (and (not gnus-group-is-exiting-p)
+                  (gnus-buffer-live-p (gnus-summary-buffer-name
+                                       gnus-tmp-group)))
+             ?* ? ))
         (gnus-tmp-process-marked
          (if (member gnus-tmp-group gnus-group-marked)
              gnus-process-mark ? ))
@@ -1083,7 +1474,9 @@ If REGEXP, only list groups matching REGEXP."
      (point)
      (prog1 (1+ (point))
        ;; Insert the text.
-       (eval gnus-group-line-format-spec))
+       (let ((gnus-tmp-group (gnus-group-name-decode
+                             gnus-tmp-group group-name-charset)))
+        (eval gnus-group-line-format-spec)))
      `(gnus-group ,(gnus-intern-safe gnus-tmp-group gnus-active-hashtb)
                  gnus-unread ,(if (numberp number)
                                   (string-to-int gnus-tmp-number-of-unread)
@@ -1091,10 +1484,10 @@ If REGEXP, only list groups matching REGEXP."
                  gnus-marked ,gnus-tmp-marked-mark
                  gnus-indentation ,gnus-group-indentation
                  gnus-level ,gnus-tmp-level))
+    (forward-line -1)
     (when (inline (gnus-visual-p 'group-highlight 'highlight))
-      (forward-line -1)
-      (gnus-run-hooks 'gnus-group-update-hook)
-      (forward-line))
+      (gnus-run-hooks 'gnus-group-update-hook))
+    (forward-line)
     ;; Allow XEmacs to remove front-sticky text properties.
     (gnus-group-remove-excess-properties)))
 
@@ -1102,7 +1495,7 @@ If REGEXP, only list groups matching REGEXP."
   "Highlight the current line according to `gnus-group-highlight'."
   (let* ((list gnus-group-highlight)
         (p (point))
-        (end (progn (end-of-line) (point)))
+        (end (gnus-point-at-eol))
         ;; now find out where the line starts and leave point there.
         (beg (progn (beginning-of-line) (point)))
         (group (gnus-group-group-name))
@@ -1111,11 +1504,15 @@ If REGEXP, only list groups matching REGEXP."
         (active (gnus-active group))
         (total (if active (1+ (- (cdr active) (car active))) 0))
         (info (nth 2 entry))
-        (method (gnus-server-get-method group (gnus-info-method info)))
+        (method (inline (gnus-server-get-method group (gnus-info-method info))))
         (marked (gnus-info-marks info))
-        (mailp (memq 'mail (assoc (symbol-name
-                                   (car (or method gnus-select-method)))
-                                  gnus-valid-select-methods)))
+        (mailp (apply 'append
+                      (mapcar
+                       (lambda (x)
+                         (memq x (assoc (symbol-name
+                                         (car (or method gnus-select-method)))
+                                        gnus-valid-select-methods)))
+                       '(mail post-mail))))
         (level (or (gnus-info-level info) gnus-level-killed))
         (score (or (gnus-info-score info) 0))
         (ticked (gnus-range-length (cdr (assq 'tick marked))))
@@ -1127,7 +1524,7 @@ If REGEXP, only list groups matching REGEXP."
       (setq list (cdr list)))
     (let ((face (cdar list)))
       (unless (eq face (get-text-property beg 'face))
-       (gnus-put-text-property
+       (gnus-put-text-property-excluding-characters-with-faces
         beg end 'face
         (setq face (if (boundp face) (symbol-value face) face)))
        (gnus-extent-start-open beg)))
@@ -1150,7 +1547,8 @@ already."
            found buffer-read-only)
        ;; Enter the current status into the dribble buffer.
        (let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
-         (when (and entry (not (gnus-ephemeral-group-p group)))
+         (when (and entry
+                    (not (gnus-ephemeral-group-p group)))
            (gnus-dribble-enter
             (concat "(gnus-group-set-info '"
                     (gnus-prin1-to-string (nth 2 entry))
@@ -1234,7 +1632,8 @@ already."
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
   (let ((group (get-text-property (gnus-point-at-bol) 'gnus-group)))
-    (and group (symbol-name group))))
+    (when group
+      (symbol-name group))))
 
 (defun gnus-group-group-level ()
   "Get the level of the newsgroup on the current line."
@@ -1311,6 +1710,12 @@ If FIRST-TOO, the current line is also eligible as a target."
 
 ;; Group marking.
 
+(defun gnus-group-mark-line-p ()
+  (save-excursion
+    (beginning-of-line)
+    (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
+    (eq (char-after) gnus-process-mark)))
+
 (defun gnus-group-mark-group (n &optional unmark no-advance)
   "Mark the current group."
   (interactive "p")
@@ -1323,7 +1728,7 @@ If FIRST-TOO, the current line is also eligible as a target."
        (beginning-of-line)
        (forward-char (or (cdr (assq 'process gnus-group-mark-positions)) 2))
        (subst-char-in-region
-        (point) (1+ (point)) (following-char)
+        (point) (1+ (point)) (char-after)
         (if unmark
             (progn
               (setq gnus-group-marked (delete group gnus-group-marked))
@@ -1372,15 +1777,17 @@ If UNMARK, remove the mark instead."
   (interactive "sMark (regexp): ")
   (let ((alist (cdr gnus-newsrc-alist))
        group)
-    (while alist
-      (when (string-match regexp (setq group (gnus-info-group (pop alist))))
-       (gnus-group-set-mark group))))
+    (save-excursion
+      (while alist
+       (when (string-match regexp (setq group (gnus-info-group (pop alist))))
+         (gnus-group-jump-to-group group)
+         (gnus-group-set-mark group)))))
   (gnus-group-position-point))
 
-(defun gnus-group-remove-mark (group)
+(defun gnus-group-remove-mark (group &optional test-marked)
   "Remove the process mark from GROUP and move point there.
 Return nil if the group isn't displayed."
-  (if (gnus-group-goto-group group)
+  (if (gnus-group-goto-group group nil test-marked)
       (save-excursion
        (gnus-group-mark-group 1 'unmark t)
        t)
@@ -1428,7 +1835,7 @@ Take into consideration N (the prefix) and the list of marked groups."
          (setq n (1- n))
          (gnus-group-next-group way)))
       (nreverse groups)))
-   ((gnus-region-active-p)
+   ((and (gnus-region-active-p) (mark))
     ;; Work on the region between point and mark.
     (let ((max (max (point) (mark)))
          groups)
@@ -1459,23 +1866,25 @@ Take into consideration N (the prefix) and the list of marked groups."
     (eval
      `(defun gnus-group-iterate (arg ,function)
        "Iterate FUNCTION over all process/prefixed groups.
-FUNCTION will be called with the group name as the paremeter
+FUNCTION will be called with the group name as the parameter
 and with point over the group in question."
        (let ((,groups (gnus-group-process-prefix arg))
              (,window (selected-window))
              ,group)
-         (while (setq ,group (pop ,groups))
+         (while ,groups
+           (setq ,group (car ,groups)
+                 ,groups (cdr ,groups))
            (select-window ,window)
            (gnus-group-remove-mark ,group)
            (save-selected-window
              (save-excursion
                (funcall ,function ,group)))))))))
-  
+
 (put 'gnus-group-iterate 'lisp-indent-function 1)
 
 ;; Selecting groups.
 
-(defun gnus-group-read-group (&optional all no-article group)
+(defun gnus-group-read-group (&optional all no-article group select-articles)
   "Read news in this newsgroup.
 If the prefix argument ALL is non-nil, already read articles become
 readable.  IF ALL is a number, fetch this number of articles.  If the
@@ -1506,14 +1915,17 @@ group."
                                          (cdr (assq 'tick marked)))
                                  (gnus-range-length
                                   (cdr (assq 'dormant marked)))))))
-     no-article nil no-display)))
+     no-article nil no-display nil select-articles)))
 
 (defun gnus-group-select-group (&optional all)
   "Select this newsgroup.
 No article is selected automatically.
+If the group is opened, just switch the summary buffer.
 If ALL is non-nil, already read articles become readable.
 If ALL is a number, fetch this number of articles."
   (interactive "P")
+  (when (and (eobp) (not (gnus-group-group-name)))
+    (forward-line -1))
   (gnus-group-read-group all t))
 
 (defun gnus-group-quick-select-group (&optional all)
@@ -1552,56 +1964,97 @@ be permanent."
         gnus-summary-mode-hook gnus-select-group-hook
         (group (gnus-group-group-name))
         (method (gnus-find-method-for-group group)))
-    (setq method
-         `(,(car method) ,(concat (cadr method) "-ephemeral")
-           (,(intern (format "%s-address" (car method))) ,(cadr method))
-           ,@(cddr method)))
     (gnus-group-read-ephemeral-group
      (gnus-group-prefixed-name group method) method)))
 
 ;;;###autoload
-(defun gnus-fetch-group (group)
+(defun gnus-fetch-group (group &optional articles)
   "Start Gnus if necessary and enter GROUP.
 Returns whether the fetching was successful or not."
-  (interactive "sGroup name: ")
+  (interactive (list (gnus-group-completing-read-group-name
+                     "Group name: " gnus-active-hashtb)))
   (unless (get-buffer gnus-group-buffer)
     (gnus-no-server))
-  (gnus-group-read-group nil nil group))
+  (gnus-group-read-group articles nil group))
+
+;;;###autoload
+(defun gnus-fetch-group-other-frame (group)
+  "Pop up a frame and enter GROUP."
+  (interactive "P")
+  (let ((window (get-buffer-window gnus-group-buffer)))
+    (cond (window
+          (select-frame (window-frame window)))
+         ((= (length (frame-list)) 1)
+          (select-frame (make-frame)))
+         (t
+          (other-frame 1))))
+  (gnus-fetch-group group))
 
 (defvar gnus-ephemeral-group-server 0)
 
+(defcustom gnus-large-ephemeral-newsgroup 200
+  "The number of articles which indicates a large ephemeral newsgroup.
+Same as `gnus-large-newsgroup', but only used for ephemeral newsgroups.
+
+If the number of articles in a newsgroup is greater than this value,
+confirmation is required for selecting the newsgroup.  If it is nil, no
+confirmation is required."
+  :group 'gnus-group-select
+  :type '(choice (const :tag "No limit" nil)
+                integer))
+
+(defcustom gnus-fetch-old-ephemeral-headers nil
+  "Same as `gnus-fetch-old-headers', but only used for ephemeral newsgroups."
+  :group 'gnus-thread
+  :type '(choice (const :tag "off" nil)
+                (const some)
+                number
+                (sexp :menu-tag "other" t)))
+
 ;; Enter a group that is not in the group buffer.  Non-nil is returned
 ;; if selection was successful.
 (defun gnus-group-read-ephemeral-group (group method &optional activate
-                                             quit-config request-only)
+                                             quit-config request-only
+                                             select-articles
+                                             parameters)
   "Read GROUP from METHOD as an ephemeral group.
 If ACTIVATE, request the group first.
 If QUIT-CONFIG, use that window configuration when exiting from the
 ephemeral group.
 If REQUEST-ONLY, don't actually read the group; just request it.
+If SELECT-ARTICLES, only select those articles.
+If PARAMETERS, use those as the group parameters.
 
-Return the name of the group is selection was successful."
+Return the name of the group if selection was successful."
+  (interactive
+   (list
+    ;; (gnus-read-group "Group name: ")
+    (completing-read
+     "Group: " gnus-active-hashtb
+     nil nil nil
+     'gnus-group-history)
+    (gnus-read-method "From method: ")))
   ;; Transform the select method into a unique server.
   (when (stringp method)
     (setq method (gnus-server-to-method method)))
-  (let ((saddr (intern (format "%s-address" (car method)))))
-    (setq method (gnus-copy-sequence method))
-    (require (car method))
-    (when (boundp saddr)
-      (unless (assq saddr method)
-       (nconc method `((,saddr ,(cadr method))))
-       (setf (cadr method) (format "%s-%d" (cadr method)
-                                   (incf gnus-ephemeral-group-server))))))
+  (setq method
+       `(,(car method) ,(concat (cadr method) "-ephemeral")
+         (,(intern (format "%s-address" (car method))) ,(cadr method))
+         ,@(cddr method)))
   (let ((group (if (gnus-group-foreign-p group) group
-                (gnus-group-prefixed-name group method))))
+                (gnus-group-prefixed-name (gnus-group-real-name group)
+                                          method))))
     (gnus-sethash
      group
      `(-1 nil (,group
               ,gnus-level-default-subscribed nil nil ,method
-              ((quit-config .
-                            ,(if quit-config quit-config
-                               (cons gnus-summary-buffer
-                                     gnus-current-window-configuration))))))
+              ,(cons
+                (if quit-config
+                    (cons 'quit-config quit-config)
+                  (cons 'quit-config
+                        (cons gnus-summary-buffer
+                              gnus-current-window-configuration)))
+                parameters)))
      gnus-newsrc-hashtb)
     (push method gnus-ephemeral-servers)
     (set-buffer gnus-group-buffer)
@@ -1615,18 +2068,23 @@ Return the name of the group is selection was successful."
     (if request-only
        group
       (condition-case ()
-         (when (gnus-group-read-group t t group)
+         (when (let ((gnus-large-newsgroup gnus-large-ephemeral-newsgroup)
+                     (gnus-fetch-old-headers
+                      gnus-fetch-old-ephemeral-headers))
+                 (gnus-group-read-group t t group select-articles))
            group)
        ;;(error nil)
-       (quit nil)))))
+       (quit
+        (message "Quit reading the ephemeral group")
+        nil)))))
 
 (defun gnus-group-jump-to-group (group)
   "Jump to newsgroup GROUP."
   (interactive
-   (list (completing-read
+   (list (gnus-group-completing-read-group-name
          "Group: " gnus-active-hashtb nil
          (gnus-read-active-file-p)
-         nil
+         gnus-group-jump-to-group-prompt
          'gnus-group-history)))
 
   (when (equal group "")
@@ -1641,41 +2099,56 @@ Return the name of the group is selection was successful."
   ;; Adjust cursor point.
   (gnus-group-position-point))
 
-(defun gnus-group-goto-group (group &optional far)
+(defun gnus-group-goto-group (group &optional far test-marked)
   "Goto to newsgroup GROUP.
-If FAR, it is likely that the group is not on the current line."
+If FAR, it is likely that the group is not on the current line.
+If TEST-MARKED, the line must be marked."
   (when group
-    (if far
-       (gnus-goto-char
-        (text-property-any
-         (point-min) (point-max)
-         'gnus-group (gnus-intern-safe group gnus-active-hashtb)))
-      (beginning-of-line)
-      (cond
-       ;; It's quite likely that we are on the right line, so
-       ;; we check the current line first.
-       ((eq (get-text-property (point) 'gnus-group)
-           (gnus-intern-safe group gnus-active-hashtb))
-       (point))
-       ;; Previous and next line are also likely, so we check them as well.
-       ((save-excursion
-         (forward-line -1)
-         (eq (get-text-property (point) 'gnus-group)
-             (gnus-intern-safe group gnus-active-hashtb)))
-       (forward-line -1)
-       (point))
-       ((save-excursion
-         (forward-line 1)
-         (eq (get-text-property (point) 'gnus-group)
-             (gnus-intern-safe group gnus-active-hashtb)))
-       (forward-line 1)
-       (point))
-       (t
-       ;; Search through the entire buffer.
-       (gnus-goto-char
-        (text-property-any
-         (point-min) (point-max)
-         'gnus-group (gnus-intern-safe group gnus-active-hashtb))))))))
+    (beginning-of-line)
+    (cond
+     ;; It's quite likely that we are on the right line, so
+     ;; we check the current line first.
+     ((and (not far)
+          (eq (get-text-property (point) 'gnus-group)
+              (gnus-intern-safe group gnus-active-hashtb))
+          (or (not test-marked) (gnus-group-mark-line-p)))
+      (point))
+     ;; Previous and next line are also likely, so we check them as well.
+     ((and (not far)
+          (save-excursion
+            (forward-line -1)
+            (and (eq (get-text-property (point) 'gnus-group)
+                     (gnus-intern-safe group gnus-active-hashtb))
+                 (or (not test-marked) (gnus-group-mark-line-p)))))
+      (forward-line -1)
+      (point))
+     ((and (not far)
+          (save-excursion
+            (forward-line 1)
+            (and (eq (get-text-property (point) 'gnus-group)
+                     (gnus-intern-safe group gnus-active-hashtb))
+                 (or (not test-marked) (gnus-group-mark-line-p)))))
+      (forward-line 1)
+      (point))
+     (test-marked
+      (goto-char (point-min))
+      (let (found)
+       (while (and (not found)
+                   (gnus-goto-char
+                    (text-property-any
+                     (point) (point-max)
+                     'gnus-group
+                     (gnus-intern-safe group gnus-active-hashtb))))
+         (if (gnus-group-mark-line-p)
+             (setq found t)
+           (forward-line 1)))
+       found))
+     (t
+      ;; Search through the entire buffer.
+      (gnus-goto-char
+       (text-property-any
+       (point-min) (point-max)
+       'gnus-group (gnus-intern-safe group gnus-active-hashtb)))))))
 
 (defun gnus-group-next-group (n &optional silent)
   "Go to next N'th newsgroup.
@@ -1757,7 +2230,7 @@ If EXCLUDE-GROUP, do not go to that group."
       (forward-line 1))
     (when best-point
       (goto-char best-point))
-    (gnus-summary-position-point)
+    (gnus-group-position-point)
     (and best-point (gnus-group-group-name))))
 
 (defun gnus-group-first-unread-group ()
@@ -1790,10 +2263,13 @@ ADDRESS."
     (gnus-read-group "Group name: ")
     (gnus-read-method "From method: ")))
 
-  (let* ((meth (when (and method
-                         (not (gnus-server-equal method gnus-select-method)))
-                (if address (list (intern method) address)
-                  method)))
+  (when (stringp method)
+    (setq method (or (gnus-server-to-method method) method)))
+  (let* ((meth (gnus-method-simplify
+               (when (and method
+                          (not (gnus-server-equal method gnus-select-method)))
+                 (if address (list (intern method) address)
+                   method))))
         (nname (if method (gnus-group-prefixed-name name meth) name))
         backend info)
     (when (gnus-gethash nname gnus-newsrc-hashtb)
@@ -1817,7 +2293,7 @@ ADDRESS."
     (forward-line -1)
     (gnus-group-position-point)
 
-    ;; Load the backend and try to make the backend create
+    ;; Load the back end and try to make the back end create
     ;; the group as well.
     (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
                                                  nil meth))))
@@ -1825,27 +2301,46 @@ ADDRESS."
       (require backend))
     (gnus-check-server meth)
     (when (gnus-check-backend-function 'request-create-group nname)
-      (gnus-request-create-group nname nil args))
+      (unless (gnus-request-create-group nname nil args)
+       (error "Could not create group on server: %s"
+              (nnheader-get-report backend))))
     t))
 
-(defun gnus-group-delete-group (group &optional force)
-  "Delete the current group.  Only meaningful with mail groups.
+(defun gnus-group-delete-groups (&optional arg)
+  "Delete the current group.  Only meaningful with editable groups."
+  (interactive "P")
+  (let ((n (length (gnus-group-process-prefix arg))))
+    (when (gnus-yes-or-no-p
+          (if (= n 1)
+              "Delete this 1 group? "
+            (format "Delete these %d groups? " n)))
+      (gnus-group-iterate arg
+       (lambda (group)
+         (gnus-group-delete-group group nil t))))))
+
+(defvar gnus-cache-active-altered)
+
+(defun gnus-group-delete-group (group &optional force no-prompt)
+  "Delete the current group.  Only meaningful with editable groups.
 If FORCE (the prefix) is non-nil, all the articles in the group will
 be deleted.  This is \"deleted\" as in \"removed forever from the face
 of the Earth\".         There is no undo.  The user will be prompted before
-doing the deletion."
+doing the deletion.
+Note that you also have to specify FORCE if you want the group to
+be removed from the server, even when it's empty."
   (interactive
    (list (gnus-group-group-name)
         current-prefix-arg))
   (unless group
-    (error "No group to rename"))
+    (error "No group to delete"))
   (unless (gnus-check-backend-function 'request-delete-group group)
-    (error "This backend does not support group deletion"))
+    (error "This back end does not support group deletion"))
   (prog1
-      (if (not (gnus-yes-or-no-p
-               (format
-                "Do you really want to delete %s%s? "
-                group (if force " and all its contents" ""))))
+      (if (and (not no-prompt)
+              (not (gnus-yes-or-no-p
+                    (format
+                     "Do you really want to delete %s%s? "
+                     group (if force " and all its contents" "")))))
          ()                            ; Whew!
        (gnus-message 6 "Deleting group %s..." group)
        (if (not (gnus-request-delete-group group force))
@@ -1854,6 +2349,10 @@ doing the deletion."
          (gnus-group-goto-group group)
          (gnus-group-kill-group 1 t)
          (gnus-sethash group nil gnus-active-hashtb)
+         (if (boundp 'gnus-cache-active-hashtb)
+             (when gnus-cache-active-hashtb
+               (gnus-sethash group nil gnus-cache-active-hashtb)
+               (setq gnus-cache-active-altered t)))
          t))
     (gnus-group-position-point)))
 
@@ -1867,12 +2366,12 @@ and NEW-NAME will be prompted for."
     (progn
       (unless (gnus-check-backend-function
               'request-rename-group (gnus-group-group-name))
-       (error "This backend does not support renaming groups"))
+       (error "This back end does not support renaming groups"))
       (gnus-read-group "Rename group to: "
                       (gnus-group-real-name (gnus-group-group-name))))))
 
   (unless (gnus-check-backend-function 'request-rename-group group)
-    (error "This backend does not support renaming groups"))
+    (error "This back end does not support renaming groups"))
   (unless group
     (error "No group to rename"))
   (when (equal (gnus-group-real-name group) new-name)
@@ -1888,12 +2387,17 @@ and NEW-NAME will be prompted for."
           (gnus-group-real-name new-name)
           (gnus-info-method (gnus-get-info group)))))
 
+  (when (gnus-active new-name)
+    (error "The group %s already exists" new-name))
+
   (gnus-message 6 "Renaming group %s to %s..." group new-name)
   (prog1
-      (if (not (gnus-request-rename-group group new-name))
+      (if (progn
+           (gnus-group-goto-group group)
+           (not (when (< (gnus-group-group-level) gnus-level-zombie)
+                  (gnus-request-rename-group group new-name))))
          (gnus-error 3 "Couldn't rename group %s to %s" group new-name)
        ;; We rename the group internally by killing it...
-       (gnus-group-goto-group group)
        (gnus-group-kill-group)
        ;; ... changing its name ...
        (setcar (cdar gnus-list-of-killed-groups) new-name)
@@ -1902,6 +2406,8 @@ and NEW-NAME will be prompted for."
        (gnus-set-active new-name (gnus-active group))
        (gnus-message 6 "Renaming group %s to %s...done" group new-name)
        new-name)
+    (setq gnus-killed-list (delete group gnus-killed-list))
+    (gnus-set-active group nil)
     (gnus-dribble-touch)
     (gnus-group-position-point)))
 
@@ -1930,9 +2436,22 @@ and NEW-NAME will be prompted for."
        ((eq part 'method) "select method")
        ((eq part 'params) "group parameters")
        (t "group info"))
-      group)
+      (gnus-group-decoded-name group))
      `(lambda (form)
-       (gnus-group-edit-group-done ',part ,group form)))))
+       (gnus-group-edit-group-done ',part ,group form)))
+    (local-set-key
+     "\C-c\C-i"
+     (gnus-create-info-command
+      (format "(%s)%s"
+             (or gnus-info-filename
+                 (get-language-info current-language-environment 'gnus-info)
+                 "gnus")
+             (cond ((eq part 'method)
+                    "Select Methods")
+                   ((eq part 'params)
+                    "Group Parameters")
+                   (t
+                    "Group Info")))))))
 
 (defun gnus-group-edit-group-method (group)
   "Edit the select method of GROUP."
@@ -1981,6 +2500,7 @@ and NEW-NAME will be prompted for."
     (gnus-group-position-point)))
 
 (defun gnus-group-make-useful-group (group method)
+  "Create one of the groups described in `gnus-useful-groups'."
   (interactive
    (let ((entry (assoc (completing-read "Create group: " gnus-useful-groups
                                        nil t)
@@ -1992,21 +2512,33 @@ and NEW-NAME will be prompted for."
       (setcar entry (eval (cadar entry)))))
   (gnus-group-make-group group method))
 
-(defun gnus-group-make-help-group ()
-  "Create the Gnus documentation group."
+(defun gnus-group-make-help-group (&optional noerror)
+  "Create the Gnus documentation group.
+Optional argument NOERROR modifies the behavior of this function when the
+group already exists:
+- if not given, and error is signaled,
+- if t, stay silent,
+- if anything else, just print a message."
   (interactive)
   (let ((name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help")))
-       (file (nnheader-find-etc-directory "gnus-tut.txt" t))
-       dir)
-    (when (gnus-gethash name gnus-newsrc-hashtb)
-      (error "Documentation group already exists"))
-    (if (not file)
-       (gnus-message 1 "Couldn't find doc group")
-      (gnus-group-make-group
-       (gnus-group-real-name name)
-       (list 'nndoc "gnus-help"
-            (list 'nndoc-address file)
-            (list 'nndoc-article-type 'mbox)))))
+       (file (nnheader-find-etc-directory "gnus-tut.txt" t)))
+    (if (gnus-gethash name gnus-newsrc-hashtb)
+       (cond ((eq noerror nil)
+              (error "Documentation group already exists"))
+             ((eq noerror t)
+              ;; stay silent
+              )
+             (t
+              (gnus-message 1 "Documentation group already exists")))
+      ;; else:
+      (if (not file)
+         (gnus-message 1 "Couldn't find doc group")
+       (gnus-group-make-group
+        (gnus-group-real-name name)
+        (list 'nndoc "gnus-help"
+              (list 'nndoc-address file)
+              (list 'nndoc-article-type 'mbox))))
+      ))
   (gnus-group-position-point))
 
 (defun gnus-group-make-doc-group (file type)
@@ -2026,6 +2558,7 @@ and NEW-NAME will be prompted for."
                          ((= char ?d) 'digest)
                          ((= char ?f) 'forward)
                          ((= char ?a) 'mmfd)
+                         ((= char ?g) 'guess)
                          (t (setq err (format "%c unknown. " char))
                             nil))))
       (setq type found)))
@@ -2070,12 +2603,77 @@ If SOLID (the prefix), create a solid group."
                  (nnweb-type ,(intern type))
                  (nnweb-ephemeral-p t))))
     (if solid
-       (gnus-group-make-group group "nnweb" "" `(,(intern type) ,search))
+       (progn
+         (gnus-pull 'nnweb-ephemeral-p method)
+         (gnus-group-make-group group method))
       (gnus-group-read-ephemeral-group
        group method t
        (cons (current-buffer)
             (if (eq major-mode 'gnus-summary-mode) 'summary 'group))))))
 
+(eval-when-compile
+  (defvar nnrss-group-alist)
+  (defun nnrss-discover-feed (arg))
+  (defun nnrss-save-server-data (arg)))
+(defun gnus-group-make-rss-group (&optional url)
+  "Given a URL, discover if there is an RSS feed.
+If there is, use Gnus to create an nnrss group"
+  (interactive)
+  (require 'nnrss)
+  (if (not url)
+      (setq url (read-from-minibuffer "URL to Search for RSS: ")))
+  (let ((feedinfo (nnrss-discover-feed url)))
+    (if feedinfo
+       (let ((title (read-from-minibuffer "Title: "
+                                          (cdr (assoc 'title
+                                                      feedinfo))))
+             (desc  (read-from-minibuffer "Description: "
+                                          (cdr (assoc 'description
+                                                      feedinfo))))
+             (href (cdr (assoc 'href feedinfo))))
+         (push (list title href desc)
+               nnrss-group-alist)
+         (gnus-group-unsubscribe-group
+          (concat "nnrss:" title))
+         (nnrss-save-server-data nil))
+      (error "No feeds found for %s" url))))
+
+(defvar nnwarchive-type-definition)
+(defvar gnus-group-warchive-type-history nil)
+(defvar gnus-group-warchive-login-history nil)
+(defvar gnus-group-warchive-address-history nil)
+
+(defun gnus-group-make-warchive-group ()
+  "Create a nnwarchive group."
+  (interactive)
+  (require 'nnwarchive)
+  (let* ((group (gnus-read-group "Group name: "))
+        (default-type (or (car gnus-group-warchive-type-history)
+                          (symbol-name (caar nnwarchive-type-definition))))
+        (type
+         (gnus-string-or
+          (completing-read
+           (format "Warchive type (default %s): " default-type)
+           (mapcar (lambda (elem) (list (symbol-name (car elem))))
+                   nnwarchive-type-definition)
+           nil t nil 'gnus-group-warchive-type-history)
+          default-type))
+        (address (read-string "Warchive address: "
+                              nil 'gnus-group-warchive-address-history))
+        (default-login (or (car gnus-group-warchive-login-history)
+                           user-mail-address))
+        (login
+         (gnus-string-or
+          (read-string
+           (format "Warchive login (default %s): " user-mail-address)
+           default-login 'gnus-group-warchive-login-history)
+          user-mail-address))
+        (method
+         `(nnwarchive ,address
+                      (nnwarchive-type ,(intern type))
+                      (nnwarchive-login ,login))))
+    (gnus-group-make-group group method)))
+
 (defun gnus-group-make-archive-group (&optional all)
   "Create the (ding) Gnus archive group of the most recent articles.
 Given a prefix, create a full group."
@@ -2109,14 +2707,14 @@ mail messages or news articles in files that have numeric names."
     (while (or (not group) (gnus-gethash group gnus-newsrc-hashtb))
       (setq group
            (gnus-group-prefixed-name
-            (concat (file-name-as-directory (directory-file-name dir))
-                    ext)
+            (expand-file-name ext dir)
             '(nndir "")))
       (setq ext (format "<%d>" (setq i (1+ i)))))
     (gnus-group-make-group
      (gnus-group-real-name group)
      (list 'nndir (gnus-group-real-name group) (list 'nndir-directory dir)))))
 
+(defvar nnkiboze-score-file)
 (defun gnus-group-make-kiboze-group (group address scores)
   "Create an nnkiboze group.
 The user will be prompted for a name, a regexp to match groups, and
@@ -2134,15 +2732,20 @@ score file entries for articles to include in the group."
                                          "Match on header: " headers nil t))))
        (setq regexps nil)
        (while (not (equal "" (setq regexp (read-string
-                                           (format "Match on %s (string): "
+                                           (format "Match on %s (regexp): "
                                                    header)))))
          (push (list regexp nil nil 'r) regexps))
        (push (cons header regexps) scores))
       scores)))
   (gnus-group-make-group group "nnkiboze" address)
-  (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group))
-    (let (emacs-lisp-mode-hook)
-      (pp scores (current-buffer)))))
+  (let* ((nnkiboze-current-group group)
+        (score-file (car (nnkiboze-score-file "")))
+        (score-dir (file-name-directory score-file)))
+    (unless (file-exists-p score-dir)
+      (make-directory score-dir))
+    (with-temp-file score-file
+      (let (emacs-lisp-mode-hook)
+       (pp scores (current-buffer))))))
 
 (defun gnus-group-add-to-virtual (n vgroup)
   "Add the current group to a virtual group."
@@ -2194,6 +2797,63 @@ score file entries for articles to include in the group."
                       'summary 'group)))
       (error "Couldn't enter %s" dir))))
 
+(eval-and-compile
+  (autoload 'nnimap-expunge "nnimap")
+  (autoload 'nnimap-acl-get "nnimap")
+  (autoload 'nnimap-acl-edit "nnimap"))
+
+(defun gnus-group-nnimap-expunge (group)
+  "Expunge deleted articles in current nnimap GROUP."
+  (interactive (list (gnus-group-group-name)))
+  (let ((mailbox (gnus-group-real-name group)) method)
+    (unless group
+      (error "No group on current line"))
+    (unless (gnus-get-info group)
+      (error "Killed group; can't be edited"))
+    (unless (eq 'nnimap (car (setq method (gnus-find-method-for-group group))))
+      (error "%s is not an nnimap group" group))
+    (nnimap-expunge mailbox (cadr method))))
+
+(defun gnus-group-nnimap-edit-acl (group)
+  "Edit the Access Control List of current nnimap GROUP."
+  (interactive (list (gnus-group-group-name)))
+  (let ((mailbox (gnus-group-real-name group)) method acl)
+    (unless group
+      (error "No group on current line"))
+    (unless (gnus-get-info group)
+      (error "Killed group; can't be edited"))
+    (unless (eq (car (setq method (gnus-find-method-for-group group))) 'nnimap)
+      (error "%s is not an nnimap group" group))
+    (unless (setq acl (nnimap-acl-get mailbox (cadr method)))
+      (error "Server does not support ACL's"))
+    (gnus-edit-form acl (format "Editing the access control list for `%s'.
+
+   An access control list is a list of (identifier . rights) elements.
+
+   The identifier string specifies the corresponding user.  The
+   identifier \"anyone\" is reserved to refer to the universal identity.
+
+   Rights is a string listing a (possibly empty) set of alphanumeric
+   characters, each character listing a set of operations which is being
+   controlled.  Letters are reserved for ``standard'' rights, listed
+   below.  Digits are reserved for implementation or site defined rights.
+
+   l - lookup (mailbox is visible to LIST/LSUB commands)
+   r - read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
+       SEARCH, COPY from mailbox)
+   s - keep seen/unseen information across sessions (STORE \\SEEN flag)
+   w - write (STORE flags other than \\SEEN and \\DELETED)
+   i - insert (perform APPEND, COPY into mailbox)
+   p - post (send mail to submission address for mailbox,
+       not enforced by IMAP4 itself)
+   c - create and delete mailbox (CREATE new sub-mailboxes in any
+       implementation-defined hierarchy, RENAME or DELETE mailbox)
+   d - delete messages (STORE \\DELETED flag, perform EXPUNGE)
+   a - administer (perform SETACL)" group)
+                   `(lambda (form)
+                      (nnimap-acl-edit
+                       ,mailbox ',method ',acl form)))))
+
 ;; Group sorting commands
 ;; Suggested by Joe Hildebrand <hildjj@idaho.fuentez.com>.
 
@@ -2205,6 +2865,7 @@ If REVERSE (the prefix), reverse the sorting order."
   (interactive (list gnus-group-sort-function current-prefix-arg))
   (funcall gnus-group-sort-alist-function
           (gnus-make-sort-function func) reverse)
+  (gnus-group-unmark-all-groups)
   (gnus-group-list-groups)
   (gnus-dribble-touch))
 
@@ -2227,6 +2888,12 @@ If REVERSE, sort in reverse order."
   (interactive "P")
   (gnus-group-sort-groups 'gnus-group-sort-by-alphabet reverse))
 
+(defun gnus-group-sort-groups-by-real-name (&optional reverse)
+  "Sort the group buffer alphabetically by real (unprefixed) group name.
+If REVERSE, sort in reverse order."
+  (interactive "P")
+  (gnus-group-sort-groups 'gnus-group-sort-by-real-name reverse))
+
 (defun gnus-group-sort-groups-by-unread (&optional reverse)
   "Sort the group buffer by number of unread articles.
 If REVERSE, sort in reverse order."
@@ -2252,11 +2919,17 @@ If REVERSE, sort in reverse order."
   (gnus-group-sort-groups 'gnus-group-sort-by-rank reverse))
 
 (defun gnus-group-sort-groups-by-method (&optional reverse)
-  "Sort the group buffer alphabetically by backend name.
+  "Sort the group buffer alphabetically by back end name.
 If REVERSE, sort in reverse order."
   (interactive "P")
   (gnus-group-sort-groups 'gnus-group-sort-by-method reverse))
 
+(defun gnus-group-sort-groups-by-server (&optional reverse)
+  "Sort the group buffer alphabetically by server name.
+If REVERSE, sort in reverse order."
+  (interactive "P")
+  (gnus-group-sort-groups 'gnus-group-sort-by-server reverse))
+
 ;;; Selected group sorting.
 
 (defun gnus-group-sort-selected-groups (n func &optional reverse)
@@ -2265,7 +2938,9 @@ If REVERSE, sort in reverse order."
   (let ((groups (gnus-group-process-prefix n)))
     (funcall gnus-group-sort-selected-function
             groups (gnus-make-sort-function func) reverse)
-    (gnus-group-list-groups)))
+    (gnus-group-unmark-all-groups)
+    (gnus-group-list-groups)
+    (gnus-dribble-touch)))
 
 (defun gnus-group-sort-selected-flat (groups func reverse)
   (let (entries infos)
@@ -2285,46 +2960,59 @@ If REVERSE, sort in reverse order."
     ;; Go through all the infos and replace the old entries
     ;; with the new infos.
     (while infos
-      (setcar entries (pop infos))
+      (setcar (car entries) (pop infos))
       (pop entries))
     ;; Update the hashtable.
     (gnus-make-hashtable-from-newsrc-alist)))
 
-(defun gnus-group-sort-selected-groups-by-alphabet (&optional reverse)
+(defun gnus-group-sort-selected-groups-by-alphabet (&optional n reverse)
   "Sort the group buffer alphabetically by group name.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-alphabet reverse))
-
-(defun gnus-group-sort-selected-groups-by-unread (&optional reverse)
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-alphabet reverse))
+
+(defun gnus-group-sort-selected-groups-by-real-name (&optional n reverse)
+  "Sort the group buffer alphabetically by real group name.
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-real-name reverse))
+
+(defun gnus-group-sort-selected-groups-by-unread (&optional n reverse)
   "Sort the group buffer by number of unread articles.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-unread reverse))
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-unread reverse))
 
-(defun gnus-group-sort-selected-groups-by-level (&optional reverse)
+(defun gnus-group-sort-selected-groups-by-level (&optional n reverse)
   "Sort the group buffer by group level.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-level reverse))
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-level reverse))
 
-(defun gnus-group-sort-selected-groups-by-score (&optional reverse)
+(defun gnus-group-sort-selected-groups-by-score (&optional n reverse)
   "Sort the group buffer by group score.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-score reverse))
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-score reverse))
 
-(defun gnus-group-sort-selected-groups-by-rank (&optional reverse)
+(defun gnus-group-sort-selected-groups-by-rank (&optional n reverse)
   "Sort the group buffer by group rank.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-rank reverse))
-
-(defun gnus-group-sort-selected-groups-by-method (&optional reverse)
-  "Sort the group buffer alphabetically by backend name.
-If REVERSE, sort in reverse order."
-  (interactive "P")
-  (gnus-group-sort-selected-groups 'gnus-group-sort-by-method reverse))
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-rank reverse))
+
+(defun gnus-group-sort-selected-groups-by-method (&optional n reverse)
+  "Sort the group buffer alphabetically by back end name.
+Obeys the process/prefix convention.  If REVERSE (the symbolic prefix),
+sort in reverse order."
+  (interactive (gnus-interactive "P\ny"))
+  (gnus-group-sort-selected-groups n 'gnus-group-sort-by-method reverse))
 
 ;;; Sorting predicates.
 
@@ -2349,15 +3037,24 @@ If REVERSE, sort in reverse order."
   (< (gnus-info-level info1) (gnus-info-level info2)))
 
 (defun gnus-group-sort-by-method (info1 info2)
-  "Sort alphabetically by backend name."
-  (string< (symbol-name (car (gnus-find-method-for-group
-                             (gnus-info-group info1) info1)))
-          (symbol-name (car (gnus-find-method-for-group
-                             (gnus-info-group info2) info2)))))
+  "Sort alphabetically by back end name."
+  (string< (car (gnus-find-method-for-group
+                (gnus-info-group info1) info1))
+          (car (gnus-find-method-for-group
+                (gnus-info-group info2) info2))))
+
+(defun gnus-group-sort-by-server (info1 info2)
+  "Sort alphabetically by server name."
+  (string< (gnus-method-to-full-server-name
+           (gnus-find-method-for-group
+            (gnus-info-group info1) info1))
+          (gnus-method-to-full-server-name
+           (gnus-find-method-for-group
+            (gnus-info-group info2) info2))))
 
 (defun gnus-group-sort-by-score (info1 info2)
   "Sort by group score."
-  (< (gnus-info-score info1) (gnus-info-score info2)))
+  (> (gnus-info-score info1) (gnus-info-score info2)))
 
 (defun gnus-group-sort-by-rank (info1 info2)
   "Sort by level and score."
@@ -2390,20 +3087,29 @@ If REVERSE, sort in reverse order."
        (when (gnus-group-native-p (gnus-info-group info))
          (gnus-info-clear-data info)))
       (gnus-get-unread-articles)
-      (gnus-dribble-enter "")
+      (gnus-dribble-touch)
       (when (gnus-y-or-n-p
             "Move the cache away to avoid problems in the future? ")
        (call-interactively 'gnus-cache-move-cache)))))
 
 (defun gnus-info-clear-data (info)
   "Clear all marks and read ranges from INFO."
-  (let ((group (gnus-info-group info)))
+  (let ((group (gnus-info-group info))
+       action)
+    (dolist (el (gnus-info-marks info))
+      (push `(,(cdr el) add (,(car el))) action))
+    (push `(,(gnus-info-read info) add (read)) action)
     (gnus-undo-register
       `(progn
+        (gnus-request-set-mark ,group ',action)
         (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
         (gnus-info-set-read ',info ',(gnus-info-read info))
         (when (gnus-group-goto-group ,group)
+          (gnus-get-unread-articles-in-group ',info ',(gnus-active group) t)
           (gnus-group-update-group-line))))
+    (setq action (mapcar (lambda (el) (list (nth 0 el) 'del (nth 2 el)))
+                        action))
+    (gnus-request-set-mark group action)
     (gnus-info-set-read info nil)
     (when (gnus-info-marks info)
       (gnus-info-set-marks info nil))))
@@ -2411,7 +3117,7 @@ If REVERSE, sort in reverse order."
 ;; Group catching up.
 
 (defun gnus-group-catchup-current (&optional n all)
-  "Mark all articles not marked as unread in current newsgroup as read.
+  "Mark all unread articles in the current newsgroup as read.
 If prefix argument N is numeric, the next N newsgroups will be
 caught up.  If ALL is non-nil, marked articles will also be marked as
 read.  Cross references (Xref: header) of articles are ignored.
@@ -2419,7 +3125,8 @@ The number of newsgroups that this function was unable to catch
 up is returned."
   (interactive "P")
   (let ((groups (gnus-group-process-prefix n))
-       (ret 0))
+       (ret 0)
+       group)
     (unless groups (error "No groups selected"))
     (if (not
         (or (not gnus-interactive-catchup) ;Without confirmation?
@@ -2433,21 +3140,20 @@ up is returned."
                   (car groups)
                 (format "these %d groups" (length groups)))))))
        n
-      (while groups
+      (while (setq group (pop groups))
+       (gnus-group-remove-mark group)
        ;; Virtual groups have to be given special treatment.
-       (let ((method (gnus-find-method-for-group (car groups))))
+       (let ((method (gnus-find-method-for-group group)))
          (when (eq 'nnvirtual (car method))
            (nnvirtual-catchup-group
-            (gnus-group-real-name (car groups)) (nth 1 method) all)))
-       (gnus-group-remove-mark (car groups))
-       (if (>= (gnus-group-group-level) gnus-level-zombie)
+            (gnus-group-real-name group) (nth 1 method) all)))
+       (if (>= (gnus-group-level group) gnus-level-zombie)
            (gnus-message 2 "Dead groups can't be caught up")
          (if (prog1
-                 (gnus-group-goto-group (car groups))
-               (gnus-group-catchup (car groups) all))
+                 (gnus-group-goto-group group)
+               (gnus-group-catchup group all))
              (gnus-group-update-group-line)
-           (setq ret (1+ ret))))
-       (setq groups (cdr groups)))
+           (setq ret (1+ ret)))))
       (gnus-group-next-unread-group 1)
       ret)))
 
@@ -2463,32 +3169,38 @@ If ALL is non-nil, all articles are marked as read.
 The return value is the number of articles that were marked as read,
 or nil if no action could be taken."
   (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
-        (num (car entry)))
+        (num (car entry))
+        (marks (nth 3 (nth 2 entry)))
+        (unread (gnus-list-of-unread-articles group)))
+    ;; Remove entries for this group.
+    (nnmail-purge-split-history (gnus-group-real-name group))
     ;; Do the updating only if the newsgroup isn't killed.
     (if (not (numberp (car entry)))
        (gnus-message 1 "Can't catch up %s; non-active group" group)
+      (gnus-update-read-articles group nil)
+      (when all
+       ;; Nix out the lists of marks and dormants.
+       (gnus-request-set-mark group (list (list (cdr (assq 'tick marks))
+                                                'del '(tick))
+                                          (list (cdr (assq 'dormant marks))
+                                                'del '(dormant))))
+       (setq unread (gnus-uncompress-range
+                     (gnus-range-add (gnus-range-add
+                                      unread (cdr (assq 'dormant marks)))
+                                     (cdr (assq 'tick marks)))))
+       (gnus-add-marked-articles group 'tick nil nil 'force)
+       (gnus-add-marked-articles group 'dormant nil nil 'force))
       ;; Do auto-expirable marks if that's required.
       (when (gnus-group-auto-expirable-p group)
-       (gnus-add-marked-articles
-        group 'expire (gnus-list-of-unread-articles group))
-       (when all
-         (let ((marks (nth 3 (nth 2 entry))))
-           (gnus-add-marked-articles
-            group 'expire (gnus-uncompress-range (cdr (assq 'tick marks))))
-           (gnus-add-marked-articles
-            group 'expire (gnus-uncompress-range (cdr (assq 'tick marks)))))))
-      (when entry
-       (gnus-update-read-articles group nil)
-       ;; Also nix out the lists of marks and dormants.
-       (when all
-         (gnus-add-marked-articles group 'tick nil nil 'force)
-         (gnus-add-marked-articles group 'dormant nil nil 'force))
-       (let ((gnus-newsgroup-name group))
-         (gnus-run-hooks 'gnus-group-catchup-group-hook))
-       num))))
+       (gnus-add-marked-articles group 'expire unread)
+       (gnus-request-set-mark group (list (list unread 'add '(expire)))))
+      (let ((gnus-newsgroup-name group))
+       (gnus-run-hooks 'gnus-group-catchup-group-hook))
+      num)))
 
 (defun gnus-group-expire-articles (&optional n)
-  "Expire all expirable articles in the current newsgroup."
+  "Expire all expirable articles in the current newsgroup.
+Uses the process/prefix convention."
   (interactive "P")
   (let ((groups (gnus-group-process-prefix n))
        group)
@@ -2496,32 +3208,41 @@ or nil if no action could be taken."
       (error "No groups to expire"))
     (while (setq group (pop groups))
       (gnus-group-remove-mark group)
-      (when (gnus-check-backend-function 'request-expire-articles group)
-       (gnus-message 6 "Expiring articles in %s..." group)
-       (let* ((info (gnus-get-info group))
-              (expirable (if (gnus-group-total-expirable-p group)
-                             (cons nil (gnus-list-of-read-articles group))
-                           (assq 'expire (gnus-info-marks info))))
-              (expiry-wait (gnus-group-find-parameter group 'expiry-wait)))
-         (when expirable
-           (setcdr
-            expirable
-            (gnus-compress-sequence
-             (if expiry-wait
-                 ;; We set the expiry variables to the group
-                 ;; parameter.
-                 (let ((nnmail-expiry-wait-function nil)
-                       (nnmail-expiry-wait expiry-wait))
-                   (gnus-request-expire-articles
-                    (gnus-uncompress-sequence (cdr expirable)) group))
-               ;; Just expire using the normal expiry values.
-               (gnus-request-expire-articles
-                (gnus-uncompress-sequence (cdr expirable)) group))))
-           (gnus-close-group group))
-         (gnus-message 6 "Expiring articles in %s...done" group)))
+      (gnus-group-expire-articles-1 group)
       (gnus-dribble-touch)
       (gnus-group-position-point))))
 
+(defun gnus-group-expire-articles-1 (group)
+  (when (gnus-check-backend-function 'request-expire-articles group)
+    (gnus-message 6 "Expiring articles in %s..." group)
+    (let* ((info (gnus-get-info group))
+          (expirable (if (gnus-group-total-expirable-p group)
+                         (cons nil (gnus-list-of-read-articles group))
+                       (assq 'expire (gnus-info-marks info))))
+          (expiry-wait (gnus-group-find-parameter group 'expiry-wait))
+          (nnmail-expiry-target
+           (or (gnus-group-find-parameter group 'expiry-target)
+               nnmail-expiry-target)))
+      (when expirable
+       (gnus-check-group group)
+       (setcdr
+        expirable
+        (gnus-compress-sequence
+         (if expiry-wait
+             ;; We set the expiry variables to the group
+             ;; parameter.
+             (let ((nnmail-expiry-wait-function nil)
+                   (nnmail-expiry-wait expiry-wait))
+               (gnus-request-expire-articles
+                (gnus-uncompress-sequence (cdr expirable)) group))
+           ;; Just expire using the normal expiry values.
+           (gnus-request-expire-articles
+            (gnus-uncompress-sequence (cdr expirable)) group))))
+       (gnus-close-group group))
+      (gnus-message 6 "Expiring articles in %s...done" group)
+      ;; Return the list of un-expired articles.
+      (cdr expirable))))
+
 (defun gnus-group-expire-all-groups ()
   "Expire all expirable articles in all newsgroups."
   (interactive)
@@ -2538,17 +3259,20 @@ or nil if no action could be taken."
   (interactive
    (list
     current-prefix-arg
-    (string-to-int
-     (let ((s (read-string
-              (format "Level (default %s): "
-                      (or (gnus-group-group-level)
-                          gnus-level-default-subscribed)))))
-       (if (string-match "^\\s-*$" s)
-          (int-to-string (or (gnus-group-group-level)
-                             gnus-level-default-subscribed))
-        s)))))
+    (progn
+      (unless (gnus-group-process-prefix current-prefix-arg)
+       (error "No group on the current line"))
+      (string-to-int
+       (let ((s (read-string
+                (format "Level (default %s): "
+                        (or (gnus-group-group-level)
+                            gnus-level-default-subscribed)))))
+        (if (string-match "^\\s-*$" s)
+            (int-to-string (or (gnus-group-group-level)
+                               gnus-level-default-subscribed))
+          s))))))
   (unless (and (>= level 1) (<= level gnus-level-killed))
-    (error "Illegal level: %d" level))
+    (error "Invalid level: %d" level))
   (let ((groups (gnus-group-process-prefix n))
        group)
     (while (setq group (pop groups))
@@ -2575,33 +3299,29 @@ or nil if no action could be taken."
   "Toggle subscription of the current group.
 If given numerical prefix, toggle the N next groups."
   (interactive "P")
-  (let ((groups (gnus-group-process-prefix n))
-       group)
-    (while groups
-      (setq group (car groups)
-           groups (cdr groups))
-      (gnus-group-remove-mark group)
-      (gnus-group-unsubscribe-group
-       group
-       (cond
-       ((eq do-sub 'unsubscribe)
-        gnus-level-default-unsubscribed)
-       ((eq do-sub 'subscribe)
-        gnus-level-default-subscribed)
-       ((<= (gnus-group-group-level) gnus-level-subscribed)
-        gnus-level-default-unsubscribed)
-       (t
-        gnus-level-default-subscribed))
-       t)
-      (gnus-group-update-group-line))
-    (gnus-group-next-group 1)))
+  (dolist (group (gnus-group-process-prefix n))
+    (gnus-group-remove-mark group)
+    (gnus-group-unsubscribe-group
+     group
+     (cond
+      ((eq do-sub 'unsubscribe)
+       gnus-level-default-unsubscribed)
+      ((eq do-sub 'subscribe)
+       gnus-level-default-subscribed)
+      ((<= (gnus-group-group-level) gnus-level-subscribed)
+       gnus-level-default-unsubscribed)
+      (t
+       gnus-level-default-subscribed))
+     t)
+    (gnus-group-update-group-line))
+  (gnus-group-next-group 1))
 
 (defun gnus-group-unsubscribe-group (group &optional level silent)
   "Toggle subscription to GROUP.
 Killed newsgroups are subscribed.  If SILENT, don't try to update the
 group line."
   (interactive
-   (list (completing-read
+   (list (gnus-group-completing-read-group-name
          "Group: " gnus-active-hashtb nil
          (gnus-read-active-file-p)
          nil
@@ -2649,13 +3369,15 @@ N and the number of steps taken is returned."
     (gnus-group-yank-group)
     (gnus-group-position-point)))
 
-(defun gnus-group-kill-all-zombies ()
-  "Kill all zombie newsgroups."
-  (interactive)
-  (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list))
-  (setq gnus-zombie-list nil)
-  (gnus-dribble-touch)
-  (gnus-group-list-groups))
+(defun gnus-group-kill-all-zombies (&optional dummy)
+  "Kill all zombie newsgroups.
+The optional DUMMY should always be nil."
+  (interactive (list (not (gnus-yes-or-no-p "Really kill all zombies? "))))
+  (unless dummy
+    (setq gnus-killed-list (nconc gnus-zombie-list gnus-killed-list))
+    (setq gnus-zombie-list nil)
+    (gnus-dribble-touch)
+    (gnus-group-list-groups)))
 
 (defun gnus-group-kill-region (begin end)
   "Kill newsgroups in current region (excluding current point).
@@ -2704,41 +3426,40 @@ of groups killed."
            (push (cons (car entry) (nth 2 entry))
                  gnus-list-of-killed-groups))
          (gnus-group-change-level
-          (if entry entry group) gnus-level-killed (if entry nil level)))
+          (if entry entry group) gnus-level-killed (if entry nil level))
+         (message "Killed group %s" group))
       ;; If there are lots and lots of groups to be killed, we use
       ;; this thing instead.
-      (let (entry)
-       (setq groups (nreverse groups))
-       (while groups
-         (gnus-group-remove-mark (setq group (pop groups)))
-         (gnus-delete-line)
-         (push group gnus-killed-list)
-         (setq gnus-newsrc-alist
-               (delq (assoc group gnus-newsrc-alist)
-                     gnus-newsrc-alist))
-         (when gnus-group-change-level-function
-           (funcall gnus-group-change-level-function group gnus-level-killed 3))
-         (cond
-          ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
-           (push (cons (car entry) (nth 2 entry))
-                 gnus-list-of-killed-groups)
-           (setcdr (cdr entry) (cdddr entry)))
-          ((member group gnus-zombie-list)
-           (setq gnus-zombie-list (delete group gnus-zombie-list))))
-         ;; There may be more than one instance displayed.
-         (while (gnus-group-goto-group group)
-           (gnus-delete-line)))
-       (gnus-make-hashtable-from-newsrc-alist)))
+      (dolist (group (nreverse groups))
+       (gnus-group-remove-mark group)
+       (gnus-delete-line)
+       (push group gnus-killed-list)
+       (setq gnus-newsrc-alist
+             (delq (assoc group gnus-newsrc-alist)
+                   gnus-newsrc-alist))
+       (when gnus-group-change-level-function
+         (funcall gnus-group-change-level-function
+                  group gnus-level-killed 3))
+       (cond
+        ((setq entry (gnus-gethash group gnus-newsrc-hashtb))
+         (push (cons (car entry) (nth 2 entry))
+               gnus-list-of-killed-groups)
+         (setcdr (cdr entry) (cdddr entry)))
+        ((member group gnus-zombie-list)
+         (setq gnus-zombie-list (delete group gnus-zombie-list))))
+       ;; There may be more than one instance displayed.
+       (while (gnus-group-goto-group group)
+         (gnus-delete-line)))
+      (gnus-make-hashtable-from-newsrc-alist))
 
     (gnus-group-position-point)
     (if (< (length out) 2) (car out) (nreverse out))))
 
 (defun gnus-group-yank-group (&optional arg)
-  "Yank the last newsgroups killed with \\[gnus-group-kill-group],
-inserting it before the current newsgroup.  The numeric ARG specifies
-how many newsgroups are to be yanked.  The name of the newsgroup yanked
-is returned, or (if several groups are yanked) a list of yanked groups
-is returned."
+  "Yank the last newsgroups killed with \\[gnus-group-kill-group], inserting it before the current newsgroup.
+The numeric ARG specifies how many newsgroups are to be yanked.  The
+name of the newsgroup yanked is returned, or (if several groups are
+yanked) a list of yanked groups is returned."
   (interactive "p")
   (setq arg (or arg 1))
   (let (info group prev out)
@@ -2790,11 +3511,11 @@ is returned."
       (gnus-make-hashtable-from-newsrc-alist)
       (gnus-group-list-groups)))
    (t
-    (error "Can't kill; illegal level: %d" level))))
+    (error "Can't kill; invalid level: %d" level))))
 
 (defun gnus-group-list-all-groups (&optional arg)
   "List all newsgroups with level ARG or lower.
-Default is gnus-level-unsubscribed, which lists all subscribed and most
+Default is `gnus-level-unsubscribed', which lists all subscribed and most
 unsubscribed groups."
   (interactive "P")
   (gnus-group-list-groups (or arg gnus-level-unsubscribed) t))
@@ -2833,7 +3554,8 @@ entail asking the server for the groups."
   (interactive)
   ;; First we make sure that we have really read the active file.
   (unless (gnus-read-active-file-p)
-    (let ((gnus-read-active-file t))
+    (let ((gnus-read-active-file t)
+         (gnus-agent nil))             ; Trick the agent into ignoring the active file.
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
   (let ((groups
@@ -2851,10 +3573,12 @@ entail asking the server for the groups."
        group)
     (erase-buffer)
     (while groups
+      (setq group (pop groups))
       (gnus-add-text-properties
        (point) (prog1 (1+ (point))
                 (insert "       *: "
-                        (setq group (pop groups)) "\n"))
+                        (gnus-group-decoded-name group)
+                        "\n"))
        (list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
             'gnus-unread t
             'gnus-level (inline (gnus-group-level group)))))
@@ -2873,7 +3597,12 @@ If ARG is a number, it specifies which levels you are interested in
 re-scanning.  If ARG is non-nil and not a number, this will force
 \"hard\" re-reading of the active files from all servers."
   (interactive "P")
-  (let ((gnus-inhibit-demon t))
+  (require 'nnmail)
+  (let ((gnus-inhibit-demon t)
+       ;; Binding this variable will inhibit multiple fetchings
+       ;; of the same mail source.
+       (nnmail-fetched-sources (list t)))
+    (gnus-run-hooks 'gnus-get-top-new-news-hook)
     (gnus-run-hooks 'gnus-get-new-news-hook)
 
     ;; Read any slave files.
@@ -2903,7 +3632,10 @@ re-scanning.  If ARG is non-nil and not a number, this will force
        (gnus-get-unread-articles arg)))
     (gnus-run-hooks 'gnus-after-getting-new-news-hook)
     (gnus-group-list-groups (and (numberp arg)
-                                (max (car gnus-group-list-mode) arg)))))
+                                (max (car gnus-group-list-mode) arg))))
+  ;; Update modeline.
+  (when (and gnus-agent (not (interactive-p)))
+    (gnus-agent-toggle-plugged gnus-plugged)))
 
 (defun gnus-group-get-new-news-this-group (&optional n dont-scan)
   "Check for newly arrived news in the current group (and the N-1 next groups).
@@ -2914,17 +3646,25 @@ If N is negative, this group and the N-1 previous groups will be checked."
         (ret (if (numberp n) (- n (length groups)) 0))
         (beg (unless n
                (point)))
-        group)
+        group method
+        (gnus-inhibit-demon t)
+        ;; Binding this variable will inhibit multiple fetchings
+        ;; of the same mail source.
+        (nnmail-fetched-sources (list t)))
+    (gnus-run-hooks 'gnus-get-new-news-hook)
     (while (setq group (pop groups))
       (gnus-group-remove-mark group)
       ;; Bypass any previous denials from the server.
-      (gnus-remove-denial (gnus-find-method-for-group group))
+      (gnus-remove-denial (setq method (gnus-find-method-for-group group)))
       (if (gnus-activate-group group (if dont-scan nil 'scan))
          (progn
            (gnus-get-unread-articles-in-group
             (gnus-get-info group) (gnus-active group) t)
            (unless (gnus-virtual-group-p group)
              (gnus-close-group group))
+           (when gnus-agent
+             (gnus-agent-save-group-info
+              method (gnus-group-real-name group) (gnus-active group)))
            (gnus-group-update-group group))
        (if (eq (gnus-server-status (gnus-find-method-for-group group))
                'denied)
@@ -2946,8 +3686,8 @@ to use."
     (gnus-group-group-name)
     (when current-prefix-arg
       (completing-read
-       "Faq dir: " (and (listp gnus-group-faq-directory)
-                       (mapcar (lambda (file) (list file))
+       "FAQ dir: " (and (listp gnus-group-faq-directory)
+                       (mapcar #'list
                                gnus-group-faq-directory))))))
   (unless group
     (error "No group name given"))
@@ -2958,15 +3698,67 @@ to use."
     (while (and (not found)
                (setq dir (pop dirs)))
       (let ((name (gnus-group-real-name group)))
-       (while (string-match "\\." name)
-         (setq name (replace-match "/" t t name)))
-       (setq file (concat (file-name-as-directory dir) name)))
+       (setq file (expand-file-name name dir)))
       (if (not (file-exists-p file))
          (gnus-message 1 "No such file: %s" file)
        (let ((enable-local-variables nil))
          (find-file file)
          (setq found t))))))
 
+(defun gnus-group-fetch-charter (group)
+  "Fetch the charter for the current group.
+If given a prefix argument, prompt for a group."
+  (interactive
+   (list (or (when current-prefix-arg
+              (completing-read "Group: " gnus-active-hashtb))
+            (gnus-group-group-name)
+            gnus-newsgroup-name)))
+  (unless group
+    (error "No group name given"))
+  (require 'mm-url)
+  (condition-case nil (require 'url-http) (error nil))
+  (let ((name (mm-url-form-encode-xwfu (gnus-group-real-name group)))
+       url hierarchy)
+    (when (string-match "\\(^[^\\.]+\\)\\..*" name)
+      (setq hierarchy (match-string 1 name))
+      (if (and (setq url (cdr (assoc hierarchy gnus-group-charter-alist)))
+              (if (fboundp 'url-http-file-exists-p)
+                  (url-http-file-exists-p (eval url))
+                t))
+         (browse-url (eval url))
+       (setq url (concat "http://" hierarchy
+                         ".news-admin.org/charters/" name))
+       (if (and (fboundp 'url-http-file-exists-p)
+                (url-http-file-exists-p url))
+           (browse-url url)
+         (gnus-group-fetch-control group))))))
+
+(defun gnus-group-fetch-control (group)
+  "Fetch the archived control messages for the current group.
+If given a prefix argument, prompt for a group."
+  (interactive
+   (list (or (when current-prefix-arg
+              (completing-read "Group: " gnus-active-hashtb))
+            (gnus-group-group-name)
+            gnus-newsgroup-name)))
+  (unless group
+    (error "No group name given"))
+  (let ((name (gnus-group-real-name group))
+       hierarchy)
+    (when (string-match "\\(^[^\\.]+\\)\\..*" name)
+      (setq hierarchy (match-string 1 name))
+      (if gnus-group-fetch-control-use-browse-url
+         (browse-url (concat "ftp://ftp.isc.org/usenet/control/"
+                             hierarchy "/" name ".gz"))
+       (let ((enable-local-variables nil))
+         (gnus-group-read-ephemeral-group
+          group
+          `(nndoc ,group (nndoc-address
+                          ,(find-file-noselect
+                            (concat "/ftp@ftp.isc.org:/usenet/control/"
+                                    hierarchy "/" name ".gz")))
+                  (nndoc-article-type mbox)) t nil nil))))))
+
 (defun gnus-group-describe-group (force &optional group)
   "Display a description of the current newsgroup."
   (interactive (list current-prefix-arg (gnus-group-group-name)))
@@ -3003,8 +3795,12 @@ to use."
     (mapatoms
      (lambda (group)
        (setq b (point))
-       (insert (format "      *: %-20s %s\n" (symbol-name group)
-                      (symbol-value group)))
+       (let ((charset (gnus-group-name-charset nil (symbol-name group))))
+        (insert (format "      *: %-20s %s\n"
+                        (gnus-group-name-decode
+                         (symbol-name group) charset)
+                        (gnus-group-name-decode
+                         (symbol-value group) charset))))
        (gnus-add-text-properties
        b (1+ b) (list 'gnus-group group
                       'gnus-unread t 'gnus-marked nil
@@ -3025,6 +3821,7 @@ to use."
      (lambda (group)
        (and (symbol-name group)
            (string-match regexp (symbol-name group))
+           (symbol-value group)
            (push (symbol-name group) groups)))
      gnus-active-hashtb)
     ;; Also go through all descriptions that are known to Gnus.
@@ -3032,7 +3829,6 @@ to use."
       (mapatoms
        (lambda (group)
         (and (string-match regexp (symbol-value group))
-             (gnus-active (symbol-name group))
              (push (symbol-name group) groups)))
        gnus-description-hashtb))
     (if (not groups)
@@ -3040,23 +3836,25 @@ to use."
       ;; Print out all the groups.
       (save-excursion
        (pop-to-buffer "*Gnus Help*")
-       (buffer-disable-undo (current-buffer))
+       (buffer-disable-undo)
        (erase-buffer)
        (setq groups (sort groups 'string<))
        (while groups
          ;; Groups may be entered twice into the list of groups.
          (when (not (string= (car groups) prev))
-           (insert (setq prev (car groups)) "\n")
-           (when (and gnus-description-hashtb
-                      (setq des (gnus-gethash (car groups)
-                                              gnus-description-hashtb)))
-             (insert "  " des "\n")))
+           (setq prev (car groups))
+           (let ((charset (gnus-group-name-charset nil prev)))
+             (insert (gnus-group-name-decode prev charset) "\n")
+             (when (and gnus-description-hashtb
+                        (setq des (gnus-gethash (car groups)
+                                                gnus-description-hashtb)))
+               (insert "  " (gnus-group-name-decode des charset) "\n"))))
          (setq groups (cdr groups)))
        (goto-char (point-min))))
     (pop-to-buffer obuf)))
 
 (defun gnus-group-description-apropos (regexp)
-  "List all newsgroups that have names or descriptions that match a regexp."
+  "List all newsgroups that have names or descriptions that match REGEXP."
   (interactive "sGnus description apropos (regexp): ")
   (when (not (or gnus-description-hashtb
                 (gnus-read-all-descriptions-files)))
@@ -3077,8 +3875,8 @@ This command may read the active file."
   (when (and level
             (> (prefix-numeric-value level) gnus-level-killed))
     (gnus-get-killed-groups))
-  (gnus-group-prepare-flat
-   (or level gnus-level-subscribed) all (or lowest 1) regexp)
+  (funcall gnus-group-prepare-function
+          (or level gnus-level-subscribed) (and all t) (or lowest 1) regexp)
   (goto-char (point-min))
   (gnus-group-position-point))
 
@@ -3124,13 +3922,15 @@ group."
 
 (defun gnus-group-find-new-groups (&optional arg)
   "Search for new groups and add them.
-Each new group will be treated with `gnus-subscribe-newsgroup-method.'
-If ARG (the prefix), use the `ask-server' method to query
-the server for new groups."
-  (interactive "P")
-  (gnus-find-new-newsgroups arg)
+Each new group will be treated with `gnus-subscribe-newsgroup-method'.
+With 1 C-u, use the `ask-server' method to query the server for new
+groups.
+With 2 C-u's, use most complete method possible to query the server
+for new groups, and subscribe the new groups as zombies."
+  (interactive "p")
+  (gnus-find-new-newsgroups (or arg 1))
   (gnus-group-list-groups))
-  
+
 (defun gnus-group-edit-global-kill (&optional article group)
   "Edit the global kill file.
 If GROUP, edit that local kill file instead."
@@ -3153,23 +3953,28 @@ If GROUP, edit that local kill file instead."
   (interactive)
   (gnus-save-newsrc-file))
 
+(defvar gnus-backlog-articles)
+
 (defun gnus-group-suspend ()
   "Suspend the current Gnus session.
 In fact, cleanup buffers except for group mode buffer.
-The hook gnus-suspend-gnus-hook is called before actually suspending."
+The hook `gnus-suspend-gnus-hook' is called before actually suspending."
   (interactive)
   (gnus-run-hooks 'gnus-suspend-gnus-hook)
+  (gnus-offer-save-summaries)
   ;; Kill Gnus buffers except for group mode buffer.
-  (let* ((group-buf (get-buffer gnus-group-buffer))
-        ;; Do this on a separate list in case the user does a ^G before we finish
-        (gnus-buffer-list
-         (delete group-buf (delete gnus-dribble-buffer
-                                   (append gnus-buffer-list nil)))))
-    (while gnus-buffer-list
-      (gnus-kill-buffer (pop gnus-buffer-list)))
+  (let ((group-buf (get-buffer gnus-group-buffer)))
+    (mapcar (lambda (buf)
+             (unless (or (member buf (list group-buf gnus-dribble-buffer))
+                         (progn
+                           (save-excursion
+                             (set-buffer buf)
+                             (eq major-mode 'message-mode))))
+               (gnus-kill-buffer buf)))
+           (gnus-buffers))
+    (setq gnus-backlog-articles nil)
     (gnus-kill-gnus-frames)
     (when group-buf
-      (setq gnus-buffer-list (list group-buf))
       (bury-buffer group-buf)
       (delete-windows-on group-buf t))))
 
@@ -3214,6 +4019,12 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting."
                     (file-name-nondirectory gnus-current-startup-file))))
     (gnus-run-hooks 'gnus-exit-gnus-hook)
     (gnus-configure-windows 'group t)
+    (when (and (gnus-buffer-live-p gnus-dribble-buffer)
+              (not (zerop (save-excursion
+                            (set-buffer gnus-dribble-buffer)
+                            (buffer-size)))))
+      (gnus-dribble-enter
+       ";;; Gnus was exited on purpose without saving the .newsrc files."))
     (gnus-dribble-save)
     (gnus-close-backends)
     (gnus-clear-system)
@@ -3234,10 +4045,10 @@ If not, METHOD should be a list where the first element is the method
 and the second element is the address."
   (interactive
    (list (let ((how (completing-read
-                    "Which backend: "
+                    "Which back end: "
                     (append gnus-valid-select-methods gnus-server-alist)
                     nil t (cons "nntp" 0) 'gnus-method-history)))
-          ;; We either got a backend name or a virtual server name.
+          ;; We either got a back end name or a virtual server name.
           ;; If the first, we also need an address.
           (if (assoc how gnus-valid-select-methods)
               (list (intern how)
@@ -3251,59 +4062,61 @@ and the second element is the address."
   (gnus-browse-foreign-server method))
 
 (defun gnus-group-set-info (info &optional method-only-group part)
-  (let* ((entry (gnus-gethash
-                (or method-only-group (gnus-info-group info))
-                gnus-newsrc-hashtb))
-        (part-info info)
-        (info (if method-only-group (nth 2 entry) info))
-        method)
-    (when method-only-group
+  (when (or info part)
+    (let* ((entry (gnus-gethash
+                  (or method-only-group (gnus-info-group info))
+                  gnus-newsrc-hashtb))
+          (part-info info)
+          (info (if method-only-group (nth 2 entry) info))
+          method)
+      (when method-only-group
+       (unless entry
+         (error "Trying to change non-existent group %s" method-only-group))
+       ;; We have received parts of the actual group info - either the
+       ;; select method or the group parameters.        We first check
+       ;; whether we have to extend the info, and if so, do that.
+       (let ((len (length info))
+             (total (if (eq part 'method) 5 6)))
+         (when (< len total)
+           (setcdr (nthcdr (1- len) info)
+                   (make-list (- total len) nil)))
+         ;; Then we enter the new info.
+         (setcar (nthcdr (1- total) info) part-info)))
       (unless entry
-       (error "Trying to change non-existent group %s" method-only-group))
-      ;; We have received parts of the actual group info - either the
-      ;; select method or the group parameters.         We first check
-      ;; whether we have to extend the info, and if so, do that.
-      (let ((len (length info))
-           (total (if (eq part 'method) 5 6)))
-       (when (< len total)
-         (setcdr (nthcdr (1- len) info)
-                 (make-list (- total len) nil)))
-       ;; Then we enter the new info.
-       (setcar (nthcdr (1- total) info) part-info)))
-    (unless entry
-      ;; This is a new group, so we just create it.
-      (save-excursion
-       (set-buffer gnus-group-buffer)
-       (setq method (gnus-info-method info))
-       (when (gnus-server-equal method "native")
-         (setq method nil))
+       ;; This is a new group, so we just create it.
        (save-excursion
          (set-buffer gnus-group-buffer)
-         (if method
-             ;; It's a foreign group...
-             (gnus-group-make-group
-              (gnus-group-real-name (gnus-info-group info))
-              (if (stringp method) method
-                (prin1-to-string (car method)))
-              (and (consp method)
-                   (nth 1 (gnus-info-method info))))
-           ;; It's a native group.
-           (gnus-group-make-group (gnus-info-group info))))
-       (gnus-message 6 "Note: New group created")
-       (setq entry
-             (gnus-gethash (gnus-group-prefixed-name
-                            (gnus-group-real-name (gnus-info-group info))
-                            (or (gnus-info-method info) gnus-select-method))
-                           gnus-newsrc-hashtb))))
-    ;; Whether it was a new group or not, we now have the entry, so we
-    ;; can do the update.
-    (if entry
-       (progn
-         (setcar (nthcdr 2 entry) info)
-         (when (and (not (eq (car entry) t))
-                    (gnus-active (gnus-info-group info)))
-           (setcar entry (length (gnus-list-of-unread-articles (car info))))))
-      (error "No such group: %s" (gnus-info-group info)))))
+         (setq method (gnus-info-method info))
+         (when (gnus-server-equal method "native")
+           (setq method nil))
+         (save-excursion
+           (set-buffer gnus-group-buffer)
+           (if method
+               ;; It's a foreign group...
+               (gnus-group-make-group
+                (gnus-group-real-name (gnus-info-group info))
+                (if (stringp method) method
+                  (prin1-to-string (car method)))
+                (and (consp method)
+                     (nth 1 (gnus-info-method info))))
+             ;; It's a native group.
+             (gnus-group-make-group (gnus-info-group info))))
+         (gnus-message 6 "Note: New group created")
+         (setq entry
+               (gnus-gethash (gnus-group-prefixed-name
+                              (gnus-group-real-name (gnus-info-group info))
+                              (or (gnus-info-method info) gnus-select-method))
+                             gnus-newsrc-hashtb))))
+      ;; Whether it was a new group or not, we now have the entry, so we
+      ;; can do the update.
+      (if entry
+         (progn
+           (setcar (nthcdr 2 entry) info)
+           (when (and (not (eq (car entry) t))
+                      (gnus-active (gnus-info-group info)))
+             (setcar entry (length
+                            (gnus-list-of-unread-articles (car info))))))
+       (error "No such group: %s" (gnus-info-group info))))))
 
 (defun gnus-group-set-method-info (group select-method)
   (gnus-group-set-info select-method group 'method))
@@ -3313,10 +4126,9 @@ and the second element is the address."
 
 (defun gnus-add-marked-articles (group type articles &optional info force)
   ;; Add ARTICLES of TYPE to the info of GROUP.
-  ;; If INFO is non-nil, use that info.         If FORCE is non-nil, don't
+  ;; If INFO is non-nil, use that info.  If FORCE is non-nil, don't
   ;; add, but replace marked articles of TYPE with ARTICLES.
   (let ((info (or info (gnus-get-info group)))
-       (uncompressed '(score bookmark killed))
        marked m)
     (or (not info)
        (and (not (setq marked (nthcdr 3 info)))
@@ -3332,12 +4144,22 @@ and the second element is the address."
        (if force
            (if (null articles)
                (setcar (nthcdr 3 info)
-                       (delq (assq type (car marked)) (car marked)))
+                       (gnus-delete-alist type (car marked)))
              (setcdr m (gnus-compress-sequence articles t)))
          (setcdr m (gnus-compress-sequence
                     (sort (nconc (gnus-uncompress-range (cdr m))
                                  (copy-sequence articles)) '<) t))))))
 
+(defun gnus-add-mark (group mark article)
+  "Mark ARTICLE in GROUP with MARK, whether the group is displayed or not."
+  (let ((buffer (gnus-summary-buffer-name group)))
+    (if (gnus-buffer-live-p buffer)
+       (save-excursion
+         (set-buffer (get-buffer buffer))
+         (gnus-summary-add-mark article mark))
+      (gnus-add-marked-articles group (cdr (assq mark gnus-article-mark-lists))
+                               (list article)))))
+
 ;;;
 ;;; Group timestamps
 ;;;
@@ -3353,13 +4175,13 @@ or `gnus-group-catchup-group-hook'."
 
 (defsubst gnus-group-timestamp (group)
   "Return the timestamp for GROUP."
-  (gnus-group-get-parameter group 'timestamp))
+  (gnus-group-get-parameter group 'timestamp t))
 
 (defun gnus-group-timestamp-delta (group)
   "Return the offset in seconds from the timestamp for GROUP to the current time, as a floating point number."
   (let* ((time (or (gnus-group-timestamp group)
-                 (list 0 0)))
-         (delta (gnus-time-minus (current-time) time)))
+                  (list 0 0)))
+        (delta (subtract-time (current-time) time)))
     (+ (* (nth 0 delta) 65536.0)
        (nth 1 delta))))
 
@@ -3370,6 +4192,133 @@ or `gnus-group-catchup-group-hook'."
        ""
       (gnus-time-iso8601 time))))
 
+(defun gnus-group-list-cached (level &optional lowest)
+  "List all groups with cached articles.
+If the prefix LEVEL is non-nil, it should be a number that says which
+level to cut off listing groups.
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
+  (interactive "P")
+  (when level
+    (setq level (prefix-numeric-value level)))
+  (when (or (not level) (>= level gnus-level-zombie))
+    (gnus-cache-open))
+  (funcall gnus-group-prepare-function
+          (or level gnus-level-subscribed)
+          #'(lambda (info)
+              (let ((marks (gnus-info-marks info)))
+                (assq 'cache marks)))
+          lowest
+          #'(lambda (group)
+              (or (gnus-gethash group
+                                gnus-cache-active-hashtb)
+                  ;; Cache active file might use "."
+                  ;; instead of ":".
+                  (gnus-gethash
+                   (mapconcat 'identity
+                              (split-string group ":")
+                              ".")
+                   gnus-cache-active-hashtb))))
+  (goto-char (point-min))
+  (gnus-group-position-point))
+
+(defun gnus-group-list-dormant (level &optional lowest)
+  "List all groups with dormant articles.
+If the prefix LEVEL is non-nil, it should be a number that says which
+level to cut off listing groups.
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
+  (interactive "P")
+  (when level
+    (setq level (prefix-numeric-value level)))
+  (when (or (not level) (>= level gnus-level-zombie))
+    (gnus-cache-open))
+  (funcall gnus-group-prepare-function
+          (or level gnus-level-subscribed)
+          #'(lambda (info)
+              (let ((marks (gnus-info-marks info)))
+                (assq 'dormant marks)))
+          lowest
+          'ignore)
+  (goto-char (point-min))
+  (gnus-group-position-point))
+
+(defun gnus-group-listed-groups ()
+  "Return a list of listed groups."
+  (let (point groups)
+    (goto-char (point-min))
+    (while (setq point (text-property-not-all (point) (point-max)
+                                             'gnus-group nil))
+      (goto-char point)
+      (push (symbol-name (get-text-property point 'gnus-group)) groups)
+      (forward-char 1))
+    groups))
+
+(defun gnus-group-list-plus (&optional args)
+  "List groups plus the current selection."
+  (interactive "P")
+  (let ((gnus-group-listed-groups (gnus-group-listed-groups))
+       (gnus-group-list-mode gnus-group-list-mode) ;; Save it.
+       func)
+    (push last-command-event unread-command-events)
+    (if (featurep 'xemacs)
+       (push (make-event 'key-press '(key ?A)) unread-command-events)
+      (push ?A unread-command-events))
+    (let (gnus-pick-mode keys)
+      (setq keys (if (featurep 'xemacs)
+                    (events-to-keys (read-key-sequence nil))
+                  (read-key-sequence nil)))
+      (setq func (lookup-key (current-local-map) keys)))
+    (if (or (not func)
+           (numberp func))
+       (ding)
+      (call-interactively func))))
+
+(defun gnus-group-list-flush (&optional args)
+  "Flush groups from the current selection."
+  (interactive "P")
+  (let ((gnus-group-list-option 'flush))
+    (gnus-group-list-plus args)))
+
+(defun gnus-group-list-limit (&optional args)
+  "List groups limited within the current selection."
+  (interactive "P")
+  (let ((gnus-group-list-option 'limit))
+    (gnus-group-list-plus args)))
+
+(defun gnus-group-mark-article-read (group article)
+  "Mark ARTICLE read."
+  (let ((buffer (gnus-summary-buffer-name group))
+       (mark gnus-read-mark)
+       active n)
+    (if (get-buffer buffer)
+       (with-current-buffer buffer
+         (setq active gnus-newsgroup-active)
+         (gnus-activate-group group)
+         (when gnus-newsgroup-prepared
+           (when (and gnus-newsgroup-auto-expire
+                      (memq mark gnus-auto-expirable-marks))
+             (setq mark gnus-expirable-mark))
+           (setq mark (gnus-request-update-mark
+                       group article mark))
+           (gnus-mark-article-as-read article mark)
+           (setq gnus-newsgroup-active (gnus-active group))
+           (when active
+             (setq n (1+ (cdr active)))
+             (while (<= n (cdr gnus-newsgroup-active))
+               (unless (eq n article)
+                 (push n gnus-newsgroup-unselected))
+               (setq n (1+ n)))
+             (setq gnus-newsgroup-unselected
+                   (nreverse gnus-newsgroup-unselected)))))
+      (gnus-activate-group group)
+      (gnus-group-make-articles-read group (list article))
+      (when (gnus-group-auto-expirable-p group)
+       (gnus-add-marked-articles
+        group 'expire (list article))))))
+
 (provide 'gnus-group)
 
 ;;; gnus-group.el ends here
diff --git a/lisp/gnus-i18n.el b/lisp/gnus-i18n.el
new file mode 100644 (file)
index 0000000..c71b1e2
--- /dev/null
@@ -0,0 +1,95 @@
+;;; gnus-i18n.el --- Internationalization for Gnus
+
+;; Copyright (C) 1996,1997 Free Software Foundation, Inc.
+
+;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Created: 1997/11/27
+;; Keywords: internationalization, news, mail
+
+;; This file is not part of GNU Emacs yet.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+;;; @ newsgroup default charset
+;;;
+
+(defvar gnus-newsgroup-default-charset-alist
+  '(("\\(^\\|:\\)\\(fj\\|tnn\\|japan\\)\\."    . iso-2022-jp-2)
+    ("\\(^\\|:\\)han\\."                       . euc-kr)
+    ("\\(^\\|:\\)relcom\\."                    . koi8-r)
+    ("\\(^\\|:\\)alt\\.chinese\\.text\\.big5"  . cn-big5)
+    ("\\(^\\|:\\)hk\\(star\\)?\\."             . cn-big5)
+    ("\\(^\\|:\\)tw\\."                                . cn-big5)
+    ("\\(^\\|:\\)alt\\.chinese"                        . hz-gb-2312)
+    )
+  "Alist of newsgroup patterns vs. corresponding default MIME charset.
+Each element looks like (REGEXP . SYMBOL).  REGEXP is pattern for
+newsgroup name.  SYMBOL is MIME charset or coding-system.")
+
+(defun gnus-set-newsgroup-default-charset (newsgroup charset)
+  "Set CHARSET for the NEWSGROUP as default MIME charset."
+  (let* ((ng-regexp (concat "^" (regexp-quote newsgroup) "\\($\\|\\.\\)"))
+        (pair (assoc ng-regexp gnus-newsgroup-default-charset-alist))
+        )
+    (if pair
+       (setcdr pair charset)
+      (setq gnus-newsgroup-default-charset-alist
+           (cons (cons ng-regexp charset)
+                 gnus-newsgroup-default-charset-alist))
+      )))
+
+
+;;; @ localization
+;;;
+
+(defun gnus-set-summary-default-charset ()
+  "Set up `default-mime-charset' of summary buffer.
+It is specified by variable `gnus-newsgroup-default-charset-alist'
+\(cf. function `gnus-set-newsgroup-default-charset')."
+  (if (buffer-live-p gnus-summary-buffer)
+      (let ((charset
+            (catch 'found
+              (let ((group
+                     (save-excursion
+                       (set-buffer gnus-summary-buffer)
+                       gnus-newsgroup-name))
+                    (alist gnus-newsgroup-default-charset-alist))
+                (while alist
+                  (let ((pair (car alist)))
+                    (if (string-match (car pair) group)
+                        (throw 'found (cdr pair))
+                      ))
+                  (setq alist (cdr alist)))
+                ))))
+       (if charset
+           (progn
+             (save-excursion
+               (set-buffer gnus-summary-buffer)
+               (make-local-variable 'default-mime-charset)
+               (setq default-mime-charset charset))
+             (make-local-variable 'default-mime-charset)
+             (setq default-mime-charset charset))
+         (kill-local-variable 'default-mime-charset)))))
+
+
+;;; @ end
+;;;
+
+(provide 'gnus-i18n)
+
+;;; gnus-i18n.el ends here
index 58f93a7..49c9ed6 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-int.el --- backend interface functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 (eval-when-compile (require 'cl))
 
 (require 'gnus)
+(require 'message)
+(require 'gnus-range)
+
+(autoload 'gnus-agent-expire "gnus-agent")
+(autoload 'gnus-agent-read-servers-validate-native "gnus-agent")
 
 (defcustom gnus-open-server-hook nil
   "Hook called just before opening connection to the news server."
   :group 'gnus-start
   :type 'hook)
 
+(defcustom gnus-server-unopen-status nil
+  "The default status if the server is not able to open.
+If the server is covered by Gnus agent, the possible values are
+`denied', set the server denied; `offline', set the server offline;
+nil, ask user.  If the server is not covered by Gnus agent, set the
+server denied."
+  :group 'gnus-start
+  :type '(choice (const :tag "Ask" nil)
+                (const :tag "Deny server" denied)
+                (const :tag "Unplug Agent" offline)))
+
+(defvar gnus-internal-registry-spool-current-method nil
+  "The current method, for the registry.")
+
 ;;;
 ;;; Server Communication
 ;;;
@@ -69,8 +90,7 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
                           (list 'nnmh-directory
                                 (file-name-as-directory
                                  (expand-file-name
-                                  (concat "~/" (substring
-                                                gnus-nntp-server 1)))))
+                                  (substring gnus-nntp-server 1) "~/")))
                           (list 'nnmh-get-new-mail nil)))
                    (t
                     (list 'nntp gnus-nntp-server)))))
@@ -87,10 +107,23 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
        (require 'nntp)))
       (setq gnus-current-select-method gnus-select-method)
       (gnus-run-hooks 'gnus-open-server-hook)
+
+      ;; Partially validate agent covered methods now that the
+      ;; gnus-select-method is known.
+
+      (if gnus-agent
+          ;; NOTE: This is here for one purpose only.  By validating
+          ;; the current select method, it converts the old 5.10.3,
+          ;; and earlier, format to the current format.  That enables
+          ;; the agent code within gnus-open-server to function
+          ;; correctly.
+          (gnus-agent-read-servers-validate-native gnus-select-method))
+
       (or
        ;; gnus-open-server-hook might have opened it
        (gnus-server-opened gnus-select-method)
        (gnus-open-server gnus-select-method)
+       gnus-batch-mode
        (gnus-y-or-n-p
        (format
         "%s (%s) open error: '%s'.  Continue? "
@@ -109,7 +142,8 @@ If CONFIRM is non-nil, the user will be asked for an NNTP server."
   "Check whether the connection to METHOD is down.
 If METHOD is nil, use `gnus-select-method'.
 If it is down, start it up (again)."
-  (let ((method (or method gnus-select-method)))
+  (let ((method (or method gnus-select-method))
+       result)
     ;; Transform virtual server names into select methods.
     (when (stringp method)
       (setq method (gnus-server-to-method method)))
@@ -123,9 +157,15 @@ If it is down, start it up (again)."
                        (format " on %s" (nth 1 method)))))
       (gnus-run-hooks 'gnus-open-server-hook)
       (prog1
-         (gnus-open-server method)
+         (condition-case ()
+             (setq result (gnus-open-server method))
+           (quit (message "Quit gnus-check-server")
+                 nil))
        (unless silent
-         (message ""))))))
+         (gnus-message 5 "Opening %s server%s...%s" (car method)
+                       (if (equal (nth 1 method) "") ""
+                         (format " on %s" (nth 1 method)))
+                       (if result "done" "failed")))))))
 
 (defun gnus-get-function (method function &optional noerror)
   "Return a function symbol based on METHOD and FUNCTION."
@@ -134,18 +174,28 @@ If it is down, start it up (again)."
     (error "Attempted use of a nil select method"))
   (when (stringp method)
     (setq method (gnus-server-to-method method)))
-  (let ((func (intern (format "%s-%s" (if gnus-agent
-                                         (gnus-agent-get-function method)
-                                       (car method))
-                             function))))
-    ;; If the functions isn't bound, we require the backend in
-    ;; question.
+  ;; Check cache of constructed names.
+  (let* ((method-sym (if gnus-agent
+                        (gnus-agent-get-function method)
+                      (car method)))
+        (method-fns (get method-sym 'gnus-method-functions))
+        (func (let ((method-fnlist-elt (assq function method-fns)))
+                (unless method-fnlist-elt
+                  (setq method-fnlist-elt
+                        (cons function
+                              (intern (format "%s-%s" method-sym function))))
+                  (put method-sym 'gnus-method-functions
+                       (cons method-fnlist-elt method-fns)))
+                (cdr method-fnlist-elt))))
+    ;; Maybe complain if there is no function.
     (unless (fboundp func)
+      (unless (car method)
+       (error "Trying to require a method that doesn't exist"))
       (require (car method))
-      (when (and (not (fboundp func))
-                (not noerror))
-       ;; This backend doesn't implement this function.
-       (error "No such function: %s" func)))
+      (when (not (fboundp func))
+       (if noerror
+           (setq func nil)
+         (error "No such function: %s" func))))
     func))
 
 \f
@@ -164,18 +214,66 @@ If it is down, start it up (again)."
          (gnus-message 1 "Denied server")
          nil)
       ;; Open the server.
-      (let ((result
-            (funcall (gnus-get-function gnus-command-method 'open-server)
-                     (nth 1 gnus-command-method)
-                     (nthcdr 2 gnus-command-method))))
+      (let* ((open-server-function (gnus-get-function gnus-command-method 'open-server))
+             (result
+             (condition-case err
+                 (funcall open-server-function
+                          (nth 1 gnus-command-method)
+                          (nthcdr 2 gnus-command-method))
+               (error
+                (gnus-message 1 (format
+                                 "Unable to open server due to: %s"
+                                 (error-message-string err)))
+                nil)
+               (quit
+                (gnus-message 1 "Quit trying to open server")
+                nil)))
+            open-offline)
        ;; If this hasn't been opened before, we add it to the list.
        (unless elem
          (setq elem (list gnus-command-method nil)
                gnus-opened-servers (cons elem gnus-opened-servers)))
        ;; Set the status of this server.
-       (setcar (cdr elem) (if result 'ok 'denied))
-       ;; Return the result from the "open" call.
-       result))))
+        (setcar (cdr elem)
+                (cond (result
+                       (if (eq open-server-function #'nnagent-open-server)
+                           ;; The agent's backend has a "special" status
+                           'offline
+                         'ok))
+                      ((and gnus-agent
+                            (gnus-agent-method-p gnus-command-method))
+                       (cond (gnus-server-unopen-status
+                              ;; Set the server's status to the unopen
+                              ;; status.  If that status is offline,
+                              ;; recurse to open the agent's backend.
+                              (setq open-offline (eq gnus-server-unopen-status 'offline))
+                              gnus-server-unopen-status)
+                             ((gnus-y-or-n-p
+                               (format "Unable to open %s:%s, go offline? "
+                                       (car gnus-command-method)
+                                       (cadr gnus-command-method)))
+                              (setq open-offline t)
+                              'offline)
+                             (t
+                              ;; This agentized server was still denied
+                              'denied)))
+                      (t
+                       ;; This unagentized server must be denied
+                       'denied)))
+
+        ;; NOTE: I MUST set the server's status to offline before this
+        ;; recursive call as this status will drive the
+        ;; gnus-get-function (called above) to return the agent's
+        ;; backend.
+        (if open-offline
+            ;; Recursively open this offline server to perform the
+            ;; open-server function of the agent's backend.
+            (let ((gnus-server-unopen-status 'denied))
+              ;; Bind gnus-server-unopen-status to avoid recursively
+              ;; prompting with "go offline?".  This is only a concern
+              ;; when the agent's backend fails to open the server.
+              (gnus-open-server gnus-command-method))
+          result)))))
 
 (defun gnus-close-server (gnus-command-method)
   "Close the connection to GNUS-COMMAND-METHOD."
@@ -208,15 +306,17 @@ If it is down, start it up (again)."
 
 (defun gnus-server-opened (gnus-command-method)
   "Check whether a connection to GNUS-COMMAND-METHOD has been opened."
-  (when (stringp gnus-command-method)
-    (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
-  (funcall (inline (gnus-get-function gnus-command-method 'server-opened))
-          (nth 1 gnus-command-method)))
+  (unless (eq (gnus-server-status gnus-command-method)
+             'denied)
+    (when (stringp gnus-command-method)
+      (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
+    (funcall (inline (gnus-get-function gnus-command-method 'server-opened))
+            (nth 1 gnus-command-method))))
 
 (defun gnus-status-message (gnus-command-method)
   "Return the status message from GNUS-COMMAND-METHOD.
-If GNUS-COMMAND-METHOD is a string, it is interpreted as a group name.   The method
-this group uses will be queried."
+If GNUS-COMMAND-METHOD is a string, it is interpreted as a group
+name.  The method this group uses will be queried."
   (let ((gnus-command-method
         (if (stringp gnus-command-method)
             (gnus-find-method-for-group gnus-command-method)
@@ -258,6 +358,14 @@ this group uses will be queried."
       (funcall (gnus-get-function gnus-command-method func)
               (gnus-group-real-name group) (nth 1 gnus-command-method)))))
 
+(defun gnus-request-group-articles (group)
+  "Request a list of existing articles in GROUP."
+  (let ((gnus-command-method (gnus-find-method-for-group group))
+       (func 'request-group-articles))
+    (when (gnus-check-backend-function func group)
+      (funcall (gnus-get-function gnus-command-method func)
+              (gnus-group-real-name group) (nth 1 gnus-command-method)))))
+
 (defun gnus-close-group (group)
   "Request the GROUP be closed."
   (let ((gnus-command-method (inline (gnus-find-method-for-group group))))
@@ -268,11 +376,16 @@ this group uses will be queried."
   "Request headers for ARTICLES in GROUP.
 If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
   (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (if (and gnus-use-cache (numberp (car articles)))
-       (gnus-cache-retrieve-headers articles group fetch-old)
+    (cond
+     ((and gnus-use-cache (numberp (car articles)))
+      (gnus-cache-retrieve-headers articles group fetch-old))
+     ((and gnus-agent (gnus-online gnus-command-method)
+          (gnus-agent-method-p gnus-command-method))
+      (gnus-agent-retrieve-headers articles group fetch-old))
+     (t
       (funcall (gnus-get-function gnus-command-method 'retrieve-headers)
               articles (gnus-group-real-name group)
-              (nth 1 gnus-command-method) fetch-old))))
+              (nth 1 gnus-command-method) fetch-old)))))
 
 (defun gnus-retrieve-articles (articles group)
   "Request ARTICLES in GROUP."
@@ -297,8 +410,18 @@ If FETCH-OLD, retrieve all headers (or some subset thereof) in the group."
       (funcall (gnus-get-function gnus-command-method 'request-type)
               (gnus-group-real-name group) article))))
 
+(defun gnus-request-set-mark (group action)
+  "Set marks on articles in the back end."
+  (let ((gnus-command-method (gnus-find-method-for-group group)))
+    (if (not (gnus-check-backend-function
+             'request-set-mark (car gnus-command-method)))
+       action
+      (funcall (gnus-get-function gnus-command-method 'request-set-mark)
+              (gnus-group-real-name group) action
+              (nth 1 gnus-command-method)))))
+
 (defun gnus-request-update-mark (group article mark)
-  "Return the type (`post' or `mail') of GROUP (and ARTICLE)."
+  "Allow the back end to change the mark the user tries to put on an article."
   (let ((gnus-command-method (gnus-find-method-for-group group)))
     (if (not (gnus-check-backend-function
              'request-update-mark (car gnus-command-method)))
@@ -327,6 +450,10 @@ If BUFFER, insert the article in that group."
           (gnus-cache-request-article article group))
       (setq res (cons group article)
            clean-up t))
+     ;; Check the agent cache.
+     ((gnus-agent-request-article article group)
+      (setq res (cons group article)
+           clean-up t))
      ;; Use `head' function.
      ((fboundp head)
       (setq res (funcall head article (gnus-group-real-name group)
@@ -346,10 +473,35 @@ If BUFFER, insert the article in that group."
 
 (defun gnus-request-body (article group)
   "Request the body of ARTICLE in GROUP."
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function gnus-command-method 'request-body)
-            article (gnus-group-real-name group)
-            (nth 1 gnus-command-method))))
+  (let* ((gnus-command-method (gnus-find-method-for-group group))
+        (head (gnus-get-function gnus-command-method 'request-body t))
+        res clean-up)
+    (cond
+     ;; Check the cache.
+     ((and gnus-use-cache
+          (numberp article)
+          (gnus-cache-request-article article group))
+      (setq res (cons group article)
+           clean-up t))
+     ;; Check the agent cache.
+     ((gnus-agent-request-article article group)
+      (setq res (cons group article)
+           clean-up t))
+     ;; Use `head' function.
+     ((fboundp head)
+      (setq res (funcall head article (gnus-group-real-name group)
+                        (nth 1 gnus-command-method))))
+     ;; Use `article' function.
+     (t
+      (setq res (gnus-request-article article group)
+           clean-up t)))
+    (when clean-up
+      (save-excursion
+       (set-buffer nntp-server-buffer)
+       (goto-char (point-min))
+       (when (search-forward "\n\n" nil t)
+         (delete-region (point-min) (1- (point))))))
+    res))
 
 (defun gnus-request-post (gnus-command-method)
   "Post the current buffer using GNUS-COMMAND-METHOD."
@@ -361,13 +513,16 @@ If BUFFER, insert the article in that 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)))
+       (progn
+         (setq gnus-internal-registry-spool-current-method 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."
@@ -375,24 +530,51 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
     (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
   (when (gnus-check-backend-function
         'request-update-info (car gnus-command-method))
-    (funcall (gnus-get-function gnus-command-method 'request-update-info)
-            (gnus-group-real-name (gnus-info-group info))
-            info (nth 1 gnus-command-method))))
+    (let ((group (gnus-info-group info)))
+      (and (funcall (gnus-get-function gnus-command-method
+                                      'request-update-info)
+                   (gnus-group-real-name group)
+                   info (nth 1 gnus-command-method))
+          ;; If the minimum article number is greater than 1, then all
+          ;; smaller article numbers are known not to exist; we'll
+          ;; artificially add those to the 'read range.
+          (let* ((active (gnus-active group))
+                 (min (car active)))
+            (when (> min 1)
+              (let* ((range (if (= min 2) 1 (cons 1 (1- min))))
+                     (read (gnus-info-read info))
+                     (new-read (gnus-range-add read (list range))))
+                (gnus-info-set-read info new-read)))
+            info)))))
 
 (defun gnus-request-expire-articles (articles group &optional force)
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function gnus-command-method 'request-expire-articles)
-            articles (gnus-group-real-name group) (nth 1 gnus-command-method)
-            force)))
-
-(defun gnus-request-move-article
-  (article group server accept-function &optional last)
-  (let ((gnus-command-method (gnus-find-method-for-group group)))
-    (funcall (gnus-get-function gnus-command-method 'request-move-article)
-            article (gnus-group-real-name group)
-            (nth 1 gnus-command-method) accept-function last)))
-
-(defun gnus-request-accept-article (group &optional gnus-command-method last)
+  (let* ((gnus-command-method (gnus-find-method-for-group group))
+        (not-deleted
+         (funcall
+          (gnus-get-function gnus-command-method 'request-expire-articles)
+          articles (gnus-group-real-name group) (nth 1 gnus-command-method)
+          force)))
+    (when (and gnus-agent
+              (gnus-agent-method-p gnus-command-method))
+      (let ((expired-articles (gnus-sorted-difference articles not-deleted)))
+        (when expired-articles
+          (gnus-agent-expire expired-articles group 'force))))
+    not-deleted))
+
+(defun gnus-request-move-article (article group server accept-function
+                                         &optional last)
+  (let* ((gnus-command-method (gnus-find-method-for-group group))
+        (result (funcall (gnus-get-function gnus-command-method
+                                            'request-move-article)
+                         article (gnus-group-real-name group)
+                         (nth 1 gnus-command-method) accept-function last)))
+    (when (and result gnus-agent
+              (gnus-agent-method-p gnus-command-method))
+      (gnus-agent-expire (list article) group 'force))
+    result))
+
+(defun gnus-request-accept-article (group &optional gnus-command-method last
+                                         no-encode)
   ;; Make sure there's a newline at the end of the article.
   (when (stringp gnus-command-method)
     (setq gnus-command-method (gnus-server-to-method gnus-command-method)))
@@ -402,14 +584,14 @@ If GROUP is nil, all groups on GNUS-COMMAND-METHOD are scanned."
   (goto-char (point-max))
   (unless (bolp)
     (insert "\n"))
-  (let ((func (car (or gnus-command-method
-                      (gnus-find-method-for-group group)))))
-    (funcall (intern (format "%s-request-accept-article" func))
+  (let ((gnus-command-method (or gnus-command-method
+                                (gnus-find-method-for-group group))))
+    (funcall (gnus-get-function gnus-command-method 'request-accept-article)
             (if (stringp group) (gnus-group-real-name group) group)
             (cadr gnus-command-method)
             last)))
 
-(defun gnus-request-replace-article (article group buffer)
+(defun gnus-request-replace-article (article group buffer &optional no-encode)
   (let ((func (car (gnus-group-name-to-method group))))
     (funcall (intern (format "%s-request-replace-article" func))
             article (gnus-group-real-name group) buffer)))
index 9773710..cf95f9f 100644 (file)
@@ -1,8 +1,9 @@
 ;;; gnus-kill.el --- kill commands for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -49,7 +50,8 @@
   :type 'boolean)
 
 (defcustom gnus-winconf-kill-file nil
-  "What does this do, Lars?"
+  "What does this do, Lars?
+I don't know, Per."
   :group 'gnus-score-kill
   :type 'sexp)
 
@@ -355,16 +357,16 @@ If NEWSGROUP is nil, return the global kill file instead."
 (defun gnus-apply-kill-file-unless-scored ()
   "Apply .KILL file, unless a .SCORE file for the same newsgroup exists."
   (cond ((file-exists-p (gnus-score-file-name gnus-newsgroup-name))
-         ;; Ignores global KILL.
-         (when (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name))
+        ;; Ignores global KILL.
+        (when (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name))
           (gnus-message 3 "Note: Ignoring %s.KILL; preferring .SCORE"
                         gnus-newsgroup-name))
-         0)
-        ((or (file-exists-p (gnus-newsgroup-kill-file nil))
-             (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name)))
-         (gnus-apply-kill-file-internal))
-        (t
-         0)))
+        0)
+       ((or (file-exists-p (gnus-newsgroup-kill-file nil))
+            (file-exists-p (gnus-newsgroup-kill-file gnus-newsgroup-name)))
+        (gnus-apply-kill-file-internal))
+       (t
+        0)))
 
 (defun gnus-apply-kill-file-internal ()
   "Apply a kill file to the current newsgroup.
@@ -396,7 +398,7 @@ Returns the number of articles marked as read."
                          gnus-newsgroup-kill-headers))
                  (setq headers (cdr headers))))
              (setq files nil))
-         (setq files (cdr files)))))
+         (setq files (cdr files)))))
     (if (not gnus-newsgroup-kill-headers)
        ()
       (save-window-excursion
@@ -406,7 +408,6 @@ Returns the number of articles marked as read."
                ()
              (gnus-message 6 "Processing kill file %s..." (car kill-files))
              (find-file (car kill-files))
-             (gnus-add-current-to-buffer-list)
              (goto-char (point-min))
 
              (if (consp (ignore-errors (read (current-buffer))))
@@ -427,16 +428,6 @@ Returns the number of articles marked as read."
        0))))
 
 ;; Parse a Gnus killfile.
-(defun gnus-score-insert-help (string alist idx)
-  (save-excursion
-    (pop-to-buffer "*Score Help*")
-    (buffer-disable-undo (current-buffer))
-    (erase-buffer)
-    (insert string ":\n\n")
-    (while alist
-      (insert (format " %c: %s\n" (caar alist) (nth idx (car alist))))
-      (setq alist (cdr alist)))))
-
 (defun gnus-kill-parse-gnus-kill-file ()
   (goto-char (point-min))
   (gnus-kill-file-mode)
@@ -445,7 +436,7 @@ Returns the number of articles marked as read."
             (setq beg (point))
             (setq form (ignore-errors (read (current-buffer)))))
       (unless (listp form)
-       (error "Illegal kill entry (possibly rn kill file?): %s" form))
+       (error "Invalid kill entry (possibly rn kill file?): %s" form))
       (if (or (eq (car form) 'gnus-kill)
              (eq (car form) 'gnus-raise)
              (eq (car form) 'gnus-lower))
@@ -469,9 +460,9 @@ Returns the number of articles marked as read."
           (?h . "")
           (?f . "from")
           (?: . "subject")))
-       (com-to-com
-        '((?m . " ")
-          (?j . "X")))
+       ;;(com-to-com
+       ;; '((?m . " ")
+       ;;   (?j . "X")))
        pattern modifier commands)
     (while (not (eobp))
       (if (not (looking-at "[ \t]*/\\([^/]*\\)/\\([ahfcH]\\)?:\\([a-z=:]*\\)"))
@@ -522,10 +513,10 @@ COMMAND must be a lisp expression or a string representing a key sequence."
          (if (listp kill-list)
              ;; It is a list.
              (if (not (consp (cdr kill-list)))
-                 ;; It's on the form (regexp . date).
+                 ;; It's of the form (regexp . date).
                  (if (zerop (gnus-execute field (car kill-list)
                                           command nil (not all)))
-                     (when (> (gnus-days-between date (cdr kill-list))
+                     (when (> (days-between date (cdr kill-list))
                               gnus-kill-expiry-days)
                        (setq regexp nil))
                    (setcdr kill-list date))
@@ -536,7 +527,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                        (setq kdate (cdr kill))
                        (if (zerop (gnus-execute
                                    field (car kill) command nil (not all)))
-                           (when (> (gnus-days-between date kdate)
+                           (when (> (days-between date kdate)
                                     gnus-kill-expiry-days)
                              ;; Time limit has been exceeded, so we
                              ;; remove the match.
@@ -566,8 +557,8 @@ COMMAND must be a lisp expression or a string representing a key sequence."
               (not (consp (cdadr (nth 2 object))))))
       (concat "\n" (gnus-prin1-to-string object))
     (save-excursion
-      (set-buffer (get-buffer-create "*Gnus PP*"))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (gnus-get-buffer-create "*Gnus PP*"))
+      (buffer-disable-undo)
       (erase-buffer)
       (insert (format "\n(%S %S\n  '(" (nth 0 object) (nth 1 object)))
       (let ((klist (cadr (nth 2 object)))
@@ -587,7 +578,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
        (insert "\n  t"))
       (insert ")")
       (prog1
-         (buffer-substring (point-min) (point-max))
+         (buffer-string)
        (kill-buffer (current-buffer))))))
 
 (defun gnus-execute-1 (function regexp form header)
@@ -607,7 +598,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                     (setq did-kill (string-match regexp value)))
                   (cond ((stringp form) ;Keyboard macro.
                          (execute-kbd-macro form))
-                        ((gnus-functionp form)
+                        ((functionp form)
                          (funcall form))
                         (t
                          (eval form)))))
@@ -626,7 +617,7 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                    (setq did-kill (re-search-forward regexp nil t)))
              (cond ((stringp form)     ;Keyboard macro.
                     (execute-kbd-macro form))
-                   ((gnus-functionp form)
+                   ((functionp form)
                     (funcall form))
                    (t
                     (eval form)))))))
@@ -640,18 +631,30 @@ If optional 2nd argument UNREAD is non-nil, articles which are
 marked as read or ticked are ignored."
   (save-excursion
     (let ((killed-no 0)
-         function article header)
+         function article header extras)
       (cond
        ;; Search body.
        ((or (null field)
            (string-equal field ""))
        (setq function nil))
        ;; Get access function of header field.
-       ((fboundp
-        (setq function
-              (intern-soft
-               (concat "mail-header-" (downcase field)))))
-       (setq function `(lambda (h) (,function h))))
+       ((cond ((fboundp
+               (setq function
+                     (intern-soft
+                      (concat "mail-header-" (downcase field)))))
+              (setq function `(lambda (h) (,function h))))
+             ((when (setq extras
+                          (member (downcase field)
+                                  (mapcar (lambda (header)
+                                            (downcase (symbol-name header)))
+                                          gnus-extra-headers)))
+                (setq function
+                      `(lambda (h)
+                         (gnus-extra-header
+                          (quote ,(nth (- (length gnus-extra-headers)
+                                          (length extras))
+                                       gnus-extra-headers))
+                          h)))))))
        ;; Signal error.
        (t
        (error "Unknown header field: \"%s\"" field)))
@@ -684,6 +687,7 @@ Usage: emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score"
                   (mapconcat 'identity command-line-args-left " "))))
         (gnus-expert-user t)
         (nnmail-spool-file nil)
+        (mail-sources nil)
         (gnus-use-dribble-file nil)
         (gnus-batch-mode t)
         info group newsrc entry
@@ -703,7 +707,8 @@ Usage: emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score"
                 (and (car entry)
                      (or (eq (car entry) t)
                          (not (zerop (car entry))))))
-       (gnus-summary-read-group group nil t nil t)
+       (ignore-errors
+         (gnus-summary-read-group group nil t nil t))
        (when (eq (current-buffer) (get-buffer gnus-summary-buffer))
          (gnus-summary-exit))))
     ;; Exit Emacs.
diff --git a/lisp/gnus-load.el b/lisp/gnus-load.el
deleted file mode 100644 (file)
index 978f272..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-;;; gnus-load.el --- automatically extracted custom dependencies
-;;
-;;; Code:
-
-(put 'nnmail 'custom-loads '("nnmail"))
-(put 'gnus-article-emphasis 'custom-loads '("gnus-art"))
-(put 'gnus-article-headers 'custom-loads '("gnus-sum" "gnus-art"))
-(put 'nnmail-procmail 'custom-loads '("nnmail"))
-(put 'gnus-score-kill 'custom-loads '("gnus-kill"))
-(put 'gnus-visual 'custom-loads '("smiley" "gnus" "gnus-picon" "gnus-art" "earcon"))
-(put 'gnus-score-expire 'custom-loads '("gnus-score" "gnus-kill"))
-(put 'gnus-summary-maneuvering 'custom-loads '("gnus-sum"))
-(put 'gnus-start 'custom-loads '("gnus" "gnus-util" "gnus-start" "gnus-int" "gnus-group"))
-(put 'gnus-extract-view 'custom-loads '("gnus-uu" "gnus-sum"))
-(put 'gnus-various 'custom-loads '("gnus-sum"))
-(put 'gnus-article-washing 'custom-loads '("gnus-art"))
-(put 'gnus-score-files 'custom-loads '("gnus-score"))
-(put 'message-news 'custom-loads '("message"))
-(put 'gnus-thread 'custom-loads '("gnus-sum"))
-(put 'languages 'custom-loads '("cus-edit"))
-(put 'development 'custom-loads '("cus-edit"))
-(put 'gnus-treading 'custom-loads '("gnus-sum"))
-(put 'nnmail-various 'custom-loads '("nnmail"))
-(put 'extensions 'custom-loads '("wid-edit"))
-(put 'message-various 'custom-loads '("message"))
-(put 'gnus-summary-exit 'custom-loads '("gnus-sum"))
-(put 'news 'custom-loads '("message" "gnus"))
-(put 'gnus 'custom-loads '("nnmail" "gnus" "gnus-win" "gnus-uu" "gnus-eform" "gnus-dup" "gnus-demon" "gnus-cache" "gnus-async" "gnus-art"))
-(put 'gnus-summary-visual 'custom-loads '("gnus-sum"))
-(put 'gnus-group-listing 'custom-loads '("gnus-group"))
-(put 'gnus-score 'custom-loads '("gnus" "gnus-nocem"))
-(put 'gnus-group-select 'custom-loads '("gnus-sum"))
-(put 'message-buffers 'custom-loads '("message"))
-(put 'gnus-threading 'custom-loads '("gnus-sum"))
-(put 'gnus-score-decay 'custom-loads '("gnus-score"))
-(put 'help 'custom-loads '("cus-edit"))
-(put 'gnus-nocem 'custom-loads '("gnus-nocem"))
-(put 'gnus-cite 'custom-loads '("gnus-cite"))
-(put 'gnus-demon 'custom-loads '("gnus-demon"))
-(put 'gnus-message 'custom-loads '("message"))
-(put 'gnus-score-default 'custom-loads '("gnus-sum" "gnus-score"))
-(put 'nnmail-duplicate 'custom-loads '("nnmail"))
-(put 'message-interface 'custom-loads '("message"))
-(put 'nnmail-files 'custom-loads '("nnmail"))
-(put 'gnus-edit-form 'custom-loads '("gnus-eform"))
-(put 'emacs 'custom-loads '("cus-edit"))
-(put 'gnus-summary-mail 'custom-loads '("gnus-sum"))
-(put 'gnus-topic 'custom-loads '("gnus-topic"))
-(put 'wp 'custom-loads '("cus-edit"))
-(put 'gnus-summary-choose 'custom-loads '("gnus-sum"))
-(put 'widget-browse 'custom-loads '("wid-browse"))
-(put 'external 'custom-loads '("cus-edit"))
-(put 'message-headers 'custom-loads '("message"))
-(put 'message-forwarding 'custom-loads '("message"))
-(put 'message-faces 'custom-loads '("message"))
-(put 'environment 'custom-loads '("cus-edit"))
-(put 'gnus-article-mime 'custom-loads '("gnus-sum" "gnus-art"))
-(put 'gnus-duplicate 'custom-loads '("gnus-dup"))
-(put 'nnmail-retrieve 'custom-loads '("nnmail"))
-(put 'widgets 'custom-loads '("wid-edit" "wid-browse"))
-(put 'earcon 'custom-loads '("earcon"))
-(put 'hypermedia 'custom-loads '("wid-edit"))
-(put 'gnus-group-levels 'custom-loads '("gnus-group"))
-(put 'gnus-summary-format 'custom-loads '("gnus-sum"))
-(put 'gnus-files 'custom-loads '("nnmail" "gnus"))
-(put 'gnus-windows 'custom-loads '("gnus-win"))
-(put 'gnus-article-buttons 'custom-loads '("gnus-art"))
-(put 'gnus-summary 'custom-loads '("gnus" "gnus-sum"))
-(put 'gnus-article-hiding 'custom-loads '("gnus-sum" "gnus-art"))
-(put 'gnus-group 'custom-loads '("gnus" "gnus-topic"))
-(put 'gnus-article-various 'custom-loads '("gnus-sum" "gnus-art"))
-(put 'gnus-summary-marks 'custom-loads '("gnus-sum"))
-(put 'gnus-article-saving 'custom-loads '("gnus-art"))
-(put 'nnmail-expire 'custom-loads '("nnmail"))
-(put 'message-mail 'custom-loads '("message"))
-(put 'faces 'custom-loads '("wid-edit" "cus-edit" "message" "gnus"))
-(put 'gnus-summary-various 'custom-loads '("gnus-sum"))
-(put 'applications 'custom-loads '("cus-edit"))
-(put 'gnus-extract-archive 'custom-loads '("gnus-uu"))
-(put 'message 'custom-loads '("message"))
-(put 'message-sending 'custom-loads '("message"))
-(put 'editing 'custom-loads '("cus-edit"))
-(put 'gnus-score-adapt 'custom-loads '("gnus-score"))
-(put 'message-insertion 'custom-loads '("message"))
-(put 'gnus-extract-post 'custom-loads '("gnus-uu"))
-(put 'mail 'custom-loads '("message" "gnus"))
-(put 'gnus-summary-sort 'custom-loads '("gnus-sum"))
-(put 'customize 'custom-loads '("wid-edit" "custom" "cus-face" "cus-edit"))
-(put 'nnmail-split 'custom-loads '("nnmail"))
-(put 'gnus-asynchronous 'custom-loads '("gnus-async"))
-(put 'gnus-article-highlight 'custom-loads '("gnus-art"))
-(put 'gnus-extract 'custom-loads '("gnus-uu"))
-(put 'gnus-article 'custom-loads '("gnus-cite" "gnus-art"))
-(put 'gnus-group-foreign 'custom-loads '("gnus-group"))
-(put 'programming 'custom-loads '("cus-edit"))
-(put 'nnmail-prepare 'custom-loads '("nnmail"))
-(put 'picons 'custom-loads '("gnus-picon"))
-(put 'gnus-article-signature 'custom-loads '("gnus-art"))
-(put 'gnus-group-various 'custom-loads '("gnus-group"))
-
-(provide 'gnus-load)
-
-;;; gnus-load.el ends here
index 8405e19..06c46fb 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-logic.el --- advanced scoring code for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 (defconst gnus-advanced-index
   ;; Name to index alist.
-  '(("number" 0 gnus-advanced-integer)
-    ("subject" 1 gnus-advanced-string)
-    ("from" 2 gnus-advanced-string)
-    ("date" 3 gnus-advanced-date)
-    ("message-id" 4 gnus-advanced-string)
-    ("references" 5 gnus-advanced-string)
-    ("chars" 6 gnus-advanced-integer)
-    ("lines" 7 gnus-advanced-integer)
-    ("xref" 8 gnus-advanced-string)
+  `(("number"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'location)
+     gnus-advanced-integer)
+    ("subject"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'subject)
+     gnus-advanced-string)
+    ("from"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'from)
+     gnus-advanced-string)
+    ("date"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'date)
+     gnus-advanced-date)
+    ("message-id"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'id)
+     gnus-advanced-string)
+    ("references"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'references)
+     gnus-advanced-string)
+    ("chars"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'chars)
+     gnus-advanced-integer)
+    ("lines"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'lines)
+     gnus-advanced-integer)
+    ("xref"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity) 'xref)
+     gnus-advanced-string)
     ("head" nil gnus-advanced-body)
     ("body" nil gnus-advanced-body)
     ("all" nil gnus-advanced-body)))
 
 (defun gnus-score-advanced (rule &optional trace)
   "Apply advanced scoring RULE to all the articles in the current group."
-  (let ((headers gnus-newsgroup-headers)
-       gnus-advanced-headers score)
-    (while (setq gnus-advanced-headers (pop headers))
-      (when (gnus-advanced-score-rule (car rule))
-       ;; This rule was successful, so we add the score to
-       ;; this article.
+  (let (new-score score multiple)
+    (dolist (gnus-advanced-headers gnus-newsgroup-headers)
+      (when (setq multiple (gnus-advanced-score-rule (car rule)))
+       (setq new-score (or (nth 1 rule)
+                           gnus-score-interactive-default-score))
+       (when (numberp multiple)
+         (setq new-score (* multiple new-score)))
+       ;; This rule was successful, so we add the score to this
+       ;; article.
        (if (setq score (assq (mail-header-number gnus-advanced-headers)
                              gnus-newsgroup-scored))
            (setcdr score
-                   (+ (cdr score)
-                      (or (nth 1 rule)
-                          gnus-score-interactive-default-score)))
+                   (+ (cdr score) new-score))
          (push (cons (mail-header-number gnus-advanced-headers)
-                     (or (nth 1 rule)
-                         gnus-score-interactive-default-score))
+                     new-score)
                gnus-newsgroup-scored)
          (when trace
            (push (cons "A file" rule)
+                 ;; Must be synced with `gnus-score-edit-file-at-point'.
                  gnus-score-trace)))))))
 
 (defun gnus-advanced-score-rule (rule)
                  ;; 1- type redirection.
                  (string-to-number
                   (substring (symbol-name type)
-                             (match-beginning 0) (match-end 0)))
+                             (match-beginning 1) (match-end 1)))
                ;; ^^^ type redirection.
                (length (symbol-name type))))))
        (when gnus-advanced-headers
       (error "Unknown advanced score type: %s" rule)))))
 
 (defun gnus-advanced-score-article (rule)
-  ;; `rule' is a semi-normal score rule, so we find out
-  ;; what function that's supposed to do the actual
-  ;; processing.
+  ;; `rule' is a semi-normal score rule, so we find out what function
+  ;; that's supposed to do the actual processing.
   (let* ((header (car rule))
         (func (assoc (downcase header) gnus-advanced-index)))
     (if (not func)
   (let* ((type (or type 's))
         (case-fold-search (not (eq (downcase (symbol-name type))
                                    (symbol-name type))))
-        (header (aref gnus-advanced-headers index)))
+        (header (or (aref gnus-advanced-headers index) "")))
     (cond
      ((memq type '(r R regexp Regexp))
       (string-match match header))
 (defun gnus-advanced-integer (index match type)
   (if (not (memq type '(< > <= >= =)))
       (error "No such integer score type: %s" type)
-    (funcall type match (or (aref gnus-advanced-headers index) 0))))
+    (funcall type (or (aref gnus-advanced-headers index) 0) match)))
 
 (defun gnus-advanced-date (index match type)
-  (let ((date (encode-time (parse-time-string
-                           (aref gnus-advanced-headers index))))
-       (match (encode-time (parse-time-string match))))
+  (let ((date (apply 'encode-time (parse-time-string
+                                  (aref gnus-advanced-headers index))))
+       (match (apply 'encode-time (parse-time-string match))))
     (cond
      ((eq type 'at)
       (equal date match))
      ((eq type 'before)
-      (gnus-time-less match date))
+      (time-less-p match date))
      ((eq type 'after)
-      (gnus-time-less date match))
+      (time-less-p date match))
      (t
       (error "No such date score type: %s" type)))))
 
                                'gnus-request-body)
                               (t 'gnus-request-article)))
           ofunc article)
-      ;; Not all backends support partial fetching.  In that case,
-      ;; we just fetch the entire article.
+      ;; Not all backends support partial fetching.  In that case, we
+      ;; just fetch the entire article.
       (unless (gnus-check-backend-function
               (intern (concat "request-" header))
               gnus-newsgroup-name)
       (when (funcall request-func article gnus-newsgroup-name)
        (goto-char (point-min))
        ;; If just parts of the article is to be searched and the
-       ;; backend didn't support partial fetching, we just narrow
-       ;; to the relevant parts.
+       ;; backend didn't support partial fetching, we just narrow to
+       ;; the relevant parts.
        (when ofunc
          (if (eq ofunc 'gnus-request-head)
              (narrow-to-region
                      ((memq type '(s S string String))
                       'search-forward)
                      (t
-                      (error "Illegal match type: %s" type)))))
+                      (error "Invalid match type: %s" type)))))
          (goto-char (point-min))
          (prog1
              (funcall search-func match nil t)
 
 (provide 'gnus-logic)
 
-;;; gnus-logic.el ends here.
+;;; gnus-logic.el ends here
diff --git a/lisp/gnus-mailcap.el b/lisp/gnus-mailcap.el
new file mode 100644 (file)
index 0000000..232b019
--- /dev/null
@@ -0,0 +1,988 @@
+;;; mailcap.el --- MIME media types configuration
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;       Free Software Foundation, Inc.
+
+;; Author: William M. Perry <wmperry@aventail.com>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news, mail, multimedia
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Provides configuration of MIME media types from directly from Lisp
+;; and via the usual mailcap mechanism (RFC 1524).  Deals with
+;; mime.types similarly.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'mail-parse)
+(require 'mm-util)
+
+(defgroup mailcap nil
+  "Definition of viewers for MIME types."
+  :version "21.1"
+  :group 'mime)
+
+(defvar mailcap-parse-args-syntax-table
+  (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
+    (modify-syntax-entry ?' "\"" table)
+    (modify-syntax-entry ?` "\"" table)
+    (modify-syntax-entry ?{ "(" table)
+    (modify-syntax-entry ?} ")" table)
+    table)
+  "A syntax table for parsing SGML attributes.")
+
+(eval-and-compile
+  (when (featurep 'xemacs)
+    (condition-case nil
+       (require 'lpr)
+      (error nil))))
+
+(defvar mailcap-print-command
+  (mapconcat 'identity
+            (cons (if (boundp 'lpr-command)
+                      lpr-command
+                    "lpr")
+                  (when (boundp 'lpr-switches)
+                    (if (stringp lpr-switches)
+                        (list lpr-switches)
+                      lpr-switches)))
+            " ")
+  "Shell command (including switches) used to print Postscript files.")
+
+;; Postpone using defcustom for this as it's so big and we essentially
+;; have to have two copies of the data around then.  Perhaps just
+;; customize the Lisp viewers and rely on the normal configuration
+;; files for the rest?  -- fx
+(defvar mailcap-mime-data
+  `(("application"
+     ("vnd.ms-excel"
+      (viewer . "gnumeric %s")
+      (test   . (getenv "DISPLAY"))
+      (type . "application/vnd.ms-excel"))
+     ("x-x509-ca-cert"
+      (viewer . ssl-view-site-cert)
+      (test . (fboundp 'ssl-view-site-cert))
+      (type . "application/x-x509-ca-cert"))
+     ("x-x509-user-cert"
+      (viewer . ssl-view-user-cert)
+      (test . (fboundp 'ssl-view-user-cert))
+      (type . "application/x-x509-user-cert"))
+     ("octet-stream"
+      (viewer . mailcap-save-binary-file)
+      (non-viewer . t)
+      (type . "application/octet-stream"))
+     ("dvi"
+      (viewer . "xdvi -safer %s")
+      (test   . (eq window-system 'x))
+      ("needsx11")
+      (type   . "application/dvi")
+      ("print" . "dvips -qRP %s"))
+     ("dvi"
+      (viewer . "dvitty %s")
+      (test   . (not (getenv "DISPLAY")))
+      (type   . "application/dvi")
+      ("print" . "dvips -qRP %s"))
+     ("emacs-lisp"
+      (viewer . mailcap-maybe-eval)
+      (type   . "application/emacs-lisp"))
+     ("x-emacs-lisp"
+      (viewer . mailcap-maybe-eval)
+      (type   . "application/x-emacs-lisp"))
+     ("x-tar"
+      (viewer . mailcap-save-binary-file)
+      (non-viewer . t)
+      (type   . "application/x-tar"))
+     ("x-latex"
+      (viewer . tex-mode)
+      (test   . (fboundp 'tex-mode))
+      (type   . "application/x-latex"))
+     ("x-tex"
+      (viewer . tex-mode)
+      (test   . (fboundp 'tex-mode))
+      (type   . "application/x-tex"))
+     ("latex"
+      (viewer . tex-mode)
+      (test   . (fboundp 'tex-mode))
+      (type   . "application/latex"))
+     ("tex"
+      (viewer . tex-mode)
+      (test   . (fboundp 'tex-mode))
+      (type   . "application/tex"))
+     ("texinfo"
+      (viewer . texinfo-mode)
+      (test   . (fboundp 'texinfo-mode))
+      (type   . "application/tex"))
+     ("zip"
+      (viewer . mailcap-save-binary-file)
+      (non-viewer . t)
+      (type   . "application/zip")
+      ("copiousoutput"))
+     ;; Prefer free viewers.
+     ("pdf"
+      (viewer . "gv -safer %s")
+      (type . "application/pdf")
+      (test . window-system)
+      ("print" . ,(concat "pdf2ps %s - | " mailcap-print-command)))
+     ("pdf"
+      (viewer . "xpdf %s")
+      (type . "application/pdf")
+      ("print" . ,(concat "pdftops %s - | " mailcap-print-command))
+      (test . (eq window-system 'x)))
+     ("pdf"
+      (viewer . "acroread %s")
+      (type   . "application/pdf")
+      ("print" . ,(concat "cat %s | acroread -toPostScript | "
+                         mailcap-print-command))
+      (test . window-system))
+     ("pdf"
+      (viewer . ,(concat "pdftotext %s -"))
+      (type   . "application/pdf")
+      ("print" . ,(concat "pdftops %s - | " mailcap-print-command))
+      ("copiousoutput"))
+     ("postscript"
+      (viewer . "gv -safer %s")
+      (type . "application/postscript")
+      (test   . window-system)
+      ("print" . ,(concat mailcap-print-command " %s"))
+      ("needsx11"))
+     ("postscript"
+      (viewer . "ghostview -dSAFER %s")
+      (type . "application/postscript")
+      (test   . (eq window-system 'x))
+      ("print" . ,(concat mailcap-print-command " %s"))
+      ("needsx11"))
+     ("postscript"
+      (viewer . "ps2ascii %s")
+      (type . "application/postscript")
+      (test . (not (getenv "DISPLAY")))
+      ("print" . ,(concat mailcap-print-command " %s"))
+      ("copiousoutput"))
+     ("sieve"
+      (viewer . sieve-mode)
+      (test   . (fboundp 'sieve-mode))
+      (type   . "application/sieve"))
+     ("pgp-keys"
+      (viewer . "gpg --import --interactive --verbose")
+      (type   . "application/pgp-keys")
+      ("needsterminal")))
+    ("audio"
+     ("x-mpeg"
+      (viewer . "maplay %s")
+      (type   . "audio/x-mpeg"))
+     (".*"
+      (viewer . "showaudio")
+      (type   . "audio/*")))
+    ("message"
+     ("rfc-*822"
+      (viewer . mm-view-message)
+      (test   . (and (featurep 'gnus)
+                    (gnus-alive-p)))
+      (type   . "message/rfc822"))
+     ("rfc-*822"
+      (viewer . vm-mode)
+      (test   . (fboundp 'vm-mode))
+      (type   . "message/rfc822"))
+     ("rfc-*822"
+      (viewer . w3-mode)
+      (test   . (fboundp 'w3-mode))
+      (type   . "message/rfc822"))
+     ("rfc-*822"
+      (viewer . view-mode)
+      (type   . "message/rfc822")))
+    ("image"
+     ("x-xwd"
+      (viewer  . "xwud -in %s")
+      (type    . "image/x-xwd")
+      ("compose" . "xwd -frame > %s")
+      (test    . (eq window-system 'x))
+      ("needsx11"))
+     ("x11-dump"
+      (viewer . "xwud -in %s")
+      (type . "image/x-xwd")
+      ("compose" . "xwd -frame > %s")
+      (test   . (eq window-system 'x))
+      ("needsx11"))
+     ("windowdump"
+      (viewer . "xwud -in %s")
+      (type . "image/x-xwd")
+      ("compose" . "xwd -frame > %s")
+      (test   . (eq window-system 'x))
+      ("needsx11"))
+     (".*"
+      (viewer . "display %s")
+      (type . "image/*")
+      (test   . (eq window-system 'x))
+      ("needsx11"))
+     (".*"
+      (viewer . "ee %s")
+      (type . "image/*")
+      (test   . (eq window-system 'x))
+      ("needsx11")))
+    ("text"
+     ("plain"
+      (viewer  . w3-mode)
+      (test    . (fboundp 'w3-mode))
+      (type    . "text/plain"))
+     ("plain"
+      (viewer  . view-mode)
+      (test    . (fboundp 'view-mode))
+      (type    . "text/plain"))
+     ("plain"
+      (viewer  . fundamental-mode)
+      (type    . "text/plain"))
+     ("enriched"
+      (viewer . enriched-decode)
+      (test   . (fboundp 'enriched-decode))
+      (type   . "text/enriched"))
+     ("html"
+      (viewer . mm-w3-prepare-buffer)
+      (test   . (fboundp 'w3-prepare-buffer))
+      (type   . "text/html")))
+    ("video"
+     ("mpeg"
+      (viewer . "mpeg_play %s")
+      (type   . "video/mpeg")
+      (test   . (eq window-system 'x))
+      ("needsx11")))
+    ("x-world"
+     ("x-vrml"
+      (viewer  . "webspace -remote %s -URL %u")
+      (type    . "x-world/x-vrml")
+      ("description"
+       "VRML document")))
+    ("archive"
+     ("tar"
+      (viewer . tar-mode)
+      (type . "archive/tar")
+      (test . (fboundp 'tar-mode)))))
+  "The mailcap structure is an assoc list of assoc lists.
+1st assoc list is keyed on the major content-type
+2nd assoc list is keyed on the minor content-type (which can be a regexp)
+
+Which looks like:
+-----------------
+ ((\"application\"
+   (\"postscript\" . <info>))
+  (\"text\"
+   (\"plain\" . <info>)))
+
+Where <info> is another assoc list of the various information
+related to the mailcap RFC 1524.  This is keyed on the lowercase
+attribute name (viewer, test, etc).  This looks like:
+ ((viewer . VIEWERINFO)
+  (test   . TESTINFO)
+  (xxxx   . \"STRING\")
+  FLAG)
+
+Where VIEWERINFO specifies how the content-type is viewed.  Can be
+a string, in which case it is run through a shell, with
+appropriate parameters, or a symbol, in which case the symbol is
+`funcall'ed, with the buffer as an argument.
+
+TESTINFO is a test for the viewer's applicability, or nil.  If nil, it
+means the viewer is always valid.  If it is a Lisp function, it is
+called with a list of items from any extra fields from the
+Content-Type header as argument to return a boolean value for the
+validity.  Otherwise, if it is a non-function Lisp symbol or list
+whose car is a symbol, it is `eval'led to yield the validity.  If it
+is a string or list of strings, it represents a shell command to run
+to return a true or false shell value for the validity.")
+
+(defcustom mailcap-download-directory nil
+  "*Directory to which `mailcap-save-binary-file' downloads files by default.
+nil means your home directory."
+  :type '(choice (const :tag "Home directory" nil)
+                directory)
+  :group 'mailcap)
+
+(defvar mailcap-poor-system-types
+  '(ms-dos ms-windows windows-nt win32 w32 mswindows)
+  "Systems that don't have a Unix-like directory hierarchy.")
+
+;;;
+;;; Utility functions
+;;;
+
+(defun mailcap-save-binary-file ()
+  (goto-char (point-min))
+  (unwind-protect
+      (let ((file (read-file-name
+                  "Filename to save as: "
+                  (or mailcap-download-directory "~/")))
+           (require-final-newline nil))
+       (write-region (point-min) (point-max) file))
+    (kill-buffer (current-buffer))))
+
+(defvar mailcap-maybe-eval-warning
+  "*** WARNING ***
+
+This MIME part contains untrusted and possibly harmful content.
+If you evaluate the Emacs Lisp code contained in it, a lot of nasty
+things can happen.  Please examine the code very carefully before you
+instruct Emacs to evaluate it.  You can browse the buffer containing
+the code using \\[scroll-other-window].
+
+If you are unsure what to do, please answer \"no\"."
+  "Text of warning message displayed by `mailcap-maybe-eval'.
+Make sure that this text consists only of few text lines.  Otherwise,
+Gnus might fail to display all of it.")
+
+(defun mailcap-maybe-eval ()
+  "Maybe evaluate a buffer of Emacs Lisp code."
+  (let ((lisp-buffer (current-buffer)))
+    (goto-char (point-min))
+    (when
+       (save-window-excursion
+         (delete-other-windows)
+         (let ((buffer (get-buffer-create (generate-new-buffer-name
+                                           "*Warning*"))))
+           (unwind-protect
+               (with-current-buffer buffer
+                 (insert (substitute-command-keys
+                          mailcap-maybe-eval-warning))
+                 (goto-char (point-min))
+                 (display-buffer buffer)
+                 (yes-or-no-p "This is potentially dangerous emacs-lisp code, evaluate it? "))
+             (kill-buffer buffer))))
+      (eval-buffer (current-buffer)))
+    (when (buffer-live-p lisp-buffer)
+      (with-current-buffer lisp-buffer
+       (emacs-lisp-mode)))))
+
+
+;;;
+;;; The mailcap parser
+;;;
+
+(defun mailcap-replace-regexp (regexp to-string)
+  ;; Quiet replace-regexp.
+  (goto-char (point-min))
+  (while (re-search-forward regexp nil t)
+    (replace-match to-string t nil)))
+
+(defvar mailcap-parsed-p nil)
+
+(defun mailcap-parse-mailcaps (&optional path force)
+  "Parse out all the mailcaps specified in a path string PATH.
+Components of PATH are separated by the `path-separator' character
+appropriate for this system.  If FORCE, re-parse even if already
+parsed.  If PATH is omitted, use the value of environment variable
+MAILCAPS if set; otherwise (on Unix) use the path from RFC 1524, plus
+/usr/local/etc/mailcap."
+  (interactive (list nil t))
+  (when (or (not mailcap-parsed-p)
+           force)
+    (cond
+     (path nil)
+     ((getenv "MAILCAPS") (setq path (getenv "MAILCAPS")))
+     ((memq system-type mailcap-poor-system-types)
+      (setq path '("~/.mailcap" "~/mail.cap" "~/etc/mail.cap")))
+     (t (setq path
+             ;; This is per RFC 1524, specifically
+             ;; with /usr before /usr/local.
+             '("~/.mailcap" "/etc/mailcap" "/usr/etc/mailcap"
+               "/usr/local/etc/mailcap"))))
+    (let ((fnames (reverse
+                  (if (stringp path)
+                      (delete "" (split-string path path-separator))
+                    path)))
+         fname)
+      (while fnames
+       (setq fname (car fnames))
+       (if (and (file-readable-p fname)
+                (file-regular-p fname))
+           (mailcap-parse-mailcap fname))
+       (setq fnames (cdr fnames))))
+    (setq mailcap-parsed-p t)))
+
+(defun mailcap-parse-mailcap (fname)
+  "Parse out the mailcap file specified by FNAME."
+  (let (major                          ; The major mime type (image/audio/etc)
+       minor                           ; The minor mime type (gif, basic, etc)
+       save-pos                        ; Misc saved positions used in parsing
+       viewer                          ; How to view this mime type
+       info                            ; Misc info about this mime type
+       )
+    (with-temp-buffer
+      (insert-file-contents fname)
+      (set-syntax-table mailcap-parse-args-syntax-table)
+      (mailcap-replace-regexp "#.*" "")        ; Remove all comments
+      (mailcap-replace-regexp "\\\\[ \t]*\n" " ") ; And collapse spaces
+      (mailcap-replace-regexp "\n+" "\n") ; And blank lines
+      (goto-char (point-max))
+      (skip-chars-backward " \t\n")
+      (delete-region (point) (point-max))
+      (while (not (bobp))
+       (skip-chars-backward " \t\n")
+       (beginning-of-line)
+       (setq save-pos (point)
+             info nil)
+       (skip-chars-forward "^/; \t\n")
+       (downcase-region save-pos (point))
+       (setq major (buffer-substring save-pos (point)))
+       (skip-chars-forward " \t")
+       (setq minor "")
+       (when (eq (char-after) ?/)
+         (forward-char)
+         (skip-chars-forward " \t")
+         (setq save-pos (point))
+         (skip-chars-forward "^; \t\n")
+         (downcase-region save-pos (point))
+         (setq minor
+               (cond
+                ((eq ?* (or (char-after save-pos) 0)) ".*")
+                ((= (point) save-pos) ".*")
+                (t (regexp-quote (buffer-substring save-pos (point)))))))
+       (skip-chars-forward " \t")
+       ;;; Got the major/minor chunks, now for the viewers/etc
+       ;;; The first item _must_ be a viewer, according to the
+       ;;; RFC for mailcap files (#1524)
+       (setq viewer "")
+       (when (eq (char-after) ?\;)
+         (forward-char)
+         (skip-chars-forward " \t")
+         (setq save-pos (point))
+         (skip-chars-forward "^;\n")
+         ;; skip \;
+         (while (eq (char-before) ?\\)
+           (backward-delete-char 1)
+           (forward-char)
+           (skip-chars-forward "^;\n"))
+         (if (eq (or (char-after save-pos) 0) ?')
+             (setq viewer (progn
+                            (narrow-to-region (1+ save-pos) (point))
+                            (goto-char (point-min))
+                            (prog1
+                                (read (current-buffer))
+                              (goto-char (point-max))
+                              (widen))))
+           (setq viewer (buffer-substring save-pos (point)))))
+       (setq save-pos (point))
+       (end-of-line)
+       (unless (equal viewer "")
+         (setq info (nconc (list (cons 'viewer viewer)
+                                 (cons 'type (concat major "/"
+                                                     (if (string= minor ".*")
+                                                         "*" minor))))
+                           (mailcap-parse-mailcap-extras save-pos (point))))
+         (mailcap-mailcap-entry-passes-test info)
+         (mailcap-add-mailcap-entry major minor info))
+       (beginning-of-line)))))
+
+(defun mailcap-parse-mailcap-extras (st nd)
+  "Grab all the extra stuff from a mailcap entry."
+  (let (
+       name                            ; From name=
+       value                           ; its value
+       results                         ; Assoc list of results
+       name-pos                        ; Start of XXXX= position
+       val-pos                         ; Start of value position
+       done                            ; Found end of \'d ;s?
+       )
+    (save-restriction
+      (narrow-to-region st nd)
+      (goto-char (point-min))
+      (skip-chars-forward " \n\t;")
+      (while (not (eobp))
+       (setq done nil)
+       (setq name-pos (point))
+       (skip-chars-forward "^ \n\t=;")
+       (downcase-region name-pos (point))
+       (setq name (buffer-substring name-pos (point)))
+       (skip-chars-forward " \t\n")
+       (if (not (eq (char-after (point)) ?=)) ; There is no value
+           (setq value t)
+         (skip-chars-forward " \t\n=")
+         (setq val-pos (point))
+         (if (memq (char-after val-pos) '(?\" ?'))
+             (progn
+               (setq val-pos (1+ val-pos))
+               (condition-case nil
+                   (progn
+                     (forward-sexp 1)
+                     (backward-char 1))
+                 (error (goto-char (point-max)))))
+           (while (not done)
+             (skip-chars-forward "^;")
+             (if (eq (char-after (1- (point))) ?\\ )
+                 (progn
+                   (subst-char-in-region (1- (point)) (point) ?\\ ? )
+                   (skip-chars-forward ";"))
+               (setq done t))))
+         (setq value (buffer-substring val-pos (point))))
+       (setq results (cons (cons name value) results))
+       (skip-chars-forward " \";\n\t"))
+      results)))
+
+(defun mailcap-mailcap-entry-passes-test (info)
+  "Return non-nil iff mailcap entry INFO passes its test clause.
+Also return non-nil if no test clause is present."
+  (let ((test (assq 'test info))       ; The test clause
+       status)
+    (setq status (and test (split-string (cdr test) " ")))
+    (if (and (or (assoc "needsterm" info)
+                (assoc "needsterminal" info)
+                (assoc "needsx11" info))
+            (not (getenv "DISPLAY")))
+       (setq status nil)
+      (cond
+       ((and (equal (nth 0 status) "test")
+            (equal (nth 1 status) "-n")
+            (or (equal (nth 2 status) "$DISPLAY")
+                (equal (nth 2 status) "\"$DISPLAY\"")))
+       (setq status (if (getenv "DISPLAY") t nil)))
+       ((and (equal (nth 0 status) "test")
+            (equal (nth 1 status) "-z")
+            (or (equal (nth 2 status) "$DISPLAY")
+                (equal (nth 2 status) "\"$DISPLAY\"")))
+       (setq status (if (getenv "DISPLAY") nil t)))
+       (test nil)
+       (t nil)))
+    (and test (listp test) (setcdr test status))))
+
+;;;
+;;; The action routines.
+;;;
+
+(defun mailcap-possible-viewers (major minor)
+  "Return a list of possible viewers from MAJOR for minor type MINOR."
+  (let ((exact '())
+       (wildcard '()))
+    (while major
+      (cond
+       ((equal (car (car major)) minor)
+       (setq exact (cons (cdr (car major)) exact)))
+       ((and minor (string-match (concat "^" (car (car major)) "$") minor))
+       (setq wildcard (cons (cdr (car major)) wildcard))))
+      (setq major (cdr major)))
+    (nconc exact wildcard)))
+
+(defun mailcap-unescape-mime-test (test type-info)
+  (let (save-pos save-chr subst)
+    (cond
+     ((symbolp test) test)
+     ((and (listp test) (symbolp (car test))) test)
+     ((or (stringp test)
+         (and (listp test) (stringp (car test))
+              (setq test (mapconcat 'identity test " "))))
+      (with-temp-buffer
+       (insert test)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (skip-chars-forward "^%")
+         (if (/= (- (point)
+                    (progn (skip-chars-backward "\\\\")
+                           (point)))
+                 0)                    ; It is an escaped %
+             (progn
+               (delete-char 1)
+               (skip-chars-forward "%."))
+           (setq save-pos (point))
+           (skip-chars-forward "%")
+           (setq save-chr (char-after (point)))
+           ;; Escapes:
+           ;; %s: name of a file for the body data
+           ;; %t: content-type
+           ;; %{<parameter name}: value of parameter in mailcap entry
+           ;; %n: number of sub-parts for multipart content-type
+           ;; %F: a set of content-type/filename pairs for multiparts
+           (cond
+            ((null save-chr) nil)
+            ((= save-chr ?t)
+             (delete-region save-pos (progn (forward-char 1) (point)))
+             (insert (or (cdr (assq 'type type-info)) "\"\"")))
+            ((memq save-chr '(?M ?n ?F))
+             (delete-region save-pos (progn (forward-char 1) (point)))
+             (insert "\"\""))
+            ((= save-chr ?{)
+             (forward-char 1)
+             (skip-chars-forward "^}")
+             (downcase-region (+ 2 save-pos) (point))
+             (setq subst (buffer-substring (+ 2 save-pos) (point)))
+             (delete-region save-pos (1+ (point)))
+             (insert (or (cdr (assoc subst type-info)) "\"\"")))
+            (t nil))))
+       (buffer-string)))
+     (t (error "Bad value to mailcap-unescape-mime-test: %s" test)))))
+
+(defvar mailcap-viewer-test-cache nil)
+
+(defun mailcap-viewer-passes-test (viewer-info type-info)
+  "Return non-nil iff viewer specified by VIEWER-INFO passes its test clause.
+Also return non-nil if it has no test clause.  TYPE-INFO is an argument
+to supply to the test."
+  (let* ((test-info (assq 'test viewer-info))
+        (test (cdr test-info))
+        (otest test)
+        (viewer (cdr (assoc 'viewer viewer-info)))
+        (default-directory (expand-file-name "~/"))
+        status parsed-test cache result)
+    (if (setq cache (assoc test mailcap-viewer-test-cache))
+       (cadr cache)
+      (setq
+       result
+       (cond
+       ((not test-info) t)             ; No test clause
+       ((not test) nil)                ; Already failed test
+       ((eq test t) t)                 ; Already passed test
+       ((functionp test)               ; Lisp function as test
+        (funcall test type-info))
+       ((and (symbolp test)            ; Lisp variable as test
+             (boundp test))
+        (symbol-value test))
+       ((and (listp test)              ; List to be eval'd
+             (symbolp (car test)))
+        (eval test))
+       (t
+        (setq test (mailcap-unescape-mime-test test type-info)
+              test (list shell-file-name nil nil nil
+                         shell-command-switch test)
+              status (apply 'call-process test))
+        (eq 0 status))))
+      (push (list otest result) mailcap-viewer-test-cache)
+      result)))
+
+(defun mailcap-add-mailcap-entry (major minor info)
+  (let ((old-major (assoc major mailcap-mime-data)))
+    (if (null old-major)               ; New major area
+       (setq mailcap-mime-data
+             (cons (cons major (list (cons minor info)))
+                   mailcap-mime-data))
+      (let ((cur-minor (assoc minor old-major)))
+       (cond
+        ((or (null cur-minor)          ; New minor area, or
+             (assq 'test info))        ; Has a test, insert at beginning
+         (setcdr old-major (cons (cons minor info) (cdr old-major))))
+        ((and (not (assq 'test info))  ; No test info, replace completely
+              (not (assq 'test cur-minor))
+              (equal (assq 'viewer info)  ; Keep alternative viewer
+                     (assq 'viewer cur-minor)))
+         (setcdr cur-minor info))
+        (t
+         (setcdr old-major (cons (cons minor info) (cdr old-major))))))
+      )))
+
+(defun mailcap-add (type viewer &optional test)
+  "Add VIEWER as a handler for TYPE.
+If TEST is not given, it defaults to t."
+  (let ((tl (split-string type "/")))
+    (when (or (not (car tl))
+             (not (cadr tl)))
+      (error "%s is not a valid MIME type" type))
+    (mailcap-add-mailcap-entry
+     (car tl) (cadr tl)
+     `((viewer . ,viewer)
+       (test . ,(if test test t))
+       (type . ,type)))))
+
+;;;
+;;; The main whabbo
+;;;
+
+(defun mailcap-viewer-lessp (x y)
+  "Return t iff viewer X is more desirable than viewer Y."
+  (let ((x-wild (string-match "[*?]" (or (cdr-safe (assq 'type x)) "")))
+       (y-wild (string-match "[*?]" (or (cdr-safe (assq 'type y)) "")))
+       (x-lisp (not (stringp (or (cdr-safe (assq 'viewer x)) ""))))
+       (y-lisp (not (stringp (or (cdr-safe (assq 'viewer y)) "")))))
+    (cond
+     ((and x-wild (not y-wild))
+      nil)
+     ((and (not x-wild) y-wild)
+      t)
+     ((and (not y-lisp) x-lisp)
+      t)
+     (t nil))))
+
+(defun mailcap-mime-info (string &optional request)
+  "Get the MIME viewer command for STRING, return nil if none found.
+Expects a complete content-type header line as its argument.
+
+Second argument REQUEST specifies what information to return.  If it is
+nil or the empty string, the viewer (second field of the mailcap
+entry) will be returned.  If it is a string, then the mailcap field
+corresponding to that string will be returned (print, description,
+whatever).  If a number, then all the information for this specific
+viewer is returned.  If `all', then all possible viewers for
+this type is returned."
+  (let (
+       major                           ; Major encoding (text, etc)
+       minor                           ; Minor encoding (html, etc)
+       info                            ; Other info
+       save-pos                        ; Misc. position during parse
+       major-info                      ; (assoc major mailcap-mime-data)
+       minor-info                      ; (assoc minor major-info)
+       test                            ; current test proc.
+       viewers                         ; Possible viewers
+       passed                          ; Viewers that passed the test
+       viewer                          ; The one and only viewer
+       ctl)
+    (save-excursion
+      (setq ctl (mail-header-parse-content-type (or string "text/plain")))
+      (setq major (split-string (car ctl) "/"))
+      (setq minor (cadr major)
+           major (car major))
+      (when (setq major-info (cdr (assoc major mailcap-mime-data)))
+       (when (setq viewers (mailcap-possible-viewers major-info minor))
+         (setq info (mapcar (lambda (a) (cons (symbol-name (car a))
+                                              (cdr a)))
+                            (cdr ctl)))
+         (while viewers
+           (if (mailcap-viewer-passes-test (car viewers) info)
+               (setq passed (cons (car viewers) passed)))
+           (setq viewers (cdr viewers)))
+         (setq passed (sort passed 'mailcap-viewer-lessp))
+         (setq viewer (car passed))))
+      (when (and (stringp (cdr (assq 'viewer viewer)))
+                passed)
+       (setq viewer (car passed)))
+      (cond
+       ((and (null viewer) (not (equal major "default")) request)
+       (mailcap-mime-info "default" request))
+       ((or (null request) (equal request ""))
+       (mailcap-unescape-mime-test (cdr (assq 'viewer viewer)) info))
+       ((stringp request)
+       (mailcap-unescape-mime-test
+        (cdr-safe (assoc request viewer)) info))
+       ((eq request 'all)
+       passed)
+       (t
+       ;; MUST make a copy *sigh*, else we modify mailcap-mime-data
+       (setq viewer (copy-sequence viewer))
+       (let ((view (assq 'viewer viewer))
+             (test (assq 'test viewer)))
+         (if view (setcdr view (mailcap-unescape-mime-test (cdr view) info)))
+         (if test (setcdr test (mailcap-unescape-mime-test (cdr test) info))))
+       viewer)))))
+
+;;;
+;;; Experimental MIME-types parsing
+;;;
+
+(defvar mailcap-mime-extensions
+  '((""       . "text/plain")
+    (".abs"   . "audio/x-mpeg")
+    (".aif"   . "audio/aiff")
+    (".aifc"  . "audio/aiff")
+    (".aiff"  . "audio/aiff")
+    (".ano"   . "application/x-annotator")
+    (".au"    . "audio/ulaw")
+    (".avi"   . "video/x-msvideo")
+    (".bcpio" . "application/x-bcpio")
+    (".bin"   . "application/octet-stream")
+    (".cdf"   . "application/x-netcdr")
+    (".cpio"  . "application/x-cpio")
+    (".csh"   . "application/x-csh")
+    (".css"   . "text/css")
+    (".dvi"   . "application/x-dvi")
+    (".diff"  . "text/x-patch")
+    (".el"    . "application/emacs-lisp")
+    (".eps"   . "application/postscript")
+    (".etx"   . "text/x-setext")
+    (".exe"   . "application/octet-stream")
+    (".fax"   . "image/x-fax")
+    (".gif"   . "image/gif")
+    (".hdf"   . "application/x-hdf")
+    (".hqx"   . "application/mac-binhex40")
+    (".htm"   . "text/html")
+    (".html"  . "text/html")
+    (".icon"  . "image/x-icon")
+    (".ief"   . "image/ief")
+    (".jpg"   . "image/jpeg")
+    (".macp"  . "image/x-macpaint")
+    (".man"   . "application/x-troff-man")
+    (".me"    . "application/x-troff-me")
+    (".mif"   . "application/mif")
+    (".mov"   . "video/quicktime")
+    (".movie" . "video/x-sgi-movie")
+    (".mp2"   . "audio/x-mpeg")
+    (".mp3"   . "audio/x-mpeg")
+    (".mp2a"  . "audio/x-mpeg2")
+    (".mpa"   . "audio/x-mpeg")
+    (".mpa2"  . "audio/x-mpeg2")
+    (".mpe"   . "video/mpeg")
+    (".mpeg"  . "video/mpeg")
+    (".mpega" . "audio/x-mpeg")
+    (".mpegv" . "video/mpeg")
+    (".mpg"   . "video/mpeg")
+    (".mpv"   . "video/mpeg")
+    (".ms"    . "application/x-troff-ms")
+    (".nc"    . "application/x-netcdf")
+    (".nc"    . "application/x-netcdf")
+    (".oda"   . "application/oda")
+    (".patch" . "text/x-patch")
+    (".pbm"   . "image/x-portable-bitmap")
+    (".pdf"   . "application/pdf")
+    (".pgm"   . "image/portable-graymap")
+    (".pict"  . "image/pict")
+    (".png"   . "image/png")
+    (".pnm"   . "image/x-portable-anymap")
+    (".ppm"   . "image/portable-pixmap")
+    (".ps"    . "application/postscript")
+    (".qt"    . "video/quicktime")
+    (".ras"   . "image/x-raster")
+    (".rgb"   . "image/x-rgb")
+    (".rtf"   . "application/rtf")
+    (".rtx"   . "text/richtext")
+    (".sh"    . "application/x-sh")
+    (".sit"   . "application/x-stuffit")
+    (".siv"   . "application/sieve")
+    (".snd"   . "audio/basic")
+    (".src"   . "application/x-wais-source")
+    (".tar"   . "archive/tar")
+    (".tcl"   . "application/x-tcl")
+    (".tex"   . "application/x-tex")
+    (".texi"  . "application/texinfo")
+    (".tga"   . "image/x-targa")
+    (".tif"   . "image/tiff")
+    (".tiff"  . "image/tiff")
+    (".tr"    . "application/x-troff")
+    (".troff" . "application/x-troff")
+    (".tsv"   . "text/tab-separated-values")
+    (".txt"   . "text/plain")
+    (".vbs"   . "video/mpeg")
+    (".vox"   . "audio/basic")
+    (".vrml"  . "x-world/x-vrml")
+    (".wav"   . "audio/x-wav")
+    (".xls"   . "application/vnd.ms-excel")
+    (".wrl"   . "x-world/x-vrml")
+    (".xbm"   . "image/xbm")
+    (".xpm"   . "image/xpm")
+    (".xwd"   . "image/windowdump")
+    (".zip"   . "application/zip")
+    (".ai"    . "application/postscript")
+    (".jpe"   . "image/jpeg")
+    (".jpeg"  . "image/jpeg"))
+  "An alist of file extensions and corresponding MIME content-types.
+This exists for you to customize the information in Lisp.  It is
+merged with values from mailcap files by `mailcap-parse-mimetypes'.")
+
+(defvar mailcap-mimetypes-parsed-p nil)
+
+(defun mailcap-parse-mimetypes (&optional path force)
+  "Parse out all the mimetypes specified in a Unix-style path string PATH.
+Components of PATH are separated by the `path-separator' character
+appropriate for this system.  If PATH is omitted, use the value of
+environment variable MIMETYPES if set; otherwise use a default path.
+If FORCE, re-parse even if already parsed."
+  (interactive (list nil t))
+  (when (or (not mailcap-mimetypes-parsed-p)
+           force)
+    (cond
+     (path nil)
+     ((getenv "MIMETYPES") (setq path (getenv "MIMETYPES")))
+     ((memq system-type mailcap-poor-system-types)
+      (setq path '("~/mime.typ" "~/etc/mime.typ")))
+     (t (setq path
+             ;; mime.types seems to be the normal name, definitely so
+             ;; on current GNUish systems.  The search order follows
+             ;; that for mailcap.
+             '("~/.mime.types"
+               "/etc/mime.types"
+               "/usr/etc/mime.types"
+               "/usr/local/etc/mime.types"
+               "/usr/local/www/conf/mime.types"
+               "~/.mime-types"
+               "/etc/mime-types"
+               "/usr/etc/mime-types"
+               "/usr/local/etc/mime-types"
+               "/usr/local/www/conf/mime-types"))))
+    (let ((fnames (reverse (if (stringp path)
+                              (delete "" (split-string path path-separator))
+                            path)))
+         fname)
+      (while fnames
+       (setq fname (car fnames))
+       (if (and (file-readable-p fname))
+           (mailcap-parse-mimetype-file fname))
+       (setq fnames (cdr fnames))))
+    (setq mailcap-mimetypes-parsed-p t)))
+
+(defun mailcap-parse-mimetype-file (fname)
+  "Parse out a mime-types file FNAME."
+  (let (type                           ; The MIME type for this line
+       extns                           ; The extensions for this line
+       save-pos                        ; Misc. saved buffer positions
+       )
+    (with-temp-buffer
+      (insert-file-contents fname)
+      (mailcap-replace-regexp "#.*" "")
+      (mailcap-replace-regexp "\n+" "\n")
+      (mailcap-replace-regexp "[ \t]+$" "")
+      (goto-char (point-max))
+      (skip-chars-backward " \t\n")
+      (delete-region (point) (point-max))
+      (goto-char (point-min))
+      (while (not (eobp))
+       (skip-chars-forward " \t\n")
+       (setq save-pos (point))
+       (skip-chars-forward "^ \t\n")
+       (downcase-region save-pos (point))
+       (setq type (buffer-substring save-pos (point)))
+       (while (not (eolp))
+         (skip-chars-forward " \t")
+         (setq save-pos (point))
+         (skip-chars-forward "^ \t\n")
+         (setq extns (cons (buffer-substring save-pos (point)) extns)))
+       (while extns
+         (setq mailcap-mime-extensions
+               (cons
+                (cons (if (= (string-to-char (car extns)) ?.)
+                          (car extns)
+                        (concat "." (car extns))) type)
+                mailcap-mime-extensions)
+               extns (cdr extns)))))))
+
+(defun mailcap-extension-to-mime (extn)
+  "Return the MIME content type of the file extensions EXTN."
+  (mailcap-parse-mimetypes)
+  (if (and (stringp extn)
+          (not (eq (string-to-char extn) ?.)))
+      (setq extn (concat "." extn)))
+  (cdr (assoc (downcase extn) mailcap-mime-extensions)))
+
+;; Unused?
+(defalias 'mailcap-command-p 'executable-find)
+
+(defun mailcap-mime-types ()
+  "Return a list of MIME media types."
+  (mailcap-parse-mimetypes)
+  (mm-delete-duplicates
+   (nconc
+    (mapcar 'cdr mailcap-mime-extensions)
+    (apply
+     'nconc
+     (mapcar
+      (lambda (l)
+       (delq nil
+             (mapcar
+              (lambda (m)
+                (let ((type (cdr (assq 'type (cdr m)))))
+                  (if (equal (cadr (split-string type "/"))
+                             "*")
+                      nil
+                    type)))
+              (cdr l))))
+      mailcap-mime-data)))))
+
+(provide 'gnus-mailcap)
+
+;;; mailcap.el ends here
index 84487f9..35ee140 100644 (file)
@@ -1,8 +1,9 @@
 ;;; gnus-mh.el --- mh-e interface for Gnus
-;; Copyright (C) 1994,95,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -39,6 +40,9 @@
 (require 'gnus-msg)
 (require 'gnus-sum)
 
+(eval-when-compile
+  (defvar mh-lib-progs))
+
 (defun gnus-summary-save-article-folder (&optional arg)
   "Append the current article to an mh folder.
 If N is a positive number, save the N next articles.
@@ -46,6 +50,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-folder))
     (gnus-summary-save-article arg)))
 
@@ -64,10 +69,14 @@ Optional argument FOLDER specifies folder name."
                   (funcall gnus-folder-save-name gnus-newsgroup-name
                            gnus-current-headers gnus-newsgroup-last-folder)
                   t))))
-       (errbuf (get-buffer-create " *Gnus rcvstore*"))
+       (errbuf (gnus-get-buffer-create " *Gnus rcvstore*"))
        ;; Find the rcvstore program.
-       (exec-path (if mh-lib (cons mh-lib exec-path) exec-path)))
-    (gnus-eval-in-buffer-window gnus-original-article-buffer
+       (exec-path (cond
+                   ((and (boundp 'mh-lib-progs) mh-lib-progs)
+                    (cons mh-lib-progs exec-path))
+                   (mh-lib (cons mh-lib exec-path))
+                   (t exec-path))))
+    (with-current-buffer gnus-original-article-buffer
       (save-restriction
        (widen)
        (unwind-protect
diff --git a/lisp/gnus-ml.el b/lisp/gnus-ml.el
new file mode 100644 (file)
index 0000000..25f6685
--- /dev/null
@@ -0,0 +1,201 @@
+;;; gnus-ml.el --- Mailing list minor mode for Gnus
+
+;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+;; Author: Julien Gilles  <jgilles@free.fr>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; implement (small subset of) RFC 2369
+
+;;; Code:
+
+(require 'gnus)
+(require 'gnus-msg)
+(eval-when-compile (require 'cl))
+
+;;; Mailing list minor mode
+
+(defvar gnus-mailing-list-mode nil
+  "Minor mode for providing mailing-list commands.")
+
+(defvar gnus-mailing-list-mode-map nil)
+
+(defvar gnus-mailing-list-menu)
+
+(unless gnus-mailing-list-mode-map
+  (setq gnus-mailing-list-mode-map (make-sparse-keymap))
+
+  (gnus-define-keys gnus-mailing-list-mode-map
+    "\C-c\C-nh" gnus-mailing-list-help
+    "\C-c\C-ns" gnus-mailing-list-subscribe
+    "\C-c\C-nu" gnus-mailing-list-unsubscribe
+    "\C-c\C-np" gnus-mailing-list-post
+    "\C-c\C-no" gnus-mailing-list-owner
+    "\C-c\C-na" gnus-mailing-list-archive
+    ))
+
+(defun gnus-mailing-list-make-menu-bar ()
+  (unless (boundp 'gnus-mailing-list-menu)
+    (easy-menu-define
+     gnus-mailing-list-menu gnus-mailing-list-mode-map ""
+     '("Mailing-Lists"
+       ["Get help" gnus-mailing-list-help t]
+       ["Subscribe" gnus-mailing-list-subscribe t]
+       ["Unsubscribe" gnus-mailing-list-unsubscribe t]
+       ["Post a message" gnus-mailing-list-post t]
+       ["Mail to owner" gnus-mailing-list-owner t]
+       ["Browse archive" gnus-mailing-list-archive t]))))
+
+;;;###autoload
+(defun turn-on-gnus-mailing-list-mode ()
+  (when (gnus-group-find-parameter gnus-newsgroup-name 'to-list)
+    (gnus-mailing-list-mode 1)))
+
+;;;###autoload
+(defun gnus-mailing-list-insinuate (&optional force)
+  "Setup group parameters from List-Post header.
+If FORCE is non-nil, replace the old ones."
+  (interactive "P")
+  (let ((list-post
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-post"))))
+    (if list-post
+       (if (and (not force)
+                (gnus-group-get-parameter gnus-newsgroup-name 'to-list))
+           (gnus-message 1 "to-list is non-nil.")
+         (if (string-match "<mailto:\\([^>]*\\)>" list-post)
+             (setq list-post (match-string 1 list-post)))
+         (gnus-group-add-parameter gnus-newsgroup-name
+                                   (cons 'to-list list-post))
+         (gnus-mailing-list-mode 1))
+      (gnus-message 1 "no list-post in this message."))))
+
+;;;###autoload
+(defun gnus-mailing-list-mode (&optional arg)
+  "Minor mode for providing mailing-list commands.
+
+\\{gnus-mailing-list-mode-map}"
+  (interactive "P")
+  (when (eq major-mode 'gnus-summary-mode)
+    (when (set (make-local-variable 'gnus-mailing-list-mode)
+              (if (null arg) (not gnus-mailing-list-mode)
+                (> (prefix-numeric-value arg) 0)))
+      ;; Set up the menu.
+      (when (gnus-visual-p 'mailing-list-menu 'menu)
+       (gnus-mailing-list-make-menu-bar))
+      (gnus-add-minor-mode 'gnus-mailing-list-mode " Mailing-List" gnus-mailing-list-mode-map)
+      (gnus-run-hooks 'gnus-mailing-list-mode-hook))))
+
+;;; Commands
+
+(defun gnus-mailing-list-help ()
+  "Get help from mailing list server."
+  (interactive)
+  (let ((list-help
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-help"))))
+    (cond (list-help (gnus-mailing-list-message list-help))
+         (t (gnus-message 1 "no list-help in this group")))))
+
+(defun gnus-mailing-list-subscribe ()
+  "Subscribe"
+  (interactive)
+  (let ((list-subscribe
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-subscribe"))))
+    (cond (list-subscribe (gnus-mailing-list-message list-subscribe))
+         (t (gnus-message 1 "no list-subscribe in this group")))))
+
+(defun gnus-mailing-list-unsubscribe ()
+  "Unsubscribe"
+  (interactive)
+  (let ((list-unsubscribe
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-unsubscribe"))))
+    (cond (list-unsubscribe (gnus-mailing-list-message list-unsubscribe))
+         (t (gnus-message 1 "no list-unsubscribe in this group")))))
+
+(defun gnus-mailing-list-post ()
+  "Post message (really useful ?)"
+  (interactive)
+  (let ((list-post
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-post"))))
+    (cond (list-post (gnus-mailing-list-message list-post))
+         (t (gnus-message 1 "no list-post in this group")))))
+
+(defun gnus-mailing-list-owner ()
+  "Mail to the owner"
+  (interactive)
+  (let ((list-owner
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-owner"))))
+    (cond (list-owner (gnus-mailing-list-message list-owner))
+         (t (gnus-message 1 "no list-owner in this group")))))
+
+(defun gnus-mailing-list-archive ()
+  "Browse archive"
+  (interactive)
+  (require 'browse-url)
+  (let ((list-archive
+        (with-current-buffer gnus-original-article-buffer
+          (gnus-fetch-field "list-archive"))))
+    (cond (list-archive
+          (if (string-match "<\\(http:[^>]*\\)>" list-archive)
+              (browse-url (match-string 1 list-archive))
+            (browse-url list-archive)))
+         (t (gnus-message 1 "no list-archive in this group")))))
+
+;;; Utility functions
+
+(defun gnus-mailing-list-message (address)
+  ""
+  (let ((mailto  "")
+       (to ())
+       (subject "None")
+       (body "")
+       )
+    (cond
+     ((string-match "<mailto:\\([^>]*\\)>" address)
+      (let ((args (match-string 1 address)))
+       (cond                                   ; with param
+        ((string-match "\\(.*\\)\\?\\(.*\\)" args)
+         (setq mailto (match-string 1 args))
+         (let ((param (match-string 2 args)))
+           (if (string-match "subject=\\([^&]*\\)" param)
+               (setq subject (match-string 1 param)))
+           (if (string-match "body=\\([^&]*\\)" param)
+               (setq body (match-string 1 param)))
+           (if (string-match "to=\\([^&]*\\)" param)
+               (push (match-string 1 param) to))
+           ))
+        (t (setq mailto args)))))                      ; without param
+
+     ; other case <http://... to be done.
+     (t nil))
+    (gnus-setup-message 'message (message-mail mailto subject))
+    (insert body)
+    ))
+
+(provide 'gnus-ml)
+
+;;; gnus-ml.el ends here
diff --git a/lisp/gnus-mlspl.el b/lisp/gnus-mlspl.el
new file mode 100644 (file)
index 0000000..2379a17
--- /dev/null
@@ -0,0 +1,231 @@
+;;; gnus-mlspl.el --- a group params-based mail splitting mechanism
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002
+;;        Free Software Foundation, Inc.
+
+;; Author: Alexandre Oliva <oliva@lsd.ic.unicamp.br>
+;; Keywords: news, mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'gnus)
+(require 'gnus-sum)
+(require 'gnus-group)
+(require 'nnmail)
+
+(defvar gnus-group-split-updated-hook nil
+  "Hook called just after nnmail-split-fancy is updated by
+gnus-group-split-update.")
+
+(defvar gnus-group-split-default-catch-all-group "mail.misc"
+  "Group name (or arbitrary fancy split) with default splitting rules.
+Used by gnus-group-split and gnus-group-split-update as a fallback
+split, in case none of the group-based splits matches.")
+
+;;;###autoload
+(defun gnus-group-split-setup (&optional auto-update catch-all)
+  "Set up the split for nnmail-split-fancy.
+Sets things up so that nnmail-split-fancy is used for mail
+splitting, and defines the variable nnmail-split-fancy according with
+group parameters.
+
+If AUTO-UPDATE is non-nil (prefix argument accepted, if called
+interactively), it makes sure nnmail-split-fancy is re-computed before
+getting new mail, by adding gnus-group-split-update to
+nnmail-pre-get-new-mail-hook.
+
+A non-nil CATCH-ALL replaces the current value of
+gnus-group-split-default-catch-all-group.  This variable is only used
+by gnus-group-split-update, and only when its CATCH-ALL argument is
+nil.  This argument may contain any fancy split, that will be added as
+the last split in a `|' split produced by gnus-group-split-fancy,
+unless overridden by any group marked as a catch-all group.  Typical
+uses are as simple as the name of a default mail group, but more
+elaborate fancy splits may also be useful to split mail that doesn't
+match any of the group-specified splitting rules.  See
+`gnus-group-split-fancy' for details."
+  (interactive "P")
+  (setq nnmail-split-methods 'nnmail-split-fancy)
+  (when catch-all
+    (setq gnus-group-split-default-catch-all-group catch-all))
+  (gnus-group-split-update)
+  (when auto-update
+    (add-hook 'nnmail-pre-get-new-mail-hook 'gnus-group-split-update)))
+
+;;;###autoload
+(defun gnus-group-split-update (&optional catch-all)
+  "Computes nnmail-split-fancy from group params and CATCH-ALL, by
+calling (gnus-group-split-fancy nil nil CATCH-ALL).
+
+If CATCH-ALL is nil, gnus-group-split-default-catch-all-group is used
+instead.  This variable is set by gnus-group-split-setup."
+  (interactive)
+  (setq nnmail-split-fancy
+       (gnus-group-split-fancy
+        nil (null nnmail-crosspost)
+        (or catch-all gnus-group-split-default-catch-all-group)))
+  (run-hooks 'gnus-group-split-updated-hook))
+
+;;;###autoload
+(defun gnus-group-split ()
+  "Uses information from group parameters in order to split mail.
+See `gnus-group-split-fancy' for more information.
+
+gnus-group-split is a valid value for nnmail-split-methods."
+  (let (nnmail-split-fancy)
+    (gnus-group-split-update)
+    (nnmail-split-fancy)))
+
+;;;###autoload
+(defun gnus-group-split-fancy
+  (&optional groups no-crosspost catch-all)
+  "Uses information from group parameters in order to split mail.
+It can be embedded into `nnmail-split-fancy' lists with the SPLIT
+
+\(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL\)
+
+GROUPS may be a regular expression or a list of group names, that will
+be used to select candidate groups.  If it is omitted or nil, all
+existing groups are considered.
+
+if NO-CROSSPOST is omitted or nil, a & split will be returned,
+otherwise, a | split, that does not allow crossposting, will be
+returned.
+
+For each selected group, a SPLIT is composed like this: if SPLIT-SPEC
+is specified, this split is returned as-is (unless it is nil: in this
+case, the group is ignored).  Otherwise, if TO-ADDRESS, TO-LIST and/or
+EXTRA-ALIASES are specified, a regexp that matches any of them is
+constructed (extra-aliases may be a list).  Additionally, if
+SPLIT-REGEXP is specified, the regexp will be extended so that it
+matches this regexp too, and if SPLIT-EXCLUDE is specified, RESTRICT
+clauses will be generated.
+
+If CATCH-ALL is nil, no catch-all handling is performed, regardless of
+catch-all marks in group parameters.  Otherwise, if there is no
+selected group whose SPLIT-REGEXP matches the empty string, nor is
+there a selected group whose SPLIT-SPEC is 'catch-all, this fancy
+split (say, a group name) will be appended to the returned SPLIT list,
+as the last element of a '| SPLIT.
+
+For example, given the following group parameters:
+
+nnml:mail.bar:
+\((to-address . \"bar@femail.com\")
+ (split-regexp . \".*@femail\\\\.com\"))
+nnml:mail.foo:
+\((to-list . \"foo@nowhere.gov\")
+ (extra-aliases \"foo@localhost\" \"foo-redist@home\")
+ (split-exclude \"bugs-foo\" \"rambling-foo\")
+ (admin-address . \"foo-request@nowhere.gov\"))
+nnml:mail.others:
+\((split-spec . catch-all))
+
+Calling (gnus-group-split-fancy nil nil \"mail.others\") returns:
+
+\(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\"
+          \"mail.bar\")
+      (any \"\\\\(foo@nowhere\\\\.gov\\\\|foo@localhost\\\\|foo-redist@home\\\\)\"
+          - \"bugs-foo\" - \"rambling-foo\" \"mail.foo\"))
+   \"mail.others\")"
+  (let* ((newsrc (cdr gnus-newsrc-alist))
+        split)
+    (dolist (info newsrc)
+      (let ((group (gnus-info-group info))
+           (params (gnus-info-params info)))
+       ;; For all GROUPs that match the specified GROUPS
+       (when (or (not groups)
+                 (and (listp groups)
+                      (memq group groups))
+                 (and (stringp groups)
+                      (string-match groups group)))
+         (let ((split-spec (assoc 'split-spec params)) group-clean)
+           ;; Remove backend from group name
+           (setq group-clean (string-match ":" group))
+           (setq group-clean
+                 (if group-clean
+                     (substring group (1+ group-clean))
+                   group))
+           (if split-spec
+               (when (setq split-spec (cdr split-spec))
+                 (if (eq split-spec 'catch-all)
+                     ;; Emit catch-all only when requested
+                     (when catch-all
+                       (setq catch-all group-clean))
+                   ;; Append split-spec to the main split
+                   (push split-spec split)))
+             ;; Let's deduce split-spec from other params
+             (let ((to-address (cdr (assoc 'to-address params)))
+                   (to-list (cdr (assoc 'to-list params)))
+                   (extra-aliases (cdr (assoc 'extra-aliases params)))
+                   (split-regexp (cdr (assoc 'split-regexp params)))
+                   (split-exclude (cdr (assoc 'split-exclude params))))
+               (when (or to-address to-list extra-aliases split-regexp)
+                 ;; regexp-quote to-address, to-list and extra-aliases
+                 ;; and add them all to split-regexp
+                 (setq split-regexp
+                       (concat
+                        "\\("
+                        (mapconcat
+                         'identity
+                         (append
+                          (and to-address (list (regexp-quote to-address)))
+                          (and to-list (list (regexp-quote to-list)))
+                          (and extra-aliases
+                               (if (listp extra-aliases)
+                                   (mapcar 'regexp-quote extra-aliases)
+                                 (list extra-aliases)))
+                          (and split-regexp (list split-regexp)))
+                         "\\|")
+                        "\\)"))
+                 ;; Now create the new SPLIT
+                 (push (append
+                        (list 'any split-regexp)
+                        ;; Generate RESTRICTs for SPLIT-EXCLUDEs.
+                        (if (listp split-exclude)
+                            (apply #'append
+                                   (mapcar (lambda (arg) (list '- arg))
+                                           split-exclude))
+                          (list '- split-exclude))
+                        (list group-clean))
+                       split)
+                 ;; If it matches the empty string, it is a catch-all
+                 (when (string-match split-regexp "")
+                   (setq catch-all nil)))))))))
+    ;; Add catch-all if not crossposting
+    (if (and catch-all no-crosspost)
+       (push catch-all split))
+    ;; Move it to the tail, while arranging that SPLITs appear in the
+    ;; same order as groups.
+    (setq split (reverse split))
+    ;; Decide whether to accept cross-postings or not.
+    (push (if no-crosspost '| '&) split)
+    ;; Even if we can cross-post, catch-all should not get
+    ;; cross-posts.
+    (if (and catch-all (not no-crosspost))
+       (setq split (list '| split catch-all)))
+    split))
+
+(provide 'gnus-mlspl)
+
+;;; gnus-mlspl.el ends here
index ef39c59..36839c8 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-move.el --- commands for moving Gnus from one server to another
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -45,6 +46,7 @@ Update the .newsrc.eld file to reflect the change of nntp server."
 
   ;; First start Gnus.
   (let ((gnus-activate-level 0)
+       (mail-sources nil)
        (nnmail-spool-file nil))
     (gnus))
 
@@ -90,6 +92,8 @@ Update the .newsrc.eld file to reflect the change of nntp server."
        ;; Then we read the headers from the `from-server'.
        (when (and (gnus-request-group group nil from-server)
                   (gnus-active group)
+                  (gnus-uncompress-range
+                   (gnus-active group))
                   (setq type (gnus-retrieve-headers
                               (gnus-uncompress-range
                                (gnus-active group))
@@ -130,7 +134,10 @@ Update the .newsrc.eld file to reflect the change of nntp server."
          ;; into the Gnus info format.
          (setq to-reads
                (gnus-range-add
-                (gnus-compress-sequence (and to-reads (sort to-reads '<)) t)
+                (gnus-compress-sequence
+                 (and (setq to-reads (delq nil to-reads))
+                      (sort to-reads '<))
+                 t)
                 (cons 1 (1- (car to-active)))))
          (gnus-info-set-read info to-reads)
          ;; Do the marks.  I'm sure y'all understand what's
index f310eed..479979e 100644 (file)
@@ -1,9 +1,14 @@
-;;; gnus-msg.el --- mail and post interface for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;;; gnus-msg.el --- mail and post interface for Semi-gnus
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+;;     Katsumi Yamaoka  <yamaoka@jpl.org>
+;;     Kiyokazu SUTO    <suto@merry.xmath.ous.ac.jp>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
 
 (require 'gnus)
 (require 'gnus-ems)
 (require 'message)
 (require 'gnus-art)
+(require 'gnus-util)
 
-;; Added by Sudish Joseph <joseph@cis.ohio-state.edu>.
-(defvar gnus-post-method nil
+(defcustom gnus-post-method 'current
   "*Preferred method for posting USENET news.
-If this variable is nil, Gnus will use the current method to decide
-which method to use when posting.  If it is non-nil, it will override
-the current method.  This method will not be used in mail groups and
-the like, only in \"real\" newsgroups.
 
-The value must be a valid method as discussed in the documentation of
-`gnus-select-method'.  It can also be a list of methods.  If that is
-the case, the user will be queried for what select method to use when
-posting.")
+If this variable is `current' (which is the default), Gnus will use
+the \"current\" select method when posting.  If it is `native', Gnus
+will use the native select method when posting.
 
-(defvar gnus-outgoing-message-group nil
+This method will not be used in mail groups and the like, only in
+\"real\" newsgroups.
+
+If not `native' nor `current', the value must be a valid method as discussed
+in the documentation of `gnus-select-method'.  It can also be a list of
+methods.  If that is the case, the user will be queried for what select
+method to use when posting."
+  :group 'gnus-group-foreign
+  :link '(custom-manual "(gnus)Posting Server")
+  :type `(choice (const native)
+                (const current)
+                (sexp :tag "Methods" ,gnus-select-method)))
+
+(defcustom gnus-outgoing-message-group nil
   "*All outgoing messages will be put in this group.
 If you want to store all your outgoing mail and articles in the group
 \"nnml:archive\", you set this variable to that value.  This variable
@@ -55,18 +69,26 @@ can also be a list of group names.
 If you want to have greater control over what group to put each
 message in, you can set this variable to a function that checks the
 current newsgroup name and then returns a suitable group name (or list
-of names).")
+of names)."
+  :group 'gnus-message
+  :type '(choice (string :tag "Group")
+                (function)))
 
-(defvar gnus-mailing-list-groups nil
-  "*Regexp matching groups that are really mailing lists.
+(defcustom gnus-mailing-list-groups nil
+  "*If non-nil a regexp matching groups that are really mailing lists.
 This is useful when you're reading a mailing list that has been
 gatewayed to a newsgroup, and you want to followup to an article in
-the group.")
+the group."
+  :group 'gnus-message
+  :type '(choice (regexp)
+                (const nil)))
 
-(defvar gnus-add-to-list nil
-  "*If non-nil, add a `to-list' parameter automatically.")
+(defcustom gnus-add-to-list nil
+  "*If non-nil, add a `to-list' parameter automatically."
+  :group 'gnus-message
+  :type 'boolean)
 
-(defvar gnus-crosspost-complaint
+(defcustom gnus-crosspost-complaint
   "Hi,
 
 You posted the article below with the following Newsgroups header:
@@ -82,28 +104,241 @@ Thank you.
 "
   "Format string to be inserted when complaining about crossposts.
 The first %s will be replaced by the Newsgroups header;
-the second with the current group name.")
-
-(defvar gnus-message-setup-hook nil
-  "Hook run after setting up a message buffer.")
+the second with the current group name."
+  :group 'gnus-message
+  :type 'string)
+
+(defcustom gnus-message-setup-hook nil
+  "Hook run after setting up a message buffer."
+  :group 'gnus-message
+  :type 'hook)
+
+(defcustom gnus-bug-create-help-buffer t
+  "*Should we create the *Gnus Help Bug* buffer?"
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-posting-styles nil
+  "*Alist of styles to use when posting.
+See Info node `(gnus)Posting Styles'."
+  :group 'gnus-message
+  :link '(custom-manual "(gnus)Posting Styles")
+  :type '(repeat (cons (choice (regexp)
+                              (variable)
+                              (list (const header)
+                                    (string :tag "Header")
+                                    (regexp :tag "Regexp"))
+                              (function)
+                              (sexp))
+                      (repeat (list
+                               (choice (const signature)
+                                       (const signature-file)
+                                       (const organization)
+                                       (const address)
+                                       (const x-face-file)
+                                       (const name)
+                                       (const body)
+                                       (const import)
+                                       (symbol)
+                                       (string :tag "Header"))
+                               (choice (string)
+                                       (function)
+                                       (variable)
+                                       (sexp)))))))
+
+(defcustom gnus-named-posting-styles nil
+  "Alist mapping names to the user-defined posting styles."
+  :group 'gnus-message
+  :type '(repeat (cons string
+                      (repeat (list
+                               (choice (const signature)
+                                       (const signature-file)
+                                       (const organization)
+                                       (const address)
+                                       (const x-face-file)
+                                       (const name)
+                                       (const body)
+                                       (const import)
+                                       (symbol)
+                                       (string :tag "Header"))
+                               (choice (string)
+                                       (function)
+                                       (variable)
+                                       (sexp)))))))
+
+(defcustom gnus-gcc-mark-as-read nil
+  "If non-nil, automatically mark Gcc articles as read."
+  :version "21.1"
+  :group 'gnus-message
+  :type 'boolean)
+
+(make-obsolete-variable 'gnus-inews-mark-gcc-as-read
+                       'gnus-gcc-mark-as-read)
+
+(defcustom gnus-gcc-externalize-attachments nil
+  "Should local-file attachments be included as external parts in Gcc copies?
+If it is `all', attach files as external parts;
+if a regexp and matches the Gcc group name, attach files as external parts;
+if nil, attach files as normal parts."
+  :version "21.1"
+  :group 'gnus-message
+  :type '(choice (const nil :tag "None")
+                (const all :tag "Any")
+                (string :tag "Regexp")))
+
+(gnus-define-group-parameter
+ posting-charset-alist
+ :type list
+ :function-document
+ "Return the permitted unencoded charsets for posting of GROUP."
+ :variable gnus-group-posting-charset-alist
+ :variable-default
+ '(("^\\(no\\|fr\\)\\.[^,]*\\(,[ \t\n]*\\(no\\|fr\\)\\.[^,]*\\)*$" iso-8859-1 (iso-8859-1))
+   ("^\\(fido7\\|relcom\\)\\.[^,]*\\(,[ \t\n]*\\(fido7\\|relcom\\)\\.[^,]*\\)*$" koi8-r (koi8-r))
+   (message-this-is-mail nil nil)
+   (message-this-is-news nil t))
+ :variable-document
+ "Alist of regexps and permitted unencoded charsets for posting.
+Each element of the alist has the form (TEST HEADER BODY-LIST), where
+TEST is either a regular expression matching the newsgroup header or a
+variable to query,
+HEADER is the charset which may be left unencoded in the header (nil
+means encode all charsets),
+BODY-LIST is a list of charsets which may be encoded using 8bit
+content-transfer encoding in the body, or one of the special values
+nil (always encode using quoted-printable) or t (always use 8bit).
+
+Note that any value other than nil for HEADER infringes some RFCs, so
+use this option with care."
+ :variable-group gnus-charset
+ :variable-type
+ '(repeat (list :tag "Permitted unencoded charsets"
+               (choice :tag "Where"
+                       (regexp :tag "Group")
+                       (const :tag "Mail message" :value message-this-is-mail)
+                       (const :tag "News article" :value message-this-is-news))
+               (choice :tag "Header"
+                       (const :tag "None" nil)
+                       (symbol :tag "Charset"))
+               (choice :tag "Body"
+                       (const :tag "Any" :value t)
+                       (const :tag "None" :value nil)
+                       (repeat :tag "Charsets"
+                               (symbol :tag "Charset")))))
+ :parameter-type '(choice :tag "Permitted unencoded charsets"
+                         :value nil
+                         (repeat (symbol)))
+ :parameter-document       "\
+List of charsets that are permitted to be unencoded.")
+
+(defcustom gnus-debug-files
+  '("gnus.el" "gnus-sum.el" "gnus-group.el"
+    "gnus-art.el" "gnus-start.el" "gnus-async.el"
+    "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el"
+    "gnus-agent.el" "gnus-cache.el" "gnus-srvr.el"
+    "mm-util.el" "mm-decode.el" "nnmail.el" "nntp.el" "message.el")
+  "Files whose variables will be reported in `gnus-bug'."
+  :version "21.1"
+  :group 'gnus-message
+  :type '(repeat (string :tag "File")))
+
+(defcustom gnus-debug-exclude-variables
+  '(mm-mime-mule-charset-alist
+    nnmail-split-fancy message-minibuffer-local-map)
+  "Variables that should not be reported in `gnus-bug'."
+  :version "21.1"
+  :group 'gnus-message
+  :type '(repeat (symbol :tag "Variable")))
+
+(defcustom gnus-discouraged-post-methods
+  '(nndraft nnml nnimap nnmaildir nnmh nnfolder nndir)
+  "A list of back ends that are not used in \"real\" newsgroups.
+This variable is used only when `gnus-post-method' is `current'."
+  :version "21.3"
+  :group 'gnus-group-foreign
+  :type '(repeat (symbol :tag "Back end")))
+
+(defcustom gnus-message-replysign
+  nil
+  "Automatically sign replies to signed messages.
+See also the `mml-default-sign-method' variable."
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-message-replyencrypt
+  nil
+  "Automatically encrypt replies to encrypted messages.
+See also the `mml-default-encrypt-method' variable."
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-message-replysignencrypted
+  t
+  "Setting this causes automatically encrypted messages to also be signed."
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-confirm-mail-reply-to-news nil
+  "If non-nil, Gnus requests confirmation when replying to news.
+This is done because new users often reply by mistake when reading
+news.
+This can also be a function receiving the group name as the only
+parameter which should return non-nil iff a confirmation is needed, or
+a regexp, in which case a confirmation is asked for iff the group name
+matches the regexp."
+  :group 'gnus-message
+  :type '(choice (const :tag "No" nil)
+                (const :tag "Yes" t)
+                (regexp :tag "Iff group matches regexp")
+                (function :tag "Iff function evaluates to non-nil")))
+
+(defcustom gnus-confirm-treat-mail-like-news
+  nil
+  "If non-nil, Gnus will treat mail like news with regard to confirmation
+when replying by mail.  See the `gnus-confirm-mail-reply-to-news' variable
+for fine-tuning this.
+If nil, Gnus will never ask for confirmation if replying to mail."
+  :group 'gnus-message
+  :type 'boolean)
+
+(defcustom gnus-summary-resend-default-address t
+  "If non-nil, Gnus tries to suggest a default address to resend to.
+If nil, the address field will always be empty after invoking
+`gnus-summary-resend-message'."
+  :group 'gnus-message
+  :type 'boolean)
 
 ;;; Internal variables.
 
+(defvar gnus-inhibit-posting-styles nil
+  "Inhibit the use of posting styles.")
+
+(defvar gnus-article-yanked-articles nil)
 (defvar gnus-message-buffer "*Mail Gnus*")
 (defvar gnus-article-copy nil)
+(defvar gnus-check-before-posting nil)
 (defvar gnus-last-posting-server nil)
 (defvar gnus-message-group-art nil)
 
+(defvar gnus-msg-force-broken-reply-to nil)
+
 (defconst gnus-bug-message
-  "Sending a bug report to the Gnus Towers.
+  (format "Sending a bug report to the Gnus Towers.
+========================================
+
+This gnus is the %s%s.
+If you think the bug is a Semi-gnus bug, send a bug report to Semi-gnus
+Developers. (the addresses below are mailing list addresses)
+
 ========================================
 
 The buffer below is a mail buffer.  When you press `C-c C-c', it will
 be sent to the Gnus Bug Exterminators.
 
-At the bottom of the buffer you'll see lots of variable settings.
-Please do not delete those.  They will tell the Bug People what your
-environment is, so that it will be easier to locate the bugs.
+The thing near the bottom of the buffer is how the environment
+settings will be included in the mail.  Please do not delete that.
+They will tell the Bug People what your environment is, so that it
+will be easier to locate the bugs.
 
 If you have found a bug that makes Emacs go \"beep\", set
 debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
@@ -112,7 +347,11 @@ and include the backtrace in your bug report.
 Please describe the bug in annoying, painstaking detail.
 
 Thank you for your help in stamping out bugs.
-")
+"
+         gnus-product-name
+         (if (string= gnus-product-name "Semi-gnus")
+             ""
+           ", a modified version of Semi-gnus")))
 
 (eval-and-compile
   (autoload 'gnus-uu-post-news "gnus-uu" nil t)
@@ -128,87 +367,271 @@ Thank you for your help in stamping out bugs.
 
 (gnus-define-keys (gnus-summary-send-map "S" gnus-summary-mode-map)
   "p" gnus-summary-post-news
+  "i" gnus-summary-news-other-window
   "f" gnus-summary-followup
   "F" gnus-summary-followup-with-original
   "c" gnus-summary-cancel-article
   "s" gnus-summary-supersede-article
   "r" gnus-summary-reply
+  "y" gnus-summary-yank-message
   "R" gnus-summary-reply-with-original
   "w" gnus-summary-wide-reply
   "W" gnus-summary-wide-reply-with-original
+  "v" gnus-summary-very-wide-reply
+  "V" gnus-summary-very-wide-reply-with-original
   "n" gnus-summary-followup-to-mail
   "N" gnus-summary-followup-to-mail-with-original
   "m" gnus-summary-mail-other-window
   "u" gnus-uu-post-news
   "\M-c" gnus-summary-mail-crosspost-complaint
+  "Br" gnus-summary-reply-broken-reply-to
+  "BR" gnus-summary-reply-broken-reply-to-with-original
   "om" gnus-summary-mail-forward
   "op" gnus-summary-post-forward
-  "Om" gnus-uu-digest-mail-forward
-  "Op" gnus-uu-digest-post-forward)
+  "Om" gnus-summary-digest-mail-forward
+  "Op" gnus-summary-digest-post-forward
+  "P" gnus-summary-execute-command-with-posting-style)
 
 (gnus-define-keys (gnus-send-bounce-map "D" gnus-summary-send-map)
   "b" gnus-summary-resend-bounced-mail
   ;; "c" gnus-summary-send-draft
-  "r" gnus-summary-resend-message)
+  "r" gnus-summary-resend-message
+  "e" gnus-summary-resend-message-edit)
 
 ;;; Internal functions.
 
+(defun gnus-inews-make-draft ()
+  `(lambda ()
+     (gnus-inews-make-draft-meta-information
+      ,gnus-newsgroup-name ',gnus-article-reply)))
+
 (defvar gnus-article-reply nil)
 (defmacro gnus-setup-message (config &rest forms)
   (let ((winconf (make-symbol "gnus-setup-message-winconf"))
        (buffer (make-symbol "gnus-setup-message-buffer"))
-       (article (make-symbol "gnus-setup-message-article")))
+       (article (make-symbol "gnus-setup-message-article"))
+       (yanked (make-symbol "gnus-setup-yanked-articles"))
+       (group (make-symbol "gnus-setup-message-group")))
     `(let ((,winconf (current-window-configuration))
           (,buffer (buffer-name (current-buffer)))
-          (,article (and gnus-article-reply (gnus-summary-article-number)))
+          (,article gnus-article-reply)
+          (,yanked gnus-article-yanked-articles)
+          (,group gnus-newsgroup-name)
           (message-header-setup-hook
-           (copy-sequence message-header-setup-hook)))
+           (copy-sequence message-header-setup-hook))
+          (message-mode-hook (copy-sequence message-mode-hook))
+          (message-startup-parameter-alist
+           '((reply-buffer . gnus-copy-article-buffer)
+             (original-buffer . gnus-original-article-buffer)
+             (user-agent . Gnus))))
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
        (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc)
+       ;; #### FIXME: for a reason that I did not manage to identify yet,
+       ;; the variable `gnus-newsgroup-name' does not honor a dynamically
+       ;; scoped or setq'ed value from a caller like `C-u gnus-summary-mail'.
+       ;; After evaluation of @forms below, it gets the value we actually want
+       ;; to override, and the posting styles are used. For that reason, I've
+       ;; added an optional argument to `gnus-configure-posting-styles' to
+       ;; make sure that the correct value for the group name is used. -- drv
+       (add-hook 'message-mode-hook
+                (lambda ()
+                  (gnus-configure-posting-styles ,group)))
+       (gnus-pull ',(intern gnus-draft-meta-information-header)
+                 message-required-headers)
+       (when (and ,group
+                 (not (string= ,group "")))
+        (push (cons
+               (intern gnus-draft-meta-information-header)
+               (gnus-inews-make-draft))
+              message-required-headers))
        (unwind-protect
           (progn
             ,@forms)
-        (gnus-inews-add-send-actions ,winconf ,buffer ,article)
+        (gnus-inews-add-send-actions ,winconf ,buffer ,article ,config
+                                     ,yanked)
         (setq gnus-message-buffer (current-buffer))
         (set (make-local-variable 'gnus-message-group-art)
-             (cons ,gnus-newsgroup-name ,article))
-        (make-local-variable 'gnus-newsgroup-name)
+             (cons ,group ,article))
+        (set (make-local-variable 'gnus-newsgroup-name) ,group)
+        (gnus-maybe-setup-default-charset)
         (gnus-run-hooks 'gnus-message-setup-hook))
+       (message-hide-headers)
+       (gnus-add-buffer)
        (gnus-configure-windows ,config t)
+       (run-hooks 'post-command-hook)
        (set-buffer-modified-p nil))))
 
-(defun gnus-inews-add-send-actions (winconf buffer article)
-  (make-local-hook 'message-sent-hook)
-  (add-hook 'message-sent-hook 'gnus-inews-do-gcc nil t)
+(defun gnus-inews-make-draft-meta-information (group article)
+  (concat "(\"" group "\" "
+         (if article (number-to-string
+                      (if (listp article)
+                          (car article)
+                        article)) "\"\"")
+         ")"))
+
+;;;###autoload
+(defun gnus-msg-mail (&optional to subject other-headers continue
+                               switch-action yank-action send-actions)
+  "Start editing a mail message to be sent.
+Like `message-mail', but with Gnus paraphernalia, particularly the
+Gcc: header for archiving purposes."
+  (interactive)
+  (let ((buf (current-buffer))
+       mail-buf)
+    (gnus-setup-message 'message
+      (message-mail to subject other-headers continue
+                   nil yank-action send-actions))
+    (when switch-action
+      (setq mail-buf (current-buffer))
+      (switch-to-buffer buf)
+      (apply switch-action mail-buf nil)))
+  ;; COMPOSEFUNC should return t if succeed.  Undocumented ???
+  t)
+
+(defvar save-selected-window-window)
+
+;;;###autoload
+(defun gnus-button-mailto (address)
+  "Mail to ADDRESS."
+  (set-buffer (gnus-copy-article-buffer))
+  (gnus-setup-message 'message
+    (message-reply address))
+  (and (boundp 'save-selected-window-window)
+       (not (window-live-p save-selected-window-window))
+       (setq save-selected-window-window (selected-window))))
+
+;;;###autoload
+(defun gnus-button-reply (&optional to-address wide)
+  "Like `message-reply'."
+  (interactive)
+  (gnus-setup-message 'message
+    (message-reply to-address wide))
+  (and (boundp 'save-selected-window-window)
+       (not (window-live-p save-selected-window-window))
+       (setq save-selected-window-window (selected-window))))
+
+;;;###autoload
+(define-mail-user-agent 'gnus-user-agent
+  'gnus-msg-mail 'message-send-and-exit
+  'message-kill-buffer 'message-send-hook)
+
+(defun gnus-setup-posting-charset (group)
+  (let ((alist gnus-group-posting-charset-alist)
+       (group (or group ""))
+       elem)
+    (when group
+      (catch 'found
+       (while (setq elem (pop alist))
+         (when (or (and (stringp (car elem))
+                        (string-match (car elem) group))
+                   (and (functionp (car elem))
+                        (funcall (car elem) group))
+                   (and (symbolp (car elem))
+                        (symbol-value (car elem))))
+           (throw 'found (cons (cadr elem) (caddr elem)))))))))
+
+(defun gnus-inews-add-send-actions (winconf buffer article
+                                           &optional config yanked)
+  (gnus-make-local-hook 'message-sent-hook)
+  (add-hook 'message-sent-hook (if gnus-agent 'gnus-agent-possibly-do-gcc
+                                'gnus-inews-do-gcc) nil t)
+  (when gnus-agent
+    (gnus-make-local-hook 'message-header-hook)
+    (add-hook 'message-header-hook 'gnus-agent-possibly-save-gcc nil t))
   (setq message-post-method
        `(lambda (arg)
           (gnus-post-method arg ,gnus-newsgroup-name)))
-  (setq message-newsreader (setq message-mailer (gnus-extended-version)))
-  (message-add-action
-   `(set-window-configuration ,winconf) 'exit 'postpone 'kill)
-  (message-add-action
-   `(when (buffer-name (get-buffer ,buffer))
-      (save-excursion
-       (set-buffer (get-buffer ,buffer))
-       ,(when article
-          `(gnus-summary-mark-article-as-replied ,article))))
-   'send))
+  (setq message-user-agent (gnus-message-make-user-agent))
+  (unless message-use-multi-frames
+    (message-add-action
+     `(if (gnus-buffer-exists-p ,buffer)
+         (set-window-configuration ,winconf))
+     'exit 'postpone 'kill))
+  (let ((to-be-marked (cond
+                      (yanked
+                       (mapcar
+                        (lambda (x) (if (listp x) (car x) x)) yanked))
+                      (article (if (listp article) article (list article)))
+                      (t nil))))
+    (message-add-action
+     `(when (gnus-buffer-exists-p ,buffer)
+       (save-excursion
+         (set-buffer ,buffer)
+         ,(when to-be-marked
+            (if (eq config 'forward)
+                `(gnus-summary-mark-article-as-forwarded ',to-be-marked)
+              `(gnus-summary-mark-article-as-replied ',to-be-marked)))))
+     'send)))
 
 (put 'gnus-setup-message 'lisp-indent-function 1)
 (put 'gnus-setup-message 'edebug-form-spec '(form body))
 
 ;;; Post news commands of Gnus group mode and summary mode
 
-(defun gnus-group-mail ()
-  "Start composing a mail."
-  (interactive)
-  (gnus-setup-message 'message
-    (message-mail)))
+(defun gnus-group-mail (&optional arg)
+  "Start composing a mail.
+If ARG, use the group under the point to find a posting style.
+If ARG is 1, prompt for a group name to find the posting style."
+  (interactive "P")
+  ;; We can't `let' gnus-newsgroup-name here, since that leads
+  ;; to local variables leaking.
+  (let ((group gnus-newsgroup-name)
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy)
+       (buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (setq gnus-newsgroup-name
+               (if arg
+                   (if (= 1 (prefix-numeric-value arg))
+                       (completing-read "Use posting style of group: "
+                                        gnus-active-hashtb nil
+                                        (gnus-read-active-file-p))
+                     (gnus-group-group-name))
+                 ""))
+         ;; #### see comment in gnus-setup-message -- drv
+         (gnus-setup-message 'message (message-mail)))
+      (save-excursion
+       (set-buffer buffer)
+       (setq gnus-newsgroup-name group)))))
+
+(defun gnus-group-news (&optional arg)
+  "Start composing a news.
+If ARG, post to group under point.
+If ARG is 1, prompt for group name to post to.
+
+This function prepares a news even when using mail groups.  This is useful
+for posting messages to mail groups without actually sending them over the
+network.  The corresponding back end must have a 'request-post method."
+  (interactive "P")
+  ;; We can't `let' gnus-newsgroup-name here, since that leads
+  ;; to local variables leaking.
+  (let ((group gnus-newsgroup-name)
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy)
+       (buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (setq gnus-newsgroup-name
+               (if arg
+                   (if (= 1 (prefix-numeric-value arg))
+                       (completing-read "Use group: "
+                                        gnus-active-hashtb nil
+                                        (gnus-read-active-file-p))
+                     (gnus-group-group-name))
+                 ""))
+         ;; #### see comment in gnus-setup-message -- drv
+         (gnus-setup-message 'message
+           (message-news (gnus-group-real-name gnus-newsgroup-name))))
+      (save-excursion
+       (set-buffer buffer)
+       (setq gnus-newsgroup-name group)))))
 
 (defun gnus-group-post-news (&optional arg)
-  "Start composing a news message.
-If ARG, post to the group under point.
-If ARG is 1, prompt for a group name."
+  "Start composing a message (a news by default).
+If ARG, post to group under point.  If ARG is 1, prompt for group name.
+Depending on the selected group, the message might be either a mail or
+a news."
   (interactive "P")
   ;; Bind this variable here to make message mode hooks work ok.
   (let ((gnus-newsgroup-name
@@ -217,22 +640,110 @@ If ARG is 1, prompt for a group name."
                 (completing-read "Newsgroup: " gnus-active-hashtb nil
                                  (gnus-read-active-file-p))
               (gnus-group-group-name))
-          "")))
+          ""))
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy))
+    (gnus-post-news 'post gnus-newsgroup-name nil nil nil nil
+                   (string= gnus-newsgroup-name ""))))
+
+(defun gnus-summary-mail-other-window (&optional arg)
+  "Start composing a mail in another window.
+Use the posting of the current group by default.
+If ARG, don't do that.  If ARG is 1, prompt for group name to find the
+posting style."
+  (interactive "P")
+  ;; We can't `let' gnus-newsgroup-name here, since that leads
+  ;; to local variables leaking.
+  (let ((group gnus-newsgroup-name)
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy)
+       (buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (setq gnus-newsgroup-name
+               (if arg
+                   (if (= 1 (prefix-numeric-value arg))
+                       (completing-read "Use group: "
+                                        gnus-active-hashtb nil
+                                        (gnus-read-active-file-p))
+                     "")
+                 gnus-newsgroup-name))
+         ;; #### see comment in gnus-setup-message -- drv
+         (gnus-setup-message 'message (message-mail)))
+      (save-excursion
+       (set-buffer buffer)
+       (setq gnus-newsgroup-name group)))))
+
+(defun gnus-summary-news-other-window (&optional arg)
+  "Start composing a news in another window.
+Post to the current group by default.
+If ARG, don't do that.  If ARG is 1, prompt for group name to post to.
+
+This function prepares a news even when using mail groups.  This is useful
+for posting messages to mail groups without actually sending them over the
+network.  The corresponding back end must have a 'request-post method."
+  (interactive "P")
+  ;; We can't `let' gnus-newsgroup-name here, since that leads
+  ;; to local variables leaking.
+  (let ((group gnus-newsgroup-name)
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy)
+       (buffer (current-buffer)))
+    (unwind-protect
+       (progn
+         (setq gnus-newsgroup-name
+               (if arg
+                   (if (= 1 (prefix-numeric-value arg))
+                       (completing-read "Use group: "
+                                        gnus-active-hashtb nil
+                                        (gnus-read-active-file-p))
+                     "")
+                 gnus-newsgroup-name))
+         ;; #### see comment in gnus-setup-message -- drv
+         (gnus-setup-message 'message
+           (progn
+             (message-news (gnus-group-real-name gnus-newsgroup-name))
+             (set (make-local-variable 'gnus-discouraged-post-methods)
+                  (delq
+                   (car (gnus-find-method-for-group gnus-newsgroup-name))
+                   (copy-sequence gnus-discouraged-post-methods))))))
+      (save-excursion
+       (set-buffer buffer)
+       (setq gnus-newsgroup-name group)))))
+
+(defun gnus-summary-post-news (&optional arg)
+  "Start composing a message.  Post to the current group by default.
+If ARG, don't do that.  If ARG is 1, prompt for a group name to post to.
+Depending on the selected group, the message might be either a mail or
+a news."
+  (interactive "P")
+  ;; Bind this variable here to make message mode hooks work ok.
+  (let ((gnus-newsgroup-name
+        (if arg
+            (if (= 1 (prefix-numeric-value arg))
+                (completing-read "Newsgroup: " gnus-active-hashtb nil
+                                 (gnus-read-active-file-p))
+              "")
+          gnus-newsgroup-name))
+       ;; make sure last viewed article doesn't affect posting styles:
+       (gnus-article-copy))
     (gnus-post-news 'post gnus-newsgroup-name)))
 
-(defun gnus-summary-post-news ()
-  "Start composing a news message."
-  (interactive)
-  (gnus-post-news 'post gnus-newsgroup-name))
 
 (defun gnus-summary-followup (yank &optional force-news)
   "Compose a followup to an article.
-If prefix argument YANK is non-nil, original article is yanked automatically."
+If prefix argument YANK is non-nil, the original article is yanked
+automatically.
+YANK is a list of elements, where the car of each element is the
+article number, and the cdr is the string to be yanked."
   (interactive
    (list (and current-prefix-arg
              (gnus-summary-work-articles 1))))
   (when yank
-    (gnus-summary-goto-subject (car yank)))
+    (gnus-summary-goto-subject
+     (if (listp (car yank))
+        (caar yank)
+       (car yank))))
   (save-window-excursion
     (gnus-summary-select-article))
   (let ((headers (gnus-summary-article-header (gnus-summary-article-number)))
@@ -240,7 +751,8 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
     ;; Send a followup.
     (gnus-post-news nil gnus-newsgroup-name
                    headers gnus-article-buffer
-                   yank nil force-news)))
+                   yank nil force-news)
+    (gnus-summary-handle-replysign)))
 
 (defun gnus-summary-followup-with-original (n &optional force-news)
   "Compose a followup to an article and include the original article."
@@ -260,21 +772,62 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
   (gnus-summary-followup (gnus-summary-work-articles arg) t))
 
 (defun gnus-inews-yank-articles (articles)
-  (let (beg article)
+  (let (beg article yank-string
+           (more-than-one (cdr articles))
+           (cur (current-buffer))
+           refs window)
     (message-goto-body)
     (while (setq article (pop articles))
+      (when (listp article)
+       (setq yank-string (nth 1 article)
+             article (nth 0 article)))
       (save-window-excursion
        (set-buffer gnus-summary-buffer)
        (gnus-summary-select-article nil nil nil article)
        (gnus-summary-remove-process-mark article))
-      (gnus-copy-article-buffer)
+
+      ;; Gathering references.
+      (when more-than-one
+       (setq refs (message-list-references
+                   refs
+                   (mail-header-references gnus-current-headers)
+                   (mail-header-message-id gnus-current-headers)))
+       (when message-use-multi-frames
+         (when (setq window (get-buffer-window cur t))
+           (select-frame (window-frame window)))))
+
+      (gnus-copy-article-buffer nil yank-string)
       (let ((message-reply-buffer gnus-article-copy)
-           (message-reply-headers gnus-current-headers))
+           (message-reply-headers
+            ;; The headers are decoded.
+            (with-current-buffer gnus-article-copy
+              (save-restriction
+                (nnheader-narrow-to-headers)
+                (nnheader-parse-naked-head)))))
        (message-yank-original)
        (setq beg (or beg (mark t))))
       (when articles
        (insert "\n")))
     (push-mark)
+
+    ;; Replace with the gathered references.
+    (when refs
+      (push-mark beg)
+      (save-restriction
+       (message-narrow-to-headers)
+       (let ((case-fold-search t))
+         (if (re-search-forward "^References:\\([\t ]+.+\n\\)+" nil t)
+             (replace-match "")
+           (goto-char (point-max))))
+       (mail-header-format
+        (list (or (assq 'References message-header-format-alist)
+                  '(References . message-shorten-references)))
+        (list (cons 'References
+                    (mapconcat 'identity (nreverse refs) " "))))
+       (backward-delete-char 1))
+      (setq beg (mark t))
+      (pop-mark))
+
     (goto-char beg)))
 
 (defun gnus-summary-cancel-article (&optional n symp)
@@ -286,12 +839,14 @@ post using the current select method."
   (let ((articles (gnus-summary-work-articles n))
        (message-post-method
         `(lambda (arg)
-           (gnus-post-method (not (eq symp 'a)) ,gnus-newsgroup-name)))
+           (gnus-post-method (eq ',symp 'a) ,gnus-newsgroup-name)))
        article)
     (while (setq article (pop articles))
       (when (gnus-summary-select-article t nil nil article)
-       (when (gnus-eval-in-buffer-window gnus-original-article-buffer
-               (message-cancel-news))
+       (when (gnus-eval-in-buffer-window gnus-article-buffer
+               (save-excursion
+                 (set-buffer gnus-original-article-buffer)
+                 (message-cancel-news)))
          (gnus-summary-mark-as-read article gnus-canceled-mark)
          (gnus-cache-remove-article 1))
        (gnus-article-hide-headers-if-wanted))
@@ -309,89 +864,128 @@ header line with the old Message-ID."
       (message-supersede)
       (push
        `((lambda ()
-          (when (buffer-name (get-buffer ,gnus-summary-buffer))
+          (when (gnus-buffer-exists-p ,gnus-summary-buffer)
             (save-excursion
-              (set-buffer (get-buffer ,gnus-summary-buffer))
+              (set-buffer ,gnus-summary-buffer)
               (gnus-cache-possibly-remove-article ,article nil nil nil t)
               (gnus-summary-mark-as-read ,article gnus-canceled-mark)))))
        message-send-actions))))
 
 \f
 
-(defun gnus-copy-article-buffer (&optional article-buffer)
+(defun gnus-copy-article-buffer (&optional article-buffer yank-string)
   ;; make a copy of the article buffer with all text properties removed
   ;; this copy is in the buffer gnus-article-copy.
   ;; if ARTICLE-BUFFER is nil, gnus-article-buffer is used
   ;; this buffer should be passed to all mail/news reply/post routines.
-  (setq gnus-article-copy (get-buffer-create " *gnus article copy*"))
-  (buffer-disable-undo gnus-article-copy)
-  (or (memq gnus-article-copy gnus-buffer-list)
-      (push gnus-article-copy gnus-buffer-list))
+  (setq gnus-article-copy (gnus-get-buffer-create " *gnus article copy*"))
+  (save-excursion
+    (set-buffer gnus-article-copy)
+    (set-buffer-multibyte t))
   (let ((article-buffer (or article-buffer gnus-article-buffer))
-       end beg contents)
+       end beg)
     (if (not (and (get-buffer article-buffer)
-                 (buffer-name (get-buffer article-buffer))))
+                 (gnus-buffer-exists-p article-buffer)))
        (error "Can't find any article buffer")
       (save-excursion
        (set-buffer article-buffer)
-       (save-restriction
-         ;; Copy over the (displayed) article buffer, delete
-         ;; hidden text and remove text properties.
-         (widen)
-         (copy-to-buffer gnus-article-copy (point-min) (point-max))
-         (set-buffer gnus-article-copy)
-         (gnus-article-delete-text-of-type 'annotation)
-         (gnus-remove-text-with-property 'gnus-prev)
-         (gnus-remove-text-with-property 'gnus-next)
-         (insert
-          (prog1
-              (format "%s" (buffer-string))
-            (erase-buffer)))
-         ;; Find the original headers.
-         (set-buffer gnus-original-article-buffer)
-         (goto-char (point-min))
-         (while (looking-at message-unix-mail-delimiter)
-           (forward-line 1))
-         (setq beg (point))
-         (setq end (or (search-forward "\n\n" nil t) (point)))
-         ;; Delete the headers from the displayed articles.
-         (set-buffer gnus-article-copy)
-         (delete-region (goto-char (point-min))
-                        (or (search-forward "\n\n" nil t) (point)))
-         ;; Insert the original article headers.
-         (insert-buffer-substring gnus-original-article-buffer beg end)
-         (gnus-article-decode-rfc1522)))
+       (let ((gnus-newsgroup-charset (or gnus-article-charset
+                                         gnus-newsgroup-charset))
+             (gnus-newsgroup-ignored-charsets
+              (or gnus-article-ignored-charsets
+                  gnus-newsgroup-ignored-charsets)))
+         (save-restriction
+           ;; Copy over the (displayed) article buffer, delete
+           ;; hidden text and remove text properties.
+           (widen)
+           (copy-to-buffer gnus-article-copy (point-min) (point-max))
+           (set-buffer gnus-article-copy)
+           ;; There's invisible and intangible text in T-gnus.  Especially,
+           ;; if there is a boundary line (X-Boundary: ------------------),
+           ;; in the end of a header, it will cause a serious problem.
+           (add-text-properties (point-min) (point-max)
+                                '(invisible nil intangible nil))
+           (when yank-string
+             (message-goto-body)
+             (delete-region (point) (point-max))
+             (insert yank-string))
+           ;; Encode bitmap smileys to ordinary text.
+           ;; Possibly, the original text might be restored.
+           (static-unless (featurep 'xemacs)
+             (when (featurep 'smiley-mule)
+               (smiley-encode-buffer)))
+           (gnus-article-delete-text-of-type 'annotation)
+           (gnus-remove-text-with-property 'gnus-prev)
+           (gnus-remove-text-with-property 'gnus-next)
+           (gnus-remove-text-with-property 'gnus-decoration)
+           (gnus-remove-text-with-property 'x-face-mule-bitmap-image)
+           (insert
+            (prog1
+                (static-if (featurep 'xemacs)
+                    ;; Revome smiley extents for (possibly) XEmacs 21.1.
+                    (format "%s"
+                            (buffer-substring-no-properties (point-min)
+                                                            (point-max)))
+                  (buffer-substring-no-properties (point-min) (point-max)))
+              (erase-buffer)))
+           ;; Find the original headers.
+           (set-buffer gnus-original-article-buffer)
+           (goto-char (point-min))
+           (while (looking-at message-unix-mail-delimiter)
+             (forward-line 1))
+           (let ((mail-header-separator ""))
+             (setq beg (point)
+                   end (or (message-goto-body)
+                           ;; There may be just a header.
+                           (point-max))))
+           ;; Delete the headers from the displayed articles.
+           (set-buffer gnus-article-copy)
+           (let ((mail-header-separator ""))
+             (delete-region (goto-char (point-min))
+                            (or (message-goto-body) (point-max))))
+           ;; Insert the original article headers.
+           (insert-buffer-substring gnus-original-article-buffer beg end)
+           ;; Decode charsets.
+           (let ((gnus-article-decode-hook
+                  (delq 'article-decode-charset
+                        (copy-sequence gnus-article-decode-hook))))
+             ;; Needed for T-gnus.
+             (add-hook 'gnus-article-decode-hook
+                       'article-decode-encoded-words)
+             (run-hooks 'gnus-article-decode-hook)))))
       gnus-article-copy)))
 
 (defun gnus-post-news (post &optional group header article-buffer yank subject
                            force-news)
   (when article-buffer
     (gnus-copy-article-buffer))
-  (let ((gnus-article-reply article-buffer)
+  (let ((gnus-article-reply (and article-buffer (gnus-summary-article-number)))
+       (gnus-article-yanked-articles yank)
        (add-to-list gnus-add-to-list))
     (gnus-setup-message (cond (yank 'reply-yank)
                              (article-buffer 'reply)
                              (t 'message))
       (let* ((group (or group gnus-newsgroup-name))
+            (charset (gnus-group-name-charset nil group))
             (pgroup group)
             to-address to-group mailing-list to-list
             newsgroup-p)
        (when group
-         (setq to-address (gnus-group-find-parameter group 'to-address)
+         (setq to-address (gnus-parameter-to-address group)
                to-group (gnus-group-find-parameter group 'to-group)
-               to-list (gnus-group-find-parameter group 'to-list)
+               to-list (gnus-parameter-to-list group)
                newsgroup-p (gnus-group-find-parameter group 'newsgroup)
                mailing-list (when gnus-mailing-list-groups
                               (string-match gnus-mailing-list-groups group))
-               group (gnus-group-real-name group)))
+               group (gnus-group-name-decode (gnus-group-real-name group)
+                                             charset)))
        (if (or (and to-group
                     (gnus-news-group-p to-group))
                newsgroup-p
                force-news
                (and (gnus-news-group-p
                      (or pgroup gnus-newsgroup-name)
-                     (if header (mail-header-number header)
-                       gnus-current-article))
+                     (or header gnus-current-article))
                     (not mailing-list)
                     (not to-list)
                     (not to-address)))
@@ -399,7 +993,14 @@ header line with the old Message-ID."
            (if post
                (message-news (or to-group group))
              (set-buffer gnus-article-copy)
-             (message-followup (if (or newsgroup-p force-news) nil to-group)))
+             (gnus-msg-treat-broken-reply-to)
+             (message-followup (if (or newsgroup-p force-news)
+                                   (if (save-restriction
+                                         (article-narrow-to-head)
+                                         (message-fetch-field "newsgroups"))
+                                       nil
+                                     "")
+                                 to-group)))
          ;; The is mail.
          (if post
              (progn
@@ -412,50 +1013,71 @@ header line with the old Message-ID."
                  (push (list 'gnus-inews-add-to-address pgroup)
                        message-send-actions)))
            (set-buffer gnus-article-copy)
-           (message-wide-reply to-address
-                               (gnus-group-find-parameter
-                                gnus-newsgroup-name 'broken-reply-to))))
+           (gnus-msg-treat-broken-reply-to)
+           (message-wide-reply to-address)))
        (when yank
          (gnus-inews-yank-articles yank))))))
 
+(defun gnus-msg-treat-broken-reply-to (&optional force)
+  "Remove the Reply-to header if broken-reply-to."
+  (when (or force
+           (gnus-group-find-parameter
+            gnus-newsgroup-name 'broken-reply-to))
+    (save-restriction
+      (message-narrow-to-head)
+      (message-remove-header "reply-to"))))
+
 (defun gnus-post-method (arg group &optional silent)
   "Return the posting method based on GROUP and ARG.
 If SILENT, don't prompt the user."
-  (let ((group-method (gnus-find-method-for-group group)))
+  (let ((gnus-post-method (or (gnus-parameter-post-method group)
+                             gnus-post-method))
+       (group-method (gnus-find-method-for-group group)))
     (cond
      ;; If the group-method is nil (which shouldn't happen) we use
      ;; the default method.
      ((null group-method)
-      (or gnus-post-method gnus-select-method message-post-method))
-     ;; We want this group's method.
+      (or (and (listp gnus-post-method)        ;If not current/native/nil
+              (not (listp (car gnus-post-method))) ; and not a list of methods
+              gnus-post-method)        ;then use it.
+         gnus-select-method
+         message-post-method))
+     ;; We want the inverse of the default
      ((and arg (not (eq arg 0)))
-      group-method)
+      (if (eq gnus-post-method 'current)
+         gnus-select-method
+       group-method))
      ;; We query the user for a post method.
      ((or arg
-         (and gnus-post-method
+         (and (listp gnus-post-method)
               (listp (car gnus-post-method))))
       (let* ((methods
              ;; Collect all methods we know about.
              (append
-              (when gnus-post-method
+              (when (listp gnus-post-method)
                 (if (listp (car gnus-post-method))
                     gnus-post-method
                   (list gnus-post-method)))
               gnus-secondary-select-methods
+              (mapcar 'cdr gnus-server-alist)
+              (mapcar 'car gnus-opened-servers)
               (list gnus-select-method)
               (list group-method)))
             method-alist post-methods method)
        ;; Weed out all mail methods.
        (while methods
          (setq method (gnus-server-get-method "" (pop methods)))
-         (when (or (gnus-method-option-p method 'post)
-                   (gnus-method-option-p method 'post-mail))
+         (when (and (or (gnus-method-option-p method 'post)
+                        (gnus-method-option-p method 'post-mail))
+                    (not (member method post-methods)))
            (push method post-methods)))
        ;; Create a name-method alist.
        (setq method-alist
              (mapcar
               (lambda (m)
-                (list (concat (cadr m) " (" (symbol-name (car m)) ")") m))
+                (if (equal (cadr m) "")
+                    (list (symbol-name (car m)) m)
+                  (list (concat (cadr m) " (" (symbol-name (car m)) ")") m)))
               post-methods))
        ;; Query the user.
        (cadr
@@ -470,75 +1092,121 @@ If SILENT, don't prompt the user."
                   (cons (or gnus-last-posting-server "") 0))))
          method-alist))))
      ;; Override normal method.
-     (gnus-post-method
+     ((and (eq gnus-post-method 'current)
+          (not (memq (car group-method) gnus-discouraged-post-methods))
+          (gnus-get-function group-method 'request-post t))
+      (assert (not arg))
+      group-method)
+     ;; Use gnus-post-method.
+     ((listp gnus-post-method)         ;A method...
+      (assert (not (listp (car gnus-post-method)))) ;... not a list of methods.
       gnus-post-method)
-     ;; Use the normal select method.
+     ;; Use the normal select method (nil or native).
      (t gnus-select-method))))
 
 \f
-
-;; Dummy to avoid byte-compile warning.
-(defvar nnspool-rejected-article-hook)
-(defvar xemacs-codename)
-
-;;; Since the X-Newsreader/X-Mailer are ``vanity'' headers, they might
-;;; as well include the Emacs version as well.
-;;; The following function works with later GNU Emacs, and XEmacs.
-(defun gnus-extended-version ()
-  "Stringified Gnus version and Emacs version"
-  (interactive)
-  (concat
-   gnus-version
-   "/"
-   (cond
-    ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version)
-     (concat "Emacs " (substring emacs-version
-                                (match-beginning 1)
-                                (match-end 1))))
-    ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?"
-                  emacs-version)
-     (concat (substring emacs-version
-                       (match-beginning 1)
-                       (match-end 1))
-            (format " %d.%d" emacs-major-version emacs-minor-version)
-            (if (match-beginning 3)
-                (substring emacs-version
-                           (match-beginning 3)
-                           (match-end 3))
-              "")
-            (if (boundp 'xemacs-codename)
-                (concat " - \"" xemacs-codename "\""))))
-    (t emacs-version))))
-
-;; Written by "Mr. Per Persson" <pp@gnu.ai.mit.edu>.
-(defun gnus-inews-insert-mime-headers ()
-  "Insert MIME headers.  
-Assumes ISO-Latin-1 is used iff 8-bit characters are present."
-  (goto-char (point-min))
-  (let ((mail-header-separator
-        (progn
-          (goto-char (point-min))
-          (if (and (search-forward (concat "\n" mail-header-separator "\n")
-                                   nil t)
-                   (not (search-backward "\n\n" nil t)))
-              mail-header-separator
-            ""))))
-    (or (mail-position-on-field "Mime-Version")
-       (insert "1.0")
-       (cond ((save-restriction
-                (widen)
-                (goto-char (point-min))
-                (re-search-forward "[^\000-\177]" nil t))
-              (or (mail-position-on-field "Content-Type")
-                  (insert "text/plain; charset=ISO-8859-1"))
-              (or (mail-position-on-field "Content-Transfer-Encoding")
-                  (insert "8bit")))
-             (t (or (mail-position-on-field "Content-Type")
-                    (insert "text/plain; charset=US-ASCII"))
-                (or (mail-position-on-field "Content-Transfer-Encoding")
-                    (insert "7bit")))))))
-
-(custom-add-option 'message-header-hook 'gnus-inews-insert-mime-headers)
+;; Dummies to avoid byte-compile warning.
+(eval-when-compile
+  (defvar xemacs-codename))
+
+(defun gnus-message-make-user-agent (&optional include-mime-info max-column
+                                                newline-product)
+  "Return a user-agent info.  If INCLUDE-MIME-INFO is non-nil and the
+variable `mime-edit-user-agent-value' is bound, the value will be
+included in the return value, and `gnus-user-agent' is ignored.  If
+MAX-COLUMN is specified, the return value will be folded up as it were
+filled.  NEWLINE-PRODUCT specifies whether a newline should be
+inserted in front of each product-token.  If the value is t or `hard',
+it works strictly.  Otherwise, if it is non-nil (e.g. `soft'), it
+works semi-strictly.
+
+Here is an odd example, which inserts a User-Agent: header when you
+begin to compose a message:
+
+\(add-hook 'gnus-message-setup-hook
+         (lambda nil
+           (setq message-user-agent nil)
+           (save-excursion
+             (save-restriction
+               (message-narrow-to-headers)
+               (goto-char (point-max))
+               (insert \"User-Agent: \"
+                       (gnus-message-make-user-agent t 76 'soft)
+                       \"\\n\")))))
+"
+  (let ((gnus-v (gnus-extended-version))
+       user-agent)
+    (cond ((and include-mime-info
+               (boundp 'mime-edit-user-agent-value))
+          (setq user-agent (concat gnus-v " " mime-edit-user-agent-value)))
+         ((eq gnus-user-agent 'gnus-mime-edit)
+          (setq user-agent
+                (if (boundp 'mime-edit-user-agent-value)
+                    (concat gnus-v " " mime-edit-user-agent-value)
+                  gnus-v)))
+         (t
+          (setq user-agent (if (stringp gnus-user-agent)
+                               gnus-user-agent
+                             (concat gnus-v
+                                     (let ((emacs-v (gnus-emacs-version)))
+                                       (when emacs-v
+                                         (concat " " emacs-v))))))))
+    (when max-column
+      (unless (natnump max-column)
+       (setq max-column 76))
+      (with-temp-buffer
+       (set-buffer-multibyte t)
+       (insert (mapconcat 'identity (split-string user-agent) " "))
+       (goto-char (point-min))
+       (let ((bol t)
+             start agent agents width element swidth)
+         (while (re-search-forward "\\([^ ]+\\) ?" nil t)
+           (setq start (match-beginning 0))
+           (if (eq (char-after start) ?\()
+               (progn
+                 (goto-char start)
+                 (forward-list)
+                 (push (buffer-substring start (point)) agent))
+             (when agent
+               (push (nreverse agent) agents))
+             (setq agent (list (match-string 1)))))
+         (when agent
+           (push (nreverse agent) agents))
+         (setq agents (nreverse agents))
+         (if (> (+ 12 (string-width (caar agents))) max-column)
+             (setq user-agent "\n"
+                   width 0)
+           (setq user-agent ""
+                 width 11))
+         (while agents
+           (setq agent (car agents)
+                 agents (cdr agents))
+           (when (and (not bol)
+                      (or (memq newline-product '(t hard))
+                          (and newline-product
+                               (> (+ width 1
+                                     (string-width (mapconcat 'identity
+                                                              agent " ")))
+                                  max-column))))
+             (setq user-agent (concat user-agent "\n")
+                   width 0
+                   bol t))
+           (while agent
+             (setq element (car agent)
+                   swidth (string-width element)
+                   agent (cdr agent))
+             (if bol
+                 (setq user-agent (if (member user-agent '("" "\n"))
+                                      (concat user-agent element)
+                                    (concat user-agent " " element))
+                       width (+ width 1 swidth)
+                       bol nil)
+               (if (> (+ width 1 swidth) max-column)
+                   (setq user-agent (concat user-agent "\n " element)
+                         width (1+ swidth))
+                 (setq user-agent (concat user-agent " " element)
+                       width (+ width 1 swidth)))))))))
+    user-agent))
 
 \f
 ;;;
@@ -547,24 +1215,76 @@ Assumes ISO-Latin-1 is used iff 8-bit characters are present."
 
 ;;; Mail reply commands of Gnus summary mode
 
-(defun gnus-summary-reply (&optional yank wide)
-  "Start composing a reply mail to the current message.
+(defun gnus-summary-reply (&optional yank wide very-wide)
+  "Start composing a mail reply to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
-automatically."
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
   (interactive
    (list (and current-prefix-arg
              (gnus-summary-work-articles 1))))
-  ;; Stripping headers should be specified with mail-yank-ignored-headers.
-  (when yank
-    (gnus-summary-goto-subject (car yank)))
-  (let ((gnus-article-reply t))
-    (gnus-setup-message (if yank 'reply-yank 'reply)
-      (gnus-summary-select-article)
-      (set-buffer (gnus-copy-article-buffer))
-      (message-reply nil wide (gnus-group-find-parameter
-                              gnus-newsgroup-name 'broken-reply-to))
+  ;; Allow user to require confirmation before replying by mail to the
+  ;; author of a news article (or mail message).
+  (when (or
+           (not (or (gnus-news-group-p gnus-newsgroup-name)
+                    gnus-confirm-treat-mail-like-news))
+           (not (cond ((stringp gnus-confirm-mail-reply-to-news)
+                       (string-match gnus-confirm-mail-reply-to-news
+                                     gnus-newsgroup-name))
+                      ((functionp gnus-confirm-mail-reply-to-news)
+                       (funcall gnus-confirm-mail-reply-to-news gnus-newsgroup-name))
+                      (t gnus-confirm-mail-reply-to-news)))
+           (y-or-n-p "Really reply by mail to article author? "))
+    (let* ((article
+           (if (listp (car yank))
+               (caar yank)
+             (car yank)))
+          (gnus-article-reply (or article (gnus-summary-article-number)))
+          (gnus-article-yanked-articles yank)
+          (headers ""))
+      ;; Stripping headers should be specified with mail-yank-ignored-headers.
       (when yank
-       (gnus-inews-yank-articles yank)))))
+       (gnus-summary-goto-subject article))
+      (gnus-setup-message (if yank 'reply-yank 'reply)
+       (if (not very-wide)
+           (gnus-summary-select-article)
+         (dolist (article very-wide)
+           (gnus-summary-select-article nil nil nil article)
+           (save-excursion
+             (set-buffer (gnus-copy-article-buffer))
+             (gnus-msg-treat-broken-reply-to)
+             (save-restriction
+               (message-narrow-to-head)
+               (setq headers (concat headers (buffer-string)))))))
+       (set-buffer (gnus-copy-article-buffer))
+       (gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
+       (save-restriction
+         (message-narrow-to-head)
+         (when very-wide
+           (erase-buffer)
+           (insert headers))
+         (goto-char (point-max)))
+       (message-reply nil wide)
+       (when yank
+         (gnus-inews-yank-articles yank))
+       (gnus-summary-handle-replysign)))))
+
+(defun gnus-summary-handle-replysign ()
+  "Check the various replysign variables and take action accordingly."
+  (when nil;;(or gnus-message-replysign gnus-message-replyencrypt)
+    (let (signed encrypted)
+      (save-excursion
+       (set-buffer gnus-article-buffer)
+       (setq signed (memq 'signed gnus-article-wash-types))
+       (setq encrypted (memq 'encrypted gnus-article-wash-types)))
+      (cond ((and gnus-message-replyencrypt encrypted)
+            (mml-secure-message mml-default-encrypt-method
+                                (if gnus-message-replysignencrypted
+                                    'signencrypt
+                                  'encrypt)))
+           ((and gnus-message-replysign signed)
+            (mml-secure-message mml-default-sign-method 'sign))))))
 
 (defun gnus-summary-reply-with-original (n &optional wide)
   "Start composing a reply mail to the current message.
@@ -572,6 +1292,24 @@ The original article will be yanked."
   (interactive "P")
   (gnus-summary-reply (gnus-summary-work-articles n) wide))
 
+(defun gnus-summary-reply-broken-reply-to (&optional yank wide very-wide)
+  "Like `gnus-summary-reply' except removing reply-to field.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically.
+If WIDE, make a wide reply.
+If VERY-WIDE, make a very wide reply."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (let ((gnus-msg-force-broken-reply-to t))
+    (gnus-summary-reply yank wide very-wide)))
+
+(defun gnus-summary-reply-broken-reply-to-with-original (n &optional wide)
+  "Like `gnus-summary-reply-with-original' except removing reply-to field.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply-broken-reply-to (gnus-summary-work-articles n) wide))
+
 (defun gnus-summary-wide-reply (&optional yank)
   "Start composing a wide reply mail to the current message.
 If prefix argument YANK is non-nil, the original article is yanked
@@ -583,31 +1321,182 @@ automatically."
 
 (defun gnus-summary-wide-reply-with-original (n)
   "Start composing a wide reply mail to the current message.
-The original article will be yanked."
+The original article will be yanked.
+Uses the process/prefix convention."
   (interactive "P")
   (gnus-summary-reply-with-original n t))
 
+(defun gnus-summary-very-wide-reply (&optional yank)
+  "Start composing a very wide reply mail to the current message.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically."
+  (interactive
+   (list (and current-prefix-arg
+             (gnus-summary-work-articles 1))))
+  (gnus-summary-reply yank t (gnus-summary-work-articles yank)))
+
+(defun gnus-summary-very-wide-reply-with-original (n)
+  "Start composing a very wide reply mail to the current message.
+The original article will be yanked."
+  (interactive "P")
+  (gnus-summary-reply
+   (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
+
 (defun gnus-summary-mail-forward (&optional full-headers post)
-  "Forward the current message to another user.
-If FULL-HEADERS (the prefix), include full headers when forwarding."
+  "Forward the current message(s) to another user.
+If process marks exist, forward all marked messages;
+If FULL-HEADERS (the prefix), include full headers when forwarding.
+
+Note that this function definition for T-gnus is totally different
+from the original Gnus."
+  (interactive "P")
+  (if (cdr (gnus-summary-work-articles nil))
+      ;; Process marks are given.
+      (gnus-summary-digest-mail-forward nil post)
+    ;; No process marks.
+    (let* ((gnus-article-reply (gnus-summary-article-number))
+          (gnus-article-yanked-articles (list gnus-article-reply))
+          charset
+          (message-included-forward-headers
+           (if full-headers "" message-included-forward-headers)))
+      (gnus-setup-message 'forward
+       (gnus-summary-select-article)
+       (setq charset default-mime-charset)
+       (set-buffer gnus-original-article-buffer)
+       (make-local-variable 'default-mime-charset)
+       (setq default-mime-charset charset)
+       (message-forward post)))))
+
+(defun gnus-summary-digest-mail-forward (&optional n post)
+  "Digests and forwards all articles in this series.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead.
+Optional POST will use news to forward instead of mail."
+  (interactive "P")
+  (let* ((articles (gnus-summary-work-articles n))
+        (gnus-article-yanked-articles (copy-sequence articles))
+        (topics "Topics:\n")
+        subject article frame)
+    (when (car articles)
+      (gnus-setup-message 'forward
+       (gnus-summary-select-article)
+       (if (cdr articles)
+           (setq articles (sort articles '<)
+                 subject "Digested Articles")
+         (with-current-buffer gnus-original-article-buffer
+           (setq subject (message-make-forward-subject))))
+       (if post
+           (message-news nil subject)
+         (message-mail nil subject))
+       (when (and message-use-multi-frames (cdr articles))
+         (setq frame (window-frame (get-buffer-window (current-buffer)))))
+       (message-goto-body)
+       (while (setq article (pop articles))
+         (save-window-excursion
+           (set-buffer gnus-summary-buffer)
+           (gnus-summary-select-article nil nil nil article)
+           (setq topics (concat topics "    "
+                                (mail-header-subject gnus-current-headers)
+                                "\n"))
+           (gnus-summary-remove-process-mark article))
+         (when frame
+           (select-frame frame))
+         (insert (mime-make-tag "message" "rfc822") "\n")
+         (narrow-to-region (point) (point))
+         (insert-buffer-substring gnus-original-article-buffer)
+         (save-restriction
+           (article-narrow-to-head)
+           (message-remove-header message-included-forward-headers t nil t))
+         (goto-char (point-max))
+         (widen))
+       (push-mark)
+       (message-goto-body)
+       (insert topics)
+       (message-goto-body)
+       (mime-edit-enclose-digest-region (point)(mark t))))))
+
+(defun gnus-summary-digest-post-forward (&optional n)
+  "Digest and forwards all articles in this series to a newsgroup.
+If N is a positive number, forward the N next articles.
+If N is a negative number, forward the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+forward those articles instead."
   (interactive "P")
-  (gnus-setup-message 'forward
-    (gnus-summary-select-article)
-    (set-buffer gnus-original-article-buffer)
-    (let ((message-included-forward-headers
-          (if full-headers "" message-included-forward-headers)))
-      (message-forward post))))
+  (gnus-summary-digest-mail-forward n t))
 
 (defun gnus-summary-resend-message (address n)
   "Resend the current article to ADDRESS."
-  (interactive "sResend message(s) to: \nP")
+  (interactive
+   (list (message-read-from-minibuffer
+         "Resend message(s) to: "
+         (when (and gnus-summary-resend-default-address
+                    (gnus-buffer-live-p gnus-original-article-buffer))
+           ;; If some other article is currently selected, the
+           ;; initial-contents is wrong. Whatever, it is just the
+           ;; initial-contents.
+           (with-current-buffer gnus-original-article-buffer
+             (nnmail-fetch-field "to"))))
+        current-prefix-arg))
   (let ((articles (gnus-summary-work-articles n))
        article)
     (while (setq article (pop articles))
       (gnus-summary-select-article nil nil nil article)
       (save-excursion
        (set-buffer gnus-original-article-buffer)
-       (message-resend address)))))
+       (message-resend address))
+      (gnus-summary-mark-article-as-forwarded article))))
+
+;; From: Matthieu Moy <Matthieu.Moy@imag.fr>
+(defun gnus-summary-resend-message-edit ()
+  "Resend an article that has already been sent.
+A new buffer will be created to allow the user to modify body and
+contents of the message, and then, everything will happen as when
+composing a new message."
+  (interactive)
+  (let ((article (gnus-summary-article-number)))
+    (gnus-setup-message 'reply-yank
+      (gnus-summary-select-article t)
+      (set-buffer gnus-original-article-buffer)
+      (let ((cur (current-buffer))
+           (to (message-fetch-field "to")))
+       ;; Get a normal message buffer.
+       (message-pop-to-buffer (message-buffer-name "Resend" to))
+       (insert-buffer-substring cur)
+
+       ;; T-gnus change: Use MIME-Edit to recompose a message.
+       ;;(mime-to-mml)
+       (let ((ofn (symbol-function 'mime-edit-decode-single-part-in-buffer)))
+         (fset 'mime-edit-decode-single-part-in-buffer
+               (lambda (&rest args)
+                 (if (let ((content-type (car args)))
+                       (and (eq 'message (mime-content-type-primary-type
+                                          content-type))
+                            (eq 'rfc822 (mime-content-type-subtype
+                                         content-type))))
+                     (setcar (cdr args) 'not-decode-text))
+                 (apply ofn args)))
+         (unwind-protect
+             (mime-edit-again nil t)
+           (fset 'mime-edit-decode-single-part-in-buffer ofn)))
+       (message-narrow-to-head-1)
+       (insert "From: " (message-make-from) "\n")
+       (while (re-search-forward "^From:" nil t)
+         (beginning-of-line)
+         (insert "Original-"))
+       (message-remove-header "^>From[\t ]" t)
+
+       ;; Gnus will generate a new one when sending.
+       (message-remove-header "Message-ID")
+       (message-remove-header message-ignored-resent-headers t)
+       ;; Remove unwanted headers.
+       (goto-char (point-max))
+       (insert mail-header-separator)
+       (goto-char (point-min))
+       (when (re-search-forward "^To:\\|^Newsgroups:" nil 'move)
+         (forward-char 1))
+       (widen)))))
 
 (defun gnus-summary-post-forward (&optional full-headers)
   "Forward the current article to a newsgroup.
@@ -646,7 +1535,8 @@ The current group name will be inserted at \"%s\".")
        (gnus-summary-select-article)
        (set-buffer gnus-original-article-buffer)
        (if (and (<= (length (message-tokenize-header
-                             (setq newsgroups (mail-fetch-field "newsgroups"))
+                             (setq newsgroups
+                                   (mail-fetch-field "newsgroups"))
                              ", "))
                     1)
                 (or (not (setq followup-to (mail-fetch-field "followup-to")))
@@ -667,12 +1557,6 @@ The current group name will be inserted at \"%s\".")
          (when (gnus-y-or-n-p "Send this complaint? ")
            (message-send-and-exit)))))))
 
-(defun gnus-summary-mail-other-window ()
-  "Compose mail in other window."
-  (interactive)
-  (gnus-setup-message 'message
-    (message-mail)))
-
 (defun gnus-mail-parse-comma-list ()
   (let (accumulated
        beg)
@@ -707,7 +1591,7 @@ The current group name will be inserted at \"%s\".")
       ;; This mail group doesn't have a `to-list', so we add one
       ;; here.  Magic!
       (when (gnus-y-or-n-p
-            (format "Do you want to add this as `to-list': %s " to-address))
+            (format "Do you want to add this as `to-list': %s? " to-address))
        (gnus-group-add-parameter group (cons 'to-list to-address))))))
 
 (defun gnus-put-message ()
@@ -716,35 +1600,34 @@ The current group name will be inserted at \"%s\".")
   (let ((reply gnus-article-reply)
        (winconf gnus-prev-winconf)
        (group gnus-newsgroup-name))
+    (unless (and group
+                (not (gnus-group-read-only-p group)))
+      (setq group (read-string "Put in group: " nil (gnus-writable-groups))))
 
-    (or (and group (not (gnus-group-read-only-p group)))
-       (setq group (read-string "Put in group: " nil
-                                (gnus-writable-groups))))
     (when (gnus-gethash group gnus-newsrc-hashtb)
       (error "No such group: %s" group))
-
     (save-excursion
       (save-restriction
        (widen)
        (message-narrow-to-headers)
-       (let (gnus-deletable-headers)
-         (if (message-news-p)
-             (message-generate-headers message-required-news-headers)
-           (message-generate-headers message-required-mail-headers)))
+       (let ((gnus-deletable-headers nil))
+         (message-generate-headers
+          (if (message-news-p)
+              message-required-news-headers
+            message-required-mail-headers)))
        (goto-char (point-max))
-       (insert "Gcc: " group "\n")
+       (if (string-match " " group)
+           (insert "Gcc: \"" group "\"\n")
+         (insert "Gcc: " group "\n"))
        (widen)))
-
     (gnus-inews-do-gcc)
-
-    (when (get-buffer gnus-group-buffer)
-      (when (gnus-buffer-exists-p (car-safe reply))
-       (set-buffer (car reply))
-       (and (cdr reply)
-            (gnus-summary-mark-article-as-replied
-             (cdr reply))))
-      (when winconf
-       (set-window-configuration winconf)))))
+    (when (and (get-buffer gnus-group-buffer)
+              (gnus-buffer-exists-p (car-safe reply))
+              (cdr reply))
+      (set-buffer (car reply))
+      (gnus-summary-mark-article-as-replied (cdr reply)))
+    (when winconf
+      (set-window-configuration winconf))))
 
 (defun gnus-article-mail (yank)
   "Send a reply to the address near point.
@@ -755,7 +1638,7 @@ If YANK is non-nil, include the original article."
          (save-excursion (re-search-backward "[ \t\n]" nil t) (1+ (point)))
          (save-excursion (re-search-forward "[ \t\n]" nil t) (1- (point))))))
     (when address
-      (message-reply address)
+      (gnus-msg-mail address)
       (when yank
        (gnus-inews-yank-articles (list (cdr gnus-article-current)))))))
 
@@ -765,25 +1648,42 @@ If YANK is non-nil, include the original article."
   (interactive)
   (unless (gnus-alive-p)
     (error "Gnus has been shut down"))
-  (gnus-setup-message 'bug
-    (delete-other-windows)
-    (switch-to-buffer (get-buffer-create "*Gnus Help Bug*"))
-    (erase-buffer)
-    (insert gnus-bug-message)
-    (goto-char (point-min))
-    (message-pop-to-buffer "*Gnus Bug*")
-    (message-setup `((To . ,gnus-maintainer) (Subject . "")))
-    (push `(gnus-bug-kill-buffer) message-send-actions)
+  (gnus-setup-message (if (message-mail-user-agent) 'message 'bug)
+    (unless (message-mail-user-agent)
+      (message-pop-to-buffer "*Gnus Bug*")
+      (delete-other-windows)
+      (when gnus-bug-create-help-buffer
+       (switch-to-buffer "*Gnus Help Bug*")
+       (erase-buffer)
+       (insert gnus-bug-message)
+       (goto-char (point-min))
+       (sit-for 0)
+       (set-buffer "*Gnus Bug*")))
+    (let ((message-this-is-mail t))
+      (message-setup `((To . ,gnus-maintainer) (Subject . ""))))
+    (when gnus-bug-create-help-buffer
+      (push `(gnus-bug-kill-buffer) message-send-actions))
     (goto-char (point-min))
     (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
     (forward-line 1)
-    (insert (gnus-version) "\n")
-    (insert (emacs-version) "\n")
+    (insert gnus-product-name " " gnus-version-number
+           " (r" gnus-revision-number ") "
+           "based on " gnus-original-product-name " v"
+           gnus-original-version-number "\n"
+           (emacs-version) "\n")
     (when (and (boundp 'nntp-server-type)
               (stringp nntp-server-type))
       (insert nntp-server-type))
     (insert "\n\n\n\n\n")
-    (gnus-debug)
+    (let (mime-content-types)
+      (mime-edit-insert-tag
+       "application" "emacs-lisp"
+       "\nContent-Disposition: inline\nContent-Description: User settings"))
+    (insert (with-temp-buffer
+             (gnus-debug)
+             (buffer-string)))
+    (let (mime-content-types)
+      (mime-edit-insert-tag "text" "plain"))
     (goto-char (point-min))
     (search-forward "Subject: " nil t)
     (message "")))
@@ -792,22 +1692,51 @@ If YANK is non-nil, include the original article."
   (when (get-buffer "*Gnus Help Bug*")
     (kill-buffer "*Gnus Help Bug*")))
 
+(defun gnus-summary-yank-message (buffer n)
+  "Yank the current article into a composed message."
+  (interactive
+   (list (completing-read "Buffer: " (mapcar 'list (message-buffers)) nil t)
+        current-prefix-arg))
+  (when (gnus-buffer-live-p buffer)
+    (let ((summary-frame (selected-frame))
+         (message-frame (when (static-if (featurep 'xemacs)
+                                  (device-on-window-system-p)
+                                window-system)
+                          (let ((window (get-buffer-window buffer t)))
+                            (when window
+                              (window-frame window)))))
+         (separator (concat "^" (regexp-quote mail-header-separator)
+                            "\n")))
+      (gnus-summary-iterate n
+       (gnus-summary-select-article)
+       (gnus-copy-article-buffer)
+       (when (frame-live-p message-frame)
+         (raise-frame message-frame)
+         (select-frame message-frame))
+       (with-current-buffer buffer
+         (when (save-excursion
+                 (beginning-of-line)
+                 (let (case-fold-search)
+                   (and (not (re-search-backward separator nil t))
+                        (re-search-forward separator nil t))))
+           (goto-char (match-end 0)))
+         (message-yank-buffer gnus-article-copy))
+       (select-frame summary-frame))
+      (when (frame-live-p message-frame)
+       (select-frame message-frame)))))
+
 (defun gnus-debug ()
   "Attempts to go through the Gnus source file and report what variables have been changed.
 The source file has to be in the Emacs load path."
   (interactive)
-  (let ((files '("gnus.el" "gnus-sum.el" "gnus-group.el"
-                "gnus-art.el" "gnus-start.el" "gnus-async.el"
-                "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el"
-                "nnmail.el" "message.el"))
+  (let ((files gnus-debug-files)
        (point (point))
        file expr olist sym)
     (gnus-message 4 "Please wait while we snoop your variables...")
-    (sit-for 0)
     ;; Go through all the files looking for non-default values for variables.
     (save-excursion
-      (set-buffer (get-buffer-create " *gnus bug info*"))
-      (buffer-disable-undo (current-buffer))
+      (sit-for 0)
+      (set-buffer (gnus-get-buffer-create " *gnus bug info*"))
       (while files
        (erase-buffer)
        (when (and (setq file (locate-library (pop files)))
@@ -820,45 +1749,47 @@ The source file has to be in the Emacs load path."
            (goto-char (point-min))
            (while (setq expr (ignore-errors (read (current-buffer))))
              (ignore-errors
-               (and (or (eq (car expr) 'defvar)
-                        (eq (car expr) 'defcustom))
+               (and (memq (car expr) '(defvar defcustom defvoo))
                     (stringp (nth 3 expr))
+                    (not (memq (nth 1 expr) gnus-debug-exclude-variables))
                     (or (not (boundp (nth 1 expr)))
                         (not (equal (eval (nth 2 expr))
                                     (symbol-value (nth 1 expr)))))
                     (push (nth 1 expr) olist)))))))
       (kill-buffer (current-buffer)))
     (when (setq olist (nreverse olist))
-      (insert "------------------ Environment follows ------------------\n\n"))
+      (insert ";----------------- Environment follows ------------------\n\n"))
     (while olist
       (if (boundp (car olist))
-         (condition-case ()
-             (pp `(setq ,(car olist)
-                        ,(if (or (consp (setq sym (symbol-value (car olist))))
-                                 (and (symbolp sym)
-                                      (not (or (eq sym nil)
-                                               (eq sym t)))))
-                             (list 'quote (symbol-value (car olist)))
-                           (symbol-value (car olist))))
-                 (current-buffer))
-           (error
-            (format "(setq %s 'whatever)\n" (car olist))))
+         (ignore-errors
+           (pp `(setq ,(car olist)
+                      ,(if (or (consp (setq sym (symbol-value (car olist))))
+                               (and (symbolp sym)
+                                    (not (or (eq sym nil)
+                                             (eq sym t)))))
+                           (list 'quote (symbol-value (car olist)))
+                         (symbol-value (car olist))))
+               (current-buffer)))
        (insert ";; (makeunbound '" (symbol-name (car olist)) ")\n"))
       (setq olist (cdr olist)))
-    (insert "\n\n")
     ;; Remove any control chars - they seem to cause trouble for some
     ;; mailers.  (Byte-compiled output from the stuff above.)
     (goto-char point)
     (while (re-search-forward "[\000-\010\013-\037\200-\237]" nil t)
       (replace-match (format "\\%03o" (string-to-char (match-string 0)))
-                    t t))))
+                    t t))
+    ;; Break MIME tags purposely.
+    (goto-char point)
+    (while (re-search-forward mime-edit-tag-regexp nil t)
+      (goto-char (1+ (match-beginning 0)))
+      (insert "X"))))
 
 ;;; Treatment of rejected articles.
 ;;; Bounced mail.
 
 (defun gnus-summary-resend-bounced-mail (&optional fetch)
   "Re-mail the current message.
-This only makes sense if the current message is a bounce message than
+This only makes sense if the current message is a bounce message that
 contains some mail you have written which has been bounced back to
 you.
 If FETCH, try to fetch the article that this is a reply to, if indeed
@@ -877,53 +1808,72 @@ this is a reply."
 
 ;;; Gcc handling.
 
+(defun gnus-inews-group-method (group)
+  (cond
+   ;; If the group doesn't exist, we assume
+   ;; it's an archive group...
+   ((and (null (gnus-get-info group))
+        (eq (car (gnus-server-to-method gnus-message-archive-method))
+            (car (gnus-server-to-method (gnus-group-method group)))))
+    gnus-message-archive-method)
+   ;; Use the method.
+   ((gnus-info-method (gnus-get-info group))
+    (gnus-info-method (gnus-get-info group)))
+   ;; Find the method.
+   (t (gnus-server-to-method (gnus-group-method group)))))
+
 ;; Do Gcc handling, which copied the message over to some group.
 (defun gnus-inews-do-gcc (&optional gcc)
   (interactive)
-  (when (gnus-alive-p)
-    (save-excursion
-      (save-restriction
-       (message-narrow-to-headers)
-       (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
-             (cur (current-buffer))
-             groups group method)
-         (when gcc
-           (message-remove-header "gcc")
-           (widen)
-           (setq groups (message-tokenize-header gcc " ,"))
-           ;; Copy the article over to some group(s).
-           (while (setq group (pop groups))
-             (gnus-check-server
-              (setq method
-                    (cond ((and (null (gnus-get-info group))
-                                (eq (car gnus-message-archive-method)
-                                    (car
-                                     (gnus-server-to-method
-                                      (gnus-group-method group)))))
-                           ;; If the group doesn't exist, we assume
-                           ;; it's an archive group...
-                           gnus-message-archive-method)
-                          ;; Use the method.
-                          ((gnus-info-method (gnus-get-info group))
-                           (gnus-info-method (gnus-get-info group)))
-                          ;; Find the method.
-                          (t (gnus-group-method group)))))
-             (gnus-check-server method)
-             (unless (gnus-request-group group t method)
-               (gnus-request-create-group group method))
-             (save-excursion
-               (nnheader-set-temp-buffer " *acc*")
-               (insert-buffer-substring cur)
-               (goto-char (point-min))
-               (when (re-search-forward
-                      (concat "^" (regexp-quote mail-header-separator) "$")
-                      nil t)
-                 (replace-match "" t t ))
-               (unless (gnus-request-accept-article group method t)
-                 (gnus-message 1 "Couldn't store article in group %s: %s"
-                               group (gnus-status-message method))
-                 (sit-for 2))
-               (kill-buffer (current-buffer))))))))))
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (let ((gcc (or gcc (mail-fetch-field "gcc" nil t)))
+           (coding-system-for-write 'raw-text)
+           (output-coding-system 'raw-text)
+           groups group method group-art
+           mml-externalize-attachments)
+       (when gcc
+         (message-remove-header "gcc")
+         (widen)
+         (setq groups (message-unquote-tokens
+                       (message-tokenize-header gcc " ,")))
+         ;; Copy the article over to some group(s).
+         (while (setq group (pop groups))
+           (unless (gnus-check-server
+                    (setq method (gnus-inews-group-method group)))
+             (error "Can't open server %s" (if (stringp method) method
+                                             (car method))))
+           (unless (gnus-request-group group nil method)
+             (gnus-request-create-group group method))
+           (setq mml-externalize-attachments
+                 (if (stringp gnus-gcc-externalize-attachments)
+                     (string-match gnus-gcc-externalize-attachments group)
+                   gnus-gcc-externalize-attachments))
+           (save-excursion
+             (nnheader-set-temp-buffer " *acc*")
+             (insert-buffer-substring message-encoding-buffer)
+             (gnus-run-hooks 'gnus-before-do-gcc-hook)
+             (goto-char (point-min))
+             (when (re-search-forward
+                    (concat "^" (regexp-quote mail-header-separator) "$")
+                    nil t)
+               (replace-match "" t t ))
+             (unless (setq group-art
+                           (gnus-request-accept-article group method t t))
+               (gnus-message 1 "Couldn't store article in group %s: %s"
+                             group (gnus-status-message method))
+               (sit-for 2))
+             (when (and group-art
+                        ;; FIXME: Should gcc-mark-as-read work when
+                        ;; Gnus is not running?
+                        (gnus-alive-p)
+                        (or gnus-gcc-mark-as-read
+                            (and
+                             (boundp 'gnus-inews-mark-gcc-as-read)
+                             (symbol-value 'gnus-inews-mark-gcc-as-read))))
+               (gnus-group-mark-article-read group (cdr group-art)))
+             (kill-buffer (current-buffer)))))))))
 
 (defun gnus-inews-insert-gcc ()
   "Insert Gcc headers based on `gnus-outgoing-message-group'."
@@ -932,14 +1882,21 @@ this is a reply."
       (message-narrow-to-headers)
       (let* ((group gnus-outgoing-message-group)
             (gcc (cond
-                  ((gnus-functionp group)
+                  ((functionp group)
                    (funcall group))
                   ((or (stringp group) (list group))
                    group))))
        (when gcc
          (insert "Gcc: "
-                 (if (stringp gcc) gcc
-                   (mapconcat 'identity gcc " "))
+                 (if (stringp gcc)
+                     (if (string-match " " gcc)
+                         (concat "\"" gcc "\"")
+                       gcc)
+                   (mapconcat (lambda (group)
+                                (if (string-match " " group)
+                                    (concat "\"" group "\"")
+                                  group))
+                              gcc " "))
                  "\n"))))))
 
 (defun gnus-inews-insert-archive-gcc (&optional group)
@@ -948,9 +1905,10 @@ this is a reply."
         (group (or group gnus-newsgroup-name ""))
         (gcc-self-val
          (and gnus-newsgroup-name
+              (not (equal gnus-newsgroup-name ""))
               (gnus-group-find-parameter
                gnus-newsgroup-name 'gcc-self)))
-        result 
+        result
         (groups
          (cond
           ((null gnus-message-archive-method)
@@ -965,7 +1923,7 @@ this is a reply."
           ((and (listp var) (stringp (car var)))
            ;; A list of groups.
            var)
-          ((gnus-functionp var)
+          ((functionp var)
            ;; A function.
            (funcall var group))
           (t
@@ -978,7 +1936,7 @@ this is a reply."
                                 ;; Regexp.
                                 (when (string-match (caar var) group)
                                   (cdar var)))
-                               ((gnus-functionp (car var))
+                               ((functionp (car var))
                                 ;; Function.
                                 (funcall (car var) group))
                                (t
@@ -999,23 +1957,259 @@ this is a reply."
              (progn
                (insert
                 (if (stringp gcc-self-val)
-                    gcc-self-val
-                  group))
+                    (if (string-match " " gcc-self-val)
+                        (concat "\"" gcc-self-val "\"")
+                      gcc-self-val)
+                  ;; In nndoc groups, we use the parent group name
+                  ;; instead of the current group.
+                  (let ((group (or (gnus-group-find-parameter
+                                    gnus-newsgroup-name 'parent-group)
+                                   group)))
+                    (if (string-match " " group)
+                        (concat "\"" group "\"")
+                      group))))
                (if (not (eq gcc-self-val 'none))
                    (insert "\n")
-                 (progn
-                   (beginning-of-line)
-                   (kill-line))))
+                 (gnus-delete-line)))
            ;; Use the list of groups.
            (while (setq name (pop groups))
-             (insert (if (string-match ":" name)
-                         name
-                       (gnus-group-prefixed-name
-                        name gnus-message-archive-method)))
+             (let ((str (if (string-match ":" name)
+                            name
+                          (gnus-group-prefixed-name
+                           name gnus-message-archive-method))))
+               (insert (if (string-match " " str)
+                           (concat "\"" str "\"")
+                         str)))
              (when groups
                (insert " ")))
            (insert "\n")))))))
 
+(defun gnus-mailing-list-followup-to ()
+  "Look at the headers in the current buffer and return a Mail-Followup-To address."
+  (let ((x-been-there (gnus-fetch-original-field "x-beenthere"))
+       (list-post (gnus-fetch-original-field "list-post")))
+    (when (and list-post
+              (string-match "mailto:\\([^>]+\\)" list-post))
+      (setq list-post (match-string 1 list-post)))
+    (or list-post
+       x-been-there)))
+
+;;; Posting styles.
+
+(defun gnus-configure-posting-styles (&optional group-name)
+  "Configure posting styles according to `gnus-posting-styles'."
+  (unless gnus-inhibit-posting-styles
+    (let ((group (or group-name gnus-newsgroup-name ""))
+         (styles gnus-posting-styles)
+         style match attribute results
+         name address)
+      ;; If the group has a posting-style parameter, add it at the end with a
+      ;; regexp matching everything, to be sure it takes precedence over all
+      ;; the others.
+      (when gnus-newsgroup-name
+       (let ((tmp-style (gnus-group-find-parameter group 'posting-style t)))
+         (when tmp-style
+           (setq styles (append styles (list (cons ".*" tmp-style)))))))
+      ;; Go through all styles and look for matches.
+      (dolist (style styles)
+       (setq match (pop style))
+       (goto-char (point-min))
+       (when (cond
+              ((stringp match)
+               ;; Regexp string match on the group name.
+               (string-match match group))
+              ((eq match 'header)
+               ;; Obsolete format of header match.
+               (and (gnus-buffer-live-p gnus-article-copy)
+                    (with-current-buffer gnus-article-copy
+                      (let ((header (message-fetch-field (pop style))))
+                        (and header
+                             (string-match (pop style) header))))))
+              ((or (symbolp match)
+                   (functionp match))
+               (cond
+                ((functionp match)
+                 ;; Function to be called.
+                 (funcall match))
+                ((boundp match)
+                 ;; Variable to be checked.
+                 (symbol-value match))))
+              ((listp match)
+               (cond
+                ((eq (car match) 'header)
+                 ;; New format of header match.
+                 (and (gnus-buffer-live-p gnus-article-copy)
+                      (with-current-buffer gnus-article-copy
+                        (let ((header (message-fetch-field (nth 1 match))))
+                          (and header
+                               (string-match (nth 2 match) header))))))
+                (t
+                 ;; This is a form to be evaled.
+                 (eval match)))))
+         ;; We have a match, so we set the variables.
+         (setq style (gnus-configure-posting-style style nil))
+         (dolist (attribute style)
+           (setq results (delq (assoc (car attribute) results) results))
+           (push attribute results))))
+      ;; Now we have all the styles, so we insert them.
+      (setq name (assq 'name results)
+           address (assq 'address results))
+      (setq results (delq name (delq address results)))
+      (gnus-make-local-hook 'message-setup-hook)
+      (setq results (sort results (lambda (x y)
+                                   (string-lessp (car x) (car y)))))
+      (dolist (result results)
+       (add-hook 'message-setup-hook
+                 (cond
+                  ((eq 'eval (car result))
+                   'ignore)
+                  ((eq 'body (car result))
+                   `(lambda ()
+                      (save-excursion
+                        (message-goto-body)
+                        (insert ,(cdr result)))))
+                  ((eq 'signature (car result))
+                   (set (make-local-variable 'message-signature) nil)
+                   (set (make-local-variable 'message-signature-file) nil)
+                   (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))
+                              (capitalize (symbol-name (car result)))
+                            (car result))))
+                     `(lambda ()
+                        (save-excursion
+                          (message-remove-header ,header)
+                          (let ((value ,(cdr result)))
+                            (when value
+                              (message-goto-eoh)
+                              (insert ,header ": " value)
+                              (unless (bolp)
+                                (insert "\n")))))))))
+                 nil 'local))
+      (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)))
+                      (save-excursion
+                        (message-remove-header "From")
+                        (message-goto-eoh)
+                        (insert "From: " (message-make-from) "\n"))))
+                 nil 'local)))))
+
+;; splitted from gnus-configure-posting-styles to allow recursive traversal.
+(defun gnus-configure-posting-style (style stack)
+  "Parse one posting style STYLE and returns the value as an alist."
+  (let (results element variable filep value v)
+    (dolist (attribute style)
+      (setq element (pop attribute)
+           variable nil
+           filep nil)
+      (setq value
+           (cond
+            ((eq (car attribute) ':file)
+             (setq filep t)
+             (cadr attribute))
+            ((eq (car attribute) :value)
+             (cadr attribute))
+            (t
+             (car attribute))))
+      ;; We get the value.
+      (setq v
+           (cond
+            ((stringp value)
+             value)
+            ((or (symbolp value)
+                 (functionp value))
+             (cond ((functionp value)
+                    (funcall value))
+                   ((boundp value)
+                    (symbol-value value))))
+            ((listp value)
+             (eval value))))
+      ;; Translate obsolescent value.
+      (cond
+       ((eq element 'signature-file)
+       (setq element 'signature
+             filep t))
+       ((eq element 'x-face-file)
+       (setq element 'x-face
+             filep t)))
+      ;; Get the contents of file elems.
+      (when (and filep v)
+       (setq v (with-temp-buffer
+                 (insert-file-contents v)
+                 (goto-char (point-max))
+                 (while (bolp)
+                   (delete-char -1))
+                 (buffer-string))))
+      (if (eq element 'import)
+         (progn
+           (if (member v stack)
+               (error "Circular import of \"%s\"" v))
+           (setq results
+                 (nconc (nreverse (gnus-configure-posting-style
+                                   (cdr (assoc v gnus-named-posting-styles))
+                                   (cons v stack)))
+                        results)))
+       (push (cons element v) results)))
+    (nreverse results)))
+
+(defun gnus-summary-execute-command-with-posting-style (style command)
+  "Temporarily select a posting-style named STYLE and execute COMMAND."
+  (interactive
+   (let ((style (completing-read "Posting style: "
+                                gnus-named-posting-styles nil t)))
+     (list style
+          (key-binding
+           (read-key-sequence
+            (format "Command to execute with %s: " style))))))
+  (let ((gnus-posting-styles (list (list ".*" (list 'import style)))))
+    (call-interactively command)))
+
+
+;;; @ for MIME Edit mode
+;;;
+
+(defun gnus-maybe-setup-default-charset ()
+  (let ((charset
+        (and (boundp 'gnus-summary-buffer)
+             (buffer-live-p gnus-summary-buffer)
+             (save-excursion
+               (set-buffer gnus-summary-buffer)
+               default-mime-charset))))
+    (if charset
+       (progn
+         (make-local-variable 'default-mime-charset)
+         (setq default-mime-charset charset)
+         ))))
+
+
+;;; @ for MIME view mode
+;;;
+
+(defun gnus-following-method (buf)
+  (gnus-setup-message 'reply-yank
+    (set-buffer buf)
+    (if (message-news-p)
+       (message-followup)
+      (message-reply nil 'wide))
+    (let ((message-reply-buffer buf))
+      (message-yank-original))
+    (message-goto-body))
+  (kill-buffer buf))
+
+
 ;;; Allow redefinition of functions.
 
 (gnus-ems-redefine)
diff --git a/lisp/gnus-namazu.el b/lisp/gnus-namazu.el
new file mode 100644 (file)
index 0000000..ee43a56
--- /dev/null
@@ -0,0 +1,866 @@
+;;; gnus-namazu.el --- Search mail with Namazu -*- coding: iso-2022-7bit; -*-
+
+;; Copyright (C) 2000,2001,2002,2003 TSUCHIYA Masatoshi <tsuchiya@namazu.org>
+
+;; Author: TSUCHIYA Masatoshi <tsuchiya@namazu.org>
+;; Keywords: mail searching namazu
+
+;; This file is a part of Semi-Gnus.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, you can either send email to this
+;; program's maintainer or write to: The Free Software Foundation,
+;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
+
+
+;;; Commentary:
+
+;; This file defines the command to search mails and persistent
+;; articles with Namazu and to browse its results with Gnus.
+;;
+;; Namazu is a full-text search engine intended for easy use.  For
+;; more detail about Namazu, visit the following page:
+;;
+;;     http://namazu.org/
+
+
+;;; Quick Start:
+
+;; If this module has already been installed, only 3 steps are
+;; required to search articles with this module.
+;;
+;;   (1) Install Namazu.
+;;   (2) Start Gnus and type M-x gnus-namazu-create-index RET to make
+;;       index of articles.
+;;   (3) In group buffer or in summary buffer, type C-c C-n query RET.
+
+
+;;; Install:
+
+;; Before installing this module, you must install Namazu.
+;;
+;; This file is a part of T-gnus but is not *YET* a part of Gnus.
+;; When you would like to use this module in Gnus (not T-gnus), put
+;; this file into the lisp/ directory in the Gnus source tree and run
+;; `make install'.  And then, put the following expression into your
+;; ~/.gnus.
+;;
+;;      (require 'gnus-namazu)
+;;      (gnus-namazu-insinuate)
+;;
+;; In order to make index of articles with Namazu before using this
+;; module, type M-x gnus-namazu-create-index RET.  Otherwise, you can
+;; create index by yourself with the following commands:
+;;
+;;      % mkdir ~/News/namazu
+;;      % mknmz -a -h -O ~/News/namazu ~/Mail ~/News/cache
+;;
+;; The first command makes the directory for index files, and the
+;; second command generates index files of mails and persistent
+;; articles.
+;;
+;; In order to update indices for incoming articles, this module
+;; automatically runs mknmz, the indexer of Namazu, at an interval of
+;; 3 days; this period is set to `gnus-namazu-index-update-interval'.
+;;
+;; Indices will be updated when `gnus-namazu-search' is called.  If
+;; you want to update indices everywhen Gnus is started, you can put
+;; the following expression to your ~/.gnus.
+;;
+;;      (add-hook 'gnus-startup-hook 'gnus-namazu-update-all-indices)
+;;
+;; In order to control mknmz closely, disable the automatic updating
+;; feature and run mknmz by yourself.  In this case, set nil to the
+;; above option.
+;;
+;;      (setq gnus-namazu-index-update-interval nil)
+;;
+;; When your index is put into the directory other than the default
+;; one (~/News/namazu), it is necessary to set its place to
+;; `gnus-namazu-index-directories' as follows:
+;;
+;;      (setq gnus-namazu-index-directories
+;;            (list (expand-file-name "~/namazu")))
+
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'nnoo)
+(require 'nnheader)
+(require 'nnmail)
+(require 'gnus-sum)
+
+;; It is required for Mule 2.3.  See the file Mule23@1934.en.
+(eval-and-compile
+  (autoload 'regexp-opt "regexp-opt"))
+
+;; To suppress byte-compile warning.
+(eval-when-compile
+  (defvar nnml-directory)
+  (defvar nnmh-directory))
+
+
+(defgroup gnus-namazu nil
+  "Search nnmh and nnml groups in Gnus with Namazu."
+  :group 'namazu
+  :group 'gnus
+  :prefix "gnus-namazu-")
+
+(defconst gnus-namazu-default-index-directory
+  (expand-file-name "namazu" gnus-directory)
+  "Default place of Namazu index files.")
+
+(defcustom gnus-namazu-index-directories
+  (list
+   (or (and (boundp 'gnus-namazu-index-directory)
+           (symbol-value 'gnus-namazu-index-directory))
+       (and (boundp 'nnir-namazu-index-directory)
+           (symbol-value 'nnir-namazu-index-directory))
+       gnus-namazu-default-index-directory))
+  "*Places of Namazu index files."
+  :type '(repeat directory)
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-command
+  (or (and (boundp 'namazu-command)
+          (symbol-value 'namazu-command))
+      (and (boundp 'nnir-namazu-program)
+          (symbol-value 'nnir-namazu-program))
+      "namazu")
+  "*Name of the executable file of Namazu."
+  :type 'string
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-additional-arguments nil
+  "*Additional arguments of Namazu.
+The options `-q', `-a', and `-l' are always used, very few other
+options make any sense in this context."
+  :type '(repeat string)
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-index-update-interval
+  259200                               ; 3 days == 259200 seconds.
+  "*Number of seconds between running the indexer of Namazu."
+  :type '(choice (const :tag "Never run the indexer" nil)
+                (integer :tag "Number of seconds"))
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-make-index-command "mknmz"
+  "*Name of the executable file of the indexer of Namazu."
+  :type 'string
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-make-index-arguments
+  (nconc
+   (list "--all" "--mailnews" "--deny=^.*[^0-9].*$")
+   (when (or (and (boundp 'current-language-environment)
+                 (string= "Japanese"
+                          (symbol-value 'current-language-environment)))
+            (boundp 'MULE))
+     (list "--indexing-lang=ja")))
+  "*Arguments of the indexer of Namazu."
+  :type '(repeat string)
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-field-keywords
+  '("date" "from" "newsgroups" "size" "subject" "summary" "to" "uri")
+  "*List of keywords to do field-search."
+  :type '(repeat string)
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-coding-system
+  (if (memq system-type '(windows-nt OS/2 emx))
+      (if (boundp 'MULE) '*sjis* 'shift_jis)
+    (if (boundp 'MULE) '*euc-japan* 'euc-japan))
+  "*Coding system for Namazu process."
+  :type 'coding-system
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-need-path-normalization
+  (and (memq system-type '(windows-nt OS/2 emx)) t)
+  "*Non-nil means that outputs of namazu may contain drive letters."
+  :type 'boolean
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-case-sensitive-filesystem
+  (not (eq system-type 'windows-nt))
+  "*Non-nil means that the using file system distinguishes cases of characters."
+  :type 'boolean
+  :group 'gnus-namazu)
+
+(defcustom gnus-namazu-query-highlight t
+  "Non-nil means that queried words is highlighted."
+  :type 'boolean
+  :group 'gnus-namazu)
+
+(defface gnus-namazu-query-highlight-face
+  '((((type tty pc) (class color))
+     (:background "magenta4" :foreground "cyan1"))
+    (((class color) (background light))
+     (:background "magenta4" :foreground "lightskyblue1"))
+    (((class color) (background dark))
+     (:background "palevioletred2" :foreground "brown4"))
+    (t (:inverse-video t)))
+  "Face used for namazu query matching words."
+  :group 'gnus-namazu)
+
+;;; Internal Variable:
+(defconst gnus-namazu/group-name-regexp "\\`nnvirtual:namazu-search\\?")
+
+;; Multibyte group name:
+(and
+ (fboundp 'gnus-group-decoded-name)
+ (let ((gnus-group-name-charset-group-alist
+       (list (cons gnus-namazu/group-name-regexp gnus-namazu-coding-system)))
+       (query (decode-coding-string
+              (string 27 36 66 52 65 59 122 27 40 66)
+              (if (boundp 'MULE) '*iso-2022-jp* 'iso-2022-7bit))))
+   (not (string-match query
+                     (gnus-summary-buffer-name
+                      (encode-coding-string
+                       (concat "nnvirtual:namazu-search?query=" query)
+                       gnus-namazu-coding-system)))))
+ (let (current-load-list)
+   (defadvice gnus-summary-buffer-name
+     (before gnus-namazu-summary-buffer-name activate compile)
+     "Advised by `gnus-namazu' to handle encoded group names."
+     (ad-set-arg 0 (gnus-group-decoded-name (ad-get-arg 0))))))
+
+(defmacro gnus-namazu/make-article (group number)
+  `(cons ,group ,number))
+(defmacro gnus-namazu/article-group  (x) `(car ,x))
+(defmacro gnus-namazu/article-number (x) `(cdr ,x))
+
+(defsubst gnus-namazu/indexed-servers ()
+  "Choice appropriate servers from opened ones, and return thier list."
+  (append
+   (gnus-servers-using-backend 'nnml)
+   (gnus-servers-using-backend 'nnmh)))
+
+(defsubst gnus-namazu/default-index-directory ()
+  (if (member gnus-namazu-default-index-directory
+             gnus-namazu-index-directories)
+      gnus-namazu-default-index-directory
+    (car gnus-namazu-index-directories)))
+
+(defun gnus-namazu/setup ()
+  (and (boundp 'gnus-group-name-charset-group-alist)
+       (not (member (cons gnus-namazu/group-name-regexp
+                         gnus-namazu-coding-system)
+                   gnus-group-name-charset-group-alist))
+       (let ((pair (assoc gnus-namazu/group-name-regexp
+                         gnus-group-name-charset-group-alist)))
+        (if pair
+            (setcdr pair gnus-namazu-coding-system)
+          (push (cons gnus-namazu/group-name-regexp
+                      gnus-namazu-coding-system)
+                gnus-group-name-charset-group-alist))))
+  (gnus-namazu-update-all-indices))
+
+(defun gnus-namazu/server-directory (server)
+  "Return the top directory of the server SERVER."
+  (and (memq (car server) '(nnml nnmh))
+       (nnoo-change-server (car server) (nth 1 server) (nthcdr 2 server))
+       (file-name-as-directory
+       (expand-file-name (if (eq 'nnml (car server))
+                             nnml-directory
+                           nnmh-directory)))))
+
+;;; Functions to call Namazu.
+(defsubst gnus-namazu/normalize-results ()
+  "Normalize file names returned by Namazu in this current buffer."
+  (goto-char (point-min))
+  (while (not (eobp))
+    (when (looking-at "file://")
+      (delete-region (point) (match-end 0)))
+    (when (if gnus-namazu-need-path-normalization
+             (or (not (looking-at "/\\(.\\)|/"))
+                 (replace-match "\\1:/"))
+           (eq ?~ (char-after (point))))
+      (insert (expand-file-name
+              (buffer-substring (gnus-point-at-bol) (gnus-point-at-eol))))
+      (delete-region (point) (gnus-point-at-eol)))
+    (forward-line 1)))
+
+(defsubst gnus-namazu/call-namazu (query)
+  (let ((coding-system-for-read gnus-namazu-coding-system)
+       (coding-system-for-write gnus-namazu-coding-system)
+       (input-coding-system gnus-namazu-coding-system)
+       (output-coding-system gnus-namazu-coding-system)
+       (default-process-coding-system
+         (cons gnus-namazu-coding-system gnus-namazu-coding-system))
+       program-coding-system-alist
+       (file-name-coding-system gnus-namazu-coding-system)
+       (pathname-coding-system gnus-namazu-coding-system))
+    (apply 'call-process
+          `(,gnus-namazu-command
+            nil                        ; input from /dev/null
+            t                          ; output
+            nil                        ; don't redisplay
+            "-q"                       ; don't be verbose
+            "-a"                       ; show all matches
+            "-l"                       ; use list format
+            ,@gnus-namazu-additional-arguments
+            ,query
+            ,@gnus-namazu-index-directories))))
+
+(defvar gnus-namazu/directory-table nil)
+(defun gnus-namazu/make-directory-table (&optional force)
+  (interactive (list t))
+  (unless (and (not force)
+              gnus-namazu/directory-table
+              (eq gnus-namazu-case-sensitive-filesystem
+                  (car gnus-namazu/directory-table)))
+    (let ((table (make-vector (length gnus-newsrc-hashtb) 0))
+         cache agent alist dir method)
+      (mapatoms
+       (lambda (group)
+        (unless (gnus-ephemeral-group-p (setq group (symbol-name group)))
+          (when (file-directory-p
+                 (setq dir (file-name-as-directory
+                            (gnus-cache-file-name group ""))))
+            (push (cons dir group) cache))
+          (when (file-directory-p
+                 (setq dir (gnus-agent-group-pathname group)))
+            (push (cons dir group) agent))
+          (when (memq (car (setq method (gnus-find-method-for-group group)))
+                      '(nnml nnmh))
+            (when (file-directory-p
+                   (setq dir (nnmail-group-pathname
+                              (gnus-group-short-name group)
+                              (gnus-namazu/server-directory method))))
+              (push (cons dir group) alist)))))
+       gnus-newsrc-hashtb)
+      (dolist (pair (nconc agent cache alist))
+       (set (intern (if gnus-namazu-case-sensitive-filesystem
+                        (car pair)
+                      (downcase (car pair)))
+                    table)
+            (cdr pair)))
+      (setq gnus-namazu/directory-table
+           (cons gnus-namazu-case-sensitive-filesystem table)))))
+
+(defun gnus-namazu/search (groups query)
+  (gnus-namazu/make-directory-table)
+  (with-temp-buffer
+    (let ((exit-status (gnus-namazu/call-namazu query)))
+      (unless (zerop exit-status)
+       (error "Namazu finished abnormally: %d" exit-status)))
+    (gnus-namazu/normalize-results)
+    (goto-char (point-min))
+    (let (articles group)
+      (while (not (eobp))
+       (setq group (buffer-substring-no-properties
+                    (point)
+                    (progn
+                      (end-of-line)
+                      ;; NOTE: Only numeric characters are permitted
+                      ;; as file names of articles.
+                      (skip-chars-backward "0-9")
+                      (point))))
+       (and (setq group
+                  (symbol-value
+                   (intern-soft (if gnus-namazu-case-sensitive-filesystem
+                                    group
+                                  (downcase group))
+                                (cdr gnus-namazu/directory-table))))
+            (or (not groups)
+                (member group groups))
+            (push (gnus-namazu/make-article
+                   group
+                   (string-to-number
+                    (buffer-substring-no-properties (point)
+                                                    (gnus-point-at-eol))))
+                  articles))
+       (forward-line 1))
+      (nreverse articles))))
+
+;;; User Interface:
+(defun gnus-namazu/get-target-groups ()
+  (cond
+   ((eq major-mode 'gnus-group-mode)
+    ;; In Group buffer.
+    (cond
+     (current-prefix-arg
+      (gnus-group-process-prefix current-prefix-arg))
+     (gnus-group-marked
+      (prog1 gnus-group-marked (gnus-group-unmark-all-groups)))))
+   ((eq major-mode 'gnus-summary-mode)
+    ;; In Summary buffer.
+    (if current-prefix-arg
+       (list (gnus-read-group "Group: "))
+      (if (and
+          (gnus-ephemeral-group-p gnus-newsgroup-name)
+          (string-match gnus-namazu/group-name-regexp gnus-newsgroup-name))
+         (cadr (assq 'gnus-namazu-target-groups
+                     (gnus-info-method (gnus-get-info gnus-newsgroup-name))))
+       (list gnus-newsgroup-name))))))
+
+(defun gnus-namazu/get-current-query ()
+  (and (eq major-mode 'gnus-summary-mode)
+       (gnus-ephemeral-group-p gnus-newsgroup-name)
+       (string-match gnus-namazu/group-name-regexp gnus-newsgroup-name)
+       (cadr (assq 'gnus-namazu-current-query
+                  (gnus-info-method (gnus-get-info gnus-newsgroup-name))))))
+
+(defvar gnus-namazu/read-query-original-buffer nil)
+(defvar gnus-namazu/read-query-prompt nil)
+(defvar gnus-namazu/read-query-history nil)
+
+(defun gnus-namazu/get-current-subject ()
+  (and gnus-namazu/read-query-original-buffer
+       (bufferp gnus-namazu/read-query-original-buffer)
+       (with-current-buffer gnus-namazu/read-query-original-buffer
+        (when (eq major-mode 'gnus-summary-mode)
+          (let ((s (gnus-summary-article-subject)))
+            ;; Remove typically prefixes of mailing lists.
+            (when (string-match
+                   "^\\(\\[[^]]*[0-9]+\\]\\|([^)]*[0-9]+)\\)\\s-*" s)
+              (setq s (substring s (match-end 0))))
+            (when (string-match
+                   "^\\(Re\\(\\^?\\([0-9]+\\|\\[[0-9]+\\]\\)\\)?:\\s-*\\)+" s)
+              (setq s (substring s (match-end 0))))
+            (when (string-match "\\s-*(\\(re\\|was\\)\\b" s)
+              (setq s (substring s 0 (match-beginning 0))))
+            s)))))
+
+(defun gnus-namazu/get-current-from ()
+  (and gnus-namazu/read-query-original-buffer
+       (bufferp gnus-namazu/read-query-original-buffer)
+       (with-current-buffer gnus-namazu/read-query-original-buffer
+        (when (eq major-mode 'gnus-summary-mode)
+          (cadr (mail-extract-address-components
+                 (mail-header-from
+                  (gnus-summary-article-header))))))))
+
+(defun gnus-namazu/get-current-to ()
+  (and gnus-namazu/read-query-original-buffer
+       (bufferp gnus-namazu/read-query-original-buffer)
+       (with-current-buffer gnus-namazu/read-query-original-buffer
+        (when (eq major-mode 'gnus-summary-mode)
+          (cadr (mail-extract-address-components
+                 (cdr (assq 'To (mail-header-extra
+                                 (gnus-summary-article-header))))))))))
+
+(defmacro gnus-namazu/minibuffer-prompt-end ()
+  (if (fboundp 'minibuffer-prompt-end)
+      '(minibuffer-prompt-end)
+    '(point-min)))
+
+(defun gnus-namazu/message (string &rest arguments)
+  (let* ((s1 (concat
+             gnus-namazu/read-query-prompt
+             (buffer-substring (gnus-namazu/minibuffer-prompt-end)
+                               (point-max))))
+        (s2 (apply (function format) string arguments))
+        (w (- (window-width)
+              (string-width s1)
+              (string-width s2)
+              1)))
+    (message (if (>= w 0)
+                (concat s1 (make-string w ?\ ) s2)
+              s2))
+    (if (sit-for 0.3) (message s1))
+    s2))
+
+(defun gnus-namazu/complete-query ()
+  (interactive)
+  (let ((pos (point)))
+    (cond
+     ((and (re-search-backward "\\+\\([-a-z]*\\)" nil t)
+          (= pos (match-end 0)))
+      (let* ((partial (match-string 1))
+            (completions
+             (all-completions
+              partial
+              (mapcar 'list gnus-namazu-field-keywords))))
+       (cond
+        ((null completions)
+         (gnus-namazu/message "No completions of %s" partial))
+        ((= 1 (length completions))
+         (goto-char (match-beginning 1))
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (car completions) ":")
+         (setq pos (point))
+         (gnus-namazu/message "Completed"))
+        (t
+         (let ((x (try-completion partial (mapcar 'list completions))))
+           (if (string= x partial)
+               (if (and (eq last-command
+                            'gnus-namazu/field-keyword-completion)
+                        completion-auto-help)
+                   (with-output-to-temp-buffer "*Completions*"
+                     (display-completion-list completions))
+                 (gnus-namazu/message "Sole completion"))
+             (goto-char (match-beginning 1))
+             (delete-region (match-beginning 1) (match-end 1))
+             (insert x)
+             (setq pos (point))))))))
+     ((and (looking-at "\\+subject:")
+          (= pos (match-end 0)))
+      (let ((s (gnus-namazu/get-current-subject)))
+       (when s
+         (goto-char pos)
+         (insert "\"" s "\"")
+         (setq pos (point)))))
+     ((and (looking-at "\\+from:")
+          (= pos (match-end 0)))
+      (let ((f (gnus-namazu/get-current-from)))
+       (when f
+         (goto-char pos)
+         (insert "\"" f "\"")
+         (setq pos (point)))))
+     ((and (looking-at "\\+to:")
+          (= pos (match-end 0)))
+      (let ((to (gnus-namazu/get-current-to)))
+       (when to
+         (goto-char pos)
+         (insert "\"" to "\"")
+         (setq pos (point))))))
+    (goto-char pos)))
+
+(defvar gnus-namazu/read-query-map
+  (let ((keymap (copy-keymap minibuffer-local-map)))
+    (define-key keymap "\t" 'gnus-namazu/complete-query)
+    keymap))
+
+(defun gnus-namazu/read-query (prompt &optional initial)
+  (let ((gnus-namazu/read-query-original-buffer (current-buffer))
+       (gnus-namazu/read-query-prompt prompt))
+    (unless initial
+      (when (setq initial (gnus-namazu/get-current-query))
+       (setq initial (cons initial 0))))
+    (read-from-minibuffer prompt initial gnus-namazu/read-query-map nil
+                         'gnus-namazu/read-query-history)))
+
+(defun gnus-namazu/highlight-words (query)
+  (with-temp-buffer
+    (insert " " query)
+    ;; Remove tokens for NOT search
+    (goto-char (point-min))
+    (while (re-search-forward "[\e$B!!\e(B \t\r\f\n]+not[\e$B!!\e(B \t\r\f\n]+\
+\\([^\e$B!!\e(B \t\r\f\n\"{(/]+\\|\"[^\"]+\"\\|{[^}]+}\\|([^)]+)\\|/[^/]+/\\)+" nil t)
+      (delete-region (match-beginning 0) (match-end 0)))
+    ;; Remove tokens for Field search
+    (goto-char (point-min))
+    (while (re-search-forward "[\e$B!!\e(B \t\r\f\n]+\\+[^\e$B!!\e(B \t\r\f\n:]+:\
+\\([^\e$B!!\e(B \t\r\f\n\"{(/]+\\|\"[^\"]+\"\\|{[^}]+}\\|([^)]+)\\|/[^/]+/\\)+" nil t)
+      (delete-region (match-beginning 0) (match-end 0)))
+    ;; Remove tokens for Regexp search
+    (goto-char (point-min))
+    (while (re-search-forward "/[^/]+/" nil t)
+      (delete-region (match-beginning 0) (match-end 0)))
+    ;; Remove brackets, double quote, asterisk and operators
+    (goto-char (point-min))
+    (while (re-search-forward "\\([(){}\"*]\\|\\b\\(and\\|or\\)\\b\\)" nil t)
+      (delete-region (match-beginning 0) (match-end 0)))
+    ;; Collect all keywords
+    (setq query nil)
+    (goto-char (point-min))
+    (while (re-search-forward "[^\e$B!!\e(B \t\r\f\n]+" nil t)
+      (push (match-string 0) query))
+    (when query
+      (let (en ja)
+       (dolist (q query)
+         (if (string-match "\\cj" q)
+             (push q ja)
+           (push q en)))
+       (append
+        (when en
+          (list (list (concat "\\b\\(" (regexp-opt en) "\\)\\b")
+                      0 0 'gnus-namazu-query-highlight-face)))
+        (when ja
+          (list (list (regexp-opt ja)
+                      0 0 'gnus-namazu-query-highlight-face))))))))
+
+(defun gnus-namazu/truncate-article-list (articles)
+  (let ((hit (length articles)))
+    (when (and gnus-large-newsgroup
+              (> hit gnus-large-newsgroup))
+      (let* ((cursor-in-echo-area nil)
+            (input (read-from-minibuffer
+                    (format "\
+Too many articles were retrieved.  How many articles (max %d): "
+                            hit)
+                    (cons (number-to-string gnus-large-newsgroup) 0))))
+       (unless (string-match "\\`[ \t]*\\'" input)
+         (setcdr (nthcdr (min (1- (string-to-number input)) hit) articles)
+                 nil)))))
+  articles)
+
+;;;###autoload
+(defun gnus-namazu-search (groups query)
+  "Search QUERY through GROUPS with Namazu,
+and make a virtual group contains its results."
+  (interactive
+   (list
+    (gnus-namazu/get-target-groups)
+    (gnus-namazu/read-query "Enter query: ")))
+  (gnus-namazu/setup)
+  (let ((articles (gnus-namazu/search groups query)))
+    (if articles
+       (let ((real-groups groups)
+             (vgroup
+              (apply (function format)
+                     "nnvirtual:namazu-search?query=%s&groups=%s&id=%d%d%d"
+                     query
+                     (if groups (mapconcat 'identity groups ",") "ALL")
+                     (current-time))))
+         (gnus-namazu/truncate-article-list articles)
+         (unless real-groups
+           (dolist (a articles)
+             (add-to-list 'real-groups (gnus-namazu/article-group a))))
+         ;; Generate virtual group which includes all results.
+         (when (fboundp 'gnus-group-decoded-name)
+           (setq vgroup
+                 (encode-coding-string vgroup gnus-namazu-coding-system)))
+         (setq vgroup
+               (gnus-group-read-ephemeral-group
+                vgroup
+                `(nnvirtual ,vgroup
+                            (nnvirtual-component-groups ,real-groups)
+                            (gnus-namazu-target-groups ,groups)
+                            (gnus-namazu-current-query ,query))
+                t (cons (current-buffer) (current-window-configuration)) t))
+         (when gnus-namazu-query-highlight
+           (gnus-group-set-parameter vgroup 'highlight-words
+                                     (gnus-namazu/highlight-words query)))
+         ;; Generate new summary buffer which contains search results.
+         (gnus-group-read-group
+          t t vgroup
+          (sort (delq nil ;; Ad-hoc fix, to avoid wrong-type-argument error.
+                      (mapcar
+                       (lambda (a)
+                         (nnvirtual-reverse-map-article
+                          (gnus-namazu/article-group a)
+                          (gnus-namazu/article-number a)))
+                       articles))
+                '<)))
+      (message "No entry."))))
+
+(defmacro gnus-namazu/lock-file-name (&optional directory)
+  `(expand-file-name "NMZ.lock2" ,directory))
+
+(defmacro gnus-namazu/status-file-name (&optional directory)
+  `(expand-file-name "NMZ.status" ,directory))
+
+(defmacro gnus-namazu/index-file-name (&optional directory)
+  `(expand-file-name "NMZ.i" ,directory))
+
+(defun gnus-namazu/mknmz-cleanup (directory)
+  (let ((lockfile (gnus-namazu/lock-file-name directory)))
+    (when (file-exists-p lockfile)
+      (delete-file lockfile)
+      (dolist (tmpfile (directory-files directory t "\\`NMZ\\..*\\.tmp\\'" t))
+       (delete-file tmpfile)))))
+
+;;;###autoload
+(defun gnus-namazu-create-index (directory &optional target-directories force)
+  "Create index under DIRECTORY."
+  (interactive
+   (list
+    (if (and current-prefix-arg (> (length gnus-namazu-index-directories) 1))
+       (completing-read "Directory: "
+                        (mapcar 'list gnus-namazu-index-directories) nil t)
+      (gnus-namazu/default-index-directory))
+    nil t))
+  (setq directory (file-name-as-directory (expand-file-name directory)))
+  (unless target-directories
+    (setq target-directories
+         (delq nil
+               (mapcar (lambda (dir)
+                         (when (file-directory-p dir) dir))
+                       (append
+                        (mapcar 'gnus-namazu/server-directory
+                                (gnus-namazu/indexed-servers))
+                        (list
+                         (expand-file-name gnus-cache-directory)
+                         (expand-file-name gnus-agent-directory)))))))
+  (if (file-exists-p (gnus-namazu/lock-file-name directory))
+      (when force
+       (error "Found lock file: %s" (gnus-namazu/lock-file-name directory)))
+    (with-current-buffer
+       (get-buffer-create (concat " *mknmz*" directory))
+      (erase-buffer)
+      (unless (file-directory-p directory)
+       (make-directory directory t))
+      (setq default-directory directory)
+      (let ((args (append gnus-namazu-make-index-arguments
+                         target-directories)))
+       (insert "% " gnus-namazu-make-index-command " "
+               (mapconcat 'identity args " ") "\n")
+       (goto-char (point-max))
+       (when force
+         (pop-to-buffer (current-buffer)))
+       (message "Make index at %s..." directory)
+       (unwind-protect
+           (apply 'call-process gnus-namazu-make-index-command nil t t args)
+         (gnus-namazu/mknmz-cleanup directory))
+       (message "Make index at %s...done" directory)
+       (unless force
+         (kill-buffer (current-buffer)))))
+    (gnus-namazu/make-directory-table t)))
+
+(defun gnus-namazu/lapse-seconds (start end)
+  "Return lapse seconds from START to END.
+START and END are lists which represent time in Emacs-style."
+  (+ (* (- (car end) (car start)) 65536)
+     (cadr end)
+     (- (cadr start))))
+
+(defun gnus-namazu/index-old-p (directory)
+  "Return non-nil value when the index under the DIRECTORY is older
+than the period that is set to `gnus-namazu-index-update-interval'"
+  (let ((file (gnus-namazu/index-file-name directory)))
+    (or (not (file-exists-p file))
+       (and (integerp gnus-namazu-index-update-interval)
+            (>= (gnus-namazu/lapse-seconds
+                 (nth 5 (file-attributes file))
+                 (current-time))
+                gnus-namazu-index-update-interval)))))
+
+(defvar gnus-namazu/update-directories nil)
+(defvar gnus-namazu/update-process nil)
+
+(defun gnus-namazu/update-p (directory &optional force)
+  "Return the DIRECTORY when the index undef the DIRECTORY should be updated."
+  (setq directory (file-name-as-directory (expand-file-name directory)))
+  (labels ((error-message (format &rest args)
+                         (apply (if force 'error 'message) format args)
+                         nil))
+    (if gnus-namazu/update-process
+       (error-message "%s" "Can not run two update processes simultaneously")
+      (and (or force
+              (gnus-namazu/index-old-p directory))
+          (let ((status-file (gnus-namazu/status-file-name directory)))
+            (or (file-exists-p status-file)
+                (error-message "Can not find status file: %s" status-file)))
+          (let ((lock-file (gnus-namazu/lock-file-name directory)))
+            (or (not (file-exists-p lock-file))
+                (error-message "Found lock file: %s" lock-file)))
+          directory))))
+
+;;;###autoload
+(defun gnus-namazu-update-index (directory &optional force)
+  "Update the index under the DIRECTORY."
+  (interactive
+   (list
+    (if (and current-prefix-arg (> (length gnus-namazu-index-directories) 1))
+       (completing-read "Directory: "
+                        (mapcar 'list gnus-namazu-index-directories) nil t)
+      (gnus-namazu/default-index-directory))
+    t))
+  (when (setq directory (gnus-namazu/update-p directory force))
+    (with-current-buffer (get-buffer-create (concat " *mknmz*" directory))
+      (buffer-disable-undo)
+      (erase-buffer)
+      (unless (file-directory-p directory)
+       (make-directory directory t))
+      (setq default-directory directory)
+      (let ((proc (start-process gnus-namazu-make-index-command
+                                (current-buffer)
+                                gnus-namazu-make-index-command
+                                (format "--update=%s" directory))))
+       (if (processp proc)
+           (prog1 (setq gnus-namazu/update-process proc)
+             (process-kill-without-query proc)
+             (set-process-sentinel proc 'gnus-namazu/update-sentinel)
+             (add-hook 'kill-emacs-hook 'gnus-namazu-stop-update)
+             (message "Update index at %s..." directory))
+         (goto-char (point-min))
+         (if (re-search-forward "^ERROR:.*$" nil t)
+             (progn
+               (pop-to-buffer (current-buffer))
+               (funcall (if force 'error 'message)
+                        "Update index at %s...%s" directory (match-string 0)))
+           (kill-buffer (current-buffer))
+           (funcall (if force 'error 'message)
+                    "Can not start %s" gnus-namazu-make-index-command))
+         nil)))))
+
+;;;###autoload
+(defun gnus-namazu-update-all-indices (&optional force)
+  "Update all indices which is set to `gnus-namazu-index-directories'."
+  (interactive (list t))
+  (gnus-namazu-update-indices gnus-namazu-index-directories force))
+
+(defun gnus-namazu-update-indices (&optional directories force)
+  (when (setq directories
+             (delq nil (mapcar (lambda (d) (gnus-namazu/update-p d force))
+                               directories)))
+    (setq gnus-namazu/update-directories (cons force (cdr directories)))
+    (gnus-namazu-update-index (car directories) force)))
+
+(defun gnus-namazu/update-sentinel (process event)
+  (let ((buffer (process-buffer process)))
+    (when (buffer-name buffer)
+      (with-current-buffer buffer
+       (gnus-namazu/mknmz-cleanup default-directory)
+       (goto-char (point-min))
+       (cond
+        ((re-search-forward "^ERROR:.*$" nil t)
+         (pop-to-buffer (current-buffer))
+         (message "Update index at %s...%s"
+                  default-directory (match-string 0))
+         (setq gnus-namazu/update-directories nil))
+        ((and (eq 'exit (process-status process))
+              (zerop (process-exit-status process)))
+         (message "Update index at %s...done" default-directory)
+         (unless (or debug-on-error debug-on-quit)
+           (kill-buffer buffer)))))))
+  (setq gnus-namazu/update-process nil)
+  (unless (gnus-namazu-update-indices (cdr gnus-namazu/update-directories)
+                                     (car gnus-namazu/update-directories))
+    (gnus-namazu/make-directory-table t)))
+
+;;;###autoload
+(defun gnus-namazu-stop-update ()
+  "Stop the running indexer of Namazu."
+  (interactive)
+  (setq gnus-namazu/update-directories nil)
+  (and gnus-namazu/update-process
+       (processp gnus-namazu/update-process)
+       (kill-process gnus-namazu/update-process)))
+
+(let (current-load-list)
+  (defadvice gnus-offer-save-summaries
+    (before gnus-namazu-kill-summary-buffers activate compile)
+    "Advised by `gnus-namazu'.
+In order to avoid annoying questions, kill summary buffers which
+generated by `gnus-namazu' itself before `gnus-offer-save-summaries'
+is called."
+    (let ((buffers (buffer-list)))
+      (while buffers
+       (when (with-current-buffer (car buffers)
+               (and (eq major-mode 'gnus-summary-mode)
+                    (gnus-ephemeral-group-p gnus-newsgroup-name)
+                    (string-match gnus-namazu/group-name-regexp
+                                  gnus-newsgroup-name)))
+         (kill-buffer (car buffers)))
+       (setq buffers (cdr buffers))))))
+
+;;;###autoload
+(defun gnus-namazu-insinuate ()
+  (add-hook
+   'gnus-group-mode-hook
+   (lambda ()
+     (define-key gnus-group-mode-map "\C-c\C-n" 'gnus-namazu-search)))
+  (add-hook
+   'gnus-summary-mode-hook
+   (lambda ()
+     (define-key gnus-summary-mode-map "\C-c\C-n" 'gnus-namazu-search))))
+
+(provide 'gnus-namazu)
+
+;; gnus-namazu.el ends here.
index 4b761bc..086b9f4 100644 (file)
@@ -1,7 +1,10 @@
 ;;; gnus-nocem.el --- NoCeM pseudo-cancellation treatment
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2004
+;;        Free Software Foundation, Inc.
+
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -26,6 +29,7 @@
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
 
 (require 'gnus)
 (require 'nnmail)
   :type '(repeat (string :tag "Group")))
 
 (defcustom gnus-nocem-issuers
-  '("AutoMoose-1" "Automoose-1"                ; CancelMoose[tm]
-    "rbraver@ohww.norman.ok.us"                ; Robert Braver
-    "clewis@ferret.ocunix.on.ca"       ; Chris Lewis
-    "jem@xpat.com"                     ; Despammer from Korea
-    "snowhare@xmission.com"            ; Benjamin "Snowhare" Franz
-    "red@redpoll.mrfs.oh.us (Richard E. Depew)" ; ARMM! ARMM!
-    )
+  '("AutoMoose-1"                      ; CancelMoose[tm]
+    "clewis@ferret.ocunix"             ; Chris Lewis
+    "cosmo.roadkill"
+    "SpamHippo"
+    "hweede@snafu.de")
   "*List of NoCeM issuers to pay attention to.
 
-This can also be a list of `(ISSUER CONDITIONS)' elements."
+This can also be a list of `(ISSUER CONDITION ...)' elements.
+
+See <URL:http://www.xs4all.nl/~rosalind/nocemreg/nocemreg.html> for an
+issuer registry."
   :group 'gnus-nocem
+  :link '(url-link "http://www.xs4all.nl/~rosalind/nocemreg/nocemreg.html")
   :type '(repeat (choice string sexp)))
 
 (defcustom gnus-nocem-directory
@@ -80,8 +86,23 @@ isn't bound, the message will be used unconditionally."
 (defcustom gnus-nocem-liberal-fetch nil
   "*If t try to fetch all messages which have @@NCM in the subject.
 Otherwise don't fetch messages which have references or whose message-id
-matches an previously scanned and verified nocem message."
+matches a previously scanned and verified nocem message."
+  :group 'gnus-nocem
+  :type 'boolean)
+
+(defcustom gnus-nocem-check-article-limit 500
+  "*If non-nil, the maximum number of articles to check in any NoCeM group."
+  :group 'gnus-nocem
+  :version "21.1"
+  :type '(choice (const :tag "unlimited" nil)
+                (integer 1000)))
+
+(defcustom gnus-nocem-check-from t
+  "Non-nil means check for valid issuers in message bodies.
+Otherwise don't bother fetching articles unless their author matches a
+valid issuer, which is much faster if you are selective about the issuers."
   :group 'gnus-nocem
+  :version "21.1"
   :type 'boolean)
 
 ;;; Internal variables
@@ -108,8 +129,7 @@ matches an previously scanned and verified nocem message."
   "Real-name mappings of subscribed groups.")
 
 (defun gnus-fill-real-hashtb ()
-  "Fill up a hash table with the real-name mappings from the user's
-active file."
+  "Fill up a hash table with the real-name mappings from the user's active file."
   (setq gnus-nocem-real-group-hashtb (gnus-make-hashtable
                                      (length gnus-newsrc-alist)))
   (mapcar (lambda (group)
@@ -122,7 +142,7 @@ active file."
   (interactive)
   (let ((groups gnus-nocem-groups)
        (gnus-inhibit-demon t)
-       group active gactive articles)
+       group active gactive articles check-headers)
     (gnus-make-directory gnus-nocem-directory)
     ;; Load any previous NoCeM headers.
     (gnus-nocem-load-cache)
@@ -147,7 +167,7 @@ active file."
          (save-excursion
            (let ((dependencies (make-vector 10 nil))
                  headers header)
-             (nnheader-temp-write nil
+             (with-temp-buffer
                (setq headers
                      (if (eq 'nov
                              (gnus-retrieve-headers
@@ -168,13 +188,34 @@ active file."
                  ;; are not allowed to have references, so we can
                  ;; ignore scanning followups.
                  (and (string-match "@@NCM" (mail-header-subject header))
+                      (and gnus-nocem-check-from
+                           (let ((case-fold-search t))
+                             (catch 'ok
+                               (mapcar
+                                (lambda (author)
+                                  (if (consp author)
+                                      (setq author (car author)))
+                                  (if (string-match
+                                       author (mail-header-from header))
+                                      (throw 'ok t)))
+                                gnus-nocem-issuers)
+                               nil)))
                       (or gnus-nocem-liberal-fetch
                           (and (or (string= "" (mail-header-references
                                                 header))
                                    (null (mail-header-references header)))
                                (not (member (mail-header-message-id header)
                                             gnus-nocem-seen-message-ids))))
-                      (gnus-nocem-check-article group header)))))))
+                      (push header check-headers)))
+               (let* ((i 0)
+                      (check-headers
+                       (last check-headers gnus-nocem-check-article-limit))
+                      (len (length check-headers)))
+                 (dolist (h check-headers)
+                   (gnus-message
+                    7 "Checking article %d in %s for NoCeM (%d of %d)..."
+                    (mail-header-number h) group (incf i) len)
+                   (gnus-nocem-check-article group h)))))))
        (setq gnus-nocem-active
              (cons (list group gactive)
                    (delq (assoc group gnus-nocem-active)
@@ -186,14 +227,13 @@ active file."
 (defun gnus-nocem-check-article (group header)
   "Check whether the current article is an NCM article and that we want it."
   ;; Get the article.
-  (gnus-message 7 "Checking article %d in %s for NoCeM..."
-               (mail-header-number header) group)
   (let ((date (mail-header-date header))
+       (gnus-newsgroup-name group)
        issuer b e type)
     (when (or (not date)
-             (nnmail-time-less
-              (nnmail-time-since (nnmail-date-to-time date))
-              (nnmail-days-to-time gnus-nocem-expiry-wait)))
+             (time-less-p
+              (time-since (date-to-time date))
+              (days-to-time gnus-nocem-expiry-wait)))
       (gnus-request-article-this-buffer (mail-header-number header) group)
       (goto-char (point-min))
       (when (re-search-forward "-----BEGIN PGP MESSAGE-----" nil t)
@@ -258,7 +298,8 @@ active file."
       (while (search-forward "\t" nil t)
        (cond
         ((not (ignore-errors
-                (setq group (let ((obarray gnus-active-hashtb)) (read buf)))))
+                (setq group (let ((obarray gnus-nocem-real-group-hashtb))
+                              (read buf)))))
          ;; An error.
          )
         ((not (symbolp group))
@@ -272,7 +313,7 @@ active file."
                              gnus-nocem-real-group-hashtb)
            ;; Valid group.
            (beginning-of-line)
-           (while (= (following-char) ?\t)
+           (while (eq (char-after) ?\t)
              (forward-line -1))
            (setq id (buffer-substring (point) (1- (search-forward "\t"))))
            (unless (gnus-gethash id gnus-nocem-hashtb)
@@ -280,7 +321,7 @@ active file."
              (gnus-sethash id t gnus-nocem-hashtb)
              (push id ncm))
            (forward-line 1)
-           (while (= (following-char) ?\t)
+           (while (eq (char-after) ?\t)
              (forward-line 1))))))
       (when ncm
        (setq gnus-nocem-touched-alist t)
@@ -303,13 +344,13 @@ active file."
   "Save the NoCeM cache."
   (when (and gnus-nocem-alist
             gnus-nocem-touched-alist)
-    (nnheader-temp-write (gnus-nocem-cache-file)
+    (with-temp-file (gnus-nocem-cache-file)
       (gnus-prin1 `(setq gnus-nocem-alist ',gnus-nocem-alist)))
     (setq gnus-nocem-touched-alist nil)))
 
 (defun gnus-nocem-save-active ()
   "Save the NoCeM active file."
-  (nnheader-temp-write (gnus-nocem-active-file)
+  (with-temp-file (gnus-nocem-active-file)
     (gnus-prin1 `(setq gnus-nocem-active ',gnus-nocem-active))))
 
 (defun gnus-nocem-alist-to-hashtb ()
@@ -317,11 +358,11 @@ active file."
   (let* ((alist gnus-nocem-alist)
         (pprev (cons nil alist))
         (prev pprev)
-        (expiry (nnmail-days-to-time gnus-nocem-expiry-wait))
+        (expiry (days-to-time gnus-nocem-expiry-wait))
         entry)
     (setq gnus-nocem-hashtb (gnus-make-hashtable (* (length alist) 51)))
     (while (setq entry (car alist))
-      (if (not (nnmail-time-less (nnmail-time-since (car entry)) expiry))
+      (if (not (time-less-p (time-since (car entry)) expiry))
          ;; This entry has expired, so we remove it.
          (setcdr prev (cdr alist))
        (setq prev alist)
diff --git a/lisp/gnus-offline.el b/lisp/gnus-offline.el
new file mode 100644 (file)
index 0000000..79eaa10
--- /dev/null
@@ -0,0 +1,978 @@
+;;; gnus-offline.el --- To process mail & news at offline environment.
+
+;;; Copyright (C) 1998, 2001 Tatsuya Ichikawa
+;;; Copyright (C) 1998, 2001 Yukihiro Ito
+;;; Author: Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;;;         Yukihiro Ito <ito@rs.civil.tohoku.ac.jp>
+;;;         Hidekazu Nakamura <u90121@uis-inf.co.jp>
+;;;         Tsukamoto Tetsuo <czkmt@remus.dti.ne.jp>
+
+;;; Version: 2.20
+;;; Keywords: news , mail , offline , gnus
+;;;
+;;; SPECIAL THANKS
+;;;    Keiichi Suzuki <kei-suzu@mail.wbs.or.jp>
+;;;    KORIYAMA Naohiro <kory@ba2.so-net.or.jp>
+;;;    Katsumi Yamaoka <yamaoka@jpl.org>
+
+;;; This file is part of Semi-gnus.
+;;;
+;;; GNU Emacs is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+
+;;; GNU Emacs is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;;; Boston, MA 02111-1307, USA.
+;;;
+;;;; Commentary:
+;;; Note.
+;;;   This file works only with after version of Emacs 19.30.
+;;;   This file needs miee.el and SEMI.
+;;;   If you set gnus-offline-drafts-queue-type to 'agent , you don't need
+;;;   miee.el
+;;;   You must use T-gnus 6.12.0 or later.
+;;;
+;;; How to use.
+;;;
+;;; Add following code at the end in your .emacs
+;;;
+;;;    (load "gnus-ofsetup")
+;;;    (gnus-setup-for-offline)
+;;;
+;;; If you use gnus-agent as souper , put gnus-agent setup code in you .gnus.el
+;;;
+;;; If you use nnspool as souper , put following code in your .emacs before
+;;; gnus-offline setting.
+;;;
+;;; Then , put hang.exe in exec-path directory.
+;;;
+;;; In Gnus group buffer , type g to get all news and mail.
+;;; Then send mail and news in spool directory.
+;;;
+;;; Variables.
+;;;  gnus-offline-dialup-program-arguments
+;;;                                   ... List of dialup program arguments.
+;;;  gnus-offline-hangup-program-arguments
+;;;                                   ... List of hangup program arguments.
+;;;  gnus-offline-mail-treat-environ  ... toggle sending mail online/offline.
+;;;  gnus-offline-articles-to-fetch   ... toggle fetch articles.
+;;;                                        both->mail->news->both...
+;;;  gnus-offline-load-hook           ... hook before gnus-offline load.
+;;;  gnus-offline-before-online-hook  ... hook before all online jobs.
+;;;  gnus-offline-after-online-hook   ... hook after all online jobs.
+;;;  gnus-offline-interval-time       ... Interval time to do all online jobs.
+;;;                                        (minutes)
+;;;  gnus-offline-dialup-function     ... Function to diualup.
+;;;  gnus-offline-hangup-function     ... Function to hangup.
+
+;;; Code:
+
+(eval '(run-hooks 'gnus-offline-load-hook))
+
+(eval-when-compile (require 'cl))
+
+(eval-when-compile
+  (require 'static)
+  (require 'gnus-agent)
+  (require 'gnus-group))
+(require 'custom)
+(require 'easymenu)
+(provide 'gnus-offline)
+
+(defgroup gnus-offline nil
+  "Offline backend utility for Gnus."
+  :prefix "gnus-offline-"
+  :group 'gnus
+  :group 'mail
+  :group 'news)
+
+(defconst gnus-offline-version-number "2.20")
+(defconst gnus-offline-codename
+;;  "Beta5"                    ; Beta
+;;  "This is the time"         ; 2.00
+;;  "A matter of trust"
+;;  "Modern Woman"
+;;  "Ahhhhhhh!!"               ; 2.10b1
+  "Cup of life"                        ; 2.20
+;;  "Code of silence"
+  )
+
+(defconst gnus-offline-version (format "Gnus offline backend utiliy v%s"
+                                      gnus-offline-version-number))
+
+(eval-when-compile
+  (defvar nnagent-version)
+  (defvar nnspool-version)
+  (defvar msspool-news-server)
+  (defvar msspool-news-service)
+  (defvar miee-popup-menu))
+
+(if (featurep 'meadow)
+    (define-process-argument-editing "/hang\\.exe\\'"
+      (lambda (x)
+       (general-process-argument-editing-function
+        x nil t t nil t t))))
+
+(defcustom gnus-offline-auto-ppp '(connect disconnect)
+  "*This variable decides whether to connect and/or disconnect automatically."
+  :group 'gnus-offline
+  :type '(choice
+         (const :tag "Connection and Disconnection" (connect disconnect))
+         (const :tag "Connection Only" (connect))
+         (const :tag "Do Everything Manually" nil)))
+
+(defcustom gnus-offline-load-hook nil
+  "*Hook to be run after the gnus-offline package has been loaded."
+  :group 'gnus-offline
+  :type 'hook)
+
+(defcustom gnus-offline-before-online-hook nil
+  "*Hook to be run before all online jobs."
+  :group 'gnus-offline
+  :type 'hook)
+
+(defcustom gnus-offline-after-online-hook nil
+  "*Hook to be run after all online jobs."
+  :group 'gnus-offline
+  :type 'hook)
+
+(defcustom gnus-offline-mail-treat-environ 'offline
+  "*If online , gnus-offline send all mail under online environ.
+If offline , gnus-offline send all mail temporary to spool dir."
+  :group 'gnus-offline
+  :type '(choice (const offline)
+                (const online)))
+
+(defcustom gnus-offline-articles-to-fetch 'both
+  "*If both , gnus-offline fetch mail and news articles.
+If mail , gnus-offline only fetch mail articles.
+ If news , gnus-offline only fetch news articles."
+  :group 'gnus-offline
+  :type '(choice (const both)
+                (const mail)
+                (const news)))
+
+(defcustom gnus-offline-mail-group-level 1
+  "*Group level for mail group."
+  :group 'gnus-offline
+  :type 'integer)
+
+(defcustom gnus-offline-after-empting-spool-hook nil
+  "*Hook to be run before empting spool."
+  :group 'gnus-offline
+  :type 'hook)
+
+(defcustom gnus-offline-before-empting-spool-hook nil
+  "*Hook to be run after empting spool."
+  :group 'gnus-offline
+  :type 'hook)
+
+(defcustom gnus-offline-dialup-function 'gnus-offline-connect-server
+  "*Function to dialup."
+  :group 'gnus-offline
+  :type 'function)
+
+(defcustom gnus-offline-hangup-function 'gnus-offline-hangup-line
+  "*Function to hangup."
+  :group 'gnus-offline
+  :type 'function)
+
+(defcustom gnus-offline-auto-expire t
+  "*Non-nil means expire articles on every session."
+  :group 'gnus-offline
+  :type 'boolean)
+
+;; These variables should be customized using `gnus-offline-customize',
+;; not by `customize'.
+
+(defvar gnus-offline-dialup-program nil
+  "*Program name for dialup.")
+
+(defvar gnus-offline-hangup-program nil
+  "*Program name for hangup.")
+
+(defvar gnus-offline-dialup-program-arguments nil
+  "*Program arguments of gnus-offline-dialup-program.")
+
+(defvar gnus-offline-hangup-program-arguments nil
+  "*Program arguments of gnus-offline-hangup-program.")
+
+(defvar gnus-offline-interval-time 0
+  "*Interval time(minutes) to do online jobs.
+If set to 0 , timer call is disabled.")
+
+(defvar gnus-offline-drafts-queue-type 'agent
+  "*Queuing function used for draft messages.")
+
+(defvar gnus-offline-MTA-type 'smtp
+  "*Type of MTA, sendmail or smtp.el.")
+
+;;; Internal variables.
+(defvar gnus-offline-connected nil
+  "*If value is t , dialup line is connected status.
+If value is nil , dialup line is disconnected status.")
+
+(defvar gnus-offline-news-fetch-method nil
+  "*Method to fetch news articles.")
+
+(defvar gnus-offline-mail-fetch-method nil
+  "*Method to fetch mail articles.")
+
+(defvar gnus-offline-header-string
+  (format "%s - \"%s\""
+         gnus-offline-version
+         gnus-offline-codename)
+  "*Header string for gnus-offline.")
+
+(defvar gnus-offline-stored-group-level nil
+  "*Mail Group level before changing.")
+
+(defvar gnus-offline-mail-source nil
+  "*mail-sources save variable.")
+
+(defvar gnus-offline-lang)
+
+(defvar gnus-offline-resource-en
+  '((error-check-1
+     . "WARNING!!: gnus-agent.el or nnagent.el is not loaded.
+Please check your .emacs or .gnus.el to work gnus-agent fine.")
+    (error-check-2 ."WARNING!!: nnspool.el is not loaded.
+Please check your .emacs or .gnus.el to work nnspool fine.")
+    (connect-server-1 . "Dialing ...")
+    (connect-server-2 . "Dialing ... done.")
+    (get-new-news-function-1 . "Set to online status.")
+    (hangup-line-1 . "Hang up line ... ")
+    (hangup-line-2 . "Hang up line ... done.")
+    (after-jobs-done-1 . "All online jobs has done.")
+    (set-auto-ppp-1 . "Connect and disconnect automatically.")
+    (set-auto-ppp-2 . "Connect automatically.")
+    (set-auto-ppp-3 . "Connect and disconnect manually.")
+    (set-auto-ppp-menu-1 . "Automatically Connect/Disconnect")
+    (set-auto-ppp-menu-2 . "Automatically Connect")
+    (set-auto-ppp-menu-3 . "Manually Connect/Disconnect")
+    (toggle-on/off-send-mail-1 . "Sending mail immidiately.")
+    (toggle-on/off-send-mail-2 . "Sending mail temporary to spool directory.")
+    (toggle-articles-to-fetch-1 . "Articles fetch from server.")
+    (toggle-articles-to-fetch-2 . "Only Mail")
+    (toggle-articles-to-fetch-3 . "Only News")
+    (toggle-articles-to-fetch-4 . "Mail/News both")
+    (empting-spool-1 . "Sending mails in spool ...")
+    (empting-spool-2 . "Sending mails in spool ... done.")
+    (empting-spool-3 . "Posting news in spool ...")
+    (empting-spool-4 . "Posting news in spool ... done.")
+    (empting-spool-5 . "Sending messages in spool ...")
+    (empting-spool-6 . "Sending messages in spool ... done.")
+    (interval-time-1 . "Interval time (now %d minutes) : ")
+    (interval-time-2 . "Retrieving message logic by timer is disabled.")
+    (interval-time-3 . "Interval time set to %d minutes")
+    (menu-miee-1 . "Post news in spool")
+    (menu-miee-2 . "Send mails in spool")
+    (menu-miee-3 . "Message Offline")
+    (menu-miee-4 . "Message Online")
+    (menu-1 . "Toggle articles to fetch")
+    (menu-2 . "Toggle online/offline send mail")
+    (menu-3 . "Set auto PPP")
+    (menu-4 . "Expire articles")
+    (menu-5 . "Set interval time")
+    (menu-6 . "Hang up Line.")
+    (menu-7 . "Customize options...")))
+
+(defvar gnus-offline-resource-ja
+  '((error-check-1
+     . "\e$B7Y9p\e(B!!: gnus-agent.el \e$B$^$?$O\e(B nnagent.el \e$B$,%m!<%I$5$l$F$$$^$;$s!#\e(B
+.emacs \e$B$^$?$O\e(B .gnus.el \e$B$N\e(B gnus-agent \e$B$N@_Dj$r@5$7$/$7$F$/$@$5$$!#\e(B")
+    (error-check-2 ."\e$B7Y9p\e(B!!: nnspool.el \e$B$,%m!<%I$5$l$F$$$^$;$s!#\e(B
+.emacs \e$B$^$?$O\e(B .gnus.el \e$B$N\e(B nnspool \e$B$N@_Dj$r@5$7$/$7$F$/$@$5$$!#\e(B")
+    (connect-server-1 . "\e$B@\B3$7$F$$$^$9\e(B...")
+    (connect-server-2 . "\e$B@\B3$7$F$$$^$9\e(B...\e$B40N;!#\e(B")
+    (get-new-news-function-1 . "\e$B%*%s%i%$%s>uBV$G$9!#\e(B")
+    (set-auto-ppp-1 . "\e$B<+F0E*$K\e(B PPP \e$B@\B3!&@ZCG$7$^$9!#\e(B")
+    (set-auto-ppp-2 . "\e$B<+F0E*$K\e(B PPP \e$B@\B3$7$^$9!#\e(B")
+    (set-auto-ppp-3 . "\e$B<jF0$G\e(B PPP \e$B@\B3!&@ZCG$7$^$9!#\e(B")
+    (hangup-line-1 . "\e$B@ZCG$7$F$$$^$9\e(B...")
+    (hangup-line-2 . "\e$B@ZCG$7$F$$$^$9\e(B...\e$B40N;!#\e(B")
+    (after-jobs-done-1 . "\e$BA4$F$N%*%s%i%$%s=hM}$r40N;$7$^$7$?!#\e(B")
+    (toggle-on/off-send-mail-1 . "\e$B%a!<%k$rD>@\Aw?.$7$^$9!#\e(B")
+    (toggle-on/off-send-mail-2 . "\e$B%a!<%k$O%-%e!<$KAw$i$l$^$9!#\e(B")
+    (toggle-articles-to-fetch-1 . "\e$B<u?.$9$k%a%C%;!<%8$O\e(B... ")
+    (toggle-articles-to-fetch-2 . "\e$B%a!<%k$N$_$G$9!#\e(B")
+    (toggle-articles-to-fetch-3 . "\e$B%K%e!<%9$N$_$G$9!#\e(B")
+    (toggle-articles-to-fetch-4 . "\e$B%a!<%k$H%K%e!<%9$NN>J}$G$9!#\e(B")
+    (empting-spool-1 . "\e$B%-%e!<$N%a!<%k$rAw?.Cf\e(B...")
+    (empting-spool-2 . "\e$B%-%e!<$N%a!<%k$rAw?.Cf\e(B... \e$B40N;!#\e(B")
+    (empting-spool-3 . "\e$B%-%e!<$N%K%e!<%95-;v$rAw?.Cf\e(B...")
+    (empting-spool-4 . "\e$B%-%e!<$N%K%e!<%95-;v$rAw?.Cf\e(B... \e$B40N;!#\e(B")
+    (empting-spool-5 . "\e$B%-%e!<$N%a%C%;!<%8$rAw?.Cf\e(B...")
+    (empting-spool-6 . "\e$B%-%e!<$N%a%C%;!<%8$rAw?.Cf\e(B... \e$B40N;!#\e(B")
+    (interval-time-1 . "\e$BAw<u?.%8%g%V$N4V3V\e(B (\e$B8=:_$N@_Dj$O\e(B %d \e$BJ,$G$9\e(B) : ")
+    (interval-time-2 . "\e$B<+F0Aw<u?.5!G=$r\e(B \e$B%*%U\e(B \e$B$K$7$^$7$?!#\e(B")
+    (interval-time-3 . "\e$B<+F0Aw<u?.$N4V3V$r\e(B %d \e$BJ,$K@_Dj$7$^$7$?!#\e(B")))
+
+(defvar gnus-offline-resource-ja_complete
+  (append
+   gnus-offline-resource-ja
+   '((menu-miee-1 . "Spool \e$B$K$"$k5-;v$NAw?.\e(B")
+     (menu-miee-2 . "Spool \e$B$K$"$k\e(B Mail \e$B$NAw?.\e(B")
+     (menu-miee-3 . "Offline \e$B>uBV$X\e(B")
+     (menu-miee-4 . "Online \e$B>uBV$X\e(B")
+     (menu-1 . "\e$B<hF@5-;v<oN`$NJQ99\e(B")
+     (menu-2 . "Mail \e$BAw?.J}K!\e(B(On/Off)\e$B$N@ZBX$(\e(B")
+     (menu-3 . "\e$B<+F0\e(B PPP \e$B@)8f$N@_Dj\e(B")
+     (menu-4 . "\e$B<hF@:Q5-;v$r>C$9\e(B")
+     (menu-5 . "\e$B5-;v<hF@4V3V;~4V$N@_Dj\e(B")
+     (menu-6 . "\e$B2s@~$N@ZCG\e(B")
+     (menu-7 . "\e$B%W%m%Q%F%#\e(B...")
+     (set-auto-ppp-menu-1 . "\e$B<+F0E*$K\e(B PPP \e$B@\B3!&@ZCG\e(B")
+     (set-auto-ppp-menu-2 . "\e$B<+F0E*$K\e(B PPP \e$B@\B3\e(B")
+     (set-auto-ppp-menu-3 . "\e$B<jF0$G\e(B PPP \e$B@\B3!&@ZCG\e(B"))))
+
+;;; Functions
+
+;; Inline functions.
+(defsubst gnus-offline-gettext (symbol &optional lang)
+  (setq lang (or lang gnus-offline-lang))
+  (or
+   (cdr (assq symbol (symbol-value
+                     (intern (format "gnus-offline-resource-%s" lang)))))
+   (cdr (assq symbol gnus-offline-resource-en))))
+
+(defsubst gnus-offline-set-online-sendmail-function ()
+  "*Initialize sendmail-function when plugged status."
+  (if (eq gnus-offline-MTA-type 'smtp)
+      (setq message-send-mail-function 'message-send-mail-with-smtp)
+    (setq message-send-mail-function 'message-send-mail-with-sendmail)))
+
+(defsubst gnus-offline-set-offline-sendmail-function ()
+  "*Initialize sendmail-function when unplugged status."
+  (cond ((eq gnus-offline-drafts-queue-type 'miee)
+        (if (eq gnus-offline-news-fetch-method 'nnagent)
+            (setq gnus-agent-send-mail-function
+                  'sendmail-to-spool-in-gnspool-format))
+        (setq message-send-mail-function 'sendmail-to-spool-in-gnspool-format))
+       (t
+        (setq gnus-agent-send-mail-function
+              (gnus-offline-set-online-sendmail-function)
+              message-send-mail-function 'gnus-agent-send-mail))))
+
+(defsubst gnus-offline-set-offline-post-news-function ()
+  "*Initialize sendnews-function when unplugged status."
+  (if (eq gnus-offline-drafts-queue-type 'miee)
+      (setq message-send-news-function 'gnspool-request-post)))
+
+(defsubst gnus-offline-set-online-post-news-function ()
+  "*Initialize sendnews-function when plugged status."
+  (setq message-send-news-function 'message-send-news-with-gnus))
+
+(defsubst gnus-offline-disable-fetch-mail ()
+  "*Set do not fetch mail."
+  (setq mail-sources nil
+       nnmail-spool-file nil))
+
+(defsubst gnus-offline-enable-fetch-mail ()
+  "*Set to fetch mail."
+  (setq gnus-offline-mail-fetch-method 'nnmail)
+  (setq mail-sources gnus-offline-mail-source))
+
+(defsubst gnus-offline-enable-fetch-news ()
+  "*Set to fetch news."
+  (if (eq gnus-offline-news-fetch-method 'nnagent)
+      (progn
+       (setq gnus-agent-handle-level gnus-level-subscribed)
+       (gnus-agent-toggle-plugged t))))
+
+(when (featurep 'gnus-ofsetup)
+  ;; Advice to Gnus functions.
+  (defadvice gnus-group-get-new-news (before gnus-offline-advice
+                                            activate preactivate)
+    "When called interactively, dial up and get online automatically."
+    (when (interactive-p)
+      (run-hooks 'gnus-offline-before-online-hook)
+      (if (and (memq 'connect gnus-offline-auto-ppp)
+              (functionp gnus-offline-dialup-function))
+         (funcall gnus-offline-dialup-function))
+      (gnus-offline-get-new-news-function)))
+
+  (defadvice gnus-agent-toggle-plugged (around gnus-offline-advice
+                                              activate preactivate)
+    "Also toggle gnus-offline `connected--disconnected' status."
+    (interactive (list (not gnus-offline-connected)))
+    (cond ((ad-get-arg 0)
+          (setq gnus-offline-connected (ad-get-arg 0))
+          ad-do-it
+          ;; Set send mail/news function to offline functions.
+          (gnus-offline-set-online-sendmail-function)
+          (gnus-offline-set-online-post-news-function))
+         (t
+          ;; Set to offline status
+          (gnus-offline-set-unplugged-state))))
+
+  (defadvice gnus-agent-expire (around gnus-offline-advice activate preactivate)
+    "Advice not to delete new articles."
+    (cond ((eq 0 gnus-agent-expire-days)
+          (let (gnus-agent-expire-all)
+            ad-do-it))
+         (t
+          ad-do-it)))
+
+  (defadvice gnus-agent-mode (around gnus-offline-advice activate preactivate)
+    "Advice not to close PPP connection."
+    (let (gnus-offline-hangup-function)
+      ad-do-it)))
+
+;;
+;; Setting up...
+;;
+(defun gnus-offline-setup ()
+  "*Initialize gnus-offline function"
+
+  (when (eq gnus-offline-drafts-queue-type 'agent)
+    (setq gnus-offline-connected gnus-plugged))
+
+  (gnus-offline-processed-by-timer)
+  (gnus-offline-error-check)
+
+  ;; To transfer Mail/News function.
+  (cond        ((or (and (eq 'gnus-offline-drafts-queue-type 'agent)
+                 gnus-offline-connected)
+            (eq gnus-offline-mail-treat-environ 'online))
+        ;; send mail under offline environ.
+        (gnus-offline-set-online-sendmail-function))
+       (t
+        ;; send mail under offline environ.
+        (gnus-offline-set-offline-sendmail-function))))
+
+;;
+;; Setting Error check.
+(defun gnus-offline-error-check ()
+  ;; Check gnus-agent and nnspool setting.
+  (let ((buffer " *Offline Error*"))
+    (cond ((eq gnus-offline-news-fetch-method 'nnagent)
+          ;; nnagent and gnus-agent loaded ??
+          (unless (and (featurep 'gnus-agent)
+                       (featurep 'nnagent))
+            (set-buffer (gnus-get-buffer-create buffer))
+            (erase-buffer)
+            (insert (gnus-offline-gettext 'error-check-1))
+            (pop-to-buffer buffer)))
+
+         ((eq gnus-offline-news-fetch-method 'nnspool)
+          (unless (featurep 'nnspool)
+            (set-buffer (gnus-get-buffer-create buffer))
+            (erase-buffer)
+            (insert (gnus-offline-gettext 'error-check-2))
+            (pop-to-buffer buffer)))
+         (t
+          nil))))
+
+;;
+;; dialup...
+;;
+(defun gnus-offline-connect-server ()
+  "*Dialup function."
+  ;; Dialup if gnus-offline-dialup-program is specified
+  (if (stringp gnus-offline-dialup-program)
+      (progn
+       (message "%s" (gnus-offline-gettext 'connect-server-1))
+       (apply 'call-process gnus-offline-dialup-program nil nil nil
+              gnus-offline-dialup-program-arguments)
+       (sleep-for 1)
+       (message "%s" (gnus-offline-gettext 'connect-server-2)))))
+
+;;
+;; Jobs before get new news , send mail and post news.
+;;
+(defun gnus-offline-get-new-news-function ()
+  "*Prepare to get new news/mail."
+  ;; Set mail group level
+  (if (eq gnus-offline-articles-to-fetch 'mail)
+      (gnus-offline-set-mail-group-level gnus-offline-mail-group-level))
+
+  ;; Set to online environ.
+  (setq gnus-offline-connected t)
+
+  ;; Set send mail/news functions to online functions.
+  (gnus-offline-set-online-sendmail-function)
+  (gnus-offline-set-online-post-news-function)
+  (message "%s" (gnus-offline-gettext 'get-new-news-function-1))
+
+  ;; fetch only news
+  (if (eq gnus-offline-articles-to-fetch 'news)
+      (gnus-offline-disable-fetch-mail))
+
+  ;; fetch both mail and news. or Only mail.
+  (gnus-offline-enable-fetch-news)
+  (if (memq gnus-offline-articles-to-fetch '(both mail))
+      (gnus-offline-enable-fetch-mail))
+
+  ;; fetch only mail for gnus-agent
+  (if (and (eq gnus-offline-news-fetch-method 'nnagent)
+          (eq gnus-offline-articles-to-fetch 'mail))
+      (setq gnus-agent-handle-level gnus-offline-mail-group-level)))
+
+;;
+;; Change mail group level to handle only mail.
+;;
+(defun gnus-offline-set-mail-group-level (level)
+  "*Set nnm* group level."
+  (switch-to-buffer gnus-group-buffer)
+  (goto-char (point-min))
+
+  ;; Save current level
+  (if (not gnus-offline-stored-group-level)
+      (while (re-search-forward " nnm" nil t)
+       (setq gnus-offline-stored-group-level
+             (append gnus-offline-stored-group-level
+                     (list (gnus-group-group-level)))))
+    (forward-line 1)
+    (beginning-of-line))
+  ;;
+  (goto-char (point-min))
+  (while (re-search-forward " nnm" nil t)
+    (gnus-group-set-current-level 1 level)
+    (forward-line 1)
+    (beginning-of-line))
+  t)
+;;
+;; Restore mail group level
+;;
+(defun gnus-offline-restore-mail-group-level ()
+  "*Restore nnm* group level."
+  (switch-to-buffer gnus-group-buffer)
+  (goto-char (point-min))
+  (let ((num 0))
+    (while (re-search-forward " nnm" nil t)
+      (gnus-group-set-current-level 1 (nth num gnus-offline-stored-group-level))
+      (forward-line 1)
+      (setq num (+ num 1))
+      (beginning-of-line))))
+;;
+;; Jobs after getting new news.
+;;
+(defun gnus-offline-after-get-new-news ()
+  "*After getting news and mail jobs."
+  (cond (gnus-offline-connected
+        (when (memq gnus-offline-articles-to-fetch '(both mail))
+          ;; Mail/both
+          ;; send mail/news in spool
+          (gnus-offline-empting-spool)
+          (when (eq gnus-offline-articles-to-fetch 'mail)
+            ;; Send only mail and hang up...
+            (if gnus-offline-connected
+                (gnus-offline-set-unplugged-state))
+            ;; Disable fetch mail.
+            (gnus-offline-disable-fetch-mail)
+            (gnus-offline-after-jobs-done)))
+        (when (memq gnus-offline-articles-to-fetch '(both news))
+          ;; News/Both
+          (cond ((eq gnus-offline-news-fetch-method 'nnagent)
+                 ;; Get New News (gnus-agent)
+                 (gnus-agent-toggle-plugged t)
+                 ;; fetch articles
+                 (gnus-agent-fetch-session)
+                 ;; Hang Up line. then set to offline status.
+                 (gnus-offline-set-unplugged-state)
+                 ;; All online jobs has done.
+                 (gnus-offline-after-jobs-done))
+                (t
+                 (if (eq gnus-offline-news-fetch-method 'nnspool)
+                     ;; Get New News (nnspool)
+                     (gnspool-get-news))))))
+       (t
+        nil)))
+\f
+;;
+;; Add your custom header.
+;;
+(defun gnus-offline-add-custom-header (header string)
+  "*Add X-Gnus-Offline-Backend header to Mail/News message."
+  (let ((delimline
+        (progn (goto-char (point-min))
+               (re-search-forward
+                (concat "^" (regexp-quote mail-header-separator) "\n"))
+               (point-marker)))
+       hdr str)
+    (goto-char (point-min))
+    (unless (re-search-forward (concat "^" header) delimline t)
+      (goto-char delimline)
+      (forward-line -1)
+      (beginning-of-line)
+      (setq hdr (concat header " "))
+      (setq str (concat hdr string))
+      (setq hdr (concat str "\n"))
+      (insert hdr))))
+;;
+;; Add X-Offline-Backend header.
+;;
+(defun gnus-offline-message-add-header ()
+  "*Add X-Gnus-Offline-Backend header to Mail/News message."
+  (when (eq gnus-offline-mail-treat-environ 'offline)
+    (let* ((ver (if (eq gnus-offline-news-fetch-method 'nnagent)
+                   nnagent-version
+                 nnspool-version))
+          (str (format "\n                        with %s" ver)))
+      (gnus-offline-add-custom-header
+       "X-Gnus-Offline-Backend:" (concat gnus-offline-header-string str)))))
+
+\f
+;;
+;; Function of hang up line.
+;;
+(defun gnus-offline-set-unplugged-state ()
+  "*Set to unplugged state."
+  (interactive)
+  ;; Hang Up Line.
+  (if (and (memq 'disconnect gnus-offline-auto-ppp)
+          (functionp gnus-offline-hangup-function))
+      (funcall gnus-offline-hangup-function))
+  (setq gnus-offline-connected nil)
+  (if (eq gnus-offline-news-fetch-method 'nnagent)
+      (ad-Orig-gnus-agent-toggle-plugged nil))
+
+  ;; Set send mail/news function to offline functions.
+  (gnus-offline-set-offline-sendmail-function)
+  (gnus-offline-set-offline-post-news-function)
+  ;;
+  (setenv "MAILHOST" nil))
+;;
+;; Hangup line function
+;;
+(defun gnus-offline-hangup-line ()
+  "*Hangup line function."
+  (message "%s" (gnus-offline-gettext 'hangup-line-1))
+  (if (stringp gnus-offline-hangup-program)
+      (apply 'start-process "hup" nil gnus-offline-hangup-program
+            gnus-offline-hangup-program-arguments))
+  (message "%s" (gnus-offline-gettext 'hangup-line-2)))
+;;
+;; Hang Up line routine whe using nnspool
+;;
+(defun gnus-offline-nnspool-hangup-line ()
+  (if gnus-offline-connected
+      (gnus-offline-set-unplugged-state))
+  (gnus-offline-after-jobs-done))
+;;
+;; Function of all jobs has done.
+;;
+(defun gnus-offline-after-jobs-done ()
+  "*Jobs after all online jobs."
+  (run-hooks 'gnus-offline-after-online-hook)
+  (if (eq gnus-offline-articles-to-fetch 'mail)
+      (gnus-offline-restore-mail-group-level))
+  (if (and (eq gnus-offline-news-fetch-method 'nnagent)
+          gnus-offline-auto-expire)
+      (gnus-agent-expire))
+  (static-if (featurep 'xemacs)
+      (if (fboundp 'play-sound-file)
+         (ding nil 'drum)
+       (ding))
+    (ding))
+  (gnus-group-save-newsrc)
+  (message "%s" (gnus-offline-gettext 'after-jobs-done-1)))
+
+\f
+;;
+;; Set auto PPP
+;;
+(defun gnus-offline-set-auto-ppp ()
+  "*Decide whether to connect and/or disconnect automatically."
+  (interactive)
+  (let ((keys (key-description (this-command-keys)))
+       menu title str)
+    (cond ((or (string= "misc-user" keys)
+              (string= "S-mouse-2" keys)
+              (string-match "^menu-bar" keys)
+              (string-match "^mouse" keys))
+          (setq title (gnus-offline-gettext 'menu-3))
+          (setq menu
+                (cons title
+                      (gnus-offline-get-menu-items
+                       '((set-auto-ppp-menu-1
+                          (progn
+                            (setq gnus-offline-auto-ppp '(connect disconnect))
+                            (message "%s"
+                                     (gnus-offline-gettext 'set-auto-ppp-1)))
+                          t)
+                         (set-auto-ppp-menu-2
+                          (progn
+                            (setq gnus-offline-auto-ppp '(connect))
+                            (message "%s"
+                                     (gnus-offline-gettext 'set-auto-ppp-2)))
+                          t)
+                         (set-auto-ppp-menu-3
+                          (progn
+                            (setq gnus-offline-auto-ppp nil)
+                            (message "%s"
+                                     (gnus-offline-gettext 'set-auto-ppp-3)))
+                          t)))))
+          (gnus-offline-popup menu title))
+         (t
+          (cond ((eq gnus-offline-auto-ppp nil)
+                 (setq gnus-offline-auto-ppp '(connect disconnect))
+                 (setq str (gnus-offline-gettext 'set-auto-ppp-1)))
+                ((memq 'connect gnus-offline-auto-ppp)
+                 (cond ((memq 'disconnect gnus-offline-auto-ppp)
+                        (setq gnus-offline-auto-ppp '(connect))
+                        (setq str
+                              (gnus-offline-gettext 'set-auto-ppp-2)))
+                       (t
+                        (setq gnus-offline-auto-ppp nil)
+                        (setq str
+                              (gnus-offline-gettext 'set-auto-ppp-3))))))
+          (message "%s" str)))))
+;;
+;; Toggle offline/online to send mail.
+;;
+(defun gnus-offline-toggle-on/off-send-mail ()
+  "*Toggel online/offline sendmail."
+  (interactive)
+  (if (eq gnus-offline-mail-treat-environ 'offline)
+      (progn
+       ;; Sending mail under online environ.
+       (gnus-offline-set-online-sendmail-function)
+       (setq gnus-offline-mail-treat-environ 'online)
+       (message "%s" (gnus-offline-gettext 'toggle-on/off-send-mail-1)))
+    ;; Sending mail under offline environ.
+    (gnus-offline-set-offline-sendmail-function)
+    (setq gnus-offline-mail-treat-environ 'offline)
+    (message "%s" (gnus-offline-gettext 'toggle-on/off-send-mail-2))))
+;;
+;; Toggle articles to fetch ... both -> mail -> news -> both
+;;
+(defun gnus-offline-toggle-articles-to-fetch ()
+  "*Set articles to fetch... both(Mail/News) -> mail only -> News only -> both"
+  (interactive)
+  (let ((string (gnus-offline-gettext 'toggle-articles-to-fetch-1))
+       str)
+    (cond ((eq gnus-offline-articles-to-fetch 'both)
+          (setq gnus-offline-articles-to-fetch 'mail
+                str (gnus-offline-gettext 'toggle-articles-to-fetch-2)))
+         ((eq gnus-offline-articles-to-fetch 'mail)
+          (setq gnus-offline-articles-to-fetch 'news
+                str (gnus-offline-gettext 'toggle-articles-to-fetch-3)))
+         (t
+          (setq gnus-offline-articles-to-fetch 'both
+                str (gnus-offline-gettext 'toggle-articles-to-fetch-4))))
+    (message "%s %s" string str)))
+;;
+;; Send mail and Post news using Miee or gnus-agent.
+;;
+(defun gnus-offline-empting-spool ()
+  "*Send all drafts on queue."
+  (run-hooks 'gnus-offline-before-empting-spool-hook)
+  (if (eq gnus-offline-drafts-queue-type 'miee)
+      ;; Send queued message by miee.el.
+      (progn
+       (if (eq gnus-offline-mail-treat-environ 'offline)
+           (progn
+             (message "%s" (gnus-offline-gettext 'empting-spool-1))
+             ;; Using miee to send mail.
+             (mail-spool-send)
+             (message "%s" (gnus-offline-gettext 'empting-spool-2))))
+       (message "%s" (gnus-offline-gettext 'empting-spool-3))
+       ;; Using miee to post news.
+       (if (and (not (stringp msspool-news-server))
+                (not msspool-news-service))
+           (progn
+             (setq msspool-news-server (nth 1 gnus-select-method))
+             (setq msspool-news-service 119)))
+       (news-spool-post)
+       (message "%s" (gnus-offline-gettext 'empting-spool-4)))
+    ;; Send queued message by gnus-agent
+    (message "%s" (gnus-offline-gettext 'empting-spool-5))
+    (gnus-group-send-queue)
+    (message "%s" (gnus-offline-gettext 'empting-spool-6)))
+  ;;
+  (run-hooks 'gnus-offline-after-empting-spool-hook))
+;;
+;; Set interval time
+;;
+(defun gnus-offline-set-interval-time ()
+  "*Set interval time for gnus-daemon."
+  (interactive)
+  (setq gnus-offline-interval-time
+       (string-to-int (read-from-minibuffer
+                       (format (gnus-offline-gettext 'interval-time-1)
+                               gnus-offline-interval-time)
+                       nil)))
+  (if (< gnus-offline-interval-time 2)
+      (progn
+       (message "%s" (gnus-offline-gettext 'interval-time-2))
+       (setq gnus-offline-interval-time 0))
+    (message
+     (format (gnus-offline-gettext 'interval-time-3)
+            gnus-offline-interval-time)))
+  (gnus-offline-processed-by-timer))
+
+;;
+;; Menu.
+;;
+(defun gnus-offline-define-menu-and-key ()
+  "*Set key and menu."
+  (cond ((eq gnus-offline-drafts-queue-type 'miee)
+        (static-cond
+         ((featurep 'xemacs)
+          (add-hook 'gnus-group-mode-hook 'gnus-offline-define-menu-on-miee))
+         (t
+          (gnus-offline-define-menu-on-miee))))
+       (t
+        (add-hook 'gnus-group-mode-hook 'gnus-offline-define-menu-on-agent)))
+  ;;
+  (add-hook 'gnus-group-mode-hook
+           #'(lambda ()
+               (local-set-key "\C-coh" 'gnus-offline-set-unplugged-state)
+               (local-set-key "\C-cof" 'gnus-offline-toggle-articles-to-fetch)
+               (local-set-key "\C-coo" 'gnus-offline-toggle-on/off-send-mail)
+               (local-set-key "\C-cox" 'gnus-offline-set-auto-ppp)
+               (local-set-key "\C-cos" 'gnus-offline-set-interval-time)
+               (if (eq gnus-offline-news-fetch-method 'nnagent)
+                   (local-set-key "\C-coe" 'gnus-agent-expire))
+               (static-unless (featurep 'xemacs)
+                 (local-set-key
+                  (if (eq system-type 'windows-nt) [S-mouse-2] [mouse-3])
+                  'gnus-offline-popup-menu)))))
+
+;;
+;;
+(defun gnus-offline-popup (menu &optional title)
+  (static-cond
+   ((featurep 'xemacs)
+    (popup-menu menu))
+   (t
+    (let ((menu-func (or (and (fboundp 'easy-menu-create-menu)
+                             'easy-menu-create-menu)
+                        'easy-menu-create-keymaps))
+         keymap pop func)
+      (static-cond ((< emacs-major-version 20)
+                   ;; For Emacsen from 19.34 down to 19.28.
+                   ;; Seems the first item in MENU will be ignored.
+                   (or (keymapp menu)
+                       (setq menu
+                             (append (list ""  ;; This will be ignored.
+                                           (or title "Popup Menu")
+                                           "-----"
+                                           "-----")
+                                     (cdr menu))))
+                   (setq keymap
+                         (if (keymapp menu)
+                             (append (list 'keymap
+                                           (if title
+                                               `(nil ,title)
+                                             '(nil "Popup Menu"))
+                                           '(nil "")
+                                           '(nil ""))
+                                     (cdr menu))
+                           (funcall menu-func (car menu) (cdr menu)))))
+                  (t
+                   (setq keymap
+                         (if (keymapp menu)
+                             menu
+                           (funcall menu-func (car menu) (cdr menu))))))
+      ;; Display the popup menu.
+      (if (and (setq pop (x-popup-menu t keymap))
+              (setq func (lookup-key keymap
+                                     (apply 'vector pop))))
+         (funcall func))))))
+
+(defun gnus-offline-get-menu-items (list)
+  (let (result)
+    (dolist (elem list)
+      (setq result
+           (nconc result
+                  (list (if (listp elem)
+                            (progn
+                              (setcar elem (gnus-offline-gettext (car elem)))
+                              (vconcat elem))
+                          elem)))))
+    result))
+
+(defvar gnus-offline-menu
+  (gnus-offline-get-menu-items
+   '((menu-1 gnus-offline-toggle-articles-to-fetch t)
+     (menu-2 gnus-offline-toggle-on/off-send-mail t)
+     (menu-3 gnus-offline-set-auto-ppp t)
+     "----"
+     (menu-4 gnus-agent-expire
+            (eq gnus-offline-news-fetch-method 'nnagent))
+     (menu-5 gnus-offline-set-interval-time t)
+     "----"
+     (menu-6 gnus-offline-set-unplugged-state gnus-offline-connected)
+     "----"
+     (menu-7 gnus-ofsetup-customize t))))
+
+(defun gnus-offline-define-menu-on-miee ()
+  "*Set and change menu bar on MIEE menu."
+  (let ((miee-menu
+        (gnus-offline-get-menu-items
+         '((menu-miee-1 news-spool-post t)
+           (menu-miee-2 mail-spool-send t)
+           "----"
+           (menu-miee-3 message-offline-state (not message-offline-state))
+           (menu-miee-4 message-online-state message-offline-state)
+           "----")))
+       menu)
+    (setq menu
+         (easy-menu-change
+          nil "Miee"
+          (append miee-menu
+                  (list (cons "Gnus Offline" gnus-offline-menu)))))
+    (static-if (featurep 'xemacs)
+       (easy-menu-add menu))))
+;;
+;; define menu without miee.
+;;
+(defun gnus-offline-define-menu-on-agent ()
+  "*Set menu bar on OFFLINE menu."
+  (easy-menu-define
+   gnus-offline-menu-on-agent gnus-group-mode-map "Gnus offline Menu"
+   (cons "Offline" gnus-offline-menu))
+  (static-if (featurep 'xemacs)
+      (easy-menu-add gnus-offline-menu-on-agent)))
+;;
+;; Popup menu within the group buffer (under Emacs).
+;;
+(static-unless (featurep 'xemacs)
+  (defun gnus-offline-popup-menu (event)
+    "Popup menu for Gnus Offline."
+    (interactive "e")
+    (apply 'gnus-offline-popup
+          (if (boundp 'miee-popup-menu)
+              (list (or (assq 'keymap
+                              (assq 'Miee (assq 'menu-bar global-map)))
+                        miee-popup-menu)
+                    "Miee")
+            (list (symbol-value 'gnus-offline-menu-on-agent)
+                  "Offline")))))
+\f
+;;
+;; Timer Function
+(defun gnus-offline-processed-by-timer ()
+  "*Set timer interval."
+  (let ((func (lambda () (call-interactively 'gnus-group-get-new-news)))
+       (time gnus-offline-interval-time))
+    (cond ((and (> time 0) (not gnus-offline-connected))
+          ;; Timer call
+          (gnus-demon-add-handler func time time))
+         ((= gnus-offline-interval-time 0)
+          (gnus-demon-remove-handler func t)))))
+;;
+;; Code for making Gnus and Gnus Offline cooperate with each other.
+;;
+
+;; Display `X-Gnus-Offline-Backend' message header aesthetically.
+(eval-after-load "eword-decode"
+  '(mime-set-field-decoder 'X-Gnus-Offline-Backend nil nil))
+
+;; Enable key and menu definitions here.
+(eval '(funcall 'gnus-offline-define-menu-and-key))
+
+;;
+;;
+;;; gnus-offline.el ends here
diff --git a/lisp/gnus-ofsetup.el b/lisp/gnus-ofsetup.el
new file mode 100644 (file)
index 0000000..839db29
--- /dev/null
@@ -0,0 +1,757 @@
+;;; gnus-ofsetup.el --- Setup advisor for Offline reading for Mail/News.
+
+;; Copyright (C) 1998, 2001 Tatsuya Ichikawa
+
+;; Author: Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;;     Tsukamoto Tetsuo <czkmt@remus.dti.ne.jp>
+;;
+;; This file is part of Semi-gnus.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+;;
+
+;;; Commentary:
+
+;; How to use.
+;;
+;;      M-x load[RET]gnus-ofsetup
+;;      M-x gnus-setup-for-offline
+;;
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(eval-and-compile
+  (defvar gnus-offline-lang
+    (cond ((and (featurep 'meadow)
+               (string= current-language-environment "Japanese"))
+          "ja_complete")
+         ((and (boundp 'current-language-environment)
+               (string= current-language-environment "Japanese"))
+          "ja")
+         (t
+          "en"))
+    "This variable decides which language will be used for display."))
+
+(eval-when-compile
+  (require 'gnus)
+  (require 'gnus-offline))
+
+(defvar gnus-offline-setting-file
+  (let ((user (user-login-name))
+       (real-user (user-real-login-name)))
+    (if (string= user real-user)
+       "~/.gnus-offline.el"
+      ;; Seems it is after "su".
+      (let ((file (concat "~" user "/.gnus-offline.el"))
+           (real-file (concat "~" real-user "/.gnus-offline.el")))
+       (cond ((file-exists-p real-file)
+              real-file)
+             ((file-exists-p file)
+              file)
+             (t
+              real-file))))))
+
+(eval-when-compile
+  (defvar gnus-ofsetup-prepare-for-miee
+    '(;; Spool directory setting - MIEE.
+      (setq mail-spool (or mail-spool "/usr/spool/mail.out"))
+      (setq news-spool (or news-spool "/usr/spool/news.out"))
+      (condition-case nil
+         (progn
+           (if (not (file-exists-p mail-spool))
+               (make-directory mail-spool t))
+           (if (not (file-exists-p news-spool))
+               (make-directory news-spool t)))
+       (error
+        (error (gnus-ofsetup-gettext 'prepare-miee-1))))))
+
+  (defvar gnus-ofsetup-update-setting-file
+    '((save-excursion
+       (set-buffer (get-buffer-create "* Setting"))
+       (erase-buffer)
+       (insert ";;\n")
+       (insert ";; This file is created by gnus-ofsetup.el\n")
+       (insert ";; Creation date : " (current-time-string) "\n")
+       (insert ";;\n")
+
+       ;; write Basic setting
+       (insert "(setq gnus-offline-news-fetch-method '"
+               (prin1-to-string news-method) ")\n")
+       (insert "(setq gnus-offline-mail-fetch-method '"
+               (prin1-to-string mail-method) ")\n")
+
+       ;; write dialup/hangup program and options.
+       (insert "(setq gnus-offline-dialup-program "
+               (prin1-to-string dialup-program) ")\n")
+       (if (stringp dialup-program)
+           (insert "(setq gnus-offline-dialup-program-arguments '"
+                   (prin1-to-string dialup-program-arguments) ")\n"))
+       (insert "(setq gnus-offline-hangup-program "
+               (prin1-to-string hangup-program) ")\n")
+       (if (stringp hangup-program)
+           (insert "(setq gnus-offline-hangup-program-arguments '"
+                   (prin1-to-string hangup-program-arguments) ")\n"))
+
+       (if (integerp interval)
+           (insert "(setq gnus-offline-interval-time "
+                   (prin1-to-string interval) ")\n"))
+
+       ;; write setting about MIEE.
+       (when use-miee
+         (insert "(setq sendmail-to-spool-directory "
+                 (prin1-to-string mail-spool) ")\n")
+         (insert "(setq news-spool-request-post-directory "
+                 (prin1-to-string news-spool) ")\n")
+         (insert "(if (not (boundp 'miee-version))
+    (load \"miee\"))\n")
+         (insert "(setq message-send-news-function 'gnspool-request-post)\n"))
+
+       ;; write setting about nnspool and gnus-agent.
+       (if (eq news-method 'nnspool)
+           (insert "(message-offline-state)\n")
+         (insert "(setq gnus-agent-directory "
+                 (prin1-to-string agent-directory) ")\n"))
+
+       ;; write setting about queue type -- MIEE or nnagent.
+       (insert "(setq gnus-offline-drafts-queue-type '"
+               (prin1-to-string drafts-queue-type) ")\n")
+       (insert "(setq gnus-offline-MTA-type '"
+               (prin1-to-string MTA-type) ")\n")
+
+       ;; Write setting about hooks.
+       (when (eq news-method 'nnspool)
+         (insert (format "%s %s %s\n"
+                         "(add-hook"
+                         "'after-getting-news-hook"
+                         "'gnus-offline-nnspool-hangup-line)"))
+         (insert (format "%s %s %s\n"
+                         "(add-hook"
+                         "'gnus-before-startup-hook"
+                         "(lambda () (setq nnmail-spool-file nil)
+          (setq mail-sources nil)))")))
+
+       ;; Write stting about mail-source.el
+       (insert "(setq gnus-offline-mail-source '"
+               (prin1-to-string mail-source) ")\n")
+       (insert "(setq mail-sources gnus-offline-mail-source)\n")
+       (if save-passwd
+           (insert "(add-hook 'gnus-setup-news-hook
+         (lambda ()
+           (add-to-list 'gnus-variable-list 'mail-source-password-cache)))\n"))
+
+       ;;
+       (write-region (point-min) (point-max) gnus-offline-setting-file))
+      (kill-buffer "* Setting")))
+
+  (defmacro gnus-ofsetup-prepare (list)
+    (let ((forms (symbol-value list)))
+      `(progn ,@forms))))
+
+(defvar gnus-ofsetup-resource-en
+  '((prepare-miee-1
+     . "Making directories failed. Set mail/news spool directories properly.")
+    (completing-read-symbol-1 . " (TAB to completion): ")
+    (setup-1 . "Method for offline News reading")
+    (setup-2 . "Agent directory: ")
+    (setup-3 . "Dialup program (give a null string if you do not use): ")
+    (setup-4 . "Dialup program options: ")
+    (setup-5 . "Hangup program (give a null string if you do not use): ")
+    (setup-6 . "Hangup program options: ")
+    (setup-7 . "Select MTA type for sending mail")
+    (setup-8 . "Use MIEE post/send message ")
+    (setup-9 . "News spool directory for sending: ")
+    (setup-10 . "Mail spool directory for sending: ")
+    (setup-11 . "How many mail sources will get mails from? : ")
+    (setup-12 . "What type of the mail source? ")
+    (setup-13 . "Mail Account name : ")
+    (setup-14 . "Mail server : ")
+    (setup-15 . "Authentification Method ")
+    (setup-16 . "Do you use pop3.el to fetch mail? ")
+    (setup-17 . "movemail program name: ")
+    (setup-18 . "movemail options: ")
+    (setup-19 . "What network stream? ")
+    (setup-20 . "File: ")
+    (setup-21 . "Directory: ")
+    (setup-22 . "Do you save password information to newsrc file? ")
+
+    (param-news-method-1 . "News Method")
+    (param-news-method-2 . "Gnus Agent")
+    (param-news-method-3 . "nnspool")
+    (param-news-method-4 . "\
+Method to fetch news articles.")
+    (param-dialup-program-1 . "Dialup Program")
+    (param-dialup-program-2 . "Use program..")
+    (param-dialup-program-3 . "Don't use a program.")
+    (param-dialup-program-4 . "\
+Program which does dial.")
+    (param-dialup-program-arg-1 . "Dialup Program Arguments")
+    (param-dialup-program-arg-2 . "Argument")
+    (param-dialup-program-arg-3 . "\
+Program arguments of gnus-offline-dialup-program.")
+    (param-hangup-program-1 . "Hangup Program")
+    (param-hangup-program-2 . "Use program..")
+    (param-hangup-program-3 . "Don't use a program.")
+    (param-hangup-program-4 . "\
+Program which does hangup.")
+    (param-hangup-program-arg-1 . "Hangup Program Arguments")
+    (param-hangup-program-arg-2 . "Argument")
+    (param-hangup-program-arg-3 . "\
+Program arguments of gnus-offline-hangup-program.")
+    (param-interval-1 . "Interval between Jobs")
+    (param-interval-2 . "\
+Interval time(minutes) to do online jobs.
+If set to 0 , timer call is disabled.")
+    (param-drafts-queue-type-1 . "Drafts Queue Type")
+    (param-drafts-queue-type-2 . "Gnus Draft for queuing.")
+    (param-drafts-queue-type-3 . "I prefer MIEE for queuing.")
+    (param-drafts-queue-type-4 . "\
+Type of queue used for draft messages.
+
+If the select method for news is nnspool, you must choose MIEE.
+MIEE is another library for offline messaging. It isn't part of
+Semi-gnus. If you want to know about MIEE, see README-offline.{en,ja}.")
+    (param-mail-spool-1 . "Mail Spool Directory for MIEE")
+    (param-news-spool-1 . "News Spool Directory for MIEE")
+    (param-MTA-type-1 . "MTA Type")
+    (param-MTA-type-2 . "Use smtp.el")
+    (param-MTA-type-3 . "Use sendmail")
+    (param-MTA-type-4 . "\
+Type of MTA used for sending mail.")
+    (param-save-passwd-1 . "Save Password in Startup File")
+    (param-save-passwd-2 . "OK, I'm sure it's safe.")
+    (param-save-passwd-3 . "No way, it's too dangerous!")
+    (param-save-passwd-4 . "\
+Whether you want your POP passwords written in .newsrc.eld or not.")
+    (param-mail-source-1 . "Mail Sources")
+    (param-mail-source-2 . "\
+Information of mail sources. Actually, a list of `Mail Source Specifiers'.
+
+The format of this variable is just the same as `mail-sources' (or
+`nnmail-spool-file' which seems obsolete).
+
+`Mail Source Specifiers' can take a lot of keywords. For example,
+if you want to use movemail instead of pop3.el which comes with
+Gnus, you can set a specifier using the kerword :program as shown
+below:
+
+         (pop :program \"movemail -pf po:%u %t %p\")
+
+If you want to know more about mail source specifiers and keywords,
+click the button below.")
+    (customize-1 . "Customize the Gnus Offline Parameters, and press ")
+    (customize-2 . "done")
+    (customize-3 . "Push me when done customizing.")
+    (customize-4 . "Parameters")
+    (customize-5 . "\
+These parameters will be saved in ~/.gnus-offline.el.
+
+Note: Touching these parameters may require Gnus or even Emacs to be
+restarted.")
+    (customize-6 . "Push me to learn more.")
+    (customize-done-1 . "(No changes need to be saved)")
+    (customize-done-2
+     . "Invalid parameters. Check the news method and drafts queue type.")))
+
+(defvar gnus-ofsetup-resource-ja
+  '((prepare-miee-1
+     . "\e$B%G%#%l%/%H%j$,:n$l$^$;$s!#%9%W!<%k$N@_Dj$r@5$7$/$7$F$/$@$5$$!#\e(B")
+    (completing-read-symbol-1 . "(TAB \e$B$GJd40$7$^$9\e(B): ")
+    (setup-1 . "\e$B%*%U%i%$%s$G%K%e!<%9$rFI$`J}K!$rA*$s$G$/$@$5$$\e(B ")
+    (setup-2 . "Gnus Agent \e$B$N%G%#%l%/%H%j\e(B: ")
+    (setup-3
+     . "\e$B%@%$%d%k@\B3%W%m%0%i%`L>\e(B (\e$B;H$o$J$$>l9g$O6uJ8;zNs$rJV$7$F2<$5$$\e(B): ")
+    (setup-4 . "\e$B%@%$%d%k@\B3%W%m%0%i%`$N0z?t\e(B: ")
+    (setup-5
+     . "\e$B%@%$%d%k@ZCG%W%m%0%i%`L>\e(B (\e$B;H$o$J$$>l9g$O6uJ8;zNs$rJV$7$F2<$5$$\e(B): ")
+    (setup-6 . "\e$B%@%$%d%k@ZCG%W%m%0%i%`$N0z?t\e(B: ")
+    (setup-7 . "\e$B%a!<%kAw?.$K;H$&\e(B MTA \e$B$rA*$s$G2<$5$$\e(B ")
+    (setup-8 . "\e$B%a%C%;!<%8$NAw?.$K\e(B MIEE \e$B$r;H$$$^$9$+\e(B? ")
+    (setup-9 . "\e$B%K%e!<%9$N%9%W!<%k%G%#%l%/%H%j\e(B: ")
+    (setup-10 . "\e$B%a!<%k$N%9%W!<%k%G%#%l%/%H%j\e(B: ")
+    (setup-11 . "\e$B@_Dj$9$k%a!<%k<hF@@h$N?t$O\e(B? (\e$B8e$GDI2C$G$-$^$9\e(B): ")
+    (setup-12 . "\e$B%a!<%k<hF@@h$N%?%$%W$O\e(B? ")
+    (setup-13 . "\e$B%a!<%k$N%"%+%&%s%HL>\e(B: ")
+    (setup-14 . "\e$B$=$N%"%+%&%s%H$N$"$k%a!<%k%5!<%PL>\e(B: ")
+    (setup-15 . "\e$BG'>ZJ}<0$O\e(B? ")
+    (setup-16 . "\e$B%a!<%k$N<u?.$K$O\e(B pop3.el \e$B$r;H$$$^$9$+\e(B? ")
+    (setup-17 . "movemail \e$B%W%m%0%i%`$NL>A0\e(B: ")
+    (setup-18 . "movemail \e$B%W%m%0%i%`$KEO$90z?t\e(B: ")
+    (setup-19 . "\e$B@\B3J}<0$O\e(B? ")
+    (setup-20 . "\e$B%U%!%$%k\e(B: ")
+    (setup-21 . "\e$B%G%#%l%/%H%j\e(B: ")
+    (setup-22 . "newsrc \e$B%U%!%$%k$K\e(B POP \e$B%Q%9%o!<%I$rJ]B8$7$^$9$+\e(B? ")
+
+    (param-news-method-4 . "\
+\e$B%K%e!<%95-;v$r<hF@$9$kJ}K!$G$9!#\e(B")
+    (param-dialup-program-4 . "\
+\e$B<+F0%@%$%d%k@\B3$K;H$&%W%m%0%i%`!#\e(B")
+    (param-dialup-program-arg-3 . "\
+\e$B%@%$%d%k@\B3%W%m%0%i%`$KEO$90z?t!#\e(B")
+    (param-hangup-program-4 . "\
+\e$B<+F0%@%$%d%k@ZCG$K;H$&%W%m%0%i%`!#\e(B")
+    (param-hangup-program-arg-3 . "\
+\e$B%@%$%d%k@ZCG%W%m%0%i%`$KEO$90z?t!#\e(B")
+    (param-interval-2 . "\
+\e$BAw<u?.%8%g%V$r9T$&4V3V!#J,C10L$G;XDj$7$^$9!#\e(B
+
+\e$B$3$l$r\e(B 0 \e$B$K@_Dj$9$k$H<+F0Aw<u?.5!G=$O%*%U$K$J$j$^$9!#\e(B")
+    (param-drafts-queue-type-4 . "\
+\e$B%I%i%U%H5-;v$rJ]B8$9$k%-%e!<$N<oN`$r;XDj$7$^$9!#\e(B
+
+\e$B%K%e!<%9$N9VFI<jCJ$,\e(B nnspool \e$B$N>l9g!"\e(BMIEE \e$B$r;XDj$9$kI,MW$,$"$j$^$9!#\e(B
+MIEE \e$B$O%*%U%i%$%s$G$N%a!<%k\e(B/\e$B%K%e!<%9Aw?.5!G=$rDs6!$9$k%i%$%V%i%j$G$9$,!"\e(B
+Semi-gnus \e$B$K$OIUB0$7$F$$$^$;$s!#\e(BMIEE \e$B$K$D$$$FCN$j$?$$>l9g$O\e(B
+README-offline.{en,ja} \e$B$r;2>H$7$F$/$@$5$$!#\e(B")
+    (param-MTA-type-4 . "\
+MTA \e$B$O%a!<%k$NAw?.$r<u$1;}$D%W%m%0%i%`$G$9!#$=$N<oN`$r;XDj$7$^$9!#\e(B")
+    (param-save-passwd-4 . "\
+POP \e$B%Q%9%o!<%I$r\e(B .newsrc.eld \e$B$KJ]B8$9$k$+H]$+$r;XDj$7$^$9!#\e(B")
+    (param-mail-source-2 . "\
+\e$B%a!<%k<hF@@h$d<hF@J}K!$r;XDj$7$^$9!#\e(B
+
+\e$B$3$N%*%W%7%g%s$N=q<0$O\e(B `mail-sources' \e$B$H$$$&JQ?t$HF1$8$G$"$j!"\e(B
+`mail source specifier' \e$B$H8F$P$l$k$b$N$N%j%9%H$H$7$F5-=R$7$^$9!#\e(B
+
+\e$B3F!9$N\e(B `mail source specifier' \e$B$K$O?'!9$J%-!<%o!<%I$r;XDj$9$k$3$H$,\e(B
+\e$B$G$-$^$9!#Nc$($P%a!<%k$N<hF@$K$O\e(B pop3.el \e$B$NBe$o$j$K30It%W%m%0%i%`\e(B
+(movemail \e$B$J$I\e(B) \e$B$r;H$$$?$$!"$H$$$&>l9g$K$O!"\e(B:program \e$B$r$$$&%-!<%o!<\e(B
+\e$B%I$r;XDj$7$F0J2<$NMM$K5-=R$7$^$9!#\e(B
+
+       (pop :program \"movemail -pf po:%u %t %p\")
+
+mail source specifier \e$B$H$+>e5-$N$h$&$J%-!<%o!<%I$K$D$$$F$b$C$H$h$/\e(B
+\e$BCN$j$?$$>l9g$O!"0J2<$N%\%?%s$r%/%j%C%/$7$F$/$@$5$$!#\e(B(Info \e$B$N3:Ev2U=j\e(B
+\e$B$X$N%j%s%/$K$J$C$F$$$^$9!#\e(B)" )
+
+     (customize-1
+      . "Gnus Offline \e$B$N%Q%i%a!<%?!#=*$o$C$?$i1&$N%\%?%s$r2!$7$F$/$@$5$$!#\e(B")
+     (customize-2 . "done")
+     (customize-3 . "\e$B@_Dj$7=*$o$C$?$i%\%/$r2!$7$F$M!#\e(B")
+     (customize-4 . "\e$B%Q%i%a!<%?\e(B")
+     (customize-5 . "\
+\e$B$3$l$i$N%Q%i%a!<%?$O\e(B ~/.gnus-offline.el \e$B$KJ]B8$5$l$^$9!#\e(B
+
+\e$BCm0U\e(B: \e$B$3$l$i$N%Q%i%a!<%?$NJQ99$O>l9g$K$h$C$F$O\e(B Gnus (\e$B$5$i$K>l9g$K\e(B
+\e$B$h$C$F$O\e(B Emacs) \e$B$N:F5/F0$rI,MW$H$9$k$3$H$,$"$j$^$9!#\e(B")
+     (customize-6 . "\e$B$b$C$HCN$j$?$$>l9g$O%\%/$r2!$7$F$M!#\e(B")
+     (customize-done-1 . "(\e$BJ]B8$9$Y$-JQ99$O$"$j$^$;$s\e(B)")
+     (customize-done-2
+      . "\e$B%K%e!<%99VFI<jCJ$H%I%i%U%H5-;v<h$j07$$<jCJ$N@_Dj$r8+D>$7$F$/$@$5$$!#\e(B")
+  ))
+
+(defvar gnus-ofsetup-resource-ja_complete
+  (append
+   gnus-ofsetup-resource-ja
+   '((param-news-method-1 . "\e$B%K%e!<%99VFIJ}K!\e(B")
+     (param-news-method-2 . "Gnus Agent")
+     (param-news-method-3 . "nnspool")
+     (param-dialup-program-1 . "\e$B%@%$%d%k@\B3%W%m%0%i%`\e(B")
+     (param-dialup-program-2 . "\e$B%W%m%0%i%`$r;H$&\e(B..")
+     (param-dialup-program-3 . "\e$B%W%m%0%i%`$O;XDj$7$J$$\e(B")
+     (param-dialup-program-arg-1 . "\e$B%@%$%d%k@\B3%W%m%0%i%`$N0z?t\e(B")
+     (param-dialup-program-arg-2 . "\e$B0z?t\e(B")
+     (param-hangup-program-1 . "\e$B%@%$%d%k@ZCG%W%m%0%i%`\e(B")
+     (param-hangup-program-2 . "\e$B%W%m%0%i%`$r;H$&\e(B..")
+     (param-hangup-program-3 . "\e$B%W%m%0%i%`$O;XDj$7$J$$\e(B")
+     (param-hangup-program-arg-1 . "\e$B%@%$%d%k@ZCG%W%m%0%i%`$N0z?t\e(B")
+     (param-hangup-program-arg-2 . "\e$B0z?t\e(B")
+     (param-interval-1 . "\e$B<+F0Aw<u?.%8%g%V$N4V3V\e(B")
+     (param-drafts-queue-type-1 . "\e$B%I%i%U%H5-;v$rJ]B8$9$k%-%e!<$N<oN`\e(B")
+     (param-drafts-queue-type-2 . "Gnus Draft \e$B$N5!G=$rMxMQ$9$k\e(B")
+     (param-drafts-queue-type-3 . "MIEE \e$B$N5!G=$rMxMQ$9$k\e(B")
+     (param-mail-spool-1 . "MIEE \e$B$,;H$&%a!<%k$N%9%W!<%k%G%#%l%/%H%j\e(B")
+     (param-news-spool-1 . "MIEE \e$B$,;H$&%K%e!<%9$N%9%W!<%k%G%#%l%/%H%j\e(B")
+     (param-MTA-type-1 . "MTA \e$B$N<oN`\e(B")
+     (param-MTA-type-2 . "smtp.el \e$B$r;H$&\e(B")
+     (param-MTA-type-3 . "sendmail \e$B$r;H$&\e(B")
+     (param-save-passwd-1
+      . "\e$B%U%!%$%k$K\e(B POP \e$B%Q%9%o!<%I$rJ]B8$9$k\e(B")
+     (param-save-passwd-2 . "\e$B0BA4$J$N$GJ]B8$9$k\e(B")
+     (param-save-passwd-3 . "\e$B4m81$@$+$i$d$a$H$/\e(B")
+     (param-mail-source-1 . "\e$B%a!<%k<hF@@h$N>pJs\e(B"))))
+
+(defsubst gnus-ofsetup-gettext (symbol &optional lang)
+  (setq lang (or lang gnus-offline-lang))
+  (or
+   (cdr (assq symbol (symbol-value
+                     (intern (format "gnus-ofsetup-resource-%s" lang)))))
+   (cdr (assq symbol gnus-ofsetup-resource-en))))
+
+(defun gnus-ofsetup-completing-read-symbol (msg &rest syms)
+  (intern
+   (completing-read (concat
+                    msg
+                    (gnus-ofsetup-gettext 'completing-read-symbol-1))
+                   (mapcar
+                    #'(lambda (sym)
+                        (list (symbol-name sym)))
+                    syms)
+                   nil t nil)))
+
+(defun gnus-setup-for-offline (&optional force)
+  "*Set up Gnus for offline environment."
+  (interactive "P")
+  (unless (and (file-exists-p gnus-offline-setting-file) (not force))
+    (let (news-method
+         mail-method agent-directory drafts-queue-type news-spool mail-spool
+         use-miee MTA-type dialup-program dialup-program-arguments
+         hangup-program hangup-program-arguments interval
+         num-of-address i n mail-source save-passwd)
+      (setq news-method
+           (gnus-ofsetup-completing-read-symbol
+            (gnus-ofsetup-gettext 'setup-1)
+            'nnagent 'nnspool))
+      ;; Setting for gnus-agent.
+      (if (eq news-method 'nnagent)
+         (setq agent-directory
+               (read-from-minibuffer
+                (gnus-ofsetup-gettext 'setup-2) "~/News/agent")))
+      (setq mail-method 'nnmail)
+      (setq dialup-program
+           (read-file-name
+            (gnus-ofsetup-gettext 'setup-3)
+            nil nil t))
+      (if (string-match "^[ \t]*$" dialup-program)
+         (setq dialup-program nil)
+       (setq dialup-program-arguments
+             (delete "" (split-string
+                         (read-from-minibuffer
+                          (gnus-ofsetup-gettext 'setup-4))
+                         "[\t ]+"))))
+      (setq hangup-program
+           (read-file-name
+            (gnus-ofsetup-gettext 'setup-5)
+            nil nil t))
+      (if (string-match "^[ \t]*$" hangup-program)
+         (setq hangup-program nil)
+       (setq hangup-program-arguments
+             (delete "" (split-string
+                         (read-from-minibuffer
+                          (gnus-ofsetup-gettext 'setup-6))
+                         "[\t ]+"))))
+      (setq MTA-type (gnus-ofsetup-completing-read-symbol
+                     (gnus-ofsetup-gettext 'setup-7)
+                     'smtp 'sendmail))
+      (if (eq news-method 'nnspool)
+         (setq use-miee t)
+       (setq use-miee (y-or-n-p (gnus-ofsetup-gettext 'setup-8))))
+      (if use-miee
+         (progn
+           ;; Setting for MIEE.
+           (setq news-spool
+                 (read-from-minibuffer
+                  (gnus-ofsetup-gettext 'setup-9)
+                  "/usr/spool/news.out"))
+           (setq mail-spool
+                 (read-from-minibuffer
+                  (gnus-ofsetup-gettext 'setup-10)
+                  "/usr/spool/mail.out"))
+           (setq drafts-queue-type 'miee)
+           (gnus-ofsetup-prepare gnus-ofsetup-prepare-for-miee))
+       ;; Set drafts type gnus-agent.
+       (setq drafts-queue-type 'agent))
+      ;; Create a list of mail source specifiers.
+      (setq num-of-address
+           (read-from-minibuffer (gnus-ofsetup-gettext 'setup-11)))
+      (setq i (setq n (string-to-int num-of-address)))
+      ;;
+      (while (> i 0)
+       (let* ((j (- n (1- i)))
+              (type (gnus-ofsetup-completing-read-symbol
+                     (format "<%d of %d> %s" j n
+                             (gnus-ofsetup-gettext 'setup-12))
+                     'pop 'imap 'file 'directory 'maildir))
+              user server authentication stream islisp source
+              prog args program path)
+         ;; Prepare.
+         (when (or (string= type "pop") (string= type "imap"))
+           (setq user (read-from-minibuffer
+                       (format "<%d of %d> %s" j n
+                               (gnus-ofsetup-gettext 'setup-13))))
+           (setq server (read-from-minibuffer
+                         (format "<%d of %d> %s" j n
+                                 (gnus-ofsetup-gettext 'setup-14)))))
+         (when (string= type "pop")
+           (setq authentication (gnus-ofsetup-completing-read-symbol
+                                 (format "<%d of %d> %s" j n
+                                         (gnus-ofsetup-gettext 'setup-15))
+                                 'password 'apop))
+           (setq islisp (y-or-n-p
+                         (format "<%d of %d> %s" j n
+                                 (gnus-ofsetup-gettext 'setup-16))))
+           (unless islisp
+             (setq prog (read-file-name
+                         (format "<%d of %d> %s" j n
+                                 (gnus-ofsetup-gettext 'setup-17))
+                         exec-directory "movemail"))
+             (setq args (read-from-minibuffer
+                         (format "<%d of %d> %s" j n
+                                 (gnus-ofsetup-gettext 'setup-18) "-pf")))
+             (setq program (format "%s %s %s %s %s"
+                                   prog args "po:%u" "%t" "%p"))))
+         (when (string= type "imap")
+           (setq stream (gnus-ofsetup-completing-read-symbol
+                         (format "<%d of %d> %s" j n
+                                 (gnus-ofsetup-gettext 'setup-19))
+                         'kerberos4 'starttls 'ssl 'network))
+           (setq authentication (gnus-ofsetup-completing-read-symbol
+                                 (format "<%d of %d> %s" j n
+                                         (gnus-ofsetup-gettext 'setup-14))
+                                 'kerberos4 'digest-md5 'cram-md5 'login
+                                 'anonymous)))
+         (when (string= type "file")
+           (setq path (read-file-name
+                       (format "<%d of %d> %s" j n
+                               (gnus-ofsetup-gettext 'setup-20)))))
+         (when (or (string= type "directory") (string= type "maildir"))
+           (setq path (read-file-name
+                       (format "<%d of %d> %s" j n
+                               (gnus-ofsetup-gettext 'setup-21)))))
+         ;; Now set a mail source specifier.
+         (setq source (list type))
+         (let (value)
+           (dolist (symbol '(path user server authentication stream program))
+             (when (setq value (symbol-value symbol))
+               (setq source (nconc source
+                                   (list (make-symbol (format ":%s" symbol))
+                                         value))))))
+         (setq mail-source (nconc mail-source (list source))))
+       (setq i (1- i)))
+      (setq save-passwd
+           (y-or-n-p (gnus-ofsetup-gettext 'setup-22)))
+      ;;
+      (gnus-ofsetup-prepare gnus-ofsetup-update-setting-file)))
+  (load gnus-offline-setting-file))
+
+
+;; Suppport for customizing gnus-ofsetup parameters.
+
+(defvar sendmail-to-spool-directory)
+(defvar news-spool-request-post-directory)
+
+(defun gnus-ofsetup-find-parameters ()
+  "Return the each current value of gnus-offline parameters."
+  `((news-method
+     (choice :tag ,(gnus-ofsetup-gettext 'param-news-method-1)
+            :value ,gnus-offline-news-fetch-method
+            (const :tag ,(gnus-ofsetup-gettext 'param-news-method-2)
+                   nnagent)
+            (const :tag ,(gnus-ofsetup-gettext 'param-news-method-3)
+                   nnspool))
+     ,(gnus-ofsetup-gettext 'param-news-method-4))
+
+    (dialup-program
+     (choice :tag ,(gnus-ofsetup-gettext 'param-dialup-program-1)
+            :value ,gnus-offline-dialup-program
+            (string :tag ,(gnus-ofsetup-gettext 'param-dialup-program-2))
+            (const :tag ,(gnus-ofsetup-gettext
+                          'param-dialup-program-3) nil))
+     ,(gnus-ofsetup-gettext 'param-dialup-program-4))
+
+    (dialup-program-arguments
+     (repeat :tag ,(gnus-ofsetup-gettext 'param-dialup-program-arg-1)
+            :value ,gnus-offline-dialup-program-arguments
+            (string :tag ,(gnus-ofsetup-gettext
+                           'param-dialup-program-arg-2)))
+     ,(gnus-ofsetup-gettext 'param-dialup-program-arg-3))
+
+    (hangup-program
+     (choice :tag ,(gnus-ofsetup-gettext 'param-hangup-program-1)
+            :value ,gnus-offline-hangup-program
+            (string :tag ,(gnus-ofsetup-gettext 'param-hangup-program-2))
+            (const :tag ,(gnus-ofsetup-gettext 'param-hangup-program-3)
+                   nil))
+     ,(gnus-ofsetup-gettext 'param-hangup-program-4))
+
+    (hangup-program-arguments
+     (repeat :tag ,(gnus-ofsetup-gettext 'param-hangup-program-arg-1)
+            :value ,gnus-offline-hangup-program-arguments
+            (string :tag ,(gnus-ofsetup-gettext
+                           'param-hangup-program-arg-2)))
+     ,(gnus-ofsetup-gettext 'param-hangup-program-arg-3))
+
+    (interval
+     (integer :tag ,(gnus-ofsetup-gettext 'param-interval-1)
+             :value ,gnus-offline-interval-time)
+     ,(gnus-ofsetup-gettext 'param-interval-2))
+
+    (drafts-queue-type
+     (choice :tag ,(gnus-ofsetup-gettext 'param-drafts-queue-type-1)
+            :value ,gnus-offline-drafts-queue-type
+            (const :tag ,(gnus-ofsetup-gettext 'param-drafts-queue-type-2)
+                   agent)
+            (const :tag ,(gnus-ofsetup-gettext 'param-drafts-queue-type-3)
+                   miee))
+     ,(gnus-ofsetup-gettext 'param-drafts-queue-type-4))
+
+    (mail-spool
+     (directory :tag ,(gnus-ofsetup-gettext 'param-mail-spool-1)
+               :value ,(cond ((and (boundp 'sendmail-to-spool-directory)
+                                   sendmail-to-spool-directory)
+                              sendmail-to-spool-directory)
+                             (t
+                              "/usr/spool/mail.out"))))
+
+    (news-spool
+     (directory :tag ,(gnus-ofsetup-gettext 'param-news-spool-1)
+               :value ,(cond ((and (boundp 'news-spool-request-post-directory)
+                                   news-spool-request-post-directory)
+                              news-spool-request-post-directory)
+                             (t
+                              "/usr/spool/news.out"))))
+
+    (MTA-type
+     (choice :tag ,(gnus-ofsetup-gettext 'param-MTA-type-1)
+            :value ,gnus-offline-MTA-type
+            (const :tag ,(gnus-ofsetup-gettext 'param-MTA-type-2) smtp)
+            (const :tag ,(gnus-ofsetup-gettext 'param-MTA-type-3)
+                   sendmail))
+     ,(gnus-ofsetup-gettext 'param-MTA-type-4))
+
+    (save-passwd
+     (choice :tag ,(gnus-ofsetup-gettext 'param-save-passwd-1)
+            :value ,(if (memq 'mail-source-password-cache gnus-variable-list)
+                        t
+                      nil)
+            (const :tag ,(gnus-ofsetup-gettext 'param-save-passwd-2) t)
+            (const :tag ,(gnus-ofsetup-gettext 'param-save-passwd-3) nil))
+     ,(gnus-ofsetup-gettext 'param-save-passwd-4))
+
+    (mail-source
+     (sexp :tag ,(gnus-ofsetup-gettext 'param-mail-source-1)
+          :value ,gnus-offline-mail-source)
+     ,(gnus-ofsetup-gettext 'param-mail-source-2))))
+
+(defvar gnus-ofsetup-params)
+
+(defun gnus-ofsetup-customize ()
+  "Edit the gnus-offline parameters."
+  (interactive)
+  (let* ((params (gnus-ofsetup-find-parameters))
+        (types (mapcar #'(lambda (entry)
+                           `(cons :format "%v%h\n"
+                                  :doc ,(nth 2 entry)
+                                  (const :format "" ,(nth 0 entry))
+                                  ,(nth 1 entry)))
+                       params)))
+    (kill-buffer (gnus-get-buffer-create "*Gnus Offline Customize*"))
+    (switch-to-buffer (gnus-get-buffer-create "*Gnus Offline Customize*"))
+    (gnus-custom-mode)
+    (widget-insert (gnus-ofsetup-gettext 'customize-1))
+    (widget-create 'push-button
+                  :tag (gnus-ofsetup-gettext 'customize-2)
+                  :help-echo (gnus-ofsetup-gettext 'customize-3)
+                  :action 'gnus-ofsetup-customize-done)
+    (widget-insert "\n\n")
+    (make-local-variable 'gnus-ofsetup-params)
+    (setq gnus-ofsetup-params
+         (widget-create 'group
+                        `(set :inline t
+                              :greedy t
+                              :tag ,(gnus-ofsetup-gettext 'customize-4)
+                              :format "%t:\n%h%v"
+                              :doc ,(gnus-ofsetup-gettext 'customize-5)
+                              ,@types)))
+
+    (widget-create 'info-link
+                  :help-echo (gnus-ofsetup-gettext 'customize-6)
+                  :tag "<Info> mail sources"
+                  (if (string-match "^ja" gnus-offline-lang)
+                      "(gnus-ja)Mail Sources"
+                    "(gnus)Mail Sources"))
+
+    (use-local-map widget-keymap)
+    (local-set-key "q" 'bury-buffer)
+    (widget-setup)
+    (goto-char (point-min))))
+
+(defun gnus-ofsetup-customize-done (&rest ignore)
+  "Apply changes and bury the buffer."
+  (interactive)
+  (let ((params (widget-value gnus-ofsetup-params))
+       (news-method gnus-offline-news-fetch-method)
+       (mail-method gnus-offline-mail-fetch-method)
+       (agent-directory gnus-agent-directory)
+       (dialup-program gnus-offline-dialup-program)
+       (dialup-program-arguments gnus-offline-dialup-program-arguments)
+       (hangup-program gnus-offline-hangup-program)
+       (hangup-program-arguments gnus-offline-hangup-program-arguments)
+       (drafts-queue-type gnus-offline-drafts-queue-type)
+       (interval gnus-offline-interval-time)
+       (use-miee (and (boundp 'miee-version)
+                      (or (eq gnus-offline-news-fetch-method 'nnspool)
+                          (eq gnus-offline-drafts-queue-type 'miee))))
+       (mail-spool (or (and (boundp 'sendmail-to-spool-directory)
+                            sendmail-to-spool-directory)
+                       "/usr/spool/mail.out"))
+       (news-spool (or (and (boundp 'news-spool-request-post-directory)
+                            news-spool-request-post-directory)
+                       "/usr/spool/news.out"))
+       (MTA-type gnus-offline-MTA-type)
+       (mail-source gnus-offline-mail-source)
+       (save-passwd (and (memq 'mail-source-password-cache gnus-variable-list)
+                         t)))
+    (if (null params)
+       (gnus-message 4 (gnus-ofsetup-gettext 'customize-done-1))
+      (let (symbol value)
+       (dolist (elem params)
+         (setq symbol (car elem)
+               value (cdr elem))
+         (set symbol value)
+         (cond ((eq symbol 'news-method)
+                (if (eq value 'nnspool)
+                    (setq use-miee t)))
+               ((eq symbol 'drafts-queue-type)
+                (setq use-miee (eq value 'miee)))
+               ((eq symbol 'save-passwd)
+                (if value
+                    (add-to-list 'gnus-variable-list
+                                 'mail-source-password-cache)
+                  (setq gnus-variable-list
+                        (delq 'mail-source-password-cache
+                              gnus-variable-list)))))))
+      (if (and (eq news-method 'nnspool)
+              (not (eq drafts-queue-type 'miee)))
+         (error (gnus-ofsetup-gettext 'customize-done-2)))
+      (if use-miee
+         (gnus-ofsetup-prepare gnus-ofsetup-prepare-for-miee))
+      (gnus-ofsetup-prepare gnus-ofsetup-update-setting-file)
+      (load gnus-offline-setting-file)))
+  (bury-buffer)
+  (switch-to-buffer gnus-group-buffer))
+
+
+;;; Code for making Gnus and Gnus Offline cooperate with each other.
+
+;; Advice.
+(defadvice gnus (around gnus-ofsetup-advice activate preactivate)
+  "Setup offline environment when Gnus is invoked."
+  (require 'gnus-offline) ad-do-it (gnus-offline-setup))
+
+;; Miscellaneous settings.
+
+(setq gnus-nntp-service nil)
+(setq gnus-nntp-server nil)
+(eval-after-load "gnus-start"
+  '(add-hook 'gnus-after-getting-new-news-hook 'gnus-offline-after-get-new-news))
+(eval-after-load "message"
+  '(add-hook 'message-send-hook 'gnus-offline-message-add-header))
+
+(provide 'gnus-ofsetup)
+
+;;; gnus-ofsetup.el ends here
index 7f04650..7c6c5e1 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-picon.el --- displaying pretty icons in Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Wes Hardaker <hardaker@ece.ucdavis.edu>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;      Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news xpm annotation glyph faces
 
 ;; This file is part of GNU Emacs.
 
 ;;; Commentary:
 
+;; There are three picon types relevant to Gnus:
+;;
+;; Persons: person@subdomain.dom
+;;          users/dom/subdomain/person/face.gif
+;;          usenix/dom/subdomain/person/face.gif
+;;          misc/MISC/person/face.gif
+;; Domains: subdomain.dom
+;;          domain/dom/subdomain/unknown/face.gif
+;; Groups:  comp.lang.lisp
+;;          news/comp/lang/lisp/unknown/face.gif
+;;
+;; Original implementation by Wes Hardaker <hardaker@ece.ucdavis.edu>.
+;;
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'gnus)
-(require 'xpm)
-(require 'annotations)
 (require 'custom)
 (require 'gnus-art)
-(require 'gnus-win)
 
 ;;; User variables:
 
-(defgroup picons nil
-  "Show pictures of people, domains, and newsgroups (XEmacs).
-For this to work, you must add gnus-group-display-picons to the
-gnus-summary-display-hook or to the gnus-article-display-hook
-depending on what gnus-picons-display-where is set to.  You must
-also add gnus-article-display-picons to gnus-article-display-hook."
-  :group 'gnus-visual)
-
-(defcustom gnus-picons-display-where 'picons
-  "Where to display the group and article icons.
-Legal values are `article' and `picons'."
-  :type '(choice symbol string)
-  :group 'picons)
-
-(defcustom gnus-picons-has-modeline-p t
-  "*Whether the picons window should have a modeline.
-This is only useful if `gnus-picons-display-where' is `picons'."
-  :type 'boolean
-  :group 'picons)
-
-(defcustom gnus-picons-database "/usr/local/faces"
-  "*Defines the location of the faces database.
-For information on obtaining this database of pretty pictures, please
-see http://www.cs.indiana.edu/picons/ftp/index.html"
-  :type 'directory
-  :group 'picons)
-
-(defcustom gnus-picons-news-directories '("news")
+(defcustom gnus-picon-news-directories '("news")
   "*List of directories to search for newsgroups faces."
   :type '(repeat string)
-  :group 'picons)
-(define-obsolete-variable-alias 'gnus-picons-news-directory
-  'gnus-picons-news-directories)
+  :group 'gnus-picon)
 
-(defcustom gnus-picons-user-directories '("local" "users" "usenix" "misc")
+(defcustom gnus-picon-user-directories '("users" "usenix" "local" "misc")
   "*List of directories to search for user faces."
   :type '(repeat string)
-  :group 'picons)
+  :group 'gnus-picon)
 
-(defcustom gnus-picons-domain-directories '("domains")
+(defcustom gnus-picon-domain-directories '("domains")
   "*List of directories to search for domain faces.
 Some people may want to add \"unknown\" to this list."
   :type '(repeat string)
-  :group 'picons)
-
-(defcustom gnus-picons-refresh-before-display nil
-  "*If non-nil, display the article buffer before computing the picons."
-  :type 'boolean
-  :group 'picons)
-
-(defcustom gnus-picons-group-excluded-groups nil
-  "*If this regexp matches the group name, group picons will be disabled."
-  :type 'regexp
-  :group 'picons)
-
-(defcustom gnus-picons-x-face-file-name
-  (format "/tmp/picon-xface.%s.xbm" (user-login-name))
-  "*The name of the file in which to store the converted X-face header."
-  :type 'string
-  :group 'picons)
-
-(defcustom gnus-picons-convert-x-face (format "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | pbmtoxbm > %s" gnus-picons-x-face-file-name)
-  "*Command to convert the x-face header into a xbm file."
-  :type 'string
-  :group 'picons)
-
-(defcustom gnus-picons-display-as-address t
-  "*If t display textual email addresses along with pictures."
-  :type 'boolean
-  :group 'picons)
-
-(defcustom gnus-picons-file-suffixes
-  (when (featurep 'x)
-    (let ((types (list "xbm")))
-      (when (featurep 'gif)
-       (push "gif" types))
-      (when (featurep 'xpm)
-       (push "xpm" types))
-      types))
+  :group 'gnus-picon)
+
+(defcustom gnus-picon-file-types
+  (let ((types (list "xbm")))
+    (if (gnus-image-type-available-p 'gif)
+       (setq types (cons "gif" types)))
+    (if (gnus-image-type-available-p 'xpm)
+       (setq types (cons "xpm" types)))
+    types)
   "*List of suffixes on picon file names to try."
   :type '(repeat string)
-  :group 'picons)
-
-(defcustom gnus-picons-display-article-move-p t
-  "*Whether to move point to first empty line when displaying picons.
-This has only an effect if `gnus-picons-display-where' has value `article'."
-  :type 'boolean
-  :group 'picons)
-
-(defcustom gnus-picons-clear-cache-on-shutdown t
-  "*Whether to clear the picons cache when exiting gnus.
-Gnus caches every picons it finds while it is running.  This saves
-some time in the search process but eats some memory.  If this
-variable is set to nil, Gnus will never clear the cache itself; you
-will have to manually call `gnus-picons-clear-cache' to clear it.
-Otherwise the cache will be cleared every time you exit Gnus."
-  :type 'boolean
-  :group 'picons)
-
-(defcustom gnus-picons-piconsearch-url nil
-  "*The url to query for picons.  Setting this to nil will disable it.
-The only publicly available address currently known is
-http://www.cs.indiana.edu:800/piconsearch.  If you know of any other,
-please tell me so that we can list it."
-  :type '(choice (const :tag "Disable" :value nil)
-                (const :tag "www.cs.indiana.edu"
-                       :value "http://www.cs.indiana.edu:800/piconsearch")
-                (string))
-  :group 'picons)
-
-(defface gnus-picons-xbm-face '((t (:foreground "black" :background "white")))
-  "Face to show X face"
-  :group 'picons)
+  :group 'gnus-picon)
 
-;;; Internal variables:
+(defface gnus-picon-xbm-face '((t (:foreground "black" :background "white")))
+  "Face to show xbm picon in."
+  :group 'gnus-picon)
 
-(defvar gnus-picons-processes-alist nil
-  "Picons processes currently running and their environment.")
-(defvar gnus-picons-glyph-alist nil
-  "Picons glyphs cache.
-List of pairs (KEY . GLYPH) where KEY is either a filename or an URL.")
-(defvar gnus-picons-url-alist nil
-  "Picons file names cache.
-List of pairs (KEY . NAME) where KEY is (USER HOST DBS) and NAME is an URL.")
+(defface gnus-picon-face '((t (:foreground "black" :background "white")))
+  "Face to show picon in."
+  :group 'gnus-picon)
 
-(defvar gnus-picons-jobs-alist nil
-  "List of jobs that still need be done.
-This is a list of (SYM-ANN TAG ARGS...) where SYM-ANN three annotations list,
-TAG is one of `picon' or `search' indicating that the job should query a
-picon or do a search for picons file names, and ARGS is some additionnal
-arguments necessary for the job.")
+;;; Internal variables:
 
-(defvar gnus-picons-job-already-running nil
-  "Lock to ensure only one stream of http requests is running.")
+(defvar gnus-picon-setup-p nil)
+(defvar gnus-picon-glyph-alist nil
+  "Picon glyphs cache.
+List of pairs (KEY . GLYPH) where KEY is either a filename or an URL.")
+(defvar gnus-picon-cache nil)
 
 ;;; Functions:
 
-(defun gnus-picons-remove-all ()
-  "Removes all picons from the Gnus display(s)."
-  (interactive)
-  (map-extents (function (lambda (ext unused) (delete-annotation ext) nil))
-              nil nil nil nil nil 'gnus-picon)
-  (setq gnus-picons-jobs-alist '())
-  ;; notify running job that it may have been preempted
-  (if (and (listp gnus-picons-job-already-running)
-          gnus-picons-job-already-running)
-      (setq gnus-picons-job-already-running t)))
-
-(defun gnus-get-buffer-name (variable)
-  "Returns the buffer name associated with the contents of a variable."
-  (cond ((symbolp variable) (let ((newvar (cdr (assq variable
-                                                    gnus-window-to-buffer))))
-                             (cond ((symbolp newvar)
-                                    (symbol-value newvar))
-                                   ((stringp newvar) newvar))))
-        ((stringp variable) variable)))
-
-(defun gnus-picons-set-buffer ()
-  (set-buffer
-   (get-buffer-create (gnus-get-buffer-name gnus-picons-display-where)))
-  (gnus-add-current-to-buffer-list)
-  (goto-char (point-min))
-  (if (and (eq gnus-picons-display-where 'article)
-          gnus-picons-display-article-move-p)
-      (if (search-forward "\n\n" nil t)
-         (forward-line -1)
-       (goto-char (point-max)))
-    (setq buffer-read-only t)
-    (unless gnus-picons-has-modeline-p
-      (set-specifier has-modeline-p
-                    (list (list (current-buffer)
-                                (cons nil gnus-picons-has-modeline-p)))))))
-
-(defun gnus-picons-prepare-for-annotations ()
-  "Prepare picons buffer for putting annotations."
-  ;; let drawing catch up
-  (when gnus-picons-refresh-before-display
-    (sit-for 0))
-  (gnus-picons-set-buffer)
-  (gnus-picons-remove-all))
-
-(defun gnus-picons-make-annotation (&rest args)
-  (let ((annot (apply 'make-annotation args)))
-    (set-extent-property annot 'gnus-picon t)
-    (set-extent-property annot 'duplicable t)
-    annot))
-
-(defun gnus-picons-article-display-x-face ()
-  "Display the x-face header bitmap in the 'gnus-picons-display-where buffer."
-  (let ((gnus-article-x-face-command 'gnus-picons-display-x-face))
-    (gnus-article-display-x-face)))
-
-(defun gnus-picons-x-face-sentinel (process event)
-  (when (memq process gnus-picons-processes-alist)
-    (setq gnus-picons-processes-alist
-         (delq process gnus-picons-processes-alist))
-    (gnus-picons-set-buffer)
-    (gnus-picons-make-annotation (make-glyph gnus-picons-x-face-file-name)
-                                nil 'text)
-    (delete-file gnus-picons-x-face-file-name)))
-
-(defun gnus-picons-display-x-face (beg end)
-  "Function to display the x-face header in the picons window.
-To use:  (setq gnus-article-x-face-command 'gnus-picons-display-x-face)"
+(defsubst gnus-picon-split-address (address)
+  (setq address (split-string address "@"))
+  (if (stringp (cadr address))
+      (cons (car address) (split-string (cadr address) "\\."))
+    (if (stringp (car address))
+       (split-string (car address) "\\."))))
+
+(defun gnus-picon-find-face (address directories &optional exact)
+  (let* ((address (gnus-picon-split-address address))
+        (user (pop address))
+        (faddress address)
+        database directory result instance base)
+    (catch 'found
+      (dolist (database gnus-picon-databases)
+       (dolist (directory directories)
+         (setq address faddress
+               base (expand-file-name directory database))
+         (while address
+           (when (setq result (gnus-picon-find-image
+                               (concat base "/" (mapconcat 'downcase
+                                                           (reverse address)
+                                                           "/")
+                                       "/" (downcase user) "/")))
+             (throw 'found result))
+           (if exact
+               (setq address nil)
+             (pop address)))
+         ;; Kludge to search MISC as well.  But not in "news".
+         (unless (string= directory "news")
+           (when (setq result (gnus-picon-find-image
+                               (concat base "/MISC/" user "/")))
+             (throw 'found result))))))))
+
+(defun gnus-picon-find-image (directory)
+  (let ((types gnus-picon-file-types)
+       found type file)
+    (while (and (not found)
+               (setq type (pop types)))
+      (setq found (file-exists-p (setq file (concat directory "face." type)))))
+    (if found
+       file
+      nil)))
+
+(defun gnus-picon-insert-glyph (glyph category)
+  "Insert GLYPH into the buffer.
+GLYPH can be either a glyph or a string."
+  (if (stringp glyph)
+      (insert glyph)
+    (gnus-add-wash-type category)
+    (gnus-add-image category (car glyph))
+    (gnus-put-image (car glyph) (cdr glyph) category)))
+
+(defun gnus-picon-create-glyph (file)
+  (or (cdr (assoc file gnus-picon-glyph-alist))
+      (cdar (push (cons file (gnus-create-image file))
+                 gnus-picon-glyph-alist))))
+
+;;; Functions that does picon transformations:
+
+(defun gnus-picon-transform-address (header category)
+  (gnus-with-article-headers
+    (let ((addresses
+          (mail-header-parse-addresses
+           ;; mail-header-parse-addresses does not work (reliably) on
+           ;; decoded headers.
+           (or
+            (ignore-errors
+              (mail-encode-encoded-word-string
+               (or (mail-fetch-field header) "")))
+            (mail-fetch-field header))))
+         spec file point cache)
+      (dolist (address addresses)
+       (setq address (car address))
+       (when (and (stringp address)
+                  (setq spec (gnus-picon-split-address address)))
+         (if (setq cache (cdr (assoc address gnus-picon-cache)))
+             (setq spec cache)
+           (when (setq file (or (gnus-picon-find-face
+                                 address gnus-picon-user-directories)
+                                (gnus-picon-find-face
+                                 (concat "unknown@"
+                                         (mapconcat
+                                          'identity (cdr spec) "."))
+                                 gnus-picon-user-directories)))
+             (setcar spec (cons (gnus-picon-create-glyph file)
+                                (car spec))))
+
+           (dotimes (i (1- (length spec)))
+             (when (setq file (gnus-picon-find-face
+                               (concat "unknown@"
+                                       (mapconcat
+                                        'identity (nthcdr (1+ i) spec) "."))
+                               gnus-picon-domain-directories t))
+               (setcar (nthcdr (1+ i) spec)
+                       (cons (gnus-picon-create-glyph file)
+                             (nth (1+ i) spec)))))
+           (setq spec (nreverse spec))
+           (push (cons address spec) gnus-picon-cache))
+
+         (gnus-article-goto-header header)
+         (mail-header-narrow-to-field)
+         (when (search-forward address nil t)
+           (delete-region (match-beginning 0) (match-end 0))
+           (setq point (point))
+           (while spec
+             (goto-char point)
+             (if (> (length spec) 2)
+                 (insert ".")
+               (if (= (length spec) 2)
+                 (insert "@")))
+             (gnus-picon-insert-glyph (pop spec) category))))))))
+
+(defun gnus-picon-transform-newsgroups (header)
   (interactive)
-  (if (featurep 'xface)
-      ;; Use builtin support
-      (save-excursion
-       (gnus-picons-set-buffer)
-       (gnus-picons-make-annotation
-        (vector 'xface
-                :data (concat "X-Face: " (buffer-substring beg end)))
-        nil 'text))
-    ;; convert the x-face header to a .xbm file
-    (let* ((process-connection-type nil)
-          (process (start-process-shell-command "gnus-x-face" nil 
-                                                gnus-picons-convert-x-face)))
-      (push process gnus-picons-processes-alist)
-      (process-kill-without-query process)
-      (set-process-sentinel process 'gnus-picons-x-face-sentinel)
-      (process-send-region process beg end)
-      (process-send-eof process))))
-
-(defun gnus-article-display-picons ()
-  "Display faces for an author and her domain in gnus-picons-display-where."
+  (gnus-with-article-headers
+    (gnus-article-goto-header header)
+    (mail-header-narrow-to-field)
+    (let ((groups (message-tokenize-header (mail-fetch-field header)))
+         spec file point)
+      (dolist (group groups)
+       (unless (setq spec (cdr (assoc group gnus-picon-cache)))
+         (setq spec (nreverse (split-string group "[.]")))
+         (dotimes (i (length spec))
+           (when (setq file (gnus-picon-find-face
+                             (concat "unknown@"
+                                     (mapconcat
+                                      'identity (nthcdr i spec) "."))
+                             gnus-picon-news-directories t))
+             (setcar (nthcdr i spec)
+                     (cons (gnus-picon-create-glyph file)
+                           (nth i spec)))))
+           (push (cons group spec) gnus-picon-cache))
+       (when (search-forward group nil t)
+         (delete-region (match-beginning 0) (match-end 0))
+         (save-restriction
+           (narrow-to-region (point) (point))
+           (while spec
+             (goto-char (point-min))
+             (if (> (length spec) 1)
+                 (insert "."))
+             (gnus-picon-insert-glyph (pop spec) 'newsgroups-picon))
+           (goto-char (point-max))))))))
+
+;;; Commands:
+
+;; #### NOTE: the test for buffer-read-only is the same as in
+;; article-display-[x-]face. See the comment up there.
+
+;;;###autoload
+(defun gnus-treat-from-picon ()
+  "Display picons in the From header.
+If picons are already displayed, remove them."
   (interactive)
-  (let (from at-idx)
-    (when (and (featurep 'xpm)
-              (or (not (fboundp 'device-type)) (equal (device-type) 'x))
-              (setq from (mail-fetch-field "from"))
-              (setq from (downcase (or (cadr (mail-extract-address-components
-                                              from))
-                                       "")))
-              (or (setq at-idx (string-match "@" from))
-                  (setq at-idx (length from))))
-      (save-excursion
-       (let ((username (downcase (substring from 0 at-idx)))
-             (addrs (if (eq at-idx (length from))
-                        (if gnus-local-domain
-                            (message-tokenize-header gnus-local-domain "."))
-                      (message-tokenize-header (substring from (1+ at-idx))
-                                               "."))))
-         (gnus-picons-prepare-for-annotations)
-         (gnus-group-display-picons)
-         (if (null gnus-picons-piconsearch-url)
-             (progn
-               (gnus-picons-display-pairs (gnus-picons-lookup-pairs
-                                           addrs
-                                           gnus-picons-domain-directories)
-                                          gnus-picons-display-as-address
-                                          "." t)
-               (if (and gnus-picons-display-as-address addrs)
-                   (gnus-picons-make-annotation
-                    [string :data "@"] nil 'text nil nil nil t))
-               (gnus-picons-display-picon-or-name
-                (gnus-picons-lookup-user username addrs)
-                username t))
-           (push (list 'gnus-article-annotations 'search username addrs
-                       gnus-picons-domain-directories t)
-                 gnus-picons-jobs-alist)
-           (gnus-picons-next-job)))))))
-
-(defun gnus-group-display-picons ()
-  "Display icons for the group in the `gnus-picons-display-where' buffer."
+  (let ((wash-picon-p buffer-read-only))
+    (gnus-with-article-buffer
+      (if (and wash-picon-p (memq 'from-picon gnus-article-wash-types))
+         (gnus-delete-images 'from-picon)
+       (gnus-picon-transform-address "from" 'from-picon)))
+    ))
+
+;;;###autoload
+(defun gnus-treat-mail-picon ()
+  "Display picons in the Cc and To headers.
+If picons are already displayed, remove them."
   (interactive)
-  (when (and (featurep 'xpm)
-            (or (not (fboundp 'device-type)) (equal (device-type) 'x))
-            (or (null gnus-picons-group-excluded-groups)
-                (not (string-match gnus-picons-group-excluded-groups
-                                   gnus-newsgroup-name))))
-    (save-excursion
-      (gnus-picons-prepare-for-annotations)
-      (if (null gnus-picons-piconsearch-url)
-         (gnus-picons-display-pairs
-                (gnus-picons-lookup-pairs
-                 (reverse (message-tokenize-header
-                           (gnus-group-real-name gnus-newsgroup-name) 
-                           "."))
-                 gnus-picons-news-directories)
-                t ".")
-       (push (list 'gnus-group-annotations 'search nil
-                   (message-tokenize-header 
-                    (gnus-group-real-name gnus-newsgroup-name) ".")
-                   (if (listp gnus-picons-news-directories)
-                       gnus-picons-news-directories
-                     (list gnus-picons-news-directories))
-                   nil)
-             gnus-picons-jobs-alist)
-       (gnus-picons-next-job))
-
-      (add-hook 'gnus-summary-exit-hook 'gnus-picons-remove-all))))
-
-(defun gnus-picons-lookup-internal (addrs dir)
-  (setq dir (expand-file-name dir gnus-picons-database))
-  (gnus-picons-try-face (dolist (part (reverse addrs) dir)
-                         (setq dir (expand-file-name part dir)))))
-
-(defun gnus-picons-lookup (addrs dirs)
-  "Lookup the picon for ADDRS in databases DIRS.
-Returns the picon filename or NIL if none found."
-  (let (result)
-    (while (and dirs (null result))
-      (setq result (gnus-picons-lookup-internal addrs (pop dirs))))
-    result))
-
-(defun gnus-picons-lookup-user-internal (user domains)
-  (let ((dirs gnus-picons-user-directories)
-       domains-tmp dir picon)
-    (while (and dirs (null picon))
-      (setq domains-tmp domains
-           dir (pop dirs))
-      (while (and domains-tmp
-                 (null (setq picon (gnus-picons-lookup-internal
-                                    (cons user domains-tmp) dir))))
-       (pop domains-tmp))
-      ;; Also make a try in MISC subdir
-      (unless picon
-       (setq picon (gnus-picons-lookup-internal (list user "MISC") dir))))
-    picon))
-
-(defun gnus-picons-lookup-user (user domains)
-  "Lookup the picon for USER at DOMAINS.
-USER is a string containing a name.
-DOMAINS is a list of strings from the fully qualified domain name."
-  (or (gnus-picons-lookup-user-internal user domains)
-      (gnus-picons-lookup-user-internal "unknown" domains)))
-
-(defun gnus-picons-lookup-pairs (domains directories)
-  "Lookup picons for DOMAINS and all its parents in DIRECTORIES.
-Returns a list of PAIRS whose CAR is the picon filename or NIL if
-none, and whose CDR is the corresponding element of DOMAINS."
-  (let (picons)
-    (setq directories (if (listp directories)
-                         directories
-                       (list directories)))
-    (while domains
-      (push (list (gnus-picons-lookup (cons "unknown" domains) directories)
-                 (pop domains))
-           picons))
-    picons))
-
-(defun gnus-picons-display-picon-or-name (picon name &optional right-p)
-  (cond (picon (gnus-picons-display-glyph picon name right-p))
-       (gnus-picons-display-as-address (list (gnus-picons-make-annotation
-                                              (vector 'string :data name)
-                                              nil 'text
-                                              nil nil nil right-p)))))
-
-(defun gnus-picons-display-pairs (pairs &optional bar-p dot-p right-p)
-  "Display picons in list PAIRS."
-  (let ((domain-p (and gnus-picons-display-as-address dot-p))
-       pair picons)
-    (when (and bar-p domain-p right-p)
-      (setq picons (gnus-picons-display-glyph
-                   (let ((gnus-picons-file-suffixes '("xbm")))
-                     (gnus-picons-try-face
-                      gnus-xmas-glyph-directory "bar."))
-                   nil right-p)))
-    (while (setq pair (pop pairs))
-      (setq picons (nconc picons
-                         (gnus-picons-display-picon-or-name
-                          (car pair) (cadr pair) right-p)
-                         (if (and domain-p pairs)
-                             (list (gnus-picons-make-annotation
-                                    (vector 'string :data dot-p)
-                                    nil 'text nil nil nil right-p))))))
-    picons))
-
-(defun gnus-picons-try-face (dir &optional filebase)
-  (let* ((dir (file-name-as-directory dir))
-        (filebase (or filebase "face."))
-        (key (concat dir filebase))
-        (glyph (cdr (assoc key gnus-picons-glyph-alist)))
-        (suffixes gnus-picons-file-suffixes)
-        f suf)
-    (while (setq suf (pop suffixes))
-      (when (file-exists-p (setq f (expand-file-name
-                                   (concat filebase suf)
-                                   dir)))
-       (setq suffixes nil
-             glyph (make-glyph f))
-       (when (equal suf "xbm")
-         (set-glyph-face glyph 'gnus-picons-xbm-face))
-       (push (cons key glyph) gnus-picons-glyph-alist)))
-    glyph))
-
-(defun gnus-picons-display-glyph (glyph &optional part rightp)
-  (let ((new (gnus-picons-make-annotation
-             glyph (point) 'text nil nil nil rightp)))
-    (when (and part gnus-picons-display-as-address)
-      (set-annotation-data
-       new (cons new (make-glyph (vector 'string :data part))))
-      (set-annotation-action new 'gnus-picons-action-toggle))
-    (nconc
-     (list new)
-     (if (and (eq major-mode 'gnus-article-mode)
-             (not gnus-picons-display-as-address)
-             (not part))
-        (list (gnus-picons-make-annotation [string :data " "] (point)
-                                           'text nil nil nil rightp))))))
-
-(defun gnus-picons-action-toggle (data)
-  "Toggle annotation"
-  (interactive "e")
-  (let* ((annot (car data))
-        (glyph (annotation-glyph annot)))
-    (set-annotation-glyph annot (cdr data))
-    (set-annotation-data annot (cons annot glyph))))
-
-(defun gnus-picons-clear-cache ()
-  "Clear the picons cache"
+  (let ((wash-picon-p buffer-read-only))
+    (gnus-with-article-buffer
+      (if (and wash-picon-p (memq 'mail-picon gnus-article-wash-types))
+         (gnus-delete-images 'mail-picon)
+       (gnus-picon-transform-address "cc" 'mail-picon)
+       (gnus-picon-transform-address "to" 'mail-picon)))
+    ))
+
+;;;###autoload
+(defun gnus-treat-newsgroups-picon ()
+  "Display picons in the Newsgroups and Followup-To headers.
+If picons are already displayed, remove them."
   (interactive)
-  (setq gnus-picons-glyph-alist nil
-       gnus-picons-url-alist nil))
-
-(gnus-add-shutdown 'gnus-picons-close 'gnus)
-
-(defun gnus-picons-close ()
-  "Shut down the picons."
-  (if gnus-picons-clear-cache-on-shutdown
-      (gnus-picons-clear-cache)))
-
-;;; Query a remote DB.  This requires some stuff from w3 !
-
-(require 'url)
-(require 'w3-forms)
-
-(defun gnus-picons-url-retrieve (url fn arg)
-  (let ((old-asynch (default-value 'url-be-asynchronous))
-       (url-working-buffer (generate-new-buffer " *picons*"))
-       (url-package-name "Gnus")
-       (url-package-version gnus-version-number)
-       url-request-method)
-    (setq-default url-be-asynchronous t)
-    (save-excursion
-      (set-buffer url-working-buffer)
-      (setq url-be-asynchronous t
-           url-current-callback-data arg
-           url-current-callback-func fn)
-      (url-retrieve url t))
-    (setq-default url-be-asynchronous old-asynch)))
-
-(defun gnus-picons-make-glyph (type)
-  "Make a TYPE glyph using current buffer as data.  Handles xbm nicely."
-  (cond ((null type) nil)
-       ((eq type 'xbm) (let ((fname (make-temp-name "/tmp/picon")))
-                         (write-region (point-min) (point-max) fname
-                                       nil 'quiet)
-                         (prog1 (make-glyph (vector 'xbm :file fname))
-                           (delete-file fname))))
-       (t (make-glyph (vector type :data (buffer-string))))))
-
-;;; Parsing of piconsearch result page.
-
-;; Assumes:
-;; 1 - each value field has the form: "<strong>key</strong> = <kbd>value</kbd>"
-;; 2 - a "<p>" separates the keywords from the results
-;; 3 - every results begins by the path within the database at the beginning
-;;     of the line in raw text.
-;; 3b - and the href following it is the preferred image type.
-
-;; if 1 or 2 is not met, it will probably cause an error.  The other
-;; will go undetected
-
-(defun gnus-picons-parse-value (name)
-  (goto-char (point-min))
-  (re-search-forward (concat "<strong>"
-                            (regexp-quote name)
-                            "</strong> *= *<kbd> *\\([^ <][^<]*\\) *</kbd>"))
-  (buffer-substring (match-beginning 1) (match-end 1)))
-
-(defun gnus-picons-parse-filenames ()
-  ;; returns an alist of ((USER ADDRS DB) . URL)
-  (let* ((case-fold-search t)
-        (user (gnus-picons-parse-value "user"))
-        (host (gnus-picons-parse-value "host"))
-        (dbs (message-tokenize-header (gnus-picons-parse-value "db") " "))
-        (start-re
-         (concat
-          ;; dbs
-          "^\\(" (mapconcat 'identity dbs "\\|") "\\)/"
-          ;; host
-          "\\(\\(" (replace-in-string host "\\." "/\\|" t) "/\\|MISC/\\)*\\)"
-          ;; user
-          "\\(" (regexp-quote user) "\\|unknown\\)/"
-          "face\\."))
-        cur-db cur-host cur-user types res)
-    ;; now point will be somewhere in the header.  Find beginning of
-    ;; entries
-    (re-search-forward "<p>[ \t\n]*")
-    (while (re-search-forward start-re nil t)
-      (setq cur-db (buffer-substring (match-beginning 1) (match-end 1))
-           cur-host (buffer-substring (match-beginning 2) (match-end 2))
-           cur-user (buffer-substring (match-beginning 4) (match-end 4))
-           cur-host (nreverse (message-tokenize-header cur-host "/")))
-      ;; XXX - KLUDGE: there is a blank picon in news/MISC/unknown
-      (unless (and (string-equal cur-db "news")
-                  (string-equal cur-user "unknown")
-                  (equal cur-host '("MISC")))
-       ;; ok now we have found an entry (USER HOST DB), find the
-       ;; corresponding picon URL
-       (save-restriction
-         ;; restrict region to this entry
-         (narrow-to-region (point) (search-forward "<br>"))
-         (goto-char (point-min))
-         (setq types gnus-picons-file-suffixes)
-         (while (and types
-                     (not (re-search-forward
-                           (concat "<a[ \t\n]+href=\"\\([^\"]*\\."
-                                   (regexp-quote (car types)) "\\)\"")
-                           nil t)))
-           (pop types))
-         (push (cons (list cur-user cur-host cur-db)
-                     (buffer-substring (match-beginning 1) (match-end 1)))
-               res))))
-    (nreverse res)))
-
-;;; picon network display functions :
-
-(defun gnus-picons-network-display-internal (sym-ann glyph part right-p)
-  (gnus-picons-set-buffer)
-  (gnus-picons-display-picon-or-name glyph part right-p)
-  (gnus-picons-next-job-internal))
-
-(defun gnus-picons-network-display-callback (url part sym-ann right-p)
-  (let ((glyph (gnus-picons-make-glyph (cdr (assoc url-current-mime-type
-                                                  w3-image-mappings)))))
-    (kill-buffer (current-buffer))
-    (push (cons url glyph) gnus-picons-glyph-alist)
-    ;; only do the job if it has not been preempted.
-    (if (equal gnus-picons-job-already-running
-              (list sym-ann 'picon url part right-p))
-       (gnus-picons-network-display-internal sym-ann glyph part right-p)
-      (gnus-picons-next-job-internal))))
-
-(defun gnus-picons-network-display (url part sym-ann right-p)
-  (let ((cache (assoc url gnus-picons-glyph-alist)))
-    (if (or cache (null url))
-       (gnus-picons-network-display-internal sym-ann (cdr cache) part right-p)
-      (gnus-picons-url-retrieve url 'gnus-picons-network-display-callback
-                               (list url part sym-ann right-p)))))
-
-;;; search job functions
-
-(defun gnus-picons-network-search-internal (user addrs dbs sym-ann right-p
-                                                &optional fnames)
-  (let (curkey dom pfx url dbs-tmp cache new-jobs)
-    ;; First do the domain search
-    (dolist (part (if right-p
-                     (reverse addrs)
-                   addrs))
-      (setq pfx (nconc (list part) pfx)
-           dom (cond ((and dom right-p) (concat part "." dom))
-                     (dom (concat dom "." part))
-                     (t part))
-           curkey (list "unknown" dom dbs))
-      (when (null (setq cache (assoc curkey gnus-picons-url-alist)))
-       ;; This one is not yet in the cache, create a new entry
-       ;; Search for an entry
-       (setq dbs-tmp dbs
-             url nil)
-       (while (and dbs-tmp (null url))
-         (setq url (or (cdr (assoc (list "unknown" pfx (car dbs-tmp)) fnames))
-                       (and (eq dom part)
-                            ;; This is the first component.  Try the
-                            ;; catch-all MISC component
-                            (cdr (assoc (list "unknown"
-                                              '("MISC")
-                                              (car dbs-tmp))
-                                        fnames)))))
-         (pop dbs-tmp))
-       (push (setq cache (cons curkey url)) gnus-picons-url-alist))
-      ;; Put this glyph in the job list
-      (if (and (not (eq dom part)) gnus-picons-display-as-address)
-         (push (list sym-ann "." right-p) new-jobs))
-      (push (list sym-ann 'picon (cdr cache) part right-p) new-jobs))
-    ;; next, the user search
-    (when user
-      (setq curkey (list user dom gnus-picons-user-directories))
-      (if (null (setq cache (assoc curkey gnus-picons-url-alist)))
-         (let ((users (list user "unknown"))
-               dirs usr domains-tmp dir picon)
-           (while (and users (null picon))
-             (setq dirs gnus-picons-user-directories
-                   usr (pop users))
-             (while (and dirs (null picon))
-               (setq domains-tmp addrs
-                     dir (pop dirs))
-               (while (and domains-tmp
-                           (null (setq picon (assoc (list usr domains-tmp dir)
-                                                    fnames))))
-                 (pop domains-tmp))
-               (unless picon
-                 (setq picon (assoc (list usr '("MISC") dir) fnames)))))
-           (push (setq cache (cons curkey (cdr picon)))
-                 gnus-picons-url-alist)))
-      (if (and gnus-picons-display-as-address new-jobs)
-         (push (list sym-ann "@" right-p) new-jobs))
-      (push (list sym-ann 'picon (cdr cache) user right-p) new-jobs))
-    (if (and gnus-picons-display-as-address (not right-p))
-       (push (list sym-ann 'bar right-p) new-jobs))
-    ;; only put the jobs in the queue if this job has not been preempted.
-    (if (equal gnus-picons-job-already-running
-              (list sym-ann 'search user addrs dbs right-p))
-       (setq gnus-picons-jobs-alist
-             (nconc (if (and gnus-picons-display-as-address right-p)
-                        (list (list sym-ann 'bar right-p)))
-                    (nreverse new-jobs)
-                    gnus-picons-jobs-alist)))
-    (gnus-picons-next-job-internal)))
-
-(defun gnus-picons-network-search-callback (user addrs dbs sym-ann right-p)
-  (gnus-picons-network-search-internal user addrs dbs sym-ann right-p
-                                      (prog1 (gnus-picons-parse-filenames)
-                                        (kill-buffer (current-buffer)))))
-
-;; Initiate a query on the picon database
-(defun gnus-picons-network-search (user addrs dbs sym-ann right-p)
-  (let* ((host (mapconcat 'identity addrs "."))
-        (key (list (or user "unknown") host (if user
-                                                 gnus-picons-user-directories
-                                               dbs)))
-        (cache (assoc key gnus-picons-url-alist)))
-    (if (null cache)
-       (gnus-picons-url-retrieve
-        (concat gnus-picons-piconsearch-url
-                "?user=" (w3-form-encode-xwfu (or user "unknown"))
-                "&host=" (w3-form-encode-xwfu host)
-                "&db=" (mapconcat 'w3-form-encode-xwfu
-                                  (if user
-                                      (append dbs
-                                              gnus-picons-user-directories)
-                                    dbs)
-                                  "+"))
-        'gnus-picons-network-search-callback
-        (list user addrs dbs sym-ann right-p))
-      (gnus-picons-network-search-internal user addrs dbs sym-ann right-p))))
-
-;;; Main jobs dispatcher function
-
-(defun gnus-picons-next-job-internal ()
-  (if (setq gnus-picons-job-already-running (pop gnus-picons-jobs-alist))
-      (let* ((job gnus-picons-job-already-running)
-            (sym-ann (pop job))
-            (tag (pop job)))
-       (if tag
-           (cond ((stringp tag);; (SYM-ANN "..." RIGHT-P)
-                  (gnus-picons-network-display-internal sym-ann nil tag
-                                                        (pop job)))
-                 ((eq 'bar tag)
-                  (gnus-picons-network-display-internal
-                   sym-ann
-                   (let ((gnus-picons-file-suffixes '("xbm")))
-                     (gnus-picons-try-face
-                      gnus-xmas-glyph-directory "bar."))
-                   nil (pop job)))
-                 ((eq 'search tag);; (SYM-ANN 'search USER ADDRS DBS RIGHT-P)
-                  (gnus-picons-network-search
-                   (pop job) (pop job) (pop job) sym-ann (pop job)))
-                 ((eq 'picon tag);; (SYM-ANN 'picon URL PART RIGHT-P)
-                  (gnus-picons-network-display
-                   (pop job) (pop job) sym-ann (pop job)))
-                 (t (setq gnus-picons-job-already-running nil)
-                    (error "Unknown picon job tag %s" tag)))))))
-
-(defun gnus-picons-next-job ()
-  "Start processing the job queue if it is not in progress"
-  (unless gnus-picons-job-already-running
-    (gnus-picons-next-job-internal)))
+  (let ((wash-picon-p buffer-read-only))
+    (gnus-with-article-buffer
+      (if (and wash-picon-p (memq 'newsgroups-picon gnus-article-wash-types))
+         (gnus-delete-images 'newsgroups-picon)
+       (gnus-picon-transform-newsgroups "newsgroups")
+       (gnus-picon-transform-newsgroups "followup-to")))
+    ))
 
 (provide 'gnus-picon)
 
index efebc35..2e0a988 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-range.el --- range and sequence functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; List and range functions
 
+(defsubst gnus-range-normalize (range)
+  "Normalize RANGE.
+If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
+  (if (listp (cdr-safe range)) range (list range)))
+
 (defun gnus-last-element (list)
   "Return last element of LIST."
   (while (cdr list)
       (setq list2 (cdr list2)))
     list1))
 
-(defun gnus-sorted-complement (list1 list2)
+(defun gnus-range-difference (range1 range2)
+  "Return the range of elements in RANGE1 that do not appear in RANGE2.
+Both ranges must be in ascending order."
+  (setq range1 (gnus-range-normalize range1))
+  (setq range2 (gnus-range-normalize range2))
+  (let* ((new-range (cons nil (copy-sequence range1)))
+         (r new-range)
+         (safe t))
+    (while (cdr r)
+      (let* ((r1 (cadr r))
+             (r2 (car range2))
+             (min1 (if (numberp r1) r1 (car r1)))
+             (max1 (if (numberp r1) r1 (cdr r1)))
+             (min2 (if (numberp r2) r2 (car r2)))
+             (max2 (if (numberp r2) r2 (cdr r2))))
+
+        (cond ((> min1 max1)
+               ;; Invalid range: may result from overlap condition (below)
+               ;; remove Invalid range
+               (setcdr r (cddr r)))
+              ((and (= min1 max1)
+                    (listp r1))
+               ;; Inefficient representation: may result from overlap condition (below)
+               (setcar (cdr r) min1))
+              ((not min2)
+               ;; All done with range2
+               (setq r nil))
+              ((< max1 min2)
+               ;; No overlap: range1 preceeds range2
+               (pop r))
+              ((< max2 min1)
+               ;; No overlap: range2 preceeds range1
+               (pop range2))
+              ((and (<= min2 min1) (<= max1 max2))
+               ;; Complete overlap: range1 removed
+               (setcdr r (cddr r)))
+              (t
+               (setcdr r (nconc (list (cons min1 (1- min2)) (cons (1+ max2) max1)) (cddr r)))))))
+    (cdr new-range)))
+
+
+
+;;;###autoload
+(defun gnus-sorted-difference (list1 list2)
   "Return a list of elements of LIST1 that do not appear in LIST2.
+Both lists have to be sorted over <.
+The tail of LIST1 is not copied."
+  (let (out)
+    (while (and list1 list2)
+      (cond ((= (car list1) (car list2))
+            (setq list1 (cdr list1)
+                  list2 (cdr list2)))
+           ((< (car list1) (car list2))
+            (setq out (cons (car list1) out))
+            (setq list1 (cdr list1)))
+           (t
+            (setq list2 (cdr list2)))))
+    (nconc (nreverse out) list1)))
+
+;;;###autoload
+(defun gnus-sorted-ndifference (list1 list2)
+  "Return a list of elements of LIST1 that do not appear in LIST2.
+Both lists have to be sorted over <.
+LIST1 is modified."
+  (let* ((top (cons nil list1))
+        (prev top))
+    (while (and list1 list2)
+      (cond ((= (car list1) (car list2))
+            (setcdr prev (cdr list1))
+            (setq list1 (cdr list1)
+                  list2 (cdr list2)))
+           ((< (car list1) (car list2))
+            (setq prev list1
+                  list1 (cdr list1)))
+           (t
+            (setq list2 (cdr list2)))))
+    (cdr top)))
+
+;;;###autoload
+(defun gnus-sorted-complement (list1 list2)
+  "Return a list of elements that are in LIST1 or LIST2 but not both.
 Both lists have to be sorted over <."
   (let (out)
     (if (or (null list1) (null list2))
@@ -72,6 +158,7 @@ Both lists have to be sorted over <."
               (setq list2 (cdr list2)))))
       (nconc (nreverse out) (or list1 list2)))))
 
+;;;###autoload
 (defun gnus-intersection (list1 list2)
   (let ((result nil))
     (while list2
@@ -80,8 +167,10 @@ Both lists have to be sorted over <."
       (setq list2 (cdr list2)))
     result))
 
+;;;###autoload
 (defun gnus-sorted-intersection (list1 list2)
-  ;; LIST1 and LIST2 have to be sorted over <.
+  "Return intersection of LIST1 and LIST2.
+LIST1 and LIST2 have to be sorted over <."
   (let (out)
     (while (and list1 list2)
       (cond ((= (car list1) (car list2))
@@ -94,9 +183,13 @@ Both lists have to be sorted over <."
             (setq list2 (cdr list2)))))
     (nreverse out)))
 
-(defun gnus-set-sorted-intersection (list1 list2)
-  ;; LIST1 and LIST2 have to be sorted over <.
-  ;; This function modifies LIST1.
+;;;###autoload
+(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection)
+
+;;;###autoload
+(defun gnus-sorted-nintersection (list1 list2)
+  "Return intersection of LIST1 and LIST2 by modifying cdr pointers of LIST1.
+LIST1 and LIST2 have to be sorted over <."
   (let* ((top (cons nil list1))
         (prev top))
     (while (and list1 list2)
@@ -112,6 +205,55 @@ Both lists have to be sorted over <."
     (setcdr prev nil)
     (cdr top)))
 
+;;;###autoload
+(defun gnus-sorted-union (list1 list2)
+  "Return union of LIST1 and LIST2.
+LIST1 and LIST2 have to be sorted over <."
+  (let (out)
+    (while (and list1 list2)
+      (cond ((= (car list1) (car list2))
+            (setq out (cons (car list1) out)
+                  list1 (cdr list1)
+                  list2 (cdr list2)))
+           ((< (car list1) (car list2))
+            (setq out (cons (car list1) out)
+                  list1 (cdr list1)))
+           (t
+            (setq out (cons (car list2) out)
+                  list2 (cdr list2)))))
+    (while list1
+      (setq out (cons (car list1) out)
+           list1 (cdr list1)))
+    (while list2
+      (setq out (cons (car list2) out)
+           list2 (cdr list2)))
+    (nreverse out)))
+
+;;;###autoload
+(defun gnus-sorted-nunion (list1 list2)
+  "Return union of LIST1 and LIST2 by modifying cdr pointers of LIST1.
+LIST1 and LIST2 have to be sorted over <."
+  (let* ((top (cons nil list1))
+        (prev top))
+    (while (and list1 list2)
+      (cond ((= (car list1) (car list2))
+            (setq prev list1
+                  list1 (cdr list1)
+                  list2 (cdr list2)))
+           ((< (car list1) (car list2))
+            (setq prev list1
+                  list1 (cdr list1)))
+           (t
+            (setcdr prev (list (car list2)))
+            (setq prev (cdr prev)
+                  list2 (cdr list2))
+            (setcdr prev list1))))
+    (while list2
+      (setcdr prev (list (car list2)))
+      (setq prev (cdr prev)
+           list2 (cdr list2)))
+    (cdr top)))
+
 (defun gnus-compress-sequence (numbers &optional always-list)
   "Convert list of numbers to a list of ranges or a single range.
 If ALWAYS-LIST is non-nil, this function will always release a list of
@@ -224,13 +366,81 @@ Note: LIST has to be sorted over `<'."
        (setq ranges (cdr ranges)))
       out)))
 
-(defun gnus-remove-from-range (ranges list)
-  "Return a list of ranges that has all articles from LIST removed from RANGES.
-Note: LIST has to be sorted over `<'."
-  ;; !!! This function shouldn't look like this, but I've got a headache.
-  (gnus-compress-sequence
-   (gnus-sorted-complement
-    (gnus-uncompress-range ranges) list)))
+(defun gnus-remove-from-range (range1 range2)
+  "Return a range that has all articles from RANGE2 removed from RANGE1.
+The returned range is always a list.  RANGE2 can also be a unsorted
+list of articles.  RANGE1 is modified by side effects, RANGE2 is not
+modified."
+  (if (or (null range1) (null range2))
+      range1
+    (let (out r1 r2 r1_min r1_max r2_min r2_max
+             (range2 (gnus-copy-sequence range2)))
+      (setq range1 (if (listp (cdr range1)) range1 (list range1))
+           range2 (sort (if (listp (cdr range2)) range2 (list range2))
+                        (lambda (e1 e2)
+                          (< (if (consp e1) (car e1) e1)
+                             (if (consp e2) (car e2) e2))))
+           r1 (car range1)
+           r2 (car range2)
+           r1_min (if (consp r1) (car r1) r1)
+           r1_max (if (consp r1) (cdr r1) r1)
+           r2_min (if (consp r2) (car r2) r2)
+           r2_max (if (consp r2) (cdr r2) r2))
+      (while (and range1 range2)
+       (cond ((< r2_max r1_min)        ; r2 < r1
+              (pop range2)
+              (setq r2 (car range2)
+                    r2_min (if (consp r2) (car r2) r2)
+                    r2_max (if (consp r2) (cdr r2) r2)))
+             ((and (<= r2_min r1_min) (<= r1_max r2_max)) ; r2 overlap r1
+              (pop range1)
+              (setq r1 (car range1)
+                    r1_min (if (consp r1) (car r1) r1)
+                    r1_max (if (consp r1) (cdr r1) r1)))
+             ((and (<= r2_min r1_min) (<= r2_max r1_max)) ; r2 overlap min r1
+              (pop range2)
+              (setq r1_min (1+ r2_max)
+                    r2 (car range2)
+                    r2_min (if (consp r2) (car r2) r2)
+                    r2_max (if (consp r2) (cdr r2) r2)))
+             ((and (<= r1_min r2_min) (<= r2_max r1_max)) ; r2 contained in r1
+              (if (eq r1_min (1- r2_min))
+                  (push r1_min out)
+                (push (cons r1_min (1- r2_min)) out))
+              (pop range2)
+              (if (< r2_max r1_max)    ; finished with r1?
+                  (setq r1_min (1+ r2_max))
+                (pop range1)
+                (setq r1 (car range1)
+                      r1_min (if (consp r1) (car r1) r1)
+                      r1_max (if (consp r1) (cdr r1) r1)))
+              (setq r2 (car range2)
+                    r2_min (if (consp r2) (car r2) r2)
+                    r2_max (if (consp r2) (cdr r2) r2)))
+             ((and (<= r2_min r1_max) (<= r1_max r2_max)) ; r2 overlap max r1
+              (if (eq r1_min (1- r2_min))
+                  (push r1_min out)
+                (push (cons r1_min (1- r2_min)) out))
+              (pop range1)
+              (setq r1 (car range1)
+                    r1_min (if (consp r1) (car r1) r1)
+                    r1_max (if (consp r1) (cdr r1) r1)))
+             ((< r1_max r2_min)        ; r2 > r1
+              (pop range1)
+              (if (eq r1_min r1_max)
+                  (push r1_min out)
+                (push (cons r1_min r1_max) out))
+              (setq r1 (car range1)
+                    r1_min (if (consp r1) (car r1) r1)
+                    r1_max (if (consp r1) (cdr r1) r1)))))
+      (when r1
+       (if (eq r1_min r1_max)
+           (push r1_min out)
+         (push (cons r1_min r1_max) out))
+       (pop range1))
+      (while range1
+       (push (pop range1) out))
+      (nreverse out))))
 
 (defun gnus-member-of-range (number ranges)
   (if (not (listp (cdr ranges)))
@@ -250,9 +460,58 @@ Note: LIST has to be sorted over `<'."
        (setq ranges (cdr ranges)))
       (not not-stop))))
 
+(defun gnus-list-range-intersection (list ranges)
+  "Return a list of numbers in LIST that are members of RANGES.
+LIST is a sorted list."
+  (setq ranges (gnus-range-normalize ranges))
+  (let (number result)
+    (while (setq number (pop list))
+      (while (and ranges
+                 (if (numberp (car ranges))
+                     (< (car ranges) number)
+                   (< (cdar ranges) number)))
+       (setq ranges (cdr ranges)))
+      (when (and ranges
+                (if (numberp (car ranges))
+                     (= (car ranges) number)
+                  ;; (caar ranges) <= number <= (cdar ranges)
+                  (>= number (caar ranges))))
+       (push number result)))
+    (nreverse result)))
+
+(defalias 'gnus-inverse-list-range-intersection 'gnus-list-range-difference)
+
+(defun gnus-list-range-difference (list ranges)
+  "Return a list of numbers in LIST that are not members of RANGES.
+LIST is a sorted list."
+  (setq ranges (gnus-range-normalize ranges))
+  (let (number result)
+    (while (setq number (pop list))
+      (while (and ranges
+                 (if (numberp (car ranges))
+                     (< (car ranges) number)
+                   (< (cdar ranges) number)))
+       (setq ranges (cdr ranges)))
+      (when (or (not ranges)
+               (if (numberp (car ranges))
+                   (not (= (car ranges) number))
+                 ;; not ((caar ranges) <= number <= (cdar ranges))
+                 (< number (caar ranges))))
+       (push number result)))
+    (nreverse result)))
+
 (defun gnus-range-length (range)
   "Return the length RANGE would have if uncompressed."
-  (length (gnus-uncompress-range range)))
+  (cond
+   ((null range)
+    0)
+   ((not (listp (cdr range)))
+    (- (cdr range) (car range) -1))
+   (t
+    (let ((sum 0))
+      (dolist (x range sum)
+       (setq sum
+             (+ sum (if (consp x) (- (cdr x) (car x) -1) 1))))))))
 
 (defun gnus-sublist-p (list sublist)
   "Test whether all elements in SUBLIST are members of LIST."
@@ -264,19 +523,71 @@ Note: LIST has to be sorted over `<'."
     sublistp))
 
 (defun gnus-range-add (range1 range2)
-  "Add RANGE2 to RANGE1 destructively."
-  (cond
-   ;; If either are nil, then the job is quite easy.
-   ((or (null range1) (null range2))
-    (or range1 range2))
-   (t
-    ;; I don't like thinking.
-    (gnus-compress-sequence
-     (sort
-      (nconc
-       (gnus-uncompress-range range1)
-       (gnus-uncompress-range range2))
-      '<)))))
+  "Add RANGE2 to RANGE1 (nondestructively)."
+  (unless (listp (cdr range1))
+    (setq range1 (list range1)))
+  (unless (listp (cdr range2))
+    (setq range2 (list range2)))
+  (let ((item1 (pop range1))
+       (item2 (pop range2))
+       range item selector)
+    (while (or item1 item2)
+      (setq selector
+           (cond
+            ((null item1) nil)
+            ((null item2) t)
+            ((and (numberp item1) (numberp item2)) (< item1 item2))
+            ((numberp item1) (< item1 (car item2)))
+            ((numberp item2) (< (car item1) item2))
+            (t (< (car item1) (car item2)))))
+      (setq item
+           (or
+            (let ((tmp1 item) (tmp2 (if selector item1 item2)))
+              (cond
+               ((null tmp1) tmp2)
+               ((null tmp2) tmp1)
+               ((and (numberp tmp1) (numberp tmp2))
+                (cond
+                 ((eq tmp1 tmp2) tmp1)
+                 ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2))
+                 ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1))
+                 (t nil)))
+               ((numberp tmp1)
+                (cond
+                 ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2)
+                 ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2)))
+                 ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1))
+                 (t nil)))
+               ((numberp tmp2)
+                (cond
+                 ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1)
+                 ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1)))
+                 ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2))
+                 (t nil)))
+               ((< (1+ (cdr tmp1)) (car tmp2)) nil)
+               ((< (1+ (cdr tmp2)) (car tmp1)) nil)
+               (t (cons (min (car tmp1) (car tmp2))
+                        (max (cdr tmp1) (cdr tmp2))))))
+            (progn
+              (if item (push item range))
+              (if selector item1 item2))))
+      (if selector
+         (setq item1 (pop range1))
+       (setq item2 (pop range2))))
+    (if item (push item range))
+    (reverse range)))
+
+;;;###autoload
+(defun gnus-add-to-sorted-list (list num)
+  "Add NUM into sorted LIST by side effect."
+  (let* ((top (cons nil list))
+        (prev top))
+    (while (and list (< (car list) num))
+      (setq prev list
+           list (cdr list)))
+    (unless (eq (car list) num)
+      (setcdr prev (cons num list)))
+    (cdr top)))
 
 (provide 'gnus-range)
 
diff --git a/lisp/gnus-registry.el b/lisp/gnus-registry.el
new file mode 100644 (file)
index 0000000..900eeab
--- /dev/null
@@ -0,0 +1,702 @@
+;;; gnus-registry.el --- article registry for Gnus
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Ted Zlatanov <tzz@lifelogs.com>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This is the gnus-registry.el package, works with other backends
+;; besides nnmail.  The major issue is that it doesn't go across
+;; backends, so for instance if an article is in nnml:sys and you see
+;; a reference to it in nnimap splitting, the article will end up in
+;; nnimap:sys
+
+;; gnus-registry.el intercepts article respooling, moving, deleting,
+;; and copying for all backends.  If it doesn't work correctly for
+;; you, submit a bug report and I'll be glad to fix it.  It needs
+;; documentation in the manual (also on my to-do list).
+
+;; Put this in your startup file (~/.gnus.el for instance)
+
+;; (setq gnus-registry-max-entries 2500
+;;       gnus-registry-use-long-group-names t)
+
+;; (gnus-registry-initialize)
+
+;; Then use this in your fancy-split:
+
+;; (: gnus-registry-split-fancy-with-parent)
+
+;; TODO:
+
+;; - get the correct group on spool actions
+
+;; - articles that are spooled to a different backend should be handled
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'gnus)
+(require 'gnus-int)
+(require 'gnus-sum)
+(require 'nnmail)
+
+(defvar gnus-registry-dirty t
+ "Boolean set to t when the registry is modified")
+
+(defgroup gnus-registry nil
+  "The Gnus registry."
+  :group 'gnus)
+
+(defvar gnus-registry-hashtb nil
+  "*The article registry by Message ID.")
+
+(defcustom gnus-registry-unfollowed-groups '("delayed" "drafts" "queue")
+  "List of groups that gnus-registry-split-fancy-with-parent won't follow.
+The group names are matched, they don't have to be fully qualified."
+  :group 'gnus-registry
+  :type '(repeat string))
+
+(defcustom gnus-registry-install nil
+  "Whether the registry should be installed."
+  :group 'gnus-registry
+  :type 'boolean)
+
+(defcustom gnus-registry-clean-empty t
+  "Whether the empty registry entries should be deleted.
+Registry entries are considered empty when they have no groups."
+  :group 'gnus-registry
+  :type 'boolean)
+
+(defcustom gnus-registry-use-long-group-names nil
+  "Whether the registry should use long group names (BUGGY)."
+  :group 'gnus-registry
+  :type 'boolean)
+
+(defcustom gnus-registry-track-extra nil
+  "Whether the registry should track extra data about a message.
+The Subject and Sender (From:) headers are currently tracked this
+way."
+  :group 'gnus-registry
+  :type      
+  '(set :tag "Tracking choices"
+    (const :tag "Track by subject (Subject: header)" subject)
+    (const :tag "Track by sender (From: header)"  sender)))
+
+(defcustom gnus-registry-entry-caching t
+  "Whether the registry should cache extra information."
+  :group 'gnus-registry
+  :type 'boolean)
+
+(defcustom gnus-registry-minimum-subject-length 5
+  "The minimum length of a subject before it's considered trackable."
+  :group 'gnus-registry
+  :type 'integer)
+
+(defcustom gnus-registry-trim-articles-without-groups t
+  "Whether the registry should clean out message IDs without groups."
+  :group 'gnus-registry
+  :type 'boolean)
+
+(defcustom gnus-registry-cache-file "~/.gnus.registry.eld"
+  "File where the Gnus registry will be stored."
+  :group 'gnus-registry
+  :type 'file)
+
+(defcustom gnus-registry-max-entries nil
+  "Maximum number of entries in the registry, nil for unlimited."
+  :group 'gnus-registry
+  :type '(radio (const :format "Unlimited " nil)
+               (integer :format "Maximum number: %v\n" :size 0)))
+
+;; Function(s) missing in Emacs 20
+(when (memq nil (mapcar 'fboundp '(puthash)))
+  (require 'cl)
+  (unless (fboundp 'puthash)
+    ;; alias puthash is missing from Emacs 20 cl-extra.el
+    (defalias 'puthash 'cl-puthash)))
+
+(defun gnus-registry-track-subject-p ()
+  (memq 'subject gnus-registry-track-extra))
+
+(defun gnus-registry-track-sender-p ()
+  (memq 'sender gnus-registry-track-extra))
+
+(defun gnus-registry-cache-read ()
+  "Read the registry cache file."
+  (interactive)
+  (let ((file gnus-registry-cache-file))
+    (when (file-exists-p file)
+      (gnus-message 5 "Reading %s..." file)
+      (gnus-load file)
+      (gnus-message 5 "Reading %s...done" file))))
+
+(defun gnus-registry-cache-save ()
+  "Save the registry cache file."
+  (interactive)
+  (let ((file gnus-registry-cache-file))
+    (save-excursion
+      (set-buffer (gnus-get-buffer-create " *Gnus-registry-cache*"))
+      (make-local-variable 'version-control)
+    (setq version-control gnus-backup-startup-file)
+    (setq buffer-file-name file)
+    (setq default-directory (file-name-directory buffer-file-name))
+    (buffer-disable-undo)
+    (erase-buffer)
+    (gnus-message 5 "Saving %s..." file)
+    (if gnus-save-startup-file-via-temp-buffer
+       (let ((coding-system-for-write gnus-ding-file-coding-system)
+             (standard-output (current-buffer)))
+         (gnus-gnus-to-quick-newsrc-format t "gnus registry startup file" 'gnus-registry-alist)
+         (gnus-registry-cache-whitespace file)
+         (save-buffer))
+      (let ((coding-system-for-write gnus-ding-file-coding-system)
+           (version-control gnus-backup-startup-file)
+           (startup-file file)
+           (working-dir (file-name-directory file))
+           working-file
+           (i -1))
+       ;; Generate the name of a non-existent file.
+       (while (progn (setq working-file
+                           (format
+                            (if (and (eq system-type 'ms-dos)
+                                     (not (gnus-long-file-names)))
+                                "%s#%d.tm#" ; MSDOS limits files to 8+3
+                              (if (memq system-type '(vax-vms axp-vms))
+                                  "%s$tmp$%d"
+                                "%s#tmp#%d"))
+                            working-dir (setq i (1+ i))))
+                     (file-exists-p working-file)))
+       
+       (unwind-protect
+           (progn
+             (gnus-with-output-to-file working-file
+               (gnus-gnus-to-quick-newsrc-format t "gnus registry startup file" 'gnus-registry-alist))
+             
+             ;; These bindings will mislead the current buffer
+             ;; into thinking that it is visiting the startup
+             ;; file.
+             (let ((buffer-backed-up nil)
+                   (buffer-file-name startup-file)
+                   (file-precious-flag t)
+                   (setmodes (file-modes startup-file)))
+               ;; Backup the current version of the startup file.
+               (backup-buffer)
+               
+               ;; Replace the existing startup file with the temp file.
+               (rename-file working-file startup-file t)
+               (set-file-modes startup-file setmodes)))
+         (condition-case nil
+             (delete-file working-file)
+           (file-error nil)))))
+    
+    (gnus-kill-buffer (current-buffer))
+    (gnus-message 5 "Saving %s...done" file))))
+
+;; Idea from Dan Christensen <jdc@chow.mat.jhu.edu>
+;; Save the gnus-registry file with extra line breaks.
+(defun gnus-registry-cache-whitespace (filename)
+  (gnus-message 5 "Adding whitespace to %s" filename)
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward "^(\\|(\\\"" nil t)
+      (replace-match "\n\\&" t))
+    (goto-char (point-min))
+    (while (re-search-forward " $" nil t)
+      (replace-match "" t t))))
+
+(defun gnus-registry-save (&optional force)
+  (when (or gnus-registry-dirty force)
+    (let ((caching gnus-registry-entry-caching))
+      ;; turn off entry caching, so mtime doesn't get recorded
+      (setq gnus-registry-entry-caching nil)
+      ;; remove entry caches
+      (maphash
+       (lambda (key value)
+        (if (hash-table-p value)
+            (remhash key gnus-registry-hashtb)))
+       gnus-registry-hashtb)
+      ;; remove empty entries
+      (when gnus-registry-clean-empty 
+       (gnus-registry-clean-empty-function))
+      ;; now trim the registry appropriately
+      (setq gnus-registry-alist (gnus-registry-trim 
+                                (hashtable-to-alist gnus-registry-hashtb)))
+      ;; really save
+      (gnus-registry-cache-save)
+      (setq gnus-registry-entry-caching caching)
+      (setq gnus-registry-dirty nil))))
+
+(defun gnus-registry-clean-empty-function ()
+  "Remove all empty entries from the registry.  Returns count thereof."
+  (let ((count 0))
+    (maphash
+     (lambda (key value)
+       (unless (gnus-registry-fetch-group key)
+        (incf count)
+        (remhash key gnus-registry-hashtb)))
+     gnus-registry-hashtb)
+    count))
+
+(defun gnus-registry-read ()
+  (gnus-registry-cache-read)
+  (setq gnus-registry-hashtb (alist-to-hashtable gnus-registry-alist))
+  (setq gnus-registry-dirty nil))
+
+(defun gnus-registry-trim (alist)
+  "Trim alist to size, using gnus-registry-max-entries."
+  (if (null gnus-registry-max-entries)
+      alist                            ; just return the alist
+    ;; else, when given max-entries, trim the alist
+    (let ((timehash (make-hash-table                       
+                    :size 4096
+                    :test 'equal)))
+      (maphash
+       (lambda (key value)
+        (puthash key (gnus-registry-fetch-extra key 'mtime) timehash))
+       gnus-registry-hashtb)
+
+      ;; we use the return value of this setq, which is the trimmed alist
+      (setq alist
+           (nthcdr
+            (- (length alist) gnus-registry-max-entries)
+            (sort alist 
+                  (lambda (a b)
+                    (time-less-p 
+                     (cdr (gethash (car a) timehash))
+                     (cdr (gethash (car b) timehash))))))))))
+
+(defun alist-to-hashtable (alist)
+  "Build a hashtable from the values in ALIST."
+  (let ((ht (make-hash-table                       
+            :size 4096
+            :test 'equal)))
+    (mapc
+     (lambda (kv-pair)
+       (puthash (car kv-pair) (cdr kv-pair) ht))
+     alist)
+     ht))
+
+(defun hashtable-to-alist (hash)
+  "Build an alist from the values in HASH."
+  (let ((list nil))
+    (maphash
+     (lambda (key value)
+       (setq list (cons (cons key value) list)))
+     hash)
+    list))
+
+(defun gnus-registry-action (action data-header from &optional to method)
+  (let* ((id (mail-header-id data-header))
+        (subject (gnus-registry-simplify-subject 
+                  (mail-header-subject data-header)))
+        (sender (mail-header-from data-header))
+        (from (gnus-group-guess-full-name-from-command-method from))
+        (to (if to (gnus-group-guess-full-name-from-command-method to) nil))
+        (to-name (if to to "the Bit Bucket"))
+        (old-entry (gethash id gnus-registry-hashtb)))
+    (gnus-message 5 "Registry: article %s %s from %s to %s"
+                 id
+                 (if method "respooling" "going")
+                 from
+                 to)
+
+    ;; All except copy will need a delete
+    (gnus-registry-delete-group id from)
+
+    (when (equal 'copy action) 
+      (gnus-registry-add-group id from subject sender)) ; undo the delete
+
+    (gnus-registry-add-group id to subject sender)))
+
+(defun gnus-registry-spool-action (id group &optional subject sender)
+  (let ((group (gnus-group-guess-full-name-from-command-method group)))
+    (when (and (stringp id) (string-match "\r$" id))
+      (setq id (substring id 0 -1)))
+    (gnus-message 5 "Registry: article %s spooled to %s"
+                 id
+                 group)
+    (gnus-registry-add-group id group subject sender)))
+
+;; Function for nn{mail|imap}-split-fancy: look up all references in
+;; the cache and if a match is found, return that group.
+(defun gnus-registry-split-fancy-with-parent ()
+  "Split this message into the same group as its parent.  The parent
+is obtained from the registry.  This function can be used as an entry
+in `nnmail-split-fancy' or `nnimap-split-fancy', for example like
+this: (: gnus-registry-split-fancy-with-parent) 
+
+For a message to be split, it looks for the parent message in the
+References or In-Reply-To header and then looks in the registry to
+see which group that message was put in.  This group is returned.
+
+See the Info node `(gnus)Fancy Mail Splitting' for more details."
+  (let ((refstr (or (message-fetch-field "references")
+                   (message-fetch-field "in-reply-to")))
+       (nnmail-split-fancy-with-parent-ignore-groups
+        (if (listp nnmail-split-fancy-with-parent-ignore-groups)
+            nnmail-split-fancy-with-parent-ignore-groups
+          (list nnmail-split-fancy-with-parent-ignore-groups)))
+       references res)
+    (if refstr
+       (progn
+         (setq references (nreverse (gnus-split-references refstr)))
+         (mapcar (lambda (x)
+                   (setq res (or (gnus-registry-fetch-group x) res))
+                   (when (or (gnus-registry-grep-in-list
+                              res
+                              gnus-registry-unfollowed-groups)
+                             (gnus-registry-grep-in-list 
+                              res
+                              nnmail-split-fancy-with-parent-ignore-groups))
+                     (setq res nil)))
+                 references))
+
+      ;; else: there were no references, now try the extra tracking
+      (let ((sender (message-fetch-field "from"))
+           (subject (gnus-registry-simplify-subject
+                     (message-fetch-field "subject")))
+           (single-match t))
+       (when (and single-match
+                  (gnus-registry-track-sender-p)
+                  sender)
+         (maphash
+          (lambda (key value)
+            (let ((this-sender (cdr 
+                                (gnus-registry-fetch-extra key 'sender))))
+              (when (and single-match
+                         this-sender
+                         (equal sender this-sender))
+                ;; too many matches, bail
+                (unless (equal res (gnus-registry-fetch-group key))
+                  (setq single-match nil))
+                (setq res (gnus-registry-fetch-group key))
+                (gnus-message
+                 ;; raise level of messaging if gnus-registry-track-extra
+                 (if gnus-registry-track-extra 5 9)
+                 "%s (extra tracking) traced sender %s to group %s"
+                 "gnus-registry-split-fancy-with-parent"
+                 sender
+                 (if res res "nil")))))
+          gnus-registry-hashtb))
+       (when (and single-match
+                  (gnus-registry-track-subject-p)
+                  subject
+                  (< gnus-registry-minimum-subject-length (length subject)))
+         (maphash
+          (lambda (key value)
+            (let ((this-subject (cdr 
+                                 (gnus-registry-fetch-extra key 'subject))))
+              (when (and single-match
+                         this-subject
+                         (equal subject this-subject))
+                ;; too many matches, bail
+                (unless (equal res (gnus-registry-fetch-group key))
+                  (setq single-match nil))
+                (setq res (gnus-registry-fetch-group key))
+                (gnus-message
+                 ;; raise level of messaging if gnus-registry-track-extra
+                 (if gnus-registry-track-extra 5 9)
+                 "%s (extra tracking) traced subject %s to group %s"
+                 "gnus-registry-split-fancy-with-parent"
+                 subject
+                 (if res res "nil")))))
+          gnus-registry-hashtb))
+       (unless single-match
+         (gnus-message
+          5
+          "gnus-registry-split-fancy-with-parent: too many extra matches for %s"
+          refstr)
+         (setq res nil))))
+    (gnus-message
+     5 
+     "gnus-registry-split-fancy-with-parent traced %s to group %s"
+     refstr (if res res "nil"))
+
+    (when (and res gnus-registry-use-long-group-names)
+      (let ((m1 (gnus-find-method-for-group res))
+           (m2 (or gnus-command-method 
+                   (gnus-find-method-for-group gnus-newsgroup-name)))
+           (short-res (gnus-group-short-name res)))
+      (if (gnus-methods-equal-p m1 m2)
+         (progn
+           (gnus-message
+            9 
+            "gnus-registry-split-fancy-with-parent stripped group %s to %s"
+            res
+            short-res)
+           (setq res short-res))
+       ;; else...
+       (gnus-message
+        5 
+        "gnus-registry-split-fancy-with-parent ignored foreign group %s"
+        res)
+       (setq res nil))))
+    res))
+
+(defun gnus-registry-register-message-ids ()
+  "Register the Message-ID of every article in the group"
+  (unless (gnus-parameter-registry-ignore gnus-newsgroup-name)
+    (dolist (article gnus-newsgroup-articles)
+      (let ((id (gnus-registry-fetch-message-id-fast article)))
+       (unless (gnus-registry-fetch-group id)
+         (gnus-message 9 "Registry: Registering article %d with group %s" 
+                       article gnus-newsgroup-name)
+         (gnus-registry-add-group 
+          (gnus-registry-fetch-message-id-fast article)
+          gnus-newsgroup-name
+          (gnus-registry-fetch-simplified-message-subject-fast article)
+          (gnus-registry-fetch-sender-fast article)))))))
+
+(defun gnus-registry-fetch-message-id-fast (article)
+  "Fetch the Message-ID quickly, using the internal gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (mail-header-id (gnus-data-header (assoc article (gnus-data-list nil))))
+    nil))
+
+(defun gnus-registry-simplify-subject (subject)
+  (if (stringp subject)
+      (gnus-simplify-subject subject)
+    nil))
+
+(defun gnus-registry-fetch-simplified-message-subject-fast (article)
+  "Fetch the Subject quickly, using the internal gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (gnus-registry-simplify-subject
+       (mail-header-subject (gnus-data-header
+                            (assoc article (gnus-data-list nil)))))
+    nil))
+
+(defun gnus-registry-fetch-sender-fast (article)
+  "Fetch the Sender quickly, using the internal gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (mail-header-from (gnus-data-header
+                        (assoc article (gnus-data-list nil))))
+    nil))
+
+(defun gnus-registry-grep-in-list (word list)
+  (when word
+    (memq nil
+         (mapcar 'not
+                 (mapcar 
+                  (lambda (x)
+                    (string-match x word))
+                  list)))))
+
+(defun gnus-registry-fetch-extra (id &optional entry)
+  "Get the extra data of a message, based on the message ID.
+Returns the first place where the trail finds a nonstring."
+  (let ((entry-cache (gethash entry gnus-registry-hashtb)))
+    (if (and entry
+            (hash-table-p entry-cache)
+            (gethash id entry-cache))
+       (gethash id entry-cache)
+      ;; else, if there is no caching possible...
+      (let ((trail (gethash id gnus-registry-hashtb)))
+       (when (listp trail)
+         (dolist (crumb trail)
+           (unless (stringp crumb)
+             (return (gnus-registry-fetch-extra-entry crumb entry id)))))))))
+
+(defun gnus-registry-fetch-extra-entry (alist &optional entry id)
+  "Get the extra data of a message, or a specific entry in it.
+Update the entry cache if needed."
+  (if (and entry id)
+      (let ((entry-cache (gethash entry gnus-registry-hashtb))
+           entree)
+       (when gnus-registry-entry-caching
+         ;; create the hash table
+         (unless (hash-table-p entry-cache)
+           (setq entry-cache (make-hash-table
+                              :size 4096
+                              :test 'equal))
+           (puthash entry entry-cache gnus-registry-hashtb))
+
+         ;; get the entree from the hash table or from the alist
+         (setq entree (gethash id entry-cache)))
+       
+       (unless entree
+         (setq entree (assq entry alist))
+         (when gnus-registry-entry-caching
+           (puthash id entree entry-cache)))
+       entree)
+    alist))
+
+(defun gnus-registry-store-extra (id extra)
+  "Store the extra data of a message, based on the message ID.
+The message must have at least one group name."
+  (when (gnus-registry-group-count id)
+    ;; we now know the trail has at least 1 group name, so it's not empty
+    (let ((trail (gethash id gnus-registry-hashtb))
+         (old-extra (gnus-registry-fetch-extra id))
+         entry-cache)
+      (dolist (crumb trail)
+       (unless (stringp crumb)
+         (dolist (entry crumb)
+           (setq entry-cache (gethash (car entry) gnus-registry-hashtb))
+         (when entry-cache
+           (remhash id entry-cache))))
+      (puthash id (cons extra (delete old-extra trail))
+              gnus-registry-hashtb)
+      (setq gnus-registry-dirty t)))))
+
+(defun gnus-registry-store-extra-entry (id key value)
+  "Put a specific entry in the extras field of the registry entry for id."
+  (let* ((extra (gnus-registry-fetch-extra id))
+        (alist (cons (cons key value)
+                (gnus-assq-delete-all key (gnus-registry-fetch-extra id)))))
+    (gnus-registry-store-extra id alist)))
+
+(defun gnus-registry-fetch-group (id)
+  "Get the group of a message, based on the message ID.
+Returns the first place where the trail finds a group name."
+  (when (gnus-registry-group-count id)
+    ;; we now know the trail has at least 1 group name
+    (let ((trail (gethash id gnus-registry-hashtb)))
+      (dolist (crumb trail)
+       (when (stringp crumb)
+         (return (if gnus-registry-use-long-group-names 
+                      crumb 
+                    (gnus-group-short-name crumb))))))))
+
+(defun gnus-registry-group-count (id)
+  "Get the number of groups of a message, based on the message ID."
+  (let ((trail (gethash id gnus-registry-hashtb)))
+    (if (and trail (listp trail))
+       (apply '+ (mapcar (lambda (x) (if (stringp x) 1 0)) trail))
+      0)))
+
+(defun gnus-registry-delete-group (id group)
+  "Delete a group for a message, based on the message ID."
+  (when group
+    (when id
+      (let ((trail (gethash id gnus-registry-hashtb))
+           (group (gnus-group-short-name group)))
+       (puthash id (if trail
+                       (delete group trail)
+                     nil)
+                gnus-registry-hashtb))
+      ;; now, clear the entry if there are no more groups
+      (when gnus-registry-trim-articles-without-groups
+       (unless (gnus-registry-group-count id)
+         (gnus-registry-delete-id id)))
+      (gnus-registry-store-extra-entry id 'mtime (current-time)))))
+
+(defun gnus-registry-delete-id (id)
+  "Delete a message ID from the registry."
+  (when (stringp id)
+    (remhash id gnus-registry-hashtb)
+    (maphash
+     (lambda (key value)
+       (when (hash-table-p value)
+        (remhash id value)))
+     gnus-registry-hashtb)))
+
+(defun gnus-registry-add-group (id group &optional subject sender)
+  "Add a group for a message, based on the message ID."
+  (when group
+    (when (and id
+              (not (string-match "totally-fudged-out-message-id" id)))
+      (let ((full-group group)
+           (group (if gnus-registry-use-long-group-names 
+                      group 
+                    (gnus-group-short-name group))))
+       (gnus-registry-delete-group id group)
+
+       (unless gnus-registry-use-long-group-names ;; unnecessary in this case
+         (gnus-registry-delete-group id full-group))
+
+       (let ((trail (gethash id gnus-registry-hashtb)))
+         (puthash id (if trail
+                         (cons group trail)
+                       (list group))
+                  gnus-registry-hashtb)
+
+         (when (and (gnus-registry-track-subject-p)
+                    subject)
+           (gnus-registry-store-extra-entry
+            id 
+            'subject 
+            (gnus-registry-simplify-subject subject)))
+         (when (and (gnus-registry-track-sender-p)
+                    sender)
+           (gnus-registry-store-extra-entry
+            id 
+            'sender
+            sender))
+         
+         (gnus-registry-store-extra-entry id 'mtime (current-time)))))))
+
+(defun gnus-registry-clear ()
+  "Clear the Gnus registry."
+  (interactive)
+  (setq gnus-registry-alist nil)
+  (setq gnus-registry-hashtb (alist-to-hashtable gnus-registry-alist))
+  (setq gnus-registry-dirty t))
+
+;;;###autoload
+(defun gnus-registry-initialize ()
+  (interactive)
+  (setq gnus-registry-install t)
+  (gnus-registry-install-hooks)
+  (gnus-registry-read))
+
+;;;###autoload
+(defun gnus-registry-install-hooks ()
+  "Install the registry hooks."
+  (interactive)
+  (add-hook 'gnus-summary-article-move-hook 'gnus-registry-action) 
+  (add-hook 'gnus-summary-article-delete-hook 'gnus-registry-action)
+  (add-hook 'gnus-summary-article-expire-hook 'gnus-registry-action)
+  (add-hook 'nnmail-spool-hook 'gnus-registry-spool-action)
+  
+  (add-hook 'gnus-save-newsrc-hook 'gnus-registry-save)
+  (add-hook 'gnus-read-newsrc-el-hook 'gnus-registry-read)
+
+  (add-hook 'gnus-summary-prepare-hook 'gnus-registry-register-message-ids))
+
+(defun gnus-registry-unload-hook ()
+  "Uninstall the registry hooks."
+  (interactive)
+  (remove-hook 'gnus-summary-article-move-hook 'gnus-registry-action) 
+  (remove-hook 'gnus-summary-article-delete-hook 'gnus-registry-action)
+  (remove-hook 'gnus-summary-article-expire-hook 'gnus-registry-action)
+  (remove-hook 'nnmail-spool-hook 'gnus-registry-spool-action)
+  
+  (remove-hook 'gnus-save-newsrc-hook 'gnus-registry-save)
+  (remove-hook 'gnus-read-newsrc-el-hook 'gnus-registry-read)
+
+  (remove-hook 'gnus-summary-prepare-hook 'gnus-registry-register-message-ids))
+
+(when gnus-registry-install
+  (gnus-registry-install-hooks)
+  (gnus-registry-read))
+
+;; TODO: a lot of things
+
+(provide 'gnus-registry)
+
+;;; gnus-registry.el ends here
index bbd3cf5..3727a4f 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-salt.el --- alternate summary mode interfaces for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2001
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 (require 'gnus)
 (require 'gnus-sum)
+(require 'gnus-win)
 
 ;;;
 ;;; gnus-pick-mode
 ;;;
 
 (defvar gnus-pick-mode nil
-  "Minor mode for providing a pick-and-read interface in Gnus summary buffers.")
+  "Minor mode for providing a pick-and-read interface in Gnus
+summary buffers.")
 
 (defcustom gnus-pick-display-summary nil
   "*Display summary while reading."
   :type 'hook
   :group 'gnus-summary-pick)
 
+(when (featurep 'xemacs)
+  (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add))
+
 (defcustom gnus-mark-unpicked-articles-as-read nil
   "*If non-nil, mark all unpicked articles as read."
   :type 'boolean
   :group 'gnus-summary-pick)
 
 (defcustom gnus-pick-elegant-flow t
-  "If non-nil, gnus-pick-start-reading will run gnus-summary-next-group when no articles have been picked."
+  "If non-nil, `gnus-pick-start-reading' runs
+ `gnus-summary-next-group' when no articles have been picked."
   :type 'boolean
   :group 'gnus-summary-pick)
 
 (defcustom gnus-summary-pick-line-format
-  "-5P %U\%R\%z\%I\%(%[%4L: %-20,20n%]%) %s\n"
+  "%-5P %U\%R\%z\%I\%(%[%4L: %-23,23n%]%) %s\n"
   "*The format specification of the lines in pick buffers.
 It accepts the same format specs that `gnus-summary-line-format' does."
   :type 'string
@@ -72,22 +80,10 @@ It accepts the same format specs that `gnus-summary-line-format' does."
   (setq gnus-pick-mode-map (make-sparse-keymap))
 
   (gnus-define-keys gnus-pick-mode-map
-    "t" gnus-uu-mark-thread
-    "T" gnus-uu-unmark-thread
     " " gnus-pick-next-page
-    "u" gnus-summary-unmark-as-processable
-    "U" gnus-summary-unmark-all-processable
-    "v" gnus-uu-mark-over
-    "r" gnus-uu-mark-region
-    "R" gnus-uu-unmark-region
-    "e" gnus-uu-mark-by-regexp
-    "E" gnus-uu-mark-by-regexp
-    "b" gnus-uu-mark-buffer
-    "B" gnus-uu-unmark-buffer
-    "." gnus-pick-article
+    "u" gnus-pick-unmark-article-or-thread
+    "." gnus-pick-article-or-thread
     gnus-down-mouse-2 gnus-pick-mouse-pick-region
-    ;;gnus-mouse-2 gnus-pick-mouse-pick
-    "X" gnus-pick-start-reading
     "\r" gnus-pick-start-reading))
 
 (defun gnus-pick-make-menu-bar ()
@@ -99,14 +95,14 @@ It accepts the same format specs that `gnus-summary-line-format' does."
        ["Article" gnus-summary-mark-as-processable t]
        ["Thread" gnus-uu-mark-thread t]
        ["Region" gnus-uu-mark-region t]
-       ["Regexp" gnus-uu-mark-regexp t]
+       ["Regexp" gnus-uu-mark-by-regexp t]
        ["Buffer" gnus-uu-mark-buffer t])
        ("Unpick"
        ["Article" gnus-summary-unmark-as-processable t]
        ["Thread" gnus-uu-unmark-thread t]
        ["Region" gnus-uu-unmark-region t]
-       ["Regexp" gnus-uu-unmark-regexp t]
-       ["Buffer" gnus-uu-unmark-buffer t])
+       ["Regexp" gnus-uu-unmark-by-regexp t]
+       ["Buffer" gnus-summary-unmark-all-processable t])
        ["Start reading" gnus-pick-start-reading t]
        ["Switch pick mode off" gnus-pick-mode gnus-pick-mode]))))
 
@@ -132,7 +128,8 @@ It accepts the same format specs that `gnus-summary-line-format' does."
       ;; Set up the menu.
       (when (gnus-visual-p 'pick-menu 'menu)
        (gnus-pick-make-menu-bar))
-      (gnus-add-minor-mode 'gnus-pick-mode " Pick" gnus-pick-mode-map)
+      (gnus-add-minor-mode 'gnus-pick-mode " Pick" gnus-pick-mode-map
+                          nil 'gnus-pick-mode)
       (gnus-run-hooks 'gnus-pick-mode-hook))))
 
 (defun gnus-pick-setup-message ()
@@ -142,7 +139,8 @@ It accepts the same format specs that `gnus-summary-line-format' does."
               (set-buffer gnus-summary-buffer)
               gnus-pick-mode))
     (message-add-action
-     '(gnus-configure-windows 'pick t) 'send 'exit 'postpone 'kill)))
+     '(gnus-configure-windows ,gnus-current-window-configuration t)
+     'send 'exit 'postpone 'kill)))
 
 (defvar gnus-pick-line-number 1)
 (defun gnus-pick-line-number ()
@@ -157,11 +155,11 @@ If given a prefix, mark all unpicked articles as read."
   (interactive "P")
   (if gnus-newsgroup-processable
       (progn
-        (gnus-summary-limit-to-articles nil)
-        (when (or catch-up gnus-mark-unpicked-articles-as-read)
+       (gnus-summary-limit-to-articles nil)
+       (when (or catch-up gnus-mark-unpicked-articles-as-read)
          (gnus-summary-limit-mark-excluded-as-read))
-        (gnus-summary-first-article)
-        (gnus-configure-windows
+       (gnus-summary-first-article)
+       (gnus-configure-windows
         (if gnus-pick-display-summary 'article 'pick) t))
     (if gnus-pick-elegant-flow
        (progn
@@ -172,21 +170,52 @@ If given a prefix, mark all unpicked articles as read."
            (gnus-summary-next-group)))
       (error "No articles have been picked"))))
 
+(defun gnus-pick-goto-article (arg)
+  "Go to the article number indicated by ARG.
+If ARG is an invalid article number, then stay on current line."
+  (let (pos)
+    (save-excursion
+      (goto-char (point-min))
+      (when (zerop (forward-line (1- (prefix-numeric-value arg))))
+       (setq pos (point))))
+    (if (not pos)
+       (gnus-error 2 "No such line: %s" arg)
+      (goto-char pos))))
+
 (defun gnus-pick-article (&optional arg)
   "Pick the article on the current line.
 If ARG, pick the article on that line instead."
   (interactive "P")
   (when arg
-    (let (pos)
-      (save-excursion
-       (goto-char (point-min))
-       (when (zerop (forward-line (1- (prefix-numeric-value arg))))
-         (setq pos (point))))
-      (if (not pos)
-         (gnus-error 2 "No such line: %s" arg)
-       (goto-char pos))))
+    (gnus-pick-goto-article arg))
   (gnus-summary-mark-as-processable 1))
 
+(defun gnus-pick-article-or-thread (&optional arg)
+  "If `gnus-thread-hide-subtree' is t, then pick the thread on the current line.
+Otherwise pick the article on the current line.
+If ARG, pick the article/thread on that line instead."
+  (interactive "P")
+  (when arg
+    (gnus-pick-goto-article arg))
+  (if gnus-thread-hide-subtree
+      (progn
+       (save-excursion
+         (gnus-uu-mark-thread))
+       (forward-line 1))
+    (gnus-summary-mark-as-processable 1)))
+
+(defun gnus-pick-unmark-article-or-thread (&optional arg)
+  "If `gnus-thread-hide-subtree' is t, then unmark the thread on current line.
+Otherwise unmark the article on current line.
+If ARG, unmark thread/article on that line instead."
+  (interactive "P")
+  (when arg
+    (gnus-pick-goto-article arg))
+  (if gnus-thread-hide-subtree
+      (save-excursion
+       (gnus-uu-unmark-thread))
+    (gnus-summary-unmark-as-processable 1)))
+
 (defun gnus-pick-mouse-pick (e)
   (interactive "e")
   (mouse-set-point e)
@@ -201,9 +230,8 @@ This must be bound to a button-down mouse event."
   (let* ((echo-keystrokes 0)
         (start-posn (event-start start-event))
         (start-point (posn-point start-posn))
-         (start-line (1+ (count-lines 1 start-point)))
+        (start-line (1+ (count-lines 1 start-point)))
         (start-window (posn-window start-posn))
-        (start-frame (window-frame start-window))
         (bounds (gnus-window-edges start-window))
         (top (nth 1 bounds))
         (bottom (if (window-minibuffer-p start-window)
@@ -223,18 +251,16 @@ This must be bound to a button-down mouse event."
     ;; end-of-range is used only in the single-click case.
     ;; It is the place where the drag has reached so far
     ;; (but not outside the window where the drag started).
-    (let (event end end-point last-end-point (end-of-range (point)))
+    (let (event end end-point (end-of-range (point)))
       (track-mouse
        (while (progn
-               (setq event (read-event))
+               (setq event (cdr (gnus-read-event-char)))
                (or (mouse-movement-p event)
                    (eq (car-safe event) 'switch-frame)))
         (if (eq (car-safe event) 'switch-frame)
             nil
           (setq end (event-end event)
                 end-point (posn-point end))
-          (when end-point
-            (setq last-end-point end-point))
 
           (cond
            ;; Are we moving within the original window?
@@ -308,8 +334,8 @@ This must be bound to a button-down mouse event."
   (setq gnus-binary-mode-map (make-sparse-keymap))
 
   (gnus-define-keys
-   gnus-binary-mode-map
-   "g" gnus-binary-show-article))
+      gnus-binary-mode-map
+    "g" gnus-binary-show-article))
 
 (defun gnus-binary-make-menu-bar ()
   (unless (boundp 'gnus-binary-menu)
@@ -335,13 +361,14 @@ This must be bound to a button-down mouse event."
       ;; Set up the menu.
       (when (gnus-visual-p 'binary-menu 'menu)
        (gnus-binary-make-menu-bar))
-      (gnus-add-minor-mode 'gnus-binary-mode " Binary" gnus-binary-mode-map)
+      (gnus-add-minor-mode 'gnus-binary-mode " Binary"
+                          gnus-binary-mode-map nil 'gnus-binary-mode)
       (gnus-run-hooks 'gnus-binary-mode-hook))))
 
 (defun gnus-binary-display-article (article &optional all-header)
   "Run ARTICLE through the binary decode functions."
   (when (gnus-summary-goto-subject article)
-    (let ((gnus-view-pseudos 'automatic))
+    (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
       (gnus-uu-decode-uu))))
 
 (defun gnus-binary-show-article (&optional arg)
@@ -363,7 +390,8 @@ This must be bound to a button-down mouse event."
   "If non-nil, minimize the tree buffer window.
 If a number, never let the tree buffer grow taller than that number of
 lines."
-  :type 'boolean
+  :type '(choice boolean
+                integer)
   :group 'gnus-summary-tree)
 
 (defcustom gnus-selected-tree-face 'modeline
@@ -397,6 +425,11 @@ Two predefined functions are available:
   :type 'hook
   :group 'gnus-summary-tree)
 
+(when (featurep 'xemacs)
+  (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
+  (add-hook 'gnus-tree-mode-hook 'gnus-xmas-switch-horizontal-scrollbar-off))
+
+
 ;;; Internal variables.
 
 (defvar gnus-tree-line-format-alist
@@ -416,6 +449,7 @@ Two predefined functions are available:
 (defvar gnus-selected-tree-overlay nil)
 
 (defvar gnus-tree-displayed-thread nil)
+(defvar gnus-tree-inhibit nil)
 
 (defvar gnus-tree-mode-map nil)
 (put 'gnus-tree-mode 'mode-class 'special)
@@ -424,13 +458,13 @@ Two predefined functions are available:
   (setq gnus-tree-mode-map (make-keymap))
   (suppress-keymap gnus-tree-mode-map)
   (gnus-define-keys
-   gnus-tree-mode-map
-   "\r" gnus-tree-select-article
-   gnus-mouse-2 gnus-tree-pick-article
-   "\C-?" gnus-tree-read-summary-keys
-   "h" gnus-tree-show-summary
+      gnus-tree-mode-map
+    "\r" gnus-tree-select-article
+    gnus-mouse-2 gnus-tree-pick-article
+    "\C-?" gnus-tree-read-summary-keys
+    "h" gnus-tree-show-summary
 
-   "\C-c\C-i" gnus-info-find-node)
+    "\C-c\C-i" gnus-info-find-node)
 
   (substitute-key-definition
    'undefined 'gnus-tree-read-summary-keys gnus-tree-mode-map))
@@ -454,7 +488,7 @@ Two predefined functions are available:
   (setq mode-name "Tree")
   (setq major-mode 'gnus-tree-mode)
   (use-local-map gnus-tree-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq buffer-read-only t)
   (setq truncate-lines t)
   (save-excursion
@@ -466,14 +500,17 @@ Two predefined functions are available:
 (defun gnus-tree-read-summary-keys (&optional arg)
   "Read a summary buffer key sequence and execute it."
   (interactive "P")
-  (let ((buf (current-buffer))
-       win)
-    (gnus-article-read-summary-keys arg nil t)
-    (when (setq win (get-buffer-window buf))
-      (select-window win)
-      (when gnus-selected-tree-overlay
-       (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
-      (gnus-tree-minimize))))
+  (unless gnus-tree-inhibit
+    (let ((buf (current-buffer))
+         (gnus-tree-inhibit t)
+         win)
+      (set-buffer gnus-article-buffer)
+      (gnus-article-read-summary-keys arg nil t)
+      (when (setq win (get-buffer-window buf))
+       (select-window win)
+       (when gnus-selected-tree-overlay
+         (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
+       (gnus-tree-minimize)))))
 
 (defun gnus-tree-show-summary ()
   "Reconfigure windows to show summary buffer."
@@ -504,19 +541,21 @@ Two predefined functions are available:
 
 (defun gnus-tree-article-region (article)
   "Return a cons with BEG and END of the article region."
-  (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
+  (let ((pos (text-property-any
+             (point-min) (point-max) 'gnus-number article)))
     (when pos
       (cons pos (next-single-property-change pos 'gnus-number)))))
 
 (defun gnus-tree-goto-article (article)
-  (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
+  (let ((pos (text-property-any
+             (point-min) (point-max) 'gnus-number article)))
     (when pos
       (goto-char pos))))
 
 (defun gnus-tree-recenter ()
   "Center point in the tree window."
   (let ((selected (selected-window))
-       (tree-window (get-buffer-window gnus-tree-buffer t)))
+       (tree-window (gnus-get-buffer-window gnus-tree-buffer t)))
     (when tree-window
       (select-window tree-window)
       (when gnus-selected-tree-overlay
@@ -539,9 +578,8 @@ Two predefined functions are available:
 (defun gnus-get-tree-buffer ()
   "Return the tree buffer properly initialized."
   (save-excursion
-    (set-buffer (get-buffer-create gnus-tree-buffer))
+    (set-buffer (gnus-get-buffer-create gnus-tree-buffer))
     (unless (eq major-mode 'gnus-tree-mode)
-      (gnus-add-current-to-buffer-list)
       (gnus-tree-mode))
     (current-buffer)))
 
@@ -630,13 +668,17 @@ Two predefined functions are available:
       (let* ((score (or (cdr (assq article gnus-newsgroup-scored))
                        gnus-summary-default-score 0))
             (default gnus-summary-default-score)
+            (default-high gnus-summary-default-high-score)
+            (default-low gnus-summary-default-low-score)
+             (uncached (memq article gnus-newsgroup-undownloaded))
+             (downloaded (not uncached))
             (mark (or (gnus-summary-article-mark article) gnus-unread-mark)))
        ;; Eval the cars of the lists until we find a match.
        (while (and list
                    (not (eval (caar list))))
          (setq list (cdr list)))))
     (unless (eq (setq face (cdar list)) (get-text-property beg 'face))
-      (gnus-put-text-property
+      (gnus-put-text-property-excluding-characters-with-faces
        beg end 'face
        (if (boundp face) (symbol-value face) face)))))
 
@@ -660,8 +702,8 @@ Two predefined functions are available:
       (gnus-tree-minimize)
       (gnus-tree-recenter)
       (let ((selected (selected-window)))
-       (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
-         (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
+       (when (gnus-get-buffer-window (set-buffer gnus-tree-buffer) t)
+         (select-window (gnus-get-buffer-window (set-buffer gnus-tree-buffer) t))
          (gnus-horizontal-recenter)
          (select-window selected))))))
 
@@ -688,7 +730,7 @@ Two predefined functions are available:
          (while (progn
                   (forward-line -1)
                   (forward-char col)
-                  (= (following-char) ? ))
+                  (eq (char-after) ? ))
            (delete-char 1)
            (insert (caddr gnus-tree-parent-child-edges)))
          (goto-char beg)))
@@ -745,7 +787,8 @@ Two predefined functions are available:
          (setq beg (point))
          (forward-char -1)
          ;; Draw "-" lines leftwards.
-         (while (= (char-after (1- (point))) ? )
+         (while (and (> (point) 1)
+                     (eq (char-after (1- (point))) ? ))
            (delete-char -1)
            (insert (car gnus-tree-parent-child-edges))
            (forward-char -1))
@@ -798,6 +841,13 @@ Two predefined functions are available:
 (defun gnus-tree-close (group)
   (gnus-kill-buffer gnus-tree-buffer))
 
+(defun gnus-tree-perhaps-minimize ()
+  (when (and gnus-tree-minimize-window
+            (get-buffer gnus-tree-buffer))
+    (save-excursion
+      (set-buffer gnus-tree-buffer)
+      (gnus-tree-minimize))))
+
 (defun gnus-highlight-selected-tree (article)
   "Highlight the selected article in the tree."
   (let ((buf (current-buffer))
@@ -816,8 +866,8 @@ Two predefined functions are available:
       (gnus-tree-minimize)
       (gnus-tree-recenter)
       (let ((selected (selected-window)))
-       (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
-         (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
+       (when (gnus-get-buffer-window (set-buffer gnus-tree-buffer) t)
+         (select-window (gnus-get-buffer-window (set-buffer gnus-tree-buffer) t))
          (gnus-horizontal-recenter)
          (select-window selected))))
     ;; If we remove this save-excursion, it updates the wrong mode lines?!?
@@ -833,7 +883,7 @@ Two predefined functions are available:
       (when (setq region (gnus-tree-article-region article))
        (gnus-put-text-property (car region) (cdr region) 'face face)
        (set-window-point
-        (get-buffer-window (current-buffer) t) (cdr region))))))
+        (gnus-get-buffer-window (current-buffer) t) (cdr region))))))
 
 ;;;
 ;;; gnus-carpal
@@ -859,6 +909,7 @@ Two predefined functions are available:
     ("matching" . gnus-group-list-matching)
     ("post" . gnus-group-post-news)
     ("mail" . gnus-group-mail)
+    ("local" . (lambda () (interactive) (gnus-group-news 0)))
     ("rescan" . gnus-group-get-new-news)
     ("browse-foreign" . gnus-group-browse-foreign)
     ("exit" . gnus-group-exit)))
@@ -889,7 +940,8 @@ Two predefined functions are available:
     ("kill" . gnus-summary-kill-thread)
     "post"
     ("post" . gnus-summary-post-news)
-    ("mail" . gnus-summary-mail)
+    ("local" . gnus-summary-news-other-window)
+    ("mail" . gnus-summary-mail-other-window)
     ("followup" . gnus-summary-followup-with-original)
     ("reply" . gnus-summary-reply-with-original)
     ("cancel" . gnus-summary-cancel-article)
@@ -952,7 +1004,7 @@ The following commands are available:
   (setq mode-name "Gnus Carpal")
   (setq mode-line-process nil)
   (use-local-map gnus-carpal-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq buffer-read-only t)
   (make-local-variable 'gnus-carpal-attached-buffer)
   (gnus-run-hooks 'gnus-carpal-mode-hook))
@@ -962,11 +1014,10 @@ The following commands are available:
     (if (get-buffer buffer)
        ()
       (save-excursion
-       (set-buffer (get-buffer-create buffer))
+       (set-buffer (gnus-get-buffer-create buffer))
        (gnus-carpal-mode)
        (setq gnus-carpal-attached-buffer
              (intern (format "gnus-%s-buffer" type)))
-       (gnus-add-current-to-buffer-list)
        (let ((buttons (symbol-value
                        (intern (format "gnus-carpal-%s-buffer-buttons"
                                        type))))
index 48709b7..d9015b6 100644 (file)
@@ -1,8 +1,9 @@
 ;;; gnus-score.el --- scoring code for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <amanda@iesd.auc.dk>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
 
 (require 'gnus)
 (require 'gnus-sum)
 (require 'gnus-range)
+(require 'gnus-win)
 (require 'message)
+(require 'score-mode)
+
+(autoload 'ffap-string-at-point "ffap")
 
 (defcustom gnus-global-score-files nil
   "List of global score files and directories.
@@ -45,7 +51,7 @@ score files in the \"/ftp.some-where:/pub/score\" directory.
 
  (setq gnus-global-score-files
        '(\"/ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE\"
-         \"/ftp.some-where:/pub/score\"))"
+        \"/ftp.some-where:/pub/score\"))"
   :group 'gnus-score-files
   :type '(repeat file))
 
@@ -57,10 +63,10 @@ Each element of this alist should be of the form
 If the name of a group is matched by REGEXP, the corresponding scorefiles
 will be used for that group.
 The first match found is used, subsequent matching entries are ignored (to
-use multiple matches, see gnus-score-file-multiple-match-alist).
+use multiple matches, see `gnus-score-file-multiple-match-alist').
 
 These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see)."
+`gnus-score-find-score-files-function'."
   :group 'gnus-score-files
   :type '(repeat (cons regexp (repeat file))))
 
@@ -73,10 +79,10 @@ If the name of a group is matched by REGEXP, the corresponding scorefiles
 will be used for that group.
 If multiple REGEXPs match a group, the score files corresponding to each
 match will be used (for only one match to be used, see
-gnus-score-file-single-match-alist).
+`gnus-score-file-single-match-alist').
 
 These score files are loaded in addition to any files returned by
-gnus-score-find-score-files-function (which see)."
+`gnus-score-find-score-files-function'."
   :group 'gnus-score-files
   :type '(repeat (cons regexp (repeat file))))
 
@@ -99,15 +105,15 @@ files do not actually have to exist.
 
 Predefined values are:
 
-gnus-score-find-single: Only apply the group's own score file.
-gnus-score-find-hierarchical: Also apply score files from parent groups.
-gnus-score-find-bnews: Apply score files whose names matches.
+`gnus-score-find-single': Only apply the group's own score file.
+`gnus-score-find-hierarchical': Also apply score files from parent groups.
+`gnus-score-find-bnews': Apply score files whose names matches.
 
 See the documentation to these functions for more information.
 
 This variable can also be a list of functions to be called.  Each
-function should either return a list of score files, or a list of
-score alists.
+function is given the group name as argument and should either return
+a list of score files, or a list of score alists.
 
 If functions other than these pre-defined functions are used,
 the `a' symbolic prefix to the score commands will always use
@@ -116,7 +122,12 @@ the `a' symbolic prefix to the score commands will always use
   :type '(radio (function-item gnus-score-find-single)
                (function-item gnus-score-find-hierarchical)
                (function-item gnus-score-find-bnews)
-               (function :tag "Other")))
+               (repeat :tag "List of functions"
+                       (choice (function :tag "Other" :value 'ignore)
+                               (function-item gnus-score-find-single)
+                               (function-item gnus-score-find-hierarchical)
+                               (function-item gnus-score-find-bnews)))
+               (function :tag "Other" :value 'ignore)))
 
 (defcustom gnus-score-interactive-default-score 1000
   "*Scoring commands will raise/lower the score with this number as the default."
@@ -137,12 +148,6 @@ will be expired along with non-matching score entries."
   :group 'gnus-score-expire
   :type 'boolean)
 
-(defcustom gnus-orphan-score nil
-  "*All orphans get this score added.  Set in the score file."
-  :group 'gnus-score-default
-  :type '(choice (const nil)
-                integer))
-
 (defcustom gnus-decay-scores nil
   "*If non-nil, decay non-permanent scores."
   :group 'gnus-score-decay
@@ -200,6 +205,8 @@ It can be:
                 (repeat (choice string
                                 (cons regexp (repeat file))
                                 (function :value fun)))
+                (function-item gnus-hierarchial-home-score-file)
+                (function-item gnus-current-home-score-file)
                 (function :value fun)))
 
 (defcustom gnus-home-adapt-file nil
@@ -220,14 +227,20 @@ This variable allows the same syntax as `gnus-home-score-file'."
     (gnus-catchup-mark (subject -10))
     (gnus-killed-mark (from -1) (subject -20))
     (gnus-del-mark (from -2) (subject -15)))
-"*Alist of marks and scores."
-:group 'gnus-score-adapt
-:type '(repeat (cons (symbol :tag "Mark")
-                    (repeat (list (choice :tag "Header"
-                                          (const from)
-                                          (const subject)
-                                          (symbol :tag "other"))
-                                  (integer :tag "Score"))))))
+  "*Alist of marks and scores."
+  :group 'gnus-score-adapt
+  :type '(repeat (cons (symbol :tag "Mark")
+                      (repeat (list (choice :tag "Header"
+                                            (const from)
+                                            (const subject)
+                                            (symbol :tag "other"))
+                                    (integer :tag "Score"))))))
+
+(defcustom gnus-adaptive-word-length-limit nil
+  "*Words of a length lesser than this limit will be ignored when doing adaptive scoring."
+  :group 'gnus-score-adapt
+  :type '(radio (const :format "Unlimited " nil)
+               (integer :format "Maximum length: %v\n" :size 0)))
 
 (defcustom gnus-ignored-adaptive-words nil
   "List of words to be ignored when doing adaptive word scoring."
@@ -258,16 +271,21 @@ This variable allows the same syntax as `gnus-home-score-file'."
     (,gnus-catchup-mark . -10)
     (,gnus-killed-mark . -20)
     (,gnus-del-mark . -15))
-"*Alist of marks and scores."
-:group 'gnus-score-adapt
-:type '(repeat (cons (character :tag "Mark")
-                    (integer :tag "Score"))))
+  "*Alist of marks and scores."
+  :group 'gnus-score-adapt
+  :type '(repeat (cons (character :tag "Mark")
+                      (integer :tag "Score"))))
 
 (defcustom gnus-adaptive-word-minimum nil
   "If a number, this is the minimum score value that can be assigned to a word."
   :group 'gnus-score-adapt
   :type '(choice (const nil) integer))
 
+(defcustom gnus-adaptive-word-no-group-words nil
+  "If t, don't adaptively score words included in the group name."
+  :group 'gnus-score-adapt
+  :type 'boolean)
+
 (defcustom gnus-score-mimic-keymap nil
   "*Have the score entry functions pretend that they are a keymap."
   :group 'gnus-score-default
@@ -302,6 +320,7 @@ Should be one of the following symbols.
  i: message-id
  t: references
  x: xref
+ e: `extra' (non-standard overview)
  l: lines
  d: date
  f: followup
@@ -315,6 +334,7 @@ If nil, the user will be asked for a header."
                 (const :tag "message-id" i)
                 (const :tag "references" t)
                 (const :tag "xref" x)
+                (const :tag "extra" e)
                 (const :tag "lines" l)
                 (const :tag "date" d)
                 (const :tag "followup" f)
@@ -330,7 +350,7 @@ Should be one of the following symbols.
  f: fuzzy string
  r: regexp string
  b: before date
- a: at date
+ a: after date
  n: this date
  <: less than number
  >: greater than number
@@ -343,7 +363,7 @@ If nil, the user will be asked for a match type."
                 (const :tag "fuzzy string" f)
                 (const :tag "regexp string" r)
                 (const :tag "before date" b)
-                (const :tag "at date" a)
+                (const :tag "after date" a)
                 (const :tag "this date" n)
                 (const :tag "less than number" <)
                 (const :tag "greater than number" >)
@@ -374,17 +394,20 @@ If nil, the user will be asked for a duration."
 (defcustom gnus-score-after-write-file-function nil
   "Function called with the name of the score file just written to disk."
   :group 'gnus-score-files
-  :type 'function)
+  :type '(choice (const nil) function))
 
 (defcustom gnus-score-thread-simplify nil
   "If non-nil, subjects will simplified as in threading."
   :group 'gnus-score-various
-  :type 'boolean) 
+  :type 'boolean)
 
 \f
 
 ;; Internal variables.
 
+(defvar gnus-score-use-all-scores t
+  "If nil, only `gnus-score-find-score-files-function' is used.")
+
 (defvar gnus-adaptive-word-syntax-table
   (let ((table (copy-syntax-table (standard-syntax-table)))
        (numbers '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)))
@@ -429,26 +452,60 @@ of the last successful match.")
 
 (defconst gnus-header-index
   ;; Name to index alist.
-  '(("number" 0 gnus-score-integer)
-    ("subject" 1 gnus-score-string)
-    ("from" 2 gnus-score-string)
-    ("date" 3 gnus-score-date)
-    ("message-id" 4 gnus-score-string)
-    ("references" 5 gnus-score-string)
-    ("chars" 6 gnus-score-integer)
-    ("lines" 7 gnus-score-integer)
-    ("xref" 8 gnus-score-string)
+  `(("number"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'location)
+     gnus-score-integer)
+    ("subject"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'subject)
+     gnus-score-string)
+    ("from"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'from)
+     gnus-score-string)
+    ("date"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'date)
+     gnus-score-date)
+    ("message-id"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'id)
+     gnus-score-string)
+    ("references"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'references)
+     gnus-score-string)
+    ("chars"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'chars)
+     gnus-score-integer)
+    ("lines"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'lines)
+     gnus-score-integer)
+    ("xref"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'xref)
+     gnus-score-string)
+;;    ("extra" 16 gnus-score-string)
+    ("extra" -1 gnus-score-body)
     ("head" -1 gnus-score-body)
     ("body" -1 gnus-score-body)
     ("all" -1 gnus-score-body)
-    ("followup" 2 gnus-score-followup)
-    ("thread" 5 gnus-score-thread)))
+    ("followup"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'from)
+     gnus-score-followup)
+    ("thread"
+     ,(luna-class-slot-index (luna-find-class 'mime-gnus-entity)
+                            'references)
+     gnus-score-thread)))
 
 ;;; Summary mode score maps.
 
 (gnus-define-keys (gnus-summary-score-map "V" gnus-summary-mode-map)
   "s" gnus-summary-set-score
-  "a" gnus-summary-score-entry
   "S" gnus-summary-current-score
   "c" gnus-score-change-score-file
   "C" gnus-score-customize
@@ -470,9 +527,10 @@ of the last successful match.")
   "Make a score entry based on the current article.
 The user will be prompted for header to score on, match type,
 permanence, and the string to be used.  The numerical prefix will be
-used as score."
+used as score.  A symbolic prefix of `a' says to use the `all.SCORE'
+file for the command instead of the current score file."
   (interactive (gnus-interactive "P\ny"))
-  (gnus-summary-increase-score (- (gnus-score-default score)) symp))
+  (gnus-summary-increase-score (- (gnus-score-delta-default score)) symp))
 
 (defun gnus-score-kill-help-buffer ()
   (when (get-buffer "*Score Help*")
@@ -484,9 +542,10 @@ used as score."
   "Make a score entry based on the current article.
 The user will be prompted for header to score on, match type,
 permanence, and the string to be used.  The numerical prefix will be
-used as score."
+used as score.  A symbolic prefix of `a' says to use the `all.SCORE'
+file for the command instead of the current score file."
   (interactive (gnus-interactive "P\ny"))
-  (let* ((nscore (gnus-score-default score))
+  (let* ((nscore (gnus-score-delta-default score))
         (prefix (if (< nscore 0) ?L ?I))
         (increase (> nscore 0))
         (char-to-header
@@ -494,13 +553,14 @@ used as score."
            (?s "subject" nil nil string)
            (?b "body" "" nil body-string)
            (?h "head" "" nil body-string)
-           (?i "message-id" nil t string)
-           (?t "references" "message-id" nil string)
+           (?i "message-id" nil nil string)
+           (?r "references" "message-id" nil string)
            (?x "xref" nil nil string)
+           (?e "extra" nil nil string)
            (?l "lines" nil nil number)
            (?d "date" nil nil date)
            (?f "followup" nil nil string)
-           (?T "thread" nil nil string)))
+           (?t "thread" "message-id" nil string)))
         (char-to-type
          '((?s s "substring" string)
            (?e e "exact string" string)
@@ -509,8 +569,8 @@ used as score."
            (?z s "substring" body-string)
            (?p r "regexp string" body-string)
            (?b before "before date" date)
-           (?a at "at date" date)
-           (?n now "this date" date)
+           (?a after "after date" date)
+           (?n at "this date" date)
            (?< < "less than number" number)
            (?> > "greater than number" number)
            (?= = "equal to number" number)))
@@ -525,7 +585,7 @@ used as score."
                     (aref (symbol-name gnus-score-default-type) 0)))
         (pchar (and gnus-score-default-duration
                     (aref (symbol-name gnus-score-default-duration) 0)))
-        entry temporary type match)
+        entry temporary type match extra)
 
     (unwind-protect
        (progn
@@ -547,7 +607,7 @@ used as score."
          (gnus-score-kill-help-buffer)
          (unless (setq entry (assq (downcase hchar) char-to-header))
            (if mimic (error "%c %c" prefix hchar)
-             (error "Illegal header type")))
+             (error "Invalid header type")))
 
          (when (/= (downcase hchar) hchar)
            ;; This was a majuscule, so we end reading and set the defaults.
@@ -580,13 +640,13 @@ used as score."
            (gnus-score-kill-help-buffer)
            (unless (setq type (nth 1 (assq (downcase tchar) legal-types)))
              (if mimic (error "%c %c" prefix hchar)
-               (error "Illegal match type"))))
+               (error "Invalid match type"))))
 
          (when (/= (downcase tchar) tchar)
            ;; It was a majuscule, so we end reading and use the default.
            (if mimic (message "%c %c %c" prefix hchar tchar)
              (message ""))
-           (setq pchar (or pchar ?p)))
+           (setq pchar (or pchar ?t)))
 
          ;; We continue reading.
          (while (not pchar)
@@ -608,18 +668,35 @@ used as score."
            ;; Deal with der(r)ided superannuated paradigms.
            (when (and (eq (1+ prefix) 77)
                       (eq (+ hchar 12) 109)
-                      (eq tchar 114)
+                      (eq (1- tchar) 113)
                       (eq (- pchar 4) 111))
              (error "You rang?"))
            (if mimic
                (error "%c %c %c %c" prefix hchar tchar pchar)
-             (error "Illegal match duration"))))
+             (error "Invalid match duration"))))
       ;; Always kill the score help buffer.
       (gnus-score-kill-help-buffer))
 
+    ;; If scoring an extra (non-standard overview) header,
+    ;; we must find out which header is in question.
+    (setq extra
+         (and gnus-extra-headers
+              (equal (nth 1 entry) "extra")
+              (intern                  ; need symbol
+               (gnus-completing-read-with-default
+                (symbol-name (car gnus-extra-headers)) ; default response
+                "Score extra header:"  ; prompt
+                (mapcar (lambda (x)    ; completion list
+                          (cons (symbol-name x) x))
+                        gnus-extra-headers)
+                nil                    ; no completion limit
+                t))))                  ; require match
+    ;; extra is now nil or a symbol.
+
     ;; We have all the data, so we enter this score.
     (setq match (if (string= (nth 2 entry) "") ""
-                 (gnus-summary-header (or (nth 2 entry) (nth 1 entry)))))
+                 (gnus-summary-header (or (nth 2 entry) (nth 1 entry))
+                                      nil extra)))
 
     ;; Modify the match, perhaps.
     (cond
@@ -646,7 +723,7 @@ used as score."
           current-score-file)
          (t
           (gnus-score-file-name "all"))))))
-    
+
     (gnus-summary-score-entry
      (nth 1 entry)                     ; Header
      match                             ; Match
@@ -655,7 +732,9 @@ used as score."
      (if (eq temporary 'perm)          ; Temp
         nil
        temporary)
-     (not (nth 3 entry)))              ; Prompt
+     (not (nth 3 entry))               ; Prompt
+     nil                               ; not silent
+     extra)                            ; non-standard overview.
 
     (when (eq symp 'a)
       ;; We change the score file back to the previous one.
@@ -666,8 +745,8 @@ used as score."
 (defun gnus-score-insert-help (string alist idx)
   (setq gnus-score-help-winconf (current-window-configuration))
   (save-excursion
-    (set-buffer (get-buffer-create "*Score Help*"))
-    (buffer-disable-undo (current-buffer))
+    (set-buffer (gnus-get-buffer-create "*Score Help*"))
+    (buffer-disable-undo)
     (delete-windows-on (current-buffer))
     (erase-buffer)
     (insert string ":\n\n")
@@ -696,22 +775,27 @@ used as score."
        (insert (format format (caar alist) (nth idx (car alist))))
        (setq alist (cdr alist))
        (setq i (1+ i))))
+    (goto-char (point-min))
     ;; display ourselves in a small window at the bottom
     (gnus-appt-select-lowest-window)
-    (split-window)
-    (pop-to-buffer "*Score Help*")
+    (if (< (/ (window-height) 2) window-min-height)
+       (switch-to-buffer "*Score Help*")
+      (split-window)
+      (pop-to-buffer "*Score Help*"))
     (let ((window-min-height 1))
       (shrink-window-if-larger-than-buffer))
-    (select-window (get-buffer-window gnus-summary-buffer))))
+    (select-window (gnus-get-buffer-window gnus-summary-buffer t))))
 
-(defun gnus-summary-header (header &optional no-err)
+(defun gnus-summary-header (header &optional no-err extra)
   ;; Return HEADER for current articles, or error.
   (let ((article (gnus-summary-article-number))
        headers)
     (if article
        (if (and (setq headers (gnus-summary-article-header article))
                 (vectorp headers))
-           (aref headers (nth 1 (assoc header gnus-header-index)))
+           (if extra                   ; `header' must be "extra"
+               (or (cdr (assq extra (mail-header-extra headers))) "")
+             (aref headers (nth 1 (assoc header gnus-header-index))))
          (if no-err
              nil
            (error "Pseudo-articles can't be scored")))
@@ -737,7 +821,7 @@ used as score."
                  (gnus-newsgroup-score-alist)))))
 
 (defun gnus-summary-score-entry (header match type score date
-                                       &optional prompt silent)
+                                       &optional prompt silent extra)
   "Enter score file entry.
 HEADER is the header being scored.
 MATCH is the string we are looking for.
@@ -745,21 +829,8 @@ TYPE is the match type: substring, regexp, exact, fuzzy.
 SCORE is the score to add.
 DATE is the expire date, or nil for no expire, or 'now for immediate expire.
 If optional argument `PROMPT' is non-nil, allow user to edit match.
-If optional argument `SILENT' is nil, show effect of score entry."
-  (interactive
-   (list (completing-read "Header: "
-                         gnus-header-index
-                         (lambda (x) (fboundp (nth 2 x)))
-                         t)
-        (read-string "Match: ")
-        (if (y-or-n-p "Use regexp match? ") 'r 's)
-        (and current-prefix-arg
-             (prefix-numeric-value current-prefix-arg))
-        (cond ((not (y-or-n-p "Add to score file? "))
-               'now)
-              ((y-or-n-p "Expire kill? ")
-               (current-time-string))
-              (t nil))))
+If optional argument `SILENT' is nil, show effect of score entry.
+If optional argument `EXTRA' is non-nil, it's a non-standard overview header."
   ;; Regexp is the default type.
   (when (eq type t)
     (setq type 'r))
@@ -768,9 +839,10 @@ If optional argument `SILENT' is nil, show effect of score entry."
         (setq match (if match (gnus-simplify-subject-re match) "")))
        ((eq type 'f)
         (setq match (gnus-simplify-subject-fuzzy match))))
-  (let ((score (gnus-score-default score))
-       (header (format "%s" (downcase header)))
+  (let ((score (gnus-score-delta-default score))
+       (header (downcase header))
        new)
+    (set-text-properties 0 (length header) nil header)
     (when prompt
       (setq match (read-string
                   (format "Match %s on %s, %s: "
@@ -785,12 +857,11 @@ If optional argument `SILENT' is nil, show effect of score entry."
                       (int-to-string match)
                     match))))
 
-    ;; Get rid of string props.
-    (setq match (format "%s" match))
-
     ;; If this is an integer comparison, we transform from string to int.
-    (when (eq (nth 2 (assoc header gnus-header-index)) 'gnus-score-integer)
-      (setq match (string-to-int match)))
+    (if (eq (nth 2 (assoc header gnus-header-index)) 'gnus-score-integer)
+       (if (stringp match)
+           (setq match (string-to-int match)))
+      (set-text-properties 0 (length match) nil match))
 
     (unless (eq date 'now)
       ;; Add the score entry to the score file.
@@ -800,12 +871,17 @@ If optional argument `SILENT' is nil, show effect of score entry."
            elem)
        (setq new
              (cond
+              (extra
+               (list match score
+                     (and date (if (numberp date) date
+                                 (date-to-day date)))
+                     type (symbol-name extra)))
               (type
                (list match score
                      (and date (if (numberp date) date
-                                 (gnus-day-number date)))
+                                 (date-to-day date)))
                      type))
-              (date (list match score (gnus-day-number date)))
+              (date (list match score (date-to-day date)))
               (score (list match score))
               (t (list match))))
        ;; We see whether we can collapse some score entries.
@@ -830,25 +906,26 @@ If optional argument `SILENT' is nil, show effect of score entry."
       (if (and (>= (nth 1 (assoc header gnus-header-index)) 0)
               (eq (nth 2 (assoc header gnus-header-index))
                   'gnus-score-string))
-         (gnus-summary-score-effect header match type score)
+         (gnus-summary-score-effect header match type score extra)
        (gnus-summary-rescore)))
 
     ;; Return the new scoring rule.
     new))
 
-(defun gnus-summary-score-effect (header match type score)
+(defun gnus-summary-score-effect (header match type score &optional extra)
   "Simulate the effect of a score file entry.
 HEADER is the header being scored.
 MATCH is the string we are looking for.
 TYPE is the score type.
-SCORE is the score to add."
+SCORE is the score to add.
+EXTRA is the possible non-standard header."
   (interactive (list (completing-read "Header: "
                                      gnus-header-index
                                      (lambda (x) (fboundp (nth 2 x)))
                                      t)
                     (read-string "Match: ")
-                    (y-or-n-p "Use regexp match? ")
-                    (prefix-numeric-value current-prefix-arg)))
+                    (if (y-or-n-p "Use regexp match? ") 'r 's)
+                    (string-to-int (read-string "Score: "))))
   (save-excursion
     (unless (and (stringp match) (> (length match) 0))
       (error "No match"))
@@ -862,7 +939,7 @@ SCORE is the score to add."
                        (t
                         (regexp-quote match)))))
       (while (not (eobp))
-       (let ((content (gnus-summary-header header 'noerr))
+       (let ((content (gnus-summary-header header 'noerr extra))
              (case-fold-search t))
          (and content
               (when (if (eq type 'f)
@@ -898,7 +975,6 @@ SCORE is the score to add."
 
 ;; All score code written by Per Abrahamsen <abraham@iesd.auc.dk>.
 
-;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
 (defun gnus-score-set-mark-below (score)
   "Automatically mark articles with score below SCORE as read."
   (interactive
@@ -945,7 +1021,7 @@ SCORE is the score to add."
 (defun gnus-score-followup-article (&optional score)
   "Add SCORE to all followups to the article in the current buffer."
   (interactive "P")
-  (setq score (gnus-score-default score))
+  (setq score (gnus-score-delta-default score))
   (when (gnus-buffer-live-p gnus-summary-buffer)
     (save-excursion
       (save-restriction
@@ -960,7 +1036,7 @@ SCORE is the score to add."
 (defun gnus-score-followup-thread (&optional score)
   "Add SCORE to all later articles in the thread the current buffer is part of."
   (interactive "P")
-  (setq score (gnus-score-default score))
+  (setq score (gnus-score-delta-default score))
   (when (gnus-buffer-live-p gnus-summary-buffer)
     (save-excursion
       (save-restriction
@@ -1005,7 +1081,7 @@ SCORE is the score to add."
     (let ((buffer-read-only nil))
       ;; Set score.
       (gnus-summary-update-mark
-       (if (= n (or gnus-summary-default-score 0)) ? 
+       (if (= n (or gnus-summary-default-score 0)) ?  ;Whitespace
         (if (< n (or gnus-summary-default-score 0))
             gnus-score-below-mark gnus-score-over-mark))
        'score))
@@ -1065,16 +1141,49 @@ SCORE is the score to add."
    4 (substitute-command-keys
       "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
 
+(defun gnus-score-edit-file-at-point (&optional format)
+  "Edit score file at point in Score Trace buffers.
+If FORMAT, also format the current score file."
+  (let* ((rule (save-excursion
+                (beginning-of-line)
+                (read (current-buffer))))
+        (sep "[ \n\r\t]*")
+        ;; Must be synced with `gnus-score-find-trace':
+        (reg " -> +")
+        (file (save-excursion
+                (end-of-line)
+                (if (and (re-search-backward reg (gnus-point-at-bol) t)
+                         (re-search-forward  reg (gnus-point-at-eol) t))
+                    (buffer-substring (point) (gnus-point-at-eol))
+                  nil))))
+    (if (or (not file)
+           (string-match "\\<\\(non-file rule\\|A file\\)\\>" file)
+           ;; (see `gnus-score-find-trace' and `gnus-score-advanced')
+           (string= "" file))
+       (gnus-error 3 "Can't find a score file in current line.")
+      (gnus-score-edit-file file)
+      (when format
+       (gnus-score-pretty-print))
+      (when (consp rule) ;; the rule exists
+       (setq rule (mapconcat #'(lambda (obj)
+                                 (regexp-quote (format "%S" obj)))
+                             rule
+                             sep))
+       (goto-char (point-min))
+       (re-search-forward rule nil t)
+       ;; make it easy to use `kill-sexp':
+       (goto-char (1- (match-beginning 0)))))))
+
 (defun gnus-score-load-file (file)
   ;; Load score file FILE.  Returns a list a retrieved score-alists.
   (let* ((file (expand-file-name
                (or (and (string-match
-                         (concat "^" (expand-file-name
-                                      gnus-kill-files-directory))
+                         (concat "^" (regexp-quote
+                                      (expand-file-name
+                                       gnus-kill-files-directory)))
                          (expand-file-name file))
                         file)
-                   (concat (file-name-as-directory gnus-kill-files-directory)
-                           file))))
+                   (expand-file-name file gnus-kill-files-directory))))
         (cached (assoc file gnus-score-cache))
         (global (member file gnus-internal-global-score-files))
         lists alist)
@@ -1097,9 +1206,13 @@ SCORE is the score to add."
          found)
       (while a
        ;; Downcase all header names.
-       (when (stringp (caar a))
+       (cond
+        ((stringp (caar a))
          (setcar (car a) (downcase (caar a)))
          (setq found t))
+        ;; Advanced scoring.
+        ((consp (caar a))
+         (setq found t)))
        (pop a))
       ;; If there are actual scores in the alist, we add it to the
       ;; return value of this function.
@@ -1111,7 +1224,7 @@ SCORE is the score to add."
          (mark-and-expunge (car (gnus-score-get 'mark-and-expunge alist)))
          (files (gnus-score-get 'files alist))
          (exclude-files (gnus-score-get 'exclude-files alist))
-          (orphan (car (gnus-score-get 'orphan alist)))
+         (orphan (car (gnus-score-get 'orphan alist)))
          (adapt (gnus-score-get 'adapt alist))
          (thread-mark-and-expunge
           (car (gnus-score-get 'thread-mark-and-expunge alist)))
@@ -1125,7 +1238,7 @@ SCORE is the score to add."
                 (or (not decay)
                     (gnus-decay-scores alist decay)))
        (gnus-score-set 'touched '(t) alist)
-       (gnus-score-set 'decay (list (gnus-time-to-day (current-time)))))
+       (gnus-score-set 'decay (list (time-to-days (current-time))) alist))
       ;; We do not respect eval and files atoms from global score
       ;; files.
       (when (and files (not global))
@@ -1170,7 +1283,6 @@ SCORE is the score to add."
                   (setq gnus-newsgroup-adaptive t)
                   adapt)
                  (t
-                  ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring)
                   gnus-default-adaptive-score-alist)))
       (setq gnus-thread-expunge-below
            (or thread-mark-and-expunge gnus-thread-expunge-below))
@@ -1206,9 +1318,9 @@ SCORE is the score to add."
        ;; Couldn't read file.
        (setq gnus-score-alist nil)
       ;; Read file.
-      (save-excursion
-       (gnus-set-work-buffer)
-       (insert-file-contents file)
+      (with-temp-buffer
+       (insert-file-contents-as-coding-system
+        score-mode-coding-system file)
        (goto-char (point-min))
        ;; Only do the loading if the score file isn't empty.
        (when (save-excursion (re-search-forward "[()0-9a-zA-Z]" nil t))
@@ -1217,10 +1329,16 @@ SCORE is the score to add."
                    (read (current-buffer))
                  (error
                   (gnus-error 3.2 "Problem with score file %s" file))))))
-      (if (eq (car alist) 'setq)
-         ;; This is an old-style score file.
-         (setq gnus-score-alist (gnus-score-transform-old-to-new alist))
-       (setq gnus-score-alist alist))
+      (cond
+       ((and alist
+            (atom alist))
+       ;; Bogus score file.
+       (error "Invalid syntax with score file %s" file))
+       ((eq (car alist) 'setq)
+       ;; This is an old-style score file.
+       (setq gnus-score-alist (gnus-score-transform-old-to-new alist)))
+       (t
+       (setq gnus-score-alist alist)))
       ;; Check the syntax of the score file.
       (setq gnus-score-alist
            (gnus-score-check-syntax gnus-score-alist file)))))
@@ -1242,11 +1360,11 @@ SCORE is the score to add."
         err
         (cond
          ((not (listp (car a)))
-          (format "Illegal score element %s in %s" (car a) file))
+          (format "Invalid score element %s in %s" (car a) file))
          ((stringp (caar a))
           (cond
            ((not (listp (setq sr (cdar a))))
-            (format "Illegal header match %s in %s" (nth 1 (car a)) file))
+            (format "Invalid header match %s in %s" (nth 1 (car a)) file))
            (t
             (setq type (caar a))
             (while (and sr (not err))
@@ -1257,7 +1375,7 @@ SCORE is the score to add."
                 ((if (member (downcase type) '("lines" "chars"))
                      (not (numberp (car s)))
                    (not (stringp (car s))))
-                 (format "Illegal match %s in %s" (car s) file))
+                 (format "Invalid match %s in %s" (car s) file))
                 ((and (cadr s) (not (integerp (cadr s))))
                  (format "Non-integer score %s in %s" (cadr s) file))
                 ((and (caddr s) (not (integerp (caddr s))))
@@ -1288,7 +1406,7 @@ SCORE is the score to add."
              (setcar scor
                      (list (caar scor) (nth 2 (car scor))
                            (and (nth 3 (car scor))
-                                (gnus-day-number (nth 3 (car scor))))
+                                (date-to-day (nth 3 (car scor))))
                            (if (nth 1 (car scor)) 'r 's)))
              (setq scor (cdr scor))))
        (push (if (not (listp (cdr entry)))
@@ -1308,14 +1426,14 @@ SCORE is the score to add."
       (while cache
        (current-buffer)
        (setq entry (pop cache)
-             file (car entry)
+             file (nnheader-translate-file-chars (car entry) t)
              score (cdr entry))
        (if (or (not (equal (gnus-score-get 'touched score) '(t)))
                (gnus-score-get 'read-only score)
                (and (file-exists-p file)
                     (not (file-writable-p file))))
            ()
-         (setq score (setcdr entry (delq (assq 'touched score) score)))
+         (setq score (setcdr entry (gnus-delete-alist 'touched score)))
          (erase-buffer)
          (let (emacs-lisp-mode-hook)
            (if (string-match
@@ -1327,14 +1445,16 @@ SCORE is the score to add."
                (gnus-prin1 score)
              ;; This is a normal score file, so we print it very
              ;; prettily.
-             (pp score (current-buffer))))
+             (let ((lisp-mode-syntax-table score-mode-syntax-table))
+               (pp score (current-buffer)))))
          (gnus-make-directory (file-name-directory file))
          ;; If the score file is empty, we delete it.
          (if (zerop (buffer-size))
              (delete-file file)
            ;; There are scores, so we write the file.
            (when (file-writable-p file)
-             (gnus-write-buffer file)
+             (gnus-write-buffer-as-coding-system
+              score-mode-coding-system file)
              (when gnus-score-after-write-file-function
                (funcall gnus-score-after-write-file-function file)))))
        (and gnus-score-uncacheable-files
@@ -1382,13 +1502,13 @@ SCORE is the score to add."
       (when (and gnus-summary-default-score
                 scores)
        (let* ((entries gnus-header-index)
-              (now (gnus-day-number (current-time-string)))
+              (now (date-to-day (current-time-string)))
               (expire (and gnus-score-expiry-days
                            (- now gnus-score-expiry-days)))
               (headers gnus-newsgroup-headers)
               (current-score-file gnus-current-score-file)
               entry header new)
-         (gnus-message 5 "Scoring...")
+         (gnus-message 7 "Scoring...")
          ;; Create articles, an alist of the form `(HEADER . SCORE)'.
          (while (setq header (pop headers))
            ;; WARNING: The assq makes the function O(N*S) while it could
@@ -1400,8 +1520,8 @@ SCORE is the score to add."
                          gnus-scores-articles))))
 
          (save-excursion
-           (set-buffer (get-buffer-create "*Headers*"))
-           (buffer-disable-undo (current-buffer))
+           (set-buffer (gnus-get-buffer-create "*Headers*"))
+           (buffer-disable-undo)
            (when (gnus-buffer-live-p gnus-summary-buffer)
              (message-clone-locals gnus-summary-buffer))
 
@@ -1425,8 +1545,12 @@ SCORE is the score to add."
                (when (setq new (funcall (nth 2 entry) scores header
                                         now expire trace))
                  (push new news))))
+           (when (gnus-buffer-live-p gnus-summary-buffer)
+             (let ((scored gnus-newsgroup-scored))
+               (with-current-buffer gnus-summary-buffer
+                 (setq gnus-newsgroup-scored scored))))
            ;; Remove the buffer.
-           (kill-buffer (current-buffer)))
+           (gnus-kill-buffer (current-buffer)))
 
          ;; Add articles to `gnus-newsgroup-scored'.
          (while gnus-scores-articles
@@ -1441,85 +1565,54 @@ SCORE is the score to add."
          (let (score)
            (while (setq score (pop scores))
              (while score
-               (when (listp (caar score))
+               (when (consp (caar score))
                  (gnus-score-advanced (car score) trace))
                (pop score))))
 
-         (gnus-message 5 "Scoring...done"))))))
-
-
-(defun gnus-get-new-thread-ids (articles)
-  (let ((index (nth 1 (assoc "message-id" gnus-header-index)))
-        (refind gnus-score-index)
-        id-list art this tref)
-    (while articles
-      (setq art (car articles)
-            this (aref (car art) index)
-            tref (aref (car art) refind)
-            articles (cdr articles))
-      (when (string-equal tref "")     ;no references line
-       (push this id-list)))
-    id-list))
+         (gnus-message 7 "Scoring...done"))))))
+
+(defun gnus-score-lower-thread (thread score-adjust)
+  "Lower the score on THREAD with SCORE-ADJUST.
+THREAD is expected to contain a list of the form `(PARENT [CHILD1
+CHILD2 ...])' where PARENT is a header array and each CHILD is a list
+of the same form as THREAD.  The empty list nil is valid.  For each
+article in the tree, the score of the corresponding entry in
+`gnus-newsgroup-scored' is adjusted by SCORE-ADJUST."
+  (while thread
+    (let ((head (car thread)))
+      (if (listp head)
+         ;; handle a child and its descendants
+         (gnus-score-lower-thread head score-adjust)
+       ;; handle the parent
+       (let* ((article (mail-header-number head))
+              (score (assq article gnus-newsgroup-scored)))
+         (if score (setcdr score (+ (cdr score) score-adjust))
+           (push (cons article score-adjust) gnus-newsgroup-scored)))))
+    (setq thread (cdr thread))))
 
-;; Orphan functions written by plm@atcmp.nl (Peter Mutsaers).
 (defun gnus-score-orphans (score)
-  (let ((new-thread-ids (gnus-get-new-thread-ids gnus-scores-articles))
-        alike articles art arts this last this-id)
-
-    (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
-         articles gnus-scores-articles)
-
-    ;;more or less the same as in gnus-score-string
-    (erase-buffer)
-    (while articles
-      (setq art (car articles)
-            this (aref (car art) gnus-score-index)
-            articles (cdr articles))
-      ;;completely skip if this is empty (not a child, so not an orphan)
-      (when (not (string= this ""))
-       (if (equal last this)
-           ;; O(N*H) cons-cells used here, where H is the number of
-           ;; headers.
-           (push art alike)
-         (when last
-           ;; Insert the line, with a text property on the
-           ;; terminating newline referring to the articles with
-           ;; this line.
-           (insert last ?\n)
-           (put-text-property (1- (point)) (point) 'articles alike))
-         (setq alike (list art)
-               last this))))
-    (when last                         ; Bwadr, duplicate code.
-      (insert last ?\n)
-      (put-text-property (1- (point)) (point) 'articles alike))
-
-    ;; PLM: now delete those lines that contain an entry from new-thread-ids
-    (while new-thread-ids
-      (setq this-id (car new-thread-ids)
-            new-thread-ids (cdr new-thread-ids))
-      (goto-char (point-min))
-      (while (search-forward this-id nil t)
-        ;; found a match.  remove this line
-       (beginning-of-line)
-       (kill-line 1)))
-
-    ;; now for each line: update its articles with score by moving to
-    ;; every end-of-line in the buffer and read the articles property
-    (goto-char (point-min))
-    (while (eq 0 (progn
-                   (end-of-line)
-                   (setq arts (get-text-property (point) 'articles))
-                   (while arts
-                     (setq art (car arts)
-                           arts (cdr arts))
-                     (setcdr art (+ score (cdr art))))
-                   (forward-line))))))
-
+  "Score orphans.
+A root is an article with no references.  An orphan is an article
+which has references, but is not connected via its references to a
+root article.  This function finds all the orphans, and adjusts their
+score in `gnus-newsgroup-scored' by SCORE."
+  ;; gnus-make-threads produces a list, where each entry is a "thread"
+  ;; as described in the gnus-score-lower-thread docs.  This function
+  ;; will be called again (after limiting has been done) if the display
+  ;; is threaded.  It would be nice to somehow save this info and use
+  ;; it later.
+  (dolist (thread (gnus-make-threads))
+    (let ((id (aref (car thread) gnus-score-index)))
+      ;; If the parent of the thread is not a root, lower the score of
+      ;; it and its descendants.  Note that some roots seem to satisfy
+      ;; (eq id nil) and some (eq id "");  not sure why.
+      (when (and id
+                (not (string= id "")))
+       (gnus-score-lower-thread thread score)))))
 
 (defun gnus-score-integer (scores header now expire &optional trace)
   (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
        entries alist)
-
     ;; Find matches.
     (while scores
       (setq alist (car scores)
@@ -1536,7 +1629,7 @@ SCORE is the score to add."
               (match-func (if (or (eq type '>) (eq type '<) (eq type '<=)
                                   (eq type '>=) (eq type '=))
                               type
-                            (error "Illegal match type: %s" type)))
+                            (error "Invalid match type: %s" type)))
               (articles gnus-scores-articles))
          ;; Instead of doing all the clever stuff that
          ;; `gnus-score-string' does to minimize searches and stuff,
@@ -1568,7 +1661,6 @@ SCORE is the score to add."
 (defun gnus-score-date (scores header now expire &optional trace)
   (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
        entries alist match match-func article)
-
     ;; Find matches.
     (while scores
       (setq alist (car scores)
@@ -1596,7 +1688,7 @@ SCORE is the score to add."
           ((eq type 'regexp)
            (setq match-func 'string-match
                  match (nth 0 kill)))
-          (t (error "Illegal match type: %s" type)))
+          (t (error "Invalid match type: %s" type)))
          ;; Instead of doing all the clever stuff that
          ;; `gnus-score-string' does to minimize searches and stuff,
          ;; I will assume that people generally will put so few
@@ -1624,204 +1716,218 @@ SCORE is the score to add."
   nil)
 
 (defun gnus-score-body (scores header now expire &optional trace)
-  (save-excursion
-    (setq gnus-scores-articles
-         (sort gnus-scores-articles
-               (lambda (a1 a2)
-                 (< (mail-header-number (car a1))
-                    (mail-header-number (car a2))))))
-    (set-buffer nntp-server-buffer)
-    (save-restriction
-      (let* ((buffer-read-only nil)
-            (articles gnus-scores-articles)
-            (all-scores scores)
-            (request-func (cond ((string= "head" header)
-                                 'gnus-request-head)
-                                ((string= "body" header)
-                                 'gnus-request-body)
-                                (t 'gnus-request-article)))
-            entries alist ofunc article last)
-       (when articles
-         (setq last (mail-header-number (caar (last articles))))
-         ;; Not all backends support partial fetching.  In that case,
-         ;; we just fetch the entire article.
-         (unless (gnus-check-backend-function
-                  (and (string-match "^gnus-" (symbol-name request-func))
-                       (intern (substring (symbol-name request-func)
-                                          (match-end 0))))
-                  gnus-newsgroup-name)
-           (setq ofunc request-func)
-           (setq request-func 'gnus-request-article))
-         (while articles
-           (setq article (mail-header-number (caar articles)))
-           (gnus-message 7 "Scoring on article %s of %s..." article last)
-           (when (funcall request-func article gnus-newsgroup-name)
+  (if gnus-agent-fetching
+      nil
+    (save-excursion
+      (setq gnus-scores-articles
+           (sort gnus-scores-articles
+                 (lambda (a1 a2)
+                   (< (mail-header-number (car a1))
+                      (mail-header-number (car a2))))))
+      (set-buffer nntp-server-buffer)
+      (save-restriction
+       (let* ((buffer-read-only nil)
+              (articles gnus-scores-articles)
+              (all-scores scores)
+              (request-func (cond ((string= "head" header)
+                                   'gnus-request-head)
+                                  ((string= "body" header)
+                                   'gnus-request-body)
+                                  (t 'gnus-request-article)))
+              entries alist ofunc article last)
+         (when articles
+           (setq last (mail-header-number (caar (last articles))))
+           ;; Not all backends support partial fetching.  In that case,
+           ;; we just fetch the entire article.
+           (unless (gnus-check-backend-function
+                    (and (string-match "^gnus-" (symbol-name request-func))
+                         (intern (substring (symbol-name request-func)
+                                            (match-end 0))))
+                    gnus-newsgroup-name)
+             (setq ofunc request-func)
+             (setq request-func 'gnus-request-article))
+           (while articles
+             (setq article (mail-header-number (caar articles)))
+             (gnus-message 7 "Scoring article %s of %s..." article last)
              (widen)
-             (goto-char (point-min))
-             ;; If just parts of the article is to be searched, but the
-             ;; backend didn't support partial fetching, we just narrow
-             ;; to the relevant parts.
-             (when ofunc
-               (if (eq ofunc 'gnus-request-head)
+             (when (funcall request-func article gnus-newsgroup-name)
+               (goto-char (point-min))
+               ;; If just parts of the article is to be searched, but the
+               ;; backend didn't support partial fetching, we just narrow
+               ;; to the relevant parts.
+               (when ofunc
+                 (if (eq ofunc 'gnus-request-head)
+                     (narrow-to-region
+                      (point)
+                      (or (search-forward "\n\n" nil t) (point-max)))
                    (narrow-to-region
-                    (point)
-                    (or (search-forward "\n\n" nil t) (point-max)))
-                 (narrow-to-region
-                  (or (search-forward "\n\n" nil t) (point))
-                  (point-max))))
-             (setq scores all-scores)
-             ;; Find matches.
-             (while scores
-               (setq alist (pop scores)
-                     entries (assoc header alist))
-               (while (cdr entries)    ;First entry is the header index.
-                 (let* ((rest (cdr entries))
-                        (kill (car rest))
-                        (match (nth 0 kill))
-                        (type (or (nth 3 kill) 's))
-                        (score (or (nth 1 kill)
-                                   gnus-score-interactive-default-score))
-                        (date (nth 2 kill))
-                        (found nil)
-                        (case-fold-search
-                         (not (or (eq type 'R) (eq type 'S)
-                                  (eq type 'Regexp) (eq type 'String))))
-                        (search-func
-                         (cond ((or (eq type 'r) (eq type 'R)
-                                    (eq type 'regexp) (eq type 'Regexp))
-                                're-search-forward)
-                               ((or (eq type 's) (eq type 'S)
-                                    (eq type 'string) (eq type 'String))
-                                'search-forward)
-                               (t
-                                (error "Illegal match type: %s" type)))))
-                   (goto-char (point-min))
-                   (when (funcall search-func match nil t)
-                     ;; Found a match, update scores.
-                     (setcdr (car articles) (+ score (cdar articles)))
-                     (setq found t)
-                     (when trace
-                       (push
-                        (cons (car-safe (rassq alist gnus-score-cache)) kill)
-                        gnus-score-trace)))
-                   ;; Update expire date
-                   (unless trace
-                     (cond
-                      ((null date))    ;Permanent entry.
-                      ((and found gnus-update-score-entry-dates)
-                       ;; Match, update date.
-                       (gnus-score-set 'touched '(t) alist)
-                       (setcar (nthcdr 2 kill) now))
-                      ((and expire (< date expire)) ;Old entry, remove.
-                       (gnus-score-set 'touched '(t) alist)
-                       (setcdr entries (cdr rest))
-                       (setq rest entries))))
-                   (setq entries rest)))))
-           (setq articles (cdr articles)))))))
-  nil)
+                    (or (search-forward "\n\n" nil t) (point))
+                    (point-max))))
+               (setq scores all-scores)
+               ;; Find matches.
+               (while scores
+                 (setq alist (pop scores)
+                       entries (assoc header alist))
+                 (while (cdr entries) ;First entry is the header index.
+                   (let* ((rest (cdr entries))
+                          (kill (car rest))
+                          (match (nth 0 kill))
+                          (type (or (nth 3 kill) 's))
+                          (score (or (nth 1 kill)
+                                     gnus-score-interactive-default-score))
+                          (date (nth 2 kill))
+                          (found nil)
+                          (case-fold-search
+                           (not (or (eq type 'R) (eq type 'S)
+                                    (eq type 'Regexp) (eq type 'String))))
+                          (search-func
+                           (cond ((or (eq type 'r) (eq type 'R)
+                                      (eq type 'regexp) (eq type 'Regexp))
+                                  're-search-forward)
+                                 ((or (eq type 's) (eq type 'S)
+                                      (eq type 'string) (eq type 'String))
+                                  'search-forward)
+                                 (t
+                                  (error "Invalid match type: %s" type)))))
+                     (goto-char (point-min))
+                     (when (funcall search-func match nil t)
+                       ;; Found a match, update scores.
+                       (setcdr (car articles) (+ score (cdar articles)))
+                       (setq found t)
+                       (when trace
+                         (push
+                          (cons (car-safe (rassq alist gnus-score-cache))
+                                kill)
+                          gnus-score-trace)))
+                     ;; Update expire date
+                     (unless trace
+                       (cond
+                        ((null date))  ;Permanent entry.
+                        ((and found gnus-update-score-entry-dates)
+                         ;; Match, update date.
+                         (gnus-score-set 'touched '(t) alist)
+                         (setcar (nthcdr 2 kill) now))
+                        ((and expire (< date expire)) ;Old entry, remove.
+                         (gnus-score-set 'touched '(t) alist)
+                         (setcdr entries (cdr rest))
+                         (setq rest entries))))
+                     (setq entries rest)))))
+             (setq articles (cdr articles)))))))
+    nil))
 
 (defun gnus-score-thread (scores header now expire &optional trace)
   (gnus-score-followup scores header now expire trace t))
 
 (defun gnus-score-followup (scores header now expire &optional trace thread)
-  ;; Insert the unique article headers in the buffer.
-  (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
-       (current-score-file gnus-current-score-file)
-       (all-scores scores)
-       ;; gnus-score-index is used as a free variable.
-       alike last this art entries alist articles
-       new news)
-
-    ;; Change score file to the adaptive score file.  All entries that
-    ;; this function makes will be put into this file.
-    (save-excursion
-      (set-buffer gnus-summary-buffer)
-      (gnus-score-load-file
-       (or gnus-newsgroup-adaptive-score-file
-          (gnus-score-file-name
-           gnus-newsgroup-name gnus-adaptive-file-suffix))))
+  (if gnus-agent-fetching
+      ;; FIXME: It seems doable in fetching mode.
+      nil
+    ;; Insert the unique article headers in the buffer.
+    (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
+         (current-score-file gnus-current-score-file)
+         (all-scores scores)
+         ;; gnus-score-index is used as a free variable.
+         alike last this art entries alist articles
+         new news)
+
+      ;; Change score file to the adaptive score file.  All entries that
+      ;; this function makes will be put into this file.
+      (save-excursion
+       (set-buffer gnus-summary-buffer)
+       (gnus-score-load-file
+        (or gnus-newsgroup-adaptive-score-file
+            (gnus-score-file-name
+             gnus-newsgroup-name gnus-adaptive-file-suffix))))
 
-    (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
-         articles gnus-scores-articles)
+      (setq gnus-scores-articles (sort gnus-scores-articles
+                                      'gnus-score-string<)
+           articles gnus-scores-articles)
 
-    (erase-buffer)
-    (while articles
-      (setq art (car articles)
-           this (aref (car art) gnus-score-index)
-           articles (cdr articles))
-      (if (equal last this)
-         (push art alike)
-       (when last
-         (insert last ?\n)
-         (put-text-property (1- (point)) (point) 'articles alike))
-       (setq alike (list art)
-             last this)))
-    (when last                         ; Bwadr, duplicate code.
-      (insert last ?\n)
-      (put-text-property (1- (point)) (point) 'articles alike))
-
-    ;; Find matches.
-    (while scores
-      (setq alist (car scores)
-           scores (cdr scores)
-           entries (assoc header alist))
-      (while (cdr entries)             ;First entry is the header index.
-       (let* ((rest (cdr entries))
-              (kill (car rest))
-              (match (nth 0 kill))
-              (type (or (nth 3 kill) 's))
-              (score (or (nth 1 kill) gnus-score-interactive-default-score))
-              (date (nth 2 kill))
-              (found nil)
-              (mt (aref (symbol-name type) 0))
-              (case-fold-search
-               (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F))))
-              (dmt (downcase mt))
-              (search-func
-               (cond ((= dmt ?r) 're-search-forward)
-                     ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
-                     (t (error "Illegal match type: %s" type))))
-              arts art)
-         (goto-char (point-min))
-         (if (= dmt ?e)
+      (erase-buffer)
+      (while articles
+       (setq art (car articles)
+             this (aref (car art) gnus-score-index)
+             articles (cdr articles))
+       (if (equal last this)
+           (push art alike)
+         (when last
+           (insert last ?\n)
+           (put-text-property (1- (point)) (point) 'articles alike))
+         (setq alike (list art)
+               last this)))
+      (when last                       ; Bwadr, duplicate code.
+       (insert last ?\n)
+       (put-text-property (1- (point)) (point) 'articles alike))
+
+      ;; Find matches.
+      (while scores
+       (setq alist (car scores)
+             scores (cdr scores)
+             entries (assoc header alist))
+       (while (cdr entries)            ;First entry is the header index.
+         (let* ((rest (cdr entries))
+                (kill (car rest))
+                (match (nth 0 kill))
+                (type (or (nth 3 kill) 's))
+                (score (or (nth 1 kill) gnus-score-interactive-default-score))
+                (date (nth 2 kill))
+                (found nil)
+                (mt (aref (symbol-name type) 0))
+                (case-fold-search
+                 (not (or (= mt ?R) (= mt ?S) (= mt ?E) (= mt ?F))))
+                (dmt (downcase mt))
+                (search-func
+                 (cond ((= dmt ?r) 're-search-forward)
+                       ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
+                       (t (error "Invalid match type: %s" type))))
+                arts art)
+           (goto-char (point-min))
+           (if (= dmt ?e)
+               (while (funcall search-func match nil t)
+                 (and (= (gnus-point-at-bol)
+                         (match-beginning 0))
+                      (= (progn (end-of-line) (point))
+                         (match-end 0))
+                      (progn
+                        (setq found (setq arts (get-text-property
+                                                (point) 'articles)))
+                        ;; Found a match, update scores.
+                        (while arts
+                          (setq art (car arts)
+                                arts (cdr arts))
+                          (gnus-score-add-followups
+                           (car art) score all-scores thread))))
+                 (end-of-line))
              (while (funcall search-func match nil t)
-               (and (= (progn (beginning-of-line) (point))
-                       (match-beginning 0))
-                    (= (progn (end-of-line) (point))
-                       (match-end 0))
-                    (progn
-                      (setq found (setq arts (get-text-property
-                                              (point) 'articles)))
-                      ;; Found a match, update scores.
-                      (while arts
-                        (setq art (car arts)
-                              arts (cdr arts))
-                        (gnus-score-add-followups
-                         (car art) score all-scores thread))))
-               (end-of-line))
-           (while (funcall search-func match nil t)
-             (end-of-line)
-             (setq found (setq arts (get-text-property (point) 'articles)))
-             ;; Found a match, update scores.
-             (while (setq art (pop arts))
-               (when (setq new (gnus-score-add-followups
-                                (car art) score all-scores thread))
-                 (push new news)))))
-         ;; Update expire date
-         (cond ((null date))           ;Permanent entry.
-               ((and found gnus-update-score-entry-dates) ;Match, update date.
-                (gnus-score-set 'touched '(t) alist)
-                (setcar (nthcdr 2 kill) now))
-               ((and expire (< date expire)) ;Old entry, remove.
-                (gnus-score-set 'touched '(t) alist)
-                (setcdr entries (cdr rest))
-                (setq rest entries)))
-         (setq entries rest))))
-    ;; We change the score file back to the previous one.
-    (save-excursion
-      (set-buffer gnus-summary-buffer)
-      (gnus-score-load-file current-score-file))
-    (list (cons "references" news))))
+               (end-of-line)
+               (setq found (setq arts (get-text-property (point) 'articles)))
+               ;; Found a match, update scores.
+               (while (setq art (pop arts))
+                 (setcdr art (+ score (cdr art)))
+                 (when trace
+                   (push (cons
+                          (car-safe (rassq alist gnus-score-cache))
+                          kill)
+                         gnus-score-trace))
+                 (when (setq new (gnus-score-add-followups
+                                  (car art) score all-scores thread))
+                   (push new news)))))
+           ;; Update expire date
+           (cond ((null date))         ;Permanent entry.
+                 ((and found gnus-update-score-entry-dates)
+                  ;Match, update date.
+                  (gnus-score-set 'touched '(t) alist)
+                  (setcar (nthcdr 2 kill) now))
+                 ((and expire (< date expire)) ;Old entry, remove.
+                  (gnus-score-set 'touched '(t) alist)
+                  (setcdr entries (cdr rest))
+                  (setq rest entries)))
+           (setq entries rest))))
+      ;; We change the score file back to the previous one.
+      (save-excursion
+       (set-buffer gnus-summary-buffer)
+       (gnus-score-load-file current-score-file))
+      (list (cons "references" news)))))
 
 (defun gnus-score-add-followups (header score scores &optional thread)
   "Add a score entry to the adapt file."
@@ -1850,8 +1956,8 @@ SCORE is the score to add."
   ;; Insert the unique article headers in the buffer.
   (let ((gnus-score-index (nth 1 (assoc header gnus-header-index)))
        ;; gnus-score-index is used as a free variable.
-        (simplify (and gnus-score-thread-simplify
-                       (string= "subject" header)))
+       (simplify (and gnus-score-thread-simplify
+                      (string= "subject" header)))
        alike last this art entries alist articles
        fuzzies arts words kill)
 
@@ -1861,14 +1967,25 @@ SCORE is the score to add."
     ;; and U is the number of unique headers.  It is assumed (but
     ;; untested) this will be a net win because of the large constant
     ;; factor involved with string matching.
-    (setq gnus-scores-articles (sort gnus-scores-articles 'gnus-score-string<)
+    (setq gnus-scores-articles
+         ;; We cannot string-sort the extra headers list.  *sigh*
+         (if (= gnus-score-index 9)
+             gnus-scores-articles
+           (sort gnus-scores-articles 'gnus-score-string<))
          articles gnus-scores-articles)
 
     (erase-buffer)
     (while (setq art (pop articles))
       (setq this (aref (car art) gnus-score-index))
+
+      ;; If we're working with non-standard headers, we are stuck
+      ;; with working on them as a group.  What a hassle.
+      ;; Just wait 'til you see what horrors we commit against `match'...
+      (if (= gnus-score-index 9)
+         (setq this (gnus-prin1-to-string this))) ; ick.
+
       (if simplify
-        (setq this (gnus-map-function gnus-simplify-subject-functions this)))
+         (setq this (gnus-map-function gnus-simplify-subject-functions this)))
       (if (equal last this)
          ;; O(N*H) cons-cells used here, where H is the number of
          ;; headers.
@@ -1897,28 +2014,38 @@ SCORE is the score to add."
               (type (or (nth 3 kill) 's))
               (score (or (nth 1 kill) gnus-score-interactive-default-score))
               (date (nth 2 kill))
+              (extra (nth 4 kill))     ; non-standard header; string.
               (found nil)
               (mt (aref (symbol-name type) 0))
               (case-fold-search (not (memq mt '(?R ?S ?E ?F))))
               (dmt (downcase mt))
-               ; Assume user already simplified regexp and fuzzies
+              ;; Assume user already simplified regexp and fuzzies
               (match (if (and simplify (not (memq dmt '(?f ?r))))
-                          (gnus-map-function
-                           gnus-simplify-subject-functions
-                           (nth 0 kill))
-                        (nth 0 kill)))
+                         (gnus-map-function
+                          gnus-simplify-subject-functions
+                          (nth 0 kill))
+                       (nth 0 kill)))
               (search-func
                (cond ((= dmt ?r) 're-search-forward)
                      ((or (= dmt ?e) (= dmt ?s) (= dmt ?f)) 'search-forward)
                      ((= dmt ?w) nil)
-                     (t (error "Illegal match type: %s" type)))))
+                     (t (error "Invalid match type: %s" type)))))
+
+         ;; Evil hackery to make match usable in non-standard headers.
+         (when extra
+           (setq match (concat "[ (](" extra " \\. \"[^)]*"
+                               match "[^\"]*\")[ )]")
+                 search-func 're-search-forward)) ; XXX danger?!?
+
          (cond
           ;; Fuzzy matches.  We save these for later.
           ((= dmt ?f)
-           (push (cons entries alist) fuzzies))
+           (push (cons entries alist) fuzzies)
+           (setq entries (cdr entries)))
           ;; Word matches.  Save these for even later.
           ((= dmt ?w)
-           (push (cons entries alist) words))
+           (push (cons entries alist) words)
+           (setq entries (cdr entries)))
           ;; Exact matches.
           ((= dmt ?e)
            ;; Do exact matching.
@@ -1943,7 +2070,26 @@ SCORE is the score to add."
                            gnus-score-trace))
                       (while (setq art (pop arts))
                         (setcdr art (+ score (cdr art)))))))
-             (forward-line 1)))
+             (forward-line 1))
+           ;; Update expiry date
+           (if trace
+               (setq entries (cdr entries))
+             (cond
+              ;; Permanent entry.
+              ((null date)
+               (setq entries (cdr entries)))
+              ;; We have a match, so we update the date.
+              ((and found gnus-update-score-entry-dates)
+               (gnus-score-set 'touched '(t) alist)
+               (setcar (nthcdr 2 kill) now)
+               (setq entries (cdr entries)))
+              ;; This entry has expired, so we remove it.
+              ((and expire (< date expire))
+               (gnus-score-set 'touched '(t) alist)
+               (setcdr entries (cddr entries)))
+              ;; No match; go to next entry.
+              (t
+               (setq entries (cdr entries))))))
           ;; Regexp and substring matching.
           (t
            (goto-char (point-min))
@@ -1962,26 +2108,26 @@ SCORE is the score to add."
                          gnus-score-trace))
                (while (setq art (pop arts))
                  (setcdr art (+ score (cdr art)))))
-             (forward-line 1))))
-         ;; Update expiry date
-         (if trace
-             (setq entries (cdr entries))
-           (cond
-            ;; Permanent entry.
-            ((null date)
-             (setq entries (cdr entries)))
-            ;; We have a match, so we update the date.
-            ((and found gnus-update-score-entry-dates)
-             (gnus-score-set 'touched '(t) alist)
-             (setcar (nthcdr 2 kill) now)
-             (setq entries (cdr entries)))
-            ;; This entry has expired, so we remove it.
-            ((and expire (< date expire))
-             (gnus-score-set 'touched '(t) alist)
-             (setcdr entries (cddr entries)))
-            ;; No match; go to next entry.
-            (t
-             (setq entries (cdr entries))))))))
+             (forward-line 1))
+           ;; Update expiry date
+           (if trace
+               (setq entries (cdr entries))
+             (cond
+              ;; Permanent entry.
+              ((null date)
+               (setq entries (cdr entries)))
+              ;; We have a match, so we update the date.
+              ((and found gnus-update-score-entry-dates)
+               (gnus-score-set 'touched '(t) alist)
+               (setcar (nthcdr 2 kill) now)
+               (setq entries (cdr entries)))
+              ;; This entry has expired, so we remove it.
+              ((and expire (< date expire))
+               (gnus-score-set 'touched '(t) alist)
+               (setcdr entries (cddr entries)))
+              ;; No match; go to next entry.
+              (t
+               (setq entries (cdr entries))))))))))
 
     ;; Find fuzzy matches.
     (when fuzzies
@@ -2013,18 +2159,20 @@ SCORE is the score to add."
                  (setcdr art (+ score (cdr art))))))
            (forward-line 1))
          ;; Update expiry date
-         (cond
-          ;; Permanent.
-          ((null date)
-           )
-          ;; Match, update date.
-          ((and found gnus-update-score-entry-dates)
-           (gnus-score-set 'touched '(t) (cdar fuzzies))
-           (setcar (nthcdr 2 kill) now))
-          ;; Old entry, remove.
-          ((and expire (< date expire))
-           (gnus-score-set 'touched '(t) (cdar fuzzies))
-           (setcdr (caar fuzzies) (cddaar fuzzies))))
+         (if (not trace)
+             (cond
+              ;; Permanent.
+              ((null date)
+               ;; Do nothing.
+               )
+              ;; Match, update date.
+              ((and found gnus-update-score-entry-dates)
+               (gnus-score-set 'touched '(t) (cdar fuzzies))
+               (setcar (nthcdr 2 kill) now))
+              ;; Old entry, remove.
+              ((and expire (< date expire))
+               (gnus-score-set 'touched '(t) (cdar fuzzies))
+               (setcdr (caar fuzzies) (cddaar fuzzies)))))
          (setq fuzzies (cdr fuzzies)))))
 
     (when words
@@ -2050,18 +2198,20 @@ SCORE is the score to add."
                (while (setq art (pop arts))
                  (setcdr art (+ score (cdr art))))))
            ;; Update expiry date
-           (cond
-            ;; Permanent.
-            ((null date)
-             )
-            ;; Match, update date.
-            ((and found gnus-update-score-entry-dates)
-             (gnus-score-set 'touched '(t) (cdar words))
-             (setcar (nthcdr 2 kill) now))
-            ;; Old entry, remove.
-            ((and expire (< date expire))
-             (gnus-score-set 'touched '(t) (cdar words))
-             (setcdr (caar words) (cddaar words))))
+           (if (not trace)
+               (cond
+                ;; Permanent.
+                ((null date)
+                 ;; Do nothing.
+                 )
+                ;; Match, update date.
+                ((and found gnus-update-score-entry-dates)
+                 (gnus-score-set 'touched '(t) (cdar words))
+                 (setcar (nthcdr 2 kill) now))
+                ;; Old entry, remove.
+                ((and expire (< date expire))
+                 (gnus-score-set 'touched '(t) (cdar words))
+                 (setcdr (caar words) (cddaar words)))))
            (setq words (cdr words))))))
     nil))
 
@@ -2087,6 +2237,10 @@ SCORE is the score to add."
       (set-syntax-table syntab))
     ;; Make all the ignorable words ignored.
     (let ((ignored (append gnus-ignored-adaptive-words
+                          (if gnus-adaptive-word-no-group-words
+                              (message-tokenize-header
+                               (gnus-group-real-name gnus-newsgroup-name)
+                               "."))
                           gnus-default-ignored-adaptive-words)))
       (while ignored
        (gnus-sethash (pop ignored) nil hashtb)))))
@@ -2179,9 +2333,9 @@ SCORE is the score to add."
     ;; Perform adaptive word scoring.
     (when (and (listp gnus-newsgroup-adaptive)
               (memq 'word gnus-newsgroup-adaptive))
-      (nnheader-temp-write nil
+      (with-temp-buffer
        (let* ((hashtb (gnus-make-hashtable 1000))
-              (date (gnus-day-number (current-time-string)))
+              (date (date-to-day (current-time-string)))
               (data gnus-newsgroup-data)
               (syntab (syntax-table))
               word d score val)
@@ -2206,15 +2360,23 @@ SCORE is the score to add."
                      ;; Put the word and score into the hashtb.
                      (setq val (gnus-gethash (setq word (match-string 0))
                                              hashtb))
-                     (setq val (+ score (or val 0)))
-                     (if (and gnus-adaptive-word-minimum
-                              (< val gnus-adaptive-word-minimum))
-                         (setq val gnus-adaptive-word-minimum))
-                     (gnus-sethash word val hashtb))
+                     (when (or (not gnus-adaptive-word-length-limit)
+                               (> (length word)
+                                  gnus-adaptive-word-length-limit))
+                       (setq val (+ score (or val 0)))
+                       (if (and gnus-adaptive-word-minimum
+                                (< val gnus-adaptive-word-minimum))
+                           (setq val gnus-adaptive-word-minimum))
+                       (gnus-sethash word val hashtb)))
                    (erase-buffer))))
            (set-syntax-table syntab))
          ;; Make all the ignorable words ignored.
          (let ((ignored (append gnus-ignored-adaptive-words
+                                (if gnus-adaptive-word-no-group-words
+                                    (message-tokenize-header
+                                     (gnus-group-real-name
+                                      gnus-newsgroup-name)
+                                     "."))
                                 gnus-default-ignored-adaptive-words)))
            (while ignored
              (gnus-sethash (pop ignored) nil hashtb)))
@@ -2244,7 +2406,10 @@ SCORE is the score to add."
     (let ((gnus-newsgroup-headers
           (list (gnus-summary-article-header)))
          (gnus-newsgroup-scored nil)
-         trace)
+         ;; Must be synced with `gnus-score-edit-file-at-point':
+         (frmt "%S [%s] -> %s\n")
+         trace
+         file)
       (save-excursion
        (nnheader-set-temp-buffer "*Score Trace*"))
       (setq gnus-score-trace nil)
@@ -2254,13 +2419,44 @@ SCORE is the score to add."
           1 "No score rules apply to the current article (default score %d)."
           gnus-summary-default-score)
        (set-buffer "*Score Trace*")
-       (gnus-add-current-to-buffer-list)
-       (while trace
-         (insert (format "%S  ->  %s\n" (cdar trace)
-                         (if (caar trace)
-                             (file-name-nondirectory (caar trace))
-                           "(non-file rule)")))
-         (setq trace (cdr trace)))
+       ;; Use a keymap instead?
+       (local-set-key "q"
+                      (lambda ()
+                        (interactive)
+                        (bury-buffer nil)
+                        (gnus-summary-expand-window)))
+       (local-set-key "e" (lambda ()
+                            "Run `gnus-score-edit-file-at-point'."
+                            (interactive)
+                            (gnus-score-edit-file-at-point)))
+       (local-set-key "f" (lambda ()
+                            "Run `gnus-score-edit-file-at-point'."
+                            (interactive)
+                            (gnus-score-edit-file-at-point 'format)))
+       (local-set-key "t" 'toggle-truncate-lines)
+       (setq truncate-lines t)
+       (dolist (entry trace)
+         (setq file (or (car entry)
+                        ;; Must be synced with
+                        ;; `gnus-score-edit-file-at-point':
+                        "(non-file rule)"))
+         (insert
+          (format frmt
+                  (cdr entry)
+                  ;; Don't use `file-name-sans-extension' to see .SCORE and
+                  ;; .ADAPT directly:
+                  (file-name-nondirectory file)
+                  (abbreviate-file-name file))))
+       (insert
+        "\n\nQuick help:
+
+Type `e' to edit score file corresponding to the score rule on current line,
+`f' to format (pretty print) the score file and edit it,
+`t' toggle to truncate long lines in this buffer,
+`q' to quit.
+
+The first sexp on each line is the score rule, followed by the file name of
+the score file and its full name, including the directory.")
        (goto-char (point-min))
        (gnus-configure-windows 'score-trace)))
     (set-buffer gnus-summary-buffer)
@@ -2300,7 +2496,6 @@ SCORE is the score to add."
       (while rules
        (insert (format "%-5d: %s\n" (caar rules) (cdar rules)))
        (pop rules))
-      (gnus-add-current-to-buffer-list)
       (goto-char (point-min))
       (gnus-configure-windows 'score-words))))
 
@@ -2353,14 +2548,14 @@ SCORE is the score to add."
       (gnus-summary-raise-score score))
     (gnus-summary-next-subject 1 t)))
 
-(defun gnus-score-default (level)
+(defun gnus-score-delta-default (level)
   (if level (prefix-numeric-value level)
     gnus-score-interactive-default-score))
 
 (defun gnus-summary-raise-thread (&optional score)
   "Raise the score of the articles in the current thread with SCORE."
   (interactive "P")
-  (setq score (gnus-score-default score))
+  (setq score (gnus-score-delta-default score))
   (let (e)
     (save-excursion
       (let ((articles (gnus-summary-articles-in-thread)))
@@ -2389,7 +2584,7 @@ SCORE is the score to add."
 (defun gnus-summary-lower-thread (&optional score)
   "Lower score of articles in the current thread with SCORE."
   (interactive "P")
-  (gnus-summary-raise-thread (- (1- (gnus-score-default score)))))
+  (gnus-summary-raise-thread (- (gnus-score-delta-default score))))
 
 ;;; Finding score files.
 
@@ -2438,8 +2633,8 @@ SCORE is the score to add."
        seen out file)
     (while (setq file (pop files))
       (cond
-       ;; Ignore "." and "..".
-       ((member (file-name-nondirectory file) '("." ".."))
+       ;; Ignore files that start with a dot.
+       ((string-match "^\\." (file-name-nondirectory file))
        nil)
        ;; Add subtrees of directory to also be searched.
        ((and (file-directory-p file)
@@ -2451,7 +2646,8 @@ SCORE is the score to add."
        (push file out))))
     (or out
        ;; Return a dummy value.
-       (list "~/News/this.file.does.not.exist.SCORE"))))
+       (list (expand-file-name "this.file.does.not.exist.SCORE"
+                               gnus-kill-files-directory)))))
 
 (defun gnus-score-file-regexp ()
   "Return a regexp that match all score files."
@@ -2469,10 +2665,11 @@ GROUP using BNews sys file syntax."
         (klen (length kill-dir))
         (score-regexp (gnus-score-file-regexp))
         (trans (cdr (assq ?: nnheader-file-name-translation-alist)))
+        (group-trans (nnheader-translate-file-chars group t))
         ofiles not-match regexp)
     (save-excursion
-      (set-buffer (get-buffer-create "*gnus score files*"))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (gnus-get-buffer-create "*gnus score files*"))
+      (buffer-disable-undo)
       ;; Go through all score file names and create regexp with them
       ;; as the source.
       (while sfiles
@@ -2488,12 +2685,14 @@ GROUP using BNews sys file syntax."
              ;; too much.
              (delete-char (min (1- (point-max)) klen))
            (goto-char (point-max))
-           (search-backward "/")
-           (delete-region (1+ (point)) (point-min)))
+           (if (re-search-backward gnus-directory-sep-char-regexp nil t)
+               (delete-region (1+ (point)) (point-min))
+             (gnus-message 1 "Can't find directory separator in %s"
+                           (car sfiles))))
          ;; If short file names were used, we have to translate slashes.
          (goto-char (point-min))
          (let ((regexp (concat
-                        "[/:" (if trans (char-to-string trans) "") "]")))
+                        "[/:" (if trans (char-to-string trans)) "]")))
            (while (re-search-forward regexp nil t)
              (replace-match "." t t)))
          ;; Kludge to get rid of "nntp+" problems.
@@ -2515,19 +2714,21 @@ GROUP using BNews sys file syntax."
          (if (looking-at "not.")
              (progn
                (setq not-match t)
-               (setq regexp (concat "^" (buffer-substring 5 (point-max)) "$")))
+               (setq regexp
+                     (concat "^" (buffer-substring 5 (point-max)) "$")))
            (setq regexp (concat "^" (buffer-substring 1 (point-max)) "$"))
            (setq not-match nil))
          ;; Finally - if this resulting regexp matches the group name,
          ;; we add this score file to the list of score files
          ;; applicable to this group.
          (when (or (and not-match
-                        (not (string-match regexp group)))
+                        (ignore-errors
+                          (not (string-match regexp group-trans))))
                    (and (not not-match)
-                        (string-match regexp group)))
+                        (ignore-errors (string-match regexp group-trans))))
            (push (car sfiles) ofiles)))
        (setq sfiles (cdr sfiles)))
-      (kill-buffer (current-buffer))
+      (gnus-kill-buffer (current-buffer))
       ;; Slight kludge here - the last score file returned should be
       ;; the local score file, whether it exists or not.  This is so
       ;; that any score commands the user enters will go to the right
@@ -2592,7 +2793,7 @@ Destroys the current buffer."
 
 (defun gnus-sort-score-files (files)
   "Sort FILES so that the most general files come first."
-  (nnheader-temp-write nil
+  (with-temp-buffer
     (let ((alist
           (mapcar
            (lambda (file)
@@ -2604,7 +2805,7 @@ Destroys the current buffer."
 
 (defun gnus-score-find-alist (group)
   "Return list of score files for GROUP.
-The list is determined from the variable gnus-score-file-alist."
+The list is determined from the variable `gnus-score-file-alist'."
   (let ((alist gnus-score-file-multiple-match-alist)
        score-files)
     ;; if this group has been seen before, return the cached entry
@@ -2642,34 +2843,37 @@ The list is determined from the variable gnus-score-file-alist."
       (and funcs
           (not (listp funcs))
           (setq funcs (list funcs)))
-      ;; Get the initial score files for this group.
-      (when funcs
-       (setq score-files (nreverse (gnus-score-find-alist group))))
-      ;; Add any home adapt files.
-      (let ((home (gnus-home-score-file group t)))
-       (when home
-         (push home score-files)
-         (setq gnus-newsgroup-adaptive-score-file home)))
-      ;; Check whether there is a `adapt-file' group parameter.
-      (let ((param-file (gnus-group-find-parameter group 'adapt-file)))
-       (when param-file
-         (push param-file score-files)
-         (setq gnus-newsgroup-adaptive-score-file param-file)))
+      (when gnus-score-use-all-scores
+       ;; Get the initial score files for this group.
+       (when funcs
+         (setq score-files (nreverse (gnus-score-find-alist group))))
+       ;; Add any home adapt files.
+       (let ((home (gnus-home-score-file group t)))
+         (when home
+           (push home score-files)
+           (setq gnus-newsgroup-adaptive-score-file home)))
+       ;; Check whether there is a `adapt-file' group parameter.
+       (let ((param-file (gnus-group-find-parameter group 'adapt-file)))
+         (when param-file
+           (push param-file score-files)
+           (setq gnus-newsgroup-adaptive-score-file param-file))))
       ;; Go through all the functions for finding score files (or actual
       ;; scores) and add them to a list.
       (while funcs
-       (when (gnus-functionp (car funcs))
+       (when (functionp (car funcs))
          (setq score-files
-               (nconc score-files (nreverse (funcall (car funcs) group)))))
+               (append score-files
+                       (nreverse (funcall (car funcs) group)))))
        (setq funcs (cdr funcs)))
-      ;; Add any home score files.
-      (let ((home (gnus-home-score-file group)))
-       (when home
-         (push home score-files)))
-      ;; Check whether there is a `score-file' group parameter.
-      (let ((param-file (gnus-group-find-parameter group 'score-file)))
-       (when param-file
-         (push param-file score-files)))
+      (when gnus-score-use-all-scores
+       ;; Add any home score files.
+       (let ((home (gnus-home-score-file group)))
+         (when home
+           (push home score-files)))
+       ;; Check whether there is a `score-file' group parameter.
+       (let ((param-file (gnus-group-find-parameter group 'score-file)))
+         (when param-file
+           (push param-file score-files))))
       ;; Expand all files names.
       (let ((files score-files))
        (while files
@@ -2723,7 +2927,8 @@ The list is determined from the variable gnus-score-file-alist."
   (interactive (list gnus-global-score-files))
   (let (out)
     (while files
-      (if (string-match "/$" (car files))
+      ;; #### /$ Unix-specific?
+      (if (file-directory-p (car files))
          (setq out (nconc (directory-files
                            (car files) t
                            (concat (gnus-score-file-regexp) "$"))))
@@ -2758,14 +2963,17 @@ If ADAPT, return the home adaptive file instead."
             ((stringp elem)
              elem)
             ;; Function.
-            ((gnus-functionp elem)
+            ((functionp elem)
              (funcall elem group))
-            ;; Regexp-file cons
+            ;; Regexp-file cons.
             ((consp elem)
-             (when (string-match (car elem) group)
-               (cadr elem))))))
+             (when (string-match (gnus-globalify-regexp (car elem)) group)
+               (replace-match (cadr elem) t nil group))))))
     (when found
-      (nnheader-concat gnus-kill-files-directory found))))
+      (setq found (nnheader-translate-file-chars found))
+      (if (file-name-absolute-p found)
+         found
+       (nnheader-concat gnus-kill-files-directory found)))))
 
 (defun gnus-hierarchial-home-score-file (group)
   "Return the score file of the top-level hierarchy of GROUP."
@@ -2783,23 +2991,33 @@ If ADAPT, return the home adaptive file instead."
     (concat group (if (gnus-use-long-file-name 'not-score) "." "/")
            gnus-adaptive-file-suffix)))
 
+(defun gnus-current-home-score-file (group)
+  "Return the \"current\" regular score file."
+  (car (nreverse (gnus-score-find-alist group))))
+
 ;;;
 ;;; Score decays
 ;;;
 
 (defun gnus-decay-score (score)
   "Decay SCORE according to `gnus-score-decay-constant' and `gnus-score-decay-scale'."
-  (floor
-   (- score
-      (* (if (< score 0) -1 1)
-        (min (abs score)
-             (max gnus-score-decay-constant
-                  (* (abs score)
-                     gnus-score-decay-scale)))))))
+  (let ((n (- score
+             (* (if (< score 0) -1 1)
+                (min (abs score)
+                     (max gnus-score-decay-constant
+                          (* (abs score)
+                             gnus-score-decay-scale)))))))
+    (if (and (featurep 'xemacs)
+            ;; XEmacs' floor can handle only the floating point
+            ;; number below the half of the maximum integer.
+            (> (abs n) (lsh -1 -2)))
+       (string-to-number
+        (car (split-string (number-to-string n) "\\.")))
+      (floor n))))
 
 (defun gnus-decay-scores (alist day)
   "Decay non-permanent scores in ALIST."
-  (let ((times (- (gnus-time-to-day (current-time)) day))
+  (let ((times (- (time-to-days (current-time)) day))
        kill entry updated score n)
     (unless (zerop times)              ;Done decays today already?
       (while (setq entry (pop alist))
@@ -2813,7 +3031,7 @@ If ADAPT, return the home adaptive file instead."
                    n times)
              (while (natnump (decf n))
                (setq score (funcall gnus-decay-score-function score)))
-             (setcdr kill (cons score 
+             (setcdr kill (cons score
                                 (cdr (cdr kill)))))))))
     ;; Return whether this score file needs to be saved.  By Je-haysuss!
     updated))
@@ -2828,7 +3046,7 @@ In the `new' case, the string is a safe replacement for REGEXP.
 In the `bad' case, the string is a unsafe subexpression of REGEXP,
 and we do not have a simple replacement to suggest.
 
-See `(Gnus)Scoring Tips' for examples of good regular expressions."
+See Info node `(gnus)Scoring Tips' for examples of good regular expressions."
   (let (case-fold-search)
     (and
      ;; First, try a relatively fast necessary condition.
@@ -2872,8 +3090,7 @@ See `(Gnus)Scoring Tips' for examples of good regular expressions."
        (cond
        (bad (cons 'bad bad))
        (new (cons 'new new))
-       ;; or nil
-       )))))
+       (t nil))))))
 
 (provide 'gnus-score)
 
index ae9909b..7ad8883 100644 (file)
@@ -1,5 +1,7 @@
 ;;; gnus-setup.el --- Initialization & Setup for Gnus 5
-;; Copyright (C) 1995, 96 Free Software Foundation, Inc.
+
+;; Copyright (C) 1995, 1996, 2000, 2001
+;;        Free Software Foundation, Inc.
 
 ;; Author: Steven L. Baur <steve@miranova.com>
 ;; Keywords: news
 
 (eval-when-compile (require 'cl))
 
-(defvar running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
-
 (defvar gnus-use-installed-gnus t
-  "*If non-nil Use installed version of Gnus.")
-
-(defvar gnus-use-installed-tm running-xemacs
-  "*If non-nil use installed version of tm.")
+  "*If non-nil use installed version of Gnus.")
 
-(defvar gnus-use-installed-mailcrypt running-xemacs
+(defvar gnus-use-installed-mailcrypt (featurep 'xemacs)
   "*If non-nil use installed version of mailcrypt.")
 
-(defvar gnus-emacs-lisp-directory (if running-xemacs
+(defvar gnus-emacs-lisp-directory (if (featurep 'xemacs)
                                      "/usr/local/lib/xemacs/"
                                    "/usr/local/share/emacs/")
   "Directory where Emacs site lisp is located.")
 
 (defvar gnus-gnus-lisp-directory (concat gnus-emacs-lisp-directory
-                                        "gnus-5.0.15/lisp/")
+                                        "gnus/lisp/")
   "Directory where Gnus Emacs lisp is found.")
 
-(defvar gnus-tm-lisp-directory (concat gnus-emacs-lisp-directory
-                                      "site-lisp/")
-  "Directory where TM Emacs lisp is found.")
-
 (defvar gnus-mailcrypt-lisp-directory (concat gnus-emacs-lisp-directory
-                                             "site-lisp/mailcrypt-3.4/")
+                                             "site-lisp/mailcrypt/")
   "Directory where Mailcrypt Emacs Lisp is found.")
 
 (defvar gnus-bbdb-lisp-directory (concat gnus-emacs-lisp-directory
-                                        "site-lisp/bbdb-1.51/")
+                                        "site-lisp/bbdb/")
   "Directory where Big Brother Database is found.")
 
-(defvar gnus-use-tm running-xemacs
-  "Set this if you want MIME support for Gnus")
 (defvar gnus-use-mhe nil
-  "Set this if you want to use MH-E for mail reading")
+  "Set this if you want to use MH-E for mail reading.")
 (defvar gnus-use-rmail nil
-  "Set this if you want to use RMAIL for mail reading")
+  "Set this if you want to use RMAIL for mail reading.")
 (defvar gnus-use-sendmail t
-  "Set this if you want to use SENDMAIL for mail reading")
+  "Set this if you want to use SENDMAIL for mail reading.")
 (defvar gnus-use-vm nil
-  "Set this if you want to use the VM package for mail reading")
+  "Set this if you want to use the VM package for mail reading.")
 (defvar gnus-use-sc nil
-  "Set this if you want to use Supercite")
+  "Set this if you want to use Supercite.")
 (defvar gnus-use-mailcrypt t
-  "Set this if you want to use Mailcrypt for dealing with PGP messages")
+  "Set this if you want to use Mailcrypt for dealing with PGP messages.")
 (defvar gnus-use-bbdb nil
-  "Set this if you want to use the Big Brother DataBase")
+  "Set this if you want to use the Big Brother DataBase.")
 
 (when (and (not gnus-use-installed-gnus)
           (null (member gnus-gnus-lisp-directory load-path)))
 ;;; We can't do this until we know where Gnus is.
 (require 'message)
 
-;;; Tools for MIME by
-;;; UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
-;;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
-
-(when gnus-use-tm
-  (when (and (not gnus-use-installed-tm)
-            (null (member gnus-tm-lisp-directory load-path)))
-    (setq load-path (cons gnus-tm-lisp-directory load-path)))
-  ;; tm may or may not be dumped with XEmacs.  In Sunpro it is, otherwise
-  ;; it isn't.
-  (unless (featurep 'mime-setup)
-    (load "mime-setup")))
-
 ;;; Mailcrypt by
 ;;; Jin Choi <jin@atype.com>
 ;;; Patrick LoPresti <patl@lcs.mit.edu>
     (setq load-path (cons gnus-mailcrypt-lisp-directory load-path)))
   (autoload 'mc-install-write-mode "mailcrypt" nil t)
   (autoload 'mc-install-read-mode "mailcrypt" nil t)
-  (add-hook 'message-mode-hook 'mc-install-write-mode)
-  (add-hook 'gnus-summary-mode-hook 'mc-install-read-mode)
+;;;   (add-hook 'message-mode-hook 'mc-install-write-mode)
+;;;   (add-hook 'gnus-summary-mode-hook 'mc-install-read-mode)
   (when gnus-use-mhe
     (add-hook 'mh-folder-mode-hook 'mc-install-read-mode)
     (add-hook 'mh-letter-mode-hook 'mc-install-write-mode)))
diff --git a/lisp/gnus-sieve.el b/lisp/gnus-sieve.el
new file mode 100644 (file)
index 0000000..824e66c
--- /dev/null
@@ -0,0 +1,239 @@
+;;; gnus-sieve.el --- Utilities to manage sieve scripts for Gnus
+;; Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: NAGY Andras <nagya@inf.elte.hu>,
+;;     Simon Josefsson <simon@josefsson.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Gnus glue to generate complete Sieve scripts from Gnus Group
+;; Parameters with "if" test predicates.
+
+;;; Code:
+
+(require 'gnus)
+(require 'gnus-sum)
+(require 'format-spec)
+(autoload 'sieve-mode "sieve-mode")
+(eval-when-compile
+  (require 'sieve))
+
+;; Variables
+
+(defgroup gnus-sieve nil
+  "Manage sieve scripts in Gnus."
+  :group 'gnus)
+
+(defcustom gnus-sieve-file "~/.sieve"
+  "Path to your Sieve script."
+  :type 'file
+  :group 'gnus-sieve)
+
+(defcustom gnus-sieve-region-start "\n## Begin Gnus Sieve Script\n"
+  "Line indicating the start of the autogenerated region in
+your Sieve script."
+  :type 'string
+  :group 'gnus-sieve)
+
+(defcustom gnus-sieve-region-end "\n## End Gnus Sieve Script\n"
+  "Line indicating the end of the autogenerated region in
+your Sieve script."
+  :type 'string
+  :group 'gnus-sieve)
+
+(defcustom gnus-sieve-select-method nil
+  "Which select method we generate the Sieve script for.
+
+For example: \"nnimap:mailbox\""
+  :group 'gnus-sieve)
+
+(defcustom gnus-sieve-crosspost t
+  "Whether the generated Sieve script should do crossposting."
+  :type 'boolean
+  :group 'gnus-sieve)
+
+(defcustom gnus-sieve-update-shell-command "echo put %f | sieveshell %s"
+  "Shell command to execute after updating your Sieve script.  The following
+formatting characters are recognized:
+
+%f    Script's file name (gnus-sieve-file)
+%s    Server name (from gnus-sieve-select-method)"
+  :type 'string
+  :group 'gnus-sieve)
+
+;;;###autoload
+(defun gnus-sieve-update ()
+  "Update the Sieve script in gnus-sieve-file, by replacing the region
+between gnus-sieve-region-start and gnus-sieve-region-end with
+\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost\), then
+execute gnus-sieve-update-shell-command.
+See the documentation for these variables and functions for details."
+  (interactive)
+  (gnus-sieve-generate)
+  (save-buffer)
+  (shell-command
+   (format-spec gnus-sieve-update-shell-command
+               (format-spec-make ?f gnus-sieve-file
+                                 ?s (or (cadr (gnus-server-get-method
+                                               nil gnus-sieve-select-method))
+                                        "")))))
+
+;;;###autoload
+(defun gnus-sieve-generate ()
+  "Generate the Sieve script in gnus-sieve-file, by replacing the region
+between gnus-sieve-region-start and gnus-sieve-region-end with
+\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost\).
+See the documentation for these variables and functions for details."
+  (interactive)
+  (require 'sieve)
+  (find-file gnus-sieve-file)
+  (goto-char (point-min))
+  (if (re-search-forward (regexp-quote gnus-sieve-region-start) nil t)
+      (delete-region (match-end 0)
+                    (or (re-search-forward (regexp-quote
+                                            gnus-sieve-region-end) nil t)
+                        (point)))
+    (insert sieve-template))
+  (insert gnus-sieve-region-start
+         (gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost)
+         gnus-sieve-region-end))
+
+(defun gnus-sieve-guess-rule-for-article ()
+  "Guess a sieve rule based on RFC822 article in buffer.
+Return nil if no rule could be guessed."
+  (when (message-fetch-field "sender")
+    `(sieve address "sender" ,(message-fetch-field "sender"))))
+
+;;;###autoload
+(defun gnus-sieve-article-add-rule ()
+  (interactive)
+  (gnus-summary-select-article nil 'force)
+  (with-current-buffer gnus-original-article-buffer
+    (let ((rule (gnus-sieve-guess-rule-for-article))
+         (info (gnus-get-info gnus-newsgroup-name)))
+      (if (null rule)
+         (error "Could not guess rule for article.")
+       (gnus-info-set-params info (cons rule (gnus-info-params info)))
+       (message "Added rule in group %s for article: %s" gnus-newsgroup-name
+                rule)))))
+
+;; Internals
+
+;; FIXME: do proper quoting of " etc
+(defun gnus-sieve-string-list (list)
+  "Convert an elisp string list to a Sieve string list.
+
+For example:
+\(gnus-sieve-string-list '(\"to\" \"cc\"))
+  => \"[\\\"to\\\", \\\"cc\\\"]\"
+"
+  (concat "[\"" (mapconcat 'identity list "\", \"") "\"]"))
+
+(defun gnus-sieve-test-list (list)
+  "Convert an elisp test list to a Sieve test list.
+
+For example:
+\(gnus-sieve-test-list '((address \"sender\" \"boss@company.com\") (size :over 4K)))
+  => \"(address \\\"sender\\\" \\\"boss@company.com\\\", size :over 4K)\""
+  (concat "(" (mapconcat 'gnus-sieve-test list ", ") ")"))
+
+;; FIXME: do proper quoting
+(defun gnus-sieve-test-token (token)
+  "Convert an elisp test token to a Sieve test token.
+
+For example:
+\(gnus-sieve-test-token 'address)
+  => \"address\"
+
+\(gnus-sieve-test-token \"sender\")
+  => \"\\\"sender\\\"\"
+
+\(gnus-sieve-test-token '(\"to\" \"cc\"))
+  => \"[\\\"to\\\", \\\"cc\\\"]\""
+  (cond
+   ((symbolp token)            ;; Keyword
+    (symbol-name token))
+
+   ((stringp token)            ;; String
+    (concat "\"" token "\""))
+
+   ((and (listp token)         ;; String list
+        (stringp (car token)))
+    (gnus-sieve-string-list token))
+
+   ((and (listp token)         ;; Test list
+        (listp (car token)))
+    (gnus-sieve-test-list token))))
+
+(defun gnus-sieve-test (test)
+  "Convert an elisp test to a Sieve test.
+
+For example:
+\(gnus-sieve-test '(address \"sender\" \"sieve-admin@extundo.com\"))
+  => \"address \\\"sender\\\" \\\"sieve-admin@extundo.com\\\"\"
+
+\(gnus-sieve-test '(anyof ((header :contains (\"to\" \"cc\") \"my@address.com\")
+                         (size :over 100K))))
+  => \"anyof (header :contains [\\\"to\\\", \\\"cc\\\"] \\\"my@address.com\\\",
+            size :over 100K)\""
+  (mapconcat 'gnus-sieve-test-token test " "))
+
+(defun gnus-sieve-script (&optional method crosspost)
+  "Generate a Sieve script based on groups with select method METHOD
+\(or all groups if nil\).  Only groups having a `sieve' parameter are
+considered.  This parameter should contain an elisp test
+\(see the documentation of gnus-sieve-test for details\).  For each
+such group, a Sieve IF control structure is generated, having the
+test as the condition and { fileinto \"group.name\"; } as the body.
+
+If CROSSPOST is nil, each conditional body contains a \"stop\" command
+which stops execution after a match is found.
+
+For example: If the INBOX.list.sieve group has the
+
+  (sieve address \"sender\" \"sieve-admin@extundo.com\")
+
+group parameter, (gnus-sieve-script) results in:
+
+  if address \"sender\" \"sieve-admin@extundo.com\" {
+          fileinto \"INBOX.list.sieve\";
+  }
+
+This is returned as a string."
+  (let* ((newsrc (cdr gnus-newsrc-alist))
+        script)
+    (dolist (info newsrc)
+      (when (or (not method)
+               (gnus-server-equal method (gnus-info-method info)))
+       (let* ((group (gnus-info-group info))
+              (spec (gnus-group-find-parameter group 'sieve t)))
+         (when spec
+           (push (concat "if " (gnus-sieve-test spec) " {\n"
+                         "\tfileinto \"" (gnus-group-real-name group) "\";\n"
+                         (if crosspost
+                             ""
+                           "\tstop;\n")
+                         "}")
+                 script)))))
+    (mapconcat 'identity script "\n")))
+
+(provide 'gnus-sieve)
+
+;;; gnus-sieve.el ends here
index 3b593ca..2b9d305 100644 (file)
@@ -1,8 +1,10 @@
 ;;; gnus-soup.el --- SOUP packet writing support for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002
+;;     Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@iesd.auc.dk>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
@@ -67,9 +69,9 @@ The SOUP packet file name will be inserted at the %s.")
 
 ;;; Internal Variables:
 
-(defvar gnus-soup-encoding-type ?n
+(defvar gnus-soup-encoding-type ?u
   "*Soup encoding type.
-`n' is news format, `m' is Unix mbox format, and `M' is MMDF mailbox
+`u' is USENET news format, `m' is Unix mbox format, and `M' is MMDF mailbox
 format.")
 
 (defvar gnus-soup-index-type ?c
@@ -133,45 +135,44 @@ If N is nil and any articles have been marked with the process mark,
 move those articles instead."
   (interactive "P")
   (let* ((articles (gnus-summary-work-articles n))
-        (tmp-buf (get-buffer-create "*soup work*"))
+        (tmp-buf (gnus-get-buffer-create "*soup work*"))
         (area (gnus-soup-area gnus-newsgroup-name))
         (prefix (gnus-soup-area-prefix area))
         headers)
     (buffer-disable-undo tmp-buf)
     (save-excursion
       (while articles
-       ;; Find the header of the article.
-       (set-buffer gnus-summary-buffer)
-       (when (setq headers (gnus-summary-article-header (car articles)))
-         ;; Put the article in a buffer.
-         (set-buffer tmp-buf)
-         (when (gnus-request-article-this-buffer
-                (car articles) gnus-newsgroup-name)
-           (save-restriction
-             (message-narrow-to-head)
-             (message-remove-header gnus-soup-ignored-headers t))
-           (gnus-soup-store gnus-soup-directory prefix headers
-                            gnus-soup-encoding-type
-                            gnus-soup-index-type)
-           (gnus-soup-area-set-number
-            area (1+ (or (gnus-soup-area-number area) 0)))))
-       ;; Mark article as read.
-       (set-buffer gnus-summary-buffer)
+       ;; Put the article in a buffer.
+       (set-buffer tmp-buf)
+       (when (gnus-request-article-this-buffer
+              (car articles) gnus-newsgroup-name)
+         (setq headers (nnheader-parse-head t))
+         (save-restriction
+           (message-narrow-to-head)
+           (message-remove-header gnus-soup-ignored-headers t))
+         (gnus-soup-store gnus-soup-directory prefix headers
+                          gnus-soup-encoding-type
+                          gnus-soup-index-type)
+         (gnus-soup-area-set-number
+          area (1+ (or (gnus-soup-area-number area) 0)))
+         ;; Mark article as read.
+         (set-buffer gnus-summary-buffer)
+         (gnus-summary-mark-as-read (car articles) gnus-souped-mark))
        (gnus-summary-remove-process-mark (car articles))
-       (gnus-summary-mark-as-read (car articles) gnus-souped-mark)
        (setq articles (cdr articles)))
       (kill-buffer tmp-buf))
-    (gnus-soup-save-areas)))
+    (gnus-soup-save-areas)
+    (gnus-set-mode-line 'summary)))
 
 (defun gnus-soup-pack-packet ()
   "Make a SOUP packet from the SOUP areas."
   (interactive)
   (gnus-soup-read-areas)
-  (unless (file-exists-p gnus-soup-directory)
-    (message "No such directory: %s" gnus-soup-directory))
-  (when (null (directory-files gnus-soup-directory nil "\\.MSG$"))
-    (message "No files to pack."))
-  (gnus-soup-pack gnus-soup-directory gnus-soup-packer))
+  (if (file-exists-p gnus-soup-directory)
+      (if (directory-files gnus-soup-directory nil "\\.MSG$")
+         (gnus-soup-pack gnus-soup-directory gnus-soup-packer)
+       (message "No files to pack."))
+    (message "No such directory: %s" gnus-soup-directory)))
 
 (defun gnus-group-brew-soup (n)
   "Make a soup packet from the current group.
@@ -204,7 +205,9 @@ for matching on group names.
 For instance, if you want to brew on all the nnml groups, as well as
 groups with \"emacs\" in the name, you could say something like:
 
-$ emacs -batch -f gnus-batch-brew-soup ^nnml \".*emacs.*\""
+$ emacs -batch -f gnus-batch-brew-soup ^nnml \".*emacs.*\"
+
+Note -- this function hasn't been implemented yet."
   (interactive)
   nil)
 
@@ -244,7 +247,8 @@ $ emacs -batch -f gnus-batch-brew-soup ^nnml \".*emacs.*\""
       ;; a soup header.
       (setq head-line
            (cond
-            ((= gnus-soup-encoding-type ?n)
+            ((or (= gnus-soup-encoding-type ?u)
+                 (= gnus-soup-encoding-type ?n)) ;;Gnus back compatibility.
              (format "#! rnews %d\n" (buffer-size)))
             ((= gnus-soup-encoding-type ?m)
              (while (search-forward "\nFrom " nil t)
@@ -310,6 +314,8 @@ If NOT-ALL, don't pack ticked articles."
           (or (mail-header-lines header) "0"))))
 
 (defun gnus-soup-save-areas ()
+  "Write all SOUP buffers."
+  (interactive)
   (gnus-soup-write-areas)
   (save-excursion
     (let (buf)
@@ -332,7 +338,9 @@ If NOT-ALL, don't pack ticked articles."
       (while (setq prefix (pop prefixes))
        (erase-buffer)
        (insert (format "(setq gnus-soup-prev-prefix %d)\n" (cdr prefix)))
-       (gnus-write-buffer (concat (car prefix) gnus-soup-prefix-file))))))
+       (gnus-write-buffer-as-coding-system
+        nnheader-text-coding-system
+        (concat (car prefix) gnus-soup-prefix-file))))))
 
 (defun gnus-soup-pack (dir packer)
   (let* ((files (mapconcat 'identity
@@ -350,9 +358,9 @@ If NOT-ALL, don't pack ticked articles."
     (gnus-make-directory dir)
     (setq gnus-soup-areas nil)
     (gnus-message 4 "Packing %s..." packer)
-    (if (zerop (call-process shell-file-name
-                            nil nil nil shell-command-switch
-                            (concat "cd " dir " ; " packer)))
+    (if (eq 0 (call-process shell-file-name
+                           nil nil nil shell-command-switch
+                           (concat "cd " dir " ; " packer)))
        (progn
          (call-process shell-file-name nil nil nil shell-command-switch
                        (concat "cd " dir " ; rm " files))
@@ -366,22 +374,23 @@ The vector contain five strings,
   [prefix name encoding description number]
 though the two last may be nil if they are missing."
   (let (areas)
-    (save-excursion
-      (set-buffer (nnheader-find-file-noselect file 'force))
-      (buffer-disable-undo (current-buffer))
-      (goto-char (point-min))
-      (while (not (eobp))
-       (push (vector (gnus-soup-field)
-                     (gnus-soup-field)
-                     (gnus-soup-field)
-                     (and (eq (preceding-char) ?\t)
-                          (gnus-soup-field))
-                     (and (eq (preceding-char) ?\t)
-                          (string-to-int (gnus-soup-field))))
-             areas)
-       (when (eq (preceding-char) ?\t)
-         (beginning-of-line 2)))
-      (kill-buffer (current-buffer)))
+    (when (file-exists-p file)
+      (save-excursion
+       (set-buffer (nnheader-find-file-noselect file 'force))
+       (buffer-disable-undo)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (push (vector (gnus-soup-field)
+                       (gnus-soup-field)
+                       (gnus-soup-field)
+                       (and (eq (preceding-char) ?\t)
+                            (gnus-soup-field))
+                       (and (eq (preceding-char) ?\t)
+                            (string-to-int (gnus-soup-field))))
+               areas)
+         (when (eq (preceding-char) ?\t)
+           (beginning-of-line 2)))
+       (kill-buffer (current-buffer))))
     areas))
 
 (defun gnus-soup-parse-replies (file)
@@ -391,7 +400,7 @@ file.  The vector contain three strings, [prefix name encoding]."
   (let (replies)
     (save-excursion
       (set-buffer (nnheader-find-file-noselect file))
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (goto-char (point-min))
       (while (not (eobp))
        (push (vector (gnus-soup-field) (gnus-soup-field)
@@ -416,7 +425,7 @@ file.  The vector contain three strings, [prefix name encoding]."
   "Write the AREAS file."
   (interactive)
   (when gnus-soup-areas
-    (nnheader-temp-write (concat gnus-soup-directory "AREAS")
+    (with-temp-file (concat gnus-soup-directory "AREAS")
       (let ((areas gnus-soup-areas)
            area)
        (while (setq area (pop areas))
@@ -437,7 +446,7 @@ file.  The vector contain three strings, [prefix name encoding]."
 
 (defun gnus-soup-write-replies (dir areas)
   "Write a REPLIES file in DIR containing AREAS."
-  (nnheader-temp-write (concat dir "REPLIES")
+  (with-temp-file (concat dir "REPLIES")
     (let (area)
       (while (setq area (pop areas))
        (insert (format "%s\t%s\t%s\n"
@@ -488,10 +497,10 @@ Return whether the unpacking was successful."
   (gnus-make-directory dir)
   (gnus-message 4 "Unpacking: %s" (format unpacker packet))
   (prog1
-      (zerop (call-process
-             shell-file-name nil nil nil shell-command-switch
-             (format "cd %s ; %s" (expand-file-name dir)
-                     (format unpacker packet))))
+      (eq 0 (call-process
+            shell-file-name nil nil nil shell-command-switch
+            (format "cd %s ; %s" (expand-file-name dir)
+                    (format unpacker packet))))
     (gnus-message 4 "Unpacking...done")))
 
 (defun gnus-soup-send-packet (packet)
@@ -506,18 +515,20 @@ Return whether the unpacking was successful."
                                 ".MSG"))
               (msg-buf (and (file-exists-p msg-file)
                             (nnheader-find-file-noselect msg-file)))
-              (tmp-buf (get-buffer-create " *soup send*"))
+              (tmp-buf (gnus-get-buffer-create " *soup send*"))
               beg end)
          (cond
-          ((/= (gnus-soup-encoding-format
-                (gnus-soup-reply-encoding (car replies)))
-               ?n)
+          ((and (/= (gnus-soup-encoding-format
+                     (gnus-soup-reply-encoding (car replies)))
+                    ?u)
+                (/= (gnus-soup-encoding-format
+                     (gnus-soup-reply-encoding (car replies)))
+                    ?n)) ;; Gnus back compatibility.
            (error "Unsupported encoding"))
           ((null msg-buf)
            t)
           (t
            (buffer-disable-undo msg-buf)
-           (buffer-disable-undo tmp-buf)
            (set-buffer msg-buf)
            (goto-char (point-min))
            (while (not (eobp))
@@ -530,26 +541,35 @@ Return whether the unpacking was successful."
                                     (match-beginning 1) (match-end 1)))))
              (switch-to-buffer tmp-buf)
              (erase-buffer)
+             (set-buffer-multibyte nil)
              (insert-buffer-substring msg-buf beg end)
-             (goto-char (point-min))
-             (search-forward "\n\n")
-             (forward-char -1)
-             (insert mail-header-separator)
-             (setq message-newsreader (setq message-mailer
-                                            (gnus-extended-version)))
              (cond
               ((string= (gnus-soup-reply-kind (car replies)) "news")
                (gnus-message 5 "Sending news message to %s..."
                              (mail-fetch-field "newsgroups"))
                (sit-for 1)
                (let ((message-syntax-checks
-                      'dont-check-for-anything-just-trust-me))
-                 (funcall message-send-news-function)))
+                      'dont-check-for-anything-just-trust-me)
+                     (method (if (functionp message-post-method)
+                                 (funcall message-post-method)
+                               message-post-method))
+                     result)
+                 (run-hooks 'message-send-news-hook)
+                 (gnus-open-server method)
+                 (message "Sending news via %s..."
+                          (gnus-server-string method))
+                 (unless (let ((mail-header-separator ""))
+                           (gnus-request-post method))
+                   (message "Couldn't send message via news: %s"
+                            (nnheader-get-report (car method))))))
               ((string= (gnus-soup-reply-kind (car replies)) "mail")
                (gnus-message 5 "Sending mail to %s..."
                              (mail-fetch-field "to"))
                (sit-for 1)
-               (message-send-mail))
+               (let ((mail-header-separator ""))
+                 (mm-with-unibyte-current-buffer
+                  (funcall (or message-send-mail-real-function
+                               message-send-mail-function)))))
               (t
                (error "Unknown reply kind")))
              (set-buffer msg-buf)
index 60be10f..a45f1ca 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-spec.el --- format spec functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 (eval-when-compile (require 'cl))
 
+(require 'alist)
 (require 'gnus)
 
+(defcustom gnus-use-correct-string-widths t
+  "*If non-nil, use correct functions for dealing with wide characters."
+  :group 'gnus-format
+  :type 'boolean)
+
+(defcustom gnus-make-format-preserve-properties (featurep 'xemacs)
+  "*If non-nil, use a replacement `format' function which preserves
+text properties. This is only needed on XEmacs, as FSF Emacs does this anyway."
+  :group 'gnus-format
+  :type 'boolean)
+
 ;;; Internal variables.
 
 (defvar gnus-summary-mark-positions nil)
@@ -68,6 +82,8 @@
 (defvar gnus-tmp-article-number)
 (defvar gnus-mouse-face)
 (defvar gnus-mouse-face-prop)
+(defvar gnus-tmp-header)
+(defvar gnus-tmp-from)
 
 (defun gnus-summary-line-format-spec ()
   (insert gnus-tmp-unread gnus-tmp-replied
    (point)
    (progn
      (insert
-      gnus-tmp-opening-bracket
-      (format "%4d: %-20s"
-             gnus-tmp-lines
-             (if (> (length gnus-tmp-name) 20)
-                 (substring gnus-tmp-name 0 20)
-               gnus-tmp-name))
-      gnus-tmp-closing-bracket)
+      (format "%c%4s: %-23s%c" gnus-tmp-opening-bracket gnus-tmp-lines
+             (let ((val
+                    (inline
+                      (gnus-summary-from-or-to-or-newsgroups
+                       gnus-tmp-header gnus-tmp-from))))
+               (if (> (length val) 23)
+                   (substring val 0 23)
+                 val))
+             gnus-tmp-closing-bracket))
      (point))
    gnus-mouse-face-prop gnus-mouse-face)
   (insert " " gnus-tmp-subject-or-nil "\n"))
   (gnus-byte-code 'gnus-group-line-format-spec))
 
 (defvar gnus-format-specs
-  `((version . ,emacs-version)
-    (group "%M\%S\%p\%P\%5y: %(%g%)%l\n" ,gnus-group-line-format-spec)
-    (summary-dummy "*  %(:                          :%) %S\n"
-                  ,gnus-summary-dummy-line-format-spec)
-    (summary "%U\%R\%z\%I\%(%[%4L: %-20,20n%]%) %s\n"
-            ,gnus-summary-line-format-spec))
+  `((group ("%M\%S\%p\%P\%5y: %(%g%)%l\n" ,gnus-group-line-format-spec))
+    (summary-dummy ("*  %(:                          :%) %S\n"
+                   ,gnus-summary-dummy-line-format-spec))
+    (summary ("%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n"
+             ,gnus-summary-line-format-spec)))
   "Alist of format specs.")
 
+(defvar gnus-default-format-specs gnus-format-specs)
+
+(defvar gnus-format-specs-compiled nil
+  "Alist of compiled format specs.  Each element should be the form:
+\(TYPE (FORMAT-STRING-1 . COMPILED-FUNCTION-1)
+                :
+       (FORMAT-STRING-n . COMPILED-FUNCTION-n)).")
+
 (defvar gnus-article-mode-line-format-spec nil)
 (defvar gnus-summary-mode-line-format-spec nil)
 (defvar gnus-group-mode-line-format-spec nil)
 
-;;; Phew.  All that gruft is over, fortunately.
+;;; Phew.  All that gruft is over with, fortunately.
 
 ;;;###autoload
 (defun gnus-update-format (var)
        (match-string 1)))))
   (let* ((type (intern (progn (string-match "gnus-\\([-a-z]+\\)-line" var)
                              (match-string 1 var))))
-        (entry (assq type gnus-format-specs))
-        value spec)
-    (when entry
-      (setq gnus-format-specs (delq entry gnus-format-specs)))
-    (set
-     (intern (format "%s-spec" var))
-     (gnus-parse-format (setq value (symbol-value (intern var)))
-                       (symbol-value (intern (format "%s-alist" var)))
-                       (not (string-match "mode" var))))
-    (setq spec (symbol-value (intern (format "%s-spec" var))))
-    (push (list type value spec) gnus-format-specs)
+        (value (symbol-value (intern var)))
+        (spec (set
+               (intern (format "%s-spec" var))
+               (gnus-parse-format
+                value (symbol-value (intern (format "%s-alist" var)))
+                (not (string-match "mode" var)))))
+        (entry (assq type gnus-format-specs)))
+    (if entry
+       (let ((elem (assoc value entry)))
+         (if elem
+             (setcdr elem spec)
+           (setcdr entry (cons (cons value elem) (cdr entry)))))
+      (push (list type (cons value spec)) gnus-format-specs))
+    (gnus-product-variable-touch 'gnus-format-specs)
 
     (pop-to-buffer "*Gnus Format*")
     (erase-buffer)
     (lisp-interaction-mode)
     (insert (pp-to-string spec))))
 
+(put 'gnus-search-or-regist-spec 'lisp-indent-function 1)
+(defmacro gnus-search-or-regist-spec (mspec &rest body)
+  (let ((specs (nth 0 mspec)) (type (nth 1 mspec)) (format (nth 2 mspec))
+       (spec (nth 3 mspec)) (entry (nth 4 mspec)) (elem (nth 5 mspec)))
+    `(let* ((,entry (assq ,type ,specs))
+           (,elem (assoc ,format (cdr ,entry))))
+       (or (cdr ,elem)
+          (when (progn ,@body)
+            (if ,entry
+                (if ,elem
+                    (setcdr ,elem ,spec)
+                  (setcdr ,entry (cons (cons ,format ,spec) (cdr ,entry))))
+              (push (list ,type (cons ,format ,spec)) ,specs))
+            (gnus-product-variable-touch (quote ,specs)))
+          ,spec))))
+
+(defun gnus-update-format-specification-1 (type format val)
+  (set (intern (format "gnus-%s-line-format-spec" type))
+       (gnus-search-or-regist-spec (gnus-format-specs-compiled
+                                   type format val entry elem)
+        (when (and gnus-compile-user-specs val)
+          (setq val (prog1
+                        (progn
+                          (fset 'gnus-tmp-func `(lambda () ,val))
+                          (require 'bytecomp)
+                          (let (byte-compile-warnings)
+                            (byte-compile 'gnus-tmp-func))
+                          (gnus-byte-code 'gnus-tmp-func))
+                      (when (get-buffer "*Compile-Log*")
+                        (bury-buffer "*Compile-Log*"))
+                      (when (get-buffer "*Compile-Log-Show*")
+                        (bury-buffer "*Compile-Log-Show*"))))))))
+
 (defun gnus-update-format-specifications (&optional force &rest types)
   "Update all (necessary) format specifications."
   ;; Make the indentation array.
   ;; See whether all the stored info needs to be flushed.
-  (when (or force
-           (not (equal emacs-version
-                       (cdr (assq 'version gnus-format-specs)))))
-    (setq gnus-format-specs nil))
+  (when force
+    (message "%s" "Force update format specs.")
+    (setq gnus-format-specs nil
+         gnus-format-specs-compiled nil)
+    (gnus-product-variable-touch 'gnus-format-specs
+                                'gnus-format-specs-compiled))
 
   ;; Go through all the formats and see whether they need updating.
-  (let (new-format entry type val)
-    (while (setq type (pop types))
-      ;; Jump to the proper buffer to find out the value of
-      ;; the variable, if possible.  (It may be buffer-local.)
-      (save-excursion
-       (let ((buffer (intern (format "gnus-%s-buffer" type)))
-             val)
-         (when (and (boundp buffer)
-                    (setq val (symbol-value buffer))
-                    (get-buffer val)
-                    (buffer-name (get-buffer val)))
-           (set-buffer (get-buffer val)))
-         (setq new-format (symbol-value
-                           (intern (format "gnus-%s-line-format" type)))))
-       (setq entry (cdr (assq type gnus-format-specs)))
-       (if (and (car entry)
-                (equal (car entry) new-format))
-           ;; Use the old format.
-           (set (intern (format "gnus-%s-line-format-spec" type))
-                (cadr entry))
-         ;; This is a new format.
-         (setq val
-               (if (not (stringp new-format))
-                   ;; This is a function call or something.
-                   new-format
-                 ;; This is a "real" format.
-                 (gnus-parse-format
-                  new-format
-                  (symbol-value
-                   (intern (format "gnus-%s-line-format-alist"
-                                   (if (eq type 'article-mode)
-                                       'summary-mode type))))
-                  (not (string-match "mode$" (symbol-name type))))))
-         ;; Enter the new format spec into the list.
-         (if entry
-             (progn
-               (setcar (cdr entry) val)
-               (setcar entry new-format))
-           (push (list type new-format val) gnus-format-specs))
-         (set (intern (format "gnus-%s-line-format-spec" type)) val)))))
-
-  (unless (assq 'version gnus-format-specs)
-    (push (cons 'version emacs-version) gnus-format-specs)))
+  (let (type val)
+    (save-excursion
+      (while (setq type (pop types))
+       ;; Jump to the proper buffer to find out the value of the
+       ;; variable, if possible.  (It may be buffer-local.)
+       (let* ((new-format
+               (let ((buffer (intern (format "gnus-%s-buffer" type))))
+                 (when (and (boundp buffer)
+                            (setq val (symbol-value buffer))
+                            (gnus-buffer-exists-p val))
+                   (set-buffer val))
+                 (symbol-value
+                  (intern (format "gnus-%s-line-format" type))))))
+         (or (gnus-update-format-specification-1 type new-format nil)
+             ;; This is a new format.
+             (gnus-update-format-specification-1
+              type new-format
+              (gnus-search-or-regist-spec (gnus-format-specs
+                                           type new-format val entry elem)
+                (setq val (if (stringp new-format)
+                              ;; This is a "real" format.
+                              (gnus-parse-format
+                               new-format
+                               (symbol-value
+                                (intern (format "gnus-%s-line-format-alist"
+                                                type)))
+                               (not (string-match "mode$"
+                                                  (symbol-name type))))
+                            ;; This is a function call or something.
+                            new-format))))))))))
 
 (defvar gnus-mouse-face-0 'highlight)
 (defvar gnus-mouse-face-1 'highlight)
 (defvar gnus-face-4 'bold)
 
 (defun gnus-face-face-function (form type)
+  `(gnus-add-text-properties
+    (point) (progn ,@form (point))
+    '(gnus-face t face ,(symbol-value (intern (format "gnus-face-%d" type))))))
+
+(defun gnus-balloon-face-function (form type)
   `(gnus-put-text-property
     (point) (progn ,@form (point))
-    'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
+    ,(if (fboundp 'balloon-help-mode)
+        ''balloon-help
+       ''help-echo)
+    ,(intern (format "gnus-balloon-face-%d" type))))
+
+(defun gnus-spec-tab (column)
+  (if (> column 0)
+      `(insert (make-string (max (- ,column (current-column)) 0) ? ))
+    (let ((column (abs column)))
+      (if gnus-use-correct-string-widths
+         `(progn
+            (if (> (current-column) ,column)
+                (while (progn
+                         (delete-backward-char 1)
+                         (> (current-column) ,column))))
+            (insert (make-string (max (- ,column (current-column)) 0) ? )))
+       `(progn
+          (if (> (current-column) ,column)
+              (delete-region (point)
+                             (- (point) (- (current-column) ,column)))
+            (insert (make-string (max (- ,column (current-column)) 0)
+                                 ? ))))))))
+
+(defun gnus-correct-length (string)
+  "Return the correct width of STRING."
+  (let ((length 0))
+    (mapcar (lambda (char) (incf length (gnus-char-width char))) string)
+    length))
+
+(defun gnus-correct-substring (string start &optional end)
+  (let ((wstart 0)
+       (wend 0)
+       (wseek 0)
+       (seek 0)
+       (length (length string))
+       (string (concat string "\0")))
+    ;; Find the start position.
+    (while (and (< seek length)
+               (< wseek start))
+      (incf wseek (gnus-char-width (aref string seek)))
+      (incf seek))
+    (setq wstart seek)
+    ;; Find the end position.
+    (while (and (<= seek length)
+               (or (not end)
+                   (<= wseek end)))
+      (incf wseek (gnus-char-width (aref string seek)))
+      (incf seek))
+    (setq wend seek)
+    (substring string wstart (1- wend))))
+
+(defun gnus-string-width-function ()
+  (cond
+   (gnus-use-correct-string-widths
+    'gnus-correct-length)
+   ((fboundp 'string-width)
+    'string-width)
+   (t
+    'length)))
+
+(defun gnus-substring-function ()
+  (cond
+   (gnus-use-correct-string-widths
+    'gnus-correct-substring)
+   ((fboundp 'string-width)
+    'gnus-correct-substring)
+   (t
+    'substring)))
 
 (defun gnus-tilde-max-form (el max-width)
   "Return a form that limits EL to MAX-WIDTH."
-  (let ((max (abs max-width)))
+  (let ((max (abs max-width))
+       (length-fun (gnus-string-width-function))
+       (substring-fun (gnus-substring-function)))
     (if (symbolp el)
-       `(if (> (length ,el) ,max)
+       `(if (> (,length-fun ,el) ,max)
             ,(if (< max-width 0)
-                 `(substring ,el (- (length el) ,max))
-               `(substring ,el 0 ,max))
+                 `(,substring-fun ,el (- (,length-fun ,el) ,max))
+               `(,substring-fun ,el 0 ,max))
           ,el)
       `(let ((val (eval ,el)))
-        (if (> (length val) ,max)
+        (if (> (,length-fun val) ,max)
             ,(if (< max-width 0)
-                 `(substring val (- (length val) ,max))
-               `(substring val 0 ,max))
+                 `(,substring-fun val (- (,length-fun val) ,max))
+               `(,substring-fun val 0 ,max))
           val)))))
 
 (defun gnus-tilde-cut-form (el cut-width)
   "Return a form that cuts CUT-WIDTH off of EL."
-  (let ((cut (abs cut-width)))
+  (let ((cut (abs cut-width))
+       (length-fun (gnus-string-width-function))
+       (substring-fun (gnus-substring-function)))
     (if (symbolp el)
-       `(if (> (length ,el) ,cut)
+       `(if (> (,length-fun ,el) ,cut)
             ,(if (< cut-width 0)
-                 `(substring ,el 0 (- (length el) ,cut))
-               `(substring ,el ,cut))
+                 `(,substring-fun ,el 0 (- (,length-fun ,el) ,cut))
+               `(,substring-fun ,el ,cut))
           ,el)
       `(let ((val (eval ,el)))
-        (if (> (length val) ,cut)
+        (if (> (,length-fun val) ,cut)
             ,(if (< cut-width 0)
-                 `(substring val 0 (- (length val) ,cut))
-               `(substring val ,cut))
+                 `(,substring-fun val 0 (- (,length-fun val) ,cut))
+               `(,substring-fun val ,cut))
           val)))))
 
 (defun gnus-tilde-ignore-form (el ignore-value)
        (if (equal val ,ignore-value)
           "" val))))
 
+(defun gnus-pad-form (el pad-width)
+  "Return a form that pads EL to PAD-WIDTH accounting for multi-column
+characters correctly. This is because `format' may pad to columns or to
+characters when given a pad value."
+  (let ((pad (abs pad-width))
+       (side (< 0 pad-width))
+       (length-fun (gnus-string-width-function)))
+    (if (symbolp el)
+       `(let ((need (- ,pad (,length-fun ,el))))
+          (if (> need 0)
+              (concat ,(when side '(make-string need ?\ ))
+                      ,el
+                      ,(when (not side) '(make-string need ?\ )))
+            ,el))
+      `(let* ((val (eval ,el))
+             (need (- ,pad (,length-fun val))))
+        (if (> need 0)
+            (concat ,(when side '(make-string need ?\ ))
+                    val
+                    ,(when (not side) '(make-string need ?\ )))
+          val)))))
+
 (defun gnus-parse-format (format spec-alist &optional insert)
   ;; This function parses the FORMAT string with the help of the
   ;; SPEC-ALIST and returns a list that can be eval'ed to return the
   ;; string.  If the FORMAT string contains the specifiers %( and %)
   ;; the text between them will have the mouse-face text property.
-  (if (string-match
-       "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
-       format)
-      (gnus-parse-complex-format format spec-alist)
-    ;; This is a simple format.
-    (gnus-parse-simple-format format spec-alist insert)))
+  ;; If the FORMAT string contains the specifiers %[ and %], the text between
+  ;; them will have the balloon-help text property.
+  (let ((case-fold-search nil))
+    (if (string-match
+        "\\`\\(.*\\)%[0-9]?[{(«]\\(.*\\)%[0-9]?[»})]\\(.*\n?\\)\\'\\|%[-0-9]*=\\|%[-0-9]*\\*"
+        format)
+       (gnus-parse-complex-format format spec-alist)
+      ;; This is a simple format.
+      (gnus-parse-simple-format format spec-alist insert))))
 
 (defun gnus-parse-complex-format (format spec-alist)
-  (save-excursion
-    (gnus-set-work-buffer)
-    (insert format)
-    (goto-char (point-min))
-    (while (re-search-forward "\"" nil t)
-      (replace-match "\\\"" nil t))
-    (goto-char (point-min))
-    (insert "(\"")
-    (while (re-search-forward "%\\([0-9]+\\)?\\([{}()]\\)" nil t)
-      (let ((number (if (match-beginning 1)
-                       (match-string 1) "0"))
-           (delim (aref (match-string 2) 0)))
-       (if (or (= delim ?\() (= delim ?\{))
-           (replace-match (concat "\"(" (if (= delim ?\() "mouse" "face")
-                                  " " number " \""))
-         (replace-match "\")\""))))
-    (goto-char (point-max))
-    (insert "\")")
-    (goto-char (point-min))
-    (let ((form (read (current-buffer))))
-      (cons 'progn (gnus-complex-form-to-spec form spec-alist)))))
+  (let ((cursor-spec nil))
+    (save-excursion
+      (gnus-set-work-buffer)
+      (insert format)
+      (goto-char (point-min))
+      (while (re-search-forward "\"" nil t)
+       (replace-match "\\\"" nil t))
+      (goto-char (point-min))
+      (insert "(\"")
+      ;; Convert all font specs into font spec lists.
+      (while (re-search-forward "%\\([0-9]+\\)?\\([«»{}()]\\)" nil t)
+       (let ((number (if (match-beginning 1)
+                         (match-string 1) "0"))
+             (delim (aref (match-string 2) 0)))
+         (if (or (= delim ?\()
+                 (= delim ?\{)
+                 (= delim ?\«))
+             (replace-match (concat "\"("
+                                    (cond ((= delim ?\() "mouse")
+                                          ((= delim ?\{) "face")
+                                          (t "balloon"))
+                                    " " number " \"")
+                            t t)
+           (replace-match "\")\""))))
+      (goto-char (point-max))
+      (insert "\")")
+      ;; Convert point position commands.
+      (goto-char (point-min))
+      (let ((case-fold-search nil))
+       (while (re-search-forward "%\\([-0-9]+\\)?\\*" nil t)
+         (replace-match "\"(point)\"" t t)
+         (setq cursor-spec t)))
+      ;; Convert TAB commands.
+      (goto-char (point-min))
+      (while (re-search-forward "%\\([-0-9]+\\)=" nil t)
+       (replace-match (format "\"(tab %s)\"" (match-string 1)) t t))
+      ;; Convert the buffer into the spec.
+      (goto-char (point-min))
+      (let ((form (read (current-buffer))))
+       (if cursor-spec
+           `(let (gnus-position)
+              ,@(gnus-complex-form-to-spec form spec-alist)
+              (if gnus-position
+                  (gnus-put-text-property gnus-position (1+ gnus-position)
+                                          'gnus-position t)))
+         `(progn
+            ,@(gnus-complex-form-to-spec form spec-alist)))))))
 
 (defun gnus-complex-form-to-spec (form spec-alist)
   (delq nil
        (mapcar
         (lambda (sform)
-          (if (stringp sform)
-              (gnus-parse-simple-format sform spec-alist t)
+          (cond
+           ((stringp sform)
+            (gnus-parse-simple-format sform spec-alist t))
+           ((eq (car sform) 'point)
+            '(setq gnus-position (point)))
+           ((eq (car sform) 'tab)
+            (gnus-spec-tab (cadr sform)))
+           (t
             (funcall (intern (format "gnus-%s-face-function" (car sform)))
                      (gnus-complex-form-to-spec (cddr sform) spec-alist)
-                     (nth 1 sform))))
+                     (nth 1 sform)))))
         form)))
 
+
+(defun gnus-xmas-format (fstring &rest args)
+  "A version of `format' which preserves text properties.
+
+Required for XEmacs, where the built in `format' function strips all text
+properties from both the format string and any inserted strings.
+
+Only supports the format sequence %s, and %% for inserting
+literal % characters. A pad width and an optional - (to right pad)
+are supported for %s."
+  (let ((re "%%\\|%\\(-\\)?\\([1-9][0-9]*\\)?s")
+       (n (length args)))
+    (with-temp-buffer
+      (insert fstring)
+      (goto-char (point-min))
+      (while (re-search-forward re nil t)
+       (goto-char (match-end 0))
+       (cond
+        ((string= (match-string 0) "%%")
+         (delete-char -1))
+        (t
+         (if (null args)
+             (error 'wrong-number-of-arguments #'my-format n fstring))
+         (let* ((minlen (string-to-int (or (match-string 2) "")))
+                (arg (car args))
+                (str (if (stringp arg) arg (format "%s" arg)))
+                (lpad (null (match-string 1)))
+                (padlen (max 0 (- minlen (length str)))))
+           (replace-match "")
+           (if lpad (insert-char ?\  padlen))
+           (insert str)
+           (unless lpad (insert-char ?\  padlen))
+           (setq args (cdr args))))))
+      (buffer-string))))
+
 (defun gnus-parse-simple-format (format spec-alist &optional insert)
   ;; This function parses the FORMAT string with the help of the
   ;; SPEC-ALIST and returns a list that can be eval'ed to return a
   ;; string.
-  (let ((max-width 0)
+  (let (max-width
        spec flist fstring elem result dontinsert user-defined
        type value pad-width spec-beg cut-width ignore-value
-       tilde-form tilde elem-type)
+       tilde-form tilde elem-type extended-spec)
     (save-excursion
       (gnus-set-work-buffer)
       (insert format)
       (goto-char (point-min))
-      (while (re-search-forward "%" nil t)
+      (while (search-forward "%" nil t)
        (setq user-defined nil
              spec-beg nil
              pad-width nil
              max-width nil
              cut-width nil
              ignore-value nil
-             tilde-form nil)
+             tilde-form nil
+             extended-spec nil)
        (setq spec-beg (1- (point)))
 
        ;; Parse this spec fully.
              t)
             (t
              nil)))
-       ;; User-defined spec -- find the spec name.
-       (when (= (setq spec (following-char)) ?u)
+       (cond
+        ;; User-defined spec -- find the spec name.
+        ((eq (setq spec (char-after)) ?u)
          (forward-char 1)
-         (setq user-defined (following-char)))
+         (when (and (eq (setq user-defined (char-after)) ?&)
+                    (looking-at "&\\([^;]+\\);"))
+           (setq user-defined (match-string 1))
+           (goto-char (match-end 1))))
+        ;; extended spec
+        ((and (eq spec ?&) (looking-at "&\\([^;]+\\);"))
+         (setq extended-spec (intern (match-string 1)))
+         (goto-char (match-end 1))))
        (forward-char 1)
        (delete-region spec-beg (point))
 
           (user-defined
            (setq elem
                  (list
-                  (list (intern (format "gnus-user-format-function-%c"
-                                        user-defined))
+                  (list (intern (format
+                                 (if (stringp user-defined)
+                                     "gnus-user-format-function-%s"
+                                   "gnus-user-format-function-%c")
+                                 user-defined))
                         'gnus-tmp-header)
                   ?s)))
           ;; Find the specification from `spec-alist'.
-          ((setq elem (cdr (assq spec spec-alist))))
+          ((setq elem (cdr (assq (or extended-spec spec) spec-alist))))
           (t
            (setq elem '("*" ?s))))
          (setq elem-type (cadr elem))
          ;; Insert the new format elements.
-         (when pad-width
+         (when (and pad-width
+                    (not (and (featurep 'xemacs)
+                              gnus-use-correct-string-widths)))
            (insert (number-to-string pad-width)))
          ;; Create the form to be evaled.
-         (if (or max-width cut-width ignore-value)
+         (if (or max-width cut-width ignore-value
+                 (and (featurep 'xemacs)
+                      gnus-use-correct-string-widths))
              (progn
                (insert ?s)
                (let ((el (car elem)))
                    (setq el (gnus-tilde-cut-form el cut-width)))
                  (when max-width
                    (setq el (gnus-tilde-max-form el max-width)))
+                 (when pad-width
+                   (setq el (gnus-pad-form el pad-width)))
                  (push el flist)))
            (insert elem-type)
            (push (car elem) flist))))
-      (setq fstring (buffer-string)))
+      (setq fstring (buffer-substring-no-properties (point-min) (point-max))))
 
     ;; Do some postprocessing to increase efficiency.
     (setq
      result
      (cond
-      ;; Emptyness.
+      ;; Emptiness.
       ((string= fstring "")
        nil)
       ;; Not a format string.
       ;; A single string spec in the end of the spec.
       ((string-match "\\`\\([^%]+\\)%[sc]\\'" fstring)
        (list (match-string 1 fstring) (car flist)))
+      ;; Only string (and %) specs (XEmacs only!)
+      ((and (featurep 'xemacs)
+           gnus-make-format-preserve-properties
+           (string-match
+            "\\`\\([^%]*\\(%%\\|%-?\\([1-9][0-9]*\\)?s\\)\\)*[^%]*\\'"
+            fstring))
+       (list (cons 'gnus-xmas-format (cons fstring (nreverse flist)))))
       ;; A more complex spec.
       (t
        (list (cons 'format (cons fstring (nreverse flist)))))))
@@ -505,13 +748,14 @@ If PROPS, insert the result."
   (require 'bytecomp)
   (let ((entries gnus-format-specs)
        (byte-compile-warnings '(unresolved callargs redefine))
-       entry gnus-tmp-func)
+       entry type compiled-function)
     (save-excursion
       (gnus-message 7 "Compiling format specs...")
 
       (while entries
-       (setq entry (pop entries))
-       (if (eq (car entry) 'version)
+       (setq entry (pop entries)
+             type (car entry))
+       (if (memq type '(gnus-version version))
            (setq gnus-format-specs (delq entry gnus-format-specs))
          (let ((form (caddr entry)))
            (when (and (listp form)
@@ -519,14 +763,19 @@ If PROPS, insert the result."
                       (not (eq 'byte-code (car form)))
                       ;; Under XEmacs, it's (funcall #<compiled-function ...>)
                       (not (and (eq 'funcall (car form))
-                                (compiled-function-p (cadr form)))))
-             (fset 'gnus-tmp-func `(lambda () ,form))
+                                (byte-code-function-p (cadr form)))))
+             (defalias 'gnus-tmp-func `(lambda () ,form))
              (byte-compile 'gnus-tmp-func)
-             (setcar (cddr entry) (gnus-byte-code 'gnus-tmp-func))))))
+             (setq compiled-function (gnus-byte-code 'gnus-tmp-func))
+             (set (intern (format "gnus-%s-line-format-spec" type))
+                  compiled-function)
+             (let ((elem (cdr (assq type gnus-format-specs-compiled))))
+               (if elem
+                   (set-alist 'elem (cadr entry) compiled-function)
+                 (setq elem (list (cadr entry) compiled-function)))
+               (set-alist 'gnus-format-specs-compiled type elem))))))
 
       (push (cons 'version emacs-version) gnus-format-specs)
-      ;; Mark the .newsrc.eld file as "dirty".
-      (gnus-dribble-enter " ")
       (gnus-message 7 "Compiling user specs...done"))))
 
 (defun gnus-set-format (type &optional insertable)
@@ -535,8 +784,13 @@ If PROPS, insert the result."
        (symbol-value (intern (format "gnus-%s-line-format" type)))
        (symbol-value (intern (format "gnus-%s-line-format-alist" type)))
        insertable)))
-       
+
+(gnus-ems-redefine)
 
 (provide 'gnus-spec)
 
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
 ;;; gnus-spec.el ends here
index 22089c1..bfc3d08 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-srvr.el --- virtual server support for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 (require 'gnus-int)
 (require 'gnus-range)
 
-(defvar gnus-server-mode-hook nil
-  "Hook run in `gnus-server-mode' buffers.")
+(defcustom gnus-server-mode-hook nil
+  "Hook run in `gnus-server-mode' buffers."
+  :group 'gnus-server
+  :type 'hook)
 
-(defconst gnus-server-line-format "     {%(%h:%w%)} %s\n"
+(defcustom gnus-server-exit-hook nil
+  "Hook run when exiting the server buffer."
+  :group 'gnus-server
+  :type 'hook)
+
+(defcustom gnus-server-line-format "     {%(%h:%w%)} %s%a\n"
   "Format of server lines.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
@@ -46,28 +54,41 @@ The following specs are understood:
 %h backend
 %n name
 %w address
-%s status")
-
-(defvar gnus-server-mode-line-format "Gnus: %%b"
-  "The format specification for the server mode line.")
-
-(defvar gnus-server-exit-hook nil
-  "*Hook run when exiting the server buffer.")
+%s status
+%a agent covered
+
+General format specifiers can also be used.
+See Info node `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
+  :group 'gnus-server-visual
+  :type 'string)
+
+(defcustom gnus-server-mode-line-format "Gnus: %%b"
+  "The format specification for the server mode line."
+  :group 'gnus-server-visual
+  :type 'string)
+
+(defcustom gnus-server-browse-in-group-buffer nil
+  "Whether server browsing should take place in the group buffer.
+If nil, a faster, but more primitive, buffer is used instead."
+  :group 'gnus-server-visual
+  :type 'boolean)
 
 ;;; Internal variables.
 
 (defvar gnus-inserted-opened-servers nil)
 
 (defvar gnus-server-line-format-alist
-  `((?h how ?s)
-    (?n name ?s)
-    (?w where ?s)
-    (?s status ?s)))
+  `((?h gnus-tmp-how ?s)
+    (?n gnus-tmp-name ?s)
+    (?w gnus-tmp-where ?s)
+    (?s gnus-tmp-status ?s)
+    (?a gnus-tmp-agent ?s)))
 
 (defvar gnus-server-mode-line-format-alist
-  `((?S news-server ?s)
-    (?M news-method ?s)
-    (?u user-defined ?s)))
+  `((?S gnus-tmp-news-server ?s)
+    (?M gnus-tmp-news-method ?s)
+    (?u gnus-tmp-user-defined ?s)))
 
 (defvar gnus-server-line-format-spec nil)
 (defvar gnus-server-mode-line-format-spec nil)
@@ -84,7 +105,7 @@ The following specs are understood:
     (easy-menu-define
      gnus-server-server-menu gnus-server-mode-map ""
      '("Server"
-       ["Add" gnus-server-add-server t]
+       ["Add..." gnus-server-add-server t]
        ["Browse" gnus-server-read-server t]
        ["Scan" gnus-server-scan-server t]
        ["List" gnus-server-list-servers t]
@@ -100,6 +121,7 @@ The following specs are understood:
      '("Connections"
        ["Open" gnus-server-open-server t]
        ["Close" gnus-server-close-server t]
+       ["Offline" gnus-server-offline-server t]
        ["Deny" gnus-server-deny-server t]
        "---"
        ["Open All" gnus-server-open-all-servers t]
@@ -116,7 +138,7 @@ The following specs are understood:
   (suppress-keymap gnus-server-mode-map)
 
   (gnus-define-keys gnus-server-mode-map
-    " " gnus-server-read-server
+    " " gnus-server-read-server-in-server-buffer
     "\r" gnus-server-read-server
     gnus-mouse-2 gnus-server-pick-server
     "q" gnus-server-exit
@@ -133,20 +155,93 @@ The following specs are understood:
     "C" gnus-server-close-server
     "\M-c" gnus-server-close-all-servers
     "D" gnus-server-deny-server
+    "L" gnus-server-offline-server
     "R" gnus-server-remove-denials
 
+    "n" next-line
+    "p" previous-line
+
     "g" gnus-server-regenerate-server
 
     "\C-c\C-i" gnus-info-find-node
     "\C-c\C-b" gnus-bug))
 
+(defface gnus-server-agent-face
+  '((((class color) (background light)) (:foreground "PaleTurquoise" :bold t))
+    (((class color) (background dark)) (:foreground "PaleTurquoise" :bold t))
+    (t (:bold t)))
+  "Face used for displaying AGENTIZED servers"
+  :group 'gnus-server-visual)
+
+(defface gnus-server-opened-face
+  '((((class color) (background light)) (:foreground "Green3" :bold t))
+    (((class color) (background dark)) (:foreground "Green1" :bold t))
+    (t (:bold t)))
+  "Face used for displaying OPENED servers"
+  :group 'gnus-server-visual)
+
+(defface gnus-server-closed-face
+  '((((class color) (background light)) (:foreground "Steel Blue" :italic t))
+    (((class color) (background dark))
+     (:foreground "Light Steel Blue" :italic t))
+    (t (:italic t)))
+  "Face used for displaying CLOSED servers"
+  :group 'gnus-server-visual)
+
+(defface gnus-server-denied-face
+  '((((class color) (background light)) (:foreground "Red" :bold t))
+    (((class color) (background dark)) (:foreground "Pink" :bold t))
+    (t (:inverse-video t :bold t)))
+  "Face used for displaying DENIED servers"
+  :group 'gnus-server-visual)
+
+(defface gnus-server-offline-face
+  '((((class color) (background light)) (:foreground "Orange" :bold t))
+    (((class color) (background dark)) (:foreground "Yellow" :bold t))
+    (t (:inverse-video t :bold t)))
+  "Face used for displaying OFFLINE servers"
+  :group 'gnus-server-visual)
+
+(defcustom gnus-server-agent-face 'gnus-server-agent-face
+  "Face name to use on AGENTIZED servers."
+  :group 'gnus-server-visual
+  :type 'face)
+
+(defcustom gnus-server-opened-face 'gnus-server-opened-face
+  "Face name to use on OPENED servers."
+  :group 'gnus-server-visual
+  :type 'face)
+
+(defcustom gnus-server-closed-face 'gnus-server-closed-face
+  "Face name to use on CLOSED servers."
+  :group 'gnus-server-visual
+  :type 'face)
+
+(defcustom gnus-server-denied-face 'gnus-server-denied-face
+  "Face name to use on DENIED servers."
+  :group 'gnus-server-visual
+  :type 'face)
+
+(defcustom gnus-server-offline-face 'gnus-server-offline-face
+  "Face name to use on OFFLINE servers."
+  :group 'gnus-server-visual
+  :type 'face)
+
+(defvar gnus-server-font-lock-keywords
+  (list
+   '("(\\(agent\\))" 1 gnus-server-agent-face)
+   '("(\\(opened\\))" 1 gnus-server-opened-face)
+   '("(\\(closed\\))" 1 gnus-server-closed-face)
+   '("(\\(offline\\))" 1 gnus-server-offline-face)
+   '("(\\(denied\\))" 1 gnus-server-denied-face)))
+
 (defun gnus-server-mode ()
   "Major mode for listing and editing servers.
 
 All normal editing commands are switched off.
 \\<gnus-server-mode-map>
 For more in-depth information on this mode, read the manual
-(`\\[gnus-info-find-node]').
+\(`\\[gnus-info-find-node]').
 
 The following commands are available:
 
@@ -161,29 +256,42 @@ The following commands are available:
   (gnus-set-default-directory)
   (setq mode-line-process nil)
   (use-local-map gnus-server-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq truncate-lines t)
   (setq buffer-read-only t)
+  (if (featurep 'xemacs)
+      (put 'gnus-server-mode 'font-lock-defaults '(gnus-server-font-lock-keywords t))
+    (set (make-local-variable 'font-lock-defaults)
+        '(gnus-server-font-lock-keywords t)))
   (gnus-run-hooks 'gnus-server-mode-hook))
 
-(defun gnus-server-insert-server-line (name method)
-  (let* ((how (car method))
-        (where (nth 1 method))
+(defun gnus-server-insert-server-line (gnus-tmp-name method)
+  (let* ((gnus-tmp-how (car method))
+        (gnus-tmp-where (nth 1 method))
         (elem (assoc method gnus-opened-servers))
-        (status (cond ((eq (nth 1 elem) 'denied)
-                       "(denied)")
-                      ((or (gnus-server-opened method)
-                           (eq (nth 1 elem) 'ok))
-                       "(opened)")
-                      (t
-                       "(closed)"))))
+        (gnus-tmp-status
+         (cond
+          ((eq (nth 1 elem) 'denied) "(denied)")
+          ((eq (nth 1 elem) 'offline) "(offline)")
+          (t
+           (condition-case nil
+               (if (or (gnus-server-opened method)
+                       (eq (nth 1 elem) 'ok))
+                   "(opened)"
+                 "(closed)")
+             ((error) "(error)")))))
+        (gnus-tmp-agent (if (and gnus-agent
+                                 (gnus-agent-method-p method))
+                            " (agent)"
+                          "")))
     (beginning-of-line)
     (gnus-add-text-properties
      (point)
      (prog1 (1+ (point))
        ;; Insert the text.
        (eval gnus-server-line-format-spec))
-     (list 'gnus-server (intern name)))))
+     (list 'gnus-server (intern gnus-tmp-name)
+           'gnus-named-server (intern (gnus-method-to-server method))))))
 
 (defun gnus-enter-server-buffer ()
   "Set up the server buffer."
@@ -195,7 +303,7 @@ The following commands are available:
   "Initialize the server buffer."
   (unless (get-buffer gnus-server-buffer)
     (save-excursion
-      (set-buffer (get-buffer-create gnus-server-buffer))
+      (set-buffer (gnus-get-buffer-create gnus-server-buffer))
       (gnus-server-mode)
       (when gnus-carpal
        (gnus-carpal-setup-buffer 'server)))))
@@ -213,7 +321,7 @@ The following commands are available:
     (while alist
       (unless (member (cdar alist) done)
        (push (cdar alist) done)
-       (cdr (setq server (pop alist)))
+       (setq server (pop alist))
        (when (and server (car server) (cdr server))
          (gnus-server-insert-server-line (car server) (cdr server))))
       (when (member (cdar alist) done)
@@ -237,6 +345,12 @@ The following commands are available:
   (let ((server (get-text-property (gnus-point-at-bol) 'gnus-server)))
     (and server (symbol-name server))))
 
+(defun gnus-server-named-server ()
+  "Returns a server name that matches one of the names returned by
+gnus-method-to-server."
+  (let ((server (get-text-property (gnus-point-at-bol) 'gnus-named-server)))
+    (and server (symbol-name server))))
+
 (defalias 'gnus-server-position-point 'gnus-goto-colon)
 
 (defconst gnus-server-edit-buffer "*Gnus edit server*")
@@ -251,7 +365,7 @@ The following commands are available:
       (when entry
        (gnus-dribble-enter
         (concat "(gnus-server-set-info \"" server "\" '"
-                (prin1-to-string (cdr entry)) ")\n")))
+                (gnus-prin1-to-string (cdr entry)) ")\n")))
       (when (or entry oentry)
        ;; Buffer may be narrowed.
        (save-restriction
@@ -270,9 +384,13 @@ The following commands are available:
   (when (and server info)
     (gnus-dribble-enter
      (concat "(gnus-server-set-info \"" server "\" '"
-            (prin1-to-string info) ")"))
+            (gnus-prin1-to-string info) ")"))
     (let* ((server (nth 1 info))
-          (entry (assoc server gnus-server-alist)))
+          (entry (assoc server gnus-server-alist))
+          (cached (assoc server gnus-server-method-cache)))
+      (if cached
+         (setq gnus-server-method-cache
+               (delq cached gnus-server-method-cache)))
       (if entry (setcdr entry info)
        (setq gnus-server-alist
              (nconc gnus-server-alist (list (cons server info))))))))
@@ -287,12 +405,24 @@ The following commands are available:
       (error "No server on the current line")))
   (unless (assoc server gnus-server-alist)
     (error "Read-only server %s" server))
-  (gnus-dribble-enter "")
+  (gnus-dribble-touch)
   (let ((buffer-read-only nil))
     (gnus-delete-line))
   (push (assoc server gnus-server-alist) gnus-server-killed-servers)
   (setq gnus-server-alist (delq (car gnus-server-killed-servers)
                                gnus-server-alist))
+  (let ((groups (gnus-groups-from-server server)))
+    (when (and groups
+              (gnus-yes-or-no-p
+               (format "Kill all %s groups from this server? "
+                       (length groups))))
+      (dolist (group groups)
+       (setq gnus-newsrc-alist
+             (delq (assoc group gnus-newsrc-alist)
+                   gnus-newsrc-alist))
+       (when gnus-group-change-level-function
+         (funcall gnus-group-change-level-function
+                  group gnus-level-killed 3)))))
   (gnus-server-position-point))
 
 (defun gnus-server-yank-server ()
@@ -312,7 +442,7 @@ The following commands are available:
          (setq alist (cdr alist)))
        (if alist
            (setcdr alist (cons killed (cdr alist)))
-         (setq gnus-server-alist (list killed)))))
+         (setq gnus-server-alist (list killed)))))
     (gnus-server-update-server (car killed))
     (setq gnus-server-killed-servers (cdr gnus-server-killed-servers))
     (gnus-server-position-point)))
@@ -321,7 +451,7 @@ The following commands are available:
   "Return to the group buffer."
   (interactive)
   (gnus-run-hooks 'gnus-server-exit-hook)
-  (kill-buffer (current-buffer))
+  (gnus-kill-buffer (current-buffer))
   (gnus-configure-windows 'group t))
 
 (defun gnus-server-list-servers ()
@@ -378,12 +508,23 @@ The following commands are available:
       (gnus-server-update-server server)
       (gnus-server-position-point))))
 
+(defun gnus-server-offline-server (server)
+  "Set SERVER to offline."
+  (interactive (list (gnus-server-server-name)))
+  (let ((method (gnus-server-to-method server)))
+    (unless method
+      (error "No such server: %s" server))
+    (prog1
+       (gnus-close-server method)
+      (gnus-server-set-status method 'offline)
+      (gnus-server-update-server server)
+      (gnus-server-position-point))))
+
 (defun gnus-server-close-all-servers ()
   "Close all servers."
   (interactive)
-  (let ((servers gnus-inserted-opened-servers))
-    (while servers
-      (gnus-server-close-server (car (pop servers))))))
+  (dolist (server gnus-inserted-opened-servers)
+    (gnus-server-close-server (car server))))
 
 (defun gnus-server-deny-server (server)
   "Make sure SERVER will never be attempted opened."
@@ -399,11 +540,9 @@ The following commands are available:
 (defun gnus-server-remove-denials ()
   "Make all denied servers into closed servers."
   (interactive)
-  (let ((servers gnus-opened-servers))
-    (while servers
-      (when (eq (nth 1 (car servers)) 'denied)
-       (setcar (nthcdr 1 (car servers)) 'closed))
-      (setq servers (cdr servers))))
+  (dolist (server gnus-opened-servers)
+    (when (eq (nth 1 server) 'denied)
+      (setcar (nthcdr 1 server) 'closed)))
   (gnus-server-list-servers))
 
 (defun gnus-server-copy-server (from to)
@@ -466,9 +605,18 @@ The following commands are available:
 (defun gnus-server-scan-server (server)
   "Request a scan from the current server."
   (interactive (list (gnus-server-server-name)))
-  (gnus-message 3 "Scanning %s...done" server)
-  (gnus-request-scan nil (gnus-server-to-method server))
-  (gnus-message 3 "Scanning %s...done" server))
+  (let ((method (gnus-server-to-method server)))
+    (if (not (gnus-get-function method 'request-scan))
+       (error "Server %s can't scan" (car method))
+      (gnus-message 3 "Scanning %s..." server)
+      (gnus-request-scan nil method)
+      (gnus-message 3 "Scanning %s...done" server))))
+
+(defun gnus-server-read-server-in-server-buffer (server)
+  "Browse a server in server buffer."
+  (interactive (list (gnus-server-server-name)))
+  (let (gnus-server-browse-in-group-buffer)
+    (gnus-server-read-server server)))
 
 (defun gnus-server-read-server (server)
   "Browse a server."
@@ -503,28 +651,29 @@ The following commands are available:
   (suppress-keymap gnus-browse-mode-map)
 
   (gnus-define-keys
-   gnus-browse-mode-map
-   " " gnus-browse-read-group
-   "=" gnus-browse-select-group
-   "n" gnus-browse-next-group
-   "p" gnus-browse-prev-group
-   "\177" gnus-browse-prev-group
-   [delete] gnus-browse-prev-group
-   "N" gnus-browse-next-group
-   "P" gnus-browse-prev-group
-   "\M-n" gnus-browse-next-group
-   "\M-p" gnus-browse-prev-group
-   "\r" gnus-browse-select-group
-   "u" gnus-browse-unsubscribe-current-group
-   "l" gnus-browse-exit
-   "L" gnus-browse-exit
-   "q" gnus-browse-exit
-   "Q" gnus-browse-exit
-   "\C-c\C-c" gnus-browse-exit
-   "?" gnus-browse-describe-briefly
-
-   "\C-c\C-i" gnus-info-find-node
-   "\C-c\C-b" gnus-bug))
+      gnus-browse-mode-map
+    " " gnus-browse-read-group
+    "=" gnus-browse-select-group
+    "n" gnus-browse-next-group
+    "p" gnus-browse-prev-group
+    "\177" gnus-browse-prev-group
+    [delete] gnus-browse-prev-group
+    "N" gnus-browse-next-group
+    "P" gnus-browse-prev-group
+    "\M-n" gnus-browse-next-group
+    "\M-p" gnus-browse-prev-group
+    "\r" gnus-browse-select-group
+    "u" gnus-browse-unsubscribe-current-group
+    "l" gnus-browse-exit
+    "L" gnus-browse-exit
+    "q" gnus-browse-exit
+    "Q" gnus-browse-exit
+    "d" gnus-browse-describe-group
+    "\C-c\C-c" gnus-browse-exit
+    "?" gnus-browse-describe-briefly
+
+    "\C-c\C-i" gnus-info-find-node
+    "\C-c\C-b" gnus-bug))
 
 (defun gnus-browse-make-menu-bar ()
   (gnus-turn-off-edit-menu 'browse)
@@ -534,9 +683,10 @@ The following commands are available:
      '("Browse"
        ["Subscribe" gnus-browse-unsubscribe-current-group t]
        ["Read" gnus-browse-read-group t]
-       ["Select" gnus-browse-read-group t]
+       ["Select" gnus-browse-select-group t]
+       ["Describe" gnus-browse-describe-group t]
        ["Next" gnus-browse-next-group t]
-       ["Prev" gnus-browse-next-group t]
+       ["Prev" gnus-browse-prev-group t]
        ["Exit" gnus-browse-exit t]))
     (gnus-run-hooks 'gnus-browse-menu-hook)))
 
@@ -547,9 +697,10 @@ The following commands are available:
 
 (defun gnus-browse-foreign-server (server &optional return-buffer)
   "Browse the server SERVER."
-  (setq gnus-browse-current-method server)
+  (setq gnus-browse-current-method (gnus-server-to-method server))
   (setq gnus-browse-return-buffer return-buffer)
-  (let* ((method (gnus-server-to-method server))
+  (let* ((method gnus-browse-current-method)
+        (orig-select-method gnus-select-method)
         (gnus-select-method method)
         groups group)
     (gnus-message 5 "Connecting to %s..." (nth 1 method))
@@ -568,41 +719,97 @@ The following commands are available:
        1 "Couldn't request list: %s" (gnus-status-message method))
       nil)
      (t
-      (get-buffer-create gnus-browse-buffer)
-      (gnus-add-current-to-buffer-list)
-      (when gnus-carpal
-       (gnus-carpal-setup-buffer 'browse))
-      (gnus-configure-windows 'browse)
-      (buffer-disable-undo (current-buffer))
-      (let ((buffer-read-only nil))
-       (erase-buffer))
-      (gnus-browse-mode)
-      (setq mode-line-buffer-identification
-           (list
-            (format
-             "Gnus: %%b {%s:%s}" (car method) (cadr method))))
-      (save-excursion
-       (set-buffer nntp-server-buffer)
+      (with-current-buffer nntp-server-buffer
        (let ((cur (current-buffer)))
          (goto-char (point-min))
          (unless (string= gnus-ignored-newsgroups "")
            (delete-matching-lines gnus-ignored-newsgroups))
-         (while (re-search-forward
-                 "\\(^[^ \t]+\\)[ \t]+[0-9]+[ \t]+[0-9]+" nil t)
-           (goto-char (match-end 1))
-           (push (cons (match-string 1)
-                       (max 0 (- (1+ (read cur)) (read cur))))
-                 groups))))
+         ;; We treat NNTP as a special case to avoid problems with
+         ;; garbage group names like `"foo' that appear in some badly
+         ;; managed active files. -jh.
+         (if (eq (car method) 'nntp)
+             (while (not (eobp))
+               (ignore-errors
+                 (push (cons 
+                        (buffer-substring 
+                         (point)
+                         (progn 
+                           (skip-chars-forward "^ \t")
+                           (point)))
+                        (let ((last (read cur)))
+                          (cons (read cur) last)))
+                       groups))
+               (forward-line))
+           (while (not (eobp))
+             (ignore-errors
+               (push (cons
+                      (if (eq (char-after) ?\")
+                          (read cur)
+                        (let ((p (point)) (name ""))
+                          (skip-chars-forward "^ \t\\\\")
+                          (setq name (buffer-substring p (point)))
+                          (while (eq (char-after) ?\\)
+                            (setq p (1+ (point)))
+                            (forward-char 2)
+                            (skip-chars-forward "^ \t\\\\")
+                            (setq name (concat name (buffer-substring
+                                                     p (point)))))
+                          name))
+                      (let ((last (read cur)))
+                        (cons (read cur) last)))
+                     groups))
+             (forward-line)))))
       (setq groups (sort groups
                         (lambda (l1 l2)
                           (string< (car l1) (car l2)))))
-      (let ((buffer-read-only nil))
-       (while groups
-         (setq group (car groups))
-         (insert
-          (format "K%7d: %s\n" (cdr group) (car group)))
-         (setq groups (cdr groups))))
-      (switch-to-buffer (current-buffer))
+      (if gnus-server-browse-in-group-buffer
+         (let* ((gnus-select-method orig-select-method)
+                (gnus-group-listed-groups
+                 (mapcar (lambda (group)
+                           (let ((name
+                                  (gnus-group-prefixed-name
+                                   (car group) method)))
+                             (gnus-set-active name (cdr group))
+                             name))
+                         groups)))
+           (gnus-configure-windows 'group)
+           (funcall gnus-group-prepare-function
+                    gnus-level-killed 'ignore 1 'ignore))
+       (gnus-get-buffer-create gnus-browse-buffer)
+       (when gnus-carpal
+         (gnus-carpal-setup-buffer 'browse))
+       (gnus-configure-windows 'browse)
+       (buffer-disable-undo)
+       (let ((buffer-read-only nil))
+         (erase-buffer))
+       (gnus-browse-mode)
+       (setq mode-line-buffer-identification
+             (list
+              (format
+               "Gnus: %%b {%s:%s}" (car method) (cadr method))))
+       (let ((buffer-read-only nil)
+             name
+             (prefix (let ((gnus-select-method orig-select-method))
+                       (gnus-group-prefixed-name "" method))))
+         (while (setq group (pop groups))
+           (gnus-add-text-properties
+            (point)
+            (prog1 (1+ (point))
+              (insert
+               (format "%c%7d: %s\n"
+                       (let ((level (gnus-group-level
+                                     (concat prefix (setq name (car group))))))
+                         (cond
+                          ((<= level gnus-level-subscribed) ? )
+                          ((<= level gnus-level-unsubscribed) ?U)
+                          ((= level gnus-level-zombie) ?Z)
+                          (t ?K)))
+                       (max 0 (- (1+ (cddr group)) (cadr group)))
+                       (decode-coding-string
+                        name
+                        (inline (gnus-group-name-charset method name))))))
+            (list 'gnus-group name))))
+       (switch-to-buffer (current-buffer)))
       (goto-char (point-min))
       (gnus-group-position-point)
       (gnus-message 5 "Connecting to %s...done" (nth 1 method))
@@ -632,7 +839,7 @@ buffer.
   (setq mode-name "Browse Server")
   (setq mode-line-process nil)
   (use-local-map gnus-browse-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq truncate-lines t)
   (gnus-set-default-directory)
   (setq buffer-read-only t)
@@ -650,7 +857,7 @@ buffer.
          (error "Couldn't enter %s" group))
       (unless (gnus-group-read-group nil no-article group)
        (error "Couldn't enter %s" group)))))
-      
+
 (defun gnus-browse-select-group ()
   "Select the current group."
   (interactive)
@@ -688,11 +895,16 @@ buffer.
 (defun gnus-browse-group-name ()
   (save-excursion
     (beginning-of-line)
-    (when (re-search-forward ": \\(.*\\)$" (gnus-point-at-eol) t)
-      (gnus-group-prefixed-name
-       ;; Remove text props.
-       (format "%s" (match-string 1))
-       gnus-browse-current-method))))
+    (let ((name (get-text-property (point) 'gnus-group)))
+      (when (re-search-forward ": \\(.*\\)$" (gnus-point-at-eol) t)
+       (concat (gnus-method-to-server-name gnus-browse-current-method) ":" 
+               (or name
+                   (match-string-no-properties 1)))))))
+
+(defun gnus-browse-describe-group (group)
+  "Describe the current group."
+  (interactive (list (gnus-browse-group-name)))
+  (gnus-group-describe-group nil group))
 
 (defun gnus-browse-unsubscribe-group ()
   "Toggle subscription of the current group in the browse buffer."
@@ -702,13 +914,11 @@ buffer.
     (save-excursion
       (beginning-of-line)
       ;; If this group it killed, then we want to subscribe it.
-      (when (= (following-char) ?K)
+      (unless (eq (char-after) ? )
        (setq sub t))
       (setq group (gnus-browse-group-name))
-      (when (and sub
-                (cadr (gnus-gethash group gnus-newsrc-hashtb)))
-       (error "Group already subscribed"))
-      (delete-char 1)
+      (when (gnus-server-equal gnus-browse-current-method "native")
+       (setq group (gnus-group-real-name group)))
       (if sub
          (progn
            ;; Make sure the group has been properly removed before we
@@ -719,23 +929,26 @@ buffer.
                   nil nil (if (gnus-server-equal
                                gnus-browse-current-method "native")
                               nil
-                            gnus-browse-current-method))
-            gnus-level-default-subscribed gnus-level-killed
+                            (gnus-method-simplify
+                             gnus-browse-current-method)))
+            gnus-level-default-subscribed (gnus-group-level group)
             (and (car (nth 1 gnus-newsrc-alist))
                  (gnus-gethash (car (nth 1 gnus-newsrc-alist))
                                gnus-newsrc-hashtb))
             t)
+           (delete-char 1)
            (insert ? ))
        (gnus-group-change-level
-        group gnus-level-killed gnus-level-default-subscribed)
-       (insert ?K)))
+        group gnus-level-unsubscribed gnus-level-default-subscribed)
+       (delete-char 1)
+       (insert ?U)))
     t))
 
 (defun gnus-browse-exit ()
   "Quit browsing and return to the group buffer."
   (interactive)
   (when (eq major-mode 'gnus-browse-mode)
-    (kill-buffer (current-buffer)))
+    (gnus-kill-buffer (current-buffer)))
   ;; Insert the newly subscribed groups in the group buffer.
   (save-excursion
     (set-buffer gnus-group-buffer)
@@ -756,16 +969,18 @@ buffer.
   (let ((server (gnus-server-server-name)))
     (unless server
       (error "No server on the current line"))
-    (if (not (gnus-check-backend-function
-             'request-regenerate (car (gnus-server-to-method server))))
-       (error "This backend doesn't support regeneration")
-      (gnus-message 5 "Requesting regeneration of %s..." server)
-      (unless (gnus-open-server server)
-       (error "Couldn't open server"))
-      (if (gnus-request-regenerate server)
-         (gnus-message 5 "Requesting regeneration of %s...done" server)
-       (gnus-message 5 "Couldn't regenerate %s" server)))))
+    (condition-case ()
+       (gnus-get-function (gnus-server-to-method server)
+                          'request-regenerate)
+      (error
+       (error "This backend doesn't support regeneration")))
+    (gnus-message 5 "Requesting regeneration of %s..." server)
+    (unless (gnus-open-server server)
+      (error "Couldn't open server"))
+    (if (gnus-request-regenerate server)
+       (gnus-message 5 "Requesting regeneration of %s...done" server)
+      (gnus-message 5 "Couldn't regenerate %s" server))))
 
 (provide 'gnus-srvr)
 
-;;; gnus-srvr.el ends here.
+;;; gnus-srvr.el ends here
index 974936e..122288a 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-start.el --- startup functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
+
 (require 'gnus)
 (require 'gnus-win)
 (require 'gnus-int)
 (require 'gnus-spec)
 (require 'gnus-range)
 (require 'gnus-util)
-(require 'message)
-(eval-when-compile (require 'cl))
+(autoload 'message-make-date "message")
+(autoload 'gnus-agent-read-servers-validate "gnus-agent")
+(autoload 'gnus-agent-possibly-alter-active "gnus-agent")
 
 (defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc")
   "Your `.newsrc' file.
   :group 'gnus-start
   :type 'file)
 
+(defcustom gnus-product-directory
+  (nnheader-concat gnus-directory (concat "." gnus-product-name))
+  "Product depend data files directory."
+  :group 'gnus-start
+  :type '(choice directory (const nil)))
+
+(defcustom gnus-backup-startup-file 'never
+  "Whether to create backup files.
+This variable takes the same values as the `version-control'
+variable."
+  :group 'gnus-start
+  :type '(choice (const :tag "Never" never)
+                (const :tag "If existing" nil)
+                (other :tag "Always" t)))
+
+(defcustom gnus-save-startup-file-via-temp-buffer t
+  "Whether to write the startup file contents to a buffer then save
+the buffer or write directly to the file.  The buffer is faster
+because all of the contents are written at once.  The direct write
+uses considerably less memory."
+  :group 'gnus-start
+  :type '(choice (const :tag "Write via buffer" t)
+                 (const :tag "Write directly to file" nil)))
+
 (defcustom gnus-init-file (nnheader-concat gnus-home-directory ".gnus")
   "Your Gnus Emacs-Lisp startup file name.
 If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
@@ -52,7 +81,7 @@ If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
               (directory-file-name installation-directory))
              "site-lisp/gnus-init")
     (error nil))
-  "*The site-wide Gnus Emacs-Lisp startup file name, or nil if none.
+  "The site-wide Gnus Emacs-Lisp startup file name, or nil if none.
 If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
   :group 'gnus-start
   :type '(choice file (const nil)))
@@ -142,27 +171,19 @@ properly with all servers."
                 (const some)
                 (const t)))
 
-(defcustom gnus-level-subscribed 5
-  "*Groups with levels less than or equal to this variable are subscribed."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-subscribed 5
+  "Groups with levels less than or equal to this variable are subscribed.")
 
-(defcustom gnus-level-unsubscribed 7
-  "*Groups with levels less than or equal to this variable are unsubscribed.
+(defconst gnus-level-unsubscribed 7
+  "Groups with levels less than or equal to this variable are unsubscribed.
 Groups with levels less than `gnus-level-subscribed', which should be
-less than this variable, are subscribed."
-  :group 'gnus-group-levels
-  :type 'integer)
+less than this variable, are subscribed.")
 
-(defcustom gnus-level-zombie 8
-  "*Groups with this level are zombie groups."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-zombie 8
+  "Groups with this level are zombie groups.")
 
-(defcustom gnus-level-killed 9
-  "*Groups with this level are killed."
-  :group 'gnus-group-levels
-  :type 'integer)
+(defconst gnus-level-killed 9
+  "Groups with this level are killed.")
 
 (defcustom gnus-level-default-subscribed 3
   "*New subscribed groups will be subscribed at this level."
@@ -197,6 +218,17 @@ groups."
   :type '(choice integer
                 (const :tag "none" nil)))
 
+(defcustom gnus-read-newsrc-file t
+  "*Non-nil means that Gnus will read the `.newsrc' file.
+Gnus always reads its own startup file, which is called
+\".newsrc.eld\".  The file called \".newsrc\" is in a format that can
+be readily understood by other newsreaders.  If you don't plan on
+using other newsreaders, set this variable to nil to save some time on
+entry."
+  :version "21.1"
+  :group 'gnus-newsrc
+  :type 'boolean)
+
 (defcustom gnus-save-newsrc-file t
   "*Non-nil means that Gnus will save the `.newsrc' file.
 Gnus always saves its own startup file, which is called
@@ -220,15 +252,20 @@ nil if you set this variable to nil.
 This variable can also be a regexp.  In that case, all groups that do
 not match this regexp will be removed before saving the list."
   :group 'gnus-newsrc
-  :type 'boolean)
+  :type '(radio (sexp :format "Non-nil\n"
+                     :match (lambda (widget value)
+                              (and value (not (stringp value))))
+                     :value t)
+               (const nil)
+               (regexp :format "%t: %v\n" :size 0)))
 
 (defcustom gnus-ignored-newsgroups
-  (purecopy (mapconcat 'identity
-                      '("^to\\."       ; not "real" groups
-                        "^[0-9. \t]+ " ; all digits in name
-                        "[][\"#'()]"   ; bogus characters
-                        )
-                      "\\|"))
+  (mapconcat 'identity
+            '("^to\\."                 ; not "real" groups
+              "^[0-9. \t]+\\( \\|$\\)" ; all digits in name
+              "^[\"][]\"[#'()]"        ; bogus characters
+              )
+            "\\|")
   "*A regexp to match uninteresting newsgroups in the active file.
 Any lines in the active file matching this regular expression are
 removed from the newsgroup list before anything else is done to it,
@@ -237,14 +274,16 @@ thus making them effectively non-existent."
   :type 'regexp)
 
 (defcustom gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
-  "*Function called with a group name when new group is detected.
+  "*Function(s) called with a group name when new group is detected.
 A few pre-made functions are supplied: `gnus-subscribe-randomly'
 inserts new groups at the beginning of the list of groups;
 `gnus-subscribe-alphabetically' inserts new groups in strict
 alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
 in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
 for your decision; `gnus-subscribe-killed' kills all new groups;
-`gnus-subscribe-zombies' will make all new groups into zombies."
+`gnus-subscribe-zombies' will make all new groups into zombies;
+`gnus-subscribe-topics' will enter groups into the topics that
+claim them."
   :group 'gnus-group-new
   :type '(radio (function-item gnus-subscribe-randomly)
                (function-item gnus-subscribe-alphabetically)
@@ -252,13 +291,19 @@ for your decision; `gnus-subscribe-killed' kills all new groups;
                (function-item gnus-subscribe-interactively)
                (function-item gnus-subscribe-killed)
                (function-item gnus-subscribe-zombies)
-               function))
+               (function-item gnus-subscribe-topics)
+               function
+               (repeat function)))
+
+(defcustom gnus-subscribe-newsgroup-hooks nil
+  "*Hooks run after you subscribe to a new group.
+The hooks will be called with new group's name as argument."
+  :group 'gnus-group-new
+  :type 'hook)
 
-;; Suggested by a bug report by Hallvard B Furuseth.
-;; <h.b.furuseth@usit.uio.no>.
 (defcustom gnus-subscribe-options-newsgroup-method
   'gnus-subscribe-alphabetically
-  "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
+  "*Function(s) called to subscribe newsgroups mentioned on \"options -n\" lines.
 If, for instance, you want to subscribe to all newsgroups in the
 \"no\" and \"alt\" hierarchies, you'd put the following in your
 .newsrc file:
@@ -274,7 +319,9 @@ the subscription method in this variable."
                (function-item gnus-subscribe-interactively)
                (function-item gnus-subscribe-killed)
                (function-item gnus-subscribe-zombies)
-               function))
+               (function-item gnus-subscribe-topics)
+               function
+               (repeat function)))
 
 (defcustom gnus-subscribe-hierarchical-interactive nil
   "*If non-nil, Gnus will offer to subscribe hierarchically.
@@ -289,7 +336,7 @@ hierarchy in its entirety."
   :type 'boolean)
 
 (defcustom gnus-auto-subscribed-groups
-  "nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
+  "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl\\|^nnmaildir"
   "*All new groups that match this regexp will be subscribed automatically.
 Note that this variable only deals with new groups.  It has no effect
 whatsoever on old groups.
@@ -349,23 +396,34 @@ This hook is called as the first thing when Gnus is started."
   :group 'gnus-start
   :type 'hook)
 
-(defcustom gnus-setup-news-hook nil
+(defcustom gnus-setup-news-hook
+  '(gnus-fixup-nnimap-unread-after-getting-new-news)
   "A hook after reading the .newsrc file, but before generating the buffer."
   :group 'gnus-start
   :type 'hook)
 
+(defcustom gnus-get-top-new-news-hook nil
+  "A hook run just before Gnus checks for new news globally."
+  :group 'gnus-group-new
+  :type 'hook)
+
 (defcustom gnus-get-new-news-hook nil
   "A hook run just before Gnus checks for new news."
   :group 'gnus-group-new
   :type 'hook)
 
 (defcustom gnus-after-getting-new-news-hook
-  (when (gnus-boundp 'display-time-timer)
-    '(display-time-event-handler))
-  "*A hook run after Gnus checks for new news."
+  '(gnus-display-time-event-handler
+    gnus-fixup-nnimap-unread-after-getting-new-news)
+  "A hook run after Gnus checks for new news when Gnus is already running."
   :group 'gnus-group-new
   :type 'hook)
 
+(defcustom gnus-read-newsrc-el-hook nil
+  "A hook called after reading the newsrc.eld? file."
+  :group 'gnus-newsrc
+  :type 'hook)
+
 (defcustom gnus-save-newsrc-hook nil
   "A hook called before saving any of the newsrc files."
   :group 'gnus-newsrc
@@ -383,10 +441,24 @@ Can be used to turn version control on or off."
   :group 'gnus-newsrc
   :type 'hook)
 
+(defcustom gnus-group-mode-hook nil
+  "Hook for Gnus group mode."
+  :group 'gnus-group-various
+  :options '(gnus-topic-mode)
+  :type 'hook)
+
+(defcustom gnus-always-read-dribble-file nil
+  "Unconditionally read the dribble file."
+  :group 'gnus-newsrc
+  :type 'boolean)
+
 ;;; Internal variables
 
-(defvar gnus-always-read-dribble-file nil
-  "Uncoditionally read the dribble file.")
+(defvar gnus-ding-file-coding-system (static-if (boundp 'MULE)
+                                        '*ctext*
+                                      'ctext)
+  "Coding system for ding file.")
+;; Note that the ding file for T-gnus ought not to have byte-codes.
 
 (defvar gnus-newsrc-file-version nil)
 (defvar gnus-override-subscribe-method nil)
@@ -414,19 +486,15 @@ Can be used to turn version control on or off."
     (if gnus-init-inhibit
        (setq gnus-init-inhibit nil)
       (setq gnus-init-inhibit inhibit-next)
-      (let ((files (list gnus-site-init-file gnus-init-file))
-           file)
-       (while files
-         (and (setq file (pop files))
-              (or (and (file-exists-p file)
-                       ;; Don't try to load a directory.
-                       (not (file-directory-p file)))
-                  (file-exists-p (concat file ".el"))
-                  (file-exists-p (concat file ".elc")))
-              (condition-case var
-                  (load file nil t)
-                (error
-                 (error "Error in %s: %s" file var)))))))))
+      (dolist (file (list gnus-site-init-file gnus-init-file))
+       (when (and file
+                  (locate-library file))
+         (if (or debug-on-error debug-on-quit)
+             (load file nil t)
+           (condition-case var
+               (load file nil t)
+             (error
+              (error "Error in %s: %s" file (cadr var))))))))))
 
 ;; For subscribing new newsgroup
 
@@ -502,7 +570,7 @@ Can be used to turn version control on or off."
   (gnus-subscribe-newsgroup newsgroup))
 
 (defun gnus-subscribe-alphabetically (newgroup)
-  "Subscribe new NEWSGROUP and insert it in alphabetical order."
+  "Subscribe new NEWGROUP and insert it in alphabetical order."
   (let ((groups (cdr gnus-newsrc-alist))
        before)
     (while (and (not before) groups)
@@ -512,26 +580,26 @@ Can be used to turn version control on or off."
     (gnus-subscribe-newsgroup newgroup before)))
 
 (defun gnus-subscribe-hierarchically (newgroup)
-  "Subscribe new NEWSGROUP and insert it in hierarchical newsgroup order."
+  "Subscribe new NEWGROUP and insert it in hierarchical newsgroup order."
   ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
   (save-excursion
     (set-buffer (nnheader-find-file-noselect gnus-current-startup-file))
-    (let ((groupkey newgroup)
-         before)
-      (while (and (not before) groupkey)
-       (goto-char (point-min))
-       (let ((groupkey-re
-              (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
-         (while (and (re-search-forward groupkey-re nil t)
-                     (progn
-                       (setq before (match-string 1))
-                       (string< before newgroup)))))
-       ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
-       (setq groupkey
-             (when (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
-               (substring groupkey (match-beginning 1) (match-end 1)))))
-      (gnus-subscribe-newsgroup newgroup before))
-    (kill-buffer (current-buffer))))
+    (prog1
+       (let ((groupkey newgroup) before)
+         (while (and (not before) groupkey)
+           (goto-char (point-min))
+           (let ((groupkey-re
+                  (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
+             (while (and (re-search-forward groupkey-re nil t)
+                         (progn
+                           (setq before (match-string 1))
+                           (string< before newgroup)))))
+           ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
+           (setq groupkey
+                 (when (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
+                   (substring groupkey (match-beginning 1) (match-end 1)))))
+         (gnus-subscribe-newsgroup newgroup before))
+      (kill-buffer (current-buffer)))))
 
 (defun gnus-subscribe-interactively (group)
   "Subscribe the new GROUP interactively.
@@ -560,7 +628,9 @@ the first newsgroup."
      newsgroup gnus-level-default-subscribed
      gnus-level-killed (gnus-gethash (or next "dummy.group")
                                     gnus-newsrc-hashtb))
-    (gnus-message 5 "Subscribe newsgroup: %s" newsgroup)))
+    (gnus-message 5 "Subscribe newsgroup: %s" newsgroup)
+    (run-hook-with-args 'gnus-subscribe-newsgroup-hooks newsgroup)
+    t))
 
 (defun gnus-read-active-file-p ()
   "Say whether the active file has been read from `gnus-select-method'."
@@ -569,26 +639,52 @@ the first newsgroup."
 ;;; General various misc type functions.
 
 ;; Silence byte-compiler.
-(defvar gnus-current-headers)
-(defvar gnus-thread-indent-array)
-(defvar gnus-newsgroup-name)
-(defvar gnus-newsgroup-headers)
-(defvar gnus-group-list-mode)
-(defvar gnus-group-mark-positions)
-(defvar gnus-newsgroup-data)
-(defvar gnus-newsgroup-unreads)
-(defvar nnoo-state-alist)
-(defvar gnus-current-select-method)
-(defun gnus-clear-system ()
-  "Clear all variables and buffers."
-  ;; Clear Gnus variables.
+(eval-when-compile
+  (defvar gnus-current-headers)
+  (defvar gnus-thread-indent-array)
+  (defvar gnus-newsgroup-name)
+  (defvar gnus-newsgroup-headers)
+  (defvar gnus-group-list-mode)
+  (defvar gnus-group-mark-positions)
+  (defvar gnus-newsgroup-data)
+  (defvar gnus-newsgroup-unreads)
+  (defvar nnoo-state-alist)
+  (defvar gnus-current-select-method)
+  (defvar mail-sources)
+  (defvar nnmail-scan-directory-mail-source-once)
+  (defvar nnmail-split-history)
+  (defvar nnmail-spool-file))
+
+(defun gnus-clear-quick-file-variables ()
+  "Clear all variables in quick startup files."
   (let ((variables gnus-variable-list))
+    ;; Clear Gnus variables.
     (while variables
       (set (car variables) nil)
       (setq variables (cdr variables))))
+  (let ((files gnus-product-variable-file-list))
+    (while files
+      (let ((variables (nthcdr 3 (car files))))
+       (while variables
+         (set (car variables) nil)
+         (setq variables (cdr variables))))
+      (setq files (cdr files)))))
+
+(defun gnus-close-all-servers ()
+  "Close all servers."
+  (interactive)
+  (dolist (server gnus-opened-servers)
+    (gnus-close-server (car server))))
+
+(defun gnus-clear-system ()
+  "Clear all variables and buffers."
+  ;; Clear gnus variables.
+  (gnus-clear-quick-file-variables)
   ;; Clear other internal variables.
   (setq gnus-list-of-killed-groups nil
        gnus-have-read-active-file nil
+        gnus-agent-covered-methods nil
+        gnus-server-method-cache nil
        gnus-newsrc-alist nil
        gnus-newsrc-hashtb nil
        gnus-killed-list nil
@@ -609,6 +705,7 @@ the first newsgroup."
        gnus-newsgroup-unreads nil
        nnoo-state-alist nil
        gnus-current-select-method nil
+       nnmail-split-history nil
        gnus-ephemeral-servers nil)
   (gnus-shutdown 'gnus)
   ;; Kill the startup file.
@@ -622,8 +719,8 @@ the first newsgroup."
     (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
   (gnus-kill-buffer nntp-server-buffer)
   ;; Kill Gnus buffers.
-  (while gnus-buffer-list
-    (gnus-kill-buffer (pop gnus-buffer-list)))
+  (dolist (buffer (gnus-buffers))
+    (gnus-kill-buffer buffer))
   ;; Remove Gnus frames.
   (gnus-kill-gnus-frames))
 
@@ -655,19 +752,21 @@ prompt the user for the name of an NNTP server to use."
              (> arg 0)
              (max (car gnus-group-list-mode) arg))))
 
-    (gnus-splash)
     (gnus-clear-system)
+    (gnus-splash)
     (gnus-run-hooks 'gnus-before-startup-hook)
     (nnheader-init-server-buffer)
     (setq gnus-slave slave)
     (gnus-read-init-file)
+    (if gnus-agent
+       (gnus-agentize))
 
     (when gnus-simple-splash
       (setq gnus-simple-splash nil)
       (cond
-       (gnus-xemacs
+       ((featurep 'xemacs)
        (gnus-xmas-splash))
-       ((and (eq window-system 'x)
+       ((and window-system
             (= (frame-height) (1+ (window-height))))
        (gnus-x-splash))))
 
@@ -698,6 +797,9 @@ prompt the user for the name of an NNTP server to use."
            (add-hook 'gnus-summary-mode-hook 'gnus-grouplens-mode))
 
          ;; Do the actual startup.
+         (if gnus-agent
+             (gnus-request-create-group "queue" '(nndraft "")))
+         (gnus-request-create-group "drafts" '(nndraft ""))
          (gnus-setup-news nil level dont-connect)
          (gnus-run-hooks 'gnus-setup-news-hook)
          (gnus-start-draft-setup)
@@ -706,6 +808,8 @@ prompt the user for the name of an NNTP server to use."
          (gnus-group-first-unread-group)
          (gnus-configure-windows 'group)
          (gnus-group-set-mode-line)
+         ;; For reading Info.
+         (set-language-info "Japanese" 'gnus-info "gnus-ja")
          (gnus-run-hooks 'gnus-started-hook))))))
 
 (defun gnus-start-draft-setup ()
@@ -717,20 +821,6 @@ prompt the user for the name of an NNTP server to use."
     (gnus-group-set-parameter
      "nndraft:drafts" 'gnus-dummy '((gnus-draft-mode)))))
 
-;;;###autoload
-(defun gnus-unload ()
-  "Unload all Gnus features."
-  (interactive)
-  (unless (boundp 'load-history)
-    (error "Sorry, `gnus-unload' is not implemented in this Emacs version"))
-  (let ((history load-history)
-       feature)
-    (while history
-      (and (string-match "^\\(gnus\\|nn\\)" (caar history))
-          (setq feature (cdr (assq 'provide (car history))))
-          (unload-feature feature 'force))
-      (setq history (cdr history)))))
-
 \f
 ;;;
 ;;; Dribble file
@@ -757,7 +847,11 @@ prompt the user for the name of an NNTP server to use."
       (set-buffer gnus-dribble-buffer)
       (goto-char (point-max))
       (insert string "\n")
-      (set-window-point (get-buffer-window (current-buffer)) (point-max))
+      ;; This has been commented by Josh Huber <huber@alum.wpi.edu>
+      ;; It causes problems with both XEmacs and Emacs 21, and doesn't
+      ;; seem to be of much value. (FIXME: remove this after we make sure
+      ;; it's not needed).
+      ;; (set-window-point (get-buffer-window (current-buffer)) (point-max))
       (bury-buffer gnus-dribble-buffer)
       (save-excursion
        (set-buffer gnus-group-buffer)
@@ -773,17 +867,17 @@ prompt the user for the name of an NNTP server to use."
   (let ((dribble-file (gnus-dribble-file-name)))
     (save-excursion
       (set-buffer (setq gnus-dribble-buffer
-                       (get-buffer-create
+                       (gnus-get-buffer-create
                         (file-name-nondirectory dribble-file))))
-      (gnus-add-current-to-buffer-list)
       (erase-buffer)
       (setq buffer-file-name dribble-file)
       (auto-save-mode t)
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (bury-buffer (current-buffer))
       (set-buffer-modified-p nil)
       (let ((auto (make-auto-save-file-name))
            (gnus-dribble-ignore t)
+           (purpose nil)
            modes)
        (when (or (file-exists-p auto) (file-exists-p dribble-file))
          ;; Load whichever file is newest -- the auto save file
@@ -799,10 +893,15 @@ prompt the user for the name of an NNTP server to use."
                     (file-exists-p dribble-file)
                     (setq modes (file-modes gnus-current-startup-file)))
            (set-file-modes dribble-file modes))
+         (goto-char (point-min))
+         (when (search-forward "Gnus was exited on purpose" nil t)
+           (setq purpose t))
          ;; Possibly eval the file later.
          (when (or gnus-always-read-dribble-file
                    (gnus-y-or-n-p
-                    "Gnus auto-save file exists.  Do you want to read it? "))
+                    (if purpose
+                        "Gnus exited on purpose without saving; read auto-save file anyway? "
+                      "Gnus auto-save file exists.  Do you want to read it? ")))
            (setq gnus-dribble-eval-file t)))))))
 
 (defun gnus-dribble-eval-file ()
@@ -849,7 +948,11 @@ prompt the user for the name of an NNTP server to use."
   "Setup news information.
 If RAWFILE is non-nil, the .newsrc file will also be read.
 If LEVEL is non-nil, the news will be set up at level LEVEL."
-  (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile)))))
+  (require 'nnmail)
+  (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile))))
+       ;; Binding this variable will inhibit multiple fetchings
+       ;; of the same mail source.
+       (nnmail-fetched-sources (list t)))
 
     (when init
       ;; Clear some variables to re-initialize news information.
@@ -860,10 +963,17 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
     ;; Make sure the archive server is available to all and sundry.
     (when gnus-message-archive-method
-      (setq gnus-server-alist (delq (assoc "archive" gnus-server-alist)
-                                   gnus-server-alist))
-      (push (cons "archive" gnus-message-archive-method)
-           gnus-server-alist))
+      (unless (assoc "archive" gnus-server-alist)
+       (push `("archive"
+               nnfolder
+               "archive"
+               (nnfolder-directory
+                ,(nnheader-concat message-directory "archive"))
+               (nnfolder-active-file
+                ,(nnheader-concat message-directory "archive/active"))
+               (nnfolder-get-new-mail nil)
+               (nnfolder-inhibit-expiry t))
+             gnus-server-alist)))
 
     ;; If we don't read the complete active file, we fill in the
     ;; hashtb here.
@@ -871,6 +981,15 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
              (eq gnus-read-active-file 'some))
       (gnus-update-active-hashtb-from-killed))
 
+    ;; Validate agent covered methods now that gnus-server-alist has
+    ;; been initialized.
+    ;; NOTE: This is here for one purpose only.  By validating the
+    ;; agentized server's, it converts the old 5.10.3, and earlier,
+    ;; format to the current format.  That enables the agent code
+    ;; within gnus-read-active-file to function correctly.
+    (if gnus-agent
+        (gnus-agent-read-servers-validate))
+
     ;; Read the active file and create `gnus-active-hashtb'.
     ;; If `gnus-read-active-file' is nil, then we just create an empty
     ;; hash table.  The partial filling out of the hash table will be
@@ -899,6 +1018,7 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
     ;; See whether we need to read the description file.
     (when (and (boundp 'gnus-group-line-format)
+              (stringp gnus-group-line-format)
               (let ((case-fold-search nil))
                 (string-match "%[-,0-9]*D" gnus-group-line-format))
               (not gnus-description-hashtb)
@@ -913,6 +1033,12 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
               gnus-plugged)
       (gnus-find-new-newsgroups))
 
+    ;; Check and remove bogus newsgroups.
+    (when (and init gnus-check-bogus-newsgroups
+              gnus-read-active-file (not level)
+              (gnus-server-opened gnus-select-method))
+      (gnus-check-bogus-newsgroups))
+
     ;; We might read in new NoCeM messages here.
     (when (and gnus-use-nocem
               (not level)
@@ -924,24 +1050,46 @@ If LEVEL is non-nil, the news will be set up at level LEVEL."
 
     ;; Find the number of unread articles in each non-dead group.
     (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
-      (gnus-get-unread-articles level))
-
-    (when (and init gnus-check-bogus-newsgroups
-              gnus-read-active-file (not level)
-              (gnus-server-opened gnus-select-method))
-      (gnus-check-bogus-newsgroups))))
+      (gnus-get-unread-articles level))))
+
+(defun gnus-call-subscribe-functions (method group)
+  "Call METHOD to subscribe GROUP.
+If no function returns `non-nil', call `gnus-subscribe-zombies'."
+  (unless (cond
+          ((functionp method)
+           (funcall method group))
+          ((listp method)
+           (catch 'found
+             (dolist (func method)
+               (if (funcall func group)
+                   (throw 'found t)))
+             nil))
+          (t nil))
+    (gnus-subscribe-zombies group)))
 
 (defun gnus-find-new-newsgroups (&optional arg)
   "Search for new newsgroups and add them.
-Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method.'
+Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method'.
 The `-n' option line from .newsrc is respected.
-If ARG (the prefix), use the `ask-server' method to query the server
-for new groups."
-  (interactive "P")
-  (let ((check (if (or (and arg (not (listp gnus-check-new-newsgroups)))
-                      (null gnus-read-active-file)
-                      (eq gnus-read-active-file 'some))
-                  'ask-server gnus-check-new-newsgroups)))
+
+With 1 C-u, use the `ask-server' method to query the server for new
+groups.
+With 2 C-u's, use most complete method possible to query the server
+for new groups, and subscribe the new groups as zombies."
+  (interactive "p")
+  (let* ((gnus-subscribe-newsgroup-method
+         gnus-subscribe-newsgroup-method)
+        (check (cond
+                ((or (and (= (or arg 1) 4)
+                          (not (listp gnus-check-new-newsgroups)))
+                     (null gnus-read-active-file)
+                     (eq gnus-read-active-file 'some))
+                 'ask-server)
+                ((= (or arg 1) 16)
+                 (setq gnus-subscribe-newsgroup-method
+                       'gnus-subscribe-zombies)
+                 t)
+                (t gnus-check-new-newsgroups))))
     (unless (gnus-check-first-time-used)
       (if (or (consp check)
              (eq check 'ask-server))
@@ -953,7 +1101,7 @@ for new groups."
          (gnus-message 5 "Looking for new newsgroups...")
          (unless gnus-have-read-active-file
            (gnus-read-active-file))
-         (setq gnus-newsrc-last-checked-date (current-time-string))
+         (setq gnus-newsrc-last-checked-date (message-make-date))
          (unless gnus-killed-hashtb
            (gnus-make-hashtable-from-killed))
          ;; Go though every newsgroup in `gnus-active-hashtb' and compare
@@ -971,7 +1119,8 @@ for new groups."
                  ((eq do-sub 'subscribe)
                   (setq groups (1+ groups))
                   (gnus-sethash group group gnus-killed-hashtb)
-                  (funcall gnus-subscribe-options-newsgroup-method group))
+                  (gnus-call-subscribe-functions
+                   gnus-subscribe-options-newsgroup-method group))
                  ((eq do-sub 'ignore)
                   nil)
                  (t
@@ -979,7 +1128,8 @@ for new groups."
                   (gnus-sethash group group gnus-killed-hashtb)
                   (if gnus-subscribe-hierarchical-interactive
                       (push group new-newsgroups)
-                    (funcall gnus-subscribe-newsgroup-method group)))))))
+                    (gnus-call-subscribe-functions
+                     gnus-subscribe-newsgroup-method group)))))))
           gnus-active-hashtb)
          (when new-newsgroups
            (gnus-subscribe-hierarchical-interactive new-newsgroups))
@@ -1016,7 +1166,8 @@ for new groups."
       (and regs (cdar regs))))))
 
 (defun gnus-ask-server-for-new-groups ()
-  (let* ((date (or gnus-newsrc-last-checked-date (current-time-string)))
+  (let* ((new-date (message-make-date))
+        (date (or gnus-newsrc-last-checked-date new-date))
         (methods (cons gnus-select-method
                        (nconc
                         (when (gnus-archive-server-wanted-p)
@@ -1026,7 +1177,6 @@ for new groups."
                               gnus-check-new-newsgroups)
                          gnus-secondary-select-methods))))
         (groups 0)
-        (new-date (current-time-string))
         group new-newsgroups got-new method hashtb
         gnus-override-subscribe-method)
     (unless gnus-killed-hashtb
@@ -1034,13 +1184,13 @@ for new groups."
     ;; Go through both primary and secondary select methods and
     ;; request new newsgroups.
     (while (setq method (gnus-server-get-method nil (pop methods)))
-      (setq new-newsgroups nil)
-      (setq gnus-override-subscribe-method method)
+      (setq new-newsgroups nil
+           gnus-override-subscribe-method method)
       (when (and (gnus-check-server method)
                 (gnus-request-newgroups date method))
        (save-excursion
-         (setq got-new t)
-         (setq hashtb (gnus-make-hashtable 100))
+         (setq got-new t
+               hashtb (gnus-make-hashtable 100))
          (set-buffer nntp-server-buffer)
          ;; Enter all the new groups into a hashtable.
          (gnus-active-to-gnus-format method hashtb 'ignore))
@@ -1064,7 +1214,8 @@ for new groups."
                ((eq do-sub 'subscribe)
                 (incf groups)
                 (gnus-sethash group group gnus-killed-hashtb)
-                (funcall gnus-subscribe-options-newsgroup-method group))
+                (gnus-call-subscribe-functions
+                 gnus-subscribe-options-newsgroup-method group))
                ((eq do-sub 'ignore)
                 nil)
                (t
@@ -1072,63 +1223,75 @@ for new groups."
                 (gnus-sethash group group gnus-killed-hashtb)
                 (if gnus-subscribe-hierarchical-interactive
                     (push group new-newsgroups)
-                  (funcall gnus-subscribe-newsgroup-method group)))))))
+                  (gnus-call-subscribe-functions
+                   gnus-subscribe-newsgroup-method group)))))))
         hashtb))
       (when new-newsgroups
        (gnus-subscribe-hierarchical-interactive new-newsgroups)))
-     (if (> groups 0)
-        (gnus-message 5 "%d new newsgroup%s arrived"
-                      groups (if (> groups 1) "s have" " has"))
-       (gnus-message 5 "No new newsgroups"))
+    (if (> groups 0)
+       (gnus-message 5 "%d new newsgroup%s arrived"
+                     groups (if (> groups 1) "s have" " has"))
+      (gnus-message 5 "No new newsgroups"))
     (when got-new
       (setq gnus-newsrc-last-checked-date new-date))
     got-new))
 
 (defun gnus-check-first-time-used ()
-  (if (or (> (length gnus-newsrc-alist) 1)
-         (file-exists-p gnus-startup-file)
-         (file-exists-p (concat gnus-startup-file ".el"))
-         (file-exists-p (concat gnus-startup-file ".eld")))
-      nil
+  (catch 'ended
+    ;; First check if any of the following files exist.  If they do,
+    ;; it's not the first time the user has used Gnus.
+    (dolist (file (list (concat gnus-current-startup-file ".el")
+                       (concat gnus-current-startup-file ".eld")
+                       (concat gnus-startup-file ".el")
+                       (concat gnus-startup-file ".eld")))
+      (when (file-exists-p file)
+       (throw 'ended nil)))
     (gnus-message 6 "First time user; subscribing you to default groups")
     (unless (gnus-read-active-file-p)
       (let ((gnus-read-active-file t))
        (gnus-read-active-file)))
-    (setq gnus-newsrc-last-checked-date (current-time-string))
-    (let ((groups gnus-default-subscribed-newsgroups)
+    (setq gnus-newsrc-last-checked-date (message-make-date))
+    ;; Subscribe to the default newsgroups.
+    (let ((groups (or gnus-default-subscribed-newsgroups
+                     gnus-backup-default-subscribed-newsgroups))
          group)
       (if (eq groups t)
-         nil
-       (setq groups (or groups gnus-backup-default-subscribed-newsgroups))
-       (mapatoms
-        (lambda (sym)
-          (if (null (setq group (symbol-name sym)))
-              ()
-            (let ((do-sub (gnus-matches-options-n group)))
-              (cond
-               ((eq do-sub 'subscribe)
-                (gnus-sethash group group gnus-killed-hashtb)
-                (funcall gnus-subscribe-options-newsgroup-method group))
-               ((eq do-sub 'ignore)
-                nil)
-               (t
-                (push group gnus-killed-list))))))
-        gnus-active-hashtb)
-       (while groups
-         (when (gnus-active (car groups))
+         ;; If t, we subscribe (or not) all groups as if they were new.
+         (mapatoms
+          (lambda (sym)
+            (when (setq group (symbol-name sym))
+              (let ((do-sub (gnus-matches-options-n group)))
+                (cond
+                 ((eq do-sub 'subscribe)
+                  (gnus-sethash group group gnus-killed-hashtb)
+                  (gnus-call-subscribe-functions
+                   gnus-subscribe-options-newsgroup-method group))
+                 ((eq do-sub 'ignore)
+                  nil)
+                 (t
+                  (push group gnus-killed-list))))))
+          gnus-active-hashtb)
+       (dolist (group groups)
+         ;; Only subscribe the default groups that are activated.
+         (when (gnus-active group)
            (gnus-group-change-level
-            (car groups) gnus-level-default-subscribed gnus-level-killed))
-         (setq groups (cdr groups)))
-       (gnus-group-make-help-group)
+            group gnus-level-default-subscribed gnus-level-killed)))
+       (save-excursion
+         (set-buffer gnus-group-buffer)
+         ;; Don't error if the group already exists. This happens when a
+         ;; first-time user types 'F'. -- didier
+         (gnus-group-make-help-group t))
        (when gnus-novice-user
          (gnus-message 7 "`A k' to list killed groups"))))))
 
-(defun gnus-subscribe-group (group previous &optional method)
+(defun gnus-subscribe-group (group &optional previous method)
+  "Subscribe GROUP and put it after PREVIOUS."
   (gnus-group-change-level
    (if method
        (list t group gnus-level-default-subscribed nil nil method)
      group)
-   gnus-level-default-subscribed gnus-level-killed previous t))
+   gnus-level-default-subscribed gnus-level-killed previous t)
+  t)
 
 ;; `gnus-group-change-level' is the fundamental function for changing
 ;; subscription levels of newsgroups.  This might mean just changing
@@ -1182,9 +1345,9 @@ for new groups."
       ;; it from the newsrc hash table and assoc.
       (cond
        ((>= oldlevel gnus-level-zombie)
-       (if (= oldlevel gnus-level-zombie)
-           (setq gnus-zombie-list (delete group gnus-zombie-list))
-         (setq gnus-killed-list (delete group gnus-killed-list))))
+       ;; oldlevel could be wrong.
+       (setq gnus-zombie-list (delete group gnus-zombie-list))
+       (setq gnus-killed-list (delete group gnus-killed-list)))
        (t
        (when (and (>= level gnus-level-zombie)
                   entry)
@@ -1207,7 +1370,11 @@ for new groups."
        (unless (gnus-group-foreign-p group)
          (if (= level gnus-level-zombie)
              (push group gnus-zombie-list)
-           (push group gnus-killed-list))))
+           (if (= oldlevel gnus-level-killed)
+               ;; Remove from active hashtb.
+               (unintern group gnus-active-hashtb)
+             ;; Don't add it into killed-list if it was killed.
+             (push group gnus-killed-list)))))
        (t
        ;; If the list is to be entered into the newsrc assoc, and
        ;; it was killed, we have to create an entry in the newsrc
@@ -1223,14 +1390,14 @@ for new groups."
            (setq active (gnus-active group))
            (setq num
                  (if active (- (1+ (cdr active)) (car active)) t))
-           ;; Check whether the group is foreign.  If so, the
-           ;; foreign select method has to be entered into the
-           ;; info.
-           (let ((method (or gnus-override-subscribe-method
-                             (gnus-group-method group))))
-             (if (eq method gnus-select-method)
-                 (setq info (list group level nil))
-               (setq info (list group level nil nil method)))))
+           ;; Shorten the select method if possible, if we need to
+           ;; store it at all (native groups).
+           (let ((method (gnus-method-simplify
+                          (or gnus-override-subscribe-method
+                              (gnus-group-method group)))))
+             (if method
+                 (setq info (list group level nil nil method))
+               (setq info (list group level nil)))))
          (unless previous
            (setq previous
                  (let ((p gnus-newsrc-alist))
@@ -1275,7 +1442,9 @@ newsgroup."
        (setq info (pop newsrc)
              group (gnus-info-group info))
        (unless (or (gnus-active group) ; Active
-                   (gnus-info-method info)) ; Foreign
+                   (and (gnus-info-method info)
+                        (not (gnus-secondary-method-p
+                              (gnus-info-method info))))) ; Foreign
          ;; Found a bogus newsgroup.
          (push group bogus)))
       (if confirm
@@ -1346,22 +1515,28 @@ newsgroup."
                (gnus-check-backend-function 'request-scan (car method))
                (gnus-request-scan group method))
           t)
-        (condition-case ()
+        (if (or debug-on-error debug-on-quit)
             (inline (gnus-request-group group dont-check method))
-          (error nil)
-          (quit nil))
-        (setq active (gnus-parse-active))
-        ;; If there are no articles in the group, the GROUP
-        ;; command may have responded with the `(0 . 0)'.  We
-        ;; ignore this if we already have an active entry
-        ;; for the group.
-        (if (and (zerop (car active))
-                 (zerop (cdr active))
-                 (gnus-active group))
-            (gnus-active group)
-          (gnus-set-active group active)
-          ;; Return the new active info.
-          active))))
+          (condition-case nil
+              (inline (gnus-request-group group dont-check method))
+            ;;(error nil)
+            (quit
+             (message "Quit activating %s" group)
+             nil)))
+        (unless dont-check
+          (setq active (gnus-parse-active))
+          ;; If there are no articles in the group, the GROUP
+          ;; command may have responded with the `(0 . 0)'.  We
+          ;; ignore this if we already have an active entry
+          ;; for the group.
+          (if (and (zerop (car active))
+                   (zerop (cdr active))
+                   (gnus-active group))
+              (gnus-active group)
+
+            (gnus-set-active group active)
+            ;; Return the new active info.
+            active)))))
 
 (defun gnus-get-unread-articles-in-group (info active &optional update)
   (when active
@@ -1371,12 +1546,19 @@ newsgroup."
                info (inline (gnus-find-method-for-group
                              (gnus-info-group info)))))
       (gnus-activate-group (gnus-info-group info) nil t))
+
     (let* ((range (gnus-info-read info))
           (num 0))
       ;; If a cache is present, we may have to alter the active info.
       (when (and gnus-use-cache info)
        (inline (gnus-cache-possibly-alter-active
                 (gnus-info-group info) active)))
+
+      ;; If the agent is enabled, we may have to alter the active info.
+      (when (and gnus-agent info)
+       (gnus-agent-possibly-alter-active
+        (gnus-info-group info) active))
+
       ;; Modify the list of read articles according to what articles
       ;; are available; then tally the unread articles and add the
       ;; number to the group hash table entry.
@@ -1419,7 +1601,7 @@ newsgroup."
        ;; Then we want to peel off any elements that are higher
        ;; than the upper active limit.
        (let ((srange range))
-         ;; Go past all legal elements.
+         ;; Go past all valid elements.
          (while (and (cdr srange)
                      (<= (or (and (atom (cadr srange))
                                   (cadr srange))
@@ -1427,7 +1609,7 @@ newsgroup."
                          (cdr active)))
            (setq srange (cdr srange)))
          (when (cdr srange)
-           ;; Nuke all remaining illegal elements.
+           ;; Nuke all remaining invalid elements.
            (setcdr srange nil))
 
          ;; Adjust the final element.
@@ -1443,13 +1625,15 @@ newsgroup."
          (setq range (cdr range)))
        (setq num (max 0 (- (cdr active) num)))))
       ;; Set the number of unread articles.
-      (when info
+      (when (and info
+                (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb))
        (setcar (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb) num))
       num)))
 
 ;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
 ;; and compute how many unread articles there are in each group.
 (defun gnus-get-unread-articles (&optional level)
+  (setq gnus-server-method-cache nil)
   (let* ((newsrc (cdr gnus-newsrc-alist))
         (level (or level gnus-activate-level (1+ gnus-level-subscribed)))
         (foreign-level
@@ -1461,8 +1645,11 @@ newsgroup."
                  gnus-activate-foreign-newsgroups)
                 (t 0))
           level))
-        info group active method)
-    (gnus-message 5 "Checking new news...")
+        (methods-cache nil)
+        (type-cache nil)
+        scanned-methods info group active method retrieve-groups cmethod
+        method-type)
+    (gnus-message 6 "Checking new news...")
 
     (while newsrc
       (setq active (gnus-active (setq group (gnus-info-group
@@ -1473,35 +1660,117 @@ newsgroup."
       ;; be reached) we just set the number of unread articles in this
       ;; newsgroup to t.  This means that Gnus thinks that there are
       ;; unread articles, but it has no idea how many.
-      (if (and (setq method (gnus-info-method info))
-              (not (inline
-                     (gnus-server-equal
-                      gnus-select-method
-                      (setq method (gnus-server-get-method nil method)))))
-              (not (gnus-secondary-method-p method)))
+
+      ;; To be more explicit:
+      ;; >0 for an active group with messages
+      ;; 0 for an active group with no unread messages
+      ;; nil for non-foreign groups that the user has requested not be checked
+      ;; t for unchecked foreign groups or bogus groups, or groups that can't
+      ;;   be checked, for one reason or other.
+      (when (setq method (gnus-info-method info))
+       (if (setq cmethod (assoc method methods-cache))
+           (setq method (cdr cmethod))
+         (setq cmethod (inline (gnus-server-get-method nil method)))
+         (push (cons method cmethod) methods-cache)
+         (setq method cmethod)))
+      (when (and method
+                (not (setq method-type (cdr (assoc method type-cache)))))
+       (setq method-type
+             (cond
+              ((gnus-secondary-method-p method)
+               'secondary)
+              ((inline (gnus-server-equal gnus-select-method method))
+               'primary)
+              (t
+               'foreign)))
+       (push (cons method method-type) type-cache))
+      (if (and method
+              (eq method-type 'foreign))
          ;; These groups are foreign.  Check the level.
-         (when (<= (gnus-info-level info) foreign-level)
-           (setq active (gnus-activate-group group 'scan))
+         (when (and (<= (gnus-info-level info) foreign-level)
+                    (setq active (gnus-activate-group group 'scan)))
+           ;; Let the Gnus agent save the active file.
+           (when (and gnus-agent active (gnus-online method))
+             (gnus-agent-save-group-info
+              method (gnus-group-real-name group) active))
            (unless (inline (gnus-virtual-group-p group))
              (inline (gnus-close-group group)))
            (when (fboundp (intern (concat (symbol-name (car method))
                                           "-request-update-info")))
              (inline (gnus-request-update-info info method))))
        ;; These groups are native or secondary.
-       (when (and (<= (gnus-info-level info) level)
-                  (not gnus-read-active-file))
-         (setq active (gnus-activate-group group 'scan))
-         (inline (gnus-close-group group))))
+       (cond
+        ;; We don't want these groups.
+        ((> (gnus-info-level info) level)
+         (setq active 'ignore))
+        ;; Activate groups.
+        ((not gnus-read-active-file)
+         (if (gnus-check-backend-function 'retrieve-groups group)
+             ;; if server support gnus-retrieve-groups we push
+             ;; the group onto retrievegroups for later checking
+             (if (assoc method retrieve-groups)
+                 (setcdr (assoc method retrieve-groups)
+                         (cons group (cdr (assoc method retrieve-groups))))
+               (push (list method group) retrieve-groups))
+           ;; hack: `nnmail-get-new-mail' changes the mail-source depending
+           ;; on the group, so we must perform a scan for every group
+           ;; if the users has any directory mail sources.
+           ;; hack: if `nnmail-scan-directory-mail-source-once' is non-nil,
+           ;; for it scan all spool files even when the groups are
+           ;; not required.
+           (if (and
+                (or nnmail-scan-directory-mail-source-once
+                    (null (assq 'directory
+                                (or mail-sources
+                                    (if (listp nnmail-spool-file)
+                                        nnmail-spool-file
+                                      (list nnmail-spool-file))))))
+                (member method scanned-methods))
+               (setq active (gnus-activate-group group))
+             (setq active (gnus-activate-group group 'scan))
+             (push method scanned-methods))
+           (when active
+             (gnus-close-group group))))))
 
       ;; Get the number of unread articles in the group.
-      (if active
-         (inline (gnus-get-unread-articles-in-group info active t))
+      (cond
+       ((eq active 'ignore)
+       ;; Don't do anything.
+       )
+       (active
+       (inline (gnus-get-unread-articles-in-group info active t)))
+       (t
        ;; The group couldn't be reached, so we nix out the number of
        ;; unread articles and stuff.
        (gnus-set-active group nil)
-       (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
+       (let ((tmp (gnus-gethash group gnus-newsrc-hashtb)))
+         (when tmp
+           (setcar tmp t))))))
+
+    ;; iterate through groups on methods which support gnus-retrieve-groups
+    ;; and fetch a partial active file and use it to find new news.
+    (dolist (rg retrieve-groups)
+      (let ((method (or (car rg) gnus-select-method))
+           (groups (cdr rg)))
+       (when (gnus-check-server method)
+         ;; Request that the backend scan its incoming messages.
+         (when (gnus-check-backend-function 'request-scan (car method))
+           (gnus-request-scan nil method))
+         (gnus-read-active-file-2
+          (mapcar (lambda (group) (gnus-group-real-name group)) groups)
+          method)
+         (dolist (group groups)
+           (cond
+            ((setq active (gnus-active (gnus-info-group
+                                        (setq info (gnus-get-info group)))))
+             (inline (gnus-get-unread-articles-in-group info active t)))
+            (t
+             ;; The group couldn't be reached, so we nix out the number of
+             ;; unread articles and stuff.
+             (gnus-set-active group nil)
+             (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))))))
 
-    (gnus-message 5 "Checking new news...done")))
+    (gnus-message 6 "Checking new news...done")))
 
 ;; Create a hash table out of the newsrc alist.  The `car's of the
 ;; alist elements are used as keys.
@@ -1561,8 +1830,82 @@ newsgroup."
             (setq article (pop articles)) ranges)
        (push article news)))
     (when news
+      ;; Enter this list into the group info.
       (gnus-info-set-read
        info (gnus-remove-from-range (gnus-info-read info) (nreverse news)))
+
+      ;; Set the number of unread articles in gnus-newsrc-hashtb.
+      (gnus-get-unread-articles-in-group info (gnus-active group))
+
+      ;; Insert the change into the group buffer and the dribble file.
+      (gnus-group-update-group group t))))
+
+(defun gnus-make-ascending-articles-unread (group articles)
+  "Mark ascending ARTICLES in GROUP as unread."
+  (let* ((entry (or (gnus-gethash group gnus-newsrc-hashtb)
+                    (gnus-gethash (gnus-group-real-name group)
+                                  gnus-newsrc-hashtb)))
+         (info (nth 2 entry))
+        (ranges (gnus-info-read info))
+         (r ranges)
+        modified)
+
+    (while articles
+      (let ((article (pop articles))) ; get the next article to remove from ranges
+        (while (let ((range (car ranges))) ; note the current range
+                 (if (atom range)       ; single value range
+                     (cond ((not range)
+                            ;; the articles extend past the end of the ranges
+                            ;; OK - I'm done
+                            (setq articles nil))
+                           ((< range article)
+                            ;; this range preceeds the article. Leave the range unmodified.
+                            (pop ranges)
+                            ranges)
+                           ((= range article)
+                            ;; this range exactly matches the article; REMOVE THE RANGE.
+                            ;; NOTE: When the range being removed is the last range, the list is corrupted by inserting null at its end.
+                            (setcar ranges (cadr ranges))
+                            (setcdr ranges (cddr ranges))
+                            (setq modified (if (car ranges) t 'remove-null))
+                            nil))
+                   (let ((min (car range))
+                         (max (cdr range)))
+                     ;; I have a min/max range to consider
+                     (cond ((> min max) ; invalid range introduced by splitter
+                            (setcar ranges (cadr ranges))
+                            (setcdr ranges (cddr ranges))
+                            (setq modified (if (car ranges) t 'remove-null))
+                            ranges)
+                           ((= min max)
+                            ;; replace min/max range with a single-value range
+                            (setcar ranges min)
+                            ranges)
+                           ((< max article)
+                            ;; this range preceeds the article. Leave the range unmodified.
+                            (pop ranges)
+                            ranges)
+                           ((< article min)
+                            ;; this article preceeds the range.  Return null to move to the
+                            ;; next article
+                            nil)
+                           (t
+                            ;; this article splits the range into two parts
+                            (setcdr ranges (cons (cons (1+ article) max) (cdr ranges)))
+                            (setcdr range (1- article))
+                            (setq modified t)
+                            ranges))))))))
+                  
+    (when modified
+      (when (eq modified 'remove-null)
+        (setq r (delq nil r)))
+      ;; Enter this list into the group info.
+      (gnus-info-set-read info r)
+
+      ;; Set the number of unread articles in gnus-newsrc-hashtb.
+      (gnus-get-unread-articles-in-group info (gnus-active group))
+
+      ;; Insert the change into the group buffer and the dribble file.
       (gnus-group-update-group group t))))
 
 ;; Enter all dead groups into the hashtb.
@@ -1607,86 +1950,94 @@ newsgroup."
 (defun gnus-read-active-file (&optional force not-native)
   (gnus-group-set-mode-line)
   (let ((methods
-        (append
-         (if (and (not not-native)
-                  (gnus-check-server gnus-select-method))
-             ;; The native server is available.
-             (cons gnus-select-method gnus-secondary-select-methods)
-           ;; The native server is down, so we just do the
-           ;; secondary ones.
-           gnus-secondary-select-methods)
-         ;; Also read from the archive server.
-         (when (gnus-archive-server-wanted-p)
-           (list "archive"))))
-       list-type)
+        (mapcar
+         (lambda (m) (if (stringp m) (gnus-server-get-method nil m) m))
+         (append
+          (if (and (not not-native)
+                   (gnus-check-server gnus-select-method))
+              ;; The native server is available.
+              (cons gnus-select-method gnus-secondary-select-methods)
+            ;; The native server is down, so we just do the
+            ;; secondary ones.
+            gnus-secondary-select-methods)
+          ;; Also read from the archive server.
+          (when (gnus-archive-server-wanted-p)
+            (list "archive")))))
+       method)
     (setq gnus-have-read-active-file nil)
     (save-excursion
       (set-buffer nntp-server-buffer)
-      (while methods
-       (let* ((method (if (stringp (car methods))
-                          (gnus-server-get-method nil (car methods))
-                        (car methods)))
-              (where (nth 1 method))
-              (mesg (format "Reading active file%s via %s..."
-                            (if (and where (not (zerop (length where))))
-                                (concat " from " where) "")
-                            (car method))))
+      (while (setq method (pop methods))
+       ;; Only do each method once, in case the methods appear more
+       ;; than once in this list.
+       (unless (member method methods)
+         (if (or debug-on-error debug-on-quit)
+             (gnus-read-active-file-1 method force)
+           (condition-case ()
+               (gnus-read-active-file-1 method force)
+             ;; We catch C-g so that we can continue past servers
+             ;; that do not respond.
+             (quit
+              (message "Quit reading the active file")
+              nil))))))))
+
+(defun gnus-read-active-file-1 (method force)
+  (let (where mesg)
+    (setq where (nth 1 method)
+         mesg (format "Reading active file%s via %s..."
+                      (if (and where (not (zerop (length where))))
+                          (concat " from " where) "")
+                      (car method)))
+    (gnus-message 5 mesg)
+    (when (gnus-check-server method)
+      ;; Request that the backend scan its incoming messages.
+      (when (gnus-check-backend-function 'request-scan (car method))
+       (gnus-request-scan nil method))
+      (cond
+       ((and (eq gnus-read-active-file 'some)
+            (gnus-check-backend-function 'retrieve-groups (car method))
+            (not force))
+       (let ((newsrc (cdr gnus-newsrc-alist))
+             (gmethod (gnus-server-get-method nil method))
+             groups info)
+         (while (setq info (pop newsrc))
+           (when (inline
+                   (gnus-server-equal
+                    (inline
+                      (gnus-find-method-for-group
+                       (gnus-info-group info) info))
+                    gmethod))
+             (push (gnus-group-real-name (gnus-info-group info))
+                   groups)))
+         (gnus-read-active-file-2 groups method)))
+       ((null method)
+       t)
+       (t
+       (if (not (gnus-request-list method))
+           (unless (equal method gnus-message-archive-method)
+             (gnus-error 1 "Cannot read active file from %s server"
+                         (car method)))
          (gnus-message 5 mesg)
-         (when (gnus-check-server method)
-           ;; Request that the backend scan its incoming messages.
-           (when (gnus-check-backend-function 'request-scan (car method))
-             (gnus-request-scan nil method))
-           (cond
-            ((and (eq gnus-read-active-file 'some)
-                  (gnus-check-backend-function 'retrieve-groups (car method))
-                  (not force))
-             (let ((newsrc (cdr gnus-newsrc-alist))
-                   (gmethod (gnus-server-get-method nil method))
-                   groups info)
-               (while (setq info (pop newsrc))
-                 (when (inline
-                         (gnus-server-equal
-                          (inline
-                            (gnus-find-method-for-group
-                             (gnus-info-group info) info))
-                          gmethod))
-                   (push (gnus-group-real-name (gnus-info-group info))
-                         groups)))
-               (when groups
-                 (gnus-check-server method)
-                 (setq list-type (gnus-retrieve-groups groups method))
-                 (cond
-                  ((not list-type)
-                   (gnus-error
-                    1.2 "Cannot read partial active file from %s server."
-                    (car method)))
-                  ((eq list-type 'active)
-                   (gnus-active-to-gnus-format
-                    method gnus-active-hashtb nil t))
-                  (t
-                   (gnus-groups-to-gnus-format
-                    method gnus-active-hashtb t))))))
-            ((null method)
-             t)
-            (t
-             (if (not (gnus-request-list method))
-                 (unless (equal method gnus-message-archive-method)
-                   (gnus-error 1 "Cannot read active file from %s server"
-                               (car method)))
-               (gnus-message 5 mesg)
-               (gnus-active-to-gnus-format method gnus-active-hashtb nil t)
-               ;; We mark this active file as read.
-               (push method gnus-have-read-active-file)
-               (gnus-message 5 "%sdone" mesg))))))
-       (setq methods (cdr methods))))))
-
-
-(defun gnus-ignored-newsgroups-has-to-p ()
-  "T only when gnus-ignored-newsgroups includes \"^to\\\\.\" as an element."
-  ;; note this regexp is the same as:
-  ;; (concat (regexp-quote "^to\\.") "\\($\\|" (regexp-quote "\\|") "\\)")
-  (string-match "\\^to\\\\\\.\\($\\|\\\\|\\)"
-               gnus-ignored-newsgroups))
+         (gnus-active-to-gnus-format method gnus-active-hashtb nil t)
+         ;; We mark this active file as read.
+         (push method gnus-have-read-active-file)
+         (gnus-message 5 "%sdone" mesg)))))))
+
+(defun gnus-read-active-file-2 (groups method)
+  "Read an active file for GROUPS in METHOD using `gnus-retrieve-groups'."
+  (when groups
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (gnus-check-server method)
+      (let ((list-type (gnus-retrieve-groups groups method)))
+       (cond ((not list-type)
+              (gnus-error
+               1.2 "Cannot read partial active file from %s server."
+               (car method)))
+             ((eq list-type 'active)
+              (gnus-active-to-gnus-format method gnus-active-hashtb nil t))
+             (t
+              (gnus-groups-to-gnus-format method gnus-active-hashtb t)))))))
 
 ;; Read an active file and place the results in `gnus-active-hashtb'.
 (defun gnus-active-to-gnus-format (&optional method hashtb ignore-errors
@@ -1705,22 +2056,22 @@ newsgroup."
                              (gnus-make-hashtable 4096)))))))
     ;; Delete unnecessary lines.
     (goto-char (point-min))
-    (cond ((gnus-ignored-newsgroups-has-to-p)
-          (delete-matching-lines gnus-ignored-newsgroups))
-         ((string= gnus-ignored-newsgroups "")
-          (delete-matching-lines "^to\\."))
-         (t
-          (delete-matching-lines (concat "^to\\.\\|"
-                                         gnus-ignored-newsgroups))))
-
-    ;; Make the group names readable as a lisp expression even if they
-    ;; contain special characters.
-    (goto-char (point-max))
-    (while (re-search-backward "[][';?()#]" nil t)
-      (insert ?\\))
+    (cond
+     ((string= gnus-ignored-newsgroups "")
+      (delete-matching-lines "^to\\."))
+     (t
+      (delete-matching-lines (concat "^to\\.\\|" gnus-ignored-newsgroups))))
+
+    (goto-char (point-min))
+    (unless (re-search-forward "[\\\"]" nil t)
+      ;; Make the group names readable as a lisp expression even if they
+      ;; contain special characters.
+      (goto-char (point-max))
+      (while (re-search-backward "[][';?()#]" nil t)
+       (insert ?\\)))
 
     ;; Let the Gnus agent save the active file.
-    (when (and gnus-agent real-active)
+    (when (and gnus-agent real-active (gnus-online method))
       (gnus-agent-save-active method))
 
     ;; If these are groups from a foreign select method, we insert the
@@ -1731,8 +2082,11 @@ newsgroup."
       (let ((prefix (gnus-group-prefixed-name "" method)))
        (goto-char (point-min))
        (while (and (not (eobp))
-                   (progn (insert prefix)
-                          (zerop (forward-line 1)))))))
+                   (progn
+                     (when (= (following-char) ?\")
+                       (forward-char 1))
+                     (insert prefix)
+                     (zerop (forward-line 1)))))))
     ;; Store the active file in a hash table.
     (goto-char (point-min))
     (let (group max min)
@@ -1743,18 +2097,22 @@ newsgroup."
              ;; group gets set to a symbol interned in the hash table
              ;; (what a hack!!) - jwz
              (setq group (let ((obarray hashtb)) (read cur)))
+             ;; ### The extended group name scheme makes
+             ;; the previous optimization strategy sort of pointless...
+             (when (stringp group)
+               (setq group (intern group hashtb)))
              (if (and (numberp (setq max (read cur)))
                       (numberp (setq min (read cur)))
                       (progn
                         (skip-chars-forward " \t")
                         (not
-                         (or (= (following-char) ?=)
-                             (= (following-char) ?x)
-                             (= (following-char) ?j)))))
+                         (or (eq (char-after) ?=)
+                             (eq (char-after) ?x)
+                             (eq (char-after) ?j)))))
                  (progn
                    (set group (cons min max))
                    ;; if group is moderated, stick in moderation table
-                   (when (= (following-char) ?m)
+                   (when (eq (char-after) ?m)
                      (unless gnus-moderated-hashtb
                        (setq gnus-moderated-hashtb (gnus-make-hashtable)))
                      (gnus-sethash (symbol-name group) t
@@ -1765,7 +2123,7 @@ newsgroup."
                (symbolp group)
                (set group nil))
           (unless ignore-errors
-            (gnus-message 3 "Warning - illegal active: %s"
+            (gnus-message 3 "Warning - invalid active: %s"
                           (buffer-substring
                            (gnus-point-at-bol) (gnus-point-at-eol))))))
        (widen)
@@ -1787,48 +2145,50 @@ newsgroup."
                     (gnus-group-prefixed-name "" method))))
 
     ;; Let the Gnus agent save the active file.
-    (when (and gnus-agent real-active)
-      (gnus-agent-save-groups method))
-    
-    (goto-char (point-min))
-    ;; We split this into to separate loops, one with the prefix
-    ;; and one without to speed the reading up somewhat.
-    (if prefix
-       (let (min max opoint group)
+    (if (and gnus-agent
+            real-active
+            (gnus-online method)
+            (gnus-agent-method-p method))
+       (progn
+         (gnus-agent-save-groups method)
+         (gnus-active-to-gnus-format method hashtb nil real-active))
+
+      (goto-char (point-min))
+      ;; We split this into to separate loops, one with the prefix
+      ;; and one without to speed the reading up somewhat.
+      (if prefix
+         (let (min max opoint group)
+           (while (not (eobp))
+             (condition-case ()
+                 (progn
+                   (read cur) (read cur)
+                   (setq min (read cur)
+                         max (read cur)
+                         opoint (point))
+                   (skip-chars-forward " \t")
+                   (insert prefix)
+                   (goto-char opoint)
+                   (set (let ((obarray hashtb)) (read cur))
+                        (cons min max)))
+               (error (and group (symbolp group) (set group nil))))
+             (forward-line 1)))
+       (let (min max group)
          (while (not (eobp))
            (condition-case ()
-               (progn
+               (when (eq (char-after) ?2)
                  (read cur) (read cur)
                  (setq min (read cur)
-                       max (read cur)
-                       opoint (point))
-                 (skip-chars-forward " \t")
-                 (insert prefix)
-                 (goto-char opoint)
-                 (set (let ((obarray hashtb)) (read cur))
+                       max (read cur))
+                 (set (setq group (let ((obarray hashtb)) (read cur)))
                       (cons min max)))
              (error (and group (symbolp group) (set group nil))))
-           (forward-line 1)))
-      (let (min max group)
-       (while (not (eobp))
-         (condition-case ()
-             (when (= (following-char) ?2)
-               (read cur) (read cur)
-               (setq min (read cur)
-                     max (read cur))
-               (set (setq group (let ((obarray hashtb)) (read cur)))
-                    (cons min max)))
-           (error (and group (symbolp group) (set group nil))))
-         (forward-line 1))))))
+           (forward-line 1)))))))
 
 (defun gnus-read-newsrc-file (&optional force)
   "Read startup file.
 If FORCE is non-nil, the .newsrc file is read."
   ;; Reset variables that might be defined in the .newsrc.eld file.
-  (let ((variables gnus-variable-list))
-    (while variables
-      (set (car variables) nil)
-      (setq variables (cdr variables))))
+  (gnus-clear-quick-file-variables)
   (let* ((newsrc-file gnus-current-startup-file)
         (quick-file (concat newsrc-file ".el")))
     (save-excursion
@@ -1837,7 +2197,8 @@ If FORCE is non-nil, the .newsrc file is read."
       ;; file (ticked articles, killed groups, foreign methods, etc.)
       (gnus-read-newsrc-el-file quick-file)
 
-      (when (and (file-exists-p gnus-current-startup-file)
+      (when (and gnus-read-newsrc-file
+                (file-exists-p gnus-current-startup-file)
                 (or force
                     (and (file-newer-than-file-p newsrc-file quick-file)
                          (file-newer-than-file-p newsrc-file
@@ -1853,61 +2214,131 @@ If FORCE is non-nil, the .newsrc file is read."
        (save-excursion
          (gnus-message 5 "Reading %s..." newsrc-file)
          (set-buffer (nnheader-find-file-noselect newsrc-file))
-         (buffer-disable-undo (current-buffer))
+         (buffer-disable-undo)
          (gnus-newsrc-to-gnus-format)
          (kill-buffer (current-buffer))
-         (gnus-message 5 "Reading %s...done" newsrc-file)))
-
-      ;; Convert old to new.
-      (gnus-convert-old-newsrc))))
-
-(defun gnus-convert-old-newsrc ()
-  "Convert old newsrc into the new format, if needed."
-  (let ((fcv (and gnus-newsrc-file-version
-                 (gnus-continuum-version gnus-newsrc-file-version))))
-    (cond
-     ;; No .newsrc.eld file was loaded.
-     ((null fcv) nil)
-     ;; Gnus 5 .newsrc.eld was loaded.
-     ((< fcv (gnus-continuum-version "September Gnus v0.1"))
-      (gnus-convert-old-ticks)))))
-
-(defun gnus-convert-old-ticks ()
-  (let ((newsrc (cdr gnus-newsrc-alist))
-       marks info dormant ticked)
-    (while (setq info (pop newsrc))
-      (when (setq marks (gnus-info-marks info))
-       (setq dormant (cdr (assq 'dormant marks))
-             ticked (cdr (assq 'tick marks)))
-       (when (or dormant ticked)
-         (gnus-info-set-read
-          info
-          (gnus-add-to-range
-           (gnus-info-read info)
-           (nconc (gnus-uncompress-range dormant)
-                  (gnus-uncompress-range ticked)))))))))
+         (gnus-message 5 "Reading %s...done" newsrc-file))))))
+
+(defun gnus-load (file &optional coding-system)
+  "Load FILE, but in such a way that read errors can be reported."
+  (with-temp-buffer
+    (if coding-system
+       (insert-file-contents-as-coding-system coding-system file)
+      (insert-file-contents file))
+    (while (not (eobp))
+      (condition-case type
+         (let ((form (read (current-buffer))))
+           (eval form))
+       (error
+        (unless (eq (car type) 'end-of-file)
+          (let ((error (format "Error in %s line %d" file
+                               (count-lines (point-min) (point)))))
+            (ding)
+            (unless (gnus-yes-or-no-p (concat error "; continue? "))
+              (error "%s" error)))))))))
 
 (defun gnus-read-newsrc-el-file (file)
   (let ((ding-file (concat file "d")))
-    ;; We always, always read the .eld file.
-    (gnus-message 5 "Reading %s..." ding-file)
-    (let (gnus-newsrc-assoc)
-      (condition-case nil
-         (load ding-file t t t)
-       (error
-        (ding)
-        (unless (gnus-yes-or-no-p
-                 (format "Error in %s; continue? " ding-file))
-          (error "Error in %s" ding-file))))
-      (when gnus-newsrc-assoc
-       (setq gnus-newsrc-alist gnus-newsrc-assoc)))
+    (when (file-exists-p ding-file)
+      ;; We always, always read the .eld file.
+      (gnus-message 5 "Reading %s..." ding-file)
+      (let (gnus-newsrc-assoc)
+       (gnus-load ding-file gnus-ding-file-coding-system)
+;;     ;; Older versions of `gnus-format-specs' are no longer valid
+;;     ;; in Oort Gnus 0.01.
+;;     (let ((version
+;;            (and gnus-newsrc-file-version
+;;                 (gnus-continuum-version gnus-newsrc-file-version))))
+;;       (when (or (not version)
+;;                 (< version 5.090009))
+;;         (setq gnus-format-specs gnus-default-format-specs)))
+       (when gnus-newsrc-assoc
+         (setq gnus-newsrc-alist gnus-newsrc-assoc))))
     (gnus-make-hashtable-from-newsrc-alist)
     (when (file-newer-than-file-p file ding-file)
       ;; Old format quick file
       (gnus-message 5 "Reading %s..." file)
       ;; The .el file is newer than the .eld file, so we read that one
       ;; as well.
-      (gnus-read-old-newsrc-el-file file))))
+      (gnus-read-old-newsrc-el-file file)))
+  (when (and gnus-product-directory
+            (file-directory-p gnus-product-directory))
+    (let ((list gnus-product-variable-file-list))
+      (while list
+       (apply 'gnus-product-read-variable-file-1 (car list))
+       (setq list (cdr list)))))
+  (gnus-run-hooks 'gnus-read-newsrc-el-hook))
+
+;;(defun gnus-re-read-newsrc-el-file (file)
+;;  "Attempt to re-read .newsrc.eld file.  Returns nil if successful.
+;;The backup file \".newsrc.eld_\" will be created before re-reading."
+;;  (message "Error in %s; retrying..." file)
+;;  (if (and
+;;       (condition-case nil
+;;        (let ((backup (concat file "_")))
+;;          (copy-file file backup 'ok-if-already-exists 'keep-time)
+;;          (message " (The backup file %s has been created)" backup)
+;;          t)
+;;      (error nil))
+;;       (progn
+;;      (insert-file-contents-as-binary file nil nil nil 'replace)
+;;      (goto-char (point-min))
+;;      (when (re-search-forward
+;;             "^[\t ]*([\t\n\r ]*setq[\t\n\r ]+gnus-format-specs" nil t)
+;;        (delete-region (goto-char (match-beginning 0)) (forward-list 1))
+;;        (decode-coding-region (point-min) (point-max)
+;;                              gnus-ding-file-coding-system)
+;;        (condition-case nil
+;;            (progn
+;;              (eval-region (point-min) (point-max))
+;;              t)
+;;          (error nil)))))
+;;      (prog1
+;;       nil
+;;     (message "Error in %s; retrying...done" file))
+;;    (message "Error in %s; retrying...failed" file)
+;;    t))
+
+(defun gnus-product-read-variable-file-1 (file checking-methods coding
+                                              &rest variables)
+  (let (error gnus-product-file-version method file-ver)
+    (when (or (condition-case err
+                 (let ((coding-system-for-read coding)
+                       (input-coding-system coding))
+                   (load (expand-file-name file gnus-product-directory)
+                         nil nil t)
+                   nil)
+               (error
+                (message "Error while reading %s: %s"
+                         (expand-file-name file gnus-product-directory)
+                         (error-message-string err))
+                (setq error t)))
+             (and (setq method (assq 'product-version checking-methods))
+                  (not (and (setq file-ver
+                                  (cdr (assq 'product-version
+                                             gnus-product-file-version)))
+                            (zerop (product-version-compare file-ver
+                                                            (cadr method))))))
+             (and (assq 'emacs-version checking-methods)
+                  (not (and (assq 'emacs-version gnus-product-file-version)
+                            (string-equal
+                             emacs-version
+                             (cdr (assq 'emacs-version
+                                        gnus-product-file-version))))))
+             (and (assq 'correct-string-widths checking-methods)
+                  (not (and (assq 'correct-string-widths
+                                  gnus-product-file-version)
+                            (eq (and gnus-use-correct-string-widths t)
+                                (and (cdr (assq 'correct-string-widths
+                                                gnus-product-file-version))
+                                     t))))))
+      (unless error
+       (message "\"%s\" seems to have mismatched contents, updating..."
+                file))
+      (while variables
+       (set (car variables) nil)
+       (gnus-product-variable-touch (car variables))
+       (setq variables (cdr variables))))))
 
 ;; Parse the old-style quick startup file
 (defun gnus-read-old-newsrc-el-file (file)
@@ -1971,7 +2402,8 @@ If FORCE is non-nil, the .newsrc file is read."
     (if (or (file-exists-p real-file)
            (file-exists-p (concat real-file ".el"))
            (file-exists-p (concat real-file ".eld")))
-       real-file file)))
+       real-file
+      file)))
 
 (defun gnus-newsrc-to-gnus-format ()
   (setq gnus-newsrc-options "")
@@ -2027,7 +2459,7 @@ If FORCE is non-nil, the .newsrc file is read."
        (unless (boundp symbol)
          (set symbol nil))
        ;; It was a group name.
-       (setq subscribed (= (following-char) ?:)
+       (setq subscribed (eq (char-after) ?:)
              group (symbol-name symbol)
              reads nil)
        (if (eolp)
@@ -2051,7 +2483,7 @@ If FORCE is non-nil, the .newsrc file is read."
                           (read buf)))
              (widen)
              ;; If the next character is a dash, then this is a range.
-             (if (= (following-char) ?-)
+             (if (eq (char-after) ?-)
                  (progn
                    ;; We read the upper bound of the range.
                    (forward-char 1)
@@ -2073,8 +2505,8 @@ If FORCE is non-nil, the .newsrc file is read."
                (push num1 reads))
              ;; If the next char in ?\n, then we have reached the end
              ;; of the line and return nil.
-             (/= (following-char) ?\n))
-            ((= (following-char) ?\n)
+             (not (eq (char-after) ?\n)))
+            ((eq (char-after) ?\n)
              ;; End of line, so we end.
              nil)
             (t
@@ -2088,7 +2520,7 @@ If FORCE is non-nil, the .newsrc file is read."
                            (buffer-substring (gnus-point-at-bol)
                                              (gnus-point-at-eol))))
              nil))
-         ;; Skip past ", ".  Spaces are illegal in these ranges, but
+         ;; Skip past ", ".  Spaces are invalid in these ranges, but
          ;; we allow them, because it's a common mistake to put a
          ;; space after the comma.
          (skip-chars-forward ", "))
@@ -2200,7 +2632,7 @@ If FORCE is non-nil, the .newsrc file is read."
                  (gnus-point-at-eol)))
        ;; Search for all "words"...
        (while (re-search-forward "[^ \t,\n]+" eol t)
-         (if (= (char-after (match-beginning 0)) ?!)
+         (if (eq (char-after (match-beginning 0)) ?!)
              ;; If the word begins with a bang (!), this is a "not"
              ;; spec.  We put this spec (minus the bang) and the
              ;; symbol `ignore' into the list.
@@ -2218,6 +2650,12 @@ If FORCE is non-nil, the .newsrc file is read."
 
       (setq gnus-newsrc-options-n out))))
 
+(eval-and-compile
+  (defalias 'gnus-long-file-names
+    (if (fboundp 'msdos-long-file-names)
+      'msdos-long-file-names
+      (lambda () t))))
+
 (defun gnus-save-newsrc-file (&optional force)
   "Save .newsrc file."
   ;; Note: We cannot save .newsrc file if all newsgroups are removed
@@ -2242,46 +2680,115 @@ If FORCE is non-nil, the .newsrc file is read."
            (gnus-gnus-to-newsrc-format)
            (gnus-message 8 "Saving %s...done" gnus-current-startup-file))
          ;; Save .newsrc.eld.
-         (set-buffer (get-buffer-create " *Gnus-newsrc*"))
+         (set-buffer (gnus-get-buffer-create " *Gnus-newsrc*"))
          (make-local-variable 'version-control)
-         (setq version-control 'never)
+         (setq version-control gnus-backup-startup-file)
          (setq buffer-file-name
                (concat gnus-current-startup-file ".eld"))
          (setq default-directory (file-name-directory buffer-file-name))
-         (gnus-add-current-to-buffer-list)
-         (buffer-disable-undo (current-buffer))
+         (buffer-disable-undo)
          (erase-buffer)
-         (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
-         (gnus-gnus-to-quick-newsrc-format)
-         (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
-         (save-buffer)
-         (kill-buffer (current-buffer))
+          (gnus-message 5 "Saving %s.eld..." gnus-current-startup-file)
+
+          (if gnus-save-startup-file-via-temp-buffer
+              (let ((coding-system-for-write gnus-ding-file-coding-system)
+                   (output-coding-system gnus-ding-file-coding-system)
+                    (standard-output (current-buffer)))
+                (gnus-gnus-to-quick-newsrc-format)
+                (gnus-run-hooks 'gnus-save-quick-newsrc-hook)
+                (save-buffer))
+            (let ((coding-system-for-write gnus-ding-file-coding-system)
+                 (output-coding-system gnus-ding-file-coding-system)
+                  (version-control gnus-backup-startup-file)
+                  (startup-file (concat gnus-current-startup-file ".eld"))
+                  (working-dir (file-name-directory gnus-current-startup-file))
+                  working-file
+                  (i -1))
+              ;; Generate the name of a non-existent file.
+              (while (progn (setq working-file
+                                  (format
+                                   (if (and (eq system-type 'ms-dos)
+                                            (not (gnus-long-file-names)))
+                                       "%s#%d.tm#" ; MSDOS limits files to 8+3
+                                     (if (memq system-type '(vax-vms axp-vms))
+                                         "%s$tmp$%d"
+                                       "%s#tmp#%d"))
+                                   working-dir (setq i (1+ i))))
+                            (file-exists-p working-file)))
+
+              (unwind-protect
+                  (progn
+                    (gnus-with-output-to-file working-file
+                     (gnus-gnus-to-quick-newsrc-format)
+                     (gnus-run-hooks 'gnus-save-quick-newsrc-hook))
+
+                    ;; These bindings will mislead the current buffer
+                    ;; into thinking that it is visiting the startup
+                    ;; file.
+                    (let ((buffer-backed-up nil)
+                          (buffer-file-name startup-file)
+                          (file-precious-flag t)
+                          (setmodes (file-modes startup-file)))
+                      ;; Backup the current version of the startup file.
+                      (backup-buffer)
+
+                      ;; Replace the existing startup file with the temp file.
+                      (rename-file working-file startup-file t)
+                      (set-file-modes startup-file setmodes)))
+                (condition-case nil
+                    (delete-file working-file)
+                  (file-error nil)))))
+
+         (gnus-kill-buffer (current-buffer))
          (gnus-message
           5 "Saving %s.eld...done" gnus-current-startup-file))
        (gnus-dribble-delete-file)
-       (gnus-group-set-mode-line)))))
-
-(defun gnus-gnus-to-quick-newsrc-format ()
-  "Insert Gnus variables such as gnus-newsrc-alist in lisp format."
-  (let ((print-quoted t)
-       (print-escape-newlines t))
-    (insert ";; -*- emacs-lisp -*-\n")
-    (insert ";; Gnus startup file.\n")
-    (insert "\
+       (gnus-group-set-mode-line))))
+  (when gnus-product-directory
+    (gnus-product-save-variable-file)))
+
+;; Call the function above at C-x C-c.
+(defadvice save-buffers-kill-emacs (before save-gnus-newsrc-file-maybe
+                                          activate preactivate)
+  "Save .newsrc and .newsrc.eld when Emacs is killed."
+  (when (gnus-alive-p)
+    (gnus-run-hooks 'gnus-exit-gnus-hook)
+    (gnus-offer-save-summaries)
+    (gnus-save-newsrc-file)))
+
+(defun gnus-gnus-to-quick-newsrc-format (&optional minimal name &rest specific-variables)
+  "Print Gnus variables such as `gnus-newsrc-alist' in Lisp format."
+    (princ ";; -*- emacs-lisp -*-\n")
+    (if name
+       (princ (format ";; %s\n" name))
+      (princ ";; Gnus startup file.\n"))
+
+    (unless minimal
+      (princ "\
 ;; Never delete this file -- if you want to force Gnus to read the
 ;; .newsrc file (if you have one), touch .newsrc instead.\n")
-    (insert "(setq gnus-newsrc-file-version "
-           (prin1-to-string gnus-version) ")\n")
-    (let* ((gnus-killed-list
+      (princ "(setq gnus-newsrc-file-version ")
+      (princ (gnus-prin1-to-string gnus-version))
+      (princ ")\n"))
+
+    (let* ((print-quoted t)
+           (print-readably t)
+           (print-escape-multibyte nil)
+           (print-escape-nonascii t)
+           (print-length nil)
+           (print-level nil)
+           (print-escape-newlines t)
+          (gnus-killed-list
            (if (and gnus-save-killed-list
                     (stringp gnus-save-killed-list))
                (gnus-strip-killed-list)
              gnus-killed-list))
           (variables
-           (if gnus-save-killed-list gnus-variable-list
-             ;; Remove the `gnus-killed-list' from the list of variables
-             ;; to be saved, if required.
-             (delq 'gnus-killed-list (copy-sequence gnus-variable-list))))
+           (or specific-variables
+               (if gnus-save-killed-list gnus-variable-list
+                 ;; Remove the `gnus-killed-list' from the list of variables
+                 ;; to be saved, if required.
+                 (delq 'gnus-killed-list (copy-sequence gnus-variable-list)))))
           ;; Peel off the "dummy" group.
           (gnus-newsrc-alist (cdr gnus-newsrc-alist))
           variable)
@@ -2289,9 +2796,85 @@ If FORCE is non-nil, the .newsrc file is read."
       (while variables
        (when (and (boundp (setq variable (pop variables)))
                   (symbol-value variable))
-         (insert "(setq " (symbol-name variable) " '")
-         (gnus-prin1 (symbol-value variable))
-         (insert ")\n"))))))
+         (princ "(setq ")
+          (princ (symbol-name variable))
+          (princ " '")
+         (prin1 (symbol-value variable))
+         (princ ")\n")))))
+
+(defun gnus-product-variable-touch (&rest variables)
+  (while variables
+    (put (pop variables) 'gnus-product-variable 'dirty)))
+
+(defun gnus-product-variables-dirty-p (variables)
+  (catch 'done
+    (while variables
+      (when (eq (get (car variables) 'gnus-product-variable) 'dirty)
+       (throw 'done t))
+      (setq variables (cdr variables)))))
+
+(defun gnus-product-save-variable-file (&optional force)
+  "Save all product variables to files, when need to be saved."
+  (let ((list gnus-product-variable-file-list))
+    (gnus-make-directory gnus-product-directory)
+    (while list
+      (apply 'gnus-product-save-variable-file-1 force (car list))
+      (setq list (cdr list)))))
+
+(defun gnus-product-save-variable-file-1 (force file checking-methods coding
+                                               &rest variables)
+  "Save a product variable file, when need to be saved."
+  (when (or force
+           (gnus-product-variables-dirty-p variables))
+    (let ((product (product-find 'gnus-vers)))
+      (set-buffer (gnus-get-buffer-create " *gnus-product*"))
+      (make-local-variable 'version-control)
+      (setq version-control 'never)
+      (setq file (expand-file-name file gnus-product-directory)
+           buffer-file-name file
+           default-directory (file-name-directory file))
+      (buffer-disable-undo)
+      (erase-buffer)
+      (gnus-message 5 "Saving %s..." file)
+      (apply 'gnus-product-quick-file-format product checking-methods coding
+            variables)
+      (save-buffer-as-coding-system coding)
+      (kill-buffer (current-buffer))
+      (while variables
+       (put (car variables) 'gnus-product-variable nil)
+       (setq variables (cdr variables)))
+      (gnus-message
+       5 "Saving %s...done" file))))
+
+(defun gnus-product-quick-file-format (product checking-methods
+                                              coding &rest variables)
+  "Insert gnus product depend variables in lisp format."
+  (let ((print-quoted t)
+       (print-escape-newlines t)
+       print-length print-level variable param)
+    (insert (format ";; -*- Mode: emacs-lisp; coding: %s -*-\n" coding))
+    (insert (format ";; %s startup file.\n" (product-name product)))
+    (when (setq param (cdr (assq 'product-version checking-methods)))
+      (insert "(or (>= (product-version-compare "
+             "(product-version (product-find 'gnus-vers))\n"
+             "\t\t\t\t '" (apply 'prin1-to-string param) ")\n"
+             "\t0)\n"
+             "    (error \"This file was created by later version of "
+             "gnus.\"))\n"))
+    (insert "(setq gnus-product-file-version\n"
+           "      '((product-version . "
+           (prin1-to-string (product-version product)) ")\n"
+           "\t(emacs-version . "
+           (prin1-to-string emacs-version) ")\n"
+           "\t(correct-string-widths . "
+           (if gnus-use-correct-string-widths "t" "nil")
+           ")))\n")
+    (while variables
+      (when (and (boundp (setq variable (pop variables)))
+                (symbol-value variable))
+       (insert "(setq " (symbol-name variable) " '")
+       (gnus-prin1 (symbol-value variable))
+       (insert ")\n")))))
 
 (defun gnus-strip-killed-list ()
   "Return the killed list minus the groups that match `gnus-save-killed-list'."
@@ -2312,7 +2895,7 @@ If FORCE is non-nil, the .newsrc file is read."
          info ranges range method)
       (setq buffer-file-name gnus-current-startup-file)
       (setq default-directory (file-name-directory buffer-file-name))
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (erase-buffer)
       ;; Write options.
       (when gnus-newsrc-options
@@ -2364,14 +2947,22 @@ If FORCE is non-nil, the .newsrc file is read."
 ;;; Slave functions.
 ;;;
 
+(defvar gnus-slave-mode nil)
+
+(defun gnus-slave-mode ()
+  "Minor mode for slave Gnusae."
+  (gnus-add-minor-mode 'gnus-slave-mode " Slave" (make-sparse-keymap))
+  (gnus-run-hooks 'gnus-slave-mode-hook))
+
 (defun gnus-slave-save-newsrc ()
   (save-excursion
     (set-buffer gnus-dribble-buffer)
     (let ((slave-name
-          (make-temp-name (concat gnus-current-startup-file "-slave-")))
+          (mm-make-temp-file (concat gnus-current-startup-file "-slave-")))
          (modes (ignore-errors
                   (file-modes (concat gnus-current-startup-file ".eld")))))
-      (gnus-write-buffer slave-name)
+      (gnus-write-buffer-as-coding-system gnus-ding-file-coding-system
+                                         slave-name)
       (when modes
        (set-file-modes slave-name modes)))))
 
@@ -2390,8 +2981,7 @@ If FORCE is non-nil, the .newsrc file is read."
        ()                              ; There are no slave files to read.
       (gnus-message 7 "Reading slave newsrcs...")
       (save-excursion
-       (set-buffer (get-buffer-create " *gnus slave*"))
-       (buffer-disable-undo (current-buffer))
+       (set-buffer (gnus-get-buffer-create " *gnus slave*"))
        (setq slave-files
              (sort (mapcar (lambda (file)
                              (list (nth 5 (file-attributes file)) file))
@@ -2402,7 +2992,7 @@ If FORCE is non-nil, the .newsrc file is read."
        (while slave-files
          (erase-buffer)
          (setq file (nth 1 (car slave-files)))
-         (insert-file-contents file)
+         (nnheader-insert-file-contents file)
          (when (condition-case ()
                    (progn
                      (eval-buffer (current-buffer))
@@ -2449,6 +3039,8 @@ If FORCE is non-nil, the .newsrc file is read."
 
     (gnus-message 5 "Reading descriptions file via %s..." (car method))
     (cond
+     ((null (gnus-get-function method 'request-list-newsgroups t))
+      t)
      ((not (gnus-check-server method))
       (gnus-message 1 "Couldn't open server")
       nil)
@@ -2490,15 +3082,16 @@ If FORCE is non-nil, the .newsrc file is read."
            (skip-chars-forward " \t")
            ;; ...  which leads to this line being effectively ignored.
            (when (symbolp group)
-             (let ((str (buffer-substring
-                         (point) (progn (end-of-line) (point))))
-                   (coding
-                    (and (boundp 'enable-multibyte-characters)
-                         enable-multibyte-characters
-                         (fboundp 'gnus-mule-get-coding-system)
-                         (gnus-mule-get-coding-system (symbol-name group)))))
-               (if coding
-                   (setq str (gnus-decode-coding-string str (car coding))))
+             (let* ((str (buffer-substring
+                          (point) (progn (end-of-line) (point))))
+                    (name (symbol-name group))
+                    (charset
+                     (or (gnus-group-name-charset method name)
+                         (gnus-parameter-charset name)
+                         gnus-default-charset)))
+               ;; Fixme: Don't decode in unibyte mode.
+               (when (and str charset (featurep 'mule))
+                 (setq str (decode-coding-string str charset)))
                (set group str)))
            (forward-line 1))))
       (gnus-message 5 "Reading descriptions file...done")
@@ -2515,10 +3108,11 @@ If FORCE is non-nil, the .newsrc file is read."
 
 ;;;###autoload
 (defun gnus-declare-backend (name &rest abilities)
-  "Declare backend NAME with ABILITIES as a Gnus backend."
+  "Declare back end NAME with ABILITIES as a Gnus back end."
   (setq gnus-valid-select-methods
        (nconc gnus-valid-select-methods
-              (list (apply 'list name abilities)))))
+              (list (apply 'list name abilities))))
+  (gnus-redefine-select-method-widget))
 
 (defun gnus-set-default-directory ()
   "Set the default directory in the current buffer to `gnus-default-directory'.
@@ -2529,6 +3123,28 @@ If this variable is nil, don't do anything."
            (file-name-as-directory (expand-file-name gnus-default-directory))
          default-directory)))
 
+(eval-and-compile
+(defalias 'gnus-display-time-event-handler
+  (if (gnus-boundp 'display-time-timer)
+      'display-time-event-handler
+    (lambda () "Does nothing as `display-time-timer' is not bound.
+Would otherwise be an alias for `display-time-event-handler'." nil))))
+
+;;;###autoload
+(defun gnus-fixup-nnimap-unread-after-getting-new-news ()
+  (let (server group info)
+    (mapatoms
+     (lambda (sym)
+       (when (and (setq group (symbol-name sym))
+                 (gnus-group-entry group)
+                 (setq info (symbol-value sym)))
+        (gnus-sethash group (cons (nth 2 info) (cdr (gnus-group-entry group)))
+                      gnus-newsrc-hashtb)))
+     (if (boundp 'nnimap-mailbox-info)
+        (symbol-value 'nnimap-mailbox-info)
+       (make-vector 1 0)))))
+
+
 (provide 'gnus-start)
 
 ;;; gnus-start.el ends here
index 22c941d..a8938f3 100644 (file)
@@ -1,8 +1,11 @@
-;;; gnus-sum.el --- summary mode commands for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;;; gnus-sum.el --- summary mode commands for Semi-gnus
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;         Katsumi Yamaoka  <yamaoka@jpl.org>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
+(eval-when-compile
+  (require 'cl)
+  (require 'gnus-clfns)
+  (defvar tool-bar-map))
 
 (require 'gnus)
 (require 'gnus-group)
 (require 'gnus-range)
 (require 'gnus-int)
 (require 'gnus-undo)
+(require 'gnus-util)
+(require 'nnoo)
+
+(eval-when-compile
+  (require 'mime-play)
+  (require 'static))
+
+(eval-and-compile
+  (autoload 'pgg-decrypt-region "pgg" nil t)
+  (autoload 'pgg-verify-region "pgg" nil t))
+
 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
+(autoload 'gnus-cache-write-active "gnus-cache")
+(autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
+(autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
+(autoload 'mm-uu-dissect "mm-uu")
+(autoload 'gnus-article-outlook-deuglify-article "deuglify"
+  "Deuglify broken Outlook (Express) articles and redisplay."
+  t)
+(autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t)
+(autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t)
+(autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t)
 
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
@@ -97,6 +124,11 @@ given by the `gnus-summary-same-subject' variable.)"
                 (const adopt)
                 (const empty)))
 
+(defcustom gnus-summary-make-false-root-always nil
+  "Always make a false dummy root."
+  :group 'gnus-thread
+  :type 'boolean)
+
 (defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
   "*A regexp to match subjects to be excluded from loose thread gathering.
 As loose thread gathering is done on subjects only, that means that
@@ -124,13 +156,14 @@ comparing subjects."
   "List of functions taking a string argument that simplify subjects.
 The functions are applied recursively.
 
-Useful functions to put in this list include: `gnus-simplify-subject-re',
-`gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
+Useful functions to put in this list include:
+`gnus-simplify-subject-re', `gnus-simplify-subject-fuzzy',
+`gnus-simplify-whitespace', and `gnus-simplify-all-whitespace'."
   :group 'gnus-thread
   :type '(repeat function))
 
 (defcustom gnus-simplify-ignored-prefixes nil
-  "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
+  "*Remove matches for this regexp from subject lines when simplifying fuzzily."
   :group 'gnus-thread
   :type '(choice (const :tag "off" nil)
                 regexp))
@@ -166,10 +199,15 @@ This variable will only be used if the value of
   :type 'string)
 
 (defcustom gnus-summary-goto-unread t
-  "*If t, marking commands will go to the next unread article.
-If `never', commands that usually go to the next unread article, will
-go to the next article, whether it is read or not.
-If nil, only the marking commands will go to the next (un)read article."
+  "*If t, many commands will go to the next unread article.
+This applies to marking commands as well as other commands that
+\"naturally\" select the next article, like, for instance, `SPC' at
+the end of an article.
+
+If nil, the marking commands do NOT go to the next unread article
+\(they go to the next article instead).  If `never', commands that
+usually go to the next unread article, will go to the next article,
+whether it is read or not."
   :group 'gnus-summary-marks
   :link '(custom-manual "(gnus)Setting Marks")
   :type '(choice (const :tag "off" nil)
@@ -184,6 +222,20 @@ If this variable is nil, scoring will be disabled."
   :type '(choice (const :tag "disable")
                 integer))
 
+(defcustom gnus-summary-default-high-score 0
+  "*Default threshold for a high scored article.
+An article will be highlighted as high scored if its score is greater
+than this score."
+  :group 'gnus-score-default
+  :type 'integer)
+
+(defcustom gnus-summary-default-low-score 0
+  "*Default threshold for a low scored article.
+An article will be highlighted as low scored if its score is smaller
+than this score."
+  :group 'gnus-score-default
+  :type 'integer)
+
 (defcustom gnus-summary-zcore-fuzz 0
   "*Fuzziness factor for the zcore in the summary buffer.
 Articles with scores closer than this to `gnus-summary-default-score'
@@ -206,21 +258,27 @@ simplification is selected."
 
 (defcustom gnus-thread-hide-subtree nil
   "*If non-nil, hide all threads initially.
+This can be a predicate specifier which says which threads to hide.
 If threads are hidden, you have to run the command
 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
 to expose hidden threads."
   :group 'gnus-thread
-  :type 'boolean)
+  :type '(radio (sexp :format "Non-nil\n"
+                     :match (lambda (widget value)
+                              (not (or (consp value) (functionp value))))
+                     :value t)
+               (const nil)
+               (sexp :tag "Predicate specifier" :size 0)))
 
 (defcustom gnus-thread-hide-killed t
   "*If non-nil, hide killed threads automatically."
   :group 'gnus-thread
   :type 'boolean)
 
-(defcustom gnus-thread-ignore-subject nil
-  "*If non-nil, ignore subjects and do all threading based on the Reference header.
-If nil, which is the default, articles that have different subjects
-from their parents will start separate threads."
+(defcustom gnus-thread-ignore-subject t
+  "*If non-nil, which is the default, ignore subjects and do all threading based on the Reference header.
+If nil, articles that have different subjects from their parents will
+start separate threads."
   :group 'gnus-thread
   :type 'boolean)
 
@@ -249,29 +307,52 @@ equal will be included."
   :type 'boolean)
 
 (defcustom gnus-auto-select-first t
-  "*If nil, don't select the first unread article when entering a group.
-If this variable is `best', select the highest-scored unread article
-in the group.  If neither nil nor `best', select the first unread
-article.
+  "*If non-nil, select the article under point.
+Which article this is is controlled by the `gnus-auto-select-subject'
+variable.
 
-If you want to prevent automatic selection of the first unread article
-in some newsgroups, set the variable to nil in
-`gnus-select-group-hook'."
+If you want to prevent automatic selection of articles in some
+newsgroups, set the variable to nil in `gnus-select-group-hook'."
   :group 'gnus-group-select
   :type '(choice (const :tag "none" nil)
-                (const best)
                 (sexp :menu-tag "first" t)))
 
+(defcustom gnus-auto-select-subject 'unread
+  "*Says what subject to place under point when entering a group.
+
+This variable can either be the symbols `first' (place point on the
+first subject), `unread' (place point on the subject line of the first
+unread article), `best' (place point on the subject line of the
+higest-scored article), `unseen' (place point on the subject line of
+the first unseen article), 'unseen-or-unread' (place point on the subject
+line of the first unseen article or, if all article have been seen, on the
+subject line of the first unread article), or a function to be called to
+place point on some subject line."
+  :group 'gnus-group-select
+  :type '(choice (const best)
+                (const unread)
+                (const first)
+                (const unseen)
+                (const unseen-or-unread)))
+
+(defcustom gnus-dont-select-after-jump-to-other-group nil
+  "If non-nil, don't select the first unread article after entering the
+other group by the command `gnus-summary-jump-to-other-group'.  If nil,
+it is depend on the value of `gnus-auto-select-first' whether to select
+or not."
+  :group 'gnus-group-select
+  :type 'boolean)
+
 (defcustom gnus-auto-select-next t
   "*If non-nil, offer to go to the next group from the end of the previous.
 If the value is t and the next newsgroup is empty, Gnus will exit
-summary mode and go back to group mode.         If the value is neither nil
-nor t, Gnus will select the following unread newsgroup.         In
+summary mode and go back to group mode.  If the value is neither nil
+nor t, Gnus will select the following unread newsgroup.  In
 particular, if the value is the symbol `quietly', the next unread
 newsgroup will be selected without any confirmation, and if it is
 `almost-quietly', the next group will be selected without any
 confirmation if you are located on the last article in the group.
-Finally, if this variable is `slightly-quietly', the `Z n' command
+Finally, if this variable is `slightly-quietly', the `\\<gnus-summary-mode-map>\\[gnus-summary-catchup-and-goto-next-group]' command
 will go to the next group without confirmation."
   :group 'gnus-summary-maneuvering
   :type '(choice (const :tag "off" nil)
@@ -281,10 +362,29 @@ will go to the next group without confirmation."
                 (sexp :menu-tag "on" t)))
 
 (defcustom gnus-auto-select-same nil
-  "*If non-nil, select the next article with the same subject."
+  "*If non-nil, select the next article with the same subject.
+If there are no more articles with the same subject, go to
+the first unread article."
   :group 'gnus-summary-maneuvering
   :type 'boolean)
 
+(defcustom gnus-auto-goto-ignores 'unfetched
+  "*Says how to handle unfetched articles when maneuvering.
+
+This variable can either be the symbols nil (maneuver to any
+article), `undownloaded' (maneuvering while unplugged ignores articles
+that have not been fetched), `always-undownloaded' (maneuvering always
+ignores articles that have not been fetched), `unfetched' (maneuvering
+ignores articles whose headers have not been fetched).
+
+NOTE: The list of unfetched articles will always be nil when plugged
+and, when unplugged, a subset of the undownloaded article list."
+  :group 'gnus-summary-maneuvering
+  :type '(choice (const :tag "None" nil)
+                 (const :tag "Undownloaded when unplugged" undownloaded)
+                 (const :tag "Undownloaded" always-undownloaded)
+                 (const :tag "Unfetched" unfetched)))
+
 (defcustom gnus-summary-check-current nil
   "*If non-nil, consider the current article when moving.
 The \"unread\" movement commands will stay on the same line if the
@@ -299,8 +399,12 @@ and non-`vertical', do both horizontal and vertical recentering."
   :group 'gnus-summary-maneuvering
   :type '(choice (const :tag "none" nil)
                 (const vertical)
+                (integer :tag "height")
                 (sexp :menu-tag "both" t)))
 
+(defvar gnus-auto-center-group t
+  "*If non-nil, always center the group buffer.")
+
 (defcustom gnus-show-all-headers nil
   "*If non-nil, don't hide any headers."
   :group 'gnus-article-hiding
@@ -311,7 +415,7 @@ and non-`vertical', do both horizontal and vertical recentering."
   "*If non-nil, ignore articles with identical Message-ID headers."
   :group 'gnus-summary
   :type 'boolean)
-  
+
 (defcustom gnus-single-article-buffer t
   "*If non-nil, display all articles in the same buffer.
 If nil, each group will get its own article buffer."
@@ -325,22 +429,24 @@ variable."
   :group 'gnus-article-various
   :type 'boolean)
 
-(defcustom gnus-show-mime nil
+(defcustom gnus-show-mime t
   "*If non-nil, do mime processing of articles.
 The articles will simply be fed to the function given by
-`gnus-show-mime-method'."
+`gnus-article-display-method-for-mime'."
   :group 'gnus-article-mime
   :type 'boolean)
 
 (defcustom gnus-move-split-methods nil
   "*Variable used to suggest where articles are to be moved to.
-It uses the same syntax as the `gnus-split-methods' variable."
+It uses the same syntax as the `gnus-split-methods' variable.
+However, whereas `gnus-split-methods' specifies file names as targets,
+this variable specifies group names."
   :group 'gnus-summary-mail
   :type '(repeat (choice (list :value (fun) function)
                         (cons :value ("" "") regexp (repeat string))
                         (sexp :value nil))))
 
-(defcustom gnus-unread-mark ? 
+(defcustom gnus-unread-mark ?\ ;;;Whitespace
   "*Mark used for unread articles."
   :group 'gnus-summary-marks
   :type 'character)
@@ -375,8 +481,13 @@ It uses the same syntax as the `gnus-split-methods' variable."
   :group 'gnus-summary-marks
   :type 'character)
 
+(defcustom gnus-spam-mark ?$
+  "*Mark used for spam articles."
+  :group 'gnus-summary-marks
+  :type 'character)
+
 (defcustom gnus-souped-mark ?F
-  "*Mark used for killed articles."
+  "*Mark used for souped articles."
   :group 'gnus-summary-marks
   :type 'character)
 
@@ -400,13 +511,33 @@ It uses the same syntax as the `gnus-split-methods' variable."
   :group 'gnus-summary-marks
   :type 'character)
 
+(defcustom gnus-forwarded-mark ?F
+  "*Mark used for articles that have been forwarded."
+  :group 'gnus-summary-marks
+  :type 'character)
+
+(defcustom gnus-recent-mark ?N
+  "*Mark used for articles that are recent."
+  :group 'gnus-summary-marks
+  :type 'character)
+
 (defcustom gnus-cached-mark ?*
   "*Mark used for articles that are in the cache."
   :group 'gnus-summary-marks
   :type 'character)
 
 (defcustom gnus-saved-mark ?S
-  "*Mark used for articles that have been saved to."
+  "*Mark used for articles that have been saved."
+  :group 'gnus-summary-marks
+  :type 'character)
+
+(defcustom gnus-unseen-mark ?.
+  "*Mark used for articles that haven't been seen."
+  :group 'gnus-summary-marks
+  :type 'character)
+
+(defcustom gnus-no-mark ?\ ;;;Whitespace
+  "*Mark used for articles that have no other secondary mark."
   :group 'gnus-summary-marks
   :type 'character)
 
@@ -430,11 +561,16 @@ It uses the same syntax as the `gnus-split-methods' variable."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-undownloaded-mark ?@
+(defcustom gnus-undownloaded-mark ?-
   "*Mark used for articles that weren't downloaded."
   :group 'gnus-summary-marks
   :type 'character)
 
+(defcustom gnus-downloaded-mark ?+
+  "*Mark used for articles that were downloaded."
+  :group 'gnus-summary-marks
+  :type 'character)
+
 (defcustom gnus-downloadable-mark ?%
   "*Mark used for articles that are to be downloaded."
   :group 'gnus-summary-marks
@@ -455,7 +591,7 @@ It uses the same syntax as the `gnus-split-methods' variable."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-empty-thread-mark ? 
+(defcustom gnus-empty-thread-mark ?\ ;;;Whitespace
   "*There is no thread under the article."
   :group 'gnus-summary-marks
   :type 'character)
@@ -470,6 +606,21 @@ It uses the same syntax as the `gnus-split-methods' variable."
   :group 'gnus-extract-view
   :type 'boolean)
 
+(defcustom gnus-auto-expirable-marks
+  (list gnus-killed-mark gnus-del-mark gnus-catchup-mark
+       gnus-low-score-mark gnus-ancient-mark gnus-read-mark
+       gnus-souped-mark gnus-duplicate-mark)
+  "*The list of marks converted into expiration if a group is auto-expirable."
+  :version "21.1"
+  :group 'gnus-summary
+  :type '(repeat character))
+
+(defcustom gnus-inhibit-user-auto-expire t
+  "*If non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on."
+  :version "21.1"
+  :group 'gnus-summary
+  :type 'boolean)
+
 (defcustom gnus-view-pseudos nil
   "*If `automatic', pseudo-articles will be viewed automatically.
 If `not-confirm', pseudos will be viewed automatically, and the user
@@ -492,16 +643,20 @@ list of parameters to that command."
   :type 'boolean)
 
 (defcustom gnus-summary-dummy-line-format
-  "  %(:                          :%) %S\n"
+  "   %(:                             :%) %S\n"
   "*The format specification for the dummy roots in the summary buffer.
 It works along the same lines as a normal formatting string,
 with some simple extensions.
 
-%S  The subject"
+%S  The subject
+
+General format specifiers can also be used.
+See `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :group 'gnus-threading
   :type 'string)
 
-(defcustom gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
+(defcustom gnus-summary-mode-line-format "Gnus: %g [%A] %Z"
   "*The format specification for the summary mode line.
 It works along the same lines as a normal formatting string,
 with some simple extensions:
@@ -509,6 +664,7 @@ with some simple extensions:
 %G  Group name
 %p  Unprefixed group name
 %A  Current article number
+%z  Current article score
 %V  Gnus version
 %U  Number of unread articles in the group
 %e  Number of unselected articles in the group
@@ -523,6 +679,16 @@ with some simple extensions:
   :group 'gnus-summary-format
   :type 'string)
 
+(defcustom gnus-list-identifiers nil
+  "Regexp that matches list identifiers to be removed from subject.
+This can also be a list of regexps."
+  :version "21.1"
+  :group 'gnus-summary-format
+  :group 'gnus-article-hiding
+  :type '(choice (const :tag "none" nil)
+                (regexp :value ".*")
+                (repeat :value (".*") regexp)))
+
 (defcustom gnus-summary-mark-below 0
   "*Mark all articles with a score below this variable as read.
 This variable is local to each summary buffer and usually set by the
@@ -532,29 +698,55 @@ score file."
 
 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
   "*List of functions used for sorting articles in the summary buffer.
-This variable is only used when not using a threaded display."
+
+Each function takes two articles and returns non-nil if the first
+article should be sorted before the other.  If you use more than one
+function, the primary sort function should be the last.  You should
+probably always include `gnus-article-sort-by-number' in the list of
+sorting functions -- preferably first.  Also note that sorting by date
+is often much slower than sorting by number, and the sorting order is
+very similar.  (Sorting by date means sorting by the time the message
+was sent, sorting by number means sorting by arrival time.)
+
+Ready-made functions include `gnus-article-sort-by-number',
+`gnus-article-sort-by-author', `gnus-article-sort-by-subject',
+`gnus-article-sort-by-date', `gnus-article-sort-by-random'
+and `gnus-article-sort-by-score'.
+
+When threading is turned on, the variable `gnus-thread-sort-functions'
+controls how articles are sorted."
   :group 'gnus-summary-sort
   :type '(repeat (choice (function-item gnus-article-sort-by-number)
                         (function-item gnus-article-sort-by-author)
                         (function-item gnus-article-sort-by-subject)
                         (function-item gnus-article-sort-by-date)
                         (function-item gnus-article-sort-by-score)
+                        (function-item gnus-article-sort-by-random)
                         (function :tag "other"))))
 
 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
   "*List of functions used for sorting threads in the summary buffer.
 By default, threads are sorted by article number.
 
-Each function takes two threads and return non-nil if the first thread
-should be sorted before the other.  If you use more than one function,
-the primary sort function should be the last.  You should probably
-always include `gnus-thread-sort-by-number' in the list of sorting
-functions -- preferably first.
+Each function takes two threads and returns non-nil if the first
+thread should be sorted before the other.  If you use more than one
+function, the primary sort function should be the last.  You should
+probably always include `gnus-thread-sort-by-number' in the list of
+sorting functions -- preferably first.  Also note that sorting by date
+is often much slower than sorting by number, and the sorting order is
+very similar.  (Sorting by date means sorting by the time the message
+was sent, sorting by number means sorting by arrival time.)
 
 Ready-made functions include `gnus-thread-sort-by-number',
 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
-`gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
-`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function')."
+`gnus-thread-sort-by-date', `gnus-thread-sort-by-score',
+`gnus-thread-sort-by-most-recent-number',
+`gnus-thread-sort-by-most-recent-date',
+`gnus-thread-sort-by-random', and
+`gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
+
+When threading is turned off, the variable
+`gnus-article-sort-functions' controls how articles are sorted."
   :group 'gnus-summary-sort
   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
                         (function-item gnus-thread-sort-by-author)
@@ -562,6 +754,7 @@ Ready-made functions include `gnus-thread-sort-by-number',
                         (function-item gnus-thread-sort-by-date)
                         (function-item gnus-thread-sort-by-score)
                         (function-item gnus-thread-sort-by-total-score)
+                        (function-item gnus-thread-sort-by-random)
                         (function :tag "other"))))
 
 (defcustom gnus-thread-score-function '+
@@ -587,7 +780,7 @@ See `gnus-thread-score-function' for en explanation of what a
 \"thread score\" is.
 
 This variable is local to the summary buffers."
-  :group 'gnus-treading
+  :group 'gnus-threading
   :group 'gnus-score-default
   :type '(choice (const :tag "off" nil)
                 integer))
@@ -595,9 +788,17 @@ This variable is local to the summary buffers."
 (defcustom gnus-summary-mode-hook nil
   "*A hook for Gnus summary mode.
 This hook is run before any variables are set in the summary buffer."
+  :options '(turn-on-gnus-mailing-list-mode gnus-pick-mode)
   :group 'gnus-summary-various
   :type 'hook)
 
+;; Extracted from gnus-xmas-redefine in order to preserve user settings
+(when (featurep 'xemacs)
+  (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
+  (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
+  (add-hook 'gnus-summary-mode-hook
+           'gnus-xmas-switch-horizontal-scrollbar-off))
+
 (defcustom gnus-summary-menu-hook nil
   "*Hook run after the creation of the summary mode menu."
   :group 'gnus-summary-visual
@@ -634,21 +835,21 @@ If you'd like to simplify subjects like the
 `gnus-summary-next-same-subject' command does, you can use the
 following hook:
 
- (setq gnus-select-group-hook
-      (list
-       (lambda ()
-         (mapcar (lambda (header)
-                    (mail-header-set-subject
-                     header
-                     (gnus-simplify-subject
-                      (mail-header-subject header) 're-only)))
-                 gnus-newsgroup-headers))))"
+ (add-hook gnus-select-group-hook
+          (lambda ()
+            (mapcar (lambda (header)
+                      (mail-header-set-subject
+                       header
+                       (gnus-simplify-subject
+                        (mail-header-subject header) 're-only)))
+                    gnus-newsgroup-headers)))"
   :group 'gnus-group-select
   :type 'hook)
 
 (defcustom gnus-select-article-hook nil
   "*A hook called when an article is selected."
   :group 'gnus-summary-choose
+  :options '(gnus-agent-fetch-selected-article)
   :type 'hook)
 
 (defcustom gnus-visual-mark-article-hook
@@ -659,24 +860,14 @@ is not run if `gnus-visual' is nil."
   :group 'gnus-summary-visual
   :type 'hook)
 
-(defcustom gnus-structured-field-decoder 'identity
-  "Function to decode non-ASCII characters in structured field for summary."
-  :group 'gnus-various
-  :type 'function)
-
-(defcustom gnus-unstructured-field-decoder 'identity
-  "Function to decode non-ASCII characters in unstructured field for summary."
-  :group 'gnus-various
-  :type 'function)
-
-(defcustom gnus-parse-headers-hook
-  (list 'gnus-hack-decode-rfc1522 'gnus-decode-rfc1522)
+(defcustom gnus-parse-headers-hook '(gnus-summary-inherit-default-charset)
   "*A hook called before parsing the headers."
   :group 'gnus-various
   :type 'hook)
 
 (defcustom gnus-exit-group-hook nil
-  "*A hook called when exiting (not quitting) summary mode."
+  "*A hook called when exiting summary mode.
+This hook is not called from the non-updating exit commands like `Q'."
   :group 'gnus-various
   :type 'hook)
 
@@ -708,48 +899,71 @@ automatically when it is selected."
   :group 'gnus-summary
   :type 'hook)
 
+(defcustom gnus-summary-article-move-hook nil
+  "*A hook called after an article is moved, copied, respooled, or crossposted."
+  :group 'gnus-summary
+  :type 'hook)
+
+(defcustom gnus-summary-article-delete-hook nil
+  "*A hook called after an article is deleted."
+  :group 'gnus-summary
+  :type 'hook)
+
+(defcustom gnus-summary-article-expire-hook nil
+  "*A hook called after an article is expired."
+  :group 'gnus-summary
+  :type 'hook)
+
+(defcustom gnus-summary-display-arrow
+  (and (fboundp 'display-graphic-p)
+       (display-graphic-p))
+  "*If non-nil, display an arrow highlighting the current article."
+  :version "21.1"
+  :group 'gnus-summary
+  :type 'boolean)
+
 (defcustom gnus-summary-selected-face 'gnus-summary-selected-face
   "Face used for highlighting the current article in the summary buffer."
   :group 'gnus-summary-visual
   :type 'face)
 
+(defvar gnus-tmp-downloaded nil)
+
 (defcustom gnus-summary-highlight
-  '(((= mark gnus-canceled-mark)
+  '(((eq mark gnus-canceled-mark)
      . gnus-summary-cancelled-face)
-    ((and (> score default)
-         (or (= mark gnus-dormant-mark)
-             (= mark gnus-ticked-mark)))
+    ((and uncached (> score default-high))
+     . gnus-summary-high-undownloaded-face)
+    ((and uncached (< score default-low))
+     . gnus-summary-low-undownloaded-face)
+    (uncached
+     . gnus-summary-normal-undownloaded-face)
+    ((and (> score default-high)
+         (or (eq mark gnus-dormant-mark)
+             (eq mark gnus-ticked-mark)))
      . gnus-summary-high-ticked-face)
-    ((and (< score default)
-         (or (= mark gnus-dormant-mark)
-             (= mark gnus-ticked-mark)))
+    ((and (< score default-low)
+         (or (eq mark gnus-dormant-mark)
+             (eq mark gnus-ticked-mark)))
      . gnus-summary-low-ticked-face)
-    ((or (= mark gnus-dormant-mark)
-        (= mark gnus-ticked-mark))
+    ((or (eq mark gnus-dormant-mark)
+        (eq mark gnus-ticked-mark))
      . gnus-summary-normal-ticked-face)
-    ((and (> score default) (= mark gnus-ancient-mark))
+    ((and (> score default-high) (eq mark gnus-ancient-mark))
      . gnus-summary-high-ancient-face)
-    ((and (< score default) (= mark gnus-ancient-mark))
+    ((and (< score default-low) (eq mark gnus-ancient-mark))
      . gnus-summary-low-ancient-face)
-    ((= mark gnus-ancient-mark)
+    ((eq mark gnus-ancient-mark)
      . gnus-summary-normal-ancient-face)
-    ((and (> score default) (= mark gnus-unread-mark))
-     . gnus-summary-high-unread-face)
-    ((and (< score default) (= mark gnus-unread-mark))
-     . gnus-summary-low-unread-face)
-    ((= mark gnus-unread-mark)
-     . gnus-summary-normal-unread-face)
-    ((and (> score default) (memq mark (list gnus-downloadable-mark
-                                            gnus-undownloaded-mark)))
+    ((and (> score default-high) (eq mark gnus-unread-mark))
      . gnus-summary-high-unread-face)
-    ((and (< score default) (memq mark (list gnus-downloadable-mark
-                                            gnus-undownloaded-mark)))
+    ((and (< score default-low) (eq mark gnus-unread-mark))
      . gnus-summary-low-unread-face)
-    ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
+    ((eq mark gnus-unread-mark)
      . gnus-summary-normal-unread-face)
-    ((> score default)
+    ((> score default-high)
      . gnus-summary-high-read-face)
-    ((< score default)
+    ((< score default-low)
      . gnus-summary-low-read-face)
     (t
      . gnus-summary-normal-read-face))
@@ -762,10 +976,13 @@ how those summary lines are displayed, by editing the face field.
 
 You can use the following variables in the FORM field.
 
-score:   The articles score
-default: The default article score.
-below:   The score below which articles are automatically marked as read.
-mark:    The articles mark."
+score:        The article's score
+default:      The default article score.
+default-high: The default score for high scored articles.
+default-low:  The default score for low scored articles.
+below:        The score below which articles are automatically marked as read.
+mark:         The article's mark.
+uncached:     Non-nil if the article is uncached."
   :group 'gnus-summary-visual
   :type '(repeat (cons (sexp :tag "Form" nil)
                       face)))
@@ -773,10 +990,166 @@ mark:    The articles mark."
 (defcustom gnus-alter-header-function nil
   "Function called to allow alteration of article header structures.
 The function is called with one parameter, the article header vector,
-which it may alter in any way.")
+which it may alter in any way."
+  :type '(choice (const :tag "None" nil)
+                function)
+  :group 'gnus-summary)
+
+(defvar gnus-decode-encoded-word-function
+  (mime-find-field-decoder 'From 'nov)
+  "Variable that says which function should be used to decode a string with encoded words.")
+
+(defcustom gnus-extra-headers '(To Newsgroups)
+  "*Extra headers to parse."
+  :version "21.1"
+  :group 'gnus-summary
+  :type '(repeat symbol))
+
+(defcustom gnus-ignored-from-addresses
+  (and user-mail-address (regexp-quote user-mail-address))
+  "*Regexp of From headers that may be suppressed in favor of To headers."
+  :version "21.1"
+  :group 'gnus-summary
+  :type 'regexp)
+
+(defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
+  "List of charsets that should be ignored.
+When these charsets are used in the \"charset\" parameter, the
+default charset will be used instead."
+  :version "21.1"
+  :type '(repeat symbol)
+  :group 'gnus-charset)
+
+(gnus-define-group-parameter
+ ignored-charsets
+ :type list
+ :function-document
+ "Return the ignored charsets of GROUP."
+ :variable gnus-group-ignored-charsets-alist
+ :variable-default
+ '(("alt\\.chinese\\.text" iso-8859-1))
+ :variable-document
+ "Alist of regexps (to match group names) and charsets that should be ignored.
+When these charsets are used in the \"charset\" parameter, the
+default charset will be used instead."
+ :variable-group gnus-charset
+ :variable-type '(repeat (cons (regexp :tag "Group")
+                              (repeat symbol)))
+ :parameter-type '(choice :tag "Ignored charsets"
+                         :value nil
+                         (repeat (symbol)))
+ :parameter-document       "\
+List of charsets that should be ignored.
+
+When these charsets are used in the \"charset\" parameter, the
+default charset will be used instead.")
+
+(defcustom gnus-group-highlight-words-alist nil
+  "Alist of group regexps and highlight regexps.
+This variable uses the same syntax as `gnus-emphasis-alist'."
+  :version "21.1"
+  :type '(repeat (cons (regexp :tag "Group")
+                      (repeat (list (regexp :tag "Highlight regexp")
+                                    (number :tag "Group for entire word" 0)
+                                    (number :tag "Group for displayed part" 0)
+                                    (symbol :tag "Face"
+                                            gnus-emphasis-highlight-words)))))
+  :group 'gnus-summary-visual)
+
+(defcustom gnus-use-wheel nil
+  "Use Intelli-mouse on summary movement"
+  :type 'boolean
+  :group 'gnus-summary-maneuvering)
+
+(defcustom gnus-wheel-scroll-amount '(5 . 1)
+  "Amount to scroll messages by spinning the mouse wheel.
+This is actually a cons cell, where the first item is the amount to scroll
+on a normal wheel event, and the second is the amount to scroll when the
+wheel is moved with the shift key depressed."
+  :type '(cons (integer :tag "Shift") integer)
+  :group 'gnus-summary-maneuvering)
+
+(defcustom gnus-wheel-edge-resistance 2
+  "How hard it should be to change the current article
+by moving the mouse over the edge of the article window."
+  :type 'integer
+  :group 'gnus-summary-maneuvering)
+
+(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))."
+  :version "21.1"
+  :type '(repeat (cons (number :tag "Argument" 1)
+                      (symbol :tag "Charset")))
+  :group 'gnus-charset)
+
+(defcustom gnus-preserve-marks t
+  "Whether marks are preserved when moving, copying and respooling messages."
+  :version "21.1"
+  :type 'boolean
+  :group 'gnus-summary-marks)
+
+(defcustom gnus-alter-articles-to-read-function nil
+  "Function to be called to alter the list of articles to be selected."
+  :type '(choice (const nil) function)
+  :group 'gnus-summary)
+
+(defcustom gnus-orphan-score nil
+  "*All orphans get this score added.  Set in the score file."
+  :group 'gnus-score-default
+  :type '(choice (const nil)
+                integer))
+
+(defcustom gnus-summary-save-parts-default-mime "image/.*"
+  "*A regexp to match MIME parts when saving multiple parts of a
+message with `gnus-summary-save-parts' (\\<gnus-summary-mode-map>\\[gnus-summary-save-parts]).
+This regexp will be used by default when prompting the user for which
+type of files to save."
+  :group 'gnus-summary
+  :type 'regexp)
+
+(defcustom gnus-read-all-available-headers nil
+  "Whether Gnus should parse all headers made available to it.
+This is mostly relevant for slow back ends where the user may
+wish to widen the summary buffer to include all headers
+that were fetched.  Say, for nnultimate groups."
+  :group 'gnus-summary
+  :type '(choice boolean regexp))
+
+(defcustom gnus-summary-muttprint-program "muttprint"
+  "Command (and optional arguments) used to run Muttprint."
+  :version "21.3"
+  :group 'gnus-summary
+  :type 'string)
+
+(defcustom gnus-article-loose-mime nil
+  "If non-nil, don't require MIME-Version header.
+Some brain-damaged MUA/MTA, e.g. Lotus Domino 5.0.6 clients, does not
+supply the MIME-Version header or deliberately strip it From the mail.
+Set it to non-nil, Gnus will treat some articles as MIME even if
+the MIME-Version header is missed."
+  :version "21.3"
+  :type 'boolean
+  :group 'gnus-article-mime)
+
+(defcustom gnus-article-emulate-mime t
+  "If non-nil, use MIME emulation for uuencode and the like.
+This means that Gnus will search message bodies for text that look
+like uuencoded bits, yEncoded bits, and so on, and present that using
+the normal Gnus MIME machinery."
+  :type 'boolean
+  :group 'gnus-article-mime)
 
 ;;; Internal variables
 
+(defvar gnus-summary-display-cache nil)
+(defvar gnus-article-mime-handles nil)
+(defvar gnus-article-decoded-p nil)
+(defvar gnus-article-charset nil)
+(defvar gnus-article-ignored-charsets nil)
 (defvar gnus-scores-exclude-files nil)
 (defvar gnus-page-broken nil)
 
@@ -786,6 +1159,11 @@ which it may alter in any way.")
 
 (defvar gnus-thread-indent-array nil)
 (defvar gnus-thread-indent-array-level gnus-thread-indent-level)
+(defvar gnus-sort-gathered-threads-function 'gnus-thread-sort-by-number
+  "Function called to sort the articles within a thread after it has been gathered together.")
+
+(defvar gnus-summary-save-parts-type-history nil)
+(defvar gnus-summary-save-parts-last-directory nil)
 
 ;; Avoid highlighting in kill files.
 (defvar gnus-summary-inhibit-highlight nil)
@@ -796,6 +1174,7 @@ which it may alter in any way.")
 (defvar gnus-current-move-group nil)
 (defvar gnus-current-copy-group nil)
 (defvar gnus-current-crosspost-group nil)
+(defvar gnus-newsgroup-display nil)
 
 (defvar gnus-newsgroup-dependencies nil)
 (defvar gnus-newsgroup-adaptive nil)
@@ -808,19 +1187,22 @@ which it may alter in any way.")
     (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
     (?s gnus-tmp-subject-or-nil ?s)
     (?n gnus-tmp-name ?s)
-    (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
-       ?s)
-    (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
+    (?A (std11-address-string
+        (car (mime-entity-read-field gnus-tmp-header 'From))) ?s)
+    (?a (or (std11-full-name-string
+            (car (mime-entity-read-field gnus-tmp-header 'From)))
            gnus-tmp-from) ?s)
     (?F gnus-tmp-from ?s)
     (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
     (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
     (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
-    (?o (gnus-date-iso8601 gnus-tmp-header) ?s)
+    (?o (gnus-date-iso8601 (mail-header-date gnus-tmp-header)) ?s)
     (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
     (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
-    (?L gnus-tmp-lines ?d)
+    (?k (gnus-summary-line-message-size gnus-tmp-header) ?s)
+    (?L gnus-tmp-lines ?s)
+    (?O gnus-tmp-downloaded ?c)
     (?I gnus-tmp-indentation ?s)
     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
     (?R gnus-tmp-replied ?c)
@@ -833,6 +1215,8 @@ which it may alter in any way.")
     (?l (bbb-grouplens-score gnus-tmp-header) ?s)
     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
     (?U gnus-tmp-unread ?c)
+    (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header gnus-tmp-from)
+       ?s)
     (?t (gnus-summary-number-of-articles-in-thread
         (and (boundp 'thread) (car thread)) gnus-tmp-level)
        ?d)
@@ -840,10 +1224,13 @@ which it may alter in any way.")
         (and (boundp 'thread) (car thread)) gnus-tmp-level t)
        ?c)
     (?u gnus-tmp-user-defined ?s)
-    (?P (gnus-pick-line-number) ?d))
-  "An alist of format specifications that can appear in summary lines,
-and what variables they correspond with, along with the type of the
-variable (string, integer, character, etc).")
+    (?P (gnus-pick-line-number) ?d)
+    (?B gnus-tmp-thread-tree-header-string ?s)
+    (user-date (gnus-user-date
+               ,(macroexpand '(mail-header-date gnus-tmp-header))) ?s))
+  "An alist of format specifications that can appear in summary lines.
+These are paired with what variables they correspond with, along with
+the type of the variable (string, integer, character, etc).")
 
 (defvar gnus-summary-dummy-line-format-alist
   `((?S gnus-tmp-subject ?s)
@@ -863,16 +1250,25 @@ variable (string, integer, character, etc).")
     (?u gnus-tmp-user-defined ?s)
     (?d (length gnus-newsgroup-dormant) ?d)
     (?t (length gnus-newsgroup-marked) ?d)
+    (?h (length gnus-newsgroup-spam-marked) ?d)
     (?r (length gnus-newsgroup-reads) ?d)
+    (?z (gnus-summary-article-score gnus-tmp-article-number) ?d)
     (?E gnus-newsgroup-expunged-tally ?d)
     (?s (gnus-current-score-file-nondirectory) ?s)))
 
 (defvar gnus-last-search-regexp nil
   "Default regexp for article search command.")
 
+(defvar gnus-summary-search-article-matched-data nil
+  "Last matched data of article search command.  It is the local variable
+in `gnus-article-buffer' which consists of the list of start position,
+end position and text.")
+
 (defvar gnus-last-shell-command nil
   "Default shell command on article.")
 
+(defvar gnus-newsgroup-agentized nil
+  "Locally bound in each summary buffer to indicate whether the server has been agentized.")
 (defvar gnus-newsgroup-begin nil)
 (defvar gnus-newsgroup-end nil)
 (defvar gnus-newsgroup-last-rmail nil)
@@ -886,12 +1282,13 @@ variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-data-reverse nil)
 (defvar gnus-newsgroup-limit nil)
 (defvar gnus-newsgroup-limits nil)
+(defvar gnus-summary-use-undownloaded-faces nil)
 
 (defvar gnus-newsgroup-unreads nil
-  "List of unread articles in the current newsgroup.")
+  "Sorted list of unread articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-unselected nil
-  "List of unselected unread articles in the current newsgroup.")
+  "Sorted list of unselected unread articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-reads nil
   "Alist of read articles and article marks in the current newsgroup.")
@@ -899,13 +1296,16 @@ variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-expunged-tally nil)
 
 (defvar gnus-newsgroup-marked nil
-  "List of ticked articles in the current newsgroup (a subset of unread art).")
+  "Sorted list of ticked articles in the current newsgroup (a subset of unread art).")
+
+(defvar gnus-newsgroup-spam-marked nil
+  "List of ranges of articles that have been marked as spam.")
 
 (defvar gnus-newsgroup-killed nil
   "List of ranges of articles that have been through the scoring process.")
 
 (defvar gnus-newsgroup-cached nil
-  "List of articles that come from the article cache.")
+  "Sorted list of articles that come from the article cache.")
 
 (defvar gnus-newsgroup-saved nil
   "List of articles that have been saved.")
@@ -915,17 +1315,29 @@ variable (string, integer, character, etc).")
 (defvar gnus-newsgroup-replied nil
   "List of articles that have been replied to in the current newsgroup.")
 
+(defvar gnus-newsgroup-forwarded nil
+  "List of articles that have been forwarded in the current newsgroup.")
+
+(defvar gnus-newsgroup-recent nil
+  "List of articles that have are recent in the current newsgroup.")
+
 (defvar gnus-newsgroup-expirable nil
-  "List of articles in the current newsgroup that can be expired.")
+  "Sorted list of articles in the current newsgroup that can be expired.")
 
 (defvar gnus-newsgroup-processable nil
   "List of articles in the current newsgroup that can be processed.")
 
 (defvar gnus-newsgroup-downloadable nil
-  "List of articles in the current newsgroup that can be processed.")
+  "Sorted list of articles in the current newsgroup that can be processed.")
+
+(defvar gnus-newsgroup-unfetched nil
+  "Sorted list of articles in the current newsgroup whose headers have
+not been fetched into the agent.
+
+This list will always be a subset of gnus-newsgroup-undownloaded.")
 
 (defvar gnus-newsgroup-undownloaded nil
-  "List of articles in the current newsgroup that haven't been downloaded..")
+  "List of articles in the current newsgroup that haven't been downloaded.")
 
 (defvar gnus-newsgroup-unsendable nil
   "List of articles in the current newsgroup that won't be sent.")
@@ -934,11 +1346,23 @@ variable (string, integer, character, etc).")
   "List of articles in the current newsgroup that have bookmarks.")
 
 (defvar gnus-newsgroup-dormant nil
-  "List of dormant articles in the current newsgroup.")
+  "Sorted list of dormant articles in the current newsgroup.")
+
+(defvar gnus-newsgroup-unseen nil
+  "List of unseen articles in the current newsgroup.")
+
+(defvar gnus-newsgroup-seen nil
+  "Range of seen articles in the current newsgroup.")
+
+(defvar gnus-newsgroup-articles nil
+  "List of articles in the current newsgroup.")
 
 (defvar gnus-newsgroup-scored nil
   "List of scored articles in the current newsgroup.")
 
+(defvar gnus-newsgroup-incorporated nil
+  "List of incorporated articles in the current newsgroup.")
+
 (defvar gnus-newsgroup-headers nil
   "List of article headers in the current newsgroup.")
 
@@ -958,19 +1382,29 @@ variable (string, integer, character, etc).")
 (defvar gnus-have-all-headers nil)
 (defvar gnus-last-article nil)
 (defvar gnus-newsgroup-history nil)
+(defvar gnus-newsgroup-charset nil)
+(defvar gnus-newsgroup-ephemeral-charset nil)
+(defvar gnus-newsgroup-ephemeral-ignored-charsets nil)
 
-(defconst gnus-summary-local-variables
+(defvar gnus-article-before-search nil)
+
+(defvar gnus-summary-local-variables
   '(gnus-newsgroup-name
     gnus-newsgroup-begin gnus-newsgroup-end
     gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
     gnus-newsgroup-last-folder gnus-newsgroup-last-file
     gnus-newsgroup-auto-expire gnus-newsgroup-unreads
     gnus-newsgroup-unselected gnus-newsgroup-marked
+    gnus-newsgroup-spam-marked
     gnus-newsgroup-reads gnus-newsgroup-saved
-    gnus-newsgroup-replied gnus-newsgroup-expirable
+    gnus-newsgroup-replied gnus-newsgroup-forwarded
+    gnus-newsgroup-recent
+    gnus-newsgroup-expirable
     gnus-newsgroup-processable gnus-newsgroup-killed
     gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
-    gnus-newsgroup-unsendable
+    gnus-newsgroup-unfetched
+    gnus-newsgroup-unsendable gnus-newsgroup-unseen
+    gnus-newsgroup-seen gnus-newsgroup-articles
     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
     gnus-newsgroup-headers gnus-newsgroup-threads
     gnus-newsgroup-prepared gnus-summary-highlight-line-function
@@ -979,8 +1413,10 @@ variable (string, integer, character, etc).")
     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
     gnus-newsgroup-scored gnus-newsgroup-kill-headers
     gnus-thread-expunge-below
-    gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
+    gnus-score-alist gnus-current-score-file
+    (gnus-summary-expunge-below . global)
     (gnus-summary-mark-below . global)
+    (gnus-orphan-score . global)
     gnus-newsgroup-active gnus-scores-exclude-files
     gnus-newsgroup-history gnus-newsgroup-ancient
     gnus-newsgroup-sparse gnus-newsgroup-process-stack
@@ -989,33 +1425,70 @@ variable (string, integer, character, etc).")
     (gnus-newsgroup-expunged-tally . 0)
     gnus-cache-removable-articles gnus-newsgroup-cached
     gnus-newsgroup-data gnus-newsgroup-data-reverse
-    gnus-newsgroup-limit gnus-newsgroup-limits)
+    gnus-newsgroup-limit gnus-newsgroup-limits
+    gnus-newsgroup-charset gnus-newsgroup-display
+    gnus-summary-use-undownloaded-faces
+    gnus-newsgroup-incorporated)
   "Variables that are buffer-local to the summary buffers.")
 
+(defvar gnus-newsgroup-variables nil
+  "A list of variables that have separate values in different newsgroups.
+A list of newsgroup (summary buffer) local variables, or cons of
+variables and their default values (when the default values are not
+nil), that should be made global while the summary buffer is active.
+These variables can be used to set variables in the group parameters
+while still allowing them to affect operations done in other
+buffers. For example:
+
+\(setq gnus-newsgroup-variables
+     '(message-use-followup-to
+       (gnus-visible-headers .
+        \"^From:\\\\|^Newsgroups:\\\\|^Subject:\\\\|^Date:\\\\|^To:\")))
+")
+
 ;; Byte-compiler warning.
-(defvar gnus-article-mode-map)
+(eval-when-compile
+  ;; Bind features so that require will believe that gnus-sum has
+  ;; already been loaded (avoids infinite recursion)
+  (let ((features (cons 'gnus-sum features)))
+    ;; Several of the declarations in gnus-sum are needed to load the
+    ;; following files. Right now, these definitions have been
+    ;; compiled but not defined (evaluated).  We could either do a
+    ;; eval-and-compile about all of the declarations or evaluate the
+    ;; source file.
+    (if (boundp 'gnus-newsgroup-variables)
+        nil
+      (load "gnus-sum.el" t t t))
+    (require 'gnus)
+    (require 'gnus-agent)
+    (require 'gnus-art)))
 
 ;; Subject simplification.
 
 (defun gnus-simplify-whitespace (str)
-  "Remove excessive whitespace."
-  (let ((mystr str))
-    ;; Multiple spaces.
-    (while (string-match "[ \t][ \t]+" mystr)
-      (setq mystr (concat (substring mystr 0 (match-beginning 0))
-                          " "
-                          (substring mystr (match-end 0)))))
-    ;; Leading spaces.
-    (when (string-match "^[ \t]+" mystr)
-      (setq mystr (substring mystr (match-end 0))))
-    ;; Trailing spaces.
-    (when (string-match "[ \t]+$" mystr)
-      (setq mystr (substring mystr 0 (match-beginning 0))))
-    mystr))
+  "Remove excessive whitespace from STR."
+  ;; Multiple spaces.
+  (while (string-match "[ \t][ \t]+" str)
+    (setq str (concat (substring str 0 (match-beginning 0))
+                       " "
+                       (substring str (match-end 0)))))
+  ;; Leading spaces.
+  (when (string-match "^[ \t]+" str)
+    (setq str (substring str (match-end 0))))
+  ;; Trailing spaces.
+  (when (string-match "[ \t]+$" str)
+    (setq str (substring str 0 (match-beginning 0))))
+  str)
+
+(defun gnus-simplify-all-whitespace (str)
+  "Remove all whitespace from STR."
+  (while (string-match "[ \t\n]+" str)
+    (setq str (replace-match "" nil nil str)))
+  str)
 
 (defsubst gnus-simplify-subject-re (subject)
   "Remove \"Re:\" from subject lines."
-  (if (string-match "^[Rr][Ee]: *" subject)
+  (if (string-match message-subject-re-regexp subject)
       (substring subject (match-end 0))
     subject))
 
@@ -1043,7 +1516,7 @@ If RE-ONLY is non-nil, strip leading `Re:'s only."
 (defsubst gnus-simplify-buffer-fuzzy-step (regexp &optional newtext)
   (goto-char (point-min))
   (while (re-search-forward regexp nil t)
-      (replace-match (or newtext ""))))
+    (replace-match (or newtext ""))))
 
 (defun gnus-simplify-buffer-fuzzy ()
   "Simplify string in the buffer fuzzily.
@@ -1051,7 +1524,7 @@ The string in the accessible portion of the current buffer is simplified.
 It is assumed to be a single-line subject.
 Whitespace is generally cleaned up, and miscellaneous leading/trailing
 matter is removed.  Additional things can be deleted by setting
-gnus-simplify-subject-fuzzy-regexp."
+`gnus-simplify-subject-fuzzy-regexp'."
   (let ((case-fold-search t)
        (modified-tick))
     (gnus-simplify-buffer-fuzzy-step "\t" " ")
@@ -1089,7 +1562,7 @@ See `gnus-simplify-buffer-fuzzy' for details."
       (buffer-string))))
 
 (defsubst gnus-simplify-subject-fully (subject)
-  "Simplify a subject string according to gnus-summary-gather-subject-limit."
+  "Simplify a subject string according to `gnus-summary-gather-subject-limit'."
   (cond
    (gnus-simplify-subject-functions
     (gnus-map-function gnus-simplify-subject-functions subject))
@@ -1105,7 +1578,7 @@ See `gnus-simplify-buffer-fuzzy' for details."
 
 (defsubst gnus-subject-equal (s1 s2 &optional simple-first)
   "Check whether two subjects are equal.
-If optional argument simple-first is t, first argument is already
+If optional argument SIMPLE-FIRST is t, first argument is already
 simplified."
   (cond
    ((null simple-first)
@@ -1128,314 +1601,462 @@ increase the score of each group you read."
 
 (put 'gnus-summary-mode 'mode-class 'special)
 
-(when t
-  ;; Non-orthogonal keys
-
-  (gnus-define-keys gnus-summary-mode-map
-    " " gnus-summary-next-page
-    "\177" gnus-summary-prev-page
-    [delete] gnus-summary-prev-page
-    [backspace] gnus-summary-prev-page
-    "\r" gnus-summary-scroll-up
-    "n" gnus-summary-next-unread-article
-    "p" gnus-summary-prev-unread-article
-    "N" gnus-summary-next-article
-    "P" gnus-summary-prev-article
-    "\M-\C-n" gnus-summary-next-same-subject
-    "\M-\C-p" gnus-summary-prev-same-subject
-    "\M-n" gnus-summary-next-unread-subject
-    "\M-p" gnus-summary-prev-unread-subject
-    "." gnus-summary-first-unread-article
-    "," gnus-summary-best-unread-article
-    "\M-s" gnus-summary-search-article-forward
-    "\M-r" gnus-summary-search-article-backward
-    "<" gnus-summary-beginning-of-article
-    ">" gnus-summary-end-of-article
-    "j" gnus-summary-goto-article
-    "^" gnus-summary-refer-parent-article
-    "\M-^" gnus-summary-refer-article
-    "u" gnus-summary-tick-article-forward
-    "!" gnus-summary-tick-article-forward
-    "U" gnus-summary-tick-article-backward
-    "d" gnus-summary-mark-as-read-forward
-    "D" gnus-summary-mark-as-read-backward
-    "E" gnus-summary-mark-as-expirable
-    "\M-u" gnus-summary-clear-mark-forward
-    "\M-U" gnus-summary-clear-mark-backward
-    "k" gnus-summary-kill-same-subject-and-select
-    "\C-k" gnus-summary-kill-same-subject
-    "\M-\C-k" gnus-summary-kill-thread
-    "\M-\C-l" gnus-summary-lower-thread
-    "e" gnus-summary-edit-article
-    "#" gnus-summary-mark-as-processable
-    "\M-#" gnus-summary-unmark-as-processable
-    "\M-\C-t" gnus-summary-toggle-threads
-    "\M-\C-s" gnus-summary-show-thread
-    "\M-\C-h" gnus-summary-hide-thread
-    "\M-\C-f" gnus-summary-next-thread
-    "\M-\C-b" gnus-summary-prev-thread
-    "\M-\C-u" gnus-summary-up-thread
-    "\M-\C-d" gnus-summary-down-thread
-    "&" gnus-summary-execute-command
-    "c" gnus-summary-catchup-and-exit
-    "\C-w" gnus-summary-mark-region-as-read
-    "\C-t" gnus-summary-toggle-truncation
-    "?" gnus-summary-mark-as-dormant
-    "\C-c\M-\C-s" gnus-summary-limit-include-expunged
-    "\C-c\C-s\C-n" gnus-summary-sort-by-number
-    "\C-c\C-s\C-l" gnus-summary-sort-by-lines
-    "\C-c\C-s\C-a" gnus-summary-sort-by-author
-    "\C-c\C-s\C-s" gnus-summary-sort-by-subject
-    "\C-c\C-s\C-d" gnus-summary-sort-by-date
-    "\C-c\C-s\C-i" gnus-summary-sort-by-score
-    "=" gnus-summary-expand-window
-    "\C-x\C-s" gnus-summary-reselect-current-group
-    "\M-g" gnus-summary-rescan-group
-    "w" gnus-summary-stop-page-breaking
-    "\C-c\C-r" gnus-summary-caesar-message
-    "\M-t" gnus-summary-toggle-mime
-    "f" gnus-summary-followup
-    "F" gnus-summary-followup-with-original
-    "C" gnus-summary-cancel-article
-    "r" gnus-summary-reply
-    "R" gnus-summary-reply-with-original
-    "\C-c\C-f" gnus-summary-mail-forward
-    "o" gnus-summary-save-article
-    "\C-o" gnus-summary-save-article-mail
-    "|" gnus-summary-pipe-output
-    "\M-k" gnus-summary-edit-local-kill
-    "\M-K" gnus-summary-edit-global-kill
-    ;; "V" gnus-version
-    "\C-c\C-d" gnus-summary-describe-group
-    "q" gnus-summary-exit
-    "Q" gnus-summary-exit-no-update
-    "\C-c\C-i" gnus-info-find-node
-    gnus-mouse-2 gnus-mouse-pick-article
-    "m" gnus-summary-mail-other-window
-    "a" gnus-summary-post-news
-    "x" gnus-summary-limit-to-unread
-    "s" gnus-summary-isearch-article
-    "t" gnus-article-hide-headers
-    "g" gnus-summary-show-article
-    "l" gnus-summary-goto-last-article
-    "\C-c\C-v\C-v" gnus-uu-decode-uu-view
-    "\C-d" gnus-summary-enter-digest-group
-    "\M-\C-d" gnus-summary-read-document
-    "\M-\C-e" gnus-summary-edit-parameters
-    "\C-c\C-b" gnus-bug
-    "*" gnus-cache-enter-article
-    "\M-*" gnus-cache-remove-article
-    "\M-&" gnus-summary-universal-argument
-    "\C-l" gnus-recenter
-    "I" gnus-summary-increase-score
-    "L" gnus-summary-lower-score
-    "\M-i" gnus-symbolic-argument
-    "h" gnus-summary-select-article-buffer
-    
-    "V" gnus-summary-score-map
-    "X" gnus-uu-extract-map
-    "S" gnus-summary-send-map)
+(defvar gnus-article-commands-menu)
+
+;; Non-orthogonal keys
+
+(gnus-define-keys gnus-summary-mode-map
+  " " gnus-summary-next-page
+  "\177" gnus-summary-prev-page
+  [delete] gnus-summary-prev-page
+  [backspace] gnus-summary-prev-page
+  "\r" gnus-summary-scroll-up
+  "\M-\r" gnus-summary-scroll-down
+  "n" gnus-summary-next-unread-article
+  "p" gnus-summary-prev-unread-article
+  "N" gnus-summary-next-article
+  "P" gnus-summary-prev-article
+  "\M-\C-n" gnus-summary-next-same-subject
+  "\M-\C-p" gnus-summary-prev-same-subject
+  "\M-n" gnus-summary-next-unread-subject
+  "\M-p" gnus-summary-prev-unread-subject
+  "." gnus-summary-first-unread-article
+  "," gnus-summary-best-unread-article
+  "\M-s" gnus-summary-search-article-forward
+  "\M-r" gnus-summary-search-article-backward
+  "<" gnus-summary-beginning-of-article
+  ">" gnus-summary-end-of-article
+  "j" gnus-summary-goto-article
+  "^" gnus-summary-refer-parent-article
+  "\M-^" gnus-summary-refer-article
+  "u" gnus-summary-tick-article-forward
+  "!" gnus-summary-tick-article-forward
+  "U" gnus-summary-tick-article-backward
+  "d" gnus-summary-mark-as-read-forward
+  "D" gnus-summary-mark-as-read-backward
+  "E" gnus-summary-mark-as-expirable
+  "\M-u" gnus-summary-clear-mark-forward
+  "\M-U" gnus-summary-clear-mark-backward
+  "k" gnus-summary-kill-same-subject-and-select
+  "\C-k" gnus-summary-kill-same-subject
+  "\M-\C-k" gnus-summary-kill-thread
+  "\M-\C-l" gnus-summary-lower-thread
+  "e" gnus-summary-edit-article
+  "#" gnus-summary-mark-as-processable
+  "\M-#" gnus-summary-unmark-as-processable
+  "\M-\C-t" gnus-summary-toggle-threads
+  "\M-\C-s" gnus-summary-show-thread
+  "\M-\C-h" gnus-summary-hide-thread
+  "\M-\C-f" gnus-summary-next-thread
+  "\M-\C-b" gnus-summary-prev-thread
+  [(meta down)] gnus-summary-next-thread
+  [(meta up)] gnus-summary-prev-thread
+  "\M-\C-u" gnus-summary-up-thread
+  "\M-\C-d" gnus-summary-down-thread
+  "&" gnus-summary-execute-command
+  "c" gnus-summary-catchup-and-exit
+  "\C-w" gnus-summary-mark-region-as-read
+  "\C-t" gnus-summary-toggle-truncation
+  "?" gnus-summary-mark-as-dormant
+  "\C-c\M-\C-s" gnus-summary-limit-include-expunged
+  "\C-c\C-s\C-n" gnus-summary-sort-by-number
+  "\C-c\C-s\C-l" gnus-summary-sort-by-lines
+  "\C-c\C-s\C-c" gnus-summary-sort-by-chars
+  "\C-c\C-s\C-a" gnus-summary-sort-by-author
+  "\C-c\C-s\C-s" gnus-summary-sort-by-subject
+  "\C-c\C-s\C-d" gnus-summary-sort-by-date
+  "\C-c\C-s\C-i" gnus-summary-sort-by-score
+  "\C-c\C-s\C-o" gnus-summary-sort-by-original
+  "\C-c\C-s\C-r" gnus-summary-sort-by-random
+  "=" gnus-summary-expand-window
+  "\C-x\C-s" gnus-summary-reselect-current-group
+  "\M-g" gnus-summary-rescan-group
+  "w" gnus-summary-stop-page-breaking
+  "\C-c\C-r" gnus-summary-caesar-message
+  "\M-t" gnus-summary-toggle-mime
+  "f" gnus-summary-followup
+  "F" gnus-summary-followup-with-original
+  "C" gnus-summary-cancel-article
+  "r" gnus-summary-reply
+  "R" gnus-summary-reply-with-original
+  "\C-c\C-f" gnus-summary-mail-forward
+  "o" gnus-summary-save-article
+  "\C-o" gnus-summary-save-article-mail
+  "|" gnus-summary-pipe-output
+  "\M-k" gnus-summary-edit-local-kill
+  "\M-K" gnus-summary-edit-global-kill
+  ;; "V" gnus-version
+  "\C-c\C-d" gnus-summary-describe-group
+  "q" gnus-summary-exit
+  "Q" gnus-summary-exit-no-update
+  "\C-c\C-i" gnus-info-find-node
+  gnus-mouse-2 gnus-mouse-pick-article
+  "m" gnus-summary-mail-other-window
+  "a" gnus-summary-post-news
+  "i" gnus-summary-news-other-window
+  "x" gnus-summary-limit-to-unread
+  "s" gnus-summary-isearch-article
+  "t" gnus-summary-toggle-header
+  "g" gnus-summary-show-article
+  "l" gnus-summary-goto-last-article
+  "v" gnus-summary-preview-mime-message
+  "\C-c\C-v\C-v" gnus-uu-decode-uu-view
+  "\C-d" gnus-summary-enter-digest-group
+  "\M-\C-d" gnus-summary-read-document
+  "\M-\C-e" gnus-summary-edit-parameters
+  "\M-\C-a" gnus-summary-customize-parameters
+  "\C-c\C-b" gnus-bug
+  "\C-c\C-n" gnus-namazu-search
+  "*" gnus-cache-enter-article
+  "\M-*" gnus-cache-remove-article
+  "\M-&" gnus-summary-universal-argument
+  "\C-l" gnus-recenter
+  "I" gnus-summary-increase-score
+  "L" gnus-summary-lower-score
+  "\M-i" gnus-symbolic-argument
+  "h" gnus-summary-select-article-buffer
+
+  "V" gnus-summary-score-map
+  "X" gnus-uu-extract-map
+  "S" gnus-summary-send-map)
 
   ;; Sort of orthogonal keymap
-  (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
-    "t" gnus-summary-tick-article-forward
-    "!" gnus-summary-tick-article-forward
-    "d" gnus-summary-mark-as-read-forward
-    "r" gnus-summary-mark-as-read-forward
-    "c" gnus-summary-clear-mark-forward
-    " " gnus-summary-clear-mark-forward
-    "e" gnus-summary-mark-as-expirable
-    "x" gnus-summary-mark-as-expirable
-    "?" gnus-summary-mark-as-dormant
-    "b" gnus-summary-set-bookmark
-    "B" gnus-summary-remove-bookmark
-    "#" gnus-summary-mark-as-processable
-    "\M-#" gnus-summary-unmark-as-processable
-    "S" gnus-summary-limit-include-expunged
-    "C" gnus-summary-catchup
-    "H" gnus-summary-catchup-to-here
-    "\C-c" gnus-summary-catchup-all
-    "k" gnus-summary-kill-same-subject-and-select
-    "K" gnus-summary-kill-same-subject
-    "P" gnus-uu-mark-map)
-
-  (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
-    "c" gnus-summary-clear-above
-    "u" gnus-summary-tick-above
-    "m" gnus-summary-mark-above
-    "k" gnus-summary-kill-below)
-
-  (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
-    "/" gnus-summary-limit-to-subject
-    "n" gnus-summary-limit-to-articles
-    "w" gnus-summary-pop-limit
-    "s" gnus-summary-limit-to-subject
-    "a" gnus-summary-limit-to-author
-    "u" gnus-summary-limit-to-unread
-    "m" gnus-summary-limit-to-marks
-    "v" gnus-summary-limit-to-score
-    "*" gnus-summary-limit-include-cached
-    "D" gnus-summary-limit-include-dormant
-    "T" gnus-summary-limit-include-thread
-    "d" gnus-summary-limit-exclude-dormant
-    "t" gnus-summary-limit-to-age
-    "E" gnus-summary-limit-include-expunged
-    "c" gnus-summary-limit-exclude-childless-dormant
-    "C" gnus-summary-limit-mark-excluded-as-read)
-
-  (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
-    "n" gnus-summary-next-unread-article
-    "p" gnus-summary-prev-unread-article
-    "N" gnus-summary-next-article
-    "P" gnus-summary-prev-article
-    "\C-n" gnus-summary-next-same-subject
-    "\C-p" gnus-summary-prev-same-subject
-    "\M-n" gnus-summary-next-unread-subject
-    "\M-p" gnus-summary-prev-unread-subject
-    "f" gnus-summary-first-unread-article
-    "b" gnus-summary-best-unread-article
-    "j" gnus-summary-goto-article
-    "g" gnus-summary-goto-subject
-    "l" gnus-summary-goto-last-article
-    "o" gnus-summary-pop-article)
-
-  (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
-    "k" gnus-summary-kill-thread
-    "l" gnus-summary-lower-thread
-    "i" gnus-summary-raise-thread
-    "T" gnus-summary-toggle-threads
-    "t" gnus-summary-rethread-current
-    "^" gnus-summary-reparent-thread
-    "s" gnus-summary-show-thread
-    "S" gnus-summary-show-all-threads
-    "h" gnus-summary-hide-thread
-    "H" gnus-summary-hide-all-threads
-    "n" gnus-summary-next-thread
-    "p" gnus-summary-prev-thread
-    "u" gnus-summary-up-thread
-    "o" gnus-summary-top-thread
-    "d" gnus-summary-down-thread
-    "#" gnus-uu-mark-thread
-    "\M-#" gnus-uu-unmark-thread)
-
-  (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
-    "g" gnus-summary-prepare
-    "c" gnus-summary-insert-cached-articles)
-
-  (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
-    "c" gnus-summary-catchup-and-exit
-    "C" gnus-summary-catchup-all-and-exit
-    "E" gnus-summary-exit-no-update
-    "Q" gnus-summary-exit
-    "Z" gnus-summary-exit
-    "n" gnus-summary-catchup-and-goto-next-group
-    "R" gnus-summary-reselect-current-group
-    "G" gnus-summary-rescan-group
-    "N" gnus-summary-next-group
-    "s" gnus-summary-save-newsrc
-    "P" gnus-summary-prev-group)
-
-  (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
-    " " gnus-summary-next-page
-    "n" gnus-summary-next-page
-    "\177" gnus-summary-prev-page
-    [delete] gnus-summary-prev-page
-    "p" gnus-summary-prev-page
-    "\r" gnus-summary-scroll-up
-    "<" gnus-summary-beginning-of-article
-    ">" gnus-summary-end-of-article
-    "b" gnus-summary-beginning-of-article
-    "e" gnus-summary-end-of-article
-    "^" gnus-summary-refer-parent-article
-    "r" gnus-summary-refer-parent-article
-    "R" gnus-summary-refer-references
-    "T" gnus-summary-refer-thread
-    "g" gnus-summary-show-article
-    "s" gnus-summary-isearch-article
-    "P" gnus-summary-print-article)
-
-  (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
-    "b" gnus-article-add-buttons
-    "B" gnus-article-add-buttons-to-head
-    "o" gnus-article-treat-overstrike
-    "e" gnus-article-emphasize
-    "w" gnus-article-fill-cited-article
-    "c" gnus-article-remove-cr
-    "q" gnus-article-de-quoted-unreadable
-    "f" gnus-article-display-x-face
-    "l" gnus-summary-stop-page-breaking
-    "r" gnus-summary-caesar-message
-    "t" gnus-article-hide-headers
-    "v" gnus-summary-verbose-headers
-    "m" gnus-summary-toggle-mime
-    "h" gnus-article-treat-html
-    "d" gnus-article-treat-dumbquotes)
-
-  (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
-    "a" gnus-article-hide
-    "h" gnus-article-hide-headers
-    "b" gnus-article-hide-boring-headers
-    "s" gnus-article-hide-signature
-    "c" gnus-article-hide-citation
-    "p" gnus-article-hide-pgp
-    "P" gnus-article-hide-pem
-    "\C-c" gnus-article-hide-citation-maybe)
-
-  (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
-    "a" gnus-article-highlight
-    "h" gnus-article-highlight-headers
-    "c" gnus-article-highlight-citation
-    "s" gnus-article-highlight-signature)
-
-  (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
-    "z" gnus-article-date-ut
-    "u" gnus-article-date-ut
-    "l" gnus-article-date-local
-    "e" gnus-article-date-lapsed
-    "o" gnus-article-date-original
-    "i" gnus-article-date-iso8601
-    "s" gnus-article-date-user)
-
-  (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
-    "t" gnus-article-remove-trailing-blank-lines
-    "l" gnus-article-strip-leading-blank-lines
-    "m" gnus-article-strip-multiple-blank-lines
-    "a" gnus-article-strip-blank-lines
-    "A" gnus-article-strip-all-blank-lines
-    "s" gnus-article-strip-leading-space)
-
-  (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
-    "v" gnus-version
-    "f" gnus-summary-fetch-faq
-    "d" gnus-summary-describe-group
-    "h" gnus-summary-describe-briefly
-    "i" gnus-info-find-node)
-
-  (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
-    "e" gnus-summary-expire-articles
-    "\M-\C-e" gnus-summary-expire-articles-now
-    "\177" gnus-summary-delete-article
-    [delete] gnus-summary-delete-article
-    "m" gnus-summary-move-article
-    "r" gnus-summary-respool-article
-    "w" gnus-summary-edit-article
-    "c" gnus-summary-copy-article
-    "B" gnus-summary-crosspost-article
-    "q" gnus-summary-respool-query
-    "i" gnus-summary-import-article
-    "p" gnus-summary-article-posted-p)
-
-  (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
-    "o" gnus-summary-save-article
-    "m" gnus-summary-save-article-mail
-    "F" gnus-summary-write-article-file
-    "r" gnus-summary-save-article-rmail
-    "f" gnus-summary-save-article-file
-    "b" gnus-summary-save-article-body-file
-    "h" gnus-summary-save-article-folder
-    "v" gnus-summary-save-article-vm
-    "p" gnus-summary-pipe-output
-    "s" gnus-soup-add-article))
+(gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
+  "t" gnus-summary-tick-article-forward
+  "!" gnus-summary-tick-article-forward
+  "d" gnus-summary-mark-as-read-forward
+  "r" gnus-summary-mark-as-read-forward
+  "c" gnus-summary-clear-mark-forward
+  " " gnus-summary-clear-mark-forward
+  "e" gnus-summary-mark-as-expirable
+  "x" gnus-summary-mark-as-expirable
+  "?" gnus-summary-mark-as-dormant
+  "b" gnus-summary-set-bookmark
+  "B" gnus-summary-remove-bookmark
+  "#" gnus-summary-mark-as-processable
+  "\M-#" gnus-summary-unmark-as-processable
+  "S" gnus-summary-limit-include-expunged
+  "C" gnus-summary-catchup
+  "H" gnus-summary-catchup-to-here
+  "h" gnus-summary-catchup-from-here
+  "\C-c" gnus-summary-catchup-all
+  "k" gnus-summary-kill-same-subject-and-select
+  "K" gnus-summary-kill-same-subject
+  "P" gnus-uu-mark-map)
+
+(gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
+  "c" gnus-summary-clear-above
+  "u" gnus-summary-tick-above
+  "m" gnus-summary-mark-above
+  "k" gnus-summary-kill-below)
+
+(gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
+  "/" gnus-summary-limit-to-subject
+  "n" gnus-summary-limit-to-articles
+  "w" gnus-summary-pop-limit
+  "s" gnus-summary-limit-to-subject
+  "a" gnus-summary-limit-to-author
+  "u" gnus-summary-limit-to-unread
+  "m" gnus-summary-limit-to-marks
+  "M" gnus-summary-limit-exclude-marks
+  "v" gnus-summary-limit-to-score
+  "*" gnus-summary-limit-include-cached
+  "D" gnus-summary-limit-include-dormant
+  "T" gnus-summary-limit-include-thread
+  "d" gnus-summary-limit-exclude-dormant
+  "t" gnus-summary-limit-to-age
+  "." gnus-summary-limit-to-unseen
+  "x" gnus-summary-limit-to-extra
+  "p" gnus-summary-limit-to-display-predicate
+  "E" gnus-summary-limit-include-expunged
+  "c" gnus-summary-limit-exclude-childless-dormant
+  "C" gnus-summary-limit-mark-excluded-as-read
+  "o" gnus-summary-insert-old-articles
+  "N" gnus-summary-insert-new-articles)
+
+(gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
+  "n" gnus-summary-next-unread-article
+  "p" gnus-summary-prev-unread-article
+  "N" gnus-summary-next-article
+  "P" gnus-summary-prev-article
+  "\C-n" gnus-summary-next-same-subject
+  "\C-p" gnus-summary-prev-same-subject
+  "\M-n" gnus-summary-next-unread-subject
+  "\M-p" gnus-summary-prev-unread-subject
+  "f" gnus-summary-first-unread-article
+  "b" gnus-summary-best-unread-article
+  "j" gnus-summary-goto-article
+  "g" gnus-summary-goto-subject
+  "l" gnus-summary-goto-last-article
+  "o" gnus-summary-pop-article)
+
+(gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
+  "k" gnus-summary-kill-thread
+  "l" gnus-summary-lower-thread
+  "i" gnus-summary-raise-thread
+  "T" gnus-summary-toggle-threads
+  "t" gnus-summary-rethread-current
+  "^" gnus-summary-reparent-thread
+  "s" gnus-summary-show-thread
+  "S" gnus-summary-show-all-threads
+  "h" gnus-summary-hide-thread
+  "H" gnus-summary-hide-all-threads
+  "n" gnus-summary-next-thread
+  "p" gnus-summary-prev-thread
+  "u" gnus-summary-up-thread
+  "o" gnus-summary-top-thread
+  "d" gnus-summary-down-thread
+  "#" gnus-uu-mark-thread
+  "\M-#" gnus-uu-unmark-thread)
+
+(gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
+  "g" gnus-summary-prepare
+  "c" gnus-summary-insert-cached-articles
+  "d" gnus-summary-insert-dormant-articles)
+
+(gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
+  "c" gnus-summary-catchup-and-exit
+  "C" gnus-summary-catchup-all-and-exit
+  "E" gnus-summary-exit-no-update
+  "J" gnus-summary-jump-to-other-group
+  "Q" gnus-summary-exit
+  "Z" gnus-summary-exit
+  "n" gnus-summary-catchup-and-goto-next-group
+  "R" gnus-summary-reselect-current-group
+  "G" gnus-summary-rescan-group
+  "N" gnus-summary-next-group
+  "s" gnus-summary-save-newsrc
+  "P" gnus-summary-prev-group)
+
+(gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
+  " " gnus-summary-next-page
+  "n" gnus-summary-next-page
+  "\177" gnus-summary-prev-page
+  [delete] gnus-summary-prev-page
+  "p" gnus-summary-prev-page
+  "\r" gnus-summary-scroll-up
+  "\M-\r" gnus-summary-scroll-down
+  "<" gnus-summary-beginning-of-article
+  ">" gnus-summary-end-of-article
+  "b" gnus-summary-beginning-of-article
+  "e" gnus-summary-end-of-article
+  "^" gnus-summary-refer-parent-article
+  "r" gnus-summary-refer-parent-article
+  "D" gnus-summary-enter-digest-group
+  "R" gnus-summary-refer-references
+  "T" gnus-summary-refer-thread
+  "g" gnus-summary-show-article
+  "s" gnus-summary-isearch-article
+  "P" gnus-summary-print-article
+  "M" gnus-mailing-list-insinuate
+  "t" gnus-article-babel)
+
+(gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
+  "b" gnus-article-add-buttons
+  "B" gnus-article-add-buttons-to-head
+  "o" gnus-article-treat-overstrike
+  "e" gnus-article-emphasize
+  "w" gnus-article-fill-cited-article
+  "Q" gnus-article-fill-long-lines
+  "C" gnus-article-capitalize-sentences
+  "c" gnus-article-remove-cr
+  "Z" gnus-article-decode-HZ
+  "h" gnus-article-wash-html
+  "u" gnus-article-unsplit-urls
+  "f" gnus-article-display-x-face
+  "l" gnus-summary-stop-page-breaking
+  "r" gnus-summary-caesar-message
+  "m" gnus-summary-morse-message
+  "t" gnus-summary-toggle-header
+  "g" gnus-treat-smiley
+  "v" gnus-summary-verbose-headers
+  "m" gnus-summary-toggle-mime
+  "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
+  "p" gnus-article-verify-x-pgp-sig
+  "d" gnus-article-treat-dumbquotes)
+
+(gnus-define-keys (gnus-summary-wash-deuglify-map "Y" gnus-summary-wash-map)
+  ;; mnemonic: deuglif*Y*
+  "u" gnus-article-outlook-unwrap-lines
+  "a" gnus-article-outlook-repair-attribution
+  "c" gnus-article-outlook-rearrange-citation
+  "f" gnus-article-outlook-deuglify-article) ;; mnemonic: full deuglify
+
+(gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
+  "a" gnus-article-hide
+  "h" gnus-article-hide-headers
+  "b" gnus-article-hide-boring-headers
+  "s" gnus-article-hide-signature
+  "c" gnus-article-hide-citation
+  "C" gnus-article-hide-citation-in-followups
+  "l" gnus-article-hide-list-identifiers
+  "B" gnus-article-strip-banner
+  "P" gnus-article-hide-pem
+  "\C-c" gnus-article-hide-citation-maybe)
+
+(gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
+  "a" gnus-article-highlight
+  "h" gnus-article-highlight-headers
+  "c" gnus-article-highlight-citation
+  "s" gnus-article-highlight-signature)
+
+(gnus-define-keys (gnus-summary-wash-header-map "G" gnus-summary-wash-map)
+  "f" gnus-article-treat-fold-headers
+  "u" gnus-article-treat-unfold-headers
+  "n" gnus-article-treat-fold-newsgroups)
+
+(gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map)
+  "x" gnus-article-display-x-face
+  "d" gnus-article-display-face
+  "s" gnus-treat-smiley
+  "D" gnus-article-remove-images
+  "f" gnus-treat-from-picon
+  "m" gnus-treat-mail-picon
+  "n" gnus-treat-newsgroups-picon)
+
+(gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
+  "z" gnus-article-date-ut
+  "u" gnus-article-date-ut
+  "l" gnus-article-date-local
+  "p" gnus-article-date-english
+  "e" gnus-article-date-lapsed
+  "o" gnus-article-date-original
+  "i" gnus-article-date-iso8601
+  "s" gnus-article-date-user)
+
+(gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
+  "t" gnus-article-remove-trailing-blank-lines
+  "l" gnus-article-strip-leading-blank-lines
+  "m" gnus-article-strip-multiple-blank-lines
+  "a" gnus-article-strip-blank-lines
+  "A" gnus-article-strip-all-blank-lines
+  "s" gnus-article-strip-leading-space
+  "e" gnus-article-strip-trailing-space
+  "w" gnus-article-remove-leading-whitespace)
+
+(gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
+  "v" gnus-version
+  "f" gnus-summary-fetch-faq
+  "d" gnus-summary-describe-group
+  "h" gnus-summary-describe-briefly
+  "i" gnus-info-find-node
+  "c" gnus-group-fetch-charter
+  "C" gnus-group-fetch-control)
+
+(gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
+  "e" gnus-summary-expire-articles
+  "\M-\C-e" gnus-summary-expire-articles-now
+  "\177" gnus-summary-delete-article
+  [delete] gnus-summary-delete-article
+  [backspace] gnus-summary-delete-article
+  "m" gnus-summary-move-article
+  "r" gnus-summary-respool-article
+  "w" gnus-summary-edit-article
+  "c" gnus-summary-copy-article
+  "B" gnus-summary-crosspost-article
+  "q" gnus-summary-respool-query
+  "t" gnus-summary-respool-trace
+  "i" gnus-summary-import-article
+  "I" gnus-summary-create-article
+  "p" gnus-summary-article-posted-p)
+
+(gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
+  "o" gnus-summary-save-article
+  "m" gnus-summary-save-article-mail
+  "F" gnus-summary-write-article-file
+  "r" gnus-summary-save-article-rmail
+  "f" gnus-summary-save-article-file
+  "b" gnus-summary-save-article-body-file
+  "h" gnus-summary-save-article-folder
+  "v" gnus-summary-save-article-vm
+  "p" gnus-summary-pipe-output
+  "P" gnus-summary-muttprint
+  "s" gnus-soup-add-article)
+
+(gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
+  "b" gnus-summary-display-buttonized
+  "m" gnus-summary-repair-multipart
+  "v" gnus-article-view-part
+  "o" gnus-article-save-part
+  "c" gnus-article-copy-part
+  "C" gnus-article-view-part-as-charset
+  "e" gnus-article-view-part-externally
+  "E" gnus-article-encrypt-body
+  "i" gnus-article-inline-part
+  "|" gnus-article-pipe-part)
+
+(gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
+  "p" gnus-summary-mark-as-processable
+  "u" gnus-summary-unmark-as-processable
+  "U" gnus-summary-unmark-all-processable
+  "v" gnus-uu-mark-over
+  "s" gnus-uu-mark-series
+  "r" gnus-uu-mark-region
+  "g" gnus-uu-unmark-region
+  "R" gnus-uu-mark-by-regexp
+  "G" gnus-uu-unmark-by-regexp
+  "t" gnus-uu-mark-thread
+  "T" gnus-uu-unmark-thread
+  "a" gnus-uu-mark-all
+  "b" gnus-uu-mark-buffer
+  "S" gnus-uu-mark-sparse
+  "k" gnus-summary-kill-process-mark
+  "y" gnus-summary-yank-process-mark
+  "w" gnus-summary-save-process-mark
+  "i" gnus-uu-invert-processable)
+
+(gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
+  ;;"x" gnus-uu-extract-any
+  "m" gnus-summary-save-parts
+  "u" gnus-uu-decode-uu
+  "U" gnus-uu-decode-uu-and-save
+  "s" gnus-uu-decode-unshar
+  "S" gnus-uu-decode-unshar-and-save
+  "o" gnus-uu-decode-save
+  "O" gnus-uu-decode-save
+  "b" gnus-uu-decode-binhex
+  "B" gnus-uu-decode-binhex
+  "p" gnus-uu-decode-postscript
+  "P" gnus-uu-decode-postscript-and-save)
+
+(gnus-define-keys
+    (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
+  "u" gnus-uu-decode-uu-view
+  "U" gnus-uu-decode-uu-and-save-view
+  "s" gnus-uu-decode-unshar-view
+  "S" gnus-uu-decode-unshar-and-save-view
+  "o" gnus-uu-decode-save-view
+  "O" gnus-uu-decode-save-view
+  "b" gnus-uu-decode-binhex-view
+  "B" gnus-uu-decode-binhex-view
+  "p" gnus-uu-decode-postscript-view
+  "P" gnus-uu-decode-postscript-and-save-view)
+
+(defvar gnus-article-post-menu nil)
+
+(defconst gnus-summary-menu-maxlen 20)
+
+(defun gnus-summary-menu-split (menu)
+  ;; If we have lots of elements, divide them into groups of 20
+  ;; and make a pane (or submenu) for each one.
+  (if (> (length menu) (/ (* gnus-summary-menu-maxlen 3) 2))
+      (let ((menu menu) sublists next
+           (i 1))
+       (while menu
+         ;; Pull off the next gnus-summary-menu-maxlen elements
+         ;; and make them the next element of sublist.
+         (setq next (nthcdr gnus-summary-menu-maxlen menu))
+         (if next
+             (setcdr (nthcdr (1- gnus-summary-menu-maxlen) menu)
+                     nil))
+         (setq sublists (cons (cons (format "%s ... %s" (aref (car menu) 0)
+                                            (aref (car (last menu)) 0)) menu)
+                              sublists))
+         (setq i (1+ i))
+         (setq menu next))
+       (nreverse sublists))
+    ;; Few elements--put them all in one pane.
+    menu))
 
 (defun gnus-summary-make-menu-bar ()
   (gnus-turn-off-edit-menu 'summary)
@@ -1448,7 +2069,6 @@ increase the score of each group you read."
       "Score"
       (nconc
        (list
-       ["Enter score..." gnus-summary-score-entry t]
        ["Customize" gnus-score-customize t])
        (gnus-make-score-map 'increase)
        (gnus-make-score-map 'lower)
@@ -1470,216 +2090,186 @@ increase the score of each group you read."
         ["Increase score..." gnus-summary-increase-score t]
         ["Lower score..." gnus-summary-lower-score t]))))
 
-    '(("Default header"
-       ["Ask" (gnus-score-set-default 'gnus-score-default-header nil)
-       :style radio
-       :selected (null gnus-score-default-header)]
-       ["From" (gnus-score-set-default 'gnus-score-default-header 'a)
-       :style radio
-       :selected (eq gnus-score-default-header 'a)]
-       ["Subject" (gnus-score-set-default 'gnus-score-default-header 's)
-       :style radio
-       :selected (eq gnus-score-default-header 's)]
-       ["Article body"
-       (gnus-score-set-default 'gnus-score-default-header 'b)
-       :style radio
-       :selected (eq gnus-score-default-header 'b )]
-       ["All headers"
-       (gnus-score-set-default 'gnus-score-default-header 'h)
-       :style radio
-       :selected (eq gnus-score-default-header 'h )]
-       ["Message-ID" (gnus-score-set-default 'gnus-score-default-header 'i)
-       :style radio
-       :selected (eq gnus-score-default-header 'i )]
-       ["Thread" (gnus-score-set-default 'gnus-score-default-header 't)
-       :style radio
-       :selected (eq gnus-score-default-header 't )]
-       ["Crossposting"
-       (gnus-score-set-default 'gnus-score-default-header 'x)
-       :style radio
-       :selected (eq gnus-score-default-header 'x )]
-       ["Lines" (gnus-score-set-default 'gnus-score-default-header 'l)
-       :style radio
-       :selected (eq gnus-score-default-header 'l )]
-       ["Date" (gnus-score-set-default 'gnus-score-default-header 'd)
-       :style radio
-       :selected (eq gnus-score-default-header 'd )]
-       ["Followups to author"
-       (gnus-score-set-default 'gnus-score-default-header 'f)
-       :style radio
-       :selected (eq gnus-score-default-header 'f )])
-      ("Default type"
-       ["Ask" (gnus-score-set-default 'gnus-score-default-type nil)
-       :style radio
-       :selected (null gnus-score-default-type)]
-       ;; The `:active' key is commented out in the following,
-       ;; because the GNU Emacs hack to support radio buttons use
-       ;; active to indicate which button is selected.
-       ["Substring" (gnus-score-set-default 'gnus-score-default-type 's)
-       :style radio
-       ;; :active (not (memq gnus-score-default-header '(l d)))
-       :selected (eq gnus-score-default-type 's)]
-       ["Regexp" (gnus-score-set-default 'gnus-score-default-type 'r)
-       :style radio
-       ;; :active (not (memq gnus-score-default-header '(l d)))
-       :selected (eq gnus-score-default-type 'r)]
-       ["Exact" (gnus-score-set-default 'gnus-score-default-type 'e)
-       :style radio
-       ;; :active (not (memq gnus-score-default-header '(l d)))
-       :selected (eq gnus-score-default-type 'e)]
-       ["Fuzzy" (gnus-score-set-default 'gnus-score-default-type 'f)
-       :style radio
-       ;; :active (not (memq gnus-score-default-header '(l d)))
-       :selected (eq gnus-score-default-type 'f)]
-       ["Before date" (gnus-score-set-default 'gnus-score-default-type 'b)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'd))
-       :selected (eq gnus-score-default-type 'b)]
-       ["At date" (gnus-score-set-default 'gnus-score-default-type 'n)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'd))
-       :selected (eq gnus-score-default-type 'n)]
-       ["After date" (gnus-score-set-default 'gnus-score-default-type 'a)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'd))
-       :selected (eq gnus-score-default-type 'a)]
-       ["Less than number"
-       (gnus-score-set-default 'gnus-score-default-type '<)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'l))
-       :selected (eq gnus-score-default-type '<)]
-       ["Equal to number"
-       (gnus-score-set-default 'gnus-score-default-type '=)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'l))
-       :selected (eq gnus-score-default-type '=)]
-       ["Greater than number"
-       (gnus-score-set-default 'gnus-score-default-type '>)
-       :style radio
-       ;; :active (eq (gnus-score-default-header 'l))
-       :selected (eq gnus-score-default-type '>)])
-      ["Default fold" gnus-score-default-fold-toggle
-       :style toggle
-       :selected gnus-score-default-fold]
-      ("Default duration"
-       ["Ask" (gnus-score-set-default 'gnus-score-default-duration nil)
-       :style radio
-       :selected (null gnus-score-default-duration)]
-       ["Permanent"
-       (gnus-score-set-default 'gnus-score-default-duration 'p)
-       :style radio
-       :selected (eq gnus-score-default-duration 'p)]
-       ["Temporary"
-       (gnus-score-set-default 'gnus-score-default-duration 't)
-       :style radio
-       :selected (eq gnus-score-default-duration 't)]
-       ["Immediate"
-       (gnus-score-set-default 'gnus-score-default-duration 'i)
-       :style radio
-       :selected (eq gnus-score-default-duration 'i)]))
-
-    (easy-menu-define
-     gnus-summary-article-menu gnus-summary-mode-map ""
-     '("Article"
-       ("Hide"
-       ["All" gnus-article-hide t]
-       ["Headers" gnus-article-hide-headers t]
-       ["Signature" gnus-article-hide-signature t]
-       ["Citation" gnus-article-hide-citation t]
-       ["PGP" gnus-article-hide-pgp t]
-       ["Boring headers" gnus-article-hide-boring-headers t])
-       ("Highlight"
-       ["All" gnus-article-highlight t]
-       ["Headers" gnus-article-highlight-headers t]
-       ["Signature" gnus-article-highlight-signature t]
-       ["Citation" gnus-article-highlight-citation t])
-       ("Date"
-       ["Local" gnus-article-date-local t]
-       ["ISO8601" gnus-article-date-iso8601 t]
-       ["UT" gnus-article-date-ut t]
-       ["Original" gnus-article-date-original t]
-       ["Lapsed" gnus-article-date-lapsed t]
-       ["User-defined" gnus-article-date-user t])
-       ("Washing"
-       ("Remove Blanks"
-        ["Leading" gnus-article-strip-leading-blank-lines t]
-        ["Multiple" gnus-article-strip-multiple-blank-lines t]
-        ["Trailing" gnus-article-remove-trailing-blank-lines t]
-        ["All of the above" gnus-article-strip-blank-lines t]
-        ["All" gnus-article-strip-all-blank-lines t]
-        ["Leading space" gnus-article-strip-leading-space t])
-       ["Overstrike" gnus-article-treat-overstrike t]
-       ["Dumb quotes" gnus-article-treat-dumbquotes t]
-       ["Emphasis" gnus-article-emphasize t]
-       ["Word wrap" gnus-article-fill-cited-article t]
-       ["CR" gnus-article-remove-cr t]
-       ["Show X-Face" gnus-article-display-x-face t]
-       ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
-       ["UnHTMLize" gnus-article-treat-html t]
-       ["Rot 13" gnus-summary-caesar-message t]
-       ["Unix pipe" gnus-summary-pipe-message t]
-       ["Add buttons" gnus-article-add-buttons t]
-       ["Add buttons to head" gnus-article-add-buttons-to-head t]
-       ["Stop page breaking" gnus-summary-stop-page-breaking t]
-       ["Toggle MIME" gnus-summary-toggle-mime t]
-       ["Verbose header" gnus-summary-verbose-headers t]
-       ["Toggle header" gnus-summary-toggle-header t])
-       ("Output"
-       ["Save in default format" gnus-summary-save-article t]
-       ["Save in file" gnus-summary-save-article-file t]
-       ["Save in Unix mail format" gnus-summary-save-article-mail t]
-       ["Save in MH folder" gnus-summary-save-article-folder t]
-       ["Save in VM folder" gnus-summary-save-article-vm t]
-       ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
-       ["Save body in file" gnus-summary-save-article-body-file t]
-       ["Pipe through a filter" gnus-summary-pipe-output t]
-       ["Add to SOUP packet" gnus-soup-add-article t]
-       ["Print" gnus-summary-print-article t])
-       ("Backend"
-       ["Respool article..." gnus-summary-respool-article t]
-       ["Move article..." gnus-summary-move-article
-        (gnus-check-backend-function
-         'request-move-article gnus-newsgroup-name)]
-       ["Copy article..." gnus-summary-copy-article t]
-       ["Crosspost article..." gnus-summary-crosspost-article
-        (gnus-check-backend-function
-         'request-replace-article gnus-newsgroup-name)]
-       ["Import file..." gnus-summary-import-article t]
-       ["Check if posted" gnus-summary-article-posted-p t]
-       ["Edit article" gnus-summary-edit-article
-        (not (gnus-group-read-only-p))]
-       ["Delete article" gnus-summary-delete-article
-        (gnus-check-backend-function
-         'request-expire-articles gnus-newsgroup-name)]
-       ["Query respool" gnus-summary-respool-query t]
-       ["Delete expirable articles" gnus-summary-expire-articles-now
-        (gnus-check-backend-function
-         'request-expire-articles gnus-newsgroup-name)])
-       ("Extract"
-       ["Uudecode" gnus-uu-decode-uu t]
-       ["Uudecode and save" gnus-uu-decode-uu-and-save t]
-       ["Unshar" gnus-uu-decode-unshar t]
-       ["Unshar and save" gnus-uu-decode-unshar-and-save t]
-       ["Save" gnus-uu-decode-save t]
-       ["Binhex" gnus-uu-decode-binhex t]
-       ["Postscript" gnus-uu-decode-postscript t])
-       ("Cache"
-       ["Enter article" gnus-cache-enter-article t]
-       ["Remove article" gnus-cache-remove-article t])
-       ["Select article buffer" gnus-summary-select-article-buffer t]
-       ["Enter digest buffer" gnus-summary-enter-digest-group t]
-       ["Isearch article..." gnus-summary-isearch-article t]
-       ["Beginning of the article" gnus-summary-beginning-of-article t]
-       ["End of the article" gnus-summary-end-of-article t]
-       ["Fetch parent of article" gnus-summary-refer-parent-article t]
-       ["Fetch referenced articles" gnus-summary-refer-references t]
-       ["Fetch current thread" gnus-summary-refer-thread t]
-       ["Fetch article with id..." gnus-summary-refer-article t]
-       ["Redisplay" gnus-summary-show-article t]))
+    ;; Define both the Article menu in the summary buffer and the
+    ;; equivalent Commands menu in the article buffer here for
+    ;; consistency.
+    (let ((innards
+          `(("Hide"
+             ["All" gnus-article-hide t]
+             ["Headers" gnus-article-hide-headers t]
+             ["Signature" gnus-article-hide-signature t]
+             ["Citation" gnus-article-hide-citation t]
+             ["List identifiers" gnus-article-hide-list-identifiers t]
+             ["Banner" gnus-article-strip-banner t]
+             ["Boring headers" gnus-article-hide-boring-headers t])
+            ("Highlight"
+             ["All" gnus-article-highlight t]
+             ["Headers" gnus-article-highlight-headers t]
+             ["Signature" gnus-article-highlight-signature t]
+             ["Citation" gnus-article-highlight-citation t])
+            ("Date"
+             ["Local" gnus-article-date-local t]
+             ["ISO8601" gnus-article-date-iso8601 t]
+             ["UT" gnus-article-date-ut t]
+             ["Original" gnus-article-date-original t]
+             ["Lapsed" gnus-article-date-lapsed t]
+             ["User-defined" gnus-article-date-user t])
+            ("Display"
+             ["Remove images" gnus-article-remove-images t]
+             ["Toggle smiley" gnus-treat-smiley t]
+             ["Show X-Face" gnus-article-display-x-face t]
+             ["Show picons in From" gnus-treat-from-picon t]
+             ["Show picons in mail headers" gnus-treat-mail-picon t]
+             ["Show picons in news headers" gnus-treat-newsgroups-picon t]
+             ("View as different encoding"
+              ,@(gnus-summary-menu-split
+                 (mapcar
+                  (lambda (cs)
+                    ;; Since easymenu under Emacs doesn't allow
+                    ;; lambda forms for menu commands, we should
+                    ;; provide intern'ed function symbols.
+                    (let ((command (intern (format "\
+gnus-summary-show-article-from-menu-as-charset-%s" cs))))
+                      (fset command
+                            `(lambda ()
+                               (interactive)
+                               (let ((gnus-summary-show-article-charset-alist
+                                      '((1 . ,cs))))
+                                 (gnus-summary-show-article 1))))
+                      `[,(symbol-name cs) ,command t]))
+                  (sort (if (fboundp 'coding-system-list)
+                            (coding-system-list)
+                          ;;(mapcar 'car mm-mime-mule-charset-alist)
+                          )
+                        'string<)))))
+            ("Washing"
+             ("Remove Blanks"
+              ["Leading" gnus-article-strip-leading-blank-lines t]
+              ["Multiple" gnus-article-strip-multiple-blank-lines t]
+              ["Trailing" gnus-article-remove-trailing-blank-lines t]
+              ["All of the above" gnus-article-strip-blank-lines t]
+              ["All" gnus-article-strip-all-blank-lines t]
+              ["Leading space" gnus-article-strip-leading-space t]
+              ["Trailing space" gnus-article-strip-trailing-space t]
+              ["Leading space in headers"
+               gnus-article-remove-leading-whitespace t])
+             ["Overstrike" gnus-article-treat-overstrike t]
+             ["Dumb quotes" gnus-article-treat-dumbquotes t]
+             ["Emphasis" gnus-article-emphasize t]
+             ["Word wrap" gnus-article-fill-cited-article t]
+             ["Fill long lines" gnus-article-fill-long-lines t]
+             ["Capitalize sentences" gnus-article-capitalize-sentences t]
+             ["Remove CR" gnus-article-remove-cr t]
+             ["Rot 13" gnus-summary-caesar-message
+              ,@(if (featurep 'xemacs) '(t)
+                  '(:help "\"Caesar rotate\" article by 13"))]
+             ["Morse decode" gnus-summary-morse-message t]
+             ["Unix pipe..." gnus-summary-pipe-message t]
+             ["Add buttons" gnus-article-add-buttons t]
+             ["Add buttons to head" gnus-article-add-buttons-to-head t]
+             ["Stop page breaking" gnus-summary-stop-page-breaking t]
+             ["Toggle MIME" gnus-summary-toggle-mime t]
+             ["Verbose header" gnus-summary-verbose-headers t]
+             ["Toggle header" gnus-summary-toggle-header t]
+             ["Unfold headers" gnus-article-treat-unfold-headers t]
+             ["Fold newsgroups" gnus-article-treat-fold-newsgroups t]
+             ["Html" gnus-article-wash-html t]
+             ["Unsplit URLs" gnus-article-unsplit-urls t]
+             ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
+             ["Decode HZ" gnus-article-decode-HZ t]
+             ("(Outlook) Deuglify"
+              ["Unwrap lines" gnus-article-outlook-unwrap-lines t]
+              ["Repair attribution" gnus-article-outlook-repair-attribution t]
+              ["Rearrange citation" gnus-article-outlook-rearrange-citation t]
+              ["Full (Outlook) deuglify"
+               gnus-article-outlook-deuglify-article t])
+             )
+            ("Output"
+             ["Save in default format..." gnus-summary-save-article
+              ,@(if (featurep 'xemacs) '(t)
+                  '(:help "Save article using default method"))]
+             ["Save in file..." gnus-summary-save-article-file
+              ,@(if (featurep 'xemacs) '(t)
+                  '(:help "Save article in file"))]
+             ["Save in Unix mail format..." gnus-summary-save-article-mail t]
+             ["Save in MH folder..." gnus-summary-save-article-folder t]
+             ["Save in VM folder..." gnus-summary-save-article-vm t]
+             ["Save in RMAIL mbox..." gnus-summary-save-article-rmail t]
+             ["Save body in file..." gnus-summary-save-article-body-file t]
+             ["Pipe through a filter..." gnus-summary-pipe-output t]
+             ["Add to SOUP packet" gnus-soup-add-article t]
+             ["Print with Muttprint..." gnus-summary-muttprint t]
+             ["Print" gnus-summary-print-article t])
+            ("Backend"
+             ["Respool article..." gnus-summary-respool-article t]
+             ["Move article..." gnus-summary-move-article
+              (gnus-check-backend-function
+               'request-move-article gnus-newsgroup-name)]
+             ["Copy article..." gnus-summary-copy-article t]
+             ["Crosspost article..." gnus-summary-crosspost-article
+              (gnus-check-backend-function
+               'request-replace-article gnus-newsgroup-name)]
+             ["Import file..." gnus-summary-import-article
+              (gnus-check-backend-function
+               'request-accept-article gnus-newsgroup-name)]
+             ["Create article..." gnus-summary-create-article
+              (gnus-check-backend-function
+               'request-accept-article gnus-newsgroup-name)]
+             ["Check if posted" gnus-summary-article-posted-p t]
+             ["Edit article" gnus-summary-edit-article
+              (not (gnus-group-read-only-p))]
+             ["Delete article" gnus-summary-delete-article
+              (gnus-check-backend-function
+               'request-expire-articles gnus-newsgroup-name)]
+             ["Query respool" gnus-summary-respool-query t]
+             ["Trace respool" gnus-summary-respool-trace t]
+             ["Delete expirable articles" gnus-summary-expire-articles-now
+              (gnus-check-backend-function
+               'request-expire-articles gnus-newsgroup-name)])
+            ("Extract"
+             ["Uudecode" gnus-uu-decode-uu
+              ,@(if (featurep 'xemacs) '(t)
+                  '(:help "Decode uuencoded article(s)"))]
+             ["Uudecode and save" gnus-uu-decode-uu-and-save t]
+             ["Unshar" gnus-uu-decode-unshar t]
+             ["Unshar and save" gnus-uu-decode-unshar-and-save t]
+             ["Save" gnus-uu-decode-save t]
+             ["Binhex" gnus-uu-decode-binhex t]
+             ["Postscript" gnus-uu-decode-postscript t])
+            ("Cache"
+             ["Enter article" gnus-cache-enter-article t]
+             ["Remove article" gnus-cache-remove-article t])
+            ["Translate" gnus-article-babel t]
+            ["Select article buffer" gnus-summary-select-article-buffer t]
+            ["Enter digest buffer" gnus-summary-enter-digest-group t]
+            ["Isearch article..." gnus-summary-isearch-article t]
+            ["Beginning of the article" gnus-summary-beginning-of-article t]
+            ["End of the article" gnus-summary-end-of-article t]
+            ["Fetch parent of article" gnus-summary-refer-parent-article t]
+            ["Fetch referenced articles" gnus-summary-refer-references t]
+            ["Fetch current thread" gnus-summary-refer-thread t]
+            ["Fetch article with id..." gnus-summary-refer-article t]
+            ["Setup Mailing List Params" gnus-mailing-list-insinuate t]
+            ["Redisplay" gnus-summary-show-article t]
+            ["Raw article" gnus-summary-show-raw-article :keys "C-u g"])))
+      (easy-menu-define
+       gnus-summary-article-menu gnus-summary-mode-map ""
+       (cons "Article" innards))
+
+      (if (not (keymapp gnus-summary-article-menu))
+         (easy-menu-define
+          gnus-article-commands-menu gnus-article-mode-map ""
+          (cons "Commands" innards))
+       ;; in Emacs, don't share menu.
+       (setq gnus-article-commands-menu
+             (copy-keymap gnus-summary-article-menu))
+       (define-key gnus-article-mode-map [menu-bar commands]
+         (cons "Commands" gnus-article-commands-menu))))
 
     (easy-menu-define
      gnus-summary-thread-menu gnus-summary-mode-map ""
      '("Threads"
+       ["Find all messages in thread" gnus-summary-refer-thread t]
        ["Toggle threading" gnus-summary-toggle-threads t]
        ["Hide threads" gnus-summary-hide-all-threads t]
        ["Show threads" gnus-summary-show-all-threads t]
@@ -1693,29 +2283,46 @@ increase the score of each group you read."
        ["Mark thread as read" gnus-summary-kill-thread t]
        ["Lower thread score" gnus-summary-lower-thread t]
        ["Raise thread score" gnus-summary-raise-thread t]
-       ["Rethread current" gnus-summary-rethread-current t]
-       ))
+       ["Rethread current" gnus-summary-rethread-current t]))
 
     (easy-menu-define
      gnus-summary-post-menu gnus-summary-mode-map ""
-     '("Post"
-       ["Post an article" gnus-summary-post-news t]
-       ["Followup" gnus-summary-followup t]
-       ["Followup and yank" gnus-summary-followup-with-original t]
+     `("Post"
+       ["Send a message (mail or news)" gnus-summary-post-news
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Post an article"))]
+       ["Followup" gnus-summary-followup
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Post followup to this article"))]
+       ["Followup and yank" gnus-summary-followup-with-original
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Post followup to this article, quoting its contents"))]
        ["Supersede article" gnus-summary-supersede-article t]
-       ["Cancel article" gnus-summary-cancel-article t]
+       ["Cancel article" gnus-summary-cancel-article
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Cancel an article you posted"))]
        ["Reply" gnus-summary-reply t]
        ["Reply and yank" gnus-summary-reply-with-original t]
        ["Wide reply" gnus-summary-wide-reply t]
-       ["Wide reply and yank" gnus-summary-wide-reply-with-original t]
+       ["Wide reply and yank" gnus-summary-wide-reply-with-original
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Mail a reply, quoting this article"))]
+       ["Very wide reply" gnus-summary-very-wide-reply t]
+       ["Very wide reply and yank" gnus-summary-very-wide-reply-with-original
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Mail a very wide reply, quoting this article"))]
        ["Mail forward" gnus-summary-mail-forward t]
        ["Post forward" gnus-summary-post-forward t]
-       ["Digest and mail" gnus-uu-digest-mail-forward t]
-       ["Digest and post" gnus-uu-digest-post-forward t]
+       ["Digest and mail" gnus-summary-digest-mail-forward t]
+       ["Digest and post" gnus-summary-digest-post-forward t]
        ["Resend message" gnus-summary-resend-message t]
+       ["Resend message edit" gnus-summary-resend-message-edit t]
        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
        ["Send a mail" gnus-summary-mail-other-window t]
-       ["Uuencode and post" gnus-uu-post-news t]
+       ["Create a local message" gnus-summary-news-other-window t]
+       ["Uuencode and post" gnus-uu-post-news
+       ,@(if (featurep 'xemacs) '(t)
+           '(:help "Post a uuencoded article"))]
        ["Followup via news" gnus-summary-followup-to-mail t]
        ["Followup via news and yank"
        gnus-summary-followup-to-mail-with-original t]
@@ -1724,18 +2331,32 @@ increase the score of each group you read."
        ;;["Send bounced" gnus-resend-bounced-mail t])
        ))
 
+    (cond
+     ((not (keymapp gnus-summary-post-menu))
+      (setq gnus-article-post-menu gnus-summary-post-menu))
+     ((not gnus-article-post-menu)
+      ;; Don't share post menu.
+      (setq gnus-article-post-menu
+           (copy-keymap gnus-summary-post-menu))))
+    (define-key gnus-article-mode-map [menu-bar post]
+      (cons "Post" gnus-article-post-menu))
+
     (easy-menu-define
      gnus-summary-misc-menu gnus-summary-mode-map ""
-     '("Misc"
+     `("Gnus"
        ("Mark Read"
        ["Mark as read" gnus-summary-mark-as-read-forward t]
        ["Mark same subject and select"
         gnus-summary-kill-same-subject-and-select t]
        ["Mark same subject" gnus-summary-kill-same-subject t]
-       ["Catchup" gnus-summary-catchup t]
+       ["Catchup" gnus-summary-catchup
+        ,@(if (featurep 'xemacs) '(t)
+            '(:help "Mark unread articles in this group as read"))]
        ["Catchup all" gnus-summary-catchup-all t]
        ["Catchup to here" gnus-summary-catchup-to-here t]
-       ["Catchup region" gnus-summary-mark-region-as-read t]
+       ["Catchup from here" gnus-summary-catchup-from-here t]
+       ["Catchup region" gnus-summary-mark-region-as-read
+        (gnus-mark-active-p)]
        ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
        ("Mark Various"
        ["Tick" gnus-summary-tick-article-forward t]
@@ -1744,29 +2365,35 @@ increase the score of each group you read."
        ["Set expirable mark" gnus-summary-mark-as-expirable t]
        ["Set bookmark" gnus-summary-set-bookmark t]
        ["Remove bookmark" gnus-summary-remove-bookmark t])
-       ("Mark Limit"
+       ("Limit to"
        ["Marks..." gnus-summary-limit-to-marks t]
        ["Subject..." gnus-summary-limit-to-subject t]
        ["Author..." gnus-summary-limit-to-author t]
        ["Age..." gnus-summary-limit-to-age t]
-       ["Score" gnus-summary-limit-to-score t]
+       ["Extra..." gnus-summary-limit-to-extra t]
+       ["Score..." gnus-summary-limit-to-score t]
+       ["Display Predicate" gnus-summary-limit-to-display-predicate t]
        ["Unread" gnus-summary-limit-to-unread t]
+       ["Unseen" gnus-summary-limit-to-unseen t]
        ["Non-dormant" gnus-summary-limit-exclude-dormant t]
-       ["Articles" gnus-summary-limit-to-articles t]
+       ["Next articles" gnus-summary-limit-to-articles t]
        ["Pop limit" gnus-summary-pop-limit t]
        ["Show dormant" gnus-summary-limit-include-dormant t]
        ["Hide childless dormant"
         gnus-summary-limit-exclude-childless-dormant t]
        ;;["Hide thread" gnus-summary-limit-exclude-thread t]
-       ["Show expunged" gnus-summary-show-all-expunged t])
+       ["Hide marked" gnus-summary-limit-exclude-marks t]
+       ["Show expunged" gnus-summary-limit-include-expunged t])
        ("Process Mark"
        ["Set mark" gnus-summary-mark-as-processable t]
        ["Remove mark" gnus-summary-unmark-as-processable t]
        ["Remove all marks" gnus-summary-unmark-all-processable t]
        ["Mark above" gnus-uu-mark-over t]
        ["Mark series" gnus-uu-mark-series t]
-       ["Mark region" gnus-uu-mark-region t]
+       ["Mark region" gnus-uu-mark-region (gnus-mark-active-p)]
+       ["Unmark region" gnus-uu-unmark-region (gnus-mark-active-p)]
        ["Mark by regexp..." gnus-uu-mark-by-regexp t]
+       ["Unmark by regexp..." gnus-uu-unmark-by-regexp t]
        ["Mark all" gnus-uu-mark-all t]
        ["Mark buffer" gnus-uu-mark-buffer t]
        ["Mark sparse" gnus-uu-mark-sparse t]
@@ -1776,10 +2403,15 @@ increase the score of each group you read."
         ["Kill" gnus-summary-kill-process-mark t]
         ["Yank" gnus-summary-yank-process-mark
          gnus-newsgroup-process-stack]
-        ["Save" gnus-summary-save-process-mark t]))
+        ["Save" gnus-summary-save-process-mark t]
+        ["Run command on marked..." gnus-summary-universal-argument t]))
        ("Scroll article"
-       ["Page forward" gnus-summary-next-page t]
-       ["Page backward" gnus-summary-prev-page t]
+       ["Page forward" gnus-summary-next-page
+        ,@(if (featurep 'xemacs) '(t)
+            '(:help "Show next page of article"))]
+       ["Page backward" gnus-summary-prev-page
+        ,@(if (featurep 'xemacs) '(t)
+            '(:help "Show previous page of article"))]
        ["Line forward" gnus-summary-scroll-up t])
        ("Move"
        ["Next unread article" gnus-summary-next-unread-article t]
@@ -1802,10 +2434,19 @@ increase the score of each group you read."
        ["Sort by subject" gnus-summary-sort-by-subject t]
        ["Sort by date" gnus-summary-sort-by-date t]
        ["Sort by score" gnus-summary-sort-by-score t]
-       ["Sort by lines" gnus-summary-sort-by-lines t])
+       ["Sort by lines" gnus-summary-sort-by-lines t]
+       ["Sort by characters" gnus-summary-sort-by-chars t]
+       ["Randomize" gnus-summary-sort-by-random t]
+       ["Original sort" gnus-summary-sort-by-original t])
        ("Help"
        ["Fetch group FAQ" gnus-summary-fetch-faq t]
        ["Describe group" gnus-summary-describe-group t]
+       ["Fetch charter" gnus-group-fetch-charter
+        ,@(if (featurep 'xemacs) nil
+            '(:help "Display the charter of the current group"))]
+       ["Fetch control message" gnus-group-fetch-control
+        ,@(if (featurep 'xemacs) nil
+            '(:help "Display the archived control message for the current group"))]
        ["Read manual" gnus-info-find-node t])
        ("Modes"
        ["Pick and read" gnus-pick-mode t]
@@ -1813,9 +2454,12 @@ increase the score of each group you read."
        ("Regeneration"
        ["Regenerate" gnus-summary-prepare t]
        ["Insert cached articles" gnus-summary-insert-cached-articles t]
+       ["Insert dormant articles" gnus-summary-insert-dormant-articles t]
        ["Toggle threading" gnus-summary-toggle-threads t])
+       ["See old articles" gnus-summary-insert-old-articles t]
+       ["See new articles" gnus-summary-insert-new-articles t]
        ["Filter articles..." gnus-summary-execute-command t]
-       ["Run command on subjects..." gnus-summary-universal-argument t]
+       ["Run command on articles..." gnus-summary-universal-argument t]
        ["Search articles forward..." gnus-summary-search-article-forward t]
        ["Search articles backward..." gnus-summary-search-article-backward t]
        ["Toggle line truncation" gnus-summary-toggle-truncation t]
@@ -1826,11 +2470,17 @@ increase the score of each group you read."
        ["Edit local kill file" gnus-summary-edit-local-kill t]
        ["Edit main kill file" gnus-summary-edit-global-kill t]
        ["Edit group parameters" gnus-summary-edit-parameters t]
+       ["Customize group parameters" gnus-summary-customize-parameters t]
+       ["Send a bug report" gnus-bug t]
        ("Exit"
-       ["Catchup and exit" gnus-summary-catchup-and-exit t]
-       ["Catchup all and exit" gnus-summary-catchup-and-exit t]
+       ["Catchup and exit" gnus-summary-catchup-and-exit
+        ,@(if (featurep 'xemacs) '(t)
+            '(:help "Mark unread articles in this group as read, then exit"))]
+       ["Catchup all and exit" gnus-summary-catchup-all-and-exit t]
        ["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
-       ["Exit group" gnus-summary-exit t]
+       ["Exit group" gnus-summary-exit
+        ,@(if (featurep 'xemacs) '(t)
+            '(:help "Exit current group, return to group selection mode"))]
        ["Exit group without updating" gnus-summary-exit-no-update t]
        ["Exit and goto next group" gnus-summary-next-group t]
        ["Exit and goto prev group" gnus-summary-prev-group t]
@@ -1840,6 +2490,50 @@ increase the score of each group you read."
 
     (gnus-run-hooks 'gnus-summary-menu-hook)))
 
+(defvar gnus-summary-tool-bar-map nil)
+
+;; Emacs 21 tool bar.  Should be no-op otherwise.
+(defun gnus-summary-make-tool-bar ()
+  (if (and (fboundp 'tool-bar-add-item-from-menu)
+          (default-value 'tool-bar-mode)
+          (not gnus-summary-tool-bar-map))
+      (setq gnus-summary-tool-bar-map
+           (let ((tool-bar-map (make-sparse-keymap))
+                 (load-path (mm-image-load-path)))
+             (tool-bar-add-item-from-menu
+              'gnus-summary-prev-unread "prev-ur" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-next-unread "next-ur" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-post-news "post" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-followup-with-original "fuwo" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-followup "followup" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-reply-with-original "reply-wo" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-reply "reply" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-caesar-message "rot13" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-uu-decode-uu "uu-decode" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-save-article-file "save-aif" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-save-article "save-art" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-uu-post-news "uu-post" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-catchup "catchup" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-catchup-and-exit "cu-exit" gnus-summary-mode-map)
+             (tool-bar-add-item-from-menu
+              'gnus-summary-exit "exit-summ" gnus-summary-mode-map)
+             tool-bar-map)))
+  (if gnus-summary-tool-bar-map
+      (set (make-local-variable 'tool-bar-map) gnus-summary-tool-bar-map)))
+
 (defun gnus-score-set-default (var value)
   "A version of set that updates the GNU Emacs menu-bar."
   (set var value)
@@ -1855,6 +2549,7 @@ increase the score of each group you read."
                     ("article body" "body" string)
                     ("article head" "head" string)
                     ("xref" "xref" string)
+                    ("extra header" "extra" string)
                     ("lines" "lines" number)
                     ("followups to author" "followup" string)))
          (types '((number ("less than" <)
@@ -1909,7 +2604,8 @@ increase the score of each group you read."
                                               (list 'gnus-summary-header
                                                     (nth 1 header)))
                                             (list 'quote (nth 1 (car ts)))
-                                            (list 'gnus-score-default nil)
+                                            (list 'gnus-score-delta-default
+                                                  nil)
                                             (nth 1 (car ps))
                                             t)
                                            t)
@@ -1936,7 +2632,7 @@ and backwards while displaying articles, type `\\[gnus-summary-next-unread-artic
 respectively.
 
 You can also post articles and send mail from this buffer.  To
-follow up an article, type `\\[gnus-summary-followup]'.         To mail a reply to the author
+follow up an article, type `\\[gnus-summary-followup]'.  To mail a reply to the author
 of an article, type `\\[gnus-summary-reply]'.
 
 There are approx. one gazillion commands you can execute in this
@@ -1946,17 +2642,20 @@ The following commands are available:
 
 \\{gnus-summary-mode-map}"
   (interactive)
-  (when (gnus-visual-p 'summary-menu 'menu)
-    (gnus-summary-make-menu-bar))
   (kill-all-local-variables)
+  (when (gnus-visual-p 'summary-menu 'menu)
+    (gnus-summary-make-menu-bar)
+    (gnus-summary-make-tool-bar))
   (gnus-summary-make-local-variables)
+  (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+    (gnus-summary-make-local-variables))
   (gnus-make-thread-indent-array)
   (gnus-simplify-mode-line)
   (setq major-mode 'gnus-summary-mode)
   (setq mode-name "Summary")
   (make-local-variable 'minor-mode-alist)
   (use-local-map gnus-summary-mode-map)
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (setq buffer-read-only t)            ;Disable modification
   (setq truncate-lines t)
   (setq selective-display t)
@@ -1964,24 +2663,25 @@ The following commands are available:
   (gnus-summary-set-display-table)
   (gnus-set-default-directory)
   (setq gnus-newsgroup-name group)
+  (unless (gnus-news-group-p group)
+    (setq gnus-newsgroup-incorporated
+         (nnmail-new-mail-numbers (gnus-group-real-name group))))
   (make-local-variable 'gnus-summary-line-format)
   (make-local-variable 'gnus-summary-line-format-spec)
   (make-local-variable 'gnus-summary-dummy-line-format)
   (make-local-variable 'gnus-summary-dummy-line-format-spec)
   (make-local-variable 'gnus-summary-mark-positions)
-  (make-local-hook 'post-command-hook)
-  (add-hook 'post-command-hook 'gnus-clear-inboxes-moved nil t)
-  (make-local-hook 'pre-command-hook)
+  (gnus-make-local-hook 'pre-command-hook)
   (add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
   (gnus-run-hooks 'gnus-summary-mode-hook)
+  (turn-on-gnus-mailing-list-mode)
   (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
   (gnus-update-summary-mark-positions))
 
 (defun gnus-summary-make-local-variables ()
   "Make all the local summary buffer variables."
-  (let ((locals gnus-summary-local-variables)
-       global local)
-    (while (setq local (pop locals))
+  (let (global)
+    (dolist (local gnus-summary-local-variables)
       (if (consp local)
          (progn
            (if (eq (cdr local) 'global)
@@ -1989,11 +2689,9 @@ The following commands are available:
                (setq global (symbol-value (car local)))
              ;; Use the value from the list.
              (setq global (eval (cdr local))))
-           (make-local-variable (car local))
-           (set (car local) global))
+           (set (make-local-variable (car local)) global))
        ;; Simple nil-valued local variable.
-       (make-local-variable local)
-       (set local nil)))))
+       (set (make-local-variable local) nil)))))
 
 (defun gnus-summary-clear-local-variables ()
   (let ((locals gnus-summary-local-variables))
@@ -2029,7 +2727,7 @@ The following commands are available:
   `(nth 3 ,data))
 
 (defmacro gnus-data-set-header (data header)
-  `(setf (nth 3 ,data) ,header))
+  `(setcar (nthcdr 3 ,data) ,header))
 
 (defmacro gnus-data-level (data)
   `(nth 4 ,data))
@@ -2067,21 +2765,26 @@ The following commands are available:
   (when list
     (let ((data (and after-article (gnus-data-find-list after-article)))
          (ilist list))
-      (or data (not after-article) (error "No such article: %d" after-article))
-      ;; Find the last element in the list to be spliced into the main
-      ;; list.
-      (while (cdr list)
-       (setq list (cdr list)))
-      (if (not data)
-         (progn
-           (setcdr list gnus-newsgroup-data)
-           (setq gnus-newsgroup-data ilist)
+      (if (not (or data
+                  after-article))
+         (let ((odata gnus-newsgroup-data))
+           (setq gnus-newsgroup-data (nconc list gnus-newsgroup-data))
            (when offset
-             (gnus-data-update-list (cdr list) offset)))
-       (setcdr list (cdr data))
-       (setcdr data ilist)
-       (when offset
-         (gnus-data-update-list (cdr list) offset)))
+             (gnus-data-update-list odata offset)))
+       ;; Find the last element in the list to be spliced into the main
+       ;; list.
+       (while (cdr list)
+         (setq list (cdr list)))
+       (if (not data)
+           (progn
+             (setcdr list gnus-newsgroup-data)
+             (setq gnus-newsgroup-data ilist)
+             (when offset
+               (gnus-data-update-list (cdr list) offset)))
+         (setcdr list (cdr data))
+         (setcdr data ilist)
+         (when offset
+           (gnus-data-update-list (cdr list) offset))))
       (setq gnus-newsgroup-data-reverse nil))))
 
 (defun gnus-data-remove (article &optional offset)
@@ -2110,21 +2813,11 @@ The following commands are available:
 
 (defun gnus-data-update-list (data offset)
   "Add OFFSET to the POS of all data entries in DATA."
+  (setq gnus-newsgroup-data-reverse nil)
   (while data
     (setcar (nthcdr 2 (car data)) (+ offset (nth 2 (car data))))
     (setq data (cdr data))))
 
-(defun gnus-data-compute-positions ()
-  "Compute the positions of all articles."
-  (let ((data gnus-newsgroup-data)
-       pos)
-    (while data
-      (when (setq pos (text-property-any
-                      (point-min) (point-max)
-                      'gnus-number (gnus-data-number (car data))))
-       (gnus-data-set-pos (car data) (+ pos 3)))
-      (setq data (cdr data)))))
-
 (defun gnus-summary-article-pseudo-p (article)
   "Say whether this article is a pseudo article or not."
   (not (vectorp (gnus-data-header (gnus-data-find article)))))
@@ -2168,6 +2861,7 @@ The following commands are available:
 (defun gnus-article-read-p (article)
   "Say whether ARTICLE is read or not."
   (not (or (memq article gnus-newsgroup-marked)
+          (memq article gnus-newsgroup-spam-marked)
           (memq article gnus-newsgroup-unreads)
           (memq article gnus-newsgroup-unselected)
           (memq article gnus-newsgroup-dormant))))
@@ -2176,7 +2870,7 @@ The following commands are available:
 
 (defmacro gnus-summary-article-number ()
   "The article number of the article on the current line.
-If there isn's an article number here, then we return the current
+If there isn't an article number here, then we return the current
 article number."
   '(progn
      (gnus-summary-skip-intangible)
@@ -2258,6 +2952,7 @@ article number."
 This is all marks except unread, ticked, dormant, and expirable."
   (not (or (= mark gnus-unread-mark)
           (= mark gnus-ticked-mark)
+          (= mark gnus-spam-mark)
           (= mark gnus-dormant-mark)
           (= mark gnus-expirable-mark))))
 
@@ -2269,10 +2964,10 @@ time; i.e., when generating the summary lines.  After that,
 marks of articles."
   `(cond
     ((memq ,number gnus-newsgroup-unsendable) gnus-unsendable-mark)
-    ((memq ,number gnus-newsgroup-undownloaded) gnus-undownloaded-mark)
     ((memq ,number gnus-newsgroup-downloadable) gnus-downloadable-mark)
     ((memq ,number gnus-newsgroup-unreads) gnus-unread-mark)
     ((memq ,number gnus-newsgroup-marked) gnus-ticked-mark)
+    ((memq ,number gnus-newsgroup-spam-marked) gnus-spam-mark)
     ((memq ,number gnus-newsgroup-dormant) gnus-dormant-mark)
     ((memq ,number gnus-newsgroup-expirable) gnus-expirable-mark)
     (t (or (cdr (assq ,number gnus-newsgroup-reads))
@@ -2280,9 +2975,6 @@ marks of articles."
 
 ;; Saving hidden threads.
 
-(put 'gnus-save-hidden-threads 'lisp-indent-function 0)
-(put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
-
 (defmacro gnus-save-hidden-threads (&rest forms)
   "Save hidden threads, eval FORMS, and restore the hidden threads."
   (let ((config (make-symbol "config")))
@@ -2291,6 +2983,23 @@ marks of articles."
           (save-excursion
             ,@forms)
         (gnus-restore-hidden-threads-configuration ,config)))))
+(put 'gnus-save-hidden-threads 'lisp-indent-function 0)
+(put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
+
+(defun gnus-data-compute-positions ()
+  "Compute the positions of all articles."
+  (setq gnus-newsgroup-data-reverse nil)
+  (let ((data gnus-newsgroup-data))
+    (save-excursion
+      (gnus-save-hidden-threads
+       (gnus-summary-show-all-threads)
+       (goto-char (point-min))
+       (while data
+         (while (get-text-property (point) 'gnus-intangible)
+           (forward-line 1))
+         (gnus-data-set-pos (car data) (+ (point) 3))
+         (setq data (cdr data))
+         (forward-line 1))))))
 
 (defun gnus-hidden-threads-configuration ()
   "Return the current hidden threads configuration."
@@ -2303,12 +3012,13 @@ marks of articles."
 
 (defun gnus-restore-hidden-threads-configuration (config)
   "Restore hidden threads configuration from CONFIG."
-  (let (point buffer-read-only)
-    (while (setq point (pop config))
-      (when (and (< point (point-max))
-                (goto-char point)
-                (= (following-char) ?\n))
-       (subst-char-in-region point (1+ point) ?\n ?\r)))))
+  (save-excursion
+    (let (point buffer-read-only)
+      (while (setq point (pop config))
+       (when (and (< point (point-max))
+                  (goto-char point)
+                  (eq (char-after) ?\n))
+         (subst-char-in-region point (1+ point) ?\n ?\r))))))
 
 ;; Various summary mode internalish functions.
 
@@ -2318,9 +3028,10 @@ marks of articles."
   (gnus-summary-next-page nil t))
 
 (defun gnus-summary-set-display-table ()
-  ;; Change the display table.  Odd characters have a tendency to mess
-  ;; up nicely formatted displays - we make all possible glyphs
-  ;; display only a single character.
+  "Change the display table.
+Odd characters have a tendency to mess
+up nicely formatted displays - we make all possible glyphs
+display only a single character."
 
   ;; We start from the standard display table, if any.
   (let ((table (or (copy-sequence standard-display-table)
@@ -2343,17 +3054,36 @@ marks of articles."
          (aset table i [??]))))
     (setq buffer-display-table table)))
 
+(defun gnus-summary-set-article-display-arrow (pos)
+  "Update the overlay arrow to point to line at position POS."
+  (when (and gnus-summary-display-arrow
+            (boundp 'overlay-arrow-position)
+            (boundp 'overlay-arrow-string))
+    (save-excursion
+      (goto-char pos)
+      (beginning-of-line)
+      (unless overlay-arrow-position
+       (setq overlay-arrow-position (make-marker)))
+      (setq overlay-arrow-string "=>"
+           overlay-arrow-position (set-marker overlay-arrow-position
+                                              (point)
+                                              (current-buffer))))))
+
 (defun gnus-summary-setup-buffer (group)
   "Initialize summary buffer."
-  (let ((buffer (concat "*Summary " group "*")))
+  (let ((buffer (gnus-summary-buffer-name group))
+       (dead-name (concat "*Dead Summary "
+                          (gnus-group-decoded-name group) "*")))
+    ;; If a dead summary buffer exists, we kill it.
+    (when (gnus-buffer-live-p dead-name)
+      (gnus-kill-buffer dead-name))
     (if (get-buffer buffer)
        (progn
          (set-buffer buffer)
          (setq gnus-summary-buffer (current-buffer))
          (not gnus-newsgroup-prepared))
       ;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
-      (setq gnus-summary-buffer (set-buffer (get-buffer-create buffer)))
-      (gnus-add-current-to-buffer-list)
+      (setq gnus-summary-buffer (set-buffer (gnus-get-buffer-create buffer)))
       (gnus-summary-mode group)
       (when gnus-carpal
        (gnus-carpal-setup-buffer 'summary))
@@ -2362,16 +3092,19 @@ marks of articles."
        (make-local-variable 'gnus-article-current)
        (make-local-variable 'gnus-original-article-buffer))
       (setq gnus-newsgroup-name group)
+      ;; Set any local variables in the group parameters.
+      (gnus-summary-set-local-parameters gnus-newsgroup-name)
       t)))
 
 (defun gnus-set-global-variables ()
-  ;; Set the global equivalents of the summary buffer-local variables
-  ;; to the latest values they had.  These reflect the summary buffer
-  ;; that was in action when the last article was fetched.
+  "Set the global equivalents of the buffer-local variables.
+They are set to the latest values they had.  These reflect the summary
+buffer that was in action when the last article was fetched."
   (when (eq major-mode 'gnus-summary-mode)
     (setq gnus-summary-buffer (current-buffer))
     (let ((name gnus-newsgroup-name)
          (marked gnus-newsgroup-marked)
+         (spam gnus-newsgroup-spam-marked)
          (unread gnus-newsgroup-unreads)
          (headers gnus-current-headers)
          (data gnus-newsgroup-data)
@@ -2380,11 +3113,21 @@ marks of articles."
          (original gnus-original-article-buffer)
          (gac gnus-article-current)
          (reffed gnus-reffed-article-number)
-         (score-file gnus-current-score-file))
+         (score-file gnus-current-score-file)
+         (default-charset gnus-newsgroup-charset)
+         vlist)
+      (let ((locals gnus-newsgroup-variables))
+       (while locals
+         (if (consp (car locals))
+             (push (eval (caar locals)) vlist)
+           (push (eval (car locals)) vlist))
+         (setq locals (cdr locals)))
+       (setq vlist (nreverse vlist)))
       (save-excursion
        (set-buffer gnus-group-buffer)
        (setq gnus-newsgroup-name name
              gnus-newsgroup-marked marked
+             gnus-newsgroup-spam-marked spam
              gnus-newsgroup-unreads unread
              gnus-current-headers headers
              gnus-newsgroup-data data
@@ -2393,7 +3136,14 @@ marks of articles."
              gnus-article-buffer article-buffer
              gnus-original-article-buffer original
              gnus-reffed-article-number reffed
-             gnus-current-score-file score-file)
+             gnus-current-score-file score-file
+             gnus-newsgroup-charset default-charset)
+       (let ((locals gnus-newsgroup-variables))
+         (while locals
+           (if (consp (car locals))
+               (set (caar locals) (pop vlist))
+             (set (car locals) (pop vlist)))
+           (setq locals (cdr locals))))
        ;; The article buffer also has local variables.
        (when (gnus-buffer-live-p gnus-article-buffer)
          (set-buffer gnus-article-buffer)
@@ -2412,7 +3162,8 @@ marks of articles."
 (defun gnus-summary-last-article-p (&optional article)
   "Return whether ARTICLE is the last article in the buffer."
   (if (not (setq article (or article (gnus-summary-article-number))))
-      t                ; All non-existent numbers are the last article.  :-)
+      ;; All non-existent numbers are the last article.  :-)
+      t
     (not (cdr (gnus-data-find-list article)))))
 
 (defun gnus-make-thread-indent-array ()
@@ -2429,35 +3180,38 @@ marks of articles."
 (defun gnus-update-summary-mark-positions ()
   "Compute where the summary marks are to go."
   (save-excursion
-    (when (and gnus-summary-buffer
-              (get-buffer gnus-summary-buffer)
-              (buffer-name (get-buffer gnus-summary-buffer)))
+    (when (gnus-buffer-exists-p gnus-summary-buffer)
       (set-buffer gnus-summary-buffer))
     (let ((gnus-replied-mark 129)
          (gnus-score-below-mark 130)
          (gnus-score-over-mark 130)
-         (gnus-download-mark 131)
+         (gnus-undownloaded-mark 131)
          (spec gnus-summary-line-format-spec)
-         thread gnus-visual pos)
+         gnus-visual pos)
       (save-excursion
        (gnus-set-work-buffer)
        (let ((gnus-summary-line-format-spec spec)
-             (gnus-newsgroup-downloadable '((0 . t))))
+             (gnus-newsgroup-downloadable '(0)))
          (gnus-summary-insert-line
-          [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
+          (make-full-mail-header 0 "" "nobody"
+                                 "05 Apr 2001 23:33:09 +0400"
+                                 "" "" 0 0 "" nil)
+          0 nil t 128 t nil "" nil 1)
          (goto-char (point-min))
          (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
-                                            (- (point) 2)))))
+                                            (- (point) (point-min) 1)))))
          (goto-char (point-min))
          (push (cons 'replied (and (search-forward "\201" nil t)
-                                   (- (point) 2)))
+                                   (- (point) (point-min) 1)))
                pos)
          (goto-char (point-min))
-         (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+         (push (cons 'score (and (search-forward "\202" nil t)
+                                 (- (point) (point-min) 1)))
                pos)
          (goto-char (point-min))
          (push (cons 'download
-                     (and (search-forward "\203" nil t) (- (point) 2)))
+                     (and (search-forward "\203" nil t)
+                          (- (point) (point-min) 1)))
                pos)))
       (setq gnus-summary-mark-positions pos))))
 
@@ -2468,9 +3222,34 @@ marks of articles."
    (point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
    (list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
 
+(defun gnus-summary-extract-address-component (from)
+  (or (car (funcall gnus-extract-address-components from))
+      from))
+
+(defun gnus-summary-from-or-to-or-newsgroups (header gnus-tmp-from)
+  (let ((default-mime-charset (with-current-buffer gnus-summary-buffer
+                               default-mime-charset)))
+    ;; Is it really necessary to do this next part for each summary line?
+    ;; Luckily, doesn't seem to slow things down much.
+    (or
+     (and gnus-ignored-from-addresses
+         (string-match gnus-ignored-from-addresses gnus-tmp-from)
+         (let ((extra-headers (mail-header-extra header))
+               to
+               newsgroups)
+           (cond
+            ((setq to (cdr (assq 'To extra-headers)))
+             (concat "-> "
+                     (inline
+                       (gnus-summary-extract-address-component
+                        (funcall gnus-decode-encoded-word-function to)))))
+            ((setq newsgroups (cdr (assq 'Newsgroups extra-headers)))
+             (concat "=> " newsgroups)))))
+     (inline (gnus-summary-extract-address-component gnus-tmp-from)))))
+
 (defun gnus-summary-insert-line (gnus-tmp-header
                                 gnus-tmp-level gnus-tmp-current
-                                gnus-tmp-unread gnus-tmp-replied
+                                undownloaded gnus-tmp-unread gnus-tmp-replied
                                 gnus-tmp-expirable gnus-tmp-subject-or-nil
                                 &optional gnus-tmp-dummy gnus-tmp-score
                                 gnus-tmp-process)
@@ -2481,40 +3260,55 @@ marks of articles."
          (if (or (null gnus-summary-default-score)
                  (<= (abs (- gnus-tmp-score gnus-summary-default-score))
                      gnus-summary-zcore-fuzz))
-             ? 
+             ?\ ;;;Whitespace
            (if (< gnus-tmp-score gnus-summary-default-score)
                gnus-score-below-mark gnus-score-over-mark)))
+        (gnus-tmp-number (mail-header-number gnus-tmp-header))
         (gnus-tmp-replied
          (cond (gnus-tmp-process gnus-process-mark)
                ((memq gnus-tmp-current gnus-newsgroup-cached)
                 gnus-cached-mark)
                (gnus-tmp-replied gnus-replied-mark)
+               ((memq gnus-tmp-current gnus-newsgroup-forwarded)
+                gnus-forwarded-mark)
                ((memq gnus-tmp-current gnus-newsgroup-saved)
                 gnus-saved-mark)
-               (t gnus-unread-mark)))
+               ((memq gnus-tmp-number gnus-newsgroup-recent)
+                gnus-recent-mark)
+               ((memq gnus-tmp-number gnus-newsgroup-unseen)
+                gnus-unseen-mark)
+               (t gnus-no-mark)))
+        (gnus-tmp-downloaded
+         (cond (undownloaded
+                 gnus-undownloaded-mark)
+                (gnus-newsgroup-agentized
+                 gnus-downloaded-mark)
+                (t
+                 gnus-no-mark)))
         (gnus-tmp-from (mail-header-from gnus-tmp-header))
         (gnus-tmp-name
          (cond
           ((string-match "<[^>]+> *$" gnus-tmp-from)
            (let ((beg (match-beginning 0)))
-             (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
-                      (substring gnus-tmp-from (1+ (match-beginning 0))
-                                 (1- (match-end 0))))
+             (or (and (string-match "^\".+\"" gnus-tmp-from)
+                      (substring gnus-tmp-from 1 (1- (match-end 0))))
                  (substring gnus-tmp-from 0 beg))))
           ((string-match "(.+)" gnus-tmp-from)
            (substring gnus-tmp-from
                       (1+ (match-beginning 0)) (1- (match-end 0))))
           (t gnus-tmp-from)))
         (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
-        (gnus-tmp-number (mail-header-number gnus-tmp-header))
         (gnus-tmp-opening-bracket (if gnus-tmp-dummy ?\< ?\[))
         (gnus-tmp-closing-bracket (if gnus-tmp-dummy ?\> ?\]))
         (buffer-read-only nil))
     (when (string= gnus-tmp-name "")
       (setq gnus-tmp-name gnus-tmp-from))
     (unless (numberp gnus-tmp-lines)
-      (setq gnus-tmp-lines 0))
-    (gnus-put-text-property
+      (setq gnus-tmp-lines -1))
+    (if (= gnus-tmp-lines -1)
+       (setq gnus-tmp-lines "?")
+      (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
+    (gnus-put-text-property-excluding-characters-with-faces
      (point)
      (progn (eval gnus-summary-line-format-spec) (point))
      'gnus-number gnus-tmp-number)
@@ -2524,7 +3318,7 @@ marks of articles."
       (forward-line 1))))
 
 (defun gnus-summary-update-line (&optional dont-update)
-  ;; Update summary line after change.
+  "Update summary line after change."
   (when (and gnus-summary-default-score
             (not gnus-summary-inhibit-highlight))
     (let* ((gnus-summary-inhibit-highlight t) ; Prevent recursion.
@@ -2546,7 +3340,7 @@ marks of articles."
         (if (or (null gnus-summary-default-score)
                 (<= (abs (- score gnus-summary-default-score))
                     gnus-summary-zcore-fuzz))
-            ? 
+            ?\ ;;;Whitespace
           (if (< score gnus-summary-default-score)
               gnus-score-below-mark gnus-score-over-mark))
         'score))
@@ -2584,9 +3378,22 @@ the thread are to be displayed."
          gnus-empty-thread-mark)
       number)))
 
+(defsubst gnus-summary-line-message-size (head)
+  "Return pretty-printed version of message size.
+This function is intended to be used in
+`gnus-summary-line-format-alist'."
+  (let ((c (or (mail-header-chars head) -1)))
+    (cond ((< c 0) "n/a")              ; chars not available
+         ((< c (* 1000 10)) (format "%1.1fk" (/ c 1024.0)))
+         ((< c (* 1000 100)) (format "%dk" (/ c 1024.0)))
+         ((< c (* 1000 10000)) (format "%1.1fM" (/ c (* 1024.0 1024))))
+         (t (format "%dM" (/ c (* 1024.0 1024)))))))
+
+
 (defun gnus-summary-set-local-parameters (group)
   "Go through the local params of GROUP and set all variable specs in that list."
   (let ((params (gnus-group-find-parameter group))
+       (vars '(quit-config))           ; Ignore quit-config.
        elem)
     (while params
       (setq elem (car params)
@@ -2594,14 +3401,15 @@ the thread are to be displayed."
       (and (consp elem)                        ; Has to be a cons.
           (consp (cdr elem))           ; The cdr has to be a list.
           (symbolp (car elem))         ; Has to be a symbol in there.
-          (not (memq (car elem)
-                     '(quit-config to-address to-list to-group)))
+          (not (memq (car elem) vars))
           (ignore-errors               ; So we set it.
+            (push (car elem) vars)
             (make-local-variable (car elem))
             (set (car elem) (eval (nth 1 elem))))))))
 
 (defun gnus-summary-read-group (group &optional show-all no-article
-                                     kill-buffer no-display)
+                                     kill-buffer no-display backward
+                                     select-articles)
   "Start reading news in newsgroup GROUP.
 If SHOW-ALL is non-nil, already read articles are also listed.
 If NO-ARTICLE is non-nil, no article is selected initially.
@@ -2612,25 +3420,55 @@ If NO-DISPLAY, don't generate a summary buffer."
                            (let ((gnus-auto-select-next nil))
                              (or (gnus-summary-read-group-1
                                   group show-all no-article
-                                  kill-buffer no-display)
-                                 (setq show-all nil)))))
+                                  kill-buffer no-display
+                                  select-articles)
+                                 (setq show-all nil
+                                       select-articles nil)))))
                (eq gnus-auto-select-next 'quietly))
       (set-buffer gnus-group-buffer)
+      ;; The entry function called above goes to the next
+      ;; group automatically, so we go two groups back
+      ;; if we are searching for the previous group.
+      (when backward
+       (gnus-group-prev-unread-group 2))
       (if (not (equal group (gnus-group-group-name)))
          (setq group (gnus-group-group-name))
        (setq group nil)))
     result))
 
+(defun gnus-summary-jump-to-other-group (group &optional show-all)
+  "Directly jump to the other GROUP from summary buffer.
+If SHOW-ALL is non-nil, already read articles are also listed."
+  (interactive
+   (if (eq gnus-summary-buffer (current-buffer))
+       (list (completing-read
+             "Group: " gnus-active-hashtb nil t
+             (when (and gnus-newsgroup-name
+                        (string-match "[.:][^.:]+$" gnus-newsgroup-name))
+               (substring gnus-newsgroup-name 0 (1+ (match-beginning 0))))
+             'gnus-group-history)
+            current-prefix-arg)
+     (error "%s must be invoked from a gnus summary buffer." this-command)))
+  (unless (or (zerop (length group))
+             (and gnus-newsgroup-name
+                  (string-equal gnus-newsgroup-name group)))
+    (gnus-summary-exit)
+    (gnus-summary-read-group group show-all
+                            gnus-dont-select-after-jump-to-other-group)))
+
 (defun gnus-summary-read-group-1 (group show-all no-article
-                                       kill-buffer no-display)
+                                       kill-buffer no-display
+                                       &optional select-articles)
   ;; Killed foreign groups can't be entered.
-  (when (and (not (gnus-group-native-p group))
-            (not (gnus-gethash group gnus-newsrc-hashtb)))
-    (error "Dead non-native groups can't be entered"))
-  (gnus-message 5 "Retrieving newsgroup: %s..." group)
+  ;;  (when (and (not (gnus-group-native-p group))
+  ;;        (not (gnus-gethash group gnus-newsrc-hashtb)))
+  ;;    (error "Dead non-native groups can't be entered"))
+  (gnus-message 5 "Retrieving newsgroup: %s..."
+               (gnus-group-decoded-name group))
   (let* ((new-group (gnus-summary-setup-buffer group))
         (quit-config (gnus-group-quit-config group))
-        (did-select (and new-group (gnus-select-newsgroup group show-all))))
+        (did-select (and new-group (gnus-select-newsgroup
+                                    group show-all select-articles))))
     (cond
      ;; This summary buffer exists already, so we just select it.
      ((not new-group)
@@ -2656,7 +3494,11 @@ If NO-DISPLAY, don't generate a summary buffer."
              (gnus-group-jump-to-group group)
              (gnus-group-next-unread-group 1))
          (gnus-handle-ephemeral-exit quit-config)))
-      (gnus-message 3 "Can't select group")
+      (let ((grpinfo (gnus-get-info group)))
+       (if (null (gnus-info-read grpinfo))
+           (gnus-message 3 "Group %s contains no messages"
+                         (gnus-group-decoded-name group))
+         (gnus-message 3 "Can't select group")))
       nil)
      ;; The user did a `C-g' while prompting for number of articles,
      ;; so we exit this group.
@@ -2684,10 +3526,9 @@ If NO-DISPLAY, don't generate a summary buffer."
             (gnus-active gnus-newsgroup-name)))
       ;; You can change the summary buffer in some way with this hook.
       (gnus-run-hooks 'gnus-select-group-hook)
-      ;; Set any local variables in the group parameters.
-      (gnus-summary-set-local-parameters gnus-newsgroup-name)
       (gnus-update-format-specifications
        nil 'summary 'summary-mode 'summary-dummy)
+      (gnus-update-summary-mark-positions)
       ;; Do score processing.
       (when gnus-use-scoring
        (gnus-possibly-score-headers))
@@ -2700,6 +3541,7 @@ If NO-DISPLAY, don't generate a summary buffer."
              (let ((gnus-newsgroup-dormant nil))
                (gnus-summary-initial-limit show-all))
            (gnus-summary-initial-limit show-all))
+       ;; When unthreaded, all articles are always shown.
        (setq gnus-newsgroup-limit
              (mapcar
               (lambda (header) (mail-header-number header))
@@ -2735,27 +3577,28 @@ If NO-DISPLAY, don't generate a summary buffer."
        ;; Hide conversation thread subtrees.  We cannot do this in
        ;; gnus-summary-prepare-hook since kill processing may not
        ;; work with hidden articles.
-       (and gnus-show-threads
-            gnus-thread-hide-subtree
-            (gnus-summary-hide-all-threads))
+       (gnus-summary-maybe-hide-threads)
        (when kill-buffer
          (gnus-kill-or-deaden-summary kill-buffer))
+       (gnus-summary-auto-select-subject)
        ;; Show first unread article if requested.
        (if (and (not no-article)
                 (not no-display)
                 gnus-newsgroup-unreads
                 gnus-auto-select-first)
-           (unless (if (eq gnus-auto-select-first 'best)
-                       (gnus-summary-best-unread-article)
-                     (gnus-summary-first-unread-article))
-             (gnus-configure-windows 'summary))
-         ;; Don't select any articles, just move point to the first
-         ;; article in the group.
-         (goto-char (point-min))
+           (progn
+             (gnus-configure-windows 'summary)
+             (let ((art (gnus-summary-article-number)))
+               (unless (and (not gnus-plugged)
+                            (or (memq art gnus-newsgroup-undownloaded)
+                                (memq art gnus-newsgroup-downloadable)))
+                 (gnus-summary-goto-article art))))
+         ;; Don't select any articles.
          (gnus-summary-position-point)
          (gnus-configure-windows 'summary 'force)
-         (gnus-set-mode-line 'summary))        
-       (when (get-buffer-window gnus-group-buffer t)
+         (gnus-set-mode-line 'summary))
+       (when (and gnus-auto-center-group
+                  (get-buffer-window gnus-group-buffer t))
          ;; Gotta use windows, because recenter does weird stuff if
          ;; the current buffer ain't the displayed window.
          (let ((owin (selected-window)))
@@ -2766,8 +3609,28 @@ If NO-DISPLAY, don't generate a summary buffer."
        ;; Mark this buffer as "prepared".
        (setq gnus-newsgroup-prepared t)
        (gnus-run-hooks 'gnus-summary-prepared-hook)
+       (unless (gnus-ephemeral-group-p group)
+         (gnus-group-update-group group))
        t)))))
 
+(defun gnus-summary-auto-select-subject ()
+  "Select the subject line on initial group entry."
+  (goto-char (point-min))
+  (cond
+   ((eq gnus-auto-select-subject 'best)
+    (gnus-summary-best-unread-subject))
+   ((eq gnus-auto-select-subject 'unread)
+    (gnus-summary-first-unread-subject))
+   ((eq gnus-auto-select-subject 'unseen)
+    (gnus-summary-first-unseen-subject))
+   ((eq gnus-auto-select-subject 'unseen-or-unread)
+    (gnus-summary-first-unseen-or-unread-subject))
+   ((eq gnus-auto-select-subject 'first)
+    ;; Do nothing.
+    )
+   ((functionp gnus-auto-select-subject)
+    (funcall gnus-auto-select-subject))))
+
 (defun gnus-summary-prepare ()
   "Generate the summary buffer."
   (interactive)
@@ -2792,7 +3655,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (gnus-run-hooks 'gnus-summary-prepare-hook)))
 
 (defsubst gnus-general-simplify-subject (subject)
-  "Simply subject by the same rules as gnus-gather-threads-by-subject."
+  "Simplify subject by the same rules as `gnus-gather-threads-by-subject'."
   (setq subject
        (cond
         ;; Truncate the subject.
@@ -2819,7 +3682,8 @@ If NO-DISPLAY, don't generate a summary buffer."
   "Query where the respool algorithm would put this article."
   (interactive)
   (gnus-summary-select-article)
-  (message (gnus-general-simplify-subject (gnus-summary-article-subject))))
+  (message "%s"
+          (gnus-general-simplify-subject (gnus-summary-article-subject))))
 
 (defun gnus-gather-threads-by-subject (threads)
   "Gather threads by looking at Subject headers."
@@ -2848,7 +3712,16 @@ If NO-DISPLAY, don't generate a summary buffer."
                (setcdr prev (cdr threads))
                (setq threads prev))
            ;; Enter this thread into the hash table.
-           (gnus-sethash subject threads hashtb)))
+           (gnus-sethash subject
+                         (if gnus-summary-make-false-root-always
+                             (progn
+                               ;; If you want a dummy root above all
+                               ;; threads...
+                               (setcar threads (list whole-subject
+                                                     (car threads)))
+                               threads)
+                           threads)
+                         hashtb)))
        (setq prev threads)
        (setq threads (cdr threads)))
       result)))
@@ -2863,7 +3736,7 @@ If NO-DISPLAY, don't generate a summary buffer."
     (while threads
       (when (setq references (mail-header-references (caar threads)))
        (setq id (mail-header-id (caar threads))
-             ids (gnus-split-references references)
+             ids (inline (gnus-split-references references))
              entered nil)
        (while (setq ref (pop ids))
          (setq ids (delete ref ids))
@@ -2893,12 +3766,12 @@ If NO-DISPLAY, don't generate a summary buffer."
     result))
 
 (defun gnus-sort-gathered-threads (threads)
-  "Sort subtreads inside each gathered thread by article number."
+  "Sort subtreads inside each gathered thread by `gnus-sort-gathered-threads-function'."
   (let ((result threads))
     (while threads
       (when (stringp (caar threads))
        (setcdr (car threads)
-               (sort (cdar threads) 'gnus-thread-sort-by-number)))
+               (sort (cdar threads) gnus-sort-gathered-threads-function)))
       (setq threads (cdr threads)))
     result))
 
@@ -2953,11 +3826,97 @@ If NO-DISPLAY, don't generate a summary buffer."
              gnus-newsgroup-dependencies)))
     threads))
 
+;; Build the thread tree.
+(defsubst gnus-dependencies-add-header (header dependencies force-new)
+  "Enter HEADER into the DEPENDENCIES table if it is not already there.
+
+If FORCE-NEW is not nil, enter HEADER into the DEPENDENCIES table even
+if it was already present.
+
+If `gnus-summary-ignore-duplicates' is nil then duplicate Message-IDs
+will not be entered in the DEPENDENCIES table.  Otherwise duplicate
+Message-IDs will be renamed to a unique Message-ID before being
+entered.
+
+Returns HEADER if it was entered in the DEPENDENCIES.  Returns nil otherwise."
+  (let* ((id (mail-header-id header))
+        (id-dep (and id (intern id dependencies)))
+        parent-id ref ref-dep ref-header replaced)
+    ;; Enter this `header' in the `dependencies' table.
+    (cond
+     ((not id-dep)
+      (setq header nil))
+     ;; The first two cases do the normal part: enter a new `header'
+     ;; in the `dependencies' table.
+     ((not (boundp id-dep))
+      (set id-dep (list header)))
+     ((null (car (symbol-value id-dep)))
+      (setcar (symbol-value id-dep) header))
+
+     ;; From here the `header' was already present in the
+     ;; `dependencies' table.
+     (force-new
+      ;; Overrides an existing entry;
+      ;; just set the header part of the entry.
+      (setcar (symbol-value id-dep) header)
+      (setq replaced t))
+
+     ;; Renames the existing `header' to a unique Message-ID.
+     ((not gnus-summary-ignore-duplicates)
+      ;; An article with this Message-ID has already been seen.
+      ;; We rename the Message-ID.
+      (set (setq id-dep (intern (setq id (nnmail-message-id)) dependencies))
+          (list header))
+      (mail-header-set-id header id))
+
+     ;; The last case ignores an existing entry, except it adds any
+     ;; additional Xrefs (in case the two articles came from different
+     ;; servers.
+     ;; Also sets `header' to `nil' meaning that the `dependencies'
+     ;; table was *not* modified.
+     (t
+      (mail-header-set-xref
+       (car (symbol-value id-dep))
+       (concat (or (mail-header-xref (car (symbol-value id-dep)))
+                  "")
+              (or (mail-header-xref header) "")))
+      (setq header nil)))
+
+    (when (and header (not replaced))
+      ;; First check that we are not creating a References loop.
+      (setq parent-id (gnus-parent-id (mail-header-references header)))
+      (setq ref parent-id)
+      (while (and ref
+                 (setq ref-dep (intern-soft ref dependencies))
+                 (boundp ref-dep)
+                 (setq ref-header (car (symbol-value ref-dep))))
+       (if (string= id ref)
+           ;; Yuk!  This is a reference loop.  Make the article be a
+           ;; root article.
+           (progn
+             (mail-header-set-references (car (symbol-value id-dep)) "none")
+             (setq ref nil)
+             (setq parent-id nil))
+         (setq ref (gnus-parent-id (mail-header-references ref-header)))))
+      (setq ref-dep (intern (or parent-id "none") dependencies))
+      (if (boundp ref-dep)
+         (setcdr (symbol-value ref-dep)
+                 (nconc (cdr (symbol-value ref-dep))
+                        (list (symbol-value id-dep))))
+       (set ref-dep (list nil (symbol-value id-dep)))))
+    header))
+
+(defun gnus-extract-message-id-from-in-reply-to (string)
+  (if (string-match "<[^>]+>" string)
+      (substring string (match-beginning 0) (match-end 0))
+    nil))
+
 (defun gnus-build-sparse-threads ()
   (let ((headers gnus-newsgroup-headers)
-       (deps gnus-newsgroup-dependencies)
+       (mail-parse-charset gnus-newsgroup-charset)
+       (gnus-summary-ignore-duplicates t)
        header references generation relations
-       cthread subject child end pthread relation new-child)
+       subject child end new-child date)
     ;; First we create an alist of generations/relations, where
     ;; generations is how much we trust the relation, and the relation
     ;; is parent/child.
@@ -2969,47 +3928,37 @@ If NO-DISPLAY, don't generate a summary buffer."
                   (not (string= references "")))
          (insert references)
          (setq child (mail-header-id header)
-               subject (mail-header-subject header))
-         (setq generation 0)
+               subject (mail-header-subject header)
+               date (mail-header-date header)
+               generation 0)
          (while (search-backward ">" nil t)
            (setq end (1+ (point)))
            (when (search-backward "<" nil t)
-             (unless (string= (setq new-child (buffer-substring (point) end))
-                              child)
-               (push (list (incf generation)
-                           child (setq child new-child)
-                           subject)
-                     relations))))
-         (push (list (1+ generation) child nil subject) relations)
+             (setq new-child (buffer-substring (point) end))
+             (push (list (incf generation)
+                         child (setq child new-child)
+                         subject date)
+                   relations)))
+         (when child
+           (push (list (1+ generation) child nil subject) relations))
          (erase-buffer)))
       (kill-buffer (current-buffer)))
     ;; Sort over trustworthiness.
-    (setq relations (sort relations 'car-less-than-car))
-    (while (setq relation (pop relations))
-      (when (if (boundp (setq cthread (intern (cadr relation) deps)))
-               (unless (car (symbol-value cthread))
-                 ;; Make this article the parent of these threads.
-                 (setcar (symbol-value cthread)
-                         (vector gnus-reffed-article-number
-                                 (cadddr relation)
-                                 "" ""
-                                 (cadr relation)
-                                 (or (caddr relation) "") 0 0 "")))
-             (set cthread (list (vector gnus-reffed-article-number
-                                        (cadddr relation)
-                                        "" "" (cadr relation)
-                                        (or (caddr relation) "") 0 0 ""))))
-       (push gnus-reffed-article-number gnus-newsgroup-limit)
-       (push gnus-reffed-article-number gnus-newsgroup-sparse)
-       (push (cons gnus-reffed-article-number gnus-sparse-mark)
-             gnus-newsgroup-reads)
-       (decf gnus-reffed-article-number)
-       ;; Make this new thread the child of its parent.
-       (if (boundp (setq pthread (intern (or (caddr relation) "none") deps)))
-           (setcdr (symbol-value pthread)
-                   (nconc (cdr (symbol-value pthread))
-                          (list (symbol-value cthread))))
-         (set pthread (list nil (symbol-value cthread))))))
+    (mapcar
+     (lambda (relation)
+       (when (gnus-dependencies-add-header
+             (make-full-mail-header-from-decoded-header
+              gnus-reffed-article-number
+              (nth 3 relation) "" (or (nth 4 relation) "")
+              (nth 1 relation)
+              (or (nth 2 relation) "") 0 0 "")
+             gnus-newsgroup-dependencies nil)
+        (push gnus-reffed-article-number gnus-newsgroup-limit)
+        (push gnus-reffed-article-number gnus-newsgroup-sparse)
+        (push (cons gnus-reffed-article-number gnus-sparse-mark)
+              gnus-newsgroup-reads)
+        (decf gnus-reffed-article-number)))
+     (sort relations 'car-less-than-car))
     (gnus-message 7 "Making sparse threads...done")))
 
 (defun gnus-build-old-threads ()
@@ -3017,7 +3966,8 @@ If NO-DISPLAY, don't generate a summary buffer."
   ;; fetch the headers for the articles that aren't there.  This will
   ;; build complete threads - if the roots haven't been expired by the
   ;; server, that is.
-  (let (id heads)
+  (let ((mail-parse-charset gnus-newsgroup-charset)
+       id heads)
     (mapatoms
      (lambda (refs)
        (when (not (car (symbol-value refs)))
@@ -3028,15 +3978,63 @@ If NO-DISPLAY, don't generate a summary buffer."
               (setq heads (cdr heads))
             (setq id (symbol-name refs))
             (while (and (setq id (gnus-build-get-header id))
-                        (not (car (gnus-gethash
-                                   id gnus-newsgroup-dependencies)))))
+                        (not (car (gnus-id-to-thread id)))))
             (setq heads nil)))))
      gnus-newsgroup-dependencies)))
 
+(defsubst gnus-remove-odd-characters (string)
+  "Translate STRING into something that doesn't contain weird characters."
+  (mm-subst-char-in-string
+   ?\r ?\-
+   (mm-subst-char-in-string
+    ?\n ?\- string)))
+
+;; This function has to be called with point after the article number
+;; on the beginning of the line.
+(defsubst gnus-nov-parse-line (number dependencies &optional force-new)
+  (let ((eol (gnus-point-at-eol))
+       (buffer (current-buffer))
+       header references in-reply-to)
+
+    ;; overview: [num subject from date id refs chars lines misc]
+    (unwind-protect
+       (progn
+         (narrow-to-region (point) eol)
+         (unless (eobp)
+           (forward-char))
+
+         (setq header
+               (make-full-mail-header
+                number                         ; number
+                (nnheader-nov-field)           ; subject
+                (nnheader-nov-field)           ; from
+                (nnheader-nov-field)           ; date
+                (nnheader-nov-read-message-id) ; id
+                (nnheader-nov-field)           ; refs
+                (nnheader-nov-read-integer)    ; chars
+                (nnheader-nov-read-integer)    ; lines
+                (unless (eobp)
+                  (if (looking-at "Xref: ")
+                      (goto-char (match-end 0)))
+                  (nnheader-nov-field))        ; Xref
+                (nnheader-nov-parse-extra))))  ; extra
+
+      (widen))
+
+    (when (and (string= references "")
+              (setq in-reply-to (mail-header-extra header))
+              (setq in-reply-to (cdr (assq 'In-Reply-To in-reply-to))))
+      (mail-header-set-references
+       header (gnus-extract-message-id-from-in-reply-to in-reply-to)))
+
+    (when gnus-alter-header-function
+      (funcall gnus-alter-header-function header))
+    (gnus-dependencies-add-header header dependencies force-new)))
+
 (defun gnus-build-get-header (id)
-  ;; Look through the buffer of NOV lines and find the header to
-  ;; ID.  Enter this line into the dependencies hash table, and return
-  ;; the id of the parent article (if any).
+  "Look through the buffer of NOV lines and find the header to ID.
+Enter this line into the dependencies hash table, and return
+the id of the parent article (if any)."
   (let ((deps gnus-newsgroup-dependencies)
        found header)
     (prog1
@@ -3063,37 +4061,44 @@ If NO-DISPLAY, don't generate a summary buffer."
          (push header gnus-newsgroup-headers)
          (if (memq number gnus-newsgroup-unselected)
              (progn
-               (push number gnus-newsgroup-unreads)
+               (setq gnus-newsgroup-unreads
+                     (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                              number))
                (setq gnus-newsgroup-unselected
                      (delq number gnus-newsgroup-unselected)))
            (push number gnus-newsgroup-ancient)))))))
 
 (defun gnus-build-all-threads ()
   "Read all the headers."
-  (let ((deps gnus-newsgroup-dependencies)
-       (gnus-summary-ignore-duplicates t)
-       found header article)
+  (let ((gnus-summary-ignore-duplicates t)
+       (mail-parse-charset gnus-newsgroup-charset)
+       (dependencies gnus-newsgroup-dependencies)
+       header article)
     (save-excursion
       (set-buffer nntp-server-buffer)
       (let ((case-fold-search nil))
        (goto-char (point-min))
        (while (not (eobp))
          (ignore-errors
-           (setq article (read (current-buffer)))
-           (setq header (gnus-nov-parse-line article deps)))
+           (setq article (read (current-buffer))
+                 header (gnus-nov-parse-line article dependencies)))
          (when header
-           (push header gnus-newsgroup-headers)
-           (if (memq (setq article (mail-header-number header))
-                     gnus-newsgroup-unselected)
-               (progn
-                 (push article gnus-newsgroup-unreads)
-                 (setq gnus-newsgroup-unselected
-                       (delq article gnus-newsgroup-unselected)))
-             (push article gnus-newsgroup-ancient))
+           (save-excursion
+             (set-buffer gnus-summary-buffer)
+             (push header gnus-newsgroup-headers)
+             (if (memq (setq article (mail-header-number header))
+                       gnus-newsgroup-unselected)
+                 (progn
+                   (setq gnus-newsgroup-unreads
+                         (gnus-add-to-sorted-list
+                          gnus-newsgroup-unreads article))
+                   (setq gnus-newsgroup-unselected
+                         (delq article gnus-newsgroup-unselected)))
+               (push article gnus-newsgroup-ancient)))
            (forward-line 1)))))))
 
 (defun gnus-summary-update-article-line (article header)
-  "Update the line for ARTICLE using HEADERS."
+  "Update the line for ARTICLE using HEADER."
   (let* ((id (mail-header-id header))
         (thread (gnus-id-to-thread id)))
     (unless thread
@@ -3103,41 +4108,46 @@ If NO-DISPLAY, don't generate a summary buffer."
     (gnus-summary-goto-subject article)
     (let* ((datal (gnus-data-find-list article))
           (data (car datal))
-          (length (when (cdr datal)
-                    (- (gnus-data-pos data)
-                       (gnus-data-pos (cadr datal)))))
           (buffer-read-only nil)
           (level (gnus-summary-thread-level)))
       (gnus-delete-line)
-      (gnus-summary-insert-line
-       header level nil (gnus-article-mark article)
-       (memq article gnus-newsgroup-replied)
-       (memq article gnus-newsgroup-expirable)
-       ;; Only insert the Subject string when it's different
-       ;; from the previous Subject string.
-       (if (gnus-subject-equal
-           (condition-case ()
-               (mail-header-subject
-                (gnus-data-header
-                 (cadr
-                  (gnus-data-find-list
-                   article
-                   (gnus-data-list t)))))
-             ;; Error on the side of excessive subjects.
-             (error ""))
-           (mail-header-subject header))
-          ""
-        (mail-header-subject header))
-       nil (cdr (assq article gnus-newsgroup-scored))
-       (memq article gnus-newsgroup-processable))
-      (when length
-       (gnus-data-update-list
-        (cdr datal) (- length (- (gnus-data-pos data) (point))))))))
+      (let ((inserted (- (point)
+                         (progn
+                           (gnus-summary-insert-line
+                            header level nil
+                            (memq article gnus-newsgroup-undownloaded)
+                            (gnus-article-mark article)
+                            (memq article gnus-newsgroup-replied)
+                            (memq article gnus-newsgroup-expirable)
+                            ;; Only insert the Subject string when it's different
+                            ;; from the previous Subject string.
+                            (if (and
+                                 gnus-show-threads
+                                 (gnus-subject-equal
+                                  (condition-case ()
+                                      (mail-header-subject
+                                       (gnus-data-header
+                                        (cadr
+                                         (gnus-data-find-list
+                                          article
+                                          (gnus-data-list t)))))
+                                    ;; Error on the side of excessive subjects.
+                                    (error ""))
+                                  (mail-header-subject header)))
+                                ""
+                              (mail-header-subject header))
+                            nil (cdr (assq article gnus-newsgroup-scored))
+                            (memq article gnus-newsgroup-processable))
+                           (point)))))
+        (when (cdr datal)
+          (gnus-data-update-list
+           (cdr datal)
+           (- (gnus-data-pos data) (gnus-data-pos (cadr datal)) inserted)))))))
 
 (defun gnus-summary-update-article (article &optional iheader)
   "Update ARTICLE in the summary buffer."
   (set-buffer gnus-summary-buffer)
-  (let* ((header (or iheader (gnus-summary-article-header article)))
+  (let* ((header (gnus-summary-article-header article))
         (id (mail-header-id header))
         (data (gnus-data-find article))
         (thread (gnus-id-to-thread id))
@@ -3150,23 +4160,21 @@ If NO-DISPLAY, don't generate a summary buffer."
                  references))
               "none")))
         (buffer-read-only nil)
-        (old (car thread))
-        (number (mail-header-number header))
-        pos)
+        (old (car thread)))
     (when thread
-      ;; !!! Should this be in or not?
       (unless iheader
-       (setcar thread nil))
-      (when parent
-       (delq thread parent))
-      (if (gnus-summary-insert-subject id header iheader)
+       (setcar thread nil)
+       (when parent
+         (delq thread parent)))
+      (if (gnus-summary-insert-subject id header)
          ;; Set the (possibly) new article number in the data structure.
          (gnus-data-set-number data (gnus-id-to-article id))
        (setcar thread old)
        nil))))
 
-(defun gnus-rebuild-thread (id)
-  "Rebuild the thread containing ID."
+(defun gnus-rebuild-thread (id &optional line)
+  "Rebuild the thread containing ID.
+If LINE, insert the rebuilt thread starting on line LINE."
   (let ((buffer-read-only nil)
        old-pos current thread data)
     (if (not gnus-show-threads)
@@ -3175,7 +4183,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (setq thread (gnus-remove-thread id)))
     (setq old-pos (gnus-point-at-bol))
     (setq current (save-excursion
-                   (and (zerop (forward-line -1))
+                   (and (re-search-backward "[\r\n]" nil t)
                         (gnus-summary-article-number))))
     ;; If this is a gathered thread, we have to go some re-gathering.
     (when (stringp (car thread))
@@ -3196,6 +4204,9 @@ If NO-DISPLAY, don't generate a summary buffer."
          (setq thread (cons subject (gnus-sort-threads roots))))))
     (let (threads)
       ;; We then insert this thread into the summary buffer.
+      (when line
+       (goto-char (point-min))
+       (forward-line (1- line)))
       (let (gnus-newsgroup-data gnus-newsgroup-threads)
        (if gnus-show-threads
            (gnus-summary-prepare-threads (gnus-cut-threads (list thread)))
@@ -3203,8 +4214,15 @@ If NO-DISPLAY, don't generate a summary buffer."
        (setq data (nreverse gnus-newsgroup-data))
        (setq threads gnus-newsgroup-threads))
       ;; We splice the new data into the data structure.
-      (gnus-data-enter-list current data (- (point) old-pos))
-      (setq gnus-newsgroup-threads (nconc threads gnus-newsgroup-threads)))))
+      ;;!!! This is kinda bogus.  We assume that in LINE is non-nil,
+      ;;!!! then we want to insert at the beginning of the buffer.
+      ;;!!! That happens to be true with Gnus now, but that may
+      ;;!!! change in the future.  Perhaps.
+      (gnus-data-enter-list
+       (if line nil current) data (- (point) old-pos))
+      (setq gnus-newsgroup-threads
+           (nconc threads gnus-newsgroup-threads))
+      (gnus-data-compute-positions))))
 
 (defun gnus-number-to-header (number)
   "Return the header for article NUMBER."
@@ -3215,19 +4233,23 @@ If NO-DISPLAY, don't generate a summary buffer."
     (when headers
       (car headers))))
 
-(defun gnus-parent-headers (headers &optional generation)
+(defun gnus-parent-headers (in-headers &optional generation)
   "Return the headers of the GENERATIONeth parent of HEADERS."
   (unless generation
     (setq generation 1))
   (let ((parent t)
+       (headers in-headers)
        references)
-    (while (and parent headers (not (zerop generation)))
-      (setq references (mail-header-references headers))
-      (when (and references
-                (setq parent (gnus-parent-id references))
-                (setq headers (car (gnus-id-to-thread parent))))
-       (decf generation)))
-    headers))
+    (while (and parent
+               (not (zerop generation))
+               (setq references (mail-header-references headers)))
+      (setq headers (if (and references
+                            (setq parent (gnus-parent-id references)))
+                       (car (gnus-id-to-thread parent))
+                     nil))
+      (decf generation))
+    (and (not (eq headers in-headers))
+        headers)))
 
 (defun gnus-id-to-thread (id)
   "Return the (sub-)thread where ID appears."
@@ -3262,8 +4284,7 @@ If NO-DISPLAY, don't generate a summary buffer."
 (defun gnus-root-id (id)
   "Return the id of the root of the thread where ID appears."
   (let (last-id prev)
-    (while (and id (setq prev (car (gnus-gethash
-                                   id gnus-newsgroup-dependencies))))
+    (while (and id (setq prev (car (gnus-id-to-thread id))))
       (setq last-id id
            id (gnus-parent-id (mail-header-references prev))))
     last-id))
@@ -3275,12 +4296,10 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defun gnus-remove-thread (id &optional dont-remove)
   "Remove the thread that has ID in it."
-  (let ((dep gnus-newsgroup-dependencies)
-       headers thread last-id)
+  (let (headers thread last-id)
     ;; First go up in this thread until we find the root.
-    (setq last-id (gnus-root-id id))
-    (setq headers (list (car (gnus-id-to-thread last-id))
-                       (caadr (gnus-id-to-thread last-id))))
+    (setq last-id (gnus-root-id id)
+         headers (message-flatten-list (gnus-id-to-thread last-id)))
     ;; We have now found the real root of this thread. It might have
     ;; been gathered into some loose thread, so we have to search
     ;; through the threads to find the thread we wanted.
@@ -3309,7 +4328,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (if thread
          (unless dont-remove
            (setq gnus-newsgroup-threads (delq thread gnus-newsgroup-threads)))
-       (setq thread (gnus-gethash last-id dep)))
+       (setq thread (gnus-id-to-thread last-id)))
       (when thread
        (prog1
            thread                      ; We return this thread.
@@ -3319,6 +4338,11 @@ If NO-DISPLAY, don't generate a summary buffer."
                  ;; If we use dummy roots, then we have to remove the
                  ;; dummy root as well.
                  (when (eq gnus-summary-make-false-root 'dummy)
+                   ;; We go to the dummy root by going to
+                   ;; the first sub-"thread", and then one line up.
+                   (gnus-summary-goto-article
+                    (mail-header-number (caadr thread)))
+                   (forward-line -1)
                    (gnus-delete-line)
                    (gnus-data-compute-positions))
                  (setq thread (cdr thread))
@@ -3336,6 +4360,7 @@ If NO-DISPLAY, don't generate a summary buffer."
       (gnus-remove-thread-1 (pop thread)))
     (when (setq d (gnus-data-find number))
       (goto-char (gnus-data-pos d))
+      (gnus-summary-show-thread)
       (gnus-data-remove
        number
        (- (gnus-point-at-bol)
@@ -3343,14 +4368,23 @@ If NO-DISPLAY, don't generate a summary buffer."
              (1+ (gnus-point-at-eol))
            (gnus-delete-line)))))))
 
+(defun gnus-sort-threads-1 (threads func)
+  (sort (mapcar (lambda (thread)
+                 (cons (car thread)
+                       (and (cdr thread)
+                            (gnus-sort-threads-1 (cdr thread) func))))
+               threads) func))
+
 (defun gnus-sort-threads (threads)
   "Sort THREADS."
   (if (not gnus-thread-sort-functions)
       threads
-    (gnus-message 7 "Sorting threads...")
-    (prog1
-       (sort threads (gnus-make-sort-function gnus-thread-sort-functions))
-      (gnus-message 7 "Sorting threads...done"))))
+    (gnus-message 8 "Sorting threads...")
+    (let ((max-lisp-eval-depth 5000))
+      (prog1 (gnus-sort-threads-1
+        threads
+        (gnus-make-sort-function gnus-thread-sort-functions))
+        (gnus-message 8 "Sorting threads...done")))))
 
 (defun gnus-sort-articles (articles)
   "Sort ARTICLES."
@@ -3364,12 +4398,12 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 ;; Written by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
 (defmacro gnus-thread-header (thread)
-  ;; Return header of first article in THREAD.
-  ;; Note that THREAD must never, ever be anything else than a variable -
-  ;; using some other form will lead to serious barfage.
+  "Return header of first article in THREAD.
+Note that THREAD must never, ever be anything else than a variable -
+using some other form will lead to serious barfage."
   (or (symbolp thread) (signal 'wrong-type-argument '(symbolp thread)))
   ;; (8% speedup to gnus-summary-prepare, just for fun :-)
-  (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" ;
+  (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207"
        (vector thread) 2))
 
 (defsubst gnus-article-sort-by-number (h1 h2)
@@ -3382,6 +4416,15 @@ If NO-DISPLAY, don't generate a summary buffer."
   (gnus-article-sort-by-number
    (gnus-thread-header h1) (gnus-thread-header h2)))
 
+(defsubst gnus-article-sort-by-random (h1 h2)
+  "Sort articles by article number."
+  (zerop (random 2)))
+
+(defun gnus-thread-sort-by-random (h1 h2)
+  "Sort threads by root article number."
+  (gnus-article-sort-by-random
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defsubst gnus-article-sort-by-lines (h1 h2)
   "Sort articles by article Lines header."
   (< (mail-header-lines h1)
@@ -3392,17 +4435,28 @@ If NO-DISPLAY, don't generate a summary buffer."
   (gnus-article-sort-by-lines
    (gnus-thread-header h1) (gnus-thread-header h2)))
 
+(defsubst gnus-article-sort-by-chars (h1 h2)
+  "Sort articles by octet length."
+  (< (mail-header-chars h1)
+     (mail-header-chars h2)))
+
+(defun gnus-thread-sort-by-chars (h1 h2)
+  "Sort threads by root article octet length."
+  (gnus-article-sort-by-chars
+   (gnus-thread-header h1) (gnus-thread-header h2)))
+
 (defsubst gnus-article-sort-by-author (h1 h2)
   "Sort articles by root author."
   (string-lessp
-   (let ((extract (funcall
-                  gnus-extract-address-components
-                  (mail-header-from h1))))
-     (or (car extract) (cadr extract) ""))
-   (let ((extract (funcall
-                  gnus-extract-address-components
-                  (mail-header-from h2))))
-     (or (car extract) (cadr extract) ""))))
+   (let ((addr (car (mime-entity-read-field h1 'From))))
+     (or (std11-full-name-string addr)
+        (std11-address-string addr)
+        ""))
+   (let ((addr (car (mime-entity-read-field h2 'From))))
+     (or (std11-full-name-string addr)
+        (std11-address-string addr)
+        ""))
+   ))
 
 (defun gnus-thread-sort-by-author (h1 h2)
   "Sort threads by root author."
@@ -3422,7 +4476,7 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
-  (gnus-time-less
+  (time-less-p
    (gnus-date-get-time (mail-header-date h1))
    (gnus-date-get-time (mail-header-date h2))))
 
@@ -3452,16 +4506,48 @@ Unscored articles will be counted as having a score of zero."
   (> (gnus-thread-total-score h1) (gnus-thread-total-score h2)))
 
 (defun gnus-thread-total-score (thread)
-  ;;  This function find the total score of THREAD.
-  (cond ((null thread)
-        0)
-       ((consp thread)
-        (if (stringp (car thread))
-            (apply gnus-thread-score-function 0
-                   (mapcar 'gnus-thread-total-score-1 (cdr thread)))
-          (gnus-thread-total-score-1 thread)))
-       (t
-        (gnus-thread-total-score-1 (list thread)))))
+  ;; This function find the total score of THREAD.
+  (cond
+   ((null thread)
+    0)
+   ((consp thread)
+    (if (stringp (car thread))
+       (apply gnus-thread-score-function 0
+              (mapcar 'gnus-thread-total-score-1 (cdr thread)))
+      (gnus-thread-total-score-1 thread)))
+   (t
+    (gnus-thread-total-score-1 (list thread)))))
+
+(defun gnus-thread-sort-by-most-recent-number (h1 h2)
+  "Sort threads such that the thread with the most recently arrived article comes first."
+  (> (gnus-thread-highest-number h1) (gnus-thread-highest-number h2)))
+
+(defun gnus-thread-highest-number (thread)
+  "Return the highest article number in THREAD."
+  (apply 'max (mapcar (lambda (header)
+                       (mail-header-number header))
+                     (message-flatten-list thread))))
+
+(defun gnus-thread-sort-by-most-recent-date (h1 h2)
+  "Sort threads such that the thread with the most recently dated article comes first."
+  (> (gnus-thread-latest-date h1) (gnus-thread-latest-date h2)))
+
+(defun gnus-thread-latest-date (thread)
+  "Return the highest article date in THREAD."
+  (let ((previous-time 0))
+    (apply 'max
+          (mapcar
+           (lambda (header)
+             (setq previous-time
+                   (condition-case ()
+                       (time-to-seconds (mail-header-parse-date
+                                         (mail-header-date header)))
+                     (error previous-time))))
+           (sort
+            (message-flatten-list thread)
+            (lambda (h1 h2)
+              (< (mail-header-number h1)
+                 (mail-header-number h2))))))))
 
 (defun gnus-thread-total-score-1 (root)
   ;; This function find the total score of the thread below ROOT.
@@ -3469,8 +4555,7 @@ Unscored articles will be counted as having a score of zero."
   (apply gnus-thread-score-function
         (or (append
              (mapcar 'gnus-thread-total-score
-                     (cdr (gnus-gethash (mail-header-id root)
-                                        gnus-newsgroup-dependencies)))
+                     (cdr (gnus-id-to-thread (mail-header-id root))))
              (when (> (mail-header-number root) 0)
                (list (or (cdr (assq (mail-header-number root)
                                     gnus-newsgroup-scored))
@@ -3484,6 +4569,46 @@ Unscored articles will be counted as having a score of zero."
 (defvar gnus-tmp-root-expunged nil)
 (defvar gnus-tmp-dummy-line nil)
 
+(eval-when-compile (defvar gnus-tmp-header))
+(defun gnus-extra-header (type &optional header)
+  "Return the extra header of TYPE."
+  (or (cdr (assq type (mail-header-extra (or header gnus-tmp-header))))
+      ""))
+
+(defvar gnus-tmp-thread-tree-header-string "")
+
+(defcustom gnus-sum-thread-tree-root "> "
+  "With %B spec, used for the root of a thread.
+If nil, use subject instead."
+  :type '(radio (const :format "%v  " nil) (string :size 0))
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-false-root "> "
+  "With %B spec, used for a false root of a thread.
+If nil, use subject instead."
+  :type '(radio (const :format "%v  " nil) (string :size 0))
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-indent ""
+  "With %B spec, used for a thread with just one message.
+If nil, use subject instead."
+  :type '(radio (const :format "%v  " nil) (string :size 0))
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-vertical "| "
+  "With %B spec, used for drawing a vertical line."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-indent "  "
+  "With %B spec, used for indenting."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-leaf-with-other "+-> "
+  "With %B spec, used for a leaf with brothers."
+  :type 'string
+  :group 'gnus-thread)
+(defcustom gnus-sum-thread-tree-single-leaf "\\-> "
+  "With %B spec, used for a leaf without brothers."
+  :type 'string
+  :group 'gnus-thread)
+
 (defun gnus-summary-prepare-threads (threads)
   "Prepare summary buffer from THREADS and indentation LEVEL.
 THREADS is either a list of `(PARENT [(CHILD1 [(GRANDCHILD ...]...) ...])'
@@ -3496,15 +4621,19 @@ or a straight list of headers."
   (let ((gnus-tmp-level 0)
        (default-score (or gnus-summary-default-score 0))
        (gnus-visual-p (gnus-visual-p 'summary-highlight 'highlight))
+       (building-line-count gnus-summary-display-while-building)
+       (building-count (integerp gnus-summary-display-while-building))
        thread number subject stack state gnus-tmp-gathered beg-match
-       new-roots gnus-tmp-new-adopts thread-end
-       gnus-tmp-header gnus-tmp-unread
+       new-roots gnus-tmp-new-adopts thread-end simp-subject
+       gnus-tmp-header gnus-tmp-unread gnus-tmp-downloaded
        gnus-tmp-replied gnus-tmp-subject-or-nil
        gnus-tmp-dummy gnus-tmp-indentation gnus-tmp-lines gnus-tmp-score
        gnus-tmp-score-char gnus-tmp-from gnus-tmp-name
-       gnus-tmp-number gnus-tmp-opening-bracket gnus-tmp-closing-bracket)
+       gnus-tmp-number gnus-tmp-opening-bracket gnus-tmp-closing-bracket
+       tree-stack)
 
-    (setq gnus-tmp-prev-subject nil)
+    (setq gnus-tmp-prev-subject nil
+          gnus-tmp-thread-tree-header-string "")
 
     (if (vectorp (car threads))
        ;; If this is a straight (sic) list of headers, then a
@@ -3514,10 +4643,11 @@ or a straight list of headers."
 
       ;; Do the threaded display.
 
+      (if gnus-summary-display-while-building
+         (switch-to-buffer (buffer-name)))
       (while (or threads stack gnus-tmp-new-adopts new-roots)
 
        (if (and (= gnus-tmp-level 0)
-                (not (setq gnus-tmp-dummy-line nil))
                 (or (not stack)
                     (= (caar stack) 0))
                 (not gnus-tmp-false-parent)
@@ -3541,7 +4671,8 @@ or a straight list of headers."
            ;; the stack.
            (setq state (car stack)
                  gnus-tmp-level (car state)
-                 thread (cdr state)
+                 tree-stack (cadr state)
+                 thread (caddr state)
                  stack (cdr stack)
                  gnus-tmp-header (caar thread))))
 
@@ -3585,7 +4716,8 @@ or a straight list of headers."
              (setq gnus-tmp-level -1)))
 
          (setq number (mail-header-number gnus-tmp-header)
-               subject (mail-header-subject gnus-tmp-header))
+               subject (mail-header-subject gnus-tmp-header)
+               simp-subject (gnus-simplify-subject-fully subject))
 
          (cond
           ;; If the thread has changed subject, we might want to make
@@ -3593,8 +4725,7 @@ or a straight list of headers."
           ((and (null gnus-thread-ignore-subject)
                 (not (zerop gnus-tmp-level))
                 gnus-tmp-prev-subject
-                (not (inline
-                       (gnus-subject-equal gnus-tmp-prev-subject subject))))
+                (not (string= gnus-tmp-prev-subject simp-subject)))
            (setq new-roots (nconc new-roots (list (car thread)))
                  thread-end t
                  gnus-tmp-header nil))
@@ -3625,14 +4756,19 @@ or a straight list of headers."
            (setq gnus-newsgroup-unreads
                  (delq number gnus-newsgroup-unreads))
            (if gnus-newsgroup-auto-expire
-               (push number gnus-newsgroup-expirable)
+               (setq gnus-newsgroup-expirable
+                     (gnus-add-to-sorted-list
+                      gnus-newsgroup-expirable number))
              (push (cons number gnus-low-score-mark)
                    gnus-newsgroup-reads))))
 
          (when gnus-tmp-header
            ;; We may have an old dummy line to output before this
            ;; article.
-           (when gnus-tmp-dummy-line
+           (when (and gnus-tmp-dummy-line
+                      (gnus-subject-equal
+                       gnus-tmp-dummy-line
+                       (mail-header-subject gnus-tmp-header)))
              (gnus-summary-insert-dummy-line
               gnus-tmp-dummy-line (mail-header-number gnus-tmp-header))
              (setq gnus-tmp-dummy-line nil))
@@ -3650,15 +4786,13 @@ or a straight list of headers."
             (cond
              ((and gnus-thread-ignore-subject
                    gnus-tmp-prev-subject
-                   (not (inline (gnus-subject-equal
-                                 gnus-tmp-prev-subject subject))))
+                   (not (string= gnus-tmp-prev-subject simp-subject)))
               subject)
              ((zerop gnus-tmp-level)
               (if (and (eq gnus-summary-make-false-root 'empty)
                        (memq number gnus-tmp-gathered)
                        gnus-tmp-prev-subject
-                       (inline (gnus-subject-equal
-                                gnus-tmp-prev-subject subject)))
+                       (string= gnus-tmp-prev-subject simp-subject))
                   gnus-summary-same-subject
                 subject))
              (t gnus-summary-same-subject)))
@@ -3679,7 +4813,7 @@ or a straight list of headers."
             (if (or (null gnus-summary-default-score)
                     (<= (abs (- gnus-tmp-score gnus-summary-default-score))
                         gnus-summary-zcore-fuzz))
-                ? 
+                ?\ ;;;Whitespace
               (if (< gnus-tmp-score gnus-summary-default-score)
                   gnus-score-below-mark gnus-score-over-mark))
             gnus-tmp-replied
@@ -3689,41 +4823,93 @@ or a straight list of headers."
                    gnus-cached-mark)
                   ((memq number gnus-newsgroup-replied)
                    gnus-replied-mark)
+                  ((memq number gnus-newsgroup-forwarded)
+                   gnus-forwarded-mark)
                   ((memq number gnus-newsgroup-saved)
                    gnus-saved-mark)
-                  (t gnus-unread-mark))
+                  ((memq number gnus-newsgroup-recent)
+                   gnus-recent-mark)
+                  ((memq number gnus-newsgroup-unseen)
+                   gnus-unseen-mark)
+                  (t gnus-no-mark))
+            gnus-tmp-downloaded
+             (cond ((memq number gnus-newsgroup-undownloaded)
+                    gnus-undownloaded-mark)
+                   (gnus-newsgroup-agentized
+                    gnus-downloaded-mark)
+                   (t
+                    gnus-no-mark))
             gnus-tmp-from (mail-header-from gnus-tmp-header)
             gnus-tmp-name
             (cond
              ((string-match "<[^>]+> *$" gnus-tmp-from)
               (setq beg-match (match-beginning 0))
-              (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
-                       (substring gnus-tmp-from (1+ (match-beginning 0))
-                                  (1- (match-end 0))))
+              (or (and (string-match "^\".+\"" gnus-tmp-from)
+                       (substring gnus-tmp-from 1 (1- (match-end 0))))
                   (substring gnus-tmp-from 0 beg-match)))
              ((string-match "(.+)" gnus-tmp-from)
               (substring gnus-tmp-from
                          (1+ (match-beginning 0)) (1- (match-end 0))))
-             (t gnus-tmp-from)))
+             (t gnus-tmp-from))
+
+            ;; Do the %B string
+            gnus-tmp-thread-tree-header-string
+            (cond
+             ((not gnus-show-threads) "")
+             ((zerop gnus-tmp-level)
+              (cond ((cdar thread)
+                     (or gnus-sum-thread-tree-root subject))
+                    (gnus-tmp-new-adopts
+                     (or gnus-sum-thread-tree-false-root subject))
+                    (t
+                     (or gnus-sum-thread-tree-single-indent subject))))
+             (t
+              (concat (apply 'concat
+                             (mapcar (lambda (item)
+                                       (if (= item 1)
+                                           gnus-sum-thread-tree-vertical
+                                         gnus-sum-thread-tree-indent))
+                                     (cdr (reverse tree-stack))))
+                      (if (nth 1 thread)
+                          gnus-sum-thread-tree-leaf-with-other
+                        gnus-sum-thread-tree-single-leaf)))))
            (when (string= gnus-tmp-name "")
              (setq gnus-tmp-name gnus-tmp-from))
            (unless (numberp gnus-tmp-lines)
-             (setq gnus-tmp-lines 0))
-           (gnus-put-text-property
+             (setq gnus-tmp-lines -1))
+           (if (= gnus-tmp-lines -1)
+               (setq gnus-tmp-lines "?")
+             (setq gnus-tmp-lines (number-to-string gnus-tmp-lines)))
+              (gnus-put-text-property
             (point)
             (progn (eval gnus-summary-line-format-spec) (point))
-            'gnus-number number)
+               'gnus-number number)
            (when gnus-visual-p
              (forward-line -1)
              (gnus-run-hooks 'gnus-summary-update-hook)
              (forward-line 1))
 
-           (setq gnus-tmp-prev-subject subject)))
+           (setq gnus-tmp-prev-subject simp-subject)))
 
        (when (nth 1 thread)
-         (push (cons (max 0 gnus-tmp-level) (nthcdr 1 thread)) stack))
+         (push (list (max 0 gnus-tmp-level)
+                     (copy-sequence tree-stack)
+                     (nthcdr 1 thread))
+               stack))
+       (push (if (nth 1 thread) 1 0) tree-stack)
        (incf gnus-tmp-level)
        (setq threads (if thread-end nil (cdar thread)))
+       (if gnus-summary-display-while-building
+           (if building-count
+               (progn
+                 ;; use a set frequency
+                 (setq building-line-count (1- building-line-count))
+                 (when (= building-line-count 0)
+                   (sit-for 0)
+                   (setq building-line-count
+                         gnus-summary-display-while-building)))
+             ;; always
+             (sit-for 0)))
        (unless threads
          (setq gnus-tmp-level 0)))))
   (gnus-message 7 "Generating summary...done"))
@@ -3757,15 +4943,64 @@ or a straight list of headers."
              gnus-newsgroup-data)
        (gnus-summary-insert-line
         header 0 number
+        (memq number gnus-newsgroup-undownloaded)
         mark (memq number gnus-newsgroup-replied)
         (memq number gnus-newsgroup-expirable)
         (mail-header-subject header) nil
         (cdr (assq number gnus-newsgroup-scored))
         (memq number gnus-newsgroup-processable))))))
 
-(defun gnus-select-newsgroup (group &optional read-all)
+(defun gnus-summary-remove-list-identifiers ()
+  "Remove list identifiers in `gnus-list-identifiers' from articles in the current group."
+  (let ((regexp (if (consp gnus-list-identifiers)
+                   (mapconcat 'identity gnus-list-identifiers " *\\|")
+                 gnus-list-identifiers))
+       changed subject)
+    (when regexp
+      (dolist (header gnus-newsgroup-headers)
+       (setq subject (mail-header-subject header)
+             changed nil)
+       (while (string-match
+               (concat "^\\(R[Ee]: +\\)*\\(" regexp " *\\)")
+               subject)
+         (setq subject
+               (concat (substring subject 0 (match-beginning 2))
+                       (substring subject (match-end 0)))
+               changed t))
+       (when (and changed
+                  (string-match
+                   "^\\(\\(R[Ee]: +\\)+\\)R[Ee]: +" subject))
+         (setq subject
+               (concat (substring subject 0 (match-beginning 1))
+                       (substring subject (match-end 1)))))
+       (when changed
+         (mail-header-set-subject header subject))))))
+
+(defun gnus-fetch-headers (articles)
+  "Fetch headers of ARTICLES."
+  (let ((name (gnus-group-decoded-name gnus-newsgroup-name)))
+    (gnus-message 5 "Fetching headers for %s..." name)
+    (prog1
+       (if (eq 'nov
+               (setq gnus-headers-retrieved-by
+                     (gnus-retrieve-headers
+                      articles gnus-newsgroup-name
+                      ;; We might want to fetch old headers, but
+                      ;; not if there is only 1 article.
+                      (and (or (and
+                                (not (eq gnus-fetch-old-headers 'some))
+                                (not (numberp gnus-fetch-old-headers)))
+                               (> (length articles) 1))
+                           gnus-fetch-old-headers))))
+           (gnus-get-newsgroup-headers-xover
+            articles nil nil gnus-newsgroup-name t)
+         (gnus-get-newsgroup-headers))
+      (gnus-message 5 "Fetching headers for %s...done" name))))
+
+(defun gnus-select-newsgroup (group &optional read-all select-articles)
   "Select newsgroup GROUP.
-If READ-ALL is non-nil, all articles in the group are selected."
+If READ-ALL is non-nil, all articles in the group are selected.
+If SELECT-ARTICLES, only select those articles from GROUP."
   (let* ((entry (gnus-gethash group gnus-newsrc-hashtb))
         ;;!!! Dirty hack; should be removed.
         (gnus-summary-ignore-duplicates
@@ -3776,48 +5011,100 @@ If READ-ALL is non-nil, all articles in the group are selected."
         articles fetched-articles cached)
 
     (unless (gnus-check-server
-            (setq gnus-current-select-method
-                  (gnus-find-method-for-group group)))
+            (set (make-local-variable 'gnus-current-select-method)
+                 (gnus-find-method-for-group group)))
       (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
        (gnus-activate-group group)     ; Or we can activate it...
        (progn                          ; Or we bug out.
          (when (equal major-mode 'gnus-summary-mode)
-           (kill-buffer (current-buffer)))
-         (error "Couldn't request group %s: %s"
+           (gnus-kill-buffer (current-buffer)))
+         (error "Couldn't activate group %s: %s"
                 group (gnus-status-message group))))
 
     (unless (gnus-request-group group t)
       (when (equal major-mode 'gnus-summary-mode)
-       (kill-buffer (current-buffer)))
+       (gnus-kill-buffer (current-buffer)))
       (error "Couldn't request group %s: %s"
             group (gnus-status-message group)))
 
-    (setq gnus-newsgroup-name group)
-    (setq gnus-newsgroup-unselected nil)
-    (setq gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
+    (when gnus-agent
+      ;; The agent may be storing articles that are no longer in the
+      ;; server's active range.  If that is the case, the active range
+      ;; needs to be expanded such that the agent's articles can be
+      ;; included in the summary.
+      (let* ((gnus-command-method (gnus-find-method-for-group group))
+             (alist (gnus-agent-load-alist group))
+             (active (gnus-active group)))
+        (if (and (car alist)
+                 (< (caar alist) (car active)))
+            (gnus-set-active group (cons (caar alist) (cdr active)))))
+
+      (setq gnus-summary-use-undownloaded-faces
+           (gnus-agent-find-parameter
+            group
+            'agent-enable-undownloaded-faces)))
+
+    (setq gnus-newsgroup-name group
+         gnus-newsgroup-unselected nil
+         gnus-newsgroup-unreads (gnus-list-of-unread-articles group))
+
+    (let ((display (gnus-group-find-parameter group 'display)))
+      (setq gnus-newsgroup-display
+           (cond
+            ((not (zerop (or (car-safe read-all) 0)))
+             ;; The user entered the group with C-u SPC/RET, let's show
+             ;; all articles.
+             'gnus-not-ignore)
+            ((eq display 'all)
+             'gnus-not-ignore)
+            ((arrayp display)
+             (gnus-summary-display-make-predicate (mapcar 'identity display)))
+            ((numberp display)
+             ;; The following is probably the "correct" solution, but
+             ;; it makes Gnus fetch all headers and then limit the
+             ;; articles (which is slow), so instead we hack the
+             ;; select-articles parameter instead. -- Simon Josefsson
+             ;; <jas@kth.se>
+             ;;
+             ;; (gnus-byte-compile
+             ;;  `(lambda () (> number ,(- (cdr (gnus-active group))
+             ;;                         display)))))
+             (setq select-articles
+                   (gnus-uncompress-range
+                    (cons (let ((tmp (- (cdr (gnus-active group)) display)))
+                            (if (> tmp 0)
+                                tmp
+                              1))
+                          (cdr (gnus-active group)))))
+             nil)
+            (t
+             nil))))
 
-    ;; Adjust and set lists of article marks.
-    (when info
-      (gnus-adjust-marked-articles info))
+    (gnus-summary-setup-default-charset)
 
     ;; Kludge to avoid having cached articles nixed out in virtual groups.
     (when (gnus-virtual-group-p group)
       (setq cached gnus-newsgroup-cached))
 
     (setq gnus-newsgroup-unreads
-         (gnus-set-difference
-          (gnus-set-difference gnus-newsgroup-unreads gnus-newsgroup-marked)
+         (gnus-sorted-ndifference
+          (gnus-sorted-ndifference gnus-newsgroup-unreads
+                                   gnus-newsgroup-marked)
           gnus-newsgroup-dormant))
 
     (setq gnus-newsgroup-processable nil)
 
     (gnus-update-read-articles group gnus-newsgroup-unreads)
-    (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
-      (gnus-group-update-group group))
 
-    (setq articles (gnus-articles-to-read group read-all))
+    ;; Adjust and set lists of article marks.
+    (when info
+      (gnus-adjust-marked-articles info))
+    (if (setq articles select-articles)
+       (setq gnus-newsgroup-unselected
+             (gnus-sorted-difference gnus-newsgroup-unreads articles))
+      (setq articles (gnus-articles-to-read group read-all)))
 
     (cond
      ((null articles)
@@ -3828,24 +5115,10 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; Init the dependencies hash table.
       (setq gnus-newsgroup-dependencies
            (gnus-make-hashtable (length articles)))
+      (gnus-set-global-variables)
       ;; Retrieve the headers and read them in.
-      (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
-      (setq gnus-newsgroup-headers
-           (if (eq 'nov
-                   (setq gnus-headers-retrieved-by
-                         (gnus-retrieve-headers
-                          articles gnus-newsgroup-name
-                          ;; We might want to fetch old headers, but
-                          ;; not if there is only 1 article.
-                          (and gnus-fetch-old-headers
-                               (or (and
-                                    (not (eq gnus-fetch-old-headers 'some))
-                                    (not (numberp gnus-fetch-old-headers)))
-                                   (> (length articles) 1))))))
-               (gnus-get-newsgroup-headers-xover
-                articles nil nil gnus-newsgroup-name t)
-             (gnus-get-newsgroup-headers)))
-      (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
+
+      (setq gnus-newsgroup-headers (gnus-fetch-headers articles))
 
       ;; Kludge to avoid having cached articles nixed out in virtual groups.
       (when cached
@@ -3858,24 +5131,30 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; Set the initial limit.
       (setq gnus-newsgroup-limit (copy-sequence articles))
       ;; Remove canceled articles from the list of unread articles.
+      (setq fetched-articles
+           (mapcar (lambda (headers) (mail-header-number headers))
+                   gnus-newsgroup-headers))
+      (setq gnus-newsgroup-articles fetched-articles)
       (setq gnus-newsgroup-unreads
-           (gnus-set-sorted-intersection
-            gnus-newsgroup-unreads
-            (setq fetched-articles
-                  (mapcar (lambda (headers) (mail-header-number headers))
-                          gnus-newsgroup-headers))))
+           (gnus-sorted-nintersection
+            gnus-newsgroup-unreads fetched-articles))
+      (gnus-compute-unseen-list)
+
       ;; Removed marked articles that do not exist.
       (gnus-update-missing-marks
-       (gnus-sorted-complement fetched-articles articles))
-      ;; Let the Gnus agent mark articles as read.
-      (when gnus-agent
-       (gnus-agent-get-undownloaded-list))
+       (gnus-sorted-difference articles fetched-articles))
       ;; We might want to build some more threads first.
       (when (and gnus-fetch-old-headers
                 (eq gnus-headers-retrieved-by 'nov))
        (if (eq gnus-fetch-old-headers 'invisible)
            (gnus-build-all-threads)
          (gnus-build-old-threads)))
+      ;; Let the Gnus agent mark articles as read.
+      (when gnus-agent
+       (gnus-agent-get-undownloaded-list))
+      ;; Remove list identifiers from subject
+      (when gnus-list-identifiers
+       (gnus-summary-remove-list-identifiers))
       ;; Check whether auto-expire is to be done in this group.
       (setq gnus-newsgroup-auto-expire
            (gnus-group-auto-expirable-p group))
@@ -3892,20 +5171,97 @@ If READ-ALL is non-nil, all articles in the group are selected."
       ;; GROUP is successfully selected.
       (or gnus-newsgroup-headers t)))))
 
+(defun gnus-compute-unseen-list ()
+  ;; The `seen' marks are treated specially.
+  (if (not gnus-newsgroup-seen)
+      (setq gnus-newsgroup-unseen gnus-newsgroup-articles)
+    (setq gnus-newsgroup-unseen
+         (gnus-inverse-list-range-intersection
+          gnus-newsgroup-articles gnus-newsgroup-seen))))
+
+(defun gnus-summary-display-make-predicate (display)
+  (require 'gnus-agent)
+  (when (= (length display) 1)
+    (setq display (car display)))
+  (unless gnus-summary-display-cache
+    (dolist (elem (append '((unread . unread)
+                           (read . read)
+                           (unseen . unseen))
+                         gnus-article-mark-lists))
+      (push (cons (cdr elem)
+                 (gnus-byte-compile
+                  `(lambda () (gnus-article-marked-p ',(cdr elem)))))
+           gnus-summary-display-cache)))
+  (let ((gnus-category-predicate-alist gnus-summary-display-cache)
+       (gnus-category-predicate-cache gnus-summary-display-cache))
+    (gnus-get-predicate display)))
+
+;; Uses the dynamically bound `number' variable.
+(eval-when-compile
+  (defvar number))
+(defun gnus-article-marked-p (type &optional article)
+  (let ((article (or article number)))
+    (cond
+     ((eq type 'tick)
+      (memq article gnus-newsgroup-marked))
+     ((eq type 'spam)
+      (memq article gnus-newsgroup-spam-marked))
+     ((eq type 'unsend)
+      (memq article gnus-newsgroup-unsendable))
+     ((eq type 'undownload)
+      (memq article gnus-newsgroup-undownloaded))
+     ((eq type 'download)
+      (memq article gnus-newsgroup-downloadable))
+     ((eq type 'unread)
+      (memq article gnus-newsgroup-unreads))
+     ((eq type 'read)
+      (memq article gnus-newsgroup-reads))
+     ((eq type 'dormant)
+      (memq article gnus-newsgroup-dormant) )
+     ((eq type 'expire)
+      (memq article gnus-newsgroup-expirable))
+     ((eq type 'reply)
+      (memq article gnus-newsgroup-replied))
+     ((eq type 'killed)
+      (memq article gnus-newsgroup-killed))
+     ((eq type 'bookmark)
+      (assq article gnus-newsgroup-bookmarks))
+     ((eq type 'score)
+      (assq article gnus-newsgroup-scored))
+     ((eq type 'save)
+      (memq article gnus-newsgroup-saved))
+     ((eq type 'cache)
+      (memq article gnus-newsgroup-cached))
+     ((eq type 'forward)
+      (memq article gnus-newsgroup-forwarded))
+     ((eq type 'seen)
+      (not (memq article gnus-newsgroup-unseen)))
+     ((eq type 'recent)
+      (memq article gnus-newsgroup-recent))
+     (t t))))
+
 (defun gnus-articles-to-read (group &optional read-all)
-  ;; Find out what articles the user wants to read.
-  (let* ((articles
+  "Find out what articles the user wants to read."
+  (let* ((display (gnus-group-find-parameter group 'display))
+        (articles
          ;; Select all articles if `read-all' is non-nil, or if there
          ;; are no unread articles.
          (if (or read-all
                  (and (zerop (length gnus-newsgroup-marked))
                       (zerop (length gnus-newsgroup-unreads)))
-                 (eq (gnus-group-find-parameter group 'display)
-                     'all))
-             (gnus-uncompress-range (gnus-active group))
-           (sort (append gnus-newsgroup-dormant gnus-newsgroup-marked
-                         (copy-sequence gnus-newsgroup-unreads))
-                 '<)))
+                 ;; Fetch all if the predicate is non-nil.
+                 gnus-newsgroup-display)
+             ;; We want to select the headers for all the articles in
+             ;; the group, so we select either all the active
+             ;; articles in the group, or (if that's nil), the
+             ;; articles in the cache.
+             (or
+              (gnus-uncompress-range (gnus-active group))
+              (gnus-cache-articles-in-group group))
+           ;; Select only the "normal" subset of articles.
+           (gnus-sorted-nunion
+            (gnus-sorted-union gnus-newsgroup-dormant gnus-newsgroup-marked)
+            gnus-newsgroup-unreads)))
         (scored-list (gnus-killed-articles gnus-newsgroup-killed articles))
         (scored (length scored-list))
         (number (length articles))
@@ -3915,18 +5271,29 @@ If READ-ALL is non-nil, all articles in the group are selected."
          (cond
           ((numberp read-all)
            read-all)
+          ((numberp gnus-newsgroup-display)
+           gnus-newsgroup-display)
           (t
            (condition-case ()
                (cond
                 ((and (or (<= scored marked) (= scored number))
                       (numberp gnus-large-newsgroup)
                       (> number gnus-large-newsgroup))
-                 (let ((input
-                        (read-string
-                         (format
-                          "How many articles from %s (default %d): "
-                          (gnus-limit-string gnus-newsgroup-name 35)
-                          number))))
+                 (let* ((cursor-in-echo-area nil)
+                        (initial (gnus-parameter-large-newsgroup-initial
+                                  gnus-newsgroup-name))
+                        (input
+                         (read-string
+                          (format
+                           "How many articles from %s (%s %d): "
+                           (gnus-limit-string
+                            (gnus-group-decoded-name gnus-newsgroup-name)
+                            35)
+                           (if initial "max" "default")
+                           number)
+                          (if initial
+                              (cons (number-to-string initial)
+                                    0)))))
                    (if (string-match "^[ \t]*$" input) number input)))
                 ((and (> scored marked) (< scored number)
                       (> (- scored number) 20))
@@ -3934,11 +5301,14 @@ If READ-ALL is non-nil, all articles in the group are selected."
                         (read-string
                          (format "%s %s (%d scored, %d total): "
                                  "How many articles from"
-                                 group scored number))))
+                                 (gnus-group-decoded-name group)
+                                 scored number))))
                    (if (string-match "^[ \t]*$" input)
                        number input)))
                 (t number))
-             (quit nil))))))
+             (quit
+              (message "Quit getting the articles to read")
+              nil))))))
     (setq select (if (stringp select) (string-to-number select) select))
     (if (or (null select) (zerop select))
        select
@@ -3955,9 +5325,13 @@ If READ-ALL is non-nil, all articles in the group are selected."
          ;; Select the N most recent articles.
          (setq articles (nthcdr (- number select) articles))))
       (setq gnus-newsgroup-unselected
-           (gnus-sorted-intersection
-            gnus-newsgroup-unreads
-            (gnus-sorted-complement gnus-newsgroup-unreads articles)))
+           (gnus-sorted-difference gnus-newsgroup-unreads articles))
+      (when gnus-alter-articles-to-read-function
+       (setq articles
+             (sort
+              (funcall gnus-alter-articles-to-read-function
+                       gnus-newsgroup-name articles)
+              '<)))
       articles)))
 
 (defun gnus-killed-articles (killed articles)
@@ -3979,35 +5353,42 @@ If READ-ALL is non-nil, all articles in the group are selected."
       (setq marks (cdr marks)))
     out))
 
+(defun gnus-article-mark-to-type (mark)
+  "Return the type of MARK."
+  (or (cadr (assq mark gnus-article-special-mark-lists))
+      'list))
+
+(defun gnus-article-unpropagatable-p (mark)
+  "Return whether MARK should be propagated to back end."
+  (memq mark gnus-article-unpropagated-mark-lists))
+
 (defun gnus-adjust-marked-articles (info)
-  "Set all article lists and remove all marks that are no longer legal."
+  "Set all article lists and remove all marks that are no longer valid."
   (let* ((marked-lists (gnus-info-marks info))
         (active (gnus-active (gnus-info-group info)))
         (min (car active))
         (max (cdr active))
         (types gnus-article-mark-lists)
-        (uncompressed '(score bookmark killed))
-        marks var articles article mark)
+        marks var articles article mark mark-type)
 
-    (while marked-lists
-      (setq marks (pop marked-lists))
-      (set (setq var (intern (format "gnus-newsgroup-%s"
-                                    (car (rassq (setq mark (car marks))
-                                                types)))))
-          (if (memq (car marks) uncompressed) (cdr marks)
-            (gnus-uncompress-range (cdr marks))))
+    (dolist (marks marked-lists)
+      (setq mark (car marks)
+           mark-type (gnus-article-mark-to-type mark)
+           var (intern (format "gnus-newsgroup-%s" (car (rassq mark types)))))
 
-      (setq articles (symbol-value var))
-
-      ;; All articles have to be subsets of the active articles.
+      ;; We set the variable according to the type of the marks list,
+      ;; and then adjust the marks to a subset of the active articles.
       (cond
        ;; Adjust "simple" lists.
-       ((memq mark '(tick dormant expire reply save))
-       (while articles
-         (when (or (< (setq article (pop articles)) min) (> article max))
-           (set var (delq article (symbol-value var))))))
+       ((eq mark-type 'list)
+       (set var (setq articles (gnus-uncompress-range (cdr marks))))
+       (when (memq mark '(tick dormant expire reply save))
+         (while articles
+           (when (or (< (setq article (pop articles)) min) (> article max))
+             (set var (delq article (symbol-value var)))))))
        ;; Adjust assocs.
-       ((memq mark uncompressed)
+       ((eq mark-type 'tuple)
+       (set var (setq articles (cdr marks)))
        (when (not (listp (cdr (symbol-value var))))
          (set var (list (symbol-value var))))
        (when (not (listp (cdr articles)))
@@ -4016,37 +5397,52 @@ If READ-ALL is non-nil, all articles in the group are selected."
          (when (or (not (consp (setq article (pop articles))))
                    (< (car article) min)
                    (> (car article) max))
-           (set var (delq article (symbol-value var))))))))))
+           (set var (delq article (symbol-value var))))))
+       ;; Adjust ranges (sloppily).
+       ((eq mark-type 'range)
+       (cond
+        ((eq mark 'seen)
+         ;; Fix the record for `seen' if it looks like (seen NUM1 . NUM2).
+         ;; It should be (seen (NUM1 . NUM2)).
+         (when (numberp (cddr marks))
+           (setcdr marks (list (cdr marks))))
+         (setq articles (cdr marks))
+         (while (and articles
+                     (or (and (consp (car articles))
+                              (> min (cdar articles)))
+                         (and (numberp (car articles))
+                              (> min (car articles)))))
+           (pop articles))
+         (set var articles))))))))
 
 (defun gnus-update-missing-marks (missing)
   "Go through the list of MISSING articles and remove them from the mark lists."
   (when missing
-    (let ((types gnus-article-mark-lists)
-         var m)
+    (let (var m)
       ;; Go through all types.
-      (while types
-       (setq var (intern (format "gnus-newsgroup-%s" (car (pop types)))))
-       (when (symbol-value var)
-         ;; This list has articles.  So we delete all missing articles
-         ;; from it.
-         (setq m missing)
-         (while m
-           (set var (delq (pop m) (symbol-value var)))))))))
+      (dolist (elem gnus-article-mark-lists)
+       (when (eq (gnus-article-mark-to-type (cdr elem)) 'list)
+         (setq var (intern (format "gnus-newsgroup-%s" (car elem))))
+         (when (symbol-value var)
+           ;; This list has articles.  So we delete all missing
+           ;; articles from it.
+           (setq m missing)
+           (while m
+             (set var (delq (pop m) (symbol-value var))))))))))
 
 (defun gnus-update-marks ()
   "Enter the various lists of marked articles into the newsgroup info list."
   (let ((types gnus-article-mark-lists)
        (info (gnus-get-info gnus-newsgroup-name))
-       (uncompressed '(score bookmark killed))
-       type list newmarked symbol)
+       type list newmarked symbol delta-marks)
     (when info
-      ;; Add all marks lists that are non-nil to the list of marks lists.
+      ;; Add all marks lists to the list of marks lists.
       (while (setq type (pop types))
-       (when (setq list (symbol-value
-                         (setq symbol
-                               (intern (format "gnus-newsgroup-%s"
-                                               (car type))))))
+       (setq list (symbol-value
+                   (setq symbol
+                         (intern (format "gnus-newsgroup-%s" (car type))))))
 
+       (when list
          ;; Get rid of the entries of the articles that have the
          ;; default score.
          (when (and (eq (cdr type) 'score)
@@ -4061,13 +5457,33 @@ If READ-ALL is non-nil, all articles in the group are selected."
                    (setcdr prev (cdr arts))
                  (setq prev arts))
                (setq arts (cdr arts)))
-             (setq list (cdr all))))
-
-         (push (cons (cdr type)
-                     (if (memq (cdr type) uncompressed) list
-                       (gnus-compress-sequence
-                        (set symbol (sort list '<)) t)))
-               newmarked)))
+             (setq list (cdr all)))))
+
+       (when (eq (cdr type) 'seen)
+         (setq list (gnus-range-add list gnus-newsgroup-unseen)))
+
+       (when (eq (gnus-article-mark-to-type (cdr type)) 'list)
+         (setq list (gnus-compress-sequence (set symbol (sort list '<)) t)))
+
+       (when (and (gnus-check-backend-function
+                   'request-set-mark gnus-newsgroup-name)
+                  (not (gnus-article-unpropagatable-p (cdr type))))
+         (let* ((old (cdr (assq (cdr type) (gnus-info-marks info))))
+                (del (gnus-remove-from-range (gnus-copy-sequence old) list))
+                (add (gnus-remove-from-range
+                      (gnus-copy-sequence list) old)))
+           (when add
+             (push (list add 'add (list (cdr type))) delta-marks))
+           (when del
+             (push (list del 'del (list (cdr type))) delta-marks))))
+
+       (when list
+         (push (cons (cdr type) list) newmarked)))
+
+      (when delta-marks
+       (unless (gnus-check-group gnus-newsgroup-name)
+         (error "Can't open server for %s" gnus-newsgroup-name))
+       (gnus-request-set-mark gnus-newsgroup-name delta-marks))
 
       ;; Enter these new marks into the info of the group.
       (if (nthcdr 3 info)
@@ -4084,10 +5500,12 @@ If READ-ALL is non-nil, all articles in the group are selected."
            (setcdr (nthcdr i info) nil)))))))
 
 (defun gnus-set-mode-line (where)
-  "This function sets the mode line of the article or summary buffers.
+  "Set the mode line of the article or summary buffers.
 If WHERE is `summary', the summary mode line format will be used."
   ;; Is this mode line one we keep updated?
-  (when (memq where gnus-updated-mode-lines)
+  (when (and (memq where gnus-updated-mode-lines)
+            (symbol-value
+             (intern (format "gnus-%s-mode-line-format-spec" where))))
     (let (mode-string)
       (save-excursion
        ;; We evaluate this in the summary buffer since these
@@ -4098,7 +5516,8 @@ If WHERE is `summary', the summary mode line format will be used."
        (let* ((mformat (symbol-value
                         (intern
                          (format "gnus-%s-mode-line-format-spec" where))))
-              (gnus-tmp-group-name gnus-newsgroup-name)
+              (gnus-tmp-group-name (gnus-group-decoded-name
+                                    gnus-newsgroup-name))
               (gnus-tmp-article-number (or gnus-current-article 0))
               (gnus-tmp-unread gnus-newsgroup-unreads)
               (gnus-tmp-unread-and-unticked (length gnus-newsgroup-unreads))
@@ -4215,7 +5634,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
         (active (gnus-active group))
         ninfo)
     (when entry
-      ;; First peel off all illegal article numbers.
+      ;; First peel off all invalid article numbers.
       (when active
        (let ((ids articles)
              id first)
@@ -4243,7 +5662,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
       ;; Then we add the read articles to the range.
       (gnus-add-to-range
        ninfo (setq articles (sort articles '<))))))
-  
+
 (defun gnus-group-make-articles-read (group articles)
   "Update the info of GROUP to say that ARTICLES are read."
   (let* ((num 0)
@@ -4260,9 +5679,11 @@ The resulting hash table is returned, or nil if no Xrefs were found."
             (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
             (gnus-info-set-read ',info ',(gnus-info-read info))
             (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
+            (gnus-request-set-mark ,group (list (list ',range 'del '(read))))
             (gnus-group-update-group ,group t))))
       ;; Add the read articles to the range.
       (gnus-info-set-read info range)
+      (gnus-request-set-mark group (list (list range 'add '(read))))
       ;; Then we have to re-compute how many unread
       ;; articles there are in this group.
       (when active
@@ -4282,16 +5703,8 @@ The resulting hash table is returned, or nil if no Xrefs were found."
        ;; Update the number of unread articles.
        (setcar entry num)
        ;; Update the group buffer.
-       (gnus-group-update-group group t)))))
-
-(defun gnus-methods-equal-p (m1 m2)
-  (let ((m1 (or m1 gnus-select-method))
-       (m2 (or m2 gnus-select-method)))
-    (or (equal m1 m2)
-       (and (eq (car m1) (car m2))
-            (or (not (memq 'address (assoc (symbol-name (car m1))
-                                           gnus-valid-select-methods)))
-                (equal (nth 1 m1) (nth 1 m2)))))))
+       (unless (gnus-ephemeral-group-p group)
+         (gnus-group-update-group group t))))))
 
 (defvar gnus-newsgroup-none-id 0)
 
@@ -4301,14 +5714,22 @@ The resulting hash table is returned, or nil if no Xrefs were found."
         (or dependencies
             (save-excursion (set-buffer gnus-summary-buffer)
                             gnus-newsgroup-dependencies)))
-       headers id id-dep ref-dep end ref)
+       headers id end ref
+       (mail-parse-charset gnus-newsgroup-charset)
+       (mail-parse-ignored-charsets
+        (save-excursion (condition-case nil
+                            (set-buffer gnus-summary-buffer)
+                          (error))
+                        gnus-newsgroup-ignored-charsets)))
     (save-excursion
       (set-buffer nntp-server-buffer)
       ;; Translate all TAB characters into SPACE characters.
       (subst-char-in-region (point-min) (point-max) ?\t ?  t)
+      (subst-char-in-region (point-min) (point-max) ?\r ?  t)
+      (ietf-drums-unfold-fws)
       (gnus-run-hooks 'gnus-parse-headers-hook)
       (let ((case-fold-search t)
-           in-reply-to header p lines)
+           in-reply-to header p lines chars ctype)
        (goto-char (point-min))
        ;; Search to the beginning of the next header.  Error messages
        ;; do not begin with 2 or 3.
@@ -4323,7 +5744,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
          ;; doesn't always go hand in hand.
          (setq
           header
-          (vector
+          (make-full-mail-header
            ;; Number.
            (prog1
                (read cur)
@@ -4336,21 +5757,19 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            ;; Subject.
            (progn
              (goto-char p)
-             (if (search-forward "\nsubject: " nil t)
-                 (funcall
-                  gnus-unstructured-field-decoder (nnheader-header-value))
+             (if (search-forward "\nsubject:" nil t)
+                 (nnheader-header-value)
                "(none)"))
            ;; From.
            (progn
              (goto-char p)
-             (if (search-forward "\nfrom: " nil t)
-                 (funcall
-                  gnus-structured-field-decoder (nnheader-header-value))
+             (if (search-forward "\nfrom:" nil t)
+                 (nnheader-header-value)
                "(nobody)"))
            ;; Date.
            (progn
              (goto-char p)
-             (if (search-forward "\ndate: " nil t)
+             (if (search-forward "\ndate:" nil t)
                  (nnheader-header-value) ""))
            ;; Message-ID.
            (progn
@@ -4367,7 +5786,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            ;; References.
            (progn
              (goto-char p)
-             (if (search-forward "\nreferences: " nil t)
+             (if (search-forward "\nreferences:" nil t)
                  (progn
                    (setq end (point))
                    (prog1
@@ -4375,7 +5794,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                      (setq ref
                            (buffer-substring
                             (progn
-                              (end-of-line)
+                              ;; (end-of-line)
                               (search-backward ">" end t)
                               (1+ (point)))
                             (progn
@@ -4384,7 +5803,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                ;; Get the references from the in-reply-to header if there
                ;; were no references and the in-reply-to header looks
                ;; promising.
-               (if (and (search-forward "\nin-reply-to: " nil t)
+               (if (and (search-forward "\nin-reply-to:" nil t)
                         (setq in-reply-to (nnheader-header-value))
                         (string-match "<[^>]+>" in-reply-to))
                    (let (ref2)
@@ -4394,22 +5813,44 @@ The resulting hash table is returned, or nil if no Xrefs were found."
                        (setq ref2 (substring in-reply-to (match-beginning 0)
                                              (match-end 0)))
                        (when (> (length ref2) (length ref))
-                         (setq ref ref2))))
+                         (setq ref ref2)))
+                     ref)
                  (setq ref nil))))
            ;; Chars.
-           0
+           (progn
+             (goto-char p)
+             (if (search-forward "\nchars: " nil t)
+                 (if (numberp (setq chars (ignore-errors (read cur))))
+                     chars -1)
+               -1))
            ;; Lines.
            (progn
              (goto-char p)
              (if (search-forward "\nlines: " nil t)
                  (if (numberp (setq lines (ignore-errors (read cur))))
-                     lines 0)
-               0))
+                     lines -1)
+               -1))
            ;; Xref.
            (progn
              (goto-char p)
-             (and (search-forward "\nxref: " nil t)
-                  (nnheader-header-value)))))
+             (and (search-forward "\nxref:" nil t)
+                  (nnheader-header-value)))
+           ;; Extra.
+           (when gnus-extra-headers
+             (let ((extra gnus-extra-headers)
+                   out)
+               (while extra
+                 (goto-char p)
+                 (when (search-forward
+                        (concat "\n" (symbol-name (car extra)) ":") nil t)
+                   (push (cons (car extra) (nnheader-header-value)) out))
+                 (pop extra))
+               out))))
+         (goto-char p)
+         (if (and (search-forward "\ncontent-type: " nil t)
+                  (setq ctype (nnheader-header-value)))
+             (mime-entity-set-content-type-internal
+              header (mime-parse-Content-Type ctype)))
          (when (equal id ref)
            (setq ref nil))
 
@@ -4417,188 +5858,61 @@ The resulting hash table is returned, or nil if no Xrefs were found."
            (funcall gnus-alter-header-function header)
            (setq id (mail-header-id header)
                  ref (gnus-parent-id (mail-header-references header))))
-    
-         ;; We do the threading while we read the headers.  The
-         ;; message-id and the last reference are both entered into
-         ;; the same hash table.  Some tippy-toeing around has to be
-         ;; done in case an article has arrived before the article
-         ;; which it refers to.
-         (if (boundp (setq id-dep (intern id dependencies)))
-             (if (and (car (symbol-value id-dep))
-                      (not force-new))
-                 ;; An article with this Message-ID has already been seen.
-                 (if gnus-summary-ignore-duplicates
-                     ;; We ignore this one, except we add
-                     ;; any additional Xrefs (in case the two articles
-                     ;; came from different servers).
-                     (progn
-                       (mail-header-set-xref
-                        (car (symbol-value id-dep))
-                        (concat (or (mail-header-xref
-                                     (car (symbol-value id-dep)))
-                                    "")
-                                (or (mail-header-xref header) "")))
-                       (setq header nil))
-                   ;; We rename the Message-ID.
-                   (set
-                    (setq id-dep (intern (setq id (nnmail-message-id))
-                                         dependencies))
-                    (list header))
-                   (mail-header-set-id header id))
-               (setcar (symbol-value id-dep) header))
-           (set id-dep (list header)))
-         (when header
-           (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
-               (setcdr (symbol-value ref-dep)
-                       (nconc (cdr (symbol-value ref-dep))
-                              (list (symbol-value id-dep))))
-             (set ref-dep (list nil (symbol-value id-dep))))
+
+         (when (setq header
+                     (gnus-dependencies-add-header
+                      header dependencies force-new))
            (push header headers))
          (goto-char (point-max))
          (widen))
        (nreverse headers)))))
 
-;; The following macros and functions were written by Felix Lee
-;; <flee@cse.psu.edu>.
-
-(defmacro gnus-nov-read-integer ()
-  '(prog1
-       (if (= (following-char) ?\t)
-          0
-        (let ((num (ignore-errors (read buffer))))
-          (if (numberp num) num 0)))
-     (unless (eobp)
-       (search-forward "\t" eol 'move))))
-
-(defmacro gnus-nov-skip-field ()
-  '(search-forward "\t" eol 'move))
-
-(defmacro gnus-nov-field ()
-  '(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
-
-;; (defvar gnus-nov-none-counter 0)
-
-;; This function has to be called with point after the article number
-;; on the beginning of the line.
-(defun gnus-nov-parse-line (number dependencies &optional force-new)
-  (let ((eol (gnus-point-at-eol))
-       (buffer (current-buffer))
-       header ref id id-dep ref-dep)
-
-    ;; overview: [num subject from date id refs chars lines misc]
-    (unwind-protect
-       (progn
-         (narrow-to-region (point) eol)
-         (unless (eobp)
-           (forward-char))
-
-         (setq header
-               (vector
-                number                 ; number
-                (funcall
-                 gnus-unstructured-field-decoder (gnus-nov-field)) ; subject
-                (funcall
-                 gnus-structured-field-decoder (gnus-nov-field)) ; from
-                (gnus-nov-field)       ; date
-                (setq id (or (gnus-nov-field)
-                             (nnheader-generate-fake-message-id))) ; id
-                (progn
-                  (let ((beg (point)))
-                    (search-forward "\t" eol)
-                    (if (search-backward ">" beg t)
-                        (setq ref
-                              (buffer-substring
-                               (1+ (point))
-                               (or (search-backward "<" beg t) beg)))
-                      (setq ref nil))
-                    (goto-char beg))
-                  (gnus-nov-field))    ; refs
-                (gnus-nov-read-integer) ; chars
-                (gnus-nov-read-integer) ; lines
-                (if (= (following-char) ?\n)
-                    nil
-                  (gnus-nov-field))))) ; misc
-
-      (widen))
-
-    (when gnus-alter-header-function
-      (funcall gnus-alter-header-function header)
-      (setq id (mail-header-id header)
-           ref (gnus-parent-id (mail-header-references header))))
-    
-    ;; We build the thread tree.
-    (when (equal id ref)
-      ;; This article refers back to itself.  Naughty, naughty.
-      (setq ref nil))
-    (if (boundp (setq id-dep (intern id dependencies)))
-       (if (and (car (symbol-value id-dep))
-                (not force-new))
-           ;; An article with this Message-ID has already been seen.
-           (if gnus-summary-ignore-duplicates
-               ;; We ignore this one, except we add any additional
-               ;; Xrefs (in case the two articles came from different
-               ;; servers.
-               (progn
-                 (mail-header-set-xref
-                  (car (symbol-value id-dep))
-                  (concat (or (mail-header-xref
-                               (car (symbol-value id-dep)))
-                              "")
-                          (or (mail-header-xref header) "")))
-                 (setq header nil))
-             ;; We rename the Message-ID.
-             (set
-              (setq id-dep (intern (setq id (nnmail-message-id))
-                                   dependencies))
-              (list header))
-             (mail-header-set-id header id))
-         (setcar (symbol-value id-dep) header))
-      (set id-dep (list header)))
-    (when header
-      (if (boundp (setq ref-dep (intern (or ref "none") dependencies)))
-         (setcdr (symbol-value ref-dep)
-                 (nconc (cdr (symbol-value ref-dep))
-                        (list (symbol-value id-dep))))
-       (set ref-dep (list nil (symbol-value id-dep)))))
-    header))
-
 ;; Goes through the xover lines and returns a list of vectors
 (defun gnus-get-newsgroup-headers-xover (sequence &optional
                                                  force-new dependencies
                                                  group also-fetch-heads)
-  "Parse the news overview data in the server buffer, and return a
-list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
+  "Parse the news overview data in the server buffer.
+Return a list of headers that match SEQUENCE (see
+`nntp-retrieve-headers')."
   ;; Get the Xref when the users reads the articles since most/some
   ;; NNTP servers do not include Xrefs when using XOVER.
   (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
-  (let ((cur nntp-server-buffer)
+  (let ((mail-parse-charset gnus-newsgroup-charset)
+       (mail-parse-ignored-charsets gnus-newsgroup-ignored-charsets)
+       (cur nntp-server-buffer)
        (dependencies (or dependencies gnus-newsgroup-dependencies))
+       (allp (cond
+              ((eq gnus-read-all-available-headers t)
+               t)
+              ((stringp gnus-read-all-available-headers)
+               (string-match gnus-read-all-available-headers group))
+              (t
+               nil)))
        number headers header)
     (save-excursion
       (set-buffer nntp-server-buffer)
+      (subst-char-in-region (point-min) (point-max) ?\r ?  t)
       ;; Allow the user to mangle the headers before parsing them.
       (gnus-run-hooks 'gnus-parse-headers-hook)
       (goto-char (point-min))
-      (while (not (eobp))
-       (condition-case ()
-           (while (and sequence (not (eobp)))
-             (setq number (read cur))
-             (while (and sequence
-                         (< (car sequence) number))
-               (setq sequence (cdr sequence)))
-             (and sequence
-                  (eq number (car sequence))
-                  (progn
-                    (setq sequence (cdr sequence))
-                    (setq header (inline
-                                   (gnus-nov-parse-line
-                                    number dependencies force-new))))
-                  (push header headers))
-             (forward-line 1))
-         (error
-          (gnus-error 4 "Strange nov line (%d)"
-                      (count-lines (point-min) (point)))))
-       (forward-line 1))
+      (gnus-parse-without-error
+       (while (and (or sequence allp)
+                   (not (eobp)))
+         (setq number (read cur))
+         (when (not allp)
+           (while (and sequence
+                       (< (car sequence) number))
+             (setq sequence (cdr sequence))))
+         (when (and (or allp
+                        (and sequence
+                             (eq number (car sequence))))
+                    (progn
+                      (setq sequence (cdr sequence))
+                      (setq header (inline
+                                     (gnus-nov-parse-line
+                                      number dependencies force-new)))))
+           (push header headers))
+         (forward-line 1)))
       ;; A common bug in inn is that if you have posted an article and
       ;; then retrieves the active file, it will answer correctly --
       ;; the new article is included.  However, a NOV entry for the
@@ -4612,7 +5926,7 @@ list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
        (let ((gnus-nov-is-evil t))
          (nconc
           (nreverse headers)
-          (when (gnus-retrieve-headers sequence group)
+          (when (eq (gnus-retrieve-headers sequence group) 'headers)
             (gnus-get-newsgroup-headers))))))))
 
 (defun gnus-article-get-xrefs ()
@@ -4629,31 +5943,36 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
          (save-restriction
            (nnheader-narrow-to-headers)
            (goto-char (point-min))
-           (when (or (and (eq (downcase (following-char)) ?x)
+           (when (or (and (not (eobp))
+                          (eq (downcase (char-after)) ?x)
                           (looking-at "Xref:"))
                      (search-forward "\nXref:" nil t))
              (goto-char (1+ (match-end 0)))
-             (setq xref (buffer-substring (point)
-                                          (progn (end-of-line) (point))))
+             (setq xref (buffer-substring (point) (gnus-point-at-eol)))
              (mail-header-set-xref headers xref)))))))
 
 (defun gnus-summary-insert-subject (id &optional old-header use-old-header)
-  "Find article ID and insert the summary line for that article."
-  (let ((header (cond ((and old-header use-old-header)
-                      old-header)
-                     ((and (numberp id)
-                           (gnus-number-to-header id))
-                      (gnus-number-to-header id))
-                     (t
-                      (gnus-read-header id))))
-       (number (and (numberp id) id))
-       pos d)
+  "Find article ID and insert the summary line for that article.
+OLD-HEADER can either be a header or a line number to insert
+the subject line on."
+  (let* ((line (and (numberp old-header) old-header))
+        (old-header (and (vectorp old-header) old-header))
+        (header (cond ((and old-header use-old-header)
+                       old-header)
+                      ((and (numberp id)
+                            (gnus-number-to-header id))
+                       (gnus-number-to-header id))
+                      (t
+                       (gnus-read-header id))))
+        (number (and (numberp id) id))
+        d)
     (when header
       ;; Rebuild the thread that this article is part of and go to the
       ;; article we have fetched.
       (when (and (not gnus-show-threads)
                 old-header)
-       (when (setq d (gnus-data-find (mail-header-number old-header)))
+       (when (and number
+                  (setq d (gnus-data-find (mail-header-number old-header))))
          (goto-char (gnus-data-pos d))
          (gnus-data-remove
           number
@@ -4668,7 +5987,7 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
                  gnus-newsgroup-sparse))
       (setq gnus-newsgroup-ancient (delq number gnus-newsgroup-ancient))
       (push number gnus-newsgroup-limit)
-      (gnus-rebuild-thread (mail-header-id header))
+      (gnus-rebuild-thread (mail-header-id header) line)
       (gnus-summary-goto-subject number nil t))
     (when (and (numberp number)
               (> number 0))
@@ -4688,9 +6007,9 @@ This is meant to be called in `gnus-article-internal-prepare-hook'."
 ;;; Process/prefix in the summary buffer
 
 (defun gnus-summary-work-articles (n)
-  "Return a list of articles to be worked upon.         The prefix argument,
-the list of process marked articles, and the current article will be
-taken into consideration."
+  "Return a list of articles to be worked upon.
+The prefix argument, the list of process marked articles, and the
+current article will be taken into consideration."
   (save-excursion
     (set-buffer gnus-summary-buffer)
     (cond
@@ -4716,7 +6035,7 @@ taken into consideration."
       (let ((max (max (point) (mark)))
            articles article)
        (save-excursion
-         (goto-char (min (min (point) (mark))))
+         (goto-char (min (point) (mark)))
          (while
              (and
               (push (setq article (gnus-summary-article-number)) articles)
@@ -4733,6 +6052,20 @@ taken into consideration."
       ;; Just return the current article.
       (list (gnus-summary-article-number))))))
 
+(defmacro gnus-summary-iterate (arg &rest forms)
+  "Iterate over the process/prefixed articles and do FORMS.
+ARG is the interactive prefix given to the command.  FORMS will be
+executed with point over the summary line of the articles."
+  (let ((articles (make-symbol "gnus-summary-iterate-articles")))
+    `(let ((,articles (gnus-summary-work-articles ,arg)))
+       (while ,articles
+        (gnus-summary-goto-subject (car ,articles))
+        ,@forms
+        (pop ,articles)))))
+
+(put 'gnus-summary-iterate 'lisp-indent-function 1)
+(put 'gnus-summary-iterate 'edebug-form-spec '(form body))
+
 (defun gnus-summary-save-process-mark ()
   "Push the current set of process marked articles on the stack."
   (interactive)
@@ -4778,49 +6111,76 @@ If EXCLUDE-GROUP, do not go to this group."
       (gnus-group-best-unread-group exclude-group))))
 
 (defun gnus-summary-find-next (&optional unread article backward)
-  (if backward (gnus-summary-find-prev)
+  (if backward
+      (gnus-summary-find-prev unread article)
     (let* ((dummy (gnus-summary-article-intangible-p))
           (article (or article (gnus-summary-article-number)))
-          (arts (gnus-data-find-list article))
+          (data (gnus-data-find-list article))
           result)
       (when (and (not dummy)
                 (or (not gnus-summary-check-current)
                     (not unread)
-                    (not (gnus-data-unread-p (car arts)))))
-       (setq arts (cdr arts)))
+                    (not (gnus-data-unread-p (car data)))))
+       (setq data (cdr data)))
       (when (setq result
                  (if unread
                      (progn
-                       (while arts
-                         (when (gnus-data-unread-p (car arts))
-                           (setq result (car arts)
-                                 arts nil))
-                         (setq arts (cdr arts)))
+                       (while data
+                          (unless (memq (gnus-data-number (car data))
+                                        (cond
+                                        ((eq gnus-auto-goto-ignores
+                                             'always-undownloaded)
+                                         gnus-newsgroup-undownloaded)
+                                        (gnus-plugged
+                                         nil)
+                                        ((eq gnus-auto-goto-ignores
+                                             'unfetched)
+                                         gnus-newsgroup-unfetched)
+                                        ((eq gnus-auto-goto-ignores
+                                             'undownloaded)
+                                         gnus-newsgroup-undownloaded)))
+                            (when (gnus-data-unread-p (car data))
+                              (setq result (car data)
+                                    data nil)))
+                         (setq data (cdr data)))
                        result)
-                   (car arts)))
+                   (car data)))
        (goto-char (gnus-data-pos result))
        (gnus-data-number result)))))
 
 (defun gnus-summary-find-prev (&optional unread article)
   (let* ((eobp (eobp))
         (article (or article (gnus-summary-article-number)))
-        (arts (gnus-data-find-list article (gnus-data-list 'rev)))
+        (data (gnus-data-find-list article (gnus-data-list 'rev)))
         result)
     (when (and (not eobp)
               (or (not gnus-summary-check-current)
                   (not unread)
-                  (not (gnus-data-unread-p (car arts)))))
-      (setq arts (cdr arts)))
+                  (not (gnus-data-unread-p (car data)))))
+      (setq data (cdr data)))
     (when (setq result
                (if unread
                    (progn
-                     (while arts
-                       (when (gnus-data-unread-p (car arts))
-                         (setq result (car arts)
-                               arts nil))
-                       (setq arts (cdr arts)))
+                     (while data
+                        (unless (memq (gnus-data-number (car data))
+                                      (cond
+                                      ((eq gnus-auto-goto-ignores
+                                           'always-undownloaded)
+                                       gnus-newsgroup-undownloaded)
+                                      (gnus-plugged
+                                       nil)
+                                      ((eq gnus-auto-goto-ignores
+                                           'unfetched)
+                                       gnus-newsgroup-unfetched)
+                                      ((eq gnus-auto-goto-ignores
+                                           'undownloaded)
+                                       gnus-newsgroup-undownloaded)))
+                          (when (gnus-data-unread-p (car data))
+                            (setq result (car data)
+                                  data nil)))
+                       (setq data (cdr data)))
                      result)
-                 (car arts)))
+                 (car data)))
       (goto-char (gnus-data-pos result))
       (gnus-data-number result))))
 
@@ -4870,24 +6230,40 @@ If `gnus-auto-center-summary' is nil, or the article buffer isn't
 displayed, no centering will be performed."
   ;; Suggested by earle@mahendo.JPL.NASA.GOV (Greg Earle).
   ;; Recenter only when requested.  Suggested by popovich@park.cs.columbia.edu.
-  (let* ((top (cond ((< (window-height) 4) 0)
-                   ((< (window-height) 7) 1)
-                   (t 2)))
-        (height (1- (window-height)))
-        (bottom (save-excursion (goto-char (point-max))
-                                (forward-line (- height))
-                                (point)))
-        (window (get-buffer-window (current-buffer))))
-    ;; The user has to want it.
-    (when gnus-auto-center-summary
+  (interactive)
+  ;; The user has to want it.
+  (when gnus-auto-center-summary
+    (let* ((top (cond ((< (window-height) 4) 0)
+                     ((< (window-height) 7) 1)
+                     (t (if (numberp gnus-auto-center-summary)
+                            gnus-auto-center-summary
+                          2))))
+          (height (1- (window-height)))
+          (bottom (save-excursion (goto-char (point-max))
+                                  (forward-line (- height))
+                                  (point)))
+          (window (get-buffer-window (current-buffer))))
       (when (get-buffer-window gnus-article-buffer)
        ;; Only do recentering when the article buffer is displayed,
        ;; Set the window start to either `bottom', which is the biggest
        ;; possible valid number, or the second line from the top,
        ;; whichever is the least.
-       (set-window-start
-        window (min bottom (save-excursion
-                             (forward-line (- top)) (point)))))
+       (let ((top-pos (save-excursion (forward-line (- top)) (point))))
+         (if (> bottom top-pos)
+             ;; Keep the second line from the top visible
+             (set-window-start window top-pos t)
+           ;; Try to keep the bottom line visible; if it's partially
+           ;; obscured, either scroll one more line to make it fully
+           ;; visible, or revert to using TOP-POS.
+           (save-excursion
+             (goto-char (point-max))
+             (forward-line -1)
+             (let ((last-line-start (point)))
+               (goto-char bottom)
+               (set-window-start window (point) t)
+               (when (not (pos-visible-in-window-p last-line-start window))
+                 (forward-line 1)
+                 (set-window-start window (min (point) top-pos) t)))))))
       ;; Do horizontal recentering while we're at it.
       (when (and (get-buffer-window (current-buffer) t)
                 (not (eq gnus-auto-center-summary 'vertical)))
@@ -4927,13 +6303,16 @@ displayed, no centering will be performed."
       ;; If the range of read articles is a single range, then the
       ;; first unread article is the article after the last read
       ;; article.  Sounds logical, doesn't it?
-      (if (not (listp (cdr read)))
-         (setq first (1+ (cdr read)))
+      (if (and (not (listp (cdr read)))
+              (or (< (car read) (car active))
+                  (progn (setq read (list read))
+                         nil)))
+         (setq first (max (car active) (1+ (cdr read))))
        ;; `read' is a list of ranges.
        (when (/= (setq nlast (or (and (numberp (car read)) (car read))
                                  (caar read)))
                  1)
-         (setq first 1))
+         (setq first (car active)))
        (while read
          (when first
            (while (< first nlast)
@@ -4955,13 +6334,13 @@ displayed, no centering will be performed."
         (marked (gnus-info-marks info))
         (active (gnus-active group)))
     (and info active
-        (gnus-set-difference
-         (gnus-sorted-complement
-          (gnus-uncompress-range active)
-          (gnus-list-of-unread-articles group))
-         (append
-          (gnus-uncompress-range (cdr (assq 'dormant marked)))
-          (gnus-uncompress-range (cdr (assq 'tick marked))))))))
+        (gnus-list-range-difference
+         (gnus-list-range-difference
+          (gnus-sorted-complement
+           (gnus-uncompress-range active)
+           (gnus-list-of-unread-articles group))
+          (cdr (assq 'dormant marked)))
+         (cdr (assq 'tick marked))))))
 
 ;; Various summary commands
 
@@ -4984,8 +6363,7 @@ displayed, no centering will be performed."
          (key-binding
           (read-key-sequence
            (substitute-command-keys
-            "\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"
-            ))))
+            "\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"))))
         'undefined)
        (gnus-error 1 "Undefined key")
       (save-excursion
@@ -4998,29 +6376,49 @@ displayed, no centering will be performed."
 
 (defun gnus-summary-toggle-truncation (&optional arg)
   "Toggle truncation of summary lines.
-With arg, turn line truncation on iff arg is positive."
+With ARG, turn line truncation on if ARG is positive."
   (interactive "P")
   (setq truncate-lines
        (if (null arg) (not truncate-lines)
          (> (prefix-numeric-value arg) 0)))
   (redraw-display))
 
+(defun gnus-summary-find-for-reselect ()
+  "Return the number of an article to stay on across a reselect.
+The current article is considered, then following articles, then previous
+articles.  An article is sought which is not cancelled and isn't a temporary
+insertion from another group.  If there's no such then return a dummy 0."
+  (let (found)
+    (dolist (rev '(nil t))
+      (unless found      ; don't demand the reverse list if we don't need it
+        (let ((data (gnus-data-find-list
+                     (gnus-summary-article-number) (gnus-data-list rev))))
+          (while (and data (not found))
+            (if (and (< 0 (gnus-data-number (car data)))
+                     (not (eq gnus-canceled-mark (gnus-data-mark (car data)))))
+                (setq found (gnus-data-number (car data))))
+            (setq data (cdr data))))))
+    (or found 0)))
+
 (defun gnus-summary-reselect-current-group (&optional all rescan)
   "Exit and then reselect the current newsgroup.
 The prefix argument ALL means to select all articles."
   (interactive "P")
   (when (gnus-ephemeral-group-p gnus-newsgroup-name)
     (error "Ephemeral groups can't be reselected"))
-  (let ((current-subject (gnus-summary-article-number))
+  (let ((current-subject (gnus-summary-find-for-reselect))
        (group gnus-newsgroup-name))
     (setq gnus-newsgroup-begin nil)
-    (gnus-summary-exit)
+    (gnus-summary-exit nil 'leave-hidden)
     ;; We have to adjust the point of group mode buffer because
     ;; point was moved to the next unread newsgroup by exiting.
     (gnus-summary-jump-to-group group)
     (when rescan
       (save-excursion
-       (gnus-group-get-new-news-this-group 1)))
+       (save-window-excursion
+         ;; Don't show group contents.
+         (set-window-start (selected-window) (point-max))
+         (gnus-group-get-new-news-this-group 1))))
     (gnus-group-read-group all t)
     (gnus-summary-goto-subject current-subject nil t)))
 
@@ -5036,28 +6434,29 @@ The prefix argument ALL means to select all articles."
        (when gnus-newsgroup-kill-headers
          (setq gnus-newsgroup-killed
                (gnus-compress-sequence
-                (nconc
-                 (gnus-set-sorted-intersection
-                  (gnus-uncompress-range gnus-newsgroup-killed)
-                  (setq gnus-newsgroup-unselected
-                        (sort gnus-newsgroup-unselected '<)))
-                 (setq gnus-newsgroup-unreads
-                       (sort gnus-newsgroup-unreads '<)))
+                (gnus-sorted-union
+                 (gnus-list-range-intersection
+                  gnus-newsgroup-unselected gnus-newsgroup-killed)
+                 gnus-newsgroup-unreads)
                 t)))
        (unless (listp (cdr gnus-newsgroup-killed))
          (setq gnus-newsgroup-killed (list gnus-newsgroup-killed)))
        (let ((headers gnus-newsgroup-headers))
-         (when (and (not gnus-save-score)
-                    (not non-destructive))
-           (setq gnus-newsgroup-scored nil))
          ;; Set the new ranges of read articles.
          (save-excursion
            (set-buffer gnus-group-buffer)
            (gnus-undo-force-boundary))
          (gnus-update-read-articles
-          group (append gnus-newsgroup-unreads gnus-newsgroup-unselected))
+          group (gnus-sorted-union
+                 gnus-newsgroup-unreads gnus-newsgroup-unselected))
          ;; Set the current article marks.
-         (gnus-update-marks)
+         (let ((gnus-newsgroup-scored
+                (if (and (not gnus-save-score)
+                         (not non-destructive))
+                    nil
+                  gnus-newsgroup-scored)))
+           (save-excursion
+             (gnus-update-marks)))
          ;; Do the cross-ref thing.
          (when gnus-use-cross-reference
            (gnus-mark-xrefs-as-read group headers gnus-newsgroup-unreads))
@@ -5076,18 +6475,25 @@ If FORCE (the prefix), also save the .newsrc file(s)."
       (gnus-save-newsrc-file)
     (gnus-dribble-save)))
 
-(defun gnus-summary-exit (&optional temporary)
+(defun gnus-summary-exit (&optional temporary leave-hidden)
   "Exit reading current newsgroup, and then return to group selection mode.
-gnus-exit-group-hook is called with no arguments if that value is non-nil."
+`gnus-exit-group-hook' is called with no arguments if that value is non-nil."
   (interactive)
   (gnus-set-global-variables)
   (gnus-kill-save-kill-buffer)
   (gnus-async-halt-prefetch)
   (let* ((group gnus-newsgroup-name)
         (quit-config (gnus-group-quit-config gnus-newsgroup-name))
+        (gnus-group-is-exiting-p t)
         (mode major-mode)
-         (group-point nil)
+        (group-point nil)
         (buf (current-buffer)))
+    (unless quit-config
+      ;; Do adaptive scoring, and possibly save score files.
+      (when gnus-newsgroup-adaptive
+       (gnus-score-adaptive))
+      (when gnus-use-scoring
+       (gnus-score-save)))
     (gnus-run-hooks 'gnus-summary-prepare-exit-hook)
     ;; If we have several article buffers, we kill them at exit.
     (unless gnus-single-article-buffer
@@ -5101,17 +6507,14 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-dup-enter-articles))
     (when gnus-use-trees
       (gnus-tree-close group))
+    (when gnus-use-cache
+      (gnus-cache-write-active))
     ;; Remove entries for this group.
     (nnmail-purge-split-history (gnus-group-real-name group))
     ;; Make all changes in this group permanent.
     (unless quit-config
       (gnus-run-hooks 'gnus-exit-group-hook)
-      (gnus-summary-update-info)
-      ;; Do adaptive scoring, and possibly save score files.
-      (when gnus-newsgroup-adaptive
-       (gnus-score-adaptive))
-      (when gnus-use-scoring
-       (gnus-score-save)))
+      (gnus-summary-update-info))
     (gnus-close-group group)
     ;; Make sure where we were, and go to next newsgroup.
     (set-buffer gnus-group-buffer)
@@ -5133,29 +6536,45 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
        (setq gnus-article-current nil))
       (set-buffer buf)
       (if (not gnus-kill-summary-on-exit)
-         (gnus-deaden-summary)
+         (progn
+           (gnus-deaden-summary)
+           (setq mode nil))
        ;; We set all buffer-local variables to nil.  It is unclear why
        ;; this is needed, but if we don't, buffer-local variables are
        ;; not garbage-collected, it seems.  This would the lead to en
        ;; ever-growing Emacs.
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        (when (get-buffer gnus-article-buffer)
          (bury-buffer gnus-article-buffer))
        ;; We clear the global counterparts of the buffer-local
        ;; variables as well, just to be on the safe side.
        (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        ;; Return to group mode buffer.
        (when (eq mode 'gnus-summary-mode)
          (gnus-kill-buffer buf)))
       (setq gnus-current-select-method gnus-select-method)
-      (pop-to-buffer gnus-group-buffer)
-      ;; Clear the current group name.
+      (if leave-hidden
+         (set-buffer gnus-group-buffer)
+       (pop-to-buffer gnus-group-buffer))
       (if (not quit-config)
          (progn
            (goto-char group-point)
-           (gnus-configure-windows 'group 'force))
+           (unless leave-hidden
+             (gnus-configure-windows 'group 'force))
+           (unless (pos-visible-in-window-p)
+             (forward-line (/ (static-if (featurep 'xemacs)
+                                  (window-displayed-height)
+                                (1- (window-height)))
+                              -2))
+             (set-window-start (selected-window) (point))
+             (goto-char group-point)))
        (gnus-handle-ephemeral-exit quit-config))
+      ;; Clear the current group name.
       (unless quit-config
        (setq gnus-newsgroup-name nil)))))
 
@@ -5164,11 +6583,14 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
   "Quit reading current newsgroup without updating read article info."
   (interactive)
   (let* ((group gnus-newsgroup-name)
+        (gnus-group-is-exiting-p t)
+        (gnus-group-is-exiting-without-update-p t)
         (quit-config (gnus-group-quit-config group)))
     (when (or no-questions
              gnus-expert-user
              (gnus-y-or-n-p "Discard changes to this group and exit? "))
       (gnus-async-halt-prefetch)
+      (run-hooks 'gnus-summary-prepare-exit-hook)
       ;; If we have several article buffers, we kill them at exit.
       (unless gnus-single-article-buffer
        (gnus-kill-buffer gnus-article-buffer)
@@ -5178,10 +6600,13 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
          (gnus-deaden-summary)
        (gnus-close-group group)
        (gnus-summary-clear-local-variables)
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
        (set-buffer gnus-group-buffer)
        (gnus-summary-clear-local-variables)
-       (when (get-buffer gnus-summary-buffer)
-         (kill-buffer gnus-summary-buffer)))
+       (let ((gnus-summary-local-variables gnus-newsgroup-variables))
+         (gnus-summary-clear-local-variables))
+       (gnus-kill-buffer gnus-summary-buffer))
       (unless gnus-single-article-buffer
        (setq gnus-article-current nil))
       (when gnus-use-trees
@@ -5193,43 +6618,58 @@ gnus-exit-group-hook is called with no arguments if that value is non-nil."
       (gnus-configure-windows 'group 'force)
       ;; Clear the current group name.
       (setq gnus-newsgroup-name nil)
+      (unless (gnus-ephemeral-group-p group)
+       (gnus-group-update-group group))
       (when (equal (gnus-group-group-name) group)
        (gnus-group-next-unread-group 1))
       (when quit-config
-        (gnus-handle-ephemeral-exit quit-config)))))
+       (gnus-handle-ephemeral-exit quit-config)))))
 
 (defun gnus-handle-ephemeral-exit (quit-config)
-  "Handle movement when leaving an ephemeral group.  The state
-which existed when entering the ephemeral is reset."
+  "Handle movement when leaving an ephemeral group.
+The state which existed when entering the ephemeral is reset."
   (if (not (buffer-name (car quit-config)))
       (gnus-configure-windows 'group 'force)
     (set-buffer (car quit-config))
     (cond ((eq major-mode 'gnus-summary-mode)
-           (gnus-set-global-variables))
-          ((eq major-mode 'gnus-article-mode)
-           (save-excursion
-             ;; The `gnus-summary-buffer' variable may point
-             ;; to the old summary buffer when using a single
-             ;; article buffer.
-             (unless (gnus-buffer-live-p gnus-summary-buffer)
-               (set-buffer gnus-group-buffer))
-             (set-buffer gnus-summary-buffer)
-             (gnus-set-global-variables))))
+          (gnus-set-global-variables))
+         ((eq major-mode 'gnus-article-mode)
+          (save-excursion
+            ;; The `gnus-summary-buffer' variable may point
+            ;; to the old summary buffer when using a single
+            ;; article buffer.
+            (unless (gnus-buffer-live-p gnus-summary-buffer)
+              (set-buffer gnus-group-buffer))
+            (set-buffer gnus-summary-buffer)
+            (gnus-set-global-variables))))
     (if (or (eq (cdr quit-config) 'article)
-            (eq (cdr quit-config) 'pick))
-        (progn
-          ;; The current article may be from the ephemeral group
-          ;; thus it is best that we reload this article
-          (gnus-summary-show-article)
-          (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
-              (gnus-configure-windows 'pick 'force)
-            (gnus-configure-windows (cdr quit-config) 'force)))
+           (eq (cdr quit-config) 'pick))
+       (progn
+         ;; The current article may be from the ephemeral group
+         ;; thus it is best that we reload this article
+         ;;
+         ;; If we're exiting from a large digest, this can be
+         ;; extremely slow.  So, it's better not to reload it. -- jh.
+         ;;(gnus-summary-show-article)
+         (if (and (boundp 'gnus-pick-mode) (symbol-value 'gnus-pick-mode))
+             (gnus-configure-windows 'pick 'force)
+           (gnus-configure-windows (cdr quit-config) 'force)))
       (gnus-configure-windows (cdr quit-config) 'force))
     (when (eq major-mode 'gnus-summary-mode)
       (gnus-summary-next-subject 1 nil t)
       (gnus-summary-recenter)
       (gnus-summary-position-point))))
 
+(defun gnus-summary-preview-mime-message ()
+  "MIME decode and play this message."
+  (interactive)
+  (let ((gnus-break-pages nil)
+       (gnus-show-mime t))
+    (gnus-summary-select-article gnus-show-all-headers t))
+  (let ((w (get-buffer-window gnus-article-buffer)))
+    (when w
+      (select-window (get-buffer-window gnus-article-buffer)))))
+
 ;;; Dead summaries.
 
 (defvar gnus-dead-summary-mode-map nil)
@@ -5239,10 +6679,11 @@ which existed when entering the ephemeral is reset."
   (suppress-keymap gnus-dead-summary-mode-map)
   (substitute-key-definition
    'undefined 'gnus-summary-wake-up-the-dead gnus-dead-summary-mode-map)
-  (let ((keys '("\C-d" "\r" "\177" [delete])))
-    (while keys
-      (define-key gnus-dead-summary-mode-map
-       (pop keys) 'gnus-summary-wake-up-the-dead))))
+  (dolist (key '("\C-d" "\r" "\177" [delete]))
+    (define-key gnus-dead-summary-mode-map
+      key 'gnus-summary-wake-up-the-dead))
+  (dolist (key '("q" "Q"))
+    (define-key gnus-dead-summary-mode-map key 'bury-buffer)))
 
 (defvar gnus-dead-summary-mode nil
   "Minor mode for Gnus summary buffers.")
@@ -5276,7 +6717,8 @@ which existed when entering the ephemeral is reset."
       (rename-buffer
        (concat (substring name 0 (match-beginning 0)) "Dead "
               (substring name (match-beginning 0)))
-       t))))
+       t)
+      (bury-buffer))))
 
 (defun gnus-kill-or-deaden-summary (buffer)
   "Kill or deaden the summary BUFFER."
@@ -5287,19 +6729,20 @@ which existed when entering the ephemeral is reset."
        (set-buffer buffer)
        (gnus-kill-buffer gnus-article-buffer)
        (gnus-kill-buffer gnus-original-article-buffer)))
-    (cond (gnus-kill-summary-on-exit
-          (when (and gnus-use-trees
-                     (and (get-buffer buffer)
-                          (buffer-name (get-buffer buffer))))
-            (save-excursion
-              (set-buffer (get-buffer buffer))
-              (gnus-tree-close gnus-newsgroup-name)))
-          (gnus-kill-buffer buffer))
-         ((and (get-buffer buffer)
-               (buffer-name (get-buffer buffer)))
-          (save-excursion
-            (set-buffer buffer)
-            (gnus-deaden-summary))))))
+    (cond
+     ;; Kill the buffer.
+     (gnus-kill-summary-on-exit
+      (when (and gnus-use-trees
+                (gnus-buffer-exists-p buffer))
+       (save-excursion
+         (set-buffer buffer)
+         (gnus-tree-close gnus-newsgroup-name)))
+      (gnus-kill-buffer buffer))
+     ;; Deaden the buffer.
+     ((gnus-buffer-exists-p buffer)
+      (save-excursion
+       (set-buffer buffer)
+       (gnus-deaden-summary))))))
 
 (defun gnus-summary-wake-up-the-dead (&rest args)
   "Wake up the dead summary buffer."
@@ -5322,7 +6765,7 @@ in."
    (list
     (when current-prefix-arg
       (completing-read
-       "Faq dir: " (and (listp gnus-group-faq-directory)
+       "FAQ dir: " (and (listp gnus-group-faq-directory)
                        (mapcar (lambda (file) (list file))
                                gnus-group-faq-directory))))))
   (let (gnus-faq-buffer)
@@ -5339,15 +6782,14 @@ in."
 (defun gnus-summary-describe-briefly ()
   "Describe summary mode commands briefly."
   (interactive)
-  (gnus-message 6
-               (substitute-command-keys "\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select  \\[gnus-summary-next-unread-article]:Forward  \\[gnus-summary-prev-unread-article]:Backward  \\[gnus-summary-exit]:Exit  \\[gnus-info-find-node]:Run Info  \\[gnus-summary-describe-briefly]:This help")))
+  (gnus-message 6 (substitute-command-keys "\\<gnus-summary-mode-map>\\[gnus-summary-next-page]:Select  \\[gnus-summary-next-unread-article]:Forward  \\[gnus-summary-prev-unread-article]:Backward  \\[gnus-summary-exit]:Exit  \\[gnus-info-find-node]:Run Info       \\[gnus-summary-describe-briefly]:This help")))
 
 ;; Walking around group mode buffer from summary mode.
 
 (defun gnus-summary-next-group (&optional no-article target-group backward)
   "Exit current newsgroup and then select next unread newsgroup.
 If prefix argument NO-ARTICLE is non-nil, no article is selected
-initially.  If NEXT-GROUP, go to this group.  If BACKWARD, go to
+initially.  If TARGET-GROUP, go to this group.  If BACKWARD, go to
 previous group instead."
   (interactive "P")
   ;; Stop pre-fetching.
@@ -5384,9 +6826,10 @@ previous group instead."
        (let ((unreads (gnus-group-group-unread)))
          (if (and (or (eq t unreads)
                       (and unreads (not (zerop unreads))))
-                  (gnus-summary-read-group
-                   target-group nil no-article
-                   (and (buffer-name current-buffer) current-buffer)))
+                  (gnus-summary-read-group
+                   target-group nil no-article
+                   (and (buffer-name current-buffer) current-buffer)
+                   nil backward))
              (setq entered t)
            (setq current-group target-group
                  target-group nil)))))))
@@ -5399,35 +6842,56 @@ If prefix argument NO-ARTICLE is non-nil, no article is selected initially."
 
 ;; Walking around summary lines.
 
-(defun gnus-summary-first-subject (&optional unread)
-  "Go to the first unread subject.
-If UNREAD is non-nil, go to the first unread article.
-Returns the article selected or nil if there are no unread articles."
+(defun gnus-summary-first-subject (&optional unread undownloaded unseen)
+  "Go to the first subject satisfying any non-nil constraint.
+If UNREAD is non-nil, the article should be unread.
+If UNDOWNLOADED is non-nil, the article should be undownloaded.
+If UNSEEN is non-nil, the article should be unseen.
+Returns the article selected or nil if there are no matching articles."
   (interactive "P")
-  (prog1
-      (cond
-       ;; Empty summary.
-       ((null gnus-newsgroup-data)
-       (gnus-message 3 "No articles in the group")
-       nil)
-       ;; Pick the first article.
-       ((not unread)
-       (goto-char (gnus-data-pos (car gnus-newsgroup-data)))
-       (gnus-data-number (car gnus-newsgroup-data)))
-       ;; No unread articles.
-       ((null gnus-newsgroup-unreads)
-       (gnus-message 3 "No more unread articles")
-       nil)
-       ;; Find the first unread article.
-       (t
-       (let ((data gnus-newsgroup-data))
-         (while (and data
-                     (not (gnus-data-unread-p (car data))))
-           (setq data (cdr data)))
-         (when data
-           (goto-char (gnus-data-pos (car data)))
-           (gnus-data-number (car data))))))
-    (gnus-summary-position-point)))
+  (cond
+   ;; Empty summary.
+   ((null gnus-newsgroup-data)
+    (gnus-message 3 "No articles in the group")
+    nil)
+   ;; Pick the first article.
+   ((not (or unread undownloaded unseen))
+    (goto-char (gnus-data-pos (car gnus-newsgroup-data)))
+    (gnus-data-number (car gnus-newsgroup-data)))
+   ;; Find the first unread article.
+   (t
+    (let ((data gnus-newsgroup-data))
+      (while (and data
+                  (let ((num (gnus-data-number (car data))))
+                    (or (memq num gnus-newsgroup-unfetched)
+                        (not (or (and unread
+                                      (memq num gnus-newsgroup-unreads))
+                                 (and undownloaded
+                                      (memq num gnus-newsgroup-undownloaded))
+                                 (and unseen
+                                      (memq num gnus-newsgroup-unseen)))))))
+        (setq data (cdr data)))
+      (prog1
+          (if data
+              (progn
+                (goto-char (gnus-data-pos (car data)))
+                (gnus-data-number (car data)))
+            (gnus-message 3 "No more%s articles"
+                          (let* ((r (when unread " unread"))
+                                 (d (when undownloaded " undownloaded"))
+                                 (s (when unseen " unseen"))
+                                 (l (delq nil (list r d s))))
+                            (cond ((= 3 (length l))
+                                   (concat r "," d ", or" s))
+                                  ((= 2 (length l))
+                                   (concat (car l) ", or" (cadr l)))
+                                  ((= 1 (length l))
+                                   (car l))
+                                  (t
+                                   ""))))
+            nil
+            )
+        (gnus-summary-position-point))))))
 
 (defun gnus-summary-next-subject (n &optional unread dont-display)
   "Go to next N'th summary line.
@@ -5442,7 +6906,8 @@ returned."
                (if backward
                    (gnus-summary-find-prev unread)
                  (gnus-summary-find-next unread)))
-      (setq n (1- n)))
+      (unless (zerop (setq n (1- n)))
+       (gnus-summary-show-thread)))
     (when (/= 0 n)
       (gnus-message 7 "No more%s articles"
                    (if unread " unread" "")))
@@ -5467,16 +6932,29 @@ If optional argument UNREAD is non-nil, only unread article is selected."
   (interactive "p")
   (gnus-summary-next-subject (- n) t))
 
+(defun gnus-summary-goto-subjects (articles)
+  "Insert the subject header for ARTICLES in the current buffer."
+  (save-excursion
+    (dolist (article articles)
+      (gnus-summary-goto-subject article t)))
+  (gnus-summary-limit (append articles gnus-newsgroup-limit))
+  (gnus-summary-position-point))
 (defun gnus-summary-goto-subject (article &optional force silent)
   "Go the subject line of ARTICLE.
 If FORCE, also allow jumping to articles not currently shown."
   (interactive "nArticle number: ")
+  (unless (numberp article)
+    (error "Article %s is not a number" article))
   (let ((b (point))
        (data (gnus-data-find article)))
     ;; We read in the article if we have to.
     (and (not data)
         force
-        (gnus-summary-insert-subject article (and (vectorp force) force) t)
+        (gnus-summary-insert-subject
+         article
+         (if (or (numberp force) (vectorp force)) force)
+         t)
         (setq data (gnus-data-find article)))
     (goto-char b)
     (if (not data)
@@ -5484,7 +6962,10 @@ If FORCE, also allow jumping to articles not currently shown."
          (unless silent
            (gnus-message 3 "Can't find article %d" article))
          nil)
-      (goto-char (gnus-data-pos data))
+      (let ((pt (gnus-data-pos data)))
+       (goto-char pt)
+       (gnus-summary-set-article-display-arrow pt))
+      (gnus-summary-position-point)
       article)))
 
 ;; Walking around summary lines with displaying articles.
@@ -5499,13 +6980,24 @@ Given a prefix, will force an `article' buffer configuration."
 
 (defun gnus-summary-display-article (article &optional all-header)
   "Display ARTICLE in article buffer."
+  (when (gnus-buffer-live-p gnus-article-buffer)
+    (with-current-buffer gnus-article-buffer
+      (set-buffer-multibyte t)))
   (gnus-set-global-variables)
+  (when (gnus-buffer-live-p gnus-article-buffer)
+    (with-current-buffer gnus-article-buffer
+      (setq gnus-article-charset gnus-newsgroup-charset)
+      (setq gnus-article-ignored-charsets gnus-newsgroup-ignored-charsets)
+      (set-buffer-multibyte t)))
   (if (null article)
       nil
     (prog1
        (if gnus-summary-display-article-function
            (funcall gnus-summary-display-article-function article all-header)
          (gnus-article-prepare article all-header))
+      (with-current-buffer gnus-article-buffer
+       (set (make-local-variable 'gnus-summary-search-article-matched-data)
+            nil))
       (gnus-run-hooks 'gnus-select-article-hook)
       (when (and gnus-current-article
                 (not (zerop gnus-current-article)))
@@ -5529,35 +7021,41 @@ be displayed."
     (set-buffer gnus-summary-buffer))
   (let ((article (or article (gnus-summary-article-number)))
        (all-headers (not (not all-headers))) ;Must be T or NIL.
-       gnus-summary-display-article-function
-       did)
+       gnus-summary-display-article-function)
     (and (not pseudo)
         (gnus-summary-article-pseudo-p article)
         (error "This is a pseudo-article"))
-    (prog1
-       (save-excursion
-         (set-buffer gnus-summary-buffer)
-         (if (or (and gnus-single-article-buffer
-                      (or (null gnus-current-article)
-                          (null gnus-article-current)
-                          (null (get-buffer gnus-article-buffer))
-                          (not (eq article (cdr gnus-article-current)))
-                          (not (equal (car gnus-article-current)
-                                      gnus-newsgroup-name))))
-                 (and (not gnus-single-article-buffer)
-                      (or (null gnus-current-article)
-                          (not (eq gnus-current-article article))))
-                 force)
-             ;; The requested article is different from the current article.
-             (prog1
-                 (gnus-summary-display-article article all-headers)
-               (setq did article))
-           (when (or all-headers gnus-show-all-headers)
-             (gnus-article-show-all-headers))
-           'old))
-      (when did
-       (gnus-article-set-window-start
-        (cdr (assq article gnus-newsgroup-bookmarks)))))))
+    (save-excursion
+      (set-buffer gnus-summary-buffer)
+      (if (or (and gnus-single-article-buffer
+                  (or (null gnus-current-article)
+                      (null gnus-article-current)
+                      (null (get-buffer gnus-article-buffer))
+                      (not (eq article (cdr gnus-article-current)))
+                      (not (equal (car gnus-article-current)
+                                  gnus-newsgroup-name))))
+             (and (not gnus-single-article-buffer)
+                  (or (null gnus-current-article)
+                      (not (eq gnus-current-article article))))
+             force)
+         ;; The requested article is different from the current article.
+         (progn
+           (gnus-summary-display-article article all-headers)
+           (gnus-article-set-window-start
+            (cdr (assq article gnus-newsgroup-bookmarks)))
+           article)
+       'old))))
+
+(defun gnus-summary-force-verify-and-decrypt ()
+  "Display buttons for signed/encrypted parts and verify/decrypt them."
+  (interactive)
+  (let ((mm-verify-option 'known)
+       (mm-decrypt-option 'known)
+       (gnus-article-emulate-mime t)
+       (gnus-buttonized-mime-types (append (list "multipart/signed"
+                                                 "multipart/encrypted")
+                                           gnus-buttonized-mime-types)))
+    (gnus-summary-select-article nil 'force)))
 
 (defun gnus-summary-set-current-mark (&optional current-mark)
   "Obsolete function."
@@ -5586,7 +7084,7 @@ If BACKWARD, the previous article is selected instead of the next."
         (not unread) (not subject))
     (gnus-summary-goto-article
      (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
-     nil t))
+     nil (count-lines (point-min) (point))))
    ;; Go to next/previous group.
    (t
     (unless (gnus-ephemeral-group-p gnus-newsgroup-name)
@@ -5630,7 +7128,7 @@ If BACKWARD, the previous article is selected instead of the next."
   (let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
                      (?\C-p (gnus-group-prev-unread-group 1))))
        (cursor-in-echo-area t)
-       keve key group ended)
+       keve key group ended prompt)
     (save-excursion
       (set-buffer gnus-group-buffer)
       (goto-char start)
@@ -5639,19 +7137,20 @@ If BACKWARD, the previous article is selected instead of the next."
                (gnus-summary-best-group gnus-newsgroup-name)
              (gnus-summary-search-group backward gnus-keep-same-level))))
     (while (not ended)
-      (gnus-message
-       5 "No more%s articles%s" (if unread " unread" "")
-       (if (and group
-               (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
-          (format " (Type %s for %s [%s])"
-                  (single-key-description cmd) group
-                  (car (gnus-gethash group gnus-newsrc-hashtb)))
-        (format " (Type %s to exit %s)"
-                (single-key-description cmd)
-                gnus-newsgroup-name)))
+      (setq prompt
+           (format
+            "No more%s articles%s " (if unread " unread" "")
+            (if (and group
+                     (not (gnus-ephemeral-group-p gnus-newsgroup-name)))
+                (format " (Type %s for %s [%s])"
+                        (single-key-description cmd) group
+                        (car (gnus-gethash group gnus-newsrc-hashtb)))
+              (format " (Type %s to exit %s)"
+                      (single-key-description cmd)
+                      gnus-newsgroup-name))))
       ;; Confirm auto selection.
-      (setq key (car (setq keve (gnus-read-event-char))))
-      (setq ended t)
+      (setq key (car (setq keve (gnus-read-event-char prompt)))
+           ended t)
       (cond
        ((assq key keystrokes)
        (let ((obuf (current-buffer)))
@@ -5694,20 +7193,27 @@ If UNREAD is non-nil, only unread articles are selected."
    (and gnus-auto-select-same
        (gnus-summary-article-subject))))
 
-(defun gnus-summary-next-page (&optional lines circular)
+(defun gnus-summary-next-page (&optional lines circular stop)
   "Show next page of the selected article.
 If at the end of the current article, select the next article.
 LINES says how many lines should be scrolled up.
 
 If CIRCULAR is non-nil, go to the start of the article instead of
 selecting the next article when reaching the end of the current
-article."
+article.
+
+If STOP is non-nil, just stop when reaching the end of the message.
+
+Also see the variable `gnus-article-skip-boring'."
   (interactive "P")
   (setq gnus-summary-buffer (current-buffer))
   (gnus-set-global-variables)
   (let ((article (gnus-summary-article-number))
        (article-window (get-buffer-window gnus-article-buffer t))
        endp)
+    ;; If the buffer is empty, we have no article.
+    (unless article
+      (error "No article to select"))
     (gnus-configure-windows 'article)
     (if (eq (cdr (assq article gnus-newsgroup-reads)) gnus-canceled-mark)
        (if (and (eq gnus-summary-goto-unread 'never)
@@ -5722,9 +7228,12 @@ article."
          (gnus-summary-display-article article)
        (when article-window
          (gnus-eval-in-buffer-window gnus-article-buffer
-           (setq endp (gnus-article-next-page lines)))
+           (setq endp (or (gnus-article-next-page lines)
+                          (gnus-article-only-boring-p))))
          (when endp
-           (cond (circular
+           (cond (stop
+                  (gnus-message 3 "End of message"))
+                 (circular
                   (gnus-summary-beginning-of-article))
                  (lines
                   (gnus-message 3 "End of message"))
@@ -5789,6 +7298,12 @@ Argument LINES specifies lines to be scrolled up (or down if negative)."
   (gnus-summary-recenter)
   (gnus-summary-position-point))
 
+(defun gnus-summary-scroll-down (lines)
+  "Scroll down (or up) one line current article.
+Argument LINES specifies lines to be scrolled down (or up if negative)."
+  (interactive "p")
+  (gnus-summary-scroll-up (- lines)))
+
 (defun gnus-summary-next-same-subject ()
   "Select next article which has the same subject as current one."
   (interactive)
@@ -5820,19 +7335,65 @@ Return nil if there are no unread articles."
        (gnus-summary-display-article (gnus-summary-article-number)))
     (gnus-summary-position-point)))
 
+(defun gnus-summary-first-unread-subject ()
+  "Place the point on the subject line of the first unread article.
+Return nil if there are no unread articles."
+  (interactive)
+  (prog1
+      (when (gnus-summary-first-subject t)
+       (gnus-summary-show-thread)
+       (gnus-summary-first-subject t))
+    (gnus-summary-position-point)))
+
+(defun gnus-summary-first-unseen-subject ()
+  "Place the point on the subject line of the first unseen article.
+Return nil if there are no unseen articles."
+  (interactive)
+  (prog1
+      (when (gnus-summary-first-subject nil nil t)
+       (gnus-summary-show-thread)
+       (gnus-summary-first-subject nil nil t))
+    (gnus-summary-position-point)))
+
+(defun gnus-summary-first-unseen-or-unread-subject ()
+  "Place the point on the subject line of the first unseen article or,
+if all article have been seen, on the subject line of the first unread
+article."
+  (interactive)
+  (prog1
+      (unless (when (gnus-summary-first-subject nil nil t)
+               (gnus-summary-show-thread)
+               (gnus-summary-first-subject nil nil t))
+       (when (gnus-summary-first-subject t)
+         (gnus-summary-show-thread)
+         (gnus-summary-first-subject t)))
+    (gnus-summary-position-point)))
+
 (defun gnus-summary-first-article ()
   "Select the first article.
 Return nil if there are no articles."
   (interactive)
   (prog1
       (when (gnus-summary-first-subject)
-      (gnus-summary-show-thread)
-      (gnus-summary-first-subject)
-      (gnus-summary-display-article (gnus-summary-article-number)))
+       (gnus-summary-show-thread)
+       (gnus-summary-first-subject)
+       (gnus-summary-display-article (gnus-summary-article-number)))
     (gnus-summary-position-point)))
 
-(defun gnus-summary-best-unread-article ()
-  "Select the unread article with the highest score."
+(defun gnus-summary-best-unread-article (&optional arg)
+  "Select the unread article with the highest score.
+If given a prefix argument, select the next unread article that has a
+score higher than the default score."
+  (interactive "P")
+  (let ((article (if arg
+                    (gnus-summary-better-unread-subject)
+                  (gnus-summary-best-unread-subject))))
+    (if article
+       (gnus-summary-goto-article article)
+      (error "No unread articles"))))
+
+(defun gnus-summary-best-unread-subject ()
+  "Select the unread subject with the highest score."
   (interactive)
   (let ((best -1000000)
        (data gnus-newsgroup-data)
@@ -5845,11 +7406,25 @@ Return nil if there are no articles."
           (setq best score
                 article (gnus-data-number (car data))))
       (setq data (cdr data)))
-    (prog1
-       (if article
-           (gnus-summary-goto-article article)
-         (error "No unread articles"))
-      (gnus-summary-position-point))))
+    (when article
+      (gnus-summary-goto-subject article))
+    (gnus-summary-position-point)
+    article))
+
+(defun gnus-summary-better-unread-subject ()
+  "Select the first unread subject that has a score over the default score."
+  (interactive)
+  (let ((data gnus-newsgroup-data)
+       article score)
+    (while (and (setq article (gnus-data-number (car data)))
+               (or (gnus-data-read-p (car data))
+                   (not (> (gnus-summary-article-score article)
+                           gnus-summary-default-score))))
+      (setq data (cdr data)))
+    (when article
+      (gnus-summary-goto-subject article))
+    (gnus-summary-position-point)
+    article))
 
 (defun gnus-summary-last-subject ()
   "Go to the last displayed subject line in the group."
@@ -5859,7 +7434,9 @@ Return nil if there are no articles."
 
 (defun gnus-summary-goto-article (article &optional all-headers force)
   "Fetch ARTICLE (article number or Message-ID) and display it if it exists.
-If ALL-HEADERS is non-nil, no header lines are hidden."
+If ALL-HEADERS is non-nil, no header lines are hidden.
+If FORCE, go to the article even if it isn't displayed.  If FORCE
+is a number, it is the line the article is to be displayed on."
   (interactive
    (list
     (completing-read
@@ -5870,7 +7447,7 @@ If ALL-HEADERS is non-nil, no header lines are hidden."
     t))
   (prog1
       (if (and (stringp article)
-              (string-match "@" article))
+              (string-match "@\\|%40" article))
          (gnus-summary-refer-article article)
        (when (stringp article)
          (setq article (string-to-number article)))
@@ -5925,45 +7502,122 @@ If given a prefix, remove all limits."
       (gnus-summary-limit nil 'pop)
     (gnus-summary-position-point)))
 
-(defun gnus-summary-limit-to-subject (subject &optional header)
-  "Limit the summary buffer to articles that have subjects that match a regexp."
-  (interactive "sLimit to subject (regexp): ")
+(defun gnus-summary-limit-to-subject (subject &optional header not-matching)
+  "Limit the summary buffer to articles that have subjects that match a regexp.
+If NOT-MATCHING, excluding articles that have subjects that match a regexp."
+  (interactive
+   (list (read-string (if current-prefix-arg
+                         "Exclude subject (regexp): "
+                       "Limit to subject (regexp): "))
+        nil current-prefix-arg))
   (unless header
     (setq header "subject"))
   (when (not (equal "" subject))
     (prog1
        (let ((articles (gnus-summary-find-matching
-                        (or header "subject") subject 'all)))
+                        (or header "subject") subject 'all nil nil
+                        not-matching)))
          (unless articles
            (error "Found no matches for \"%s\"" subject))
          (gnus-summary-limit articles))
       (gnus-summary-position-point))))
 
-(defun gnus-summary-limit-to-author (from)
-  "Limit the summary buffer to articles that have authors that match a regexp."
-  (interactive "sLimit to author (regexp): ")
-  (gnus-summary-limit-to-subject from "from"))
+(defun gnus-summary-limit-to-author (from &optional not-matching)
+  "Limit the summary buffer to articles that have authors that match a regexp.
+If NOT-MATCHING, excluding articles that have authors that match a regexp."
+  (interactive
+   (list (read-string (if current-prefix-arg
+                         "Exclude author (regexp): "
+                       "Limit to author (regexp): "))
+        current-prefix-arg))
+  (gnus-summary-limit-to-subject from "from" not-matching))
 
 (defun gnus-summary-limit-to-age (age &optional younger-p)
   "Limit the summary buffer to articles that are older than (or equal) AGE days.
 If YOUNGER-P (the prefix) is non-nil, limit the summary buffer to
 articles that are younger than AGE days."
-  (interactive "nTime in days: \nP")
+  (interactive
+   (let ((younger current-prefix-arg)
+        (days-got nil)
+        days)
+     (while (not days-got)
+       (setq days (if younger
+                     (read-string "Limit to articles younger than (in days, older when negative): ")
+                   (read-string
+                    "Limit to articles older than (in days, younger when negative): ")))
+       (when (> (length days) 0)
+        (setq days (read days)))
+       (if (numberp days)
+          (progn
+            (setq days-got t)
+            (if (< days 0)
+                (progn
+                  (setq younger (not younger))
+                  (setq days (* days -1)))))
+        (message "Please enter a number.")
+        (sleep-for 1)))
+     (list days younger)))
   (prog1
       (let ((data gnus-newsgroup-data)
-           (cutoff (nnmail-days-to-time age))
+           (cutoff (days-to-time age))
            articles d date is-younger)
        (while (setq d (pop data))
          (when (and (vectorp (gnus-data-header d))
                     (setq date (mail-header-date (gnus-data-header d))))
-           (setq is-younger (nnmail-time-less
-                             (nnmail-time-since (nnmail-date-to-time date))
+           (setq is-younger (time-less-p
+                             (time-since (condition-case ()
+                                             (date-to-time date)
+                                           (error '(0 0))))
                              cutoff))
-           (when (if younger-p is-younger (not is-younger))
+           (when (if younger-p
+                     is-younger
+                   (not is-younger))
              (push (gnus-data-number d) articles))))
        (gnus-summary-limit (nreverse articles)))
     (gnus-summary-position-point)))
 
+(defun gnus-summary-limit-to-extra (header regexp &optional not-matching)
+  "Limit the summary buffer to articles that match an 'extra' header."
+  (interactive
+   (let ((header
+         (intern
+          (gnus-completing-read-with-default
+           (symbol-name (car gnus-extra-headers))
+           (if current-prefix-arg
+               "Exclude extra header:"
+             "Limit extra header:")
+           (mapcar (lambda (x)
+                     (cons (symbol-name x) x))
+                   gnus-extra-headers)
+           nil
+           t))))
+     (list header
+          (read-string (format "%s header %s (regexp): "
+                               (if current-prefix-arg "Exclude" "Limit to")
+                               header))
+          current-prefix-arg)))
+  (when (not (equal "" regexp))
+    (prog1
+       (let ((articles (gnus-summary-find-matching
+                        (cons 'extra header) regexp 'all nil nil
+                        not-matching)))
+         (unless articles
+           (error "Found no matches for \"%s\"" regexp))
+         (gnus-summary-limit articles))
+      (gnus-summary-position-point))))
+
+(defun gnus-summary-limit-to-display-predicate ()
+  "Limit the summary buffer to the predicated in the `display' group parameter."
+  (interactive)
+  (unless gnus-newsgroup-display
+    (error "There is no `display' group parameter"))
+  (let (articles)
+    (dolist (number gnus-newsgroup-articles)
+      (when (funcall gnus-newsgroup-display)
+       (push number articles)))
+    (gnus-summary-limit articles))
+  (gnus-summary-position-point))
+
 (defalias 'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
 (make-obsolete
  'gnus-summary-delete-marked-as-read 'gnus-summary-limit-to-unread)
@@ -5978,7 +7632,7 @@ If ALL is non-nil, limit strictly to unread articles."
      ;; Concat all the marks that say that an article is read and have
      ;; those removed.
      (list gnus-del-mark gnus-read-mark gnus-ancient-mark
-          gnus-killed-mark gnus-kill-file-mark
+          gnus-killed-mark gnus-spam-mark gnus-kill-file-mark
           gnus-low-score-mark gnus-expirable-mark
           gnus-canceled-mark gnus-catchup-mark gnus-sparse-mark
           gnus-duplicate-mark gnus-souped-mark)
@@ -5986,7 +7640,7 @@ If ALL is non-nil, limit strictly to unread articles."
 
 (defalias 'gnus-summary-delete-marked-with 'gnus-summary-limit-exclude-marks)
 (make-obsolete 'gnus-summary-delete-marked-with
-              'gnus-summary-limit-exlude-marks)
+              'gnus-summary-limit-exclude-marks)
 
 (defun gnus-summary-limit-exclude-marks (marks &optional reverse)
   "Exclude articles that are marked with MARKS (e.g. \"DK\").
@@ -6016,12 +7670,9 @@ Returns how many articles were removed."
        (gnus-summary-limit articles))
     (gnus-summary-position-point)))
 
-(defun gnus-summary-limit-to-score (&optional score)
+(defun gnus-summary-limit-to-score (score)
   "Limit to articles with score at or above SCORE."
-  (interactive "P")
-  (setq score (if score
-                 (prefix-numeric-value score)
-               (or gnus-summary-default-score 0)))
+  (interactive "NLimit to articles with score of at least: ")
   (let ((data gnus-newsgroup-data)
        articles)
     (while data
@@ -6033,15 +7684,45 @@ Returns how many articles were removed."
        (gnus-summary-limit articles)
       (gnus-summary-position-point))))
 
+(defun gnus-summary-limit-to-unseen ()
+  "Limit to unseen articles."
+  (interactive)
+  (prog1
+      (gnus-summary-limit gnus-newsgroup-unseen)
+    (gnus-summary-position-point)))
+
 (defun gnus-summary-limit-include-thread (id)
-  "Display all the hidden articles that in the current thread."
+  "Display all the hidden articles that is in the thread with ID in it.
+When called interactively, ID is the Message-ID of the current
+article."
   (interactive (list (mail-header-id (gnus-summary-article-header))))
   (let ((articles (gnus-articles-in-thread
                   (gnus-id-to-thread (gnus-root-id id)))))
     (prog1
        (gnus-summary-limit (nconc articles gnus-newsgroup-limit))
+      (gnus-summary-limit-include-matching-articles
+       "subject"
+       (regexp-quote (gnus-simplify-subject-re
+                     (mail-header-subject (gnus-id-to-header id)))))
+      (gnus-summary-position-point))))
+
+(defun gnus-summary-limit-include-matching-articles (header regexp)
+  "Display all the hidden articles that have HEADERs that match REGEXP."
+  (interactive (list (read-string "Match on header: ")
+                    (read-string "Regexp: ")))
+  (let ((articles (gnus-find-matching-articles header regexp)))
+    (prog1
+       (gnus-summary-limit (nconc articles gnus-newsgroup-limit))
       (gnus-summary-position-point))))
 
+(defun gnus-summary-insert-dormant-articles ()
+  "Insert all the dormant articles for this group into the current buffer."
+  (interactive)
+  (let ((gnus-verbose (max 6 gnus-verbose)))
+    (if (not gnus-newsgroup-dormant)
+       (gnus-message 3 "No cached articles for this group")
+      (gnus-summary-goto-subjects gnus-newsgroup-dormant))))
+
 (defun gnus-summary-limit-include-dormant ()
   "Display all the hidden articles that are marked as dormant.
 Note that this command only works on a subset of the articles currently
@@ -6088,14 +7769,17 @@ fetched for this group."
   "Mark all unread excluded articles as read.
 If ALL, mark even excluded ticked and dormants as read."
   (interactive "P")
-  (let ((articles (gnus-sorted-complement
+  (setq gnus-newsgroup-limit (sort gnus-newsgroup-limit '<))
+  (let ((articles (gnus-sorted-ndifference
                   (sort
                    (mapcar (lambda (h) (mail-header-number h))
                            gnus-newsgroup-headers)
                    '<)
-                  (sort gnus-newsgroup-limit '<)))
+                  gnus-newsgroup-limit))
        article)
-    (setq gnus-newsgroup-unreads gnus-newsgroup-limit)
+    (setq gnus-newsgroup-unreads
+         (gnus-sorted-intersection gnus-newsgroup-unreads
+                                   gnus-newsgroup-limit))
     (if all
        (setq gnus-newsgroup-dormant nil
              gnus-newsgroup-marked nil
@@ -6125,9 +7809,7 @@ If ALL, mark even excluded ticked and dormants as read."
     ;; according to the new limit.
     (gnus-summary-prepare)
     ;; Hide any threads, possibly.
-    (and gnus-show-threads
-        gnus-thread-hide-subtree
-        (gnus-summary-hide-all-threads))
+    (gnus-summary-maybe-hide-threads)
     ;; Try to return to the article you were at, or one in the
     ;; neighborhood.
     (when data
@@ -6143,6 +7825,7 @@ If ALL, mark even excluded ticked and dormants as read."
       ;; after the current one.
       (goto-char (point-max))
       (gnus-summary-find-prev))
+    (gnus-set-mode-line 'summary)
     ;; We return how many articles were removed from the summary
     ;; buffer as a result of the new limit.
     (- total (length gnus-newsgroup-data))))
@@ -6158,7 +7841,8 @@ If ALL, mark even excluded ticked and dormants as read."
 (defsubst gnus-cut-thread (thread)
   "Go forwards in the thread until we find an article that we want to display."
   (when (or (eq gnus-fetch-old-headers 'some)
-           (eq gnus-fetch-old-headers 'invisible)          
+           (eq gnus-fetch-old-headers 'invisible)
+           (numberp gnus-fetch-old-headers)
            (eq gnus-build-sparse-threads 'some)
            (eq gnus-build-sparse-threads 'more))
     ;; Deal with old-fetched headers and sparse threads.
@@ -6185,9 +7869,10 @@ If ALL, mark even excluded ticked and dormants as read."
   thread)
 
 (defun gnus-cut-threads (threads)
-  "Cut off all uninteresting articles from the beginning of threads."
+  "Cut off all uninteresting articles from the beginning of THREADS."
   (when (or (eq gnus-fetch-old-headers 'some)
            (eq gnus-fetch-old-headers 'invisible)
+           (numberp gnus-fetch-old-headers)
            (eq gnus-build-sparse-threads 'some)
            (eq gnus-build-sparse-threads 'more))
     (let ((th threads))
@@ -6204,7 +7889,9 @@ fetch-old-headers verbiage, and so on."
   ;; Most groups have nothing to remove.
   (if (or gnus-inhibit-limiting
          (and (null gnus-newsgroup-dormant)
+              (eq gnus-newsgroup-display 'gnus-not-ignore)
               (not (eq gnus-fetch-old-headers 'some))
+              (not (numberp gnus-fetch-old-headers))
               (not (eq gnus-fetch-old-headers 'invisible))
               (null gnus-summary-expunge-below)
               (not (eq gnus-build-sparse-threads 'some))
@@ -6242,7 +7929,8 @@ fetch-old-headers verbiage, and so on."
   ;; will really go down to a leaf article first, before slowly
   ;; working its way up towards the root.
   (when thread
-    (let ((children
+    (let* ((max-lisp-eval-depth 5000)
+          (children
           (if (cdr thread)
               (apply '+ (mapcar 'gnus-summary-limit-children
                                 (cdr thread)))
@@ -6258,7 +7946,8 @@ fetch-old-headers verbiage, and so on."
                 (zerop children))
            ;; If this is "fetch-old-headered" and there is no
            ;; visible children, then we don't want this article.
-           (and (eq gnus-fetch-old-headers 'some)
+           (and (or (eq gnus-fetch-old-headers 'some)
+                    (numberp gnus-fetch-old-headers))
                 (gnus-summary-article-ancient-p number)
                 (zerop children))
            ;; If this is "fetch-old-headered" and `invisible', then
@@ -6290,6 +7979,9 @@ fetch-old-headers verbiage, and so on."
                  (push (cons number gnus-low-score-mark)
                        gnus-newsgroup-reads)))
              t)
+           ;; Do the `display' group parameter.
+           (and gnus-newsgroup-display
+                (not (funcall gnus-newsgroup-display)))
            ;; Check NoCeM things.
            (if (and gnus-use-nocem
                     (gnus-nocem-unwanted-article-p
@@ -6347,7 +8039,8 @@ The difference between N and the number of articles fetched is returned."
            (set-buffer gnus-original-article-buffer)
            (nnheader-narrow-to-headers)
            (unless (setq ref (message-fetch-field "references"))
-             (setq ref (message-fetch-field "in-reply-to")))
+             (when (setq ref (message-fetch-field "in-reply-to"))
+               (setq ref (gnus-extract-message-id-from-in-reply-to ref))))
            (widen))
        (setq ref
              ;; It's not the current article, so we take a bet on
@@ -6392,44 +8085,50 @@ of what's specified by the `gnus-refer-thread-limit' variable."
   (interactive "P")
   (let ((id (mail-header-id (gnus-summary-article-header)))
        (limit (if limit (prefix-numeric-value limit)
-                gnus-refer-thread-limit))
-       fmethod root)
-    ;; We want to fetch LIMIT *old* headers, but we also have to
-    ;; re-fetch all the headers in the current buffer, because many of
-    ;; them may be undisplayed.  So we adjust LIMIT.
-    (when (numberp limit)
-      (incf limit (- gnus-newsgroup-end gnus-newsgroup-begin)))
+                gnus-refer-thread-limit)))
     (unless (eq gnus-fetch-old-headers 'invisible)
       (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
       ;; Retrieve the headers and read them in.
-      (if (eq (gnus-retrieve-headers
-              (list gnus-newsgroup-end) gnus-newsgroup-name limit)
+      (if (eq (if (numberp limit)
+                 (gnus-retrieve-headers
+                  (list (min
+                         (+ (mail-header-number
+                             (gnus-summary-article-header))
+                            limit)
+                         gnus-newsgroup-end))
+                  gnus-newsgroup-name (* limit 2))
+               ;; gnus-refer-thread-limit is t, i.e. fetch _all_
+               ;; headers.
+               (gnus-retrieve-headers (list gnus-newsgroup-end)
+                                      gnus-newsgroup-name limit))
              'nov)
          (gnus-build-all-threads)
-       (error "Can't fetch thread from backends that don't support NOV"))
+       (error "Can't fetch thread from back ends that don't support NOV"))
       (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name))
     (gnus-summary-limit-include-thread id)))
 
-(defun gnus-summary-refer-article (message-id &optional arg)
-  "Fetch an article specified by MESSAGE-ID.
-If ARG (the prefix), fetch the article using `gnus-refer-article-method'
-or `gnus-select-method', no matter what backend the article comes from."
-  (interactive "sMessage-ID: \nP")
+(defun gnus-summary-refer-article (message-id)
+  "Fetch an article specified by MESSAGE-ID."
+  (interactive "sMessage-ID: ")
   (when (and (stringp message-id)
             (not (zerop (length message-id))))
+    (setq message-id (gnus-replace-in-string message-id " " ""))
     ;; Construct the correct Message-ID if necessary.
     ;; Suggested by tale@pawl.rpi.edu.
     (unless (string-match "^<" message-id)
       (setq message-id (concat "<" message-id)))
     (unless (string-match ">$" message-id)
       (setq message-id (concat message-id ">")))
+    ;; People often post MIDs from URLs, so unhex it:
+    (unless (string-match "@" message-id)
+      (setq message-id (gnus-url-unhex-string message-id)))
     (let* ((header (gnus-id-to-header message-id))
           (sparse (and header
                        (gnus-summary-article-sparse-p
                         (mail-header-number header))
                        (memq (mail-header-number header)
                              gnus-newsgroup-limit)))
-          h)
+          number)
       (cond
        ;; If the article is present in the buffer we just go to it.
        ((and header
@@ -6442,35 +8141,62 @@ or `gnus-select-method', no matter what backend the article comes from."
          (when sparse
            (gnus-summary-update-article (mail-header-number header)))))
        (t
-       ;; We fetch the article
-       (let ((gnus-override-method
-              (cond ((gnus-news-group-p gnus-newsgroup-name)
-                     gnus-refer-article-method)
-                    (arg
-                     (or gnus-refer-article-method gnus-select-method))
-                    (t nil)))
-             number)
-         ;; Start the special refer-article method, if necessary.
-         (when (and gnus-refer-article-method
-                    (gnus-news-group-p gnus-newsgroup-name))
-           (gnus-check-server gnus-refer-article-method))
-         ;; Fetch the header, and display the article.
-         (if (setq number (gnus-summary-insert-subject message-id))
+       ;; We fetch the article.
+       (catch 'found
+         (dolist (gnus-override-method (gnus-refer-article-methods))
+           (when (and (gnus-check-server gnus-override-method)
+                      ;; Fetch the header,
+                      (setq number (gnus-summary-insert-subject message-id)))
+             ;; and display the article.
              (gnus-summary-select-article nil nil nil number)
-           (gnus-message 3 "Couldn't fetch article %s" message-id))))))))
+             (throw 'found t)))
+         (gnus-message 3 "Couldn't fetch article %s" message-id)))))))
+
+(defun gnus-refer-article-methods ()
+  "Return a list of referable methods."
+  (cond
+   ;; No method, so we default to current and native.
+   ((null gnus-refer-article-method)
+    (list gnus-current-select-method gnus-select-method))
+   ;; Current.
+   ((eq 'current gnus-refer-article-method)
+    (list gnus-current-select-method))
+   ;; List of select methods.
+   ((not (and (symbolp (car gnus-refer-article-method))
+             (assq (car gnus-refer-article-method) nnoo-definition-alist)))
+    (let (out)
+      (dolist (method gnus-refer-article-method)
+       (push (if (eq 'current method)
+                 gnus-current-select-method
+               method)
+             out))
+      (nreverse out)))
+   ;; One single select method.
+   (t
+    (list gnus-refer-article-method))))
 
 (defun gnus-summary-edit-parameters ()
   "Edit the group parameters of the current group."
+  (interactive)
   (gnus-group-edit-group gnus-newsgroup-name 'params))
 
+(defun gnus-summary-customize-parameters ()
+  "Customize the group parameters of the current group."
+  (interactive)
+  (gnus-group-customize gnus-newsgroup-name))
+
 (defun gnus-summary-enter-digest-group (&optional force)
   "Enter an nndoc group based on the current article.
 If FORCE, force a digest interpretation.  If not, try
 to guess what the document format is."
   (interactive "P")
   (let ((conf gnus-current-window-configuration))
-    (save-excursion
-      (gnus-summary-select-article))
+    (save-window-excursion
+      (save-excursion
+       (let (gnus-article-prepare-hook
+             gnus-display-mime-function
+             gnus-break-pages)
+         (gnus-summary-select-article))))
     (setq gnus-current-window-configuration conf)
     (let* ((name (format "%s-%d"
                         (gnus-group-prefixed-name
@@ -6481,11 +8207,21 @@ to guess what the document format is."
           (ogroup gnus-newsgroup-name)
           (params (append (gnus-info-params (gnus-get-info ogroup))
                           (list (cons 'to-group ogroup))
+                          (list (cons 'parent-group ogroup))
                           (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 (gnus-fetch-field "reply-to")
+                                  (gnus-fetch-field "from")))
+         (setq params (append
+                       (list (cons 'to-address
+                                   (funcall gnus-decode-encoded-word-function
+                                            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
@@ -6494,21 +8230,27 @@ to guess what the document format is."
         (goto-char (point-min))
         (or (search-forward "\n\n" nil t) (point)))
        (goto-char (point-min))
-       (delete-matching-lines "^\\(Path\\):\\|^From ")
+       (delete-matching-lines "^Path:\\|^From ")
        (widen))
       (unwind-protect
-          (if (gnus-group-read-ephemeral-group
-               name `(nndoc ,name (nndoc-address ,(get-buffer dig))
-                            (nndoc-article-type
-                             ,(if force 'digest 'guess))) t)
-              ;; Make all postings to this group go to the parent group.
-              (nconc (gnus-info-params (gnus-get-info name))
-                     params)
-            ;; Couldn't select this doc group.
-            (switch-to-buffer buf)
-            (gnus-set-global-variables)
-            (gnus-configure-windows 'summary)
-            (gnus-message 3 "Article couldn't be entered?"))
+         (if (let ((gnus-newsgroup-ephemeral-charset gnus-newsgroup-charset)
+                   (gnus-newsgroup-ephemeral-ignored-charsets
+                    gnus-newsgroup-ignored-charsets))
+               (gnus-group-read-ephemeral-group
+                name `(nndoc ,name (nndoc-address ,(get-buffer dig))
+                             (nndoc-article-type
+                              ,(if force 'mbox 'guess)))
+                t nil nil nil
+                `((adapt-file . ,(gnus-score-file-name gnus-newsgroup-name
+                                                       "ADAPT")))))
+             ;; Make all postings to this group go to the parent group.
+             (nconc (gnus-info-params (gnus-get-info name))
+                    params)
+           ;; Couldn't select this doc group.
+           (switch-to-buffer buf)
+           (gnus-set-global-variables)
+           (gnus-configure-windows 'summary)
+           (gnus-message 3 "Article couldn't be entered?"))
        (kill-buffer dig)))))
 
 (defun gnus-summary-read-document (n)
@@ -6527,7 +8269,7 @@ Obeys the standard process/prefix convention."
       (gnus-summary-remove-process-mark article)
       (when (gnus-summary-display-article article)
        (save-excursion
-         (nnheader-temp-write nil
+         (with-temp-buffer
            (insert-buffer-substring gnus-original-article-buffer)
            ;; Remove some headers that may lead nndoc to make
            ;; the wrong guess.
@@ -6565,12 +8307,16 @@ Obeys the standard process/prefix convention."
   "Do incremental search forward on the current article.
 If REGEXP-P (the prefix) is non-nil, do regexp isearch."
   (interactive "P")
-  (gnus-summary-select-article)
-  (gnus-configure-windows 'article)
-  (gnus-eval-in-buffer-window gnus-article-buffer
-    (save-restriction
-      (widen)
-      (isearch-forward regexp-p))))
+  (let* ((gnus-inhibit-treatment t)
+        (old (gnus-summary-select-article)))
+    (gnus-configure-windows 'article)
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-restriction
+       (widen)
+       (when (eq 'old old)
+         (gnus-article-show-all-headers))
+       (goto-char (point-min))
+       (isearch-forward regexp-p)))))
 
 (defun gnus-summary-search-article-forward (regexp &optional backward)
   "Search for an article containing REGEXP forward.
@@ -6585,10 +8331,14 @@ If BACKWARD, search backward instead."
         current-prefix-arg))
   (if (string-equal regexp "")
       (setq regexp (or gnus-last-search-regexp ""))
-    (setq gnus-last-search-regexp regexp))
-  (if (gnus-summary-search-article regexp backward)
-      (gnus-summary-show-thread)
-    (error "Search failed: \"%s\"" regexp)))
+    (setq gnus-last-search-regexp regexp)
+    (setq gnus-article-before-search gnus-current-article))
+  ;; Intentionally set gnus-last-article.
+  (setq gnus-last-article gnus-article-before-search)
+  (let ((gnus-last-article gnus-last-article))
+    (if (gnus-summary-search-article regexp backward)
+       (gnus-summary-show-thread)
+      (error "Search failed: \"%s\"" regexp))))
 
 (defun gnus-summary-search-article-backward (regexp)
   "Search for an article containing REGEXP backward."
@@ -6600,6 +8350,84 @@ If BACKWARD, search backward instead."
                    "")))))
   (gnus-summary-search-article-forward regexp 'backward))
 
+(eval-when-compile
+  (defmacro gnus-summary-search-article-position-point (regexp backward)
+    "Dehighlight the last matched text and goto the beginning position."
+    (` (if (and gnus-summary-search-article-matched-data
+               (let ((text (caddr gnus-summary-search-article-matched-data))
+                     (inhibit-read-only t)
+                     buffer-read-only)
+                 (delete-region
+                  (goto-char (car gnus-summary-search-article-matched-data))
+                  (cadr gnus-summary-search-article-matched-data))
+                 (insert text)
+                 (string-match (, regexp) text)))
+          (if (, backward) (beginning-of-line) (end-of-line))
+        (goto-char (if (, backward) (point-max) (point-min))))))
+
+  (defmacro gnus-summary-search-article-highlight-goto-x-face (opoint)
+    "Place point where X-Face image is displayed."
+    (if (featurep 'xemacs)
+       (` (let ((end (if (search-forward "\n\n" nil t)
+                         (goto-char (1- (point)))
+                       (point-min)))
+                extent)
+            (or (search-backward "\n\n" nil t) (goto-char (point-min)))
+            (unless (and (re-search-forward "^From:" end t)
+                         (setq extent (extent-at (point)))
+                         (extent-begin-glyph extent))
+              (goto-char (, opoint)))))
+      (` (let ((end (if (search-forward "\n\n" nil t)
+                       (goto-char (1- (point)))
+                     (point-min)))
+              (start (or (search-backward "\n\n" nil t) (point-min))))
+          (goto-char
+           (or (text-property-any start end 'x-face-image t);; x-face-e21
+               (text-property-any start end 'x-face-mule-bitmap-image t)
+               (, opoint)))))))
+
+  (defmacro gnus-summary-search-article-highlight-matched-text
+    (backward treated x-face)
+    "Highlight matched text in the function `gnus-summary-search-article'."
+    (` (let ((start (set-marker (make-marker) (match-beginning 0)))
+            (end (set-marker (make-marker) (match-end 0)))
+            (inhibit-read-only t)
+            buffer-read-only)
+        (unless treated
+          (let ((,@
+                 (let ((items (mapcar 'car gnus-treatment-function-alist)))
+                   (mapcar
+                    (lambda (item) (setq items (delq item items)))
+                    '(gnus-treat-buttonize
+                      gnus-treat-fill-article
+                      gnus-treat-fill-long-lines
+                      gnus-treat-emphasize
+                      gnus-treat-highlight-headers
+                      gnus-treat-highlight-citation
+                      gnus-treat-highlight-signature
+                      gnus-treat-overstrike
+                      gnus-treat-display-x-face
+                      gnus-treat-buttonize-head
+                      gnus-treat-decode-article-as-default-mime-charset))
+                   (static-if (featurep 'xemacs)
+                       items
+                     (cons '(x-face-mule-delete-x-face-field
+                             (quote never))
+                           items))))
+                (gnus-treat-display-x-face
+                 (when (, x-face) gnus-treat-display-x-face)))
+            (gnus-article-prepare-mime-display)))
+        (goto-char (if (, backward) start end))
+        (when (, x-face)
+          (gnus-summary-search-article-highlight-goto-x-face (point)))
+        (setq gnus-summary-search-article-matched-data
+              (list start end (buffer-substring start end)))
+        (unless (eq start end);; matched text has been deleted. :-<
+          (put-text-property start end 'face
+                             (or (find-face 'isearch)
+                                 'secondary-selection))))))
+  )
+
 (defun gnus-summary-search-article (regexp &optional backward)
   "Search for an article containing REGEXP.
 Optional argument BACKWARD means do search for backward.
@@ -6607,20 +8435,52 @@ Optional argument BACKWARD means do search for backward.
   ;; We have to require this here to make sure that the following
   ;; dynamic binding isn't shadowed by autoloading.
   (require 'gnus-async)
+  (require 'gnus-art)
   (let ((gnus-select-article-hook nil) ;Disable hook.
-       (gnus-article-display-hook nil)
+       (gnus-article-prepare-hook nil)
        (gnus-mark-article-hook nil)    ;Inhibit marking as read.
        (gnus-use-article-prefetch nil)
        (gnus-xmas-force-redisplay nil) ;Inhibit XEmacs redisplay.
        (gnus-use-trees nil)            ;Inhibit updating tree buffer.
+       (gnus-visual nil)
+       (gnus-keep-backlog nil)
+       (gnus-break-pages nil)
+       (gnus-summary-display-arrow nil)
+       (gnus-updated-mode-lines nil)
+       (gnus-auto-center-summary nil)
        (sum (current-buffer))
        (found nil)
-       point)
+       point treated)
     (gnus-save-hidden-threads
-      (gnus-summary-select-article)
+      (static-if (featurep 'xemacs)
+         (let ((gnus-inhibit-treatment t))
+           (setq treated (eq 'old (gnus-summary-select-article)))
+           (when (and treated
+                      (not (and (gnus-buffer-live-p gnus-article-buffer)
+                                (window-live-p (get-buffer-window
+                                                gnus-article-buffer t)))))
+             (gnus-summary-select-article nil t)
+             (setq treated nil)))
+       (let ((gnus-inhibit-treatment t)
+             (x-face-mule-delete-x-face-field 'never))
+         (setq treated (eq 'old (gnus-summary-select-article)))
+         (when (and treated
+                    (not
+                     (and (gnus-buffer-live-p gnus-article-buffer)
+                          (window-live-p (get-buffer-window
+                                          gnus-article-buffer t))
+                          (or (not (string-match "^\\^X-Face:" regexp))
+                              (with-current-buffer gnus-article-buffer
+                                gnus-summary-search-article-matched-data)))))
+           (gnus-summary-select-article nil t)
+           (setq treated nil))))
       (set-buffer gnus-article-buffer)
-      (when backward
-       (forward-line -1))
+      (widen)
+      (if treated
+         (progn
+           (gnus-article-show-all-headers)
+           (gnus-summary-search-article-position-point regexp backward))
+       (goto-char (if backward (point-max) (point-min))))
       (while (not found)
        (gnus-message 7 "Searching article: %d..." (cdr gnus-article-current))
        (if (if backward
@@ -6628,12 +8488,16 @@ Optional argument BACKWARD means do search for backward.
              (re-search-forward regexp nil t))
            ;; We found the regexp.
            (progn
+             (gnus-summary-search-article-highlight-matched-text
+              backward treated (string-match "^\\^X-Face:" regexp))
              (setq found 'found)
-             (beginning-of-line)
+             (forward-line
+              (/ (- 2 (window-height
+                       (get-buffer-window gnus-article-buffer t)))
+                 2))
              (set-window-start
               (get-buffer-window (current-buffer))
               (point))
-             (forward-line 1)
              (set-buffer sum)
              (setq point (point)))
          ;; We didn't find it, so we go to the next article.
@@ -6648,7 +8512,9 @@ Optional argument BACKWARD means do search for backward.
              (unless (gnus-summary-article-sparse-p
                       (gnus-summary-article-number))
                (setq found nil)
-               (gnus-summary-select-article)
+               (let ((gnus-inhibit-treatment t))
+                 (gnus-summary-select-article))
+               (setq treated nil)
                (set-buffer gnus-article-buffer)
                (widen)
                (goto-char (if backward (point-max) (point-min))))))))
@@ -6661,30 +8527,54 @@ Optional argument BACKWARD means do search for backward.
       (gnus-summary-position-point)
       t)))
 
+(defun gnus-find-matching-articles (header regexp)
+  "Return a list of all articles that match REGEXP on HEADER.
+This search includes all articles in the current group that Gnus has
+fetched headers for, whether they are displayed or not."
+  (let ((articles nil)
+       (func `(lambda (h) (,(intern (concat "mail-header-" header)) h)))
+       (case-fold-search t))
+    (dolist (header gnus-newsgroup-headers)
+      (when (string-match regexp (funcall func header))
+       (push (mail-header-number header) articles)))
+    (nreverse articles)))
+
 (defun gnus-summary-find-matching (header regexp &optional backward unread
-                                         not-case-fold)
+                                         not-case-fold not-matching)
   "Return a list of all articles that match REGEXP on HEADER.
 The search stars on the current article and goes forwards unless
 BACKWARD is non-nil.  If BACKWARD is `all', do all articles.
 If UNREAD is non-nil, only unread articles will
 be taken into consideration.  If NOT-CASE-FOLD, case won't be folded
-in the comparisons."
-  (let ((data (if (eq backward 'all) gnus-newsgroup-data
-               (gnus-data-find-list
-                (gnus-summary-article-number) (gnus-data-list backward))))
-       (func `(lambda (h) (,(intern (concat "mail-header-" header)) h)))
-       (case-fold-search (not not-case-fold))
-       articles d)
-    (unless (fboundp (intern (concat "mail-header-" header)))
-      (error "%s is not a valid header" header))
-    (while data
-      (setq d (car data))
-      (and (or (not unread)            ; We want all articles...
-              (gnus-data-unread-p d))  ; Or just unreads.
-          (vectorp (gnus-data-header d)) ; It's not a pseudo.
-          (string-match regexp (funcall func (gnus-data-header d))) ; Match.
-          (push (gnus-data-number d) articles)) ; Success!
-      (setq data (cdr data)))
+in the comparisons. If NOT-MATCHING, return a list of all articles that
+not match REGEXP on HEADER."
+  (let ((case-fold-search (not not-case-fold))
+       articles d func)
+    (if (consp header)
+       (if (eq (car header) 'extra)
+           (setq func
+                 `(lambda (h)
+                    (or (cdr (assq ',(cdr header) (mail-header-extra h)))
+                        "")))
+         (error "%s is an invalid header" header))
+      (unless (fboundp (intern (concat "mail-header-" header)))
+       (error "%s is not a valid header" header))
+      (setq func `(lambda (h) (,(intern (concat "mail-header-" header)) h))))
+    (dolist (d (if (eq backward 'all)
+                  gnus-newsgroup-data
+                (gnus-data-find-list
+                 (gnus-summary-article-number)
+                 (gnus-data-list backward))))
+      (when (and (or (not unread)      ; We want all articles...
+                    (gnus-data-unread-p d)) ; Or just unreads.
+                (vectorp (gnus-data-header d)) ; It's not a pseudo.
+                (if not-matching
+                    (not (string-match
+                          regexp
+                          (funcall func (gnus-data-header d))))
+                  (string-match regexp
+                                (funcall func (gnus-data-header d)))))
+       (push (gnus-data-number d) articles))) ; Success!
     (nreverse articles)))
 
 (defun gnus-summary-execute-command (header regexp command &optional backward)
@@ -6695,9 +8585,11 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
    (list (let ((completion-ignore-case t))
           (completing-read
            "Header name: "
-           (mapcar (lambda (string) (list string))
-                   '("Number" "Subject" "From" "Lines" "Date"
-                     "Message-ID" "Xref" "References" "Body"))
+           (mapcar (lambda (header) (list (format "%s" header)))
+                   (append
+                    '("Number" "Subject" "From" "Lines" "Date"
+                      "Message-ID" "Xref" "References" "Body")
+                    gnus-extra-headers))
            nil 'require-match))
         (read-string "Regexp: ")
         (read-key-sequence "Command: ")
@@ -6709,12 +8601,19 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   ;; We don't want to change current point nor window configuration.
   (save-excursion
     (save-window-excursion
-      (gnus-message 6 "Executing %s..." (key-description command))
-      ;; We'd like to execute COMMAND interactively so as to give arguments.
-      (gnus-execute header regexp
-                   `(call-interactively ',(key-binding command))
-                   backward)
-      (gnus-message 6 "Executing %s...done" (key-description command)))))
+      (let (gnus-visual
+           gnus-treat-strip-trailing-blank-lines
+           gnus-treat-strip-leading-blank-lines
+           gnus-treat-strip-multiple-blank-lines
+           gnus-treat-hide-boring-headers
+           gnus-treat-fold-newsgroups
+           gnus-article-prepare-hook)
+       (gnus-message 6 "Executing %s..." (key-description command))
+       ;; We'd like to execute COMMAND interactively so as to give arguments.
+       (gnus-execute header regexp
+                     `(call-interactively ',(key-binding command))
+                     backward)
+       (gnus-message 6 "Executing %s...done" (key-description command))))))
 
 (defun gnus-summary-beginning-of-article ()
   "Scroll the article back to the beginning."
@@ -6724,7 +8623,7 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
   (gnus-eval-in-buffer-window gnus-article-buffer
     (widen)
     (goto-char (point-min))
-    (when gnus-page-broken
+    (when gnus-break-pages
       (gnus-narrow-to-page))))
 
 (defun gnus-summary-end-of-article ()
@@ -6736,64 +8635,152 @@ article.  If BACKWARD (the prefix) is non-nil, search backward instead."
     (widen)
     (goto-char (point-max))
     (recenter -3)
-    (when gnus-page-broken
+    (when gnus-break-pages
+      (when (re-search-backward page-delimiter nil t)
+       (narrow-to-region (match-end 0) (point-max)))
       (gnus-narrow-to-page))))
 
+(defun gnus-summary-print-truncate-and-quote (string &optional len)
+  "Truncate to LEN and quote all \"(\"'s in STRING."
+  (gnus-replace-in-string (if (and len (> (length string) len))
+                             (substring string 0 len)
+                           string)
+                         "[()]" "\\\\\\&"))
+
 (defun gnus-summary-print-article (&optional filename n)
-  "Generate and print a PostScript image of the N next (mail) articles.
+  "Generate and print a PostScript image of the process-marked (mail) articles.
+
+If used interactively, print the current article if none are
+process-marked.  With prefix arg, prompt the user for the name of the
+file to save in.
 
-If N is negative, print the N previous articles.  If N is nil and articles
-have been marked with the process mark, print these instead.
+When used from Lisp, accept two optional args FILENAME and N.  N means
+to print the next N articles.  If N is negative, print the N previous
+articles.  If N is nil and articles have been marked with the process
+mark, print these instead.
 
-If the optional second argument FILENAME is nil, send the image to the
+If the optional first argument FILENAME is nil, send the image to the
 printer.  If FILENAME is a string, save the PostScript image in a file with
 that name.  If FILENAME is a number, prompt the user for the name of the file
 to save in."
-  (interactive (list (ps-print-preprint current-prefix-arg)
-                    current-prefix-arg))
+  (interactive (list (ps-print-preprint current-prefix-arg)))
   (dolist (article (gnus-summary-work-articles n))
     (gnus-summary-select-article nil nil 'pseudo article)
     (gnus-eval-in-buffer-window gnus-article-buffer
-      (let ((buffer (generate-new-buffer " *print*")))
-       (unwind-protect
-           (progn
-             (copy-to-buffer buffer (point-min) (point-max))
-             (set-buffer buffer)
-             (gnus-article-delete-invisible-text)
-             (let ((ps-left-header
-                    (list 
-                     (concat "("
-                             (mail-header-subject gnus-current-headers) ")")
-                     (concat "("
-                             (mail-header-from gnus-current-headers) ")")))
-                   (ps-right-header 
-                    (list 
-                     "/pagenumberstring load" 
-                     (concat "("
-                             (mail-header-date gnus-current-headers) ")"))))
-               (gnus-run-hooks 'gnus-ps-print-hook)
-               (ps-print-buffer-with-faces filename)))
-         (kill-buffer buffer))))))
+      (gnus-print-buffer))
+    (gnus-summary-remove-process-mark article))
+  (ps-despool filename))
+
+(defun gnus-print-buffer ()
+  (let ((buffer (generate-new-buffer " *print*")))
+    (unwind-protect
+       (progn
+         (copy-to-buffer buffer (point-min) (point-max))
+         (set-buffer buffer)
+         (gnus-remove-text-with-property 'gnus-decoration)
+         (when (gnus-visual-p 'article-highlight 'highlight)
+           ;; Copy-to-buffer doesn't copy overlay.  So redo
+           ;; highlight.
+           (let ((gnus-article-buffer buffer))
+             (gnus-article-highlight-citation t)
+             (gnus-article-highlight-signature)
+             (gnus-article-emphasize)
+             (gnus-article-delete-invisible-text)))
+         (let ((ps-left-header
+                (list
+                 (concat "("
+                         (gnus-summary-print-truncate-and-quote
+                          (mail-header-subject gnus-current-headers)
+                          66) ")")
+                 (concat "("
+                         (gnus-summary-print-truncate-and-quote
+                          (mail-header-from gnus-current-headers)
+                          45) ")")))
+               (ps-right-header
+                (list
+                 "/pagenumberstring load"
+                 (concat "("
+                         (mail-header-date gnus-current-headers) ")"))))
+           (gnus-run-hooks 'gnus-ps-print-hook)
+           (save-excursion
+             (if window-system
+                 (ps-spool-buffer-with-faces)
+               (ps-spool-buffer)))))
+      (kill-buffer buffer))))
 
 (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."
+  "Force redisplaying of the current article.
+If ARG (the prefix) is a number, show the article with the charset
+defined in `gnus-summary-show-article-charset-alist', or the charset
+input.
+If ARG (the prefix) is non-nil and not a number, show the raw article
+without any article massaging functions being run.  Normally, the key
+strokes are `C-u g'."
   (interactive "P")
-  (if (not arg)
-      ;; Select the article the normal way.
+  (cond
+   ((numberp arg)
+    (gnus-summary-show-article t)
+    (let* ((gnus-newsgroup-charset
+           (or (cdr (assq arg gnus-summary-show-article-charset-alist))
+               (mm-read-coding-system
+                "View as charset: " ;; actually it is coding system.
+                (save-excursion
+                  (set-buffer gnus-article-buffer)
+                  (mm-detect-coding-region (point) (point-max))))))
+          (default-mime-charset gnus-newsgroup-charset)
+          (gnus-newsgroup-ignored-charsets 'gnus-all))
       (gnus-summary-select-article nil 'force)
+      (let ((deps gnus-newsgroup-dependencies)
+           head header lines)
+       (save-excursion
+         (set-buffer gnus-original-article-buffer)
+         (save-restriction
+           (message-narrow-to-head)
+           (setq head (buffer-string))
+           (goto-char (point-min))
+           (unless (re-search-forward "^lines:[ \t]\\([0-9]+\\)" nil t)
+             (goto-char (point-max))
+             (widen)
+             (setq lines (1- (count-lines (point) (point-max))))))
+         (with-temp-buffer
+           (insert (format "211 %d Article retrieved.\n"
+                           (cdr gnus-article-current)))
+           (insert head)
+           (if lines (insert (format "Lines: %d\n" lines)))
+           (insert ".\n")
+           (let ((nntp-server-buffer (current-buffer)))
+             (setq header (car (gnus-get-newsgroup-headers deps t))))))
+       (gnus-data-set-header
+        (gnus-data-find (cdr gnus-article-current))
+        header)
+       (gnus-summary-update-article-line
+        (cdr gnus-article-current) header)
+       (when (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+         (gnus-summary-update-secondary-mark (cdr gnus-article-current))))))
+   ((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)
+    (require 'gnus-art)
     ;; Bind the article treatment functions to nil.
     (let ((gnus-have-all-headers t)
-         gnus-article-display-hook
          gnus-article-prepare-hook
+         gnus-article-decode-hook
          gnus-break-pages
          gnus-show-mime
-         gnus-visual)
-      (gnus-summary-select-article nil 'force)))
+         (gnus-inhibit-treatment t))
+      (gnus-summary-select-article nil 'force))))
   (gnus-summary-goto-subject gnus-current-article)
   (gnus-summary-position-point))
 
+(defun gnus-summary-show-raw-article ()
+  "Show the raw article without any article massaging functions being run."
+  (interactive)
+  (gnus-summary-show-article t))
+
 (defun gnus-summary-verbose-headers (&optional arg)
   "Toggle permanent full header display.
 If ARG is a positive number, turn header display on.
@@ -6812,39 +8799,57 @@ If ARG is a negative number, turn header display off."
 If ARG is a positive number, show the entire header.
 If ARG is a negative number, hide the unwanted header lines."
   (interactive "P")
-  (save-excursion
-    (set-buffer gnus-article-buffer)
-    (let* ((buffer-read-only nil)
-          (inhibit-point-motion-hooks t)
-          (hidden (text-property-any
-                   (goto-char (point-min)) (search-forward "\n\n")
-                   'invisible t))
-          e)
-      (goto-char (point-min))
-      (when (search-forward "\n\n" nil t)
-       (delete-region (point-min) (1- (point))))
-      (goto-char (point-min))
-      (save-excursion
-       (set-buffer gnus-original-article-buffer)
-       (goto-char (point-min))
-       (setq e (1- (or (search-forward "\n\n" nil t) (point-max)))))
-      (insert-buffer-substring gnus-original-article-buffer 1 e)
-      (let ((article-inhibit-hiding t))
-       (gnus-run-hooks 'gnus-article-display-hook))
-      (when (or (not hidden) (and (numberp arg) (< arg 0)))
-       (gnus-article-hide-headers)))))
+  (let ((window (and (gnus-buffer-live-p gnus-article-buffer)
+                    (get-buffer-window gnus-article-buffer t))))
+    (with-current-buffer gnus-article-buffer
+      (widen)
+      (article-narrow-to-head)
+      (let* ((buffer-read-only nil)
+            (inhibit-point-motion-hooks t)
+            (hidden (if (numberp arg)
+                        (>= arg 0)
+                      (gnus-article-hidden-text-p 'headers)))
+            s e)
+       (delete-region (point-min) (point-max))
+       (with-current-buffer gnus-original-article-buffer
+         (goto-char (setq s (point-min)))
+         (setq e (if (search-forward "\n\n" nil t)
+                     (1- (point))
+                   (point-max))))
+       (insert-buffer-substring gnus-original-article-buffer s e)
+       ;; In T-gnus, gnus-article-decode-hook doesn't contain
+       ;; article-decode-encoded-words by default.
+       (article-decode-encoded-words)
+       (run-hooks 'gnus-article-decode-hook)
+       (if hidden
+           (let ((gnus-treat-hide-headers nil)
+                 (gnus-treat-hide-boring-headers nil))
+             (gnus-delete-wash-type 'headers)
+             (gnus-treat-article 'head))
+         (gnus-treat-article 'head))
+       (widen)
+       (if window
+           (set-window-start window (goto-char (point-min))))
+       (if gnus-break-pages
+           (gnus-narrow-to-page)
+         (when (gnus-visual-p 'page-marker)
+           (let ((buffer-read-only nil))
+             (gnus-remove-text-with-property 'gnus-prev)
+             (gnus-remove-text-with-property 'gnus-next))))
+       (gnus-set-mode-line 'article)))))
 
 (defun gnus-summary-show-all-headers ()
   "Make all header lines visible."
   (interactive)
-  (gnus-article-show-all-headers))
+  (gnus-summary-toggle-header 1))
 
 (defun gnus-summary-toggle-mime (&optional arg)
   "Toggle MIME processing.
 If ARG is a positive number, turn MIME processing on."
   (interactive "P")
   (setq gnus-show-mime
-       (if (null arg) (not gnus-show-mime)
+       (if (null arg)
+           (not gnus-show-mime)
          (> (prefix-numeric-value arg) 0)))
   (gnus-summary-select-article t 'force))
 
@@ -6863,6 +8868,31 @@ forward."
          (message-caesar-buffer-body arg)
          (set-window-start (get-buffer-window (current-buffer)) start))))))
 
+(autoload 'unmorse-region "morse"
+  "Convert morse coded text in region to ordinary ASCII text."
+  t)
+
+(defun gnus-summary-morse-message (&optional arg)
+  "Morse decode the current article."
+  (interactive "P")
+  (gnus-summary-select-article)
+  (let ((mail-header-separator ""))
+    (gnus-eval-in-buffer-window gnus-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (let ((pos (window-start))
+               buffer-read-only)
+           (goto-char (point-min))
+           (when (message-goto-body)
+             (gnus-narrow-to-body))
+           (goto-char (point-min))
+           (while (re-search-forward "·" (point-max) t)
+             (replace-match "."))
+           (unmorse-region (point-min) (point-max))
+           (widen)
+           (set-window-start (get-buffer-window (current-buffer)) pos)))))))
+
 (defun gnus-summary-stop-page-breaking ()
   "Stop page breaking in the current article."
   (interactive)
@@ -6886,16 +8916,18 @@ If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
 If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method.
 
+When called interactively with TO-NEWSGROUP being nil, the value of
+the variable `gnus-move-split-methods' is used for finding a default
+for the target newsgroup.
+
 For this function to work, both the current newsgroup and the
 newsgroup that you want to move to have to support the `request-move'
-and `request-accept' functions."
+and `request-accept' functions.
+
+ACTION can be either `move' (the default), `crosspost' or `copy'."
   (interactive "P")
   (unless action
     (setq action 'move))
-  ;; Disable marking as read.
-  (let (gnus-mark-article-hook)
-    (save-window-excursion
-      (gnus-summary-select-article)))
   ;; Check whether the source group supports the required functions.
   (cond ((and (eq action 'move)
              (not (gnus-check-backend-function
@@ -6906,7 +8938,10 @@ and `request-accept' functions."
                    'request-replace-article gnus-newsgroup-name)))
         (error "The current group does not support article editing")))
   (let ((articles (gnus-summary-work-articles n))
-       (prefix (gnus-group-real-prefix gnus-newsgroup-name))
+       (prefix (if (gnus-check-backend-function
+                    'request-move-article gnus-newsgroup-name)
+                   (gnus-group-real-prefix gnus-newsgroup-name)
+                 ""))
        (names '((move "Move" "Moving")
                 (copy "Copy" "Copying")
                 (crosspost "Crosspost" "Crossposting")))
@@ -6918,6 +8953,18 @@ and `request-accept' functions."
     ;; Read the newsgroup name.
     (when (and (not to-newsgroup)
               (not select-method))
+      (if (and gnus-move-split-methods
+              (not
+               (and (memq gnus-current-article articles)
+                    (gnus-buffer-live-p gnus-original-article-buffer))))
+         ;; When `gnus-move-split-methods' is non-nil, we have to
+         ;; select an article to give `gnus-read-move-group-name' an
+         ;; opportunity to suggest an appropriate default.  However,
+         ;; we needn't render or mark the article.
+         (let ((gnus-display-mime-function nil)
+               (gnus-article-prepare-hook nil)
+               (gnus-mark-article-hook nil))
+           (gnus-summary-select-article nil nil nil (car articles))))
       (setq to-newsgroup
            (gnus-read-move-group-name
             (cadr (assq action names))
@@ -6925,7 +8972,8 @@ and `request-accept' functions."
             articles prefix))
       (set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
     (setq to-method (or select-method
-                       (gnus-group-name-to-method to-newsgroup)))
+                       (gnus-server-to-method
+                        (gnus-group-method to-newsgroup))))
     ;; Check the method we are to move this article to...
     (unless (gnus-check-backend-function
             'request-accept-article (car to-method))
@@ -6951,7 +8999,7 @@ and `request-accept' functions."
                  gnus-newsgroup-name)) ; Server
          (list 'gnus-request-accept-article
                to-newsgroup (list 'quote select-method)
-               (not articles))         ; Accept form
+               (not articles) t)       ; Accept form
          (not articles)))              ; Only save nov last time
        ;; Copy the article.
        ((eq action 'copy)
@@ -6959,14 +9007,14 @@ and `request-accept' functions."
           (set-buffer copy-buf)
           (when (gnus-request-article-this-buffer article gnus-newsgroup-name)
             (gnus-request-accept-article
-             to-newsgroup select-method (not articles)))))
+             to-newsgroup select-method (not articles) t))))
        ;; Crosspost the article.
        ((eq action 'crosspost)
         (let ((xref (message-tokenize-header
                      (mail-header-xref (gnus-summary-article-header article))
                      " ")))
           (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name)
-                                 ":" article))
+                                 ":" (number-to-string article)))
           (unless xref
             (setq xref (list (system-name))))
           (setq new-xref
@@ -6983,7 +9031,8 @@ and `request-accept' functions."
                                (gnus-request-accept-article
                                 to-newsgroup select-method (not articles))))
               (setq new-xref (concat new-xref " " (car art-group)
-                                     ":" (cdr art-group)))
+                                     ":"
+                                     (number-to-string (cdr art-group))))
               ;; Now we have the new Xrefs header, so we insert
               ;; it and replace the new article.
               (nnheader-replace-header "Xref" new-xref)
@@ -6992,24 +9041,28 @@ and `request-accept' functions."
               art-group))))))
       (cond
        ((not art-group)
-       (gnus-message 1 "Couldn't %s article %s"
-                     (cadr (assq action names)) article))
-       ((and (eq art-group 'junk)
-            (eq action 'move))
-       (gnus-summary-mark-article article gnus-canceled-mark)
-       (gnus-message 4 "Deleted article %s" article))
+       (gnus-message 1 "Couldn't %s article %s: %s"
+                     (cadr (assq action names)) article
+                     (nnheader-get-report (car to-method))))
+       ((eq art-group 'junk)
+       (when (eq action 'move)
+         (gnus-summary-mark-article article gnus-canceled-mark)
+         (gnus-message 4 "Deleted article %s" article)
+         ;; run the delete hook
+         (run-hook-with-args 'gnus-summary-article-delete-hook
+                             action
+                             (gnus-data-header
+                              (assoc article (gnus-data-list nil)))
+                             gnus-newsgroup-name nil
+                             select-method)))
        (t
-       (let* ((entry
-               (or
-                (gnus-gethash (car art-group) gnus-newsrc-hashtb)
-                (gnus-gethash
-                 (gnus-group-prefixed-name
-                  (car art-group)
-                  (or select-method
-                      (gnus-find-method-for-group to-newsgroup)))
-                 gnus-newsrc-hashtb)))
+       (let* ((pto-group (gnus-group-prefixed-name
+                          (car art-group) to-method))
+              (entry
+               (gnus-gethash pto-group gnus-newsrc-hashtb))
               (info (nth 2 entry))
-              (to-group (gnus-info-group info)))
+              (to-group (gnus-info-group info))
+              to-marks)
          ;; Update the group that has been moved to.
          (when (and info
                     (memq action '(move copy)))
@@ -7017,15 +9070,20 @@ and `request-accept' functions."
              (push to-group to-groups))
 
            (unless (memq article gnus-newsgroup-unreads)
+             (push 'read to-marks)
              (gnus-info-set-read
               info (gnus-add-to-range (gnus-info-read info)
                                       (list (cdr art-group)))))
 
-           ;; Copy any marks over to the new group.
-           (let ((marks gnus-article-mark-lists)
+           ;; See whether the article is to be put in the cache.
+           (let ((marks (if (gnus-group-auto-expirable-p to-group)
+                            gnus-article-mark-lists
+                          (delete '(expirable . expire)
+                                  (copy-sequence gnus-article-mark-lists))))
                  (to-article (cdr art-group)))
 
-             ;; See whether the article is to be put in the cache.
+             ;; Enter the article into the cache in the new group,
+             ;; if that is required.
              (when gnus-use-cache
                (gnus-cache-possibly-enter-article
                 to-group to-article
@@ -7037,29 +9095,36 @@ and `request-accept' functions."
                 (memq article gnus-newsgroup-dormant)
                 (memq article gnus-newsgroup-unreads)))
 
-             (when (and (equal to-group gnus-newsgroup-name)
-                        (not (memq article gnus-newsgroup-unreads)))
-               ;; Mark this article as read in this group.
-               (push (cons to-article gnus-read-mark) gnus-newsgroup-reads)
-               (setcdr (gnus-active to-group) to-article)
-               (setcdr gnus-newsgroup-active to-article))
-
-             (while marks
-               (when (memq article (symbol-value
-                                    (intern (format "gnus-newsgroup-%s"
-                                                    (caar marks)))))
-                 ;; If the other group is the same as this group,
-                 ;; then we have to add the mark to the list.
-                 (when (equal to-group gnus-newsgroup-name)
-                   (set (intern (format "gnus-newsgroup-%s" (caar marks)))
-                        (cons to-article
-                              (symbol-value
-                               (intern (format "gnus-newsgroup-%s"
-                                               (caar marks)))))))
-                 ;; Copy the marks to other group.
-                 (gnus-add-marked-articles
-                  to-group (cdar marks) (list to-article) info))
-               (setq marks (cdr marks)))
+             (when gnus-preserve-marks
+               ;; Copy any marks over to the new group.
+               (when (and (equal to-group gnus-newsgroup-name)
+                          (not (memq article gnus-newsgroup-unreads)))
+                 ;; Mark this article as read in this group.
+                 (push (cons to-article gnus-read-mark) gnus-newsgroup-reads)
+                 (setcdr (gnus-active to-group) to-article)
+                 (setcdr gnus-newsgroup-active to-article))
+
+               (while marks
+                 (when (eq (gnus-article-mark-to-type (cdar marks)) 'list)
+                   (when (memq article (symbol-value
+                                        (intern (format "gnus-newsgroup-%s"
+                                                        (caar marks)))))
+                     (push (cdar marks) to-marks)
+                     ;; If the other group is the same as this group,
+                     ;; then we have to add the mark to the list.
+                     (when (equal to-group gnus-newsgroup-name)
+                       (set (intern (format "gnus-newsgroup-%s" (caar marks)))
+                            (cons to-article
+                                  (symbol-value
+                                   (intern (format "gnus-newsgroup-%s"
+                                                   (caar marks)))))))
+                     ;; Copy the marks to other group.
+                     (gnus-add-marked-articles
+                      to-group (cdar marks) (list to-article) info)))
+                 (setq marks (cdr marks)))
+
+               (gnus-request-set-mark
+                to-group (list (list (list to-article) 'add to-marks))))
 
              (gnus-dribble-enter
               (concat "(gnus-group-set-info '"
@@ -7074,7 +9139,16 @@ and `request-accept' functions."
              (gnus-request-article-this-buffer article gnus-newsgroup-name)
              (nnheader-replace-header "Xref" new-xref)
              (gnus-request-replace-article
-              article gnus-newsgroup-name (current-buffer)))))
+              article gnus-newsgroup-name (current-buffer))))
+
+         ;; run the move/copy/crosspost/respool hook
+         (run-hook-with-args 'gnus-summary-article-move-hook
+                             action
+                             (gnus-data-header
+                              (assoc article (gnus-data-list nil)))
+                             gnus-newsgroup-name
+                             to-newsgroup
+                             select-method))
 
        ;;;!!!Why is this necessary?
        (set-buffer gnus-summary-buffer)
@@ -7084,12 +9158,10 @@ and `request-accept' functions."
          (gnus-summary-mark-article article gnus-canceled-mark))))
       (gnus-summary-remove-process-mark article))
     ;; Re-activate all groups that have been moved to.
-    (while to-groups
-      (save-excursion
-       (set-buffer gnus-group-buffer)
-       (when (gnus-group-goto-group (car to-groups) t)
-         (gnus-group-get-new-news-this-group 1 t))
-       (pop to-groups)))
+    (save-excursion
+      (set-buffer gnus-group-buffer)
+      (let ((gnus-group-marked to-groups))
+       (gnus-group-get-new-news-this-group nil t)))
 
     (gnus-kill-buffer copy-buf)
     (gnus-summary-position-point)
@@ -7098,6 +9170,9 @@ and `request-accept' functions."
 (defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
   "Move the current article to a different newsgroup.
 If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
+When called interactively, if TO-NEWSGROUP is nil, use the value of
+the variable `gnus-move-split-methods' for finding a default target
+newsgroup.
 If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
 re-spool using this method."
   (interactive "P")
@@ -7109,12 +9184,20 @@ re-spool using this method."
   (gnus-summary-move-article n nil nil 'crosspost))
 
 (defcustom gnus-summary-respool-default-method nil
-  "Default method for respooling an article.
+  "Default method type for respooling an article.
 If nil, use to the current newsgroup method."
-  :type `(choice (gnus-select-method :value (nnml ""))
-                (const nil))
+  :type 'symbol
   :group 'gnus-summary-mail)
 
+(defcustom gnus-summary-display-while-building nil
+  "If non-nil, show and update the summary buffer as it's being built.
+If the value is t, update the buffer after every line is inserted.  If
+the value is an integer (N), update the display every N lines."
+  :group 'gnus-thread
+  :type '(choice (const :tag "off" nil)
+                number
+                (const :tag "frequently" t)))
+
 (defun gnus-summary-respool-article (&optional n method)
   "Respool the current article.
 The article will be squeezed through the mail spooling process again,
@@ -7137,7 +9220,7 @@ latter case, they will be copied into the relevant groups."
                                  (car (gnus-find-method-for-group
                                        gnus-newsgroup-name)))))
                (method
-                (gnus-completing-read
+                (gnus-completing-read-with-default
                  methname "What backend do you want to use when respooling?"
                  methods nil t nil 'gnus-mail-method-history))
                ms)
@@ -7159,47 +9242,78 @@ latter case, they will be copied into the relevant groups."
       (gnus-summary-move-article n nil method)
     (gnus-summary-copy-article n nil method)))
 
-(defun gnus-summary-import-article (file)
-  "Import a random file into a mail newsgroup."
-  (interactive "fImport file: ")
+(defun gnus-summary-import-article (file &optional edit)
+  "Import an arbitrary file into a mail newsgroup."
+  (interactive "fImport file: \nP")
   (let ((group gnus-newsgroup-name)
        (now (current-time))
-       atts lines)
+       atts lines group-art)
     (unless (gnus-check-backend-function 'request-accept-article group)
       (error "%s does not support article importing" group))
     (or (file-readable-p file)
        (not (file-regular-p file))
        (error "Can't read %s" file))
     (save-excursion
-      (set-buffer (get-buffer-create " *import file*"))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (gnus-get-buffer-create " *import file*"))
       (erase-buffer)
-      (insert-file-contents file)
+      (nnheader-insert-file-contents file)
       (goto-char (point-min))
-      (unless (nnheader-article-p)
+      (if (nnheader-article-p)
+         (save-restriction
+           (goto-char (point-min))
+           (search-forward "\n\n" nil t)
+           (narrow-to-region (point-min) (1- (point)))
+           (goto-char (point-min))
+           (unless (re-search-forward "^date:" nil t)
+             (goto-char (point-max))
+             (insert "Date: " (message-make-date (nth 5 atts)) "\n")))
        ;; This doesn't look like an article, so we fudge some headers.
        (setq atts (file-attributes file)
              lines (count-lines (point-min) (point-max)))
        (insert "From: " (read-string "From: ") "\n"
                "Subject: " (read-string "Subject: ") "\n"
-               "Date: " (timezone-make-date-arpa-standard
-                         (current-time-string (nth 5 atts))
-                         (current-time-zone now)
-                         (current-time-zone now))
-               "\n"
+               "Date: " (message-make-date (nth 5 atts)) "\n"
                "Message-ID: " (message-make-message-id) "\n"
                "Lines: " (int-to-string lines) "\n"
                "Chars: " (int-to-string (nth 7 atts)) "\n\n"))
-      (gnus-request-accept-article group nil t)
-      (kill-buffer (current-buffer)))))
+      (setq group-art (gnus-request-accept-article group nil t))
+      (kill-buffer (current-buffer)))
+    (setq gnus-newsgroup-active (gnus-activate-group group))
+    (forward-line 1)
+    (gnus-summary-goto-article (cdr group-art) nil t)
+    (when edit
+      (gnus-summary-edit-article))))
+
+(defun gnus-summary-create-article ()
+  "Create an article in a mail newsgroup."
+  (interactive)
+  (let ((group gnus-newsgroup-name)
+       (now (current-time))
+       group-art)
+    (unless (gnus-check-backend-function 'request-accept-article group)
+      (error "%s does not support article importing" group))
+    (save-excursion
+      (set-buffer (gnus-get-buffer-create " *import file*"))
+      (erase-buffer)
+      (goto-char (point-min))
+      ;; This doesn't look like an article, so we fudge some headers.
+      (insert "From: " (read-string "From: ") "\n"
+             "Subject: " (read-string "Subject: ") "\n"
+             "Date: " (message-make-date now) "\n"
+             "Message-ID: " (message-make-message-id) "\n")
+      (setq group-art (gnus-request-accept-article group nil t))
+      (kill-buffer (current-buffer)))
+    (setq gnus-newsgroup-active (gnus-activate-group group))
+    (forward-line 1)
+    (gnus-summary-goto-article (cdr group-art) nil t)
+    (gnus-summary-edit-article)))
 
 (defun gnus-summary-article-posted-p ()
-  "Say whether the current (mail) article is available from `gnus-select-method' as well.
+  "Say whether the current (mail) article is available from news as well.
 This will be the case if the article has both been mailed and posted."
   (interactive)
   (let ((id (mail-header-references (gnus-summary-article-header)))
-       (gnus-override-method
-        (or gnus-refer-article-method gnus-select-method)))
+       (gnus-override-method (car (gnus-refer-article-methods))))
     (if (gnus-request-head id "")
        (gnus-message 2 "The current message was found on %s"
                      gnus-override-method)
@@ -7210,8 +9324,9 @@ This will be the case if the article has both been mailed and posted."
 (defun gnus-summary-expire-articles (&optional now)
   "Expire all articles that are marked as expirable in the current group."
   (interactive)
-  (when (gnus-check-backend-function
-        'request-expire-articles gnus-newsgroup-name)
+  (when (and (not gnus-group-is-exiting-without-update-p)
+            (gnus-check-backend-function
+             'request-expire-articles gnus-newsgroup-name))
     ;; This backend supports expiry.
     (let* ((total (gnus-group-total-expirable-p gnus-newsgroup-name))
           (expirable (if total
@@ -7227,11 +9342,16 @@ This will be the case if the article has both been mailed and posted."
           (expiry-wait (if now 'immediate
                          (gnus-group-find-parameter
                           gnus-newsgroup-name 'expiry-wait)))
+          (nnmail-expiry-target
+           (or (gnus-group-find-parameter gnus-newsgroup-name 'expiry-target)
+               nnmail-expiry-target))
           es)
       (when expirable
        ;; There are expirable articles in this group, so we run them
        ;; through the expiry process.
        (gnus-message 6 "Expiring articles...")
+       (unless (gnus-check-group gnus-newsgroup-name)
+         (error "Can't open server for %s" gnus-newsgroup-name))
        ;; The list of articles that weren't expired is returned.
        (save-excursion
          (if expiry-wait
@@ -7240,19 +9360,24 @@ This will be the case if the article has both been mailed and posted."
                (setq es (gnus-request-expire-articles
                          expirable gnus-newsgroup-name)))
            (setq es (gnus-request-expire-articles
-                     expirable gnus-newsgroup-name))))
-       (unless total
-         (setq gnus-newsgroup-expirable es))
-       ;; We go through the old list of expirable, and mark all
-       ;; really expired articles as nonexistent.
-       (unless (eq es expirable)       ;If nothing was expired, we don't mark.
-         (let ((gnus-use-cache nil))
-           (while expirable
-             (unless (memq (car expirable) es)
-               (when (gnus-data-find (car expirable))
-                 (gnus-summary-mark-article
-                  (car expirable) gnus-canceled-mark)))
-             (setq expirable (cdr expirable)))))
+                     expirable gnus-newsgroup-name)))
+         (unless total
+           (setq gnus-newsgroup-expirable es))
+         ;; We go through the old list of expirable, and mark all
+         ;; really expired articles as nonexistent.
+         (unless (eq es expirable)     ;If nothing was expired, we don't mark.
+           (let ((gnus-use-cache nil))
+             (dolist (article expirable)
+               (when (and (not (memq article es))
+                          (gnus-data-find article))
+                 (gnus-summary-mark-article article gnus-canceled-mark)
+                 (run-hook-with-args 'gnus-summary-article-expire-hook
+                                     'delete
+                                     (gnus-data-header
+                                      (assoc article (gnus-data-list nil)))
+                                     gnus-newsgroup-name
+                                     nil
+                                     nil))))))
        (gnus-message 6 "Expiring articles...done")))))
 
 (defun gnus-summary-expire-articles-now ()
@@ -7260,10 +9385,10 @@ This will be the case if the article has both been mailed and posted."
 This means that *all* articles that are marked as expirable will be
 deleted forever, right now."
   (interactive)
-  (unless gnus-expert-user
-    (gnus-yes-or-no-p
-     "Are you really, really, really sure you want to delete all these messages? ")
-    (error "Phew!"))
+  (or gnus-expert-user
+      (gnus-yes-or-no-p
+       "Are you really, really, really sure you want to delete all these messages? ")
+      (error "Phew!"))
   (gnus-summary-expire-articles t))
 
 ;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
@@ -7272,15 +9397,22 @@ deleted forever, right now."
 This command actually deletes articles.         This is not a marking
 command.  The article will disappear forever from your life, never to
 return.
+
 If N is negative, delete backwards.
 If N is nil and articles have been marked with the process mark,
-delete these instead."
+delete these instead.
+
+If `gnus-novice-user' is non-nil you will be asked for
+confirmation before the articles are deleted."
   (interactive "P")
   (unless (gnus-check-backend-function 'request-expire-articles
                                       gnus-newsgroup-name)
     (error "The current newsgroup does not support article deletion"))
+  (unless (gnus-check-server (gnus-find-method-for-group gnus-newsgroup-name))
+    (error "Couldn't open server"))
   ;; Compute the list of articles to delete.
-  (let ((articles (gnus-summary-work-articles n))
+  (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) '<))
+       (nnmail-expiry-target 'delete)
        not-deleted)
     (if (and gnus-novice-user
             (not (gnus-yes-or-no-p
@@ -7298,6 +9430,12 @@ delete these instead."
        ;; after all.
        (unless (memq (car articles) not-deleted)
          (gnus-summary-mark-article (car articles) gnus-canceled-mark))
+       (let* ((article (car articles))
+              (id (mail-header-id (gnus-data-header
+                                   (assoc article (gnus-data-list nil))))))
+         (run-hook-with-args 'gnus-summary-article-delete-hook
+                             'delete id gnus-newsgroup-name nil
+                             nil))
        (setq articles (cdr articles)))
       (when not-deleted
        (gnus-message 4 "Couldn't delete articles %s" not-deleted)))
@@ -7313,20 +9451,24 @@ groups."
   (interactive "P")
   (save-excursion
     (set-buffer gnus-summary-buffer)
-    (gnus-set-global-variables)
-    (when (and (not force)
-              (gnus-group-read-only-p))
-      (error "The current newsgroup does not support article editing"))
-    ;; Select article if needed.
-    (unless (eq (gnus-summary-article-number)
-               gnus-current-article)
-      (gnus-summary-select-article t))
-    (gnus-article-date-original)
-    (gnus-article-edit-article
-     `(lambda (no-highlight)
-       (gnus-summary-edit-article-done
-        ,(or (mail-header-references gnus-current-headers) "")
-        ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight)))))
+    (let ((mail-parse-charset gnus-newsgroup-charset)
+         (mail-parse-ignored-charsets gnus-newsgroup-ignored-charsets))
+      (gnus-set-global-variables)
+      (when (and (not force)
+                (gnus-group-read-only-p))
+       (error "The current newsgroup does not support article editing"))
+      (gnus-summary-show-article t)
+      (gnus-article-edit-article
+       'ignore
+       `(lambda (no-highlight)
+         (let ((mail-parse-charset ',gnus-newsgroup-charset)
+               (message-options message-options)
+               (message-options-set-recipient)
+               (mail-parse-ignored-charsets
+                ',gnus-newsgroup-ignored-charsets))
+           (gnus-summary-edit-article-done
+            ,(or (mail-header-references gnus-current-headers) "")
+            ,(gnus-group-read-only-p) ,gnus-summary-buffer no-highlight)))))))
 
 (defalias 'gnus-summary-edit-article-postpone 'gnus-article-edit-exit)
 
@@ -7334,59 +9476,88 @@ groups."
                                                 no-highlight)
   "Make edits to the current article permanent."
   (interactive)
+  (save-excursion
+    ;; The buffer restriction contains the entire article if it exists.
+    (when (article-goto-body)
+      (let ((lines (count-lines (point) (point-max)))
+           (length (- (point-max) (point)))
+           (case-fold-search t)
+           (body (copy-marker (point))))
+       (goto-char (point-min))
+       (when (re-search-forward "^content-length:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string length)))
+       (goto-char (point-min))
+       (when (re-search-forward
+              "^x-content-length:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string length)))
+       (goto-char (point-min))
+       (when (re-search-forward "^lines:[ \t]\\([0-9]+\\)" body t)
+         (delete-region (match-beginning 1) (match-end 1))
+         (insert (number-to-string lines))))))
   ;; Replace the article.
-  (if (and (not read-only)
-          (not (gnus-request-replace-article
-                (cdr gnus-article-current) (car gnus-article-current)
-                (current-buffer))))
-      (error "Couldn't replace article")
-    ;; Update the summary buffer.
-    (if (and references
-            (equal (message-tokenize-header references " ")
-                   (message-tokenize-header
-                    (or (message-fetch-field "references") "") " ")))
-       ;; We only have to update this line.
-       (save-excursion
-         (save-restriction
-           (message-narrow-to-head)
-           (let ((head (buffer-string))
-                 header)
-             (nnheader-temp-write nil
-               (insert (format "211 %d Article retrieved.\n"
-                               (cdr gnus-article-current)))
-               (insert head)
-               (insert ".\n")
-               (let ((nntp-server-buffer (current-buffer)))
-                 (setq header (car (gnus-get-newsgroup-headers
-                                    (save-excursion
-                                      (set-buffer gnus-summary-buffer)
-                                      gnus-newsgroup-dependencies)
-                                    t))))
-               (save-excursion
-                 (set-buffer gnus-summary-buffer)
-                 (gnus-data-set-header
-                  (gnus-data-find (cdr gnus-article-current))
-                  header)
-                 (gnus-summary-update-article-line
-                  (cdr gnus-article-current) header))))))
-      ;; Update threads.
-      (set-buffer (or buffer gnus-summary-buffer))
-      (gnus-summary-update-article (cdr gnus-article-current)))
-    ;; Prettify the article buffer again.
-    (unless no-highlight
-      (save-excursion
-       (set-buffer gnus-article-buffer)
-       (gnus-run-hooks 'gnus-article-display-hook)
-       (set-buffer gnus-original-article-buffer)
-       (gnus-request-article
-        (cdr gnus-article-current)
-        (car gnus-article-current) (current-buffer))))
-    ;; Prettify the summary buffer line.
-    (when (gnus-visual-p 'summary-highlight 'highlight)
-      (gnus-run-hooks 'gnus-visual-mark-article-hook))))
+  (let ((buf (current-buffer)))
+    (with-temp-buffer
+      (insert-buffer-substring buf)
+
+      (if (and (not read-only)
+              (not (gnus-request-replace-article
+                    (cdr gnus-article-current) (car gnus-article-current)
+                    (current-buffer) t)))
+         (error "Couldn't replace article")
+       ;; Update the summary buffer.
+       (if (and references
+                (equal (message-tokenize-header references " ")
+                       (message-tokenize-header
+                        (or (message-fetch-field "references") "") " ")))
+           ;; We only have to update this line.
+           (save-excursion
+             (save-restriction
+               (message-narrow-to-head)
+               (let ((head (buffer-string))
+                     header)
+                 (with-temp-buffer
+                   (insert (format "211 %d Article retrieved.\n"
+                                   (cdr gnus-article-current)))
+                   (insert head)
+                   (insert ".\n")
+                   (let ((nntp-server-buffer (current-buffer)))
+                     (setq header (car (gnus-get-newsgroup-headers
+                                        nil t))))
+                   (save-excursion
+                     (set-buffer gnus-summary-buffer)
+                     (gnus-data-set-header
+                      (gnus-data-find (cdr gnus-article-current))
+                      header)
+                     (gnus-summary-update-article-line
+                      (cdr gnus-article-current) header)
+                     (if (gnus-summary-goto-subject
+                          (cdr gnus-article-current) nil t)
+                         (gnus-summary-update-secondary-mark
+                          (cdr gnus-article-current))))))))
+         ;; Update threads.
+         (set-buffer (or buffer gnus-summary-buffer))
+         (gnus-summary-update-article (cdr gnus-article-current))
+         (if (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+             (gnus-summary-update-secondary-mark
+              (cdr gnus-article-current))))
+       ;; Prettify the article buffer again.
+       (unless no-highlight
+         (save-excursion
+           (set-buffer gnus-article-buffer)
+           ;;;!!! Fix this -- article should be rehighlighted.
+           ;;;(gnus-run-hooks 'gnus-article-display-hook)
+           (set-buffer gnus-original-article-buffer)
+           (gnus-request-article
+            (cdr gnus-article-current)
+            (car gnus-article-current) (current-buffer))))
+       ;; Prettify the summary buffer line.
+       (when (gnus-visual-p 'summary-highlight 'highlight)
+         (gnus-run-hooks 'gnus-visual-mark-article-hook))))))
 
 (defun gnus-summary-edit-wash (key)
-  "Perform editing command in the article buffer."
+  "Perform editing command KEY in the article buffer."
   (interactive
    (list
     (progn
@@ -7399,22 +9570,26 @@ groups."
 
 ;;; Respooling
 
-(defun gnus-summary-respool-query (&optional silent)
+(defun gnus-summary-respool-query (&optional silent trace)
   "Query where the respool algorithm would put this article."
   (interactive)
   (let (gnus-mark-article-hook)
     (gnus-summary-select-article)
     (save-excursion
       (set-buffer gnus-original-article-buffer)
-      (save-restriction
-       (message-narrow-to-head)
-       (let ((groups (nnmail-article-group 'identity)))
-         (unless silent
-           (if groups
-               (message "This message would go to %s"
-                        (mapconcat 'car groups ", "))
-             (message "This message would go to no groups"))
-           groups))))))
+      (let ((groups (nnmail-article-group 'identity trace)))
+       (unless silent
+         (if groups
+             (message "This message would go to %s"
+                      (mapconcat 'car groups ", "))
+           (message "This message would go to no groups"))
+         groups)))))
+
+(defun gnus-summary-respool-trace ()
+  "Trace where the respool algorithm would put this article.
+Display a buffer showing all fancy splitting patterns which matched."
+  (interactive)
+  (gnus-summary-respool-query nil t))
 
 ;; Summary marking commands.
 
@@ -7490,28 +9665,31 @@ If optional argument UNMARK is negative, mark articles as unread instead."
 If N is negative, mark backward instead.  If UNMARK is non-nil, remove
 the process mark instead.  The difference between N and the actual
 number of articles marked is returned."
-  (interactive "p")
-  (let ((backward (< n 0))
-       (n (abs n)))
-    (while (and
-           (> n 0)
-           (if unmark
-               (gnus-summary-remove-process-mark
-                (gnus-summary-article-number))
-             (gnus-summary-set-process-mark (gnus-summary-article-number)))
-           (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
-      (setq n (1- n)))
-    (when (/= 0 n)
-      (gnus-message 7 "No more articles"))
-    (gnus-summary-recenter)
-    (gnus-summary-position-point)
-    n))
+  (interactive "P")
+  (if (and (null n) (gnus-region-active-p))
+      (gnus-uu-mark-region (region-beginning) (region-end) unmark)
+    (setq n (prefix-numeric-value n))
+    (let ((backward (< n 0))
+         (n (abs n)))
+      (while (and
+             (> n 0)
+             (if unmark
+                 (gnus-summary-remove-process-mark
+                  (gnus-summary-article-number))
+               (gnus-summary-set-process-mark (gnus-summary-article-number)))
+             (zerop (gnus-summary-next-subject (if backward -1 1) nil t)))
+       (setq n (1- n)))
+      (when (/= 0 n)
+       (gnus-message 7 "No more articles"))
+      (gnus-summary-recenter)
+      (gnus-summary-position-point)
+      n)))
 
 (defun gnus-summary-unmark-as-processable (n)
   "Remove the process mark from the next N articles.
 If N is negative, unmark backward instead.  The difference between N and
 the actual number of articles unmarked is returned."
-  (interactive "p")
+  (interactive "P")
   (gnus-summary-mark-as-processable n t))
 
 (defun gnus-summary-unmark-all-processable ()
@@ -7522,6 +9700,20 @@ the actual number of articles unmarked is returned."
       (gnus-summary-remove-process-mark (car gnus-newsgroup-processable))))
   (gnus-summary-position-point))
 
+(defun gnus-summary-add-mark (article type)
+  "Mark ARTICLE with a mark of TYPE."
+  (let ((vtype (car (assq type gnus-article-mark-lists)))
+       var)
+    (if (not vtype)
+       (error "No such mark type: %s" type)
+      (setq var (intern (format "gnus-newsgroup-%s" type)))
+      (set var (cons article (symbol-value var)))
+      (if (memq type '(processable cached replied forwarded recent saved))
+         (gnus-summary-update-secondary-mark article)
+       ;;; !!! This is bogus.  We should find out what primary
+       ;;; !!! mark we want to set.
+       (gnus-summary-update-mark gnus-del-mark 'unread)))))
+
 (defun gnus-summary-mark-as-expirable (n)
   "Mark N articles forward as expirable.
 If N is negative, mark backward instead.  The difference between N and
@@ -7529,12 +9721,35 @@ the actual number of articles marked is returned."
   (interactive "p")
   (gnus-summary-mark-forward n gnus-expirable-mark))
 
+(defun gnus-summary-mark-as-spam (n)
+  "Mark N articles forward as spam.
+If N is negative, mark backward instead.  The difference between N and
+the actual number of articles marked is returned."
+  (interactive "p")
+  (gnus-summary-mark-forward n gnus-spam-mark))
+
 (defun gnus-summary-mark-article-as-replied (article)
-  "Mark ARTICLE replied and update the summary line."
-  (push article gnus-newsgroup-replied)
-  (let ((buffer-read-only nil))
-    (when (gnus-summary-goto-subject article)
-      (gnus-summary-update-secondary-mark article))))
+  "Mark ARTICLE as replied to and update the summary line.
+ARTICLE can also be a list of articles."
+  (interactive (list (gnus-summary-article-number)))
+  (let ((articles (if (listp article) article (list article))))
+    (dolist (article articles)
+      (unless (numberp article)
+       (error "%s is not a number" article))
+      (push article gnus-newsgroup-replied)
+      (let ((buffer-read-only nil))
+       (when (gnus-summary-goto-subject article nil t)
+         (gnus-summary-update-secondary-mark article))))))
+
+(defun gnus-summary-mark-article-as-forwarded (article)
+  "Mark ARTICLE as forwarded and update the summary line.
+ARTICLE can also be a list of articles."
+  (let ((articles (if (listp article) article (list article))))
+    (dolist (article articles)
+      (push article gnus-newsgroup-forwarded)
+      (let ((buffer-read-only nil))
+       (when (gnus-summary-goto-subject article nil t)
+         (gnus-summary-update-secondary-mark article))))))
 
 (defun gnus-summary-set-bookmark (article)
   "Set a bookmark in current article."
@@ -7545,10 +9760,7 @@ the actual number of articles marked is returned."
            (not (equal gnus-newsgroup-name (car gnus-article-current))))
     (error "No current article selected"))
   ;; Remove old bookmark, if one exists.
-  (let ((old (assq article gnus-newsgroup-bookmarks)))
-    (when old
-      (setq gnus-newsgroup-bookmarks
-           (delq old gnus-newsgroup-bookmarks))))
+  (gnus-pull article gnus-newsgroup-bookmarks)
   ;; Set the new bookmark, which is on the form
   ;; (article-number . line-number-in-body).
   (push
@@ -7558,8 +9770,7 @@ the actual number of articles marked is returned."
           (count-lines
            (min (point)
                 (save-excursion
-                  (goto-char (point-min))
-                  (search-forward "\n\n" nil t)
+                  (article-goto-body)
                   (point)))
            (point))))
    gnus-newsgroup-bookmarks)
@@ -7569,13 +9780,10 @@ the actual number of articles marked is returned."
   "Remove the bookmark from the current article."
   (interactive (list (gnus-summary-article-number)))
   ;; Remove old bookmark, if one exists.
-  (let ((old (assq article gnus-newsgroup-bookmarks)))
-    (if old
-       (progn
-         (setq gnus-newsgroup-bookmarks
-               (delq old gnus-newsgroup-bookmarks))
-         (gnus-message 6 "Removed bookmark."))
-      (gnus-message 6 "No bookmark in current article."))))
+  (if (not (assq article gnus-newsgroup-bookmarks))
+      (gnus-message 6 "No bookmark in current article.")
+    (gnus-pull article gnus-newsgroup-bookmarks)
+    (gnus-message 6 "Removed bookmark.")))
 
 ;; Suggested by Daniel Quinlan <quinlan@best.com>.
 (defun gnus-summary-mark-as-dormant (n)
@@ -7592,6 +9800,7 @@ the actual number of articles marked is returned."
              (delq article gnus-newsgroup-processable)))
   (when (gnus-summary-goto-subject article)
     (gnus-summary-show-thread)
+    (gnus-summary-goto-subject article)
     (gnus-summary-update-secondary-mark article)))
 
 (defun gnus-summary-remove-process-mark (article)
@@ -7599,6 +9808,7 @@ the actual number of articles marked is returned."
   (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable))
   (when (gnus-summary-goto-subject article)
     (gnus-summary-show-thread)
+    (gnus-summary-goto-subject article)
     (gnus-summary-update-secondary-mark article)))
 
 (defun gnus-summary-set-saved-mark (article)
@@ -7611,13 +9821,15 @@ the actual number of articles marked is returned."
   "Mark N articles as read forwards.
 If N is negative, mark backwards instead.  Mark with MARK, ?r by default.
 The difference between N and the actual number of articles marked is
-returned."
+returned.
+If NO-EXPIRE, auto-expiry will be inhibited."
   (interactive "p")
+  (gnus-summary-show-thread)
   (let ((backward (< n 0))
        (gnus-summary-goto-unread
         (and gnus-summary-goto-unread
              (not (eq gnus-summary-goto-unread 'never))
-             (not (memq mark (list gnus-unread-mark
+             (not (memq mark (list gnus-unread-mark gnus-spam-mark
                                    gnus-ticked-mark gnus-dormant-mark)))))
        (n (abs n))
        (mark (or mark gnus-del-mark)))
@@ -7641,6 +9853,7 @@ returned."
   (let ((article (gnus-summary-article-number)))
     (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
     (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+    (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
     (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
     (push (cons article mark) gnus-newsgroup-reads)
     ;; Possibly remove from cache, if that is used.
@@ -7650,12 +9863,10 @@ returned."
     (setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
     ;; Check for auto-expiry.
     (when (and gnus-newsgroup-auto-expire
-              (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
-                  (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
-                  (= mark gnus-ancient-mark)
-                  (= mark gnus-read-mark) (= mark gnus-souped-mark)
-                  (= mark gnus-duplicate-mark)))
+              (memq mark gnus-auto-expirable-marks))
       (setq mark gnus-expirable-mark)
+      ;; Let the backend know about the mark change.
+      (setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
       (push article gnus-newsgroup-expirable))
     ;; Set the mark in the buffer.
     (gnus-summary-update-mark mark 'unread)
@@ -7665,6 +9876,8 @@ returned."
   "Mark the current article quickly as unread with MARK."
   (let* ((article (gnus-summary-article-number))
         (old-mark (gnus-summary-article-mark article)))
+    ;; Allow the backend to change the mark.
+    (setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
     (if (eq mark old-mark)
        t
       (if (<= article 0)
@@ -7672,18 +9885,28 @@ returned."
            (gnus-error 1 "Can't mark negative article numbers")
            nil)
        (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+       (setq gnus-newsgroup-spam-marked
+             (delq article gnus-newsgroup-spam-marked))
        (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
        (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable))
        (setq gnus-newsgroup-reads (delq article gnus-newsgroup-reads))
        (cond ((= mark gnus-ticked-mark)
-              (push article gnus-newsgroup-marked))
+              (setq gnus-newsgroup-marked
+                    (gnus-add-to-sorted-list gnus-newsgroup-marked
+                                             article)))
+             ((= mark gnus-spam-mark)
+              (setq gnus-newsgroup-spam-marked
+                    (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+                                             article)))
              ((= mark gnus-dormant-mark)
-              (push article gnus-newsgroup-dormant))
+              (setq gnus-newsgroup-dormant
+                    (gnus-add-to-sorted-list gnus-newsgroup-dormant
+                                             article)))
              (t
-              (push article gnus-newsgroup-unreads)))
-       (setq gnus-newsgroup-reads
-             (delq (assq article gnus-newsgroup-reads)
-                   gnus-newsgroup-reads))
+              (setq gnus-newsgroup-unreads
+                    (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                             article))))
+       (gnus-pull article gnus-newsgroup-reads)
 
        ;; See whether the article is to be put in the cache.
        (and gnus-use-cache
@@ -7703,31 +9926,31 @@ returned."
   "Mark ARTICLE with MARK.  MARK can be any character.
 Four MARK strings are reserved: `? ' (unread), `?!' (ticked),
 `??' (dormant) and `?E' (expirable).
-If MARK is nil, then the default character `?D' is used.
+If MARK is nil, then the default character `?r' is used.
 If ARTICLE is nil, then the article on the current line will be
-marked."
+marked.
+If NO-EXPIRE, auto-expiry will be inhibited."
   ;; The mark might be a string.
   (when (stringp mark)
     (setq mark (aref mark 0)))
   ;; If no mark is given, then we check auto-expiring.
-  (and (not no-expire)
-       gnus-newsgroup-auto-expire
-       (or (not mark)
-          (and (gnus-characterp mark)
-               (or (= mark gnus-killed-mark) (= mark gnus-del-mark)
-                   (= mark gnus-catchup-mark) (= mark gnus-low-score-mark)
-                   (= mark gnus-read-mark) (= mark gnus-souped-mark)
-                   (= mark gnus-duplicate-mark))))
-       (setq mark gnus-expirable-mark))
-  (let* ((mark (or mark gnus-del-mark))
-        (article (or article (gnus-summary-article-number)))
-        (old-mark (gnus-summary-article-mark article)))
+  (when (null mark)
+    (setq mark gnus-del-mark))
+  (when (and (not no-expire)
+            gnus-newsgroup-auto-expire
+            (memq mark gnus-auto-expirable-marks))
+    (setq mark gnus-expirable-mark))
+  (let ((article (or article (gnus-summary-article-number)))
+       (old-mark (gnus-summary-article-mark article)))
+    ;; Allow the backend to change the mark.
+    (setq mark (gnus-request-update-mark gnus-newsgroup-name article mark))
     (if (eq mark old-mark)
        t
       (unless article
        (error "No article on current line"))
       (if (not (if (or (= mark gnus-unread-mark)
                       (= mark gnus-ticked-mark)
+                      (= mark gnus-spam-mark)
                       (= mark gnus-dormant-mark))
                   (gnus-mark-article-as-unread article mark)
                 (gnus-mark-article-as-read article mark)))
@@ -7759,42 +9982,63 @@ marked."
          gnus-cached-mark)
         ((memq article gnus-newsgroup-replied)
          gnus-replied-mark)
+        ((memq article gnus-newsgroup-forwarded)
+         gnus-forwarded-mark)
         ((memq article gnus-newsgroup-saved)
          gnus-saved-mark)
-        (t gnus-unread-mark))
+        ((memq article gnus-newsgroup-recent)
+         gnus-recent-mark)
+        ((memq article gnus-newsgroup-unseen)
+         gnus-unseen-mark)
+        (t gnus-no-mark))
    'replied)
   (when (gnus-visual-p 'summary-highlight 'highlight)
     (gnus-run-hooks 'gnus-summary-update-hook))
   t)
 
+(defun gnus-summary-update-download-mark (article)
+  "Update the download mark."
+  (gnus-summary-update-mark
+   (cond ((memq article gnus-newsgroup-undownloaded)
+          gnus-undownloaded-mark)
+         (gnus-newsgroup-agentized
+          gnus-downloaded-mark)
+         (t
+          gnus-no-mark))
+   'download)
+  (gnus-summary-update-line t)
+  t)
+
 (defun gnus-summary-update-mark (mark type)
   (let ((forward (cdr (assq type gnus-summary-mark-positions)))
-        (buffer-read-only nil))
+       (buffer-read-only nil))
     (re-search-backward "[\n\r]" (gnus-point-at-bol) 'move-to-limit)
-    (when (looking-at "\r")
-      (incf forward))
-    (when (and forward
-               (<= (+ forward (point)) (point-max)))
-      ;; Go to the right position on the line.
-      (goto-char (+ forward (point)))
-      ;; Replace the old mark with the new mark.
-      (subst-char-in-region (point) (1+ (point)) (following-char) mark)
-      ;; Optionally update the marks by some user rule.
-      (when (eq type 'unread)
-        (gnus-data-set-mark
-         (gnus-data-find (gnus-summary-article-number)) mark)
-        (gnus-summary-update-line (eq mark gnus-unread-mark))))))
+    (when forward
+      (when (looking-at "\r")
+       (incf forward))
+      (when (<= (+ forward (point)) (point-max))
+       ;; Go to the right position on the line.
+       (goto-char (+ forward (point)))
+       ;; Replace the old mark with the new mark.
+       (subst-char-in-region (point) (1+ (point)) (char-after) mark)
+       ;; Optionally update the marks by some user rule.
+       (when (eq type 'unread)
+         (gnus-data-set-mark
+          (gnus-data-find (gnus-summary-article-number)) mark)
+         (gnus-summary-update-line (eq mark gnus-unread-mark)))))))
 
 (defun gnus-mark-article-as-read (article &optional mark)
   "Enter ARTICLE in the pertinent lists and remove it from others."
   ;; Make the article expirable.
   (let ((mark (or mark gnus-del-mark)))
-    (if (= mark gnus-expirable-mark)
-       (push article gnus-newsgroup-expirable)
-      (setq gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)))
+    (setq gnus-newsgroup-expirable
+         (if (= mark gnus-expirable-mark)
+             (gnus-add-to-sorted-list gnus-newsgroup-expirable article)
+           (delq article gnus-newsgroup-expirable)))
     ;; Remove from unread and marked lists.
     (setq gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
     (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked))
+    (setq gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked))
     (setq gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant))
     (push (cons article mark) gnus-newsgroup-reads)
     ;; Possibly remove from cache, if that is used.
@@ -7810,6 +10054,7 @@ marked."
          (gnus-error 1 "Can't mark negative article numbers")
          nil)
       (setq gnus-newsgroup-marked (delq article gnus-newsgroup-marked)
+           gnus-newsgroup-spam-marked (delq article gnus-newsgroup-spam-marked)
            gnus-newsgroup-dormant (delq article gnus-newsgroup-dormant)
            gnus-newsgroup-expirable (delq article gnus-newsgroup-expirable)
            gnus-newsgroup-unreads (delq article gnus-newsgroup-unreads))
@@ -7819,14 +10064,19 @@ marked."
        (gnus-dup-unsuppress-article article))
 
       (cond ((= mark gnus-ticked-mark)
-            (push article gnus-newsgroup-marked))
+            (setq gnus-newsgroup-marked
+                  (gnus-add-to-sorted-list gnus-newsgroup-marked article)))
+           ((= mark gnus-spam-mark)
+            (setq gnus-newsgroup-spam-marked
+                  (gnus-add-to-sorted-list gnus-newsgroup-spam-marked
+                                           article)))
            ((= mark gnus-dormant-mark)
-            (push article gnus-newsgroup-dormant))
+            (setq gnus-newsgroup-dormant
+                  (gnus-add-to-sorted-list gnus-newsgroup-dormant article)))
            (t
-            (push article gnus-newsgroup-unreads)))
-      (setq gnus-newsgroup-reads
-           (delq (assq article gnus-newsgroup-reads)
-                 gnus-newsgroup-reads))
+            (setq gnus-newsgroup-unreads
+                  (gnus-add-to-sorted-list gnus-newsgroup-unreads article))))
+      (gnus-pull article gnus-newsgroup-reads)
       t)))
 
 (defalias 'gnus-summary-mark-as-unread-forward
@@ -7866,14 +10116,15 @@ If N is negative, mark backwards instead.
 The difference between N and the actual number of articles marked is
 returned."
   (interactive "p")
-  (gnus-summary-mark-forward n gnus-del-mark t))
+  (gnus-summary-mark-forward n gnus-del-mark gnus-inhibit-user-auto-expire))
 
 (defun gnus-summary-mark-as-read-backward (n)
   "Mark the N articles as read backwards.
 The difference between N and the actual number of articles marked is
 returned."
   (interactive "p")
-  (gnus-summary-mark-forward (- n) gnus-del-mark t))
+  (gnus-summary-mark-forward
+   (- n) gnus-del-mark gnus-inhibit-user-auto-expire))
 
 (defun gnus-summary-mark-as-read (&optional article mark)
   "Mark current article as read.
@@ -7899,12 +10150,26 @@ The difference between N and the number of marks cleared is returned."
   (when (memq gnus-current-article gnus-newsgroup-unreads)
     (gnus-summary-mark-article gnus-current-article gnus-read-mark)))
 
-(defun gnus-summary-mark-read-and-unread-as-read ()
+(defun gnus-summary-mark-read-and-unread-as-read (&optional new-mark)
   "Intended to be used by `gnus-summary-mark-article-hook'."
   (let ((mark (gnus-summary-article-mark)))
     (when (or (gnus-unread-mark-p mark)
              (gnus-read-mark-p mark))
-      (gnus-summary-mark-article gnus-current-article gnus-read-mark))))
+      (gnus-summary-mark-article gnus-current-article
+                                (or new-mark gnus-read-mark)))))
+
+(defun gnus-summary-mark-current-read-and-unread-as-read (&optional new-mark)
+  "Intended to be used by `gnus-summary-mark-article-hook'."
+  (let ((mark (gnus-summary-article-mark)))
+    (when (or (gnus-unread-mark-p mark)
+             (gnus-read-mark-p mark))
+      (gnus-summary-mark-article (gnus-summary-article-number)
+                                (or new-mark gnus-read-mark)))))
+
+(defun gnus-summary-mark-unread-as-ticked ()
+  "Intended to be used by `gnus-summary-mark-article-hook'."
+  (when (memq gnus-current-article gnus-newsgroup-unreads)
+    (gnus-summary-mark-article gnus-current-article gnus-ticked-mark)))
 
 (defun gnus-summary-mark-region-as-read (point mark all)
   "Mark all unread articles between point and mark as read.
@@ -7979,8 +10244,8 @@ even ticked and dormant ones."
     (let ((scored gnus-newsgroup-scored)
          headers h)
       (while scored
-       (unless (gnus-summary-goto-subject (caar scored))
-         (and (setq h (gnus-summary-article-header (caar scored)))
+       (unless (gnus-summary-article-header (caar scored))
+         (and (setq h (gnus-number-to-header (caar scored)))
               (< (cdar scored) gnus-summary-expunge-below)
               (push h headers)))
        (setq scored (cdr scored)))
@@ -7988,20 +10253,29 @@ even ticked and dormant ones."
          (when (not no-error)
            (error "No expunged articles hidden"))
        (goto-char (point-min))
+       (push gnus-newsgroup-limit gnus-newsgroup-limits)
+       (setq gnus-newsgroup-limit (copy-sequence gnus-newsgroup-limit))
+       (mapcar (lambda (x) (push (mail-header-number x)
+                                 gnus-newsgroup-limit))
+               headers)
        (gnus-summary-prepare-unthreaded (nreverse headers))
        (goto-char (point-min))
        (gnus-summary-position-point)
        t))))
 
-(defun gnus-summary-catchup (&optional all quietly to-here not-mark)
+(defun gnus-summary-catchup (&optional all quietly to-here not-mark reverse)
   "Mark all unread articles in this newsgroup as read.
 If prefix argument ALL is non-nil, ticked and dormant articles will
 also be marked as read.
 If QUIETLY is non-nil, no questions will be asked.
+
 If TO-HERE is non-nil, it should be a point in the buffer.  All
-articles before this point will be marked as read.
+articles before (after, if REVERSE is set) this point will be marked
+as read.
+
 Note that this function will only catch up the unread article
 in the current summary buffer limitation.
+
 The number of articles marked as read is returned."
   (interactive "P")
   (prog1
@@ -8022,16 +10296,28 @@ The number of articles marked as read is returned."
              (progn
                (when all
                  (setq gnus-newsgroup-marked nil
+                       gnus-newsgroup-spam-marked nil
                        gnus-newsgroup-dormant nil))
-               (setq gnus-newsgroup-unreads gnus-newsgroup-downloadable))
+               (setq gnus-newsgroup-unreads
+                     (gnus-sorted-nunion
+                       (gnus-intersection gnus-newsgroup-unreads
+                                          gnus-newsgroup-downloadable)
+                       gnus-newsgroup-unfetched)))
            ;; We actually mark all articles as canceled, which we
            ;; have to do when using auto-expiry or adaptive scoring.
            (gnus-summary-show-all-threads)
-           (when (gnus-summary-first-subject (not all))
-             (while (and
-                     (if to-here (< (point) to-here) t)
-                     (gnus-summary-mark-article-as-read gnus-catchup-mark)
-                     (gnus-summary-find-next (not all)))))
+           (if (and to-here reverse)
+               (progn
+                 (goto-char to-here)
+                 (gnus-summary-mark-current-read-and-unread-as-read
+                  gnus-catchup-mark)
+                 (while (gnus-summary-find-next (not all))
+                   (gnus-summary-mark-article-as-read gnus-catchup-mark)))
+             (when (gnus-summary-first-subject (not all))
+               (while (and
+                       (if to-here (< (point) to-here) t)
+                       (gnus-summary-mark-article-as-read gnus-catchup-mark)
+                       (gnus-summary-find-next (not all))))))
            (gnus-set-mode-line 'summary))
          t))
     (gnus-summary-position-point)))
@@ -8048,27 +10334,44 @@ If ALL is non-nil, also mark ticked and dormant articles as read."
          (gnus-summary-catchup all t beg)))))
   (gnus-summary-position-point))
 
+(defun gnus-summary-catchup-from-here (&optional all)
+  "Mark all unticked articles after (and including) the current one as read.
+If ALL is non-nil, also mark ticked and dormant articles as read."
+  (interactive "P")
+  (save-excursion
+    (gnus-save-hidden-threads
+      (let ((beg (point)))
+       ;; We check that there are unread articles.
+       (when (or all (gnus-summary-find-next))
+         (gnus-summary-catchup all t beg nil t)))))
+  (gnus-summary-position-point))
+
 (defun gnus-summary-catchup-all (&optional quietly)
-  "Mark all articles in this newsgroup as read."
+  "Mark all articles in this newsgroup as read.
+This command is dangerous.  Normally, you want \\[gnus-summary-catchup]
+instead, which marks only unread articles as read."
   (interactive "P")
   (gnus-summary-catchup t quietly))
 
 (defun gnus-summary-catchup-and-exit (&optional all quietly)
-  "Mark all articles not marked as unread in this newsgroup as read, then exit.
-If prefix argument ALL is non-nil, all articles are marked as read."
+  "Mark all unread articles in this group as read, then exit.
+If prefix argument ALL is non-nil, all articles are marked as read.
+If QUIETLY is non-nil, no questions will be asked."
   (interactive "P")
   (when (gnus-summary-catchup all quietly nil 'fast)
     ;; Select next newsgroup or exit.
-    (if (eq gnus-auto-select-next 'quietly)
+    (if (and (not (gnus-group-quit-config gnus-newsgroup-name))
+            (eq gnus-auto-select-next 'quietly))
        (gnus-summary-next-group nil)
       (gnus-summary-exit))))
 
 (defun gnus-summary-catchup-all-and-exit (&optional quietly)
-  "Mark all articles in this newsgroup as read, and then exit."
+  "Mark all articles in this newsgroup as read, and then exit.
+This command is dangerous.  Normally, you want \\[gnus-summary-catchup-and-exit]
+instead, which marks only unread articles as read."
   (interactive "P")
   (gnus-summary-catchup-and-exit t quietly))
 
-;; Suggested by "Arne Eofsson" <arne@hodgkin.mbi.ucla.edu>.
 (defun gnus-summary-catchup-and-goto-next-group (&optional all)
   "Mark all articles in this group as read and select the next group.
 If given a prefix, mark all articles, unread as well as ticked, as
@@ -8076,7 +10379,38 @@ read."
   (interactive "P")
   (save-excursion
     (gnus-summary-catchup all))
-  (gnus-summary-next-article t nil nil t))
+  (gnus-summary-next-group))
+
+;;;
+;;; with article
+;;;
+
+(defmacro gnus-with-article (article &rest forms)
+  "Select ARTICLE and perform FORMS in the original article buffer.
+Then replace the article with the result."
+  `(progn
+     ;; We don't want the article to be marked as read.
+     (let (gnus-mark-article-hook)
+       (gnus-summary-select-article t t nil ,article))
+     (set-buffer gnus-original-article-buffer)
+     ,@forms
+     (if (not (gnus-check-backend-function
+              'request-replace-article (car gnus-article-current)))
+        (gnus-message 5 "Read-only group; not replacing")
+       (unless (gnus-request-replace-article
+               ,article (car gnus-article-current)
+               (current-buffer) t)
+        (error "Couldn't replace article")))
+     ;; The cache and backlog have to be flushed somewhat.
+     (when gnus-keep-backlog
+       (gnus-backlog-remove-article
+       (car gnus-article-current) (cdr gnus-article-current)))
+     (when gnus-use-cache
+       (gnus-cache-update-article
+       (car gnus-article-current) (cdr gnus-article-current)))))
+
+(put 'gnus-with-article 'lisp-indent-function 1)
+(put 'gnus-with-article 'edebug-form-spec '(form body))
 
 ;; Thread-based commands.
 
@@ -8155,28 +10489,22 @@ is non-nil or the Subject: of both articles are the same."
                         (gnus-summary-article-header parent-article))))
        (unless (and message-id (not (equal message-id "")))
          (error "No message-id in desired parent"))
-       ;; We don't want the article to be marked as read.
-       (let (gnus-mark-article-hook)
-         (gnus-summary-select-article t t nil current-article))
-       (set-buffer gnus-original-article-buffer)
-       (let ((buf (format "%s" (buffer-string))))
-         (nnheader-temp-write nil
-           (insert buf)
+       (gnus-with-article current-article
+         (save-restriction
            (goto-char (point-min))
+           (message-narrow-to-head)
            (if (re-search-forward "^References: " nil t)
                (progn
                  (re-search-forward "^[^ \t]" nil t)
                  (forward-line -1)
                  (end-of-line)
                  (insert " " message-id))
-             (insert "References: " message-id "\n"))
-           (unless (gnus-request-replace-article
-                    current-article (car gnus-article-current)
-                    (current-buffer))
-             (error "Couldn't replace article"))))
+             (insert "References: " message-id "\n"))))
        (set-buffer gnus-summary-buffer)
        (gnus-summary-unmark-all-processable)
        (gnus-summary-update-article current-article)
+       (if (gnus-summary-goto-subject (cdr gnus-article-current) nil t)
+           (gnus-summary-update-secondary-mark (cdr gnus-article-current)))
        (gnus-summary-rethread-current)
        (gnus-message 3 "Article %d is now the child of article %d"
                      current-article parent-article)))))
@@ -8208,8 +10536,8 @@ Returns nil if no thread was there to be shown."
   (interactive)
   (let ((buffer-read-only nil)
        (orig (point))
-       ;; first goto end then to beg, to have point at beg after let
-       (end (progn (end-of-line) (point)))
+       (end (gnus-point-at-eol))
+       ;; Leave point at bol
        (beg (progn (beginning-of-line) (point))))
     (prog1
        ;; Any hidden lines here?
@@ -8218,18 +10546,49 @@ Returns nil if no thread was there to be shown."
       (goto-char orig)
       (gnus-summary-position-point))))
 
-(defun gnus-summary-hide-all-threads ()
-  "Hide all thread subtrees."
+(defun gnus-summary-maybe-hide-threads ()
+  "If requested, hide the threads that should be hidden."
+  (when (and gnus-show-threads
+            gnus-thread-hide-subtree)
+    (gnus-summary-hide-all-threads
+     (if (or (consp gnus-thread-hide-subtree)
+            (functionp gnus-thread-hide-subtree))
+        (gnus-make-predicate gnus-thread-hide-subtree)
+       nil))))
+
+;;; Hiding predicates.
+
+(defun gnus-article-unread-p (header)
+  (memq (mail-header-number header) gnus-newsgroup-unreads))
+
+(defun gnus-article-unseen-p (header)
+  (memq (mail-header-number header) gnus-newsgroup-unseen))
+
+(defun gnus-map-articles (predicate articles)
+  "Map PREDICATE over ARTICLES and return non-nil if any predicate is non-nil."
+  (apply 'gnus-or (mapcar predicate
+                         (mapcar 'gnus-summary-article-header articles))))
+
+(defun gnus-summary-hide-all-threads (&optional predicate)
+  "Hide all thread subtrees.
+If PREDICATE is supplied, threads that satisfy this predicate
+will not be hidden."
   (interactive)
   (save-excursion
     (goto-char (point-min))
-    (gnus-summary-hide-thread)
-    (while (zerop (gnus-summary-next-thread 1 t))
-      (gnus-summary-hide-thread)))
+    (let ((end nil))
+      (while (not end)
+       (when (or (not predicate)
+                 (gnus-map-articles
+                  predicate (gnus-summary-article-children)))
+           (gnus-summary-hide-thread))
+       (setq end (not (zerop (gnus-summary-next-thread 1 t)))))))
   (gnus-summary-position-point))
 
 (defun gnus-summary-hide-thread ()
   "Hide thread subtrees.
+If PREDICATE is supplied, threads that satisfy this predicate
+will not be hidden.
 Returns nil if no threads were there to be hidden."
   (interactive)
   (let ((buffer-read-only nil)
@@ -8248,9 +10607,7 @@ Returns nil if no threads were there to be hidden."
                (subst-char-in-region start (point) ?\n ?\^M)
                (gnus-summary-goto-subject article))
            (goto-char start)
-           nil)
-       ;;(gnus-summary-position-point)
-       ))))
+           nil)))))
 
 (defun gnus-summary-go-to-next-thread (&optional previous)
   "Go to the same level (or less) next thread.
@@ -8329,7 +10686,7 @@ taken."
 
 (defun gnus-summary-up-thread (n)
   "Go up thread N steps.
-If N is negative, go up instead.
+If N is negative, go down instead.
 Returns the difference between N and how many steps down that were
 taken."
   (interactive "p")
@@ -8380,16 +10737,22 @@ Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'number reverse))
 
+(defun gnus-summary-sort-by-random (&optional reverse)
+  "Randomize the order in the summary buffer.
+Argument REVERSE means to randomize in reverse order."
+  (interactive "P")
+  (gnus-summary-sort 'random reverse))
+
 (defun gnus-summary-sort-by-author (&optional reverse)
   "Sort the summary buffer by author name alphabetically.
-If case-fold-search is non-nil, case of letters is ignored.
+If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'author reverse))
 
 (defun gnus-summary-sort-by-subject (&optional reverse)
   "Sort the summary buffer by subject alphabetically.  `Re:'s are ignored.
-If case-fold-search is non-nil, case of letters is ignored.
+If `case-fold-search' is non-nil, case of letters is ignored.
 Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'subject reverse))
@@ -8407,34 +10770,50 @@ Argument REVERSE means reverse order."
   (gnus-summary-sort 'score reverse))
 
 (defun gnus-summary-sort-by-lines (&optional reverse)
-  "Sort the summary buffer by article length.
+  "Sort the summary buffer by the number of lines.
 Argument REVERSE means reverse order."
   (interactive "P")
   (gnus-summary-sort 'lines reverse))
 
+(defun gnus-summary-sort-by-chars (&optional reverse)
+  "Sort the summary buffer by article length.
+Argument REVERSE means reverse order."
+  (interactive "P")
+  (gnus-summary-sort 'chars reverse))
+
+(defun gnus-summary-sort-by-original (&optional reverse)
+  "Sort the summary buffer using the default sorting method.
+Argument REVERSE means reverse order."
+  (interactive "P")
+  (let* ((buffer-read-only)
+        (gnus-summary-prepare-hook nil))
+    ;; We do the sorting by regenerating the threads.
+    (gnus-summary-prepare)
+    ;; Hide subthreads if needed.
+    (gnus-summary-maybe-hide-threads)))
+
 (defun gnus-summary-sort (predicate reverse)
   "Sort summary buffer by PREDICATE.  REVERSE means reverse order."
   (let* ((thread (intern (format "gnus-thread-sort-by-%s" predicate)))
         (article (intern (format "gnus-article-sort-by-%s" predicate)))
         (gnus-thread-sort-functions
-         (list
-          (if (not reverse)
-              thread
-            `(lambda (t1 t2)
-               (,thread t2 t1)))))
+         (if (not reverse)
+             thread
+           `(lambda (t1 t2)
+              (,thread t2 t1))))
+        (gnus-sort-gathered-threads-function
+         gnus-thread-sort-functions)
         (gnus-article-sort-functions
-         (list
-          (if (not reverse)
-              article
-            `(lambda (t1 t2)
-               (,article t2 t1)))))
+         (if (not reverse)
+             article
+           `(lambda (t1 t2)
+              (,article t2 t1))))
         (buffer-read-only)
         (gnus-summary-prepare-hook nil))
     ;; We do the sorting by regenerating the threads.
     (gnus-summary-prepare)
     ;; Hide subthreads if needed.
-    (when (and gnus-show-threads gnus-thread-hide-subtree)
-      (gnus-summary-hide-all-threads))))
+    (gnus-summary-maybe-hide-threads)))
 
 ;; Summary saving commands.
 
@@ -8450,10 +10829,9 @@ The variable `gnus-default-article-saver' specifies the saver function."
         (save-buffer (save-excursion
                        (nnheader-set-temp-buffer " *Gnus Save*")))
         (num (length articles))
-        header article file)
-    (while articles
-      (setq header (gnus-summary-article-header
-                   (setq article (pop articles))))
+        header file)
+    (dolist (article articles)
+      (setq header (gnus-summary-article-header article))
       (if (not (vectorp header))
          ;; This is a pseudo-article.
          (if (assq 'name header)
@@ -8461,7 +10839,9 @@ The variable `gnus-default-article-saver' specifies the saver function."
            (gnus-message 1 "Article %d is unsaveable" article))
        ;; This is a real article.
        (save-window-excursion
-         (gnus-summary-select-article t nil nil article))
+         (let ((gnus-display-mime-function nil)
+               (gnus-article-prepare-hook nil))
+           (gnus-summary-select-article t nil nil article)))
        (save-excursion
          (set-buffer save-buffer)
          (erase-buffer)
@@ -8475,16 +10855,22 @@ The variable `gnus-default-article-saver' specifies the saver function."
     (gnus-set-mode-line 'summary)
     n))
 
-(defun gnus-summary-pipe-output (&optional arg)
+(defun gnus-summary-pipe-output (&optional arg headers)
   "Pipe the current article to a subprocess.
 If N is a positive number, pipe the N next articles.
 If N is a negative number, pipe the N previous articles.
 If N is nil and any articles have been marked with the process mark,
-pipe those articles instead."
-  (interactive "P")
-  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe))
+pipe those articles instead.
+If HEADERS (the symbolic prefix), include the headers, too."
+  (interactive (gnus-interactive "P\ny"))
+  (require 'gnus-art)
+  (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)
+       (gnus-save-all-headers (or headers gnus-save-all-headers)))
     (gnus-summary-save-article arg t))
-  (gnus-configure-windows 'pipe))
+  (let ((buffer (get-buffer "*Shell Command Output*")))
+    (when (and buffer
+              (not (zerop (buffer-size buffer))))
+      (gnus-configure-windows 'pipe))))
 
 (defun gnus-summary-save-article-mail (&optional arg)
   "Append the current article to an mail file.
@@ -8493,6 +10879,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-mail))
     (gnus-summary-save-article arg)))
 
@@ -8503,6 +10890,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-rmail))
     (gnus-summary-save-article arg)))
 
@@ -8513,6 +10901,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-in-file))
     (gnus-summary-save-article arg)))
 
@@ -8523,6 +10912,7 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-write-to-file))
     (gnus-summary-save-article arg)))
 
@@ -8533,22 +10923,33 @@ If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
   (interactive "P")
+  (require 'gnus-art)
   (let ((gnus-default-article-saver 'gnus-summary-save-body-in-file))
     (gnus-summary-save-article arg)))
 
+(defun gnus-summary-muttprint (&optional arg)
+  "Print the current article using Muttprint.
+If N is a positive number, save the N next articles.
+If N is a negative number, save the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+save those articles instead."
+  (interactive "P")
+  (require 'gnus-art)
+  (let ((gnus-default-article-saver 'gnus-summary-pipe-to-muttprint))
+    (gnus-summary-save-article arg t)))
+
 (defun gnus-summary-pipe-message (program)
   "Pipe the current article through PROGRAM."
   (interactive "sProgram: ")
   (gnus-summary-select-article)
-  (let ((mail-header-separator "")
-        (art-buf (get-buffer gnus-article-buffer)))
+  (let ((mail-header-separator ""))
     (gnus-eval-in-buffer-window gnus-article-buffer
       (save-restriction
-        (widen)
-        (let ((start (window-start))
-              buffer-read-only)
-          (message-pipe-buffer-body program)
-          (set-window-start (get-buffer-window (current-buffer)) start))))))
+       (widen)
+       (let ((start (window-start))
+             buffer-read-only)
+         (message-pipe-buffer-body program)
+         (set-window-start (get-buffer-window (current-buffer)) start))))))
 
 (defun gnus-get-split-value (methods)
   "Return a value based on the split METHODS."
@@ -8558,7 +10959,7 @@ save those articles instead."
        (set-buffer gnus-original-article-buffer)
        (save-restriction
          (nnheader-narrow-to-headers)
-         (while methods
+         (while (and methods (not split-name))
            (goto-char (point-min))
            (setq method (pop methods))
            (setq match (car method))
@@ -8567,7 +10968,7 @@ save those articles instead."
                    ;; Regular expression.
                    (ignore-errors
                      (re-search-forward match nil t)))
-                  ((gnus-functionp match)
+                  ((functionp match)
                    ;; Function.
                    (save-restriction
                      (widen)
@@ -8577,23 +10978,21 @@ save those articles instead."
                    (save-restriction
                      (widen)
                      (setq result (eval match)))))
-             (setq split-name (append (cdr method) split-name))
+             (setq split-name (cdr method))
              (cond ((stringp result)
                     (push (expand-file-name
                            result gnus-article-save-directory)
                           split-name))
                    ((consp result)
                     (setq split-name (append result split-name)))))))))
-    split-name))
+    (nreverse split-name)))
 
 (defun gnus-valid-move-group-p (group)
   (and (boundp group)
        (symbol-name group)
-       (memq 'respool
-            (assoc (symbol-name
-                    (car (gnus-find-method-for-group
-                          (symbol-name group))))
-                   gnus-valid-select-methods))))
+       (symbol-value group)
+       (gnus-get-function (gnus-find-method-for-group
+                          (symbol-name group)) 'request-accept-article t)))
 
 (defun gnus-read-move-group-name (prompt default articles prefix)
   "Read a group name."
@@ -8608,23 +11007,27 @@ save those articles instead."
         (to-newsgroup
          (cond
           ((null split-name)
-           (gnus-completing-read default prom
-                                 gnus-active-hashtb
-                                 'gnus-valid-move-group-p
-                                 nil prefix
-                                 'gnus-group-history))
+           (gnus-completing-read-with-default
+            default prom
+            gnus-active-hashtb
+            'gnus-valid-move-group-p
+            nil prefix
+            'gnus-group-history))
           ((= 1 (length split-name))
-           (gnus-completing-read (car split-name) prom
-                                 gnus-active-hashtb
-                                 'gnus-valid-move-group-p
-                                 nil nil
-                                 'gnus-group-history))
+           (gnus-completing-read-with-default
+            (car split-name) prom
+            gnus-active-hashtb
+            'gnus-valid-move-group-p
+            nil nil
+            'gnus-group-history))
           (t
-           (gnus-completing-read nil prom
-                                 (mapcar (lambda (el) (list el))
-                                         (nreverse split-name))
-                                 nil nil nil
-                                 'gnus-group-history)))))
+           (gnus-completing-read-with-default
+            nil prom
+            (mapcar (lambda (el) (list el))
+                    (nreverse split-name))
+            nil nil nil
+            'gnus-group-history))))
+        (to-method (gnus-server-to-method (gnus-group-method to-newsgroup))))
     (when to-newsgroup
       (if (or (string= to-newsgroup "")
              (string= to-newsgroup prefix))
@@ -8632,18 +11035,68 @@ save those articles instead."
       (unless to-newsgroup
        (error "No group name entered"))
       (or (gnus-active to-newsgroup)
-         (gnus-activate-group to-newsgroup)
+         (gnus-activate-group to-newsgroup nil nil to-method)
          (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
                                     to-newsgroup))
-             (or (and (gnus-request-create-group
-                       to-newsgroup (gnus-group-name-to-method to-newsgroup))
-                      (gnus-activate-group to-newsgroup nil nil
-                                           (gnus-group-name-to-method
-                                            to-newsgroup)))
+             (or (and (gnus-request-create-group to-newsgroup to-method)
+                      (gnus-activate-group
+                       to-newsgroup nil nil to-method)
+                      (gnus-subscribe-group to-newsgroup))
                  (error "Couldn't create group %s" to-newsgroup)))
          (error "No such group: %s" to-newsgroup)))
     to-newsgroup))
 
+(defun gnus-summary-save-parts (type dir n &optional reverse)
+  "Save parts matching TYPE to DIR.
+If REVERSE, save parts that do not match TYPE."
+  (interactive
+   (list (read-string "Save parts of type: "
+                     (or (car gnus-summary-save-parts-type-history)
+                         gnus-summary-save-parts-default-mime)
+                     'gnus-summary-save-parts-type-history)
+        (setq gnus-summary-save-parts-last-directory
+              (read-file-name "Save to directory: "
+                              gnus-summary-save-parts-last-directory
+                              nil t))
+        current-prefix-arg))
+  (gnus-summary-iterate n
+    (let ((gnus-display-mime-function nil)
+         (gnus-inhibit-treatment t))
+      (gnus-summary-select-article))
+    (save-excursion
+      (set-buffer gnus-article-buffer)
+      (let ((handles (or gnus-article-mime-handles
+                        (mm-dissect-buffer nil gnus-article-loose-mime)
+                        (and gnus-article-emulate-mime
+                             (mm-uu-dissect)))))
+       (when handles
+         (gnus-summary-save-parts-1 type dir handles reverse)
+         (unless gnus-article-mime-handles ;; Don't destroy this case.
+           (mm-destroy-parts handles)))))))
+
+(defun gnus-summary-save-parts-1 (type dir handle reverse)
+  (if (stringp (car handle))
+      (mapcar (lambda (h) (gnus-summary-save-parts-1 type dir h reverse))
+             (cdr handle))
+    (when (if reverse
+             (not (string-match type (mm-handle-media-type handle)))
+           (string-match type (mm-handle-media-type handle)))
+      (let ((file (expand-file-name
+                  (gnus-map-function
+                   mm-file-name-rewrite-functions
+                   (file-name-nondirectory
+                    (or
+                     (mail-content-type-get
+                      (mm-handle-disposition handle) 'filename)
+                     (mail-content-type-get
+                      (mm-handle-type handle) 'name)
+                     (concat gnus-newsgroup-name
+                             "." (number-to-string
+                                  (cdr gnus-article-current))))))
+                  dir)))
+       (unless (file-exists-p file)
+         (mm-save-part-to-file handle file))))))
+
 ;; Summary extract commands
 
 (defun gnus-summary-insert-pseudos (pslist &optional not-view)
@@ -8706,7 +11159,9 @@ save those articles instead."
          (gnus-data-enter
           after-article gnus-reffed-article-number
           gnus-unread-mark b (car pslist) 0 (- e b))
-         (push gnus-reffed-article-number gnus-newsgroup-unreads)
+         (setq gnus-newsgroup-unreads
+               (gnus-add-to-sorted-list gnus-newsgroup-unreads
+                                        gnus-reffed-article-number))
          (setq gnus-reffed-article-number (1- gnus-reffed-article-number))
          (setq pslist (cdr pslist)))))))
 
@@ -8756,8 +11211,10 @@ save those articles instead."
   "Read the headers of article ID and enter them into the Gnus system."
   (let ((group gnus-newsgroup-name)
        (gnus-override-method
-        (and (gnus-news-group-p gnus-newsgroup-name)
-             gnus-refer-article-method))
+        (or
+         gnus-override-method
+         (and (gnus-news-group-p gnus-newsgroup-name)
+              (car (gnus-refer-article-methods)))))
        where)
     ;; First we check to see whether the header in question is already
     ;; fetched.
@@ -8775,9 +11232,7 @@ save those articles instead."
       (when (and header
                 (gnus-summary-article-sparse-p (mail-header-number header)))
        (let* ((parent (gnus-parent-id (mail-header-references header)))
-              (thread
-               (and parent
-                    (gnus-gethash parent gnus-newsgroup-dependencies))))
+              (thread (and parent (gnus-id-to-thread parent))))
          (when thread
            (delq (assq header thread) thread))))
       ;; We have to really fetch the header to this article.
@@ -8833,12 +11288,12 @@ save those articles instead."
 ;;;
 
 (defun gnus-highlight-selected-summary ()
+  "Highlight selected article in summary buffer."
   ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
-  ;; Highlight selected article in summary buffer
   (when gnus-summary-selected-face
     (save-excursion
-      (let* ((beg (progn (beginning-of-line) (point)))
-            (end (progn (end-of-line) (point)))
+      (let* ((beg (gnus-point-at-bol))
+            (end (gnus-point-at-eol))
             ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
             (from (if (get-text-property beg gnus-mouse-face-prop)
                       beg
@@ -8865,41 +11320,55 @@ save those articles instead."
           (setq gnus-newsgroup-selected-overlay (gnus-make-overlay from to))
           'face gnus-summary-selected-face))))))
 
-;; New implementation by Christian Limpach <Christian.Limpach@nice.ch>.
+(defvar gnus-summary-highlight-line-cached nil)
+(defvar gnus-summary-highlight-line-trigger nil)
+
+(defun gnus-summary-highlight-line-0 ()
+  (if (and (eq gnus-summary-highlight-line-trigger
+               gnus-summary-highlight)
+           gnus-summary-highlight-line-cached)
+      gnus-summary-highlight-line-cached
+    (setq gnus-summary-highlight-line-trigger gnus-summary-highlight
+          gnus-summary-highlight-line-cached
+          (let* ((cond (list 'cond))
+                 (c cond)
+                 (list gnus-summary-highlight))
+            (while list
+              (setcdr c (cons (list (caar list) (list 'quote (cdar list)))
+                             nil))
+              (setq c (cdr c)
+                    list (cdr list)))
+            (gnus-byte-compile (list 'lambda nil cond))))))
+
 (defun gnus-summary-highlight-line ()
   "Highlight current line according to `gnus-summary-highlight'."
-  (let* ((list gnus-summary-highlight)
-        (p (point))
-        (end (progn (end-of-line) (point)))
-        ;; now find out where the line starts and leave point there.
-        (beg (progn (beginning-of-line) (point)))
-        (article (gnus-summary-article-number))
-        (score (or (cdr (assq (or article gnus-current-article)
+  (let* ((beg (gnus-point-at-bol))
+        (article (or (gnus-summary-article-number) gnus-current-article))
+        (score (or (cdr (assq article
                               gnus-newsgroup-scored))
                    gnus-summary-default-score 0))
         (mark (or (gnus-summary-article-mark) gnus-unread-mark))
-        (inhibit-read-only t))
-    ;; Eval the cars of the lists until we find a match.
-    (let ((default gnus-summary-default-score))
-      (while (and list
-                 (not (eval (caar list))))
-       (setq list (cdr list))))
-    (let ((face (cdar list)))
+        (inhibit-read-only t)
+        (default gnus-summary-default-score)
+        (default-high gnus-summary-default-high-score)
+        (default-low gnus-summary-default-low-score)
+        (uncached (and gnus-summary-use-undownloaded-faces
+                        (memq article gnus-newsgroup-undownloaded))))
+    (let ((face (funcall (gnus-summary-highlight-line-0))))
       (unless (eq face (get-text-property beg 'face))
-       (gnus-put-text-property
-        beg end 'face
+       (gnus-put-text-property-excluding-characters-with-faces
+        beg (gnus-point-at-eol) 'face
         (setq face (if (boundp face) (symbol-value face) face)))
        (when gnus-summary-highlight-line-function
-         (funcall gnus-summary-highlight-line-function article face))))
-    (goto-char p)))
+         (funcall gnus-summary-highlight-line-function article face))))))
 
 (defun gnus-update-read-articles (group unread &optional compute)
-  "Update the list of read articles in GROUP."
+  "Update the list of read articles in GROUP.
+UNREAD is a sorted list."
   (let* ((active (or gnus-newsgroup-active (gnus-active group)))
         (entry (gnus-gethash group gnus-newsrc-hashtb))
         (info (nth 2 entry))
         (prev 1)
-        (unread (sort (copy-sequence unread) '<))
         read)
     (if (or (not info) (not active))
        ;; There is no info on this group if it was, in fact,
@@ -8925,44 +11394,62 @@ save those articles instead."
        (setq unread (cdr unread)))
       (when (<= prev (cdr active))
        (push (cons prev (cdr active)) read))
+      (setq read (if (> (length read) 1) (nreverse read) read))
       (if compute
-         (if (> (length read) 1) (nreverse read) read)
+         read
        (save-excursion
-         (set-buffer gnus-group-buffer)
-         (gnus-undo-register
-           `(progn
-              (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
-              (gnus-info-set-read ',info ',(gnus-info-read info))
-              (gnus-get-unread-articles-in-group ',info (gnus-active ,group))
-              (gnus-group-update-group ,group t))))
+         (let (setmarkundo)
+           ;; Propagate the read marks to the backend.
+           (when (gnus-check-backend-function 'request-set-mark group)
+             (let ((del (gnus-remove-from-range (gnus-info-read info) read))
+                   (add (gnus-remove-from-range read (gnus-info-read info))))
+               (when (or add del)
+                 (unless (gnus-check-group group)
+                   (error "Can't open server for %s" group))
+                 (gnus-request-set-mark
+                  group (delq nil (list (if add (list add 'add '(read)))
+                                        (if del (list del 'del '(read))))))
+                 (setq setmarkundo
+                       `(gnus-request-set-mark
+                         ,group
+                         ',(delq nil (list
+                                      (if del (list del 'add '(read)))
+                                      (if add (list add 'del '(read))))))))))
+           (set-buffer gnus-group-buffer)
+           (gnus-undo-register
+             `(progn
+                (gnus-info-set-marks ',info ',(gnus-info-marks info) t)
+                (gnus-info-set-read ',info ',(gnus-info-read info))
+                (gnus-get-unread-articles-in-group ',info
+                                                   (gnus-active ,group))
+                (gnus-group-update-group ,group t)
+                ,setmarkundo))))
        ;; Enter this list into the group info.
-       (gnus-info-set-read
-        info (if (> (length read) 1) (nreverse read) read))
+       (gnus-info-set-read info read)
        ;; Set the number of unread articles in gnus-newsrc-hashtb.
        (gnus-get-unread-articles-in-group info (gnus-active group))
        t))))
 
 (defun gnus-offer-save-summaries ()
   "Offer to save all active summary buffers."
-  (save-excursion
-    (let ((buflist (buffer-list))
-         buffers bufname)
-      ;; Go through all buffers and find all summaries.
-      (while buflist
-       (and (setq bufname (buffer-name (car buflist)))
-            (string-match "Summary" bufname)
-            (save-excursion
-              (set-buffer bufname)
-              ;; We check that this is, indeed, a summary buffer.
-              (and (eq major-mode 'gnus-summary-mode)
-                   ;; Also make sure this isn't bogus.
-                   gnus-newsgroup-prepared
-                   ;; Also make sure that this isn't a dead summary buffer.
-                   (not gnus-dead-summary-mode)))
-            (push bufname buffers))
-       (setq buflist (cdr buflist)))
-      ;; Go through all these summary buffers and offer to save them.
-      (when buffers
+  (let (buffers)
+    ;; Go through all buffers and find all summaries.
+    (dolist (buffer (buffer-list))
+      (when (and (setq buffer (buffer-name buffer))
+                (string-match "Summary" buffer)
+                (save-excursion
+                  (set-buffer buffer)
+                  ;; We check that this is, indeed, a summary buffer.
+                  (and (eq major-mode 'gnus-summary-mode)
+                       ;; Also make sure this isn't bogus.
+                       gnus-newsgroup-prepared
+                       ;; Also make sure that this isn't a
+                       ;; dead summary buffer.
+                       (not gnus-dead-summary-mode))))
+       (push buffer buffers)))
+    ;; Go through all these summary buffers and offer to save them.
+    (when buffers
+      (save-excursion
        (map-y-or-n-p
         "Update summary buffer %s? "
         (lambda (buf)
@@ -8970,10 +11457,511 @@ save those articles instead."
           (gnus-summary-exit))
         buffers)))))
 
+
+;;; @ for mime-partial
+;;;
+
+(defun gnus-request-partial-message ()
+  (save-excursion
+    (let ((number (gnus-summary-article-number))
+         (group gnus-newsgroup-name)
+         (mother gnus-article-buffer))
+      (set-buffer (get-buffer-create " *Partial Article*"))
+      (erase-buffer)
+      (setq mime-preview-buffer mother)
+      (gnus-request-article-this-buffer number group)
+      (mime-parse-buffer)
+      )))
+
+(autoload 'mime-combine-message/partial-pieces-automatically
+  "mime-partial"
+  "Internal method to combine message/partial messages automatically.")
+
+(mime-add-condition
+ 'action '((type . message)(subtype . partial)
+          (major-mode . gnus-original-article-mode)
+          (method . mime-combine-message/partial-pieces-automatically)
+          (summary-buffer-exp . gnus-summary-buffer)
+          (request-partial-message-method . gnus-request-partial-message)
+          ))
+
+
+;;; @ for message/rfc822
+;;;
+
+(defun gnus-mime-extract-message/rfc822 (entity situation)
+  "Burst a forwarded article."
+  (save-excursion
+    (set-buffer gnus-summary-buffer)
+    (let* ((group (completing-read "Group: " gnus-active-hashtb nil t
+                                  gnus-newsgroup-name 'gnus-group-history))
+          (gnus-group-marked (list group))
+          article info)
+      (with-temp-buffer
+       (mime-insert-entity-content entity)
+       (setq article (gnus-request-accept-article group)))
+      (when (and (consp article)
+                (numberp (setq article (cdr article))))
+       (setq info (gnus-get-info group))
+       (gnus-info-set-read info
+                           (gnus-remove-from-range (gnus-info-read info)
+                                                   (list article)))
+       (when (string-equal group gnus-newsgroup-name)
+         (forward-line 1)
+         (let (gnus-show-threads)
+           (gnus-summary-goto-subject article t))
+         (gnus-summary-clear-mark-forward 1))
+       (set-buffer gnus-group-buffer)
+       (gnus-group-get-new-news-this-group nil t)))))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . rfc822)
+          (major-mode . gnus-original-article-mode)
+          (method . gnus-mime-extract-message/rfc822)
+          (mode . "extract")
+          ))
+
+(mime-add-condition
+ 'action '((type . message)(subtype . news)
+          (major-mode . gnus-original-article-mode)
+          (method . gnus-mime-extract-message/rfc822)
+          (mode . "extract")
+          ))
+
+(defun gnus-mime-extract-multipart (entity situation)
+  (let ((children (mime-entity-children entity))
+       mime-acting-situation-to-override
+       f)
+    (while children
+      (mime-play-entity (car children)
+                       (cons (assq 'mode situation)
+                             mime-acting-situation-to-override))
+      (setq children (cdr children)))
+    (if (setq f (cdr (assq 'after-method
+                          mime-acting-situation-to-override)))
+       (eval f)
+      )))
+
+(mime-add-condition
+ 'action '((type . multipart)
+          (method . gnus-mime-extract-multipart)
+          (mode . "extract")
+          )
+ 'with-default)
+
+
+;;; @ end
+;;;
+
+(defun gnus-summary-inherit-default-charset ()
+  "Import `default-mime-charset' from summary buffer.
+Also take care of `default-mime-charset-unlimited' if the LIMIT version
+of FLIM is used."
+  (if (buffer-live-p gnus-summary-buffer)
+      (let (d-m-c d-m-c-u)
+       (with-current-buffer gnus-summary-buffer
+         (setq d-m-c (if (local-variable-p 'default-mime-charset
+                                           gnus-summary-buffer)
+                         default-mime-charset
+                       t)
+               ;; LIMIT
+               d-m-c-u (if (local-variable-p 'default-mime-charset-unlimited
+                                             gnus-summary-buffer)
+                           (symbol-value 'default-mime-charset-unlimited)
+                         t)))
+       (if (eq t d-m-c)
+           (kill-local-variable 'default-mime-charset)
+         (set (make-local-variable 'default-mime-charset) d-m-c))
+       (if (eq t d-m-c-u)
+           (kill-local-variable 'default-mime-charset-unlimited)
+         (set (make-local-variable 'default-mime-charset-unlimited)
+              d-m-c-u)))))
+
+(defun gnus-summary-setup-default-charset ()
+  "Setup newsgroup default charset."
+  (if (member gnus-newsgroup-name '("nndraft:delayed" "nndraft:drafts"))
+      (progn
+       (setq gnus-newsgroup-charset nil)
+       (set (make-local-variable 'default-mime-charset) nil)
+       (when (boundp 'default-mime-charset-unlimited);; LIMIT
+         (set (make-local-variable 'default-mime-charset-unlimited) nil)))
+    (let ((ignored-charsets
+          (or gnus-newsgroup-ephemeral-ignored-charsets
+              (append
+               (and gnus-newsgroup-name
+                    (gnus-parameter-ignored-charsets gnus-newsgroup-name))
+               gnus-newsgroup-ignored-charsets)))
+         charset)
+      (setq gnus-newsgroup-charset
+           (or gnus-newsgroup-ephemeral-charset
+               (when (and gnus-newsgroup-name
+                          (setq charset (gnus-parameter-charset
+                                         gnus-newsgroup-name)))
+                 (make-local-variable 'default-mime-charset)
+                 (setq default-mime-charset charset))
+               gnus-default-charset))
+      (set (make-local-variable 'gnus-newsgroup-ignored-charsets)
+          ignored-charsets))))
+
+;;;
+;;; Mime Commands
+;;;
+
+(defun gnus-summary-display-buttonized (&optional show-all-parts)
+  "Display the current article buffer fully MIME-buttonized.
+If SHOW-ALL-PARTS (the prefix) is non-nil, all multipart/* parts are
+treated as multipart/mixed."
+  (interactive "P")
+  (require 'gnus-art)
+  (let ((gnus-unbuttonized-mime-types nil)
+       (gnus-mime-display-multipart-as-mixed show-all-parts))
+    (gnus-summary-show-article)))
+
+(defun gnus-summary-repair-multipart (article)
+  "Add a Content-Type header to a multipart article without one."
+  (interactive (list (gnus-summary-article-number)))
+  (gnus-with-article article
+    (message-narrow-to-head)
+    (message-remove-header "Mime-Version")
+    (goto-char (point-max))
+    (insert "Mime-Version: 1.0\n")
+    (widen)
+    (when (search-forward "\n--" nil t)
+      (let ((separator (buffer-substring (point) (gnus-point-at-eol))))
+       (message-narrow-to-head)
+       (message-remove-header "Content-Type")
+       (goto-char (point-max))
+       (insert (format "Content-Type: multipart/mixed; boundary=\"%s\"\n"
+                       separator))
+       (widen))))
+  (let (gnus-mark-article-hook)
+    (gnus-summary-select-article t t nil article)))
+
+(defun gnus-summary-toggle-display-buttonized ()
+  "Toggle the buttonizing of the article buffer."
+  (interactive)
+  (require 'gnus-art)
+  (if (setq gnus-inhibit-mime-unbuttonizing
+           (not gnus-inhibit-mime-unbuttonizing))
+      (let ((gnus-unbuttonized-mime-types nil))
+       (gnus-summary-show-article))
+    (gnus-summary-show-article)))
+
+;;;
+;;; Intelli-mouse commmands
+;;;
+
+(defun gnus-wheel-summary-scroll (event)
+  (interactive "e")
+  (let ((amount (if (memq 'shift (event-modifiers event))
+                   (car gnus-wheel-scroll-amount)
+                 (cdr gnus-wheel-scroll-amount)))
+       (direction (- (* (static-if (featurep 'xemacs)
+                            (event-button event)
+                          (cond ((eq 'mouse-4 (event-basic-type event))
+                                 4)
+                                ((eq 'mouse-5 (event-basic-type event))
+                                 5)))
+                        2) 9))
+       edge)
+    (gnus-summary-scroll-up (* amount direction))
+    (when (gnus-eval-in-buffer-window gnus-article-buffer
+           (save-restriction
+             (widen)
+             (and (if (< 0 direction)
+                      (gnus-article-next-page 0)
+                    (gnus-article-prev-page 0)
+                    (bobp))
+                  (if (setq edge (get-text-property
+                                  (point-min) 'gnus-wheel-edge))
+                      (setq edge (* edge direction))
+                    (setq edge -1))
+                  (or (plusp edge)
+                      (let ((buffer-read-only nil)
+                            (inhibit-read-only t))
+                        (put-text-property (point-min) (point-max)
+                                           'gnus-wheel-edge direction)
+                        nil))
+                  (or (> edge gnus-wheel-edge-resistance)
+                      (let ((buffer-read-only nil)
+                            (inhibit-read-only t))
+                        (put-text-property (point-min) (point-max)
+                                           'gnus-wheel-edge
+                                           (* (1+ edge) direction))
+                        nil))
+                  (eq last-command 'gnus-wheel-summary-scroll))))
+      (gnus-summary-next-article nil nil (minusp direction)))))
+
+(defun gnus-wheel-install ()
+  "Enable mouse wheel support on summary window."
+  (when gnus-use-wheel
+    (let ((keys
+          '([(mouse-4)] [(shift mouse-4)] [(mouse-5)] [(shift mouse-5)])))
+      (dolist (key keys)
+       (define-key gnus-summary-mode-map key
+         'gnus-wheel-summary-scroll)))))
+
+(add-hook 'gnus-summary-mode-hook 'gnus-wheel-install)
+
+;;;
+;;; Traditional PGP commmands
+;;;
+
+(defun gnus-summary-decrypt-article (&optional force)
+  "Decrypt the current article in traditional PGP way.
+This will have permanent effect only in mail groups.
+If FORCE is non-nil, allow editing of articles even in read-only
+groups."
+  (interactive "P")
+  (gnus-summary-select-article t)
+  (gnus-eval-in-buffer-window gnus-article-buffer
+    (save-excursion
+      (save-restriction
+       (widen)
+       (goto-char (point-min))
+       (unless (re-search-forward (car pgg-armor-header-lines) nil t)
+         (error "Not a traditional PGP message!"))
+       (let ((armor-start (match-beginning 0)))
+         (if (and (pgg-decrypt-region armor-start (point-max))
+                  (or force (not (gnus-group-read-only-p))))
+             (let ((inhibit-read-only t)
+                   buffer-read-only)
+               (delete-region armor-start
+                              (progn
+                                (re-search-forward "^-+END PGP" nil t)
+                                (beginning-of-line 2)
+                                (point)))
+               (insert-buffer-substring pgg-output-buffer))))))))
+
+(defun gnus-summary-verify-article ()
+  "Verify the current article in traditional PGP way."
+  (interactive)
+  (save-excursion
+    (set-buffer gnus-original-article-buffer)
+    (goto-char (point-min))
+    (unless (re-search-forward "^-+BEGIN PGP SIGNED MESSAGE" nil t)
+      (error "Not a traditional PGP message!"))
+    (re-search-forward "^-+END PGP" nil t)
+    (beginning-of-line 2)
+    (call-interactively (function pgg-verify-region))))
+
+;;;
+;;; Generic summary marking commands
+;;;
+
+(defvar gnus-summary-marking-alist
+  '((read gnus-del-mark "d")
+    (unread gnus-unread-mark "u")
+    (ticked gnus-ticked-mark "!")
+    (dormant gnus-dormant-mark "?")
+    (expirable gnus-expirable-mark "e"))
+  "An alist of names/marks/keystrokes.")
+
+(defvar gnus-summary-generic-mark-map (make-sparse-keymap))
+(defvar gnus-summary-mark-map)
+
+(defun gnus-summary-make-all-marking-commands ()
+  (define-key gnus-summary-mark-map "M" gnus-summary-generic-mark-map)
+  (dolist (elem gnus-summary-marking-alist)
+    (apply 'gnus-summary-make-marking-command elem)))
+
+(defun gnus-summary-make-marking-command (name mark keystroke)
+  (let ((map (make-sparse-keymap)))
+    (define-key gnus-summary-generic-mark-map keystroke map)
+    (dolist (lway `((next "next" next nil "n")
+                   (next-unread "next unread" next t "N")
+                   (prev "previous" prev nil "p")
+                   (prev-unread "previous unread" prev t "P")
+                   (nomove "" nil nil ,keystroke)))
+      (let ((func (gnus-summary-make-marking-command-1
+                  mark (car lway) lway name)))
+       (setq func (eval func))
+       (define-key map (nth 4 lway) func)))))
+
+(defun gnus-summary-make-marking-command-1 (mark way lway name)
+  `(defun ,(intern
+           (format "gnus-summary-put-mark-as-%s%s"
+                   name (if (eq way 'nomove)
+                            ""
+                          (concat "-" (symbol-name way)))))
+     (n)
+     ,(format
+       "Mark the current article as %s%s.
+If N, the prefix, then repeat N times.
+If N is negative, move in reverse order.
+The difference between N and the actual number of articles marked is
+returned."
+       name (car (cdr lway)))
+     (interactive "p")
+     (gnus-summary-generic-mark n ,mark ',(nth 2 lway) ,(nth 3 lway))))
+
+(defun gnus-summary-generic-mark (n mark move unread)
+  "Mark N articles with MARK."
+  (unless (eq major-mode 'gnus-summary-mode)
+    (error "This command can only be used in the summary buffer"))
+  (gnus-summary-show-thread)
+  (let ((nummove
+        (cond
+         ((eq move 'next) 1)
+         ((eq move 'prev) -1)
+         (t 0))))
+    (if (zerop nummove)
+       (setq n 1)
+      (when (< n 0)
+       (setq n (abs n)
+             nummove (* -1 nummove))))
+    (while (and (> n 0)
+               (gnus-summary-mark-article nil mark)
+               (zerop (gnus-summary-next-subject nummove unread t)))
+      (setq n (1- n)))
+    (when (/= 0 n)
+      (gnus-message 7 "No more %sarticles" (if mark "" "unread ")))
+    (gnus-summary-recenter)
+    (gnus-summary-position-point)
+    (gnus-set-mode-line 'summary)
+    n))
+
+(defun gnus-summary-insert-articles (articles)
+  (when (setq articles
+             (gnus-sorted-difference articles
+                                     (mapcar (lambda (h)
+                                               (mail-header-number h))
+                                             gnus-newsgroup-headers)))
+    (setq gnus-newsgroup-headers
+         (gnus-merge 'list
+                     gnus-newsgroup-headers
+                     (gnus-fetch-headers articles)
+                     'gnus-article-sort-by-number))
+    ;; Suppress duplicates?
+    (when gnus-suppress-duplicates
+      (gnus-dup-suppress-articles))
+
+    ;; We might want to build some more threads first.
+    (when (and gnus-fetch-old-headers
+              (eq gnus-headers-retrieved-by 'nov))
+      (if (eq gnus-fetch-old-headers 'invisible)
+         (gnus-build-all-threads)
+       (gnus-build-old-threads)))
+    ;; Let the Gnus agent mark articles as read.
+    (when gnus-agent
+      (gnus-agent-get-undownloaded-list))
+    ;; Remove list identifiers from subject
+    (when gnus-list-identifiers
+      (gnus-summary-remove-list-identifiers))
+    ;; First and last article in this newsgroup.
+    (when gnus-newsgroup-headers
+      (setq gnus-newsgroup-begin
+           (mail-header-number (car gnus-newsgroup-headers))
+           gnus-newsgroup-end
+           (mail-header-number
+            (gnus-last-element gnus-newsgroup-headers))))
+    (when gnus-use-scoring
+      (gnus-possibly-score-headers))))
+
+(defun gnus-summary-insert-old-articles (&optional all)
+  "Insert all old articles in this group.
+If ALL is non-nil, already read articles become readable.
+If ALL is a number, fetch this number of articles."
+  (interactive "P")
+  (prog1
+      (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
+           older len)
+       (setq older
+             ;; Some nntp servers lie about their active range.  When
+             ;; this happens, the active range can be in the millions.
+             ;; Use a compressed range to avoid creating a huge list.
+             (gnus-range-difference (list gnus-newsgroup-active) old))
+       (setq len (gnus-range-length older))
+       (cond
+        ((null older) nil)
+        ((numberp all)
+         (if (< all len)
+             (let ((older-range (nreverse older)))
+               (setq older nil)
+
+               (while (> all 0)
+                 (let* ((r (pop older-range))
+                        (min (if (numberp r) r (car r)))
+                        (max (if (numberp r) r (cdr r))))
+                   (while (and (<= min max)
+                               (> all 0))
+                     (push max older)
+                     (setq all (1- all)
+                           max (1- max))))))
+           (setq older (gnus-uncompress-range older))))
+        (all
+         (setq older (gnus-uncompress-range older)))
+        (t
+         (when (and (numberp gnus-large-newsgroup)
+                  (> len gnus-large-newsgroup))
+             (let* ((cursor-in-echo-area nil)
+                    (initial (gnus-parameter-large-newsgroup-initial
+                              gnus-newsgroup-name))
+                    (input
+                     (read-string
+                      (format
+                       "How many articles from %s (%s %d): "
+                       (gnus-limit-string
+                        (gnus-group-decoded-name gnus-newsgroup-name) 35)
+                       (if initial "max" "default")
+                       len)
+                      (if initial
+                          (cons (number-to-string initial)
+                                0)))))
+               (unless (string-match "^[ \t]*$" input)
+                 (setq all (string-to-number input))
+                 (if (< all len)
+                     (let ((older-range (nreverse older)))
+                       (setq older nil)
+
+                       (while (> all 0)
+                         (let* ((r (pop older-range))
+                                (min (if (numberp r) r (car r)))
+                                (max (if (numberp r) r (cdr r))))
+                           (while (and (<= min max)
+                                       (> all 0))
+                             (push max older)
+                             (setq all (1- all)
+                                   max (1- max))))))))))
+         (setq older (gnus-uncompress-range older))))
+       (if (not older)
+           (message "No old news.")
+         (gnus-summary-insert-articles older)
+         (gnus-summary-limit (gnus-sorted-nunion old older))))
+    (gnus-summary-position-point)))
+
+(defun gnus-summary-insert-new-articles ()
+  "Insert all new articles in this group."
+  (interactive)
+  (prog1
+      (let ((old (sort (mapcar 'car gnus-newsgroup-data) '<))
+           (old-active gnus-newsgroup-active)
+           (nnmail-fetched-sources (list t))
+           i new)
+       (setq gnus-newsgroup-active
+             (gnus-activate-group gnus-newsgroup-name 'scan))
+       (setq i (cdr gnus-newsgroup-active))
+       (while (> i (cdr old-active))
+         (push i new)
+         (decf i))
+       (if (not new)
+           (message "No gnus is bad news.")
+         (gnus-summary-insert-articles new)
+         (setq gnus-newsgroup-unreads
+               (gnus-sorted-nunion gnus-newsgroup-unreads new))
+         (gnus-summary-limit (gnus-sorted-nunion old new))))
+    (gnus-summary-position-point)))
+
+(gnus-summary-make-all-marking-commands)
+
 (gnus-ems-redefine)
 
 (provide 'gnus-sum)
 
 (run-hooks 'gnus-sum-load-hook)
 
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
 ;;; gnus-sum.el ends here
index 178bcb9..2352e2b 100644 (file)
@@ -1,8 +1,9 @@
 ;;; gnus-topic.el --- a folding minor mode for Gnus group buffers
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Ilja Weis <kult@uni-paderborn.de>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
 
 (require 'gnus)
 (require 'gnus-group)
 (require 'gnus-start)
+(require 'gnus-util)
 
 (defgroup gnus-topic nil
   "Group topics."
@@ -44,6 +47,9 @@
   :type 'hook
   :group 'gnus-topic)
 
+(when (featurep 'xemacs)
+  (add-hook 'gnus-topic-mode-hook 'gnus-xmas-topic-menu-add))
+
 (defcustom gnus-topic-line-format "%i[ %(%{%n%}%) -- %A ]%v\n"
   "Format of topic lines.
 It works along the same lines as a normal formatting string,
@@ -55,7 +61,10 @@ with some simple extensions.
 %g  Number of groups in the topic.
 %a  Number of unread articles in the groups in the topic.
 %A  Number of unread articles in the groups in the topic and its subtopics.
-"
+
+General format specifiers can also be used.
+See Info node `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :type 'string
   :group 'gnus-topic)
 
@@ -73,6 +82,7 @@ with some simple extensions.
 
 (defvar gnus-topic-active-topology nil)
 (defvar gnus-topic-active-alist nil)
+(defvar gnus-topic-unreads nil)
 
 (defvar gnus-topology-checked-p nil
   "Whether the topology has been checked in this session.")
@@ -108,9 +118,7 @@ with some simple extensions.
 
 (defun gnus-topic-unread (topic)
   "Return the number of unread articles in TOPIC."
-  (or (save-excursion
-       (and (gnus-topic-goto-topic topic)
-            (gnus-group-topic-unread)))
+  (or (cdr (assoc topic gnus-topic-unreads))
       0))
 
 (defun gnus-group-topic-p ()
@@ -149,11 +157,21 @@ with some simple extensions.
       (gnus-group-topic group))))
 
 (defun gnus-topic-goto-topic (topic)
-  "Go to TOPIC."
   (when topic
     (gnus-goto-char (text-property-any (point-min) (point-max)
                                       'gnus-topic (intern topic)))))
 
+(defun gnus-topic-jump-to-topic (topic)
+  "Go to TOPIC."
+  (interactive
+   (list (completing-read "Go to topic: "
+                         (mapcar 'list (gnus-topic-list))
+                         nil t)))
+  (dolist (topic (gnus-current-topics topic))
+    (gnus-topic-goto-topic topic)
+    (gnus-topic-fold t))
+  (gnus-topic-goto-topic topic))
+
 (defun gnus-current-topic ()
   "Return the name of the current topic."
   (let ((result
@@ -166,9 +184,10 @@ with some simple extensions.
     (when result
       (symbol-name result))))
 
-(defun gnus-current-topics ()
-  "Return a list of all current topics, lowest in hierarchy first."
-  (let ((topic (gnus-current-topic))
+(defun gnus-current-topics (&optional topic)
+  "Return a list of all current topics, lowest in hierarchy first.
+If TOPIC, start with that topic."
+  (let ((topic (or topic (gnus-current-topic)))
        topics)
     (while topic
       (push topic topics)
@@ -181,10 +200,11 @@ with some simple extensions.
     (beginning-of-line)
     (get-text-property (point) 'gnus-active)))
 
-(defun gnus-topic-find-groups (topic &optional level all lowest)
-  "Return entries for all visible groups in TOPIC."
+(defun gnus-topic-find-groups (topic &optional level all lowest recursive)
+  "Return entries for all visible groups in TOPIC.
+If RECURSIVE is t, return groups in its subtopics too."
   (let ((groups (cdr (assoc topic gnus-topic-alist)))
-        info clevel unread group params visible-groups entry active)
+       info clevel unread group params visible-groups entry active)
     (setq lowest (or lowest 1))
     (setq level (or level gnus-level-unsubscribed))
     ;; We go through the newsrc to look for matches.
@@ -199,18 +219,20 @@ with some simple extensions.
                              active
                              (- (1+ (cdr active)) (car active))))
              clevel (or (gnus-info-level info)
-                        (if (member group gnus-zombie-list) gnus-level-zombie gnus-level-killed))))
+                        (if (member group gnus-zombie-list)
+                            gnus-level-zombie gnus-level-killed))))
       (and
-       unread                          ; nil means that the group is dead.
+       info                            ; nil means that the group is dead.
        (<= clevel level)
        (>= clevel lowest)              ; Is inside the level we want.
        (or all
-          (if (eq unread t)
+          (if (or (eq unread t)
+                  (eq unread nil))
               gnus-group-list-inactive-groups
             (> unread 0))
           (and gnus-list-groups-with-ticked-articles
                (cdr (assq 'tick (gnus-info-marks info))))
-                                       ; Has right readedness.
+          ;; Has right readedness.
           ;; Check for permanent visibility.
           (and gnus-permanently-visible-groups
                (string-match gnus-permanently-visible-groups group))
@@ -218,7 +240,40 @@ with some simple extensions.
           (cdr (assq 'visible params)))
        ;; Add this group to the list of visible groups.
        (push (or entry group) visible-groups)))
-    (nreverse visible-groups)))
+    (setq visible-groups (nreverse visible-groups))
+    (when recursive
+      (if (eq recursive t)
+         (setq recursive (cdr (gnus-topic-find-topology topic))))
+      (mapcar (lambda (topic-topology)
+               (setq visible-groups
+                     (nconc visible-groups
+                            (gnus-topic-find-groups
+                             (caar topic-topology)
+                             level all lowest topic-topology))))
+             (cdr recursive)))
+    visible-groups))
+
+(defun gnus-topic-goto-previous-topic (n)
+  "Go to the N'th previous topic."
+  (interactive "p")
+  (gnus-topic-goto-next-topic (- n)))
+
+(defun gnus-topic-goto-next-topic (n)
+  "Go to the N'th next topic."
+  (interactive "p")
+  (let ((backward (< n 0))
+       (n (abs n))
+       (topic (gnus-current-topic)))
+    (while (and (> n 0)
+               (setq topic
+                     (if backward
+                         (gnus-topic-previous-topic topic)
+                       (gnus-topic-next-topic topic))))
+      (gnus-topic-goto-topic topic)
+      (setq n (1- n)))
+    (when (/= 0 n)
+      (gnus-message 7 "No more topics"))
+    n))
 
 (defun gnus-topic-previous-topic (topic)
   "Return the previous topic on the same level as TOPIC."
@@ -324,27 +379,40 @@ with some simple extensions.
 
 (defun gnus-group-topic-parameters (group)
   "Compute the group parameters for GROUP taking into account inheritance from topics."
-  (let ((params-list (list (gnus-group-get-parameter group)))
-       topics params param out)
+  (let ((params-list (copy-sequence (gnus-group-get-parameter group))))
     (save-excursion
-      (gnus-group-goto-group group)
-      (setq topics (gnus-current-topics))
-      (while topics
-       (push (gnus-topic-parameters (pop topics)) params-list))
-      ;; We probably have lots of nil elements here, so
-      ;; we remove them.  Probably faster than doing this "properly".
-      (setq params-list (delq nil params-list))
-      ;; Now we have all the parameters, so we go through them
-      ;; and do inheritance in the obvious way.
-      (while (setq params (pop params-list))
-       (while (setq param (pop params))
-         (when (atom param)
-           (setq param (cons param t)))
-         ;; Override any old versions of this param.
-         (setq out (delq (assq (car param) out) out))
-         (push param out)))
-      ;; Return the resulting parameter list.
-      out)))
+      (nconc params-list
+            (gnus-topic-hierarchical-parameters
+             ;; First we try to go to the group within the group
+             ;; buffer and find the topic for the group that way.
+             ;; This hopefully copes well with groups that are in
+             ;; more than one topic.  Failing that (i.e. when the
+             ;; group isn't visible in the group buffer) we find a
+             ;; topic for the group via gnus-group-topic.
+             (or (and (gnus-group-goto-group group)
+                      (gnus-current-topic))
+                 (gnus-group-topic group)))))))
+
+(defun gnus-topic-hierarchical-parameters (topic)
+  "Return a topic list computed for TOPIC."
+  (let ((topics (gnus-current-topics topic))
+       params-list param out params)
+    (while topics
+      (push (gnus-topic-parameters (pop topics)) params-list))
+    ;; We probably have lots of nil elements here, so
+    ;; we remove them.  Probably faster than doing this "properly".
+    (setq params-list (delq nil params-list))
+    ;; Now we have all the parameters, so we go through them
+    ;; and do inheritance in the obvious way.
+    (while (setq params (pop params-list))
+      (while (setq param (pop params))
+       (when (atom param)
+         (setq param (cons param t)))
+       ;; Override any old versions of this param.
+       (gnus-pull (car param) out)
+       (push param out)))
+    ;; Return the resulting parameter list.
+    out))
 
 ;;; General utility functions
 
@@ -354,15 +422,22 @@ with some simple extensions.
 
 ;;; Generating group buffers
 
-(defun gnus-group-prepare-topics (level &optional all lowest regexp list-topic topic-level)
-  "List all newsgroups with unread articles of level LEVEL or lower, and
-use the `gnus-group-topics' to sort the groups.
-If ALL is non-nil, list groups that have no unread articles.
+(defun gnus-group-prepare-topics (level &optional predicate lowest
+                                       regexp list-topic topic-level)
+  "List all newsgroups with unread articles of level LEVEL or lower.
+Use the `gnus-group-topics' to sort the groups.
+If PREDICTE is a function, list groups that the function returns non-nil;
+if it is t, list groups that have no unread articles.
 If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
   (set-buffer gnus-group-buffer)
   (let ((buffer-read-only nil)
-        (lowest (or lowest 1)))
+       (lowest (or lowest 1))
+       (not-in-list
+        (and gnus-group-listed-groups
+             (copy-sequence gnus-group-listed-groups))))
 
+    (gnus-update-format-specifications nil 'topic)
+    
     (when (or (not gnus-topic-alist)
              (not gnus-topology-checked-p))
       (gnus-topic-check-topology))
@@ -371,42 +446,63 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
       (erase-buffer))
 
     ;; List dead groups?
-    (when (and (>= level gnus-level-zombie)
-              (<= lowest gnus-level-zombie))
+    (when (or gnus-group-listed-groups
+             (and (>= level gnus-level-zombie)
+                  (<= lowest gnus-level-zombie)))
       (gnus-group-prepare-flat-list-dead
        (setq gnus-zombie-list (sort gnus-zombie-list 'string<))
        gnus-level-zombie ?Z
        regexp))
 
-    (when (and (>= level gnus-level-killed) (<= lowest gnus-level-killed))
+    (when (or gnus-group-listed-groups
+             (and (>= level gnus-level-killed)
+                  (<= lowest gnus-level-killed)))
       (gnus-group-prepare-flat-list-dead
        (setq gnus-killed-list (sort gnus-killed-list 'string<))
-       gnus-level-killed ?K
-       regexp))
+       gnus-level-killed ?K regexp)
+      (when not-in-list
+       (unless gnus-killed-hashtb
+         (gnus-make-hashtable-from-killed))
+       (gnus-group-prepare-flat-list-dead
+        (gnus-remove-if (lambda (group)
+                          (or (gnus-gethash group gnus-newsrc-hashtb)
+                              (gnus-gethash group gnus-killed-hashtb)))
+                        not-in-list)
+        gnus-level-killed ?K regexp)))
 
     ;; Use topics.
     (prog1
-       (when (< lowest gnus-level-zombie)
+       (when (or (< lowest gnus-level-zombie)
+                 gnus-group-listed-groups)
          (if list-topic
              (let ((top (gnus-topic-find-topology list-topic)))
                (gnus-topic-prepare-topic (cdr top) (car top)
-                                         (or topic-level level) all
-                                         nil lowest))
+                                         (or topic-level level) predicate
+                                         nil lowest regexp))
            (gnus-topic-prepare-topic gnus-topic-topology 0
-                                     (or topic-level level) all
-                                     nil lowest)))
-
+                                     (or topic-level level) predicate
+                                     nil lowest regexp)))
       (gnus-group-set-mode-line)
-      (setq gnus-group-list-mode (cons level all))
+      (setq gnus-group-list-mode (cons level predicate))
       (gnus-run-hooks 'gnus-group-prepare-hook))))
 
-(defun gnus-topic-prepare-topic (topicl level &optional list-level all silent
-                                       lowest)
+(defun gnus-topic-prepare-topic (topicl level &optional list-level
+                                       predicate silent
+                                       lowest regexp)
   "Insert TOPIC into the group buffer.
 If SILENT, don't insert anything.  Return the number of unread
 articles in the topic and its subtopics."
   (let* ((type (pop topicl))
-        (entries (gnus-topic-find-groups (car type) list-level all lowest))
+        (entries (gnus-topic-find-groups
+                  (car type)
+                  (if gnus-group-listed-groups
+                      gnus-level-killed
+                    list-level)
+                  (or predicate gnus-group-listed-groups
+                      (cdr (assq 'visible
+                                 (gnus-topic-hierarchical-parameters
+                                  (car type)))))
+                  (if gnus-group-listed-groups 0 lowest)))
         (visiblep (and (eq (nth 1 type) 'visible) (not silent)))
         (gnus-group-indentation
          (make-string (* gnus-topic-indent-level level) ? ))
@@ -421,31 +517,61 @@ articles in the topic and its subtopics."
     (while topicl
       (incf unread
            (gnus-topic-prepare-topic
-            (pop topicl) (1+ level) list-level all
-            (not visiblep) lowest)))
+            (pop topicl) (1+ level) list-level predicate
+            (not visiblep) lowest regexp)))
     (setq end (point))
     (goto-char beg)
     ;; Insert all the groups that belong in this topic.
     (while (setq entry (pop entries))
-      (when visiblep
-       (if (stringp entry)
-           ;; Dead groups.
-           (gnus-group-insert-group-line
-            entry (if (member entry gnus-zombie-list) gnus-level-zombie gnus-level-killed)
-            nil (- (1+ (cdr (setq active (gnus-active entry))))
-                   (car active))
-            nil)
-         ;; Living groups.
-         (when (setq info (nth 2 entry))
-           (gnus-group-insert-group-line
-            (gnus-info-group info)
-            (gnus-info-level info) (gnus-info-marks info)
-            (car entry) (gnus-info-method info)))))
-      (when (and (listp entry)
-                (numberp (car entry)))
-       (incf unread (car entry)))
-      (when (listp entry)
-       (setq tick t)))
+      (when (if (stringp entry)
+               (gnus-group-prepare-logic
+                entry
+                (and
+                 (or (not gnus-group-listed-groups)
+                     (if (< list-level gnus-level-zombie) nil
+                       (let ((entry-level
+                              (if (member entry gnus-zombie-list)
+                                  gnus-level-zombie gnus-level-killed)))
+                         (and (<= entry-level list-level)
+                              (>= entry-level lowest)))))
+                 (cond
+                  ((stringp regexp)
+                   (string-match regexp entry))
+                  ((functionp regexp)
+                   (funcall regexp entry))
+                  ((null regexp) t)
+                  (t nil))))
+             (setq info (nth 2 entry))
+             (gnus-group-prepare-logic
+              (gnus-info-group info)
+              (and (or (not gnus-group-listed-groups)
+                       (let ((entry-level (gnus-info-level info)))
+                         (and (<= entry-level list-level)
+                              (>= entry-level lowest))))
+                   (or (not (functionp predicate))
+                       (funcall predicate info))
+                   (or (not (stringp regexp))
+                       (string-match regexp (gnus-info-group info))))))
+       (when visiblep
+         (if (stringp entry)
+             ;; Dead groups.
+             (gnus-group-insert-group-line
+              entry (if (member entry gnus-zombie-list)
+                        gnus-level-zombie gnus-level-killed)
+              nil (- (1+ (cdr (setq active (gnus-active entry))))
+                     (car active))
+              nil)
+           ;; Living groups.
+           (when (setq info (nth 2 entry))
+             (gnus-group-insert-group-line
+              (gnus-info-group info)
+              (gnus-info-level info) (gnus-info-marks info)
+              (car entry) (gnus-info-method info)))))
+       (when (and (listp entry)
+                  (numberp (car entry)))
+         (incf unread (car entry)))
+       (when (listp entry)
+         (setq tick t))))
     (goto-char beg)
     ;; Insert the topic line.
     (when (and (not silent)
@@ -458,6 +584,7 @@ articles in the topic and its subtopics."
        (car type) visiblep
        (not (eq (nth 2 type) 'hidden))
        level all-entries unread))
+    (gnus-topic-update-unreads (car type) unread)
     (goto-char end)
     unread))
 
@@ -478,7 +605,7 @@ articles in the topic and its subtopics."
       (let ((data (cadr (gnus-topic-find-topology topic))))
        (setcdr data
                (list (if insert 'visible 'invisible)
-                     (if hide 'hide nil)
+                     (caddr data)
                      (cadddr data))))
       (if total-remove
          (setq gnus-topic-alist
@@ -491,9 +618,9 @@ articles in the topic and its subtopics."
    (car gnus-group-list-mode) (cdr gnus-group-list-mode)
    nil nil topic level))
 
-(defun gnus-topic-fold (&optional insert)
+(defun gnus-topic-fold (&optional insert topic)
   "Remove/insert the current topic."
-  (let ((topic (gnus-group-topic-name)))
+  (let ((topic (or topic (gnus-group-topic-name))))
     (when topic
       (save-excursion
        (if (not (gnus-group-active-topic-p))
@@ -514,17 +641,24 @@ articles in the topic and its subtopics."
         (number-of-groups (length entries))
         (active-topic (eq gnus-topic-alist gnus-topic-active-alist))
         gnus-tmp-header)
+    (gnus-topic-update-unreads name unread)
     (beginning-of-line)
     ;; Insert the text.
-    (gnus-add-text-properties
-     (point)
-     (prog1 (1+ (point))
-       (eval gnus-topic-line-format-spec))
-     (list 'gnus-topic (intern name)
-          'gnus-topic-level level
-          'gnus-topic-unread unread
-          'gnus-active active-topic
-          'gnus-topic-visible visiblep))))
+    (if shownp
+       (gnus-add-text-properties
+        (point)
+        (prog1 (1+ (point))
+          (eval gnus-topic-line-format-spec))
+        (list 'gnus-topic (intern name)
+              'gnus-topic-level level
+              'gnus-topic-unread unread
+              'gnus-active active-topic
+              'gnus-topic-visible visiblep)))))
+
+(defun gnus-topic-update-unreads (topic unreads)
+  (setq gnus-topic-unreads (delq (assoc topic gnus-topic-unreads)
+                                gnus-topic-unreads))
+  (push (cons topic unreads) gnus-topic-unreads))
 
 (defun gnus-topic-update-topics-containing-group (group)
   "Update all topics that have GROUP as a member."
@@ -547,7 +681,7 @@ articles in the topic and its subtopics."
   (when (and (eq major-mode 'gnus-group-mode)
             gnus-topic-mode)
     (let ((group (gnus-group-group-name))
-          (m (point-marker))
+         (m (point-marker))
          (buffer-read-only nil))
       (when (and group
                 (gnus-get-info group)
@@ -562,9 +696,11 @@ articles in the topic and its subtopics."
   (let* ((topic (gnus-group-topic group))
         (groups (cdr (assoc topic gnus-topic-alist)))
         (g (cdr (member group groups)))
-        (unfound t))
+        (unfound t)
+        entry)
     ;; Try to jump to a visible group.
-    (while (and g (not (gnus-group-goto-group (car g) t)))
+    (while (and g
+               (not (gnus-group-goto-group (car g) t)))
       (pop g))
     ;; It wasn't visible, so we try to see where to insert it.
     (when (not g)
@@ -576,8 +712,31 @@ articles in the topic and its subtopics."
       (when (and unfound
                 topic
                 (not (gnus-topic-goto-missing-topic topic)))
-       (gnus-topic-insert-topic-line
-        topic t t (car (gnus-topic-find-topology topic)) nil 0)))))
+       (gnus-topic-display-missing-topic topic)))))
+
+(defun gnus-topic-display-missing-topic (topic)
+  "Insert topic lines recursively for missing topics."
+  (let ((parent (gnus-topic-find-topology
+                (gnus-topic-parent-topic topic))))
+    (when (and parent
+              (not (gnus-topic-goto-missing-topic (caadr parent))))
+      (gnus-topic-display-missing-topic (caadr parent))))
+  (gnus-topic-goto-missing-topic topic)
+  (let* ((top (gnus-topic-find-topology topic))
+        (children (cddr top))
+        (type (cadr top))
+        (unread 0)
+        (entries (gnus-topic-find-groups
+                  (car type) (car gnus-group-list-mode)
+                  (cdr gnus-group-list-mode)))
+       entry)
+    (while children
+      (incf unread (gnus-topic-unread (caar (pop children)))))
+    (while (setq entry (pop entries))
+      (when (numberp (car entry))
+       (incf unread (car entry))))
+    (gnus-topic-insert-topic-line
+     topic t t (car (gnus-topic-find-topology topic)) nil unread)))
 
 (defun gnus-topic-goto-missing-topic (topic)
   (if (gnus-topic-goto-topic topic)
@@ -586,15 +745,18 @@ articles in the topic and its subtopics."
     (let* ((top (gnus-topic-find-topology
                 (gnus-topic-parent-topic topic)))
           (tp (reverse (cddr top))))
-      (while (not (equal (caaar tp) topic))
-       (setq tp (cdr tp)))
-      (pop tp)
-      (while (and tp
-                 (not (gnus-topic-goto-topic (caaar tp))))
-       (pop tp))
-      (if tp
-         (gnus-topic-forward-topic 1)
-       (gnus-topic-goto-missing-topic (caadr top))))
+      (if (not top)
+         (gnus-topic-insert-topic-line
+          topic t t (car (gnus-topic-find-topology topic)) nil 0)
+       (while (not (equal (caaar tp) topic))
+         (setq tp (cdr tp)))
+       (pop tp)
+       (while (and tp
+                   (not (gnus-topic-goto-topic (caaar tp))))
+         (pop tp))
+       (if tp
+           (gnus-topic-forward-topic 1)
+         (gnus-topic-goto-missing-topic (caadr top)))))
     nil))
 
 (defun gnus-topic-update-topic-line (topic-name &optional reads)
@@ -607,7 +769,7 @@ articles in the topic and its subtopics."
         (parent (gnus-topic-parent-topic topic-name))
         (all-entries entries)
         (unread 0)
-        old-unread entry)
+        old-unread entry new-unread)
     (when (gnus-topic-goto-topic (car type))
       ;; Tally all the groups that belong in this topic.
       (if reads
@@ -623,11 +785,14 @@ articles in the topic and its subtopics."
        (car type) (gnus-topic-visible-p)
        (not (eq (nth 2 type) 'hidden))
        (gnus-group-topic-level) all-entries unread)
-      (gnus-delete-line))
+      (gnus-delete-line)
+      (forward-line -1)
+      (setq new-unread (gnus-group-topic-unread)))
     (when parent
       (forward-line -1)
       (gnus-topic-update-topic-line
-       parent (- (or old-unread 0) (or (gnus-group-topic-unread) 0))))
+       parent
+       (- (or old-unread 0) (or new-unread 0))))
     unread))
 
 (defun gnus-topic-group-indentation ()
@@ -765,8 +930,8 @@ articles in the topic and its subtopics."
                       ? ))
                     (yanked (list group))
                     alist talist end)
-               ;; Then we enter the yanked groups into the topics they belong
-               ;; to.
+               ;; Then we enter the yanked groups into the topics
+               ;; they belong to.
                (when (setq alist (assoc (save-excursion
                                           (forward-line -1)
                                           (or
@@ -883,6 +1048,8 @@ articles in the topic and its subtopics."
     "=" gnus-topic-select-group
     "\r" gnus-topic-select-group
     " " gnus-topic-read-group
+    "\C-c\C-x" gnus-topic-expire-articles
+    "c" gnus-topic-catchup-articles
     "\C-k" gnus-topic-kill-group
     "\C-y" gnus-topic-yank-group
     "\M-g" gnus-topic-get-new-news-this-topic
@@ -890,10 +1057,14 @@ articles in the topic and its subtopics."
     "Gp" gnus-topic-edit-parameters
     "#" gnus-topic-mark-topic
     "\M-#" gnus-topic-unmark-topic
+    [tab] gnus-topic-indent
+    [(meta tab)] gnus-topic-unindent
+    "\C-i" gnus-topic-indent
+    "\M-\C-i" gnus-topic-unindent
     gnus-mouse-2 gnus-mouse-pick-topic)
 
   ;; Define a new submap.
-  (gnus-define-keys (gnus-group-topic-map "T" gnus-group-mode-map)
+  (gnus-define-keys (gnus-group-topic-map "T" gnus-topic-mode-map)
     "#" gnus-topic-mark-topic
     "\M-#" gnus-topic-unmark-topic
     "n" gnus-topic-create-topic
@@ -902,20 +1073,24 @@ articles in the topic and its subtopics."
     "c" gnus-topic-copy-group
     "h" gnus-topic-hide-topic
     "s" gnus-topic-show-topic
+    "j" gnus-topic-jump-to-topic
     "M" gnus-topic-move-matching
     "C" gnus-topic-copy-matching
+    "\M-p" gnus-topic-goto-previous-topic
+    "\M-n" gnus-topic-goto-next-topic
     "\C-i" gnus-topic-indent
     [tab] gnus-topic-indent
     "r" gnus-topic-rename
     "\177" gnus-topic-delete
     [delete] gnus-topic-delete
-    "h" gnus-topic-toggle-display-empty-topics)
+    "H" gnus-topic-toggle-display-empty-topics)
 
   (gnus-define-keys (gnus-topic-sort-map "S" gnus-group-topic-map)
     "s" gnus-topic-sort-groups
     "a" gnus-topic-sort-groups-by-alphabet
     "u" gnus-topic-sort-groups-by-unread
     "l" gnus-topic-sort-groups-by-level
+    "e" gnus-topic-sort-groups-by-server
     "v" gnus-topic-sort-groups-by-score
     "r" gnus-topic-sort-groups-by-rank
     "m" gnus-topic-sort-groups-by-method))
@@ -927,19 +1102,23 @@ articles in the topic and its subtopics."
      '("Topics"
        ["Toggle topics" gnus-topic-mode t]
        ("Groups"
-       ["Copy" gnus-topic-copy-group t]
-       ["Move" gnus-topic-move-group t]
+       ["Copy..." gnus-topic-copy-group t]
+       ["Move..." gnus-topic-move-group t]
        ["Remove" gnus-topic-remove-group t]
-       ["Copy matching" gnus-topic-copy-matching t]
-       ["Move matching" gnus-topic-move-matching t])
+       ["Copy matching..." gnus-topic-copy-matching t]
+       ["Move matching..." gnus-topic-move-matching t])
        ("Topics"
+       ["Goto..." gnus-topic-jump-to-topic t]
        ["Show" gnus-topic-show-topic t]
        ["Hide" gnus-topic-hide-topic t]
        ["Delete" gnus-topic-delete t]
-       ["Rename" gnus-topic-rename t]
-       ["Create" gnus-topic-create-topic t]
+       ["Rename..." gnus-topic-rename t]
+       ["Create..." gnus-topic-create-topic t]
        ["Mark" gnus-topic-mark-topic t]
        ["Indent" gnus-topic-indent t]
+       ["Sort" gnus-topic-sort-topics t]
+       ["Previous topic" gnus-topic-goto-previous-topic t]
+       ["Next topic" gnus-topic-goto-next-topic t]
        ["Toggle hide empty" gnus-topic-toggle-display-empty-topics t]
        ["Edit parameters" gnus-topic-edit-parameters t])
        ["List active" gnus-topic-list-active t]))))
@@ -953,13 +1132,15 @@ articles in the topic and its subtopics."
          (if (null arg) (not gnus-topic-mode)
            (> (prefix-numeric-value arg) 0)))
     ;; Infest Gnus with topics.
-     (if (not gnus-topic-mode)
-       (setq gnus-goto-missing-group-function nil)
+    (if (not gnus-topic-mode)
+       (setq gnus-goto-missing-group-function nil)
       (when (gnus-visual-p 'topic-menu 'menu)
        (gnus-topic-make-menu-bar))
       (gnus-set-format 'topic t)
-      (gnus-add-minor-mode 'gnus-topic-mode " Topic" gnus-topic-mode-map)
-      (add-hook 'gnus-summary-exit-hook 'gnus-topic-update-topic)
+      (gnus-add-minor-mode 'gnus-topic-mode " Topic"
+                          gnus-topic-mode-map nil (lambda (&rest junk)
+                                                    (interactive)
+                                                    (gnus-topic-mode nil t)))
       (add-hook 'gnus-group-catchup-group-hook 'gnus-topic-update-topic)
       (set (make-local-variable 'gnus-group-prepare-function)
           'gnus-group-prepare-topics)
@@ -975,8 +1156,9 @@ articles in the topic and its subtopics."
           'gnus-group-sort-topic)
       (setq gnus-group-change-level-function 'gnus-topic-change-level)
       (setq gnus-goto-missing-group-function 'gnus-topic-goto-missing-group)
-      (make-local-hook 'gnus-check-bogus-groups-hook)
-      (add-hook 'gnus-check-bogus-groups-hook 'gnus-topic-clean-alist)
+      (gnus-make-local-hook 'gnus-check-bogus-groups-hook)
+      (add-hook 'gnus-check-bogus-groups-hook 'gnus-topic-clean-alist
+               nil 'local)
       (setq gnus-topology-checked-p nil)
       ;; We check the topology.
       (when gnus-newsrc-alist
@@ -985,8 +1167,7 @@ articles in the topic and its subtopics."
     ;; Remove topic infestation.
     (unless gnus-topic-mode
       (remove-hook 'gnus-summary-exit-hook 'gnus-topic-update-topic)
-      (remove-hook 'gnus-group-change-level-function
-                  'gnus-topic-change-level)
+      (setq gnus-group-change-level-function nil)
       (remove-hook 'gnus-check-bogus-groups-hook 'gnus-topic-clean-alist)
       (setq gnus-group-prepare-function 'gnus-group-prepare-flat)
       (setq gnus-group-sort-alist-function 'gnus-group-sort-flat))
@@ -996,15 +1177,19 @@ articles in the topic and its subtopics."
 (defun gnus-topic-select-group (&optional all)
   "Select this newsgroup.
 No article is selected automatically.
+If the group is opened, just switch the summary buffer.
 If ALL is non-nil, already read articles become readable.
 If ALL is a number, fetch this number of articles.
 
 If performed over a topic line, toggle folding the topic."
   (interactive "P")
+  (when (and (eobp) (not (gnus-group-group-name)))
+    (forward-line -1))
   (if (gnus-group-topic-p)
       (let ((gnus-group-list-mode
             (if all (cons (if (numberp all) all 7) t) gnus-group-list-mode)))
-       (gnus-topic-fold all))
+       (gnus-topic-fold all)
+       (gnus-dribble-touch))
     (gnus-group-select-group all)))
 
 (defun gnus-mouse-pick-topic (e)
@@ -1013,6 +1198,36 @@ If performed over a topic line, toggle folding the topic."
   (mouse-set-point e)
   (gnus-topic-read-group nil))
 
+(defun gnus-topic-expire-articles (topic)
+  "Expire articles in this topic or group."
+  (interactive (list (gnus-group-topic-name)))
+  (if (not topic)
+      (call-interactively 'gnus-group-expire-articles)
+    (save-excursion
+      (gnus-message 5 "Expiring groups in %s..." topic)
+      (let ((gnus-group-marked
+            (mapcar (lambda (entry) (car (nth 2 entry)))
+                    (gnus-topic-find-groups topic gnus-level-killed t
+                                            nil t))))
+       (gnus-group-expire-articles nil))
+      (gnus-message 5 "Expiring groups in %s...done" topic))))
+
+(defun gnus-topic-catchup-articles (topic)
+  "Catchup this topic or group.
+Also see `gnus-group-catchup'."
+  (interactive (list (gnus-group-topic-name)))
+  (if (not topic)
+      (call-interactively 'gnus-group-catchup-current)
+    (save-excursion
+      (let* ((groups
+            (mapcar (lambda (entry) (car (nth 2 entry)))
+                    (gnus-topic-find-groups topic gnus-level-killed t
+                                            nil t)))
+            (buffer-read-only nil)
+            (gnus-group-marked groups))
+       (gnus-group-catchup-current)
+       (mapcar 'gnus-topic-update-topics-containing-group groups)))))
+
 (defun gnus-topic-read-group (&optional all no-article group)
   "Read news in this newsgroup.
 If the prefix argument ALL is non-nil, already read articles become
@@ -1042,7 +1257,7 @@ When used interactively, PARENT will be the topic under point."
   (unless parent
     (setq parent (caar gnus-topic-topology)))
   (let ((top (cdr (gnus-topic-find-topology parent)))
-       (full-topic (or full-topic `((,topic visible)))))
+       (full-topic (or full-topic (list (list topic 'visible nil nil)))))
     (unless top
       (error "No such parent topic: %s" parent))
     (if previous
@@ -1058,44 +1273,61 @@ When used interactively, PARENT will be the topic under point."
   (gnus-group-list-groups)
   (gnus-topic-goto-topic topic))
 
+;; FIXME:
+;;  1. When the marked groups are overlapped with the process
+;;     region, the behavior of move or remove is not right.
+;;  2. Can't process on several marked groups with a same name,
+;;     because gnus-group-marked only keeps one copy.
+
 (defun gnus-topic-move-group (n topic &optional copyp)
   "Move the next N groups to TOPIC.
 If COPYP, copy the groups instead."
   (interactive
    (list current-prefix-arg
-        (completing-read "Move to topic: " gnus-topic-alist nil t)))
-  (let ((groups (gnus-group-process-prefix n))
+        (gnus-completing-read "Move to topic" gnus-topic-alist nil t
+                              'gnus-topic-history)))
+  (let ((use-marked (and (not n) (not (gnus-region-active-p))
+                        gnus-group-marked t))
+       (groups (gnus-group-process-prefix n))
        (topicl (assoc topic gnus-topic-alist))
-       (start-group (progn (forward-line 1) (gnus-group-group-name)))
        (start-topic (gnus-group-topic-name))
+       (start-group (progn (forward-line 1) (gnus-group-group-name)))
        entry)
-    (mapcar
-     (lambda (g)
-       (gnus-group-remove-mark g)
-       (when (and
-             (setq entry (assoc (gnus-current-topic) gnus-topic-alist))
-             (not copyp))
-        (setcdr entry (gnus-delete-first g (cdr entry))))
-       (nconc topicl (list g)))
-     groups)
-    (gnus-topic-enter-dribble)
-    (if start-group
-       (gnus-group-goto-group start-group)
-      (gnus-topic-goto-topic start-topic))
-    (gnus-group-list-groups)))
+    (if (and (not groups) (not copyp) start-topic)
+       (gnus-topic-move start-topic topic)
+      (mapcar
+       (lambda (g)
+        (gnus-group-remove-mark g use-marked)
+        (when (and
+               (setq entry (assoc (gnus-current-topic) gnus-topic-alist))
+               (not copyp))
+          (setcdr entry (gnus-delete-first g (cdr entry))))
+        (nconc topicl (list g)))
+       groups)
+      (gnus-topic-enter-dribble)
+      (if start-group
+         (gnus-group-goto-group start-group)
+       (gnus-topic-goto-topic start-topic))
+      (gnus-group-list-groups))))
 
-(defun gnus-topic-remove-group (&optional arg)
+(defun gnus-topic-remove-group (&optional n)
   "Remove the current group from the topic."
   (interactive "P")
-  (gnus-group-iterate arg
-    (lambda (group)
-      (let ((topicl (assoc (gnus-current-topic) gnus-topic-alist))
-           (buffer-read-only nil))
-       (when (and topicl group)
-         (gnus-delete-line)
-         (gnus-delete-first group topicl))
-       (gnus-topic-update-topic)
-       (gnus-group-position-point)))))
+  (let ((use-marked (and (not n) (not (gnus-region-active-p))
+                        gnus-group-marked t))
+       (groups (gnus-group-process-prefix n)))
+    (mapcar
+     (lambda (group)
+       (gnus-group-remove-mark group use-marked)
+       (let ((topicl (assoc (gnus-current-topic) gnus-topic-alist))
+            (buffer-read-only nil))
+        (when (and topicl group)
+          (gnus-delete-line)
+          (gnus-delete-first group topicl))
+        (gnus-topic-update-topic)))
+     groups)
+    (gnus-topic-enter-dribble)
+    (gnus-group-position-point)))
 
 (defun gnus-topic-copy-group (n topic)
   "Copy the current group to a topic."
@@ -1117,7 +1349,12 @@ If COPYP, copy the groups instead."
        (gnus-topic-find-topology topic nil nil gnus-topic-topology)
        (gnus-topic-enter-dribble))
     (gnus-group-kill-group n discard)
-    (gnus-topic-update-topic)))
+    (if (not (gnus-group-topic-p))
+       (gnus-topic-update-topic)
+      ;; Move up one line so that we update the right topic.
+      (forward-line -1)
+      (gnus-topic-update-topic)
+      (forward-line 1))))
 
 (defun gnus-topic-yank-group (&optional arg)
   "Yank the last topic."
@@ -1167,44 +1404,69 @@ If COPYP, copy the groups instead."
            (setq alist (cdr alist))))))
     (gnus-topic-update-topic)))
 
-(defun gnus-topic-hide-topic ()
-  "Hide the current topic."
-  (interactive)
+(defun gnus-topic-hide-topic (&optional permanent)
+  "Hide the current topic.
+If PERMANENT, make it stay hidden in subsequent sessions as well."
+  (interactive "P")
   (when (gnus-current-topic)
     (gnus-topic-goto-topic (gnus-current-topic))
-    (gnus-topic-remove-topic nil nil 'hidden)))
-
-(defun gnus-topic-show-topic ()
-  "Show the hidden topic."
-  (interactive)
+    (if permanent
+       (setcar (cddr
+                (cadr
+                 (gnus-topic-find-topology (gnus-current-topic))))
+               'hidden))
+    (gnus-topic-remove-topic nil nil)))
+
+(defun gnus-topic-show-topic (&optional permanent)
+  "Show the hidden topic.
+If PERMANENT, make it stay shown in subsequent sessions as well."
+  (interactive "P")
   (when (gnus-group-topic-p)
-    (gnus-topic-remove-topic t nil 'shown)))
-
-(defun gnus-topic-mark-topic (topic &optional unmark)
-  "Mark all groups in the topic with the process mark."
-  (interactive (list (gnus-group-topic-name)))
+    (if (not permanent)
+       (gnus-topic-remove-topic t nil)
+      (let ((topic
+            (gnus-topic-find-topology
+             (completing-read "Show topic: " gnus-topic-alist nil t))))
+       (setcar (cddr (cadr topic)) nil)
+       (setcar (cdr (cadr topic)) 'visible)
+       (gnus-group-list-groups)))))
+
+(defun gnus-topic-mark-topic (topic &optional unmark non-recursive)
+  "Mark all groups in the TOPIC with the process mark.
+If NON-RECURSIVE (which is the prefix) is t, don't mark its subtopics."
+  (interactive (list (gnus-group-topic-name)
+                    nil
+                    (and current-prefix-arg t)))
   (if (not topic)
       (call-interactively 'gnus-group-mark-group)
     (save-excursion
-      (let ((groups (gnus-topic-find-groups topic gnus-level-killed t)))
+      (let ((groups (gnus-topic-find-groups topic gnus-level-killed t nil
+                                           (not non-recursive))))
        (while groups
          (funcall (if unmark 'gnus-group-remove-mark 'gnus-group-set-mark)
                   (gnus-info-group (nth 2 (pop groups)))))))))
 
-(defun gnus-topic-unmark-topic (topic &optional unmark)
-  "Remove the process mark from all groups in the topic."
-  (interactive (list (gnus-group-topic-name)))
+(defun gnus-topic-unmark-topic (topic &optional dummy non-recursive)
+  "Remove the process mark from all groups in the TOPIC.
+If NON-RECURSIVE (which is the prefix) is t, don't unmark its subtopics."
+  (interactive (list (gnus-group-topic-name)
+                    nil
+                    (and current-prefix-arg t)))
   (if (not topic)
       (call-interactively 'gnus-group-unmark-group)
-    (gnus-topic-mark-topic topic t)))
+    (gnus-topic-mark-topic topic t non-recursive)))
 
 (defun gnus-topic-get-new-news-this-topic (&optional n)
   "Check for new news in the current topic."
   (interactive "P")
   (if (not (gnus-group-topic-p))
       (gnus-group-get-new-news-this-group n)
-    (gnus-topic-mark-topic (gnus-group-topic-name))
-    (gnus-group-get-new-news-this-group)))
+    (let* ((topic (gnus-group-topic-name))
+          (data (cadr (gnus-topic-find-topology topic))))
+      (save-excursion
+       (gnus-topic-mark-topic topic nil (and n t))
+       (gnus-group-get-new-news-this-group))
+      (gnus-topic-remove-topic (eq 'visible (cadr data))))))
 
 (defun gnus-topic-move-matching (regexp topic &optional copyp)
   "Move all groups that match REGEXP to some topic."
@@ -1250,10 +1512,14 @@ If COPYP, copy the groups instead."
   (interactive
    (let ((topic (gnus-current-topic)))
      (list topic
-          (read-string (format "Rename %s to: " topic)))))
+          (read-string (format "Rename %s to: " topic) topic))))
   ;; Check whether the new name exists.
   (when (gnus-topic-find-topology new-name)
-    (error "Topic '%s' already exists"))
+    (error "Topic '%s' already exists" new-name))
+  ;; "nil" is an invalid name, for reasons I'd rather not go
+  ;; into here.  Trust me.
+  (when (equal new-name "nil")
+    (error "Invalid name: %s" nil))
   ;; Do the renaming.
   (let ((top (gnus-topic-find-topology old-name))
        (entry (assoc old-name gnus-topic-alist)))
@@ -1263,7 +1529,8 @@ If COPYP, copy the groups instead."
       (setcar entry new-name))
     (forward-line -1)
     (gnus-dribble-touch)
-    (gnus-group-list-groups)))
+    (gnus-group-list-groups)
+    (forward-line 1)))
 
 (defun gnus-topic-indent (&optional unindent)
   "Indent a topic -- make it a sub-topic of the previous topic.
@@ -1281,7 +1548,7 @@ If UNINDENT, remove an indentation."
        (gnus-topic-kill-group)
        (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
        (gnus-topic-create-topic
-        topic parent nil (cdaar gnus-topic-killed-topics))
+        topic parent nil (cdar (car gnus-topic-killed-topics)))
        (pop gnus-topic-killed-topics)
        (or (gnus-topic-goto-topic topic)
            (gnus-topic-goto-topic parent))))))
@@ -1300,7 +1567,7 @@ If UNINDENT, remove an indentation."
       (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
       (gnus-topic-create-topic
        topic grandparent (gnus-topic-next-topic parent)
-       (cdaar gnus-topic-killed-topics))
+       (cdar (car gnus-topic-killed-topics)))
       (pop gnus-topic-killed-topics)
       (gnus-topic-goto-topic topic))))
 
@@ -1417,6 +1684,82 @@ If REVERSE, sort in reverse order."
   (interactive "P")
   (gnus-topic-sort-groups 'gnus-group-sort-by-method reverse))
 
+(defun gnus-topic-sort-groups-by-server (&optional reverse)
+  "Sort the current topic alphabetically by server name.
+If REVERSE, sort in reverse order."
+  (interactive "P")
+  (gnus-topic-sort-groups 'gnus-group-sort-by-server reverse))
+
+(defun gnus-topic-sort-topics-1 (top reverse)
+  (if (cdr top)
+      (let ((subtop
+            (mapcar (gnus-byte-compile
+                     `(lambda (top)
+                        (gnus-topic-sort-topics-1 top ,reverse)))
+                    (sort (cdr top)
+                          (lambda (t1 t2)
+                            (string-lessp (caar t1) (caar t2)))))))
+       (setcdr top (if reverse (reverse subtop) subtop))))
+  top)
+
+(defun gnus-topic-sort-topics (&optional topic reverse)
+  "Sort topics in TOPIC alphabetically by topic name.
+If REVERSE, reverse the sorting order."
+  (interactive
+   (list (completing-read "Sort topics in : " gnus-topic-alist nil t
+                         (gnus-current-topic))
+        current-prefix-arg))
+  (let ((topic-topology (or (and topic (cdr (gnus-topic-find-topology topic)))
+                           gnus-topic-topology)))
+    (gnus-topic-sort-topics-1 topic-topology reverse)
+    (gnus-topic-enter-dribble)
+    (gnus-group-list-groups)
+    (gnus-topic-goto-topic topic)))
+
+(defun gnus-topic-move (current to)
+  "Move the CURRENT topic to TO."
+  (interactive
+   (list
+    (gnus-group-topic-name)
+    (completing-read "Move to topic: " gnus-topic-alist nil t)))
+  (unless (and current to)
+    (error "Can't find topic"))
+  (let ((current-top (cdr (gnus-topic-find-topology current)))
+       (to-top (cdr (gnus-topic-find-topology to))))
+    (unless current-top
+      (error "Can't find topic `%s'" current))
+    (unless to-top
+      (error "Can't find topic `%s'" to))
+    (if (gnus-topic-find-topology to current-top 0);; Don't care the level
+       (error "Can't move `%s' to its sub-level" current))
+    (gnus-topic-find-topology current nil nil 'delete)
+    (while (cdr to-top)
+      (setq to-top (cdr to-top)))
+    (setcdr to-top (list current-top))
+    (gnus-topic-enter-dribble)
+    (gnus-group-list-groups)
+    (gnus-topic-goto-topic current)))
+
+(defun gnus-subscribe-topics (newsgroup)
+  (catch 'end
+    (let (match gnus-group-change-level-function)
+      (dolist (topic (gnus-topic-list))
+       (when (and (setq match (cdr (assq 'subscribe
+                                         (gnus-topic-parameters topic))))
+                  (string-match match newsgroup))
+         ;; Just subscribe the group.
+         (gnus-subscribe-alphabetically newsgroup)
+         ;; Add the group to the topic.
+         (nconc (assoc topic gnus-topic-alist) (list newsgroup))
+         ;; if this topic specifies a default level, use it
+         (let ((subscribe-level (cdr (assq 'subscribe-level
+                                           (gnus-topic-parameters topic)))))
+           (when subscribe-level
+               (gnus-group-change-level newsgroup subscribe-level
+                                        gnus-level-default-subscribed)))
+         (throw 'end t)))
+      nil)))
+
 (provide 'gnus-topic)
 
 ;;; gnus-topic.el ends here
index 5321f3a..f022926 100644 (file)
@@ -1,7 +1,9 @@
 ;;; gnus-undo.el --- minor mode for undoing in Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -25,7 +27,7 @@
 
 ;; This package allows arbitrary undoing in Gnus buffers.  As all the
 ;; Gnus buffers aren't very text-oriented (what is in the buffers is
-;; just some random representation of the actual data), normal Emacs
+;; just some arbitrary representation of the actual data), normal Emacs
 ;; undoing doesn't work at all for Gnus.
 ;;
 ;; This package works by letting Gnus register functions for reversing
 
 (require 'gnus-util)
 (require 'gnus)
+(require 'custom)
+
+(defgroup gnus-undo nil
+  "Undoing in Gnus buffers."
+  :group 'gnus)
+
+(defcustom gnus-undo-limit 2000
+  "The number of undoable actions recorded."
+  :type 'integer
+  :group 'gnus-undo)
 
-(defvar gnus-undo-mode nil
-  "Minor mode for undoing in Gnus buffers.")
+(defcustom gnus-undo-mode nil
+  "Minor mode for undoing in Gnus buffers."
+  :type 'boolean
+  :group 'gnus-undo)
 
-(defvar gnus-undo-mode-hook nil
-  "Hook called in all `gnus-undo-mode' buffers.")
+(defcustom gnus-undo-mode-hook nil
+  "Hook called in all `gnus-undo-mode' buffers."
+  :type 'hook
+  :group 'gnus-undo)
 
 ;;; Internal variables.
 
   (setq gnus-undo-mode-map (make-sparse-keymap))
 
   (gnus-define-keys gnus-undo-mode-map
-   "\M-\C-_"     gnus-undo
-   "\C-_"        gnus-undo
-   "\C-xu"       gnus-undo
-   ;; many people are used to type `C-/' on X terminals and get `C-_'.
-   [(control /)] gnus-undo))
+    "\M-\C-_"     gnus-undo
+    "\C-_"        gnus-undo
+    "\C-xu"       gnus-undo
+    ;; many people are used to type `C-/' on X terminals and get `C-_'.
+    [(control /)] gnus-undo))
 
 (defun gnus-undo-make-menu-bar ()
   ;; This is disabled for the time being.
     (when (gnus-visual-p 'undo-menu 'menu)
       (gnus-undo-make-menu-bar))
     (gnus-add-minor-mode 'gnus-undo-mode "" gnus-undo-mode-map)
-    (make-local-hook 'post-command-hook)
+    (gnus-make-local-hook 'post-command-hook)
     (add-hook 'post-command-hook 'gnus-undo-boundary nil t)
     (gnus-run-hooks 'gnus-undo-mode-hook)))
 
@@ -148,6 +164,11 @@ FORMS may use backtick quote syntax."
      ;; Initialize list.
      (t
       (setq gnus-undo-actions (list (list function)))))
+    ;; Limit the length of the undo list.
+    (let ((next (nthcdr gnus-undo-limit gnus-undo-actions)))
+      (when next
+       (setcdr next nil)))
+    ;; We are not at a boundary...
     (setq gnus-undo-boundary-inhibit t)))
 
 (defun gnus-undo (n)
index 856b7a2..09cf62b 100644 (file)
@@ -1,8 +1,10 @@
-;;; gnus-util.el --- utility functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;;; gnus-util.el --- utility functions for Semi-gnus
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 ;; used by Gnus and may be used by any other package without loading
 ;; Gnus first.
 
+;; [Unfortunately, it does depend on other parts of Gnus, e.g. the
+;; autoloads below...]
+
 ;;; Code:
 
+(eval-when-compile
+  (require 'cl)
+  ;; Fixme: this should be a gnus variable, not nnmail-.
+  (defvar nnmail-pathname-coding-system))
+(eval-when-compile (require 'static))
+
 (require 'custom)
-(eval-when-compile (require 'cl))
-(require 'nnheader)
-(require 'timezone)
-(require 'message)
+(require 'time-date)
+(require 'netrc)
 
 (eval-and-compile
-  (autoload 'nnmail-date-to-time "nnmail")
+  (autoload 'message-fetch-field "message")
+  (autoload 'gnus-get-buffer-window "gnus-win")
   (autoload 'rmail-insert-rmail-file-header "rmail")
   (autoload 'rmail-count-new-messages "rmail")
-  (autoload 'rmail-show-message "rmail"))
+  (autoload 'rmail-show-message "rmail")
+  (autoload 'nnheader-narrow-to-headers "nnheader")
+  (autoload 'nnheader-replace-chars-in-string "nnheader"))
+
+(eval-and-compile
+  (cond
+   ((fboundp 'replace-in-string)
+    (defalias 'gnus-replace-in-string 'replace-in-string))
+   ((fboundp 'replace-regexp-in-string)
+    (defun gnus-replace-in-string  (string regexp newtext &optional literal)
+      (replace-regexp-in-string regexp newtext string nil literal)))
+   (t
+    (defun gnus-replace-in-string (string regexp newtext &optional literal)
+      (let ((start 0) tail)
+       (while (string-match regexp string start)
+         (setq tail (- (length string) (match-end 0)))
+         (setq string (replace-match newtext nil literal string))
+         (setq start (- (length string) tail))))
+      string))))
+
+;;; bring in the netrc functions as aliases
+(defalias 'gnus-netrc-get 'netrc-get)
+(defalias 'gnus-netrc-machine 'netrc-machine)
+(defalias 'gnus-parse-netrc 'netrc-parse)
 
 (defun gnus-boundp (variable)
   "Return non-nil if VARIABLE is bound and non-nil."
 (defmacro gnus-eval-in-buffer-window (buffer &rest forms)
   "Pop to BUFFER, evaluate FORMS, and then return to the original window."
   (let ((tempvar (make-symbol "GnusStartBufferWindow"))
-        (w (make-symbol "w"))
-        (buf (make-symbol "buf")))
+       (w (make-symbol "w"))
+       (buf (make-symbol "buf"))
+       (frame (make-symbol "frame")))
     `(let* ((,tempvar (selected-window))
-            (,buf ,buffer)
-            (,w (get-buffer-window ,buf 'visible)))
+           (,buf ,buffer)
+           (,w (gnus-get-buffer-window ,buf 'visible))
+           ,frame)
        (unwind-protect
-           (progn
-             (if ,w
-                 (progn
-                   (select-window ,w)
-                   (set-buffer (window-buffer ,w)))
-               (pop-to-buffer ,buf))
-             ,@forms)
-         (select-window ,tempvar)))))
+          (progn
+            (if ,w
+                (progn
+                  (select-window ,w)
+                  (set-buffer (window-buffer ,w)))
+              (pop-to-buffer ,buf))
+            ,@forms)
+        (setq ,frame (selected-frame))
+        (select-window ,tempvar)
+        (select-frame ,frame)))))
 
 (put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
 (put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
         (set symbol nil))
      symbol))
 
-(defun gnus-truncate-string (str width)
-  (substring str 0 width))
-
 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>.  A safe way
 ;; to limit the length of a string.  This function is necessary since
 ;; `(substr "abc" 0 30)' pukes with "Args out of range".
+;; Fixme: Why not `truncate-string-to-width'?
 (defsubst gnus-limit-string (str width)
   (if (> (length str) width)
       (substring str 0 width)
     str))
 
-(defsubst gnus-functionp (form)
-  "Return non-nil if FORM is funcallable."
-  (or (and (symbolp form) (fboundp form))
-      (and (listp form) (eq (car form) 'lambda))
-      (byte-code-function-p form)))
-
 (defsubst gnus-goto-char (point)
   (and point (goto-char point)))
 
        (funcall (if (stringp buffer) 'get-buffer 'buffer-name)
                buffer))))
 
-(defmacro gnus-kill-buffer (buffer)
-  `(let ((buf ,buffer))
-     (when (gnus-buffer-exists-p buf)
-       (kill-buffer buf))))
-
-(if (fboundp 'point-at-bol)
-    (fset 'gnus-point-at-bol 'point-at-bol)
+(static-cond
+ ((fboundp 'point-at-bol)
+  (defalias 'gnus-point-at-bol 'point-at-bol))
+ ((fboundp 'line-beginning-position)
+  (defalias 'gnus-point-at-bol 'line-beginning-position))
+ (t
   (defun gnus-point-at-bol ()
     "Return point at the beginning of the line."
     (let ((p (point)))
       (beginning-of-line)
       (prog1
          (point)
-       (goto-char p)))))
-
-(if (fboundp 'point-at-eol)
-    (fset 'gnus-point-at-eol 'point-at-eol)
+       (goto-char p))))
+  ))
+(static-cond
+ ((fboundp 'point-at-eol)
+  (defalias 'gnus-point-at-eol 'point-at-eol))
+ ((fboundp 'line-end-position)
+  (defalias 'gnus-point-at-eol 'line-end-position))
+ (t
   (defun gnus-point-at-eol ()
     "Return point at the end of the line."
     (let ((p (point)))
       (end-of-line)
       (prog1
          (point)
-       (goto-char p)))))
+       (goto-char p))))
+  ))
+
+;; The LOCAL arg to `add-hook' is interpreted differently in Emacs and
+;; XEmacs.  In Emacs we don't need to call `make-local-hook' first.
+;; It's harmless, though, so the main purpose of this alias is to shut
+;; up the byte compiler.
+(defalias 'gnus-make-local-hook
+  (if (eq (get 'make-local-hook 'byte-compile)
+         'byte-compile-obsolete)
+      'ignore                          ; Emacs
+    'make-local-hook))                 ; XEmacs
 
 (defun gnus-delete-first (elt list)
   "Delete by side effect the first occurrence of ELT as a member of LIST."
 
 ;; Delete the current line (and the next N lines).
 (defmacro gnus-delete-line (&optional n)
-  `(delete-region (progn (beginning-of-line) (point))
+  `(delete-region (gnus-point-at-bol)
                  (progn (forward-line ,(or n 1)) (point))))
 
 (defun gnus-byte-code (func)
       (cons 'progn (cddr fval)))))
 
 (defun gnus-extract-address-components (from)
+  "Extract address components from a From header.
+Given an RFC-822 address FROM, extract full name and canonical address.
+Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).  Much more simple
+solution than `mail-extract-address-components', which works much better, but
+is slower."
   (let (name address)
     ;; First find the address - the thing with the @ in it.  This may
     ;; not be accurate in mail addresses, but does the trick most of
         (string-match (concat "[ \t]*<" (regexp-quote address) ">") from)
         (and (setq name (substring from 0 (match-beginning 0)))
              ;; Strip any quotes from the name.
-             (string-match "\".*\"" name)
+             (string-match "^\".*\"$" name)
              (setq name (substring name 1 (1- (match-end 0))))))
     ;; If not, then "address (name)" is used.
     (or name
        (and (string-match "(.*" from)
             (setq name (substring from (1+ (match-beginning 0))
                                   (match-end 0)))))
-    ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
-    (list (or name from) (or address from))))
+    (list (if (string= name "") nil name) (or address from))))
+
 
 (defun gnus-fetch-field (field)
   "Return the value of the header FIELD of current article."
        (nnheader-narrow-to-headers)
        (message-fetch-field field)))))
 
+(defun gnus-fetch-original-field (field)
+  "Fetch FIELD from the original version of the current article."
+  (with-current-buffer gnus-original-article-buffer
+    (gnus-fetch-field field)))
+
+
 (defun gnus-goto-colon ()
   (beginning-of-line)
-  (search-forward ":" (gnus-point-at-eol) t))
+  (let ((eol (gnus-point-at-eol)))
+    (goto-char (or (text-property-any (point) eol 'gnus-position t)
+                  (search-forward ":" eol t)
+                  (point)))))
+
+(defun gnus-decode-newsgroups (newsgroups group &optional method)
+  (let ((method (or method (gnus-find-method-for-group group))))
+    (mapconcat (lambda (group)
+                (gnus-group-name-decode group (gnus-group-name-charset
+                                               method group)))
+              (message-tokenize-header newsgroups)
+              ",")))
 
 (defun gnus-remove-text-with-property (prop)
   "Delete all text in the current buffer with text property PROP."
 
 (defun gnus-newsgroup-directory-form (newsgroup)
   "Make hierarchical directory name from NEWSGROUP name."
-  (let ((newsgroup (gnus-newsgroup-savable-name newsgroup))
-       (len (length newsgroup))
-       idx)
-    ;; If this is a foreign group, we don't want to translate the
-    ;; entire name.
-    (if (setq idx (string-match ":" newsgroup))
-       (aset newsgroup idx ?/)
-      (setq idx 0))
-    ;; Replace all occurrences of `.' with `/'.
-    (while (< idx len)
-      (when (= (aref newsgroup idx) ?.)
-       (aset newsgroup idx ?/))
-      (setq idx (1+ idx)))
-    newsgroup))
+  (let* ((newsgroup (gnus-newsgroup-savable-name newsgroup))
+        (idx (string-match ":" newsgroup)))
+    (concat
+     (if idx (substring newsgroup 0 idx))
+     (if idx "/")
+     (nnheader-replace-chars-in-string
+      (if idx (substring newsgroup (1+ idx)) newsgroup)
+      ?. ?/))))
 
 (defun gnus-newsgroup-savable-name (group)
   ;; Replace any slashes in a group name (eg. an ange-ftp nndoc group)
 
 ;;; Time functions.
 
-(defun gnus-days-between (date1 date2)
-  ;; Return the number of days between date1 and date2.
-  (- (gnus-day-number date1) (gnus-day-number date2)))
-
-(defun gnus-day-number (date)
-  (let ((dat (mapcar (lambda (s) (and s (string-to-int s)) )
-                    (timezone-parse-date date))))
-    (timezone-absolute-from-gregorian
-     (nth 1 dat) (nth 2 dat) (car dat))))
-
-(defun gnus-time-to-day (time)
-  "Convert TIME to day number."
-  (let ((tim (decode-time time)))
-    (timezone-absolute-from-gregorian
-     (nth 4 tim) (nth 3 tim) (nth 5 tim))))
-
-(defun gnus-encode-date (date)
-  "Convert DATE to internal time."
-  (let* ((parse (timezone-parse-date date))
-        (date (mapcar (lambda (d) (and d (string-to-int d))) parse))
-        (time (mapcar 'string-to-int (timezone-parse-time (aref parse 3)))))
-    (encode-time (caddr time) (cadr time) (car time)
-                (caddr date) (cadr date) (car date)
-                (* 60 (timezone-zone-to-minute (nth 4 date))))))
-
-(defun gnus-time-minus (t1 t2)
-  "Subtract two internal times."
-  (let ((borrow (< (cadr t1) (cadr t2))))
-    (list (- (car t1) (car t2) (if borrow 1 0))
-         (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
-
-(defun gnus-time-less (t1 t2)
-  "Say whether time T1 is less than time T2."
-  (or (< (car t1) (car t2))
-      (and (= (car t1) (car t2))
-          (< (nth 1 t1) (nth 1 t2)))))
-
 (defun gnus-file-newer-than (file date)
   (let ((fdate (nth 5 (file-attributes file))))
     (or (> (car fdate) (car date))
          (define-key keymap key (pop plist))
        (pop plist)))))
 
-(defun gnus-completing-read (default prompt &rest args)
+(defun gnus-completing-read-with-default (default prompt &rest args)
   ;; Like `completing-read', except that DEFAULT is the default argument.
   (let* ((prompt (if default
                     (concat prompt " (default " default ") ")
       (yes-or-no-p prompt)
     (message "")))
 
-;; I suspect there's a better way, but I haven't taken the time to do
-;; it yet.  -erik selberg@cs.washington.edu
+;; By Frank Schmitt <ich@Frank-Schmitt.net>. Allows to have
+;; age-depending date representations. (e.g. just the time if it's
+;; from today, the day of the week if it's within the last 7 days and
+;; the full date if it's older)
+
+(defun gnus-seconds-today ()
+  "Return the number of seconds passed today."
+  (let ((now (decode-time (current-time))))
+    (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600))))
+
+(defun gnus-seconds-month ()
+  "Return the number of seconds passed this month."
+  (let ((now (decode-time (current-time))))
+    (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600)
+       (* (- (car (nthcdr 3 now)) 1) 3600 24))))
+
+(defun gnus-seconds-year ()
+  "Return the number of seconds passed this year."
+  (let ((now (decode-time (current-time)))
+       (days (format-time-string "%j" (current-time))))
+    (+ (car now) (* (car (cdr now)) 60) (* (car (nthcdr 2 now)) 3600)
+       (* (- (string-to-number days) 1) 3600 24))))
+
+(defvar gnus-user-date-format-alist
+  '(((gnus-seconds-today) . "%k:%M")
+    (604800 . "%a %k:%M")                   ;;that's one week
+    ((gnus-seconds-month) . "%a %d")
+    ((gnus-seconds-year) . "%b %d")
+    (t . "%b %d '%y"))                      ;;this one is used when no
+                                           ;;other does match
+  "Specifies date format depending on age of article.
+This is an alist of items (AGE . FORMAT).  AGE can be a number (of
+seconds) or a Lisp expression evaluating to a number.  When the age of
+the article is less than this number, then use `format-time-string'
+with the corresponding FORMAT for displaying the date of the article.
+If AGE is not a number or a Lisp expression evaluating to a
+non-number, then the corresponding FORMAT is used as a default value.
+
+Note that the list is processed from the beginning, so it should be
+sorted by ascending AGE.  Also note that items following the first
+non-number AGE will be ignored.
+
+You can use the functions `gnus-seconds-today', `gnus-seconds-month'
+and `gnus-seconds-year' in the AGE spec.  They return the number of
+seconds passed since the start of today, of this month, of this year,
+respectively.")
+
+(defun gnus-user-date (messy-date)
+  "Format the messy-date according to gnus-user-date-format-alist.
+Returns \"  ?  \" if there's bad input or if an other error occurs.
+Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"."
+  (condition-case ()
+      (let* ((messy-date (time-to-seconds (safe-date-to-time messy-date)))
+            (now (time-to-seconds (current-time)))
+            ;;If we don't find something suitable we'll use this one
+            (my-format "%b %d '%y"))
+       (let* ((difference (- now messy-date))
+              (templist gnus-user-date-format-alist)
+              (top (eval (caar templist))))
+         (while (if (numberp top) (< top difference) (not top))
+           (progn
+             (setq templist (cdr templist))
+             (setq top (eval (caar templist)))))
+         (if (stringp (cdr (car templist)))
+             (setq my-format (cdr (car templist)))))
+       (format-time-string (eval my-format) (seconds-to-time messy-date)))
+    (error "  ?   ")))
+
 (defun gnus-dd-mmm (messy-date)
-  "Return a string like DD-MMM from a big messy string"
-  (let ((datevec (ignore-errors (timezone-parse-date messy-date))))
-    (if (not datevec)
-       "??-???"
-      (format "%2s-%s"
-             (condition-case ()
-                 ;; Make sure leading zeroes are stripped.
-                 (number-to-string (string-to-number (aref datevec 2)))
-               (error "??"))
-             (capitalize
-              (or (car
-                   (nth (1- (string-to-number (aref datevec 1)))
-                        timezone-months-assoc))
-                  "???"))))))
+  "Return a string like DD-MMM from a big messy string."
+  (condition-case ()
+      (format-time-string "%d-%b" (safe-date-to-time messy-date))
+    (error "  -   ")))
 
 (defmacro gnus-date-get-time (date)
   "Convert DATE string to Emacs time.
@@ -367,30 +445,24 @@ Cache the result as a text property stored in DATE."
         '(0 0)
        (or (get-text-property 0 'gnus-time d)
           ;; or compute the value...
-          (let ((time (nnmail-date-to-time d)))
+          (let ((time (safe-date-to-time d)))
             ;; and store it back in the string.
             (put-text-property 0 1 'gnus-time time d)
             time)))))
 
 (defsubst gnus-time-iso8601 (time)
-  "Return a string of TIME in YYMMDDTHHMMSS format."
+  "Return a string of TIME in YYYYMMDDTHHMMSS format."
   (format-time-string "%Y%m%dT%H%M%S" time))
 
-(defun gnus-date-iso8601 (header)
-  "Convert the date field in HEADER to YYMMDDTHHMMSS"
+(defun gnus-date-iso8601 (date)
+  "Convert the DATE to YYYYMMDDTHHMMSS."
   (condition-case ()
-      (gnus-time-iso8601 (gnus-date-get-time (mail-header-date header)))
+      (gnus-time-iso8601 (gnus-date-get-time date))
     (error "")))
 
 (defun gnus-mode-string-quote (string)
   "Quote all \"%\"'s in STRING."
-  (save-excursion
-    (gnus-set-work-buffer)
-    (insert string)
-    (goto-char (point-min))
-    (while (search-forward "%" nil t)
-      (insert "%"))
-    (buffer-string)))
+  (gnus-replace-in-string string "%" "%%"))
 
 ;; Make a hash table (default and minimum size is 256).
 ;; Optional argument HASHSIZE specifies the table size.
@@ -418,12 +490,13 @@ jabbering all the time."
   :group 'gnus-start
   :type 'integer)
 
-;; Show message if message has a lower level than `gnus-verbose'.
-;; Guideline for numbers:
-;; 1 - error messages, 3 - non-serious error messages, 5 - messages
-;; for things that take a long time, 7 - not very important messages
-;; on stuff, 9 - messages inside loops.
 (defun gnus-message (level &rest args)
+  "If LEVEL is lower than `gnus-verbose' print ARGS using `message'.
+
+Guideline for numbers:
+1 - error messages, 3 - non-serious error messages, 5 - messages for things
+that take a long time, 7 - not very important messages on stuff, 9 - messages
+inside loops."
   (if (<= level gnus-verbose)
       (apply 'message args)
     ;; We have to do this format thingy here even if the result isn't
@@ -446,21 +519,25 @@ jabbering all the time."
   "Return a list of Message-IDs in REFERENCES."
   (let ((beg 0)
        ids)
-    (while (string-match "<[^>]+>" references beg)
+    (while (string-match "<[^<]+[^< \t]" references beg)
       (push (substring references (match-beginning 0) (setq beg (match-end 0)))
            ids))
     (nreverse ids)))
 
-(defun gnus-parent-id (references &optional n)
+(defsubst gnus-parent-id (references &optional n)
   "Return the last Message-ID in REFERENCES.
 If N, return the Nth ancestor instead."
-  (when references
-    (let ((ids (inline (gnus-split-references references))))
-      (while (nthcdr (or n 1) ids)
-       (setq ids (cdr ids)))
-      (car ids))))
-
-(defsubst gnus-buffer-live-p (buffer)
+  (when (and references
+            (not (zerop (length references))))
+    (if n
+       (let ((ids (inline (gnus-split-references references))))
+         (while (nthcdr n ids)
+           (setq ids (cdr ids)))
+         (car ids))
+      (when (string-match "\\(<[^<]+>\\)[ \t]*\\'" references)
+       (match-string 1 references)))))
+
+(defun gnus-buffer-live-p (buffer)
   "Say whether BUFFER is alive or not."
   (and buffer
        (get-buffer buffer)
@@ -469,48 +546,43 @@ If N, return the Nth ancestor instead."
 (defun gnus-horizontal-recenter ()
   "Recenter the current buffer horizontally."
   (if (< (current-column) (/ (window-width) 2))
-      (set-window-hscroll (get-buffer-window (current-buffer) t) 0)
+      (set-window-hscroll (gnus-get-buffer-window (current-buffer) t) 0)
     (let* ((orig (point))
-          (end (window-end (get-buffer-window (current-buffer) t)))
+          (end (window-end (gnus-get-buffer-window (current-buffer) t)))
           (max 0))
-      ;; Find the longest line currently displayed in the window.
-      (goto-char (window-start))
-      (while (and (not (eobp))
-                 (< (point) end))
-       (end-of-line)
-       (setq max (max max (current-column)))
-       (forward-line 1))
-      (goto-char orig)
-      ;; Scroll horizontally to center (sort of) the point.
-      (if (> max (window-width))
-         (set-window-hscroll
-          (get-buffer-window (current-buffer) t)
-          (min (- (current-column) (/ (window-width) 3))
-               (+ 2 (- max (window-width)))))
-       (set-window-hscroll (get-buffer-window (current-buffer) t) 0))
-      max)))
-
-(defun gnus-read-event-char ()
+      (when end
+       ;; Find the longest line currently displayed in the window.
+       (goto-char (window-start))
+       (while (and (not (eobp))
+                   (< (point) end))
+         (end-of-line)
+         (setq max (max max (current-column)))
+         (forward-line 1))
+       (goto-char orig)
+       ;; Scroll horizontally to center (sort of) the point.
+       (if (> max (window-width))
+           (set-window-hscroll
+            (gnus-get-buffer-window (current-buffer) t)
+            (min (- (current-column) (/ (window-width) 3))
+                 (+ 2 (- max (window-width)))))
+         (set-window-hscroll (gnus-get-buffer-window (current-buffer) t) 0))
+       max))))
+
+(defun gnus-read-event-char (&optional prompt)
   "Get the next event."
-  (let ((event (read-event)))
+  (let ((event (condition-case nil
+                  (read-event prompt)
+                ;; `read-event' doesn't allow arguments in Mule 2.3
+                (wrong-number-of-arguments
+                 (when prompt
+                   (message "%s" prompt))
+                 (read-event)))))
     ;; should be gnus-characterp, but this can't be called in XEmacs anyway
     (cons (and (numberp event) event) event)))
 
 (defun gnus-sortable-date (date)
-  "Make sortable string by string-lessp from DATE.
-Timezone package is used."
-  (condition-case ()
-      (progn
-       (setq date (inline (timezone-fix-time
-                           date nil
-                           (aref (inline (timezone-parse-date date)) 4))))
-       (inline
-         (timezone-make-sortable-date
-          (aref date 0) (aref date 1) (aref date 2)
-          (inline
-            (timezone-make-time-string
-             (aref date 3) (aref date 4) (aref date 5))))))
-    (error "")))
+  "Make string suitable for sorting from DATE."
+  (gnus-time-iso8601 (date-to-time date)))
 
 (defun gnus-copy-file (file &optional to)
   "Copy FILE to TO."
@@ -524,14 +596,6 @@ Timezone package is used."
                     (file-name-nondirectory file))))
   (copy-file file to))
 
-(defun gnus-kill-all-overlays ()
-  "Delete all overlays in the current buffer."
-  (let* ((overlayss (overlay-lists))
-        (buffer-read-only nil)
-        (overlays (delq nil (nconc (car overlayss) (cdr overlayss)))))
-    (while overlays
-      (delete-overlay (pop overlays)))))
-
 (defvar gnus-work-buffer " *gnus work*")
 
 (defun gnus-set-work-buffer ()
@@ -540,9 +604,8 @@ Timezone package is used."
       (progn
        (set-buffer gnus-work-buffer)
        (erase-buffer))
-    (set-buffer (get-buffer-create gnus-work-buffer))
-    (kill-all-local-variables)
-    (buffer-disable-undo (current-buffer))))
+    (set-buffer (gnus-get-buffer-create gnus-work-buffer))
+    (kill-all-local-variables)))
 
 (defmacro gnus-group-real-name (group)
   "Find the real name of a foreign newsgroup."
@@ -552,23 +615,44 @@ Timezone package is used."
        gname)))
 
 (defun gnus-make-sort-function (funs)
-  "Return a composite sort condition based on the functions in FUNC."
+  "Return a composite sort condition based on the functions in FUNS."
   (cond
-   ((not (listp funs)) funs)
+   ;; Just a simple function.
+   ((functionp funs) funs)
+   ;; No functions at all.
    ((null funs) funs)
-   ((cdr funs)
-    `(lambda (t1 t2)
-       ,(gnus-make-sort-function-1 (reverse funs))))
+   ;; A list of functions.
+   ((or (cdr funs)
+       (listp (car funs)))
+    (gnus-byte-compile
+     `(lambda (t1 t2)
+       ,(gnus-make-sort-function-1 (reverse funs)))))
+   ;; A list containing just one function.
    (t
     (car funs))))
 
 (defun gnus-make-sort-function-1 (funs)
-  "Return a composite sort condition based on the functions in FUNC."
-  (if (cdr funs)
-      `(or (,(car funs) t1 t2)
-          (and (not (,(car funs) t2 t1))
-               ,(gnus-make-sort-function-1 (cdr funs))))
-    `(,(car funs) t1 t2)))
+  "Return a composite sort condition based on the functions in FUNS."
+  (let ((function (car funs))
+       (first 't1)
+       (last 't2))
+    (when (consp function)
+      (cond
+       ;; Reversed spec.
+       ((eq (car function) 'not)
+       (setq function (cadr function)
+             first 't2
+             last 't1))
+       ((functionp function)
+       ;; Do nothing.
+       )
+       (t
+       (error "Invalid sort spec: %s" function))))
+    (if (cdr funs)
+       `(or (,function ,first ,last)
+            (and (not (,function ,last ,first))
+                 ,(gnus-make-sort-function-1 (cdr funs))))
+      `(,function ,first ,last))))
 
 (defun gnus-turn-off-edit-menu (type)
   "Turn off edit menu in `gnus-TYPE-mode-map'."
@@ -580,36 +664,53 @@ Timezone package is used."
 Bind `print-quoted' and `print-readably' to t while printing."
   (let ((print-quoted t)
        (print-readably t)
+       (print-escape-multibyte nil)
        print-level print-length)
     (prin1 form (current-buffer))))
 
 (defun gnus-prin1-to-string (form)
-  "The same as `prin1', but bind `print-quoted' and `print-readably' to t."
+  "The same as `prin1'.
+Bind `print-quoted' and `print-readably' to t, and `print-length'
+and `print-level' to nil."
   (let ((print-quoted t)
-       (print-readably t))
+       (print-readably t)
+       (print-length nil)
+       (print-level nil))
     (prin1-to-string form)))
 
 (defun gnus-make-directory (directory)
   "Make DIRECTORY (and all its parents) if it doesn't exist."
-  (when (and directory
-            (not (file-exists-p directory)))
-    (make-directory directory t))
+  (require 'nnmail)
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
+    (when (and directory
+              (not (file-exists-p directory)))
+      (make-directory directory t)))
   t)
 
 (defun gnus-write-buffer (file)
   "Write the current buffer's contents to FILE."
   ;; Make sure the directory exists.
   (gnus-make-directory (file-name-directory file))
-  ;; Write the buffer.
-  (write-region (point-min) (point-max) file nil 'quietly))
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
+    ;; Write the buffer.
+    (write-region (point-min) (point-max) file nil 'quietly)))
 
-(defmacro gnus-delete-assq (key list)
-  `(let ((listval (eval ,list)))
-     (setq ,list (delq (assq ,key listval) listval))))
+(defun gnus-write-buffer-as-binary (file)
+  "Write the current buffer's contents to FILE without code conversion."
+  ;; Make sure the directory exists.
+  (gnus-make-directory (file-name-directory file))
+  ;; Write the buffer.
+  (write-region-as-binary (point-min) (point-max) file nil 'quietly))
 
-(defmacro gnus-delete-assoc (key list)
-  `(let ((listval ,list))
-     (setq ,list (delq (assoc ,key listval) listval))))
+(defun gnus-write-buffer-as-coding-system (coding-system file)
+  "Write the current buffer's contents to FILE with code conversion."
+  ;; Make sure the directory exists.
+  (gnus-make-directory (file-name-directory file))
+  ;; Write the buffer.
+  (write-region-as-coding-system
+   coding-system (point-min) (point-max) file nil 'quietly))
 
 (defun gnus-delete-file (file)
   "Delete FILE if it exists."
@@ -622,16 +723,55 @@ Bind `print-quoted' and `print-readably' to t while printing."
     (setq string (replace-match "" t t string)))
   string)
 
-(defun gnus-put-text-property-excluding-newlines (beg end prop val)
+(defsubst gnus-put-text-property-excluding-newlines (beg end prop val)
+  "The same as `put-text-property', but don't put this prop on any newlines in the region."
+  (save-match-data
+    (save-excursion
+      (save-restriction
+       (goto-char beg)
+       (while (re-search-forward gnus-emphasize-whitespace-regexp end 'move)
+         (gnus-put-text-property beg (match-beginning 0) prop val)
+         (setq beg (point)))
+       (gnus-put-text-property beg (point) prop val)))))
+
+(defsubst gnus-put-overlay-excluding-newlines (beg end prop val)
   "The same as `put-text-property', but don't put this prop on any newlines in the region."
   (save-match-data
     (save-excursion
       (save-restriction
        (goto-char beg)
-       (while (re-search-forward "[ \t]*\n" end 'move)
-         (put-text-property beg (match-beginning 0) prop val)
+       (while (re-search-forward gnus-emphasize-whitespace-regexp end 'move)
+         (gnus-overlay-put
+          (gnus-make-overlay beg (match-beginning 0))
+          prop val)
          (setq beg (point)))
-       (put-text-property beg (point) prop val)))))
+       (gnus-overlay-put (gnus-make-overlay beg (point)) prop val)))))
+
+(defun gnus-put-text-property-excluding-characters-with-faces (beg end
+                                                                  prop val)
+  "The same as `put-text-property', but don't put props on characters with the `gnus-face' property."
+  (let ((b beg))
+    (while (/= b end)
+      (when (get-text-property b 'gnus-face)
+       (setq b (next-single-property-change b 'gnus-face nil end)))
+      (when (/= b end)
+       (inline
+         (gnus-put-text-property
+          b (setq b (next-single-property-change b 'gnus-face nil end))
+          prop val))))))
+
+(defmacro gnus-faces-at (position)
+  "Return a list of faces at POSITION."
+  (if (featurep 'xemacs)
+      `(let ((pos ,position))
+        (mapcar-extents 'extent-face
+                        nil (current-buffer) pos pos nil 'face))
+    `(let ((pos ,position))
+       (delq nil (cons (get-text-property pos 'face)
+                      (mapcar
+                       (lambda (overlay)
+                         (overlay-get overlay 'face))
+                       (overlays-at pos)))))))
 
 ;;; Protected and atomic operations.  dmoore@ucsd.edu 21.11.1996
 ;;; The primary idea here is to try to protect internal datastructures
@@ -662,7 +802,7 @@ non-locally exits.  The variables listed in PROTECT are updated atomically.
 It is safe to use gnus-atomic-progn-assign with long computations.
 
 Note that if any of the symbols in PROTECT were unbound, they will be
-set to nil on a sucessful assignment.  In case of an error or other
+set to nil on a successful assignment.  In case of an error or other
 non-local exit, it will still be unbound."
   (let* ((temp-sym-map (mapcar (lambda (x) (list (make-symbol
                                                  (concat (symbol-name x)
@@ -710,10 +850,31 @@ with potentially long computations."
 
 ;;; Functions for saving to babyl/mail files.
 
-(defvar rmail-default-rmail-file)
+(eval-when-compile
+  (condition-case nil
+      (progn
+       (require 'rmail)
+       (autoload 'rmail-update-summary "rmailsum"))
+    (error
+     (define-compiler-macro rmail-select-summary (&rest body)
+       ;; Rmail of the XEmacs version is supplied by the package, and
+       ;; requires tm and apel packages.  However, there may be those
+       ;; who haven't installed those packages.  This macro helps such
+       ;; people even if they install those packages later.
+       `(eval '(rmail-select-summary ,@body)))
+     ;; If there's rmail but there's no tm (or there's apel of the
+     ;; mainstream, not the XEmacs version), loading rmail of the XEmacs
+     ;; version fails halfway, however it provides the rmail-select-summary
+     ;; macro which uses the following functions:
+     (autoload 'rmail-summary-displayed "rmail")
+     (autoload 'rmail-maybe-display-summary "rmail")))
+  (defvar rmail-default-rmail-file)
+  (defvar mm-text-coding-system))
+
 (defun gnus-output-to-rmail (filename &optional ask)
   "Append the current article to an Rmail file named FILENAME."
   (require 'rmail)
+  (require 'mm-util)
   ;; Most of these codes are borrowed from rmailout.el.
   (setq filename (expand-file-name filename))
   (setq rmail-default-rmail-file filename)
@@ -730,7 +891,8 @@ with potentially long computations."
                  (set-buffer file-buffer)
                  (rmail-insert-rmail-file-header)
                  (let ((require-final-newline nil))
-                   (gnus-write-buffer filename)))
+                   (gnus-write-buffer-as-coding-system
+                    nnheader-text-coding-system filename)))
                (kill-buffer file-buffer))
            (error "Output file does not exist")))
       (set-buffer tmpbuf)
@@ -740,7 +902,10 @@ with potentially long computations."
       ;; Decide whether to append to a file or to an Emacs buffer.
       (let ((outbuf (get-file-buffer filename)))
        (if (not outbuf)
-           (append-to-file (point-min) (point-max) filename)
+           (let ((file-name-coding-system nnmail-pathname-coding-system)
+                 (pathname-coding-system nnmail-pathname-coding-system))
+             (write-region-as-binary (point-min) (point-max)
+                                     filename 'append))
          ;; File has been visited, in buffer OUTBUF.
          (set-buffer outbuf)
          (let ((buffer-read-only nil)
@@ -754,9 +919,12 @@ with potentially long computations."
            (when msg
              (goto-char (point-min))
              (widen)
-             (search-backward "\^_")
+             (search-backward "\n\^_")
              (narrow-to-region (point) (point-max))
-             (goto-char (1+ (point-min)))
+             (rmail-count-new-messages t)
+             (when (rmail-summary-exists)
+               (rmail-select-summary
+                (rmail-update-summary)))
              (rmail-count-new-messages t)
              (rmail-show-message msg))
            (save-buffer)))))
@@ -778,7 +946,8 @@ with potentially long computations."
              (save-excursion
                (set-buffer file-buffer)
                (let ((require-final-newline nil))
-                 (gnus-write-buffer filename)))
+                 (gnus-write-buffer-as-coding-system
+                  nnheader-text-coding-system filename)))
              (kill-buffer file-buffer))
          (error "Output file does not exist")))
       (set-buffer tmpbuf)
@@ -805,7 +974,10 @@ with potentially long computations."
                    (insert "\n"))
                  (insert "\n"))
                (goto-char (point-max))
-               (append-to-file (point-min) (point-max) filename)))
+               (let ((file-name-coding-system nnmail-pathname-coding-system)
+                     (pathname-coding-system nnmail-pathname-coding-system))
+                 (write-region-as-binary (point-min) (point-max)
+                                         filename 'append))))
          ;; File has been visited, in buffer OUTBUF.
          (set-buffer outbuf)
          (let ((buffer-read-only nil))
@@ -828,97 +1000,556 @@ with potentially long computations."
     (insert "\^_")))
 
 (defun gnus-map-function (funs arg)
-  "Applies the result of the first function in FUNS to the second, and so on.
+  "Apply the result of the first function in FUNS to the second, and so on.
 ARG is passed to the first function."
-  (let ((myfuns funs)
-        (myarg arg))
-    (while myfuns
-      (setq arg (funcall (pop myfuns) arg)))
-    arg))
+  (while funs
+    (setq arg (funcall (pop funs) arg)))
+  arg)
 
 (defun gnus-run-hooks (&rest funcs)
-  "Does the same as `run-hooks', but saves excursion."
-  (let ((buf (current-buffer)))
-    (unwind-protect
-       (apply 'run-hooks funcs)
-      (set-buffer buf))))
-  
-;;;
-;;; .netrc and .authinforc parsing
-;;;
-
-(defvar gnus-netrc-syntax-table
-  (let ((table (copy-syntax-table text-mode-syntax-table)))
-    (modify-syntax-entry ?- "w" table)
-    (modify-syntax-entry ?_ "w" table)
-    (modify-syntax-entry ?! "w" table)
-    (modify-syntax-entry ?. "w" table)
-    (modify-syntax-entry ?, "w" table)
-    (modify-syntax-entry ?: "w" table)
-    (modify-syntax-entry ?\; "w" table)
-    (modify-syntax-entry ?% "w" table)
-    (modify-syntax-entry ?) "w" table)
-    (modify-syntax-entry ?( "w" table)
-    table)
-  "Syntax table when parsing .netrc files.")
-
-(defun gnus-parse-netrc (file)
-  "Parse FILE and return an list of all entries in the file."
-  (if (not (file-exists-p file))
-      ()
-    (save-excursion
-      (let ((tokens '("machine" "default" "login"
-                     "password" "account" "macdef"))
-           alist elem result pair)
-       (nnheader-set-temp-buffer " *netrc*")
-       (set-syntax-table gnus-netrc-syntax-table)
-       (insert-file-contents file)
-       (goto-char (point-min))
-       ;; Go through the file, line by line.
-       (while (not (eobp))
-         (narrow-to-region (point) (gnus-point-at-eol))
-         ;; For each line, get the tokens and values.
-         (while (not (eobp))
-           (skip-chars-forward "\t ")
-           (unless (eobp)
-             (setq elem (buffer-substring
-                         (point) (progn (forward-sexp 1) (point))))
-             (cond
-              ((equal elem "macdef")
-               ;; We skip past the macro definition.
-               (widen)
-               (while (and (zerop (forward-line 1))
-                           (looking-at "$")))
-               (narrow-to-region (point) (point)))
-              ((member elem tokens)
-               ;; Tokens that don't have a following value are ignored.
-               (when (and pair (cdr pair))
-                 (push pair alist))
-               (setq pair (list elem)))
-              (t
-               ;; Values that haven't got a preceding token are ignored.
-               (when pair
-                 (setcdr pair elem)
-                 (push pair alist)
-                 (setq pair nil))))))
-         (push alist result)
-         (setq alist nil
-               pair nil)
-         (widen)
-         (forward-line 1))
-       result))))
-
-(defun gnus-netrc-machine (list machine)
-  "Return the netrc values from LIST for MACHINE."
-  (while (and list
-             (not (equal (cdr (assoc "machine" (car list))) machine)))
-    (pop list))
-  (when list
-    (car list)))
-
-(defun gnus-netrc-get (alist type)
-  "Return the value of token TYPE from ALIST."
-  (cdr (assoc type alist)))
+  "Does the same as `run-hooks', but saves the current buffer."
+  (save-current-buffer
+    (apply 'run-hooks funcs)))
+
+;;; Various
+
+(defvar gnus-group-buffer)             ; Compiler directive
+(defun gnus-alive-p ()
+  "Say whether Gnus is running or not."
+  (and (boundp 'gnus-group-buffer)
+       (get-buffer gnus-group-buffer)
+       (save-excursion
+        (set-buffer gnus-group-buffer)
+        (eq major-mode 'gnus-group-mode))))
+
+(defun gnus-remove-duplicates (list)
+  (let (new)
+    (while list
+      (or (member (car list) new)
+         (setq new (cons (car list) new)))
+      (setq list (cdr list)))
+    (nreverse new)))
+
+(defun gnus-remove-if (predicate list)
+  "Return a copy of LIST with all items satisfying PREDICATE removed."
+  (let (out)
+    (while list
+      (unless (funcall predicate (car list))
+       (push (car list) out))
+      (setq list (cdr list)))
+    (nreverse out)))
+
+(if (fboundp 'assq-delete-all)
+    (defalias 'gnus-delete-alist 'assq-delete-all)
+  (defun gnus-delete-alist (key alist)
+    "Delete from ALIST all elements whose car is KEY.
+Return the modified alist."
+    (let (entry)
+      (while (setq entry (assq key alist))
+       (setq alist (delq entry alist)))
+      alist)))
+
+(defmacro gnus-pull (key alist &optional assoc-p)
+  "Modify ALIST to be without KEY."
+  (unless (symbolp alist)
+    (error "Not a symbol: %s" alist))
+  (let ((fun (if assoc-p 'assoc 'assq)))
+    `(setq ,alist (delq (,fun ,key ,alist) ,alist))))
+
+(defun gnus-globalify-regexp (re)
+  "Return a regexp that matches a whole line, iff RE matches a part of it."
+  (concat (unless (string-match "^\\^" re) "^.*")
+         re
+         (unless (string-match "\\$$" re) ".*$")))
+
+(defun gnus-set-window-start (&optional point)
+  "Set the window start to POINT, or (point) if nil."
+  (let ((win (gnus-get-buffer-window (current-buffer) t)))
+    (when win
+      (set-window-start win (or point (point))))))
+
+(defun gnus-annotation-in-region-p (b e)
+  (if (= b e)
+      (eq (cadr (memq 'gnus-undeletable (text-properties-at b))) t)
+    (text-property-any b e 'gnus-undeletable t)))
+
+(defun gnus-or (&rest elems)
+  "Return non-nil if any of the elements are non-nil."
+  (catch 'found
+    (while elems
+      (when (pop elems)
+       (throw 'found t)))))
+
+(defun gnus-and (&rest elems)
+  "Return non-nil if all of the elements are non-nil."
+  (catch 'found
+    (while elems
+      (unless (pop elems)
+       (throw 'found nil)))
+    t))
+
+(defun gnus-write-active-file (file hashtb &optional full-names)
+  (let ((output-coding-system nnmail-active-file-coding-system)
+       (coding-system-for-write nnmail-active-file-coding-system))
+    (with-temp-file file
+      (mapatoms
+       (lambda (sym)
+        (when (and sym
+                   (boundp sym)
+                   (symbol-value sym))
+          (insert (format "%S %d %d y\n"
+                          (if full-names
+                              sym
+                            (intern (gnus-group-real-name (symbol-name sym))))
+                          (or (cdr (symbol-value sym))
+                              (car (symbol-value sym)))
+                          (car (symbol-value sym))))))
+       hashtb)
+      (goto-char (point-max))
+      (while (search-backward "\\." nil t)
+       (delete-char 1)))))
+
+;; Fixme: Why not use `with-output-to-temp-buffer'?
+(defmacro gnus-with-output-to-file (file &rest body)
+  (let ((buffer (make-symbol "output-buffer"))
+        (size (make-symbol "output-buffer-size"))
+        (leng (make-symbol "output-buffer-length"))
+        (append (make-symbol "output-buffer-append")))
+    `(let* ((,size 131072)
+            (,buffer (make-string ,size 0))
+            (,leng 0)
+            (,append nil)
+            (standard-output
+            (lambda (c)
+               (aset ,buffer ,leng c)
+                   
+              (if (= ,size (setq ,leng (1+ ,leng)))
+                  (progn (write-region ,buffer nil ,file ,append 'no-msg)
+                         (setq ,leng 0
+                               ,append t))))))
+       ,@body
+       (when (> ,leng 0)
+         (let ((coding-system-for-write 'no-conversion))
+        (write-region (substring ,buffer 0 ,leng) nil ,file
+                      ,append 'no-msg))))))
+
+(put 'gnus-with-output-to-file 'lisp-indent-function 1)
+(put 'gnus-with-output-to-file 'edebug-form-spec '(form body))
+
+(if (fboundp 'union)
+    (defalias 'gnus-union 'union)
+  (defun gnus-union (l1 l2)
+    "Set union of lists L1 and L2."
+    (cond ((null l1) l2)
+         ((null l2) l1)
+         ((equal l1 l2) l1)
+         (t
+          (or (>= (length l1) (length l2))
+              (setq l1 (prog1 l2 (setq l2 l1))))
+          (while l2
+            (or (member (car l2) l1)
+                (push (car l2) l1))
+            (pop l2))
+          l1))))
+
+(defun gnus-add-text-properties-when
+  (property value start end properties &optional object)
+  "Like `gnus-add-text-properties', only applied on where PROPERTY is VALUE."
+  (let (point)
+    (while (and start
+               (< start end) ;; XEmacs will loop for every when start=end.
+               (setq point (text-property-not-all start end property value)))
+      (gnus-add-text-properties start point properties object)
+      (setq start (text-property-any point end property value)))
+    (if start
+       (gnus-add-text-properties start end properties object))))
+
+(defun gnus-remove-text-properties-when
+  (property value start end properties &optional object)
+  "Like `remove-text-properties', only applied on where PROPERTY is VALUE."
+  (let (point)
+    (while (and start
+               (< start end)
+               (setq point (text-property-not-all start end property value)))
+      (remove-text-properties start point properties object)
+      (setq start (text-property-any point end property value)))
+    (if start
+       (remove-text-properties start end properties object))
+    t))
+
+;; This might use `compare-strings' to reduce consing in the
+;; case-insensitive case, but it has to cope with null args.
+;; (`string-equal' uses symbol print names.)
+(defun gnus-string-equal (x y)
+  "Like `string-equal', except it compares case-insensitively."
+  (and (= (length x) (length y))
+       (or (string-equal x y)
+          (string-equal (downcase x) (downcase y)))))
+
+(defcustom gnus-use-byte-compile t
+  "If non-nil, byte-compile crucial run-time code.
+Setting it to nil has no effect after the first time `gnus-byte-compile'
+is run."
+  :type 'boolean
+  :version "21.1"
+  :group 'gnus-various)
+
+(defun gnus-byte-compile (form)
+  "Byte-compile FORM if `gnus-use-byte-compile' is non-nil."
+  (if gnus-use-byte-compile
+      (progn
+       (condition-case nil
+           ;; Work around a bug in XEmacs 21.4
+           (require 'byte-optimize)
+         (error))
+       (require 'bytecomp)
+       (defalias 'gnus-byte-compile
+         (lambda (form)
+           (let ((byte-compile-warnings '(unresolved callargs redefine)))
+             (byte-compile form))))
+       (gnus-byte-compile form))
+    form))
+
+(defun gnus-remassoc (key alist)
+  "Delete by side effect any elements of LIST whose car is `equal' to KEY.
+The modified LIST is returned.  If the first member
+of LIST has a car that is `equal' to KEY, there is no way to remove it
+by side effect; therefore, write `(setq foo (remassoc key foo))' to be
+sure of changing the value of `foo'."
+  (when alist
+    (if (equal key (caar alist))
+       (cdr alist)
+      (setcdr alist (gnus-remassoc key (cdr alist)))
+      alist)))
+
+(defun gnus-update-alist-soft (key value alist)
+  (if value
+      (cons (cons key value) (gnus-remassoc key alist))
+    (gnus-remassoc key alist)))
+
+(defun gnus-create-info-command (node)
+  "Create a command that will go to info NODE."
+  `(lambda ()
+     (interactive)
+     ,(concat "Enter the info system at node " node)
+     (Info-goto-node ,node)
+     (setq gnus-info-buffer (current-buffer))
+     (gnus-configure-windows 'info)))
+
+(defun gnus-not-ignore (&rest args)
+  t)
+
+(defvar gnus-directory-sep-char-regexp "/"
+  "The regexp of directory separator character.
+If you find some problem with the directory separator character, try
+\"[/\\\\\]\" for some systems.")
+
+(defun gnus-url-unhex (x)
+  (if (> x ?9)
+      (if (>= x ?a)
+         (+ 10 (- x ?a))
+       (+ 10 (- x ?A)))
+    (- x ?0)))
+
+;; Fixme: Do it like QP.
+(defun gnus-url-unhex-string (str &optional allow-newlines)
+  "Remove %XX, embedded spaces, etc in a url.
+If optional second argument ALLOW-NEWLINES is non-nil, then allow the
+decoding of carriage returns and line feeds in the string, which is normally
+forbidden in URL encoding."
+  (let ((tmp "")
+       (case-fold-search t))
+    (while (string-match "%[0-9a-f][0-9a-f]" str)
+      (let* ((start (match-beginning 0))
+            (ch1 (gnus-url-unhex (elt str (+ start 1))))
+            (code (+ (* 16 ch1)
+                     (gnus-url-unhex (elt str (+ start 2))))))
+       (setq tmp (concat
+                  tmp (substring str 0 start)
+                  (cond
+                   (allow-newlines
+                    (char-to-string code))
+                   ((or (= code ?\n) (= code ?\r))
+                    " ")
+                   (t (char-to-string code))))
+             str (substring str (match-end 0)))))
+    (setq tmp (concat tmp str))
+    tmp))
+
+(defun gnus-make-predicate (spec)
+  "Transform SPEC into a function that can be called.
+SPEC is a predicate specifier that contains stuff like `or', `and',
+`not', lists and functions.  The functions all take one parameter."
+  `(lambda (elem) ,(gnus-make-predicate-1 spec)))
+
+(defun gnus-make-predicate-1 (spec)
+  (cond
+   ((symbolp spec)
+    `(,spec elem))
+   ((listp spec)
+    (if (memq (car spec) '(or and not))
+       `(,(car spec) ,@(mapcar 'gnus-make-predicate-1 (cdr spec)))
+      (error "Invalid predicate specifier: %s" spec)))))
+
+(defun gnus-local-map-property (map)
+  "Return a list suitable for a text property list specifying keymap MAP."
+  (cond
+   ((featurep 'xemacs)
+    (list 'keymap map))
+   ((>= emacs-major-version 21)
+    (list 'keymap map))
+   (t
+    (list 'local-map map))))
+
+(defmacro gnus-completing-read-maybe-default (prompt table &optional predicate
+                                             require-match initial-contents
+                                             history default)
+  "Like `completing-read', allowing for non-existent 7th arg in older XEmacsen."
+  `(completing-read ,prompt ,table ,predicate ,require-match
+                    ,initial-contents ,history
+                    ,@(if (and (featurep 'xemacs) (< emacs-minor-version 2))
+                          ()
+                        (list default))))
+
+(defun gnus-completing-read (prompt table &optional predicate require-match
+                                   history)
+  (when (and history
+            (not (boundp history)))
+    (set history nil))
+  (gnus-completing-read-maybe-default
+   (if (symbol-value history)
+       (concat prompt " (" (car (symbol-value history)) "): ")
+     (concat prompt ": "))
+   table
+   predicate
+   require-match
+   nil
+   history
+   (car (symbol-value history))))
+
+(defun gnus-graphic-display-p ()
+  (or (and (fboundp 'display-graphic-p)
+          (display-graphic-p))
+      ;;;!!!This is bogus.  Fixme!
+      (and (featurep 'xemacs)
+          t)))
+
+(put 'gnus-parse-without-error 'lisp-indent-function 0)
+(put 'gnus-parse-without-error 'edebug-form-spec '(body))
+
+(defmacro gnus-parse-without-error (&rest body)
+  "Allow continuing onto the next line even if an error occurs."
+  `(while (not (eobp))
+     (condition-case ()
+        (progn
+          ,@body
+          (goto-char (point-max)))
+       (error
+       (gnus-error 4 "Invalid data on line %d"
+                   (count-lines (point-min) (point)))
+       (forward-line 1)))))
+
+(defun gnus-cache-file-contents (file variable function)
+  "Cache the contents of FILE in VARIABLE.  The contents come from FUNCTION."
+  (let ((time (nth 5 (file-attributes file)))
+       contents value)
+    (if (or (null (setq value (symbol-value variable)))
+           (not (equal (car value) file))
+           (not (equal (nth 1 value) time)))
+       (progn
+         (setq contents (funcall function file))
+         (set variable (list file time contents))
+         contents)
+      (nth 2 value))))
+
+(defun gnus-multiple-choice (prompt choice &optional idx)
+  "Ask user a multiple choice question.
+CHOICE is a list of the choice char and help message at IDX."
+  (let (tchar buf)
+    (save-window-excursion
+      (save-excursion
+       (while (not tchar)
+         (message "%s (%s): "
+                  prompt
+                  (concat
+                   (mapconcat (lambda (s) (char-to-string (car s)))
+                              choice ", ") ", ?"))
+         (setq tchar (read-char))
+         (when (not (assq tchar choice))
+           (setq tchar nil)
+           (setq buf (get-buffer-create "*Gnus Help*"))
+           (pop-to-buffer buf)
+           (fundamental-mode)          ; for Emacs 20.4+
+           (buffer-disable-undo)
+           (erase-buffer)
+           (insert prompt ":\n\n")
+           (let ((max -1)
+                 (list choice)
+                 (alist choice)
+                 (idx (or idx 1))
+                 (i 0)
+                 n width pad format)
+             ;; find the longest string to display
+             (while list
+               (setq n (length (nth idx (car list))))
+               (unless (> max n)
+                 (setq max n))
+               (setq list (cdr list)))
+             (setq max (+ max 4))      ; %c, `:', SPACE, a SPACE at end
+             (setq n (/ (1- (window-width)) max)) ; items per line
+             (setq width (/ (1- (window-width)) n)) ; width of each item
+             ;; insert `n' items, each in a field of width `width'
+             (while alist
+               (if (< i n)
+                   ()
+                 (setq i 0)
+                 (delete-char -1)              ; the `\n' takes a char
+                 (insert "\n"))
+               (setq pad (- width 3))
+               (setq format (concat "%c: %-" (int-to-string pad) "s"))
+               (insert (format format (caar alist) (nth idx (car alist))))
+               (setq alist (cdr alist))
+               (setq i (1+ i))))))))
+    (if (buffer-live-p buf)
+       (kill-buffer buf))
+    tchar))
+
+(defun gnus-select-frame-set-input-focus (frame)
+  "Select FRAME, raise it, and set input focus, if possible."
+  (cond ((featurep 'xemacs)
+        (raise-frame frame)
+        (select-frame frame)
+        (focus-frame frame))
+       ;; The function `select-frame-set-input-focus' won't set
+       ;; the input focus under Emacs 21.2 and X window system.
+       ;;((fboundp 'select-frame-set-input-focus)
+       ;; (defalias 'gnus-select-frame-set-input-focus
+       ;;   'select-frame-set-input-focus)
+       ;; (select-frame-set-input-focus frame))
+       (t
+        (raise-frame frame)
+        (select-frame frame)
+        (cond ((and (eq window-system 'x)
+                    (fboundp 'x-focus-frame))
+               (x-focus-frame frame))
+              ((eq window-system 'w32)
+               (w32-focus-frame frame)))
+        (when (or (not (boundp 'focus-follows-mouse))
+                  (symbol-value 'focus-follows-mouse))
+          (set-mouse-position frame (1- (frame-width frame)) 0)))))
+
+(unless (fboundp 'frame-parameter)
+  (defalias 'frame-parameter
+    (lambda (frame parameter)
+      "Return FRAME's value for parameter PARAMETER.
+If FRAME is nil, describe the currently selected frame."
+      (cdr (assq parameter (frame-parameters frame))))))
+
+(defun gnus-frame-or-window-display-name (object)
+  "Given a frame or window, return the associated display name.
+Return nil otherwise."
+  (if (featurep 'xemacs)
+      (device-connection (dfw-device object))
+    (if (or (framep object)
+           (and (windowp object)
+                (setq object (window-frame object))))
+       (let ((display (frame-parameter object 'display)))
+         (if (and (stringp display)
+                  ;; Exclude invalid display names.
+                  (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'"
+                                display))
+             display)))))
+
+;; Fixme: This has only one use (in gnus-agent), which isn't worthwhile.
+(defmacro gnus-mapcar (function seq1 &rest seqs2_n)
+  "Apply FUNCTION to each element of the sequences, and make a list of the results.
+If there are several sequences, FUNCTION is called with that many arguments,
+and mapping stops as soon as the shortest sequence runs out.  With just one
+sequence, this is like `mapcar'.  With several, it is like the Common Lisp
+`mapcar' function extended to arbitrary sequence types."
+
+  (if seqs2_n
+      (let* ((seqs (cons seq1 seqs2_n))
+            (cnt 0)
+            (heads (mapcar (lambda (seq)
+                             (make-symbol (concat "head"
+                                                  (int-to-string
+                                                   (setq cnt (1+ cnt))))))
+                           seqs))
+            (result (make-symbol "result"))
+            (result-tail (make-symbol "result-tail")))
+       `(let* ,(let* ((bindings (cons nil nil))
+                      (heads heads))
+                 (nconc bindings (list (list result '(cons nil nil))))
+                 (nconc bindings (list (list result-tail result)))
+                 (while heads
+                   (nconc bindings (list (list (pop heads) (pop seqs)))))
+                 (cdr bindings))
+          (while (and ,@heads)
+            (setcdr ,result-tail (cons (funcall ,function
+                                                ,@(mapcar (lambda (h) (list 'car h))
+                                                          heads))
+                                       nil))
+            (setq ,result-tail (cdr ,result-tail)
+                  ,@(apply 'nconc (mapcar (lambda (h) (list h (list 'cdr h))) heads))))
+          (cdr ,result)))
+    `(mapcar ,function ,seq1)))
+
+(if (fboundp 'merge)
+    (defalias 'gnus-merge 'merge)
+  ;; Adapted from cl-seq.el
+  (defun gnus-merge (type list1 list2 pred)
+    "Destructively merge lists LIST1 and LIST2 to produce a new list.
+Argument TYPE is for compatibility and ignored.
+Ordering of the elements is preserved according to PRED, a `less-than'
+predicate on the elements."
+    (let ((res nil))
+      (while (and list1 list2)
+       (if (funcall pred (car list2) (car list1))
+           (push (pop list2) res)
+         (push (pop list1) res)))
+      (nconc (nreverse res) list1 list2))))
+
+(eval-when-compile
+  (defvar xemacs-codename))
+
+(defun gnus-emacs-version ()
+  "Stringified Emacs version."
+  (let ((system-v
+        (cond
+         ((eq gnus-user-agent 'emacs-gnus-config)
+          system-configuration)
+         ((eq gnus-user-agent 'emacs-gnus-type)
+          (symbol-name system-type))
+         (t nil))))
+    (cond
+     ((eq gnus-user-agent 'gnus)
+      nil)
+     ((string-match "^\\(\\([.0-9]+\\)*\\)\\.[0-9]+$" emacs-version)
+      (concat (format (if (boundp 'MULE)
+                         "Mule/2.3 (based on Emacs %s)"
+                       "Emacs/%s")
+                     (match-string 1 emacs-version))
+             (if system-v
+                 (concat " (" system-v ")")
+               "")))
+     ((string-match
+       "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?"
+       emacs-version)
+      (concat
+       (match-string 1 emacs-version)
+       (format "/%d.%d" emacs-major-version emacs-minor-version)
+       (if (match-beginning 3)
+          (match-string 3 emacs-version)
+        "")
+       (if (boundp 'xemacs-codename)
+          (concat
+           " (" xemacs-codename
+           (if system-v
+               (concat ", " system-v ")")
+             ")"))
+        "")))
+     (t emacs-version))))
 
 (provide 'gnus-util)
 
index 940fab5..c6703be 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-uu.el --- extract (uu)encoded files in Gnus
-;; Copyright (C) 1985,86,87,93,94,95,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
+;;        2001, 2002, 2003 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Created: 2 Oct 1993
 ;; Keyword: news
 
 ;; Default viewing action rules
 
 (defcustom gnus-uu-default-view-rules
-  '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/\r//g")
-    ("\\.pas$" "cat %s | sed s/\r//g")
+  '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed 's/\r$//'")
+    ("\\.pas$" "cat %s | sed 's/\r$//'")
     ("\\.[1-9]$" "groff -mandoc -Tascii %s | sed s/\b.//g")
-    ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
-    ("\\.tga$" "tgatoppm %s | xv -")
+    ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "display")
+    ("\\.tga$" "tgatoppm %s | ee -")
     ("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
      "sox -v .5 %s -t .au -u - > /dev/audio")
     ("\\.au$" "cat %s > /dev/audio")
@@ -215,7 +216,10 @@ Note that this variable can be used in conjunction with the
 
 ;; Various variables users may set
 
-(defcustom gnus-uu-tmp-dir "/tmp/"
+(defcustom gnus-uu-tmp-dir
+  (cond ((fboundp 'temp-directory) (temp-directory))
+       ((boundp 'temporary-file-directory) temporary-file-directory)
+       ("/tmp/"))
   "*Variable saying where gnus-uu is to do its work.
 Default is \"/tmp/\"."
   :group 'gnus-extract
@@ -290,9 +294,12 @@ so I simply dropped them."
 
 (defcustom gnus-uu-digest-headers
   '("^Date:" "^From:" "^To:" "^Cc:" "^Subject:" "^Message-ID:" "^Keywords:"
-    "^Summary:" "^References:")
+    "^Summary:" "^References:" "^Content-Type:" "^Content-Transfer-Encoding:"
+    "^MIME-Version:" "^Content-Disposition:" "^Content-Description:"
+    "^Content-ID:" "^User-Agent:" "^X-Face:")
   "*List of regexps to match headers included in digested messages.
-The headers will be included in the sequence they are matched."
+The headers will be included in the sequence they are matched.  If nil
+include all headers."
   :group 'gnus-extract
   :type '(repeat regexp))
 
@@ -314,7 +321,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 
 (defvar gnus-uu-saved-article-name nil)
 
-(defvar gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
+(defvar gnus-uu-begin-string "^begin[ \t]+0?[0-7][0-7][0-7][ \t]+\\(.*\\)$")
 (defvar gnus-uu-end-string "^end[ \t]*$")
 
 (defvar gnus-uu-body-line "^M")
@@ -328,7 +335,8 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 (defvar gnus-uu-shar-begin-string "^#! */bin/sh")
 
 (defvar gnus-uu-shar-file-name nil)
-(defvar gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)")
+(defvar gnus-uu-shar-name-marker
+  "begin 0?[0-7][0-7][0-7][ \t]+\\(\\(\\w\\|[.\\:]\\)*\\b\\)")
 
 (defvar gnus-uu-postscript-begin-string "^%!PS-")
 (defvar gnus-uu-postscript-end-string "^%%EOF$")
@@ -343,54 +351,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 
 (defvar gnus-uu-default-dir gnus-article-save-directory)
 (defvar gnus-uu-digest-from-subject nil)
-
-;; Keymaps
-
-(gnus-define-keys (gnus-uu-mark-map "P" gnus-summary-mark-map)
-  "p" gnus-summary-mark-as-processable
-  "u" gnus-summary-unmark-as-processable
-  "U" gnus-summary-unmark-all-processable
-  "v" gnus-uu-mark-over
-  "s" gnus-uu-mark-series
-  "r" gnus-uu-mark-region
-  "R" gnus-uu-mark-by-regexp
-  "t" gnus-uu-mark-thread
-  "T" gnus-uu-unmark-thread
-  "a" gnus-uu-mark-all
-  "b" gnus-uu-mark-buffer
-  "S" gnus-uu-mark-sparse
-  "k" gnus-summary-kill-process-mark
-  "y" gnus-summary-yank-process-mark
-  "w" gnus-summary-save-process-mark
-  "i" gnus-uu-invert-processable)
-
-(gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map)
-  ;;"x" gnus-uu-extract-any
-  ;;"m" gnus-uu-extract-mime
-  "u" gnus-uu-decode-uu
-  "U" gnus-uu-decode-uu-and-save
-  "s" gnus-uu-decode-unshar
-  "S" gnus-uu-decode-unshar-and-save
-  "o" gnus-uu-decode-save
-  "O" gnus-uu-decode-save
-  "b" gnus-uu-decode-binhex
-  "B" gnus-uu-decode-binhex
-  "p" gnus-uu-decode-postscript
-  "P" gnus-uu-decode-postscript-and-save)
-
-(gnus-define-keys
- (gnus-uu-extract-view-map "v" gnus-uu-extract-map)
- "u" gnus-uu-decode-uu-view
- "U" gnus-uu-decode-uu-and-save-view
- "s" gnus-uu-decode-unshar-view
- "S" gnus-uu-decode-unshar-and-save-view
- "o" gnus-uu-decode-save-view
- "O" gnus-uu-decode-save-view
- "b" gnus-uu-decode-binhex-view
- "B" gnus-uu-decode-binhex-view
- "p" gnus-uu-decode-postscript-view
- "P" gnus-uu-decode-postscript-and-save-view)
-
+(defvar gnus-uu-digest-buffer nil)
 
 ;; Commands.
 
@@ -446,7 +407,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                          gnus-uu-default-dir
                          gnus-uu-default-dir))))
   (setq gnus-uu-binhex-article-name
-       (make-temp-name (concat gnus-uu-work-dir "binhex")))
+       (mm-make-temp-file (expand-file-name "binhex" gnus-uu-work-dir)))
   (gnus-uu-decode-with-method 'gnus-uu-binhex-article n dir))
 
 (defun gnus-uu-decode-uu-view (&optional n)
@@ -499,7 +460,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
         (read-file-name "Unbinhex, view and save in dir: "
                         gnus-uu-default-dir gnus-uu-default-dir)))
   (setq gnus-uu-binhex-article-name
-       (make-temp-name (concat gnus-uu-work-dir "binhex")))
+       (mm-make-temp-file (expand-file-name "binhex" gnus-uu-work-dir)))
   (let ((gnus-view-pseudos (or gnus-view-pseudos 'automatic)))
     (gnus-uu-decode-binhex n file)))
 
@@ -510,47 +471,52 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
   "Digests and forwards all articles in this series."
   (interactive "P")
   (let ((gnus-uu-save-in-digest t)
-       (file (make-temp-name (nnheader-concat gnus-uu-tmp-dir "forward")))
-       buf subject from newsgroups)
-    (gnus-setup-message 'forward
-      (setq gnus-uu-digest-from-subject nil)
-      (gnus-uu-decode-save n file)
-      (setq buf (switch-to-buffer (get-buffer-create " *gnus-uu-forward*")))
-      (gnus-add-current-to-buffer-list)
-      (erase-buffer)
-      (insert-file file)
-      (let ((fs gnus-uu-digest-from-subject))
-       (when fs
-         (setq from (caar fs)
-               subject (gnus-simplify-subject-fuzzy (cdar fs))
-               fs (cdr fs))
-         (while (and fs (or from subject))
-           (when from
-             (unless (string= from (caar fs))
-               (setq from nil)))
-           (when subject
-             (unless (string= (gnus-simplify-subject-fuzzy (cdar fs))
-                              subject)
-               (setq subject nil)))
-           (setq fs (cdr fs))))
-       (unless subject
-         (setq subject "Digested Articles"))
-       (unless from
-         (setq from
-               (if (gnus-news-group-p gnus-newsgroup-name)
-                   gnus-newsgroup-name
-                 "Various"))))
-      (goto-char (point-min))
-      (when (re-search-forward "^Subject: ")
-       (delete-region (point) (gnus-point-at-eol))
-       (insert subject))
-      (goto-char (point-min))
-      (when (re-search-forward "^From: ")
-       (delete-region (point) (gnus-point-at-eol))
-       (insert from))
-      (message-forward post))
-    (delete-file file)
-    (kill-buffer buf)
+       (file (mm-make-temp-file (nnheader-concat gnus-uu-tmp-dir "forward")))
+       (message-forward-as-mime message-forward-as-mime)
+       (mail-parse-charset gnus-newsgroup-charset)
+       (mail-parse-ignored-charsets gnus-newsgroup-ignored-charsets)
+       gnus-uu-digest-buffer subject from)
+    (if (and n (not (numberp n)))
+       (setq message-forward-as-mime (not message-forward-as-mime)
+             n nil))
+    (let ((gnus-article-reply (gnus-summary-work-articles n)))
+      (gnus-setup-message 'forward
+       (setq gnus-uu-digest-from-subject nil)
+       (setq gnus-uu-digest-buffer
+             (gnus-get-buffer-create " *gnus-uu-forward*"))
+       (gnus-uu-decode-save n file)
+       (switch-to-buffer gnus-uu-digest-buffer)
+       (let ((fs gnus-uu-digest-from-subject))
+         (when fs
+           (setq from (caar fs)
+                 subject (gnus-simplify-subject-fuzzy (cdar fs))
+                 fs (cdr fs))
+           (while (and fs (or from subject))
+             (when from
+               (unless (string= from (caar fs))
+                 (setq from nil)))
+             (when subject
+               (unless (string= (gnus-simplify-subject-fuzzy (cdar fs))
+                                subject)
+                 (setq subject nil)))
+             (setq fs (cdr fs))))
+         (unless subject
+           (setq subject "Digested Articles"))
+         (unless from
+           (setq from
+                 (if (gnus-news-group-p gnus-newsgroup-name)
+                     gnus-newsgroup-name
+                   "Various"))))
+       (goto-char (point-min))
+       (when (re-search-forward "^Subject: ")
+         (delete-region (point) (gnus-point-at-eol))
+         (insert subject))
+       (goto-char (point-min))
+       (when (re-search-forward "^From:")
+         (delete-region (point) (gnus-point-at-eol))
+         (insert " " from))
+       (let ((message-forward-decoded-p t))
+         (message-forward post))))
     (setq gnus-uu-digest-from-subject nil)))
 
 (defun gnus-uu-digest-post-forward (&optional n)
@@ -560,30 +526,57 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 
 ;; Process marking.
 
+(defun gnus-message-process-mark (unmarkp new-marked)
+  (let ((old (- (length gnus-newsgroup-processable) (length new-marked))))
+    (message "%d mark%s %s%s"
+            (length new-marked)
+            (if (= (length new-marked) 1) "" "s")
+            (if unmarkp "removed" "added")
+            (cond
+             ((and (zerop old)
+                   (not unmarkp))
+              "")
+             (unmarkp
+              (format ", %d remain marked"
+                      (length gnus-newsgroup-processable)))
+             (t
+              (format ", %d already marked" old))))))
+
+(defun gnus-new-processable (unmarkp articles)
+  (if unmarkp
+      (gnus-intersection gnus-newsgroup-processable articles)
+    (gnus-set-difference articles gnus-newsgroup-processable)))
+
 (defun gnus-uu-mark-by-regexp (regexp &optional unmark)
-  "Ask for a regular expression and set the process mark on all articles that match."
-  (interactive (list (read-from-minibuffer "Mark (regexp): ")))
-  (let ((articles (gnus-uu-find-articles-matching regexp)))
-    (while articles
-      (if unmark
-         (gnus-summary-remove-process-mark (pop articles))
-       (gnus-summary-set-process-mark (pop articles))))
-    (message ""))
+  "Set the process mark on articles whose subjects match REGEXP.
+When called interactively, prompt for REGEXP.
+Optional UNMARK non-nil means unmark instead of mark."
+  (interactive "sMark (regexp): \nP")
+  (save-excursion
+    (let* ((articles (gnus-uu-find-articles-matching regexp))
+          (new-marked (gnus-new-processable unmark articles)))
+      (while articles
+       (if unmark
+           (gnus-summary-remove-process-mark (pop articles))
+         (gnus-summary-set-process-mark (pop articles))))
+      (gnus-message-process-mark unmark new-marked)))
   (gnus-summary-position-point))
 
-(defun gnus-uu-unmark-by-regexp (regexp &optional unmark)
-  "Ask for a regular expression and remove the process mark on all articles that match."
-  (interactive (list (read-from-minibuffer "Mark (regexp): ")))
+(defun gnus-uu-unmark-by-regexp (regexp)
+  "Remove the process mark from articles whose subjects match REGEXP.
+When called interactively, prompt for REGEXP."
+  (interactive "sUnmark (regexp): ")
   (gnus-uu-mark-by-regexp regexp t))
 
 (defun gnus-uu-mark-series ()
   "Mark the current series with the process mark."
   (interactive)
-  (let ((articles (gnus-uu-find-articles-matching)))
+  (let* ((articles (gnus-uu-find-articles-matching))
+         (l (length articles)))
     (while articles
       (gnus-summary-set-process-mark (car articles))
       (setq articles (cdr articles)))
-    (message ""))
+    (message "Marked %d articles" l))
   (gnus-summary-position-point))
 
 (defun gnus-uu-mark-region (beg end &optional unmark)
@@ -616,10 +609,12 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 (defun gnus-uu-mark-thread ()
   "Marks all articles downwards in this thread."
   (interactive)
-  (let ((level (gnus-summary-thread-level)))
-    (while (and (gnus-summary-set-process-mark (gnus-summary-article-number))
-               (zerop (gnus-summary-next-subject 1))
-               (> (gnus-summary-thread-level) level))))
+  (gnus-save-hidden-threads
+    (let ((level (gnus-summary-thread-level)))
+      (while (and (gnus-summary-set-process-mark
+                  (gnus-summary-article-number))
+                 (zerop (gnus-summary-next-subject 1 nil t))
+                 (> (gnus-summary-thread-level) level)))))
   (gnus-summary-position-point))
 
 (defun gnus-uu-unmark-thread ()
@@ -636,7 +631,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
   "Invert the list of process-marked articles."
   (interactive)
   (let ((data gnus-newsgroup-data)
-       d number)
+       number)
     (save-excursion
       (while data
        (if (memq (setq number (gnus-data-number (pop data)))
@@ -646,9 +641,9 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
   (gnus-summary-position-point))
 
 (defun gnus-uu-mark-over (&optional score)
-  "Mark all articles with a score over SCORE (the prefix.)"
+  "Mark all articles with a score over SCORE (the prefix)."
   (interactive "P")
-  (let ((score (gnus-score-default score))
+  (let ((score (or score gnus-summary-default-score 0))
        (data gnus-newsgroup-data))
     (save-excursion
       (while data
@@ -804,7 +799,8 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
    (gnus-uu-save-separate-articles
     (save-excursion
       (set-buffer buffer)
-      (gnus-write-buffer
+      (gnus-write-buffer-as-coding-system
+       nnheader-text-coding-system
        (concat gnus-uu-saved-article-name gnus-current-article))
       (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin))
            ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name
@@ -826,24 +822,25 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                  (mail-header-subject header))
            gnus-uu-digest-from-subject))
     (let ((name (file-name-nondirectory gnus-uu-saved-article-name))
-         (delim (concat "^" (make-string 30 ?-) "$"))
          beg subj headers headline sorthead body end-string state)
       (if (or (eq in-state 'first)
              (eq in-state 'first-and-last))
          (progn
            (setq state (list 'begin))
-           (save-excursion (set-buffer (get-buffer-create "*gnus-uu-body*"))
-                           (erase-buffer))
            (save-excursion
-             (set-buffer (get-buffer-create "*gnus-uu-pre*"))
+             (set-buffer (gnus-get-buffer-create "*gnus-uu-body*"))
+             (erase-buffer))
+           (save-excursion
+             (set-buffer (gnus-get-buffer-create "*gnus-uu-pre*"))
              (erase-buffer)
              (insert (format
-                      "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n"
-                      (current-time-string) name name))))
+                      "Date: %s\nFrom: %s\nSubject: %s Digest\n\n"
+                      (current-time-string) name name))
+             (insert "Topics:\n")))
        (when (not (eq in-state 'end))
          (setq state (list 'middle))))
       (save-excursion
-       (set-buffer (get-buffer "*gnus-uu-body*"))
+       (set-buffer "*gnus-uu-body*")
        (goto-char (setq beg (point-max)))
        (save-excursion
          (save-restriction
@@ -855,16 +852,17 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
              (put-text-property (point-min) (point-max) 'intangible nil))
            (goto-char (point-min))
            (re-search-forward "\n\n")
-           ;; Quote all 30-dash lines.
-           (save-excursion
-             (while (re-search-forward "^-" nil t)
-               (beginning-of-line)
-               (delete-char 1)
-               (insert "- ")))
+           (unless gnus-uu-digest-buffer
+             ;; Quote all 30-dash lines.
+             (save-excursion
+               (while (re-search-forward "^-" nil t)
+                 (beginning-of-line)
+                 (delete-char 1)
+                 (insert "- "))))
            (setq body (buffer-substring (1- (point)) (point-max)))
            (narrow-to-region (point-min) (point))
            (if (not (setq headers gnus-uu-digest-headers))
-               (setq sorthead (buffer-substring (point-min) (point-max)))
+               (setq sorthead (buffer-string))
              (while headers
                (setq headline (car headers))
                (setq headers (cdr headers))
@@ -878,32 +876,52 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                                          (1- (point)))
                                     (progn (forward-line 1) (point)))))))))
            (widen)))
+       (insert message-forward-start-separator)
        (insert sorthead) (goto-char (point-max))
        (insert body) (goto-char (point-max))
-       (insert (concat "\n" (make-string 30 ?-) "\n\n"))
        (goto-char beg)
-       (when (re-search-forward "^Subject: \\(.*\\)$" nil t)
-         (setq subj (buffer-substring (match-beginning 1) (match-end 1)))
+       (when (re-search-forward "^Subject:" nil t)
+         (setq subj (nnheader-decode-subject
+                     (buffer-substring (match-end 0) (std11-field-end)))))
+       (when subj
          (save-excursion
-           (set-buffer (get-buffer "*gnus-uu-pre*"))
+           (set-buffer "*gnus-uu-pre*")
            (insert (format "   %s\n" subj)))))
       (when (or (eq in-state 'last)
                (eq in-state 'first-and-last))
-       (save-excursion
-         (set-buffer (get-buffer "*gnus-uu-pre*"))
-         (insert (format "\n\n%s\n\n" (make-string 70 ?-)))
-         (gnus-write-buffer gnus-uu-saved-article-name))
-       (save-excursion
-         (set-buffer (get-buffer "*gnus-uu-body*"))
-         (goto-char (point-max))
-         (insert
-          (concat (setq end-string (format "End of %s Digest" name))
-                  "\n"))
-         (insert (concat (make-string (length end-string) ?*) "\n"))
-         (write-region
-          (point-min) (point-max) gnus-uu-saved-article-name t))
-       (kill-buffer (get-buffer "*gnus-uu-pre*"))
-       (kill-buffer (get-buffer "*gnus-uu-body*"))
+       (if gnus-uu-digest-buffer
+           (with-current-buffer gnus-uu-digest-buffer
+             (erase-buffer)
+             (insert-buffer "*gnus-uu-pre*")
+             (goto-char (point-max))
+             (insert-buffer "*gnus-uu-body*"))
+         (save-excursion
+           (set-buffer "*gnus-uu-pre*")
+           (insert (format "\n\n%s\n\n" (make-string 70 ?-)))
+           (if gnus-uu-digest-buffer
+               (with-current-buffer gnus-uu-digest-buffer
+                 (erase-buffer)
+                 (insert-buffer "*gnus-uu-pre*"))
+             (gnus-write-buffer-as-coding-system
+              nnheader-text-coding-system gnus-uu-saved-article-name)))
+         (save-excursion
+           (set-buffer "*gnus-uu-body*")
+           (goto-char (point-max))
+           (insert
+            (concat (setq end-string (format "End of %s Digest" name))
+                    "\n"))
+           (insert (concat (make-string (length end-string) ?*) "\n"))
+           (if gnus-uu-digest-buffer
+               (with-current-buffer gnus-uu-digest-buffer
+                 (goto-char (point-max))
+                 (insert-buffer "*gnus-uu-body*"))
+             (let ((file-name-coding-system nnmail-pathname-coding-system)
+                   (pathname-coding-system nnmail-pathname-coding-system))
+               (write-region-as-coding-system
+                nnheader-text-coding-system
+                (point-min) (point-max) gnus-uu-saved-article-name t)))))
+       (gnus-kill-buffer "*gnus-uu-pre*")
+       (gnus-kill-buffer "*gnus-uu-body*")
        (push 'end state))
       (if (memq 'begin state)
          (cons gnus-uu-saved-article-name state)
@@ -935,7 +953,8 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        (if (looking-at gnus-uu-binhex-begin-line)
            (progn
              (setq state (list 'begin))
-             (write-region 1 1 gnus-uu-binhex-article-name))
+             (write-region (point-min) (point-min)
+                           gnus-uu-binhex-article-name))
          (setq state (list 'middle)))
        (goto-char (point-max))
        (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
@@ -948,7 +967,8 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        (beginning-of-line)
        (forward-line 1)
        (when (file-exists-p gnus-uu-binhex-article-name)
-         (append-to-file start-char (point) gnus-uu-binhex-article-name))))
+         (write-region-as-binary start-char (point)
+                                 gnus-uu-binhex-article-name 'append))))
     (if (memq 'begin state)
        (cons gnus-uu-binhex-article-name state)
       state)))
@@ -968,7 +988,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        (if (not (re-search-forward gnus-uu-postscript-end-string nil t))
            (setq state (list 'wrong-type))
          (setq end-char (point))
-         (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
+         (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
          (insert-buffer-substring process-buffer start-char end-char)
          (setq file-name (concat gnus-uu-work-dir
                                  (cdr gnus-article-current) ".ps"))
@@ -1018,45 +1038,36 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
 
 (defun gnus-uu-reginize-string (string)
   ;; Takes a string and puts a \ in front of every special character;
-  ;; ignores any leading "version numbers" thingies that they use in
-  ;; the comp.binaries groups, and either replaces anything that looks
-  ;; like "2/3" with "[0-9]+/[0-9]+" or, if it can't find something
-  ;; like that, replaces the last two numbers with "[0-9]+".  This, in
-  ;; my experience, should get most postings of a series.
-  (let ((count 2)
-       (vernum "v[0-9]+[a-z][0-9]+:")
-       beg)
-    (save-excursion
-      (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
-      (insert (regexp-quote string))
-      (setq beg 1)
+  ;; replaces the last thing that looks like "2/3" with "[0-9]+/3"
+  ;; or, if it can't find something like that, tries "2 of 3", then
+  ;; finally just replaces the next to last number with "[0-9]+".
+  (save-excursion
+    (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
+    (buffer-disable-undo)
+    (erase-buffer)
+    (insert (regexp-quote string))
 
-      (setq case-fold-search nil)
-      (goto-char (point-min))
-      (when (looking-at vernum)
-       (replace-match vernum t t)
-       (setq beg (length vernum)))
+    (setq case-fold-search nil)
 
-      (goto-char beg)
-      (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
-         (replace-match " [0-9]+/[0-9]+")
+    (end-of-line)
+    (if (re-search-backward "\\([^0-9]\\)[0-9]+/\\([0-9]+\\)" nil t)
+       (replace-match "\\1[0-9]+/\\2")
 
-       (goto-char beg)
-       (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
-           (replace-match "[0-9]+ of [0-9]+")
+      (end-of-line)
+      (if (re-search-backward "\\([^0-9]\\)[0-9]+[ \t]*of[ \t]*\\([0-9]+\\)"
+                             nil t)
+         (replace-match "\\1[0-9]+ of \\2")
 
-         (end-of-line)
-          (if (re-search-backward "\\([^0-9]\\)[0-9]+\\([^0-9]+\\)[0-9]+"
-                                  nil t)
-              (replace-match "\\1[0-9]+\\2[0-9]+" t nil nil nil))))
+       (end-of-line)
+       (if (re-search-backward "\\([^0-9]\\)[0-9]+\\([^0-9]+\\)[0-9]+"
+                               nil t)
+           (replace-match "\\1[0-9]+\\2[0-9]+" t nil nil nil))))
 
-      (goto-char beg)
-      (while (re-search-forward "[ \t]+" nil t)
-       (replace-match "[ \t]*" t t))
+    (goto-char 1)
+    (while (re-search-forward "[ \t]+" nil t)
+      (replace-match "[ \t]+" t t))
 
-      (buffer-substring 1 (point-max)))))
+    (buffer-string)))
 
 (defun gnus-uu-get-list-of-articles (n)
   ;; If N is non-nil, the article numbers of the N next articles
@@ -1096,8 +1107,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                     (gnus-uu-reginize-string (gnus-summary-article-subject))))
        list-of-subjects)
     (save-excursion
-      (if (not subject)
-         ()
+      (when subject
        ;; Collect all subjects matching subject.
        (let ((case-fold-search t)
              (data gnus-newsgroup-data)
@@ -1132,8 +1142,8 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
   (let ((out-list string-list)
        string)
     (save-excursion
-      (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
+      (buffer-disable-undo)
       (while string-list
        (erase-buffer)
        (insert (caar string-list))
@@ -1149,10 +1159,11 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        ;; Expand numbers.
        (goto-char (point-min))
        (while (re-search-forward "[0-9]+" nil t)
-         (replace-match
-          (format "%06d"
-                  (string-to-int (buffer-substring
-                                  (match-beginning 0) (match-end 0))))))
+         (ignore-errors
+           (replace-match
+            (format "%06d"
+                    (string-to-int (buffer-substring
+                                    (match-beginning 0) (match-end 0)))))))
        (setq string (buffer-substring 1 (point-max)))
        (setcar (car string-list) string)
        (setq string-list (cdr string-list))))
@@ -1208,9 +1219,10 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                                       &optional sloppy limit no-errors)
   (let ((state 'first)
        (gnus-asynchronous nil)
+       (gnus-inhibit-treatment t)
        has-been-begin article result-file result-files process-state
        gnus-summary-display-article-function
-       gnus-article-display-hook gnus-article-prepare-hook
+       gnus-article-prepare-hook gnus-display-mime-function
        article-series files)
 
     (while (and articles
@@ -1219,105 +1231,107 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                    (not (memq 'end process-state))))
 
       (setq article (pop articles))
-      (push article article-series)
+      (when (vectorp (gnus-summary-article-header article))
+       (push article article-series)
 
-      (unless articles
-       (if (eq state 'first)
-           (setq state 'first-and-last)
-         (setq state 'last)))
+       (unless articles
+         (if (eq state 'first)
+             (setq state 'first-and-last)
+           (setq state 'last)))
 
-      (let ((part (gnus-uu-part-number article)))
-       (gnus-message 6 "Getting article %d%s..."
-                     article (if (string= part "") "" (concat ", " part))))
-      (gnus-summary-display-article article)
+       (let ((part (gnus-uu-part-number article)))
+         (gnus-message 6 "Getting article %d%s..."
+                       article (if (string= part "") "" (concat ", " part))))
+       (gnus-summary-display-article article)
 
-      ;; Push the article to the processing function.
-      (save-excursion
-       (set-buffer gnus-original-article-buffer)
-       (let ((buffer-read-only nil))
-         (save-excursion
-           (set-buffer gnus-summary-buffer)
-           (setq process-state
-                 (funcall process-function
-                          gnus-original-article-buffer state)))))
-
-      (gnus-summary-remove-process-mark article)
-
-      ;; If this is the beginning of a decoded file, we push it
-      ;; on to a list.
-      (when (or (memq 'begin process-state)
-               (and (or (eq state 'first)
-                        (eq state 'first-and-last))
-                    (memq 'ok process-state)))
-       (when has-been-begin
-         ;; If there is a `result-file' here, that means that the
-         ;; file was unsuccessfully decoded, so we delete it.
-         (when (and result-file
-                    (file-exists-p result-file)
-                    (not gnus-uu-be-dangerous)
-                    (or (eq gnus-uu-be-dangerous t)
-                        (gnus-y-or-n-p
-                         (format "Delete unsuccessfully decoded file %s"
-                                 result-file))))
-           (delete-file result-file)))
-       (when (memq 'begin process-state)
-         (setq result-file (car process-state)))
-       (setq has-been-begin t))
-
-      ;; Check whether we have decoded one complete file.
-      (when (memq 'end process-state)
-       (setq article-series nil)
-       (setq has-been-begin nil)
-       (if (stringp result-file)
-           (setq files (list result-file))
-         (setq files result-file))
-       (setq result-file (car files))
-       (while files
-         (push (list (cons 'name (pop files))
-                     (cons 'article article))
-               result-files))
-       ;; Allow user-defined functions to be run on this file.
-       (when gnus-uu-grabbed-file-functions
-         (let ((funcs gnus-uu-grabbed-file-functions))
-           (unless (listp funcs)
-             (setq funcs (list funcs)))
-           (while funcs
-             (funcall (pop funcs) result-file))))
-       (setq result-file nil)
-       ;; Check whether we have decoded enough articles.
-       (and limit (= (length result-files) limit)
-            (setq articles nil)))
-
-      ;; If this is the last article to be decoded, and
-      ;; we still haven't reached the end, then we delete
-      ;; the partially decoded file.
-      (and (or (eq state 'last) (eq state 'first-and-last))
-          (not (memq 'end process-state))
-          result-file
-          (file-exists-p result-file)
-          (not gnus-uu-be-dangerous)
-          (or (eq gnus-uu-be-dangerous t)
-              (gnus-y-or-n-p (format "Delete incomplete file %s? " result-file)))
-          (delete-file result-file))
-
-      ;; If this was a file of the wrong sort, then
-      (when (and (or (memq 'wrong-type process-state)
-                    (memq 'error process-state))
-                gnus-uu-unmark-articles-not-decoded)
-       (gnus-summary-tick-article article t))
-
-      ;; Set the new series state.
-      (if (and (not has-been-begin)
-              (not sloppy)
-              (or (memq 'end process-state)
-                  (memq 'middle process-state)))
-         (progn
-           (setq process-state (list 'error))
-           (gnus-message 2 "No begin part at the beginning")
-           (sleep-for 2))
-       (setq state 'middle)))
-
-    ;; When there are no result-files, then something must be wrong.
+       ;; Push the article to the processing function.
+       (save-excursion
+         (set-buffer gnus-original-article-buffer)
+         (let ((buffer-read-only nil))
+           (save-excursion
+             (set-buffer gnus-summary-buffer)
+             (setq process-state
+                   (funcall process-function
+                            gnus-original-article-buffer state)))))
+
+       (gnus-summary-remove-process-mark article)
+
+       ;; If this is the beginning of a decoded file, we push it
+       ;; on to a list.
+       (when (or (memq 'begin process-state)
+                 (and (or (eq state 'first)
+                          (eq state 'first-and-last))
+                      (memq 'ok process-state)))
+         (when has-been-begin
+           ;; If there is a `result-file' here, that means that the
+           ;; file was unsuccessfully decoded, so we delete it.
+           (when (and result-file
+                      (file-exists-p result-file)
+                      (not gnus-uu-be-dangerous)
+                      (or (eq gnus-uu-be-dangerous t)
+                          (gnus-y-or-n-p
+                           (format "Delete unsuccessfully decoded file %s"
+                                   result-file))))
+             (delete-file result-file)))
+         (when (memq 'begin process-state)
+           (setq result-file (car process-state)))
+         (setq has-been-begin t))
+
+       ;; Check whether we have decoded one complete file.
+       (when (memq 'end process-state)
+         (setq article-series nil)
+         (setq has-been-begin nil)
+         (if (stringp result-file)
+             (setq files (list result-file))
+           (setq files result-file))
+         (setq result-file (car files))
+         (while files
+           (push (list (cons 'name (pop files))
+                       (cons 'article article))
+                 result-files))
+         ;; Allow user-defined functions to be run on this file.
+         (when gnus-uu-grabbed-file-functions
+           (let ((funcs gnus-uu-grabbed-file-functions))
+             (unless (listp funcs)
+               (setq funcs (list funcs)))
+             (while funcs
+               (funcall (pop funcs) result-file))))
+         (setq result-file nil)
+         ;; Check whether we have decoded enough articles.
+         (and limit (= (length result-files) limit)
+              (setq articles nil)))
+
+       ;; If this is the last article to be decoded, and
+       ;; we still haven't reached the end, then we delete
+       ;; the partially decoded file.
+       (and (or (eq state 'last) (eq state 'first-and-last))
+            (not (memq 'end process-state))
+            result-file
+            (file-exists-p result-file)
+            (not gnus-uu-be-dangerous)
+            (or (eq gnus-uu-be-dangerous t)
+                (gnus-y-or-n-p
+                 (format "Delete incomplete file %s? " result-file)))
+            (delete-file result-file))
+
+       ;; If this was a file of the wrong sort, then
+       (when (and (or (memq 'wrong-type process-state)
+                      (memq 'error process-state))
+                  gnus-uu-unmark-articles-not-decoded)
+         (gnus-summary-tick-article article t))
+
+       ;; Set the new series state.
+       (if (and (not has-been-begin)
+                (not sloppy)
+                (or (memq 'end process-state)
+                    (memq 'middle process-state)))
+           (progn
+             (setq process-state (list 'error))
+             (gnus-message 2 "No begin part at the beginning")
+             (sleep-for 2))
+         (setq state 'middle))))
+    
+      ;; When there are no result-files, then something must be wrong.
     (if result-files
        (message "")
       (cond
@@ -1333,6 +1347,9 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
        (while article-series
          (gnus-summary-tick-article (pop article-series) t))))
 
+    ;; The original article buffer is hosed, shoot it down.
+    (gnus-kill-buffer gnus-original-article-buffer)
+    (setq gnus-current-article nil)
     result-files))
 
 (defun gnus-uu-grab-view (file)
@@ -1349,17 +1366,27 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
   (when gnus-uu-default-dir
     (let ((to-file (concat (file-name-as-directory gnus-uu-default-dir)
                           (file-name-nondirectory file))))
-      (rename-file file to-file)
-      (unless (file-exists-p file)
-       (make-symbolic-link to-file file)))))
+      (cond ((fboundp 'make-symbolic-link)
+            (rename-file file to-file)
+            (unless (file-exists-p file)
+              (make-symbolic-link to-file file)))
+           (t
+            (copy-file file to-file))))))
 
 (defun gnus-uu-part-number (article)
   (let* ((header (gnus-summary-article-header article))
-        (subject (and header (mail-header-subject header))))
-    (if (and subject
-            (string-match "[0-9]+ */[0-9]+\\|[0-9]+ * of *[0-9]+" subject))
-       (match-string 0 subject)
-      "")))
+        (subject (and header (mail-header-subject header)))
+        (part nil))
+    (if subject
+       (while (string-match "[0-9]+/[0-9]+\\|[0-9]+[ \t]+of[ \t]+[0-9]+"
+                            subject)
+         (setq part (match-string 0 subject))
+         (setq subject (substring subject (match-end 0)))))
+    (or part
+       (while (string-match "\\([0-9]+\\)[^0-9]+\\([0-9]+\\)" subject)
+         (setq part (match-string 0 subject))
+         (setq subject (substring subject (match-end 0)))))
+    (or part "")))
 
 (defun gnus-uu-uudecode-sentinel (process event)
   (delete-process (get-process process)))
@@ -1392,9 +1419,9 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
          ;; We replace certain characters that could make things messy.
          (setq gnus-uu-file-name
                (let ((nnheader-file-name-translation-alist
-                      '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_))))
+                      '((?/ . ?,) (?  . ?_) (?* . ?_) (?$ . ?_))))
                  (nnheader-translate-file-chars (match-string 1))))
-          (replace-match (concat "begin 644 " gnus-uu-file-name) t t)
+         (replace-match (concat "begin 644 " gnus-uu-file-name) t t)
 
          ;; Remove any non gnus-uu-body-line right after start.
          (forward-line 1)
@@ -1417,7 +1444,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                  (setq gnus-uu-uudecode-process
                        (start-process
                         "*uudecode*"
-                        (get-buffer-create gnus-uu-output-buffer-name)
+                        (gnus-get-buffer-create gnus-uu-output-buffer-name)
                         shell-file-name shell-command-switch
                         (format "cd %s %s uudecode" gnus-uu-work-dir
                                 gnus-shell-command-separator))))
@@ -1469,6 +1496,21 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
          (cons (if (= (length files) 1) (car files) files) state)
        state))))
 
+(defvar gnus-uu-unshar-warning
+  "*** WARNING ***
+
+Shell archives are an archaic method of bundling files for distribution
+across computer networks.  During the unpacking process, arbitrary commands
+are executed on your system, and all kinds of nasty things can happen.
+Please examine the archive very carefully before you instruct Emacs to
+unpack it.  You can browse the archive buffer using \\[scroll-other-window].
+
+If you are unsure what to do, please answer \"no\"."
+  "Text of warning message displayed by `gnus-uu-unshar-article'.
+Make sure that this text consists only of few text lines.  Otherwise,
+Gnus might fail to display all of it.")
+
+
 ;; This function is used by `gnus-uu-grab-articles' to treat
 ;; a shared article.
 (defun gnus-uu-unshar-article (process-buffer in-state)
@@ -1479,14 +1521,31 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
       (goto-char (point-min))
       (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
          (setq state (list 'wrong-type))
-       (beginning-of-line)
-       (setq start-char (point))
-       (call-process-region
-        start-char (point-max) shell-file-name nil
-        (get-buffer-create gnus-uu-output-buffer-name) nil
-        shell-command-switch
-        (concat "cd " gnus-uu-work-dir " "
-                gnus-shell-command-separator  " sh"))))
+       (save-window-excursion
+         (save-excursion
+           (switch-to-buffer (current-buffer))
+           (delete-other-windows)
+           (let ((buffer (get-buffer-create (generate-new-buffer-name
+                                             "*Warning*"))))
+             (unless
+                 (unwind-protect
+                     (with-current-buffer buffer
+                       (insert (substitute-command-keys
+                                gnus-uu-unshar-warning))
+                       (goto-char (point-min))
+                       (display-buffer buffer)
+                       (yes-or-no-p "This is a shell archive, unshar it? "))
+                   (kill-buffer buffer))
+               (setq state (list 'error))))))
+       (unless (memq 'error state)
+         (beginning-of-line)
+         (setq start-char (point))
+         (call-process-region
+          start-char (point-max) shell-file-name nil
+          (gnus-get-buffer-create gnus-uu-output-buffer-name) nil
+          shell-command-switch
+          (concat "cd " gnus-uu-work-dir " "
+                  gnus-shell-command-separator  " sh")))))
     state))
 
 ;; Returns the name of what the shar file is going to unpack.
@@ -1546,13 +1605,13 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
     (setq command (format "cd %s ; %s" dir (gnus-uu-command action file-path)))
 
     (save-excursion
-      (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
+      (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name))
       (erase-buffer))
 
     (gnus-message 5 "Unpacking: %s..." (gnus-uu-command action file-path))
 
-    (if (= 0 (call-process shell-file-name nil
-                          (get-buffer-create gnus-uu-output-buffer-name)
+    (if (eq 0 (call-process shell-file-name nil
+                          (gnus-get-buffer-create gnus-uu-output-buffer-name)
                           nil shell-command-switch command))
        (message "")
       (gnus-message 2 "Error during unpacking of archive")
@@ -1676,8 +1735,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
                 gnus-uu-tmp-dir)))
 
       (setq gnus-uu-work-dir
-           (make-temp-name (concat gnus-uu-tmp-dir "gnus")))
-      (gnus-make-directory gnus-uu-work-dir)
+           (mm-make-temp-file (concat gnus-uu-tmp-dir "gnus") 'dir))
       (set-file-modes gnus-uu-work-dir 448)
       (setq gnus-uu-work-dir (file-name-as-directory gnus-uu-work-dir))
       (push (cons gnus-newsgroup-name gnus-uu-work-dir)
@@ -1703,7 +1761,7 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
       (push (list (aref arg new-pos)) accum)
       (setq pos (1+ new-pos)))
     (if (= pos 0)
-        arg
+       arg
       (apply 'concat (nconc (nreverse accum) (list (substring arg pos)))))))
 
 ;; Inputs an action and a filename and returns a full command, making sure
@@ -1729,9 +1787,13 @@ didn't work, and overwrite existing files.  Otherwise, ask each time."
          (if (file-directory-p file)
              (gnus-uu-delete-work-dir file)
            (gnus-message 9 "Deleting file %s..." file)
-           (delete-file file))))
-      (delete-directory dir)))
-  (gnus-message 7 ""))
+            (condition-case err
+                (delete-file file)
+              (error (gnus-message 3 "Deleting file %s failed... %s" file err))))))
+      (condition-case err
+          (delete-directory dir)
+        (error (gnus-message 3 "Deleting directory %s failed... %s" file err))))
+    (gnus-message 7 "")))
 
 ;; Initializing
 
@@ -1806,8 +1868,10 @@ is t."
 
   (gnus-summary-post-news)
 
-  (use-local-map (copy-keymap (current-local-map)))
-  (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done)
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map (current-local-map))
+    (use-local-map map))
+  ;;(local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done)
   (local-set-key "\C-c\C-c" 'gnus-uu-post-news-inews)
   (local-set-key "\C-c\C-s" 'gnus-uu-post-news-inews)
   (local-set-key "\C-c\C-i" 'gnus-uu-post-insert-binary-in-article)
@@ -1840,8 +1904,8 @@ The user will be asked for a file name."
 
 ;; Encodes with base64 and adds MIME headers
 (defun gnus-uu-post-encode-mime (path file-name)
-  (when (zerop (call-process shell-file-name nil t nil shell-command-switch
-                            (format "%s %s -o %s" "mmencode" path file-name)))
+  (when (eq 0 (call-process shell-file-name nil t nil shell-command-switch
+                           (format "%s %s -o %s" "mmencode" path file-name)))
     (gnus-uu-post-make-mime file-name "base64")
     t))
 
@@ -1857,7 +1921,7 @@ The user will be asked for a file name."
     (goto-char (point-min))
     (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
     (forward-line -1)
-    (narrow-to-region 1 (point))
+    (narrow-to-region (point-min) (point))
     (unless (mail-fetch-field "mime-version")
       (widen)
       (insert "MIME-Version: 1.0\n"))
@@ -1866,8 +1930,8 @@ The user will be asked for a file name."
 ;; Encodes a file PATH with COMMAND, leaving the result in the
 ;; current buffer.
 (defun gnus-uu-post-encode-file (command path file-name)
-  (= 0 (call-process shell-file-name nil t nil shell-command-switch
-                    (format "%s %s %s" command path file-name))))
+  (eq 0 (call-process shell-file-name nil t nil shell-command-switch
+                     (format "%s %s %s" command path file-name))))
 
 (defun gnus-uu-post-news-inews ()
   "Posts the composed news article and encoded file.
@@ -1899,8 +1963,10 @@ If no file has been included, the user will be asked for a file."
     (goto-char (point-max))
     (insert (format "\n%s\n" gnus-uu-post-binary-separator))
 
+    ;; #### Unix-specific?
     (when (string-match "^~/" file-path)
       (setq file-path (concat "$HOME" (substring file-path 1))))
+    ;; #### Unix-specific?
     (if (string-match "/[^/]*$" file-path)
        (setq file-name (substring file-path (1+ (match-beginning 0))))
       (setq file-name file-path))
@@ -1908,7 +1974,7 @@ If no file has been included, the user will be asked for a file."
     (unwind-protect
        (if (save-excursion
              (set-buffer (setq uubuf
-                               (get-buffer-create uuencode-buffer-name)))
+                               (gnus-get-buffer-create uuencode-buffer-name)))
              (erase-buffer)
              (funcall gnus-uu-post-encode-method file-path file-name))
            (insert-buffer-substring uubuf)
@@ -1923,7 +1989,7 @@ If no file has been included, the user will be asked for a file."
        (top-string "[ cut here %s (%s %d/%d) %s gnus-uu ]")
        (separator (concat mail-header-separator "\n\n"))
        uubuf length parts header i end beg
-       beg-line minlen buf post-buf whole-len beg-binary end-binary)
+       beg-line minlen post-buf whole-len beg-binary end-binary)
 
     (setq post-buf (current-buffer))
 
@@ -1941,11 +2007,11 @@ If no file has been included, the user will be asked for a file."
     (setq end-binary (point-max))
 
     (save-excursion
-      (set-buffer (setq uubuf (get-buffer-create encoded-buffer-name)))
+      (set-buffer (setq uubuf (gnus-get-buffer-create encoded-buffer-name)))
       (erase-buffer)
       (insert-buffer-substring post-buf beg-binary end-binary)
       (goto-char (point-min))
-      (setq length (count-lines 1 (point-max)))
+      (setq length (count-lines (point-min) (point-max)))
       (setq parts (/ length gnus-uu-post-length))
       (unless (< (% length gnus-uu-post-length) 4)
        (incf parts)))
@@ -1958,7 +2024,7 @@ If no file has been included, the user will be asked for a file."
     (re-search-forward
      (concat "^" (regexp-quote mail-header-separator) "$") nil t)
     (beginning-of-line)
-    (setq header (buffer-substring 1 (point)))
+    (setq header (buffer-substring (point-min) (point)))
 
     (goto-char (point-min))
     (when gnus-uu-post-separate-description
@@ -1973,7 +2039,7 @@ If no file has been included, the user will be asked for a file."
       (setq i 1)
       (setq beg 1)
       (while (not (> i parts))
-       (set-buffer (get-buffer-create send-buffer-name))
+       (set-buffer (gnus-get-buffer-create send-buffer-name))
        (erase-buffer)
        (insert header)
        (when (and threaded gnus-uu-post-message-id)
@@ -2039,4 +2105,4 @@ If no file has been included, the user will be asked for a file."
 
 (provide 'gnus-uu)
 
-;; gnus-uu.el ends here
+;;; gnus-uu.el ends here
diff --git a/lisp/gnus-vers.el b/lisp/gnus-vers.el
new file mode 100644 (file)
index 0000000..0f64bfe
--- /dev/null
@@ -0,0 +1,88 @@
+;;; gnus-vers.el --- Declare gnus version
+
+;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Keiichi Suzuki <keiichi@nanap.org>
+;;         Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: news, mail, compatibility
+
+;; This file is part of T-gnus.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(require 'poe)
+(require 'product)
+(provide 'gnus-vers)
+
+(defconst gnus-revision-number "00"
+  "Revision number for this version of gnus.")
+
+;; Product information of this gnus.
+(product-provide 'gnus-vers
+  (product-define "T-gnus" nil
+                 (list 6 16 6
+                       (string-to-number gnus-revision-number))))
+
+(defconst gnus-original-version-number "5.10.6"
+  "Version number for this version of Gnus.")
+
+(provide 'running-pterodactyl-gnus-0_73-or-later)
+
+(defconst gnus-original-product-name "Gnus"
+  "Product name of the original version of Gnus.")
+
+(defconst gnus-product-name (product-name (product-find 'gnus-vers))
+  "Product name of this version of gnus.")
+
+(defconst gnus-version-number
+  (mapconcat
+   'number-to-string
+   (butlast (product-version (product-find 'gnus-vers)))
+   ".")
+  "Version number for this version of gnus.")
+
+(defconst gnus-version
+  (format "%s %s r%s (based on %s v%s ; for SEMI 1.14 FLIM 1.14)"
+         gnus-product-name gnus-version-number gnus-revision-number
+         gnus-original-product-name gnus-original-version-number)
+  "Version string for this version of gnus.")
+
+(defun gnus-version (&optional arg)
+  "Version number of this version of Gnus.
+If ARG, insert string at point."
+  (interactive "P")
+  (if arg
+      (insert (message "%s" gnus-version))
+    (message "%s" gnus-version)))
+
+(defun gnus-extended-version ()
+  "Stringified gnus version."
+  (concat gnus-product-name "/" gnus-version-number
+         " (based on "
+         gnus-original-product-name " v" gnus-original-version-number ")"
+         (if (zerop (string-to-number gnus-revision-number))
+             ""
+           (concat " (revision " gnus-revision-number ")"))
+         ))
+
+;; gnus-vers.el ends here
index bbefaac..2737151 100644 (file)
@@ -1,7 +1,10 @@
 ;;; gnus-vm.el --- vm interface for Gnus
-;; Copyright (C) 1994,95,96,97,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+;;     Free Software Foundation, Inc.
 
 ;; Author: Per Persson <pp@gnu.ai.mit.edu>
+;;         Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
-(require 'sendmail)
-(require 'message)
-(require 'gnus)
-(require 'gnus-msg)
+(eval-when-compile (require 'cl))
+
+(require 'gnus-art)
 
 (eval-when-compile
   (autoload 'vm-mode "vm")
-  (autoload 'vm-save-message "vm")
-  (autoload 'vm-forward-message "vm")
-  (autoload 'vm-reply "vm")
-  (autoload 'vm-mail "vm"))
-
-(defvar gnus-vm-inhibit-window-system nil
-  "Inhibit loading `win-vm' if using a window-system.
-Has to be set before gnus-vm is loaded.")
-
-(or gnus-vm-inhibit-window-system
-    (condition-case nil
-       (when window-system
-         (require 'win-vm))
-      (error nil)))
+  (autoload 'vm-read-file-name "vm")
+  (autoload 'vm-save-message "vm"))
 
 (when (not (featurep 'vm))
   (load "vm"))
 
+(defvar vm-folder-directory)
+(defvar vm-folder-history)
+(defvar vm-primary-inbox)
+(defvar vm-use-toolbar)
+
 (defun gnus-vm-make-folder (&optional buffer)
   (let ((article (or buffer (current-buffer)))
        (tmp-folder (generate-new-buffer " *tmp-folder*"))
@@ -72,34 +67,101 @@ Has to be set before gnus-vm is loaded.")
     ;; insert a newline, otherwise the last line gets lost
     (goto-char (point-max))
     (insert "\n")
-    (vm-mode)
+    (let (mime-display-header-hook
+         mime-display-text/plain-hook mime-text-decode-hook
+         mime-view-define-keymap-hook mime-view-mode-hook)
+      (vm-mode))
     tmp-folder))
 
-(defun gnus-summary-save-article-vm (&optional arg)
+(defvar gnus-summary-save-article-vm-folder nil)
+(defvar gnus-summary-save-article-vm-count nil)
+
+(defun gnus-summary-save-article-vm (&optional arg folder)
   "Append the current article to a vm folder.
 If N is a positive number, save the N next articles.
 If N is a negative number, save the N previous articles.
 If N is nil and any articles have been marked with the process mark,
 save those articles instead."
-  (interactive "P")
-  (let ((gnus-default-article-saver 'gnus-summary-save-in-vm))
-    (gnus-summary-save-article arg)))
+  (interactive
+   (let ((prefix-arg current-prefix-arg)
+        articles marks default-folder)
+     (setq default-folder (or (car vm-folder-history) vm-primary-inbox))
+     (if (numberp prefix-arg)
+        (setq articles prefix-arg)
+       (setq marks (delq nil (gnus-summary-work-articles nil))
+            articles (length marks)))
+     (list
+      prefix-arg
+      (unless (zerop articles)
+       (vm-read-file-name
+        (format
+         "Save %s in VM folder: "
+         (cond ((eq 1 articles)
+                (if (or (not marks) (eq gnus-current-article (car marks)))
+                    "this article"
+                  "the marked article"))
+               ((< 0 articles)
+                (if marks
+                    (format "the marked %d articles" articles)
+                  (format "the %d next articles" articles)))
+               ((> 0 articles)
+                (format "the %d previous articles" (- articles)))))
+        (if default-folder "" vm-folder-directory)
+        nil nil default-folder 'vm-folder-history)))))
+  (if (interactive-p)
+      (unless folder
+       (error "No articles to be saved"))
+    (unless (setq folder (or folder gnus-summary-save-article-vm-folder))
+      (error "No VM folder is specified")))
+  (unwind-protect
+      (progn
+       (setq gnus-summary-save-article-vm-folder folder
+             gnus-summary-save-article-vm-count 0)
+       (let ((gnus-default-article-saver 'gnus-summary-save-in-vm)
+             mime-display-header-hook mime-display-text/plain-hook
+             mime-text-decode-hook mime-view-define-keymap-hook
+             mime-view-mode-hook)
+         (gnus-summary-save-article arg))
+       (cond ((eq 1 gnus-summary-save-article-vm-count)
+              (message "One article is saved in %s" folder))
+             ((< 0 gnus-summary-save-article-vm-count)
+              (message "%d articles are saved in %s"
+                       gnus-summary-save-article-vm-count folder))
+             (t
+              (message "Maybe no articles are saved in %s" folder))))
+    (setq gnus-summary-save-article-vm-folder nil
+         gnus-summary-save-article-vm-count nil)))
 
 (defun gnus-summary-save-in-vm (&optional folder)
-  (interactive)
-  (setq folder
-       (gnus-read-save-file-name
-        "Save %s in VM folder:" folder
-        gnus-mail-save-name gnus-newsgroup-name
-        gnus-current-headers 'gnus-newsgroup-last-mail))
-  (gnus-eval-in-buffer-window gnus-original-article-buffer
-    (save-excursion
-      (save-restriction
-       (widen)
-       (let ((vm-folder (gnus-vm-make-folder)))
-         (vm-save-message folder)
-         (kill-buffer vm-folder))))))
+  (interactive
+   (let (default-folder)
+     (setq default-folder (or (car vm-folder-history) vm-primary-inbox))
+     (list (vm-read-file-name "Save this article in VM folder: "
+                             (if default-folder "" vm-folder-directory)
+                             nil nil default-folder 'vm-folder-history))))
+  (unless (interactive-p)
+    (setq folder (or folder gnus-summary-save-article-vm-folder)))
+  (unless folder
+    (error "No VM folder is specified"))
+  (unless (interactive-p)
+    (message "Saving the article %d in %s..." gnus-current-article folder)
+    (when (numberp gnus-summary-save-article-vm-count)
+      (incf gnus-summary-save-article-vm-count)))
+  (save-window-excursion
+    (apply 'gnus-summary-select-article gnus-show-all-headers
+          (unless (interactive-p)
+            (list nil nil gnus-current-article)))
+    (gnus-eval-in-buffer-window gnus-original-article-buffer
+      (save-excursion
+       (save-restriction
+         (widen)
+         (let* ((vm-use-toolbar nil)
+                (vm-folder (gnus-vm-make-folder)))
+           (vm-save-message folder)
+           (when (interactive-p)
+             (message "This article is saved in %s" folder))
+           (kill-buffer vm-folder)))))))
 
 (provide 'gnus-vm)
 
-;;; gnus-vm.el ends here.
+;;; gnus-vm.el ends here
index e6a2037..0d578d7 100644 (file)
@@ -1,7 +1,8 @@
 ;;; gnus-win.el --- window configuration functions for Gnus
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -28,6 +29,7 @@
 (eval-when-compile (require 'cl))
 
 (require 'gnus)
+(require 'gnus-util)
 
 (defgroup gnus-windows nil
   "Window configuration."
   :group 'gnus-windows
   :type 'boolean)
 
+(defcustom gnus-use-frames-on-any-display nil
+  "*If non-nil, frames on all displays will be considered useable by Gnus.
+When nil, only frames on the same display as the selected frame will be
+used to display Gnus windows."
+  :group 'gnus-windows
+  :type 'boolean)
+
 (defvar gnus-buffer-configuration
   '((group
      (vertical 1.0
               (if gnus-carpal '(summary-carpal 4))))
     (article
      (cond
-      ((and gnus-use-picons
-           (eq gnus-picons-display-where 'picons))
-       '(frame 1.0
-              (vertical 1.0
-                        (summary 0.25 point)
-                        (if gnus-carpal '(summary-carpal 4))
-                        (article 1.0))
-              (vertical ((height . 5) (width . 15)
-                         (user-position . t)
-                         (left . -1) (top . 1))
-                        (picons 1.0))))
       (gnus-use-trees
        '(vertical 1.0
                  (summary 0.25 point)
@@ -85,9 +83,9 @@
                  (article 1.0)))
       (t
        '(vertical 1.0
-                (summary 0.25 point)
-                (if gnus-carpal '(summary-carpal 4))
-                (article 1.0)))))
+                 (summary 0.25 point)
+                 (if gnus-carpal '(summary-carpal 4))
+                 (article 1.0)))))
     (server
      (vertical 1.0
               (server 1.0 point)
               (post 1.0 point)))
     (reply
      (vertical 1.0
-              (article-copy 0.5)
+              (article 0.5)
               (message 1.0 point)))
     (forward
      (vertical 1.0
               ("*Shell Command Output*" 1.0)))
     (bug
      (vertical 1.0
-              ("*Gnus Help Bug*" 0.5)
+              (if gnus-bug-create-help-buffer '("*Gnus Help Bug*" 0.5))
               ("*Gnus Bug*" 1.0 point)))
     (score-trace
      (vertical 1.0
      (vertical 1.0
               (summary 0.5 point)
               ("*Score Words*" 1.0)))
+    (split-trace
+     (vertical 1.0
+              (summary 0.5 point)
+              ("*Split Trace*" 1.0)))
     (category
      (vertical 1.0
               (category 1.0)))
     (compose-bounce
      (vertical 1.0
               (article 0.5)
-              (message 1.0 point))))
+              (message 1.0 point)))
+    (display-term
+     (vertical 1.0
+              ("*display*" 1.0))))
   "Window configuration for all possible Gnus buffers.
 See the Gnus manual for an explanation of the syntax used.")
 
@@ -182,21 +187,27 @@ See the Gnus manual for an explanation of the syntax used.")
     (mail . gnus-message-buffer)
     (post-news . gnus-message-buffer)
     (faq . gnus-faq-buffer)
-    (picons . "*Picons*")
     (tree . gnus-tree-buffer)
     (score-trace . "*Score Trace*")
+    (split-trace . "*Split Trace*")
     (info . gnus-info-buffer)
     (category . gnus-category-buffer)
     (article-copy . gnus-article-copy)
     (draft . gnus-draft-buffer))
   "Mapping from short symbols to buffer names or buffer variables.")
 
+(defcustom gnus-configure-windows-hook nil
+  "*A hook called when configuring windows."
+  :group 'gnus-windows
+  :type 'hook)
+
 ;;; Internal variables.
 
 (defvar gnus-current-window-configuration nil
   "The most recently set window configuration.")
 
 (defvar gnus-created-frames nil)
+(defvar gnus-window-frame-focus nil)
 
 (defun gnus-kill-gnus-frames ()
   "Kill all frames Gnus has created."
@@ -267,185 +278,201 @@ See the Gnus manual for an explanation of the syntax used.")
 
 (defvar gnus-frame-list nil)
 
+(defun gnus-window-to-buffer-helper (obj)
+  (cond ((not (symbolp obj))
+        obj)
+       ((boundp obj)
+        (symbol-value obj))
+       ((fboundp obj)
+        (funcall obj))
+       (t
+        nil)))
+
 (defun gnus-configure-frame (split &optional window)
   "Split WINDOW according to SPLIT."
-  (unless window
-    (setq window (get-buffer-window (current-buffer))))
-  (select-window window)
-  ;; This might be an old-stylee buffer config.
-  (when (vectorp split)
-    (setq split (append split nil)))
-  (when (or (consp (car split))
-           (vectorp (car split)))
-    (push 1.0 split)
-    (push 'vertical split))
-  ;; The SPLIT might be something that is to be evaled to
-  ;; return a new SPLIT.
-  (while (and (not (assq (car split) gnus-window-to-buffer))
-             (gnus-functionp (car split)))
-    (setq split (eval split)))
-  (let* ((type (car split))
-        (subs (cddr split))
-        (len (if (eq type 'horizontal) (window-width) (window-height)))
-        (total 0)
-        (window-min-width (or gnus-window-min-width window-min-width))
-        (window-min-height (or gnus-window-min-height window-min-height))
-        s result new-win rest comp-subs size sub)
-    (cond
-     ;; Nothing to do here.
-     ((null split))
-     ;; Don't switch buffers.
-     ((null type)
-      (and (memq 'point split) window))
-     ;; This is a buffer to be selected.
-     ((not (memq type '(frame horizontal vertical)))
-      (let ((buffer (cond ((stringp type) type)
-                         (t (cdr (assq type gnus-window-to-buffer)))))
-           buf)
-       (unless buffer
-         (error "Illegal buffer type: %s" type))
-       (unless (setq buf (get-buffer (if (symbolp buffer)
-                                         (symbol-value buffer) buffer)))
-         (setq buf (get-buffer-create (if (symbolp buffer)
-                                          (symbol-value buffer) buffer))))
-       (switch-to-buffer buf)
-       ;; We return the window if it has the `point' spec.
-       (and (memq 'point split) window)))
-     ;; This is a frame split.
-     ((eq type 'frame)
-      (unless gnus-frame-list
-       (setq gnus-frame-list (list (window-frame
-                                    (get-buffer-window (current-buffer))))))
-      (let ((i 0)
-           params frame fresult)
-       (while (< i (length subs))
-         ;; Frame parameter is gotten from the sub-split.
-         (setq params (cadr (elt subs i)))
-         ;; It should be a list.
-         (unless (listp params)
-           (setq params nil))
-         ;; Create a new frame?
-         (unless (setq frame (elt gnus-frame-list i))
-           (nconc gnus-frame-list (list (setq frame (make-frame params))))
-           (push frame gnus-created-frames))
-         ;; Is the old frame still alive?
-         (unless (frame-live-p frame)
-           (setcar (nthcdr i gnus-frame-list)
-                   (setq frame (make-frame params))))
-         ;; Select the frame in question and do more splits there.
-         (select-frame frame)
-         (setq fresult (or (gnus-configure-frame (elt subs i)) fresult))
-         (incf i))
-       ;; Select the frame that has the selected buffer.
-       (when fresult
-         (select-frame (window-frame fresult)))))
-     ;; This is a normal split.
-     (t
-      (when (> (length subs) 0)
-       ;; First we have to compute the sizes of all new windows.
-       (while subs
-         (setq sub (append (pop subs) nil))
-         (while (and (not (assq (car sub) gnus-window-to-buffer))
-                     (gnus-functionp (car sub)))
-           (setq sub (eval sub)))
-         (when sub
-           (push sub comp-subs)
-           (setq size (cadar comp-subs))
-           (cond ((equal size 1.0)
-                  (setq rest (car comp-subs))
-                  (setq s 0))
-                 ((floatp size)
-                  (setq s (floor (* size len))))
-                 ((integerp size)
-                  (setq s size))
-                 (t
-                  (error "Illegal size: %s" size)))
-           ;; Try to make sure that we are inside the safe limits.
-           (cond ((zerop s))
-                 ((eq type 'horizontal)
-                  (setq s (max s window-min-width)))
-                 ((eq type 'vertical)
-                  (setq s (max s window-min-height))))
-           (setcar (cdar comp-subs) s)
-           (incf total s)))
-       ;; Take care of the "1.0" spec.
-       (if rest
-           (setcar (cdr rest) (- len total))
-         (error "No 1.0 specs in %s" split))
-       ;; The we do the actual splitting in a nice recursive
-       ;; fashion.
-       (setq comp-subs (nreverse comp-subs))
-       (while comp-subs
-         (if (null (cdr comp-subs))
-             (setq new-win window)
-           (setq new-win
-                 (split-window window (cadar comp-subs)
-                               (eq type 'horizontal))))
-         (setq result (or (gnus-configure-frame
-                           (car comp-subs) window)
-                          result))
-         (select-window new-win)
-         (setq window new-win)
-         (setq comp-subs (cdr comp-subs))))
-      ;; Return the proper window, if any.
-      (when result
-       (select-window result))))))
+  (let ((current-window
+        (or (get-buffer-window (current-buffer)) (selected-window))))
+    (unless window
+      (setq window current-window))
+    (select-window window)
+    ;; This might be an old-style buffer config.
+    (when (vectorp split)
+      (setq split (append split nil)))
+    (when (or (consp (car split))
+             (vectorp (car split)))
+      (push 1.0 split)
+      (push 'vertical split))
+    ;; The SPLIT might be something that is to be evaled to
+    ;; return a new SPLIT.
+    (while (and (not (assq (car split) gnus-window-to-buffer))
+               (functionp (car split)))
+      (setq split (eval split)))
+    (let* ((type (car split))
+          (subs (cddr split))
+          (len (if (eq type 'horizontal) (window-width) (window-height)))
+          (total 0)
+          (window-min-width (or gnus-window-min-width window-min-width))
+          (window-min-height (or gnus-window-min-height window-min-height))
+          s result new-win rest comp-subs size sub)
+      (cond
+       ;; Nothing to do here.
+       ((null split))
+       ;; Don't switch buffers.
+       ((null type)
+       (and (memq 'point split) window))
+       ;; This is a buffer to be selected.
+       ((not (memq type '(frame horizontal vertical)))
+       (let ((buffer (cond ((stringp type) type)
+                           (t (cdr (assq type gnus-window-to-buffer))))))
+         (unless buffer
+           (error "Invalid buffer type: %s" type))
+         (let ((buf (gnus-get-buffer-create
+                     (gnus-window-to-buffer-helper buffer))))
+           (if (eq buf (window-buffer (selected-window))) (set-buffer buf)
+             (switch-to-buffer buf)))
+         (when (memq 'frame-focus split)
+           (setq gnus-window-frame-focus window))
+         ;; We return the window if it has the `point' spec.
+         (and (memq 'point split) window)))
+       ;; This is a frame split.
+       ((eq type 'frame)
+       (unless gnus-frame-list
+         (setq gnus-frame-list (list (window-frame current-window))))
+       (let ((i 0)
+             params frame fresult)
+         (while (< i (length subs))
+           ;; Frame parameter is gotten from the sub-split.
+           (setq params (cadr (elt subs i)))
+           ;; It should be a list.
+           (unless (listp params)
+             (setq params nil))
+           ;; Create a new frame?
+           (unless (setq frame (elt gnus-frame-list i))
+             (nconc gnus-frame-list (list (setq frame (make-frame params))))
+             (push frame gnus-created-frames))
+           ;; Is the old frame still alive?
+           (unless (frame-live-p frame)
+             (setcar (nthcdr i gnus-frame-list)
+                     (setq frame (make-frame params))))
+           ;; Select the frame in question and do more splits there.
+           (select-frame frame)
+           (setq fresult (or (gnus-configure-frame (elt subs i)) fresult))
+           (incf i))
+         ;; Select the frame that has the selected buffer.
+         (when fresult
+           (select-frame (window-frame fresult)))))
+       ;; This is a normal split.
+       (t
+       (when (> (length subs) 0)
+         ;; First we have to compute the sizes of all new windows.
+         (while subs
+           (setq sub (append (pop subs) nil))
+           (while (and (not (assq (car sub) gnus-window-to-buffer))
+                       (functionp (car sub)))
+             (setq sub (eval sub)))
+           (when sub
+             (push sub comp-subs)
+             (setq size (cadar comp-subs))
+             (cond ((equal size 1.0)
+                    (setq rest (car comp-subs))
+                    (setq s 0))
+                   ((floatp size)
+                    (setq s (floor (* size len))))
+                   ((integerp size)
+                    (setq s size))
+                   (t
+                    (error "Invalid size: %s" size)))
+             ;; Try to make sure that we are inside the safe limits.
+             (cond ((zerop s))
+                   ((eq type 'horizontal)
+                    (setq s (max s window-min-width)))
+                   ((eq type 'vertical)
+                    (setq s (max s window-min-height))))
+             (setcar (cdar comp-subs) s)
+             (incf total s)))
+         ;; Take care of the "1.0" spec.
+         (if rest
+             (setcar (cdr rest) (- len total))
+           (error "No 1.0 specs in %s" split))
+         ;; The we do the actual splitting in a nice recursive
+         ;; fashion.
+         (setq comp-subs (nreverse comp-subs))
+         (while comp-subs
+           (if (null (cdr comp-subs))
+               (setq new-win window)
+             (setq new-win
+                   (split-window window (cadar comp-subs)
+                                 (eq type 'horizontal))))
+           (setq result (or (gnus-configure-frame
+                             (car comp-subs) window)
+                            result))
+           (select-window new-win)
+           (setq window new-win)
+           (setq comp-subs (cdr comp-subs))))
+       ;; Return the proper window, if any.
+       (when result
+         (select-window result)))))))
 
 (defvar gnus-frame-split-p nil)
 
 (defun gnus-configure-windows (setting &optional force)
-  (setq gnus-current-window-configuration setting)
-  (setq force (or force gnus-always-force-window-configuration))
-  (setq setting (gnus-windows-old-to-new setting))
-  (let ((split (if (symbolp setting)
-                  (cadr (assq setting gnus-buffer-configuration))
-                setting))
-       all-visible)
-
-    (setq gnus-frame-split-p nil)
-
-    (unless split
-      (error "No such setting: %s" setting))
-
-    (if (and (setq all-visible (gnus-all-windows-visible-p split))
-            (not force))
-       ;; All the windows mentioned are already visible, so we just
-       ;; put point in the assigned buffer, and do not touch the
-       ;; winconf.
-       (select-window all-visible)
-
-      ;; Either remove all windows or just remove all Gnus windows.
-      (let ((frame (selected-frame)))
-       (unwind-protect
-           (if gnus-use-full-window
-               ;; We want to remove all other windows.
-               (if (not gnus-frame-split-p)
-                   ;; This is not a `frame' split, so we ignore the
-                   ;; other frames.
-                   (delete-other-windows)
+  (if (window-configuration-p setting)
+      (set-window-configuration setting)
+    (setq gnus-current-window-configuration setting)
+    (setq force (or force gnus-always-force-window-configuration))
+    (setq setting (gnus-windows-old-to-new setting))
+    (let ((split (if (symbolp setting)
+                    (cadr (assq setting gnus-buffer-configuration))
+                  setting))
+         all-visible)
+
+      (setq gnus-frame-split-p nil)
+
+      (unless split
+       (error "No such setting in `gnus-buffer-configuration': %s" setting))
+
+      (if (and (setq all-visible (gnus-all-windows-visible-p split))
+              (not force))
+         ;; All the windows mentioned are already visible, so we just
+         ;; put point in the assigned buffer, and do not touch the
+         ;; winconf.
+         (select-window all-visible)
+
+       ;; Make sure "the other" buffer, nntp-server-buffer, is live.
+       (unless (gnus-buffer-live-p nntp-server-buffer)
+         (nnheader-init-server-buffer))
+
+       ;; Either remove all windows or just remove all Gnus windows.
+       (let ((frame (selected-frame)))
+         (unwind-protect
+             (if gnus-use-full-window
+                 ;; We want to remove all other windows.
+                 (if (not gnus-frame-split-p)
+                     ;; This is not a `frame' split, so we ignore the
+                     ;; other frames.
+                     (delete-other-windows)
                  ;; This is a `frame' split, so we delete all windows
-                 ;; on all frames.
-                 (gnus-delete-windows-in-gnusey-frames))
-             ;; Just remove some windows.
-             (gnus-remove-some-windows)
-             (switch-to-buffer nntp-server-buffer))
-         (select-frame frame)))
-
-      (switch-to-buffer nntp-server-buffer)
-      (gnus-configure-frame split (get-buffer-window (current-buffer))))))
+                   ;; on all frames.
+                   (gnus-delete-windows-in-gnusey-frames))
+               ;; Just remove some windows.
+               (gnus-remove-some-windows)
+               (if (featurep 'xemacs)
+                   (switch-to-buffer nntp-server-buffer)
+                 (set-buffer nntp-server-buffer)))
+           (select-frame frame)))
+
+       (let (gnus-window-frame-focus)
+         (if (featurep 'xemacs)
+             (switch-to-buffer nntp-server-buffer)
+           (set-buffer nntp-server-buffer))
+         (gnus-configure-frame split)
+         (run-hooks 'gnus-configure-windows-hook)
+         (when gnus-window-frame-focus
+           (select-frame (window-frame gnus-window-frame-focus))))))))
 
 (defun gnus-delete-windows-in-gnusey-frames ()
   "Do a `delete-other-windows' in all frames that have Gnus windows."
-  (let ((buffers
-        (mapcar
-         (lambda (elem)
-           (if (symbolp (cdr elem))
-               (when (and (boundp (cdr elem))
-                          (symbol-value (cdr elem)))
-                 (get-buffer (symbol-value (cdr elem))))
-             (when (cdr elem)
-               (get-buffer (cdr elem)))))
-         gnus-window-to-buffer)))
+  (let ((buffers (gnus-buffers)))
     (mapcar
      (lambda (frame)
        (unless (eq (cdr (assq 'minibuffer
@@ -480,7 +507,7 @@ should have point."
       ;; The SPLIT might be something that is to be evaled to
       ;; return a new SPLIT.
       (while (and (not (assq (car split) gnus-window-to-buffer))
-                 (gnus-functionp (car split)))
+                 (functionp (car split)))
        (setq split (eval split)))
 
       (setq type (elt split 0))
@@ -492,14 +519,11 @@ should have point."
        (setq buffer (cond ((stringp type) type)
                           (t (cdr (assq type gnus-window-to-buffer)))))
        (unless buffer
-         (error "Illegal buffer type: %s" type))
-       (when (setq buf (get-buffer (if (symbolp buffer)
-                                       (symbol-value buffer)
-                                     buffer)))
-         (setq win (get-buffer-window buf t)))
-       (if win
-           (when (memq 'point split)
-             (setq all-visible win))
+         (error "Invalid buffer type: %s" type))
+       (if (and (setq buf (get-buffer (gnus-window-to-buffer-helper buffer)))
+                (setq win (gnus-get-buffer-window buf t)))
+           (if (memq 'point split)
+               (setq all-visible win))
          (setq all-visible nil)))
        (t
        (when (eq type 'frame)
@@ -512,42 +536,46 @@ should have point."
   (nth 1 (window-edges window)))
 
 (defun gnus-remove-some-windows ()
-  (let ((buffers gnus-window-to-buffer)
+  (let ((buffers (gnus-buffers))
        buf bufs lowest-buf lowest)
     (save-excursion
       ;; Remove windows on all known Gnus buffers.
-      (while buffers
-       (setq buf (cdar buffers))
-       (when (symbolp buf)
-         (setq buf (and (boundp buf) (symbol-value buf))))
-       (and buf
-            (get-buffer-window buf)
-            (progn
-              (push buf bufs)
-              (pop-to-buffer buf)
-              (when (or (not lowest)
-                        (< (gnus-window-top-edge) lowest))
-                (setq lowest (gnus-window-top-edge))
-                (setq lowest-buf buf))))
-       (setq buffers (cdr buffers)))
-      ;; Remove windows on *all* summary buffers.
-      (walk-windows
-       (lambda (win)
-        (let ((buf (window-buffer win)))
-          (when (string-match  "^\\*\\(Dead \\)?Summary" (buffer-name buf))
-            (push buf bufs)
-            (pop-to-buffer buf)
-            (when (or (not lowest)
-                      (< (gnus-window-top-edge) lowest))
-              (setq lowest-buf buf)
-              (setq lowest (gnus-window-top-edge)))))))
+      (while (setq buf (pop buffers))
+       (when (get-buffer-window buf)
+         (push buf bufs)
+         (pop-to-buffer buf)
+         (when (or (not lowest)
+                   (< (gnus-window-top-edge) lowest))
+           (setq lowest (gnus-window-top-edge)
+                 lowest-buf buf))))
       (when lowest-buf
        (pop-to-buffer lowest-buf)
-       (switch-to-buffer nntp-server-buffer))
-      (while bufs
-       (when (not (eq (car bufs) lowest-buf))
-         (delete-windows-on (car bufs)))
-       (setq bufs (cdr bufs))))))
+       (if (featurep 'xemacs)
+           (switch-to-buffer nntp-server-buffer)
+         (set-buffer nntp-server-buffer)))
+      (mapcar (lambda (b) (delete-windows-on b t))
+             (delq lowest-buf bufs)))))
+
+(eval-and-compile
+  (cond
+   ((fboundp 'frames-on-display-list)
+    (defalias 'gnus-frames-on-display-list 'frames-on-display-list))
+   ((and (featurep 'xemacs) (fboundp 'frame-device))
+    (defun gnus-frames-on-display-list ()
+      (apply 'filtered-frame-list 'identity (list (frame-device nil)))))
+   (t
+    (defalias 'gnus-frames-on-display-list 'frame-list))))
+
+(defun gnus-get-buffer-window (buffer &optional frame)
+  (cond ((and (null gnus-use-frames-on-any-display)
+             (memq frame '(t 0 visible)))
+        (car
+         (let ((frames (gnus-frames-on-display-list)))
+           (gnus-remove-if (lambda (win) (not (memq (window-frame win)
+                                                    frames)))
+                           (get-buffer-window-list buffer nil frame)))))
+       (t
+        (get-buffer-window buffer frame))))
 
 (provide 'gnus-win)
 
index bb65e65..6fff59e 100644 (file)
@@ -1,7 +1,10 @@
 ;;; gnus-xmas.el --- Gnus functions for XEmacs
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile
+  (autoload 'gnus-active "gnus" nil nil 'macro)
+  (autoload 'gnus-group-entry "gnus" nil nil 'macro)
+  (autoload 'gnus-info-level "gnus" nil nil 'macro)
+  (autoload 'gnus-info-marks "gnus" nil nil 'macro)
+  (autoload 'gnus-info-method "gnus" nil nil 'macro)
+  (autoload 'gnus-info-score "gnus" nil nil 'macro))
+
 (require 'text-props)
 (defvar menu-bar-mode (featurep 'menubar))
 (require 'messagexmas)
+(require 'wid-edit)
 
 (defgroup gnus-xmas nil
   "XEmacsoid support for Gnus"
@@ -41,56 +53,20 @@ automatically."
                 directory)
   :group 'gnus-xmas)
 
-(defvar gnus-xmas-logo-color-alist
-  '((flame "#cc3300" "#ff2200")
-    (pine "#c0cc93" "#f8ffb8")
-    (moss "#a1cc93" "#d2ffb8")
-    (irish "#04cc90" "#05ff97")
-    (sky "#049acc" "#05deff")
-    (tin "#6886cc" "#82b6ff")
-    (velvet "#7c68cc" "#8c82ff")
-    (grape "#b264cc" "#cf7df")
-    (labia "#cc64c2" "#fd7dff")
-    (berry "#cc6485" "#ff7db5")
-    (neutral "#b4b4b4" "#878787")
-    (september "#bf9900" "#ffcc00"))
-  "Color alist used for the Gnus logo.")
-
-(defcustom gnus-xmas-logo-color-style 'moss
-  "*Color styles used for the Gnus logo."
-  :type '(choice (const flame) (const pine) (const moss)
-                (const irish) (const sky) (const tin)
-                (const velvet) (const grape) (const labia)
-                (const berry) (const neutral) (const september))
-  :group 'gnus-xmas)
-
-(defvar gnus-xmas-logo-colors
-  (cdr (assq gnus-xmas-logo-color-style gnus-xmas-logo-color-alist))
-  "Colors used for the Gnus logo.")
-
-(defcustom gnus-article-x-face-command
-  (if (or (featurep 'xface)
-         (featurep 'xpm))
-      'gnus-xmas-article-display-xface
-    "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -")
-  "*String or function to be executed to display an X-Face header.
-If it is a string, the command will be executed in a sub-shell
-asynchronously.         The compressed face will be piped to this command."
-  :type '(choice string function))
+(unless gnus-xmas-glyph-directory
+  (unless (setq gnus-xmas-glyph-directory
+               (message-xmas-find-glyph-directory "gnus"))
+    (error "Can't find glyph directory. \
+Possibly the `etc' directory has not been installed.")))
 
 ;;; Internal variables.
 
 ;; Don't warn about these undefined variables.
 
-(defvar gnus-group-mode-hook)
-(defvar gnus-summary-mode-hook)
-(defvar gnus-article-mode-hook)
-
 ;;defined in gnus.el
 (defvar gnus-active-hashtb)
 (defvar gnus-article-buffer)
 (defvar gnus-auto-center-summary)
-(defvar gnus-buffer-list)
 (defvar gnus-current-headers)
 (defvar gnus-level-killed)
 (defvar gnus-level-zombie)
@@ -134,12 +110,12 @@ It is provided only to ease porting of broken FSF Emacs programs."
   (if (stringp buffer)
       nil
     (map-extents (lambda (extent ignored)
-                   (remove-text-properties
-                    start end
-                    (list (extent-property extent 'text-prop) nil)
-                    buffer)
+                  (remove-text-properties
+                   start end
+                   (list (extent-property extent 'text-prop) nil)
+                   buffer)
                   nil)
-                 buffer start end nil nil 'text-prop)
+                buffer start end nil nil 'text-prop)
     (gnus-add-text-properties start end props buffer)))
 
 (defun gnus-xmas-highlight-selected-summary ()
@@ -177,7 +153,9 @@ displayed, no centering will be performed."
                     (- (window-height) 2)))
           (top (cond ((< height 4) 0)
                      ((< height 7) 1)
-                     (t 2)))
+                     (t (if (numberp gnus-auto-center-summary)
+                            gnus-auto-center-summary
+                          2))))
           (bottom (save-excursion (goto-char (point-max))
                                   (forward-line (- height))
                                   (point)))
@@ -187,8 +165,10 @@ displayed, no centering will be performed."
        ;; Set the window start to either `bottom', which is the biggest
        ;; possible valid number, or the second line from the top,
        ;; whichever is the least.
+       ;; NOFORCE parameter suggested by Daniel Pittman <daniel@danann.net>.
        (set-window-start
-        window (min bottom (save-excursion (forward-line (- top)) (point)))))
+        window (min bottom (save-excursion (forward-line (- top)) (point)))
+        t))
       ;; Do horizontal recentering while we're at it.
       (when (and (get-buffer-window (current-buffer) t)
                 (not (eq gnus-auto-center-summary 'vertical)))
@@ -242,6 +222,7 @@ call it with the value of the `gnus-data' text property."
   (let* ((pos (event-closest-point event))
         (data (get-text-property pos 'gnus-data))
         (fun (get-text-property pos 'gnus-callback)))
+    (goto-char pos)
     (when fun
       (funcall fun data))))
 
@@ -254,21 +235,6 @@ call it with the value of the `gnus-data' text property."
                 (delete-extent extent)
                 nil)))
 
-;; Fixed by Christopher Davis <ckd@loiosh.kei.com>.
-(defun gnus-xmas-article-add-button (from to fun &optional data)
-  "Create a button between FROM and TO with callback FUN and data DATA."
-  (when gnus-article-button-face
-    (gnus-overlay-put (gnus-make-overlay from to)
-                     'face gnus-article-button-face))
-  (gnus-add-text-properties
-   from to
-   (nconc
-    (and gnus-article-mouse-face
-        (list 'mouse-face gnus-article-mouse-face))
-    (list 'gnus-callback fun)
-    (and data (list 'gnus-data data))
-    (list 'highlight t))))
-
 (defun gnus-xmas-window-top-edge (&optional window)
   (nth 1 (window-pixel-edges window)))
 
@@ -294,19 +260,19 @@ call it with the value of the `gnus-data' text property."
 (defun gnus-xmas-appt-select-lowest-window ()
   (let* ((lowest-window (selected-window))
         (bottom-edge (car (cdr (cdr (cdr (window-pixel-edges))))))
-         (last-window (previous-window))
-         (window-search t))
+        (last-window (previous-window))
+        (window-search t))
     (while window-search
       (let* ((this-window (next-window))
-             (next-bottom-edge (car (cdr (cdr (cdr
-                                               (window-pixel-edges
+            (next-bottom-edge (car (cdr (cdr (cdr
+                                              (window-pixel-edges
                                                this-window)))))))
-        (when (< bottom-edge next-bottom-edge)
+       (when (< bottom-edge next-bottom-edge)
          (setq bottom-edge next-bottom-edge)
          (setq lowest-window this-window))
 
-        (select-window this-window)
-        (when (eq last-window this-window)
+       (select-window this-window)
+       (when (eq last-window this-window)
          (select-window lowest-window)
          (setq window-search nil))))))
 
@@ -332,7 +298,8 @@ call it with the value of the `gnus-data' text property."
 
 (defun gnus-xmas-article-menu-add ()
   (gnus-xmas-menu-add article
-    gnus-article-article-menu gnus-article-treatment-menu))
+    gnus-article-article-menu gnus-article-treatment-menu
+    gnus-article-post-menu gnus-article-commands-menu))
 
 (defun gnus-xmas-score-menu-add ()
   (gnus-xmas-menu-add score
@@ -366,6 +333,10 @@ call it with the value of the `gnus-data' text property."
   (gnus-xmas-menu-add tree
     gnus-tree-menu))
 
+(defun gnus-xmas-draft-menu-add ()
+  (gnus-xmas-menu-add draft
+    gnus-draft-menu))
+
 (defun gnus-xmas-server-menu-add ()
   (gnus-xmas-menu-add menu
     gnus-server-server-menu gnus-server-connections-menu))
@@ -378,8 +349,10 @@ call it with the value of the `gnus-data' text property."
   (gnus-xmas-menu-add grouplens
     gnus-grouplens-menu))
 
-(defun gnus-xmas-read-event-char ()
+(defun gnus-xmas-read-event-char (&optional prompt)
   "Get the next event."
+  (when prompt
+    (message "%s" prompt))
   (let ((event (next-command-event)))
     (sit-for 0)
     ;; We junk all non-key events.  Is this naughty?
@@ -391,26 +364,10 @@ call it with the value of the `gnus-data' text property."
               (event-to-character event))
          event)))
 
-(defun gnus-xmas-seconds-since-epoch (date)
-  "Return a floating point number that says how many seconds have lapsed between Jan 1 12:00:00 1970 and DATE."
-  (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-date date)))
-        (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-time
-                        (aref (timezone-parse-date date) 3))))
-        (edate (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-date "Jan 1 12:00:00 1970")))
-        (tday (- (timezone-absolute-from-gregorian
-                  (nth 1 tdate) (nth 2 tdate) (nth 0 tdate))
-                 (timezone-absolute-from-gregorian
-                  (nth 1 edate) (nth 2 edate) (nth 0 edate)))))
-    (+ (nth 2 ttime)
-       (* (nth 1 ttime) 60)
-       (* (float (nth 0 ttime)) 60 60)
-       (* (float tday) 60 60 24))))
-
 (defun gnus-xmas-define ()
   (setq gnus-mouse-2 [button2])
+  (setq gnus-mouse-3 [button3])
+  (setq gnus-widget-button-keymap widget-button-keymap)
 
   (unless (memq 'underline (face-list))
     (and (fboundp 'make-face)
@@ -424,45 +381,35 @@ call it with the value of the `gnus-data' text property."
   (cond
    ((fboundp 'char-or-char-int-p)
     ;; Handle both types of marks for XEmacs-20.x.
-    (fset 'gnus-characterp 'char-or-char-int-p))
+    (defalias 'gnus-characterp 'char-or-char-int-p))
    ;; V19 of XEmacs, probably.
    (t
-    (fset 'gnus-characterp 'characterp)))
-
-  (fset 'gnus-make-overlay 'make-extent)
-  (fset 'gnus-delete-overlay 'delete-extent)
-  (fset 'gnus-overlay-put 'set-extent-property)
-  (fset 'gnus-move-overlay 'gnus-xmas-move-overlay)
-  (fset 'gnus-overlay-end 'extent-end-position)
-  (fset 'gnus-kill-all-overlays 'gnus-xmas-kill-all-overlays)
-  (fset 'gnus-extent-detached-p 'extent-detached-p)
-  (fset 'gnus-add-text-properties 'gnus-xmas-add-text-properties)
-  (fset 'gnus-put-text-property 'gnus-xmas-put-text-property)
-  (fset 'gnus-deactivate-mark 'ignore)
-  (fset 'gnus-window-edges 'window-pixel-edges)
+    (defalias 'gnus-characterp 'characterp)))
+
+  (defalias 'gnus-make-overlay 'make-extent)
+  (defalias 'gnus-delete-overlay 'delete-extent)
+  (defalias 'gnus-overlay-put 'set-extent-property)
+  (defalias 'gnus-move-overlay 'gnus-xmas-move-overlay)
+  (defalias 'gnus-overlay-buffer 'extent-object)
+  (defalias 'gnus-overlay-start 'extent-start-position)
+  (defalias 'gnus-overlay-end 'extent-end-position)
+  (defalias 'gnus-kill-all-overlays 'gnus-xmas-kill-all-overlays)
+  (defalias 'gnus-extent-detached-p 'extent-detached-p)
+  (defalias 'gnus-add-text-properties 'gnus-xmas-add-text-properties)
+  (defalias 'gnus-put-text-property 'gnus-xmas-put-text-property)
+  (defalias 'gnus-deactivate-mark 'ignore)
+  (defalias 'gnus-window-edges 'window-pixel-edges)
+  (defalias 'gnus-assq-delete-all 'gnus-xmas-assq-delete-all)
 
   (if (and (<= emacs-major-version 19)
-          (< emacs-minor-version 14))
-      (fset 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
-
-  (when (fboundp 'turn-off-scroll-in-place)
-    (add-hook 'gnus-article-mode-hook 'turn-off-scroll-in-place))
+          (< emacs-minor-version 14))
+      (defalias 'gnus-set-text-properties 'gnus-xmas-set-text-properties))
 
   (unless (boundp 'standard-display-table)
     (setq standard-display-table nil))
 
   (defvar gnus-mouse-face-prop 'highlight)
 
-  (unless (fboundp 'encode-time)
-    (defun encode-time (sec minute hour day month year &optional zone)
-      (let ((seconds
-            (gnus-xmas-seconds-since-epoch
-             (timezone-make-arpa-date
-              year month day (timezone-make-time-string hour minute sec)
-              zone))))
-       (list (floor (/ seconds (expt 2 16)))
-             (round (mod seconds (expt 2 16)))))))
-
   (defun gnus-byte-code (func)
     "Return a form that can be `eval'ed based on FUNC."
     (let ((fval (indirect-function func)))
@@ -470,65 +417,117 @@ call it with the value of the `gnus-data' text property."
          (list 'funcall fval)
        (cons 'progn (cdr (cdr fval))))))
 
-  (fset 'gnus-x-color-values
-       (if (fboundp 'x-color-values)
-           'x-color-values
-         (lambda (color)
-           (color-instance-rgb-components
-            (make-color-instance color))))))
+  (defalias 'gnus-x-color-values
+    (if (fboundp 'x-color-values)
+       'x-color-values
+      (lambda (color)
+       (color-instance-rgb-components
+        (make-color-instance color))))))
 
 (defun gnus-xmas-redefine ()
   "Redefine lots of Gnus functions for XEmacs."
-  (fset 'gnus-summary-set-display-table 'gnus-xmas-summary-set-display-table)
-  (fset 'gnus-visual-turn-off-edit-menu 'identity)
-  (fset 'gnus-summary-recenter 'gnus-xmas-summary-recenter)
-  (fset 'gnus-extent-start-open 'gnus-xmas-extent-start-open)
-  (fset 'gnus-article-push-button 'gnus-xmas-article-push-button)
-  (fset 'gnus-article-add-button 'gnus-xmas-article-add-button)
-  (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
-  (fset 'gnus-read-event-char 'gnus-xmas-read-event-char)
-  (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
-  (fset 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
-  (fset 'gnus-appt-select-lowest-window
-       'gnus-xmas-appt-select-lowest-window)
-  (fset 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
-  (fset 'gnus-character-to-event 'character-to-event)
-  (fset 'gnus-mode-line-buffer-identification
-       'gnus-xmas-mode-line-buffer-identification)
-  (fset 'gnus-key-press-event-p 'key-press-event-p)
-  (fset 'gnus-region-active-p 'region-active-p)
-
-  (add-hook 'gnus-group-mode-hook 'gnus-xmas-group-menu-add)
-  (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
-  (add-hook 'gnus-article-mode-hook 'gnus-xmas-article-menu-add)
+  (defalias 'gnus-summary-set-display-table 'gnus-xmas-summary-set-display-table)
+  (defalias 'gnus-visual-turn-off-edit-menu 'identity)
+  (defalias 'gnus-summary-recenter 'gnus-xmas-summary-recenter)
+  (defalias 'gnus-extent-start-open 'gnus-xmas-extent-start-open)
+  (defalias 'gnus-article-push-button 'gnus-xmas-article-push-button)
+  (defalias 'gnus-window-top-edge 'gnus-xmas-window-top-edge)
+  (defalias 'gnus-read-event-char 'gnus-xmas-read-event-char)
+  (defalias 'gnus-group-startup-message 'gnus-xmas-group-startup-message)
+  (defalias 'gnus-tree-minimize 'gnus-xmas-tree-minimize)
+  (defalias 'gnus-appt-select-lowest-window
+    'gnus-xmas-appt-select-lowest-window)
+  (defalias 'gnus-mail-strip-quoted-names 'gnus-xmas-mail-strip-quoted-names)
+  (defalias 'gnus-character-to-event 'character-to-event)
+  (defalias 'gnus-mode-line-buffer-identification
+    'gnus-xmas-mode-line-buffer-identification)
+  (defalias 'gnus-key-press-event-p 'key-press-event-p)
+  (defalias 'gnus-region-active-p 'region-active-p)
+  (defalias 'gnus-mark-active-p 'region-exists-p)
+  (defalias 'gnus-annotation-in-region-p 'gnus-xmas-annotation-in-region-p)
+  (defalias 'gnus-mime-button-menu 'gnus-xmas-mime-button-menu)
+  (defalias 'gnus-image-type-available-p 'gnus-xmas-image-type-available-p)
+  (defalias 'gnus-put-image 'gnus-xmas-put-image)
+  (defalias 'gnus-create-image 'gnus-xmas-create-image)
+  (defalias 'gnus-remove-image 'gnus-xmas-remove-image)
+
+  (when (or (< emacs-major-version 21)
+           (and (= emacs-major-version 21)
+                (< emacs-minor-version 3)))
+    (defalias 'gnus-completing-read 'gnus-xmas-completing-read))
+
+  ;; These ones are not defcutom'ed, sometimes not even defvar'ed. They
+  ;; probably should. If that is done, the code below should then be moved
+  ;; where each variable is defined, in order not to mess with user settings.
+  ;; -- didier
   (add-hook 'gnus-score-mode-hook 'gnus-xmas-score-menu-add)
-
-  (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add)
-  (add-hook 'gnus-topic-mode-hook 'gnus-xmas-topic-menu-add)
-  (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
   (add-hook 'gnus-binary-mode-hook 'gnus-xmas-binary-menu-add)
   (add-hook 'gnus-grouplens-mode-hook 'gnus-xmas-grouplens-menu-add)
   (add-hook 'gnus-server-mode-hook 'gnus-xmas-server-menu-add)
   (add-hook 'gnus-browse-mode-hook 'gnus-xmas-browse-menu-add)
-
-  (add-hook 'gnus-group-mode-hook 'gnus-xmas-setup-group-toolbar)
-  (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
-
-  (add-hook 'gnus-agent-summary-mode-hook 'gnus-xmas-agent-summary-menu-add)
-  (add-hook 'gnus-agent-group-mode-hook 'gnus-xmas-agent-group-menu-add)
-  (add-hook 'gnus-agent-server-mode-hook 'gnus-xmas-agent-server-menu-add)
-  
-  (add-hook 'gnus-summary-mode-hook
-           'gnus-xmas-switch-horizontal-scrollbar-off)
-  (add-hook 'gnus-tree-mode-hook 'gnus-xmas-switch-horizontal-scrollbar-off))
-
+  (add-hook 'gnus-draft-mode-hook 'gnus-xmas-draft-menu-add)
+  (add-hook 'gnus-mailing-list-mode-hook 'gnus-xmas-mailing-list-menu-add)
+
+  (when (featurep 'mule)
+    (defun gnus-truncate-string (str end-column &optional start-column padding)
+      "Truncate string STR to end at column END-COLUMN.
+The optional 2nd arg START-COLUMN, if non-nil, specifies
+the starting column; that means to return the characters occupying
+columns START-COLUMN ... END-COLUMN of STR.
+
+The optional 3rd arg PADDING, if non-nil, specifies a padding character
+to add at the end of the result if STR doesn't reach column END-COLUMN,
+or if END-COLUMN comes in the middle of a character in STR.
+PADDING is also added at the beginning of the result
+if column START-COLUMN appears in the middle of a character in STR.
+
+If PADDING is nil, no padding is added in these cases, so
+the resulting string may be narrower than END-COLUMN.
+\[Emacs 20.3 emulating function]"
+      (or start-column
+         (setq start-column 0))
+      (let ((len (length str))
+           (idx 0)
+           (column 0)
+           (head-padding "") (tail-padding "")
+           ch last-column last-idx from-idx)
+       (condition-case nil
+           (while (< column start-column)
+             (setq ch (aref str idx)
+                   column (+ column (char-width ch))
+                   idx (1+ idx)))
+         (args-out-of-range (setq idx len)))
+       (if (< column start-column)
+           (if padding (make-string end-column padding) "")
+         (if (and padding (> column start-column))
+             (setq head-padding
+                   (make-string (- column start-column) padding)))
+         (setq from-idx idx)
+         (if (< end-column column)
+             (setq idx from-idx)
+           (condition-case nil
+               (while (< column end-column)
+                 (setq last-column column
+                       last-idx idx
+                       ch (aref str idx)
+                       column (+ column (char-width ch))
+                       idx (1+ idx)))
+             (args-out-of-range (setq idx len)))
+           (if (> column end-column)
+               (setq column last-column idx last-idx))
+           (if (and padding (< column end-column))
+               (setq tail-padding
+                     (make-string (- end-column column) padding))))
+         (setq str (substring str from-idx idx))
+         (if padding
+             (concat head-padding str tail-padding)
+           str))))))
 
 ;;; XEmacs logo and toolbar.
 
 (defun gnus-xmas-group-startup-message (&optional x y)
   "Insert startup message in current buffer."
   ;; Insert the message.
-  (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
   (erase-buffer)
   (cond
    ((and (console-on-window-system-p)
@@ -541,49 +540,75 @@ call it with the value of the `gnus-data' text property."
                          `[xpm
                            :file ,logo-xpm
                            :color-symbols
-                           (("thing" . ,(car gnus-xmas-logo-colors))
-                            ("shadow" . ,(cadr gnus-xmas-logo-colors))
+                           (("thing" . ,(car gnus-logo-colors))
+                            ("shadow" . ,(cadr gnus-logo-colors))
+                            ("oort" . "#eeeeee")
                             ("background" . ,(face-background 'default)))])
                         ((featurep 'xbm)
                          `[xbm :file ,logo-xbm])
-                        (t [nothing])))))
+                        (t [nothing]))))
+          (wpheight (window-pixel-height))
+          (rest (max 0 (1- (/ (* (- wpheight (glyph-height glyph))
+                                 (window-height))
+                              wpheight 2)))))
       (insert " ")
       (set-extent-begin-glyph (make-extent (point) (point)) glyph)
       (goto-char (point-min))
       (while (not (eobp))
        (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2)
                             ?\ ))
-       (forward-line 1)))
-    (goto-char (point-min))
-    (let* ((pheight (+ 20 (count-lines (point-min) (point-max))))
-          (wheight (window-height))
-          (rest (- wheight pheight)))
-      (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n))))
+       (forward-line 1))
+      (setq gnus-simple-splash nil)
+      (goto-char (point-min))
+      (insert gnus-product-name " " gnus-version-number
+             (if (zerop (string-to-number gnus-revision-number))
+                 ""
+               (concat " (r" gnus-revision-number ")"))
+             " based on " gnus-original-product-name " v"
+             gnus-original-version-number "\n")
+      (end-of-line 0)
+      (put-text-property (point-min) (point) 'face 'gnus-splash-face)
+      (insert-char ?\  (prog1
+                          (max 0 (/ (- (window-width) (point)) 2))
+                        (goto-char (point-min))))
+      (forward-line 1)
+      (insert-char ?\n rest)
+      (set-window-start (selected-window) (point-min))))
    (t
-    (insert
-     (format "              %s
-          _    ___ _             _
-          _ ___ __ ___  __    _ ___
-          __   _     ___    __  ___
-              _           ___     _
-             _  _ __             _
-             ___   __            _
-                   __           _
-                    _      _   _
-                   _      _    _
-                      _  _    _
-                  __  ___
-                 _   _ _     _
-                _   _
-              _    _
-             _    _
-            _
-          __
+    (insert "
+         _    ___ _             _
+         _ ___ __ ___  __    _ ___
+         __   _     ___    __  ___
+             _           ___     _
+            _  _ __             _
+            ___   __            _
+                  __           _
+                   _      _   _
+                  _      _    _
+                     _  _    _
+                 __  ___
+                _   _ _     _
+               _   _
+             _    _
+            _    _
+           _
+         __
 
 "
-            ""))
+           )
+    (goto-char (point-min))
+    (insert gnus-product-name " " gnus-version-number
+           (if (zerop (string-to-number gnus-revision-number))
+               ""
+             (concat " (r" gnus-revision-number ")"))
+           " based on " gnus-original-product-name " v"
+           gnus-original-version-number)
+    (insert-char ?\  (prog1
+                        (max 0 (/ (- (window-width) (point)) 2))
+                      (goto-char (point-min))))
+    (forward-line 1)
     ;; And then hack it.
-    (gnus-indent-rigidly (point-min) (point-max)
+    (gnus-indent-rigidly (point) (point-max)
                         (/ (max (- (window-width) (or x 46)) 0) 2))
     (goto-char (point-min))
     (forward-line 1)
@@ -593,6 +618,7 @@ call it with the value of the `gnus-data' text property."
       (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))
     ;; Paint it.
     (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)))
+  (goto-char (point-min))
   (setq modeline-buffer-identification
        (list (concat gnus-version ": *Group*")))
   (set-buffer-modified-p t))
@@ -604,7 +630,7 @@ call it with the value of the `gnus-data' text property."
                                'default-toolbar
                              nil)
   "*If nil, do not use a toolbar.
-If it is non-nil, it must be a toolbar.  The five legal values are
+If it is non-nil, it must be a toolbar.  The five valid values are
 `default-toolbar', `top-toolbar', `bottom-toolbar',
 `right-toolbar', and `left-toolbar'."
   :type '(choice (const default-toolbar)
@@ -624,8 +650,9 @@ If it is non-nil, it must be a toolbar.  The five legal values are
     [gnus-group-unsubscribe gnus-group-unsubscribe t "Unsubscribe group"]
     [gnus-group-subscribe gnus-group-subscribe t "Subscribe group"]
     [gnus-group-kill-group gnus-group-kill-group t "Kill group"]
-    [gnus-group-exit gnus-group-exit t "Exit Gnus"]
-    )
+    [gnus-summary-mail-save
+     gnus-group-save-newsrc t "Save .newsrc files"] ; borrowed icon.
+    [gnus-group-exit gnus-group-exit t "Exit Gnus"])
   "The group buffer toolbar.")
 
 (defvar gnus-summary-toolbar
@@ -660,8 +687,7 @@ If it is non-nil, it must be a toolbar.  The five legal values are
      gnus-summary-catchup t "Catchup"]
     [gnus-summary-catchup-and-exit
      gnus-summary-catchup-and-exit t "Catchup and exit"]
-    [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
-    )
+    [gnus-summary-exit gnus-summary-exit t "Exit this summary"])
   "The summary buffer toolbar.")
 
 (defvar gnus-summary-mail-toolbar
@@ -671,14 +697,10 @@ If it is non-nil, it must be a toolbar.  The five legal values are
     [gnus-summary-next-unread
      gnus-summary-next-unread-article t "Next unread article"]
     [gnus-summary-mail-reply gnus-summary-reply t "Reply"]
-;    [gnus-summary-mail-get gnus-mail-get t "Message get"]
     [gnus-summary-mail-originate gnus-summary-post-news t "Originate"]
     [gnus-summary-mail-save gnus-summary-save-article t "Save"]
     [gnus-summary-mail-copy gnus-summary-copy-article t "Copy message"]
-;    [gnus-summary-mail-delete gnus-summary-delete-article t "Delete message"]
     [gnus-summary-mail-forward gnus-summary-mail-forward t "Forward message"]
-;    [gnus-summary-mail-spell gnus-mail-spell t "Spell"]
-;    [gnus-summary-mail-help gnus-mail-help  t "Message help"]
     [gnus-summary-caesar-message
      gnus-summary-caesar-message t "Rot 13"]
     [gnus-uu-decode-uu
@@ -687,12 +709,13 @@ If it is non-nil, it must be a toolbar.  The five legal values are
      gnus-summary-save-article-file t "Save article in file"]
     [gnus-summary-save-article
      gnus-summary-save-article t "Save article"]
+    [gnus-summary-cancel-article ; usenet : cancellation :: mail : deletion.
+     gnus-summary-delete-article t "Delete message"]
     [gnus-summary-catchup
      gnus-summary-catchup t "Catchup"]
     [gnus-summary-catchup-and-exit
      gnus-summary-catchup-and-exit t "Catchup and exit"]
-    [gnus-summary-exit gnus-summary-exit t "Exit this summary"]
-    )
+    [gnus-summary-exit gnus-summary-exit t "Exit this summary"])
   "The summary buffer mail toolbar.")
 
 (defun gnus-xmas-setup-group-toolbar ()
@@ -710,7 +733,7 @@ If it is non-nil, it must be a toolbar.  The five legal values are
                        (cons (current-buffer) bar)))))
 
 (defun gnus-xmas-mail-strip-quoted-names (address)
-  "Protect mail-strip-quoted-names from NIL input.
+  "Protect mail-strip-quoted-names from nil input.
 XEmacs compatibility workaround."
   (if (null address)
       nil
@@ -721,66 +744,16 @@ XEmacs compatibility workaround."
    'call-process-region (point-min) (point-max) command t '(t nil) nil
    args))
 
-(defface gnus-x-face '((t (:foreground "black" :background "white")))
-  "Face to show X face"
-  :group 'gnus-xmas)
-
-(defun gnus-xmas-article-display-xface (beg end)
-  "Display any XFace headers in the current article."
-  (save-excursion
-    (let ((xface-glyph
-          (cond ((featurep 'xface)
-                 (make-glyph (vector 'xface :data
-                                     (concat "X-Face: "
-                                             (buffer-substring beg end)))))
-                ((featurep 'xpm)
-                 (let ((cur (current-buffer)))
-                   (save-excursion
-                     (gnus-set-work-buffer)
-                     (insert (format "%s" (buffer-substring beg end cur)))
-                     (gnus-xmas-call-region "uncompface")
-                     (goto-char (point-min))
-                     (insert "/* Width=48, Height=48 */\n")
-                     (gnus-xmas-call-region "icontopbm")
-                     (gnus-xmas-call-region "ppmtoxpm")
-                     (make-glyph
-                      (vector 'xpm :data (buffer-string))))))
-                (t
-                 (make-glyph [nothing]))))
-         (ext (make-extent (progn
-                             (goto-char (point-min))
-                             (re-search-forward "^From:" nil t)
-                             (point))
-                           (1+ (point)))))
-      (set-glyph-face xface-glyph 'gnus-x-face)
-      (set-extent-begin-glyph ext xface-glyph)
-      (set-extent-property ext 'duplicable t))))
-
-;;(defvar gnus-xmas-pointer-glyph
-;;  (progn
-;;    (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory
-;;                                     "gnus"))
-;;    (let ((file-xpm (expand-file-name "gnus-pointer.xpm"
-;;                                   gnus-xmas-glyph-directory))
-;;       (file-xbm (expand-file-name "gnus-pointer.xbm"
-;;                                   gnus-xmas-glyph-directory)))
-;;      (make-pointer-glyph
-;;       (list (vector 'xpm ':file file-xpm)
-;;          (vector 'xbm ':file file-xbm))))))
-
 (defvar gnus-xmas-modeline-left-extent
   (let ((ext (copy-extent modeline-buffer-id-left-extent)))
-;    (set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
     ext))
 
 (defvar gnus-xmas-modeline-right-extent
   (let ((ext (copy-extent modeline-buffer-id-right-extent)))
-;    (set-extent-property ext 'pointer gnus-xmas-pointer-glyph)
     ext))
 
 (defvar gnus-xmas-modeline-glyph
   (progn
-    (setq gnus-xmas-glyph-directory (message-xmas-find-glyph-directory "gnus"))
     (let* ((file-xpm (expand-file-name "gnus-pointer.xpm"
                                       gnus-xmas-glyph-directory))
           (file-xbm (expand-file-name "gnus-pointer.xbm"
@@ -792,7 +765,7 @@ XEmacs compatibility workaround."
                          `[xpm :file ,file-xpm])
                         ((featurep 'xbm)
                          ;; Then a not-so-nifty XBM
-                         [xbm :file ,file-xbm])
+                         `[xbm :file ,file-xbm])
                         ;; Then the simple string
                         (t [string :data "Gnus:"])))))
       (set-glyph-face glyph 'modeline-buffer-id)
@@ -821,6 +794,189 @@ XEmacs compatibility workaround."
   (when (eq (device-type) 'x)
     (gnus-splash)))
 
+(defun gnus-xmas-annotation-in-region-p (b e)
+  (or (map-extents (lambda (e u) t) nil b e nil nil 'mm t)
+      (if (= b e)
+         (eq (cadr (memq 'gnus-undeletable (text-properties-at b))) t)
+       (text-property-any b e 'gnus-undeletable t))))
+
+(defun gnus-xmas-mime-button-menu (event prefix)
+  "Construct a context-sensitive menu of MIME commands."
+  (interactive "e\nP")
+  (let ((response (get-popup-menu-response
+                  `("MIME Part"
+                    ,@(mapcar (lambda (c) `[,(caddr c) ,(car c) t])
+                              gnus-mime-button-commands)))))
+    (set-buffer (event-buffer event))
+    (goto-char (event-point event))
+    (funcall (event-function response) (event-object response))))
+
+(defun gnus-group-add-icon ()
+  "Add an icon to the current line according to `gnus-group-icon-list'."
+  (let* ((p (point))
+        (end (gnus-point-at-eol))
+        ;; now find out where the line starts and leave point there.
+        (beg (progn (beginning-of-line) (point))))
+    (save-restriction
+      (narrow-to-region beg end)
+      (goto-char beg)
+      (when (search-forward "==&&==" nil t)
+       (let* ((group (gnus-group-group-name))
+              (entry (gnus-group-entry group))
+              (unread (if (numberp (car entry)) (car entry) 0))
+              (active (gnus-active group))
+              (total (if active (1+ (- (cdr active) (car active))) 0))
+              (info (nth 2 entry))
+              (method (gnus-server-get-method group (gnus-info-method info)))
+              (marked (gnus-info-marks info))
+              (mailp (memq 'mail (assoc (symbol-name
+                                         (car (or method gnus-select-method)))
+                                        gnus-valid-select-methods)))
+              (level (or (gnus-info-level info) gnus-level-killed))
+              (score (or (gnus-info-score info) 0))
+              (ticked (gnus-range-length (cdr (assq 'tick marked))))
+              (group-age (gnus-group-timestamp-delta group))
+              (inhibit-read-only t)
+              (list gnus-group-icon-list)
+              (mystart (match-beginning 0))
+              (myend (match-end 0)))
+         (goto-char (point-min))
+         (while (and list
+                     (not (eval (caar list))))
+           (setq list (cdr list)))
+         (if list
+             (let* ((file (cdar list))
+                    (glyph (gnus-group-icon-create-glyph
+                            (buffer-substring mystart myend)
+                            file)))
+               (if glyph
+                   (progn
+                     (mapcar 'delete-annotation (annotations-at myend))
+                     (let ((ext (make-extent mystart myend))
+                           (ant (make-annotation glyph myend 'text)))
+                       ;; set text extent params
+                       (set-extent-property ext 'end-open t)
+                       (set-extent-property ext 'start-open t)
+                       (set-extent-property ext 'invisible t)))
+                 (delete-region mystart myend)))
+           (delete-region mystart myend))))
+      (widen))
+    (goto-char p)))
+
+(defun gnus-group-icon-create-glyph (substring pixmap)
+  "Create a glyph for insertion into a group line."
+  (or
+   (cdr-safe (assoc pixmap gnus-group-icon-cache))
+   (let* ((glyph (make-glyph
+                 (list
+                  (cons 'x
+                        (expand-file-name pixmap gnus-xmas-glyph-directory))
+                  (cons 'mswindows
+                        (expand-file-name pixmap gnus-xmas-glyph-directory))
+                  (cons 'tty substring)))))
+     (setq gnus-group-icon-cache
+          (cons (cons pixmap glyph) gnus-group-icon-cache))
+     (set-glyph-face glyph 'default)
+     glyph)))
+
+(defun gnus-xmas-mailing-list-menu-add ()
+  (gnus-xmas-menu-add mailing-list
+    gnus-mailing-list-menu))
+
+(defun gnus-xmas-image-type-available-p (type)
+  (and window-system
+       (featurep (if (eq type 'pbm) 'xbm type))))
+
+(defun gnus-xmas-create-image (file &optional type data-p &rest props)
+  (let ((type (if type
+                 (symbol-name type)
+               (car (last (split-string file "[.]")))))
+       (face (plist-get props :face))
+       glyph)
+    (when (equal type "pbm")
+      (with-temp-buffer
+       (if data-p
+           (insert file)
+         (insert-file-contents-literally file))
+       (shell-command-on-region (point-min) (point-max)
+                                "ppmtoxpm 2>/dev/null" t)
+       (setq file (buffer-string)
+             type "xpm"
+             data-p t)))
+    (setq glyph
+         (if (equal type "xbm")
+             (make-glyph (list (cons 'x file)))
+           (with-temp-buffer
+             (if data-p
+                 (insert file)
+               (insert-file-contents-literally file))
+             (make-glyph
+              (vector
+               (or (intern type)
+                   (mm-image-type-from-buffer))
+               :data (buffer-string))))))
+    (when face
+      (set-glyph-face glyph face))
+    glyph))
+
+(defun gnus-xmas-put-image (glyph &optional string category)
+  "Insert STRING, but display GLYPH.
+Warning: Don't insert text immediately after the image."
+  (let ((begin (point))
+       extent)
+    (if (and (bobp) (not string))
+       (setq string " "))
+    (if string
+       (insert string)
+      (setq begin (1- begin)))
+    (setq extent (make-extent begin (point)))
+    (set-extent-property extent 'gnus-image category)
+    (set-extent-property extent 'duplicable t)
+    (if string
+       (set-extent-property extent 'invisible t))
+    (set-extent-property extent 'end-glyph glyph))
+  glyph)
+
+(defun gnus-xmas-remove-image (image &optional category)
+  (map-extents
+   (lambda (ext unused)
+     (when (equal (extent-end-glyph ext) image)
+       (set-extent-property ext 'invisible nil)
+       (set-extent-property ext 'end-glyph nil))
+     nil)
+   nil nil nil nil nil 'gnus-image category))
+
+(defun gnus-xmas-completing-read (prompt table &optional
+                                        predicate require-match history)
+  (when (and history
+            (not (boundp history)))
+    (set history nil))
+  (completing-read
+   (if (symbol-value history)
+       (concat prompt " (" (car (symbol-value history)) "): ")
+     (concat prompt ": "))
+   table
+   predicate
+   require-match
+   nil
+   history))
+
+;; This macro is because XEmacs versions prior to 21.2 do not have the
+;; PROTOCOL argument to `open-network-stream'.
+(defmacro gnus-xmas-open-network-stream (name buffer host service &optional protocol)
+  "Like `open-network-stream' but take into account older XEmacs versions."
+  (if (and (featurep 'xemacs)
+          (fboundp 'open-network-stream)
+          (emacs-version>= 21 2))
+      `(open-network-stream ,name ,buffer ,host ,service ,protocol)
+    `(open-network-stream ,name ,buffer ,host ,service)))
+
+(defun gnus-xmas-assq-delete-all (key alist)
+  (let ((elem nil))
+    (while (setq elem (assq key alist))
+      (setq alist (delq elem alist)))
+    alist))
+
 (provide 'gnus-xmas)
 
 ;;; gnus-xmas.el ends here
index f201216..85f57a8 100644 (file)
@@ -1,8 +1,12 @@
 ;;; gnus.el --- a newsreader for GNU Emacs
-;; Copyright (C) 1987,88,89,90,93,94,95,96,97,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996, 1997,
+;; 1998, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;;     Yoshiki Hayashi <t90553@mail.ecc.u-tokyo.ac.jp>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 (eval '(run-hooks 'gnus-load-hook))
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
 
-(require 'custom)
-(eval-and-compile
-  (if (< emacs-major-version 20)
-      (require 'gnus-load)))
-(require 'message)
+(require 'wid-edit)
+(require 'nnheader)
+
+(require 'gnus-vers)
 
 (defgroup gnus nil
   "The coffee-brewing, all singing, all dancing, kitchen sink newsreader."
   :group 'news
   :group 'mail)
 
+(defgroup gnus-format nil
+  "Dealing with formatting issues."
+  :group 'gnus)
+
+(defgroup gnus-charset nil
+  "Group character set issues."
+  :link '(custom-manual "(gnus)Charsets")
+  :version "21.1"
+  :group 'gnus)
+
+(defgroup gnus-cache nil
+  "Cache interface."
+  :link '(custom-manual "(gnus)Article Caching")
+  :group 'gnus)
+
+(defgroup gnus-registry nil
+  "Article Registry."
+  :group 'gnus)
+
 (defgroup gnus-start nil
   "Starting your favorite newsreader."
   :group 'gnus)
   :link '(custom-manual "(gnus)Summary Maneuvering")
   :group 'gnus-summary)
 
+(defgroup gnus-picon nil
+  "Show pictures of people, domains, and newsgroups."
+  :group 'gnus-visual)
+
 (defgroup gnus-summary-mail nil
   "Mail group commands."
   :link '(custom-manual "(gnus)Mail Group Commands")
 
 ;; Other
 (defgroup gnus-visual nil
-  "Options controling the visual fluff."
+  "Options controlling the visual fluff."
   :group 'gnus
   :group 'faces)
 
   "Options related to newsservers and other servers used by Gnus."
   :group 'gnus)
 
+(defgroup gnus-server-visual nil
+  "Highlighting and menus in the server buffer."
+  :group 'gnus-visual
+  :group 'gnus-server)
+
 (defgroup gnus-message '((message custom-group))
   "Composing replies and followups in Gnus."
   :group 'gnus)
 
 (defgroup gnus-meta nil
-  "Meta variables controling major portions of Gnus.
+  "Meta variables controlling major portions of Gnus.
 In general, modifying these variables does not take affect until Gnus
 is restarted, and sometimes reloaded."
   :group 'gnus)
@@ -241,16 +273,19 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Various Various")
   :group 'gnus)
 
+(defgroup gnus-mime nil
+  "Variables for controlling the Gnus MIME interface."
+  :group 'gnus)
+
 (defgroup gnus-exit nil
   "Exiting gnus."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "0.34"
-  "Version number for this version of Gnus.")
-
-(defconst gnus-version (format "Quassia Gnus v%s" gnus-version-number)
-  "Version string for this version of Gnus.")
+(defgroup gnus-fun nil
+  "Frivolous Gnus extensions."
+  :link '(custom-manual "(gnus)Exiting Gnus")
+  :group 'gnus)
 
 (defcustom gnus-inhibit-startup-message nil
   "If non-nil, the startup message will not be displayed.
@@ -264,28 +299,58 @@ be set in `.emacs' instead."
   :group 'gnus-start
   :type 'boolean)
 
-;;; Kludges to help the transition from the old `custom.el'.
+(unless (fboundp 'gnus-group-remove-excess-properties)
+  (defalias 'gnus-group-remove-excess-properties 'ignore))
+
+(unless (fboundp 'gnus-set-text-properties)
+  (defalias 'gnus-set-text-properties 'set-text-properties))
 
 (unless (featurep 'gnus-xmas)
   (defalias 'gnus-make-overlay 'make-overlay)
   (defalias 'gnus-delete-overlay 'delete-overlay)
   (defalias 'gnus-overlay-put 'overlay-put)
   (defalias 'gnus-move-overlay 'move-overlay)
+  (defalias 'gnus-overlay-buffer 'overlay-buffer)
+  (defalias 'gnus-overlay-start 'overlay-start)
   (defalias 'gnus-overlay-end 'overlay-end)
   (defalias 'gnus-extent-detached-p 'ignore)
   (defalias 'gnus-extent-start-open 'ignore)
-  (defalias 'gnus-set-text-properties 'set-text-properties)
-  (defalias 'gnus-group-remove-excess-properties 'ignore)
   (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'identity)
+  (defalias 'gnus-assq-delete-all 'assq-delete-all)
   (defalias 'gnus-add-text-properties 'add-text-properties)
   (defalias 'gnus-put-text-property 'put-text-property)
-  (defalias 'gnus-mode-line-buffer-identification 'identity)
+  (defvar gnus-mode-line-image-cache t)
+  (if (fboundp 'find-image)
+      (defun gnus-mode-line-buffer-identification (line)
+       (let ((str (car-safe line)))
+         (if (and (stringp str)
+                  (string-match "^Gnus:" str))
+             (progn (add-text-properties
+                     0 5
+                     (list 'display
+                           (if (eq t gnus-mode-line-image-cache)
+                               (setq gnus-mode-line-image-cache
+                                     (find-image
+                                      '((:type xpm :file "gnus-pointer.xpm"
+                                               :ascent center)
+                                        (:type xbm :file "gnus-pointer.xbm"
+                                               :ascent center))))
+                             gnus-mode-line-image-cache)
+                           'help-echo (format
+                                       "This is %s, %s."
+                                       gnus-version (gnus-emacs-version)))
+                     str)
+                    (list str))
+           line)))
+    (defalias 'gnus-mode-line-buffer-identification 'identity))
   (defalias 'gnus-characterp 'numberp)
   (defalias 'gnus-deactivate-mark 'deactivate-mark)
   (defalias 'gnus-window-edges 'window-edges)
-  (defalias 'gnus-key-press-event-p 'numberp))
+  (defalias 'gnus-key-press-event-p 'numberp)
+  ;;(defalias 'gnus-decode-rfc1522 'ignore)
+  )
 
 ;; We define these group faces here to avoid the display
 ;; update forced when creating new faces.
@@ -356,6 +421,72 @@ be set in `.emacs' instead."
      ()))
   "Level 3 empty newsgroup face.")
 
+(defface gnus-group-news-4-face
+  '((((class color)
+      (background dark))
+     (:bold t))
+    (((class color)
+      (background light))
+     (:bold t))
+    (t
+     ()))
+  "Level 4 newsgroup face.")
+
+(defface gnus-group-news-4-empty-face
+  '((((class color)
+      (background dark))
+     ())
+    (((class color)
+      (background light))
+     ())
+    (t
+     ()))
+  "Level 4 empty newsgroup face.")
+
+(defface gnus-group-news-5-face
+  '((((class color)
+      (background dark))
+     (:bold t))
+    (((class color)
+      (background light))
+     (:bold t))
+    (t
+     ()))
+  "Level 5 newsgroup face.")
+
+(defface gnus-group-news-5-empty-face
+  '((((class color)
+      (background dark))
+     ())
+    (((class color)
+      (background light))
+     ())
+    (t
+     ()))
+  "Level 5 empty newsgroup face.")
+
+(defface gnus-group-news-6-face
+  '((((class color)
+      (background dark))
+     (:bold t))
+    (((class color)
+      (background light))
+     (:bold t))
+    (t
+     ()))
+  "Level 6 newsgroup face.")
+
+(defface gnus-group-news-6-empty-face
+  '((((class color)
+      (background dark))
+     ())
+    (((class color)
+      (background light))
+     ())
+    (t
+     ()))
+  "Level 6 empty newsgroup face.")
+
 (defface gnus-group-news-low-face
   '((((class color)
       (background dark))
@@ -543,6 +674,33 @@ be set in `.emacs' instead."
      ()))
   "Face used for normal interest ancient articles.")
 
+(defface gnus-summary-high-undownloaded-face
+   '((((class color)
+       (background light))
+      (:bold t :foreground "cyan4"))
+     (((class color) (background dark))
+      (:bold t :foreground "LightGray"))
+     (t (:inverse-video t :bold t)))
+  "Face used for high interest uncached articles.")
+
+(defface gnus-summary-low-undownloaded-face
+   '((((class color)
+       (background light))
+      (:italic t :foreground "cyan4" :bold nil))
+     (((class color) (background dark))
+      (:italic t :foreground "LightGray" :bold nil))
+     (t (:inverse-video t :italic t)))
+  "Face used for low interest uncached articles.")
+
+(defface gnus-summary-normal-undownloaded-face
+   '((((class color)
+       (background light))
+      (:foreground "cyan4" :bold nil))
+     (((class color) (background dark))
+      (:foreground "LightGray" :bold nil))
+     (t (:inverse-video t)))
+  "Face used for normal interest uncached articles.")
+
 (defface gnus-summary-high-unread-face
   '((t
      (:bold t)))
@@ -558,6 +716,11 @@ be set in `.emacs' instead."
      ()))
   "Face used for normal interest unread articles.")
 
+(defface gnus-summary-incorporated-face
+  '((t
+     ()))
+  "Face used for incorporated articles.")
+
 (defface gnus-summary-high-read-face
   '((((class color)
       (background dark))
@@ -596,6 +759,40 @@ be set in `.emacs' instead."
   "Face used for normal interest read articles.")
 
 
+;;;
+;;; Gnus buffers
+;;;
+
+(defvar gnus-buffers nil)
+
+(defun gnus-get-buffer-create (name)
+  "Do the same as `get-buffer-create', but store the created buffer."
+  (or (get-buffer name)
+      (car (push (get-buffer-create name) gnus-buffers))))
+
+(defun gnus-add-buffer ()
+  "Add the current buffer to the list of Gnus buffers."
+  (push (current-buffer) gnus-buffers))
+
+(defmacro gnus-kill-buffer (buffer)
+  "Kill BUFFER and remove from the list of Gnus buffers."
+  `(let ((buf ,buffer))
+     (when (gnus-buffer-exists-p buf)
+       (setq gnus-buffers (delete (get-buffer buf) gnus-buffers))
+       (kill-buffer buf))))
+
+(defun gnus-buffers ()
+  "Return a list of live Gnus buffers."
+  (while (and gnus-buffers
+             (not (buffer-name (car gnus-buffers))))
+    (pop gnus-buffers))
+  (let ((buffers gnus-buffers))
+    (while (cdr buffers)
+      (if (buffer-name (cadr buffers))
+         (pop buffers)
+       (setcdr buffers (cddr buffers)))))
+  gnus-buffers)
+
 ;;; Splash screen.
 
 (defvar gnus-group-buffer "*Group*")
@@ -606,17 +803,17 @@ be set in `.emacs' instead."
 (defface gnus-splash-face
   '((((class color)
       (background dark))
-     (:foreground "ForestGreen"))
+     (:foreground "#888888"))
     (((class color)
       (background light))
-     (:foreground "ForestGreen"))
+     (:foreground "#888888"))
     (t
      ()))
-  "Level 1 newsgroup face.")
+  "Face for the splash screen.")
 
 (defun gnus-splash ()
   (save-excursion
-    (switch-to-buffer (get-buffer-create gnus-group-buffer))
+    (switch-to-buffer (gnus-get-buffer-create gnus-group-buffer))
     (let ((buffer-read-only nil))
       (erase-buffer)
       (unless gnus-inhibit-startup-message
@@ -640,69 +837,267 @@ be set in `.emacs' instead."
 
 (defvar gnus-simple-splash nil)
 
+;;(format "%02x%02x%02x" 114 66 20) "724214"
+
+(defvar gnus-logo-color-alist
+  '((flame "#cc3300" "#ff2200")
+    (pine "#c0cc93" "#f8ffb8")
+    (moss "#a1cc93" "#d2ffb8")
+    (irish "#04cc90" "#05ff97")
+    (sky "#049acc" "#05deff")
+    (tin "#6886cc" "#82b6ff")
+    (velvet "#7c68cc" "#8c82ff")
+    (grape "#b264cc" "#cf7df")
+    (labia "#cc64c2" "#fd7dff")
+    (berry "#cc6485" "#ff7db5")
+    (dino "#724214" "#1e3f03")
+    (oort "#cccccc" "#888888")
+    (storm "#666699" "#99ccff")
+    (pdino "#9999cc" "#99ccff")
+    (purp "#9999cc" "#666699")
+    (no "#000000" "#ff0000")
+    (neutral "#b4b4b4" "#878787")
+    (september "#bf9900" "#ffcc00"))
+  "Color alist used for the Gnus logo.")
+
+(defcustom gnus-logo-color-style 'oort
+  "*Color styles used for the Gnus logo."
+  :type `(choice ,@(mapcar (lambda (elem) (list 'const (car elem)))
+                          gnus-logo-color-alist))
+  :group 'gnus-xmas)
+
+(defvar gnus-logo-colors
+  (cdr (assq gnus-logo-color-style gnus-logo-color-alist))
+  "Colors used for the Gnus logo.")
+
 (defun gnus-group-startup-message (&optional x y)
   "Insert startup message in current buffer."
   ;; Insert the message.
   (erase-buffer)
-  (insert
-   (format "              %s
-          _    ___ _             _
-          _ ___ __ ___  __    _ ___
-          __   _     ___    __  ___
-              _           ___     _
-             _  _ __             _
-             ___   __            _
-                   __           _
-                    _      _   _
-                   _      _    _
-                      _  _    _
-                  __  ___
-                 _   _ _     _
-                _   _
-              _    _
-             _    _
-            _
-          __
+  (cond
+   ((and (fboundp 'find-image)
+        (display-graphic-p)
+        (let* ((bg (face-background 'default))
+               (fg (face-foreground 'gnus-splash-face))
+               (data-directory (nnheader-find-etc-directory "gnus"))
+               (image (find-image
+                       `((:type xpm :file "gnus.xpm"
+                                :color-symbols
+                                (("thing" . ,(car gnus-logo-colors))
+                                 ("shadow" . ,(cadr gnus-logo-colors))
+                                 ("oort" . "#eeeeee")
+                                 ("background" . ,bg)))
+                         (:type pbm :file "gnus.pbm"
+                                ;; Account for the pbm's blackground.
+                                :background ,bg :foreground ,fg)
+                         (:type xbm :file "gnus.xbm"
+                                ;; Account for the xbm's blackground.
+                                :background ,bg :foreground ,fg)))))
+          (when image
+            (insert
+             (propertize
+              (concat gnus-product-name " " gnus-version-number
+                      (if (zerop (string-to-number gnus-revision-number))
+                          ""
+                        (concat " (r" gnus-revision-number ")"))
+                      " based on " gnus-original-product-name " v"
+                      gnus-original-version-number)
+              'face `(variable-pitch :background ,bg :foreground ,fg)))
+            (let ((fill-column (window-width)))
+              (center-region (point-min) (point)))
+            (let ((size (image-size image)))
+              (insert-char ?\n (max 1 (round (- (window-height)
+                                                (or y (cdr size))) 2)))
+              (insert
+               (propertize " " 'display
+                           `(space :align-to
+                                   ,(max 0 (round (- (window-width)
+                                                     (or x (car size))) 2)))))
+              (insert-image image))
+            (setq gnus-simple-splash nil)
+            t))))
+   (t
+    (insert "
+         _    ___ _             _
+         _ ___ __ ___  __    _ ___
+         __   _     ___    __  ___
+             _           ___     _
+            _  _ __             _
+            ___   __            _
+                  __           _
+                   _      _   _
+                  _      _    _
+                     _  _    _
+                 __  ___
+                _   _ _     _
+               _   _
+             _    _
+            _    _
+           _
+         __
 
 "
-           ""))
-  ;; And then hack it.
-  (gnus-indent-rigidly (point-min) (point-max)
-                      (/ (max (- (window-width) (or x 46)) 0) 2))
-  (goto-char (point-min))
-  (forward-line 1)
-  (let* ((pheight (count-lines (point-min) (point-max)))
-        (wheight (window-height))
-        (rest (- wheight pheight)))
-    (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))
-  ;; Fontify some.
-  (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)
+           )
+    (goto-char (point-min))
+    (insert gnus-product-name " " gnus-version-number
+           (if (zerop (string-to-number gnus-revision-number))
+               ""
+             (concat " (r" gnus-revision-number ")"))
+           " based on " gnus-original-product-name " v"
+           gnus-original-version-number)
+    (insert-char ?\  (prog1
+                        (max 0 (/ (- (window-width) (point)) 2))
+                      (goto-char (point-min))))
+    (forward-line 1)
+    ;; And then hack it.
+    (gnus-indent-rigidly (point) (point-max)
+                        (/ (max (- (window-width) (or x 46)) 0) 2))
+    (goto-char (point-min))
+    (forward-line 1)
+    (let* ((pheight (count-lines (point-min) (point-max)))
+          (wheight (window-height))
+          (rest (- wheight pheight)))
+      (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))
+    ;; Fontify some.
+    (put-text-property (point-min) (point-max) 'face 'gnus-splash-face)
+    (setq gnus-simple-splash t)))
   (goto-char (point-min))
   (setq mode-line-buffer-identification (concat " " gnus-version))
-  (setq gnus-simple-splash t)
   (set-buffer-modified-p t))
 
 (eval-when (load)
   (let ((command (format "%s" this-command)))
-    (when (and (string-match "gnus" command)
-              (not (string-match "gnus-other-frame" command)))
-      (gnus-splash))))
+    (if (and (string-match "gnus" command)
+            (not (string-match "gnus-other-frame" command)))
+       (gnus-splash)
+      (gnus-get-buffer-create gnus-group-buffer))))
 
 ;;; Do the rest.
 
-(require 'custom)
 (require 'gnus-util)
 (require 'nnheader)
 
+(defcustom gnus-parameters nil
+  "Alist of group parameters.
+
+For example:
+   ((\"mail\\\\..*\"  (gnus-show-threads nil)
+                 (gnus-use-scoring nil)
+                 (gnus-summary-line-format
+                       \"%U%R%z%I%(%[%d:%ub%-23,23f%]%) %s\\n\")
+                 (gcc-self . t)
+                 (display . all))
+     (\"mail\\\\.me\" (gnus-use-scoring  t))
+     (\"list\\\\..*\" (total-expire . t)
+                 (broken-reply-to . t)))"
+  :group 'gnus-group-various
+  :type '(repeat (cons regexp
+                      (repeat sexp))))
+
+(defvar gnus-group-parameters-more nil)
+
+(defvar gnus-colon-keywords
+  (eval-when-compile
+    (when (boundp 'dgnushack-colon-keywords)
+      (symbol-value 'dgnushack-colon-keywords)))
+  "List of the colon keywords should be bound at run-time.  This variable
+defaults to a proper value only if this file is byte-compiled by make.")
+
+(dolist (keyword gnus-colon-keywords)
+  (set keyword keyword))
+
+(defmacro gnus-define-group-parameter (param &rest rest)
+  "Define a group parameter PARAM.
+REST is a plist of following:
+:type               One of `bool', `list' or nil.
+:function           The name of the function.
+:function-document  The documentation of the function.
+:parameter-type     The type for customizing the parameter.
+:parameter-document The documentation for the parameter.
+:variable           The name of the variable.
+:variable-document  The documentation for the variable.
+:variable-group     The group for customizing the variable.
+:variable-type      The type for customizing the variable.
+:variable-default   The default value of the variable."
+  (let* ((type (plist-get rest :type))
+        (parameter-type (plist-get rest :parameter-type))
+        (parameter-document (plist-get rest :parameter-document))
+        (function (or (plist-get rest :function)
+                      (intern (format "gnus-parameter-%s" param))))
+        (function-document (or (plist-get rest :function-document) ""))
+        (variable (or (plist-get rest :variable)
+                      (intern (format "gnus-parameter-%s-alist" param))))
+        (variable-document (or (plist-get rest :variable-document) ""))
+        (variable-group (plist-get rest :variable-group))
+        (variable-type (or (plist-get rest :variable-type)
+                           `(quote (repeat
+                                    (list (regexp :tag "Group")
+                                          ,(car (cdr parameter-type)))))))
+        (variable-default (plist-get rest :variable-default)))
+    (list
+     'progn
+     `(defcustom ,variable ,variable-default
+       ,variable-document
+       :group 'gnus-group-parameter
+       :group ',variable-group
+       :type ,variable-type)
+     `(setq gnus-group-parameters-more
+           (delq (assq ',param gnus-group-parameters-more)
+                 gnus-group-parameters-more))
+     `(add-to-list 'gnus-group-parameters-more
+                  (list ',param
+                        ,parameter-type
+                        ,parameter-document))
+     (if (eq type 'bool)
+        `(defun ,function (name)
+           ,function-document
+           (let ((params (gnus-group-find-parameter name))
+                 val)
+             (cond
+              ((memq ',param params)
+               t)
+              ((setq val (assq ',param params))
+               (cdr val))
+              ((stringp ,variable)
+               (string-match ,variable name))
+              (,variable
+               (let ((alist ,variable)
+                     elem value)
+                 (while (setq elem (pop alist))
+                   (when (and name
+                              (string-match (car elem) name))
+                     (setq alist nil
+                           value (cdr elem))))
+                 (if (consp value) (car value) value))))))
+       `(defun ,function (name)
+         ,function-document
+         (and name
+              (or (gnus-group-find-parameter name ',param ,(and type t))
+                  (let ((alist ,variable)
+                        elem value)
+                    (while (setq elem (pop alist))
+                      (when (and name
+                                 (string-match (car elem) name))
+                        (setq alist nil
+                              value (cdr elem))))
+                    ,(if type
+                         'value
+                       '(if (consp value) (car value) value))))))))))
+
 (defcustom gnus-home-directory "~/"
   "Directory variable that specifies the \"home\" directory.
-All other Gnus path variables are initialized from this variable."
+All other Gnus file and directory variables are initialized from this variable."
   :group 'gnus-files
   :type 'directory)
 
 (defcustom gnus-directory (or (getenv "SAVEDIR")
-                     (nnheader-concat gnus-home-directory "News/"))
-  "*Directory variable from which all other Gnus file variables are derived."
+                             (nnheader-concat gnus-home-directory "News/"))
+  "*Directory variable from which all other Gnus file variables are derived.
+
+Note that Gnus is mostly loaded when the `.gnus.el' file is read.
+This means that other directory variables that are initialized from
+this variable won't be set properly if you set this variable in `.gnus.el'.
+Set this variable in `.emacs' instead."
   :group 'gnus-files
   :type 'directory)
 
@@ -737,44 +1132,39 @@ used to 899, you would say something along these lines:
   :group 'gnus-server
   :type 'file)
 
-;; This function is used to check both the environment variable
-;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
-;; an nntp server name default.
 (defun gnus-getenv-nntpserver ()
+  "Find default nntp server.
+Check the NNTPSERVER environment variable and the
+`gnus-nntpserver-file' file."
   (or (getenv "NNTPSERVER")
       (and (file-readable-p gnus-nntpserver-file)
-          (save-excursion
-            (set-buffer (get-buffer-create " *gnus nntp*"))
-            (buffer-disable-undo (current-buffer))
+          (with-temp-buffer
             (insert-file-contents gnus-nntpserver-file)
             (let ((name (buffer-string)))
-              (prog1
-                  (if (string-match "^[ \t\n]*$" name)
-                      nil
-                    name)
-                (kill-buffer (current-buffer))))))))
+              (unless (string-match "\\`[ \t\n]*$" name)
+                name))))))
 
 (defcustom gnus-select-method
   (condition-case nil
-    (nconc
-     (list 'nntp (or (condition-case nil
-                        (gnus-getenv-nntpserver)
-                      (error nil))
-                    (when (and gnus-default-nntp-server
-                               (not (string= gnus-default-nntp-server "")))
-                      gnus-default-nntp-server)
-                    "news"))
-     (if (or (null gnus-nntp-service)
-            (equal gnus-nntp-service "nntp"))
-        nil
-       (list gnus-nntp-service)))
+      (nconc
+       (list 'nntp (or (condition-case nil
+                          (gnus-getenv-nntpserver)
+                        (error nil))
+                      (when (and gnus-default-nntp-server
+                                 (not (string= gnus-default-nntp-server "")))
+                        gnus-default-nntp-server)
+                      "news"))
+       (if (or (null gnus-nntp-service)
+              (equal gnus-nntp-service "nntp"))
+          nil
+        (list gnus-nntp-service)))
     (error nil))
-  "*Default method for selecting a newsgroup.
+  "Default method for selecting a newsgroup.
 This variable should be a list, where the first element is how the
 news is to be fetched, the second is the address.
 
-For instance, if you want to get your news via NNTP from
-\"flab.flab.edu\", you could say:
+For instance, if you want to get your news via \"flab.flab.edu\" using
+NNTP, you could say:
 
 \(setq gnus-select-method '(nntp \"flab.flab.edu\"))
 
@@ -789,23 +1179,13 @@ see the manual for details."
   :group 'gnus-server
   :type 'gnus-select-method)
 
-(defcustom gnus-message-archive-method
-  `(nnfolder
-    "archive"
-    (nnfolder-directory ,(nnheader-concat message-directory "archive"))
-    (nnfolder-active-file
-     ,(nnheader-concat message-directory "archive/active"))
-    (nnfolder-get-new-mail nil)
-    (nnfolder-inhibit-expiry t))
+(defcustom gnus-message-archive-method "archive"
   "*Method used for archiving messages you've sent.
-This should be a mail method.
-
-It's probably not a very effective to change this variable once you've
-run Gnus once.  After doing that, you must edit this server from the
-server buffer."
+This should be a mail method."
   :group 'gnus-server
   :group 'gnus-message
-  :type 'gnus-select-method)
+  :type '(choice (const :tag "Default archive method" "archive")
+                gnus-select-method))
 
 (defcustom gnus-message-archive-group nil
   "*Name of the group in which to save the messages you've written.
@@ -818,9 +1198,9 @@ If you want to save your mail in one group and the news articles you
 write in another group, you could say something like:
 
  \(setq gnus-message-archive-group
-        '((if (message-news-p)
-              \"misc-news\"
-            \"misc-mail\")))
+       '((if (message-news-p)
+             \"misc-news\"
+           \"misc-mail\")))
 
 Normally the group names returned by this variable should be
 unprefixed -- which implicitly means \"store on the archive server\".
@@ -829,6 +1209,8 @@ that case, just return a fully prefixed name of the group --
 \"nnml+private:mail.misc\", for instance."
   :group 'gnus-message
   :type '(choice (const :tag "none" nil)
+                function
+                sexp
                 string))
 
 (defcustom gnus-secondary-servers nil
@@ -851,12 +1233,12 @@ variable instead."
 This is a list where each element is a complete select method (see
 `gnus-select-method').
 
-If, for instance, you want to read your mail with the nnml backend,
+If, for instance, you want to read your mail with the nnml back end,
 you could set this variable:
 
 \(setq gnus-secondary-select-methods '((nnml \"\")))"
-:group 'gnus-server
-:type '(repeat gnus-select-method))
+  :group 'gnus-server
+  :type '(repeat gnus-select-method))
 
 (defvar gnus-backup-default-subscribed-newsgroups
   '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
@@ -866,7 +1248,7 @@ Should be set in paths.el, and shouldn't be touched by the user.")
 (defcustom gnus-local-domain nil
   "Local domain name without a host name.
 The DOMAINNAME environment variable is used instead if it is defined.
-If the `system-name' function returns the full Internet name, there is
+If the function `system-name' returns the full Internet name, there is
 no need to set this variable."
   :group 'gnus-message
   :type '(choice (const :tag "default" nil)
@@ -885,21 +1267,35 @@ articles by Message-ID is painfully slow.  By setting this method to an
 nntp method, you might get acceptable results.
 
 The value of this variable must be a valid select method as discussed
-in the documentation of `gnus-select-method'."
+in the documentation of `gnus-select-method'.
+
+It can also be a list of select methods, as well as the special symbol
+`current', which means to use the current select method.  If it is a
+list, Gnus will try all the methods in the list until it finds a match."
   :group 'gnus-server
   :type '(choice (const :tag "default" nil)
-                gnus-select-method))
+                (const current)
+                (const :tag "Google" (nnweb "refer" (nnweb-type google)))
+                gnus-select-method
+                (repeat :menu-tag "Try multiple"
+                        :tag "Multiple"
+                        :value (current (nnweb "refer" (nnweb-type google)))
+                        (choice :tag "Method"
+                                (const current)
+                                (const :tag "Google"
+                                       (nnweb "refer" (nnweb-type google)))
+                                gnus-select-method))))
 
 (defcustom gnus-group-faq-directory
   '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
-    "/ftp@sunsite.auc.dk:/pub/usenet/"
     "/ftp@sunsite.doc.ic.ac.uk:/pub/usenet/news-faqs/"
     "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
     "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
+    "/ftp@ftp.pasteur.fr:/pub/FAQ/"
     "/ftp@rtfm.mit.edu:/pub/usenet/"
     "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
     "/ftp@ftp.sunet.se:/pub/usenet/"
-    "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
+    "/ftp@nctuccca.nctu.edu.tw:/pub/Documents/rtfm/usenet-by-group/"
     "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
     "/ftp@ftp.hk.super.net:/mirror/faqs/")
   "*Directory where the group FAQs are stored.
@@ -920,16 +1316,50 @@ If the default site is too slow, try one of these:
                  ftp.seas.gwu.edu               /pub/rtfm
                  rtfm.mit.edu                   /pub/usenet
    Europe:       ftp.uni-paderborn.de           /pub/FAQ
-                  src.doc.ic.ac.uk               /usenet/news-FAQS
+                 src.doc.ic.ac.uk               /usenet/news-FAQS
                  ftp.sunet.se                   /pub/usenet
-                 sunsite.auc.dk                 /pub/usenet
-   Asia:         nctuccca.edu.tw                /USENET/FAQ
+                 ftp.pasteur.fr                 /pub/FAQ
+   Asia:         nctuccca.nctu.edu.tw           /pub/Documents/rtfm/usenet-by-group/
                  hwarang.postech.ac.kr          /pub/usenet
                  ftp.hk.super.net               /mirror/faqs"
   :group 'gnus-group-various
   :type '(choice directory
                 (repeat directory)))
 
+(defcustom gnus-group-charter-alist
+  '(("no" . (concat "http://no.news-admin.org/charter/" name ".txt"))
+    ("de" . (concat "http://purl.net/charta/" name ".html"))
+    ("dk" . (concat "http://www.usenet.dk/grupper.pl?get=" name))
+    ("england" . (concat "http://england.news-admin.org/charters/" name))
+    ("fr" . (concat "http://www.usenet-fr.net/fur/chartes/" name ".html"))
+    ("europa" . (concat "http://www.europa.usenet.eu.org/chartas/charta-en-"
+                       (gnus-replace-in-string name "europa\\." "") ".html"))
+    ("nl" . (concat "http://www.xs4all.nl/~sister/usenet/charters/" name))
+    ("aus" . (concat "http://aus.news-admin.org/groupinfo.cgi/" name))
+    ("pl" . (concat "http://www.usenet.pl/opisy/" name))
+    ("ch" . (concat "http://www.use-net.ch/Usenet/charter.html#" name))
+    ("at" . (concat "http://www.usenet.at/chartas/" name "/charta"))
+    ("uk" . (concat "http://www.usenet.org.uk/" name ".html"))
+    ("dfw" . (concat "http://www.cirr.com/dfw/charters/" name ".html"))
+    ("se" . (concat "http://www.usenet-se.net/Reglementen/"
+                   (gnus-replace-in-string name "\\." "_") ".html"))
+    ("milw" . (concat "http://usenet.mil.wi.us/"
+                     (gnus-replace-in-string name "milw\\." "") "-charter"))
+    ("ca" . (concat "http://www.sbay.org/ca/charter-" name ".html"))
+    ("netins" . (concat "http://www.netins.net/usenet/charter/"
+                       (gnus-replace-in-string name "\\." "-") "-charter.html")))
+  "*An alist of (HIERARCHY . FORM) pairs used to construct the URL of a charter.
+When FORM is evaluated `name' is bound to the name of the group."
+  :group 'gnus-group-various
+  :type '(repeat (cons (string :tag "Hierarchy") (sexp :tag "Form"))))
+
+(defcustom gnus-group-fetch-control-use-browse-url nil
+  "*Non-nil means that control messages are displayed using `browse-url'.
+Otherwise they are fetched with ange-ftp and displayed in an ephemeral
+group."
+  :group 'gnus-group-various
+  :type 'boolean)
+
 (defcustom gnus-use-cross-reference t
   "*Non-nil means that cross referenced articles will be marked as read.
 If nil, ignore cross references.  If t, mark articles as read in
@@ -947,17 +1377,14 @@ newsgroups."
   :group 'gnus-summary-marks
   :type 'character)
 
-(defcustom gnus-asynchronous nil
-  "*If non-nil, Gnus will supply backends with data needed for async article fetching."
-  :group 'gnus-asynchronous
-  :type 'boolean)
-
 (defcustom gnus-large-newsgroup 200
   "*The number of articles which indicates a large newsgroup.
 If the number of articles in a newsgroup is greater than this value,
-confirmation is required for selecting the newsgroup."
+confirmation is required for selecting the newsgroup.
+If it is nil, no confirmation is required."
   :group 'gnus-group-select
-  :type 'integer)
+  :type '(choice (const :tag "No limit" nil)
+                integer))
 
 (defcustom gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
   "*Non-nil means that the default name of a file to save articles in is the group name.
@@ -973,7 +1400,14 @@ Note that the default for this variable varies according to what system
 type you're using.  On `usg-unix-v' and `xenix' this variable defaults
 to nil while on all other systems it defaults to t."
   :group 'gnus-start
-  :type 'boolean)
+  :type '(radio (sexp :format "Non-nil\n"
+                     :match (lambda (widget value)
+                              (and value (not (listp value))))
+                     :value t)
+               (const nil)
+               (checklist (const :format "%v " not-score)
+                          (const :format "%v " not-save)
+                          (const not-kill))))
 
 (defcustom gnus-kill-files-directory gnus-directory
   "*Name of the directory where kill files will be stored (default \"~/News\")."
@@ -1022,7 +1456,7 @@ cache to the full extent of the law."
   :group 'gnus-meta
   :type 'boolean)
 
-(defcustom gnus-keep-backlog nil
+(defcustom gnus-keep-backlog 20
   "*If non-nil, Gnus will keep read articles for later re-retrieval.
 If it is a number N, then Gnus will only keep the last N articles
 read.  If it is neither nil nor a number, Gnus will keep all read
@@ -1043,21 +1477,11 @@ articles.  This is not a good idea."
   :group 'gnus-meta
   :type 'boolean)
 
-(defcustom gnus-use-demon nil
-  "If non-nil, Gnus might use some demons."
-  :group 'gnus-meta
-  :type 'boolean)
-
 (defcustom gnus-use-scoring t
   "*If non-nil, enable scoring."
   :group 'gnus-meta
   :type 'boolean)
 
-(defcustom gnus-use-picons nil
-  "*If non-nil, display picons."
-  :group 'gnus-meta
-  :type 'boolean)
-
 (defcustom gnus-summary-prepare-exit-hook
   '(gnus-summary-expire-articles)
   "*A hook called when preparing to exit from the summary buffer.
@@ -1066,7 +1490,7 @@ It calls `gnus-summary-expire-articles' by default."
   :type 'hook)
 
 (defcustom gnus-novice-user t
-  "*Non-nil means that you are a usenet novice.
+  "*Non-nil means that you are a Usenet novice.
 If non-nil, verbose messages may be displayed and confirmations may be
 required."
   :group 'gnus-meta
@@ -1090,14 +1514,15 @@ commands will still require prompting."
   :type 'boolean)
 
 (defcustom gnus-extract-address-components 'gnus-extract-address-components
-  "*Function for extracting address components from a From header.
-Two pre-defined function exist: `gnus-extract-address-components',
-which is the default, quite fast, and too simplistic solution, and
+  "Function for extracting address components from a From header.
+Three pre-defined functions exist: `gnus-extract-address-components',
+which is the default, quite fast, and too simplistic solution,
 `mail-extract-address-components', which works much better, but is
-slower."
+slower, and `std11-extract-address-components'."
   :group 'gnus-summary-format
   :type '(radio (function-item gnus-extract-address-components)
                (function-item mail-extract-address-components)
+               (function-item std11-extract-address-components)
                (function :tag "Other")))
 
 (defcustom gnus-carpal nil
@@ -1106,7 +1531,7 @@ slower."
   :type 'boolean)
 
 (defcustom gnus-shell-command-separator ";"
-  "String used to separate to shell commands."
+  "String used to separate shell commands."
   :group 'gnus-files
   :type 'string)
 
@@ -1115,7 +1540,7 @@ slower."
     ("nnspool" post address)
     ("nnvirtual" post-mail virtual prompt-address)
     ("nnmbox" mail respool address)
-    ("nnml" mail respool address)
+    ("nnml" post-mail respool address)
     ("nnmh" mail respool address)
     ("nndir" post-mail prompt-address physical-address)
     ("nneething" none address prompt-address physical-address)
@@ -1125,10 +1550,19 @@ slower."
     ("nnsoup" post-mail address)
     ("nndraft" post-mail)
     ("nnfolder" mail respool address)
-    ("nngateway" none address prompt-address physical-address)
+    ("nngateway" post-mail address prompt-address physical-address)
     ("nnweb" none)
+    ("nngoogle" post)
+    ("nnslashdot" post)
+    ("nnultimate" none)
+    ("nnrss" none)
+    ("nnwfm" none)
+    ("nnwarchive" none)
     ("nnlistserv" none)
-    ("nnagent" post-mail))
+    ("nnagent" post-mail)
+    ("nnimap" post-mail address prompt-address physical-address)
+    ("nnmaildir" mail respool address)
+    ("nnnil" none))
   "*An alist of valid select methods.
 The first element of each list lists should be a string with the name
 of the select method.  The other elements may be the category of
@@ -1149,18 +1583,27 @@ this variable.  I think."
                                   (const :format "%v " virtual)
                                   (const respool)))))
 
-(define-widget 'gnus-select-method 'list
-  "Widget for entering a select method."
-  :args `((choice :tag "Method"
-                 ,@(mapcar (lambda (entry)
-                             (list 'const :format "%v\n"
-                                   (intern (car entry))))
-                           gnus-valid-select-methods))
-         (string :tag "Address")
-         (editable-list  :inline t
-                         (list :format "%v"
-                               variable
-                               (sexp :tag "Value")))))
+(defun gnus-redefine-select-method-widget ()
+  "Recomputes the select-method widget based on the value of
+`gnus-valid-select-methods'."
+  (define-widget 'gnus-select-method 'list
+    "Widget for entering a select method."
+    :value '(nntp "")
+    :tag "Select Method"
+    :args `((choice :tag "Method"
+                   ,@(mapcar (lambda (entry)
+                               (list 'const :format "%v\n"
+                                     (intern (car entry))))
+                             gnus-valid-select-methods)
+                   (symbol :tag "other"))
+           (string :tag "Address")
+           (repeat :tag "Options"
+                   :inline t
+                   (list :format "%v"
+                         variable
+                         (sexp :tag "Value"))))))
+
+(gnus-redefine-select-method-widget)
 
 (defcustom gnus-updated-mode-lines '(group article summary tree)
   "List of buffers that should update their mode lines.
@@ -1178,29 +1621,582 @@ If this variable is nil, screen refresh may be quicker."
 (defcustom gnus-mode-non-string-length nil
   "*Max length of mode-line non-string contents.
 If this is nil, Gnus will take space as is needed, leaving the rest
-of the modeline intact.  Note that the default of nil is unlikely
+of the mode line intact.  Note that the default of nil is unlikely
 to be desirable; see the manual for further details."
   :group 'gnus-various
   :type '(choice (const nil)
                 integer))
 
-(defcustom gnus-auto-expirable-newsgroups nil
-  "*Groups in which to automatically mark read articles as expirable.
+;; There should be special validation for this.
+(define-widget 'gnus-email-address 'string
+  "An email address.")
+
+(gnus-define-group-parameter
+ to-address
+ :function-document
+ "Return GROUP's to-address."
+ :variable-document
+ "*Alist of group regexps and correspondent to-addresses."
+ :parameter-type '(gnus-email-address :tag "To Address")
+ :parameter-document "\
+This will be used when doing followups and posts.
+
+This is primarily useful in mail groups that represent closed
+mailing lists--mailing lists where it's expected that everybody that
+writes to the mailing list is subscribed to it.  Since using this
+parameter ensures that the mail only goes to the mailing list itself,
+it means that members won't receive two copies of your followups.
+
+Using `to-address' will actually work whether the group is foreign or
+not.  Let's say there's a group on the server that is called
+`fa.4ad-l'.  This is a real newsgroup, but the server has gotten the
+articles from a mail-to-news gateway.  Posting directly to this group
+is therefore impossible--you have to send mail to the mailing list
+address instead.
+
+The gnus-group-split mail splitting mechanism will behave as if this
+address was listed in gnus-group-split Addresses (see below).")
+
+(gnus-define-group-parameter
+ to-list
+ :function-document
+ "Return GROUP's to-list."
+ :variable-document
+ "*Alist of group regexps and correspondent to-lists."
+ :parameter-type '(gnus-email-address :tag "To List")
+ :parameter-document "\
+This address will be used when doing a `a' in the group.
+
+It is totally ignored when doing a followup--except that if it is
+present in a news group, you'll get mail group semantics when doing
+`f'.
+
+The gnus-group-split mail splitting mechanism will behave as if this
+address was listed in gnus-group-split Addresses (see below).")
+
+(gnus-define-group-parameter
+ subscribed
+ :type bool
+ :function-document
+ "Return GROUP's subscription status."
+ :variable-document
+ "*Groups which are automatically considered subscribed."
+ :parameter-type '(const :tag "Subscribed" t)
+ :parameter-document "\
+Gnus assumed that you are subscribed to the To/List address.
+
+When constructing a list of subscribed groups using
+`gnus-find-subscribed-addresses', Gnus includes the To address given
+above, or the list address (if the To address has not been set).")
+
+(gnus-define-group-parameter
+ auto-expire
+ :type bool
+ :function gnus-group-auto-expirable-p
+ :function-document
+ "Check whether GROUP is auto-expirable or not."
+ :variable gnus-auto-expirable-newsgroups
+ :variable-default nil
+ :variable-document
+ "*Groups in which to automatically mark read articles as expirable.
 If non-nil, this should be a regexp that should match all groups in
 which to perform auto-expiry.  This only makes sense for mail groups."
-  :group 'nnmail-expire
-  :type '(choice (const nil)
-                regexp))
-
-(defcustom gnus-total-expirable-newsgroups nil
-  "*Groups in which to perform expiry of all read articles.
+ :variable-group nnmail-expire
+ :variable-type '(choice (const nil)
+                        regexp)
+ :parameter-type '(const :tag "Automatic Expire" t)
+ :parameter-document
+ "All articles that are read will be marked as expirable.")
+
+(gnus-define-group-parameter
+ total-expire
+ :type bool
+ :function gnus-group-total-expirable-p
+ :function-document
+ "Check whether GROUP is total-expirable or not."
+ :variable gnus-total-expirable-newsgroups
+ :variable-default nil
+ :variable-document
+ "*Groups in which to perform expiry of all read articles.
 Use with extreme caution.  All groups that match this regexp will be
 expiring - which means that all read articles will be deleted after
 \(say) one week.        (This only goes for mail groups and the like, of
 course.)"
-  :group 'nnmail-expire
-  :type '(choice (const nil)
-                regexp))
+ :variable-group nnmail-expire
+ :variable-type '(choice (const nil)
+                        regexp)
+ :parameter-type '(const :tag "Total Expire" t)
+ :parameter-document
+ "All read articles will be put through the expiry process
+
+This happens even if they are not marked as expirable.
+Use with caution.")
+
+(gnus-define-group-parameter
+ charset
+ :function-document
+ "Return the default charset of GROUP."
+ :variable gnus-group-charset-alist
+ :variable-default
+ '(("\\(^\\|:\\)hk\\>\\|\\(^\\|:\\)tw\\>\\|\\<big5\\>" cn-big5)
+   ("\\(^\\|:\\)cn\\>\\|\\<chinese\\>" cn-gb-2312)
+   ("\\(^\\|:\\)fj\\>\\|\\(^\\|:\\)japan\\>" iso-2022-jp-2)
+   ("\\(^\\|:\\)tnn\\>\\|\\(^\\|:\\)pin\\>\\|\\(^\\|:\\)sci.lang.japan" iso-2022-7bit)
+   ("\\(^\\|:\\)relcom\\>" koi8-r)
+   ("\\(^\\|:\\)fido7\\>" koi8-r)
+   ("\\(^\\|:\\)\\(cz\\|hun\\|pl\\|sk\\|hr\\)\\>" iso-8859-2)
+   ("\\(^\\|:\\)israel\\>" iso-8859-1)
+   ("\\(^\\|:\\)han\\>" euc-kr)
+   ("\\(^\\|:\\)alt.chinese.text.big5\\>" chinese-big5)
+   ("\\(^\\|:\\)soc.culture.vietnamese\\>" vietnamese-viqr)
+   ("\\(^\\|:\\)\\(comp\\|rec\\|alt\\|sci\\|soc\\|news\\|gnu\\|bofh\\)\\>" iso-8859-1))
+ :variable-document
+ "Alist of regexps (to match group names) and default charsets to be used when reading."
+ :variable-group gnus-charset
+ :variable-type '(repeat (list (regexp :tag "Group")
+                              (symbol :tag "Charset")))
+ :parameter-type '(symbol :tag "Charset")
+ :parameter-document "\
+The default charset to use in the group.")
+
+(gnus-define-group-parameter
+ post-method
+ :type list
+ :function-document
+ "Return a posting method for GROUP."
+ :variable gnus-post-method-alist
+ :variable-document
+ "Alist of regexps (to match group names) and method to be used when
+posting an article."
+ :variable-group gnus-group-foreign
+ :parameter-type
+ '(choice :tag "Posting Method"
+         (const :tag "Use native server" native)
+         (const :tag "Use current server" current)
+         (list :convert-widget
+               (lambda (widget)
+                 (list 'sexp :tag "Methods"
+                       :value gnus-select-method))))
+ :parameter-document
+ "Posting method for this group.")
+
+(gnus-define-group-parameter
+ large-newsgroup-initial
+ :type integer
+ :function-document
+ "Return GROUP's initial input of the number of articles."
+ :variable-document
+ "*Alist of group regexps and its initial input of the number of articles."
+ :parameter-type '(choice :tag "Initial Input for Large Newsgroup"
+                         (const :tag "All" nil)
+                         (integer))
+ :parameter-document "\
+
+This number will be prompted as the initial value of the number of
+articles to list when the group is a large newsgroup (see
+`gnus-large-newsgroup').  If it is nil, the default value is the
+total number of articles in the group.")
+
+;; The Gnus registry's ignored groups
+(gnus-define-group-parameter
+ registry-ignore
+ :type list
+ :function-document
+ "Whether this group should be ignored by the registry."
+ :variable gnus-registry-ignored-groups
+ :variable-default nil
+ :variable-document
+ "*Groups in which the registry should be turned off."
+ :variable-group gnus-registry
+ :variable-type '(repeat
+                 (list
+                  (regexp :tag "Group Name Regular Expression")
+                  (boolean :tag "Ignored")))
+ :parameter-type '(boolean :tag "Group Ignored by the Registry")
+ :parameter-document
+ "Whether the Gnus Registry should ignore this group.")
+
+;; group parameters for spam processing added by Ted Zlatanov <tzz@lifelogs.com>
+(defcustom gnus-install-group-spam-parameters t
+  "*Disable the group parameters for spam detection.
+Enable if `G c' in XEmacs is giving you trouble, and make sure to submit a bug report."
+  :type 'boolean
+  :group 'gnus-start)
+
+(when gnus-install-group-spam-parameters
+  (defvar gnus-group-spam-classification-spam t
+    "Spam group classification (requires spam.el).
+This group contains spam messages.  On summary entry, unread messages
+will be marked as spam.  On summary exit, the specified spam
+processors will be invoked on spam-marked messages, then those
+messages will be expired, so the spam processor will only see a
+spam-marked message once.")
+
+  (defvar gnus-group-spam-classification-ham 'ask
+    "The ham value for the spam group parameter (requires spam.el).
+On summary exit, the specified ham processors will be invoked on
+ham-marked messages.  Exercise caution, since the ham processor will
+see the same message more than once because there is no ham message
+registry.")
+
+  (gnus-define-group-parameter
+   spam-contents
+   :type list
+   :function-document
+   "The spam type (spam, ham, or neither) of the group."
+   :variable gnus-spam-newsgroup-contents
+   :variable-default nil
+   :variable-document
+   "*Groups in which to automatically mark new articles as spam on
+summary entry.  If non-nil, this should be a list of group name
+regexps that should match all groups in which to do automatic spam
+tagging, associated with a classification (spam, ham, or neither).
+This only makes sense for mail groups."
+   :variable-group spam
+   :variable-type '(repeat
+                   (list :tag "Group contents spam/ham classification"
+                         (regexp :tag "Group")
+                         (choice
+                          (variable-item gnus-group-spam-classification-spam)
+                          (variable-item gnus-group-spam-classification-ham)
+                          (const :tag "Unclassified" nil))))
+
+   :parameter-type '(list :tag "Group contents spam/ham classification"
+                         (choice :tag "Group contents classification for spam sorting"
+                                 (variable-item gnus-group-spam-classification-spam)
+                                 (variable-item gnus-group-spam-classification-ham)
+                                 (const :tag "Unclassified" nil)))
+   :parameter-document
+   "The spam classification (spam, ham, or neither) of this group.
+When a spam group is entered, all unread articles are marked as spam.")
+
+  (defvar gnus-group-spam-exit-processor-ifile "ifile"
+    "OBSOLETE: The ifile summary exit spam processor.")
+
+  (defvar gnus-group-spam-exit-processor-stat "stat"
+    "OBSOLETE: The spam-stat summary exit spam processor.")
+
+  (defvar gnus-group-spam-exit-processor-bogofilter "bogofilter"
+    "OBSOLETE: The Bogofilter summary exit spam processor.")
+
+  (defvar gnus-group-spam-exit-processor-blacklist "blacklist"
+    "OBSOLETE: The Blacklist summary exit spam processor.")
+
+  (defvar gnus-group-spam-exit-processor-report-gmane "report-gmane"
+    "OBSOLETE: The Gmane reporting summary exit spam processor.
+Only applicable to NNTP groups with articles from Gmane.  See spam-report.el")
+
+  (defvar gnus-group-spam-exit-processor-spamoracle "spamoracle-spam"
+    "OBSOLETE: The spamoracle summary exit spam processor.")
+
+  (defvar gnus-group-ham-exit-processor-ifile "ifile-ham"
+    "OBSOLETE: The ifile summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-bogofilter "bogofilter-ham"
+    "OBSOLETE: The Bogofilter summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-stat "stat-ham"
+    "OBSOLETE: The spam-stat summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-whitelist "whitelist"
+    "OBSOLETE: The whitelist summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-BBDB "bbdb"
+    "OBSOLETE: The BBDB summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-copy "copy"
+    "OBSOLETE: The ham copy exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (defvar gnus-group-ham-exit-processor-spamoracle "spamoracle-ham"
+    "OBSOLETE: The spamoracle summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+  (gnus-define-group-parameter
+   spam-process
+   :type list
+   :parameter-type 
+   '(choice 
+     :tag "Spam Summary Exit Processor"
+     :value nil
+     (list :tag "Spam Summary Exit Processor Choices"
+          (set
+           (variable-item gnus-group-spam-exit-processor-ifile)
+           (variable-item gnus-group-spam-exit-processor-stat)
+           (variable-item gnus-group-spam-exit-processor-bogofilter)
+           (variable-item gnus-group-spam-exit-processor-blacklist)
+           (variable-item gnus-group-spam-exit-processor-spamoracle)
+           (variable-item gnus-group-spam-exit-processor-report-gmane)
+           (variable-item gnus-group-ham-exit-processor-bogofilter)
+           (variable-item gnus-group-ham-exit-processor-ifile)
+           (variable-item gnus-group-ham-exit-processor-stat)
+           (variable-item gnus-group-ham-exit-processor-whitelist)
+           (variable-item gnus-group-ham-exit-processor-BBDB)
+           (variable-item gnus-group-ham-exit-processor-spamoracle)
+           (variable-item gnus-group-ham-exit-processor-copy)
+           (const :tag "Spam: Gmane Report"  (spam spam-use-gmane))
+           (const :tag "Spam: Bogofilter"    (spam spam-use-bogofilter))
+           (const :tag "Spam: Blacklist"     (spam spam-use-blacklist))
+           (const :tag "Spam: ifile"         (spam spam-use-ifile))
+           (const :tag "Spam: Spam-stat"     (spam spam-use-stat))
+           (const :tag "Spam: Spam Oracle"   (spam spam-use-spamoracle))
+           (const :tag "Ham: ifile"          (ham spam-use-ifile))
+           (const :tag "Ham: Bogofilter"     (ham spam-use-bogofilter))
+           (const :tag "Ham: Spam-stat"      (ham spam-use-stat))
+           (const :tag "Ham: Whitelist"      (ham spam-use-whitelist))
+           (const :tag "Ham: BBDB"           (ham spam-use-BBDB))
+           (const :tag "Ham: Copy"           (ham spam-use-ham-copy))
+           (const :tag "Ham: Spam Oracle"    (ham spam-use-spamoracle)))))
+   :function-document
+   "Which spam or ham processors will be applied when the summary is exited."
+   :variable gnus-spam-process-newsgroups
+   :variable-default nil
+   :variable-document
+   "*Groups in which to automatically process spam or ham articles with
+a backend on summary exit.  If non-nil, this should be a list of group
+name regexps that should match all groups in which to do automatic
+spam processing, associated with the appropriate processor."
+   :variable-group spam
+   :variable-type 
+   '(repeat :tag "Spam/Ham Processors"
+           (list :tag "Spam Summary Exit Processor Choices"
+                 (regexp :tag "Group Regexp")
+                 (set 
+                  :tag "Spam/Ham Summary Exit Processor"
+                  (variable-item gnus-group-spam-exit-processor-ifile)
+                  (variable-item gnus-group-spam-exit-processor-stat)
+                  (variable-item gnus-group-spam-exit-processor-bogofilter)
+                  (variable-item gnus-group-spam-exit-processor-blacklist)
+                  (variable-item gnus-group-spam-exit-processor-spamoracle)
+                  (variable-item gnus-group-spam-exit-processor-report-gmane)
+                  (variable-item gnus-group-ham-exit-processor-bogofilter)
+                  (variable-item gnus-group-ham-exit-processor-ifile)
+                  (variable-item gnus-group-ham-exit-processor-stat)
+                  (variable-item gnus-group-ham-exit-processor-whitelist)
+                  (variable-item gnus-group-ham-exit-processor-BBDB)
+                  (variable-item gnus-group-ham-exit-processor-spamoracle)
+                  (variable-item gnus-group-ham-exit-processor-copy)
+                  (const :tag "Spam: Gmane Report"  (spam spam-use-gmane))
+                  (const :tag "Spam: Bogofilter"    (spam spam-use-bogofilter))
+                  (const :tag "Spam: Blacklist"     (spam spam-use-blacklist))
+                  (const :tag "Spam: ifile"         (spam spam-use-ifile))
+                  (const :tag "Spam: Spam-stat"     (spam spam-use-stat))
+                  (const :tag "Spam: Spam Oracle"   (spam spam-use-spamoracle))
+                  (const :tag "Ham: ifile"          (ham spam-use-ifile))
+                  (const :tag "Ham: Bogofilter"     (ham spam-use-bogofilter))
+                  (const :tag "Ham: Spam-stat"      (ham spam-use-stat))
+                  (const :tag "Ham: Whitelist"      (ham spam-use-whitelist))
+                  (const :tag "Ham: BBDB"           (ham spam-use-BBDB))
+                  (const :tag "Ham: Copy"           (ham spam-use-ham-copy))
+                  (const :tag "Ham: Spam Oracle"    (ham spam-use-spamoracle)))))
+
+   :parameter-document
+   "Which spam or ham processors will be applied when the summary is exited.")
+
+  (gnus-define-group-parameter
+   spam-autodetect
+   :type list
+   :parameter-type 
+   '(boolean :tag "Spam autodetection")
+   :function-document
+   "Should spam be autodetected (with spam-split) in this group?"
+   :variable gnus-spam-autodetect
+   :variable-default nil
+   :variable-document
+   "*Groups in which spam should be autodetected when they are entered.
+   Only unseen articles will be examined, unless
+   spam-autodetect-recheck-messages is set."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Autodetection setting"
+     (list
+      (regexp :tag "Group Regexp")
+      boolean))
+   :parameter-document
+   "Spam autodetection.
+Only unseen articles will be examined, unless
+spam-autodetect-recheck-messages is set.")
+
+  (gnus-define-group-parameter
+   spam-autodetect-methods
+   :type list
+   :parameter-type 
+   '(choice :tag "Spam autodetection-specific methods"
+     (const none)
+     (const default)
+     (set :tag "Use specific methods"
+         (variable-item spam-use-blacklist)
+         (variable-item spam-use-regex-headers)
+         (variable-item spam-use-regex-body)
+         (variable-item spam-use-whitelist)
+         (variable-item spam-use-BBDB)
+         (variable-item spam-use-ifile)
+         (variable-item spam-use-spamoracle)
+         (variable-item spam-use-stat)
+         (variable-item spam-use-blackholes)
+         (variable-item spam-use-hashcash)
+         (variable-item spam-use-bogofilter-headers)
+         (variable-item spam-use-bogofilter)))
+   :function-document
+   "Methods to be used for autodetection in each group"
+   :variable gnus-spam-autodetect-methods
+   :variable-default nil
+   :variable-document
+   "*Methods for autodetecting spam per group.
+Requires the spam-autodetect parameter.  Only unseen articles
+will be examined, unless spam-autodetect-recheck-messages is
+set."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Autodetection methods"
+     (list
+      (regexp :tag "Group Regexp")
+      (choice
+       (const none)
+       (const default)
+       (set :tag "Use specific methods"
+       (variable-item spam-use-blacklist)
+       (variable-item spam-use-regex-headers)
+       (variable-item spam-use-regex-body)
+       (variable-item spam-use-whitelist)
+       (variable-item spam-use-BBDB)
+       (variable-item spam-use-ifile)
+       (variable-item spam-use-spamoracle)
+       (variable-item spam-use-stat)
+       (variable-item spam-use-blackholes)
+       (variable-item spam-use-hashcash)
+       (variable-item spam-use-bogofilter-headers)
+       (variable-item spam-use-bogofilter)))))
+     :parameter-document
+   "Spam autodetection methods.  
+Requires the spam-autodetect parameter.  Only unseen articles
+will be examined, unless spam-autodetect-recheck-messages is
+set.")
+
+  (gnus-define-group-parameter
+   spam-process-destination
+   :type list
+   :parameter-type 
+   '(choice :tag "Destination for spam-processed articles at summary exit"
+           (string :tag "Move to a group")
+           (repeat :tag "Move to multiple groups"
+                   (string :tag "Destination group"))
+           (const :tag "Expire" nil))
+   :function-document
+   "Where spam-processed articles will go at summary exit."
+   :variable gnus-spam-process-destinations
+   :variable-default nil
+   :variable-document
+   "*Groups in which to explicitly send spam-processed articles to
+another group, or expire them (the default).  If non-nil, this should
+be a list of group name regexps that should match all groups in which
+to do spam-processed article moving, associated with the destination
+group or nil for explicit expiration.  This only makes sense for
+mail groups."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Spam-processed articles destination"
+     (list
+      (regexp :tag "Group Regexp")
+      (choice
+       :tag "Destination for spam-processed articles at summary exit"
+       (string :tag "Move to a group")
+       (repeat :tag "Move to multiple groups"
+              (string :tag "Destination group"))
+       (const :tag "Expire" nil))))
+   :parameter-document
+   "Where spam-processed articles will go at summary exit.")
+  
+  (gnus-define-group-parameter
+   ham-process-destination
+   :type list
+   :parameter-type 
+   '(choice
+     :tag "Destination for ham articles at summary exit from a spam group"
+     (string :tag "Move to a group")
+     (repeat :tag "Move to multiple groups"
+            (string :tag "Destination group"))
+     (const :tag "Respool" respool)
+     (const :tag "Do nothing" nil))
+   :function-document
+   "Where ham articles will go at summary exit from a spam group."
+   :variable gnus-ham-process-destinations
+   :variable-default nil
+   :variable-document
+   "*Groups in which to explicitly send ham articles to
+another group, or do nothing (the default).  If non-nil, this should
+be a list of group name regexps that should match all groups in which
+to do ham article moving, associated with the destination
+group or nil for explicit ignoring.  This only makes sense for
+mail groups, and only works in spam groups."
+   :variable-group spam
+   :variable-type 
+   '(repeat
+     :tag "Ham articles destination"
+     (list
+      (regexp :tag "Group Regexp")
+      (choice
+       :tag "Destination for ham articles at summary exit from spam group"
+       (string :tag "Move to a group")
+       (repeat :tag "Move to multiple groups"
+               (string :tag "Destination group"))
+       (const :tag "Respool" respool)
+       (const :tag "Expire" nil))))
+   :parameter-document
+   "Where ham articles will go at summary exit from a spam group.")
+
+  (gnus-define-group-parameter
+   ham-marks
+   :type 'list
+   :parameter-type '(list :tag "Ham mark choices"
+                         (set
+                          (variable-item gnus-del-mark)
+                          (variable-item gnus-read-mark)
+                          (variable-item gnus-ticked-mark)
+                          (variable-item gnus-killed-mark)
+                          (variable-item gnus-kill-file-mark)
+                          (variable-item gnus-low-score-mark)))
+
+   :parameter-document
+   "Marks considered ham (positively not spam).  Such articles will be
+processed as ham (non-spam) on group exit.  When nil, the global
+spam-ham-marks variable takes precedence."
+   :variable-default '((".*" ((gnus-del-mark
+                              gnus-read-mark
+                              gnus-killed-mark
+                              gnus-kill-file-mark
+                              gnus-low-score-mark))))
+   :variable-group spam
+   :variable-document
+   "*Groups in which to explicitly set the ham marks to some value.")
+
+  (gnus-define-group-parameter
+   spam-marks
+   :type 'list
+   :parameter-type '(list :tag "Spam mark choices"
+                         (set
+                          (variable-item gnus-spam-mark)
+                          (variable-item gnus-killed-mark)
+                          (variable-item gnus-kill-file-mark)
+                          (variable-item gnus-low-score-mark)))
+
+   :parameter-document
+   "Marks considered spam.
+Such articles will be processed as spam on group exit.  When nil, the global
+spam-spam-marks variable takes precedence."
+   :variable-default '((".*" ((gnus-spam-mark))))
+   :variable-group spam
+   :variable-document
+   "*Groups in which to explicitly set the spam marks to some value."))
 
 (defcustom gnus-group-uncollapsed-levels 1
   "Number of group name elements to leave alone when making a short group name."
@@ -1243,7 +2239,7 @@ following hook:
 (defcustom gnus-group-change-level-function nil
   "Function run when a group level is changed.
 It is called with three parameters -- GROUP, LEVEL and OLDLEVEL."
-  :group 'gnus-group-level
+  :group 'gnus-group-levels
   :type 'function)
 
 ;;; Face thingies.
@@ -1291,6 +2287,18 @@ and `grouplens-menu'."
              (const pick-menu)
              (const grouplens-menu)))
 
+;; Byte-compiler warning.
+(defvar gnus-visual)
+;; Find out whether the gnus-visual TYPE is wanted.
+(defun gnus-visual-p (&optional type class)
+  (and gnus-visual                     ; Has to be non-nil, at least.
+       (if (not type)                  ; We don't care about type.
+          gnus-visual
+        (if (listp gnus-visual)        ; It's a list, so we check it.
+            (or (memq type gnus-visual)
+                (memq class gnus-visual))
+          t))))
+
 (defcustom gnus-mouse-face
   (condition-case ()
       (if (gnus-visual-p 'mouse-face 'highlight)
@@ -1305,60 +2313,6 @@ face."
   :group 'gnus-visual
   :type 'face)
 
-(defcustom gnus-article-display-hook
-  (if (and (string-match "XEmacs" emacs-version)
-          (featurep 'xface))
-      '(gnus-article-hide-headers-if-wanted
-       gnus-article-hide-boring-headers
-       gnus-article-treat-overstrike
-       gnus-article-maybe-highlight
-       gnus-article-display-x-face)
-    '(gnus-article-hide-headers-if-wanted
-      gnus-article-hide-boring-headers
-      gnus-article-treat-overstrike
-      gnus-article-maybe-highlight))
-  "*Controls how the article buffer will look.
-
-If you leave the list empty, the article will appear exactly as it is
-stored on the disk.  The list entries will hide or highlight various
-parts of the article, making it easier to find the information you
-want."
-  :group 'gnus-article-highlight
-  :group 'gnus-visual
-  :type 'hook
-  :options '(gnus-article-add-buttons
-            gnus-article-add-buttons-to-head
-            gnus-article-emphasize
-            gnus-article-fill-cited-article
-            gnus-article-remove-cr
-            gnus-article-de-quoted-unreadable
-            gnus-summary-stop-page-breaking
-            ;; gnus-summary-caesar-message
-            ;; gnus-summary-verbose-headers
-            gnus-summary-toggle-mime
-            gnus-article-hide
-            gnus-article-hide-headers
-            gnus-article-hide-boring-headers
-            gnus-article-hide-signature
-            gnus-article-hide-citation
-            gnus-article-hide-pgp
-            gnus-article-hide-pem
-            gnus-article-highlight
-            gnus-article-highlight-headers
-            gnus-article-highlight-citation
-            gnus-article-highlight-signature
-            gnus-article-date-ut
-            gnus-article-date-local
-            gnus-article-date-lapsed
-            gnus-article-date-original
-            gnus-article-remove-trailing-blank-lines
-            gnus-article-strip-leading-blank-lines
-            gnus-article-strip-multiple-blank-lines
-            gnus-article-strip-blank-lines
-            gnus-article-treat-overstrike
-            gnus-article-display-x-face
-            gnus-smiley-display))
-
 (defcustom gnus-article-save-directory gnus-directory
   "*Name of the directory articles will be saved in (default \"~/News\")."
   :group 'gnus-article-saving
@@ -1367,19 +2321,100 @@ want."
 (defvar gnus-plugged t
   "Whether Gnus is plugged or not.")
 
+(defcustom gnus-agent-cache t
+  "Controls use of the agent cache while plugged.
+When set, Gnus will prefer using the locally stored content rather
+than re-fetching it from the server.  You also need to enable
+`gnus-agent' for this to have any affect."
+  :version "21.3"
+  :group 'gnus-agent
+  :type 'boolean)
+
+(defcustom gnus-default-charset 'undecided
+  "Default charset assumed to be used when viewing non-ASCII characters.
+This variable is overridden on a group-to-group basis by the
+`gnus-group-charset-alist' variable and is only used on groups not
+covered by that variable."
+  :type 'symbol
+  :group 'gnus-charset)
+
+;; Fixme: Doc reference to agent.
+(defcustom gnus-agent t
+  "Whether we want to use the Gnus agent or not.
+
+You may customize gnus-agent to disable its use.  However, some
+back ends have started to use the agent as a client-side cache.
+Disabling the agent may result in noticeable loss of performance."
+  :version "21.3"
+  :group 'gnus-agent
+  :type 'boolean)
+
+(defcustom gnus-other-frame-function 'gnus
+  "Function called by the command `gnus-other-frame'."
+  :group 'gnus-start
+  :type '(choice (function-item gnus)
+                (function-item gnus-no-server)
+                (function-item gnus-slave)
+                (function-item gnus-slave-no-server)))
+
+(defcustom gnus-other-frame-parameters nil
+  "Frame parameters used by `gnus-other-frame' to create a Gnus frame.
+This should be an alist for Emacs, or a plist for XEmacs."
+  :group 'gnus-start
+  :type (if (featurep 'xemacs)
+           '(repeat (list :inline t :format "%v"
+                          (symbol :tag "Property")
+                          (sexp :tag "Value")))
+         '(repeat (cons :format "%v"
+                        (symbol :tag "Parameter")
+                        (sexp :tag "Value")))))
+
+(defcustom gnus-user-agent 'gnus-mime-edit
+  "Which information should be exposed in the User-Agent header.
+
+It can be one of the symbols `gnus' \(show only Gnus version\), `emacs-gnus'
+\(show only Emacs and Gnus versions\), `emacs-gnus-config' \(same as
+`emacs-gnus' plus system configuration\), `emacs-gnus-type' \(same as
+`emacs-gnus' plus system type\), `gnus-mime-edit' \(show Gnus version and
+MIME Edit User-Agent\) or a custom string.  If you set it to a string,
+be sure to use a valid format, see RFC 2616."
+  :group 'gnus-message
+  :type '(choice
+         (item :tag "Show Gnus version and MIME Edit User-Agent"
+               gnus-mime-edit)
+         (item :tag "Show Gnus and Emacs versions and system type"
+               emacs-gnus-type)
+         (item :tag "Show Gnus and Emacs versions and system configuration"
+               emacs-gnus-config)
+         (item :tag "Show Gnus and Emacs versions" emacs-gnus)
+         (item :tag "Show only Gnus version" gnus)
+         (string :tag "Other")))
+
 \f
 ;;; Internal variables
 
+(defvar gnus-agent-gcc-header "X-Gnus-Agent-Gcc")
+(defvar gnus-agent-meta-information-header "X-Gnus-Agent-Meta-Information")
+(defvar gnus-agent-method-p-cache nil
+  ; Reset each time gnus-agent-covered-methods is changed else
+  ; gnus-agent-method-p may mis-report a methods status.
+  )
+(defvar gnus-agent-target-move-group-header "X-Gnus-Agent-Move-To")
+(defvar gnus-draft-meta-information-header "X-Draft-From")
 (defvar gnus-group-get-parameter-function 'gnus-group-get-parameter)
 (defvar gnus-original-article-buffer " *Original Article*")
 (defvar gnus-newsgroup-name nil)
 (defvar gnus-ephemeral-servers nil)
+(defvar gnus-server-method-cache nil)
+
+(defvar gnus-agent-fetching nil
+  "Whether Gnus agent is in fetching mode.")
 
-(defvar gnus-agent nil
-  "Whether we want to use the Gnus agent or not.")
+(defvar gnus-agent-covered-methods nil
+  "A list of servers, NOT methods, showing which servers are covered by the agent.")
 
 (defvar gnus-command-method nil
-  "Dynamically bound variable that says what the current backend is.")
+  "Dynamically bound variable that says what the current back end is.")
 
 (defvar gnus-current-select-method nil
   "The current method for selecting a newsgroup.")
@@ -1402,15 +2437,22 @@ want."
 (defvar gnus-server-alist nil
   "List of available servers.")
 
+(defcustom gnus-cache-directory
+  (nnheader-concat gnus-directory "cache/")
+  "*The directory where cached articles will be stored."
+  :group 'gnus-cache
+  :type 'directory)
+
 (defvar gnus-predefined-server-alist
   `(("cache"
-     (nnspool "cache"
-             (nnspool-spool-directory "~/News/cache/")
-             (nnspool-nov-directory "~/News/cache/")
-             (nnspool-active-file "~/News/cache/active"))))
+     nnspool "cache"
+     (nnspool-spool-directory ,gnus-cache-directory)
+     (nnspool-nov-directory ,gnus-cache-directory)
+     (nnspool-active-file
+      ,(nnheader-concat gnus-cache-directory "active"))))
   "List of predefined (convenience) servers.")
 
-(defvar gnus-topic-indentation "") ;; Obsolete variable.
+(defvar gnus-topic-indentation "");; Obsolete variable.
 
 (defconst gnus-article-mark-lists
   '((marked . tick) (replied . reply)
@@ -1418,7 +2460,28 @@ want."
     (bookmarks . bookmark) (dormant . dormant)
     (scored . score) (saved . save)
     (cached . cache) (downloadable . download)
-    (unsendable . unsend)))
+    (unsendable . unsend) (forwarded . forward)
+    (recent . recent) (seen . seen)))
+
+(defconst gnus-article-special-mark-lists
+  '((seen range)
+    (killed range)
+    (bookmark tuple)
+    (score tuple)))
+
+;; Propagate flags to server, with the following exceptions:
+;; `seen' is private to each gnus installation
+;; `cache' is a internal gnus flag for each gnus installation
+;; `download' is a agent flag private to each gnus installation
+;; `unsend' are for nndraft groups only
+;; `score' is not a proper mark
+;; `bookmark': don't propagated it, or fix the bug in update-mark.
+(defconst gnus-article-unpropagated-mark-lists
+  '(seen cache download unsend score bookmark)
+  "Marks that shouldn't be propagated to back ends.
+Typical marks are those that make no sense in a standalone back end,
+such as a mark that says whether an article is stored in the cache
+\(which doesn't make sense in a standalone back end).")
 
 (defvar gnus-headers-retrieved-by nil)
 (defvar gnus-article-reply nil)
@@ -1431,17 +2494,26 @@ want."
 (defvar gnus-have-read-active-file nil)
 
 (defconst gnus-maintainer
-  "bugs@gnus.org (The Gnus Bugfixing Girls + Boys)"
-  "The mail address of the Gnus maintainers.")
+  "semi-gnus-ja@meadowy.org (T-gnus Bugfixing Girls + Boys)"
+  "The mail address of the T-gnus maintainers.")
+
+(defcustom gnus-info-filename nil
+  "*Controls language of gnus Info.
+If nil and current-language-environment is Japanese, go to gnus-ja.
+Otherwise go to corresponding Info.
+This variable can be nil, gnus or gnus-ja."
+  :group 'gnus-start
+  :type '(choice (const nil)
+                (const :tag "English" gnus)
+                (const :tag "Japanese" gnus-ja)))
 
 (defvar gnus-info-nodes
-  '((gnus-group-mode "(gnus)The Group Buffer")
-    (gnus-summary-mode "(gnus)The Summary Buffer")
-    (gnus-article-mode "(gnus)The Article Buffer")
-    (mime/viewer-mode "(gnus)The Article Buffer")
-    (gnus-server-mode "(gnus)The Server Buffer")
-    (gnus-browse-mode "(gnus)Browse Foreign Server")
-    (gnus-tree-mode "(gnus)Tree Display"))
+  '((gnus-group-mode "Group Buffer")
+    (gnus-summary-mode "Summary Buffer")
+    (gnus-article-mode "Article Buffer")
+    (gnus-server-mode "Server Buffer")
+    (gnus-browse-mode "Browse Foreign Server")
+    (gnus-tree-mode "Tree Display"))
   "Alist of major modes and related Info nodes.")
 
 (defvar gnus-group-buffer "*Group*")
@@ -1449,9 +2521,6 @@ want."
 (defvar gnus-article-buffer "*Article*")
 (defvar gnus-server-buffer "*Server*")
 
-(defvar gnus-buffer-list nil
-  "Gnus buffers that should be killed on exit.")
-
 (defvar gnus-slave nil
   "Whether this Gnus is a slave or not.")
 
@@ -1460,25 +2529,62 @@ want."
 
 (defvar gnus-variable-list
   '(gnus-newsrc-options gnus-newsrc-options-n
-    gnus-newsrc-last-checked-date
-    gnus-newsrc-alist gnus-server-alist
-    gnus-killed-list gnus-zombie-list
-    gnus-topic-topology gnus-topic-alist
-    gnus-format-specs)
+                       gnus-newsrc-last-checked-date
+                       gnus-newsrc-alist gnus-server-alist
+                       gnus-killed-list gnus-zombie-list
+                       gnus-topic-topology gnus-topic-alist)
   "Gnus variables saved in the quick startup file.")
 
+(defvar gnus-product-variable-file-list
+  (let ((version (product-version (product-find 'gnus-vers)))
+       (codesys (static-if (boundp 'MULE) '*ctext* 'ctext)))
+    `(("strict-cache"
+       ((product-version ,version)
+       (emacs-version)
+       (correct-string-widths))
+       binary
+       gnus-format-specs-compiled)
+      ("cache"
+       ((product-version ,version)
+       (emacs-version)
+       (correct-string-widths))
+       ,codesys
+       gnus-format-specs)))
+  "Alist of the methods for checking whether the contents of the T-gnus
+quick startup files are valid.  One is for the byte-compiled format
+specifications, the other is for the source form.  Each element should
+be a list which looks like follows:
+
+\(\"FILE_NAME\"
+ ((VARIABLE EXPECTED_VALUE_or_NIL)
+  (VARIABLE EXPECTED_VALUE_or_NIL)
+  ...)
+ CODING-SYSTEM_FOR_READING_FILE
+ SYMBOL_OF_FORMAT_SPECS)")
+
+(defcustom gnus-compile-user-specs t
+  "If non-nil, the user-defined format specs will be byte-compiled
+automatically.
+It has an effect on the values of `gnus-*-line-format-spec'."
+  :group 'gnus
+  :type 'boolean)
+
 (defvar gnus-newsrc-alist nil
   "Assoc list of read articles.
-gnus-newsrc-hashtb should be kept so that both hold the same information.")
+`gnus-newsrc-hashtb' should be kept so that both hold the same information.")
+
+(defvar gnus-registry-alist nil
+  "Assoc list of registry data.
+gnus-registry.el will populate this if it's loaded.")
 
 (defvar gnus-newsrc-hashtb nil
-  "Hashtable of gnus-newsrc-alist.")
+  "Hashtable of `gnus-newsrc-alist'.")
 
 (defvar gnus-killed-list nil
   "List of killed newsgroups.")
 
 (defvar gnus-killed-hashtb nil
-  "Hash table equivalent of gnus-killed-list.")
+  "Hash table equivalent of `gnus-killed-list'.")
 
 (defvar gnus-zombie-list nil
   "List of almost dead newsgroups.")
@@ -1505,6 +2611,12 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
 
 (defvar gnus-dead-summary nil)
 
+(defvar gnus-invalid-group-regexp "[: `'\"/]\\|^$"
+  "Regexp matching invalid groups.")
+
+(defvar gnus-other-frame-object nil
+  "A frame object which will be created by `gnus-other-frame'.")
+
 ;;; End of variables.
 
 ;; Define some autoload functions Gnus might use.
@@ -1521,26 +2633,23 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
            (when (consp function)
              (setq keymap (car (memq 'keymap function)))
              (setq function (car function)))
-           (autoload function (car package) nil interactive keymap)))
+           (unless (fboundp function)
+             (autoload function (car package) nil interactive keymap))))
        (if (eq (nth 1 package) ':interactive)
-           (cdddr package)
+           (nthcdr 3 package)
          (cdr package)))))
-   '(("metamail" metamail-buffer)
-     ("info" Info-goto-node)
-     ("hexl" hexl-hex-string-to-integer)
-     ("pp" pp pp-to-string pp-eval-expression)
+   '(("info" :interactive t Info-goto-node)
+     ("pp" pp-to-string)
      ("ps-print" ps-print-preprint)
-     ("mail-extr" mail-extract-address-components)
-     ("browse-url" browse-url)
      ("message" :interactive t
       message-send-and-exit message-yank-original)
-     ("nnmail" nnmail-split-fancy nnmail-article-group nnmail-date-to-time)
+     ("babel" babel-as-string)
+     ("nnmail" nnmail-split-fancy nnmail-article-group)
      ("nnvirtual" nnvirtual-catchup-group nnvirtual-convert-headers)
-     ("timezone" timezone-make-date-arpa-standard timezone-fix-time
-      timezone-make-sortable-date timezone-make-time-string)
-     ("rmailout" rmail-output)
+     ("rmailout" rmail-output rmail-output-to-rmail-file)
      ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
-      rmail-show-message)
+      rmail-show-message rmail-summary-exists
+      rmail-select-summary rmail-update-summary)
      ("gnus-audio" :interactive t gnus-audio-play)
      ("gnus-xmas" gnus-xmas-splash)
      ("gnus-soup" :interactive t
@@ -1557,6 +2666,9 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-demon-remove-handler)
      ("gnus-demon" :interactive t
       gnus-demon-init gnus-demon-cancel)
+     ("gnus-fun" gnus-convert-gray-x-face-to-xpm gnus-display-x-face-in-from
+      gnus-convert-image-to-gray-x-face gnus-convert-face-to-png
+      gnus-face-from-file)
      ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
       gnus-tree-open gnus-tree-close gnus-carpal-setup-buffer)
      ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
@@ -1570,31 +2682,34 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-hide-citation-in-followups)
      ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
       gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
-      gnus-execute gnus-expunge)
+      gnus-execute gnus-expunge gnus-batch-kill gnus-batch-score)
      ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
       gnus-cache-possibly-remove-articles gnus-cache-request-article
       gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
       gnus-cache-enter-remove-article gnus-cached-article-p
-      gnus-cache-open gnus-cache-close gnus-cache-update-article)
-      ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
-       gnus-cache-remove-article gnus-summary-insert-cached-articles)
-      ("gnus-score" :interactive t
-       gnus-summary-increase-score gnus-summary-set-score
-       gnus-summary-raise-thread gnus-summary-raise-same-subject
-       gnus-summary-raise-score gnus-summary-raise-same-subject-and-select
-       gnus-summary-lower-thread gnus-summary-lower-same-subject
-       gnus-summary-lower-score gnus-summary-lower-same-subject-and-select
-       gnus-summary-current-score gnus-score-default
-       gnus-score-flush-cache gnus-score-close
-       gnus-possibly-score-headers gnus-score-followup-article
-       gnus-score-followup-thread)
-      ("gnus-score"
-       (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
+      gnus-cache-open gnus-cache-close gnus-cache-update-article
+      gnus-cache-articles-in-group)
+     ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
+      gnus-cache-remove-article gnus-summary-insert-cached-articles)
+     ("gnus-score" :interactive t
+      gnus-summary-increase-score gnus-summary-set-score
+      gnus-summary-raise-thread gnus-summary-raise-same-subject
+      gnus-summary-raise-score gnus-summary-raise-same-subject-and-select
+      gnus-summary-lower-thread gnus-summary-lower-same-subject
+      gnus-summary-lower-score gnus-summary-lower-same-subject-and-select
+      gnus-summary-current-score gnus-score-delta-default
+      gnus-score-flush-cache gnus-score-close
+      gnus-possibly-score-headers gnus-score-followup-article
+      gnus-score-followup-thread)
+     ("gnus-score"
+      (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
       gnus-current-score-file-nondirectory gnus-score-adaptive
       gnus-score-find-trace gnus-score-file-name)
-     ("gnus-cus" :interactive t gnus-group-customize gnus-score-customize)
+     ("gnus-cus" :interactive t gnus-custom-mode gnus-group-customize
+      gnus-score-customize)
      ("gnus-topic" :interactive t gnus-topic-mode)
-     ("gnus-topic" gnus-topic-remove-group gnus-topic-set-parameters)
+     ("gnus-topic" gnus-topic-remove-group gnus-topic-set-parameters
+      gnus-subscribe-topics)
      ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
      ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
      ("gnus-uu" :interactive t
@@ -1607,36 +2722,41 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-uu-decode-binhex gnus-uu-decode-uu-view
       gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
       gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
-      gnus-uu-decode-binhex-view)
-     ("gnus-uu" gnus-uu-delete-work-dir gnus-quote-arg-for-sh-or-csh)
+      gnus-uu-decode-binhex-view gnus-uu-unmark-thread
+      gnus-uu-mark-over gnus-uu-post-news)
+     ("gnus-uu" gnus-uu-delete-work-dir gnus-quote-arg-for-sh-or-csh
+      gnus-uu-unmark-thread)
      ("gnus-msg" (gnus-summary-send-map keymap)
-      gnus-article-mail gnus-copy-article-buffer gnus-extended-version)
+      gnus-article-mail gnus-copy-article-buffer gnus-following-method)
      ("gnus-msg" :interactive t
-      gnus-group-post-news gnus-group-mail gnus-summary-post-news
+      gnus-group-post-news gnus-group-mail gnus-group-news
+      gnus-summary-post-news gnus-summary-news-other-window
       gnus-summary-followup gnus-summary-followup-with-original
       gnus-summary-cancel-article gnus-summary-supersede-article
       gnus-post-news gnus-summary-reply gnus-summary-reply-with-original
       gnus-summary-mail-forward gnus-summary-mail-other-window
       gnus-summary-resend-message gnus-summary-resend-bounced-mail
-      gnus-bug)
-     ("gnus-picon" :interactive t gnus-article-display-picons
-      gnus-group-display-picons gnus-picons-article-display-x-face
-      gnus-picons-display-x-face)
+      gnus-summary-wide-reply gnus-summary-followup-to-mail
+      gnus-summary-followup-to-mail-with-original gnus-bug
+      gnus-summary-wide-reply-with-original gnus-summary-post-forward
+      gnus-summary-digest-mail-forward gnus-summary-digest-post-forward)
+     ("gnus-picon" :interactive t gnus-treat-from-picon)
      ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p
       gnus-grouplens-mode)
-     ("smiley" :interactive t gnus-smiley-display)
+     ("smiley" :interactive t smiley-region)
      ("gnus-win" gnus-configure-windows gnus-add-configuration)
      ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group
       gnus-list-of-unread-articles gnus-list-of-read-articles
       gnus-offer-save-summaries gnus-make-thread-indent-array
-      gnus-summary-exit gnus-update-read-articles)
+      gnus-summary-exit gnus-update-read-articles gnus-summary-last-subject
+      gnus-summary-skip-intangible gnus-summary-article-number
+      gnus-data-header gnus-data-find gnus-summary-jump-to-other-group)
      ("gnus-group" gnus-group-insert-group-line gnus-group-quit
       gnus-group-list-groups gnus-group-first-unread-group
       gnus-group-set-mode-line gnus-group-set-info gnus-group-save-newsrc
       gnus-group-setup-buffer gnus-group-get-new-news
       gnus-group-make-help-group gnus-group-update-group
-      gnus-clear-inboxes-moved gnus-group-iterate
-      gnus-group-group-name)
+      gnus-group-iterate gnus-group-group-name)
      ("gnus-bcklg" gnus-backlog-request-article gnus-backlog-enter-article
       gnus-backlog-remove-article)
      ("gnus-art" gnus-article-read-summary-keys gnus-article-save
@@ -1644,23 +2764,26 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-next-page gnus-article-prev-page
       gnus-request-article-this-buffer gnus-article-mode
       gnus-article-setup-buffer gnus-narrow-to-page
-      gnus-article-delete-invisible-text gnus-hack-decode-rfc1522)
+      gnus-article-delete-invisible-text gnus-treat-article)
      ("gnus-art" :interactive t
       gnus-article-hide-headers gnus-article-hide-boring-headers
-      gnus-article-treat-overstrike gnus-article-word-wrap
+      gnus-article-treat-overstrike
       gnus-article-remove-cr gnus-article-remove-trailing-blank-lines
-      gnus-article-display-x-face gnus-article-de-quoted-unreadable
-      gnus-article-mime-decode-quoted-printable gnus-article-hide-pgp
+      gnus-article-display-x-face
+      gnus-article-decode-HZ
+      gnus-article-wash-html
+      gnus-article-unsplit-urls
       gnus-article-hide-pem gnus-article-hide-signature
       gnus-article-strip-leading-blank-lines gnus-article-date-local
       gnus-article-date-original gnus-article-date-lapsed
       gnus-article-show-all-headers
+      ;; gnus-article-show-all
       gnus-article-edit-mode gnus-article-edit-article
-      gnus-article-edit-done gnus-decode-rfc1522 article-decode-rfc1522
+      gnus-article-edit-done article-decode-encoded-words
       gnus-start-date-timer gnus-stop-date-timer)
      ("gnus-int" gnus-request-type)
      ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1
-      gnus-dribble-enter gnus-read-init-file)
+      gnus-dribble-enter gnus-read-init-file gnus-dribble-touch)
      ("gnus-dup" gnus-dup-suppress-articles gnus-dup-unsuppress-article
       gnus-dup-enter-articles)
      ("gnus-range" gnus-copy-sequence)
@@ -1672,19 +2795,65 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-async" gnus-async-request-fetched-article gnus-async-prefetch-next
       gnus-async-prefetch-article gnus-async-prefetch-remove-group
       gnus-async-halt-prefetch)
+     ("gnus-offline"
+      gnus-offline-setup)
+     ("gnus-offline" :interactive t
+      gnus-offline-toggle-plugged
+      gnus-offline-set-unplugged-state
+      gnus-offline-toggle-auto-hangup
+      gnus-offline-toggle-on/off-send-mail
+      gnus-offline-toggle-articles-to-fetch
+      gnus-offline-set-interval-time
+      gnus-offline-agent-expire)
+     ("miee" :interactive t gnspool-get-news
+      mail-spool-send news-spool-post)
+     ("international/mw32misc" define-process-argument-editing
+      general-process-argument-editing-function)
      ("gnus-agent" gnus-open-agent gnus-agent-get-function
       gnus-agent-save-groups gnus-agent-save-active gnus-agent-method-p
-      gnus-agent-get-undownloaded-list gnus-agent-fetch-session)
+      gnus-agent-get-undownloaded-list gnus-agent-fetch-session
+      gnus-summary-set-agent-mark gnus-agent-save-group-info
+      gnus-agent-request-article gnus-agent-retrieve-headers)
      ("gnus-agent" :interactive t
       gnus-unplugged gnus-agentize gnus-agent-batch)
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
       gnus-summary-save-article-vm)
-     ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-drafts))))
+     ("compface" uncompface)
+     ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-queue)
+     ("gnus-mlspl" gnus-group-split gnus-group-split-fancy)
+     ("gnus-mlspl" :interactive t gnus-group-split-setup
+      gnus-group-split-update)
+     ("gnus-delay" gnus-delay-initialize))))
+
+(eval-and-compile
+  (unless (featurep 'xemacs)
+    (if (>= emacs-major-version 21)
+       (autoload 'x-face-decode-message-header "x-face-e21")
+      (autoload 'x-face-mule-gnus-article-display-x-face "x-face-mule"))))
+
+(unless (and (fboundp 'base64-encode-string)
+            (subrp (symbol-function 'base64-encode-string)))
+  (require 'base64))
+
+;; To search articles with Namazu.
+(autoload 'gnus-namazu-search "gnus-namazu" nil t)
+(autoload 'gnus-namazu-create-index "gnus-namazu" nil t)
+(autoload 'gnus-namazu-update-index "gnus-namazu" nil t)
+(autoload 'gnus-namazu-update-all-indices "gnus-namazu" nil t)
+
+;; To make nnir groups.
+(autoload 'gnus-group-make-nnir-group "nnir" nil t)
+
+;; To make shimbun groups.
+(autoload 'gnus-group-make-shimbun-group "nnshimbun" nil t)
+
+;; A tool for the developers.
+(autoload 'find-cl-run-time-functions "gnus-clfns" nil t)
 
 ;;; gnus-sum.el thingies
 
 
-(defcustom gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
+(defcustom gnus-summary-line-format "%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n"
   "*The format specification of the lines in the summary buffer.
 
 It works along the same lines as a normal formatting string,
@@ -1697,14 +2866,20 @@ with some simple extensions.
 %a   Extracted name of the poster (string)
 %A   Extracted address of the poster (string)
 %F   Contents of the From: header (string)
+%f   Contents of the From: or To: headers (string)
 %x   Contents of the Xref: header (string)
 %D   Date of the article (string)
 %d   Date of the article (string) in DD-MMM format
+%o   Date of the article (string) in YYYYMMDD`T'HHMMSS format
 %M   Message-id of the article (string)
 %r   References of the article (string)
 %c   Number of characters in the article (integer)
+%k   Pretty-printed version of the above (string)
+     For example, \"1.2k\" or \"0.4M\".
 %L   Number of lines in the article (integer)
 %I   Indentation based on thread level (a string of spaces)
+%B   A complex trn-style thread tree (string)
+     The variables `gnus-sum-thread-*' can be used for customization.
 %T   A string with two possible values: 80 spaces if the article
      is on thread level two or larger and 0 spaces on level one
 %R   \"A\" if this article has been replied to, \" \" otherwise (character)
@@ -1721,6 +2896,8 @@ with some simple extensions.
 %V   Total thread score (number).
 %P   The line number (number).
 %O   Download mark (character).
+%*   If present, indicates desired cursor position
+     (instead of after first colon).
 %u   User defined specifier.  The next character in the format string should
      be a letter.  Gnus will call the function gnus-user-format-function-X,
      where X is the letter following %u.  The function will be passed the
@@ -1728,21 +2905,21 @@ with some simple extensions.
      will be inserted into the summary just like information from any other
      summary specifier.
 
-Text between %( and %) will be highlighted with `gnus-mouse-face'
-when the mouse point is placed inside the area.         There can only be one
-such area.
-
 The %U (status), %R (replied) and %z (zcore) specs have to be handled
 with care.  For reasons of efficiency, Gnus will compute what column
 these characters will end up in, and \"hard-code\" that.  This means that
-it is illegal to have these specs after a variable-length spec.         Well,
+it is invalid to have these specs after a variable-length spec.         Well,
 you might not be arrested, but your summary buffer will look strange,
 which is bad enough.
 
-The smart choice is to have these specs as for to the left as
+The smart choice is to have these specs as far to the left as
 possible.
 
-This restriction may disappear in later versions of Gnus."
+This restriction may disappear in later versions of Gnus.
+
+General format specifiers can also be used.
+See Info node `(gnus)Formatting Variables'."
+  :link '(custom-manual "(gnus)Formatting Variables")
   :type 'string
   :group 'gnus-summary-format)
 
@@ -1757,7 +2934,7 @@ This restriction may disappear in later versions of Gnus."
       (define-key keymap (pop keys) 'undefined))))
 
 (defvar gnus-article-mode-map
-  (let ((keymap (make-keymap)))
+  (let ((keymap (make-sparse-keymap)))
     (gnus-suppress-keymap keymap)
     keymap))
 (defvar gnus-summary-mode-map
@@ -1786,6 +2963,12 @@ This restriction may disappear in later versions of Gnus."
   "Get hash value of STRING in HASHTABLE."
   `(symbol-value (intern-soft ,string ,hashtable)))
 
+(defmacro gnus-gethash-safe (string hashtable)
+  "Get hash value of STRING in HASHTABLE.
+Return nil if not defined."
+  `(let ((sym (intern-soft ,string ,hashtable)))
+     (and (boundp sym) (symbol-value sym))))
+
 (defmacro gnus-sethash (string value hashtable)
   "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
   `(set (intern ,string ,hashtable) ,value))
@@ -1807,14 +2990,6 @@ This restriction may disappear in later versions of Gnus."
   "Set GROUP's active info."
   `(gnus-sethash ,group ,active gnus-active-hashtb))
 
-(defun gnus-alive-p ()
-  "Say whether Gnus is running or not."
-  (and gnus-group-buffer
-       (get-buffer gnus-group-buffer)
-       (save-excursion
-        (set-buffer gnus-group-buffer)
-        (eq major-mode 'gnus-group-mode))))
-
 ;; Info access macros.
 
 (defmacro gnus-info-group (info)
@@ -1879,19 +3054,7 @@ This restriction may disappear in later versions of Gnus."
 (defmacro gnus-get-info (group)
   `(nth 2 (gnus-gethash ,group gnus-newsrc-hashtb)))
 
-;; Byte-compiler warning.
-(defvar gnus-visual)
-;; Find out whether the gnus-visual TYPE is wanted.
-(defun gnus-visual-p (&optional type class)
-  (and gnus-visual                     ; Has to be non-nil, at least.
-       (if (not type)                  ; We don't care about type.
-          gnus-visual
-        (if (listp gnus-visual)        ; It's a list, so we check it.
-            (or (memq type gnus-visual)
-                (memq class gnus-visual))
-          t))))
-
-;;; Load the compatability functions.
+;;; Load the compatibility functions.
 
 (require 'gnus-ems)
 
@@ -1919,6 +3082,22 @@ This restriction may disappear in later versions of Gnus."
 ;;; Gnus Utility Functions
 ;;;
 
+(defun gnus-find-subscribed-addresses ()
+  "Return a regexp matching the addresses of all subscribed mail groups.
+It consists of the `to-address' or `to-list' parameter of all groups
+with a `subscribed' parameter."
+  (let (group address addresses)
+    (dolist (entry (cdr gnus-newsrc-alist))
+      (setq group (car entry))
+      (when (gnus-parameter-subscribed group)
+       (setq address (mail-strip-quoted-names
+                      (or (gnus-group-fast-parameter group 'to-address)
+                          (gnus-group-fast-parameter group 'to-list))))
+       (when address
+         (add-to-list 'addresses address))))
+    (when addresses
+      (list (mapconcat 'regexp-quote addresses "\\|")))))
+
 (defmacro gnus-string-or (&rest strings)
   "Return the first element of STRINGS that is a non-blank string.
 STRINGS will be evaluated in normal `or' order."
@@ -1933,61 +3112,20 @@ STRINGS will be evaluated in normal `or' order."
        (setq strings nil)))
     string))
 
-;; Add the current buffer to the list of buffers to be killed on exit.
-(defun gnus-add-current-to-buffer-list ()
-  (or (memq (current-buffer) gnus-buffer-list)
-      (push (current-buffer) gnus-buffer-list)))
-
-(defun gnus-version (&optional arg)
-  "Version number of this version of Gnus.
-If ARG, insert string at point."
-  (interactive "P")
-  (let ((methods gnus-valid-select-methods)
-       (mess gnus-version)
-       meth)
-    ;; Go through all the legal select methods and add their version
-    ;; numbers to the total version string.  Only the backends that are
-    ;; currently in use will have their message numbers taken into
-    ;; consideration.
-    (while methods
-      (setq meth (intern (concat (caar methods) "-version")))
-      (and (boundp meth)
-          (stringp (symbol-value meth))
-          (setq mess (concat mess "; " (symbol-value meth))))
-      (setq methods (cdr methods)))
-    (if arg
-       (insert (message mess))
-      (message mess))))
-
-(defun gnus-continuum-version (version)
-  "Return VERSION as a floating point number."
-  (when (or (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version)
-           (string-match "^\\(.?\\)gnus-\\([0-9.]+\\)$" version))
-    (let* ((alpha (and (match-beginning 1) (match-string 1 version)))
-          (number (match-string 2 version))
-          major minor least)
-      (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number)
-      (setq major (string-to-number (match-string 1 number)))
-      (setq minor (string-to-number (match-string 2 number)))
-      (setq least (if (match-beginning 3)
-                     (string-to-number (match-string 3 number))
-                   0))
-      (string-to-number
-       (if (zerop major)
-          (format "%s00%02d%02d"
-                  (cond
-                   ((member alpha '("(ding)" "d")) "4.99")
-                   ((member alpha '("September" "s")) "5.01")
-                   ((member alpha '("Red" "r")) "5.03"))
-                  minor least)
-        (format "%d.%02d%02d" major minor least))))))
-
-(defun gnus-info-find-node ()
+(defun gnus-info-find-node (&optional nodename)
   "Find Info documentation of Gnus."
   (interactive)
   ;; Enlarge info window if needed.
   (let (gnus-info-buffer)
-    (Info-goto-node (cadr (assq major-mode gnus-info-nodes)))
+    (Info-goto-node
+     (format "(%s)%s"
+            (or gnus-info-filename
+                (get-language-info current-language-environment 'gnus-info)
+                "gnus")
+            (or nodename
+                (cadr (assq major-mode gnus-info-nodes))
+                (and (eq (current-buffer) (get-buffer gnus-article-buffer))
+                     (cadr (assq 'gnus-article-mode gnus-info-nodes))))))
     (setq gnus-info-buffer (current-buffer))
     (gnus-configure-windows 'info)))
 
@@ -2021,7 +3159,7 @@ g -- Group name."
        (setq prompt (match-string 1 string)))
       (setq i (match-end 0))
       ;; We basically emulate just about everything that
-      ;; `interactive' does, but adds the "g" and "G" specs.
+      ;; `interactive' does, but add the specs listed above.
       (push
        (cond
        ((= c ?a)
@@ -2088,8 +3226,8 @@ g -- Group name."
        out)
       (cond
        ((= c ?r)
-       (push (if (< (point) (mark) (point) (mark))) out)
-       (push (if (> (point) (mark) (point) (mark))) out))))
+       (push (if (< (point) (mark)) (point) (mark)) out)
+       (push (if (> (point) (mark)) (point) (mark)) out))))
     (setq out (delq 'gnus-prefix-nil out))
     (nreverse out)))
 
@@ -2129,30 +3267,6 @@ that that variable is buffer-local to the summary buffers."
   (let ((group (or group gnus-newsgroup-name)))
     (not (gnus-check-backend-function 'request-replace-article group))))
 
-(defun gnus-group-total-expirable-p (group)
-  "Check whether GROUP is total-expirable or not."
-  (let ((params (gnus-group-find-parameter group))
-       val)
-    (cond
-     ((memq 'total-expire params)
-      t)
-     ((setq val (assq 'total-expire params)) ; (auto-expire . t)
-      (cdr val))
-     (gnus-total-expirable-newsgroups  ; Check var.
-      (string-match gnus-total-expirable-newsgroups group)))))
-
-(defun gnus-group-auto-expirable-p (group)
-  "Check whether GROUP is auto-expirable or not."
-  (let ((params (gnus-group-find-parameter group))
-       val)
-    (cond
-     ((memq 'auto-expire params)
-      t)
-     ((setq val (assq 'auto-expire params)) ; (auto-expire . t)
-      (cdr val))
-     (gnus-auto-expirable-newsgroups   ; Check var.
-      (string-match gnus-auto-expirable-newsgroups group)))))
-
 (defun gnus-virtual-group-p (group)
   "Say whether GROUP is virtual or not."
   (memq 'virtual (assoc (symbol-name (car (gnus-find-method-for-group group)))
@@ -2160,9 +3274,18 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-news-group-p (group &optional article)
   "Return non-nil if GROUP (and ARTICLE) come from a news server."
-  (or (gnus-member-of-valid 'post group) ; Ordinary news group.
-      (and (gnus-member-of-valid 'post-mail group) ; Combined group.
-          (eq (gnus-request-type group article) 'news))))
+  (cond ((gnus-member-of-valid 'post group) ;Ordinary news group
+        t)                             ;is news of course.
+       ((not (gnus-member-of-valid 'post-mail group)) ;Non-combined.
+        nil)                           ;must be mail then.
+       ((vectorp article)              ;Has header info.
+        (eq (gnus-request-type group (mail-header-id article)) 'news))
+       ((null article)                 ;Hasn't header info
+        (eq (gnus-request-type group) 'news)) ;(unknown ==> mail)
+       ((< article 0)                  ;Virtual message
+        nil)                           ;we don't know, guess mail.
+       (t                              ;Has positive number
+        (eq (gnus-request-type group article) 'news)))) ;use it.
 
 ;; Returns a list of writable groups.
 (defun gnus-writable-groups ()
@@ -2193,11 +3316,11 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-ephemeral-group-p (group)
   "Say whether GROUP is ephemeral or not."
-  (gnus-group-get-parameter group 'quit-config))
+  (gnus-group-get-parameter group 'quit-config t))
 
 (defun gnus-group-quit-config (group)
   "Return the quit-config of GROUP."
-  (gnus-group-get-parameter group 'quit-config))
+  (gnus-group-get-parameter group 'quit-config t))
 
 (defun gnus-kill-ephemeral-group (group)
   "Remove ephemeral GROUP from relevant structures."
@@ -2224,6 +3347,85 @@ that that variable is buffer-local to the summary buffers."
                                   (nth 1 method))))
       method)))
 
+(defsubst gnus-server-to-method (server)
+  "Map virtual server names to select methods."
+  (or (and server (listp server) server)
+      (cdr (assoc server gnus-server-method-cache))
+      (let ((result
+            (or
+             ;; Perhaps this is the native server?
+             (and (equal server "native") gnus-select-method)
+             ;; It should be in the server alist.
+             (cdr (assoc server gnus-server-alist))
+             ;; It could be in the predefined server alist.
+             (cdr (assoc server gnus-predefined-server-alist))
+             ;; If not, we look through all the opened server
+             ;; to see whether we can find it there.
+             (let ((opened gnus-opened-servers))
+               (while (and opened
+                           (not (equal server (format "%s:%s" (caaar opened)
+                                                      (cadaar opened)))))
+                 (pop opened))
+               (caar opened))
+             ;; It could be a named method, search all servers
+             (let ((servers gnus-secondary-select-methods))
+               (while (and servers
+                           (not (equal server (format "%s:%s" (caar servers)
+                                                      (cadar servers)))))
+                 (pop servers))
+               (car servers))
+              ;; This could be some sort of foreign server that I
+              ;; simply haven't opened (yet).  Do a brute-force scan
+              ;; of the entire gnus-newsrc-alist for the server name
+              ;; of every method.  As a side-effect, loads the
+              ;; gnus-server-method-cache so this only happens once,
+              ;; if at all.
+              (let (match)
+                (mapcar 
+                 (lambda (info)
+                   (let ((info-method (gnus-info-method info)))
+                     (unless (stringp info-method)
+                       (let ((info-server (gnus-method-to-server info-method)))
+                         (when (equal server info-server)
+                           (setq match info-method))))))
+                 (cdr gnus-newsrc-alist))
+                match))))
+        (when result
+          (push (cons server result) gnus-server-method-cache))
+       result)))
+
+(defsubst gnus-method-to-server (method)
+  (catch 'server-name
+    (setq method (or method gnus-select-method))
+
+    ;; Perhaps it is already in the cache.
+    (mapc (lambda (name-method)
+            (if (equal (cdr name-method) method)
+                (throw 'server-name (car name-method))))
+          gnus-server-method-cache)
+
+    (mapc
+     (lambda (server-alist)
+       (mapc (lambda (name-method)
+               (when (gnus-methods-equal-p (cdr name-method) method)
+                 (unless (member name-method gnus-server-method-cache)
+                   (push name-method gnus-server-method-cache))
+                 (throw 'server-name (car name-method))))
+             server-alist))
+     (let ((alists (list gnus-server-alist
+                         gnus-predefined-server-alist)))
+       (if gnus-select-method
+           (push (list (cons "native" gnus-select-method)) alists))
+       alists))
+
+    (let* ((name (if (member (cadr method) '(nil ""))
+                     (format "%s" (car method))
+                   (format "%s:%s" (car method) (cadr method))))
+           (name-method (cons name method)))
+      (unless (member name-method gnus-server-method-cache)
+        (push name-method gnus-server-method-cache))
+      name)))
+
 (defsubst gnus-server-get-method (group method)
   ;; Input either a server name, and extended server name, or a
   ;; select method, and return a select method.
@@ -2231,34 +3433,16 @@ that that variable is buffer-local to the summary buffers."
         (gnus-server-to-method method))
        ((equal method gnus-select-method)
         gnus-select-method)
-       ((and (stringp (car method)) group)
+       ((and (stringp (car method))
+             group)
         (gnus-server-extend-method group method))
-       ((and method (not group)
+       ((and method
+             (not group)
              (equal (cadr method) ""))
         method)
        (t
         (gnus-server-add-address method))))
 
-(defun gnus-server-to-method (server)
-  "Map virtual server names to select methods."
-  (or
-   ;; Is this a method, perhaps?
-   (and server (listp server) server)
-   ;; Perhaps this is the native server?
-   (and (equal server "native") gnus-select-method)
-   ;; It should be in the server alist.
-   (cdr (assoc server gnus-server-alist))
-   ;; It could be in the predefined server alist.
-   (cdr (assoc server gnus-predefined-server-alist))
-   ;; If not, we look through all the opened server
-   ;; to see whether we can find it there.
-   (let ((opened gnus-opened-servers))
-     (while (and opened
-                (not (equal server (format "%s:%s" (caaar opened)
-                                           (cadaar opened)))))
-       (pop opened))
-     (caar opened))))
-
 (defmacro gnus-method-equal (ss1 ss2)
   "Say whether two servers are equal."
   `(let ((s1 ,ss1)
@@ -2270,6 +3454,15 @@ that that variable is buffer-local to the summary buffers."
                  (setq s1 (cdr s1)))
                (null s1))))))
 
+(defun gnus-methods-equal-p (m1 m2)
+  (let ((m1 (or m1 gnus-select-method))
+       (m2 (or m2 gnus-select-method)))
+    (or (equal m1 m2)
+       (and (eq (car m1) (car m2))
+            (or (not (memq 'address (assoc (symbol-name (car m1))
+                                           gnus-valid-select-methods)))
+                (equal (nth 1 m1) (nth 1 m2)))))))
+
 (defun gnus-server-equal (m1 m2)
   "Say whether two methods are equal."
   (let ((m1 (cond ((null m1) gnus-select-method)
@@ -2304,27 +3497,77 @@ that that variable is buffer-local to the summary buffers."
       (and active
           (file-exists-p active))))))
 
-(defun gnus-group-prefixed-name (group method)
-  "Return the whole name from GROUP and METHOD."
-  (and (stringp method) (setq method (gnus-server-to-method method)))
+(defsubst gnus-method-to-server-name (method)
+  (concat
+   (format "%s" (car method))
+   (when (and
+         (or (assoc (format "%s" (car method))
+                    (gnus-methods-using 'address))
+             (gnus-server-equal method gnus-message-archive-method))
+         (nth 1 method)
+         (not (string= (nth 1 method) "")))
+     (concat "+" (nth 1 method)))))
+
+(defsubst gnus-method-to-full-server-name (method)
+  (format "%s+%s" (car method) (nth 1 method)))
+
+(defun gnus-group-prefixed-name (group method &optional full)
+  "Return the whole name from GROUP and METHOD.
+Call with full set to get the fully qualified group name (even if the
+server is native)."
+  (when (stringp method)
+    (setq method (gnus-server-to-method method)))
   (if (or (not method)
-         (gnus-server-equal method "native"))
+         (and (not full) (gnus-server-equal method "native"))
+         ;;;!!! This might not be right.  We'll see...
+         ;(string-match ":" group)
+         )
+      group
+    (concat (gnus-method-to-server-name method) ":" group)))
+
+(defun gnus-group-guess-prefixed-name (group)
+  "Guess the whole name from GROUP and METHOD."
+  (gnus-group-prefixed-name group (gnus-find-method-for-group
+                              group)))
+
+(defun gnus-group-full-name (group method)
+  "Return the full name from GROUP and METHOD, even if the method is native."
+  (gnus-group-prefixed-name group method t))
+
+(defun gnus-group-guess-full-name (group)
+  "Guess the full name from GROUP, even if the method is native."
+  (if (gnus-group-prefixed-p group)
+      group
+    (gnus-group-full-name group (gnus-find-method-for-group group))))
+
+(defun gnus-group-guess-full-name-from-command-method (group)
+  "Guess the full name from GROUP, even if the method is native."
+  (if (gnus-group-prefixed-p group)
       group
-    (concat (format "%s" (car method))
-           (when (and
-                  (or (assoc (format "%s" (car method))
-                             (gnus-methods-using 'address))
-                      (gnus-server-equal method gnus-message-archive-method))
-                  (nth 1 method)
-                  (not (string= (nth 1 method) "")))
-             (concat "+" (nth 1 method)))
-           ":" group)))
+    (gnus-group-full-name group gnus-command-method)))
 
 (defun gnus-group-real-prefix (group)
   "Return the prefix of the current group name."
-  (if (string-match "^[^:]+:" group)
-      (substring group 0 (match-end 0))
-    ""))
+  (if (stringp group)
+      (if (string-match "^[^:]+:" group)
+         (substring group 0 (match-end 0))
+       "")
+    nil))
+
+(defun gnus-group-short-name (group)
+  "Return the short group name."
+  (let ((prefix (gnus-group-real-prefix group)))
+    (if (< 0 (length prefix))
+       (substring group (length prefix) nil)
+      group)))
+
+(defun gnus-group-prefixed-p (group)
+  "Return the prefix of the current group name."
+  (< 0 (length (gnus-group-real-prefix group))))
+
+(defun gnus-summary-buffer-name (group)
+  "Return the summary buffer name of GROUP."
+  (concat "*Summary " (gnus-group-decoded-name group) "*"))
 
 (defun gnus-group-method (group)
   "Return the server or method used for selecting GROUP.
@@ -2351,16 +3594,32 @@ You should probably use `gnus-find-method-for-group' instead."
            possible
            (list backend server))))))
 
+(defsubst gnus-native-method-p (method)
+  "Return whether METHOD is the native select method."
+  (gnus-method-equal method gnus-select-method))
+
 (defsubst gnus-secondary-method-p (method)
   "Return whether METHOD is a secondary select method."
   (let ((methods gnus-secondary-select-methods)
-       (gmethod (gnus-server-get-method nil method)))
+       (gmethod (inline (gnus-server-get-method nil method))))
     (while (and methods
-               (not (equal (gnus-server-get-method nil (car methods))
-                           gmethod)))
+               (not (gnus-method-equal
+                     (inline (gnus-server-get-method nil (car methods)))
+                     gmethod)))
       (setq methods (cdr methods)))
     methods))
 
+(defun gnus-method-simplify (method)
+  "Return the shortest uniquely identifying string or method for METHOD."
+  (cond ((stringp method)
+        method)
+       ((gnus-native-method-p method)
+        nil)
+       ((gnus-secondary-method-p method)
+        (format "%s:%s" (nth 0 method) (nth 1 method)))
+       (t
+        method)))
+
 (defun gnus-groups-from-server (server)
   "Return a list of all groups that are fetched from SERVER."
   (let ((alist (cdr gnus-newsrc-alist))
@@ -2383,30 +3642,116 @@ You should probably use `gnus-find-method-for-group' instead."
   "Say whether the group is secondary or not."
   (gnus-secondary-method-p (gnus-find-method-for-group group)))
 
-(defun gnus-group-find-parameter (group &optional symbol)
+(defun gnus-parameters-get-parameter (group)
+  "Return the group parameters for GROUP from `gnus-parameters'."
+  (let (params-list)
+    (dolist (elem gnus-parameters)
+      (when (string-match (car elem) group)
+       (setq params-list
+             (nconc (gnus-expand-group-parameters
+                     (car elem) (cdr elem) group)
+                    params-list))))
+    params-list))
+
+(defun gnus-expand-group-parameter (match value group)
+  "Use MATCH to expand VALUE in GROUP."
+  (with-temp-buffer
+    (insert group)
+    (goto-char (point-min))
+    (while (re-search-forward match nil t)
+      (replace-match value))
+    (buffer-string)))
+
+(defun gnus-expand-group-parameters (match parameters group)
+  "Go through PARAMETERS and expand them according to the match data."
+  (let (new)
+    (dolist (elem parameters)
+      (if (and (stringp (cdr elem))
+              (string-match "\\\\[0-9&]" (cdr elem)))
+         (push (cons (car elem)
+                     (gnus-expand-group-parameter match (cdr elem) group))
+               new)
+       (push elem new)))
+    new))
+
+(defun gnus-group-fast-parameter (group symbol &optional allow-list)
+  "For GROUP, return the value of SYMBOL.
+
+You should call this in the `gnus-group-buffer' buffer.
+The function `gnus-group-find-parameter' will do that for you."
+  ;; The speed trick:  No cons'ing and quit early.
+  (let* ((params (funcall gnus-group-get-parameter-function group))
+        ;; Start easy, check the "real" group parameters.
+        (simple-results
+         (gnus-group-parameter-value params symbol allow-list t)))
+    (if simple-results
+       ;; Found results; return them.
+       (car simple-results)
+      ;; We didn't found it there, try `gnus-parameters'.
+      (let ((result nil)
+           (head nil)
+           (tail gnus-parameters))
+       ;; A good old-fashioned non-cl loop.
+       (while tail
+         (setq head (car tail)
+               tail (cdr tail))
+         ;; The car is regexp matching for matching the group name.
+         (when (string-match (car head) group)
+           ;; The cdr is the parameters.
+           (setq result (gnus-group-parameter-value (cdr head)
+                                                    symbol allow-list))
+           (when result
+             ;; Expand if necessary.
+             (if (and (stringp result) (string-match "\\\\[0-9&]" result))
+                 (setq result (gnus-expand-group-parameter (car head)
+                                                           result group)))
+             ;; Exit the loop early.
+             (setq tail nil))))
+       ;; Done.
+       result))))
+
+(defun gnus-group-find-parameter (group &optional symbol allow-list)
   "Return the group parameters for GROUP.
-If SYMBOL, return the value of that symbol in the group parameters."
+If SYMBOL, return the value of that symbol in the group parameters.
+
+If you call this function inside a loop, consider using the faster
+`gnus-group-fast-parameter' instead."
   (save-excursion
     (set-buffer gnus-group-buffer)
-    (let ((parameters (funcall gnus-group-get-parameter-function group)))
-      (if symbol
-         (gnus-group-parameter-value parameters symbol)
-       parameters))))
+    (if symbol
+       (gnus-group-fast-parameter group symbol allow-list)
+      (nconc
+       (copy-sequence
+       (funcall gnus-group-get-parameter-function group))
+       (gnus-parameters-get-parameter group)))))
 
-(defun gnus-group-get-parameter (group &optional symbol)
+(defun gnus-group-get-parameter (group &optional symbol allow-list)
   "Return the group parameters for GROUP.
 If SYMBOL, return the value of that symbol in the group parameters.
 Most functions should use `gnus-group-find-parameter', which
 also examines the topic parameters."
   (let ((params (gnus-info-params (gnus-get-info group))))
     (if symbol
-       (gnus-group-parameter-value params symbol)
+       (gnus-group-parameter-value params symbol allow-list)
       params)))
 
-(defun gnus-group-parameter-value (params symbol)
+(defun gnus-group-parameter-value (params symbol &optional
+                                         allow-list present-p)
   "Return the value of SYMBOL in group PARAMS."
-  (or (car (memq symbol params))       ; It's either a simple symbol
-      (cdr (assq symbol params))))     ; or a cons.
+  ;; We only wish to return group parameters (dotted lists) and
+  ;; not local variables, which may have the same names.
+  ;; But first we handle single elements...
+  (or (car (memq symbol params))
+      ;; Handle alist.
+      (let (elem)
+       (catch 'found
+         (while (setq elem (pop params))
+           (when (and (consp elem)
+                      (eq (car elem) symbol)
+                      (or allow-list
+                          (atom (cdr elem))))
+             (throw 'found (if present-p (list (cdr elem))
+                             (cdr elem)))))))))
 
 (defun gnus-group-add-parameter (group param)
   "Add parameter PARAM to GROUP."
@@ -2439,7 +3784,7 @@ also examines the topic parameters."
        (when params
          (setq params (delq name params))
          (while (assq name params)
-           (setq params (delq (assq name params) params)))
+           (gnus-pull name params))
          (gnus-info-set-params info params))))))
 
 (defun gnus-group-add-score (group &optional score)
@@ -2449,47 +3794,60 @@ If SCORE is nil, add 1 to the score of GROUP."
     (when info
       (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
 
-;; Function written by Stainless Steel Rat <ratinox@peorth.gweep.net>
 (defun gnus-short-group-name (group &optional levels)
   "Collapse GROUP name LEVELS.
 Select methods are stripped and any remote host name is stripped down to
 just the host name."
-  (let* ((name "") (foreign "") (depth -1) (skip 1)
+  (let* ((name "")
+        (foreign "")
+        (depth 0)
+        (skip 1)
         (levels (or levels
+                    gnus-group-uncollapsed-levels
                     (progn
                       (while (string-match "\\." group skip)
                         (setq skip (match-end 0)
                               depth (+ depth 1)))
                       depth))))
-    ;; separate foreign select method from group name and collapse.
-    ;; if method contains a server, collapse to non-domain server name,
-    ;; otherwise collapse to select method
-    (when (string-match ":" group)
-      (cond ((string-match "+" group)
-            (let* ((plus (string-match "+" group))
-                   (colon (string-match ":" group (or plus 0)))
-                   (dot (string-match "\\." group)))
-              (setq foreign (concat
-                             (substring group (+ 1 plus)
-                                        (cond ((null dot) colon)
-                                              ((< colon dot) colon)
-                                              ((< dot colon) dot)))
-                             ":")
-                    group (substring group (+ 1 colon)))))
-           (t
-            (let* ((colon (string-match ":" group)))
-              (setq foreign (concat (substring group 0 (+ 1 colon)))
-                    group (substring group (+ 1 colon)))))))
-    ;; collapse group name leaving LEVELS uncollapsed elements
-    (while group
-      (if (and (string-match "\\." group) (> levels 0))
-         (setq name (concat name (substring group 0 1))
-               group (substring group (match-end 0))
-               levels (- levels 1)
-               name (concat name "."))
-       (setq name (concat foreign name group)
-             group nil)))
-    name))
+    ;; Separate foreign select method from group name and collapse.
+    ;; If method contains a server, collapse to non-domain server name,
+    ;; otherwise collapse to select method.
+    (let* ((colon (string-match ":" group))
+          (server (and colon (substring group 0 colon)))
+          (plus (and server (string-match "+" server))))
+      (when server
+       (if plus
+           (setq foreign (substring server (+ 1 plus)
+                                    (string-match "\\." server))
+                 group (substring group (+ 1 colon)))
+         (setq foreign server
+               group (substring group (+ 1 colon))))
+       (setq foreign (concat foreign ":")))
+      ;; Collapse group name leaving LEVELS uncollapsed elements
+      (let* ((slist (split-string group "/"))
+            (slen (length slist))
+            (dlist (split-string group "\\."))
+            (dlen (length dlist))
+            glist
+            glen
+            gsep
+            res)
+       (if (> slen dlen)
+           (setq glist slist
+                 glen slen
+                 gsep "/")
+         (setq glist dlist
+               glen dlen
+               gsep "."))
+       (setq levels (- glen levels))
+       (dolist (g glist)
+         (push (if (>= (decf levels) 0)
+                   (if (zerop (length g))
+                       ""
+                     (substring g 0 1))
+                 g)
+               res))
+       (concat foreign (mapconcat 'identity (nreverse res) gsep))))))
 
 (defun gnus-narrow-to-body ()
   "Narrow to the body of an article."
@@ -2567,6 +3925,7 @@ If NEWSGROUP is nil, return the global kill file name instead."
   (let ((opened gnus-opened-servers))
     (while (and method opened)
       (when (and (equal (cadr method) (cadaar opened))
+                (equal (car method) (caaar opened))
                 (not (equal method (caar opened))))
        (setq method nil))
       (pop opened))
@@ -2598,11 +3957,22 @@ If NEWSGROUP is nil, return the global kill file name instead."
          (list (intern server) "")))
     gnus-select-method))
 
+(defun gnus-server-string (server)
+  "Return a readable string that describes SERVER."
+  (let* ((server (gnus-server-to-method server))
+        (address (nth 1 server)))
+    (if (and address
+            (not (zerop (length address))))
+       (format "%s using %s" address (car server))
+      (format "%s" (car server)))))
+
 (defun gnus-find-method-for-group (group &optional info)
   "Find the select method that GROUP uses."
   (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)
@@ -2635,57 +4005,105 @@ If NEWSGROUP is nil, return the global kill file name instead."
 
 (defun gnus-read-group (prompt &optional default)
   "Prompt the user for a group name.
-Disallow illegal group names."
+Disallow invalid group names."
   (let ((prefix "")
        group)
     (while (not group)
       (when (string-match
-            "[: `'\"/]\\|^$"
+            gnus-invalid-group-regexp
             (setq group (read-string (concat prefix prompt)
                                      (cons (or default "") 0)
                                      'gnus-group-history)))
-       (setq prefix (format "Illegal group name: \"%s\".  " group)
-             group nil)))
+       (let ((match (match-string 0 group)))
+         ;; Might be okay (e.g. for nnimap), so ask the user:
+         (unless (and (not (string-match "^$\\|:" match))
+                      (message-y-or-n-p
+                       "Proceed and create group anyway? " t
+"The group name \"" group "\" contains a forbidden character: \"" match "\".
+
+Usually, it's dangerous to create a group with this name, because it's not
+supported by all back ends and servers.  On IMAP servers it should work,
+though.  If you are really sure, you can proceed anyway and create the group.
+
+You may customize the variable `gnus-invalid-group-regexp', which currently is
+set to \"" gnus-invalid-group-regexp
+"\", if you want to get rid of this query permanently."))
+           (setq prefix (format "Invalid group name: \"%s\".  " group)
+                 group nil)))))
     group))
 
 (defun gnus-read-method (prompt)
   "Prompt the user for a method.
 Allow completion over sensible values."
-  (let ((method
-        (completing-read
-         prompt (append gnus-valid-select-methods gnus-predefined-server-alist
-                        gnus-server-alist)
-         nil t nil 'gnus-method-history)))
+  (let* ((open-servers
+         (mapcar (lambda (i) (cons (format "%s:%s" (caar i) (cadar i)) i))
+                 gnus-opened-servers))
+        (valid-methods
+         (let (methods)
+           (dolist (method gnus-valid-select-methods)
+             (if (or (memq 'prompt-address method)
+                     (not (assoc (format "%s:" (car method)) open-servers)))
+                 (push method methods)))
+           methods))
+        (servers
+         (append valid-methods
+                 open-servers
+                 gnus-predefined-server-alist
+                 gnus-server-alist))
+        (method
+         (completing-read
+          prompt servers
+          nil t nil 'gnus-method-history)))
     (cond
      ((equal method "")
       (setq method gnus-select-method))
      ((assoc method gnus-valid-select-methods)
-      (list (intern method)
-           (if (memq 'prompt-address
-                     (assoc method gnus-valid-select-methods))
-               (read-string "Address: ")
-             "")))
-     ((assoc method gnus-server-alist)
+      (let ((address (if (memq 'prompt-address
+                              (assoc method gnus-valid-select-methods))
+                        (read-string "Address: ")
+                      "")))
+       (or (cadr (assoc (format "%s:%s" method address) open-servers))
+           (list (intern method) address))))
+     ((assoc method servers)
       method)
      (t
       (list (intern method) "")))))
 
+;;; Agent functions
+
+(defun gnus-agent-method-p (method)
+  "Say whether METHOD is covered by the agent."
+  (or (eq (car gnus-agent-method-p-cache) method)
+      (setq gnus-agent-method-p-cache 
+            (cons method
+                  (member (if (stringp method) 
+                              method 
+                            (gnus-method-to-server method)) gnus-agent-covered-methods))))
+  (cdr gnus-agent-method-p-cache))
+
+(defun gnus-online (method)
+  (not
+   (if gnus-plugged
+       (eq (cadr (assoc method gnus-opened-servers)) 'offline)
+     (gnus-agent-method-p method))))
+
 ;;; User-level commands.
 
 ;;;###autoload
 (defun gnus-slave-no-server (&optional arg)
-  "Read network news as a slave, without connecting to local server"
+  "Read network news as a slave, without connecting to the local server."
   (interactive "P")
   (gnus-no-server arg t))
 
 ;;;###autoload
 (defun gnus-no-server (&optional arg slave)
   "Read network news.
-If ARG is a positive number, Gnus will use that as the
-startup level. If ARG is nil, Gnus will be started at level 2.
-If ARG is non-nil and not a positive number, Gnus will
-prompt the user for the name of an NNTP server to use.
-As opposed to `gnus', this command will not connect to the local server."
+If ARG is a positive number, Gnus will use that as the startup
+level. If ARG is nil, Gnus will be started at level 2.  If ARG is
+non-nil and not a positive number, Gnus will prompt the user for the
+name of an NNTP server to use.
+As opposed to `gnus', this command will not connect to the local
+server."
   (interactive "P")
   (gnus-no-server-1 arg slave))
 
@@ -2695,32 +4113,77 @@ As opposed to `gnus', this command will not connect to the local server."
   (interactive "P")
   (gnus arg nil 'slave))
 
+(defcustom gnus-frame-properties nil
+  "The properties of the frame in which gnus is displayed. Under XEmacs,
+the variable `toolbar-news-frame-plist' will be refered instead."
+  :type '(repeat (cons :format "%v"
+                      (symbol :tag "Parameter")
+                      (sexp :tag "Value")))
+  :group 'gnus)
+
 ;;;###autoload
-(defun gnus-other-frame (&optional arg)
-  "Pop up a frame to read news."
+(defun gnus-other-frame (&optional arg display)
+  "Pop up a frame to read news.
+This will call one of the Gnus commands which is specified by the user
+option `gnus-other-frame-function' (default `gnus') with the argument
+ARG if Gnus is not running, otherwise just pop up a Gnus frame.  The
+optional second argument DISPLAY should be a standard display string
+such as \"unix:0\" to specify where to pop up a frame.  If DISPLAY is
+omitted or the function `make-frame-on-display' is not available, the
+current display is used."
   (interactive "P")
-  (let ((window (get-buffer-window gnus-group-buffer)))
-    (cond (window
-          (select-frame (window-frame window)))
-         ((= (length (frame-list)) 1)
-          (select-frame (make-frame)))
-         (t
-          (other-frame 1))))
-  (gnus arg))
+  (if (fboundp 'make-frame-on-display)
+      (unless display
+       (setq display (gnus-frame-or-window-display-name (selected-frame))))
+    (setq display nil))
+  (let ((alive (gnus-alive-p)))
+    (unless (and alive
+                (catch 'found
+                  (walk-windows
+                   (lambda (window)
+                     (when (and (or (not display)
+                                    (equal display
+                                           (gnus-frame-or-window-display-name
+                                            window)))
+                                (with-current-buffer (window-buffer window)
+                                  (string-match "\\`gnus-"
+                                                (symbol-name major-mode))))
+                       (gnus-select-frame-set-input-focus
+                        (setq gnus-other-frame-object (window-frame window)))
+                       (select-window window)
+                       (throw 'found t)))
+                   'ignore t)))
+      (gnus-select-frame-set-input-focus
+       (setq gnus-other-frame-object
+            (if display
+                (make-frame-on-display display gnus-other-frame-parameters)
+              (make-frame gnus-other-frame-parameters))))
+      (if alive
+         (switch-to-buffer gnus-group-buffer)
+       (funcall gnus-other-frame-function arg)
+       (add-hook 'gnus-exit-gnus-hook
+                 '(lambda nil
+                    (when (and (frame-live-p gnus-other-frame-object)
+                               (cdr (frame-list)))
+                      (delete-frame gnus-other-frame-object))
+                    (setq gnus-other-frame-object nil)))))))
 
 ;;;###autoload
 (defun gnus (&optional arg dont-connect slave)
   "Read network news.
 If ARG is non-nil and a positive number, Gnus will use that as the
-startup level. If ARG is non-nil and not a positive number, Gnus will
+startup level.  If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use."
   (interactive "P")
+  (unless (byte-code-function-p (symbol-function 'gnus))
+    (message "You should byte-compile Gnus")
+    (sit-for 2))
   (gnus-1 arg dont-connect slave))
 
 ;; Allow redefinition of Gnus functions.
 
 (gnus-ems-redefine)
 
-(provide 'gnus)
+(product-provide (provide 'gnus) 'gnus-vers)
 
 ;;; gnus.el ends here
diff --git a/lisp/hex-util.el b/lisp/hex-util.el
new file mode 100644 (file)
index 0000000..6936bf3
--- /dev/null
@@ -0,0 +1,73 @@
+;;; hex-util.el --- Functions to encode/decode hexadecimal string.
+
+;; Copyright (C) 1999, 2001  Free Software Foundation, Inc.
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: data
+
+;; This file is part of FLIM (Faithful Library about Internet Message).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile
+  (defmacro hex-char-to-num (chr)
+    (` (let ((chr (, chr)))
+        (cond
+         ((and (<= ?a chr)(<= chr ?f)) (+ (- chr ?a) 10))
+         ((and (<= ?A chr)(<= chr ?F)) (+ (- chr ?A) 10))
+         ((and (<= ?0 chr)(<= chr ?9)) (- chr ?0))
+         (t (error "Invalid hexadecimal digit `%c'" chr))))))
+  (defmacro num-to-hex-char (num)
+    (` (aref "0123456789abcdef" (, num)))))
+
+(defun decode-hex-string (string)
+  "Decode hexadecimal STRING to octet string."
+  (let* ((len (length string))
+        (dst (make-string (/ len 2) 0))
+        (idx 0)(pos 0))
+    (while (< pos len)
+;;; logior and lsh are not byte-coded.
+;;;  (aset dst idx (logior (lsh (hex-char-to-num (aref string pos)) 4)
+;;;                        (hex-char-to-num (aref string (1+ pos)))))
+      (aset dst idx (+ (* (hex-char-to-num (aref string pos)) 16)
+                      (hex-char-to-num (aref string (1+ pos)))))
+      (setq idx (1+ idx)
+           pos (+ 2 pos)))
+    dst))
+
+(defun encode-hex-string (string)
+  "Encode octet STRING to hexadecimal string."
+  (let* ((len (length string))
+        (dst (make-string (* len 2) 0))
+        (idx 0)(pos 0))
+    (while (< pos len)
+;;; logand and lsh are not byte-coded.
+;;;  (aset dst idx (num-to-hex-char (logand (lsh (aref string pos) -4) 15)))
+      (aset dst idx (num-to-hex-char (/ (aref string pos) 16)))
+      (setq idx (1+ idx))
+;;;  (aset dst idx (num-to-hex-char (logand (aref string pos) 15)))
+      (aset dst idx (num-to-hex-char (% (aref string pos) 16)))
+      (setq idx (1+ idx)
+           pos (1+ pos)))
+    dst))
+
+(provide 'hex-util)
+
+;;; hex-util.el ends here
diff --git a/lisp/html2text.el b/lisp/html2text.el
new file mode 100644 (file)
index 0000000..41fea4b
--- /dev/null
@@ -0,0 +1,549 @@
+;;; html2text.el --- a simple html to plain text converter
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Joakim Hove <hove@phys.ntnu.no>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; These functions provide a simple way to wash/clean html infected
+;; mails.  Definitely do not work in all cases, but some improvement
+;; in readability is generally obtained. Formatting is only done in
+;; the buffer, so the next time you enter the article it will be
+;; "re-htmlized".
+;;
+;; The main function is "html2text"
+
+;;; Code:
+
+;;
+;; <Global variables>
+;;
+
+(eval-when-compile
+  (require 'cl))
+
+(defvar html2text-format-single-element-list '(("hr" . html2text-clean-hr)))
+
+(defvar html2text-replace-list
+  '(("&nbsp;" . " ") ("&gt;" . ">") ("&lt;" . "<") ("&quot;" . "\""))
+  "The map of entity to text.
+
+This is an alist were each element is a dotted pair consisting of an
+old string, and a replacement string. This replacement is done by the
+function \"html2text-substitute\" which basically performs a
+replace-string operation for every element in the list. This is
+completely verbatim - without any use of REGEXP.")
+
+(defvar html2text-remove-tag-list
+  '("html" "body" "p" "img" "dir" "head" "div" "br" "font" "title" "meta")
+  "A list of removable tags.
+
+This is a list of tags which should be removed, without any
+formatting.  Observe that if you the tags in the list are presented
+*without* any \"<\" or \">\". All occurences of a tag appearing in
+this list are removed, irrespective of whether it is a closing or
+opening tag, or if the tag has additional attributes. The actual
+deletion is done by the function \"html2text-remove-tags\".
+
+For instance the text:
+
+\"Here comes something <font size\"+3\" face=\"Helvetica\"> big </font>.\"
+
+will be reduced to:
+
+\"Here comes something big.\"
+
+If this list contains the element \"font\".")
+
+(defvar html2text-format-tag-list
+  '(("b"         . html2text-clean-bold)
+    ("u"         . html2text-clean-underline)
+    ("i"         . html2text-clean-italic)
+    ("blockquote" . html2text-clean-blockquote)
+    ("a"          . html2text-clean-anchor)
+    ("ul"         . html2text-clean-ul)
+    ("ol"         . html2text-clean-ol)
+    ("dl"         . html2text-clean-dl)
+    ("center"     . html2text-clean-center))
+  "An alist of tags and processing functions.
+
+This is an alist where each dotted pair consists of a tag, and then
+the name of a function to be called when this tag is found. The
+function is called with the arguments p1, p2, p3 and p4. These are
+demontrated below:
+
+\"<b> This is bold text </b>\"
+ ^   ^                 ^    ^
+ |   |                 |    |
+p1  p2                p3   p4
+
+Then the called function will typically format the text somewhat and
+remove the tags.")
+
+(defvar html2text-remove-tag-list2  '("li" "dt" "dd" "meta")
+  "Another list of removable tags.
+
+This is a list of tags which are removed similarly to the list
+`html2text-remove-tag-list' - but these tags are retained for the
+formatting, and then moved afterward.")
+
+;;
+;; </Global variables>
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; <Utility functions>
+;;
+
+(defun html2text-buffer-head ()
+  (if (string= mode-name "Article")
+      (beginning-of-buffer)
+    (beginning-of-buffer)
+    )
+  )
+
+(defun html2text-replace-string (from-string to-string p1 p2)
+  (goto-char p1)
+  (let ((delta (- (string-width to-string) (string-width from-string)))
+       (change 0))
+    (while (search-forward from-string p2 t)
+      (replace-match to-string)
+      (setq change (+ change delta))
+      )
+    change
+    )
+  )
+
+;;
+;; </Utility functions>
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; <Functions related to attributes> i.e. <font size=+3>
+;;
+
+(defun html2text-attr-value (attr-list attr)
+  (nth 1 (assoc attr attr-list))
+  )
+
+(defun html2text-get-attr (p1 p2 tag)
+  (goto-char p1)
+  (re-search-forward " +[^ ]" p2 t)
+  (let* ((attr-string (buffer-substring-no-properties (1- (point)) (1- p2)))
+        (tmp-list (split-string attr-string))
+        (attr-list)
+        (counter 0)
+        (prev (car tmp-list))
+        (this (nth 1 tmp-list))
+        (next (nth 2 tmp-list))
+        (index 1))
+
+    (cond
+     ;; size=3
+     ((string-match "[^ ]=[^ ]" prev)
+      (let ((attr  (nth 0 (split-string prev "=")))
+           (value (nth 1 (split-string prev "="))))
+       (setq attr-list (cons (list attr value) attr-list))
+       )
+      )
+     ;; size= 3
+     ((string-match "[^ ]=\\'" prev)
+      (setq attr-list (cons (list (substring prev 0 -1) this) attr-list))
+      )
+     )
+
+    (while (< index (length tmp-list))
+      (cond
+       ;; size=3
+       ((string-match "[^ ]=[^ ]" this)
+       (let ((attr  (nth 0 (split-string this "=")))
+             (value (nth 1 (split-string this "="))))
+         (setq attr-list (cons (list attr value) attr-list))
+         )
+       )
+       ;; size =3
+       ((string-match "\\`=[^ ]" this)
+       (setq attr-list (cons (list prev (substring this 1)) attr-list)))
+
+       ;; size= 3
+       ((string-match "[^ ]=\\'" this)
+       (setq attr-list (cons (list (substring this 0 -1) next) attr-list))
+       )
+
+       ;; size = 3
+       ((string= "=" this)
+       (setq attr-list (cons (list prev next) attr-list))
+       )
+       )
+      (setq index (1+ index))
+      (setq prev this)
+      (setq this next)
+      (setq next (nth (1+ index) tmp-list))
+      )
+
+    ;;
+    ;; Tags with no accompanying "=" i.e. value=nil
+    ;;
+    (setq prev (car tmp-list))
+    (setq this (nth 1 tmp-list))
+    (setq next (nth 2 tmp-list))
+    (setq index 1)
+
+    (if (not (string-match "=" prev))
+       (progn
+         (if (not (string= (substring this 0 1) "="))
+             (setq attr-list (cons (list prev nil) attr-list))
+           )
+         )
+      )
+
+    (while (< index (1- (length tmp-list)))
+      (if (not (string-match "=" this))
+         (if (not (or (string= (substring next 0 1) "=")
+                      (string= (substring prev -1) "=")))
+             (setq attr-list (cons (list this nil) attr-list))
+           )
+       )
+      (setq index (1+ index))
+      (setq prev this)
+      (setq this next)
+      (setq next (nth (1+ index) tmp-list))
+      )
+
+    (if this
+       (progn
+         (if (not (string-match "=" this))
+             (progn
+               (if (not (string= (substring prev -1) "="))
+                   (setq attr-list (cons (list this nil) attr-list))
+                 )
+               )
+           )
+         )
+      )
+    attr-list ;; return - value
+    )
+  )
+
+;;
+;; </Functions related to attributes>
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; <Functions to be called to format a tag-pair>
+;;
+(defun html2text-clean-list-items (p1 p2 list-type)
+  (goto-char p1)
+  (let ((item-nr 0)
+       (items   0))
+    (while (re-search-forward "<li>" p2 t)
+      (setq items (1+ items)))
+    (goto-char p1)
+    (while (< item-nr items)
+      (setq item-nr (1+ item-nr))
+      (re-search-forward "<li>" (point-max) t)
+      (cond
+       ((string= list-type "ul") (insert " o "))
+       ((string= list-type "ol") (insert (format " %s: " item-nr)))
+       (t (insert " x ")))
+      )
+    )
+  )
+
+(defun html2text-clean-dtdd (p1 p2)
+  (goto-char p1)
+  (let ((items   0)
+       (item-nr 0))
+    (while (re-search-forward "<dt>" p2 t)
+      (setq items (1+ items)))
+    (goto-char p1)
+    (while (< item-nr items)
+      (setq item-nr (1+ item-nr))
+      (re-search-forward "<dt>\\([ ]*\\)" (point-max) t)
+      (when (match-string 1)
+       (delete-region (point) (- (point) (string-width (match-string 1)))))
+      (let ((def-p1 (point))
+           (def-p2 0))
+       (re-search-forward "\\([ ]*\\)\\(</dt>\\|<dd>\\)" (point-max) t)
+       (if (match-string 1)
+           (progn
+             (let* ((mw1 (string-width (match-string 1)))
+                    (mw2 (string-width (match-string 2)))
+                    (mw  (+ mw1 mw2)))
+               (goto-char (- (point) mw))
+               (delete-region (point) (+ (point) mw1))
+               (setq def-p2 (point))))
+         (setq def-p2 (- (point) (string-width (match-string 2)))))
+       (put-text-property def-p1 def-p2 'face 'bold)))))
+
+(defun html2text-delete-tags (p1 p2 p3 p4)
+  (delete-region p1 p2)
+  (delete-region (- p3 (- p2 p1)) (- p4 (- p2 p1))))
+
+(defun html2text-delete-single-tag (p1 p2)
+  (delete-region p1 p2))
+
+(defun html2text-clean-hr (p1 p2)
+  (html2text-delete-single-tag p1 p2)
+  (goto-char p1)
+  (newline 1)
+  (insert (make-string fill-column ?-))
+  )
+
+(defun html2text-clean-ul (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  (html2text-clean-list-items p1 (- p3 (- p1 p2)) "ul")
+  )
+
+(defun html2text-clean-ol (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  (html2text-clean-list-items p1 (- p3 (- p1 p2)) "ol")
+  )
+
+(defun html2text-clean-dl (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  (html2text-clean-dtdd p1 (- p3 (- p1 p2)))
+  )
+
+(defun html2text-clean-center (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  (center-region p1 (- p3 (- p2 p1)))
+  )
+
+(defun html2text-clean-bold (p1 p2 p3 p4)
+  (put-text-property p2 p3 'face 'bold)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-title (p1 p2 p3 p4)
+  (put-text-property p2 p3 'face 'bold)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-underline (p1 p2 p3 p4)
+  (put-text-property p2 p3 'face 'underline)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-italic (p1 p2 p3 p4)
+  (put-text-property p2 p3 'face 'italic)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-font (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-blockquote (p1 p2 p3 p4)
+  (html2text-delete-tags p1 p2 p3 p4)
+  )
+
+(defun html2text-clean-anchor (p1 p2 p3 p4)
+  ;; If someone can explain how to make the URL clickable I will
+  ;; surely improve upon this.
+  (let* ((attr-list (html2text-get-attr p1 p2 "a"))
+        (href (html2text-attr-value attr-list "href")))
+    (delete-region p1 p4)
+    (when href
+      (goto-char p1)
+      (insert (substring href 1 -1 ))
+      (put-text-property p1 (point) 'face 'bold))))
+
+;;
+;; </Functions to be called to format a tag-pair>
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; <Functions to be called to fix up paragraphs>
+;;
+
+(defun html2text-fix-paragraph (p1 p2)
+  (goto-char p1)
+  (let ((has-br-line)
+       (refill-start)
+       (refill-stop))
+    (if (re-search-forward "<br>$" p2 t)
+       (setq has-br-line t)
+      )
+    (if has-br-line
+       (progn
+         (goto-char p1)
+         (if (re-search-forward ".+[^<][^b][^r][^>]$" p2 t)
+             (progn
+               (beginning-of-line)
+               (setq refill-start (point))
+               (goto-char p2)
+               (re-search-backward ".+[^<][^b][^r][^>]$" refill-start t)
+               (next-line 1)
+               (end-of-line)
+               ;; refill-stop should ideally be adjusted to
+               ;; accomodate the "<br>" strings which are removed
+               ;; between refill-start and refill-stop.  Can simply
+               ;; be returned from my-replace-string
+               (setq refill-stop (+ (point)
+                                    (html2text-replace-string
+                                     "<br>" ""
+                                     refill-start (point))))
+               ;; (message "Point = %s  refill-stop = %s" (point) refill-stop)
+               ;; (sleep-for 4)
+               (fill-region refill-start refill-stop)
+               )
+           )
+         )
+      )
+    )
+  (html2text-replace-string "<br>" "" p1 p2)
+  )
+
+;;
+;; This one is interactive ...
+;;
+(defun html2text-fix-paragraphs ()
+  "This _tries_ to fix up the paragraphs - this is done in quite a ad-hook
+fashion, quite close to pure guess-work. It does work in some cases though."
+  (interactive)
+  (html2text-buffer-head)
+  (replace-regexp "^<br>$" "")
+  ;; Removing lonely <br> on a single line, if they are left intact we
+  ;; dont have any paragraphs at all.
+  (html2text-buffer-head)
+  (while (not (eobp))
+    (let ((p1 (point)))
+      (forward-paragraph 1)
+      ;;(message "Kaller fix med p1=%s  p2=%s " p1 (1- (point))) (sleep-for 5)
+      (html2text-fix-paragraph p1 (1- (point)))
+      (goto-char p1)
+      (when (not (eobp))
+       (forward-paragraph 1)))))
+
+;;
+;; </Functions to be called to fix up paragraphs>
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; <Interactive functions>
+;;
+
+(defun html2text-remove-tags (tag-list)
+  "Removes the tags listed in the list \"html2text-remove-tag-list\".
+See the documentation for that variable."
+  (interactive)
+  (dolist (tag tag-list)
+    (html2text-buffer-head)
+    (while (re-search-forward (format "\\(</?%s[^>]*>\\)" tag) (point-max) t)
+      (delete-region (match-beginning 0) (match-end 0)))))
+
+(defun html2text-format-tags ()
+  "See the variable \"html2text-format-tag-list\" for documentation"
+  (interactive)
+  (dolist (tag-and-function html2text-format-tag-list)
+    (let ((tag      (car tag-and-function))
+         (function (cdr tag-and-function)))
+      (html2text-buffer-head)
+      (while (re-search-forward (format "\\(<%s\\( [^>]*\\)?>\\)" tag)
+                               (point-max) t)
+       (let ((p1)
+             (p2 (point))
+             (p3) (p4)
+             (attr (match-string 1)))
+         (search-backward "<" (point-min) t)
+         (setq p1 (point))
+         (re-search-forward (format "</%s>" tag) (point-max) t)
+         (setq p4 (point))
+         (search-backward "</" (point-min) t)
+         (setq p3 (point))
+         (funcall function p1 p2 p3 p4)
+         (goto-char p1)
+         )
+       )
+      )
+    )
+  )
+
+(defun html2text-substitute ()
+  "See the variable \"html2text-replace-list\" for documentation"
+  (interactive)
+  (dolist (e html2text-replace-list)
+    (html2text-buffer-head)
+    (let ((old-string (car e))
+         (new-string (cdr e)))
+      (html2text-replace-string old-string new-string (point-min) (point-max))
+      )
+    )
+  )
+
+(defun html2text-format-single-elements ()
+  ""
+  (interactive)
+  (dolist (tag-and-function html2text-format-single-element-list)
+    (let ((tag      (car tag-and-function))
+         (function (cdr tag-and-function)))
+      (html2text-buffer-head)
+      (while (re-search-forward (format "\\(<%s\\( [^>]*\\)?>\\)" tag)
+                               (point-max) t)
+       (let ((p1)
+             (p2 (point)))
+         (search-backward "<" (point-min) t)
+         (setq p1 (point))
+         (funcall function p1 p2)
+         )
+       )
+      )
+    )
+  )
+
+;;
+;; Main function
+;;
+
+;;;###autoload
+(defun html2text ()
+  "Convert HTML to plain text in the current buffer."
+  (interactive)
+  (save-excursion
+    (let ((case-fold-search t)
+         (buffer-read-only))
+      (html2text-remove-tags html2text-remove-tag-list)
+      (html2text-format-tags)
+      (html2text-remove-tags html2text-remove-tag-list2)
+      (html2text-substitute)
+      (html2text-format-single-elements)
+      (html2text-fix-paragraphs))))
+
+;;
+;; </Interactive functions>
+;;
+
+;;; html2text.el ends here
diff --git a/lisp/ietf-drums.el b/lisp/ietf-drums.el
new file mode 100644 (file)
index 0000000..c546316
--- /dev/null
@@ -0,0 +1,268 @@
+;;; ietf-drums.el --- Functions for parsing RFC822bis headers
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; DRUMS is an IETF Working Group that works (or worked) on the
+;; successor to RFC822, "Standard For The Format Of Arpa Internet Text
+;; Messages".  This library is based on
+;; draft-ietf-drums-msg-fmt-05.txt, released on 1998-08-05.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'time-date)
+(require 'mm-util)
+
+(defvar ietf-drums-no-ws-ctl-token "\001-\010\013\014\016-\037\177"
+  "US-ASCII control characters excluding CR, LF and white space.")
+(defvar ietf-drums-text-token "\001-\011\013\014\016-\177"
+  "US-ASCII characters excluding CR and LF.")
+(defvar ietf-drums-specials-token "()<>[]:;@\\,.\""
+  "Special characters.")
+(defvar ietf-drums-quote-token "\\"
+  "Quote character.")
+(defvar ietf-drums-wsp-token " \t"
+  "White space.")
+(defvar ietf-drums-fws-regexp
+  (concat "[" ietf-drums-wsp-token "]*\n[" ietf-drums-wsp-token "]+")
+  "Folding white space.")
+(defvar ietf-drums-atext-token "-^a-zA-Z0-9!#$%&'*+/=?_`{|}~"
+  "Textual token.")
+(defvar ietf-drums-dot-atext-token "-^a-zA-Z0-9!#$%&'*+/=?_`{|}~."
+  "Textual token including full stop.")
+(defvar ietf-drums-qtext-token
+  (concat ietf-drums-no-ws-ctl-token "\041\043-\133\135-\177")
+  "Non-white-space control characters, plus the rest of ASCII excluding
+backslash and doublequote.")
+(defvar ietf-drums-tspecials "][()<>@,;:\\\"/?="
+  "Tspecials.")
+
+(defvar ietf-drums-syntax-table
+  (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
+    (modify-syntax-entry ?\\ "/" table)
+    (modify-syntax-entry ?< "(" table)
+    (modify-syntax-entry ?> ")" table)
+    (modify-syntax-entry ?@ "w" table)
+    (modify-syntax-entry ?/ "w" table)
+    (modify-syntax-entry ?* " " table)
+    (modify-syntax-entry ?\; " " table)
+    (modify-syntax-entry ?\' " " table)
+    (if (featurep 'xemacs)
+       (let ((i 128))
+         (while (< i 256)
+           (modify-syntax-entry i "w" table)
+           (setq i (1+ i)))))
+    table))
+
+(defun ietf-drums-token-to-list (token)
+  "Translate TOKEN into a list of characters."
+  (let ((i 0)
+       b e c out range)
+    (while (< i (length token))
+      (setq c (mm-char-int (aref token i)))
+      (incf i)
+      (cond
+       ((eq c (mm-char-int ?-))
+       (if b
+           (setq range t)
+         (push c out)))
+       (range
+       (while (<= b c)
+         (push (mm-make-char 'ascii b) out)
+         (incf b))
+       (setq range nil))
+       ((= i (length token))
+       (push (mm-make-char 'ascii c) out))
+       (t
+       (when b
+         (push (mm-make-char 'ascii b) out))
+       (setq b c))))
+    (nreverse out)))
+
+(defsubst ietf-drums-init (string)
+  (set-syntax-table ietf-drums-syntax-table)
+  (insert string)
+  (ietf-drums-unfold-fws)
+  (goto-char (point-min)))
+
+(defun ietf-drums-remove-comments (string)
+  "Remove comments from STRING."
+  (with-temp-buffer
+    (let (c)
+      (ietf-drums-init string)
+      (while (not (eobp))
+       (setq c (char-after))
+       (cond
+        ((eq c ?\")
+         (forward-sexp 1))
+        ((eq c ?\()
+         (delete-region (point) (progn (forward-sexp 1) (point))))
+        (t
+         (forward-char 1))))
+      (buffer-string))))
+
+(defun ietf-drums-remove-whitespace (string)
+  "Remove whitespace from STRING."
+  (with-temp-buffer
+    (ietf-drums-init string)
+    (let (c)
+      (while (not (eobp))
+       (setq c (char-after))
+       (cond
+        ((eq c ?\")
+         (forward-sexp 1))
+        ((eq c ?\()
+         (forward-sexp 1))
+        ((memq c '(? ?\t ?\n))
+         (delete-char 1))
+        (t
+         (forward-char 1))))
+      (buffer-string))))
+
+(defun ietf-drums-get-comment (string)
+  "Return the first comment in STRING."
+  (with-temp-buffer
+    (ietf-drums-init string)
+    (let (result c)
+      (while (not (eobp))
+       (setq c (char-after))
+       (cond
+        ((eq c ?\")
+         (forward-sexp 1))
+        ((eq c ?\()
+         (setq result
+               (buffer-substring
+                (1+ (point))
+                (progn (forward-sexp 1) (1- (point))))))
+        (t
+         (forward-char 1))))
+      result)))
+
+(defun ietf-drums-strip (string)
+  "Remove comments and whitespace from STRING."
+  (ietf-drums-remove-whitespace (ietf-drums-remove-comments string)))
+
+(defun ietf-drums-parse-address (string)
+  "Parse STRING and return a MAILBOX / DISPLAY-NAME pair."
+  (with-temp-buffer
+    (let (display-name mailbox c display-string)
+      (ietf-drums-init string)
+      (while (not (eobp))
+       (setq c (char-after))
+       (cond
+        ((or (eq c ? )
+             (eq c ?\t))
+         (forward-char 1))
+        ((eq c ?\()
+         (forward-sexp 1))
+        ((eq c ?\")
+         (push (buffer-substring
+                (1+ (point)) (progn (forward-sexp 1) (1- (point))))
+               display-name))
+        ((looking-at (concat "[" ietf-drums-atext-token "@" "]"))
+         (push (buffer-substring (point) (progn (forward-sexp 1) (point)))
+               display-name))
+        ((eq c ?<)
+         (setq mailbox
+               (ietf-drums-remove-whitespace
+                (ietf-drums-remove-comments
+                 (buffer-substring
+                  (1+ (point))
+                  (progn (forward-sexp 1) (1- (point))))))))
+        (t (error "Unknown symbol: %c" c))))
+      ;; If we found no display-name, then we look for comments.
+      (if display-name
+         (setq display-string
+               (mapconcat 'identity (reverse display-name) " "))
+       (setq display-string (ietf-drums-get-comment string)))
+      (if (not mailbox)
+         (when (string-match "@" display-string)
+           (cons
+            (mapconcat 'identity (nreverse display-name) "")
+            (ietf-drums-get-comment string)))
+       (cons mailbox display-string)))))
+
+(defun ietf-drums-parse-addresses (string)
+  "Parse STRING and return a list of MAILBOX / DISPLAY-NAME pairs."
+  (if (null string)
+      nil
+    (with-temp-buffer
+      (ietf-drums-init string)
+      (let ((beg (point))
+           pairs c address)
+       (while (not (eobp))
+         (setq c (char-after))
+         (cond
+          ((memq c '(?\" ?< ?\())
+           (condition-case nil
+               (forward-sexp 1)
+             (error
+              (skip-chars-forward "^,"))))
+          ((eq c ?,)
+           (setq address
+                 (condition-case nil
+                     (ietf-drums-parse-address
+                      (buffer-substring beg (point)))
+                   (error nil)))
+           (if address (push address pairs))
+           (forward-char 1)
+           (setq beg (point)))
+          (t
+           (forward-char 1))))
+       (setq address
+             (condition-case nil
+                 (ietf-drums-parse-address
+                  (buffer-substring beg (point)))
+               (error nil)))
+       (if address (push address pairs))
+       (nreverse pairs)))))
+
+(defun ietf-drums-unfold-fws ()
+  "Unfold folding white space in the current buffer."
+  (goto-char (point-min))
+  (while (re-search-forward ietf-drums-fws-regexp nil t)
+    (replace-match " " t t))
+  (goto-char (point-min)))
+
+(defun ietf-drums-parse-date (string)
+  "Return an Emacs time spec from STRING."
+  (apply 'encode-time (parse-time-string string)))
+
+(defun ietf-drums-narrow-to-header ()
+  "Narrow to the header section in the current buffer."
+  (narrow-to-region
+   (goto-char (point-min))
+   (if (re-search-forward "^\r?$" nil 1)
+       (match-beginning 0)
+     (point-max)))
+  (goto-char (point-min)))
+
+(defun ietf-drums-quote-string (string)
+  "Quote string if it needs quoting to be displayed in a header."
+  (if (string-match (concat "[^" ietf-drums-atext-token "]") string)
+      (concat "\"" string "\"")
+    string))
+
+(provide 'ietf-drums)
+
+;;; ietf-drums.el ends here
diff --git a/lisp/imap.el b/lisp/imap.el
new file mode 100644 (file)
index 0000000..0c7f5dc
--- /dev/null
@@ -0,0 +1,2790 @@
+;;; imap.el --- imap library
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <jas@pdc.kth.se>
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; imap.el is a elisp library providing an interface for talking to
+;; IMAP servers.
+;;
+;; imap.el is roughly divided in two parts, one that parses IMAP
+;; responses from the server and storing data into buffer-local
+;; variables, and one for utility functions which send commands to
+;; server, waits for an answer, and return information.  The latter
+;; part is layered on top of the previous.
+;;
+;; The imap.el API consist of the following functions, other functions
+;; in this file should not be called directly and the result of doing
+;; so are at best undefined.
+;;
+;; Global commands:
+;;
+;; imap-open,       imap-opened,    imap-authenticate, imap-close,
+;; imap-capability, imap-namespace, imap-error-text
+;;
+;; Mailbox commands:
+;;
+;; imap-mailbox-get,       imap-mailbox-map,         imap-current-mailbox,
+;; imap-current-mailbox-p, imap-search,              imap-mailbox-select,
+;; imap-mailbox-examine,   imap-mailbox-unselect,    imap-mailbox-expunge
+;; imap-mailbox-close,     imap-mailbox-create,      imap-mailbox-delete
+;; imap-mailbox-rename,    imap-mailbox-lsub,        imap-mailbox-list
+;; imap-mailbox-subscribe, imap-mailbox-unsubscribe, imap-mailbox-status
+;; imap-mailbox-acl-get,   imap-mailbox-acl-set,     imap-mailbox-acl-delete
+;;
+;; Message commands:
+;;
+;; imap-fetch-asynch,                 imap-fetch,
+;; imap-current-message,              imap-list-to-message-set,
+;; imap-message-get,                  imap-message-map
+;; imap-message-envelope-date,        imap-message-envelope-subject,
+;; imap-message-envelope-from,        imap-message-envelope-sender,
+;; imap-message-envelope-reply-to,    imap-message-envelope-to,
+;; imap-message-envelope-cc,          imap-message-envelope-bcc
+;; imap-message-envelope-in-reply-to, imap-message-envelope-message-id
+;; imap-message-body,                 imap-message-flag-permanent-p
+;; imap-message-flags-set,            imap-message-flags-del
+;; imap-message-flags-add,            imap-message-copyuid
+;; imap-message-copy,                 imap-message-appenduid
+;; imap-message-append,               imap-envelope-from
+;; imap-body-lines
+;;
+;; It is my hope that theese commands should be pretty self
+;; explanatory for someone that know IMAP.  All functions have
+;; additional documentation on how to invoke them.
+;;
+;; imap.el support RFC1730/2060 (IMAP4/IMAP4rev1), implemented IMAP
+;; extensions are RFC2195 (CRAM-MD5), RFC2086 (ACL), RFC2342
+;; (NAMESPACE), RFC2359 (UIDPLUS), the IMAP-part of RFC2595 (STARTTLS,
+;; LOGINDISABLED) (with use of external library starttls.el and
+;; program starttls) and the GSSAPI / kerberos V4 sections of RFC1731
+;; (with use of external program `imtest').  It also take advantage
+;; the UNSELECT extension in Cyrus IMAPD.
+;;
+;; Without the work of John McClary Prevost and Jim Radford this library
+;; would not have seen the light of day.  Many thanks.
+;;
+;; This is a transcript of short interactive session for demonstration
+;; purposes.
+;;
+;; (imap-open "my.mail.server")
+;; => " *imap* my.mail.server:0"
+;;
+;; The rest are invoked with current buffer as the buffer returned by
+;; `imap-open'.  It is possible to do all without this, but it would
+;; look ugly here since `buffer' is always the last argument for all
+;; imap.el API functions.
+;;
+;; (imap-authenticate "myusername" "mypassword")
+;; => auth
+;;
+;; (imap-mailbox-lsub "*")
+;; => ("INBOX.sentmail" "INBOX.private" "INBOX.draft" "INBOX.spam")
+;;
+;; (imap-mailbox-list "INBOX.n%")
+;; => ("INBOX.namedroppers" "INBOX.nnimap" "INBOX.ntbugtraq")
+;;
+;; (imap-mailbox-select "INBOX.nnimap")
+;; => "INBOX.nnimap"
+;;
+;; (imap-mailbox-get 'exists)
+;; => 166
+;;
+;; (imap-mailbox-get 'uidvalidity)
+;; => "908992622"
+;;
+;; (imap-search "FLAGGED SINCE 18-DEC-98")
+;; => (235 236)
+;;
+;; (imap-fetch 235 "RFC822.PEEK" 'RFC822)
+;; => "X-Sieve: cmu-sieve 1.3^M\nX-Username: <jas@pdc.kth.se>^M\r...."
+;;
+;; Todo:
+;;
+;; o Parse UIDs as strings? We need to overcome the 28 bit limit somehow.
+;; o Don't use `read' at all (important places already fixed)
+;; o Accept list of articles instead of message set string in most
+;;   imap-message-* functions.
+;; o Send strings as literal if they contain, e.g., ".
+;;
+;; Revision history:
+;;
+;;  - 19991218 added starttls/digest-md5 patch,
+;;             by Daiki Ueno <ueno@ueda.info.waseda.ac.jp>
+;;             NB! you need SLIM for starttls.el and digest-md5.el
+;;  - 19991023 commited to pgnus
+;;
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
+
+(require 'base64)
+
+(eval-and-compile
+  (autoload 'starttls-open-stream "starttls")
+  (autoload 'starttls-negotiate "starttls")
+  (autoload 'rfc2104-hash "rfc2104")
+  (autoload 'md5 "md5")
+  (autoload 'utf7-encode "utf7")
+  (autoload 'utf7-decode "utf7")
+  (autoload 'format-spec "format-spec")
+  (autoload 'format-spec-make "format-spec")
+  (autoload 'open-tls-stream "tls")
+  ;; Avoid use gnus-point-at-eol so we're independent of Gnus.  These
+  ;; days we have point-at-eol anyhow.
+  (if (fboundp 'point-at-eol)
+      (defalias 'imap-point-at-eol 'point-at-eol)
+    (defun imap-point-at-eol ()
+      (save-excursion
+       (end-of-line)
+       (point))))
+  (autoload 'sasl-digest-md5-digest-response "sasl"))
+
+;; User variables.
+
+(defgroup imap nil
+  "Low-level IMAP issues."
+  :version "21.1"
+  :group 'mail)
+
+(defcustom imap-kerberos4-program '("imtest -m kerberos_v4 -u %l -p %p %s"
+                                   "imtest -kp %s %p")
+  "List of strings containing commands for Kerberos 4 authentication.
+%s is replaced with server hostname, %p with port to connect to, and
+%l with the value of `imap-default-user'.  The program should accept
+IMAP commands on stdin and return responses to stdout.  Each entry in
+the list is tried until a successful connection is made."
+  :group 'imap
+  :type '(repeat string))
+
+(defcustom imap-gssapi-program (list
+                               (concat "gsasl --client --connect %s:%p "
+                                       "--imap --application-data "
+                                       "--mechanism GSSAPI "
+                                       "--authentication-id %l")
+                               "imtest -m gssapi -u %l -p %p %s")
+  "List of strings containing commands for GSSAPI (krb5) authentication.
+%s is replaced with server hostname, %p with port to connect to, and
+%l with the value of `imap-default-user'.  The program should accept
+IMAP commands on stdin and return responses to stdout.  Each entry in
+the list is tried until a successful connection is made."
+  :group 'imap
+  :type '(repeat string))
+
+(defcustom imap-ssl-program '("openssl s_client -quiet -ssl3 -connect %s:%p"
+                             "openssl s_client -quiet -ssl2 -connect %s:%p"
+                             "s_client -quiet -ssl3 -connect %s:%p"
+                             "s_client -quiet -ssl2 -connect %s:%p")
+  "A string, or list of strings, containing commands for SSL connections.
+Within a string, %s is replaced with the server address and %p with
+port number on server.  The program should accept IMAP commands on
+stdin and return responses to stdout.  Each entry in the list is tried
+until a successful connection is made."
+  :group 'imap
+  :type '(choice string
+                (repeat string)))
+
+(defcustom imap-shell-program '("ssh %s imapd"
+                               "rsh %s imapd"
+                               "ssh %g ssh %s imapd"
+                               "rsh %g rsh %s imapd")
+  "A list of strings, containing commands for IMAP connection.
+Within a string, %s is replaced with the server address, %p with port
+number on server, %g with `imap-shell-host', and %l with
+`imap-default-user'.  The program should read IMAP commands from stdin
+and write IMAP response to stdout. Each entry in the list is tried
+until a successful connection is made."
+  :group 'imap
+  :type '(repeat string))
+
+(defcustom imap-process-connection-type nil
+  "*Value for `process-connection-type' to use for Kerberos4, GSSAPI and SSL.
+The `process-connection-type' variable control type of device
+used to communicate with subprocesses.  Values are nil to use a
+pipe, or t or `pty' to use a pty.  The value has no effect if the
+system has no ptys or if all ptys are busy: then a pipe is used
+in any case.  The value takes effect when a IMAP server is
+opened, changing it after that has no effect.."
+  :group 'imap
+  :type 'boolean)
+
+(defcustom imap-use-utf7 t
+  "If non-nil, do utf7 encoding/decoding of mailbox names.
+Since the UTF7 decoding currently only decodes into ISO-8859-1
+characters, you may disable this decoding if you need to access UTF7
+encoded mailboxes which doesn't translate into ISO-8859-1."
+  :group 'imap
+  :type 'boolean)
+
+(defcustom imap-log nil
+  "If non-nil, a imap session trace is placed in *imap-log* buffer."
+  :group 'imap
+  :type 'boolean)
+
+(defcustom imap-debug nil
+  "If non-nil, random debug spews are placed in *imap-debug* buffer."
+  :group 'imap
+  :type 'boolean)
+
+(defcustom imap-shell-host "gateway"
+  "Hostname of rlogin proxy."
+  :group 'imap
+  :type 'string)
+
+(defcustom imap-default-user (user-login-name)
+  "Default username to use."
+  :group 'imap
+  :type 'string)
+
+(defcustom imap-read-timeout (if (string-match
+                                 "windows-nt\\|os/2\\|emx\\|cygwin"
+                                 (symbol-name system-type))
+                                1.0
+                              0.1)
+  "*How long to wait between checking for the end of output.
+Shorter values mean quicker response, but is more CPU intensive."
+  :type 'number
+  :group 'imap)
+
+;; Various variables.
+
+(defvar imap-fetch-data-hook nil
+  "Hooks called after receiving each FETCH response.")
+
+(defvar imap-streams '(gssapi kerberos4 starttls tls ssl network shell)
+  "Priority of streams to consider when opening connection to server.")
+
+(defvar imap-stream-alist
+  '((gssapi    imap-gssapi-stream-p    imap-gssapi-open)
+    (kerberos4 imap-kerberos4-stream-p imap-kerberos4-open)
+    (tls       imap-tls-p              imap-tls-open)
+    (ssl       imap-ssl-p              imap-ssl-open)
+    (network   imap-network-p          imap-network-open)
+    (shell     imap-shell-p            imap-shell-open)
+    (starttls  imap-starttls-p         imap-starttls-open))
+  "Definition of network streams.
+
+\(NAME CHECK OPEN)
+
+NAME names the stream, CHECK is a function returning non-nil if the
+server support the stream and OPEN is a function for opening the
+stream.")
+
+(defvar imap-authenticators '(gssapi
+                             kerberos4
+                             digest-md5
+                             cram-md5
+                             login
+                             anonymous)
+  "Priority of authenticators to consider when authenticating to server.")
+
+(defvar imap-authenticator-alist
+  '((gssapi     imap-gssapi-auth-p    imap-gssapi-auth)
+    (kerberos4  imap-kerberos4-auth-p imap-kerberos4-auth)
+    (cram-md5   imap-cram-md5-p       imap-cram-md5-auth)
+    (login      imap-login-p          imap-login-auth)
+    (anonymous  imap-anonymous-p      imap-anonymous-auth)
+    (digest-md5 imap-digest-md5-p     imap-digest-md5-auth))
+  "Definition of authenticators.
+
+\(NAME CHECK AUTHENTICATE)
+
+NAME names the authenticator.  CHECK is a function returning non-nil if
+the server support the authenticator and AUTHENTICATE is a function
+for doing the actual authentication.")
+
+(defvar imap-error nil
+  "Error codes from the last command.")
+
+;; Internal constants.  Change theese and die.
+
+(defconst imap-default-port 143)
+(defconst imap-default-ssl-port 993)
+(defconst imap-default-tls-port 993)
+(defconst imap-default-stream 'network)
+(defconst imap-local-variables '(imap-server
+                                imap-port
+                                imap-client-eol
+                                imap-server-eol
+                                imap-auth
+                                imap-stream
+                                imap-username
+                                imap-password
+                                imap-current-mailbox
+                                imap-current-target-mailbox
+                                imap-message-data
+                                imap-capability
+                                imap-namespace
+                                imap-state
+                                imap-reached-tag
+                                imap-failed-tags
+                                imap-tag
+                                imap-process
+                                imap-calculate-literal-size-first
+                                imap-mailbox-data))
+(defconst imap-log-buffer "*imap-log*")
+(defconst imap-debug-buffer "*imap-debug*")
+
+;; Internal variables.
+
+(defvar imap-stream nil)
+(defvar imap-auth nil)
+(defvar imap-server nil)
+(defvar imap-port nil)
+(defvar imap-username nil)
+(defvar imap-password nil)
+(defvar imap-calculate-literal-size-first nil)
+(defvar imap-state 'closed
+  "IMAP state.
+Valid states are `closed', `initial', `nonauth', `auth', `selected'
+and `examine'.")
+
+(defvar imap-server-eol "\r\n"
+  "The EOL string sent from the server.")
+
+(defvar imap-client-eol "\r\n"
+  "The EOL string we send to the server.")
+
+(defvar imap-current-mailbox nil
+  "Current mailbox name.")
+
+(defvar imap-current-target-mailbox nil
+  "Current target mailbox for COPY and APPEND commands.")
+
+(defvar imap-mailbox-data nil
+  "Obarray with mailbox data.")
+
+(defvar imap-mailbox-prime 997
+  "Length of imap-mailbox-data.")
+
+(defvar imap-current-message nil
+  "Current message number.")
+
+(defvar imap-message-data nil
+  "Obarray with message data.")
+
+(defvar imap-message-prime 997
+  "Length of imap-message-data.")
+
+(defvar imap-capability nil
+  "Capability for server.")
+
+(defvar imap-namespace nil
+  "Namespace for current server.")
+
+(defvar imap-reached-tag 0
+  "Lower limit on command tags that have been parsed.")
+
+(defvar imap-failed-tags nil
+  "Alist of tags that failed.
+Each element is a list with four elements; tag (a integer), response
+state (a symbol, `OK', `NO' or `BAD'), response code (a string), and
+human readable response text (a string).")
+
+(defvar imap-tag 0
+  "Command tag number.")
+
+(defvar imap-process nil
+  "Process.")
+
+(defvar imap-continuation nil
+  "Non-nil indicates that the server emitted a continuation request.
+The actual value is really the text on the continuation line.")
+
+(defvar imap-callbacks nil
+  "List of response tags and callbacks, on the form `(number . function)'.
+The function should take two arguments, the first the IMAP tag and the
+second the status (OK, NO, BAD etc) of the command.")
+
+\f
+;; Utility functions:
+
+(defun imap-remassoc (key alist)
+  "Delete by side effect any elements of LIST whose car is `equal' to KEY.
+The modified LIST is returned.  If the first member
+of LIST has a car that is `equal' to KEY, there is no way to remove it
+by side effect; therefore, write `(setq foo (remassoc key foo))' to be
+sure of changing the value of `foo'."
+  (when alist
+    (if (equal key (caar alist))
+       (cdr alist)
+      (setcdr alist (imap-remassoc key (cdr alist)))
+      alist)))
+
+(defmacro imap-disable-multibyte ()
+  "Enable multibyte in the current buffer."
+  '(set-buffer-multibyte nil))
+
+(defsubst imap-utf7-encode (string)
+  (if imap-use-utf7
+      (and string
+          (condition-case ()
+              (utf7-encode string t)
+            (error (message
+                    "imap: Could not UTF7 encode `%s', using it unencoded..."
+                    string)
+                   string)))
+    string))
+
+(defsubst imap-utf7-decode (string)
+  (if imap-use-utf7
+      (and string
+          (condition-case ()
+              (utf7-decode string t)
+            (error (message
+                    "imap: Could not UTF7 decode `%s', using it undecoded..."
+                    string)
+                   string)))
+    string))
+
+(defsubst imap-ok-p (status)
+  (if (eq status 'OK)
+      t
+    (setq imap-error status)
+    nil))
+
+(defun imap-error-text (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (nth 3 (car imap-failed-tags))))
+
+\f
+;; Server functions; stream stuff:
+
+(defun imap-kerberos4-stream-p (buffer)
+  (imap-capability 'AUTH=KERBEROS_V4 buffer))
+
+(defun imap-kerberos4-open (name buffer server port)
+  (let ((cmds imap-kerberos4-program)
+       cmd done)
+    (while (and (not done) (setq cmd (pop cmds)))
+      (message "Opening Kerberos 4 IMAP connection with `%s'..." cmd)
+      (erase-buffer)
+      (let* ((port (or port imap-default-port))
+            (process-connection-type imap-process-connection-type)
+            (process (as-binary-process
+                      (start-process
+                       name buffer shell-file-name shell-command-switch
+                       (format-spec
+                        cmd
+                        (format-spec-make
+                         ?s server
+                         ?p (number-to-string port)
+                         ?l imap-default-user)))))
+            response)
+       (when process
+         (with-current-buffer buffer
+           (setq imap-client-eol "\n"
+                 imap-calculate-literal-size-first t)
+           (while (and (memq (process-status process) '(open run))
+                       (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                       (goto-char (point-min))
+                       ;; Athena IMTEST can output SSL verify errors
+                       (or (while (looking-at "^verify error:num=")
+                             (forward-line))
+                           t)
+                       (or (while (looking-at "^TLS connection established")
+                             (forward-line))
+                           t)
+                       ;; cyrus 1.6.x (13? < x <= 22) queries capabilities
+                       (or (while (looking-at "^C:")
+                             (forward-line))
+                           t)
+                       ;; cyrus 1.6 imtest print "S: " before server greeting
+                       (or (not (looking-at "S: "))
+                           (forward-char 3)
+                           t)
+                       (not (and (imap-parse-greeting)
+                                 ;; success in imtest < 1.6:
+                                 (or (re-search-forward
+                                      "^__\\(.*\\)__\n" nil t)
+                                     ;; success in imtest 1.6:
+                                     (re-search-forward
+                                      "^\\(Authenticat.*\\)" nil t))
+                                 (setq response (match-string 1)))))
+             (accept-process-output process 1)
+             (sit-for 1))
+           (and imap-log
+                (with-current-buffer (get-buffer-create imap-log-buffer)
+                  (imap-disable-multibyte)
+                  (buffer-disable-undo)
+                  (goto-char (point-max))
+                  (insert-buffer-substring buffer)))
+           (erase-buffer)
+           (message "Opening Kerberos 4 IMAP connection with `%s'...%s" cmd
+                    (if response (concat "done, " response) "failed"))
+           (if (and response (let ((case-fold-search nil))
+                               (not (string-match "failed" response))))
+               (setq done process)
+             (if (memq (process-status process) '(open run))
+                 (imap-send-command "LOGOUT"))
+             (delete-process process)
+             nil)))))
+    done))
+
+(defun imap-gssapi-stream-p (buffer)
+  (imap-capability 'AUTH=GSSAPI buffer))
+
+(defun imap-gssapi-open (name buffer server port)
+  (let ((cmds imap-gssapi-program)
+       cmd done)
+    (while (and (not done) (setq cmd (pop cmds)))
+      (message "Opening GSSAPI IMAP connection with `%s'..." cmd)
+      (erase-buffer)
+      (let* ((port (or port imap-default-port))
+            (process-connection-type imap-process-connection-type)
+            (process (as-binary-process
+                      (start-process
+                       name buffer shell-file-name shell-command-switch
+                       (format-spec
+                        cmd
+                        (format-spec-make
+                         ?s server
+                         ?p (number-to-string port)
+                         ?l imap-default-user)))))
+            response)
+       (when process
+         (with-current-buffer buffer
+           (setq imap-client-eol "\n"
+                 imap-calculate-literal-size-first t)
+           (while (and (memq (process-status process) '(open run))
+                       (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                       (goto-char (point-min))
+                       ;; cyrus 1.6.x (13? < x <= 22) queries capabilities
+                       (or (while (looking-at "^C:")
+                             (forward-line))
+                           t)
+                       ;; cyrus 1.6 imtest print "S: " before server greeting
+                       (or (not (looking-at "S: "))
+                           (forward-char 3)
+                           t)
+                       (not (and (imap-parse-greeting)
+                                 ;; success in imtest 1.6:
+                                 (re-search-forward
+                                  (concat "^\\(\\(Authenticat.*\\)\\|\\("
+                                          "Client authentication "
+                                          "finished.*\\)\\)")
+                                  nil t)
+                                 (setq response (match-string 1)))))
+             (accept-process-output process 1)
+             (sit-for 1))
+           (and imap-log
+                (with-current-buffer (get-buffer-create imap-log-buffer)
+                  (imap-disable-multibyte)
+                  (buffer-disable-undo)
+                  (goto-char (point-max))
+                  (insert-buffer-substring buffer)))
+           (erase-buffer)
+           (message "GSSAPI IMAP connection: %s" (or response "failed"))
+           (if (and response (let ((case-fold-search nil))
+                               (not (string-match "failed" response))))
+               (setq done process)
+             (if (memq (process-status process) '(open run))
+                 (imap-send-command "LOGOUT"))
+             (delete-process process)
+             nil)))))
+    done))
+
+(defun imap-ssl-p (buffer)
+  nil)
+
+(defun imap-ssl-open (name buffer server port)
+  "Open a SSL connection to server."
+  (let ((cmds (if (listp imap-ssl-program) imap-ssl-program
+               (list imap-ssl-program)))
+       cmd done)
+    (while (and (not done) (setq cmd (pop cmds)))
+      (message "imap: Opening SSL connection with `%s'..." cmd)
+      (erase-buffer)
+      (let ((port (or port imap-default-ssl-port))
+           (process-connection-type nil)
+           process)
+       (when (prog1
+                 (setq process (as-binary-process
+                                (start-process
+                                 name buffer shell-file-name
+                                 shell-command-switch
+                                 (format-spec cmd
+                                              (format-spec-make
+                                               ?s server
+                                               ?p (number-to-string port))))))
+               (process-kill-without-query process))
+         (with-current-buffer buffer
+           (goto-char (point-min))
+           (while (and (memq (process-status process) '(open run))
+                       (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                       (goto-char (point-max))
+                       (forward-line -1)
+                       (not (imap-parse-greeting)))
+             (accept-process-output process 1)
+             (sit-for 1))
+           (and imap-log
+                (with-current-buffer (get-buffer-create imap-log-buffer)
+                  (imap-disable-multibyte)
+                  (buffer-disable-undo)
+                  (goto-char (point-max))
+                  (insert-buffer-substring buffer)))
+           (erase-buffer)
+           (when (memq (process-status process) '(open run))
+             (setq done process))))))
+    (if done
+       (progn
+         (message "imap: Opening SSL connection with `%s'...done" cmd)
+         done)
+      (message "imap: Opening SSL connection with `%s'...failed" cmd)
+      nil)))
+
+(defun imap-tls-p (buffer)
+  nil)
+
+(defun imap-tls-open (name buffer server port)
+  (let* ((port (or port imap-default-tls-port))
+        (process (open-tls-stream name buffer server port)))
+    (when process
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-max))
+                 (forward-line -1)
+                 (not (imap-parse-greeting)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (and imap-log
+          (with-current-buffer (get-buffer-create imap-log-buffer)
+            (imap-disable-multibyte)
+            (buffer-disable-undo)
+            (goto-char (point-max))
+            (insert-buffer-substring buffer)))
+      (when (memq (process-status process) '(open run))
+       process))))
+
+(defun imap-network-p (buffer)
+  t)
+
+(defun imap-network-open (name buffer server port)
+  (let* ((port (or port imap-default-port))
+        (process (open-network-stream-as-binary name buffer server port)))
+    (when process
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-min))
+                 (not (imap-parse-greeting)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (and imap-log
+          (with-current-buffer (get-buffer-create imap-log-buffer)
+            (imap-disable-multibyte)
+            (buffer-disable-undo)
+            (goto-char (point-max))
+            (insert-buffer-substring buffer)))
+      (when (memq (process-status process) '(open run))
+       process))))
+
+(defun imap-shell-p (buffer)
+  nil)
+
+(defun imap-shell-open (name buffer server port)
+  (let ((cmds (if (listp imap-shell-program) imap-shell-program
+               (list imap-shell-program)))
+       cmd done)
+    (while (and (not done) (setq cmd (pop cmds)))
+      (message "imap: Opening IMAP connection with `%s'..." cmd)
+      (setq imap-client-eol "\n")
+      (let* ((port (or port imap-default-port))
+            (process (as-binary-process
+                      (start-process
+                       name buffer shell-file-name shell-command-switch
+                       (format-spec
+                        cmd
+                        (format-spec-make
+                         ?s server
+                         ?g imap-shell-host
+                         ?p (number-to-string port)
+                         ?l imap-default-user))))))
+       (when process
+         (while (and (memq (process-status process) '(open run))
+                     (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                     (goto-char (point-max))
+                     (forward-line -1)
+                     (not (imap-parse-greeting)))
+           (accept-process-output process 1)
+           (sit-for 1))
+         (and imap-log
+              (with-current-buffer (get-buffer-create imap-log-buffer)
+                (imap-disable-multibyte)
+                (buffer-disable-undo)
+                (goto-char (point-max))
+                (insert-buffer-substring buffer)))
+         (erase-buffer)
+         (when (memq (process-status process) '(open run))
+           (setq done process)))))
+    (if done
+       (progn
+         (message "imap: Opening IMAP connection with `%s'...done" cmd)
+         done)
+      (message "imap: Opening IMAP connection with `%s'...failed" cmd)
+      nil)))
+
+(defun imap-starttls-p (buffer)
+  (imap-capability 'STARTTLS buffer))
+
+(defun imap-starttls-open (name buffer server port)
+  (let* ((port (or port imap-default-port))
+        (process (as-binary-process
+                  (starttls-open-stream name buffer server port)))
+        done tls-info)
+    (message "imap: Connecting with STARTTLS...")
+    (when process
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-max))
+                 (forward-line -1)
+                 (not (imap-parse-greeting)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (imap-send-command "STARTTLS")
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-max))
+                 (forward-line -1)
+                 (not (re-search-forward "[0-9]+ OK.*\r?\n" nil t)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (and imap-log
+          (with-current-buffer (get-buffer-create imap-log-buffer)
+            (buffer-disable-undo)
+            (goto-char (point-max))
+            (insert-buffer-substring buffer)))
+      (when (and (setq tls-info (starttls-negotiate process))
+                (memq (process-status process) '(open run)))
+       (setq done process)))
+    (if (stringp tls-info)
+       (message "imap: STARTTLS info: %s" tls-info))
+    (message "imap: Connecting with STARTTLS...%s" (if done "done" "failed"))
+    done))
+
+;; Server functions; authenticator stuff:
+
+(defun imap-interactive-login (buffer loginfunc)
+  "Login to server in BUFFER.
+LOGINFUNC is passed a username and a password, it should return t if
+it where successful authenticating itself to the server, nil otherwise.
+Returns t if login was successful, nil otherwise."
+  (with-current-buffer buffer
+    (make-local-variable 'imap-username)
+    (make-local-variable 'imap-password)
+    (let (user passwd ret)
+      ;;      (condition-case ()
+      (while (or (not user) (not passwd))
+       (setq user (or imap-username
+                      (read-from-minibuffer
+                       (concat "IMAP username for " imap-server
+                               " (using stream `" (symbol-name imap-stream)
+                               "'): ")
+                       (or user imap-default-user))))
+       (setq passwd (or imap-password
+                        (read-passwd
+                         (concat "IMAP password for " user "@"
+                                 imap-server " (using authenticator `"
+                                 (symbol-name imap-auth) "'): "))))
+       (when (and user passwd)
+         (if (funcall loginfunc user passwd)
+             (progn
+               (setq ret t
+                     imap-username user)
+               (if (and (not imap-password)
+                        (y-or-n-p "Store password for this session? "))
+                   (setq imap-password passwd)))
+           (message "Login failed...")
+           (setq passwd nil)
+           (setq imap-password nil)
+           (sit-for 1))))
+      ;;       (quit (with-current-buffer buffer
+      ;;               (setq user nil
+      ;;                     passwd nil)))
+      ;;       (error (with-current-buffer buffer
+      ;;                (setq user nil
+      ;;                      passwd nil))))
+      ret)))
+
+(defun imap-gssapi-auth-p (buffer)
+  (eq imap-stream 'gssapi))
+
+(defun imap-gssapi-auth (buffer)
+  (message "imap: Authenticating using GSSAPI...%s"
+          (if (eq imap-stream 'gssapi) "done" "failed"))
+  (eq imap-stream 'gssapi))
+
+(defun imap-kerberos4-auth-p (buffer)
+  (and (imap-capability 'AUTH=KERBEROS_V4 buffer)
+       (eq imap-stream 'kerberos4)))
+
+(defun imap-kerberos4-auth (buffer)
+  (message "imap: Authenticating using Kerberos 4...%s"
+          (if (eq imap-stream 'kerberos4) "done" "failed"))
+  (eq imap-stream 'kerberos4))
+
+(defun imap-cram-md5-p (buffer)
+  (imap-capability 'AUTH=CRAM-MD5 buffer))
+
+(defun imap-cram-md5-auth (buffer)
+  "Login to server using the AUTH CRAM-MD5 method."
+  (message "imap: Authenticating using CRAM-MD5...")
+  (let ((done (imap-interactive-login
+              buffer
+              (lambda (user passwd)
+                (imap-ok-p
+                 (imap-send-command-wait
+                  (list
+                   "AUTHENTICATE CRAM-MD5"
+                   (lambda (challenge)
+                     (let* ((decoded (base64-decode-string challenge))
+                            (hash-function
+                             (if (and (featurep 'xemacs)
+                                      (>= (function-max-args 'md5) 4))
+                                 (lambda (object &optional start end)
+                                   (md5 object start end 'binary))
+                               'md5))
+                            (hash (rfc2104-hash hash-function 64 16
+                                                passwd decoded))
+                            (response (concat user " " hash))
+                            (encoded (base64-encode-string response)))
+                       encoded)))))))))
+    (if done
+       (message "imap: Authenticating using CRAM-MD5...done")
+      (message "imap: Authenticating using CRAM-MD5...failed"))))
+
+(defun imap-login-p (buffer)
+  (and (not (imap-capability 'LOGINDISABLED buffer))
+       (not (imap-capability 'X-LOGIN-CMD-DISABLED buffer))))
+
+(defun imap-login-auth (buffer)
+  "Login to server using the LOGIN command."
+  (message "imap: Plaintext authentication...")
+  (imap-interactive-login buffer
+                         (lambda (user passwd)
+                           (imap-ok-p (imap-send-command-wait
+                                       (concat "LOGIN \"" user "\" \""
+                                               passwd "\""))))))
+
+(defun imap-anonymous-p (buffer)
+  t)
+
+(defun imap-anonymous-auth (buffer)
+  (message "imap: Logging in anonymously...")
+  (with-current-buffer buffer
+    (imap-ok-p (imap-send-command-wait
+               (concat "LOGIN anonymous \"" (concat (user-login-name) "@"
+                                                    (system-name)) "\"")))))
+
+(defun imap-digest-md5-p (buffer)
+  (and (imap-capability 'AUTH=DIGEST-MD5 buffer)
+       (condition-case ()
+          (require 'digest-md5)
+        (error nil))))
+
+(defun imap-digest-md5-auth (buffer)
+  "Login to server using the AUTH DIGEST-MD5 method."
+  (message "imap: Authenticating using DIGEST-MD5...")
+  (imap-interactive-login
+   buffer
+   (lambda (user passwd)
+     (let ((tag
+           (imap-send-command
+            (list
+             "AUTHENTICATE DIGEST-MD5"
+             (lambda (challenge)
+               (base64-encode-string
+                (sasl-digest-md5-digest-response
+                 (base64-decode-string challenge)
+                 user passwd "imap" imap-server)
+                'no-line-break))))))
+       (if (not (eq (imap-wait-for-tag tag) 'INCOMPLETE))
+          nil
+        (setq imap-continuation nil)
+        (imap-send-command-1 "")
+        (imap-ok-p (imap-wait-for-tag tag)))))))
+
+;; Server functions:
+
+(defun imap-open-1 (buffer)
+  (with-current-buffer buffer
+    (erase-buffer)
+    (setq imap-current-mailbox nil
+         imap-current-message nil
+         imap-state 'initial
+         imap-process (condition-case ()
+                          (funcall (nth 2 (assq imap-stream
+                                                imap-stream-alist))
+                                   "imap" buffer imap-server imap-port)
+                        ((error quit) nil)))
+    (when imap-process
+      (set-process-filter imap-process 'imap-arrival-filter)
+      (set-process-sentinel imap-process 'imap-sentinel)
+      (while (and (eq imap-state 'initial)
+                 (memq (process-status imap-process) '(open run)))
+       (message "Waiting for response from %s..." imap-server)
+       (accept-process-output imap-process 1))
+      (message "Waiting for response from %s...done" imap-server)
+      (and (memq (process-status imap-process) '(open run))
+          imap-process))))
+
+(defun imap-open (server &optional port stream auth buffer)
+  "Open a IMAP connection to host SERVER at PORT returning a buffer.
+If PORT is unspecified, a default value is used (143 except
+for SSL which use 993).
+STREAM indicates the stream to use, see `imap-streams' for available
+streams.  If nil, it choices the best stream the server is capable of.
+AUTH indicates authenticator to use, see `imap-authenticators' for
+available authenticators.  If nil, it choices the best stream the
+server is capable of.
+BUFFER can be a buffer or a name of a buffer, which is created if
+necessary.  If nil, the buffer name is generated."
+  (setq buffer (or buffer (format " *imap* %s:%d" server (or port 0))))
+  (with-current-buffer (get-buffer-create buffer)
+    (if (imap-opened buffer)
+       (imap-close buffer))
+    (mapcar 'make-local-variable imap-local-variables)
+    (imap-disable-multibyte)
+    (buffer-disable-undo)
+    (setq imap-server (or server imap-server))
+    (setq imap-port (or port imap-port))
+    (setq imap-auth (or auth imap-auth))
+    (setq imap-stream (or stream imap-stream))
+    (message "imap: Connecting to %s..." imap-server)
+    (if (null (let ((imap-stream (or imap-stream imap-default-stream)))
+               (imap-open-1 buffer)))
+       (progn
+         (message "imap: Connecting to %s...failed" imap-server)
+         nil)
+      (when (null imap-stream)
+       ;; Need to choose stream.
+       (let ((streams imap-streams))
+         (while (setq stream (pop streams))
+           ;; OK to use this stream?
+           (when (funcall (nth 1 (assq stream imap-stream-alist)) buffer)
+             ;; Stream changed?
+             (if (not (eq imap-default-stream stream))
+                 (with-current-buffer (get-buffer-create
+                                       (generate-new-buffer-name " *temp*"))
+                   (mapcar 'make-local-variable imap-local-variables)
+                   (imap-disable-multibyte)
+                   (buffer-disable-undo)
+                   (setq imap-server (or server imap-server))
+                   (setq imap-port (or port imap-port))
+                   (setq imap-auth (or auth imap-auth))
+                   (message "imap: Reconnecting with stream `%s'..." stream)
+                   (if (null (let ((imap-stream stream))
+                               (imap-open-1 (current-buffer))))
+                       (progn
+                         (kill-buffer (current-buffer))
+                         (message
+                          "imap: Reconnecting with stream `%s'...failed"
+                          stream))
+                     ;; We're done, kill the first connection
+                     (imap-close buffer)
+                     (kill-buffer buffer)
+                     (rename-buffer buffer)
+                     (message "imap: Reconnecting with stream `%s'...done"
+                              stream)
+                     (setq imap-stream stream)
+                     (setq imap-capability nil)
+                     (setq streams nil)))
+               ;; We're done
+               (message "imap: Connecting to %s...done" imap-server)
+               (setq imap-stream stream)
+               (setq imap-capability nil)
+               (setq streams nil))))))
+      (when (imap-opened buffer)
+       (setq imap-mailbox-data (make-vector imap-mailbox-prime 0)))
+      (when imap-stream
+       buffer))))
+
+(defun imap-opened (&optional buffer)
+  "Return non-nil if connection to imap server in BUFFER is open.
+If BUFFER is nil then the current buffer is used."
+  (and (setq buffer (get-buffer (or buffer (current-buffer))))
+       (buffer-live-p buffer)
+       (with-current-buffer buffer
+        (and imap-process
+             (memq (process-status imap-process) '(open run))))))
+
+(defun imap-authenticate (&optional user passwd buffer)
+  "Authenticate to server in BUFFER, using current buffer if nil.
+It uses the authenticator specified when opening the server.  If the
+authenticator requires username/passwords, they are queried from the
+user and optionally stored in the buffer.  If USER and/or PASSWD is
+specified, the user will not be questioned and the username and/or
+password is remembered in the buffer."
+  (with-current-buffer (or buffer (current-buffer))
+    (if (not (eq imap-state 'nonauth))
+       (or (eq imap-state 'auth)
+           (eq imap-state 'select)
+           (eq imap-state 'examine))
+      (make-local-variable 'imap-username)
+      (make-local-variable 'imap-password)
+      (if user (setq imap-username user))
+      (if passwd (setq imap-password passwd))
+      (if imap-auth
+         (and (funcall (nth 2 (assq imap-auth
+                                    imap-authenticator-alist)) buffer)
+              (setq imap-state 'auth))
+       ;; Choose authenticator.
+       (let ((auths imap-authenticators)
+             auth)
+         (while (setq auth (pop auths))
+           ;; OK to use authenticator?
+           (when (funcall (nth 1 (assq auth imap-authenticator-alist)) buffer)
+             (message "imap: Authenticating to `%s' using `%s'..."
+                      imap-server auth)
+             (setq imap-auth auth)
+             (if (funcall (nth 2 (assq auth imap-authenticator-alist)) buffer)
+                 (progn
+                   (message "imap: Authenticating to `%s' using `%s'...done"
+                            imap-server auth)
+                   (setq auths nil))
+               (message "imap: Authenticating to `%s' using `%s'...failed"
+                        imap-server auth)))))
+       imap-state))))
+
+(defun imap-close (&optional buffer)
+  "Close connection to server in BUFFER.
+If BUFFER is nil, the current buffer is used."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (imap-opened)
+      (condition-case nil
+         (imap-send-command-wait "LOGOUT")
+       (quit nil)))
+    (when (and imap-process
+              (memq (process-status imap-process) '(open run)))
+      (delete-process imap-process))
+    (setq imap-current-mailbox nil
+         imap-current-message nil
+         imap-process nil)
+    (erase-buffer)
+    t))
+
+(defun imap-capability (&optional identifier buffer)
+  "Return a list of identifiers which server in BUFFER support.
+If IDENTIFIER, return non-nil if it's among the servers capabilities.
+If BUFFER is nil, the current buffer is assumed."
+  (with-current-buffer (or buffer (current-buffer))
+    (unless imap-capability
+      (unless (imap-ok-p (imap-send-command-wait "CAPABILITY"))
+       (setq imap-capability '(IMAP2))))
+    (if identifier
+       (memq (intern (upcase (symbol-name identifier))) imap-capability)
+      imap-capability)))
+
+(defun imap-namespace (&optional buffer)
+  "Return a namespace hierarchy at server in BUFFER.
+If BUFFER is nil, the current buffer is assumed."
+  (with-current-buffer (or buffer (current-buffer))
+    (unless imap-namespace
+      (when (imap-capability 'NAMESPACE)
+       (imap-send-command-wait "NAMESPACE")))
+    imap-namespace))
+
+(defun imap-send-command-wait (command &optional buffer)
+  (imap-wait-for-tag (imap-send-command command buffer) buffer))
+
+\f
+;; Mailbox functions:
+
+(defun imap-mailbox-put (propname value &optional mailbox buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (if imap-mailbox-data
+       (put (intern (or mailbox imap-current-mailbox) imap-mailbox-data)
+            propname value)
+      (error "Imap-mailbox-data is nil, prop %s value %s mailbox %s buffer %s"
+            propname value mailbox (current-buffer)))
+    t))
+
+(defsubst imap-mailbox-get-1 (propname &optional mailbox)
+  (get (intern-soft (or mailbox imap-current-mailbox) imap-mailbox-data)
+       propname))
+
+(defun imap-mailbox-get (propname &optional mailbox buffer)
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-mailbox-get-1 propname (or mailbox imap-current-mailbox)))))
+
+(defun imap-mailbox-map-1 (func &optional mailbox-decoder buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (let (result)
+      (mapatoms
+       (lambda (s)
+        (push (funcall func (if mailbox-decoder
+                                (funcall mailbox-decoder (symbol-name s))
+                              (symbol-name s))) result))
+       imap-mailbox-data)
+      result)))
+
+(defun imap-mailbox-map (func &optional buffer)
+  "Map a function across each mailbox in `imap-mailbox-data', returning a list.
+Function should take a mailbox name (a string) as
+the only argument."
+  (imap-mailbox-map-1 func 'imap-utf7-decode buffer))
+
+(defun imap-current-mailbox (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-utf7-decode imap-current-mailbox)))
+
+(defun imap-current-mailbox-p-1 (mailbox &optional examine)
+  (and (string= mailbox imap-current-mailbox)
+       (or (and examine
+               (eq imap-state 'examine))
+          (and (not examine)
+               (eq imap-state 'selected)))))
+
+(defun imap-current-mailbox-p (mailbox &optional examine buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-current-mailbox-p-1 (imap-utf7-encode mailbox) examine)))
+
+(defun imap-mailbox-select-1 (mailbox &optional examine)
+  "Select MAILBOX on server in BUFFER.
+If EXAMINE is non-nil, do a read-only select."
+  (if (imap-current-mailbox-p-1 mailbox examine)
+      imap-current-mailbox
+    (setq imap-current-mailbox mailbox)
+    (if (imap-ok-p (imap-send-command-wait
+                   (concat (if examine "EXAMINE" "SELECT") " \""
+                           mailbox "\"")))
+       (progn
+         (setq imap-message-data (make-vector imap-message-prime 0)
+               imap-state (if examine 'examine 'selected))
+         imap-current-mailbox)
+      ;; Failed SELECT/EXAMINE unselects current mailbox
+      (setq imap-current-mailbox nil))))
+
+(defun imap-mailbox-select (mailbox &optional examine buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-utf7-decode
+     (imap-mailbox-select-1 (imap-utf7-encode mailbox) examine))))
+
+(defun imap-mailbox-examine-1 (mailbox &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-mailbox-select-1 mailbox 'examine)))
+
+(defun imap-mailbox-examine (mailbox &optional buffer)
+  "Examine MAILBOX on server in BUFFER."
+  (imap-mailbox-select mailbox 'examine buffer))
+
+(defun imap-mailbox-unselect (&optional buffer)
+  "Close current folder in BUFFER, without expunging articles."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (or (eq imap-state 'auth)
+             (and (imap-capability 'UNSELECT)
+                  (imap-ok-p (imap-send-command-wait "UNSELECT")))
+             (and (imap-ok-p
+                   (imap-send-command-wait (concat "EXAMINE \""
+                                                   imap-current-mailbox
+                                                   "\"")))
+                  (imap-ok-p (imap-send-command-wait "CLOSE"))))
+      (setq imap-current-mailbox nil
+           imap-message-data nil
+           imap-state 'auth)
+      t)))
+
+(defun imap-mailbox-expunge (&optional asynch buffer)
+  "Expunge articles in current folder in BUFFER.
+If ASYNCH, do not wait for succesful completion of the command.
+If BUFFER is nil the current buffer is assumed."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (and imap-current-mailbox (not (eq imap-state 'examine)))
+      (if asynch
+         (imap-send-command "EXPUNGE")
+      (imap-ok-p (imap-send-command-wait "EXPUNGE"))))))
+
+(defun imap-mailbox-close (&optional asynch buffer)
+  "Expunge articles and close current folder in BUFFER.
+If ASYNCH, do not wait for succesful completion of the command.
+If BUFFER is nil the current buffer is assumed."
+  (with-current-buffer (or buffer (current-buffer))
+    (when imap-current-mailbox
+      (if asynch
+         (imap-add-callback (imap-send-command "CLOSE")
+                            `(lambda (tag status)
+                               (message "IMAP mailbox `%s' closed... %s"
+                                        imap-current-mailbox status)
+                               (when (eq ,imap-current-mailbox
+                                         imap-current-mailbox)
+                                 ;; Don't wipe out data if another mailbox
+                                 ;; was selected...
+                                 (setq imap-current-mailbox nil
+                                       imap-message-data nil
+                                       imap-state 'auth))))
+       (when (imap-ok-p (imap-send-command-wait "CLOSE"))
+         (setq imap-current-mailbox nil
+               imap-message-data nil
+               imap-state 'auth)))
+      t)))
+
+(defun imap-mailbox-create-1 (mailbox)
+  (imap-ok-p (imap-send-command-wait (list "CREATE \"" mailbox "\""))))
+
+(defun imap-mailbox-create (mailbox &optional buffer)
+  "Create MAILBOX on server in BUFFER.
+If BUFFER is nil the current buffer is assumed."
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-mailbox-create-1 (imap-utf7-encode mailbox))))
+
+(defun imap-mailbox-delete (mailbox &optional buffer)
+  "Delete MAILBOX on server in BUFFER.
+If BUFFER is nil the current buffer is assumed."
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p
+       (imap-send-command-wait (list "DELETE \"" mailbox "\""))))))
+
+(defun imap-mailbox-rename (oldname newname &optional buffer)
+  "Rename mailbox OLDNAME to NEWNAME on server in BUFFER.
+If BUFFER is nil the current buffer is assumed."
+  (let ((oldname (imap-utf7-encode oldname))
+       (newname (imap-utf7-encode newname)))
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p
+       (imap-send-command-wait (list "RENAME \"" oldname "\" "
+                                    "\"" newname "\""))))))
+
+(defun imap-mailbox-lsub (&optional root reference add-delimiter buffer)
+  "Return a list of subscribed mailboxes on server in BUFFER.
+If ROOT is non-nil, only list matching mailboxes.  If ADD-DELIMITER is
+non-nil, a hierarchy delimiter is added to root.  REFERENCE is a
+implementation-specific string that has to be passed to lsub command."
+  (with-current-buffer (or buffer (current-buffer))
+    ;; Make sure we know the hierarchy separator for root's hierarchy
+    (when (and add-delimiter (null (imap-mailbox-get-1 'delimiter root)))
+      (imap-send-command-wait (concat "LIST \"" reference "\" \""
+                                     (imap-utf7-encode root) "\"")))
+    ;; clear list data (NB not delimiter and other stuff)
+    (imap-mailbox-map-1 (lambda (mailbox)
+                         (imap-mailbox-put 'lsub nil mailbox)))
+    (when (imap-ok-p
+          (imap-send-command-wait
+           (concat "LSUB \"" reference "\" \"" (imap-utf7-encode root)
+                   (and add-delimiter (imap-mailbox-get-1 'delimiter root))
+                   "%\"")))
+      (let (out)
+       (imap-mailbox-map-1 (lambda (mailbox)
+                             (when (imap-mailbox-get-1 'lsub mailbox)
+                               (push (imap-utf7-decode mailbox) out))))
+       (nreverse out)))))
+
+(defun imap-mailbox-list (root &optional reference add-delimiter buffer)
+  "Return a list of mailboxes matching ROOT on server in BUFFER.
+If ADD-DELIMITER is non-nil, a hierarchy delimiter is added to
+root.  REFERENCE is a implementation-specific string that has to be
+passed to list command."
+  (with-current-buffer (or buffer (current-buffer))
+    ;; Make sure we know the hierarchy separator for root's hierarchy
+    (when (and add-delimiter (null (imap-mailbox-get-1 'delimiter root)))
+      (imap-send-command-wait (concat "LIST \"" reference "\" \""
+                                     (imap-utf7-encode root) "\"")))
+    ;; clear list data (NB not delimiter and other stuff)
+    (imap-mailbox-map-1 (lambda (mailbox)
+                         (imap-mailbox-put 'list nil mailbox)))
+    (when (imap-ok-p
+          (imap-send-command-wait
+           (concat "LIST \"" reference "\" \"" (imap-utf7-encode root)
+                   (and add-delimiter (imap-mailbox-get-1 'delimiter root))
+                   "%\"")))
+      (let (out)
+       (imap-mailbox-map-1 (lambda (mailbox)
+                             (when (imap-mailbox-get-1 'list mailbox)
+                               (push (imap-utf7-decode mailbox) out))))
+       (nreverse out)))))
+
+(defun imap-mailbox-subscribe (mailbox &optional buffer)
+  "Send the SUBSCRIBE command on the mailbox to server in BUFFER.
+Returns non-nil if successful."
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-ok-p (imap-send-command-wait (concat "SUBSCRIBE \""
+                                              (imap-utf7-encode mailbox)
+                                              "\"")))))
+
+(defun imap-mailbox-unsubscribe (mailbox &optional buffer)
+  "Send the SUBSCRIBE command on the mailbox to server in BUFFER.
+Returns non-nil if successful."
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-ok-p (imap-send-command-wait (concat "UNSUBSCRIBE "
+                                              (imap-utf7-encode mailbox)
+                                              "\"")))))
+
+(defun imap-mailbox-status (mailbox items &optional buffer)
+  "Get status items ITEM in MAILBOX from server in BUFFER.
+ITEMS can be a symbol or a list of symbols, valid symbols are one of
+the STATUS data items -- ie 'messages, 'recent, 'uidnext, 'uidvalidity
+or 'unseen.  If ITEMS is a list of symbols, a list of values is
+returned, if ITEMS is a symbol only its value is returned."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (imap-ok-p
+          (imap-send-command-wait (list "STATUS \""
+                                        (imap-utf7-encode mailbox)
+                                        "\" "
+                                        (upcase
+                                         (format "%s"
+                                                 (if (listp items)
+                                                     items
+                                                   (list items)))))))
+      (if (listp items)
+         (mapcar (lambda (item)
+                   (imap-mailbox-get item mailbox))
+                 items)
+       (imap-mailbox-get items mailbox)))))
+
+(defun imap-mailbox-status-asynch (mailbox items &optional buffer)
+  "Send status item request ITEM on MAILBOX to server in BUFFER.
+ITEMS can be a symbol or a list of symbols, valid symbols are one of
+the STATUS data items -- ie 'messages, 'recent, 'uidnext, 'uidvalidity
+or 'unseen.  The IMAP command tag is returned."
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-send-command (list "STATUS \""
+                            (imap-utf7-encode mailbox)
+                            "\" "
+                            (format "%s"
+                                    (if (listp items)
+                                        items
+                                      (list items)))))))
+
+(defun imap-mailbox-acl-get (&optional mailbox buffer)
+  "Get ACL on mailbox from server in BUFFER."
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (when (imap-ok-p
+            (imap-send-command-wait (list "GETACL \""
+                                          (or mailbox imap-current-mailbox)
+                                          "\"")))
+       (imap-mailbox-get-1 'acl (or mailbox imap-current-mailbox))))))
+
+(defun imap-mailbox-acl-set (identifier rights &optional mailbox buffer)
+  "Change/set ACL for IDENTIFIER to RIGHTS in MAILBOX from server in BUFFER."
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p
+       (imap-send-command-wait (list "SETACL \""
+                                    (or mailbox imap-current-mailbox)
+                                    "\" "
+                                    identifier
+                                    " "
+                                    rights))))))
+
+(defun imap-mailbox-acl-delete (identifier &optional mailbox buffer)
+  "Removes any <identifier,rights> pair for IDENTIFIER in MAILBOX from server in BUFFER."
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p
+       (imap-send-command-wait (list "DELETEACL \""
+                                    (or mailbox imap-current-mailbox)
+                                    "\" "
+                                    identifier))))))
+
+\f
+;; Message functions:
+
+(defun imap-current-message (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    imap-current-message))
+
+(defun imap-list-to-message-set (list)
+  (mapconcat (lambda (item)
+              (number-to-string item))
+            (if (listp list)
+                list
+              (list list))
+            ","))
+
+(defun imap-range-to-message-set (range)
+  (mapconcat
+   (lambda (item)
+     (if (consp item)
+        (format "%d:%d"
+                (car item) (cdr item))
+       (format "%d" item)))
+   (if (and (listp range) (not (listp (cdr range))))
+       (list range) ;; make (1 . 2) into ((1 . 2))
+     range)
+   ","))
+
+(defun imap-fetch-asynch (uids props &optional nouidfetch buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-send-command (format "%sFETCH %s %s" (if nouidfetch "" "UID ")
+                              (if (listp uids)
+                                  (imap-list-to-message-set uids)
+                                uids)
+                              props))))
+
+(defun imap-fetch (uids props &optional receive nouidfetch buffer)
+  "Fetch properties PROPS from message set UIDS from server in BUFFER.
+UIDS can be a string, number or a list of numbers.  If RECEIVE
+is non-nil return theese properties."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (imap-ok-p (imap-send-command-wait
+                     (format "%sFETCH %s %s" (if nouidfetch "" "UID ")
+                             (if (listp uids)
+                                 (imap-list-to-message-set uids)
+                               uids)
+                             props)))
+      (if (or (null receive) (stringp uids))
+         t
+       (if (listp uids)
+           (mapcar (lambda (uid)
+                     (if (listp receive)
+                         (mapcar (lambda (prop)
+                                   (imap-message-get uid prop))
+                                 receive)
+                       (imap-message-get uid receive)))
+                   uids)
+         (imap-message-get uids receive))))))
+
+(defun imap-message-put (uid propname value &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (if imap-message-data
+       (put (intern (number-to-string uid) imap-message-data)
+            propname value)
+      (error "Imap-message-data is nil, uid %s prop %s value %s buffer %s"
+            uid propname value (current-buffer)))
+    t))
+
+(defun imap-message-get (uid propname &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (get (intern-soft (number-to-string uid) imap-message-data)
+        propname)))
+
+(defun imap-message-map (func propname &optional buffer)
+  "Map a function across each mailbox in `imap-message-data', returning a list."
+  (with-current-buffer (or buffer (current-buffer))
+    (let (result)
+      (mapatoms
+       (lambda (s)
+        (push (funcall func (get s 'UID) (get s propname)) result))
+       imap-message-data)
+      result)))
+
+(defmacro imap-message-envelope-date (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 0)))
+
+(defmacro imap-message-envelope-subject (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 1)))
+
+(defmacro imap-message-envelope-from (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 2)))
+
+(defmacro imap-message-envelope-sender (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 3)))
+
+(defmacro imap-message-envelope-reply-to (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 4)))
+
+(defmacro imap-message-envelope-to (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 5)))
+
+(defmacro imap-message-envelope-cc (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 6)))
+
+(defmacro imap-message-envelope-bcc (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 7)))
+
+(defmacro imap-message-envelope-in-reply-to (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 8)))
+
+(defmacro imap-message-envelope-message-id (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (elt (imap-message-get ,uid 'ENVELOPE) 9)))
+
+(defmacro imap-message-body (uid &optional buffer)
+  `(with-current-buffer (or ,buffer (current-buffer))
+     (imap-message-get ,uid 'BODY)))
+
+(defun imap-search (predicate &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-mailbox-put 'search 'dummy)
+    (when (imap-ok-p (imap-send-command-wait (concat "UID SEARCH " predicate)))
+      (if (eq (imap-mailbox-get-1 'search imap-current-mailbox) 'dummy)
+         (progn
+           (message "Missing SEARCH response to a SEARCH command (server not RFC compliant)...")
+           nil)
+       (imap-mailbox-get-1 'search imap-current-mailbox)))))
+
+(defun imap-message-flag-permanent-p (flag &optional mailbox buffer)
+  "Return t iff FLAG can be permanently (between IMAP sessions) saved on articles, in MAILBOX on server in BUFFER."
+  (with-current-buffer (or buffer (current-buffer))
+    (or (member "\\*" (imap-mailbox-get 'permanentflags mailbox))
+       (member flag (imap-mailbox-get 'permanentflags mailbox)))))
+
+(defun imap-message-flags-set (articles flags &optional silent buffer)
+  (when (and articles flags)
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p (imap-send-command-wait
+                 (concat "UID STORE " articles
+                         " FLAGS" (if silent ".SILENT") " (" flags ")"))))))
+
+(defun imap-message-flags-del (articles flags &optional silent buffer)
+  (when (and articles flags)
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p (imap-send-command-wait
+                 (concat "UID STORE " articles
+                         " -FLAGS" (if silent ".SILENT") " (" flags ")"))))))
+
+(defun imap-message-flags-add (articles flags &optional silent buffer)
+  (when (and articles flags)
+    (with-current-buffer (or buffer (current-buffer))
+      (imap-ok-p (imap-send-command-wait
+                 (concat "UID STORE " articles
+                         " +FLAGS" (if silent ".SILENT") " (" flags ")"))))))
+
+(defun imap-message-copyuid-1 (mailbox)
+  (if (imap-capability 'UIDPLUS)
+      (list (nth 0 (imap-mailbox-get-1 'copyuid mailbox))
+           (string-to-number (nth 2 (imap-mailbox-get-1 'copyuid mailbox))))
+    (let ((old-mailbox imap-current-mailbox)
+         (state imap-state)
+         (imap-message-data (make-vector 2 0)))
+      (when (imap-mailbox-examine-1 mailbox)
+       (prog1
+           (and (imap-fetch "*" "UID")
+                (list (imap-mailbox-get-1 'uidvalidity mailbox)
+                      (apply 'max (imap-message-map
+                                   (lambda (uid prop) uid) 'UID))))
+         (if old-mailbox
+             (imap-mailbox-select old-mailbox (eq state 'examine))
+           (imap-mailbox-unselect)))))))
+
+(defun imap-message-copyuid (mailbox &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-message-copyuid-1 (imap-utf7-decode mailbox))))
+
+(defun imap-message-copy (articles mailbox
+                                  &optional dont-create no-copyuid buffer)
+  "Copy ARTICLES (a string message set) to MAILBOX on server in
+BUFFER, creating mailbox if it doesn't exist.  If dont-create is
+non-nil, it will not create a mailbox.  On success, return a list with
+the UIDVALIDITY of the mailbox the article(s) was copied to as the
+first element, rest of list contain the saved articles' UIDs."
+  (when articles
+    (with-current-buffer (or buffer (current-buffer))
+      (let ((mailbox (imap-utf7-encode mailbox)))
+       (if (let ((cmd (concat "UID COPY " articles " \"" mailbox "\""))
+                 (imap-current-target-mailbox mailbox))
+             (if (imap-ok-p (imap-send-command-wait cmd))
+                 t
+               (when (and (not dont-create)
+                          ;; removed because of buggy Oracle server
+                          ;; that doesn't send TRYCREATE tags (which
+                          ;; is a MUST according to specifications):
+                          ;;(imap-mailbox-get-1 'trycreate mailbox)
+                          (imap-mailbox-create-1 mailbox))
+                 (imap-ok-p (imap-send-command-wait cmd)))))
+           (or no-copyuid
+               (imap-message-copyuid-1 mailbox)))))))
+
+(defun imap-message-appenduid-1 (mailbox)
+  (if (imap-capability 'UIDPLUS)
+      (imap-mailbox-get-1 'appenduid mailbox)
+    (let ((old-mailbox imap-current-mailbox)
+         (state imap-state)
+         (imap-message-data (make-vector 2 0)))
+      (when (imap-mailbox-examine-1 mailbox)
+       (prog1
+           (and (imap-fetch "*" "UID")
+                (list (imap-mailbox-get-1 'uidvalidity mailbox)
+                      (apply 'max (imap-message-map
+                                   (lambda (uid prop) uid) 'UID))))
+         (if old-mailbox
+             (imap-mailbox-select old-mailbox (eq state 'examine))
+           (imap-mailbox-unselect)))))))
+
+(defun imap-message-appenduid (mailbox &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (imap-message-appenduid-1 (imap-utf7-encode mailbox))))
+
+(defun imap-message-append (mailbox article &optional flags date-time buffer)
+  "Append ARTICLE (a buffer) to MAILBOX on server in BUFFER.
+FLAGS and DATE-TIME is currently not used.  Return a cons holding
+uidvalidity of MAILBOX and UID the newly created article got, or nil
+on failure."
+  (let ((mailbox (imap-utf7-encode mailbox)))
+    (with-current-buffer (or buffer (current-buffer))
+      (and (let ((imap-current-target-mailbox mailbox))
+            (imap-ok-p
+             (imap-send-command-wait
+              (list "APPEND \"" mailbox "\" "  article))))
+          (imap-message-appenduid-1 mailbox)))))
+
+(defun imap-body-lines (body)
+  "Return number of lines in article by looking at the mime bodystructure BODY."
+  (if (listp body)
+      (if (stringp (car body))
+         (cond ((and (string= (upcase (car body)) "TEXT")
+                     (numberp (nth 7 body)))
+                (nth 7 body))
+               ((and (string= (upcase (car body)) "MESSAGE")
+                     (numberp (nth 9 body)))
+                (nth 9 body))
+               (t 0))
+       (apply '+ (mapcar 'imap-body-lines body)))
+    0))
+
+(defun imap-envelope-from (from)
+  "Return a from string line."
+  (and from
+       (concat (aref from 0)
+              (if (aref from 0) " <")
+              (aref from 2)
+              "@"
+              (aref from 3)
+              (if (aref from 0) ">"))))
+
+\f
+;; Internal functions.
+
+(defun imap-add-callback (tag func)
+  (setq imap-callbacks (append (list (cons tag func)) imap-callbacks)))
+
+(defun imap-send-command-1 (cmdstr)
+  (setq cmdstr (concat cmdstr imap-client-eol))
+  (and imap-log
+       (with-current-buffer (get-buffer-create imap-log-buffer)
+        (imap-disable-multibyte)
+        (buffer-disable-undo)
+        (goto-char (point-max))
+        (insert cmdstr)))
+  (process-send-string imap-process cmdstr))
+
+(defun imap-send-command (command &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (if (not (listp command)) (setq command (list command)))
+    (let ((tag (setq imap-tag (1+ imap-tag)))
+         cmd cmdstr)
+      (setq cmdstr (concat (number-to-string imap-tag) " "))
+      (while (setq cmd (pop command))
+       (cond ((stringp cmd)
+              (setq cmdstr (concat cmdstr cmd)))
+             ((bufferp cmd)
+              (let ((eol imap-client-eol)
+                    (calcfirst imap-calculate-literal-size-first)
+                    size)
+                (with-current-buffer cmd
+                  (if calcfirst
+                      (setq size (buffer-size)))
+                  (when (not (equal eol "\r\n"))
+                    ;; XXX modifies buffer!
+                    (goto-char (point-min))
+                    (while (search-forward "\r\n" nil t)
+                      (replace-match eol)))
+                  (if (not calcfirst)
+                      (setq size (buffer-size))))
+                (setq cmdstr
+                      (concat cmdstr (format "{%d}" size))))
+              (unwind-protect
+                  (progn
+                    (imap-send-command-1 cmdstr)
+                    (setq cmdstr nil)
+                    (if (not (eq (imap-wait-for-tag tag) 'INCOMPLETE))
+                        (setq command nil) ;; abort command if no cont-req
+                      (let ((process imap-process)
+                            (stream imap-stream)
+                            (eol imap-client-eol))
+                        (with-current-buffer cmd
+                          (and imap-log
+                               (with-current-buffer (get-buffer-create
+                                                     imap-log-buffer)
+                                 (imap-disable-multibyte)
+                                 (buffer-disable-undo)
+                                 (goto-char (point-max))
+                                 (insert-buffer-substring cmd)))
+                          (process-send-region process (point-min)
+                                               (point-max)))
+                        (process-send-string process imap-client-eol))))
+                (setq imap-continuation nil)))
+             ((functionp cmd)
+              (imap-send-command-1 cmdstr)
+              (setq cmdstr nil)
+              (unwind-protect
+                  (if (not (eq (imap-wait-for-tag tag) 'INCOMPLETE))
+                      (setq command nil) ;; abort command if no cont-req
+                    (setq command (cons (funcall cmd imap-continuation)
+                                        command)))
+                (setq imap-continuation nil)))
+             (t
+              (error "Unknown command type"))))
+      (if cmdstr
+         (imap-send-command-1 cmdstr))
+      tag)))
+
+(defun imap-wait-for-tag (tag &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (let (imap-have-messaged)
+      (while (and (null imap-continuation)
+                 (memq (process-status imap-process) '(open run))
+                 (< imap-reached-tag tag))
+       (let ((len (/ (point-max) 1024))
+             message-log-max)
+         (unless (< len 10)
+           (setq imap-have-messaged t)
+           (message "imap read: %dk" len))
+         (accept-process-output imap-process
+                                (truncate imap-read-timeout)
+                                (truncate (* (- imap-read-timeout
+                                                (truncate imap-read-timeout))
+                                             1000)))))
+      ;; A process can die _before_ we have processed everything it
+      ;; has to say.  Moreover, this can happen in between the call to
+      ;; accept-process-output and the call to process-status in an
+      ;; iteration of the loop above.
+      (when (and (null imap-continuation)
+                (< imap-reached-tag tag))
+       (accept-process-output imap-process 0 0))
+      (when imap-have-messaged
+       (message ""))
+      (and (memq (process-status imap-process) '(open run))
+          (or (assq tag imap-failed-tags)
+              (if imap-continuation
+                  'INCOMPLETE
+                'OK))))))
+
+(defun imap-sentinel (process string)
+  (delete-process process))
+
+(defun imap-find-next-line ()
+  "Return point at end of current line, taking into account literals.
+Return nil if no complete line has arrived."
+  (when (re-search-forward (concat imap-server-eol "\\|{\\([0-9]+\\)}"
+                                  imap-server-eol)
+                          nil t)
+    (if (match-string 1)
+       (if (< (point-max) (+ (point) (string-to-number (match-string 1))))
+           nil
+         (goto-char (+ (point) (string-to-number (match-string 1))))
+         (imap-find-next-line))
+      (point))))
+
+(defun imap-arrival-filter (proc string)
+  "IMAP process filter."
+  ;; Sometimes, we are called even though the process has died.
+  ;; Better abstain from doing stuff in that case.
+  (when (buffer-name (process-buffer proc))
+    (with-current-buffer (process-buffer proc)
+      (goto-char (point-max))
+      (insert string)
+      (and imap-log
+          (with-current-buffer (get-buffer-create imap-log-buffer)
+            (imap-disable-multibyte)
+            (buffer-disable-undo)
+            (goto-char (point-max))
+            (insert string)))
+      (let (end)
+       (goto-char (point-min))
+       (while (setq end (imap-find-next-line))
+         (save-restriction
+           (narrow-to-region (point-min) end)
+           (delete-backward-char (length imap-server-eol))
+           (goto-char (point-min))
+           (unwind-protect
+               (cond ((eq imap-state 'initial)
+                      (imap-parse-greeting))
+                     ((or (eq imap-state 'auth)
+                          (eq imap-state 'nonauth)
+                          (eq imap-state 'selected)
+                          (eq imap-state 'examine))
+                      (imap-parse-response))
+                     (t
+                      (message "Unknown state %s in arrival filter"
+                               imap-state)))
+             (delete-region (point-min) (point-max)))))))))
+
+\f
+;; Imap parser.
+
+(defsubst imap-forward ()
+  (or (eobp) (forward-char)))
+
+;;   number          = 1*DIGIT
+;;                       ; Unsigned 32-bit integer
+;;                       ; (0 <= n < 4,294,967,296)
+
+(defsubst imap-parse-number ()
+  (when (looking-at "[0-9]+")
+    (prog1
+       (string-to-number (match-string 0))
+      (goto-char (match-end 0)))))
+
+;;   literal         = "{" number "}" CRLF *CHAR8
+;;                       ; Number represents the number of CHAR8s
+
+(defsubst imap-parse-literal ()
+  (when (looking-at "{\\([0-9]+\\)}\r\n")
+    (let ((pos (match-end 0))
+         (len (string-to-number (match-string 1))))
+      (if (< (point-max) (+ pos len))
+         nil
+       (goto-char (+ pos len))
+       (buffer-substring pos (+ pos len))))))
+
+;;   string          = quoted / literal
+;;
+;;   quoted          = DQUOTE *QUOTED-CHAR DQUOTE
+;;
+;;   QUOTED-CHAR     = <any TEXT-CHAR except quoted-specials> /
+;;                     "\" quoted-specials
+;;
+;;   quoted-specials = DQUOTE / "\"
+;;
+;;   TEXT-CHAR       = <any CHAR except CR and LF>
+
+(defsubst imap-parse-string ()
+  (cond ((eq (char-after) ?\")
+        (forward-char 1)
+        (let ((p (point)) (name ""))
+          (skip-chars-forward "^\"\\\\")
+          (setq name (buffer-substring p (point)))
+          (while (eq (char-after) ?\\)
+            (setq p (1+ (point)))
+            (forward-char 2)
+            (skip-chars-forward "^\"\\\\")
+            (setq name (concat name (buffer-substring p (point)))))
+          (forward-char 1)
+          name))
+       ((eq (char-after) ?{)
+        (imap-parse-literal))))
+
+;;   nil             = "NIL"
+
+(defsubst imap-parse-nil ()
+  (if (looking-at "NIL")
+      (goto-char (match-end 0))))
+
+;;   nstring         = string / nil
+
+(defsubst imap-parse-nstring ()
+  (or (imap-parse-string)
+      (and (imap-parse-nil)
+          nil)))
+
+;;   astring         = atom / string
+;;
+;;   atom            = 1*ATOM-CHAR
+;;
+;;   ATOM-CHAR       = <any CHAR except atom-specials>
+;;
+;;   atom-specials   = "(" / ")" / "{" / SP / CTL / list-wildcards /
+;;                     quoted-specials
+;;
+;;   list-wildcards  = "%" / "*"
+;;
+;;   quoted-specials = DQUOTE / "\"
+
+(defsubst imap-parse-astring ()
+  (or (imap-parse-string)
+      (buffer-substring (point)
+                       (if (re-search-forward "[(){ \r\n%*\"\\]" nil t)
+                           (goto-char (1- (match-end 0)))
+                         (end-of-line)
+                         (point)))))
+
+;;   address         = "(" addr-name SP addr-adl SP addr-mailbox SP
+;;                      addr-host ")"
+;;
+;;   addr-adl        = nstring
+;;                       ; Holds route from [RFC-822] route-addr if
+;;                       ; non-nil
+;;
+;;   addr-host       = nstring
+;;                       ; nil indicates [RFC-822] group syntax.
+;;                       ; Otherwise, holds [RFC-822] domain name
+;;
+;;   addr-mailbox    = nstring
+;;                       ; nil indicates end of [RFC-822] group; if
+;;                       ; non-nil and addr-host is nil, holds
+;;                       ; [RFC-822] group name.
+;;                       ; Otherwise, holds [RFC-822] local-part
+;;                       ; after removing [RFC-822] quoting
+;;
+;;   addr-name       = nstring
+;;                       ; If non-nil, holds phrase from [RFC-822]
+;;                       ; mailbox after removing [RFC-822] quoting
+;;
+
+(defsubst imap-parse-address ()
+  (let (address)
+    (when (eq (char-after) ?\()
+      (imap-forward)
+      (setq address (vector (prog1 (imap-parse-nstring)
+                             (imap-forward))
+                           (prog1 (imap-parse-nstring)
+                             (imap-forward))
+                           (prog1 (imap-parse-nstring)
+                             (imap-forward))
+                           (imap-parse-nstring)))
+      (when (eq (char-after) ?\))
+       (imap-forward)
+       address))))
+
+;;   address-list    = "(" 1*address ")" / nil
+;;
+;;   nil             = "NIL"
+
+(defsubst imap-parse-address-list ()
+  (if (eq (char-after) ?\()
+      (let (address addresses)
+       (imap-forward)
+       (while (and (not (eq (char-after) ?\)))
+                   ;; next line for MS Exchange bug
+                   (progn (and (eq (char-after) ? ) (imap-forward)) t)
+                   (setq address (imap-parse-address)))
+         (setq addresses (cons address addresses)))
+       (when (eq (char-after) ?\))
+         (imap-forward)
+         (nreverse addresses)))
+    (assert (imap-parse-nil) t "In imap-parse-address-list")))
+
+;;   mailbox         = "INBOX" / astring
+;;                       ; INBOX is case-insensitive.  All case variants of
+;;                       ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX
+;;                       ; not as an astring.  An astring which consists of
+;;                       ; the case-insensitive sequence "I" "N" "B" "O" "X"
+;;                       ; is considered to be INBOX and not an astring.
+;;                       ;  Refer to section 5.1 for further
+;;                       ; semantic details of mailbox names.
+
+(defsubst imap-parse-mailbox ()
+  (let ((mailbox (imap-parse-astring)))
+    (if (string-equal "INBOX" (upcase mailbox))
+       "INBOX"
+      mailbox)))
+
+;;   greeting        = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
+;;
+;;   resp-cond-auth  = ("OK" / "PREAUTH") SP resp-text
+;;                       ; Authentication condition
+;;
+;;   resp-cond-bye   = "BYE" SP resp-text
+
+(defun imap-parse-greeting ()
+  "Parse a IMAP greeting."
+  (cond ((looking-at "\\* OK ")
+        (setq imap-state 'nonauth))
+       ((looking-at "\\* PREAUTH ")
+        (setq imap-state 'auth))
+       ((looking-at "\\* BYE ")
+        (setq imap-state 'closed))))
+
+;;   response        = *(continue-req / response-data) response-done
+;;
+;;   continue-req    = "+" SP (resp-text / base64) CRLF
+;;
+;;   response-data   = "*" SP (resp-cond-state / resp-cond-bye /
+;;                     mailbox-data / message-data / capability-data) CRLF
+;;
+;;   response-done   = response-tagged / response-fatal
+;;
+;;   response-fatal  = "*" SP resp-cond-bye CRLF
+;;                       ; Server closes connection immediately
+;;
+;;   response-tagged = tag SP resp-cond-state CRLF
+;;
+;;   resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
+;;                       ; Status condition
+;;
+;;   resp-cond-bye   = "BYE" SP resp-text
+;;
+;;   mailbox-data    =  "FLAGS" SP flag-list /
+;;                      "LIST" SP mailbox-list /
+;;                      "LSUB" SP mailbox-list /
+;;                      "SEARCH" *(SP nz-number) /
+;;                      "STATUS" SP mailbox SP "("
+;;                            [status-att SP number *(SP status-att SP number)] ")" /
+;;                      number SP "EXISTS" /
+;;                      number SP "RECENT"
+;;
+;;   message-data    = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
+;;
+;;   capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
+;;                     *(SP capability)
+;;                       ; IMAP4rev1 servers which offer RFC 1730
+;;                       ; compatibility MUST list "IMAP4" as the first
+;;                       ; capability.
+
+(defun imap-parse-response ()
+  "Parse a IMAP command response."
+  (let (token)
+    (case (setq token (read (current-buffer)))
+      (+ (setq imap-continuation
+              (or (buffer-substring (min (point-max) (1+ (point)))
+                                    (point-max))
+                  t)))
+      (* (case (prog1 (setq token (read (current-buffer)))
+                (imap-forward))
+          (OK         (imap-parse-resp-text))
+          (NO         (imap-parse-resp-text))
+          (BAD        (imap-parse-resp-text))
+          (BYE        (imap-parse-resp-text))
+          (FLAGS      (imap-mailbox-put 'flags (imap-parse-flag-list)))
+          (LIST       (imap-parse-data-list 'list))
+          (LSUB       (imap-parse-data-list 'lsub))
+          (SEARCH     (imap-mailbox-put
+                       'search
+                       (read (concat "(" (buffer-substring (point) (point-max)) ")"))))
+          (STATUS     (imap-parse-status))
+          (CAPABILITY (setq imap-capability
+                              (read (concat "(" (upcase (buffer-substring
+                                                         (point) (point-max)))
+                                            ")"))))
+          (ACL        (imap-parse-acl))
+          (t       (case (prog1 (read (current-buffer))
+                           (imap-forward))
+                     (EXISTS  (imap-mailbox-put 'exists token))
+                     (RECENT  (imap-mailbox-put 'recent token))
+                     (EXPUNGE t)
+                     (FETCH   (imap-parse-fetch token))
+                     (t       (message "Garbage: %s" (buffer-string)))))))
+      (t (let (status)
+          (if (not (integerp token))
+              (message "Garbage: %s" (buffer-string))
+            (case (prog1 (setq status (read (current-buffer)))
+                    (imap-forward))
+              (OK  (progn
+                     (setq imap-reached-tag (max imap-reached-tag token))
+                     (imap-parse-resp-text)))
+              (NO  (progn
+                     (setq imap-reached-tag (max imap-reached-tag token))
+                     (save-excursion
+                       (imap-parse-resp-text))
+                     (let (code text)
+                       (when (eq (char-after) ?\[)
+                         (setq code (buffer-substring (point)
+                                                      (search-forward "]")))
+                         (imap-forward))
+                       (setq text (buffer-substring (point) (point-max)))
+                       (push (list token status code text)
+                             imap-failed-tags))))
+              (BAD (progn
+                     (setq imap-reached-tag (max imap-reached-tag token))
+                     (save-excursion
+                       (imap-parse-resp-text))
+                     (let (code text)
+                       (when (eq (char-after) ?\[)
+                         (setq code (buffer-substring (point)
+                                                      (search-forward "]")))
+                         (imap-forward))
+                       (setq text (buffer-substring (point) (point-max)))
+                       (push (list token status code text) imap-failed-tags)
+                       (error "Internal error, tag %s status %s code %s text %s"
+                              token status code text))))
+              (t   (message "Garbage: %s" (buffer-string))))
+            (when (assq token imap-callbacks)
+              (funcall (cdr (assq token imap-callbacks)) token status)
+              (setq imap-callbacks
+                    (imap-remassoc token imap-callbacks)))))))))
+
+;;   resp-text       = ["[" resp-text-code "]" SP] text
+;;
+;;   text            = 1*TEXT-CHAR
+;;
+;;   TEXT-CHAR       = <any CHAR except CR and LF>
+
+(defun imap-parse-resp-text ()
+  (imap-parse-resp-text-code))
+
+;;   resp-text-code  = "ALERT" /
+;;                     "BADCHARSET [SP "(" astring *(SP astring) ")" ] /
+;;                     "NEWNAME" SP string SP string /
+;;                     "PARSE" /
+;;                     "PERMANENTFLAGS" SP "("
+;;                               [flag-perm *(SP flag-perm)] ")" /
+;;                     "READ-ONLY" /
+;;                     "READ-WRITE" /
+;;                     "TRYCREATE" /
+;;                     "UIDNEXT" SP nz-number /
+;;                     "UIDVALIDITY" SP nz-number /
+;;                     "UNSEEN" SP nz-number /
+;;                     resp-text-atom [SP 1*<any TEXT-CHAR except "]">]
+;;
+;;   resp_code_apnd  = "APPENDUID" SPACE nz_number SPACE uniqueid
+;;
+;;   resp_code_copy  = "COPYUID" SPACE nz_number SPACE set SPACE set
+;;
+;;   set             = sequence-num / (sequence-num ":" sequence-num) /
+;;                        (set "," set)
+;;                          ; Identifies a set of messages.  For message
+;;                          ; sequence numbers, these are consecutive
+;;                          ; numbers from 1 to the number of messages in
+;;                          ; the mailbox
+;;                          ; Comma delimits individual numbers, colon
+;;                          ; delimits between two numbers inclusive.
+;;                          ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,
+;;                          ; 14,15 for a mailbox with 15 messages.
+;;
+;;   sequence-num    = nz-number / "*"
+;;                          ; * is the largest number in use.  For message
+;;                          ; sequence numbers, it is the number of messages
+;;                          ; in the mailbox.  For unique identifiers, it is
+;;                          ; the unique identifier of the last message in
+;;                          ; the mailbox.
+;;
+;;   flag-perm       = flag / "\*"
+;;
+;;   flag            = "\Answered" / "\Flagged" / "\Deleted" /
+;;                     "\Seen" / "\Draft" / flag-keyword / flag-extension
+;;                       ; Does not include "\Recent"
+;;
+;;   flag-extension  = "\" atom
+;;                       ; Future expansion.  Client implementations
+;;                       ; MUST accept flag-extension flags.  Server
+;;                       ; implementations MUST NOT generate
+;;                       ; flag-extension flags except as defined by
+;;                       ; future standard or standards-track
+;;                       ; revisions of this specification.
+;;
+;;   flag-keyword    = atom
+;;
+;;   resp-text-atom  = 1*<any ATOM-CHAR except "]">
+
+(defun imap-parse-resp-text-code ()
+  ;; xxx next line for stalker communigate pro 3.3.1 bug
+  (when (looking-at " \\[")
+    (imap-forward))
+  (when (eq (char-after) ?\[)
+    (imap-forward)
+    (cond ((search-forward "PERMANENTFLAGS " nil t)
+          (imap-mailbox-put 'permanentflags (imap-parse-flag-list)))
+         ((search-forward "UIDNEXT \\([0-9]+\\)" nil t)
+          (imap-mailbox-put 'uidnext (match-string 1)))
+         ((search-forward "UNSEEN " nil t)
+          (imap-mailbox-put 'first-unseen (read (current-buffer))))
+         ((looking-at "UIDVALIDITY \\([0-9]+\\)")
+          (imap-mailbox-put 'uidvalidity (match-string 1)))
+         ((search-forward "READ-ONLY" nil t)
+          (imap-mailbox-put 'read-only t))
+         ((search-forward "NEWNAME " nil t)
+          (let (oldname newname)
+            (setq oldname (imap-parse-string))
+            (imap-forward)
+            (setq newname (imap-parse-string))
+            (imap-mailbox-put 'newname newname oldname)))
+         ((search-forward "TRYCREATE" nil t)
+          (imap-mailbox-put 'trycreate t imap-current-target-mailbox))
+         ((looking-at "APPENDUID \\([0-9]+\\) \\([0-9]+\\)")
+          (imap-mailbox-put 'appenduid
+                            (list (match-string 1)
+                                  (string-to-number (match-string 2)))
+                            imap-current-target-mailbox))
+         ((looking-at "COPYUID \\([0-9]+\\) \\([0-9,:]+\\) \\([0-9,:]+\\)")
+          (imap-mailbox-put 'copyuid (list (match-string 1)
+                                           (match-string 2)
+                                           (match-string 3))
+                            imap-current-target-mailbox))
+         ((search-forward "ALERT] " nil t)
+          (message "Imap server %s information: %s" imap-server
+                   (buffer-substring (point) (point-max)))))))
+
+;;   mailbox-list    = "(" [mbx-list-flags] ")" SP
+;;                      (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
+;;
+;;   mbx-list-flags  = *(mbx-list-oflag SP) mbx-list-sflag
+;;                     *(SP mbx-list-oflag) /
+;;                     mbx-list-oflag *(SP mbx-list-oflag)
+;;
+;;   mbx-list-oflag  = "\Noinferiors" / flag-extension
+;;                       ; Other flags; multiple possible per LIST response
+;;
+;;   mbx-list-sflag  = "\Noselect" / "\Marked" / "\Unmarked"
+;;                       ; Selectability flags; only one per LIST response
+;;
+;;   QUOTED-CHAR     = <any TEXT-CHAR except quoted-specials> /
+;;                     "\" quoted-specials
+;;
+;;   quoted-specials = DQUOTE / "\"
+
+(defun imap-parse-data-list (type)
+  (let (flags delimiter mailbox)
+    (setq flags (imap-parse-flag-list))
+    (when (looking-at " NIL\\| \"\\\\?\\(.\\)\"")
+      (setq delimiter (match-string 1))
+      (goto-char (1+ (match-end 0)))
+      (when (setq mailbox (imap-parse-mailbox))
+       (imap-mailbox-put type t mailbox)
+       (imap-mailbox-put 'list-flags flags mailbox)
+       (imap-mailbox-put 'delimiter delimiter mailbox)))))
+
+;;  msg_att         ::= "(" 1#("ENVELOPE" SPACE envelope /
+;;                      "FLAGS" SPACE "(" #(flag / "\Recent") ")" /
+;;                      "INTERNALDATE" SPACE date_time /
+;;                      "RFC822" [".HEADER" / ".TEXT"] SPACE nstring /
+;;                      "RFC822.SIZE" SPACE number /
+;;                      "BODY" ["STRUCTURE"] SPACE body /
+;;                      "BODY" section ["<" number ">"] SPACE nstring /
+;;                      "UID" SPACE uniqueid) ")"
+;;
+;;  date_time       ::= <"> date_day_fixed "-" date_month "-" date_year
+;;                      SPACE time SPACE zone <">
+;;
+;;  section         ::= "[" [section_text / (nz_number *["." nz_number]
+;;                      ["." (section_text / "MIME")])] "]"
+;;
+;;  section_text    ::= "HEADER" / "HEADER.FIELDS" [".NOT"]
+;;                      SPACE header_list / "TEXT"
+;;
+;;  header_fld_name ::= astring
+;;
+;;  header_list     ::= "(" 1#header_fld_name ")"
+
+(defsubst imap-parse-header-list ()
+  (when (eq (char-after) ?\()
+    (let (strlist)
+      (while (not (eq (char-after) ?\)))
+       (imap-forward)
+       (push (imap-parse-astring) strlist))
+      (imap-forward)
+      (nreverse strlist))))
+
+(defsubst imap-parse-fetch-body-section ()
+  (let ((section
+        (buffer-substring (point) (1- (re-search-forward "[] ]" nil t)))))
+    (if (eq (char-before) ? )
+       (prog1
+           (mapconcat 'identity (cons section (imap-parse-header-list)) " ")
+         (search-forward "]" nil t))
+      section)))
+
+(defun imap-parse-fetch (response)
+  (when (eq (char-after) ?\()
+    (let (uid flags envelope internaldate rfc822 rfc822header rfc822text
+             rfc822size body bodydetail bodystructure flags-empty)
+      (while (not (eq (char-after) ?\)))
+       (imap-forward)
+       (let ((token (read (current-buffer))))
+         (imap-forward)
+         (cond ((eq token 'UID)
+                (setq uid (condition-case ()
+                              (read (current-buffer))
+                            (error))))
+               ((eq token 'FLAGS)
+                (setq flags (imap-parse-flag-list))
+                (if (not flags)
+                    (setq flags-empty 't)))
+               ((eq token 'ENVELOPE)
+                (setq envelope (imap-parse-envelope)))
+               ((eq token 'INTERNALDATE)
+                (setq internaldate (imap-parse-string)))
+               ((eq token 'RFC822)
+                (setq rfc822 (imap-parse-nstring)))
+               ((eq token 'RFC822.HEADER)
+                (setq rfc822header (imap-parse-nstring)))
+               ((eq token 'RFC822.TEXT)
+                (setq rfc822text (imap-parse-nstring)))
+               ((eq token 'RFC822.SIZE)
+                (setq rfc822size (read (current-buffer))))
+               ((eq token 'BODY)
+                (if (eq (char-before) ?\[)
+                    (push (list
+                           (upcase (imap-parse-fetch-body-section))
+                           (and (eq (char-after) ?<)
+                                (buffer-substring (1+ (point))
+                                                  (search-forward ">" nil t)))
+                           (progn (imap-forward)
+                                  (imap-parse-nstring)))
+                          bodydetail)
+                  (setq body (imap-parse-body))))
+               ((eq token 'BODYSTRUCTURE)
+                (setq bodystructure (imap-parse-body))))))
+      (when uid
+       (setq imap-current-message uid)
+       (imap-message-put uid 'UID uid)
+       (and (or flags flags-empty) (imap-message-put uid 'FLAGS flags))
+       (and envelope (imap-message-put uid 'ENVELOPE envelope))
+       (and internaldate (imap-message-put uid 'INTERNALDATE internaldate))
+       (and rfc822 (imap-message-put uid 'RFC822 rfc822))
+       (and rfc822header (imap-message-put uid 'RFC822.HEADER rfc822header))
+       (and rfc822text (imap-message-put uid 'RFC822.TEXT rfc822text))
+       (and rfc822size (imap-message-put uid 'RFC822.SIZE rfc822size))
+       (and body (imap-message-put uid 'BODY body))
+       (and bodydetail (imap-message-put uid 'BODYDETAIL bodydetail))
+       (and bodystructure (imap-message-put uid 'BODYSTRUCTURE bodystructure))
+       (run-hooks 'imap-fetch-data-hook)))))
+
+;;   mailbox-data    =  ...
+;;                      "STATUS" SP mailbox SP "("
+;;                            [status-att SP number
+;;                            *(SP status-att SP number)] ")"
+;;                      ...
+;;
+;;   status-att      = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
+;;                     "UNSEEN"
+
+(defun imap-parse-status ()
+  (let ((mailbox (imap-parse-mailbox)))
+    (if (eq (char-after) ? )
+       (forward-char))
+    (when (and mailbox (eq (char-after) ?\())
+      (while (and (not (eq (char-after) ?\)))
+                 (or (forward-char) t)
+                 (looking-at "\\([A-Za-z]+\\) "))
+       (let ((token (match-string 1)))
+         (goto-char (match-end 0))
+         (cond ((string= token "MESSAGES")
+                (imap-mailbox-put 'messages (read (current-buffer)) mailbox))
+               ((string= token "RECENT")
+                (imap-mailbox-put 'recent (read (current-buffer)) mailbox))
+               ((string= token "UIDNEXT")
+                (and (looking-at "[0-9]+")
+                     (imap-mailbox-put 'uidnext (match-string 0) mailbox)
+                     (goto-char (match-end 0))))
+               ((string= token "UIDVALIDITY")
+                (and (looking-at "[0-9]+")
+                     (imap-mailbox-put 'uidvalidity (match-string 0) mailbox)
+                     (goto-char (match-end 0))))
+               ((string= token "UNSEEN")
+                (imap-mailbox-put 'unseen (read (current-buffer)) mailbox))
+               (t
+                (message "Unknown status data %s in mailbox %s ignored"
+                         token mailbox)
+                (read (current-buffer)))))))))
+
+;;   acl_data        ::= "ACL" SPACE mailbox *(SPACE identifier SPACE
+;;                        rights)
+;;
+;;   identifier      ::= astring
+;;
+;;   rights          ::= astring
+
+(defun imap-parse-acl ()
+  (let ((mailbox (imap-parse-mailbox))
+       identifier rights acl)
+    (while (eq (char-after) ?\ )
+      (imap-forward)
+      (setq identifier (imap-parse-astring))
+      (imap-forward)
+      (setq rights (imap-parse-astring))
+      (setq acl (append acl (list (cons identifier rights)))))
+    (imap-mailbox-put 'acl acl mailbox)))
+
+;;   flag-list       = "(" [flag *(SP flag)] ")"
+;;
+;;   flag            = "\Answered" / "\Flagged" / "\Deleted" /
+;;                     "\Seen" / "\Draft" / flag-keyword / flag-extension
+;;                       ; Does not include "\Recent"
+;;
+;;   flag-keyword    = atom
+;;
+;;   flag-extension  = "\" atom
+;;                       ; Future expansion.  Client implementations
+;;                       ; MUST accept flag-extension flags.  Server
+;;                       ; implementations MUST NOT generate
+;;                       ; flag-extension flags except as defined by
+;;                       ; future standard or standards-track
+;;                       ; revisions of this specification.
+
+(defun imap-parse-flag-list ()
+  (let (flag-list start)
+    (assert (eq (char-after) ?\() t "In imap-parse-flag-list")
+    (while (and (not (eq (char-after) ?\)))
+               (setq start (progn
+                             (imap-forward)
+                             ;; next line for Courier IMAP bug.
+                             (skip-chars-forward " ")
+                             (point)))
+               (> (skip-chars-forward "^ )" (imap-point-at-eol)) 0))
+      (push (buffer-substring start (point)) flag-list))
+    (assert (eq (char-after) ?\)) t "In imap-parse-flag-list")
+    (imap-forward)
+    (nreverse flag-list)))
+
+;;   envelope        = "(" env-date SP env-subject SP env-from SP env-sender SP
+;;                     env-reply-to SP env-to SP env-cc SP env-bcc SP
+;;                     env-in-reply-to SP env-message-id ")"
+;;
+;;   env-bcc         = "(" 1*address ")" / nil
+;;
+;;   env-cc          = "(" 1*address ")" / nil
+;;
+;;   env-date        = nstring
+;;
+;;   env-from        = "(" 1*address ")" / nil
+;;
+;;   env-in-reply-to = nstring
+;;
+;;   env-message-id  = nstring
+;;
+;;   env-reply-to    = "(" 1*address ")" / nil
+;;
+;;   env-sender      = "(" 1*address ")" / nil
+;;
+;;   env-subject     = nstring
+;;
+;;   env-to          = "(" 1*address ")" / nil
+
+(defun imap-parse-envelope ()
+  (when (eq (char-after) ?\()
+    (imap-forward)
+    (vector (prog1 (imap-parse-nstring) ;; date
+             (imap-forward))
+           (prog1 (imap-parse-nstring) ;; subject
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; from
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; sender
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; reply-to
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; to
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; cc
+             (imap-forward))
+           (prog1 (imap-parse-address-list) ;; bcc
+             (imap-forward))
+           (prog1 (imap-parse-nstring) ;; in-reply-to
+             (imap-forward))
+           (prog1 (imap-parse-nstring) ;; message-id
+             (imap-forward)))))
+
+;;   body-fld-param  = "(" string SP string *(SP string SP string) ")" / nil
+
+(defsubst imap-parse-string-list ()
+  (cond ((eq (char-after) ?\() ;; body-fld-param
+        (let (strlist str)
+          (imap-forward)
+          (while (setq str (imap-parse-string))
+            (push str strlist)
+            ;; buggy stalker communigate pro 3.0 doesn't print SPC
+            ;; between body-fld-param's sometimes
+            (or (eq (char-after) ?\")
+                (imap-forward)))
+          (nreverse strlist)))
+       ((imap-parse-nil)
+        nil)))
+
+;;   body-extension  = nstring / number /
+;;                      "(" body-extension *(SP body-extension) ")"
+;;                       ; Future expansion.  Client implementations
+;;                       ; MUST accept body-extension fields.  Server
+;;                       ; implementations MUST NOT generate
+;;                       ; body-extension fields except as defined by
+;;                       ; future standard or standards-track
+;;                       ; revisions of this specification.
+
+(defun imap-parse-body-extension ()
+  (if (eq (char-after) ?\()
+      (let (b-e)
+       (imap-forward)
+       (push (imap-parse-body-extension) b-e)
+       (while (eq (char-after) ?\ )
+         (imap-forward)
+         (push (imap-parse-body-extension) b-e))
+       (assert (eq (char-after) ?\)) t "In imap-parse-body-extension")
+       (imap-forward)
+       (nreverse b-e))
+    (or (imap-parse-number)
+       (imap-parse-nstring))))
+
+;;   body-ext-1part  = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
+;;                     *(SP body-extension)]]
+;;                       ; MUST NOT be returned on non-extensible
+;;                       ; "BODY" fetch
+;;
+;;   body-ext-mpart  = body-fld-param [SP body-fld-dsp [SP body-fld-lang
+;;                     *(SP body-extension)]]
+;;                       ; MUST NOT be returned on non-extensible
+;;                       ; "BODY" fetch
+
+(defsubst imap-parse-body-ext ()
+  (let (ext)
+    (when (eq (char-after) ?\ ) ;; body-fld-dsp
+      (imap-forward)
+      (let (dsp)
+       (if (eq (char-after) ?\()
+           (progn
+             (imap-forward)
+             (push (imap-parse-string) dsp)
+             (imap-forward)
+             (push (imap-parse-string-list) dsp)
+             (imap-forward))
+         (assert (imap-parse-nil) t "In imap-parse-body-ext"))
+       (push (nreverse dsp) ext))
+      (when (eq (char-after) ?\ ) ;; body-fld-lang
+       (imap-forward)
+       (if (eq (char-after) ?\()
+           (push (imap-parse-string-list) ext)
+         (push (imap-parse-nstring) ext))
+       (while (eq (char-after) ?\ ) ;; body-extension
+         (imap-forward)
+         (setq ext (append (imap-parse-body-extension) ext)))))
+    ext))
+
+;;   body            = "(" body-type-1part / body-type-mpart ")"
+;;
+;;   body-ext-1part  = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
+;;                     *(SP body-extension)]]
+;;                       ; MUST NOT be returned on non-extensible
+;;                       ; "BODY" fetch
+;;
+;;   body-ext-mpart  = body-fld-param [SP body-fld-dsp [SP body-fld-lang
+;;                     *(SP body-extension)]]
+;;                       ; MUST NOT be returned on non-extensible
+;;                       ; "BODY" fetch
+;;
+;;   body-fields     = body-fld-param SP body-fld-id SP body-fld-desc SP
+;;                     body-fld-enc SP body-fld-octets
+;;
+;;   body-fld-desc   = nstring
+;;
+;;   body-fld-dsp    = "(" string SP body-fld-param ")" / nil
+;;
+;;   body-fld-enc    = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
+;;                     "QUOTED-PRINTABLE") DQUOTE) / string
+;;
+;;   body-fld-id     = nstring
+;;
+;;   body-fld-lang   = nstring / "(" string *(SP string) ")"
+;;
+;;   body-fld-lines  = number
+;;
+;;   body-fld-md5    = nstring
+;;
+;;   body-fld-octets = number
+;;
+;;   body-fld-param  = "(" string SP string *(SP string SP string) ")" / nil
+;;
+;;   body-type-1part = (body-type-basic / body-type-msg / body-type-text)
+;;                     [SP body-ext-1part]
+;;
+;;   body-type-basic = media-basic SP body-fields
+;;                       ; MESSAGE subtype MUST NOT be "RFC822"
+;;
+;;   body-type-msg   = media-message SP body-fields SP envelope
+;;                     SP body SP body-fld-lines
+;;
+;;   body-type-text  = media-text SP body-fields SP body-fld-lines
+;;
+;;   body-type-mpart = 1*body SP media-subtype
+;;                     [SP body-ext-mpart]
+;;
+;;   media-basic     = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
+;;                     "MESSAGE" / "VIDEO") DQUOTE) / string) SP media-subtype
+;;                       ; Defined in [MIME-IMT]
+;;
+;;   media-message   = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
+;;                      ; Defined in [MIME-IMT]
+;;
+;;   media-subtype   = string
+;;                       ; Defined in [MIME-IMT]
+;;
+;;   media-text      = DQUOTE "TEXT" DQUOTE SP media-subtype
+;;                       ; Defined in [MIME-IMT]
+
+(defun imap-parse-body ()
+  (let (body)
+    (when (eq (char-after) ?\()
+      (imap-forward)
+      (if (eq (char-after) ?\()
+         (let (subbody)
+           (while (and (eq (char-after) ?\()
+                       (setq subbody (imap-parse-body)))
+             ;; buggy stalker communigate pro 3.0 insert a SPC between
+             ;; parts in multiparts
+             (when (and (eq (char-after) ?\ )
+                        (eq (char-after (1+ (point))) ?\())
+               (imap-forward))
+             (push subbody body))
+           (imap-forward)
+           (push (imap-parse-string) body) ;; media-subtype
+           (when (eq (char-after) ?\ ) ;; body-ext-mpart:
+             (imap-forward)
+             (if (eq (char-after) ?\() ;; body-fld-param
+                 (push (imap-parse-string-list) body)
+               (push (and (imap-parse-nil) nil) body))
+             (setq body
+                   (append (imap-parse-body-ext) body))) ;; body-ext-...
+           (assert (eq (char-after) ?\)) t "In imap-parse-body")
+           (imap-forward)
+           (nreverse body))
+
+       (push (imap-parse-string) body) ;; media-type
+       (imap-forward)
+       (push (imap-parse-string) body) ;; media-subtype
+       (imap-forward)
+       ;; next line for Sun SIMS bug
+       (and (eq (char-after) ? ) (imap-forward))
+       (if (eq (char-after) ?\() ;; body-fld-param
+           (push (imap-parse-string-list) body)
+         (push (and (imap-parse-nil) nil) body))
+       (imap-forward)
+       (push (imap-parse-nstring) body) ;; body-fld-id
+       (imap-forward)
+       (push (imap-parse-nstring) body) ;; body-fld-desc
+       (imap-forward)
+       ;; next `or' for Sun SIMS bug, it regard body-fld-enc as a
+       ;; nstring and return nil instead of defaulting back to 7BIT
+       ;; as the standard says.
+       (push (or (imap-parse-nstring) "7BIT") body) ;; body-fld-enc
+       (imap-forward)
+       (push (imap-parse-number) body) ;; body-fld-octets
+
+       ;; ok, we're done parsing the required parts, what comes now is one
+       ;; of three things:
+       ;;
+       ;; envelope       (then we're parsing body-type-msg)
+       ;; body-fld-lines (then we're parsing body-type-text)
+       ;; body-ext-1part (then we're parsing body-type-basic)
+       ;;
+       ;; the problem is that the two first are in turn optionally followed
+       ;; by the third.  So we parse the first two here (if there are any)...
+
+       (when (eq (char-after) ?\ )
+         (imap-forward)
+         (let (lines)
+           (cond ((eq (char-after) ?\() ;; body-type-msg:
+                  (push (imap-parse-envelope) body) ;; envelope
+                  (imap-forward)
+                  (push (imap-parse-body) body) ;; body
+                  ;; buggy stalker communigate pro 3.0 doesn't print
+                  ;; number of lines in message/rfc822 attachment
+                  (if (eq (char-after) ?\))
+                      (push 0 body)
+                    (imap-forward)
+                    (push (imap-parse-number) body))) ;; body-fld-lines
+                 ((setq lines (imap-parse-number)) ;; body-type-text:
+                  (push lines body)) ;; body-fld-lines
+                 (t
+                  (backward-char))))) ;; no match...
+
+       ;; ...and then parse the third one here...
+
+       (when (eq (char-after) ?\ ) ;; body-ext-1part:
+         (imap-forward)
+         (push (imap-parse-nstring) body) ;; body-fld-md5
+         (setq body (append (imap-parse-body-ext) body))) ;; body-ext-1part..
+
+       (assert (eq (char-after) ?\)) t "In imap-parse-body 2")
+       (imap-forward)
+       (nreverse body)))))
+
+(when imap-debug                       ; (untrace-all)
+  (require 'trace)
+  (buffer-disable-undo (get-buffer-create imap-debug-buffer))
+  (mapcar (lambda (f) (trace-function-background f imap-debug-buffer))
+         '(
+           imap-utf7-encode
+           imap-utf7-decode
+           imap-error-text
+           imap-kerberos4s-p
+           imap-kerberos4-open
+           imap-ssl-p
+           imap-ssl-open
+           imap-network-p
+           imap-network-open
+           imap-interactive-login
+           imap-kerberos4a-p
+           imap-kerberos4-auth
+           imap-cram-md5-p
+           imap-cram-md5-auth
+           imap-login-p
+           imap-login-auth
+           imap-anonymous-p
+           imap-anonymous-auth
+           imap-open-1
+           imap-open
+           imap-opened
+           imap-authenticate
+           imap-close
+           imap-capability
+           imap-namespace
+           imap-send-command-wait
+           imap-mailbox-put
+           imap-mailbox-get
+           imap-mailbox-map-1
+           imap-mailbox-map
+           imap-current-mailbox
+           imap-current-mailbox-p-1
+           imap-current-mailbox-p
+           imap-mailbox-select-1
+           imap-mailbox-select
+           imap-mailbox-examine-1
+           imap-mailbox-examine
+           imap-mailbox-unselect
+           imap-mailbox-expunge
+           imap-mailbox-close
+           imap-mailbox-create-1
+           imap-mailbox-create
+           imap-mailbox-delete
+           imap-mailbox-rename
+           imap-mailbox-lsub
+           imap-mailbox-list
+           imap-mailbox-subscribe
+           imap-mailbox-unsubscribe
+           imap-mailbox-status
+           imap-mailbox-acl-get
+           imap-mailbox-acl-set
+           imap-mailbox-acl-delete
+           imap-current-message
+           imap-list-to-message-set
+           imap-fetch-asynch
+           imap-fetch
+           imap-message-put
+           imap-message-get
+           imap-message-map
+           imap-search
+           imap-message-flag-permanent-p
+           imap-message-flags-set
+           imap-message-flags-del
+           imap-message-flags-add
+           imap-message-copyuid-1
+           imap-message-copyuid
+           imap-message-copy
+           imap-message-appenduid-1
+           imap-message-appenduid
+           imap-message-append
+           imap-body-lines
+           imap-envelope-from
+           imap-send-command-1
+           imap-send-command
+           imap-wait-for-tag
+           imap-sentinel
+           imap-find-next-line
+           imap-arrival-filter
+           imap-parse-greeting
+           imap-parse-response
+           imap-parse-resp-text
+           imap-parse-resp-text-code
+           imap-parse-data-list
+           imap-parse-fetch
+           imap-parse-status
+           imap-parse-acl
+           imap-parse-flag-list
+           imap-parse-envelope
+           imap-parse-body-extension
+           imap-parse-body
+           )))
+
+(provide 'imap)
+
+;;; imap.el ends here
index 288dc8a..0529e9a 100644 (file)
 ;; Shut up.
 
-(defvar byte-compile-default-warnings)
-
 (defun maybe-fbind (args)
   (while args
     (or (fboundp (car args))
-       (fset (car args) 'ignore))
+       (defalias (car args) 'ignore))
     (setq args (cdr args))))
 
 (defun maybe-bind (args)
   (mapcar (lambda (var) (unless (boundp var) (set var nil))) args))
 
-(if (string-match "XEmacs" emacs-version)
+(maybe-fbind '(Info-directory
+              Info-menu bbdb-create-internal bbdb-records create-image
+              display-graphic-p find-coding-system find-image image-size
+              image-type-available-p insert-image make-mode-line-mouse-map
+              make-temp-file propertize put-image replace-regexp-in-string
+              rmail-msg-is-pruned rmail-msg-restore-non-pruned-header
+              sort-coding-systems spam-BBDB-register-routine
+              spam-enter-ham-BBDB string-to-multibyte tool-bar-add-item
+              tool-bar-add-item-from-menu tool-bar-local-item-from-menu
+              url-generic-parse-url url-http-file-exists-p
+              url-insert-file-contents vcard-pretty-print w32-focus-frame
+              w3m-charset-to-coding-system w3m-region x-focus-frame))
+(maybe-bind '(filladapt-mode
+             mc-pgp-always-sign rmail-insert-mime-forwarded-message-function
+             url-current-object url-package-name url-package-version
+             w3-meta-charset-content-type-regexp
+             w3-meta-content-type-charset-regexp
+             w3m-cid-retrieve-function-alist w3m-current-buffer
+             w3m-display-inline-images w3m-meta-content-type-charset-regexp
+             w3m-minor-mode-map))
+
+(if (featurep 'xemacs)
     (progn
-      (defvar track-mouse nil)
-      (maybe-fbind '(posn-point
-                    event-start x-popup-menu
-                    facemenu-get-face window-at coordinates-in-window-p
-                    compute-motion x-defined-colors easy-menu-create-keymaps
-                    read-event internal-find-face internal-next-face-id
-                    make-face-internal set-frame-face-alist frame-face-alist
-                    facemenu-add-new-face make-face-x-resource-internal
-                    set-font-size set-font-family posn-window
-                    run-with-idle-timer mouse-minibuffer-check window-edges
-                    event-click-count track-mouse read-event mouse-movement-p
-                    event-end mouse-scroll-subr overlay-lists delete-overlay
-                    set-face-stipple mail-abbrevs-setup char-int
-                    make-char-table set-char-table-range font-create-object
-                    x-color-values widget-make-intangible error-message-string
-                    w3-form-encode-xwfu gnus-mule-get-coding-system
-                    decode-coding-string))
-      (maybe-bind '(global-face-data
-                   mark-active transient-mark-mode mouse-selection-click-count
-                   mouse-selection-click-count-buffer buffer-display-table
-                   font-lock-defaults user-full-name user-login-name
-                   gnus-newsgroup-name gnus-article-x-face-too-ugly
-                   mail-mode-hook enable-multibyte-characters)))
-  (maybe-bind '(mail-mode-hook
-               enable-multibyte-characters browse-url-browser-function))
-  (maybe-fbind '(color-instance-rgb-components
-                make-color-instance color-instance-name specifier-instance
-                device-type device-class get-popup-menu-response event-object
-                x-defined-colors read-color add-submenu set-font-family
-                font-create-object set-font-size frame-device find-face
-                set-extent-property make-extent characterp display-error
-                set-face-doc-string frame-property face-doc-string
-                button-press-event-p next-command-event
-                widget-make-intangible glyphp make-glyph set-glyph-image
-                set-glyph-property event-glyph glyph-property event-point
-                device-on-window-system-p make-gui-button Info-goto-node
-                pp-to-string color-name 
-                gnus-mule-get-coding-system decode-coding-string)))
-
-(setq load-path (cons "." load-path))
-(require 'custom)
-
-(defun md5 (a &optional b c)
+      (maybe-fbind '(delete-overlay
+                    event-click-count event-end event-start
+                    find-coding-systems-for-charsets
+                    find-coding-systems-region find-coding-systems-string
+                    mail-abbrevs-setup mouse-minibuffer-check
+                    mouse-movement-p mouse-scroll-subr overlay-lists
+                    posn-point posn-window read-event set-buffer-multibyte
+                    track-mouse window-edges))
+      (maybe-bind '(adaptive-fill-first-line-regexp
+                   buffer-display-table buffer-file-coding-system
+                   current-language-environment
+                   default-enable-multibyte-characters
+                   enable-multibyte-characters gnus-agent-expire-current-dirs
+                   language-info-alist mark-active mouse-selection-click-count
+                   mouse-selection-click-count-buffer pgg-parse-crc24
+                   temporary-file-directory transient-mark-mode)))
+  (maybe-fbind '(bbdb-complete-name
+                delete-annotation delete-extent device-connection dfw-device
+                events-to-keys font-lock-set-defaults frame-device
+                get-char-table glyph-height glyph-width mail-aliases-setup
+                make-annotation make-event make-glyph make-network-process
+                map-extents message-xmas-redefine put-char-table
+                set-extent-property temp-directory
+                valid-image-instantiator-format-p
+                w3-coding-system-for-mime-charset w3-do-setup
+                w3-prepare-buffer w3-region window-pixel-height
+                window-pixel-width))
+  (maybe-bind '(help-echo-owns-message mail-mode-hook mm-w3m-mode-map)))
+
+(when (and (featurep 'xemacs)
+          (not (featurep 'mule)))
+  (maybe-fbind '(ccl-execute-on-string
+                char-charset charsetp coding-system-get define-ccl-program
+                find-charset-region get-charset-property
+                pgg-parse-crc24-string))
+  (unless (featurep 'file-coding)
+    (maybe-fbind '(coding-system-base
+                  coding-system-list coding-system-p decode-coding-region
+                  decode-coding-string detect-coding-region
+                  encode-coding-region encode-coding-string))))
+
+(defun nnkiboze-score-file (a)
   )
 
+(defun split-line (&optional arg)
+  )
+
+
+;; T-gnus.
+(let ((functions
+       (cond
+       ((featurep 'xemacs)
+        '(frame-char-height frame-char-width))
+       ((>= emacs-major-version 21)
+        '(function-max-args smiley-encode-buffer))
+       ((boundp 'MULE)
+        '(charsetp
+          coding-system-base coding-system-get coding-system-list
+          coding-system-to-mime-charset compose-mail
+          file-name-extension find-coding-systems-for-charsets
+          find-coding-systems-region function-max-args get-charset-property
+          read-passwd ;; See the Mule23@1934 file.
+          smiley-encode-buffer smtpmail-send-it))
+       (t
+        '(function-max-args smiley-encode-buffer))))
+      (common-fns
+       nil)
+      (variables
+       (cond
+       ((featurep 'xemacs)
+        '(font-lock-defaults))
+       ((>= emacs-major-version 21)
+        nil)
+       ((boundp 'MULE)
+        '(adaptive-fill-first-line-regexp
+          default-enable-multibyte-characters enable-multibyte-characters))
+       (t
+        nil)))
+      (common-vars
+       '(default-mime-charset-unlimited navi2ch-mona-font)))
+  (maybe-fbind functions)
+  (maybe-fbind common-fns)
+  (maybe-bind variables)
+  (maybe-bind common-vars))
+
 (provide 'lpath)
diff --git a/lisp/mail-parse.el b/lisp/mail-parse.el
new file mode 100644 (file)
index 0000000..a5de09b
--- /dev/null
@@ -0,0 +1,75 @@
+;;; mail-parse.el --- Interface functions for parsing mail
+;; Copyright (C) 1998, 1999, 2000
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file contains wrapper functions for a wide range of mail
+;; parsing functions.  The idea is that there are low-level libraries
+;; that impement according to various specs (RFC2231, DRUMS, USEFOR),
+;; but that programmers that want to parse some header (say,
+;; Content-Type) will want to use the latest spec.
+;;
+;; So while each low-level library (rfc2231.el, for instance) decodes
+;; faithfully according to that (proposed) standard, this library is
+;; the interface library.  If some later RFC supersedes RFC2231, one
+;; would just have to write a new low-level library, adjust the
+;; aliases in this library, and the users and programmers won't notice
+;; any changes.
+
+;;; Code:
+
+(require 'mail-prsvr)
+(require 'ietf-drums)
+(require 'rfc2231)
+(require 'rfc2047)
+(require 'rfc2045)
+
+(defalias 'mail-header-parse-content-type 'rfc2231-parse-qp-string)
+(defalias 'mail-header-parse-content-disposition 'rfc2231-parse-qp-string)
+(defalias 'mail-content-type-get 'rfc2231-get-value)
+;(defalias 'mail-header-encode-parameter 'rfc2045-encode-string)
+(defalias 'mail-header-encode-parameter 'rfc2231-encode-string)
+
+(defalias 'mail-header-remove-comments 'ietf-drums-remove-comments)
+(defalias 'mail-header-remove-whitespace 'ietf-drums-remove-whitespace)
+(defalias 'mail-header-strip 'ietf-drums-strip)
+(defalias 'mail-header-get-comment 'ietf-drums-get-comment)
+(defalias 'mail-header-parse-address 'ietf-drums-parse-address)
+(defalias 'mail-header-parse-addresses 'ietf-drums-parse-addresses)
+(defalias 'mail-header-parse-date 'ietf-drums-parse-date)
+(defalias 'mail-narrow-to-head 'ietf-drums-narrow-to-header)
+(defalias 'mail-quote-string 'ietf-drums-quote-string)
+
+(defalias 'mail-header-fold-field 'rfc2047-fold-field)
+(defalias 'mail-header-unfold-field 'rfc2047-unfold-field)
+(defalias 'mail-header-narrow-to-field 'rfc2047-narrow-to-field)
+(defalias 'mail-header-field-value 'rfc2047-field-value)
+
+(defalias 'mail-encode-encoded-word-region 'rfc2047-encode-region)
+(defalias 'mail-encode-encoded-word-buffer 'rfc2047-encode-message-header)
+(defalias 'mail-encode-encoded-word-string 'rfc2047-encode-string)
+(defalias 'mail-decode-encoded-word-region 'rfc2047-decode-region)
+(defalias 'mail-decode-encoded-word-string 'rfc2047-decode-string)
+
+(provide 'mail-parse)
+
+;;; mail-parse.el ends here
diff --git a/lisp/mail-prsvr.el b/lisp/mail-prsvr.el
new file mode 100644 (file)
index 0000000..2566abc
--- /dev/null
@@ -0,0 +1,44 @@
+;;; mail-prsvr.el --- Interface variables for parsing mail
+;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(defvar mail-parse-charset nil
+  "Default charset used by low-level libraries.
+This variable should never be set.  Instead, it should be bound by
+functions that wish to call mail-parse functions and let them know
+what the desired charset is to be.")
+
+(defvar mail-parse-mule-charset nil
+  "Default MULE charset used by low-level libraries.
+This variable should never be set.")
+
+(defvar mail-parse-ignored-charsets nil
+  "Ignored charsets used by low-level libraries.
+This variable should never be set.  Instead, it should be bound by
+functions that wish to call mail-parse functions and let them know
+what the desired charsets is to be ignored.")
+
+(provide 'mail-prsvr)
+
+;;; mail-prsvr.el ends here
diff --git a/lisp/mail-source.el b/lisp/mail-source.el
new file mode 100644 (file)
index 0000000..061530e
--- /dev/null
@@ -0,0 +1,1076 @@
+;;; mail-source.el --- functions for fetching mail
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news, mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)
+  (require 'imap)
+  (defvar display-time-mail-function)
+  (autoload 'pop3-movemail "pop3")
+  (autoload 'pop3-get-message-count "pop3"))
+(eval-and-compile
+  (autoload 'nnheader-cancel-timer "nnheader")
+  (autoload 'nnheader-run-at-time "nnheader"))
+(require 'format-spec)
+(require 'message) ;; for `message-directory'
+
+(defgroup mail-source nil
+  "The mail-fetching library."
+  :version "21.1"
+  :group 'gnus)
+
+;; Define these at compile time to avoid dragging in imap always.
+(defconst mail-source-imap-authenticators
+  (eval-when-compile
+    (mapcar (lambda (a)
+             (list 'const (car a)))
+           imap-authenticator-alist)))
+(defconst mail-source-imap-streams
+  (eval-when-compile
+    (mapcar (lambda (a)
+             (list 'const (car a)))
+           imap-stream-alist)))
+
+(defcustom mail-sources nil
+  "*Where the mail backends will look for incoming mail.
+This variable is a list of mail source specifiers.
+See Info node `(gnus)Mail Source Specifiers'."
+  :group 'mail-source
+  :link '(custom-manual "(gnus)Mail Source Specifiers")
+  :type `(repeat
+         (choice :format "%[Value Menu%] %v"
+                 :value (file)
+                 (cons :tag "Spool file"
+                       (const :format "" file)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :path)
+                                         file)))
+                 (cons :tag "Several files in a directory"
+                       (const :format "" directory)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :path)
+                                         (directory :tag "Path"))
+                                  (group :inline t
+                                         (const :format "" :value :suffix)
+                                         (string :tag "Suffix"))
+                                  (group :inline t
+                                         (const :format "" :value :predicate)
+                                         (function :tag "Predicate"))
+                                  (group :inline t
+                                         (const :format "" :value :prescript)
+                                         (choice :tag "Prescript"
+                                                 :value nil
+                                                 (string :format "%v")
+                                                 (function :format "%v")))
+                                  (group :inline t
+                                         (const :format "" :value :postscript)
+                                         (choice :tag "Postscript"
+                                                 :value nil
+                                                 (string :format "%v")
+                                                 (function :format "%v")))
+                                  (group :inline t
+                                         (const :format "" :value :plugged)
+                                         (boolean :tag "Plugged"))))
+                 (cons :tag "POP3 server"
+                       (const :format "" pop)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :server)
+                                         (string :tag "Server"))
+                                  (group :inline t
+                                         (const :format "" :value :port)
+                                         (choice :tag "Port"
+                                                 :value "pop3"
+                                                 (number :format "%v")
+                                                 (string :format "%v")))
+                                  (group :inline t
+                                         (const :format "" :value :user)
+                                         (string :tag "User"))
+                                  (group :inline t
+                                         (const :format "" :value :password)
+                                         (string :tag "Password"))
+                                  (group :inline t
+                                         (const :format "" :value :program)
+                                         (string :tag "Program"))
+                                  (group :inline t
+                                         (const :format "" :value :prescript)
+                                         (choice :tag "Prescript"
+                                                 :value nil
+                                                 (string :format "%v")
+                                                 (function :format "%v")))
+                                  (group :inline t
+                                         (const :format "" :value :postscript)
+                                         (choice :tag "Postscript"
+                                                 :value nil
+                                                 (string :format "%v")
+                                                 (function :format "%v")))
+                                  (group :inline t
+                                         (const :format "" :value :function)
+                                         (function :tag "Function"))
+                                  (group :inline t
+                                         (const :format ""
+                                                :value :authentication)
+                                         (choice :tag "Authentication"
+                                                 :value apop
+                                                 (const password)
+                                                 (const apop)))
+                                  (group :inline t
+                                         (const :format "" :value :plugged)
+                                         (boolean :tag "Plugged"))))
+                 (cons :tag "Maildir (qmail, postfix...)"
+                       (const :format "" maildir)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :path)
+                                         (directory :tag "Path"))
+                                  (group :inline t
+                                         (const :format "" :value :plugged)
+                                         (boolean :tag "Plugged"))))
+                 (cons :tag "IMAP server"
+                       (const :format "" imap)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :server)
+                                         (string :tag "Server"))
+                                  (group :inline t
+                                         (const :format "" :value :port)
+                                         (choice :tag "Port"
+                                                 :value 143
+                                                 number string))
+                                  (group :inline t
+                                         (const :format "" :value :user)
+                                         (string :tag "User"))
+                                  (group :inline t
+                                         (const :format "" :value :password)
+                                         (string :tag "Password"))
+                                  (group :inline t
+                                         (const :format "" :value :stream)
+                                         (choice :tag "Stream"
+                                                 :value network
+                                                 ,@mail-source-imap-streams))
+                                  (group :inline t
+                                         (const :format "" :value :program)
+                                         (string :tag "Program"))
+                                  (group :inline t
+                                         (const :format ""
+                                                :value :authenticator)
+                                         (choice :tag "Authenticator"
+                                                 :value login
+                                                 ,@mail-source-imap-authenticators))
+                                  (group :inline t
+                                         (const :format "" :value :mailbox)
+                                         (string :tag "Mailbox"
+                                                 :value "INBOX"))
+                                  (group :inline t
+                                         (const :format "" :value :predicate)
+                                         (string :tag "Predicate"
+                                                 :value "UNSEEN UNDELETED"))
+                                  (group :inline t
+                                         (const :format "" :value :fetchflag)
+                                         (string :tag "Fetchflag"
+                                                 :value  "\\Deleted"))
+                                  (group :inline t
+                                         (const :format ""
+                                                :value :dontexpunge)
+                                         (boolean :tag "Dontexpunge"))
+                                  (group :inline t
+                                         (const :format "" :value :plugged)
+                                         (boolean :tag "Plugged"))))
+                 (cons :tag "Webmail server"
+                       (const :format "" webmail)
+                       (checklist :tag "Options" :greedy t
+                                  (group :inline t
+                                         (const :format "" :value :subtype)
+                                         ;; Should be generated from
+                                         ;; `webmail-type-definition', but we
+                                         ;; can't require webmail without W3.
+                                         (choice :tag "Subtype"
+                                                 :value hotmail
+                                                 (const hotmail)
+                                                 (const yahoo)
+                                                 (const netaddress)
+                                                 (const netscape)
+                                                 (const my-deja)))
+                                  (group :inline t
+                                         (const :format "" :value :user)
+                                         (string :tag "User"))
+                                  (group :inline t
+                                         (const :format "" :value :password)
+                                         (string :tag "Password"))
+                                  (group :inline t
+                                         (const :format ""
+                                                :value :dontexpunge)
+                                         (boolean :tag "Dontexpunge"))
+                                  (group :inline t
+                                         (const :format "" :value :plugged)
+                                         (boolean :tag "Plugged")))))))
+
+(defcustom mail-source-ignore-errors nil
+  "*Ignore errors when querying mail sources.
+If nil, the user will be prompted when an error occurs.  If non-nil,
+the error will be ignored.")
+
+(defcustom mail-source-primary-source nil
+  "*Primary source for incoming mail.
+If non-nil, this maildrop will be checked periodically for new mail."
+  :group 'mail-source
+  :type 'sexp)
+
+(defcustom mail-source-flash t
+  "*If non-nil, flash periodically when mail is available."
+  :group 'mail-source
+  :type 'boolean)
+
+(defcustom mail-source-crash-box "~/.emacs-mail-crash-box"
+  "File where mail will be stored while processing it."
+  :group 'mail-source
+  :type 'file)
+
+(defcustom mail-source-directory message-directory
+  "Directory where files (if any) will be stored."
+  :group 'mail-source
+  :type 'directory)
+
+(defcustom mail-source-default-file-modes 384
+  "Set the mode bits of all new mail files to this integer."
+  :group 'mail-source
+  :type 'integer)
+
+(defcustom mail-source-delete-incoming t
+  "*If non-nil, delete incoming files after handling.
+If t, delete immediately, if nil, never delete.  If a positive number, delete
+files older than number of days."
+  ;; Note: The removing happens in `mail-source-callback', i.e. no old
+  ;; incoming files will be deleted, unless you receive new mail.
+  ;;
+  ;; You may also set this to `nil' and call `mail-source-delete-old-incoming'
+  ;; from a hook or interactively.
+  :group 'mail-source
+  :type '(choice (const :tag "immediately" t)
+                (const :tag "never" nil)
+                (integer :tag "days")))
+
+(defcustom mail-source-delete-old-incoming-confirm t
+  "*If non-nil, ask for for confirmation before deleting old incoming files.
+This variable only applies when `mail-source-delete-incoming' is a positive
+number."
+  :group 'mail-source
+  :type 'boolean)
+
+(defcustom mail-source-incoming-file-prefix "Incoming"
+  "Prefix for file name for storing incoming mail"
+  :group 'mail-source
+  :type 'string)
+
+(defcustom mail-source-report-new-mail-interval 5
+  "Interval in minutes between checks for new mail."
+  :group 'mail-source
+  :type 'number)
+
+(defcustom mail-source-idle-time-delay 5
+  "Number of idle seconds to wait before checking for new mail."
+  :group 'mail-source
+  :type 'number)
+
+(defcustom mail-source-movemail-program nil
+  "If non-nil, name of program for fetching new mail."
+  :group 'mail-source
+  :type '(choice (const nil) string))
+
+;;; Internal variables.
+
+(defvar mail-source-string ""
+  "A dynamically bound string that says what the current mail source is.")
+
+(defvar mail-source-new-mail-available nil
+  "Flag indicating when new mail is available.")
+
+(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)
+       (:prescript-delay)
+       (:postscript)
+       (:path (or (getenv "MAIL")
+                 (expand-file-name (user-login-name) rmail-spool-directory))))
+      (directory
+       (:prescript)
+       (:prescript-delay)
+       (:postscript)
+       (:path)
+       (:suffix ".spool")
+       (:predicate identity))
+      (pop
+       (:prescript)
+       (:prescript-delay)
+       (:postscript)
+       (:server (getenv "MAILHOST"))
+       (:port 110)
+       (:user (or (user-login-name) (getenv "LOGNAME") (getenv "USER")))
+       (:program)
+       (:function)
+       (:password)
+       (:connection)
+       (:authentication password)
+       (:leave))
+      (maildir
+       (:path (or (getenv "MAILDIR") "~/Maildir/"))
+       (:subdirs ("cur" "new"))
+       (:function))
+      (imap
+       (:server (getenv "MAILHOST"))
+       (:port)
+       (:stream)
+       (:program)
+       (:authentication)
+       (:user (or (user-login-name) (getenv "LOGNAME") (getenv "USER")))
+       (:password)
+       (:mailbox "INBOX")
+       (:predicate "UNSEEN UNDELETED")
+       (:fetchflag "\\Deleted")
+       (:prescript)
+       (:prescript-delay)
+       (:postscript)
+       (:dontexpunge))
+      (webmail
+       (:subtype hotmail)
+       (:user (or (user-login-name) (getenv "LOGNAME") (getenv "USER")))
+       (:password)
+       (:dontexpunge)
+       (:authentication password)))
+    "Mapping from keywords to default values.
+All keywords that can be used must be listed here."))
+
+(defvar mail-source-fetcher-alist
+  '((file mail-source-fetch-file)
+    (directory mail-source-fetch-directory)
+    (pop mail-source-fetch-pop)
+    (maildir mail-source-fetch-maildir)
+    (imap mail-source-fetch-imap)
+    (webmail mail-source-fetch-webmail))
+  "A mapping from source type to fetcher function.")
+
+(defvar mail-source-password-cache nil)
+
+(defvar mail-source-plugged t)
+
+;;; Functions
+
+(eval-and-compile
+  (defun mail-source-strip-keyword (keyword)
+    "Strip the leading colon off the KEYWORD."
+    (intern (substring (symbol-name keyword) 1))))
+
+(eval-and-compile
+  (defun mail-source-bind-1 (type)
+    (let* ((defaults (cdr (assq type mail-source-keyword-map)))
+          default bind)
+      (while (setq default (pop defaults))
+       (push (list (mail-source-strip-keyword (car default))
+                   nil)
+             bind))
+      bind)))
+
+(defmacro mail-source-bind (type-source &rest body)
+  "Return a `let' form that binds all variables in source TYPE.
+TYPE-SOURCE is a list where the first element is the TYPE, and
+the second variable is the SOURCE.
+At run time, the mail source specifier SOURCE will be inspected,
+and the variables will be set according to it.  Variables not
+specified will be given default values.
+
+After this is done, BODY will be executed in the scope
+of the `let' form.
+
+The variables bound and their default values are described by
+the `mail-source-keyword-map' variable."
+  `(let ,(mail-source-bind-1 (car type-source))
+     (mail-source-set-1 ,(cadr type-source))
+     ,@body))
+
+(put 'mail-source-bind 'lisp-indent-function 1)
+(put 'mail-source-bind 'edebug-form-spec '(sexp body))
+
+(defun mail-source-set-1 (source)
+  (let* ((type (pop source))
+        (defaults (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)
+            (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 '(sexp body))
+
+(defun mail-source-value (value)
+  "Return the value of VALUE."
+  (cond
+   ;; String
+   ((stringp value)
+    value)
+   ;; Function
+   ((and (listp value)
+        (functionp (car value)))
+    (eval value))
+   ;; Just return the value.
+   (t
+    value)))
+
+(defun mail-source-fetch (source callback)
+  "Fetch mail from SOURCE and call CALLBACK zero or more times.
+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."
+  (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
+              (if (or debug-on-quit debug-on-error)
+                  (funcall function source callback)
+                (condition-case err
+                    (funcall function source callback)
+                  (error
+                   (if (and (not mail-source-ignore-errors)
+                            (not
+                             (yes-or-no-p
+                              (format "Mail source %s error (%s).  Continue? "
+                                      (if (memq ':password source)
+                                          (let ((s (copy-sequence source)))
+                                            (setcar (cdr (memq ':password s)) 
+                                                    "********")
+                                            s)
+                                        source)
+                                      (cadr err)))))
+                     (error "Cannot get new mail"))
+                   0)))))))))
+
+(defun mail-source-delete-old-incoming (&optional age confirm)
+  "Remove incoming files older than AGE days.
+If CONFIRM is non-nil, ask for confirmation before removing a file."
+  (interactive "P")
+  (let* ((high2days (/ 65536.0 60 60 24));; convert high bits to days
+        (low2days  (/ 1.0 65536.0))     ;; convert low bits to days
+        (diff (if (natnump age) age 30));; fallback, if no valid AGE given
+        currday files)
+    (setq files (directory-files
+                mail-source-directory t
+                (concat mail-source-incoming-file-prefix "*"))
+         currday (* (car (current-time)) high2days)
+         currday (+ currday (* low2days (nth 1 (current-time)))))
+    (while files
+      (let* ((ffile (car files))
+            (bfile (gnus-replace-in-string
+                    ffile "\\`.*/\\([^/]+\\)\\'" "\\1"))
+            (filetime (nth 5 (file-attributes ffile)))
+            (fileday (* (car filetime) high2days))
+            (fileday (+ fileday (* low2days (nth 1 filetime)))))
+       (setq files (cdr files))
+       (when (and (> (- currday fileday) diff)
+                  (gnus-message 8 "File `%s' is older than %s day(s)"
+                                bfile diff)
+                  (or (not confirm)
+                      (y-or-n-p (concat "Remove file `" bfile "'? "))))
+         (delete-file ffile))))))
+
+(defun mail-source-callback (callback info)
+  "Call CALLBACK on the mail file, and then remove the mail file.
+Pass INFO on to CALLBACK."
+  (if (or (not (file-exists-p mail-source-crash-box))
+         (zerop (nth 7 (file-attributes mail-source-crash-box))))
+      (progn
+       (when (file-exists-p mail-source-crash-box)
+         (delete-file mail-source-crash-box))
+       0)
+    (prog1
+       (funcall callback mail-source-crash-box info)
+      (when (file-exists-p mail-source-crash-box)
+       ;; Delete or move the incoming mail out of the way.
+       (if (eq mail-source-delete-incoming t)
+           (delete-file mail-source-crash-box)
+         (let ((incoming
+                (mm-make-temp-file
+                 (expand-file-name
+                  mail-source-incoming-file-prefix
+                  mail-source-directory))))
+           (unless (file-exists-p (file-name-directory incoming))
+             (make-directory (file-name-directory incoming) t))
+           (rename-file mail-source-crash-box incoming t)
+           ;; remove old incoming files?
+           (when (natnump mail-source-delete-incoming)
+             (mail-source-delete-old-incoming
+              mail-source-delete-incoming
+              mail-source-delete-old-incoming-confirm))))))))
+
+(defun mail-source-movemail (from to)
+  "Move FROM to TO using movemail."
+  (if (not (file-writable-p to))
+      (error "Can't write to crash box %s.  Not moving mail" to)
+    (let ((to (file-truename (expand-file-name to)))
+         errors result)
+      (setq to (file-truename to)
+           from (file-truename from))
+      ;; Set TO if have not already done so, and rename or copy
+      ;; the file FROM to TO if and as appropriate.
+      (cond
+       ((file-exists-p to)
+       ;; The crash box exists already.
+       t)
+       ((not (file-exists-p from))
+       ;; There is no inbox.
+       (setq to nil))
+       ((zerop (nth 7 (file-attributes from)))
+       ;; Empty file.
+       (setq to nil))
+       (t
+       ;; If getting from mail spool directory, use movemail to move
+       ;; rather than just renaming, so as to interlock with the
+       ;; mailer.
+       (unwind-protect
+           (save-excursion
+             (setq errors (generate-new-buffer " *mail source loss*"))
+             (let ((default-directory "/"))
+               (setq result
+                     (apply
+                      'call-process
+                      (append
+                       (list
+                        (or mail-source-movemail-program
+                            (expand-file-name "movemail" exec-directory))
+                        nil errors nil from to)))))
+             (when (file-exists-p to)
+               (set-file-modes to mail-source-default-file-modes))
+             (if (and (or (not (buffer-modified-p errors))
+                          (zerop (buffer-size errors)))
+                      (and (numberp result)
+                           (zerop result)))
+                 ;; No output => movemail won.
+                 t
+               (set-buffer errors)
+               ;; There may be a warning about older revisions.  We
+               ;; ignore that.
+               (goto-char (point-min))
+               (if (search-forward "older revision" nil t)
+                   t
+                 ;; Probably a real error.
+                 (subst-char-in-region (point-min) (point-max) ?\n ?\  )
+                 (goto-char (point-max))
+                 (skip-chars-backward " \t")
+                 (delete-region (point) (point-max))
+                 (goto-char (point-min))
+                 (when (looking-at "movemail: ")
+                   (delete-region (point-min) (match-end 0)))
+                 ;; Result may be a signal description string.
+                 (unless (yes-or-no-p
+                          (format "movemail: %s (%s return).  Continue? "
+                                  (buffer-string) result))
+                   (error "%s" (buffer-string)))
+                 (setq to nil)))))))
+      (when (and errors
+                (buffer-name errors))
+       (kill-buffer errors))
+      ;; Return whether we moved successfully or not.
+      to)))
+
+(defun mail-source-movemail-and-remove (from to)
+  "Move FROM to TO using movemail, then remove FROM if empty."
+  (or (not (mail-source-movemail from to))
+      (not (zerop (nth 7 (file-attributes from))))
+      (delete-file from)))
+
+(defun mail-source-fetch-with-program (program)
+  (eq 0 (call-process shell-file-name nil nil nil
+                     shell-command-switch program)))
+
+(defun mail-source-run-script (script spec &optional delay)
+  (when script
+    (if (functionp script)
+       (funcall script)
+      (mail-source-call-script
+       (format-spec script spec))))
+  (when delay
+    (sleep-for delay)))
+
+(defun mail-source-call-script (script)
+  (let ((background nil))
+    (when (string-match "& *$" script)
+      (setq script (substring script 0 (match-beginning 0))
+           background 0))
+    (call-process shell-file-name nil background nil
+                 shell-command-switch script)))
+
+;;;
+;;; Different fetchers
+;;;
+
+(defun mail-source-fetch-file (source callback)
+  "Fetcher for single-file sources."
+  (mail-source-bind (file source)
+    (mail-source-run-script
+     prescript (format-spec-make ?t mail-source-crash-box)
+     prescript-delay)
+    (let ((mail-source-string (format "file:%s" path)))
+      (if (mail-source-movemail path mail-source-crash-box)
+         (prog1
+             (mail-source-callback callback path)
+           (mail-source-run-script
+            postscript (format-spec-make ?t mail-source-crash-box)))
+       0))))
+
+(defun mail-source-fetch-directory (source callback)
+  "Fetcher for directory sources."
+  (mail-source-bind (directory source)
+    (mail-source-run-script
+     prescript (format-spec-make ?t path) prescript-delay)
+    (let ((found 0)
+         (mail-source-string (format "directory:%s" path)))
+      (dolist (file (directory-files
+                    path t (concat (regexp-quote suffix) "$")))
+       (when (and (file-regular-p file)
+                  (funcall predicate file)
+                  (mail-source-movemail file mail-source-crash-box))
+         (incf found (mail-source-callback callback file))))
+      (mail-source-run-script postscript (format-spec-make ?t path))
+      found)))
+
+(defun mail-source-fetch-pop (source callback)
+  "Fetcher for single-file sources."
+  (mail-source-bind (pop source)
+    (mail-source-run-script
+     prescript
+     (format-spec-make ?p password ?t mail-source-crash-box
+                      ?s server ?P port ?u user)
+     prescript-delay)
+    (let ((from (format "%s:%s:%s" server user port))
+         (mail-source-string (format "pop:%s@%s" user server))
+         result)
+      (when (eq authentication 'password)
+       (setq password
+             (or password
+                 (cdr (assoc from mail-source-password-cache))
+                 (read-passwd
+                  (format "Password for %s at %s: " user server)))))
+      (when server
+       (setenv "MAILHOST" server))
+      (setq result
+           (cond
+            (program
+             (mail-source-fetch-with-program
+              (format-spec
+               program
+               (format-spec-make ?p password ?t mail-source-crash-box
+                                 ?s server ?P port ?u user))))
+            (function
+             (funcall function mail-source-crash-box))
+            ;; The default is to use pop3.el.
+            (t
+             (require 'pop3)
+             (let ((pop3-password password)
+                   (pop3-maildrop user)
+                   (pop3-mailhost server)
+                   (pop3-port port)
+                   (pop3-authentication-scheme
+                    (if (eq authentication 'apop) 'apop 'pass))
+                   (pop3-connection-type connection)
+                   (pop3-leave-mail-on-server
+                    (or leave
+                        (and (boundp 'pop3-leave-mail-on-server)
+                             (symbol-value 'pop3-leave-mail-on-server)))))
+               (if (or debug-on-quit debug-on-error)
+                   (save-excursion (pop3-movemail mail-source-crash-box))
+                 (condition-case err
+                     (save-excursion (pop3-movemail mail-source-crash-box))
+                   (error
+                    ;; We nix out the password in case the error
+                    ;; was because of a wrong password being given.
+                    (setq mail-source-password-cache
+                          (delq (assoc from mail-source-password-cache)
+                                mail-source-password-cache))
+                    (signal (car err) (cdr err)))))))))
+      (if result
+         (progn
+           (when (eq authentication 'password)
+             (unless (assoc from mail-source-password-cache)
+               (push (cons from password) mail-source-password-cache)))
+           (prog1
+               (mail-source-callback callback server)
+             ;; Update display-time's mail flag, if relevant.
+             (if (equal source mail-source-primary-source)
+                 (setq mail-source-new-mail-available nil))
+             (mail-source-run-script
+              postscript
+              (format-spec-make ?p password ?t mail-source-crash-box
+                                ?s server ?P port ?u user))))
+       ;; We nix out the password in case the error
+       ;; was because of a wrong password being given.
+       (setq mail-source-password-cache
+             (delq (assoc from mail-source-password-cache)
+                   mail-source-password-cache))
+       0))))
+
+(defun mail-source-check-pop (source)
+  "Check whether there is new mail."
+  (mail-source-bind (pop source)
+    (let ((from (format "%s:%s:%s" server user port))
+         (mail-source-string (format "pop:%s@%s" user server))
+         result)
+      (when (eq authentication 'password)
+       (setq password
+             (or password
+                 (cdr (assoc from mail-source-password-cache))
+                 (read-passwd
+                  (format "Password for %s at %s: " user server))))
+       (unless (assoc from mail-source-password-cache)
+         (push (cons from password) mail-source-password-cache)))
+      (when server
+       (setenv "MAILHOST" server))
+      (setq result
+           (cond
+            ;; No easy way to check whether mail is waiting for these.
+            (program)
+            (function)
+            ;; The default is to use pop3.el.
+            (t
+             (require 'pop3)
+             (let ((pop3-password password)
+                   (pop3-maildrop user)
+                   (pop3-mailhost server)
+                   (pop3-port port)
+                   (pop3-authentication-scheme
+                    (if (eq authentication 'apop) 'apop 'pass)))
+               (if (or debug-on-quit debug-on-error)
+                   (save-excursion (pop3-get-message-count))
+                 (condition-case err
+                     (save-excursion (pop3-get-message-count))
+                   (error
+                    ;; We nix out the password in case the error
+                    ;; was because of a wrong password being given.
+                    (setq mail-source-password-cache
+                          (delq (assoc from mail-source-password-cache)
+                                mail-source-password-cache))
+                    (signal (car err) (cdr err)))))))))
+      (if result
+         ;; Inform display-time that we have new mail.
+         (setq mail-source-new-mail-available (> result 0))
+       ;; We nix out the password in case the error
+       ;; was because of a wrong password being given.
+       (setq mail-source-password-cache
+             (delq (assoc from mail-source-password-cache)
+                   mail-source-password-cache)))
+      result)))
+
+(defun mail-source-touch-pop ()
+  "Open and close a POP connection shortly.
+POP server should be defined in `mail-source-primary-source' (which is
+preferred) or `mail-sources'.  You may use it for the POP-before-SMTP
+authentication.  To do that, you need to set the option
+`message-send-mail-function' to `message-send-mail-with-smtp' or
+`message-smtpmail-send-it' and put the following line in .gnus file:
+
+\(add-hook 'message-send-mail-hook 'mail-source-touch-pop)
+"
+  (let ((sources (if mail-source-primary-source
+                    (list mail-source-primary-source)
+                  mail-sources)))
+    (while sources
+      (if (eq 'pop (car (car sources)))
+         (mail-source-check-pop (car sources)))
+      (setq sources (cdr sources)))))
+
+(defun mail-source-new-mail-p ()
+  "Handler for `display-time' to indicate when new mail is available."
+  ;; Flash (ie. ring the visible bell) if mail is available.
+  (if (and mail-source-flash mail-source-new-mail-available)
+      (let ((visible-bell t))
+       (ding)))
+  ;; Only report flag setting; flag is updated on a different schedule.
+  mail-source-new-mail-available)
+
+
+(defvar mail-source-report-new-mail nil)
+(defvar mail-source-report-new-mail-timer nil)
+(defvar mail-source-report-new-mail-idle-timer nil)
+
+(eval-when-compile
+  (if (featurep 'xemacs)
+      (require 'itimer)
+    (require 'timer)))
+
+(defun mail-source-start-idle-timer ()
+  ;; Start our idle timer if necessary, so we delay the check until the
+  ;; user isn't typing.
+  (unless mail-source-report-new-mail-idle-timer
+    (setq mail-source-report-new-mail-idle-timer
+         (run-with-idle-timer
+          mail-source-idle-time-delay
+          nil
+          (lambda ()
+            (unwind-protect
+                (mail-source-check-pop mail-source-primary-source)
+              (setq mail-source-report-new-mail-idle-timer nil)))))
+    ;; Since idle timers created when Emacs is already in the idle
+    ;; state don't get activated until Emacs _next_ becomes idle, we
+    ;; need to force our timer to be considered active now.  We do
+    ;; this by being naughty and poking the timer internals directly
+    ;; (element 0 of the vector is nil if the timer is active).
+    (aset mail-source-report-new-mail-idle-timer 0 nil)))
+
+(defun mail-source-report-new-mail (arg)
+  "Toggle whether to report when new mail is available.
+This only works when `display-time' is enabled."
+  (interactive "P")
+  (if (not mail-source-primary-source)
+      (error "Need to set `mail-source-primary-source' to check for new mail"))
+  (let ((on (if (null arg)
+               (not mail-source-report-new-mail)
+             (> (prefix-numeric-value arg) 0))))
+    (setq mail-source-report-new-mail on)
+    (and mail-source-report-new-mail-timer
+        (nnheader-cancel-timer mail-source-report-new-mail-timer))
+    (and mail-source-report-new-mail-idle-timer
+        (nnheader-cancel-timer mail-source-report-new-mail-idle-timer))
+    (setq mail-source-report-new-mail-timer nil)
+    (setq mail-source-report-new-mail-idle-timer nil)
+    (if on
+       (progn
+         (require 'time)
+         ;; display-time-mail-function is an Emacs 21 feature.
+         (setq display-time-mail-function #'mail-source-new-mail-p)
+         ;; Set up the main timer.
+         (setq mail-source-report-new-mail-timer
+               (nnheader-run-at-time
+                (* 60 mail-source-report-new-mail-interval)
+                (* 60 mail-source-report-new-mail-interval)
+                #'mail-source-start-idle-timer))
+         ;; When you get new mail, clear "Mail" from the mode line.
+         (add-hook 'nnmail-post-get-new-mail-hook
+                   'display-time-event-handler)
+         (message "Mail check enabled"))
+      (setq display-time-mail-function nil)
+      (remove-hook 'nnmail-post-get-new-mail-hook
+                  'display-time-event-handler)
+      (message "Mail check disabled"))))
+
+(defun mail-source-fetch-maildir (source callback)
+  "Fetcher for maildir sources."
+  (mail-source-bind (maildir source)
+    (let ((found 0)
+         mail-source-string)
+      (unless (string-match "/$" path)
+       (setq path (concat path "/")))
+      (dolist (subdir subdirs)
+       (when (file-directory-p (concat path subdir))
+         (setq mail-source-string (format "maildir:%s%s" path subdir))
+         (dolist (file (directory-files (concat path subdir) t))
+           (when (and (not (file-directory-p file))
+                      (not (if function
+                               (funcall function file mail-source-crash-box)
+                             (let ((coding-system-for-write
+                                    nnheader-text-coding-system)
+                                   (coding-system-for-read
+                                    nnheader-text-coding-system)
+                                   (output-coding-system
+                                    nnheader-text-coding-system)
+                                   (input-coding-system
+                                    nnheader-text-coding-system))
+                               (with-temp-file mail-source-crash-box
+                                 (insert-file-contents file)
+                                 (goto-char (point-min))
+;;;                              ;; Unix mail format
+;;;                              (unless (looking-at "\n*From ")
+;;;                                (insert "From maildir "
+;;;                                        (current-time-string) "\n"))
+;;;                              (while (re-search-forward "^From " nil t)
+;;;                                (replace-match ">From "))
+;;;                              (goto-char (point-max))
+;;;                              (insert "\n\n")
+                                 ;; MMDF mail format
+                                 (insert "\001\001\001\001\n"))
+                               (delete-file file)))))
+             (incf found (mail-source-callback callback file))))))
+      found)))
+
+(eval-and-compile
+  (autoload 'imap-open "imap")
+  (autoload 'imap-authenticate "imap")
+  (autoload 'imap-mailbox-select "imap")
+  (autoload 'imap-mailbox-unselect "imap")
+  (autoload 'imap-mailbox-close "imap")
+  (autoload 'imap-search "imap")
+  (autoload 'imap-fetch "imap")
+  (autoload 'imap-close "imap")
+  (autoload 'imap-error-text "imap")
+  (autoload 'imap-message-flags-add "imap")
+  (autoload 'imap-list-to-message-set "imap")
+  (autoload 'imap-range-to-message-set "imap"))
+
+(defvar mail-source-imap-file-coding-system 'binary
+  "Coding system for the crashbox made by `mail-source-fetch-imap'.")
+
+(defun mail-source-fetch-imap (source callback)
+  "Fetcher for imap sources."
+  (mail-source-bind (imap source)
+    (mail-source-run-script
+     prescript (format-spec-make ?p password ?t mail-source-crash-box
+                                ?s server ?P port ?u user)
+     prescript-delay)
+    (let ((from (format "%s:%s:%s" server user port))
+         (found 0)
+         (buf (generate-new-buffer " *imap source*"))
+         (mail-source-string (format "imap:%s:%s" server mailbox))
+         (imap-shell-program (or (list program) imap-shell-program))
+         remove)
+      (if (and (imap-open server port stream authentication buf)
+              (imap-authenticate
+               user (or (cdr (assoc from mail-source-password-cache))
+                        password) buf)
+              (imap-mailbox-select mailbox nil buf))
+         (let ((coding-system-for-write mail-source-imap-file-coding-system)
+               (output-coding-system mail-source-imap-file-coding-system)
+               str)
+           (with-temp-file mail-source-crash-box
+             ;; Avoid converting 8-bit chars from inserted strings to
+             ;; multibyte.
+             (set-buffer-multibyte nil)
+             ;; remember password
+             (with-current-buffer buf
+               (when (and imap-password
+                          (not (assoc from mail-source-password-cache)))
+                 (push (cons from imap-password) mail-source-password-cache)))
+             ;; if predicate is nil, use all uids
+             (dolist (uid (imap-search (or predicate "1:*") buf))
+               (when (setq str
+                           (if (imap-capability 'IMAP4rev1 buf)
+                               (caddar (imap-fetch uid "BODY.PEEK[]"
+                                                   'BODYDETAIL nil buf))
+                             (imap-fetch uid "RFC822.PEEK" 'RFC822 nil buf)))
+                 (push uid remove)
+                 (insert "From imap " (current-time-string) "\n")
+                 (save-excursion
+                   (insert str "\n\n"))
+                 (while (re-search-forward "^From " nil t)
+                   (replace-match ">From "))
+                 (goto-char (point-max))))
+             (nnheader-ms-strip-cr))
+           (incf found (mail-source-callback callback server))
+           (when (and remove fetchflag)
+             (setq remove (nreverse remove))
+             (imap-message-flags-add
+              (imap-range-to-message-set (gnus-compress-sequence remove))
+              fetchflag nil buf))
+           (if dontexpunge
+               (imap-mailbox-unselect buf)
+             (imap-mailbox-close nil buf))
+           (imap-close buf))
+       (imap-close buf)
+       ;; We nix out the password in case the error
+       ;; was because of a wrong password being given.
+       (setq mail-source-password-cache
+             (delq (assoc from mail-source-password-cache)
+                   mail-source-password-cache))
+       (error "IMAP error: %s" (imap-error-text buf)))
+      (kill-buffer buf)
+      (mail-source-run-script
+       postscript
+       (format-spec-make ?p password ?t mail-source-crash-box
+                        ?s server ?P port ?u user))
+      found)))
+
+(eval-and-compile
+  (autoload 'webmail-fetch "webmail"))
+
+(defun mail-source-fetch-webmail (source callback)
+  "Fetch for webmail source."
+  (mail-source-bind (webmail source)
+    (let ((mail-source-string (format "webmail:%s:%s" subtype user))
+         (webmail-newmail-only dontexpunge)
+         (webmail-move-to-trash-can (not dontexpunge)))
+      (when (eq authentication 'password)
+       (setq password
+             (or password
+                 (cdr (assoc (format "webmail:%s:%s" subtype user)
+                             mail-source-password-cache))
+                 (read-passwd
+                  (format "Password for %s at %s: " user subtype))))
+       (when (and password
+                  (not (assoc (format "webmail:%s:%s" subtype user)
+                              mail-source-password-cache)))
+         (push (cons (format "webmail:%s:%s" subtype user) password)
+               mail-source-password-cache)))
+      (webmail-fetch mail-source-crash-box subtype user password)
+      (mail-source-callback callback (symbol-name subtype)))))
+
+(provide 'mail-source)
+
+;;; mail-source.el ends here
index 5e2b097..796ae75 100644 (file)
@@ -46,7 +46,7 @@
 
 ;;; Code:
 
-(require 'cl)
+(eval-when-compile (require 'cl))
 
 ;; Make the byte-compiler shut up.
 (defvar headers)
@@ -60,7 +60,7 @@ that name."
        start end)
     (while (and (setq start (point))
                (> (skip-chars-forward "^\0- :") 0)
-               (= (following-char) ?:)
+               (eq (char-after) ?:)
                (setq end (point))
                (progn (forward-char)
                       (> (skip-chars-forward " \t") 0)))
index 3fabf29..2f85d70 100644 (file)
@@ -11,7 +11,7 @@
 ;; This is a direct translation into Emacs LISP of the reference C
 ;; implementation of the MD5 Message-Digest Algorithm written by RSA
 ;; Data Security, Inc.
-;; 
+;;
 ;; The algorithm takes a message (that is, a string of bytes) and
 ;; computes a 16-byte checksum or "digest" for the message.  This digest
 ;; is supposed to be cryptographically strong in the sense that if you
@@ -20,7 +20,7 @@
 ;; space of messages.  However, the robustness of the algorithm has not
 ;; been proven, and a similar algorithm (MD4) was shown to be unsound,
 ;; so treat with caution!
-;; 
+;;
 ;; The C algorithm uses 32-bit integers; because GNU Emacs
 ;; implementations provide 28-bit integers (with 24-bit integers on
 ;; versions prior to 19.29), the code represents a 32-bit integer as the
 
 ;; To compute the MD5 Message Digest for a message M (represented as a
 ;; string or as a vector of bytes), call
-;; 
+;;
 ;;   (md5-encode M)
-;; 
+;;
 ;; which returns the message digest as a vector of 16 bytes.  If you
 ;; need to supply the message in pieces M1, M2, ... Mn, then call
-;; 
+;;
 ;;   (md5-init)
 ;;   (md5-update M1)
 ;;   (md5-update M2)
 
 ;; Copyright (C) 1995 by Gareth Rees
 ;; Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
-;; 
+;;
 ;; md5.el is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by the
 ;; Free Software Foundation; either version 2, or (at your option) any
 ;; later version.
-;; 
+;;
 ;; md5.el is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 ;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 ;; for more details.
-;; 
+;;
 ;; The original copyright notice is given below, as required by the
 ;; licence for the original code.  This code is distributed under *both*
 ;; RSA's original licence and the GNU General Public Licence.  (There
@@ -148,16 +148,16 @@ Returns a vector of 16 bytes containing the message digest."
 (defsubst md5-add (x y)
   "Return 32-bit sum of 32-bit integers X and Y."
   (let ((m (+ (car x) (car y)))
-        (l (+ (cdr x) (cdr y))))
+       (l (+ (cdr x) (cdr y))))
     (cons (logand 65535 (+ m (lsh l -16))) (logand l 65535))))
 
 ;; FF, GG, HH and II are basic MD5 functions, providing transformations
 ;; for rounds 1, 2, 3 and 4 respectively.  Each function follows this
 ;; pattern of computation (where ROTATE(x,y) means rotate 32-bit value x
 ;; by y bits to the left):
-;; 
+;;
 ;;   FF(a,b,c,d,x,s,ac) = ROTATE(a + F(b,c,d) + x + ac,s) + b
-;; 
+;;
 ;; so we use the macro `md5-make-step' to construct each one.  The
 ;; helper functions F, G, H and I operate on 16-bit numbers; the full
 ;; operation splits its inputs, operates on the halves separately and
@@ -172,16 +172,16 @@ Returns a vector of 16 bytes containing the message digest."
   (`
    (defun (, name) (a b c d x s ac)
      (let*
-         ((m1 (+ (car a) ((, func) (car b) (car c) (car d)) (car x) (car ac)))
-          (l1 (+ (cdr a) ((, func) (cdr b) (cdr c) (cdr d)) (cdr x) (cdr ac)))
-          (m2 (logand 65535 (+ m1 (lsh l1 -16))))
-          (l2 (logand 65535 l1))
-          (m3 (logand 65535 (if (> s 15)
-                                (+ (lsh m2 (- s 32)) (lsh l2 (- s 16)))
-                              (+ (lsh m2 s) (lsh l2 (- s 16))))))
-          (l3 (logand 65535 (if (> s 15)
-                                (+ (lsh l2 (- s 32)) (lsh m2 (- s 16)))
-                              (+ (lsh l2 s) (lsh m2 (- s 16)))))))
+        ((m1 (+ (car a) ((, func) (car b) (car c) (car d)) (car x) (car ac)))
+         (l1 (+ (cdr a) ((, func) (cdr b) (cdr c) (cdr d)) (cdr x) (cdr ac)))
+         (m2 (logand 65535 (+ m1 (lsh l1 -16))))
+         (l2 (logand 65535 l1))
+         (m3 (logand 65535 (if (> s 15)
+                               (+ (lsh m2 (- s 32)) (lsh l2 (- s 16)))
+                             (+ (lsh m2 s) (lsh l2 (- s 16))))))
+         (l3 (logand 65535 (if (> s 15)
+                               (+ (lsh l2 (- s 32)) (lsh m2 (- s 16)))
+                             (+ (lsh l2 s) (lsh m2 (- s 16)))))))
        (md5-add (cons m3 l3) b)))))
 
 (md5-make-step md5-FF md5-F)
@@ -203,8 +203,8 @@ Returns a vector of 16 bytes containing the message digest."
 (defun md5-update (string)
   "Update the current MD5 state with STRING (an array of bytes)."
   (let ((len (length string))
-        (i 0)
-        (j 0))
+       (i 0)
+       (j 0))
     (while (< i len)
       ;; Compute number of bytes modulo 64
       (setq j (% (/ (aref md5-bits 0) 8) 64))
@@ -214,11 +214,11 @@ Returns a vector of 16 bytes containing the message digest."
 
       ;; Update number of bits by 8 (modulo 2^64)
       (let ((c 8) (k 0))
-        (while (and (> c 0) (< k 4))
-          (let ((b (aref md5-bits k)))
-            (aset md5-bits k (logand 65535 (+ b c)))
-            (setq c (if (> b (- 65535 c)) 1 0)
-                  k (1+ k)))))
+       (while (and (> c 0) (< k 4))
+         (let ((b (aref md5-bits k)))
+           (aset md5-bits k (logand 65535 (+ b c)))
+           (setq c (if (> b (- 65535 c)) 1 0)
+                 k (1+ k)))))
 
       ;; Increment number of bytes processed
       (setq i (1+ i))
@@ -226,32 +226,32 @@ Returns a vector of 16 bytes containing the message digest."
       ;; When 64 bytes accumulated, pack them into sixteen 32-bit
       ;; integers in the array `in' and then tranform them.
       (if (= j 63)
-          (let ((in (make-vector 16 (cons 0 0)))
-                (k 0)
-                (kk 0))
-            (while (< k 16)
-              (aset in k (md5-pack md5-input kk))
-              (setq k (+ k 1) kk (+ kk 4)))
-            (md5-transform in))))))
+         (let ((in (make-vector 16 (cons 0 0)))
+               (k 0)
+               (kk 0))
+           (while (< k 16)
+             (aset in k (md5-pack md5-input kk))
+             (setq k (+ k 1) kk (+ kk 4)))
+           (md5-transform in))))))
 
 (defun md5-pack (array i)
   "Pack the four bytes at ARRAY reference I to I+3 into a 32-bit integer."
   (cons (+ (lsh (aref array (+ i 3)) 8) (aref array (+ i 2)))
-        (+ (lsh (aref array (+ i 1)) 8) (aref array (+ i 0)))))
+       (+ (lsh (aref array (+ i 1)) 8) (aref array (+ i 0)))))
 
 (defun md5-byte (array n b)
   "Unpack byte B (0 to 3) from Nth member of ARRAY of 32-bit integers."
   (let ((e (aref array n)))
     (cond ((eq b 0) (logand 255 (cdr e)))
-          ((eq b 1) (lsh (cdr e) -8))
-          ((eq b 2) (logand 255 (car e)))
-          ((eq b 3) (lsh (car e) -8)))))
+         ((eq b 1) (lsh (cdr e) -8))
+         ((eq b 2) (logand 255 (car e)))
+         ((eq b 3) (lsh (car e) -8)))))
 
 (defun md5-final ()
   (let ((in (make-vector 16 (cons 0 0)))
-        (j 0)
-        (digest (make-vector 16 0))
-        (padding))
+       (j 0)
+       (digest (make-vector 16 0))
+       (padding))
 
     ;; Save the number of bits in the message
     (aset in 14 (cons (aref md5-bits 1) (aref md5-bits 0)))
@@ -268,18 +268,18 @@ Returns a vector of 16 bytes containing the message digest."
     ;; Append length in bits and transform
     (let ((k 0) (kk 0))
       (while (< k 14)
-        (aset in k (md5-pack md5-input kk))
-        (setq k (+ k 1) kk (+ kk 4))))
+       (aset in k (md5-pack md5-input kk))
+       (setq k (+ k 1) kk (+ kk 4))))
     (md5-transform in)
 
     ;; Store the results in the digest
     (let ((k 0) (kk 0))
       (while (< k 4)
-        (aset digest (+ kk 0) (md5-byte md5-buffer k 0))
-        (aset digest (+ kk 1) (md5-byte md5-buffer k 1))
-        (aset digest (+ kk 2) (md5-byte md5-buffer k 2))
-        (aset digest (+ kk 3) (md5-byte md5-buffer k 3))
-        (setq k (+ k 1) kk (+ kk 4))))
+       (aset digest (+ kk 0) (md5-byte md5-buffer k 0))
+       (aset digest (+ kk 1) (md5-byte md5-buffer k 1))
+       (aset digest (+ kk 2) (md5-byte md5-buffer k 2))
+       (aset digest (+ kk 3) (md5-byte md5-buffer k 3))
+       (setq k (+ k 1) kk (+ kk 4))))
 
     ;; Return digest
     digest))
@@ -291,9 +291,9 @@ Returns a vector of 16 bytes containing the message digest."
 (defun md5-transform (in)
   "Basic MD5 step. Transform md5-buffer based on array IN."
   (let ((a (aref md5-buffer 0))
-        (b (aref md5-buffer 1))
-        (c (aref md5-buffer 2))
-        (d (aref md5-buffer 3)))
+       (b (aref md5-buffer 1))
+       (c (aref md5-buffer 2))
+       (d (aref md5-buffer 3)))
     (setq
      a (md5-FF a b c d (aref in  0)  7 '(55146 . 42104))
      d (md5-FF d a b c (aref in  1) 12 '(59591 . 46934))
@@ -360,21 +360,25 @@ Returns a vector of 16 bytes containing the message digest."
      c (md5-II c d a b (aref in  2) 15 '(10967 . 53947))
      b (md5-II b c d a (aref in  9) 21 '(60294 . 54161)))
 
-     (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a))
-     (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b))
-     (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c))
-     (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d))))
+    (aset md5-buffer 0 (md5-add (aref md5-buffer 0) a))
+    (aset md5-buffer 1 (md5-add (aref md5-buffer 1) b))
+    (aset md5-buffer 2 (md5-add (aref md5-buffer 2) c))
+    (aset md5-buffer 3 (md5-add (aref md5-buffer 3) d))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Here begins the merger with the XEmacs API and the md5.el from the URL
 ;;; package.  Courtesy wmperry@spry.com
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun md5 (object &optional start end)
+(defun md5 (object &optional start end coding noerror)
   "Return the MD5 (a secure message digest algorithm) of an object.
 OBJECT is either a string or a buffer.
 Optional arguments START and END denote buffer positions for computing the
-hash of a portion of OBJECT."
- (let ((buffer nil))
+hash of a portion of OBJECT.
+
+The optional CODING and NOERROR arguments are ignored.  They are no
+more than placeholders to ensure the compatibility with XEmacsen with
+file-coding or Mule support."
+  (let ((buffer nil))
     (unwind-protect
        (save-excursion
          (setq buffer (generate-new-buffer " *md5-work*"))
@@ -406,4 +410,4 @@ hash of a portion of OBJECT."
 
 (provide 'md5)
 
-;;; md5.el ends here ----------------------------------------------------------
+;;; md5.el ends here
index 3269031..6784330 100644 (file)
@@ -1,8 +1,15 @@
 ;;; message.el --- composing mail and news messages
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
-
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: mail, news
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
+;;     Keiichi Suzuki   <kei-suzu@mail.wbs.ne.jp>
+;;     Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;;     Katsumi Yamaoka  <yamaoka@jpl.org>
+;;     Kiyokazu SUTO    <suto@merry.xmath.ous.ac.jp>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
-
+(eval-when-compile
+  (require 'cl)
+  (require 'smtp)
+  (defvar gnus-message-group-art)
+  (defvar gnus-list-identifiers)) ; gnus-sum is required where necessary
+(eval-and-compile
+  (if (boundp 'MULE)
+      (progn
+       (require 'base64)
+       (require 'canlock-om))
+    (require 'canlock)))
 (require 'mailheader)
 (require 'nnheader)
-(require 'timezone)
-(require 'easymenu)
-(require 'custom)
-(if (string-match "XEmacs\\|Lucid" emacs-version)
+;; This is apparently necessary even though things are autoloaded.
+;; Because we dynamically bind mail-abbrev-mode-regexp, we'd better
+;; require mailabbrev here.
+(if (featurep 'xemacs)
     (require 'mail-abbrevs)
   (require 'mailabbrev))
+(require 'mime-edit)
+(eval-when-compile (require 'static))
+
+;; Avoid byte-compile warnings.
+(eval-when-compile
+  (require 'mail-parse)
+  (require 'mml))
+
+(require 'rfc822)
+(eval-and-compile
+  (autoload 'customize-save-variable "cus-edit") ;; for Mule 2.
+  (autoload 'sha1 "sha1-el")
+  (autoload 'gnus-find-method-for-group "gnus")
+  (autoload 'nnvirtual-find-group-art "nnvirtual")
+  (autoload 'gnus-group-decoded-name "gnus-group"))
 
 (defgroup message '((user-mail-address custom-variable)
                    (user-full-name custom-variable))
   :group 'message
   :group 'faces)
 
+(defgroup message-frames nil
+  "Message frames"
+  :group 'message)
+
 (defcustom message-directory "~/Mail/"
   "*Directory from which all other mail file variables are derived."
   :group 'message-various
 (defcustom message-send-rename-function nil
   "Function called to rename the buffer after sending it."
   :group 'message-buffers
-  :type 'function)
+  :type '(choice function (const nil)))
 
 (defcustom message-fcc-handler-function 'message-output
   "*A function called to save outgoing articles.
@@ -122,6 +157,21 @@ mailbox format."
                (function :tag "Other"))
   :group 'message-sending)
 
+(defcustom message-encode-function 'message-maybe-encode
+  "*A function called to encode messages."
+  :group 'message-sending
+  :type 'function)
+
+(defcustom message-8bit-encoding-list '(8bit binary)
+  "*8bit encoding type in Content-Transfer-Encoding field."
+  :group 'message-sending
+  :type '(repeat (symbol :tag "Type")))
+
+(defcustom message-fcc-externalize-attachments nil
+  "If non-nil, attachments are included as external parts in Fcc copies."
+  :type 'boolean
+  :group 'message-sending)
+
 (defcustom message-courtesy-message
   "The following message is a courtesy copy of an article\nthat has been posted to %s as well.\n\n"
   "*This is inserted at the start of a mailed copy of a posted message.
@@ -129,18 +179,148 @@ If the string contains the format spec \"%s\", the Newsgroups
 the article has been posted to will be inserted there.
 If this variable is nil, no such courtesy message will be added."
   :group 'message-sending
-  :type 'string)
+  :type '(radio (string :format "%t: %v\n" :size 0) (const nil)))
 
-(defcustom message-ignored-bounced-headers "^\\(Received\\|Return-Path\\):"
+(defcustom message-ignored-bounced-headers
+  "^\\(Received\\|Return-Path\\|Delivered-To\\):"
   "*Regexp that matches headers to be removed in resent bounced mail."
   :group 'message-interface
   :type 'regexp)
 
+(defcustom message-bounce-setup-function 'message-bounce-setup-for-mime-edit
+  "Function to setup a re-sending bounced message."
+  :group 'message-sending
+  :type 'function)
+
+;;; Start of variables adopted from `message-utils.el'.
+
+(defcustom message-subject-trailing-was-query 'ask
+  "*What to do with trailing \"(was: <old subject>)\" in subject lines.
+If nil, leave the subject unchanged.  If it is the symbol `ask', query
+the user what do do.  In this case, the subject is matched against
+`message-subject-trailing-was-ask-regexp'.  If
+`message-subject-trailing-was-query' is t, always strip the trailing
+old subject.  In this case, `message-subject-trailing-was-regexp' is
+used."
+  :type '(choice (const :tag "never" nil)
+                (const :tag "always strip" t)
+                 (const ask))
+  :link '(custom-manual "(message)Message Headers")
+  :group 'message-various)
+
+(defcustom message-subject-trailing-was-ask-regexp
+  "[ \t]*\\([[(]+[Ww][Aa][Ss][ \t]*.*[\])]+\\)"
+  "*Regexp matching \"(was: <old subject>)\" in the subject line.
+
+The function `message-strip-subject-trailing-was' uses this regexp if
+`message-subject-trailing-was-query' is set to the symbol `ask'.  If
+the variable is t instead of `ask', use
+`message-subject-trailing-was-regexp' instead.
+
+It is okay to create some false positives here, as the user is asked."
+  :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
+  :type 'regexp)
+
+(defcustom message-subject-trailing-was-regexp
+  "[ \t]*\\((*[Ww][Aa][Ss]:[ \t]*.*)\\)"
+  "*Regexp matching \"(was: <old subject>)\" in the subject line.
+
+If `message-subject-trailing-was-query' is set to t, the subject is
+matched against `message-subject-trailing-was-regexp' in
+`message-strip-subject-trailing-was'.  You should use a regexp creating very
+few false positives here."
+  :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
+  :type 'regexp)
+
+;; Fixme: Why are all these things autoloaded?
+
+;;; marking inserted text
+
+;;;###autoload
+(defcustom message-mark-insert-begin
+  "--8<---------------cut here---------------start------------->8---\n"
+  "How to mark the beginning of some inserted text."
+  :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-mark-insert-end
+  "--8<---------------cut here---------------end--------------->8---\n"
+  "How to mark the end of some inserted text."
+  :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-archive-header
+  "X-No-Archive: Yes\n"
+  "Header to insert when you don't want your article to be archived.
+Archives \(such as groups.google.com\) respect this header."
+  :type 'string
+  :link '(custom-manual "(message)Header Commands")
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-archive-note
+  "X-No-Archive: Yes - save http://groups.google.com/"
+  "Note to insert why you wouldn't want this posting archived.
+If nil, don't insert any text in the body."
+  :type '(radio (string :format "%t: %v\n" :size 0)
+               (const nil))
+  :link '(custom-manual "(message)Header Commands")
+  :group 'message-various)
+
+;;; Crossposts and Followups
+;; inspired by JoH-followup-to by Jochem Huhman <joh  at gmx.de>
+;; new suggestions by R. Weikusat <rw at another.de>
+
+(defvar message-cross-post-old-target nil
+  "Old target for cross-posts or follow-ups.")
+(make-variable-buffer-local 'message-cross-post-old-target)
+
+;;;###autoload
+(defcustom message-cross-post-default t
+  "When non-nil `message-cross-post-followup-to' will perform a crosspost.
+If nil, `message-cross-post-followup-to' will only do a followup.  Note that
+you can explicitly override this setting by calling
+`message-cross-post-followup-to' with a prefix."
+  :type 'boolean
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-cross-post-note
+  "Crosspost & Followup-To: "
+  "Note to insert before signature to notify of xpost and follow-up."
+  :type 'string
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-followup-to-note
+  "Followup-To: "
+  "Note to insert before signature to notify of follow-up only."
+  :type 'string
+  :group 'message-various)
+
+;;;###autoload
+(defcustom message-cross-post-note-function
+  'message-cross-post-insert-note
+  "Function to use to insert note about Crosspost or Followup-To.
+The function will be called with four arguments.  The function should not only
+insert a note, but also ensure old notes are deleted.  See the documentation
+for `message-cross-post-insert-note'."
+  :type 'function
+  :group 'message-various)
+
+;;; End of variables adopted from `message-utils.el'.
+
 ;;;###autoload
 (defcustom message-from-style 'default
   "*Specifies how \"From\" headers look.
 
-If `nil', they contain just the return address like:
+If nil, they contain just the return address like:
        king@grassland.com
 If `parens', they look like:
        king@grassland.com (Elvis Parsley)
@@ -155,102 +335,223 @@ Otherwise, most addresses look like `angles', but they look like
                 (const default))
   :group 'message-headers)
 
-(defcustom message-syntax-checks nil
-  ; Guess this one shouldn't be easy to customize...
+(defcustom message-insert-canlock t
+  "Whether to insert a Cancel-Lock header in news postings."
+  :version "21.3"
+  :group 'message-headers
+  :type 'boolean)
+
+(defcustom message-syntax-checks
+  (if message-insert-canlock '((sender . disabled)) nil)
+  ;; Guess this one shouldn't be easy to customize...
   "*Controls what syntax checks should not be performed on outgoing posts.
 To disable checking of long signatures, for instance, add
  `(signature . disabled)' to this list.
 
 Don't touch this variable unless you really know what you're doing.
 
-Checks include subject-cmsg multiple-headers sendsys message-id from
-long-lines control-chars size new-text redirected-followup signature
-approved sender empty empty-headers message-id from subject
-shorten-followup-to existing-newsgroups buffer-file-name unchanged."
-  :group 'message-news)
+Checks include `subject-cmsg', `multiple-headers', `sendsys',
+`message-id', `from', `long-lines', `control-chars', `size',
+`new-text', `quoting-style', `redirected-followup', `signature',
+`approved', `sender', `empty', `empty-headers', `message-id', `from',
+`subject', `shorten-followup-to', `existing-newsgroups',
+`buffer-file-name', `unchanged', `newsgroups', `reply-to',
+`continuation-headers', `long-header-lines', `invisible-text' and
+`illegible-text'."
+  :group 'message-news
+  :type '(repeat sexp))                        ; Fixme: improve this
+
+(defcustom message-required-headers '((optional . References)
+                                     From)
+  "*Headers to be generated or prompted for when sending a message.
+Also see `message-required-news-headers' and
+`message-required-mail-headers'."
+  :group 'message-news
+  :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat sexp))
+
+(defcustom message-draft-headers '(References From)
+  "*Headers to be generated when saving a draft message."
+  :group 'message-news
+  :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat sexp))
 
 (defcustom message-required-news-headers
   '(From Newsgroups Subject Date Message-ID
-        (optional . Organization) Lines
-        (optional . X-Newsreader))
+        (optional . Organization)
+        (optional . User-Agent))
   "*Headers to be generated or prompted for when posting an article.
 RFC977 and RFC1036 require From, Date, Newsgroups, Subject,
 Message-ID.  Organization, Lines, In-Reply-To, Expires, and
-X-Newsreader are optional.  If don't you want message to insert some
+User-Agent are optional.  If don't you want message to insert some
 header, remove it from this list."
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-required-mail-headers
-  '(From Subject Date (optional . In-Reply-To) Message-ID Lines
-        (optional . X-Mailer))
+  '(From Subject Date (optional . In-Reply-To) Message-ID
+        (optional . User-Agent))
   "*Headers to be generated or prompted for when mailing a message.
-RFC822 required that From, Date, To, Subject and Message-ID be
-included.  Organization, Lines and X-Mailer are optional."
+It is recommended that From, Date, To, Subject and Message-ID be
+included.  Organization and User-Agent are optional."
   :group 'message-mail
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type '(repeat sexp))
 
 (defcustom message-deletable-headers '(Message-ID Date Lines)
   "Headers to be deleted if they already exist and were generated by message previously."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type 'sexp)
 
 (defcustom message-ignored-news-headers
-  "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:"
+  "^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:"
   "*Regexp of headers to be removed unconditionally before posting."
   :group 'message-news
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type 'regexp)
 
-(defcustom message-ignored-mail-headers "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:"
+(defcustom message-ignored-mail-headers
+  "^[GF]cc:\\|^Resent-Fcc:\\|^Xref:\\|^X-Draft-From:\\|^X-Gnus-Agent-Meta-Information:"
   "*Regexp of headers to be removed unconditionally before mailing."
   :group 'message-mail
   :group 'message-headers
+  :link '(custom-manual "(message)Mail Headers")
   :type 'regexp)
 
-(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:"
+(defcustom message-ignored-supersedes-headers "^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|^X-Trace:\\|^X-Complaints-To:\\|Return-Path:\\|^Supersedes:\\|^NNTP-Posting-Date:\\|^X-Trace:\\|^X-Complaints-To:\\|^Cancel-Lock:\\|^Cancel-Key:\\|^X-Hashcash:\\|^X-Payment:"
   "*Header lines matching this regexp will be deleted before posting.
 It's best to delete old Path and Date headers before posting to avoid
 any confusion."
   :group 'message-interface
+  :link '(custom-manual "(message)Superseding")
   :type 'regexp)
 
+(defcustom message-supersede-setup-function
+  'message-supersede-setup-for-mime-edit
+  "Function to setup a supersede message."
+  :group 'message-sending
+  :type 'function)
+
+(defcustom message-subject-re-regexp
+  "^[ \t]*\\([Rr][Ee]\\(\\[[0-9]*\\]\\)*:[ \t]*\\)*[ \t]*"
+  "*Regexp matching \"Re: \" in the subject line."
+  :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
+  :type 'regexp)
+
+;;; Some sender agents encode the whole subject including leading "Re: ".
+;;; And if followup agent does not decode it for some reason (e.g. unknown
+;;; charset) and just add a new "Re: " in front of the encoded-word, the
+;;; result will contain multiple "Re: "'s.
+(defcustom message-subject-encoded-re-regexp
+  (concat
+   "^[ \t]*"
+   (regexp-quote "=?")
+   "[-!#$%&'*+0-9A-Z^_`a-z{|}~]+" ; charset
+   (regexp-quote "?")
+   "\\("
+   "[Bb]" (regexp-quote "?") ; B encoding
+   "\\(\\(CQk\\|CSA\\|IAk\\|ICA\\)[Jg]\\)*" ; \([ \t][ \t][ \t]\)*
+   "\\("
+   "[Uc][km]U6" ; [Rr][Ee]:
+   "\\|"
+   "\\(C[VX]\\|I[FH]\\)J[Fl]O[g-v]" ; [ \t][Rr][Ee]:
+   "\\|"
+   "\\(CQl\\|CSB\\|IAl\\|ICB\\)[Sy][RZ]T[o-r]" ; [ \t][ \t][Rr][Ee]:
+   "\\)"
+   "\\|"
+   "[Qb]" (regexp-quote "?") ; Q encoding
+   "\\(_\\|=09\\|=20\\)*"
+   "\\([Rr]\\|=[57]2\\)\\([Ee]\\|=[46]5\\)\\(:\\|=3[Aa]\\)"
+   "\\)"
+   )
+  "*Regexp matching \"Re: \" in the subject line.
+Unlike `message-subject-re-regexp', this regexp matches \"Re: \" within
+an encoded-word."
+  :group 'message-various
+  :link '(custom-manual "(message)Message Headers")
+  :type 'regexp)
+
+(defcustom message-use-subject-re t
+  "*If t, remove any (buggy) \"Re: \"'s from the subject of the precursor
+and add a new \"Re: \".  If it is nil, use the subject \"as-is\".  If it
+is the symbol `guess', try to detect \"Re: \" within an encoded-word."
+  :group 'message-various
+  :type '(choice (const :tag "off" nil)
+                (const :tag "on" t)
+                (const guess)))
+
 ;;;###autoload
 (defcustom message-signature-separator "^-- *$"
   "Regexp matching the signature separator."
   :type 'regexp
+  :link '(custom-manual "(message)Various Message Variables")
   :group 'message-various)
 
-(defcustom message-elide-elipsis "\n[...]\n\n"
+(defcustom message-signature-separator-for-insertion "-- \n"
+  "*Signature separator. This value will be inserted as signature separator
+when composing message. Default value is \"-- \\n\". Notice: Changing this
+value may go against RFC-1036 and draft-ietf-usefor-article-05.txt. "
+  :type 'string
+  :group 'message-insertion)
+
+(defcustom message-elide-ellipsis "\n[...]\n\n"
   "*The string which is inserted for elided text."
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-various)
 
-(defcustom message-interactive nil
+(defcustom message-interactive t
   "Non-nil means when sending a message wait for and display errors.
 nil means let mailer mail back a message to report errors."
   :group 'message-sending
   :group 'message-mail
+  :link '(custom-manual "(message)Sending Variables")
   :type 'boolean)
 
-(defcustom message-generate-new-buffers t
-  "*Non-nil means that a new message buffer will be created whenever `mail-setup' is called.
+(defcustom message-generate-new-buffers 'unique
+  "*Non-nil means create a new message buffer whenever `message-setup' is called.
 If this is a function, call that function with three parameters:  The type,
 the to address and the group name.  (Any of these may be nil.)  The function
 should return the new buffer name."
   :group 'message-buffers
+  :link '(custom-manual "(message)Message Buffers")
   :type '(choice (const :tag "off" nil)
-                (const :tag "on" t)
+                (const :tag "unique" unique)
+                (const :tag "unsent" unsent)
                 (function fun)))
 
 (defcustom message-kill-buffer-on-exit nil
   "*Non-nil means that the message buffer will be killed after sending a message."
   :group 'message-buffers
+  :link '(custom-manual "(message)Message Buffers")
+  :type 'boolean)
+
+(defcustom message-kill-buffer-query-function 'yes-or-no-p
+  "*Function used to prompt user whether to kill the message buffer.  If
+it is t, the buffer will be killed unconditionally."
+  :type '(radio (function-item yes-or-no-p)
+               (function-item y-or-n-p)
+               (function-item nnheader-Y-or-n-p)
+               (function :tag "Other" t))
+  :group 'message-buffers)
+
+(defcustom message-kill-buffer-and-remove-file t
+  "*Non-nil means that the associated file will be removed before
+removing the message buffer.  However, it is treated as nil when the
+command `message-mimic-kill-buffer' is used."
+  :group 'message-buffers
   :type 'boolean)
 
-(defvar gnus-local-organization)
+(eval-when-compile
+  (defvar gnus-local-organization))
 (defcustom message-user-organization
   (or (and (boundp 'gnus-local-organization)
           (stringp gnus-local-organization)
@@ -267,51 +568,128 @@ If t, use `message-user-organization-file'."
 (defcustom message-user-organization-file "/usr/lib/news/organization"
   "*Local news organization file."
   :type 'file
+  :link '(custom-manual "(message)News Headers")
   :group 'message-headers)
 
-(defcustom message-autosave-directory
-  (nnheader-concat message-directory "drafts/")
-  "*Directory where Message autosaves buffers.
-If nil, Message won't autosave."
-  :group 'message-buffers
-  :type 'directory)
-
 (defcustom message-forward-start-separator
-  "------- Start of forwarded message -------\n"
+  (concat (mime-make-tag "message" "rfc822") "\n")
   "*Delimiter inserted before forwarded messages."
   :group 'message-forwarding
   :type 'string)
 
 (defcustom message-forward-end-separator
-  "------- End of forwarded message -------\n"
+  (concat (mime-make-tag "text" "plain") "\n")
   "*Delimiter inserted after forwarded messages."
   :group 'message-forwarding
   :type 'string)
 
-(defcustom message-signature-before-forwarded-message t
-  "*If non-nil, put the signature before any included forwarded message."
-  :group 'message-forwarding
-  :type 'boolean)
-
 (defcustom message-included-forward-headers
-  "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:\\|^Content-Transfer-Encoding:\\|^Content-Type:\\|^Mime-Version:"
+  "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^\\(Mail-\\)?Followup-To:\\|^\\(Mail-\\)?Reply-To:\\|^Mail-Copies-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-\\|^Message-ID:\\|^References:\\|^Content-\\|^MIME-Version:"
   "*Regexp matching headers to be included in forwarded messages."
   :group 'message-forwarding
   :type 'regexp)
 
-(defcustom message-ignored-resent-headers "^Return-receipt"
+(defcustom message-make-forward-subject-function
+  #'message-forward-subject-name-subject
+  "*List of functions called to generate subject headers for forwarded messages.
+The subject generated by the previous function is passed into each
+successive function.
+
+The provided functions are:
+
+* `message-forward-subject-author-subject' Source of article (author or
+      newsgroup), in brackets followed by the subject
+* `message-forward-subject-name-subject' Source of article (name of author
+      or newsgroup), in brackets followed by the subject
+* `message-forward-subject-fwd' Subject of article with 'Fwd:' prepended
+      to it."
+  :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
+  :type '(radio (function-item message-forward-subject-author-subject)
+               (function-item message-forward-subject-fwd)
+               (function-item message-forward-subject-name-subject)
+               (repeat :tag "List of functions" function)))
+
+(defcustom message-forward-as-mime t
+  "*Non-nil means forward messages as an inline/rfc822 MIME section.
+Otherwise, directly inline the old message in the forwarded message."
+  :version "21.1"
+  :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
+  :type 'boolean)
+
+(defcustom message-forward-show-mml 'best
+  "*Non-nil means show forwarded messages as MML (decoded from MIME).
+Otherwise, forwarded messages are unchanged.
+Can also be the symbol `best' to indicate that MML should be
+used, except when it is a bad idea to use MML.  One example where
+it is a bad idea is when forwarding a signed or encrypted
+message, because converting MIME to MML would invalidate the
+digital signature."
+  :version "21.1"
+  :group 'message-forwarding
+  :type '(choice (const :tag "use MML" t)
+                (const :tag "don't use MML " nil)
+                (const :tag "use MML when appropriate" best)))
+
+(defcustom message-forward-before-signature t
+  "*Non-nil means put forwarded message before signature, else after."
+  :group 'message-forwarding
+  :type 'boolean)
+
+(defcustom message-wash-forwarded-subjects nil
+  "*Non-nil means try to remove as much cruft as possible from the subject.
+Done before generating the new subject of a forward."
+  :group 'message-forwarding
+  :link '(custom-manual "(message)Forwarding")
+  :type 'boolean)
+
+(defcustom message-ignored-resent-headers "^Return-receipt\\|^X-Gnus\\|^Gnus-Warning:\\|^>?From "
   "*All headers that match this regexp will be deleted when resending a message."
   :group 'message-interface
+  :link '(custom-manual "(message)Resending")
   :type 'regexp)
 
+(defcustom message-forward-ignored-headers "^Content-Transfer-Encoding:\\|^X-Gnus"
+  "*All headers that match this regexp will be deleted when forwarding a message."
+  :version "21.1"
+  :group 'message-forwarding
+  :type '(choice (const :tag "None" nil)
+                regexp))
+
 (defcustom message-ignored-cited-headers "."
   "*Delete these headers from the messages you yank."
   :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
   :type 'regexp)
 
-(defcustom message-cancel-message "I am canceling my own article."
+(defcustom message-cite-prefix-regexp
+  (if (string-match "[[:digit:]]" "1") ;; support POSIX?
+      "\\([ \t]*[-_.[:word:]]+>+\\|[ \t]*[]>|}+]\\)+"
+    ;; ?-, ?_ or ?. MUST NOT be in syntax entry w.
+    (let ((old-table (syntax-table))
+         non-word-constituents)
+      (set-syntax-table text-mode-syntax-table)
+      (setq non-word-constituents
+           (concat
+            (if (string-match "\\w" "-")  "" "-")
+            (if (string-match "\\w" "_")  "" "_")
+            (if (string-match "\\w" ".")  "" ".")))
+      (set-syntax-table old-table)
+      (if (equal non-word-constituents "")
+         "\\([ \t]*\\(\\w\\)+>+\\|[ \t]*[]>|}+]\\)+"
+       (concat "\\([ \t]*\\(\\w\\|["
+               non-word-constituents
+               "]\\)+>+\\|[ \t]*[]>|}+]\\)+"))))
+  "*Regexp matching the longest possible citation prefix on a line."
+  :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
+  :type 'regexp)
+
+(defcustom message-cancel-message "I am canceling my own article.\n"
   "Message to be inserted in the cancel message."
   :group 'message-interface
+  :link '(custom-manual "(message)Canceling News")
   :type 'string)
 
 ;; Useful to set in site-init.el
@@ -321,45 +699,57 @@ If nil, Message won't autosave."
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'.
 
-Legal values include `message-send-mail-with-sendmail' (the default),
-`message-send-mail-with-mh', `message-send-mail-with-qmail' and
-`smtpmail-send-it'."
+Valid values include `message-send-mail-with-sendmail' (the default),
+`message-send-mail-with-mh', `message-send-mail-with-qmail',
+`message-send-mail-with-smtp', `message-smtpmail-send-it',
+`smtpmail-send-it' and `feedmail-send-it'.
+
+See also `send-mail-function'."
   :type '(radio (function-item message-send-mail-with-sendmail)
                (function-item message-send-mail-with-mh)
                (function-item message-send-mail-with-qmail)
+               (function-item message-send-mail-with-smtp)
+               (function-item message-smtpmail-send-it)
                (function-item smtpmail-send-it)
+               (function-item feedmail-send-it)
                (function :tag "Other"))
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :group 'message-mail)
 
-(defcustom message-send-news-function 'message-send-news
+;; 1997-09-29 by MORIOKA Tomohiko
+(defcustom message-send-news-function 'message-send-news-with-gnus
   "Function to call to send the current buffer as news.
 The headers should be delimited by a line whose contents match the
 variable `mail-header-separator'."
   :group 'message-sending
   :group 'message-news
+  :link '(custom-manual "(message)News Variables")
   :type 'function)
 
 (defcustom message-reply-to-function nil
-  "Function that should return a list of headers.
+  "If non-nil, function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
-  :type 'function)
+  :link '(custom-manual "(message)Reply")
+  :type '(choice function (const nil)))
 
 (defcustom message-wide-reply-to-function nil
-  "Function that should return a list of headers.
+  "If non-nil, function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
-  :type 'function)
+  :link '(custom-manual "(message)Wide Reply")
+  :type '(choice function (const nil)))
 
 (defcustom message-followup-to-function nil
-  "Function that should return a list of headers.
+  "If non-nil, function that should return a list of headers.
 This function should pick out addresses from the To, Cc, and From headers
 and respond with new To and Cc headers."
   :group 'message-interface
-  :type 'function)
+  :link '(custom-manual "(message)Followup")
+  :type '(choice function (const nil)))
 
 (defcustom message-use-followup-to 'ask
   "*Specifies what to do with Followup-To header.
@@ -368,58 +758,192 @@ query before using the \"poster\" value.  If it is the symbol `ask',
 always query the user whether to use the value.  If it is the symbol
 `use', always use the value."
   :group 'message-interface
+  :link '(custom-manual "(message)Followup")
+  :type '(choice (const :tag "ignore" nil)
+                (const :tag "use & query" t)
+                (const :tag "maybe" t)
+                (const :tag "always" use)
+                (const :tag "ask" ask)))
+
+(defcustom message-use-mail-copies-to 'ask
+  "*Specifies what to do with Mail-Copies-To header.
+If nil, always ignore the header.  If it is t, use its value, but
+query before using the value other than \"always\" or \"never\".
+If it is the symbol `ask', always query the user whether to use
+the value.  If it is the symbol `use', always use the value."
+  :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(choice (const :tag "ignore" nil)
+                (const :tag "maybe" t)
+                (const :tag "always" use)
+                (const :tag "ask" ask)))
+
+;;; XXX: 'ask and 'use are not implemented yet.
+(defcustom message-use-mail-reply-to 'ask
+  "*Specifies what to do with Mail-Reply-To/Reply-To header.
+If nil, always ignore the header.  If it is t or the symbol `use', use
+its value.  If it is the symbol `ask', always query the user whether to
+use the value.  Note that if \"Reply-To\" is marked as \"broken\", its value
+is never used."
+  :group 'message-interface
+  :type '(choice (const :tag "ignore" nil)
+                (const :tag "maybe" t)
+                (const :tag "always" use)
+                (const :tag "ask" ask)))
+
+(defcustom message-use-mail-followup-to 'use
+  "*Specifies what to do with Mail-Followup-To header.
+If nil, always ignore the header.  If it is the symbol `ask', always
+query the user whether to use the value.  If it is t or the symbol
+`use', always use the value."
+  :group 'message-interface
   :type '(choice (const :tag "ignore" nil)
-                (const use)
+                (const :tag "maybe" t)
+                (const :tag "always" use)
+                (const :tag "ask" ask)))
+
+(defcustom message-subscribed-address-functions nil
+  "*Specifies functions for determining list subscription.
+If nil, do not attempt to determine list subscription with functions.
+If non-nil, this variable contains a list of functions which return
+regular expressions to match lists.  These functions can be used in
+conjunction with `message-subscribed-regexps' and
+`message-subscribed-addresses'."
+  :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(repeat sexp))
+
+(defcustom message-subscribed-address-file nil
+  "*A file containing addresses the user is subscribed to.
+If nil, do not look at any files to determine list subscriptions.  If
+non-nil, each line of this file should be a mailing list address."
+  :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(radio (file :format "%t: %v\n" :size 0)
+               (const nil)))
+
+(defcustom message-subscribed-addresses nil
+  "*Specifies a list of addresses the user is subscribed to.
+If nil, do not use any predefined list subscriptions.  This list of
+addresses can be used in conjunction with
+`message-subscribed-address-functions' and `message-subscribed-regexps'."
+  :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(repeat string))
+
+(defcustom message-subscribed-regexps nil
+  "*Specifies a list of addresses the user is subscribed to.
+If nil, do not use any predefined list subscriptions.  This list of
+regular expressions can be used in conjunction with
+`message-subscribed-address-functions' and `message-subscribed-addresses'."
+  :group 'message-interface
+  :link '(custom-manual "(message)Mailing Lists")
+  :type '(repeat regexp))
+
+(defcustom message-allow-no-recipients 'ask
+  "Specifies what to do when there are no recipients other than Gcc/Fcc.
+If it is the symbol `always', the posting is allowed.  If it is the
+symbol `never', the posting is not allowed.  If it is the symbol
+`ask', you are prompted."
+  :group 'message-interface
+  :link '(custom-manual "(message)Message Headers")
+  :type '(choice (const always)
+                (const never)
                 (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 don't add \"-f username\" to the sendmail command line.
+Doing so would be even more evil than leaving it out."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'boolean)
 
+(defcustom message-sendmail-envelope-from nil
+  "*Envelope-from when sending mail with sendmail.
+If this is nil, use `user-mail-address'.  If it is the symbol
+`header', use the From: header of the message."
+  :type '(choice (string :tag "From name")
+                (const :tag "Use From: header from message" header)
+                (const :tag "Use `user-mail-address'" nil))
+  :link '(custom-manual "(message)Mail Variables")
+  :group 'message-sending)
+
 ;; qmail-related stuff
 (defcustom message-qmail-inject-program "/var/qmail/bin/qmail-inject"
   "Location of the qmail-inject program."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'file)
 
 (defcustom message-qmail-inject-args nil
   "Arguments passed to qmail-inject programs.
-This should be a list of strings, one string for each argument.
+This should be a list of strings, one string for each argument.  It
+may also be a function.
 
 For e.g., if you wish to set the envelope sender address so that bounces
 go to the right place or to deal with listserv's usage of that address, you
 might set this variable to '(\"-f\" \"you@some.where\")."
   :group 'message-sending
-  :type '(repeat string))
-
-(defvar gnus-post-method)
-(defvar gnus-select-method)
+  :link '(custom-manual "(message)Mail Variables")
+  :type '(choice (function)
+                (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.")
+
+(eval-when-compile
+  (defvar gnus-post-method)
+  (defvar gnus-select-method))
 (defcustom message-post-method
   (cond ((and (boundp 'gnus-post-method)
+             (listp gnus-post-method)
              gnus-post-method)
         gnus-post-method)
        ((boundp 'gnus-select-method)
         gnus-select-method)
        (t '(nnspool "")))
-  "*Method used to post news."
+  "*Method used to post news.
+Note that when posting from inside Gnus, for instance, this
+variable isn't used."
   :group 'message-news
   :group 'message-sending
   ;; This should be the `gnus-select-method' widget, but that might
   ;; create a dependence to `gnus.el'.
   :type 'sexp)
 
-(defcustom message-generate-headers-first nil
-  "*If non-nil, generate all possible headers before composing."
+;; FIXME: This should be a temporary workaround until someone implements a
+;; proper solution.  If a crash happens while replying, the auto-save file
+;; will *not* have a `References:' header if `message-generate-headers-first'
+;; is nil.  See: http://article.gmane.org/gmane.emacs.gnus.general/51138
+(defcustom message-generate-headers-first '(references)
+  "Which headers should be generated before starting to compose a message.
+If `t', generate all required headers.  This can also be a list of headers to
+generate.  The variables `message-required-news-headers' and
+`message-required-mail-headers' specify which headers to generate.
+
+Note that the variable `message-deletable-headers' specifies headers which
+are to be deleted and then re-generated before sending, so this variable
+will not have a visible effect for those headers."
   :group 'message-headers
-  :type 'boolean)
+  :link '(custom-manual "(message)Message Headers")
+  :type '(choice (const :tag "None" nil)
+                 (const :tag "References" '(references))
+                 (const :tag "All" t)
+                 (repeat (sexp :tag "Header"))))
 
-(defcustom message-setup-hook nil
+(defcustom message-setup-hook '(turn-on-mime-edit)
   "Normal hook, run each time a new outgoing message is initialized.
 The function `message-setup' runs this hook."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
+  :type 'hook)
+
+(defcustom message-cancel-hook nil
+  "Hook run when cancelling articles."
+  :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-signature-setup-hook nil
@@ -427,6 +951,19 @@ The function `message-setup' runs this hook."
 It is run after the headers have been inserted and before
 the signature is inserted."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
+  :type 'hook)
+
+(defcustom message-bounce-setup-hook nil
+  "Normal hook, run each time a re-sending bounced message is initialized.
+The function `message-bounce' runs this hook."
+  :group 'message-various
+  :type 'hook)
+
+(defcustom message-supersede-setup-hook nil
+  "Normal hook, run each time a supersede message is initialized.
+The function `message-supersede' runs this hook."
+  :group 'message-various
   :type 'hook)
 
 (defcustom message-mode-hook nil
@@ -434,7 +971,7 @@ the signature is inserted."
   :group 'message-various
   :type 'hook)
 
-(defcustom message-header-hook nil
+(defcustom message-header-hook '((lambda () (mime-encode-header-in-buffer t)))
   "Hook run in a message mode buffer narrowed to the headers."
   :group 'message-various
   :type 'hook)
@@ -442,40 +979,92 @@ the signature is inserted."
 (defcustom message-header-setup-hook nil
   "Hook called narrowed to the headers when setting up a message buffer."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
+(defcustom message-minibuffer-local-map
+  (let ((map (make-sparse-keymap 'message-minibuffer-local-map)))
+    (set-keymap-parent map minibuffer-local-map)
+    map)
+  "Keymap for `message-read-from-minibuffer'.")
+
 ;;;###autoload
 (defcustom message-citation-line-function 'message-insert-citation-line
-  "*Function called to insert the \"Whomever writes:\" line."
+  "*Function called to insert the \"Whomever writes:\" line.
+
+Note that Gnus provides a feature where the reader can click on
+`writes:' to hide the cited text.  If you change this line too much,
+people who read your message will have to change their Gnus
+configuration.  See the variable `gnus-cite-attribution-suffix'."
   :type 'function
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
 (defcustom message-yank-prefix "> "
   "*Prefix inserted on the lines of yanked messages.
-nil means use indentation."
+Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
+See also `message-yank-cited-prefix'."
+  :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
+  :group 'message-insertion)
+
+(defcustom message-yank-add-new-references t
+  "Non-nil means new IDs will be added to \"References\" field when an
+article is yanked by the command `message-yank-original' interactively.
+If it is a symbol `message-id-only', only an ID from \"Message-ID\" field
+is used, otherwise IDs extracted from \"References\", \"In-Reply-To\" and
+\"Message-ID\" fields are used."
+  :type '(radio (const :tag "Do not add anything" nil)
+               (const :tag "From Message-Id, References and In-Reply-To fields" t)
+               (const :tag "From only Message-Id field." message-id-only))
+  :group 'message-insertion)
+
+(defcustom message-list-references-add-position nil
+  "Integer value means position for adding to \"References\" field when
+an article is yanked by the command `message-yank-original' interactively."
+  :type '(radio (const :tag "Add to last" nil)
+               (integer :tag "Position from last ID"))
+  :group 'message-insertion)
+
+(defcustom message-yank-cited-prefix ">"
+  "*Prefix inserted on cited or empty lines of yanked messages.
+Fix `message-cite-prefix-regexp' if it is set to an abnormal value.
+See also `message-yank-prefix'."
   :type 'string
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 (defcustom message-indentation-spaces 3
   "*Number of spaces to insert at the beginning of each cited line.
 Used by `message-yank-original' via `message-yank-cite'."
   :group 'message-insertion
+  :link '(custom-manual "(message)Insertion Variables")
   :type 'integer)
 
 ;;;###autoload
-(defcustom message-cite-function
-  (if (and (boundp 'mail-citation-hook)
-          mail-citation-hook)
-      mail-citation-hook
-    'message-cite-original)
+(defcustom message-cite-function 'message-cite-original
   "*Function for citing an original message.
-Pre-defined functions include `message-cite-original' and
-`message-cite-original-without-signature'."
+Predefined functions include `message-cite-original' and
+`message-cite-original-without-signature'.
+Note that `message-cite-original' uses `mail-citation-hook' if that is non-nil."
   :type '(radio (function-item message-cite-original)
                (function-item message-cite-original-without-signature)
+               (function-item mu-cite-original)
                (function-item sc-cite-original)
                (function :tag "Other"))
+  :link '(custom-manual "(message)Insertion Variables")
+  :group 'message-insertion)
+
+;;;###autoload
+(defcustom message-suspend-font-lock-when-citing nil
+  "Non-nil means suspend font-lock'ing while citing an original message.
+Some lazy demand-driven fontification tools (or Emacs itself) have a
+bug that they often miss a buffer to be fontified.  It will mostly
+occur when Emacs prompts user for any inputs in the minibuffer.
+Setting this option to non-nil may help you to avoid unpleasant errors
+even if it is an add-hoc expedient."
+  :type 'boolean
   :group 'message-insertion)
 
 ;;;###autoload
@@ -485,10 +1074,9 @@ This can also be a list of functions.  Each function can find the
 citation between (point) and (mark t).  And each function should leave
 point and mark around the citation text as modified."
   :type 'function
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
-(defvar message-abbrevs-loaded nil)
-
 ;;;###autoload
 (defcustom message-signature t
   "*String to be inserted at the end of the message buffer.
@@ -496,19 +1084,31 @@ If t, the `message-signature-file' file will be inserted instead.
 If a function, the result from the function will be used instead.
 If a form, the result from the form will be used instead."
   :type 'sexp
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 ;;;###autoload
 (defcustom message-signature-file "~/.signature"
-  "*File containing the text inserted at end of message buffer."
-  :type 'file
+  "*Name of file containing the text inserted at end of message buffer.
+Ignored if the named file doesn't exist.
+If nil, don't insert a signature."
+  :type '(choice file (const :tags "None" nil))
+  :link '(custom-manual "(message)Insertion Variables")
+  :group 'message-insertion)
+
+;;;###autoload
+(defcustom message-signature-insert-empty-line t
+  "*If non-nil, insert an empty line before the signature separator."
+  :type 'boolean
+  :link '(custom-manual "(message)Insertion Variables")
   :group 'message-insertion)
 
 (defcustom message-distribution-function nil
   "*Function called to return a Distribution header."
   :group 'message-news
   :group 'message-headers
-  :type 'function)
+  :link '(custom-manual "(message)News Headers")
+  :type '(choice function (const nil)))
 
 (defcustom message-expires 14
   "Number of days before your article expires."
@@ -528,9 +1128,10 @@ If stringp, use this; if non-nil, use no host name (user name only)."
                 (sexp :tag "none" :format "%t" t)))
 
 (defvar message-reply-buffer nil)
-(defvar message-reply-headers nil)
-(defvar message-newsreader nil)
-(defvar message-mailer nil)
+(defvar message-reply-headers nil
+  "The headers of the current replied article.
+It is a vector of the following headers:
+\[number subject from date id references chars lines xref extra].")
 (defvar message-sent-message-via nil)
 (defvar message-checksum nil)
 (defvar message-send-actions nil
@@ -541,9 +1142,13 @@ If stringp, use this; if non-nil, use no host name (user name only)."
   "A list of actions to be performed before killing a message buffer.")
 (defvar message-postpone-actions nil
   "A list of actions to be performed after postponing a message.")
+(defvar message-original-frame nil)
+(defvar message-parameter-alist nil)
+(defvar message-startup-parameter-alist nil)
 
 (define-widget 'message-header-lines 'text
   "All header lines must be LFD terminated."
+  :format "%{%t%}:%n%v"
   :valid-regexp "^\\'"
   :error "All header lines must be newline terminated")
 
@@ -552,19 +1157,21 @@ If stringp, use this; if non-nil, use no host name (user name only)."
 It is inserted before you edit the message, so you can edit or delete
 these lines."
   :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
   :type 'message-header-lines)
 
 (defcustom message-default-mail-headers ""
   "*A string of header lines to be inserted in outgoing mails."
   :group 'message-headers
   :group 'message-mail
+  :link '(custom-manual "(message)Mail Headers")
   :type 'message-header-lines)
 
 (defcustom message-default-news-headers ""
-  "*A string of header lines to be inserted in outgoing news
-articles."
+  "*A string of header lines to be inserted in outgoing news articles."
   :group 'message-headers
   :group 'message-news
+  :link '(custom-manual "(message)News Headers")
   :type 'message-header-lines)
 
 ;; Note: could use /usr/ucb/mail instead of sendmail;
@@ -592,16 +1199,20 @@ articles."
 The value should be an expression to test whether the problem will
 actually occur."
   :group 'message-sending
+  :link '(custom-manual "(message)Mail Variables")
   :type 'sexp)
 
-;; Ignore errors in case this is used in Emacs 19.
-;; Don't use ignore-errors because this is copied into loaddefs.el.
+;;; XXX: This symbol is overloaded!  See below.
+(defvar message-user-agent nil
+  "String of the form of PRODUCT/VERSION.  Used for User-Agent header field.")
+
+(static-when (boundp 'MULE)
+  (require 'reporter));; `define-mail-user-agent' is here.
+
 ;;;###autoload
-(condition-case nil
-    (define-mail-user-agent 'message-user-agent
-      'message-mail 'message-send-and-exit
-      'message-kill-buffer 'message-send-hook)
-  (error nil))
+(define-mail-user-agent 'message-user-agent
+  'message-mail 'message-send-and-exit
+  'message-kill-buffer 'message-send-hook)
 
 (defvar message-mh-deletable-headers '(Message-ID Date Lines Sender)
   "If non-nil, delete the deletable headers before feeding to mh.")
@@ -620,10 +1231,64 @@ a message of type TYPE; and FUNCTION is a function to be called if
 PREDICATE returns non-nil.  FUNCTION is called with one parameter --
 the prefix.")
 
-(defvar message-mail-alias-type 'abbrev
+(defcustom message-mail-alias-type 'abbrev
   "*What alias expansion type to use in Message buffers.
 The default is `abbrev', which uses mailabbrev.  nil switches
-mail aliases off.")
+mail aliases off."
+  :group 'message
+  :link '(custom-manual "(message)Mail Aliases")
+  :type '(choice (const :tag "Use Mailabbrev" abbrev)
+                (const :tag "No expansion" nil)))
+
+(defcustom message-auto-save-directory
+  (file-name-as-directory (nnheader-concat message-directory "drafts"))
+  "*Directory where Message auto-saves buffers if Gnus isn't running.
+If nil, Message won't auto-save."
+  :group 'message-buffers
+  :link '(custom-manual "(message)Various Message Variables")
+  :type '(choice directory (const :tag "Don't auto-save" nil)))
+
+(defcustom message-default-charset
+  (and (featurep 'xemacs) (not (featurep 'mule)) 'iso-8859-1)
+  "Default charset used in non-MULE XEmacsen."
+  :version "21.1"
+  :group 'message
+  :link '(custom-manual "(message)Various Message Variables")
+  :type 'symbol)
+
+(defcustom message-dont-reply-to-names
+  (and (boundp 'rmail-dont-reply-to-names) rmail-dont-reply-to-names)
+  "*A regexp specifying addresses to prune when doing wide replies.
+A value of nil means exclude your own user name only."
+  :version "21.1"
+  :group 'message
+  :link '(custom-manual "(message)Wide Reply")
+  :type '(choice (const :tag "Yourself" nil)
+                regexp))
+
+(defvar message-shoot-gnksa-feet nil
+  "*A list of GNKSA feet you are allowed to shoot.
+Gnus gives you all the opportunity you could possibly want for
+shooting yourself in the foot.  Also, Gnus allows you to shoot the
+feet of Good Net-Keeping Seal of Approval.  The following are foot
+candidates:
+`empty-article'     Allow you to post an empty article;
+`quoted-text-only'  Allow you to post quoted text only;
+`multiple-copies'   Allow you to post multiple copies;
+`cancel-messages'   Allow you to cancel or supersede messages from
+                    your other email addresses.")
+
+(defsubst message-gnksa-enable-p (feature)
+  (or (not (listp message-shoot-gnksa-feet))
+      (memq feature message-shoot-gnksa-feet)))
+
+(defcustom message-hidden-headers nil
+  "Regexp of headers to be hidden when composing new messages.
+This can also be a list of regexps to match headers.  Or a list
+starting with `not' and followed by regexps."
+  :group 'message
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat regexp))
 
 ;;; Internal variables.
 ;;; Well, not really internal.
@@ -631,17 +1296,11 @@ mail aliases off.")
 (defvar message-mode-syntax-table
   (let ((table (copy-syntax-table text-mode-syntax-table)))
     (modify-syntax-entry ?% ". " table)
+    (modify-syntax-entry ?> ". " table)
+    (modify-syntax-entry ?< ". " table)
     table)
   "Syntax table used while in Message mode.")
 
-(defvar message-mode-abbrev-table text-mode-abbrev-table
-  "Abbrev table used in Message mode buffers.
-Defaults to `text-mode-abbrev-table'.")
-(defgroup message-headers nil
-  "Message headers."
-  :link '(custom-manual "(message)Variables")
-  :group 'message)
-
 (defface message-header-to-face
   '((((class color)
       (background dark))
@@ -750,34 +1409,78 @@ Defaults to `text-mode-abbrev-table'.")
   "Face used for displaying cited text names."
   :group 'message-faces)
 
+(defface message-mml-face
+  '((((class color)
+      (background dark))
+     (:foreground "ForestGreen"))
+    (((class color)
+      (background light))
+     (:foreground "ForestGreen"))
+    (t
+     (:bold t)))
+  "Face used for displaying MML."
+  :group 'message-faces)
+
+(defun message-font-lock-make-header-matcher (regexp)
+  (let ((form
+        `(lambda (limit)
+           (let ((start (point)))
+             (save-restriction
+               (widen)
+               (goto-char (point-min))
+               (if (re-search-forward
+                    (concat "^" (regexp-quote mail-header-separator) "$")
+                    nil t)
+                   (setq limit (min limit (match-beginning 0))))
+               (goto-char start))
+             (and (< start limit)
+                  (re-search-forward ,regexp limit t))))))
+    (if (featurep 'bytecomp)
+       (byte-compile form)
+      form)))
+
 (defvar message-font-lock-keywords
-  (let* ((cite-prefix "A-Za-z")
-        (cite-suffix (concat cite-prefix "0-9_.@-"))
-        (content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)"))
-    `((,(concat "^\\([Tt]o:\\)" content)
+  (let ((content "[ \t]*\\(.+\\(\n[ \t].*\\)*\\)\n?"))
+    `((,(message-font-lock-make-header-matcher
+        (concat "^\\([Tt]o:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-to-face nil t))
-      (,(concat "^\\(^[GBF]?[Cc][Cc]:\\|^[Rr]eply-[Tt]o:\\)" content)
+      (,(message-font-lock-make-header-matcher
+        (concat "^\\([GBF]?[Cc][Cc]:\\|[Rr]eply-[Tt]o:\\|"
+                "[Mm]ail-[Cc]opies-[Tt]o:\\|"
+                "[Mm]ail-[Rr]eply-[Tt]o:\\|"
+                "[Mm]ail-[Ff]ollowup-[Tt]o:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-cc-face nil t))
-      (,(concat "^\\([Ss]ubject:\\)" content)
+      (,(message-font-lock-make-header-matcher
+        (concat "^\\([Ss]ubject:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-subject-face nil t))
-      (,(concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content)
+      (,(message-font-lock-make-header-matcher
+        (concat "^\\([Nn]ewsgroups:\\|Followup-[Tt]o:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-newsgroups-face nil t))
-      (,(concat "^\\([A-Z][^: \n\t]+:\\)" content)
+      (,(message-font-lock-make-header-matcher
+        (concat "^\\([A-Z][^: \n\t]+:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-other-face nil t))
-      (,(concat "^\\(X-[A-Za-z0-9-]+\\|In-Reply-To\\):" content)
+      (,(message-font-lock-make-header-matcher
+        (concat "^\\(X-[A-Za-z0-9-]+:\\|In-Reply-To:\\)" content))
        (1 'message-header-name-face)
        (2 'message-header-name-face))
-      (,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
-       1 'message-separator-face)
-      (,(concat "^[ \t]*"
-               "\\([" cite-prefix "]+[" cite-suffix "]*\\)?"
-               "[:>|}].*")
-       (0 'message-cited-text-face))))
+      ,@(if (and mail-header-separator
+                (not (equal mail-header-separator "")))
+           `((,(concat "^\\(" (regexp-quote mail-header-separator) "\\)$")
+              1 'message-separator-face))
+         nil)
+      ((lambda (limit)
+        (re-search-forward (concat "^\\("
+                                   message-cite-prefix-regexp
+                                   "\\).*")
+                           limit t))
+       (0 'message-cited-text-face))
+      (,mime-edit-tag-regexp
+       (0 'message-mml-face))))
   "Additional expressions to highlight in Message mode.")
 
 ;; XEmacs does it like this.  For Emacs, we have to set the
@@ -791,22 +1494,30 @@ Defaults to `text-mode-abbrev-table'.")
                 (unbold-region b e)
                 (ununderline-region b e))))
   "Alist of mail and news faces for facemenu.
-The cdr of ech entry is a function for applying the face to a region.")
+The cdr of each entry is a function for applying the face to a region.")
 
 (defcustom message-send-hook nil
-  "Hook run before sending messages."
+  "Hook run before sending messages.
+This hook is run quite early when sending."
   :group 'message-various
   :options '(ispell-message)
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-send-mail-hook nil
-  "Hook run before sending mail messages."
+  "Hook run before sending mail messages.
+This hook is run very late -- just before the message is sent as
+mail."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-send-news-hook nil
-  "Hook run before sending news messages."
+  "Hook run before sending news messages.
+This hook is run very late -- just before the message is sent as
+news."
   :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
   :type 'hook)
 
 (defcustom message-sent-hook nil
@@ -814,16 +1525,122 @@ The cdr of ech entry is a function for applying the face to a region.")
   :group 'message-various
   :type 'hook)
 
+(defcustom message-use-multi-frames nil
+  "Make new frame when sending messages."
+  :group 'message-frames
+  :type 'boolean)
+
+(defcustom message-delete-frame-on-exit nil
+  "Delete frame after sending messages."
+  :group 'message-frames
+  :type '(choice (const :tag "off" nil)
+                (const :tag "always" t)
+                (const :tag "ask" ask)))
+
+(defvar message-draft-coding-system
+  nnheader-auto-save-coding-system
+  "*Coding system to compose mail.
+If you'd like to make it possible to share draft files between XEmacs
+and Emacs, you may use `iso-2022-7bit' for this value at your own risk.
+Note that the coding-system `iso-2022-7bit' isn't suitable to all data.")
+
+(defcustom message-send-mail-partially-limit 1000000
+  "The limitation of messages sent as message/partial.
+The lower bound of message size in characters, beyond which the message
+should be sent in several parts.  If it is nil, the size is unlimited."
+  :version "21.1"
+  :group 'message-buffers
+  :link '(custom-manual "(message)Mail Variables")
+  :type '(choice (const :tag "unlimited" nil)
+                (integer 1000000)))
+
+(defcustom message-alternative-emails nil
+  "A regexp to match the alternative email addresses.
+The first matched address (not primary one) is used in the From field."
+  :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
+  :type '(choice (const :tag "Always use primary" nil)
+                regexp))
+
+(defcustom message-hierarchical-addresses nil
+  "A list of hierarchical mail address definitions.
+
+Inside each entry, the first address is the \"top\" address, and
+subsequent addresses are subaddresses; this is used to indicate that
+mail sent to the first address will automatically be delivered to the
+subaddresses.  So if the first address appears in the recipient list
+for a message, the subaddresses will be removed (if present) before
+the mail is sent.  All addresses in this structure should be
+downcased."
+  :group 'message-headers
+  :type '(repeat (repeat string)))
+
+(defcustom message-mail-user-agent nil
+  "Like `mail-user-agent'.
+Except if it is nil, use Gnus native MUA; if it is t, use
+`mail-user-agent'."
+  :type '(radio (const :tag "Gnus native"
+                      :format "%t\n"
+                      nil)
+               (const :tag "`mail-user-agent'"
+                      :format "%t\n"
+                      t)
+               (function-item :tag "Default Emacs mail"
+                              :format "%t\n"
+                              sendmail-user-agent)
+               (function-item :tag "Emacs interface to MH"
+                              :format "%t\n"
+                              mh-e-user-agent)
+               (function :tag "Other"))
+  :version "21.1"
+  :group 'message)
+
+(defcustom message-wide-reply-confirm-recipients nil
+  "Whether to confirm a wide reply to multiple email recipients.
+If this variable is nil, don't ask whether to reply to all recipients.
+If this variable is non-nil, pose the question \"Reply to all
+recipients?\" before a wide reply to multiple recipients.  If the user
+answers yes, reply to all recipients as usual.  If the user answers
+no, only reply back to the author."
+  :version "21.3"
+  :group 'message-headers
+  :link '(custom-manual "(message)Wide Reply")
+  :type 'boolean)
+
+(defcustom message-user-fqdn nil
+  "*Domain part of Messsage-Ids."
+  :group 'message-headers
+  :link '(custom-manual "(message)News Headers")
+  :type '(radio (const :format "%v  " nil)
+               (string :format "FQDN: %v\n" :size 0)))
+
+(defcustom message-use-idna (and (condition-case nil (require 'idna)
+                                  (file-error))
+                                (mm-coding-system-p 'utf-8)
+                                (executable-find idna-program)
+                                'ask)
+  "Whether to encode non-ASCII in domain names into ASCII according to IDNA."
+  :group 'message-headers
+  :link '(custom-manual "(message)IDNA")
+  :type '(choice (const :tag "Ask" ask)
+                (const :tag "Never" nil)
+                (const :tag "Always" t)))
+
 ;;; Internal variables.
 
+(defvar message-sending-message "Sending...")
 (defvar message-buffer-list nil)
 (defvar message-this-is-news nil)
 (defvar message-this-is-mail nil)
 (defvar message-draft-article nil)
+(defvar message-mime-part nil)
+(defvar message-posting-charset nil)
+(defvar message-inserted-headers nil)
 
 ;; Byte-compiler warning
-(defvar gnus-active-hashtb)
-(defvar gnus-read-active-file)
+(eval-when-compile
+  (defvar gnus-active-hashtb)
+  (defvar gnus-read-active-file))
 
 ;;; Regexp matching the delimiter of messages in UNIX mail format
 ;;; (UNIX From lines), minus the initial ^.  It should be a copy
@@ -844,7 +1661,7 @@ The cdr of ech entry is a function for applying the face to a region.")
      ;; can be removed, e.g.
      ;;                From: joe@y.z (Joe      K
      ;;                        User)
-     ;; can yield `From joe@y.z (Joe   K Fri Mar 22 08:11:15 1996', and
+     ;; can yield `From joe@y.z (Joe   K Fri Mar 22 08:11:15 1996', and
      ;;                From: Joe User
      ;;                        <joe@y.z>
      ;; can yield `From Joe User Fri Mar 22 08:11:15 1996'.
@@ -856,13 +1673,13 @@ The cdr of ech entry is a function for applying the face to a region.")
      ;; We want to match the results of any of these manglings.
      ;; The following regexp rejects names whose first characters are
      ;; obviously bogus, but after that anything goes.
-     "\\([^\0-\b\n-\r\^?].*\\)? "
+     "\\([^\0-\b\n-\r\^?].*\\)?"
 
      ;; The time the message was sent.
-     "\\([^\0-\r \^?]+\\) +"                           ; day of the week
-     "\\([^\0-\r \^?]+\\) +"                           ; month
-     "\\([0-3]?[0-9]\\) +"                             ; day of month
-     "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *" ; time of day
+     "\\([^\0-\r \^?]+\\) +"           ; day of the week
+     "\\([^\0-\r \^?]+\\) +"           ; month
+     "\\([0-3]?[0-9]\\) +"             ; day of month
+     "\\([0-2][0-9]:[0-5][0-9]\\(:[0-6][0-9]\\)?\\) *" ; time of day
 
      ;; Perhaps a time zone, specified by an abbreviation, or by a
      ;; numeric offset.
@@ -887,6 +1704,7 @@ The cdr of ech entry is a function for applying the face to a region.")
          "^ *---+ +Original message +---+ *$\\|"
          "^ *--+ +begin message +--+ *$\\|"
          "^ *---+ +Original message follows +---+ *$\\|"
+         "^ *---+ +Undelivered message follows +---+ *$\\|"
          "^|? *---+ +Message text follows: +---+ *|?$")
   "A regexp that matches the separator before the text of a failed message.")
 
@@ -904,52 +1722,114 @@ The cdr of ech entry is a function for applying the face to a region.")
     (Lines)
     (Expires)
     (Message-ID)
-    (References . message-fill-header)
-    (X-Mailer)
-    (X-Newsreader))
+    (References . message-shorten-references)
+    (User-Agent))
   "Alist used for formatting headers.")
 
+(defvar        message-options nil
+  "Some saved answers when sending message.")
+
+(defvar message-send-mail-real-function nil
+  "Internal send mail function.")
+
+(defvar message-bogus-system-names "^localhost\\."
+  "The regexp of bogus system names.")
+
+(defcustom message-valid-fqdn-regexp
+  (concat "[a-z0-9][-.a-z0-9]+\\." ;; [hostname.subdomain.]domain.
+         ;; valid TLDs:
+         "\\([a-z][a-z]" ;; two letter country TDLs
+         "\\|biz\\|com\\|edu\\|gov\\|int\\|mil\\|net\\|org"
+         "\\|aero\\|coop\\|info\\|name\\|museum"
+         "\\|arpa\\|pro\\|uucp\\|bitnet\\|bofh" ;; old style?
+         "\\)")
+  "Regular expression that matches a valid FQDN."
+  ;; see also: gnus-button-valid-fqdn-regexp
+  :group 'message-headers
+  :type 'regexp)
+
 (eval-and-compile
   (autoload 'message-setup-toolbar "messagexmas")
   (autoload 'mh-new-draft-name "mh-comp")
   (autoload 'mh-send-letter "mh-comp")
   (autoload 'gnus-point-at-eol "gnus-util")
   (autoload 'gnus-point-at-bol "gnus-util")
-  (autoload 'gnus-output-to-mail "gnus-util")
   (autoload 'gnus-output-to-rmail "gnus-util")
-  (autoload 'mail-abbrev-in-expansion-header-p "mailabbrev")
+  (autoload 'gnus-output-to-mail "gnus-util")
   (autoload 'nndraft-request-associate-buffer "nndraft")
   (autoload 'nndraft-request-expire-articles "nndraft")
   (autoload 'gnus-open-server "gnus-int")
   (autoload 'gnus-request-post "gnus-int")
-  (autoload 'rmail-output "rmail"))
+  (autoload 'gnus-copy-article-buffer "gnus-msg")
+  (autoload 'gnus-alive-p "gnus-util")
+  (autoload 'gnus-server-string "gnus")
+  (autoload 'gnus-group-name-charset "gnus-group")
+  (autoload 'gnus-group-name-decode "gnus-group")
+  (autoload 'gnus-groups-from-server "gnus")
+  (autoload 'rmail-output "rmailout")
+  (autoload 'gnus-delay-article "gnus-delay")
+  (autoload 'gnus-make-local-hook "gnus-util")
+  (autoload 'gnus-extract-address-components "gnus-util"))
+
+(eval-and-compile
+  (autoload 'mu-cite-original "mu-cite"))
 
 \f
 
 ;;;
 ;;; Utility functions.
 ;;;
+(defun message-eval-parameter (parameter)
+  (condition-case ()
+      (if (symbolp parameter)
+         (if (functionp parameter)
+             (funcall parameter)
+           (eval parameter))
+       parameter)
+    (error nil)))
+
+(defsubst message-get-parameter (key &optional alist)
+  (unless alist
+    (setq alist message-parameter-alist))
+  (cdr (assq key alist)))
+
+(defmacro message-get-parameter-with-eval (key &optional alist)
+  `(message-eval-parameter (message-get-parameter ,key ,alist)))
 
 (defmacro message-y-or-n-p (question show &rest text)
-  "Ask QUESTION, displaying the rest of the arguments in a temp. buffer if SHOW"
+  "Ask QUESTION, displaying remaining args in a temporary buffer if SHOW."
   `(message-talkative-question 'y-or-n-p ,question ,show ,@text))
 
-;; Delete the current line (and the next N lines.);
 (defmacro message-delete-line (&optional n)
+  "Delete the current line (and the next N lines)."
   `(delete-region (progn (beginning-of-line) (point))
                  (progn (forward-line ,(or n 1)) (point))))
 
+(defun message-mark-active-p ()
+  "Non-nil means the mark and region are currently active in this buffer."
+  mark-active)
+
+(defun message-unquote-tokens (elems)
+  "Remove double quotes (\") from strings in list ELEMS."
+  (mapcar (lambda (item)
+           (while (string-match "^\\(.*\\)\"\\(.*\\)$" item)
+             (setq item (concat (match-string 1 item)
+                                (match-string 2 item))))
+           item)
+         elems))
+
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
-\",\" is used as the separator."
+SEPARATOR is a string of characters to be used as separators.  \",\"
+is used by default."
   (if (not header)
       nil
     (let ((regexp (format "[%s]+" (or separator ",")))
          (beg 1)
          (first t)
          quoted elems paren)
-      (save-excursion
-       (message-set-work-buffer)
+      (with-temp-buffer
+       (set-buffer-multibyte t)
        (insert header)
        (goto-char (point-min))
        (while (not (eobp))
@@ -963,12 +1843,12 @@ The cdr of ech entry is a function for applying the face to a region.")
                               (not paren))))
                 (push (buffer-substring beg (point)) elems)
                 (setq beg (match-end 0)))
-               ((= (following-char) ?\")
+               ((eq (char-after) ?\")
                 (setq quoted (not quoted)))
-               ((and (= (following-char) ?\()
+               ((and (eq (char-after) ?\()
                      (not quoted))
                 (setq paren t))
-               ((and (= (following-char) ?\))
+               ((and (eq (char-after) ?\))
                      (not quoted))
                 (setq paren nil))))
        (nreverse elems)))))
@@ -978,16 +1858,44 @@ The cdr of ech entry is a function for applying the face to a region.")
   (when (and (file-exists-p file)
             (file-readable-p file)
             (file-regular-p file))
-    (nnheader-temp-write nil
+    (with-temp-buffer
       (nnheader-insert-file-contents file)
       (goto-char (point-min))
       (looking-at message-unix-mail-delimiter))))
 
 (defun message-fetch-field (header &optional not-all)
-  "The same as `mail-fetch-field', only remove all newlines."
-  (let ((value (mail-fetch-field header nil (not not-all))))
+  "The same as `mail-fetch-field', only remove all newlines.
+The buffer is expected to be narrowed to just the header of the message;
+see `message-narrow-to-headers-or-head'."
+  (let* ((inhibit-point-motion-hooks t)
+        (case-fold-search t)
+        (value (mail-fetch-field header nil (not not-all))))
     (when value
-      (nnheader-replace-chars-in-string value ?\n ? ))))
+      (while (string-match "\n[\t ]+" value)
+       (setq value (replace-match " " t t value)))
+      (set-text-properties 0 (length value) nil value)
+      value)))
+
+(defun message-field-value (header &optional not-all)
+  "The same as `message-fetch-field', only narrow to the headers first."
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers-or-head)
+      (message-fetch-field header not-all))))
+
+(defun message-narrow-to-field ()
+  "Narrow the buffer to the header on the current line."
+  (beginning-of-line)
+  (narrow-to-region
+   (point)
+   (progn
+     (forward-line 1)
+     (if (re-search-forward "^[^ \n\t]" nil t)
+        (progn
+          (beginning-of-line)
+          (point))
+       (point-max))))
+  (goto-char (point-min)))
 
 (defun message-add-header (&rest headers)
   "Add the HEADERS to the message header, skipping those already present."
@@ -996,48 +1904,321 @@ The cdr of ech entry is a function for applying the face to a region.")
       (unless (string-match "^\\([^:]+\\):[ \t]*[^ \t]" (car headers))
        (error "Invalid header `%s'" (car headers)))
       (setq hclean (match-string 1 (car headers)))
-    (save-restriction
-      (message-narrow-to-headers)
-      (unless (re-search-forward (concat "^" (regexp-quote hclean) ":") nil t)
-       (insert (car headers) ?\n))))
+      (save-restriction
+       (message-narrow-to-headers)
+       (unless (re-search-forward (concat "^" (regexp-quote hclean) ":") nil t)
+         (goto-char (point-max))
+         (if (string-match "\n$" (car headers))
+             (insert (car headers))
+           (insert (car headers) ?\n)))))
     (setq headers (cdr headers))))
 
+(defmacro message-with-reply-buffer (&rest forms)
+  "Evaluate FORMS in the reply buffer, if it exists."
+  `(let ((buffer (message-eval-parameter message-reply-buffer)))
+     (when (and buffer
+               (buffer-name buffer))
+       (save-excursion
+        (set-buffer buffer)
+        ,@forms))))
+
+(put 'message-with-reply-buffer 'lisp-indent-function 0)
+(put 'message-with-reply-buffer 'edebug-form-spec '(body))
+
 (defun message-fetch-reply-field (header)
-  "Fetch FIELD from the message we're replying to."
-  (when (and message-reply-buffer
-            (buffer-name message-reply-buffer))
-    (save-excursion
-      (set-buffer message-reply-buffer)
+  "Fetch field HEADER from the message we're replying to."
+  (message-with-reply-buffer
+    (save-restriction
+      (mail-narrow-to-head)
       (message-fetch-field header))))
 
-(defun message-set-work-buffer ()
-  (if (get-buffer " *message work*")
-      (progn
-       (set-buffer " *message work*")
-       (erase-buffer))
-    (set-buffer (get-buffer-create " *message work*"))
-    (kill-all-local-variables)
-    (buffer-disable-undo (current-buffer))))
+(defun message-strip-list-identifiers (subject)
+  "Remove list identifiers in `gnus-list-identifiers' from string SUBJECT."
+  (require 'gnus-sum)                  ; for gnus-list-identifiers
+  (let ((regexp (if (stringp gnus-list-identifiers)
+                   gnus-list-identifiers
+                 (mapconcat 'identity gnus-list-identifiers " *\\|"))))
+    (if (string-match (concat "\\(\\(\\(Re: +\\)?\\(" regexp
+                             " *\\)\\)+\\(Re: +\\)?\\)") subject)
+       (concat (substring subject 0 (match-beginning 1))
+               (or (match-string 3 subject)
+                   (match-string 5 subject))
+               (substring subject
+                          (match-end 1)))
+      subject)))
+
+(defun message-strip-subject-re (subject)
+  "Remove \"Re:\" from subject lines in string SUBJECT."
+  (if (string-match message-subject-re-regexp subject)
+      (substring subject (match-end 0))
+    subject))
+
+;;; Start of functions adopted from `message-utils.el'.
+
+(defun message-strip-subject-trailing-was (subject)
+  "Remove trailing \"(Was: <old subject>)\" from SUBJECT lines.
+Leading \"Re: \" is not stripped by this function.  Use the function
+`message-strip-subject-re' for this."
+  (let* ((query message-subject-trailing-was-query)
+        (new) (found))
+    (setq found
+         (string-match
+          (if (eq query 'ask)
+              message-subject-trailing-was-ask-regexp
+            message-subject-trailing-was-regexp)
+          subject))
+    (if found
+       (setq new (substring subject 0 (match-beginning 0))))
+    (if (or (not found) (eq query nil))
+       subject
+      (if (eq query 'ask)
+         (if (message-y-or-n-p
+              "Strip `(was: <old subject>)' in subject? " t
+              (concat
+               "Strip `(was: <old subject>)' in subject "
+               "and use the new one instead?\n\n"
+               "Current subject is:   \""
+               subject "\"\n\n"
+               "New subject would be: \""
+               new "\"\n\n"
+               "See the variable `message-subject-trailing-was-query' "
+               "to get rid of this query."
+               ))
+             new subject)
+       new))))
+
+;;; Suggested by Jonas Steverud  @  www.dtek.chalmers.se/~d4jonas/
+
+;;;###autoload
+(defun message-change-subject (new-subject)
+  "Ask for NEW-SUBJECT header, append (was: <Old Subject>)."
+  ;; <URL:http://www.landfield.com/usefor/drafts/draft-ietf-usefor-useage--1.02.unpaged>
+  (interactive
+   (list
+    (read-from-minibuffer "New subject: ")))
+  (cond ((and (not (or (null new-subject) ; new subject not empty
+                      (zerop (string-width new-subject))
+                      (string-match "^[ \t]*$" new-subject))))
+        (save-excursion
+          (let ((old-subject
+                 (save-restriction
+                   (message-narrow-to-headers)
+                   (message-fetch-field "Subject"))))
+            (cond ((not old-subject)
+                   (error "No current subject"))
+                  ((not (string-match
+                         (concat "^[ \t]*"
+                                 (regexp-quote new-subject)
+                                 " \t]*$")
+                         old-subject))  ; yes, it really is a new subject
+                   ;; delete eventual Re: prefix
+                   (setq old-subject
+                         (message-strip-subject-re old-subject))
+                   (message-goto-subject)
+                   (message-delete-line)
+                   (insert (concat "Subject: "
+                                   new-subject
+                                   " (was: "
+                                   old-subject ")\n")))))))))
 
-(defun message-functionp (form)
-  "Return non-nil if FORM is funcallable."
-  (or (and (symbolp form) (fboundp form))
-      (and (listp form) (eq (car form) 'lambda))
-      (byte-code-function-p form)))
+;;;###autoload
+(defun message-mark-inserted-region (beg end)
+  "Mark some region in the current article with enclosing tags.
+See `message-mark-insert-begin' and `message-mark-insert-end'."
+  (interactive "r")
+  (save-excursion
+    ;; add to the end of the region first, otherwise end would be invalid
+    (goto-char end)
+    (insert message-mark-insert-end)
+    (goto-char beg)
+    (insert message-mark-insert-begin)))
+
+;;;###autoload
+(defun message-mark-insert-file (file)
+  "Insert FILE at point, marking it with enclosing tags.
+See `message-mark-insert-begin' and `message-mark-insert-end'."
+  (interactive "fFile to insert: ")
+    ;; reverse insertion to get correct result.
+  (let ((p (point)))
+    (insert message-mark-insert-end)
+    (goto-char p)
+    (insert-file-contents file)
+    (goto-char p)
+    (insert message-mark-insert-begin)))
+
+;;;###autoload
+(defun message-add-archive-header ()
+  "Insert \"X-No-Archive: Yes\" in the header and a note in the body.
+The note can be customized using `message-archive-note'.  When called with a
+prefix argument, ask for a text to insert.  If you don't want the note in the
+body, set  `message-archive-note' to nil."
+  (interactive)
+  (if current-prefix-arg
+      (setq message-archive-note
+           (read-from-minibuffer "Reason for No-Archive: "
+                                 (cons message-archive-note 0))))
+    (save-excursion
+      (if (message-goto-signature)
+         (re-search-backward message-signature-separator))
+      (when message-archive-note
+       (insert message-archive-note)
+       (newline))
+      (message-add-header message-archive-header)
+      (message-sort-headers)))
+
+;;;###autoload
+(defun message-cross-post-followup-to-header (target-group)
+  "Mangles FollowUp-To and Newsgroups header to point to TARGET-GROUP.
+With prefix-argument just set Follow-Up, don't cross-post."
+  (interactive
+   (list ; Completion based on Gnus
+    (completing-read "Followup To: "
+                    (if (boundp 'gnus-newsrc-alist)
+                        gnus-newsrc-alist)
+                    nil nil '("poster" . 0)
+                    (if (boundp 'gnus-group-history)
+                        'gnus-group-history))))
+  (message-remove-header "Follow[Uu]p-[Tt]o" t)
+  (message-goto-newsgroups)
+  (beginning-of-line)
+  ;; if we already did a crosspost before, kill old target
+  (if (and message-cross-post-old-target
+          (re-search-forward
+           (regexp-quote (concat "," message-cross-post-old-target))
+           nil t))
+      (replace-match ""))
+  ;; unless (followup is to poster or user explicitly asked not
+  ;; to cross-post, or target-group is already in Newsgroups)
+  ;; add target-group to Newsgroups line.
+  (cond ((and (or
+              ;; def: cross-post, req:no
+              (and message-cross-post-default (not current-prefix-arg))
+              ;; def: no-cross-post, req:yes
+              (and (not message-cross-post-default) current-prefix-arg))
+             (not (string-match "poster" target-group))
+             (not (string-match (regexp-quote target-group)
+                                (message-fetch-field "Newsgroups"))))
+        (end-of-line)
+        (insert (concat "," target-group))))
+  (end-of-line) ; ensure Followup: comes after Newsgroups:
+  ;; unless new followup would be identical to Newsgroups line
+  ;; make a new Followup-To line
+  (if (not (string-match (concat "^[ \t]*"
+                                target-group
+                                "[ \t]*$")
+                        (message-fetch-field "Newsgroups")))
+      (insert (concat "\nFollowup-To: " target-group)))
+  (setq message-cross-post-old-target target-group))
+
+;;;###autoload
+(defun message-cross-post-insert-note (target-group cross-post in-old
+                                                   old-groups)
+  "Insert a in message body note about a set Followup or Crosspost.
+If there have been previous notes, delete them.  TARGET-GROUP specifies the
+group to Followup-To.  When CROSS-POST is t, insert note about
+crossposting.  IN-OLD specifies whether TARGET-GROUP is a member of
+OLD-GROUPS.  OLD-GROUPS lists the old-groups the posting would have
+been made to before the user asked for a Crosspost."
+  ;; start scanning body for previous uses
+  (message-goto-signature)
+  (let ((head (re-search-backward
+              (concat "^" mail-header-separator)
+              nil t))) ; just search in body
+    (message-goto-signature)
+    (while (re-search-backward
+           (concat "^" (regexp-quote message-cross-post-note) ".*")
+           head t)
+      (message-delete-line))
+    (message-goto-signature)
+    (while (re-search-backward
+           (concat "^" (regexp-quote message-followup-to-note) ".*")
+           head t)
+      (message-delete-line))
+    ;; insert new note
+    (if (message-goto-signature)
+       (re-search-backward message-signature-separator))
+    (if (or in-old
+           (not cross-post)
+           (string-match "^[ \t]*poster[ \t]*$" target-group))
+       (insert (concat message-followup-to-note target-group "\n"))
+      (insert (concat message-cross-post-note target-group "\n")))))
+
+;;;###autoload
+(defun message-cross-post-followup-to (target-group)
+  "Crossposts message and set Followup-To to TARGET-GROUP.
+With prefix-argument just set Follow-Up, don't cross-post."
+  (interactive
+   (list ; Completion based on Gnus
+    (completing-read "Followup To: "
+                    (if (boundp 'gnus-newsrc-alist)
+                        gnus-newsrc-alist)
+                    nil nil '("poster" . 0)
+                    (if (boundp 'gnus-group-history)
+                        'gnus-group-history))))
+  (cond ((not (or (null target-group) ; new subject not empty
+                 (zerop (string-width target-group))
+                 (string-match "^[ \t]*$" target-group)))
+        (save-excursion
+          (let* ((old-groups (message-fetch-field "Newsgroups"))
+                 (in-old (string-match
+                          (regexp-quote target-group)
+                          (or old-groups ""))))
+            ;; check whether target exactly matches old Newsgroups
+            (cond ((not old-groups)
+                   (error "No current newsgroup"))
+                  ((or (not in-old)
+                       (not (string-match
+                             (concat "^[ \t]*"
+                                     (regexp-quote target-group)
+                                     "[ \t]*$")
+                             old-groups)))
+                   ;; yes, Newsgroups line must change
+                   (message-cross-post-followup-to-header target-group)
+                   ;; insert note whether we do cross-post or followup-to
+                   (funcall message-cross-post-note-function
+                            target-group
+                            (if (or (and message-cross-post-default
+                                         (not current-prefix-arg))
+                                    (and (not message-cross-post-default)
+                                         current-prefix-arg)) t)
+                            in-old old-groups))))))))
+
+;;; Reduce To: to Cc: or Bcc: header
+
+;;;###autoload
+(defun message-reduce-to-to-cc ()
+ "Replace contents of To: header with contents of Cc: or Bcc: header."
+ (interactive)
+ (let ((cc-content
+       (save-restriction (message-narrow-to-headers)
+                         (message-fetch-field "cc")))
+       (bcc nil))
+   (if (and (not cc-content)
+           (setq cc-content
+                 (save-restriction
+                   (message-narrow-to-headers)
+                   (message-fetch-field "bcc"))))
+       (setq bcc t))
+   (cond (cc-content
+         (save-excursion
+           (message-goto-to)
+           (message-delete-line)
+           (insert (concat "To: " cc-content "\n"))
+           (save-restriction
+             (message-narrow-to-headers)
+             (message-remove-header (if bcc
+                                        "bcc"
+                                      "cc"))))))))
 
-(defun message-strip-subject-re (subject)
-  "Remove \"Re:\" from subject lines."
-  (if (string-match "^[Rr][Ee]: *" subject)
-      (substring subject (match-end 0))
-    subject))
+;;; End of functions adopted from `message-utils.el'.
 
 (defun message-remove-header (header &optional is-regexp first reverse)
   "Remove HEADER in the narrowed buffer.
-If REGEXP, HEADER is a regular expression.
+If IS-REGEXP, HEADER is a regular expression.
 If FIRST, only remove the first instance of the header.
 Return the number of headers removed."
   (goto-char (point-min))
-  (let ((regexp (if is-regexp header (concat "^" header ":")))
+  (let ((regexp (if is-regexp header (concat "^" (regexp-quote header) ":")))
        (number 0)
        (case-fold-search t)
        last)
@@ -1062,9 +2243,21 @@ Return the number of headers removed."
        (forward-line 1)
        (if (re-search-forward "^[^ \t]" nil t)
            (goto-char (match-beginning 0))
-         (point-max))))
+         (goto-char (point-max)))))
     number))
 
+(defun message-remove-first-header (header)
+  "Remove the first instance of HEADER if there is more than one."
+  (let ((count 0)
+       (regexp (concat "^" (regexp-quote header) ":")))
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward regexp nil t)
+       (incf count)))
+    (while (> count 1)
+      (message-remove-header header nil t)
+      (decf count))))
+
 (defun message-narrow-to-headers ()
   "Narrow the buffer to the head of the message."
   (widen)
@@ -1076,9 +2269,8 @@ Return the number of headers removed."
      (point-max)))
   (goto-char (point-min)))
 
-(defun message-narrow-to-head ()
-  "Narrow the buffer to the head of the message."
-  (widen)
+(defun message-narrow-to-head-1 ()
+  "Like `message-narrow-to-head'.  Don't widen."
   (narrow-to-region
    (goto-char (point-min))
    (if (search-forward "\n\n" nil 1)
@@ -1086,24 +2278,54 @@ Return the number of headers removed."
      (point-max)))
   (goto-char (point-min)))
 
+(defun message-narrow-to-head ()
+  "Narrow the buffer to the head of the message.
+Point is left at the beginning of the narrowed-to region."
+  (widen)
+  (message-narrow-to-head-1))
+
+(defun message-narrow-to-headers-or-head ()
+  "Narrow the buffer to the head of the message."
+  (widen)
+  (narrow-to-region
+   (goto-char (point-min))
+   (cond
+    ((re-search-forward
+      (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
+     (match-beginning 0))
+    ((search-forward "\n\n" nil t)
+     (1- (point)))
+    (t
+     (point-max))))
+  (goto-char (point-min)))
+
 (defun message-news-p ()
   "Say whether the current buffer contains a news message."
-  (or message-this-is-news
-      (save-excursion
-       (save-restriction
-         (message-narrow-to-headers)
-         (and (message-fetch-field "newsgroups")
-              (not (message-fetch-field "posted-to")))))))
+  (and (not message-this-is-mail)
+       (or message-this-is-news
+          (save-excursion
+            (save-restriction
+              (message-narrow-to-headers)
+              (and (message-fetch-field "newsgroups")
+                   (not (message-fetch-field "posted-to"))))))))
 
 (defun message-mail-p ()
   "Say whether the current buffer contains a mail message."
-  (or message-this-is-mail
-      (save-excursion
-       (save-restriction
-         (message-narrow-to-headers)
-         (or (message-fetch-field "to")
-             (message-fetch-field "cc")
-             (message-fetch-field "bcc"))))))
+  (and (not message-this-is-news)
+       (or message-this-is-mail
+          (save-excursion
+            (save-restriction
+              (message-narrow-to-headers)
+              (or (message-fetch-field "to")
+                  (message-fetch-field "cc")
+                  (message-fetch-field "bcc")))))))
+
+(defun message-subscribed-p ()
+  "Say whether we need to insert a MFT header."
+  (or message-subscribed-regexps
+      message-subscribed-addresses
+      message-subscribed-address-file
+      message-subscribed-address-functions))
 
 (defun message-next-header ()
   "Go to the beginning of the next header."
@@ -1116,6 +2338,7 @@ Return the number of headers removed."
 (defun message-sort-headers-1 ()
   "Sort the buffer as headers using `message-rank' text props."
   (goto-char (point-min))
+  (require 'sort)
   (sort-subr
    nil 'message-next-header
    (lambda ()
@@ -1158,29 +2381,59 @@ Return the number of headers removed."
 (defvar message-mode-map nil)
 
 (unless message-mode-map
-  (setq message-mode-map (copy-keymap text-mode-map))
+  (setq message-mode-map (make-keymap))
+  (set-keymap-parent message-mode-map text-mode-map)
   (define-key message-mode-map "\C-c?" 'describe-mode)
 
   (define-key message-mode-map "\C-c\C-f\C-t" 'message-goto-to)
+  (define-key message-mode-map "\C-c\C-f\C-o" 'message-goto-from)
   (define-key message-mode-map "\C-c\C-f\C-b" 'message-goto-bcc)
   (define-key message-mode-map "\C-c\C-f\C-w" 'message-goto-fcc)
   (define-key message-mode-map "\C-c\C-f\C-c" 'message-goto-cc)
   (define-key message-mode-map "\C-c\C-f\C-s" 'message-goto-subject)
-  (define-key message-mode-map "\C-c\C-f\C-r" 'message-goto-reply-to)
+  ;; (define-key message-mode-map "\C-c\C-f\C-r" 'message-goto-reply-to)
+  (define-key message-mode-map "\C-c\C-f\C-r" 'message-goto-mail-reply-to)
+  (define-key message-mode-map "\C-c\C-f\C-m" 'message-goto-mail-followup-to)
   (define-key message-mode-map "\C-c\C-f\C-n" 'message-goto-newsgroups)
   (define-key message-mode-map "\C-c\C-f\C-d" 'message-goto-distribution)
   (define-key message-mode-map "\C-c\C-f\C-f" 'message-goto-followup-to)
+  (define-key message-mode-map "\C-c\C-f\C-m" 'message-goto-mail-followup-to)
   (define-key message-mode-map "\C-c\C-f\C-k" 'message-goto-keywords)
   (define-key message-mode-map "\C-c\C-f\C-u" 'message-goto-summary)
+  (define-key message-mode-map "\C-c\C-f\C-i"
+    'message-insert-or-toggle-importance)
+  (define-key message-mode-map "\C-c\C-f\C-a"
+    'message-generate-unsubscribed-mail-followup-to)
+
+  ;; modify headers (and insert notes in body)
+  (define-key message-mode-map "\C-c\C-fs"    'message-change-subject)
+  ;;
+  (define-key message-mode-map "\C-c\C-fx"    'message-cross-post-followup-to)
+  ;; prefix+message-cross-post-followup-to = same w/o cross-post
+  (define-key message-mode-map "\C-c\C-ft"    'message-reduce-to-to-cc)
+  (define-key message-mode-map "\C-c\C-fa"    'message-add-archive-header)
+  ;; mark inserted text
+  (define-key message-mode-map "\C-c\M-m" 'message-mark-inserted-region)
+  (define-key message-mode-map "\C-c\M-f" 'message-mark-insert-file)
+
   (define-key message-mode-map "\C-c\C-b" 'message-goto-body)
   (define-key message-mode-map "\C-c\C-i" 'message-goto-signature)
+  (define-key message-mode-map "\C-c\C-fc" 'message-goto-mail-copies-to)
 
   (define-key message-mode-map "\C-c\C-t" 'message-insert-to)
+  (define-key message-mode-map "\C-c\C-fw" 'message-insert-wide-reply)
   (define-key message-mode-map "\C-c\C-n" 'message-insert-newsgroups)
+  (define-key message-mode-map "\C-c\C-l" 'message-to-list-only)
+
+  (define-key message-mode-map "\C-c\C-u" 'message-insert-or-toggle-importance)
+  (define-key message-mode-map "\C-c\M-n"
+    'message-insert-disposition-notification-to)
 
   (define-key message-mode-map "\C-c\C-y" 'message-yank-original)
+  (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)
   (define-key message-mode-map "\C-c\C-r" 'message-caesar-buffer-body)
   (define-key message-mode-map "\C-c\C-o" 'message-sort-headers)
   (define-key message-mode-map "\C-c\M-r" 'message-rename-buffer)
@@ -1189,141 +2442,326 @@ Return the number of headers removed."
   (define-key message-mode-map "\C-c\C-s" 'message-send)
   (define-key message-mode-map "\C-c\C-k" 'message-kill-buffer)
   (define-key message-mode-map "\C-c\C-d" 'message-dont-send)
+  (define-key message-mode-map "\C-c\n" 'gnus-delay-article)
 
   (define-key message-mode-map "\C-c\C-e" 'message-elide-region)
   (define-key message-mode-map "\C-c\C-v" 'message-delete-not-region)
   (define-key message-mode-map "\C-c\C-z" 'message-kill-to-signature)
   (define-key message-mode-map "\M-\r" 'message-newline-and-reformat)
+  ;;(define-key message-mode-map "\M-q" 'message-fill-paragraph)
+  (define-key message-mode-map [remap split-line]  'message-split-line)
 
-  (define-key message-mode-map "\t" 'message-tab))
+  (define-key message-mode-map "\C-a" 'message-beginning-of-line)
+  (define-key message-mode-map "\t" 'message-tab)
+  (define-key message-mode-map "\M-;" 'comment-region)
+
+  (define-key message-mode-map "\C-xk" 'message-mimic-kill-buffer))
 
 (easy-menu-define
  message-mode-menu message-mode-map "Message Menu."
- '("Message"
-   ["Sort Headers" message-sort-headers t]
+ `("Message"
    ["Yank Original" message-yank-original t]
    ["Fill Yanked Message" message-fill-yanked-message t]
    ["Insert Signature" message-insert-signature t]
    ["Caesar (rot13) Message" message-caesar-buffer-body t]
-   ["Caesar (rot13) Region" message-caesar-region (mark t)]
-   ["Elide Region" message-elide-region (mark t)]
-   ["Delete Outside Region" message-delete-not-region (mark t)]
+   ["Caesar (rot13) Region" message-caesar-region (message-mark-active-p)]
+   ["Elide Region" message-elide-region
+    :active (message-mark-active-p)
+    ,@(if (featurep 'xemacs) nil
+       '(:help "Replace text in region with an ellipsis"))]
+   ["Delete Outside Region" message-delete-not-region
+    :active (message-mark-active-p)
+    ,@(if (featurep 'xemacs) nil
+       '(:help "Delete all quoted text outside region"))]
    ["Kill To Signature" message-kill-to-signature t]
    ["Newline and Reformat" message-newline-and-reformat t]
    ["Rename buffer" message-rename-buffer t]
-   ["Spellcheck" ispell-message t]
+   ["Spellcheck" ispell-message
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Spellcheck this message"))]
+   ["Attach file as MIME" mime-edit-insert-file
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Attach a file at point"))]
    "----"
-   ["Send Message" message-send-and-exit t]
-   ["Abort Message" message-dont-send t]))
+   ["Insert Region Marked" message-mark-inserted-region
+    :active (message-mark-active-p)
+    ,@(if (featurep 'xemacs) nil
+       '(:help "Mark region with enclosing tags"))]
+   ["Insert File Marked..." message-mark-insert-file
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Insert file at point marked with enclosing tags"))]
+   "----"
+   ["Send Message" message-send-and-exit
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Send this message"))]
+   ["Postpone Message" message-dont-send
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "File this draft message and exit"))]
+   ["Send at Specific Time..." gnus-delay-article
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Ask, then arrange to send message at that time"))]
+   ["Kill Message" message-kill-buffer
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Delete this message without sending"))]))
 
 (easy-menu-define
  message-mode-field-menu message-mode-map ""
- '("Field"
-   ["Fetch To" message-insert-to t]
-   ["Fetch Newsgroups" message-insert-newsgroups t]
-   "----"
+ `("Field"
    ["To" message-goto-to t]
+   ["From" message-goto-from t]
    ["Subject" message-goto-subject t]
+   ["Change subject..." message-change-subject t]
    ["Cc" message-goto-cc t]
+   ["Bcc" message-goto-bcc t]
+   ["Fcc" message-goto-fcc t]
    ["Reply-To" message-goto-reply-to t]
+   ["Flag As Important" message-insert-importance-high
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Mark this message as important"))]
+   ["Flag As Unimportant" message-insert-importance-low
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Mark this message as unimportant"))]
+   ["Request Receipt"
+    message-insert-disposition-notification-to
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Request a receipt notification"))]
+   "----"
+   ;; (typical) news stuff
    ["Summary" message-goto-summary t]
    ["Keywords" message-goto-keywords t]
    ["Newsgroups" message-goto-newsgroups t]
+   ["Fetch Newsgroups" message-insert-newsgroups t]
    ["Followup-To" message-goto-followup-to t]
+   ;; ["Followup-To (with note in body)" message-cross-post-followup-to t]
+   ["Crosspost / Followup-To..." message-cross-post-followup-to t]
    ["Distribution" message-goto-distribution t]
-   ["Body" message-goto-body t]
-   ["Signature" message-goto-signature t]))
+   ["X-No-Archive:" message-add-archive-header t ]
+   "----"
+   ;; (typical) mailing-lists stuff
+   ["Fetch To" message-insert-to
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Insert a To header that points to the author."))]
+   ["Fetch To and Cc" message-insert-wide-reply
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help
+         "Insert To and Cc headers as if you were doing a wide reply."))]
+   "----"
+   ["Send to list only" message-to-list-only t]
+   ["Mail-Followup-To" message-goto-mail-followup-to t]
+   ["Mail-Reply-To" message-goto-mail-reply-to t]
+   ["Mail-Copies-To" message-goto-mail-copies-to t]
+   ["Unsubscribed list post" message-generate-unsubscribed-mail-followup-to
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Insert a reasonable `Mail-Followup-To:' header."))]
+   ["Reduce To: to Cc:" message-reduce-to-to-cc t]
+   "----"
+   ["Sort Headers" message-sort-headers t]
+   ["Encode non-ASCII domain names" message-idna-to-ascii-rhs t]
+   ["Goto Body" message-goto-body t]
+   ["Goto Signature" message-goto-signature t]))
+
+(defvar message-tool-bar-map nil)
+
+(eval-when-compile
+  (defvar facemenu-add-face-function)
+  (defvar facemenu-remove-face-function))
+
+;;; Forbidden properties
+;;
+;; We use `after-change-functions' to keep special text properties
+;; that interfer with the normal function of message mode out of the
+;; buffer.
+
+(defcustom message-strip-special-text-properties t
+  "Strip special properties from the message buffer.
+
+Emacs has a number of special text properties which can break message
+composing in various ways.  If this option is set, message will strip
+these properties from the message composition buffer.  However, some
+packages requires these properties to be present in order to work.
+If you use one of these packages, turn this option off, and hope the
+message composition doesn't break too bad."
+  :group 'message-various
+  :link '(custom-manual "(message)Various Message Variables")
+  :type 'boolean)
 
-(defvar facemenu-add-face-function)
-(defvar facemenu-remove-face-function)
+(defconst message-forbidden-properties
+  ;; No reason this should be clutter up customize.  We make it a
+  ;; property list (rather than a list of property symbols), to be
+  ;; directly useful for `remove-text-properties'.
+  '(field nil read-only nil invisible nil intangible nil
+         mouse-face nil modification-hooks nil insert-in-front-hooks nil
+         insert-behind-hooks nil point-entered nil point-left nil)
+  ;; Other special properties:
+  ;; category, face, display: probably doesn't do any harm.
+  ;; fontified: is used by font-lock.
+  ;; syntax-table, local-map: I dunno.
+  ;; We need to add XEmacs names to the list.
+  "Property list of with properties.forbidden in message buffers.
+The values of the properties are ignored, only the property names are used.")
+
+(defun message-tamago-not-in-use-p (pos)
+  "Return t when tamago version 4 is not in use at the cursor position.
+Tamago version 4 is a popular input method for writing Japanese text.
+It uses the properties `intangible', `invisible', `modification-hooks'
+and `read-only' when translating ascii or kana text to kanji text.
+These properties are essential to work, so we should never strip them."
+  (not (and (boundp 'egg-modefull-mode)
+           (symbol-value 'egg-modefull-mode)
+           (or (memq (get-text-property pos 'intangible)
+                     '(its-part-1 its-part-2))
+               (get-text-property pos 'egg-end)
+               (get-text-property pos 'egg-lang)
+               (get-text-property pos 'egg-start)))))
+
+(defun message-strip-forbidden-properties (begin end &optional old-length)
+  "Strip forbidden properties between BEGIN and END, ignoring the third arg.
+This function is intended to be called from `after-change-functions'.
+See also `message-forbidden-properties'."
+  (when (and message-strip-special-text-properties
+            (message-tamago-not-in-use-p begin)
+            ;; Check whether the invisible MIME part is not inserted.
+            (not (text-property-any begin end 'mime-edit-invisible t)))
+    (while (not (= begin end))
+      (when (not (get-text-property begin 'message-hidden))
+       (remove-text-properties begin (1+ begin)
+                               message-forbidden-properties))
+      (incf begin))))
 
 ;;;###autoload
-(defun message-mode ()
+(define-derived-mode message-mode text-mode "Message"
   "Major mode for editing mail and news to be sent.
-Like Text Mode but with these additional commands:
-C-c C-s  message-send (send the message)    C-c C-c  message-send-and-exit
+Like Text Mode but with these additional commands:\\<message-mode-map>
+C-c C-s  `message-send' (send the message)  C-c C-c  `message-send-and-exit'
+C-c C-d  Postpone sending the message       C-c C-k  Kill the message
 C-c C-f  move to a header field (and create it if there isn't):
         C-c C-f C-t  move to To        C-c C-f C-s  move to Subject
         C-c C-f C-c  move to Cc        C-c C-f C-b  move to Bcc
         C-c C-f C-w  move to Fcc       C-c C-f C-r  move to Reply-To
         C-c C-f C-u  move to Summary   C-c C-f C-n  move to Newsgroups
         C-c C-f C-k  move to Keywords  C-c C-f C-d  move to Distribution
+         C-c C-f C-o  move to From (\"Originator\")
         C-c C-f C-f  move to Followup-To
-C-c C-t  message-insert-to (add a To header to a news followup)
-C-c C-n  message-insert-newsgroups (add a Newsgroup header to a news reply)
-C-c C-b  message-goto-body (move to beginning of message text).
-C-c C-i  message-goto-signature (move to the beginning of the signature).
-C-c C-w  message-insert-signature (insert `message-signature-file' file).
-C-c C-y  message-yank-original (insert current message, if any).
-C-c C-q  message-fill-yanked-message (fill what was yanked).
-C-c C-e  message-elide-region (elide the text between point and mark).
-C-c C-r  message-caesar-buffer-body (rot13 the message body)."
-  (interactive)
-  (kill-all-local-variables)
-  (make-local-variable 'message-reply-buffer)
-  (setq message-reply-buffer nil)
-  (make-local-variable 'message-send-actions) 
-  (make-local-variable 'message-exit-actions) 
-  (make-local-variable 'message-kill-actions)
-  (make-local-variable 'message-postpone-actions)
-  (make-local-variable 'message-draft-article)
-  (make-local-hook 'kill-buffer-hook)
-  (set-syntax-table message-mode-syntax-table)
-  (use-local-map message-mode-map)
-  (setq local-abbrev-table message-mode-abbrev-table)
-  (setq major-mode 'message-mode)
-  (setq mode-name "Message")
+        C-c C-f C-m  move to Mail-Followup-To
+        C-c C-f c    move to Mail-Copies-To
+        C-c C-f C-i  cycle through Importance values
+        C-c C-f s    change subject and append \"(was: <Old Subject>)\"
+        C-c C-f x    crossposting with FollowUp-To header and note in body
+        C-c C-f t    replace To: header with contents of Cc: or Bcc:
+        C-c C-f a    Insert X-No-Archive: header and a note in the body
+C-c C-t  `message-insert-to' (add a To header to a news followup)
+C-c C-l  `message-to-list-only' (removes all but list address in to/cc)
+C-c C-n  `message-insert-newsgroups' (add a Newsgroup header to a news reply)
+C-c C-b  `message-goto-body' (move to beginning of message text).
+C-c C-i  `message-goto-signature' (move to the beginning of the signature).
+C-c C-w  `message-insert-signature' (insert `message-signature-file' file).
+C-c C-y  `message-yank-original' (insert current message, if any).
+C-c C-q  `message-fill-yanked-message' (fill what was yanked).
+C-c C-e  `message-elide-region' (elide the text between point and mark).
+C-c C-v  `message-delete-not-region' (remove the text outside the region).
+C-c C-z  `message-kill-to-signature' (kill the text up to the signature).
+C-c C-r  `message-caesar-buffer-body' (rot13 the message body).
+C-c C-u  `message-insert-or-toggle-importance'  (insert or cycle importance).
+C-c M-n  `message-insert-disposition-notification-to'  (request receipt).
+C-c M-m  `message-mark-inserted-region' (mark region with enclosing tags).
+C-c M-f  `message-mark-insert-file' (insert file marked with enclosing tags).
+M-RET    `message-newline-and-reformat' (break the line and reformat)."
+  (setq local-abbrev-table text-mode-abbrev-table)
+  (set (make-local-variable 'message-reply-buffer) nil)
+  (set (make-local-variable 'message-inserted-headers) nil)
+  (set (make-local-variable 'message-send-actions) nil)
+  (set (make-local-variable 'message-exit-actions) nil)
+  (set (make-local-variable 'message-kill-actions) nil)
+  (set (make-local-variable 'message-postpone-actions) nil)
+  (set (make-local-variable 'message-draft-article) nil)
   (setq buffer-offer-save t)
-  (make-local-variable 'facemenu-add-face-function)
-  (make-local-variable 'facemenu-remove-face-function)
-  (setq facemenu-add-face-function
-       (lambda (face end)
-         (let ((face-fun (cdr (assq face message-face-alist))))
-           (if face-fun
-               (funcall face-fun (point) end)
-             (error "Face %s not configured for %s mode" face mode-name)))
-         "")
-       facemenu-remove-face-function t)
-  (make-local-variable 'paragraph-separate)
-  (make-local-variable 'paragraph-start)
-  (setq paragraph-start
-       (concat (regexp-quote mail-header-separator)
-               "$\\|[ \t]*[-_][-_][-_]+$\\|"
-               "-- $\\|"
-               ;;!!! Uhm... shurely this can't be right.
-               "[> " (regexp-quote message-yank-prefix) "]+$\\|"
-               paragraph-start))
-  (setq paragraph-separate
-       (concat (regexp-quote mail-header-separator)
-               "$\\|[ \t]*[-_][-_][-_]+$\\|"
-               "-- $\\|"
-               "[> " (regexp-quote message-yank-prefix) "]+$\\|"
-               paragraph-separate))
-  (make-local-variable 'message-reply-headers)
-  (setq message-reply-headers nil)
-  (make-local-variable 'message-newsreader)
-  (make-local-variable 'message-mailer)
+  (set (make-local-variable 'facemenu-add-face-function)
+       (lambda (face end)
+        (let ((face-fun (cdr (assq face message-face-alist))))
+          (if face-fun
+              (funcall face-fun (point) end)
+            (error "Face %s not configured for %s mode" face mode-name)))
+        ""))
+  (set (make-local-variable 'facemenu-remove-face-function) t)
+  (set (make-local-variable 'message-reply-headers) nil)
+  (make-local-variable 'message-user-agent)
   (make-local-variable 'message-post-method)
-  (make-local-variable 'message-sent-message-via)
-  (setq message-sent-message-via nil)
-  (make-local-variable 'message-checksum)
-  (setq message-checksum nil)
-  ;;(when (fboundp 'mail-hist-define-keys)
-  ;;  (mail-hist-define-keys))
-  (when (string-match "XEmacs\\|Lucid" emacs-version)
-    (message-setup-toolbar))
+  (set (make-local-variable 'message-sent-message-via) nil)
+  (set (make-local-variable 'message-checksum) nil)
+  (make-local-variable 'message-parameter-alist)
+  (setq message-parameter-alist
+       (copy-sequence message-startup-parameter-alist))
+  (message-setup-fill-variables)
+  (set
+   (make-local-variable 'paragraph-separate)
+   (format "\\(%s\\)\\|\\(%s\\)"
+          paragraph-separate
+          "<#!*/?\\(multipart\\|part\\|external\\|mml\\|secure\\)"))
+  ;; Allow using comment commands to add/remove quoting.
+  (set (make-local-variable 'comment-start) message-yank-prefix)
+  (if (featurep 'xemacs)
+      (message-setup-toolbar)
+    (set (make-local-variable 'font-lock-defaults)
+        '(message-font-lock-keywords t))
+    (if (boundp 'tool-bar-map)
+       (set (make-local-variable 'tool-bar-map) (message-tool-bar-map))))
   (easy-menu-add message-mode-menu message-mode-map)
   (easy-menu-add message-mode-field-menu message-mode-map)
+  (gnus-make-local-hook 'after-change-functions)
+  ;; Mmmm... Forbidden properties...
+  (add-hook 'after-change-functions 'message-strip-forbidden-properties
+           nil 'local)
   ;; Allow mail alias things.
   (when (eq message-mail-alias-type 'abbrev)
     (if (fboundp 'mail-abbrevs-setup)
        (mail-abbrevs-setup)
-      (funcall (intern "mail-aliases-setup"))))
-  (message-set-auto-save-file-name)
-  (unless (string-match "XEmacs" emacs-version)
-    (set (make-local-variable 'font-lock-defaults)
-        '(message-font-lock-keywords t)))
-  (run-hooks 'text-mode-hook 'message-mode-hook))
+      (if (fboundp 'mail-aliases-setup)        ; warning avoidance
+         (mail-aliases-setup))))
+  (unless buffer-file-name
+    (message-set-auto-save-file-name))
+  (set (make-local-variable 'indent-tabs-mode) nil)) ;No tabs for indentation.
+
+(defun message-setup-fill-variables ()
+  "Setup message fill variables."
+  (set (make-local-variable 'fill-paragraph-function)
+       'message-fill-paragraph)
+  (make-local-variable 'paragraph-separate)
+  (make-local-variable 'paragraph-start)
+  (make-local-variable 'adaptive-fill-regexp)
+  (unless (boundp 'adaptive-fill-first-line-regexp)
+    (setq adaptive-fill-first-line-regexp nil))
+  (make-local-variable 'adaptive-fill-first-line-regexp)
+  (let ((quote-prefix-regexp
+        ;; User should change message-cite-prefix-regexp if
+        ;; message-yank-prefix is set to an abnormal value.
+        (concat "\\(" message-cite-prefix-regexp "\\)[ \t]*")))
+    (setq paragraph-start
+         (concat
+          (regexp-quote mail-header-separator) "$\\|"
+          "[ \t]*$\\|"                 ; blank lines
+          "-- $\\|"                    ; signature delimiter
+          "---+$\\|"                   ; delimiters for forwarded messages
+          page-delimiter "$\\|"        ; spoiler warnings
+          ".*wrote:$\\|"               ; attribution lines
+          quote-prefix-regexp "$"))    ; empty lines in quoted text
+    (setq paragraph-separate paragraph-start)
+    (setq adaptive-fill-regexp
+         (concat quote-prefix-regexp "\\|" adaptive-fill-regexp))
+    (setq adaptive-fill-first-line-regexp
+         (concat quote-prefix-regexp "\\|"
+                 adaptive-fill-first-line-regexp)))
+  (make-local-variable 'auto-fill-inhibit-regexp)
+  ;;(setq auto-fill-inhibit-regexp "^[A-Z][^: \n\t]+:")
+  (setq auto-fill-inhibit-regexp nil)
+  (make-local-variable 'normal-auto-fill-function)
+  (setq normal-auto-fill-function 'message-do-auto-fill)
+  ;; KLUDGE: auto fill might already be turned on in `text-mode-hook'.
+  ;; In that case, ensure that it uses the right function.  The real
+  ;; solution would be not to use `define-derived-mode', and run
+  ;; `text-mode-hook' ourself at the end of the mode.
+  ;; -- Per Abrahamsen <abraham@dina.kvl.dk> Date: 2001-10-19.
+  (when auto-fill-function
+    (setq auto-fill-function normal-auto-fill-function)))
 
 \f
 
@@ -1338,6 +2776,11 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
   (interactive)
   (message-position-on-field "To"))
 
+(defun message-goto-from ()
+  "Move point to the From header."
+  (interactive)
+  (message-position-on-field "From"))
+
 (defun message-goto-subject ()
   "Move point to the Subject header."
   (interactive)
@@ -1363,6 +2806,19 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
   (interactive)
   (message-position-on-field "Reply-To" "Subject"))
 
+(defun message-goto-mail-reply-to ()
+  "Move point to the Mail-Reply-To header."
+  (interactive)
+  (message-position-on-field "Mail-Reply-To" "Subject"))
+
+(defun message-goto-mail-copies-to ()
+  "Move point to the Mail-Copies-To header.  If the header is newly created,
+a string \"never\" is inserted in default."
+  (interactive)
+  (unless (message-position-on-field "Mail-Copies-To" "Subject")
+    (insert "never")
+    (backward-char 5)))
+
 (defun message-goto-newsgroups ()
   "Move point to the Newsgroups header."
   (interactive)
@@ -1378,6 +2834,23 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
   (interactive)
   (message-position-on-field "Followup-To" "Newsgroups"))
 
+(defun message-goto-mail-followup-to ()
+  "Move point to the Mail-Followup-To header.  If the header is newly created
+and To field contains only one address, the address is inserted in default."
+  (interactive)
+  (unless (message-position-on-field "Mail-Followup-To" "Subject")
+    (let ((start (point))
+         addresses)
+      (save-restriction
+       (message-narrow-to-headers)
+       (setq addresses (split-string (mail-strip-quoted-names
+                                      (or (std11-fetch-field "to") ""))
+                                     "[ \f\t\n\r\v,]+"))
+       (when (eq 1 (length addresses))
+         (goto-char start)
+         (insert (car addresses))
+         (goto-char start))))))
+
 (defun message-goto-keywords ()
   "Move point to the Keywords header."
   (interactive)
@@ -1388,40 +2861,138 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
   (interactive)
   (message-position-on-field "Summary" "Subject"))
 
-(defun message-goto-body ()
+(defun message-goto-body (&optional interactivep)
   "Move point to the beginning of the message body."
-  (interactive)
-  (if (looking-at "[ \t]*\n") (expand-abbrev))
+  (interactive (list t))
+  (when (and interactivep
+            (looking-at "[ \t]*\n"))
+    (expand-abbrev))
   (goto-char (point-min))
-  (search-forward (concat "\n" mail-header-separator "\n") nil t))
+  (or (search-forward (concat "\n" mail-header-separator "\n") nil t)
+      (search-forward-regexp "[^:]+:\\([^\n]\\|\n[ \t]\\)+\n\n" nil t)))
+
+(defun message-goto-eoh ()
+  "Move point to the end of the headers."
+  (interactive)
+  (message-goto-body)
+  (forward-line -1))
 
 (defun message-goto-signature ()
-  "Move point to the beginning of the message signature."
+  "Move point to the beginning of the message signature.
+If there is no signature in the article, go to the end and
+return nil."
   (interactive)
   (goto-char (point-min))
   (if (re-search-forward message-signature-separator nil t)
       (forward-line 1)
-    (goto-char (point-max))))
+    (goto-char (point-max))
+    nil))
+
+(defun message-generate-unsubscribed-mail-followup-to (&optional include-cc)
+  "Insert a reasonable MFT header in a post to an unsubscribed list.
+When making original posts to a mailing list you are not subscribed to,
+you have to type in a MFT header by hand.  The contents, usually, are
+the addresses of the list and your own address.  This function inserts
+such a header automatically.  It fetches the contents of the To: header
+in the current mail buffer, and appends the current `user-mail-address'.
+
+If the optional argument INCLUDE-CC is non-nil, the addresses in the
+Cc: header are also put into the MFT."
+
+  (interactive "P")
+  (let* (cc tos)
+    (save-restriction
+      (message-narrow-to-headers)
+      (message-remove-header "Mail-Followup-To")
+      (setq cc (and include-cc (message-fetch-field "Cc")))
+      (setq tos (if cc
+                   (concat (message-fetch-field "To") "," cc)
+                 (message-fetch-field "To"))))
+    (message-goto-mail-followup-to)
+    (insert (concat tos ", " user-mail-address))))
 
 \f
 
 (defun message-insert-to (&optional force)
   "Insert a To header that points to the author of the article being replied to.
-If the original author requested not to be sent mail, the function signals
-an error.
-With the prefix argument FORCE, insert the header anyway."
+If the original author requested not to be sent mail, don't insert unless the
+prefix FORCE is given."
   (interactive "P")
-  (let ((co (message-fetch-reply-field "mail-copies-to")))
-    (when (and (null force)
-              co
-              (equal (downcase co) "never"))
-      (error "The user has requested not to have copies sent via mail")))
-  (when (and (message-position-on-field "To")
-            (mail-fetch-field "to")
-            (not (string-match "\\` *\\'" (mail-fetch-field "to"))))
-    (insert ", "))
-  (insert (or (message-fetch-reply-field "reply-to")
-             (message-fetch-reply-field "from") "")))
+  (let* ((mct (message-fetch-reply-field "mail-copies-to"))
+         (dont (and mct (or (equal (downcase mct) "never")
+                           (equal (downcase mct) "nobody"))))
+         (to (or (message-fetch-reply-field "mail-reply-to")
+                 (message-fetch-reply-field "reply-to")
+                 (message-fetch-reply-field "from"))))
+    (when (and dont to)
+      (message
+       (if force
+          "Ignoring the user request not to have copies sent via mail"
+        "Complying with the user request not to have copies sent via mail")))
+    (when (and force (not to))
+      (error "No mail address in the article"))
+    (when (and to (or force (not dont)))
+      (message-carefully-insert-headers (list (cons 'To to))))))
+
+(defun message-insert-wide-reply ()
+  "Insert To and Cc headers as if you were doing a wide reply."
+  (interactive)
+  (let ((headers (message-with-reply-buffer
+                  (message-get-reply-headers t))))
+    (message-carefully-insert-headers headers)))
+
+(defcustom message-header-synonyms
+  '((To Cc Bcc))
+  "List of lists of header synonyms.
+E.g., if this list contains a member list with elements `Cc' and `To',
+then `message-carefully-insert-headers' will not insert a `To' header
+when the message is already `Cc'ed to the recipient."
+  :group 'message-headers
+  :link '(custom-manual "(message)Message Headers")
+  :type '(repeat sexp))
+
+(defun message-carefully-insert-headers (headers)
+  "Insert the HEADERS, an alist, into the message buffer.
+Does not insert the headers when they are already present there
+or in the synonym headers, defined by `message-header-synonyms'."
+  ;; FIXME: Should compare only the address and not the full name.  Comparison
+  ;; should be done case-folded (and with `string=' rather than
+  ;; `string-match').
+  (dolist (header headers)
+    (let* ((header-name (symbol-name (car header)))
+           (new-header (cdr header))
+           (synonyms (loop for synonym in message-header-synonyms
+                          when (memq (car header) synonym) return synonym))
+           (old-header
+            (loop for synonym in synonyms
+                 for old-header = (mail-fetch-field (symbol-name synonym))
+                 when (and old-header (string-match new-header old-header))
+                 return synonym)))
+      (if old-header
+          (message "already have `%s' in `%s'" new-header old-header)
+       (when (and (message-position-on-field header-name)
+                   (setq old-header (mail-fetch-field header-name))
+                   (not (string-match "\\` *\\'" old-header)))
+         (insert ", "))
+        (insert new-header)))))
+
+(defun message-widen-reply ()
+  "Widen the reply to include maximum recipients."
+  (interactive)
+  (let ((follow-to
+        (and message-reply-buffer
+             (buffer-name message-reply-buffer)
+             (save-excursion
+               (set-buffer message-reply-buffer)
+               (message-get-reply-headers t)))))
+    (save-excursion
+      (save-restriction
+       (message-narrow-to-headers)
+       (dolist (elem follow-to)
+         (message-remove-header (symbol-name (car elem)))
+         (goto-char (point-min))
+         (insert (symbol-name (car elem)) ": "
+                 (cdr elem) "\n"))))))
 
 (defun message-insert-newsgroups ()
   "Insert the Newsgroups header from the article being replied to."
@@ -1437,20 +3008,29 @@ With the prefix argument FORCE, insert the header anyway."
 ;;; Various commands
 
 (defun message-delete-not-region (beg end)
-  "Delete everything in the body of the current message that is outside of the region."
+  "Delete everything in the body of the current message outside of the region."
   (interactive "r")
-  (save-excursion
-    (goto-char end)
-    (delete-region (point) (progn (message-goto-signature)
-                                 (forward-line -2)
-                                 (point)))
-    (insert "\n")
-    (goto-char beg)
-    (delete-region beg (progn (message-goto-body)
-                             (forward-line 2)
-                             (point))))
-  (message-goto-signature)
-  (forward-line -2))
+  (let (citeprefix)
+    (save-excursion
+      (goto-char beg)
+      ;; snarf citation prefix, if appropriate
+      (unless (eq (point) (progn (beginning-of-line) (point)))
+       (when (looking-at message-cite-prefix-regexp)
+         (setq citeprefix (match-string 0))))
+      (goto-char end)
+      (delete-region (point) (if (not (message-goto-signature))
+                                (point)
+                              (forward-line -2)
+                              (point)))
+      (insert "\n")
+      (goto-char beg)
+      (delete-region beg (progn (message-goto-body)
+                               (forward-line 2)
+                               (point)))
+      (when citeprefix
+       (insert citeprefix))))
+  (when (message-goto-signature)
+    (forward-line -2)))
 
 (defun message-kill-to-signature ()
   "Deletes all text up to the signature."
@@ -1458,28 +3038,124 @@ With the prefix argument FORCE, insert the header anyway."
   (let ((point (point)))
     (message-goto-signature)
     (unless (eobp)
-      (forward-line -2))
+      (end-of-line -1))
     (kill-region point (point))
     (unless (bolp)
       (insert "\n"))))
 
-(defun message-newline-and-reformat ()
-  "Insert four newlines, and then reformat if inside quoted text."
-  (interactive)
-  (let ((point (point))
-       quoted)
-    (save-excursion
-      (beginning-of-line)
-      (setq quoted (looking-at (regexp-quote message-yank-prefix))))
-    (insert "\n\n\n\n")
-    (when quoted
-      (insert message-yank-prefix))
-    (fill-paragraph nil)
+(defun message-newline-and-reformat (&optional arg not-break)
+  "Insert four newlines, and then reformat if inside quoted text.
+Prefix arg means justify as well."
+  (interactive (list (if current-prefix-arg 'full)))
+  (let (quoted point beg end leading-space bolp)
+    (setq point (point))
+    (beginning-of-line)
+    (setq beg (point))
+    (setq bolp (= beg point))
+    ;; Find first line of the paragraph.
+    (if not-break
+       (while (and (not (eobp))
+                   (not (looking-at message-cite-prefix-regexp))
+                   (looking-at paragraph-start))
+         (forward-line 1)))
+    ;; Find the prefix
+    (when (looking-at message-cite-prefix-regexp)
+      (setq quoted (match-string 0))
+      (goto-char (match-end 0))
+      (looking-at "[ \t]*")
+      (setq leading-space (match-string 0)))
+    (if (and quoted
+            (not not-break)
+            (not bolp)
+            (< (- point beg) (length quoted)))
+       ;; break inside the cite prefix.
+       (setq quoted nil
+             end nil))
+    (if quoted
+       (progn
+         (forward-line 1)
+         (while (and (not (eobp))
+                     (not (looking-at paragraph-separate))
+                     (looking-at message-cite-prefix-regexp)
+                     (equal quoted (match-string 0)))
+           (goto-char (match-end 0))
+           (looking-at "[ \t]*")
+           (if (> (length leading-space) (length (match-string 0)))
+               (setq leading-space (match-string 0)))
+           (forward-line 1))
+         (setq end (point))
+         (goto-char beg)
+         (while (and (if (bobp) nil (forward-line -1) t)
+                     (not (looking-at paragraph-start))
+                     (looking-at message-cite-prefix-regexp)
+                     (equal quoted (match-string 0)))
+           (setq beg (point))
+           (goto-char (match-end 0))
+           (looking-at "[ \t]*")
+           (if (> (length leading-space) (length (match-string 0)))
+               (setq leading-space (match-string 0)))))
+      (while (and (not (eobp))
+                 (not (looking-at paragraph-separate))
+                 (not (looking-at message-cite-prefix-regexp)))
+       (forward-line 1))
+      (setq end (point))
+      (goto-char beg)
+      (while (and (if (bobp) nil (forward-line -1) t)
+                 (not (looking-at paragraph-start))
+                 (not (looking-at message-cite-prefix-regexp)))
+       (setq beg (point))))
     (goto-char point)
-    (forward-line 2)))
+    (save-restriction
+      (narrow-to-region beg end)
+      (if not-break
+         (setq point nil)
+       (if bolp
+           (newline)
+         (newline)
+         (newline))
+       (setq point (point))
+       ;; (newline 2) doesn't mark both newline's as hard, so call
+       ;; newline twice. -jas
+       (newline)
+       (newline)
+       (delete-region (point) (re-search-forward "[ \t]*"))
+       (when (and quoted (not bolp))
+         (insert quoted leading-space)))
+      (undo-boundary)
+      (if quoted
+         (let* ((adaptive-fill-regexp
+                 (regexp-quote (concat quoted leading-space)))
+                (adaptive-fill-first-line-regexp
+                 adaptive-fill-regexp ))
+           (fill-paragraph arg))
+       (fill-paragraph arg))
+      (if point (goto-char point)))))
+
+(defun message-fill-paragraph (&optional arg)
+  "Like `fill-paragraph'."
+  (interactive (list (if current-prefix-arg 'full)))
+  (if (if (boundp 'filladapt-mode) filladapt-mode)
+      nil
+    (message-newline-and-reformat arg t)
+    t))
+
+;; Is it better to use `mail-header-end'?
+(defun message-point-in-header-p ()
+  "Return t if point is in the header."
+  (save-excursion
+    (let ((p (point)))
+      (goto-char (point-min))
+      (not (re-search-forward
+           (concat "^" (regexp-quote mail-header-separator) "\n")
+           p t)))))
+
+(defun message-do-auto-fill ()
+  "Like `do-auto-fill', but don't fill in message header."
+  (unless (message-point-in-header-p)
+    (do-auto-fill)))
 
 (defun message-insert-signature (&optional force)
-  "Insert a signature.  See documentation for the `message-signature' variable."
+  "Insert a signature.  See documentation for variable `message-signature'."
   (interactive (list 0))
   (let* ((signature
          (cond
@@ -1487,12 +3163,11 @@ With the prefix argument FORCE, insert the header anyway."
                 (eq force 0))
            (save-excursion
              (goto-char (point-max))
-             (not (re-search-backward
-                   message-signature-separator nil t))))
+             (not (re-search-backward message-signature-separator nil t))))
           ((and (null message-signature)
                 force)
            t)
-          ((message-functionp message-signature)
+          ((functionp message-signature)
            (funcall message-signature))
           ((listp message-signature)
            (eval message-signature))
@@ -1509,27 +3184,85 @@ With the prefix argument FORCE, insert the header anyway."
       ;; Insert the signature.
       (unless (bolp)
        (insert "\n"))
-      (insert "\n-- \n")
+      (when message-signature-insert-empty-line
+       (insert "\n"))
+      (insert "\n" message-signature-separator-for-insertion)
+      (unless (bolp)
+       (insert "\n"))
       (if (eq signature t)
          (insert-file-contents message-signature-file)
        (insert signature))
       (goto-char (point-max))
       (or (bolp) (insert "\n")))))
 
+(defun message-insert-importance-high ()
+  "Insert header to mark message as important."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (message-remove-header "Importance"))
+    (message-goto-eoh)
+    (insert "Importance: high\n")))
+
+(defun message-insert-importance-low ()
+  "Insert header to mark message as unimportant."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (message-remove-header "Importance"))
+    (message-goto-eoh)
+    (insert "Importance: low\n")))
+
+(defun message-insert-or-toggle-importance ()
+  "Insert a \"Importance: high\" header, or cycle through the header values.
+The three allowed values according to RFC 1327 are `high', `normal'
+and `low'."
+  (interactive)
+  (save-excursion
+    (let ((valid '("high" "normal" "low"))
+         (new "high")
+         cur)
+      (save-restriction
+       (message-narrow-to-headers)
+       (when (setq cur (message-fetch-field "Importance"))
+         (message-remove-header "Importance")
+         (setq new (cond ((string= cur "high")
+                          "low")
+                         ((string= cur "low")
+                          "normal")
+                         (t
+                          "high")))))
+      (message-goto-eoh)
+      (insert (format "Importance: %s\n" new)))))
+
+(defun message-insert-disposition-notification-to ()
+  "Request a disposition notification (return receipt) to this message.
+Note that this should not be used in newsgroups."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (message-remove-header "Disposition-Notification-To"))
+    (message-goto-eoh)
+    (insert (format "Disposition-Notification-To: %s\n"
+                   (or (message-field-value "Reply-to")
+                       (message-field-value "From")
+                       (message-make-from))))))
+
 (defun message-elide-region (b e)
-  "Elide the text between point and mark.
-An ellipsis (from `message-elide-elipsis') will be inserted where the
+  "Elide the text in the region.
+An ellipsis (from `message-elide-ellipsis') will be inserted where the
 text was killed."
   (interactive "r")
   (kill-region b e)
-  (unless (bolp)
-    (insert "\n"))
-  (insert message-elide-elipsis))
+  (insert message-elide-ellipsis))
 
 (defvar message-caesar-translation-table nil)
 
 (defun message-caesar-region (b e &optional n)
-  "Caesar rotation of region by N, default 13, for decrypting netnews."
+  "Caesar rotate region B to E by N, default 13, for decrypting netnews."
   (interactive
    (list
     (min (point) (or (mark t) (point)))
@@ -1543,15 +3276,9 @@ text was killed."
     ;; We build the table, if necessary.
     (when (or (not message-caesar-translation-table)
              (/= (aref message-caesar-translation-table ?a) (+ ?a n)))
-       (setq message-caesar-translation-table
-             (message-make-caesar-translation-table n)))
-    ;; Then we translate the region.  Do it this way to retain
-    ;; text properties.
-    (while (< b e)
-      (subst-char-in-region
-       b (1+ b) (char-after b)
-       (aref message-caesar-translation-table (char-after b)))
-      (incf b))))
+      (setq message-caesar-translation-table
+           (message-make-caesar-translation-table n)))
+    (translate-region b e message-caesar-translation-table)))
 
 (defun message-make-caesar-translation-table (n)
   "Create a rot table with offset N."
@@ -1569,8 +3296,8 @@ text was killed."
      (substring table (+ ?a 26) 255))))
 
 (defun message-caesar-buffer-body (&optional rotnum)
-  "Caesar rotates all letters in the current buffer by 13 places.
-Used to encode/decode possiblyun offensive messages (commonly in net.jokes).
+  "Caesar rotate all letters in the current buffer by 13 places.
+Used to encode/decode possibly offensive messages (commonly in rec.humor).
 With prefix arg, specifies the number of places to rotate each letter forward.
 Mail and USENET news headers are not rotated."
   (interactive (if current-prefix-arg
@@ -1587,12 +3314,9 @@ Mail and USENET news headers are not rotated."
   (save-excursion
     (save-restriction
       (when (message-goto-body)
-        (narrow-to-region (point) (point-max)))
-      (let ((body (buffer-substring (point-min) (point-max))))
-        (unless (equal 0 (call-process-region
-                           (point-min) (point-max) program t t))
-            (insert body)
-            (message "%s failed." program))))))
+       (narrow-to-region (point) (point-max)))
+      (shell-command-on-region
+       (point-min) (point-max) program nil t))))
 
 (defun message-rename-buffer (&optional enter-string)
   "Rename the *message* buffer to \"*message* RECIPIENT\".
@@ -1615,11 +3339,7 @@ name, rather than giving an automatic name."
             (name-default (concat "*message* " mail-trimmed-to))
             (name (if enter-string
                       (read-string "New buffer name: " name-default)
-                    name-default))
-            (default-directory
-              (if message-autosave-directory
-                  (file-name-as-directory message-autosave-directory)
-                default-directory)))
+                    name-default)))
        (rename-buffer name t)))))
 
 (defun message-fill-yanked-message (&optional justifyp)
@@ -1630,7 +3350,7 @@ Numeric argument means justify as well."
     (goto-char (point-min))
     (search-forward (concat "\n" mail-header-separator "\n") nil t)
     (let ((fill-prefix message-yank-prefix))
-      (fill-individual-paragraphs (point) (point-max) justifyp t))))
+      (fill-individual-paragraphs (point) (point-max) justifyp))))
 
 (defun message-indent-citation ()
   "Modify text just inserted from a message to be cited.
@@ -1663,7 +3383,7 @@ However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
       (message-delete-line))
     ;; Delete blank lines at the end of the buffer.
     (goto-char (point-max))
-    (unless (eolp)
+    (unless (bolp)
       (insert "\n"))
     (while (and (zerop (forward-line -1))
                (looking-at "$"))
@@ -1674,10 +3394,36 @@ However, if `message-yank-prefix' is non-nil, insert that prefix on each line."
       (save-excursion
        (goto-char start)
        (while (< (point) (mark t))
-         (insert message-yank-prefix)
+         (if (or (looking-at ">") (looking-at "^$"))
+             (insert message-yank-cited-prefix)
+           (insert message-yank-prefix))
          (forward-line 1))))
     (goto-char start)))
 
+(defun message-list-references (refs-list &rest refs-strs)
+  "Add `Message-ID's which appear in REFS-STRS but not in REFS-LIST,
+to REFS-LIST."
+  (let (refs ref id saved-id)
+    (when (and refs-list
+              (integerp message-list-references-add-position))
+      (let ((pos message-list-references-add-position))
+       (while (and refs-list
+                   (> pos 0))
+         (push (pop refs-list) saved-id)
+         (setq pos (1- pos)))))
+    (while refs-strs
+      (when (setq refs (pop refs-strs))
+       (setq refs (std11-parse-msg-ids (std11-lexical-analyze refs)))
+       (while refs
+         (when (eq (car (setq ref (pop refs))) 'msg-id)
+           (setq id (concat "<" (mapconcat 'cdr (cdr ref) "") ">"))
+           (or (member id refs-list)
+               (member id saved-id)
+               (push id refs-list))))))
+    (while saved-id
+      (push (pop saved-id) refs-list))
+    refs-list))
+
 (defun message-yank-original (&optional arg)
   "Insert the message being replied to, if any.
 Puts point before the text and mark after.
@@ -1687,19 +3433,100 @@ if `message-yank-prefix' is non-nil, insert that prefix on each line.
 This function uses `message-cite-function' to do the actual citing.
 
 Just \\[universal-argument] as argument means don't indent, insert no
-prefix, and don't delete any headers."
+prefix, and don't delete any headers.
+
+In addition, if `message-yank-add-new-references' is non-nil and this
+command is called interactively, new IDs from the yanked article will
+be added to the \"References\" field."
   (interactive "P")
   (let ((modified (buffer-modified-p)))
-    (when (and message-reply-buffer
-              message-cite-function)
-      (delete-windows-on message-reply-buffer t)
-      (insert-buffer message-reply-buffer)
-      (funcall message-cite-function)
+    (when (let ((buffer (message-eval-parameter message-reply-buffer)))
+           (and buffer
+                message-cite-function
+                (prog1
+                    t
+                  (delete-windows-on buffer t)
+                  ; The mark will be set at the end of the article.
+                  (insert-buffer buffer))))
+      ;; Add new IDs to the References field.
+      (when (and message-yank-add-new-references
+                (interactive-p))
+       (let ((start (point))
+             (end (mark t))
+             refs newrefs)
+         (save-excursion
+           (save-restriction
+             (widen)
+             (setq refs (message-list-references
+                         nil
+                         (or (message-make-references)
+                             (prog2
+                                 (message-narrow-to-headers)
+                                 (message-fetch-field "References")
+                               (widen)))))
+             (narrow-to-region start end)
+             (std11-narrow-to-header)
+             (unless (equal (setq newrefs
+                                  (message-list-references
+                                   (copy-sequence refs)
+                                   (unless (eq message-yank-add-new-references
+                                               'message-id-only)
+                                     (or (message-fetch-field "References")
+                                         (message-fetch-field "In-Reply-To")))
+                                   (message-fetch-field "Message-ID")))
+                            refs)
+               ;; If the References field has been changed, we make it
+               ;; visible in the header.
+               (when message-reply-headers
+                 (mail-header-set-message-id message-reply-headers nil)
+                 (mail-header-set-references message-reply-headers nil))
+               (widen)
+               (message-narrow-to-headers)
+               (if (let ((case-fold-search t))
+                     (re-search-forward "^References:\\([\t ]+.+\n\\)+"
+                                        nil t))
+                   (replace-match "")
+                 (goto-char (point-max)))
+               (mail-header-format
+                (list (or (assq 'References message-header-format-alist)
+                          '(References . message-fill-references)))
+                (list (cons 'References (mapconcat 'identity
+                                                   (nreverse newrefs) " "))))
+               (backward-delete-char 1))))))
+      (unless arg
+       (if (and message-suspend-font-lock-when-citing
+                (boundp 'font-lock-mode)
+                (symbol-value 'font-lock-mode))
+           (unwind-protect
+               (progn
+                 (sit-for 0)
+                 (font-lock-mode 0)
+                 (funcall message-cite-function))
+             (font-lock-mode 1))
+         (funcall message-cite-function)))
       (message-exchange-point-and-mark)
       (unless (bolp)
        (insert ?\n))
       (unless modified
-       (setq message-checksum (cons (message-checksum) (buffer-size)))))))
+       (setq message-checksum (message-checksum))))))
+
+(defun message-yank-buffer (buffer)
+  "Insert BUFFER into the current buffer and quote it."
+  (interactive "bYank buffer: ")
+  (let ((message-reply-buffer (get-buffer buffer)))
+    (save-window-excursion
+      (message-yank-original))))
+
+(defun message-buffers ()
+  "Return a list of active message buffers."
+  (let (buffers)
+    (save-excursion
+      (dolist (buffer (buffer-list t))
+       (set-buffer buffer)
+       (when (and (eq major-mode 'message-mode)
+                  (null message-sent-message-via))
+         (push (buffer-name buffer) buffers))))
+    (nreverse buffers)))
 
 (defun message-cite-original-without-signature ()
   "Cite function in the standard Message manner."
@@ -1709,10 +3536,31 @@ prefix, and don't delete any headers."
         (when message-indent-citation-function
           (if (listp message-indent-citation-function)
               message-indent-citation-function
-            (list message-indent-citation-function)))))
+            (list message-indent-citation-function))))
+       (message-reply-headers (or message-reply-headers
+                                  (make-mail-header))))
+    (mail-header-set-from message-reply-headers
+                         (save-restriction
+                           (narrow-to-region
+                            (point)
+                            (if (search-forward "\n\n" nil t)
+                                (1- (point))
+                              (point-max)))
+                           (or (message-fetch-field "from")
+                               "unknown sender")))
+    ;; Allow undoing.
+    (undo-boundary)
     (goto-char end)
-    (when (re-search-backward "^-- $" start t)
-      (delete-region (point) end))
+    (when (re-search-backward message-signature-separator start t)
+      ;; Also peel off any blank lines before the signature.
+      (forward-line -1)
+      (while (looking-at "^[ \t]*$")
+       (forward-line -1))
+      (forward-line 1)
+      (delete-region (point) end)
+      (unless (search-backward "\n\n" start t)
+       ;; Insert a blank line if it is peeled off.
+       (insert "\n")))
     (goto-char start)
     (while functions
       (funcall (pop functions)))
@@ -1721,24 +3569,40 @@ prefix, and don't delete any headers."
        (insert "\n"))
       (funcall message-citation-line-function))))
 
+(eval-when-compile (defvar mail-citation-hook))                ;Compiler directive
 (defun message-cite-original ()
   "Cite function in the standard Message manner."
-  (let ((start (point))
-       (functions
-        (when message-indent-citation-function
-          (if (listp message-indent-citation-function)
-              message-indent-citation-function
-            (list message-indent-citation-function)))))
-    (goto-char start)
-    (while functions
-      (funcall (pop functions)))
-    (when message-citation-line-function
-      (unless (bolp)
-       (insert "\n"))
-      (funcall message-citation-line-function))))
+  (if (and (boundp 'mail-citation-hook)
+          mail-citation-hook)
+      (run-hooks 'mail-citation-hook)
+    (let ((start (point))
+         (end (mark t))
+         (functions
+          (when message-indent-citation-function
+            (if (listp message-indent-citation-function)
+                message-indent-citation-function
+              (list message-indent-citation-function))))
+         (message-reply-headers (or message-reply-headers
+                                    (make-mail-header))))
+      (mail-header-set-from message-reply-headers
+                           (save-restriction
+                             (narrow-to-region
+                              (point)
+                              (if (search-forward "\n\n" nil t)
+                                  (1- (point))
+                                (point-max)))
+                             (or (message-fetch-field "from")
+                                 "unknown sender")))
+      (goto-char start)
+      (while functions
+       (funcall (pop functions)))
+      (when message-citation-line-function
+       (unless (bolp)
+         (insert "\n"))
+       (funcall message-citation-line-function)))))
 
 (defun message-insert-citation-line ()
-  "Function that inserts a simple citation line."
+  "Insert a simple citation line."
   (when message-reply-headers
     (insert (mail-header-from message-reply-headers) " writes:\n\n")))
 
@@ -1798,11 +3662,18 @@ The text will also be indented the normal way."
 ;;; Sending messages
 ;;;
 
+;; Avoid byte-compile warning.
+(defvar message-encoding-buffer nil)
+(defvar message-edit-buffer nil)
+(defvar message-mime-mode nil)
+
 (defun message-send-and-exit (&optional arg)
   "Send message like `message-send', then, if no errors, exit from mail buffer."
   (interactive "P")
   (let ((buf (current-buffer))
-       (actions message-exit-actions))
+       (actions message-exit-actions)
+       (frame (selected-frame))
+       (org-frame message-original-frame))
     (when (and (message-send arg)
               (buffer-name buf))
       (if message-kill-buffer-on-exit
@@ -1810,29 +3681,87 @@ The text will also be indented the normal way."
        (bury-buffer buf)
        (when (eq buf (current-buffer))
          (message-bury buf)))
-      (message-do-actions actions))))
+      (message-do-actions actions)
+      (message-delete-frame frame org-frame)
+      t)))
 
 (defun message-dont-send ()
-  "Don't send the message you have been editing."
+  "Don't send the message you have been editing.
+Instead, just auto-save the buffer and then bury it."
   (interactive)
   (set-buffer-modified-p t)
   (save-buffer)
-  (let ((actions message-postpone-actions))
+  (let ((actions message-postpone-actions)
+       (frame (selected-frame))
+       (org-frame message-original-frame))
     (message-bury (current-buffer))
-    (message-do-actions actions)))
+    (message-do-actions actions)
+    (message-delete-frame frame org-frame)))
 
 (defun message-kill-buffer ()
   "Kill the current buffer."
   (interactive)
   (when (or (not (buffer-modified-p))
-           (yes-or-no-p "Message modified; kill anyway? "))
-    (let ((actions message-kill-actions))
+           (eq t message-kill-buffer-query-function)
+           (funcall message-kill-buffer-query-function
+                    "The buffer modified; kill anyway? "))
+    (let ((actions message-kill-actions)
+         (draft-article message-draft-article)
+         (auto-save-file-name buffer-auto-save-file-name)
+         (file-name buffer-file-name)
+         (modified (buffer-modified-p))
+         (frame (selected-frame))
+         (org-frame message-original-frame))
       (setq buffer-file-name nil)
       (kill-buffer (current-buffer))
-      (message-do-actions actions))))
+      (when (and message-kill-buffer-and-remove-file
+                (or (and auto-save-file-name
+                         (file-exists-p auto-save-file-name))
+                    (and file-name
+                         (file-exists-p file-name)))
+                (yes-or-no-p (format "Remove the backup file%s? "
+                                     (if modified " too" ""))))
+       (ignore-errors
+         (delete-file auto-save-file-name))
+       (let ((message-draft-article draft-article))
+         (message-disassociate-draft)))
+      (message-do-actions actions)
+      (message-delete-frame frame org-frame)))
+  (message ""))
+
+(defun message-mimic-kill-buffer ()
+  "Kill the current buffer with query.  This is an imitation for
+`kill-buffer', but it will delete a message frame."
+  (interactive)
+  (let ((bufname (read-buffer (format "Kill buffer: (default %s) "
+                                     (buffer-name))))
+       message-kill-buffer-and-remove-file)
+    (when (or (not bufname)
+             (string-equal bufname "")
+             (string-equal bufname (buffer-name)))
+      (message-kill-buffer))))
+
+(defun message-delete-frame (frame org-frame)
+  "Delete frame for editing message."
+  (when (and (or (static-if (featurep 'xemacs)
+                    (device-on-window-system-p)
+                  window-system)
+                (>= emacs-major-version 20))
+            (or (and (eq message-delete-frame-on-exit t)
+                     (select-frame frame)
+                     (or (eq frame org-frame)
+                         (prog1
+                             (y-or-n-p "Delete this frame?")
+                           (message ""))))
+                (and (eq message-delete-frame-on-exit 'ask)
+                     (select-frame frame)
+                     (prog1
+                         (y-or-n-p "Delete this frame?")
+                       (message "")))))
+    (delete-frame frame)))
 
 (defun message-bury (buffer)
-  "Bury this mail buffer."
+  "Bury this mail BUFFER."
   (let ((newbuf (other-buffer buffer)))
     (bury-buffer buffer)
     (if (and (fboundp 'frame-parameters)
@@ -1843,10 +3772,12 @@ The text will also be indented the normal way."
 
 (defun message-send (&optional arg)
   "Send the message in the current buffer.
-If `message-interactive' is non-nil, wait for success indication
-or error messages, and inform user.
-Otherwise any failure is reported in a message back to
-the user from the mailer."
+If `message-interactive' is non-nil, wait for success indication or
+error messages, and inform user.
+Otherwise any failure is reported in a message back to the user from
+the mailer.
+The usage of ARG is defined by the instance that called Message.
+It should typically alter the sending method in some way or other."
   (interactive "P")
   ;; Disabled test.
   (when (or (buffer-modified-p)
@@ -1856,60 +3787,240 @@ the user from the mailer."
     (undo-boundary)
     (let ((inhibit-read-only t))
       (put-text-property (point-min) (point-max) 'read-only nil))
-    (message-fix-before-sending)
     (run-hooks 'message-send-hook)
-    (message "Sending...")
-    (let ((alist message-send-method-alist)
+    (message-fix-before-sending)
+    (message message-sending-message)
+    (let ((message-encoding-buffer
+          (message-generate-new-buffer-clone-locals " message encoding"))
+         (message-edit-buffer (current-buffer))
+         (message-mime-mode mime-edit-mode-flag)
+         (alist message-send-method-alist)
          (success t)
-         elem sent)
-      (while (and success
-                 (setq elem (pop alist)))
-       (when (and (or (not (funcall (cadr elem)))
-                      (and (or (not (memq (car elem)
-                                          message-sent-message-via))
-                               (y-or-n-p
-                                (format
-                                 "Already sent message via %s; resend? "
-                                 (car elem))))
-                           (setq success (funcall (caddr elem) arg)))))
-         (setq sent t)))
-      (when (and success sent)
-       (message-do-fcc)
-       ;;(when (fboundp 'mail-hist-put-headers-into-history)
-       ;; (mail-hist-put-headers-into-history))
-       (run-hooks 'message-sent-hook)
-       (message "Sending...done")
-       ;; Mark the buffer as unmodified and delete autosave.
-       (set-buffer-modified-p nil)
-       (delete-auto-save-file-if-necessary t)
-       (message-disassociate-draft)
-       ;; Delete other mail buffers and stuff.
-       (message-do-send-housekeeping)
-       (message-do-actions message-send-actions)
-       ;; Return success.
-       t))))
+         elem sent dont-barf-on-no-method
+         (message-options message-options))
+      (unwind-protect
+         (progn
+           (message-options-set-recipient)
+           (save-excursion
+             (set-buffer message-encoding-buffer)
+             (erase-buffer)
+             ;; ;; Avoid copying text props (except hard newlines).
+             ;; T-gnus change: copy all text props from the editing buffer
+             ;; into the encoding buffer.
+             (insert-buffer-substring message-edit-buffer)
+             (funcall message-encode-function)
+             (while (and success
+                         (setq elem (pop alist)))
+               (when (funcall (cadr elem))
+                 (when (and
+                        (or (not (memq (car elem)
+                                       message-sent-message-via))
+                            (message-fetch-field "supersedes")
+                            (if (or (message-gnksa-enable-p 'multiple-copies)
+                                    (not (eq (car elem) 'news)))
+                                (y-or-n-p
+                                 (format
+                                  "Already sent message via %s; resend? "
+                                  (car elem)))
+                              (error "Denied posting -- multiple copies")))
+                        (setq success (funcall (caddr elem) arg)))
+                   (setq sent t)))))
+           (unless
+               (or
+                sent
+                (not success)
+                (let ((fcc (message-fetch-field "Fcc"))
+                      (gcc (message-fetch-field "Gcc")))
+                  (when (or fcc gcc)
+                    (or
+                     (eq message-allow-no-recipients 'always)
+                     (and (not (eq message-allow-no-recipients 'never))
+                          (setq dont-barf-on-no-method
+                                (gnus-y-or-n-p
+                                 (format "No receiver, perform %s anyway? "
+                                         (cond ((and fcc gcc) "Fcc and Gcc")
+                                               (fcc "Fcc")
+                                               (t "Gcc"))))))))))
+             (error "No methods specified to send by"))
+           (when (or dont-barf-on-no-method
+                     (and success sent))
+             (message-do-fcc)
+             (save-excursion
+               (run-hooks 'message-sent-hook))
+             (message "Sending...done")
+             ;; Mark the buffer as unmodified and delete auto-save.
+             (set-buffer-modified-p nil)
+             (delete-auto-save-file-if-necessary t)
+             (message-disassociate-draft)
+             ;; Delete other mail buffers and stuff.
+             (message-do-send-housekeeping)
+             (message-do-actions message-send-actions)
+             ;; Return success.
+             t))
+       (kill-buffer message-encoding-buffer)))))
 
 (defun message-send-via-mail (arg)
-  "Send the current message via mail."  
+  "Send the current message via mail."
   (message-send-mail arg))
 
 (defun message-send-via-news (arg)
   "Send the current message via news."
-  (funcall message-send-news-function arg))
+  (message-send-news arg))
+
+(defmacro message-check (type &rest forms)
+  "Eval FORMS if TYPE is to be checked."
+  `(or (message-check-element ,type)
+       (save-excursion
+        ,@forms)))
+
+(put 'message-check 'lisp-indent-function 1)
+(put 'message-check 'edebug-form-spec '(form body))
+
+;; Advise the function `invisible-region'.
+(let (current-load-list)
+  (eval
+   `(defadvice invisible-region (around add-mime-edit-invisible (start end)
+                                       activate)
+      "Advised by T-gnus Message.
+Add the text property `mime-edit-invisible' to an invisible text when
+the buffer's major mode is `message-mode'.  The added property will be
+used to distinguish whether the invisible text is a MIME part or not."
+      ,(if (featurep 'xemacs)
+          '(if (eq ?\n (char-after start))
+               (setq start (1+ start)))
+        '(if (eq ?\n (char-after (1- end)))
+             (setq end (1- end))))
+      (setq ad-return-value
+           (if (eq 'message-mode major-mode)
+               (add-text-properties start end
+                                    '(invisible t mime-edit-invisible t))
+             (put-text-property start end 'invisible t))))))
+
+(defun message-text-with-property (prop)
+  "Return a list of all points where the text has PROP."
+  (let ((points nil)
+       (point (point-min)))
+    (save-excursion
+      (while (< point (point-max))
+       (when (get-text-property point prop)
+         (push point points))
+       (incf point)))
+    (nreverse points)))
 
 (defun message-fix-before-sending ()
   "Do various things to make the message nice before sending it."
   ;; Make sure there's a newline at the end of the message.
+  (widen)
   (goto-char (point-max))
   (unless (bolp)
-    (insert "\n")))
+    (insert "\n"))
+  ;; Make the hidden headers visible.
+  (let ((points (message-text-with-property 'message-hidden)))
+    (when points
+      (goto-char (car points))
+      (dolist (point points)
+       (add-text-properties point (1+ point)
+                            '(invisible nil intangible nil)))))
+  ;; Make invisible text visible except for mime parts which may be
+  ;; inserted by the MIME-Edit.
+  ;; It doesn't seem as if this is useful, since the invisible property
+  ;; is clobbered by an after-change hook anyhow.
+  (message-check 'invisible-text
+    ;; FIXME T-gnus: It should also detect invisible overlays.
+    (let (from
+         (to (point-min))
+         mime-from mime-to hidden-start)
+      (while (setq from (text-property-any to (point-max) 'invisible t))
+       (setq to (or (text-property-not-all from (point-max) 'invisible t)
+                    (point-max))
+             mime-to from)
+       (while (setq mime-from (text-property-any mime-to to
+                                                 'mime-edit-invisible t))
+         (when (> mime-from mime-to)
+           (setq hidden-start (or hidden-start mime-to))
+           (add-text-properties mime-to mime-from
+                                '(invisible nil face highlight
+                                            font-lock-face highlight)))
+         (setq mime-to (or (text-property-not-all mime-from to
+                                                  'mime-edit-invisible t)
+                           to)))
+       (when (< mime-to to)
+         (setq hidden-start (or hidden-start mime-to))
+         (add-text-properties mime-to to
+                              '(invisible nil face highlight
+                                          font-lock-face highlight))))
+      (when hidden-start
+       (goto-char hidden-start)
+       (set-window-start (selected-window) (gnus-point-at-bol))
+       (unless (yes-or-no-p
+                "Invisible text found and made visible; continue sending? ")
+         (error "Invisible text found and made visible")))))
+;; The following check is needless to T-gnus since T-gnus determines
+;; a MIME charset forcibly (even if it cannot be determined properly,
+;; the value of the `default-mime-charset-for-write' variable is used).
+;;  (message-check 'illegible-text
+;;    (let (found choice)
+;;      (message-goto-body)
+;;      (skip-chars-forward mm-7bit-chars)
+;;      (while (not (eobp))
+;;     (when (let ((char (char-after)))
+;;             (or (< (mm-char-int char) 128)
+;;                 (and (mm-multibyte-p)
+;;                      (memq (char-charset char)
+;;                            '(eight-bit-control eight-bit-graphic
+;;                                                control-1))
+;;                      (not (get-text-property
+;;                            (point) 'untranslated-utf-8)))))
+;;       (message-overlay-put (message-make-overlay (point) (1+ (point)))
+;;                            'face 'highlight)
+;;       (setq found t))
+;;     (forward-char)
+;;     (skip-chars-forward mm-7bit-chars))
+;;      (when found
+;;     (setq choice
+;;           (gnus-multiple-choice
+;;            "Non-printable characters found.  Continue sending?"
+;;            '((?d "Remove non-printable characters and send")
+;;              (?r "Replace non-printable characters with dots and send")
+;;              (?i "Ignore non-printable characters and send")
+;;              (?e "Continue editing"))))
+;;     (if (eq choice ?e)
+;;         (error "Non-printable characters"))
+;;     (message-goto-body)
+;;     (skip-chars-forward mm-7bit-chars)
+;;     (while (not (eobp))
+;;       (when (let ((char (char-after)))
+;;               (or (< (mm-char-int char) 128)
+;;                   (and (mm-multibyte-p)
+;;                        ;; Fixme: Wrong for Emacs 22 and for things
+;;                        ;; like undecable utf-8.  Should at least
+;;                        ;; use find-coding-systems-region.
+;;                        (memq (char-charset char)
+;;                              '(eight-bit-control eight-bit-graphic
+;;                                                  control-1))
+;;                        (not (get-text-property
+;;                              (point) 'untranslated-utf-8)))))
+;;         (if (eq choice ?i)
+;;             (message-kill-all-overlays)
+;;           (delete-char 1)
+;;           (when (eq choice ?r)
+;;             (insert "."))))
+;;       (forward-char)
+;;       (skip-chars-forward mm-7bit-chars)))))
+  )
 
 (defun message-add-action (action &rest types)
   "Add ACTION to be performed when doing an exit of type TYPES."
+  (while types
+    (add-to-list (intern (format "message-%s-actions" (pop types)))
+                action)))
+
+(defun message-delete-action (action &rest types)
+  "Delete ACTION from lists of actions performed when doing an exit of type TYPES."
   (let (var)
     (while types
       (set (setq var (intern (format "message-%s-actions" (pop types))))
-          (nconc (symbol-value var) (list action))))))
+          (delq action (symbol-value var))))))
 
 (defun message-do-actions (actions)
   "Perform all actions in ACTIONS."
@@ -1918,115 +4029,279 @@ the user from the mailer."
     (ignore-errors
       (cond
        ;; A simple function.
-       ((message-functionp (car actions))
+       ((functionp (car actions))
        (funcall (car actions)))
        ;; Something to be evaled.
        (t
        (eval (car actions)))))
     (pop actions)))
 
+(defsubst message-maybe-split-and-send-mail ()
+  "Split a message if necessary, and send it via mail.
+Returns nil if sending succeeded, returns any string if sending failed.
+This sub function is for exclusive use of `message-send-mail'."
+  (let ((mime-edit-split-ignored-field-regexp
+        mime-edit-split-ignored-field-regexp)
+       (case-fold-search t)
+       failure)
+    (while (string-match "Message-ID" mime-edit-split-ignored-field-regexp)
+      (setq mime-edit-split-ignored-field-regexp
+           (concat (substring mime-edit-split-ignored-field-regexp
+                              0 (match-beginning 0))
+                   "Hey_MIME-Edit,_there_is_an_inviolable_Message_ID"
+                   "_so_don't_rape_it!"
+                   (substring mime-edit-split-ignored-field-regexp
+                              (match-end 0)))))
+    (setq failure
+         (or
+          (catch 'message-sending-mail-failure
+            (mime-edit-maybe-split-and-send
+             (function
+              (lambda ()
+                (interactive)
+                (save-restriction
+                  (std11-narrow-to-header mail-header-separator)
+                  (goto-char (point-min))
+                  (when (re-search-forward "^Message-ID:" nil t)
+                    (delete-region (match-end 0) (std11-field-end))
+                    (insert " " (message-make-message-id))))
+                (condition-case err
+                    (funcall (or message-send-mail-real-function
+                                 message-send-mail-function))
+                  (error
+                   (throw 'message-sending-mail-failure err))))))
+            nil)
+          (condition-case err
+              (progn
+                (funcall (or message-send-mail-real-function
+                             message-send-mail-function))
+                nil)
+            (error err))))
+    (when failure
+      (if (eq 'error (car failure))
+         (cadr failure)
+       (prin1-to-string failure)))))
+
+(defun message-send-mail-partially ()
+  "Send mail as message/partial."
+  ;; replace the header delimiter with a blank line
+  (goto-char (point-min))
+  (re-search-forward
+   (concat "^" (regexp-quote mail-header-separator) "\n"))
+  (replace-match "\n")
+  (run-hooks 'message-send-mail-hook)
+  (let ((p (goto-char (point-min)))
+       (tembuf (message-generate-new-buffer-clone-locals " message temp"))
+       (curbuf (current-buffer))
+       (id (message-make-message-id)) (n 1)
+       plist total  header required-mail-headers)
+    (while (not (eobp))
+      (if (< (point-max) (+ p message-send-mail-partially-limit))
+         (goto-char (point-max))
+       (goto-char (+ p message-send-mail-partially-limit))
+       (beginning-of-line)
+       (if (<= (point) p) (forward-line 1))) ;; In case of bad message.
+      (push p plist)
+      (setq p (point)))
+    (setq total (length plist))
+    (push (point-max) plist)
+    (setq plist (nreverse plist))
+    (unwind-protect
+       (save-excursion
+         (setq p (pop plist))
+         (while plist
+           (set-buffer curbuf)
+           (copy-to-buffer tembuf p (car plist))
+           (set-buffer tembuf)
+           (goto-char (point-min))
+           (if header
+               (progn
+                 (goto-char (point-min))
+                 (narrow-to-region (point) (point))
+                 (insert header))
+             (message-goto-eoh)
+             (setq header (buffer-substring (point-min) (point)))
+             (goto-char (point-min))
+             (narrow-to-region (point) (point))
+             (insert header)
+             (message-remove-header "Mime-Version")
+             (message-remove-header "Content-Type")
+             (message-remove-header "Content-Transfer-Encoding")
+             (message-remove-header "Message-ID")
+             (message-remove-header "Lines")
+             (goto-char (point-max))
+             (insert "Mime-Version: 1.0\n")
+             (setq header (buffer-string)))
+           (goto-char (point-max))
+           (insert (format "Content-Type: message/partial; id=\"%s\"; number=%d; total=%d\n\n"
+                           id n total))
+           (forward-char -1)
+           (let ((mail-header-separator ""))
+             (when (memq 'Message-ID message-required-mail-headers)
+               (insert "Message-ID: " (message-make-message-id) "\n"))
+             (when (memq 'Lines message-required-mail-headers)
+               (insert "Lines: " (message-make-lines) "\n"))
+             (message-goto-subject)
+             (end-of-line)
+             (insert (format " (%d/%d)" n total))
+             (widen)
+             (mm-with-unibyte-current-buffer
+               (funcall (or message-send-mail-real-function
+                            message-send-mail-function))))
+           (setq n (+ n 1))
+           (setq p (pop plist))
+           (erase-buffer)))
+      (kill-buffer tembuf))))
+
 (defun message-send-mail (&optional arg)
   (require 'mail-utils)
-  (let ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
-       (case-fold-search nil)
-       (news (message-news-p))
-       (mailbuf (current-buffer)))
+  (let* ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
+        (case-fold-search nil)
+        (news (message-news-p))
+        (message-this-is-mail t)
+        (headers message-required-mail-headers)
+        failure)
     (save-restriction
       (message-narrow-to-headers)
+      ;; Generate the Mail-Followup-To header if the header is not there...
+      (if (and (message-subscribed-p)
+              (not (mail-fetch-field "mail-followup-to")))
+         (setq headers
+               (cons
+                (cons "Mail-Followup-To" (message-make-mail-followup-to))
+                message-required-mail-headers))
+       ;; otherwise, delete the MFT header if the field is empty
+       (when (equal "" (mail-fetch-field "mail-followup-to"))
+         (message-remove-header "^Mail-Followup-To:")))
       ;; Insert some headers.
       (let ((message-deletable-headers
             (if news nil message-deletable-headers)))
-       (message-generate-headers message-required-mail-headers))
+       (message-generate-headers headers))
       ;; Let the user do all of the above.
       (run-hooks 'message-header-hook))
-    (unwind-protect
-       (save-excursion
-         (set-buffer tembuf)
-         (erase-buffer)
-         ;; Avoid copying text props.
-         (insert (format
-                  "%s" (save-excursion
-                         (set-buffer mailbuf)
-                         (buffer-string))))
-         ;; Remove some headers.
-         (save-restriction
-           (message-narrow-to-headers)
+    (if (not (message-check-mail-syntax))
+       (progn
+         (message "")
+         nil)
+      (unwind-protect
+         (save-excursion
+           (set-buffer tembuf)
+           (erase-buffer)
+           ;; ;; Avoid copying text props (except hard newlines).
+           ;; T-gnus change: copy all text props from the editing buffer
+           ;; into the encoding buffer.
+           (insert-buffer-substring message-encoding-buffer)
            ;; Remove some headers.
-           (message-remove-header message-ignored-mail-headers t))
-         (goto-char (point-max))
-         ;; require one newline at the end.
-         (or (= (preceding-char) ?\n)
-             (insert ?\n))
-         (when (and news
-                    (or (message-fetch-field "cc")
-                        (message-fetch-field "to")))
-           (message-insert-courtesy-copy))
-         (funcall message-send-mail-function))
-      (kill-buffer tembuf))
-    (set-buffer mailbuf)
-    (push 'mail message-sent-message-via)))
+           (save-restriction
+             (message-narrow-to-headers)
+;; We Semi-gnus people have no use for it.
+;;           ;; We (re)generate the Lines header.
+;;           (when (memq 'Lines message-required-mail-headers)
+;;             (message-generate-headers '(Lines)))
+             (message-remove-header message-ignored-mail-headers t))
+           (goto-char (point-max))
+           ;; require one newline at the end.
+           (or (= (preceding-char) ?\n)
+               (insert ?\n))
+           (message-cleanup-headers)
+           ;; FIXME: we're inserting the courtesy copy after encoding.
+           ;; This is wrong if the courtesy copy string contains
+           ;; non-ASCII characters. -- jh
+           (when
+               (save-restriction
+                 (message-narrow-to-headers)
+                 (and news
+                      (or (message-fetch-field "cc")
+                          (message-fetch-field "bcc")
+                          (message-fetch-field "to"))
+                      (let ((content-type (mime-read-Content-Type)))
+                        (and
+                         (or
+                          (not content-type)
+                          (and
+                           (eq 'text (cdr (assq 'type content-type)))
+                           (eq 'plain (cdr (assq 'subtype content-type)))))
+                         (not
+                          (string= "base64"
+                                   (mime-read-Content-Transfer-Encoding)))))))
+             (message-insert-courtesy-copy))
+           (setq failure (message-maybe-split-and-send-mail)))
+       (kill-buffer tembuf))
+      (set-buffer message-edit-buffer)
+      (if failure
+         (progn
+           (message "Couldn't send message via mail: %s" failure)
+           nil)
+       (push 'mail message-sent-message-via)))))
 
 (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))
-      (save-restriction
-       (message-narrow-to-headers)
-       (setq resend-to-addresses (message-fetch-field "resent-to")))
-      ;; Change header-delimiter to be what sendmail expects.
-      (goto-char (point-min))
-      (re-search-forward
-       (concat "^" (regexp-quote mail-header-separator) "\n"))
-      (replace-match "\n")
-      (backward-char 1)
-      (setq delimline (point-marker))
-      (run-hooks 'message-send-mail-hook)
-      ;; Insert an extra newline if we need it to work around
-      ;; Sun's bug that swallows newlines.
-      (goto-char (1+ delimline))
-      (when (eval message-mailer-swallows-blank-line)
-       (newline))
-      (when message-interactive
-       (save-excursion
-         (set-buffer errbuf)
-         (erase-buffer))))
-    (let ((default-directory "/")
-         (coding-system-for-write 'binary))
-      (apply 'call-process-region
-            (append (list (point-min) (point-max)
-                          (if (boundp 'sendmail-program)
-                              sendmail-program
-                            "/usr/lib/sendmail")
-                          nil errbuf nil "-oi")
-                    ;; Always specify who from,
-                    ;; since some systems have broken sendmails.
-                    ;; 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)))
-                    ;; These mean "report errors by mail"
-                    ;; and "deliver in background".
-                    (if (null message-interactive) '("-oem" "-odb"))
-                    ;; Get the addresses from the message
-                    ;; unless this is a resend.
-                    ;; We must not do that for a resend
-                    ;; because we would find the original addresses.
-                    ;; For a resend, include the specific addresses.
-                    (if resend-to-addresses
-                        (list resend-to-addresses)
-                      '("-t")))))
-    (when message-interactive
-      (save-excursion
-       (set-buffer errbuf)
-       (goto-char (point-min))
-       (while (re-search-forward "\n\n* *" nil t)
-         (replace-match "; "))
-       (if (not (zerop (buffer-size)))
-           (error "Sending...failed to %s"
-                  (buffer-substring (point-min) (point-max)))))
+    (unwind-protect
+       (progn
+         (let ((case-fold-search t))
+           (save-restriction
+             (message-narrow-to-headers)
+             (setq resend-to-addresses (message-fetch-field "resent-to")))
+           ;; Change header-delimiter to be what sendmail expects.
+           (goto-char (point-min))
+           (re-search-forward
+            (concat "^" (regexp-quote mail-header-separator) "\n"))
+           (replace-match "\n")
+           (backward-char 1)
+           (setq delimline (point-marker))
+           (run-hooks 'message-send-mail-hook)
+           ;; Insert an extra newline if we need it to work around
+           ;; Sun's bug that swallows newlines.
+           (goto-char (1+ delimline))
+           (when (eval message-mailer-swallows-blank-line)
+             (newline))
+           (when message-interactive
+             (save-excursion
+               (set-buffer errbuf)
+               (erase-buffer))))
+         (let* ((default-directory "/")
+                (cpr (as-binary-process
+                      (apply
+                       'call-process-region
+                       (append
+                        (list (point-min) (point-max)
+                              (if (boundp 'sendmail-program)
+                                  sendmail-program
+                                "/usr/lib/sendmail")
+                              nil errbuf nil "-oi")
+                        ;; Always specify who from,
+                        ;; since some systems have broken sendmails.
+                        ;; But some systems are more broken with -f, so
+                        ;; we'll let users override this.
+                        (if (null message-sendmail-f-is-evil)
+                            (list "-f" (message-sendmail-envelope-from)))
+                        ;; These mean "report errors by mail"
+                        ;; and "deliver in background".
+                        (if (null message-interactive) '("-oem" "-odb"))
+                        ;; Get the addresses from the message
+                        ;; unless this is a resend.
+                        ;; We must not do that for a resend
+                        ;; because we would find the original addresses.
+                        ;; For a resend, include the specific addresses.
+                        (if resend-to-addresses
+                            (list resend-to-addresses)
+                          '("-t")))))))
+           (unless (or (null cpr) (and (numberp cpr) (zerop cpr)))
+             (error "Sending...failed with exit value %d" cpr)))
+         (when message-interactive
+           (save-excursion
+             (set-buffer errbuf)
+             (goto-char (point-min))
+             (while (re-search-forward "\n\n* *" nil t)
+               (replace-match "; "))
+             (if (not (zerop (buffer-size)))
+                 (error "Sending...failed to %s"
+                        (buffer-string))))))
       (when (bufferp errbuf)
        (kill-buffer errbuf)))))
 
@@ -2039,35 +4314,38 @@ to find out how to use this."
   (re-search-forward
    (concat "^" (regexp-quote mail-header-separator) "\n"))
   (replace-match "\n")
+  (backward-char 1)
   (run-hooks 'message-send-mail-hook)
   ;; send the message
   (case
-      (let ((coding-system-for-write 'binary))
-       (apply
-        'call-process-region 1 (point-max) message-qmail-inject-program
-        nil nil nil
-        ;; qmail-inject's default behaviour is to look for addresses on the
-        ;; command line; if there're none, it scans the headers.
-        ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
-        ;;
-        ;; in general, ALL of qmail-inject's defaults are perfect for simply
-        ;; reading a formatted (i. e., at least a To: or Resent-To header)
-        ;; message from stdin.
-        ;;
-        ;; qmail also has the advantage of not having been raped by
-        ;; various vendors, so we don't have to allow for that, either --
-        ;; compare this with message-send-mail-with-sendmail and weep
-        ;; for sendmail's lost innocence.
-        ;;
-        ;; all this is way cool coz it lets us keep the arguments entirely
-        ;; free for -inject-arguments -- a big win for the user and for us
-        ;; since we don't have to play that double-guessing game and the user
-        ;; gets full control (no gestapo'ish -f's, for instance).  --sj
-        message-qmail-inject-args))
+      (as-binary-process
+       (apply
+       'call-process-region 1 (point-max) message-qmail-inject-program
+       nil nil nil
+       ;; qmail-inject's default behaviour is to look for addresses on the
+       ;; command line; if there're none, it scans the headers.
+       ;; yes, it does The Right Thing w.r.t. Resent-To and it's kin.
+       ;;
+       ;; in general, ALL of qmail-inject's defaults are perfect for simply
+       ;; reading a formatted (i. e., at least a To: or Resent-To header)
+       ;; message from stdin.
+       ;;
+       ;; qmail also has the advantage of not having been raped by
+       ;; various vendors, so we don't have to allow for that, either --
+       ;; compare this with message-send-mail-with-sendmail and weep
+       ;; for sendmail's lost innocence.
+       ;;
+       ;; all this is way cool coz it lets us keep the arguments entirely
+       ;; free for -inject-arguments -- a big win for the user and for us
+       ;; since we don't have to play that double-guessing game and the user
+       ;; gets full control (no gestapo'ish -f's, for instance).  --sj
+       (if (functionp message-qmail-inject-args)
+           (funcall message-qmail-inject-args)
+         message-qmail-inject-args)))
     ;; qmail-inject doesn't say anything on it's stdout/stderr,
     ;; we have to look at the retval instead
     (0 nil)
-    (1   (error "qmail-inject reported permanent failure"))
+    (100 (error "qmail-inject reported permanent failure"))
     (111 (error "qmail-inject reported transient failure"))
     ;; should never happen
     (t   (error "qmail-inject reported unknown failure"))))
@@ -2090,88 +4368,196 @@ to find out how to use this."
     ;; Pass it on to mh.
     (mh-send-letter)))
 
+(defun message-send-mail-with-smtp ()
+  "Send off the prepared buffer with SMTP."
+  (require 'smtp) ; XXX
+  (let ((case-fold-search t)
+       recipients)
+    (save-restriction
+      (message-narrow-to-headers)
+      (setq recipients
+           ;; XXX: Should be replaced by better one.
+           (smtp-deduce-address-list (current-buffer)
+                                     (point-min) (point-max)))
+      ;; Remove BCC lines.
+      (message-remove-header "bcc"))
+    ;; replace the header delimiter with a blank line.
+    (goto-char (point-min))
+    (re-search-forward
+     (concat "^" (regexp-quote mail-header-separator) "\n"))
+    (replace-match "\n")
+    (backward-char 1)
+    (run-hooks 'message-send-mail-hook)
+    (if recipients
+       (smtp-send-buffer user-mail-address recipients (current-buffer))
+      (error "Sending failed; no recipients"))))
+
+(defsubst message-maybe-split-and-send-news (method)
+  "Split a message if necessary, and send it via news.
+Returns nil if sending succeeded, returns t if sending failed.
+This sub function is for exclusive use of `message-send-news'."
+  (let ((mime-edit-split-ignored-field-regexp
+        mime-edit-split-ignored-field-regexp)
+       (case-fold-search t))
+    (while (string-match "Message-ID" mime-edit-split-ignored-field-regexp)
+      (setq mime-edit-split-ignored-field-regexp
+           (concat (substring mime-edit-split-ignored-field-regexp
+                              0 (match-beginning 0))
+                   "Hey_MIME-Edit,_there_is_an_inviolable_Message_ID"
+                   "_so_don't_rape_it!"
+                   (substring mime-edit-split-ignored-field-regexp
+                              (match-end 0)))))
+    (or
+     (catch 'message-sending-news-failure
+       (mime-edit-maybe-split-and-send
+       (function
+        (lambda ()
+          (interactive)
+          (save-restriction
+            (std11-narrow-to-header mail-header-separator)
+            (goto-char (point-min))
+            (when (re-search-forward "^Message-ID:" nil t)
+              (delete-region (match-end 0) (std11-field-end))
+              (insert " " (message-make-message-id))))
+          (unless (funcall message-send-news-function method)
+            (throw 'message-sending-news-failure t)))))
+       nil)
+     (not (funcall message-send-news-function method)))))
+
+(defun message-smtpmail-send-it ()
+  "Send the prepared message buffer with `smtpmail-send-it'.
+This only differs from `smtpmail-send-it' that this command evaluates
+`message-send-mail-hook' just before sending a message.  It is useful
+if your ISP requires the POP-before-SMTP authentication.  See the
+documentation for the function `mail-source-touch-pop'."
+  (run-hooks 'message-send-mail-hook)
+  (smtpmail-send-it))
+
+(defun message-canlock-generate ()
+  "Return a string that is non-trivial to guess.
+Do not use this for anything important, it is cryptographically weak."
+  (let (sha1-maximum-internal-length)
+    (sha1 (concat (message-unique-id)
+                 (format "%x%x%x" (random) (random t) (random))
+                 (prin1-to-string (recent-keys))
+                 (prin1-to-string (garbage-collect))))))
+
+(defun message-canlock-password ()
+  "The password used by message for cancel locks.
+This is the value of `canlock-password', if that option is non-nil.
+Otherwise, generate and save a value for `canlock-password' first."
+  (unless canlock-password
+    (customize-save-variable 'canlock-password (message-canlock-generate))
+    (setq canlock-password-for-verify canlock-password))
+  canlock-password)
+
+(defun message-insert-canlock ()
+  (when message-insert-canlock
+    (message-canlock-password)
+    (canlock-insert-header)))
+
 (defun message-send-news (&optional arg)
-  (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
-       (case-fold-search nil)
-       (method (if (message-functionp message-post-method)
-                   (funcall message-post-method arg)
-                 message-post-method))
-       (messbuf (current-buffer))
-       (message-syntax-checks
-        (if arg
-            (cons '(existing-newsgroups . disabled)
-                  message-syntax-checks)
-          message-syntax-checks))
-       result)
+  (let* ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
+        (case-fold-search nil)
+        (method (if (functionp message-post-method)
+                    (funcall message-post-method arg)
+                  message-post-method))
+        (newsgroups-field (save-restriction
+                            (message-narrow-to-headers-or-head)
+                            (message-fetch-field "Newsgroups")))
+        (followup-field (save-restriction
+                          (message-narrow-to-headers-or-head)
+                          (message-fetch-field "Followup-To")))
+        ;; BUG: We really need to get the charset for each name in the
+        ;; Newsgroups and Followup-To lines to allow crossposting
+        ;; between group namess with incompatible character sets.
+        ;; -- Per Abrahamsen <abraham@dina.kvl.dk> 2001-10-08.
+        (group-field-charset
+         (gnus-group-name-charset method newsgroups-field))
+        (followup-field-charset
+         (gnus-group-name-charset method (or followup-field "")))
+        (mime-field-encoding-method-alist
+         (append (when group-field-charset
+                   (list (cons "Newsgroups" group-field-charset)))
+                 (when followup-field-charset
+                   (list (cons "Followup-To" followup-field-charset)))
+                 mime-field-encoding-method-alist))
+        (message-syntax-checks
+         (if (and arg
+                  (listp message-syntax-checks))
+             (cons '(existing-newsgroups . disabled)
+                   message-syntax-checks)
+           message-syntax-checks))
+        (message-this-is-news t)
+        result)
     (save-restriction
       (message-narrow-to-headers)
       ;; Insert some headers.
       (message-generate-headers message-required-news-headers)
+      (message-insert-canlock)
       ;; Let the user do all of the above.
       (run-hooks 'message-header-hook))
+    ;; Note: This check will be disabled by the ".*" default value for
+    ;; gnus-group-name-charset-group-alist. -- Pa 2001-10-07.
+    (when (and group-field-charset
+              (listp message-syntax-checks))
+      (setq message-syntax-checks
+           (cons '(valid-newsgroups . disabled)
+                 message-syntax-checks)))
     (message-cleanup-headers)
-    (if (not (message-check-news-syntax))
-       (progn
-         ;;(message "Posting not performed")
-         nil)
+    (if (not (let ((message-post-method method))
+              (message-check-news-syntax)))
+       nil
       (unwind-protect
          (save-excursion
            (set-buffer tembuf)
-           (buffer-disable-undo (current-buffer))
+           (buffer-disable-undo)
            (erase-buffer)
-           ;; Avoid copying text props.
-           (insert (format
-                    "%s" (save-excursion
-                           (set-buffer messbuf)
-                           (buffer-string))))
+           (insert-buffer-substring message-encoding-buffer)
            ;; Remove some headers.
            (save-restriction
              (message-narrow-to-headers)
+;; We Semi-gnus people have no use for it.
+;;           ;; We (re)generate the Lines header.
+;;           (when (memq 'Lines message-required-mail-headers)
+;;             (message-generate-headers '(Lines)))
              ;; Remove some headers.
              (message-remove-header message-ignored-news-headers t))
            (goto-char (point-max))
            ;; require one newline at the end.
            (or (= (preceding-char) ?\n)
                (insert ?\n))
-           (let ((case-fold-search t))
-             ;; Remove the delimiter.
-             (goto-char (point-min))
-             (re-search-forward
-              (concat "^" (regexp-quote mail-header-separator) "\n"))
-             (replace-match "\n")
-             (backward-char 1))
-           (run-hooks 'message-send-news-hook)
-           ;;(require (car method))
-           ;;(funcall (intern (format "%s-open-server" (car method)))
-           ;;(cadr method) (cddr method))
-           ;;(setq result
-           ;;    (funcall (intern (format "%s-request-post" (car method)))
-           ;;             (cadr method)))
-           (gnus-open-server method)
-           (setq result (gnus-request-post method)))
+           (setq result (message-maybe-split-and-send-news method)))
        (kill-buffer tembuf))
-      (set-buffer messbuf)
+      (set-buffer message-edit-buffer)
       (if result
-         (push 'news message-sent-message-via)
-       (message "Couldn't send message via news: %s"
-                (nnheader-get-report (car method)))
-       nil))))
+         (progn
+           (message "Couldn't send message via news: %s"
+                    (nnheader-get-report (car method)))
+           nil)
+       (push 'news message-sent-message-via)))))
+
+;; 1997-09-29 by MORIOKA Tomohiko
+(defun message-send-news-with-gnus (method)
+  (let ((case-fold-search t))
+    ;; Remove the delimiter.
+    (goto-char (point-min))
+    (re-search-forward
+     (concat "^" (regexp-quote mail-header-separator) "\n"))
+    (replace-match "\n")
+    (backward-char 1)
+    (run-hooks 'message-send-news-hook)
+    (gnus-open-server method)
+    (message "Sending news via %s..." (gnus-server-string method))
+    (gnus-request-post method)
+    ))
 
 ;;;
 ;;; Header generation & syntax checking.
 ;;;
 
-(defmacro message-check (type &rest forms)
-  "Eval FORMS if TYPE is to be checked."
-  `(or (message-check-element ,type)
-       (save-excursion
-        ,@forms)))
-
-(put 'message-check 'lisp-indent-function 1)
-(put 'message-check 'edebug-form-spec '(form body))
-
 (defun message-check-element (type)
-  "Returns non-nil if this type is not to be checked."
+  "Return non-nil if this TYPE is not to be checked."
   (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
       t
     (let ((able (assq type message-syntax-checks)))
@@ -2190,10 +4576,21 @@ to find out how to use this."
           (message-narrow-to-headers)
           (message-check-news-header-syntax)))
        ;; Check the body.
-       (message-check-news-body-syntax)))))
+       (save-excursion
+        (set-buffer message-edit-buffer)
+        (message-check-news-body-syntax))))))
 
 (defun message-check-news-header-syntax ()
   (and
+   ;; Check Newsgroups header.
+   (message-check 'newsgroups
+     (let ((group (message-fetch-field "newsgroups")))
+       (or
+       (and group
+            (not (string-match "\\`[ \t]*\\'" group)))
+       (ignore
+        (message
+         "The newsgroups field is empty or missing.  Posting is denied.")))))
    ;; Check the Subject header.
    (message-check 'subject
      (let* ((case-fold-search t)
@@ -2210,6 +4607,24 @@ to find out how to use this."
         (y-or-n-p
          "The control code \"cmsg\" is in the subject.  Really post? ")
        t))
+   ;; Check long header lines.
+   (message-check 'long-header-lines
+     (let ((start (point))
+          (header nil)
+          (length 0)
+          found)
+       (while (and (not found)
+                  (re-search-forward "^\\([^ \t:]+\\): " nil t))
+        (if (> (- (point) (match-beginning 0)) 998)
+            (setq found t
+                  length (- (point) (match-beginning 0)))
+          (setq header (match-string-no-properties 1)))
+        (setq start (match-beginning 0))
+        (forward-line 1))
+       (if found
+          (y-or-n-p (format "Your %s header is too long (%d).  Really post? "
+                            header length))
+        t)))
    ;; Check for multiple identical headers.
    (message-check 'multiple-headers
      (let (found)
@@ -2248,8 +4663,8 @@ to find out how to use this."
                   (zerop
                    (length
                     (setq to (completing-read
-                              "Followups to: (default all groups) "
-                              (mapcar (lambda (g) (list g))
+                              "Followups to (default: no Followup-To header) "
+                              (mapcar #'list
                                       (cons "poster"
                                             (message-tokenize-header
                                              newsgroups)))))))))
@@ -2259,7 +4674,7 @@ to find out how to use this."
    ;; Check "Shoot me".
    (message-check 'shoot
      (if (re-search-forward
-         "Message-ID.*.i-did-not-set--mail-host-address--so-shoot-me" nil t)
+         "Message-ID.*.i-did-not-set--mail-host-address--so-tickle-me" nil t)
         (y-or-n-p "You appear to have a misconfigured system.  Really post? ")
        t))
    ;; Check for Approved.
@@ -2290,27 +4705,72 @@ to find out how to use this."
                     (if followup-to
                         (concat newsgroups "," followup-to)
                       newsgroups)))
-           (hashtb (and (boundp 'gnus-active-hashtb)
-                        gnus-active-hashtb))
+           (post-method (if (functionp message-post-method)
+                            (funcall message-post-method)
+                          message-post-method))
+           ;; KLUDGE to handle nnvirtual groups.  Doing this right
+           ;; would probably involve a new nnoo function.
+           ;; -- Per Abrahamsen <abraham@dina.kvl.dk>, 2001-10-17.
+           (method (if (and (consp post-method)
+                            (eq (car post-method) 'nnvirtual)
+                            gnus-message-group-art)
+                       (let ((group (car (nnvirtual-find-group-art
+                                          (car gnus-message-group-art)
+                                          (cdr gnus-message-group-art)))))
+                         (gnus-find-method-for-group group))
+                     post-method))
+           (known-groups
+            (mapcar (lambda (n)
+                      (gnus-group-name-decode
+                       (gnus-group-real-name n)
+                       (gnus-group-name-charset method n)))
+                    (gnus-groups-from-server method)))
            errors)
-       (if (or (not hashtb)
-              (not (boundp 'gnus-read-active-file))
-              (not gnus-read-active-file)
-              (eq gnus-read-active-file 'some))
-          t
-        (while groups
-          (when (and (not (boundp (intern (car groups) hashtb)))
-                     (not (equal (car groups) "poster")))
-            (push (car groups) errors))
-          (pop groups))
-        (if (not errors)
-            t
-          (y-or-n-p
-           (format
-            "Really post to %s unknown group%s: %s "
-            (if (= (length errors) 1) "this" "these")
-            (if (= (length errors) 1) "" "s")
-            (mapconcat 'identity errors ", ")))))))
+       (while groups
+        (when (and (not (equal (car groups) "poster"))
+                   (not (member (car groups) known-groups))
+                   (not (member (car groups) errors)))
+          (push (car groups) errors))
+        (pop groups))
+       (cond
+       ;; Gnus is not running.
+       ((or (not (and (boundp 'gnus-active-hashtb)
+                      gnus-active-hashtb))
+            (not (boundp 'gnus-read-active-file)))
+        t)
+       ;; We don't have all the group names.
+       ((and (or (not gnus-read-active-file)
+                 (eq gnus-read-active-file 'some))
+             errors)
+        (y-or-n-p
+         (format
+          "Really use %s possibly unknown group%s: %s? "
+          (if (= (length errors) 1) "this" "these")
+          (if (= (length errors) 1) "" "s")
+          (mapconcat 'identity errors ", "))))
+       ;; There were no errors.
+       ((not errors)
+        t)
+       ;; There are unknown groups.
+       (t
+        (y-or-n-p
+         (format
+          "Really post to %s unknown group%s: %s? "
+          (if (= (length errors) 1) "this" "these")
+          (if (= (length errors) 1) "" "s")
+          (mapconcat 'identity errors ", ")))))))
+   ;; Check continuation headers.
+   (message-check 'continuation-headers
+     (goto-char (point-min))
+     (let ((do-posting t))
+       (while (re-search-forward "^[^ \t\n][^:\n]*$" nil t)
+        (if (y-or-n-p "Fix continuation lines? ")
+            (progn
+              (goto-char (match-beginning 0))
+              (insert " "))
+          (unless (y-or-n-p "Send anyway? ")
+            (setq do-posting nil))))
+       do-posting))
    ;; Check the Newsgroups & Followup-To headers for syntax errors.
    (message-check 'valid-newsgroups
      (let ((case-fold-search t)
@@ -2356,12 +4816,15 @@ to find out how to use this."
    (message-check 'from
      (let* ((case-fold-search t)
            (from (message-fetch-field "from"))
-           (ad (nth 1 (mail-extract-address-components from))))
+           ad)
        (cond
        ((not from)
         (message "There is no From line.  Posting is denied.")
         nil)
-       ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi
+       ((or (not (string-match
+                  "@[^\\.]*\\."
+                  (setq ad (nth 1 (std11-extract-address-components
+                                   from))))) ;larsi@ifi
             (string-match "\\.\\." ad) ;larsi@ifi..uio
             (string-match "@\\." ad)   ;larsi@.ifi.uio
             (string-match "\\.$" ad)   ;larsi@ifi.uio.
@@ -2370,6 +4833,40 @@ to find out how to use this."
         (message
          "Denied posting -- the From looks strange: \"%s\"." from)
         nil)
+       ((let ((addresses (rfc822-addresses from)))
+          (while (and addresses
+                      (not (eq (string-to-char (car addresses)) ?\()))
+            (setq addresses (cdr addresses)))
+          addresses)
+        (message
+         "Denied posting -- bad From address: \"%s\"." from)
+        nil)
+       (t t))))
+   ;; Check the Reply-To header.
+   (message-check 'reply-to
+     (let* ((case-fold-search t)
+           (reply-to (message-fetch-field "reply-to"))
+           ad)
+       (cond
+       ((not reply-to)
+        t)
+       ((string-match "," reply-to)
+        (y-or-n-p
+         (format "Multiple Reply-To addresses: \"%s\". Really post? "
+                 reply-to)))
+       ((or (not (string-match
+                  "@[^\\.]*\\."
+                  (setq ad (nth 1 (std11-extract-address-components
+                                   reply-to))))) ;larsi@ifi
+            (string-match "\\.\\." ad) ;larsi@ifi..uio
+            (string-match "@\\." ad)   ;larsi@.ifi.uio
+            (string-match "\\.$" ad)   ;larsi@ifi.uio.
+            (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
+            (string-match "(.*).*(.*)" reply-to)) ;(lars) (lars)
+        (y-or-n-p
+         (format
+          "The Reply-To looks strange: \"%s\". Really post? "
+          reply-to)))
        (t t))))))
 
 (defun message-check-news-body-syntax ()
@@ -2379,10 +4876,13 @@ to find out how to use this."
      (goto-char (point-min))
      (re-search-forward
       (concat "^" (regexp-quote mail-header-separator) "$"))
+     (forward-line 1)
      (while (and
-            (progn
-              (end-of-line)
-              (< (current-column) 80))
+            (or (looking-at
+                 mime-edit-tag-regexp)
+                (let ((p (point)))
+                  (end-of-line)
+                  (< (- (point) p) 80)))
             (zerop (forward-line 1))))
      (or (bolp)
         (eobp)
@@ -2399,13 +4899,19 @@ to find out how to use this."
        (re-search-backward message-signature-separator nil t)
        (beginning-of-line)
        (or (re-search-backward "[^ \n\t]" b t)
-          (y-or-n-p "Empty article.  Really post? "))))
+          (if (message-gnksa-enable-p 'empty-article)
+              (y-or-n-p "Empty article.  Really post? ")
+            (message "Denied posting -- Empty article.")
+            nil))))
    ;; Check for control characters.
    (message-check 'control-chars
-     (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
+     (if (re-search-forward "[\000-\007\013\015-\032\034-\037\200-\237]" nil t)
         (y-or-n-p
          "The article contains control characters.  Really post? ")
        t))
+   ;; Check 8bit characters.
+   (message-check '8bit
+     (message-check-8bit))
    ;; Check excessive size.
    (message-check 'size
      (if (> (buffer-size) 60000)
@@ -2417,22 +4923,87 @@ to find out how to use this."
    (message-check 'new-text
      (or
       (not message-checksum)
-      (not (and (eq (message-checksum) (car message-checksum))
-               (eq (buffer-size) (cdr message-checksum))))
-      (y-or-n-p
-       "It looks like no new text has been added.  Really post? ")))
+      (not (eq (message-checksum) message-checksum))
+      (if (message-gnksa-enable-p 'quoted-text-only)
+         (y-or-n-p
+          "It looks like no new text has been added.  Really post? ")
+       (message "Denied posting -- no new text has been added.")
+       nil)))
    ;; Check the length of the signature.
    (message-check 'signature
      (goto-char (point-max))
-     (if (or (not (re-search-backward message-signature-separator nil t))
-            (search-forward message-forward-end-separator nil t))
-        t
-       (if (> (count-lines (point) (point-max)) 5)
-          (y-or-n-p
-           (format
-            "Your .sig is %d lines; it should be max 4.  Really post? "
-            (1- (count-lines (point) (point-max)))))
-        t)))))
+     (if (> (count-lines (point) (point-max)) 5)
+        (y-or-n-p
+         (format
+          "Your .sig is %d lines; it should be max 4.  Really post? "
+          (1- (count-lines (point) (point-max)))))
+       t))
+   ;; Ensure that text follows last quoted portion.
+   (message-check 'quoting-style
+     (goto-char (point-max))
+     (let ((no-problem t))
+       (when (search-backward-regexp "^>[^\n]*\n" nil t)
+        (setq no-problem (search-forward-regexp "^[ \t]*[^>\n]" nil t)))
+       (if no-problem
+          t
+        (if (message-gnksa-enable-p 'quoted-text-only)
+            (y-or-n-p "Your text should follow quoted text.  Really post? ")
+          ;; Ensure that
+          (goto-char (point-min))
+          (re-search-forward
+           (concat "^" (regexp-quote mail-header-separator) "$"))
+          (if (search-forward-regexp "^[ \t]*[^>\n]" nil t)
+              (y-or-n-p "Your text should follow quoted text.  Really post? ")
+            (message "Denied posting -- only quoted text.")
+            nil)))))))
+
+(defun message-check-mail-syntax ()
+  "Check the syntax of the message."
+  (save-excursion
+    (save-restriction
+      (widen)
+      (and
+       ;; We narrow to the headers and check them first.
+       (save-excursion
+        (save-restriction
+          (message-narrow-to-headers)
+          (message-check-mail-header-syntax)))
+       ;; Check the body.
+       (save-excursion
+        (set-buffer message-edit-buffer)
+        (message-check-mail-body-syntax))))))
+
+(defun message-check-mail-header-syntax ()
+  t)
+
+(defun message-check-mail-body-syntax ()
+  (and
+   ;; Check 8bit characters.
+   (message-check '8bit
+     (message-check-8bit)
+     )))
+
+(defun message-check-8bit ()
+  "Check the article contains 8bit characters."
+  (save-excursion
+    (set-buffer message-encoding-buffer)
+    (message-narrow-to-headers)
+    (let* ((case-fold-search t)
+          (field-value (message-fetch-field "content-transfer-encoding")))
+      (if (and field-value
+              (member (downcase field-value) message-8bit-encoding-list))
+         t
+       (widen)
+       (set-buffer (get-buffer-create " message syntax"))
+       (erase-buffer)
+       (goto-char (point-min))
+       (set-buffer-multibyte nil)
+       (insert-buffer-substring message-encoding-buffer)
+       (goto-char (point-min))
+       (if (re-search-forward "[^\x00-\x7f]" nil t)
+           (y-or-n-p
+            "The article contains 8bit characters.  Really post? ")
+         t)))))
 
 (defun message-checksum ()
   "Return a \"checksum\" for the current buffer."
@@ -2443,53 +5014,59 @@ to find out how to use this."
        (concat "^" (regexp-quote mail-header-separator) "$"))
       (while (not (eobp))
        (when (not (looking-at "[ \t\n]"))
-         (setq sum (logxor (ash sum 1) (if (natnump sum) 0 1)
-                           (following-char))))
+         (setq sum (logxor (ash sum 1) (if (natnump sum) 0 1)
+                           (char-after))))
        (forward-char 1)))
     sum))
 
 (defun message-do-fcc ()
   "Process Fcc headers in the current buffer."
   (let ((case-fold-search t)
-       (buf (current-buffer))
-       list file)
+       (coding-system-for-write 'raw-text)
+       (output-coding-system 'raw-text)
+       list file
+       (mml-externalize-attachments message-fcc-externalize-attachments))
     (save-excursion
-      (set-buffer (get-buffer-create " *message temp*"))
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
-      (insert-buffer-substring buf)
       (save-restriction
        (message-narrow-to-headers)
-       (while (setq file (message-fetch-field "fcc"))
-         (push file list)
-         (message-remove-header "fcc" nil t)))
-      (goto-char (point-min))
-      (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$"))
-      (replace-match "" t t)
-      ;; Process FCC operations.
-      (while list
-       (setq file (pop list))
-       (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
-           ;; Pipe the article to the program in question.
-           (call-process-region (point-min) (point-max) shell-file-name
-                                nil nil nil shell-command-switch
-                                (match-string 1 file))
-         ;; Save the article.
-         (setq file (expand-file-name file))
-         (unless (file-exists-p (file-name-directory file))
-           (make-directory (file-name-directory file) t))
-         (if (and message-fcc-handler-function
-                  (not (eq message-fcc-handler-function 'rmail-output)))
-             (funcall message-fcc-handler-function file)
-           (if (and (file-readable-p file) (mail-file-babyl-p file))
-               (rmail-output file 1 nil t)
-             (let ((mail-use-rfc822 t))
-               (rmail-output file 1 t t))))))
-
-      (kill-buffer (current-buffer)))))
+       (setq file (message-fetch-field "fcc" t)))
+      (when file
+       (set-buffer (get-buffer-create " *message temp*"))
+       (erase-buffer)
+       (insert-buffer-substring message-encoding-buffer)
+       (save-restriction
+         (message-narrow-to-headers)
+         (while (setq file (message-fetch-field "fcc"))
+           (push file list)
+           (message-remove-header "fcc" nil t)))
+       (goto-char (point-min))
+       (when (re-search-forward
+              (concat "^" (regexp-quote mail-header-separator) "$")
+              nil t)
+         (replace-match "" t t))
+       ;; Process FCC operations.
+       (while list
+         (setq file (pop list))
+         (if (string-match "^[ \t]*|[ \t]*\\(.*\\)[ \t]*$" file)
+             ;; Pipe the article to the program in question.
+             (call-process-region (point-min) (point-max) shell-file-name
+                                  nil nil nil shell-command-switch
+                                  (match-string 1 file))
+           ;; Save the article.
+           (setq file (expand-file-name file))
+           (unless (file-exists-p (file-name-directory file))
+             (make-directory (file-name-directory file) t))
+           (if (and message-fcc-handler-function
+                    (not (eq message-fcc-handler-function 'rmail-output)))
+               (funcall message-fcc-handler-function file)
+             (if (and (file-readable-p file) (mail-file-babyl-p file))
+                 (rmail-output file 1 nil t)
+               (let ((mail-use-rfc822 t))
+                 (rmail-output file 1 t t))))))
+       (kill-buffer (current-buffer))))))
 
 (defun message-output (filename)
-  "Append this article to Unix/babyl mail file.."
+  "Append this article to Unix/babyl mail file FILENAME."
   (if (and (file-readable-p filename)
           (mail-file-babyl-p filename))
       (gnus-output-to-rmail filename t)
@@ -2527,11 +5104,37 @@ to find out how to use this."
        (when (re-search-forward ",+$" nil t)
          (replace-match "" t t))))))
 
-(defun message-make-date ()
-  "Make a valid data header."
-  (let ((now (current-time)))
-    (timezone-make-date-arpa-standard
-     (current-time-string now) (current-time-zone now))))
+(defun message-make-date (&optional now)
+  "Make a valid data header.
+If NOW, use that time instead."
+  (let* ((now (or now (current-time)))
+        (zone (nth 8 (decode-time now)))
+        (sign "+"))
+    (when (< zone 0)
+      (setq sign "-")
+      (setq zone (- zone)))
+    (concat
+     ;; The day name of the %a spec is locale-specific.  Pfff.
+     (format "%s, " (capitalize (car (rassoc (nth 6 (decode-time now))
+                                            parse-time-weekdays))))
+     (format-time-string "%d" now)
+     ;; The month name of the %b spec is locale-specific.  Pfff.
+     (format " %s "
+            (capitalize (car (rassoc (nth 4 (decode-time now))
+                                     parse-time-months))))
+     (format-time-string "%Y %H:%M:%S " now)
+     ;; We do all of this because XEmacs doesn't have the %z spec.
+     (format "%s%02d%02d" sign (/ zone 3600) (/ (% zone 3600) 60)))))
+
+(defun message-make-followup-subject (subject)
+  "Make a followup Subject."
+  (cond
+   ((and (eq message-use-subject-re 'guess)
+        (string-match message-subject-encoded-re-regexp subject))
+    subject)
+   (message-use-subject-re
+    (concat "Re: " (message-strip-subject-re subject)))
+   (t subject)))
 
 (defun message-make-message-id ()
   "Make a unique Message-ID."
@@ -2544,7 +5147,6 @@ to find out how to use this."
                      (mail-header-references message-reply-headers)
                      (mail-header-subject message-reply-headers)
                      psubject
-                     (mail-header-subject message-reply-headers)
                      (not (string=
                            (message-strip-subject-re
                             (mail-header-subject message-reply-headers))
@@ -2576,13 +5178,13 @@ to find out how to use this."
             (aset user (match-beginning 0) ?_))
           user)
        (message-number-base36 (user-uid) -1))
-     (message-number-base36 (+ (car   tm)
+     (message-number-base36 (+ (car tm)
                               (lsh (% message-unique-id-char 25) 16)) 4)
      (message-number-base36 (+ (nth 1 tm)
                               (lsh (/ message-unique-id-char 25) 16)) 4)
-     ;; Append the newsreader name, because while the generated
-     ;; ID is unique to this newsreader, other newsreaders might
-     ;; otherwise generate the same ID via another algorithm.
+     ;; Append a given name, because while the generated ID is unique
+     ;; to this newsreader, other newsreaders might otherwise generate
+     ;; the same ID via another algorithm.
      ".fsf")))
 
 (defun message-number-base36 (num len)
@@ -2598,11 +5200,11 @@ to find out how to use this."
   "Make an Organization header."
   (let* ((organization
          (when message-user-organization
-               (if (message-functionp message-user-organization)
-                   (funcall message-user-organization)
-                 message-user-organization))))
-    (save-excursion
-      (message-set-work-buffer)
+           (if (functionp message-user-organization)
+               (funcall message-user-organization)
+             message-user-organization))))
+    (with-temp-buffer
+      (set-buffer-multibyte t)
       (cond ((stringp organization)
             (insert organization))
            ((and (eq t organization)
@@ -2620,30 +5222,40 @@ to find out how to use this."
   (save-excursion
     (save-restriction
       (widen)
-      (goto-char (point-min))
-      (re-search-forward
-       (concat "^" (regexp-quote mail-header-separator) "$"))
-      (forward-line 1)
+      (message-goto-body)
       (int-to-string (count-lines (point) (point-max))))))
 
+(defun message-make-references ()
+  "Return the References header for this message."
+  (when message-reply-headers
+    (let ((message-id (mail-header-message-id message-reply-headers))
+         (references (mail-header-references message-reply-headers))
+         new-references)
+      (if (or references message-id)
+         (concat (or references "") (and references " ")
+                 (or message-id ""))
+       nil))))
+
 (defun message-make-in-reply-to ()
   "Return the In-Reply-To header for this message."
   (when message-reply-headers
     (let ((from (mail-header-from message-reply-headers))
-         (date (mail-header-date message-reply-headers)))
+         (date (mail-header-date message-reply-headers))
+         (msg-id (mail-header-message-id message-reply-headers)))
       (when from
-       (let ((stop-pos
-              (string-match "  *at \\|  *@ \\| *(\\| *<" from)))
-         (concat (if stop-pos (substring from 0 stop-pos) from)
+       (let ((name (std11-extract-address-components from)))
+         (concat msg-id (if msg-id " (")
+                 (or (car name)
+                     (nth 1 name))
                  "'s message of \""
                  (if (or (not date) (string= date ""))
                      "(unknown date)" date)
-                 "\""))))))
+                 "\"" (if msg-id ")")))))))
 
 (defun message-make-distribution ()
   "Make a Distribution header."
   (let ((orig-distribution (message-fetch-reply-field "distribution")))
-    (cond ((message-functionp message-distribution-function)
+    (cond ((functionp message-distribution-function)
           (funcall message-distribution-function))
          (t orig-distribution))))
 
@@ -2654,9 +5266,7 @@ to find out how to use this."
     ;; Add the future to current.
     (setcar current (+ (car current) (round (/ future (expt 2 16)))))
     (setcar (cdr current) (+ (nth 1 current) (% (round future) (expt 2 16))))
-    ;; Return the date in the future in UT.
-    (timezone-make-date-arpa-standard
-     (current-time-string current) (current-time-zone current) '(0 "UT"))))
+    (message-make-date current)))
 
 (defun message-make-path ()
   "Return uucp path."
@@ -2678,8 +5288,8 @@ to find out how to use this."
              (user-full-name))))
     (when (string= fullname "&")
       (setq fullname (user-login-name)))
-    (save-excursion
-      (message-set-work-buffer)
+    (with-temp-buffer
+      (set-buffer-multibyte t)
       (cond
        ((or (null style)
            (equal fullname ""))
@@ -2696,15 +5306,15 @@ to find out how to use this."
                       (string-match "[\\()]" tmp)))))
        (insert fullname)
        (goto-char (point-min))
-       ;; Look for a character that cannot appear unquoted
-       ;; according to RFC 822.
-       (when (re-search-forward "[^- !#-'*+/-9=?A-Z^-~]" nil 1)
-         ;; Quote fullname, escaping specials.
-         (goto-char (point-min))
-         (insert "\"")
-         (while (re-search-forward "[\"\\]" nil 1)
-           (replace-match "\\\\\\&" t))
-         (insert "\""))
+       ;; Look for a character that cannot appear unquoted
+       ;; according to RFC 822.
+       (when (re-search-forward "[^- !#-'*+/-9=?A-Z^-~]" nil 1)
+         ;; Quote fullname, escaping specials.
+         (goto-char (point-min))
+         (insert "\"")
+         (while (re-search-forward "[\"\\]" nil 1)
+           (replace-match "\\\\\\&" t))
+         (insert "\""))
        (insert " <" login ">"))
        (t                              ; 'parens or default
        (insert login " (")
@@ -2740,32 +5350,58 @@ give as trustworthy answer as possible."
 
 (defun message-user-mail-address ()
   "Return the pertinent part of `user-mail-address'."
-  (when user-mail-address
+  (when (and user-mail-address
+            (string-match "@.*\\." user-mail-address))
     (if (string-match " " user-mail-address)
-       (nth 1 (mail-extract-address-components user-mail-address))
+       (nth 1 (std11-extract-address-components user-mail-address))
       user-mail-address)))
 
+(defun message-sendmail-envelope-from ()
+  "Return the envelope from."
+  (cond ((eq message-sendmail-envelope-from 'header)
+        (nth 1 (std11-extract-address-components
+                (message-fetch-field "from"))))
+       ((stringp message-sendmail-envelope-from)
+        message-sendmail-envelope-from)
+       (t
+        (message-make-address))))
+
 (defun message-make-fqdn ()
   "Return user's fully qualified domain name."
-  (let ((system-name (system-name))
-       (user-mail (message-user-mail-address)))
+  (let* ((system-name (system-name))
+        (user-mail (message-user-mail-address))
+        (user-domain
+         (if (and user-mail
+                  (string-match "@\\(.*\\)\\'" user-mail))
+             (match-string 1 user-mail)))
+        (case-fold-search t))
     (cond
-     ((string-match "[^.]\\.[^.]" system-name)
+     ((and message-user-fqdn
+          (stringp message-user-fqdn)
+          (string-match message-valid-fqdn-regexp message-user-fqdn)
+          (not (string-match message-bogus-system-names message-user-fqdn)))
+      message-user-fqdn)
+     ;; `message-user-fqdn' seems to be valid
+     ((and (string-match message-valid-fqdn-regexp system-name)
+          (not (string-match message-bogus-system-names system-name)))
       ;; `system-name' returned the right result.
       system-name)
      ;; Try `mail-host-address'.
      ((and (boundp 'mail-host-address)
           (stringp mail-host-address)
-          (string-match "\\." mail-host-address))
+          (string-match message-valid-fqdn-regexp mail-host-address)
+          (not (string-match message-bogus-system-names mail-host-address)))
       mail-host-address)
      ;; We try `user-mail-address' as a backup.
-     ((and user-mail
-          (string-match "\\." user-mail)
-          (string-match "@\\(.*\\)\\'" user-mail))
-      (match-string 1 user-mail))
+     ((and user-domain
+          (stringp user-domain)
+          (string-match message-valid-fqdn-regexp user-domain)
+          (not (string-match message-bogus-system-names user-domain)))
+      user-domain)
      ;; Default to this bogus thing.
      (t
-      (concat system-name ".i-did-not-set--mail-host-address--so-shoot-me")))))
+      (concat system-name
+             ".i-did-not-set--mail-host-address--so-tickle-me")))))
 
 (defun message-make-host-name ()
   "Return the name of the host."
@@ -2778,9 +5414,147 @@ give as trustworthy answer as possible."
   (or mail-host-address
       (message-make-fqdn)))
 
+(defun message-to-list-only ()
+  "Send a message to the list only.
+Remove all addresses but the list address from To and Cc headers."
+  (interactive)
+  (let ((listaddr (message-make-mail-followup-to t)))
+    (when listaddr
+      (save-excursion
+       (message-remove-header "to")
+       (message-remove-header "cc")
+       (message-position-on-field "To" "X-Draft-From")
+       (insert listaddr)))))
+
+(defun message-make-mail-followup-to (&optional only-show-subscribed)
+  "Return the Mail-Followup-To header.
+If passed the optional argument ONLY-SHOW-SUBSCRIBED only return the
+subscribed address (and not the additional To and Cc header contents)."
+  (let* ((case-fold-search t)
+        (to (message-fetch-field "To"))
+        (cc (message-fetch-field "cc"))
+        (msg-recipients (concat to (and to cc ", ") cc))
+        (recipients
+         (mapcar 'mail-strip-quoted-names
+                 (message-tokenize-header msg-recipients)))
+        (file-regexps
+         (if message-subscribed-address-file
+             (let (begin end item re)
+               (save-excursion
+                 (with-temp-buffer
+                   (insert-file-contents message-subscribed-address-file)
+                   (while (not (eobp))
+                     (setq begin (point))
+                     (forward-line 1)
+                     (setq end (point))
+                     (if (bolp) (setq end (1- end)))
+                     (setq item (regexp-quote (buffer-substring begin end)))
+                     (if re (setq re (concat re "\\|" item))
+                       (setq re (concat "\\`\\(" item))))
+                   (and re (list (concat re "\\)\\'"))))))))
+        (mft-regexps (apply 'append message-subscribed-regexps
+                            (mapcar 'regexp-quote
+                                    message-subscribed-addresses)
+                            file-regexps
+                            (mapcar 'funcall
+                                    message-subscribed-address-functions))))
+    (save-match-data
+      (let ((subscribed-lists nil)
+           (list
+            (loop for recipient in recipients
+              when (loop for regexp in mft-regexps
+                     when (string-match regexp recipient) return t)
+              return recipient)))
+       (when list
+         (if only-show-subscribed
+             list
+           msg-recipients))))))
+
+;; Dummy to avoid byte-compile warning.
+(defvar mule-version)
+(defvar emacs-beta-version)
+(defvar xemacs-codename)
+(defvar gnus-inviolable-extended-version)
+
+(defun message-make-user-agent ()
+  "Return user-agent info if the value `message-user-agent' is non-nil. If the
+\"User-Agent\" field has already exist, remove it."
+  (when message-user-agent
+    (save-excursion
+      (goto-char (point-min))
+      (let ((case-fold-search t))
+       (when (re-search-forward "^User-Agent:[\t ]*" nil t)
+         (delete-region (match-beginning 0) (1+ (std11-field-end)))))))
+  message-user-agent)
+
+(defun message-idna-inside-rhs-p ()
+  "Return t iff point is inside a RHS (heuristically).
+Only works properly if header contains mailbox-list or address-list.
+I.e., calling it on a Subject: header is useless."
+  (save-restriction
+    (narrow-to-region (save-excursion (or (re-search-backward "^[^ \t]" nil t)
+                                         (point-min)))
+                     (save-excursion (or (re-search-forward "^[^ \t]" nil t)
+                                         (point-max))))
+    (if (re-search-backward "[\\\n\r\t ]"
+                           (save-excursion (search-backward "@" nil t)) t)
+       ;; whitespace between @ and point
+       nil
+      (let ((dquote 1) (paren 1))
+       (while (save-excursion (re-search-backward "[^\\]\"" nil t dquote))
+         (incf dquote))
+       (while (save-excursion (re-search-backward "[^\\]\(" nil t paren))
+         (incf paren))
+       (and (= (% dquote 2) 1) (= (% paren 2) 1))))))
+
+(autoload 'idna-to-ascii "idna")
+
+(defun message-idna-to-ascii-rhs-1 (header)
+  "Interactively potentially IDNA encode domain names in HEADER."
+  (let (rhs ace start startpos endpos ovl)
+    (goto-char (point-min))
+    (while (re-search-forward (concat "^" header) nil t)
+      (while (re-search-forward "@\\([^ \t\r\n>,]+\\)"
+                               (or (save-excursion
+                                     (re-search-forward "^[^ \t]" nil t))
+                                   (point-max))
+                               t)
+       (setq rhs (match-string-no-properties 1)
+             startpos (match-beginning 1)
+             endpos (match-end 1))
+       (when (save-match-data
+               (and (message-idna-inside-rhs-p)
+                    (setq ace (idna-to-ascii rhs))
+                    (not (string= rhs ace))
+                    (if (eq message-use-idna 'ask)
+                        (unwind-protect
+                            (progn
+                              (setq ovl (message-make-overlay startpos
+                                                              endpos))
+                              (message-overlay-put ovl 'face 'highlight)
+                              (y-or-n-p
+                               (format "Replace with `%s'? " ace)))
+                          (message "")
+                          (message-delete-overlay ovl))
+                      message-use-idna)))
+         (replace-match (concat "@" ace)))))))
+
+(defun message-idna-to-ascii-rhs ()
+  "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers.
+See `message-idna-encode'."
+  (interactive)
+  (when message-use-idna
+    (save-excursion
+      (save-restriction
+       (message-narrow-to-head)
+       (message-idna-to-ascii-rhs-1 "From")
+       (message-idna-to-ascii-rhs-1 "To")
+       (message-idna-to-ascii-rhs-1 "Cc")))))
+
 (defun message-generate-headers (headers)
   "Prepare article HEADERS.
 Headers already prepared in the buffer are not modified."
+  (setq headers (append headers message-required-headers))
   (save-restriction
     (message-narrow-to-headers)
     (let* ((Date (message-make-date))
@@ -2791,15 +5565,15 @@ Headers already prepared in the buffer are not modified."
           (Subject nil)
           (Newsgroups nil)
           (In-Reply-To (message-make-in-reply-to))
+          (References (message-make-references))
           (To nil)
           (Distribution (message-make-distribution))
           (Lines (message-make-lines))
-          (X-Newsreader message-newsreader)
-          (X-Mailer (and (not (message-fetch-field "X-Newsreader"))
-                         message-mailer))
+          (User-Agent (message-make-user-agent))
           (Expires (message-make-expires))
           (case-fold-search t)
-          header value elem)
+          (optionalp nil)
+          header value elem header-string)
       ;; First we remove any old generated headers.
       (let ((headers message-deletable-headers))
        (unless (buffer-modified-p)
@@ -2820,40 +5594,53 @@ Headers already prepared in the buffer are not modified."
        (setq elem (pop headers))
        (if (consp elem)
            (if (eq (car elem) 'optional)
-               (setq header (cdr elem))
+               (setq header (cdr elem)
+                     optionalp t)
              (setq header (car elem)))
          (setq header elem))
+       (setq header-string  (if (stringp header)
+                                header
+                              (symbol-name header)))
        (when (or (not (re-search-forward
-                       (concat "^" (downcase (symbol-name header)) ":")
+                       (concat "^"
+                               (regexp-quote (downcase header-string))
+                               ":")
                        nil t))
                  (progn
                    ;; The header was found.  We insert a space after the
                    ;; colon, if there is none.
-                   (if (/= (following-char) ? ) (insert " ") (forward-char 1))
-                   ;; Find out whether the header is empty...
-                   (looking-at "[ \t]*$")))
+                   (if (/= (char-after) ? ) (insert " ") (forward-char 1))
+                   ;; Find out whether the header is empty.
+                   (looking-at "[ \t]*\n[^ \t]")))
          ;; So we find out what value we should insert.
          (setq value
                (cond
-                ((and (consp elem) (eq (car elem) 'optional))
+                ((and (consp elem)
+                      (eq (car elem) 'optional)
+                      (not (member header-string message-inserted-headers)))
                  ;; This is an optional header.  If the cdr of this
                  ;; is something that is nil, then we do not insert
                  ;; this header.
                  (setq header (cdr elem))
-                 (or (and (fboundp (cdr elem)) (funcall (cdr elem)))
-                     (and (boundp (cdr elem)) (symbol-value (cdr elem)))))
+                 (or (and (functionp (cdr elem))
+                          (funcall (cdr elem)))
+                     (and (boundp (cdr elem))
+                          (symbol-value (cdr elem)))))
                 ((consp elem)
                  ;; The element is a cons.  Either the cdr is a
                  ;; string to be inserted verbatim, or it is a
                  ;; function, and we insert the value returned from
                  ;; this function.
-                 (or (and (stringp (cdr elem)) (cdr elem))
-                     (and (fboundp (cdr elem)) (funcall (cdr elem)))))
-                ((and (boundp header) (symbol-value header))
+                 (or (and (stringp (cdr elem))
+                          (cdr elem))
+                     (and (functionp (cdr elem))
+                          (funcall (cdr elem)))))
+                ((and (boundp header)
+                      (symbol-value header))
                  ;; The element is a symbol.  We insert the value
                  ;; of this symbol, if any.
                  (symbol-value header))
-                (t
+                ((not (message-check-element header))
                  ;; We couldn't generate a value for this header,
                  ;; so we just ask the user.
                  (read-from-minibuffer
@@ -2866,12 +5653,26 @@ Headers already prepared in the buffer are not modified."
                  (progn
                    ;; This header didn't exist, so we insert it.
                    (goto-char (point-max))
-                   (insert (symbol-name header) ": " value "\n")
-                   (forward-line -1))
+                   (let ((formatter
+                          (cdr (assq header message-header-format-alist))))
+                     (if formatter
+                         (funcall formatter header value)
+                       (insert header-string ": " value))
+                     ;; We check whether the value was ended by a
+                     ;; newline.  If now, we insert one.
+                     (unless (bolp)
+                       (insert "\n"))
+                     (forward-line -1)))
                ;; The value of this header was empty, so we clear
                ;; totally and insert the new value.
                (delete-region (point) (gnus-point-at-eol))
-               (insert value))
+               ;; If the header is optional, and the header was
+               ;; empty, we can't insert it anyway.
+               (unless optionalp
+                 (push header-string message-inserted-headers)
+                 (insert value)
+                 (when (bolp)
+                   (delete-char -1))))
              ;; Add the deletable property to the headers that require it.
              (and (memq header message-deletable-headers)
                   (progn (beginning-of-line) (looking-at "[^:]+: "))
@@ -2886,13 +5687,13 @@ Headers already prepared in the buffer are not modified."
                   (not (message-check-element 'sender))
                   (not (string=
                         (downcase
-                         (cadr (mail-extract-address-components from)))
+                         (cadr (std11-extract-address-components from)))
                         (downcase secure-sender)))
                   (or (null sender)
                       (not
                        (string=
                         (downcase
-                         (cadr (mail-extract-address-components sender)))
+                         (cadr (std11-extract-address-components sender)))
                         (downcase secure-sender)))))
          (goto-char (point-min))
          ;; Rename any old Sender headers to Original-Sender.
@@ -2901,8 +5702,10 @@ Headers already prepared in the buffer are not modified."
            (insert "Original-")
            (beginning-of-line))
          (when (or (message-news-p)
-                   (string-match "^[^@]@.+\\..+" secure-sender))
-           (insert "Sender: " secure-sender "\n")))))))
+                   (string-match "@.+\\.." secure-sender))
+           (insert "Sender: " secure-sender "\n"))))
+      ;; Check for IDNA
+      (message-idna-to-ascii-rhs))))
 
 (defun message-insert-courtesy-copy ()
   "Insert a courtesy message in mail copies of combined messages."
@@ -2937,17 +5740,16 @@ Headers already prepared in the buffer are not modified."
       (goto-char (point-min))
       (while (not (eobp))
        (skip-chars-forward "^,\"" (point-max))
-       (if (or (= (following-char) ?,)
+       (if (or (eq (char-after) ?,)
                (eobp))
            (when (not quoted)
              (if (and (> (current-column) 78)
                       last)
-                 (progn
-                   (save-excursion
-                     (goto-char last)
-                     (insert "\n\t"))
-                   (setq last (1+ (point))))
-               (setq last (1+ (point)))))
+                 (save-excursion
+                   (goto-char last)
+                   (looking-at "[ \t]*")
+                   (replace-match "\n " t t)))
+             (setq last (1+ (point))))
          (setq quoted (not quoted)))
        (unless (eobp)
          (forward-char 1))))
@@ -2955,10 +5757,26 @@ Headers already prepared in the buffer are not modified."
     (widen)
     (forward-line 1)))
 
+(defun message-fill-references (header value)
+  (insert (capitalize (symbol-name header))
+         ": "
+         (std11-fill-msg-id-list-string
+          (if (consp value) (car value) value))
+         "\n"))
+
+(defun message-split-line ()
+  "Split current line, moving portion beyond point vertically down.
+If the current line has `message-yank-prefix', insert it on the new line."
+  (interactive "*")
+  (condition-case nil
+      (split-line message-yank-prefix) ;; Emacs 21.3.50+ supports arg.
+    (error
+     (split-line))))
+     
 (defun message-fill-header (header value)
   (let ((begin (point))
-       (fill-column 990)
-       (fill-prefix "\t"))
+       (fill-column 78)
+       (fill-prefix " "))
     (insert (capitalize (symbol-name header))
            ": "
            (if (consp value) (car value) value)
@@ -2976,6 +5794,64 @@ Headers already prepared in the buffer are not modified."
        (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)
+  "Trim REFERENCES to be 21 Message-ID long or less, 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 21)
+       (count 0)
+       (cut 2)
+       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)
+           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.
+    ;;
+    ;; Only disallow folding for News messages. At this point the headers
+    ;; have not been generated, thus we use message-this-is-news directly.
+    (when (and message-this-is-news 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 (and message-this-is-news 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."
   (message-narrow-to-headers)
@@ -2984,7 +5860,7 @@ Headers already prepared in the buffer are not modified."
     (search-backward ":" )
     (widen)
     (forward-char 1)
-    (if (= (following-char) ? )
+    (if (eq (char-after) ? )
        (forward-char 1)
       (insert " ")))
    (t
@@ -2995,20 +5871,65 @@ Headers already prepared in the buffer are not modified."
       (forward-line 2)))
    (sit-for 0)))
 
+(defcustom message-beginning-of-line t
+  "Whether \\<message-mode-map>\\[message-beginning-of-line]\
+ goes to beginning of header values."
+  :group 'message-buffers
+  :link '(custom-manual "(message)Movement")
+  :type 'boolean)
+
+(defun message-beginning-of-line (&optional n)
+  "Move point to beginning of header value or to beginning of line.
+The prefix argument N is passed directly to `beginning-of-line'.
+
+This command is identical to `beginning-of-line' if point is
+outside the message header or if the option `message-beginning-of-line'
+is nil.
+
+If point is in the message header and on a (non-continued) header
+line, move point to the beginning of the header value.  If point
+is already there, move point to beginning of line.  Therefore,
+repeated calls will toggle point between beginning of field and
+beginning of line."
+  (interactive "p")
+  (let ((zrs 'zmacs-region-stays))
+    (when (and (interactive-p) (boundp zrs))
+      (set zrs t)))
+  (if (and message-beginning-of-line
+          (message-point-in-header-p))
+      (let* ((here (point))
+            (bol (progn (beginning-of-line n) (point)))
+            (eol (gnus-point-at-eol))
+            (eoh (re-search-forward ": *" eol t)))
+       (if (or (not eoh) (equal here eoh))
+           (goto-char bol)
+         (goto-char eoh)))
+    (beginning-of-line n)))
+
 (defun message-buffer-name (type &optional to group)
   "Return a new (unique) buffer name based on TYPE and TO."
   (cond
+   ;; Generate a new buffer name The Message Way.
+   ((eq message-generate-new-buffers 'unique)
+    (generate-new-buffer-name
+     (concat "*" type
+            (if to
+                (concat " to "
+                        (or (car (std11-extract-address-components to))
+                            to) "")
+              "")
+            (if (and group (not (string= group ""))) (concat " on " group) "")
+            "*")))
    ;; Check whether `message-generate-new-buffers' is a function,
    ;; and if so, call it.
-   ((message-functionp message-generate-new-buffers)
+   ((functionp message-generate-new-buffers)
     (funcall message-generate-new-buffers type to group))
-   ;; Generate a new buffer name The Message Way.
-   (message-generate-new-buffers
+   ((eq message-generate-new-buffers 'unsent)
     (generate-new-buffer-name
-     (concat "*" type
+     (concat "*unsent " type
             (if to
                 (concat " to "
-                        (or (car (mail-extract-address-components to))
+                        (or (car (std11-extract-address-components to))
                             to) "")
               "")
             (if (and group (not (string= group ""))) (concat " on " group) "")
@@ -3017,20 +5938,36 @@ Headers already prepared in the buffer are not modified."
    (t
     (format "*%s message*" type))))
 
+(defmacro message-pop-to-buffer-1 (buffer)
+  `(if pop-up-frames
+       (let (special-display-buffer-names
+            special-display-regexps
+            same-window-buffer-names
+            same-window-regexps)
+        (pop-to-buffer ,buffer))
+     (pop-to-buffer ,buffer)))
+
 (defun message-pop-to-buffer (name)
   "Pop to buffer NAME, and warn if it already exists and is modified."
-  (let ((buffer (get-buffer name)))
+  (let ((buffer (get-buffer name))
+       (pop-up-frames (and (or (static-if (featurep 'xemacs)
+                                   (device-on-window-system-p)
+                                 window-system)
+                               (>= emacs-major-version 20))
+                           message-use-multi-frames)))
     (if (and buffer
             (buffer-name buffer))
        (progn
-         (set-buffer (pop-to-buffer buffer))
+         (message-pop-to-buffer-1 buffer)
          (when (and (buffer-modified-p)
                     (not (y-or-n-p
                           "Message already being composed; erase? ")))
            (error "Message being composed")))
-      (set-buffer (pop-to-buffer name))))
-  (erase-buffer)
-  (message-mode))
+      (message-pop-to-buffer-1 name))
+    (erase-buffer)
+    (message-mode)
+    (when pop-up-frames
+      (set (make-local-variable 'message-original-frame) (selected-frame)))))
 
 (defun message-do-send-housekeeping ()
   "Kill old message buffers."
@@ -3038,7 +5975,7 @@ Headers already prepared in the buffer are not modified."
   ;; list of buffers.
   (setq message-buffer-list (delq (current-buffer) message-buffer-list))
   (while (and message-max-buffers
-              message-buffer-list
+             message-buffer-list
              (>= (length message-buffer-list) message-max-buffers))
     ;; Kill the oldest buffer -- unless it has been changed.
     (let ((buffer (pop message-buffer-list)))
@@ -3048,24 +5985,102 @@ Headers already prepared in the buffer are not modified."
   ;; Rename the buffer.
   (if message-send-rename-function
       (funcall message-send-rename-function)
-    (when (string-match "\\`\\*" (buffer-name))
-      (rename-buffer
-       (concat "*sent " (substring (buffer-name) (match-end 0))) t)))
+    ;; Note: mail-abbrevs of XEmacs renames buffer name behind Gnus.
+    (when (string-match
+          "\\`\\*\\(sent \\|unsent \\)?\\(.+\\)\\*[^\\*]*\\|\\`mail to "
+          (buffer-name))
+      (let ((name (match-string 2 (buffer-name)))
+           to group)
+       (if (not (or (null name)
+                    (string-equal name "mail")
+                    (string-equal name "posting")))
+           (setq name (concat "*sent " name "*"))
+         (message-narrow-to-headers)
+         (setq to (message-fetch-field "to"))
+         (setq group (message-fetch-field "newsgroups"))
+         (widen)
+         (setq name
+               (cond
+                (to (concat "*sent mail to "
+                            (or (car (std11-extract-address-components to))
+                                to) "*"))
+                ((and group (not (string= group "")))
+                 (concat "*sent posting on " group "*"))
+                (t "*sent mail*"))))
+       (unless (string-equal name (buffer-name))
+         (rename-buffer name t)))))
   ;; Push the current buffer onto the list.
   (when message-max-buffers
     (setq message-buffer-list
          (nconc message-buffer-list (list (current-buffer))))))
 
-(defvar mc-modes-alist)
-(defun message-setup (headers &optional replybuffer actions)
-  (when (and (boundp 'mc-modes-alist)
-            (not (assq 'message-mode mc-modes-alist)))
-    (push '(message-mode (encrypt . mc-encrypt-message)
-                        (sign . mc-sign-message))
-         mc-modes-alist))
-  (when actions
-    (setq message-send-actions actions))
-  (setq message-reply-buffer replybuffer)
+(defun message-mail-user-agent ()
+  (let ((mua (cond
+             ((not message-mail-user-agent) nil)
+             ((eq message-mail-user-agent t) mail-user-agent)
+             (t message-mail-user-agent))))
+    (if (memq mua '(message-user-agent gnus-user-agent))
+       nil
+      mua)))
+
+(defun message-setup (headers &optional replybuffer actions switch-function)
+  (let ((mua (message-mail-user-agent))
+       subject to field yank-action)
+    (if (not (and message-this-is-mail mua))
+       (message-setup-1 headers replybuffer actions)
+      (if replybuffer
+         (setq yank-action (list 'insert-buffer replybuffer)))
+      (setq headers (copy-sequence headers))
+      (setq field (assq 'Subject headers))
+      (when field
+       (setq subject (cdr field))
+       (setq headers (delq field headers)))
+      (setq field (assq 'To headers))
+      (when field
+       (setq to (cdr field))
+       (setq headers (delq field headers)))
+      (let ((mail-user-agent mua))
+       (compose-mail to subject
+                     (mapcar (lambda (item)
+                               (cons
+                                (format "%s" (car item))
+                                (cdr item)))
+                             headers)
+                     nil switch-function yank-action actions)))))
+
+(defun message-headers-to-generate (headers included-headers excluded-headers)
+  "Return a list that includes all headers from HEADERS.
+If INCLUDED-HEADERS is a list, just include those headers.  If if is
+t, include all headers.  In any case, headers from EXCLUDED-HEADERS
+are not included."
+  (let ((result nil)
+       header-name)
+    (dolist (header headers)
+      (setq header-name (cond
+                        ((and (consp header)
+                              (eq (car header) 'optional))
+                         ;; On the form (optional . Header)
+                         (cdr header))
+                        ((consp header)
+                         ;; On the form (Header . function)
+                         (car header))
+                        (t
+                         ;; Just a Header.
+                         header)))
+      (when (and (not (memq header-name excluded-headers))
+                (or (eq included-headers t)
+                    (memq header-name included-headers)))
+       (push header result)))
+    (nreverse result)))
+
+(defun message-setup-1 (headers &optional replybuffer actions)
+  (dolist (action actions)
+    (condition-case nil
+       (add-to-list 'message-send-actions
+                    `(apply ',(car action) ',(cdr action)))))
+  (setq message-reply-buffer
+       (or (message-get-parameter 'reply-buffer)
+           replybuffer))
   (goto-char (point-min))
   ;; Insert all the headers.
   (mail-header-format
@@ -3094,18 +6109,27 @@ Headers already prepared in the buffer are not modified."
       (or (bolp) (insert ?\n)))
     (when message-generate-headers-first
       (message-generate-headers
-       (delq 'Lines
-            (delq 'Subject
-                  (copy-sequence message-required-news-headers))))))
+       (message-headers-to-generate
+       (append message-required-news-headers
+               message-required-headers)
+       message-generate-headers-first
+       '(Lines Subject)))))
   (when (message-mail-p)
     (when message-default-mail-headers
       (insert message-default-mail-headers)
       (or (bolp) (insert ?\n)))
+    (save-restriction
+      (message-narrow-to-headers)
+      (if (and replybuffer
+              message-alternative-emails)
+         (message-use-alternative-email-as-from)))
     (when message-generate-headers-first
       (message-generate-headers
-       (delq 'Lines
-            (delq 'Subject
-                  (copy-sequence message-required-mail-headers))))))
+       (message-headers-to-generate
+       (append message-required-mail-headers
+               message-required-headers)
+       message-generate-headers-first
+       '(Lines Subject)))))
   (run-hooks 'message-signature-setup-hook)
   (message-insert-signature)
   (save-restriction
@@ -3119,9 +6143,26 @@ Headers already prepared in the buffer are not modified."
 
 (defun message-set-auto-save-file-name ()
   "Associate the message buffer with a file in the drafts directory."
-  (when message-autosave-directory
-    (setq message-draft-article (nndraft-request-associate-buffer "drafts"))
-    (clear-visited-file-modtime)))
+  (when message-auto-save-directory
+    (unless (file-directory-p
+            (directory-file-name message-auto-save-directory))
+      (make-directory message-auto-save-directory t))
+    (if (gnus-alive-p)
+       (setq message-draft-article
+             (nndraft-request-associate-buffer "drafts"))
+      (setq buffer-file-name (expand-file-name
+                             (if (memq system-type
+                                       '(ms-dos ms-windows windows-nt
+                                                cygwin cygwin32 win32 w32
+                                                mswindows))
+                                 "message"
+                               "*message*")
+                             message-auto-save-directory))
+      (setq buffer-auto-save-file-name (make-auto-save-file-name)))
+    (clear-visited-file-modtime)
+    (static-if (boundp 'MULE)
+       (set-file-coding-system message-draft-coding-system)
+      (setq buffer-file-coding-system message-draft-coding-system))))
 
 (defun message-disassociate-draft ()
   "Disassociate the message buffer from the drafts directory."
@@ -3129,6 +6170,23 @@ Headers already prepared in the buffer are not modified."
     (nndraft-request-expire-articles
      (list message-draft-article) "drafts" nil t)))
 
+(defun message-insert-headers ()
+  "Generate the headers for the article."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-headers)
+      (when (message-news-p)
+       (message-generate-headers
+        (delq 'Lines
+              (delq 'Subject
+                    (copy-sequence message-required-news-headers)))))
+      (when (message-mail-p)
+       (message-generate-headers
+        (delq 'Lines
+              (delq 'Subject
+                    (copy-sequence message-required-mail-headers))))))))
+
 \f
 
 ;;;
@@ -3139,155 +6197,276 @@ Headers already prepared in the buffer are not modified."
 (defun message-mail (&optional to subject
                               other-headers continue switch-function
                               yank-action send-actions)
-  "Start editing a mail message to be sent."
+  "Start editing a mail message to be sent.
+OTHER-HEADERS is an alist of header/value pairs."
   (interactive)
-  (let ((message-this-is-mail t))
-    (message-pop-to-buffer (message-buffer-name "mail" to))
+  (let ((message-this-is-mail t) replybuffer)
+    (unless (message-mail-user-agent)
+      (message-pop-to-buffer (message-buffer-name "mail" to)))
+    ;; FIXME: message-mail should do something if YANK-ACTION is not
+    ;; insert-buffer.
+    (and (consp yank-action) (eq (car yank-action) 'insert-buffer)
+        (setq replybuffer (nth 1 yank-action)))
     (message-setup
      (nconc
       `((To . ,(or to "")) (Subject . ,(or subject "")))
-      (when other-headers other-headers)))))
+      (when other-headers other-headers))
+     replybuffer send-actions)
+    ;; FIXME: Should return nil if failure.
+    t))
 
 ;;;###autoload
 (defun message-news (&optional newsgroups subject)
   "Start editing a news article to be sent."
   (interactive)
   (let ((message-this-is-news t))
-    (message-pop-to-buffer (message-buffer-name "news" nil newsgroups))
+    (message-pop-to-buffer (message-buffer-name "posting" nil newsgroups))
     (message-setup `((Newsgroups . ,(or newsgroups ""))
                     (Subject . ,(or subject ""))))))
 
+(defun message-get-reply-headers (wide &optional to-address address-headers)
+  (let (follow-to mct never-mct to cc author mft recipients)
+    ;; Find all relevant headers we need.
+    (save-restriction
+      (message-narrow-to-headers-or-head)
+      (let ((mrt (when message-use-mail-reply-to
+                  (message-fetch-field "mail-reply-to")))
+           (reply-to (message-fetch-field "reply-to")))
+       ;; Gmane renames "To".  Look at "Original-To", too, if it is present in
+       ;; message-header-synonyms.
+       (setq to (or (message-fetch-field "to")
+                    (and (loop for synonym in message-header-synonyms
+                           when (memq 'Original-To synonym)
+                           return t)
+                         (message-fetch-field "original-to")))
+             cc (message-fetch-field "cc")
+             mct (when message-use-mail-copies-to
+                   (message-fetch-field "mail-copies-to"))
+             author (or mrt
+                        reply-to
+                        (message-fetch-field "from")
+                        "")
+             mft (when (and (not (or to-address mrt reply-to))
+                            message-use-mail-followup-to)
+                   (message-fetch-field "mail-followup-to")))))
+
+    (save-match-data
+      ;; Handle special values of Mail-Copies-To.
+      (when mct
+       (cond ((or (equal (downcase mct) "never")
+                  (equal (downcase mct) "nobody"))
+              (when (or (not (eq message-use-mail-copies-to 'ask))
+                        (message-y-or-n-p
+                         (concat "Obey Mail-Copies-To: never? ") t "\
+You should normally obey the Mail-Copies-To: header.
+
+       `Mail-Copies-To: " mct "'
+directs you not to send your response to the author."))
+                (setq never-mct t))
+              (setq mct nil))
+             ((or (equal (downcase mct) "always")
+                  (equal (downcase mct) "poster"))
+              (if (or (not (eq message-use-mail-copies-to 'ask))
+                      (message-y-or-n-p
+                       (concat "Obey Mail-Copies-To: always? ") t "\
+You should normally obey the Mail-Copies-To: header.
+
+       `Mail-Copies-To: " mct "'
+sends a copy of your response to the author."))
+                  (setq mct author)
+                (setq mct nil)))
+             ((and (eq message-use-mail-copies-to 'ask)
+                   (not (message-y-or-n-p
+                         (concat "Obey Mail-Copies-To: " mct " ? ") t "\
+You should normally obey the Mail-Copies-To: header.
+
+       `Mail-Copies-To: " mct "'
+sends a copy of your response to " (if (string-match "," mct)
+                                      "the specified addresses"
+                                    "that address") ".")))
+              (setq mct nil))))
+
+      ;; Build (textual) list of new recipient addresses.
+      (cond
+       ((not wide)
+       (setq recipients (concat ", " author)))
+       (address-headers
+       (dolist (header address-headers)
+         (let ((value (message-fetch-field header)))
+           (when value
+             (setq recipients (concat recipients ", " value))))))
+       ((and mft
+            (string-match "[^ \t,]" mft)
+            (or (not (eq message-use-mail-followup-to 'ask))
+                (message-y-or-n-p "Obey Mail-Followup-To? " t "\
+You should normally obey the Mail-Followup-To: header.  In this
+article, it has the value of
+
+" mft "
+
+which directs your response to " (if (string-match "," mft)
+                                    "the specified addresses"
+                                  "that address only") ".
+
+Most commonly, Mail-Followup-To is used by a mailing list poster to
+express that responses should be sent to just the list, and not the
+poster as well.
+
+If a message is posted to several mailing lists, Mail-Followup-To may
+also be used to direct the following discussion to one list only,
+because discussions that are spread over several lists tend to be
+fragmented and very difficult to follow.
+
+Also, some source/announcement lists are not intended for discussion;
+responses here are directed to other addresses.")))
+       (setq recipients (concat ", " mft)))
+       (to-address
+       (setq recipients (concat ", " to-address))
+       ;; If the author explicitly asked for a copy, we don't deny it to them.
+       (if mct (setq recipients (concat recipients ", " mct))))
+       (t
+       (setq recipients (if never-mct "" (concat ", " author)))
+       (if to  (setq recipients (concat recipients ", " to)))
+       (if cc  (setq recipients (concat recipients ", " cc)))
+       (if mct (setq recipients (concat recipients ", " mct)))))
+      (if (>= (length recipients) 2)
+         ;; Strip the leading ", ".
+         (setq recipients (substring recipients 2)))
+      ;; Squeeze whitespace.
+      (while (string-match "[ \t][ \t]+" recipients)
+       (setq recipients (replace-match " " t t recipients)))
+      ;; Remove addresses that match `rmail-dont-reply-to-names'.
+      (let ((rmail-dont-reply-to-names message-dont-reply-to-names))
+       (setq recipients (rmail-dont-reply-to recipients)))
+      ;; Perhaps "Mail-Copies-To: never" removed the only address?
+      (if (string-equal recipients "")
+         (setq recipients author))
+      ;; Convert string to a list of (("foo@bar" . "Name <Foo@BAR>") ...).
+      (setq recipients
+           (mapcar
+            (lambda (addr)
+              (cons (downcase (mail-strip-quoted-names addr)) addr))
+            (message-tokenize-header recipients)))
+      ;; Remove first duplicates.  (Why not all duplicates?  Is this a bug?)
+      (let ((s recipients))
+       (while s
+         (setq recipients (delq (assoc (car (pop s)) s) recipients))))
+
+      ;; Remove hierarchical lists that are contained within each other,
+      ;; if message-hierarchical-addresses is defined.
+      (when message-hierarchical-addresses
+       (let ((plain-addrs (mapcar 'car recipients))
+             subaddrs recip)
+         (while plain-addrs
+           (setq subaddrs (assoc (car plain-addrs)
+                                 message-hierarchical-addresses)
+                 plain-addrs (cdr plain-addrs))
+           (when subaddrs
+             (setq subaddrs (cdr subaddrs))
+             (while subaddrs
+               (setq recip (assoc (car subaddrs) recipients)
+                     subaddrs (cdr subaddrs))
+               (if recip
+                   (setq recipients (delq recip recipients))))))))
+
+      ;; Build the header alist.  Allow the user to be asked whether
+      ;; or not to reply to all recipients in a wide reply.
+      (setq follow-to (list (cons 'To (cdr (pop recipients)))))
+      (when (and recipients
+                (or (not message-wide-reply-confirm-recipients)
+                    (y-or-n-p "Reply to all recipients? ")))
+       (setq recipients (mapconcat
+                         (lambda (addr) (cdr addr)) recipients ", "))
+       (if (string-match "^ +" recipients)
+           (setq recipients (substring recipients (match-end 0))))
+       (push (cons 'Cc recipients) follow-to)))
+    follow-to))
+
 ;;;###autoload
-(defun message-reply (&optional to-address wide ignore-reply-to)
+(defun message-reply (&optional to-address wide)
   "Start editing a reply to the article in the current buffer."
   (interactive)
+  (require 'gnus-sum)                  ; for gnus-list-identifiers
   (let ((cur (current-buffer))
-       from subject date reply-to to cc
+       from subject date
        references message-id follow-to
        (inhibit-point-motion-hooks t)
-       mct never-mct gnus-warning)
+       (message-this-is-mail t)
+       gnus-warning in-reply-to)
     (save-restriction
-      (message-narrow-to-head)
+      (message-narrow-to-head-1)
       ;; Allow customizations to have their say.
       (if (not wide)
          ;; This is a regular reply.
-         (if (message-functionp message-reply-to-function)
-             (setq follow-to (funcall message-reply-to-function)))
-       ;; This is a followup.
-       (if (message-functionp message-wide-reply-to-function)
+         (when (functionp message-reply-to-function)
            (save-excursion
-             (setq follow-to
-                   (funcall message-wide-reply-to-function)))))
-      ;; Find all relevant headers we need.
-      (setq from (message-fetch-field "from")
-           date (message-fetch-field "date")
-           subject (or (message-fetch-field "subject") "none")
-           to (message-fetch-field "to")
-           cc (message-fetch-field "cc")
-           mct (message-fetch-field "mail-copies-to")
-           reply-to (unless ignore-reply-to (message-fetch-field "reply-to"))
+             (setq follow-to (funcall message-reply-to-function))))
+       ;; This is a followup.
+       (when (functionp message-wide-reply-to-function)
+         (save-excursion
+           (setq follow-to
+                 (funcall message-wide-reply-to-function)))))
+      (setq message-id (message-fetch-field "message-id" t)
            references (message-fetch-field "references")
-           message-id (message-fetch-field "message-id" t))
-      ;; Remove any (buggy) Re:'s that are present and make a
-      ;; proper one.
-      (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
-       (setq subject (substring subject (match-end 0))))
-      (setq subject (concat "Re: " subject))
+           date (message-fetch-field "date")
+           from (message-fetch-field "from")
+           subject (or (message-fetch-field "subject") "none"))
+      (when gnus-list-identifiers
+       (setq subject (message-strip-list-identifiers subject)))
+      (setq subject (message-make-followup-subject subject))
+      (when message-subject-trailing-was-query
+       (setq subject (message-strip-subject-trailing-was subject)))
 
       (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
                 (string-match "<[^>]+>" gnus-warning))
        (setq message-id (match-string 0 gnus-warning)))
 
-      ;; Handle special values of Mail-Copies-To.
-      (when mct
-       (cond ((equal (downcase mct) "never")
-              (setq never-mct t)
-              (setq mct nil))
-             ((equal (downcase mct) "always")
-              (setq mct (or reply-to from)))))
-
       (unless follow-to
-       (if (or (not wide)
-               to-address)
-           (progn
-             (setq follow-to (list (cons 'To (or to-address reply-to from))))
-             (when (and wide mct)
-               (push (cons 'Cc mct) follow-to)))
-         (let (ccalist)
-           (save-excursion
-             (message-set-work-buffer)
-             (unless never-mct
-               (insert (or reply-to from "")))
-             (insert (if to (concat (if (bolp) "" ", ") to "") ""))
-             (insert (if mct (concat (if (bolp) "" ", ") mct) ""))
-             (insert (if cc (concat (if (bolp) "" ", ") cc) ""))
-             (goto-char (point-min))
-             (while (re-search-forward "[ \t]+" nil t)
-               (replace-match " " t t))
-             ;; Remove addresses that match `rmail-dont-reply-to-names'.
-             (insert (prog1 (rmail-dont-reply-to (buffer-string))
-                       (erase-buffer)))
-             (goto-char (point-min))
-             ;; Perhaps Mail-Copies-To: never removed the only address?
-             (when (eobp)
-               (insert (or reply-to from "")))
-             (setq ccalist
-                   (mapcar
-                    (lambda (addr)
-                      (cons (mail-strip-quoted-names addr) addr))
-                    (message-tokenize-header (buffer-string))))
-             (let ((s ccalist))
-               (while s
-                 (setq ccalist (delq (assoc (car (pop s)) s) ccalist)))))
-           (setq follow-to (list (cons 'To (cdr (pop ccalist)))))
-           (when ccalist
-             (let ((ccs (cons 'Cc (mapconcat
-                                   (lambda (addr) (cdr addr)) ccalist ", "))))
-               (when (string-match "^ +" (cdr ccs))
-                 (setcdr ccs (substring (cdr ccs) (match-end 0))))
-               (push ccs follow-to))))))
-      (widen))
+       (setq follow-to (message-get-reply-headers wide to-address)))
+
+      ;; Get the references from "In-Reply-To" field if there were
+      ;; no references and "In-Reply-To" field looks promising.
+      (unless references
+       (when (and (setq in-reply-to (message-fetch-field "in-reply-to"))
+                  (string-match "<[^>]+>" in-reply-to))
+         (setq references (match-string 0 in-reply-to)))))
 
-    (message-pop-to-buffer (message-buffer-name
-                           (if wide "wide reply" "reply") from
-                           (if wide to-address nil)))
+    (unless (message-mail-user-agent)
+      (message-pop-to-buffer
+       (message-buffer-name
+       (if wide "wide reply" "reply") from
+       (if wide to-address nil))))
 
     (setq message-reply-headers
-         (vector 0 subject from date message-id references 0 0 ""))
+         (make-full-mail-header-from-decoded-header
+          0 subject from date message-id references 0 0 ""))
 
     (message-setup
      `((Subject . ,subject)
-       ,@follow-to
-       ,@(if (or references message-id)
-            `((References . ,(concat (or references "") (and references " ")
-                                     (or message-id ""))))
-          nil))
+       ,@follow-to)
      cur)))
 
 ;;;###autoload
-(defun message-wide-reply (&optional to-address ignore-reply-to)
+(defun message-wide-reply (&optional to-address)
   "Make a \"wide\" reply to the message in the current buffer."
   (interactive)
-  (message-reply to-address t ignore-reply-to))
+  (message-reply to-address t))
 
 ;;;###autoload
 (defun message-followup (&optional to-newsgroups)
   "Follow up to the message in the current buffer.
 If TO-NEWSGROUPS, use that as the new Newsgroups line."
   (interactive)
+  (require 'gnus-sum)                  ; for gnus-list-identifiers
   (let ((cur (current-buffer))
-       from subject date reply-to mct
+       from subject date reply-to mrt mct mft
        references message-id follow-to
        (inhibit-point-motion-hooks t)
        (message-this-is-news t)
        followup-to distribution newsgroups gnus-warning posted-to)
     (save-restriction
-      (narrow-to-region
-       (goto-char (point-min))
-       (if (search-forward "\n\n" nil t)
-          (1- (point))
-        (point-max)))
-      (when (message-functionp message-followup-to-function)
+      (message-narrow-to-head)
+      (when (functionp message-followup-to-function)
        (setq follow-to
              (funcall message-followup-to-function)))
       (setq from (message-fetch-field "from")
@@ -3299,8 +6478,13 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
            newsgroups (message-fetch-field "newsgroups")
            posted-to (message-fetch-field "posted-to")
            reply-to (message-fetch-field "reply-to")
+           mrt (when message-use-mail-reply-to
+                 (message-fetch-field "mail-reply-to"))
            distribution (message-fetch-field "distribution")
-           mct (message-fetch-field "mail-copies-to"))
+           mct (when message-use-mail-copies-to
+                 (message-fetch-field "mail-copies-to"))
+           mft (when message-use-mail-followup-to
+                 (message-fetch-field "mail-followup-to")))
       (when (and (setq gnus-warning (message-fetch-field "gnus-warning"))
                 (string-match "<[^>]+>" gnus-warning))
        (setq message-id (match-string 0 gnus-warning)))
@@ -3309,42 +6493,67 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
                 (let ((case-fold-search t))
                   (string-match "world" distribution)))
        (setq distribution nil))
-      ;; Remove any (buggy) Re:'s that are present and make a
-      ;; proper one.
-      (when (string-match "^[ \t]*[Rr][Ee]:[ \t]*" subject)
-       (setq subject (substring subject (match-end 0))))
-      (setq subject (concat "Re: " subject))
+      (if gnus-list-identifiers
+         (setq subject (message-strip-list-identifiers subject)))
+      (setq subject (message-make-followup-subject subject))
+      (when message-subject-trailing-was-query
+       (setq subject (message-strip-subject-trailing-was subject)))
       (widen))
 
-    (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
-
-    (message-setup
-     `((Subject . ,subject)
-       ,@(cond
-         (to-newsgroups
-          (list (cons 'Newsgroups to-newsgroups)))
-         (follow-to follow-to)
-         ((and followup-to message-use-followup-to)
-          (list
-           (cond
-            ((equal (downcase followup-to) "poster")
-             (if (or (eq message-use-followup-to 'use)
-                     (message-y-or-n-p "Obey Followup-To: poster? " t "\
+    ;; Handle special values of Mail-Copies-To.
+    (when mct
+      (cond
+       ((and (or (equal (downcase mct) "never")
+                (equal (downcase mct) "nobody")))
+       (setq mct nil))
+       ((and (or (equal (downcase mct) "always")
+                (equal (downcase mct) "poster")))
+       (if (or (not (eq message-use-mail-copies-to 'ask))
+               (message-y-or-n-p
+                (concat "Obey Mail-Copies-To: always? ") t "\
+You should normally obey the Mail-Copies-To: header.
+
+       `Mail-Copies-To: " mct "'
+sends a copy of your response to the author."))
+           (setq mct (or mrt reply-to from))
+         (setq mct nil)))
+       ((and (eq message-use-mail-copies-to 'ask)
+            (not
+             (message-y-or-n-p
+              (concat "Obey Mail-Copies-To: " mct " ? ") t "\
+You should normally obey the Mail-Copies-To: header.
+
+       `Mail-Copies-To: " mct "'
+sends a copy of your response to " (if (string-match "," mct)
+                                      "the specified addresses"
+                                    "that address") ".")))
+       (setq mct nil))))
+
+    (unless follow-to
+      (cond
+       (to-newsgroups (setq follow-to (list (cons 'Newsgroups to-newsgroups))))
+       ;; Handle Followup-To.
+       (followup-to
+       (cond
+        ((equal (downcase followup-to) "poster")
+         (if (or (and followup-to (eq message-use-followup-to 'use))
+                 (message-y-or-n-p "Obey Followup-To: poster? " t "\
 You should normally obey the Followup-To: header.
 
-`Followup-To: poster' sends your response via e-mail instead of news.
+       `Followup-To: poster'
+sends your response via e-mail instead of news.
 
-A typical situation where `Followup-To: poster' is used is when the poster
+A typical situation where `Followup-To: poster' is used is when the author
 does not read the newsgroup, so he wouldn't see any replies sent to it."))
-                 (progn
-                   (setq message-this-is-news nil)
-                   (cons 'To (or reply-to from "")))
-               (cons 'Newsgroups newsgroups)))
-            (t
-             (if (or (equal followup-to newsgroups)
-                     (not (eq message-use-followup-to 'ask))
-                     (message-y-or-n-p
-                      (concat "Obey Followup-To: " followup-to "? ") t "\
+             (setq message-this-is-news nil
+                   distribution nil
+                   follow-to (list (cons 'To (or mrt reply-to from ""))))
+           (setq follow-to (list (cons 'Newsgroups newsgroups)))))
+        (t
+         (if (or (equal followup-to newsgroups)
+                 (not (and followup-to (eq message-use-followup-to 'ask)))
+                 (message-y-or-n-p
+                  (concat "Obey Followup-To: " followup-to "? ") t "\
 You should normally obey the Followup-To: header.
 
        `Followup-To: " followup-to "'
@@ -3357,57 +6566,117 @@ used to direct the following discussion to one newsgroup only,
 because discussions that are spread over several newsgroup tend to
 be fragmented and very difficult to follow.
 
-Also, some source/announcement newsgroups are not indented for discussion;
+Also, some source/announcement newsgroups are not intended for discussion;
 responses here are directed to other newsgroups."))
-                 (cons 'Newsgroups followup-to)
-               (cons 'Newsgroups newsgroups))))))
-         (posted-to
-          `((Newsgroups . ,posted-to)))
-         (t
-          `((Newsgroups . ,newsgroups))))
-       ,@(and distribution (list (cons 'Distribution distribution)))
-       ,@(if (or references message-id)
-            `((References . ,(concat (or references "") (and references " ")
-                                     (or message-id "")))))
-       ,@(when (and mct
-                   (not (equal (downcase mct) "never")))
-          (list (cons 'Cc (if (equal (downcase mct) "always")
-                              (or reply-to from "")
-                            mct)))))
-
-     cur)
+             (setq follow-to (list (cons 'Newsgroups followup-to)))
+           (setq follow-to (list (cons 'Newsgroups newsgroups)))))))
+       ;; Handle Mail-Followup-To, followup via e-mail.
+       ((and mft
+            (or (not (eq message-use-mail-followup-to 'ask))
+                (message-y-or-n-p
+                 (concat "Obey Mail-Followup-To: " mft "? ") t "\
+You should normally obey the Mail-Followup-To: header.
+
+       `Mail-Followup-To: " mft "'
+directs your response to " (if (string-match "," mft)
+                              "the specified addresses"
+                            "that address only") " instead of news.
+
+A typical situation where Mail-Followup-To is used is when the author thinks
+that further discussion should take place only in "
+                            (if (string-match "," mft)
+                                "the specified mailing lists"
+                              "that mailing list") ".")))
+       (setq message-this-is-news nil
+             distribution nil
+             follow-to (list (cons 'To mft))))
+       (posted-to (setq follow-to (list (cons 'Newsgroups posted-to))))
+       (t
+       (setq follow-to (list (cons 'Newsgroups newsgroups))))))
+
+    (message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
 
     (setq message-reply-headers
-         (vector 0 subject from date message-id references 0 0 ""))))
+         (make-full-mail-header-from-decoded-header
+          0 subject from date message-id references 0 0 ""))
+
+    (message-setup
+     `((Subject . ,subject)
+       ,@follow-to
+       ,@(and mct (list (cons 'Cc mct)))
+       ,@(and distribution (list (cons 'Distribution distribution))))
+     cur)))
 
+(defun message-is-yours-p ()
+  "Non-nil means current article is yours.
+If you have added 'cancel-messages to 'message-shoot-gnksa-feet', all articles
+are yours except those that have Cancel-Lock header not belonging to you.
+Instead of shooting GNKSA feet, you should modify 'message-alternative-emails'
+regexp to match all of yours addresses."
+  ;; Canlock-logic as suggested by Per Abrahamsen
+  ;; <abraham@dina.kvl.dk>
+  ;;
+  ;; IF article has cancel-lock THEN
+  ;;   IF we can verify it THEN
+  ;;     issue cancel
+  ;;   ELSE
+  ;;     error: cancellock: article is not yours
+  ;; ELSE
+  ;;   Use old rules, comparing sender...
+  (save-excursion
+    (save-restriction
+      (message-narrow-to-head-1)
+      (if (message-fetch-field "Cancel-Lock")
+         (if (null (canlock-verify))
+             t
+           (error "Failed to verify Cancel-lock: This article is not yours"))
+       (let (sender from)
+         (or
+          (message-gnksa-enable-p 'cancel-messages)
+          (and (setq sender (message-fetch-field "sender"))
+               (string-equal (downcase sender)
+                             (downcase (message-make-sender))))
+          ;; Email address in From field equals to our address
+          (and (setq from (message-fetch-field "from"))
+               (string-equal
+                (downcase (cadr (std11-extract-address-components from)))
+                (downcase (cadr (std11-extract-address-components
+                                 (message-make-from))))))
+          ;; Email address in From field matches
+          ;; 'message-alternative-emails' regexp
+          (and from
+               message-alternative-emails
+               (string-match
+                message-alternative-emails
+                (cadr (std11-extract-address-components from))))))))))
 
 ;;;###autoload
-(defun message-cancel-news ()
-  "Cancel an article you posted."
-  (interactive)
+(defun message-cancel-news (&optional arg)
+  "Cancel an article you posted.
+If ARG, allow editing of the cancellation message."
+  (interactive "P")
   (unless (message-news-p)
     (error "This is not a news article; canceling is impossible"))
-  (when (yes-or-no-p "Do you really want to cancel this article? ")
-    (let (from newsgroups message-id distribution buf)
-      (save-excursion
-       ;; Get header info. from original article.
-       (save-restriction
-         (message-narrow-to-head)
-         (setq from (message-fetch-field "from")
-               newsgroups (message-fetch-field "newsgroups")
-               message-id (message-fetch-field "message-id" t)
-               distribution (message-fetch-field "distribution")))
-       ;; Make sure that this article was written by the user.
-       (unless (string-equal
-                (downcase (cadr (mail-extract-address-components from)))
-                (downcase (message-make-address)))
-         (error "This article is not yours"))
+  (let (from newsgroups message-id distribution buf)
+    (save-excursion
+      ;; Get header info from original article.
+      (save-restriction
+       (message-narrow-to-head-1)
+       (setq from (message-fetch-field "from")
+             newsgroups (message-fetch-field "newsgroups")
+             message-id (message-fetch-field "message-id" t)
+             distribution (message-fetch-field "distribution")))
+      ;; Make sure that this article was written by the user.
+      (unless (message-is-yours-p)
+       (error "This article is not yours"))
+      (when (yes-or-no-p "Do you really want to cancel this article? ")
        ;; Make control message.
-       (setq buf (set-buffer (get-buffer-create " *message cancel*")))
-       (buffer-disable-undo (current-buffer))
+       (if arg
+           (message-news)
+         (setq buf (set-buffer (get-buffer-create " *message cancel*"))))
        (erase-buffer)
        (insert "Newsgroups: " newsgroups "\n"
-               "From: " (message-make-from) "\n"
+               "From: " from "\n"
                "Subject: cmsg cancel " message-id "\n"
                "Control: cancel " message-id "\n"
                (if distribution
@@ -3415,12 +6684,20 @@ responses here are directed to other newsgroups."))
                  "")
                mail-header-separator "\n"
                message-cancel-message)
-       (message "Canceling your article...")
-       (if (let ((message-syntax-checks
-                  'dont-check-for-anything-just-trust-me))
-             (funcall message-send-news-function))
-           (message "Canceling your article...done"))
-       (kill-buffer buf)))))
+       (run-hooks 'message-cancel-hook)
+       (unless arg
+         (message "Canceling your article...")
+         (if (let ((message-syntax-checks
+                    'dont-check-for-anything-just-trust-me)
+                   (message-encoding-buffer (current-buffer))
+                   (message-edit-buffer (current-buffer)))
+               (message-send-news))
+             (message "Canceling your article...done"))
+         (kill-buffer buf))))))
+
+(defun message-supersede-setup-for-mime-edit ()
+  (set (make-local-variable 'message-setup-hook) nil)
+  (mime-edit-again))
 
 ;;;###autoload
 (defun message-supersede ()
@@ -3430,15 +6707,12 @@ header line with the old Message-ID."
   (interactive)
   (let ((cur (current-buffer)))
     ;; Check whether the user owns the article that is to be superseded.
-    (unless (string-equal
-            (downcase (cadr (mail-extract-address-components
-                             (message-fetch-field "from"))))
-            (downcase (message-make-address)))
+    (unless (message-is-yours-p)
       (error "This article is not yours"))
     ;; Get a normal message buffer.
     (message-pop-to-buffer (message-buffer-name "supersede"))
     (insert-buffer-substring cur)
-    (message-narrow-to-head)
+    (message-narrow-to-head-1)
     ;; Remove unwanted headers.
     (when message-ignored-supersedes-headers
       (message-remove-header message-ignored-supersedes-headers t))
@@ -3449,7 +6723,11 @@ header line with the old Message-ID."
     (goto-char (point-max))
     (insert mail-header-separator)
     (widen)
-    (forward-line 1)))
+    (when message-supersede-setup-function
+      (funcall message-supersede-setup-function))
+    (run-hooks 'message-supersede-setup-hook)
+    (goto-char (point-min))
+    (search-forward (concat "\n" mail-header-separator "\n") nil t)))
 
 ;;;###autoload
 (defun message-recover ()
@@ -3459,6 +6737,8 @@ header line with the old Message-ID."
     (cond ((save-window-excursion
             (if (not (eq system-type 'vax-vms))
                 (with-output-to-temp-buffer "*Directory*"
+                  (with-current-buffer standard-output
+                    (fundamental-mode)) ; for Emacs 20.4+
                   (buffer-disable-undo standard-output)
                   (let ((default-directory "/"))
                     (call-process
@@ -3469,18 +6749,109 @@ header line with the old Message-ID."
             (insert-file-contents file-name nil)))
          (t (error "message-recover cancelled")))))
 
+;;; Washing Subject:
+
+(defun message-wash-subject (subject)
+  "Remove junk like \"Re:\", \"(fwd)\", etc. added to subject string SUBJECT.
+Previous forwarders, replyers, etc. may add it."
+  (with-temp-buffer
+    (insert subject)
+    (goto-char (point-min))
+    ;; strip Re/Fwd stuff off the beginning
+    (while (re-search-forward
+           "\\([Rr][Ee]:\\|[Ff][Ww][Dd]\\(\\[[0-9]*\\]\\)?:\\|[Ff][Ww]:\\)" nil t)
+      (replace-match ""))
+
+    ;; and gnus-style forwards [foo@bar.com] subject
+    (goto-char (point-min))
+    (while (re-search-forward "\\[[^ \t]*\\(@\\|\\.\\)[^ \t]*\\]" nil t)
+      (replace-match ""))
+
+    ;; and off the end
+    (goto-char (point-max))
+    (while (re-search-backward "([Ff][Ww][Dd])" nil t)
+      (replace-match ""))
+
+    ;; and finally, any whitespace that was left-over
+    (goto-char (point-min))
+    (while (re-search-forward "^[ \t]+" nil t)
+      (replace-match ""))
+    (goto-char (point-max))
+    (while (re-search-backward "[ \t]+$" nil t)
+      (replace-match ""))
+
+    (buffer-string)))
+
 ;;; Forwarding messages.
 
+(defvar message-forward-decoded-p nil
+  "Non-nil means the original message is decoded.")
+
+(defun message-forward-subject-name-subject (subject)
+  "Generate a SUBJECT for a forwarded message.
+The form is: [Source] Subject, where if the original message was mail,
+Source is the name of the sender, and if the original message was
+news, Source is the list of newsgroups is was posted to."
+  (concat "["
+         (let ((group (message-fetch-field "newsgroups"))
+               from)
+           (if group
+               (gnus-group-decoded-name group)
+             (or (and (setq from (message-fetch-field "from"))
+                      (car (std11-extract-address-components
+                            (nnheader-decode-from from))))
+                 "(nowhere)")))
+         "] " subject))
+
+(defun message-forward-subject-author-subject (subject)
+  "Generate a SUBJECT for a forwarded message.
+The form is: [Source] Subject, where if the original message was mail,
+Source is the sender, and if the original message was news, Source is
+the list of newsgroups is was posted to."
+  (concat "["
+         (let ((group (message-fetch-field "newsgroups"))
+               from)
+           (if group
+               (gnus-group-decoded-name group)
+             (if (setq from (message-fetch-field "from"))
+                 (nnheader-decode-from from)
+               "(nowhere)")))
+         "] " subject))
+
+(defun message-forward-subject-fwd (subject)
+  "Generate a SUBJECT for a forwarded message.
+The form is: Fwd: Subject, where Subject is the original subject of
+the message."
+  (if (string-match "^Fwd: " subject)
+      subject
+    (concat "Fwd: " subject)))
+
 (defun message-make-forward-subject ()
   "Return a Subject header suitable for the message in the current buffer."
   (save-excursion
     (save-restriction
-      (current-buffer)
-      (message-narrow-to-head)
-      (concat "[" (or (message-fetch-field
-                      (if (message-news-p) "newsgroups" "from"))
-                     "(nowhere)")
-             "] " (or (message-fetch-field "Subject") "")))))
+      (message-narrow-to-head-1)
+      (let ((funcs message-make-forward-subject-function)
+           (subject (message-fetch-field "Subject")))
+       (setq subject
+             (if subject
+                 (if message-forward-decoded-p
+                     subject
+                   (nnheader-decode-subject subject))
+               ""))
+       (if message-wash-forwarded-subjects
+           (setq subject (message-wash-subject subject)))
+       ;; Make sure funcs is a list.
+       (and funcs
+            (not (listp funcs))
+            (setq funcs (list funcs)))
+       ;; Apply funcs in order, passing subject generated by previous
+       ;; func to the next one.
+       (while funcs
+         (when (functionp (car funcs))
+           (setq subject (funcall (car funcs) subject)))
+         (setq funcs (cdr funcs)))
+       subject))))
 
 ;;;###autoload
 (defun message-forward (&optional news)
@@ -3488,23 +6859,132 @@ header line with the old Message-ID."
 Optional NEWS will use news to forward instead of mail."
   (interactive "P")
   (let ((cur (current-buffer))
-       (subject (message-make-forward-subject))
-       art-beg)
-    (if news (message-news nil subject) (message-mail nil subject))
-    ;; Put point where we want it before inserting the forwarded
-    ;; message.
-    (if message-signature-before-forwarded-message
-       (goto-char (point-max))
-      (message-goto-body))
-    ;; Make sure we're at the start of the line.
-    (unless (eolp)
-      (insert "\n"))
-    ;; Narrow to the area we are to insert.
-    (narrow-to-region (point) (point))
-    ;; Insert the separators and the forwarded buffer.
-    (insert message-forward-start-separator)
-    (setq art-beg (point))
-    (insert-buffer-substring cur)
+       (subject (message-make-forward-subject)))
+    (if news
+       (message-news nil subject)
+      (message-mail nil subject))
+    (message-forward-make-body cur)))
+
+(defun message-forward-make-body-plain (forward-buffer)
+  (insert
+   "\n-------------------- Start of forwarded message --------------------\n")
+  (let ((b (point)) e)
+    (insert
+     (with-temp-buffer
+       (mm-disable-multibyte)
+       (insert
+       (with-current-buffer forward-buffer
+         (mm-with-unibyte-current-buffer (buffer-string))))
+       (mm-enable-multibyte)
+       (mime-to-mml)
+       (goto-char (point-min))
+       (when (looking-at "From ")
+        (replace-match "X-From-Line: "))
+       (buffer-string)))
+    (setq e (point))
+    (insert
+     "\n-------------------- End of forwarded message --------------------\n")
+    (when (and (not current-prefix-arg)
+              message-forward-ignored-headers)
+      (save-restriction
+       (narrow-to-region b e)
+       (goto-char b)
+       (narrow-to-region (point)
+                         (or (search-forward "\n\n" nil t) (point)))
+       (message-remove-header message-forward-ignored-headers t)))))
+
+(defun message-forward-make-body-mime (forward-buffer)
+  (insert "\n\n<#part type=message/rfc822 disposition=inline raw=t>\n")
+  (let ((b (point)) e)
+    (save-restriction
+      (narrow-to-region (point) (point))
+      (mml-insert-buffer forward-buffer)
+      (goto-char (point-min))
+      (when (looking-at "From ")
+       (replace-match "X-From-Line: "))
+      (goto-char (point-max)))
+    (setq e (point))
+    (insert "<#/part>\n")))
+
+(defun message-forward-make-body-mml (forward-buffer)
+  (insert "\n\n<#mml type=message/rfc822 disposition=inline>\n")
+  (let ((b (point)) e)
+    (if (not message-forward-decoded-p)
+       (insert
+        (with-temp-buffer
+          (mm-disable-multibyte)
+          (insert
+           (with-current-buffer forward-buffer
+             (mm-with-unibyte-current-buffer (buffer-string))))
+          (mm-enable-multibyte)
+          (mime-to-mml)
+          (goto-char (point-min))
+          (when (looking-at "From ")
+            (replace-match "X-From-Line: "))
+          (buffer-string)))
+      (save-restriction
+       (narrow-to-region (point) (point))
+       (mml-insert-buffer forward-buffer)
+       (goto-char (point-min))
+       (when (looking-at "From ")
+         (replace-match "X-From-Line: "))
+       (goto-char (point-max))))
+    (setq e (point))
+    (insert "<#/mml>\n")
+    (when (and (not current-prefix-arg)
+              message-forward-ignored-headers)
+      (save-restriction
+       (narrow-to-region b e)
+       (goto-char b)
+       (narrow-to-region (point)
+                         (or (search-forward "\n\n" nil t) (point)))
+       (message-remove-header message-forward-ignored-headers t)))))
+
+(defun message-forward-make-body-digest-plain (forward-buffer)
+  (insert
+   "\n-------------------- Start of forwarded message --------------------\n")
+  (let ((b (point)) e)
+    (mml-insert-buffer forward-buffer)
+    (setq e (point))
+    (insert
+     "\n-------------------- End of forwarded message --------------------\n")))
+
+(defun message-forward-make-body-digest-mime (forward-buffer)
+  (insert "\n<#multipart type=digest>\n")
+  (let ((b (point)) e)
+    (insert-buffer-substring forward-buffer)
+    (setq e (point))
+    (insert "<#/multipart>\n")
+    (save-restriction
+      (narrow-to-region b e)
+      (goto-char b)
+      (narrow-to-region (point)
+                       (or (search-forward "\n\n" nil t) (point)))
+      (delete-region (point-min) (point-max)))))
+
+(defun message-forward-make-body-digest (forward-buffer)
+  (if message-forward-as-mime
+      (message-forward-make-body-digest-mime forward-buffer)
+    (message-forward-make-body-digest-plain forward-buffer)))
+
+;;;###autoload
+(defun message-forward-make-body (forward-buffer)
+  ;; Put point where we want it before inserting the forwarded
+  ;; message.
+  ;; Note that this function definition for T-gnus is totally different
+  ;; from the original Gnus."
+  (if message-forward-before-signature
+      (message-goto-body)
+    (goto-char (point-max)))
+  ;; Make sure we're at the start of the line.
+  (unless (bolp)
+    (insert "\n"))
+  ;; Narrow to the area we are to insert.
+  (narrow-to-region (point) (point))
+  ;; Insert the separators and the forwarded buffer.
+  (insert message-forward-start-separator)
+  (let ((art-beg (point)))
+    (insert-buffer-substring forward-buffer)
     (goto-char (point-max))
     (insert message-forward-end-separator)
     (set-text-properties (point-min) (point-max) nil)
@@ -3519,22 +6999,49 @@ Optional NEWS will use news to forward instead of mail."
     (message-position-point)))
 
 ;;;###autoload
+(defun message-forward-rmail-make-body (forward-buffer)
+  (save-window-excursion
+    (set-buffer forward-buffer)
+    ;; Rmail doesn't have rmail-msg-restore-non-pruned-header in Emacs
+    ;; 20.  FIXIT, or we drop support for rmail in Emacs 20.
+    (if (rmail-msg-is-pruned)
+       (rmail-msg-restore-non-pruned-header)))
+  (message-forward-make-body forward-buffer))
+
+(eval-when-compile (defvar rmail-enable-mime-composing))
+
+;; Fixme: Should have defcustom.
+;;;###autoload
+(defun message-insinuate-rmail ()
+  "Let RMAIL use message to forward."
+  (interactive)
+  (setq rmail-enable-mime-composing t)
+  (setq rmail-insert-mime-forwarded-message-function
+       'message-forward-rmail-make-body))
+
+;;;###autoload
 (defun message-resend (address)
   "Resend the current article to ADDRESS."
-  (interactive "sResend message to: ")
+  (interactive
+   (list (message-read-from-minibuffer "Resend message to: ")))
   (message "Resending message to %s..." address)
   (save-excursion
     (let ((cur (current-buffer))
          beg)
       ;; We first set up a normal mail buffer.
-      (set-buffer (get-buffer-create " *message resend*"))
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
-      (message-setup `((To . ,address)))
+      (unless (message-mail-user-agent)
+       (set-buffer (get-buffer-create " *message resend*"))
+       (erase-buffer))
+      (let ((message-this-is-mail t)
+           message-setup-hook)
+       (message-setup `((To . ,address))))
       ;; Insert our usual headers.
-      (message-generate-headers '(From Date To))
+      (message-generate-headers '(From Date To Message-ID))
       (message-narrow-to-headers)
+      ;; Remove X-Draft-From header etc.
+      (message-remove-header message-ignored-mail-headers t)
       ;; Rename them all to "Resent-*".
+      (goto-char (point-min))
       (while (re-search-forward "^[A-Za-z]" nil t)
        (forward-char -1)
        (insert "Resent-"))
@@ -3561,49 +7068,65 @@ Optional NEWS will use news to forward instead of mail."
       (when (looking-at "From ")
        (replace-match "X-From-Line: "))
       ;; Send it.
-      (message-send-mail)
+      (let ((message-encoding-buffer (current-buffer))
+           (message-edit-buffer (current-buffer))
+           message-required-mail-headers)
+       (message-send-mail))
       (kill-buffer (current-buffer)))
     (message "Resending message to %s...done" address)))
 
+(defun message-bounce-setup-for-mime-edit ()
+  (set (make-local-variable 'message-setup-hook) nil)
+  (mime-edit-again))
+
 ;;;###autoload
 (defun message-bounce ()
   "Re-mail the current message.
-This only makes sense if the current message is a bounce message than
+This only makes sense if the current message is a bounce message that
 contains some mail you have written which has been bounced back to
 you."
   (interactive)
   (let ((cur (current-buffer))
-       boundary)
+       mime-boundary boundary)
     (message-pop-to-buffer (message-buffer-name "bounce"))
     (insert-buffer-substring cur)
     (undo-boundary)
     (message-narrow-to-head)
-    (if (and (message-fetch-field "Mime-Version")
-            (setq boundary (message-fetch-field "Content-Type")))
-       (if (string-match "boundary=\"\\([^\"]+\\)\"" boundary)
-           (setq boundary (concat (match-string 1 boundary) " *\n"
-                                  "Content-Type: message/rfc822"))
-         (setq boundary nil)))
+    (if (and (message-fetch-field "MIME-Version")
+            (setq mime-boundary (message-fetch-field "Content-Type")))
+       (if (string-match "boundary=\"\\([^\"]+\\)\"" mime-boundary)
+           (setq mime-boundary (concat (regexp-quote
+                                        (match-string 1 mime-boundary))
+                                       " *\nContent-Type: message/rfc822"))
+         (setq mime-boundary nil)))
     (widen)
     (goto-char (point-min))
-    (search-forward "\n\n" nil t)
-    (or (and boundary
-            (re-search-forward boundary nil t)
-            (forward-line 2))
-       (and (re-search-forward message-unsent-separator nil t)
-            (forward-line 1))
-       (re-search-forward "^Return-Path:.*\n" nil t))
+    (re-search-forward "\n\n+" nil t)
+    (setq boundary (point))
     ;; We remove everything before the bounced mail.
-    (delete-region
-     (point-min)
-     (if (re-search-forward "^[^ \n\t]+:" nil t)
-        (match-beginning 0)
-       (point)))
+    (if (or (and mime-boundary
+                (re-search-forward mime-boundary nil t)
+                (forward-line 1))
+           (re-search-forward message-unsent-separator nil t)
+           (progn
+             (search-forward "\n\n" nil 'move)
+             (re-search-backward "^Return-Path:.*\n" boundary t)))
+       (progn
+         (forward-line 1)
+         (delete-region (point-min)
+                        (if (re-search-forward "^[^ \n\t]+:" nil t)
+                            (match-beginning 0)
+                          (point))))
+      (when (re-search-backward "^.?From .*\n" nil t)
+       (delete-region (match-beginning 0) (match-end 0))))
     (save-restriction
-      (message-narrow-to-head)
+      (message-narrow-to-head-1)
       (message-remove-header message-ignored-bounced-headers t)
       (goto-char (point-max))
       (insert mail-header-separator))
+    (when message-bounce-setup-function
+      (funcall message-bounce-setup-function))
+    (run-hooks 'message-bounce-setup-hook)
     (message-position-point)))
 
 ;;;
@@ -3614,25 +7137,31 @@ you."
 (defun message-mail-other-window (&optional to subject)
   "Like `message-mail' command, but display mail buffer in another window."
   (interactive)
-  (let ((pop-up-windows t)
-       (special-display-buffer-names nil)
-       (special-display-regexps nil)
-       (same-window-buffer-names nil)
-       (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "mail" to)))
-  (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
+  (unless (message-mail-user-agent)
+    (let ((pop-up-windows t)
+         (special-display-buffer-names nil)
+         (special-display-regexps nil)
+         (same-window-buffer-names nil)
+         (same-window-regexps nil))
+      (message-pop-to-buffer (message-buffer-name "mail" to))))
+  (let ((message-this-is-mail t))
+    (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))
+                  nil nil 'switch-to-buffer-other-window)))
 
 ;;;###autoload
 (defun message-mail-other-frame (&optional to subject)
   "Like `message-mail' command, but display mail buffer in another frame."
   (interactive)
-  (let ((pop-up-frames t)
-       (special-display-buffer-names nil)
-       (special-display-regexps nil)
-       (same-window-buffer-names nil)
-       (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "mail" to)))
-  (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))))
+  (unless (message-mail-user-agent)
+    (let ((pop-up-frames t)
+         (special-display-buffer-names nil)
+         (special-display-regexps nil)
+         (same-window-buffer-names nil)
+         (same-window-regexps nil))
+      (message-pop-to-buffer (message-buffer-name "mail" to))))
+  (let ((message-this-is-mail t))
+    (message-setup `((To . ,(or to "")) (Subject . ,(or subject "")))
+                  nil nil 'switch-to-buffer-other-frame)))
 
 ;;;###autoload
 (defun message-news-other-window (&optional newsgroups subject)
@@ -3643,9 +7172,10 @@ you."
        (special-display-regexps nil)
        (same-window-buffer-names nil)
        (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
-  (message-setup `((Newsgroups . ,(or newsgroups ""))
-                  (Subject . ,(or subject "")))))
+    (message-pop-to-buffer (message-buffer-name "posting" nil newsgroups)))
+  (let ((message-this-is-news t))
+    (message-setup `((Newsgroups . ,(or newsgroups ""))
+                    (Subject . ,(or subject ""))))))
 
 ;;;###autoload
 (defun message-news-other-frame (&optional newsgroups subject)
@@ -3656,9 +7186,10 @@ you."
        (special-display-regexps nil)
        (same-window-buffer-names nil)
        (same-window-regexps nil))
-    (message-pop-to-buffer (message-buffer-name "news" nil newsgroups)))
-  (message-setup `((Newsgroups . ,(or newsgroups ""))
-                  (Subject . ,(or subject "")))))
+    (message-pop-to-buffer (message-buffer-name "posting" nil newsgroups)))
+  (let ((message-this-is-news t))
+    (message-setup `((Newsgroups . ,(or newsgroups ""))
+                    (Subject . ,(or subject ""))))))
 
 ;;; underline.el
 
@@ -3677,7 +7208,7 @@ which specify the range to operate on."
       (goto-char (min start end))
       (while (< (point) end1)
        (or (looking-at "[_\^@- ]")
-           (insert (following-char) "\b"))
+           (insert (char-after) "\b"))
        (forward-char 1)))))
 
 ;;;###autoload
@@ -3691,33 +7222,124 @@ which specify the range to operate on."
       (move-marker end1 (max start end))
       (goto-char (min start end))
       (while (re-search-forward "\b" end1 t)
-       (if (eq (following-char) (char-after (- (point) 2)))
+       (if (eq (char-after) (char-after (- (point) 2)))
            (delete-char -2))))))
 
 (defalias 'message-exchange-point-and-mark 'exchange-point-and-mark)
+(defalias 'message-make-overlay 'make-overlay)
+(defalias 'message-delete-overlay 'delete-overlay)
+(defalias 'message-overlay-put 'overlay-put)
+(defun message-kill-all-overlays ()
+  (if (featurep 'xemacs)
+      (map-extents (lambda (extent ignore) (delete-extent extent)))
+    (mapcar #'delete-overlay (overlays-in (point-min) (point-max)))))
 
 ;; Support for toolbar
-(when (string-match "XEmacs\\|Lucid" emacs-version)
-  (require 'messagexmas))
+(eval-when-compile
+  (defvar tool-bar-map)
+  (defvar tool-bar-mode))
+
+(defun message-tool-bar-local-item-from-menu (command icon in-map &optional from-map &rest props)
+  ;; We need to make tool bar entries in local keymaps with
+  ;; `tool-bar-local-item-from-menu' in Emacs > 21.3
+  (if (fboundp 'tool-bar-local-item-from-menu)
+      ;; This is for Emacs 21.3
+      (tool-bar-local-item-from-menu command icon in-map from-map props)
+    (tool-bar-add-item-from-menu command icon from-map props)))
+
+(defun message-tool-bar-map ()
+  (or message-tool-bar-map
+      (setq message-tool-bar-map
+           (and
+            (condition-case nil (require 'tool-bar) (error nil))
+            (fboundp 'tool-bar-add-item-from-menu)
+            tool-bar-mode
+            (let ((tool-bar-map (copy-keymap tool-bar-map))
+                  (load-path (mm-image-load-path)))
+              ;; Zap some items which aren't so relevant and take
+              ;; up space.
+              (dolist (key '(print-buffer kill-buffer save-buffer
+                                          write-file dired open-file))
+                (define-key tool-bar-map (vector key) nil))
+              (message-tool-bar-local-item-from-menu
+               'message-send-and-exit "mail_send" tool-bar-map message-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'message-kill-buffer "close" tool-bar-map message-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'message-dont-send "cancel" tool-bar-map message-mode-map)
+;;            (message-tool-bar-local-item-from-menu
+;;             'mime-edit-insert-file "attach"
+;;             tool-bar-map mime-edit-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'ispell-message "spell" tool-bar-map message-mode-map)
+;;            (message-tool-bar-local-item-from-menu
+;;             'mime-edit-preview-message "preview"
+;;             tool-bar-map mime-edit-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'message-insert-importance-high "important"
+               tool-bar-map message-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'message-insert-importance-low "unimportant"
+               tool-bar-map message-mode-map)
+              (message-tool-bar-local-item-from-menu
+               'message-insert-disposition-notification-to "receipt"
+               tool-bar-map message-mode-map)
+              tool-bar-map)))))
 
 ;;; Group name completion.
 
-(defvar message-newgroups-header-regexp
+(defcustom message-newgroups-header-regexp
   "^\\(Newsgroups\\|Followup-To\\|Posted-To\\|Gcc\\):"
-  "Regexp that match headers that lists groups.")
+  "Regexp that match headers that lists groups."
+  :group 'message
+  :type 'regexp)
+
+(defcustom message-completion-alist
+  (list (cons message-newgroups-header-regexp 'message-expand-group)
+       '("^\\(Resent-\\)?\\(To\\|B?Cc\\):" . message-expand-name)
+       '("^\\(Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\):"
+         . message-expand-name)
+       '("^\\(Disposition-Notification-To\\|Return-Receipt-To\\):"
+         . message-expand-name))
+  "Alist of (RE . FUN).  Use FUN for completion on header lines matching RE."
+  :group 'message
+  :type '(alist :key-type regexp :value-type function))
+
+(defcustom message-expand-name-function
+  (if (fboundp 'bbdb-complete-name)
+      'bbdb-complete-name
+    (if (fboundp 'lsdb-complete-name)
+       'lsdb-complete-name
+      'expand-abbrev))
+  "*A function called to expand addresses in field body."
+  :group 'message
+  :type 'function)
+
+(defcustom message-tab-body-function nil
+  "*Function to execute when `message-tab' (TAB) is executed in the body.
+If nil, the function bound in `text-mode-map' or `global-map' is executed."
+  :group 'message
+  :link '(custom-manual "(message)Various Commands")
+  :type 'function)
 
 (defun message-tab ()
-  "Expand group names in Newsgroups and Followup-To headers.
-Do a `tab-to-tab-stop' if not in those headers."
+  "Complete names according to `message-completion-alist'.
+Execute function specified by `message-tab-body-function' when not in
+those headers."
   (interactive)
-  (if (let ((mail-abbrev-mode-regexp message-newgroups-header-regexp))
-       (mail-abbrev-in-expansion-header-p))
-      (message-expand-group)
-    (tab-to-tab-stop)))
+  (let ((alist message-completion-alist))
+    (while (and alist
+               (let ((mail-abbrev-mode-regexp (caar alist)))
+                 (not (mail-abbrev-in-expansion-header-p))))
+      (setq alist (cdr alist)))
+    (funcall (or (cdar alist) message-tab-body-function
+                (lookup-key text-mode-map "\t")
+                (lookup-key global-map "\t")
+                'indent-relative))))
 
-(defvar gnus-active-hashtb)
 (defun message-expand-group ()
-  "Expand the group name under point."  (let* ((b (save-excursion
+  "Expand the group name under point."
+  (let* ((b (save-excursion
              (save-restriction
                (narrow-to-region
                 (save-excursion
@@ -3727,10 +7349,10 @@ Do a `tab-to-tab-stop' if not in those headers."
                 (point))
                (skip-chars-backward "^, \t\n") (point))))
         (completion-ignore-case t)
-        (string (buffer-substring b (point)))
+        (string (buffer-substring b (progn (skip-chars-forward "^,\t\n ")
+                                           (point))))
         (hashtb (and (boundp 'gnus-active-hashtb) gnus-active-hashtb))
         (completions (all-completions string hashtb))
-        (cur (current-buffer))
         comp)
     (delete-region b (point))
     (cond
@@ -3749,7 +7371,7 @@ Do a `tab-to-tab-stop' if not in those headers."
          (message "No matching groups")
        (save-selected-window
          (pop-to-buffer "*Completions*")
-         (buffer-disable-undo (current-buffer))
+         (buffer-disable-undo)
          (let ((buffer-read-only nil))
            (erase-buffer)
            (let ((standard-output (current-buffer)))
@@ -3757,6 +7379,9 @@ Do a `tab-to-tab-stop' if not in those headers."
            (goto-char (point-min))
            (delete-region (point) (progn (forward-line 3) (point))))))))))
 
+(defun message-expand-name ()
+  (funcall message-expand-name-function))
+
 ;;; Help stuff.
 
 (defun message-talkative-question (ask question show &rest text)
@@ -3769,6 +7394,7 @@ The following arguments may contain lists of values."
        (save-excursion
          (with-output-to-temp-buffer " *MESSAGE information message*"
            (set-buffer " *MESSAGE information message*")
+           (fundamental-mode)          ; for Emacs 20.4+
            (mapcar 'princ text)
            (goto-char (point-min))))
        (funcall ask question))
@@ -3785,49 +7411,227 @@ The following arguments may contain lists of values."
         (list list))))
 
 (defun message-generate-new-buffer-clone-locals (name &optional varstr)
-  "Create and return a buffer with a name based on NAME using generate-new-buffer.
+  "Create and return a buffer with name based on NAME using `generate-new-buffer'.
 Then clone the local variables and values from the old buffer to the
 new one, cloning only the locals having a substring matching the
-regexp varstr."
+regexp VARSTR."
   (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\\|full-name\\)\\)"))
     (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)))))
      locals)))
 
-;;; Miscellaneous functions
-
-;; stolen (and renamed) from nnheader.el
-(defun message-replace-chars-in-string (string from to)
-  "Replace characters in STRING from FROM to TO."
-  (let ((string (substring string 0))  ;Copy string.
-       (len (length string))
-       (idx 0))
-    ;; Replace all occurrences of FROM with TO.
-    (while (< idx len)
-      (when (= (aref string idx) from)
-       (aset string idx to))
-      (setq idx (1+ idx)))
-    string))
+;;; @ for MIME Edit mode
+;;;
 
-(run-hooks 'message-load-hook)
+(defun message-maybe-encode ()
+  (when message-mime-mode
+    ;; Inherit the buffer local variable `mime-edit-pgp-processing'.
+    (let ((pgp-processing (with-current-buffer message-edit-buffer
+                           mime-edit-pgp-processing)))
+      (setq mime-edit-pgp-processing pgp-processing))
+    (run-hooks 'mime-edit-translate-hook)
+    (if (catch 'mime-edit-error
+         (save-excursion
+           (mime-edit-pgp-enclose-buffer)
+           (mime-edit-translate-body)))
+       (error "Translation error!"))
+    (run-hooks 'mime-edit-exit-hook)))
+
+(defun message-mime-insert-article (&optional full-headers)
+  (interactive "P")
+  (let ((message-cite-function 'mime-edit-inserted-message-filter)
+       (message-reply-buffer
+        (message-get-parameter-with-eval 'original-buffer))
+       (start (point)))
+    (message-yank-original nil)
+    (save-excursion
+      (narrow-to-region (goto-char start)
+                       (if (search-forward "\n\n" nil t)
+                           (1- (point))
+                         (point-max)))
+      (goto-char (point-min))
+      (let ((message-included-forward-headers
+            (if full-headers "" message-included-forward-headers)))
+       (message-remove-header message-included-forward-headers t nil t))
+      (widen))))
+
+(set-alist 'mime-edit-message-inserter-alist
+          'message-mode (function message-mime-insert-article))
+
+;;;
+;;; MIME functions
+;;;
+
+(defvar message-inhibit-body-encoding t)
+
+(defun message-encode-message-body ()
+  (unless message-inhibit-body-encoding
+    (let ((mail-parse-charset (or mail-parse-charset
+                                 message-default-charset))
+         (case-fold-search t)
+         lines content-type-p)
+      (message-goto-body)
+      (save-restriction
+       (narrow-to-region (point) (point-max))
+       (let ((new (mml-generate-mime)))
+         (when new
+           (delete-region (point-min) (point-max))
+           (insert new)
+           (goto-char (point-min))
+           (if (eq (aref new 0) ?\n)
+               (delete-char 1)
+             (search-forward "\n\n")
+             (setq lines (buffer-substring (point-min) (1- (point))))
+             (delete-region (point-min) (point))))))
+      (save-restriction
+       (message-narrow-to-headers-or-head)
+       (message-remove-header "Mime-Version")
+       (goto-char (point-max))
+       (insert "MIME-Version: 1.0\n")
+       (when lines
+         (insert lines))
+       (setq content-type-p
+             (or mml-boundary
+                 (re-search-backward "^Content-Type:" nil t))))
+      (save-restriction
+       (message-narrow-to-headers-or-head)
+       (message-remove-first-header "Content-Type")
+       (message-remove-first-header "Content-Transfer-Encoding"))
+      ;; We always make sure that the message has a Content-Type
+      ;; header.  This is because some broken MTAs and MUAs get
+      ;; awfully confused when confronted with a message with a
+      ;; MIME-Version header and without a Content-Type header.  For
+      ;; instance, Solaris' /usr/bin/mail.
+      (unless content-type-p
+       (goto-char (point-min))
+       ;; For unknown reason, MIME-Version doesn't exist.
+       (when (re-search-forward "^MIME-Version:" nil t)
+         (forward-line 1)
+         (insert "Content-Type: text/plain; charset=us-ascii\n"))))))
+
+(defun message-read-from-minibuffer (prompt &optional initial-contents)
+  "Read from the minibuffer while providing abbrev expansion."
+  (if (fboundp 'mail-abbrevs-setup)
+      (let ((mail-abbrev-mode-regexp "")
+           (minibuffer-setup-hook 'mail-abbrevs-setup)
+           (minibuffer-local-map message-minibuffer-local-map))
+       (read-from-minibuffer prompt initial-contents))
+    (let ((minibuffer-setup-hook 'mail-abbrev-minibuffer-setup-hook)
+         (minibuffer-local-map message-minibuffer-local-map))
+      (read-string prompt initial-contents))))
+
+(defun message-use-alternative-email-as-from ()
+  (require 'mail-utils)
+  (let* ((fields '("To" "Cc"))
+        (emails
+         (split-string
+          (mail-strip-quoted-names
+           (mapconcat 'message-fetch-reply-field fields ","))
+          "[ \f\t\n\r\v,]+"))
+        email)
+    (while emails
+      (if (string-match message-alternative-emails (car emails))
+         (setq email (car emails)
+               emails nil))
+      (pop emails))
+    (unless (or (not email) (equal email user-mail-address))
+      (goto-char (point-max))
+      (insert "From: " email "\n"))))
+
+(defun message-options-get (symbol)
+  (cdr (assq symbol message-options)))
+
+(defun message-options-set (symbol value)
+  (let ((the-cons (assq symbol message-options)))
+    (if the-cons
+       (if value
+           (setcdr the-cons value)
+         (setq message-options (delq the-cons message-options)))
+      (and value
+          (push (cons symbol value) message-options))))
+  value)
+
+(defun message-options-set-recipient ()
+  (save-restriction
+    (message-narrow-to-headers-or-head)
+    (message-options-set 'message-sender
+                        (mail-strip-quoted-names
+                         (message-fetch-field "from")))
+    (message-options-set 'message-recipients
+                        (mail-strip-quoted-names
+                         (let ((to (message-fetch-field "to"))
+                               (cc (message-fetch-field "cc"))
+                               (bcc (message-fetch-field "bcc")))
+                           (concat
+                            (or to "")
+                            (if (and to cc) ", ")
+                            (or cc "")
+                            (if (and (or to cc) bcc) ", ")
+                            (or bcc "")))))))
+
+(defun message-hide-headers ()
+  "Hide headers based on the `message-hidden-headers' variable."
+  (let ((regexps (if (stringp message-hidden-headers)
+                    (list message-hidden-headers)
+                  message-hidden-headers))
+       (inhibit-point-motion-hooks t)
+       (after-change-functions nil))
+    (when regexps
+      (save-excursion
+       (save-restriction
+         (message-narrow-to-headers)
+         (goto-char (point-min))
+         (while (not (eobp))
+           (if (not (message-hide-header-p regexps))
+               (message-next-header)
+             (let ((begin (point)))
+               (message-next-header)
+               (add-text-properties
+                begin (point)
+                '(invisible t message-hidden t))))))))))
+
+(defun message-hide-header-p (regexps)
+  (let ((result nil)
+       (reverse nil))
+    (when (eq (car regexps) 'not)
+      (setq reverse t)
+      (pop regexps))
+    (dolist (regexp regexps)
+      (setq result (or result (looking-at regexp))))
+    (if reverse
+       (not result)
+      result)))
+
+(when (featurep 'xemacs)
+  (require 'messagexmas)
+  (message-xmas-redefine))
 
 (provide 'message)
 
+(run-hooks 'message-load-hook)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
 ;;; message.el ends here
index 73f4cd4..d94afa8 100644 (file)
@@ -1,7 +1,9 @@
 ;;; messagexmas.el --- XEmacs extensions to message
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2003
+;;      Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, news
 
 ;; This file is part of GNU Emacs.
@@ -25,6 +27,7 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
 (require 'nnheader)
 
 (defvar message-xmas-dont-activate-region t
@@ -39,7 +42,7 @@ automatically.")
                                'default-toolbar
                              nil)
   "*If nil, do not use a toolbar.
-If it is non-nil, it must be a toolbar.  The five legal values are
+If it is non-nil, it must be a toolbar.  The five valid values are
 `default-toolbar', `top-toolbar', `bottom-toolbar',
 `right-toolbar', and `left-toolbar'.")
 
@@ -90,8 +93,6 @@ If it is non-nil, it must be a toolbar.  The five legal values are
   "Exchange point and mark, but allow for XEmacs' optional argument."
   (exchange-point-and-mark message-xmas-dont-activate-region))
 
-(fset 'message-exchange-point-and-mark 'message-xmas-exchange-point-and-mark)
-
 (defun message-xmas-maybe-fontify ()
   (when (featurep 'font-lock)
     (font-lock-set-defaults)))
@@ -113,12 +114,23 @@ If it is non-nil, it must be a toolbar.  The five legal values are
      (substring table a (+ a n))
      (substring table (+ a 26) 255))))
 
-(when (>= emacs-major-version 20)
-  (fset 'message-make-caesar-translation-table
-       'message-xmas-make-caesar-translation-table))
-
 (add-hook 'message-mode-hook 'message-xmas-maybe-fontify)
 
+(defun message-xmas-redefine ()
+  "Redefine message functions for XEmacs."
+  (defalias 'message-exchange-point-and-mark
+    'message-xmas-exchange-point-and-mark)
+  (defalias 'message-mark-active-p
+    'region-exists-p)
+  (when (>= emacs-major-version 20)
+    (defalias 'message-make-caesar-translation-table
+      'message-xmas-make-caesar-translation-table))
+  (defalias 'message-make-overlay 'make-extent)
+  (defalias 'message-delete-overlay 'delete-extent)
+  (defalias 'message-overlay-put 'set-extent-property))
+
+(message-xmas-redefine)
+
 (provide 'messagexmas)
 
 ;;; messagexmas.el ends here
index d363700..ff7520f 100644 (file)
@@ -1,7 +1,9 @@
 ;;; messcompat.el --- making message mode compatible with mail mode
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, news
 
 ;; This file is part of GNU Emacs.
@@ -23,7 +25,7 @@
 
 ;;; Commentary:
 
-;; This file tries to provide backward compatability with sendmail.el
+;; This file tries to provide backward compatibility with sendmail.el
 ;; for Message mode.  It should be used by simply adding
 ;;
 ;; (require 'messcompat)
@@ -38,7 +40,7 @@
 (defvar message-from-style mail-from-style
   "*Specifies how \"From\" headers look.
 
-If `nil', they contain just the return address like:
+If nil, they contain just the return address like:
        king@grassland.com
 If `parens', they look like:
        king@grassland.com (Elvis Parsley)
@@ -72,7 +74,7 @@ If a form, the result from the form will be used instead.")
 
 ;; Deleted the autoload cookie because this crashes in loaddefs.el.
 (defvar message-signature-file mail-signature-file
-  "*File containing the text inserted at end of message. buffer.")
+  "*File containing the text inserted at end of the message buffer.")
 
 (defvar message-default-headers mail-default-headers
   "*A string containing header lines to be inserted in outgoing messages.
@@ -82,6 +84,11 @@ these lines.")
 (defvar message-send-hook mail-send-hook
   "Hook run before sending messages.")
 
+(defvar message-send-mail-function send-mail-function
+  "Function to call to send the current buffer as mail.
+The headers should be delimited by a line whose contents match the
+variable `mail-header-separator'.")
+
 (provide 'messcompat)
 
 ;;; messcompat.el ends here
diff --git a/lisp/mm-bodies.el b/lisp/mm-bodies.el
new file mode 100644 (file)
index 0000000..3475168
--- /dev/null
@@ -0,0 +1,290 @@
+;;; mm-bodies.el --- Functions for decoding MIME things
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-and-compile
+  (or (fboundp  'base64-decode-region)
+      (require 'base64)))
+
+(eval-when-compile
+  (defvar mm-uu-decode-function)
+  (defvar mm-uu-binhex-decode-function))
+
+(require 'mm-util)
+(require 'rfc2047)
+(require 'mm-encode)
+
+;; 8bit treatment gets any char except: 0x32 - 0x7f, CR, LF, TAB, BEL,
+;; BS, vertical TAB, form feed, and ^_
+(defvar mm-7bit-chars "\x20-\x7f\r\n\t\x7\x8\xb\xc\x1f")
+
+(defcustom mm-body-charset-encoding-alist
+  '((iso-2022-jp . 7bit)
+    (iso-2022-jp-2 . 7bit)
+    ;; We MUST encode UTF-16 because it can contain \0's which is
+    ;; known to break servers.
+    ;; Note: UTF-16 variants are invalid for text parts [RFC 2781],
+    ;; so this can't happen :-/.
+    (utf-16 . base64)
+    (utf-16be . base64)
+    (utf-16le . base64))
+  "Alist of MIME charsets to encodings.
+Valid encodings are `7bit', `8bit', `quoted-printable' and `base64'."
+  :type '(repeat (cons (symbol :tag "charset")
+                      (choice :tag "encoding"
+                              (const 7bit)
+                              (const 8bit)
+                              (const quoted-printable)
+                              (const base64))))
+  :group 'mime)
+
+(defun mm-encode-body (&optional charset)
+  "Encode a body.
+Should be called narrowed to the body that is to be encoded.
+If there is more than one non-ASCII MULE charset in the body, then the
+list of MULE charsets found is returned.
+If CHARSET is non-nil, it is used as the MIME charset to encode the body.
+If successful, the MIME charset is returned.
+If no encoding was done, nil is returned."
+  (if (not (mm-multibyte-p))
+      ;; In the non-Mule case, we search for non-ASCII chars and
+      ;; return the value of `mail-parse-charset' if any are found.
+      (or charset
+         (save-excursion
+           (goto-char (point-min))
+           (if (re-search-forward "[^\x0-\x7f]" nil t)
+               (or mail-parse-charset
+                   (message-options-get 'mm-encody-body-charset)
+                   (message-options-set
+                    'mm-encody-body-charset
+                    (mm-read-coding-system "Charset used in the article: ")))
+             ;; The logic in `mml-generate-mime-1' confirms that it's OK
+             ;; to return nil here.
+             nil)))
+    (save-excursion
+      (if charset
+         (progn
+           (mm-encode-coding-region (point-min) (point-max) charset)
+           charset)
+       (goto-char (point-min))
+       (let ((charsets (mm-find-mime-charset-region (point-min) (point-max)
+                                                    mm-hack-charsets)))
+         (cond
+          ;; No encoding.
+          ((null charsets)
+           nil)
+          ;; Too many charsets.
+          ((> (length charsets) 1)
+           charsets)
+          ;; We encode.
+          (t
+           (prog1
+               (setq charset (car charsets))
+             (mm-encode-coding-region (point-min) (point-max)
+                                      (mm-charset-to-coding-system charset))))
+          ))))))
+
+(defun mm-long-lines-p (length)
+  "Say whether any of the lines in the buffer is longer than LENGTH."
+  (save-excursion
+    (goto-char (point-min))
+    (end-of-line)
+    (while (and (not (eobp))
+               (not (> (current-column) length)))
+      (forward-line 1)
+      (end-of-line))
+    (and (> (current-column) length)
+        (current-column))))
+
+(defvar message-posting-charset)
+
+(defun mm-body-encoding (charset &optional encoding)
+  "Do Content-Transfer-Encoding and return the encoding of the current buffer."
+  (when (stringp encoding)
+    (setq encoding (intern (downcase encoding))))
+  (let ((bits (mm-body-7-or-8))
+       (longp (mm-long-lines-p 1000)))
+    (require 'message)
+    (cond
+     ((and (not longp)
+          (not (and mm-use-ultra-safe-encoding
+                    (save-excursion (re-search-forward "^From " nil t))))
+          (eq bits '7bit))
+      bits)
+     ((and (not mm-use-ultra-safe-encoding)
+          (not longp)
+          (not (cdr (assq charset mm-body-charset-encoding-alist)))
+          (or (eq t (cdr message-posting-charset))
+              (memq charset (cdr message-posting-charset))
+              (eq charset mail-parse-charset)))
+      bits)
+     (t
+      (let ((encoding (or encoding
+                         (cdr (assq charset mm-body-charset-encoding-alist))
+                         (mm-qp-or-base64))))
+       (when mm-use-ultra-safe-encoding
+         (setq encoding (mm-safer-encoding encoding)))
+       (mm-encode-content-transfer-encoding encoding "text/plain")
+       encoding)))))
+
+(defun mm-body-7-or-8 ()
+  "Say whether the body is 7bit or 8bit."
+  (if (save-excursion
+       (goto-char (point-min))
+       (skip-chars-forward mm-7bit-chars)
+       (eobp))
+      '7bit
+    '8bit))
+
+;;;
+;;; Functions for decoding
+;;;
+
+(eval-when-compile (defvar mm-uu-yenc-decode-function))
+
+(defun mm-decode-content-transfer-encoding (encoding &optional type)
+  "Decodes buffer encoded with ENCODING, returning success status.
+If TYPE is `text/plain' CRLF->LF translation may occur."
+  (prog1
+      (condition-case error
+         (cond
+          ((eq encoding 'quoted-printable)
+           (quoted-printable-decode-region (point-min) (point-max))
+           t)
+          ((eq encoding 'base64)
+           (base64-decode-region
+            (point-min)
+            ;; Some mailers insert whitespace
+            ;; junk at the end which
+            ;; base64-decode-region dislikes.
+            ;; Also remove possible junk which could
+            ;; have been added by mailing list software.
+            (save-excursion
+              (goto-char (point-min))
+              (while (re-search-forward "^[\t ]*\r?\n" nil t)
+                (delete-region (match-beginning 0) (match-end 0)))
+              (goto-char (point-max))
+              (when (re-search-backward "^[A-Za-z0-9+/]+=*[\t ]*$" nil t)
+                (forward-line))
+              (point))))
+          ((memq encoding '(7bit 8bit binary))
+           ;; Do nothing.
+           t)
+          ((null encoding)
+           ;; Do nothing.
+           t)
+          ((memq encoding '(x-uuencode x-uue))
+           (require 'mm-uu)
+           (funcall mm-uu-decode-function (point-min) (point-max))
+           t)
+          ((eq encoding 'x-binhex)
+           (require 'mm-uu)
+           (funcall mm-uu-binhex-decode-function (point-min) (point-max))
+           t)
+          ((eq encoding 'x-yenc)
+           (require 'mm-uu)
+           (funcall mm-uu-yenc-decode-function (point-min) (point-max))
+           )
+          ((functionp encoding)
+           (funcall encoding (point-min) (point-max))
+           t)
+          (t
+           (message "Unknown encoding %s; defaulting to 8bit" encoding)))
+       (error
+        (message "Error while decoding: %s" error)
+        nil))
+    (when (and
+          (memq encoding '(base64 x-uuencode x-uue x-binhex x-yenc))
+          (equal type "text/plain"))
+      (goto-char (point-min))
+      (while (search-forward "\r\n" nil t)
+       (replace-match "\n" t t)))))
+
+(defun mm-decode-body (charset &optional encoding type)
+  "Decode the current article that has been encoded with ENCODING to CHARSET.
+ENCODING is a MIME content transfer encoding.
+CHARSET is the MIME charset with which to decode the data after transfer
+decoding.  If it is nil, default to `mail-parse-charset'."
+  (when (stringp charset)
+    (setq charset (intern (downcase charset))))
+  (when (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)  ; Fixme: Wrong test for unibyte session.
+      (let ((coding-system (mm-charset-to-coding-system charset)))
+       (if (and (not coding-system)
+                (listp mail-parse-ignored-charsets)
+                (memq 'gnus-unknown mail-parse-ignored-charsets))
+           (setq coding-system
+                 (mm-charset-to-coding-system mail-parse-charset)))
+       (when (and charset coding-system
+                  ;; buffer-file-coding-system
+                  ;;Article buffer is nil coding system
+                  ;;in XEmacs
+                  (mm-multibyte-p)
+                  (or (not (eq coding-system 'ascii))
+                      (setq coding-system mail-parse-charset))
+                  (not (eq coding-system 'gnus-decoded)))
+         (mm-decode-coding-region (point-min) (point-max)
+                                  coding-system))
+       (setq buffer-file-coding-system
+             (if (boundp 'last-coding-system-used)
+                 (symbol-value 'last-coding-system-used)
+               coding-system))))))
+
+(defun mm-decode-string (string charset)
+  "Decode STRING with CHARSET."
+  (when (stringp charset)
+    (setq charset (intern (downcase charset))))
+  (when (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 ((coding-system (mm-charset-to-coding-system charset)))
+       (if (and (not coding-system)
+               (listp mail-parse-ignored-charsets)
+               (memq 'gnus-unknown mail-parse-ignored-charsets))
+          (setq coding-system
+                (mm-charset-to-coding-system mail-parse-charset)))
+       (when (and charset coding-system
+                 (mm-multibyte-p)
+                 (or (not (eq coding-system 'ascii))
+                     (setq coding-system mail-parse-charset)))
+        (mm-decode-coding-string string coding-system))))
+   string))
+
+(provide 'mm-bodies)
+
+;;; mm-bodies.el ends here
diff --git a/lisp/mm-decode.el b/lisp/mm-decode.el
new file mode 100644 (file)
index 0000000..0fcc1be
--- /dev/null
@@ -0,0 +1,1481 @@
+;;; mm-decode.el --- Functions for decoding MIME things
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'mail-parse)
+(require 'gnus-mailcap)
+(require 'mm-bodies)
+(eval-when-compile (require 'cl)
+                  (require 'term))
+
+(eval-and-compile
+  (autoload 'executable-find "executable")
+  (autoload 'mm-inline-partial "mm-partial")
+  (autoload 'mm-inline-external-body "mm-extern")
+  (autoload 'mm-insert-inline "mm-view"))
+
+(add-hook 'gnus-exit-gnus-hook 'mm-destroy-postponed-undisplay-list)
+
+(defgroup mime-display ()
+  "Display of MIME in mail and news articles."
+  :link '(custom-manual "(emacs-mime)Customization")
+  :version "21.1"
+  :group 'mail
+  :group 'news
+  :group 'multimedia)
+
+(defgroup mime-security ()
+  "MIME security in mail and news articles."
+  :link '(custom-manual "(emacs-mime)Customization")
+  :group 'mail
+  :group 'news
+  :group 'multimedia)
+
+;;; Convenience macros.
+
+(defmacro mm-handle-buffer (handle)
+  `(nth 0 ,handle))
+(defmacro mm-handle-type (handle)
+  `(nth 1 ,handle))
+(defsubst mm-handle-media-type (handle)
+  (if (stringp (car handle))
+      (car handle)
+    (car (mm-handle-type handle))))
+(defsubst mm-handle-media-supertype (handle)
+  (car (split-string (mm-handle-media-type handle) "/")))
+(defsubst mm-handle-media-subtype (handle)
+  (cadr (split-string (mm-handle-media-type handle) "/")))
+(defmacro mm-handle-encoding (handle)
+  `(nth 2 ,handle))
+(defmacro mm-handle-undisplayer (handle)
+  `(nth 3 ,handle))
+(defmacro mm-handle-set-undisplayer (handle function)
+  `(setcar (nthcdr 3 ,handle) ,function))
+(defmacro mm-handle-disposition (handle)
+  `(nth 4 ,handle))
+(defmacro mm-handle-description (handle)
+  `(nth 5 ,handle))
+(defmacro mm-handle-cache (handle)
+  `(nth 6 ,handle))
+(defmacro mm-handle-set-cache (handle contents)
+  `(setcar (nthcdr 6 ,handle) ,contents))
+(defmacro mm-handle-id (handle)
+  `(nth 7 ,handle))
+(defmacro mm-handle-multipart-original-buffer (handle)
+  `(get-text-property 0 'buffer (car ,handle)))
+(defmacro mm-handle-multipart-from (handle)
+  `(get-text-property 0 'from (car ,handle)))
+(defmacro mm-handle-multipart-ctl-parameter (handle parameter)
+  `(get-text-property 0 ,parameter (car ,handle)))
+
+(defmacro mm-make-handle (&optional buffer type encoding undisplayer
+                                   disposition description cache
+                                   id)
+  `(list ,buffer ,type ,encoding ,undisplayer
+        ,disposition ,description ,cache ,id))
+
+(defcustom mm-text-html-renderer
+  (cond ((locate-library "w3") 'w3)
+       ((locate-library "w3m") 'w3m)
+       ((executable-find "w3m") 'w3m-standalone)
+       ((executable-find "links") 'links)
+       ((executable-find "lynx") 'lynx)
+       (t 'html2text))
+  "Render of HTML contents.
+It is one of defined renderer types, or a rendering function.
+The defined renderer types are:
+`w3'   : use Emacs/W3;
+`w3m'  : use emacs-w3m;
+`w3m-standalone': use w3m;
+`links': use links;
+`lynx' : use lynx;
+`html2text' : use html2text;
+nil    : use external viewer."
+  :type '(choice (const w3)
+                (const w3m)
+                (const w3m-standalone)
+                (const links)
+                (const lynx)
+                (const html2text)
+                (const nil)
+                (function))
+  :version "21.3"
+  :group 'mime-display)
+
+(defvar mm-inline-text-html-renderer nil
+  "Function used for rendering inline HTML contents.
+It is suggested to customize `mm-text-html-renderer' instead.")
+
+(defcustom mm-inline-text-html-with-images nil
+  "If non-nil, Gnus will allow retrieving images in HTML contents with
+the <img> tags.  It has no effect on Emacs/w3.  See also the
+documentation for the `mm-w3m-safe-url-regexp' variable."
+  :type 'boolean
+  :group 'mime-display)
+
+(defcustom mm-w3m-safe-url-regexp "\\`cid:"
+  "Regexp matching URLs which are considered to be safe.
+Some HTML mails might contain a nasty trick used by spammers, using
+the <img> tag which is far more evil than the [Click Here!] button.
+It is most likely intended to check whether the ominous spam mail has
+reached your eyes or not, in which case the spammer knows for sure
+that your email address is valid.  It is done by embedding an
+identifier string into a URL that you might automatically retrieve
+when displaying the image.  The default value is \"\\\\`cid:\" which only
+matches parts embedded to the Multipart/Related type MIME contents and
+Gnus will never connect to the spammer's site arbitrarily.  You may
+set this variable to nil if you consider all urls to be safe."
+  :type '(choice (regexp :tag "Regexp")
+                (const :tag "All URLs are safe" nil))
+  :group 'mime-display)
+
+(defcustom mm-inline-text-html-with-w3m-keymap t
+  "If non-nil, use emacs-w3m command keys in the article buffer."
+  :type 'boolean
+  :group 'mime-display)
+
+(defcustom mm-enable-external t
+  "Indicate whether external MIME handlers should be used.
+
+If t, all defined external MIME handlers are used.  If nil, files are saved by
+`mailcap-save-binary-file'.  If it is the symbol `ask', you are prompted
+before the external MIME handler is invoked."
+  :version "21.4"
+  :type '(choice (const :tag "Always" t)
+                (const :tag "Never" nil)
+                (const :tag "Ask" ask))
+  :group 'mime-display)
+
+(defcustom mm-inline-media-tests
+  '(("image/p?jpeg"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'jpeg handle)))
+    ("image/png"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'png handle)))
+    ("image/gif"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'gif handle)))
+    ("image/tiff"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'tiff handle)) )
+    ("image/xbm"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xbm handle)))
+    ("image/x-xbitmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xbm handle)))
+    ("image/xpm"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xpm handle)))
+    ("image/x-xpixmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'xpm handle)))
+    ("image/bmp"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'bmp handle)))
+    ("image/x-portable-bitmap"
+     mm-inline-image
+     (lambda (handle)
+       (mm-valid-and-fit-image-p 'pbm handle)))
+    ("text/plain" mm-inline-text identity)
+    ("text/enriched" mm-inline-text identity)
+    ("text/richtext" mm-inline-text identity)
+    ("text/x-patch" mm-display-patch-inline
+     (lambda (handle)
+       (locate-library "diff-mode")))
+    ("application/emacs-lisp" mm-display-elisp-inline identity)
+    ("application/x-emacs-lisp" mm-display-elisp-inline identity)
+    ("text/html"
+     mm-inline-text-html
+     (lambda (handle)
+       (or mm-inline-text-html-renderer
+          mm-text-html-renderer)))
+    ("text/x-vcard"
+     mm-inline-text-vcard
+     (lambda (handle)
+       (or (featurep 'vcard)
+          (locate-library "vcard"))))
+    ("message/delivery-status" mm-inline-text identity)
+    ("message/rfc822" mm-inline-message identity)
+    ("message/partial" mm-inline-partial identity)
+    ("message/external-body" mm-inline-external-body identity)
+    ("text/.*" mm-inline-text identity)
+    ("audio/wav" mm-inline-audio
+     (lambda (handle)
+       (and (or (featurep 'nas-sound) (featurep 'native-sound))
+           (device-sound-enabled-p))))
+    ("audio/au"
+     mm-inline-audio
+     (lambda (handle)
+       (and (or (featurep 'nas-sound) (featurep 'native-sound))
+           (device-sound-enabled-p))))
+    ("application/pgp-signature" ignore identity)
+    ("application/x-pkcs7-signature" ignore identity)
+    ("application/pkcs7-signature" ignore identity)
+    ("application/x-pkcs7-mime" ignore identity)
+    ("application/pkcs7-mime" ignore identity)
+    ("multipart/alternative" ignore identity)
+    ("multipart/mixed" ignore identity)
+    ("multipart/related" ignore identity)
+    ;; Disable audio and image
+    ("audio/.*" ignore ignore)
+    ("image/.*" ignore ignore)
+    ;; Default to displaying as text
+    (".*" mm-inline-text mm-readable-p))
+  "Alist of media types/tests saying whether types can be displayed inline."
+  :type '(repeat (list (regexp :tag "MIME type")
+                      (function :tag "Display function")
+                      (function :tag "Display test")))
+  :group 'mime-display)
+
+(defcustom mm-inlined-types
+  '("image/.*" "text/.*" "message/delivery-status" "message/rfc822"
+    "message/partial" "message/external-body" "application/emacs-lisp"
+    "application/x-emacs-lisp"
+    "application/pgp-signature" "application/x-pkcs7-signature"
+    "application/pkcs7-signature" "application/x-pkcs7-mime"
+    "application/pkcs7-mime")
+  "List of media types that are to be displayed inline.
+See also `mm-inline-media-tests', which says how to display a media
+type inline."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-keep-viewer-alive-types
+  '("application/postscript" "application/msword" "application/vnd.ms-excel"
+    "application/pdf" "application/x-dvi")
+  "List of media types for which the external viewer will not be killed
+when selecting a different article."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-automatic-display
+  '("text/plain" "text/enriched" "text/richtext" "text/html"
+    "text/x-vcard" "image/.*" "message/delivery-status" "multipart/.*"
+    "message/rfc822" "text/x-patch" "application/pgp-signature"
+    "application/emacs-lisp" "application/x-emacs-lisp"
+    "application/x-pkcs7-signature"
+    "application/pkcs7-signature" "application/x-pkcs7-mime"
+    "application/pkcs7-mime")
+  "A list of MIME types to be displayed automatically."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-attachment-override-types '("text/x-vcard"
+                                         "application/pkcs7-mime"
+                                         "application/x-pkcs7-mime"
+                                         "application/pkcs7-signature"
+                                         "application/x-pkcs7-signature")
+  "Types to have \"attachment\" ignored if they can be displayed inline."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-inline-override-types nil
+  "Types to be treated as attachments even if they can be displayed inline."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-automatic-external-display nil
+  "List of MIME type regexps that will be displayed externally automatically."
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-discouraged-alternatives nil
+  "List of MIME types that are discouraged when viewing multipart/alternative.
+Viewing agents are supposed to view the last possible part of a message,
+as that is supposed to be the richest.  However, users may prefer other
+types instead, and this list says what types are most unwanted.  If,
+for instance, text/html parts are very unwanted, and text/richtext are
+somewhat unwanted, then the value of this variable should be set
+to:
+
+ (\"text/html\" \"text/richtext\")"
+  :type '(repeat string)
+  :group 'mime-display)
+
+(defcustom mm-tmp-directory
+  (if (fboundp 'temp-directory)
+      (temp-directory)
+    (if (boundp 'temporary-file-directory)
+       temporary-file-directory
+      "/tmp/"))
+  "Where mm will store its temporary files."
+  :type 'directory
+  :group 'mime-display)
+
+(defcustom mm-inline-large-images nil
+  "If non-nil, then all images fit in the buffer."
+  :type 'boolean
+  :group 'mime-display)
+
+(defvar mm-file-name-rewrite-functions
+  '(mm-file-name-delete-control mm-file-name-delete-gotchas)
+  "*List of functions used for rewriting file names of MIME parts.
+Each function takes a file name as input and returns a file name.
+
+Ready-made functions include
+`mm-file-name-delete-control'
+`mm-file-name-delete-gotchas'
+`mm-file-name-delete-whitespace',
+`mm-file-name-trim-whitespace',
+`mm-file-name-collapse-whitespace',
+`mm-file-name-replace-whitespace',
+`capitalize', `downcase', `upcase', and
+`upcase-initials'.")
+
+(defvar mm-path-name-rewrite-functions nil
+  "*List of functions for rewriting the full file names of MIME parts.
+This is used when viewing parts externally, and is meant for
+transforming the absolute name so that non-compliant programs can find
+the file where it's saved.
+
+Each function takes a file name as input and returns a file name.")
+
+(defvar mm-file-name-replace-whitespace nil
+  "String used for replacing whitespace characters; default is `\"_\"'.")
+
+(defcustom mm-default-directory nil
+  "The default directory where mm will save files.
+If not set, `default-directory' will be used."
+  :type '(choice directory (const :tag "Default" nil))
+  :group 'mime-display)
+
+(defcustom mm-attachment-file-modes 384
+  "Set the mode bits of saved attachments to this integer."
+  :type 'integer
+  :group 'mime-display)
+
+(defcustom mm-external-terminal-program "xterm"
+  "The program to start an external terminal."
+  :type 'string
+  :group 'mime-display)
+
+;;; Internal variables.
+
+(defvar mm-last-shell-command "")
+(defvar mm-content-id-alist nil)
+(defvar mm-postponed-undisplay-list nil)
+
+;; According to RFC2046, in particular, in a digest, the default
+;; Content-Type value for a body part is changed from "text/plain" to
+;; "message/rfc822".
+(defvar mm-dissect-default-type "text/plain")
+
+(autoload 'mml2015-verify "mml2015")
+(autoload 'mml2015-verify-test "mml2015")
+(autoload 'mml-smime-verify "mml-smime")
+(autoload 'mml-smime-verify-test "mml-smime")
+
+(defvar mm-verify-function-alist
+  '(("application/pgp-signature" mml2015-verify "PGP" mml2015-verify-test)
+    ("application/x-gnus-pgp-signature" mm-uu-pgp-signed-extract-1 "PGP"
+     mm-uu-pgp-signed-test)
+    ("application/pkcs7-signature" mml-smime-verify "S/MIME"
+     mml-smime-verify-test)
+    ("application/x-pkcs7-signature" mml-smime-verify "S/MIME"
+     mml-smime-verify-test)))
+
+(defcustom mm-verify-option 'never
+  "Option of verifying signed parts.
+`never', not verify; `always', always verify;
+`known', only verify known protocols.  Otherwise, ask user."
+  :type '(choice (item always)
+                (item never)
+                (item :tag "only known protocols" known)
+                (item :tag "ask" nil))
+  :group 'mime-security)
+
+(autoload 'mml2015-decrypt "mml2015")
+(autoload 'mml2015-decrypt-test "mml2015")
+
+(defvar mm-decrypt-function-alist
+  '(("application/pgp-encrypted" mml2015-decrypt "PGP" mml2015-decrypt-test)
+    ("application/x-gnus-pgp-encrypted" mm-uu-pgp-encrypted-extract-1 "PGP"
+     mm-uu-pgp-encrypted-test)))
+
+(defcustom mm-decrypt-option nil
+  "Option of decrypting encrypted parts.
+`never', not decrypt; `always', always decrypt;
+`known', only decrypt known protocols.  Otherwise, ask user."
+  :type '(choice (item always)
+                (item never)
+                (item :tag "only known protocols" known)
+                (item :tag "ask" nil))
+  :group 'mime-security)
+
+(defvar mm-viewer-completion-map
+  (let ((map (make-sparse-keymap 'mm-viewer-completion-map)))
+    (set-keymap-parent map minibuffer-local-completion-map)
+    map)
+  "Keymap for input viewer with completion.")
+
+;; Should we bind other key to minibuffer-complete-word?
+(define-key mm-viewer-completion-map " " 'self-insert-command)
+
+(defvar mm-viewer-completion-map
+  (let ((map (make-sparse-keymap 'mm-viewer-completion-map)))
+    (set-keymap-parent map minibuffer-local-completion-map)
+    map)
+  "Keymap for input viewer with completion.")
+
+;; Should we bind other key to minibuffer-complete-word?
+(define-key mm-viewer-completion-map " " 'self-insert-command)
+
+;;; The functions.
+
+(defun mm-alist-to-plist (alist)
+  "Convert association list ALIST into the equivalent property-list form.
+The plist is returned.  This converts from
+
+\((a . 1) (b . 2) (c . 3))
+
+into
+
+\(a 1 b 2 c 3)
+
+The original alist is not modified.  See also `destructive-alist-to-plist'."
+  (let (plist)
+    (while alist
+      (let ((el (car alist)))
+       (setq plist (cons (cdr el) (cons (car el) plist))))
+      (setq alist (cdr alist)))
+    (nreverse plist)))
+
+(defun mm-keep-viewer-alive-p (handle)
+  "Say whether external viewer for HANDLE should stay alive."
+  (let ((types mm-keep-viewer-alive-types)
+       (type (mm-handle-media-type handle))
+       ty)
+    (catch 'found
+      (while (setq ty (pop types))
+       (when (string-match ty type)
+         (throw 'found t))))))
+
+(defun mm-handle-set-external-undisplayer (handle function)
+  "Set the undisplayer for HANDLE to FUNCTION.
+Postpone undisplaying of viewers for types in
+`mm-keep-viewer-alive-types'."
+  (if (mm-keep-viewer-alive-p handle)
+      (let ((new-handle (copy-sequence handle)))
+       (mm-handle-set-undisplayer new-handle function)
+       (mm-handle-set-undisplayer handle nil)
+       (push new-handle mm-postponed-undisplay-list))
+    (mm-handle-set-undisplayer handle function)))
+
+(defun mm-destroy-postponed-undisplay-list ()
+  (when mm-postponed-undisplay-list
+    (message "Destroying external MIME viewers")
+    (mm-destroy-parts mm-postponed-undisplay-list)))
+
+(defun mm-dissect-buffer (&optional no-strict-mime loose-mime)
+  "Dissect the current buffer and return a list of MIME handles."
+  (save-excursion
+    (let (ct ctl type subtype cte cd description id result from)
+      (save-restriction
+       (mail-narrow-to-head)
+       (when (or no-strict-mime
+                 loose-mime
+                 (mail-fetch-field "mime-version"))
+         (setq ct (mail-fetch-field "content-type")
+               ctl (ignore-errors (mail-header-parse-content-type ct))
+               cte (mail-fetch-field "content-transfer-encoding")
+               cd (mail-fetch-field "content-disposition")
+               description (mail-fetch-field "content-description")
+               from (mail-fetch-field "from")
+               id (mail-fetch-field "content-id"))
+         ;; FIXME: In some circumstances, this code is running within
+         ;; an unibyte macro.  mail-extract-address-components
+         ;; creates unibyte buffers. This `if', though not a perfect
+         ;; solution, avoids most of them.
+         (if from
+             (setq from (cadr (mail-extract-address-components from))))))
+      (when cte
+       (setq cte (mail-header-strip cte)))
+      (if (or (not ctl)
+             (not (string-match "/" (car ctl))))
+         (mm-dissect-singlepart
+          (list mm-dissect-default-type)
+          (and cte (intern (downcase (mail-header-remove-whitespace
+                                      (mail-header-remove-comments
+                                       cte)))))
+          no-strict-mime
+          (and cd (ignore-errors (mail-header-parse-content-disposition cd)))
+          description)
+       (setq type (split-string (car ctl) "/"))
+       (setq subtype (cadr type)
+             type (pop type))
+       (setq
+        result
+        (cond
+         ((equal type "multipart")
+          (let ((mm-dissect-default-type (if (equal subtype "digest")
+                                             "message/rfc822"
+                                           "text/plain"))
+                (start (cdr (assq 'start (cdr ctl)))))
+            (add-text-properties 0 (length (car ctl))
+                                 (mm-alist-to-plist (cdr ctl)) (car ctl))
+
+            ;; what really needs to be done here is a way to link a
+            ;; MIME handle back to it's parent MIME handle (in a multilevel
+            ;; MIME article).  That would probably require changing
+            ;; the mm-handle API so we simply store the multipart buffert
+            ;; name as a text property of the "multipart/whatever" string.
+            (add-text-properties 0 (length (car ctl))
+                                 (list 'buffer (mm-copy-to-buffer)
+                                       'from from
+                                       'start start)
+                                 (car ctl))
+            (cons (car ctl) (mm-dissect-multipart ctl))))
+         (t
+          (mm-possibly-verify-or-decrypt
+           (mm-dissect-singlepart
+            ctl
+            (and cte (intern (downcase (mail-header-remove-whitespace
+                                        (mail-header-remove-comments
+                                         cte)))))
+            no-strict-mime
+            (and cd (ignore-errors
+                      (mail-header-parse-content-disposition cd)))
+            description id)
+           ctl))))
+       (when id
+         (when (string-match " *<\\(.*\\)> *" id)
+           (setq id (match-string 1 id)))
+         (push (cons id result) mm-content-id-alist))
+       result))))
+
+(defun mm-dissect-singlepart (ctl cte &optional force cdl description id)
+  (when (or force
+           (if (equal "text/plain" (car ctl))
+               (assoc 'format ctl)
+             t))
+    (mm-make-handle
+     (mm-copy-to-buffer) ctl cte nil cdl description nil id)))
+
+(defun mm-dissect-multipart (ctl)
+  (goto-char (point-min))
+  (let* ((boundary (concat "\n--" (mail-content-type-get ctl 'boundary)))
+        (close-delimiter (concat (regexp-quote boundary) "--[ \t]*$"))
+        start parts
+        (end (save-excursion
+               (goto-char (point-max))
+               (if (re-search-backward close-delimiter nil t)
+                   (match-beginning 0)
+                 (point-max)))))
+    (setq boundary (concat (regexp-quote boundary) "[ \t]*$"))
+    (while (and (< (point) end) (re-search-forward boundary end t))
+      (goto-char (match-beginning 0))
+      (when start
+       (save-excursion
+         (save-restriction
+           (narrow-to-region start (point))
+           (setq parts (nconc (list (mm-dissect-buffer t)) parts)))))
+      (end-of-line 2)
+      (or (looking-at boundary)
+         (forward-line 1))
+      (setq start (point)))
+    (when (and start (< start end))
+      (save-excursion
+       (save-restriction
+         (narrow-to-region start end)
+         (setq parts (nconc (list (mm-dissect-buffer t)) parts)))))
+    (mm-possibly-verify-or-decrypt (nreverse parts) ctl)))
+
+(defun mm-copy-to-buffer ()
+  "Copy the contents of the current buffer to a fresh buffer."
+  (save-excursion
+    (let ((flag enable-multibyte-characters)
+         (new-buffer (generate-new-buffer " *mm*")))
+      (goto-char (point-min))
+      (search-forward-regexp "^\n" nil t)
+      (save-restriction
+       (narrow-to-region (point) (point-max))
+       (when flag
+         (set-buffer-multibyte nil))
+       (copy-to-buffer new-buffer (point-min) (point-max))
+       (when flag
+         (set-buffer-multibyte t)))
+      new-buffer)))
+
+(defun mm-display-parts (handle &optional no-default)
+  (if (stringp (car handle))
+      (mapcar 'mm-display-parts (cdr handle))
+    (if (bufferp (car handle))
+       (save-restriction
+         (narrow-to-region (point) (point))
+         (mm-display-part handle)
+         (goto-char (point-max)))
+      (mapcar 'mm-display-parts handle))))
+
+(defun mm-display-part (handle &optional no-default)
+  "Display the MIME part represented by HANDLE.
+Returns nil if the part is removed; inline if displayed inline;
+external if displayed external."
+  (save-excursion
+    (mailcap-parse-mailcaps)
+    (if (mm-handle-displayed-p handle)
+       (mm-remove-part handle)
+      (let* ((type (mm-handle-media-type handle))
+            (method (mailcap-mime-info type))
+            (filename (or (mail-content-type-get
+                           (mm-handle-disposition handle) 'filename)
+                          (mail-content-type-get
+                           (mm-handle-type handle) 'name)
+                          "<file>"))
+            (external mm-enable-external))
+       (if (and (mm-inlinable-p handle)
+                (mm-inlined-p handle))
+           (progn
+             (forward-line 1)
+             (mm-display-inline handle)
+             'inline)
+         (when (or method
+                   (not no-default))
+           (if (and (not method)
+                    (equal "text" (car (split-string type))))
+               (progn
+                 (forward-line 1)
+                 (mm-insert-inline handle (mm-get-part handle))
+                 'inline)
+             (if (and method ;; If nil, we always use "save".
+                      (stringp method) ;; 'mailcap-save-binary-file
+                      (or (eq mm-enable-external t)
+                          (and (eq mm-enable-external 'ask)
+                               (y-or-n-p
+                                (concat
+                                 "Display part (" type
+                                 ") using external program"
+                                 ;; Can non-string method ever happen?
+                                 (if (stringp method)
+                                     (concat
+                                      " \"" (format method filename) "\"")
+                                   "")
+                                 "? ")))))
+                 (setq external t)
+               (setq external nil))
+             (if external
+                 (mm-display-external
+                  handle (or method 'mailcap-save-binary-file))
+               (mm-display-external
+                handle 'mailcap-save-binary-file)))))))))
+
+(defun mm-display-external (handle method)
+  "Display HANDLE using METHOD."
+  (let ((outbuf (current-buffer)))
+    (mm-with-unibyte-buffer
+      (if (functionp method)
+         (let ((cur (current-buffer)))
+           (if (eq method 'mailcap-save-binary-file)
+               (progn
+                 (set-buffer (generate-new-buffer " *mm*"))
+                 (setq method nil))
+             (mm-insert-part handle)
+             (let ((win (get-buffer-window cur t)))
+               (when win
+                 (select-window win)))
+             (switch-to-buffer (generate-new-buffer " *mm*")))
+           (buffer-disable-undo)
+           (mm-set-buffer-file-coding-system mm-binary-coding-system)
+           (insert-buffer-substring cur)
+           (goto-char (point-min))
+           (when method
+             (message "Viewing with %s" method))
+           (let ((mm (current-buffer))
+                 (non-viewer (assq 'non-viewer
+                                   (mailcap-mime-info
+                                    (mm-handle-media-type handle) t))))
+             (unwind-protect
+                 (if method
+                     (funcall method)
+                   (mm-save-part handle))
+               (when (and (not non-viewer)
+                          method)
+                 (mm-handle-set-undisplayer handle mm)))))
+       ;; The function is a string to be executed.
+       (mm-insert-part handle)
+       (let* ((dir (mm-make-temp-file
+                    (expand-file-name "emm." mm-tmp-directory) 'dir))
+              (filename (or
+                         (mail-content-type-get
+                          (mm-handle-disposition handle) 'filename)
+                         (mail-content-type-get
+                          (mm-handle-type handle) 'name)))
+              (mime-info (mailcap-mime-info
+                          (mm-handle-media-type handle) t))
+              (needsterm (or (assoc "needsterm" mime-info)
+                             (assoc "needsterminal" mime-info)))
+              (copiousoutput (assoc "copiousoutput" mime-info))
+              file buffer)
+         ;; We create a private sub-directory where we store our files.
+         (set-file-modes dir 448)
+         (if filename
+             (setq file (expand-file-name
+                         (gnus-map-function mm-file-name-rewrite-functions
+                                            (file-name-nondirectory filename))
+                         dir))
+           (setq file (mm-make-temp-file (expand-file-name "mm." dir))))
+         (let ((coding-system-for-write mm-binary-coding-system))
+           (write-region (point-min) (point-max) file nil 'nomesg))
+         (message "Viewing with %s" method)
+         (cond
+          (needsterm
+           (let ((command (mm-mailcap-command
+                           method file (mm-handle-type handle))))
+             (unwind-protect
+                 (if window-system
+                     (start-process "*display*" nil
+                                    mm-external-terminal-program
+                                    "-e" shell-file-name
+                                    shell-command-switch command)
+                   (require 'term)
+                   (require 'gnus-win)
+                   (set-buffer
+                    (setq buffer
+                          (make-term "display"
+                                     shell-file-name
+                                     nil
+                                     shell-command-switch command)))
+                   (term-mode)
+                   (term-char-mode)
+                   (set-process-sentinel
+                    (get-buffer-process buffer)
+                    `(lambda (process state)
+                       (if (eq 'exit (process-status process))
+                           (gnus-configure-windows
+                            ',gnus-current-window-configuration))))
+                   (gnus-configure-windows 'display-term))
+               (mm-handle-set-external-undisplayer handle (cons file buffer)))
+             (message "Displaying %s..." command))
+           'external)
+          (copiousoutput
+           (with-current-buffer outbuf
+             (forward-line 1)
+             (mm-insert-inline
+              handle
+              (unwind-protect
+                  (progn
+                    (call-process shell-file-name nil
+                                  (setq buffer
+                                        (generate-new-buffer " *mm*"))
+                                  nil
+                                  shell-command-switch
+                                  (mm-mailcap-command
+                                   method file (mm-handle-type handle)))
+                    (if (buffer-live-p buffer)
+                        (save-excursion
+                          (set-buffer buffer)
+                          (buffer-string))))
+                (progn
+                  (ignore-errors (delete-file file))
+                  (ignore-errors (delete-directory
+                                  (file-name-directory file)))
+                  (ignore-errors (kill-buffer buffer))))))
+           'inline)
+          (t
+           (let ((command (mm-mailcap-command
+                           method file (mm-handle-type handle))))
+             (unwind-protect
+                 (start-process "*display*"
+                                (setq buffer
+                                      (generate-new-buffer " *mm*"))
+                                shell-file-name
+                                shell-command-switch command)
+               (mm-handle-set-external-undisplayer
+                handle (cons file buffer)))
+             (message "Displaying %s..." command))
+           'external)))))))
+
+(defun mm-mailcap-command (method file type-list)
+  (let ((ctl (cdr type-list))
+       (beg 0)
+       (uses-stdin t)
+       out sub total)
+    (while (string-match "%{\\([^}]+\\)}\\|'%s'\\|\"%s\"\\|%s\\|%t\\|%%"
+                        method beg)
+      (push (substring method beg (match-beginning 0)) out)
+      (setq beg (match-end 0)
+           total (match-string 0 method)
+           sub (match-string 1 method))
+      (cond
+       ((string= total "%%")
+       (push "%" out))
+       ((or (string= total "%s")
+           ;; We do our own quoting.
+           (string= total "'%s'")
+           (string= total "\"%s\""))
+       (setq uses-stdin nil)
+       (push (mm-quote-arg
+              (gnus-map-function mm-path-name-rewrite-functions file)) out))
+       ((string= total "%t")
+       (push (mm-quote-arg (car type-list)) out))
+       (t
+       (push (mm-quote-arg (or (cdr (assq (intern sub) ctl)) "")) out))))
+    (push (substring method beg (length method)) out)
+    (when uses-stdin
+      (push "<" out)
+      (push (mm-quote-arg
+            (gnus-map-function mm-path-name-rewrite-functions file))
+           out))
+    (mapconcat 'identity (nreverse out) "")))
+
+(defun mm-remove-parts (handles)
+  "Remove the displayed MIME parts represented by HANDLES."
+  (if (and (listp handles)
+          (bufferp (car handles)))
+      (mm-remove-part handles)
+    (let (handle)
+      (while (setq handle (pop handles))
+       (cond
+        ((stringp handle)
+         (when (buffer-live-p (get-text-property 0 'buffer handle))
+           (kill-buffer (get-text-property 0 'buffer handle))))
+        ((and (listp handle)
+              (stringp (car handle)))
+         (mm-remove-parts (cdr handle)))
+        (t
+         (mm-remove-part handle)))))))
+
+(defun mm-destroy-parts (handles)
+  "Remove the displayed MIME parts represented by HANDLES."
+  (if (and (listp handles)
+          (bufferp (car handles)))
+      (mm-destroy-part handles)
+    (let (handle)
+      (while (setq handle (pop handles))
+       (cond
+        ((stringp handle)
+         (when (buffer-live-p (get-text-property 0 'buffer handle))
+           (kill-buffer (get-text-property 0 'buffer handle))))
+        ((and (listp handle)
+              (stringp (car handle)))
+         (mm-destroy-parts handle))
+        (t
+         (mm-destroy-part handle)))))))
+
+(defun mm-remove-part (handle)
+  "Remove the displayed MIME part represented by HANDLE."
+  (when (listp handle)
+    (let ((object (mm-handle-undisplayer handle)))
+      (ignore-errors
+       (cond
+        ;; Internally displayed part.
+        ((mm-annotationp object)
+         (delete-annotation object))
+        ((or (functionp object)
+             (and (listp object)
+                  (eq (car object) 'lambda)))
+         (funcall object))
+        ;; Externally displayed part.
+        ((consp object)
+         (condition-case ()
+             (while (get-buffer-process (cdr object))
+               (interrupt-process (get-buffer-process (cdr object)))
+               (message "Waiting for external displayer to die...")
+               (sit-for 1))
+           (quit)
+           (error))
+         (ignore-errors (and (cdr object) (kill-buffer (cdr object))))
+         (message "Waiting for external displayer to die...done")
+         (ignore-errors (delete-file (car object)))
+         (ignore-errors (delete-directory (file-name-directory
+                                           (car object)))))
+        ((bufferp object)
+         (when (buffer-live-p object)
+           (kill-buffer object)))))
+      (mm-handle-set-undisplayer handle nil))))
+
+(defun mm-display-inline (handle)
+  (let* ((type (mm-handle-media-type handle))
+        (function (cadr (mm-assoc-string-match mm-inline-media-tests type))))
+    (funcall function handle)
+    (goto-char (point-min))))
+
+(defun mm-assoc-string-match (alist type)
+  (dolist (elem alist)
+    (when (string-match (car elem) type)
+      (return elem))))
+
+(defun mm-automatic-display-p (handle)
+  "Say whether the user wants HANDLE to be displayed automatically."
+  (let ((methods mm-automatic-display)
+       (type (mm-handle-media-type handle))
+       method result)
+    (while (setq method (pop methods))
+      (when (and (not (mm-inline-override-p handle))
+                (string-match method type))
+       (setq result t
+             methods nil)))
+    result))
+
+(defun mm-inlinable-p (handle)
+  "Say whether HANDLE can be displayed inline."
+  (let ((alist mm-inline-media-tests)
+       (type (mm-handle-media-type handle))
+       test)
+    (while alist
+      (when (string-match (caar alist) type)
+       (setq test (caddar alist)
+             alist nil)
+       (setq test (funcall test handle)))
+      (pop alist))
+    test))
+
+(defun mm-inlined-p (handle)
+  "Say whether the user wants HANDLE to be displayed inline."
+  (let ((methods mm-inlined-types)
+       (type (mm-handle-media-type handle))
+       method result)
+    (while (setq method (pop methods))
+      (when (and (not (mm-inline-override-p handle))
+                (string-match method type))
+       (setq result t
+             methods nil)))
+    result))
+
+(defun mm-attachment-override-p (handle)
+  "Say whether HANDLE should have attachment behavior overridden."
+  (let ((types mm-attachment-override-types)
+       (type (mm-handle-media-type handle))
+       ty)
+    (catch 'found
+      (while (setq ty (pop types))
+       (when (and (string-match ty type)
+                  (mm-inlinable-p handle))
+         (throw 'found t))))))
+
+(defun mm-inline-override-p (handle)
+  "Say whether HANDLE should have inline behavior overridden."
+  (let ((types mm-inline-override-types)
+       (type (mm-handle-media-type handle))
+       ty)
+    (catch 'found
+      (while (setq ty (pop types))
+       (when (string-match ty type)
+         (throw 'found t))))))
+
+(defun mm-automatic-external-display-p (type)
+  "Return the user-defined method for TYPE."
+  (let ((methods mm-automatic-external-display)
+       method result)
+    (while (setq method (pop methods))
+      (when (string-match method type)
+       (setq result t
+             methods nil)))
+    result))
+
+(defun mm-destroy-part (handle)
+  "Destroy the data structures connected to HANDLE."
+  (when (listp handle)
+    (mm-remove-part handle)
+    (when (buffer-live-p (mm-handle-buffer handle))
+      (kill-buffer (mm-handle-buffer handle)))))
+
+(defun mm-handle-displayed-p (handle)
+  "Say whether HANDLE is displayed or not."
+  (mm-handle-undisplayer handle))
+
+;;;
+;;; Functions for outputting parts
+;;;
+
+(defun mm-get-part (handle)
+  "Return the contents of HANDLE as a string."
+  (mm-with-unibyte-buffer
+    (insert (with-current-buffer (mm-handle-buffer handle)
+             (mm-with-unibyte-current-buffer
+               (buffer-string))))
+    (mm-decode-content-transfer-encoding
+     (mm-handle-encoding handle)
+     (mm-handle-media-type handle))
+    (buffer-string)))
+
+(defun mm-insert-part (handle)
+  "Insert the contents of HANDLE in the current buffer."
+  (let ((cur (current-buffer)))
+    (save-excursion
+      (if (member (mm-handle-media-supertype handle) '("text" "message"))
+         (with-temp-buffer
+           (insert-buffer-substring (mm-handle-buffer handle))
+           (prog1
+               (mm-decode-content-transfer-encoding
+                (mm-handle-encoding handle)
+                (mm-handle-media-type handle))
+             (let ((temp (current-buffer)))
+               (set-buffer cur)
+               (insert-buffer-substring temp))))
+       (mm-with-unibyte-buffer
+         (insert-buffer-substring (mm-handle-buffer handle))
+         (prog1
+             (mm-decode-content-transfer-encoding
+              (mm-handle-encoding handle)
+              (mm-handle-media-type handle))
+           (let ((temp (current-buffer)))
+             (set-buffer cur)
+             (insert-buffer-substring temp))))))))
+
+(defun mm-file-name-delete-whitespace (file-name)
+  "Remove all whitespace characters from FILE-NAME."
+  (while (string-match "\\s-+" file-name)
+    (setq file-name (replace-match "" t t file-name)))
+  file-name)
+
+(defun mm-file-name-trim-whitespace (file-name)
+  "Remove leading and trailing whitespace characters from FILE-NAME."
+  (when (string-match "\\`\\s-+" file-name)
+    (setq file-name (substring file-name (match-end 0))))
+  (when (string-match "\\s-+\\'" file-name)
+    (setq file-name (substring file-name 0 (match-beginning 0))))
+  file-name)
+
+(defun mm-file-name-collapse-whitespace (file-name)
+  "Collapse multiple whitespace characters in FILE-NAME."
+  (while (string-match "\\s-\\s-+" file-name)
+    (setq file-name (replace-match " " t t file-name)))
+  file-name)
+
+(defun mm-file-name-replace-whitespace (file-name)
+  "Replace whitespace characters in FILE-NAME with underscores.
+Set the option `mm-file-name-replace-whitespace' to any other
+string if you do not like underscores."
+  (let ((s (or mm-file-name-replace-whitespace "_")))
+    (while (string-match "\\s-" file-name)
+      (setq file-name (replace-match s t t file-name))))
+  file-name)
+
+(defun mm-file-name-delete-control (filename)
+  "Delete control characters from FILENAME."
+  (gnus-replace-in-string filename "[\x00-\x1f\x7f]" ""))
+
+(defun mm-file-name-delete-gotchas (filename)
+  "Delete shell gotchas from FILENAME."
+  (setq filename (gnus-replace-in-string filename "[<>|]" ""))
+  (gnus-replace-in-string filename "^[.-]+" ""))
+
+(defun mm-save-part (handle)
+  "Write HANDLE to a file."
+  (let* ((name (mail-content-type-get (mm-handle-type handle) 'name))
+        (filename (mail-content-type-get
+                   (mm-handle-disposition handle) 'filename))
+        file)
+    (when filename
+      (setq filename (gnus-map-function mm-file-name-rewrite-functions
+                                       (file-name-nondirectory filename))))
+    (setq file
+         (read-file-name "Save MIME part to: "
+                         (or mm-default-directory default-directory)
+                         nil nil (or filename name "")))
+    (setq mm-default-directory (file-name-directory file))
+    (and (or (not (file-exists-p file))
+            (yes-or-no-p (format "File %s already exists; overwrite? "
+                                 file)))
+        (progn
+          (mm-save-part-to-file handle file)
+          file))))
+
+(defun mm-save-part-to-file (handle file)
+  (mm-with-unibyte-buffer
+    (mm-insert-part handle)
+    (let ((coding-system-for-write 'binary)
+         (current-file-modes (default-file-modes))
+         ;; Don't re-compress .gz & al.  Arguably we should make
+         ;; `file-name-handler-alist' nil, but that would chop
+         ;; ange-ftp, which is reasonable to use here.
+         (inhibit-file-name-operation 'write-region)
+         (inhibit-file-name-handlers
+          (cons 'jka-compr-handler inhibit-file-name-handlers)))
+      (set-default-file-modes mm-attachment-file-modes)
+      (unwind-protect
+         (write-region (point-min) (point-max) file)
+       (set-default-file-modes current-file-modes)))))
+
+(defun mm-pipe-part (handle)
+  "Pipe HANDLE to a process."
+  (let* ((name (mail-content-type-get (mm-handle-type handle) 'name))
+        (command
+         (read-string "Shell command on MIME part: " mm-last-shell-command)))
+    (mm-with-unibyte-buffer
+      (mm-insert-part handle)
+      (let ((coding-system-for-write 'binary))
+       (shell-command-on-region (point-min) (point-max) command nil)))))
+
+(defun mm-interactively-view-part (handle)
+  "Display HANDLE using METHOD."
+  (let* ((type (mm-handle-media-type handle))
+        (methods
+         (mapcar (lambda (i) (list (cdr (assoc 'viewer i))))
+                 (mailcap-mime-info type 'all)))
+        (method (let ((minibuffer-local-completion-map
+                       mm-viewer-completion-map))
+                  (completing-read "Viewer: " methods))))
+    (when (string= method "")
+      (error "No method given"))
+    (if (string-match "^[^% \t]+$" method)
+       (setq method (concat method " %s")))
+    (mm-display-external handle method)))
+
+(defun mm-preferred-alternative (handles &optional preferred)
+  "Say which of HANDLES are preferred."
+  (let ((prec (if preferred (list preferred)
+               (mm-preferred-alternative-precedence handles)))
+       p h result type handle)
+    (while (setq p (pop prec))
+      (setq h handles)
+      (while h
+       (setq handle (car h))
+       (setq type (mm-handle-media-type handle))
+       (when (and (equal p type)
+                  (mm-automatic-display-p handle)
+                  (or (stringp (car handle))
+                      (not (mm-handle-disposition handle))
+                      (equal (car (mm-handle-disposition handle))
+                             "inline")))
+         (setq result handle
+               h nil
+               prec nil))
+       (pop h)))
+    result))
+
+(defun mm-preferred-alternative-precedence (handles)
+  "Return the precedence based on HANDLES and `mm-discouraged-alternatives'."
+  (let ((seq (nreverse (mapcar #'mm-handle-media-type
+                              handles))))
+    (dolist (disc (reverse mm-discouraged-alternatives))
+      (dolist (elem (copy-sequence seq))
+       (when (string-match disc elem)
+         (setq seq (nconc (delete elem seq) (list elem))))))
+    seq))
+
+(defun mm-get-content-id (id)
+  "Return the handle(s) referred to by ID."
+  (cdr (assoc id mm-content-id-alist)))
+
+(defconst mm-image-type-regexps
+  '(("/\\*.*XPM.\\*/" . xpm)
+    ("P[1-6]" . pbm)
+    ("GIF8" . gif)
+    ("\377\330" . jpeg)
+    ("\211PNG\r\n" . png)
+    ("#define" . xbm)
+    ("\\(MM\0\\*\\)\\|\\(II\\*\0\\)" . tiff)
+    ("%!PS" . postscript))
+  "Alist of (REGEXP . IMAGE-TYPE) pairs used to auto-detect image types.
+When the first bytes of an image file match REGEXP, it is assumed to
+be of image type IMAGE-TYPE.")
+
+;; Steal from image.el. image-type-from-data suffers multi-line matching bug.
+(defun mm-image-type-from-buffer ()
+  "Determine the image type from data in the current buffer.
+Value is a symbol specifying the image type or nil if type cannot
+be determined."
+  (let ((types mm-image-type-regexps)
+       type)
+    (goto-char (point-min))
+    (while (and types (null type))
+      (let ((regexp (car (car types)))
+           (image-type (cdr (car types))))
+       (when (looking-at regexp)
+         (setq type image-type))
+       (setq types (cdr types))))
+    type))
+
+(defun mm-get-image (handle)
+  "Return an image instance based on HANDLE."
+  (let ((type (mm-handle-media-subtype handle))
+       spec)
+    ;; Allow some common translations.
+    (setq type
+         (cond
+          ((equal type "x-pixmap")
+           "xpm")
+          ((equal type "x-xbitmap")
+           "xbm")
+          ((equal type "x-portable-bitmap")
+           "pbm")
+          (t type)))
+    (or (mm-handle-cache handle)
+       (mm-with-unibyte-buffer
+         (mm-insert-part handle)
+         (prog1
+             (setq spec
+                   (ignore-errors
+                     ;; Avoid testing `make-glyph' since W3 may define
+                     ;; a bogus version of it.
+                     (if (fboundp 'create-image)
+                         (create-image (buffer-string)
+                                       (or (mm-image-type-from-buffer)
+                                           (intern type))
+                                       'data-p)
+                       (mm-create-image-xemacs type))))
+           (mm-handle-set-cache handle spec))))))
+
+(defun mm-create-image-xemacs (type)
+  (cond
+   ((equal type "xbm")
+    ;; xbm images require special handling, since
+    ;; the only way to create glyphs from these
+    ;; (without a ton of work) is to write them
+    ;; out to a file, and then create a file
+    ;; specifier.
+    (let ((file (mm-make-temp-file
+                (expand-file-name "emm.xbm"
+                                  mm-tmp-directory))))
+      (unwind-protect
+         (progn
+           (write-region (point-min) (point-max) file)
+           (make-glyph (list (cons 'x file))))
+       (ignore-errors
+         (delete-file file)))))
+   (t
+    (make-glyph
+     (vector
+      (or (mm-image-type-from-buffer)
+         (intern type))
+      :data (buffer-string))))))
+
+(defun mm-image-fit-p (handle)
+  "Say whether the image in HANDLE will fit the current window."
+  (let ((image (mm-get-image handle)))
+    (if (fboundp 'glyph-width)
+       ;; XEmacs' glyphs can actually tell us about their width, so
+       ;; lets be nice and smart about them.
+       (or mm-inline-large-images
+           (and (< (glyph-width image) (window-pixel-width))
+                (< (glyph-height image) (window-pixel-height))))
+      (let* ((size (image-size image))
+            (w (car size))
+            (h (cdr size)))
+       (or mm-inline-large-images
+           (and (< h (1- (window-height))) ; Don't include mode line.
+                (< w (window-width))))))))
+
+(defun mm-valid-image-format-p (format)
+  "Say whether FORMAT can be displayed natively by Emacs."
+  (cond
+   ;; Handle XEmacs
+   ((fboundp 'valid-image-instantiator-format-p)
+    (valid-image-instantiator-format-p format))
+   ;; Handle Emacs 21
+   ((fboundp 'image-type-available-p)
+    (and (display-graphic-p)
+        (image-type-available-p format)))
+   ;; Nobody else can do images yet.
+   (t
+    nil)))
+
+(defun mm-valid-and-fit-image-p (format handle)
+  "Say whether FORMAT can be displayed natively and HANDLE fits the window."
+  (and (mm-valid-image-format-p format)
+       (mm-image-fit-p handle)))
+
+(defun mm-find-part-by-type (handles type &optional notp recursive)
+  "Search in HANDLES for part with TYPE.
+If NOTP, returns first non-matching part.
+If RECURSIVE, search recursively."
+  (let (handle)
+    (while handles
+      (if (and recursive (stringp (caar handles)))
+         (if (setq handle (mm-find-part-by-type (cdar handles) type
+                                                notp recursive))
+             (setq handles nil))
+       (if (if notp
+               (not (equal (mm-handle-media-type (car handles)) type))
+             (equal (mm-handle-media-type (car handles)) type))
+           (setq handle (car handles)
+                 handles nil)))
+      (setq handles (cdr handles)))
+    handle))
+
+(defun mm-find-raw-part-by-type (ctl type &optional notp)
+  (goto-char (point-min))
+  (let* ((boundary (concat "--" (mm-handle-multipart-ctl-parameter ctl
+                                                                  'boundary)))
+        (close-delimiter (concat "^" (regexp-quote boundary) "--[ \t]*$"))
+        start
+        (end (save-excursion
+               (goto-char (point-max))
+               (if (re-search-backward close-delimiter nil t)
+                   (match-beginning 0)
+                 (point-max))))
+        result)
+    (setq boundary (concat "^" (regexp-quote boundary) "[ \t]*$"))
+    (while (and (not result)
+               (re-search-forward boundary end t))
+      (goto-char (match-beginning 0))
+      (when start
+       (save-excursion
+         (save-restriction
+           (narrow-to-region start (1- (point)))
+           (when (let ((ctl (ignore-errors
+                              (mail-header-parse-content-type
+                               (mail-fetch-field "content-type")))))
+                   (if notp
+                       (not (equal (car ctl) type))
+                     (equal (car ctl) type)))
+             (setq result (buffer-string))))))
+      (forward-line 1)
+      (setq start (point)))
+    (when (and (not result) start)
+      (save-excursion
+       (save-restriction
+         (narrow-to-region start end)
+         (when (let ((ctl (ignore-errors
+                            (mail-header-parse-content-type
+                             (mail-fetch-field "content-type")))))
+                 (if notp
+                     (not (equal (car ctl) type))
+                   (equal (car ctl) type)))
+           (setq result (buffer-string))))))
+    result))
+
+(defvar mm-security-handle nil)
+
+(defsubst mm-set-handle-multipart-parameter (handle parameter value)
+  ;; HANDLE could be a CTL.
+  (when handle
+    (put-text-property 0 (length (car handle)) parameter value
+                      (car handle))))
+
+(defun mm-possibly-verify-or-decrypt (parts ctl)
+  (let ((type (car ctl))
+       (subtype (cadr (split-string (car ctl) "/")))
+       (mm-security-handle ctl) ;; (car CTL) is the type.
+       protocol func functest)
+    (cond
+     ((or (equal type "application/x-pkcs7-mime")
+         (equal type "application/pkcs7-mime"))
+      (with-temp-buffer
+       (when (and (cond
+                   ((eq mm-decrypt-option 'never) nil)
+                   ((eq mm-decrypt-option 'always) t)
+                   ((eq mm-decrypt-option 'known) t)
+                   (t (y-or-n-p
+                       (format "Decrypt (S/MIME) part? "))))
+                  (mm-view-pkcs7 parts))
+         (setq parts (mm-dissect-buffer t)))))
+     ((equal subtype "signed")
+      (unless (and (setq protocol
+                        (mm-handle-multipart-ctl-parameter ctl 'protocol))
+                  (not (equal protocol "multipart/mixed")))
+       ;; The message is broken or draft-ietf-openpgp-multsig-01.
+       (let ((protocols mm-verify-function-alist))
+         (while protocols
+           (if (and (or (not (setq functest (nth 3 (car protocols))))
+                        (funcall functest parts ctl))
+                    (mm-find-part-by-type parts (caar protocols) nil t))
+               (setq protocol (caar protocols)
+                     protocols nil)
+             (setq protocols (cdr protocols))))))
+      (setq func (nth 1 (assoc protocol mm-verify-function-alist)))
+      (when (cond
+            ((eq mm-verify-option 'never) nil)
+            ((eq mm-verify-option 'always) t)
+            ((eq mm-verify-option 'known)
+             (and func
+                  (or (not (setq functest
+                                 (nth 3 (assoc protocol
+                                               mm-verify-function-alist))))
+                      (funcall functest parts ctl))))
+            (t
+             (y-or-n-p
+              (format "Verify signed (%s) part? "
+                      (or (nth 2 (assoc protocol mm-verify-function-alist))
+                          (format "protocol=%s" protocol))))))
+       (save-excursion
+         (if func
+             (funcall func parts ctl)
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-details
+            (format "Unknown sign protocol (%s)" protocol))))))
+     ((equal subtype "encrypted")
+      (unless (setq protocol
+                   (mm-handle-multipart-ctl-parameter ctl 'protocol))
+       ;; The message is broken.
+       (let ((parts parts))
+         (while parts
+           (if (assoc (mm-handle-media-type (car parts))
+                      mm-decrypt-function-alist)
+               (setq protocol (mm-handle-media-type (car parts))
+                     parts nil)
+             (setq parts (cdr parts))))))
+      (setq func (nth 1 (assoc protocol mm-decrypt-function-alist)))
+      (when (cond
+            ((eq mm-decrypt-option 'never) nil)
+            ((eq mm-decrypt-option 'always) t)
+            ((eq mm-decrypt-option 'known)
+             (and func
+                  (or (not (setq functest
+                                 (nth 3 (assoc protocol
+                                               mm-decrypt-function-alist))))
+                      (funcall functest parts ctl))))
+            (t
+             (y-or-n-p
+              (format "Decrypt (%s) part? "
+                      (or (nth 2 (assoc protocol mm-decrypt-function-alist))
+                          (format "protocol=%s" protocol))))))
+       (save-excursion
+         (if func
+             (setq parts (funcall func parts ctl))
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-details
+            (format "Unknown encrypt protocol (%s)" protocol))))))
+     (t nil))
+    parts))
+
+(defun mm-multiple-handles (handles)
+  (and (listp (car handles))
+       (> (length handles) 1)))
+
+(defun mm-merge-handles (handles1 handles2)
+  (append
+   (if (listp (car handles1))
+       handles1
+     (list handles1))
+   (if (listp (car handles2))
+       handles2
+     (list handles2))))
+
+(defun mm-readable-p (handle)
+  "Say whether the content of HANDLE is readable."
+  (and (< (with-current-buffer (mm-handle-buffer handle)
+           (buffer-size)) 10000)
+       (mm-with-unibyte-buffer
+        (mm-insert-part handle)
+        (and (eq (mm-body-7-or-8) '7bit)
+             (not (mm-long-lines-p 76))))))
+
+(provide 'mm-decode)
+
+;;; mm-decode.el ends here
diff --git a/lisp/mm-encode.el b/lisp/mm-encode.el
new file mode 100644 (file)
index 0000000..cb17414
--- /dev/null
@@ -0,0 +1,197 @@
+;;; mm-encode.el --- Functions for encoding MIME things
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'mail-parse)
+(require 'gnus-mailcap)
+(eval-and-compile
+  (autoload 'mm-body-7-or-8 "mm-bodies")
+  (autoload 'mm-long-lines-p "mm-bodies"))
+
+(defcustom mm-content-transfer-encoding-defaults
+  '(("text/x-patch" 8bit)
+    ("text/.*" qp-or-base64)
+    ("message/rfc822" 8bit)
+    ("application/emacs-lisp" 8bit)
+    ("application/x-emacs-lisp" 8bit)
+    ("application/x-patch" 8bit)
+    (".*" base64))
+  "Alist of regexps that match MIME types and their encodings.
+If the encoding is `qp-or-base64', then either quoted-printable
+or base64 will be used, depending on what is more efficient."
+  :type '(repeat (list (regexp :tag "MIME type")
+                      (choice :tag "encoding"
+                              (const 7bit)
+                              (const 8bit)
+                              (const qp-or-base64)
+                              (const quoted-printable)
+                              (const base64))))
+  :group 'mime)
+
+(defvar mm-use-ultra-safe-encoding nil
+  "If non-nil, use encodings aimed at Procrustean bed survival.
+
+This means that textual parts are encoded as quoted-printable if they
+contain lines longer than 76 characters or starting with \"From \" in
+the body.  Non-7bit encodings (8bit, binary) are generally disallowed.
+This is to reduce the probability that a broken MTA or MDA changes the
+message.
+
+This variable should never be set directly, but bound before a call to
+`mml-generate-mime' or similar functions.")
+
+(defun mm-insert-rfc822-headers (charset encoding)
+  "Insert text/plain headers with CHARSET and ENCODING."
+  (insert "MIME-Version: 1.0\n")
+  (insert "Content-Type: text/plain; charset="
+         (mail-quote-string (downcase (symbol-name charset))) "\n")
+  (insert "Content-Transfer-Encoding: "
+         (downcase (symbol-name encoding)) "\n"))
+
+(defun mm-insert-multipart-headers ()
+  "Insert multipart/mixed headers."
+  (let ((boundary "=-=-="))
+    (insert "MIME-Version: 1.0\n")
+    (insert "Content-Type: multipart/mixed; boundary=\"" boundary "\"\n")
+    boundary))
+
+(defun mm-default-file-encoding (file)
+  "Return a default encoding for FILE."
+  (if (not (string-match "\\.[^.]+$" file))
+      "application/octet-stream"
+    (mailcap-extension-to-mime (match-string 0 file))))
+
+(defun mm-safer-encoding (encoding)
+  "Return an encoding similar to ENCODING but safer than it."
+  (cond
+   ((memq encoding '(7bit 8bit quoted-printable)) 'quoted-printable)
+   ;; The remaining encodings are binary and base64 (and perhaps some
+   ;; non-standard ones), which are both turned into base64.
+   (t 'base64)))
+
+(defun mm-encode-content-transfer-encoding (encoding &optional type)
+  "Encode the current buffer with ENCODING for MIME type TYPE.
+ENCODING can be: nil (do nothing); one of `quoted-printable', `base64';
+`7bit', `8bit' or `binary' (all do nothing); a function to do the encoding."
+  (cond
+   ((eq encoding 'quoted-printable)
+    ;; This used to try to make a multibyte buffer unibyte.  That's
+    ;; completely wrong, since you'd get QP-encoded emacs-mule.  If
+    ;; this gets run on multibyte text it's an error that needs
+    ;; fixing, and the encoding function will signal an error.
+    ;; Likewise base64 below.
+    (quoted-printable-encode-region (point-min) (point-max) t))
+   ((eq encoding 'base64)
+    (when (equal type "text/plain")
+      (goto-char (point-min))
+      (while (search-forward "\n" nil t)
+       (replace-match "\r\n" t t)))
+    (base64-encode-region (point-min) (point-max)))
+   ((memq encoding '(7bit 8bit binary))
+    ;; Do nothing.
+    )
+   ((null encoding)
+    ;; Do nothing.
+    )
+   ;; Fixme: Ignoring errors here looks bogus.
+   ((functionp encoding)
+    (ignore-errors (funcall encoding (point-min) (point-max))))
+   (t
+    (error "Unknown encoding %s" encoding))))
+
+(defun mm-encode-buffer (type)
+  "Encode the buffer which contains data of MIME type TYPE.
+TYPE is a string or a list of the components.
+The encoding used is returned."
+  (let* ((mime-type (if (stringp type) type (car type)))
+        (encoding
+         (or (and (listp type)
+                  (cadr (assq 'encoding type)))
+             (mm-content-transfer-encoding mime-type)))
+        (bits (mm-body-7-or-8)))
+    ;; We force buffers that are 7bit to be unencoded, no matter
+    ;; what the preferred encoding is.
+    ;; Only if the buffers don't contain lone lines.
+    (when (and (eq bits '7bit) (not (mm-long-lines-p 76)))
+      (setq encoding bits))
+    (mm-encode-content-transfer-encoding encoding mime-type)
+    encoding))
+
+(defun mm-insert-headers (type encoding &optional file)
+  "Insert headers for TYPE."
+  (insert "Content-Type: " type)
+  (when file
+    (insert ";\n\tname=\"" (file-name-nondirectory file) "\""))
+  (insert "\n")
+  (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+  (insert "Content-Disposition: inline")
+  (when file
+    (insert ";\n\tfilename=\"" (file-name-nondirectory file) "\""))
+  (insert "\n")
+  (insert "\n"))
+
+(defun mm-content-transfer-encoding (type)
+  "Return a CTE suitable for TYPE to encode the current buffer."
+  (let ((rules mm-content-transfer-encoding-defaults))
+    (catch 'found
+      (while rules
+       (when (string-match (caar rules) type)
+         (throw 'found
+                (let ((encoding
+                       (if (eq (cadr (car rules)) 'qp-or-base64)
+                           (mm-qp-or-base64)
+                         (cadr (car rules)))))
+                  (if mm-use-ultra-safe-encoding
+                      (mm-safer-encoding encoding)
+                    encoding))))
+       (pop rules)))))
+
+(defun mm-qp-or-base64 ()
+  "Return the type with which to encode the buffer.
+This is either `base64' or `quoted-printable'."
+  (if (equal mm-use-ultra-safe-encoding '(sign . "pgp"))
+      ;; perhaps not always accurate?
+      'quoted-printable
+    (save-excursion
+      (let ((limit (min (point-max) (+ 2000 (point-min))))
+           (n8bit 0))
+       (goto-char (point-min))
+       (skip-chars-forward "\x20-\x7f\r\n\t" limit)
+       (while (< (point) limit)
+         (incf n8bit)
+         (forward-char 1)
+         (skip-chars-forward "\x20-\x7f\r\n\t" limit))
+       (if (or (< (* 6 n8bit) (- limit (point-min)))
+               ;; Don't base64, say, a short line with a single
+               ;; non-ASCII char when splitting parts by charset.
+               (= n8bit 1))
+           'quoted-printable
+         'base64)))))
+
+(provide 'mm-encode)
+
+;;; mm-encode.el ends here
diff --git a/lisp/mm-extern.el b/lisp/mm-extern.el
new file mode 100644 (file)
index 0000000..b063ee8
--- /dev/null
@@ -0,0 +1,168 @@
+;;; mm-extern.el --- showing message/external-body
+;; Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: message external-body
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'mm-util)
+(require 'mm-decode)
+(require 'mm-url)
+
+(defvar mm-extern-function-alist
+  '((local-file . mm-extern-local-file)
+    (url . mm-extern-url)
+    (anon-ftp . mm-extern-anon-ftp)
+    (ftp . mm-extern-ftp)
+;;;     (tftp . mm-extern-tftp)
+    (mail-server . mm-extern-mail-server)
+;;;     (afs . mm-extern-afs))
+    ))
+
+(defvar mm-extern-anonymous "anonymous")
+
+(defun mm-extern-local-file (handle)
+  (erase-buffer)
+  (let ((name (cdr (assq 'name (cdr (mm-handle-type handle)))))
+       (coding-system-for-read mm-binary-coding-system))
+    (unless name
+      (error "The filename is not specified"))
+    (mm-disable-multibyte)
+    (if (file-exists-p name)
+       (mm-insert-file-contents name nil nil nil nil t)
+      (error (format "File %s is gone" name)))))
+
+(defun mm-extern-url (handle)
+  (erase-buffer)
+  (let ((url (cdr (assq 'url (cdr (mm-handle-type handle)))))
+       (name buffer-file-name)
+       (coding-system-for-read mm-binary-coding-system))
+    (unless url
+      (error "URL is not specified"))
+    (mm-with-unibyte-current-buffer
+      (mm-url-insert-file-contents url))
+    (mm-disable-multibyte)
+    (setq buffer-file-name name)))
+
+(defun mm-extern-anon-ftp (handle)
+  (erase-buffer)
+  (let* ((params (cdr (mm-handle-type handle)))
+        (name (cdr (assq 'name params)))
+        (site (cdr (assq 'site params)))
+        (directory (cdr (assq 'directory params)))
+        (mode (cdr (assq 'mode params)))
+        (path (concat "/" (or mm-extern-anonymous
+                              (read-string (format "ID for %s: " site)))
+                      "@" site ":" directory "/" name))
+        (coding-system-for-read mm-binary-coding-system))
+    (unless name
+      (error "The filename is not specified"))
+    (mm-disable-multibyte)
+    (mm-insert-file-contents path nil nil nil nil t)))
+
+(defun mm-extern-ftp (handle)
+  (let (mm-extern-anonymous)
+    (mm-extern-anon-ftp handle)))
+
+(defun mm-extern-mail-server (handle)
+  (require 'message)
+  (let* ((params (cdr (mm-handle-type handle)))
+        (server (cdr (assq 'server params)))
+        (subject (or (cdr (assq 'subject params)) "none"))
+        (buf (current-buffer))
+        info)
+    (if (y-or-n-p (format "Send a request message to %s?" server))
+       (save-window-excursion
+         (message-mail server subject)
+         (message-goto-body)
+         (delete-region (point) (point-max))
+         (insert-buffer-substring buf)
+         (message "Requesting external body...")
+         (message-send-and-exit)
+         (setq info "Request is sent.")
+         (message info))
+      (setq info "Request is not sent."))
+    (goto-char (point-min))
+    (insert "[" info "]\n\n")))
+
+;;;###autoload
+(defun mm-inline-external-body (handle &optional no-display)
+  "Show the external-body part of HANDLE.
+This function replaces the buffer of HANDLE with a buffer contains
+the entire message.
+If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing."
+  (let* ((access-type (cdr (assq 'access-type
+                                (cdr (mm-handle-type handle)))))
+        (func (cdr (assq (intern
+                          (downcase
+                           (or access-type
+                               (error "Couldn't find access type"))))
+                         mm-extern-function-alist)))
+        gnus-displaying-mime buf
+        handles)
+    (unless (mm-handle-cache handle)
+      (unless func
+       (error (format "Access type (%s) is not supported" access-type)))
+      (with-temp-buffer
+       (mm-insert-part handle)
+       (goto-char (point-max))
+       (insert "\n\n")
+       (setq handles (mm-dissect-buffer t)))
+      (unless (bufferp (car handles))
+       (mm-destroy-parts handles)
+       (error "Multipart external body is not supported"))
+      (save-excursion ;; single part
+       (set-buffer (setq buf (mm-handle-buffer handles)))
+       (let (good)
+         (unwind-protect
+             (progn
+               (funcall func handle)
+               (setq good t))
+           (unless good
+             (mm-destroy-parts handles))))
+       (mm-handle-set-cache handle handles))
+      (setq gnus-article-mime-handles
+           (mm-merge-handles gnus-article-mime-handles handles)))
+    (unless no-display
+      (save-excursion
+       (save-restriction
+         (narrow-to-region (point) (point))
+         (gnus-display-mime (mm-handle-cache handle))
+         (mm-handle-set-undisplayer
+          handle
+          `(lambda ()
+             (let (buffer-read-only)
+               (condition-case nil
+                   ;; This is only valid on XEmacs.
+                   (mapcar (lambda (prop)
+                             (remove-specifier
+                              (face-property 'default prop) (current-buffer)))
+                           '(background background-pixmap foreground))
+                 (error nil))
+               (delete-region ,(point-min-marker) ,(point-max-marker))))))))))
+
+(provide 'mm-extern)
+
+;;; mm-extern.el ends here
diff --git a/lisp/mm-partial.el b/lisp/mm-partial.el
new file mode 100644 (file)
index 0000000..7a4cd0b
--- /dev/null
@@ -0,0 +1,154 @@
+;;; mm-partial.el --- showing message/partial
+;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: message partial
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'gnus-sum)
+(require 'mm-util)
+(require 'mm-decode)
+
+(defun mm-partial-find-parts (id &optional art)
+  (let ((headers (save-excursion
+                  (set-buffer gnus-summary-buffer)
+                  gnus-newsgroup-headers))
+       phandles header)
+    (while (setq header (pop headers))
+      (unless (eq (aref header 0) art)
+       (mm-with-unibyte-buffer
+         (gnus-request-article-this-buffer (aref header 0)
+                                           gnus-newsgroup-name)
+         (when (search-forward id nil t)
+           (let ((nhandles (mm-dissect-buffer
+                            nil gnus-article-loose-mime)) nid)
+             (if (consp (car nhandles))
+                 (mm-destroy-parts nhandles)
+               (setq nid (cdr (assq 'id
+                                    (cdr (mm-handle-type nhandles)))))
+               (if (not (equal id nid))
+                   (mm-destroy-parts nhandles)
+                 (push nhandles phandles))))))))
+    phandles))
+
+;;;###autoload
+(defun mm-inline-partial (handle &optional no-display)
+  "Show the partial part of HANDLE.
+This function replaces the buffer of HANDLE with a buffer contains
+the entire message.
+If NO-DISPLAY is nil, display it. Otherwise, do nothing after replacing."
+  (let ((id (cdr (assq 'id (cdr (mm-handle-type handle)))))
+       phandles
+       (b (point)) (n 1) total
+       phandle nn ntotal
+       gnus-displaying-mime handles buffer)
+    (unless (mm-handle-cache handle)
+      (unless id
+       (error "Can not find message/partial id"))
+      (setq phandles
+           (sort (cons handle
+                       (mm-partial-find-parts
+                        id
+                        (save-excursion
+                          (set-buffer gnus-summary-buffer)
+                          (gnus-summary-article-number))))
+                 #'(lambda (a b)
+                     (let ((anumber (string-to-number
+                                     (cdr (assq 'number
+                                                (cdr (mm-handle-type a))))))
+                           (bnumber (string-to-number
+                                     (cdr (assq 'number
+                                                (cdr (mm-handle-type b)))))))
+                       (< anumber bnumber)))))
+      (setq gnus-article-mime-handles
+           (mm-merge-handles gnus-article-mime-handles phandles))
+      (save-excursion
+       (set-buffer (generate-new-buffer " *mm*"))
+       (while (setq phandle (pop phandles))
+         (setq nn (string-to-number
+                   (cdr (assq 'number
+                              (cdr (mm-handle-type phandle))))))
+         (setq ntotal (string-to-number
+                       (cdr (assq 'total
+                                  (cdr (mm-handle-type phandle))))))
+         (if ntotal
+             (if total
+                 (unless (eq total ntotal)
+                   (error "The numbers of total are different"))
+               (setq total ntotal)))
+         (unless (< nn n)
+           (unless (eq nn n)
+             (error "Missing part %d" n))
+           (mm-insert-part phandle)
+           (goto-char (point-max))
+           (when (not (eq 0 (skip-chars-backward "\r\n")))
+             ;; remove tail blank spaces except one
+             (if (looking-at "\r?\n")
+                 (goto-char (match-end 0)))
+             (delete-region (point) (point-max)))
+           (setq n (+ n 1))))
+       (unless total
+         (error "Don't known the total number of"))
+       (if (<= n total)
+           (error "Missing part %d" n))
+       (kill-buffer (mm-handle-buffer handle))
+       (goto-char (point-min))
+       (let ((point (if (search-forward "\n\n" nil t)
+                        (1- (point))
+                      (point-max))))
+         (goto-char (point-min))
+         (unless (re-search-forward "^mime-version:" point t)
+           (insert "MIME-Version: 1.0\n")))
+       (setcar handle (current-buffer))
+       (mm-handle-set-cache handle t)))
+    (unless no-display
+      (save-excursion
+       (save-restriction
+         (narrow-to-region b b)
+         (mm-insert-part handle)
+         (let (gnus-article-mime-handles)
+           (run-hooks 'gnus-article-decode-hook)
+           (gnus-article-prepare-display)
+           (setq handles gnus-article-mime-handles))
+         (when handles
+           ;; It is in article buffer.
+           (setq gnus-article-mime-handles
+                 (mm-merge-handles gnus-article-mime-handles handles)))
+         (mm-handle-set-undisplayer
+          handle
+          `(lambda ()
+             (let (buffer-read-only)
+               (condition-case nil
+                   ;; This is only valid on XEmacs.
+                   (mapcar (lambda (prop)
+                             (remove-specifier
+                              (face-property 'default prop) (current-buffer)))
+                           '(background background-pixmap foreground))
+                 (error nil))
+               (delete-region ,(point-min-marker) ,(point-max-marker))))))))))
+
+(provide 'mm-partial)
+
+;;; mm-partial.el ends here
diff --git a/lisp/mm-url.el b/lisp/mm-url.el
new file mode 100644 (file)
index 0000000..7ff8140
--- /dev/null
@@ -0,0 +1,451 @@
+;;; mm-url.el --- a wrapper of url functions/commands for Gnus
+;; Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Some codes are stolen from w3 and url packages. Some are moved from
+;; nnweb.
+
+;; TODO: Support POST, cookie.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'mm-util)
+(require 'gnus)
+
+(eval-and-compile
+  (autoload 'exec-installed-p "path-util"))
+
+(eval-when-compile
+  (require 'timer))
+
+(defgroup mm-url nil
+  "A wrapper of url package and external url command for Gnus."
+  :group 'gnus)
+
+(defcustom mm-url-use-external (not
+                               (condition-case nil
+                                   (require 'url)
+                                 (error nil)))
+  "*If non-nil, use external grab program `mm-url-program'."
+  :type 'boolean
+  :group 'mm-url)
+
+(defvar mm-url-predefined-programs
+  '((wget "wget" "--user-agent=mm-url" "-q" "-O" "-")
+    (w3m  "w3m" "-dump_source")
+    (lynx "lynx" "-source")
+    (curl "curl")))
+
+(defcustom mm-url-program
+  (cond
+   ((exec-installed-p "wget") 'wget)
+   ((exec-installed-p "w3m") 'w3m)
+   ((exec-installed-p "lynx") 'lynx)
+   ((exec-installed-p "curl") 'curl)
+   (t "GET"))
+  "The url grab program.
+Likely values are `wget', `w3m', `lynx' and `curl'."
+  :type '(choice
+         (symbol :tag "wget" wget)
+         (symbol :tag "w3m" w3m)
+         (symbol :tag "lynx" lynx)
+         (symbol :tag "curl" curl)
+         (string :tag "other"))
+  :group 'mm-url)
+
+(defcustom mm-url-arguments nil
+  "The arguments for `mm-url-program'."
+  :type '(repeat string)
+  :group 'mm-url)
+
+\f
+;;; Internal variables
+
+(defvar mm-url-package-name
+  (gnus-replace-in-string
+   (gnus-replace-in-string gnus-version " v.*$" "")
+   " " "-"))
+
+(defvar        mm-url-package-version gnus-version-number)
+
+;; Stolen from w3.
+(defvar mm-url-html-entities
+  '(
+    ;;(excl        .  33)
+    (quot        .  34)
+    ;;(num         .  35)
+    ;;(dollar      .  36)
+    ;;(percent     .  37)
+    (amp         .  38)
+    (rsquo       .  39)                        ; should be U+8217
+    ;;(apos        .  39)
+    ;;(lpar        .  40)
+    ;;(rpar        .  41)
+    ;;(ast         .  42)
+    ;;(plus        .  43)
+    ;;(comma       .  44)
+    ;;(period      .  46)
+    ;;(colon       .  58)
+    ;;(semi        .  59)
+    (lt          .  60)
+    ;;(equals      .  61)
+    (gt          .  62)
+    ;;(quest       .  63)
+    ;;(commat      .  64)
+    ;;(lsqb        .  91)
+    ;;(rsqb        .  93)
+    (uarr        .  94)                        ; should be U+8593
+    ;;(lowbar      .  95)
+    (lsquo       .  96)                        ; should be U+8216
+    (lcub        . 123)
+    ;;(verbar      . 124)
+    (rcub        . 125)
+    (tilde       . 126)
+    (nbsp        . 160)
+    (iexcl       . 161)
+    (cent        . 162)
+    (pound       . 163)
+    (curren      . 164)
+    (yen         . 165)
+    (brvbar      . 166)
+    (sect        . 167)
+    (uml         . 168)
+    (copy        . 169)
+    (ordf        . 170)
+    (laquo       . 171)
+    (not         . 172)
+    (shy         . 173)
+    (reg         . 174)
+    (macr        . 175)
+    (deg         . 176)
+    (plusmn      . 177)
+    (sup2        . 178)
+    (sup3        . 179)
+    (acute       . 180)
+    (micro       . 181)
+    (para        . 182)
+    (middot      . 183)
+    (cedil       . 184)
+    (sup1        . 185)
+    (ordm        . 186)
+    (raquo       . 187)
+    (frac14      . 188)
+    (frac12      . 189)
+    (frac34      . 190)
+    (iquest      . 191)
+    (Agrave      . 192)
+    (Aacute      . 193)
+    (Acirc       . 194)
+    (Atilde      . 195)
+    (Auml        . 196)
+    (Aring       . 197)
+    (AElig       . 198)
+    (Ccedil      . 199)
+    (Egrave      . 200)
+    (Eacute      . 201)
+    (Ecirc       . 202)
+    (Euml        . 203)
+    (Igrave      . 204)
+    (Iacute      . 205)
+    (Icirc       . 206)
+    (Iuml        . 207)
+    (ETH         . 208)
+    (Ntilde      . 209)
+    (Ograve      . 210)
+    (Oacute      . 211)
+    (Ocirc       . 212)
+    (Otilde      . 213)
+    (Ouml        . 214)
+    (times       . 215)
+    (Oslash      . 216)
+    (Ugrave      . 217)
+    (Uacute      . 218)
+    (Ucirc       . 219)
+    (Uuml        . 220)
+    (Yacute      . 221)
+    (THORN       . 222)
+    (szlig       . 223)
+    (agrave      . 224)
+    (aacute      . 225)
+    (acirc       . 226)
+    (atilde      . 227)
+    (auml        . 228)
+    (aring       . 229)
+    (aelig       . 230)
+    (ccedil      . 231)
+    (egrave      . 232)
+    (eacute      . 233)
+    (ecirc       . 234)
+    (euml        . 235)
+    (igrave      . 236)
+    (iacute      . 237)
+    (icirc       . 238)
+    (iuml        . 239)
+    (eth         . 240)
+    (ntilde      . 241)
+    (ograve      . 242)
+    (oacute      . 243)
+    (ocirc       . 244)
+    (otilde      . 245)
+    (ouml        . 246)
+    (divide      . 247)
+    (oslash      . 248)
+    (ugrave      . 249)
+    (uacute      . 250)
+    (ucirc       . 251)
+    (uuml        . 252)
+    (yacute      . 253)
+    (thorn       . 254)
+    (yuml        . 255)
+
+    ;; Special handling of these
+    (frac56      . "5/6")
+    (frac16      . "1/6")
+    (frac45      . "4/5")
+    (frac35      . "3/5")
+    (frac25      . "2/5")
+    (frac15      . "1/5")
+    (frac23      . "2/3")
+    (frac13      . "1/3")
+    (frac78      . "7/8")
+    (frac58      . "5/8")
+    (frac38      . "3/8")
+    (frac18      . "1/8")
+
+    ;; The following 5 entities are not mentioned in the HTML 2.0
+    ;; standard, nor in any other HTML proposed standard of which I
+    ;; am aware.  I am not even sure they are ISO entity names.  ***
+    ;; Hence, some arrangement should be made to give a bad HTML
+    ;; message when they are seen.
+    (ndash       .  45)
+    (mdash       .  45)
+    (emsp        .  32)
+    (ensp        .  32)
+    (sim         . 126)
+    (le          . "<=")
+    (agr         . "alpha")
+    (rdquo       . "''")
+    (ldquo       . "``")
+    (trade       . "(TM)")
+    ;; To be done
+    ;; (shy      . ????) ; soft hyphen
+    )
+  "*An assoc list of entity names and how to actually display them.")
+
+(defconst mm-url-unreserved-chars
+  '(
+    ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
+    ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
+    ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
+    ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\))
+  "A list of characters that are _NOT_ reserved in the URL spec.
+This is taken from RFC 2396.")
+
+(defun mm-url-load-url ()
+  "Load `url-insert-file-contents'."
+  (unless (condition-case ()
+             (require 'url-handlers)
+           (error nil))
+    ;; w3-4.0pre0.46 or earlier version.
+    (require 'w3-vars)
+    (require 'url)))
+
+;;;###autoload
+(defun mm-url-insert-file-contents (url)
+  "Insert file contents of URL.
+If `mm-url-use-external' is non-nil, use `mm-url-program'."
+  (if mm-url-use-external
+      (progn
+       (if (string-match "^file:/+" url)
+           (insert-file-contents (substring url (1- (match-end 0))))
+         (mm-url-insert-file-contents-external url))
+       (goto-char (point-min))
+       (if (fboundp 'url-generic-parse-url)
+           (setq url-current-object
+                 (url-generic-parse-url url)))
+       (list url (buffer-size)))
+    (mm-url-load-url)
+    (let ((name buffer-file-name)
+         (url-request-extra-headers (list (cons "Connection" "Close")))
+         (url-package-name (or mm-url-package-name
+                               url-package-name))
+         (url-package-version (or mm-url-package-version
+                                  url-package-version))
+         result)
+      (setq result (url-insert-file-contents url))
+      (save-excursion
+       (goto-char (point-min))
+       (while (re-search-forward "\r 1000\r ?" nil t)
+         (replace-match "")))
+      (setq buffer-file-name name)
+      (if (and (fboundp 'url-generic-parse-url)
+              (listp result))
+         (setq url-current-object (url-generic-parse-url
+                                   (car result))))
+      result)))
+
+;;;###autoload
+(defun mm-url-insert-file-contents-external (url)
+  "Insert file contents of URL using `mm-url-program'."
+  (let (program args)
+    (if (symbolp mm-url-program)
+       (let ((item (cdr (assq mm-url-program mm-url-predefined-programs))))
+         (setq program (car item)
+               args (append (cdr item) (list url))))
+      (setq program mm-url-program
+           args (append mm-url-arguments (list url))))
+    (unless (eq 0 (apply 'call-process program nil t nil args))
+      (error "Couldn't fetch %s" url))))
+
+(defvar mm-url-timeout 30
+  "The number of seconds before timing out an URL fetch.")
+
+(defvar mm-url-retries 10
+  "The number of retries after timing out when fetching an URL.")
+
+(defun mm-url-insert (url &optional follow-refresh)
+  "Insert the contents from an URL in the current buffer.
+If FOLLOW-REFRESH is non-nil, redirect refresh url in META."
+  (let ((times mm-url-retries)
+       (done nil)
+       (first t)
+       result)
+    (while (and (not (zerop (decf times)))
+               (not done))
+      (with-timeout (mm-url-timeout)
+       (unless first
+         (message "Trying again (%s)..." (- mm-url-retries times)))
+       (setq first nil)
+       (if follow-refresh
+           (save-restriction
+             (narrow-to-region (point) (point))
+             (mm-url-insert-file-contents url)
+             (goto-char (point-min))
+             (when (re-search-forward
+                    "<meta[ \t\r\n]*http-equiv=\"Refresh\"[^>]*URL=\\([^\"]+\\)\"" nil t)
+               (let ((url (match-string 1)))
+                 (delete-region (point-min) (point-max))
+                 (setq result (mm-url-insert url t)))))
+         (setq result (mm-url-insert-file-contents url)))
+       (setq done t)))
+    result))
+
+(defun mm-url-decode-entities ()
+  "Decode all HTML entities."
+  (goto-char (point-min))
+  (while (re-search-forward "&\\(#[0-9]+\\|[a-z]+\\);" nil t)
+    (let ((elem (if (eq (aref (match-string 1) 0) ?\#)
+                       (let ((c
+                              (string-to-number (substring
+                                                 (match-string 1) 1))))
+                         (if (mm-char-or-char-int-p c) c 32))
+                     (or (cdr (assq (intern (match-string 1))
+                                    mm-url-html-entities))
+                         ?#))))
+      (unless (stringp elem)
+       (setq elem (char-to-string elem)))
+      (replace-match elem t t))))
+
+(defun mm-url-decode-entities-nbsp ()
+  "Decode all HTML entities and &nbsp; to a space."
+  (let ((mm-url-html-entities (cons '(nbsp . 32) mm-url-html-entities)))
+    (mm-url-decode-entities)))
+
+(defun mm-url-decode-entities-string (string)
+  (with-temp-buffer
+    (insert string)
+    (mm-url-decode-entities)
+    (buffer-string)))
+
+(defun mm-url-form-encode-xwfu (chunk)
+  "Escape characters in a string for application/x-www-form-urlencoded.
+Blasphemous crap because someone didn't think %20 was good enough for encoding
+spaces.  Die Die Die."
+  ;; This will get rid of the 'attributes' specified by the file type,
+  ;; which are useless for an application/x-www-form-urlencoded form.
+  (if (consp chunk)
+      (setq chunk (cdr chunk)))
+
+  (mapconcat
+   (lambda (char)
+     (cond
+      ((= char ?  ) "+")
+      ((memq char mm-url-unreserved-chars) (char-to-string char))
+      (t (upcase (format "%%%02x" char)))))
+   ;; Fixme: Should this actually be accepting multibyte?  Is there a
+   ;; better way in XEmacs?
+   (if (featurep 'mule)
+       (encode-coding-string chunk
+                            (if (fboundp 'find-coding-systems-string)
+                                (car (find-coding-systems-string chunk))
+                              (static-if (boundp 'MULE)
+                                  file-coding-system
+                                buffer-file-coding-system)))
+     chunk)
+   ""))
+
+(defun mm-url-encode-www-form-urlencoded (pairs)
+  "Return PAIRS encoded for forms."
+  (mapconcat
+   (lambda (data)
+     (concat (mm-url-form-encode-xwfu (car data)) "="
+            (mm-url-form-encode-xwfu (cdr data))))
+   pairs "&"))
+
+(defun mm-url-fetch-form (url pairs)
+  "Fetch a form from URL with PAIRS as the data using the POST method."
+  (mm-url-load-url)
+  (let ((url-request-data (mm-url-encode-www-form-urlencoded pairs))
+       (url-request-method "POST")
+       (url-request-extra-headers
+        '(("Content-type" . "application/x-www-form-urlencoded"))))
+    (url-insert-file-contents url)
+    (setq buffer-file-name nil))
+  t)
+
+(defun mm-url-fetch-simple (url content)
+  (mm-url-load-url)
+  (let ((url-request-data content)
+       (url-request-method "POST")
+       (url-request-extra-headers
+        '(("Content-type" . "application/x-www-form-urlencoded"))))
+    (url-insert-file-contents url)
+    (setq buffer-file-name nil))
+  t)
+
+(defun mm-url-remove-markup ()
+  "Remove all HTML markup, leaving just plain text."
+  (goto-char (point-min))
+  (while (search-forward "<!--" nil t)
+    (delete-region (match-beginning 0)
+                  (or (search-forward "-->" nil t)
+                      (point-max))))
+  (goto-char (point-min))
+  (while (re-search-forward "<[^>]+>" nil t)
+    (replace-match "" t t)))
+
+(provide 'mm-url)
+
+;;; mm-url.el ends here
diff --git a/lisp/mm-util.el b/lisp/mm-util.el
new file mode 100644 (file)
index 0000000..5c1ea1e
--- /dev/null
@@ -0,0 +1,811 @@
+;;; mm-util.el --- Utility functions for Mule and low level things
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;   Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+(eval-when-compile (require 'static))
+
+(require 'mail-prsvr)
+
+(eval-and-compile
+  (mapcar
+   (lambda (elem)
+     (let ((nfunc (intern (format "mm-%s" (car elem)))))
+       (if (fboundp (car elem))
+          (defalias nfunc (car elem))
+        (defalias nfunc (cdr elem)))))
+   '((decode-coding-string . (lambda (s a) s))
+     (encode-coding-string . (lambda (s a) s))
+     (encode-coding-region . ignore)
+     (coding-system-list . ignore)
+     (decode-coding-region . ignore)
+     (char-int . identity)
+     (coding-system-equal . equal)
+     (annotationp . ignore)
+     (set-buffer-file-coding-system . ignore)
+     (make-char
+      . (lambda (charset int)
+         (int-to-char int)))
+     (read-charset
+      . (lambda (prompt)
+         "Return a charset."
+         (intern
+          (completing-read
+           prompt
+           (mapcar (lambda (e) (list (symbol-name (car e))))
+                   mm-mime-mule-charset-alist)
+           nil t))))
+     (subst-char-in-string
+      . (lambda (from to string) ;; stolen (and renamed) from nnheader.el
+         "Replace characters in STRING from FROM to TO."
+         (let ((string (substring string 0)) ;Copy string.
+               (len (length string))
+               (idx 0))
+           ;; Replace all occurrences of FROM with TO.
+           (while (< idx len)
+             (when (= (aref string idx) from)
+               (aset string idx to))
+             (setq idx (1+ idx)))
+           string)))
+     (string-as-unibyte . identity)
+     (string-make-unibyte . identity)
+     (string-as-multibyte . identity)
+     (multibyte-string-p . ignore)
+     ;; It is not a MIME function, but some MIME functions use it.
+     (make-temp-file . (lambda (prefix &optional dir-flag)
+                        (let ((file (expand-file-name
+                                     (make-temp-name prefix)
+                                     (if (fboundp 'temp-directory)
+                                         (temp-directory)
+                                       temporary-file-directory))))
+                          (if dir-flag
+                              (make-directory file))
+                          file)))
+     (insert-byte . insert-char)
+     (multibyte-char-to-unibyte . identity))))
+
+(eval-and-compile
+  (defalias 'mm-char-or-char-int-p
+    (cond
+     ((fboundp 'char-or-char-int-p) 'char-or-char-int-p)
+     ((fboundp 'char-valid-p) 'char-valid-p)
+     (t 'identity))))
+
+;; Fixme:  This seems always to be used to read a MIME charset, so it
+;; should be re-named and fixed (in Emacs) to offer completion only on
+;; proper charset names (base coding systems which have a
+;; mime-charset defined).  XEmacs doesn't believe in mime-charset;
+;; test with
+;;   `(or (coding-system-get 'iso-8859-1 'mime-charset)
+;;        (coding-system-get 'iso-8859-1 :mime-charset))'
+;; Actually, there should be an `mm-coding-system-mime-charset'.
+(eval-and-compile
+  (defalias 'mm-read-coding-system
+    (cond
+     ((fboundp 'read-coding-system)
+      (if (and (featurep 'xemacs)
+              (<= (string-to-number emacs-version) 21.1))
+         (lambda (prompt &optional default-coding-system)
+           (read-coding-system prompt))
+       'read-coding-system))
+     (t (lambda (prompt &optional default-coding-system)
+         "Prompt the user for a coding system."
+         (completing-read
+          prompt (mapcar (lambda (s) (list (symbol-name (car s))))
+                         mm-mime-mule-charset-alist)))))))
+
+(defvar mm-coding-system-list nil)
+(defun mm-get-coding-system-list ()
+  "Get the coding system list."
+  (or mm-coding-system-list
+      (setq mm-coding-system-list (mm-coding-system-list))))
+
+(defun mm-coding-system-p (cs)
+  "Return non-nil if CS is a symbol naming a coding system.
+In XEmacs, also return non-nil if CS is a coding system object."
+  (if (fboundp 'find-coding-system)
+      (find-coding-system cs)
+    (if (fboundp 'coding-system-p)
+       (coding-system-p cs)
+      ;; Is this branch ever actually useful?
+      (memq cs (mm-get-coding-system-list)))))
+
+(defvar mm-charset-synonym-alist
+  `(
+    ;; Perfectly fine?  A valid MIME name, anyhow.
+    ,@(unless (mm-coding-system-p 'big5)
+       '((big5 . cn-big5)))
+    ;; Not in XEmacs, but it's not a proper MIME charset anyhow.
+    ,@(unless (mm-coding-system-p 'x-ctext)
+       '((x-ctext . ctext)))
+    ;; Apparently not defined in Emacs 20, but is a valid MIME name.
+    ,@(unless (mm-coding-system-p 'gb2312)
+       '((gb2312 . cn-gb-2312)))
+    ;; ISO-8859-15 is very similar to ISO-8859-1.  But it's _different_!
+    ,@(unless (mm-coding-system-p 'iso-8859-15)
+       '((iso-8859-15 . iso-8859-1)))
+    ;; BIG-5HKSCS is similar to, but different than, BIG-5.
+    ,@(unless (mm-coding-system-p 'big5-hkscs)
+       '((big5-hkscs . big5)))
+    ;; Windows-1252 is actually a superset of Latin-1.  See also
+    ;; `gnus-article-dumbquotes-map'.
+    ,@(unless (mm-coding-system-p 'windows-1252)
+       (if (mm-coding-system-p 'cp1252)
+          '((windows-1252 . cp1252))
+        '((windows-1252 . iso-8859-1))))
+    ;; Windows-1250 is a variant of Latin-2 heavily used by Microsoft
+    ;; Outlook users in Czech republic. Use this to allow reading of their
+    ;; e-mails. cp1250 should be defined by M-x codepage-setup.
+    ,@(if (and (not (mm-coding-system-p 'windows-1250))
+              (mm-coding-system-p 'cp1250))
+         '((windows-1250 . cp1250)))
+    )
+  "A mapping from invalid charset names to the real charset names.")
+
+(defvar mm-binary-coding-system
+  (cond
+   ((mm-coding-system-p 'binary) 'binary)
+   ((mm-coding-system-p 'no-conversion) 'no-conversion)
+   (t nil))
+  "100% binary coding system.")
+
+(defvar mm-text-coding-system
+  (or (if (memq system-type '(windows-nt ms-dos ms-windows))
+         (and (mm-coding-system-p 'raw-text-dos) 'raw-text-dos)
+       (and (mm-coding-system-p 'raw-text) 'raw-text))
+      mm-binary-coding-system)
+  "Text-safe coding system (For removing ^M).")
+
+(defvar mm-text-coding-system-for-write nil
+  "Text coding system for write.")
+
+(defvar mm-auto-save-coding-system
+  (cond
+   ((mm-coding-system-p 'utf-8-emacs)  ; Mule 7
+    (if (memq system-type '(windows-nt ms-dos ms-windows))
+       (if (mm-coding-system-p 'utf-8-emacs-dos)
+           'utf-8-emacs-dos mm-binary-coding-system)
+      'utf-8-emacs))
+   ((mm-coding-system-p 'emacs-mule)
+    (if (memq system-type '(windows-nt ms-dos ms-windows))
+       (if (mm-coding-system-p 'emacs-mule-dos)
+           'emacs-mule-dos mm-binary-coding-system)
+      'emacs-mule))
+   ((mm-coding-system-p 'escape-quoted) 'escape-quoted)
+   (t mm-binary-coding-system))
+  "Coding system of auto save file.")
+
+(defvar mm-universal-coding-system mm-auto-save-coding-system
+  "The universal coding system.")
+
+;; Fixme: some of the cars here aren't valid MIME charsets.  That
+;; should only matter with XEmacs, though.
+(defvar mm-mime-mule-charset-alist
+  `((us-ascii ascii)
+    (iso-8859-1 latin-iso8859-1)
+    (iso-8859-2 latin-iso8859-2)
+    (iso-8859-3 latin-iso8859-3)
+    (iso-8859-4 latin-iso8859-4)
+    (iso-8859-5 cyrillic-iso8859-5)
+    ;; Non-mule (X)Emacs uses the last mule-charset for 8bit characters.
+    ;; The fake mule-charset, gnus-koi8-r, tells Gnus that the default
+    ;; charset is koi8-r, not iso-8859-5.
+    (koi8-r cyrillic-iso8859-5 gnus-koi8-r)
+    (iso-8859-6 arabic-iso8859-6)
+    (iso-8859-7 greek-iso8859-7)
+    (iso-8859-8 hebrew-iso8859-8)
+    (iso-8859-9 latin-iso8859-9)
+    (iso-8859-14 latin-iso8859-14)
+    (iso-8859-15 latin-iso8859-15)
+    (viscii vietnamese-viscii-lower)
+    (iso-2022-jp latin-jisx0201 japanese-jisx0208 japanese-jisx0208-1978)
+    (euc-kr korean-ksc5601)
+    (gb2312 chinese-gb2312)
+    (big5 chinese-big5-1 chinese-big5-2)
+    (tibetan tibetan)
+    (thai-tis620 thai-tis620)
+    (iso-2022-7bit ethiopic arabic-1-column arabic-2-column)
+    (iso-2022-jp-2 latin-iso8859-1 greek-iso8859-7
+                  latin-jisx0201 japanese-jisx0208-1978
+                  chinese-gb2312 japanese-jisx0208
+                  korean-ksc5601 japanese-jisx0212
+                  katakana-jisx0201)
+    (iso-2022-int-1 latin-iso8859-1 greek-iso8859-7
+                   latin-jisx0201 japanese-jisx0208-1978
+                   chinese-gb2312 japanese-jisx0208
+                   korean-ksc5601 japanese-jisx0212
+                   chinese-cns11643-1 chinese-cns11643-2)
+    (iso-2022-int-1 latin-iso8859-1 latin-iso8859-2
+                   cyrillic-iso8859-5 greek-iso8859-7
+                   latin-jisx0201 japanese-jisx0208-1978
+                   chinese-gb2312 japanese-jisx0208
+                   korean-ksc5601 japanese-jisx0212
+                   chinese-cns11643-1 chinese-cns11643-2
+                   chinese-cns11643-3 chinese-cns11643-4
+                   chinese-cns11643-5 chinese-cns11643-6
+                   chinese-cns11643-7)
+    ,(if (or (not (fboundp 'charsetp)) ;; non-Mule case
+            (charsetp 'unicode-a)
+            (not (mm-coding-system-p 'mule-utf-8)))
+        '(utf-8 unicode-a unicode-b unicode-c unicode-d unicode-e)
+       ;; If we have utf-8 we're in Mule 5+.
+       (append '(utf-8)
+              (delete 'ascii
+                      (coding-system-get 'mule-utf-8 'safe-charsets)))))
+  "Alist of MIME-charset/MULE-charsets.")
+
+;; Correct by construction, but should be unnecessary:
+;; XEmacs hates it.
+(when (and (not (featurep 'xemacs))
+          (fboundp 'coding-system-list)
+          (fboundp 'sort-coding-systems))
+  (setq mm-mime-mule-charset-alist
+       (apply
+        'nconc
+        (mapcar
+         (lambda (cs)
+           (when (and (or (coding-system-get cs :mime-charset) ; Emacs 22
+                          (coding-system-get cs 'mime-charset))
+                      (not (eq t (coding-system-get cs 'safe-charsets))))
+             (list (cons (or (coding-system-get cs :mime-charset)
+                             (coding-system-get cs 'mime-charset))
+                         (delq 'ascii
+                               (coding-system-get cs 'safe-charsets))))))
+         (sort-coding-systems (coding-system-list 'base-only))))))
+
+(defvar mm-hack-charsets '(iso-8859-15 iso-2022-jp-2)
+  "A list of special charsets.
+Valid elements include:
+`iso-8859-15'    convert ISO-8859-1, -9 to ISO-8859-15 if ISO-8859-15 exists.
+`iso-2022-jp-2'  convert ISO-2022-jp to ISO-2022-jp-2 if ISO-2022-jp-2 exists."
+)
+
+(defvar mm-iso-8859-15-compatible
+  '((iso-8859-1 "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE")
+    (iso-8859-9 "\xA4\xA6\xA8\xB4\xB8\xBC\xBD\xBE\xD0\xDD\xDE\xF0\xFD\xFE"))
+  "ISO-8859-15 exchangeable coding systems and inconvertible characters.")
+
+(defvar mm-iso-8859-x-to-15-table
+  (and (fboundp 'coding-system-p)
+       (mm-coding-system-p 'iso-8859-15)
+       (mapcar
+       (lambda (cs)
+         (if (mm-coding-system-p (car cs))
+             (let ((c (string-to-char
+                       (decode-coding-string "\341" (car cs)))))
+               (cons (char-charset c)
+                     (cons
+                      (- (string-to-char
+                          (decode-coding-string "\341" 'iso-8859-15)) c)
+                      (string-to-list (decode-coding-string (car (cdr cs))
+                                                            (car cs))))))
+           '(gnus-charset 0)))
+       mm-iso-8859-15-compatible))
+  "A table of the difference character between ISO-8859-X and ISO-8859-15.")
+
+(defcustom mm-coding-system-priorities
+  (if (boundp 'current-language-environment)
+      (let ((lang (symbol-value 'current-language-environment)))
+       (cond ((string= lang "Japanese")
+              ;; Japanese users may prefer iso-2022-jp to shift-jis.
+              '(iso-2022-jp iso-2022-jp-2 japanese-shift-jis
+                            iso-latin-1 utf-8)))))
+  "Preferred coding systems for encoding outgoing messages.
+
+More than one suitable coding system may be found for some text.
+By default, the coding system with the highest priority is used
+to encode outgoing messages (see `sort-coding-systems').  If this
+variable is set, it overrides the default priority."
+  :type '(repeat (symbol :tag "Coding system"))
+  :group 'mime)
+
+;; ??
+(defvar mm-use-find-coding-systems-region
+  (fboundp 'find-coding-systems-region)
+  "Use `find-coding-systems-region' to find proper coding systems.
+
+Setting it to nil is useful on Emacsen supporting Unicode if sending
+mail with multiple parts is preferred to sending a Unicode one.")
+
+;;; Internal variables:
+
+;;; Functions:
+
+(defun mm-mule-charset-to-mime-charset (charset)
+  "Return the MIME charset corresponding to the given Mule CHARSET."
+  (if (and (fboundp 'find-coding-systems-for-charsets)
+          (fboundp 'sort-coding-systems))
+      (let (mime)
+       (dolist (cs (sort-coding-systems
+                    (copy-sequence
+                     (find-coding-systems-for-charsets (list charset)))))
+         (unless mime
+           (when cs
+             (setq mime (or (coding-system-get cs :mime-charset)
+                            (coding-system-get cs 'mime-charset))))))
+       mime)
+    (let ((alist mm-mime-mule-charset-alist)
+         out)
+      (while alist
+       (when (memq charset (cdar alist))
+         (setq out (caar alist)
+               alist nil))
+       (pop alist))
+      out)))
+
+(defun mm-charset-to-coding-system (charset &optional lbt)
+  "Return coding-system corresponding to CHARSET.
+CHARSET is a symbol naming a MIME charset.
+If optional argument LBT (`unix', `dos' or `mac') is specified, it is
+used as the line break code type of the coding system."
+  (when (stringp charset)
+    (setq charset (intern (downcase charset))))
+  (when lbt
+    (setq charset (intern (format "%s-%s" charset lbt))))
+  (cond
+   ((null charset)
+    charset)
+   ;; Running in a non-MULE environment.
+   ((or (null (mm-get-coding-system-list))
+       (not (fboundp 'coding-system-get)))
+    charset)
+   ;; ascii
+   ((eq charset 'us-ascii)
+    'ascii)
+   ;; Check to see whether we can handle this charset.  (This depends
+   ;; on there being some coding system matching each `mime-charset'
+   ;; property defined, as there should be.)
+   ((and (mm-coding-system-p charset)
+;;; Doing this would potentially weed out incorrect charsets.
+;;;     charset
+;;;     (eq charset (coding-system-get charset 'mime-charset))
+        )
+    charset)
+   ;; Translate invalid charsets.
+   ((let ((cs (cdr (assq charset mm-charset-synonym-alist))))
+      (and cs (mm-coding-system-p cs) cs)))
+   ;; Last resort: search the coding system list for entries which
+   ;; have the right mime-charset in case the canonical name isn't
+   ;; defined (though it should be).
+   ((let (cs)
+      ;; mm-get-coding-system-list returns a list of cs without lbt.
+      ;; Do we need -lbt?
+      (dolist (c (mm-get-coding-system-list))
+       (if (and (null cs)
+                (eq charset (or (coding-system-get c :mime-charset)
+                                (coding-system-get c 'mime-charset))))
+           (setq cs c)))
+      cs))))
+
+(defsubst mm-replace-chars-in-string (string from to)
+  (mm-subst-char-in-string from to string))
+
+(eval-and-compile
+  (defvar mm-emacs-mule (and (not (featurep 'xemacs))
+                            (boundp 'default-enable-multibyte-characters)
+                            default-enable-multibyte-characters
+                            (fboundp 'set-buffer-multibyte))
+    "True in Emacs with Mule.")
+
+  (if mm-emacs-mule
+      (defun mm-enable-multibyte ()
+       "Set the multibyte flag of the current buffer.
+Only do this if the default value of `enable-multibyte-characters' is
+non-nil.  This is a no-op in XEmacs."
+       (set-buffer-multibyte 'to))
+    (defalias 'mm-enable-multibyte 'ignore))
+
+  (if mm-emacs-mule
+      (defun mm-disable-multibyte ()
+       "Unset the multibyte flag of in the current buffer.
+This is a no-op in XEmacs."
+       (set-buffer-multibyte nil))
+    (defalias 'mm-disable-multibyte 'ignore)))
+
+(defun mm-preferred-coding-system (charset)
+  ;; A typo in some Emacs versions.
+  (or (get-charset-property charset 'preferred-coding-system)
+      (get-charset-property charset 'prefered-coding-system)))
+
+;; Mule charsets shouldn't be used.
+(defsubst mm-guess-charset ()
+  "Guess Mule charset from the language environment."
+  (or
+   mail-parse-mule-charset ;; cached mule-charset
+   (progn
+     (setq mail-parse-mule-charset
+          (and (boundp 'current-language-environment)
+               (car (last
+                     (assq 'charset
+                           (assoc current-language-environment
+                                  language-info-alist))))))
+     (if (or (not mail-parse-mule-charset)
+            (eq mail-parse-mule-charset 'ascii))
+        (setq mail-parse-mule-charset
+              (or (car (last (assq mail-parse-charset
+                                   mm-mime-mule-charset-alist)))
+                  ;; default
+                  'latin-iso8859-1)))
+     mail-parse-mule-charset)))
+
+(defun mm-charset-after (&optional pos)
+  "Return charset of a character in current buffer at position POS.
+If POS is nil, it defauls to the current point.
+If POS is out of range, the value is nil.
+If the charset is `composition', return the actual one."
+  (let ((char (char-after pos)) charset)
+    (if (< (mm-char-int char) 128)
+       (setq charset 'ascii)
+      ;; charset-after is fake in some Emacsen.
+      (setq charset (and (fboundp 'char-charset) (char-charset char)))
+      (if (eq charset 'composition)    ; Mule 4
+         (let ((p (or pos (point))))
+           (cadr (find-charset-region p (1+ p))))
+       (if (and charset (not (memq charset '(ascii eight-bit-control
+                                                   eight-bit-graphic))))
+           charset
+         (mm-guess-charset))))))
+
+(defun mm-mime-charset (charset)
+  "Return the MIME charset corresponding to the given Mule CHARSET."
+  (if (eq charset 'unknown)
+      (error "The message contains non-printable characters, please use attachment"))
+  (if (and (fboundp 'coding-system-get) (fboundp 'get-charset-property))
+      ;; This exists in Emacs 20.
+      (or
+       (and (mm-preferred-coding-system charset)
+           (or (coding-system-get
+                (mm-preferred-coding-system charset) :mime-charset)
+               (coding-system-get
+                (mm-preferred-coding-system charset) 'mime-charset)))
+       (and (eq charset 'ascii)
+           'us-ascii)
+       (mm-preferred-coding-system charset)
+       (mm-mule-charset-to-mime-charset charset))
+    ;; This is for XEmacs.
+    (mm-mule-charset-to-mime-charset charset)))
+
+(defun mm-delete-duplicates (list)
+  "Simple substitute for CL `delete-duplicates', testing with `equal'."
+  (let (result head)
+    (while list
+      (setq head (car list))
+      (setq list (delete head list))
+      (setq result (cons head result)))
+    (nreverse result)))
+
+;; Fixme:  This is used in places when it should be testing the
+;; default multibyteness.  See mm-default-multibyte-p.
+(eval-and-compile
+  (if (and (not (featurep 'xemacs))
+          (boundp 'enable-multibyte-characters))
+      (defun mm-multibyte-p ()
+       "Non-nil if multibyte is enabled in the current buffer."
+       enable-multibyte-characters)
+    (defun mm-multibyte-p () (featurep 'mule))))
+
+(defun mm-default-multibyte-p ()
+  "Return non-nil if the session is multibyte.
+This affects whether coding conversion should be attempted generally."
+  (if (featurep 'mule)
+      (if (boundp 'default-enable-multibyte-characters)
+         default-enable-multibyte-characters
+       t)))
+
+(defun mm-iso-8859-x-to-15-region (&optional b e)
+  (if (fboundp 'char-charset)
+      (let (charset item c inconvertible)
+       (save-restriction
+         (if e (narrow-to-region b e))
+         (goto-char (point-min))
+         (skip-chars-forward "\0-\177")
+         (while (not (eobp))
+           (cond
+            ((not (setq item (assq (char-charset (setq c (char-after)))
+                                   mm-iso-8859-x-to-15-table)))
+             (forward-char))
+            ((memq c (cdr (cdr item)))
+             (setq inconvertible t)
+             (forward-char))
+            (t
+             (insert-before-markers (prog1 (+ c (car (cdr item)))
+                                      (delete-char 1)))))
+           (skip-chars-forward "\0-\177")))
+       (not inconvertible))))
+
+(defun mm-sort-coding-systems-predicate (a b)
+  (let ((priorities
+        (mapcar (lambda (cs)
+                  ;; Note: invalid entries are dropped silently
+                  (and (coding-system-p cs)
+                       (coding-system-base cs)))
+                mm-coding-system-priorities)))
+    (> (length (memq a priorities))
+       (length (memq b priorities)))))
+
+(defun mm-find-mime-charset-region (b e &optional hack-charsets)
+  "Return the MIME charsets needed to encode the region between B and E.
+nil means ASCII, a single-element list represents an appropriate MIME
+charset, and a longer list means no appropriate charset."
+  (let (charsets)
+    ;; The return possibilities of this function are a mess...
+    (or (and (mm-multibyte-p)
+            mm-use-find-coding-systems-region
+            ;; Find the mime-charset of the most preferred coding
+            ;; system that has one.
+            (let ((systems (find-coding-systems-region b e)))
+              (when mm-coding-system-priorities
+                (setq systems
+                      (sort systems 'mm-sort-coding-systems-predicate)))
+              (setq systems (delq 'compound-text systems))
+              (unless (equal systems '(undecided))
+                (while systems
+                  (let* ((head (pop systems))
+                         (cs (or (coding-system-get head :mime-charset)
+                                 (coding-system-get head 'mime-charset))))
+                    ;; The mime-charset (`x-ctext') of
+                    ;; `compound-text' is not in the IANA list.  We
+                    ;; shouldn't normally use anything here with a
+                    ;; mime-charset having an `x-' prefix.
+                    ;; Fixme:  Allow this to be overridden, since
+                    ;; there is existing use of x-ctext.
+                    ;; Also people apparently need the coding system
+                    ;; `iso-2022-jp-3' (which Mule-UCS defines with
+                    ;; mime-charset, though it's not valid).
+                    (if (and cs
+                             (not (string-match "^[Xx]-" (symbol-name cs)))
+                             ;; UTF-16 of any variety is invalid for
+                             ;; text parts and, unfortunately, has
+                             ;; mime-charset defined both in Mule-UCS
+                             ;; and versions of Emacs.  (The name
+                             ;; might be `mule-utf-16...'  or
+                             ;; `utf-16...'.)
+                             (not (string-match "utf-16" (symbol-name cs))))
+                        (setq systems nil
+                              charsets (list cs))))))
+              charsets))
+       ;; Otherwise we're not multibyte, we're XEmacs, or a single
+       ;; coding system won't cover it.
+       (setq charsets
+             (mm-delete-duplicates
+              (mapcar 'mm-mime-charset
+                      (delq 'ascii
+                            (mm-find-charset-region b e))))))
+    (if (and (> (length charsets) 1)
+            (memq 'iso-8859-15 charsets)
+            (memq 'iso-8859-15 hack-charsets)
+            (save-excursion (mm-iso-8859-x-to-15-region b e)))
+       (mapcar (lambda (x) (setq charsets (delq (car x) charsets)))
+               mm-iso-8859-15-compatible))
+    (if (and (memq 'iso-2022-jp-2 charsets)
+            (memq 'iso-2022-jp-2 hack-charsets))
+       (setq charsets (delq 'iso-2022-jp charsets)))
+    charsets))
+
+(defmacro mm-with-unibyte-buffer (&rest forms)
+  "Create a temporary buffer, and evaluate FORMS there like `progn'.
+Use unibyte mode for this."
+  `(let (default-enable-multibyte-characters)
+     (with-temp-buffer ,@forms)))
+(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 with current buffer temporarily made unibyte.
+Also bind `default-enable-multibyte-characters' to nil.
+Equivalent to `progn' in XEmacs"
+  (let ((multibyte (make-symbol "multibyte"))
+       (buffer (make-symbol "buffer")))
+    `(if mm-emacs-mule
+        (let ((,multibyte enable-multibyte-characters)
+              (,buffer (current-buffer)))
+          (unwind-protect
+              (let (default-enable-multibyte-characters)
+                (set-buffer-multibyte nil)
+                ,@forms)
+            (set-buffer ,buffer)
+            (set-buffer-multibyte ,multibyte)))
+       (let (default-enable-multibyte-characters)
+        ,@forms))))
+(put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0)
+(put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body))
+
+(defmacro mm-with-unibyte (&rest forms)
+  "Eval the FORMS with the default value of `enable-multibyte-characters' nil, ."
+  `(let (default-enable-multibyte-characters)
+     ,@forms))
+(put 'mm-with-unibyte 'lisp-indent-function 0)
+(put 'mm-with-unibyte 'edebug-form-spec '(body))
+
+(defun mm-find-charset-region (b e)
+  "Return a list of Emacs charsets in the region B to E."
+  (cond
+   ((and (mm-multibyte-p)
+        (fboundp 'find-charset-region))
+    ;; Remove composition since the base charsets have been included.
+    ;; Remove eight-bit-*, treat them as ascii.
+    (let ((css (find-charset-region b e)))
+      (mapcar (lambda (cs) (setq css (delq cs css)))
+             '(composition eight-bit-control eight-bit-graphic
+                           control-1))
+      css))
+   (t
+    ;; We are in a unibyte buffer or XEmacs non-mule, so we futz around a bit.
+    (save-excursion
+      (save-restriction
+       (narrow-to-region b e)
+       (goto-char (point-min))
+       (skip-chars-forward "\0-\177")
+       (if (eobp)
+           '(ascii)
+         (let (charset)
+           (setq charset
+                 (and (boundp 'current-language-environment)
+                      (car (last (assq 'charset
+                                       (assoc current-language-environment
+                                              language-info-alist))))))
+           (if (eq charset 'ascii) (setq charset nil))
+           (or charset
+               (setq charset
+                     (car (last (assq mail-parse-charset
+                                      mm-mime-mule-charset-alist)))))
+           (list 'ascii (or charset 'latin-iso8859-1)))))))))
+
+(static-if (fboundp 'shell-quote-argument)
+    (defalias 'mm-quote-arg 'shell-quote-argument)
+  (defun mm-quote-arg (arg)
+    "Return a version of ARG that is safe to evaluate in a shell."
+    (let ((pos 0) new-pos accum)
+      ;; *** bug: we don't handle newline characters properly
+      (while (setq new-pos (string-match "[]*[;!'`\"$\\& \t{} |()<>]" arg pos))
+       (push (substring arg pos new-pos) accum)
+       (push "\\" accum)
+       (push (list (aref arg new-pos)) accum)
+       (setq pos (1+ new-pos)))
+      (if (= pos 0)
+         arg
+       (apply 'concat (nconc (nreverse accum) (list (substring arg pos))))))))
+
+(defun mm-auto-mode-alist ()
+  "Return an `auto-mode-alist' with only the .gz (etc) thingies."
+  (let ((alist auto-mode-alist)
+       out)
+    (while alist
+      (when (listp (cdar alist))
+       (push (car alist) out))
+      (pop alist))
+    (nreverse out)))
+
+(defvar mm-inhibit-file-name-handlers
+  '(jka-compr-handler image-file-handler)
+  "A list of handlers doing (un)compression (etc) thingies.")
+
+(defun mm-insert-file-contents (filename &optional visit beg end replace
+                                        inhibit)
+  "Like `insert-file-contents', but only reads in the file.
+A buffer may be modified in several ways after reading into the buffer due
+to advanced Emacs features, such as file-name-handlers, format decoding,
+`find-file-hooks', etc.
+If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'.
+  This function ensures that none of these modifications will take place."
+  (let ((format-alist nil)
+       (auto-mode-alist (if inhibit nil (mm-auto-mode-alist)))
+       (default-major-mode 'fundamental-mode)
+       (enable-local-variables nil)
+       (after-insert-file-functions nil)
+       (enable-local-eval nil)
+       (find-file-hooks nil)
+       (inhibit-file-name-operation (if inhibit
+                                        'insert-file-contents
+                                      inhibit-file-name-operation))
+       (inhibit-file-name-handlers
+        (if inhibit
+            (append mm-inhibit-file-name-handlers
+                    inhibit-file-name-handlers)
+          inhibit-file-name-handlers)))
+    (insert-file-contents filename visit beg end replace)))
+
+(defun mm-append-to-file (start end filename &optional codesys inhibit)
+  "Append the contents of the region to the end of file FILENAME.
+When called from a function, expects three arguments,
+START, END and FILENAME.  START and END are buffer positions
+saying what text to write.
+Optional fourth argument specifies the coding system to use when
+encoding the file.
+If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'."
+  (let ((coding-system-for-write
+        (or codesys mm-text-coding-system-for-write
+            mm-text-coding-system))
+       (inhibit-file-name-operation (if inhibit
+                                        'append-to-file
+                                      inhibit-file-name-operation))
+       (inhibit-file-name-handlers
+        (if inhibit
+            (append mm-inhibit-file-name-handlers
+                    inhibit-file-name-handlers)
+          inhibit-file-name-handlers)))
+    (write-region start end filename t 'no-message)
+    (message "Appended to %s" filename)))
+
+(defun mm-write-region (start end filename &optional append visit lockname
+                             coding-system inhibit)
+
+  "Like `write-region'.
+If INHIBIT is non-nil, inhibit `mm-inhibit-file-name-handlers'."
+  (let ((coding-system-for-write
+        (or coding-system mm-text-coding-system-for-write
+            mm-text-coding-system))
+       (inhibit-file-name-operation (if inhibit
+                                        'write-region
+                                      inhibit-file-name-operation))
+       (inhibit-file-name-handlers
+        (if inhibit
+            (append mm-inhibit-file-name-handlers
+                    inhibit-file-name-handlers)
+          inhibit-file-name-handlers)))
+    (write-region start end filename append visit lockname)))
+
+(defun mm-image-load-path (&optional package)
+  (let (dir result)
+    (dolist (path load-path (nreverse result))
+      (if (file-directory-p
+          (setq dir (concat (file-name-directory
+                             (directory-file-name path))
+                            "etc/" (or package "gnus/"))))
+         (push dir result))
+      (push path result))))
+
+;; Fixme: This doesn't look useful where it's used.
+(if (fboundp 'detect-coding-region)
+    (defun mm-detect-coding-region (start end)
+      "Like `detect-coding-region' except returning the best one."
+      (let ((coding-systems
+            (detect-coding-region (point) (point-max))))
+       (or (car-safe coding-systems)
+           coding-systems)))
+  (defun mm-detect-coding-region (start end)
+    (let ((point (point)))
+      (goto-char start)
+      (skip-chars-forward "\0-\177" end)
+      (prog1
+         (if (eq (point) end) 'ascii (mm-guess-charset))
+       (goto-char point)))))
+
+(if (fboundp 'coding-system-get)
+    (defun mm-detect-mime-charset-region (start end)
+      "Detect MIME charset of the text in the region between START and END."
+      (let ((cs (mm-detect-coding-region start end)))
+       (coding-system-get cs 'mime-charset)))
+  (defun mm-detect-mime-charset-region (start end)
+    "Detect MIME charset of the text in the region between START and END."
+    (let ((cs (mm-detect-coding-region start end)))
+      cs)))
+
+
+(provide 'mm-util)
+
+;;; mm-util.el ends here
diff --git a/lisp/mm-uu.el b/lisp/mm-uu.el
new file mode 100644 (file)
index 0000000..269a787
--- /dev/null
@@ -0,0 +1,498 @@
+;;; mm-uu.el --- Return uu stuff as mm handles
+;; Copyright (c) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: postscript uudecode binhex shar forward gnatsweb pgp
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'mail-parse)
+(require 'nnheader)
+(require 'mm-decode)
+(require 'gnus-mailcap)
+(require 'mml2015)
+
+(autoload 'uudecode-decode-region "uudecode")
+(autoload 'uudecode-decode-region-external "uudecode")
+(autoload 'uudecode-decode-region-internal "uudecode")
+
+(autoload 'binhex-decode-region "binhex")
+(autoload 'binhex-decode-region-external "binhex")
+(autoload 'binhex-decode-region-internal "binhex")
+
+(autoload 'yenc-decode-region "yenc")
+(autoload 'yenc-extract-filename "yenc")
+
+(defcustom mm-uu-decode-function 'uudecode-decode-region
+  "*Function to uudecode.
+Internal function is done in Lisp by default, therefore decoding may
+appear to be horribly slow.  You can make Gnus use an external
+decoder, such as uudecode."
+  :type '(choice
+         (function-item :tag "Auto detect" uudecode-decode-region)
+         (function-item :tag "Internal" uudecode-decode-region-internal)
+         (function-item :tag "External" uudecode-decode-region-external))
+  :group 'gnus-article-mime)
+
+(defcustom mm-uu-binhex-decode-function 'binhex-decode-region
+  "*Function to binhex decode.
+Internal function is done in elisp by default, therefore decoding may
+appear to be horribly slow . You can make Gnus use the external Unix
+decoder, such as hexbin."
+  :type '(choice (function-item :tag "Auto detect" binhex-decode-region)
+                (function-item :tag "Internal" binhex-decode-region-internal)
+                (function-item :tag "External" binhex-decode-region-external))
+  :group 'gnus-article-mime)
+
+(defvar mm-uu-yenc-decode-function 'yenc-decode-region)
+
+(defvar mm-uu-pgp-beginning-signature
+  "^-----BEGIN PGP SIGNATURE-----")
+
+(defvar mm-uu-beginning-regexp nil)
+
+(defvar mm-dissect-disposition "inline"
+  "The default disposition of uu parts.
+This can be either \"inline\" or \"attachment\".")
+
+(defvar mm-uu-emacs-sources-regexp "gnu\\.emacs\\.sources"
+  "The regexp of Emacs sources groups.")
+
+(defcustom mm-uu-diff-groups-regexp "gnus\\.commits"
+  "*Regexp matching diff groups."
+  :type 'regexp
+  :group 'gnus-article-mime)
+
+(defvar mm-uu-type-alist
+  '((postscript
+     "^%!PS-"
+     "^%%EOF$"
+     mm-uu-postscript-extract
+     nil)
+    (uu
+     "^begin[ \t]+0?[0-7][0-7][0-7][ \t]+"
+     "^end[ \t]*$"
+     mm-uu-uu-extract
+     mm-uu-uu-filename)
+    (binhex
+     "^:...............................................................$"
+     ":$"
+     mm-uu-binhex-extract
+     nil
+     mm-uu-binhex-filename)
+    (yenc
+     "^=ybegin.*size=[0-9]+.*name=.*$"
+     "^=yend.*size=[0-9]+"
+     mm-uu-yenc-extract
+     mm-uu-yenc-filename)
+    (shar
+     "^#! */bin/sh"
+     "^exit 0$"
+     mm-uu-shar-extract)
+    (forward
+;;; Thanks to Edward J. Sabol <sabol@alderaan.gsfc.nasa.gov> and
+;;; Peter von der Ah\'e <pahe@daimi.au.dk>
+     "^-+ \\(Start of \\)?Forwarded message"
+     "^-+ End \\(of \\)?forwarded message"
+     mm-uu-forward-extract
+     nil
+     mm-uu-forward-test)
+    (gnatsweb
+     "^----gnatsweb-attachment----"
+     nil
+     mm-uu-gnatsweb-extract)
+    (pgp-signed
+     "^-----BEGIN PGP SIGNED MESSAGE-----"
+     "^-----END PGP SIGNATURE-----"
+     mm-uu-pgp-signed-extract
+     nil
+     nil)
+    (pgp-encrypted
+     "^-----BEGIN PGP MESSAGE-----"
+     "^-----END PGP MESSAGE-----"
+     mm-uu-pgp-encrypted-extract
+     nil
+     nil)
+    (pgp-key
+     "^-----BEGIN PGP PUBLIC KEY BLOCK-----"
+     "^-----END PGP PUBLIC KEY BLOCK-----"
+     mm-uu-pgp-key-extract
+     mm-uu-gpg-key-skip-to-last
+     nil)
+    (emacs-sources
+     "^;;;?[ \t]*[^ \t]+\\.el[ \t]*--"
+     "^;;;?[ \t]*\\([^ \t]+\\.el\\)[ \t]+ends here"
+     mm-uu-emacs-sources-extract
+     nil
+     mm-uu-emacs-sources-test)
+    (diff
+     "^Index: "
+     nil
+     mm-uu-diff-extract
+     nil
+     mm-uu-diff-test)))
+
+(defcustom mm-uu-configure-list '((shar . disabled))
+  "A list of mm-uu configuration.
+To disable dissecting shar codes, for instance, add
+`(shar . disabled)' to this list."
+  :type 'alist
+  :options (mapcar (lambda (entry)
+                    (list (car entry) '(const disabled)))
+                  mm-uu-type-alist)
+  :group 'gnus-article-mime)
+
+;; functions
+
+(defsubst mm-uu-type (entry)
+  (car entry))
+
+(defsubst mm-uu-beginning-regexp (entry)
+  (nth 1 entry))
+
+(defsubst mm-uu-end-regexp (entry)
+  (nth 2 entry))
+
+(defsubst mm-uu-function-extract (entry)
+  (nth 3 entry))
+
+(defsubst mm-uu-function-1 (entry)
+  (nth 4 entry))
+
+(defsubst mm-uu-function-2 (entry)
+  (nth 5 entry))
+
+(defun mm-uu-copy-to-buffer (&optional from to)
+  "Copy the contents of the current buffer to a fresh buffer.
+Return that buffer."
+  (save-excursion
+    (let ((obuf (current-buffer))
+         (coding-system
+          ;; Might not exist in non-MULE XEmacs
+          (when (boundp 'buffer-file-coding-system)
+            buffer-file-coding-system)))
+      (set-buffer (generate-new-buffer " *mm-uu*"))
+      (setq buffer-file-coding-system coding-system)
+      (insert-buffer-substring obuf from to)
+      (current-buffer))))
+
+(defun mm-uu-configure-p  (key val)
+  (member (cons key val) mm-uu-configure-list))
+
+(defun mm-uu-configure (&optional symbol value)
+  (if symbol (set-default symbol value))
+  (setq mm-uu-beginning-regexp nil)
+  (mapcar (lambda (entry)
+           (if (mm-uu-configure-p (mm-uu-type entry) 'disabled)
+               nil
+             (setq mm-uu-beginning-regexp
+                   (concat mm-uu-beginning-regexp
+                           (if mm-uu-beginning-regexp "\\|")
+                           (mm-uu-beginning-regexp entry)))))
+         mm-uu-type-alist))
+
+(mm-uu-configure)
+
+(eval-when-compile
+  (defvar file-name)
+  (defvar start-point)
+  (defvar end-point)
+  (defvar entry))
+
+(defun mm-uu-uu-filename ()
+  (if (looking-at ".+")
+      (setq file-name
+           (let ((nnheader-file-name-translation-alist
+                  '((?/ . ?,) (?\  . ?_) (?* . ?_) (?$ . ?_))))
+             (nnheader-translate-file-chars (match-string 0))))))
+
+(defun mm-uu-binhex-filename ()
+  (setq file-name
+       (ignore-errors
+         (binhex-decode-region start-point end-point t))))
+
+(defun mm-uu-yenc-filename ()
+  (goto-char start-point)
+  (setq file-name
+       (ignore-errors
+         (yenc-extract-filename))))
+
+(defun mm-uu-forward-test ()
+  (save-excursion
+    (goto-char start-point)
+    (forward-line)
+    (looking-at "[\r\n]*[a-zA-Z][a-zA-Z0-9-]*:")))
+
+(defun mm-uu-postscript-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 '("application/postscript")))
+
+(defun mm-uu-emacs-sources-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 '("application/emacs-lisp")
+                 nil nil
+                 (list mm-dissect-disposition
+                       (cons 'filename file-name))))
+
+(eval-when-compile
+  (defvar gnus-newsgroup-name))
+
+(defun mm-uu-emacs-sources-test ()
+  (setq file-name (match-string 1))
+  (and gnus-newsgroup-name
+       mm-uu-emacs-sources-regexp
+       (string-match mm-uu-emacs-sources-regexp gnus-newsgroup-name)))
+
+(defun mm-uu-diff-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 '("text/x-patch")))
+
+(defun mm-uu-diff-test ()
+  (and gnus-newsgroup-name
+       mm-uu-diff-groups-regexp
+       (string-match mm-uu-diff-groups-regexp gnus-newsgroup-name)))
+
+(defun mm-uu-forward-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer
+                  (progn (goto-char start-point) (forward-line) (point))
+                  (progn (goto-char end-point) (forward-line -1) (point)))
+                 '("message/rfc822" (charset . gnus-decoded))))
+
+(defun mm-uu-uu-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 (list (or (and file-name
+                                (string-match "\\.[^\\.]+$"
+                                              file-name)
+                                (mailcap-extension-to-mime
+                                 (match-string 0 file-name)))
+                           "application/octet-stream"))
+                 'x-uuencode nil
+                 (if (and file-name (not (equal file-name "")))
+                     (list mm-dissect-disposition
+                           (cons 'filename file-name)))))
+
+(defun mm-uu-binhex-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 (list (or (and file-name
+                                (string-match "\\.[^\\.]+$" file-name)
+                                (mailcap-extension-to-mime
+                                 (match-string 0 file-name)))
+                           "application/octet-stream"))
+                 'x-binhex nil
+                 (if (and file-name (not (equal file-name "")))
+                     (list mm-dissect-disposition
+                           (cons 'filename file-name)))))
+
+(defun mm-uu-yenc-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 (list (or (and file-name
+                                (string-match "\\.[^\\.]+$" file-name)
+                                (mailcap-extension-to-mime
+                                 (match-string 0 file-name)))
+                           "application/octet-stream"))
+                 'x-yenc nil
+                 (if (and file-name (not (equal file-name "")))
+                     (list mm-dissect-disposition
+                           (cons 'filename file-name)))))
+
+
+(defun mm-uu-shar-extract ()
+  (mm-make-handle (mm-uu-copy-to-buffer start-point end-point)
+                 '("application/x-shar")))
+
+(defun mm-uu-gnatsweb-extract ()
+  (save-restriction
+    (goto-char start-point)
+    (forward-line)
+    (narrow-to-region (point) end-point)
+    (mm-dissect-buffer t)))
+
+(defun mm-uu-pgp-signed-test (&rest rest)
+  (and
+   mml2015-use
+   (mml2015-clear-verify-function)
+   (cond
+    ((eq mm-verify-option 'never) nil)
+    ((eq mm-verify-option 'always) t)
+    ((eq mm-verify-option 'known) t)
+    (t (y-or-n-p "Verify pgp signed part? ")))))
+
+(eval-when-compile
+  (defvar gnus-newsgroup-charset))
+
+(defun mm-uu-pgp-signed-extract-1 (handles ctl)
+  (let ((buf (mm-uu-copy-to-buffer (point-min) (point-max))))
+    (with-current-buffer buf
+      (if (mm-uu-pgp-signed-test)
+         (progn
+           (mml2015-clean-buffer)
+           (let ((coding-system-for-write (or gnus-newsgroup-charset
+                                              'iso-8859-1)))
+             (funcall (mml2015-clear-verify-function))))
+       (when (and mml2015-use (null (mml2015-clear-verify-function)))
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-details
+          (format "Clear verification not supported by `%s'.\n" mml2015-use))))
+      (goto-char (point-min))
+      (if (search-forward "\n\n" nil t)
+         (delete-region (point-min) (point)))
+      (if (re-search-forward mm-uu-pgp-beginning-signature nil t)
+         (delete-region (match-beginning 0) (point-max)))
+      (goto-char (point-min))
+      (while (re-search-forward "^- " nil t)
+       (replace-match "" t t)
+       (forward-line 1)))
+    (list (mm-make-handle buf '("text/plain" (charset . gnus-decoded))))))
+
+(defun mm-uu-pgp-signed-extract ()
+  (let ((mm-security-handle (list (format "multipart/signed"))))
+    (mm-set-handle-multipart-parameter
+     mm-security-handle 'protocol "application/x-gnus-pgp-signature")
+    (save-restriction
+      (narrow-to-region start-point end-point)
+      (add-text-properties 0 (length (car mm-security-handle))
+                          (list 'buffer (mm-uu-copy-to-buffer))
+                          (car mm-security-handle))
+      (setcdr mm-security-handle
+             (mm-uu-pgp-signed-extract-1 nil
+                                         mm-security-handle)))
+    mm-security-handle))
+
+(defun mm-uu-pgp-encrypted-test (&rest rest)
+  (and
+   mml2015-use
+   (mml2015-clear-decrypt-function)
+   (cond
+    ((eq mm-decrypt-option 'never) nil)
+    ((eq mm-decrypt-option 'always) t)
+    ((eq mm-decrypt-option 'known) t)
+    (t (y-or-n-p "Decrypt pgp encrypted part? ")))))
+
+(defun mm-uu-pgp-encrypted-extract-1 (handles ctl)
+  (let ((buf (mm-uu-copy-to-buffer (point-min) (point-max))))
+    (if (mm-uu-pgp-encrypted-test)
+       (with-current-buffer buf
+         (mml2015-clean-buffer)
+         (funcall (mml2015-clear-decrypt-function))))
+    (list
+     (mm-make-handle buf
+                    '("text/plain"  (charset . gnus-decoded))))))
+
+(defun mm-uu-pgp-encrypted-extract ()
+  (let ((mm-security-handle (list (format "multipart/encrypted"))))
+    (mm-set-handle-multipart-parameter
+     mm-security-handle 'protocol "application/x-gnus-pgp-encrypted")
+    (save-restriction
+      (narrow-to-region start-point end-point)
+      (add-text-properties 0 (length (car mm-security-handle))
+                          (list 'buffer (mm-uu-copy-to-buffer))
+                          (car mm-security-handle))
+      (setcdr mm-security-handle
+             (mm-uu-pgp-encrypted-extract-1 nil
+                                            mm-security-handle)))
+    mm-security-handle))
+
+(defun mm-uu-gpg-key-skip-to-last ()
+  (let ((point (point))
+       (end-regexp (mm-uu-end-regexp entry))
+       (beginning-regexp (mm-uu-beginning-regexp entry)))
+    (when (and end-regexp
+              (not (mm-uu-configure-p (mm-uu-type entry) 'disabled)))
+      (while (re-search-forward end-regexp nil t)
+       (skip-chars-forward " \t\n\r")
+       (if (looking-at beginning-regexp)
+           (setq point (match-end 0)))))
+    (goto-char point)))
+
+(defun mm-uu-pgp-key-extract ()
+  (let ((buf (mm-uu-copy-to-buffer start-point end-point)))
+    (mm-make-handle buf
+                   '("application/pgp-keys"))))
+
+;;;###autoload
+(defun mm-uu-dissect ()
+  "Dissect the current buffer and return a list of uu handles."
+  (let ((case-fold-search t)
+       text-start start-point end-point file-name result
+       text-plain-type entry func)
+    (save-excursion
+      (goto-char (point-min))
+      (cond
+       ((looking-at "\n")
+       (forward-line))
+       ((search-forward "\n\n" nil t)
+       t)
+       (t (goto-char (point-max))))
+      ;;; gnus-decoded is a fake charset, which means no further
+      ;;; decoding.
+      (setq text-start (point)
+           text-plain-type '("text/plain"  (charset . gnus-decoded)))
+      (while (re-search-forward mm-uu-beginning-regexp nil t)
+       (setq start-point (match-beginning 0))
+       (let ((alist mm-uu-type-alist)
+             (beginning-regexp (match-string 0)))
+         (while (not entry)
+           (if (string-match (mm-uu-beginning-regexp (car alist))
+                             beginning-regexp)
+               (setq entry (car alist))
+             (pop alist))))
+       (if (setq func (mm-uu-function-1 entry))
+           (funcall func))
+       (forward-line);; in case of failure
+       (when (and (not (mm-uu-configure-p (mm-uu-type entry) 'disabled))
+                  (let ((end-regexp (mm-uu-end-regexp entry)))
+                    (if (not end-regexp)
+                        (or (setq end-point (point-max)) t)
+                      (prog1
+                          (re-search-forward end-regexp nil t)
+                        (forward-line)
+                        (setq end-point (point)))))
+                  (or (not (setq func (mm-uu-function-2 entry)))
+                      (funcall func)))
+         (if (and (> start-point text-start)
+                  (progn
+                    (goto-char text-start)
+                    (re-search-forward "." start-point t)))
+             (push
+              (mm-make-handle (mm-uu-copy-to-buffer text-start start-point)
+                              text-plain-type)
+              result))
+         (push
+          (funcall (mm-uu-function-extract entry))
+          result)
+         (goto-char (setq text-start end-point))))
+      (when result
+       (if (and (> (point-max) (1+ text-start))
+                (save-excursion
+                  (goto-char text-start)
+                  (re-search-forward "." nil t)))
+           (push
+            (mm-make-handle (mm-uu-copy-to-buffer text-start (point-max))
+                            text-plain-type)
+            result))
+       (setq result (cons "multipart/mixed" (nreverse result))))
+      result)))
+
+(provide 'mm-uu)
+
+;;; mm-uu.el ends here
diff --git a/lisp/mm-view.el b/lisp/mm-view.el
new file mode 100644 (file)
index 0000000..27a873f
--- /dev/null
@@ -0,0 +1,593 @@
+;;; mm-view.el --- functions for viewing MIME objects
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'mail-parse)
+(require 'gnus-mailcap)
+(require 'mm-bodies)
+(require 'mm-decode)
+
+(eval-and-compile
+  (autoload 'gnus-article-prepare-display "gnus-art")
+  (autoload 'vcard-parse-string "vcard")
+  (autoload 'vcard-format-string "vcard")
+  (autoload 'fill-flowed "flow-fill")
+  (autoload 'html2text "html2text")
+  (unless (fboundp 'diff-mode)
+    (autoload 'diff-mode "diff-mode" "" t nil)))
+
+(defvar mm-text-html-renderer-alist
+  '((w3  . mm-inline-text-html-render-with-w3)
+    (w3m . mm-inline-text-html-render-with-w3m)
+    (w3m-standalone mm-inline-render-with-stdin nil
+                   "w3m" "-dump" "-T" "text/html")
+    (links mm-inline-render-with-file
+          mm-links-remove-leading-blank
+          "links" "-dump" file)
+    (lynx  mm-inline-render-with-stdin nil
+          "lynx" "-dump" "-force_html" "-stdin" "-nolist")
+    (html2text  mm-inline-render-with-function html2text))
+  "The attributes of renderer types for text/html.")
+
+(defvar mm-text-html-washer-alist
+  '((w3  . gnus-article-wash-html-with-w3)
+    (w3m . gnus-article-wash-html-with-w3m)
+    (w3m-standalone mm-inline-wash-with-stdin nil
+                   "w3m" "-dump" "-T" "text/html")
+    (links mm-inline-wash-with-file
+          mm-links-remove-leading-blank
+          "links" "-dump" file)
+    (lynx  mm-inline-wash-with-stdin nil
+          "lynx" "-dump" "-force_html" "-stdin" "-nolist")
+    (html2text  html2text))
+  "The attributes of washer types for text/html.")
+
+;;; Internal variables.
+
+;;;
+;;; Functions for displaying various formats inline
+;;;
+
+(defun mm-inline-image-emacs (handle)
+  (let ((b (point-marker))
+       buffer-read-only)
+    (put-image (mm-get-image handle) b)
+    (insert "\n\n")
+    (mm-handle-set-undisplayer
+     handle
+     `(lambda ()
+       (let ((b ,b)
+             buffer-read-only)
+         (remove-images b b)
+         (delete-region b (+ b 2)))))))
+
+(defun mm-inline-image-xemacs (handle)
+  (insert "\n\n")
+  (forward-char -2)
+  (let ((annot (make-annotation (mm-get-image handle) nil 'text))
+       buffer-read-only)
+    (mm-handle-set-undisplayer
+     handle
+     `(lambda ()
+       (let ((b ,(point-marker))
+             buffer-read-only)
+         (delete-annotation ,annot)
+         (delete-region (- b 2) b))))
+    (set-extent-property annot 'mm t)
+    (set-extent-property annot 'duplicable t)))
+
+(eval-and-compile
+  (if (featurep 'xemacs)
+      (defalias 'mm-inline-image 'mm-inline-image-xemacs)
+    (defalias 'mm-inline-image 'mm-inline-image-emacs)))
+
+(defvar mm-w3-setup nil)
+(defun mm-setup-w3 ()
+  (unless mm-w3-setup
+    (require 'w3)
+    (w3-do-setup)
+    (require 'url)
+    (require 'w3-vars)
+    (require 'url-vars)
+    (setq mm-w3-setup t)))
+
+(defun mm-inline-text-html-render-with-w3 (handle)
+  (mm-setup-w3)
+  (let ((text (mm-get-part handle))
+       (b (point))
+       (url-standalone-mode t)
+       (url-gateway-unplugged t)
+       (w3-honor-stylesheets nil)
+       (url-current-object
+        (url-generic-parse-url (format "cid:%s" (mm-handle-id handle))))
+       (width (window-width))
+       (charset (mail-content-type-get
+                 (mm-handle-type handle) 'charset)))
+    (save-excursion
+      (insert text)
+      (save-restriction
+       (narrow-to-region b (point))
+       (goto-char (point-min))
+       (if (or (and (boundp 'w3-meta-content-type-charset-regexp)
+                    (re-search-forward
+                     w3-meta-content-type-charset-regexp nil t))
+               (and (boundp 'w3-meta-charset-content-type-regexp)
+                    (re-search-forward
+                     w3-meta-charset-content-type-regexp nil t)))
+           (setq charset
+                 (or (let ((bsubstr (buffer-substring-no-properties
+                                     (match-beginning 2)
+                                     (match-end 2))))
+                       (if (fboundp 'w3-coding-system-for-mime-charset)
+                           (w3-coding-system-for-mime-charset bsubstr)
+                         (mm-charset-to-coding-system bsubstr)))
+                     charset)))
+       (delete-region (point-min) (point-max))
+       (insert (mm-decode-string text charset))
+       (save-window-excursion
+         (save-restriction
+           (let ((w3-strict-width width)
+                 ;; Don't let w3 set the global version of
+                 ;; this variable.
+                 (fill-column fill-column))
+             (if (or debug-on-error debug-on-quit)
+                 (w3-region (point-min) (point-max))
+               (condition-case ()
+                   (w3-region (point-min) (point-max))
+                 (error
+                  (delete-region (point-min) (point-max))
+                  (let ((b (point))
+                        (charset (mail-content-type-get
+                                  (mm-handle-type handle) 'charset)))
+                    (if (or (eq charset 'gnus-decoded)
+                            (eq mail-parse-charset 'gnus-decoded))
+                      (save-restriction
+                        (narrow-to-region (point) (point))
+                        (mm-insert-part handle)
+                        (goto-char (point-max)))
+                      (insert (mm-decode-string (mm-get-part handle)
+                                                charset))))
+                  (message
+                   "Error while rendering html; showing as text/plain")))))))
+       (mm-handle-set-undisplayer
+        handle
+        `(lambda ()
+           (let (buffer-read-only)
+             (if (functionp 'remove-specifier)
+                 (mapcar (lambda (prop)
+                           (remove-specifier
+                            (face-property 'default prop)
+                            (current-buffer)))
+                         '(background background-pixmap foreground)))
+             (delete-region ,(point-min-marker)
+                            ,(point-max-marker)))))))))
+
+(defvar mm-w3m-setup nil
+  "Whether gnus-article-mode has been setup to use emacs-w3m.")
+
+(defun mm-setup-w3m ()
+  "Setup gnus-article-mode to use emacs-w3m."
+  (unless mm-w3m-setup
+    (require 'w3m)
+    (unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist)
+      (push (cons 'gnus-article-mode 'mm-w3m-cid-retrieve)
+           w3m-cid-retrieve-function-alist))
+    (setq mm-w3m-setup t))
+  (setq w3m-display-inline-images mm-inline-text-html-with-images))
+
+(defun mm-w3m-cid-retrieve-1 (url handle)
+  (dolist (elem handle)
+    (when (and (listp elem)
+              (equal url (mm-handle-id elem)))
+      (mm-insert-part elem)
+      (throw 'found-handle (mm-handle-media-type elem)))))
+
+(defun mm-w3m-cid-retrieve (url &rest args)
+  "Insert a content pointed by URL if it has the cid: scheme."
+  (when (string-match "\\`cid:" url)
+    (setq url (concat "<" (substring url (match-end 0)) ">"))
+    (catch 'found-handle
+      (let ((handles (with-current-buffer w3m-current-buffer
+                      gnus-article-mime-handles)))
+       (if (mm-multiple-handles handles)
+           (dolist (handle handles)
+             (mm-w3m-cid-retrieve-1 url handle))
+         (mm-w3m-cid-retrieve-1 url handles))))))
+
+(eval-and-compile
+  (unless (or (featurep 'xemacs)
+             (>= emacs-major-version 21))
+    (defvar mm-w3m-mode-map nil
+      "Keymap for text/html parts rendered by emacs-w3m.
+This keymap will be bound only when Emacs 20 is running and overwritten
+by the value of `w3m-minor-mode-map'.  In order to add some commands to
+this keymap, add them to `w3m-minor-mode-map' instead of this keymap.")))
+
+(defun mm-w3m-local-map-property ()
+  (when (and (boundp 'w3m-minor-mode-map) w3m-minor-mode-map)
+    (if (or (featurep 'xemacs)
+           (>= emacs-major-version 21))
+       (list 'keymap w3m-minor-mode-map)
+      (list 'local-map
+           (or mm-w3m-mode-map
+               (progn
+                 (setq mm-w3m-mode-map (copy-keymap w3m-minor-mode-map))
+                 (set-keymap-parent mm-w3m-mode-map gnus-article-mode-map)
+                 mm-w3m-mode-map))))))
+
+(defun mm-inline-text-html-render-with-w3m (handle)
+  "Render a text/html part using emacs-w3m."
+  (mm-setup-w3m)
+  (let ((text (mm-get-part handle))
+       (b (point))
+       (charset (mail-content-type-get (mm-handle-type handle) 'charset)))
+    (save-excursion
+      (insert text)
+      (save-restriction
+       (narrow-to-region b (point))
+       (goto-char (point-min))
+       (when (re-search-forward w3m-meta-content-type-charset-regexp nil t)
+         (setq charset (or (w3m-charset-to-coding-system (match-string 2))
+                           charset)))
+       (when charset
+         (delete-region (point-min) (point-max))
+         (insert (mm-decode-string text charset)))
+       (let ((w3m-safe-url-regexp mm-w3m-safe-url-regexp)
+             w3m-force-redisplay)
+         (w3m-region (point-min) (point-max)))
+       (when mm-inline-text-html-with-w3m-keymap
+         (add-text-properties
+          (point-min) (point-max)
+          (nconc (mm-w3m-local-map-property)
+                 ;; Put the mark meaning this part was rendered by emacs-w3m.
+                 '(mm-inline-text-html-with-w3m t)))))
+      (mm-handle-set-undisplayer
+       handle
+       `(lambda ()
+         (let (buffer-read-only)
+           (if (functionp 'remove-specifier)
+               (mapcar (lambda (prop)
+                         (remove-specifier
+                          (face-property 'default prop)
+                          (current-buffer)))
+                       '(background background-pixmap foreground)))
+           (delete-region ,(point-min-marker)
+                          ,(point-max-marker))))))))
+
+(defun mm-links-remove-leading-blank ()
+  ;; Delete the annoying three spaces preceding each line of links
+  ;; output.
+  (goto-char (point-min))
+  (while (re-search-forward "^   " nil t)
+    (delete-region (match-beginning 0) (match-end 0))))
+
+(defun mm-inline-wash-with-file (post-func cmd &rest args)
+  (let ((file (mm-make-temp-file
+              (expand-file-name "mm" mm-tmp-directory))))
+    (let ((coding-system-for-write 'binary))
+      (write-region (point-min) (point-max) file nil 'silent))
+    (delete-region (point-min) (point-max))
+    (unwind-protect
+       (apply 'call-process cmd nil t nil (mapcar 'eval args))
+      (delete-file file))
+    (and post-func (funcall post-func))))
+
+(defun mm-inline-wash-with-stdin (post-func cmd &rest args)
+  (let ((coding-system-for-write 'binary))
+    (apply 'call-process-region (point-min) (point-max)
+          cmd t t nil args))
+  (and post-func (funcall post-func)))
+
+(defun mm-inline-render-with-file (handle post-func cmd &rest args)
+  (let ((source (mm-get-part handle)))
+    (mm-insert-inline
+     handle
+     (mm-with-unibyte-buffer
+       (insert source)
+       (apply 'mm-inline-wash-with-file post-func cmd args)
+       (buffer-string)))))
+
+(defun mm-inline-render-with-stdin (handle post-func cmd &rest args)
+  (let ((source (mm-get-part handle)))
+    (mm-insert-inline
+     handle
+     (mm-with-unibyte-buffer
+       (insert source)
+       (apply 'mm-inline-wash-with-stdin post-func cmd args)
+       (buffer-string)))))
+
+(defun mm-inline-render-with-function (handle func &rest args)
+  (let ((source (mm-get-part handle)))
+    (mm-insert-inline
+     handle
+     (mm-with-unibyte-buffer
+       (insert source)
+       (apply func args)
+       (buffer-string)))))
+
+(defun mm-inline-text-html (handle)
+  (let* ((func (or mm-inline-text-html-renderer mm-text-html-renderer))
+        (entry (assq func mm-text-html-renderer-alist))
+        buffer-read-only)
+    (if entry
+       (setq func (cdr entry)))
+    (cond
+     ((functionp func)
+      (funcall func handle))
+     (t
+      (apply (car func) handle (cdr func))))))
+
+(defun mm-inline-text-vcard (handle)
+  (let (buffer-read-only)
+    (mm-insert-inline
+     handle
+     (concat "\n-- \n"
+            (ignore-errors
+              (if (fboundp 'vcard-pretty-print)
+                  (vcard-pretty-print (mm-get-part handle))
+                (vcard-format-string
+                 (vcard-parse-string (mm-get-part handle)
+                                     'vcard-standard-filter))))))))
+
+(defun mm-inline-text (handle)
+  (let ((b (point))
+       (type (mm-handle-media-subtype handle))
+       (charset (mail-content-type-get
+                 (mm-handle-type handle) 'charset))
+       buffer-read-only)
+    (if (or (eq charset 'gnus-decoded)
+           ;; This is probably not entirely correct, but
+           ;; makes rfc822 parts with embedded multiparts work.
+           (eq mail-parse-charset 'gnus-decoded))
+       (save-restriction
+         (narrow-to-region (point) (point))
+         (mm-insert-part handle)
+         (goto-char (point-max)))
+      (insert (mm-decode-string (mm-get-part handle) charset)))
+    (when (and (equal type "plain")
+              (equal (cdr (assoc 'format (mm-handle-type handle)))
+                     "flowed"))
+      (save-restriction
+       (narrow-to-region b (point))
+       (goto-char b)
+       (fill-flowed)
+       (goto-char (point-max))))
+    (save-restriction
+      (narrow-to-region b (point))
+      (set-text-properties (point-min) (point-max) nil)
+      (when (or (equal type "enriched")
+               (equal type "richtext"))
+       (ignore-errors
+         (enriched-decode (point-min) (point-max))))
+      (mm-handle-set-undisplayer
+       handle
+       `(lambda ()
+         (let (buffer-read-only)
+           (delete-region ,(point-min-marker)
+                          ,(point-max-marker))))))))
+
+(defun mm-insert-inline (handle text)
+  "Insert TEXT inline from HANDLE."
+  (let ((b (point)))
+    (insert text)
+    (mm-handle-set-undisplayer
+     handle
+     `(lambda ()
+       (let (buffer-read-only)
+         (delete-region ,(set-marker (make-marker) b)
+                        ,(set-marker (make-marker) (point))))))))
+
+(defun mm-inline-audio (handle)
+  (message "Not implemented"))
+
+(defun mm-view-sound-file ()
+  (message "Not implemented"))
+
+(defun mm-w3-prepare-buffer ()
+  (require 'w3)
+  (let ((url-standalone-mode t)
+       (url-gateway-unplugged t)
+       (w3-honor-stylesheets nil))
+    (w3-prepare-buffer)))
+
+(defun mm-view-message ()
+  (mm-enable-multibyte)
+  (let (handles)
+    (let (gnus-article-mime-handles)
+      ;; Double decode problem may happen.  See mm-inline-message.
+      (run-hooks 'gnus-article-decode-hook)
+      (gnus-article-prepare-display)
+      (setq handles gnus-article-mime-handles))
+    (when handles
+      (setq gnus-article-mime-handles
+           (mm-merge-handles gnus-article-mime-handles handles))))
+  (fundamental-mode)
+  (goto-char (point-min)))
+
+(defun mm-inline-message (handle)
+  (let ((b (point))
+       (bolp (bolp))
+       (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
+             ;; disable prepare hook
+             gnus-article-prepare-hook
+             (gnus-newsgroup-charset
+              (or charset gnus-newsgroup-charset)))
+         (let ((gnus-original-article-buffer (mm-handle-buffer handle)))
+           (run-hooks 'gnus-article-decode-hook))
+         (gnus-article-prepare-display)
+         (setq handles gnus-article-mime-handles))
+       (goto-char (point-min))
+       (unless bolp
+         (insert "\n"))
+       (goto-char (point-max))
+       (unless (bolp)
+         (insert "\n"))
+       (insert "----------\n\n")
+       (when handles
+         (setq gnus-article-mime-handles
+               (mm-merge-handles gnus-article-mime-handles handles)))
+       (mm-handle-set-undisplayer
+        handle
+        `(lambda ()
+           (let (buffer-read-only)
+             (if (fboundp 'remove-specifier)
+                 ;; This is only valid on XEmacs.
+                 (mapcar (lambda (prop)
+                           (remove-specifier
+                            (face-property 'default prop) (current-buffer)))
+                         '(background background-pixmap foreground)))
+             (delete-region ,(point-min-marker) ,(point-max-marker)))))))))
+
+(defun mm-display-inline-fontify (handle mode)
+  (let (text)
+    ;; XEmacs @#$@ version of font-lock refuses to fully turn itself
+    ;; on for buffers whose name begins with " ".  That's why we use
+    ;; save-current-buffer/get-buffer-create rather than
+    ;; with-temp-buffer.
+    (save-current-buffer
+      (set-buffer (generate-new-buffer "*fontification*"))
+      (unwind-protect
+         (progn
+           (buffer-disable-undo)
+           (mm-insert-part handle)
+           (funcall mode)
+           (require 'font-lock)
+           (let ((font-lock-verbose nil))
+             ;; I find font-lock a bit too verbose.
+             (font-lock-fontify-buffer))
+           ;; By default, XEmacs font-lock uses non-duplicable text
+           ;; properties.  This code forces all the text properties
+           ;; to be copied along with the text.
+           (when (fboundp 'extent-list)
+             (map-extents (lambda (ext ignored)
+                            (set-extent-property ext 'duplicable t)
+                            nil)
+                          nil nil nil nil nil 'text-prop))
+           (setq text (buffer-string)))
+       (kill-buffer (current-buffer))))
+    (mm-insert-inline handle text)))
+
+;; Shouldn't these functions check whether the user even wants to use
+;; font-lock?  At least under XEmacs, this fontification is pretty
+;; much unconditional.  Also, it would be nice to change for the size
+;; of the fontified region.
+
+(defun mm-display-patch-inline (handle)
+  (mm-display-inline-fontify handle 'diff-mode))
+
+(defun mm-display-elisp-inline (handle)
+  (mm-display-inline-fontify handle 'emacs-lisp-mode))
+
+;;      id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+;;          us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
+(defvar mm-pkcs7-signed-magic
+  (mm-string-as-unibyte
+   (apply 'concat
+         (mapcar 'char-to-string
+                 (list ?\x30 ?\x5c ?\x28 ?\x80 ?\x5c ?\x7c ?\x81 ?\x2e ?\x5c
+                       ?\x7c ?\x82 ?\x2e ?\x2e ?\x5c ?\x7c ?\x83 ?\x2e ?\x2e
+                       ?\x2e ?\x5c ?\x29 ?\x06 ?\x09 ?\x5c ?\x2a ?\x86 ?\x48
+                       ?\x86 ?\xf7 ?\x0d ?\x01 ?\x07 ?\x02)))))
+
+;;      id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+;;          us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 }
+(defvar mm-pkcs7-enveloped-magic
+  (mm-string-as-unibyte
+   (apply 'concat
+         (mapcar 'char-to-string
+                 (list ?\x30 ?\x5c ?\x28 ?\x80 ?\x5c ?\x7c ?\x81 ?\x2e ?\x5c
+                       ?\x7c ?\x82 ?\x2e ?\x2e ?\x5c ?\x7c ?\x83 ?\x2e ?\x2e
+                       ?\x2e ?\x5c ?\x29 ?\x06 ?\x09 ?\x5c ?\x2a ?\x86 ?\x48
+                       ?\x86 ?\xf7 ?\x0d ?\x01 ?\x07 ?\x03)))))
+
+(defun mm-view-pkcs7-get-type (handle)
+  (mm-with-unibyte-buffer
+   (mm-insert-part handle)
+   (cond ((looking-at mm-pkcs7-enveloped-magic)
+         'enveloped)
+        ((looking-at mm-pkcs7-signed-magic)
+         'signed)
+        (t
+         (error "Could not identify PKCS#7 type")))))
+
+(defun mm-view-pkcs7 (handle)
+  (case (mm-view-pkcs7-get-type handle)
+    (enveloped (mm-view-pkcs7-decrypt handle))
+    (signed (mm-view-pkcs7-verify handle))
+    (otherwise (error "Unknown or unimplemented PKCS#7 type"))))
+
+(defun mm-view-pkcs7-verify (handle)
+  ;; A bogus implementation of PKCS#7. FIXME::
+  (mm-insert-part handle)
+  (goto-char (point-min))
+  (if (search-forward "Content-Type: " nil t)
+      (delete-region (point-min) (match-beginning 0)))
+  (goto-char (point-max))
+  (if (re-search-backward "--\r?\n?" nil t)
+      (delete-region (match-end 0) (point-max)))
+  (goto-char (point-min))
+  (while (search-forward "\r\n" nil t)
+    (replace-match "\n"))
+  (message "Verify signed PKCS#7 message is unimplemented.")
+  (sit-for 1)
+  t)
+
+(autoload 'gnus-completing-read-maybe-default "gnus-util" nil nil 'macro)
+
+(defun mm-view-pkcs7-decrypt (handle)
+  (insert-buffer-substring (mm-handle-buffer handle))
+  (goto-char (point-min))
+  (insert "MIME-Version: 1.0\n")
+  (mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m")
+  (smime-decrypt-region
+   (point-min) (point-max)
+   (if (= (length smime-keys) 1)
+       (cadar smime-keys)
+     (smime-get-key-by-email
+      (gnus-completing-read-maybe-default
+       (concat "Decipher using which key? "
+              (if smime-keys (concat "(default " (caar smime-keys) ") ")
+                ""))
+       smime-keys nil nil nil nil (car-safe (car-safe smime-keys))))))
+  (goto-char (point-min))
+  (while (search-forward "\r\n" nil t)
+    (replace-match "\n"))
+  (goto-char (point-min)))
+
+(provide 'mm-view)
+
+;;; mm-view.el ends here
diff --git a/lisp/mmgnus.el b/lisp/mmgnus.el
new file mode 100644 (file)
index 0000000..d5ad15f
--- /dev/null
@@ -0,0 +1,44 @@
+;;; mmgnus.el --- MIME entity implementation for gnus-article
+
+;; Copyright (C) 1998 Free Software Foundation, Inc.
+
+;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Keywords: MIME, multimedia, mail, news
+
+;; This file is part of Chao-gnus.
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'mmbuffer)
+
+(luna-define-class mime-gnus-entity (mime-buffer-entity)
+                  (number
+                   subject from date id references chars lines xref extra))
+
+(luna-define-internal-accessors 'mime-gnus-entity)
+
+(luna-define-method initialize-instance ((entity mime-gnus-entity)
+                                        &rest init-args)
+  (apply (car (luna-class-find-functions
+              (luna-find-class 'standard-object)
+              'initialize-instance))
+        entity init-args))
+
+(provide 'mmgnus)
+
+;;; mmgnus.el ends here
diff --git a/lisp/mml-sec.el b/lisp/mml-sec.el
new file mode 100644 (file)
index 0000000..c1a494b
--- /dev/null
@@ -0,0 +1,292 @@
+;;; mml-sec.el --- A package with security functions for MML documents
+;; Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'mml-smime)
+(eval-when-compile (require 'cl))
+(autoload 'mml2015-sign "mml2015")
+(autoload 'mml2015-encrypt "mml2015")
+(autoload 'mml1991-sign "mml1991")
+(autoload 'mml1991-encrypt "mml1991")
+(autoload 'message-goto-body "message")
+(autoload 'mml-insert-tag "mml")
+
+(defvar mml-sign-alist
+  '(("smime"     mml-smime-sign-buffer     mml-smime-sign-query)
+    ("pgp"       mml-pgp-sign-buffer       list)
+    ("pgpauto"   mml-pgpauto-sign-buffer  list)
+    ("pgpmime"   mml-pgpmime-sign-buffer   list))
+  "Alist of MIME signer functions.")
+
+(defcustom mml-default-sign-method "pgpmime"
+  "Default sign method.
+The string must have an entry in `mml-sign-alist'."
+  :type '(choice (const "smime")
+                (const "pgp")
+                (const "pgpauto")
+                (const "pgpmime")
+                string)
+  :group 'message)
+
+(defvar mml-encrypt-alist
+  '(("smime"     mml-smime-encrypt-buffer     mml-smime-encrypt-query)
+    ("pgp"       mml-pgp-encrypt-buffer       list)
+    ("pgpauto"   mml-pgpauto-sign-buffer  list)
+    ("pgpmime"   mml-pgpmime-encrypt-buffer   list))
+  "Alist of MIME encryption functions.")
+
+(defcustom mml-default-encrypt-method "pgpmime"
+  "Default encryption method.
+The string must have an entry in `mml-encrypt-alist'."
+  :type '(choice (const "smime")
+                (const "pgp")
+                (const "pgpauto")
+                (const "pgpmime")
+                string)
+  :group 'message)
+
+(defcustom mml-signencrypt-style-alist
+  '(("smime"   separate)
+    ("pgp"     combined)
+    ("pgpauto" combined)
+    ("pgpmime" combined))
+  "Alist specifying if `signencrypt' results in two separate operations or not.
+The first entry indicates the MML security type, valid entries include
+the strings \"smime\", \"pgp\", and \"pgpmime\".  The second entry is
+a symbol `separate' or `combined' where `separate' means that MML signs
+and encrypt messages in a two step process, and `combined' means that MML
+signs and encrypt the message in one step.
+
+Note that the output generated by using a `combined' mode is NOT
+understood by all PGP implementations, in particular PGP version
+2 does not support it!  See Info node `(message)Security' for
+details."
+  :type '(repeat (list (choice (const :tag "S/MIME" "smime")
+                              (const :tag "PGP" "pgp")
+                              (const :tag "PGP/MIME" "pgpmime")
+                              (string :tag "User defined"))
+                      (choice (const :tag "Separate" separate)
+                              (const :tag "Combined" combined)))))
+
+;;; Configuration/helper functions
+
+(defun mml-signencrypt-style (method &optional style)
+  "Function for setting/getting the signencrypt-style used.  Takes two
+arguments, the method (e.g. \"pgp\") and optionally the mode
+\(e.g. combined).  If the mode is omitted, the current value is returned.
+
+For example, if you prefer to use combined sign & encrypt with
+smime, putting the following in your Gnus startup file will
+enable that behavior:
+
+\(mml-set-signencrypt-style \"smime\" combined)
+
+You can also customize or set `mml-signencrypt-style-alist' instead."
+  (let ((style-item (assoc method mml-signencrypt-style-alist)))
+    (if style-item
+       (if (or (eq style 'separate)
+               (eq style 'combined))
+           ;; valid style setting?
+           (setf (second style-item) style)
+         ;; otherwise, just return the current value
+         (second style-item))
+      (gnus-message 3 "Warning, attempt to set invalid signencrypt-style"))))
+
+;;; Security functions
+
+(defun mml-smime-sign-buffer (cont)
+  (or (mml-smime-sign cont)
+      (error "Signing failed... inspect message logs for errors")))
+
+(defun mml-smime-encrypt-buffer (cont &optional sign)
+  (when sign
+    (message "Combined sign and encrypt S/MIME not support yet")
+    (sit-for 1))
+  (or (mml-smime-encrypt cont)
+      (error "Encryption failed... inspect message logs for errors")))
+
+(defun mml-pgp-sign-buffer (cont)
+  (or (mml1991-sign cont)
+      (error "Signing failed... inspect message logs for errors")))
+
+(defun mml-pgp-encrypt-buffer (cont &optional sign)
+  (or (mml1991-encrypt cont sign)
+      (error "Encryption failed... inspect message logs for errors")))
+
+(defun mml-pgpmime-sign-buffer (cont)
+  (or (mml2015-sign cont)
+      (error "Signing failed... inspect message logs for errors")))
+
+(defun mml-pgpmime-encrypt-buffer (cont &optional sign)
+  (or (mml2015-encrypt cont sign)
+      (error "Encryption failed... inspect message logs for errors")))
+
+(defun mml-pgpauto-sign-buffer (cont)
+  (message-goto-body)
+  (or (if (re-search-backward "Content-Type: *multipart/.*" nil t) ; there must be a better way...
+         (mml2015-sign cont)
+       (mml1991-sign cont))
+      (error "Encryption failed... inspect message logs for errors")))
+
+(defun mml-pgpauto-encrypt-buffer (cont &optional sign)
+  (message-goto-body)
+  (or (if (re-search-backward "Content-Type: *multipart/.*" nil t) ; there must be a better way...
+         (mml2015-encrypt cont sign)
+       (mml1991-encrypt cont sign))
+      (error "Encryption failed... inspect message logs for errors")))
+
+(defun mml-secure-part (method &optional sign)
+  (save-excursion
+    (let ((tags (funcall (nth 2 (assoc method (if sign mml-sign-alist
+                                               mml-encrypt-alist))))))
+      (cond ((re-search-backward
+             "<#\\(multipart\\|part\\|external\\|mml\\)" nil t)
+            (goto-char (match-end 0))
+            (insert (if sign " sign=" " encrypt=") method)
+            (while tags
+              (let ((key (pop tags))
+                    (value (pop tags)))
+                (when value
+                  ;; Quote VALUE if it contains suspicious characters.
+                  (when (string-match "[\"'\\~/*;() \t\n]" value)
+                    (setq value (prin1-to-string value)))
+                  (insert (format " %s=%s" key value))))))
+           ((or (re-search-backward
+                 (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
+                (re-search-forward
+                 (concat "^" (regexp-quote mail-header-separator) "\n") nil t))
+            (goto-char (match-end 0))
+            (apply 'mml-insert-tag 'part (cons (if sign 'sign 'encrypt)
+                                               (cons method tags))))
+           (t (error "The message is corrupted. No mail header separator"))))))
+
+(defun mml-secure-sign-pgp ()
+  "Add MML tags to PGP sign this MML part."
+  (interactive)
+  (mml-secure-part "pgp" 'sign))
+
+(defun mml-secure-sign-pgpauto ()
+  "Add MML tags to PGP-auto sign this MML part."
+  (interactive)
+  (mml-secure-part "pgpauto" 'sign))
+
+(defun mml-secure-sign-pgpmime ()
+  "Add MML tags to PGP/MIME sign this MML part."
+  (interactive)
+  (mml-secure-part "pgpmime" 'sign))
+
+(defun mml-secure-sign-smime ()
+  "Add MML tags to S/MIME sign this MML part."
+  (interactive)
+  (mml-secure-part "smime" 'sign))
+
+(defun mml-secure-encrypt-pgp ()
+  "Add MML tags to PGP encrypt this MML part."
+  (interactive)
+  (mml-secure-part "pgp"))
+
+(defun mml-secure-encrypt-pgpmime ()
+  "Add MML tags to PGP/MIME encrypt this MML part."
+  (interactive)
+  (mml-secure-part "pgpmime"))
+
+(defun mml-secure-encrypt-smime ()
+  "Add MML tags to S/MIME encrypt this MML part."
+  (interactive)
+  (mml-secure-part "smime"))
+
+;; defuns that add the proper <#secure ...> tag to the top of the message body
+(defun mml-secure-message (method &optional modesym)
+  (let ((mode (prin1-to-string modesym))
+       insert-loc)
+    (mml-unsecure-message)
+    (save-excursion
+      (goto-char (point-min))
+      (cond ((re-search-forward
+             (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
+            (goto-char (setq insert-loc (match-end 0)))
+            (unless (looking-at "<#secure")
+              (mml-insert-tag
+               'secure 'method method 'mode mode)))
+           (t (error
+               "The message is corrupted. No mail header separator"))))
+    (when (eql insert-loc (point))
+      (forward-line 1))))
+
+(defun mml-unsecure-message ()
+  "Remove security related MML tags from message."
+  (interactive)
+  (save-excursion
+    (goto-char (point-max))
+    (when (re-search-backward "^<#secure.*>\n" nil t)
+      (delete-region (match-beginning 0) (match-end 0)))))
+
+(defun mml-secure-message-sign-smime ()
+  "Add MML tag to encrypt/sign the entire message."
+  (interactive)
+  (mml-secure-message "smime" 'sign))
+
+(defun mml-secure-message-sign-pgp ()
+  "Add MML tag to encrypt/sign the entire message."
+  (interactive)
+  (mml-secure-message "pgp" 'sign))
+
+(defun mml-secure-message-sign-pgpmime ()
+  "Add MML tag to encrypt/sign the entire message."
+  (interactive)
+  (mml-secure-message "pgpmime" 'sign))
+
+(defun mml-secure-message-sign-pgpauto ()
+  "Add MML tag to encrypt/sign the entire message."
+  (interactive)
+  (mml-secure-message "pgpauto" 'sign))
+
+(defun mml-secure-message-encrypt-smime (&optional dontsign)
+  "Add MML tag to encrypt and sign the entire message.
+If called with a prefix argument, only encrypt (do NOT sign)."
+  (interactive "P")
+  (mml-secure-message "smime" (if dontsign 'encrypt 'signencrypt)))
+
+(defun mml-secure-message-encrypt-pgp (&optional dontsign)
+  "Add MML tag to encrypt and sign the entire message.
+If called with a prefix argument, only encrypt (do NOT sign)."
+  (interactive "P")
+  (mml-secure-message "pgp" (if dontsign 'encrypt 'signencrypt)))
+
+(defun mml-secure-message-encrypt-pgpmime (&optional dontsign)
+  "Add MML tag to encrypt and sign the entire message.
+If called with a prefix argument, only encrypt (do NOT sign)."
+  (interactive "P")
+  (mml-secure-message "pgpmime" (if dontsign 'encrypt 'signencrypt)))
+
+(defun mml-secure-message-encrypt-pgpauto (&optional dontsign)
+  "Add MML tag to encrypt and sign the entire message.
+If called with a prefix argument, only encrypt (do NOT sign)."
+  (interactive "P")
+  (mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt)))
+
+(provide 'mml-sec)
+
+;;; mml-sec.el ends here
diff --git a/lisp/mml-smime.el b/lisp/mml-smime.el
new file mode 100644 (file)
index 0000000..45e06d7
--- /dev/null
@@ -0,0 +1,200 @@
+;;; mml-smime.el --- S/MIME support for MML
+;; Copyright (c) 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: Gnus, MIME, S/MIME, MML
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'smime)
+(require 'mm-decode)
+(autoload 'message-narrow-to-headers "message")
+
+(defun mml-smime-sign (cont)
+  (when (null smime-keys)
+    (customize-variable 'smime-keys)
+    (error "No S/MIME keys configured, use customize to add your key"))
+  (smime-sign-buffer (cdr (assq 'keyfile cont)))
+  (goto-char (point-min))
+  (while (search-forward "\r\n" nil t)
+    (replace-match "\n" t t))
+  (goto-char (point-max)))
+
+(defun mml-smime-encrypt (cont)
+  (let (certnames certfiles tmp file tmpfiles)
+    ;; xxx tmp files are always an security issue
+    (while (setq tmp (pop cont))
+      (if (and (consp tmp) (eq (car tmp) 'certfile))
+         (push (cdr tmp) certnames)))
+    (while (setq tmp (pop certnames))
+      (if (not (and (not (file-exists-p tmp))
+                   (get-buffer tmp)))
+         (push tmp certfiles)
+       (setq file (mm-make-temp-file (expand-file-name "mml." 
+                                                       mm-tmp-directory)))
+       (with-current-buffer tmp
+         (write-region (point-min) (point-max) file))
+       (push file certfiles)
+       (push file tmpfiles)))
+    (if (smime-encrypt-buffer certfiles)
+       (progn
+         (while (setq tmp (pop tmpfiles))
+           (delete-file tmp))
+         t)
+      (while (setq tmp (pop tmpfiles))
+       (delete-file tmp))
+      nil))
+  (goto-char (point-max)))
+
+(defun mml-smime-sign-query ()
+  ;; query information (what certificate) from user when MML tag is
+  ;; added, for use later by the signing process
+  (when (null smime-keys)
+    (customize-variable 'smime-keys)
+    (error "No S/MIME keys configured, use customize to add your key"))
+  (list 'keyfile
+       (if (= (length smime-keys) 1)
+           (cadar smime-keys)
+         (or (let ((from (cadr (funcall gnus-extract-address-components
+                                        (or (save-excursion
+                                              (save-restriction
+                                                (message-narrow-to-headers)
+                                                (message-fetch-field "from")))
+                                            "")))))
+               (and from (smime-get-key-by-email from)))
+             (smime-get-key-by-email
+              (completing-read "Sign this part with what signature? "
+                               smime-keys nil nil
+                               (and (listp (car-safe smime-keys))
+                                    (caar smime-keys))))))))
+
+(defun mml-smime-get-file-cert ()
+  (ignore-errors
+    (list 'certfile (read-file-name
+                    "File with recipient's S/MIME certificate: "
+                    smime-certificate-directory nil t ""))))
+
+(defun mml-smime-get-dns-cert ()
+  ;; todo: deal with comma separated multiple recipients
+  (let (result who bad cert)
+    (condition-case ()
+       (while (not result)
+         (setq who (read-from-minibuffer
+                    (format "%sLookup certificate for: " (or bad ""))
+                    (cadr (funcall gnus-extract-address-components
+                                   (or (save-excursion
+                                         (save-restriction
+                                           (message-narrow-to-headers)
+                                           (message-fetch-field "to")))
+                                       "")))))
+         (if (setq cert (smime-cert-by-dns who))
+             (setq result (list 'certfile (buffer-name cert)))
+           (setq bad (format "`%s' not found. " who))))
+      (quit))
+    result))
+
+(defun mml-smime-encrypt-query ()
+  ;; todo: add ldap support (xemacs ldap api?)
+  ;; todo: try dns/ldap automatically first, before prompting user
+  (let (certs done)
+    (while (not done)
+      (ecase (read (gnus-completing-read-with-default
+                   "dns" "Fetch certificate from"
+                   '(("dns") ("file")) nil t))
+       (dns (setq certs (append certs
+                                (mml-smime-get-dns-cert))))
+       (file (setq certs (append certs
+                                 (mml-smime-get-file-cert)))))
+      (setq done (not (y-or-n-p "Add more recipients? "))))
+    certs))
+
+(defun mml-smime-verify (handle ctl)
+  (with-temp-buffer
+    (insert-buffer-substring (mm-handle-multipart-original-buffer ctl))
+    (goto-char (point-min))
+    (insert (format "Content-Type: %s; " (mm-handle-media-type ctl)))
+    (insert (format "protocol=\"%s\"; "
+                   (mm-handle-multipart-ctl-parameter ctl 'protocol)))
+    (insert (format "micalg=\"%s\"; "
+                   (mm-handle-multipart-ctl-parameter ctl 'micalg)))
+    (insert (format "boundary=\"%s\"\n\n"
+                   (mm-handle-multipart-ctl-parameter ctl 'boundary)))
+    (when (get-buffer smime-details-buffer)
+      (kill-buffer smime-details-buffer))
+    (let ((buf (current-buffer))
+         (good-signature (smime-noverify-buffer))
+         (good-certificate (and (or smime-CA-file smime-CA-directory)
+                                (smime-verify-buffer)))
+         addresses openssl-output)
+      (setq openssl-output (with-current-buffer smime-details-buffer
+                            (buffer-string)))
+      (if (not good-signature)
+         (progn
+           ;; we couldn't verify message, fail with openssl output as message
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-info "Failed")
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-details
+            (concat "OpenSSL failed to verify message integrity:\n"
+                    "-------------------------------------------\n"
+                    openssl-output)))
+       ;; verify mail addresses in mail against those in certificate
+       (when (and (smime-pkcs7-region (point-min) (point-max))
+                  (smime-pkcs7-certificates-region (point-min) (point-max)))
+         (with-temp-buffer
+           (insert-buffer-substring buf)
+           (goto-char (point-min))
+           (while (re-search-forward "-----END CERTIFICATE-----" nil t)
+             (when (smime-pkcs7-email-region (point-min) (point))
+               (setq addresses (append (smime-buffer-as-string-region
+                                        (point-min) (point)) addresses)))
+             (delete-region (point-min) (point)))
+           (setq addresses (mapcar 'downcase addresses))))
+       (if (not (member (downcase (or (mm-handle-multipart-from ctl) "")) addresses))
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-info "Sender address forged")
+         (if good-certificate
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-info "Ok (sender authenticated)")
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-info "Ok (sender not trusted)")))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-details
+        (concat "Sender claimed to be: " (mm-handle-multipart-from ctl) "\n"
+                (if addresses
+                    (concat "Addresses in certificate: "
+                            (mapconcat 'identity addresses ", "))
+                  "No addresses found in certificate. (Requires OpenSSL 0.9.6 or later.)")
+                "\n" "\n"
+                "OpenSSL output:\n"
+                "---------------\n" openssl-output "\n"
+                "Certificate(s) inside S/MIME signature:\n"
+                "---------------------------------------\n"
+                (buffer-string) "\n")))))
+  handle)
+
+(defun mml-smime-verify-test (handle ctl)
+  smime-openssl-program)
+
+(provide 'mml-smime)
+
+;;; mml-smime.el ends here
diff --git a/lisp/mml.el b/lisp/mml.el
new file mode 100644 (file)
index 0000000..cdec507
--- /dev/null
@@ -0,0 +1,1174 @@
+;;; mml.el --- A package for parsing and validating MML documents
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'mm-util)
+(require 'mm-bodies)
+(require 'mm-encode)
+(require 'mm-decode)
+(require 'mml-sec)
+(eval-when-compile (require 'cl))
+
+(eval-and-compile
+  (autoload 'message-make-message-id "message")
+  (autoload 'gnus-setup-posting-charset "gnus-msg")
+  (autoload 'gnus-add-minor-mode "gnus-ems")
+  (autoload 'gnus-make-local-hook "gnus-util")
+  (autoload 'message-fetch-field "message")
+  (autoload 'fill-flowed-encode "flow-fill")
+  (autoload 'message-posting-charset "message"))
+
+(defcustom mml-content-type-parameters
+  '(name access-type expiration size permission format)
+  "*A list of acceptable parameters in MML tag.
+These parameters are generated in Content-Type header if exists."
+  :type '(repeat (symbol :tag "Parameter"))
+  :group 'message)
+
+(defcustom mml-content-disposition-parameters
+  '(filename creation-date modification-date read-date)
+  "*A list of acceptable parameters in MML tag.
+These parameters are generated in Content-Disposition header if exists."
+  :type '(repeat (symbol :tag "Parameter"))
+  :group 'message)
+
+(defcustom mml-insert-mime-headers-always nil
+  "If non-nil, always put Content-Type: text/plain at top of empty parts.
+It is necessary to work against a bug in certain clients."
+  :type 'boolean
+  :group 'message)
+
+(defvar mml-tweak-type-alist nil
+  "A list of (TYPE . FUNCTION) for tweaking MML parts.
+TYPE is a string containing a regexp to match the MIME type.  FUNCTION
+is a Lisp function which is called with the MML handle to tweak the
+part.  This variable is used only when no TWEAK parameter exists in
+the MML handle.")
+
+(defvar mml-tweak-function-alist nil
+  "A list of (NAME . FUNCTION) for tweaking MML parts.
+NAME is a string containing the name of the TWEAK parameter in the MML
+handle.  FUNCTION is a Lisp function which is called with the MML
+handle to tweak the part.")
+
+(defvar mml-tweak-sexp-alist
+  '((mml-externalize-attachments . mml-tweak-externalize-attachments))
+  "A list of (SEXP . FUNCTION) for tweaking MML parts.
+SEXP is an s-expression.  If the evaluation of SEXP is non-nil, FUNCTION
+is called.  FUNCTION is a Lisp function which is called with the MML
+handle to tweak the part.")
+
+(defvar mml-externalize-attachments nil
+  "*If non-nil, local-file attachments are generated as external parts.")
+
+(defvar mml-generate-multipart-alist nil
+  "*Alist of multipart generation functions.
+Each entry has the form (NAME . FUNCTION), where
+NAME is a string containing the name of the part (without the
+leading \"/multipart/\"),
+FUNCTION is a Lisp function which is called to generate the part.
+
+The Lisp function has to supply the appropriate MIME headers and the
+contents of this part.")
+
+(defvar mml-syntax-table
+  (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
+    (modify-syntax-entry ?\\ "/" table)
+    (modify-syntax-entry ?< "(" table)
+    (modify-syntax-entry ?> ")" table)
+    (modify-syntax-entry ?@ "w" table)
+    (modify-syntax-entry ?/ "w" table)
+    (modify-syntax-entry ?= " " table)
+    (modify-syntax-entry ?* " " table)
+    (modify-syntax-entry ?\; " " table)
+    (modify-syntax-entry ?\' " " table)
+    table))
+
+(defvar mml-boundary-function 'mml-make-boundary
+  "A function called to suggest a boundary.
+The function may be called several times, and should try to make a new
+suggestion each time.  The function is called with one parameter,
+which is a number that says how many times the function has been
+called for this message.")
+
+(defvar mml-confirmation-set nil
+  "A list of symbols, each of which disables some warning.
+`unknown-encoding': always send messages contain characters with
+unknown encoding; `use-ascii': always use ASCII for those characters
+with unknown encoding; `multipart': always send messages with more than
+one charsets.")
+
+(defvar mml-generate-default-type "text/plain")
+
+(defvar mml-buffer-list nil)
+
+(defun mml-generate-new-buffer (name)
+  (let ((buf (generate-new-buffer name)))
+    (push buf mml-buffer-list)
+    buf))
+
+(defun mml-destroy-buffers ()
+  (let (kill-buffer-hook)
+    (mapcar 'kill-buffer mml-buffer-list)
+    (setq mml-buffer-list nil)))
+
+(defun mml-parse ()
+  "Parse the current buffer as an MML document."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((table (syntax-table)))
+      (unwind-protect
+         (progn
+           (set-syntax-table mml-syntax-table)
+           (mml-parse-1))
+       (set-syntax-table table)))))
+
+(defun mml-parse-1 ()
+  "Parse the current buffer as an MML document."
+  (let (struct tag point contents charsets warn use-ascii no-markup-p raw)
+    (while (and (not (eobp))
+               (not (looking-at "<#/multipart")))
+      (cond
+       ((looking-at "<#secure")
+       ;; The secure part is essentially a meta-meta tag, which
+       ;; expands to either a part tag if there are no other parts in
+       ;; the document or a multipart tag if there are other parts
+       ;; included in the message
+       (let* (secure-mode
+              (taginfo (mml-read-tag))
+              (recipients (cdr (assq 'recipients taginfo)))
+              (sender (cdr (assq 'sender taginfo)))
+              (location (cdr (assq 'tag-location taginfo)))
+              (mode (cdr (assq 'mode taginfo)))
+              (method (cdr (assq 'method taginfo)))
+              tags)
+         (save-excursion
+           (if
+               (re-search-forward
+                "<#\\(/\\)?\\(multipart\\|part\\|external\\|mml\\)." nil t)
+               (setq secure-mode "multipart")
+             (setq secure-mode "part")))
+         (save-excursion
+           (goto-char location)
+           (re-search-forward "<#secure[^\n]*>\n"))
+         (delete-region (match-beginning 0) (match-end 0))
+         (cond ((string= mode "sign")
+                (setq tags (list "sign" method)))
+               ((string= mode "encrypt")
+                (setq tags (list "encrypt" method)))
+               ((string= mode "signencrypt")
+                (setq tags (list "sign" method "encrypt" method))))
+         (eval `(mml-insert-tag ,secure-mode
+                                ,@tags
+                                ,(if recipients "recipients")
+                                ,recipients
+                                ,(if sender "sender")
+                                ,sender))
+         ;; restart the parse
+         (goto-char location)))
+       ((looking-at "<#multipart")
+       (push (nconc (mml-read-tag) (mml-parse-1)) struct))
+       ((looking-at "<#external")
+       (push (nconc (mml-read-tag) (list (cons 'contents (mml-read-part))))
+             struct))
+       (t
+       (if (or (looking-at "<#part") (looking-at "<#mml"))
+           (setq tag (mml-read-tag)
+                 no-markup-p nil
+                 warn nil)
+         (setq tag (list 'part '(type . "text/plain"))
+               no-markup-p t
+               warn t))
+       (setq raw (cdr (assq 'raw tag))
+             point (point)
+             contents (mml-read-part (eq 'mml (car tag)))
+             charsets (cond
+                       (raw nil)
+                       ((assq 'charset tag)
+                        (list
+                         (intern (downcase (cdr (assq 'charset tag))))))
+                       (t
+                        (mm-find-mime-charset-region point (point)
+                                                     mm-hack-charsets))))
+       (when (and (not raw) (memq nil charsets))
+         (if (or (memq 'unknown-encoding mml-confirmation-set)
+                 (message-options-get 'unknown-encoding)
+                 (and (y-or-n-p "\
+Message contains characters with unknown encoding.  Really send? ")
+                      (message-options-set 'unknown-encoding t)))
+             (if (setq use-ascii
+                       (or (memq 'use-ascii mml-confirmation-set)
+                           (message-options-get 'use-ascii)
+                           (and (y-or-n-p "Use ASCII as charset? ")
+                                (message-options-set 'use-ascii t))))
+                 (setq charsets (delq nil charsets))
+               (setq warn nil))
+           (error "Edit your message to remove those characters")))
+       (if (or raw
+               (eq 'mml (car tag))
+               (< (length charsets) 2))
+           (if (or (not no-markup-p)
+                   (string-match "[^ \t\r\n]" contents))
+               ;; Don't create blank parts.
+               (push (nconc tag (list (cons 'contents contents)))
+                     struct))
+         (let ((nstruct (mml-parse-singlepart-with-multiple-charsets
+                         tag point (point) use-ascii)))
+           (when (and warn
+                      (not (memq 'multipart mml-confirmation-set))
+                      (not (message-options-get 'multipart))
+                      (not (and (y-or-n-p (format "\
+A message part needs to be split into %d charset parts.  Really send? "
+                                                  (length nstruct)))
+                                (message-options-set 'multipart t))))
+             (error "Edit your message to use only one charset"))
+           (setq struct (nconc nstruct struct)))))))
+    (unless (eobp)
+      (forward-line 1))
+    (nreverse struct)))
+
+(defun mml-parse-singlepart-with-multiple-charsets
+  (orig-tag beg end &optional use-ascii)
+  (save-excursion
+    (save-restriction
+      (narrow-to-region beg end)
+      (goto-char (point-min))
+      (let ((current (or (mm-mime-charset (mm-charset-after))
+                        (and use-ascii 'us-ascii)))
+           charset struct space newline paragraph)
+       (while (not (eobp))
+         (setq charset (mm-mime-charset (mm-charset-after)))
+         (cond
+          ;; The charset remains the same.
+          ((eq charset 'us-ascii))
+          ((or (and use-ascii (not charset))
+               (eq charset current))
+           (setq space nil
+                 newline nil
+                 paragraph nil))
+          ;; The initial charset was ascii.
+          ((eq current 'us-ascii)
+           (setq current charset
+                 space nil
+                 newline nil
+                 paragraph nil))
+          ;; We have a change in charsets.
+          (t
+           (push (append
+                  orig-tag
+                  (list (cons 'contents
+                              (buffer-substring-no-properties
+                               beg (or paragraph newline space (point))))))
+                 struct)
+           (setq beg (or paragraph newline space (point))
+                 current charset
+                 space nil
+                 newline nil
+                 paragraph nil)))
+         ;; Compute places where it might be nice to break the part.
+         (cond
+          ((memq (following-char) '(?  ?\t))
+           (setq space (1+ (point))))
+          ((and (eq (following-char) ?\n)
+                (not (bobp))
+                (eq (char-after (1- (point))) ?\n))
+           (setq paragraph (point)))
+          ((eq (following-char) ?\n)
+           (setq newline (1+ (point)))))
+         (forward-char 1))
+       ;; Do the final part.
+       (unless (= beg (point))
+         (push (append orig-tag
+                       (list (cons 'contents
+                                   (buffer-substring-no-properties
+                                    beg (point)))))
+               struct))
+       struct))))
+
+(defun mml-read-tag ()
+  "Read a tag and return the contents."
+  (let ((orig-point (point))
+       contents name elem val)
+    (forward-char 2)
+    (setq name (buffer-substring-no-properties
+               (point) (progn (forward-sexp 1) (point))))
+    (skip-chars-forward " \t\n")
+    (while (not (looking-at ">[ \t]*\n?"))
+      (setq elem (buffer-substring-no-properties
+                 (point) (progn (forward-sexp 1) (point))))
+      (skip-chars-forward "= \t\n")
+      (setq val (buffer-substring-no-properties
+                (point) (progn (forward-sexp 1) (point))))
+      (when (string-match "^\"\\(.*\\)\"$" val)
+       (setq val (match-string 1 val)))
+      (push (cons (intern elem) val) contents)
+      (skip-chars-forward " \t\n"))
+    (goto-char (match-end 0))
+    ;; Don't skip the leading space.
+    ;;(skip-chars-forward " \t\n")
+    ;; Put the tag location into the returned contents
+    (setq contents (append (list (cons 'tag-location orig-point)) contents))
+    (cons (intern name) (nreverse contents))))
+
+(defun mml-buffer-substring-no-properties-except-hard-newlines (start end)
+  (let ((str (buffer-substring-no-properties start end))
+       (bufstart start) tmp)
+    (while (setq tmp (text-property-any start end 'hard 't))
+      (set-text-properties (- tmp bufstart) (- tmp bufstart -1)
+                          '(hard t) str)
+      (setq start (1+ tmp)))
+    str))
+
+(defun mml-read-part (&optional mml)
+  "Return the buffer up till the next part, multipart or closing part or multipart.
+If MML is non-nil, return the buffer up till the correspondent mml tag."
+  (let ((beg (point)) (count 1))
+    ;; If the tag ended at the end of the line, we go to the next line.
+    (when (looking-at "[ \t]*\n")
+      (forward-line 1))
+    (if mml
+       (progn
+         (while (and (> count 0) (not (eobp)))
+           (if (re-search-forward "<#\\(/\\)?mml." nil t)
+               (setq count (+ count (if (match-beginning 1) -1 1)))
+             (goto-char (point-max))))
+         (mml-buffer-substring-no-properties-except-hard-newlines
+          beg (if (> count 0)
+                  (point)
+                (match-beginning 0))))
+      (if (re-search-forward
+          "<#\\(/\\)?\\(multipart\\|part\\|external\\|mml\\)." nil t)
+         (prog1
+             (mml-buffer-substring-no-properties-except-hard-newlines
+              beg (match-beginning 0))
+           (if (or (not (match-beginning 1))
+                   (equal (match-string 2) "multipart"))
+               (goto-char (match-beginning 0))
+             (when (looking-at "[ \t]*\n")
+               (forward-line 1))))
+       (mml-buffer-substring-no-properties-except-hard-newlines
+        beg (goto-char (point-max)))))))
+
+(defvar mml-boundary nil)
+(defvar mml-base-boundary "-=-=")
+(defvar mml-multipart-number 0)
+
+(defun mml-generate-mime ()
+  "Generate a MIME message based on the current MML document."
+  (let ((cont (mml-parse))
+       (mml-multipart-number mml-multipart-number))
+    (if (not cont)
+       nil
+      (with-temp-buffer
+       (if (and (consp (car cont))
+                (= (length cont) 1))
+           (mml-generate-mime-1 (car cont))
+         (mml-generate-mime-1 (nconc (list 'multipart '(type . "mixed"))
+                                     cont)))
+       (buffer-string)))))
+
+(defun mml-generate-mime-1 (cont)
+  (let ((mm-use-ultra-safe-encoding
+        (or mm-use-ultra-safe-encoding (assq 'sign cont))))
+    (save-restriction
+      (narrow-to-region (point) (point))
+      (mml-tweak-part cont)
+      (cond
+       ((or (eq (car cont) 'part) (eq (car cont) 'mml))
+       (let ((raw (cdr (assq 'raw cont)))
+             coded encoding charset filename type flowed)
+         (setq type (or (cdr (assq 'type cont)) "text/plain"))
+         (if (and (not raw)
+                  (member (car (split-string type "/")) '("text" "message")))
+             (progn
+               (with-temp-buffer
+                 (setq charset (mm-charset-to-coding-system
+                                (cdr (assq 'charset cont))))
+                 (when (eq charset 'ascii)
+                   (setq charset nil))
+                 (cond
+                  ((cdr (assq 'buffer cont))
+                   (insert-buffer-substring (cdr (assq 'buffer cont))))
+                  ((and (setq filename (cdr (assq 'filename cont)))
+                        (not (equal (cdr (assq 'nofile cont)) "yes")))
+                   (let ((coding-system-for-read charset))
+                     (mm-insert-file-contents filename)))
+                  ((eq 'mml (car cont))
+                   (insert (cdr (assq 'contents cont))))
+                  (t
+                   (save-restriction
+                     (narrow-to-region (point) (point))
+                     (insert (cdr (assq 'contents cont)))
+                     ;; Remove quotes from quoted tags.
+                     (goto-char (point-min))
+                     (while (re-search-forward
+                             "<#!+/?\\(part\\|multipart\\|external\\|mml\\)"
+                             nil t)
+                       (delete-region (+ (match-beginning 0) 2)
+                                      (+ (match-beginning 0) 3))))))
+                 (cond
+                  ((eq (car cont) 'mml)
+                   (let ((mml-boundary (mml-compute-boundary cont))
+                         (mml-generate-default-type "text/plain"))
+                     (mml-to-mime))
+                   (let ((mm-7bit-chars (concat mm-7bit-chars "\x1b")))
+                     ;; ignore 0x1b, it is part of iso-2022-jp
+                     (setq encoding (mm-body-7-or-8))))
+                  ((string= (car (split-string type "/")) "message")
+                   (let ((mm-7bit-chars (concat mm-7bit-chars "\x1b")))
+                     ;; ignore 0x1b, it is part of iso-2022-jp
+                     (setq encoding (mm-body-7-or-8))))
+                  (t
+                   ;; Only perform format=flowed filling on text/plain
+                   ;; parts where there either isn't a format parameter
+                   ;; in the mml tag or it says "flowed" and there
+                   ;; actually are hard newlines in the text.
+                   (let (use-hard-newlines)
+                     (when (and (string= type "text/plain")
+                                (or (null (assq 'format cont))
+                                    (string= (cdr (assq 'format cont))
+                                             "flowed"))
+                                (setq use-hard-newlines
+                                      (text-property-any
+                                       (point-min) (point-max) 'hard 't)))
+                       (fill-flowed-encode)
+                       ;; Indicate that `mml-insert-mime-headers' should
+                       ;; insert a "; format=flowed" string unless the
+                       ;; user has already specified it.
+                       (setq flowed (null (assq 'format cont)))))
+                   (setq charset (mm-encode-body charset))
+                   (setq encoding (mm-body-encoding
+                                   charset (cdr (assq 'encoding cont))))))
+                 (setq coded (buffer-string)))
+               (mml-insert-mime-headers cont type charset encoding flowed)
+               (insert "\n")
+               (insert coded))
+           (mm-with-unibyte-buffer
+             (cond
+              ((cdr (assq 'buffer cont))
+               (insert-buffer-substring (cdr (assq 'buffer cont))))
+              ((and (setq filename (cdr (assq 'filename cont)))
+                    (not (equal (cdr (assq 'nofile cont)) "yes")))
+               (let ((coding-system-for-read mm-binary-coding-system))
+                 (mm-insert-file-contents filename nil nil nil nil t)))
+              (t
+               (insert (cdr (assq 'contents cont)))))
+             (setq encoding (mm-encode-buffer type)
+                   coded (mm-string-as-multibyte (buffer-string))))
+           (mml-insert-mime-headers cont type charset encoding nil)
+           (insert "\n")
+           (mm-with-unibyte-current-buffer
+             (insert coded)))))
+       ((eq (car cont) 'external)
+       (insert "Content-Type: message/external-body")
+       (let ((parameters (mml-parameter-string
+                          cont '(expiration size permission)))
+             (name (cdr (assq 'name cont)))
+             (url (cdr (assq 'url cont))))
+         (when name
+           (setq name (mml-parse-file-name name))
+           (if (stringp name)
+               (mml-insert-parameter
+                (mail-header-encode-parameter "name" name)
+                "access-type=local-file")
+             (mml-insert-parameter
+              (mail-header-encode-parameter
+               "name" (file-name-nondirectory (nth 2 name)))
+              (mail-header-encode-parameter "site" (nth 1 name))
+              (mail-header-encode-parameter
+               "directory" (file-name-directory (nth 2 name))))
+             (mml-insert-parameter
+              (concat "access-type="
+                      (if (member (nth 0 name) '("ftp@" "anonymous@"))
+                          "anon-ftp"
+                        "ftp")))))
+         (when url
+           (mml-insert-parameter
+            (mail-header-encode-parameter "url" url)
+            "access-type=url"))
+         (when parameters
+           (mml-insert-parameter-string
+            cont '(expiration size permission))))
+       (insert "\n\n")
+       (insert "Content-Type: " (cdr (assq 'type cont)) "\n")
+       (insert "Content-ID: " (message-make-message-id) "\n")
+       (insert "Content-Transfer-Encoding: "
+               (or (cdr (assq 'encoding cont)) "binary"))
+       (insert "\n\n")
+       (insert (or (cdr (assq 'contents cont))))
+       (insert "\n"))
+       ((eq (car cont) 'multipart)
+       (let* ((type (or (cdr (assq 'type cont)) "mixed"))
+              (mml-generate-default-type (if (equal type "digest")
+                                             "message/rfc822"
+                                           "text/plain"))
+              (handler (assoc type mml-generate-multipart-alist)))
+         (if handler
+             (funcall (cdr handler) cont)
+           ;; No specific handler.  Use default one.
+           (let ((mml-boundary (mml-compute-boundary cont)))
+             (insert (format "Content-Type: multipart/%s; boundary=\"%s\""
+                             type mml-boundary)
+                     (if (cdr (assq 'start cont))
+                         (format "; start=\"%s\"\n" (cdr (assq 'start cont)))
+                       "\n"))
+             (let ((cont cont) part)
+               (while (setq part (pop cont))
+                 ;; Skip `multipart' and attributes.
+                 (when (and (consp part) (consp (cdr part)))
+                   (insert "\n--" mml-boundary "\n")
+                   (mml-generate-mime-1 part))))
+             (insert "\n--" mml-boundary "--\n")))))
+       (t
+       (error "Invalid element: %S" cont)))
+      ;; handle sign & encrypt tags in a semi-smart way.
+      (let ((sign-item (assoc (cdr (assq 'sign cont)) mml-sign-alist))
+           (encrypt-item (assoc (cdr (assq 'encrypt cont))
+                                mml-encrypt-alist))
+           sender recipients)
+       (when (or sign-item encrypt-item)
+         (when (setq sender (cdr (assq 'sender cont)))
+           (message-options-set 'mml-sender sender)
+           (message-options-set 'message-sender sender))
+         (if (setq recipients (cdr (assq 'recipients cont)))
+             (message-options-set 'message-recipients recipients))
+         (let ((style (mml-signencrypt-style (first (or sign-item encrypt-item)))))
+           ;; check if: we're both signing & encrypting, both methods
+           ;; are the same (why would they be different?!), and that
+           ;; the signencrypt style allows for combined operation.
+           (if (and sign-item encrypt-item (equal (first sign-item)
+                                                  (first encrypt-item))
+                    (equal style 'combined))
+               (funcall (nth 1 encrypt-item) cont t)
+             ;; otherwise, revert to the old behavior.
+             (when sign-item
+               (funcall (nth 1 sign-item) cont))
+             (when encrypt-item
+               (funcall (nth 1 encrypt-item) cont)))))))))
+
+(defun mml-compute-boundary (cont)
+  "Return a unique boundary that does not exist in CONT."
+  (let ((mml-boundary (funcall mml-boundary-function
+                              (incf mml-multipart-number))))
+    ;; This function tries again and again until it has found
+    ;; a unique boundary.
+    (while (not (catch 'not-unique
+                 (mml-compute-boundary-1 cont))))
+    mml-boundary))
+
+(defun mml-compute-boundary-1 (cont)
+  (let (filename)
+    (cond
+     ((eq (car cont) 'part)
+      (with-temp-buffer
+       (cond
+        ((cdr (assq 'buffer cont))
+         (insert-buffer-substring (cdr (assq 'buffer cont))))
+        ((and (setq filename (cdr (assq 'filename cont)))
+              (not (equal (cdr (assq 'nofile cont)) "yes")))
+         (mm-insert-file-contents filename))
+        (t
+         (insert (cdr (assq 'contents cont)))))
+       (goto-char (point-min))
+       (when (re-search-forward (concat "^--" (regexp-quote mml-boundary))
+                                nil t)
+         (setq mml-boundary (funcall mml-boundary-function
+                                     (incf mml-multipart-number)))
+         (throw 'not-unique nil))))
+     ((eq (car cont) 'multipart)
+      (mapcar 'mml-compute-boundary-1 (cddr cont))))
+    t))
+
+(defun mml-make-boundary (number)
+  (concat (make-string (% number 60) ?=)
+         (if (> number 17)
+             (format "%x" number)
+           "")
+         mml-base-boundary))
+
+(defun mml-insert-mime-headers (cont type charset encoding flowed)
+  (let (parameters id disposition description)
+    (setq parameters
+         (mml-parameter-string
+          cont mml-content-type-parameters))
+    (when (or charset
+             parameters
+             flowed
+             (not (equal type mml-generate-default-type))
+             mml-insert-mime-headers-always)
+      (when (consp charset)
+       (error
+        "Can't encode a part with several charsets"))
+      (insert "Content-Type: " type)
+      (when charset
+       (insert "; " (mail-header-encode-parameter
+                     "charset" (symbol-name charset))))
+      (when flowed
+       (insert "; format=flowed"))
+      (when parameters
+       (mml-insert-parameter-string
+        cont mml-content-type-parameters))
+      (insert "\n"))
+    (when (setq id (cdr (assq 'id cont)))
+      (insert "Content-ID: " id "\n"))
+    (setq parameters
+         (mml-parameter-string
+          cont mml-content-disposition-parameters))
+    (when (or (setq disposition (cdr (assq 'disposition cont)))
+             parameters)
+      (insert "Content-Disposition: " (or disposition "inline"))
+      (when parameters
+       (mml-insert-parameter-string
+        cont mml-content-disposition-parameters))
+      (insert "\n"))
+    (unless (eq encoding '7bit)
+      (insert (format "Content-Transfer-Encoding: %s\n" encoding)))
+    (when (setq description (cdr (assq 'description cont)))
+      (insert "Content-Description: "
+             (mail-encode-encoded-word-string description) "\n"))))
+
+(defun mml-parameter-string (cont types)
+  (let ((string "")
+       value type)
+    (while (setq type (pop types))
+      (when (setq value (cdr (assq type cont)))
+       ;; Strip directory component from the filename parameter.
+       (when (eq type 'filename)
+         (setq value (file-name-nondirectory value)))
+       (setq string (concat string "; "
+                            (mail-header-encode-parameter
+                             (symbol-name type) value)))))
+    (when (not (zerop (length string)))
+      string)))
+
+(defun mml-insert-parameter-string (cont types)
+  (let (value type)
+    (while (setq type (pop types))
+      (when (setq value (cdr (assq type cont)))
+       ;; Strip directory component from the filename parameter.
+       (when (eq type 'filename)
+         (setq value (file-name-nondirectory value)))
+       (mml-insert-parameter
+        (mail-header-encode-parameter
+         (symbol-name type) value))))))
+
+(eval-when-compile
+  (defvar ange-ftp-name-format)
+  (defvar efs-path-regexp))
+(defun mml-parse-file-name (path)
+  (if (if (boundp 'efs-path-regexp)
+         (string-match efs-path-regexp path)
+       (if (boundp 'ange-ftp-name-format)
+           (string-match (car ange-ftp-name-format) path)))
+      (list (match-string 1 path) (match-string 2 path)
+           (substring path (1+ (match-end 2))))
+    path))
+
+(defun mml-insert-buffer (buffer)
+  "Insert BUFFER at point and quote any MML markup."
+  (save-restriction
+    (narrow-to-region (point) (point))
+    (insert-buffer-substring buffer)
+    (mml-quote-region (point-min) (point-max))
+    (goto-char (point-max))))
+
+;;;
+;;; Transforming MIME to MML
+;;;
+
+(defun mime-to-mml (&optional handles)
+  "Translate the current buffer (which should be a message) into MML.
+If HANDLES is non-nil, use it instead reparsing the buffer."
+  ;; First decode the head.
+  (save-restriction
+    (message-narrow-to-head)
+    (mail-decode-encoded-word-region (point-min) (point-max)))
+  (unless handles
+    (setq handles (mm-dissect-buffer t)))
+  (goto-char (point-min))
+  (search-forward "\n\n" nil t)
+  (delete-region (point) (point-max))
+  (if (stringp (car handles))
+      (mml-insert-mime handles)
+    (mml-insert-mime handles t))
+  (mm-destroy-parts handles)
+  (save-restriction
+    (message-narrow-to-head)
+    ;; Remove them, they are confusing.
+    (message-remove-header "Content-Type")
+    (message-remove-header "MIME-Version")
+    (message-remove-header "Content-Disposition")
+    (message-remove-header "Content-Transfer-Encoding")))
+
+(defun mml-to-mime ()
+  "Translate the current buffer from MML to MIME."
+  (message-encode-message-body)
+  (save-restriction
+    (message-narrow-to-headers-or-head)
+    ;; Skip past any From_ headers.
+    (while (looking-at "From ")
+      (forward-line 1))
+    (let ((mail-parse-charset message-default-charset))
+      (mail-encode-encoded-word-buffer))))
+
+(defun mml-insert-mime (handle &optional no-markup)
+  (let (textp buffer mmlp)
+    ;; Determine type and stuff.
+    (unless (stringp (car handle))
+      (unless (setq textp (equal (mm-handle-media-supertype handle) "text"))
+       (save-excursion
+         (set-buffer (setq buffer (mml-generate-new-buffer " *mml*")))
+         (mm-insert-part handle)
+         (if (setq mmlp (equal (mm-handle-media-type handle)
+                               "message/rfc822"))
+             (mime-to-mml)))))
+    (if mmlp
+       (mml-insert-mml-markup handle nil t t)
+      (unless (and no-markup
+                  (equal (mm-handle-media-type handle) "text/plain"))
+       (mml-insert-mml-markup handle buffer textp)))
+    (cond
+     (mmlp
+      (insert-buffer-substring buffer)
+      (goto-char (point-max))
+      (insert "<#/mml>\n"))
+     ((stringp (car handle))
+      (mapcar 'mml-insert-mime (cdr handle))
+      (insert "<#/multipart>\n"))
+     (textp
+      (let ((charset (mail-content-type-get
+                     (mm-handle-type handle) 'charset))
+           (start (point)))
+       (if (eq charset 'gnus-decoded)
+           (mm-insert-part handle)
+         (insert (mm-decode-string (mm-get-part handle) charset)))
+       (mml-quote-region start (point)))
+      (goto-char (point-max)))
+     (t
+      (insert "<#/part>\n")))))
+
+(defun mml-insert-mml-markup (handle &optional buffer nofile mmlp)
+  "Take a MIME handle and insert an MML tag."
+  (if (stringp (car handle))
+      (progn
+       (insert "<#multipart type=" (mm-handle-media-subtype handle))
+       (let ((start (mm-handle-multipart-ctl-parameter handle 'start)))
+         (when start
+           (insert " start=\"" start "\"")))
+       (insert ">\n"))
+    (if mmlp
+       (insert "<#mml type=" (mm-handle-media-type handle))
+      (insert "<#part type=" (mm-handle-media-type handle)))
+    (dolist (elem (append (cdr (mm-handle-type handle))
+                         (cdr (mm-handle-disposition handle))))
+      (unless (symbolp (cdr elem))
+       (insert " " (symbol-name (car elem)) "=\"" (cdr elem) "\"")))
+    (when (mm-handle-id handle)
+      (insert " id=\"" (mm-handle-id handle) "\""))
+    (when (mm-handle-disposition handle)
+      (insert " disposition=" (car (mm-handle-disposition handle))))
+    (when buffer
+      (insert " buffer=\"" (buffer-name buffer) "\""))
+    (when nofile
+      (insert " nofile=yes"))
+    (when (mm-handle-description handle)
+      (insert " description=\"" (mm-handle-description handle) "\""))
+    (insert ">\n")))
+
+(defun mml-insert-parameter (&rest parameters)
+  "Insert PARAMETERS in a nice way."
+  (dolist (param parameters)
+    (insert ";")
+    (let ((point (point)))
+      (insert " " param)
+      (when (> (current-column) 71)
+       (goto-char point)
+       (insert "\n ")
+       (end-of-line)))))
+
+;;;
+;;; Mode for inserting and editing MML forms
+;;;
+
+(defvar mml-mode-map
+  (let ((sign (make-sparse-keymap))
+       (encrypt (make-sparse-keymap))
+       (signpart (make-sparse-keymap))
+       (encryptpart (make-sparse-keymap))
+       (map (make-sparse-keymap))
+       (main (make-sparse-keymap)))
+    (define-key sign "p" 'mml-secure-message-sign-pgpmime)
+    (define-key sign "o" 'mml-secure-message-sign-pgp)
+    (define-key sign "s" 'mml-secure-message-sign-smime)
+    (define-key signpart "p" 'mml-secure-sign-pgpmime)
+    (define-key signpart "o" 'mml-secure-sign-pgp)
+    (define-key signpart "s" 'mml-secure-sign-smime)
+    (define-key encrypt "p" 'mml-secure-message-encrypt-pgpmime)
+    (define-key encrypt "o" 'mml-secure-message-encrypt-pgp)
+    (define-key encrypt "s" 'mml-secure-message-encrypt-smime)
+    (define-key encryptpart "p" 'mml-secure-encrypt-pgpmime)
+    (define-key encryptpart "o" 'mml-secure-encrypt-pgp)
+    (define-key encryptpart "s" 'mml-secure-encrypt-smime)
+    (define-key map "\C-n" 'mml-unsecure-message)
+    (define-key map "f" 'mml-attach-file)
+    (define-key map "b" 'mml-attach-buffer)
+    (define-key map "e" 'mml-attach-external)
+    (define-key map "q" 'mml-quote-region)
+    (define-key map "m" 'mml-insert-multipart)
+    (define-key map "p" 'mml-insert-part)
+    (define-key map "v" 'mml-validate)
+    (define-key map "P" 'mml-preview)
+    (define-key map "s" sign)
+    (define-key map "S" signpart)
+    (define-key map "c" encrypt)
+    (define-key map "C" encryptpart)
+    ;;(define-key map "n" 'mml-narrow-to-part)
+    ;; `M-m' conflicts with `back-to-indentation'.
+    ;; (define-key main "\M-m" map)
+    (define-key main "\C-c\C-m" map)
+    main))
+
+(easy-menu-define
+ mml-menu mml-mode-map ""
+ `("Attachments"
+   ["Attach File..." mml-attach-file
+    ,@(if (featurep 'xemacs) '(t)
+       '(:help "Attach a file at point"))]
+   ["Attach Buffer..." mml-attach-buffer t]
+   ["Attach External..." mml-attach-external t]
+   ["Insert Part..." mml-insert-part t]
+   ["Insert Multipart..." mml-insert-multipart t]
+   ["PGP/MIME Sign" mml-secure-message-sign-pgpmime t]
+   ["PGP/MIME Encrypt" mml-secure-message-encrypt-pgpmime t]
+   ["PGP Sign" mml-secure-message-sign-pgp t]
+   ["PGP Encrypt" mml-secure-message-encrypt-pgp t]
+   ["S/MIME Sign" mml-secure-message-sign-smime t]
+   ["S/MIME Encrypt" mml-secure-message-encrypt-smime t]
+   ("Secure MIME part"
+    ["PGP/MIME Sign Part" mml-secure-sign-pgpmime t]
+    ["PGP/MIME Encrypt Part" mml-secure-encrypt-pgpmime t]
+    ["PGP Sign Part" mml-secure-sign-pgp t]
+    ["PGP Encrypt Part" mml-secure-encrypt-pgp t]
+    ["S/MIME Sign Part" mml-secure-sign-smime t]
+    ["S/MIME Encrypt Part" mml-secure-encrypt-smime t])
+   ["Encrypt/Sign off" mml-unsecure-message t]
+   ;;["Narrow" mml-narrow-to-part t]
+   ["Quote MML" mml-quote-region t]
+   ["Validate MML" mml-validate t]
+   ["Preview" mml-preview t]))
+
+(defvar mml-mode nil
+  "Minor mode for editing MML.")
+
+(defun mml-mode (&optional arg)
+  "Minor mode for editing MML.
+MML is the MIME Meta Language, a minor mode for composing MIME articles.
+See Info node `(emacs-mime)Composing'.
+
+\\{mml-mode-map}"
+  (interactive "P")
+  (when (set (make-local-variable 'mml-mode)
+            (if (null arg) (not mml-mode)
+              (> (prefix-numeric-value arg) 0)))
+    (gnus-add-minor-mode 'mml-mode " MML" mml-mode-map)
+    (easy-menu-add mml-menu mml-mode-map)
+    (run-hooks 'mml-mode-hook)))
+
+;;;
+;;; Helper functions for reading MIME stuff from the minibuffer and
+;;; inserting stuff to the buffer.
+;;;
+
+(defun mml-minibuffer-read-file (prompt)
+  (let* ((completion-ignored-extensions nil)
+        (file (read-file-name prompt nil nil t)))
+    ;; Prevent some common errors.  This is inspired by similar code in
+    ;; VM.
+    (when (file-directory-p file)
+      (error "%s is a directory, cannot attach" file))
+    (unless (file-exists-p file)
+      (error "No such file: %s" file))
+    (unless (file-readable-p file)
+      (error "Permission denied: %s" file))
+    file))
+
+(defun mml-minibuffer-read-type (name &optional default)
+  (mailcap-parse-mimetypes)
+  (let* ((default (or default
+                     (mm-default-file-encoding name)
+                     ;; Perhaps here we should check what the file
+                     ;; looks like, and offer text/plain if it looks
+                     ;; like text/plain.
+                     "application/octet-stream"))
+        (string (completing-read
+                 (format "Content type (default %s): " default)
+                 (mapcar 'list (mailcap-mime-types)))))
+    (if (not (equal string ""))
+       string
+      default)))
+
+(defun mml-minibuffer-read-description ()
+  (let ((description (read-string "One line description: ")))
+    (when (string-match "\\`[ \t]*\\'" description)
+      (setq description nil))
+    description))
+
+(defun mml-minibuffer-read-disposition (type &optional default)
+  (let* ((default (or default
+                     (if (string-match "^text/.*" type)
+                         "inline"
+                       "attachment")))
+        (disposition (completing-read "Disposition: "
+                                      '(("attachment") ("inline") (""))
+                                      nil
+                                      nil)))
+    (if (not (equal disposition ""))
+       disposition
+      default)))
+
+(defun mml-quote-region (beg end)
+  "Quote the MML tags in the region."
+  (interactive "r")
+  (save-excursion
+    (save-restriction
+      ;; Temporarily narrow the region to defend from changes
+      ;; invalidating END.
+      (narrow-to-region beg end)
+      (goto-char (point-min))
+      ;; Quote parts.
+      (while (re-search-forward
+             "<#!*/?\\(multipart\\|part\\|external\\|mml\\)" nil t)
+       ;; Insert ! after the #.
+       (goto-char (+ (match-beginning 0) 2))
+       (insert "!")))))
+
+(defun mml-insert-tag (name &rest plist)
+  "Insert an MML tag described by NAME and PLIST."
+  (when (symbolp name)
+    (setq name (symbol-name name)))
+  (insert "<#" name)
+  (while plist
+    (let ((key (pop plist))
+         (value (pop plist)))
+      (when value
+       ;; Quote VALUE if it contains suspicious characters.
+       (when (string-match "[\"'\\~/*;() \t\n]" value)
+         (setq value (with-output-to-string
+                       (let (print-escape-nonascii)
+                         (prin1 value)))))
+       (insert (format " %s=%s" key value)))))
+  (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.
+
+(defun mml-attach-file (file &optional type description disposition)
+  "Attach a file to the outgoing MIME message.
+The file is not inserted or encoded until you send the message with
+`\\[message-send-and-exit]' or `\\[message-send]'.
+
+FILE is the name of the file to attach.  TYPE is its content-type, a
+string of the form \"type/subtype\".  DESCRIPTION is a one-line
+description of the attachment."
+  (interactive
+   (let* ((file (mml-minibuffer-read-file "Attach file: "))
+         (type (mml-minibuffer-read-type file))
+         (description (mml-minibuffer-read-description))
+         (disposition (mml-minibuffer-read-disposition type)))
+     (list file type description disposition)))
+  (mml-insert-empty-tag 'part
+                       'type type
+                       'filename file
+                       'disposition (or disposition "attachment")
+                       'description description))
+
+(defun mml-attach-buffer (buffer &optional type description)
+  "Attach a buffer to the outgoing MIME message.
+See `mml-attach-file' for details of operation."
+  (interactive
+   (let* ((buffer (read-buffer "Attach buffer: "))
+         (type (mml-minibuffer-read-type buffer "text/plain"))
+         (description (mml-minibuffer-read-description)))
+     (list buffer type 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.
+FILE is an ange-ftp/efs specification of the part location.
+TYPE is the MIME type to use."
+  (interactive
+   (let* ((file (mml-minibuffer-read-file "Attach external file: "))
+         (type (mml-minibuffer-read-type file))
+         (description (mml-minibuffer-read-description)))
+     (list file type 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): "
+                                     '(("mixed") ("alternative") ("digest") ("parallel")
+                                       ("signed") ("encrypted"))
+                                     nil nil "mixed")))
+  (or type
+      (setq type "mixed"))
+  (mml-insert-empty-tag "multipart" 'type type)
+  (forward-line -1))
+
+(defun mml-insert-part (&optional type)
+  (interactive
+   (list (mml-minibuffer-read-type "")))
+  (mml-insert-tag 'part 'type type 'disposition "inline")
+  (forward-line -1))
+
+(defun mml-preview-insert-mail-followup-to ()
+  "Insert a Mail-Followup-To header before previewing an article.
+Should be adopted if code in `message-send-mail' is changed."
+  (when (and (message-mail-p)
+            (message-subscribed-p)
+            (not (mail-fetch-field "mail-followup-to"))
+            (message-make-mail-followup-to))
+    (message-position-on-field "Mail-Followup-To" "X-Draft-From")
+    (insert (message-make-mail-followup-to))))
+
+(defun mml-preview (&optional raw)
+  "Display current buffer with Gnus, in a new buffer.
+If RAW, don't highlight the article."
+  (interactive "P")
+  (save-excursion
+    (let* ((buf (current-buffer))
+          (message-options message-options)
+          (message-this-is-mail (message-mail-p))
+          (message-this-is-news (message-news-p))
+          (message-posting-charset (or (gnus-setup-posting-charset
+                                        (save-restriction
+                                          (message-narrow-to-headers-or-head)
+                                          (message-fetch-field "Newsgroups")))
+                                       message-posting-charset)))
+      (message-options-set-recipient)
+      (switch-to-buffer (generate-new-buffer
+                        (concat (if raw "*Raw MIME preview of "
+                                  "*MIME preview of ") (buffer-name))))
+      (when (boundp 'gnus-buffers)
+       (push (current-buffer) gnus-buffers))
+      (erase-buffer)
+      (insert-buffer-substring buf)
+      (mml-preview-insert-mail-followup-to)
+      (let ((message-deletable-headers (if (message-news-p)
+                                          nil
+                                        message-deletable-headers)))
+       (message-generate-headers
+        (copy-sequence (if (message-news-p)
+                           message-required-news-headers
+                         message-required-mail-headers))))
+      (if (re-search-forward
+          (concat "^" (regexp-quote mail-header-separator) "\n") nil t)
+         (replace-match "\n"))
+      (let ((mail-header-separator ""));; mail-header-separator is removed.
+       (mml-to-mime))
+      (if raw
+         (when (fboundp 'set-buffer-multibyte)
+           (let ((s (buffer-string)))
+             ;; Insert the content into unibyte buffer.
+             (erase-buffer)
+             (mm-disable-multibyte)
+             (insert s)))
+       (let ((gnus-newsgroup-charset (car message-posting-charset))
+             gnus-article-prepare-hook gnus-original-article-buffer)
+         (run-hooks 'gnus-article-decode-hook)
+         (let ((gnus-newsgroup-name "dummy")
+               (gnus-newsrc-hashtb (or gnus-newsrc-hashtb
+                                       (gnus-make-hashtable 5))))
+           (gnus-article-prepare-display))))
+      ;; Disable article-mode-map.
+      (use-local-map nil)
+      (gnus-make-local-hook 'kill-buffer-hook)
+      (add-hook 'kill-buffer-hook
+               (lambda ()
+                 (mm-destroy-parts gnus-article-mime-handles)) nil t)
+      (setq buffer-read-only t)
+      (local-set-key "q" (lambda () (interactive) (kill-buffer nil)))
+      (local-set-key "=" (lambda () (interactive) (delete-other-windows)))
+      (local-set-key "\r"
+                    (lambda ()
+                      (interactive)
+                      (widget-button-press (point))))
+      (local-set-key gnus-mouse-2
+                    (lambda (event)
+                      (interactive "@e")
+                      (widget-button-press (widget-event-point event) event)))
+      (goto-char (point-min)))))
+
+(defun mml-validate ()
+  "Validate the current MML document."
+  (interactive)
+  (mml-parse))
+
+(defun mml-tweak-part (cont)
+  "Tweak a MML part."
+  (let ((tweak (cdr (assq 'tweak cont)))
+       func)
+    (cond
+     (tweak
+      (setq func
+           (or (cdr (assoc tweak mml-tweak-function-alist))
+               (intern tweak))))
+     (mml-tweak-type-alist
+      (let ((alist mml-tweak-type-alist)
+           (type (or (cdr (assq 'type cont)) "text/plain")))
+       (while alist
+         (if (string-match (caar alist) type)
+             (setq func (cdar alist)
+                   alist nil)
+           (setq alist (cdr alist)))))))
+    (if func
+       (funcall func cont)
+      cont)
+    (let ((alist mml-tweak-sexp-alist))
+      (while alist
+       (if (eval (caar alist))
+           (funcall (cdar alist) cont))
+       (setq alist (cdr alist)))))
+  cont)
+
+(defun mml-tweak-externalize-attachments (cont)
+  "Tweak attached files as external parts."
+  (let (filename-cons)
+    (when (and (eq (car cont) 'part)
+              (not (cdr (assq 'buffer cont)))
+              (and (setq filename-cons (assq 'filename cont))
+                   (not (equal (cdr (assq 'nofile cont)) "yes"))))
+      (setcar cont 'external)
+      (setcar filename-cons 'name))))
+
+(provide 'mml)
+
+;;; mml.el ends here
diff --git a/lisp/mml1991.el b/lisp/mml1991.el
new file mode 100644 (file)
index 0000000..dbd980b
--- /dev/null
@@ -0,0 +1,306 @@
+;;; mml1991.el --- Old PGP message format (RFC 1991) support for MML
+;; Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Sascha Ldecke <sascha@meta-x.de>,
+;;     Simon Josefsson <simon@josefsson.org> (Mailcrypt interface, Gnus glue)
+;; Keywords PGP
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)
+  (require 'mm-util))
+
+(autoload 'quoted-printable-decode-region "qp")
+(autoload 'quoted-printable-encode-region "qp")
+
+(defvar mml1991-use mml2015-use
+  "The package used for PGP.")
+
+(defvar mml1991-function-alist
+  '((mailcrypt mml1991-mailcrypt-sign
+              mml1991-mailcrypt-encrypt)
+    (gpg mml1991-gpg-sign
+        mml1991-gpg-encrypt)
+    (pgg mml1991-pgg-sign
+        mml1991-pgg-encrypt))
+  "Alist of PGP functions.")
+
+;;; mailcrypt wrapper
+
+(eval-and-compile
+  (autoload 'mc-sign-generic "mc-toplev"))
+
+(defvar mml1991-decrypt-function 'mailcrypt-decrypt)
+(defvar mml1991-verify-function 'mailcrypt-verify)
+
+(defun mml1991-mailcrypt-sign (cont)
+  (let ((text (current-buffer))
+       headers signature
+       (result-buffer (get-buffer-create "*GPG Result*")))
+    ;; Save MIME Content[^ ]+: headers from signing
+    (goto-char (point-min))
+    (while (looking-at "^Content[^ ]+:") (forward-line))
+    (unless (bobp)
+      (setq headers (buffer-string))
+      (delete-region (point-min) (point)))
+    (goto-char (point-max))
+    (unless (bolp)
+      (insert "\n"))
+    (quoted-printable-decode-region (point-min) (point-max))
+    (with-temp-buffer
+      (setq signature (current-buffer))
+      (insert-buffer-substring text)
+      (unless (mc-sign-generic (message-options-get 'message-sender)
+                              nil nil nil nil)
+       (unless (> (point-max) (point-min))
+         (pop-to-buffer result-buffer)
+         (error "Sign error")))
+      (goto-char (point-min))
+      (while (re-search-forward "\r+$" nil t)
+       (replace-match "" t t))
+      (quoted-printable-encode-region (point-min) (point-max))
+      (set-buffer text)
+      (delete-region (point-min) (point-max))
+      (if headers (insert headers))
+      (insert "\n")
+      (insert-buffer-substring signature)
+      (goto-char (point-max)))))
+
+(defun mml1991-mailcrypt-encrypt (cont &optional sign)
+  (let ((text (current-buffer))
+       (mc-pgp-always-sign
+        (or mc-pgp-always-sign
+            sign
+            (eq t (or (message-options-get 'message-sign-encrypt)
+                      (message-options-set
+                       'message-sign-encrypt
+                       (or (y-or-n-p "Sign the message? ")
+                           'not))))
+            'never))
+       cipher
+       (result-buffer (get-buffer-create "*GPG Result*")))
+    ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED
+    (goto-char (point-min))
+    (while (looking-at "^Content[^ ]+:") (forward-line))
+    (unless (bobp)
+      (delete-region (point-min) (point)))
+    (mm-with-unibyte-current-buffer
+      (with-temp-buffer
+       (setq cipher (current-buffer))
+       (insert-buffer-substring text)
+       (unless (mc-encrypt-generic
+                (or
+                 (message-options-get 'message-recipients)
+                 (message-options-set 'message-recipients
+                                      (read-string "Recipients: ")))
+                nil
+                (point-min) (point-max)
+                (message-options-get 'message-sender)
+                'sign)
+         (unless (> (point-max) (point-min))
+           (pop-to-buffer result-buffer)
+           (error "Encrypt error")))
+       (goto-char (point-min))
+       (while (re-search-forward "\r+$" nil t)
+         (replace-match "" t t))
+       (set-buffer text)
+       (delete-region (point-min) (point-max))
+       ;;(insert "Content-Type: application/pgp-encrypted\n\n")
+       ;;(insert "Version: 1\n\n")
+       (insert "\n")
+       (insert-buffer-substring cipher)
+       (goto-char (point-max))))))
+
+;;; gpg wrapper
+
+(eval-and-compile
+  (autoload 'gpg-sign-cleartext "gpg"))
+
+(defun mml1991-gpg-sign (cont)
+  (let ((text (current-buffer))
+       headers signature
+       (result-buffer (get-buffer-create "*GPG Result*")))
+    ;; Save MIME Content[^ ]+: headers from signing
+    (goto-char (point-min))
+    (while (looking-at "^Content[^ ]+:") (forward-line))
+    (unless (bobp)
+      (setq headers (buffer-string))
+      (delete-region (point-min) (point)))
+    (goto-char (point-max))
+    (unless (bolp)
+      (insert "\n"))
+    (quoted-printable-decode-region (point-min) (point-max))
+    (with-temp-buffer
+      (unless (gpg-sign-cleartext text (setq signature (current-buffer))
+                                 result-buffer
+                                 nil
+                                 (message-options-get 'message-sender))
+       (unless (> (point-max) (point-min))
+         (pop-to-buffer result-buffer)
+         (error "Sign error")))
+      (goto-char (point-min))
+      (while (re-search-forward "\r+$" nil t)
+       (replace-match "" t t))
+      (quoted-printable-encode-region (point-min) (point-max))
+      (set-buffer text)
+      (delete-region (point-min) (point-max))
+      (if headers (insert headers))
+      (insert "\n")
+      (insert-buffer-substring signature)
+      (goto-char (point-max)))))
+
+(defun mml1991-gpg-encrypt (cont &optional sign)
+  (let ((text (current-buffer))
+       cipher
+       (result-buffer (get-buffer-create "*GPG Result*")))
+    ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED
+    (goto-char (point-min))
+    (while (looking-at "^Content[^ ]+:") (forward-line))
+    (unless (bobp)
+      (delete-region (point-min) (point)))
+    (mm-with-unibyte-current-buffer
+      (with-temp-buffer
+       (flet ((gpg-encrypt-func 
+               (sign plaintext ciphertext result recipients &optional
+                     passphrase sign-with-key armor textmode)
+               (if sign
+                   (gpg-sign-encrypt
+                    plaintext ciphertext result recipients passphrase
+                    sign-with-key armor textmode)
+                 (gpg-encrypt
+                  plaintext ciphertext result recipients passphrase
+                  armor textmode))))
+         (unless (gpg-encrypt-func
+                  sign
+                  text (setq cipher (current-buffer))
+                  result-buffer
+                  (split-string
+                   (or
+                    (message-options-get 'message-recipients)
+                    (message-options-set 'message-recipients
+                                         (read-string "Recipients: ")))
+                   "[ \f\t\n\r\v,]+")
+                  nil
+                  (message-options-get 'message-sender)
+                  t t) ; armor & textmode
+           (unless (> (point-max) (point-min))
+             (pop-to-buffer result-buffer)
+             (error "Encrypt error"))))
+       (goto-char (point-min))
+       (while (re-search-forward "\r+$" nil t)
+         (replace-match "" t t))
+       (set-buffer text)
+       (delete-region (point-min) (point-max))
+       ;;(insert "Content-Type: application/pgp-encrypted\n\n")
+       ;;(insert "Version: 1\n\n")
+       (insert "\n")
+       (insert-buffer-substring cipher)
+       (goto-char (point-max))))))
+
+;; pgg wrapper
+
+(defvar pgg-output-buffer)
+(defvar pgg-errors-buffer)
+
+(defun mml1991-pgg-sign (cont)
+  (let (headers cte)
+    ;; Don't sign headers.
+    (goto-char (point-min))
+    (while (not (looking-at "^$"))
+      (forward-line))
+    (unless (eobp) ;; no headers?
+      (setq headers (buffer-substring (point-min) (point)))
+      (forward-line) ;; skip header/body separator
+      (delete-region (point-min) (point)))
+    (when (string-match "^Content-Transfer-Encoding: \\(.+\\)" headers)
+      (setq cte (intern (match-string 1 headers))))
+    (mm-decode-content-transfer-encoding cte)
+    (unless (let ((pgg-default-user-id
+                  (or (message-options-get 'mml-sender)
+                      pgg-default-user-id)))
+             (pgg-sign-region (point-min) (point-max) t))
+      (pop-to-buffer pgg-errors-buffer)
+      (error "Encrypt error"))
+    (delete-region (point-min) (point-max))
+    (mm-with-unibyte-current-buffer
+      (insert-buffer-substring pgg-output-buffer)
+      (goto-char (point-min))
+      (while (re-search-forward "\r+$" nil t)
+       (replace-match "" t t))
+      (mm-encode-content-transfer-encoding cte)
+      (goto-char (point-min))
+      (when headers
+       (insert headers))
+      (insert "\n"))
+    t))
+
+(defun mml1991-pgg-encrypt (cont &optional sign)
+  (let (cte)
+    ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMOURED
+    (goto-char (point-min))
+    (while (looking-at "^Content[^ ]+:")
+      (when (looking-at "^Content-Transfer-Encoding: \\(.+\\)")
+       (setq cte (intern (match-string 1))))
+      (forward-line))
+    (unless (bobp)
+      (delete-region (point-min) (point)))
+    (mm-decode-content-transfer-encoding cte)
+    (unless (pgg-encrypt-region
+            (point-min) (point-max) 
+            (split-string
+             (or
+              (message-options-get 'message-recipients)
+              (message-options-set 'message-recipients
+                                   (read-string "Recipients: ")))
+             "[ \f\t\n\r\v,]+")
+            sign)
+      (pop-to-buffer pgg-errors-buffer)
+      (error "Encrypt error"))
+    (delete-region (point-min) (point-max))
+    ;;(insert "Content-Type: application/pgp-encrypted\n\n")
+    ;;(insert "Version: 1\n\n")
+    (insert "\n")
+    (insert-buffer-substring pgg-output-buffer)
+    t))
+
+;;;###autoload
+(defun mml1991-encrypt (cont &optional sign)
+  (let ((func (nth 2 (assq mml1991-use mml1991-function-alist))))
+    (if func
+       (funcall func cont sign)
+      (error "Cannot find encrypt function"))))
+
+;;;###autoload
+(defun mml1991-sign (cont)
+  (let ((func (nth 1 (assq mml1991-use mml1991-function-alist))))
+    (if func
+       (funcall func cont)
+      (error "Cannot find sign function"))))
+
+(provide 'mml1991)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; mml1991.el ends here
diff --git a/lisp/mml2015.el b/lisp/mml2015.el
new file mode 100644 (file)
index 0000000..6bf4f4e
--- /dev/null
@@ -0,0 +1,918 @@
+;;; mml2015.el --- MIME Security with Pretty Good Privacy (PGP)
+;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: PGP MIME MML
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; RFC 2015 is updated by RFC 3156, this file should be compatible
+;; with both.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+(require 'mm-decode)
+(require 'mm-util)
+(require 'mml)
+
+(defvar mml2015-use (or
+                    (progn
+                      (ignore-errors
+                        (require 'pgg))
+                      (and (fboundp 'pgg-sign-region)
+                           'pgg))
+                    (progn
+                      (ignore-errors
+                        (require 'gpg))
+                      (and (fboundp 'gpg-sign-detached)
+                           'gpg))
+                    (progn (ignore-errors
+                             (load "mc-toplev"))
+                           (and (fboundp 'mc-encrypt-generic)
+                                (fboundp 'mc-sign-generic)
+                                (fboundp 'mc-cleanup-recipient-headers)
+                                'mailcrypt)))
+  "The package used for PGP/MIME.")
+
+;; Something is not RFC2015.
+(defvar mml2015-function-alist
+  '((mailcrypt mml2015-mailcrypt-sign
+              mml2015-mailcrypt-encrypt
+              mml2015-mailcrypt-verify
+              mml2015-mailcrypt-decrypt
+              mml2015-mailcrypt-clear-verify
+              mml2015-mailcrypt-clear-decrypt)
+    (gpg mml2015-gpg-sign
+        mml2015-gpg-encrypt
+        mml2015-gpg-verify
+        mml2015-gpg-decrypt
+        mml2015-gpg-clear-verify
+        mml2015-gpg-clear-decrypt)
+  (pgg mml2015-pgg-sign
+       mml2015-pgg-encrypt
+       mml2015-pgg-verify
+       mml2015-pgg-decrypt
+       mml2015-pgg-clear-verify
+       mml2015-pgg-clear-decrypt))
+  "Alist of PGP/MIME functions.")
+
+(defvar mml2015-result-buffer nil)
+
+(defcustom mml2015-unabbrev-trust-alist
+  '(("TRUST_UNDEFINED" . nil)
+    ("TRUST_NEVER"     . nil)
+    ("TRUST_MARGINAL"  . t)
+    ("TRUST_FULLY"     . t)
+    ("TRUST_ULTIMATE"  . t))
+  "Map GnuPG trust output values to a boolean saying if you trust the key."
+  :type '(repeat (cons (regexp :tag "GnuPG output regexp")
+                      (boolean :tag "Trust key"))))
+
+;;; mailcrypt wrapper
+
+(eval-and-compile
+  (autoload 'mailcrypt-decrypt "mailcrypt")
+  (autoload 'mailcrypt-verify "mailcrypt")
+  (autoload 'mc-pgp-always-sign "mailcrypt")
+  (autoload 'mc-encrypt-generic "mc-toplev")
+  (autoload 'mc-cleanup-recipient-headers "mc-toplev")
+  (autoload 'mc-sign-generic "mc-toplev"))
+
+(eval-when-compile
+  (defvar mc-default-scheme)
+  (defvar mc-schemes))
+
+(defvar mml2015-decrypt-function 'mailcrypt-decrypt)
+(defvar mml2015-verify-function 'mailcrypt-verify)
+
+(defun mml2015-format-error (err)
+  (if (stringp (cadr err))
+      (cadr err)
+    (format "%S" (cdr err))))
+
+(defun mml2015-mailcrypt-decrypt (handle ctl)
+  (catch 'error
+    (let (child handles result)
+      (unless (setq child (mm-find-part-by-type
+                          (cdr handle)
+                          "application/octet-stream" nil t))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "Corrupted")
+       (throw 'error handle))
+      (with-temp-buffer
+       (mm-insert-part child)
+       (setq result
+             (condition-case err
+                 (funcall mml2015-decrypt-function)
+               (error
+                (mm-set-handle-multipart-parameter
+                 mm-security-handle 'gnus-details (mml2015-format-error err))
+                nil)
+               (quit
+                (mm-set-handle-multipart-parameter
+                 mm-security-handle 'gnus-details "Quit.")
+                nil)))
+       (unless (car result)
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "Failed")
+         (throw 'error handle))
+       (setq handles (mm-dissect-buffer t)))
+      (mm-destroy-parts handle)
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info
+       (concat "OK"
+              (let ((sig (with-current-buffer mml2015-result-buffer
+                           (mml2015-gpg-extract-signature-details))))
+                (concat ", Signer: " sig))))
+      (if (listp (car handles))
+         handles
+       (list handles)))))
+
+(defun mml2015-mailcrypt-clear-decrypt ()
+  (let (result)
+    (setq result
+         (condition-case err
+             (funcall mml2015-decrypt-function)
+           (error
+            (mm-set-handle-multipart-parameter
+             mm-security-handle 'gnus-details (mml2015-format-error err))
+            nil)
+           (quit
+            (mm-set-handle-multipart-parameter
+             mm-security-handle 'gnus-details "Quit.")
+            nil)))
+    (if (car result)
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "OK")
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "Failed"))))
+
+(defun mml2015-fix-micalg (alg)
+  (and alg
+       ;; Mutt/1.2.5i has seen sending micalg=php-sha1
+       (upcase (if (string-match "^p[gh]p-" alg)
+                  (substring alg (match-end 0))
+                alg))))
+
+(defun mml2015-mailcrypt-verify (handle ctl)
+  (catch 'error
+    (let (part)
+      (unless (setq part (mm-find-raw-part-by-type
+                         ctl (or (mm-handle-multipart-ctl-parameter
+                                  ctl 'protocol)
+                                 "application/pgp-signature")
+                         t))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "Corrupted")
+       (throw 'error handle))
+      (with-temp-buffer
+       (insert "-----BEGIN PGP SIGNED MESSAGE-----\n")
+       (insert (format "Hash: %s\n\n"
+                       (or (mml2015-fix-micalg
+                            (mm-handle-multipart-ctl-parameter
+                             ctl 'micalg))
+                           "SHA1")))
+       (save-restriction
+         (narrow-to-region (point) (point))
+         (insert part "\n")
+         (goto-char (point-min))
+         (while (not (eobp))
+           (if (looking-at "^-")
+               (insert "- "))
+           (forward-line)))
+       (unless (setq part (mm-find-part-by-type
+                           (cdr handle) "application/pgp-signature" nil t))
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "Corrupted")
+         (throw 'error handle))
+       (save-restriction
+         (narrow-to-region (point) (point))
+         (mm-insert-part part)
+         (goto-char (point-min))
+         (if (re-search-forward "^-----BEGIN PGP [^-]+-----\r?$" nil t)
+             (replace-match "-----BEGIN PGP SIGNATURE-----" t t))
+         (if (re-search-forward "^-----END PGP [^-]+-----\r?$" nil t)
+             (replace-match "-----END PGP SIGNATURE-----" t t)))
+       (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
+         (unless (condition-case err
+                     (prog1
+                         (funcall mml2015-verify-function)
+                       (if (get-buffer " *mailcrypt stderr temp")
+                           (mm-set-handle-multipart-parameter
+                            mm-security-handle 'gnus-details
+                            (with-current-buffer " *mailcrypt stderr temp"
+                              (buffer-string))))
+                       (if (get-buffer " *mailcrypt stdout temp")
+                           (kill-buffer " *mailcrypt stdout temp"))
+                       (if (get-buffer " *mailcrypt stderr temp")
+                           (kill-buffer " *mailcrypt stderr temp"))
+                       (if (get-buffer " *mailcrypt status temp")
+                           (kill-buffer " *mailcrypt status temp"))
+                       (if (get-buffer mc-gpg-debug-buffer)
+                           (kill-buffer mc-gpg-debug-buffer)))
+                   (error
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-details (mml2015-format-error err))
+                    nil)
+                   (quit
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-details "Quit.")
+                    nil))
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-info "Failed")
+           (throw 'error handle))))
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "OK")
+      handle)))
+
+(defun mml2015-mailcrypt-clear-verify ()
+  (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
+    (if (condition-case err
+           (prog1
+               (funcall mml2015-verify-function)
+             (if (get-buffer " *mailcrypt stderr temp")
+                 (mm-set-handle-multipart-parameter
+                  mm-security-handle 'gnus-details
+                  (with-current-buffer " *mailcrypt stderr temp"
+                    (buffer-string))))
+             (if (get-buffer " *mailcrypt stdout temp")
+                 (kill-buffer " *mailcrypt stdout temp"))
+             (if (get-buffer " *mailcrypt stderr temp")
+                 (kill-buffer " *mailcrypt stderr temp"))
+             (if (get-buffer " *mailcrypt status temp")
+                 (kill-buffer " *mailcrypt status temp"))
+             (if (get-buffer mc-gpg-debug-buffer)
+                 (kill-buffer mc-gpg-debug-buffer)))
+         (error
+          (mm-set-handle-multipart-parameter
+           mm-security-handle 'gnus-details (mml2015-format-error err))
+          nil)
+         (quit
+          (mm-set-handle-multipart-parameter
+           mm-security-handle 'gnus-details "Quit.")
+          nil))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "OK")
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "Failed"))))
+
+(defun mml2015-mailcrypt-sign (cont)
+  (mc-sign-generic (message-options-get 'message-sender)
+                  nil nil nil nil)
+  (let ((boundary (mml-compute-boundary cont))
+       hash point)
+    (goto-char (point-min))
+    (unless (re-search-forward "^-----BEGIN PGP SIGNED MESSAGE-----\r?$" nil t)
+      (error "Cannot find signed begin line"))
+    (goto-char (match-beginning 0))
+    (forward-line 1)
+    (unless (looking-at "Hash:[ \t]*\\([a-zA-Z0-9]+\\)")
+      (error "Cannot not find PGP hash"))
+    (setq hash (match-string 1))
+    (unless (re-search-forward "^$" nil t)
+      (error "Cannot not find PGP message"))
+    (forward-line 1)
+    (delete-region (point-min) (point))
+    (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
+                   boundary))
+    (insert (format "\tmicalg=pgp-%s; protocol=\"application/pgp-signature\"\n"
+                   (downcase hash)))
+    (insert (format "\n--%s\n" boundary))
+    (setq point (point))
+    (goto-char (point-max))
+    (unless (re-search-backward "^-----END PGP SIGNATURE-----\r?$" nil t)
+      (error "Cannot find signature part"))
+    (replace-match "-----END PGP MESSAGE-----" t t)
+    (goto-char (match-beginning 0))
+    (unless (re-search-backward "^-----BEGIN PGP SIGNATURE-----\r?$"
+                               nil t)
+      (error "Cannot find signature part"))
+    (replace-match "-----BEGIN PGP MESSAGE-----" t t)
+    (goto-char (match-beginning 0))
+    (save-restriction
+      (narrow-to-region point (point))
+      (goto-char point)
+      (while (re-search-forward "^- -" nil t)
+       (replace-match "-" t t))
+      (goto-char (point-max)))
+    (insert (format "--%s\n" boundary))
+    (insert "Content-Type: application/pgp-signature\n\n")
+    (goto-char (point-max))
+    (insert (format "--%s--\n" boundary))
+    (goto-char (point-max))))
+
+(defun mml2015-mailcrypt-encrypt (cont &optional sign)
+  (let ((mc-pgp-always-sign
+        (or mc-pgp-always-sign
+            sign
+            (eq t (or (message-options-get 'message-sign-encrypt)
+                      (message-options-set
+                       'message-sign-encrypt
+                       (or (y-or-n-p "Sign the message? ")
+                           'not))))
+            'never)))
+    (mm-with-unibyte-current-buffer
+      (mc-encrypt-generic
+       (or (message-options-get 'message-recipients)
+          (message-options-set 'message-recipients
+                               (mc-cleanup-recipient-headers
+                                (read-string "Recipients: "))))
+       nil nil nil
+       (message-options-get 'message-sender))))
+  (goto-char (point-min))
+  (unless (looking-at "-----BEGIN PGP MESSAGE-----")
+    (error "Fail to encrypt the message"))
+  (let ((boundary (mml-compute-boundary cont)))
+    (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
+                   boundary))
+    (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
+    (insert (format "--%s\n" boundary))
+    (insert "Content-Type: application/pgp-encrypted\n\n")
+    (insert "Version: 1\n\n")
+    (insert (format "--%s\n" boundary))
+    (insert "Content-Type: application/octet-stream\n\n")
+    (goto-char (point-max))
+    (insert (format "--%s--\n" boundary))
+    (goto-char (point-max))))
+
+;;; gpg wrapper
+
+(eval-and-compile
+  (autoload 'gpg-decrypt "gpg")
+  (autoload 'gpg-verify "gpg")
+  (autoload 'gpg-verify-cleartext "gpg")
+  (autoload 'gpg-sign-detached "gpg")
+  (autoload 'gpg-sign-encrypt "gpg")
+  (autoload 'gpg-encrypt "gpg")
+  (autoload 'gpg-passphrase-read "gpg"))
+
+(defun mml2015-gpg-passphrase ()
+  (or (message-options-get 'gpg-passphrase)
+      (message-options-set 'gpg-passphrase (gpg-passphrase-read))))
+
+(defun mml2015-gpg-decrypt-1 ()
+  (let ((cipher (current-buffer)) plain result)
+    (if (with-temp-buffer
+         (prog1
+             (gpg-decrypt cipher (setq plain (current-buffer))
+                          mml2015-result-buffer nil)
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-details
+            (with-current-buffer mml2015-result-buffer
+              (buffer-string)))
+           (set-buffer cipher)
+           (erase-buffer)
+           (insert-buffer-substring plain)
+           (goto-char (point-min))
+           (while (search-forward "\r\n" nil t)
+             (replace-match "\n" t t))))
+       '(t)
+      ;; Some wrong with the return value, check plain text buffer.
+      (if (> (point-max) (point-min))
+         '(t)
+       nil))))
+
+(defun mml2015-gpg-decrypt (handle ctl)
+  (let ((mml2015-decrypt-function 'mml2015-gpg-decrypt-1))
+    (mml2015-mailcrypt-decrypt handle ctl)))
+
+(defun mml2015-gpg-clear-decrypt ()
+  (let (result)
+    (setq result (mml2015-gpg-decrypt-1))
+    (if (car result)
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "OK")
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "Failed"))))
+
+(defun mml2015-gpg-pretty-print-fpr (fingerprint)
+  (let* ((result "")
+        (fpr-length (string-width fingerprint))
+        (n-slice 0)
+        slice)
+    (setq fingerprint (string-to-list fingerprint))
+    (while fingerprint
+      (setq fpr-length (- fpr-length 4))
+      (setq slice (butlast fingerprint fpr-length))
+      (setq fingerprint (nthcdr 4 fingerprint))
+      (setq n-slice (1+ n-slice))
+      (setq result
+           (concat
+            result
+            (case n-slice
+              (1  slice)
+              (otherwise (concat " " slice))))))
+    result))
+
+(defun mml2015-gpg-extract-signature-details ()
+  (goto-char (point-min))
+  (let* ((expired (re-search-forward
+                  "^\\[GNUPG:\\] SIGEXPIRED$"
+                  nil t))
+        (signer (and (re-search-forward
+                      "^\\[GNUPG:\\] GOODSIG \\([0-9A-Za-z]*\\) \\(.*\\)$"
+                      nil t)
+                     (cons (match-string 1) (match-string 2))))
+        (fprint (and (re-search-forward
+                      "^\\[GNUPG:\\] VALIDSIG \\([0-9a-zA-Z]*\\) "
+                      nil t)
+                     (match-string 1)))
+        (trust  (and (re-search-forward
+                      "^\\[GNUPG:\\] \\(TRUST_.*\\)$"
+                      nil t)
+                     (match-string 1)))
+        (trust-good-enough-p
+         (cdr (assoc trust mml2015-unabbrev-trust-alist))))
+    (cond ((and signer fprint)
+          (concat (cdr signer)
+                  (unless trust-good-enough-p
+                    (concat "\nUntrusted, Fingerprint: "
+                            (mml2015-gpg-pretty-print-fpr fprint)))
+                  (when expired
+                    (format "\nWARNING: Signature from expired key (%s)"
+                            (car signer)))))
+         ((re-search-forward
+           "^\\(gpg: \\)?Good signature from \"\\(.*\\)\"$" nil t)
+          (match-string 2))
+         (t
+          "From unknown user"))))
+
+(defun mml2015-gpg-verify (handle ctl)
+  (catch 'error
+    (let (part message signature info-is-set-p)
+      (unless (setq part (mm-find-raw-part-by-type
+                         ctl (or (mm-handle-multipart-ctl-parameter
+                                  ctl 'protocol)
+                                 "application/pgp-signature")
+                         t))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "Corrupted")
+       (throw 'error handle))
+      (with-temp-buffer
+       (setq message (current-buffer))
+       (insert part)
+       ;; Convert <LF> to <CR><LF> in verify mode.  Sign and
+       ;; clearsign use --textmode. The conversion is not necessary.
+       ;; In clearverify, the conversion is not necessary either.
+       (goto-char (point-min))
+       (end-of-line)
+       (while (not (eobp))
+         (unless (eq (char-before) ?\r)
+           (insert "\r"))
+         (forward-line)
+         (end-of-line))
+       (with-temp-buffer
+         (setq signature (current-buffer))
+         (unless (setq part (mm-find-part-by-type
+                             (cdr handle) "application/pgp-signature" nil t))
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-info "Corrupted")
+           (throw 'error handle))
+         (mm-insert-part part)
+         (unless (condition-case err
+                     (prog1
+                         (gpg-verify message signature mml2015-result-buffer)
+                       (mm-set-handle-multipart-parameter
+                        mm-security-handle 'gnus-details
+                        (with-current-buffer mml2015-result-buffer
+                          (buffer-string))))
+                   (error
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-details (mml2015-format-error err))
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-info "Error.")
+                    (setq info-is-set-p t)
+                    nil)
+                   (quit
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-details "Quit.")
+                    (mm-set-handle-multipart-parameter
+                     mm-security-handle 'gnus-info "Quit.")
+                    (setq info-is-set-p t)
+                    nil))
+           (unless info-is-set-p
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-info "Failed"))
+           (throw 'error handle)))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info
+        (with-current-buffer mml2015-result-buffer
+          (mml2015-gpg-extract-signature-details))))
+      handle)))
+
+(defun mml2015-gpg-clear-verify ()
+  (if (condition-case err
+         (prog1
+             (gpg-verify-cleartext (current-buffer) mml2015-result-buffer)
+           (mm-set-handle-multipart-parameter
+            mm-security-handle 'gnus-details
+            (with-current-buffer mml2015-result-buffer
+              (buffer-string))))
+       (error
+        (mm-set-handle-multipart-parameter
+         mm-security-handle 'gnus-details (mml2015-format-error err))
+        nil)
+       (quit
+        (mm-set-handle-multipart-parameter
+         mm-security-handle 'gnus-details "Quit.")
+        nil))
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info
+       (with-current-buffer mml2015-result-buffer
+        (mml2015-gpg-extract-signature-details)))
+    (mm-set-handle-multipart-parameter
+     mm-security-handle 'gnus-info "Failed")))
+
+(defun mml2015-gpg-sign (cont)
+  (let ((boundary (mml-compute-boundary cont))
+       (text (current-buffer)) signature)
+    (goto-char (point-max))
+    (unless (bolp)
+      (insert "\n"))
+    (with-temp-buffer
+      (unless (gpg-sign-detached text (setq signature (current-buffer))
+                                mml2015-result-buffer
+                                nil
+                                (message-options-get 'message-sender)
+                                t t) ; armor & textmode
+       (unless (> (point-max) (point-min))
+         (pop-to-buffer mml2015-result-buffer)
+         (error "Sign error")))
+      (goto-char (point-min))
+      (while (re-search-forward "\r+$" nil t)
+       (replace-match "" t t))
+      (set-buffer text)
+      (goto-char (point-min))
+      (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
+                     boundary))
+      ;;; FIXME: what is the micalg?
+      (insert "\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"\n")
+      (insert (format "\n--%s\n" boundary))
+      (goto-char (point-max))
+      (insert (format "\n--%s\n" boundary))
+      (insert "Content-Type: application/pgp-signature\n\n")
+      (insert-buffer-substring signature)
+      (goto-char (point-max))
+      (insert (format "--%s--\n" boundary))
+      (goto-char (point-max)))))
+
+(defun mml2015-gpg-encrypt (cont &optional sign)
+  (let ((boundary (mml-compute-boundary cont))
+       (text (current-buffer))
+       cipher)
+    (mm-with-unibyte-current-buffer
+      (with-temp-buffer
+       ;; set up a function to call the correct gpg encrypt routine
+       ;; with the right arguments. (FIXME: this should be done
+       ;; differently.)
+       (flet ((gpg-encrypt-func
+                (sign plaintext ciphertext result recipients &optional
+                      passphrase sign-with-key armor textmode)
+                (if sign
+                    (gpg-sign-encrypt
+                     plaintext ciphertext result recipients passphrase
+                     sign-with-key armor textmode)
+                  (gpg-encrypt
+                   plaintext ciphertext result recipients passphrase
+                   armor textmode))))
+         (unless (gpg-encrypt-func
+                   sign ; passed in when using signencrypt
+                   text (setq cipher (current-buffer))
+                   mml2015-result-buffer
+                   (split-string
+                    (or
+                     (message-options-get 'message-recipients)
+                     (message-options-set 'message-recipients
+                                          (read-string "Recipients: ")))
+                    "[ \f\t\n\r\v,]+")
+                   nil
+                   (message-options-get 'message-sender)
+                   t t) ; armor & textmode
+           (unless (> (point-max) (point-min))
+             (pop-to-buffer mml2015-result-buffer)
+             (error "Encrypt error"))))
+       (goto-char (point-min))
+       (while (re-search-forward "\r+$" nil t)
+         (replace-match "" t t))
+       (set-buffer text)
+       (delete-region (point-min) (point-max))
+       (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
+                       boundary))
+       (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
+       (insert (format "--%s\n" boundary))
+       (insert "Content-Type: application/pgp-encrypted\n\n")
+       (insert "Version: 1\n\n")
+       (insert (format "--%s\n" boundary))
+       (insert "Content-Type: application/octet-stream\n\n")
+       (insert-buffer-substring cipher)
+       (goto-char (point-max))
+       (insert (format "--%s--\n" boundary))
+       (goto-char (point-max))))))
+
+;;; pgg wrapper
+
+(eval-when-compile
+  (defvar pgg-errors-buffer)
+  (defvar pgg-output-buffer))
+
+(eval-and-compile
+  (autoload 'pgg-decrypt-region "pgg")
+  (autoload 'pgg-verify-region "pgg")
+  (autoload 'pgg-sign-region "pgg")
+  (autoload 'pgg-encrypt-region "pgg"))
+
+(defun mml2015-pgg-decrypt (handle ctl)
+  (catch 'error
+    (let ((pgg-errors-buffer mml2015-result-buffer)
+         child handles result decrypt-status)
+      (unless (setq child (mm-find-part-by-type
+                          (cdr handle)
+                          "application/octet-stream" nil t))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info "Corrupted")
+       (throw 'error handle))
+      (with-temp-buffer
+       (mm-insert-part child)
+       (if (condition-case err
+               (prog1
+                   (pgg-decrypt-region (point-min) (point-max))
+                 (setq decrypt-status
+                       (with-current-buffer mml2015-result-buffer
+                         (buffer-string)))
+                 (mm-set-handle-multipart-parameter
+                  mm-security-handle 'gnus-details
+                  decrypt-status))
+             (error
+              (mm-set-handle-multipart-parameter
+               mm-security-handle 'gnus-details (mml2015-format-error err))
+              nil)
+             (quit
+              (mm-set-handle-multipart-parameter
+               mm-security-handle 'gnus-details "Quit.")
+              nil))
+           (with-current-buffer pgg-output-buffer
+             (goto-char (point-min))
+             (while (search-forward "\r\n" nil t)
+               (replace-match "\n" t t))
+             (setq handles (mm-dissect-buffer t))
+             (mm-destroy-parts handle)
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-info "OK")
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-details
+              (concat decrypt-status
+                      (when (stringp (car handles))
+                        "\n" (mm-handle-multipart-ctl-parameter
+                              handles 'gnus-details))))
+             (if (listp (car handles))
+                 handles
+               (list handles)))
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "Failed")
+         (throw 'error handle))))))
+
+(defun mml2015-pgg-clear-decrypt ()
+  (let ((pgg-errors-buffer mml2015-result-buffer))
+    (if (prog1
+           (pgg-decrypt-region (point-min) (point-max))
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-details
+          (with-current-buffer mml2015-result-buffer
+            (buffer-string))))
+       (progn
+         (erase-buffer)
+         (insert-buffer-substring pgg-output-buffer)
+         (goto-char (point-min))
+         (while (search-forward "\r\n" nil t)
+           (replace-match "\n" t t))
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "OK"))
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "Failed"))))
+
+(defun mml2015-pgg-verify (handle ctl)
+  (let ((pgg-errors-buffer mml2015-result-buffer)
+       signature-file part signature)
+    (if (or (null (setq part (mm-find-raw-part-by-type
+                             ctl (or (mm-handle-multipart-ctl-parameter
+                                      ctl 'protocol)
+                                     "application/pgp-signature")
+                             t)))
+           (null (setq signature (mm-find-part-by-type
+                                  (cdr handle) "application/pgp-signature" nil t))))
+       (progn
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "Corrupted")
+         handle)
+      (with-temp-buffer
+       (insert part)
+       ;; Convert <LF> to <CR><LF> in verify mode.  Sign and
+       ;; clearsign use --textmode. The conversion is not necessary.
+       ;; In clearverify, the conversion is not necessary either.
+       (goto-char (point-min))
+       (end-of-line)
+       (while (not (eobp))
+         (unless (eq (char-before) ?\r)
+           (insert "\r"))
+         (forward-line)
+         (end-of-line))
+       (with-temp-file (setq signature-file (mm-make-temp-file "pgg"))
+         (mm-insert-part signature))
+       (if (condition-case err
+               (prog1
+                   (pgg-verify-region (point-min) (point-max)
+                                      signature-file t)
+                 (goto-char (point-min))
+                 (while (search-forward "\r\n" nil t)
+                   (replace-match "\n" t t))
+                 (mm-set-handle-multipart-parameter
+                  mm-security-handle 'gnus-details
+                  (concat (with-current-buffer pgg-output-buffer
+                            (buffer-string))
+                          (with-current-buffer pgg-errors-buffer
+                            (buffer-string)))))
+             (error
+              (mm-set-handle-multipart-parameter
+               mm-security-handle 'gnus-details (mml2015-format-error err))
+              nil)
+             (quit
+              (mm-set-handle-multipart-parameter
+               mm-security-handle 'gnus-details "Quit.")
+              nil))
+           (progn
+             (delete-file signature-file)
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-info
+              (with-current-buffer pgg-errors-buffer
+                (mml2015-gpg-extract-signature-details))))
+         (delete-file signature-file)
+         (mm-set-handle-multipart-parameter
+          mm-security-handle 'gnus-info "Failed")))))
+  handle)
+
+(defun mml2015-pgg-clear-verify ()
+  (let ((pgg-errors-buffer mml2015-result-buffer)
+       (text (buffer-string))
+       (coding-system buffer-file-coding-system))
+    (if (condition-case err
+           (prog1
+               (mm-with-unibyte-buffer
+                 (insert (encode-coding-string text coding-system))
+                 (pgg-verify-region (point-min) (point-max) nil t))
+             (goto-char (point-min))
+             (while (search-forward "\r\n" nil t)
+               (replace-match "\n" t t))
+             (mm-set-handle-multipart-parameter
+              mm-security-handle 'gnus-details
+              (concat (with-current-buffer pgg-output-buffer
+                        (buffer-string))
+                      (with-current-buffer pgg-errors-buffer
+                        (buffer-string)))))
+         (error
+          (mm-set-handle-multipart-parameter
+           mm-security-handle 'gnus-details (mml2015-format-error err))
+          nil)
+         (quit
+          (mm-set-handle-multipart-parameter
+           mm-security-handle 'gnus-details "Quit.")
+          nil))
+       (mm-set-handle-multipart-parameter
+        mm-security-handle 'gnus-info
+        (with-current-buffer pgg-errors-buffer
+          (mml2015-gpg-extract-signature-details)))
+      (mm-set-handle-multipart-parameter
+       mm-security-handle 'gnus-info "Failed"))))
+
+(defun mml2015-pgg-sign (cont)
+  (let ((pgg-errors-buffer mml2015-result-buffer)
+       (boundary (mml-compute-boundary cont))
+       (pgg-default-user-id (or (message-options-get 'mml-sender)
+                                pgg-default-user-id)))
+    (unless (pgg-sign-region (point-min) (point-max))
+      (pop-to-buffer mml2015-result-buffer)
+      (error "Sign error"))
+    (goto-char (point-min))
+    (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
+                   boundary))
+      ;;; FIXME: what is the micalg?
+    (insert "\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"\n")
+    (insert (format "\n--%s\n" boundary))
+    (goto-char (point-max))
+    (insert (format "\n--%s\n" boundary))
+    (insert "Content-Type: application/pgp-signature\n\n")
+    (insert-buffer-substring pgg-output-buffer)
+    (goto-char (point-max))
+    (insert (format "--%s--\n" boundary))
+    (goto-char (point-max))))
+
+(defun mml2015-pgg-encrypt (cont &optional sign)
+  (let ((pgg-errors-buffer mml2015-result-buffer)
+       (boundary (mml-compute-boundary cont)))
+    (unless (pgg-encrypt-region (point-min) (point-max)
+                               (split-string
+                                (or
+                                 (message-options-get 'message-recipients)
+                                 (message-options-set 'message-recipients
+                                                      (read-string "Recipients: ")))
+                                "[ \f\t\n\r\v,]+")
+                               sign)
+      (pop-to-buffer mml2015-result-buffer)
+      (error "Encrypt error"))
+    (delete-region (point-min) (point-max))
+    (goto-char (point-min))
+    (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
+                   boundary))
+    (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
+    (insert (format "--%s\n" boundary))
+    (insert "Content-Type: application/pgp-encrypted\n\n")
+    (insert "Version: 1\n\n")
+    (insert (format "--%s\n" boundary))
+    (insert "Content-Type: application/octet-stream\n\n")
+    (insert-buffer-substring pgg-output-buffer)
+    (goto-char (point-max))
+    (insert (format "--%s--\n" boundary))
+    (goto-char (point-max))))
+
+;;; General wrapper
+
+(defun mml2015-clean-buffer ()
+  (if (gnus-buffer-live-p mml2015-result-buffer)
+      (with-current-buffer mml2015-result-buffer
+       (erase-buffer)
+       t)
+    (setq mml2015-result-buffer
+         (gnus-get-buffer-create "*MML2015 Result*"))
+    nil))
+
+(defsubst mml2015-clear-decrypt-function ()
+  (nth 6 (assq mml2015-use mml2015-function-alist)))
+
+(defsubst mml2015-clear-verify-function ()
+  (nth 5 (assq mml2015-use mml2015-function-alist)))
+
+;;;###autoload
+(defun mml2015-decrypt (handle ctl)
+  (mml2015-clean-buffer)
+  (let ((func (nth 4 (assq mml2015-use mml2015-function-alist))))
+    (if func
+       (funcall func handle ctl)
+      handle)))
+
+;;;###autoload
+(defun mml2015-decrypt-test (handle ctl)
+  mml2015-use)
+
+;;;###autoload
+(defun mml2015-verify (handle ctl)
+  (mml2015-clean-buffer)
+  (let ((func (nth 3 (assq mml2015-use mml2015-function-alist))))
+    (if func
+       (funcall func handle ctl)
+      handle)))
+
+;;;###autoload
+(defun mml2015-verify-test (handle ctl)
+  mml2015-use)
+
+;;;###autoload
+(defun mml2015-encrypt (cont &optional sign)
+  (mml2015-clean-buffer)
+  (let ((func (nth 2 (assq mml2015-use mml2015-function-alist))))
+    (if func
+       (funcall func cont sign)
+      (error "Cannot find encrypt function"))))
+
+;;;###autoload
+(defun mml2015-sign (cont)
+  (mml2015-clean-buffer)
+  (let ((func (nth 1 (assq mml2015-use mml2015-function-alist))))
+    (if func
+       (funcall func cont)
+      (error "Cannot find sign function"))))
+
+;;;###autoload
+(defun mml2015-self-encrypt ()
+  (mml2015-encrypt nil))
+
+(provide 'mml2015)
+
+;;; mml2015.el ends here
diff --git a/lisp/netrc.el b/lisp/netrc.el
new file mode 100644 (file)
index 0000000..3bfc76d
--- /dev/null
@@ -0,0 +1,128 @@
+;;; netrc.el --- .netrc parsing functionality
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Modularizer: Ted Zlatanov <tzz@lifelogs.com>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Just the .netrc parsing functionality, abstracted so other packages
+;; besides Gnus can use it.
+
+;;; Code:
+
+;;;
+;;; .netrc and .authinforc parsing
+;;;
+
+(eval-and-compile
+  (defalias 'netrc-point-at-eol
+    (if (fboundp 'point-at-eol)
+       'point-at-eol
+      'line-end-position)))
+
+(defun netrc-parse (file)
+  "Parse FILE and return an list of all entries in the file."
+  (when (file-exists-p file)
+    (with-temp-buffer
+      (let ((tokens '("machine" "default" "login"
+                     "password" "account" "macdef" "force"
+                     "port"))
+           alist elem result pair)
+       (insert-file-contents file)
+       (goto-char (point-min))
+       ;; Go through the file, line by line.
+       (while (not (eobp))
+         (narrow-to-region (point) (netrc-point-at-eol))
+         ;; For each line, get the tokens and values.
+         (while (not (eobp))
+           (skip-chars-forward "\t ")
+           ;; Skip lines that begin with a "#".
+           (if (eq (char-after) ?#)
+               (goto-char (point-max))
+             (unless (eobp)
+               (setq elem
+                     (if (= (following-char) ?\")
+                         (read (current-buffer))
+                       (buffer-substring
+                        (point) (progn (skip-chars-forward "^\t ")
+                                       (point)))))
+               (cond
+                ((equal elem "macdef")
+                 ;; We skip past the macro definition.
+                 (widen)
+                 (while (and (zerop (forward-line 1))
+                             (looking-at "$")))
+                 (narrow-to-region (point) (point)))
+                ((member elem tokens)
+                 ;; Tokens that don't have a following value are ignored,
+                 ;; except "default".
+                 (when (and pair (or (cdr pair)
+                                     (equal (car pair) "default")))
+                   (push pair alist))
+                 (setq pair (list elem)))
+                (t
+                 ;; Values that haven't got a preceding token are ignored.
+                 (when pair
+                   (setcdr pair elem)
+                   (push pair alist)
+                   (setq pair nil)))))))
+         (when alist
+           (push (nreverse alist) result))
+         (setq alist nil
+               pair nil)
+         (widen)
+         (forward-line 1))
+       (nreverse result)))))
+
+(defun netrc-machine (list machine &optional port defaultport)
+  "Return the netrc values from LIST for MACHINE or for the default entry.
+If PORT specified, only return entries with matching port tokens.
+Entries without port tokens default to DEFAULTPORT."
+  (let ((rest list)
+       result)
+    (while list
+      (when (equal (cdr (assoc "machine" (car list))) machine)
+       (push (car list) result))
+      (pop list))
+    (unless result
+      ;; No machine name matches, so we look for default entries.
+      (while rest
+       (when (assoc "default" (car rest))
+         (push (car rest) result))
+       (pop rest)))
+    (when result
+      (setq result (nreverse result))
+      (while (and result
+                 (not (equal (or port defaultport "nntp")
+                             (or (netrc-get (car result) "port")
+                                 defaultport "nntp"))))
+       (pop result))
+      (car result))))
+
+(defun netrc-get (alist type)
+  "Return the value of token TYPE from ALIST."
+  (cdr (assoc type alist)))
+
+(provide 'netrc)
+
+;;; netrc.el ends here
index 76d4390..21b9f97 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nnagent.el --- offline backend for Gnus
-;; Copyright (C) 1997,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
@@ -27,7 +29,7 @@
 
 (require 'nnheader)
 (require 'nnoo)
-(require 'cl)
+(eval-when-compile (require 'cl))
 (require 'gnus-agent)
 (require 'nnml)
 
 
 (nnoo-define-basics nnagent)
 
+(defun nnagent-server (server)
+  (and server (format "%s+%s" (car gnus-command-method) server)))
+
 (deffoo nnagent-open-server (server &optional defs)
   (setq defs
        `((nnagent-directory ,(gnus-agent-directory))
          (nnagent-active-file ,(gnus-agent-lib-file "active"))
          (nnagent-newsgroups-file ,(gnus-agent-lib-file "newsgroups"))
          (nnagent-get-new-mail nil)))
-  (nnoo-change-server 'nnagent server defs)
+  (nnoo-change-server 'nnagent
+                     (nnagent-server server)
+                     defs)
   (let ((dir (gnus-agent-directory))
        err)
     (cond
@@ -73,7 +80,8 @@
             (ftp-error (setq err (format "%s" arg)))))
       (nnagent-close-server)
       (nnheader-report
-       'nnagent (or err "No such file or directory: %s" dir)))
+       'nnagent (or err
+                   (format "No such file or directory: %s" dir))))
      ((not (file-directory-p (file-truename dir)))
       (nnagent-close-server)
       (nnheader-report 'nnagent "Not a directory: %s" dir))
      (t nil))))
 
 (defun nnagent-request-type (group article)
-  (let ((gnus-plugged t))
-    (if (not (gnus-check-backend-function
-             'request-type (car gnus-command-method)))
-       'unknown
-      (funcall (gnus-get-function gnus-command-method 'request-type)
-              (gnus-group-real-name group) article))))
+  (unless (stringp article)
+    (let ((gnus-plugged t))
+      (if (not (gnus-check-backend-function
+               'request-type (car gnus-command-method)))
+         'unknown
+       (funcall (gnus-get-function gnus-command-method 'request-type)
+                (gnus-group-real-name group) article)))))
 
 (deffoo nnagent-request-newgroups (date server)
   nil)
   nil)
 
 (deffoo nnagent-request-post (&optional server)
-  (gnus-request-accept-article "nndraft:queue"))
+  (gnus-agent-insert-meta-information 'news gnus-command-method)
+  (gnus-request-accept-article "nndraft:queue" nil t t))
+
+(deffoo nnagent-request-set-mark (group action server)
+  (with-temp-buffer
+    (insert (format "(%s-request-set-mark \"%s\" '%s \"%s\")\n"
+                   (nth 0 gnus-command-method) group action
+                   (or server (nth 1 gnus-command-method))))
+    (append-to-file (point-min) (point-max) (gnus-agent-lib-file "flags")))
+  nil)
+
+(deffoo nnagent-retrieve-headers (articles &optional group server fetch-old)
+  (let ((file (gnus-agent-article-name ".overview" group))
+       arts n first)
+    (save-excursion
+      (gnus-agent-load-alist group)
+      (setq arts (gnus-sorted-difference
+                 articles (mapcar 'car gnus-agent-article-alist)))
+      ;; Assume that articles with smaller numbers than the first one
+      ;; Agent knows are gone.
+      (setq first (caar gnus-agent-article-alist))
+      (when first 
+       (while (and arts (< (car arts) first))
+         (pop arts)))
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (nnheader-insert-nov-file file (car articles))
+      (goto-char (point-min))
+      (gnus-parse-without-error
+       (while (and arts (not (eobp)))
+         (setq n (read (current-buffer)))
+         (when (> n (car arts))
+           (beginning-of-line))
+         (while (and arts (> n (car arts)))
+           (insert (format
+                    "%d\t[Undownloaded article %d]\tGnus Agent\t\t\t\n"
+                    (car arts) (car arts)))
+           (pop arts))
+         (when (and arts (= n (car arts)))
+           (pop arts))
+         (forward-line 1)))
+      (while arts
+       (insert (format
+                "%d\t[Undownloaded article %d]\tGnus Agent\t\t\t\n"
+                (car arts) (car arts)))
+       (pop arts))
+      (if (and fetch-old
+              (not (numberp fetch-old)))
+         t                             ; Don't remove anything.
+       (nnheader-nov-delete-outside-range
+        (if fetch-old (max 1 (- (car articles) fetch-old))
+          (car articles))
+        (car (last articles)))
+       t)
+      'nov)))
+
+(deffoo nnagent-request-expire-articles (articles group &optional server force)
+  articles)
+
+(deffoo nnagent-request-group (group &optional server dont-check)
+  (nnoo-parent-function 'nnagent 'nnml-request-group
+                       (list group (nnagent-server server) dont-check)))
+
+(deffoo nnagent-close-group (group &optional server)
+  (nnoo-parent-function 'nnagent 'nnml-close-group
+                       (list group (nnagent-server server))))
+
+(deffoo nnagent-request-accept-article (group &optional server last)
+  (nnoo-parent-function 'nnagent 'nnml-request-accept-article
+                       (list group (nnagent-server server) last)))
+
+(deffoo nnagent-request-article (id &optional group server buffer)
+  (nnoo-parent-function 'nnagent 'nnml-request-article
+                       (list id group (nnagent-server server) buffer)))
+
+(deffoo nnagent-request-create-group (group &optional server args)
+  (nnoo-parent-function 'nnagent 'nnml-request-create-group
+                       (list group (nnagent-server server) args)))
+
+(deffoo nnagent-request-delete-group (group &optional force server)
+  (nnoo-parent-function 'nnagent 'nnml-request-delete-group
+                       (list group force (nnagent-server server))))
+
+(deffoo nnagent-request-list (&optional server)
+  (nnoo-parent-function 'nnagent 'nnml-request-list
+                       (list (nnagent-server server))))
+
+(deffoo nnagent-request-list-newsgroups (&optional server)
+  (nnoo-parent-function 'nnagent 'nnml-request-list-newsgroups
+                       (list (nnagent-server server))))
+
+(deffoo nnagent-request-move-article
+    (article group server accept-form &optional last)
+  (nnoo-parent-function 'nnagent 'nnml-request-move-article
+                       (list article group (nnagent-server server)
+                             accept-form last)))
+
+(deffoo nnagent-request-rename-group (group new-name &optional server)
+  (nnoo-parent-function 'nnagent 'nnml-request-rename-group
+                       (list group new-name (nnagent-server server))))
+
+(deffoo nnagent-request-scan (&optional group server)
+  (nnoo-parent-function 'nnagent 'nnml-request-scan
+                       (list group (nnagent-server server))))
+
+(deffoo nnagent-set-status (article name value &optional group server)
+  (nnoo-parent-function 'nnagent 'nnml-set-status
+                       (list article name value group (nnagent-server server))))
+
+(deffoo nnagent-server-opened (&optional server)
+  (nnoo-parent-function 'nnagent 'nnml-server-opened
+                       (list (nnagent-server server))))
+
+(deffoo nnagent-status-message (&optional server)
+  (nnoo-parent-function 'nnagent 'nnml-status-message
+                       (list (nnagent-server server))))
+
+(deffoo nnagent-request-regenerate (server)
+  (nnoo-parent-function 'nnagent 'nnml-request-regenerate
+                       (list (nnagent-server server))))
 
 ;; Use nnml functions for just about everything.
 (nnoo-import nnagent
index f5e8468..0dd568d 100644 (file)
@@ -1,8 +1,10 @@
 ;;; nnbabyl.el --- rmail mbox access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1099, 2000, 2001
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nnheader)
 (condition-case nil
     (require 'rmail)
-  (t (message "Ignore rmail errors from this file, you don't have rmail")))
+  (t (nnheader-message
+      5 "Ignore rmail errors from this file, you don't have rmail")))
 (require 'nnmail)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nnbabyl)
 
@@ -48,6 +52,7 @@
 (defvoo nnbabyl-get-new-mail t
   "If non-nil, nnbabyl will check the incoming mail file and split the mail.")
 
+
 (defvoo nnbabyl-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
   (nnmail-activate 'nnbabyl)
   (unless (assoc group nnbabyl-group-alist)
     (push (list group (cons 1 0))
-                                   nnbabyl-group-alist)
+         nnbabyl-group-alist)
     (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
   t)
 
   (nnheader-report 'nnbabyl "nnbabyl: LIST NEWSGROUPS is not implemented."))
 
 (deffoo nnbabyl-request-expire-articles
-  (articles newsgroup &optional server force)
+    (articles newsgroup &optional server force)
   (nnbabyl-possibly-change-newsgroup newsgroup server)
   (let* ((is-old t)
         rest)
                     (buffer-substring
                      (point) (progn (end-of-line) (point))) force))
              (progn
+               (unless (eq nnmail-expiry-target 'delete)
+                 (with-temp-buffer
+                   (nnbabyl-request-article (car articles)
+                                            newsgroup server
+                                            (current-buffer))
+                   (let ((nnml-current-directory nil))
+                     (nnmail-expiry-target-group
+                      nnmail-expiry-target newsgroup)))
+                 (nnbabyl-possibly-change-newsgroup newsgroup server))
                (nnheader-message 5 "Deleting article %d in %s..."
                                  (car articles) newsgroup)
                (nnbabyl-delete-mail))
       (nconc rest articles))))
 
 (deffoo nnbabyl-request-move-article
-  (article group server accept-form &optional last)
+    (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnbabyl move*"))
        result)
     (and
         (while (re-search-backward "^X-Gnus-Newsgroup: " beg t)
           (delete-region (point) (progn (forward-line 1) (point)))))
        (when nnmail-cache-accepted-message-ids
-        (nnmail-cache-insert (nnmail-fetch-field "message-id")))
+        (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                             group
+                             (nnmail-fetch-field "subject")
+                             (nnmail-fetch-field "from")))
        (setq result
             (if (stringp group)
                 (list (cons group (nnbabyl-active-number group)))
        (insert-buffer-substring buf)
        (when last
         (when nnmail-cache-accepted-message-ids
-          (nnmail-cache-insert (nnmail-fetch-field "message-id")))
+          (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                               group
+                               (nnmail-fetch-field "subject")
+                               (nnmail-fetch-field "from")))
         (save-buffer)
         (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file))
        result))))
       (widen)
       (narrow-to-region
        (save-excursion
-       (unless (re-search-backward (concat "^" nnbabyl-mail-delimiter) nil t)
-         (goto-char (point-min))
-         (end-of-line))
+        (unless (re-search-backward (concat "^" nnbabyl-mail-delimiter) nil t)
+          (goto-char (point-min))
+          (end-of-line))
         (if leave-delim (progn (forward-line 1) (point))
           (match-beginning 0)))
        (progn
   (nnbabyl-create-mbox)
 
   (unless (and nnbabyl-mbox-buffer
-          (buffer-name nnbabyl-mbox-buffer)
-          (save-excursion
-            (set-buffer nnbabyl-mbox-buffer)
-            (= (buffer-size) (nnheader-file-size nnbabyl-mbox-file))))
+              (buffer-name nnbabyl-mbox-buffer)
+              (save-excursion
+                (set-buffer nnbabyl-mbox-buffer)
+                (= (buffer-size) (nnheader-file-size nnbabyl-mbox-file))))
     ;; This buffer has changed since we read it last.  Possibly.
     (save-excursion
       (let ((delim (concat "^" nnbabyl-mail-delimiter))
            start end number)
        (set-buffer (setq nnbabyl-mbox-buffer
                          (nnheader-find-file-noselect
-                          nnbabyl-mbox-file nil 'raw)))
+                          nnbabyl-mbox-file nil t)))
        ;; Save previous buffer mode.
        (setq nnbabyl-previous-buffer-mode
              (cons (cons (point-min) (point-max))
                    major-mode))
 
-       (buffer-disable-undo (current-buffer))
+       (buffer-disable-undo)
        (widen)
        (setq buffer-read-only nil)
        (fundamental-mode)
       (when (buffer-modified-p (current-buffer))
        (save-buffer))
       (nnmail-save-active nnbabyl-group-alist nnbabyl-active-file)
-      (message ""))))
+      (nnheader-message 5 ""))))
 
 (provide 'nnbabyl)
 
index 032d7c0..fa5e641 100644 (file)
@@ -1,5 +1,6 @@
 ;;; nndb.el --- nndb access for Gnus
-;; Copyright (C) 1997,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;         Kai Grossjohann <grossjohann@ls6.informatik.uni-dortmund.de>
@@ -7,7 +8,7 @@
 ;;         David Blacka <davidb@rwhois.net>
 ;; Keywords: news
 
-;; This file is NOT part of GNU Emacs.
+;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 (eval-when-compile (require 'cl))
 
 (eval-and-compile
-  (unless (fboundp 'open-network-stream)
-    (require 'tcp)))
-
-(eval-when-compile (require 'cl))
-
-(eval-and-compile
   (autoload 'news-setup "rnewspost")
   (autoload 'news-reply-mode "rnewspost")
   (autoload 'cancel-timer "timer")
   (autoload 'telnet "telnet" nil t)
   (autoload 'telnet-send-input "telnet" nil t)
-  (autoload 'timezone-parse-date "timezone")
   (autoload 'gnus-declare-backend "gnus-start"))
 
 ;; Declare nndb as derived from nntp
   "*The program used to put a message in an NNDB group.")
 
 (defvoo nndb-server-side-expiry nil
-  "If t, expiry calculation will occur on the server side")
+  "If t, expiry calculation will occur on the server side.")
 
 (defvoo nndb-set-expire-date-on-mark nil
   "If t, the expiry date for a given article will be set to the time
 it was marked as expireable; otherwise the date will be the time the
 article was posted to nndb")
-  
+
 ;; Variables copied from nntp
 
 (defvoo nndb-server-opened-hook '(nntp-send-authinfo-from-file)
@@ -140,7 +134,7 @@ article was posted to nndb")
        (push art rest)))
     rest))
 
-      
+
 ;;
 (deffoo nndb-request-type (group &optional article)
   nndb-article-type)
@@ -153,7 +147,7 @@ article was posted to nndb")
   (nntp-send-command nil "X-TOUCH" article))
 
 (deffoo nndb-request-update-mark
-  (group article mark)
+    (group article mark)
   "Sets the expiry date for ARTICLE in GROUP to now, if the mark is 'E'"
   (if (and nndb-set-expire-date-on-mark (string-equal mark "E"))
       (nndb-touch-article group article))
@@ -175,27 +169,26 @@ article was posted to nndb")
       (nntp-send-command "^\\([23]\\|^423\\).*\n" "X-DATE" art)
       (setq msg (nndb-status-message))
       (if (string-match "^423" msg)
-          ()
+         ()
        (or (string-match "'\\(.+\\)'" msg)
            (error "Not a valid response for X-DATE command: %s"
                   msg))
        (if (nnmail-expired-article-p
             group
-            (gnus-encode-date
-             (substring msg (match-beginning 1) (match-end 1)))
+            (date-to-time (substring msg (match-beginning 1) (match-end 1)))
             force)
            (progn
              (setq delete-list (concat delete-list " " (int-to-string art)))
              (setq num-delete  (1+ num-delete)))
          (push art rest))))
     (if (> (length delete-list) 0)
-       (progn 
+       (progn
          (nnheader-message 5 "Deleting %s article(s) from %s"
                            (int-to-string num-delete) group)
          (nntp-send-command "^[23].*\n" "X-DELETE" delete-list))
       )
-       
-    (message "")
+
+    (nnheader-message 5 "")
     (nconc rest articles)))
 
 (defun nndb-get-remote-expire-response ()
@@ -216,7 +209,7 @@ article was posted to nndb")
   "Let the nndb backend expire articles"
   (let (days art-string delete-list (num-delete 0))
     (nntp-possibly-change-group group server)
-    
+
     ;; first calculate the wait period in days
     (setq days (or (and nnmail-expiry-wait-function
                        (funcall nnmail-expiry-wait-function group))
@@ -229,12 +222,12 @@ article was posted to nndb")
           (setq days -1))
          ((eq days 'immediate)
           (setq days 0)))
-    
+
 
     ;; build article string
     (setq art-string (concat days " " (nndb-build-article-string articles)))
     (nntp-send-command "^\.\r?\n\\|^[345].*\n" "X-EXPIRE" art-string)
-    
+
     (setq delete-list (nndb-get-remote-expire-response))
     (setq num-delete (length delete-list))
     (if (> num-delete 0)
@@ -261,7 +254,7 @@ Optional LAST is ignored."
   ;; which it will be for nndb, which is all that matters anyway
   (let ((new-group (nth 1 accept-form)) result)
     (nntp-possibly-change-group group server)
-    
+
     ;; use the move command for nndb-to-nndb moves
     (if (string-match "^nndb" new-group)
        (let ((new-group-name (gnus-group-real-name new-group)))
@@ -283,7 +276,7 @@ Optional LAST is ignored."
                                       t))
        result)
       )))
-  
+
 (deffoo nndb-request-accept-article (group server &optional last)
   "The article in the current buffer is put into GROUP."
   (nntp-possibly-change-group group server)
@@ -291,18 +284,17 @@ Optional LAST is ignored."
     (when (nntp-send-command "^[23].*\r?\n" "ACCEPT" group)
       (nnheader-insert "")
       (nntp-send-buffer "^[23].*\n"))
-    
+
     (set-buffer nntp-server-buffer)
-    (setq msg (buffer-string (point-min) (point-max)))
+    (setq msg (buffer-string))
     (or (string-match "^\\([0-9]+\\)" msg)
        (error "nndb: %s" msg))
     (setq art (substring msg (match-beginning 1) (match-end 1)))
-    (message "nndb: accepted %s" art)
+    (nnheader-message 5 "nndb: accepted %s" art)
     (list art)))
 
 (deffoo nndb-request-replace-article (article group buffer)
-  "ARTICLE is the number of the article in GROUP to be replaced 
-with the contents of the BUFFER."
+  "ARTICLE is the number of the article in GROUP to be replaced with the contents of the BUFFER."
   (set-buffer buffer)
   (when (nntp-send-command "^[23].*\r?\n" "X-REPLACE" (int-to-string article))
     (nnheader-insert "")
@@ -320,7 +312,7 @@ with the contents of the BUFFER."
 (deffoo nndb-status-message (&optional server)
   "Return server status as a string."
   (set-buffer nntp-server-buffer)
-  (buffer-string (point-min) (point-max)))
+  (buffer-string))
 
 ;; Import stuff from nntp
 
@@ -329,5 +321,4 @@ with the contents of the BUFFER."
 
 (provide 'nndb)
 
-
-
+;;; nndb.el ends here
diff --git a/lisp/nndiary.el b/lisp/nndiary.el
new file mode 100644 (file)
index 0000000..51cbd9a
--- /dev/null
@@ -0,0 +1,1711 @@
+;;; nndiary.el --- A diary backend for Gnus
+
+;; Copyright (C) 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author:        Didier Verna <didier@xemacs.org>
+;; Maintainer:    Didier Verna <didier@xemacs.org>
+;; Created:       Fri Jul 16 18:55:42 1999
+;; Keywords:      calendar mail news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;; Commentary:
+
+;; Contents management by FCM version 0.1.
+
+;; Description:
+;; ===========
+
+;; This package implements NNDiary, a diary backend for Gnus.  NNDiary is a
+;; mail backend, pretty similar to nnml in its functionnning (it has all the
+;; features of nnml, actually), but in which messages are treated as event
+;; reminders.
+
+;; Here is a typical scenario:
+;; - You've got a date with Andy Mc Dowell or Bruce Willis (select according
+;;   to your sexual preference) in one month.  You don't want to forget it.
+;; - Send a (special) diary message to yourself (see below).
+;; - Forget all about it and keep on getting and reading new mail, as usual.
+;; - From time to time, as you type `g' in the group buffer and as the date
+;;   is getting closer, the message will pop up again, just like if it were
+;;   new and unread.
+;; - Read your "new" messages, this one included, and start dreaming of the
+;;   night you're gonna have.
+;; - Once the date is over (you actually fell asleep just after dinner), the
+;;   message will be automatically deleted if it is marked as expirable.
+
+;; Some more notes on the diary backend:
+;; - NNDiary is a *real* mail backend.  You *really* send real diary
+;;   messsages.  This means for instance that you can give appointements to
+;;   anybody (provided they use Gnus and NNDiary) by sending the diary message
+;;   to them as well.
+;; - However, since NNDiary also has a 'request-post method, you can also
+;;  `C-u a' instead of `C-u m' on a diary group and the message won't actually
+;;   be sent; just stored in the group.
+;; - The events you want to remember need not be punctual.  You can set up
+;;   reminders for regular dates (like once each week, each monday at 13:30
+;;   and so on).  Diary messages of this kind will never be deleted (unless
+;;   you do it explicitely).  But that, you guessed.
+
+
+;; Usage:
+;; =====
+
+;;  1/ NNDiary has two modes of operation: traditional (the default) and
+;;     autonomous.
+;;     a/ In traditional mode, NNDiary does not get new mail by itself.  You
+;;        have to move mails from your primary mail backend to nndiary
+;;        groups.
+;;     b/ In autonomous mode, NNDiary retrieves its own mail and handles it
+;;        independantly of your primary mail backend.  To use NNDiary in
+;;        autonomous mode, you have several things to do:
+;;           i/ Put (setq nndiary-get-new-mail t) in your gnusrc file.
+;;          ii/ Diary messages contain several `X-Diary-*' special headers.
+;;              You *must* arrange that these messages be split in a private
+;;              folder *before* Gnus treat them.  You need this because Gnus
+;;              is not able yet to manage multiple backends for mail
+;;              retrieval.  Getting them from a separate source will
+;;              compensate this misfeature to some extent, as we will see.
+;;              As an example, here's my procmailrc entry to store diary files
+;;              in ~/.nndiary (the default nndiary mail source file):
+;;
+;;              :0 HD :
+;;              * ^X-Diary
+;;              .nndiary
+;;         iii/ Customize the variables `nndiary-mail-sources' and
+;;              `nndiary-split-methods'.  These are replacements for the usual
+;;              mail sources and split methods which, and will be used in
+;;              autonomous mode.  `nndiary-mail-sources' defaults to
+;;              '(file :path "~/.nndiary").
+;;  2/ Install nndiary somewhere Emacs / Gnus can find it.  Normally, you
+;;     *don't* have to '(require 'nndiary) anywhere.  Gnus will do so when
+;;     appropriate as long as nndiary is somewhere in the load path.
+;;  3/ Now, customize the rest of nndiary.  In particular, you should
+;;     customize `nndiary-reminders', the list of times when you want to be
+;;     reminded of your appointements (e.g. 3 weeks before, then 2 days
+;;     before, then 1 hour before and that's it).
+;;  4/ You *must* use the group timestamp feature of Gnus.  This adds a
+;;     timestamp to each groups' parameters (please refer to the Gnus
+;;     documentation ("Group Timestamp" info node) to see how it's done.
+;;  5/ Once you have done this, you may add a permanent nndiary virtual server
+;;     (something like '(nndiary "")) to your `gnus-secondary-select-methods'.
+;;     Yes, this server will be able to retrieve mails and split them when you
+;;     type `g' in the group buffer, just as if it were your only mail backend.
+;;     This is the benefit of using a private folder.
+;;  6/ Hopefully, almost everything (see the TODO section below) will work as
+;;     expected when you restart Gnus: in the group buffer, `g' and `M-g' will
+;;     also get your new diary mails, `F' will find your new diary groups etc.
+
+
+;; How to send diary messages:
+;; ==========================
+
+;; There are 7 special headers in diary messages. These headers are of the
+;; form `X-Diary-<something>', the <something> being one of `Minute', `Hour',
+;; `Dom', `Month', `Year', `Time-Zone' and `Dow'. `Dom' means "Day of Month",
+;; and `dow' means "Day of Week".  These headers actually behave like crontab
+;; specifications and define the event date(s).
+
+;; For all headers but the `Time-Zone' one, a header value is either a
+;; star (meaning all possible values), or a list of fields (separated by a
+;; comma).  A field is either an integer, or a range.  A range is two integers
+;; separated by a dash.  Possible integer values are 0-59 for `Minute', 0-23
+;; for `Hour', 1-31 for `Dom', `1-12' for Month, above 1971 for `Year' and 0-6
+;; for `Dow' (0 = sunday).  As a special case, a star in either `Dom' or `Dow'
+;; doesn't mean "all possible values", but "use only the other field".  Note
+;; that if both are star'ed, the use of either one gives the same result :-),
+
+;; The `Time-Zone' header is special in that it can have only one value (you
+;; bet ;-).
+;; A star doesn't mean "all possible values" (because it has no sense), but
+;; "the current local time zone".
+
+;; As an example, here's how you would say "Each Monday and each 1st of month,
+;; at 12:00, 20:00, 21:00, 22:00, 23:00 and 24:00, from 1999 to 2010" (I let
+;; you find what to do then):
+;;
+;;   X-Diary-Minute: 0
+;;   X-Diary-Hour: 12, 20-24
+;;   X-Diary-Dom: 1
+;;   X-Diary-Month: *
+;;   X-Diary-Year: 1999-2010
+;;   X-Diary-Dow: 1
+;;   X-Diary-Time-Zone: *
+;;
+;;
+;; Sending a diary message is not different from sending any other kind of
+;; mail, except that such messages are identified by the presence of these
+;; special headers.
+
+
+
+;; Bugs / Todo:
+;; ===========
+
+;; * Respooling doesn't work because contrary to the request-scan function,
+;;   Gnus won't allow me to override the split methods when calling the
+;;   respooling backend functions.
+;; * There's a bug in the time zone mechanism with variable TZ locations.
+;; * We could allow a keyword like `ask' in X-Diary-* headers, that would mean
+;;   "ask for value upon reception of the message".
+;; * We could add an optional header X-Diary-Reminders to specify a special
+;;   reminders value for this message. Suggested by Jody Klymak.
+;; * We should check messages validity in other circumstances than just
+;;   moving an article from sonwhere else (request-accept). For instance, when
+;;   editing / saving and so on.
+
+
+;; Remarks:
+;; =======
+
+;; * nnoo.
+;;   NNDiary is very similar to nnml.  This makes the idea of using nnoo (to
+;;   derive nndiary from nnml) natural.  However, my experience with nnoo is
+;;   that for reasonably complex backends like this one, noo is a burden
+;;   rather than an help.  It's tricky to use, not everything can be
+;;   inherited, what can be inherited and when is not very clear, and you've
+;;   got to be very careful because a little mistake can fuck up your your
+;;   other backends, especially because their variables will be use instead of
+;;   your real ones.  Finally, I found it easier to just clone the needed
+;;   parts of nnml, and tracking nnml updates is not a big deal.
+
+;;   IMHO, nnoo is actually badly designed.  A much simpler, and yet more
+;;   powerful one would be to make *real* functions and variables for a new
+;;   backend based on another. Lisp is a reflexive language so that's a very
+;;   easy thing to do: inspect the function's form, replace occurences of
+;;   <nnfrom> (even in strings) with <nnto>, and you're done.
+
+;; * nndiary-get-new-mail, nndiary-mail-source and nndiary-split-methods:
+;;   NNDiary has some experimental parts, in the sense Gnus normally uses only
+;;   one mail backends for mail retreival and splitting.  This backend is also
+;;   an attempt to make it behave differently.  For Gnus developpers: as you
+;;   can see if you snarf into the code, that was not a very difficult thing
+;;   to do.  Something should be done about the respooling breakage though.
+
+
+;;; Code:
+
+(require 'nnoo)
+(require 'nnheader)
+(require 'nnmail)
+(eval-when-compile (require 'cl))
+
+(require 'gnus-start)
+(require 'gnus-sum)
+
+;; Compatibility Functions  =================================================
+
+(eval-and-compile
+  (if (fboundp 'signal-error)
+      (defun nndiary-error (&rest args)
+       (apply #'signal-error 'nndiary args))
+    (defun nndiary-error (&rest args)
+      (apply #'error args))))
+
+
+;; Backend behavior customization ===========================================
+
+(defgroup nndiary nil
+  "The Gnus Diary backend."
+  :group 'gnus-diary)
+
+(defcustom nndiary-mail-sources
+  `((file :path ,(expand-file-name "~/.nndiary")))
+  "*NNDiary specific mail sources.
+This variable is used by nndiary in place of the standard `mail-sources'
+variable when `nndiary-get-new-mail' is set to non-nil.  These sources
+must contain diary messages ONLY."
+  :group 'nndiary
+  :group 'mail-source
+  :type 'sexp)
+
+(defcustom nndiary-split-methods '(("diary" ""))
+  "*NNDiary specific split methods.
+This variable is used by nndiary in place of the standard
+`nnmail-split-methods' variable when `nndiary-get-new-mail' is set to
+non-nil."
+  :group 'nndiary
+  :group 'nnmail-split
+  :type '(choice (repeat :tag "Alist" (group (string :tag "Name") regexp))
+                (function-item nnmail-split-fancy)
+                (function :tag "Other")))
+
+
+(defcustom nndiary-reminders '((0 . day))
+  "*Different times when you want to be reminded of your appointements.
+Diary articles will appear again, as if they'd been just received.
+
+Entries look like (3 . day) which means something like \"Please
+Hortense, would you be so kind as to remind me of my appointments 3 days
+before the date, thank you very much. Anda, hmmm... by the way, are you
+doing anything special tonight ?\".
+
+The units of measure are 'minute 'hour 'day 'week 'month and 'year (no,
+not 'century, sorry).
+
+NOTE: the units of measure actually express dates, not durations: if you
+use 'week, messages will pop up on Sundays at 00:00 (or Mondays if
+`nndiary-week-starts-on-monday' is non nil) and *not* 7 days before the
+appointement, if you use 'month, messages will pop up on the first day of
+each months, at 00:00 and so on.
+
+If you really want to specify a duration (like 24 hours exactly), you can
+use the equivalent in minutes (the smallest unit).  A fuzz of 60 seconds
+maximum in the reminder is not that painful, I think.  Although this
+scheme might appear somewhat weird at a first glance, it is very powerful.
+In order to make this clear, here are some examples:
+
+- '(0 . day): this is the default value of `nndiary-reminders'.  It means
+  pop up the appointements of the day each morning at 00:00.
+
+- '(1 . day): this means pop up the appointements the day before, at 00:00.
+
+- '(6 . hour): for an appointement at 18:30, this would pop up the
+  appointement message at 12:00.
+
+- '(360 . minute): for an appointement at 18:30 and 15 seconds, this would
+  pop up the appointement message at 12:30."
+  :group 'nndiary
+  :type '(repeat (cons :format "%v\n"
+                      (integer :format "%v")
+                      (choice :format "%[%v(s)%] before...\n"
+                              :value day
+                              (const :format "%v" minute)
+                              (const :format "%v" hour)
+                              (const :format "%v" day)
+                              (const :format "%v" week)
+                              (const :format "%v" month)
+                              (const :format "%v" year)))))
+
+(defcustom nndiary-week-starts-on-monday nil
+  "*Whether a week starts on monday (otherwise, sunday)."
+  :type 'boolean
+  :group 'nndiary)
+
+
+(defcustom nndiary-request-create-group-hooks nil
+  "*Hooks to run after `nndiary-request-create-group' is executed.
+The hooks will be called with the full group name as argument."
+  :group 'nndiary
+  :type 'hook)
+
+(defcustom nndiary-request-update-info-hooks nil
+  "*Hooks to run after `nndiary-request-update-info-group' is executed.
+The hooks will be called with the full group name as argument."
+  :group 'nndiary
+  :type 'hook)
+
+(defcustom nndiary-request-accept-article-hooks nil
+  "*Hooks to run before accepting an article.
+Executed near the beginning of `nndiary-request-accept-article'.
+The hooks will be called with the article in the current buffer."
+  :group 'nndiary
+  :type 'hook)
+
+(defcustom nndiary-check-directory-twice t
+  "*If t, check directories twice to avoid NFS failures."
+  :group 'nndiary
+  :type 'boolean)
+
+
+;; Backend declaration ======================================================
+
+;; Well, most of this is nnml clonage.
+
+(nnoo-declare nndiary)
+
+(defvoo nndiary-directory (nnheader-concat gnus-directory "diary/")
+  "Spool directory for the nndiary backend.")
+
+(defvoo nndiary-active-file
+    (expand-file-name "active" nndiary-directory)
+  "Active file for the nndiary backend.")
+
+(defvoo nndiary-newsgroups-file
+    (expand-file-name "newsgroups" nndiary-directory)
+  "Newsgroups description file for the nndiary backend.")
+
+(defvoo nndiary-get-new-mail nil
+  "Whether nndiary gets new mail and split it.
+Contrary to traditional mail backends, this variable can be set to t
+even if your primary mail backend also retreives mail. In such a case,
+NDiary uses its own mail-sources and split-methods.")
+
+(defvoo nndiary-nov-is-evil nil
+  "If non-nil, Gnus will never use nov databases for nndiary groups.
+Using nov databases will speed up header fetching considerably.
+This variable shouldn't be flipped much.  If you have, for some reason,
+set this to t, and want to set it to nil again, you should always run
+the `nndiary-generate-nov-databases' command.  The function will go
+through all nnml directories and generate nov databases for them
+all.  This may very well take some time.")
+
+(defvoo nndiary-prepare-save-mail-hook nil
+  "*Hook run narrowed to an article before saving.")
+
+(defvoo nndiary-inhibit-expiry nil
+  "If non-nil, inhibit expiry.")
+
+\f
+
+(defconst nndiary-version "0.2-b14"
+  "Current Diary backend version.")
+
+(defun nndiary-version ()
+  "Current Diary backend version."
+  (interactive)
+  (message "NNDiary version %s" nndiary-version))
+
+(defvoo nndiary-nov-file-name ".overview")
+
+(defvoo nndiary-current-directory nil)
+(defvoo nndiary-current-group nil)
+(defvoo nndiary-status-string "" )
+(defvoo nndiary-nov-buffer-alist nil)
+(defvoo nndiary-group-alist nil)
+(defvoo nndiary-active-timestamp nil)
+(defvoo nndiary-article-file-alist nil)
+
+(defvoo nndiary-generate-active-function 'nndiary-generate-active-info)
+(defvoo nndiary-nov-buffer-file-name nil)
+(defvoo nndiary-file-coding-system nnmail-file-coding-system)
+
+(defconst nndiary-headers
+  '(("Minute" 0 59)
+    ("Hour" 0 23)
+    ("Dom" 1 31)
+    ("Month" 1 12)
+    ("Year" 1971)
+    ("Dow" 0 6)
+    ("Time-Zone" (("Y" -43200)
+
+                 ("X" -39600)
+
+                 ("W" -36000)
+
+                 ("V" -32400)
+
+                 ("U" -28800)
+                 ("PST" -28800)
+
+                 ("T"   -25200)
+                 ("MST" -25200)
+                 ("PDT" -25200)
+
+                 ("S"   -21600)
+                 ("CST" -21600)
+                 ("MDT" -21600)
+
+                 ("R"   -18000)
+                 ("EST" -18000)
+                 ("CDT" -18000)
+
+                 ("Q"   -14400)
+                 ("AST" -14400)
+                 ("EDT" -14400)
+
+                 ("P"   -10800)
+                 ("ADT" -10800)
+
+                 ("O" -7200)
+
+                 ("N" -3600)
+
+                 ("Z"   0)
+                 ("GMT" 0)
+                 ("UT"  0)
+                 ("UTC" 0)
+                 ("WET" 0)
+
+                 ("A"    3600)
+                 ("CET"  3600)
+                 ("MET"  3600)
+                 ("MEZ"  3600)
+                 ("BST"  3600)
+                 ("WEST" 3600)
+
+                 ("B"    7200)
+                 ("EET"  7200)
+                 ("CEST" 7200)
+                 ("MEST" 7200)
+                 ("MESZ" 7200)
+
+                 ("C" 10800)
+
+                 ("D" 14400)
+
+                 ("E" 18000)
+
+                 ("F" 21600)
+
+                 ("G" 25200)
+
+                 ("H" 28800)
+
+                 ("I"   32400)
+                 ("JST" 32400)
+
+                 ("K"   36000)
+                 ("GST" 36000)
+
+                 ("L" 39600)
+
+                 ("M"    43200)
+                 ("NZST" 43200)
+
+                 ("NZDT" 46800))))
+  ;; List of NNDiary headers that specify the time spec. Each header name is
+  ;; followed by either two integers (specifying a range of possible values
+  ;; for this header) or one list (specifying all the possible values for this
+  ;; header). In the latter case, the list does NOT include the unspecifyed
+  ;; spec (*).
+  ;; For time zone values, we have symbolic time zone names associated with
+  ;; the (relative) number of seconds ahead GMT.
+  )
+
+(defsubst nndiary-schedule ()
+  (let (head)
+    (condition-case arg
+       (mapcar
+        (lambda (elt)
+          (setq head (nth 0 elt))
+          (nndiary-parse-schedule (nth 0 elt) (nth 1 elt) (nth 2 elt)))
+        nndiary-headers)
+      (t
+       (nnheader-report 'nndiary "X-Diary-%s header parse error: %s."
+                       head (cdr arg))
+       nil))
+    ))
+
+;;; Interface functions =====================================================
+
+(nnoo-define-basics nndiary)
+
+(deffoo nndiary-retrieve-headers (sequence &optional group server fetch-old)
+  (when (nndiary-possibly-change-directory group server)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (let* ((file nil)
+            (number (length sequence))
+            (count 0)
+            (file-name-coding-system nnmail-pathname-coding-system)
+            beg article
+            (nndiary-check-directory-twice
+             (and nndiary-check-directory-twice
+                  ;; To speed up, disable it in some case.
+                  (or (not (numberp nnmail-large-newsgroup))
+                      (<= number nnmail-large-newsgroup)))))
+       (if (stringp (car sequence))
+           'headers
+         (if (nndiary-retrieve-headers-with-nov sequence fetch-old)
+             'nov
+           (while sequence
+             (setq article (car sequence))
+             (setq file (nndiary-article-to-file article))
+             (when (and file
+                        (file-exists-p file)
+                        (not (file-directory-p file)))
+               (insert (format "221 %d Article retrieved.\n" article))
+               (setq beg (point))
+               (nnheader-insert-head file)
+               (goto-char beg)
+               (if (search-forward "\n\n" nil t)
+                   (forward-char -1)
+                 (goto-char (point-max))
+                 (insert "\n\n"))
+               (insert ".\n")
+               (delete-region (point) (point-max)))
+             (setq sequence (cdr sequence))
+             (setq count (1+ count))
+             (and (numberp nnmail-large-newsgroup)
+                  (> number nnmail-large-newsgroup)
+                  (zerop (% count 20))
+                  (nnheader-message 6 "nndiary: Receiving headers... %d%%"
+                                    (/ (* count 100) number))))
+
+           (and (numberp nnmail-large-newsgroup)
+                (> number nnmail-large-newsgroup)
+                (nnheader-message 6 "nndiary: Receiving headers...done"))
+
+           (nnheader-fold-continuation-lines)
+           'headers))))))
+
+(deffoo nndiary-open-server (server &optional defs)
+  (nnoo-change-server 'nndiary server defs)
+  (when (not (file-exists-p nndiary-directory))
+    (ignore-errors (make-directory nndiary-directory t)))
+  (cond
+   ((not (file-exists-p nndiary-directory))
+    (nndiary-close-server)
+    (nnheader-report 'nndiary "Couldn't create directory: %s"
+                    nndiary-directory))
+   ((not (file-directory-p (file-truename nndiary-directory)))
+    (nndiary-close-server)
+    (nnheader-report 'nndiary "Not a directory: %s" nndiary-directory))
+   (t
+    (nnheader-report 'nndiary "Opened server %s using directory %s"
+                    server nndiary-directory)
+    t)))
+
+(deffoo nndiary-request-regenerate (server)
+  (nndiary-possibly-change-directory nil server)
+  (nndiary-generate-nov-databases server)
+  t)
+
+(deffoo nndiary-request-article (id &optional group server buffer)
+  (nndiary-possibly-change-directory group server)
+  (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
+        (file-name-coding-system nnmail-pathname-coding-system)
+        path gpath group-num)
+    (if (stringp id)
+       (when (and (setq group-num (nndiary-find-group-number id))
+                  (cdr
+                   (assq (cdr group-num)
+                         (nnheader-article-to-file-alist
+                          (setq gpath
+                                (nnmail-group-pathname
+                                 (car group-num)
+                                 nndiary-directory))))))
+         (setq path (concat gpath (int-to-string (cdr group-num)))))
+      (setq path (nndiary-article-to-file id)))
+    (cond
+     ((not path)
+      (nnheader-report 'nndiary "No such article: %s" id))
+     ((not (file-exists-p path))
+      (nnheader-report 'nndiary "No such file: %s" path))
+     ((file-directory-p path)
+      (nnheader-report 'nndiary "File is a directory: %s" path))
+     ((not (save-excursion (let ((nnmail-file-coding-system
+                                 nndiary-file-coding-system))
+                            (nnmail-find-file path))))
+      (nnheader-report 'nndiary "Couldn't read file: %s" path))
+     (t
+      (nnheader-report 'nndiary "Article %s retrieved" id)
+      ;; We return the article number.
+      (cons (if group-num (car group-num) group)
+           (string-to-int (file-name-nondirectory path)))))))
+
+(deffoo nndiary-request-group (group &optional server dont-check)
+  (let ((file-name-coding-system nnmail-pathname-coding-system))
+    (cond
+     ((not (nndiary-possibly-change-directory group server))
+      (nnheader-report 'nndiary "Invalid group (no such directory)"))
+     ((not (file-exists-p nndiary-current-directory))
+      (nnheader-report 'nndiary "Directory %s does not exist"
+                      nndiary-current-directory))
+     ((not (file-directory-p nndiary-current-directory))
+      (nnheader-report 'nndiary "%s is not a directory"
+                      nndiary-current-directory))
+     (dont-check
+      (nnheader-report 'nndiary "Group %s selected" group)
+      t)
+     (t
+      (nnheader-re-read-dir nndiary-current-directory)
+      (nnmail-activate 'nndiary)
+      (let ((active (nth 1 (assoc group nndiary-group-alist))))
+       (if (not active)
+           (nnheader-report 'nndiary "No such group: %s" group)
+         (nnheader-report 'nndiary "Selected group %s" group)
+         (nnheader-insert "211 %d %d %d %s\n"
+                          (max (1+ (- (cdr active) (car active))) 0)
+                          (car active) (cdr active) group)))))))
+
+(deffoo nndiary-request-scan (&optional group server)
+  ;; Use our own mail sources and split methods while Gnus doesn't let us have
+  ;; multiple backends for retrieving mail.
+  (let ((mail-sources nndiary-mail-sources)
+       (nnmail-split-methods nndiary-split-methods))
+    (setq nndiary-article-file-alist nil)
+    (nndiary-possibly-change-directory group server)
+    (nnmail-get-new-mail 'nndiary 'nndiary-save-nov nndiary-directory group)))
+
+(deffoo nndiary-close-group (group &optional server)
+  (setq nndiary-article-file-alist nil)
+  t)
+
+(deffoo nndiary-request-create-group (group &optional server args)
+  (nndiary-possibly-change-directory nil server)
+  (nnmail-activate 'nndiary)
+  (cond
+   ((assoc group nndiary-group-alist)
+    t)
+   ((and (file-exists-p (nnmail-group-pathname group nndiary-directory))
+        (not (file-directory-p (nnmail-group-pathname
+                                group nndiary-directory))))
+    (nnheader-report 'nndiary "%s is a file"
+                    (nnmail-group-pathname group nndiary-directory)))
+   (t
+    (let (active)
+      (push (list group (setq active (cons 1 0)))
+           nndiary-group-alist)
+      (nndiary-possibly-create-directory group)
+      (nndiary-possibly-change-directory group server)
+      (let ((articles (nnheader-directory-articles nndiary-current-directory)))
+       (when articles
+         (setcar active (apply 'min articles))
+         (setcdr active (apply 'max articles))))
+      (nnmail-save-active nndiary-group-alist nndiary-active-file)
+      (run-hook-with-args 'nndiary-request-create-group-hooks
+                         (gnus-group-prefixed-name group
+                                                   (list "nndiary" server)))
+      t))
+   ))
+
+(deffoo nndiary-request-list (&optional server)
+  (save-excursion
+    (let ((nnmail-file-coding-system nnmail-active-file-coding-system)
+         (file-name-coding-system nnmail-pathname-coding-system))
+      (nnmail-find-file nndiary-active-file))
+    (setq nndiary-group-alist (nnmail-get-active))
+    t))
+
+(deffoo nndiary-request-newgroups (date &optional server)
+  (nndiary-request-list server))
+
+(deffoo nndiary-request-list-newsgroups (&optional server)
+  (save-excursion
+    (nnmail-find-file nndiary-newsgroups-file)))
+
+(deffoo nndiary-request-expire-articles (articles group &optional server force)
+  (nndiary-possibly-change-directory group server)
+  (let ((active-articles
+        (nnheader-directory-articles nndiary-current-directory))
+       article rest number)
+    (nnmail-activate 'nndiary)
+    ;; Articles not listed in active-articles are already gone,
+    ;; so don't try to expire them.
+    (setq articles (gnus-intersection articles active-articles))
+    (while articles
+      (setq article (nndiary-article-to-file (setq number (pop articles))))
+      (if (and (nndiary-deletable-article-p group number)
+              ;; Don't use nnmail-expired-article-p. Our notion of expiration
+              ;; is a bit peculiar ...
+              (or force (nndiary-expired-article-p article)))
+         (progn
+           ;; Allow a special target group.
+           (unless (eq nnmail-expiry-target 'delete)
+             (with-temp-buffer
+               (nndiary-request-article number group server (current-buffer))
+               (let ((nndiary-current-directory nil))
+                 (nnmail-expiry-target-group nnmail-expiry-target group)))
+             (nndiary-possibly-change-directory group server))
+           (nnheader-message 5 "Deleting article %s in %s" number group)
+           (condition-case ()
+               (funcall nnmail-delete-file-function article)
+             (file-error (push number rest)))
+           (setq active-articles (delq number active-articles))
+           (nndiary-nov-delete-article group number))
+       (push number rest)))
+    (let ((active (nth 1 (assoc group nndiary-group-alist))))
+      (when active
+       (setcar active (or (and active-articles
+                               (apply 'min active-articles))
+                          (1+ (cdr active)))))
+      (nnmail-save-active nndiary-group-alist nndiary-active-file))
+    (nndiary-save-nov)
+    (nconc rest articles)))
+
+(deffoo nndiary-request-move-article
+    (article group server accept-form &optional last)
+  (let ((buf (get-buffer-create " *nndiary move*"))
+       result)
+    (nndiary-possibly-change-directory group server)
+    (nndiary-update-file-alist)
+    (and
+     (nndiary-deletable-article-p group article)
+     (nndiary-request-article article group server)
+     (let (nndiary-current-directory
+          nndiary-current-group
+          nndiary-article-file-alist)
+       (save-excursion
+        (set-buffer buf)
+        (insert-buffer-substring nntp-server-buffer)
+        (setq result (eval accept-form))
+        (kill-buffer (current-buffer))
+        result))
+     (progn
+       (nndiary-possibly-change-directory group server)
+       (condition-case ()
+          (funcall nnmail-delete-file-function
+                   (nndiary-article-to-file  article))
+        (file-error nil))
+       (nndiary-nov-delete-article group article)
+       (when last
+        (nndiary-save-nov)
+        (nnmail-save-active nndiary-group-alist nndiary-active-file))))
+    result))
+
+(deffoo nndiary-request-accept-article (group &optional server last)
+  (nndiary-possibly-change-directory group server)
+  (nnmail-check-syntax)
+  (run-hooks 'nndiary-request-accept-article-hooks)
+  (when (nndiary-schedule)
+    (let (result)
+      (when nnmail-cache-accepted-message-ids
+       (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                            group
+                            (nnmail-fetch-field "subject")))
+      (if (stringp group)
+         (and
+          (nnmail-activate 'nndiary)
+          (setq result
+                (car (nndiary-save-mail
+                      (list (cons group (nndiary-active-number group))))))
+          (progn
+            (nnmail-save-active nndiary-group-alist nndiary-active-file)
+            (and last (nndiary-save-nov))))
+       (and
+        (nnmail-activate 'nndiary)
+        (if (and (not (setq result
+                            (nnmail-article-group 'nndiary-active-number)))
+                 (yes-or-no-p "Moved to `junk' group; delete article? "))
+            (setq result 'junk)
+          (setq result (car (nndiary-save-mail result))))
+        (when last
+          (nnmail-save-active nndiary-group-alist nndiary-active-file)
+          (when nnmail-cache-accepted-message-ids
+            (nnmail-cache-close))
+          (nndiary-save-nov))))
+      result))
+  )
+
+(deffoo nndiary-request-post (&optional server)
+  (nnmail-do-request-post 'nndiary-request-accept-article server))
+
+(deffoo nndiary-request-replace-article (article group buffer)
+  (nndiary-possibly-change-directory group)
+  (save-excursion
+    (set-buffer buffer)
+    (nndiary-possibly-create-directory group)
+    (let ((chars (nnmail-insert-lines))
+         (art (concat (int-to-string article) "\t"))
+         headers)
+      (when (ignore-errors
+             (nnmail-write-region
+              (point-min) (point-max)
+              (or (nndiary-article-to-file article)
+                  (expand-file-name (int-to-string article)
+                                    nndiary-current-directory))
+              nil (if (nnheader-be-verbose 5) nil 'nomesg))
+             t)
+       (setq headers (nndiary-parse-head chars article))
+       ;; Replace the NOV line in the NOV file.
+       (save-excursion
+         (set-buffer (nndiary-open-nov group))
+         (goto-char (point-min))
+         (if (or (looking-at art)
+                 (search-forward (concat "\n" art) nil t))
+             ;; Delete the old NOV line.
+             (delete-region (progn (beginning-of-line) (point))
+                            (progn (forward-line 1) (point)))
+           ;; The line isn't here, so we have to find out where
+           ;; we should insert it.  (This situation should never
+           ;; occur, but one likes to make sure...)
+           (while (and (looking-at "[0-9]+\t")
+                       (< (string-to-int
+                           (buffer-substring
+                            (match-beginning 0) (match-end 0)))
+                          article)
+                       (zerop (forward-line 1)))))
+         (beginning-of-line)
+         (nnheader-insert-nov headers)
+         (nndiary-save-nov)
+         t)))))
+
+(deffoo nndiary-request-delete-group (group &optional force server)
+  (nndiary-possibly-change-directory group server)
+  (when force
+    ;; Delete all articles in GROUP.
+    (let ((articles
+          (directory-files
+           nndiary-current-directory t
+           (concat nnheader-numerical-short-files
+                   "\\|" (regexp-quote nndiary-nov-file-name) "$")))
+         article)
+      (while articles
+       (setq article (pop articles))
+       (when (file-writable-p article)
+         (nnheader-message 5 "Deleting article %s in %s..." article group)
+         (funcall nnmail-delete-file-function article))))
+    ;; Try to delete the directory itself.
+    (ignore-errors (delete-directory nndiary-current-directory)))
+  ;; Remove the group from all structures.
+  (setq nndiary-group-alist
+       (delq (assoc group nndiary-group-alist) nndiary-group-alist)
+       nndiary-current-group nil
+       nndiary-current-directory nil)
+  ;; Save the active file.
+  (nnmail-save-active nndiary-group-alist nndiary-active-file)
+  t)
+
+(deffoo nndiary-request-rename-group (group new-name &optional server)
+  (nndiary-possibly-change-directory group server)
+  (let ((new-dir (nnmail-group-pathname new-name nndiary-directory))
+       (old-dir (nnmail-group-pathname group nndiary-directory)))
+    (when (ignore-errors
+           (make-directory new-dir t)
+           t)
+      ;; We move the articles file by file instead of renaming
+      ;; the directory -- there may be subgroups in this group.
+      ;; One might be more clever, I guess.
+      (let ((files (nnheader-article-to-file-alist old-dir)))
+       (while files
+         (rename-file
+          (concat old-dir (cdar files))
+          (concat new-dir (cdar files)))
+         (pop files)))
+      ;; Move .overview file.
+      (let ((overview (concat old-dir nndiary-nov-file-name)))
+       (when (file-exists-p overview)
+         (rename-file overview (concat new-dir nndiary-nov-file-name))))
+      (when (<= (length (directory-files old-dir)) 2)
+       (ignore-errors (delete-directory old-dir)))
+      ;; That went ok, so we change the internal structures.
+      (let ((entry (assoc group nndiary-group-alist)))
+       (when entry
+         (setcar entry new-name))
+       (setq nndiary-current-directory nil
+             nndiary-current-group nil)
+       ;; Save the new group alist.
+       (nnmail-save-active nndiary-group-alist nndiary-active-file)
+       t))))
+
+(deffoo nndiary-set-status (article name value &optional group server)
+  (nndiary-possibly-change-directory group server)
+  (let ((file (nndiary-article-to-file article)))
+    (cond
+     ((not (file-exists-p file))
+      (nnheader-report 'nndiary "File %s does not exist" file))
+     (t
+      (with-temp-file file
+       (nnheader-insert-file-contents file)
+       (nnmail-replace-status name value))
+      t))))
+
+\f
+;;; Interface optional functions ============================================
+
+(deffoo nndiary-request-update-info (group info &optional server)
+  (nndiary-possibly-change-directory group)
+  (let ((timestamp (gnus-group-parameter-value (gnus-info-params info)
+                                              'timestamp t)))
+    (if (not timestamp)
+       (nnheader-report 'nndiary "Group %s doesn't have a timestamp" group)
+      ;; else
+      ;; Figure out which articles should be re-new'ed
+      (let ((articles (nndiary-flatten (gnus-info-read info) 0))
+           article file unread buf)
+       (save-excursion
+         (setq buf (nnheader-set-temp-buffer " *nndiary update*"))
+         (while (setq article (pop articles))
+           (setq file (concat nndiary-current-directory
+                              (int-to-string article)))
+           (and (file-exists-p file)
+                (nndiary-renew-article-p file timestamp)
+                (push article unread)))
+         ;;(message "unread: %s" unread)
+         (sit-for 1)
+         (kill-buffer buf))
+       (setq unread (sort unread '<))
+       (and unread
+            (gnus-info-set-read info (gnus-update-read-articles
+                                      (gnus-info-group info) unread t)))
+       ))
+    (run-hook-with-args 'nndiary-request-update-info-hooks
+                       (gnus-info-group info))
+    t))
+
+
+\f
+;;; Internal functions ======================================================
+
+(defun nndiary-article-to-file (article)
+  (nndiary-update-file-alist)
+  (let (file)
+    (if (setq file (cdr (assq article nndiary-article-file-alist)))
+       (expand-file-name file nndiary-current-directory)
+      ;; Just to make sure nothing went wrong when reading over NFS --
+      ;; check once more.
+      (if nndiary-check-directory-twice
+         (when (file-exists-p
+                (setq file (expand-file-name (number-to-string article)
+                                             nndiary-current-directory)))
+           (nndiary-update-file-alist t)
+           file)))))
+
+(defun nndiary-deletable-article-p (group article)
+  "Say whether ARTICLE in GROUP can be deleted."
+  (let (path)
+    (when (setq path (nndiary-article-to-file article))
+      (when (file-writable-p path)
+       (or (not nnmail-keep-last-article)
+           (not (eq (cdr (nth 1 (assoc group nndiary-group-alist)))
+                    article)))))))
+
+;; Find an article number in the current group given the Message-ID.
+(defun nndiary-find-group-number (id)
+  (save-excursion
+    (set-buffer (get-buffer-create " *nndiary id*"))
+    (let ((alist nndiary-group-alist)
+         number)
+      ;; We want to look through all .overview files, but we want to
+      ;; start with the one in the current directory.  It seems most
+      ;; likely that the article we are looking for is in that group.
+      (if (setq number (nndiary-find-id nndiary-current-group id))
+         (cons nndiary-current-group number)
+       ;; It wasn't there, so we look through the other groups as well.
+       (while (and (not number)
+                   alist)
+         (or (string= (caar alist) nndiary-current-group)
+             (setq number (nndiary-find-id (caar alist) id)))
+         (or number
+             (setq alist (cdr alist))))
+       (and number
+            (cons (caar alist) number))))))
+
+(defun nndiary-find-id (group id)
+  (erase-buffer)
+  (let ((nov (expand-file-name nndiary-nov-file-name
+                              (nnmail-group-pathname group
+                                                     nndiary-directory)))
+       number found)
+    (when (file-exists-p nov)
+      (nnheader-insert-file-contents nov)
+      (while (and (not found)
+                 (search-forward id nil t)) ; We find the ID.
+       ;; And the id is in the fourth field.
+       (if (not (and (search-backward "\t" nil t 4)
+                     (not (search-backward"\t" (gnus-point-at-bol) t))))
+           (forward-line 1)
+         (beginning-of-line)
+         (setq found t)
+         ;; We return the article number.
+         (setq number
+               (ignore-errors (read (current-buffer))))))
+      number)))
+
+(defun nndiary-retrieve-headers-with-nov (articles &optional fetch-old)
+  (if (or gnus-nov-is-evil nndiary-nov-is-evil)
+      nil
+    (let ((nov (expand-file-name nndiary-nov-file-name
+                                nndiary-current-directory)))
+      (when (file-exists-p nov)
+       (save-excursion
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (nnheader-insert-file-contents nov)
+         (if (and fetch-old
+                  (not (numberp fetch-old)))
+             t                         ; Don't remove anything.
+           (nnheader-nov-delete-outside-range
+            (if fetch-old (max 1 (- (car articles) fetch-old))
+              (car articles))
+            (car (last articles)))
+           t))))))
+
+(defun nndiary-possibly-change-directory (group &optional server)
+  (when (and server
+            (not (nndiary-server-opened server)))
+    (nndiary-open-server server))
+  (if (not group)
+      t
+    (let ((pathname (nnmail-group-pathname group nndiary-directory))
+         (file-name-coding-system nnmail-pathname-coding-system))
+      (when (not (equal pathname nndiary-current-directory))
+       (setq nndiary-current-directory pathname
+             nndiary-current-group group
+             nndiary-article-file-alist nil))
+      (file-exists-p nndiary-current-directory))))
+
+(defun nndiary-possibly-create-directory (group)
+  (let ((dir (nnmail-group-pathname group nndiary-directory)))
+    (unless (file-exists-p dir)
+      (make-directory (directory-file-name dir) t)
+      (nnheader-message 5 "Creating mail directory %s" dir))))
+
+(defun nndiary-save-mail (group-art)
+  "Called narrowed to an article."
+  (let (chars headers)
+    (setq chars (nnmail-insert-lines))
+    (nnmail-insert-xref group-art)
+    (run-hooks 'nnmail-prepare-save-mail-hook)
+    (run-hooks 'nndiary-prepare-save-mail-hook)
+    (goto-char (point-min))
+    (while (looking-at "From ")
+      (replace-match "X-From-Line: ")
+      (forward-line 1))
+    ;; We save the article in all the groups it belongs in.
+    (let ((ga group-art)
+         first)
+      (while ga
+       (nndiary-possibly-create-directory (caar ga))
+       (let ((file (concat (nnmail-group-pathname
+                            (caar ga) nndiary-directory)
+                           (int-to-string (cdar ga)))))
+         (if first
+             ;; It was already saved, so we just make a hard link.
+             (funcall nnmail-crosspost-link-function first file t)
+           ;; Save the article.
+           (nnmail-write-region (point-min) (point-max) file nil
+                                (if (nnheader-be-verbose 5) nil 'nomesg))
+           (setq first file)))
+       (setq ga (cdr ga))))
+    ;; Generate a nov line for this article.  We generate the nov
+    ;; line after saving, because nov generation destroys the
+    ;; header.
+    (setq headers (nndiary-parse-head chars))
+    ;; Output the nov line to all nov databases that should have it.
+    (let ((ga group-art))
+      (while ga
+       (nndiary-add-nov (caar ga) (cdar ga) headers)
+       (setq ga (cdr ga))))
+    group-art))
+
+(defun nndiary-active-number (group)
+  "Compute the next article number in GROUP."
+  (let ((active (cadr (assoc group nndiary-group-alist))))
+    ;; The group wasn't known to nndiary, so we just create an active
+    ;; entry for it.
+    (unless active
+      ;; Perhaps the active file was corrupt?  See whether
+      ;; there are any articles in this group.
+      (nndiary-possibly-create-directory group)
+      (nndiary-possibly-change-directory group)
+      (unless nndiary-article-file-alist
+       (setq nndiary-article-file-alist
+             (sort
+              (nnheader-article-to-file-alist nndiary-current-directory)
+              'car-less-than-car)))
+      (setq active
+           (if nndiary-article-file-alist
+               (cons (caar nndiary-article-file-alist)
+                     (caar (last nndiary-article-file-alist)))
+             (cons 1 0)))
+      (push (list group active) nndiary-group-alist))
+    (setcdr active (1+ (cdr active)))
+    (while (file-exists-p
+           (expand-file-name (int-to-string (cdr active))
+                             (nnmail-group-pathname group nndiary-directory)))
+      (setcdr active (1+ (cdr active))))
+    (cdr active)))
+
+(defun nndiary-add-nov (group article headers)
+  "Add a nov line for the GROUP base."
+  (save-excursion
+    (set-buffer (nndiary-open-nov group))
+    (goto-char (point-max))
+    (mail-header-set-number headers article)
+    (nnheader-insert-nov headers)))
+
+(defsubst nndiary-header-value ()
+  (buffer-substring (match-end 0) (progn (end-of-line) (point))))
+
+(defun nndiary-parse-head (chars &optional number)
+  "Parse the head of the current buffer."
+  (save-excursion
+    (save-restriction
+      (unless (zerop (buffer-size))
+       (narrow-to-region
+        (goto-char (point-min))
+        (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
+      (let ((headers (nnheader-parse-naked-head)))
+       (mail-header-set-chars headers chars)
+       (mail-header-set-number headers number)
+       headers))))
+
+(defun nndiary-open-nov (group)
+  (or (cdr (assoc group nndiary-nov-buffer-alist))
+      (let ((buffer (get-buffer-create (format " *nndiary overview %s*"
+                                              group))))
+       (save-excursion
+         (set-buffer buffer)
+         (set (make-local-variable 'nndiary-nov-buffer-file-name)
+              (expand-file-name
+               nndiary-nov-file-name
+               (nnmail-group-pathname group nndiary-directory)))
+         (erase-buffer)
+         (when (file-exists-p nndiary-nov-buffer-file-name)
+           (nnheader-insert-file-contents nndiary-nov-buffer-file-name)))
+       (push (cons group buffer) nndiary-nov-buffer-alist)
+       buffer)))
+
+(defun nndiary-save-nov ()
+  (save-excursion
+    (while nndiary-nov-buffer-alist
+      (when (buffer-name (cdar nndiary-nov-buffer-alist))
+       (set-buffer (cdar nndiary-nov-buffer-alist))
+       (when (buffer-modified-p)
+         (nnmail-write-region 1 (point-max) nndiary-nov-buffer-file-name
+                              nil 'nomesg))
+       (set-buffer-modified-p nil)
+       (kill-buffer (current-buffer)))
+      (setq nndiary-nov-buffer-alist (cdr nndiary-nov-buffer-alist)))))
+
+;;;###autoload
+(defun nndiary-generate-nov-databases (&optional server)
+  "Generate NOV databases in all nndiary directories."
+  (interactive (list (or (nnoo-current-server 'nndiary) "")))
+  ;; Read the active file to make sure we don't re-use articles
+  ;; numbers in empty groups.
+  (nnmail-activate 'nndiary)
+  (unless (nndiary-server-opened server)
+    (nndiary-open-server server))
+  (setq nndiary-directory (expand-file-name nndiary-directory))
+  ;; Recurse down the directories.
+  (nndiary-generate-nov-databases-1 nndiary-directory nil t)
+  ;; Save the active file.
+  (nnmail-save-active nndiary-group-alist nndiary-active-file))
+
+(defun nndiary-generate-nov-databases-1 (dir &optional seen no-active)
+  "Regenerate the NOV database in DIR."
+  (interactive "DRegenerate NOV in: ")
+  (setq dir (file-name-as-directory dir))
+  ;; Only scan this sub-tree if we haven't been here yet.
+  (unless (member (file-truename dir) seen)
+    (push (file-truename dir) seen)
+    ;; We descend recursively
+    (let ((dirs (directory-files dir t nil t))
+         dir)
+      (while (setq dir (pop dirs))
+       (when (and (not (string-match "^\\." (file-name-nondirectory dir)))
+                  (file-directory-p dir))
+         (nndiary-generate-nov-databases-1 dir seen))))
+    ;; Do this directory.
+    (let ((files (sort (nnheader-article-to-file-alist dir)
+                      'car-less-than-car)))
+      (if (not files)
+         (let* ((group (nnheader-file-to-group
+                        (directory-file-name dir) nndiary-directory))
+                (info (cadr (assoc group nndiary-group-alist))))
+           (when info
+             (setcar info (1+ (cdr info)))))
+       (funcall nndiary-generate-active-function dir)
+       ;; Generate the nov file.
+       (nndiary-generate-nov-file dir files)
+       (unless no-active
+         (nnmail-save-active nndiary-group-alist nndiary-active-file))))))
+
+(eval-when-compile (defvar files))
+(defun nndiary-generate-active-info (dir)
+  ;; Update the active info for this group.
+  (let* ((group (nnheader-file-to-group
+                (directory-file-name dir) nndiary-directory))
+        (entry (assoc group nndiary-group-alist))
+        (last (or (caadr entry) 0)))
+    (setq nndiary-group-alist (delq entry nndiary-group-alist))
+    (push (list group
+               (cons (or (caar files) (1+ last))
+                     (max last
+                          (or (let ((f files))
+                                (while (cdr f) (setq f (cdr f)))
+                                (caar f))
+                              0))))
+         nndiary-group-alist)))
+
+(defun nndiary-generate-nov-file (dir files)
+  (let* ((dir (file-name-as-directory dir))
+        (nov (concat dir nndiary-nov-file-name))
+        (nov-buffer (get-buffer-create " *nov*"))
+        chars file headers)
+    (save-excursion
+      ;; Init the nov buffer.
+      (set-buffer nov-buffer)
+      (buffer-disable-undo)
+      (erase-buffer)
+      (set-buffer nntp-server-buffer)
+      ;; Delete the old NOV file.
+      (when (file-exists-p nov)
+       (funcall nnmail-delete-file-function nov))
+      (while files
+       (unless (file-directory-p (setq file (concat dir (cdar files))))
+         (erase-buffer)
+         (nnheader-insert-file-contents file)
+         (narrow-to-region
+          (goto-char (point-min))
+          (progn
+            (search-forward "\n\n" nil t)
+            (setq chars (- (point-max) (point)))
+            (max 1 (1- (point)))))
+         (unless (zerop (buffer-size))
+           (goto-char (point-min))
+           (setq headers (nndiary-parse-head chars (caar files)))
+           (save-excursion
+             (set-buffer nov-buffer)
+             (goto-char (point-max))
+             (nnheader-insert-nov headers)))
+         (widen))
+       (setq files (cdr files)))
+      (save-excursion
+       (set-buffer nov-buffer)
+       (nnmail-write-region 1 (point-max) nov nil 'nomesg)
+       (kill-buffer (current-buffer))))))
+
+(defun nndiary-nov-delete-article (group article)
+  (save-excursion
+    (set-buffer (nndiary-open-nov group))
+    (when (nnheader-find-nov-line article)
+      (delete-region (point) (progn (forward-line 1) (point)))
+      (when (bobp)
+       (let ((active (cadr (assoc group nndiary-group-alist)))
+             num)
+         (when active
+           (if (eobp)
+               (setf (car active) (1+ (cdr active)))
+             (when (and (setq num (ignore-errors (read (current-buffer))))
+                        (numberp num))
+               (setf (car active) num)))))))
+    t))
+
+(defun nndiary-update-file-alist (&optional force)
+  (when (or (not nndiary-article-file-alist)
+           force)
+    (setq nndiary-article-file-alist
+         (nnheader-article-to-file-alist nndiary-current-directory))))
+
+
+(defun nndiary-string-to-int (str min &optional max)
+  ;; Like `string-to-int' but barf if STR is not exactly an integer, and not
+  ;; within the specified bounds.
+  ;; Signals are caught by `nndiary-schedule'.
+  (if (not (string-match "^[ \t]*[0-9]+[ \t]*$" str))
+      (nndiary-error "not an integer value")
+    ;; else
+    (let ((val (string-to-int str)))
+      (and (or (< val min)
+              (and max (> val max)))
+          (nndiary-error "value out of range"))
+      val)))
+
+(defun nndiary-parse-schedule-value (str min-or-values max)
+  ;; Parse the schedule string STR, or signal an error.
+  ;; Signals are caught by `nndary-schedule'.
+  (if (string-match "[ \t]*\\*[ \t]*" str)
+      ;; unspecifyed
+      nil
+    ;; specifyed
+    (if (listp min-or-values)
+       ;; min-or-values is values
+       ;; #### NOTE: this is actually only a hack for time zones.
+       (let ((val (and (string-match "[ \t]*\\([^ \t]+\\)[ \t]*" str)
+                       (match-string 1 str))))
+         (if (and val (setq val (assoc val min-or-values)))
+             (list (cadr val))
+           (nndiary-error "invalid syntax")))
+      ;; min-or-values is min
+      (mapcar
+       (lambda (val)
+        (let ((res (split-string val "-")))
+          (cond
+           ((= (length res) 1)
+            (nndiary-string-to-int (car res) min-or-values max))
+           ((= (length res) 2)
+            ;; don't know if crontab accepts this, but ensure
+            ;; that BEG is <= END
+            (let ((beg (nndiary-string-to-int (car res) min-or-values max))
+                  (end (nndiary-string-to-int (cadr res) min-or-values max)))
+              (cond ((< beg end)
+                     (cons beg end))
+                    ((= beg end)
+                     beg)
+                    (t
+                     (cons end beg)))))
+           (t
+            (nndiary-error "invalid syntax")))
+          ))
+       (split-string str ",")))
+    ))
+
+;; ### FIXME: remove this function if it's used only once.
+(defun nndiary-parse-schedule (head min-or-values max)
+  ;; Parse the cron-like value of header X-Diary-HEAD in current buffer.
+  ;; - Returns nil if `*'
+  ;; - Otherwise returns a list of integers and/or ranges (BEG . END)
+  ;; The exception is the Timze-Zone value which is always of the form (STR).
+  ;; Signals are caught by `nndary-schedule'.
+  (let ((header (format "^X-Diary-%s: \\(.*\\)$" head)))
+    (goto-char (point-min))
+    (if (not (re-search-forward header nil t))
+       (nndiary-error "header missing")
+      ;; else
+      (nndiary-parse-schedule-value (match-string 1) min-or-values max))
+    ))
+
+(defun nndiary-max (spec)
+  ;; Returns the max of specification SPEC, or nil for permanent schedules.
+  (unless (null spec)
+    (let ((elts spec)
+         (max 0)
+         elt)
+      (while (setq elt (pop elts))
+       (if (integerp elt)
+           (and (> elt max) (setq max elt))
+         (and (> (cdr elt) max) (setq max (cdr elt)))))
+      max)))
+
+(defun nndiary-flatten (spec min &optional max)
+  ;; flatten the spec by expanding ranges to all possible values.
+  (let (flat n)
+    (cond ((null spec)
+          ;; this happens when I flatten something else than one of my
+          ;; schedules (a list of read articles for instance).
+          (unless (null max)
+            (setq n min)
+            (while (<= n max)
+              (push n flat)
+              (setq n (1+ n)))))
+         (t
+          (let ((elts spec)
+                elt)
+            (while (setq elt (pop elts))
+              (if (integerp elt)
+                  (push elt flat)
+                ;; else
+                (setq n (car elt))
+                (while (<= n (cdr elt))
+                  (push n flat)
+                  (setq n (1+ n))))))))
+    flat))
+
+(defun nndiary-unflatten (spec)
+  ;; opposite of flatten: build ranges if possible
+  (setq spec (sort spec '<))
+  (let (min max res)
+    (while (setq min (pop spec))
+      (setq max min)
+      (while (and (car spec) (= (car spec) (1+ max)))
+       (setq max (1+ max))
+       (pop spec))
+      (if (= max min)
+         (setq res (append res (list min)))
+       (setq res (append res (list (cons min max))))))
+    res))
+
+(defun nndiary-compute-reminders (date)
+  ;; Returns a list of times corresponding to the reminders of date DATE.
+  ;; See the comment in `nndiary-reminders' about rounding.
+  (let* ((reminders nndiary-reminders)
+        (date-elts (decode-time date))
+        ;; ### NOTE: out-of-range values are accepted by encode-time. This
+        ;; makes our life easier.
+        (monday (- (nth 3 date-elts)
+                   (if nndiary-week-starts-on-monday
+                       (if (zerop (nth 6 date-elts))
+                           6
+                         (- (nth 6 date-elts) 1))
+                     (nth 6 date-elts))))
+        reminder res)
+    ;; remove the DOW and DST entries
+    (setcdr (nthcdr 5 date-elts) (nthcdr 8 date-elts))
+    (while (setq reminder (pop reminders))
+      (push
+       (cond ((eq (cdr reminder) 'minute)
+             (subtract-time
+              (apply 'encode-time 0 (nthcdr 1 date-elts))
+              (seconds-to-time (* (car reminder) 60.0))))
+            ((eq (cdr reminder) 'hour)
+             (subtract-time
+              (apply 'encode-time 0 0 (nthcdr 2 date-elts))
+              (seconds-to-time (* (car reminder) 3600.0))))
+            ((eq (cdr reminder) 'day)
+             (subtract-time
+              (apply 'encode-time 0 0 0 (nthcdr 3 date-elts))
+              (seconds-to-time (* (car reminder) 86400.0))))
+            ((eq (cdr reminder) 'week)
+             (subtract-time
+              (apply 'encode-time 0 0 0 monday (nthcdr 4 date-elts))
+              (seconds-to-time (* (car reminder) 604800.0))))
+            ((eq (cdr reminder) 'month)
+             (subtract-time
+              (apply 'encode-time 0 0 0 1 (nthcdr 4 date-elts))
+              (seconds-to-time (* (car reminder) 18748800.0))))
+            ((eq (cdr reminder) 'year)
+             (subtract-time
+              (apply 'encode-time 0 0 0 1 1 (nthcdr 5 date-elts))
+              (seconds-to-time (* (car reminder) 400861056.0)))))
+       res))
+    (sort res 'time-less-p)))
+
+(defun nndiary-last-occurence (sched)
+  ;; Returns the last occurence of schedule SCHED as an Emacs time struct, or
+  ;; nil for permanent schedule or errors.
+  (let ((minute (nndiary-max (nth 0 sched)))
+       (hour (nndiary-max (nth 1 sched)))
+       (year (nndiary-max (nth 4 sched)))
+       (time-zone (or (and (nth 6 sched) (car (nth 6 sched)))
+                      (current-time-zone))))
+    (when year
+      (or minute (setq minute 59))
+      (or hour (setq hour 23))
+      ;; I'll just compute all possible values and test them by decreasing
+      ;; order until one succeeds. This is probably quide rude, but I got
+      ;; bored in finding a good algorithm for doing that ;-)
+      ;; ### FIXME: remove identical entries.
+      (let ((dom-list (nth 2 sched))
+           (month-list (sort (nndiary-flatten (nth 3 sched) 1 12) '>))
+           (year-list (sort (nndiary-flatten (nth 4 sched) 1971) '>))
+           (dow-list (nth 5 sched)))
+       ;; Special case: an asterisk in one of the days specifications means
+       ;; that only the other should be taken into account. If both are
+       ;; unspecified, you would get all possible days in both.
+       (cond ((null dow-list)
+              ;; this gets all days if dom-list is nil
+              (setq dom-list (nndiary-flatten dom-list 1 31)))
+             ((null dom-list)
+              ;; this also gets all days if dow-list is nil
+              (setq dow-list (nndiary-flatten dow-list 0 6)))
+             (t
+              (setq dom-list (nndiary-flatten dom-list 1 31))
+              (setq dow-list (nndiary-flatten dow-list 0 6))))
+       (or
+        (catch 'found
+          (while (setq year (pop year-list))
+            (let ((months month-list)
+                  month)
+              (while (setq month (pop months))
+                ;; Now we must merge the Dows with the Doms. To do that, we
+                ;; have to know which day is the 1st one for this month.
+                ;; Maybe there's simpler, but decode-time(encode-time) will
+                ;; give us the answer.
+                (let ((first (nth 6 (decode-time
+                                     (encode-time 0 0 0 1 month year
+                                                  time-zone))))
+                      (max (cond ((= month 2)
+                                  (if (date-leap-year-p year) 29 28))
+                                 ((<= month 7)
+                                  (if (zerop (% month 2)) 30 31))
+                                 (t
+                                  (if (zerop (% month 2)) 31 30))))
+                      (doms dom-list)
+                      (dows dow-list)
+                      day days)
+                  ;; first, review the doms to see if they are valid.
+                  (while (setq day (pop doms))
+                    (and (<= day max)
+                         (push day days)))
+                  ;; second add all possible dows
+                  (while (setq day (pop dows))
+                    ;; days start at 1.
+                    (setq day (1+ (- day first)))
+                    (and (< day 0) (setq day (+ 7 day)))
+                    (while (<= day max)
+                      (push day days)
+                      (setq day (+ 7 day))))
+                  ;; Finally, if we have some days, they are valid
+                  (when days
+                    (sort days '>)
+                    (throw 'found
+                           (encode-time 0 minute hour
+                                        (car days) month year time-zone)))
+                  )))))
+        ;; There's an upper limit, but we didn't find any last occurence.
+        ;; This means that the schedule is undecidable. This can happen if
+        ;; you happen to say something like "each Feb 31 until 2038".
+        (progn
+          (nnheader-report 'nndiary "Undecidable schedule")
+          nil))
+       ))))
+
+(defun nndiary-next-occurence (sched now)
+  ;; Returns the next occurence of schedule SCHED, starting from time NOW.
+  ;; If there's no next occurence, returns the last one (if any) which is then
+  ;; in the past.
+  (let* ((today (decode-time now))
+        (this-minute (nth 1 today))
+        (this-hour (nth 2 today))
+        (this-day (nth 3 today))
+        (this-month (nth 4 today))
+        (this-year (nth 5 today))
+        (minute-list (sort (nndiary-flatten (nth 0 sched) 0 59) '<))
+        (hour-list (sort (nndiary-flatten (nth 1 sched) 0 23) '<))
+        (dom-list (nth 2 sched))
+        (month-list (sort (nndiary-flatten (nth 3 sched) 1 12) '<))
+        (years (if (nth 4 sched)
+                   (sort (nndiary-flatten (nth 4 sched) 1971) '<)
+                 t))
+        (dow-list (nth 5 sched))
+        (year (1- this-year))
+        (time-zone (or (and (nth 6 sched) (car (nth 6 sched)))
+                       (current-time-zone))))
+    ;; Special case: an asterisk in one of the days specifications means that
+    ;; only the other should be taken into account. If both are unspecified,
+    ;; you would get all possible days in both.
+    (cond ((null dow-list)
+          ;; this gets all days if dom-list is nil
+          (setq dom-list (nndiary-flatten dom-list 1 31)))
+         ((null dom-list)
+          ;; this also gets all days if dow-list is nil
+          (setq dow-list (nndiary-flatten dow-list 0 6)))
+         (t
+          (setq dom-list (nndiary-flatten dom-list 1 31))
+          (setq dow-list (nndiary-flatten dow-list 0 6))))
+    ;; Remove past years.
+    (unless (eq years t)
+      (while (and (car years) (< (car years) this-year))
+       (pop years)))
+    (if years
+       ;; Because we might not be limited in years, we must guard against
+       ;; infinite loops. Appart from cases like Feb 31, there are probably
+       ;; other ones, (no monday XXX 2nd etc). I don't know any algorithm to
+       ;; decide this, so I assume that if we reach 10 years later, the
+       ;; schedule is undecidable.
+       (or
+        (catch 'found
+          (while (if (eq years t)
+                     (and (setq year (1+ year))
+                          (<= year (+ 10 this-year)))
+                   (setq year (pop years)))
+            (let ((months month-list)
+                  month)
+              ;; Remove past months for this year.
+              (and (= year this-year)
+                   (while (and (car months) (< (car months) this-month))
+                     (pop months)))
+              (while (setq month (pop months))
+                ;; Now we must merge the Dows with the Doms. To do that, we
+                ;; have to know which day is the 1st one for this month.
+                ;; Maybe there's simpler, but decode-time(encode-time) will
+                ;; give us the answer.
+                (let ((first (nth 6 (decode-time
+                                     (encode-time 0 0 0 1 month year
+                                                  time-zone))))
+                      (max (cond ((= month 2)
+                                  (if (date-leap-year-p year) 29 28))
+                                 ((<= month 7)
+                                  (if (zerop (% month 2)) 30 31))
+                                 (t
+                                  (if (zerop (% month 2)) 31 30))))
+                      (doms dom-list)
+                      (dows dow-list)
+                      day days)
+                  ;; first, review the doms to see if they are valid.
+                  (while (setq day (pop doms))
+                    (and (<= day max)
+                         (push day days)))
+                  ;; second add all possible dows
+                  (while (setq day (pop dows))
+                    ;; days start at 1.
+                    (setq day (1+ (- day first)))
+                    (and (< day 0) (setq day (+ 7 day)))
+                    (while (<= day max)
+                      (push day days)
+                      (setq day (+ 7 day))))
+                  ;; Aaaaaaall right. Now we have a valid list of DAYS for
+                  ;; this month and this year.
+                  (when days
+                    (setq days (sort days '<))
+                    ;; Remove past days for this year and this month.
+                    (and (= year this-year)
+                         (= month this-month)
+                         (while (and (car days) (< (car days) this-day))
+                           (pop days)))
+                    (while (setq day (pop days))
+                      (let ((hours hour-list)
+                            hour)
+                        ;; Remove past hours for this year, this month and
+                        ;; this day.
+                        (and (= year this-year)
+                             (= month this-month)
+                             (= day this-day)
+                             (while (and (car hours)
+                                         (< (car hours) this-hour))
+                               (pop hours)))
+                        (while (setq hour (pop hours))
+                          (let ((minutes minute-list)
+                                minute)
+                            ;; Remove past hours for this year, this month,
+                            ;; this day and this hour.
+                            (and (= year this-year)
+                                 (= month this-month)
+                                 (= day this-day)
+                                 (= hour this-hour)
+                                 (while (and (car minutes)
+                                             (< (car minutes) this-minute))
+                                   (pop minutes)))
+                            (while (setq minute (pop minutes))
+                              ;; Ouch! Here, we've got a complete valid
+                              ;; schedule. It's a good one if it's in the
+                              ;; future.
+                              (let ((time (encode-time 0 minute hour day
+                                                       month year
+                                                       time-zone)))
+                                (and (time-less-p now time)
+                                     (throw 'found time)))
+                              ))))
+                      ))
+                  )))
+            ))
+        (nndiary-last-occurence sched))
+      ;; else
+      (nndiary-last-occurence sched))
+    ))
+
+(defun nndiary-expired-article-p (file)
+  (with-temp-buffer
+    (if (nnheader-insert-head file)
+       (let ((sched (nndiary-schedule)))
+         ;; An article has expired if its last schedule (if any) is in the
+         ;; past. A permanent schedule never expires.
+         (and sched
+              (setq sched (nndiary-last-occurence sched))
+              (time-less-p sched (current-time))))
+      ;; else
+      (nnheader-report 'nndiary "Could not read file %s" file)
+      nil)
+    ))
+
+(defun nndiary-renew-article-p (file timestamp)
+  (erase-buffer)
+  (if (nnheader-insert-head file)
+      (let ((now (current-time))
+           (sched (nndiary-schedule)))
+       ;; The article should be re-considered as unread if there's a reminder
+       ;; between the group timestamp and the current time.
+       (when (and sched (setq sched (nndiary-next-occurence sched now)))
+         (let ((reminders ;; add the next occurence itself at the end.
+                (append (nndiary-compute-reminders sched) (list sched))))
+           (while (and reminders (time-less-p (car reminders) timestamp))
+             (pop reminders))
+           ;; The reminders might be empty if the last date is in the past,
+           ;; or we've got at least the next occurence itself left. All past
+           ;; dates are renewed.
+           (or (not reminders)
+               (time-less-p (car reminders) now)))
+         ))
+    ;; else
+    (nnheader-report 'nndiary "Could not read file %s" file)
+    nil))
+
+;; The end... ===============================================================
+
+(mapcar
+ (lambda (elt)
+   (let ((header (intern (format "X-Diary-%s" (car elt)))))
+     ;; Required for building NOV databases and some other stuff
+     (add-to-list 'gnus-extra-headers header)
+     (add-to-list 'nnmail-extra-headers header)))
+ nndiary-headers)
+
+(unless (assoc "nndiary" gnus-valid-select-methods)
+  (gnus-declare-backend "nndiary" 'post-mail 'respool 'address))
+
+(provide 'nndiary)
+
+
+;;; nndiary.el ends here
index 968637d..f1a6635 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nndir.el --- single directory newsgroup access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 (nnoo-map-functions nndir
   (nnml-retrieve-headers 0 nndir-current-group 0 0)
-  (nnmh-request-article 0 nndir-current-group 0 0)
+  (nnml-request-article 0 nndir-current-group 0 0)
   (nnmh-request-group nndir-current-group 0 0)
   (nnml-close-group nndir-current-group 0)
-  (nnmh-request-list (nnoo-current-server 'nndir) nndir-directory)
-  (nnmh-request-newsgroups (nnoo-current-server 'nndir) nndir-directory))
+  (nnml-request-list (nnoo-current-server 'nndir) nndir-directory)
+  (nnml-request-newsgroups (nnoo-current-server 'nndir) nndir-directory))
 
 (provide 'nndir)
 
index 067b2a8..2c008f3 100644 (file)
@@ -1,8 +1,9 @@
 ;;; nndoc.el --- single file access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Commentary:
 
+;; For Outlook mail boxes format, see http://mbx2mbox.sourceforge.net/
+
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nnheader)
 (require 'message)
 (require 'nnmail)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
+(require 'gnus-util)
 
 (nnoo-declare nndoc)
 
 (defvoo nndoc-article-type 'guess
   "*Type of the file.
 One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
-`rfc934', `rfc822-forward', `mime-digest', `standard-digest',
-`slack-digest', `clari-briefs' or `guess'.")
+`rfc934', `rfc822-forward', `mime-parts', `standard-digest',
+`slack-digest', `clari-briefs', `nsmail', `outlook', `oe-dbx',
+`mailman', `exim-bounce', or `guess'.")
 
 (defvoo nndoc-post-type 'mail
   "*Whether the nndoc group is `mail' or `post'.")
@@ -46,12 +52,24 @@ One of `mbox', `babyl', `digest', `news', `rnews', `mmdf', `forward',
 (defvoo nndoc-open-document-hook 'nnheader-ms-strip-cr
   "Hook run after opening a document.
 The default function removes all trailing carriage returns
-from the document.")  
+from the document.")
 
 (defvar nndoc-type-alist
   `((mmdf
      (article-begin .  "^\^A\^A\^A\^A\n")
      (body-end .  "^\^A\^A\^A\^A\n"))
+    (mime-digest
+     (article-begin . "")
+     (head-begin . "^ ?\n")
+     (head-end . "^ ?$")
+     (body-end . "")
+     (file-end . "")
+     (subtype digest guess))
+    (mime-parts
+     (generate-head-function . nndoc-generate-mime-parts-head)
+     (article-transform-function . nndoc-transform-mime-parts))
+    (nsmail
+     (article-begin .  "^From - "))
     (news
      (article-begin . "^Path:"))
     (rnews
@@ -65,14 +83,17 @@ from the document.")
      (body-end . "\^_")
      (body-begin-function . nndoc-babyl-body-begin)
      (head-begin-function . nndoc-babyl-head-begin))
-    (forward
-     (article-begin . "^-+ Start of forwarded message -+\n+")
-     (body-end . "^-+ End of forwarded message -+$")
-     (prepare-body-function . nndoc-unquote-dashes))
+    (exim-bounce
+     (article-begin . "^------ This is a copy of the message, including all the headers. ------\n\n")
+     (body-end-function . nndoc-exim-bounce-body-end-function))
     (rfc934
      (article-begin . "^--.*\n+")
      (body-end . "^--.*$")
      (prepare-body-function . nndoc-unquote-dashes))
+    (mailman
+     (article-begin . "^--__--__--\n\nMessage:")
+     (body-end . "^--__--__--$")
+     (prepare-body-function . nndoc-unquote-dashes))
     (clari-briefs
      (article-begin . "^ \\*")
      (body-end . "^\t------*[ \t]^*\n^ \\*")
@@ -80,15 +101,10 @@ from the document.")
      (head-end . "^\t")
      (generate-head-function . nndoc-generate-clari-briefs-head)
      (article-transform-function . nndoc-transform-clari-briefs))
-    (mime-digest
-     (article-begin . "")
-     (head-end . "^ ?$")
-     (body-end . "")
-     (file-end . "")
-     (subtype digest guess))
+    
     (standard-digest
-     (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
-     (article-begin . ,(concat "^\n" (make-string 30 ?-) "\n\n+"))
+     (first-article . ,(concat "^" (make-string 70 ?-) "\n *\n+"))
+     (article-begin . ,(concat "^\n" (make-string 30 ?-) "\n *\n+"))
      (prepare-body-function . nndoc-unquote-dashes)
      (body-end-function . nndoc-digest-body-end)
      (head-end . "^ *$")
@@ -108,14 +124,27 @@ from the document.")
      (head-begin . "^Paper.*:")
      (head-end   . "\\(^\\\\\\\\.*\n\\|-----------------\\)")
      (body-begin . "")
-     (body-end   . "-------------------------------------------------")
-     (file-end   . "^Title: Recent Seminal")
+     (body-end   . "\\(-------------------------------------------------\\|%-%-%-%-%-%-%-%-%-%-%-%-%-%-\\|%%--%%--%%--%%--%%--%%--%%--%%--\\|%%%---%%%---%%%---%%%---\\)")
+     (file-end   . "\\(^Title: Recent Seminal\\|%%%---%%%---%%%---%%%---\\)")
      (generate-head-function . nndoc-generate-lanl-gov-head)
      (article-transform-function . nndoc-transform-lanl-gov-announce)
      (subtype preprints guess))
     (rfc822-forward
      (article-begin . "^\n")
      (body-end-function . nndoc-rfc822-forward-body-end-function))
+    (outlook
+     (article-begin-function . nndoc-outlook-article-begin)
+     (body-end .  "\0"))
+    (oe-dbx  ;; Outlook Express DBX format
+     (dissection-function . nndoc-oe-dbx-dissection)
+     (generate-head-function . nndoc-oe-dbx-generate-head)
+     (generate-article-function . nndoc-oe-dbx-generate-article))
+    (forward
+     (article-begin . "^-+ \\(Start of \\)?forwarded message.*\n+")
+     (body-end . "^-+ End \\(of \\)?forwarded message.*$")
+     (prepare-body-function . nndoc-unquote-dashes))
+    (mail-in-mail ;; Wild guess on mailer daemon's messages or others
+     (article-begin-function . nndoc-mail-in-mail-article-begin))
     (guess
      (guess . t)
      (subtype nil))
@@ -126,11 +155,12 @@ from the document.")
      (guess . t)
      (subtype nil))))
 
-\f
+(defvar nndoc-binary-file-names ".[Dd][Bb][Xx]$"
+  "Regexp for binary nndoc file names.")
 
+\f
 (defvoo nndoc-file-begin nil)
 (defvoo nndoc-first-article nil)
-(defvoo nndoc-article-end nil)
 (defvoo nndoc-article-begin nil)
 (defvoo nndoc-head-begin nil)
 (defvoo nndoc-head-end nil)
@@ -140,11 +170,21 @@ from the document.")
 (defvoo nndoc-body-begin-function nil)
 (defvoo nndoc-head-begin-function nil)
 (defvoo nndoc-body-end nil)
+;; nndoc-dissection-alist is a list of sublists.  Each sublist holds the
+;; following items.  ARTICLE acts as the association key and is an ordinal
+;; starting at 1.  HEAD-BEGIN [0], HEAD-END [1], BODY-BEGIN [2] and BODY-END
+;; [3] are positions in the `nndoc' buffer.  LINE-COUNT [4] is a count of
+;; lines in the body.  For MIME dissections only, ARTICLE-INSERT [5] and
+;; SUMMARY-INSERT [6] give headers to insert for full article or summary line
+;; generation, respectively.  Other headers usually follow directly from the
+;; buffer.  Value `nil' means no insert.
 (defvoo nndoc-dissection-alist nil)
 (defvoo nndoc-prepare-body-function nil)
 (defvoo nndoc-generate-head-function nil)
 (defvoo nndoc-article-transform-function nil)
 (defvoo nndoc-article-begin-function nil)
+(defvoo nndoc-generate-article-function nil)
+(defvoo nndoc-dissection-function nil)
 
 (defvoo nndoc-status-string "")
 (defvoo nndoc-group-alist nil)
@@ -178,7 +218,7 @@ from the document.")
                (insert-buffer-substring
                 nndoc-current-buffer (car entry) (nth 1 entry)))
              (goto-char (point-max))
-             (unless (= (char-after (1- (point))) ?\n)
+             (unless (eq (char-after (1- (point))) ?\n)
                (insert "\n"))
              (insert (format "Lines: %d\n" (nth 4 entry)))
              (insert ".\n")))
@@ -195,8 +235,11 @@ from the document.")
       (set-buffer buffer)
       (erase-buffer)
       (when entry
-       (if (stringp article)
-           nil
+       (cond
+        ((stringp article) nil)
+        (nndoc-generate-article-function
+         (funcall nndoc-generate-article-function article))
+        (t
          (insert-buffer-substring
           nndoc-current-buffer (car entry) (nth 1 entry))
          (insert "\n")
@@ -208,7 +251,7 @@ from the document.")
            (funcall nndoc-prepare-body-function))
          (when nndoc-article-transform-function
            (funcall nndoc-article-transform-function article))
-         t)))))
+         t))))))
 
 (deffoo nndoc-request-group (group &optional server dont-check)
   "Select news GROUP."
@@ -228,8 +271,8 @@ from the document.")
 
 (deffoo nndoc-request-type (group &optional article)
   (cond ((not article) 'unknown)
-        (nndoc-post-type nndoc-post-type)
-        (t 'unknown)))
+       (nndoc-post-type nndoc-post-type)
+       (t 'unknown)))
 
 (deffoo nndoc-close-group (group &optional server)
   (nndoc-possibly-change-buffer group server)
@@ -280,19 +323,24 @@ from the document.")
       (setq nndoc-dissection-alist nil)
       (save-excursion
        (set-buffer nndoc-current-buffer)
-       (buffer-disable-undo (current-buffer))
        (erase-buffer)
-       (if (stringp nndoc-address)
-           (nnheader-insert-file-contents nndoc-address)
-         (insert-buffer-substring nndoc-address))
-       (run-hooks 'nndoc-open-document-hook))))
+       (if (and (stringp nndoc-address)
+                (string-match nndoc-binary-file-names nndoc-address))
+           (let ((nnheader-file-coding-system 'binary))
+             (nnheader-insert-file-contents nndoc-address))
+         (if (stringp nndoc-address)
+             (nnheader-insert-file-contents nndoc-address)
+           (insert-buffer-substring nndoc-address))
+         (run-hooks 'nndoc-open-document-hook)))))
     ;; Initialize the nndoc structures according to this new document.
     (when (and nndoc-current-buffer
               (not nndoc-dissection-alist))
       (save-excursion
        (set-buffer nndoc-current-buffer)
        (nndoc-set-delims)
-       (nndoc-dissect-buffer)))
+       (if (eq nndoc-article-type 'mime-parts)
+           (nndoc-dissect-mime-parts)
+         (nndoc-dissect-buffer))))
     (unless nndoc-current-buffer
       (nndoc-close-server))
     ;; Return whether we managed to select a file.
@@ -306,12 +354,15 @@ from the document.")
   "Set the nndoc delimiter variables according to the type of the document."
   (let ((vars '(nndoc-file-begin
                nndoc-first-article
-               nndoc-article-end nndoc-head-begin nndoc-head-end
+               nndoc-article-begin-function
+               nndoc-head-begin nndoc-head-end
                nndoc-file-end nndoc-article-begin
                nndoc-body-begin nndoc-body-end-function nndoc-body-end
                nndoc-prepare-body-function nndoc-article-transform-function
                nndoc-generate-head-function nndoc-body-begin-function
-               nndoc-head-begin-function)))
+               nndoc-head-begin-function
+               nndoc-generate-article-function
+               nndoc-dissection-function)))
     (while vars
       (set (pop vars) nil)))
   (let (defs)
@@ -331,6 +382,9 @@ from the document.")
                (setq entry (pop alist)))
       (when (memq subtype (or (cdr (assq 'subtype entry)) '(guess)))
        (goto-char (point-min))
+       ;; Remove blank lines.
+       (while (eq (following-char) ?\n)
+         (delete-char 1))
        (when (numberp (setq result (funcall (intern
                                              (format "nndoc-%s-type-p"
                                                      (car entry))))))
@@ -340,7 +394,7 @@ from the document.")
       (error "Document is not of any recognized type"))
     (if result
        (car entry)
-      (cadar (sort results 'car-less-than-car)))))
+      (cadar (last (sort results 'car-less-than-car))))))
 
 ;;;
 ;;; Built-in type predicates and functions
@@ -413,10 +467,9 @@ from the document.")
     t))
 
 (defun nndoc-forward-type-p ()
-  (when (and (re-search-forward "^-+ Start of forwarded message -+\n+" nil t)
-            (not (re-search-forward "^Subject:.*digest" nil t))
-            (not (re-search-backward "^From:" nil t 2))
-            (not (re-search-forward "^From:" nil t 2)))
+  (when (and (re-search-forward "^-+ \\(Start of \\)?forwarded message.*\n+"
+                               nil t)
+            (looking-at "[\r\n]*[a-zA-Z][a-zA-Z0-9-]*:"))
     t))
 
 (defun nndoc-rfc934-type-p ()
@@ -426,6 +479,10 @@ from the document.")
             (not (re-search-forward "^From:" nil t 2)))
     t))
 
+(defun nndoc-mailman-type-p ()
+  (when (re-search-forward "^--__--__--\n+" nil t)
+    t))
+
 (defun nndoc-rfc822-forward-type-p ()
   (save-restriction
     (message-narrow-to-head)
@@ -435,6 +492,36 @@ from the document.")
 (defun nndoc-rfc822-forward-body-end-function ()
   (goto-char (point-max)))
 
+(defun nndoc-mime-parts-type-p ()
+  (let ((case-fold-search t)
+       (limit (search-forward "\n\n" nil t)))
+    (goto-char (point-min))
+    (when (and limit
+              (re-search-forward
+               (concat "\
+^Content-Type:[ \t]*multipart/[a-z]+ *; *\\(\\(\n[ \t]\\)?.*;\\)*"
+                       "\\(\n[ \t]\\)?[ \t]*boundary=\"?[^\"\n]*[^\" \t\n]")
+               limit t))
+      t)))
+
+(defun nndoc-transform-mime-parts (article)
+  (let* ((entry (cdr (assq article nndoc-dissection-alist)))
+        (headers (nth 5 entry)))
+    (when headers
+      (goto-char (point-min))
+      (insert headers))))
+
+(defun nndoc-generate-mime-parts-head (article)
+  (let* ((entry (cdr (assq article nndoc-dissection-alist)))
+        (headers (nth 6 entry)))
+    (save-restriction
+      (narrow-to-region (point) (point))
+      (insert-buffer-substring
+       nndoc-current-buffer (car entry) (nth 1 entry))
+      (goto-char (point-max)))
+    (when headers
+      (insert headers))))
+
 (defun nndoc-clari-briefs-type-p ()
   (when (let ((case-fold-search nil))
          (re-search-forward "^\t[^a-z]+ ([^a-z]+) --" nil t))
@@ -466,25 +553,34 @@ from the document.")
     (insert "From: " "clari@clari.net (" (or from "unknown") ")"
            "\nSubject: " (or subject "(no subject)") "\n")))
 
+(defun nndoc-exim-bounce-type-p ()
+  (and (re-search-forward "^------ This is a copy of the message, including all the headers. ------" nil t)
+       t))
+
+(defun nndoc-exim-bounce-body-end-function ()
+  (goto-char (point-max)))
+
+
 (defun nndoc-mime-digest-type-p ()
   (let ((case-fold-search t)
        boundary-id b-delimiter entry)
     (when (and
           (re-search-forward
            (concat "^Content-Type: *multipart/digest;[ \t\n]*[ \t]"
-                   "boundary=\"\\([^\"\n]*[^\" \t\n]\\)\"")
+                   "boundary=\"?\\([^\"\n]*[^\" \t\n]\\)")
            nil t)
           (match-beginning 1))
       (setq boundary-id (match-string 1)
-           b-delimiter (concat "\n--" boundary-id "[\n \t]+"))
+           b-delimiter (concat "\n--" boundary-id "[ \t]*$"))
       (setq entry (assq 'mime-digest nndoc-type-alist))
       (setcdr entry
              (list
+              (cons 'head-begin "^ ?\n")
               (cons 'head-end "^ ?$")
               (cons 'body-begin "^ ?\n")
               (cons 'article-begin b-delimiter)
               (cons 'body-end-function 'nndoc-digest-body-end)
-              (cons 'file-end (concat "\n--" boundary-id "--[ \t]*$"))))
+              (cons 'file-end (concat "^--" boundary-id "--[ \t]*$"))))
       t)))
 
 (defun nndoc-standard-digest-type-p ()
@@ -502,41 +598,166 @@ from the document.")
 
 (defun nndoc-lanl-gov-announce-type-p ()
   (when (let ((case-fold-search nil))
-         (re-search-forward "^\\\\\\\\\nPaper: [a-z-]+/[0-9]+" nil t))
+         (re-search-forward "^\\\\\\\\\nPaper\\( (\\*cross-listing\\*)\\)?: [a-zA-Z-\\.]+/[0-9]+" nil t))
     t))
 
 (defun nndoc-transform-lanl-gov-announce (article)
   (goto-char (point-max))
-  (when (re-search-backward "^\\\\\\\\ +(\\([^ ]*\\) , *\\([^ ]*\\))" nil t)
+  (when (re-search-backward "^\\\\\\\\ +( *\\([^ ]*\\) , *\\([^ ]*\\))" nil t)
     (replace-match "\n\nGet it at \\1 (\\2)" t nil))
-  ;;  (when (re-search-backward "^\\\\\\\\$" nil t)
-  ;;    (replace-match "" t t))
-  )
+  (goto-char (point-min))
+  (while (re-search-forward "^\\\\\\\\$" nil t)
+    (replace-match "" t nil))
+  (goto-char (point-min))
+  (when (re-search-forward "^replaced with revised version +\\(.*[^ ]\\) +" nil t)
+    (replace-match "Date: \\1 (revised) " t nil))
+  (goto-char (point-min))
+  (unless (re-search-forward "^From" nil t)
+    (goto-char (point-min))
+    (when (re-search-forward "^Authors?: \\(.*\\)" nil t)
+      (goto-char (point-min))
+      (insert "From: " (match-string 1) "\n"))))
 
 (defun nndoc-generate-lanl-gov-head (article)
   (let ((entry (cdr (assq article nndoc-dissection-alist)))
-       (e-mail "no address given")
-       subject from)
+       (from "<no address given>")
+       subject date)
     (save-excursion
       (set-buffer nndoc-current-buffer)
       (save-restriction
-       (narrow-to-region (car entry) (nth 1 entry))
-       (goto-char (point-min))
-       (when (looking-at "^Paper.*: \\([a-z-]+/[0-9]+\\)")
-         (setq subject (concat " (" (match-string 1) ")"))
-         (when (re-search-forward "^From: \\([^ ]+\\)" nil t)
-           (setq e-mail (match-string 1)))
-         (when (re-search-forward "^Title: \\([^\f]*\\)\nAuthors?: \\(.*\\)"
-                                  nil t)
-           (setq subject (concat (match-string 1) subject))
-           (setq from (concat (match-string 2) " <" e-mail ">"))))
-       ))
+       (narrow-to-region (car entry) (nth 1 entry))
+       (goto-char (point-min))
+       (when (looking-at "^Paper.*: \\([a-zA-Z-\\.]+/[0-9]+\\)")
+         (setq subject (concat " (" (match-string 1) ")"))
+         (when (re-search-forward "^From: \\(.*\\)" nil t)
+           (setq from (concat "<"
+                              (cadr (funcall gnus-extract-address-components
+                                             (match-string 1))) ">")))
+         (if (re-search-forward "^Date: +\\([^(]*\\)" nil t)
+             (setq date (match-string 1))
+           (when (re-search-forward "^replaced with revised version +\\([^(]*\\)" nil t)
+             (setq date (match-string 1))))
+         (when (re-search-forward "^Title: \\([^\f]*\\)\nAuthors?: \\(.*\\)"
+                                  nil t)
+           (setq subject (concat (match-string 1) subject))
+           (setq from (concat (match-string 2) " " from))))))
     (while (and from (string-match "(\[^)\]*)" from))
       (setq from (replace-match "" t t from)))
     (insert "From: "  (or from "unknown")
-           "\nSubject: " (or subject "(no subject)") "\n")))
+           "\nSubject: " (or subject "(no subject)") "\n")
+    (if date (insert "Date: " date))))
 
+(defun nndoc-nsmail-type-p ()
+  (when (looking-at "From - ")
+    t))
 
+(defun nndoc-outlook-article-begin ()
+  (prog1 (re-search-forward "From:\\|Received:" nil t)
+    (goto-char (match-beginning 0))))
+
+(defun nndoc-outlook-type-p ()
+  ;; FIXME: Is JMF the magic of outlook mailbox? -- ShengHuo.
+  (looking-at "JMF"))
+
+(defun nndoc-oe-dbx-type-p ()
+  (looking-at (string-as-multibyte "\317\255\022\376")))
+
+(defun nndoc-read-little-endian ()
+  (+ (prog1 (char-after) (forward-char 1))
+     (lsh (prog1 (char-after) (forward-char 1)) 8)
+     (lsh (prog1 (char-after) (forward-char 1)) 16)
+     (lsh (prog1 (char-after) (forward-char 1)) 24)))
+
+(defun nndoc-oe-dbx-decode-block ()
+  (list
+   (nndoc-read-little-endian)   ;; this address
+   (nndoc-read-little-endian)   ;; next address offset
+   (nndoc-read-little-endian)   ;; blocksize
+   (nndoc-read-little-endian))) ;; next address
+
+(defun nndoc-oe-dbx-dissection ()
+  (let ((i 0) blk p tp)
+    (goto-char 60117) ;; 0x0000EAD4+1
+    (setq p (point))
+    (unless (eobp)
+      (setq blk (nndoc-oe-dbx-decode-block)))
+    (while (and blk (> (car blk) 0) (or (zerop (nth 3 blk))
+                                       (> (nth 3 blk) p)))
+      (push (list (incf i) p nil nil nil 0) nndoc-dissection-alist)
+      (while (and (> (car blk) 0) (> (nth 3 blk) p))
+       (goto-char (1+ (nth 3 blk)))
+       (setq blk (nndoc-oe-dbx-decode-block)))
+      (if (or (<= (car blk) p)
+             (<= (nth 1 blk) 0)
+             (not (zerop (nth 3 blk))))
+         (setq blk nil)
+       (setq tp (+ (car blk) (nth 1 blk) 17))
+       (if (or (<= tp p) (>= tp (point-max)))
+           (setq blk nil)
+         (goto-char tp)
+         (setq p tp
+               blk (nndoc-oe-dbx-decode-block)))))))
+
+(defun nndoc-oe-dbx-generate-article (article &optional head)
+  (let ((entry (cdr (assq article nndoc-dissection-alist)))
+       (cur (current-buffer))
+       (begin (point))
+       blk p)
+    (with-current-buffer nndoc-current-buffer
+      (setq p (car entry))
+      (while (> p (point-min))
+       (goto-char p)
+       (setq blk (nndoc-oe-dbx-decode-block))
+       (setq p (point))
+       (with-current-buffer cur
+         (insert-buffer-substring nndoc-current-buffer p (+ p (nth 2 blk))))
+       (setq p (1+ (nth 3 blk)))))
+    (goto-char begin)
+    (while (re-search-forward "\r$" nil t)
+      (delete-backward-char 1))
+    (when head
+      (goto-char begin)
+      (when (search-forward "\n\n" nil t)
+       (setcar (cddddr entry) (count-lines (point) (point-max)))
+       (delete-region (1- (point)) (point-max))))
+    t))
+
+(defun nndoc-oe-dbx-generate-head (article)
+  (nndoc-oe-dbx-generate-article article 'head))
+
+(defun nndoc-mail-in-mail-type-p ()
+  (let (found)
+    (save-excursion
+      (catch 'done
+       (while (re-search-forward "\n\n[-A-Za-z0-9]+:" nil t)
+         (setq found 0)
+         (forward-line)
+         (while (looking-at "[ \t]\\|[-A-Za-z0-9]+:")
+           (if (looking-at "[-A-Za-z0-9]+:")
+               (setq found (1+ found)))
+           (forward-line))
+         (if (and (> found 0) (looking-at "\n"))
+             (throw 'done 9999)))
+       nil))))
+
+(defun nndoc-mail-in-mail-article-begin ()
+  (let (point found)
+    (if (catch 'done
+         (while (re-search-forward "\n\n\\([-A-Za-z0-9]+:\\)" nil t)
+           (setq found 0)
+           (setq point (match-beginning 1))
+           (forward-line)
+           (while (looking-at "[ \t]\\|[-A-Za-z0-9]+:")
+             (if (looking-at "[-A-Za-z0-9]+:")
+                 (setq found (1+ found)))
+             (forward-line))
+           (if (and (> found 0) (looking-at "\n"))
+               (throw 'done t)))
+         nil)
+       (goto-char point))))
+
+(deffoo nndoc-request-accept-article (group &optional server last)
+  nil)
 
 ;;;
 ;;; Functions for dissecting the documents
@@ -551,48 +772,57 @@ from the document.")
   "Go through the document and partition it into heads/bodies/articles."
   (let ((i 0)
        (first t)
-       head-begin head-end body-begin body-end)
+       art-begin head-begin head-end body-begin body-end)
     (setq nndoc-dissection-alist nil)
     (save-excursion
       (set-buffer nndoc-current-buffer)
       (goto-char (point-min))
-      ;; Find the beginning of the file.
-      (when nndoc-file-begin
-       (nndoc-search nndoc-file-begin))
-      ;; Go through the file.
-      (while (if (and first nndoc-first-article)
-                (nndoc-search nndoc-first-article)
-              (nndoc-article-begin))
-       (setq first nil)
-       (cond (nndoc-head-begin-function
-              (funcall nndoc-head-begin-function))
-             (nndoc-head-begin
-              (nndoc-search nndoc-head-begin)))
-       (if (or (>= (point) (point-max))
-               (and nndoc-file-end
-                    (looking-at nndoc-file-end)))
-           (goto-char (point-max))
-         (setq head-begin (point))
-         (nndoc-search (or nndoc-head-end "^$"))
-         (setq head-end (point))
-         (if nndoc-body-begin-function
-             (funcall nndoc-body-begin-function)
-           (nndoc-search (or nndoc-body-begin "^\n")))
-         (setq body-begin (point))
-         (or (and nndoc-body-end-function
-                  (funcall nndoc-body-end-function))
-             (and nndoc-body-end
-                  (nndoc-search nndoc-body-end))
-             (nndoc-article-begin)
-             (progn
-               (goto-char (point-max))
-               (when nndoc-file-end
-                 (and (re-search-backward nndoc-file-end nil t)
-                      (beginning-of-line)))))
-         (setq body-end (point))
-         (push (list (incf i) head-begin head-end body-begin body-end
-                     (count-lines body-begin body-end))
-               nndoc-dissection-alist))))))
+      ;; Remove blank lines.
+      (while (eq (following-char) ?\n)
+       (delete-char 1))
+      (if nndoc-dissection-function
+         (funcall nndoc-dissection-function)
+       ;; Find the beginning of the file.
+       (when nndoc-file-begin
+         (nndoc-search nndoc-file-begin))
+       ;; Go through the file.
+       (while (if (and first nndoc-first-article)
+                  (nndoc-search nndoc-first-article)
+                (if art-begin
+                    (goto-char art-begin)
+                  (nndoc-article-begin)))
+         (setq first nil
+               art-begin nil)
+         (cond (nndoc-head-begin-function
+                (funcall nndoc-head-begin-function))
+               (nndoc-head-begin
+                (nndoc-search nndoc-head-begin)))
+         (if (or (eobp)
+                 (and nndoc-file-end
+                      (looking-at nndoc-file-end)))
+             (goto-char (point-max))
+           (setq head-begin (point))
+           (nndoc-search (or nndoc-head-end "^$"))
+           (setq head-end (point))
+           (if nndoc-body-begin-function
+               (funcall nndoc-body-begin-function)
+             (nndoc-search (or nndoc-body-begin "^\n")))
+           (setq body-begin (point))
+           (or (and nndoc-body-end-function
+                    (funcall nndoc-body-end-function))
+               (and nndoc-body-end
+                    (nndoc-search nndoc-body-end))
+               (and (nndoc-article-begin)
+                    (setq art-begin (point)))
+               (progn
+                 (goto-char (point-max))
+                 (when nndoc-file-end
+                   (and (re-search-backward nndoc-file-end nil t)
+                        (beginning-of-line)))))
+           (setq body-end (point))
+           (push (list (incf i) head-begin head-end body-begin body-end
+                       (count-lines body-begin body-end))
+                 nndoc-dissection-alist)))))))
 
 (defun nndoc-article-begin ()
   (if nndoc-article-begin-function
@@ -605,6 +835,145 @@ from the document.")
   (while (re-search-forward "^- -"nil t)
     (replace-match "-" t t)))
 
+;; Against compiler warnings.
+(defvar nndoc-mime-split-ordinal)
+
+(defun nndoc-dissect-mime-parts ()
+  "Go through a MIME composite article and partition it into sub-articles.
+When a MIME entity contains sub-entities, dissection produces one article for
+the header of this entity, and one article per sub-entity."
+  (setq nndoc-dissection-alist nil
+       nndoc-mime-split-ordinal 0)
+  (save-excursion
+    (set-buffer nndoc-current-buffer)
+    (nndoc-dissect-mime-parts-sub (point-min) (point-max) nil nil nil)))
+
+(defun nndoc-dissect-mime-parts-sub (head-begin body-end article-insert
+                                               position parent)
+  "Dissect an entity, within a composite MIME message.
+The complete message or MIME entity extends from HEAD-BEGIN to BODY-END.
+ARTICLE-INSERT should be added at beginning for generating a full article.
+The string POSITION holds a dotted decimal representation of the article
+position in the hierarchical structure, it is nil for the outer entity.
+PARENT is the message-ID of the parent summary line, or nil for none."
+  (let ((case-fold-search t)
+       (message-id (nnmail-message-id))
+       head-end body-begin summary-insert message-rfc822 multipart-any
+       subject content-type type subtype boundary-regexp)
+    ;; Gracefully handle a missing body.
+    (goto-char head-begin)
+    (if (or (and (eq (char-after) ?\n) (or (forward-char 1) t))
+           (search-forward "\n\n" body-end t))
+       (setq head-end (1- (point))
+             body-begin (point))
+      (setq head-end body-end
+           body-begin body-end))
+    (narrow-to-region head-begin head-end)
+    ;; Save MIME attributes.
+    (goto-char head-begin)
+    (setq content-type (message-fetch-field "Content-Type"))
+    (when content-type
+      (when (string-match
+            "^ *\\([^ \t\n/;]+\\)/\\([^ \t\n/;]+\\)" content-type)
+       (setq type (downcase (match-string 1 content-type))
+             subtype (downcase (match-string 2 content-type))
+             message-rfc822 (and (string= type "message")
+                                 (string= subtype "rfc822"))
+             multipart-any (string= type "multipart")))
+      (when (string-match ";[ \t\n]*name=\\([^ \t\n;]+\\)" content-type)
+       (setq subject (match-string 1 content-type)))
+      (when (string-match "boundary=\"?\\([^\"\n]*[^\" \t\n]\\)" content-type)
+       (setq boundary-regexp (concat "^--"
+                                     (regexp-quote
+                                      (match-string 1 content-type))
+                                     "\\(--\\)?[ \t]*\n"))))
+    (unless subject
+      (when (or multipart-any (not article-insert))
+       (setq subject (message-fetch-field "Subject"))))
+    (unless type
+      (setq type "text"
+           subtype "plain"))
+    ;; Prepare the article and summary inserts.
+    (unless article-insert
+      (setq article-insert (buffer-string)
+           head-end head-begin))
+    ;; Fix MIME-Version
+    (unless (string-match "MIME-Version:" article-insert)
+      (setq article-insert
+           (concat article-insert "MIME-Version: 1.0\n")))
+    (setq summary-insert article-insert)
+    ;; - summary Subject.
+    (setq summary-insert
+         (let ((line (concat "Subject: <" position
+                             (and position multipart-any ".")
+                             (and multipart-any "*")
+                             (and (or position multipart-any) " ")
+                             (cond ((string= subtype "plain") type)
+                                   ((string= subtype "basic") type)
+                                   (t subtype))
+                             ">"
+                             (and subject " ")
+                             subject
+                             "\n")))
+           (if (string-match "Subject:.*\n\\([ \t].*\n\\)*" summary-insert)
+               (replace-match line t t summary-insert)
+             (concat summary-insert line))))
+    ;; - summary Message-ID.
+    (setq summary-insert
+         (let ((line (concat "Message-ID: " message-id "\n")))
+           (if (string-match "Message-ID:.*\n\\([ \t].*\n\\)*" summary-insert)
+               (replace-match line t t summary-insert)
+             (concat summary-insert line))))
+    ;; - summary References.
+    (when parent
+      (setq summary-insert
+           (let ((line (concat "References: " parent "\n")))
+             (if (string-match "References:.*\n\\([ \t].*\n\\)*"
+                               summary-insert)
+                 (replace-match line t t summary-insert)
+               (concat summary-insert line)))))
+    ;; Generate dissection information for this entity.
+    (push (list (incf nndoc-mime-split-ordinal)
+               head-begin head-end body-begin body-end
+               (count-lines body-begin body-end)
+               article-insert summary-insert)
+         nndoc-dissection-alist)
+    ;; Recurse for all sub-entities, if any.
+    (widen)
+    (cond
+     (message-rfc822
+      (save-excursion
+       (nndoc-dissect-mime-parts-sub body-begin body-end nil
+                                     position message-id)))
+     ((and multipart-any boundary-regexp)
+      (let ((part-counter 0)
+           part-begin part-end eof-flag)
+       (while (string-match "\
+^\\(Lines\\|Content-\\(Type\\|Transfer-Encoding\\|Disposition\\)\\):.*\n\\([ \t].*\n\\)*"
+                            article-insert)
+         (setq article-insert (replace-match "" t t article-insert)))
+       (let ((case-fold-search nil))
+         (goto-char body-begin)
+         (setq eof-flag (not (re-search-forward boundary-regexp body-end t)))
+         (while (not eof-flag)
+           (setq part-begin (point))
+           (cond ((re-search-forward boundary-regexp body-end t)
+                  (or (not (match-string 1))
+                      (string= (match-string 1) "")
+                      (setq eof-flag t))
+                  (forward-line -1)
+                  (setq part-end (point))
+                  (forward-line 1))
+                 (t (setq part-end body-end
+                          eof-flag t)))
+           (save-excursion
+             (nndoc-dissect-mime-parts-sub
+              part-begin part-end article-insert
+              (concat position
+                      (and position ".")
+                      (format "%d" (incf part-counter)))
+              message-id)))))))))
+
 ;;;###autoload
 (defun nndoc-add-type (definition &optional position)
   "Add document DEFINITION to the list of nndoc document definitions.
@@ -613,9 +982,7 @@ as the last checked definition, if t or `first', add as the
 first definition, and if any other symbol, add after that
 symbol in the alist."
   ;; First remove any old instances.
-  (setq nndoc-type-alist
-       (delq (assq (car definition) nndoc-type-alist)
-             nndoc-type-alist))
+  (gnus-pull (car definition) nndoc-type-alist)
   ;; Then enter the new definition in the proper place.
   (cond
    ((or (null position) (eq position 'last))
index be653df..0f978cb 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nndraft.el --- draft article access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nnheader)
 (require 'nnmail)
 (require 'gnus-start)
 (require 'nnmh)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nndraft
   nnmh)
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
-    (let* ((buf (get-buffer-create " *draft headers*"))
-          article)
-      (set-buffer buf)
-      (buffer-disable-undo (current-buffer))
-      (erase-buffer)
+    (let* (article)
       ;; We don't support fetching by Message-ID.
       (if (stringp (car articles))
          'headers
        (while articles
-         (set-buffer buf)
+         (narrow-to-region (point) (point))
          (when (nndraft-request-article
                 (setq article (pop articles)) group server (current-buffer))
            (goto-char (point-min))
                (forward-line -1)
              (goto-char (point-max)))
            (delete-region (point) (point-max))
-           (set-buffer nntp-server-buffer)
-           (goto-char (point-max))
+           (goto-char (point-min))
            (insert (format "221 %d Article retrieved.\n" article))
-           (insert-buffer-substring buf)
+           (widen)
+           (goto-char (point-max))
            (insert ".\n")))
 
        (nnheader-fold-continuation-lines)
           (newest (if (file-newer-than-file-p file auto) file auto))
           (nntp-server-buffer (or buffer nntp-server-buffer)))
       (when (and (file-exists-p newest)
-                (nnmail-find-file newest))
+                (let ((nnmail-file-coding-system
+                       (if (file-newer-than-file-p file auto)
+                           (if (member group '("drafts" "delayed"))
+                               message-draft-coding-system
+                             nnheader-text-coding-system)
+                         nnheader-auto-save-coding-system)))
+                  (nnmail-find-file newest)))
        (save-excursion
          (set-buffer nntp-server-buffer)
          (goto-char (point-min))
          ;; If there's a mail header separator in this file,
          ;; we remove it.
          (when (re-search-forward
-                (concat "^" mail-header-separator "$") nil t)
+                (concat "^" (regexp-quote mail-header-separator) "$") nil t)
            (replace-match "" t t)))
        t))))
 
   "Request a new buffer that is restored to the state of ARTICLE."
   (nndraft-possibly-change-group group)
   (when (nndraft-request-article article group server (current-buffer))
-    (message-remove-header "xrefs")
+    (message-remove-header "xref")
     (message-remove-header "lines")
-    (let ((gnus-verbose-backends nil))
-      (nndraft-request-expire-articles (list article) group server t))
+    ;; Articles in nndraft:queue are considered as sent messages.  The
+    ;; Date field should be the time when they are sent.
+    ;;(message-remove-header "date")
     t))
 
 (deffoo nndraft-request-update-info (group info &optional server)
    info
    (gnus-update-read-articles (gnus-group-prefixed-name group '(nndraft ""))
                              (nndraft-articles) t))
-  (let (marks)
-    (when (setq marks (nth 3 info))
+  (let ((marks (nth 3 info)))
+    (when marks
+      ;; Nix out all marks except the `unsend'-able article marks.
       (setcar (nthcdr 3 info)
              (if (assq 'unsend marks)
                  (list (assq 'unsend marks))
                nil))))
   t)
 
+(defun nndraft-generate-headers ()
+  (save-excursion
+    (message-generate-headers
+     (message-headers-to-generate
+      message-required-headers message-draft-headers nil))))
+
 (deffoo nndraft-request-associate-buffer (group)
   "Associate the current buffer with some article in the draft group."
   (nndraft-open-server "")
   (nndraft-possibly-change-group group)
   (let ((gnus-verbose-backends nil)
        (buf (current-buffer))
-        article file)
-    (nnheader-temp-write nil
-      (insert-buffer buf)
+       article file)
+    (with-temp-buffer
+      (insert-buffer-substring buf)
       (setq article (nndraft-request-accept-article
-                    group (nnoo-current-server 'nndraft) t 'noinsert))
-      (setq file (nndraft-article-filename article)))
-    (setq buffer-file-name (expand-file-name file))
-    (setq buffer-auto-save-file-name (make-auto-save-file-name))
+                    group (nnoo-current-server 'nndraft) t 'noinsert)
+           file (nndraft-article-filename article)))
+    (setq buffer-file-name (expand-file-name file)
+         buffer-auto-save-file-name (make-auto-save-file-name))
     (clear-visited-file-modtime)
+    (make-local-variable 'write-contents-hooks)
+    (push 'nndraft-generate-headers write-contents-hooks)
     article))
 
+(deffoo nndraft-request-group (group &optional server dont-check)
+  (nndraft-possibly-change-group group)
+  (unless dont-check
+    (let* ((pathname (nnmail-group-pathname group nndraft-directory))
+          (file-name-coding-system nnmail-pathname-coding-system)
+          dir file)
+      (nnheader-re-read-dir pathname)
+      (setq dir (mapcar (lambda (name) (string-to-int (substring name 1)))
+                       (ignore-errors (directory-files
+                                       pathname nil "^#[0-9]+#$" t))))
+      (dolist (n dir)
+       (unless (file-exists-p
+                (setq file (expand-file-name (int-to-string n) pathname)))
+         (rename-file (nndraft-auto-save-file-name file) file)))))
+  (nnoo-parent-function 'nndraft
+                       'nnmh-request-group
+                       (list group server dont-check)))
+
+(deffoo nndraft-request-move-article (article group server
+                                             accept-form &optional last)
+  (nndraft-possibly-change-group group)
+  (let ((buf (get-buffer-create " *nndraft move*"))
+       result)
+    (and
+     (nndraft-request-article article group server)
+     (save-excursion
+       (set-buffer buf)
+       (erase-buffer)
+       (insert-buffer-substring nntp-server-buffer)
+       (setq result (eval accept-form))
+       (kill-buffer (current-buffer))
+       result)
+     (null (nndraft-request-expire-articles (list article) group server 'force))
+     result)))
+
 (deffoo nndraft-request-expire-articles (articles group &optional server force)
   (nndraft-possibly-change-group group)
   (let* ((nnmh-allow-delete-final t)
        (let ((auto (nndraft-auto-save-file-name
                     (nndraft-article-filename article))))
          (when (file-exists-p auto)
-           (funcall nnmail-delete-file-function auto)))))
+           (funcall nnmail-delete-file-function auto)))
+       (dolist (backup
+                (let ((kept-new-versions 1)
+                      (kept-old-versions 0))
+                  (find-backup-file-name
+                   (nndraft-article-filename article))))
+         (when (file-exists-p backup)
+           (funcall nnmail-delete-file-function backup)))))
     res))
 
 (deffoo nndraft-request-accept-article (group &optional server last noinsert)
     (nnoo-parent-function 'nndraft 'nnmh-request-accept-article
                          (list group server last noinsert))))
 
+(deffoo nndraft-request-replace-article (article group buffer)
+  (nndraft-possibly-change-group group)
+  (let ((nnmail-file-coding-system
+        (if (member group '("drafts" "delayed"))
+            message-draft-coding-system
+          nnheader-text-coding-system)))
+    (nnoo-parent-function 'nndraft 'nnmh-request-replace-article
+                         (list article group buffer))))
+
 (deffoo nndraft-request-create-group (group &optional server args)
   (nndraft-possibly-change-group group)
   (if (file-exists-p nndraft-current-directory)
    nnmh-retrieve-headers
    nnmh-request-group
    nnmh-close-group
-   nnmh-request-list 
-   nnmh-request-newsgroups
-   nnmh-request-move-article
-   nnmh-request-replace-article))
+   nnmh-request-list
+   nnmh-request-newsgroups))
 
 (provide 'nndraft)
 
index 4584560..420d7f9 100644 (file)
@@ -1,8 +1,10 @@
-;;; nneething.el --- random file access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;;; nneething.el --- arbitrary file access for Gnus
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
   "Regexp saying what files to exclude from the group.
 If this variable is nil, no files will be excluded.")
 
+(defvoo nneething-include-files nil
+  "Regexp saying what files to include in the group.
+If this variable is non-nil, only files matching this regexp will be
+included.")
+
 \f
 
 ;;; Internal variables.
@@ -57,19 +64,113 @@ If this variable is nil, no files will be excluded.")
 
 (defvoo nneething-status-string "")
 
-(defvoo nneething-message-id-number 0)
 (defvoo nneething-work-buffer " *nneething work*")
 
 (defvoo nneething-group nil)
 (defvoo nneething-map nil)
 (defvoo nneething-read-only nil)
 (defvoo nneething-active nil)
-(defvoo nneething-directory nil)
+(defvoo nneething-address nil)
+
+(defvar nneething-mime-extensions
+  '((""        . "text/plain")
+    (".abs"   . "audio/x-mpeg")
+    (".aif"   . "audio/aiff")
+    (".aifc"  . "audio/aiff")
+    (".aiff"  . "audio/aiff")
+    (".ano"   . "application/x-annotator")
+    (".au"    . "audio/ulaw")
+    (".avi"   . "video/x-msvideo")
+    (".bcpio" . "application/x-bcpio")
+    (".bin"   . "application/octet-stream")
+    (".cdf"   . "application/x-netcdr")
+    (".cpio"  . "application/x-cpio")
+    (".csh"   . "application/x-csh")
+    (".css"   . "text/css")
+    (".dvi"   . "application/x-dvi")
+    (".diff"  . "text/x-patch")
+    (".el"    . "application/emacs-lisp")
+    (".eps"   . "application/postscript")
+    (".etx"   . "text/x-setext")
+    (".exe"   . "application/octet-stream")
+    (".fax"   . "image/x-fax")
+    (".gif"   . "image/gif")
+    (".hdf"   . "application/x-hdf")
+    (".hqx"   . "application/mac-binhex40")
+    (".htm"   . "text/html")
+    (".html"  . "text/html")
+    (".icon"  . "image/x-icon")
+    (".ief"   . "image/ief")
+    (".jpg"   . "image/jpeg")
+    (".macp"  . "image/x-macpaint")
+    (".man"   . "application/x-troff-man")
+    (".me"    . "application/x-troff-me")
+    (".mif"   . "application/mif")
+    (".mov"   . "video/quicktime")
+    (".movie" . "video/x-sgi-movie")
+    (".mp2"   . "audio/x-mpeg")
+    (".mp3"   . "audio/x-mpeg")
+    (".mp2a"  . "audio/x-mpeg2")
+    (".mpa"   . "audio/x-mpeg")
+    (".mpa2"  . "audio/x-mpeg2")
+    (".mpe"   . "video/mpeg")
+    (".mpeg"  . "video/mpeg")
+    (".mpega" . "audio/x-mpeg")
+    (".mpegv" . "video/mpeg")
+    (".mpg"   . "video/mpeg")
+    (".mpv"   . "video/mpeg")
+    (".ms"    . "application/x-troff-ms")
+    (".nc"    . "application/x-netcdf")
+    (".nc"    . "application/x-netcdf")
+    (".oda"   . "application/oda")
+    (".patch" . "text/x-patch")
+    (".pbm"   . "image/x-portable-bitmap")
+    (".pdf"   . "application/pdf")
+    (".pgm"   . "image/portable-graymap")
+    (".pict"  . "image/pict")
+    (".png"   . "image/png")
+    (".pnm"   . "image/x-portable-anymap")
+    (".ppm"   . "image/portable-pixmap")
+    (".ps"    . "application/postscript")
+    (".qt"    . "video/quicktime")
+    (".ras"   . "image/x-raster")
+    (".rgb"   . "image/x-rgb")
+    (".rtf"   . "application/rtf")
+    (".rtx"   . "text/richtext")
+    (".sh"    . "application/x-sh")
+    (".sit"   . "application/x-stuffit")
+    (".siv"   . "application/sieve")
+    (".snd"   . "audio/basic")
+    (".src"   . "application/x-wais-source")
+    (".tar"   . "archive/tar")
+    (".tcl"   . "application/x-tcl")
+    (".tex"   . "application/x-tex")
+    (".texi"  . "application/texinfo")
+    (".tga"   . "image/x-targa")
+    (".tif"   . "image/tiff")
+    (".tiff"  . "image/tiff")
+    (".tr"    . "application/x-troff")
+    (".troff" . "application/x-troff")
+    (".tsv"   . "text/tab-separated-values")
+    (".txt"   . "text/plain")
+    (".vbs"   . "video/mpeg")
+    (".vox"   . "audio/basic")
+    (".vrml"  . "x-world/x-vrml")
+    (".wav"   . "audio/x-wav")
+    (".xls"   . "application/vnd.ms-excel")
+    (".wrl"   . "x-world/x-vrml")
+    (".xbm"   . "image/xbm")
+    (".xpm"   . "image/xpm")
+    (".xwd"   . "image/windowdump")
+    (".zip"   . "application/zip")
+    (".ai"    . "application/postscript")
+    (".jpe"   . "image/jpeg")
+    (".jpeg"  . "image/jpeg"))
+  "An alist of file extensions and corresponding MIME content-types.
+This variable is used as the alternative of `mailcap-mime-extensions'.")
 
 \f
 
-(autoload 'gnus-encode-coding-string "gnus-ems")
-
 ;;; Interface functions.
 
 (nnoo-define-basics nneething)
@@ -103,11 +204,11 @@ If this variable is nil, no files will be excluded.")
 
          (and large
               (zerop (% count 20))
-              (message "nneething: Receiving headers... %d%%"
-                       (/ (* count 100) number))))
+              (nnheader-message 5 "nneething: Receiving headers... %d%%"
+                                (/ (* count 100) number))))
 
        (when large
-         (message "nneething: Receiving headers...done"))
+         (nnheader-message 5 "nneething: Receiving headers...done"))
 
        (nnheader-fold-continuation-lines)
        'headers))))
@@ -121,10 +222,25 @@ If this variable is nil, no files will be excluded.")
         (file-exists-p file)           ; The file exists.
         (not (file-directory-p file))  ; It's not a dir.
         (save-excursion
-          (nnmail-find-file file)      ; Insert the file in the nntp buf.
+          (let ((nnmail-file-coding-system 'binary))
+            (nnmail-find-file file))   ; Insert the file in the nntp buf.
           (unless (nnheader-article-p) ; Either it's a real article...
-            (goto-char (point-min))
-            (nneething-make-head file (current-buffer)) ; ... or we fake some headers.
+            (let ((type
+                   (unless (file-directory-p file)
+                     (or (cdr (assoc (concat "." (file-name-extension file))
+                                     (if (boundp 'mailcap-mime-extensions)
+                                         (symbol-value 'mailcap-mime-extensions)
+                                       nneething-mime-extensions)))
+                         "text/plain")))
+                  (charset
+                   (mm-detect-mime-charset-region (point-min) (point-max)))
+                  (encoding))
+              (unless (string-match "\\`text/" type)
+                (base64-encode-region (point-min) (point-max))
+                (setq encoding "base64"))
+              (goto-char (point-min))
+              (nneething-make-head file (current-buffer)
+                                   nil type charset encoding))
             (insert "\n"))
           t))))
 
@@ -158,8 +274,8 @@ If this variable is nil, no files will be excluded.")
   (nnheader-init-server-buffer)
   (if (nneething-server-opened server)
       t
-    (unless (assq 'nneething-directory defs)
-      (setq defs (append defs (list (list 'nneething-directory server)))))
+    (unless (assq 'nneething-address defs)
+      (setq defs (append defs (list (list 'nneething-address server)))))
     (nnoo-change-server 'nneething server defs)))
 
 \f
@@ -185,9 +301,9 @@ If this variable is nil, no files will be excluded.")
 
 (defun nneething-create-mapping ()
   ;; Read nneething-active and nneething-map.
-  (when (file-exists-p nneething-directory)
+  (when (file-exists-p nneething-address)
     (let ((map-file (nneething-map-file))
-         (files (directory-files nneething-directory))
+         (files (directory-files nneething-address))
          touched map-files)
       (when (file-exists-p map-file)
        (ignore-errors
@@ -213,17 +329,27 @@ If this variable is nil, no files will be excluded.")
                  (setq files (cdr files)))
              (setq prev f))
            (setq f (cdr f)))))
+      ;; Remove files not matching the inclusion regexp.
+      (when nneething-include-files
+       (let ((f files)
+             prev)
+         (while f
+           (if (not (string-match nneething-include-files (car f)))
+               (if prev (setcdr prev (cdr f))
+                 (setq files (cdr files)))
+             (setq prev f))
+           (setq f (cdr f)))))
       ;; Remove deleted files from the map.
       (let ((map nneething-map)
            prev)
        (while map
-         (if (and (member (cadar map) files)
+         (if (and (member (cadr (car map)) files)
                   ;; We also remove files that have changed mod times.
                   (equal (nth 5 (file-attributes
-                                 (nneething-file-name (cadar map))))
-                         (caddar map)))
+                                 (nneething-file-name (cadr (car map)))))
+                         (cadr (cdar map))))
              (progn
-               (push (cadar map) map-files)
+               (push (cadr (car map)) map-files)
                (setq prev map))
            (setq touched t)
            (if prev
@@ -243,7 +369,7 @@ If this variable is nil, no files will be excluded.")
        (setq files (cdr files)))
       (when (and touched
                 (not nneething-read-only))
-       (nnheader-temp-write map-file
+       (with-temp-file map-file
          (insert "(setq nneething-map '")
          (gnus-prin1 nneething-map)
          (insert ")\n(setq nneething-active '")
@@ -256,13 +382,42 @@ If this variable is nil, no files will be excluded.")
     (insert-buffer-substring nneething-work-buffer)
     (goto-char (point-max))))
 
-(defun nneething-make-head (file &optional buffer)
+(defun nneething-encode-file-name (file &optional coding-system)
+  "Encode the name of the FILE in CODING-SYSTEM."
+  (let ((pos 0) buf)
+    (setq file (mm-encode-coding-string
+               file (or coding-system nnmail-pathname-coding-system)))
+    (while (string-match "[^-0-9a-zA-Z_:/.]" file pos)
+      (setq buf (cons (format "%%%02x" (aref file (match-beginning 0)))
+                     (cons (substring file pos (match-beginning 0)) buf))
+           pos (match-end 0)))
+    (apply (function concat)
+          (nreverse (cons (substring file pos) buf)))))
+
+(defun nneething-decode-file-name (file &optional coding-system)
+  "Decode the name of the FILE is encoded in CODING-SYSTEM."
+  (let ((pos 0) buf)
+    (while (string-match "%\\([0-9a-fA-F][0-9a-fA-F]\\)" file pos)
+      (setq buf (cons (string (string-to-number (match-string 1 file) 16))
+                     (cons (substring file pos (match-beginning 0)) buf))
+           pos (match-end 0)))
+    (decode-coding-string
+     (apply (function concat)
+           (nreverse (cons (substring file pos) buf)))
+     (or coding-system nnmail-pathname-coding-system))))
+
+(defun nneething-get-file-name (id)
+  "Extract the file name from the message ID string."
+  (when (string-match "\\`<nneething-\\([^@]+\\)@.*>\\'" id)
+    (nneething-decode-file-name (match-string 1 id))))
+
+(defun nneething-make-head (file &optional buffer extra-msg
+                                mime-type mime-charset mime-encoding)
   "Create a head by looking at the file attributes of FILE."
   (let ((atts (file-attributes file)))
     (insert
-     "Subject: " (file-name-nondirectory file) "\n"
-     "Message-ID: <nneething-"
-     (int-to-string (incf nneething-message-id-number))
+     "Subject: " (file-name-nondirectory file) (or extra-msg "") "\n"
+     "Message-ID: <nneething-" (nneething-encode-file-name file)
      "@" (system-name) ">\n"
      (if (equal '(0 0) (nth 5 atts)) ""
        (concat "Date: " (current-time-string (nth 5 atts)) "\n"))
@@ -282,7 +437,19 @@ If this variable is nil, no files will be excluded.")
                              (count-lines (point-min) (point-max)))
                   "\n"))
        "")
-     )))
+     (if mime-type
+        (concat "Content-Type: " mime-type
+                (if mime-charset
+                    (concat "; charset="
+                            (if (stringp mime-charset)
+                                mime-charset
+                              (symbol-name mime-charset)))
+                  "")
+                (if mime-encoding
+                    (concat "\nContent-Transfer-Encoding: " mime-encoding)
+                  "")
+                "\nMIME-Version: 1.0\n")
+       ""))))
 
 (defun nneething-from-line (uid &optional file)
   "Return a From header based of UID."
@@ -302,7 +469,8 @@ If this variable is nil, no files will be excluded.")
                       (substring file
                                  (match-beginning 1)
                                  (match-end 1))
-                    (when (string-match "/\\(users\\|home\\)/\\([^/]+\\)/" file)
+                    (when (string-match
+                           "/\\(users\\|home\\)/\\([^/]+\\)/" file)
                       (setq login (substring file
                                              (match-beginning 2)
                                              (match-end 2))
@@ -316,7 +484,7 @@ If this variable is nil, no files will be excluded.")
   (save-excursion
     (set-buffer (get-buffer-create nneething-work-buffer))
     (setq case-fold-search nil)
-    (buffer-disable-undo (current-buffer))
+    (buffer-disable-undo)
     (erase-buffer)
     (cond
      ((not (file-exists-p file))
@@ -328,26 +496,33 @@ If this variable is nil, no files will be excluded.")
       (nneething-make-head file) t)
      (t
       ;; We examine the file.
-      (nnheader-insert-head file)
-      (if (nnheader-article-p)
-         (delete-region
-          (progn
-            (goto-char (point-min))
-            (or (and (search-forward "\n\n" nil t)
-                     (1- (point)))
-                (point-max)))
-          (point-max))
-       (goto-char (point-min))
-       (nneething-make-head file (current-buffer))
-       (delete-region (point) (point-max)))
+      (condition-case ()
+         (progn
+           (nnheader-insert-head file)
+           (if (nnheader-article-p)
+               (delete-region
+                (progn
+                  (goto-char (point-min))
+                  (or (and (search-forward "\n\n" nil t)
+                           (1- (point)))
+                      (point-max)))
+                (point-max))
+             (goto-char (point-min))
+             (nneething-make-head file (current-buffer))
+             (delete-region (point) (point-max))))
+       (file-error
+        (nneething-make-head file (current-buffer) " (unreadable)")))
       t))))
 
 (defun nneething-file-name (article)
   "Return the file name of ARTICLE."
-  (concat (file-name-as-directory nneething-directory)
-         (if (numberp article)
-             (cadr (assq article nneething-map))
-           article)))
+  (let ((dir (file-name-as-directory nneething-address))
+       fname)
+    (if (numberp article)
+       (if (setq fname (cadr (assq article nneething-map)))
+           (expand-file-name fname dir)
+         (mm-make-temp-file (expand-file-name "nneething" dir)))
+      (expand-file-name article dir))))
 
 (provide 'nneething)
 
index 56ca0d6..1102078 100644 (file)
@@ -1,9 +1,12 @@
 ;;; nnfolder.el --- mail folder access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
-
-;; Author: Scott Byer <byer@mv.us.adobe.com>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org> (adding MARKS)
+;;      ShengHuo Zhu <zsh@cs.rochester.edu> (adding NOV)
+;;      Scott Byer <byer@mv.us.adobe.com>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'nnheader)
 (require 'message)
 (require 'nnmail)
 (require 'nnoo)
-(require 'cl)
+(require 'gnus)
 (require 'gnus-util)
+(require 'gnus-range)
+
+(eval-and-compile
+  (autoload 'gnus-article-unpropagatable-p "gnus-sum")
+  (autoload 'gnus-intersection "gnus-range"))
 
 (nnoo-declare nnfolder)
 
 (defvoo nnfolder-directory (expand-file-name message-directory)
   "The name of the nnfolder directory.")
 
+(defvoo nnfolder-nov-directory nil
+  "The name of the nnfolder NOV directory.
+If nil, `nnfolder-directory' is used.")
+
+(defvoo nnfolder-marks-directory nil
+  "The name of the nnfolder MARKS directory.
+If nil, `nnfolder-directory' is used.")
+
 (defvoo nnfolder-active-file
-  (nnheader-concat nnfolder-directory "active")
+    (nnheader-concat nnfolder-directory "active")
   "The name of the active file.")
 
 ;; I renamed this variable to something more in keeping with the general GNU
 ;; style. -SLB
 
 (defvoo nnfolder-ignore-active-file nil
-  "If non-nil, causes nnfolder to do some extra work in order to determine
-the true active ranges of an mbox file.  Note that the active file is still
-saved, but it's values are not used.  This costs some extra time when
-scanning an mbox when opening it.")
+  "If non-nil, the active file is ignored.
+This causes nnfolder to do some extra work in order to determine the
+true active ranges of an mbox file.  Note that the active file is
+still saved, but its values are not used.  This costs some extra time
+when scanning an mbox when opening it.")
 
 (defvoo nnfolder-distrust-mbox nil
-  "If non-nil, causes nnfolder to not trust the user with respect to
-inserting unaccounted for mail in the middle of an mbox file.  This can greatly
-slow down scans, which now must scan the entire file for unmarked messages.
-When nil, scans occur forward from the last marked message, a huge
-time saver for large mailboxes.")
+  "If non-nil, the folder will be distrusted.
+This means that nnfolder will not trust the user with respect to
+inserting unaccounted for mail in the middle of an mbox file.  This
+can greatly slow down scans, which now must scan the entire file for
+unmarked messages.  When nil, scans occur forward from the last marked
+message, a huge time saver for large mailboxes.")
 
 (defvoo nnfolder-newsgroups-file
-  (concat (file-name-as-directory nnfolder-directory) "newsgroups")
+    (concat (file-name-as-directory nnfolder-directory) "newsgroups")
   "Mail newsgroups description file.")
 
 (defvoo nnfolder-get-new-mail t
@@ -72,12 +93,13 @@ time saver for large mailboxes.")
 (defvoo nnfolder-save-buffer-hook nil
   "Hook run before saving the nnfolder mbox buffer.")
 
+
 (defvoo nnfolder-inhibit-expiry nil
   "If non-nil, inhibit expiry.")
 
 \f
 
-(defconst nnfolder-version "nnfolder 1.0"
+(defconst nnfolder-version "nnfolder 2.0"
   "nnfolder version.")
 
 (defconst nnfolder-article-marker "X-Gnus-Article-Number: "
@@ -90,6 +112,43 @@ time saver for large mailboxes.")
 (defvoo nnfolder-buffer-alist nil)
 (defvoo nnfolder-scantime-alist nil)
 (defvoo nnfolder-active-timestamp nil)
+(defvoo nnfolder-active-file-coding-system nnheader-text-coding-system)
+(defvoo nnfolder-active-file-coding-system-for-write
+    nnmail-active-file-coding-system)
+(defvoo nnfolder-file-coding-system nnheader-text-coding-system)
+(defvoo nnfolder-file-coding-system-for-write nnheader-file-coding-system
+  "Coding system for save nnfolder file.
+if nil, `nnfolder-file-coding-system' is used.") ; FIXME: fill-in the doc-string of this variable
+
+(defvoo nnfolder-nov-is-evil nil
+  "If non-nil, Gnus will never generate and use nov databases for mail groups.
+Using nov databases will speed up header fetching considerably.
+This variable shouldn't be flipped much.  If you have, for some reason,
+set this to t, and want to set it to nil again, you should always run
+the `nnfolder-generate-active-file' command.  The function will go
+through all nnfolder directories and generate nov databases for them
+all.  This may very well take some time.")
+
+(defvoo nnfolder-nov-file-suffix ".nov")
+
+(defvoo nnfolder-nov-buffer-alist nil)
+
+(defvar nnfolder-nov-buffer-file-name nil)
+
+(defvoo nnfolder-marks-is-evil nil
+  "If non-nil, Gnus will never generate and use marks file for mail groups.
+Using marks files makes it possible to backup and restore mail groups
+separately from `.newsrc.eld'.  If you have, for some reason, set
+this to t, and want to set it to nil again, you should always remove
+the corresponding marks file (usually base nnfolder file name
+concatenated with `.mrk', but see `nnfolder-marks-file-suffix') for
+the group.  Then the marks file will be regenerated properly by Gnus.")
+
+(defvoo nnfolder-marks nil)
+
+(defvoo nnfolder-marks-file-suffix ".mrk")
+
+(defvar nnfolder-marks-modtime (gnus-make-hashtable))
 
 \f
 
@@ -101,42 +160,82 @@ time saver for large mailboxes.")
   (save-excursion
     (set-buffer nntp-server-buffer)
     (erase-buffer)
-    (let (article art-string start stop)
+    (let (article start stop num)
       (nnfolder-possibly-change-group group server)
       (when nnfolder-current-buffer
        (set-buffer nnfolder-current-buffer)
        (goto-char (point-min))
        (if (stringp (car articles))
            'headers
-         (while articles
-           (setq article (car articles))
-           (setq art-string (nnfolder-article-string article))
-           (set-buffer nnfolder-current-buffer)
-           (when (or (search-forward art-string nil t)
-                     ;; Don't search the whole file twice!  Also, articles
-                     ;; probably have some locality by number, so searching
-                     ;; backwards will be faster.  Especially if we're at the
-                     ;; beginning of the buffer :-). -SLB
-                     (search-backward art-string nil t))
-             (nnmail-search-unix-mail-delim-backward)
-             (setq start (point))
-             (search-forward "\n\n" nil t)
-             (setq stop (1- (point)))
-             (set-buffer nntp-server-buffer)
-             (insert (format "221 %d Article retrieved.\n" article))
-             (insert-buffer-substring nnfolder-current-buffer start stop)
-             (goto-char (point-max))
-             (insert ".\n"))
-           (setq articles (cdr articles)))
-
-         (set-buffer nntp-server-buffer)
-         (nnheader-fold-continuation-lines)
-         'headers)))))
+         (if (nnfolder-retrieve-headers-with-nov articles fetch-old)
+             'nov
+           (setq articles (gnus-sorted-intersection
+                           ;; Is ARTICLES sorted?
+                           (sort articles '<)
+                           (nnfolder-existing-articles)))
+           (while (setq article (pop articles))
+             (set-buffer nnfolder-current-buffer)
+             (cond ((nnfolder-goto-article article)
+                    (setq start (point))
+                    (setq stop (if (search-forward "\n\n" nil t)
+                                   (1- (point))
+                                 (point-max)))
+                    (set-buffer nntp-server-buffer)
+                    (insert (format "221 %d Article retrieved.\n" article))
+                    (insert-buffer-substring nnfolder-current-buffer
+                                             start stop)
+                    (goto-char (point-max))
+                    (insert ".\n"))
+
+                   ;; If we couldn't find this article, skip over ranges
+                   ;; of missing articles so we don't search the whole file
+                   ;; for each of them.
+                   ((numberp article)
+                    (setq start (point))
+                    (and
+                     ;; Check that we are either at BOF or after an
+                     ;; article with a lower number.  We do this so we
+                     ;; won't be confused by out-of-order article numbers,
+                     ;; as caused by active file bogosity.
+                     (cond
+                      ((bobp))
+                      ((search-backward (concat "\n" nnfolder-article-marker)
+                                        nil t)
+                       (goto-char (match-end 0))
+                       (setq num (string-to-int
+                                  (buffer-substring
+                                   (point) (gnus-point-at-eol))))
+                       (goto-char start)
+                       (< num article)))
+                     ;; Check that we are before an article with a
+                     ;; higher number.
+                     (search-forward (concat "\n" nnfolder-article-marker)
+                                     nil t)
+                     (progn
+                       (setq num (string-to-int
+                                  (buffer-substring
+                                   (point) (gnus-point-at-eol))))
+                       (> num article))
+                     ;; Discard any article numbers before the one we're
+                     ;; now looking at.
+                     (while (and articles
+                                 (< (car articles) num))
+                       (setq articles (cdr articles))))
+                    (goto-char start))))
+           (set-buffer nntp-server-buffer)
+           (nnheader-fold-continuation-lines)
+           'headers))))))
 
 (deffoo nnfolder-open-server (server &optional defs)
   (nnoo-change-server 'nnfolder server defs)
   (nnmail-activate 'nnfolder t)
   (gnus-make-directory nnfolder-directory)
+  (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+    (and nnfolder-nov-directory
+        (gnus-make-directory nnfolder-nov-directory)))
+  (unless nnfolder-marks-is-evil
+    (and nnfolder-marks-directory
+        (gnus-make-directory nnfolder-marks-directory)))
   (cond
    ((not (file-exists-p nnfolder-directory))
     (nnfolder-close-server)
@@ -165,9 +264,8 @@ time saver for large mailboxes.")
   (save-excursion
     (set-buffer nnfolder-current-buffer)
     (goto-char (point-min))
-    (when (search-forward (nnfolder-article-string article) nil t)
+    (when (nnfolder-goto-article article)
       (let (start stop)
-       (nnmail-search-unix-mail-delim-backward)
        (setq start (point))
        (forward-line 1)
        (unless (and (nnmail-search-unix-mail-delim)
@@ -186,11 +284,12 @@ time saver for large mailboxes.")
          (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) (gnus-point-at-eol)))
+                   -1))))))))
 
 (deffoo nnfolder-request-group (group &optional server dont-check)
   (nnfolder-possibly-change-group group server t)
@@ -276,15 +375,14 @@ time saver for large mailboxes.")
   (when group
     (unless (assoc group nnfolder-group-alist)
       (push (list group (cons 1 0)) nnfolder-group-alist)
-      (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+      (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
       (nnfolder-read-folder group)))
   t)
 
 (deffoo nnfolder-request-list (&optional server)
   (nnfolder-possibly-change-group nil server)
   (save-excursion
-    (let ((nnmail-file-coding-system nnmail-active-file-coding-system)
-         (pathname-coding-system 'binary))
+    (let ((nnmail-file-coding-system nnfolder-active-file-coding-system))
       (nnmail-find-file nnfolder-active-file)
       (setq nnfolder-group-alist (nnmail-get-active)))
     t))
@@ -296,38 +394,79 @@ time saver for large mailboxes.")
 (deffoo nnfolder-request-list-newsgroups (&optional server)
   (nnfolder-possibly-change-group nil server)
   (save-excursion
-    (nnmail-find-file nnfolder-newsgroups-file)))
+    (let ((nnmail-file-coding-system nnfolder-file-coding-system))
+      (nnmail-find-file nnfolder-newsgroups-file))))
+
+;; Return a list consisting of all article numbers existing in the
+;; current folder.
+
+(defun nnfolder-existing-articles ()
+  (save-excursion
+    (when nnfolder-current-buffer
+      (set-buffer nnfolder-current-buffer)
+      (goto-char (point-min))
+      (let ((marker (concat "\n" nnfolder-article-marker))
+           (number "[0-9]+")
+           numbers)
+       (while (and (search-forward marker nil t)
+                   (re-search-forward number nil t))
+         (let ((newnum (string-to-number (match-string 0))))
+           (if (nnmail-within-headers-p)
+               (push newnum numbers))))
+       ;; The article numbers are increasing, so this result is sorted.
+       (nreverse numbers)))))
 
 (deffoo nnfolder-request-expire-articles
-  (articles newsgroup &optional server force)
+    (articles newsgroup &optional server force)
   (nnfolder-possibly-change-group newsgroup server)
   (let* ((is-old t)
-        rest)
+        ;; The articles we have deleted so far.
+        (deleted-articles nil)
+        ;; The articles that really exist and will
+        ;; be expired if they are old enough.
+        (maybe-expirable
+         (gnus-sorted-intersection articles (nnfolder-existing-articles))))
     (nnmail-activate 'nnfolder)
 
     (save-excursion
       (set-buffer nnfolder-current-buffer)
-      (while (and articles is-old)
+      ;; Since messages are sorted in arrival order and expired in the
+      ;; same order, we can stop as soon as we find a message that is
+      ;; too old.
+      (while (and maybe-expirable is-old)
        (goto-char (point-min))
-       (when (search-forward (nnfolder-article-string (car articles)) nil t)
-         (if (setq is-old
-                   (nnmail-expired-article-p
-                    newsgroup
-                    (buffer-substring
-                     (point) (progn (end-of-line) (point)))
-                    force nnfolder-inhibit-expiry))
-             (progn
-               (nnheader-message 5 "Deleting article %d..."
-                                 (car articles) newsgroup)
-               (nnfolder-delete-mail))
-           (push (car articles) rest)))
-       (setq articles (cdr articles)))
+       (when (and (nnfolder-goto-article (car maybe-expirable))
+                  (search-forward (concat "\n" nnfolder-article-marker)
+                                  nil t))
+         (forward-sexp)
+         (when (setq is-old
+                     (nnmail-expired-article-p
+                      newsgroup
+                      (buffer-substring
+                       (point) (progn (end-of-line) (point)))
+                      force nnfolder-inhibit-expiry))
+           (unless (eq nnmail-expiry-target 'delete)
+             (with-temp-buffer
+               (nnfolder-request-article (car maybe-expirable)
+                                         newsgroup server (current-buffer))
+               (let ((nnfolder-current-directory nil))
+                 (nnmail-expiry-target-group
+                  nnmail-expiry-target newsgroup)))
+             (nnfolder-possibly-change-group newsgroup server))
+           (nnheader-message 5 "Deleting article %d in %s..."
+                             (car maybe-expirable) newsgroup)
+           (nnfolder-delete-mail)
+           (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+             (nnfolder-nov-delete-article newsgroup (car maybe-expirable)))
+           ;; Must remember which articles were actually deleted
+           (push (car maybe-expirable) deleted-articles)))
+       (setq maybe-expirable (cdr maybe-expirable)))
       (unless nnfolder-inhibit-expiry
        (nnheader-message 5 "Deleting articles...done"))
       (nnfolder-save-buffer)
       (nnfolder-adjust-min-active newsgroup)
-      (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
-      (nconc rest articles))))
+      (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
+      (gnus-sorted-difference articles (nreverse deleted-articles)))))
 
 (deffoo nnfolder-request-move-article (article group server
                                               accept-form &optional last)
@@ -338,15 +477,14 @@ time saver for large mailboxes.")
        (nnfolder-request-article article group server)
        (save-excursion
         (set-buffer buf)
-        (buffer-disable-undo (current-buffer))
         (erase-buffer)
         (insert-buffer-substring nntp-server-buffer)
         (goto-char (point-min))
         (while (re-search-forward
                 (concat "^" nnfolder-article-marker)
-                (save-excursion (search-forward "\n\n" nil t) (point)) t)
-          (delete-region (progn (beginning-of-line) (point))
-                         (progn (forward-line 1) (point))))
+                (save-excursion (and (search-forward "\n\n" nil t) (point)))
+                t)
+          (gnus-delete-line))
         (setq result (eval accept-form))
         (kill-buffer buf)
         result)
@@ -354,12 +492,14 @@ time saver for large mailboxes.")
         (nnfolder-possibly-change-group group server)
         (set-buffer nnfolder-current-buffer)
         (goto-char (point-min))
-        (when (search-forward (nnfolder-article-string article) nil t)
+        (when (nnfolder-goto-article article)
           (nnfolder-delete-mail))
+        (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+          (nnfolder-nov-delete-article group article))
         (when last
           (nnfolder-save-buffer)
           (nnfolder-adjust-min-active group)
-          (nnmail-save-active nnfolder-group-alist nnfolder-active-file))))
+          (nnfolder-save-active nnfolder-group-alist nnfolder-active-file))))
       result)))
 
 (deffoo nnfolder-request-accept-article (group &optional server last)
@@ -370,34 +510,42 @@ time saver for large mailboxes.")
          result art-group)
       (goto-char (point-min))
       (when (looking-at "X-From-Line: ")
-       (replace-match "From "))
-      (and
-       (nnfolder-request-list)
-       (save-excursion
-        (set-buffer buf)
-        (goto-char (point-min))
-        (search-forward "\n\n" nil t)
-        (forward-line -1)
-        (while (re-search-backward (concat "^" nnfolder-article-marker) nil t)
-          (delete-region (point) (progn (forward-line 1) (point))))
-        (when nnmail-cache-accepted-message-ids
-          (nnmail-cache-insert (nnmail-fetch-field "message-id")))
-        (setq result (if (stringp group)
-                         (list (cons group (nnfolder-active-number group)))
-                       (setq art-group
-                             (nnmail-article-group 'nnfolder-active-number))))
-        (if (and (null result)
-                 (yes-or-no-p "Moved to `junk' group; delete article? "))
-            (setq result 'junk)
-          (setq result
-                (car (nnfolder-save-mail result)))))
-       (when last
-        (save-excursion
-          (nnfolder-possibly-change-folder (or (caar art-group) group))
-          (nnfolder-save-buffer)
-          (when nnmail-cache-accepted-message-ids
-            (nnmail-cache-close)))))
-      (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+       (replace-match "From ")
+       (while (progn (forward-line) (looking-at "[ \t]"))
+         (delete-char -1)))
+      (with-temp-buffer
+       (let ((nnmail-file-coding-system nnfolder-active-file-coding-system)
+             (nntp-server-buffer (current-buffer)))
+         (nnmail-find-file nnfolder-active-file)
+         (setq nnfolder-group-alist (nnmail-parse-active))))
+      (save-excursion
+       (goto-char (point-min))
+       (if (search-forward "\n\n" nil t)
+           (forward-line -1)
+         (goto-char (point-max)))
+       (while (re-search-backward (concat "^" nnfolder-article-marker) nil t)
+         (delete-region (point) (progn (forward-line 1) (point))))
+       (when nnmail-cache-accepted-message-ids
+         (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                              group
+                              (nnmail-fetch-field "subject")
+                              (nnmail-fetch-field "from")))
+       (setq result (if (stringp group)
+                        (list (cons group (nnfolder-active-number group)))
+                      (setq art-group
+                            (nnmail-article-group 'nnfolder-active-number))))
+       (if (and (null result)
+                (yes-or-no-p "Moved to `junk' group; delete article? "))
+           (setq result 'junk)
+         (setq result
+               (car (nnfolder-save-mail result)))))
+      (when last
+       (save-excursion
+         (nnfolder-possibly-change-folder (or (caar art-group) group))
+         (nnfolder-save-buffer)
+         (when nnmail-cache-accepted-message-ids
+           (nnmail-cache-close))))
+      (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
       (unless result
        (nnheader-report 'nnfolder "Couldn't store article"))
       result)))
@@ -406,13 +554,30 @@ time saver for large mailboxes.")
   (nnfolder-possibly-change-group group)
   (save-excursion
     (set-buffer buffer)
+    (goto-char (point-min))
+    (if (not (looking-at "X-From-Line: "))
+       (insert "From nobody " (current-time-string) "\n")
+      (replace-match "From ")
+      (forward-line 1)
+      (while (looking-at "[ \t]")
+       (delete-char -1)
+       (forward-line 1)))
     (nnfolder-normalize-buffer)
     (set-buffer nnfolder-current-buffer)
     (goto-char (point-min))
-    (if (not (search-forward (nnfolder-article-string article) nil t))
+    (if (not (nnfolder-goto-article article))
        nil
-      (nnfolder-delete-mail t t)
+      (nnfolder-delete-mail)
       (insert-buffer-substring buffer)
+      (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+       (save-excursion
+         (set-buffer buffer)
+         (let ((headers (nnfolder-parse-head article
+                                             (point-min) (point-max))))
+           (with-current-buffer (nnfolder-open-nov group)
+             (if (nnheader-find-nov-line article)
+                 (delete-region (point) (progn (forward-line 1) (point))))
+             (nnheader-insert-nov headers)))))
       (nnfolder-save-buffer)
       t)))
 
@@ -422,15 +587,19 @@ time saver for large mailboxes.")
   (if (not force)
       ()                               ; Don't delete the articles.
     ;; Delete the file that holds the group.
-    (ignore-errors
-      (delete-file (nnfolder-group-pathname group))))
+    (let ((data (nnfolder-group-pathname group))
+         (nov (nnfolder-group-nov-pathname group))
+         (mrk (nnfolder-group-marks-pathname group)))
+      (ignore-errors (delete-file data))
+      (ignore-errors (delete-file nov))
+      (ignore-errors (delete-file mrk))))
   ;; Remove the group from all structures.
   (setq nnfolder-group-alist
        (delq (assoc group nnfolder-group-alist) nnfolder-group-alist)
        nnfolder-current-group nil
        nnfolder-current-buffer nil)
   ;; Save the active file.
-  (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+  (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
   t)
 
 (deffoo nnfolder-request-rename-group (group new-name &optional server)
@@ -439,9 +608,17 @@ time saver for large mailboxes.")
     (set-buffer nnfolder-current-buffer)
     (and (file-writable-p buffer-file-name)
         (ignore-errors
-          (rename-file
-           buffer-file-name
-           (nnfolder-group-pathname new-name))
+          (let ((new-file (nnfolder-group-pathname new-name)))
+            (gnus-make-directory (file-name-directory new-file))
+            (rename-file buffer-file-name new-file)
+            (when (file-exists-p (nnfolder-group-nov-pathname group))
+              (setq new-file (nnfolder-group-nov-pathname new-name))
+              (gnus-make-directory (file-name-directory new-file))
+              (rename-file (nnfolder-group-nov-pathname group) new-file))
+            (when (file-exists-p (nnfolder-group-marks-pathname group))
+              (setq new-file (nnfolder-group-marks-pathname new-name))
+              (gnus-make-directory (file-name-directory new-file))
+              (rename-file (nnfolder-group-marks-pathname group) new-file)))
           t)
         ;; That went ok, so we change the internal structures.
         (let ((entry (assoc group nnfolder-group-alist)))
@@ -449,12 +626,12 @@ time saver for large mailboxes.")
           (setq nnfolder-current-buffer nil
                 nnfolder-current-group nil)
           ;; Save the new group alist.
-          (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+          (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
           ;; We kill the buffer instead of renaming it and stuff.
           (kill-buffer (current-buffer))
           t))))
 
-(defun nnfolder-request-regenerate (server)
+(deffoo nnfolder-request-regenerate (server)
   (nnfolder-possibly-change-group nil server)
   (nnfolder-generate-active-file)
   t)
@@ -473,10 +650,9 @@ time saver for large mailboxes.")
       (goto-char (point-min))
       (while (and (search-forward marker nil t)
                  (re-search-forward number nil t))
-       (setq activemin (min activemin
-                            (string-to-number (buffer-substring
-                                               (match-beginning 0)
-                                               (match-end 0))))))
+       (let ((newnum (string-to-number (match-string 0))))
+         (if (nnmail-within-headers-p)
+             (setq activemin (min activemin newnum)))))
       (setcar active activemin))))
 
 (defun nnfolder-article-string (article)
@@ -484,11 +660,39 @@ time saver for large mailboxes.")
       (concat "\n" nnfolder-article-marker (int-to-string article) " ")
     (concat "\nMessage-ID: " article)))
 
-(defun nnfolder-delete-mail (&optional force leave-delim)
-  "Delete the message that point is in."
-  (save-excursion
-    (delete-region
+(defun nnfolder-goto-article (article)
+  "Place point at the start of the headers of ARTICLE.
+ARTICLE can be an article number or a Message-ID.
+Returns t if successful, nil otherwise."
+  (let ((art-string (nnfolder-article-string article))
+       start found)
+    ;; It is likely that we are at or before the delimiter line.
+    ;; We therefore go to the end of the previous line, and start
+    ;; searching from there.
+    (beginning-of-line)
+    (unless (bobp)
+      (forward-char -1))
+    (setq start (point))
+    ;; First search forward.
+    (while (and (setq found (search-forward art-string nil t))
+               (not (nnmail-within-headers-p))))
+    ;; If unsuccessful, search backward from where we started,
+    (unless found
+      (goto-char start)
+      (while (and (setq found (search-backward art-string nil t))
+                 (not (nnmail-within-headers-p)))))
+    (when found
+      (nnmail-search-unix-mail-delim-backward))))
+
+(defun nnfolder-delete-mail (&optional leave-delim)
+  "Delete the message that point is in.
+If optional argument LEAVE-DELIM is t, then mailbox delimiter is not
+deleted.  Point is left where the deleted region was."
+  (save-restriction
+    (narrow-to-region
      (save-excursion
+       ;; In case point is at the beginning of the message already.
+       (forward-line 1)
        (nnmail-search-unix-mail-delim-backward)
        (if leave-delim (progn (forward-line 1) (point))
         (point)))
@@ -496,7 +700,9 @@ time saver for large mailboxes.")
        (forward-line 1)
        (if (nnmail-search-unix-mail-delim)
           (point)
-        (point-max))))))
+        (point-max))))
+    (run-hooks 'nnfolder-delete-mail-hook)
+    (delete-region (point-min) (point-max))))
 
 (defun nnfolder-possibly-change-group (group &optional server dont-check)
   ;; Change servers.
@@ -507,30 +713,27 @@ time saver for large mailboxes.")
     (setq nnfolder-current-buffer nil
          nnfolder-current-group nil))
   ;; Change group.
-  (when (and group
-            (not (equal group nnfolder-current-group)))
-    (let ((pathname-coding-system 'binary))
-      (nnmail-activate 'nnfolder)
-      (when (and (not (assoc group nnfolder-group-alist))
-                (not (file-exists-p
-                      (nnfolder-group-pathname group))))
-       ;; The group doesn't exist, so we create a new entry for it.
-       (push (list group (cons 1 0)) nnfolder-group-alist)
-       (nnmail-save-active nnfolder-group-alist nnfolder-active-file))
-
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
+    (when (and group
+              (not (equal group nnfolder-current-group))
+              (progn
+                (nnmail-activate 'nnfolder)
+                (and (assoc group nnfolder-group-alist)
+                     (file-exists-p (nnfolder-group-pathname group)))))
       (if dont-check
          (setq nnfolder-current-group group
                nnfolder-current-buffer nil)
        (let (inf file)
-         ;; If we have to change groups, see if we don't already have the
-         ;; folder in memory.  If we do, verify the modtime and destroy
-         ;; the folder if needed so we can rescan it.
+         ;; If we have to change groups, see if we don't already have
+         ;; the folder in memory.  If we do, verify the modtime and
+         ;; destroy the folder if needed so we can rescan it.
          (setq nnfolder-current-buffer
                (nth 1 (assoc group nnfolder-buffer-alist)))
 
-         ;; If the buffer is not live, make sure it isn't in the alist.  If it
-         ;; is live, verify that nobody else has touched the file since last
-         ;; time.
+         ;; If the buffer is not live, make sure it isn't in the
+         ;; alist.  If it is live, verify that nobody else has
+         ;; touched the file since last time.
          (when (and nnfolder-current-buffer
                     (not (gnus-buffer-live-p nnfolder-current-buffer)))
            (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)
@@ -546,7 +749,11 @@ time saver for large mailboxes.")
              ;; See whether we need to create the new file.
              (unless (file-exists-p file)
                (gnus-make-directory (file-name-directory file))
-               (nnmail-write-region 1 1 file t 'nomesg))
+               (let ((nnmail-file-coding-system
+                      (or nnfolder-file-coding-system-for-write
+                          nnfolder-file-coding-system-for-write)))
+                 (nnmail-write-region (point-min) (point-min)
+                                      file t 'nomesg)))
              (when (setq nnfolder-current-buffer (nnfolder-read-folder group))
                (set-buffer nnfolder-current-buffer)
                (push (list group nnfolder-current-buffer)
@@ -557,10 +764,10 @@ time saver for large mailboxes.")
   (let* (save-list group-art)
     (goto-char (point-min))
     ;; The From line may have been quoted by movemail.
-    (when (looking-at (concat ">" message-unix-mail-delimiter))
+    (when (looking-at ">From")
       (delete-char 1))
     ;; This might come from somewhere else.
-    (unless (looking-at message-unix-mail-delimiter)
+    (unless (looking-at "From ")
       (insert "From nobody " (current-time-string) "\n")
       (goto-char (point-min)))
     ;; Quote all "From " lines in the article.
@@ -579,8 +786,9 @@ time saver for large mailboxes.")
     (while (setq group-art (pop group-art-list))
       ;; Kill any previous newsgroup markers.
       (goto-char (point-min))
-      (search-forward "\n\n" nil t)
-      (forward-line -1)
+      (if (search-forward "\n\n" nil t)
+         (forward-line -1)
+       (goto-char (point-max)))
       (while (search-backward (concat "\n" nnfolder-article-marker) nil t)
        (delete-region (1+ (point)) (progn (forward-line 2) (point))))
 
@@ -594,7 +802,11 @@ time saver for large mailboxes.")
          (nnfolder-possibly-change-folder (car group-art))
          (let ((buffer-read-only nil))
            (nnfolder-normalize-buffer)
-           (insert-buffer-substring obuf beg end)))))
+           (insert-buffer-substring obuf beg end))
+         (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+           (set-buffer obuf)
+           (nnfolder-add-nov (car group-art) (cdr group-art)
+                             (nnfolder-parse-head nil beg end))))))
 
     ;; Did we save it anywhere?
     save-list))
@@ -604,15 +816,18 @@ time saver for large mailboxes.")
   (goto-char (point-max))
   (skip-chars-backward "\n")
   (delete-region (point) (point-max))
-  (insert "\n\n"))
+  (unless (bobp)
+    (insert "\n\n")))
 
 (defun nnfolder-insert-newsgroup-line (group-art)
   (save-excursion
     (goto-char (point-min))
-    (when (search-forward "\n\n" nil t)
-      (forward-char -1)
-      (insert (format (concat nnfolder-article-marker "%d   %s\n")
-                     (cdr group-art) (current-time-string))))))
+    (unless (search-forward "\n\n" nil t)
+      (goto-char (point-max))
+      (insert "\n"))
+    (forward-char -1)
+    (insert (format (concat nnfolder-article-marker "%d   %s\n")
+                   (cdr group-art) (current-time-string)))))
 
 (defun nnfolder-active-number (group)
   ;; Find the next article number in GROUP.
@@ -634,28 +849,34 @@ time saver for large mailboxes.")
       (when inf
        (setq nnfolder-buffer-alist (delq inf nnfolder-buffer-alist)))
       (when nnfolder-group-alist
-       (nnmail-save-active nnfolder-group-alist nnfolder-active-file))
+       (nnfolder-save-active nnfolder-group-alist nnfolder-active-file))
       (push (list group (nnfolder-read-folder group))
            nnfolder-buffer-alist))))
 
-;; This method has a problem if you've accidentally let the active list get
-;; out of sync with the files.  This could happen, say, if you've
-;; accidentally gotten new mail with something other than Gnus (but why
-;; would _that_ ever happen? :-).  In that case, we will be in the middle of
-;; processing the file, ready to add new X-Gnus article number markers, and
-;; we'll run across a message with no ID yet - the active list _may_not_ be
-;; ready for us yet.
-
-;; To handle this, I'm modifying this routine to maintain the maximum ID seen
-;; so far, and when we hit a message with no ID, we will _manually_ scan the
-;; rest of the message looking for any more, possibly higher IDs.  We'll
-;; assume the maximum that we find is the highest active.  Note that this
-;; shouldn't cost us much extra time at all, but will be a lot less
-;; vulnerable to glitches between the mbox and the active file.
+;; This method has a problem if you've accidentally let the active
+;; list get out of sync with the files.  This could happen, say, if
+;; you've accidentally gotten new mail with something other than Gnus
+;; (but why would _that_ ever happen? :-).  In that case, we will be
+;; in the middle of processing the file, ready to add new X-Gnus
+;; article number markers, and we'll run across a message with no ID
+;; yet - the active list _may_not_ be ready for us yet.
+
+;; To handle this, I'm modifying this routine to maintain the maximum
+;; ID seen so far, and when we hit a message with no ID, we will
+;; _manually_ scan the rest of the message looking for any more,
+;; possibly higher IDs.  We'll assume the maximum that we find is the
+;; highest active.  Note that this shouldn't cost us much extra time
+;; at all, but will be a lot less vulnerable to glitches between the
+;; mbox and the active file.
 
 (defun nnfolder-read-folder (group)
   (let* ((file (nnfolder-group-pathname group))
-        (buffer (set-buffer (nnheader-find-file-noselect file))))
+        (nov  (nnfolder-group-nov-pathname group))
+        (buffer (set-buffer
+                 (let ((nnheader-file-coding-system
+                        nnfolder-file-coding-system))
+                   (nnheader-find-file-noselect file)))))
+    (set-buffer-multibyte t) ;; Use multibyte buffer for future copying.
     (if (equal (cadr (assoc group nnfolder-scantime-alist))
               (nth 5 (file-attributes file)))
        ;; This looks up-to-date, so we don't do any scanning.
@@ -663,12 +884,16 @@ time saver for large mailboxes.")
            buffer
          (push (list group buffer) nnfolder-buffer-alist)
          (set-buffer-modified-p t)
-         (save-buffer))
+         (nnfolder-save-buffer))
       ;; Parse the damn thing.
       (save-excursion
+       (goto-char (point-min))
+       ;; Remove any blank lines at the start.
+       (while (eq (following-char) ?\n)
+         (delete-char 1))
        (nnmail-activate 'nnfolder)
        ;; Read in the file.
-       (let ((delim (concat "^" message-unix-mail-delimiter))
+       (let ((delim "^From ")
              (marker (concat "\n" nnfolder-article-marker))
              (number "[0-9]+")
              (active (or (cadr (assoc group nnfolder-group-alist))
@@ -676,43 +901,74 @@ time saver for large mailboxes.")
              (scantime (assoc group nnfolder-scantime-alist))
              (minid (lsh -1 -1))
              maxid start end newscantime
+             novbuf articles newnum
              buffer-read-only)
-         (buffer-disable-undo (current-buffer))
+         (buffer-disable-undo)
          (setq maxid (cdr active))
+
+         (unless (or gnus-nov-is-evil nnfolder-nov-is-evil
+                     (and (file-exists-p nov)
+                          (file-newer-than-file-p nov file)))
+           (unless (file-exists-p nov)
+             (gnus-make-directory (file-name-directory nov)))
+           (with-current-buffer
+               (setq novbuf (nnfolder-open-nov group))
+             (goto-char (point-min))
+             (while (not (eobp))
+               (push (read novbuf) articles)
+               (forward-line 1))
+             (setq articles (nreverse articles))))
          (goto-char (point-min))
 
-         ;; Anytime the active number is 1 or 0, it is suspect.  In that
-         ;; case, search the file manually to find the active number.  Or,
-         ;; of course, if we're being paranoid.  (This would also be the
-         ;; place to build other lists from the header markers, such as
-         ;; expunge lists, etc., if we ever desired to abandon the active
-         ;; file entirely for mboxes.)
+         ;; Anytime the active number is 1 or 0, it is suspect.  In
+         ;; that case, search the file manually to find the active
+         ;; number.  Or, of course, if we're being paranoid.  (This
+         ;; would also be the place to build other lists from the
+         ;; header markers, such as expunge lists, etc., if we ever
+         ;; desired to abandon the active file entirely for mboxes.)
          (when (or nnfolder-ignore-active-file
+                   novbuf
                    (< maxid 2))
            (while (and (search-forward marker nil t)
-                       (re-search-forward number nil t))
-             (let ((newnum (string-to-number (match-string 0))))
-               (setq maxid (max maxid newnum))
-               (setq minid (min minid newnum))))
+                       (looking-at number))
+             (setq newnum (string-to-number (match-string 0)))
+             (when (nnmail-within-headers-p)
+               (setq maxid (max maxid newnum)
+                     minid (min minid newnum))
+               (when novbuf
+                 (if (memq newnum articles)
+                     (setq articles (delq newnum articles))
+                   (let ((headers (nnfolder-parse-head newnum)))
+                     (with-current-buffer novbuf
+                       (nnheader-find-nov-line newnum)
+                       (nnheader-insert-nov headers)))))))
+           (when (and novbuf articles)
+             (with-current-buffer novbuf
+               (dolist (article articles)
+                 (when (nnheader-find-nov-line article)
+                   (delete-region (point)
+                                  (progn (forward-line 1) (point)))))))
            (setcar active (max 1 (min minid maxid)))
            (setcdr active (max maxid (cdr active)))
            (goto-char (point-min)))
 
-         ;; As long as we trust that the user will only insert unmarked mail
-         ;; at the end, go to the end and search backwards for the last
-         ;; marker.  Find the start of that message, and begin to search for
-         ;; unmarked messages from there.
+         ;; As long as we trust that the user will only insert
+         ;; unmarked mail at the end, go to the end and search
+         ;; backwards for the last marker.  Find the start of that
+         ;; message, and begin to search for unmarked messages from
+         ;; there.
          (when (not (or nnfolder-distrust-mbox
                         (< maxid 2)))
            (goto-char (point-max))
            (unless (re-search-backward marker nil t)
              (goto-char (point-min)))
-           (when (nnmail-search-unix-mail-delim)
-             (goto-char (point-min))))
+           ;;(when (nnmail-search-unix-mail-delim)
+           ;;  (goto-char (point-min)))
+           )
 
-         ;; Keep track of the active number on our own, and insert it back
-         ;; into the active list when we're done.  Also, prime the pump to
-         ;; cut down on the number of searches we do.
+         ;; Keep track of the active number on our own, and insert it
+         ;; back into the active list when we're done.  Also, prime
+         ;; the pump to cut down on the number of searches we do.
          (unless (nnmail-search-unix-mail-delim)
            (goto-char (point-max)))
          (setq end (point-marker))
@@ -731,47 +987,72 @@ time saver for large mailboxes.")
              (narrow-to-region start end)
              (nnmail-insert-lines)
              (nnfolder-insert-newsgroup-line
-              (cons nil (nnfolder-active-number nnfolder-current-group)))
+              (cons nil
+                    (setq newnum
+                          (nnfolder-active-number group))))
+             (when novbuf
+               (let ((headers (nnfolder-parse-head newnum (point-min)
+                                                   (point-max))))
+                 (with-current-buffer novbuf
+                   (goto-char (point-max))
+                   (nnheader-insert-nov headers))))
              (widen)))
 
          (set-marker end nil)
-         ;; Make absolutely sure that the active list reflects reality!
-         (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
+         ;; Make absolutely sure that the active list reflects
+         ;; reality!
+         (nnfolder-save-active nnfolder-group-alist nnfolder-active-file)
+
          ;; Set the scantime for this group.
          (setq newscantime (visited-file-modtime))
          (if scantime
              (setcdr scantime (list newscantime))
-           (push (list nnfolder-current-group newscantime)
+           (push (list group newscantime)
                  nnfolder-scantime-alist))
+         ;; Save nov.
+         (when novbuf
+           (nnfolder-save-nov))
          (current-buffer))))))
 
 ;;;###autoload
 (defun nnfolder-generate-active-file ()
-  "Look for mbox folders in the nnfolder directory and make them into groups."
+  "Look for mbox folders in the nnfolder directory and make them into groups.
+This command does not work if you use short group names."
   (interactive)
   (nnmail-activate 'nnfolder)
+  (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+    (dolist (file (directory-files (or nnfolder-nov-directory
+                                      nnfolder-directory)
+                                  t
+                                  (concat
+                                   (regexp-quote nnfolder-nov-file-suffix)
+                                   "$")))
+      (when (not (message-mail-file-mbox-p file))
+       (ignore-errors
+         (delete-file file)))))
   (let ((files (directory-files nnfolder-directory))
-        file)
+       file)
     (while (setq file (pop files))
       (when (and (not (backup-file-name-p file))
-                 (message-mail-file-mbox-p
+                (message-mail-file-mbox-p
                  (nnheader-concat nnfolder-directory file)))
-        (let ((oldgroup (assoc file nnfolder-group-alist)))
-          (if oldgroup
-              (nnheader-message 5 "Refreshing group %s..." file)
-            (nnheader-message 5 "Adding group %s..." file))
+       (let ((oldgroup (assoc file nnfolder-group-alist)))
+         (if oldgroup
+             (nnheader-message 5 "Refreshing group %s..." file)
+           (nnheader-message 5 "Adding group %s..." file))
          (if oldgroup
              (setq nnfolder-group-alist
                    (delq oldgroup (copy-sequence nnfolder-group-alist))))
-          (push (list file (cons 1 0)) nnfolder-group-alist)
-          (nnfolder-possibly-change-folder file)
-          (nnfolder-possibly-change-group file)
-          (nnfolder-close-group file))))
-    (message "")))
+         (push (list file (cons 1 0)) nnfolder-group-alist)
+         (nnfolder-possibly-change-folder file)
+         (nnfolder-possibly-change-group file)
+         (nnfolder-close-group file))))
+    (nnheader-message 5 "")))
 
 (defun nnfolder-group-pathname (group)
-  "Make pathname for GROUP."
-  (setq group (gnus-encode-coding-string group nnmail-pathname-coding-system))
+  "Make file name for GROUP."
+  (setq group
+       (encode-coding-string group nnmail-pathname-coding-system))
   (let ((dir (file-name-as-directory (expand-file-name nnfolder-directory))))
     ;; If this file exists, we use it directly.
     (if (or nnmail-use-long-file-names
@@ -780,12 +1061,218 @@ time saver for large mailboxes.")
       ;; If not, we translate dots into slashes.
       (concat dir (nnheader-replace-chars-in-string group ?. ?/)))))
 
+(defun nnfolder-group-nov-pathname (group)
+  "Make pathname for GROUP NOV."
+  (let ((nnfolder-directory
+        (or nnfolder-nov-directory nnfolder-directory)))
+    (concat (nnfolder-group-pathname group) nnfolder-nov-file-suffix)))
+
 (defun nnfolder-save-buffer ()
   "Save the buffer."
   (when (buffer-modified-p)
     (run-hooks 'nnfolder-save-buffer-hook)
     (gnus-make-directory (file-name-directory (buffer-file-name)))
-    (save-buffer)))
+    (let* ((coding-system-for-write
+           (or nnfolder-file-coding-system-for-write
+               nnfolder-file-coding-system))
+          (output-coding-system coding-system-for-write))
+      (save-buffer)))
+  (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
+    (nnfolder-save-nov)))
+
+(defun nnfolder-save-active (group-alist active-file)
+  (let ((nnmail-active-file-coding-system
+        (or nnfolder-active-file-coding-system-for-write
+            nnfolder-active-file-coding-system)))
+    (nnmail-save-active group-alist active-file)))
+
+(defun nnfolder-open-nov (group)
+  (or (cdr (assoc group nnfolder-nov-buffer-alist))
+      (let ((buffer (get-buffer-create (format " *nnfolder overview %s*" group))))
+       (save-excursion
+         (set-buffer buffer)
+         (set (make-local-variable 'nnfolder-nov-buffer-file-name)
+              (nnfolder-group-nov-pathname group))
+         (erase-buffer)
+         (when (file-exists-p nnfolder-nov-buffer-file-name)
+           (nnheader-insert-file-contents nnfolder-nov-buffer-file-name)))
+       (push (cons group buffer) nnfolder-nov-buffer-alist)
+       buffer)))
+
+(defun nnfolder-save-nov ()
+  (save-excursion
+    (while nnfolder-nov-buffer-alist
+      (when (buffer-name (cdar nnfolder-nov-buffer-alist))
+       (set-buffer (cdar nnfolder-nov-buffer-alist))
+       (when (buffer-modified-p)
+         (gnus-make-directory (file-name-directory
+                               nnfolder-nov-buffer-file-name))
+         (nnmail-write-region 1 (point-max) nnfolder-nov-buffer-file-name
+                              nil 'nomesg))
+       (set-buffer-modified-p nil)
+       (kill-buffer (current-buffer)))
+      (setq nnfolder-nov-buffer-alist (cdr nnfolder-nov-buffer-alist)))))
+
+(defun nnfolder-nov-delete-article (group article)
+  (save-excursion
+    (set-buffer (nnfolder-open-nov group))
+    (when (nnheader-find-nov-line article)
+      (delete-region (point) (progn (forward-line 1) (point))))
+    t))
+
+(defun nnfolder-retrieve-headers-with-nov (articles &optional fetch-old)
+  (if (or gnus-nov-is-evil nnfolder-nov-is-evil)
+      nil
+    (let ((nov (nnfolder-group-nov-pathname nnfolder-current-group)))
+      (when (file-exists-p nov)
+       (save-excursion
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (nnheader-insert-file-contents nov)
+         (if (and fetch-old
+                  (not (numberp fetch-old)))
+             t                         ; Don't remove anything.
+           (nnheader-nov-delete-outside-range
+            (if fetch-old (max 1 (- (car articles) fetch-old))
+              (car articles))
+            (car (last articles)))
+           t))))))
+
+(defun nnfolder-parse-head (&optional number b e)
+  "Parse the head of the current buffer."
+  (let ((buf (current-buffer))
+       chars)
+    (save-excursion
+      (unless b
+       (setq b (if (nnmail-search-unix-mail-delim-backward)
+                   (point) (point-min)))
+       (forward-line 1)
+       (setq e (if (nnmail-search-unix-mail-delim)
+                   (point) (point-max))))
+      (setq chars (- e b))
+      (unless (zerop chars)
+       (goto-char b)
+       (if (search-forward "\n\n" e t) (setq e (1- (point)))))
+      (with-temp-buffer
+       (insert-buffer-substring buf b e)
+       (let ((headers (nnheader-parse-naked-head)))
+         (mail-header-set-chars headers chars)
+         (mail-header-set-number headers number)
+         headers)))))
+
+(defun nnfolder-add-nov (group article headers)
+  "Add a nov line for the GROUP base."
+  (save-excursion
+    (set-buffer (nnfolder-open-nov group))
+    (goto-char (point-max))
+    (mail-header-set-number headers article)
+    (nnheader-insert-nov headers)))
+
+(deffoo nnfolder-request-set-mark (group actions &optional server)
+  (when (and server
+            (not (nnfolder-server-opened server)))
+    (nnfolder-open-server server))
+  (unless nnfolder-marks-is-evil
+    (nnfolder-open-marks group server)
+    (dolist (action actions)
+      (let ((range (nth 0 action))
+           (what  (nth 1 action))
+           (marks (nth 2 action)))
+       (assert (or (eq what 'add) (eq what 'del)) t
+               "Unknown request-set-mark action: %s" what)
+       (dolist (mark marks)
+         (setq nnfolder-marks (gnus-update-alist-soft
+                           mark
+                           (funcall (if (eq what 'add) 'gnus-range-add
+                                      'gnus-remove-from-range)
+                                    (cdr (assoc mark nnfolder-marks)) range)
+                           nnfolder-marks)))))
+    (nnfolder-save-marks group server))
+  nil)
+
+(deffoo nnfolder-request-update-info (group info &optional server)
+  ;; Change servers.
+  (when (and server
+            (not (nnfolder-server-opened server)))
+    (nnfolder-open-server server))
+  (when (and (not nnfolder-marks-is-evil) (nnfolder-marks-changed-p group))
+    (nnheader-message 8 "Updating marks for %s..." group)
+    (nnfolder-open-marks group server)
+    ;; Update info using `nnfolder-marks'.
+    (mapcar (lambda (pred)
+             (unless (memq (cdr pred) gnus-article-unpropagated-mark-lists)
+               (gnus-info-set-marks
+                info
+                (gnus-update-alist-soft
+                 (cdr pred)
+                 (cdr (assq (cdr pred) nnfolder-marks))
+                 (gnus-info-marks info))
+                t)))
+           gnus-article-mark-lists)
+    (let ((seen (cdr (assq 'read nnfolder-marks))))
+      (gnus-info-set-read info
+                         (if (and (integerp (car seen))
+                                  (null (cdr seen)))
+                             (list (cons (car seen) (car seen)))
+                           seen)))
+    (nnheader-message 8 "Updating marks for %s...done" group))
+  info)
+
+(defun nnfolder-group-marks-pathname (group)
+  "Make pathname for GROUP NOV."
+  (let ((nnfolder-directory (or nnfolder-marks-directory nnfolder-directory)))
+    (concat (nnfolder-group-pathname group) nnfolder-marks-file-suffix)))
+
+(defun nnfolder-marks-changed-p (group)
+  (let ((file (nnfolder-group-marks-pathname group)))
+    (if (null (gnus-gethash file nnfolder-marks-modtime))
+       t ;; never looked at marks file, assume it has changed
+      (not (equal (gnus-gethash file nnfolder-marks-modtime)
+                 (nth 5 (file-attributes file)))))))
+
+(defun nnfolder-save-marks (group server)
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (file (nnfolder-group-marks-pathname group)))
+    (condition-case err
+       (progn
+         (with-temp-file file
+           (erase-buffer)
+           (gnus-prin1 nnfolder-marks)
+           (insert "\n"))
+         (gnus-sethash file
+                       (nth 5 (file-attributes file))
+                       nnfolder-marks-modtime))
+      (error (or (gnus-yes-or-no-p
+                 (format "Could not write to %s (%s).  Continue? " file err))
+                (error "Cannot write to %s (%s)" err))))))
+
+(defun nnfolder-open-marks (group server)
+  (let ((file (nnfolder-group-marks-pathname group)))
+    (if (file-exists-p file)
+       (condition-case err
+           (with-temp-buffer
+             (gnus-sethash file (nth 5 (file-attributes file))
+                           nnfolder-marks-modtime)
+             (nnheader-insert-file-contents file)
+             (setq nnfolder-marks (read (current-buffer)))
+             (dolist (el gnus-article-unpropagated-mark-lists)
+               (setq nnfolder-marks (gnus-remassoc el nnfolder-marks))))
+         (error (or (gnus-yes-or-no-p
+                     (format "Error reading nnfolder marks file %s (%s).  Continuing will use marks from .newsrc.eld.  Continue? " file err))
+                    (error "Cannot read nnfolder marks file %s (%s)" file err))))
+      ;; User didn't have a .marks file.  Probably first time
+      ;; user of the .marks stuff.  Bootstrap it from .newsrc.eld.
+      (let ((info (gnus-get-info
+                  (gnus-group-prefixed-name
+                   group
+                   (gnus-server-to-method (format "nnfolder:%s" server))))))
+       (nnheader-message 7 "Bootstrapping marks for %s..." group)
+       (setq nnfolder-marks (gnus-info-marks info))
+       (push (cons 'read (gnus-info-read info)) nnfolder-marks)
+       (dolist (el gnus-article-unpropagated-mark-lists)
+         (setq nnfolder-marks (gnus-remassoc el nnfolder-marks)))
+       (nnfolder-save-marks group server)
+       (nnheader-message 7 "Bootstrapping marks for %s...done" group)))))
 
 (provide 'nnfolder)
 
index 6dd6361..6059dcf 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nngateway.el --- posting news via mail gateways
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
@@ -25,6 +27,7 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
 (require 'nnoo)
 (require 'message)
 
@@ -54,7 +57,7 @@ parameter -- the gateway address.")
            (nngateway-open-server server))
     ;; Rewrite the header.
     (let ((buf (current-buffer)))
-      (nnheader-temp-write nil
+      (with-temp-buffer
        (insert-buffer-substring buf)
        (message-narrow-to-head)
        (funcall nngateway-header-transformation nngateway-address)
@@ -62,7 +65,9 @@ parameter -- the gateway address.")
        (insert mail-header-separator "\n")
        (widen)
        (let (message-required-mail-headers)
-         (funcall message-send-mail-function))))))
+         (funcall (or message-send-mail-real-function
+                      message-send-mail-function)))
+       t))))
 
 ;;; Internal functions
 
@@ -75,6 +80,13 @@ parameter -- the gateway address.")
     (insert "To: " (nnheader-replace-chars-in-string newsgroups ?. ?-)
            "@" gateway "\n")))
 
+(defun nngateway-mail2news-header-transformation (gateway)
+  "Transform the headers for sending to a mail2news gateway."
+  (message-remove-header "to")
+  (message-remove-header "cc")
+  (goto-char (point-min))
+  (insert "To: " gateway "\n"))
+
 (nnoo-define-skeleton nngateway)
 
 (provide 'nngateway)
index 5751973..49f2ba5 100644 (file)
@@ -1,9 +1,14 @@
-;;; nnheader.el --- header access macros for Gnus and its backends
-;; Copyright (C) 1987,88,89,90,93,94,95,96,97,98 Free Software Foundation, Inc.
+;;; nnheader.el --- header access macros for Semi-gnus and its backends
+
+;; Copyright (C) 1987, 1988, 1989, 1990, 1993, 1994, 1995, 1996,
+;;        1997, 1998, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;; Keywords: news
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
+;; Keywords: mail, news, MIME
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Commentary:
 
-;; These macros may look very much like the ones in GNUS 4.1.  They
-;; are, in a way, but you should note that the indices they use have
-;; been changed from the internal GNUS format to the NOV format.  The
-;; makes it possible to read headers from XOVER much faster.
-;;
-;; The format of a header is now:
-;; [number subject from date id references chars lines xref]
-;;
-;; (That last entry is defined as "misc" in the NOV format, but Gnus
-;; uses it for xrefs.)
-
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
+
+;; Requiring `gnus-util' at compile time creates a circular
+;; dependency between nnheader.el and gnus-util.el.
+;;(eval-when-compile (require 'gnus-util))
 
 (require 'mail-utils)
+(require 'gnus-util)
+
+;; Reduce the required value of `recursive-load-depth-limit' for Emacs 21.
+(require 'pces)
+(require 'poem)
+(require 'std11)
+
+(require 'mime)
+(eval-and-compile
+  (autoload 'gnus-sorted-intersection "gnus-range")
+  (autoload 'gnus-intersection "gnus-range")
+  (autoload 'gnus-sorted-complement "gnus-range")
+  (autoload 'gnus-sorted-difference "gnus-range"))
+
+(defcustom gnus-verbose-backends 7
+  "Integer that says how verbose the Gnus backends should be.
+The higher the number, the more messages the Gnus backends will flash
+to say what it's doing.  At zero, the Gnus backends will be totally
+mute; at five, they will display most important messages; and at ten,
+they will keep on jabbering all the time."
+  :group 'gnus-start
+  :type 'integer)
+
+(defcustom gnus-nov-is-evil nil
+  "If non-nil, Gnus backends will never output headers in the NOV format."
+  :group 'gnus-server
+  :type 'boolean)
 
 (defvar nnheader-max-head-length 4096
-  "*Max length of the head of articles.")
+  "*Max length of the head of articles.
+
+Value is an integer, nil, or t.  nil means read in chunks of a file
+indefinitely until a complete head is found\; t means always read the
+entire file immediately, disregarding `nnheader-head-chop-length'.
+
+Integer values will in effect be rounded up to the nearest multiple of
+`nnheader-head-chop-length'.")
 
 (defvar nnheader-head-chop-length 2048
   "*Length of each read operation when trying to fetch HEAD headers.")
 
-(defvar nnheader-file-name-translation-alist nil
+(defvar nnheader-read-timeout
+  (if (string-match "windows-nt\\|os/2\\|emx\\|cygwin"
+                   (symbol-name system-type))
+      1.0                              ; why?
+    0.1)
+  "How long nntp should wait between checking for the end of output.
+Shorter values mean quicker response, but are more CPU intensive.")
+
+(defvar nnheader-file-name-translation-alist
+  (let ((case-fold-search t))
+    (cond
+     ((string-match "windows-nt\\|os/2\\|emx\\|cygwin"
+                   (symbol-name system-type))
+      (append (mapcar (lambda (c) (cons c ?_))
+                     '(?: ?* ?\" ?< ?> ??))
+             (if (string-match "windows-nt\\|cygwin"
+                               (symbol-name system-type))
+                 nil
+               '((?+ . ?-)))))
+     (t nil)))
   "*Alist that says how to translate characters in file names.
-For instance, if \":\" is illegal as a file character in file names
+For instance, if \":\" is invalid as a file character in file names
 on your system, you could say something like:
 
 \(setq nnheader-file-name-translation-alist '((?: . ?_)))")
 
+(defvar nnheader-text-coding-system
+  (if (memq system-type '(windows-nt ms-dos ms-windows))
+      'raw-text-dos
+    'raw-text)
+  "Text-safe coding system (For removing ^M).
+This variable is a substitute for `mm-text-coding-system'.")
+
+(defvar nnheader-text-coding-system-for-write nil
+  "Text coding system for write.
+This variable is a substitute for `mm-text-coding-system-for-write'.")
+
+(defvar nnheader-auto-save-coding-system
+  (cond
+   ((boundp 'MULE) '*junet*)
+   ((not (fboundp 'find-coding-system)) nil)
+   ((find-coding-system 'emacs-mule)
+    (if (memq system-type '(windows-nt ms-dos ms-windows))
+       'emacs-mule-dos 'emacs-mule))
+   ((find-coding-system 'escape-quoted) 'escape-quoted)
+   ((find-coding-system 'no-conversion) 'no-conversion)
+   (t nil))
+  "Coding system of auto save file.")
+
+(defvar nnheader-directory-separator-character
+  (string-to-char (substring (file-name-as-directory ".") -1))
+  "*A character used to a directory separator.")
+
 (eval-and-compile
- (autoload 'nnmail-message-id "nnmail")
- (autoload 'mail-position-on-field "sendmail")
- (autoload 'message-remove-header "message")
- (autoload 'cancel-function-timers "timers")
- (autoload 'gnus-point-at-eol "gnus-util")
- (autoload 'gnus-delete-line "gnus-util")
- (autoload 'gnus-buffer-live-p "gnus-util")
- (autoload 'gnus-encode-coding-string "gnus-ems"))
+  (autoload 'nnmail-message-id "nnmail")
+  (autoload 'mail-position-on-field "sendmail")
+  (autoload 'message-remove-header "message")
+  (autoload 'gnus-point-at-eol "gnus-util")
+  (autoload 'gnus-buffer-live-p "gnus-util"))
+
+;; mm-util stuff.
+(unless (featurep 'mm-util)
+  ;; Should keep track of `mm-image-load-path' in mm-util.el.
+  (defun nnheader-image-load-path (&optional package)
+    (let (dir result)
+      (dolist (path load-path (nreverse result))
+       (if (file-directory-p
+            (setq dir (concat (file-name-directory
+                               (directory-file-name path))
+                              "etc/" (or package "gnus/"))))
+           (push dir result))
+       (push path result))))
+  (defalias 'mm-image-load-path 'nnheader-image-load-path)
+
+  ;; Should keep track of `mm-read-coding-system' in mm-util.el.
+  (defalias 'mm-read-coding-system
+    (if (or (and (featurep 'xemacs)
+                (<= (string-to-number emacs-version) 21.1))
+           (boundp 'MULE))
+       (lambda (prompt &optional default-coding-system)
+         (read-coding-system prompt))
+      'read-coding-system))
+
+  ;; Should keep track of `mm-%s' in mm-util.el.
+  (defalias 'mm-multibyte-string-p
+    (if (fboundp 'multibyte-string-p)
+       'multibyte-string-p
+      'ignore))
+  (defalias 'mm-encode-coding-string 'encode-coding-string)
+  (defalias 'mm-decode-coding-string 'decode-coding-string)
+
+  ;; Should keep track of `mm-detect-coding-region' in mm-util.el.
+  (defun nnheader-detect-coding-region (start end)
+    "Like 'detect-coding-region' except returning the best one."
+    (let ((coding-systems
+          (static-if (boundp 'MULE)
+              (code-detect-region (point) (point-max))
+            (detect-coding-region (point) (point-max)))))
+      (or (car-safe coding-systems)
+         coding-systems)))
+  (defalias 'mm-detect-coding-region 'nnheader-detect-coding-region)
+
+  ;; Should keep track of `mm-detect-mime-charset-region' in mm-util.el.
+  (defun nnheader-detect-mime-charset-region (start end)
+    "Detect MIME charset of the text in the region between START and END."
+    (coding-system-to-mime-charset
+     (nnheader-detect-coding-region start end)))
+  (defalias 'mm-detect-mime-charset-region
+    'nnheader-detect-mime-charset-region)
+
+  ;; Should keep track of `mm-with-unibyte-buffer' in mm-util.el.
+  (defmacro nnheader-with-unibyte-buffer (&rest forms)
+  "Create a temporary buffer, and evaluate FORMS there like `progn'.
+Use unibyte mode for this."
+  `(let (default-enable-multibyte-characters default-mc-flag)
+     (with-temp-buffer ,@forms)))
+  (put 'nnheader-with-unibyte-buffer 'lisp-indent-function 0)
+  (put 'nnheader-with-unibyte-buffer 'edebug-form-spec '(body))
+  (put 'mm-with-unibyte-buffer 'lisp-indent-function 0)
+  (put 'mm-with-unibyte-buffer 'edebug-form-spec '(body))
+  (defalias 'mm-with-unibyte-buffer 'nnheader-with-unibyte-buffer)
+
+  ;; Should keep track of `mm-with-unibyte-current-buffer' in mm-util.el.
+  (defmacro nnheader-with-unibyte-current-buffer (&rest forms)
+    "Evaluate FORMS with current current buffer temporarily made unibyte.
+Also bind `default-enable-multibyte-characters' to nil.
+Equivalent to `progn' in XEmacs"
+    (let ((multibyte (make-symbol "multibyte"))
+         (buffer (make-symbol "buffer")))
+      (cond ((featurep 'xemacs)
+            `(let (default-enable-multibyte-characters)
+               ,@forms))
+           ((boundp 'MULE)
+            `(let ((,multibyte mc-flag)
+                   (,buffer (current-buffer)))
+               (unwind-protect
+                   (let (default-enable-multibyte-characters default-mc-flag)
+                     (setq mc-flag nil)
+                     ,@forms)
+                 (set-buffer ,buffer)
+                 (setq mc-flag ,multibyte))))
+           (t
+            `(let ((,multibyte enable-multibyte-characters)
+                   (,buffer (current-buffer)))
+               (unwind-protect
+                   (let (default-enable-multibyte-characters)
+                     (set-buffer-multibyte nil)
+                     ,@forms)
+                 (set-buffer ,buffer)
+                 (set-buffer-multibyte ,multibyte)))))))
+  (put 'nnheader-with-unibyte-current-buffer 'lisp-indent-function 0)
+  (put 'nnheader-with-unibyte-current-buffer 'edebug-form-spec '(body))
+  (put 'mm-with-unibyte-current-buffer 'lisp-indent-function 0)
+  (put 'mm-with-unibyte-current-buffer 'edebug-form-spec '(body))
+  (defalias 'mm-with-unibyte-current-buffer
+    'nnheader-with-unibyte-current-buffer)
+
+  ;; Should keep track of `mm-with-unibyte' in mm-util.el.
+  (defmacro nnheader-with-unibyte (&rest forms)
+    "Eval the FORMS with the default value of `enable-multibyte-characters'
+nil, ."
+    `(let (default-enable-multibyte-characters)
+       ,@forms))
+  (put 'nnheader-with-unibyte 'lisp-indent-function 0)
+  (put 'nnheader-with-unibyte 'edebug-form-spec '(body))
+  (put 'mm-with-unibyte 'lisp-indent-function 0)
+  (put 'mm-with-unibyte 'edebug-form-spec '(body))
+  (defalias 'mm-with-unibyte 'nnheader-with-unibyte)
+
+  ;; Should keep track of `mm-guess-mime-charset' in mm-util.el.
+  (defun nnheader-guess-mime-charset ()
+  "Guess the default MIME charset from the language environment."
+  (let ((language-info
+        (and (boundp 'current-language-environment)
+             (assoc current-language-environment
+                    language-info-alist)))
+       item)
+    (cond
+     ((null language-info)
+      'iso-8859-1)
+     ((setq item
+           (cadr
+            (or (assq 'coding-priority language-info)
+                (assq 'coding-system language-info))))
+      (if (fboundp 'coding-system-get)
+         (or (coding-system-get item 'mime-charset)
+             item)
+       item))
+     ((setq item (car (last (assq 'charset language-info))))
+      (if (eq item 'ascii)
+         'iso-8859-1
+        (charsets-to-mime-charset (list item))))
+     (t
+      'iso-8859-1))))
+  (defalias 'mm-guess-mime-charset 'nnheader-guess-mime-charset)
+
+  (defalias 'mm-char-int 'char-int)
+
+  ;; Should keep track of the same alias in mm-util.el.
+  (defalias 'mm-multibyte-p
+    (static-cond ((and (featurep 'xemacs) (featurep 'mule))
+                 (lambda nil t))
+                ((featurep 'xemacs)
+                 (lambda nil nil))
+                ((boundp 'MULE)
+                 (lambda nil mc-flag))
+                (t
+                 (lambda nil enable-multibyte-characters))))
+
+  ;; Should keep track of the same alias in mm-util.el.
+  (defalias 'mm-make-temp-file
+    (if (fboundp 'make-temp-file)
+       'make-temp-file
+      (lambda (prefix &optional dir-flag)
+       (let ((file (expand-file-name
+                    (make-temp-name prefix)
+                    (if (fboundp 'temp-directory)
+                        (temp-directory)
+                      temporary-file-directory))))
+         (if dir-flag
+             (make-directory file))
+         file))))
+
+  ;; Should keep track of `mm-coding-system-p' in mm-util.el.
+  (defun nnheader-coding-system-p (sym)
+    "Return non-nil if SYM is a coding system."
+    (or (and (fboundp 'find-coding-system) (find-coding-system sym))
+       (and (fboundp 'coding-system-p) (coding-system-p sym))))
+  (defalias 'mm-coding-system-p 'nnheader-coding-system-p))
+
+;; mail-parse stuff.
+(unless (featurep 'mail-parse)
+  (unless (fboundp 'std11-narrow-to-field)
+    (defalias 'std11-narrow-to-field
+      ;; Should keep track of `rfc2047-narrow-to-field' in rfc2047.el.
+      (lambda ()
+       "Narrow the buffer to the header on the current line."
+       (forward-line 0)
+       (narrow-to-region (point)
+                         (progn
+                           (std11-field-end)
+                           (when (eolp) (forward-line 1))
+                           (point)))
+       (goto-char (point-min)))))
+  (defalias 'mail-header-narrow-to-field 'std11-narrow-to-field)
+
+  ;; Should keep track of `ietf-drums-narrow-to-header' in ietf-drums.el.
+  (defun mail-narrow-to-head ()
+    "Narrow to the header section in the current buffer."
+    (narrow-to-region
+     (goto-char (point-min))
+     (if (re-search-forward "^\r?$" nil 1)
+        (match-beginning 0)
+       (point-max)))
+    (goto-char (point-min)))
+
+  (unless (fboundp 'std11-fold-region)
+    (defalias 'std11-fold-region
+      ;; Should keep track of `rfc2047-fold-region' in rfc2047.el.
+      (lambda (b e)
+       "Fold long lines in region B to E."
+       (save-restriction
+         (narrow-to-region b e)
+         (goto-char (point-min))
+         (let ((break nil)
+               (qword-break nil)
+               (first t)
+               (bol (save-restriction
+                      (widen)
+                      (gnus-point-at-bol))))
+           (while (not (eobp))
+             (when (and (or break qword-break)
+                        (> (- (point) bol) 76))
+               (goto-char (or break qword-break))
+               (setq break nil
+                     qword-break nil)
+               (if (looking-at "[ \t]")
+                   (insert "\n")
+                 (insert "\n "))
+               (setq bol (1- (point)))
+               ;; Don't break before the first non-LWSP characters.
+               (skip-chars-forward " \t")
+               (unless (eobp)
+                 (forward-char 1)))
+             (cond
+              ((eq (char-after) ?\n)
+               (forward-char 1)
+               (setq bol (point)
+                     break nil
+                     qword-break nil)
+               (skip-chars-forward " \t")
+               (unless (or (eobp) (eq (char-after) ?\n))
+                 (forward-char 1)))
+              ((eq (char-after) ?\r)
+               (forward-char 1))
+              ((memq (char-after) '(?  ?\t))
+               (skip-chars-forward " \t")
+               (if first
+                   ;; Don't break just after the header name.
+                   (setq first nil)
+                 (setq break (1- (point)))))
+              ((not break)
+               (if (not (looking-at "=\\?[^=]"))
+                   (if (eq (char-after) ?=)
+                       (forward-char 1)
+                     (skip-chars-forward "^ \t\n\r="))
+                 (setq qword-break (point))
+                 (skip-chars-forward "^ \t\n\r")))
+              (t
+               (skip-chars-forward "^ \t\n\r"))))
+           (when (and (or break qword-break)
+                      (> (- (point) bol) 76))
+             (goto-char (or break qword-break))
+             (setq break nil
+                   qword-break nil)
+             (if (looking-at "[ \t]")
+                 (insert "\n")
+               (insert "\n "))
+             (setq bol (1- (point)))
+             ;; Don't break before the first non-LWSP characters.
+             (skip-chars-forward " \t")
+             (unless (eobp)
+               (forward-char 1))))))))
+
+  (unless (fboundp 'std11-fold-field)
+    (defalias 'std11-fold-field
+      ;; Should keep track of `rfc2047-fold-field' in rfc2047.el.
+      (lambda ()
+       "Fold the current line."
+       (save-excursion
+         (save-restriction
+           (std11-narrow-to-field)
+           (std11-fold-region (point-min) (point-max)))))))
+  (defalias 'mail-header-fold-field 'std11-fold-field)
+
+  (unless (fboundp 'std11-unfold-region)
+    (defalias 'std11-unfold-region
+      ;; Should keep track of `rfc2047-unfold-region' in rfc2047.el.
+      (lambda (b e)
+       "Unfold lines in region B to E."
+       (save-restriction
+         (narrow-to-region b e)
+         (goto-char (point-min))
+         (let ((bol (save-restriction
+                      (widen)
+                      (gnus-point-at-bol)))
+               (eol (gnus-point-at-eol)))
+           (forward-line 1)
+           (while (not (eobp))
+             (if (and (looking-at "[ \t]")
+                      (< (- (gnus-point-at-eol) bol) 76))
+                 (delete-region eol (progn
+                                      (goto-char eol)
+                                      (skip-chars-forward "\r\n")
+                                      (point)))
+               (setq bol (gnus-point-at-bol)))
+             (setq eol (gnus-point-at-eol))
+             (forward-line 1)))))))
+
+  (unless (fboundp 'std11-unfold-field)
+    (defalias 'std11-unfold-field
+      ;; Should keep track of `rfc2047-unfold-field' in rfc2047.el.
+      (lambda ()
+       "Fold the current line."
+       (save-excursion
+         (save-restriction
+           (std11-narrow-to-field)
+           (std11-unfold-region (point-min) (point-max)))))))
+  (defalias 'mail-header-unfold-field 'std11-unfold-field)
+
+  (unless (fboundp 'std11-extract-addresses-components)
+    (defalias 'std11-extract-addresses-components
+      ;; This is the original function in T-gnus.
+      (lambda (string)
+       "Extract a list of full name and canonical address from STRING.  Each
+element looks like a list of the form (FULL-NAME CANONICAL-ADDRESS).
+If no name can be extracted, FULL-NAME will be nil."
+       (when string
+         (let (addresses)
+           (dolist (structure (std11-parse-addresses-string
+                               (std11-unfold-string string))
+                              addresses)
+             (push (list (std11-full-name-string structure)
+                         (std11-address-string structure))
+                   addresses))
+           (nreverse addresses))))))
+
+  ;; Should keep track of `ietf-drums-parse-addresses' in ietf-drums.el.
+  (defun mail-header-parse-addresses (string)
+    "Parse STRING and return a list of MAILBOX / DISPLAY-NAME pairs."
+    (mapcar (function
+            (lambda (components)
+              (cons (nth 1 components) (car components))))
+           (std11-extract-addresses-components string)))
+
+  ;; Should keep track of `rfc2047-field-value' in rfc2047.el.
+  (defun std11-field-value (&optional dont-include-last-newline)
+    "Return the value of the field at point.  If the optional argument is
+given, the return value will not contain the last newline."
+    (let ((begin (point))
+         (inhibit-point-motion-hooks t)
+         start value)
+      (beginning-of-line)
+      (unless (eobp)
+       (while (and (memq (char-after) '(?\t ?\ ))
+                   (zerop (forward-line -1))))
+       (when (looking-at "[^\t\n ]+:[\t\n ]+")
+         (goto-char (setq start (match-end 0)))
+         (forward-line 1)
+         (while (and (memq (char-after) '(?\t ?\ ))
+                     (zerop (forward-line 1))))
+         (when dont-include-last-newline
+           (skip-chars-backward "\t\n " start))
+         (setq value (buffer-substring start (point)))))
+      (goto-char begin)
+      value))
+  (defalias 'mail-header-field-value 'std11-field-value))
+
+;; ietf-drums stuff.
+(unless (featurep 'ietf-drums)
+  ;; Should keep track of `ietf-drums-unfold-fws' in ietf-drums.el.
+  (defun nnheader-unfold-fws ()
+    "Unfold folding white space in the current buffer."
+    (goto-char (point-min))
+    (while (re-search-forward "[ \t]*\n[ \t]+" nil t)
+      (replace-match " " t t))
+    (goto-char (point-min)))
+
+  (defalias 'ietf-drums-unfold-fws 'nnheader-unfold-fws))
 
 ;;; Header access macros.
 
+;; These macros may look very much like the ones in GNUS 4.1.  They
+;; are, in a way, but you should note that the indices they use have
+;; been changed from the internal GNUS format to the NOV format.  The
+;; makes it possible to read headers from XOVER much faster.
+;;
+;; The format of a header is now:
+;; [number subject from date id references chars lines xref extra]
+;;
+;; (That next-to-last entry is defined as "misc" in the NOV format,
+;; but Gnus uses it for xrefs.)
+
+(require 'mmgnus)
+
 (defmacro mail-header-number (header)
   "Return article number in HEADER."
-  `(aref ,header 0))
+  `(mime-entity-location-internal ,header))
 
 (defmacro mail-header-set-number (header number)
   "Set article number of HEADER to NUMBER."
-  `(aset ,header 0 ,number))
-
-(defmacro mail-header-subject (header)
-  "Return subject string in HEADER."
-  `(aref ,header 1))
+  `(mime-entity-set-location-internal ,header ,number))
 
-(defmacro mail-header-set-subject (header subject)
-  "Set article subject of HEADER to SUBJECT."
-  `(aset ,header 1 ,subject))
+(defalias 'mail-header-subject 'mime-gnus-entity-subject-internal)
+(defalias 'mail-header-set-subject 'mime-gnus-entity-set-subject-internal)
 
-(defmacro mail-header-from (header)
-  "Return author string in HEADER."
-  `(aref ,header 2))
+(defalias 'mail-header-from 'mime-gnus-entity-from-internal)
+(defalias 'mail-header-set-from 'mime-gnus-entity-set-from-internal)
 
-(defmacro mail-header-set-from (header from)
-  "Set article author of HEADER to FROM."
-  `(aset ,header 2 ,from))
+(defalias 'mail-header-date 'mime-gnus-entity-date-internal)
+(defalias 'mail-header-set-date 'mime-gnus-entity-set-date-internal)
 
-(defmacro mail-header-date (header)
-  "Return date in HEADER."
-  `(aref ,header 3))
+(defalias 'mail-header-message-id 'mime-gnus-entity-id-internal)
+(defalias 'mail-header-id 'mime-gnus-entity-id-internal)
+(defalias 'mail-header-set-message-id 'mime-gnus-entity-set-id-internal)
+(defalias 'mail-header-set-id 'mime-gnus-entity-set-id-internal)
 
-(defmacro mail-header-set-date (header date)
-  "Set article date of HEADER to DATE."
-  `(aset ,header 3 ,date))
+(defalias 'mail-header-references 'mime-gnus-entity-references-internal)
+(defalias 'mail-header-set-references
+  'mime-gnus-entity-set-references-internal)
 
-(defalias 'mail-header-message-id 'mail-header-id)
-(defmacro mail-header-id (header)
-  "Return Id in HEADER."
-  `(aref ,header 4))
+(defalias 'mail-header-chars 'mime-gnus-entity-chars-internal)
+(defalias 'mail-header-set-chars 'mime-gnus-entity-set-chars-internal)
 
-(defalias 'mail-header-set-message-id 'mail-header-set-id)
-(defmacro mail-header-set-id (header id)
-  "Set article Id of HEADER to ID."
-  `(aset ,header 4 ,id))
+(defalias 'mail-header-lines 'mime-gnus-entity-lines-internal)
+(defalias 'mail-header-set-lines 'mime-gnus-entity-set-lines-internal)
 
-(defmacro mail-header-references (header)
-  "Return references in HEADER."
-  `(aref ,header 5))
+(defalias 'mail-header-xref 'mime-gnus-entity-xref-internal)
+(defalias 'mail-header-set-xref 'mime-gnus-entity-set-xref-internal)
 
-(defmacro mail-header-set-references (header ref)
-  "Set article references of HEADER to REF."
-  `(aset ,header 5 ,ref))
+(defalias 'nnheader-decode-subject
+  (mime-find-field-decoder 'Subject 'nov))
+(defalias 'nnheader-decode-from
+  (mime-find-field-decoder 'From 'nov))
 
-(defmacro mail-header-chars (header)
-  "Return number of chars of article in HEADER."
-  `(aref ,header 6))
+(defalias 'mail-header-extra 'mime-gnus-entity-extra-internal)
+(defalias 'mail-header-set-extra 'mime-gnus-entity-set-extra-internal)
 
-(defmacro mail-header-set-chars (header chars)
-  "Set number of chars in article of HEADER to CHARS."
-  `(aset ,header 6 ,chars))
+(defun nnheader-decode-field-body (field-body field-name
+                                             &optional mode max-column)
+  (mime-decode-field-body field-body
+                         (if (stringp field-name)
+                             (intern (capitalize field-name))
+                           field-name)
+                         mode max-column))
 
-(defmacro mail-header-lines (header)
-  "Return lines in HEADER."
-  `(aref ,header 7))
-
-(defmacro mail-header-set-lines (header lines)
-  "Set article lines of HEADER to LINES."
-  `(aset ,header 7 ,lines))
-
-(defmacro mail-header-xref (header)
-  "Return xref string in HEADER."
-  `(aref ,header 8))
-
-(defmacro mail-header-set-xref (header xref)
-  "Set article xref of HEADER to xref."
-  `(aset ,header 8 ,xref))
-
-(defun make-mail-header (&optional init)
-  "Create a new mail header structure initialized with INIT."
-  (make-vector 9 init))
-
-(defun make-full-mail-header (&optional number subject from date id
-                                       references chars lines xref)
+(defsubst make-full-mail-header (&optional number subject from date id
+                                          references chars lines xref
+                                          extra)
   "Create a new mail header structure initialized with the parameters given."
-  (vector number subject from date id references chars lines xref))
+  (luna-make-entity (mm-expand-class-name 'gnus)
+                   :location number
+                   :subject (if subject
+                                (nnheader-decode-subject subject))
+                   :from (if from
+                             (nnheader-decode-from from))
+                   :date date
+                   :id id
+                   :references references
+                   :chars chars
+                   :lines lines
+                   :xref xref
+                   :original-header (list (cons 'Subject subject)
+                                          (cons 'From from))
+                   :extra extra))
+
+(defsubst make-full-mail-header-from-decoded-header
+  (&optional number subject from date id references chars lines xref extra)
+  "Create a new mail header structure initialized with the parameters given."
+  (luna-make-entity (mm-expand-class-name 'gnus)
+                   :location number
+                   :subject subject
+                   :from from
+                   :date date
+                   :id id
+                   :references references
+                   :chars chars
+                   :lines lines
+                   :xref xref
+                   :extra extra))
+
+(defsubst make-mail-header (&optional init)
+  "Create a new mail header structure initialized with INIT."
+  (make-full-mail-header init init init init init
+                        init init init init init))
 
 ;; fake message-ids: generation and detection
 
@@ -162,104 +629,138 @@ on your system, you could say something like:
 
 ;; Parsing headers and NOV lines.
 
-(defsubst nnheader-header-value ()
-  (buffer-substring (match-end 0) (gnus-point-at-eol)))
+(defsubst nnheader-remove-cr-followed-by-lf ()
+  (goto-char (point-max))
+  (while (search-backward "\r\n" nil t)
+    (delete-char 1)))
 
-(defun nnheader-parse-head (&optional naked)
+(defsubst nnheader-header-value ()
+  (let ((pt (point)))
+    (prog2
+       (skip-chars-forward " \t")
+       (buffer-substring (point) (std11-field-end))
+      (goto-char pt))))
+
+(defun nnheader-parse-naked-head (&optional number)
+  ;; This function unfolds continuation lines in this buffer
+  ;; destructively.  When this side effect is unwanted, use
+  ;; `nnheader-parse-head' instead of this function.
   (let ((case-fold-search t)
-       (cur (current-buffer))
        (buffer-read-only nil)
-       in-reply-to lines p ref)
-    (goto-char (point-min))
-    (when naked
-      (insert "\n"))
-    ;; Search to the beginning of the next header.  Error messages
-    ;; do not begin with 2 or 3.
+       (cur (current-buffer))
+       (p (point-min))
+       in-reply-to lines ref)
+    (nnheader-remove-cr-followed-by-lf)
+    (ietf-drums-unfold-fws)
+    (subst-char-in-region (point-min) (point-max) ?\t ? )
+    (goto-char p)
+    (insert "\n")
     (prog1
-       (when (or naked (re-search-forward "^[23][0-9]+ " nil t))
-         ;; This implementation of this function, with nine
-         ;; search-forwards instead of the one re-search-forward and
-         ;; a case (which basically was the old function) is actually
-         ;; about twice as fast, even though it looks messier.  You
-         ;; can't have everything, I guess.  Speed and elegance
-         ;; don't always go hand in hand.
-         (vector
-          ;; Number.
-          (if naked
-              (progn
-                (setq p (point-min))
-                0)
-            (prog1
-                (read cur)
-              (end-of-line)
-              (setq p (point))
-              (narrow-to-region (point)
-                                (or (and (search-forward "\n.\n" nil t)
-                                         (- (point) 2))
-                                    (point)))))
-          ;; Subject.
-          (progn
-            (goto-char p)
-            (if (search-forward "\nsubject: " nil t)
-                (nnheader-header-value) "(none)"))
-          ;; From.
-          (progn
-            (goto-char p)
-            (if (search-forward "\nfrom: " nil t)
-                (nnheader-header-value) "(nobody)"))
-          ;; Date.
-          (progn
-            (goto-char p)
-            (if (search-forward "\ndate: " nil t)
-                (nnheader-header-value) ""))
-          ;; Message-ID.
-          (progn
-            (goto-char p)
-            (if (search-forward "\nmessage-id:" nil t)
-                (buffer-substring
-                 (1- (or (search-forward "<" (gnus-point-at-eol) t)
-                         (point)))
-                 (or (search-forward ">" (gnus-point-at-eol) t) (point)))
-              ;; If there was no message-id, we just fake one to make
-              ;; subsequent routines simpler.
-              (nnheader-generate-fake-message-id)))
-          ;; References.
-          (progn
-            (goto-char p)
-            (if (search-forward "\nreferences: " nil t)
-                (nnheader-header-value)
-              ;; Get the references from the in-reply-to header if there
-              ;; were no references and the in-reply-to header looks
-              ;; promising.
-              (if (and (search-forward "\nin-reply-to: " nil t)
-                       (setq in-reply-to (nnheader-header-value))
-                       (string-match "<[^>]+>" in-reply-to))
-                  (let (ref2)
-                    (setq ref (substring in-reply-to (match-beginning 0)
-                                         (match-end 0)))
-                    (while (string-match "<[^>]+>" in-reply-to (match-end 0))
-                      (setq ref2 (substring in-reply-to (match-beginning 0)
-                                            (match-end 0)))
-                      (when (> (length ref2) (length ref))
-                        (setq ref ref2))))
-                "")))
-          ;; Chars.
-          0
-          ;; Lines.
-          (progn
-            (goto-char p)
-            (if (search-forward "\nlines: " nil t)
-                (if (numberp (setq lines (read cur)))
-                    lines 0)
-              0))
-          ;; Xref.
-          (progn
-            (goto-char p)
-            (and (search-forward "\nxref: " nil t)
-                 (nnheader-header-value)))))
-      (when naked
-       (goto-char (point-min))
-       (delete-char 1)))))
+       ;; This implementation of this function, with nine
+       ;; search-forwards instead of the one re-search-forward and a
+       ;; case (which basically was the old function) is actually
+       ;; about twice as fast, even though it looks messier.  You
+       ;; can't have everything, I guess.  Speed and elegance don't
+       ;; always go hand in hand.
+       (make-full-mail-header
+        ;; Number.
+        (or number 0)
+        ;; Subject.
+        (progn
+          (goto-char p)
+          (if (search-forward "\nsubject:" nil t)
+              (nnheader-header-value) "(none)"))
+        ;; From.
+        (progn
+          (goto-char p)
+          (if (search-forward "\nfrom:" nil t)
+              (nnheader-header-value) "(nobody)"))
+        ;; Date.
+        (progn
+          (goto-char p)
+          (if (search-forward "\ndate:" nil t)
+              (nnheader-header-value) ""))
+        ;; Message-ID.
+        (progn
+          (goto-char p)
+          (if (search-forward "\nmessage-id:" nil t)
+              (buffer-substring
+               (1- (or (search-forward "<" (gnus-point-at-eol) t)
+                       (point)))
+               (or (search-forward ">" (gnus-point-at-eol) t) (point)))
+            ;; If there was no message-id, we just fake one to make
+            ;; subsequent routines simpler.
+            (nnheader-generate-fake-message-id)))
+        ;; References.
+        (progn
+          (goto-char p)
+          (if (search-forward "\nreferences:" nil t)
+              (nnheader-header-value)
+            ;; Get the references from the in-reply-to header if
+            ;; there were no references and the in-reply-to header
+            ;; looks promising.
+            (if (and (search-forward "\nin-reply-to:" nil t)
+                     (setq in-reply-to (nnheader-header-value))
+                     (string-match "<[^\n>]+>" in-reply-to))
+                (let (ref2)
+                  (setq ref (substring in-reply-to (match-beginning 0)
+                                       (match-end 0)))
+                  (while (string-match "<[^\n>]+>"
+                                       in-reply-to (match-end 0))
+                    (setq ref2 (substring in-reply-to (match-beginning 0)
+                                          (match-end 0)))
+                    (when (> (length ref2) (length ref))
+                      (setq ref ref2)))
+                  ref)
+              nil)))
+        ;; Chars.
+        0
+        ;; Lines.
+        (progn
+          (goto-char p)
+          (if (search-forward "\nlines: " nil t)
+              (if (numberp (setq lines (read cur)))
+                  lines 0)
+            0))
+        ;; Xref.
+        (progn
+          (goto-char p)
+          (and (search-forward "\nxref:" nil t)
+               (nnheader-header-value)))
+        ;; Extra.
+        (when nnmail-extra-headers
+          (let ((extra nnmail-extra-headers)
+                out)
+            (while extra
+              (goto-char p)
+              (when (search-forward
+                     (concat "\n" (symbol-name (car extra)) ":") nil t)
+                (push (cons (car extra) (nnheader-header-value))
+                      out))
+              (pop extra))
+            out)))
+      (goto-char p)
+      (delete-char 1))))
+
+(defun nnheader-parse-head (&optional naked)
+  (let ((cur (current-buffer)) num beg end)
+    (when (if naked
+             (setq num 0
+                   beg (point-min)
+                   end (point-max))
+           (goto-char (point-min))
+           ;; Search to the beginning of the next header.  Error
+           ;; messages do not begin with 2 or 3.
+           (when (re-search-forward "^[23][0-9]+ " nil t)
+             (end-of-line)
+             (setq num (read cur)
+                   beg (point)
+                   end (if (search-forward "\n.\n" nil t)
+                           (- (point) 2)
+                         (point)))))
+      (with-temp-buffer
+       (insert-buffer-substring cur beg end)
+       (nnheader-parse-naked-head num)))))
 
 (defmacro nnheader-nov-skip-field ()
   '(search-forward "\t" eol 'move))
@@ -269,49 +770,108 @@ on your system, you could say something like:
 
 (defmacro nnheader-nov-read-integer ()
   '(prog1
-       (if (= (following-char) ?\t)
+       (if (eq (char-after) ?\t)
           0
-        (let ((num (ignore-errors (read (current-buffer)))))
+        (let ((num (condition-case nil
+                       (read (current-buffer))
+                     (error nil))))
           (if (numberp num) num 0)))
-     (or (eobp) (forward-char 1))))
-
-;; (defvar nnheader-none-counter 0)
+     (unless (eobp)
+       (search-forward "\t" eol 'move))))
+
+(defmacro nnheader-nov-parse-extra ()
+  '(let (out string)
+     (while (not (memq (char-after) '(?\n nil)))
+       (setq string (nnheader-nov-field))
+       (when (string-match "^\\([^ :]+\\): " string)
+        (push (cons (intern (match-string 1 string))
+                    (substring string (match-end 0)))
+              out)))
+     out))
+
+(defmacro nnheader-nov-read-message-id ()
+  '(let ((id (nnheader-nov-field)))
+     (if (string-match "^<[^>]+>$" id)
+        id
+       (nnheader-generate-fake-message-id))))
 
 (defun nnheader-parse-nov ()
   (let ((eol (gnus-point-at-eol)))
-    (vector
+    (make-full-mail-header
      (nnheader-nov-read-integer)       ; number
      (nnheader-nov-field)              ; subject
      (nnheader-nov-field)              ; from
      (nnheader-nov-field)              ; date
-     (or (nnheader-nov-field)
-        (nnheader-generate-fake-message-id)) ; id
+     (nnheader-nov-read-message-id)    ; id
      (nnheader-nov-field)              ; refs
      (nnheader-nov-read-integer)       ; chars
      (nnheader-nov-read-integer)       ; lines
-     (if (= (following-char) ?\n)
+     (if (eq (char-after) ?\n)
         nil
-       (nnheader-nov-field))           ; misc
-     )))
+       (if (looking-at "Xref: ")
+          (goto-char (match-end 0)))
+       (nnheader-nov-field))           ; Xref
+     (nnheader-nov-parse-extra))))     ; extra
 
 (defun nnheader-insert-nov (header)
   (princ (mail-header-number header) (current-buffer))
+  (let ((p (point)))
+    (insert
+     "\t"
+     (or (mime-entity-fetch-field header 'Subject) "(none)") "\t"
+     (or (mime-entity-fetch-field header 'From) "(nobody)") "\t"
+     (or (mail-header-date header) "") "\t"
+     (or (mail-header-id header)
+        (nnmail-message-id))
+     "\t"
+     (or (mail-header-references header) "") "\t")
+    (princ (or (mail-header-chars header) 0) (current-buffer))
+    (insert "\t")
+    (princ (or (mail-header-lines header) 0) (current-buffer))
+    (insert "\t")
+    (when (mail-header-xref header)
+      (insert "Xref: " (mail-header-xref header)))
+    (when (or (mail-header-xref header)
+             (mail-header-extra header))
+      (insert "\t"))
+    (when (mail-header-extra header)
+      (let ((extra (mail-header-extra header)))
+       (while extra
+         (insert (symbol-name (caar extra))
+                 ": " (cdar extra) "\t")
+         (pop extra))))
+    (insert "\n")
+    (backward-char 1)
+    (while (search-backward "\n" p t)
+      (delete-char 1))
+    (forward-line 1)))
+
+(defun nnheader-parse-overview-file (file)
+  "Parse FILE and return a list of headers."
+  (mm-with-unibyte-buffer
+    (nnheader-insert-file-contents file)
+    (goto-char (point-min))
+    (let (headers)
+      (while (not (eobp))
+       (push (nnheader-parse-nov) headers)
+       (forward-line 1))
+      (nreverse headers))))
+
+(defun nnheader-write-overview-file (file headers)
+  "Write HEADERS to FILE."
+  (with-temp-file file
+    (mapcar 'nnheader-insert-nov headers)))
+
+(defun nnheader-insert-header (header)
   (insert
-   "\t"
-   (or (mail-header-subject header) "(none)") "\t"
-   (or (mail-header-from header) "(nobody)") "\t"
-   (or (mail-header-date header) "") "\t"
-   (or (mail-header-id header)
-       (nnmail-message-id))
-   "\t"
-   (or (mail-header-references header) "") "\t")
-  (princ (or (mail-header-chars header) 0) (current-buffer))
-  (insert "\t")
+   "Subject: " (or (mail-header-subject header) "(none)") "\n"
+   "From: " (or (mail-header-from header) "(nobody)") "\n"
+   "Date: " (or (mail-header-date header) "") "\n"
+   "Message-ID: " (or (mail-header-id header) (nnmail-message-id)) "\n"
+   "References: " (or (mail-header-references header) "") "\n"
+   "Lines: ")
   (princ (or (mail-header-lines header) 0) (current-buffer))
-  (insert "\t")
-  (when (mail-header-xref header)
-    (insert "Xref: " (mail-header-xref header) "\t"))
-  (insert "\n"))
+  (insert "\n\n"))
 
 (defun nnheader-insert-article-line (article)
   (goto-char (point-min))
@@ -345,7 +905,7 @@ the line could be found."
        (prev (point-min))
        num found)
     (while (not found)
-      (goto-char (/ (+ max min) 2))
+      (goto-char (+ min (/ (- max min) 2)))
       (beginning-of-line)
       (if (or (= (point) prev)
              (eobp))
@@ -381,13 +941,196 @@ the line could be found."
     (beginning-of-line)
     (eq num article)))
 
+(defun nnheader-retrieve-headers-from-directory* (articles
+                                                 directory dependencies
+                                                 &optional
+                                                 fetch-old force-new large
+                                                 backend)
+  (with-temp-buffer
+    (let* ((file nil)
+          (number (length articles))
+          (count 0)
+          (file-name-coding-system 'binary)
+          (pathname-coding-system 'binary)
+          (case-fold-search t)
+          (cur (current-buffer))
+          article
+          headers header id end ref in-reply-to lines chars ctype)
+      ;; We don't support fetching by Message-ID.
+      (if (stringp (car articles))
+         'headers
+       (while articles
+         (when (and (file-exists-p
+                     (setq file (expand-file-name
+                                 (int-to-string
+                                  (setq article (pop articles)))
+                                 directory)))
+                    (not (file-directory-p file)))
+           (erase-buffer)
+           (nnheader-insert-head file)
+           (save-restriction
+             (std11-narrow-to-header)
+             (setq
+              header
+              (make-full-mail-header
+               ;; Number.
+               article
+               ;; Subject.
+               (or (std11-fetch-field "Subject")
+                   "(none)")
+               ;; From.
+               (or (std11-fetch-field "From")
+                   "(nobody)")
+               ;; Date.
+               (or (std11-fetch-field "Date")
+                   "")
+               ;; Message-ID.
+               (progn
+                 (goto-char (point-min))
+                 (setq id (if (re-search-forward
+                               "^Message-ID: *\\(<[^\n\t> ]+>\\)" nil t)
+                              ;; We do it this way to make sure the Message-ID
+                              ;; is (somewhat) syntactically valid.
+                              (buffer-substring (match-beginning 1)
+                                                (match-end 1))
+                            ;; If there was no message-id, we just fake one
+                            ;; to make subsequent routines simpler.
+                            (nnheader-generate-fake-message-id))))
+               ;; References.
+               (progn
+                 (goto-char (point-min))
+                 (if (search-forward "\nReferences: " nil t)
+                     (progn
+                       (setq end (point))
+                       (prog1
+                           (buffer-substring (match-end 0) (std11-field-end))
+                         (setq ref
+                               (buffer-substring
+                                (progn
+                                  ;; (end-of-line)
+                                  (search-backward ">" end t)
+                                  (1+ (point)))
+                                (progn
+                                  (search-backward "<" end t)
+                                  (point))))))
+                   ;; Get the references from the in-reply-to header if there
+                   ;; were no references and the in-reply-to header looks
+                   ;; promising.
+                   (if (and (search-forward "\nIn-Reply-To: " nil t)
+                            (setq in-reply-to
+                                  (buffer-substring (match-end 0)
+                                                    (std11-field-end)))
+                            (string-match "<[^>]+>" in-reply-to))
+                       (let (ref2)
+                         (setq ref (substring in-reply-to (match-beginning 0)
+                                              (match-end 0)))
+                         (while (string-match "<[^>]+>"
+                                              in-reply-to (match-end 0))
+                           (setq ref2
+                                 (substring in-reply-to (match-beginning 0)
+                                            (match-end 0)))
+                           (when (> (length ref2) (length ref))
+                             (setq ref ref2)))
+                         ref)
+                     (setq ref nil))))
+               ;; Chars.
+               (progn
+                 (goto-char (point-min))
+                 (if (search-forward "\nChars: " nil t)
+                     (if (numberp (setq chars (ignore-errors (read cur))))
+                         chars 0)
+                   0))
+               ;; Lines.
+               (progn
+                 (goto-char (point-min))
+                 (if (search-forward "\nLines: " nil t)
+                     (if (numberp (setq lines (ignore-errors (read cur))))
+                         lines 0)
+                   0))
+               ;; Xref.
+               (std11-fetch-field "Xref")
+               ))
+             (goto-char (point-min))
+             (if (setq ctype (std11-fetch-field "Content-Type"))
+                 (mime-entity-set-content-type-internal
+                  header (mime-parse-Content-Type ctype)))
+             )
+           (when (setq header
+                       (gnus-dependencies-add-header
+                        header dependencies force-new))
+             (push header headers))
+           )
+         (setq count (1+ count))
+
+         (and large
+              (zerop (% count 20))
+              (nnheader-message 5 "%s: Receiving headers... %d%%"
+                                backend
+                                (/ (* count 100) number))))
+
+       (when large
+         (nnheader-message 5 "%s: Receiving headers...done" backend))
+
+       headers))))
+
+(defun nnheader-retrieve-headers-from-directory (articles
+                                                directory dependencies
+                                                &optional
+                                                fetch-old force-new large
+                                                backend)
+  (cons 'header
+       (nreverse (nnheader-retrieve-headers-from-directory*
+                  articles directory dependencies
+                  fetch-old force-new large backend))))
+
+(defun nnheader-get-newsgroup-headers-xover* (sequence
+                                             &optional
+                                             force-new dependencies
+                                             group)
+  "Parse the news overview data in the server buffer, and return a
+list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
+  ;; Get the Xref when the users reads the articles since most/some
+  ;; NNTP servers do not include Xrefs when using XOVER.
+  ;; (setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
+  (let ((cur nntp-server-buffer)
+       number headers header)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      ;; Allow the user to mangle the headers before parsing them.
+      (gnus-run-hooks 'gnus-parse-headers-hook)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (condition-case ()
+           (while (and sequence (not (eobp)))
+             (setq number (read cur))
+             (while (and sequence
+                         (< (car sequence) number))
+               (setq sequence (cdr sequence)))
+             (and sequence
+                  (eq number (car sequence))
+                  (progn
+                    (setq sequence (cdr sequence))
+                    (setq header (inline
+                                   (gnus-nov-parse-line
+                                    number dependencies force-new))))
+                  (push header headers))
+             (forward-line 1))
+         (error
+          (gnus-error 4 "Strange nov line (%d)"
+                      (count-lines (point-min) (point)))))
+       (forward-line 1))
+      ;; A common bug in inn is that if you have posted an article and
+      ;; then retrieves the active file, it will answer correctly --
+      ;; the new article is included.  However, a NOV entry for the
+      ;; article may not have been generated yet, so this may fail.
+      ;; We work around this problem by retrieving the last few
+      ;; headers using HEAD.
+      headers)))
+
 ;; Various cruft the backends and Gnus need to communicate.
 
 (defvar nntp-server-buffer nil)
-(defvar gnus-verbose-backends 7
-  "*A number that says how talkative the Gnus backends should be.")
-(defvar gnus-nov-is-evil nil
-  "If non-nil, Gnus backends will never output headers in the NOV format.")
+(defvar nntp-process-response nil)
 (defvar news-reply-yank-from nil)
 (defvar news-reply-yank-message-id nil)
 
@@ -399,10 +1142,10 @@ the line could be found."
     (unless (gnus-buffer-live-p nntp-server-buffer)
       (setq nntp-server-buffer (get-buffer-create " *nntpd*")))
     (set-buffer nntp-server-buffer)
-    (buffer-disable-undo (current-buffer))
     (erase-buffer)
     (kill-all-local-variables)
     (setq case-fold-search t)          ;Should ignore case.
+    (set (make-local-variable 'nntp-process-response) nil)
     t))
 
 ;;; Various functions the backends use.
@@ -445,7 +1188,7 @@ the line could be found."
       nil
     (narrow-to-region (point-min) (1- (point)))
     (goto-char (point-min))
-    (while (looking-at "[A-Z][^ \t]+:.*\n\\([ \t].*\n\\)*\\|From .*\n")
+    (while (looking-at "[a-zA-Z][^ \t]+:.*\n\\([ \t].*\n\\)*\\|From .*\n")
       (goto-char (match-end 0)))
     (prog1
        (eobp)
@@ -454,9 +1197,10 @@ the line could be found."
 (defun nnheader-insert-references (references message-id)
   "Insert a References header based on REFERENCES and MESSAGE-ID."
   (if (and (not references) (not message-id))
-      ()                               ; This is illegal, but not all articles have Message-IDs.
+      ;; This is invalid, but not all articles have Message-IDs.
+      ()
     (mail-position-on-field "References")
-    (let ((begin (save-excursion (beginning-of-line) (point)))
+    (let ((begin (gnus-point-at-bol))
          (fill-column 78)
          (fill-prefix "\t"))
       (when references
@@ -490,61 +1234,21 @@ the line could be found."
      (point-max)))
   (goto-char (point-min)))
 
+(defun nnheader-remove-body ()
+  "Remove the body from an article in this current buffer."
+  (goto-char (point-min))
+  (when (re-search-forward "\n\r?\n" nil t)
+    (delete-region (point) (point-max))))
+
 (defun nnheader-set-temp-buffer (name &optional noerase)
   "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
   (set-buffer (get-buffer-create name))
-  (buffer-disable-undo (current-buffer))
+  (buffer-disable-undo)
   (unless noerase
     (erase-buffer))
   (current-buffer))
 
-(defmacro nnheader-temp-write (file &rest forms)
-  "Create a new buffer, evaluate FORMS there, and write the buffer to FILE.
-Return the value of FORMS.
-If FILE is nil, just evaluate FORMS and don't save anything.
-If FILE is t, return the buffer contents as a string."
-  (let ((temp-file (make-symbol "temp-file"))
-       (temp-buffer (make-symbol "temp-buffer"))
-       (temp-results (make-symbol "temp-results")))
-    `(save-excursion
-       (let* ((,temp-file ,file)
-             (default-major-mode 'fundamental-mode)
-             (,temp-buffer
-              (set-buffer
-               (get-buffer-create
-                (generate-new-buffer-name " *nnheader temp*"))))
-             ,temp-results)
-        (unwind-protect
-            (progn
-              (setq ,temp-results (progn ,@forms))
-              (cond
-               ;; Don't save anything.
-               ((null ,temp-file)
-                ,temp-results)
-               ;; Return the buffer contents.
-               ((eq ,temp-file t)
-                (set-buffer ,temp-buffer)
-                (buffer-string))
-               ;; Save a file.
-               (t
-                (set-buffer ,temp-buffer)
-                ;; Make sure the directory where this file is
-                ;; to be saved exists.
-                (when (not (file-directory-p
-                            (file-name-directory ,temp-file)))
-                  (make-directory (file-name-directory ,temp-file) t))
-                ;; Save the file.
-                (write-region (point-min) (point-max)
-                              ,temp-file nil 'nomesg)
-                ,temp-results)))
-          ;; Kill the buffer.
-          (when (buffer-name ,temp-buffer)
-            (kill-buffer ,temp-buffer)))))))
-
-(put 'nnheader-temp-write 'lisp-indent-function 1)
-(put 'nnheader-temp-write 'edebug-form-spec '(form body))
-
-(defvar jka-compr-compression-info-list)
+(eval-when-compile (defvar jka-compr-compression-info-list))
 (defvar nnheader-numerical-files
   (if (boundp 'jka-compr-compression-info-list)
       (concat "\\([0-9]+\\)\\("
@@ -558,20 +1262,26 @@ If FILE is t, return the buffer contents as a string."
   "Regexp that matches numerical file names.")
 
 (defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files)
-  "Regexp that matches numerical full file paths.")
+  "Regexp that matches numerical full file names.")
 
 (defsubst nnheader-file-to-number (file)
-  "Take a file name and return the article number."
-  (if (not (boundp 'jka-compr-compression-info-list))
+  "Take a FILE name and return the article number."
+  (if (string= nnheader-numerical-short-files "^[0-9]+$")
       (string-to-int file)
     (string-match nnheader-numerical-short-files file)
     (string-to-int (match-string 0 file))))
 
+(defvar nnheader-directory-files-is-safe
+  (or (eq system-type 'windows-nt)
+      (and (not (featurep 'xemacs))
+          (> emacs-major-version 20)))
+  "If non-nil, Gnus believes `directory-files' is safe.
+It has been reported numerous times that `directory-files' fails with
+an alarming frequency on NFS mounted file systems. If it is nil,
+`nnheader-directory-files-safe' is used.")
+
 (defun nnheader-directory-files-safe (&rest args)
-  ;; It has been reported numerous times that `directory-files'
-  ;; fails with an alarming frequency on NFS mounted file systems.
-  ;; This function executes that function twice and returns
-  ;; the longest result.
+  "Execute `directory-files' twice and returns the longer result."
   (let ((first (apply 'directory-files args))
        (second (apply 'directory-files args)))
     (if (> (length first) (length second))
@@ -579,36 +1289,66 @@ If FILE is t, return the buffer contents as a string."
       second)))
 
 (defun nnheader-directory-articles (dir)
-  "Return a list of all article files in a directory."
+  "Return a list of all article files in directory DIR."
   (mapcar 'nnheader-file-to-number
-         (nnheader-directory-files-safe
-          dir nil nnheader-numerical-short-files t)))
+         (if nnheader-directory-files-is-safe
+             (directory-files
+              dir nil nnheader-numerical-short-files t)
+           (nnheader-directory-files-safe
+            dir nil nnheader-numerical-short-files t))))
 
 (defun nnheader-article-to-file-alist (dir)
   "Return an alist of article/file pairs in DIR."
   (mapcar (lambda (file) (cons (nnheader-file-to-number file) file))
-         (nnheader-directory-files-safe
-          dir nil nnheader-numerical-short-files t)))
+         (if nnheader-directory-files-is-safe
+             (directory-files
+              dir nil nnheader-numerical-short-files t)
+           (nnheader-directory-files-safe
+            dir nil nnheader-numerical-short-files t))))
 
 (defun nnheader-fold-continuation-lines ()
   "Fold continuation lines in the current buffer."
   (nnheader-replace-regexp "\\(\r?\n[ \t]+\\)+" " "))
 
-(defun nnheader-translate-file-chars (file)
+(defun nnheader-translate-file-chars (file &optional full)
+  "Translate FILE into something that can be a file name.
+If FULL, translate everything."
   (if (null nnheader-file-name-translation-alist)
       ;; No translation is necessary.
       file
-    ;; We translate -- but only the file name.  We leave the directory
-    ;; alone.
     (let* ((i 0)
           trans leaf path len)
-      (if (string-match "/[^/]+\\'" file)
-         ;; This is needed on NT's and stuff.
-         (setq leaf (substring file (1+ (match-beginning 0)))
-               path (substring file 0 (1+ (match-beginning 0))))
-       ;; Fall back on this.
-       (setq leaf (file-name-nondirectory file)
-             path (file-name-directory file)))
+      (if full
+         ;; Do complete translation.
+         (setq leaf (copy-sequence file)
+               path ""
+               i (if (and (< 1 (length leaf)) (eq ?: (aref leaf 1)))
+                     2 0))
+       ;; We translate -- but only the file name.  We leave the directory
+       ;; alone.
+       (if (and (featurep 'xemacs)
+                (memq system-type '(cygwin32 win32 w32 mswindows windows-nt
+                                             cygwin)))
+           ;; This is needed on NT and stuff, because
+           ;; file-name-nondirectory is not enough to split
+           ;; file names, containing ':', e.g.
+           ;; "d:\\Work\\News\\nntp+news.fido7.ru:fido7.ru.gnu.SCORE"
+           ;;
+           ;; we are trying to correctly split such names:
+           ;; "d:file.name" -> "a:" "file.name"
+           ;; "aaa:bbb.ccc" -> "" "aaa:bbb.ccc"
+           ;; "d:aaa\\bbb:ccc"   -> "d:aaa\\" "bbb:ccc"
+           ;; etc.
+           ;; to translate then only the file name part.
+           (progn
+             (setq leaf file
+                   path "")
+             (if (string-match "\\(^\\w:\\|[/\\]\\)\\([^/\\]+\\)$" file)
+                 (setq leaf (substring file (match-beginning 2))
+                       path (substring file 0 (match-beginning 2)))))
+         ;; Emacs DTRT, says andrewi.
+         (setq leaf (file-name-nondirectory file)
+               path (file-name-directory file))))
       (setq len (length leaf))
       (while (< i len)
        (when (setq trans (cdr (assq (aref leaf i)
@@ -629,9 +1369,9 @@ The first string in ARGS can be a format string."
 (defun nnheader-get-report (backend)
   "Get the most recent report from BACKEND."
   (condition-case ()
-      (message "%s" (symbol-value (intern (format "%s-status-string"
-                                                 backend))))
-    (error (message ""))))
+      (nnheader-message 5 "%s" (symbol-value (intern (format "%s-status-string"
+                                                            backend))))
+    (error (nnheader-message 5 ""))))
 
 (defun nnheader-insert (format &rest args)
   "Clear the communication buffer and insert FORMAT and ARGS into the buffer.
@@ -645,15 +1385,33 @@ without formatting."
       (apply 'insert format args))
     t))
 
-(defun nnheader-replace-chars-in-string (string from to)
+(static-if (fboundp 'subst-char-in-string)
+    (defsubst nnheader-replace-chars-in-string (string from to)
+      (subst-char-in-string from to string))
+  (defun nnheader-replace-chars-in-string (string from to)
+    "Replace characters in STRING from FROM to TO."
+    (let ((string (substring string 0))        ;Copy string.
+         (len (length string))
+         (idx 0))
+      ;; Replace all occurrences of FROM with TO.
+      (while (< idx len)
+       (when (= (aref string idx) from)
+         (aset string idx to))
+       (setq idx (1+ idx)))
+      string)))
+
+(defun nnheader-replace-duplicate-chars-in-string (string from to)
   "Replace characters in STRING from FROM to TO."
   (let ((string (substring string 0))  ;Copy string.
        (len (length string))
-       (idx 0))
+       (idx 0) prev i)
     ;; Replace all occurrences of FROM with TO.
     (while (< idx len)
-      (when (= (aref string idx) from)
+      (setq i (aref string idx))
+      (when (and (eq prev from) (= i from))
+       (aset string (1- idx) to)
        (aset string idx to))
+      (setq prev i)
       (setq idx (1+ idx)))
     string))
 
@@ -668,7 +1426,7 @@ without formatting."
                     (expand-file-name
                      (file-name-as-directory top))))
        (error "")))
-   ?/ ?.))
+   nnheader-directory-separator-character ?.))
 
 (defun nnheader-message (level &rest args)
   "Message if the Gnus backends are talkative."
@@ -682,51 +1440,48 @@ without formatting."
   (or (not (numberp gnus-verbose-backends))
       (<= level gnus-verbose-backends)))
 
-(defvar nnheader-pathname-coding-system 'iso-8859-1
-  "*Coding system for pathname.")
+(defvar nnheader-pathname-coding-system 'binary
+  "*Coding system for file name.")
 
 (defun nnheader-group-pathname (group dir &optional file)
-  "Make pathname for GROUP."
+  "Make file name for GROUP."
   (concat
    (let ((dir (file-name-as-directory (expand-file-name dir))))
      ;; If this directory exists, we use it directly.
-     (if (file-directory-p (concat dir group))
-        (concat dir group "/")
-       ;; If not, we translate dots into slashes.
-       (concat dir
-              (gnus-encode-coding-string
-               (nnheader-replace-chars-in-string group ?. ?/)
-               nnheader-pathname-coding-system)
-              "/")))
+     (file-name-as-directory
+      (if (file-directory-p (concat dir group))
+         (expand-file-name group dir)
+       ;; If not, we translate dots into slashes.
+       (expand-file-name (encode-coding-string
+                          (nnheader-replace-chars-in-string group ?. ?/)
+                          nnheader-pathname-coding-system)
+                         dir))))
    (cond ((null file) "")
         ((numberp file) (int-to-string file))
         (t file))))
 
-(defun nnheader-functionp (form)
-  "Return non-nil if FORM is funcallable."
-  (or (and (symbolp form) (fboundp form))
-      (and (listp form) (eq (car form) 'lambda))))
-
 (defun nnheader-concat (dir &rest files)
-  "Concat DIR as directory to FILE."
+  "Concat DIR as directory to FILES."
   (apply 'concat (file-name-as-directory dir) files))
 
 (defun nnheader-ms-strip-cr ()
   "Strip ^M from the end of all lines."
   (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "\r$" nil t)
-      (delete-backward-char 1))))
+    (nnheader-remove-cr-followed-by-lf)))
 
 (defun nnheader-file-size (file)
   "Return the file size of FILE or 0."
   (or (nth 7 (file-attributes file)) 0))
 
-(defun nnheader-find-etc-directory (package &optional file)
-  "Go through the path and find the \".../etc/PACKAGE\" directory.
-If FILE, find the \".../etc/PACKAGE\" file instead."
+(defun nnheader-find-etc-directory (package &optional file first)
+  "Go through `load-path' and find the \"../etc/PACKAGE\" directory.
+This function will look in the parent directory of each `load-path'
+entry, and look for the \"etc\" directory there.
+If FILE, find the \".../etc/PACKAGE\" file instead.
+If FIRST is non-nil, return the directory or the file found at the
+first.  Otherwise, find the newest one, though it may take a time."
   (let ((path load-path)
-       dir result)
+       dir results)
     ;; We try to find the dir by looking at the load path,
     ;; stripping away the last component and adding "etc/".
     (while path
@@ -738,13 +1493,18 @@ If FILE, find the \".../etc/PACKAGE\" file instead."
                           "etc/" package
                           (if file "" "/"))))
               (or file (file-directory-p dir)))
-         (setq result dir
-               path nil)
+         (progn
+           (or (member dir results)
+               (push dir results))
+           (setq path (if first nil (cdr path))))
        (setq path (cdr path))))
-    result))
+    (if (or first (not (cdr results)))
+       (car results)
+      (car (sort results 'file-newer-than-file-p)))))
 
-(defvar ange-ftp-path-format)
-(defvar efs-path-regexp)
+(eval-when-compile
+  (defvar ange-ftp-path-format)
+  (defvar efs-path-regexp))
 (defun nnheader-re-read-dir (path)
   "Re-read directory PATH if PATH is on a remote system."
   (if (and (fboundp 'efs-re-read-dir) (boundp 'efs-path-regexp))
@@ -766,18 +1526,43 @@ find-file-hooks, etc.
   (let ((format-alist nil)
        (auto-mode-alist (nnheader-auto-mode-alist))
        (default-major-mode 'fundamental-mode)
-        (after-insert-file-functions nil)
-       (coding-system-for-read nnheader-file-coding-system))
-    (insert-file-contents filename visit beg end replace)))
+       (enable-local-variables nil)
+       (after-insert-file-functions nil)
+       (enable-local-eval nil)
+       (find-file-hooks nil))
+    (insert-file-contents-as-coding-system
+     nnheader-file-coding-system filename visit beg end replace)))
+
+(defun nnheader-insert-nov-file (file first)
+  (let ((size (nth 7 (file-attributes file)))
+       (cutoff (* 32 1024)))
+    (when size
+      (if (< size cutoff)
+          ;; If the file is small, we just load it.
+          (nnheader-insert-file-contents file)
+        ;; We start on the assumption that FIRST is pretty recent.  If
+        ;; not, we just insert the rest of the file as well.
+        (let (current)
+          (nnheader-insert-file-contents file nil (- size cutoff) size)
+          (goto-char (point-min))
+          (delete-region (point) (or (search-forward "\n" nil 'move) (point)))
+          (setq current (ignore-errors (read (current-buffer))))
+          (if (and (numberp current)
+                   (< current first))
+              t
+            (delete-region (point-min) (point-max))
+            (nnheader-insert-file-contents file)))))))
 
 (defun nnheader-find-file-noselect (&rest args)
   (let ((format-alist nil)
        (auto-mode-alist (nnheader-auto-mode-alist))
        (default-major-mode 'fundamental-mode)
        (enable-local-variables nil)
-        (after-insert-file-functions nil)
-       (coding-system-for-read nnheader-file-coding-system))
-    (apply 'find-file-noselect args)))
+       (after-insert-file-functions nil)
+       (enable-local-eval nil)
+       (find-file-hooks nil))
+    (apply 'find-file-noselect-as-coding-system
+          nnheader-file-coding-system args)))
 
 (defun nnheader-auto-mode-alist ()
   "Return an `auto-mode-alist' with only the .gz (etc) thingies."
@@ -813,8 +1598,6 @@ find-file-hooks, etc.
   `(let ((new (generate-new-buffer " *nnheader replace*"))
         (cur (current-buffer))
         (start (point-min)))
-     (set-buffer new)
-     (buffer-disable-undo (current-buffer))
      (set-buffer cur)
      (goto-char (point-min))
      (while (,(if regexp 're-search-forward 'search-forward)
@@ -832,22 +1615,55 @@ find-file-hooks, etc.
      (set-buffer cur)))
 
 (defun nnheader-replace-string (from to)
-  "Do a fast replacement of FROM to TO from point to point-max."
+  "Do a fast replacement of FROM to TO from point to `point-max'."
   (nnheader-skeleton-replace from to))
 
 (defun nnheader-replace-regexp (from to)
-  "Do a fast regexp replacement of FROM to TO from point to point-max."
+  "Do a fast regexp replacement of FROM to TO from point to `point-max'."
   (nnheader-skeleton-replace from to t))
 
 (defun nnheader-strip-cr ()
   "Strip all \r's from the current buffer."
   (nnheader-skeleton-replace "\r"))
 
-(fset 'nnheader-run-at-time 'run-at-time)
-(fset 'nnheader-cancel-timer 'cancel-timer)
-(fset 'nnheader-cancel-function-timers 'cancel-function-timers)
-
-(when (string-match "XEmacs\\|Lucid" emacs-version)
+(defalias 'nnheader-run-at-time 'run-at-time)
+(defalias 'nnheader-cancel-timer 'cancel-timer)
+(defalias 'nnheader-cancel-function-timers 'cancel-function-timers)
+(defalias 'nnheader-string-as-multibyte 'string-as-multibyte)
+
+(defun nnheader-Y-or-n-p (prompt)
+  "Ask user a \"Y/n\" question. Return t if answer is neither \"n\", \"N\" nor \"C-g\"."
+  (let ((cursor-in-echo-area t)
+       (echo-keystrokes 0)
+       (inhibit-quit t)
+       ans)
+    (let (message-log-max)
+      (while (not (memq ans '(?\  ?N ?Y ?\C-g ?\e ?\n ?\r ?n ?y)))
+       (message "%s(Y/n) " prompt)
+       (setq ans (read-char-exclusive))))
+    (if (memq ans '(?\C-g ?N ?n))
+       (progn
+         (message "%s(Y/n) No" prompt)
+         nil)
+      (message "%s(Y/n) Yes" prompt)
+      t)))
+
+(defun-maybe shell-command-to-string (command)
+  "Execute shell command COMMAND and return its output as a string."
+  (with-output-to-string
+    (with-current-buffer
+       standard-output
+      (call-process shell-file-name nil t nil shell-command-switch command))))
+
+(defun nnheader-accept-process-output (process)
+  (accept-process-output
+   process
+   (truncate nnheader-read-timeout)
+   (truncate (* (- nnheader-read-timeout
+                  (truncate nnheader-read-timeout))
+               1000))))
+
+(when (featurep 'xemacs)
   (require 'nnheaderxm))
 
 (run-hooks 'nnheader-load-hook)
index 869ed69..af0979c 100644 (file)
@@ -1,7 +1,10 @@
 ;;; nnheaderxm.el --- making Gnus backends work under XEmacs
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;      Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Katsumi Yamaoka  <yamaoka@jpl.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
-(defun nnheader-xmas-run-at-time (time repeat function &rest args)
-  (start-itimer
-   "nnheader-run-at-time"
-   `(lambda ()
-      (,function ,@args))
-   time repeat))
+(if (condition-case nil
+       (progn
+         (unless (or itimer-process itimer-timer)
+           (itimer-driver-start))
+         ;; Check whether there is a bug to which the difference of
+         ;; the present time and the time when the itimer driver was
+         ;; woken up is subtracted from the initial itimer value.
+         (let* ((inhibit-quit t)
+                (ctime (current-time))
+                (itimer-timer-last-wakeup
+                 (prog1
+                     ctime
+                   (setcar ctime (1- (car ctime)))))
+                (itimer-list nil)
+                (itimer (start-itimer "nnheader-run-at-time" 'ignore 5)))
+           (sleep-for 0.1) ;; Accept the timeout interrupt.
+           (prog1
+               (> (itimer-value itimer) 0)
+             (delete-itimer itimer))))
+      (error nil))
+    (defun nnheader-xmas-run-at-time (time repeat function &rest args)
+      "Emulating function run as `run-at-time'.
+TIME should be nil meaning now, or a number of seconds from now.
+Return an itimer object which can be used in either `delete-itimer'
+or `cancel-timer'."
+      (apply #'start-itimer "nnheader-run-at-time"
+            function (if time (max time 1e-9) 1e-9)
+            repeat nil t args))
+  (defun nnheader-xmas-run-at-time (time repeat function &rest args)
+    "Emulating function run as `run-at-time' in the right way.
+TIME should be nil meaning now, or a number of seconds from now.
+Return an itimer object which can be used in either `delete-itimer'
+or `cancel-timer'."
+    (let ((itimers (list nil)))
+      (setcar
+       itimers
+       (apply #'start-itimer "nnheader-run-at-time"
+             (lambda (itimers repeat function &rest args)
+               (let ((itimer (car itimers)))
+                 (if repeat
+                     (progn
+                       (set-itimer-function
+                        itimer
+                        (lambda (itimer repeat function &rest args)
+                          (set-itimer-restart itimer repeat)
+                          (set-itimer-function itimer function)
+                          (set-itimer-function-arguments itimer args)
+                          (apply function args)))
+                       (set-itimer-function-arguments
+                        itimer
+                        (append (list itimer repeat function) args)))
+                   (set-itimer-function
+                    itimer
+                    (lambda (itimer function &rest args)
+                      (delete-itimer itimer)
+                      (apply function args)))
+                   (set-itimer-function-arguments
+                    itimer
+                    (append (list itimer function) args)))))
+             1e-9 (if time (max time 1e-9) 1e-9)
+             nil t itimers repeat function args)))))
+
+(defun nnheader-xmas-Y-or-n-p (prompt)
+  "Ask user a \"Y/n\" question. Return t if answer is neither \"n\", \"N\" nor \"C-g\"."
+  (if (should-use-dialog-box-p)
+      (yes-or-no-p-dialog-box prompt)
+    (let ((cursor-in-echo-area t)
+         (echo-keystrokes 0)
+         (inhibit-quit t)
+         event)
+      (message "%s(Y/n) " prompt)
+      (while (or (not (key-press-event-p (setq event (next-command-event))))
+                (not (or (eq (event-key event) 'escape)
+                         (memq (event-to-character event)
+                               '(?\  ?N ?Y ?\C-g ?\e ?\n ?\r ?n ?y))))))
+      (if (memq (event-key event) '(?\C-g ?N ?n))
+         (progn
+           (message "%s(Y/n) No" prompt)
+           nil)
+       (message "%s(Y/n) Yes" prompt)
+       t))))
 
-(fset 'nnheader-run-at-time 'nnheader-xmas-run-at-time)
-(fset 'nnheader-cancel-timer 'delete-itimer)
-(fset 'nnheader-cancel-function-timers 'ignore)
+(defalias 'nnheader-run-at-time 'nnheader-xmas-run-at-time)
+(defalias 'nnheader-cancel-timer 'delete-itimer)
+(defalias 'nnheader-cancel-function-timers 'ignore)
+(defalias 'nnheader-string-as-multibyte 'identity)
+(defalias 'nnheader-Y-or-n-p 'nnheader-xmas-Y-or-n-p)
 
 (provide 'nnheaderxm)
 
-;;; nnheaderxm.el ends here.
+;;; nnheaderxm.el ends here
diff --git a/lisp/nnimap.el b/lisp/nnimap.el
new file mode 100644 (file)
index 0000000..7001a0d
--- /dev/null
@@ -0,0 +1,1671 @@
+;;; nnimap.el --- imap backend for Gnus
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <jas@pdc.kth.se>
+;;         Jim Radford <radford@robby.caltech.edu>
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Todo, major things:
+;;
+;;   o Fix Gnus to view correct number of unread/total articles in group buffer
+;;   o Fix Gnus to handle leading '.' in group names (fixed?)
+;;   o Finish disconnected mode (moving articles between mailboxes unplugged)
+;;   o Sieve
+;;   o MIME (partial article fetches)
+;;   o Split to other backends, different split rules for different
+;;     servers/inboxes
+;;
+;; Todo, minor things:
+;;
+;;   o Don't require half of Gnus -- backends should be standalone
+;;   o Verify that we don't use IMAP4rev1 specific things (RFC2060 App B)
+;;   o Dont uid fetch 1,* in nnimap-retrive-groups (slow)
+;;   o Split up big fetches (1,* header especially) in smaller chunks
+;;   o What do I do with gnus-newsgroup-*?
+;;   o Tell Gnus about new groups (how can we tell?)
+;;   o Respooling (fix Gnus?) (unnecessary?)
+;;   o Add support for the following: (if applicable)
+;;       request-list-newsgroups, request-regenerate
+;;       list-active-group,
+;;       request-associate-buffer, request-restore-buffer,
+;;   o Do The Right Thing when UIDVALIDITY changes (what's the right thing?)
+;;   o Support RFC2221 (Login referrals)
+;;   o IMAP2BIS compatibility? (RFC2061)
+;;   o ACAP stuff (perhaps a different project, would be nice to ACAPify
+;;     .newsrc.eld)
+;;   o What about Gnus's article editing, can we support it?  NO!
+;;   o Use \Draft to support the draft group??
+;;   o Duplicate suppression
+;;   o Rewrite UID SEARCH UID X as UID FETCH X (UID) for those with slow servers
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+(require 'imap)
+
+(require 'nnoo)
+(require 'nnmail)
+(require 'nnheader)
+(require 'gnus)
+(require 'gnus-range)
+(require 'gnus-start)
+(require 'gnus-int)
+
+(eval-when-compile (require 'cl))
+
+(nnoo-declare nnimap)
+
+(defconst nnimap-version "nnimap 1.0")
+
+(defgroup nnimap nil
+  "Reading IMAP mail with Gnus."
+  :group 'gnus)
+
+(defvoo nnimap-address nil
+  "Address of physical IMAP server.  If nil, use the virtual server's name.")
+
+(defvoo nnimap-server-port nil
+  "Port number on physical IMAP server.
+If nil, defaults to 993 for TLS/SSL connections and 143 otherwise.")
+
+;; Splitting variables
+
+(defcustom nnimap-split-crosspost t
+  "If non-nil, do crossposting if several split methods match the mail.
+If nil, the first match found will be used."
+  :group 'nnimap
+  :type 'boolean)
+
+(defcustom nnimap-split-inbox nil
+  "Name of mailbox to split mail from.
+
+Mail is read from this mailbox and split according to rules in
+`nnimap-split-rule'.
+
+This can be a string or a list of strings."
+  :group 'nnimap
+  :type '(choice (string)
+                (repeat string)))
+
+(define-widget 'nnimap-strict-function 'function
+  "This widget only matches values that are functionp.
+
+Warning: This means that a value that is the symbol of a not yet
+loaded function will not match.  Use with care."
+  :match 'nnimap-strict-function-match)
+
+(defun nnimap-strict-function-match (widget value)
+  "Ignoring WIDGET, match if VALUE is a function."
+  (functionp value))
+
+(defcustom nnimap-split-rule nil
+  "Mail will be split according to these rules.
+
+Mail is read from mailbox(es) specified in `nnimap-split-inbox'.
+
+If you'd like, for instance, one mail group for mail from the
+\"gnus-imap\" mailing list, one group for junk mail and leave
+everything else in the incoming mailbox, you could do something like
+this:
+
+\(setq nnimap-split-rule '((\"INBOX.gnus-imap\"   \"From:.*gnus-imap\")
+                         (\"INBOX.junk\"        \"Subject:.*buy\")))
+
+As you can see, `nnimap-split-rule' is a list of lists, where the
+first element in each \"rule\" is the name of the IMAP mailbox (or the
+symbol `junk' if you want to remove the mail), and the second is a
+regexp that nnimap will try to match on the header to find a fit.
+
+The second element can also be a function.  In that case, it will be
+called narrowed to the headers with the first element of the rule as
+the argument.  It should return a non-nil value if it thinks that the
+mail belongs in that group.
+
+This variable can also have a function as its value, the function will
+be called with the headers narrowed and should return a group where it
+thinks the article should be splitted to.  See `nnimap-split-fancy'.
+
+To allow for different split rules on different virtual servers, and
+even different split rules in different inboxes on the same server,
+the syntax of this variable have been extended along the lines of:
+
+\(setq nnimap-split-rule
+      '((\"my1server\"    (\".*\"    ((\"ding\"    \"ding@gnus.org\")
+                                 (\"junk\"    \"From:.*Simon\")))
+       (\"my2server\"    (\"INBOX\" nnimap-split-fancy))
+       (\"my[34]server\" (\".*\"    ((\"private\" \"To:.*Simon\")
+                                 (\"junk\"    my-junk-func)))))
+
+The virtual server name is in fact a regexp, so that the same rules
+may apply to several servers.  In the example, the servers
+\"my3server\" and \"my4server\" both use the same rules.  Similarly,
+the inbox string is also a regexp.  The actual splitting rules are as
+before, either a function, or a list with group/regexp or
+group/function elements."
+  :group 'nnimap
+  :type '(choice :tag "Rule type"
+                (repeat :menu-tag "Single-server"
+                        :tag "Single-server list"
+                        (list (string :tag "Mailbox")
+                              (choice :tag "Predicate"
+                                      (regexp :tag "A regexp")
+                                      (nnimap-strict-function :tag "A function"))))
+                (choice :menu-tag "A function"
+                        :tag "A function"
+                        (function-item nnimap-split-fancy)
+                        (function-item nnmail-split-fancy)
+                        (nnimap-strict-function :tag "User-defined function"))
+                (repeat :menu-tag "Multi-server (extended)"
+                        :tag "Multi-server list"
+                        (list (regexp :tag "Server regexp")
+                              (list (regexp :tag "Incoming Mailbox regexp")
+                                    (repeat :tag "Rules for matching server(s) and mailbox(es)"
+                                            (list (string :tag "Destination mailbox")
+                                                  (choice :tag "Predicate"
+                                                          (regexp :tag "A Regexp")
+                                                          (nnimap-strict-function :tag "A Function")))))))))
+
+(defcustom nnimap-split-predicate "UNSEEN UNDELETED"
+  "The predicate used to find articles to split.
+If you use another IMAP client to peek on articles but always would
+like nnimap to split them once it's started, you could change this to
+\"UNDELETED\". Other available predicates are available in
+RFC2060 section 6.4.4."
+  :group 'nnimap
+  :type 'string)
+
+(defcustom nnimap-split-fancy nil
+  "Like the variable `nnmail-split-fancy'."
+  :group 'nnimap
+  :type 'sexp)
+
+(defvar nnimap-split-download-body-default nil
+  "Internal variable with default value for `nnimap-split-download-body'.")
+
+(defcustom nnimap-split-download-body 'default
+  "Whether to download entire articles during splitting.
+This is generally not required, and will slow things down considerably.
+You may need it if you want to use an advanced splitting function that
+analyses the body before splitting the article.
+If this variable is nil, bodies will not be downloaded; if this
+variable is the symbol `default' the default behaviour is
+used (which currently is nil, unless you use a statistical
+spam.el test); if this variable is another non-nil value bodies
+will be downloaded."
+  :group 'nnimap
+  :type '(choice (const :tag "Let system decide" deault)
+                boolean))
+
+;; Performance / bug workaround variables
+
+(defcustom nnimap-close-asynchronous t
+  "Close mailboxes asynchronously in `nnimap-close-group'.
+This means that errors cought by nnimap when closing the mailbox will
+not prevent Gnus from updating the group status, which may be harmful.
+However, it increases speed."
+  :type 'boolean
+  :group 'nnimap)
+
+(defcustom nnimap-dont-close t
+  "Never close mailboxes.
+This increases the speed of closing mailboxes (quiting group) but may
+decrease the speed of selecting another mailbox later.  Re-selecting
+the same mailbox will be faster though."
+  :type 'boolean
+  :group 'nnimap)
+
+(defcustom nnimap-retrieve-groups-asynchronous t
+  "Send asynchronous STATUS commands for each mailbox before checking mail.
+If you have mailboxes that rarely receives mail, this speeds up new
+mail checking.  It works by first sending STATUS commands for each
+mailbox, and then only checking groups which has a modified UIDNEXT
+more carefully for new mail.
+
+In summary, the default is O((1-p)*k+p*n) and changing it to nil makes
+it O(n).  If p is small, then the default is probably faster."
+  :type 'boolean
+  :group 'nnimap)
+
+(defvoo nnimap-need-unselect-to-notice-new-mail nil
+  "Unselect mailboxes before looking for new mail in them.
+Some servers seem to need this under some circumstances.")
+
+;; Authorization / Privacy variables
+
+(defvoo nnimap-auth-method nil
+  "Obsolete.")
+
+(defvoo nnimap-stream nil
+  "How nnimap will connect to the server.
+
+The default, nil, will try to use the \"best\" method the server can
+handle.
+
+Change this if
+
+1) you want to connect with TLS/SSL.  The TLS/SSL integration
+   with IMAP is suboptimal so you'll have to tell it
+   specifically.
+
+2) your server is more capable than your environment -- i.e. your
+   server accept Kerberos login's but you haven't installed the
+   `imtest' program or your machine isn't configured for Kerberos.
+
+Possible choices: gssapi, kerberos4, starttls, tls, ssl, network, shell.
+See also `imap-streams' and `imap-stream-alist'.")
+
+(defvoo nnimap-authenticator nil
+  "How nnimap authenticate itself to the server.
+
+The default, nil, will try to use the \"best\" method the server can
+handle.
+
+There is only one reason for fiddling with this variable, and that is
+if your server is more capable than your environment -- i.e. you
+connect to a server that accept Kerberos login's but you haven't
+installed the `imtest' program or your machine isn't configured for
+Kerberos.
+
+Possible choices: gssapi, kerberos4, digest-md5, cram-md5, login, anonymous.
+See also `imap-authenticators' and `imap-authenticator-alist'")
+
+(defvoo nnimap-directory (nnheader-concat gnus-directory "overview/")
+  "Directory to keep NOV cache files for nnimap groups.
+See also `nnimap-nov-file-name'.")
+
+(defvoo nnimap-nov-file-name "nnimap."
+  "NOV cache base filename.
+The group name and `nnimap-nov-file-name-suffix' will be appended.  A
+typical complete file name would be
+~/News/overview/nnimap.pdc.INBOX.ding.nov, or
+~/News/overview/nnimap/pdc/INBOX/ding/nov if
+`nnmail-use-long-file-names' is nil")
+
+(defvoo nnimap-nov-file-name-suffix ".novcache"
+  "Suffix for NOV cache base filename.")
+
+(defvoo nnimap-nov-is-evil gnus-agent
+  "If non-nil, never generate or use a local nov database for this backend.
+Using nov databases should speed up header fetching considerably.
+However, it will invoke a UID SEARCH UID command on the server, and
+some servers implement this command inefficiently by opening each and
+every message in the group, thus making it quite slow.
+Unlike other backends, you do not need to take special care if you
+flip this variable.")
+
+(defvoo nnimap-expunge-on-close 'always ; 'ask, 'never
+  "Whether to expunge a group when it is closed.
+When a IMAP group with articles marked for deletion is closed, this
+variable determine if nnimap should actually remove the articles or
+not.
+
+If always, nnimap always perform a expunge when closing the group.
+If never, nnimap never expunges articles marked for deletion.
+If ask, nnimap will ask you if you wish to expunge marked articles.
+
+When setting this variable to `never', you can only expunge articles
+by using `G x' (gnus-group-nnimap-expunge) from the Group buffer.")
+
+(defvoo nnimap-list-pattern "*"
+  "A string LIMIT or list of strings with mailbox wildcards used to limit available groups.
+See below for available wildcards.
+
+The LIMIT string can be a cons cell (REFERENCE . LIMIT), where
+REFERENCE will be passed as the first parameter to LIST/LSUB.  The
+semantics of this are server specific, on the University of Washington
+server you can specify a directory.
+
+Example:
+ '(\"INBOX\" \"mail/*\" (\"~friend/mail/\" . \"list/*\"))
+
+There are two wildcards * and %. * matches everything, % matches
+everything in the current hierarchy.")
+
+(defvoo nnimap-news-groups nil
+  "IMAP support a news-like mode, also known as bulletin board mode,
+where replies is sent via IMAP instead of SMTP.
+
+This variable should contain a regexp matching groups where you wish
+replies to be stored to the mailbox directly.
+
+Example:
+  '(\"^[^I][^N][^B][^O][^X].*$\")
+
+This will match all groups not beginning with \"INBOX\".
+
+Note that there is nothing technically different between mail-like and
+news-like mailboxes.  If you wish to have a group with todo items or
+similar which you wouldn't want to set up a mailing list for, you can
+use this to make replies go directly to the group.")
+
+(defvoo nnimap-expunge-search-string "UID %s NOT SINCE %s"
+  "IMAP search command to use for articles that are to be expired.
+The first %s is replaced by a UID set of articles to search on,
+and the second %s is replaced by a date criterium.
+
+One useful (and perhaps the only useful) value to change this to would
+be `UID %s NOT SENTSINCE %s' to make nnimap use the Date: header
+instead of the internal date of messages.  See section 6.4.4 of RFC
+2060 for more information on valid strings.")
+
+(defvoo nnimap-importantize-dormant t
+  "If non-nil, mark \"dormant\" articles as \"ticked\" for other IMAP clients.
+Note that within Gnus, dormant articles will still (only) be
+marked as ticked.  This is to make \"dormant\" articles stand out,
+just like \"ticked\" articles, in other IMAP clients.")
+
+(defvoo nnimap-server-address nil
+  "Obsolete.  Use `nnimap-address'.")
+
+(defcustom nnimap-authinfo-file "~/.authinfo"
+  "Authorization information for IMAP servers.  In .netrc format."
+  :type
+  '(choice file
+          (repeat :tag "Entries"
+                  :menu-tag "Inline"
+                  (list :format "%v"
+                        :value ("" ("login" . "") ("password" . ""))
+                        (string :tag "Host")
+                        (checklist :inline t
+                                   (cons :format "%v"
+                                         (const :format "" "login")
+                                         (string :format "Login: %v"))
+                                   (cons :format "%v"
+                                         (const :format "" "password")
+                                         (string :format "Password: %v")))))))
+
+(defcustom nnimap-prune-cache t
+  "If non-nil, nnimap check whether articles still exist on server before using data stored in NOV cache."
+  :type 'boolean)
+
+(defvar nnimap-request-list-method 'imap-mailbox-list
+  "Method to use to request a list of all folders from the server.
+If this is 'imap-mailbox-lsub, then use a server-side subscription list to
+restrict visible folders.")
+
+(defcustom nnimap-debug nil
+  "If non-nil, random debug spews are placed in *nnimap-debug* buffer."
+  :group 'nnimap
+  :type 'boolean)
+
+;; Internal variables:
+
+(defvar nnimap-debug-buffer "*nnimap-debug*")
+(defvar nnimap-mailbox-info (gnus-make-hashtable 997))
+(defvar nnimap-current-move-server nil)
+(defvar nnimap-current-move-group nil)
+(defvar nnimap-current-move-article nil)
+(defvar nnimap-length)
+(defvar nnimap-progress-chars '(?| ?/ ?- ?\\))
+(defvar nnimap-progress-how-often 20)
+(defvar nnimap-counter)
+(defvar nnimap-server-buffer-alist nil)        ;; Map server name to buffers.
+(defvar nnimap-current-server nil)     ;; Current server
+(defvar nnimap-server-buffer nil)      ;; Current servers' buffer
+
+\f
+
+(nnoo-define-basics nnimap)
+
+;; Utility functions:
+
+(defsubst nnimap-get-server-buffer (server)
+  "Return buffer for SERVER, if nil use current server."
+  (cadr (assoc (or server nnimap-current-server) nnimap-server-buffer-alist)))
+
+(defun nnimap-possibly-change-server (server)
+  "Return buffer for SERVER, changing the current server as a side-effect.
+If SERVER is nil, uses the current server."
+  (setq nnimap-current-server (or server nnimap-current-server)
+       nnimap-server-buffer (nnimap-get-server-buffer nnimap-current-server)))
+
+(defun nnimap-verify-uidvalidity (group server)
+  "Verify stored uidvalidity match current one in GROUP on SERVER."
+  (let* ((gnusgroup (gnus-group-prefixed-name
+                    group (gnus-server-to-method
+                           (format "nnimap:%s" server))))
+        (new-uidvalidity (imap-mailbox-get 'uidvalidity))
+        (old-uidvalidity (gnus-group-get-parameter gnusgroup 'uidvalidity))
+        (dir (file-name-as-directory (expand-file-name nnimap-directory)))
+        (nameuid (nnheader-translate-file-chars
+                  (concat nnimap-nov-file-name
+                          (if (equal server "")
+                              "unnamed"
+                            server) "." group "." old-uidvalidity
+                            nnimap-nov-file-name-suffix) t))
+        (file (if (or nnmail-use-long-file-names
+                      (file-exists-p (expand-file-name nameuid dir)))
+                  (expand-file-name nameuid dir)
+                (expand-file-name
+                 (encode-coding-string
+                  (nnheader-replace-chars-in-string nameuid ?. ?/)
+                  nnmail-pathname-coding-system)
+                 dir))))
+    (if old-uidvalidity
+       (if (not (equal old-uidvalidity new-uidvalidity))
+           ;; uidvalidity clash
+           (gnus-delete-file file)
+         (gnus-group-set-parameter gnusgroup 'uidvalidity new-uidvalidity)
+         t)
+      (gnus-group-add-parameter gnusgroup (cons 'uidvalidity new-uidvalidity))
+      t)))
+
+(defun nnimap-before-find-minmax-bugworkaround ()
+  "Function called before iterating through mailboxes with
+`nnimap-find-minmax-uid'."
+  (when nnimap-need-unselect-to-notice-new-mail
+    ;; XXX this is for UoW imapd problem, it doesn't notice new mail in
+    ;; currently selected mailbox without a re-select/examine.
+    (or (null (imap-current-mailbox nnimap-server-buffer))
+       (imap-mailbox-unselect nnimap-server-buffer))))
+
+(defun nnimap-find-minmax-uid (group &optional examine)
+  "Find lowest and highest active article number in GROUP.
+If EXAMINE is non-nil the group is selected read-only."
+  (with-current-buffer nnimap-server-buffer
+    (when (or (string= group (imap-current-mailbox))
+             (imap-mailbox-select group examine))
+      (let (minuid maxuid)
+       (when (> (imap-mailbox-get 'exists) 0)
+         (imap-fetch "1,*" "UID" nil 'nouidfetch)
+         (imap-message-map (lambda (uid Uid)
+                             (setq minuid (if minuid (min minuid uid) uid)
+                                   maxuid (if maxuid (max maxuid uid) uid)))
+                           'UID))
+       (list (imap-mailbox-get 'exists) minuid maxuid)))))
+
+(defun nnimap-possibly-change-group (group &optional server)
+  "Make GROUP the current group, and SERVER the current server."
+  (when (nnimap-possibly-change-server server)
+    (with-current-buffer nnimap-server-buffer
+      (if (or (null group) (imap-current-mailbox-p group))
+         imap-current-mailbox
+       (if (imap-mailbox-select group)
+           (if (or (nnimap-verify-uidvalidity
+                    group (or server nnimap-current-server))
+                   (zerop (imap-mailbox-get 'exists group))
+                   t ;; for OGnus to see if ignoring uidvalidity
+                     ;; changes has any bad effects.
+                   (yes-or-no-p
+                    (format
+                     "nnimap: Group %s is not uidvalid.  Continue? " group)))
+               imap-current-mailbox
+             (imap-mailbox-unselect)
+             (error "nnimap: Group %s is not uid-valid" group))
+         (nnheader-report 'nnimap (imap-error-text)))))))
+
+(defun nnimap-replace-whitespace (string)
+  "Return STRING with all whitespace replaced with space."
+  (when string
+    (while (string-match "[\r\n\t]+" string)
+      (setq string (replace-match " " t t string)))
+    string))
+
+;; Required backend functions
+
+(defun nnimap-retrieve-headers-progress ()
+  "Hook to insert NOV line for current article into `nntp-server-buffer'."
+  (and (numberp nnmail-large-newsgroup)
+       (zerop (% (incf nnimap-counter) nnimap-progress-how-often))
+       (> nnimap-length nnmail-large-newsgroup)
+       (nnheader-message 6 "nnimap: Retrieving headers... %c"
+                        (nth (/ (% nnimap-counter
+                                   (* (length nnimap-progress-chars)
+                                      nnimap-progress-how-often))
+                                nnimap-progress-how-often)
+                             nnimap-progress-chars)))
+  (with-current-buffer nntp-server-buffer
+    (let (headers lines chars uid mbx)
+      (with-current-buffer nnimap-server-buffer
+       (setq uid imap-current-message
+             mbx imap-current-mailbox
+             headers (nnimap-demule
+                      (if (imap-capability 'IMAP4rev1)
+                          ;; xxx don't just use car? alist doesn't contain
+                          ;; anything else now, but it might...
+                          (nth 2 (car (imap-message-get uid 'BODYDETAIL)))
+                        (imap-message-get uid 'RFC822.HEADER)))
+             lines (imap-body-lines (imap-message-body imap-current-message))
+             chars (imap-message-get imap-current-message 'RFC822.SIZE)))
+      (nnheader-insert-nov
+       (with-temp-buffer
+        (buffer-disable-undo)
+        (insert headers)
+        (let ((head (nnheader-parse-naked-head)))
+          (mail-header-set-number head uid)
+          (mail-header-set-chars head chars)
+          (mail-header-set-lines head lines)
+          (mail-header-set-xref
+           head (format "%s %s:%d" (system-name) mbx uid))
+          head))))))
+
+(defun nnimap-retrieve-which-headers (articles fetch-old)
+  "Get a range of articles to fetch based on ARTICLES and FETCH-OLD."
+  (with-current-buffer nnimap-server-buffer
+    (if (numberp (car-safe articles))
+       (imap-search
+        (concat "UID "
+                (imap-range-to-message-set
+                 (gnus-compress-sequence
+                  (append (gnus-uncompress-sequence
+                           (and fetch-old
+                                (cons (if (numberp fetch-old)
+                                          (max 1 (- (car articles) fetch-old))
+                                        1)
+                                      (1- (car articles)))))
+                          articles)))))
+      (mapcar (lambda (msgid)
+               (imap-search
+                (format "HEADER Message-Id \"%s\"" msgid)))
+             articles))))
+
+(defun nnimap-group-overview-filename (group server)
+  "Make file name for GROUP on SERVER."
+  (let* ((dir (file-name-as-directory (expand-file-name nnimap-directory)))
+        (uidvalidity (gnus-group-get-parameter
+                      (gnus-group-prefixed-name
+                       group (gnus-server-to-method
+                              (format "nnimap:%s" server)))
+                      'uidvalidity))
+        (name (nnheader-translate-file-chars
+               (concat nnimap-nov-file-name
+                       (if (equal server "")
+                           "unnamed"
+                         server) "." group nnimap-nov-file-name-suffix) t))
+        (nameuid (nnheader-translate-file-chars
+                  (concat nnimap-nov-file-name
+                          (if (equal server "")
+                              "unnamed"
+                            server) "." group "." uidvalidity
+                            nnimap-nov-file-name-suffix) t))
+        (oldfile (if (or nnmail-use-long-file-names
+                         (file-exists-p (expand-file-name name dir)))
+                     (expand-file-name name dir)
+                   (expand-file-name
+                    (encode-coding-string
+                     (nnheader-replace-chars-in-string name ?. ?/)
+                     nnmail-pathname-coding-system)
+                    dir)))
+        (newfile (if (or nnmail-use-long-file-names
+                         (file-exists-p (expand-file-name nameuid dir)))
+                     (expand-file-name nameuid dir)
+                   (expand-file-name
+                    (encode-coding-string
+                     (nnheader-replace-chars-in-string nameuid ?. ?/)
+                     nnmail-pathname-coding-system)
+                    dir))))
+    (when (and (file-exists-p oldfile) (not (file-exists-p newfile)))
+      (message "nnimap: Upgrading novcache filename...")
+      (sit-for 1)
+      (gnus-make-directory (file-name-directory newfile))
+      (unless (ignore-errors (rename-file oldfile newfile) t)
+       (if (ignore-errors (copy-file oldfile newfile) t)
+           (delete-file oldfile)
+         (error "Can't rename `%s' to `%s'" oldfile newfile))))
+    newfile))
+
+(defun nnimap-retrieve-headers-from-file (group server)
+  (with-current-buffer nntp-server-buffer
+    (let ((nov (nnimap-group-overview-filename group server)))
+      (when (file-exists-p nov)
+       (nnheader-insert-file-contents nov)
+       (set-buffer-modified-p nil)
+       (let ((min (ignore-errors (goto-char (point-min))
+                                 (read (current-buffer))))
+             (max (ignore-errors (goto-char (point-max))
+                                 (forward-line -1)
+                                 (read (current-buffer)))))
+         (if (and (numberp min) (numberp max))
+             (cons min max)
+           ;; junk, remove it, it's saved later
+           (erase-buffer)
+           nil))))))
+
+(defun nnimap-retrieve-headers-from-server (articles group server)
+  (with-current-buffer nnimap-server-buffer
+    (let ((imap-fetch-data-hook '(nnimap-retrieve-headers-progress))
+         (nnimap-length (gnus-range-length articles))
+         (nnimap-counter 0))
+      (imap-fetch (imap-range-to-message-set articles)
+                 (concat "(UID RFC822.SIZE BODY "
+                         (let ((headers
+                                (append '(Subject From Date Message-Id
+                                                  References In-Reply-To Xref)
+                                        (copy-sequence
+                                         nnmail-extra-headers))))
+                           (if (imap-capability 'IMAP4rev1)
+                               (format "BODY.PEEK[HEADER.FIELDS %s])" headers)
+                             (format "RFC822.HEADER.LINES %s)" headers)))))
+      (and (numberp nnmail-large-newsgroup)
+          (> nnimap-length nnmail-large-newsgroup)
+          (nnheader-message 6 "nnimap: Retrieving headers...done")))))
+
+(defun nnimap-dont-use-nov-p (group server)
+  (or gnus-nov-is-evil nnimap-nov-is-evil
+      (unless (and (gnus-make-directory
+                   (file-name-directory
+                    (nnimap-group-overview-filename group server)))
+                  (file-writable-p
+                   (nnimap-group-overview-filename group server)))
+       (message "nnimap: Nov cache not writable, %s"
+                (nnimap-group-overview-filename group server)))))
+
+(deffoo nnimap-retrieve-headers (articles &optional group server fetch-old)
+  (when (nnimap-possibly-change-group group server)
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (if (nnimap-dont-use-nov-p group server)
+         (nnimap-retrieve-headers-from-server
+          (gnus-compress-sequence articles) group server)
+       (let (uids cached low high)
+         (when (setq uids (nnimap-retrieve-which-headers articles fetch-old)
+                     low (car uids)
+                     high (car (last uids)))
+           (if (setq cached (nnimap-retrieve-headers-from-file group server))
+               (progn
+                 ;; fetch articles with uids before cache block
+                 (when (< low (car cached))
+                   (goto-char (point-min))
+                   (nnimap-retrieve-headers-from-server
+                    (cons low (1- (car cached))) group server))
+                 ;; fetch articles with uids after cache block
+                 (when (> high (cdr cached))
+                   (goto-char (point-max))
+                   (nnimap-retrieve-headers-from-server
+                    (cons (1+ (cdr cached)) high) group server))
+                 (when nnimap-prune-cache
+                   ;; remove nov's for articles which has expired on server
+                   (goto-char (point-min))
+                   (dolist (uid (gnus-set-difference articles uids))
+                     (when (re-search-forward (format "^%d\t" uid) nil t)
+                       (gnus-delete-line)))))
+             ;; nothing cached, fetch whole range from server
+             (nnimap-retrieve-headers-from-server
+              (cons low high) group server))
+           (when (buffer-modified-p)
+             (nnmail-write-region
+              (point-min) (point-max)
+              (nnimap-group-overview-filename group server) nil 'nomesg))
+           (nnheader-nov-delete-outside-range low high))))
+      'nov)))
+
+(defun nnimap-open-connection (server)
+  (if (not (imap-open nnimap-address nnimap-server-port nnimap-stream
+                     nnimap-authenticator nnimap-server-buffer))
+      (nnheader-report 'nnimap "Can't open connection to server %s" server)
+    (unless (or (imap-capability 'IMAP4 nnimap-server-buffer)
+               (imap-capability 'IMAP4rev1 nnimap-server-buffer))
+      (imap-close nnimap-server-buffer)
+      (nnheader-report 'nnimap "Server %s is not IMAP4 compliant" server))
+    (let* ((list (gnus-parse-netrc nnimap-authinfo-file))
+          (port (if nnimap-server-port
+                    (int-to-string nnimap-server-port)
+                  "imap"))
+          (alist (or (gnus-netrc-machine list server port "imap")
+                     (gnus-netrc-machine list
+                                         (or nnimap-server-address
+                                             nnimap-address)
+                                         port "imap")))
+          (user (gnus-netrc-get alist "login"))
+          (passwd (gnus-netrc-get alist "password")))
+      (if (imap-authenticate user passwd nnimap-server-buffer)
+         (prog1
+             (push (list server nnimap-server-buffer)
+                   nnimap-server-buffer-alist)
+           (nnimap-possibly-change-server server))
+       (imap-close nnimap-server-buffer)
+       (kill-buffer nnimap-server-buffer)
+       (nnheader-report 'nnimap "Could not authenticate to %s" server)))))
+
+(deffoo nnimap-open-server (server &optional defs)
+  (nnheader-init-server-buffer)
+  (if (nnimap-server-opened server)
+      t
+    (unless (assq 'nnimap-server-buffer defs)
+      (push (list 'nnimap-server-buffer (concat " *nnimap* " server)) defs))
+    ;; translate `nnimap-server-address' to `nnimap-address' in defs
+    ;; for people that configured nnimap with a very old version
+    (unless (assq 'nnimap-address defs)
+      (if (assq 'nnimap-server-address defs)
+         (push (list 'nnimap-address
+                     (cadr (assq 'nnimap-server-address defs))) defs)
+       (push (list 'nnimap-address server) defs)))
+    (nnoo-change-server 'nnimap server defs)
+    (or nnimap-server-buffer
+       (setq nnimap-server-buffer (cadr (assq 'nnimap-server-buffer defs))))
+    (with-current-buffer (get-buffer-create nnimap-server-buffer)
+      (nnoo-change-server 'nnimap server defs))
+    (or (and nnimap-server-buffer
+            (imap-opened nnimap-server-buffer)
+            (if (with-current-buffer nnimap-server-buffer
+                  (memq imap-state '(auth select examine)))
+                t
+              (imap-close nnimap-server-buffer)
+              (nnimap-open-connection server)))
+       (nnimap-open-connection server))))
+
+(deffoo nnimap-server-opened (&optional server)
+  "Whether SERVER is opened.
+If SERVER is the current virtual server, and the connection to the
+physical server is alive, this function return a non-nil value.  If
+SERVER is nil, it is treated as the current server."
+  ;; clean up autologouts??
+  (and (or server nnimap-current-server)
+       (nnoo-server-opened 'nnimap (or server nnimap-current-server))
+       (imap-opened (nnimap-get-server-buffer server))))
+
+(deffoo nnimap-close-server (&optional server)
+  "Close connection to server and free all resources connected to it.
+Return nil if the server couldn't be closed for some reason."
+  (let ((server (or server nnimap-current-server)))
+    (when (or (nnimap-server-opened server)
+             (imap-opened (nnimap-get-server-buffer server)))
+      (imap-close (nnimap-get-server-buffer server))
+      (kill-buffer (nnimap-get-server-buffer server))
+      (setq nnimap-server-buffer nil
+           nnimap-current-server nil
+           nnimap-server-buffer-alist
+           (delq server nnimap-server-buffer-alist)))
+    (nnoo-close-server 'nnimap server)))
+
+(deffoo nnimap-request-close ()
+  "Close connection to all servers and free all resources that the backend have reserved.
+All buffers that have been created by that
+backend should be killed.  (Not the nntp-server-buffer, though.) This
+function is generally only called when Gnus is shutting down."
+  (mapcar (lambda (server) (nnimap-close-server (car server)))
+         nnimap-server-buffer-alist)
+  (setq nnimap-server-buffer-alist nil))
+
+(deffoo nnimap-status-message (&optional server)
+  "This function returns the last error message from server."
+  (when (nnimap-possibly-change-server server)
+    (nnoo-status-message 'nnimap server)))
+
+(defun nnimap-demule (string)
+  (funcall (if (and (fboundp 'string-as-multibyte)
+                   (subrp (symbol-function 'string-as-multibyte)))
+              'string-as-multibyte
+            'identity)
+          (or string "")))
+
+(defun nnimap-make-callback (article gnus-callback buffer)
+  "Return a callback function."
+  `(lambda ()
+     (nnimap-callback ,article ,gnus-callback ,buffer)))
+
+(defun nnimap-callback (article gnus-callback buffer)
+  (when (eq article (imap-current-message))
+    (remove-hook 'imap-fetch-data-hook
+                (nnimap-make-callback article gnus-callback buffer))
+    (with-current-buffer buffer
+      (insert
+       (with-current-buffer nnimap-server-buffer
+        (nnimap-demule
+         (if (imap-capability 'IMAP4rev1)
+             ;; xxx don't just use car? alist doesn't contain
+             ;; anything else now, but it might...
+             (nth 2 (car (imap-message-get article 'BODYDETAIL)))
+           (imap-message-get article 'RFC822)))))
+      (nnheader-ms-strip-cr)
+      (funcall gnus-callback t))))
+
+(defun nnimap-request-article-part (article part prop &optional
+                                           group server to-buffer detail)
+  (when (nnimap-possibly-change-group group server)
+    (let ((article (if (stringp article)
+                      (car-safe (imap-search
+                                 (format "HEADER Message-Id \"%s\"" article)
+                                 nnimap-server-buffer))
+                    article)))
+      (when article
+       (gnus-message 10 "nnimap: Fetching (part of) article %d from %s..."
+                     article (or group imap-current-mailbox
+                                 gnus-newsgroup-name))
+       (if (not nnheader-callback-function)
+           (with-current-buffer (or to-buffer nntp-server-buffer)
+             (erase-buffer)
+             (let ((data (imap-fetch article part prop nil
+                                     nnimap-server-buffer)))
+               (when data
+                 (insert (nnimap-demule (if detail (nth 2 (car data)) data)))
+                 (nnheader-ms-strip-cr)
+                 (gnus-message
+                  10 "nnimap: Fetching (part of) article %d from %s...done"
+                  article (or group imap-current-mailbox gnus-newsgroup-name))
+                 (if (bobp)
+                     (nnheader-report 'nnimap "No such article %d in %s: %s"
+                                      article (or group imap-current-mailbox
+                                                  gnus-newsgroup-name)
+                                      (imap-error-text nnimap-server-buffer))
+                   (cons group article)))))
+         (add-hook 'imap-fetch-data-hook
+                   (nnimap-make-callback article
+                                         nnheader-callback-function
+                                         nntp-server-buffer))
+         (imap-fetch-asynch article part nil nnimap-server-buffer)
+         (cons group article))))))
+
+(deffoo nnimap-asynchronous-p ()
+  t)
+
+(deffoo nnimap-request-article (article &optional group server to-buffer)
+  (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
+      (nnimap-request-article-part
+       article "BODY.PEEK[]" 'BODYDETAIL group server to-buffer 'detail)
+    (nnimap-request-article-part
+     article "RFC822.PEEK" 'RFC822 group server to-buffer)))
+
+(deffoo nnimap-request-head (article &optional group server to-buffer)
+  (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
+      (nnimap-request-article-part
+       article "BODY.PEEK[HEADER]" 'BODYDETAIL group server to-buffer 'detail)
+    (nnimap-request-article-part
+     article "RFC822.HEADER" 'RFC822.HEADER group server to-buffer)))
+
+(deffoo nnimap-request-body (article &optional group server to-buffer)
+  (if (imap-capability 'IMAP4rev1 nnimap-server-buffer)
+      (nnimap-request-article-part
+       article "BODY.PEEK[TEXT]" 'BODYDETAIL group server to-buffer 'detail)
+    (nnimap-request-article-part
+     article "RFC822.TEXT.PEEK" 'RFC822.TEXT group server to-buffer)))
+
+(deffoo nnimap-request-group (group &optional server fast)
+  (nnimap-request-update-info-internal
+   group
+   (gnus-get-info (gnus-group-prefixed-name
+                  group (gnus-server-to-method (format "nnimap:%s" server))))
+   server)
+  (when (nnimap-possibly-change-group group server)
+    (nnimap-before-find-minmax-bugworkaround)
+    (let (info)
+      (cond (fast group)
+           ((null (setq info (nnimap-find-minmax-uid group t)))
+            (nnheader-report 'nnimap "Could not get active info for %s"
+                             group))
+           (t
+            (nnheader-insert "211 %d %d %d %s\n" (or (nth 0 info) 0)
+                             (max 1 (or (nth 1 info) 1))
+                             (or (nth 2 info) 0) group)
+            (nnheader-report 'nnimap "Group %s selected" group)
+            t)))))
+
+(defun nnimap-update-unseen (group &optional server)
+  "Update the unseen count in `nnimap-mailbox-info'."
+  (gnus-sethash
+   (gnus-group-prefixed-name group server)
+   (let ((old (gnus-gethash-safe (gnus-group-prefixed-name group server)
+                                nnimap-mailbox-info)))
+     (list (nth 0 old) (nth 1 old)
+          (imap-mailbox-status group 'unseen nnimap-server-buffer)
+          (nth 3 old)))
+   nnimap-mailbox-info))
+
+(defun nnimap-close-group (group &optional server)
+  (with-current-buffer nnimap-server-buffer
+    (when (and (imap-opened)
+              (nnimap-possibly-change-group group server))
+      (nnimap-update-unseen group server)
+      (case nnimap-expunge-on-close
+       (always (progn
+                 (imap-mailbox-expunge nnimap-close-asynchronous)
+                 (unless nnimap-dont-close
+                   (imap-mailbox-close nnimap-close-asynchronous))))
+       (ask (if (and (imap-search "DELETED")
+                     (gnus-y-or-n-p (format "Expunge articles in group `%s'? "
+                                            imap-current-mailbox)))
+                (progn
+                  (imap-mailbox-expunge nnimap-close-asynchronous)
+                  (unless nnimap-dont-close
+                    (imap-mailbox-close nnimap-close-asynchronous)))
+              (imap-mailbox-unselect)))
+       (t (imap-mailbox-unselect)))
+      (not imap-current-mailbox))))
+
+(defun nnimap-pattern-to-list-arguments (pattern)
+  (mapcar (lambda (p)
+           (cons (car-safe p) (or (cdr-safe p) p)))
+         (if (and (listp pattern)
+                  (listp (cdr pattern)))
+             pattern
+           (list pattern))))
+
+(deffoo nnimap-request-list (&optional server)
+  (when (nnimap-possibly-change-server server)
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer))
+    (gnus-message 5 "nnimap: Generating active list%s..."
+                 (if (> (length server) 0) (concat " for " server) ""))
+    (nnimap-before-find-minmax-bugworkaround)
+    (with-current-buffer nnimap-server-buffer
+      (dolist (pattern (nnimap-pattern-to-list-arguments nnimap-list-pattern))
+       (dolist (mbx (funcall nnimap-request-list-method
+                             (cdr pattern) (car pattern)))
+         (or (member "\\NoSelect" (imap-mailbox-get 'list-flags mbx))
+             (let ((info (nnimap-find-minmax-uid mbx 'examine)))
+               (when info
+                 (with-current-buffer nntp-server-buffer
+                   (insert (format "\"%s\" %d %d y\n"
+                                   mbx (or (nth 2 info) 0)
+                                   (max 1 (or (nth 1 info) 1)))))))))))
+    (gnus-message 5 "nnimap: Generating active list%s...done"
+                 (if (> (length server) 0) (concat " for " server) ""))
+    t))
+
+(deffoo nnimap-request-post (&optional server)
+  (let ((success t))
+    (dolist (mbx (message-unquote-tokens
+                 (message-tokenize-header
+                  (message-fetch-field "Newsgroups") ", ")) success)
+      (let ((to-newsgroup (gnus-group-prefixed-name mbx gnus-command-method)))
+       (or (gnus-active to-newsgroup)
+           (gnus-activate-group to-newsgroup)
+           (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
+                                      to-newsgroup))
+               (or (and (gnus-request-create-group
+                         to-newsgroup gnus-command-method)
+                        (gnus-activate-group to-newsgroup nil nil
+                                             gnus-command-method))
+                   (error "Couldn't create group %s" to-newsgroup)))
+           (error "No such group: %s" to-newsgroup))
+       (unless (nnimap-request-accept-article mbx (nth 1 gnus-command-method))
+         (setq success nil))))))
+
+;; Optional backend functions
+
+(defun nnimap-string-lessp-numerical (s1 s2)
+  "Return t if first arg string is less than second in numerical order."
+  (cond ((string= s1 s2)
+        nil)
+       ((> (length s1) (length s2))
+        nil)
+       ((< (length s1) (length s2))
+        t)
+       ((< (string-to-number (substring s1 0 1))
+           (string-to-number (substring s2 0 1)))
+        t)
+       ((> (string-to-number (substring s1 0 1))
+           (string-to-number (substring s2 0 1)))
+        nil)
+       (t
+        (nnimap-string-lessp-numerical (substring s1 1) (substring s2 1)))))
+
+(deffoo nnimap-retrieve-groups (groups &optional server)
+  (when (nnimap-possibly-change-server server)
+    (gnus-message 5 "nnimap: Checking mailboxes...")
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (nnimap-before-find-minmax-bugworkaround)
+      (let (asyncgroups slowgroups)
+       (if (null nnimap-retrieve-groups-asynchronous)
+           (setq slowgroups groups)
+         (dolist (group groups)
+           (gnus-message 9 "nnimap: Quickly checking mailbox %s" group)
+           (add-to-list (if (gnus-gethash-safe
+                             (gnus-group-prefixed-name group server)
+                             nnimap-mailbox-info)
+                            'asyncgroups
+                          'slowgroups)
+                        (list group (imap-mailbox-status-asynch
+                                     group '(uidvalidity uidnext unseen)
+                                     nnimap-server-buffer))))
+         (dolist (asyncgroup asyncgroups)
+           (let ((group (nth 0 asyncgroup))
+                 (tag   (nth 1 asyncgroup))
+                 new old)
+             (when (imap-ok-p (imap-wait-for-tag tag nnimap-server-buffer))
+               (if (or (not (string=
+                             (nth 0 (gnus-gethash (gnus-group-prefixed-name
+                                                   group server)
+                                                  nnimap-mailbox-info))
+                             (imap-mailbox-get 'uidvalidity group
+                                               nnimap-server-buffer)))
+                       (not (string=
+                             (nth 1 (gnus-gethash (gnus-group-prefixed-name
+                                                   group server)
+                                                  nnimap-mailbox-info))
+                             (imap-mailbox-get 'uidnext group
+                                               nnimap-server-buffer))))
+                   (push (list group) slowgroups)
+                 (insert (nth 3 (gnus-gethash (gnus-group-prefixed-name
+                                               group server)
+                                              nnimap-mailbox-info))))))))
+       (dolist (group slowgroups)
+         (if nnimap-retrieve-groups-asynchronous
+             (setq group (car group)))
+         (gnus-message 7 "nnimap: Mailbox %s modified" group)
+         (imap-mailbox-put 'uidnext nil group nnimap-server-buffer)
+         (or (member "\\NoSelect" (imap-mailbox-get 'list-flags group
+                                                    nnimap-server-buffer))
+             (let* ((info (nnimap-find-minmax-uid group 'examine))
+                    (str (format "\"%s\" %d %d y\n" group
+                                 (or (nth 2 info) 0)
+                                 (max 1 (or (nth 1 info) 1)))))
+               (when (> (or (imap-mailbox-get 'recent group
+                                              nnimap-server-buffer) 0)
+                        0)
+                 (push (list (cons group 0)) nnmail-split-history))
+               (insert str)
+               (when nnimap-retrieve-groups-asynchronous
+                 (gnus-sethash
+                  (gnus-group-prefixed-name group server)
+                  (list (or (imap-mailbox-get
+                             'uidvalidity group nnimap-server-buffer)
+                            (imap-mailbox-status
+                             group 'uidvalidity nnimap-server-buffer))
+                        (or (imap-mailbox-get
+                             'uidnext group nnimap-server-buffer)
+                            (imap-mailbox-status
+                             group 'uidnext nnimap-server-buffer))
+                        (or (imap-mailbox-get
+                             'unseen group nnimap-server-buffer)
+                            (imap-mailbox-status
+                             group 'unseen nnimap-server-buffer))
+                        str)
+                  nnimap-mailbox-info)))))))
+    (gnus-message 5 "nnimap: Checking mailboxes...done")
+    'active))
+
+(deffoo nnimap-request-update-info-internal (group info &optional server)
+  (when (nnimap-possibly-change-group group server)
+    (when info;; xxx what does this mean? should we create a info?
+      (with-current-buffer nnimap-server-buffer
+       (gnus-message 5 "nnimap: Updating info for %s..."
+                     (gnus-info-group info))
+
+       (when (nnimap-mark-permanent-p 'read)
+         (let (seen unseen)
+           ;; read info could contain articles marked unread by other
+           ;; imap clients!  we correct this
+           (setq seen (gnus-uncompress-range (gnus-info-read info))
+                 unseen (imap-search "UNSEEN UNDELETED")
+                 seen (gnus-set-difference seen unseen)
+                 ;; seen might lack articles marked as read by other
+                 ;; imap clients! we correct this
+                 seen (append seen (imap-search "SEEN"))
+                 ;; remove dupes
+                 seen (sort seen '<)
+                 seen (gnus-compress-sequence seen t)
+                 ;; we can't return '(1) since this isn't a "list of ranges",
+                 ;; and we can't return '((1)) since g-list-of-unread-articles
+                 ;; is buggy so we return '((1 . 1)).
+                 seen (if (and (integerp (car seen))
+                               (null (cdr seen)))
+                          (list (cons (car seen) (car seen)))
+                        seen))
+           (gnus-info-set-read info seen)))
+
+       (mapcar (lambda (pred)
+                 (when (or (eq (cdr pred) 'recent)
+                           (and (nnimap-mark-permanent-p (cdr pred))
+                                (member (nnimap-mark-to-flag (cdr pred))
+                                        (imap-mailbox-get 'flags))))
+                   (gnus-info-set-marks
+                    info
+                    (gnus-update-alist-soft
+                     (cdr pred)
+                     (gnus-compress-sequence
+                      (imap-search (nnimap-mark-to-predicate (cdr pred))))
+                     (gnus-info-marks info))
+                    t)))
+               gnus-article-mark-lists)
+
+       (when nnimap-importantize-dormant
+         ;; nnimap mark dormant article as ticked too (for other clients)
+         ;; so we remove that mark for gnus since we support dormant
+         (gnus-info-set-marks
+          info
+          (gnus-update-alist-soft
+           'tick
+           (gnus-remove-from-range
+            (cdr-safe (assoc 'tick (gnus-info-marks info)))
+            (cdr-safe (assoc 'dormant (gnus-info-marks info))))
+           (gnus-info-marks info))
+          t))
+
+       (gnus-message 5 "nnimap: Updating info for %s...done"
+                     (gnus-info-group info))
+
+       info))))
+
+(deffoo nnimap-request-type (group &optional article)
+  (if (and nnimap-news-groups (string-match nnimap-news-groups group))
+      'news
+    'mail))
+
+(deffoo nnimap-request-set-mark (group actions &optional server)
+  (when (nnimap-possibly-change-group group server)
+    (with-current-buffer nnimap-server-buffer
+      (let (action)
+       (gnus-message 7 "nnimap: Setting marks in %s..." group)
+       (while (setq action (pop actions))
+         (let ((range (nth 0 action))
+               (what  (nth 1 action))
+               (cmdmarks (nth 2 action))
+               marks)
+           ;; bookmark can't be stored (not list/range
+           (setq cmdmarks (delq 'bookmark cmdmarks))
+           ;; killed can't be stored (not list/range
+           (setq cmdmarks (delq 'killed cmdmarks))
+           ;; unsent are for nndraft groups only
+           (setq cmdmarks (delq 'unsent cmdmarks))
+           ;; cache flags are pointless on the server
+           (setq cmdmarks (delq 'cache cmdmarks))
+           ;; seen flags are local to each gnus
+           (setq cmdmarks (delq 'seen cmdmarks))
+           ;; recent marks can't be set
+           (setq cmdmarks (delq 'recent cmdmarks))
+           (when nnimap-importantize-dormant
+             ;; flag dormant articles as ticked
+             (if (memq 'dormant cmdmarks)
+                 (setq cmdmarks (cons 'tick cmdmarks))))
+           ;; remove stuff we are forbidden to store
+           (mapcar (lambda (mark)
+                     (if (imap-message-flag-permanent-p
+                          (nnimap-mark-to-flag mark))
+                         (setq marks (cons mark marks))))
+                   cmdmarks)
+           (when (and range marks)
+             (cond ((eq what 'del)
+                    (imap-message-flags-del
+                     (imap-range-to-message-set range)
+                     (nnimap-mark-to-flag marks nil t)))
+                   ((eq what 'add)
+                    (imap-message-flags-add
+                     (imap-range-to-message-set range)
+                     (nnimap-mark-to-flag marks nil t)))
+                   ((eq what 'set)
+                    (imap-message-flags-set
+                     (imap-range-to-message-set range)
+                     (nnimap-mark-to-flag marks nil t)))))))
+       (gnus-message 7 "nnimap: Setting marks in %s...done" group))))
+  nil)
+
+(defun nnimap-split-fancy ()
+  "Like the function `nnmail-split-fancy', but uses `nnimap-split-fancy'."
+  (let ((nnmail-split-fancy nnimap-split-fancy))
+    (nnmail-split-fancy)))
+
+(defun nnimap-split-to-groups (rules)
+  ;; tries to match all rules in nnimap-split-rule against content of
+  ;; nntp-server-buffer, returns a list of groups that matched.
+  (with-current-buffer nntp-server-buffer
+    ;; Fold continuation lines.
+    (goto-char (point-min))
+    (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
+      (replace-match " " t t))
+    (if (functionp rules)
+       (funcall rules)
+      (let (to-groups regrepp)
+       (catch 'split-done
+         (dolist (rule rules to-groups)
+           (let ((group (car rule))
+                 (regexp (cadr rule)))
+             (goto-char (point-min))
+             (when (and (if (stringp regexp)
+                            (progn
+                              (if (not (stringp group))
+                                  (setq group (eval group))
+                                (setq regrepp
+                                      (string-match "\\\\[0-9&]" group)))
+                              (re-search-forward regexp nil t))
+                          (funcall regexp group))
+                        ;; Don't enter the article into the same group twice.
+                        (not (assoc group to-groups)))
+               (push (if regrepp
+                         (nnmail-expand-newtext group)
+                       group)
+                     to-groups)
+               (or nnimap-split-crosspost
+                   (throw 'split-done to-groups))))))))))
+
+(defun nnimap-assoc-match (key alist)
+  (let (element)
+    (while (and alist (not element))
+      (if (string-match (car (car alist)) key)
+         (setq element (car alist)))
+      (setq alist (cdr alist)))
+    element))
+
+(defun nnimap-split-find-rule (server inbox)
+  (if (and (listp nnimap-split-rule) (listp (car nnimap-split-rule))
+          (list (cdar nnimap-split-rule)) (listp (cadar nnimap-split-rule)))
+      ;; extended format
+      (cadr (nnimap-assoc-match inbox (cdr (nnimap-assoc-match
+                                           server nnimap-split-rule))))
+    nnimap-split-rule))
+
+(defun nnimap-split-find-inbox (server)
+  (if (listp nnimap-split-inbox)
+      nnimap-split-inbox
+    (list nnimap-split-inbox)))
+
+(defun nnimap-split-articles (&optional group server)
+  (when (nnimap-possibly-change-server server)
+    (with-current-buffer nnimap-server-buffer
+      (let (rule inbox removeorig (inboxes (nnimap-split-find-inbox server)))
+       ;; iterate over inboxes
+       (while (and (setq inbox (pop inboxes))
+                   (nnimap-possibly-change-group inbox));; SELECT
+         ;; find split rule for this server / inbox
+         (when (setq rule (nnimap-split-find-rule server inbox))
+           ;; iterate over articles
+           (dolist (article (imap-search nnimap-split-predicate))
+             (when (if (if (eq nnimap-split-download-body 'default)
+                           nnimap-split-download-body-default
+                         nnimap-split-download-body)
+                       (and (nnimap-request-article article)
+                            (with-current-buffer nntp-server-buffer (mail-narrow-to-head)))
+                     (nnimap-request-head article))
+               ;; copy article to right group(s)
+               (setq removeorig nil)
+               (dolist (to-group (nnimap-split-to-groups rule))
+                 (cond ((eq to-group 'junk)
+                        (message "IMAP split removed %s:%s:%d" server inbox
+                                 article)
+                        (setq removeorig t))
+                       ((imap-message-copy (number-to-string article)
+                                           to-group nil 'nocopyuid)
+                        (message "IMAP split moved %s:%s:%d to %s" server
+                                 inbox article to-group)
+                        (setq removeorig t)
+                        (when nnmail-cache-accepted-message-ids
+                          (with-current-buffer nntp-server-buffer
+                            (let (msgid)
+                              (and (setq msgid
+                                         (nnmail-fetch-field "message-id"))
+                                   (nnmail-cache-insert msgid 
+                                                        to-group
+                                                        (nnmail-fetch-field "subject"))))))
+                        ;; Add the group-art list to the history list.
+                        (push (list (cons to-group 0)) nnmail-split-history))
+                       (t
+                        (message "IMAP split failed to move %s:%s:%d to %s"
+                                 server inbox article to-group))))
+               (if (if (eq nnimap-split-download-body 'default)
+                       nnimap-split-download-body-default
+                     nnimap-split-download-body)
+                   (widen))
+               ;; remove article if it was successfully copied somewhere
+               (and removeorig
+                    (imap-message-flags-add (format "%d" article)
+                                            "\\Seen \\Deleted")))))
+         (when (imap-mailbox-select inbox);; just in case
+           ;; todo: UID EXPUNGE (if available) to remove splitted articles
+           (imap-mailbox-expunge)
+           (imap-mailbox-close)))
+       (when nnmail-cache-accepted-message-ids
+         (nnmail-cache-close))
+       t))))
+
+(deffoo nnimap-request-scan (&optional group server)
+  (nnimap-split-articles group server))
+
+(deffoo nnimap-request-newgroups (date &optional server)
+  (when (nnimap-possibly-change-server server)
+    (with-current-buffer nntp-server-buffer
+      (gnus-message 5 "nnimap: Listing subscribed mailboxes%s%s..."
+                   (if (> (length server) 0) " on " "") server)
+      (erase-buffer)
+      (nnimap-before-find-minmax-bugworkaround)
+      (dolist (pattern (nnimap-pattern-to-list-arguments
+                       nnimap-list-pattern))
+       (dolist (mbx (imap-mailbox-lsub (cdr pattern) (car pattern) nil
+                                       nnimap-server-buffer))
+         (or (catch 'found
+               (dolist (mailbox (imap-mailbox-get 'list-flags mbx
+                                                  nnimap-server-buffer))
+                 (if (string= (downcase mailbox) "\\noselect")
+                     (throw 'found t)))
+               nil)
+             (let ((info (nnimap-find-minmax-uid mbx 'examine)))
+               (when info
+                 (insert (format "\"%s\" %d %d y\n"
+                                 mbx (or (nth 2 info) 0)
+                                 (max 1 (or (nth 1 info) 1)))))))))
+      (gnus-message 5 "nnimap: Listing subscribed mailboxes%s%s...done"
+                   (if (> (length server) 0) " on " "") server))
+    t))
+
+(deffoo nnimap-request-create-group (group &optional server args)
+  (when (nnimap-possibly-change-server server)
+    (or (imap-mailbox-status group 'uidvalidity nnimap-server-buffer)
+       (imap-mailbox-create group nnimap-server-buffer)
+       (nnheader-report 'nnimap "%S"
+                        (imap-error-text nnimap-server-buffer)))))
+
+(defun nnimap-time-substract (time1 time2)
+  "Return TIME for TIME1 - TIME2."
+  (let* ((ms (- (car time1) (car time2)))
+        (ls (- (nth 1 time1) (nth 1 time2))))
+    (if (< ls 0)
+       (list (- ms 1) (+ (expt 2 16) ls))
+      (list ms ls))))
+
+(defun nnimap-date-days-ago (daysago)
+  "Return date, in format \"3-Aug-1998\", for DAYSAGO days ago."
+  (let* ((time (nnimap-time-substract (current-time) (days-to-time daysago)))
+        (date (format-time-string
+               (format "%%d-%s-%%Y"
+                       (capitalize (car (rassoc (nth 4 (decode-time time))
+                                                parse-time-months))))
+               time)))
+    (if (eq ?0 (string-to-char date))
+       (substring date 1)
+      date)))
+
+(defun nnimap-request-expire-articles-progress ()
+  (gnus-message 5 "nnimap: Marking article %d for deletion..."
+               imap-current-message))
+
+(defun nnimap-expiry-target (arts group server)
+  (unless (eq nnmail-expiry-target 'delete)
+    (with-temp-buffer
+      (dolist (art arts)
+       (nnimap-request-article art group server (current-buffer))
+       ;; hints for optimization in `nnimap-request-accept-article'
+       (let ((nnimap-current-move-article art)
+             (nnimap-current-move-group group)
+             (nnimap-current-move-server server))
+         (nnmail-expiry-target-group nnmail-expiry-target group))))
+    ;; It is not clear if `nnmail-expiry-target' somehow cause the
+    ;; current group to be changed or not, so we make sure here.
+    (nnimap-possibly-change-group group server)))
+
+;; Notice that we don't actually delete anything, we just mark them deleted.
+(deffoo nnimap-request-expire-articles (articles group &optional server force)
+  (let ((artseq (gnus-compress-sequence articles)))
+    (when (and artseq (nnimap-possibly-change-group group server))
+      (with-current-buffer nnimap-server-buffer
+       (let ((days (or (and nnmail-expiry-wait-function
+                            (funcall nnmail-expiry-wait-function group))
+                       nnmail-expiry-wait)))
+         (cond ((or force (eq days 'immediate))
+                (let ((oldarts (imap-search
+                                (concat "UID "
+                                        (imap-range-to-message-set artseq)))))
+                  (when oldarts
+                    (nnimap-expiry-target oldarts group server)
+                    (when (imap-message-flags-add
+                           (imap-range-to-message-set
+                            (gnus-compress-sequence oldarts)) "\\Deleted")
+                      (setq articles (gnus-set-difference
+                                      articles oldarts))))))
+               ((numberp days)
+                (let ((oldarts (imap-search
+                                (format nnimap-expunge-search-string
+                                        (imap-range-to-message-set artseq)
+                                        (nnimap-date-days-ago days))))
+                      (imap-fetch-data-hook
+                       '(nnimap-request-expire-articles-progress)))
+                  (when oldarts
+                    (nnimap-expiry-target oldarts group server)
+                    (when (imap-message-flags-add
+                           (imap-range-to-message-set
+                            (gnus-compress-sequence oldarts)) "\\Deleted")
+                      (setq articles (gnus-set-difference
+                                      articles oldarts)))))))))))
+  ;; return articles not deleted
+  articles)
+
+(deffoo nnimap-request-move-article (article group server
+                                            accept-form &optional last)
+  (when (nnimap-possibly-change-server server)
+    (save-excursion
+      (let ((buf (get-buffer-create " *nnimap move*"))
+           (nnimap-current-move-article article)
+           (nnimap-current-move-group group)
+           (nnimap-current-move-server nnimap-current-server)
+           result)
+       (and (nnimap-request-article article group server)
+            (save-excursion
+              (set-buffer buf)
+              (buffer-disable-undo (current-buffer))
+              (insert-buffer-substring nntp-server-buffer)
+              (setq result (eval accept-form))
+              (kill-buffer buf)
+              result)
+            (imap-message-flags-add
+             (imap-range-to-message-set (list article))
+             "\\Deleted" 'silent nnimap-server-buffer))
+       result))))
+
+(deffoo nnimap-request-accept-article (group &optional server last)
+  (when (nnimap-possibly-change-server server)
+    (let (uid)
+      (if (setq uid
+               (if (string= nnimap-current-server nnimap-current-move-server)
+                   ;; moving article within same server, speed it up...
+                   (and (nnimap-possibly-change-group
+                         nnimap-current-move-group)
+                        (imap-message-copy (number-to-string
+                                            nnimap-current-move-article)
+                                           group 'dontcreate nil
+                                           nnimap-server-buffer))
+                 (with-current-buffer (current-buffer)
+                   (goto-char (point-min))
+                   ;; remove any 'From blabla' lines, some IMAP servers
+                   ;; reject the entire message otherwise.
+                   (when (looking-at "^From[^:]")
+                     (delete-region (point) (progn (forward-line) (point))))
+                   ;; turn into rfc822 format (\r\n eol's)
+                   (while (search-forward "\n" nil t)
+                     (replace-match "\r\n"))
+                   (when nnmail-cache-accepted-message-ids
+                     (nnmail-cache-insert (nnmail-fetch-field "message-id")
+                                          group
+                                          (nnmail-fetch-field "subject"))))
+                 (when (and last nnmail-cache-accepted-message-ids)
+                   (nnmail-cache-close))
+                 ;; this 'or' is for Cyrus server bug
+                 (or (null (imap-current-mailbox nnimap-server-buffer))
+                     (imap-mailbox-unselect nnimap-server-buffer))
+                 (imap-message-append group (current-buffer) nil nil
+                                      nnimap-server-buffer)))
+         (cons group (nth 1 uid))
+       (nnheader-report 'nnimap (imap-error-text nnimap-server-buffer))))))
+
+(deffoo nnimap-request-delete-group (group force &optional server)
+  (when (nnimap-possibly-change-server server)
+    (with-current-buffer nnimap-server-buffer
+      (if force
+         (or (null (imap-mailbox-status group 'uidvalidity))
+             (imap-mailbox-delete group))
+       ;; UNSUBSCRIBE?
+       t))))
+
+(deffoo nnimap-request-rename-group (group new-name &optional server)
+  (when (nnimap-possibly-change-server server)
+    (imap-mailbox-rename group new-name nnimap-server-buffer)))
+
+(defun nnimap-expunge (mailbox server)
+  (when (nnimap-possibly-change-group mailbox server)
+    (imap-mailbox-expunge nil nnimap-server-buffer)))
+
+(defun nnimap-acl-get (mailbox server)
+  (when (nnimap-possibly-change-server server)
+    (and (imap-capability 'ACL nnimap-server-buffer)
+        (imap-mailbox-acl-get mailbox nnimap-server-buffer))))
+
+(defun nnimap-acl-edit (mailbox method old-acls new-acls)
+  (when (nnimap-possibly-change-server (cadr method))
+    (unless (imap-capability 'ACL nnimap-server-buffer)
+      (error "Your server does not support ACL editing"))
+    (with-current-buffer nnimap-server-buffer
+      ;; delete all removed identifiers
+      (mapcar (lambda (old-acl)
+               (unless (assoc (car old-acl) new-acls)
+                 (or (imap-mailbox-acl-delete (car old-acl) mailbox)
+                     (error "Can't delete ACL for %s" (car old-acl)))))
+             old-acls)
+      ;; set all changed acl's
+      (mapcar (lambda (new-acl)
+               (let ((new-rights (cdr new-acl))
+                     (old-rights (cdr (assoc (car new-acl) old-acls))))
+                 (unless (and old-rights new-rights
+                              (string= old-rights new-rights))
+                   (or (imap-mailbox-acl-set (car new-acl) new-rights mailbox)
+                       (error "Can't set ACL for %s to %s" (car new-acl)
+                              new-rights)))))
+             new-acls)
+      t)))
+
+\f
+;;; Internal functions
+
+;;
+;; This is confusing.
+;;
+;; mark      => read, tick, draft, reply etc
+;; flag      => "\\Seen", "\\Flagged", "\\Draft", "gnus-expire" etc
+;; predicate => "SEEN", "FLAGGED", "DRAFT", "KEYWORD gnus-expire" etc
+;;
+;; Mark should not really contain 'read since it's not a "mark" in the Gnus
+;; world, but we cheat.  Mark == gnus-article-mark-lists + '(read . read).
+;;
+
+(defconst nnimap-mark-to-predicate-alist
+  (mapcar
+   (lambda (pair)                      ; cdr is the mark
+     (or (assoc (cdr pair)
+               '((read . "SEEN")
+                 (tick . "FLAGGED")
+                 (draft . "DRAFT")
+                 (recent . "RECENT")
+                 (reply . "ANSWERED")))
+        (cons (cdr pair)
+              (format "KEYWORD gnus-%s" (symbol-name (cdr pair))))))
+   (cons '(read . read) gnus-article-mark-lists)))
+
+(defun nnimap-mark-to-predicate (pred)
+  "Convert a Gnus mark (a symbol such as read, tick, expire) to a IMAP predicate.
+This is a string such as \"SEEN\", \"FLAGGED\", \"KEYWORD gnus-expire\",
+to be used within a IMAP SEARCH query."
+  (cdr (assq pred nnimap-mark-to-predicate-alist)))
+
+(defconst nnimap-mark-to-flag-alist
+  (mapcar
+   (lambda (pair)
+     (or (assoc (cdr pair)
+               '((read . "\\Seen")
+                 (tick . "\\Flagged")
+                 (draft . "\\Draft")
+                 (recent . "\\Recent")
+                 (reply . "\\Answered")))
+        (cons (cdr pair)
+              (format "gnus-%s" (symbol-name (cdr pair))))))
+   (cons '(read . read) gnus-article-mark-lists)))
+
+(defun nnimap-mark-to-flag-1 (preds)
+  (if (and (not (null preds)) (listp preds))
+      (cons (nnimap-mark-to-flag (car preds))
+           (nnimap-mark-to-flag (cdr preds)))
+    (cdr (assoc preds nnimap-mark-to-flag-alist))))
+
+(defun nnimap-mark-to-flag (preds &optional always-list make-string)
+  "Convert a Gnus mark (a symbol such as read, tick, expire) to a IMAP flag.
+This is a string such as \"\\Seen\", \"\\Flagged\", \"gnus-expire\", to
+be used in a STORE FLAGS command."
+  (let ((result (nnimap-mark-to-flag-1 preds)))
+    (setq result (if (and (or make-string always-list)
+                         (not (listp result)))
+                    (list result)
+                  result))
+    (if make-string
+       (mapconcat (lambda (flag)
+                    (if (listp flag)
+                        (mapconcat 'identity flag " ")
+                      flag))
+                  result " ")
+      result)))
+
+(defun nnimap-mark-permanent-p (mark &optional group)
+  "Return t iff MARK can be permanently (between IMAP sessions) saved on articles, in GROUP."
+  (imap-message-flag-permanent-p (nnimap-mark-to-flag mark)))
+
+(when nnimap-debug
+  (require 'trace)
+  (buffer-disable-undo (get-buffer-create nnimap-debug-buffer))
+  (mapcar (lambda (f) (trace-function-background f nnimap-debug-buffer))
+         '(
+           nnimap-possibly-change-server
+           nnimap-verify-uidvalidity
+           nnimap-find-minmax-uid
+           nnimap-before-find-minmax-bugworkaround
+           nnimap-possibly-change-group
+           ;;nnimap-replace-whitespace
+           nnimap-retrieve-headers-progress
+           nnimap-retrieve-which-headers
+           nnimap-group-overview-filename
+           nnimap-retrieve-headers-from-file
+           nnimap-retrieve-headers-from-server
+           nnimap-retrieve-headers
+           nnimap-open-connection
+           nnimap-open-server
+           nnimap-server-opened
+           nnimap-close-server
+           nnimap-request-close
+           nnimap-status-message
+           ;;nnimap-demule
+           nnimap-request-article-part
+           nnimap-request-article
+           nnimap-request-head
+           nnimap-request-body
+           nnimap-request-group
+           nnimap-close-group
+           nnimap-pattern-to-list-arguments
+           nnimap-request-list
+           nnimap-request-post
+           nnimap-retrieve-groups
+           nnimap-request-update-info-internal
+           nnimap-request-type
+           nnimap-request-set-mark
+           nnimap-split-to-groups
+           nnimap-split-find-rule
+           nnimap-split-find-inbox
+           nnimap-split-articles
+           nnimap-request-scan
+           nnimap-request-newgroups
+           nnimap-request-create-group
+           nnimap-time-substract
+           nnimap-date-days-ago
+           nnimap-request-expire-articles-progress
+           nnimap-request-expire-articles
+           nnimap-request-move-article
+           nnimap-request-accept-article
+           nnimap-request-delete-group
+           nnimap-request-rename-group
+           gnus-group-nnimap-expunge
+           gnus-group-nnimap-edit-acl
+           gnus-group-nnimap-edit-acl-done
+           nnimap-group-mode-hook
+           nnimap-mark-to-predicate
+           nnimap-mark-to-flag-1
+           nnimap-mark-to-flag
+           nnimap-mark-permanent-p
+           )))
+
+(provide 'nnimap)
+
+;;; nnimap.el ends here
diff --git a/lisp/nnir.el b/lisp/nnir.el
new file mode 100644 (file)
index 0000000..846db89
--- /dev/null
@@ -0,0 +1,1375 @@
+;;; nnir.el --- search mail with various search engines
+;; Copyright (C) 1998 Kai Großjohann
+
+;; Author: Kai Großjohann <grossjohann@ls6.cs.uni-dortmund.de>
+;; Keywords: news, mail, searching, ir, glimpse, wais
+
+;; This file is not part of GNU Emacs.
+
+;; This is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The most recent version of this can always be fetched from the
+;; following FTP site:
+;; ls6-ftp.cs.uni-dortmund.de:/pub/src/emacs
+
+;; This code is still in the development stage but I'd like other
+;; people to have a look at it.  Please do not hesitate to contact me
+;; with your ideas.
+
+;; What does it do?  Well, it allows you to index your mail using some
+;; search engine (freeWAIS-sf and Glimpse are currently supported),
+;; then type `G G' in the Group buffer and issue a query to the search
+;; engine.  You will then get a buffer which shows all articles
+;; matching the query, sorted by Retrieval Status Value (score).
+
+;; When looking at the retrieval result (in the Summary buffer) you
+;; can type `G T' (aka M-x gnus-summary-nnir-goto-thread RET) on an
+;; article.  You will be teleported into the group this article came
+;; from, showing the thread this article is part of.  (See below for
+;; restrictions.)
+
+;; The Lisp installation is simple: just put this file on your
+;; load-path, byte-compile it, and load it from ~/.gnus or something.
+;; This will install a new command `G G' in your Group buffer for
+;; searching your mail.  Note that you also need to configure a number
+;; of variables, as described below.
+
+;; Restrictions:
+;;
+;; * Currently, this expects that you use nnml or another
+;;   one-file-per-message backend.
+;; * It can only search one mail backend.
+;; * There are restrictions to the Glimpse setup.
+;; * There are restrictions to the Wais setup.
+;; * gnus-summary-nnir-goto-thread: Fetches whole group first, before
+;;   limiting to the right articles.  This is much too slow, of
+;;   course.  May issue a query for number of articles to fetch; you
+;;   must accept the default of all articles at this point or things
+;;   may break.
+
+;; The Lisp setup involves setting a few variables and setting up the
+;; search engine.  The first variable to set is `nnir-mail-backend'.
+;; For me, `gnus-secondary-select-methods' contains just one select
+;; method, and this is also what I put in `nnir-mail-backend'.  Type
+;; `C-h v nnir-mail-backend RET' for more information -- the variable
+;; documentation includes more details and a few examples.  The second
+;; variable to set is `nnir-search-engine'.  Choose one of the engines
+;; listed in `nnir-engines'.  (Actually `nnir-engines' is an alist,
+;; type `C-h v nnir-engines RET' for more information; this includes
+;; examples for setting `nnir-search-engine', too.)
+
+;; You must also set up a search engine.  I'll tell you about the two
+;; search engines currently supported:
+
+;; 1. freeWAIS-sf
+;;
+;; As always with freeWAIS-sf, you need a so-called `format file'.  I
+;; use the following file:
+;;
+;; ,-----
+;; | # Kai's format file for freeWAIS-sf for indexing mails.
+;; | # Each mail is in a file, much like the MH format.
+;; |
+;; | # Document separator should never match -- each file is a document.
+;; | record-sep: /^@this regex should never match@$/
+;; |
+;; | # Searchable fields specification.
+;; |
+;; | region: /^[sS]ubject:/ /^[sS]ubject: */
+;; |         subject "Subject header" stemming TEXT BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^([tT][oO]|[cC][cC]):/ /^([tT][oO]|[cC][cC]): */
+;; |         to "To and Cc headers" SOUNDEX BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^[fF][rR][oO][mM]:/ /^[fF][rR][oO][mM]: */
+;; |         from "From header" SOUNDEX BOTH
+;; | end: /^[^ \t]/
+;; |
+;; | region: /^$/
+;; |         stemming TEXT GLOBAL
+;; | end: /^@this regex should never match@$/
+;; `-----
+;;
+;; 1998-07-22: waisindex would dump core on me for large articles with
+;; the above settings.  I used /^$/ as the end regex for the global
+;; field.  That seemed to work okay.
+
+;; There is a Perl module called `WAIS.pm' which is available from
+;; CPAN as well as ls6-ftp.cs.uni-dortmund.de:/pub/wais/Perl.  This
+;; module comes with a nifty tool called `makedb', which I use for
+;; indexing.  Here's my `makedb.conf':
+;;
+;; ,-----
+;; | # Config file for makedb
+;; |
+;; | # Global options
+;; | waisindex = /usr/local/bin/waisindex
+;; | wais_opt  = -stem -t fields
+;; | # `-stem' option necessary when `stemming' is specified for the
+;; | # global field in the *.fmt file
+;; |
+;; | # Own variables
+;; | homedir = /home/kai
+;; |
+;; | # The mail database.
+;; | database        = mail
+;; | files           = `find $homedir/Mail -name \*[0-9] -print`
+;; | dbdir           = $homedir/.wais
+;; | limit           = 100
+;; `-----
+;;
+;; The Lisp setup involves the `nnir-wais-*' variables.  The most
+;; difficult to understand variable is probably
+;; `nnir-wais-remove-prefix'.  Here's what it does: the output of
+;; `waissearch' basically contains the file name and the (full)
+;; directory name.  As Gnus works with group names rather than
+;; directory names, the directory name is transformed into a group
+;; name as follows: first, a prefix is removed from the (full)
+;; directory name, then all `/' are replaced with `.'.  The variable
+;; `nnir-wais-remove-prefix' should contain a regex matching exactly
+;; this prefix.  It defaults to `$HOME/Mail/' (note the trailing
+;; slash).
+
+;; 2. Glimpse
+;;
+;; The code expects you to have one Glimpse index which contains all
+;; your mail files.  The Lisp setup involves setting the
+;; `nnir-glimpse-*' variables.  The most difficult to understand
+;; variable is probably `nnir-glimpse-remove-prefix', it corresponds
+;; to `nnir-wais-remove-prefix', see above.  The `nnir-glimpse-home'
+;; variable should be set to the value of the `-H' option which allows
+;; one to search this Glimpse index.  I have indexed my whole home
+;; directory with Glimpse, so I assume a default of `$HOME'.
+
+;; 3. Namazu
+;;
+;; The Namazu backend requires you to have one directory containing all
+;; index files, this is controlled by the `nnir-namazu-index-directory'
+;; variable.  To function the `nnir-namazu-remove-prefix' variable must
+;; also be correct, see the documentation for `nnir-wais-remove-prefix'
+;; above.
+;;
+;; It is particularly important not to pass any any switches to namazu
+;; that will change the output format.  Good switches to use include
+;; `--sort', `--ascending', `--early' and `--late'.  Refer to the Namazu
+;; documentation for further information on valid switches.
+;;
+;; To index my mail with the `mknmz' program I use the following
+;; configuration file:
+;;
+;; ,----
+;; | package conf;  # Don't remove this line!
+;; |
+;; | # Paths which will not be indexed. Don't use `^' or `$' anchors.
+;; | $EXCLUDE_PATH = "spam|sent";
+;; |
+;; | # Header fields which should be searchable. case-insensitive
+;; | $REMAIN_HEADER = "from|date|message-id|subject";
+;; |
+;; | # Searchable fields. case-insensitive
+;; | $SEARCH_FIELD = "from|date|message-id|subject";
+;; |
+;; | # The max length of a word.
+;; | $WORD_LENG_MAX = 128;
+;; |
+;; | # The max length of a field.
+;; | $MAX_FIELD_LENGTH = 256;
+;; `----
+;;
+;; My mail is stored in the directories ~/Mail/mail/, ~/Mail/lists/ and
+;; ~/Mail/archive/, so to index them I go to the directory set in
+;; `nnir-namazu-index-directory' and issue the following command.
+;;
+;;      mknmz --mailnews ~/Mail/archive/ ~/Mail/mail/ ~/Mail/lists/
+;;
+;; For maximum searching efficiency I have a cron job set to run this
+;; command every four hours.
+
+;; Developer information:
+
+;; I have tried to make the code expandable.  Basically, it is divided
+;; into two layers.  The upper layer is somewhat like the `nnvirtual'
+;; or `nnkiboze' backends: given a specification of what articles to
+;; show from another backend, it creates a group containing exactly
+;; those articles.  The lower layer issues a query to a search engine
+;; and produces such a specification of what articles to show from the
+;; other backend.
+
+;; The interface between the two layers consists of the single
+;; function `nnir-run-query', which just selects the appropriate
+;; function for the search engine one is using.  The input to
+;; `nnir-run-query' is a string, representing the query as input by
+;; the user.  The output of `nnir-run-query' is supposed to be a
+;; vector, each element of which should in turn be a three-element
+;; vector.  The first element should be group name of the article, the
+;; second element should be the article number, and the third element
+;; should be the Retrieval Status Value (RSV) as returned from the
+;; search engine.  An RSV is the score assigned to the document by the
+;; search engine.  For Boolean search engines like Glimpse, the RSV is
+;; always 1000 (or 1 or 100, or whatever you like).
+
+;; The sorting order of the articles in the summary buffer created by
+;; nnir is based on the order of the articles in the above mentioned
+;; vector, so that's where you can do the sorting you'd like.  Maybe
+;; it would be nice to have a way of displaying the search result
+;; sorted differently?
+
+;; So what do you need to do when you want to add another search
+;; engine?  You write a function that executes the query.  Temporary
+;; data from the search engine can be put in `nnir-tmp-buffer'.  This
+;; function should return the list of articles as a vector, as
+;; described above.  Then, you need to register this backend in
+;; `nnir-engines'.  Then, users can choose the backend by setting
+;; `nnir-search-engine'.
+
+;; Todo, or future ideas:
+
+;; * Make it so that Glimpse can also be called without `-F'.
+;;
+;; * It should be possible to restrict search to certain groups.
+;;
+;; * There is currently no error checking.
+;;
+;; * The summary buffer display is currently really ugly, with all the
+;;   added information in the subjects.  How could I make this
+;;   prettier?
+;;
+;; * A function which can be called from an nnir summary buffer which
+;;   teleports you into the group the current article came from and
+;;   shows you the whole thread this article is part of.
+;;   Implementation suggestions?
+;;   (1998-07-24: There is now a preliminary implementation, but
+;;   it is much too slow and quite fragile.)
+;;
+;; * Support other mail backends.  In particular, probably quite a few
+;;   people use nnfolder.  How would one go about searching nnfolders
+;;   and producing the right data needed?  The group name and the RSV
+;;   are simple, but what about the article number?
+;;
+;; * Support compressed mail files.  Probably, just stripping off the
+;;   `.gz' or `.Z' file name extension is sufficient.
+;;
+;; * Support a find/grep combination.
+;;
+;; * At least for imap, the query is performed twice.
+;;
+;; * Support multiple mail backends.  The information that is needed
+;;   by nnir could be put in the server parameters.  (Use sensible
+;;   default values, though: include the name of the backend in the
+;;   default value such that people do not have to mess with the
+;;   server parameters if they don't want to.)  It is not clear how to
+;;   do the user interface, though.  Hm.  Maybe offer the user a
+;;   completable list of backends to search?  Or use the
+;;   process-marked groups to find out which backends to search?  Or
+;;   always search all backends?
+;;
+
+;; Have you got other ideas?
+
+;;; Setup Code:
+
+(defconst nnir-version "1.72"
+  "Version of NNIR.")
+
+(require 'cl)
+(require 'nnoo)
+(require 'gnus-group)
+(require 'gnus-sum)
+(eval-and-compile
+  (require 'gnus-util))
+
+(nnoo-declare nnir)
+(nnoo-define-basics nnir)
+
+(gnus-declare-backend "nnir" 'mail)
+
+;;; Developer Extension Variable:
+
+(defvar nnir-engines
+  '((glimpse nnir-run-glimpse
+             ((group . "Group spec: ")))
+    (wais    nnir-run-waissearch
+             ())
+    (excite  nnir-run-excite-search
+            ())
+    (imap    nnir-run-imap
+             ())
+    (swish++ nnir-run-swish++
+             ((group . "Group spec: ")))
+    (swish-e nnir-run-swish-e
+             ((group . "Group spec: ")))
+    (namazu nnir-run-namazu
+            ()))
+"Alist of supported search engines.
+Each element in the alist is a three-element list (ENGINE FUNCTION ARGS).
+ENGINE is a symbol designating the searching engine.  FUNCTION is also
+a symbol, giving the function that does the search.  The third element
+ARGS is a list of cons pairs (PARAM . PROMPT).  When issuing a query,
+the FUNCTION will issue a query for each of the PARAMs, using PROMPT.
+
+The value of `nnir-search-engine' must be one of the ENGINE symbols.
+For example, use the following line for searching using freeWAIS-sf:
+    (setq nnir-search-engine 'wais)
+Use the following line if you read your mail via IMAP and your IMAP
+server supports searching:
+    (setq nnir-search-engine 'imap)
+Note that you have to set additional variables for most backends.  For
+example, the `wais' backend needs the variables `nnir-wais-program',
+`nnir-wais-database' and `nnir-wais-remove-prefix'.
+
+Add an entry here when adding a new search engine.")
+
+;;; User Customizable Variables:
+
+(defgroup nnir nil
+  "Search nnmh and nnml groups in Gnus with Glimpse, freeWAIS-sf, or EWS.")
+
+;; Mail backend.
+
+;; TODO:
+;; If `nil', use server parameters to find out which server to search. CCC
+;;
+(defcustom nnir-mail-backend '(nnml "")
+  "*Specifies which backend should be searched.
+More precisely, this is used to determine from which backend to fetch the
+messages found.
+
+This must be equal to an existing server, so maybe it is best to use
+something like the following:
+    (setq nnir-mail-backend (nth 0 gnus-secondary-select-methods))
+The above line works fine if the mail backend you want to search is
+the first element of gnus-secondary-select-methods (`nth' starts counting
+at zero)."
+  :type '(sexp)
+  :group 'nnir)
+
+;; Search engine to use.
+
+(defcustom nnir-search-engine 'wais
+  "*The search engine to use.  Must be a symbol.
+See `nnir-engines' for a list of supported engines, and for example
+settings of `nnir-search-engine'."
+  :type '(sexp)
+  :group 'nnir)
+
+;; Glimpse engine.
+
+(defcustom nnir-glimpse-program "glimpse"
+  "*Name of Glimpse executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-home (getenv "HOME")
+  "*Value of `-H' glimpse option.
+`~' and environment variables must be expanded, see the functions
+`expand-file-name' and `substitute-in-file-name'."
+  :type '(directory)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by Glimpse
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+For example, suppose that Glimpse returns file names such as
+\"/home/john/Mail/mail/misc/42\".  For this example, use the following
+setting:  (setq nnir-glimpse-remove-prefix \"/home/john/Mail/\")
+Note the trailing slash.  Removing this prefix gives \"mail/misc/42\".
+`nnir' knows to remove the \"/42\" and to replace \"/\" with \".\" to
+arrive at the correct group name, \"mail.misc\"."
+  :type '(regexp)
+  :group 'nnir)
+
+(defcustom nnir-glimpse-additional-switches '("-i")
+  "*A list of strings, to be given as additional arguments to glimpse.
+The switches `-H', `-W', `-l' and `-y' are always used -- calling
+glimpse without them does not make sense in our situation.
+Suggested elements to put here are `-i' and `-w'.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-glimpse-additional-switches \"-i -w\") ; wrong!
+Instead, use this:
+    (setq nnir-glimpse-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+;; freeWAIS-sf.
+
+(defcustom nnir-wais-program "waissearch"
+  "*Name of waissearch executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-wais-database (expand-file-name "~/.wais/mail")
+  "*Name of Wais database containing the mail.
+
+Note that this should be a file name without extension.  For example,
+if you have a file /home/john/.wais/mail.fmt, use this:
+    (setq nnir-wais-database \"/home/john/.wais/mail\")
+The string given here is passed to `waissearch -d' as-is."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-wais-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each directory name returned by waissearch
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is similar to `nnir-glimpse-remove-prefix', only for Wais,
+not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; EWS (Excite for Web Servers) engine.
+
+(defcustom nnir-excite-aquery-program "aquery.pl"
+  "*Name of the EWS query program.  Should be `aquery.pl' or a path to same."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-excite-collection "Mail"
+  "*Name of the EWS collection to search."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-excite-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by EWS
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for EWS, not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+(defcustom nnir-imap-default-charset nil
+  "*Name of the charset of the strings that appear in the search criteria."
+  :type '(choice (const nil) symbol)
+  :group 'nnir)
+
+;; Swish++.  Next three variables Copyright (C) 2000, 2001 Christoph
+;; Conrad <christoph.conrad@gmx.de>.
+;; Swish++ home page: http://homepage.mac.com/pauljlucas/software/swish/
+
+(defcustom nnir-swish++-configuration-file
+  (expand-file-name "~/Mail/swish++.conf")
+  "*Configuration file for swish++."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-swish++-program "search"
+  "*Name of swish++ search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-swish++-additional-switches '()
+    "*A list of strings, to be given as additional arguments to swish++.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-swish++-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-swish++-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-swish++-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by swish++
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for swish++, not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; Swish-E.  Next three variables Copyright (C) 2000 Christoph Conrad
+;; <christoph.conrad@gmx.de>.
+;; URL: http://sunsite.berkeley.edu/SWISH-E/
+;; New version: http://www.boe.es/swish-e
+
+(defcustom nnir-swish-e-index-file
+  (expand-file-name "~/Mail/index.swish-e")
+  "*Index file for swish-e."
+  :type '(file)
+  :group 'nnir)
+
+(defcustom nnir-swish-e-program "swish-e"
+  "*Name of swish-e search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-swish-e-additional-switches '()
+  "*A list of strings, to be given as additional arguments to swish-e.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-swish-e-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-swish-e-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-swish-e-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by swish-e
+in order to get a group name (albeit with / instead of .).  This is a
+regular expression.
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for swish-e, not Glimpse."
+  :type '(regexp)
+  :group 'nnir)
+
+;; Namazu engine, see <URL:http://ww.namazu.org/>
+
+(defcustom nnir-namazu-program "namazu"
+  "*Name of Namazu search executable."
+  :type '(string)
+  :group 'nnir)
+
+(defcustom nnir-namazu-index-directory (expand-file-name "~/Mail/namazu/")
+  "*Index directory for Namazu."
+  :type '(directory)
+  :group 'nnir)
+
+(defcustom nnir-namazu-additional-switches '()
+  "*A list of strings, to be given as additional arguments to namazu.
+The switches `-q', `-a', and `-s' are always used, very few other switches
+make any sense in this context.
+
+Note that this should be a list.  Ie, do NOT use the following:
+    (setq nnir-namazu-additional-switches \"-i -w\") ; wrong
+Instead, use this:
+    (setq nnir-namazu-additional-switches '(\"-i\" \"-w\"))"
+  :type '(repeat (string))
+  :group 'nnir)
+
+(defcustom nnir-namazu-remove-prefix (concat (getenv "HOME") "/Mail/")
+  "*The prefix to remove from each file name returned by Namazu
+in order to get a group name (albeit with / instead of .).
+
+This variable is very similar to `nnir-glimpse-remove-prefix', except
+that it is for Namazu, not Glimpse."
+  :type '(directory)
+  :group 'nnir)
+
+;;; Internal Variables:
+
+(defvar nnir-current-query nil
+  "Internal: stores current query (= group name).")
+
+(defvar nnir-current-server nil
+  "Internal: stores current server (does it ever change?).")
+
+(defvar nnir-current-group-marked nil
+  "Internal: stores current list of process-marked groups.")
+
+(defvar nnir-artlist nil
+  "Internal: stores search result.")
+
+(defvar nnir-tmp-buffer " *nnir*"
+  "Internal: temporary buffer.")
+
+;;; Code:
+
+;; Gnus glue.
+
+(defun gnus-group-make-nnir-group (extra-parms query)
+  "Create an nnir group.  Asks for query."
+  (interactive "P\nsQuery: ")
+  (let ((parms nil))
+    (if extra-parms
+        (setq parms (nnir-read-parms query))
+      (setq parms (list (cons 'query query))))
+    (gnus-group-read-ephemeral-group
+     (concat "nnir:" (prin1-to-string parms)) '(nnir "") t
+     (cons (current-buffer)
+           gnus-current-window-configuration)
+     nil)))
+
+;; Emacs 19 compatibility?
+(or (fboundp 'kbd) (defalias 'kbd 'read-kbd-macro))
+
+(defun nnir-group-mode-hook ()
+  (define-key gnus-group-mode-map
+    (if (fboundp 'read-kbd-macro)
+        (kbd "G G")
+      "GG")                             ; XEmacs 19 compat
+    'gnus-group-make-nnir-group))
+(add-hook 'gnus-group-mode-hook
+         (lambda ()
+           (unless (string-match "T-gnus" gnus-version)
+             (nnir-group-mode-hook))))
+
+
+
+;; Summary mode commands.
+
+(defun gnus-summary-nnir-goto-thread ()
+  "Only applies to nnir groups.  Go to group this article came from
+and show thread that contains this article."
+  (interactive)
+  (unless (eq 'nnir (car (gnus-find-method-for-group gnus-newsgroup-name)))
+    (error "Can't execute this command unless in nnir group."))
+  (let* ((cur (gnus-summary-article-number))
+         (backend-group (nnir-artlist-artitem-group nnir-artlist cur))
+         (backend-number (nnir-artlist-artitem-number nnir-artlist cur)))
+    (gnus-group-read-ephemeral-group
+     backend-group
+     nnir-mail-backend
+     t                                  ; activate
+     (cons (current-buffer)
+           'summary)                    ; window config
+     nil
+     (list backend-number))
+    (gnus-summary-limit (list backend-number))
+    (gnus-summary-refer-thread)))
+
+(if (fboundp 'eval-after-load)
+    (eval-after-load "gnus-sum"
+      '(define-key gnus-summary-goto-map
+         "T" 'gnus-summary-nnir-goto-thread))
+  (add-hook 'gnus-summary-mode-hook
+            (function (lambda ()
+                        (define-key gnus-summary-goto-map
+                          "T" 'gnus-summary-nnir-goto-thread)))))
+
+
+
+;; Gnus backend interface functions.
+
+(deffoo nnir-open-server (server &optional definitions)
+  ;; Just set the server variables appropriately.
+  (nnoo-change-server 'nnir server definitions))
+
+(deffoo nnir-request-group (group &optional server fast)
+  "GROUP is the query string."
+  (nnir-possibly-change-server server)
+  ;; Check for cache and return that if appropriate.
+  (if (and (equal group nnir-current-query)
+           (equal gnus-group-marked nnir-current-group-marked)
+           (or (null server)
+               (equal server nnir-current-server)))
+      nnir-artlist
+    ;; Cache miss.
+    (setq nnir-artlist (nnir-run-query group))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (if (zerop (length nnir-artlist))
+          (progn
+            (setq nnir-current-query nil
+                  nnir-current-server nil
+                  nnir-current-group-marked nil
+                  nnir-artlist nil)
+            (nnheader-report 'nnir "Search produced empty results."))
+        ;; Remember data for cache.
+        (setq nnir-current-query group)
+        (when server (setq nnir-current-server server))
+        (setq nnir-current-group-marked gnus-group-marked)
+        (nnheader-insert "211 %d %d %d %s\n"
+                         (nnir-artlist-length nnir-artlist) ; total #
+                         1              ; first #
+                         (nnir-artlist-length nnir-artlist) ; last #
+                         group)))))     ; group name
+
+(deffoo nnir-retrieve-headers (articles &optional group server fetch-old)
+  (save-excursion
+    (let ((artlist (copy-sequence articles))
+          (idx 1)
+          (art nil)
+          (artitem nil)
+          (artgroup nil) (artno nil)
+          (artrsv nil)
+          (artfullgroup nil)
+          (novitem nil)
+          (novdata nil)
+          (foo nil))
+      (while (not (null artlist))
+        (setq art (car artlist))
+        (or (numberp art)
+            (nnheader-report
+             'nnir
+             "nnir-retrieve-headers doesn't grok message ids: %s"
+             art))
+        (setq artitem (nnir-artlist-article nnir-artlist art))
+        (setq artrsv (nnir-artitem-rsv artitem))
+        (setq artgroup (nnir-artitem-group artitem))
+        (setq artno (nnir-artitem-number artitem))
+        (setq artfullgroup (nnir-group-full-name artgroup))
+        ;; retrieve NOV or HEAD data for this article, transform into
+        ;; NOV data and prepend to `novdata'
+        (set-buffer nntp-server-buffer)
+        (case (setq foo (gnus-retrieve-headers (list artno) artfullgroup nil))
+          (nov
+           (goto-char (point-min))
+           (setq novitem (nnheader-parse-nov))
+           (unless novitem
+             (pop-to-buffer nntp-server-buffer)
+             (error
+              "nnheader-parse-nov returned nil for article %s in group %s"
+              artno artfullgroup)))
+          (headers
+           (goto-char (point-min))
+           (setq novitem (nnheader-parse-head))
+           (unless novitem
+             (pop-to-buffer nntp-server-buffer)
+             (error
+              "nnheader-parse-head returned nil for article %s in group %s"
+              artno artfullgroup)))
+          (t (nnheader-report 'nnir "Don't support header type %s." foo)))
+        ;; replace article number in original group with article number
+        ;; in nnir group
+        (mail-header-set-number novitem idx)
+        (mail-header-set-from novitem
+                              (mail-header-from novitem))
+        (mail-header-set-subject
+         novitem
+         (format "[%d: %s/%d] %s"
+                 artrsv artgroup artno
+                 (mail-header-subject novitem)))
+        ;;-(mail-header-set-extra novitem nil)
+        (push novitem novdata)
+        (setq artlist (cdr artlist))
+        (setq idx (1+ idx)))
+      (setq novdata (nreverse novdata))
+      (set-buffer nntp-server-buffer) (erase-buffer)
+      (mapcar 'nnheader-insert-nov novdata)
+      'nov)))
+
+(deffoo nnir-request-article (article
+                              &optional group server to-buffer)
+  (save-excursion
+    (let* ((artitem (nnir-artlist-article nnir-artlist
+                                          article))
+           (artgroup (nnir-artitem-group artitem))
+           (artno (nnir-artitem-number artitem))
+           ;; Bug?
+           ;; Why must we bind nntp-server-buffer here?  It won't
+           ;; work if `buf' is used, say.  (Of course, the set-buffer
+           ;; line below must then be updated, too.)
+           (nntp-server-buffer (or to-buffer nntp-server-buffer)))
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (message "Requesting article %d from group %s"
+               artno
+               (nnir-group-full-name artgroup))
+      (gnus-request-article artno (nnir-group-full-name artgroup)
+                            nntp-server-buffer)
+      (cons artgroup artno))))
+
+
+(nnoo-define-skeleton nnir)
+
+;;; Search Engine Interfaces:
+
+;; Glimpse interface.
+(defun nnir-run-glimpse (query &optional group)
+  "Run given query against glimpse.  Returns a vector of (group name, file name)
+pairs (also vectors, actually)."
+  (save-excursion
+    (let ((artlist nil)
+          (groupspec (cdr (assq 'group query)))
+          (qstring (cdr (assq 'query query))))
+      (when (and group groupspec)
+        (error (concat "It does not make sense to use a group spec"
+                       " with process-marked groups.")))
+      (when group
+        (setq groupspec (gnus-group-real-name group)))
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (if groupspec
+          (message "Doing glimpse query %s on %s..." query groupspec)
+        (message "Doing glimpse query %s..." query))
+      (let* ((cp-list
+              `( ,nnir-glimpse-program
+                 nil                    ; input from /dev/null
+                 t                      ; output
+                 nil                    ; don't redisplay
+                 "-H" ,nnir-glimpse-home ; search home dir
+                 "-W"                   ; match pattern in file
+                 "-l" "-y"              ; misc options
+                 ,@nnir-glimpse-additional-switches
+                 "-F" ,nnir-glimpse-remove-prefix ; restrict output to mail
+                 ,qstring               ; the query, in glimpse format
+                ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-glimpse-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run glimpse: %s" exitstatus)
+          ;; Glimpse failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+      (when groupspec
+        (keep-lines groupspec))
+      (if groupspec
+          (message "Doing glimpse query %s on %s...done" query groupspec)
+        (message "Doing glimpse query %s...done" query))
+      (sit-for 0)
+      ;; CCC: The following work of extracting group name and article
+      ;; number from the Glimpse output can probably better be done by
+      ;; just going through the buffer once, and plucking out the
+      ;; right information from each line.
+      ;; remove superfluous stuff from glimpse output
+      (goto-char (point-min))
+      (delete-non-matching-lines "/[0-9]+$")
+      ;;(delete-matching-lines "\\.overview~?$")
+      (goto-char (point-min))
+      (while (re-search-forward (concat "^" nnir-glimpse-remove-prefix) nil t)
+        (replace-match ""))
+      ;; separate group name from article number with \t
+      ;; XEmacs compatible version
+      (goto-char (point-max))
+      (while (re-search-backward "/[0-9]+$" nil t)
+        (delete-char 1 nil)
+        (insert-char ?\t 1))
+; Emacs compatible version
+;      (goto-char (point-min))
+;      (while (re-search-forward "\\(/\\)[0-9]+$" nil t)
+;        (replace-match "\t" t t nil 1))
+      ;; replace / with . in group names
+      (subst-char-in-region (point-min) (point-max) ?/ ?. t)
+      ;; massage buffer to contain some Lisp;
+      ;; this depends on the artlist encoding internals
+      ;; maybe this dependency should be removed?
+      (goto-char (point-min))
+      (while (not (eobp))
+        (insert "[\"")
+        (skip-chars-forward "^\t")
+        (insert "\" ")
+        (end-of-line)
+        (insert " 1000 ]")              ; 1000 = score
+        (forward-line 1))
+      (insert "])\n")
+      (goto-char (point-min))
+      (insert "(setq artlist [\n")
+      (eval-buffer)
+      (sort* artlist
+             (function (lambda (x y)
+                         (if (string-lessp (nnir-artitem-group x)
+                                           (nnir-artitem-group y))
+                             t
+                           (< (nnir-artitem-number x)
+                              (nnir-artitem-number y))))))
+      )))
+
+;; freeWAIS-sf interface.
+(defun nnir-run-waissearch (query &optional group)
+  "Run given query agains waissearch.  Returns vector of (group name, file name)
+pairs (also vectors, actually)."
+  (when group
+    (error "The freeWAIS-sf backend cannot search specific groups."))
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+          (artlist nil)
+          (score nil) (artno nil) (dirnam nil) (group nil))
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (message "Doing WAIS query %s..." query)
+      (call-process nnir-wais-program
+                    nil                 ; input from /dev/null
+                    t                   ; output to current buffer
+                    nil                 ; don't redisplay
+                    "-d" nnir-wais-database ; database to search
+                    qstring)
+      (message "Massaging waissearch output...")
+      ;; remove superfluous lines
+      (keep-lines "Score:")
+      ;; extract data from result lines
+      (goto-char (point-min))
+      (while (re-search-forward
+              "Score: +\\([0-9]+\\).*'\\([0-9]+\\) +\\([^']+\\)/'" nil t)
+        (setq score (match-string 1)
+              artno (match-string 2)
+              dirnam (match-string 3))
+        (unless (string-match nnir-wais-remove-prefix dirnam)
+          (nnheader-report 'nnir "Dir name %s doesn't contain prefix %s"
+                           dirnam nnir-wais-remove-prefix))
+        (setq group (substitute ?. ?/ (replace-match "" t t dirnam)))
+        (push (vector group
+                      (string-to-int artno)
+                      (string-to-int score))
+              artlist))
+      (message "Massaging waissearch output...done")
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; EWS (Excite for Web Servers) interface
+(defun nnir-run-excite-search (query &optional group)
+  "Run a given query against EWS.  Returns vector of (group name, file name)
+pairs (also vectors, actually)."
+  (when group
+    (error "Searching specific groups not implemented for EWS."))
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         artlist group article-num article)
+      (setq nnir-current-query query)
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (message "Doing EWS query %s..." qstring)
+      (call-process nnir-excite-aquery-program
+                   nil                 ; input from /dev/null
+                   t                   ; output to current buffer
+                   nil                 ; don't redisplay
+                   nnir-excite-collection
+                   (if (string= (substring qstring 0 1) "(")
+                       qstring
+                     (format "(concept %s)" qstring)))
+      (message "Gathering query output...")
+
+      (goto-char (point-min))
+      (while (re-search-forward
+             "^[0-9]+\\s-[0-9]+\\s-[0-9]+\\s-\\(\\S-*\\)" nil t)
+       (setq article (match-string 1))
+       (unless (string-match
+                (concat "^" (regexp-quote nnir-excite-remove-prefix)
+                        "\\(.*\\)/\\([0-9]+\\)") article)
+         (nnheader-report 'nnir "Dir name %s doesn't contain prefix %s"
+                          article nnir-excite-remove-prefix))
+       (setq group (substitute ?. ?/ (match-string 1 article)))
+       (setq article-num (match-string 2 article))
+       (setq artlist (vconcat artlist (vector (vector group
+                                                      (string-to-int article-num)
+                                                      1000)))))
+      (message "Gathering query output...done")
+      artlist)))
+
+;; IMAP interface.  The following function is Copyright (C) 1998 Simon
+;; Josefsson <jas@pdc.kth.se>.
+;; todo:
+;; nnir invokes this two (2) times???!
+;; we should not use nnimap at all but open our own server connection
+;; we should not LIST * but use nnimap-list-pattern from defs
+;; send queries as literals
+;; handle errors
+
+(eval-when-compile
+  (defvar nnimap-server-buffer))
+
+(defun nnir-run-imap (query &optional group)
+  (require 'imap)
+  (require 'nnimap)
+  (require 'mm-util)
+  (unless group
+    (error "Must specify groups for IMAP searching."))
+  (save-excursion
+    (let ((qstring (cdr (assq 'query query)))
+         (server (cadr nnir-mail-backend))
+         (defs (caddr nnir-mail-backend))
+         artlist buf)
+      (message "Opening server %s" server)
+      (condition-case ()
+         (when (nnimap-open-server server defs) ;; xxx
+           (setq buf nnimap-server-buffer) ;; xxx
+           (message "Searching %s..." group)
+            (let ((arts 0)
+                  (mbx (gnus-group-real-name group))
+                 (multibyte-p (mm-multibyte-p))
+                 charset coding-system)
+              (when (imap-mailbox-select mbx nil buf)
+               (with-temp-buffer
+                 (if multibyte-p
+                     (mm-enable-multibyte))
+                 (insert qstring)
+                 (setq charset (car (mm-find-mime-charset-region
+                                     (point-min)(point-max)))))
+               (unless charset
+                 (setq charset nnir-imap-default-charset))
+                (mapcar
+                 (lambda (artnum)
+                   (push (vector mbx artnum 1) artlist)
+                   (setq arts (1+ arts)))
+                (if (and (not (eq charset 'us-ascii))
+                         (setq coding-system (mm-charset-to-coding-system
+                                              charset)))
+                    (imap-search
+                     (concat "CHARSET " (symbol-name charset) " TEXT \""
+                             (mm-encode-coding-string qstring coding-system)
+                             "\"") buf)
+                  (imap-search (concat "TEXT \"" qstring "\"") buf)))
+                (message "Searching %s... %d matches" mbx arts)))
+            (message "Searching %s...done" group))
+        (quit nil))
+      (reverse artlist))))
+
+;; Swish++ interface.  The following function is Copyright (C) 2000,
+;; 2001 Christoph Conrad <christoph.conrad@gmx.de>.
+;; -cc- Todo
+;; Search by
+;; - group
+;; Sort by
+;; - rank (default)
+;; - article number
+;; - file size
+;; - group
+(defun nnir-run-swish++ (query &optional group)
+  "Run given query against swish++.
+Returns a vector of (group name, file name) pairs (also vectors,
+actually).
+
+Tested with swish++ 4.7 on GNU/Linux and with with swish++ 5.0b2 on
+Windows NT 4.0."
+
+  (when group
+    (error "The swish++ backend cannot search specific groups."))
+
+  (save-excursion
+    (let ( (qstring (cdr (assq 'query query)))
+          (groupspec (cdr (assq 'group query)))
+           (artlist nil)
+           (score nil) (artno nil) (dirnam nil) (group nil) )
+
+      (when (equal "" qstring)
+        (error "swish++: You didn't enter anything."))
+
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+
+      (if groupspec
+          (message "Doing swish++ query %s on %s..." qstring groupspec)
+        (message "Doing swish++ query %s..." qstring))
+
+      (let* ((cp-list `( ,nnir-swish++-program
+                         nil            ; input from /dev/null
+                         t              ; output
+                         nil            ; don't redisplay
+                         "--config-file" ,nnir-swish++-configuration-file
+                         ,@nnir-swish++-additional-switches
+                         ,qstring       ; the query, in swish++ format
+                         ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-swish++-program
+                         (mapconcat 'identity (cddddr cp-list) " "));; ???
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run swish++: %s" exitstatus)
+          ;; swish++ failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; The results are output in the format of:
+      ;; V 4.7 Linux
+      ;; rank relative-path-name file-size file-title
+      ;; V 5.0b2:
+      ;; rank relative-path-name file-size topic??
+      ;; where rank is an integer from 1 to 100.
+      (goto-char (point-min))
+      (while (re-search-forward
+              "\\(^[0-9]+\\) \\([^ ]+\\) [0-9]+ \\(.*\\)$" nil t)
+        (setq score (match-string 1)
+              artno (file-name-nondirectory (match-string 2))
+              dirnam (file-name-directory (match-string 2)))
+
+        ;; don't match directories
+        (when (string-match "^[0-9]+$" artno)
+          (when (not (null dirnam))
+
+           ; maybe limit results to matching groups.
+           (when (or (not groupspec)
+                     (string-match groupspec dirnam))
+
+             ;; remove nnir-swish++-remove-prefix from beginning of dirname
+             (when (string-match (concat "^" nnir-swish++-remove-prefix)
+                                 dirnam)
+               (setq dirnam (replace-match "" t t dirnam)))
+
+             (setq dirnam (substring dirnam 0 -1))
+             ;; eliminate all ".", "/", "\" from beginning. Always matches.
+             (string-match "^[./\\]*\\(.*\\)$" dirnam)
+             ;; "/" -> "."
+             (setq group (substitute ?. ?/ (match-string 1 dirnam)))
+             ;; "\\" -> "."
+             (setq group (substitute ?. ?\\ group))
+
+             (push (vector group
+                           (string-to-int artno)
+                           (string-to-int score))
+                   artlist)))))
+
+      (message "Massaging swish++ output...done")
+
+      ;; Sort by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; Swish-E interface.  The following function is Copyright (C) 2000,
+;; 2001 by Christoph Conrad <christoph.conrad@gmx.de>.
+(defun nnir-run-swish-e (query &optional group)
+  "Run given query against swish-e.
+Returns a vector of (group name, file name) pairs (also vectors,
+actually).
+
+Tested with swish-e-2.0.1 on Windows NT 4.0."
+
+  ;; swish-e crashes with empty parameter to "-w" on commandline...
+  (when group
+    (error "The swish-e backend cannot search specific groups."))
+
+  (save-excursion
+    (let ( (qstring (cdr (assq 'query query)))
+           (artlist nil)
+           (score nil) (artno nil) (dirnam nil) (group nil) )
+
+      (when (equal "" qstring)
+        (error "swish-e: You didn't enter anything."))
+
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+
+      (message "Doing swish-e query %s..." query)
+      (let* ((cp-list `( ,nnir-swish-e-program
+                         nil            ; input from /dev/null
+                         t              ; output
+                         nil            ; don't redisplay
+                         "-f" ,nnir-swish-e-index-file
+                         ,@nnir-swish-e-additional-switches
+                         "-w"
+                         ,qstring       ; the query, in swish-e format
+                         ))
+             (exitstatus
+              (progn
+                (message "%s args: %s" nnir-swish-e-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+                (apply 'call-process cp-list))))
+        (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run swish-e: %s" exitstatus)
+          ;; swish-e failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; The results are output in the format of:
+      ;; rank path-name file-title file-size
+      (goto-char (point-min))
+      (while (re-search-forward
+              "\\(^[0-9]+\\) \\([^ ]+\\) \"\\([^\"]+\\)\" [0-9]+$" nil t)
+        (setq score (match-string 1)
+              artno (match-string 3)
+              dirnam (file-name-directory (match-string 2)))
+
+        ;; don't match directories
+        (when (string-match "^[0-9]+$" artno)
+          (when (not (null dirnam))
+
+            ;; remove nnir-swish-e-remove-prefix from beginning of dirname
+            (when (string-match (concat "^" nnir-swish-e-remove-prefix)
+                                dirnam)
+              (setq dirnam (replace-match "" t t dirnam)))
+
+            (setq dirnam (substring dirnam 0 -1))
+            ;; eliminate all ".", "/", "\" from beginning. Always matches.
+            (string-match "^[./\\]*\\(.*\\)$" dirnam)
+            ;; "/" -> "."
+            (setq group (substitute ?. ?/ (match-string 1 dirnam)))
+            ;; Windows "\\" -> "."
+            (setq group (substitute ?. ?\\ group))
+
+            (push (vector group
+                          (string-to-int artno)
+                          (string-to-int score))
+                  artlist))))
+
+      (message "Massaging swish-e output...done")
+
+      ;; Sort by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;; Namazu interface
+(defun nnir-run-namazu (query &optional group)
+  "Run given query against Namazu.  Returns a vector of (group name, file name)
+pairs (also vectors, actually).
+
+Tested with Namazu 2.0.6 on a GNU/Linux system."
+  (when group
+    (error "The Namazu backend cannot search specific groups"))
+  (save-excursion
+    (let (
+          (artlist nil)
+          (qstring (cdr (assq 'query query)))
+          (score nil)
+          (group nil)
+          (article nil)
+          )
+      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (erase-buffer)
+      (let* ((cp-list
+              `( ,nnir-namazu-program
+                 nil              ; input from /dev/null
+                 t                ; output
+                 nil              ; don't redisplay
+                 "-q"             ; don't be verbose
+                 "-a"             ; show all matches
+                 "-s"             ; use short format
+                 ,@nnir-namazu-additional-switches
+                 ,qstring         ; the query, in namazu format
+                 ,nnir-namazu-index-directory ; index directory
+                 ))
+             (exitstatus
+             (let ((process-environment (copy-sequence process-environment)))
+               ;; Disable locale.
+               (setenv "LC_ALL" "C")
+                (message "%s args: %s" nnir-namazu-program
+                         (mapconcat 'identity (cddddr cp-list) " "))
+               (apply 'call-process cp-list))))
+       (unless (or (null exitstatus)
+                    (zerop exitstatus))
+          (nnheader-report 'nnir "Couldn't run namazu: %s" exitstatus)
+          ;; Namazu failure reason is in this buffer, show it if
+          ;; the user wants it.
+          (when (> gnus-verbose 6)
+            (display-buffer nnir-tmp-buffer))))
+
+      ;; Namazu output looks something like this:
+      ;; 2. Re: Gnus agent expire broken (score: 55)
+      ;; /home/henrik/Mail/mail/sent/1310 (4,138 bytes)
+
+      (goto-char (point-min))
+      (while (re-search-forward
+              "^\\([0-9]+\\.\\).*\\((score: \\([0-9]+\\)\\))\n\\([^ ]+\\)"
+              nil t)
+        (setq score (match-string 3)
+              group (file-name-directory (match-string 4))
+              article (file-name-nondirectory (match-string 4)))
+
+        ;; make sure article and group is sane
+        (when (and (string-match "^[0-9]+$" article)
+                   (not (null group)))
+          (when (string-match (concat "^" nnir-namazu-remove-prefix) group)
+            (setq group (replace-match "" t t group)))
+
+          ;; remove trailing slash from groupname
+          (setq group (substring group 0 -1))
+
+          ;; stuff results into artlist vector
+          (push (vector (substitute ?. ?/ group)
+                        (string-to-int article)
+                        (string-to-int score)) artlist)))
+
+      ;; sort artlist by score
+      (apply 'vector
+             (sort* artlist
+                    (function (lambda (x y)
+                                (> (nnir-artitem-rsv x)
+                                   (nnir-artitem-rsv y)))))))))
+
+;;; Util Code:
+
+(defun nnir-read-parms (query)
+  "Reads additional search parameters according to `nnir-engines'."
+  (let ((parmspec (caddr (assoc nnir-search-engine nnir-engines))))
+    (cons (cons 'query query)
+          (mapcar 'nnir-read-parm parmspec))))
+
+(defun nnir-read-parm (parmspec)
+  "Reads a single search parameter.
+`parmspec' is a cons cell, the car is a symbol, the cdr is a prompt."
+  (let ((sym (car parmspec))
+        (prompt (cdr parmspec)))
+    (cons sym (read-string prompt))))
+
+(defun nnir-run-query (query)
+  "Invoke appropriate search engine function (see `nnir-engines').
+If some groups were process-marked, run the query for each of the groups
+and concat the results."
+  (let ((search-func (cadr (assoc nnir-search-engine nnir-engines)))
+        (q (car (read-from-string query))))
+    (if gnus-group-marked
+        (apply 'append
+               (mapcar (lambda (x)
+                         (funcall search-func q x))
+                       gnus-group-marked))
+      (funcall search-func q nil))))
+
+(defun nnir-group-full-name (shortname)
+  "For the given group name, return a full Gnus group name.
+The Gnus backend/server information is added."
+  (gnus-group-prefixed-name shortname nnir-mail-backend))
+
+(defun nnir-possibly-change-server (server)
+  (unless (and server (nnir-server-opened server))
+    (nnir-open-server server)))
+
+
+;; Data type article list.
+
+(defun nnir-artlist-length (artlist)
+  "Returns number of articles in artlist."
+  (length artlist))
+
+(defun nnir-artlist-article (artlist n)
+  "Returns from ARTLIST the Nth artitem (counting starting at 1)."
+  (elt artlist (1- n)))
+
+(defun nnir-artitem-group (artitem)
+  "Returns the group from the ARTITEM."
+  (elt artitem 0))
+
+(defun nnir-artlist-artitem-group (artlist n)
+  "Returns from ARTLIST the group of the Nth artitem (counting from 1)."
+  (nnir-artitem-group (nnir-artlist-article artlist n)))
+
+(defun nnir-artitem-number (artitem)
+  "Returns the number from the ARTITEM."
+  (elt artitem 1))
+
+(defun nnir-artlist-artitem-number (artlist n)
+  "Returns from ARTLIST the number of the Nth artitem (counting from 1)."
+  (nnir-artitem-number (nnir-artlist-article artlist n)))
+
+(defun nnir-artitem-rsv (artitem)
+  "Returns the Retrieval Status Value (RSV, score) from the ARTITEM."
+  (elt artitem 2))
+
+(defun nnir-artlist-artitem-rsv (artlist n)
+  "Returns from ARTLIST the Retrieval Status Value of the Nth artitem
+(counting from 1)."
+  (nnir-artitem-rsv (nnir-artlist-article artlist n)))
+
+;; unused?
+(defun nnir-artlist-groups (artlist)
+  "Returns a list of all groups in the given ARTLIST."
+  (let ((res nil)
+        (with-dups nil))
+    ;; from each artitem, extract group component
+    (setq with-dups (mapcar 'nnir-artitem-group artlist))
+    ;; remove duplicates from above
+    (mapcar (function (lambda (x) (add-to-list 'res x)))
+            with-dups)
+    res))
+
+
+;; The end.
+(provide 'nnir)
index 54c3ee0..07aa565 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nnkiboze.el --- select virtual news access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'nntp)
 (require 'nnheader)
 (require 'gnus)
 (require 'gnus-score)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nnkiboze)
 (defvoo nnkiboze-directory (nnheader-concat gnus-directory "kiboze/")
@@ -55,6 +59,9 @@
 (defvoo nnkiboze-regexp nil
   "Regexp for matching component groups.")
 
+(defvoo nnkiboze-file-coding-system nnheader-text-coding-system
+  "Coding system for nnkiboze files.")
+
 \f
 
 (defconst nnkiboze-version "nnkiboze 1.0")
@@ -80,7 +87,8 @@
          (save-excursion
            (set-buffer nntp-server-buffer)
            (erase-buffer)
-           (nnheader-insert-file-contents nov)
+           (let ((nnheader-file-coding-system nnkiboze-file-coding-system))
+             (nnheader-insert-file-contents nov))
            (nnheader-nov-delete-outside-range
             (car articles) (car (last articles)))
            'nov))))))
       ;; article fetching by message-id at all.
       (nntp-request-article article newsgroup gnus-nntp-server buffer)
     (let* ((header (gnus-summary-article-header article))
-          (xref (mail-header-xref header)))
+          (xref (mail-header-xref header))
+          num group)
       (unless xref
        (error "nnkiboze: No xref"))
       (unless (string-match " \\([^ ]+\\):\\([0-9]+\\)" xref)
        (error "nnkiboze: Malformed xref"))
-      (gnus-request-article (string-to-int (match-string 2 xref))
-                           (match-string 1 xref)
-                           buffer))))
+      (setq num (string-to-int (match-string 2 xref))
+           group (match-string 1 xref))
+      (or (with-current-buffer buffer
+           (or (and gnus-use-cache (gnus-cache-request-article num group))
+               (gnus-agent-request-article num group)))
+         (gnus-request-article num group buffer)))))
 
 (deffoo nnkiboze-request-scan (&optional group server)
+  (nnkiboze-possibly-change-group group)
   (nnkiboze-generate-group (concat "nnkiboze:" group)))
 
 (deffoo nnkiboze-request-group (group &optional server dont-check)
       (save-excursion
        (set-buffer nntp-server-buffer)
        (erase-buffer)
+       (unless (file-exists-p nov-file)
+         (nnkiboze-request-scan group))
        (if (not (file-exists-p nov-file))
            (nnheader-report 'nnkiboze "Can't select group %s" group)
-         (nnheader-insert-file-contents nov-file)
+         (let ((nnheader-file-coding-system nnkiboze-file-coding-system))
+           (nnheader-insert-file-contents nov-file))
          (if (zerop (buffer-size))
              (nnheader-insert "211 0 0 0 %s\n" group)
            (goto-char (point-min))
   ;; Remove NOV lines of articles that are marked as read.
   (when (and (file-exists-p (nnkiboze-nov-file-name))
             nnkiboze-remove-read-articles)
-    (nnheader-temp-write (nnkiboze-nov-file-name)
-      (let ((cur (current-buffer)))
-       (nnheader-insert-file-contents (nnkiboze-nov-file-name))
-       (goto-char (point-min))
-       (while (not (eobp))
-         (if (not (gnus-article-read-p (read cur)))
-             (forward-line 1)
-           (gnus-delete-line))))))
-  (setq nnkiboze-current-group nil))
+    (let ((coding-system-for-write nnkiboze-file-coding-system)
+         (output-coding-system nnkiboze-file-coding-system))
+      (with-temp-file (nnkiboze-nov-file-name)
+       (let ((cur (current-buffer))
+             (nnheader-file-coding-system nnkiboze-file-coding-system))
+         (nnheader-insert-file-contents (nnkiboze-nov-file-name))
+         (goto-char (point-min))
+         (while (not (eobp))
+           (if (not (gnus-article-read-p (read cur)))
+               (forward-line 1)
+             (gnus-delete-line))))))
+    (setq nnkiboze-current-group nil)))
 
 (deffoo nnkiboze-open-server (server &optional defs)
   (unless (assq 'nnkiboze-regexp defs)
 (deffoo nnkiboze-request-delete-group (group &optional force server)
   (nnkiboze-possibly-change-group group)
   (when force
-     (let ((files (list (nnkiboze-nov-file-name)
-                       (concat nnkiboze-directory
-                                (nnheader-translate-file-chars
-                                 (concat group ".newsrc")))
-                       (nnkiboze-score-file group))))
-       (while files
-        (and (file-exists-p (car files))
-             (file-writable-p (car files))
-             (delete-file (car files)))
-        (setq files (cdr files)))))
-  (setq nnkiboze-current-group nil))
+    (let ((files (nconc
+                 (nnkiboze-score-file group)
+                 (list (nnkiboze-nov-file-name)
+                       (nnkiboze-nov-file-name ".newsrc")))))
+      (while files
+       (and (file-exists-p (car files))
+            (file-writable-p (car files))
+            (delete-file (car files)))
+       (setq files (cdr files)))))
+  (setq nnkiboze-current-group nil)
+  t)
 
 (nnoo-define-skeleton nnkiboze)
 
 
 ;;;###autoload
 (defun nnkiboze-generate-groups ()
-  "Usage: emacs -batch -l nnkiboze -f nnkiboze-generate-groups
+  "\"Usage: emacs -batch -l nnkiboze -f nnkiboze-generate-groups\".
 Finds out what articles are to be part of the nnkiboze groups."
   (interactive)
   (let ((nnmail-spool-file nil)
+       (mail-sources nil)
        (gnus-use-dribble-file nil)
        (gnus-read-active-file t)
        (gnus-expert-user t))
@@ -196,7 +216,10 @@ Finds out what articles are to be part of the nnkiboze groups."
       (when (string-match "nnkiboze" (gnus-info-group info))
        ;; For each kiboze group, we call this function to generate
        ;; it.
-       (nnkiboze-generate-group (gnus-info-group info))))))
+       (nnkiboze-generate-group (gnus-info-group info) t))))
+  (save-excursion
+    (set-buffer gnus-group-buffer)
+    (gnus-group-list-groups)))
 
 (defun nnkiboze-score-file (group)
   (list (expand-file-name
@@ -205,126 +228,142 @@ Finds out what articles are to be part of the nnkiboze groups."
                  (concat (nnkiboze-prefixed-name nnkiboze-current-group)
                          "." gnus-score-file-suffix))))))
 
-(defun nnkiboze-generate-group (group)
+(defun nnkiboze-generate-group (group &optional inhibit-list-groups)
   (let* ((info (nth 2 (gnus-gethash group gnus-newsrc-hashtb)))
-        (newsrc-file (concat nnkiboze-directory 
-                              (nnheader-translate-file-chars
-                               (concat group ".newsrc"))))
+        (newsrc-file (concat nnkiboze-directory
+                             (nnheader-translate-file-chars
+                              (concat group ".newsrc"))))
         (nov-file (concat nnkiboze-directory
-                           (nnheader-translate-file-chars
-                            (concat group ".nov"))))
+                          (nnheader-translate-file-chars
+                           (concat group ".nov"))))
         method nnkiboze-newsrc gname newsrc active
         ginfo lowest glevel orig-info nov-buffer
         ;; Bind various things to nil to make group entry faster.
         (gnus-expert-user t)
         (gnus-large-newsgroup nil)
         (gnus-score-find-score-files-function 'nnkiboze-score-file)
+        ;; Use only nnkiboze-score-file!
+        (gnus-score-use-all-scores nil)
+        (gnus-use-scoring t)
         (gnus-verbose (min gnus-verbose 3))
-        gnus-select-group-hook gnus-summary-prepare-hook
+        gnus-select-group-hook gnus-summary-prepare-hook
         gnus-thread-sort-functions gnus-show-threads
-        gnus-visual gnus-suppress-duplicates)
+        gnus-visual gnus-suppress-duplicates num-unread)
     (unless info
       (error "No such group: %s" group))
     ;; Load the kiboze newsrc file for this group.
-    (when (file-exists-p newsrc-file)
-      (load newsrc-file))
-    (nnheader-temp-write nov-file
-      (when (file-exists-p nov-file)
-       (insert-file-contents nov-file))
-      (setq nov-buffer (current-buffer))
-      ;; Go through the active hashtb and add new all groups that match the
-      ;; kiboze regexp.
-      (mapatoms
-       (lambda (group)
-        (and (string-match nnkiboze-regexp
-                           (setq gname (symbol-name group))) ; Match
-             (not (assoc gname nnkiboze-newsrc)) ; It isn't registered
-             (numberp (car (symbol-value group))) ; It is active
-             (or (> nnkiboze-level 7)
-                 (and (setq glevel (nth 1 (nth 2 (gnus-gethash
-                                                  gname gnus-newsrc-hashtb))))
-                      (>= nnkiboze-level glevel)))
-             (not (string-match "^nnkiboze:" gname)) ; Exclude kibozes
-             (push (cons gname (1- (car (symbol-value group))))
-                   nnkiboze-newsrc)))
-       gnus-active-hashtb)
-      ;; `newsrc' is set to the list of groups that possibly are
-      ;; component groups to this kiboze group.  This list has elements
-      ;; on the form `(GROUP . NUMBER)', where NUMBER is the highest
-      ;; number that has been kibozed in GROUP in this kiboze group.
-      (setq newsrc nnkiboze-newsrc)
-      (while newsrc
-       (if (not (setq active (gnus-gethash
-                              (caar newsrc) gnus-active-hashtb)))
-           ;; This group isn't active after all, so we remove it from
-           ;; the list of component groups.
-           (setq nnkiboze-newsrc (delq (car newsrc) nnkiboze-newsrc))
-         (setq lowest (cdar newsrc))
-         ;; Ok, we have a valid component group, so we jump to it.
-         (switch-to-buffer gnus-group-buffer)
-         (gnus-group-jump-to-group (caar newsrc))
-         (gnus-message 3 "nnkiboze: Checking %s..." (caar newsrc))
-         (setq ginfo (gnus-get-info (gnus-group-group-name))
-               orig-info (gnus-copy-sequence ginfo))
-         (unwind-protect
-             (progn
-               ;; We set all list of article marks to nil.  Since we operate
-               ;; on copies of the real lists, we can destroy anything we
-               ;; want here.
-               (when (nth 3 ginfo)
-                 (setcar (nthcdr 3 ginfo) nil))
-               ;; We set the list of read articles to be what we expect for
-               ;; this kiboze group -- either nil or `(1 . LOWEST)'.
-               (when ginfo
-                 (setcar (nthcdr 2 ginfo)
-                         (and (not (= lowest 1)) (cons 1 lowest))))
-               (when (and (or (not ginfo)
-                              (> (length (gnus-list-of-unread-articles
-                                          (car ginfo)))
-                                 0))
-                          (progn
-                            (ignore-errors 
-                              (gnus-group-select-group nil))
-                            (eq major-mode 'gnus-summary-mode)))
-                 ;; We are now in the group where we want to be.
-                 (setq method (gnus-find-method-for-group
-                               gnus-newsgroup-name))
-                 (when (eq method gnus-select-method)
-                   (setq method nil))
-                 ;; We go through the list of scored articles.
-                 (while gnus-newsgroup-scored
-                   (when (> (caar gnus-newsgroup-scored) lowest)
-                     ;; If it has a good score, then we enter this article
-                     ;; into the kiboze group.
-                     (nnkiboze-enter-nov
-                      nov-buffer
-                      (gnus-summary-article-header
-                       (caar gnus-newsgroup-scored))
-                      gnus-newsgroup-name))
-                   (setq gnus-newsgroup-scored (cdr gnus-newsgroup-scored)))
-                 ;; That's it.  We exit this group.
-                 (gnus-summary-exit-no-update)))
-           ;; Restore the proper info.
-           (when ginfo
-             (setcdr ginfo (cdr orig-info)))))
-       (setcdr (car newsrc) (car active))
-       (gnus-message 3 "nnkiboze: Checking %s...done" (caar newsrc))
-       (setq newsrc (cdr newsrc))))
-    ;; We save the kiboze newsrc for this group.
-    (nnheader-temp-write newsrc-file
-      (insert "(setq nnkiboze-newsrc '")
-      (gnus-prin1 nnkiboze-newsrc)
-      (insert ")\n"))
+    (mm-with-unibyte
+     (when (file-exists-p newsrc-file)
+       (load newsrc-file))
+     (let ((coding-system-for-write nnkiboze-file-coding-system)
+          (output-coding-system nnkiboze-file-coding-system))
+       (gnus-make-directory (file-name-directory nov-file))
+       (with-temp-file nov-file
+        (when (file-exists-p nov-file)
+          (nnheader-insert-file-contents nov-file))
+        (setq nov-buffer (current-buffer))
+        ;; Go through the active hashtb and add new all groups that match the
+        ;; kiboze regexp.
+        (mapatoms
+         (lambda (group)
+           (and (string-match nnkiboze-regexp
+                              (setq gname (symbol-name group))) ; Match
+                (not (assoc gname nnkiboze-newsrc)) ; It isn't registered
+                (numberp (car (symbol-value group))) ; It is active
+                (or (> nnkiboze-level 7)
+                    (and (setq glevel
+                               (nth 1 (nth 2 (gnus-gethash
+                                              gname gnus-newsrc-hashtb))))
+                         (>= nnkiboze-level glevel)))
+                (not (string-match "^nnkiboze:" gname)) ; Exclude kibozes
+                (push (cons gname (1- (car (symbol-value group))))
+                      nnkiboze-newsrc)))
+         gnus-active-hashtb)
+        ;; `newsrc' is set to the list of groups that possibly are
+        ;; component groups to this kiboze group.  This list has elements
+        ;; on the form `(GROUP . NUMBER)', where NUMBER is the highest
+        ;; number that has been kibozed in GROUP in this kiboze group.
+        (setq newsrc nnkiboze-newsrc)
+        (while newsrc
+          (if (not (setq active (gnus-gethash
+                                 (caar newsrc) gnus-active-hashtb)))
+              ;; This group isn't active after all, so we remove it from
+              ;; the list of component groups.
+              (setq nnkiboze-newsrc (delq (car newsrc) nnkiboze-newsrc))
+            (setq lowest (cdar newsrc))
+            ;; Ok, we have a valid component group, so we jump to it.
+            (switch-to-buffer gnus-group-buffer)
+            (gnus-group-jump-to-group (caar newsrc))
+            (gnus-message 3 "nnkiboze: Checking %s..." (caar newsrc))
+            (setq ginfo (gnus-get-info (gnus-group-group-name))
+                  orig-info (gnus-copy-sequence ginfo)
+                  num-unread (car (gnus-gethash (caar newsrc)
+                                                gnus-newsrc-hashtb)))
+            (unwind-protect
+                (progn
+                  ;; We set all list of article marks to nil.  Since we operate
+                  ;; on copies of the real lists, we can destroy anything we
+                  ;; want here.
+                  (when (nth 3 ginfo)
+                    (setcar (nthcdr 3 ginfo) nil))
+                  ;; We set the list of read articles to be what we expect for
+                  ;; this kiboze group -- either nil or `(1 . LOWEST)'.
+                  (when ginfo
+                    (setcar (nthcdr 2 ginfo)
+                            (and (not (= lowest 1)) (cons 1 lowest))))
+                  (when (and (or (not ginfo)
+                                 (> (length (gnus-list-of-unread-articles
+                                             (car ginfo)))
+                                    0))
+                             (progn
+                               (ignore-errors
+                                 (gnus-group-select-group nil))
+                               (eq major-mode 'gnus-summary-mode)))
+                    ;; We are now in the group where we want to be.
+                    (setq method (gnus-find-method-for-group
+                                  gnus-newsgroup-name))
+                    (when (eq method gnus-select-method)
+                      (setq method nil))
+                    ;; We go through the list of scored articles.
+                    (while gnus-newsgroup-scored
+                      (when (> (caar gnus-newsgroup-scored) lowest)
+                        ;; If it has a good score, then we enter this article
+                        ;; into the kiboze group.
+                        (nnkiboze-enter-nov
+                         nov-buffer
+                         (gnus-summary-article-header
+                          (caar gnus-newsgroup-scored))
+                         gnus-newsgroup-name))
+                      (setq gnus-newsgroup-scored (cdr gnus-newsgroup-scored)))
+                    ;; That's it.  We exit this group.
+                    (when (eq major-mode 'gnus-summary-mode)
+                      (kill-buffer (current-buffer)))))
+              ;; Restore the proper info.
+              (when ginfo
+                (setcdr ginfo (cdr orig-info)))
+              (setcar (gnus-gethash (caar newsrc) gnus-newsrc-hashtb)
+                      num-unread)))
+          (setcdr (car newsrc) (cdr active))
+          (gnus-message 3 "nnkiboze: Checking %s...done" (caar newsrc))
+          (setq newsrc (cdr newsrc)))))
+     ;; We save the kiboze newsrc for this group.
+     (gnus-make-directory (file-name-directory newsrc-file))
+     (with-temp-file newsrc-file
+       (insert "(setq nnkiboze-newsrc '")
+       (gnus-prin1 nnkiboze-newsrc)
+       (insert ")\n")))
+    (unless inhibit-list-groups
+      (save-excursion
+       (set-buffer gnus-group-buffer)
+       (gnus-group-list-groups)))
     t))
 
 (defun nnkiboze-enter-nov (buffer header group)
   (save-excursion
     (set-buffer buffer)
     (goto-char (point-max))
-    (let ((xref (mail-header-xref header))
-         (prefix (gnus-group-real-prefix group))
+    (let ((prefix (gnus-group-real-prefix group))
          (oheader (copy-sequence header))
-         (first t)
          article)
       (if (zerop (forward-line -1))
          (progn
@@ -332,24 +371,28 @@ Finds out what articles are to be part of the nnkiboze groups."
            (forward-line 1))
        (setq article 1))
       (mail-header-set-number oheader article)
-      (nnheader-insert-nov oheader)
-      (search-backward "\t" nil t 2)
-      (if (re-search-forward " [^ ]+:[0-9]+" nil t)
-         (goto-char (match-beginning 0))
-       (forward-char 1))
-      ;; The first Xref has to be the group this article
-      ;; really came for - this is the article nnkiboze
-      ;; will request when it is asked for the article.
-      (insert group ":"
-             (int-to-string (mail-header-number header)) " ")
-      (while (re-search-forward " [^ ]+:[0-9]+" nil t)
-       (goto-char (1+ (match-beginning 0)))
-       (insert prefix)))))
-
-(defun nnkiboze-nov-file-name ()
+      (with-temp-buffer
+       (insert (or (mail-header-xref oheader) ""))
+       (goto-char (point-min))
+       (if (re-search-forward " [^ ]+:[0-9]+" nil t)
+           (goto-char (match-beginning 0))
+         (or (eobp) (forward-char 1)))
+       ;; The first Xref has to be the group this article
+       ;; really came for - this is the article nnkiboze
+       ;; will request when it is asked for the article.
+       (insert " " group ":"
+               (int-to-string (mail-header-number header)) " ")
+       (while (re-search-forward " [^ ]+:[0-9]+" nil t)
+         (goto-char (1+ (match-beginning 0)))
+         (insert prefix))
+       (mail-header-set-xref oheader (buffer-string)))
+      (nnheader-insert-nov oheader))))
+
+(defun nnkiboze-nov-file-name (&optional suffix)
   (concat (file-name-as-directory nnkiboze-directory)
          (nnheader-translate-file-chars
-          (concat (nnkiboze-prefixed-name nnkiboze-current-group) ".nov"))))
+          (concat (nnkiboze-prefixed-name nnkiboze-current-group)
+                  (or suffix ".nov")))))
 
 (provide 'nnkiboze)
 
index 684595c..1008141 100644 (file)
@@ -1,7 +1,8 @@
 ;;; nnlistserv.el --- retrieving articles via web mailing list archives
-;; Copyright (C) 1997,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Commentary:
 
-;; Note: You need to have `url' and `w3' installed for this
-;; backend to work.
-
 ;;; Code:
 
 (eval-when-compile (require 'cl))
 
 (require 'nnoo)
+(require 'mm-url)
 (require 'nnweb)
 
 (nnoo-declare nnlistserv
   nnweb-type)
 
 (defvoo nnlistserv-type-definition
-  '((kk
-     (article . nnlistserv-kk-wash-article)
-     (map . nnlistserv-kk-create-mapping)
-     (search . nnlistserv-kk-search)
-     (address . "http://www.itk.ntnu.no/ansatte/Andresen_Trond/kk-f/%s/")
-     (pages "fra160396" "fra160796" "fra061196" "fra160197"
-           "fra090997" "fra040797" "fra130397" "nye")
-     (index . "date.html")
-     (identifier . nnlistserv-kk-identity)))
+    '((kk
+       (article . nnlistserv-kk-wash-article)
+       (map . nnlistserv-kk-create-mapping)
+       (search . nnlistserv-kk-search)
+       (address . "http://www.itk.ntnu.no/ansatte/Andresen_Trond/kk-f/%s/")
+       (pages "fra160396" "fra160796" "fra061196" "fra160197"
+             "fra090997" "fra040797" "fra130397" "nye")
+       (index . "date.html")
+       (identifier . nnlistserv-kk-identity)))
   "Type-definition alist."
   nnweb-type-definition)
 
@@ -81,7 +80,7 @@
 ;;;
 
 (defun nnlistserv-kk-create-mapping ()
-  "Perform the search and create an number-to-url alist."
+  "Perform the search and create a number-to-url alist."
   (save-excursion
     (set-buffer nnweb-buffer)
     (let ((case-fold-search t)
@@ -94,7 +93,7 @@
        (when (funcall (nnweb-definition 'search) page)
          ;; Go through all the article hits on this page.
          (goto-char (point-min))
-         (nnweb-decode-entities)
+         (mm-url-decode-entities)
          (goto-char (point-min))
          (while (re-search-forward "^<li> *<a href=\"\\([^\"]+\\)\"><b>\\([^\\>]+\\)</b></a> *<[^>]+><i>\\([^>]+\\)<" nil t)
            (setq url (match-string 1)
                 nil 0 0 url))
               map)
              (nnweb-set-hashtb (cadar map) (car map))
-             (message "%s %s %s" (cdr active) (point) pages)
-             ))))
+             (nnheader-message 5 "%s %s %s" (cdr active) (point) pages)))))
       ;; Return the articles in the right order.
       (setq nnweb-articles
            (sort (nconc nnweb-articles map) 'car-less-than-car)))))
   (let ((case-fold-search t)
        (headers '(sent name email subject id))
        sent name email subject id)
-    (nnweb-decode-entities)
+    (mm-url-decode-entities)
     (while headers
       (goto-char (point-min))
       (re-search-forward (format "<!-- %s=\"\\([^\"]+\\)" (car headers) nil t))
     (goto-char (point-max))
     (search-backward "<!-- body" nil t)
     (delete-region (point-max) (progn (beginning-of-line) (point)))
-    (nnweb-remove-markup)
+    (mm-url-remove-markup)
     (goto-char (point-min))
     (insert (format "From: %s <%s>\n" name email)
            (format "Subject: %s\n" subject)
            (format "Date: %s\n\n" sent))))
 
 (defun nnlistserv-kk-search (search)
-  (url-insert-file-contents
-   (concat (format (nnweb-definition 'address) search) 
+  (mm-url-insert
+   (concat (format (nnweb-definition 'address) search)
           (nnweb-definition 'index)))
   t)
 
index 5c0cd70..3e52196 100644 (file)
@@ -1,7 +1,8 @@
 ;;; nnmail.el --- mail support functions for the Gnus mail backends
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 (eval-when-compile (require 'cl))
 
+(require 'gnus)                                ; for macro gnus-kill-buffer, at least
 (require 'nnheader)
-(require 'timezone)
 (require 'message)
 (require 'custom)
+(require 'gnus-util)
+(require 'mail-source)
 
 (eval-and-compile
-  (autoload 'gnus-error "gnus-util")
-  (autoload 'gnus-buffer-live-p "gnus-util")
-  (autoload 'gnus-encode-coding-string "gnus-ems"))
+  (autoload 'gnus-add-buffer "gnus")
+  (autoload 'gnus-kill-buffer "gnus"))
 
 (defgroup nnmail nil
   "Reading mail with Gnus."
@@ -54,7 +56,7 @@
   :group 'nnmail)
 
 (defgroup nnmail-split nil
-  "Organizing the incomming mail in folders."
+  "Organizing the incoming mail in folders."
   :group 'nnmail)
 
 (defgroup nnmail-files nil
@@ -74,8 +76,7 @@
   "Various mail options."
   :group 'nnmail)
 
-(defcustom nnmail-split-methods
-  '(("mail.misc" ""))
+(defcustom nnmail-split-methods '(("mail.misc" ""))
   "*Incoming mail will be split according to this variable.
 
 If you'd like, for instance, one mail group for mail from the
@@ -84,8 +85,8 @@ else, you could do something like this:
 
  (setq nnmail-split-methods
        '((\"mail.4ad\" \"From:.*4ad\")
-         (\"mail.junk\" \"From:.*Lars\\\\|Subject:.*buy\")
-         (\"mail.misc\" \"\")))
+        (\"mail.junk\" \"From:.*Lars\\\\|Subject:.*buy\")
+        (\"mail.misc\" \"\")))
 
 As you can see, this variable is a list of lists, where the first
 element in each \"rule\" is the name of the group (which, by the way,
@@ -102,7 +103,8 @@ The last element should always have \"\" as the regexp.
 
 This variable can also have a function as its value."
   :group 'nnmail-split
-  :type '(choice (repeat :tag "Alist" (group (string :tag "Name") regexp))
+  :type '(choice (repeat :tag "Alist" (group (string :tag "Name")
+                                            (choice regexp function)))
                 (function-item nnmail-split-fancy)
                 (function :tag "Other")))
 
@@ -113,6 +115,22 @@ If nil, the first match found will be used."
   :group 'nnmail-split
   :type 'boolean)
 
+(defcustom nnmail-split-fancy-with-parent-ignore-groups nil
+  "Regexp that matches group names to be ignored when applying `nnmail-split-fancy-with-parent'.
+This can also be a list of regexps."
+  :group 'nnmail-split
+  :type '(choice (const :tag "none" nil)
+                (regexp :value ".*")
+                (repeat :value (".*") regexp)))
+
+(defcustom nnmail-cache-ignore-groups nil
+  "Regexp that matches group names to be ignored when inserting message ids into the cache (`nnmail-cache-insert').
+This can also be a list of regexps."
+  :group 'nnmail-split
+  :type '(choice (const :tag "none" nil)
+                (regexp :value ".*")
+                (repeat :value (".*") regexp)))
+
 ;; Added by gord@enci.ucalgary.ca (Gordon Matzigkeit).
 (defcustom nnmail-keep-last-article nil
   "If non-nil, nnmail will never delete/move a group's last article.
@@ -143,72 +161,97 @@ number of days) -- this doesn't have to be an integer.  This variable
 can also be `immediate' and `never'."
   :group 'nnmail-expire
   :type '(choice (const immediate)
-                (integer :tag "days")
+                (number :tag "days")
                 (const never)))
 
 (defcustom nnmail-expiry-wait-function nil
   "Variable that holds function to specify how old articles should be before they are expired.
-  The function will be called with the name of the group that the
-expiry is to be performed in, and it should return an integer that
-says how many days an article can be stored before it is considered
-\"old\".  It can also return the values `never' and `immediate'.
+The function will be called with the name of the group that the expiry
+is to be performed in, and it should return an integer that says how
+many days an article can be stored before it is considered \"old\".
+It can also return the values `never' and `immediate'.
 
 Eg.:
 
 \(setq nnmail-expiry-wait-function
       (lambda (newsgroup)
-        (cond ((string-match \"private\" newsgroup) 31)
-              ((string-match \"junk\" newsgroup) 1)
+       (cond ((string-match \"private\" newsgroup) 31)
+             ((string-match \"junk\" newsgroup) 1)
              ((string-match \"important\" newsgroup) 'never)
              (t 7))))"
   :group 'nnmail-expire
   :type '(choice (const :tag "nnmail-expiry-wait" nil)
                 (function :format "%v" nnmail-)))
 
+(defcustom nnmail-expiry-target 'delete
+  "*Variable that says where expired messages should end up.
+The default value is `delete' (which says to delete the messages),
+but it can also be a string or a function.  If it is a string, expired
+messages end up in that group.  If it is a function, the function is
+called in a buffer narrowed to the message in question.  The function
+receives one argument, the name of the group the message comes from.
+The return value should be `delete' or a group name (a string)."
+  :version "21.1"
+  :group 'nnmail-expire
+  :type '(choice (const delete)
+                (function :format "%v" nnmail-)
+                string))
+
+(defcustom nnmail-fancy-expiry-targets nil
+  "Determine expiry target based on articles using fancy techniques.
+
+This is a list of (\"HEADER\" \"REGEXP\" \"TARGET\") entries.  If
+`nnmail-expiry-target' is set to the function
+`nnmail-fancy-expiry-target' and HEADER of the article matches REGEXP,
+the message will be expired to a group determined by invoking
+`format-time-string' with TARGET used as the format string and the
+time extracted from the articles' Date header (if missing the current
+time is used).
+
+In the special cases that HEADER is the symbol `to-from', the regexp
+will try to match against both the From and the To header.
+
+Example:
+
+\(setq nnmail-fancy-expiry-targets
+      '((to-from \"boss\" \"nnfolder:Work\")
+       (\"Subject\" \"IMPORTANT\" \"nnfolder:IMPORTANT.%Y.%b\")
+       (\"from\" \".*\" \"nnfolder:Archive-%Y\")))
+
+In this case, articles containing the string \"boss\" in the To or the
+From header will be expired to the group \"nnfolder:Work\";
+articles containing the sting \"IMPORTANT\" in the Subject header will
+be expired to the group \"nnfolder:IMPORTANT.YYYY.MMM\"; and
+everything else will be expired to \"nnfolder:Archive-YYYY\"."
+  :group 'nnmail-expire
+  :type '(repeat (list (choice :tag "Match against"
+                              (string :tag "Header")
+                              (const to-from))
+                      regexp
+                      (string :tag "Target group format string"))))
+
 (defcustom nnmail-cache-accepted-message-ids nil
-  "If non-nil, put Message-IDs of Gcc'd articles into the duplicate cache."
+  "If non-nil, put Message-IDs of Gcc'd articles into the duplicate cache.
+If non-nil, also update the cache when copy or move articles."
   :group 'nnmail
   :type 'boolean)
 
-(defcustom nnmail-spool-file
-  (or (getenv "MAIL")
-      (concat "/usr/spool/mail/" (user-login-name)))
+(defcustom nnmail-spool-file '((file))
   "*Where the mail backends will look for incoming mail.
-This variable is \"/usr/spool/mail/$user\" by default.
-If this variable is nil, no mail backends will read incoming mail.
-If this variable is a list, all files mentioned in this list will be
-used as incoming mailboxes.
-If this variable is a directory (i. e., it's name ends with a \"/\"),
-treat all files in that directory as incoming spool files."
-  :group 'nnmail-files
-  :type 'file)
-
-(defcustom nnmail-crash-box "~/.gnus-crash-box"
-  "File where Gnus will store mail while processing it."
+This variable is a list of mail source specifiers.
+This variable is obsolete; `mail-sources' should be used instead."
   :group 'nnmail-files
-  :type 'file)
+  :type 'sexp)
 
-(defcustom nnmail-use-procmail nil
-  "*If non-nil, the mail backends will look in `nnmail-procmail-directory' for spool files.
-The file(s) in `nnmail-spool-file' will also be read."
+(defcustom nnmail-resplit-incoming nil
+  "*If non-nil, re-split incoming procmail sorted mail."
   :group 'nnmail-procmail
   :type 'boolean)
 
-(defcustom nnmail-procmail-directory "~/incoming/"
-  "*When using procmail (and the like), incoming mail is put in this directory.
-The Gnus mail backends will read the mail from this directory."
-  :group 'nnmail-procmail
-  :type 'directory)
-
-(defcustom nnmail-procmail-suffix "\\.spool"
-  "*Suffix of files created by procmail (and the like).
-This variable might be a suffix-regexp to match the suffixes of
-several files - eg. \".spool[0-9]*\"."
-  :group 'nnmail-procmail
-  :type 'regexp)
-
-(defcustom nnmail-resplit-incoming nil
-  "*If non-nil, re-split incoming procmail sorted mail."
+(defcustom nnmail-scan-directory-mail-source-once nil
+  "*If non-nil, scan all incoming procmail sorted mails once.
+It scans low-level sorted spools even when not required."
+  :version "21.1"
   :group 'nnmail-procmail
   :type 'boolean)
 
@@ -218,7 +261,7 @@ several files - eg. \".spool[0-9]*\"."
   :type 'function)
 
 (defcustom nnmail-crosspost-link-function
-  (if (string-match "windows-nt\\|emx" (format "%s" system-type))
+  (if (string-match "windows-nt\\|emx" (symbol-name system-type))
       'copy-file
     'add-name-to-file)
   "*Function called to create a copy of a file.
@@ -230,28 +273,12 @@ links, you could set this variable to `copy-file' instead."
                (function-item copy-file)
                (function :tag "Other")))
 
-(defcustom nnmail-movemail-program "movemail"
-  "*A command to be executed to move mail from the inbox.
-The default is \"movemail\".
-
-This can also be a function.  In that case, the function will be
-called with two parameters -- the name of the INBOX file, and the file
-to be moved to."
-  :group 'nnmail-files
-  :group 'nnmail-retrieve
-  :type 'string)
-
-(defcustom nnmail-pop-password-required nil
-  "*Non-nil if a password is required when reading mail using POP."
-  :group 'nnmail-retrieve
-  :type 'boolean)
-
 (defcustom nnmail-read-incoming-hook
   (if (eq system-type 'windows-nt)
       '(nnheader-ms-strip-cr)
     nil)
   "*Hook that will be run after the incoming mail has been transferred.
-The incoming mail is moved from `nnmail-spool-file' (which normally is
+The incoming mail is moved from the specified spool file (which normally is
 something like \"/usr/spool/mail/$user\") to the user's home
 directory.  This hook is called after the incoming mail box has been
 emptied, and can be used to call any mail box programs you have
@@ -260,9 +287,9 @@ running (\"xwatch\", etc.)
 Eg.
 
 \(add-hook 'nnmail-read-incoming-hook
-          (lambda ()
-            (start-process \"mailsend\" nil
-                           \"/local/bin/mailsend\" \"read\" \"mbox\")))
+         (lambda ()
+           (call-process \"/local/bin/mailsend\" nil nil nil
+                         \"read\" nnmail-spool-file)))
 
 If you have xwatch running, this will alert it that mail has been
 read.
@@ -278,7 +305,6 @@ If you use `display-time', you could use something like this:
   :group 'nnmail-prepare
   :type 'hook)
 
-;; Suggested by Erik Selberg <speed@cs.washington.edu>.
 (defcustom nnmail-prepare-incoming-hook nil
   "Hook called before treating incoming mail.
 The hook is run in a buffer with all the new, incoming mail."
@@ -323,33 +349,102 @@ discarded after running the split process."
   :group 'nnmail-split
   :type 'hook)
 
-;; Suggested by Mejia Pablo J <pjm9806@usl.edu>.
-(defcustom nnmail-tmp-directory nil
-  "*If non-nil, use this directory for temporary storage.
-Used when reading incoming mail."
-  :group 'nnmail-files
-  :group 'nnmail-retrieve
-  :type '(choice (const :tag "default" nil)
-                (directory :format "%v")))
+(defcustom nnmail-spool-hook nil
+  "*A hook called when a new article is spooled."
+  :group 'nnmail
+  :type 'hook)
 
 (defcustom nnmail-large-newsgroup 50
-  "*The number of the articles which indicates a large newsgroup.
-If the number of the articles is greater than the value, verbose
+  "*The number of articles which indicates a large newsgroup or nil.
+If the number of articles is greater than the value, verbose
 messages will be shown to indicate the current status."
   :group 'nnmail-various
-  :type 'integer)
+  :type '(choice (const :tag "infinite" nil)
+                 (number :tag "count")))
+
+(define-widget 'nnmail-lazy 'default
+  "Base widget for recursive datastructures.
+
+This is copy of the `lazy' widget in Emacs 21.4 provided for compatibility."
+  :format "%{%t%}: %v"
+  :convert-widget 'widget-value-convert-widget
+  :value-create (lambda (widget)
+                  (let ((value (widget-get widget :value))
+                        (type (widget-get widget :type)))
+                    (widget-put widget :children 
+                                (list (widget-create-child-value 
+                                       widget (widget-convert type) value)))))
+  :value-delete 'widget-children-value-delete
+  :value-get (lambda (widget)
+               (widget-value (car (widget-get widget :children))))
+  :value-inline (lambda (widget)
+                  (widget-apply (car (widget-get widget :children))
+                                :value-inline))
+  :default-get (lambda (widget)
+                 ;;(widget-default-get
+                 ;; (widget-convert (widget-get widget :type))))
+                ;; `widget-default-get' isn't available in Mule 2.
+                (let ((w (widget-convert (widget-get widget :type))))
+                  (or (widget-get w :value)
+                      (widget-apply w :default-get))))
+  :match (lambda (widget value)
+           (widget-apply (widget-convert (widget-get widget :type))
+                         :match value))
+  :validate (lambda (widget)
+              (widget-apply (car (widget-get widget :children)) :validate)))
+
+(define-widget 'nnmail-split-fancy 'nnmail-lazy
+  "Widget for customizing splits in the variable of the same name."
+  :tag "Split"
+  :type '(menu-choice :value (any ".*value.*" "misc")
+                      :tag "Type"
+                      (string :tag "Destination")
+                      (list :tag "Use first match (|)" :value (|)
+                            (const :format "" |)
+                            (editable-list :inline t nnmail-split-fancy))
+                      (list :tag "Use all matches (&)" :value (&)
+                            (const :format "" &)
+                            (editable-list :inline t nnmail-split-fancy))
+                      (list :tag "Function with fixed arguments (:)"
+                            :value (: nil)
+                            (const :format "" :value :)
+                            function 
+                            (editable-list :inline t (sexp :tag "Arg"))
+                            )
+                      (list :tag "Function with split arguments (!)"
+                            :value (! nil)
+                            (const :format "" !)
+                            function
+                            (editable-list :inline t nnmail-split-fancy))
+                      (list :tag "Field match" 
+                            (choice :tag "Field" 
+                                    regexp symbol)
+                            (choice :tag "Match"
+                                    regexp 
+                                    (symbol :value mail))
+                            (repeat :inline t
+                                    :tag "Restrictions"
+                                    (group :inline t
+                                           (const :format "" -)
+                                           regexp))
+                            nnmail-split-fancy)
+                      (const :tag "Junk (delete mail)" junk)))
 
 (defcustom nnmail-split-fancy "mail.misc"
   "Incoming mail can be split according to this fancy variable.
 To enable this, set `nnmail-split-methods' to `nnmail-split-fancy'.
 
-The format is this variable is SPLIT, where SPLIT can be one of
+The format of this variable is SPLIT, where SPLIT can be one of
 the following:
 
 GROUP: Mail will be stored in GROUP (a string).
 
-\(FIELD VALUE SPLIT): If the message field FIELD (a regexp) contains
-  VALUE (a regexp), store the messages as specified by SPLIT.
+\(FIELD VALUE [- RESTRICT [- RESTRICT [...]]] SPLIT): If the message
+  field FIELD (a regexp) contains VALUE (a regexp), store the messages
+  as specified by SPLIT.  If RESTRICT (a regexp) matches some string
+  after FIELD and before the end of the matched VALUE, return nil,
+  otherwise process SPLIT.  Multiple RESTRICTs add up, further
+  restricting the possibility of processing SPLIT.
 
 \(| SPLIT...): Process each SPLIT expression until one of them matches.
   A SPLIT expression is said to match if it will cause the mail
@@ -361,6 +456,16 @@ GROUP: Mail will be stored in GROUP (a string).
   the buffer containing the message headers.  The return value FUNCTION
   should be a split, which is then recursively processed.
 
+\(! FUNCTION SPLIT): Call FUNCTION with the result of SPLIT.  The
+  return value FUNCTION should be a split, which is then recursively
+  processed.
+
+junk: Mail will be deleted.  Use with care!  Do not submerge in water!
+  Example:
+  (setq nnmail-split-fancy
+       '(| (\"Subject\" \"MAKE MONEY FAST\" junk)
+           ...other.rules.omitted...))
+
 FIELD must match a complete field name.  VALUE must match a complete
 word according to the `nnmail-split-fancy-syntax-table' syntax table.
 You can use \".*\" in the regexps to match partial field names or words.
@@ -388,13 +493,19 @@ Example:
             ;; Other mailing lists...
             (any \"procmail@informatik\\\\.rwth-aachen\\\\.de\" \"procmail.list\")
             (any \"SmartList@informatik\\\\.rwth-aachen\\\\.de\" \"SmartList.list\")
+            ;; Both lists below have the same suffix, so prevent
+            ;; cross-posting to mkpkg.list of messages posted only to
+            ;; the bugs- list, but allow cross-posting when the
+            ;; message was really cross-posted.
+            (any \"bugs-mypackage@somewhere\" \"mypkg.bugs\")
+            (any \"mypackage@somewhere\" - \"bugs-mypackage\" \"mypkg.list\")
+            ;;
             ;; People...
             (any \"larsi@ifi\\\\.uio\\\\.no\" \"people.Lars Magne Ingebrigtsen\"))
          ;; Unmatched mail goes to the catch all group.
          \"misc.misc\"))"
   :group 'nnmail-split
-  ;; Sigh!
-  :type 'sexp)
+  :type 'nnmail-split-fancy)
 
 (defcustom nnmail-split-abbrev-alist
   '((any . "from\\|to\\|cc\\|sender\\|apparently-to\\|resent-from\\|resent-to\\|resent-cc")
@@ -407,12 +518,6 @@ Example:
   :group 'nnmail-split
   :type '(repeat (cons :format "%v" symbol regexp)))
 
-(defcustom nnmail-delete-incoming nil
-  "*If non-nil, the mail backends will delete incoming files after
-splitting."
-  :group 'nnmail-retrieve
-  :type 'boolean)
-
 (defcustom nnmail-message-id-cache-length 1000
   "*The approximate number of Message-IDs nnmail will keep in its cache.
 If this variable is nil, no checking on duplicate messages will be
@@ -429,7 +534,7 @@ performed."
 
 (defcustom nnmail-treat-duplicates 'warn
   "*If non-nil, nnmail keep a cache of Message-IDs to discover mail duplicates.
-Three values are legal: nil, which means that nnmail is not to keep a
+Three values are valid: nil, which means that nnmail is not to keep a
 Message-ID cache; `warn', which means that nnmail should insert extra
 headers to warn the user about the duplication (this is the default);
 and `delete', which means that nnmail will delete duplicated mails.
@@ -442,36 +547,57 @@ parameter.  It should return nil, `warn' or `delete'."
                 (const warn)
                 (const delete)))
 
+(defcustom nnmail-extra-headers '(To Newsgroups)
+  "*Extra headers to parse."
+  :version "21.1"
+  :group 'nnmail
+  :type '(repeat symbol))
+
+(defcustom nnmail-split-header-length-limit 512
+  "Header lines longer than this limit are excluded from the split function."
+  :version "21.1"
+  :group 'nnmail
+  :type 'integer)
+
+(defcustom nnmail-mail-splitting-charset nil
+  "Default charset to be used when splitting incoming mail."
+  :group 'nnmail
+  :type 'symbol)
+
+(defcustom nnmail-mail-splitting-decodes t
+  "Whether the nnmail splitting functionality should MIME decode headers."
+  :group 'nnmail
+  :type 'boolean)
+
+(defcustom nnmail-split-fancy-match-partial-words nil
+  "Whether to match partial words when fancy splitting.
+Normally, regexes given in `nnmail-split-fancy' are implicitly surrounded
+by \"\\=\\<...\\>\".  If this variable is true, they are not implicitly\
+ surrounded
+by anything."
+  :group 'nnmail
+  :type 'boolean)
+
 ;;; Internal variables.
 
+(defvar nnmail-article-buffer " *nnmail incoming*"
+  "The buffer used for splitting incoming mails.")
+
 (defvar nnmail-split-history nil
   "List of group/article elements that say where the previous split put messages.")
 
-(defvar nnmail-current-spool nil)
-
-(defvar nnmail-pop-password nil
-  "*Password to use when reading mail from a POP server, if required.")
-
-(defvar nnmail-split-fancy-syntax-table nil
+(defvar nnmail-split-fancy-syntax-table
+  (let ((table (make-syntax-table)))
+    ;; support the %-hack
+    (modify-syntax-entry ?\% "." table)
+    table)
   "Syntax table used by `nnmail-split-fancy'.")
-(unless (syntax-table-p nnmail-split-fancy-syntax-table)
-  (setq nnmail-split-fancy-syntax-table
-       (copy-syntax-table (standard-syntax-table)))
-  ;; support the %-hack
-  (modify-syntax-entry ?\% "." nnmail-split-fancy-syntax-table))
 
 (defvar nnmail-prepare-save-mail-hook nil
   "Hook called before saving mail.")
 
-(defvar nnmail-moved-inboxes nil
-  "List of inboxes that have been moved.")
-
-(defvar nnmail-internal-password nil)
-
-\f
-
-(defconst nnmail-version "nnmail 1.0"
-  "nnmail version.")
+(defvar nnmail-split-tracing nil)
+(defvar nnmail-split-trace nil)
 
 \f
 
@@ -481,224 +607,92 @@ parameter.  It should return nil, `warn' or `delete'."
 (defvar nnmail-file-coding-system 'raw-text
   "Coding system used in nnmail.")
 
+(defvar nnmail-incoming-coding-system
+  nnheader-text-coding-system
+  "Coding system used in reading inbox")
+
+(defvar nnmail-pathname-coding-system nil
+  "*Coding system for file name.")
+
 (defun nnmail-find-file (file)
   "Insert FILE in server buffer safely."
   (set-buffer nntp-server-buffer)
-  (erase-buffer)
+  (delete-region (point-min) (point-max))
   (let ((format-alist nil)
-        (after-insert-file-functions nil))
+       (after-insert-file-functions nil))
     (condition-case ()
-       (let ((coding-system-for-read nnmail-file-coding-system)
-             (pathname-coding-system 'binary))
-         (insert-file-contents file)
+       (let ((auto-mode-alist (nnheader-auto-mode-alist))
+             (file-name-coding-system nnmail-pathname-coding-system)
+             (pathname-coding-system nnmail-pathname-coding-system))
+         (insert-file-contents-as-coding-system
+          nnmail-file-coding-system file)
          t)
       (file-error nil))))
 
-(defvar nnmail-pathname-coding-system
-  'iso-8859-1
-  "*Coding system for pathname.")
-
 (defun nnmail-group-pathname (group dir &optional file)
-  "Make pathname for GROUP."
+  "Make file name for GROUP."
   (concat
    (let ((dir (file-name-as-directory (expand-file-name dir))))
+     (setq group (nnheader-replace-duplicate-chars-in-string
+                 (nnheader-replace-chars-in-string group ?/ ?_)
+                 ?. ?_))
      (setq group (nnheader-translate-file-chars group))
      ;; If this directory exists, we use it directly.
-     (if (or nnmail-use-long-file-names
-            (file-directory-p (concat dir group)))
-        (concat dir group "/")
-       ;; If not, we translate dots into slashes.
-       (concat dir
-              (gnus-encode-coding-string
-               (nnheader-replace-chars-in-string group ?. ?/)
-               nnmail-pathname-coding-system)
-              "/")))
+     (file-name-as-directory
+      (if (or nnmail-use-long-file-names
+             (file-directory-p (concat dir group)))
+         (expand-file-name group dir)
+       ;; If not, we translate dots into slashes.
+       (expand-file-name
+        (encode-coding-string
+         (nnheader-replace-chars-in-string group ?. ?/)
+         nnmail-pathname-coding-system)
+        dir))))
    (or file "")))
 
-(defun nnmail-date-to-time (date)
-  "Convert DATE into time."
-  (condition-case ()
-      (let* ((d1 (timezone-parse-date date))
-            (t1 (timezone-parse-time (aref d1 3))))
-       (apply 'encode-time
-              (mapcar (lambda (el)
-                        (and el (string-to-number el)))
-                      (list
-                       (aref t1 2) (aref t1 1) (aref t1 0)
-                       (aref d1 2) (aref d1 1) (aref d1 0)
-                       (number-to-string
-                        (* 60 (timezone-zone-to-minute (aref d1 4))))))))
-    ;; If we get an error, then we just return a 0 time.
-    (error (list 0 0))))
-
-(defun nnmail-time-less (t1 t2)
-  "Say whether time T1 is less than time T2."
-  (or (< (car t1) (car t2))
-      (and (= (car t1) (car t2))
-          (< (nth 1 t1) (nth 1 t2)))))
-
-(defun nnmail-days-to-time (days)
-  "Convert DAYS into time."
-  (let* ((seconds (* 1.0 days 60 60 24))
-        (rest (expt 2 16))
-        (ms (condition-case nil (round (/ seconds rest))
-              (range-error (expt 2 16)))))
-    (list ms (condition-case nil (round (- seconds (* ms rest)))
-              (range-error (expt 2 16))))))
-
-(defun nnmail-time-since (time)
-  "Return the time since TIME, which is either an internal time or a date."
-  (when (stringp time)
-    ;; Convert date strings to internal time.
-    (setq time (nnmail-date-to-time time)))
-  (let* ((current (current-time))
-        (rest (when (< (nth 1 current) (nth 1 time))
-                (expt 2 16))))
-    (list (- (+ (car current) (if rest -1 0)) (car time))
-         (- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
-
-;; Function rewritten from rmail.el.
-(defun nnmail-move-inbox (inbox)
-  "Move INBOX to `nnmail-crash-box'."
-  (if (not (file-writable-p nnmail-crash-box))
-      (gnus-error 1 "Can't write to crash box %s.  Not moving mail"
-                 nnmail-crash-box)
-    ;; If the crash box exists and is empty, we delete it.
-    (when (and (file-exists-p nnmail-crash-box)
-              (zerop (nnheader-file-size (file-truename nnmail-crash-box))))
-      (delete-file nnmail-crash-box))
-    (let ((tofile (file-truename (expand-file-name nnmail-crash-box)))
-         (popmail (string-match "^po:" inbox))
-         movemail errors result)
-      (unless popmail
-       (setq inbox (file-truename (expand-file-name inbox)))
-       (setq movemail t)
-       ;; On some systems, /usr/spool/mail/foo is a directory
-       ;; and the actual inbox is /usr/spool/mail/foo/foo.
-       (when (file-directory-p inbox)
-         (setq inbox (expand-file-name (user-login-name) inbox))))
-      (if (member inbox nnmail-moved-inboxes)
-         ;; We don't try to move an already moved inbox.
-         nil
-       (if popmail
-           (progn
-             (when (and nnmail-pop-password
-                        (not nnmail-internal-password))
-               (setq nnmail-internal-password nnmail-pop-password))
-             (when (and nnmail-pop-password-required
-                        (not nnmail-internal-password))
-               (setq nnmail-internal-password
-                     (nnmail-read-passwd
-                      (format "Password for %s: "
-                              (substring inbox (+ popmail 3))))))
-             (message "Getting mail from the post office..."))
-         (when (or (and (file-exists-p tofile)
-                        (/= 0 (nnheader-file-size tofile)))
-                   (and (file-exists-p inbox)
-                        (/= 0 (nnheader-file-size inbox))))
-           (message "Getting mail from %s..." inbox)))
-       ;; Set TOFILE if have not already done so, and
-       ;; rename or copy the file INBOX to TOFILE if and as appropriate.
-       (cond
-        ((file-exists-p tofile)
-         ;; The crash box exists already.
-         t)
-        ((and (not popmail)
-              (not (file-exists-p inbox)))
-         ;; There is no inbox.
-         (setq tofile nil))
-        (t
-         ;; If getting from mail spool directory, use movemail to move
-         ;; rather than just renaming, so as to interlock with the
-         ;; mailer.
-         (unwind-protect
-             (save-excursion
-               (setq errors (generate-new-buffer " *nnmail loss*"))
-               (buffer-disable-undo errors)
-               (if (nnheader-functionp nnmail-movemail-program)
-                   (condition-case err
-                       (progn
-                         (funcall nnmail-movemail-program inbox tofile)
-                         (setq result 0))
-                     (error
-                      (save-excursion
-                        (set-buffer errors)
-                        (insert (prin1-to-string err))
-                        (setq result 255))))
-                 (let ((default-directory "/"))
-                   (setq result
-                         (apply
-                          'call-process
-                          (append
-                           (list
-                            (expand-file-name
-                             nnmail-movemail-program exec-directory)
-                            nil errors nil inbox tofile)
-                           (when nnmail-internal-password
-                             (list nnmail-internal-password)))))))
-               (if (and (not (buffer-modified-p errors))
-                        (zerop result))
-                   ;; No output => movemail won
-                   (progn
-                     (unless popmail
-                       (when (file-exists-p tofile)
-                         (set-file-modes tofile nnmail-default-file-modes)))
-                     (push inbox nnmail-moved-inboxes))
-                 (set-buffer errors)
-                 ;; There may be a warning about older revisions.  We
-                 ;; ignore those.
-                 (goto-char (point-min))
-                 (if (search-forward "older revision" nil t)
-                     (progn
-                       (unless popmail
-                         (when (file-exists-p tofile)
-                           (set-file-modes tofile nnmail-default-file-modes)))
-                       (push inbox nnmail-moved-inboxes))
-                   ;; Probably a real error.
-                   (subst-char-in-region (point-min) (point-max) ?\n ?\  )
-                   (goto-char (point-max))
-                   (skip-chars-backward " \t")
-                   (delete-region (point) (point-max))
-                   (goto-char (point-min))
-                   (when (looking-at "movemail: ")
-                     (delete-region (point-min) (match-end 0)))
-                   (unless (yes-or-no-p
-                            (format "movemail: %s (%d return).  Continue? "
-                                    (buffer-string) result))
-                     (error "%s" (buffer-string)))
-                   (setq tofile nil)))))))
-       (message "Getting mail from %s...done" inbox)
-       (and errors
-            (buffer-name errors)
-            (kill-buffer errors))
-       tofile))))
-
 (defun nnmail-get-active ()
   "Returns an assoc of group names and active ranges.
 nn*-request-list should have been called before calling this function."
-  (let (group-assoc)
-    ;; Go through all groups from the active list.
-    (save-excursion
-      (set-buffer nntp-server-buffer)
-      (goto-char (point-min))
-      (while (re-search-forward
-             "^\\([^ \t]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)" nil t)
-       ;; We create an alist with `(GROUP (LOW . HIGH))' elements.
-       (push (list (match-string 1)
-                   (cons (string-to-int (match-string 3))
-                         (string-to-int (match-string 2))))
-             group-assoc)))
+  ;; Go through all groups from the active list.
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (nnmail-parse-active)))
+
+(defun nnmail-parse-active ()
+  "Parse the active file in the current buffer and return an alist."
+  (goto-char (point-min))
+  (unless (re-search-forward "[\\\"]" nil t)
+    (goto-char (point-max))
+    (while (re-search-backward "[][';?()#]" nil t)
+      (insert ?\\)))
+  (goto-char (point-min))
+  (let ((buffer (current-buffer))
+       group-assoc group max min)
+    (while (not (eobp))
+      (condition-case err
+         (progn
+           (narrow-to-region (point) (gnus-point-at-eol))
+           (setq group (read buffer))
+           (unless (stringp group)
+             (setq group (symbol-name group)))
+           (if (and (numberp (setq max (read buffer)))
+                    (numberp (setq min (read buffer))))
+               (push (list group (cons min max))
+                     group-assoc)))
+       (error nil))
+      (widen)
+      (forward-line 1))
     group-assoc))
 
-(defvar nnmail-active-file-coding-system
-  'iso-8859-1
+(defvar nnmail-active-file-coding-system 'raw-text
   "*Coding system for active file.")
 
 (defun nnmail-save-active (group-assoc file-name)
   "Save GROUP-ASSOC in ACTIVE-FILE."
-  (let ((coding-system-for-write nnmail-active-file-coding-system))
+  (let ((coding-system-for-write nnmail-active-file-coding-system)
+       (output-coding-system nnmail-active-file-coding-system))
     (when file-name
-      (nnheader-temp-write file-name
+      (with-temp-file file-name
        (nnmail-generate-active group-assoc)))))
 
 (defun nnmail-generate-active (alist)
@@ -706,35 +700,26 @@ nn*-request-list should have been called before calling this function."
   (erase-buffer)
   (let (group)
     (while (setq group (pop alist))
-      (insert (format "%s %d %d y\n" (car group) (cdadr group)
-                     (caadr group))))))
+      (insert (format "%S %d %d y\n" (intern (car group)) (cdadr group)
+                     (caadr group))))
+    (goto-char (point-max))
+    (while (search-backward "\\." nil t)
+      (delete-char 1))))
 
-(defun nnmail-get-split-group (file group)
+(defun nnmail-get-split-group (file source)
   "Find out whether this FILE is to be split into GROUP only.
-If GROUP is non-nil and we are using procmail, return the group name
-only when the file is the correct procmail file.  When GROUP is nil,
-return nil if FILE is a spool file or the procmail group for which it
-is a spool.  If not using procmail, return GROUP."
-  (if (or (eq nnmail-spool-file 'procmail)
-         nnmail-use-procmail)
-      (if (string-match (concat "^" (expand-file-name
-                                    (file-name-as-directory
-                                     nnmail-procmail-directory))
-                               "\\([^/]*\\)" nnmail-procmail-suffix "$")
-                       (expand-file-name file))
-         (let ((procmail-group (substring (expand-file-name file)
-                                          (match-beginning 1)
-                                          (match-end 1))))
-           (if group
-               (if (string-equal group procmail-group)
-                   group
-                 nil)
-             procmail-group))
-       nil)
-    group))
+If SOURCE is a directory spec, try to return the group name component."
+  (if (eq (car source) 'directory)
+      (let ((file (file-name-nondirectory file)))
+       (mail-source-bind (directory source)
+         (if (string-match (concat (regexp-quote suffix) "$") file)
+             (substring file 0 (match-beginning 0))
+           nil)))
+    nil))
 
 (defun nnmail-process-babyl-mail-format (func artnum-func)
   (let ((case-fold-search t)
+       (count 0)
        start message-id content-length do-search end)
     (while (not (eobp))
       (goto-char (point-min))
@@ -806,12 +791,14 @@ is a spool.  If not using procmail, return GROUP."
          (narrow-to-region start (point))
          (goto-char (point-min))
          (nnmail-check-duplication message-id func artnum-func)
+         (incf count)
          (setq end (point-max))))
-      (goto-char end))))
+      (goto-char end))
+    count))
 
 (defsubst nnmail-search-unix-mail-delim ()
   "Put point at the beginning of the next Unix mbox message."
-  ;; Algorithm used to find the the next article in the
+  ;; Algorithm used to find the next article in the
   ;; brain-dead Unix mbox format:
   ;;
   ;; 1) Search for "^From ".
@@ -828,7 +815,7 @@ is a spool.  If not using procmail, return GROUP."
          (when (and (or (bobp)
                         (save-excursion
                           (forward-line -1)
-                          (= (following-char) ?\n)))
+                          (eq (char-after) ?\n)))
                     (save-excursion
                       (forward-line 1)
                       (while (looking-at ">From \\|From ")
@@ -840,7 +827,7 @@ is a spool.  If not using procmail, return GROUP."
 
 (defun nnmail-search-unix-mail-delim-backward ()
   "Put point at the beginning of the current Unix mbox message."
-  ;; Algorithm used to find the the next article in the
+  ;; Algorithm used to find the next article in the
   ;; brain-dead Unix mbox format:
   ;;
   ;; 1) Search for "^From ".
@@ -857,7 +844,7 @@ is a spool.  If not using procmail, return GROUP."
          (when (and (or (bobp)
                         (save-excursion
                           (forward-line -1)
-                          (= (following-char) ?\n)))
+                          (eq (char-after) ?\n)))
                     (save-excursion
                       (forward-line 1)
                       (while (looking-at ">From \\|From ")
@@ -869,14 +856,15 @@ is a spool.  If not using procmail, return GROUP."
 
 (defun nnmail-process-unix-mail-format (func artnum-func)
   (let ((case-fold-search t)
+       (count 0)
        start message-id content-length end skip head-end)
     (goto-char (point-min))
     (if (not (and (re-search-forward "^From " nil t)
                  (goto-char (match-beginning 0))))
        ;; Possibly wrong format?
-       (progn
-         (pop-to-buffer (find-file-noselect nnmail-current-spool))
-         (error "Error, unknown mail format! (Possibly corrupted.)"))
+       (error "Error, unknown mail format! (Possibly corrupted %s `%s'.)"
+              (if (buffer-file-name) "file" "buffer")
+              (or (buffer-file-name) (buffer-name)))
       ;; Carry on until the bitter end.
       (while (not (eobp))
        (setq start (point)
@@ -921,7 +909,7 @@ is a spool.  If not using procmail, return GROUP."
        (setq head-end (point))
        ;; We try the Content-Length value.  The idea: skip over the header
        ;; separator, then check what happens content-length bytes into the
-       ;; message body.  This should be either the end ot the buffer, the
+       ;; message body.  This should be either the end of the buffer, the
        ;; message separator or a blank line followed by the separator.
        ;; The blank line should probably be deleted.  If neither of the
        ;; three is met, the content-length header is probably invalid.
@@ -949,21 +937,22 @@ is a spool.  If not using procmail, return GROUP."
          (save-restriction
            (narrow-to-region start (point))
            (goto-char (point-min))
+           (incf count)
            (nnmail-check-duplication message-id func artnum-func)
            (setq end (point-max))))
-       (goto-char end)))))
+       (goto-char end)))
+    count))
 
 (defun nnmail-process-mmdf-mail-format (func artnum-func)
   (let ((delim "^\^A\^A\^A\^A$")
        (case-fold-search t)
+       (count 0)
        start message-id end)
     (goto-char (point-min))
     (if (not (and (re-search-forward delim nil t)
                  (forward-line 1)))
        ;; Possibly wrong format?
-       (progn
-         (pop-to-buffer (find-file-noselect nnmail-current-spool))
-         (error "Error, unknown mail format! (Possibly corrupted.)"))
+       (error "Error, unknown mail format! (Possibly corrupted.)")
       ;; Carry on until the bitter end.
       (while (not (eobp))
        (setq start (point))
@@ -1001,10 +990,47 @@ is a spool.  If not using procmail, return GROUP."
          (save-restriction
            (narrow-to-region start (point))
            (goto-char (point-min))
+           (incf count)
            (nnmail-check-duplication message-id func artnum-func)
            (setq end (point-max))))
        (goto-char end)
-       (forward-line 2)))))
+       (forward-line 2)))
+    count))
+
+(defun nnmail-process-maildir-mail-format (func artnum-func)
+  ;; In a maildir, every file contains exactly one mail.
+  (let ((case-fold-search t)
+       message-id)
+    (goto-char (point-min))
+    ;; Find the end of the head.
+    (narrow-to-region
+     (point-min)
+     (if (search-forward "\n\n" nil t)
+        (1- (point))
+       ;; This will never happen, but just to be on the safe side --
+       ;; if there is no head-body delimiter, we search a bit manually.
+       (while (and (looking-at "From \\|[^ \t]+:")
+                  (not (eobp)))
+        (forward-line 1))
+       (point)))
+    ;; Find the Message-ID header.
+    (goto-char (point-min))
+    (if (re-search-forward "^Message-ID:[ \t]*\\(<[^>]+>\\)" nil t)
+       (setq message-id (match-string 1))
+      ;; There is no Message-ID here, so we create one.
+      (save-excursion
+       (when (re-search-backward "^Message-ID[ \t]*:" nil t)
+         (beginning-of-line)
+         (insert "Original-")))
+      (forward-line 1)
+      (insert "Message-ID: " (setq message-id (nnmail-message-id)) "\n"))
+    (run-hooks 'nnmail-prepare-incoming-header-hook)
+    ;; Allow the backend to save the article.
+    (widen)
+    (save-excursion
+      (goto-char (point-min))
+      (nnmail-check-duplication message-id func artnum-func))
+    1))
 
 (defun nnmail-split-incoming (incoming func &optional exit-func
                                       group artnum-func)
@@ -1013,41 +1039,42 @@ FUNC will be called with the buffer narrowed to each mail."
   (let (;; If this is a group-specific split, we bind the split
        ;; methods to just this group.
        (nnmail-split-methods (if (and group
-                                      (or (eq nnmail-spool-file 'procmail)
-                                          nnmail-use-procmail)
                                       (not nnmail-resplit-incoming))
                                  (list (list group ""))
                                nnmail-split-methods)))
     (save-excursion
       ;; Insert the incoming file.
-      (set-buffer (get-buffer-create " *nnmail incoming*"))
-      (buffer-disable-undo (current-buffer))
+      (set-buffer (get-buffer-create nnmail-article-buffer))
       (erase-buffer)
-      (nnheader-insert-file-contents incoming)
-      (unless (zerop (buffer-size))
-       (goto-char (point-min))
-       (save-excursion (run-hooks 'nnmail-prepare-incoming-hook))
-       ;; Handle both babyl, MMDF and unix mail formats, since movemail will
-       ;; use the former when fetching from a mailbox, the latter when
-       ;; fetching from a file.
-       (cond ((or (looking-at "\^L")
-                  (looking-at "BABYL OPTIONS:"))
-              (nnmail-process-babyl-mail-format func artnum-func))
-             ((looking-at "\^A\^A\^A\^A")
-              (nnmail-process-mmdf-mail-format func artnum-func))
-             (t
-              (nnmail-process-unix-mail-format func artnum-func))))
-      (when exit-func
-       (funcall exit-func))
-      (kill-buffer (current-buffer)))))
-
-(defun nnmail-article-group (func)
+      (let ((nnheader-file-coding-system nnmail-incoming-coding-system))
+       (nnheader-insert-file-contents incoming))
+      (prog1
+         (if (zerop (buffer-size))
+             0
+           (goto-char (point-min))
+           (save-excursion (run-hooks 'nnmail-prepare-incoming-hook))
+           ;; Handle both babyl, MMDF and unix mail formats, since
+           ;; movemail will use the former when fetching from a
+           ;; mailbox, the latter when fetching from a file.
+           (cond ((or (looking-at "\^L")
+                      (looking-at "BABYL OPTIONS:"))
+                  (nnmail-process-babyl-mail-format func artnum-func))
+                 ((looking-at "\^A\^A\^A\^A")
+                  (nnmail-process-mmdf-mail-format func artnum-func))
+                 ((looking-at "Return-Path:")
+                  (nnmail-process-maildir-mail-format func artnum-func))
+                 (t
+                  (nnmail-process-unix-mail-format func artnum-func))))
+       (when exit-func
+         (funcall exit-func))
+       (kill-buffer (current-buffer))))))
+
+(defun nnmail-article-group (func &optional trace)
   "Look at the headers and return an alist of groups that match.
 FUNC will be called with the group name to determine the article number."
-  (let ((methods nnmail-split-methods)
+  (let ((methods (or nnmail-split-methods '(("bogus" ""))))
        (obuf (current-buffer))
-       (beg (point-min))
-       end group-art method regrepp)
+       group-art method grp)
     (if (and (sequencep methods)
             (= (length methods) 1))
        ;; If there is only just one group to put everything in, we
@@ -1056,19 +1083,40 @@ FUNC will be called with the group name to determine the article number."
              (list (cons (caar methods) (funcall func (caar methods)))))
       ;; We do actual comparison.
       (save-excursion
-       ;; Find headers.
-       (goto-char beg)
-       (setq end (if (search-forward "\n\n" nil t) (point) (point-max)))
+       ;; Copy the article into the work buffer.
        (set-buffer nntp-server-buffer)
        (erase-buffer)
-       ;; Copy the headers into the work buffer.
-       (insert-buffer-substring obuf beg end)
+       (insert-buffer-substring obuf)
+       ;; Narrow to headers.
+       (narrow-to-region
+        (goto-char (point-min))
+        (if (search-forward "\n\n" nil t)
+            (point)
+          (point-max)))
+       (goto-char (point-min))
+       ;; Decode MIME headers and charsets.
+       (when nnmail-mail-splitting-decodes
+         (mime-decode-header-in-region (point-min) (point-max)
+                                       nnmail-mail-splitting-charset))
        ;; Fold continuation lines.
        (goto-char (point-min))
        (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
          (replace-match " " t t))
+       ;; Nuke pathologically long headers.  Since Gnus applies
+       ;; pathologically complex regexps to the buffer, lines
+       ;; that are looong will take longer than the Universe's
+       ;; existence to process.
+       (goto-char (point-min))
+       (while (not (eobp))
+         (unless (< (move-to-column nnmail-split-header-length-limit)
+                    nnmail-split-header-length-limit)
+           (delete-region (point) (gnus-point-at-eol)))
+         (forward-line 1))
        ;; Allow washing.
+       (goto-char (point-min))
        (run-hooks 'nnmail-split-hook)
+       (when (setq nnmail-split-tracing trace)
+         (setq nnmail-split-trace nil))
        (if (and (symbolp nnmail-split-methods)
                 (fboundp nnmail-split-methods))
            (let ((split
@@ -1079,11 +1127,11 @@ FUNC will be called with the group name to determine the article number."
                       (or (funcall nnmail-split-methods)
                           '("bogus"))
                     (error
-                     (message
-                      "Error in `nnmail-split-methods'; using `bogus' mail group")
+                     (nnheader-message
+                      5 "Error in `nnmail-split-methods'; using `bogus' mail group")
                      (sit-for 1)
                      '("bogus")))))
-             (setq split (remove-duplicates split :test 'equal))
+             (setq split (gnus-remove-duplicates split))
              ;; The article may be "cross-posted" to `junk'.  What
              ;; to do?  Just remove the `junk' spec.  Don't really
              ;; see anything else to do...
@@ -1101,33 +1149,46 @@ FUNC will be called with the group name to determine the article number."
                          (not group-art)))
            (goto-char (point-max))
            (setq method (pop methods)
-                 regrepp nil)
+                 grp (car method))
            (if (or methods
                    (not (equal "" (nth 1 method))))
                (when (and
                       (ignore-errors
                         (if (stringp (nth 1 method))
-                            (progn
-                              (setq regrepp
-                                    (string-match "\\\\[0-9&]" (car method)))
-                              (re-search-backward (cadr method) nil t))
+                            (let ((expand (string-match "\\\\[0-9&]" grp))
+                                  (pos (re-search-backward (cadr method)
+                                                           nil t)))
+                              (and expand
+                                   (setq grp (nnmail-expand-newtext grp)))
+                              pos)
                           ;; Function to say whether this is a match.
-                          (funcall (nth 1 method) (car method))))
+                          (funcall (nth 1 method) grp)))
                       ;; Don't enter the article into the same
                       ;; group twice.
-                      (not (assoc (car method) group-art)))
-                 (push (cons (if regrepp
-                                 (replace-match
-                                  (car method) nil nil (car method))
-                               (car method))
-                             (funcall func (car method)))
+                      (not (assoc grp group-art)))
+                 (push (cons grp (funcall func grp))
                        group-art))
              ;; This is the final group, which is used as a
              ;; catch-all.
              (unless group-art
                (setq group-art
                      (list (cons (car method)
-                                 (funcall func (car method)))))))))
+                                 (funcall func (car method))))))))
+         ;; Fall back on "bogus" if all else fails.
+         (unless group-art
+           (setq group-art (list (cons "bogus" (funcall func "bogus"))))))
+       ;; Produce a trace if non-empty.
+       (when (and trace nnmail-split-trace)
+         (let ((restore (current-buffer)))
+           (nnheader-set-temp-buffer "*Split Trace*")
+           (gnus-add-buffer)
+           (dolist (trace (nreverse nnmail-split-trace))
+             (prin1 trace (current-buffer))
+             (insert "\n"))
+           (goto-char (point-min))
+           (gnus-configure-windows 'split-trace)
+           (set-buffer restore)))
+       (widen)
        ;; See whether the split methods returned `junk'.
        (if (equal group-art '(junk))
            nil
@@ -1145,34 +1206,39 @@ Return the number of characters in the body."
   (let (lines chars)
     (save-excursion
       (goto-char (point-min))
-      (when (search-forward "\n\n" nil t)
-       (setq chars (- (point-max) (point)))
-       (setq lines (count-lines (point) (point-max)))
-       (forward-char -1)
-       (save-excursion
-         (when (re-search-backward "^Lines: " nil t)
-           (delete-region (point) (progn (forward-line 1) (point)))))
-       (beginning-of-line)
-       (insert (format "Lines: %d\n" (max lines 0)))
-       chars))))
+      (unless (search-forward "\n\n" nil t)
+       (goto-char (point-max))
+       (insert "\n"))
+      (setq chars (- (point-max) (point)))
+      (setq lines (count-lines (point) (point-max)))
+      (forward-char -1)
+      (save-excursion
+       (when (re-search-backward "^Lines: " nil t)
+         (delete-region (point) (progn (forward-line 1) (point)))))
+      (beginning-of-line)
+      (insert (format "Lines: %d\n" (max lines 0)))
+      chars)))
 
 (defun nnmail-insert-xref (group-alist)
   "Insert an Xref line based on the (group . article) alist."
   (save-excursion
     (goto-char (point-min))
-    (when (search-forward "\n\n" nil t)
-      (forward-char -1)
-      (when (re-search-backward "^Xref: " nil t)
-       (delete-region (match-beginning 0)
-                      (progn (forward-line 1) (point))))
-      (insert (format "Xref: %s" (system-name)))
-      (while group-alist
-       (insert (format " %s:%d"
-                       (gnus-encode-coding-string (caar group-alist)
-                                             nnmail-pathname-coding-system)
-                       (cdar group-alist)))
-       (setq group-alist (cdr group-alist)))
-      (insert "\n"))))
+    (unless (search-forward "\n\n" nil t)
+      (goto-char (point-max))
+      (insert "\n"))
+    (forward-char -1)
+    (when (re-search-backward "^Xref: " nil t)
+      (delete-region (match-beginning 0)
+                    (progn (forward-line 1) (point))))
+    (insert (format "Xref: %s" (system-name)))
+    (while group-alist
+      (insert (format " %s:%d"
+                     (encode-coding-string
+                      (caar group-alist)
+                      nnmail-pathname-coding-system)
+                     (cdar group-alist)))
+      (setq group-alist (cdr group-alist)))
+    (insert "\n")))
 
 ;;; Message washing functions
 
@@ -1184,34 +1250,68 @@ Return the number of characters in the body."
 
 (defun nnmail-remove-list-identifiers ()
   "Remove list identifiers from Subject headers."
-  (let ((regexp (if (stringp nnmail-list-identifiers) nnmail-list-identifiers
-                 (mapconcat 'identity nnmail-list-identifiers "\\|"))))
+  (let ((regexp
+        (if (consp nnmail-list-identifiers)
+            (mapconcat 'identity nnmail-list-identifiers " *\\|")
+          nnmail-list-identifiers)))
     (when regexp
       (goto-char (point-min))
-      (when (re-search-forward
-            (concat "^Subject: +\\(Re: +\\)?\\(" regexp "\\) *")
-            nil t)
-       (delete-region (match-beginning 2) (match-end 0))))))
+      (while (re-search-forward
+             (concat "^Subject: +\\(R[Ee]: +\\)*\\(" regexp " *\\)")
+             nil t)
+       (delete-region (match-beginning 2) (match-end 0))
+       (beginning-of-line))
+      (when (re-search-forward "^Subject: +\\(\\(R[Ee]: +\\)+\\)R[Ee]: +"
+                              nil t)
+       (delete-region (match-beginning 1) (match-end 1))
+       (beginning-of-line)))))
 
 (defun nnmail-remove-tabs ()
   "Translate TAB characters into SPACE characters."
   (subst-char-in-region (point-min) (point-max) ?\t ?  t))
 
-;;; Utility functions
+(defun nnmail-fix-eudora-headers ()
+  "Eudora has a broken References line, but an OK In-Reply-To."
+  (goto-char (point-min))
+  (when (re-search-forward "^X-Mailer:.*Eudora" nil t)
+    (goto-char (point-min))
+    (when (re-search-forward "^References:" nil t)
+      (beginning-of-line)
+      (insert "X-Gnus-Broken-Eudora-"))
+    (goto-char (point-min))
+    (when (re-search-forward "^\\(In-Reply-To:[^\n]+\\)\n[ \t]+" nil t)
+      (replace-match "\\1" t))))
 
-(defun nnmail-make-complex-temp-name (prefix)
-  (let ((newname (make-temp-name prefix))
-       (newprefix prefix))
-    (while (file-exists-p newname)
-      (setq newprefix (concat newprefix "x"))
-      (setq newname (make-temp-name newprefix)))
-    newname))
+(custom-add-option 'nnmail-prepare-incoming-header-hook
+                  'nnmail-fix-eudora-headers)
 
-;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
+;;; Utility functions
+
+(defun nnmail-do-request-post (accept-func &optional server)
+  "Utility function to directly post a message to an nnmail-derived group.
+Calls ACCEPT-FUNC (which should be `nnchoke-request-accept-article')
+to actually put the message in the right group."
+  (let ((success t))
+    (dolist (mbx (message-unquote-tokens
+                 (message-tokenize-header
+                  (message-fetch-field "Newsgroups") ", ")) success)
+      (let ((to-newsgroup (gnus-group-prefixed-name mbx gnus-command-method)))
+       (or (gnus-active to-newsgroup)
+           (gnus-activate-group to-newsgroup)
+           (if (gnus-y-or-n-p (format "No such group: %s.  Create it? "
+                                      to-newsgroup))
+               (or (and (gnus-request-create-group
+                         to-newsgroup gnus-command-method)
+                        (gnus-activate-group to-newsgroup nil nil
+                                             gnus-command-method))
+                   (error "Couldn't create group %s" to-newsgroup)))
+           (error "No such group: %s" to-newsgroup))
+       (unless (funcall accept-func mbx (nth 1 gnus-command-method))
+         (setq success nil))))))
 
 (defun nnmail-split-fancy ()
   "Fancy splitting method.
-See the documentation for the variable `nnmail-split-fancy' for documentation."
+See the documentation for the variable `nnmail-split-fancy' for details."
   (let ((syntab (syntax-table)))
     (unwind-protect
        (progn
@@ -1224,81 +1324,129 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 
 (defun nnmail-split-it (split)
   ;; Return a list of groups matching SPLIT.
-  (cond
-   ;; nil split
-   ((null split)
-    nil)
-
-   ;; A group name.  Do the \& and \N subs into the string.
-   ((stringp split)
-    (list (nnmail-expand-newtext split)))
-
-   ;; Junk the message.
-   ((eq split 'junk)
-    (list 'junk))
-
-   ;; Builtin & operation.
-   ((eq (car split) '&)
-    (apply 'nconc (mapcar 'nnmail-split-it (cdr split))))
-
-   ;; Builtin | operation.
-   ((eq (car split) '|)
-    (let (done)
-      (while (and (not done) (cdr split))
-       (setq split (cdr split)
-             done (nnmail-split-it (car split))))
-      done))
-
-   ;; Builtin : operation.
-   ((eq (car split) ':)
-    (nnmail-split-it (save-excursion (eval (cdr split)))))
-
-   ;; Check the cache for the regexp for this split.
-   ;; FIX FIX FIX could avoid calling assq twice here
-   ((assq split nnmail-split-cache)
-    (goto-char (point-max))
-    ;; FIX FIX FIX problem with re-search-backward is that if you have
-    ;; a split: (from "foo-\\(bar\\|baz\\)@gnus.org "mail.foo.\\1")
-    ;; and someone mails a message with 'To: foo-bar@gnus.org' and
-    ;; 'CC: foo-baz@gnus.org', we'll pick 'mail.foo.baz' as the group
-    ;; if the cc line is a later header, even though the other choice
-    ;; is probably better.  Also, this routine won't do a crosspost
-    ;; when there are two different matches.
-    ;; I guess you could just make this more determined, and it could
-    ;; look for still more matches prior to this one, and recurse
-    ;; on each of the multiple matches hit.  Of course, then you'd
-    ;; want to make sure that nnmail-article-group or nnmail-split-fancy
-    ;; removed duplicates, since there might be more of those.
-    ;; I guess we could also remove duplicates in the & split case, since
-    ;; that's the only thing that can introduce them.
-    (when (re-search-backward (cdr (assq split nnmail-split-cache)) nil t)
-      ;; Someone might want to do a \N sub on this match, so get the
-      ;; correct match positions.
-      (goto-char (match-end 0))
-      (let ((value (nth 1 split)))
-       (re-search-backward (if (symbolp value)
-                               (cdr (assq value nnmail-split-abbrev-alist))
-                             value)
-                           (match-end 1)))
-      (nnmail-split-it (nth 2 split))))
-
-   ;; Not in cache, compute a regexp for the field/value pair.
-   (t
-    (let* ((field (nth 0 split))
-          (value (nth 1 split))
-          (regexp (concat "^\\(\\("
-                          (if (symbolp field)
-                              (cdr (assq field nnmail-split-abbrev-alist))
-                            field)
-                          "\\):.*\\)\\<\\("
-                          (if (symbolp value)
-                              (cdr (assq value nnmail-split-abbrev-alist))
-                            value)
-                          "\\)\\>")))
-      (push (cons split regexp) nnmail-split-cache)
-      ;; Now that it's in the cache, just call nnmail-split-it again
-      ;; on the same split, which will find it immediately in the cache.
-      (nnmail-split-it split)))))
+  (let (cached-pair)
+    (cond
+     ;; nil split
+     ((null split)
+      nil)
+
+     ;; A group name.  Do the \& and \N subs into the string.
+     ((stringp split)
+      (when nnmail-split-tracing
+       (push split nnmail-split-trace))
+      (list (nnmail-expand-newtext split)))
+
+     ;; Junk the message.
+     ((eq split 'junk)
+      (when nnmail-split-tracing
+       (push "junk" nnmail-split-trace))
+      (list 'junk))
+
+     ;; Builtin & operation.
+     ((eq (car split) '&)
+      (apply 'nconc (mapcar 'nnmail-split-it (cdr split))))
+
+     ;; Builtin | operation.
+     ((eq (car split) '|)
+      (let (done)
+       (while (and (not done) (cdr split))
+         (setq split (cdr split)
+               done (nnmail-split-it (car split))))
+       done))
+
+     ;; Builtin : operation.
+     ((eq (car split) ':)
+      (when nnmail-split-tracing
+       (push split nnmail-split-trace))
+      (nnmail-split-it (save-excursion (eval (cdr split)))))
+
+     ;; Builtin ! operation.
+     ((eq (car split) '!)
+      (funcall (cadr split) (nnmail-split-it (caddr split))))
+
+     ;; Check the cache for the regexp for this split.
+     ((setq cached-pair (assq split nnmail-split-cache))
+      (let (split-result
+           (end-point (point-max))
+           (value (nth 1 split)))
+       (if (symbolp value)
+           (setq value (cdr (assq value nnmail-split-abbrev-alist))))
+       (while (and (goto-char end-point)
+                   (re-search-backward (cdr cached-pair) nil t))
+         (when nnmail-split-tracing
+           (push split nnmail-split-trace))
+         (let ((split-rest (cddr split))
+               (end (match-end 0))
+               ;; The searched regexp is \(\(FIELD\).*\)\(VALUE\).  So,
+               ;; start-of-value is the the point just before the
+               ;; beginning of the value, whereas after-header-name is
+               ;; the point just after the field name.
+               (start-of-value (match-end 1))
+               (after-header-name (match-end 2)))
+           ;; Start the next search just before the beginning of the
+           ;; VALUE match.
+           (setq end-point (1- start-of-value))
+           ;; Handle - RESTRICTs
+           (while (eq (car split-rest) '-)
+             ;; RESTRICT must start after-header-name and
+             ;; end after start-of-value, so that, for
+             ;; (any "foo" - "x-foo" "foo.list")
+             ;; we do not exclude foo.list just because
+             ;; the header is: ``To: x-foo, foo''
+             (goto-char end)
+             (if (and (re-search-backward (cadr split-rest)
+                                          after-header-name t)
+                      (> (match-end 0) start-of-value))
+                 (setq split-rest nil)
+               (setq split-rest (cddr split-rest))))
+           (when split-rest
+             (goto-char end)
+             (let ((value (nth 1 split)))
+               (if (symbolp value)
+                   (setq value (cdr (assq value nnmail-split-abbrev-alist))))
+               ;; Someone might want to do a \N sub on this match, so get the
+               ;; correct match positions.
+               (re-search-backward value start-of-value))
+             (dolist (sp (nnmail-split-it (car split-rest)))
+               (unless (member sp split-result)
+                 (push sp split-result))))))
+       split-result))
+
+     ;; Not in cache, compute a regexp for the field/value pair.
+     (t
+      (let* ((field (nth 0 split))
+            (value (nth 1 split))
+            partial-front
+            partial-rear
+            regexp)
+       (if (symbolp value)
+           (setq value (cdr (assq value nnmail-split-abbrev-alist))))
+       (if (and (>= (length value) 2)
+                (string= ".*" (substring value 0 2)))
+           (setq value (substring value 2)
+                 partial-front ""))
+       ;; Same trick for the rear of the regexp
+       (if (and (>= (length value) 2)
+                (string= ".*" (substring value -2)))
+           (setq value (substring value 0 -2)
+                 partial-rear ""))
+       (when nnmail-split-fancy-match-partial-words
+         (setq partial-front ""
+               partial-rear ""))
+       (setq regexp (concat "^\\(\\("
+                            (if (symbolp field)
+                                (cdr (assq field nnmail-split-abbrev-alist))
+                              field)
+                            "\\):.*\\)"
+                            (or partial-front "\\<")
+                            "\\("
+                            value
+                            "\\)"
+                            (or partial-rear "\\>")))
+       (push (cons split regexp) nnmail-split-cache)
+       ;; Now that it's in the cache, just call nnmail-split-it again
+       ;; on the same split, which will find it immediately in the cache.
+       (nnmail-split-it split))))))
 
 (defun nnmail-expand-newtext (newtext)
   (let ((len (length newtext))
@@ -1312,14 +1460,14 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
       (unless (= beg pos)
        (push (substring newtext beg pos) expanded))
       (when (< pos len)
-       ;; we hit a \, expand it.
-       (setq did-expand t)
-       (setq pos (1+ pos))
-       (setq c (aref newtext pos))
+       ;; We hit a \; expand it.
+       (setq did-expand t
+             pos (1+ pos)
+             c (aref newtext pos))
        (if (not (or (= c ?\&)
                     (and (>= c ?1)
                          (<= c ?9))))
-           ;; \ followed by some character we don't expand
+           ;; \ followed by some character we don't expand.
            (push (char-to-string c) expanded)
          ;; \& or \N
          (if (= c ?\&)
@@ -1333,68 +1481,6 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
        (apply 'concat (nreverse expanded))
       newtext)))
 
-;; Get a list of spool files to read.
-(defun nnmail-get-spool-files (&optional group)
-  (if (null nnmail-spool-file)
-      ;; No spool file whatsoever.
-      nil
-    (let* ((procmails
-           ;; If procmail is used to get incoming mail, the files
-           ;; are stored in this directory.
-           (and (file-exists-p nnmail-procmail-directory)
-                (or (eq nnmail-spool-file 'procmail)
-                    nnmail-use-procmail)
-                (directory-files
-                 nnmail-procmail-directory
-                 t (concat (if group (concat "^" (regexp-quote group)) "")
-                           nnmail-procmail-suffix "$"))))
-          (p procmails)
-          (crash (when (and (file-exists-p nnmail-crash-box)
-                            (> (nnheader-file-size
-                                (file-truename nnmail-crash-box))
-                               0))
-                   (list nnmail-crash-box))))
-      ;; Remove any directories that inadvertently match the procmail
-      ;; suffix, which might happen if the suffix is "".
-      (while p
-       (when (file-directory-p (car p))
-         (setq procmails (delete (car p) procmails)))
-       (setq p (cdr p)))
-      ;; Return the list of spools.
-      (append
-       crash
-       (cond ((and group
-                  (or (eq nnmail-spool-file 'procmail)
-                      nnmail-use-procmail)
-                  procmails)
-             procmails)
-            ((and group
-                  (eq nnmail-spool-file 'procmail))
-             nil)
-            ((listp nnmail-spool-file)
-             (nconc
-              (apply
-               'nconc
-               (mapcar
-                (lambda (file)
-                  (if (and (not (string-match "^po:" file))
-                           (file-directory-p file))
-                      (nnheader-directory-regular-files file)
-                    (list file)))
-                nnmail-spool-file))
-              procmails))
-            ((stringp nnmail-spool-file)
-             (if (and (not (string-match "^po:" nnmail-spool-file))
-                      (file-directory-p nnmail-spool-file))
-                 (nconc
-                  (nnheader-directory-regular-files nnmail-spool-file)
-                  procmails)
-               (cons nnmail-spool-file procmails)))
-            ((eq nnmail-spool-file 'pop)
-             (cons (format "po:%s" (user-login-name)) procmails))
-            (t
-             procmails))))))
-
 ;; Activate a backend only if it isn't already activated.
 ;; If FORCE, re-read the active file even if the backend is
 ;; already activated.
@@ -1444,7 +1530,7 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
       (set-buffer
        (setq nnmail-cache-buffer
             (get-buffer-create " *nnmail message-id cache*")))
-      (buffer-disable-undo (current-buffer))
+      (gnus-add-buffer)
       (when (file-exists-p nnmail-message-id-cache-file)
        (nnheader-insert-file-contents nnmail-message-id-cache-file))
       (set-buffer-modified-p nil)
@@ -1471,16 +1557,103 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
                           nnmail-message-id-cache-file nil 'silent)
       (set-buffer-modified-p nil)
       (setq nnmail-cache-buffer nil)
-      (kill-buffer (current-buffer)))))
-
-(defun nnmail-cache-insert (id)
-  (when nnmail-treat-duplicates
-    (unless (gnus-buffer-live-p nnmail-cache-buffer)
-      (nnmail-cache-open))
+      (gnus-kill-buffer (current-buffer)))))
+
+;; Compiler directives.
+(defvar group)
+(defvar group-art-list)
+(defvar group-art)
+(defun nnmail-cache-insert (id grp &optional subject sender)
+  (when (stringp id)
+    ;; this will handle cases like `B r' where the group is nil
+    (let ((grp (or grp gnus-newsgroup-name "UNKNOWN")))
+      (run-hook-with-args 'nnmail-spool-hook 
+                         id grp subject sender))
+    (when nnmail-treat-duplicates
+      ;; Store some information about the group this message is written
+      ;; to.  This is passed in as the grp argument -- all locations this
+      ;; has been called from have been checked and the group is available.
+      ;; The only ambiguous case is nnmail-check-duplication which will only
+      ;; pass the first (of possibly >1) group which matches. -Josh
+      (unless (gnus-buffer-live-p nnmail-cache-buffer)
+       (nnmail-cache-open))
+      (save-excursion
+       (set-buffer nnmail-cache-buffer)
+       (goto-char (point-max))
+       (if (and grp (not (string= "" grp))
+                (gnus-methods-equal-p gnus-command-method
+                                      (nnmail-cache-primary-mail-backend)))
+           (let ((regexp (if (consp nnmail-cache-ignore-groups)
+                             (mapconcat 'identity nnmail-cache-ignore-groups
+                                        "\\|")
+                           nnmail-cache-ignore-groups)))
+             (unless (and regexp (string-match regexp grp))
+               (insert id "\t" grp "\n")))
+         (insert id "\n"))))))
+  
+(defun nnmail-cache-primary-mail-backend ()
+  (let ((be-list (cons gnus-select-method gnus-secondary-select-methods))
+       (be nil)
+       (res nil)
+        (get-new-mail nil))
+    (while (and (null res) be-list)
+      (setq be (car be-list))
+      (setq be-list (cdr be-list))
+      (when (and (gnus-method-option-p be 'respool)
+                 (setq get-new-mail
+                       (intern (format "%s-get-new-mail" (car be))))
+                 (boundp get-new-mail)
+                (symbol-value get-new-mail))
+       (setq res be)))
+    res))
+
+;; Fetch the group name corresponding to the message id stored in the
+;; cache.
+(defun nnmail-cache-fetch-group (id)
+  (when (and nnmail-treat-duplicates nnmail-cache-buffer)
     (save-excursion
       (set-buffer nnmail-cache-buffer)
       (goto-char (point-max))
-      (insert id "\n"))))
+      (when (search-backward id nil t)
+       (beginning-of-line)
+       (skip-chars-forward "^\n\r\t")
+       (unless (looking-at "[\r\n]")
+         (forward-char 1)
+         (buffer-substring (point) (gnus-point-at-eol)))))))
+
+;; Function for nnmail-split-fancy: look up all references in the
+;; cache and if a match is found, return that group.
+(defun nnmail-split-fancy-with-parent ()
+  "Split this message into the same group as its parent.
+This function can be used as an entry in `nnmail-split-fancy', for
+example like this: (: nnmail-split-fancy-with-parent)
+For a message to be split, it looks for the parent message in the
+References or In-Reply-To header and then looks in the message id
+cache file (given by the variable `nnmail-message-id-cache-file') to
+see which group that message was put in.  This group is returned.
+
+See the Info node `(gnus)Fancy Mail Splitting' for more details."
+  (let* ((refstr (or (message-fetch-field "references")
+                    (message-fetch-field "in-reply-to")))
+        (references nil)
+        (res nil)
+        (regexp (if (consp nnmail-split-fancy-with-parent-ignore-groups)
+                    (mapconcat
+                     (lambda (x) (format "\\(%s\\)" x))
+                     nnmail-split-fancy-with-parent-ignore-groups
+                     "\\|")
+                  nnmail-split-fancy-with-parent-ignore-groups)))
+    (when refstr
+      (setq references (nreverse (gnus-split-references refstr)))
+      (unless (gnus-buffer-live-p nnmail-cache-buffer)
+       (nnmail-cache-open))
+      (mapcar (lambda (x)
+               (setq res (or (nnmail-cache-fetch-group x) res))
+               (when (or (member res '("delayed" "drafts" "queue"))
+                         (and regexp res (string-match regexp res)))
+                 (setq res nil)))
+             references)
+      res)))
 
 (defun nnmail-cache-id-exists-p (id)
   (when nnmail-treat-duplicates
@@ -1504,17 +1677,24 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
                   (cond
                    ((memq nnmail-treat-duplicates '(warn delete))
                     nnmail-treat-duplicates)
-                   ((nnheader-functionp nnmail-treat-duplicates)
+                   ((functionp nnmail-treat-duplicates)
                     (funcall nnmail-treat-duplicates message-id))
                    (t
                     nnmail-treat-duplicates))))
         group-art)
+    ;; We insert a line that says what the mail source is.
+    (let ((case-fold-search t))
+      (goto-char (point-min))
+      (re-search-forward "^message-id[ \t]*:" nil t)
+      (beginning-of-line)
+      (insert (format "X-Gnus-Mail-Source: %s\n" mail-source-string)))
+
     ;; Let the backend save the article (or not).
     (cond
      ((not duplication)
-      (nnmail-cache-insert message-id)
       (funcall func (setq group-art
-                         (nreverse (nnmail-article-group artnum-func)))))
+                         (nreverse (nnmail-article-group artnum-func))))
+      (nnmail-cache-insert message-id (caar group-art)))
      ((eq action 'delete)
       (setq group-art nil))
      ((eq action 'warn)
@@ -1537,6 +1717,8 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 
 ;;; Get new mail.
 
+(defvar nnmail-fetched-sources nil)
+
 (defun nnmail-get-value (&rest args)
   (let ((sym (intern (apply 'format args))))
     (when (boundp sym)
@@ -1545,72 +1727,92 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 (defun nnmail-get-new-mail (method exit-func temp
                                   &optional group spool-func)
   "Read new incoming mail."
-  (let* ((spools (nnmail-get-spool-files group))
+  (let* ((sources (or mail-sources
+                     (if (listp nnmail-spool-file) nnmail-spool-file
+                       (list nnmail-spool-file))))
+        fetching-sources
         (group-in group)
-        nnmail-current-spool incoming incomings spool)
+        (i 0)
+        (new 0)
+        (total 0)
+        incoming incomings source)
     (when (and (nnmail-get-value "%s-get-new-mail" method)
-              nnmail-spool-file)
+              sources)
+      (while (setq source (pop sources))
+       ;; Be compatible with old values.
+       (cond
+        ((stringp source)
+         (setq source
+               (cond
+                ((string-match "^po:" source)
+                 (list 'pop :user (substring source (match-end 0))))
+                ((file-directory-p source)
+                 (list 'directory :path source))
+                (t
+                 (list 'file :path source)))))
+        ((eq source 'procmail)
+         (message "Invalid value for nnmail-spool-file: `procmail'")
+         nil))
+       ;; Hack to only fetch the contents of a single group's spool file.
+       (when (and (eq (car source) 'directory)
+                  (null nnmail-scan-directory-mail-source-once)
+                  group)
+         (mail-source-bind (directory source)
+           (setq source (append source
+                                (list
+                                 :predicate
+                                 (gnus-byte-compile
+                                  `(lambda (file)
+                                     (string-equal
+                                      ,(concat group suffix)
+                                      (file-name-nondirectory file)))))))))
+       (when nnmail-fetched-sources
+         (if (member source nnmail-fetched-sources)
+             (setq source nil)
+           (push source nnmail-fetched-sources)
+           (push source fetching-sources)))))
+    (when fetching-sources
       ;; We first activate all the groups.
       (nnmail-activate method)
       ;; Allow the user to hook.
       (run-hooks 'nnmail-pre-get-new-mail-hook)
       ;; Open the message-id cache.
       (nnmail-cache-open)
-      ;; The we go through all the existing spool files and split the
-      ;; mail from each.
-      (while spools
-       (setq spool (pop spools))
-       ;; We read each spool file if either the spool is a POP-mail
-       ;; spool, or the file exists.  We can't check for the
-       ;; existence of POPped mail.
-       (when (or (string-match "^po:" spool)
-                 (and (file-exists-p (file-truename spool))
-                      (> (nnheader-file-size (file-truename spool)) 0)))
-         (nnheader-message 3 "%s: Reading incoming mail..." method)
-         (when (and (nnmail-move-inbox spool)
-                    (file-exists-p nnmail-crash-box))
-           (setq nnmail-current-spool spool)
-           ;; There is new mail.  We first find out if all this mail
-           ;; is supposed to go to some specific group.
-           (setq group (nnmail-get-split-group spool group-in))
-           ;; We split the mail
-           (nnmail-split-incoming
-            nnmail-crash-box (intern (format "%s-save-mail" method))
-            spool-func group (intern (format "%s-active-number" method)))
-           ;; Check whether the inbox is to be moved to the special tmp dir.
-           (setq incoming
-                 (nnmail-make-complex-temp-name
-                  (expand-file-name
-                   (if nnmail-tmp-directory
-                       (concat
-                        (file-name-as-directory nnmail-tmp-directory)
-                        (file-name-nondirectory
-                         (concat (file-name-as-directory temp) "Incoming")))
-                     (concat (file-name-as-directory temp) "Incoming")))))
-           (unless (file-exists-p (file-name-directory incoming))
-             (make-directory (file-name-directory incoming) t))
-           (rename-file nnmail-crash-box incoming t)
-           (push incoming incomings))))
+      ;; The we go through all the existing mail source specification
+      ;; and fetch the mail from each.
+      (while (setq source (pop fetching-sources))
+       (nnheader-message 4 "%s: Reading incoming mail from %s..."
+                         method (car source))
+       (when (setq new
+                   (mail-source-fetch
+                    source
+                    (gnus-byte-compile
+                     `(lambda (file orig-file)
+                        (nnmail-split-incoming
+                         file ',(intern (format "%s-save-mail" method))
+                         ',spool-func
+                         (if (equal file orig-file)
+                             nil
+                           (nnmail-get-split-group orig-file ',source))
+                         ',(intern (format "%s-active-number" method)))))))
+         (incf total new)
+         (incf i)))
       ;; If we did indeed read any incoming spools, we save all info.
-      (when incomings
+      (if (zerop total)
+         (nnheader-message 4 "%s: Reading incoming mail (no new mail)...done"
+                           method (car source))
        (nnmail-save-active
         (nnmail-get-value "%s-group-alist" method)
         (nnmail-get-value "%s-active-file" method))
        (when exit-func
          (funcall exit-func))
        (run-hooks 'nnmail-read-incoming-hook)
-       (nnheader-message 3 "%s: Reading incoming mail...done" method))
+       (nnheader-message 4 "%s: Reading incoming mail (%d new)...done" method
+                         total))
       ;; Close the message-id cache.
       (nnmail-cache-close)
       ;; Allow the user to hook.
-      (run-hooks 'nnmail-post-get-new-mail-hook)
-      ;; Delete all the temporary files.
-      (while incomings
-       (setq incoming (pop incomings))
-       (and nnmail-delete-incoming
-            (file-exists-p incoming)
-            (file-writable-p incoming)
-            (delete-file incoming))))))
+      (run-hooks 'nnmail-post-get-new-mail-hook))))
 
 (defun nnmail-expired-article-p (group time force &optional inhibit)
   "Say whether an article that is TIME old in GROUP should be expired."
@@ -1631,25 +1833,51 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
             ;; This is an ange-ftp group, and we don't have any dates.
             nil)
            ((numberp days)
-            (setq days (nnmail-days-to-time days))
+            (setq days (days-to-time days))
             ;; Compare the time with the current time.
-            (nnmail-time-less days (nnmail-time-since time)))))))
-
-(defvar nnmail-read-passwd nil)
-(defun nnmail-read-passwd (prompt &rest args)
-  "Read a password using PROMPT.
-If ARGS, PROMPT is used as an argument to `format'."
-  (let ((prompt
-        (if args
-            (apply 'format prompt args)
-          prompt)))
-    (unless nnmail-read-passwd
-      (if (load "passwd" t)
-         (setq nnmail-read-passwd 'read-passwd)
-       (unless (fboundp 'ange-ftp-read-passwd)
-         (autoload 'ange-ftp-read-passwd "ange-ftp"))
-       (setq nnmail-read-passwd 'ange-ftp-read-passwd)))
-    (funcall nnmail-read-passwd prompt)))
+            (ignore-errors (time-less-p days (time-since time))))))))
+
+(defun nnmail-expiry-target-group (target group)
+  ;; Do not invoke this from nntp-server-buffer!  At least nnfolder clears
+  ;; that buffer if the nnfolder group isn't selected.
+  (let (nnmail-cache-accepted-message-ids)
+    ;; Don't enter Message-IDs into cache.
+    ;; Let users hack it in TARGET function.
+    (when (functionp target)
+      (setq target (funcall target group)))
+    (unless (eq target 'delete)
+      (when (or (gnus-request-group target)
+               (gnus-request-create-group target))
+       (let ((group-art (gnus-request-accept-article target nil nil t)))
+         (when (consp group-art)
+           (gnus-group-mark-article-read target (cdr group-art))))))))
+
+(defun nnmail-fancy-expiry-target (group)
+  "Returns a target expiry group determined by `nnmail-fancy-expiry-targets'."
+  (let* (header
+        (case-fold-search nil)
+        (from (or (message-fetch-field "from") ""))
+        (to (or (message-fetch-field "to") ""))
+        (date (date-to-time
+               (or (message-fetch-field "date") (current-time-string))))
+        (target 'delete))
+    (dolist (regexp-target-pair (reverse nnmail-fancy-expiry-targets) target)
+      (setq header (car regexp-target-pair))
+      (cond
+       ;; If the header is to-from then match against the
+       ;; To or From header
+       ((and (equal header 'to-from)
+            (or (string-match (cadr regexp-target-pair) from)
+                (and (string-match message-dont-reply-to-names from)
+                     (string-match (cadr regexp-target-pair) to))))
+       (setq target (format-time-string (caddr regexp-target-pair) date)))
+       ((and (not (equal header 'to-from))
+            (string-match (cadr regexp-target-pair)
+                          (or
+                           (message-fetch-field header)
+                           "")))
+       (setq target
+             (format-time-string (caddr regexp-target-pair) date)))))))
 
 (defun nnmail-check-syntax ()
   "Check (and modify) the syntax of the message in the current buffer."
@@ -1661,9 +1889,10 @@ If ARGS, PROMPT is used as an argument to `format'."
 
 (defun nnmail-write-region (start end filename &optional append visit lockname)
   "Do a `write-region', and then set the file modes."
-  (let ((coding-system-for-write nnmail-file-coding-system)
-       (pathname-coding-system 'binary))
-    (write-region start end filename append visit lockname)
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
+    (write-region-as-coding-system
+     nnmail-file-coding-system start end filename append visit lockname)
     (set-file-modes filename nnmail-default-file-modes)))
 
 ;;;
@@ -1698,11 +1927,11 @@ If ARGS, PROMPT is used as an argument to `format'."
        (goto-char (point-min))
        (while (re-search-forward "[^ \t=]+" nil t)
          (setq name (match-string 0))
-         (if (not (= (following-char) ?=))
+         (if (not (eq (char-after) ?=))
              ;; Implied "yes".
              (setq value "yes")
            (forward-char 1)
-           (if (not (= (following-char) ?\"))
+           (if (not (eq (char-after) ?\"))
                (if (not (looking-at "[^ \t]"))
                    ;; Implied "no".
                    (setq value "no")
@@ -1731,6 +1960,8 @@ If ARGS, PROMPT is used as an argument to `format'."
   (unless nnmail-split-history
     (error "No current split history"))
   (with-output-to-temp-buffer "*nnmail split history*"
+    (with-current-buffer standard-output
+      (fundamental-mode))              ; for Emacs 20.4+
     (let ((history nnmail-split-history)
          elem)
       (while (setq elem (pop history))
@@ -1742,11 +1973,10 @@ If ARGS, PROMPT is used as an argument to `format'."
 
 (defun nnmail-purge-split-history (group)
   "Remove all instances of GROUP from `nnmail-split-history'."
-  (let ((history nnmail-split-history)
-       prev)
+  (let ((history nnmail-split-history))
     (while history
-      (setcar history (delete-if (lambda (e) (string= (car e) group))
-                                (car history)))
+      (setcar history (gnus-remove-if (lambda (e) (string= (car e) group))
+                                     (car history)))
       (pop history))
     (setq nnmail-split-history (delq nil nnmail-split-history))))
 
@@ -1760,14 +1990,23 @@ If ARGS, PROMPT is used as an argument to `format'."
              his nil)))
     found))
 
-(eval-and-compile
-  (autoload 'pop3-movemail "pop3"))
-
-(defun nnmail-pop3-movemail (inbox crashbox)
-  "Function to move mail from INBOX on a pop3 server to file CRASHBOX."
-  (let ((pop3-maildrop
-         (substring inbox (match-end (string-match "^po:" inbox)))))
-    (pop3-movemail crashbox)))
+(defun nnmail-new-mail-numbers (group)
+  "Say how many articles has been incorporated to GROUP."
+  (let ((his (apply 'append nnmail-split-history))
+       numbers)
+    (while his
+      (when (string= group (caar his))
+       (push (cdar his) numbers))
+      (setq his (cdr his)))
+    numbers))
+
+(defun nnmail-within-headers-p ()
+  "Check to see if point is within the headers of a unix mail message.
+Doesn't change point."
+  (let ((pos (point)))
+    (save-excursion
+      (and (nnmail-search-unix-mail-delim-backward)
+          (not (search-forward "\n\n" pos t))))))
 
 (run-hooks 'nnmail-load-hook)
 
diff --git a/lisp/nnmaildir.el b/lisp/nnmaildir.el
new file mode 100644 (file)
index 0000000..65bb5bd
--- /dev/null
@@ -0,0 +1,1636 @@
+;;; nnmaildir.el --- maildir backend for Gnus
+;; Public domain.
+
+;; Author: Paul Jarc <prj@po.cwru.edu>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Maildir format is documented at <URL:http://cr.yp.to/proto/maildir.html>
+;; and in the maildir(5) man page from qmail (available at
+;; <URL:http://www.qmail.org/man/man5/maildir.html>).  nnmaildir also stores
+;; extra information in the .nnmaildir/ directory within a maildir.
+;;
+;; Some goals of nnmaildir:
+;; * Everything Just Works, and correctly.  E.g., NOV data is automatically
+;;   regenerated when stale; no need for manually running
+;;   *-generate-nov-databases.
+;; * Perfect reliability: [C-g] will never corrupt its data in memory, and
+;;   SIGKILL will never corrupt its data in the filesystem.
+;; * Allow concurrent operation as much as possible.  If files change out
+;;   from under us, adapt to the changes or degrade gracefully.
+;; * We use the filesystem as a database, so that, e.g., it's easy to
+;;   manipulate marks from outside Gnus.
+;; * All information about a group is stored in the maildir, for easy backup,
+;;   copying, restoring, etc.
+;;
+;; Todo:
+;; * Add a hook for when moving messages from new/ to cur/, to support
+;;   nnmail's duplicate detection.
+;; * Improve generated Xrefs, so crossposts are detectable.
+;; * Improve code readability.
+
+;;; Code:
+
+;; eval this before editing
+[(progn
+   (put 'nnmaildir--with-nntp-buffer 'lisp-indent-function 0)
+   (put 'nnmaildir--with-work-buffer 'lisp-indent-function 0)
+   (put 'nnmaildir--with-nov-buffer  'lisp-indent-function 0)
+   (put 'nnmaildir--with-move-buffer 'lisp-indent-function 0)
+   )
+]
+
+(eval-and-compile
+  (require 'nnheader)
+  (require 'gnus)
+  (require 'gnus-util)
+  (require 'gnus-range)
+  (require 'gnus-start)
+  (require 'gnus-int)
+  (require 'message))
+(eval-when-compile
+  (require 'cl)
+  (require 'nnmail))
+
+(defconst nnmaildir-version "Gnus")
+
+(defvar nnmaildir-article-file-name nil
+  "*The filename of the most recently requested article.  This variable is set
+by nnmaildir-request-article.")
+
+;; The filename of the article being moved/copied:
+(defvar nnmaildir--file nil)
+
+;; Variables to generate filenames of messages being delivered:
+(defvar   nnmaildir--delivery-time "")
+(defconst nnmaildir--delivery-pid (concat "P" (number-to-string (emacs-pid))))
+(defvar   nnmaildir--delivery-count nil)
+
+;; An obarry containing symbols whose names are server names and whose values
+;; are servers:
+(defvar nnmaildir--servers (make-vector 3 0))
+;; The current server:
+(defvar nnmaildir--cur-server nil)
+
+;; A copy of nnmail-extra-headers
+(defvar nnmaildir--extra nil)
+
+;; A NOV structure looks like this (must be prin1-able, so no defstruct):
+["subject\tfrom\tdate"
+ "references\tchars\lines"
+ "To: you\tIn-Reply-To: <your.mess@ge>"
+ (12345 67890)     ;; modtime of the corresponding article file
+ (to in-reply-to)] ;; contemporary value of nnmail-extra-headers
+(defconst nnmaildir--novlen 5)
+(defmacro nnmaildir--nov-new (beg mid end mtime extra)
+  `(vector ,beg ,mid ,end ,mtime ,extra))
+(defmacro nnmaildir--nov-get-beg   (nov) `(aref ,nov 0))
+(defmacro nnmaildir--nov-get-mid   (nov) `(aref ,nov 1))
+(defmacro nnmaildir--nov-get-end   (nov) `(aref ,nov 2))
+(defmacro nnmaildir--nov-get-mtime (nov) `(aref ,nov 3))
+(defmacro nnmaildir--nov-get-extra (nov) `(aref ,nov 4))
+(defmacro nnmaildir--nov-set-beg   (nov value) `(aset ,nov 0 ,value))
+(defmacro nnmaildir--nov-set-mid   (nov value) `(aset ,nov 1 ,value))
+(defmacro nnmaildir--nov-set-end   (nov value) `(aset ,nov 2 ,value))
+(defmacro nnmaildir--nov-set-mtime (nov value) `(aset ,nov 3 ,value))
+(defmacro nnmaildir--nov-set-extra (nov value) `(aset ,nov 4 ,value))
+
+(defstruct nnmaildir--art
+  (prefix nil :type string)  ;; "time.pid.host"
+  (suffix nil :type string)  ;; ":2,flags"
+  (num    nil :type natnum)  ;; article number
+  (msgid  nil :type string)  ;; "<mess.age@id>"
+  (nov    nil :type vector)) ;; cached nov structure, or nil
+
+(defstruct nnmaildir--grp
+  (name  nil :type string)  ;; "group.name"
+  (new   nil :type list)    ;; new/ modtime
+  (cur   nil :type list)    ;; cur/ modtime
+  (min   1   :type natnum)  ;; minimum article number
+  (count 0   :type natnum)  ;; count of articles
+  (nlist nil :type list)    ;; list of articles, ordered descending by number
+  (flist nil :type vector)  ;; obarray mapping filename prefix->article
+  (mlist nil :type vector)  ;; obarray mapping message-id->article
+  (cache nil :type vector)  ;; nov cache
+  (index nil :type natnum)  ;; index of next cache entry to replace
+  (mmth  nil :type vector)) ;; obarray mapping mark name->dir modtime
+                                       ; ("Mark Mod Time Hash")
+
+(defstruct nnmaildir--srv
+  (address      nil :type string)         ;; server address string
+  (method       nil :type list)           ;; (nnmaildir "address" ...)
+  (prefix       nil :type string)         ;; "nnmaildir+address:"
+  (dir          nil :type string)         ;; "/expanded/path/to/server/dir/"
+  (ls           nil :type function)       ;; directory-files function
+  (groups       nil :type vector)         ;; obarray mapping group name->group
+  (curgrp       nil :type nnmaildir--grp) ;; current group, or nil
+  (error        nil :type string)         ;; last error message, or nil
+  (mtime        nil :type list)           ;; modtime of dir
+  (gnm          nil)                      ;; flag: split from mail-sources?
+  (target-prefix nil :type string))        ;; symlink target prefix
+
+(defun nnmaildir--expired-article (group article)
+  (setf (nnmaildir--art-nov article) nil)
+  (let ((flist  (nnmaildir--grp-flist group))
+       (mlist  (nnmaildir--grp-mlist group))
+       (min    (nnmaildir--grp-min   group))
+       (count  (1- (nnmaildir--grp-count group)))
+       (prefix (nnmaildir--art-prefix article))
+       (msgid  (nnmaildir--art-msgid  article))
+       (new-nlist nil)
+       (nlist-pre '(nil . nil))
+       nlist-post num)
+    (unless (zerop count)
+      (setq nlist-post (nnmaildir--grp-nlist group)
+           num (nnmaildir--art-num article))
+      (if (eq num (caar nlist-post))
+         (setq new-nlist (cdr nlist-post))
+       (setq new-nlist nlist-post
+             nlist-pre nlist-post
+             nlist-post (cdr nlist-post))
+       (while (/= num (caar nlist-post))
+         (setq nlist-pre nlist-post
+               nlist-post (cdr nlist-post)))
+       (setq nlist-post (cdr nlist-post))
+       (if (eq num min)
+           (setq min (caar nlist-pre)))))
+    (let ((inhibit-quit t))
+      (setf (nnmaildir--grp-min   group) min)
+      (setf (nnmaildir--grp-count group) count)
+      (setf (nnmaildir--grp-nlist group) new-nlist)
+      (setcdr nlist-pre nlist-post)
+      (unintern prefix flist)
+      (unintern msgid mlist))))
+
+(defun nnmaildir--nlist-art (group num)
+  (let ((entry (assq num (nnmaildir--grp-nlist group))))
+    (if entry
+       (cdr entry))))
+(defmacro nnmaildir--flist-art (list file)
+  `(symbol-value (intern-soft ,file ,list)))
+(defmacro nnmaildir--mlist-art (list msgid)
+  `(symbol-value (intern-soft ,msgid ,list)))
+
+(defun nnmaildir--pgname (server gname)
+  (let ((prefix (nnmaildir--srv-prefix server)))
+    (if prefix (concat prefix gname)
+      (setq gname (gnus-group-prefixed-name gname
+                                           (nnmaildir--srv-method server)))
+      (setf (nnmaildir--srv-prefix server) (gnus-group-real-prefix gname))
+      gname)))
+
+(defun nnmaildir--param (pgname param)
+  (setq param (gnus-group-find-parameter pgname param 'allow-list))
+  (if (vectorp param) (setq param (aref param 0)))
+  (eval param))
+
+(defmacro nnmaildir--with-nntp-buffer (&rest body)
+  `(save-excursion
+     (set-buffer nntp-server-buffer)
+     ,@body))
+(defmacro nnmaildir--with-work-buffer (&rest body)
+  `(save-excursion
+     (set-buffer (get-buffer-create " *nnmaildir work*"))
+     ,@body))
+(defmacro nnmaildir--with-nov-buffer (&rest body)
+  `(save-excursion
+     (set-buffer (get-buffer-create " *nnmaildir nov*"))
+     ,@body))
+(defmacro nnmaildir--with-move-buffer (&rest body)
+  `(save-excursion
+     (set-buffer (get-buffer-create " *nnmaildir move*"))
+     ,@body))
+
+(defmacro nnmaildir--subdir (dir subdir)
+  `(file-name-as-directory (concat ,dir ,subdir)))
+(defmacro nnmaildir--srvgrp-dir (srv-dir gname)
+  `(nnmaildir--subdir ,srv-dir ,gname))
+(defmacro nnmaildir--tmp       (dir) `(nnmaildir--subdir ,dir "tmp"))
+(defmacro nnmaildir--new       (dir) `(nnmaildir--subdir ,dir "new"))
+(defmacro nnmaildir--cur       (dir) `(nnmaildir--subdir ,dir "cur"))
+(defmacro nnmaildir--nndir     (dir) `(nnmaildir--subdir ,dir ".nnmaildir"))
+(defmacro nnmaildir--nov-dir   (dir) `(nnmaildir--subdir ,dir "nov"))
+(defmacro nnmaildir--marks-dir (dir) `(nnmaildir--subdir ,dir "marks"))
+(defmacro nnmaildir--num-dir   (dir) `(nnmaildir--subdir ,dir "num"))
+(defmacro nnmaildir--num-file  (dir) `(concat ,dir ":"))
+
+(defmacro nnmaildir--unlink (file-arg)
+  `(let ((file ,file-arg))
+     (if (file-attributes file) (delete-file file))))
+(defun nnmaildir--mkdir (dir)
+  (or (file-exists-p (file-name-as-directory dir))
+      (make-directory-internal (directory-file-name dir))))
+(defun nnmaildir--delete-dir-files (dir ls)
+  (when (file-attributes dir)
+    (mapcar 'delete-file (funcall ls dir 'full "\\`[^.]" 'nosort))
+    (delete-directory dir)))
+
+(defun nnmaildir--group-maxnum (server group)
+  (if (zerop (nnmaildir--grp-count group)) 0
+    (let ((x (nnmaildir--srvgrp-dir (nnmaildir--srv-dir server)
+                                   (nnmaildir--grp-name group))))
+      (setq x (nnmaildir--nndir x)
+           x (nnmaildir--num-dir x)
+           x (nnmaildir--num-file x)
+           x (file-attributes x))
+      (if x (1- (nth 1 x)) 0))))
+
+;; Make the given server, if non-nil, be the current server.  Then make the
+;; given group, if non-nil, be the current group of the current server.  Then
+;; return the group object for the current group.
+(defun nnmaildir--prepare (server group)
+  (let (x groups)
+    (catch 'return
+      (if (null server)
+         (unless (setq server nnmaildir--cur-server)
+           (throw 'return nil))
+       (unless (setq server (intern-soft server nnmaildir--servers))
+         (throw 'return nil))
+       (setq server (symbol-value server)
+             nnmaildir--cur-server server))
+      (unless (setq groups (nnmaildir--srv-groups server))
+       (throw 'return nil))
+      (unless (nnmaildir--srv-method server)
+       (setq x (concat "nnmaildir:" (nnmaildir--srv-address server))
+             x (gnus-server-to-method x))
+       (unless x (throw 'return nil))
+       (setf (nnmaildir--srv-method server) x))
+      (if (null group)
+         (unless (setq group (nnmaildir--srv-curgrp server))
+           (throw 'return nil))
+       (unless (setq group (intern-soft group groups))
+         (throw 'return nil))
+       (setq group (symbol-value group)))
+      group)))
+
+(defun nnmaildir--tab-to-space (string)
+  (let ((pos 0))
+    (while (string-match "\t" string pos)
+      (aset string (match-beginning 0) ? )
+      (setq pos (match-end 0))))
+  string)
+
+(defun nnmaildir--update-nov (server group article)
+  (let ((nnheader-file-coding-system 'binary)
+       (srv-dir (nnmaildir--srv-dir server))
+       (storage-version 1) ;; [version article-number msgid [...nov...]]
+       dir gname pgname msgdir prefix suffix file attr mtime novdir novfile
+       nov msgid nov-beg nov-mid nov-end field val old-extra num numdir
+       deactivate-mark)
+    (catch 'return
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname server gname)
+           dir (nnmaildir--srvgrp-dir srv-dir gname)
+           msgdir (if (nnmaildir--param pgname 'read-only)
+                      (nnmaildir--new dir) (nnmaildir--cur dir))
+           prefix (nnmaildir--art-prefix article)
+           suffix (nnmaildir--art-suffix article)
+           file (concat msgdir prefix suffix)
+           attr (file-attributes file))
+      (unless attr
+       (nnmaildir--expired-article group article)
+       (throw 'return nil))
+      (setq mtime (nth 5 attr)
+           attr (nth 7 attr)
+           nov (nnmaildir--art-nov article)
+           dir (nnmaildir--nndir dir)
+           novdir (nnmaildir--nov-dir dir)
+           novfile (concat novdir prefix))
+      (unless (equal nnmaildir--extra nnmail-extra-headers)
+       (setq nnmaildir--extra (copy-sequence nnmail-extra-headers)))
+      (nnmaildir--with-nov-buffer
+       ;; First we'll check for already-parsed NOV data.
+       (cond ((not (file-exists-p novfile))
+              ;; The NOV file doesn't exist; we have to parse the message.
+              (setq nov nil))
+             ((not nov)
+              ;; The file exists, but the data isn't in memory; read the file.
+              (erase-buffer)
+              (nnheader-insert-file-contents novfile)
+              (setq nov (read (current-buffer)))
+              (if (not (and (vectorp nov)
+                            (/= 0 (length nov))
+                            (equal storage-version (aref nov 0))))
+                  ;; This NOV data seems to be in the wrong format.
+                  (setq nov nil)
+                (unless (nnmaildir--art-num   article)
+                  (setf (nnmaildir--art-num   article) (aref nov 1)))
+                (unless (nnmaildir--art-msgid article)
+                  (setf (nnmaildir--art-msgid article) (aref nov 2)))
+                (setq nov (aref nov 3)))))
+       ;; Now check whether the already-parsed data (if we have any) is
+       ;; usable: if the message has been edited or if nnmail-extra-headers
+       ;; has been augmented since this data was parsed from the message,
+       ;; then we have to reparse.  Otherwise it's up-to-date.
+       (when (and nov (equal mtime (nnmaildir--nov-get-mtime nov)))
+         ;; The timestamp matches.  Now check nnmail-extra-headers.
+         (setq old-extra (nnmaildir--nov-get-extra nov))
+         (when (equal nnmaildir--extra old-extra) ;; common case
+           ;; Save memory; use a single copy of the list value.
+           (nnmaildir--nov-set-extra nov nnmaildir--extra)
+           (throw 'return nov))
+         ;; They're not equal, but maybe the new is a subset of the old.
+         (if (null nnmaildir--extra)
+             ;; The empty set is a subset of every set.
+             (throw 'return nov))
+         (if (not (memq nil (mapcar (lambda (e) (memq e old-extra))
+                                    nnmaildir--extra)))
+             (throw 'return nov)))
+       ;; Parse the NOV data out of the message.
+       (erase-buffer)
+       (nnheader-insert-file-contents file)
+       (insert "\n")
+       (goto-char (point-min))
+       (save-restriction
+         (if (search-forward "\n\n" nil 'noerror)
+             (progn
+               (setq nov-mid (count-lines (point) (point-max)))
+               (narrow-to-region (point-min) (1- (point))))
+           (setq nov-mid 0))
+         (goto-char (point-min))
+         (delete-char 1)
+         (setq nov (nnheader-parse-naked-head)
+               field (or (mail-header-lines nov) 0)))
+       (unless (or (zerop field) (nnmaildir--param pgname 'distrust-Lines:))
+         (setq nov-mid field))
+       (setq nov-mid (number-to-string nov-mid)
+             nov-mid (concat (number-to-string attr) "\t" nov-mid))
+       (save-match-data
+         (setq field (or (mail-header-references nov) ""))
+         (nnmaildir--tab-to-space field)
+         (setq nov-mid (concat field "\t" nov-mid)
+               nov-beg (mapconcat
+                         (lambda (f) (nnmaildir--tab-to-space (or f "")))
+                         (list (mail-header-subject nov)
+                               (mail-header-from nov)
+                               (mail-header-date nov)) "\t")
+               nov-end (mapconcat
+                         (lambda (extra)
+                           (setq field (symbol-name (car extra))
+                                 val (cdr extra))
+                           (nnmaildir--tab-to-space field)
+                           (nnmaildir--tab-to-space val)
+                           (concat field ": " val))
+                         (mail-header-extra nov) "\t")))
+       (setq msgid (mail-header-id nov))
+       (if (or (null msgid) (nnheader-fake-message-id-p msgid))
+           (setq msgid (concat "<" prefix "@nnmaildir>")))
+       (nnmaildir--tab-to-space msgid)
+       ;; The data is parsed; create an nnmaildir NOV structure.
+       (setq nov (nnmaildir--nov-new nov-beg nov-mid nov-end mtime
+                                     nnmaildir--extra)
+             num (nnmaildir--art-num article))
+       (unless num
+         ;; Allocate a new article number.
+         (erase-buffer)
+         (setq numdir (nnmaildir--num-dir dir)
+               file (nnmaildir--num-file numdir)
+               num -1)
+         (nnmaildir--mkdir numdir)
+         (write-region "" nil file nil 'no-message)
+         (while file
+           ;; Get the number of links to file.
+           (setq attr (nth 1 (file-attributes file)))
+           (if (= attr num)
+               ;; We've already tried this number, in the previous loop
+               ;; iteration, and failed.
+               (signal 'error `("Corrupt internal nnmaildir data" ,numdir)))
+           ;; If attr is 123, try to link file to "123".  This atomically
+           ;; increases the link count and creates the "123" link, failing
+           ;; if that link was already created by another Gnus, just after
+           ;; we stat()ed file.
+           (condition-case nil
+               (progn
+                 (add-name-to-file file (concat numdir (format "%x" attr)))
+                 (setq file nil)) ;; Stop looping.
+             (file-already-exists nil))
+           (setq num attr))
+         (setf (nnmaildir--art-num article) num))
+       ;; Store this new NOV data in a file
+       (erase-buffer)
+       (prin1 (vector storage-version num msgid nov) (current-buffer))
+       (setq file (concat novfile ":"))
+       (nnmaildir--unlink file)
+       (write-region (point-min) (point-max) file nil 'no-message nil 'excl))
+      (rename-file file novfile 'replace)
+      (setf (nnmaildir--art-msgid article) msgid)
+      nov)))
+
+(defun nnmaildir--cache-nov (group article nov)
+  (let ((cache (nnmaildir--grp-cache group))
+       (index (nnmaildir--grp-index group))
+       goner)
+    (unless (nnmaildir--art-nov article)
+      (setq goner (aref cache index))
+      (if goner (setf (nnmaildir--art-nov goner) nil))
+      (aset cache index article)
+      (setf (nnmaildir--grp-index group) (% (1+ index) (length cache))))
+    (setf (nnmaildir--art-nov article) nov)))
+
+(defun nnmaildir--grp-add-art (server group article)
+  (let ((nov (nnmaildir--update-nov server group article))
+       count num min nlist nlist-cdr insert-nlist)
+    (when nov
+      (setq count (1+ (nnmaildir--grp-count group))
+           num (nnmaildir--art-num article)
+           min (if (= count 1) num
+                 (min num (nnmaildir--grp-min group)))
+           nlist (nnmaildir--grp-nlist group))
+      (if (or (null nlist) (> num (caar nlist)))
+         (setq nlist (cons (cons num article) nlist))
+       (setq insert-nlist t
+             nlist-cdr (cdr nlist))
+       (while (and nlist-cdr (< num (caar nlist-cdr)))
+         (setq nlist nlist-cdr
+               nlist-cdr (cdr nlist))))
+      (let ((inhibit-quit t))
+       (setf (nnmaildir--grp-count group) count)
+       (setf (nnmaildir--grp-min group) min)
+       (if insert-nlist
+           (setcdr nlist (cons (cons num article) nlist-cdr))
+         (setf (nnmaildir--grp-nlist group) nlist))
+       (set (intern (nnmaildir--art-prefix article)
+                    (nnmaildir--grp-flist group))
+            article)
+       (set (intern (nnmaildir--art-msgid article)
+                    (nnmaildir--grp-mlist group))
+            article)
+       (set (intern (nnmaildir--grp-name group)
+                    (nnmaildir--srv-groups server))
+            group))
+      (nnmaildir--cache-nov group article nov)
+      t)))
+
+(defun nnmaildir--group-ls (server pgname)
+  (or (nnmaildir--param pgname 'directory-files)
+      (nnmaildir--srv-ls server)))
+
+(defun nnmaildir-article-number-to-file-name
+  (number group-name server-address-string)
+  (let ((group (nnmaildir--prepare server-address-string group-name))
+       article dir pgname)
+    (catch 'return
+      (unless group
+       ;; The given group or server does not exist.
+       (throw 'return nil))
+      (setq article (nnmaildir--nlist-art group number))
+      (unless article
+       ;; The given article number does not exist in this group.
+       (throw 'return nil))
+      (setq pgname (nnmaildir--pgname nnmaildir--cur-server group-name)
+           dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir group-name)
+           dir (if (nnmaildir--param pgname 'read-only)
+                   (nnmaildir--new dir) (nnmaildir--cur dir)))
+      (concat dir (nnmaildir--art-prefix article)
+             (nnmaildir--art-suffix article)))))
+
+(defun nnmaildir-article-number-to-base-name
+  (number group-name server-address-string)
+  (let ((x (nnmaildir--prepare server-address-string group-name)))
+    (when x
+      (setq x (nnmaildir--nlist-art x number))
+      (and x (cons (nnmaildir--art-prefix x)
+                  (nnmaildir--art-suffix x))))))
+
+(defun nnmaildir-base-name-to-article-number
+  (base-name group-name server-address-string)
+  (let ((x (nnmaildir--prepare server-address-string group-name)))
+    (when x
+      (setq x (nnmaildir--grp-flist x)
+           x (nnmaildir--flist-art x base-name))
+      (and x (nnmaildir--art-num x)))))
+
+(defun nnmaildir--nlist-iterate (nlist ranges func)
+  (let (entry high low nlist2)
+    (if (eq ranges 'all)
+       (setq ranges `((1 . ,(caar nlist)))))
+    (while ranges
+      (setq entry (car ranges) ranges (cdr ranges))
+      (while (and ranges (eq entry (car ranges)))
+       (setq ranges (cdr ranges))) ;; skip duplicates
+      (if (numberp entry)
+         (setq low entry
+               high entry)
+       (setq low (car entry)
+             high (cdr entry)))
+      (setq nlist2 nlist) ;; Don't assume any sorting of ranges
+      (catch 'iterate-loop
+       (while nlist2
+         (if (<= (caar nlist2) high) (throw 'iterate-loop nil))
+         (setq nlist2 (cdr nlist2))))
+      (catch 'iterate-loop
+       (while nlist2
+         (setq entry (car nlist2) nlist2 (cdr nlist2))
+         (if (< (car entry) low) (throw 'iterate-loop nil))
+         (funcall func (cdr entry)))))))
+
+(defun nnmaildir--up2-1 (n)
+  (if (zerop n) 1 (1- (lsh 1 (1+ (logb n))))))
+
+(defun nnmaildir--system-name ()
+  (gnus-replace-in-string
+   (gnus-replace-in-string
+    (gnus-replace-in-string
+     (system-name)
+     "\\\\" "\\134" 'literal)
+    "/" "\\057" 'literal)
+   ":" "\\072" 'literal))
+
+(defun nnmaildir-request-type (group &optional article)
+  'mail)
+
+(defun nnmaildir-status-message (&optional server)
+  (nnmaildir--prepare server nil)
+  (nnmaildir--srv-error nnmaildir--cur-server))
+
+(defun nnmaildir-server-opened (&optional server)
+  (and nnmaildir--cur-server
+       (if server
+          (string-equal server (nnmaildir--srv-address nnmaildir--cur-server))
+        t)
+       (nnmaildir--srv-groups nnmaildir--cur-server)
+       t))
+
+(defun nnmaildir-open-server (server &optional defs)
+  (let ((x server)
+       dir size)
+    (catch 'return
+      (setq server (intern-soft x nnmaildir--servers))
+      (if server
+         (and (setq server (symbol-value server))
+              (nnmaildir--srv-groups server)
+              (setq nnmaildir--cur-server server)
+              (throw 'return t))
+       (setq server (make-nnmaildir--srv :address x))
+       (let ((inhibit-quit t))
+         (set (intern x nnmaildir--servers) server)))
+      (setq dir (assq 'directory defs))
+      (unless dir
+       (setf (nnmaildir--srv-error server)
+             "You must set \"directory\" in the select method")
+       (throw 'return nil))
+      (setq dir (cadr dir)
+           dir (eval dir)
+           dir (expand-file-name dir)
+           dir (file-name-as-directory dir))
+      (unless (file-exists-p dir)
+       (setf (nnmaildir--srv-error server) (concat "No such directory: " dir))
+       (throw 'return nil))
+      (setf (nnmaildir--srv-dir server) dir)
+      (setq x (assq 'directory-files defs))
+      (if (null x)
+         (setq x (if nnheader-directory-files-is-safe 'directory-files
+                   'nnheader-directory-files-safe))
+       (setq x (cadr x))
+       (unless (functionp x)
+         (setf (nnmaildir--srv-error server)
+               (concat "Not a function: " (prin1-to-string x)))
+         (throw 'return nil)))
+      (setf (nnmaildir--srv-ls server) x)
+      (setq size (length (funcall x dir nil "\\`[^.]" 'nosort))
+           size (nnmaildir--up2-1 size))
+      (and (setq x (assq 'get-new-mail defs))
+          (setq x (cdr x))
+          (car x)
+          (setf (nnmaildir--srv-gnm server) t)
+          (require 'nnmail))
+      (setq x (assq 'target-prefix defs))
+      (if x
+         (progn
+           (setq x (cadr x)
+                 x (eval x))
+           (setf (nnmaildir--srv-target-prefix server) x))
+       (setq x (assq 'create-directory defs))
+       (if x
+           (progn
+             (setq x (cadr x)
+                   x (eval x)
+                   x (file-name-as-directory x))
+             (setf (nnmaildir--srv-target-prefix server) x))
+         (setf (nnmaildir--srv-target-prefix server) "")))
+      (setf (nnmaildir--srv-groups server) (make-vector size 0))
+      (setq nnmaildir--cur-server server)
+      t)))
+
+(defun nnmaildir--parse-filename (file)
+  (let ((prefix (car file))
+       timestamp len)
+    (if (string-match "\\`\\([0-9]+\\)\\(\\..*\\)\\'" prefix)
+       (progn
+         (setq timestamp (concat "0000" (match-string 1 prefix))
+               len (- (length timestamp) 4))
+         (vector (string-to-number (substring timestamp 0 len))
+                 (string-to-number (substring timestamp len))
+                 (match-string 2 prefix)
+                 file))
+      file)))
+
+(defun nnmaildir--sort-files (a b)
+  (catch 'return
+    (if (consp a)
+       (throw 'return (and (consp b) (string-lessp (car a) (car b)))))
+    (if (consp b) (throw 'return t))
+    (if (< (aref a 0) (aref b 0)) (throw 'return t))
+    (if (> (aref a 0) (aref b 0)) (throw 'return nil))
+    (if (< (aref a 1) (aref b 1)) (throw 'return t))
+    (if (> (aref a 1) (aref b 1)) (throw 'return nil))
+    (string-lessp (aref a 2) (aref b 2))))
+
+(defun nnmaildir--scan (gname scan-msgs groups method srv-dir srv-ls)
+  (catch 'return
+    (let ((36h-ago (- (car (current-time)) 2))
+         absdir nndir tdir ndir cdir nattr cattr isnew pgname read-only ls
+         files num dir flist group x)
+      (setq absdir (nnmaildir--srvgrp-dir srv-dir gname)
+           nndir (nnmaildir--nndir absdir))
+      (unless (file-exists-p absdir)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such directory: " absdir))
+       (throw 'return nil))
+      (setq tdir (nnmaildir--tmp absdir)
+           ndir (nnmaildir--new absdir)
+           cdir (nnmaildir--cur absdir)
+           nattr (file-attributes ndir)
+           cattr (file-attributes cdir))
+      (unless (and (file-exists-p tdir) nattr cattr)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Not a maildir: " absdir))
+       (throw 'return nil))
+      (setq group (nnmaildir--prepare nil gname)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname))
+      (if group
+         (setq isnew nil)
+       (setq isnew t
+             group (make-nnmaildir--grp :name gname :index 0))
+       (nnmaildir--mkdir nndir)
+       (nnmaildir--mkdir (nnmaildir--nov-dir   nndir))
+       (nnmaildir--mkdir (nnmaildir--marks-dir nndir))
+       (write-region "" nil (concat nndir "markfile") nil 'no-message))
+      (setq read-only (nnmaildir--param pgname 'read-only)
+           ls (or (nnmaildir--param pgname 'directory-files) srv-ls))
+      (unless read-only
+       (setq x (nth 11 (file-attributes tdir)))
+       (unless (and (= x (nth 11 nattr)) (= x (nth 11 cattr)))
+         (setf (nnmaildir--srv-error nnmaildir--cur-server)
+               (concat "Maildir spans filesystems: " absdir))
+         (throw 'return nil))
+       (mapcar
+        (lambda (file)
+          (setq x (file-attributes file))
+          (if (or (> (cadr x) 1) (< (car (nth 4 x)) 36h-ago))
+              (delete-file file)))
+        (funcall ls tdir 'full "\\`[^.]" 'nosort)))
+      (or scan-msgs
+         isnew
+         (throw 'return t))
+      (setq nattr (nth 5 nattr))
+      (if (equal nattr (nnmaildir--grp-new group))
+         (setq nattr nil))
+      (if read-only (setq dir (and (or isnew nattr) ndir))
+       (when (or isnew nattr)
+         (mapcar
+          (lambda (file)
+            (let ((path (concat ndir file)))
+              (and (time-less-p (nth 5 (file-attributes path)) (current-time))
+                   (rename-file path (concat cdir file ":2,")))))
+          (funcall ls ndir nil "\\`[^.]" 'nosort))
+         (setf (nnmaildir--grp-new group) nattr))
+       (setq cattr (nth 5 (file-attributes cdir)))
+       (if (equal cattr (nnmaildir--grp-cur group))
+           (setq cattr nil))
+       (setq dir (and (or isnew cattr) cdir)))
+      (unless dir (throw 'return t))
+      (setq files (funcall ls dir nil "\\`[^.]" 'nosort)
+           files (save-match-data
+                   (mapcar
+                    (lambda (f)
+                      (string-match "\\`\\([^:]*\\)\\(\\(:.*\\)?\\)\\'" f)
+                      (cons (match-string 1 f) (match-string 2 f)))
+                    files)))
+      (when isnew
+       (setq num (nnmaildir--up2-1 (length files)))
+       (setf (nnmaildir--grp-flist group) (make-vector num 0))
+       (setf (nnmaildir--grp-mlist group) (make-vector num 0))
+       (setf (nnmaildir--grp-mmth group) (make-vector 1 0))
+       (setq num (nnmaildir--param pgname 'nov-cache-size))
+       (if (numberp num) (if (< num 1) (setq num 1))
+         (setq num 16
+               cdir (nnmaildir--marks-dir nndir)
+               ndir (nnmaildir--subdir cdir "tick")
+               cdir (nnmaildir--subdir cdir "read"))
+         (mapcar
+          (lambda (file)
+            (setq file (car file))
+            (if (or (not (file-exists-p (concat cdir file)))
+                    (file-exists-p (concat ndir file)))
+                (setq num (1+ num))))
+          files))
+       (setf (nnmaildir--grp-cache group) (make-vector num nil))
+        (let ((inhibit-quit t))
+          (set (intern gname groups) group))
+       (or scan-msgs (throw 'return t)))
+      (setq flist (nnmaildir--grp-flist group)
+           files (mapcar
+                  (lambda (file)
+                    (and (null (nnmaildir--flist-art flist (car file)))
+                         file))
+                  files)
+           files (delq nil files)
+           files (mapcar 'nnmaildir--parse-filename files)
+           files (sort files 'nnmaildir--sort-files))
+      (mapcar
+       (lambda (file)
+        (setq file (if (consp file) file (aref file 3))
+              x (make-nnmaildir--art :prefix (car file) :suffix (cdr file)))
+        (nnmaildir--grp-add-art nnmaildir--cur-server group x))
+       files)
+      (if read-only (setf (nnmaildir--grp-new group) nattr)
+       (setf (nnmaildir--grp-cur group) cattr)))
+    t))
+
+(defun nnmaildir-request-scan (&optional scan-group server)
+  (let ((coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (buffer-file-coding-system nil)
+       (file-coding-system nil)
+       (file-coding-system-alist nil)
+       (nnmaildir-get-new-mail t)
+       (nnmaildir-group-alist nil)
+       (nnmaildir-active-file nil)
+       x srv-ls srv-dir method groups target-prefix group dirs grp-dir seen
+       deactivate-mark)
+    (nnmaildir--prepare server nil)
+    (setq srv-ls (nnmaildir--srv-ls nnmaildir--cur-server)
+         srv-dir (nnmaildir--srv-dir nnmaildir--cur-server)
+         method (nnmaildir--srv-method nnmaildir--cur-server)
+         groups (nnmaildir--srv-groups nnmaildir--cur-server)
+         target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server))
+    (nnmaildir--with-work-buffer
+      (save-match-data
+       (if (stringp scan-group)
+           (if (nnmaildir--scan scan-group t groups method srv-dir srv-ls)
+               (if (nnmaildir--srv-gnm nnmaildir--cur-server)
+                   (nnmail-get-new-mail 'nnmaildir nil nil scan-group))
+             (unintern scan-group groups))
+         (setq x (nth 5 (file-attributes srv-dir))
+               scan-group (null scan-group))
+         (if (equal x (nnmaildir--srv-mtime nnmaildir--cur-server))
+             (if scan-group
+                 (mapatoms (lambda (sym)
+                             (nnmaildir--scan (symbol-name sym) t groups
+                                              method srv-dir srv-ls))
+                           groups))
+           (setq dirs (funcall srv-ls srv-dir nil "\\`[^.]" 'nosort)
+                 dirs (if (zerop (length target-prefix))
+                          dirs
+                        (gnus-remove-if
+                         (lambda (dir)
+                           (and (>= (length dir) (length target-prefix))
+                                (string= (substring dir 0
+                                                    (length target-prefix))
+                                         target-prefix)))
+                         dirs))
+                 seen (nnmaildir--up2-1 (length dirs))
+                 seen (make-vector seen 0))
+           (mapcar
+            (lambda (grp-dir)
+              (if (nnmaildir--scan grp-dir scan-group groups method srv-dir
+                                   srv-ls)
+                  (intern grp-dir seen)))
+            dirs)
+           (setq x nil)
+           (mapatoms (lambda (group)
+                       (setq group (symbol-name group))
+                       (unless (intern-soft group seen)
+                         (setq x (cons group x))))
+                     groups)
+           (mapcar (lambda (grp) (unintern grp groups)) x)
+           (setf (nnmaildir--srv-mtime nnmaildir--cur-server)
+                 (nth 5 (file-attributes srv-dir))))
+         (and scan-group
+              (nnmaildir--srv-gnm nnmaildir--cur-server)
+              (nnmail-get-new-mail 'nnmaildir nil nil))))))
+  t)
+
+(defun nnmaildir-request-list (&optional server)
+  (nnmaildir-request-scan 'find-new-groups server)
+  (let (pgname ro deactivate-mark)
+    (nnmaildir--prepare server nil)
+    (nnmaildir--with-nntp-buffer
+      (erase-buffer)
+      (mapatoms (lambda (group)
+                 (setq pgname (symbol-name group)
+                       pgname (nnmaildir--pgname nnmaildir--cur-server pgname)
+                       group (symbol-value group)
+                       ro (nnmaildir--param pgname 'read-only))
+                 (insert (nnmaildir--grp-name group) " ")
+                  (princ (nnmaildir--group-maxnum nnmaildir--cur-server group)
+                        nntp-server-buffer)
+                 (insert " ")
+                  (princ (nnmaildir--grp-min group) nntp-server-buffer)
+                 (insert " " (if ro "n" "y") "\n"))
+               (nnmaildir--srv-groups nnmaildir--cur-server))))
+  t)
+
+(defun nnmaildir-request-newgroups (date &optional server)
+  (nnmaildir-request-list server))
+
+(defun nnmaildir-retrieve-groups (groups &optional server)
+  (let (group deactivate-mark)
+    (nnmaildir--prepare server nil)
+    (nnmaildir--with-nntp-buffer
+      (erase-buffer)
+      (mapcar
+       (lambda (gname)
+        (setq group (nnmaildir--prepare nil gname))
+        (if (null group) (insert "411 no such news group\n")
+          (insert "211 ")
+          (princ (nnmaildir--grp-count group) nntp-server-buffer)
+          (insert " ")
+          (princ (nnmaildir--grp-min   group) nntp-server-buffer)
+          (insert " ")
+          (princ (nnmaildir--group-maxnum nnmaildir--cur-server group)
+                 nntp-server-buffer)
+          (insert " " gname "\n")))
+       groups)))
+  'group)
+
+(defun nnmaildir-request-update-info (gname info &optional server)
+  (let ((group (nnmaildir--prepare server gname))
+       pgname flist always-marks never-marks old-marks dotfile num dir
+       markdirs marks mark ranges markdir article read end new-marks ls
+       old-mmth new-mmth mtime mark-sym existing missing deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+           flist (nnmaildir--grp-flist group))
+      (when (zerop (nnmaildir--grp-count group))
+       (gnus-info-set-read info nil)
+       (gnus-info-set-marks info nil 'extend)
+       (throw 'return info))
+      (setq old-marks (cons 'read (gnus-info-read info))
+           old-marks (cons old-marks (gnus-info-marks info))
+           always-marks (nnmaildir--param pgname 'always-marks)
+           never-marks (nnmaildir--param pgname 'never-marks)
+           existing (nnmaildir--grp-nlist group)
+           existing (mapcar 'car existing)
+           existing (nreverse existing)
+           existing (gnus-compress-sequence existing 'always-list)
+           missing (list (cons 1 (nnmaildir--group-maxnum
+                                  nnmaildir--cur-server group)))
+           missing (gnus-range-difference missing existing)
+           dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir gname)
+           dir (nnmaildir--nndir dir)
+           dir (nnmaildir--marks-dir dir)
+            ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
+           markdirs (funcall ls dir nil "\\`[^.]" 'nosort)
+           new-mmth (nnmaildir--up2-1 (length markdirs))
+           new-mmth (make-vector new-mmth 0)
+           old-mmth (nnmaildir--grp-mmth group))
+      (mapcar
+       (lambda (mark)
+        (setq markdir (nnmaildir--subdir dir mark)
+              mark-sym (intern mark)
+              ranges nil)
+        (catch 'got-ranges
+          (if (memq mark-sym never-marks) (throw 'got-ranges nil))
+          (when (memq mark-sym always-marks)
+            (setq ranges existing)
+            (throw 'got-ranges nil))
+          (setq mtime (nth 5 (file-attributes markdir)))
+          (set (intern mark new-mmth) mtime)
+          (when (equal mtime (symbol-value (intern-soft mark old-mmth)))
+            (setq ranges (assq mark-sym old-marks))
+            (if ranges (setq ranges (cdr ranges)))
+            (throw 'got-ranges nil))
+          (mapcar
+           (lambda (prefix)
+             (setq article (nnmaildir--flist-art flist prefix))
+             (if article
+                 (setq ranges
+                       (gnus-add-to-range ranges
+                                          `(,(nnmaildir--art-num article))))))
+           (funcall ls markdir nil "\\`[^.]" 'nosort)))
+        (if (eq mark-sym 'read) (setq read ranges)
+          (if ranges (setq marks (cons (cons mark-sym ranges) marks)))))
+       markdirs)
+      (gnus-info-set-read info (gnus-range-add read missing))
+      (gnus-info-set-marks info marks 'extend)
+      (setf (nnmaildir--grp-mmth group) new-mmth)
+      info)))
+
+(defun nnmaildir-request-group (gname &optional server fast)
+  (let ((group (nnmaildir--prepare server gname))
+       deactivate-mark)
+    (catch 'return
+      (unless group
+       ;; (insert "411 no such news group\n")
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (setf (nnmaildir--srv-curgrp nnmaildir--cur-server) group)
+      (if fast (throw 'return t))
+      (nnmaildir--with-nntp-buffer
+       (erase-buffer)
+       (insert "211 ")
+       (princ (nnmaildir--grp-count group) nntp-server-buffer)
+       (insert " ")
+       (princ (nnmaildir--grp-min   group) nntp-server-buffer)
+       (insert " ")
+       (princ (nnmaildir--group-maxnum nnmaildir--cur-server group)
+              nntp-server-buffer)
+       (insert " " gname "\n")
+       t))))
+
+(defun nnmaildir-request-create-group (gname &optional server args)
+  (nnmaildir--prepare server nil)
+  (catch 'return
+    (let ((target-prefix (nnmaildir--srv-target-prefix nnmaildir--cur-server))
+         srv-dir dir groups)
+      (when (zerop (length gname))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Invalid (empty) group name")
+       (throw 'return nil))
+      (when (eq (aref "." 0) (aref gname 0))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Group names may not start with \".\"")
+       (throw 'return nil))
+      (when (save-match-data (string-match "[\0/\t]" gname))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Illegal characters (null, tab, or /) in group name: "
+                     gname))
+       (throw 'return nil))
+      (setq groups (nnmaildir--srv-groups nnmaildir--cur-server))
+      (when (intern-soft gname groups)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Group already exists: " gname))
+       (throw 'return nil))
+      (setq srv-dir (nnmaildir--srv-dir nnmaildir--cur-server))
+      (if (file-name-absolute-p target-prefix)
+         (setq dir (expand-file-name target-prefix))
+       (setq dir srv-dir
+             dir (file-truename dir)
+             dir (concat dir target-prefix)))
+      (setq dir (nnmaildir--subdir dir gname))
+      (nnmaildir--mkdir dir)
+      (nnmaildir--mkdir (nnmaildir--tmp dir))
+      (nnmaildir--mkdir (nnmaildir--new dir))
+      (nnmaildir--mkdir (nnmaildir--cur dir))
+      (unless (string= target-prefix "")
+       (make-symbolic-link (concat target-prefix gname)
+                           (concat srv-dir gname)))
+      (nnmaildir-request-scan 'find-new-groups))))
+
+(defun nnmaildir-request-rename-group (gname new-name &optional server)
+  (let ((group (nnmaildir--prepare server gname))
+       (coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (buffer-file-coding-system nil)
+       (file-coding-system nil)
+       (file-coding-system-alist nil)
+       srv-dir x groups)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (when (zerop (length new-name))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Invalid (empty) group name")
+       (throw 'return nil))
+      (when (eq (aref "." 0) (aref new-name 0))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Group names may not start with \".\"")
+       (throw 'return nil))
+      (when (save-match-data (string-match "[\0/\t]" new-name))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Illegal characters (null, tab, or /) in group name: "
+                     new-name))
+       (throw 'return nil))
+      (if (string-equal gname new-name) (throw 'return t))
+      (when (intern-soft new-name
+                        (nnmaildir--srv-groups nnmaildir--cur-server))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Group already exists: " new-name))
+       (throw 'return nil))
+      (setq srv-dir (nnmaildir--srv-dir nnmaildir--cur-server))
+      (condition-case err
+         (rename-file (concat srv-dir gname)
+                      (concat srv-dir new-name))
+       (error
+        (setf (nnmaildir--srv-error nnmaildir--cur-server)
+              (concat "Error renaming link: " (prin1-to-string err)))
+        (throw 'return nil)))
+      (setq x (nnmaildir--srv-groups nnmaildir--cur-server)
+           groups (make-vector (length x) 0))
+      (mapatoms (lambda (sym)
+                 (unless (eq (symbol-value sym) group)
+                   (set (intern (symbol-name sym) groups)
+                        (symbol-value sym))))
+               x)
+      (setq group (copy-sequence group))
+      (setf (nnmaildir--grp-name group) new-name)
+      (set (intern new-name groups) group)
+      (setf (nnmaildir--srv-groups nnmaildir--cur-server) groups)
+      t)))
+
+(defun nnmaildir-request-delete-group (gname force &optional server)
+  (let ((group (nnmaildir--prepare server gname))
+       pgname grp-dir target dir ls deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+           grp-dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           target (car (file-attributes (concat grp-dir gname)))
+           grp-dir (nnmaildir--srvgrp-dir grp-dir gname))
+      (unless (or force (stringp target))
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Not a symlink: " gname))
+       (throw 'return nil))
+      (if (eq group (nnmaildir--srv-curgrp nnmaildir--cur-server))
+         (setf (nnmaildir--srv-curgrp nnmaildir--cur-server) nil))
+      (unintern gname (nnmaildir--srv-groups nnmaildir--cur-server))
+      (if (not force)
+         (progn
+           (setq grp-dir (directory-file-name grp-dir))
+           (nnmaildir--unlink grp-dir))
+       (setq ls (nnmaildir--group-ls nnmaildir--cur-server pgname))
+       (if (nnmaildir--param pgname 'read-only)
+           (progn (delete-directory  (nnmaildir--tmp grp-dir))
+                  (nnmaildir--unlink (nnmaildir--new grp-dir))
+                  (delete-directory  (nnmaildir--cur grp-dir)))
+         (nnmaildir--delete-dir-files (nnmaildir--tmp grp-dir) ls)
+         (nnmaildir--delete-dir-files (nnmaildir--new grp-dir) ls)
+         (nnmaildir--delete-dir-files (nnmaildir--cur grp-dir) ls))
+       (setq dir (nnmaildir--nndir grp-dir))
+       (mapcar (lambda (subdir) (nnmaildir--delete-dir-files subdir ls))
+               `(,(nnmaildir--nov-dir dir) ,(nnmaildir--num-dir dir)
+                 ,@(funcall ls (nnmaildir--marks-dir dir) 'full "\\`[^.]"
+                            'nosort)))
+       (setq dir (nnmaildir--nndir grp-dir))
+       (nnmaildir--unlink (concat dir "markfile"))
+       (nnmaildir--unlink (concat dir "markfile{new}"))
+       (delete-directory (nnmaildir--marks-dir dir))
+       (delete-directory dir)
+       (if (not (stringp target))
+           (delete-directory grp-dir)
+         (setq grp-dir (directory-file-name grp-dir)
+               dir target)
+         (unless (eq (aref "/" 0) (aref dir 0))
+           (setq dir (concat (file-truename
+                              (nnmaildir--srv-dir nnmaildir--cur-server))
+                             dir)))
+         (delete-directory dir)
+         (nnmaildir--unlink grp-dir)))
+      t)))
+
+(defun nnmaildir-retrieve-headers (articles &optional gname server fetch-old)
+  (let ((group (nnmaildir--prepare server gname))
+       srv-dir dir nlist mlist article num start stop nov nlist2 insert-nov
+       deactivate-mark)
+    (setq insert-nov
+         (lambda (article)
+           (setq nov (nnmaildir--update-nov nnmaildir--cur-server group
+                                            article))
+           (when nov
+             (nnmaildir--cache-nov group article nov)
+             (setq num (nnmaildir--art-num article))
+             (princ num nntp-server-buffer)
+             (insert "\t" (nnmaildir--nov-get-beg nov) "\t"
+                     (nnmaildir--art-msgid article) "\t"
+                     (nnmaildir--nov-get-mid nov) "\tXref: nnmaildir "
+                     gname ":")
+             (princ num nntp-server-buffer)
+             (insert "\t" (nnmaildir--nov-get-end nov) "\n"))))
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (if gname (concat "No such group: " gname) "No current group"))
+       (throw 'return nil))
+      (nnmaildir--with-nntp-buffer
+       (erase-buffer)
+       (setq mlist (nnmaildir--grp-mlist group)
+             nlist (nnmaildir--grp-nlist group)
+             gname (nnmaildir--grp-name group)
+             srv-dir (nnmaildir--srv-dir nnmaildir--cur-server)
+             dir (nnmaildir--srvgrp-dir srv-dir gname))
+       (cond
+        ((null nlist))
+        ((and fetch-old (not (numberp fetch-old)))
+         (nnmaildir--nlist-iterate nlist 'all insert-nov))
+        ((null articles))
+        ((stringp (car articles))
+         (mapcar
+          (lambda (msgid)
+            (setq article (nnmaildir--mlist-art mlist msgid))
+            (if article (funcall insert-nov article)))
+          articles))
+        (t
+         (if fetch-old
+             ;; Assume the article range list is sorted ascending
+             (setq stop (car articles)
+                   start (car (last articles))
+                   stop  (if (numberp stop)  stop  (car stop))
+                   start (if (numberp start) start (cdr start))
+                   stop (- stop fetch-old)
+                   stop (if (< stop 1) 1 stop)
+                   articles (list (cons stop start))))
+         (nnmaildir--nlist-iterate nlist articles insert-nov)))
+       (sort-numeric-fields 1 (point-min) (point-max))
+       'nov))))
+
+(defun nnmaildir-request-article (num-msgid &optional gname server to-buffer)
+  (let ((group (nnmaildir--prepare server gname))
+       (case-fold-search t)
+       list article dir pgname deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (if gname (concat "No such group: " gname) "No current group"))
+       (throw 'return nil))
+      (if (numberp num-msgid)
+         (setq article (nnmaildir--nlist-art group num-msgid))
+       (setq list (nnmaildir--grp-mlist group)
+             article (nnmaildir--mlist-art list num-msgid))
+       (if article (setq num-msgid (nnmaildir--art-num article))
+         (catch 'found
+           (mapatoms
+              (lambda (group-sym)
+                (setq group (symbol-value group-sym)
+                      list (nnmaildir--grp-mlist group)
+                      article (nnmaildir--mlist-art list num-msgid))
+                (when article
+                  (setq num-msgid (nnmaildir--art-num article))
+                  (throw 'found nil)))
+              (nnmaildir--srv-groups nnmaildir--cur-server))))
+       (unless article
+         (setf (nnmaildir--srv-error nnmaildir--cur-server) "No such article")
+         (throw 'return nil)))
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+           dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir gname)
+           dir (if (nnmaildir--param pgname 'read-only)
+                   (nnmaildir--new dir) (nnmaildir--cur dir))
+           nnmaildir-article-file-name
+           (concat dir
+                   (nnmaildir--art-prefix article)
+                   (nnmaildir--art-suffix article)))
+      (unless (file-exists-p nnmaildir-article-file-name)
+       (nnmaildir--expired-article group article)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Article has expired")
+       (throw 'return nil))
+      (save-excursion
+       (set-buffer (or to-buffer nntp-server-buffer))
+       (erase-buffer)
+       (nnheader-insert-file-contents nnmaildir-article-file-name))
+      (cons gname num-msgid))))
+
+(defun nnmaildir-request-post (&optional server)
+  (let (message-required-mail-headers)
+    (funcall message-send-mail-function)))
+
+(defun nnmaildir-request-replace-article (number gname buffer)
+  (let ((group (nnmaildir--prepare nil gname))
+       (coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (buffer-file-coding-system nil)
+       (file-coding-system nil)
+       (file-coding-system-alist nil)
+       dir file article suffix tmpfile deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (when (nnmaildir--param (nnmaildir--pgname nnmaildir--cur-server gname)
+                             'read-only)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Read-only group: " group))
+       (throw 'return nil))
+      (setq dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir gname)
+           article (nnmaildir--nlist-art group number))
+      (unless article
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such article: " (number-to-string number)))
+       (throw 'return nil))
+      (setq suffix (nnmaildir--art-suffix article)
+           file (nnmaildir--art-prefix article)
+           tmpfile (concat (nnmaildir--tmp dir) file))
+      (when (file-exists-p tmpfile)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "File exists: " tmpfile))
+       (throw 'return nil))
+      (save-excursion
+       (set-buffer buffer)
+       (write-region (point-min) (point-max) tmpfile nil 'no-message nil
+                     'excl))
+      (unix-sync) ;; no fsync :(
+      (rename-file tmpfile (concat (nnmaildir--cur dir) file suffix) 'replace)
+      t)))
+
+(defun nnmaildir-request-move-article (article gname server accept-form
+                                              &optional last)
+  (let ((group (nnmaildir--prepare server gname))
+       pgname suffix result nnmaildir--file deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+           article (nnmaildir--nlist-art group article))
+      (unless article
+       (setf (nnmaildir--srv-error nnmaildir--cur-server) "No such article")
+       (throw 'return nil))
+      (setq suffix (nnmaildir--art-suffix article)
+           nnmaildir--file (nnmaildir--srv-dir nnmaildir--cur-server)
+           nnmaildir--file (nnmaildir--srvgrp-dir nnmaildir--file gname)
+           nnmaildir--file (if (nnmaildir--param pgname 'read-only)
+                               (nnmaildir--new nnmaildir--file)
+                             (nnmaildir--cur nnmaildir--file))
+           nnmaildir--file (concat nnmaildir--file
+                                   (nnmaildir--art-prefix article)
+                                   suffix))
+      (unless (file-exists-p nnmaildir--file)
+       (nnmaildir--expired-article group article)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             "Article has expired")
+       (throw 'return nil))
+      (nnmaildir--with-move-buffer
+       (erase-buffer)
+       (nnheader-insert-file-contents nnmaildir--file)
+       (setq result (eval accept-form)))
+      (unless (or (null result) (nnmaildir--param pgname 'read-only))
+       (nnmaildir--unlink nnmaildir--file)
+       (nnmaildir--expired-article group article))
+      result)))
+
+(defun nnmaildir-request-accept-article (gname &optional server last)
+  (let ((group (nnmaildir--prepare server gname))
+       (coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (buffer-file-coding-system nil)
+       (file-coding-system nil)
+       (file-coding-system-alist nil)
+       srv-dir dir file time tmpfile curfile 24h article)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (throw 'return nil))
+      (setq gname (nnmaildir--grp-name group))
+      (when (nnmaildir--param (nnmaildir--pgname nnmaildir--cur-server gname)
+                             'read-only)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "Read-only group: " gname))
+       (throw 'return nil))
+      (setq srv-dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir srv-dir gname)
+           time (current-time)
+           file (format-time-string "%s." time))
+      (unless (string-equal nnmaildir--delivery-time file)
+       (setq nnmaildir--delivery-time file
+             nnmaildir--delivery-count 0))
+      (when (and (consp (cdr time))
+                (consp (cddr time)))
+       (setq file (concat file "M" (number-to-string (caddr time)))))
+      (setq file (concat file nnmaildir--delivery-pid)
+           file (concat file "Q" (number-to-string nnmaildir--delivery-count))
+           file (concat file "." (nnmaildir--system-name))
+           tmpfile (concat (nnmaildir--tmp dir) file)
+           curfile (concat (nnmaildir--cur dir) file ":2,"))
+      (when (file-exists-p tmpfile)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "File exists: " tmpfile))
+       (throw 'return nil))
+      (when (file-exists-p curfile)
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "File exists: " curfile))
+       (throw 'return nil))
+      (setq nnmaildir--delivery-count (1+ nnmaildir--delivery-count)
+           24h (run-with-timer 86400 nil
+                               (lambda ()
+                                 (nnmaildir--unlink tmpfile)
+                                 (setf (nnmaildir--srv-error
+                                         nnmaildir--cur-server)
+                                       "24-hour timer expired")
+                                 (throw 'return nil))))
+      (condition-case nil
+         (add-name-to-file nnmaildir--file tmpfile)
+       (error
+        (write-region (point-min) (point-max) tmpfile nil 'no-message nil
+                      'excl)
+        (unix-sync))) ;; no fsync :(
+      (cancel-timer 24h)
+      (condition-case err
+         (add-name-to-file tmpfile curfile)
+       (error
+        (setf (nnmaildir--srv-error nnmaildir--cur-server)
+              (concat "Error linking: " (prin1-to-string err)))
+        (nnmaildir--unlink tmpfile)
+        (throw 'return nil)))
+      (nnmaildir--unlink tmpfile)
+      (setq article (make-nnmaildir--art :prefix file :suffix ":2,"))
+      (if (nnmaildir--grp-add-art nnmaildir--cur-server group article)
+         (cons gname (nnmaildir--art-num article))))))
+
+(defun nnmaildir-save-mail (group-art)
+  (catch 'return
+    (unless group-art
+      (throw 'return nil))
+    (let (ga gname x groups nnmaildir--file deactivate-mark)
+      (save-excursion
+       (goto-char (point-min))
+       (save-match-data
+         (while (looking-at "From ")
+           (replace-match "X-From-Line: ")
+           (forward-line 1))))
+      (setq groups (nnmaildir--srv-groups nnmaildir--cur-server)
+           ga (car group-art) group-art (cdr group-art)
+           gname (car ga))
+      (or (intern-soft gname groups)
+         (nnmaildir-request-create-group gname)
+         (throw 'return nil)) ;; not that nnmail bothers to check :(
+      (unless (nnmaildir-request-accept-article gname)
+       (throw 'return nil))
+      (setq nnmaildir--file (nnmaildir--srv-dir nnmaildir--cur-server)
+           nnmaildir--file (nnmaildir--srvgrp-dir nnmaildir--file gname)
+           x (nnmaildir--prepare nil gname)
+           x (nnmaildir--grp-nlist x)
+           x (cdar x)
+           nnmaildir--file (concat nnmaildir--file
+                                   (nnmaildir--art-prefix x)
+                                   (nnmaildir--art-suffix x)))
+      (delq nil
+           (mapcar
+            (lambda (ga)
+              (setq gname (car ga))
+              (and (or (intern-soft gname groups)
+                       (nnmaildir-request-create-group gname))
+                   (nnmaildir-request-accept-article gname)
+                   ga))
+            group-art)))))
+
+(defun nnmaildir-active-number (gname)
+  0)
+
+(defun nnmaildir-request-expire-articles (ranges &optional gname server force)
+  (let ((no-force (not force))
+       (group (nnmaildir--prepare server gname))
+       pgname time boundary bound-iter high low target dir nlist nlist2
+       stop article didnt nnmaildir--file nnmaildir-article-file-name
+       deactivate-mark)
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (if gname (concat "No such group: " gname) "No current group"))
+       (throw 'return (gnus-uncompress-range ranges)))
+      (setq gname (nnmaildir--grp-name group)
+           pgname (nnmaildir--pgname nnmaildir--cur-server gname))
+      (if (nnmaildir--param pgname 'read-only)
+         (throw 'return (gnus-uncompress-range ranges)))
+      (setq time (nnmaildir--param pgname 'expire-age))
+      (unless time
+       (setq time (or (and nnmail-expiry-wait-function
+                           (funcall nnmail-expiry-wait-function gname))
+                      nnmail-expiry-wait))
+       (if (eq time 'immediate)
+           (setq time 0)
+         (if (numberp time)
+             (setq time (* time 86400)))))
+      (when no-force
+       (unless (integerp time) ;; handle 'never
+         (throw 'return (gnus-uncompress-range ranges)))
+       (setq boundary (current-time)
+             high (- (car boundary) (/ time 65536))
+             low (- (cadr boundary) (% time 65536)))
+       (if (< low 0)
+           (setq low (+ low 65536)
+                 high (1- high)))
+       (setcar (cdr boundary) low)
+       (setcar boundary high))
+      (setq dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir gname)
+           dir (nnmaildir--cur dir)
+           nlist (nnmaildir--grp-nlist group)
+           ranges (reverse ranges))
+      (nnmaildir--with-move-buffer
+       (nnmaildir--nlist-iterate
+        nlist ranges
+        (lambda (article)
+          (setq nnmaildir--file (nnmaildir--art-prefix article)
+                nnmaildir--file (concat dir nnmaildir--file
+                                        (nnmaildir--art-suffix article))
+                time (file-attributes nnmaildir--file))
+          (cond
+           ((null time)
+            (nnmaildir--expired-article group article))
+           ((and no-force
+                 (progn
+                   (setq time (nth 5 time)
+                         bound-iter boundary)
+                   (while (and bound-iter time
+                               (= (car bound-iter) (car time)))
+                     (setq bound-iter (cdr bound-iter)
+                           time (cdr time)))
+                   (and bound-iter time
+                        (car-less-than-car bound-iter time))))
+            (setq didnt (cons (nnmaildir--art-num article) didnt)))
+           (t
+            (setq nnmaildir-article-file-name nnmaildir--file
+                  target (if force nil
+                           (save-excursion
+                             (save-restriction
+                               (nnmaildir--param pgname 'expire-group)))))
+            (when (and (stringp target)
+                       (not (string-equal target pgname))) ;; Move it.
+              (erase-buffer)
+              (nnheader-insert-file-contents nnmaildir--file)
+              (gnus-request-accept-article target nil nil 'no-encode))
+            (if (equal target pgname)
+                ;; Leave it here.
+                (setq didnt (cons (nnmaildir--art-num article) didnt))
+              (nnmaildir--unlink nnmaildir--file)
+              (nnmaildir--expired-article group article))))))
+       (erase-buffer))
+      didnt)))
+
+(defun nnmaildir-request-set-mark (gname actions &optional server)
+  (let ((group (nnmaildir--prepare server gname))
+       (coding-system-for-write nnheader-file-coding-system)
+       (output-coding-system nnheader-file-coding-system)
+       (buffer-file-coding-system nil)
+       (file-coding-system nil)
+       (file-coding-system-alist nil)
+       del-mark del-action add-action set-action marksdir markfile nlist
+       ranges begin end article all-marks todo-marks did-marks mdir mfile
+       pgname ls permarkfile deactivate-mark)
+    (setq del-mark
+         (lambda (mark)
+           (setq mfile (nnmaildir--subdir marksdir (symbol-name mark))
+                 mfile (concat mfile (nnmaildir--art-prefix article)))
+           (nnmaildir--unlink mfile))
+         del-action (lambda (article) (mapcar del-mark todo-marks))
+         add-action
+         (lambda (article)
+           (mapcar
+            (lambda (mark)
+              (setq mdir (nnmaildir--subdir marksdir (symbol-name mark))
+                    permarkfile (concat mdir ":")
+                    mfile (concat mdir (nnmaildir--art-prefix article)))
+              (unless (memq mark did-marks)
+                (setq did-marks (cons mark did-marks))
+                (nnmaildir--mkdir mdir)
+                (unless (file-attributes permarkfile)
+                  (condition-case nil
+                      (add-name-to-file markfile permarkfile)
+                    (file-error
+                     ;; AFS can't make hard links in separate directories
+                     (write-region "" nil permarkfile nil 'no-message)))))
+              (unless (file-exists-p mfile)
+                (add-name-to-file permarkfile mfile)))
+            todo-marks))
+         set-action (lambda (article)
+                      (funcall add-action)
+                      (mapcar (lambda (mark)
+                                (unless (memq mark todo-marks)
+                                  (funcall del-mark mark)))
+                              all-marks)))
+    (catch 'return
+      (unless group
+       (setf (nnmaildir--srv-error nnmaildir--cur-server)
+             (concat "No such group: " gname))
+       (mapcar (lambda (action)
+                 (setq ranges (gnus-range-add ranges (car action))))
+               actions)
+       (throw 'return ranges))
+      (setq nlist (nnmaildir--grp-nlist group)
+           marksdir (nnmaildir--srv-dir nnmaildir--cur-server)
+           marksdir (nnmaildir--srvgrp-dir marksdir gname)
+           marksdir (nnmaildir--nndir marksdir)
+           markfile (concat marksdir "markfile")
+           marksdir (nnmaildir--marks-dir marksdir)
+           gname (nnmaildir--grp-name group)
+            pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+            ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
+           all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort)
+           all-marks (mapcar 'intern all-marks))
+      (mapcar
+       (lambda (action)
+        (setq ranges (car action)
+              todo-marks (caddr action))
+        (mapcar (lambda (mark) (add-to-list 'all-marks mark)) todo-marks)
+        (if (numberp (cdr ranges)) (setq ranges (list ranges)))
+        (nnmaildir--nlist-iterate nlist ranges
+                                  (cond ((eq 'del (cadr action)) del-action)
+                                        ((eq 'add (cadr action)) add-action)
+                                        (t set-action))))
+       actions)
+      nil)))
+
+(defun nnmaildir-close-group (gname &optional server)
+  (let ((group (nnmaildir--prepare server gname))
+       pgname ls dir msgdir files flist dirs)
+    (if (null group)
+       (progn
+         (setf (nnmaildir--srv-error nnmaildir--cur-server)
+               (concat "No such group: " gname))
+         nil)
+      (setq pgname (nnmaildir--pgname nnmaildir--cur-server gname)
+           ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
+           dir (nnmaildir--srv-dir nnmaildir--cur-server)
+           dir (nnmaildir--srvgrp-dir dir gname)
+           msgdir (if (nnmaildir--param pgname 'read-only)
+                      (nnmaildir--new dir) (nnmaildir--cur dir))
+           dir (nnmaildir--nndir dir)
+           dirs (cons (nnmaildir--nov-dir dir)
+                      (funcall ls (nnmaildir--marks-dir dir) 'full "\\`[^.]"
+                               'nosort))
+           dirs (mapcar
+                 (lambda (dir)
+                   (cons dir (funcall ls dir nil "\\`[^.]" 'nosort)))
+                 dirs)
+           files (funcall ls msgdir nil "\\`[^.]" 'nosort)
+           flist (nnmaildir--up2-1 (length files))
+           flist (make-vector flist 0))
+      (save-match-data
+       (mapcar
+        (lambda (file)
+          (string-match "\\`\\([^:]*\\)\\(:.*\\)?\\'" file)
+          (intern (match-string 1 file) flist))
+        files))
+      (mapcar
+       (lambda (dir)
+        (setq files (cdr dir)
+              dir (file-name-as-directory (car dir)))
+        (mapcar
+         (lambda (file)
+           (unless (or (intern-soft file flist) (string= file ":"))
+             (setq file (concat dir file))
+             (delete-file file)))
+         files))
+       dirs)
+      t)))
+
+(defun nnmaildir-close-server (&optional server)
+  (let (flist ls dirs dir files file x)
+    (nnmaildir--prepare server nil)
+    (when nnmaildir--cur-server
+      (setq server nnmaildir--cur-server
+           nnmaildir--cur-server nil)
+      (unintern (nnmaildir--srv-address server) nnmaildir--servers)))
+  t)
+
+(defun nnmaildir-request-close ()
+  (let (servers buffer)
+    (mapatoms (lambda (server)
+               (setq servers (cons (symbol-name server) servers)))
+             nnmaildir--servers)
+    (mapcar 'nnmaildir-close-server servers)
+    (setq buffer (get-buffer " *nnmaildir work*"))
+    (if buffer (kill-buffer buffer))
+    (setq buffer (get-buffer " *nnmaildir nov*"))
+    (if buffer (kill-buffer buffer))
+    (setq buffer (get-buffer " *nnmaildir move*"))
+    (if buffer (kill-buffer buffer)))
+  t)
+
+(provide 'nnmaildir)
+
+;; Local Variables:
+;; indent-tabs-mode: t
+;; fill-column: 77
+;; End:
+
+;;; nnmaildir.el ends here
index ee703ff..efa5e5a 100644 (file)
@@ -1,8 +1,10 @@
 ;;; nnmbox.el --- mail mbox access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
+
 (require 'nnheader)
 (require 'message)
 (require 'nnmail)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
+(require 'gnus-range)
 
 (nnoo-declare nnmbox)
 
 (defvoo nnmbox-current-group nil
   "Current nnmbox news group directory.")
 
-(defconst nnmbox-mbox-buffer nil)
+(defvar nnmbox-mbox-buffer nil)
 
 (defvoo nnmbox-status-string "")
 
 (defvoo nnmbox-group-alist nil)
 (defvoo nnmbox-active-timestamp nil)
 
+(defvoo nnmbox-file-coding-system 'binary)
+(defvoo nnmbox-file-coding-system-for-write nil)
+(defvoo nnmbox-active-file-coding-system 'binary)
+(defvoo nnmbox-active-file-coding-system-for-write nil)
+
+(defvar nnmbox-group-building-active-articles nil)
+(defvar nnmbox-group-active-articles nil)
 \f
 
 ;;; Interface functions
     (erase-buffer)
     (let ((number (length sequence))
          (count 0)
-         article art-string start stop)
+         article start stop)
       (nnmbox-possibly-change-newsgroup newsgroup server)
       (while sequence
        (setq article (car sequence))
-       (setq art-string (nnmbox-article-string article))
        (set-buffer nnmbox-mbox-buffer)
-       (when (or (search-forward art-string nil t)
-                 (progn (goto-char (point-min))
-                        (search-forward art-string nil t)))
+       (when (nnmbox-find-article article)
          (setq start
                (save-excursion
                  (re-search-backward
   (nnmbox-possibly-change-newsgroup newsgroup server)
   (save-excursion
     (set-buffer nnmbox-mbox-buffer)
-    (goto-char (point-min))
-    (when (search-forward (nnmbox-article-string article) nil t)
+    (when (nnmbox-find-article article)
       (let (start stop)
        (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
        (setq start (point))
            (forward-line 1))
          (if (numberp article)
              (cons nnmbox-current-group article)
-           (nnmbox-article-group-number)))))))
+           (nnmbox-article-group-number nil)))))))
 
 (deffoo nnmbox-request-group (group &optional server dont-check)
+  (nnmbox-possibly-change-newsgroup nil server)
   (let ((active (cadr (assoc group nnmbox-group-alist))))
     (cond
      ((or (null active)
                       (1+ (- (cdr active) (car active)))
                       (car active) (cdr active) group)))))
 
+(defun nnmbox-save-buffer ()
+  (let* ((coding-system-for-write (or nnmbox-file-coding-system-for-write
+                                     nnmbox-file-coding-system))
+        (output-coding-system coding-system-for-write))
+    (save-buffer)))
+
+(defun nnmbox-save-active (group-alist active-file)
+  (let ((nnmail-active-file-coding-system
+        (or nnmbox-active-file-coding-system-for-write
+            nnmbox-active-file-coding-system)))
+    (nnmail-save-active group-alist active-file)))
+
 (deffoo nnmbox-request-scan (&optional group server)
   (nnmbox-possibly-change-newsgroup group server)
   (nnmbox-read-mbox)
    (lambda ()
      (save-excursion
        (set-buffer nnmbox-mbox-buffer)
-       (save-buffer)))
+       (nnmbox-save-buffer)))
    (file-name-directory nnmbox-mbox-file)
    group
    (lambda ()
         (set-buffer nnmbox-mbox-buffer)
         (goto-char (point-max))
         (insert-buffer-substring in-buf)))
-     (nnmail-save-active nnmbox-group-alist nnmbox-active-file))))
+     (nnmbox-save-active nnmbox-group-alist nnmbox-active-file))))
 
 (deffoo nnmbox-close-group (group &optional server)
   t)
 
+(deffoo nnmbox-request-create-group (group &optional server args)
+  (nnmail-activate 'nnmbox)
+  (unless (assoc group nnmbox-group-alist)
+    (push (list group (cons 1 0))
+         nnmbox-group-alist)
+    (nnmbox-save-active nnmbox-group-alist nnmbox-active-file))
+  t)
+
 (deffoo nnmbox-request-list (&optional server)
   (save-excursion
-    (nnmail-find-file nnmbox-active-file)
+    (let ((nnmail-file-coding-system
+          nnmbox-active-file-coding-system))
+      (nnmail-find-file nnmbox-active-file))
     (setq nnmbox-group-alist (nnmail-get-active))
     t))
 
   (nnheader-report 'nnmbox "LIST NEWSGROUPS is not implemented."))
 
 (deffoo nnmbox-request-expire-articles
-  (articles newsgroup &optional server force)
+    (articles newsgroup &optional server force)
   (nnmbox-possibly-change-newsgroup newsgroup server)
   (let* ((is-old t)
         rest)
     (save-excursion
       (set-buffer nnmbox-mbox-buffer)
       (while (and articles is-old)
-       (goto-char (point-min))
-       (when (search-forward (nnmbox-article-string (car articles)) nil t)
+       (when (nnmbox-find-article (car articles))
          (if (setq is-old
                    (nnmail-expired-article-p
                     newsgroup
                     (buffer-substring
                      (point) (progn (end-of-line) (point))) force))
              (progn
+               (unless (eq nnmail-expiry-target 'delete)
+                 (with-temp-buffer
+                   (nnmbox-request-article (car articles)
+                                           newsgroup server
+                                           (current-buffer))
+                   (let ((nnml-current-directory nil))
+                     (nnmail-expiry-target-group
+                      nnmail-expiry-target newsgroup)))
+                 (nnmbox-possibly-change-newsgroup newsgroup server))
                (nnheader-message 5 "Deleting article %d in %s..."
                                  (car articles) newsgroup)
                (nnmbox-delete-mail))
            (push (car articles) rest)))
        (setq articles (cdr articles)))
-      (save-buffer)
+      (nnmbox-save-buffer)
       ;; Find the lowest active article in this group.
       (let ((active (nth 1 (assoc newsgroup nnmbox-group-alist))))
-       (goto-char (point-min))
-       (while (and (not (search-forward
-                         (nnmbox-article-string (car active)) nil t))
+       (while (and (not (nnmbox-find-article (car active)))
                    (<= (car active) (cdr active)))
-         (setcar active (1+ (car active)))
-         (goto-char (point-min))))
-      (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
+         (setcar active (1+ (car active)))))
+      (nnmbox-save-active nnmbox-group-alist nnmbox-active-file)
       (nconc rest articles))))
 
 (deffoo nnmbox-request-move-article
-  (article group server accept-form &optional last)
+    (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnmbox move*"))
        result)
     (and
      (nnmbox-request-article article group server)
      (save-excursion
        (set-buffer buf)
-       (buffer-disable-undo (current-buffer))
        (erase-buffer)
        (insert-buffer-substring nntp-server-buffer)
        (goto-char (point-min))
        (while (re-search-forward
               "^X-Gnus-Newsgroup:"
               (save-excursion (search-forward "\n\n" nil t) (point)) t)
-        (delete-region (progn (beginning-of-line) (point))
-                       (progn (forward-line 1) (point))))
+        (gnus-delete-line))
        (setq result (eval accept-form))
        (kill-buffer buf)
        result)
      (save-excursion
        (nnmbox-possibly-change-newsgroup group server)
        (set-buffer nnmbox-mbox-buffer)
-       (goto-char (point-min))
-       (when (search-forward (nnmbox-article-string article) nil t)
+       (when (nnmbox-find-article article)
         (nnmbox-delete-mail))
-       (and last (save-buffer))))
+       (and last (nnmbox-save-buffer))))
     result))
 
 (deffoo nnmbox-request-accept-article (group &optional server last)
        (while (re-search-backward "^X-Gnus-Newsgroup: " nil t)
         (delete-region (point) (progn (forward-line 1) (point))))
        (when nnmail-cache-accepted-message-ids
-        (nnmail-cache-insert (nnmail-fetch-field "message-id")))
+        (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                             group
+                             (nnmail-fetch-field "subject")
+                             (nnmail-fetch-field "from")))
        (setq result (if (stringp group)
                        (list (cons group (nnmbox-active-number group)))
                      (nnmail-article-group 'nnmbox-active-number)))
        (when last
         (when nnmail-cache-accepted-message-ids
           (nnmail-cache-close))
-        (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
-        (save-buffer))))
+        (nnmbox-save-active nnmbox-group-alist nnmbox-active-file)
+        (nnmbox-save-buffer))))
     result))
 
 (deffoo nnmbox-request-replace-article (article group buffer)
   (nnmbox-possibly-change-newsgroup group)
   (save-excursion
     (set-buffer nnmbox-mbox-buffer)
-    (goto-char (point-min))
-    (if (not (search-forward (nnmbox-article-string article) nil t))
+    (if (not (nnmbox-find-article article))
        nil
       (nnmbox-delete-mail t t)
       (insert-buffer-substring buffer)
-      (save-buffer)
+      (nnmbox-save-buffer)
       t)))
 
 (deffoo nnmbox-request-delete-group (group &optional force server)
          (setq found t)
          (nnmbox-delete-mail))
        (when found
-         (save-buffer)))))
+         (nnmbox-save-buffer)))))
   ;; Remove the group from all structures.
   (setq nnmbox-group-alist
        (delq (assoc group nnmbox-group-alist) nnmbox-group-alist)
        nnmbox-current-group nil)
   ;; Save the active file.
-  (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
+  (nnmbox-save-active nnmbox-group-alist nnmbox-active-file)
   t)
 
 (deffoo nnmbox-request-rename-group (group new-name &optional server)
        (replace-match new-ident t t)
        (setq found t))
       (when found
-       (save-buffer))))
+       (nnmbox-save-buffer))))
+  (let ((entry (assoc group nnmbox-group-active-articles)))
+    (when entry
+      (setcar entry new-name)))
   (let ((entry (assoc group nnmbox-group-alist)))
     (when entry
       (setcar entry new-name))
     (setq nnmbox-current-group nil)
     ;; Save the new group alist.
-    (nnmail-save-active nnmbox-group-alist nnmbox-active-file)
+    (nnmbox-save-active nnmbox-group-alist nnmbox-active-file)
     t))
 
 \f
 ;; delimiter line.
 (defun nnmbox-delete-mail (&optional force leave-delim)
   ;; Delete the current X-Gnus-Newsgroup line.
+  ;; First delete record of active article, unless the article is being
+  ;; replaced, indicated by FORCE being non-nil.
+  (if (not force)
+      (nnmbox-record-deleted-article (nnmbox-article-group-number t)))
   (or force
-      (delete-region
-       (progn (beginning-of-line) (point))
-       (progn (forward-line 1) (point))))
+      (gnus-delete-line))
   ;; Beginning of the article.
   (save-excursion
     (save-restriction
                    (match-beginning 0)))
             (point-max))))
       (goto-char (point-min))
-      ;; Only delete the article if no other groups owns it as well.
+      ;; Only delete the article if no other group owns it as well.
       (when (or force (not (re-search-forward "^X-Gnus-Newsgroup: " nil t)))
        (delete-region (point-min) (point-max))))))
 
     (nnmbox-open-server server))
   (when (or (not nnmbox-mbox-buffer)
            (not (buffer-name nnmbox-mbox-buffer)))
-    (save-excursion
-      (set-buffer (setq nnmbox-mbox-buffer
-                       (nnheader-find-file-noselect
-                        nnmbox-mbox-file nil 'raw)))
-      (buffer-disable-undo (current-buffer))))
+    (nnmbox-read-mbox))
   (when (not nnmbox-group-alist)
     (nnmail-activate 'nnmbox))
   (if newsgroup
              (int-to-string article) " ")
     (concat "\nMessage-ID: " article)))
 
-(defun nnmbox-article-group-number ()
+(defun nnmbox-article-group-number (this-line)
   (save-excursion
-    (goto-char (point-min))
+    (if this-line
+       (beginning-of-line)
+      (goto-char (point-min)))
     (when (re-search-forward "^X-Gnus-Newsgroup: +\\([^:]+\\):\\([0-9]+\\) "
                             nil t)
       (cons (buffer-substring (match-beginning 1) (match-end 1))
            (string-to-int
             (buffer-substring (match-beginning 2) (match-end 2)))))))
 
+(defun nnmbox-in-header-p (pos)
+  "Return non-nil if POS is in the header of an article."
+  (save-excursion
+    (goto-char pos)
+    (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
+    (search-forward "\n\n" nil t)
+    (< pos (point))))
+
+(defun nnmbox-find-article (article)
+  "Leaves point on the relevant X-Gnus-Newsgroup line if found."
+  ;; Check that article is in the active range first, to avoid an
+  ;; expensive exhaustive search if it isn't.
+  (if (and (numberp article)
+          (not (nnmbox-is-article-active-p article)))
+      nil
+    (let ((art-string (nnmbox-article-string article))
+         (found nil))
+      ;; There is the possibility that the X-Gnus-Newsgroup line appears
+      ;; in the body of an article (for instance, if an article has been
+      ;; forwarded from someone using Gnus as their mailer), so check
+      ;; that the line is actually part of the article header.
+      (or (and (search-forward art-string nil t)
+              (nnmbox-in-header-p (point)))
+         (progn
+           (goto-char (point-min))
+           (while (and (not found)
+                       (search-forward art-string nil t))
+             (setq found (nnmbox-in-header-p (point))))
+           found)))))
+
+(defun nnmbox-record-active-article (group-art)
+  (let* ((group (car group-art))
+        (article (cdr group-art))
+        (entry
+         (or (assoc group nnmbox-group-active-articles)
+             (progn
+               (push (list group)
+                     nnmbox-group-active-articles)
+               (car nnmbox-group-active-articles)))))
+    ;; add article to index, either by building complete list
+    ;; in reverse order, or as a list of ranges.
+    (if (not nnmbox-group-building-active-articles)
+       (setcdr entry (gnus-add-to-range (cdr entry) (list article)))
+      (when (memq article (cdr entry))
+       (switch-to-buffer nnmbox-mbox-buffer)
+       (error "Article %s:%d already exists!" group article))
+      (when (and (cadr entry) (< article (cadr entry)))
+       (switch-to-buffer nnmbox-mbox-buffer)
+       (error "Article %s:%d out of order" group article))
+      (setcdr entry (cons article (cdr entry))))))
+
+(defun nnmbox-record-deleted-article (group-art)
+  (let* ((group (car group-art))
+        (article (cdr group-art))
+        (entry
+         (or (assoc group nnmbox-group-active-articles)
+             (progn
+               (push (list group)
+                     nnmbox-group-active-articles)
+               (car nnmbox-group-active-articles)))))
+    ;; remove article from index
+    (setcdr entry (gnus-remove-from-range (cdr entry) (list article)))))
+
+(defun nnmbox-is-article-active-p (article)
+  (gnus-member-of-range
+   article
+   (cdr (assoc nnmbox-current-group
+              nnmbox-group-active-articles))))
+
 (defun nnmbox-save-mail (group-art)
   "Called narrowed to an article."
   (let ((delim (concat "^" message-unix-mail-delimiter)))
     (nnmail-insert-lines)
     (nnmail-insert-xref group-art)
     (nnmbox-insert-newsgroup-line group-art)
+    (let ((alist group-art))
+      (while alist
+       (nnmbox-record-active-article (car alist))
+       (setq alist (cdr alist))))
     (run-hooks 'nnmail-prepare-save-mail-hook)
     (run-hooks 'nnmbox-prepare-save-mail-hook)
     group-art))
 
 (defun nnmbox-create-mbox ()
   (when (not (file-exists-p nnmbox-mbox-file))
-    (nnmail-write-region 1 1 nnmbox-mbox-file t 'nomesg)))
+    (let ((nnmail-file-coding-system
+          (or nnmbox-file-coding-system-for-write
+              nnmbox-file-coding-system))
+         (dir (file-name-directory nnmbox-mbox-file)))
+      (and dir (gnus-make-directory dir))
+      (nnmail-write-region (point-min) (point-min)
+                          nnmbox-mbox-file t 'nomesg))))
 
 (defun nnmbox-read-mbox ()
   (nnmail-activate 'nnmbox)
     (save-excursion
       (let ((delim (concat "^" message-unix-mail-delimiter))
            (alist nnmbox-group-alist)
-           start end number)
+           (nnmbox-group-building-active-articles t)
+           start end end-header number)
        (set-buffer (setq nnmbox-mbox-buffer
-                         (nnheader-find-file-noselect
-                          nnmbox-mbox-file nil 'raw)))
-       (buffer-disable-undo (current-buffer))
+                         (let ((nnheader-file-coding-system
+                                nnmbox-file-coding-system))
+                           (nnheader-find-file-noselect
+                            nnmbox-mbox-file t t))))
+       (buffer-disable-undo)
 
-       ;; Go through the group alist and compare against
-       ;; the mbox file.
+       ;; Go through the group alist and compare against the mbox file.
        (while alist
          (goto-char (point-max))
          (when (and (re-search-backward
                      (format "^X-Gnus-Newsgroup: %s:\\([0-9]+\\) "
                              (caar alist)) nil t)
-                    (>= (setq number
-                              (string-to-number
-                               (buffer-substring
-                                (match-beginning 1) (match-end 1))))
-                        (cdadar alist)))
-           (setcdr (cadar alist) (1+ number)))
+                    (> (setq number
+                             (string-to-number
+                              (buffer-substring
+                               (match-beginning 1) (match-end 1))))
+                       (cdadar alist)))
+           (setcdr (cadar alist) number))
          (setq alist (cdr alist)))
 
+       ;; Examine all articles for our private X-Gnus-Newsgroup
+       ;; headers.  This is done primarily as a consistency check, but
+       ;; it is convenient for building an index of the articles
+       ;; present, to avoid costly searches for missing articles
+       ;; (eg. when expiring articles).
        (goto-char (point-min))
+       (setq nnmbox-group-active-articles nil)
        (while (re-search-forward delim nil t)
          (setq start (match-beginning 0))
-         (when (not (search-forward "\nX-Gnus-Newsgroup: "
-                                    (save-excursion
-                                      (setq end
-                                            (or
-                                             (and
-                                              (re-search-forward delim nil t)
-                                              (match-beginning 0))
-                                             (point-max))))
-                                    t))
+         (save-excursion
+           (search-forward "\n\n" nil t)
+           (setq end-header (point))
+           (setq end (or (and
+                          (re-search-forward delim nil t)
+                          (match-beginning 0))
+                         (point-max))))
+         (if (search-forward "\nX-Gnus-Newsgroup: " end-header t)
+             ;; Build a list of articles in each group, remembering
+             ;; that each article may be in more than one group.
+             (progn
+               (nnmbox-record-active-article (nnmbox-article-group-number t))
+               (while (search-forward "\nX-Gnus-Newsgroup: " end-header t)
+                 (nnmbox-record-active-article (nnmbox-article-group-number t))))
+           ;; The article is either new, or for some other reason
+           ;; hasn't got our private headers, so add them now.  The
+           ;; only situation I've encountered when the X-Gnus-Newsgroup
+           ;; header is missing is if the article contains a forwarded
+           ;; message which does contain that header line (earlier
+           ;; versions of Gnus didn't restrict their search to the
+           ;; headers).  In this case, there is an Xref line which
+           ;; provides the relevant information to construct the
+           ;; missing header(s).
            (save-excursion
              (save-restriction
                (narrow-to-region start end)
-               (nnmbox-save-mail
-                (nnmail-article-group 'nnmbox-active-number)))))
-         (goto-char end))))))
+               (if (re-search-forward "\nXref: [^ ]+" end-header t)
+                   ;; generate headers from Xref:
+                   (let (alist)
+                     (while (re-search-forward " \\([^:]+\\):\\([0-9]+\\)" end-header t)
+                       (push (cons (match-string 1)
+                                   (string-to-int (match-string 2))) alist))
+                     (nnmbox-insert-newsgroup-line alist))
+                 ;; this is really a new article
+                 (nnmbox-save-mail
+                  (nnmail-article-group 'nnmbox-active-number))))))
+         (goto-char end))
+       ;; put article lists in order
+       (setq alist nnmbox-group-active-articles)
+       (while alist
+         (setcdr (car alist) (gnus-compress-sequence (nreverse (cdar alist))))
+         (setq alist (cdr alist)))))))
 
 (provide 'nnmbox)
 
index ab9716c..cfefeb4 100644 (file)
@@ -1,8 +1,11 @@
 ;;; nnmh.el --- mhspool access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'nnheader)
 (require 'nnmail)
 (require 'gnus-start)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nnmh)
 
 (defvoo nnmh-directory message-directory
-  "*Mail spool directory.")
+  "Mail spool directory.")
 
 (defvoo nnmh-get-new-mail t
-  "*If non-nil, nnmh will check the incoming mail file and split the mail.")
+  "If non-nil, nnmh will check the incoming mail file and split the mail.")
 
 (defvoo nnmh-prepare-save-mail-hook nil
-  "*Hook run narrowed to an article before saving.")
+  "Hook run narrowed to an article before saving.")
 
 (defvoo nnmh-be-safe nil
-  "*If non-nil, nnmh will check all articles to make sure whether they are new or not.")
+  "If non-nil, nnmh will check all articles to make sure whether they are new or not.
+Go through the .nnmh-articles file and compare with the actual
+articles in this folder.  The articles that are \"new\" will be marked
+as unread by Gnus.")
 
 \f
 
 
 (defvoo nnmh-status-string "")
 (defvoo nnmh-group-alist nil)
-(defvoo nnmh-allow-delete-final nil)
+;; Don't even think about setting this variable.  It does not exist.
+;; Forget about it.  Uh-huh.  Nope.  Nobody here.  It's only bound
+;; dynamically by certain functions in nndraft.
+(defvar nnmh-allow-delete-final nil)
 
 \f
 
@@ -77,7 +88,8 @@
           (large (and (numberp nnmail-large-newsgroup)
                       (> number nnmail-large-newsgroup)))
           (count 0)
-          (pathname-coding-system 'binary)
+          (file-name-coding-system nnmail-pathname-coding-system)
+          (pathname-coding-system nnmail-pathname-coding-system)
           beg article)
       (nnmh-possibly-change-directory newsgroup server)
       ;; We don't support fetching by Message-ID.
 
          (and large
               (zerop (% count 20))
-              (message "nnmh: Receiving headers... %d%%"
-                       (/ (* count 100) number))))
+              (nnheader-message 5 "nnmh: Receiving headers... %d%%"
+                                (/ (* count 100) number))))
 
        (when large
-         (message "nnmh: Receiving headers...done"))
+         (nnheader-message 5 "nnmh: Receiving headers...done"))
 
-       (nnheader-fold-continuation-lines)
+       ;; (nnheader-fold-continuation-lines)
        'headers))))
 
 (deffoo nnmh-open-server (server &optional defs)
   (let ((file (if (stringp id)
                  nil
                (concat nnmh-current-directory (int-to-string id))))
-       (pathname-coding-system 'binary)
+       (file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system)
        (nntp-server-buffer (or buffer nntp-server-buffer)))
     (and (stringp file)
         (file-exists-p file)
   (nnheader-init-server-buffer)
   (nnmh-possibly-change-directory group server)
   (let ((pathname (nnmail-group-pathname group nnmh-directory))
-       (pathname-coding-system 'binary)
+       (file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system)
        dir)
     (cond
      ((not (file-directory-p pathname))
               (mapcar (lambda (name) (string-to-int name))
                       (directory-files pathname nil "^[0-9]+$" t))
               '<))
-         (cond
-          (dir
-           (nnheader-report 'nnmh "Selected group %s" group)
-           (nnheader-insert
-            "211 %d %d %d %s\n" (length dir) (car dir)
-            (progn (while (cdr dir) (setq dir (cdr dir))) (car dir))
-            group))
-          (t
-           (nnheader-report 'nnmh "Empty group %s" group)
-           (nnheader-insert (format "211 0 1 0 %s\n" group))))))))))
+       (cond
+        (dir
+         (setq nnmh-group-alist
+               (delq (assoc group nnmh-group-alist) nnmh-group-alist))
+         (push (list group (cons (car dir) (car (last dir))))
+               nnmh-group-alist)
+         (nnheader-report 'nnmh "Selected group %s" group)
+         (nnheader-insert
+          "211 %d %d %d %s\n" (length dir) (car dir)
+          (car (last dir)) group))
+        (t
+         (nnheader-report 'nnmh "Empty group %s" group)
+         (nnheader-insert (format "211 0 1 0 %s\n" group))))))))))
 
 (deffoo nnmh-request-scan (&optional group server)
   (nnmail-get-new-mail 'nnmh nil nnmh-directory group))
 (deffoo nnmh-request-list (&optional server dir)
   (nnheader-insert "")
   (nnmh-possibly-change-directory nil server)
-  (let ((pathname-coding-system 'binary)
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system)
        (nnmh-toplev
         (file-truename (or dir (file-name-as-directory nnmh-directory)))))
     (nnmh-request-list-1 nnmh-toplev))
          (goto-char (point-max))
          (insert
           (format
-           "%s %d %d y\n"
+           "%s %.0f %.0f y\n"
            (progn
              (string-match
               (regexp-quote
                (file-truename (file-name-as-directory
                                (expand-file-name nnmh-toplev))))
               dir)
-             (nnheader-replace-chars-in-string
-              (gnus-decode-coding-string (substring dir (match-end 0))
-                                         nnmail-pathname-coding-system)
-              ?/ ?.))
+             (string-as-multibyte
+              (encode-coding-string
+               (nnheader-replace-chars-in-string
+                (substring dir (match-end 0))
+                ?/ ?.)
+               nnmail-pathname-coding-system)))
            (apply 'max files)
            (apply 'min files)))))))
   t)
 (deffoo nnmh-request-expire-articles (articles newsgroup
                                               &optional server force)
   (nnmh-possibly-change-directory newsgroup server)
-  (let* ((active-articles
-         (mapcar
-          (function
-           (lambda (name)
-             (string-to-int name)))
-          (directory-files nnmh-current-directory nil "^[0-9]+$" t)))
-        (is-old t)
+  (let* ((is-old t)
         article rest mod-time)
     (nnheader-init-server-buffer)
 
                 (setq is-old
                       (nnmail-expired-article-p newsgroup mod-time force)))
            (progn
+             ;; Allow a special target group. -- jcn
+             (unless (eq nnmail-expiry-target 'delete)
+               (with-temp-buffer
+                 (nnmh-request-article (car articles)
+                                       newsgroup server (current-buffer))
+                 (nnmail-expiry-target-group
+                  nnmail-expiry-target newsgroup)))
              (nnheader-message 5 "Deleting article %s in %s..."
                                article newsgroup)
              (condition-case ()
                 (push (car articles) rest))))
          (push (car articles) rest)))
       (setq articles (cdr articles)))
-    (message "")
+    (nnheader-message 5 "")
     (nconc rest articles)))
 
 (deffoo nnmh-close-group (group &optional server)
   t)
 
-(deffoo nnmh-request-move-article
-  (article group server accept-form &optional last)
+(deffoo nnmh-request-move-article (article group server
+                                          accept-form &optional last)
   (let ((buf (get-buffer-create " *nnmh move*"))
        result)
     (and
 
 (deffoo nnmh-request-accept-article (group &optional server last noinsert)
   (nnmh-possibly-change-directory group server)
-  (nnmail-check-syntax)
+  (if (and (not (equal group "queue"))
+          (not (equal group "draft")))
+      (nnmail-check-syntax))
   (when nnmail-cache-accepted-message-ids
-    (nnmail-cache-insert (nnmail-fetch-field "message-id")))
+    (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                        group
+                        (nnmail-fetch-field "subject")
+                        (nnmail-fetch-field "from")))
   (nnheader-init-server-buffer)
   (prog1
       (if (stringp group)
     (nnmh-open-server server))
   (when newsgroup
     (let ((pathname (nnmail-group-pathname newsgroup nnmh-directory))
-         (pathname-coding-system 'binary))
+         (file-name-coding-system nnmail-pathname-coding-system)
+         (pathname-coding-system nnmail-pathname-coding-system))
       (if (file-directory-p pathname)
          (setq nnmh-current-directory pathname)
-       (error "No such newsgroup: %s" newsgroup)))))
+       (nnheader-report 'nnmh "Not a directory: %s" nnmh-directory)))))
 
 (defun nnmh-possibly-create-directory (group)
   (let (dir dirs)
   "Compute the next article number in GROUP."
   (let ((active (cadr (assoc group nnmh-group-alist)))
        (dir (nnmail-group-pathname group nnmh-directory))
-       (pathname-coding-system 'binary))
+       (file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system)
+       file)
     (unless active
       ;; The group wasn't known to nnmh, so we just create an active
       ;; entry for it.
        (when files
          (setcdr active (car files)))))
     (setcdr active (1+ (cdr active)))
-    (while (file-exists-p
-           (concat (nnmail-group-pathname group nnmh-directory)
-                   (int-to-string (cdr active))))
+    (while (or
+           ;; See whether the file exists...
+           (file-exists-p
+            (setq file (concat (nnmail-group-pathname group nnmh-directory)
+                               (int-to-string (cdr active)))))
+           ;; ... or there is a buffer that will make that file exist
+           ;; in the future.
+           (get-file-buffer file))
+      ;; Skip past that file.
       (setcdr active (1+ (cdr active))))
     (cdr active)))
 
     (setq articles (sort articles (lambda (art1 art2)
                                    (> (car art1) (car art2)))))
     ;; Finally write this list back to the .nnmh-articles file.
-    (nnheader-temp-write nnmh-file
+    (with-temp-file nnmh-file
       (insert ";; Gnus article active file for " group "\n\n")
       (insert "(setq nnmh-newsgroup-articles '")
       (gnus-prin1 articles)
index 68dcc5f..7b0ae9c 100644 (file)
@@ -1,8 +1,10 @@
 ;;; nnml.el --- mail spool access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Author: Simon Josefsson <simon@josefsson.org> (adding MARKS)
+;;      Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(require 'gnus)
 (require 'nnheader)
 (require 'nnmail)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
+
+(eval-and-compile
+  (autoload 'gnus-article-unpropagatable-p "gnus-sum"))
 
 (nnoo-declare nnml)
 
   "Spool directory for the nnml mail backend.")
 
 (defvoo nnml-active-file
-  (concat (file-name-as-directory nnml-directory) "active")
+    (expand-file-name "active" nnml-directory)
   "Mail active file.")
 
 (defvoo nnml-newsgroups-file
-  (concat (file-name-as-directory nnml-directory) "newsgroups")
+    (expand-file-name "newsgroups" nnml-directory)
   "Mail newsgroups description file.")
 
 (defvoo nnml-get-new-mail t
   "If non-nil, nnml will check the incoming mail file and split the mail.")
 
 (defvoo nnml-nov-is-evil nil
-  "If non-nil, Gnus will never generate and use nov databases for mail groups.
+  "If non-nil, Gnus will never generate and use nov databases for mail spools.
 Using nov databases will speed up header fetching considerably.
 This variable shouldn't be flipped much.  If you have, for some reason,
 set this to t, and want to set it to nil again, you should always run
@@ -60,12 +68,23 @@ the `nnml-generate-nov-databases' command.  The function will go
 through all nnml directories and generate nov databases for them
 all.  This may very well take some time.")
 
+(defvoo nnml-marks-is-evil nil
+  "If non-nil, Gnus will never generate and use marks file for mail spools.
+Using marks files makes it possible to backup and restore mail groups
+separately from `.newsrc.eld'.  If you have, for some reason, set this
+to t, and want to set it to nil again, you should always remove the
+corresponding marks file (usually named `.marks' in the nnml group
+directory, but see `nnml-marks-file-name') for the group.  Then the
+marks file will be regenerated properly by Gnus.")
+
 (defvoo nnml-prepare-save-mail-hook nil
   "Hook run narrowed to an article before saving.")
 
 (defvoo nnml-inhibit-expiry nil
   "If non-nil, inhibit expiry.")
 
+(defvoo nnml-use-compressed-files nil
+  "If non-nil, allow using compressed message files.")
 
 \f
 
@@ -73,6 +92,7 @@ all.  This may very well take some time.")
   "nnml version.")
 
 (defvoo nnml-nov-file-name ".overview")
+(defvoo nnml-marks-file-name ".marks")
 
 (defvoo nnml-current-directory nil)
 (defvoo nnml-current-group nil)
@@ -86,8 +106,13 @@ all.  This may very well take some time.")
 
 (defvar nnml-nov-buffer-file-name nil)
 
-\f
+(defvoo nnml-file-coding-system nnmail-file-coding-system)
 
+(defvoo nnml-marks nil)
+
+(defvar nnml-marks-modtime (gnus-make-hashtable))
+
+\f
 ;;; Interface functions.
 
 (nnoo-define-basics nnml)
@@ -97,11 +122,12 @@ all.  This may very well take some time.")
     (save-excursion
       (set-buffer nntp-server-buffer)
       (erase-buffer)
-      (let ((file nil)
-           (number (length sequence))
-           (count 0)
-           (pathname-coding-system 'binary)
-           beg article)
+      (let* ((file nil)
+            (number (length sequence))
+            (count 0)
+            (file-name-coding-system nnmail-pathname-coding-system)
+            (pathname-coding-system nnmail-pathname-coding-system)
+            beg article)
        (if (stringp (car sequence))
            'headers
          (if (nnml-retrieve-headers-with-nov sequence fetch-old)
@@ -116,7 +142,7 @@ all.  This may very well take some time.")
                (setq beg (point))
                (nnheader-insert-head file)
                (goto-char beg)
-               (if (search-forward "\n\n" nil t)
+               (if (re-search-forward "\n\r?\n" nil t)
                    (forward-char -1)
                  (goto-char (point-max))
                  (insert "\n\n"))
@@ -140,9 +166,7 @@ all.  This may very well take some time.")
 (deffoo nnml-open-server (server &optional defs)
   (nnoo-change-server 'nnml server defs)
   (when (not (file-exists-p nnml-directory))
-    (condition-case ()
-       (make-directory nnml-directory t)
-      (error)))
+    (ignore-errors (make-directory nnml-directory t)))
   (cond
    ((not (file-exists-p nnml-directory))
     (nnml-close-server)
@@ -155,15 +179,16 @@ all.  This may very well take some time.")
                     server nnml-directory)
     t)))
 
-(defun nnml-request-regenerate (server)
+(deffoo nnml-request-regenerate (server)
   (nnml-possibly-change-directory nil server)
-  (nnml-generate-nov-databases)
+  (nnml-generate-nov-databases server)
   t)
 
 (deffoo nnml-request-article (id &optional group server buffer)
   (nnml-possibly-change-directory group server)
   (let* ((nntp-server-buffer (or buffer nntp-server-buffer))
-        (pathname-coding-system 'binary)
+        (file-name-coding-system nnmail-pathname-coding-system)
+        (pathname-coding-system nnmail-pathname-coding-system)
         path gpath group-num)
     (if (stringp id)
        (when (and (setq group-num (nnml-find-group-number id))
@@ -183,7 +208,9 @@ all.  This may very well take some time.")
       (nnheader-report 'nnml "No such file: %s" path))
      ((file-directory-p path)
       (nnheader-report 'nnml "File is a directory: %s" path))
-     ((not (save-excursion (nnmail-find-file path)))
+     ((not (save-excursion (let ((nnmail-file-coding-system
+                                 nnml-file-coding-system))
+                            (nnmail-find-file path))))
       (nnheader-report 'nnml "Couldn't read file: %s" path))
      (t
       (nnheader-report 'nnml "Article %s retrieved" id)
@@ -192,7 +219,8 @@ all.  This may very well take some time.")
            (string-to-int (file-name-nondirectory path)))))))
 
 (deffoo nnml-request-group (group &optional server dont-check)
-  (let ((pathname-coding-system 'binary))
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (pathname-coding-system nnmail-pathname-coding-system))
     (cond
      ((not (nnml-possibly-change-directory group server))
       (nnheader-report 'nnml "Invalid group (no such directory)"))
@@ -225,6 +253,7 @@ all.  This may very well take some time.")
   t)
 
 (deffoo nnml-request-create-group (group &optional server args)
+  (nnml-possibly-change-directory nil server)
   (nnmail-activate 'nnml)
   (cond
    ((assoc group nnml-group-alist)
@@ -239,7 +268,7 @@ all.  This may very well take some time.")
            nnml-group-alist)
       (nnml-possibly-create-directory group)
       (nnml-possibly-change-directory group server)
-      (let ((articles (nnheader-directory-articles nnml-current-directory)))
+      (let ((articles (nnml-directory-articles nnml-current-directory)))
        (when articles
          (setcar active (apply 'min articles))
          (setcdr active (apply 'max articles))))
@@ -249,9 +278,9 @@ all.  This may very well take some time.")
 (deffoo nnml-request-list (&optional server)
   (save-excursion
     (let ((nnmail-file-coding-system nnmail-active-file-coding-system)
-         (pathname-coding-system 'binary)) ; for XEmacs/mule
-      (nnmail-find-file nnml-active-file)
-      )
+         (file-name-coding-system nnmail-pathname-coding-system)
+         (pathname-coding-system nnmail-pathname-coding-system))
+      (nnmail-find-file nnml-active-file))
     (setq nnml-group-alist (nnmail-get-active))
     t))
 
@@ -262,32 +291,46 @@ all.  This may very well take some time.")
   (save-excursion
     (nnmail-find-file nnml-newsgroups-file)))
 
-(deffoo nnml-request-expire-articles (articles group
-                                              &optional server force)
+(deffoo nnml-request-expire-articles (articles group &optional server force)
   (nnml-possibly-change-directory group server)
   (let ((active-articles
-        (nnheader-directory-articles nnml-current-directory))
+        (nnml-directory-articles nnml-current-directory))
        (is-old t)
        article rest mod-time number)
     (nnmail-activate 'nnml)
 
+    (setq active-articles (sort active-articles '<))
+    ;; Articles not listed in active-articles are already gone,
+    ;; so don't try to expire them.
+    (setq articles (gnus-sorted-intersection articles active-articles))
+
     (while (and articles is-old)
-      (when (setq article (nnml-article-to-file (setq number (pop articles))))
-       (when (setq mod-time (nth 5 (file-attributes article)))
-         (if (and (nnml-deletable-article-p group number)
-                  (setq is-old
-                        (nnmail-expired-article-p group mod-time force
-                                                  nnml-inhibit-expiry)))
-             (progn
-               (nnheader-message 5 "Deleting article %s in %s"
-                                 article group)
-               (condition-case ()
-                   (funcall nnmail-delete-file-function article)
-                 (file-error
-                  (push number rest)))
-               (setq active-articles (delq number active-articles))
-               (nnml-nov-delete-article group number))
-           (push number rest)))))
+      (if (and (setq article (nnml-article-to-file
+                             (setq number (pop articles))))
+              (setq mod-time (nth 5 (file-attributes article)))
+              (nnml-deletable-article-p group number)
+              (setq is-old (nnmail-expired-article-p group mod-time force
+                                                     nnml-inhibit-expiry)))
+         (progn
+           ;; Allow a special target group.
+           (unless (eq nnmail-expiry-target 'delete)
+             (with-temp-buffer
+               (nnml-request-article number group server (current-buffer))
+               (let (nnml-current-directory
+                     nnml-current-group
+                     nnml-article-file-alist)
+                 (nnmail-expiry-target-group nnmail-expiry-target group)))
+             ;; Maybe directory is changed during nnmail-expiry-target-group.
+             (nnml-possibly-change-directory group server))
+           (nnheader-message 5 "Deleting article %s in %s"
+                             number group)
+           (condition-case ()
+               (funcall nnmail-delete-file-function article)
+             (file-error
+              (push number rest)))
+           (setq active-articles (delq number active-articles))
+           (nnml-nov-delete-article group number))
+       (push number rest)))
     (let ((active (nth 1 (assoc group nnml-group-alist))))
       (when active
        (setcar active (or (and active-articles
@@ -298,7 +341,7 @@ all.  This may very well take some time.")
     (nconc rest articles)))
 
 (deffoo nnml-request-move-article
-  (article group server accept-form &optional last)
+    (article group server accept-form &optional last)
   (let ((buf (get-buffer-create " *nnml move*"))
        result)
     (nnml-possibly-change-directory group server)
@@ -306,12 +349,15 @@ all.  This may very well take some time.")
     (and
      (nnml-deletable-article-p group article)
      (nnml-request-article article group server)
-     (save-excursion
-       (set-buffer buf)
-       (insert-buffer-substring nntp-server-buffer)
-       (setq result (eval accept-form))
-       (kill-buffer (current-buffer))
-       result)
+     (let (nnml-current-directory
+          nnml-current-group
+          nnml-article-file-alist)
+       (save-excursion
+        (set-buffer buf)
+        (insert-buffer-substring nntp-server-buffer)
+        (setq result (eval accept-form))
+        (kill-buffer (current-buffer))
+        result))
      (progn
        (nnml-possibly-change-directory group server)
        (condition-case ()
@@ -329,7 +375,10 @@ all.  This may very well take some time.")
   (nnmail-check-syntax)
   (let (result)
     (when nnmail-cache-accepted-message-ids
-      (nnmail-cache-insert (nnmail-fetch-field "message-id")))
+      (nnmail-cache-insert (nnmail-fetch-field "message-id") 
+                          group
+                          (nnmail-fetch-field "subject")
+                          (nnmail-fetch-field "from")))
     (if (stringp group)
        (and
         (nnmail-activate 'nnml)
@@ -351,6 +400,9 @@ all.  This may very well take some time.")
         (nnml-save-nov))))
     result))
 
+(deffoo nnml-request-post (&optional server)
+  (nnmail-do-request-post 'nnml-request-accept-article server))
+
 (deffoo nnml-request-replace-article (article group buffer)
   (nnml-possibly-change-directory group)
   (save-excursion
@@ -359,16 +411,14 @@ all.  This may very well take some time.")
     (let ((chars (nnmail-insert-lines))
          (art (concat (int-to-string article) "\t"))
          headers)
-      (when (condition-case ()
-               (progn
-                 (nnmail-write-region
-                  (point-min) (point-max)
-                  (or (nnml-article-to-file article)
-                      (concat nnml-current-directory
-                              (int-to-string article)))
-                  nil (if (nnheader-be-verbose 5) nil 'nomesg))
-                 t)
-             (error nil))
+      (when (ignore-errors
+             (nnmail-write-region
+              (point-min) (point-max)
+              (or (nnml-article-to-file article)
+                  (expand-file-name (int-to-string article)
+                                    nnml-current-directory))
+              nil (if (nnheader-be-verbose 5) nil 'nomesg))
+             t)
        (setq headers (nnml-parse-head chars article))
        ;; Replace the NOV line in the NOV file.
        (save-excursion
@@ -377,8 +427,7 @@ all.  This may very well take some time.")
          (if (or (looking-at art)
                  (search-forward (concat "\n" art) nil t))
              ;; Delete the old NOV line.
-             (delete-region (progn (beginning-of-line) (point))
-                            (progn (forward-line 1) (point)))
+             (gnus-delete-line)
            ;; The line isn't here, so we have to find out where
            ;; we should insert it.  (This situation should never
            ;; occur, but one likes to make sure...)
@@ -401,7 +450,8 @@ all.  This may very well take some time.")
           (directory-files
            nnml-current-directory t
            (concat nnheader-numerical-short-files
-                   "\\|" (regexp-quote nnml-nov-file-name) "$")))
+                   "\\|" (regexp-quote nnml-nov-file-name) "$"
+                   "\\|" (regexp-quote nnml-marks-file-name) "$")))
          article)
       (while articles
        (setq article (pop articles))
@@ -409,9 +459,7 @@ all.  This may very well take some time.")
          (nnheader-message 5 "Deleting article %s in %s..." article group)
          (funcall nnmail-delete-file-function article))))
     ;; Try to delete the directory itself.
-    (condition-case ()
-       (delete-directory nnml-current-directory)
-      (error nil)))
+    (ignore-errors (delete-directory nnml-current-directory)))
   ;; Remove the group from all structures.
   (setq nnml-group-alist
        (delq (assoc group nnml-group-alist) nnml-group-alist)
@@ -425,11 +473,9 @@ all.  This may very well take some time.")
   (nnml-possibly-change-directory group server)
   (let ((new-dir (nnmail-group-pathname new-name nnml-directory))
        (old-dir (nnmail-group-pathname group nnml-directory)))
-    (when (condition-case ()
-             (progn
-               (make-directory new-dir t)
-               t)
-           (error nil))
+    (when (ignore-errors
+           (make-directory new-dir t)
+           t)
       ;; We move the articles file by file instead of renaming
       ;; the directory -- there may be subgroups in this group.
       ;; One might be more clever, I guess.
@@ -443,10 +489,12 @@ all.  This may very well take some time.")
       (let ((overview (concat old-dir nnml-nov-file-name)))
        (when (file-exists-p overview)
          (rename-file overview (concat new-dir nnml-nov-file-name))))
+      ;; Move .marks file.
+      (let ((marks (concat old-dir nnml-marks-file-name)))
+       (when (file-exists-p marks)
+         (rename-file marks (concat new-dir nnml-marks-file-name))))
       (when (<= (length (directory-files old-dir)) 2)
-       (condition-case ()
-           (delete-directory old-dir)
-         (error nil)))
+       (ignore-errors (delete-directory old-dir)))
       ;; That went ok, so we change the internal structures.
       (let ((entry (assoc group nnml-group-alist)))
        (when entry
@@ -464,7 +512,7 @@ all.  This may very well take some time.")
      ((not (file-exists-p file))
       (nnheader-report 'nnml "File %s does not exist" file))
      (t
-      (nnheader-temp-write file
+      (with-temp-file file
        (nnheader-insert-file-contents file)
        (nnmail-replace-status name value))
       t))))
@@ -475,15 +523,19 @@ all.  This may very well take some time.")
 (defun nnml-article-to-file (article)
   (nnml-update-file-alist)
   (let (file)
-    (if (setq file (cdr (assq article nnml-article-file-alist)))
-       (concat nnml-current-directory file)
-      ;; Just to make sure nothing went wrong when reading over NFS --
-      ;; check once more.
-      (when (file-exists-p
-            (setq file (concat nnml-current-directory "/"
-                               (number-to-string article))))
-       (nnml-update-file-alist t)
-       file))))
+    (if (setq file
+             (if nnml-use-compressed-files
+                 (cdr (assq article nnml-article-file-alist))
+               (number-to-string article)))
+       (expand-file-name file nnml-current-directory)
+      (when (not nnheader-directory-files-is-safe)
+       ;; Just to make sure nothing went wrong when reading over NFS --
+       ;; check once more.
+       (when (file-exists-p
+              (setq file (expand-file-name (number-to-string article)
+                                           nnml-current-directory)))
+         (nnml-update-file-alist t)
+         file)))))
 
 (defun nnml-deletable-article-p (group article)
   "Say whether ARTICLE in GROUP can be deleted."
@@ -498,7 +550,6 @@ all.  This may very well take some time.")
 (defun nnml-find-group-number (id)
   (save-excursion
     (set-buffer (get-buffer-create " *nnml id*"))
-    (buffer-disable-undo (current-buffer))
     (let ((alist nnml-group-alist)
          number)
       ;; We want to look through all .overview files, but we want to
@@ -518,8 +569,8 @@ all.  This may very well take some time.")
 
 (defun nnml-find-id (group id)
   (erase-buffer)
-  (let ((nov (concat (nnmail-group-pathname group nnml-directory)
-                    nnml-nov-file-name))
+  (let ((nov (expand-file-name nnml-nov-file-name
+                              (nnmail-group-pathname group nnml-directory)))
        number found)
     (when (file-exists-p nov)
       (nnheader-insert-file-contents nov)
@@ -533,15 +584,13 @@ all.  This may very well take some time.")
          (setq found t)
          ;; We return the article number.
          (setq number
-               (condition-case ()
-                   (read (current-buffer))
-                 (error nil)))))
+               (ignore-errors (read (current-buffer))))))
       number)))
 
 (defun nnml-retrieve-headers-with-nov (articles &optional fetch-old)
   (if (or gnus-nov-is-evil nnml-nov-is-evil)
       nil
-    (let ((nov (concat nnml-current-directory nnml-nov-file-name)))
+    (let ((nov (expand-file-name nnml-nov-file-name nnml-current-directory)))
       (when (file-exists-p nov)
        (save-excursion
          (set-buffer nntp-server-buffer)
@@ -563,7 +612,8 @@ all.  This may very well take some time.")
   (if (not group)
       t
     (let ((pathname (nnmail-group-pathname group nnml-directory))
-         (pathname-coding-system 'binary))
+         (file-name-coding-system nnmail-pathname-coding-system)
+         (pathname-coding-system nnmail-pathname-coding-system))
       (when (not (equal pathname nnml-current-directory))
        (setq nnml-current-directory pathname
              nnml-current-group group
@@ -571,20 +621,19 @@ all.  This may very well take some time.")
       (file-exists-p nnml-current-directory))))
 
 (defun nnml-possibly-create-directory (group)
-  (let (dir dirs)
-    (setq dir (nnmail-group-pathname group nnml-directory))
-    (while (not (file-directory-p dir))
-      (push dir dirs)
-      (setq dir (file-name-directory (directory-file-name dir))))
-    (while dirs
-      (make-directory (directory-file-name (car dirs)))
-      (nnheader-message 5 "Creating mail directory %s" (car dirs))
-      (setq dirs (cdr dirs)))))
+  (let ((dir (nnmail-group-pathname group nnml-directory)))
+    (unless (file-exists-p dir)
+      (make-directory (directory-file-name dir) t)
+      (nnheader-message 5 "Creating mail directory %s" dir))))
 
 (defun nnml-save-mail (group-art)
   "Called narrowed to an article."
-  (let (chars headers)
+  (let (chars headers extension)
     (setq chars (nnmail-insert-lines))
+    (setq extension
+         (and nnml-use-compressed-files
+              (> chars 1000)
+              ".gz"))
     (nnmail-insert-xref group-art)
     (run-hooks 'nnmail-prepare-save-mail-hook)
     (run-hooks 'nnml-prepare-save-mail-hook)
@@ -599,7 +648,8 @@ all.  This may very well take some time.")
        (nnml-possibly-create-directory (caar ga))
        (let ((file (concat (nnmail-group-pathname
                             (caar ga) nnml-directory)
-                           (int-to-string (cdar ga)))))
+                           (int-to-string (cdar ga))
+                           extension)))
          (if first
              ;; It was already saved, so we just make a hard link.
              (funcall nnmail-crosspost-link-function first file t)
@@ -632,7 +682,7 @@ all.  This may very well take some time.")
       (unless nnml-article-file-alist
        (setq nnml-article-file-alist
              (sort
-              (nnheader-article-to-file-alist nnml-current-directory)
+              (nnml-current-group-article-to-file-alist)
               'car-less-than-car)))
       (setq active
            (if nnml-article-file-alist
@@ -642,8 +692,8 @@ all.  This may very well take some time.")
       (push (list group active) nnml-group-alist))
     (setcdr active (1+ (cdr active)))
     (while (file-exists-p
-           (concat (nnmail-group-pathname group nnml-directory)
-                   (int-to-string (cdr active))))
+           (expand-file-name (int-to-string (cdr active))
+                             (nnmail-group-pathname group nnml-directory)))
       (setcdr active (1+ (cdr active))))
     (cdr active)))
 
@@ -656,7 +706,7 @@ all.  This may very well take some time.")
     (nnheader-insert-nov headers)))
 
 (defsubst nnml-header-value ()
-  (buffer-substring (match-end 0) (progn (end-of-line) (point))))
+  (buffer-substring (match-end 0) (gnus-point-at-eol)))
 
 (defun nnml-parse-head (chars &optional number)
   "Parse the head of the current buffer."
@@ -665,29 +715,30 @@ all.  This may very well take some time.")
       (unless (zerop (buffer-size))
        (narrow-to-region
         (goto-char (point-min))
-        (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-       (replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      (let ((headers (nnheader-parse-head t)))
+        (if (re-search-forward "\n\r?\n" nil t)
+            (1- (point))
+          (point-max))))
+      (let ((headers (nnheader-parse-naked-head)))
        (mail-header-set-chars headers chars)
        (mail-header-set-number headers number)
        headers))))
 
+(defun nnml-get-nov-buffer (group)
+  (let ((buffer (get-buffer-create (format " *nnml overview %s*" group))))
+    (save-excursion
+      (set-buffer buffer)
+      (set (make-local-variable 'nnml-nov-buffer-file-name)
+          (expand-file-name
+           nnml-nov-file-name
+           (nnmail-group-pathname group nnml-directory)))
+      (erase-buffer)
+      (when (file-exists-p nnml-nov-buffer-file-name)
+       (nnheader-insert-file-contents nnml-nov-buffer-file-name)))
+    buffer))
+
 (defun nnml-open-nov (group)
   (or (cdr (assoc group nnml-nov-buffer-alist))
-      (let ((buffer (get-buffer-create (format " *nnml overview %s*" group))))
-       (save-excursion
-         (set-buffer buffer)
-         (set (make-local-variable 'nnml-nov-buffer-file-name)
-              (concat (nnmail-group-pathname group nnml-directory)
-                      nnml-nov-file-name))
-         (erase-buffer)
-         (when (file-exists-p nnml-nov-buffer-file-name)
-           (nnheader-insert-file-contents nnml-nov-buffer-file-name)))
+      (let ((buffer (nnml-get-nov-buffer group)))
        (push (cons group buffer) nnml-nov-buffer-alist)
        buffer)))
 
@@ -697,20 +748,21 @@ all.  This may very well take some time.")
       (when (buffer-name (cdar nnml-nov-buffer-alist))
        (set-buffer (cdar nnml-nov-buffer-alist))
        (when (buffer-modified-p)
-         (nnmail-write-region 1 (point-max) nnml-nov-buffer-file-name
-                              nil 'nomesg))
+         (nnmail-write-region (point-min) (point-max)
+                              nnml-nov-buffer-file-name nil 'nomesg))
        (set-buffer-modified-p nil)
        (kill-buffer (current-buffer)))
       (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist)))))
 
 ;;;###autoload
-(defun nnml-generate-nov-databases ()
+(defun nnml-generate-nov-databases (&optional server)
   "Generate NOV databases in all nnml directories."
-  (interactive)
+  (interactive (list (or (nnoo-current-server 'nnml) "")))
   ;; Read the active file to make sure we don't re-use articles
   ;; numbers in empty groups.
   (nnmail-activate 'nnml)
-  (nnml-open-server (or (nnoo-current-server 'nnml) ""))
+  (unless (nnml-server-opened server)
+    (nnml-open-server server))
   (setq nnml-directory (expand-file-name nnml-directory))
   ;; Recurse down the directories.
   (nnml-generate-nov-databases-1 nnml-directory nil t)
@@ -728,7 +780,7 @@ all.  This may very well take some time.")
     (let ((dirs (directory-files dir t nil t))
          dir)
       (while (setq dir (pop dirs))
-       (when (and (not (member (file-name-nondirectory dir) '("." "..")))
+       (when (and (not (string-match "^\\." (file-name-nondirectory dir)))
                   (file-directory-p dir))
          (nnml-generate-nov-databases-1 dir seen))))
     ;; Do this directory.
@@ -746,18 +798,21 @@ all.  This may very well take some time.")
        (unless no-active
          (nnmail-save-active nnml-group-alist nnml-active-file))))))
 
-(defvar files)
+(eval-when-compile (defvar files))
 (defun nnml-generate-active-info (dir)
   ;; Update the active info for this group.
-  (let ((group (nnheader-file-to-group
-               (directory-file-name dir) nnml-directory)))
-    (setq nnml-group-alist
-         (delq (assoc group nnml-group-alist) nnml-group-alist))
+  (let* ((group (nnheader-file-to-group
+                (directory-file-name dir) nnml-directory))
+        (entry (assoc group nnml-group-alist))
+        (last (or (caadr entry) 0)))
+    (setq nnml-group-alist (delq entry nnml-group-alist))
     (push (list group
-               (cons (caar files)
-                     (let ((f files))
-                       (while (cdr f) (setq f (cdr f)))
-                       (caar f))))
+               (cons (or (caar files) (1+ last))
+                     (max last
+                          (or (let ((f files))
+                                (while (cdr f) (setq f (cdr f)))
+                                (caar f))
+                              0))))
          nnml-group-alist)))
 
 (defun nnml-generate-nov-file (dir files)
@@ -768,7 +823,7 @@ all.  This may very well take some time.")
     (save-excursion
       ;; Init the nov buffer.
       (set-buffer nov-buffer)
-      (buffer-disable-undo (current-buffer))
+      (buffer-disable-undo)
       (erase-buffer)
       (set-buffer nntp-server-buffer)
       ;; Delete the old NOV file.
@@ -781,9 +836,9 @@ all.  This may very well take some time.")
          (narrow-to-region
           (goto-char (point-min))
           (progn
-            (search-forward "\n\n" nil t)
+            (re-search-forward "\n\r?\n" nil t)
             (setq chars (- (point-max) (point)))
-            (max 1 (1- (point)))))
+            (max (point-min) (1- (point)))))
          (unless (zerop (buffer-size))
            (goto-char (point-min))
            (setq headers (nnml-parse-head chars (caar files)))
@@ -795,7 +850,7 @@ all.  This may very well take some time.")
        (setq files (cdr files)))
       (save-excursion
        (set-buffer nov-buffer)
-       (nnmail-write-region 1 (point-max) nov nil 'nomesg)
+       (nnmail-write-region (point-min) (point-max) nov nil 'nomesg)
        (kill-buffer (current-buffer))))))
 
 (defun nnml-nov-delete-article (group article)
@@ -815,10 +870,158 @@ all.  This may very well take some time.")
     t))
 
 (defun nnml-update-file-alist (&optional force)
-  (when (or (not nnml-article-file-alist)
-           force)
-    (setq nnml-article-file-alist
-         (nnheader-article-to-file-alist nnml-current-directory))))
+  (when nnml-use-compressed-files
+    (when (or (not nnml-article-file-alist)
+             force)
+      (setq nnml-article-file-alist
+           (nnml-current-group-article-to-file-alist)))))
+
+(defun nnml-directory-articles (dir)
+  "Return a list of all article files in a directory.
+Use the nov database for that directory if available."
+  (if (or gnus-nov-is-evil nnml-nov-is-evil
+         (not (file-exists-p
+               (expand-file-name nnml-nov-file-name dir))))
+      (nnheader-directory-articles dir)
+    ;; build list from .overview if available
+    ;; We would use nnml-open-nov, except that nnml-nov-buffer-alist is
+    ;; defvoo'd, and we might get called when it hasn't been swapped in.
+    (save-excursion
+      (let ((list nil)
+           art
+           (buffer (nnml-get-nov-buffer nnml-current-group)))
+       (set-buffer buffer)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (setq art (read (current-buffer)))
+         (push art list)
+         (forward-line 1))
+       list))))
+
+(defun nnml-current-group-article-to-file-alist ()
+  "Return an alist of article/file pairs in the current group.
+Use the nov database for the current group if available."
+  (if (or nnml-use-compressed-files
+         gnus-nov-is-evil
+         nnml-nov-is-evil
+         (not (file-exists-p
+               (expand-file-name nnml-nov-file-name
+                                 nnml-current-directory))))
+      (nnheader-article-to-file-alist nnml-current-directory)
+    ;; build list from .overview if available
+    (save-excursion
+      (let ((alist nil)
+           (buffer (nnml-get-nov-buffer nnml-current-group))
+           art)
+       (set-buffer buffer)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (setq art (read (current-buffer)))
+         ;; assume file name is unadorned (ie. not compressed etc)
+         (push (cons art (int-to-string art)) alist)
+         (forward-line 1))
+       alist))))
+
+(deffoo nnml-request-set-mark (group actions &optional server)
+  (nnml-possibly-change-directory group server)
+  (unless nnml-marks-is-evil
+    (nnml-open-marks group server)
+    (dolist (action actions)
+      (let ((range (nth 0 action))
+           (what  (nth 1 action))
+           (marks (nth 2 action)))
+       (assert (or (eq what 'add) (eq what 'del)) t
+               "Unknown request-set-mark action: %s" what)
+       (dolist (mark marks)
+         (setq nnml-marks (gnus-update-alist-soft
+                           mark
+                           (funcall (if (eq what 'add) 'gnus-range-add
+                                      'gnus-remove-from-range)
+                                    (cdr (assoc mark nnml-marks)) range)
+                           nnml-marks)))))
+    (nnml-save-marks group server))
+  nil)
+
+(deffoo nnml-request-update-info (group info &optional server)
+  (nnml-possibly-change-directory group server)
+  (when (and (not nnml-marks-is-evil) (nnml-marks-changed-p group))
+    (nnheader-message 8 "Updating marks for %s..." group)
+    (nnml-open-marks group server)
+    ;; Update info using `nnml-marks'.
+    (mapcar (lambda (pred)
+             (unless (memq (cdr pred) gnus-article-unpropagated-mark-lists)
+               (gnus-info-set-marks
+                info
+                (gnus-update-alist-soft
+                 (cdr pred)
+                 (cdr (assq (cdr pred) nnml-marks))
+                 (gnus-info-marks info))
+                t)))
+           gnus-article-mark-lists)
+    (let ((seen (cdr (assq 'read nnml-marks))))
+      (gnus-info-set-read info
+                         (if (and (integerp (car seen))
+                                  (null (cdr seen)))
+                             (list (cons (car seen) (car seen)))
+                           seen)))
+    (nnheader-message 8 "Updating marks for %s...done" group))
+  info)
+
+(defun nnml-marks-changed-p (group)
+  (let ((file (expand-file-name nnml-marks-file-name
+                               (nnmail-group-pathname group nnml-directory))))
+    (if (null (gnus-gethash file nnml-marks-modtime))
+       t ;; never looked at marks file, assume it has changed
+      (not (equal (gnus-gethash file nnml-marks-modtime)
+                 (nth 5 (file-attributes file)))))))
+
+(defun nnml-save-marks (group server)
+  (let ((file-name-coding-system nnmail-pathname-coding-system)
+       (file (expand-file-name nnml-marks-file-name
+                               (nnmail-group-pathname group nnml-directory))))
+    (condition-case err
+       (progn
+         (nnml-possibly-create-directory group)
+         (with-temp-file file
+           (erase-buffer)
+           (gnus-prin1 nnml-marks)
+           (insert "\n"))
+         (gnus-sethash file
+                       (nth 5 (file-attributes file))
+                       nnml-marks-modtime))
+      (error (or (gnus-yes-or-no-p
+                 (format "Could not write to %s (%s).  Continue? " file err))
+                (error "Cannot write to %s (%s)" err))))))
+
+(defun nnml-open-marks (group server)
+  (let ((file (expand-file-name
+              nnml-marks-file-name
+              (nnmail-group-pathname group nnml-directory))))
+    (if (file-exists-p file)
+       (condition-case err
+           (with-temp-buffer
+             (gnus-sethash file (nth 5 (file-attributes file))
+                           nnml-marks-modtime)
+             (nnheader-insert-file-contents file)
+             (setq nnml-marks (read (current-buffer)))
+             (dolist (el gnus-article-unpropagated-mark-lists)
+               (setq nnml-marks (gnus-remassoc el nnml-marks))))
+         (error (or (gnus-yes-or-no-p
+                     (format "Error reading nnml marks file %s (%s).  Continuing will use marks from .newsrc.eld.  Continue? " file err))
+                    (error "Cannot read nnml marks file %s (%s)" file err))))
+      ;; User didn't have a .marks file.  Probably first time
+      ;; user of the .marks stuff.  Bootstrap it from .newsrc.eld.
+      (let ((info (gnus-get-info
+                  (gnus-group-prefixed-name
+                   group
+                   (gnus-server-to-method (format "nnml:%s" server))))))
+       (nnheader-message 7 "Bootstrapping marks for %s..." group)
+       (setq nnml-marks (gnus-info-marks info))
+       (push (cons 'read (gnus-info-read info)) nnml-marks)
+       (dolist (el gnus-article-unpropagated-mark-lists)
+         (setq nnml-marks (gnus-remassoc el nnml-marks)))
+       (nnml-save-marks group server)
+       (nnheader-message 7 "Bootstrapping marks for %s...done" group)))))
 
 (provide 'nnml)
 
diff --git a/lisp/nnnil.el b/lisp/nnnil.el
new file mode 100644 (file)
index 0000000..08a097d
--- /dev/null
@@ -0,0 +1,81 @@
+;;; nnnil.el --- empty backend for Gnus
+;; Public domain.
+
+;; Author: Paul Jarc <prj@po.cwru.edu>
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; nnnil is a Gnus backend that provides no groups or articles.  It's useful
+;; as a primary select method when you want all your real select methods to
+;; be secondary or foreign.
+
+;;; Code:
+
+(eval-and-compile
+  (require 'nnheader))
+
+(defvar nnnil-status-string "")
+
+(defun nnnil-retrieve-headers (articles &optional group server fetch-old)
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer))
+  'nov)
+
+(defun nnnil-open-server (server &optional definitions)
+  t)
+
+(defun nnnil-close-server (&optional server)
+  t)
+
+(defun nnnil-request-close ()
+  t)
+
+(defun nnnil-server-opened (&optional server)
+  t)
+
+(defun nnnil-status-message (&optional server)
+  nnnil-status-string)
+
+(defun nnnil-request-article (article &optional group server to-buffer)
+  (setq nnnil-status-string "No such group")
+  nil)
+
+(defun nnnil-request-group (group &optional server fast)
+  (let (deactivate-mark)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (insert "411 no such news group\n")))
+  (setq nnnil-status-string "No such group")
+  nil)
+
+(defun nnnil-close-group (group &optional server)
+  t)
+
+(defun nnnil-request-list (&optional server)
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer))
+  t)
+
+(defun nnnil-request-post (&optional server)
+  (setq nnnil-status-string "Read-only server")
+  nil)
+
+(provide 'nnnil)
index 37ac4bb..384599b 100644 (file)
@@ -1,7 +1,9 @@
 ;;; nnoo.el --- OO Gnus Backends
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -25,8 +27,8 @@
 
 ;;; Code:
 
-(require 'nnheader)
 (eval-when-compile (require 'cl))
+(require 'nnheader)
 
 (defvar nnoo-definition-alist nil)
 (defvar nnoo-state-alist nil)
@@ -36,7 +38,7 @@
   "The same as `defvar', only takes list of variables to MAP to."
   `(prog1
        ,(if doc
-           `(defvar ,var ,init ,doc)
+           `(defvar ,var ,init ,(concat doc "\n\nThis is a Gnus server variable.  See Info node `(gnus)Select Methods'."))
          `(defvar ,var ,init))
      (nnoo-define ',var ',map)))
 (put 'defvoo 'lisp-indent-function 2)
                        (cdr (assq pbackend (nnoo-parents backend))))
     (prog1
        (apply function args)
-    ;; Copy the changed variables back into the child.
-    (let ((vars (cdr (assq pbackend (nnoo-parents backend)))))
-      (while vars
-       (set (cadar vars) (symbol-value (caar vars)))
-       (setq vars (cdr vars)))))))
+      ;; Copy the changed variables back into the child.
+      (let ((vars (cdr (assq pbackend (nnoo-parents backend)))))
+       (while vars
+         (set (cadar vars) (symbol-value (caar vars)))
+         (setq vars (cdr vars)))))))
 
 (defun nnoo-execute (backend function &rest args)
   "Execute FUNCTION on behalf of BACKEND."
        (while (setq def (pop defs))
          (unless (assq (car def) bvariables)
            (nconc bvariables
-                  (list (cons (car def) (and (boundp (car def))
-                                             (symbol-value (car def)))))))
+                  (list (cons (car def) (and (boundp (car def))
+                                             (symbol-value (car def)))))))
          (if (equal server "*internal-non-initialized-backend*")
              (set (car def) (symbol-value (cadr def)))
            (set (car def) (cadr def)))))
        (setcdr bstate (delq defs (cdr bstate)))
        (pop defs)
        (while defs
-         (set (car (pop defs)) nil)))))
+         (set (car (pop defs)) nil))))) 
   t)
 
 (defun nnoo-close (backend)
@@ -302,6 +304,20 @@ All functions will return nil and report an error."
                   (&rest args)
                 (nnheader-report ',backend ,(format "%s-%s not implemented"
                                                     backend function))))))))
+
+(defun nnoo-set (server &rest args)
+  (let ((parents (nnoo-parents (car server)))
+       (nnoo-parent-backend (car server)))
+    (while parents
+      (nnoo-change-server (caar parents)
+                         (cadr server)
+                         (cdar parents))
+      (pop parents)))
+  (nnoo-change-server (car server)
+                     (cadr server) (cddr server))
+  (while args
+    (set (pop args) (pop args))))
+
 (provide 'nnoo)
 
-;;; nnoo.el ends here.
+;;; nnoo.el ends here
diff --git a/lisp/nnrss.el b/lisp/nnrss.el
new file mode 100644 (file)
index 0000000..89494fa
--- /dev/null
@@ -0,0 +1,774 @@
+;;; nnrss.el --- interfacing with RSS
+;; Copyright (C) 2001, 2002, 2003  Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: RSS
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'gnus)
+(require 'nnoo)
+(require 'nnmail)
+(require 'message)
+(require 'mm-util)
+(require 'gnus-util)
+(require 'time-date)
+(require 'rfc2231)
+(require 'mm-url)
+(eval-when-compile
+  (ignore-errors
+    (require 'xml)))
+(eval '(require 'xml))
+
+(nnoo-declare nnrss)
+
+(defvoo nnrss-directory (nnheader-concat gnus-directory "rss/")
+  "Where nnrss will save its files.")
+
+;; (group max rss-url)
+(defvoo nnrss-server-data nil)
+
+;; (num timestamp url subject author date extra)
+(defvoo nnrss-group-data nil)
+(defvoo nnrss-group-max 0)
+(defvoo nnrss-group-min 1)
+(defvoo nnrss-group nil)
+(defvoo nnrss-group-hashtb nil)
+(defvoo nnrss-status-string "")
+
+(defconst nnrss-version "nnrss 1.0")
+
+(defvar nnrss-group-alist '()
+  "List of RSS addresses.")
+
+(defvar nnrss-use-local nil)
+
+(defvar nnrss-description-field 'X-Gnus-Description
+  "Field name used for DESCRIPTION.
+To use the description in headers, put this name into `nnmail-extra-headers'.")
+
+(defvar nnrss-url-field 'X-Gnus-Url
+  "Field name used for URL.
+To use the description in headers, put this name into `nnmail-extra-headers'.")
+
+(defvar nnrss-content-function nil
+  "A function which is called in `nnrss-request-article'.
+The arguments are (ENTRY GROUP ARTICLE).
+ENTRY is the record of the current headline. GROUP is the group name.
+ARTICLE is the article number of the current headline.")
+
+(nnoo-define-basics nnrss)
+
+;;; Interface functions
+
+(deffoo nnrss-retrieve-headers (articles &optional group server fetch-old)
+  (nnrss-possibly-change-group group server)
+  (let (e)
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (dolist (article articles)
+       (if (setq e (assq article nnrss-group-data))
+           (insert (number-to-string (car e)) "\t" ;; number
+                   (if (nth 3 e)
+                       (nnrss-format-string (nth 3 e)) "")
+                   "\t" ;; subject
+                   (if (nth 4 e)
+                       (nnrss-format-string (nth 4 e))
+                     "(nobody)")
+                   "\t" ;;from
+                   (or (nth 5 e) "")
+                   "\t" ;; date
+                   (format "<%d@%s.nnrss>" (car e) group)
+                   "\t" ;; id
+                   "\t" ;; refs
+                   "-1" "\t" ;; chars
+                   "-1" "\t" ;; lines
+                   "" "\t" ;; Xref
+                   (if (and (nth 6 e)
+                            (memq nnrss-description-field
+                                  nnmail-extra-headers))
+                       (concat (symbol-name nnrss-description-field)
+                               ": "
+                               (nnrss-format-string (nth 6 e))
+                               "\t")
+                     "")
+                   (if (and (nth 2 e)
+                            (memq nnrss-url-field
+                                  nnmail-extra-headers))
+                       (concat (symbol-name nnrss-url-field)
+                               ": "
+                               (nnrss-format-string (nth 2 e))
+                               "\t")
+                     "")
+                   "\n")))))
+  'nov)
+
+(deffoo nnrss-request-group (group &optional server dont-check)
+  (nnrss-possibly-change-group group server)
+  (if dont-check
+      t
+    (nnrss-check-group group server)
+    (nnheader-report 'nnrss "Opened group %s" group)
+    (nnheader-insert
+     "211 %d %d %d %s\n" nnrss-group-max nnrss-group-min nnrss-group-max
+     (prin1-to-string group)
+     t)))
+
+(deffoo nnrss-close-group (group &optional server)
+  t)
+
+(deffoo nnrss-request-article (article &optional group server buffer)
+  (nnrss-possibly-change-group group server)
+  (let ((e (assq article nnrss-group-data))
+       (boundary "=-=-=-=-=-=-=-=-=-")
+       (nntp-server-buffer (or buffer nntp-server-buffer))
+       post err)
+    (when e
+      (catch 'error
+       (with-current-buffer nntp-server-buffer
+         (erase-buffer)
+         (goto-char (point-min))
+         (insert "Mime-Version: 1.0\nContent-Type: multipart/alternative; boundary=\"" boundary "\"\n")
+         (if group
+             (insert "Newsgroups: " group "\n"))
+         (if (nth 3 e)
+             (insert "Subject: " (nnrss-format-string (nth 3 e)) "\n"))
+         (if (nth 4 e)
+             (insert "From: " (nnrss-format-string (nth 4 e)) "\n"))
+         (if (nth 5 e)
+             (insert "Date: " (nnrss-format-string (nth 5 e)) "\n"))
+         (insert "Message-ID: " (format "<%d@%s.nnrss>" (car e) group) "\n")
+         (insert "\n")
+         (let ((text (if (nth 6 e)
+                         (nnrss-string-as-multibyte (nth 6 e))))
+               (link (if (nth 2 e)
+                         (nth 2 e))))
+           (insert "\n\n--" boundary "\nContent-Type: text/plain\n\n")
+           (let ((point (point)))
+             (if text
+                 (progn (insert text)
+                        (goto-char point)
+                        (while (re-search-forward "\n" nil t)
+                          (replace-match " "))
+                        (goto-char (point-max))
+                        (insert "\n\n")))
+             (if link
+                 (insert link)))
+           (insert "\n\n--" boundary "\nContent-Type: text/html\n\n")
+           (let ((point (point)))
+             (if text
+                 (progn (insert "<html><head></head><body>\n" text "\n</body></html>")
+                        (goto-char point)
+                        (while (re-search-forward "\n" nil t)
+                          (replace-match " "))
+                        (goto-char (point-max))
+                        (insert "\n\n")))
+             (if link
+                 (insert "<p><a href=\"" link "\">link</a></p>\n"))))
+         (if nnrss-content-function
+             (funcall nnrss-content-function e group article)))))
+    (cond
+     (err
+      (nnheader-report 'nnrss err))
+     ((not e)
+      (nnheader-report 'nnrss "no such id: %d" article))
+     (t
+      (nnheader-report 'nnrss "article %s retrieved" (car e))
+      ;; we return the article number.
+      (cons nnrss-group (car e))))))
+
+(deffoo nnrss-request-list (&optional server)
+  (nnrss-possibly-change-group nil server)
+  (nnrss-generate-active)
+  t)
+
+(deffoo nnrss-open-server (server &optional defs connectionless)
+  (nnrss-read-server-data server)
+  (nnoo-change-server 'nnrss server defs)
+  t)
+
+(deffoo nnrss-request-expire-articles
+    (articles group &optional server force)
+  (nnrss-possibly-change-group group server)
+  (let (e days not-expirable changed)
+    (dolist (art articles)
+      (if (and (setq e (assq art nnrss-group-data))
+              (nnmail-expired-article-p
+               group
+               (if (listp (setq days (nth 1 e))) days
+                 (days-to-time (- days (time-to-days '(0 0)))))
+               force))
+         (setq nnrss-group-data (delq e nnrss-group-data)
+               changed t)
+       (push art not-expirable)))
+    (if changed
+       (nnrss-save-group-data group server))
+    not-expirable))
+
+(deffoo nnrss-request-delete-group (group &optional force server)
+  (nnrss-possibly-change-group group server)
+  (setq nnrss-server-data
+       (delq (assoc group nnrss-server-data) nnrss-server-data))
+  (nnrss-save-server-data server)
+  (let ((file (expand-file-name
+              (nnrss-translate-file-chars
+               (concat group (and server
+                                  (not (equal server ""))
+                                  "-")
+                       server ".el")) nnrss-directory)))
+    (ignore-errors
+      (delete-file file)))
+  t)
+
+(deffoo nnrss-request-list-newsgroups (&optional server)
+  (nnrss-possibly-change-group nil server)
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnrss-group-alist)
+      (if (third elem)
+         (insert (car elem) "\t" (third elem) "\n"))))
+  t)
+
+(nnoo-define-skeleton nnrss)
+
+;;; Internal functions
+(eval-when-compile (defun xml-rpc-method-call (&rest args)))
+(defun nnrss-fetch (url &optional local)
+  "Fetch the url and put it in a the expected lisp structure."
+  (with-temp-buffer
+  ;some CVS versions of url.el need this to close the connection quickly
+    (let* (xmlform htmlform)
+      ;; bit o' work necessary for w3 pre-cvs and post-cvs
+      (if local
+         (let ((coding-system-for-read 'binary))
+           (insert-file-contents url))
+       (mm-url-insert url))
+
+;; Because xml-parse-region can't deal with anything that isn't
+;; xml and w3-parse-buffer can't deal with some xml, we have to
+;; parse with xml-parse-region first and, if that fails, parse
+;; with w3-parse-buffer.  Yuck.  Eventually, someone should find out
+;; why w3-parse-buffer fails to parse some well-formed xml and
+;; fix it.
+
+    (condition-case err
+       (setq xmlform (xml-parse-region (point-min) (point-max)))
+      (error (if (fboundp 'w3-parse-buffer)
+                (setq htmlform (caddar (w3-parse-buffer
+                                        (current-buffer))))
+              (message "nnrss: Not valid XML and w3 parse not available (%s)"
+                       url))))
+    (if htmlform
+       htmlform
+      xmlform))))
+
+(defun nnrss-possibly-change-group (&optional group server)
+  (when (and server
+            (not (nnrss-server-opened server)))
+    (nnrss-open-server server))
+  (when (and group (not (equal group nnrss-group)))
+    (nnrss-read-group-data group server)
+    (setq nnrss-group group)))
+
+(defvar nnrss-extra-categories '(nnrss-snarf-moreover-categories))
+
+(defun nnrss-generate-active ()
+  (if (y-or-n-p "fetch extra categories? ")
+      (dolist (func nnrss-extra-categories)
+       (funcall func)))
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnrss-group-alist)
+      (insert (prin1-to-string (car elem)) " 0 1 y\n"))
+    (dolist (elem nnrss-server-data)
+      (unless (assoc (car elem) nnrss-group-alist)
+       (insert (prin1-to-string (car elem)) " 0 1 y\n")))))
+
+;;; data functions
+
+(defun nnrss-read-server-data (server)
+  (setq nnrss-server-data nil)
+  (let ((file (expand-file-name
+              (nnrss-translate-file-chars
+               (concat "nnrss" (and server
+                                    (not (equal server ""))
+                                    "-")
+                       server
+                       ".el"))
+              nnrss-directory)))
+    (when (file-exists-p file)
+      (with-temp-buffer
+       (let ((coding-system-for-read 'binary)
+             (input-coding-system 'binary)
+             emacs-lisp-mode-hook)
+         (insert-file-contents file)
+         (emacs-lisp-mode)
+         (goto-char (point-min))
+         (eval-buffer))))))
+
+(defun nnrss-save-server-data (server)
+  (gnus-make-directory nnrss-directory)
+  (let ((file (expand-file-name
+              (nnrss-translate-file-chars
+               (concat "nnrss" (and server
+                                    (not (equal server ""))
+                                    "-")
+                       server ".el"))
+              nnrss-directory)))
+    (let ((coding-system-for-write 'binary)
+         (output-coding-system 'binary)
+         print-level print-length)
+      (with-temp-file file
+       (insert "(setq nnrss-group-alist '"
+               (prin1-to-string nnrss-group-alist)
+               ")\n")
+       (insert "(setq nnrss-server-data '"
+               (prin1-to-string nnrss-server-data)
+               ")\n")))))
+
+(defun nnrss-read-group-data (group server)
+  (setq nnrss-group-data nil)
+  (setq nnrss-group-hashtb (gnus-make-hashtable))
+  (let ((pair (assoc group nnrss-server-data)))
+    (setq nnrss-group-max (or (cadr pair) 0))
+    (setq nnrss-group-min (+ nnrss-group-max 1)))
+  (let ((file (expand-file-name
+              (nnrss-translate-file-chars
+               (concat group (and server
+                                  (not (equal server ""))
+                                  "-")
+                       server ".el"))
+              nnrss-directory)))
+    (when (file-exists-p file)
+      (with-temp-buffer
+       (let ((coding-system-for-read 'binary)
+             (input-coding-system 'binary)
+             emacs-lisp-mode-hook)
+         (insert-file-contents file)
+         (emacs-lisp-mode)
+         (goto-char (point-min))
+         (eval-buffer)))
+      (dolist (e nnrss-group-data)
+       (gnus-sethash (nth 2 e) e nnrss-group-hashtb)
+       (if (and (car e) (> nnrss-group-min (car e)))
+           (setq nnrss-group-min (car e)))
+       (if (and (car e) (< nnrss-group-max (car e)))
+           (setq nnrss-group-max (car e)))))))
+
+(defun nnrss-save-group-data (group server)
+  (gnus-make-directory nnrss-directory)
+  (let ((file (expand-file-name
+              (nnrss-translate-file-chars
+               (concat group (and server
+                                  (not (equal server ""))
+                                  "-")
+                       server ".el"))
+              nnrss-directory)))
+    (let ((coding-system-for-write 'binary)
+         (output-coding-system 'binary)
+         print-level print-length)
+      (with-temp-file file
+       (insert "(setq nnrss-group-data '"
+               (prin1-to-string nnrss-group-data)
+               ")\n")))))
+
+;;; URL interface
+
+(defun nnrss-no-cache (url)
+  "")
+
+(defun nnrss-insert-w3 (url)
+  (mm-with-unibyte-current-buffer
+    (mm-url-insert url)))
+
+(defun nnrss-decode-entities-unibyte-string (string)
+  (if string
+      (mm-with-unibyte-buffer
+       (insert string)
+       (mm-url-decode-entities-nbsp)
+       (buffer-string))))
+
+(defalias 'nnrss-insert 'nnrss-insert-w3)
+
+(if (featurep 'xemacs)
+    (defalias 'nnrss-string-as-multibyte 'identity)
+  (defalias 'nnrss-string-as-multibyte 'string-as-multibyte))
+
+;;; Snarf functions
+
+(defun nnrss-check-group (group server)
+  (let (file xml subject url extra changed author
+            date rss-ns rdf-ns content-ns dc-ns)
+    (if (and nnrss-use-local
+            (file-exists-p (setq file (expand-file-name
+                                       (nnrss-translate-file-chars
+                                        (concat group ".xml"))
+                                       nnrss-directory))))
+       (setq xml (nnrss-fetch file t))
+      (setq url (or (nth 2 (assoc group nnrss-server-data))
+                   (second (assoc group nnrss-group-alist))))
+      (unless url
+       (setq url
+             (cdr
+              (assoc 'href
+                     (nnrss-discover-feed
+                      (read-string
+                       (format "URL to search for %s: " group) "http://")))))
+       (let ((pair (assoc group nnrss-server-data)))
+         (if pair
+             (setcdr (cdr pair) (list url))
+           (push (list group nnrss-group-max url) nnrss-server-data)))
+       (setq changed t))
+      (setq xml (nnrss-fetch url)))
+    ;; See
+    ;; http://feeds.archive.org/validator/docs/howto/declare_namespaces.html
+    ;; for more RSS namespaces.
+    (setq dc-ns (nnrss-get-namespace-prefix xml "http://purl.org/dc/elements/1.1/")
+         rdf-ns (nnrss-get-namespace-prefix xml "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+         rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")
+         content-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/modules/content/"))
+    (dolist (item (nreverse (nnrss-find-el (intern (concat rss-ns "item")) xml)))
+      (when (and (listp item)
+                (eq (intern (concat rss-ns "item")) (car item))
+                (setq url (nnrss-decode-entities-unibyte-string
+                           (nnrss-node-text rss-ns 'link (cddr item))))
+                (not (gnus-gethash url nnrss-group-hashtb)))
+       (setq subject (nnrss-node-text rss-ns 'title item))
+       (setq extra (or (nnrss-node-text content-ns 'encoded item)
+                       (nnrss-node-text rss-ns 'description item)))
+       (setq author (or (nnrss-node-text rss-ns 'author item)
+                        (nnrss-node-text dc-ns 'creator item)
+                        (nnrss-node-text dc-ns 'contributor item)))
+       (setq date (or (nnrss-node-text dc-ns 'date item)
+                      (nnrss-node-text rss-ns 'pubDate item)
+                      (message-make-date)))
+       (push
+        (list
+         (incf nnrss-group-max)
+         (current-time)
+         url
+         (and subject (nnrss-decode-entities-unibyte-string subject))
+         (and author (nnrss-decode-entities-unibyte-string author))
+         date
+         (and extra (nnrss-decode-entities-unibyte-string extra)))
+        nnrss-group-data)
+       (gnus-sethash url (car nnrss-group-data) nnrss-group-hashtb)
+       (setq changed t)))
+    (when changed
+      (nnrss-save-group-data group server)
+      (let ((pair (assoc group nnrss-server-data)))
+       (if pair
+           (setcar (cdr pair) nnrss-group-max)
+         (push (list group nnrss-group-max) nnrss-server-data)))
+      (nnrss-save-server-data server))))
+
+(defun nnrss-generate-download-script ()
+  "Generate a download script in the current buffer.
+It is useful when `(setq nnrss-use-local t)'."
+  (interactive)
+  (insert "#!/bin/sh\n")
+  (insert "WGET=wget\n")
+  (insert "RSSDIR='" (expand-file-name nnrss-directory) "'\n")
+  (dolist (elem nnrss-server-data)
+    (let ((url (or (nth 2 elem)
+                  (second (assoc (car elem) nnrss-group-alist)))))
+      (insert "$WGET -q -O \"$RSSDIR\"/'"
+             (nnrss-translate-file-chars (concat (car elem) ".xml"))
+             "' '" url "'\n"))))
+
+(defun nnrss-translate-file-chars (name)
+  (let ((nnheader-file-name-translation-alist
+        (append nnheader-file-name-translation-alist '((?' . ?_)))))
+    (nnheader-translate-file-chars name)))
+
+(defvar nnrss-moreover-url
+  "http://w.moreover.com/categories/category_list_rss.html"
+  "The url of moreover.com categories.")
+
+(defun nnrss-snarf-moreover-categories ()
+  "Snarf RSS links from moreover.com."
+  (interactive)
+  (let (category name url changed)
+    (with-temp-buffer
+      (nnrss-insert nnrss-moreover-url)
+      (goto-char (point-min))
+      (while (re-search-forward
+             "<a name=\"\\([^\"]+\\)\">\\|<a href=\"\\(http://[^\"]*moreover\\.com[^\"]+page\\?c=\\([^\"&]+\\)&o=rss\\)" nil t)
+       (if (match-string 1)
+           (setq category (match-string 1))
+         (setq url (match-string 2)
+               name (mm-url-decode-entities-string
+                     (rfc2231-decode-encoded-string
+                      (match-string 3))))
+         (if category
+             (setq name (concat category "." name)))
+         (unless (assoc name nnrss-server-data)
+           (setq changed t)
+           (push (list name 0 url) nnrss-server-data)))))
+    (if changed
+       (nnrss-save-server-data ""))))
+
+(defun nnrss-format-string (string)
+  (gnus-replace-in-string (nnrss-string-as-multibyte string) " *\n *" " "))
+
+(defun nnrss-node-text (namespace local-name element)
+  (let* ((node (assq (intern (concat namespace (symbol-name local-name)))
+                    element))
+        (text (if (and node (listp node))
+                  (nnrss-node-just-text node)
+                node))
+        (cleaned-text (if text (gnus-replace-in-string
+                                text "^[\000-\037\177]+\\|^ +\\| +$" ""))))
+    (if (string-equal "" cleaned-text)
+       nil
+      cleaned-text)))
+
+(defun nnrss-node-just-text (node)
+  (if (and node (listp node))
+      (mapconcat 'nnrss-node-just-text (cddr node) " ")
+    node))
+
+(defun nnrss-find-el (tag data &optional found-list)
+  "Find the all matching elements in the data.  Careful with this on
+large documents!"
+  (if (listp data)
+      (mapcar (lambda (bit)
+               (if (car-safe bit)
+                   (progn (if (equal tag (car bit))
+                              (setq found-list
+                                    (append found-list
+                                            (list bit))))
+                          (if (and (listp (car-safe (caddr bit)))
+                                   (not (stringp (caddr bit))))
+                              (setq found-list
+                                    (append found-list
+                                            (nnrss-find-el
+                                             tag (caddr bit))))
+                            (setq found-list
+                                  (append found-list
+                                          (nnrss-find-el
+                                           tag (cddr bit))))))))
+               data))
+  found-list)
+
+(defun nnrss-rsslink-p (el)
+  "Test if the element we are handed is an RSS autodiscovery link."
+  (and (eq (car-safe el) 'link)
+       (string-equal (cdr (assoc 'rel (cadr el))) "alternate")
+       (or (string-equal (cdr (assoc 'type (cadr el))) 
+                        "application/rss+xml")
+          (string-equal (cdr (assoc 'type (cadr el))) "text/xml"))))
+
+(defun nnrss-get-rsslinks (data)
+  "Extract the <link> elements that are links to RSS from the parsed data."
+  (delq nil (mapcar 
+            (lambda (el)
+              (if (nnrss-rsslink-p el) el))
+            (nnrss-find-el 'link data))))
+
+(defun nnrss-extract-hrefs (data)
+  "Recursively extract hrefs from a page's source.  DATA should be
+the output of xml-parse-region or w3-parse-buffer."
+  (mapcar (lambda (ahref)
+           (cdr (assoc 'href (cadr ahref))))
+         (nnrss-find-el 'a data)))
+
+(defmacro nnrss-match-macro (base-uri item 
+                                          onsite-list offsite-list)
+  `(cond ((or (string-match (concat "^" ,base-uri) ,item)
+              (not (string-match "://" ,item)))
+          (setq ,onsite-list (append ,onsite-list (list ,item))))
+         (t (setq ,offsite-list (append ,offsite-list (list ,item))))))
+
+(defun nnrss-order-hrefs (base-uri hrefs)
+  "Given a list of hrefs, sort them using the following priorities:
+  1. links ending in .rss
+  2. links ending in .rdf
+  3. links ending in .xml
+  4. links containing the above
+  5. offsite links
+
+BASE-URI is used to determine the location of the links and
+whether they are `offsite' or `onsite'."
+  (let (rss-onsite-end  rdf-onsite-end  xml-onsite-end
+       rss-onsite-in   rdf-onsite-in   xml-onsite-in
+       rss-offsite-end rdf-offsite-end xml-offsite-end
+       rss-offsite-in rdf-offsite-in xml-offsite-in)
+    (mapcar (lambda (href)
+             (if (not (null href))
+             (cond ((string-match "\\.rss$" href)
+                    (nnrss-match-macro
+                     base-uri href rss-onsite-end rss-offsite-end))
+                   ((string-match "\\.rdf$" href)
+                    (nnrss-match-macro 
+                     base-uri href rdf-onsite-end rdf-offsite-end))
+                   ((string-match "\\.xml$" href)
+                    (nnrss-match-macro
+                     base-uri href xml-onsite-end xml-offsite-end))
+                   ((string-match "rss" href)
+                    (nnrss-match-macro
+                     base-uri href rss-onsite-in rss-offsite-in))
+                   ((string-match "rdf" href)
+                    (nnrss-match-macro
+                     base-uri href rdf-onsite-in rdf-offsite-in))
+                   ((string-match "xml" href)
+                    (nnrss-match-macro
+                     base-uri href xml-onsite-in xml-offsite-in)))))
+           hrefs)
+    (append 
+     rss-onsite-end  rdf-onsite-end  xml-onsite-end
+     rss-onsite-in   rdf-onsite-in   xml-onsite-in
+     rss-offsite-end rdf-offsite-end xml-offsite-end
+     rss-offsite-in rdf-offsite-in xml-offsite-in)))
+
+(defun nnrss-discover-feed (url)
+  "Given a page, find an RSS feed using Mark Pilgrim's
+`ultra-liberal rss locator' (http://diveintomark.org/2002/08/15.html)."
+
+  (let ((parsed-page (nnrss-fetch url)))
+
+;;    1. if this url is the rss, use it.
+    (if (nnrss-rss-p parsed-page)
+       (let ((rss-ns (nnrss-get-namespace-prefix parsed-page "http://purl.org/rss/1.0/")))
+         (nnrss-rss-title-description rss-ns parsed-page url))
+
+;;    2. look for the <link rel="alternate"
+;;    type="application/rss+xml" and use that if it is there.
+      (let ((links (nnrss-get-rsslinks parsed-page)))
+       (if links
+           (let* ((xml (nnrss-fetch
+                        (cdr (assoc 'href (cadar links)))))
+                  (rss-ns (nnrss-get-namespace-prefix xml "http://purl.org/rss/1.0/")))
+             (nnrss-rss-title-description rss-ns xml (cdr (assoc 'href (cadar links)))))
+
+;;    3. look for links on the site in the following order:
+;;       - onsite links ending in .rss, .rdf, or .xml
+;;       - onsite links containing any of the above
+;;       - offsite links ending in .rss, .rdf, or .xml
+;;       - offsite links containing any of the above
+         (let* ((base-uri (progn (string-match ".*://[^/]+/?" url)
+                                 (match-string 0 url)))
+                (hrefs (nnrss-order-hrefs 
+                        base-uri (nnrss-extract-hrefs parsed-page)))
+                (rss-link nil))
+         (while (and (eq rss-link nil) (not (eq hrefs nil)))
+           (let ((href-data (nnrss-fetch (car hrefs))))
+             (if (nnrss-rss-p href-data)
+                 (let* ((rss-ns (nnrss-get-namespace-prefix href-data "http://purl.org/rss/1.0/")))
+                   (setq rss-link (nnrss-rss-title-description
+                                   rss-ns href-data (car hrefs))))
+               (setq hrefs (cdr hrefs)))))
+         (if rss-link rss-link
+
+;;    4. check syndic8
+           (nnrss-find-rss-via-syndic8 url))))))))
+
+(defun nnrss-find-rss-via-syndic8 (url)
+  "query syndic8 for the rss feeds it has for the url."
+  (if (not (locate-library "xml-rpc"))
+      (progn
+       (message "XML-RPC is not available... not checking Syndic8.")
+       nil)
+    (require 'xml-rpc)
+    (let ((feedid (xml-rpc-method-call
+                  "http://www.syndic8.com/xmlrpc.php"
+                  'syndic8.FindSites
+                  url)))
+      (when feedid
+       (let* ((feedinfo (xml-rpc-method-call 
+                         "http://www.syndic8.com/xmlrpc.php"
+                         'syndic8.GetFeedInfo
+                         feedid))
+              (urllist
+               (delq nil 
+                     (mapcar
+                      (lambda (listinfo)
+                        (if (string-equal 
+                             (cdr (assoc "status" listinfo))
+                             "Syndicated")
+                            (cons
+                             (cdr (assoc "sitename" listinfo))
+                             (list
+                              (cons 'title
+                                    (cdr (assoc 
+                                          "sitename" listinfo)))
+                              (cons 'href
+                                    (cdr (assoc
+                                          "dataurl" listinfo)))))))
+                      feedinfo))))
+         (if (not (> (length urllist) 1))
+             (cdar urllist)
+           (let ((completion-ignore-case t)
+                 (selection 
+                  (mapcar (lambda (listinfo)
+                            (cons (cdr (assoc "sitename" listinfo)) 
+                                  (string-to-int 
+                                   (cdr (assoc "feedid" listinfo)))))
+                          feedinfo)))
+             (cdr (assoc 
+                   (completing-read
+                    "Multiple feeds found.  Select one: "
+                    selection nil t) urllist)))))))))
+
+(defun nnrss-rss-p (data)
+  "Test if data is an RSS feed.  Simply ensures that the first
+element is rss or rdf."
+  (or (eq (caar data) 'rss)
+      (eq (caar data) 'rdf:RDF)))
+
+(defun nnrss-rss-title-description (rss-namespace data url)
+  "Return the title of an RSS feed."
+  (if (nnrss-rss-p data)
+      (let ((description (intern (concat rss-namespace "description")))
+           (title (intern (concat rss-namespace "title")))
+           (channel (nnrss-find-el (intern (concat rss-namespace "channel"))
+                                   data)))
+       (list
+        (cons 'description (caddr (nth 0 (nnrss-find-el description channel))))
+        (cons 'title (caddr (nth 0 (nnrss-find-el title channel))))
+        (cons 'href url)))))
+
+(defun nnrss-get-namespace-prefix (el uri)
+  "Given EL (containing a parsed element) and URI (containing a string
+that gives the URI for which you want to retrieve the namespace
+prefix), return the prefix."
+  (let* ((prefix (car (rassoc uri (cadar el))))
+        (nslist (if prefix 
+                    (split-string (symbol-name prefix) ":")))
+        (ns (cond ((eq (length nslist) 1) ; no prefix given
+                   "")
+                  ((eq (length nslist) 2) ; extract prefix
+                   (cadr nslist)))))
+    (if (and ns (not (eq ns "")))
+       (concat ns ":")
+      ns)))
+
+(provide 'nnrss)
+
+
+;;; nnrss.el ends here
+
diff --git a/lisp/nnshimbun.el b/lisp/nnshimbun.el
new file mode 100644 (file)
index 0000000..87675c9
--- /dev/null
@@ -0,0 +1,762 @@
+;;; nnshimbun.el --- interfacing with web newspapers
+
+;; Copyright (C) 2000,2001,2002 TSUCHIYA Masatoshi <tsuchiya@namazu.org>
+
+;; Authors: TSUCHIYA Masatoshi <tsuchiya@namazu.org>,
+;;          Akihiro Arisawa    <ari@atesoft.advantest.co.jp>,
+;;          Katsumi Yamaoka    <yamaoka@jpl.org>,
+;;          Yuuichi Teranishi  <teranisi@gohome.org>
+;; Keywords: news
+
+;; This file is a part of Semi-Gnus.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, you can either send email to this
+;; program's maintainer or write to: The Free Software Foundation,
+;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Gnus (or gnus) backend to read newspapers on the World Wide Web.
+;; This module requires the emacs-w3m and the external command w3m.
+;; Visit the following pages for more information.
+;;
+;;     http://emacs-w3m.namazu.org/
+;;     http://w3m.sourceforge.net/
+
+;; If you would like to use this module in Gnus (not T-gnus), put this
+;; file into the lisp/ directory in the Gnus source tree and run `make
+;; install'.  And then, put the following expression into your ~/.gnus.
+;;
+;; (autoload 'gnus-group-make-shimbun-group "nnshimbun" nil t)
+
+
+;;; Definitions:
+
+(eval-when-compile (require 'cl))
+(require 'nnoo)
+(require 'nnheader)
+(require 'nnmail)
+(require 'gnus-bcklg)
+(require 'shimbun)
+
+
+;; Customize variables
+(defgroup nnshimbun nil
+  "Reading Web Newspapers with Gnus."
+  :group 'gnus)
+
+(defvar nnshimbun-group-parameters-custom
+  '(list :format "%v"
+        (checklist :inline t
+                   (list :inline t :format "%v"
+                         (const :format "" index-range)
+                         (choice :tag "Index range"
+                                 :value all
+                                 (const all)
+                                 (const last)
+                                 (integer :tag "days")))
+                   (list :inline t :format "%v"
+                         (const :format "" prefetch-articles)
+                         (choice :tag "Prefetch articles"
+                                 :value off
+                                 (const on)
+                                 (const off)))
+                   (list :inline t :format "%v"
+                         (const :format "" encapsulate-images)
+                         (choice :tag "Encapsulate article"
+                                 :value on
+                                 (const on)
+                                 (const off)))
+                   (list :inline t :format "%v"
+                         (const :format "" expiry-wait)
+                         (choice :tag "Expire wait"
+                                 :value never
+                                 (const never)
+                                 (const immediate)
+                                 (number :tag "days"))))
+        (repeat :inline t :tag "Others"
+                (list :inline t :format "%v"
+                      (symbol :tag "Keyword")
+                      (sexp :tag "Value"))))
+  "A type definition for customizing the nnshimbun group parameters.")
+
+;; The following definition provides the group parameter
+;; `nnshimbun-group-parameters', the user option
+;; `nnshimbun-group-parameters-alist' and the function
+;; `nnshimbun-find-group-parameters'.
+;; The group parameter `nnshimbun-group-parameters' will have a
+;; property list like the following:
+;;
+;; '(index-range all prefetch-articles off encapsulate-images on
+;;               expiry-wait 6)
+
+(unless (fboundp 'gnus-define-group-parameter)
+  (defmacro gnus-define-group-parameter (&rest args) nil)
+  (defun nnshimbun-find-group-parameters (name)
+    "Return a nnshimbun GROUP's group parameters."
+    (when name
+      (or (gnus-group-find-parameter name 'nnshimbun-group-parameters t)
+         (assoc-default name
+                        (and (boundp 'nnshimbun-group-parameters-alist)
+                             (symbol-value 'nnshimbun-group-parameters-alist))
+                        (function string-match))))))
+
+(gnus-define-group-parameter
+ nnshimbun-group-parameters
+ :type list
+ :function nnshimbun-find-group-parameters
+ :function-document "\
+Return a nnshimbun GROUP's group parameters."
+ :variable nnshimbun-group-parameters-alist
+ :variable-default nil
+ :variable-document "\
+Alist of nnshimbun group parameters.  Each element should be a cons of
+a group name regexp and a plist which consists of a keyword and a value
+pairs like the following:
+
+'(\"^nnshimbun\\\\+asahi:\" index-range all prefetch-articles off
+  encapsulate-images on expiry-wait 6)
+
+`index-range' specifies a range of header indices as described below:
+      all: Retrieve all header indices.
+     last: Retrieve the last header index.
+integer N: Retrieve N pages of header indices.
+
+`prefetch-articles' specifies whether to pre-fetch the unread articles
+when scanning the group.
+
+`encapsulate-images' specifies whether inline images in the shimbun
+article are encapsulated.
+
+`expiry-wait' is similar to the generic group parameter `expiry-wait',
+but it has a preference."
+ :variable-group nnshimbun
+ :variable-type `(repeat (cons :format "%v" (regexp :tag "Group name regexp"
+                                                   :value "^nnshimbun\\+")
+                              ,nnshimbun-group-parameters-custom))
+ :parameter-type nnshimbun-group-parameters-custom
+ :parameter-document "\
+Group parameters for the nnshimbun group.
+
+`Index range' specifies a range of header indices as described below:
+      all: Retrieve all header indices.
+     last: Retrieve the last header index.
+integer N: Retrieve N pages of header indices.
+
+`Prefetch articles' specifies whether to pre-fetch the unread articles
+when scanning the group.
+
+`Encapsulate article' specifies whether inline images in the shimbun
+article are encapsulated.
+
+`Expire wait' is similar to the generic group parameter `expiry-wait',
+but it has a preference.")
+
+(defcustom nnshimbun-keep-unparsable-dated-articles t "\
+*If non-nil, nnshimbun will never delete articles whose NOV date is unparsable."
+  :group 'nnshimbun
+  :type 'boolean)
+
+
+;; Define backend
+(gnus-declare-backend "nnshimbun" 'address)
+(nnoo-declare nnshimbun)
+
+(defvoo nnshimbun-directory (nnheader-concat gnus-directory "shimbun/")
+  "Where nnshimbun will save its files.")
+
+(defvoo nnshimbun-nov-is-evil nil
+  "*Non-nil means that nnshimbun will never retrieve NOV headers.")
+
+(defvoo nnshimbun-nov-file-name ".overview")
+
+(defvoo nnshimbun-pre-fetch-article 'off
+  "*If it is neither `off' nor nil, nnshimbun fetch unread articles when
+scanning groups.  Note that this variable has just a default value for
+all the nnshimbun groups.  You can specify the nnshimbun group
+parameter `prefecth-articles' for each nnshimbun group.")
+
+(defvoo nnshimbun-encapsulate-images shimbun-encapsulate-images
+  "*If it is neither `off' nor nil, inline images will be encapsulated in
+the articles.  Note that this variable has just a default value for
+all the nnshimbun groups.  You can specify the nnshimbun group
+parameter `encapsulate-images' for each nnshimbun group.")
+
+(defvoo nnshimbun-index-range nil
+  "*Range of indices to detect new pages.  Note that this variable has
+just a default value for all the nnshimbun groups.  You can specify
+the nnshimbun group parameter `index-range' for each nnshimbun group.")
+
+
+;; set by nnshimbun-open-server
+(defvoo nnshimbun-shimbun nil)
+
+(defvoo nnshimbun-status-string "")
+(defvoo nnshimbun-keep-backlog 300)
+(defvoo nnshimbun-backlog-articles nil)
+(defvoo nnshimbun-backlog-hashtb nil)
+
+
+;;; backlog
+(defmacro nnshimbun-current-server ()
+  '(nnoo-current-server 'nnshimbun))
+
+(defmacro nnshimbun-server-directory (&optional server)
+  `(nnmail-group-pathname ,(or server '(nnshimbun-current-server))
+                         nnshimbun-directory))
+
+(defmacro nnshimbun-current-group ()
+  '(shimbun-current-group-internal nnshimbun-shimbun))
+
+(defmacro nnshimbun-current-directory (&optional group)
+  `(nnmail-group-pathname ,(or group '(nnshimbun-current-group))
+                         (nnshimbun-server-directory)))
+
+(defmacro nnshimbun-backlog (&rest form)
+  `(let ((gnus-keep-backlog nnshimbun-keep-backlog)
+        (gnus-backlog-buffer
+         (format " *nnshimbun backlog %s*" (nnshimbun-current-server)))
+        (gnus-backlog-articles nnshimbun-backlog-articles)
+        (gnus-backlog-hashtb nnshimbun-backlog-hashtb))
+     (unwind-protect
+        (progn ,@form)
+       (setq nnshimbun-backlog-articles gnus-backlog-articles
+            nnshimbun-backlog-hashtb gnus-backlog-hashtb))))
+(put 'nnshimbun-backlog 'lisp-indent-function 0)
+(put 'nnshimbun-backlog 'edebug-form-spec t)
+
+
+;;; Group parameter
+(defmacro nnshimbun-find-parameter (group symbol &optional full-name-p)
+  "Return the value of a nnshimbun group parameter for GROUP which is
+associated with SYMBOL.  If FULL-NAME-P is non-nil, it treats that
+GROUP has a full name."
+  (let ((name (if full-name-p
+                 group
+               `(concat "nnshimbun+" (nnshimbun-current-server) ":" ,group))))
+    (cond ((eq 'index-range (eval symbol))
+          `(or (plist-get (nnshimbun-find-group-parameters ,name)
+                          'index-range)
+               nnshimbun-index-range))
+         ((eq 'prefetch-articles (eval symbol))
+          `(let ((val (or (plist-get (nnshimbun-find-group-parameters ,name)
+                                     'prefetch-articles)
+                          nnshimbun-pre-fetch-article)))
+             (if (eq 'off val)
+                 nil
+               val)))
+         ((eq 'encapsulate-images (eval symbol))
+          `(let ((val (or (plist-get (nnshimbun-find-group-parameters ,name)
+                                     'encapsulate-images)
+                          nnshimbun-encapsulate-images)))
+             (if (eq 'off val)
+                 nil
+               val)))
+         ((eq 'expiry-wait (eval symbol))
+          (if full-name-p
+              `(or (plist-get (nnshimbun-find-group-parameters ,group)
+                              'expiry-wait)
+                   (gnus-group-find-parameter ,group 'expiry-wait))
+            `(let ((name ,name))
+               (or (plist-get (nnshimbun-find-group-parameters name)
+                              'expiry-wait)
+                   (gnus-group-find-parameter name 'expiry-wait)))))
+         (t
+          `(plist-get (nnshimbun-find-group-parameters ,name) ,symbol)))))
+
+
+;;; Interface Functions
+(nnoo-define-basics nnshimbun)
+
+(defun nnshimbun-possibly-change-group (group &optional server)
+  (when (if server
+           (nnshimbun-open-server server)
+         nnshimbun-shimbun)
+    (or (not group)
+       (when (condition-case err
+                 (shimbun-open-group nnshimbun-shimbun group)
+               (error
+                (nnheader-report 'nnshimbun "%s" (error-message-string err))))
+         (let ((file-name-coding-system nnmail-pathname-coding-system)
+               (pathname-coding-system nnmail-pathname-coding-system)
+               (dir (nnshimbun-current-directory group)))
+           (or (file-directory-p dir)
+               (ignore-errors
+                 (make-directory dir)
+                 (file-directory-p dir))
+               (nnheader-report 'nnshimbun
+                                (if (file-exists-p dir)
+                                    "Not a directory: %s"
+                                  "Couldn't create directory: %s")
+                                dir)))))))
+
+(deffoo nnshimbun-open-server (server &optional defs)
+  (or (nnshimbun-server-opened server)
+      (let ((file-name-coding-system nnmail-pathname-coding-system)
+           (pathname-coding-system nnmail-pathname-coding-system)
+           (shimbun))
+       (when (condition-case err
+                 (setq shimbun
+                       (shimbun-open server
+                                     (luna-make-entity 'shimbun-gnus-mua)))
+               (error
+                (nnheader-report 'nnshimbun "%s" (error-message-string err))))
+         (nnoo-change-server 'nnshimbun server
+                             (cons (list 'nnshimbun-shimbun shimbun) defs))
+         (when (or (file-directory-p nnshimbun-directory)
+                   (ignore-errors
+                     (make-directory nnshimbun-directory)
+                     (file-directory-p nnshimbun-directory))
+                   (progn
+                     (nnshimbun-close-server)
+                     (nnheader-report 'nnshimbun
+                                      (if (file-exists-p nnshimbun-directory)
+                                          "Not a directory: %s"
+                                        "Couldn't create directory: %s")
+                                      nnshimbun-directory)))
+           (let ((dir (nnshimbun-server-directory server)))
+             (when (or (file-directory-p dir)
+                       (ignore-errors
+                         (make-directory dir)
+                         (file-directory-p dir))
+                       (progn
+                         (nnshimbun-close-server)
+                         (nnheader-report 'nnshimbun
+                                          (if (file-exists-p dir)
+                                              "Not a directory: %s"
+                                            "Couldn't create directory: %s")
+                                          dir)))
+               (nnheader-report 'nnshimbun
+                                "Opened server %s using directory %s"
+                                server dir)
+               t)))))))
+
+(deffoo nnshimbun-close-server (&optional server)
+  (when (nnshimbun-server-opened server)
+    (when nnshimbun-shimbun
+      (dolist (group (shimbun-groups nnshimbun-shimbun))
+       (nnshimbun-write-nov group t))
+      (shimbun-close nnshimbun-shimbun)))
+  (nnshimbun-backlog (gnus-backlog-shutdown))
+  (nnoo-close-server 'nnshimbun server)
+  t)
+
+(eval-when-compile
+  (require 'gnus-sum)) ;; For the macro `gnus-summary-article-header'.
+
+(defun nnshimbun-request-article-1 (article &optional group server to-buffer)
+  (if (nnshimbun-backlog
+       (gnus-backlog-request-article
+        group article (or to-buffer nntp-server-buffer)))
+      (cons group article)
+    (let* ((header (with-current-buffer (nnshimbun-open-nov group)
+                    (and (nnheader-find-nov-line article)
+                         (nnshimbun-parse-nov))))
+          (original-id (shimbun-header-id header)))
+      (when header
+       (with-current-buffer (or to-buffer nntp-server-buffer)
+         (erase-buffer)
+         (let ((shimbun-encapsulate-images
+                (nnshimbun-find-parameter group 'encapsulate-images)))
+           (shimbun-article nnshimbun-shimbun header))
+         (when (> (buffer-size) 0)
+           ;; Kludge! replace a date string in `gnus-newsgroup-data'
+           ;; based on the newly retrieved article.
+           (let ((x (gnus-summary-article-header article)))
+             (when x
+               ;; Trick to suppress byte compile of mail-header-set-date(),
+               ;; in order to keep compatibility between T-gnus and Oort Gnus.
+               (eval
+                `(mail-header-set-date ,x ,(shimbun-header-date header)))))
+           (nnshimbun-replace-nov-entry group article header original-id)
+           (nnshimbun-backlog
+             (gnus-backlog-enter-article group article (current-buffer)))
+           (nnheader-report 'nnshimbun "Article %s retrieved"
+                            (shimbun-header-id header))
+           (cons group article)))))))
+
+(deffoo nnshimbun-request-article (article &optional group server to-buffer)
+  (when (nnshimbun-possibly-change-group group server)
+    (if (or (integerp article)
+           (when (stringp article)
+             (setq article
+                   (or (when (or group (setq group (nnshimbun-current-group)))
+                         (nnshimbun-search-id group article))
+                       (catch 'found
+                         (dolist (x (shimbun-groups nnshimbun-shimbun))
+                           (and (nnshimbun-possibly-change-group x)
+                                (setq x (nnshimbun-search-id x article))
+                                (throw 'found x))))))))
+       (nnshimbun-request-article-1 article group server to-buffer)
+      (nnheader-report 'nnshimbun "Couldn't retrieve article: %s"
+                      (prin1-to-string article)))))
+
+(deffoo nnshimbun-request-group (group &optional server dont-check)
+  (if (not (nnshimbun-possibly-change-group group server))
+      (nnheader-report 'nnshimbun "Invalid group (no such directory)")
+    (let (beg end lines)
+      (with-current-buffer (nnshimbun-open-nov group)
+       (goto-char (point-min))
+       (setq beg (ignore-errors (read (current-buffer))))
+       (goto-char (point-max))
+       (forward-line -1)
+       (setq end (ignore-errors (read (current-buffer)))
+             lines (count-lines (point-min) (point-max))))
+      (nnheader-report 'nnshimbun "Selected group %s" group)
+      (nnheader-insert "211 %d %d %d %s\n"
+                      lines (or beg 0) (or end 0) group))))
+
+(deffoo nnshimbun-request-scan (&optional group server)
+  (when (nnshimbun-possibly-change-group nil server)
+    (if group
+       (nnshimbun-generate-nov-database group)
+      (dolist (group (shimbun-groups nnshimbun-shimbun))
+       (nnshimbun-generate-nov-database group)))))
+
+(deffoo nnshimbun-close-group (group &optional server)
+  (nnshimbun-write-nov group)
+  t)
+
+(deffoo nnshimbun-request-list (&optional server)
+  (when (nnshimbun-possibly-change-group nil server)
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (dolist (group (shimbun-groups nnshimbun-shimbun))
+       (when (nnshimbun-possibly-change-group group)
+         (let (beg end)
+           (with-current-buffer (nnshimbun-open-nov group)
+             (goto-char (point-min))
+             (setq beg (ignore-errors (read (current-buffer))))
+             (goto-char (point-max))
+             (forward-line -1)
+             (setq end (ignore-errors (read (current-buffer)))))
+           (insert (format "%s %d %d n\n" group (or end 0) (or beg 0)))))))
+    t)) ; return value
+
+(deffoo nnshimbun-retrieve-headers (articles &optional group server fetch-old)
+  (when (nnshimbun-possibly-change-group group server)
+    (if (nnshimbun-retrieve-headers-with-nov articles group fetch-old)
+       'nov
+      (with-current-buffer nntp-server-buffer
+       (erase-buffer)
+       (let (header)
+         (dolist (art articles)
+           (when (and (if (stringp art)
+                          (setq art (nnshimbun-search-id group art))
+                        (integerp art))
+                      (setq header
+                            (with-current-buffer (nnshimbun-open-nov group)
+                              (and (nnheader-find-nov-line art)
+                                   (nnshimbun-parse-nov)))))
+             (insert (format "220 %d Article retrieved.\n" art))
+             (shimbun-header-insert nnshimbun-shimbun header)
+             (insert ".\n")
+             (delete-region (point) (point-max)))))
+       'header))))
+
+(defun nnshimbun-retrieve-headers-with-nov (articles &optional group fetch-old)
+  (unless (or gnus-nov-is-evil nnshimbun-nov-is-evil)
+    (with-current-buffer nntp-server-buffer
+      (erase-buffer)
+      (insert-buffer (nnshimbun-open-nov group))
+      (unless (and fetch-old (not (numberp fetch-old)))
+       (nnheader-nov-delete-outside-range
+        (if fetch-old
+            (max 1 (- (car articles) fetch-old))
+          (car articles))
+        (nth (1- (length articles)) articles)))
+      t)))
+
+
+;;; Nov Database Operations
+(defvar nnshimbun-tmp-string nil
+  "Internal variable used to just a rest for a temporary string.  The
+macro `nnshimbun-string-or' uses it exclusively.")
+
+(defmacro nnshimbun-string-or (&rest strings)
+  "Return the first element of STRINGS that is a non-blank string.  It
+should run fast, especially if two strings are given.  Each string can
+also be nil."
+  (cond ((null strings)
+        nil)
+       ((= 1 (length strings))
+        ;; Return irregularly nil if one blank string is given.
+        `(unless (zerop (length (setq nnshimbun-tmp-string ,(car strings))))
+           nnshimbun-tmp-string))
+       ((= 2 (length strings))
+        ;; Return the second string when the first string is blank.
+        `(if (zerop (length (setq nnshimbun-tmp-string ,(car strings))))
+             ,(cadr strings)
+           nnshimbun-tmp-string))
+       (t
+        `(let ((strings (list ,@strings)))
+           (while strings
+             (setq strings (if (zerop (length (setq nnshimbun-tmp-string
+                                                    (car strings))))
+                               (cdr strings))))
+           nnshimbun-tmp-string))))
+
+(autoload 'message-make-date "message")
+
+(defsubst nnshimbun-insert-nov (number header &optional id)
+  (insert "\n")
+  (backward-char 1)
+  (let ((header-id (nnshimbun-string-or (shimbun-header-id header)))
+       ;; Force `princ' to work in the current buffer.
+       (standard-output (current-buffer))
+       (xref (nnshimbun-string-or (shimbun-header-xref header)))
+       (start (point)))
+    (and (stringp id)
+        header-id
+        (string-equal id header-id)
+        (setq id nil))
+    (princ number)
+    (insert
+     "\t"
+     (nnshimbun-string-or (shimbun-header-subject header) "(none)") "\t"
+     (nnshimbun-string-or (shimbun-header-from header) "(nobody)") "\t"
+     (nnshimbun-string-or (shimbun-header-date header) (message-make-date))
+     "\t"
+     (or header-id (nnmail-message-id)) "\t"
+     (or (shimbun-header-references header) "") "\t")
+    (princ (or (shimbun-header-chars header) 0))
+    (insert "\t")
+    (princ (or (shimbun-header-lines header) 0))
+    (insert "\t")
+    (if xref
+       (progn
+         (insert "Xref: " xref "\t")
+         (when id
+           (insert "X-Nnshimbun-Id: " id "\t")))
+      (when id
+       (insert "\tX-Nnshimbun-Id: " id "\t")))
+    ;; Replace newlines with spaces in the current NOV line.
+    (while (progn
+            (forward-line 0)
+            (> (point) start))
+      (backward-delete-char 1)
+      (insert " "))
+    (forward-line 1)))
+
+(defun nnshimbun-generate-nov-database (group)
+  (when (nnshimbun-possibly-change-group group)
+    (with-current-buffer (nnshimbun-open-nov group)
+      (goto-char (point-max))
+      (forward-line -1)
+      (let* ((i (or (ignore-errors (read (current-buffer))) 0))
+            (name (concat "nnshimbun+" (nnshimbun-current-server) ":" group))
+            (pre-fetch (nnshimbun-find-parameter name 'prefetch-articles t)))
+       (dolist (header
+                (shimbun-headers nnshimbun-shimbun
+                                 (nnshimbun-find-parameter name
+                                                           'index-range t)))
+         (unless (nnshimbun-search-id group (shimbun-header-id header))
+           (goto-char (point-max))
+           (nnshimbun-insert-nov (setq i (1+ i)) header)
+           (when pre-fetch
+             (with-temp-buffer
+               (nnshimbun-request-article-1 i group nil (current-buffer)))))))
+      (nnshimbun-write-nov group))))
+
+(defun nnshimbun-replace-nov-entry (group article header &optional id)
+  (with-current-buffer (nnshimbun-open-nov group)
+    (when (nnheader-find-nov-line article)
+      (delete-region (point) (progn (forward-line 1) (point)))
+      (nnshimbun-insert-nov article header id))))
+
+(defun nnshimbun-search-id (group id)
+  (with-current-buffer (nnshimbun-open-nov group)
+    (goto-char (point-min))
+    (let (found)
+      (while (and (not found)
+                 (search-forward id nil t)) ; We find the ID.
+       ;; And the id is in the fourth field.
+       (if (not (and (search-backward "\t" nil t 4)
+                     (not (search-backward "\t" (gnus-point-at-bol) t))))
+           (forward-line 1)
+         (forward-line 0)
+         (setq found t)))
+      (unless found
+       (goto-char (point-min))
+       (setq id (concat "X-Nnshimbun-Id: " id))
+       (while (and (not found)
+                   (search-forward id nil t))
+         (if (not (search-backward "\t" (gnus-point-at-bol) t 8))
+             (forward-line 1)
+           (forward-line 0)
+           (setq found t))))
+      (when found
+       (ignore-errors (read (current-buffer)))))))
+
+;; This function is defined as an alternative of `nnheader-parse-nov',
+;; in order to keep compatibility between T-gnus and Oort Gnus.
+(defun nnshimbun-parse-nov ()
+  (let ((eol (gnus-point-at-eol)))
+    (let ((number  (nnheader-nov-read-integer))
+         (subject (nnheader-nov-field))
+         (from    (nnheader-nov-field))
+         (date    (nnheader-nov-field))
+         (id      (nnheader-nov-read-message-id))
+         (refs    (nnheader-nov-field))
+         (chars   (nnheader-nov-read-integer))
+         (lines   (nnheader-nov-read-integer))
+         (xref    (unless (eq (char-after) ?\n)
+                    (when (looking-at "Xref: ")
+                      (goto-char (match-end 0)))
+                    (nnheader-nov-field)))
+         (extra   (nnheader-nov-parse-extra)))
+      (shimbun-make-header number subject from date
+                          (or (cdr (assq 'X-Nnshimbun-Id extra)) id)
+                          refs chars lines xref))))
+
+(defsubst nnshimbun-nov-buffer-name (&optional group)
+  (format " *nnshimbun overview %s %s*"
+         (nnshimbun-current-server)
+         (or group (nnshimbun-current-group))))
+
+(defsubst nnshimbun-nov-file-name (&optional group)
+  (nnmail-group-pathname (or group (nnshimbun-current-group))
+                        (nnshimbun-server-directory)
+                        nnshimbun-nov-file-name))
+
+(defun nnshimbun-open-nov (group)
+  (let ((buffer (nnshimbun-nov-buffer-name group)))
+    (unless (gnus-buffer-live-p buffer)
+      (with-current-buffer (gnus-get-buffer-create buffer)
+       (erase-buffer)
+       (let ((file-name-coding-system nnmail-pathname-coding-system)
+             (pathname-coding-system nnmail-pathname-coding-system)
+             (nov (nnshimbun-nov-file-name group)))
+         (when (file-exists-p nov)
+           (nnheader-insert-file-contents nov)))
+       (set-buffer-modified-p nil)))
+    buffer))
+
+(defun nnshimbun-write-nov (group &optional close)
+  (let ((buffer (nnshimbun-nov-buffer-name group)))
+    (when (gnus-buffer-live-p buffer)
+      (with-current-buffer buffer
+       (let ((file-name-coding-system nnmail-pathname-coding-system)
+             (pathname-coding-system nnmail-pathname-coding-system)
+             (nov (nnshimbun-nov-file-name group)))
+         (when (and (buffer-modified-p)
+                    (or (> (buffer-size) 0)
+                        (file-exists-p nov)))
+           (nnmail-write-region 1 (point-max) nov nil 'nomesg)
+           (set-buffer-modified-p nil))))
+      (when close
+       (kill-buffer buffer)))))
+
+(deffoo nnshimbun-request-expire-articles (articles group
+                                                   &optional server force)
+  "Do expiration for the specified ARTICLES in the nnshimbun GROUP.
+Notice that nnshimbun does not actually delete any articles, it just
+delete the corresponding entries in the NOV database locally.  The
+optional fourth argument FORCE is ignored."
+  (when (nnshimbun-possibly-change-group group server)
+    (let* ((expirable (copy-sequence articles))
+          (name (concat "nnshimbun+" (nnshimbun-current-server) ":" group))
+          ;; If the group's parameter `expiry-wait' is non-nil, the
+          ;; value of the option `nnmail-expiry-wait' will be bound
+          ;; to that value, and the value of the option
+          ;; `nnmail-expiry-wait-function' will be bound to nil.  See
+          ;; the source code of `gnus-summary-expire-articles' how
+          ;; does it work.  If the group's parameter is not specified
+          ;; by user, the shimbun's default value will be used.
+          (expiry-wait
+           (or (nnshimbun-find-parameter name 'expiry-wait t)
+               (shimbun-article-expiration-days nnshimbun-shimbun)))
+          (nnmail-expiry-wait (or expiry-wait nnmail-expiry-wait))
+          (nnmail-expiry-wait-function (if expiry-wait
+                                           nil
+                                         nnmail-expiry-wait-function))
+          article end time)
+      (with-current-buffer (nnshimbun-open-nov group)
+       (while expirable
+         (setq article (pop expirable))
+         (when (and (nnheader-find-nov-line article)
+                    (setq end (gnus-point-at-eol))
+                    (not (= (point-max) (1+ end))))
+           (setq time (and (search-forward "\t" end t)
+                           (search-forward "\t" end t)
+                           (search-forward "\t" end t)
+                           (parse-time-string
+                            (buffer-substring
+                             (point)
+                             (if (search-forward "\t" end t)
+                                 (1- (point))
+                               end)))))
+           (when (if (setq time (condition-case nil
+                                    (apply 'encode-time time)
+                                  (error nil)))
+                     (nnmail-expired-article-p name time nil)
+                   ;; Inhibit expiration if there's no parsable date
+                   ;; and the following option is non-nil.
+                   (not nnshimbun-keep-unparsable-dated-articles))
+             (forward-line 0)
+             (delete-region (point) (1+ end))
+             (setq articles (delq article articles)))))
+       (nnshimbun-write-nov group))
+      articles)))
+
+
+;;; shimbun-gnus-mua
+(luna-define-class shimbun-gnus-mua (shimbun-mua) ())
+
+(luna-define-method shimbun-mua-search-id ((mua shimbun-gnus-mua) id)
+  (nnshimbun-search-id
+   (shimbun-current-group-internal (shimbun-mua-shimbun-internal mua))
+   id))
+
+
+;;; Command to create nnshimbun group
+(defvar nnshimbun-server-history nil)
+
+;;;###autoload
+(defun gnus-group-make-shimbun-group ()
+  "Create a nnshimbun group."
+  (interactive)
+  (let* ((minibuffer-setup-hook
+         (append minibuffer-setup-hook '(beginning-of-line)))
+        (alist
+         (apply 'nconc
+                (mapcar
+                 (lambda (d)
+                   (and (stringp d)
+                        (file-directory-p d)
+                        (delq nil
+                              (mapcar
+                               (lambda (f)
+                                 (and (string-match "^sb-\\(.*\\)\\.el$" f)
+                                      (list (match-string 1 f))))
+                               (directory-files d)))))
+                 load-path)))
+        (server (completing-read
+                 "Shimbun address: "
+                 alist nil t
+                 (or (car nnshimbun-server-history)
+                     (caar alist))
+                 'nnshimbun-server-history))
+        (groups)
+        (nnshimbun-pre-fetch-article))
+    (if (setq groups (shimbun-groups (shimbun-open server)))
+       (gnus-group-make-group
+        (completing-read "Group name: " (mapcar 'list groups) nil t nil)
+        (list 'nnshimbun server))
+      (error "%s" "Can't find group"))))
+
+
+(provide 'nnshimbun)
+
+;;; nnshimbun.el ends here
diff --git a/lisp/nnslashdot.el b/lisp/nnslashdot.el
new file mode 100644 (file)
index 0000000..57de225
--- /dev/null
@@ -0,0 +1,518 @@
+;;; nnslashdot.el --- interfacing with Slashdot
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(require 'nnoo)
+(require 'message)
+(require 'gnus-util)
+(require 'gnus)
+(require 'nnmail)
+(require 'mm-util)
+(require 'mm-url)
+
+(nnoo-declare nnslashdot)
+
+(defvoo nnslashdot-directory (nnheader-concat gnus-directory "slashdot/")
+  "Where nnslashdot will save its files.")
+
+(defvoo nnslashdot-active-url "http://slashdot.org/search.pl?section=&min=%d"
+  "Where nnslashdot will fetch the active file from.")
+
+(defvoo nnslashdot-comments-url "http://slashdot.org/comments.pl?sid=%s&threshold=%d&commentsort=%d&mode=flat&startat=%d"
+  "Where nnslashdot will fetch comments from.")
+
+(defvoo nnslashdot-article-url
+    "http://slashdot.org/article.pl?sid=%s&mode=nocomment"
+  "Where nnslashdot will fetch the article from.")
+
+(defvoo nnslashdot-backslash-url "http://slashdot.org/slashdot.xml"
+  "Where nnslashdot will fetch the stories from.")
+
+(defvoo nnslashdot-use-front-page nil
+  "Use the front page in addition to the backslash page.")
+
+(defvoo nnslashdot-threshold -1
+  "The article threshold.")
+
+(defvoo nnslashdot-threaded t
+  "Whether the nnslashdot groups should be threaded or not.")
+
+(defvoo nnslashdot-group-number 0
+  "The number of non-fresh groups to keep updated.")
+
+(defvoo nnslashdot-login-name ""
+  "The login name to use when posting.")
+
+(defvoo nnslashdot-password ""
+  "The password to use when posting.")
+
+;;; Internal variables
+
+(defvar nnslashdot-groups nil)
+(defvar nnslashdot-buffer nil)
+(defvar nnslashdot-headers nil)
+
+;;; Interface functions
+
+(nnoo-define-basics nnslashdot)
+
+(deffoo nnslashdot-retrieve-headers (articles &optional group server fetch-old)
+  (nnslashdot-possibly-change-server group server)
+  (condition-case why
+      (unless gnus-nov-is-evil
+       (nnslashdot-retrieve-headers-1 articles group))
+    (search-failed (nnslashdot-lose why))))
+
+(deffoo nnslashdot-retrieve-headers-1 (articles group)
+  (let* ((last (car (last articles)))
+        (start (if nnslashdot-threaded 1 (pop articles)))
+        (entry (assoc group nnslashdot-groups))
+        (sid (nth 2 entry))
+        (first-comments t)
+        headers article subject score from date lines parent point cid
+        s startats changed)
+    (save-excursion
+      (set-buffer nnslashdot-buffer)
+      (let ((case-fold-search t))
+       (erase-buffer)
+       (when (= start 1)
+         (mm-url-insert (format nnslashdot-article-url sid) t)
+         (goto-char (point-min))
+         (if (eobp)
+             (error "Couldn't open connection to slashdot"))
+         (re-search-forward "Posted by[ \t\r\n]+")
+         (when (looking-at "\\(<a[^>]+>\\)?[ \t\r\n]*\\([^<\r\n]+\\)")
+           (setq from (mm-url-decode-entities-string (match-string 2))))
+         (search-forward "on ")
+         (setq date (nnslashdot-date-to-date
+                     (buffer-substring (point) (1- (search-forward "<")))))
+         (setq lines (/ (- (point)
+                           (progn (forward-line 1) (point)))
+                        60))
+         (push
+          (cons
+           1
+           (make-full-mail-header
+            1 group from date
+            (concat "<" sid "%1@slashdot>")
+            "" 0 lines nil nil))
+          headers)
+         (setq start (if nnslashdot-threaded 2 (pop articles))))
+       (while (and start (<= start last))
+         (setq point (goto-char (point-max)))
+         (mm-url-insert
+          (format nnslashdot-comments-url sid
+                  nnslashdot-threshold 0 (- start 2))
+          t)
+         (when (and nnslashdot-threaded first-comments)
+           (setq first-comments nil)
+           (goto-char (point-max))
+           (while (re-search-backward "startat=\\([0-9]+\\)" nil t)
+             (setq s (string-to-number (match-string 1)))
+             (unless (memq s startats)
+               (push s startats)))
+           (setq startats (sort startats '<)))
+         (setq article (if (and article (< start article)) article start))
+         (goto-char point)
+         (while (re-search-forward
+                 "<a name=\"\\([0-9]+\\)\"><\\(b\\|H4\\)>\\([^<]+\\)</\\(b\\|H4\\)>.*score:\\([^)]+\\))"
+                 nil t)
+           (setq cid (match-string 1)
+                 subject (match-string 3)
+                 score (match-string 5))
+           (unless (assq article (nth 4 entry))
+             (setcar (nthcdr 4 entry) (cons (cons article cid) (nth 4 entry)))
+             (setq changed t))
+           (when (string-match "^Re: *" subject)
+             (setq subject (concat "Re: " (substring subject (match-end 0)))))
+           (setq subject (mm-url-decode-entities-string subject))
+           (search-forward "<BR>")
+           (cond 
+            ((looking-at
+              "by[ \t\n]+<a[^>]+>\\([^<]+\\)</a>[ \t\n]*(\\(<[^>]+>\\)*\\([^<>)]+\\))")
+             (goto-char (- (match-end 0) 5))
+             (setq from (concat
+                         (mm-url-decode-entities-string (match-string 1))
+                         " <" (match-string 3) ">")))
+            ((looking-at "by[ \t\n]+<a[^>]+>\\([^<(]+\\) (\\([0-9]+\\))</a>")
+             (goto-char (- (match-end 0) 5))
+             (setq from (concat 
+                         (mm-url-decode-entities-string (match-string 1))
+                         " <" (match-string 2) ">")))
+            ((looking-at "by \\([^<>]*\\)[\t\n\r ]+on ")
+             (goto-char (- (match-end 0) 5))
+             (setq from (mm-url-decode-entities-string (match-string 1))))
+            (t
+             (setq from "")))
+           (search-forward "on ")
+           (setq date
+                 (nnslashdot-date-to-date
+                  (buffer-substring (point) (progn (skip-chars-forward "^()<>\n\r") (point)))))
+           (setq lines (/ (abs (- (search-forward "<td")
+                                  (search-forward "</td>")))
+                          70))
+           (if (not
+                (re-search-forward ".*cid=\\([0-9]+\\)\">Parent</A>" nil t))
+               (setq parent nil)
+             (setq parent (match-string 1))
+             (when (string= parent "0")
+               (setq parent nil)))
+           (push
+            (cons
+             article
+             (make-full-mail-header
+              article
+              (concat subject " (" score ")")
+              from date
+              (concat "<" sid "%" cid "@slashdot>")
+              (if parent
+                  (concat "<" sid "%" parent "@slashdot>")
+                "")
+              0 lines nil nil))
+            headers)
+           (while (and articles (<= (car articles) article))
+             (pop articles))
+           (setq article (1+ article)))
+         (if nnslashdot-threaded
+             (progn
+               (setq start (pop startats))
+               (if start (setq start (+ start 2))))
+           (setq start (pop articles))))))
+    (if changed (nnslashdot-write-groups))
+    (setq nnslashdot-headers (sort headers 'car-less-than-car))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (mm-with-unibyte-current-buffer
+       (dolist (header nnslashdot-headers)
+         (nnheader-insert-nov (cdr header)))))
+    'nov))
+
+(deffoo nnslashdot-request-group (group &optional server dont-check)
+  (nnslashdot-possibly-change-server nil server)
+  (let ((elem (assoc group nnslashdot-groups)))
+    (cond
+     ((not elem)
+      (nnheader-report 'nnslashdot "Group does not exist"))
+     (t
+      (nnheader-report 'nnslashdot "Opened group %s" group)
+      (nnheader-insert
+       "211 %d %d %d %s\n" (cadr elem) 1 (cadr elem)
+       (prin1-to-string group))))))
+
+(deffoo nnslashdot-close-group (group &optional server)
+  (nnslashdot-possibly-change-server group server)
+  (when (gnus-buffer-live-p nnslashdot-buffer)
+    (save-excursion
+      (set-buffer nnslashdot-buffer)
+      (kill-buffer nnslashdot-buffer)))
+  t)
+
+(deffoo nnslashdot-request-article (article &optional group server buffer)
+  (nnslashdot-possibly-change-server group server)
+  (let (contents cid)
+    (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 cid (match-string 1 article))
+             (let ((map (nth 4 (assoc group nnslashdot-groups))))
+               (while map
+                 (if (equal (cdar map) cid)
+                     (setq article (caar map)
+                           map nil)
+                   (setq map (cdr map))))))
+           (when (numberp article)
+             (if (= article 1)
+                 (progn
+                   (re-search-forward
+                    "Posted by")
+                   (search-forward "<BR>")
+                   (setq contents
+                         (buffer-substring
+                          (point)
+                          (progn
+                            (re-search-forward
+                             "<IFRAME\\|<SCRIPT LANGUAGE=\"JAVASCRIPT\">\\|<!-- no ad 6 -->\\|&lt;&nbsp;[ \t\r\n]*<A HREF=\"\\(\\(http:\\)?//slashdot\\.org\\)?/article")
+                            (match-beginning 0)))))
+               (setq cid (cdr (assq article
+                                    (nth 4 (assoc group nnslashdot-groups)))))
+               (search-forward (format "<a name=\"%s\">" cid))
+               (setq contents
+                     (buffer-substring
+                      (re-search-forward "<td[^>]*>")
+                      (search-forward "</td>")))))))
+      (search-failed (nnslashdot-lose why)))
+
+    (when contents
+      (save-excursion
+       (set-buffer (or buffer nntp-server-buffer))
+       (erase-buffer)
+       (mm-with-unibyte-current-buffer
+         (insert contents)
+         (goto-char (point-min))
+         (while (re-search-forward "\\(<br>\r?\\)+" nil t)
+           (replace-match "<p>" t t))
+         (goto-char (point-min))
+         (insert "Content-Type: text/html\nMIME-Version: 1.0\n")
+         (insert "Newsgroups: " (caddr (assoc group nnslashdot-groups))
+                 "\n")
+         (let ((header (cdr (assq article nnslashdot-headers))))
+           (nnheader-insert-header header))
+         (nnheader-report 'nnslashdot "Fetched article %s" article))
+       (cons group article)))))
+
+(deffoo nnslashdot-close-server (&optional server)
+  (when (and (nnslashdot-server-opened server)
+            (gnus-buffer-live-p nnslashdot-buffer))
+    (save-excursion
+      (set-buffer nnslashdot-buffer)
+      (kill-buffer nnslashdot-buffer)))
+  (nnoo-close-server 'nnslashdot server))
+
+(deffoo nnslashdot-request-list (&optional server)
+  (nnslashdot-possibly-change-server nil server)
+  (let ((number 0)
+       (first nnslashdot-use-front-page)
+       sid elem description articles gname)
+    (condition-case why
+       ;; First we do the Ultramode to get info on all the latest groups.
+       (progn
+         (mm-with-unibyte-buffer
+           (mm-url-insert nnslashdot-backslash-url t)
+           (goto-char (point-min))
+           (if (eobp)
+               (error "Couldn't open connection to slashdot"))
+           (while (search-forward "<story>" nil t)
+             (narrow-to-region (point) (search-forward "</story>"))
+             (goto-char (point-min))
+             (re-search-forward "<title>\\([^<]+\\)</title>")
+             (setq description
+                   (mm-url-decode-entities-string (match-string 1)))
+             (re-search-forward "<url>\\([^<]+\\)</url>")
+             (setq sid (match-string 1))
+             (string-match "sid=\\([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 (current-time) nil)
+                     nnslashdot-groups))
+             (goto-char (point-max))
+             (widen)))
+         ;; Then do the older groups.
+         (while (or first
+                    (> (- nnslashdot-group-number number) 0))
+           (setq first nil)
+           (mm-with-unibyte-buffer
+             (let ((case-fold-search t))
+               (mm-url-insert (format nnslashdot-active-url number) t)
+               (goto-char (point-min))
+               (while (re-search-forward
+                       "article.pl\\?sid=\\([^&]+\\).*>\\([^<]+\\)</a>"
+                       nil t)
+                 (setq sid (match-string 1)
+                       description
+                       (mm-url-decode-entities-string (match-string 2)))
+                 (forward-line 1)
+                 (when (re-search-forward "with \\([0-9]+\\) comment" nil t)
+                   (setq articles (1+ (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 (current-time) nil)
+                         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)
+  t)
+
+(deffoo nnslashdot-request-post (&optional server)
+  (nnslashdot-possibly-change-server nil server)
+  (let ((sid (message-fetch-field "newsgroups"))
+       (subject (message-fetch-field "subject"))
+       (references (car (last (split-string
+                               (message-fetch-field "references")))))
+       body quoted pid)
+    (string-match "%\\([0-9]+\\)@slashdot" references)
+    (setq pid (match-string 1 references))
+    (message-goto-body)
+    (narrow-to-region (point) (progn (message-goto-signature) (point)))
+    (goto-char (point-min))
+    (while (not (eobp))
+      (if (looking-at "> ")
+         (progn
+           (delete-region (point) (+ (point) 2))
+           (unless quoted
+             (insert "<blockquote>\n"))
+           (setq quoted t))
+       (when quoted
+         (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)
+      (insert "<p>\n")
+      (while (not (eobp))
+       (end-of-line)
+       (insert "<br>")
+       (forward-line 1)))
+    (message-goto-body)
+    (setq body (buffer-substring (point) (point-max)))
+    (erase-buffer)
+    (mm-url-fetch-form
+     "http://slashdot.org/comments.pl"
+     `(("sid" . ,sid)
+       ("pid" . ,pid)
+       ("rlogin" . "userlogin")
+       ("unickname" . ,nnslashdot-login-name)
+       ("upasswd" . ,nnslashdot-password)
+       ("postersubj" . ,subject)
+       ("op" . "Submit")
+       ("postercomment" . ,body)
+       ("posttype" . "html")))))
+
+(deffoo nnslashdot-request-delete-group (group &optional force server)
+  (nnslashdot-possibly-change-server group server)
+  (setq nnslashdot-groups (delq (assoc group nnslashdot-groups)
+                               nnslashdot-groups))
+  (nnslashdot-write-groups))
+
+(deffoo nnslashdot-request-close ()
+  (setq nnslashdot-headers nil
+       nnslashdot-groups nil))
+
+(deffoo nnslashdot-request-expire-articles
+    (articles group &optional server force)
+  (nnslashdot-possibly-change-server group server)
+  (let ((item (assoc group nnslashdot-groups)))
+    (when item
+      (if (fourth item)
+         (when (and (>= (length articles) (cadr item)) ;; All are expirable.
+                    (nnmail-expired-article-p
+                     group
+                     (fourth item)
+                     force))
+           (setq nnslashdot-groups (delq item nnslashdot-groups))
+           (nnslashdot-write-groups)
+           (setq articles nil)) ;; all expired.
+       (setcdr (cddr item) (list (current-time)))
+       (nnslashdot-write-groups))))
+  articles)
+
+(nnoo-define-skeleton nnslashdot)
+
+;;; Internal functions
+
+(defun nnslashdot-possibly-change-server (&optional group server)
+  (nnslashdot-init server)
+  (when (and server
+            (not (nnslashdot-server-opened server)))
+    (nnslashdot-open-server server))
+  (unless nnslashdot-groups
+    (nnslashdot-read-groups)))
+
+(defun nnslashdot-make-tuple (tuple n)
+  (prog1
+      tuple
+    (while (> n 1)
+      (unless (cdr tuple)
+       (setcdr tuple (list nil)))
+      (setq tuple (cdr tuple)
+           n (1- n)))))
+
+(defun nnslashdot-read-groups ()
+  (let ((file (expand-file-name "groups" nnslashdot-directory)))
+    (when (file-exists-p file)
+      (mm-with-unibyte-buffer
+       (insert-file-contents file)
+       (goto-char (point-min))
+       (setq nnslashdot-groups (read (current-buffer))))
+      (if (and nnslashdot-groups (< (length (car nnslashdot-groups)) 5))
+         (let ((groups nnslashdot-groups))
+           (while groups
+             (nnslashdot-make-tuple (car groups) 5)
+             (setq groups (cdr groups))))))))
+
+(defun nnslashdot-write-groups ()
+  (with-temp-file (expand-file-name "groups" nnslashdot-directory)
+    (gnus-prin1 nnslashdot-groups)))
+
+(defun nnslashdot-init (server)
+  "Initialize buffers and such."
+  (unless (file-exists-p nnslashdot-directory)
+    (gnus-make-directory nnslashdot-directory))
+  (unless (gnus-buffer-live-p nnslashdot-buffer)
+    (setq nnslashdot-buffer
+         (save-excursion
+           (nnheader-set-temp-buffer
+            (format " *nnslashdot %s*" server))))
+    (push nnslashdot-buffer gnus-buffers)))
+
+(defun nnslashdot-date-to-date (sdate)
+  (condition-case err
+      (let ((elem (delete "" (split-string sdate))))
+       (concat (substring (nth 0 elem) 0 3) " "
+               (substring (nth 1 elem) 0 3) " "
+               (substring (nth 2 elem) 0 2) " "
+               (substring (nth 3 elem) 1 6) " "
+               (format-time-string "%Y") " "
+               (nth 4 elem)))
+    (error "")))
+
+(defun nnslashdot-generate-active ()
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnslashdot-groups)
+      (when (numberp (cadr elem))
+       (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
index 6eb1a02..d39c999 100644 (file)
@@ -1,8 +1,10 @@
 ;;; nnsoup.el --- SOUP access for Gnus
-;; Copyright (C) 1995,96,97,98 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;     Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nnheader)
 (require 'nnmail)
 (require 'gnus-soup)
 (require 'gnus-msg)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nnsoup)
 
 (defvoo nnsoup-directory "~/SOUP/"
   "*SOUP packet directory.")
 
-(defvoo nnsoup-tmp-directory "/tmp/"
+(defvoo nnsoup-tmp-directory
+    (cond ((fboundp 'temp-directory) (temp-directory))
+         ((boundp 'temporary-file-directory) temporary-file-directory)
+         ("/tmp/"))
   "*Where nnsoup will store temporary files.")
 
-(defvoo nnsoup-replies-directory (concat nnsoup-directory "replies/")
+(defvoo nnsoup-replies-directory (expand-file-name "replies/" nnsoup-directory)
   "*Directory where outgoing packets will be composed.")
 
-(defvoo nnsoup-replies-format-type ?n
+(defvoo nnsoup-replies-format-type ?u  ;; u is USENET news format.
   "*Format of the replies packages.")
 
 (defvoo nnsoup-replies-index-type ?n
   "*Index type of the replies packages.")
 
-(defvoo nnsoup-active-file (concat nnsoup-directory "active")
+(defvoo nnsoup-active-file (expand-file-name "active" nnsoup-directory)
   "Active file.")
 
 (defvoo nnsoup-packer "tar cf - %s | gzip > $HOME/Soupin%d.tgz"
@@ -70,8 +76,8 @@ The SOUP packet file name will be inserted at the %s.")
   "*Regular expression matching SOUP packets in `nnsoup-packet-directory'.")
 
 (defvoo nnsoup-always-save t
-  "If non nil commit the reply buffer on each message send. 
-This is necessary if using message mode outside Gnus with nnsoup as a 
+  "If non nil commit the reply buffer on each message send.
+This is necessary if using message mode outside Gnus with nnsoup as a
 backend for the messages.")
 
 \f
@@ -109,7 +115,7 @@ backend for the messages.")
        ;; articles in SEQUENCE come from.
        (while (and areas sequence)
          ;; Peel off areas that are below sequence.
-         (while (and areas (< (cdaar areas) (car sequence)))
+         (while (and areas (< (cdar (car areas)) (car sequence)))
            (setq areas (cdr areas)))
          (when areas
            ;; This is a useful area.
@@ -125,7 +131,7 @@ backend for the messages.")
              (setq use-nov nil))
            ;; We assign the portion of `sequence' that is relevant to
            ;; this MSG packet to this packet.
-           (while (and sequence (<= (car sequence) (cdaar areas)))
+           (while (and sequence (<= (car sequence) (cdar (car areas))))
              (push (car sequence) this-area-seq)
              (setq sequence (cdr sequence)))
            (setcar useful-areas (cons (nreverse this-area-seq)
@@ -153,7 +159,7 @@ backend for the messages.")
                  (when index-buffer
                    (insert-buffer-substring index-buffer)
                    (goto-char b)
-                   ;; We have to remove the index number entires and
+                   ;; We have to remove the index number entries and
                    ;; insert article numbers instead.
                    (while (looking-at "[0-9]+")
                      (replace-match (int-to-string number) t t)
@@ -244,7 +250,7 @@ backend for the messages.")
   ;; Try to guess the type based on the first article in the group.
   (when (not article)
     (setq article
-         (cdaar (cddr (assoc group nnsoup-group-alist)))))
+         (cdar (car (cddr (assoc group nnsoup-group-alist))))))
   (if (not article)
       'unknown
     (let ((kind (gnus-soup-encoding-kind
@@ -310,7 +316,7 @@ backend for the messages.")
       (setq info (pop infolist)
            range-list (gnus-uncompress-range (car info))
            prefix (gnus-soup-area-prefix (nth 1 info)))
-      (when ;; All the articles in this file are marked for expiry.
+      (when;; All the articles in this file are marked for expiry.
          (and (or (setq mod-time (nth 5 (file-attributes
                                          (nnsoup-file prefix))))
                   (setq mod-time (nth 5 (file-attributes
@@ -332,7 +338,7 @@ backend for the messages.")
                  (delete-file (nnsoup-file prefix t)))
                t)
          (setcdr (cdr total-infolist) (delq info (cddr total-infolist)))
-         (setq articles (gnus-sorted-complement articles range-list))))
+         (setq articles (gnus-sorted-difference articles range-list))))
       (when (not mod-time)
        (setcdr (cdr total-infolist) (delq info (cddr total-infolist)))))
     (if (cddr total-infolist)
@@ -366,7 +372,7 @@ backend for the messages.")
          (setq min (caaar e))
          (while (cdr e)
            (setq e (cdr e)))
-         (setq max (cdaar e))
+         (setq max (cdar (car e)))
          (setcdr entry (cons (cons min max) (cdr entry)))))
       (setq nnsoup-group-alist-touched t))
     nnsoup-group-alist))
@@ -376,7 +382,7 @@ backend for the messages.")
             (or force
                 nnsoup-group-alist-touched))
     (setq nnsoup-group-alist-touched nil)
-    (nnheader-temp-write nnsoup-active-file
+    (with-temp-file nnsoup-active-file
       (gnus-prin1 `(setq nnsoup-group-alist ',nnsoup-group-alist))
       (insert "\n")
       (gnus-prin1 `(setq nnsoup-current-prefix ,nnsoup-current-prefix))
@@ -394,7 +400,7 @@ backend for the messages.")
     prefix))
 
 (defun nnsoup-file-name (dir file)
-  "Return the full path of FILE (in any case) in DIR."
+  "Return the full name of FILE (in any case) in DIR."
   (let* ((case-fold-search t)
         (files (directory-files dir t))
         (regexp (concat (regexp-quote file) "$")))
@@ -417,14 +423,17 @@ backend for the messages.")
          (while (setq area (pop areas))
            ;; Change the name to the permanent name and move the files.
            (setq cur-prefix (nnsoup-next-prefix))
-           (message "Incorporating file %s..." cur-prefix)
+           (nnheader-message 5 "Incorporating file %s..." cur-prefix)
            (when (file-exists-p
-                  (setq file (concat nnsoup-tmp-directory
-                                     (gnus-soup-area-prefix area) ".IDX")))
+                  (setq file
+                        (expand-file-name
+                         (concat (gnus-soup-area-prefix area) ".IDX")
+                         nnsoup-tmp-directory)))
              (rename-file file (nnsoup-file cur-prefix)))
            (when (file-exists-p
-                  (setq file (concat nnsoup-tmp-directory
-                                     (gnus-soup-area-prefix area) ".MSG")))
+                  (setq file (expand-file-name
+                              (concat (gnus-soup-area-prefix area) ".MSG")
+                              nnsoup-tmp-directory)))
              (rename-file file (nnsoup-file cur-prefix t))
              (gnus-soup-set-area-prefix area cur-prefix)
              ;; Find the number of new articles in this area.
@@ -473,7 +482,8 @@ backend for the messages.")
     (goto-char (point-min))
     (cond
      ;; rnews batch format
-     ((= format ?n)
+     ((or (= format ?u)
+         (= format ?n)) ;; Gnus back compatibility.
       (while (looking-at "^#! *rnews \\(+[0-9]+\\) *$")
        (forward-line 1)
        (push (list
@@ -527,17 +537,19 @@ backend for the messages.")
   (let* ((file (concat prefix (if message ".MSG" ".IDX")))
         (buffer-name (concat " *nnsoup " file "*")))
     (or (get-buffer buffer-name)       ; File already loaded.
-       (when (file-exists-p (concat nnsoup-directory file))
+       (when (file-exists-p (expand-file-name file nnsoup-directory))
          (save-excursion               ; Load the file.
            (set-buffer (get-buffer-create buffer-name))
-           (buffer-disable-undo (current-buffer))
+           (buffer-disable-undo)
            (push (cons nnsoup-current-group (current-buffer)) nnsoup-buffers)
-           (nnheader-insert-file-contents (concat nnsoup-directory file))
+           (nnheader-insert-file-contents
+            (expand-file-name file nnsoup-directory))
            (current-buffer))))))
 
 (defun nnsoup-file (prefix &optional message)
   (expand-file-name
-   (concat nnsoup-directory prefix (if message ".MSG" ".IDX"))))
+   (concat prefix (if message ".MSG" ".IDX"))
+   nnsoup-directory))
 
 (defun nnsoup-message-buffer (prefix)
   (nnsoup-index-buffer prefix 'msg))
@@ -548,13 +560,13 @@ backend for the messages.")
                  nnsoup-packet-directory t nnsoup-packet-regexp))
        packet)
     (while (setq packet (pop packets))
-      (message "nnsoup: unpacking %s..." packet)
+      (nnheader-message 5 "nnsoup: unpacking %s..." packet)
       (if (not (gnus-soup-unpack-packet
                nnsoup-tmp-directory nnsoup-unpacker packet))
-         (message "Couldn't unpack %s" packet)
+         (nnheader-message 5 "Couldn't unpack %s" packet)
        (delete-file packet)
        (nnsoup-read-areas)
-       (message "Unpacking...done")))))
+       (nnheader-message 5 "Unpacking...done")))))
 
 (defun nnsoup-narrow-to-article (article &optional area head)
   (let* ((area (or area (nnsoup-article-to-area article nnsoup-current-group)))
@@ -587,7 +599,7 @@ backend for the messages.")
                (let ((format (gnus-soup-encoding-format
                               (gnus-soup-area-encoding (nth 1 area)))))
                  (goto-char end)
-                 (when (or (= format ?n) (= format ?m))
+                 (when (or (= format ?u) (= format ?n) (= format ?m))
                    (setq end (progn (forward-line -1) (point))))))
            (set-buffer msg-buf))
          (widen)
@@ -618,7 +630,7 @@ backend for the messages.")
   "Make an outbound package of SOUP replies."
   (interactive)
   (unless (file-exists-p nnsoup-replies-directory)
-    (message "No such directory: %s" nnsoup-replies-directory))
+    (nnheader-message 5 "No such directory: %s" nnsoup-replies-directory))
   ;; Write all data buffers.
   (gnus-soup-save-areas)
   ;; Write the active file.
@@ -640,25 +652,25 @@ backend for the messages.")
 (defun nnsoup-article-to-area (article group)
   "Return the area that ARTICLE in GROUP is located in."
   (let ((areas (cddr (assoc group nnsoup-group-alist))))
-    (while (and areas (< (cdaar areas) article))
+    (while (and areas (< (cdar (car areas)) article))
       (setq areas (cdr areas)))
     (and areas (car areas))))
 
 (defvar nnsoup-old-functions
-  (list message-send-mail-function message-send-news-function))
+  (list message-send-mail-real-function message-send-news-function))
 
 ;;;###autoload
 (defun nnsoup-set-variables ()
   "Use the SOUP methods for posting news and mailing mail."
   (interactive)
   (setq message-send-news-function 'nnsoup-request-post)
-  (setq message-send-mail-function 'nnsoup-request-mail))
+  (setq message-send-mail-real-function 'nnsoup-request-mail))
 
 ;;;###autoload
 (defun nnsoup-revert-variables ()
   "Revert posting and mailing methods to the standard Emacs methods."
   (interactive)
-  (setq message-send-mail-function (car nnsoup-old-functions))
+  (setq message-send-mail-real-function (car nnsoup-old-functions))
   (setq message-send-news-function (cadr nnsoup-old-functions)))
 
 (defun nnsoup-store-reply (kind)
@@ -666,8 +678,6 @@ backend for the messages.")
   (require 'mail-utils)
   (let ((tembuf (generate-new-buffer " message temp"))
        (case-fold-search nil)
-       (real-header-separator mail-header-separator)
-       (mail-header-separator "")
        delimline
        (mailbuf (current-buffer)))
     (unwind-protect
@@ -693,15 +703,11 @@ backend for the messages.")
            ;; Change header-delimiter to be what sendmail expects.
            (goto-char (point-min))
            (re-search-forward
-            (concat "^" (regexp-quote real-header-separator) "\n"))
+            (concat "^" (regexp-quote mail-header-separator) "\n"))
            (replace-match "\n")
            (backward-char 1)
            (setq delimline (point-marker))
-           ;; Insert an extra newline if we need it to work around
-           ;; Sun's bug that swallows newlines.
            (goto-char (1+ delimline))
-           (when (eval message-mailer-swallows-blank-line)
-             (newline))
            (let ((msg-buf
                   (gnus-soup-store
                    nnsoup-replies-directory
@@ -716,7 +722,7 @@ backend for the messages.")
                    (incf num))
                  (when nnsoup-always-save
                    (save-buffer)))
-               (message "Stored %d messages" num)))
+               (nnheader-message 5 "Stored %d messages" num)))
            (nnsoup-write-replies)
            (kill-buffer tembuf))))))
 
@@ -724,7 +730,7 @@ backend for the messages.")
   (unless nnsoup-replies-list
     (setq nnsoup-replies-list
          (gnus-soup-parse-replies
-          (concat nnsoup-replies-directory "REPLIES"))))
+          (expand-file-name "REPLIES" nnsoup-replies-directory))))
   (let ((replies nnsoup-replies-list))
     (while (and replies
                (not (string= kind (gnus-soup-reply-kind (car replies)))))
@@ -752,9 +758,8 @@ backend for the messages.")
                                 (string-to-int (match-string 1 f2)))))))
        active group lines ident elem min)
     (set-buffer (get-buffer-create " *nnsoup work*"))
-    (buffer-disable-undo (current-buffer))
     (while files
-      (message "Doing %s..." (car files))
+      (nnheader-message 5 "Doing %s..." (car files))
       (erase-buffer)
       (nnheader-insert-file-contents (car files))
       (goto-char (point-min))
@@ -770,16 +775,16 @@ backend for the messages.")
       (if (not (setq elem (assoc group active)))
          (push (list group (cons 1 lines)
                      (list (cons 1 lines)
-                           (vector ident group "ncm" "" lines)))
+                           (vector ident group "ucm" "" lines)))
                active)
        (nconc elem
               (list
                (list (cons (1+ (setq min (cdadr elem)))
                            (+ min lines))
-                     (vector ident group "ncm" "" lines))))
+                     (vector ident group "ucm" "" lines))))
        (setcdr (cadr elem) (+ min lines)))
       (setq files (cdr files)))
-    (message "")
+    (nnheader-message 5 "")
     (setq nnsoup-group-alist active)
     (nnsoup-write-active-file t)))
 
@@ -804,7 +809,8 @@ backend for the messages.")
     ;; Sort and delete the files.
     (setq non-files (sort non-files 'string<))
     (map-y-or-n-p "Delete file %s? "
-                 (lambda (file) (delete-file (concat nnsoup-directory file)))
+                 (lambda (file) (delete-file
+                                 (expand-file-name file nnsoup-directory)))
                  non-files)))
 
 (provide 'nnsoup)
index 50fc4b6..add0e7e 100644 (file)
@@ -1,8 +1,11 @@
 ;;; nnspool.el --- spool access for GNU Emacs
-;; Copyright (C) 1988,89,90,93,94,95,96,97,98 Free Software Foundation, Inc.
+
+;; Copyright (C) 1988, 1989, 1990, 1993, 1994, 1995, 1996, 1997, 1998,
+;;               2000, 2002, 2003
+;;               Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'nnheader)
 (require 'nntp)
-(require 'timezone)
 (require 'nnoo)
-(eval-when-compile (require 'cl))
 
 (nnoo-declare nnspool)
 
@@ -48,7 +52,10 @@ If you are using Cnews, you probably should set this variable to nil.")
 (defvoo nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
   "Local news nov directory.")
 
-(defvoo nnspool-lib-dir "/usr/lib/news/"
+(defvoo nnspool-lib-dir
+    (if (file-exists-p "/usr/lib/news/active")
+       "/usr/lib/news/"
+      "/var/lib/news/")
   "Where the local news library files are stored.")
 
 (defvoo nnspool-active-file (concat nnspool-lib-dir "active")
@@ -67,8 +74,8 @@ If you are using Cnews, you probably should set this variable to nil.")
   "Local news active date file.")
 
 (defvoo nnspool-large-newsgroup 50
-  "The number of the articles which indicates a large newsgroup.
-If the number of the articles is greater than the value, verbose
+  "The number of articles which indicates a large newsgroup.
+If the number of articles is greater than the value, verbose
 messages will be shown to indicate the current status.")
 
 (defvoo nnspool-nov-is-evil nil
@@ -137,18 +144,22 @@ there.")
              (setq beg (point))
              (inline (nnheader-insert-head file))
              (goto-char beg)
-             (search-forward "\n\n" nil t)
-             (forward-char -1)
-             (insert ".\n")
+             (if (search-forward "\n\n" nil t)
+                 (progn (forward-char -1)
+                        (insert ".\n"))
+               (goto-char (point-max))
+               (if (bolp)
+                   (insert ".\n")
+                 (insert "\n.\n")))
              (delete-region (point) (point-max)))
 
            (and do-message
                 (zerop (% (incf count) 20))
-                (message "nnspool: Receiving headers... %d%%"
-                         (/ (* count 100) number))))
+                (nnheader-message 5 "nnspool: Receiving headers... %d%%"
+                                  (/ (* count 100) number))))
 
          (when do-message
-           (message "nnspool: Receiving headers...done"))
+           (nnheader-message 5 "nnspool: Receiving headers...done"))
 
          ;; Fold continuation lines.
          (nnheader-fold-continuation-lines)
@@ -280,7 +291,7 @@ there.")
        (while (and (not (looking-at
                          "\\([^ ]+\\) +\\([0-9]+\\)[0-9][0-9][0-9] "))
                    (zerop (forward-line -1))))
-       (let ((seconds (nnspool-seconds-since-epoch date))
+       (let ((seconds (time-to-seconds (date-to-time date)))
              groups)
          ;; Go through lines and add the latest groups to a list.
          (while (and (looking-at "\\([^ ]+\\) +[0-9]+ ")
@@ -295,8 +306,8 @@ there.")
                             (read (current-buffer)))
                           seconds))
                      (push (buffer-substring
-                                         (match-beginning 1) (match-end 1))
-                                        groups)
+                            (match-beginning 1) (match-end 1))
+                           groups)
                      (zerop (forward-line -1))))
          (erase-buffer)
          (while groups
@@ -321,7 +332,8 @@ there.")
          ()
        (nnheader-report 'nnspool "")
        (set-process-sentinel proc 'nnspool-inews-sentinel)
-       (process-send-region proc (point-min) (point-max))
+       (mm-with-unibyte-current-buffer
+         (process-send-region proc (point-min) (point-max)))
        ;; We slap a condition-case around this, because the process may
        ;; have exited already...
        (ignore-errors
@@ -343,7 +355,7 @@ there.")
       (while (re-search-forward "[ \t\n]+" nil t)
        (replace-match " " t t))
       (nnheader-report 'nnspool "%s" (buffer-string))
-      (message "nnspool: %s" nnspool-status-string)
+      (nnheader-message 5 "nnspool: %s" nnspool-status-string)
       (ding)
       (run-hooks 'nnspool-rejected-article-hook))))
 
@@ -353,7 +365,7 @@ there.")
     (let ((nov (nnheader-group-pathname
                nnspool-current-group nnspool-nov-directory ".overview"))
          (arts articles)
-         (nnheader-file-coding-system nnspool-file-coding-system)
+         (nnheader-file-coding-system nnspool-file-coding-system)
          last)
       (if (not (file-exists-p nov))
          ()
@@ -420,7 +432,6 @@ there.")
 (defun nnspool-find-id (id)
   (save-excursion
     (set-buffer (get-buffer-create " *nnspool work*"))
-    (buffer-disable-undo (current-buffer))
     (erase-buffer)
     (ignore-errors
       (call-process "grep" nil t nil (regexp-quote id) nnspool-history-file))
@@ -450,21 +461,9 @@ there.")
        (nnheader-report 'nnspool "No such newsgroup: %s" group)))))
 
 (defun nnspool-article-pathname (group &optional article)
-  "Find the path for GROUP."
+  "Find the file name for GROUP."
   (nnheader-group-pathname group nnspool-spool-directory article))
 
-(defun nnspool-seconds-since-epoch (date)
-  (let* ((tdate (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-date date)))
-        (ttime (mapcar (lambda (ti) (and ti (string-to-int ti)))
-                       (timezone-parse-time
-                        (aref (timezone-parse-date date) 3))))
-        (unix (encode-time (nth 2 ttime) (nth 1 ttime) (nth 0 ttime)
-                           (nth 2 tdate) (nth 1 tdate) (nth 0 tdate)
-                           (nth 4 tdate))))
-    (+ (* (car unix) 65536.0)
-       (cadr unix))))
-
 (provide 'nnspool)
 
 ;;; nnspool.el ends here
index 560dae1..784d7c0 100644 (file)
@@ -1,63 +1,95 @@
 ;;; nntp.el --- nntp access for Gnus
-;;; Copyright (C) 1987-90,92-97 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1987, 1988, 1989, 1990, 1992, 1993, 1994, 1995, 1996,
+;; 1997, 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;         Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
 
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
 ;;; Commentary:
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
 (require 'nnheader)
 (require 'nnoo)
 (require 'gnus-util)
 
 (nnoo-declare nntp)
 
-(eval-and-compile
-  (unless (fboundp 'open-network-stream)
-    (require 'tcp)))
-
-(eval-when-compile (require 'cl))
-
 (defvoo nntp-address nil
   "Address of the physical nntp server.")
 
 (defvoo nntp-port-number "nntp"
   "Port number on the physical nntp server.")
 
+(defvoo nntp-list-options nil
+  "List of newsgroup name used for a option of the LIST command to
+restrict the listing output to only the specified newsgroups.
+Each newsgroup name can be a shell-style wildcard, for instance,
+\"fj.*\", \"japan.*\", etc.  Fortunately, if the server can accept
+such a option, it will probably make gnus run faster.  You may
+use it as a server variable as follows:
+
+\(setq gnus-select-method
+      '(nntp \"news.somewhere.edu\"
+            (nntp-list-options (\"fj.*\" \"japan.*\"))))")
+
+(defvoo nntp-options-subscribe nil
+  "Regexp matching the newsgroup names which will be subscribed
+unconditionally.  It may be effective as well as `nntp-list-options'
+even though the server could not accept a shell-style wildcard as a
+option of the LIST command.  You may use it as a server variable as
+follows:
+
+\(setq gnus-select-method
+      '(nntp \"news.somewhere.edu\"
+            (nntp-options-subscribe \"^fj\\\\.\\\\|^japan\\\\.\")))")
+
+(defvoo nntp-options-not-subscribe nil
+  "Regexp matching the newsgroup names which will not be subscribed
+unconditionally.  It may be effective as well as `nntp-list-options'
+even though the server could not accept a shell-style wildcard as a
+option of the LIST command.  You may use it as a server variable as
+follows:
+
+\(setq gnus-select-method
+      '(nntp \"news.somewhere.edu\"
+            (nntp-options-not-subscribe \"\\\\.binaries\\\\.\")))")
+
 (defvoo nntp-server-opened-hook '(nntp-send-mode-reader)
   "*Hook used for sending commands to the server at startup.
 The default value is `nntp-send-mode-reader', which makes an innd
-server spawn an nnrpd server.  Another useful function to put in this
-hook might be `nntp-send-authinfo', which will prompt for a password
-to allow posting from the server.  Note that this is only necessary to
-do on servers that use strict access control.")
+server spawn an nnrpd server.")
 
 (defvoo nntp-authinfo-function 'nntp-send-authinfo
-  "Function used to send AUTHINFO to the server.")
+  "Function used to send AUTHINFO to the server.
+It is called with no parameters.")
 
 (defvoo nntp-server-action-alist
-  '(("nntpd 1\\.5\\.11t"
-     (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader))
-    ("NNRP server Netscape"
-     (setq nntp-server-list-active-group nil)))
+    '(("nntpd 1\\.5\\.11t"
+       (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader))
+      ("NNRP server Netscape"
+       (setq nntp-server-list-active-group nil)))
   "Alist of regexps to match on server types and actions to be taken.
 For instance, if you want Gnus to beep every time you connect
 to innd, you could say something like:
@@ -69,60 +101,82 @@ You probably don't want to do that, though.")
 
 (defvoo nntp-open-connection-function 'nntp-open-network-stream
   "*Function used for connecting to a remote system.
-It will be called with the buffer to output in.
+It will be called with the buffer to output in as argument.
 
-Two pre-made functions are `nntp-open-network-stream', which is the
-default, and simply connects to some port or other on the remote
-system (see nntp-port-number).  The other are `nntp-open-rlogin',
-which does an rlogin on the remote system, and then does a telnet to
-the NNTP server available there (see nntp-rlogin-parameters) and
-`nntp-open-telnet' which telnets to a remote system, logs in and does
-the same.")
+Currently, five such functions are provided (please refer to their
+respective doc string for more information), three of them establishing
+direct connections to the nntp server, and two of them using an indirect
+host.
 
-(defvoo nntp-rlogin-program "rsh"
-  "*Program used to log in on remote machines.
-The default is \"rsh\", but \"ssh\" is a popular alternative.")
+Direct connections:
+- `nntp-open-network-stream' (the default),
+- `nntp-open-ssl-stream',
+- `nntp-open-tls-stream',
+- `nntp-open-telnet-stream'.
 
-(defvoo nntp-rlogin-parameters '("telnet" "-8" "${NNTPSERVER:=news}" "nntp")
-  "*Parameters to `nntp-open-login'.
-That function may be used as `nntp-open-connection-function'.  In that
-case, this list will be used as the parameter list given to rsh.")
+Indirect connections:
+- `nntp-open-via-rlogin-and-telnet',
+- `nntp-open-via-telnet-and-telnet'.")
 
-(defvoo nntp-rlogin-user-name nil
-  "*User name on remote system when using the rlogin connect method.")
+(defvoo nntp-pre-command nil
+  "*Pre-command to use with the various nntp-open-via-* methods.
+This is where you would put \"runsocks\" or stuff like that.")
 
-(defvoo nntp-telnet-parameters '("exec" "telnet" "-8" "${NNTPSERVER:=news}" "nntp")
-  "*Parameters to `nntp-open-telnet'.
-That function may be used as `nntp-open-connection-function'.  In that
-case, this list will be executed as a command after logging in
-via telnet.")
+(defvoo nntp-telnet-command "telnet"
+  "*Telnet command used to connect to the nntp server.
+This command is used by the various nntp-open-via-* methods.")
 
-(defvoo nntp-telnet-user-name nil
-  "User name to log in via telnet with.")
+(defvoo nntp-telnet-switches '("-8")
+  "*Switches given to the telnet command `nntp-telnet-command'.")
 
-(defvoo nntp-telnet-passwd nil
-  "Password to use to log in via telnet with.")
+(defvoo nntp-end-of-line "\r\n"
+  "*String to use on the end of lines when talking to the NNTP server.
+This is \"\\r\\n\" by default, but should be \"\\n\" when
+using and indirect connection method (nntp-open-via-*).")
 
-(defvoo nntp-open-telnet-envuser nil
-  "*If non-nil, telnet session (client and server both) will support the ENVIRON option and not prompt for login name.")
+(defvoo nntp-via-rlogin-command "rsh"
+  "*Rlogin command used to connect to an intermediate host.
+This command is used by the `nntp-open-via-rlogin-and-telnet' method.
+The default is \"rsh\", but \"ssh\" is a popular alternative.")
 
-(defvoo nntp-telnet-shell-prompt "bash\\|\$ *\r?$\\|> *\r?"
-  "*Regular expression to match the shell prompt on the remote machine.")
+(defvoo nntp-via-rlogin-command-switches nil
+  "*Switches given to the rlogin command `nntp-via-rlogin-command'.
+If you use \"ssh\" for `nntp-via-rlogin-command', you may set this to
+\(\"-C\") in order to compress all data connections, otherwise set this
+to \(\"-t\" \"-e\" \"none\") or (\"-C\" \"-t\" \"-e\" \"none\") if the telnet
+command requires a pseudo-tty allocation on an intermediate host.")
 
-(defvoo nntp-telnet-command "telnet"
-  "Command used to start telnet.")
+(defvoo nntp-via-telnet-command "telnet"
+  "*Telnet command used to connect to an intermediate host.
+This command is used by the `nntp-open-via-telnet-and-telnet' method.")
 
-(defvoo nntp-telnet-switches '("-8")
-  "Switches given to the telnet command.")
+(defvoo nntp-via-telnet-switches '("-8")
+  "*Switches given to the telnet command `nntp-via-telnet-command'.")
 
-(defvoo nntp-end-of-line "\r\n"
-  "String to use on the end of lines when talking to the NNTP server.
-This is \"\\r\\n\" by default, but should be \"\\n\" when
-using rlogin or telnet to communicate with the server.")
+(defvoo nntp-via-user-name nil
+  "*User name to log in on an intermediate host with.
+This variable is used by the `nntp-open-via-telnet-and-telnet' method.")
+
+(defvoo nntp-via-user-password nil
+  "*Password to use to log in on an intermediate host with.
+This variable is used by the `nntp-open-via-telnet-and-telnet' method.")
+
+(defvoo nntp-via-address nil
+  "*Address of an intermediate host to connect to.
+This variable is used by the `nntp-open-via-rlogin-and-telnet' and
+`nntp-open-via-telnet-and-telnet' methods.")
+
+(defvoo nntp-via-envuser nil
+  "*Whether both telnet client and server support the ENVIRON option.
+If non-nil, there will be no prompt for a login name.")
+
+(defvoo nntp-via-shell-prompt "bash\\|\$ *\r?$\\|> *\r?"
+  "*Regular expression to match the shell prompt on an intermediate host.
+This variable is used by the `nntp-open-via-telnet-and-telnet' method.")
 
 (defvoo nntp-large-newsgroup 50
-  "*The number of the articles which indicates a large newsgroup.
-If the number of the articles is greater than the value, verbose
+  "*The number of articles which indicates a large newsgroup.
+If the number of articles is greater than the value, verbose
 messages will be shown to indicate the current status.")
 
 (defvoo nntp-maximum-request 400
@@ -144,10 +198,6 @@ by one.")
 If the gap between two consecutive articles is bigger than this
 variable, split the XOVER request into two requests.")
 
-(defvoo nntp-connection-timeout nil
-  "*Number of seconds to wait before an nntp connection times out.
-If this variable is nil, which is the default, no timers are set.")
-
 (defvoo nntp-prepare-server-hook nil
   "*Hook run before a server is opened.
 If can be used to set up a server remotely, for instance.  Say you
@@ -160,14 +210,8 @@ server there that you can connect to.  See also
 (defvoo nntp-warn-about-losing-connection t
   "*If non-nil, beep when a server closes connection.")
 
-(defvoo nntp-coding-system-for-read 'binary
-  "*Coding system to read from NNTP.")
-
-(defvoo nntp-coding-system-for-write 'binary
-  "*Coding system to write to NNTP.")
-
-(defcustom nntp-authinforc-file "~/.authinforc"
-  "Docstring."
+(defcustom nntp-authinfo-file "~/.authinfo"
+  ".netrc-like file that holds nntp authinfo passwords."
   :type
   '(choice file
           (repeat :tag "Entries"
@@ -185,8 +229,20 @@ server there that you can connect to.  See also
 
 \f
 
+(defvoo nntp-connection-timeout nil
+  "*Number of seconds to wait before an nntp connection times out.
+If this variable is nil, which is the default, no timers are set.
+NOTE: This variable is never seen to work in Emacs 20 and XEmacs 21.")
+
+(defvoo nntp-prepare-post-hook nil
+  "*Hook run just before posting an article.  It is supposed to be used
+to insert Cancel-Lock headers.")
+
 ;;; Internal variables.
 
+(defvar nntp-record-commands nil
+  "*If non-nil, nntp will record all commands in the \"*nntp-log*\" buffer.")
+
 (defvar nntp-have-messaged nil)
 
 (defvar nntp-process-wait-for nil)
@@ -198,6 +254,7 @@ server there that you can connect to.  See also
 (defvoo nntp-last-command-time nil)
 (defvoo nntp-last-command nil)
 (defvoo nntp-authinfo-password nil)
+(defvoo nntp-authinfo-user nil)
 
 (defvar nntp-connection-list nil)
 
@@ -211,8 +268,22 @@ server there that you can connect to.  See also
 (defvoo nntp-server-xover 'try)
 (defvoo nntp-server-list-active-group 'try)
 
-(eval-and-compile
-  (autoload 'nnmail-read-passwd "nnmail"))
+(defvar nntp-async-needs-kluge
+  (string-match "^GNU Emacs 20\\.3\\." (emacs-version))
+  "*When non-nil, nntp will poll asynchronous connections
+once a second.  By default, this is turned on only for Emacs
+20.3, which has a bug that breaks nntp's normal method of
+noticing asynchronous data.")
+
+(defvar nntp-async-timer nil)
+(defvar nntp-async-process-list nil)
+
+(defvar nntp-ssl-program 
+  "openssl s_client -quiet -ssl3 -connect %s:%p"
+"A string containing commands for SSL connections.
+Within a string, %s is replaced with the server address and %p with
+port number on server.  The program should accept IMAP commands on
+stdin and return responses to stdout.")
 
 \f
 
@@ -220,34 +291,83 @@ server there that you can connect to.  See also
 
 (defsubst nntp-send-string (process string)
   "Send STRING to PROCESS."
+  ;; We need to store the time to provide timeouts, and
+  ;; to store the command so the we can replay the command
+  ;; if the server gives us an AUTHINFO challenge.
   (setq nntp-last-command-time (current-time)
        nntp-last-command string)
-  (process-send-string process (concat string nntp-end-of-line)))
+  (when nntp-record-commands
+    (nntp-record-command string))
+  (process-send-string process (concat string nntp-end-of-line))
+  (or (memq (process-status process) '(open run))
+      (nntp-report "Server closed connection")))
+
+(defun nntp-record-command (string)
+  "Record the command STRING."
+  (save-excursion
+    (set-buffer (get-buffer-create "*nntp-log*"))
+    (goto-char (point-max))
+    (let ((time (current-time)))
+      (insert (format-time-string "%Y%m%dT%H%M%S" time)
+             "." (format "%03d" (/ (nth 2 time) 1000))
+             " " nntp-address " " string "\n"))))
+
+(defun nntp-report (&rest args)
+  "Report an error from the nntp backend.  The first string in ARGS
+can be a format string.  For some commands, the failed command may be
+retried once before actually displaying the error report."
+
+  (when nntp-record-commands
+    (nntp-record-command "*** CALLED nntp-report ***"))
+
+  (nnheader-report 'nntp args)
+
+  (apply 'error args))
+
+(defun nntp-report-1 (&rest args)
+  "Throws out to nntp-with-open-group-error so that the connection may
+be restored and the command retried."
+
+  (when nntp-record-commands
+    (nntp-record-command "*** CONNECTION LOST ***"))
+
+  (throw 'nntp-with-open-group-error t))
 
 (defsubst nntp-wait-for (process wait-for buffer &optional decode discard)
   "Wait for WAIT-FOR to arrive from PROCESS."
   (save-excursion
     (set-buffer (process-buffer process))
     (goto-char (point-min))
-    (while (or (not (memq (char-after (point)) '(?2 ?3 ?4 ?5)))
-              (looking-at "480"))
+    (while (and (or (not (memq (char-after (point)) '(?2 ?3 ?4 ?5)))
+                   (looking-at "480"))
+               (memq (process-status process) '(open run)))
       (when (looking-at "480")
        (nntp-handle-authinfo process))
+      (when (looking-at "^.*\n")
+       (delete-region (point) (progn (forward-line 1) (point))))
       (nntp-accept-process-output process)
       (goto-char (point-min)))
     (prog1
-       (if (looking-at "[45]")
-           (progn
-             (nntp-snarf-error-message)
-             nil)
+       (cond
+        ((looking-at "[45]")
+         (progn
+           (nntp-snarf-error-message)
+           nil))
+        ((not (memq (process-status process) '(open run)))
+         (nntp-report "Server closed connection"))
+        (t
          (goto-char (point-max))
-         (let ((limit (point-min)))
+         (let ((limit (point-min))
+               response)
            (while (not (re-search-backward wait-for limit t))
              (nntp-accept-process-output process)
              ;; We assume that whatever we wait for is less than 1000
              ;; characters long.
              (setq limit (max (- (point-max) 1000) (point-min)))
-             (goto-char (point-max))))
+             (goto-char (point-max)))
+           (setq response (match-string 0))
+           (with-current-buffer nntp-server-buffer
+             (setq nntp-process-response response)))
          (nntp-decode-text (not decode))
          (unless discard
            (save-excursion
@@ -257,25 +377,29 @@ server there that you can connect to.  See also
              ;; Nix out "nntp reading...." message.
              (when nntp-have-messaged
                (setq nntp-have-messaged nil)
-               (message ""))
-             t)))
+               (nnheader-message 5 ""))))
+         t))
       (unless discard
        (erase-buffer)))))
 
+(defun nntp-kill-buffer (buffer)
+  (when (buffer-name buffer)
+    (kill-buffer buffer)
+    (nnheader-init-server-buffer)))
+
 (defsubst nntp-find-connection (buffer)
   "Find the connection delivering to BUFFER."
   (let ((alist nntp-connection-alist)
        (buffer (if (stringp buffer) (get-buffer buffer) buffer))
        process entry)
-    (while (setq entry (pop alist))
+    (while (and alist (setq entry (pop alist)))
       (when (eq buffer (cadr entry))
        (setq process (car entry)
              alist nil)))
     (when process
       (if (memq (process-status process) '(open run))
          process
-       (when (buffer-name (process-buffer process))
-         (kill-buffer (process-buffer process)))
+       (nntp-kill-buffer (process-buffer process))
        (setq nntp-connection-alist (delq entry nntp-connection-alist))
        nil))))
 
@@ -294,33 +418,33 @@ server there that you can connect to.  See also
   "Use COMMAND to retrieve data into BUFFER from PORT on ADDRESS."
   (let ((process (or (nntp-find-connection buffer)
                     (nntp-open-connection buffer))))
-    (if (not process)
-       (nnheader-report 'nntp "Couldn't open connection to %s" address)
-      (unless (or nntp-inhibit-erase nnheader-callback-function)
-       (save-excursion
-         (set-buffer (process-buffer process))
-         (erase-buffer)))
-      (when command
-       (nntp-send-string process command))
-      (cond
-       ((eq callback 'ignore)
-       t)
-       ((and callback wait-for)
-       (save-excursion
-         (set-buffer (process-buffer process))
-         (unless nntp-inside-change-function
-           (erase-buffer))
-         (setq nntp-process-decode decode
-               nntp-process-to-buffer buffer
-               nntp-process-wait-for wait-for
-               nntp-process-callback callback
-               nntp-process-start-point (point-max)
-               after-change-functions
-               (list 'nntp-after-change-function-callback)))
-       t)
-       (wait-for
-       (nntp-wait-for process wait-for buffer decode))
-       (t t)))))
+    (if process
+        (progn
+          (unless (or nntp-inhibit-erase nnheader-callback-function)
+            (save-excursion
+              (set-buffer (process-buffer process))
+              (erase-buffer)))
+          (condition-case err
+              (progn
+                (when command
+                  (nntp-send-string process command))
+                (cond
+                 ((eq callback 'ignore)
+                  t)
+                 ((and callback wait-for)
+                  (nntp-async-wait process wait-for buffer decode callback)
+                  t)
+                 (wait-for
+                  (nntp-wait-for process wait-for buffer decode))
+                 (t t)))
+            (error
+             (nnheader-report 'nntp "Couldn't open connection to %s: %s"
+                              address err))
+            (quit
+             (message "Quit retrieving data from nntp")
+             (signal 'quit nil)
+             nil)))
+      (nnheader-report 'nntp "Couldn't open connection to %s" address))))
 
 (defsubst nntp-send-command (wait-for &rest strings)
   "Send STRINGS to server and wait until WAIT-FOR returns."
@@ -329,17 +453,56 @@ server there that you can connect to.  See also
     (save-excursion
       (set-buffer nntp-server-buffer)
       (erase-buffer)))
-  (nntp-retrieve-data
-   (mapconcat 'identity strings " ")
-   nntp-address nntp-port-number nntp-server-buffer
-   wait-for nnheader-callback-function))
+  (let* ((command (mapconcat 'identity strings " "))
+        (process (nntp-find-connection nntp-server-buffer))
+        (buffer (and process (process-buffer process)))
+        (pos (and buffer (with-current-buffer buffer (point)))))
+    (if process
+       (prog1
+           (nntp-retrieve-data command
+                               nntp-address nntp-port-number
+                               nntp-server-buffer
+                               wait-for nnheader-callback-function)
+         ;; If nothing to wait for, still remove possibly echo'ed commands.
+         ;; We don't have echos if nntp-open-connection-function
+         ;; is `nntp-open-network-stream', so we skip this in that case.
+         (unless (or wait-for
+                     (equal nntp-open-connection-function
+                            'nntp-open-network-stream))
+           (nntp-accept-response)
+           (save-excursion
+             (set-buffer buffer)
+             (goto-char pos)
+             (if (looking-at (regexp-quote command))
+                 (delete-region pos (progn (forward-line 1)
+                                           (gnus-point-at-bol)))))))
+      (nnheader-report 'nntp "Couldn't open connection to %s."
+                      nntp-address))))
 
 (defun nntp-send-command-nodelete (wait-for &rest strings)
   "Send STRINGS to server and wait until WAIT-FOR returns."
-  (nntp-retrieve-data
-   (mapconcat 'identity strings " ")
-   nntp-address nntp-port-number nntp-server-buffer
-   wait-for nnheader-callback-function))
+  (let* ((command (mapconcat 'identity strings " "))
+        (process (nntp-find-connection nntp-server-buffer))
+        (buffer (and process (process-buffer process)))
+        (pos (and buffer (with-current-buffer buffer (point)))))
+    (if process
+       (prog1
+           (nntp-retrieve-data command
+                               nntp-address nntp-port-number
+                               nntp-server-buffer
+                               wait-for nnheader-callback-function)
+         ;; If nothing to wait for, still remove possibly echo'ed commands
+         (unless wait-for
+           (nntp-accept-response)
+           (save-excursion
+             (set-buffer buffer)
+             (goto-char pos)
+             (if (looking-at (regexp-quote command))
+                 (delete-region pos (progn (forward-line 1)
+                                           (gnus-point-at-bol))))
+             )))
+      (nnheader-report 'nntp "Couldn't open connection to %s."
+                      nntp-address))))
 
 (defun nntp-send-command-and-decode (wait-for &rest strings)
   "Send STRINGS to server and wait until WAIT-FOR returns."
@@ -348,10 +511,27 @@ server there that you can connect to.  See also
     (save-excursion
       (set-buffer nntp-server-buffer)
       (erase-buffer)))
-  (nntp-retrieve-data
-   (mapconcat 'identity strings " ")
-   nntp-address nntp-port-number nntp-server-buffer
-   wait-for nnheader-callback-function t))
+  (let* ((command (mapconcat 'identity strings " "))
+        (process (nntp-find-connection nntp-server-buffer))
+        (buffer (and process (process-buffer process)))
+        (pos (and buffer (with-current-buffer buffer (point)))))
+    (if process
+       (prog1
+           (nntp-retrieve-data command
+                               nntp-address nntp-port-number
+                               nntp-server-buffer
+                               wait-for nnheader-callback-function t)
+         ;; If nothing to wait for, still remove possibly echo'ed commands
+         (unless wait-for
+           (nntp-accept-response)
+           (save-excursion
+         (set-buffer buffer)
+         (goto-char pos)
+         (if (looking-at (regexp-quote command))
+             (delete-region pos (progn (forward-line 1) (gnus-point-at-bol))))
+         )))
+      (nnheader-report 'nntp "Couldn't open connection to %s."
+                      nntp-address))))
 
 (defun nntp-send-buffer (wait-for)
   "Send the current buffer to server and wait until WAIT-FOR returns."
@@ -361,8 +541,16 @@ server there that you can connect to.  See also
       (set-buffer (nntp-find-connection-buffer nntp-server-buffer))
       (erase-buffer)))
   (nntp-encode-text)
-  (process-send-region (nntp-find-connection nntp-server-buffer)
-                      (point-min) (point-max))
+  (let ((multibyte (and (boundp 'enable-multibyte-characters)
+                       (symbol-value 'enable-multibyte-characters))))
+    (unwind-protect
+       ;; Some encoded unicode text contains character 0x80-0x9f e.g. Euro.
+       (let (default-enable-multibyte-characters mc-flag)
+         ;; `set-buffer-multibyte' will be provided by APEL for all Emacsen.
+         (set-buffer-multibyte nil)
+         (process-send-region (nntp-find-connection nntp-server-buffer)
+                              (point-min) (point-max))))
+    (set-buffer-multibyte multibyte))
   (nntp-retrieve-data
    nil nntp-address nntp-port-number nntp-server-buffer
    wait-for nnheader-callback-function))
@@ -374,210 +562,305 @@ server there that you can connect to.  See also
 (nnoo-define-basics nntp)
 
 (defsubst nntp-next-result-arrived-p ()
-  (let ((point (point)))
-    (cond
-     ((eq (following-char) ?2)
-      (if (re-search-forward "\n\\.\r?\n" nil t)
-         t
-       (goto-char point)
-       nil))
-     ((looking-at "[34]")
-      (forward-line 1)
-      t)
-     (t
-      nil))))
+  (cond
+   ;; A result that starts with a 2xx code is terminated by
+   ;; a line with only a "." on it.
+   ((eq (char-after) ?2)
+    (if (re-search-forward "\n\\.\r?\n" nil t)
+       t
+      nil))
+   ;; A result that starts with a 3xx or 4xx code is terminated
+   ;; by a newline.
+   ((looking-at "[34]")
+    (if (search-forward "\n" nil t)
+       t
+      nil))
+   ;; No result here.
+   (t
+    nil)))
+
+(eval-when-compile
+  (defvar nntp-with-open-group-internal nil)
+  (defvar nntp-report-n nil))
+
+(defmacro nntp-with-open-group (group server &optional connectionless &rest forms)
+  "Protect against servers that don't like clients that keep idle connections opens.
+The problem being that these servers may either close a connection or
+simply ignore any further requests on a connection.  Closed
+connections are not detected until accept-process-output has updated
+the process-status.  Dropped connections are not detected until the
+connection timeouts (which may be several minutes) or
+nntp-connection-timeout has expired.  When these occur
+nntp-with-open-group, opens a new connection then re-issues the NNTP
+command whose response triggered the error."
+  (when (and (listp connectionless)
+            (not (eq connectionless nil)))
+    (setq forms (cons connectionless forms)
+         connectionless nil))
+  `(letf ((nntp-report-n (symbol-function 'nntp-report))
+         ((symbol-function 'nntp-report) (symbol-function 'nntp-report-1))
+         (nntp-with-open-group-internal nil))
+     (while (catch 'nntp-with-open-group-error
+             ;; Open the connection to the server
+             ;; NOTE: Existing connections are NOT tested.
+             (nntp-possibly-change-group ,group ,server ,connectionless)
+
+             (let ((timer
+                    (and nntp-connection-timeout
+                         (nnheader-run-at-time
+                          nntp-connection-timeout nil
+                          '(lambda ()
+                             (let ((process (nntp-find-connection
+                                             nntp-server-buffer))
+                                   (buffer  (and process
+                                                 (process-buffer process))))
+                               ;; When I an able to identify the
+                               ;; connection to the server AND I've
+                               ;; received NO reponse for
+                               ;; nntp-connection-timeout seconds.
+                               (when (and buffer (eq 0 (buffer-size buffer)))
+                                 ;; Close the connection.  Take no
+                                 ;; other action as the accept input
+                                 ;; code will handle the closed
+                                 ;; connection.
+                                 (nntp-kill-buffer buffer))))))))
+               (unwind-protect
+                   (setq nntp-with-open-group-internal
+                          (condition-case nil
+                             (progn ,@forms)
+                           (quit
+                            (nntp-close-server)
+                             (signal 'quit nil))))
+                 (when timer
+                   (nnheader-cancel-timer timer)))
+               nil))
+       (setf (symbol-function 'nntp-report) nntp-report-n))
+     nntp-with-open-group-internal))
 
 (deffoo nntp-retrieve-headers (articles &optional group server fetch-old)
   "Retrieve the headers of ARTICLES."
-  (nntp-possibly-change-group group server)
-  (save-excursion
-    (set-buffer (nntp-find-connection-buffer nntp-server-buffer))
-    (erase-buffer)
-    (if (and (not gnus-nov-is-evil)
-            (not nntp-nov-is-evil)
-            (nntp-retrieve-headers-with-xover articles fetch-old))
-       ;; We successfully retrieved the headers via XOVER.
-        'nov
-      ;; XOVER didn't work, so we do it the hard, slow and inefficient
-      ;; way.
-      (let ((number (length articles))
-           (count 0)
-           (received 0)
-           (last-point (point-min))
-           (buf (nntp-find-connection-buffer nntp-server-buffer))
-           (nntp-inhibit-erase t)
-           article)
-       ;; Send HEAD commands.
-      (while (setq article (pop articles))
-       (nntp-send-command
-        nil
-        "HEAD" (if (numberp article)
-                   (int-to-string article)
-                 ;; `articles' is either a list of article numbers
-                 ;; or a list of article IDs.
-                 article))
-       (incf count)
-       ;; Every 400 requests we have to read the stream in
-       ;; order to avoid deadlocks.
-       (when (or (null articles)       ;All requests have been sent.
-                 (zerop (% count nntp-maximum-request)))
-         (nntp-accept-response)
-         (while (progn
-                  (set-buffer buf)
-                  (goto-char last-point)
-                  ;; Count replies.
-                  (while (nntp-next-result-arrived-p)
-                    (setq last-point (point))
-                    (incf received))
-                  (< received count))
-           ;; If number of headers is greater than 100, give
-           ;;  informative messages.
-           (and (numberp nntp-large-newsgroup)
-                (> number nntp-large-newsgroup)
-                (zerop (% received 20))
-                (nnheader-message 6 "NNTP: Receiving headers... %d%%"
-                                  (/ (* received 100) number)))
-           (nntp-accept-response))))
-       (and (numberp nntp-large-newsgroup)
-            (> number nntp-large-newsgroup)
-            (nnheader-message 6 "NNTP: Receiving headers...done"))
-
-       ;; Now all of replies are received.  Fold continuation lines.
-       (nnheader-fold-continuation-lines)
-       ;; Remove all "\r"'s.
-       (nnheader-strip-cr)
-       (copy-to-buffer nntp-server-buffer (point-min) (point-max))
-       'headers))))
+  (nntp-with-open-group
+   group server
+   (save-excursion
+     (set-buffer (nntp-find-connection-buffer nntp-server-buffer))
+     (erase-buffer)
+     (if (and (not gnus-nov-is-evil)
+              (not nntp-nov-is-evil)
+              (nntp-retrieve-headers-with-xover articles fetch-old))
+         ;; We successfully retrieved the headers via XOVER.
+         'nov
+       ;; XOVER didn't work, so we do it the hard, slow and inefficient
+       ;; way.
+       (let ((number (length articles))
+             (articles articles)
+             (count 0)
+             (received 0)
+             (last-point (point-min))
+             (buf (nntp-find-connection-buffer nntp-server-buffer))
+             (nntp-inhibit-erase t)
+             article)
+         ;; Send HEAD commands.
+         (while (setq article (pop articles))
+           (nntp-send-command
+            nil
+            "HEAD" (if (numberp article)
+                       (int-to-string article)
+                     ;; `articles' is either a list of article numbers
+                     ;; or a list of article IDs.
+                     article))
+           (incf count)
+           ;; Every 400 requests we have to read the stream in
+           ;; order to avoid deadlocks.
+           (when (or (null articles)    ;All requests have been sent.
+                     (zerop (% count nntp-maximum-request)))
+             (nntp-accept-response)
+             (while (progn
+                      (set-buffer buf)
+                      (goto-char last-point)
+                      ;; Count replies.
+                      (while (nntp-next-result-arrived-p)
+                        (setq last-point (point))
+                        (incf received))
+                      (< received count))
+               ;; If number of headers is greater than 100, give
+               ;;  informative messages.
+               (and (numberp nntp-large-newsgroup)
+                    (> number nntp-large-newsgroup)
+                    (zerop (% received 20))
+                    (nnheader-message 6 "NNTP: Receiving headers... %d%%"
+                                      (/ (* received 100) number)))
+               (nntp-accept-response))))
+         (and (numberp nntp-large-newsgroup)
+              (> number nntp-large-newsgroup)
+              (nnheader-message 6 "NNTP: Receiving headers...done"))
+
+         ;; Now all of replies are received.  Fold continuation lines.
+         (nnheader-fold-continuation-lines)
+         ;; Remove all "\r"'s.
+         (nnheader-strip-cr)
+         (copy-to-buffer nntp-server-buffer (point-min) (point-max))
+         'headers)))))
 
 (deffoo nntp-retrieve-groups (groups &optional server)
   "Retrieve group info on GROUPS."
-  (nntp-possibly-change-group nil server)
-  (save-excursion
-    (set-buffer (nntp-find-connection-buffer nntp-server-buffer))
-    ;; The first time this is run, this variable is `try'.  So we
-    ;; try.
-    (when (eq nntp-server-list-active-group 'try)
-      (nntp-try-list-active (car groups)))
-    (erase-buffer)
-    (let ((count 0)
-         (received 0)
-         (last-point (point-min))
-         (nntp-inhibit-erase t)
-         (command (if nntp-server-list-active-group "LIST ACTIVE" "GROUP")))
-      (while groups
-       ;; Send the command to the server.
-       (nntp-send-command nil command (pop groups))
-       (incf count)
-       ;; Every 400 requests we have to read the stream in
-       ;; order to avoid deadlocks.
-       (when (or (null groups)         ;All requests have been sent.
-                 (zerop (% count nntp-maximum-request)))
-         (nntp-accept-response)
-         (while (progn
-                  (goto-char last-point)
-                  ;; Count replies.
-                  (while (re-search-forward "^[0-9]" nil t)
-                    (incf received))
-                  (setq last-point (point))
-                  (< received count))
-           (nntp-accept-response))))
-
-      ;; Wait for the reply from the final command.
-      (goto-char (point-max))
-      (re-search-backward "^[0-9]" nil t)
-      (when (looking-at "^[23]")
-       (while (progn
-                (goto-char (point-max))
-                (if (not nntp-server-list-active-group)
-                    (not (re-search-backward "\r?\n" (- (point) 3) t))
-                  (not (re-search-backward "^\\.\r?\n" (- (point) 4) t))))
-         (nntp-accept-response)))
-
-      ;; Now all replies are received.  We remove CRs.
-      (goto-char (point-min))
-      (while (search-forward "\r" nil t)
-       (replace-match "" t t))
-
-      (if (not nntp-server-list-active-group)
-         (progn
-           (copy-to-buffer nntp-server-buffer (point-min) (point-max))
-           'group)
-       ;; We have read active entries, so we just delete the
-       ;; superfluous gunk.
-       (goto-char (point-min))
-       (while (re-search-forward "^[.2-5]" nil t)
-         (delete-region (match-beginning 0)
-                        (progn (forward-line 1) (point))))
-       (copy-to-buffer nntp-server-buffer (point-min) (point-max))
-       'active))))
+  (nntp-with-open-group
+   nil server
+   (when (nntp-find-connection-buffer nntp-server-buffer)
+     (catch 'done
+       (save-excursion
+         ;; Erase nntp-server-buffer before nntp-inhibit-erase.
+         (set-buffer nntp-server-buffer)
+         (erase-buffer)
+         (set-buffer (nntp-find-connection-buffer nntp-server-buffer))
+         ;; The first time this is run, this variable is `try'.  So we
+         ;; try.
+         (when (eq nntp-server-list-active-group 'try)
+           (nntp-try-list-active (car groups)))
+         (erase-buffer)
+         (let ((count 0)
+               (groups groups)
+               (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
+             ;; Timeout may have killed the buffer.
+             (unless (gnus-buffer-live-p buf)
+               (nnheader-report 'nntp "Connection to %s is closed." server)
+               (throw 'done nil))
+             ;; Send the command to the server.
+             (nntp-send-command nil command (pop groups))
+             (incf count)
+             ;; Every 400 requests we have to read the stream in
+             ;; order to avoid deadlocks.
+             (when (or (null groups)    ;All requests have been sent.
+                       (zerop (% count nntp-maximum-request)))
+               (nntp-accept-response)
+               (while (and (gnus-buffer-live-p buf)
+                           (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)
+                               (incf received))
+                             (setq last-point (point))
+                             (< received count)))
+                 (nntp-accept-response))))
+
+           ;; Wait for the reply from the final command.
+           (unless (gnus-buffer-live-p buf)
+             (nnheader-report 'nntp "Connection to %s is closed." server)
+             (throw 'done nil))
+           (set-buffer buf)
+           (goto-char (point-max))
+           (re-search-backward "^[0-9]" nil t)
+           (when (looking-at "^[23]")
+             (while (and (gnus-buffer-live-p buf)
+                         (progn
+                           (set-buffer buf)
+                           (goto-char (point-max))
+                           (if (not nntp-server-list-active-group)
+                               (not (re-search-backward "\r?\n"
+                                                       (- (point) 3) t))
+                             (not (re-search-backward "^\\.\r?\n"
+                                                      (- (point) 4) t)))))
+               (nntp-accept-response)))
+
+           ;; Now all replies are received.  We remove CRs.
+           (unless (gnus-buffer-live-p buf)
+             (nnheader-report 'nntp "Connection to %s is closed." server)
+             (throw 'done nil))
+           (set-buffer buf)
+           (goto-char (point-min))
+           (while (search-forward "\r" nil t)
+             (replace-match "" t t))
+
+           (if (not nntp-server-list-active-group)
+               (progn
+                 (copy-to-buffer nntp-server-buffer (point-min) (point-max))
+                 'group)
+             ;; We have read active entries, so we just delete the
+             ;; superfluous gunk.
+             (goto-char (point-min))
+             (while (re-search-forward "^[.2-5]" nil t)
+               (delete-region (match-beginning 0)
+                              (progn (forward-line 1) (point))))
+             (copy-to-buffer nntp-server-buffer (point-min) (point-max))
+             'active)))))))
 
 (deffoo nntp-retrieve-articles (articles &optional group server)
-  (nntp-possibly-change-group group server)
-  (save-excursion
-    (let ((number (length articles))
-         (count 0)
-         (received 0)
-         (last-point (point-min))
-         (buf (nntp-find-connection-buffer nntp-server-buffer))
-         (nntp-inhibit-erase t)
-         (map (apply 'vector articles))
-         (point 1)
-         article alist)
-      (set-buffer buf)
-      (erase-buffer)
-      ;; Send ARTICLE command.
-      (while (setq article (pop articles))
-       (nntp-send-command
-        nil
-        "ARTICLE" (if (numberp article)
-                      (int-to-string article)
-                    ;; `articles' is either a list of article numbers
-                    ;; or a list of article IDs.
-                    article))
-       (incf count)
-       ;; Every 400 requests we have to read the stream in
-       ;; order to avoid deadlocks.
-       (when (or (null articles)       ;All requests have been sent.
-                 (zerop (% count nntp-maximum-request)))
-         (nntp-accept-response)
-         (while (progn
-                  (set-buffer buf)
-                  (goto-char last-point)
-                  ;; Count replies.
-                  (while (nntp-next-result-arrived-p)
-                    (aset map received (cons (aref map received) (point)))
-                    (setq last-point (point))
-                    (incf received))
-                  (< received count))
-           ;; If number of headers is greater than 100, give
-           ;;  informative messages.
-           (and (numberp nntp-large-newsgroup)
-                (> number nntp-large-newsgroup)
-                (zerop (% received 20))
-                (nnheader-message 6 "NNTP: Receiving articles... %d%%"
-                                  (/ (* received 100) number)))
-           (nntp-accept-response))))
-      (and (numberp nntp-large-newsgroup)
-          (> number nntp-large-newsgroup)
-          (nnheader-message 6 "NNTP: Receiving articles...done"))
-      
-      ;; Now we have all the responses.  We go through the results,
-      ;; washes it and copies it over to the server buffer.
-      (set-buffer nntp-server-buffer)
-      (erase-buffer)
-      (setq last-point (point-min))
-      (mapcar
-       (lambda (entry)
-        (narrow-to-region
-         (setq point (goto-char (point-max)))
-         (progn
-           (insert-buffer-substring buf last-point (cdr entry))
-           (point-max)))
-        (setq last-point (cdr entry))
-        (nntp-decode-text)
-        (widen)
-        (cons (car entry) point))
-       map))))
+  (nntp-with-open-group
+    group server
+   (save-excursion
+     (let ((number (length articles))
+           (articles articles)
+           (count 0)
+           (received 0)
+           (last-point (point-min))
+           (buf (nntp-find-connection-buffer nntp-server-buffer))
+           (nntp-inhibit-erase t)
+           (map (apply 'vector articles))
+           (point 1)
+           article)
+       (set-buffer buf)
+       (erase-buffer)
+       ;; Send ARTICLE command.
+       (while (setq article (pop articles))
+         (nntp-send-command
+          nil
+          "ARTICLE" (if (numberp article)
+                        (int-to-string article)
+                      ;; `articles' is either a list of article numbers
+                      ;; or a list of article IDs.
+                      article))
+         (incf count)
+         ;; Every 400 requests we have to read the stream in
+         ;; order to avoid deadlocks.
+         (when (or (null articles)     ;All requests have been sent.
+                   (zerop (% count nntp-maximum-request)))
+           (nntp-accept-response)
+           (while (progn
+                    (set-buffer buf)
+                    (goto-char last-point)
+                    ;; Count replies.
+                    (while (nntp-next-result-arrived-p)
+                      (aset map received (cons (aref map received) (point)))
+                      (setq last-point (point))
+                      (incf received))
+                    (< received count))
+             ;; If number of headers is greater than 100, give
+             ;;  informative messages.
+             (and (numberp nntp-large-newsgroup)
+                  (> number nntp-large-newsgroup)
+                  (zerop (% received 20))
+                  (nnheader-message 6 "NNTP: Receiving articles... %d%%"
+                                    (/ (* received 100) number)))
+             (nntp-accept-response))))
+       (and (numberp nntp-large-newsgroup)
+            (> number nntp-large-newsgroup)
+            (nnheader-message 6 "NNTP: Receiving articles...done"))
+
+       ;; Now we have all the responses.  We go through the results,
+       ;; wash it and copy it over to the server buffer.
+       (set-buffer nntp-server-buffer)
+       (erase-buffer)
+       (setq last-point (point-min))
+       (mapcar
+        (lambda (entry)
+          (narrow-to-region
+           (setq point (goto-char (point-max)))
+           (progn
+             (insert-buffer-substring buf last-point (cdr entry))
+             (point-max)))
+          (setq last-point (cdr entry))
+          (nntp-decode-text)
+          (widen)
+          (cons (car entry) point))
+        map)))))
 
 (defun nntp-try-list-active (group)
   (nntp-list-active-group group)
@@ -591,43 +874,54 @@ server there that you can connect to.  See also
           (setq nntp-server-list-active-group t)))))
 
 (deffoo nntp-list-active-group (group &optional server)
-  "Return the active info on GROUP (which can be a regexp."
-  (nntp-possibly-change-group nil server)
-  (nntp-send-command "^.*\r?\n" "LIST ACTIVE" group))
+  "Return the active info on GROUP (which can be a regexp)."
+  (nntp-with-open-group
+   nil server
+   (nntp-send-command "^\\.*\r?\n" "LIST ACTIVE" group)))
+
+(deffoo nntp-request-group-articles (group &optional server)
+  "Return the list of existing articles in GROUP."
+  (nntp-with-open-group
+   nil server
+   (nntp-send-command "^\\.*\r?\n" "LISTGROUP" group)))
 
 (deffoo nntp-request-article (article &optional group server buffer command)
-  (nntp-possibly-change-group group server)
-  (when (nntp-send-command-and-decode
-        "\r?\n\\.\r?\n" "ARTICLE"
-        (if (numberp article) (int-to-string article) article))
-    (if (and buffer
-            (not (equal buffer nntp-server-buffer)))
-       (save-excursion
-         (set-buffer nntp-server-buffer)
-         (copy-to-buffer buffer (point-min) (point-max))
-         (nntp-find-group-and-number))
-      (nntp-find-group-and-number))))
+  (nntp-with-open-group
+    group server
+    (when (nntp-send-command-and-decode
+           "\r?\n\\.\r?\n" "ARTICLE"
+           (if (numberp article) (int-to-string article) article))
+      (if (and buffer
+               (not (equal buffer nntp-server-buffer)))
+          (save-excursion
+            (set-buffer nntp-server-buffer)
+            (copy-to-buffer buffer (point-min) (point-max))
+            (nntp-find-group-and-number group))
+        (nntp-find-group-and-number group)))))
 
 (deffoo nntp-request-head (article &optional group server)
-  (nntp-possibly-change-group group server)
-  (when (nntp-send-command
-        "\r?\n\\.\r?\n" "HEAD"
-        (if (numberp article) (int-to-string article) article))
-    (prog1
-       (nntp-find-group-and-number)
-      (nntp-decode-text))))
+  (nntp-with-open-group
+   group server
+   (when (nntp-send-command
+          "\r?\n\\.\r?\n" "HEAD"
+          (if (numberp article) (int-to-string article) article))
+     (prog1
+         (nntp-find-group-and-number group)
+       (nntp-decode-text)))))
 
 (deffoo nntp-request-body (article &optional group server)
-  (nntp-possibly-change-group group server)
-  (nntp-send-command-and-decode
-   "\r?\n\\.\r?\n" "BODY"
-   (if (numberp article) (int-to-string article) article)))
+  (nntp-with-open-group
+   group server
+   (nntp-send-command-and-decode
+    "\r?\n\\.\r?\n" "BODY"
+    (if (numberp article) (int-to-string article) article))))
 
 (deffoo nntp-request-group (group &optional server dont-check)
-  (nntp-possibly-change-group nil server)
-  (when (nntp-send-command "^21.*\n" "GROUP" group)
-    (let ((entry (nntp-find-connection-entry nntp-server-buffer)))
-      (setcar (cddr entry) group))))
+  (nntp-with-open-group 
+    nil server
+    (when (nntp-send-command "^[245].*\n" "GROUP" group)
+      (let ((entry (nntp-find-connection-entry nntp-server-buffer)))
+        (setcar (cddr entry) group)))))
 
 (deffoo nntp-close-group (group &optional server)
   t)
@@ -655,61 +949,120 @@ server there that you can connect to.  See also
 
 (deffoo nntp-close-server (&optional server)
   (nntp-possibly-change-group nil server t)
-  (let (process)
-    (while (setq process (car (pop nntp-connection-alist)))
+  (let ((process (nntp-find-connection nntp-server-buffer)))
+    (while process
       (when (memq (process-status process) '(open run))
-       (set-process-sentinel process nil)
        (ignore-errors
          (nntp-send-string process "QUIT")
          (unless (eq nntp-open-connection-function 'nntp-open-network-stream)
+           ;; Ok, this is evil, but when using telnet and stuff
+           ;; as the connection method, it's important that the
+           ;; QUIT command actually is sent out before we kill
+           ;; the process.
            (sleep-for 1))))
-      (when (buffer-name (process-buffer process))
-       (kill-buffer (process-buffer process))))
+      (nntp-kill-buffer (process-buffer process))
+      (setq process (car (pop nntp-connection-alist))))
     (nnoo-close-server 'nntp)))
 
 (deffoo nntp-request-close ()
   (let (process)
     (while (setq process (pop nntp-connection-list))
       (when (memq (process-status process) '(open run))
-       (set-process-sentinel process nil)
        (ignore-errors
          (nntp-send-string process "QUIT")
          (unless (eq nntp-open-connection-function 'nntp-open-network-stream)
            ;; Ok, this is evil, but when using telnet and stuff
            ;; as the connection method, it's important that the
            ;; QUIT command actually is sent out before we kill
-           ;; the process.  
+           ;; the process.
            (sleep-for 1))))
-      (when (buffer-name (process-buffer process))
-       (kill-buffer (process-buffer process))))))
+      (nntp-kill-buffer (process-buffer process)))))
 
 (deffoo nntp-request-list (&optional server)
-  (nntp-possibly-change-group nil server)
-  (nntp-send-command-and-decode "\r?\n\\.\r?\n" "LIST"))
+  "List active groups.  If `nntp-list-options' is non-nil, the listing
+output from the server will be restricted to the specified newsgroups.
+If `nntp-options-subscribe' is non-nil, remove newsgroups that do not
+match the regexp.  If `nntp-options-not-subscribe' is non-nil, remove
+newsgroups that match the regexp."
+  (nntp-with-open-group
+   nil server
+   (with-current-buffer nntp-server-buffer
+     (prog1
+        (if (not nntp-list-options)
+            (nntp-send-command-and-decode "\r?\n\\.\r?\n" "LIST")
+          (let ((options (if (consp nntp-list-options)
+                             nntp-list-options
+                           (list nntp-list-options)))
+                (ret t))
+            (erase-buffer)
+            (while options
+              (goto-char (point-max))
+              (narrow-to-region (point) (point))
+              (setq ret (and ret
+                             (nntp-send-command-nodelete
+                              "\r?\n\\.\r?\n"
+                              (format "LIST ACTIVE %s" (car options))))
+                    options (cdr options))
+              (nntp-decode-text))
+            (widen)
+            ret))
+       (when (and (stringp nntp-options-subscribe)
+                 (not (string-equal "" nntp-options-subscribe)))
+        (goto-char (point-min))
+        (keep-lines nntp-options-subscribe))
+       (when (and (stringp nntp-options-not-subscribe)
+                 (not (string-equal "" nntp-options-not-subscribe)))
+        (goto-char (point-min))
+        (flush-lines nntp-options-subscribe))))))
 
 (deffoo nntp-request-list-newsgroups (&optional server)
-  (nntp-possibly-change-group nil server)
-  (nntp-send-command "\r?\n\\.\r?\n" "LIST NEWSGROUPS"))
+  (nntp-with-open-group
+   nil server
+   (nntp-send-command "\r?\n\\.\r?\n" "LIST NEWSGROUPS")))
 
 (deffoo nntp-request-newgroups (date &optional server)
-  (nntp-possibly-change-group nil server)
-  (save-excursion
-    (set-buffer nntp-server-buffer)
-    (let* ((date (timezone-parse-date date))
-          (time-string
-           (format "%s%02d%02d %s%s%s"
-                   (substring (aref date 0) 2) (string-to-int (aref date 1))
-                   (string-to-int (aref date 2)) (substring (aref date 3) 0 2)
-                   (substring
-                    (aref date 3) 3 5) (substring (aref date 3) 6 8))))
-      (prog1
-         (nntp-send-command "^\\.\r?\n" "NEWGROUPS" time-string)
-       (nntp-decode-text)))))
+  (nntp-with-open-group
+   nil server
+   (save-excursion
+     (set-buffer nntp-server-buffer)
+     (let* ((time (date-to-time date))
+           (ls (- (cadr time) (nth 8 (decode-time time)))))
+       (cond ((< ls 0)
+             (setcar time (1- (car time)))
+             (setcar (cdr time) (+ ls 65536)))
+            ((>= ls 65536)
+             (setcar time (1+ (car time)))
+             (setcar (cdr time) (- ls 65536)))
+            (t
+             (setcar (cdr time) ls)))
+       (prog1
+          (nntp-send-command
+           "^\\.\r?\n" "NEWGROUPS"
+           (format-time-string "%y%m%d %H%M%S" time)
+           "GMT")
+        (nntp-decode-text))))))
 
 (deffoo nntp-request-post (&optional server)
-  (nntp-possibly-change-group nil server)
-  (when (nntp-send-command "^[23].*\r?\n" "POST")
-    (nntp-send-buffer "^[23].*\n")))
+  (nntp-with-open-group
+   nil server
+   (when (nntp-send-command "^[23].*\r?\n" "POST")
+     (let ((response (with-current-buffer nntp-server-buffer
+                      nntp-process-response))
+          server-id)
+       (when (and response
+                 (string-match "^[23].*\\(<[^\t\n @<>]+@[^\t\n @<>]+>\\)"
+                               response))
+        (setq server-id (match-string 1 response))
+        (narrow-to-region (goto-char (point-min))
+                          (if (search-forward "\n\n" nil t)
+                              (1- (point))
+                            (point-max)))
+        (unless (mail-fetch-field "Message-ID")
+          (goto-char (point-min))
+          (insert "Message-ID: " server-id "\n"))
+        (widen))
+       (run-hooks 'nntp-prepare-post-hook)
+       (nntp-send-buffer "^[23].*\n")))))
 
 (deffoo nntp-request-type (group article)
   'news)
@@ -724,54 +1077,60 @@ server there that you can connect to.  See also
 This function is supposed to be called from `nntp-server-opened-hook'.
 It will make innd servers spawn an nnrpd process to allow actual article
 reading."
-  (nntp-send-command "^.*\r?\n" "MODE READER"))
+  (nntp-send-command "^.*\n" "MODE READER"))
 
-(defun nntp-send-authinfo ()
+(defun nntp-send-authinfo (&optional send-if-force)
   "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will look in the \"~/.authinforc\" file for matching entries.  If
+It will look in the \"~/.authinfo\" file for matching entries.  If
 nothing suitable is found there, it will prompt for a user name
-and a password."
-  (let* ((list (gnus-parse-netrc nntp-authinforc-file))
-        (alist (gnus-netrc-machine list nntp-address))
-        (user (gnus-netrc-get alist "login"))
+and a password.
+
+If SEND-IF-FORCE, only send authinfo to the server if the
+.authinfo file has the FORCE token."
+  (let* ((list (gnus-parse-netrc nntp-authinfo-file))
+        (alist (gnus-netrc-machine list nntp-address "nntp"))
+        (force (gnus-netrc-get alist "force"))
+        (user (or (gnus-netrc-get alist "login") nntp-authinfo-user))
         (passwd (gnus-netrc-get alist "password")))
-    (nntp-send-command
-     "^3.*\r?\n" "AUTHINFO USER"
-     (or user (read-string (format "NNTP (%s) user name: " nntp-address))))
-    (nntp-send-command
-     "^2.*\r?\n" "AUTHINFO PASS"
-     (or passwd
-        nntp-authinfo-password
-        (setq nntp-authinfo-password
-              (nnmail-read-passwd (format "NNTP (%s) password: "
-                                          nntp-address)))))))
+    (when (or (not send-if-force)
+             force)
+      (unless user
+       (setq user (read-string (format "NNTP (%s) user name: " nntp-address))
+             nntp-authinfo-user user))
+      (unless (member user '(nil ""))
+       (nntp-send-command "^3.*\r?\n" "AUTHINFO USER" user)
+       (when t                         ;???Should check if AUTHINFO succeeded
+         (nntp-send-command
+          "^2.*\r?\n" "AUTHINFO PASS"
+          (or passwd
+              nntp-authinfo-password
+              (setq nntp-authinfo-password
+                    (read-passwd (format "NNTP (%s@%s) password: "
+                                         user nntp-address))))))))))
 
 (defun nntp-send-nosy-authinfo ()
-  "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
-It will prompt for a password."
-  (nntp-send-command
-   "^3.*\r?\n" "AUTHINFO USER"
-   (read-string (format "NNTP (%s) user name: " nntp-address)))
-  (nntp-send-command
-   "^2.*\r?\n" "AUTHINFO PASS"
-   (nnmail-read-passwd "NNTP (%s) password: " nntp-address)))
+  "Send the AUTHINFO to the nntp server."
+  (let ((user (read-string (format "NNTP (%s) user name: " nntp-address))))
+    (unless (member user '(nil ""))
+      (nntp-send-command "^3.*\r?\n" "AUTHINFO USER" user)
+      (when t                          ;???Should check if AUTHINFO succeeded
+       (nntp-send-command "^2.*\r?\n" "AUTHINFO PASS"
+                          (read-passwd (format "NNTP (%s@%s) password: "
+                                               user nntp-address)))))))
 
 (defun nntp-send-authinfo-from-file ()
   "Send the AUTHINFO to the nntp server.
-This function is supposed to be called from `nntp-server-opened-hook'.
 
 The authinfo login name is taken from the user's login name and the
 password contained in '~/.nntp-authinfo'."
   (when (file-exists-p "~/.nntp-authinfo")
-    (nnheader-temp-write nil
+    (with-temp-buffer
       (insert-file-contents "~/.nntp-authinfo")
       (goto-char (point-min))
       (nntp-send-command "^3.*\r?\n" "AUTHINFO USER" (user-login-name))
       (nntp-send-command
        "^2.*\r?\n" "AUTHINFO PASS"
-       (buffer-substring (point) (progn (end-of-line) (point)))))))
+       (buffer-substring (point) (gnus-point-at-eol))))))
 
 ;;; Internal functions.
 
@@ -793,8 +1152,7 @@ password contained in '~/.nntp-authinfo'."
      (generate-new-buffer
       (format " *server %s %s %s*"
              nntp-address nntp-port-number
-             (buffer-name (get-buffer buffer)))))
-    (buffer-disable-undo (current-buffer))
+             (gnus-buffer-exists-p buffer))))
     (set (make-local-variable 'after-change-functions) nil)
     (set (make-local-variable 'nntp-process-wait-for) nil)
     (set (make-local-variable 'nntp-process-callback) nil)
@@ -807,16 +1165,30 @@ password contained in '~/.nntp-authinfo'."
   "Open a connection to PORT on ADDRESS delivering output to BUFFER."
   (run-hooks 'nntp-prepare-server-hook)
   (let* ((pbuffer (nntp-make-process-buffer buffer))
+        (timer
+         (and nntp-connection-timeout
+              (nnheader-run-at-time
+               nntp-connection-timeout nil
+               `(lambda ()
+                  (nntp-kill-buffer ,pbuffer)))))
         (process
          (condition-case ()
-             (let ((coding-system-for-read nntp-coding-system-for-read))
-               (funcall nntp-open-connection-function pbuffer))
+             (funcall nntp-open-connection-function pbuffer)
            (error nil)
-           (quit nil))))
-    (when process
+           (quit
+            (message "Quit opening connection")
+            (nntp-kill-buffer pbuffer)
+            (signal 'quit nil)
+            nil))))
+    (when timer
+      (nnheader-cancel-timer timer))
+    (unless process
+      (nntp-kill-buffer pbuffer))
+    (when (and (buffer-name pbuffer)
+              process)
       (process-kill-without-query process)
-      (nntp-wait-for process "^.*\n" buffer nil t)
-      (if (memq (process-status process) '(open run))
+      (if (and (nntp-wait-for process "^2.*\n" buffer nil t)
+              (memq (process-status process) '(open run)))
          (prog1
              (caar (push (list process buffer nil) nntp-connection-alist))
            (push process nntp-connection-list)
@@ -826,13 +1198,48 @@ password contained in '~/.nntp-authinfo'."
              (erase-buffer)
              (set-buffer nntp-server-buffer)
              (let ((nnheader-callback-function nil))
-               (run-hooks 'nntp-server-opened-hook))))
-       (when (buffer-name (process-buffer process))
-         (kill-buffer (process-buffer process)))
+               (run-hooks 'nntp-server-opened-hook)
+               (nntp-send-authinfo t))))
+       (nntp-kill-buffer (process-buffer process))
        nil))))
 
 (defun nntp-open-network-stream (buffer)
-  (open-network-stream "nntpd" buffer nntp-address nntp-port-number))
+  (open-network-stream-as-binary
+   "nntpd" buffer nntp-address nntp-port-number))
+
+(autoload 'format-spec "format")
+(autoload 'format-spec-make "format")
+(autoload 'open-tls-stream "tls")
+
+(defun nntp-open-ssl-stream (buffer)
+  (let* ((process-connection-type nil)
+        (proc (as-binary-process
+               (start-process "nntpd" buffer
+                              shell-file-name
+                              shell-command-switch
+                              (format-spec nntp-ssl-program
+                                           (format-spec-make
+                                            ?s nntp-address
+                                            ?p nntp-port-number))))))
+    (process-kill-without-query proc)
+    (save-excursion
+      (set-buffer buffer)
+      (let ((nntp-connection-alist (list proc buffer nil)))
+       (nntp-wait-for-string "^\r*20[01]"))
+      (beginning-of-line)
+      (delete-region (point-min) (point))
+      proc)))
+
+(defun nntp-open-tls-stream (buffer)
+  (let ((proc (open-tls-stream "nntpd" buffer nntp-address nntp-port-number)))
+    (process-kill-without-query proc)
+    (save-excursion
+      (set-buffer buffer)
+      (let ((nntp-connection-alist (list proc buffer nil)))
+       (nntp-wait-for-string "^\r*20[01]"))
+      (beginning-of-line)
+      (delete-region (point-min) (point))
+      proc)))
 
 (defun nntp-read-server-type ()
   "Find out what the name of the server we have connected to is."
@@ -850,40 +1257,100 @@ password contained in '~/.nntp-authinfo'."
            (eval (cadr entry))
          (funcall (cadr entry)))))))
 
-(defun nntp-after-change-function-callback (beg end len)
-  (when nntp-process-callback
-    (save-match-data
-      (if (and (= beg (point-min))
-              (memq (char-after beg) '(?4 ?5)))
-         ;; Report back error messages.
-         (save-excursion
-           (goto-char beg)
-           (if (looking-at "480")
-               (nntp-handle-authinfo nntp-process-to-buffer)
-             (nntp-snarf-error-message)
-             (funcall nntp-process-callback nil)))
-       (goto-char end)
-       (when (and (> (point) nntp-process-start-point)
-                  (re-search-backward nntp-process-wait-for
-                                      nntp-process-start-point t))
-         (when (buffer-name (get-buffer nntp-process-to-buffer))
-           (let ((cur (current-buffer))
-                 (start nntp-process-start-point))
+(defun nntp-async-wait (process wait-for buffer decode callback)
+  (save-excursion
+    (set-buffer (process-buffer process))
+    (unless nntp-inside-change-function
+      (erase-buffer))
+    (setq nntp-process-wait-for wait-for
+         nntp-process-to-buffer buffer
+         nntp-process-decode decode
+         nntp-process-callback callback
+         nntp-process-start-point (point-max))
+    (setq after-change-functions '(nntp-after-change-function))
+    (if nntp-async-needs-kluge
+       (nntp-async-kluge process))))
+
+(defun nntp-async-kluge (process)
+  ;; emacs 20.3 bug: process output with encoding 'binary
+  ;; doesn't trigger after-change-functions.
+  (unless nntp-async-timer
+    (setq nntp-async-timer
+         (nnheader-run-at-time 1 1 'nntp-async-timer-handler)))
+  (add-to-list 'nntp-async-process-list process))
+
+(defun nntp-async-timer-handler ()
+  (mapcar
+   (lambda (proc)
+     (if (memq (process-status proc) '(open run))
+        (nntp-async-trigger proc)
+       (nntp-async-stop proc)))
+   nntp-async-process-list))
+
+(defun nntp-async-stop (proc)
+  (setq nntp-async-process-list (delq proc nntp-async-process-list))
+  (when (and nntp-async-timer (not nntp-async-process-list))
+    (nnheader-cancel-timer nntp-async-timer)
+    (setq nntp-async-timer nil)))
+
+(defun nntp-after-change-function (beg end len)
+  (unwind-protect
+      ;; we only care about insertions at eob
+      (when (and (eq 0 len) (eq (point-max) end))
+       (save-match-data
+         (let ((proc (get-buffer-process (current-buffer))))
+           (when proc
+             (nntp-async-trigger proc)))))
+    ;; any throw from after-change-functions will leave it
+    ;; set to nil.  so we reset it here, if necessary.
+    (when quit-flag
+      (setq after-change-functions '(nntp-after-change-function)))))
+
+(defun nntp-async-trigger (process)
+  (save-excursion
+    (set-buffer (process-buffer process))
+    (when nntp-process-callback
+      ;; do we have an error message?
+      (goto-char nntp-process-start-point)
+      (if (memq (following-char) '(?4 ?5))
+         ;; wants credentials?
+         (if (looking-at "480")
+             (nntp-handle-authinfo process)
+           ;; report error message.
+           (nntp-snarf-error-message)
+           (nntp-do-callback nil))
+
+       ;; got what we expect?
+       (goto-char (point-max))
+       (when (re-search-backward
+              nntp-process-wait-for nntp-process-start-point t)
+         (let ((response (match-string 0)))
+           (with-current-buffer nntp-server-buffer
+             (setq nntp-process-response response)))
+         (nntp-async-stop process)
+         ;; convert it.
+         (when (gnus-buffer-exists-p nntp-process-to-buffer)
+           (let ((buf (current-buffer))
+                 (start nntp-process-start-point)
+                 (decode nntp-process-decode))
              (save-excursion
-               (set-buffer (get-buffer nntp-process-to-buffer))
+               (set-buffer nntp-process-to-buffer)
                (goto-char (point-max))
-               (let ((b (point)))
-                 (insert-buffer-substring cur start)
-                 (narrow-to-region b (point-max))
-                 (nntp-decode-text)
-                 (widen)))))
-         (goto-char end)
-         (let ((callback nntp-process-callback)
-               (nntp-inside-change-function t))
-           (setq nntp-process-callback nil)
-           (save-excursion
-             (funcall callback (buffer-name
-                                (get-buffer nntp-process-to-buffer))))))))))
+               (save-restriction
+                 (narrow-to-region (point) (point))
+                 (insert-buffer-substring buf start)
+                 (when decode
+                   (nntp-decode-text))))))
+         ;; report it.
+         (goto-char (point-max))
+         (nntp-do-callback
+          (buffer-name (get-buffer nntp-process-to-buffer))))))))
+
+(defun nntp-do-callback (arg)
+  (let ((callback nntp-process-callback)
+       (nntp-inside-change-function t))
+    (setq nntp-process-callback nil)
+    (funcall callback arg)))
 
 (defun nntp-snarf-error-message ()
   "Save the error message in the current buffer."
@@ -898,12 +1365,19 @@ password contained in '~/.nntp-authinfo'."
   (save-excursion
     (set-buffer (or (nntp-find-connection-buffer nntp-server-buffer)
                    nntp-server-buffer))
-    (let ((len (/ (point-max) 1024))
+    (let ((len (/ (buffer-size) 1024))
          message-log-max)
       (unless (< len 10)
        (setq nntp-have-messaged t)
        (nnheader-message 7 "nntp read: %dk" len)))
-    (accept-process-output process 1)))
+    (nnheader-accept-process-output process)
+    ;; accept-process-output may update status of process to indicate
+    ;; that the server has closed the connection.  This MUST be
+    ;; handled here as the buffer restored by the save-excursion may
+    ;; be the process's former output buffer (i.e. now killed)
+    (or (and process 
+            (memq (process-status process) '(open run)))
+        (nntp-report "Server closed connection"))))
 
 (defun nntp-accept-response ()
   "Wait for output from the process that outputs to BUFFER."
@@ -921,14 +1395,18 @@ password contained in '~/.nntp-authinfo'."
 
   (when group
     (let ((entry (nntp-find-connection-entry nntp-server-buffer)))
-      (when (not (equal group (caddr entry)))
-       (save-excursion
-         (set-buffer (process-buffer (car entry)))
-         (erase-buffer)
-         (nntp-send-string (car entry) (concat "GROUP " group))
-         (nntp-wait-for-string "^2.*\n")
-         (setcar (cddr entry) group)
-         (erase-buffer))))))
+      (cond ((not entry)
+             (nntp-report "Server closed connection"))
+            ((not (equal group (caddr entry)))
+             (save-excursion
+               (set-buffer (process-buffer (car entry)))
+               (erase-buffer)
+               (nntp-send-command "^[245].*\n" "GROUP" group)
+               (setcar (cddr entry) group)
+               (erase-buffer)
+               (save-excursion
+                 (set-buffer nntp-server-buffer)
+                 (erase-buffer))))))))
 
 (defun nntp-decode-text (&optional cr-only)
   "Decode the text in the current buffer."
@@ -943,7 +1421,9 @@ password contained in '~/.nntp-authinfo'."
       (delete-char 2))
     ;; Delete status line.
     (goto-char (point-min))
-    (delete-region (point) (progn (forward-line 1) (point)))
+    (while (looking-at "[1-5][0-9][0-9] .*\n")
+      ;; For some unknown reason, there is more than one status line.
+      (delete-region (point) (progn (forward-line 1) (point))))
     ;; Remove "." -> ".." encoding.
     (while (search-forward "\n.." nil t)
       (delete-char -1))))
@@ -965,8 +1445,8 @@ password contained in '~/.nntp-authinfo'."
     (goto-char (point-min))
     (while (not (eobp))
       (end-of-line)
-      (insert "\r")
-      (forward-line 1))))
+      (delete-char 1)
+      (insert nntp-end-of-line))))
 
 (defun nntp-retrieve-headers-with-xover (articles &optional fetch-old)
   (set-buffer nntp-server-buffer)
@@ -989,7 +1469,7 @@ password contained in '~/.nntp-authinfo'."
      (car (last articles)) 'wait)
 
     (goto-char (point-min))
-    (when (looking-at "[1-5][0-9][0-9] ")
+    (when (looking-at "[1-5][0-9][0-9] .*\n")
       (delete-region (point) (progn (forward-line 1) (point))))
     (while (search-forward "\r" nil t)
       (replace-match "" t t))
@@ -1006,10 +1486,11 @@ password contained in '~/.nntp-authinfo'."
    ((numberp nntp-nov-gap)
     (let ((count 0)
          (received 0)
-         (last-point (point-min))
+         last-point
+         in-process-buffer-p
          (buf nntp-server-buffer)
-         ;;(process-buffer (nntp-find-connection (current-buffer))))
-         first)
+         (process-buffer (nntp-find-connection-buffer nntp-server-buffer))
+         first last status)
       ;; We have to check `nntp-server-xover'.  If it gets set to nil,
       ;; that means that the server does not understand XOVER, but we
       ;; won't know that until we try.
@@ -1021,40 +1502,77 @@ password contained in '~/.nntp-authinfo'."
                    (< (- (nth 1 articles) (car articles)) nntp-nov-gap))
          (setq articles (cdr articles)))
 
-       (when (nntp-send-xover-command first (car articles))
-         (setq articles (cdr articles)
-               count (1+ count))
+       (setq in-process-buffer-p (stringp nntp-server-xover))
+        (nntp-send-xover-command first (setq last (car articles)))
+        (setq articles (cdr articles))
+
+       (when (and nntp-server-xover in-process-buffer-p)
+         ;; Don't count tried request.
+         (setq count (1+ count))
 
          ;; Every 400 requests we have to read the stream in
          ;; order to avoid deadlocks.
          (when (or (null articles)     ;All requests have been sent.
-                   (zerop (% count nntp-maximum-request)))
-           (accept-process-output)
-           ;; On some Emacs versions the preceding function has
-           ;; a tendency to change the buffer.  Perhaps.  It's
-           ;; quite difficult to reproduce, because it only
-           ;; seems to happen once in a blue moon.
-           (set-buffer buf)
+                   (= 1 (% count nntp-maximum-request)))
+
+           (nntp-accept-response)
+           ;; On some Emacs versions the preceding function has a
+           ;; tendency to change the buffer.  Perhaps.  It's quite
+           ;; difficult to reproduce, because it only seems to happen
+           ;; once in a blue moon.
+           (set-buffer process-buffer)
            (while (progn
-                    (goto-char last-point)
+                    (goto-char (or last-point (point-min)))
                     ;; Count replies.
-                    (while (re-search-forward "^[0-9][0-9][0-9] " nil t)
-                      (setq received (1+ received)))
+                    (while (re-search-forward "^\\([0-9][0-9][0-9]\\) .*\n"
+                                              nil t)
+                      (incf received)
+                      (setq status (match-string 1))
+                      (if (string-match "^[45]" status)
+                          (setq status 'error)
+                        (setq status 'ok)))
                     (setq last-point (point))
-                    (< received count))
-             (accept-process-output)
-             (set-buffer buf)))))
+                    (or (< received count)
+                        (if (eq status 'error)
+                            nil
+                          ;; I haven't started reading the final response
+                          (progn
+                            (goto-char (point-max))
+                            (forward-line -1)
+                            (not (looking-at "^\\.\r?\n"))))))
+             ;; I haven't read the end of the final response
+             (nntp-accept-response)
+             (set-buffer process-buffer))))
+
+        ;; Some nntp servers seem to have an extension to the XOVER
+        ;; extension.  On these servers, requesting an article range
+        ;; preceeding the active range does not return an error as
+        ;; specified in the RFC.  What we instead get is the NOV entry
+        ;; for the first available article.  Obviously, a client can
+        ;; use that entry to avoid making unnecessary requests.  The
+        ;; only problem is for a client that assumes that the response
+        ;; will always be within the requested ranage.  For such a
+        ;; client, we can get N copies of the same entry (one for each
+        ;; XOVER command sent to the server).
+
+        (when (<= count 1)
+          (goto-char (point-min))
+          (when (re-search-forward "^[0-9][0-9][0-9] .*\n\\([0-9]+\\)" nil t)
+            (let ((low-limit (string-to-int
+                             (buffer-substring (match-beginning 1) 
+                                               (match-end 1)))))
+              (while (and articles (<= (car articles) low-limit))
+                (setq articles (cdr articles))))))
+        (set-buffer buf))
 
       (when nntp-server-xover
-       ;; Wait for the reply from the final command.
-       (goto-char (point-max))
-       (re-search-backward "^[0-9][0-9][0-9] " nil t)
-       (when (looking-at "^[23]")
-         (while (progn
-                  (goto-char (point-max))
-                  (forward-line -1)
-                  (not (looking-at "^\\.\r?\n")))
-           (nntp-accept-response)))
+       (when in-process-buffer-p
+         (set-buffer buf)
+         (goto-char (point-max))
+         (insert-buffer-substring process-buffer)
+         (set-buffer process-buffer)
+         (erase-buffer)
+         (set-buffer buf))
 
        ;; We remove any "." lines and status lines.
        (goto-char (point-min))
@@ -1062,7 +1580,6 @@ password contained in '~/.nntp-authinfo'."
          (delete-char -1))
        (goto-char (point-min))
        (delete-matching-lines "^\\.$\\|^[1-5][0-9][0-9] ")
-       ;;(copy-to-buffer nntp-server-buffer (point-min) (point-max))
        t))))
 
   nntp-server-xover)
@@ -1078,7 +1595,7 @@ password contained in '~/.nntp-authinfo'."
            (nntp-send-command-nodelete
             "\r?\n\\.\r?\n" nntp-server-xover range)
          ;; We do not wait for the reply.
-         (nntp-send-command-nodelete "\r?\n\\.\r?\n" nntp-server-xover range))
+         (nntp-send-command-nodelete nil nntp-server-xover range))
       (let ((commands nntp-xover-commands))
        ;; `nntp-xover-commands' is a list of possible XOVER commands.
        ;; We try them all until we get at positive response.
@@ -1102,28 +1619,125 @@ password contained in '~/.nntp-authinfo'."
            (set-buffer nntp-server-buffer)
            (erase-buffer)
            (setq nntp-server-xover nil)))
-       nntp-server-xover))))
+        nntp-server-xover))))
 
-;;; Alternative connection methods.
+(defun nntp-find-group-and-number (&optional group)
+  (save-excursion
+    (save-restriction
+      (set-buffer nntp-server-buffer)
+      (narrow-to-region (goto-char (point-min))
+                       (or (search-forward "\n\n" nil t) (point-max)))
+      (goto-char (point-min))
+      ;; We first find the number by looking at the status line.
+      (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ")
+                        (string-to-int
+                         (buffer-substring (match-beginning 1)
+                                           (match-end 1)))))
+           newsgroups xref)
+       (and number (zerop number) (setq number nil))
+       (if number
+           ;; Then we find the group name.
+           (setq group
+                 (cond
+                  ;; If there is only one group in the Newsgroups
+                  ;; header, then it seems quite likely that this
+                  ;; article comes from that group, I'd say.
+                  ((and (setq newsgroups
+                              (mail-fetch-field "newsgroups"))
+                        (not (string-match "," newsgroups)))
+                   newsgroups)
+                  ;; If there is more than one group in the
+                  ;; Newsgroups header, then the Xref header should
+                  ;; be filled out.  We hazard a guess that the group
+                  ;; that has this article number in the Xref header
+                  ;; is the one we are looking for.  This might very
+                  ;; well be wrong if this article happens to have
+                  ;; the same number in several groups, but that's
+                  ;; life.
+                  ((and (setq xref (mail-fetch-field "xref"))
+                        number
+                        (string-match
+                         (format "\\([^ :]+\\):%d" number) xref))
+                   (match-string 1 xref))
+                  (t "")))
+         (cond
+          ((and (setq xref (mail-fetch-field "xref"))
+                (string-match
+                 (if group
+                     (concat "\\(" (regexp-quote group) "\\):\\([0-9]+\\)")
+                   "\\([^ :]+\\):\\([0-9]+\\)")
+                 xref))
+           (setq group (match-string 1 xref)
+                 number (string-to-int (match-string 2 xref))))
+          ((and (setq newsgroups
+                      (mail-fetch-field "newsgroups"))
+                (not (string-match "," newsgroups)))
+           (setq group newsgroups))
+          (group)
+          (t (setq group ""))))
+       (when (string-match "\r" group)
+         (setq group (substring group 0 (match-beginning 0))))
+       (cons group number)))))
 
 (defun nntp-wait-for-string (regexp)
   "Wait until string arrives in the buffer."
-  (let ((buf (current-buffer)))
+  (let ((buf (current-buffer))
+       proc)
     (goto-char (point-min))
-    (while (not (re-search-forward regexp nil t))
-      (accept-process-output (nntp-find-connection nntp-server-buffer))
+    (while (and (setq proc (get-buffer-process buf))
+               (memq (process-status proc) '(open run))
+               (not (re-search-forward regexp nil t)))
+      (accept-process-output proc)
       (set-buffer buf)
       (goto-char (point-min)))))
 
+
+;; ==========================================================================
+;; Obsolete nntp-open-* connection methods -- drv
+;; ==========================================================================
+
+(defvoo nntp-open-telnet-envuser nil
+  "*If non-nil, telnet session (client and server both) will support the ENVIRON option and not prompt for login name.")
+
+(defvoo nntp-telnet-shell-prompt "bash\\|\$ *\r?$\\|> *\r?"
+  "*Regular expression to match the shell prompt on the remote machine.")
+
+(defvoo nntp-rlogin-program "rsh"
+  "*Program used to log in on remote machines.
+The default is \"rsh\", but \"ssh\" is a popular alternative.")
+
+(defvoo nntp-rlogin-parameters '("telnet" "-8" "${NNTPSERVER:=news}" "nntp")
+  "*Parameters to `nntp-open-rlogin'.
+That function may be used as `nntp-open-connection-function'.  In that
+case, this list will be used as the parameter list given to rsh.")
+
+(defvoo nntp-rlogin-user-name nil
+  "*User name on remote system when using the rlogin connect method.")
+
+(defvoo nntp-telnet-parameters
+    '("exec" "telnet" "-8" "${NNTPSERVER:=news}" "nntp")
+  "*Parameters to `nntp-open-telnet'.
+That function may be used as `nntp-open-connection-function'.  In that
+case, this list will be executed as a command after logging in
+via telnet.")
+
+(defvoo nntp-telnet-user-name nil
+  "User name to log in via telnet with.")
+
+(defvoo nntp-telnet-passwd nil
+  "Password to use to log in via telnet with.")
+
 (defun nntp-open-telnet (buffer)
   (save-excursion
     (set-buffer buffer)
     (erase-buffer)
-    (let ((proc (apply
-                'start-process
-                "nntpd" buffer nntp-telnet-command nntp-telnet-switches))
+    (let ((proc (as-binary-process
+                (apply
+                 'start-process
+                 "nntpd" buffer nntp-telnet-command nntp-telnet-switches)))
          (case-fold-search t))
       (when (memq (process-status proc) '(open run))
+       (nntp-wait-for-string "^r?telnet")
        (process-send-string proc "set escape \^X\n")
        (cond
         ((and nntp-open-telnet-envuser nntp-telnet-user-name)
@@ -1144,9 +1758,8 @@ password contained in '~/.nntp-authinfo'."
         proc (concat
               (or nntp-telnet-passwd
                   (setq nntp-telnet-passwd
-                        (nnmail-read-passwd "Password: ")))
+                        (read-passwd "Password: ")))
               "\n"))
-       (erase-buffer)
        (nntp-wait-for-string nntp-telnet-shell-prompt)
        (process-send-string
         proc (concat (mapconcat 'identity nntp-telnet-parameters " ") "\n"))
@@ -1154,7 +1767,7 @@ password contained in '~/.nntp-authinfo'."
        (beginning-of-line)
        (delete-region (point-min) (point))
        (process-send-string proc "\^]")
-       (nntp-wait-for-string "^telnet")
+       (nntp-wait-for-string "^r?telnet")
        (process-send-string proc "mode character\n")
        (accept-process-output proc 1)
        (sit-for 1)
@@ -1166,57 +1779,174 @@ password contained in '~/.nntp-authinfo'."
 (defun nntp-open-rlogin (buffer)
   "Open a connection to SERVER using rsh."
   (let ((proc (if nntp-rlogin-user-name
-                 (apply 'start-process
-                        "nntpd" buffer nntp-rlogin-program
-                        nntp-address "-l" nntp-rlogin-user-name
-                        nntp-rlogin-parameters)
-               (apply 'start-process
-                      "nntpd" buffer nntp-rlogin-program nntp-address
-                      nntp-rlogin-parameters))))
-    (set-buffer buffer)
-    (nntp-wait-for-string "^\r*20[01]")
-    (beginning-of-line)
-    (delete-region (point-min) (point))
+                 (as-binary-process
+                  (apply 'start-process
+                         "nntpd" buffer nntp-rlogin-program
+                         nntp-address "-l" nntp-rlogin-user-name
+                         nntp-rlogin-parameters))
+               (as-binary-process
+                (apply 'start-process
+                       "nntpd" buffer nntp-rlogin-program nntp-address
+                       nntp-rlogin-parameters)))))
+    (save-excursion
+      (set-buffer buffer)
+      (nntp-wait-for-string "^\r*20[01]")
+      (beginning-of-line)
+      (delete-region (point-min) (point))
+      proc)))
+
+
+;; ==========================================================================
+;; Replacements for the nntp-open-* functions -- drv
+;; ==========================================================================
+
+(defun nntp-open-telnet-stream (buffer)
+  "Open a nntp connection by telnet'ing the news server.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-telnet-command',
+- `nntp-telnet-switches',
+- `nntp-address',
+- `nntp-port-number',
+- `nntp-end-of-line'."
+  (let ((command `(,nntp-telnet-command
+                  ,@nntp-telnet-switches
+                  ,nntp-address ,nntp-port-number))
+       proc)
+    (and nntp-pre-command
+        (push nntp-pre-command command))
+    (setq proc (as-binary-process
+               (apply 'start-process "nntpd" buffer command)))
+    (save-excursion
+      (set-buffer buffer)
+      (nntp-wait-for-string "^\r*20[01]")
+      (beginning-of-line)
+      (delete-region (point-min) (point))
+      proc)))
+
+(defun nntp-open-via-rlogin-and-telnet (buffer)
+  "Open a connection to an nntp server through an intermediate host.
+First rlogin to the remote host, and then telnet the real news server
+from there.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-via-rlogin-command',
+- `nntp-via-rlogin-command-switches',
+- `nntp-via-user-name',
+- `nntp-via-address',
+- `nntp-telnet-command',
+- `nntp-telnet-switches',
+- `nntp-address',
+- `nntp-port-number',
+- `nntp-end-of-line'."
+  (let ((command `(,nntp-via-address
+                  ,nntp-telnet-command
+                  ,@nntp-telnet-switches))
+       proc)
+    (when nntp-via-user-name
+      (setq command `("-l" ,nntp-via-user-name ,@command)))
+    (when nntp-via-rlogin-command-switches
+      (setq command (append nntp-via-rlogin-command-switches command)))
+    (push nntp-via-rlogin-command command)
+    (and nntp-pre-command
+        (push nntp-pre-command command))
+    (setq proc (as-binary-process
+               (apply 'start-process "nntpd" buffer command)))
+    (save-excursion
+      (set-buffer buffer)
+      (nntp-wait-for-string "^r?telnet")
+      (process-send-string proc (concat "open " nntp-address
+                                       " " nntp-port-number "\n"))
+      (nntp-wait-for-string "^\r*20[01]")
+      (beginning-of-line)
+      (delete-region (point-min) (point))
+      (process-send-string proc "\^]")
+      (nntp-wait-for-string "^r?telnet")
+      (process-send-string proc "mode character\n")
+      (accept-process-output proc 1)
+      (sit-for 1)
+      (goto-char (point-min))
+      (forward-line 1)
+      (delete-region (point) (point-max)))
     proc))
 
-(defun nntp-find-group-and-number ()
+(defun nntp-open-via-telnet-and-telnet (buffer)
+  "Open a connection to an nntp server through an intermediate host.
+First telnet the remote host, and then telnet the real news server
+from there.
+
+Please refer to the following variables to customize the connection:
+- `nntp-pre-command',
+- `nntp-via-telnet-command',
+- `nntp-via-telnet-switches',
+- `nntp-via-address',
+- `nntp-via-envuser',
+- `nntp-via-user-name',
+- `nntp-via-user-password',
+- `nntp-via-shell-prompt',
+- `nntp-telnet-command',
+- `nntp-telnet-switches',
+- `nntp-address',
+- `nntp-port-number',
+- `nntp-end-of-line'."
   (save-excursion
-    (save-restriction
-      (set-buffer nntp-server-buffer)
-      (narrow-to-region (goto-char (point-min))
-                       (or (search-forward "\n\n" nil t) (point-max)))
-      (goto-char (point-min))
-      ;; We first find the number by looking at the status line.
-      (let ((number (and (looking-at "2[0-9][0-9] +\\([0-9]+\\) ")
-                        (string-to-int
-                         (buffer-substring (match-beginning 1)
-                                           (match-end 1)))))
-           group newsgroups xref)
-       (and number (zerop number) (setq number nil))
-       ;; Then we find the group name.
-       (setq group
-             (cond
-              ;; If there is only one group in the Newsgroups header,
-              ;; then it seems quite likely that this article comes
-              ;; from that group, I'd say.
-              ((and (setq newsgroups (mail-fetch-field "newsgroups"))
-                    (not (string-match "," newsgroups)))
-               newsgroups)
-              ;; If there is more than one group in the Newsgroups
-              ;; header, then the Xref header should be filled out.
-              ;; We hazard a guess that the group that has this
-              ;; article number in the Xref header is the one we are
-              ;; looking for.  This might very well be wrong if this
-              ;; article happens to have the same number in several
-              ;; groups, but that's life.
-              ((and (setq xref (mail-fetch-field "xref"))
-                    number
-                    (string-match (format "\\([^ :]+\\):%d" number) xref))
-               (substring xref (match-beginning 1) (match-end 1)))
-              (t "")))
-       (when (string-match "\r" group)
-         (setq group (substring group 0 (match-beginning 0))))
-       (cons group number)))))
+    (set-buffer buffer)
+    (erase-buffer)
+    (let ((command `(,nntp-via-telnet-command ,@nntp-via-telnet-switches))
+         (case-fold-search t)
+         proc)
+      (and nntp-pre-command (push nntp-pre-command command))
+      (setq proc (as-binary-process
+                 (apply 'start-process "nntpd" buffer command)))
+      (when (memq (process-status proc) '(open run))
+       (nntp-wait-for-string "^r?telnet")
+       (process-send-string proc "set escape \^X\n")
+       (cond
+        ((and nntp-via-envuser nntp-via-user-name)
+         (process-send-string proc (concat "open " "-l" nntp-via-user-name
+                                           nntp-via-address "\n")))
+        (t
+         (process-send-string proc (concat "open " nntp-via-address
+                                           "\n"))))
+       (when (not nntp-via-envuser)
+         (nntp-wait-for-string "^\r*.?login:")
+         (process-send-string proc
+                              (concat
+                               (or nntp-via-user-name
+                                   (setq nntp-via-user-name
+                                         (read-string "login: ")))
+                               "\n")))
+       (nntp-wait-for-string "^\r*.?password:")
+       (process-send-string proc
+                            (concat
+                             (or nntp-via-user-password
+                                 (setq nntp-via-user-password
+                                       (read-passwd "Password: ")))
+                             "\n"))
+       (nntp-wait-for-string nntp-via-shell-prompt)
+       (let ((real-telnet-command `("exec"
+                                    ,nntp-telnet-command
+                                    ,@nntp-telnet-switches
+                                    ,nntp-address
+                                    ,nntp-port-number)))
+         (process-send-string proc
+                              (concat (mapconcat 'identity
+                                                 real-telnet-command " ")
+                                      "\n")))
+       (nntp-wait-for-string "^\r*20[01]")
+       (beginning-of-line)
+       (delete-region (point-min) (point))
+       (process-send-string proc "\^]")
+       (nntp-wait-for-string "^r?telnet")
+       (process-send-string proc "mode character\n")
+       (accept-process-output proc 1)
+       (sit-for 1)
+       (goto-char (point-min))
+       (forward-line 1)
+       (delete-region (point) (point-max)))
+      proc)))
 
 (provide 'nntp)
 
diff --git a/lisp/nnultimate.el b/lisp/nnultimate.el
new file mode 100644 (file)
index 0000000..9730922
--- /dev/null
@@ -0,0 +1,480 @@
+;;; nnultimate.el --- interfacing with the Ultimate Bulletin Board system
+
+;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Note: You need to have `url' and `w3' installed for this
+;; backend to work.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(require 'nnoo)
+(require 'message)
+(require 'gnus-util)
+(require 'gnus)
+(require 'nnmail)
+(require 'mm-util)
+(require 'mm-url)
+(require 'nnweb)
+(autoload 'w3-parse-buffer "w3-parse")
+
+(nnoo-declare nnultimate)
+
+(defvoo nnultimate-directory (nnheader-concat gnus-directory "ultimate/")
+  "Where nnultimate will save its files.")
+
+(defvoo nnultimate-address ""
+  "The address of the Ultimate bulletin board.")
+
+;;; Internal variables
+
+(defvar nnultimate-groups-alist nil)
+(defvoo nnultimate-groups nil)
+(defvoo nnultimate-headers nil)
+(defvoo nnultimate-articles nil)
+(defvar nnultimate-table-regexp
+  "postings.*editpost\\|forumdisplay\\|Forum[0-9]+/HTML\\|getbio")
+
+;;; Interface functions
+
+(nnoo-define-basics nnultimate)
+
+(deffoo nnultimate-retrieve-headers (articles &optional group server fetch-old)
+  (nnultimate-possibly-change-server group server)
+  (unless gnus-nov-is-evil
+    (let* ((last (car (last articles)))
+          (did nil)
+          (start 1)
+          (entry (assoc group nnultimate-groups))
+          (sid (nth 2 entry))
+          (topics (nth 4 entry))
+          (mapping (nth 5 entry))
+          (old-total (or (nth 6 entry) 1))
+          (furl "forumdisplay.cgi?action=topics&number=%d&DaysPrune=1000")
+          (furls (list (concat nnultimate-address (format furl sid))))
+          (nnultimate-table-regexp
+           "postings.*editpost\\|forumdisplay\\|getbio")
+          headers article subject score from date lines parent point
+          contents tinfo fetchers map elem a href garticles topic old-max
+          inc datel table current-page total-contents pages
+          farticles forum-contents parse furl-fetched mmap farticle)
+      (setq map mapping)
+      (while (and (setq article (car articles))
+                 map)
+       ;; Skip past the articles in the map until we reach the
+       ;; article we're looking for.
+       (while (and map
+                   (or (> article (caar map))
+                       (< (cadar map) (caar map))))
+         (pop map))
+       (when (setq mmap (car map))
+         (setq farticle -1)
+         (while (and article
+                     (<= article (nth 1 mmap)))
+           ;; Do we already have a fetcher for this topic?
+           (if (setq elem (assq (nth 2 mmap) fetchers))
+               ;; Yes, so we just add the spec to the end.
+               (nconc elem (list (cons article
+                                       (+ (nth 3 mmap) (incf farticle)))))
+             ;; No, so we add a new one.
+             (push (list (nth 2 mmap)
+                         (cons article
+                               (+ (nth 3 mmap) (incf farticle))))
+                   fetchers))
+           (pop articles)
+           (setq article (car articles)))))
+      ;; Now we have the mapping from/to Gnus/nnultimate article numbers,
+      ;; so we start fetching the topics that we need to satisfy the
+      ;; request.
+      (if (not fetchers)
+         (save-excursion
+           (set-buffer nntp-server-buffer)
+           (erase-buffer))
+       (setq nnultimate-articles nil)
+       (mm-with-unibyte-buffer
+         (dolist (elem fetchers)
+           (setq pages 1
+                 current-page 1
+                 total-contents nil)
+           (while (<= current-page pages)
+             (erase-buffer)
+             (setq subject (nth 2 (assq (car elem) topics)))
+             (setq href (nth 3 (assq (car elem) topics)))
+             (if (= current-page 1)
+                 (mm-url-insert href)
+               (string-match "\\.html$" href)
+               (mm-url-insert (concat (substring href 0 (match-beginning 0))
+                                     "-" (number-to-string current-page)
+                                     (match-string 0 href))))
+             (goto-char (point-min))
+             (setq contents
+                   (ignore-errors (w3-parse-buffer (current-buffer))))
+             (setq table (nnultimate-find-forum-table contents))
+             (goto-char (point-min))
+             (when (re-search-forward "topic is \\([0-9]+\\) pages" nil t)
+               (setq pages (string-to-number (match-string 1))))
+             (setq contents (cdr (nth 2 (car (nth 2 table)))))
+             (setq total-contents (nconc total-contents contents))
+             (incf current-page))
+           (when t
+             (let ((i 0))
+               (dolist (co total-contents)
+                 (push (list (or (nnultimate-topic-article-to-article
+                                  group (car elem) (incf i))
+                                 1)
+                             co subject)
+                       nnultimate-articles))))
+           (when nil
+             (dolist (art (cdr elem))
+               (when (nth (1- (cdr art)) total-contents)
+                 (push (list (car art)
+                             (nth (1- (cdr art)) total-contents)
+                             subject)
+                       nnultimate-articles))))))
+       (setq nnultimate-articles
+             (sort nnultimate-articles 'car-less-than-car))
+       ;; Now we have all the articles, conveniently in an alist
+       ;; where the key is the Gnus article number.
+       (dolist (articlef nnultimate-articles)
+         (setq article (nth 0 articlef)
+               contents (nth 1 articlef)
+               subject (nth 2 articlef))
+         (setq from (mapconcat 'identity
+                               (nnweb-text (car (nth 2 contents)))
+                               " ")
+               datel (nnweb-text (nth 2 (car (cdr (nth 2 contents))))))
+         (while datel
+           (when (string-match "Posted" (car datel))
+             (setq date (substring (car datel) (match-end 0))
+                   datel nil))
+           (pop datel))
+         (when date
+           (setq date (delete "" (split-string date "[-, \n\t\r Â Â Â ]")))
+           (setq date
+                 (if (or (member "AM" date)
+                         (member "PM" date))
+                     (format
+                      "%s %s %s %s"
+                      (nth 1 date)
+                      (if (and (>= (length (nth 0 date)) 3)
+                               (assoc (downcase
+                                       (substring (nth 0 date) 0 3))
+                                      parse-time-months))
+                          (substring (nth 0 date) 0 3)
+                        (car (rassq (string-to-number (nth 0 date))
+                                    parse-time-months)))
+                      (nth 2 date) (nth 3 date))
+                   (format "%s %s %s %s"
+                           (car (rassq (string-to-number (nth 1 date))
+                                       parse-time-months))
+                           (nth 0 date) (nth 2 date) (nth 3 date)))))
+         (push
+          (cons
+           article
+           (make-full-mail-header
+            article subject
+            from (or date "")
+            (concat "<" (number-to-string sid) "%"
+                    (number-to-string article)
+                    "@ultimate." server ">")
+            "" 0
+            (/ (length (mapconcat
+                        'identity
+                        (nnweb-text
+                         (cdr (nth 2 (nth 1 (nth 2 contents)))))
+                        ""))
+               70)
+            nil nil))
+          headers))
+       (setq nnultimate-headers (sort headers 'car-less-than-car))
+       (save-excursion
+         (set-buffer nntp-server-buffer)
+         (mm-with-unibyte-current-buffer
+           (erase-buffer)
+           (dolist (header nnultimate-headers)
+             (nnheader-insert-nov (cdr header))))))
+      'nov)))
+
+(defun nnultimate-topic-article-to-article (group topic article)
+  (catch 'found
+    (dolist (elem (nth 5 (assoc group nnultimate-groups)))
+      (when (and (= topic (nth 2 elem))
+                (>= article (nth 3 elem))
+                (< article (+ (- (nth 1 elem) (nth 0 elem)) 1
+                              (nth 3 elem))))
+       (throw 'found
+              (+ (nth 0 elem) (- article (nth 3 elem))))))))
+
+(deffoo nnultimate-request-group (group &optional server dont-check)
+  (nnultimate-possibly-change-server nil server)
+  (when (not nnultimate-groups)
+    (nnultimate-request-list))
+  (unless dont-check
+    (nnultimate-create-mapping group))
+  (let ((elem (assoc group nnultimate-groups)))
+    (cond
+     ((not elem)
+      (nnheader-report 'nnultimate "Group does not exist"))
+     (t
+      (nnheader-report 'nnultimate "Opened group %s" group)
+      (nnheader-insert
+       "211 %d %d %d %s\n" (cadr elem) 1 (cadr elem)
+       (prin1-to-string group))))))
+
+(deffoo nnultimate-request-close ()
+  (setq nnultimate-groups-alist nil
+       nnultimate-groups nil))
+
+(deffoo nnultimate-request-article (article &optional group server buffer)
+  (nnultimate-possibly-change-server group server)
+  (let ((contents (cdr (assq article nnultimate-articles))))
+    (setq contents (cddr (nth 2 (nth 1 (nth 2 (car contents))))))
+    (when contents
+      (save-excursion
+       (set-buffer (or buffer nntp-server-buffer))
+       (erase-buffer)
+       (nnweb-insert-html (cons 'p (cons nil (list contents))))
+       (goto-char (point-min))
+       (insert "Content-Type: text/html\nMIME-Version: 1.0\n")
+       (let ((header (cdr (assq article nnultimate-headers))))
+         (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)
+  (mm-with-unibyte-buffer
+    (mm-url-insert
+     (if (string-match "/$" nnultimate-address)
+        (concat nnultimate-address "Ultimate.cgi")
+       nnultimate-address))
+    (let ((contents (nth 2 (car (nth 2
+                                    (nnultimate-find-forum-table
+                                     (w3-parse-buffer (current-buffer)))))))
+         sid elem description articles a href group forum
+         a1 a2)
+      (dolist (row contents)
+       (setq row (nth 2 row))
+       (when (setq a (nnweb-parse-find 'a row))
+         (setq group (car (last (nnweb-text a)))
+               href (cdr (assq 'href (nth 1 a))))
+         (setq description (car (last (nnweb-text (nth 1 row)))))
+         (setq a1 (car (last (nnweb-text (nth 2 row)))))
+         (setq a2 (car (last (nnweb-text (nth 3 row)))))
+         (when (string-match "^[0-9]+$" a1)
+           (setq articles (string-to-number a1)))
+         (when (and a2 (string-match "^[0-9]+$" a2))
+           (setq articles (max articles (string-to-number a2))))
+         (when href
+           (string-match "number=\\([0-9]+\\)" href)
+           (setq forum (string-to-number (match-string 1 href)))
+           (if (setq elem (assoc group nnultimate-groups))
+               (setcar (cdr elem) articles)
+             (push (list group articles forum description nil nil nil nil)
+                   nnultimate-groups))))))
+    (nnultimate-write-groups)
+    (nnultimate-generate-active)
+    t))
+
+(deffoo nnultimate-request-newgroups (date &optional server)
+  (nnultimate-possibly-change-server nil server)
+  (nnultimate-generate-active)
+  t)
+
+(nnoo-define-skeleton nnultimate)
+
+;;; Internal functions
+
+(defun nnultimate-prune-days (group time)
+  "Compute the number of days to fetch info for."
+  (let ((old-time (nth 7 (assoc group nnultimate-groups))))
+    (if (null old-time)
+       1000
+      (- (time-to-days time) (time-to-days old-time)))))
+
+(defun nnultimate-create-mapping (group)
+  (let* ((entry (assoc group nnultimate-groups))
+        (sid (nth 2 entry))
+        (topics (nth 4 entry))
+        (mapping (nth 5 entry))
+        (old-total (or (nth 6 entry) 1))
+        (current-time (current-time))
+        (furl
+         (concat "forumdisplay.cgi?action=topics&number=%d&DaysPrune="
+                 (number-to-string
+                  (nnultimate-prune-days group current-time))))
+        (furls (list (concat nnultimate-address (format furl sid))))
+        contents forum-contents furl-fetched a subject href
+        garticles topic tinfo old-max inc parse)
+    (mm-with-unibyte-buffer
+      (while furls
+       (erase-buffer)
+       (mm-url-insert (pop furls))
+       (goto-char (point-min))
+       (setq parse (w3-parse-buffer (current-buffer)))
+       (setq contents
+             (cdr (nth 2 (car (nth 2 (nnultimate-find-forum-table
+                                      parse))))))
+       (setq forum-contents (nconc contents forum-contents))
+       (unless furl-fetched
+         (setq furl-fetched t)
+         ;; On the first time through this loop, we find all the
+         ;; forum URLs.
+         (dolist (a (nnweb-parse-find-all 'a parse))
+           (let ((href (cdr (assq 'href (nth 1 a)))))
+             (when (and href
+                        (string-match "forumdisplay.*startpoint" href))
+               (push href furls))))
+         (setq furls (nreverse furls))))
+      ;; The main idea here is to map Gnus article numbers to
+      ;; nnultimate article numbers.  Say there are three topics in
+      ;; this forum, the first with 4 articles, the seconds with 2,
+      ;; and the third with 1.  Then this will translate into 7 Gnus
+      ;; article numbers, where 1-4 comes from the first topic, 5-6
+      ;; from the second and 7 from the third.  Now, then next time
+      ;; the group is entered, there's 2 new articles in topic one
+      ;; and 1 in topic three.  Then Gnus article number 8-9 be 5-6
+      ;; in topic one and 10 will be the 2 in topic three.
+      (dolist (row (nreverse forum-contents))
+       (setq row (nth 2 row))
+       (when (setq a (nnweb-parse-find 'a row))
+         (setq subject (car (last (nnweb-text a)))
+               href (cdr (assq 'href (nth 1 a))))
+         (let ((artlist (nreverse (nnweb-text row)))
+               art)
+           (while (and (not art)
+                       artlist)
+             (when (string-match "^[0-9]+$" (car artlist))
+               (setq art (1+ (string-to-number (car artlist)))))
+             (pop artlist))
+           (setq garticles art))
+         (when garticles
+           (string-match "/\\([0-9]+\\).html" href)
+           (setq topic (string-to-number (match-string 1 href)))
+           (if (setq tinfo (assq topic topics))
+               (progn
+                 (setq old-max (cadr tinfo))
+                 (setcar (cdr tinfo) garticles))
+             (setq old-max 0)
+             (push (list topic garticles subject href) topics)
+             (setcar (nthcdr 4 entry) topics))
+           (when (not (= old-max garticles))
+             (setq inc (- garticles old-max))
+             (setq mapping (nconc mapping
+                                  (list
+                                   (list
+                                    old-total (1- (incf old-total inc))
+                                    topic (1+ old-max)))))
+             (incf old-max inc)
+             (setcar (nthcdr 5 entry) mapping)
+             (setcar (nthcdr 6 entry) old-total))))))
+    (setcar (nthcdr 7 entry) current-time)
+    (setcar (nthcdr 1 entry) (1- old-total))
+    (nnultimate-write-groups)
+    mapping))
+
+(defun nnultimate-possibly-change-server (&optional group server)
+  (nnultimate-init server)
+  (when (and server
+            (not (nnultimate-server-opened server)))
+    (nnultimate-open-server server))
+  (unless nnultimate-groups-alist
+    (nnultimate-read-groups)
+    (setq nnultimate-groups (cdr (assoc nnultimate-address
+                                       nnultimate-groups-alist)))))
+
+(deffoo nnultimate-open-server (server &optional defs connectionless)
+  (nnheader-init-server-buffer)
+  (if (nnultimate-server-opened server)
+      t
+    (unless (assq 'nnultimate-address defs)
+      (setq defs (append defs (list (list 'nnultimate-address server)))))
+    (nnoo-change-server 'nnultimate server defs)))
+
+(defun nnultimate-read-groups ()
+  (setq nnultimate-groups-alist nil)
+  (let ((file (expand-file-name "groups" nnultimate-directory)))
+    (when (file-exists-p file)
+      (mm-with-unibyte-buffer
+       (insert-file-contents file)
+       (goto-char (point-min))
+       (setq nnultimate-groups-alist (read (current-buffer)))))))
+
+(defun nnultimate-write-groups ()
+  (setq nnultimate-groups-alist
+       (delq (assoc nnultimate-address nnultimate-groups-alist)
+             nnultimate-groups-alist))
+  (push (cons nnultimate-address nnultimate-groups)
+       nnultimate-groups-alist)
+  (with-temp-file (expand-file-name "groups" nnultimate-directory)
+    (prin1 nnultimate-groups-alist (current-buffer))))
+
+(defun nnultimate-init (server)
+  "Initialize buffers and such."
+  (unless (file-exists-p nnultimate-directory)
+    (gnus-make-directory nnultimate-directory)))
+
+(defun nnultimate-generate-active ()
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnultimate-groups)
+      (insert (prin1-to-string (car elem))
+             " " (number-to-string (cadr elem)) " 1 y\n"))))
+
+(defun nnultimate-find-forum-table (contents)
+  (catch 'found
+    (nnultimate-find-forum-table-1 contents)))
+
+(defun nnultimate-find-forum-table-1 (contents)
+  (dolist (element contents)
+    (unless (stringp element)
+      (when (and (eq (car element) 'table)
+                (nnultimate-forum-table-p element))
+       (throw 'found element))
+      (when (nth 2 element)
+       (nnultimate-find-forum-table-1 (nth 2 element))))))
+
+(defun nnultimate-forum-table-p (parse)
+  (when (not (apply 'gnus-or
+                   (mapcar
+                    (lambda (p)
+                      (nnweb-parse-find 'table p))
+                    (nth 2 parse))))
+    (let ((href (cdr (assq 'href (nth 1 (nnweb-parse-find 'a parse 20)))))
+         case-fold-search)
+      (when (and href (string-match nnultimate-table-regexp href))
+       t))))
+
+(provide 'nnultimate)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; nnultimate.el ends here
index 41964dc..76a4670 100644 (file)
@@ -1,9 +1,10 @@
 ;;; nnvirtual.el --- virtual newsgroups access for Gnus
-;; Copyright (C) 1994,95,96,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: David Moore <dmoore@ucsd.edu>
-;;     Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
-;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
+;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
@@ -31,6 +32,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 (require 'nntp)
 (require 'nnheader)
 (require 'gnus)
 (require 'gnus-start)
 (require 'gnus-sum)
 (require 'gnus-msg)
-(require 'cl)
 
 (nnoo-declare nnvirtual)
 
-(defvoo nnvirtual-always-rescan nil
-  "*If non-nil, always scan groups for unread articles when entering a group.
-If this variable is nil (which is the default) and you read articles
-in a component group after the virtual group has been activated, the
-read articles from the component group will show up when you enter the
-virtual group.")
+(defvoo nnvirtual-always-rescan t
+  "If non-nil, always scan groups for unread articles when entering a group.
+If this variable is nil and you read articles in a component group
+after the virtual group has been activated, the read articles from the
+component group will show up when you enter the virtual group.")
 
 (defvoo nnvirtual-component-regexp nil
-  "*Regexp to match component groups.")
+  "Regexp to match component groups.")
 
 (defvoo nnvirtual-component-groups nil
   "Component group in this nnvirtual group.")
@@ -63,8 +64,7 @@ virtual group.")
 (defvoo nnvirtual-current-group nil)
 
 (defvoo nnvirtual-mapping-table nil
-  "Table of rules on how to map between component group and article number
-to virtual article number.")
+  "Table of rules on how to map between component group and article number to virtual article number.")
 
 (defvoo nnvirtual-mapping-offsets nil
   "Table indexed by component group to an offset to be applied to article numbers in that group.")
@@ -122,47 +122,47 @@ to virtual article number.")
                       (let ((gnus-use-cache t))
                         (setq result (gnus-retrieve-headers
                                       articles cgroup nil))))
-           (set-buffer nntp-server-buffer)
-           ;; If we got HEAD headers, we convert them into NOV
-           ;; headers.  This is slow, inefficient and, come to think
-           ;; of it, downright evil.  So sue me.  I couldn't be
-           ;; bothered to write a header parse routine that could
-           ;; parse a mixed HEAD/NOV buffer.
-           (when (eq result 'headers)
-             (nnvirtual-convert-headers))
-           (goto-char (point-min))
-           (while (not (eobp))
-             (delete-region (point)
-                            (progn
-                              (setq carticle (read nntp-server-buffer))
-                              (point)))
-
-             ;; We remove this article from the articles list, if
-             ;; anything is left in the articles list after going through
-             ;; the entire buffer, then those articles have been
-             ;; expired or canceled, so we appropriately update the
-             ;; component group below.  They should be coming up
-             ;; generally in order, so this shouldn't be slow.
-             (setq articles (delq carticle articles))
-
-             (setq article (nnvirtual-reverse-map-article cgroup carticle))
-             (if (null article)
-                 ;; This line has no reverse mapping, that means it
-                 ;; was an extra article reference returned by nntp.
-                 (progn
-                   (beginning-of-line)
-                   (delete-region (point) (progn (forward-line 1) (point))))
-               ;; Otherwise insert the virtual article number,
-               ;; and clean up the xrefs.
-               (princ article nntp-server-buffer)
-               (nnvirtual-update-xref-header cgroup carticle
-                                             prefix system-name)
-               (forward-line 1))
-             )
-
-           (set-buffer vbuf)
-           (goto-char (point-max))
-           (insert-buffer-substring nntp-server-buffer))
+             (set-buffer nntp-server-buffer)
+             ;; If we got HEAD headers, we convert them into NOV
+             ;; headers.  This is slow, inefficient and, come to think
+             ;; of it, downright evil.  So sue me.  I couldn't be
+             ;; bothered to write a header parse routine that could
+             ;; parse a mixed HEAD/NOV buffer.
+             (when (eq result 'headers)
+               (nnvirtual-convert-headers))
+             (goto-char (point-min))
+             (while (not (eobp))
+               (delete-region (point)
+                              (progn
+                                (setq carticle (read nntp-server-buffer))
+                                (point)))
+
+               ;; We remove this article from the articles list, if
+               ;; anything is left in the articles list after going through
+               ;; the entire buffer, then those articles have been
+               ;; expired or canceled, so we appropriately update the
+               ;; component group below.  They should be coming up
+               ;; generally in order, so this shouldn't be slow.
+               (setq articles (delq carticle articles))
+
+               (setq article (nnvirtual-reverse-map-article cgroup carticle))
+               (if (null article)
+                   ;; This line has no reverse mapping, that means it
+                   ;; was an extra article reference returned by nntp.
+                   (progn
+                     (beginning-of-line)
+                     (delete-region (point) (progn (forward-line 1) (point))))
+                 ;; Otherwise insert the virtual article number,
+                 ;; and clean up the xrefs.
+                 (princ article nntp-server-buffer)
+                 (nnvirtual-update-xref-header cgroup carticle
+                                               prefix system-name)
+                 (forward-line 1))
+               )
+
+             (set-buffer vbuf)
+             (goto-char (point-max))
+             (insert-buffer-substring nntp-server-buffer))
            ;; Anything left in articles is expired or canceled.
            ;; Could be smart and not tell it about articles already known?
            (when articles
@@ -199,8 +199,9 @@ to virtual article number.")
          (save-excursion
            (when buffer
              (set-buffer buffer))
-           (let ((method (gnus-find-method-for-group
-                          nnvirtual-last-accessed-component-group)))
+           (let* ((gnus-override-method nil)
+                  (method (gnus-find-method-for-group
+                           nnvirtual-last-accessed-component-group)))
              (funcall (gnus-get-function method 'request-article)
                       article nil (nth 1 method) buffer)))))
       ;; This is a fetch by number.
@@ -219,7 +220,9 @@ to virtual article number.")
          (if buffer
              (save-excursion
                (set-buffer buffer)
-               (gnus-request-article-this-buffer (cdr amap) cgroup))
+               ;; We bind this here to avoid double decoding.
+               (let ((gnus-article-decode-hook nil))
+                 (gnus-request-article-this-buffer (cdr amap) cgroup)))
            (gnus-request-article (cdr amap) cgroup))))))))
 
 
@@ -259,10 +262,14 @@ to virtual article number.")
     (setq nnvirtual-current-group nil)
     (nnheader-report 'nnvirtual "No component groups in %s" group))
    (t
+    (setq nnvirtual-current-group group)
     (when (or (not dont-check)
              nnvirtual-always-rescan)
-      (nnvirtual-create-mapping))
-    (setq nnvirtual-current-group group)
+      (nnvirtual-create-mapping)
+      (when nnvirtual-always-rescan
+       (nnvirtual-request-update-info
+        (nnvirtual-current-group)
+        (gnus-get-info (nnvirtual-current-group)))))
     (nnheader-insert "211 %d 1 %d %s\n"
                     nnvirtual-mapping-len nnvirtual-mapping-len group))))
 
@@ -270,17 +277,20 @@ to virtual article number.")
 (deffoo nnvirtual-request-type (group &optional article)
   (if (not article)
       'unknown
-    (let ((mart (nnvirtual-map-article article)))
-      (when mart
-       (gnus-request-type (car mart) (cdr mart))))))
+    (if (numberp article)
+       (let ((mart (nnvirtual-map-article article)))
+         (if mart
+             (gnus-request-type (car mart) (cdr mart))))
+      (gnus-request-type
+       nnvirtual-last-accessed-component-group nil))))
 
 (deffoo nnvirtual-request-update-mark (group article mark)
   (let* ((nart (nnvirtual-map-article article))
-        (cgroup (car nart))
-        ;; The component group might be a virtual group.
-        (nmark (gnus-request-update-mark cgroup (cdr nart) mark)))
+        (cgroup (car nart)))
     (when (and nart
-              (= mark nmark)
+              (memq mark gnus-auto-expirable-marks)
+              ;; The component group might be a virtual group.
+              (= mark (gnus-request-update-mark cgroup (cdr nart) mark))
               (gnus-group-auto-expirable-p cgroup))
       (setq mark gnus-expirable-mark)))
   mark)
@@ -352,6 +362,23 @@ to virtual article number.")
                       (cdr gnus-message-group-art)))))
       (gnus-request-post (gnus-find-method-for-group group)))))
 
+
+(deffoo nnvirtual-request-expire-articles (articles group
+                                                   &optional server force)
+  (nnvirtual-possibly-change-server server)
+  (setq nnvirtual-component-groups
+       (delete (nnvirtual-current-group) nnvirtual-component-groups))
+  (let (unexpired)
+    (dolist (group nnvirtual-component-groups)
+      (setq unexpired (nconc unexpired
+                            (mapcar
+                             #'(lambda (article)
+                                 (nnvirtual-reverse-map-article
+                                  group article))
+                             (gnus-uncompress-range
+                              (gnus-group-expire-articles-1 group))))))
+    (sort (delq nil unexpired) '<)))
+
 \f
 ;;; Internal functions.
 
@@ -378,7 +405,7 @@ to virtual article number.")
     (insert "\t"))
 
   ;; Remove any spaces at the beginning of the Xref field.
-  (while (= (char-after (1- (point))) ? )
+  (while (eq (char-after (1- (point))) ? )
     (forward-char -1)
     (delete-char 1))
 
@@ -397,10 +424,10 @@ to virtual article number.")
       (replace-match "" t t))
     (goto-char (point-min))
     (when (re-search-forward
-          (concat (gnus-group-real-name group) ":[0-9]+")
+          (concat (regexp-quote (gnus-group-real-name group)) ":[0-9]+")
           nil t)
       (replace-match "" t t))
-    (unless (= (point) (point-max))
+    (unless (eobp)
       (insert " ")
       (when (not (string= "" prefix))
        (while (re-search-forward "[^ ]+:[0-9]+" nil t)
@@ -410,7 +437,7 @@ to virtual article number.")
 
   ;; Ensure a trailing \t.
   (end-of-line)
-  (or (= (char-after (1- (point))) ?\t)
+  (or (eq (char-after (1- (point))) ?\t)
       (insert ?\t)))
 
 
@@ -429,19 +456,24 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
                        (nnvirtual-partition-sequence
                         (gnus-list-of-unread-articles
                          (nnvirtual-current-group)))))
-         (type-marks (mapcar (lambda (ml)
-                               (cons (car ml)
-                                     (nnvirtual-partition-sequence (cdr ml))))
-                             (gnus-info-marks (gnus-get-info
-                                               (nnvirtual-current-group)))))
+         (type-marks
+          (delq nil
+                (mapcar (lambda (ml)
+                          (if (eq (car ml) 'score)
+                              nil
+                            (cons (car ml)
+                                  (nnvirtual-partition-sequence (cdr ml)))))
+                        (gnus-info-marks (gnus-get-info
+                                          (nnvirtual-current-group))))))
          mark type groups carticles info entry)
 
       ;; Ok, atomically move all of the (un)read info, clear any old
       ;; marks, and move all of the current marks.  This way if someone
       ;; hits C-g, you won't leave the component groups in a half-way state.
-      (gnus-atomic-progn
+      (progn
        ;; move (un)read
-       (let ((gnus-newsgroup-active nil)) ;workaround guns-update-read-articles
+       ;; bind for workaround guns-update-read-articles
+       (let ((gnus-newsgroup-active nil))
          (while (setq entry (pop unreads))
            (gnus-update-read-articles (car entry) (cdr entry))))
 
@@ -450,7 +482,11 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
        (while groups
          (when (and (setq info (gnus-get-info (pop groups)))
                     (gnus-info-marks info))
-           (gnus-info-set-marks info nil)))
+           (gnus-info-set-marks
+            info
+            (if (assq 'score (gnus-info-marks info))
+                (list (assq 'score (gnus-info-marks info)))
+              nil))))
 
        ;; Ok, currently type-marks is an assq list with keys of a mark type,
        ;; with data of an assq list with keys of component group names
@@ -486,14 +522,15 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
 
 
 ;;; We map between virtual articles and real articles in a manner
-;;; which keeps the size of the virtual active list the same as
-;;; the sum of the component active lists.
-;;; To achieve fair mixing of the groups, the last article in
-;;; each of N component groups will be in the the last N articles
-;;; in the virtual group.
-
-;;; If you have 3 components A, B and C, with articles 1-8, 1-5, and 6-7
-;;; resprectively, then the virtual article numbers look like:
+;;; which keeps the size of the virtual active list the same as the
+;;; sum of the component active lists.
+
+;;; To achieve fair mixing of the groups, the last article in each of
+;;; N component groups will be in the last N articles in the virtual
+;;; group.
+
+;;; If you have 3 components A, B and C, with articles 1-8, 1-5, and
+;;; 6-7 respectively, then the virtual article numbers look like:
 ;;;
 ;;;  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
 ;;;  A1 A2 A3 A4 B1 A5 B2 A6 B3 A7 B4 C6 A8 B5 C7
@@ -564,7 +601,7 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
               (aref entry 1)
               (cdr (aref nnvirtual-mapping-offsets group-pos)))
            ))
-      ))
+    ))
 
 
 
@@ -622,7 +659,7 @@ then it is left out of the result."
   "Return an association list of component article numbers.
 These are indexed by elements of nnvirtual-component-groups, based on
 the sequence ARTICLES of virtual article numbers.  ARTICLES should be
-sorted, and can be a compressed sequence. If any of the article
+sorted, and can be a compressed sequence.  If any of the article
 numbers has no corresponding component article, then it is left out of
 the result."
   (when (numberp (cdr-safe articles))
@@ -664,28 +701,28 @@ based on the marks on the component groups."
     ;; Into all-unreads we put (g unreads).
     ;; Into all-marks we put (g marks).
     ;; We also increment cnt and tot here, and compute M (max of sizes).
-    (mapc (lambda (g)
-           (setq active (gnus-activate-group g)
-                 min (car active)
-                 max (cdr active))
-           (when (and active (>= max min) (not (zerop max)))
-             ;; store active information
-             (push (list g (- max min -1) max) actives)
-             ;; collect unread/mark info for later
-             (setq unreads (gnus-list-of-unread-articles g))
-             (setq marks (gnus-info-marks (gnus-get-info g)))
-             (when gnus-use-cache
-               (push (cons 'cache
-                           (gnus-cache-articles-in-group g))
-                     marks))
-             (push (cons g unreads) all-unreads)
-             (push (cons g marks) all-marks)
-             ;; count groups, total #articles, and max size
-             (setq size (- max min -1))
-             (setq cnt (1+ cnt)
-                   tot (+ tot size)
-                   M (max M size))))
-         nnvirtual-component-groups)
+    (mapcar (lambda (g)
+             (setq active (gnus-activate-group g)
+                   min (car active)
+                   max (cdr active))
+             (when (and active (>= max min) (not (zerop max)))
+               ;; store active information
+               (push (list g (- max min -1) max) actives)
+               ;; collect unread/mark info for later
+               (setq unreads (gnus-list-of-unread-articles g))
+               (setq marks (gnus-info-marks (gnus-get-info g)))
+               (when gnus-use-cache
+                 (push (cons 'cache
+                             (gnus-cache-articles-in-group g))
+                       marks))
+               (push (cons g unreads) all-unreads)
+               (push (cons g marks) all-marks)
+               ;; count groups, total #articles, and max size
+               (setq size (- max min -1))
+               (setq cnt (1+ cnt)
+                     tot (+ tot size)
+                     M (max M size))))
+           nnvirtual-component-groups)
 
     ;; Number of articles in the virtual group.
     (setq nnvirtual-mapping-len tot)
diff --git a/lisp/nnwarchive.el b/lisp/nnwarchive.el
new file mode 100644 (file)
index 0000000..57f31e9
--- /dev/null
@@ -0,0 +1,726 @@
+;;; nnwarchive.el --- interfacing with web archives
+;; Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: news egroups mail-archive
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Note: You need to have `url' (w3 0.46) or greater version
+;; installed for some functions of this backend to work.
+
+;; Todo:
+;; 1. To support more web archives.
+;; 2. Generalize webmail to other MHonArc archive.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'nnoo)
+(require 'message)
+(require 'gnus-util)
+(require 'gnus)
+(require 'gnus-bcklg)
+(require 'nnmail)
+(require 'mm-util)
+(require 'mm-url)
+
+(nnoo-declare nnwarchive)
+
+(defvar nnwarchive-type-definition
+  '((egroups
+     (address . "www.egroups.com")
+     (open-url
+      "http://www.egroups.com/login.cgi?&login_email=%s&login_password=%s"
+      nnwarchive-login nnwarchive-passwd)
+     (list-url
+      "http://www.egroups.com/mygroups")
+     (list-dissect . nnwarchive-egroups-list)
+     (list-groups . nnwarchive-egroups-list-groups)
+     (xover-url
+      "http://www.egroups.com/messages/%s/%d" group aux)
+     (xover-last-url
+      "http://www.egroups.com/messages/%s/" group)
+     (xover-page-size . 13)
+     (xover-dissect . nnwarchive-egroups-xover)
+     (article-url
+      "http://www.egroups.com/message/%s/%d?source=1" group article)
+     (article-dissect . nnwarchive-egroups-article)
+     (authentication . t)
+     (article-offset . 0)
+     (xover-files . nnwarchive-egroups-xover-files))
+    (mail-archive
+     (address . "www.mail-archive.com")
+     (open-url)
+     (list-url
+      "http://www.mail-archive.com/lists.html")
+     (list-dissect . nnwarchive-mail-archive-list)
+     (list-groups . nnwarchive-mail-archive-list-groups)
+     (xover-url
+      "http://www.mail-archive.com/%s/mail%d.html" group aux)
+     (xover-last-url
+      "http://www.mail-archive.com/%s/maillist.html" group)
+     (xover-page-size)
+     (xover-dissect . nnwarchive-mail-archive-xover)
+     (article-url
+      "http://www.mail-archive.com/%s/msg%05d.html" group article1)
+     (article-dissect . nnwarchive-mail-archive-article)
+     (xover-files . nnwarchive-mail-archive-xover-files)
+     (authentication)
+     (article-offset . 1))))
+
+(defvar nnwarchive-default-type 'egroups)
+
+(defvoo nnwarchive-directory (nnheader-concat gnus-directory "warchive/")
+  "Where nnwarchive will save its files.")
+
+(defvoo nnwarchive-type nil
+  "The type of nnwarchive.")
+
+(defvoo nnwarchive-address ""
+  "The address of nnwarchive.")
+
+(defvoo nnwarchive-login nil
+  "Your login name for the group.")
+
+(defvoo nnwarchive-passwd nil
+  "Your password for the group.")
+
+(defvoo nnwarchive-groups nil)
+
+(defvoo nnwarchive-headers-cache nil)
+
+(defvoo nnwarchive-authentication nil)
+
+(defvoo nnwarchive-nov-is-evil nil)
+
+(defconst nnwarchive-version "nnwarchive 1.0")
+
+;;; Internal variables
+
+(defvoo nnwarchive-open-url nil)
+(defvoo nnwarchive-open-dissect nil)
+
+(defvoo nnwarchive-list-url nil)
+(defvoo nnwarchive-list-dissect nil)
+(defvoo nnwarchive-list-groups nil)
+
+(defvoo nnwarchive-xover-files nil)
+(defvoo nnwarchive-xover-url nil)
+(defvoo nnwarchive-xover-last-url nil)
+(defvoo nnwarchive-xover-dissect nil)
+(defvoo nnwarchive-xover-page-size nil)
+
+(defvoo nnwarchive-article-url nil)
+(defvoo nnwarchive-article-dissect nil)
+(defvoo nnwarchive-xover-files nil)
+(defvoo nnwarchive-article-offset 0)
+
+(defvoo nnwarchive-buffer nil)
+
+(defvoo nnwarchive-keep-backlog 300)
+(defvar nnwarchive-backlog-articles nil)
+(defvar nnwarchive-backlog-hashtb nil)
+
+(defvoo nnwarchive-headers nil)
+
+
+;;; Interface functions
+
+(nnoo-define-basics nnwarchive)
+
+(defun nnwarchive-set-default (type)
+  (let ((defs (cdr (assq type nnwarchive-type-definition)))
+       def)
+    (dolist (def defs)
+      (set (intern (concat "nnwarchive-" (symbol-name (car def))))
+          (cdr def)))))
+
+(defmacro nnwarchive-backlog (&rest form)
+  `(let ((gnus-keep-backlog nnwarchive-keep-backlog)
+        (gnus-backlog-buffer
+         (format " *nnwarchive backlog %s*" nnwarchive-address))
+        (gnus-backlog-articles nnwarchive-backlog-articles)
+        (gnus-backlog-hashtb nnwarchive-backlog-hashtb))
+     (unwind-protect
+        (progn ,@form)
+       (setq nnwarchive-backlog-articles gnus-backlog-articles
+            nnwarchive-backlog-hashtb gnus-backlog-hashtb))))
+(put 'nnwarchive-backlog 'lisp-indent-function 0)
+(put 'nnwarchive-backlog 'edebug-form-spec '(form body))
+
+(defun nnwarchive-backlog-enter-article (group number buffer)
+  (nnwarchive-backlog
+    (gnus-backlog-enter-article group number buffer)))
+
+(defun nnwarchive-get-article (article &optional group server buffer)
+  (if (numberp article)
+      (if (nnwarchive-backlog
+           (gnus-backlog-request-article group article
+                                         (or buffer nntp-server-buffer)))
+         (cons group article)
+       (let (contents)
+         (save-excursion
+           (set-buffer nnwarchive-buffer)
+           (goto-char (point-min))
+           (let ((article1 (- article nnwarchive-article-offset)))
+             (nnwarchive-url nnwarchive-article-url))
+           (setq contents (funcall nnwarchive-article-dissect group article)))
+         (when contents
+           (save-excursion
+             (set-buffer (or buffer nntp-server-buffer))
+             (erase-buffer)
+             (insert contents)
+             (nnwarchive-backlog-enter-article group article (current-buffer))
+             (nnheader-report 'nnwarchive "Fetched article %s" article)
+             (cons group article)))))
+    nil))
+
+(deffoo nnwarchive-retrieve-headers (articles &optional group server fetch-old)
+  (nnwarchive-possibly-change-server group server)
+  (if (or gnus-nov-is-evil nnwarchive-nov-is-evil)
+      (with-temp-buffer
+       (with-current-buffer nntp-server-buffer
+         (erase-buffer))
+       (let ((buf (current-buffer)) b e)
+         (dolist (art articles)
+           (nnwarchive-get-article art group server buf)
+           (setq b (goto-char (point-min)))
+           (if (search-forward "\n\n" nil t)
+               (forward-char -1)
+             (goto-char (point-max)))
+           (setq e (point))
+           (with-current-buffer nntp-server-buffer
+             (insert (format "221 %d Article retrieved.\n" art))
+             (insert-buffer-substring buf b e)
+             (insert ".\n"))))
+       'headers)
+    (setq nnwarchive-headers (cdr (assoc group nnwarchive-headers-cache)))
+    (save-excursion
+      (set-buffer nnwarchive-buffer)
+      (erase-buffer)
+      (funcall nnwarchive-xover-files group articles))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (let (header)
+       (dolist (art articles)
+         (if (setq header (assq art nnwarchive-headers))
+             (nnheader-insert-nov (cdr header))))))
+    (let ((elem (assoc group nnwarchive-headers-cache)))
+      (if elem
+         (setcdr elem nnwarchive-headers)
+       (push (cons group nnwarchive-headers) nnwarchive-headers-cache)))
+    'nov))
+
+(deffoo nnwarchive-request-group (group &optional server dont-check)
+  (nnwarchive-possibly-change-server nil server)
+  (when (and (not dont-check) nnwarchive-list-groups)
+    (funcall nnwarchive-list-groups (list group))
+    (nnwarchive-write-groups))
+  (let ((elem (assoc group nnwarchive-groups)))
+    (cond
+     ((not elem)
+      (nnheader-report 'nnwarchive "Group does not exist"))
+     (t
+      (nnheader-report 'nnwarchive "Opened group %s" group)
+      (nnheader-insert
+       "211 %d %d %d %s\n" (or (cadr elem) 0) 1 (or (cadr elem) 0)
+       (prin1-to-string group))
+      t))))
+
+(deffoo nnwarchive-request-article (article &optional group server buffer)
+  (nnwarchive-possibly-change-server group server)
+  (nnwarchive-get-article article group server buffer))
+
+(deffoo nnwarchive-close-server (&optional server)
+  (when (and (nnwarchive-server-opened server)
+            (gnus-buffer-live-p nnwarchive-buffer))
+    (save-excursion
+      (set-buffer nnwarchive-buffer)
+      (kill-buffer nnwarchive-buffer)))
+  (nnwarchive-backlog
+    (gnus-backlog-shutdown))
+  (nnoo-close-server 'nnwarchive server))
+
+(deffoo nnwarchive-request-list (&optional server)
+  (nnwarchive-possibly-change-server nil server)
+  (save-excursion
+    (set-buffer nnwarchive-buffer)
+    (erase-buffer)
+    (if nnwarchive-list-url
+       (nnwarchive-url nnwarchive-list-url))
+    (if nnwarchive-list-dissect
+       (funcall nnwarchive-list-dissect))
+    (nnwarchive-write-groups)
+    (nnwarchive-generate-active))
+  t)
+
+(deffoo nnwarchive-open-server (server &optional defs connectionless)
+  (nnoo-change-server 'nnwarchive server defs)
+  (nnwarchive-init server)
+  (when nnwarchive-authentication
+    (setq nnwarchive-login
+         (or nnwarchive-login
+             (read-string
+              (format "Login at %s: " server)
+              user-mail-address)))
+    (setq nnwarchive-passwd
+         (or nnwarchive-passwd
+             (read-passwd
+              (format "Password for %s at %s: "
+                      nnwarchive-login server)))))
+  (unless nnwarchive-groups
+    (nnwarchive-read-groups))
+  (save-excursion
+    (set-buffer nnwarchive-buffer)
+    (erase-buffer)
+    (if nnwarchive-open-url
+       (nnwarchive-url nnwarchive-open-url))
+    (if nnwarchive-open-dissect
+       (funcall nnwarchive-open-dissect)))
+  t)
+
+(nnoo-define-skeleton nnwarchive)
+
+;;; Internal functions
+
+(defun nnwarchive-possibly-change-server (&optional group server)
+  (nnwarchive-init server)
+  (when (and server
+            (not (nnwarchive-server-opened server)))
+    (nnwarchive-open-server server)))
+
+(defun nnwarchive-read-groups ()
+  (let ((file (expand-file-name (concat "groups-" nnwarchive-address)
+                               nnwarchive-directory)))
+    (when (file-exists-p file)
+      (with-temp-buffer
+       (insert-file-contents file)
+       (goto-char (point-min))
+       (setq nnwarchive-groups (read (current-buffer)))))))
+
+(defun nnwarchive-write-groups ()
+  (with-temp-file (expand-file-name (concat "groups-" nnwarchive-address)
+                                   nnwarchive-directory)
+    (prin1 nnwarchive-groups (current-buffer))))
+
+(defun nnwarchive-init (server)
+  "Initialize buffers and such."
+  (let ((type (intern server)) (defs nnwarchive-type-definition) def)
+    (cond
+     ((equal server "")
+      (setq type nnwarchive-default-type))
+     ((assq type nnwarchive-type-definition) t)
+     (t
+      (setq type nil)
+      (while (setq def (pop defs))
+       (when (equal (cdr (assq 'address (cdr def))) server)
+         (setq defs nil)
+         (setq type (car def))))
+      (unless type
+       (error "Undefined server %s" server))))
+    (setq nnwarchive-type type))
+  (unless (file-exists-p nnwarchive-directory)
+    (gnus-make-directory nnwarchive-directory))
+  (unless (gnus-buffer-live-p nnwarchive-buffer)
+    (setq nnwarchive-buffer
+         (save-excursion
+           (nnheader-set-temp-buffer
+            (format " *nnwarchive %s %s*" nnwarchive-type server)))))
+  (nnwarchive-set-default nnwarchive-type))
+
+(defun nnwarchive-eval (expr)
+  (cond
+   ((consp expr)
+    (cons (nnwarchive-eval (car expr)) (nnwarchive-eval (cdr expr))))
+   ((symbolp expr)
+    (eval expr))
+   (t
+    expr)))
+
+(defun nnwarchive-url (xurl)
+  (mm-with-unibyte-current-buffer
+    (let ((url-confirmation-func 'identity) ;; Some hacks.
+         (url-cookie-multiple-line nil))
+      (cond
+       ((eq (car xurl) 'post)
+       (pop xurl)
+       (mm-url-fetch-form (car xurl) (nnwarchive-eval (cdr xurl))))
+       (t
+       (mm-url-insert (apply 'format (nnwarchive-eval xurl))))))))
+
+(defun nnwarchive-generate-active ()
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnwarchive-groups)
+      (insert (prin1-to-string (car elem))
+             " " (number-to-string (or (cadr elem) 0)) " 1 y\n"))))
+
+(defun nnwarchive-paged (articles)
+  (let (art narts next)
+    (while (setq art (pop articles))
+      (when (and (>= art (or next 0))
+                (not (assq art nnwarchive-headers)))
+       (push art narts)
+       (setq next (+ art nnwarchive-xover-page-size))))
+    narts))
+
+;; egroups
+
+(defun nnwarchive-egroups-list-groups (groups)
+  (save-excursion
+    (let (articles)
+      (set-buffer nnwarchive-buffer)
+      (dolist (group groups)
+       (erase-buffer)
+       (nnwarchive-url nnwarchive-xover-last-url)
+       (goto-char (point-min))
+       (when (re-search-forward "of \\([0-9]+\\)[ \t\n\r]*</title>" nil t)
+         (setq articles (string-to-number (match-string 1))))
+       (let ((elem (assoc group nnwarchive-groups)))
+         (if elem
+             (setcar (cdr elem) articles)
+           (push (list group articles "") nnwarchive-groups)))
+       (setq nnwarchive-headers (cdr (assoc group nnwarchive-headers-cache)))
+       (nnwarchive-egroups-xover group)
+       (let ((elem (assoc group nnwarchive-headers-cache)))
+         (if elem
+             (setcdr elem nnwarchive-headers)
+           (push (cons group nnwarchive-headers) nnwarchive-headers-cache)))))))
+
+(defun nnwarchive-egroups-list ()
+  (let ((case-fold-search t)
+       group description elem articles)
+    (goto-char (point-min))
+    (while
+       (re-search-forward "href=\"/group/\\([^/\"\> ]+\\)" nil t)
+      (setq group (match-string 1)
+           description (match-string 2))
+      (if (setq elem (assoc group nnwarchive-groups))
+         (setcar (cdr elem) 0)
+       (push (list group articles description) nnwarchive-groups))))
+  t)
+
+(defun nnwarchive-egroups-xover (group)
+  (let (article subject from date)
+    (goto-char (point-min))
+    (while (re-search-forward
+           "<a href=\"/group/\\([^/]+\\)/\\([0-9]+\\)[^>]+>\\([^<]+\\)<"
+           nil t)
+      (setq group  (match-string 1)
+           article (string-to-number (match-string 2))
+           subject (match-string 3))
+      (forward-line 1)
+      (unless (assq article nnwarchive-headers)
+       (if (looking-at "<td[^>]+><font[^>]+>\\([^<]+\\)</font>")
+           (setq from (match-string 1)))
+       (forward-line 1)
+       (if (looking-at "<td[^>]+><font[^>]+>\\([^<]+\\)</font>")
+           (setq date (identity (match-string 1))))
+       (push (cons
+              article
+              (make-full-mail-header
+               article
+               (mm-url-decode-entities-string subject)
+               (mm-url-decode-entities-string from)
+               date
+               (concat "<" group "%"
+                       (number-to-string article)
+                       "@egroup.com>")
+               ""
+               0 0 "")) nnwarchive-headers))))
+  nnwarchive-headers)
+
+(defun nnwarchive-egroups-article (group articles)
+  (goto-char (point-min))
+  (if (search-forward "<pre>" nil t)
+      (delete-region (point-min) (point)))
+  (goto-char (point-max))
+  (if (search-backward "</pre>" nil t)
+      (delete-region (point) (point-max)))
+  (goto-char (point-min))
+  (while (re-search-forward "<a[^>]+>\\([^<]+\\)</a>" nil t)
+    (replace-match "\\1"))
+  (mm-url-decode-entities)
+  (buffer-string))
+
+(defun nnwarchive-egroups-xover-files (group articles)
+  (let (aux auxs)
+    (setq auxs (nnwarchive-paged (sort articles '<)))
+    (while (setq aux (pop auxs))
+      (goto-char (point-max))
+      (nnwarchive-url nnwarchive-xover-url))
+    (if nnwarchive-xover-dissect
+       (nnwarchive-egroups-xover group))))
+
+;; mail-archive
+
+(defun nnwarchive-mail-archive-list-groups (groups)
+  (save-excursion
+    (let (articles)
+      (set-buffer nnwarchive-buffer)
+      (dolist (group groups)
+       (erase-buffer)
+       (nnwarchive-url nnwarchive-xover-last-url)
+       (goto-char (point-min))
+       (when (re-search-forward "msg\\([0-9]+\\)\\.html" nil t)
+         (setq articles (1+ (string-to-number (match-string 1)))))
+       (let ((elem (assoc group nnwarchive-groups)))
+         (if elem
+             (setcar (cdr elem) articles)
+           (push (list group articles "") nnwarchive-groups)))
+       (setq nnwarchive-headers (cdr (assoc group nnwarchive-headers-cache)))
+       (nnwarchive-mail-archive-xover group)
+       (let ((elem (assoc group nnwarchive-headers-cache)))
+         (if elem
+             (setcdr elem nnwarchive-headers)
+           (push (cons group nnwarchive-headers)
+                 nnwarchive-headers-cache)))))))
+
+(defun nnwarchive-mail-archive-list ()
+  (let ((case-fold-search t)
+       group description elem articles)
+    (goto-char (point-min))
+    (while (re-search-forward "<a href=\"\\([^/]+\\)/\">\\([^>]+\\)<" nil t)
+      (setq group (match-string 1)
+           description (match-string 2))
+      (forward-line 1)
+      (setq articles 0)
+      (if (setq elem (assoc group nnwarchive-groups))
+         (setcar (cdr elem) articles)
+       (push (list group articles description) nnwarchive-groups))))
+  t)
+
+(defun nnwarchive-mail-archive-xover (group)
+  (let (article subject from date)
+    (goto-char (point-min))
+    (while (re-search-forward
+           "<A[^>]*HREF=\"msg\\([0-9]+\\)\\.html[^>]+>\\([^<]+\\)<"
+           nil t)
+      (setq article (1+ (string-to-number (match-string 1)))
+           subject (match-string 2))
+      (forward-line 1)
+      (unless (assq article nnwarchive-headers)
+       (if (looking-at "<UL><LI><EM>From</EM>: *\\([^<]*[^< ]\\) *&lt;\\([^&]+\\)&gt;")
+           (progn
+             (setq from (match-string 1)
+                   date (identity (match-string 2))))
+         (setq from "" date ""))
+       (push (cons
+              article
+              (make-full-mail-header
+               article
+               (mm-url-decode-entities-string subject)
+               (mm-url-decode-entities-string from)
+               date
+               (format "<%05d%%%s>\n" (1- article) group)
+               ""
+               0 0 "")) nnwarchive-headers))))
+  nnwarchive-headers)
+
+(defun nnwarchive-mail-archive-xover-files (group articles)
+  (unless nnwarchive-headers
+    (erase-buffer)
+    (nnwarchive-url nnwarchive-xover-last-url)
+    (goto-char (point-min))
+    (nnwarchive-mail-archive-xover group))
+  (let ((minart (apply 'min articles))
+       (min (apply 'min (mapcar 'car nnwarchive-headers)))
+       (aux 2))
+    (while (> min minart)
+      (erase-buffer)
+      (nnwarchive-url nnwarchive-xover-url)
+      (nnwarchive-mail-archive-xover group)
+      (setq min (apply 'min (mapcar 'car nnwarchive-headers))))))
+
+(defvar nnwarchive-caesar-translation-table nil
+  "Modified rot13 table. tr/@A-Z[a-z/N-Z[@A-Mn-za-m/.")
+
+(defun nnwarchive-make-caesar-translation-table ()
+  "Create modified rot13 table. tr/@A-Z[a-z/N-Z[@A-Mn-za-m/."
+  (let ((i -1)
+       (table (make-string 256 0))
+       (a (mm-char-int ?a))
+       (A (mm-char-int ?A)))
+    (while (< (incf i) 256)
+      (aset table i i))
+    (concat
+     (substring table 0 (1- A))
+     (substring table (+ A 13) (+ A 27))
+     (substring table (1- A) (+ A 13))
+     (substring table (+ A 27) a)
+     (substring table (+ a 13) (+ a 26))
+     (substring table a (+ a 13))
+     (substring table (+ a 26) 255))))
+
+(defun nnwarchive-from-r13 (from-r13)
+  (when from-r13
+    (with-temp-buffer
+      (insert from-r13)
+      (let ((message-caesar-translation-table
+            (or nnwarchive-caesar-translation-table
+                (setq nnwarchive-caesar-translation-table
+                      (nnwarchive-make-caesar-translation-table)))))
+       (message-caesar-region (point-min) (point-max))
+       (buffer-string)))))
+
+(defun nnwarchive-mail-archive-article (group article)
+  (let (p refs url mime e
+         from subject date id
+         done
+         (case-fold-search t))
+    (save-restriction
+      (goto-char (point-min))
+      (when (search-forward "X-Head-End" nil t)
+       (beginning-of-line)
+       (narrow-to-region (point-min) (point))
+       (mm-url-decode-entities)
+       (goto-char (point-min))
+       (while (search-forward "<!--X-" nil t)
+         (replace-match ""))
+       (goto-char (point-min))
+       (while (search-forward " -->" nil t)
+         (replace-match ""))
+       (setq from
+             (or (mail-fetch-field "from")
+                 (nnwarchive-from-r13
+                  (mail-fetch-field "from-r13"))))
+       (setq date (mail-fetch-field "date"))
+       (setq id (mail-fetch-field "message-id"))
+       (setq subject (mail-fetch-field "subject"))
+       (goto-char (point-max))
+       (widen))
+      (when (search-forward "<ul>" nil t)
+       (forward-line)
+       (delete-region (point-min) (point))
+       (search-forward "</ul>" nil t)
+       (end-of-line)
+       (narrow-to-region (point-min) (point))
+       (mm-url-remove-markup)
+       (mm-url-decode-entities)
+       (goto-char (point-min))
+       (delete-blank-lines)
+       (when from
+         (message-remove-header "from")
+         (goto-char (point-max))
+         (insert "From: " from "\n"))
+       (when subject
+         (message-remove-header "subject")
+         (goto-char (point-max))
+         (insert "Subject: " subject "\n"))
+       (when id
+         (goto-char (point-max))
+         (insert "X-Message-ID: <" id ">\n"))
+       (when date
+         (message-remove-header "date")
+         (goto-char (point-max))
+         (insert "Date: " date "\n"))
+       (goto-char (point-max))
+       (widen)
+       (insert "\n"))
+      (setq p (point))
+      (when (search-forward "X-Body-of-Message" nil t)
+       (forward-line)
+       (delete-region p (point))
+       (search-forward "X-Body-of-Message-End" nil t)
+       (beginning-of-line)
+       (save-restriction
+         (narrow-to-region p (point))
+         (goto-char (point-min))
+         (if (> (skip-chars-forward "\040\n\r\t") 0)
+             (delete-region (point-min) (point)))
+         (while (not (eobp))
+           (cond
+            ((looking-at "<PRE>\r?\n?")
+             (delete-region (match-beginning 0) (match-end 0))
+             (setq p (point))
+             (when (search-forward "</PRE>" nil t)
+               (delete-region (match-beginning 0) (match-end 0))
+               (save-restriction
+                 (narrow-to-region p (point))
+                 (mm-url-remove-markup)
+                 (mm-url-decode-entities)
+                 (goto-char (point-max)))))
+            ((looking-at "<P><A HREF=\"\\([^\"]+\\)")
+             (setq url (match-string 1))
+             (delete-region (match-beginning 0)
+                            (progn (forward-line) (point)))
+             ;; I hate to download the url encode it, then immediately
+             ;; decode it.
+             (insert "<#external"
+                     " type="
+                     (or (and url
+                              (string-match "\\.[^\\.]+$" url)
+                              (mailcap-extension-to-mime
+                               (match-string 0 url)))
+                         "application/octet-stream")
+                     (format " url=\"http://www.mail-archive.com/%s/%s\""
+                             group url)
+                     ">\n"
+                     "<#/external>")
+             (setq mime t))
+            (t
+             (setq p (point))
+             (insert "<#part type=\"text/html\" disposition=inline>")
+             (goto-char
+              (if (re-search-forward
+                   "[\040\n\r\t]*<PRE>\\|[\040\n\r\t]*<P><A HREF=\""
+                   nil t)
+                  (match-beginning 0)
+                (point-max)))
+             (insert "<#/part>")
+             (setq mime t)))
+           (setq p (point))
+           (if (> (skip-chars-forward "\040\n\r\t") 0)
+               (delete-region p (point))))
+         (goto-char (point-max))))
+      (setq p (point))
+      (when (search-forward "X-References-End" nil t)
+       (setq e (point))
+       (beginning-of-line)
+       (search-backward "X-References" p t)
+       (while (re-search-forward "msg\\([0-9]+\\)\\.html" e t)
+         (push (concat "<" (match-string 1) "%" group ">") refs)))
+      (delete-region p (point-max))
+      (goto-char (point-min))
+      (insert (format "Message-ID: <%05d%%%s>\n" (1- article) group))
+      (when refs
+       (insert "References:")
+       (while refs
+         (insert " " (pop refs)))
+       (insert "\n"))
+      (when mime
+       (unless (looking-at "$")
+         (search-forward "\n\n" nil t)
+         (forward-line -1))
+       (narrow-to-region (point) (point-max))
+       (insert "MIME-Version: 1.0\n"
+               (prog1
+                   (mml-generate-mime)
+                 (delete-region (point-min) (point-max))))
+       (widen)))
+    (buffer-string)))
+
+(provide 'nnwarchive)
+
+;;; nnwarchive.el ends here
index cbb04ed..d71f595 100644 (file)
@@ -1,7 +1,8 @@
 ;;; nnweb.el --- retrieving articles via web search engines
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;; This file is part of GNU Emacs.
 
 ;;; Commentary:
 
-;; Note: You need to have `url' and `w3' installed for this
-;; backend to work.
+;; Note: You need to have `w3' installed for some functions to work.
 
 ;;; Code:
 
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
 
 (require 'nnoo)
 (require 'message)
 (require 'gnus-util)
 (require 'gnus)
-(require 'w3)
-(require 'url)
 (require 'nnmail)
-(ignore-errors
-  (require 'w3-forms))
+(require 'mm-util)
+(require 'mm-url)
+(eval-and-compile
+  (ignore-errors
+    (require 'url)))
+(autoload 'w3-parse-buffer "w3-parse")
 
 (nnoo-declare nnweb)
 
 (defvoo nnweb-directory (nnheader-concat gnus-directory "nnweb/")
   "Where nnweb will save its files.")
 
-(defvoo nnweb-type 'dejanews
-  "What search engine type is being used.")
-
-(defvoo nnweb-type-definition
-  '((dejanews
-     (article . nnweb-dejanews-wash-article)
-     (map . nnweb-dejanews-create-mapping)
-     (search . nnweb-dejanews-search)
-     (address . "http://x8.dejanews.com/dnquery.xp")
-     (identifier . nnweb-dejanews-identity))
-    (dejanewsold
-     (article . nnweb-dejanews-wash-article)
-     (map . nnweb-dejanews-create-mapping)
-     (search . nnweb-dejanewsold-search)
-     (address . "http://x8.dejanews.com/dnquery.xp")
-     (identifier . nnweb-dejanews-identity))
-    (reference
-     (article . nnweb-reference-wash-article)
-     (map . nnweb-reference-create-mapping)
-     (search . nnweb-reference-search)
-     (address . "http://www.reference.com/cgi-bin/pn/go")
-     (identifier . identity))
-    (altavista
-     (article . nnweb-altavista-wash-article)
-     (map . nnweb-altavista-create-mapping)
-     (search . nnweb-altavista-search)
-     (address . "http://www.altavista.digital.com/cgi-bin/query")
-     (id . "/cgi-bin/news?id@%s")
-     (identifier . identity)))
+(defvoo nnweb-type 'google
+  "What search engine type is being used.
+Valid types include `google', `dejanews', and `gmane'.")
+
+(defvar nnweb-type-definition
+  '((google
+     (article . ignore)
+     (id . "http://groups.google.com/groups?selm=%s&output=gplain")
+     (reference . identity)
+     (map . nnweb-google-create-mapping)
+     (search . nnweb-google-search)
+     (address . "http://groups.google.com/groups")
+     (identifier . nnweb-google-identity))
+    (dejanews ;; alias of google
+     (article . ignore)
+     (id . "http://groups.google.com/groups?selm=%s&output=gplain")
+     (reference . identity)
+     (map . nnweb-google-create-mapping)
+     (search . nnweb-google-search)
+     (address . "http://groups.google.com/groups")
+     (identifier . nnweb-google-identity))
+    (gmane
+     (article . nnweb-gmane-wash-article)
+     (id . "http://gmane.org/view.php?group=%s")
+     (reference . identity)
+     (map . nnweb-gmane-create-mapping)
+     (search . nnweb-gmane-search)
+     (address . "http://gmane.org/")
+     (identifier . nnweb-gmane-identity)))
   "Type-definition alist.")
 
 (defvoo nnweb-search nil
-  "Search string to feed to DejaNews.")
+  "Search string to feed to Google.")
 
 (defvoo nnweb-max-hits 999
   "Maximum number of hits to display.")
     (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)
   (nnweb-possibly-change-server group server)
-  (setq nnweb-hashtb (gnus-make-hashtable 4095))
+  (if nnweb-ephemeral-p
+      (setq nnweb-hashtb (gnus-make-hashtable 4095)))
   (funcall (nnweb-definition 'map))
   (unless nnweb-ephemeral-p
     (nnweb-write-active)
   (when (and group
             (not (equal group nnweb-group))
             (not nnweb-ephemeral-p))
+    (setq nnweb-group group
+         nnweb-articles nil)
     (let ((info (assoc group nnweb-group-alist)))
-      (setq nnweb-group group)
-      (setq nnweb-type (nth 2 info))
-      (setq nnweb-search (nth 3 info))
-      (unless dont-check
-       (nnweb-read-overview group))))
+      (when info
+       (setq nnweb-type (nth 2 info))
+       (setq nnweb-search (nth 3 info))
+       (unless dont-check
+         (nnweb-read-overview group)))))
   (cond
    ((not nnweb-articles)
     (nnheader-report 'nnweb "No matching articles"))
     (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
+                      (mm-url-insert url)))
                (and (stringp article)
                     (nnweb-definition 'id t)
                     (let ((fetch (nnweb-definition 'id))
-                          art)
+                          art active)
                       (when (string-match "^<\\(.*\\)>$" article)
                         (setq art (match-string 1 article)))
-                      (and fetch
-                           art
-                           (nnweb-fetch-url
-                            (format fetch article))))))
+                      (when (and fetch art)
+                        (setq url (format fetch art))
+                        (mm-with-unibyte-current-buffer
+                          (mm-url-insert url))
+                        (if (nnweb-definition 'reference t)
+                            (setq article
+                                  (funcall (nnweb-definition
+                                            'reference) article)))))))
        (unless nnheader-callback-function
-         (funcall (nnweb-definition 'article))
-         (nnweb-decode-entities))
+         (funcall (nnweb-definition 'article)))
        (nnheader-report 'nnweb "Fetched article %s" article)
-       t))))
+       (cons group (and (numberp article) article))))))
 
 (deffoo nnweb-close-server (&optional server)
   (when (and (nnweb-server-opened server)
     t))
 
 (deffoo nnweb-request-update-info (group info &optional server)
-  (nnweb-possibly-change-server group server)
-  ;;(setcar (cddr info) nil)
-  )
+  (nnweb-possibly-change-server group server))
 
 (deffoo nnweb-asynchronous-p ()
-  t)
+  nil)
 
 (deffoo nnweb-request-create-group (group &optional server args)
   (nnweb-possibly-change-server nil server)
 
 (deffoo nnweb-request-delete-group (group &optional force server)
   (nnweb-possibly-change-server group server)
-  (gnus-delete-assoc group nnweb-group-alist)
+  (gnus-pull group nnweb-group-alist t)
+  (nnweb-write-active)
   (gnus-delete-file (nnweb-overview-file group))
   t)
 
 (defun nnweb-read-overview (group)
   "Read the overview of GROUP and build the map."
   (when (file-exists-p (nnweb-overview-file group))
-    (nnheader-temp-write nil
+    (mm-with-unibyte-buffer
       (nnheader-insert-file-contents (nnweb-overview-file group))
       (goto-char (point-min))
       (let (header)
 
 (defun nnweb-write-overview (group)
   "Write the overview file for GROUP."
-  (nnheader-temp-write (nnweb-overview-file group)
+  (with-temp-file (nnweb-overview-file group)
     (let ((articles nnweb-articles))
       (while articles
        (nnheader-insert-nov (cadr (pop articles)))))))
 
 (defun nnweb-write-active ()
   "Save the active file."
-  (nnheader-temp-write (nnheader-concat nnweb-directory "active")
+  (gnus-make-directory nnweb-directory)
+  (with-temp-file (nnheader-concat nnweb-directory "active")
     (prin1 `(setq nnweb-group-alist ',nnweb-group-alist) (current-buffer))))
 
 (defun nnweb-read-active ()
       (nnweb-open-server server)))
   (unless nnweb-group-alist
     (nnweb-read-active))
+  (unless nnweb-hashtb
+    (setq nnweb-hashtb (gnus-make-hashtable 4095)))
   (when group
     (when (and (not nnweb-ephemeral-p)
-              (not (equal group nnweb-group)))
+              (equal group nnweb-group))
       (nnweb-request-group group nil t))))
 
 (defun nnweb-init (server)
   (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))))))
-
-(defun nnweb-fetch-url (url)
-  (save-excursion
-    (if (not nnheader-callback-function)
-       (let ((buf (current-buffer)))
-         (save-excursion
-           (set-buffer nnweb-buffer)
-           (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)))
-
-(defun nnweb-callback (buffer callback)
-  (when (gnus-buffer-live-p url-working-buffer)
-    (save-excursion
-      (set-buffer url-working-buffer)
-      (funcall (nnweb-definition 'article))
-      (nnweb-decode-entities)
-      (set-buffer buffer)
-      (goto-char (point-max))
-      (insert-buffer-substring url-working-buffer))
-    (funcall callback t)
-    (gnus-kill-buffer url-working-buffer)))
-
-(defun nnweb-url-retrieve-asynch (url callback &rest data)
-  (let ((url-request-method "GET")
-       (old-asynch url-be-asynchronous)
-       (url-request-data nil)
-       (url-request-extra-headers nil)
-       (url-working-buffer (generate-new-buffer-name " *nnweb*")))
-    (setq-default url-be-asynchronous t)
-    (save-excursion
-      (set-buffer (get-buffer-create url-working-buffer))
-      (setq url-current-callback-data data
-           url-be-asynchronous t
-           url-current-callback-func callback)
-      (url-retrieve url))
-    (setq-default url-be-asynchronous old-asynch)))
-
-(defun nnweb-encode-www-form-urlencoded (pairs)
-  "Return PAIRS encoded for forms."
-  (mapconcat
-   (function
-    (lambda (data)
-      (concat (w3-form-encode-xwfu (car data)) "="
-             (w3-form-encode-xwfu (cdr data)))))
-   pairs "&"))
-
-(defun nnweb-fetch-form (url pairs)
-  (let ((url-request-data (nnweb-encode-www-form-urlencoded pairs))
-       (url-request-method "POST")
-       (url-request-extra-headers
-        '(("Content-type" . "application/x-www-form-urlencoded"))))
-    (url-insert-file-contents url)
-    (setq buffer-file-name nil))
-  t)
-
-(defun nnweb-decode-entities ()
-  (goto-char (point-min))
-  (while (re-search-forward "&\\([a-z]+\\);" nil t)
-    (replace-match (char-to-string (or (cdr (assq (intern (match-string 1))
-                                                 w3-html-entities))
-                                      ?#))
-                  t t)))
-
-(defun nnweb-remove-markup ()
-  (goto-char (point-min))
-  (while (search-forward "<!--" nil t)
-    (delete-region (match-beginning 0)
-                  (or (search-forward "-->" nil t)
-                      (point-max))))
-  (goto-char (point-min))
-  (while (re-search-forward "<[^>]+>" nil t)
-    (replace-match "" t t)))
+           (mm-with-unibyte
+             (nnheader-set-temp-buffer
+              (format " *nnweb %s %s %s*"
+                      nnweb-type nnweb-search server))
+             (current-buffer))))))
 
 ;;;
-;;; DejaNews functions.
+;;; Deja bought by google.com
 ;;;
 
-(defun nnweb-dejanews-create-mapping ()
-  "Perform the search and create an number-to-url alist."
+(defun nnweb-google-wash-article ()
+  (let ((case-fold-search t) url)
+    (goto-char (point-min))
+    (re-search-forward "^<pre>" nil t)
+    (narrow-to-region (point-min) (point))
+    (search-backward "<table " nil t 2)
+    (delete-region (point-min) (point))
+    (if (re-search-forward "Search Result [0-9]+" nil t)
+       (replace-match ""))
+    (if (re-search-forward "View complete thread ([0-9]+ articles?)" nil t)
+       (replace-match ""))
+    (goto-char (point-min))
+    (while (search-forward "<br>" nil t)
+      (replace-match "\n"))
+    (mm-url-remove-markup)
+    (goto-char (point-min))
+    (while (re-search-forward "^[ \t]*\n" nil t)
+      (replace-match ""))
+    (goto-char (point-max))
+    (insert "\n")
+    (widen)
+    (narrow-to-region (point) (point-max))
+    (search-forward "</pre>" nil t)
+    (delete-region (point) (point-max))
+    (mm-url-remove-markup)
+    (widen)))
+
+(defun nnweb-google-parse-1 (&optional Message-ID)
+  (let ((i 0)
+       (case-fold-search t)
+       (active (cadr (assoc nnweb-group nnweb-group-alist)))
+       Subject Score Date Newsgroups From
+       map url mid)
+    (unless active
+      (push (list nnweb-group (setq active (cons 1 0))
+                 nnweb-type nnweb-search)
+           nnweb-group-alist))
+    ;; Go through all the article hits on this page.
+    (goto-char (point-min))
+    (while (re-search-forward
+           "a href=/groups\\(\\?[^ \">]*selm=\\([^ &\">]+\\)\\)" nil t)
+      (setq mid (match-string 2)
+           url (format
+                "http://groups.google.com/groups?selm=%s&output=gplain" mid))
+      (narrow-to-region (search-forward ">" nil t)
+                       (search-forward "</a>" nil t))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities)
+      (setq Subject (buffer-string))
+      (goto-char (point-max))
+      (widen)
+      (forward-line 2)
+      (when (looking-at "<br><font[^>]+>")
+       (goto-char (match-end 0)))
+      (if (not (looking-at "<a[^>]+>"))
+         (skip-chars-forward " \t")
+       (narrow-to-region (point)
+                         (search-forward "</a>" nil t))
+       (mm-url-remove-markup)
+       (mm-url-decode-entities)
+       (setq Newsgroups (buffer-string))
+       (goto-char (point-max))
+       (widen)
+       (skip-chars-forward "- \t"))
+      (when (looking-at
+            "\\([0-9]+\\)[/ ]\\([A-Za-z]+\\)[/ ]\\([0-9]+\\)[ \t]*by[ \t]*\\([^<]*\\) - <a")
+       (setq From (match-string 4)
+             Date (format "%s %s 00:00:00 %s"
+                          (match-string 2) (match-string 1)
+                          (match-string 3))))
+      (forward-line 1)
+      (incf i)
+      (unless (nnweb-get-hashtb url)
+       (push
+        (list
+         (incf (cdr active))
+         (make-full-mail-header
+          (cdr active) (if Newsgroups
+                           (concat  "(" Newsgroups ") " Subject)
+                         Subject)
+          From Date (or Message-ID mid)
+          nil 0 0 url))
+        map)
+       (nnweb-set-hashtb (cadar map) (car map))))
+    map))
+
+(defun nnweb-google-reference (id)
+  (let ((map (nnweb-google-parse-1 id)) header)
+    (setq nnweb-articles
+         (nconc nnweb-articles map))
+    (when (setq header (cadar map))
+      (mm-with-unibyte-current-buffer
+       (mm-url-insert (mail-header-xref header)))
+      (caar map))))
+
+(defun nnweb-google-create-mapping ()
+  "Perform the search and create a number-to-url alist."
   (save-excursion
     (set-buffer nnweb-buffer)
     (erase-buffer)
     (when (funcall (nnweb-definition 'search) nnweb-search)
-      (let ((i 0)
-           (more t)
-           (case-fold-search t)
-           (active (or (cadr (assoc nnweb-group nnweb-group-alist))
-                       (cons 1 0)))
-           Subject (Score "0") Date Newsgroup Author
-           map url)
+      (let ((more t)
+           (i 0))
        (while more
-         ;; Go through all the article hits on this page.
-         (goto-char (point-min))
-         (nnweb-decode-entities)
+         (setq nnweb-articles
+               (nconc nnweb-articles (nnweb-google-parse-1)))
+         ;; Check if there are more articles to fetch
          (goto-char (point-min))
-         (while (re-search-forward "^ <P>\n" nil t)
-           (narrow-to-region
-            (point)
-            (cond ((re-search-forward "^ <P>\n" nil t)
-                   (match-beginning 0))
-                  ((search-forward "\n\n" nil t)
-                   (point))
-                  (t
-                   (point-max))))
-           (goto-char (point-min))
-           (looking-at ".*HREF=\"\\([^\"]+\\)\"\\(.*\\)")
-           (setq url (match-string 1))
-           (let ((begin (point)))
-             (nnweb-remove-markup)
-             (goto-char begin)
-             (while (search-forward "\t" nil t)
-               (replace-match " "))
-             (goto-char begin)
-             (end-of-line)
-             (setq Subject (buffer-substring begin (point)))
-             (if (re-search-forward
-                  "^ Newsgroup: \\(.*\\)\n Posted on \\([0-9/]+\\) by \\(.*\\)$" nil t)
-                 (setq Newsgroup (match-string 1)
-                       Date (match-string 2)
-                       Author (match-string 3))))
-           (widen)
-           (incf i)
-           (unless (nnweb-get-hashtb url)
-             (push
-              (list
-               (incf (cdr active))
-               (make-full-mail-header
-                (cdr active) Subject Author Date
-                (concat "<" (nnweb-identifier url) "@dejanews>")
-                nil 0 (string-to-int Score) url))
-              map)
-             (nnweb-set-hashtb (cadar map) (car map))))
-         ;; See whether there is a "Get next 20 hits" button here.
+         (incf i 100)
          (if (or (not (re-search-forward
-                       "HREF=\"\\([^\"]+\\)\"[<>b]+Next result" nil t))
+                       "<td nowrap><a href=\\([^>]+\\).*<span class=b>Next</span>" nil t))
                  (>= i nnweb-max-hits))
              (setq more nil)
-           ;; Yup -- fetch it.
-           (setq more (match-string 1))
-           (erase-buffer)
-           (url-insert-file-contents more)))
+           ;; Yup, there are more articles
+           (setq more (concat "http://groups.google.com" (match-string 1)))
+           (when more
+             (erase-buffer)
+             (mm-url-insert more))))
        ;; Return the articles in the right order.
        (setq nnweb-articles
-             (sort (nconc nnweb-articles map) 'car-less-than-car))))))
-
-(defun nnweb-dejanews-wash-article ()
-  (let ((case-fold-search t))
-    (goto-char (point-min))
-    (re-search-forward "<PRE>" nil t)
-    (delete-region (point-min) (point))
-    (re-search-forward "</PRE>" nil t)
-    (delete-region (point) (point-max))
-    (nnweb-remove-markup)
-    (goto-char (point-min))
-    (while (and (looking-at " *$")
-               (not (eobp)))
-      (gnus-delete-line))
-    (while (looking-at "\\(^[^ ]+:\\) *")
-      (replace-match "\\1 " t)
-      (forward-line 1))
-    (when (re-search-forward "\n\n+" nil t)
-      (replace-match "\n" t t))
-    (goto-char (point-min))
-    (when (search-forward "[More Headers]" nil t)
-      (replace-match "" t t))))
-
-(defun nnweb-dejanews-search (search)
-  (nnweb-fetch-form
-   (nnweb-definition 'address)
-   `(("query" . ,search)
-     ("defaultOp" . "AND")
-     ("svcclass" . "dncurrent")
-     ("maxhits" . "100")
-     ("format" . "verbose2")
-     ("threaded" . "0")
-     ("showsort" . "date")
-     ("agesign" . "1")
-     ("ageweight" . "1")))
-  t)
+             (sort nnweb-articles 'car-less-than-car))))))
 
-(defun nnweb-dejanewsold-search (search)
-  (nnweb-fetch-form
-   (nnweb-definition 'address)
-   `(("query" . ,search)
-     ("defaultOp" . "AND")
-     ("svcclass" . "dnold")
-     ("maxhits" . "100")
-     ("format" . "verbose2")
-     ("threaded" . "0")
-     ("showsort" . "date")
-     ("agesign" . "1")
-     ("ageweight" . "1")))
+(defun nnweb-google-search (search)
+  (mm-url-insert
+   (concat
+    (nnweb-definition 'address)
+    "?"
+    (mm-url-encode-www-form-urlencoded
+     `(("q" . ,search)
+       ("num". "100")
+       ("hq" . "")
+       ("hl" . "")
+       ("lr" . "")
+       ("safe" . "off")
+       ("sites" . "groups")))))
   t)
 
-(defun nnweb-dejanews-identity (url)
+(defun nnweb-google-identity (url)
   "Return an unique identifier based on URL."
-  (if (string-match "recnum=\\([0-9]+\\)" url)
+  (if (string-match "selm=\\([^ &>]+\\)" url)
       (match-string 1 url)
     url))
 
 ;;;
-;;; InReference
+;;; gmane.org
 ;;;
-
-(defun nnweb-reference-create-mapping ()
-  "Perform the search and create an number-to-url alist."
+(defun nnweb-gmane-create-mapping ()
+  "Perform the search and create a number-to-url alist."
   (save-excursion
     (set-buffer nnweb-buffer)
     (erase-buffer)
     (when (funcall (nnweb-definition 'search) nnweb-search)
-      (let ((i 0)
-           (more t)
+      (let ((more t)
            (case-fold-search t)
            (active (or (cadr (assoc nnweb-group nnweb-group-alist))
                        (cons 1 0)))
-           Subject Score Date Newsgroups From Message-ID
-           map url)
-       (while more
-         ;; Go through all the article hits on this page.
-         (goto-char (point-min))
-         (search-forward "</pre><hr>" nil t)
-         (delete-region (point-min) (point))
-                                       ;(nnweb-decode-entities)
-         (goto-char (point-min))
-         (while (re-search-forward "^ +[0-9]+\\." nil t)
-           (narrow-to-region
-            (point)
-            (if (re-search-forward "^$" nil t)
-                (match-beginning 0)
-              (point-max)))
-           (goto-char (point-min))
-           (when (looking-at ".*href=\"\\([^\"]+\\)\"")
-             (setq url (match-string 1)))
-           (nnweb-remove-markup)
-           (goto-char (point-min))
-           (while (search-forward "\t" nil t)
-             (replace-match " "))
-           (goto-char (point-min))
-           (while (re-search-forward "^\\([^:]+\\): \\(.*\\)$" nil t)
-             (set (intern (match-string 1)) (match-string 2)))
-           (widen)
-           (search-forward "</pre>" nil t)
-           (incf i)
-           (unless (nnweb-get-hashtb url)
-             (push
-              (list
-               (incf (cdr active))
-               (make-full-mail-header
-                (cdr active) (concat  "(" Newsgroups ") " Subject) From Date
-                Message-ID
-                nil 0 (string-to-int Score) url))
-              map)
-             (nnweb-set-hashtb (cadar map) (car map))))
-         (setq more nil))
+           subject group url
+           map)
+         ;; Remove stuff from the beginning of results
+       (goto-char (point-min))
+       (search-forward "Search Results</h1><ul>" nil t)
+       (delete-region (point-min) (point))
+       (goto-char (point-min))
+       ;; Iterate over the actual hits
+       (while (re-search-forward ".*href=\"\\([^\"]+\\)\">\\(.*\\)" nil t)
+           (setq url (concat "http://gmane.org/" (match-string 1)))
+           (setq subject (match-string 2))
+         (unless (nnweb-get-hashtb url)
+           (push
+            (list
+             (incf (cdr active))
+             (make-full-mail-header
+              (cdr active) (concat  "(" group ") " subject) nil nil
+              nil nil 0 0 url))
+            map)
+           (nnweb-set-hashtb (cadar map) (car map))))
        ;; Return the articles in the right order.
        (setq nnweb-articles
              (sort (nconc nnweb-articles map) 'car-less-than-car))))))
 
-(defun nnweb-reference-wash-article ()
+(defun nnweb-gmane-wash-article ()
   (let ((case-fold-search t))
     (goto-char (point-min))
-    (re-search-forward "^</center><hr>" nil t)
+    (re-search-forward "<!--X-Head-of-Message-->" nil t)
     (delete-region (point-min) (point))
-    (search-forward "<pre>" nil t)
-    (forward-line -1)
-    (let ((body (point-marker)))
-      (search-forward "</pre>" nil t)
-      (delete-region (point) (point-max))
-      (nnweb-remove-markup)
-      (goto-char (point-min))
-      (while (looking-at " *$")
-       (gnus-delete-line))
-      (narrow-to-region (point-min) body)
-      (while (and (re-search-forward "^$" nil t)
-                 (not (eobp)))
-       (gnus-delete-line))
-      (goto-char (point-min))
-      (while (looking-at "\\(^[^ ]+:\\) *")
-       (replace-match "\\1 " t)
-       (forward-line 1))
-      (goto-char (point-min))
-      (when (re-search-forward "^References:" nil t)
-       (narrow-to-region
-        (point) (if (re-search-forward "^$\\|^[^:]+:" nil t)
-                    (match-beginning 0)
-                  (point-max)))
-       (goto-char (point-min))
-       (while (not (eobp))
-         (unless (looking-at "References")
-           (insert "\t")
-           (forward-line 1)))
-       (goto-char (point-min))
-       (while (search-forward "," nil t)
-         (replace-match " " t t)))
-      (widen)
-      (set-marker body nil))))
+    (goto-char (point-min))
+    (while (looking-at "^<li><em>\\([^ ]+\\)</em>.*</li>")
+      (replace-match "\\1\\2" t)
+      (forward-line 1))
+    (mm-url-remove-markup)))
 
-(defun nnweb-reference-search (search)
-  (url-insert-file-contents
+(defun nnweb-gmane-search (search)
+  (mm-url-insert
    (concat
     (nnweb-definition 'address)
     "?"
-    (nnweb-encode-www-form-urlencoded
-     `(("search" . "advanced")
-       ("querytext" . ,search)
-       ("subj" . "")
-       ("name" . "")
-       ("login" . "")
-       ("host" . "")
-       ("organization" . "")
-       ("groups" . "")
-       ("keywords" . "")
-       ("choice" . "Search")
-       ("startmonth" . "Jul")
-       ("startday" . "25")
-       ("startyear" . "1996")
-       ("endmonth" . "Aug")
-       ("endday" . "24")
-       ("endyear" . "1996")
-       ("mode" . "Quick")
-       ("verbosity" . "Verbose")
-       ("ranking" . "Relevance")
-       ("first" . "1")
-       ("last" . "25")
-       ("score" . "50")))))
+    (mm-url-encode-www-form-urlencoded
+     `(("query" . ,search)))))
   (setq buffer-file-name nil)
   t)
 
-;;;
-;;; Alta Vista
-;;;
 
-(defun nnweb-altavista-create-mapping ()
-  "Perform the search and create an number-to-url alist."
-  (save-excursion
-    (set-buffer nnweb-buffer)
-    (erase-buffer)
-    (let ((part 0))
-      (when (funcall (nnweb-definition 'search) nnweb-search part)
-       (let ((i 0)
-             (more t)
-             (case-fold-search t)
-             (active (or (cadr (assoc nnweb-group nnweb-group-alist))
-                         (cons 1 0)))
-             subject date from id group
-             map url)
-         (while more
-           ;; Go through all the article hits on this page.
-           (goto-char (point-min))
-           (search-forward "<dt>" nil t)
-           (delete-region (point-min) (match-beginning 0))
-           (goto-char (point-min))
-           (while (search-forward "<dt>" nil t)
-             (replace-match "\n<blubb>"))
-           (nnweb-decode-entities)
-           (goto-char (point-min))
-           (while (re-search-forward "<blubb>.*href=\"\\([^\"]+\\)\"><strong>\\([^>]*\\)</strong></a><dd>\\([^-]+\\)- <b>\\([^<]+\\)<.*href=\"news:\\([^\"]+\\)\">.*\">\\(.+\\)</a><P>"
-                                     nil t)
-             (setq url (match-string 1)
-                   subject (match-string 2)
-                   date (match-string 3)
-                   group (match-string 4)
-                   id (concat "<" (match-string 5) ">")
-                   from (match-string 6))
-             (incf i)
-             (unless (nnweb-get-hashtb url)
-               (push
-                (list
-                 (incf (cdr active))
-                 (make-full-mail-header
-                  (cdr active) (concat  "(" group ") " subject) from date
-                  id nil 0 0 url))
-                map)
-               (nnweb-set-hashtb (cadar map) (car map))))
-           ;; See if we want more.
-           (when (or (not nnweb-articles)
-                     (>= i nnweb-max-hits)
-                     (not (funcall (nnweb-definition 'search)
-                                   nnweb-search (incf part))))
-             (setq more nil)))
-         ;; Return the articles in the right order.
-         (setq nnweb-articles
-               (sort (nconc nnweb-articles map) 'car-less-than-car)))))))
+(defun nnweb-gmane-identity (url)
+  "Return a unique identifier based on URL."
+  (if (string-match "group=\\(.+\\)" url)
+      (match-string 1 url)
+    url))
 
-(defun nnweb-altavista-wash-article ()
-  (goto-char (point-min))
-  (let ((case-fold-search t))
-    (when (re-search-forward "^<strong>" nil t)
-      (delete-region (point-min) (match-beginning 0)))
-    (goto-char (point-min))
-    (while (looking-at "<strong>\\([^ ]+\\) +</strong> +\\(.*\\)$")
-      (replace-match "\\1: \\2" t)
-      (forward-line 1))
-    (when (re-search-backward "^References:" nil t)
-      (narrow-to-region (point) (progn (forward-line 1) (point)))
-      (goto-char (point-min))
-      (while (re-search-forward "<A.*\\?id@\\([^\"]+\\)\">[0-9]+</A>" nil t)
-       (replace-match "&lt;\\1&gt; " t)))
-    (widen)
-    (nnweb-remove-markup)))
+;;;
+;;; General web/w3 interface utility functions
+;;;
 
-(defun nnweb-altavista-search (search &optional part)
-  (url-insert-file-contents
-   (concat
-    (nnweb-definition 'address)
-    "?"
-    (nnweb-encode-www-form-urlencoded
-     `(("pg" . "aq")
-       ("what" . "news")
-       ,@(when part `(("stq" . ,(int-to-string (* part 30)))))
-       ("fmt" . "d")
-       ("q" . ,search)
-       ("r" . "")
-       ("d0" . "")
-       ("d1" . "")))))
-  (setq buffer-file-name nil)
-  t)
+(defun nnweb-insert-html (parse)
+  "Insert HTML based on a w3 parse tree."
+  (if (stringp parse)
+      (insert (nnheader-string-as-multibyte parse))
+    (insert "<" (symbol-name (car parse)) " ")
+    (insert (mapconcat
+            (lambda (param)
+              (concat (symbol-name (car param)) "="
+                      (prin1-to-string
+                       (if (consp (cdr param))
+                           (cadr param)
+                         (cdr param)))))
+            (nth 1 parse)
+            " "))
+    (insert ">\n")
+    (mapcar 'nnweb-insert-html (nth 2 parse))
+    (insert "</" (symbol-name (car parse)) ">\n")))
+
+(defun nnweb-parse-find (type parse &optional maxdepth)
+  "Find the element of TYPE in PARSE."
+  (catch 'found
+    (nnweb-parse-find-1 type parse maxdepth)))
+
+(defun nnweb-parse-find-1 (type contents maxdepth)
+  (when (or (null maxdepth)
+           (not (zerop maxdepth)))
+    (when (consp contents)
+      (when (eq (car contents) type)
+       (throw 'found contents))
+      (when (listp (cdr contents))
+       (dolist (element contents)
+         (when (consp element)
+           (nnweb-parse-find-1 type element
+                               (and maxdepth (1- maxdepth)))))))))
+
+(defun nnweb-parse-find-all (type parse)
+  "Find all elements of TYPE in PARSE."
+  (catch 'found
+    (nnweb-parse-find-all-1 type parse)))
+
+(defun nnweb-parse-find-all-1 (type contents)
+  (let (result)
+    (when (consp contents)
+      (if (eq (car contents) type)
+         (push contents result)
+       (when (listp (cdr contents))
+         (dolist (element contents)
+           (when (consp element)
+             (setq result
+                   (nconc result (nnweb-parse-find-all-1 type element))))))))
+    result))
+
+(defvar nnweb-text)
+(defun nnweb-text (parse)
+  "Return a list of text contents in PARSE."
+  (let ((nnweb-text nil))
+    (nnweb-text-1 parse)
+    (nreverse nnweb-text)))
+
+(defun nnweb-text-1 (contents)
+  (dolist (element contents)
+    (if (stringp element)
+       (push element nnweb-text)
+      (when (and (consp element)
+                (listp (cdr element)))
+       (nnweb-text-1 element)))))
 
 (provide 'nnweb)
 
diff --git a/lisp/nnwfm.el b/lisp/nnwfm.el
new file mode 100644 (file)
index 0000000..17f2656
--- /dev/null
@@ -0,0 +1,432 @@
+;;; nnwfm.el --- interfacing with a web forum
+;; Copyright (C) 2000 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Note: You need to have `url' and `w3' installed for this
+;; backend to work.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(require 'nnoo)
+(require 'message)
+(require 'gnus-util)
+(require 'gnus)
+(require 'nnmail)
+(require 'mm-util)
+(require 'mm-url)
+(require 'nnweb)
+(autoload 'w3-parse-buffer "w3-parse")
+
+(nnoo-declare nnwfm)
+
+(defvoo nnwfm-directory (nnheader-concat gnus-directory "wfm/")
+  "Where nnwfm will save its files.")
+
+(defvoo nnwfm-address ""
+  "The address of the Ultimate bulletin board.")
+
+;;; Internal variables
+
+(defvar nnwfm-groups-alist nil)
+(defvoo nnwfm-groups nil)
+(defvoo nnwfm-headers nil)
+(defvoo nnwfm-articles nil)
+(defvar nnwfm-table-regexp
+  "postings.*editpost\\|forumdisplay\\|Forum[0-9]+/HTML\\|getbio")
+
+;;; Interface functions
+
+(nnoo-define-basics nnwfm)
+
+(deffoo nnwfm-retrieve-headers (articles &optional group server fetch-old)
+  (nnwfm-possibly-change-server group server)
+  (unless gnus-nov-is-evil
+    (let* ((last (car (last articles)))
+          (did nil)
+          (start 1)
+          (entry (assoc group nnwfm-groups))
+          (sid (nth 2 entry))
+          (topics (nth 4 entry))
+          (mapping (nth 5 entry))
+          (old-total (or (nth 6 entry) 1))
+          (nnwfm-table-regexp "Thread.asp")
+          headers article subject score from date lines parent point
+          contents tinfo fetchers map elem a href garticles topic old-max
+          inc datel table string current-page total-contents pages
+          farticles forum-contents parse furl-fetched mmap farticle
+          thread-id tables hstuff bstuff time)
+      (setq map mapping)
+      (while (and (setq article (car articles))
+                 map)
+       (while (and map
+                   (or (> article (caar map))
+                       (< (cadar map) (caar map))))
+         (pop map))
+       (when (setq mmap (car map))
+         (setq farticle -1)
+         (while (and article
+                     (<= article (nth 1 mmap)))
+           ;; Do we already have a fetcher for this topic?
+           (if (setq elem (assq (nth 2 mmap) fetchers))
+               ;; Yes, so we just add the spec to the end.
+               (nconc elem (list (cons article
+                                       (+ (nth 3 mmap) (incf farticle)))))
+             ;; No, so we add a new one.
+             (push (list (nth 2 mmap)
+                         (cons article
+                               (+ (nth 3 mmap) (incf farticle))))
+                   fetchers))
+           (pop articles)
+           (setq article (car articles)))))
+      ;; Now we have the mapping from/to Gnus/nnwfm article numbers,
+      ;; so we start fetching the topics that we need to satisfy the
+      ;; request.
+      (if (not fetchers)
+         (save-excursion
+           (set-buffer nntp-server-buffer)
+           (erase-buffer))
+       (setq nnwfm-articles nil)
+       (mm-with-unibyte-buffer
+         (dolist (elem fetchers)
+           (erase-buffer)
+           (setq subject (nth 2 (assq (car elem) topics))
+                 thread-id (nth 0 (assq (car elem) topics)))
+           (mm-url-insert
+            (concat nnwfm-address
+                    (format "Item.asp?GroupID=%d&ThreadID=%d" sid
+                            thread-id)))
+           (goto-char (point-min))
+           (setq tables (caddar
+                         (caddar
+                          (cdr (caddar
+                                (caddar
+                                 (ignore-errors
+                                   (w3-parse-buffer (current-buffer)))))))))
+           (setq tables (cdr (caddar (memq (assq 'div tables) tables))))
+           (setq contents nil)
+           (dolist (table tables)
+             (when (eq (car table) 'table)
+               (setq table (caddar (caddar (caddr table)))
+                     hstuff (delete ":link" (nnweb-text (car table)))
+                     bstuff (car (caddar (cdr table)))
+                     from (car hstuff))
+               (when (nth 2 hstuff)
+                 (setq time (nnwfm-date-to-time (nth 2 hstuff)))
+                 (push (list from time bstuff) contents))))
+           (setq contents (nreverse contents))
+           (dolist (art (cdr elem))
+             (push (list (car art)
+                         (nth (1- (cdr art)) contents)
+                         subject)
+                   nnwfm-articles))))
+       (setq nnwfm-articles
+             (sort nnwfm-articles 'car-less-than-car))
+       ;; Now we have all the articles, conveniently in an alist
+       ;; where the key is the Gnus article number.
+       (dolist (articlef nnwfm-articles)
+         (setq article (nth 0 articlef)
+               contents (nth 1 articlef)
+               subject (nth 2 articlef))
+         (setq from (nth 0 contents)
+               date (message-make-date (nth 1 contents)))
+         (push
+          (cons
+           article
+           (make-full-mail-header
+            article subject
+            from (or date "")
+            (concat "<" (number-to-string sid) "%"
+                    (number-to-string article)
+                    "@wfm>")
+            "" 0
+            (/ (length (mapconcat 'identity (nnweb-text (nth 2 contents)) ""))
+               70)
+            nil nil))
+          headers))
+       (setq nnwfm-headers (sort headers 'car-less-than-car))
+       (save-excursion
+         (set-buffer nntp-server-buffer)
+         (mm-with-unibyte-current-buffer
+           (erase-buffer)
+           (dolist (header nnwfm-headers)
+             (nnheader-insert-nov (cdr header))))))
+      'nov)))
+
+(deffoo nnwfm-request-group (group &optional server dont-check)
+  (nnwfm-possibly-change-server nil server)
+  (when (not nnwfm-groups)
+    (nnwfm-request-list))
+  (unless dont-check
+    (nnwfm-create-mapping group))
+  (let ((elem (assoc group nnwfm-groups)))
+    (cond
+     ((not elem)
+      (nnheader-report 'nnwfm "Group does not exist"))
+     (t
+      (nnheader-report 'nnwfm "Opened group %s" group)
+      (nnheader-insert
+       "211 %d %d %d %s\n" (cadr elem) 1 (cadr elem)
+       (prin1-to-string group))))))
+
+(deffoo nnwfm-request-close ()
+  (setq nnwfm-groups-alist nil
+       nnwfm-groups nil))
+
+(deffoo nnwfm-request-article (article &optional group server buffer)
+  (nnwfm-possibly-change-server group server)
+  (let ((contents (cdr (assq article nnwfm-articles))))
+    (when (setq contents (nth 2 (car contents)))
+      (save-excursion
+       (set-buffer (or buffer nntp-server-buffer))
+       (erase-buffer)
+       (nnweb-insert-html contents)
+       (goto-char (point-min))
+       (insert "Content-Type: text/html\nMIME-Version: 1.0\n")
+       (let ((header (cdr (assq article nnwfm-headers))))
+         (mm-with-unibyte-current-buffer
+           (nnheader-insert-header header)))
+       (nnheader-report 'nnwfm "Fetched article %s" article)
+       (cons group article)))))
+
+(deffoo nnwfm-request-list (&optional server)
+  (nnwfm-possibly-change-server nil server)
+  (mm-with-unibyte-buffer
+    (mm-url-insert
+     (if (string-match "/$" nnwfm-address)
+        (concat nnwfm-address "Group.asp")
+       nnwfm-address))
+    (let* ((nnwfm-table-regexp "Thread.asp")
+          (contents (w3-parse-buffer (current-buffer)))
+          sid elem description articles a href group forum
+          a1 a2)
+      (dolist (row (cdr (nth 2 (car (nth 2 (nnwfm-find-forum-table
+                                           contents))))))
+       (setq row (nth 2 row))
+       (when (setq a (nnweb-parse-find 'a row))
+         (setq group (car (last (nnweb-text a)))
+               href (cdr (assq 'href (nth 1 a))))
+         (setq description (car (last (nnweb-text (nth 1 row)))))
+         (setq articles
+               (string-to-number
+                (gnus-replace-in-string
+                 (car (last (nnweb-text (nth 3 row)))) "," "")))
+         (when (and href
+                    (string-match "GroupId=\\([0-9]+\\)" href))
+           (setq forum (string-to-number (match-string 1 href)))
+           (if (setq elem (assoc group nnwfm-groups))
+               (setcar (cdr elem) articles)
+             (push (list group articles forum description nil nil nil nil)
+                   nnwfm-groups))))))
+    (nnwfm-write-groups)
+    (nnwfm-generate-active)
+    t))
+
+(deffoo nnwfm-request-newgroups (date &optional server)
+  (nnwfm-possibly-change-server nil server)
+  (nnwfm-generate-active)
+  t)
+
+(nnoo-define-skeleton nnwfm)
+
+;;; Internal functions
+
+(defun nnwfm-new-threads-p (group time)
+  "See whether we want to fetch the threads for GROUP written before TIME."
+  (let ((old-time (nth 7 (assoc group nnwfm-groups))))
+    (or (null old-time)
+       (time-less-p old-time time))))
+
+(defun nnwfm-create-mapping (group)
+  (let* ((entry (assoc group nnwfm-groups))
+        (sid (nth 2 entry))
+        (topics (nth 4 entry))
+        (mapping (nth 5 entry))
+        (old-total (or (nth 6 entry) 1))
+        (current-time (current-time))
+        (nnwfm-table-regexp "Thread.asp")
+        (furls (list (concat nnwfm-address
+                             (format "Thread.asp?GroupId=%d" sid))))
+        fetched-urls
+        contents forum-contents a subject href
+        garticles topic tinfo old-max inc parse elem date
+        url time)
+    (mm-with-unibyte-buffer
+      (while furls
+       (erase-buffer)
+       (push (car furls) fetched-urls)
+       (mm-url-insert (pop furls))
+       (goto-char (point-min))
+       (while (re-search-forward "  wr(" nil t)
+         (forward-char -1)
+         (setq elem (message-tokenize-header
+                     (gnus-replace-in-string
+                      (buffer-substring
+                       (1+ (point))
+                       (progn
+                         (forward-sexp 1)
+                         (1- (point))))
+                      "\\\\[\"\\\\]" "")))
+         (push (list
+                (string-to-number (nth 1 elem))
+                (gnus-replace-in-string (nth 2 elem) "\"" "")
+                (string-to-number (nth 5 elem)))
+               forum-contents))
+       (when (re-search-forward "href=\"\\(Thread.*DateLast=\\([^\"]+\\)\\)"
+                                nil t)
+         (setq url (match-string 1)
+               time (nnwfm-date-to-time (gnus-url-unhex-string
+                                         (match-string 2))))
+         (when (and (nnwfm-new-threads-p group time)
+                    (not (member
+                          (setq url (concat
+                                     nnwfm-address
+                                     (mm-url-decode-entities-string url)))
+                          fetched-urls)))
+           (push url furls))))
+      ;; The main idea here is to map Gnus article numbers to
+      ;; nnwfm article numbers.  Say there are three topics in
+      ;; this forum, the first with 4 articles, the seconds with 2,
+      ;; and the third with 1.  Then this will translate into 7 Gnus
+      ;; article numbers, where 1-4 comes from the first topic, 5-6
+      ;; from the second and 7 from the third.  Now, then next time
+      ;; the group is entered, there's 2 new articles in topic one
+      ;; and 1 in topic three.  Then Gnus article number 8-9 be 5-6
+      ;; in topic one and 10 will be the 2 in topic three.
+      (dolist (elem (nreverse forum-contents))
+       (setq subject (nth 1 elem)
+             topic (nth 0 elem)
+             garticles (nth 2 elem))
+       (if (setq tinfo (assq topic topics))
+           (progn
+             (setq old-max (cadr tinfo))
+             (setcar (cdr tinfo) garticles))
+         (setq old-max 0)
+         (push (list topic garticles subject) topics)
+         (setcar (nthcdr 4 entry) topics))
+       (when (not (= old-max garticles))
+         (setq inc (- garticles old-max))
+         (setq mapping (nconc mapping
+                              (list
+                               (list
+                                old-total (1- (incf old-total inc))
+                                topic (1+ old-max)))))
+         (incf old-max inc)
+         (setcar (nthcdr 5 entry) mapping)
+         (setcar (nthcdr 6 entry) old-total))))
+    (setcar (nthcdr 7 entry) current-time)
+    (setcar (nthcdr 1 entry) (1- old-total))
+    (nnwfm-write-groups)
+    mapping))
+
+(defun nnwfm-possibly-change-server (&optional group server)
+  (nnwfm-init server)
+  (when (and server
+            (not (nnwfm-server-opened server)))
+    (nnwfm-open-server server))
+  (unless nnwfm-groups-alist
+    (nnwfm-read-groups)
+    (setq nnwfm-groups (cdr (assoc nnwfm-address
+                                  nnwfm-groups-alist)))))
+
+(deffoo nnwfm-open-server (server &optional defs connectionless)
+  (nnheader-init-server-buffer)
+  (if (nnwfm-server-opened server)
+      t
+    (unless (assq 'nnwfm-address defs)
+      (setq defs (append defs (list (list 'nnwfm-address server)))))
+    (nnoo-change-server 'nnwfm server defs)))
+
+(defun nnwfm-read-groups ()
+  (setq nnwfm-groups-alist nil)
+  (let ((file (expand-file-name "groups" nnwfm-directory)))
+    (when (file-exists-p file)
+      (mm-with-unibyte-buffer
+       (insert-file-contents file)
+       (goto-char (point-min))
+       (setq nnwfm-groups-alist (read (current-buffer)))))))
+
+(defun nnwfm-write-groups ()
+  (setq nnwfm-groups-alist
+       (delq (assoc nnwfm-address nnwfm-groups-alist)
+             nnwfm-groups-alist))
+  (push (cons nnwfm-address nnwfm-groups)
+       nnwfm-groups-alist)
+  (with-temp-file (expand-file-name "groups" nnwfm-directory)
+    (prin1 nnwfm-groups-alist (current-buffer))))
+
+(defun nnwfm-init (server)
+  "Initialize buffers and such."
+  (unless (file-exists-p nnwfm-directory)
+    (gnus-make-directory nnwfm-directory)))
+
+(defun nnwfm-generate-active ()
+  (save-excursion
+    (set-buffer nntp-server-buffer)
+    (erase-buffer)
+    (dolist (elem nnwfm-groups)
+      (insert (prin1-to-string (car elem))
+             " " (number-to-string (cadr elem)) " 1 y\n"))))
+
+(defun nnwfm-find-forum-table (contents)
+  (catch 'found
+    (nnwfm-find-forum-table-1 contents)))
+
+(defun nnwfm-find-forum-table-1 (contents)
+  (dolist (element contents)
+    (unless (stringp element)
+      (when (and (eq (car element) 'table)
+                (nnwfm-forum-table-p element))
+       (throw 'found element))
+      (when (nth 2 element)
+       (nnwfm-find-forum-table-1 (nth 2 element))))))
+
+(defun nnwfm-forum-table-p (parse)
+  (when (not (apply 'gnus-or
+                   (mapcar
+                    (lambda (p)
+                      (nnweb-parse-find 'table p))
+                    (nth 2 parse))))
+    (let ((href (cdr (assq 'href (nth 1 (nnweb-parse-find 'a parse 20)))))
+         case-fold-search)
+      (when (and href (string-match nnwfm-table-regexp href))
+       t))))
+
+(defun nnwfm-date-to-time (date)
+  (let ((time (mapcar #'string-to-number (split-string date "[\\.\\+ :]"))))
+    (encode-time 0 (nth 4 time) (nth 3 time)
+                (nth 0 time) (nth 1 time)
+                (if (< (nth 2 time) 70)
+                    (+ 2000 (nth 2 time))
+                  (+ 1900 (nth 2 time))))))
+
+(provide 'nnwfm)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; nnwfm.el ends here
index e25abbb..34dd3fd 100644 (file)
@@ -1,8 +1,8 @@
 ;;; parse-time.el --- Parsing time strings
 
-;; Copyright (C) 1996 by Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2000, 2002 by Free Software Foundation, Inc.
 
-;; Author: Erik Naggum <erik@arcana.naggum.no>
+;; Author: Erik Naggum <erik@naggum.no>
 ;; Keywords: util
 
 ;; This file is part of GNU Emacs.
 ;; `parse-time-string' parses a time in a string and returns a list of 9
 ;; values, just like `decode-time', where unspecified elements in the
 ;; string are returned as nil.  `encode-time' may be applied on these
-;; valuse to obtain an internal time value.
+;; values to obtain an internal time value.
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))              ;and ah ain't kiddin' 'bout it
+(eval-when-compile (require 'cl))      ;and ah ain't kiddin' 'bout it
 
-(put 'parse-time-syntax 'char-table-extra-slots 0)
-
-(defvar parse-time-syntax (make-char-table 'parse-time-syntax))
-(defvar parse-time-digits (make-char-table 'parse-time-syntax))
+(defvar parse-time-syntax (make-vector 256 nil))
+(defvar parse-time-digits (make-vector 256 nil))
 
 ;; Byte-compiler warnings
 (defvar elt)
 
 (unless (aref parse-time-digits ?0)
   (loop for i from ?0 to ?9
-       do (set-char-table-range parse-time-digits i (- i ?0))))
+    do (aset parse-time-digits i (- i ?0))))
 
 (unless (aref parse-time-syntax ?0)
   (loop for i from ?0 to ?9
-       do (set-char-table-range parse-time-syntax i ?0))
+    do (aset parse-time-syntax i ?0))
   (loop for i from ?A to ?Z
-       do (set-char-table-range parse-time-syntax i ?A))
+    do (aset parse-time-syntax i ?A))
   (loop for i from ?a to ?z
-       do (set-char-table-range parse-time-syntax i ?a))
-  (set-char-table-range parse-time-syntax ?+ 1)
-  (set-char-table-range parse-time-syntax ?- -1)
-  (set-char-table-range parse-time-syntax ?: ?d)
+    do (aset parse-time-syntax i ?a))
+  (aset parse-time-syntax ?+ 1)
+  (aset parse-time-syntax ?- -1)
+  (aset parse-time-syntax ?: ?d)
   )
 
 (defsubst digit-char-p (char)
@@ -89,7 +87,8 @@
          (setq integer (+ (* integer 10) digit)
                index (1+ index)))
        (if (/= index end)
-           (signal 'parse-error `("not an integer" ,(substring string (or start 0) end)))
+           (signal 'parse-error `("not an integer"
+                                  ,(substring string (or start 0) end)))
          (* sign integer))))))
 
 (defun parse-time-tokenize (string)
                list)))
     (nreverse list)))
 
-(defvar parse-time-months '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3)
-                           ("Apr" . 4) ("May" . 5) ("Jun" . 6)
-                           ("Jul" . 7) ("Aug" . 8) ("Sep" . 9)
-                           ("Oct" . 10) ("Nov" . 11) ("Dec" . 12)))
-(defvar parse-time-weekdays '(("Sun" . 0) ("Mon" . 1) ("Tue" . 2)
-                             ("Wed" . 3) ("Thu" . 4) ("Fri" . 5) ("Sat" . 6)))
-(defvar parse-time-zoneinfo `(("Z" 0) ("UT" 0) ("GMT" 0)
-                             ("PST" ,(* -8 3600)) ("PDT" ,(* -7 3600) t)
-                             ("MST" ,(* -7 3600)) ("MDT" ,(* -6 3600) t)
-                             ("CST" ,(* -6 3600)) ("CDT" ,(* -5 3600) t)
-                             ("EST" ,(* -5 3600)) ("EDT" ,(* -4 3600) t))
+(defvar parse-time-months '(("jan" . 1) ("feb" . 2) ("mar" . 3)
+                           ("apr" . 4) ("may" . 5) ("jun" . 6)
+                           ("jul" . 7) ("aug" . 8) ("sep" . 9)
+                           ("oct" . 10) ("nov" . 11) ("dec" . 12)))
+(defvar parse-time-weekdays '(("sun" . 0) ("mon" . 1) ("tue" . 2)
+                             ("wed" . 3) ("thu" . 4) ("fri" . 5) ("sat" . 6)))
+(defvar parse-time-zoneinfo `(("z" 0) ("ut" 0) ("gmt" 0)
+                             ("pst" ,(* -8 3600)) ("pdt" ,(* -7 3600) t)
+                             ("mst" ,(* -7 3600)) ("mdt" ,(* -6 3600) t)
+                             ("cst" ,(* -6 3600)) ("cdt" ,(* -5 3600) t)
+                             ("est" ,(* -5 3600)) ("edt" ,(* -4 3600) t))
   "(zoneinfo seconds-off daylight-savings-time-p)")
 
 (defvar parse-time-rules
   `(((6) parse-time-weekdays)
     ((3) (1 31))
     ((4) parse-time-months)
-    ((5) (1970 2038))
+    ((5) (100 4038))
     ((2 1 0)
      ,#'(lambda () (and (stringp elt)
                        (= (length elt) 8)
                            (* 60 (parse-integer elt 1 3)))
                      (if (= (aref elt 0) ?-) -1 1))))
     ((5 4 3)
-     ,#'(lambda () (and (stringp elt) (= (length elt) 10) (= (aref elt 4) ?-) (= (aref elt 7) ?-)))
+     ,#'(lambda () (and (stringp elt)
+                       (= (length elt) 10)
+                       (= (aref elt 4) ?-)
+                       (= (aref elt 7) ?-)))
      [0 4] [5 7] [8 10])
-    ((2 1)
+    ((2 1 0)
      ,#'(lambda () (and (stringp elt) (= (length elt) 5) (= (aref elt 2) ?:)))
-     [0 2] [3 5])
-    ((5) (70 99) ,#'(lambda () (+ 1900 elt))))
+     [0 2] [3 5] ,#'(lambda () 0))
+    ((2 1 0)
+     ,#'(lambda () (and (stringp elt)
+                       (= (length elt) 4)
+                       (= (aref elt 1) ?:)))
+     [0 1] [2 4] ,#'(lambda () 0))
+    ((2 1 0)
+     ,#'(lambda () (and (stringp elt)
+                       (= (length elt) 7)
+                       (= (aref elt 1) ?:)))
+     [0 1] [2 4] [5 7])
+    ((5) (50 110) ,#'(lambda () (+ 1900 elt)))
+    ((5) (0 49) ,#'(lambda () (+ 2000 elt))))
   "(slots predicate extractor...)")
 
 (defun parse-time-string (string)
   "Parse the time-string STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
 The values are identical to those of `decode-time', but any values that are
 unknown are returned as nil."
-  (let ((time (list nil nil nil nil nil nil nil nil nil nil))
-       (temp (parse-time-tokenize string)))
+  (let ((time (list nil nil nil nil nil nil nil nil nil))
+       (temp (parse-time-tokenize (downcase string))))
     (while temp
       (let ((elt (pop temp))
            (rules parse-time-rules)
@@ -173,25 +186,27 @@ unknown are returned as nil."
                 (slots (pop rule))
                 (predicate (pop rule))
                 (val))
-           (if (and (not (nth (car slots) time)) ;not already set
-                    (setq val (cond ((and (consp predicate)
-                                          (not (eq (car predicate) 'lambda)))
-                                     (and (numberp elt)
-                                          (<= (car predicate) elt)
-                                          (<= elt (cadr predicate))
-                                          elt))
-                                    ((symbolp predicate)
-                                     (cdr (assoc elt (symbol-value predicate))))
-                                    ((funcall predicate)))))
-               (progn
-                 (setq exit t)
-                 (while slots
-                   (let ((new-val (and rule
-                                       (let ((this (pop rule)))
-                                         (if (vectorp this)
-                                             (parse-integer elt (aref this 0) (aref this 1))
-                                           (funcall this))))))
-                     (rplaca (nthcdr (pop slots) time) (or new-val val))))))))))
+           (when (and (not (nth (car slots) time)) ;not already set
+                      (setq val (cond ((and (consp predicate)
+                                            (not (eq (car predicate)
+                                                     'lambda)))
+                                       (and (numberp elt)
+                                            (<= (car predicate) elt)
+                                            (<= elt (cadr predicate))
+                                            elt))
+                                      ((symbolp predicate)
+                                       (cdr (assoc elt
+                                                   (symbol-value predicate))))
+                                      ((funcall predicate)))))
+             (setq exit t)
+             (while slots
+               (let ((new-val (and rule
+                                   (let ((this (pop rule)))
+                                     (if (vectorp this)
+                                         (parse-integer
+                                          elt (aref this 0) (aref this 1))
+                                       (funcall this))))))
+                 (rplaca (nthcdr (pop slots) time) (or new-val val)))))))))
     time))
 
 (provide 'parse-time)
index 3362ed5..c47a2e4 100644 (file)
@@ -1,12 +1,15 @@
 ;;; pop3.el --- Post Office Protocol (RFC 1460) interface
 
-;; Copyright (C) 1996,1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+;;        Free Software Foundation, Inc.
 
 ;; Author: Richard L. Pieri <ratinox@peorth.gweep.net>
-;; Keywords: mail, pop3
-;; Version: 1.3l
+;;      Daiki Ueno  <ueno@ueda.info.waseda.ac.jp>
+;;      Katsumi Yamaoka <yamaoka@jpl.org>
+;; Maintainer: Volunteers
+;; Keywords: mail
 
-;; This file is part of GNU Emacs.
+;; This file is part of T-gnus.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 
 ;; This program was inspired by Kyle E. Jones's vm-pop program.
 
+;; You have to set the variable `pop3-connection-type' to `ssl' or
+;; `tls' expressly, if you would like to use this module with Gnus
+;; (not T-gnus) for those connection types.  For examples:
+;;
+;;(setq mail-sources '((pop :server "POPSERVER" :port 995 :connection ssl
+;;                          :authentication apop)))
+;;(setq pop3-connection-type 'ssl)
+
 ;;; Code:
 
-(require 'mail-utils)
-(provide 'pop3)
+(eval-when-compile
+  (require 'cl)
+  ;; For compiling this module in Gnus with XEmacs -no-autoloads.
+  (require 'advice))
 
-(defconst pop3-version "1.3l")
+;; as-binary-process, open-network-stream-as-binary, write-region-as-binary
+(require 'pces)
+;; exec-installed-p
+(require 'path-util)
+
+(require 'mail-utils)
 
 (defvar pop3-maildrop (or (user-login-name) (getenv "LOGNAME") (getenv "USER") nil)
   "*POP3 maildrop.")
@@ -45,6 +63,8 @@
   "*POP3 mailhost.")
 (defvar pop3-port 110
   "*POP3 port.")
+(defvar pop3-connection-type nil
+  "*POP3 connection type.")
 
 (defvar pop3-password-required t
   "*Non-nil if a password is required when connecting to POP server.")
@@ -60,9 +80,45 @@ values are 'apop.")
   "Timestamp returned when initially connected to the POP server.
 Used for APOP authentication.")
 
+(defvar pop3-leave-mail-on-server nil
+  "Non-nil if mail is to be left on the server and UIDL used for message retrieval.")
+
+(defvar pop3-maximum-message-size nil
+  "If non-nil only download messages smaller than this.")
+
+(defvar pop3-except-header-regexp nil
+  "If non-nil we do not retrieve messages whose headers are matching this regexp.")
+
+(defvar pop3-uidl-file-name "~/.uidls"
+  "File in which to store the UIDL of processed messages.")
+
+(defvar pop3-uidl-support nil
+  "Alist of servers and flags of whether they support UIDLs.
+Users don't have to set this value.")
+
+(defvar pop3-uidl-obarray (make-vector 31 0)
+  "Uidl hash table.")
+
 (defvar pop3-read-point nil)
 (defvar pop3-debug nil)
 
+(eval-and-compile
+  (autoload 'starttls-open-stream "starttls")
+  (autoload 'starttls-negotiate "starttls"))
+
+(defvar pop3-ssl-program-name
+  (if (exec-installed-p "openssl")
+      "openssl"
+    "ssleay")
+  "The program to run in a subprocess to open an SSL connection.")
+
+(defvar pop3-ssl-program-arguments
+  '("s_client" "-quiet")
+  "Arguments to be passed to the program `pop3-ssl-program-name'.")
+
+(defun pop3-progress-message (format percent &rest args)
+  (apply (function message) format args))
+
 (defun pop3-movemail (&optional crashbox)
   "Transfer contents of a maildrop to the specified CRASHBOX."
   (or crashbox (setq crashbox (expand-file-name "~/.crashbox")))
@@ -71,60 +127,147 @@ Used for APOP authentication.")
         (n 1)
         message-count
         (pop3-password pop3-password)
+        (pop3-uidl-file-name (convert-standard-filename
+                              (concat pop3-uidl-file-name "-"
+                                      pop3-mailhost)))
+        retrieved-messages messages)
+    ;; for debugging only
+    (if pop3-debug (switch-to-buffer (process-buffer process)))
+    ;; query for password
+    (if (and pop3-password-required (not pop3-password))
+       (setq pop3-password
+             (read-passwd (format "Password for %s: " pop3-maildrop))))
+    (cond ((equal 'apop pop3-authentication-scheme)
+          (pop3-apop process pop3-maildrop))
+         ((equal 'pass pop3-authentication-scheme)
+          (pop3-user process pop3-maildrop)
+          (pop3-pass process))
+         (t (error "Invalid POP3 authentication scheme")))
+    ;; get messages that are suitable for download
+    (message "Retrieving message list...")
+    (setq messages (pop3-get-message-numbers process)
+         message-count (length (cdr messages)))
+    (message "Retrieving message list...%d of %d unread"
+            message-count (pop messages))
+    (unwind-protect
+       (unless (not (stringp crashbox))
+         (while messages
+           (pop3-progress-message
+            "Retrieving message %d of %d (%d octets) from %s..."
+            (floor (* (/ (float n) message-count) 100))
+            n message-count (cdar messages) pop3-mailhost)
+           (pop3-retr process (caar messages) crashbuf)
+           (push (caar messages) retrieved-messages)
+           (setq messages (cdr messages)
+                 n (1+ n)))
+         (with-current-buffer crashbuf
+           (write-region-as-binary (point-min) (point-max)
+                                   crashbox 'append 'nomesg))
+         ;; mark messages as read
+         (when pop3-leave-mail-on-server
+           (pop3-save-uidls))
+         ;; now delete the messages we have retrieved
+         (unless pop3-leave-mail-on-server
+           (dolist (n retrieved-messages)
+             (message "Deleting message %d of %d from %s..."
+                      n message-count pop3-mailhost)
+             (pop3-dele process n)))
+         )
+      (pop3-quit process))
+    (kill-buffer crashbuf)
+    message-count))
+
+(defun pop3-get-message-count ()
+  "Return the number of messages in the maildrop."
+  (let* ((process (pop3-open-server pop3-mailhost pop3-port))
+        message-count
+        (pop3-password pop3-password)
         )
     ;; for debugging only
     (if pop3-debug (switch-to-buffer (process-buffer process)))
     ;; query for password
     (if (and pop3-password-required (not pop3-password))
        (setq pop3-password
-             (pop3-read-passwd (format "Password for %s: " pop3-maildrop))))
+             (read-passwd (format "Password for %s: " pop3-maildrop))))
     (cond ((equal 'apop pop3-authentication-scheme)
           (pop3-apop process pop3-maildrop))
          ((equal 'pass pop3-authentication-scheme)
           (pop3-user process pop3-maildrop)
           (pop3-pass process))
-         (t (error "Invalid POP3 authentication scheme.")))
+         (t (error "Invalid POP3 authentication scheme")))
     (setq message-count (car (pop3-stat process)))
-    (while (<= n message-count)
-      (message (format "Retrieving message %d of %d from %s..."
-                      n message-count pop3-mailhost))
-      (pop3-retr process n crashbuf)
-      (save-excursion
-       (set-buffer crashbuf)
-       (append-to-file (point-min) (point-max) crashbox)
-       (set-buffer (process-buffer process))
-       (while (> (buffer-size) 5000)
-         (goto-char (point-min))
-         (forward-line 50)
-         (delete-region (point-min) (point))))
-      (pop3-dele process n)
-      (setq n (+ 1 n))
-      (if pop3-debug (sit-for 1) (sit-for 0.1))
-      )
     (pop3-quit process)
-    (kill-buffer crashbuf)
-    )
-  )
+    message-count))
 
 (defun pop3-open-server (mailhost port)
-  "Open TCP connection to MAILHOST.
-Returns the process associated with the connection."
-  (let ((process-buffer
-        (get-buffer-create (format "trace of POP session to %s" mailhost)))
-       (process))
+  "Open TCP connection to MAILHOST on PORT.
+Returns the process associated with the connection.
+Argument PORT specifies connecting port."
+  (let (process)
     (save-excursion
-      (set-buffer process-buffer)
+      (set-buffer (get-buffer-create (concat " trace of POP session to "
+                                            mailhost)))
       (erase-buffer)
       (setq pop3-read-point (point-min))
-      )
-    (setq process
-         (open-network-stream "POP" process-buffer mailhost port))
-    (let ((response (pop3-read-response process t)))
-      (setq pop3-timestamp
-           (substring response (or (string-match "<" response) 0)
-                      (+ 1 (or (string-match ">" response) -1)))))
-    process
-    ))
+      (setq
+       process
+       (cond
+       ((eq pop3-connection-type 'ssl)
+        (pop3-open-ssl-stream "POP" (current-buffer) mailhost port))
+       ((eq pop3-connection-type 'tls)
+        (pop3-open-tls-stream "POP" (current-buffer) mailhost port))
+       (t
+        (open-network-stream-as-binary "POP" (current-buffer)
+                                       mailhost port))))
+      (let ((response (pop3-read-response process t)))
+       (setq pop3-timestamp
+             (substring response (or (string-match "<" response) 0)
+                        (+ 1 (or (string-match ">" response) -1)))))
+      process)))
+
+(eval-when-compile
+  (autoload 'open-ssl-stream "ssl"))
+
+(defun pop3-open-ssl-stream-1 (name buffer host service extra-arg)
+  (require 'ssl)
+  (let* ((ssl-program-name
+         pop3-ssl-program-name)
+        (ssl-program-arguments
+         `(,@pop3-ssl-program-arguments
+           ,extra-arg
+           "-connect" ,(format "%s:%d" host service)))
+        (process (open-ssl-stream name buffer host service)))
+    (when process
+      (with-current-buffer buffer
+       (goto-char (point-min))
+       (while (and (memq (process-status process) '(open run))
+                   (goto-char (point-max))
+                   (forward-line -1)
+                   (not (looking-at "+OK")))
+         (nnheader-accept-process-output process)
+         (sit-for 1))
+       (delete-region (point-min) (point)))
+      (and process (memq (process-status process) '(open run))
+          process))))
+
+(defun pop3-open-ssl-stream (name buffer host service)
+  "Open a SSL connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Args are NAME BUFFER HOST SERVICE."
+  (as-binary-process
+   (or (pop3-open-ssl-stream-1 name buffer host service "-ssl3")
+       (pop3-open-ssl-stream-1 name buffer host service "-ssl2"))))
+
+(defun pop3-open-tls-stream (name buffer host service)
+  "Open a TLSv1 connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Args are NAME BUFFER HOST SERVICE."
+  (let ((process
+        (as-binary-process (starttls-open-stream
+                            name buffer host service))))
+    (pop3-stls process)
+    (starttls-negotiate process)
+    process))
 
 ;; Support functions
 
@@ -135,27 +278,27 @@ Returns the process associated with the connection."
     (insert output)))
 
 (defun pop3-send-command (process command)
-    (set-buffer (process-buffer process))
-    (goto-char (point-max))
-;;    (if (= (aref command 0) ?P)
-;;     (insert "PASS <omitted>\r\n")
-;;      (insert command "\r\n"))
-    (setq pop3-read-point (point))
-    (goto-char (point-max))
-    (process-send-string process command)
-    (process-send-string process "\r\n")
-    )
+  (set-buffer (process-buffer process))
+  (goto-char (point-max))
+;;  (if (= (aref command 0) ?P)
+;;      (insert "PASS <omitted>\r\n")
+;;    (insert command "\r\n"))
+  (setq pop3-read-point (point))
+  (goto-char (point-max))
+  (process-send-string process (concat command "\r\n"))
+  )
 
 (defun pop3-read-response (process &optional return)
-  "Read the response from the server.
-Return the response string if optional second argument is non-nil."
+  "Read the response from the server PROCESS.
+Return the response string if optional second argument RETURN is non-nil."
   (let ((case-fold-search nil)
        match-end)
     (save-excursion
       (set-buffer (process-buffer process))
       (goto-char pop3-read-point)
-      (while (not (search-forward "\r\n" nil t))
-       (accept-process-output process 3)
+      (while (and (memq (process-status process) '(open run))
+                 (not (search-forward "\r\n" nil t)))
+       (nnheader-accept-process-output process)
        (goto-char pop3-read-point))
       (setq match-end (point))
       (goto-char pop3-read-point)
@@ -169,31 +312,6 @@ Return the response string if optional second argument is non-nil."
            t)
          )))))
 
-(defun pop3-string-to-list (string &optional regexp)
-  "Chop up a string into a list."
-  (let ((list)
-       (regexp (or regexp " "))
-       (string (if (string-match "\r" string)
-                   (substring string 0 (match-beginning 0))
-                 string)))
-    (store-match-data nil)
-    (while string
-      (if (string-match regexp string)
-         (setq list (cons (substring string 0 (- (match-end 0) 1)) list)
-               string (substring string (match-end 0)))
-       (setq list (cons string list)
-             string nil)))
-    (nreverse list)))
-
-(defvar pop3-read-passwd nil)
-(defun pop3-read-passwd (prompt)
-  (if (not pop3-read-passwd)
-      (if (load "passwd" t)
-         (setq pop3-read-passwd 'read-passwd)
-       (autoload 'ange-ftp-read-passwd "ange-ftp")
-       (setq pop3-read-passwd 'ange-ftp-read-passwd)))
-  (funcall pop3-read-passwd prompt))
-
 (defun pop3-clean-region (start end)
   (setq end (set-marker (make-marker) end))
   (save-excursion
@@ -201,14 +319,39 @@ Return the response string if optional second argument is non-nil."
     (while (and (< (point) end) (search-forward "\r\n" end t))
       (replace-match "\n" t t))
     (goto-char start)
+    (while (re-search-forward "\n\n\\(From \\)" end t)
+      (replace-match "\n\n>\\1" t nil))
+    (goto-char start)
     (while (and (< (point) end) (re-search-forward "^\\." end t))
       (replace-match "" t t)
       (forward-char)))
   (set-marker end nil))
 
+(eval-when-compile (defvar parse-time-months))
+
+;; Copied from message-make-date.
+(defun pop3-make-date (&optional now)
+  "Make a valid date header.
+If NOW, use that time instead."
+  (require 'parse-time)
+  (let* ((now (or now (current-time)))
+        (zone (nth 8 (decode-time now)))
+        (sign "+"))
+    (when (< zone 0)
+      (setq sign "-")
+      (setq zone (- zone)))
+    (concat
+     (format-time-string "%d" now)
+     ;; The month name of the %b spec is locale-specific.  Pfff.
+     (format " %s "
+            (capitalize (car (rassoc (nth 4 (decode-time now))
+                                     parse-time-months))))
+     (format-time-string "%Y %H:%M:%S " now)
+     ;; We do all of this because XEmacs doesn't have the %z spec.
+     (format "%s%02d%02d" sign (/ zone 3600) (/ (% zone 3600) 60)))))
+
 (defun pop3-munge-message-separator (start end)
   "Check to see if a message separator exists.  If not, generate one."
-  (if (not (fboundp 'message-make-date)) (autoload 'message-make-date "message"))
   (save-excursion
     (save-restriction
       (narrow-to-region start end)
@@ -217,17 +360,23 @@ Return the response string if optional second argument is non-nil."
                   (looking-at "\001\001\001\001\n") ; MMDF
                   (looking-at "BABYL OPTIONS:") ; Babyl
                   ))
-         (let ((from (mail-strip-quoted-names (mail-fetch-field "From")))
-               (date (pop3-string-to-list (or (mail-fetch-field "Date")
-                                              (message-make-date))))
-               (From_))
+         (let* ((from (mail-strip-quoted-names (mail-fetch-field "From")))
+                (tdate (mail-fetch-field "Date"))
+                (date (split-string (or (and tdate
+                                             (not (string= "" tdate))
+                                             tdate)
+                                        (pop3-make-date))
+                                    " "))
+                (From_))
            ;; sample date formats I have seen
            ;; Date: Tue, 9 Jul 1996 09:04:21 -0400 (EDT)
            ;; Date: 08 Jul 1996 23:22:24 -0400
            ;; should be
            ;; Tue Jul 9 09:04:21 1996
            (setq date
-                 (cond ((string-match "[A-Z]" (nth 0 date))
+                 (cond ((not date)
+                        "Tue Jan 1 00:00:0 1900")
+                       ((string-match "[A-Z]" (nth 0 date))
                         (format "%s %s %s %s %s"
                                 (nth 0 date) (nth 2 date) (nth 1 date)
                                 (nth 4 date) (nth 3 date)))
@@ -243,7 +392,106 @@ Return the response string if optional second argument is non-nil."
              (setq From_ (concat (substring From_ 0 (match-beginning 0))
                                  (substring From_ (match-end 0)))))
            (goto-char (point-min))
-           (insert From_))))))
+           (insert From_)
+           (if (search-forward "\n\n" nil t)
+               nil
+             (goto-char (point-max))
+             (insert "\n"))
+           (narrow-to-region (point) (point-max))
+           (let ((size (- (point-max) (point-min))))
+             (goto-char (point-min))
+             (widen)
+             (forward-line -1)
+             (insert (format "Content-Length: %s\n" size)))
+           )))))
+
+;; UIDL support
+
+(defun pop3-get-message-numbers (process)
+  "Get the list of message numbers and lengths to retrieve via PROCESS."
+  ;; we use the LIST comand first anyway to get the message lengths.
+  ;; then if we're leaving mail on the server, see if the UIDL command
+  ;; is implemented. if so, we use it to get the message number list.
+  (let* ((messages (pop3-list process))
+        (total (or (pop messages) 0))
+        (uidl (if pop3-leave-mail-on-server
+                  (pop3-get-uidl process)))
+        out)
+    (while messages
+      ;; only retrieve messages matching our regexp or in the uidl list
+      (when (and
+            ;; remove elements not in the uidl, this assumes the uidl is short
+            (or (not (and pop3-leave-mail-on-server
+                          (cdr (assoc pop3-mailhost pop3-uidl-support))))
+                (memq (caar messages) uidl))
+            (caar messages)
+            ;; don't download messages that are too large
+            (not (and pop3-maximum-message-size
+                      (> (cdar messages) pop3-maximum-message-size)))
+            (not (and pop3-except-header-regexp
+                      (string-match pop3-except-header-regexp
+                                    (pop3-top process (caar messages) 0)))))
+       (push (car messages) out))
+      (setq messages (cdr messages)))
+    (cons total (nreverse out))))
+
+(defun pop3-get-uidl (process)
+  "Use PROCESS to get a list of unread message numbers."
+  (let ((messages (pop3-uidl process))
+       (support (assoc pop3-mailhost pop3-uidl-support))
+       uidl)
+    (if support
+       (setcdr support (and messages t))
+      (push (cons pop3-mailhost (and messages t))
+           pop3-uidl-support))
+    (when messages
+      (save-excursion
+       (with-temp-buffer
+         (when (file-readable-p pop3-uidl-file-name)
+           (insert-file-contents pop3-uidl-file-name))
+         (goto-char (point-min))
+         (while (looking-at "\\([^ \n\t]+\\)")
+           (set (intern (match-string 1) pop3-uidl-obarray)
+                (cons nil t))
+           (forward-line 1))))
+      (dolist (message (cdr messages))
+       (if (setq uidl (intern-soft (cdr message) pop3-uidl-obarray))
+           (setcar (symbol-value uidl) (car message))
+         (set (intern (cdr message) pop3-uidl-obarray)
+              (cons (car message) nil))))
+      (pop3-get-unread-message-numbers))))
+
+(defun pop3-get-unread-message-numbers ()
+  "Return a sorted list of unread msg numbers to retrieve."
+  (let (nums)
+    (mapatoms (lambda (atom)
+               (if (not (cdr (symbol-value atom)))
+                   (push (car (symbol-value atom)) nums)))
+             pop3-uidl-obarray)
+    (sort nums '<)))
+
+(defun pop3-save-uidls ()
+  "Save the updated UIDLs to disk for use next time."
+  (when (and pop3-leave-mail-on-server
+            ;; UIDL hash table is non-empty
+            (let ((len (length pop3-uidl-obarray)))
+              (while (< 0 len)
+                (setq len (if (symbolp (aref pop3-uidl-obarray (1- len)))
+                              -1 (1- len))))
+              (minusp len)))
+    (when (file-readable-p pop3-uidl-file-name)
+      (copy-file pop3-uidl-file-name
+                (concat pop3-uidl-file-name ".old")
+                'overwrite 'keeptime))
+    (save-excursion
+      (with-temp-file pop3-uidl-file-name
+       (mapatoms
+        (lambda (atom)
+          (when (car (symbol-value atom))
+            (insert (format "%s\n" atom))))
+        pop3-uidl-obarray)))
+    (fillarray pop3-uidl-obarray 0)))
+
 
 ;; The Command Set
 
@@ -254,7 +502,7 @@ Return the response string if optional second argument is non-nil."
   (pop3-send-command process (format "USER %s" user))
   (let ((response (pop3-read-response process t)))
     (if (not (and response (string-match "+OK" response)))
-       (error (format "USER %s not valid." user)))))
+       (error (format "USER %s not valid" user)))))
 
 (defun pop3-pass (process)
   "Send authentication information to the server."
@@ -263,14 +511,65 @@ Return the response string if optional second argument is non-nil."
     (if (not (and response (string-match "+OK" response)))
        (pop3-quit process))))
 
+;; When this file is being compiled in the Gnus (not T-gnus) source
+;; tree, `md5' might have been defined in w3/md5.el, ./lpath.el or one
+;; of some other libraries and `md5' will accept only 3 arguments.  We
+;; will deceive the byte-compiler not to say warnings.
+(eval-when-compile
+  (if (boundp 'byte-compile-function-environment)
+      (let ((def (assq 'md5 byte-compile-function-environment)))
+       (if def
+           (setcdr def '(lambda (object &optional start end
+                                        coding-system noerror)))
+         (setq byte-compile-function-environment
+               (cons '(md5 . (lambda (object &optional start end
+                                             coding-system noerror)))
+                     byte-compile-function-environment))))))
+
+;; Note that `pop3-md5' should never encode a given string to use for
+;; the apop authentication.
+(eval-and-compile
+  (if (fboundp 'md5)
+      (if (condition-case nil
+             (md5 "\
+Check whether the 4th argument CODING-SYSTEM is allowed"
+                  nil nil 'binary)
+           (error nil))
+         ;; Emacs 21 or XEmacs 21
+         ;; (md5 OBJECT &optional START END CODING-SYSTEM NOERROR)
+         (defun pop3-md5 (string)
+           (md5 string nil nil 'binary))
+       ;; The reason why the program reaches here:
+       ;; 1. XEmacs 20 is running and the built-in `md5' doesn't
+       ;;    allow the 4th argument.
+       ;; 2. `md5' has been defined by one of some lisp libraries.
+       ;; 3. This file is being compiled in the Gnus source tree,
+       ;;    and `md5' has been defined in lpath.el.
+       (defalias 'pop3-md5 'md5))
+    ;; The lisp function will be provided by FLIM or other libraries.
+    (autoload 'md5 "md5")
+    (defalias 'pop3-md5 'md5)))
+
 (defun pop3-apop (process user)
   "Send alternate authentication information to the server."
-  (if (not (fboundp 'md5)) (autoload 'md5 "md5"))
-  (let ((hash (md5 (concat pop3-timestamp pop3-password))))
-    (pop3-send-command process (format "APOP %s %s" user hash))
-    (let ((response (pop3-read-response process t)))
-      (if (not (and response (string-match "+OK" response)))
-         (pop3-quit process)))))
+  (let ((pass pop3-password))
+    (if (and pop3-password-required (not pass))
+       (setq pass
+             (read-passwd (format "Password for %s: " pop3-maildrop))))
+    (if pass
+       (let ((hash (pop3-md5 (concat pop3-timestamp pass))))
+         (pop3-send-command process (format "APOP %s %s" user hash))
+         (let ((response (pop3-read-response process t)))
+           (if (not (and response (string-match "+OK" response)))
+               (pop3-quit process)))))
+    ))
+
+(defun pop3-stls (process)
+  "Query whether TLS extension is supported"
+  (pop3-send-command process "STLS")
+  (let ((response (pop3-read-response process t)))
+    (if (not (and response (string-match "+OK" response)))
+       (pop3-quit process))))
 
 ;; TRANSACTION STATE
 
@@ -278,53 +577,19 @@ Return the response string if optional second argument is non-nil."
   "Return the number of messages in the maildrop and the maildrop's size."
   (pop3-send-command process "STAT")
   (let ((response (pop3-read-response process t)))
-    (list (string-to-int (nth 1 (pop3-string-to-list response)))
-         (string-to-int (nth 2 (pop3-string-to-list response))))
+    (list (string-to-int (nth 1 (split-string response " ")))
+         (string-to-int (nth 2 (split-string response " "))))
     ))
 
-(defun pop3-list (process &optional msg)
-  "Scan listing of available messages.
-This function currently does nothing.")
-
 (defun pop3-retr (process msg crashbuf)
   "Retrieve message-id MSG to buffer CRASHBUF."
   (pop3-send-command process (format "RETR %s" msg))
   (pop3-read-response process)
-  (let ((start pop3-read-point) end)
-    (save-excursion
-      (set-buffer (process-buffer process))
-      (while (not (re-search-forward "^\\.\r\n" nil t))
-       (accept-process-output process 3)
-       ;; bill@att.com ... to save wear and tear on the heap
-       ;; uncommented because the condensed version below is a problem for
-       ;; some.
-       (if (> (buffer-size)  20000) (sleep-for 1))
-       (if (> (buffer-size)  50000) (sleep-for 1))
-       (if (> (buffer-size) 100000) (sleep-for 1))
-       (if (> (buffer-size) 200000) (sleep-for 1))
-       (if (> (buffer-size) 500000) (sleep-for 1))
-       ;; bill@att.com
-       ;; condensed into:
-       ;; (sometimes causes problems for really large messages.)
-;      (if (> (buffer-size) 20000) (sleep-for (/ (buffer-size) 20000)))
-       (goto-char start))
-      (setq pop3-read-point (point-marker))
-;; this code does not seem to work for some POP servers...
-;; and I cannot figure out why not.
-;      (goto-char (match-beginning 0))
-;      (backward-char 2)
-;      (if (not (looking-at "\r\n"))
-;        (insert "\r\n"))
-;      (re-search-forward "\\.\r\n")
-      (goto-char (match-beginning 0))
-      (setq end (point-marker))
-      (pop3-clean-region start end)
-      (pop3-munge-message-separator start end)
-      (save-excursion
-       (set-buffer crashbuf)
-       (erase-buffer))
-      (copy-to-buffer crashbuf start end)
-      (delete-region start end)
+  (save-excursion
+    (let ((region (pop3-get-extended-response process)))
+      (pop3-munge-message-separator (car region) (cadr region))
+      (append-to-buffer crashbuf (car region) (cadr region))
+      (delete-region (car region) (cadr region))
       )))
 
 (defun pop3-dele (process msg)
@@ -341,7 +606,7 @@ This function currently does nothing.")
   "Return highest accessed message-id number for the session."
   (pop3-send-command process "LAST")
   (let ((response (pop3-read-response process t)))
-    (string-to-int (nth 1 (pop3-string-to-list response)))
+    (string-to-int (nth 1 (split-string response " ")))
     ))
 
 (defun pop3-rset (process)
@@ -357,11 +622,100 @@ Tell server to remove all messages marked as deleted, unlock the maildrop,
 and close the connection."
   (pop3-send-command process "QUIT")
   (pop3-read-response process t)
-  (if process
+  (when process
+    (save-excursion
+      (set-buffer (process-buffer process))
+      (goto-char (point-max))
+      (delete-process process))))
+
+(defun pop3-uidl (process &optional msgno)
+  "Return the results of a UIDL command in PROCESS for optional MSGNO.
+If UIDL is unsupported on this mail server or if msgno is invalid, return nil.
+Otherwise, return a list in the form
+
+   (N (1 UIDL-1) (2 UIDL-2) ... (N UIDL-N))
+
+where
+
+   N is an integer for the number of UIDLs returned (could be 0)
+   UIDL-n is a string."
+
+  (if msgno
+      (pop3-send-command process (format "UIDL %d" msgno))
+    (pop3-send-command process "UIDL"))
+
+  (if (null (pop3-read-response process t))
+      nil ;; UIDL is not supported on this server
+    (let (pairs uidl)
+      (save-excursion
+       (save-restriction
+         (apply 'narrow-to-region (pop3-get-extended-response process))
+         (goto-char (point-min))
+         (while (looking-at "\\([^ \n\t]*\\) \\([^ \n\t]*\\)")
+           (setq msgno (string-to-int (match-string 1))
+                 uidl (match-string 2))
+           (push (cons msgno uidl) pairs)
+           (beginning-of-line 2))
+         (cons (length pairs) (nreverse pairs))
+         )))))
+
+(defun pop3-list (process &optional msgno)
+  "Return the results of a LIST command for PROCESS and optional MSGNO.
+If (optional) msgno is invalid, return nil.  Otherwise, return a list
+in the form
+
+   (N (1 LEN-1) (2 LEN-2) ... (N LEN-N))
+
+where
+
+   N is an integer for the number of msg/len pairs (could be 0)
+   LEN-n is an integer."
+  (if msgno
+      (pop3-send-command process (format "LIST %d" msgno))
+    (pop3-send-command process "LIST"))
+
+  (if (null (pop3-read-response process t))
+      nil ;; MSGNO is not valid number
+    (let (pairs len)
       (save-excursion
-       (set-buffer (process-buffer process))
-       (goto-char (point-max))
-       (delete-process process))))
+       (save-restriction
+         (apply 'narrow-to-region (pop3-get-extended-response process))
+         (goto-char (point-min))
+         (while (looking-at "\\([^ \n\t]*\\) \\([^ \n\t]*\\)")
+           (setq msgno (string-to-int (match-string 1))
+                 len (string-to-int (match-string 2)))
+           (push (cons msgno len) pairs)
+           (beginning-of-line 2))
+         (cons (length pairs) (nreverse pairs))
+         )))))
+
+(defun pop3-top (process msgno &optional lines)
+  "Return the top LINES of messages for PROCESS and MSGNO.
+If msgno is invalid, return nil.  Otherwise, return a string."
+  (pop3-send-command process (format "TOP %d %d" msgno (or lines 1)))
+  (if (pop3-read-response process t)
+      nil ;; MSGNO is not valid number
+    (save-excursion
+      (apply 'buffer-substring (pop3-get-extended-response process)))
+    ))
+
+;;; Utility code
+
+(defun pop3-get-extended-response (process)
+  "Get the extended pop3 response in the PROCESS buffer."
+  (let ((start pop3-read-point) end)
+    (set-buffer (process-buffer process))
+    (goto-char start)
+    (while (not (re-search-forward "^\\.\r\n" nil t))
+      ;; Fixme: Shouldn't depend on nnheader.
+      (nnheader-accept-process-output process)
+      (goto-char start))
+    (setq pop3-read-point (point-marker))
+    (goto-char (match-beginning 0))
+    (setq end (point-marker))
+    (pop3-clean-region start end)
+    (list start end)))
+
 \f
 ;; Summary of POP3 (Post Office Protocol version 3) commands and responses
 
@@ -388,6 +742,13 @@ and close the connection."
 ;;  -ERR [invalid password]
 ;;  -ERR [unable to lock maildrop]
 
+;; STLS
+;; Arguments: none
+;; Restrictions: authorization state
+;; Possible responses:
+;;  +OK [negotiation is ready]
+;;  -ERR [security layer is already active]
+
 ;;; TRANSACTION STATE
 
 ;; STAT
@@ -403,6 +764,20 @@ and close the connection."
 ;;  +OK [scan listing follows]
 ;;  -ERR [no such message]
 
+;; TOP msg [lines]
+;; Arguments: a message-id (required), number of lines (optional)
+;; Restrictions: transaction state; msg must not be deleted
+;; Possible responses:
+;;  +OK [partial message listing follows]
+;;  -ERR [no such message]
+
+;; UIDL [msg]
+;; Arguments: a message-id (optional)
+;; Restrictions: transaction state; msg must not be deleted
+;; Possible responses:
+;;  +OK [uidl listing follows]
+;;  -ERR [no such message]
+
 ;; RETR msg
 ;; Arguments: a message-id (required)
 ;; Restrictions: transaction state; msg must not be deleted
@@ -442,3 +817,7 @@ and close the connection."
 ;; Restrictions: none
 ;; Possible responses:
 ;;  +OK [TCP connection closed]
+
+(provide 'pop3)
+
+;;; pop3.el ends here
diff --git a/lisp/qp.el b/lisp/qp.el
new file mode 100644 (file)
index 0000000..f87ec66
--- /dev/null
@@ -0,0 +1,171 @@
+;;; qp.el --- Quoted-Printable functions
+
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: mail, extensions
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Functions for encoding and decoding quoted-printable text as
+;; defined in RFC 2045.
+
+;;; Code:
+
+(require 'mm-util)
+(eval-when-compile (defvar mm-use-ultra-safe-encoding))
+
+;;;###autoload
+(defun quoted-printable-decode-region (from to &optional coding-system)
+  "Decode quoted-printable in the region between FROM and TO, per RFC 2045.
+If CODING-SYSTEM is non-nil, decode bytes into characters with that
+coding-system.
+
+Interactively, you can supply the CODING-SYSTEM argument
+with \\[universal-coding-system-argument].
+
+The CODING-SYSTEM argument is a historical hangover and is deprecated.
+QP encodes raw bytes and should be decoded into raw bytes.  Decoding
+them into characters should be done separately."
+  (interactive
+   ;; Let the user determine the coding system with "C-x RET c".
+   (list (region-beginning) (region-end) coding-system-for-read))
+  (unless (mm-coding-system-p coding-system) ; e.g. `ascii' from Gnus
+    (setq coding-system nil))
+  (save-excursion
+    (save-restriction
+      ;; RFC 2045:  ``An "=" followed by two hexadecimal digits, one
+      ;; or both of which are lowercase letters in "abcdef", is
+      ;; formally illegal. A robust implementation might choose to
+      ;; recognize them as the corresponding uppercase letters.''
+      (let ((case-fold-search t))
+       (narrow-to-region from to)
+       ;; Do this in case we're called from Gnus, say, in a buffer
+       ;; which already contains non-ASCII characters which would
+       ;; then get doubly-decoded below.
+       (if coding-system
+           (mm-encode-coding-region (point-min) (point-max) coding-system))
+       (goto-char (point-min))
+       (while (and (skip-chars-forward "^=")
+                   (not (eobp)))
+         (cond ((eq (char-after (1+ (point))) ?\n)
+                (delete-char 2))
+               ((looking-at "=[0-9A-F][0-9A-F]")
+                (let ((byte (string-to-int (buffer-substring (1+ (point))
+                                                             (+ 3 (point)))
+                                           16)))
+                  (mm-insert-byte byte 1)
+                  (delete-char 3)))
+               (t
+                (message "Malformed quoted-printable text")
+                (forward-char)))))
+      (if coding-system
+         (mm-decode-coding-region (point-min) (point-max) coding-system)))))
+
+(defun quoted-printable-decode-string (string &optional coding-system)
+  "Decode the quoted-printable encoded STRING and return the result.
+If CODING-SYSTEM is non-nil, decode the region with coding-system.
+Use of CODING-SYSTEM is deprecated; this function should deal with
+raw bytes, and coding conversion should be done separately."
+  (mm-with-unibyte-buffer
+    (insert string)
+    (quoted-printable-decode-region (point-min) (point-max) coding-system)
+    (buffer-string)))
+
+(defun quoted-printable-encode-region (from to &optional fold class)
+  "Quoted-printable encode the region between FROM and TO per RFC 2045.
+
+If FOLD, fold long lines at 76 characters (as required by the RFC).
+If CLASS is non-nil, translate the characters not matched by that
+regexp class, which is in the form expected by `skip-chars-forward'.
+You should probably avoid non-ASCII characters in this arg.
+
+If `mm-use-ultra-safe-encoding' is set, fold lines unconditionally and
+encode lines starting with \"From\"."
+  (interactive "r")
+  (save-excursion
+    (goto-char from)
+    (if (fboundp 'string-to-multibyte) ; Emacs 22
+       (if (re-search-forward (string-to-multibyte "[^\x0-\x7f\x80-\xff]")
+                              to t)
+           ;; Fixme: This is somewhat misleading.
+           (error "Multibyte character in QP encoding region"))
+      (if (re-search-forward (mm-string-as-multibyte "[^\0-\377]") to t)
+         (error "Multibyte character in QP encoding region"))))
+  (unless class
+    ;; Avoid using 8bit characters. = is \075.
+    ;; Equivalent to "^\000-\007\013\015-\037\200-\377="
+    (setq class "\010-\012\014\040-\074\076-\177"))
+  (save-excursion
+    (save-restriction
+      (narrow-to-region from to)
+      ;; Encode all the non-ascii and control characters.
+      (goto-char (point-min))
+      (while (and (skip-chars-forward class)
+                 (not (eobp)))
+       (insert
+        (prog1
+            ;; To unibyte in case of Emacs 22 eight-bit.
+            (format "=%02X" (mm-multibyte-char-to-unibyte (char-after)))
+          (delete-char 1))))
+      ;; Encode white space at the end of lines.
+      (goto-char (point-min))
+      (while (re-search-forward "[ \t]+$" nil t)
+       (goto-char (match-beginning 0))
+       (while (not (eolp))
+         (insert
+          (prog1
+              (format "=%02X" (char-after))
+            (delete-char 1)))))
+      (let ((mm-use-ultra-safe-encoding
+            (and (boundp 'mm-use-ultra-safe-encoding)
+                 mm-use-ultra-safe-encoding)))
+       (when (or fold mm-use-ultra-safe-encoding)
+         (let ((tab-width 1))          ; HTAB is one character.
+           (goto-char (point-min))
+           (while (not (eobp))
+             ;; In ultra-safe mode, encode "From " at the beginning
+             ;; of a line.
+             (when mm-use-ultra-safe-encoding
+               (if (looking-at "From ")
+                   (replace-match "From=20" nil t)
+                 (if (looking-at "-")
+                     (replace-match "=2D" nil t))))
+             (end-of-line)
+             ;; Fold long lines.
+             (while (> (current-column) 76) ; tab-width must be 1.
+               (beginning-of-line)
+               (forward-char 75)       ; 75 chars plus an "="
+               (search-backward "=" (- (point) 2) t)
+               (insert "=\n")
+               (end-of-line))
+             (forward-line))))))))
+
+(defun quoted-printable-encode-string (string)
+  "Encode the STRING as quoted-printable and return the result."
+  (let ((default-enable-multibyte-characters (mm-multibyte-string-p string)))
+    (with-temp-buffer
+      (insert string)
+      (quoted-printable-encode-region (point-min) (point-max))
+      (buffer-string))))
+
+(provide 'qp)
+
+;;; qp.el ends here
diff --git a/lisp/read-passwd.el b/lisp/read-passwd.el
new file mode 100644 (file)
index 0000000..4542604
--- /dev/null
@@ -0,0 +1,113 @@
+;; read-passwd.el.el --- Read password function for Pterodactyl Gnus.
+;; Copyright (C) 1996,97,98 Free Software Foundation, Inc. , Tatsuya Ichikawa
+;; Author: Tatsuya Ichikawa <t-ichi@po.shiojiri.ne.jp>
+;; Version: 0.01
+;; Keywords: mail , gnus , pop3 , password
+;;
+;; SPECIAL THANKS
+;;    Katsumi Yamaoka <yamaoka@jpl.org>
+;;
+;; This file is part of Semi-gnus.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+;;
+;;
+(require 'mail-source)
+(provide 'read-passwd)
+
+(defun read-pw-read-passwd (prompt)
+  (read-pw-read-noecho prompt t))
+;;
+(defmacro read-pw-read-char-exclusive ()
+  (cond ((featurep 'xemacs)
+        '(let ((table (quote ((backspace . ?\C-h) (delete . ?\C-?)
+                              (left . ?\C-h))))
+               event key)
+           (while (not
+                   (and
+                    (key-press-event-p (setq event (next-command-event)))
+                    (setq key (or (event-to-character event)
+                                  (cdr (assq (event-key event) table)))))))
+           key))
+       ((fboundp 'read-char-exclusive)
+        '(read-char-exclusive))
+       (t
+        '(read-char))))
+;;
+(defun read-pw-read-noecho (prompt &optional stars)
+  "Read a single line of text from user without echoing, and return it.
+Argument PROMPT ."
+  (let ((ans "")
+       (c 0)
+       (echo-keystrokes 0)
+       (cursor-in-echo-area t)
+       (log-message-max-size 0)
+       message-log-max done msg truncate)
+    (while (not done)
+      (if (or (not stars) (string-equal "" ans))
+         (setq msg prompt)
+       (setq msg (concat prompt (make-string (length ans) ?*)))
+       (setq truncate
+             (1+ (- (length msg) (window-width (minibuffer-window)))))
+       (and (> truncate 0)
+            (setq msg (concat "$" (substring msg (1+ truncate))))))
+      (message "%s" msg)
+      (setq c (read-pw-read-char-exclusive))
+      (cond ((eq ?\C-g c)
+            (setq quit-flag t
+                  done t))
+           ((memq c '(?\r ?\n ?\e))
+            (setq done t))
+           ((eq ?\C-u c)
+            (setq ans ""))
+           ((and (/= ?\b c) (/= ?\177 c))
+            (setq ans (concat ans (char-to-string c))))
+           ((> (length ans) 0)
+            (setq ans (substring ans 0 -1)))))
+    (if quit-flag
+       (prog1
+           (setq quit-flag nil)
+         (message "Quit")
+         (beep t))
+      (message "")
+      ans)))
+;;
+(defvar pw nil)
+(defun read-pw-set-mail-source-passwd-cache ()
+  (if (not mail-source-password-cache)
+      (car (mapcar
+           (lambda (x)
+             (when (eq 'pop (car x))
+               (mail-source-bind (pop x)
+                 (let ((from (format "%s:%s:%s" server user port))
+                       (mail-source-string
+                        (format "pop:%s@%s" user server)))
+                   (setq pw (read-pw-return-passwd-string user server))
+                   (unless (assoc user mail-source-password-cache)
+                     (set-alist 'mail-source-password-cache
+                                (format "%s:%s:%s" server user port)
+                                pw))
+                   (cdr (assoc from mail-source-password-cache))))))
+           mail-sources))))
+;;
+;;
+(defvar passwd nil)
+(defun read-pw-return-passwd-string (user server)
+  (setq passwd (read-pw-read-passwd
+               (message "POP Password for %s at %s : " user server)))
+  passwd)
+;;
+;; read-passwd.el ends here.
diff --git a/lisp/rfc1843.el b/lisp/rfc1843.el
new file mode 100644 (file)
index 0000000..16260cb
--- /dev/null
@@ -0,0 +1,185 @@
+;;; rfc1843.el --- HZ (rfc1843) decoding
+;; Copyright (c) 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: news HZ HZ+ mail i18n
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Usage:
+;; (require 'rfc1843)
+;; (rfc1843-gnus-setup)
+;;
+;; Test:
+;; (rfc1843-decode-string  "~{<:Ky2;S{#,NpJ)l6HK!#~}")
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'mm-util)
+
+(defvar rfc1843-word-regexp
+  "~\\({\\([\041-\167][\041-\176]\\| \\)+\\)\\(~}\\|$\\)")
+
+(defvar rfc1843-word-regexp-strictly
+  "~\\({\\([\041-\167][\041-\176]\\)+\\)\\(~}\\|$\\)")
+
+(defvar rfc1843-hzp-word-regexp
+  "~\\({\\([\041-\167][\041-\176]\\| \\)+\\|\
+\[<>]\\([\041-\175][\041-\176]\\| \\)+\\)\\(~}\\|$\\)")
+
+(defvar rfc1843-hzp-word-regexp-strictly
+  "~\\({\\([\041-\167][\041-\176]\\)+\\|\
+\[<>]\\([\041-\175][\041-\176]\\)+\\)\\(~}\\|$\\)")
+
+(defcustom rfc1843-decode-loosely nil
+  "Loosely check HZ encoding if non-nil.
+When it is set non-nil, only buffers or strings with strictly
+HZ-encoded are decoded."
+  :type 'boolean
+  :group 'mime)
+
+(defcustom rfc1843-decode-hzp t
+  "HZ+ decoding support if non-nil.
+HZ+ specification (also known as HZP) is to provide a standardized
+7-bit representation of mixed Big5, GB, and ASCII text for convenient
+e-mail transmission, news posting, etc.
+The document of HZ+ 0.78 specification can be found at
+ftp://ftp.math.psu.edu/pub/simpson/chinese/hzp/hzp.doc"
+  :type 'boolean
+  :group 'mime)
+
+(defcustom rfc1843-newsgroups-regexp "chinese\\|hz"
+  "Regexp of newsgroups in which might be HZ encoded."
+  :type 'string
+  :group 'mime)
+
+(defun rfc1843-decode-region (from to)
+  "Decode HZ in the region between FROM and TO."
+  (interactive "r")
+  (let (str firstc)
+    (save-excursion
+      (goto-char from)
+      (if (or rfc1843-decode-loosely
+             (re-search-forward (if rfc1843-decode-hzp
+                                    rfc1843-hzp-word-regexp-strictly
+                                  rfc1843-word-regexp-strictly) to t))
+         (save-restriction
+           (narrow-to-region from to)
+           (goto-char (point-min))
+           (while (re-search-forward (if rfc1843-decode-hzp
+                                         rfc1843-hzp-word-regexp
+                                       rfc1843-word-regexp) (point-max) t)
+             ;;; Text with extents may cause XEmacs crash
+             (setq str (buffer-substring-no-properties
+                        (match-beginning 1)
+                        (match-end 1)))
+             (setq firstc (aref str 0))
+             (insert (mm-decode-coding-string
+                      (rfc1843-decode
+                       (prog1
+                           (substring str 1)
+                         (delete-region (match-beginning 0) (match-end 0)))
+                       firstc)
+                      (if (eq firstc ?{) 'cn-gb-2312 'cn-big5))))
+           (goto-char (point-min))
+           (while (search-forward "~" (point-max) t)
+             (cond ((eq (char-after) ?\n)
+                    (delete-char -1)
+                    (delete-char 1))
+                   ((eq (char-after) ?~)
+                    (delete-char 1)))))))))
+
+(defun rfc1843-decode-string (string)
+  "Decode HZ STRING and return the results."
+  (let ((m (mm-multibyte-p)))
+    (with-temp-buffer
+      (when m
+       (mm-enable-multibyte))
+      (insert string)
+      (inline
+       (rfc1843-decode-region (point-min) (point-max)))
+      (buffer-string))))
+
+(defun rfc1843-decode (word &optional firstc)
+  "Decode HZ WORD and return it."
+  (let ((i -1) (s (substring word 0)) v)
+    (if (or (not firstc) (eq firstc ?{))
+       (while (< (incf i) (length s))
+         (if (eq (setq v (aref s i)) ? ) nil
+           (aset s i (+ 128 v))))
+      (while (< (incf i) (length s))
+       (if (eq (setq v (aref s i)) ? ) nil
+         (setq v (+ (* 94 v) (aref s (1+ i)) -3135))
+         (aset s i (+ (/ v 157) (if (eq firstc ?<) 201 161)))
+         (setq v (% v 157))
+         (aset s (incf i) (+ v (if (< v 63) 64 98))))))
+    s))
+
+(defun rfc1843-decode-article-body ()
+  "Decode HZ encoded text in the article body."
+  (if (string-match (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
+                   (or gnus-newsgroup-name ""))
+      (save-excursion
+       (save-restriction
+         (message-narrow-to-head)
+         (let* ((inhibit-point-motion-hooks t)
+                (case-fold-search t)
+                (ct (message-fetch-field "Content-Type" t))
+                (ctl (and ct (ignore-errors
+                               (mail-header-parse-content-type ct)))))
+           (if (and ctl (not (string-match "/" (car ctl))))
+               (setq ctl nil))
+           (goto-char (point-max))
+           (widen)
+           (forward-line 1)
+           (narrow-to-region (point) (point-max))
+           (when (or (not ctl)
+                     (equal (car ctl) "text/plain"))
+             (rfc1843-decode-region (point) (point-max))))))))
+
+(defvar rfc1843-old-gnus-decode-header-function  nil)
+(defvar gnus-decode-header-methods)
+(defvar gnus-decode-encoded-word-methods)
+(defvar gnus-decode-encoded-word-function)
+
+(defun rfc1843-gnus-setup ()
+  "Setup HZ decoding for Gnus."
+  (require 'gnus-art)
+  (require 'gnus-sum)
+  (add-hook 'gnus-article-decode-hook 'rfc1843-decode-article-body t)
+  (setq gnus-decode-encoded-word-function
+       'gnus-multi-decode-encoded-word-string
+       gnus-decode-header-function
+       'gnus-multi-decode-header
+       gnus-decode-encoded-word-methods
+       (nconc gnus-decode-encoded-word-methods
+              (list
+               (cons (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
+                     'rfc1843-decode-string)))
+       gnus-decode-header-methods
+       (nconc gnus-decode-header-methods
+              (list
+               (cons (concat "\\<\\(" rfc1843-newsgroups-regexp "\\)\\>")
+                     'rfc1843-decode-region)))))
+
+(provide 'rfc1843)
+
+;;; rfc1843.el ends here
diff --git a/lisp/rfc2045.el b/lisp/rfc2045.el
new file mode 100644 (file)
index 0000000..ba3116b
--- /dev/null
@@ -0,0 +1,43 @@
+;;; rfc2045.el --- Functions for decoding rfc2045 headers
+
+;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; RFC 2045 is: "Multipurpose Internet Mail Extensions (MIME) Part
+;; One:  Format of Internet Message Bodies".
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ietf-drums)
+
+(defun rfc2045-encode-string (param value)
+  "Return and PARAM=VALUE string encoded according to RFC2045."
+  (if (or (string-match (concat "[" ietf-drums-no-ws-ctl-token "]") value)
+         (string-match (concat "[" ietf-drums-tspecials "]") value)
+         (string-match "[ \n\t]" value)
+         (not (string-match (concat "[" ietf-drums-text-token "]") value)))
+      (concat param "=" (format "%S" value))
+    (concat param "=" value)))
+
+(provide 'rfc2045)
+
+;;; rfc2045.el ends here
diff --git a/lisp/rfc2047.el b/lisp/rfc2047.el
new file mode 100644 (file)
index 0000000..3453f7b
--- /dev/null
@@ -0,0 +1,762 @@
+;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages
+;; Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; RFC 2047 is "MIME (Multipurpose Internet Mail Extensions) Part
+;; Three:  Message Header Extensions for Non-ASCII Text".
+
+;;; Code:
+
+(eval-when-compile
+  (require 'cl)
+  (defvar message-posting-charset)
+  (unless (fboundp 'with-syntax-table) ; not in Emacs 20
+    (defmacro with-syntax-table (table &rest body)
+      "Evaluate BODY with syntax table of current buffer set to TABLE.
+The syntax table of the current buffer is saved, BODY is evaluated, and the
+saved table is restored, even in case of an abnormal exit.
+Value is what BODY returns."
+      (let ((old-table (make-symbol "table"))
+           (old-buffer (make-symbol "buffer")))
+       `(let ((,old-table (syntax-table))
+              (,old-buffer (current-buffer)))
+          (unwind-protect
+              (progn
+                (set-syntax-table ,table)
+                ,@body)
+            (save-current-buffer
+              (set-buffer ,old-buffer)
+              (set-syntax-table ,old-table))))))))
+
+(require 'qp)
+(require 'mm-util)
+;; Fixme: Avoid this (used for mail-parse-charset) mm dependence on gnus.
+(require 'mail-prsvr)
+(require 'base64)
+(autoload 'mm-body-7-or-8 "mm-bodies")
+
+(eval-and-compile
+  ;; Avoid gnus-util for mm- code.
+  (defalias 'rfc2047-point-at-bol
+    (if (fboundp 'point-at-bol)
+       'point-at-bol
+      'line-beginning-position))
+
+  (defalias 'rfc2047-point-at-eol
+    (if (fboundp 'point-at-eol)
+       'point-at-eol
+      'line-end-position)))
+
+(defvar rfc2047-header-encoding-alist
+  '(("Newsgroups" . nil)
+    ("Followup-To" . nil)
+    ("Message-ID" . nil)
+    ("\\(Resent-\\)?\\(From\\|Cc\\|To\\|Bcc\\|Reply-To\\|Sender\
+\\|Mail-Followup-To\\|Mail-Copies-To\\|Approved\\)" . address-mime)
+    (t . mime))
+  "*Header/encoding method alist.
+The list is traversed sequentially.  The keys can either be
+header regexps or t.
+
+The values can be:
+
+1) nil, in which case no encoding is done;
+2) `mime', in which case the header will be encoded according to RFC2047;
+3) `address-mime', like `mime', but takes account of the rules for address
+   fields (where quoted strings and comments must be treated separately);
+4) a charset, in which case it will be encoded as that charset;
+5) `default', in which case the field will be encoded as the rest
+   of the article.")
+
+(defvar rfc2047-charset-encoding-alist
+  '((us-ascii . nil)
+    (iso-8859-1 . Q)
+    (iso-8859-2 . Q)
+    (iso-8859-3 . Q)
+    (iso-8859-4 . Q)
+    (iso-8859-5 . B)
+    (koi8-r . B)
+    (iso-8859-7 . B)
+    (iso-8859-8 . B)
+    (iso-8859-9 . Q)
+    (iso-8859-14 . Q)
+    (iso-8859-15 . Q)
+    (iso-2022-jp . B)
+    (iso-2022-kr . B)
+    (gb2312 . B)
+    (big5 . B)
+    (cn-big5 . B)
+    (cn-gb . B)
+    (cn-gb-2312 . B)
+    (euc-kr . B)
+    (iso-2022-jp-2 . B)
+    (iso-2022-int-1 . B)
+    (viscii . Q))
+  "Alist of MIME charsets to RFC2047 encodings.
+Valid encodings are nil, `Q' and `B'.  These indicate binary (no) encoding,
+quoted-printable and base64 respectively.")
+
+(defvar rfc2047-encoding-function-alist
+  '((Q . rfc2047-q-encode-region)
+    (B . rfc2047-b-encode-region)
+    (nil . ignore))
+  "Alist of RFC2047 encodings to encoding functions.")
+
+;;;
+;;; Functions for encoding RFC2047 messages
+;;;
+
+(defun rfc2047-narrow-to-field ()
+  "Narrow the buffer to the header on the current line."
+  (beginning-of-line)
+  (narrow-to-region
+   (point)
+   (progn
+     (forward-line 1)
+     (if (re-search-forward "^[^ \n\t]" nil t)
+        (rfc2047-point-at-bol)
+       (point-max))))
+  (goto-char (point-min)))
+
+(defun rfc2047-field-value ()
+  "Return the value of the field at point."
+  (save-excursion
+    (save-restriction
+      (rfc2047-narrow-to-field)
+      (re-search-forward ":[ \t\n]*" nil t)
+      (buffer-substring (point) (point-max)))))
+
+(defvar rfc2047-encoding-type 'address-mime
+  "The type of encoding done by `rfc2047-encode-region'.
+This should be dynamically bound around calls to
+`rfc2047-encode-region' to either `mime' or `address-mime'.  See
+`rfc2047-header-encoding-alist', for definitions.")
+
+(defun rfc2047-encode-message-header ()
+  "Encode the message header according to `rfc2047-header-encoding-alist'.
+Should be called narrowed to the head of the message."
+  (interactive "*")
+  (save-excursion
+    (goto-char (point-min))
+    (let (alist elem method)
+      (while (not (eobp))
+       (save-restriction
+         (rfc2047-narrow-to-field)
+         (if (not (rfc2047-encodable-p))
+             (prog1
+                 (if (and (eq (mm-body-7-or-8) '8bit)
+                          (mm-multibyte-p)
+                          (mm-coding-system-p
+                           (car message-posting-charset)))
+                     ;; 8 bit must be decoded.
+                     (mm-encode-coding-region
+                      (point-min) (point-max)
+                      (mm-charset-to-coding-system
+                       (car message-posting-charset))))
+               ;; No encoding necessary, but folding is nice
+               (rfc2047-fold-region
+                (save-excursion
+                  (goto-char (point-min))
+                  (skip-chars-forward "^:")
+                  (when (looking-at ": ")
+                    (forward-char 2))
+                  (point))
+                (point-max)))
+           ;; We found something that may perhaps be encoded.
+           (setq method nil
+                 alist rfc2047-header-encoding-alist)
+           (while (setq elem (pop alist))
+             (when (or (and (stringp (car elem))
+                            (looking-at (car elem)))
+                       (eq (car elem) t))
+               (setq alist nil
+                     method (cdr elem))))
+           (goto-char (point-min))
+           (re-search-forward "^[^:]+: *" nil t)
+           (cond
+            ((eq method 'address-mime)
+             (rfc2047-encode-region (point) (point-max)))
+            ((eq method 'mime)
+             (let ((rfc2047-encoding-type 'mime))
+               (rfc2047-encode-region (point) (point-max))))
+            ((eq method 'default)
+             (if (and (featurep 'mule)
+                      (if (boundp 'default-enable-multibyte-characters)
+                          default-enable-multibyte-characters)
+                      mail-parse-charset)
+                 (mm-encode-coding-region (point) (point-max)
+                                          mail-parse-charset)))
+            ;; We get this when CC'ing messsages to newsgroups with
+            ;; 8-bit names.  The group name mail copy just got
+            ;; unconditionally encoded.  Previously, it would ask
+            ;; whether to encode, which was quite confusing for the
+            ;; user.  If the new behaviour is wrong, tell me. I have
+            ;; left the old code commented out below.
+            ;; -- Per Abrahamsen <abraham@dina.kvl.dk> Date: 2001-10-07.
+            ;; Modified by Dave Love, with the commented-out code changed
+            ;; in accordance with changes elsewhere.
+            ((null method)
+             (rfc2047-encode-region (point) (point-max)))
+;;;         ((null method)
+;;;          (if (or (message-options-get
+;;;                   'rfc2047-encode-message-header-encode-any)
+;;;                  (message-options-set
+;;;                   'rfc2047-encode-message-header-encode-any
+;;;                   (y-or-n-p
+;;;                    "Some texts are not encoded. Encode anyway?")))
+;;;              (rfc2047-encode-region (point-min) (point-max))
+;;;            (error "Cannot send unencoded text")))
+            ((mm-coding-system-p method)
+             (if (and (featurep 'mule)
+                      (if (boundp 'default-enable-multibyte-characters)
+                          default-enable-multibyte-characters))
+                 (mm-encode-coding-region (point) (point-max) method)))
+            ;; Hm.
+            (t)))
+         (goto-char (point-max)))))))
+
+;; Fixme: This, and the require below may not be the Right Thing, but
+;; should be safe just before release.  -- fx 2001-02-08
+(eval-when-compile (defvar message-posting-charset))
+
+(defun rfc2047-encodable-p ()
+  "Return non-nil if any characters in current buffer need encoding in headers.
+The buffer may be narrowed."
+  (require 'message)                   ; for message-posting-charset
+  (let ((charsets
+        (mm-find-mime-charset-region (point-min) (point-max))))
+    (and charsets
+        (not (equal charsets (list (car message-posting-charset)))))))
+
+;; Use this syntax table when parsing into regions that may need
+;; encoding.  Double quotes are string delimiters, backslash is
+;; character quoting, and all other RFC 2822 special characters are
+;; treated as punctuation so we can use forward-sexp/forward-word to
+;; skip to the end of regions appropriately.  Nb. ietf-drums does
+;; things differently.
+(defconst rfc2047-syntax-table
+  ;; (make-char-table 'syntax-table '(2)) only works in Emacs.
+  (let ((table (make-syntax-table)))
+    ;; The following is done to work for setting all elements of the table
+    ;; in Emacs 21 and 22 and XEmacs; it appears to be the cleanest way.
+    ;; Play safe and don't assume the form of the word syntax entry --
+    ;; copy it from ?a.
+    (if (fboundp 'set-char-table-range)        ; Emacs
+       (funcall (intern "set-char-table-range")
+                table t (aref (standard-syntax-table) ?a))
+      (if (fboundp 'put-char-table)
+         (if (fboundp 'get-char-table) ; warning avoidance
+             (put-char-table t (get-char-table ?a (standard-syntax-table))
+                             table))))
+    (modify-syntax-entry ?\\ "\\" table)
+    (modify-syntax-entry ?\" "\"" table)
+    (modify-syntax-entry ?\( "." table)
+    (modify-syntax-entry ?\) "." table)
+    (modify-syntax-entry ?\< "." table)
+    (modify-syntax-entry ?\> "." table)
+    (modify-syntax-entry ?\[ "." table)
+    (modify-syntax-entry ?\] "." table)
+    (modify-syntax-entry ?: "." table)
+    (modify-syntax-entry ?\; "." table)
+    (modify-syntax-entry ?, "." table)
+    (modify-syntax-entry ?@ "." table)
+    table))
+
+(defun rfc2047-encode-region (b e)
+  "Encode words in region B to E that need encoding.
+By default, the region is treated as containing RFC2822 addresses.
+Dynamically bind `rfc2047-encoding-type' to change that."
+  (save-restriction
+    (narrow-to-region b e)
+    (if (eq 'mime rfc2047-encoding-type)
+       ;; Simple case.  Treat as single word after any initial ASCII
+       ;; part and before any tailing ASCII part.  The leading ASCII
+       ;; is relevant for instance in Subject headers with `Re:' for
+       ;; interoperability with non-MIME clients, and we might as
+       ;; well avoid the tail too.
+       (progn
+         (goto-char (point-min))
+         ;; Does it need encoding?
+         (skip-chars-forward "\000-\177")
+         (unless (eobp)
+           (skip-chars-backward "^ \n") ; beginning of space-delimited word
+           (rfc2047-encode (point) (progn
+                                     (goto-char e)
+                                     (skip-chars-backward "\000-\177")
+                                     (skip-chars-forward "^ \n")
+                                     ;; end of space-delimited word
+                                     (point)))))
+      ;; `address-mime' case -- take care of quoted words, comments.
+      (with-syntax-table rfc2047-syntax-table
+       (let ((start)                   ; start of current token
+             end                       ; end of current token
+             ;; Whether there's an encoded word before the current
+             ;; token, either immediately or separated by space.
+             last-encoded)
+         (goto-char (point-min))
+         (condition-case nil           ; in case of unbalanced quotes
+             ;; Look for rfc2822-style: sequences of atoms, quoted
+             ;; strings, specials, whitespace.  (Specials mustn't be
+             ;; encoded.)
+             (while (not (eobp))
+               (setq start (point))
+               ;; Skip whitespace.
+               (unless (= 0 (skip-chars-forward " \t\n"))
+                 (setq start (point)))
+               (cond
+                ((not (char-after)))   ; eob
+                ;; else token start
+                ((eq ?\" (char-syntax (char-after)))
+                 ;; Quoted word.
+                 (forward-sexp)
+                 (setq end (point))
+                 ;; Does it need encoding?
+                 (goto-char start)
+                 (skip-chars-forward "\000-\177" end)
+                 (if (= end (point))
+                     (setq last-encoded  nil)
+                   ;; It needs encoding.  Strip the quotes first,
+                   ;; since encoded words can't occur in quotes.
+                   (goto-char end)
+                   (delete-backward-char 1)
+                   (goto-char start)
+                   (delete-char 1)
+                   (when last-encoded
+                     ;; There was a preceding quoted word.  We need
+                     ;; to include any separating whitespace in this
+                     ;; word to avoid it getting lost.
+                     (skip-chars-backward " \t")
+                     ;; A space is needed between the encoded words.
+                     (insert ? )
+                     (setq start (point)
+                           end (1+ end)))
+                   ;; Adjust the end position for the deleted quotes.
+                   (rfc2047-encode start (- end 2))
+                   (setq last-encoded t))) ; record that it was encoded
+                ((eq ?. (char-syntax (char-after)))
+                 ;; Skip other delimiters, but record that they've
+                 ;; potentially separated quoted words.
+                 (forward-char)
+                 (setq last-encoded nil))
+                (t                 ; normal token/whitespace sequence
+                 ;; Find the end.
+                 (forward-word 1)
+                 (skip-chars-backward " \t")
+                 (setq end (point))
+                 ;; Deal with encoding and leading space as for
+                 ;; quoted words.
+                 (goto-char start)
+                 (skip-chars-forward "\000-\177" end)
+                 (if (= end (point))
+                     (setq last-encoded  nil)
+                   (when last-encoded
+                     (goto-char start)
+                     (skip-chars-backward " \t")
+                     (insert ? )
+                     (setq start (point)
+                           end (1+ end)))
+                   (rfc2047-encode start end)
+                   (setq last-encoded t)))))
+           (error
+            (error "Invalid data for rfc2047 encoding: %s"
+                   (buffer-substring b e)))))))
+    (rfc2047-fold-region b (point))))
+
+(defun rfc2047-encode-string (string)
+  "Encode words in STRING.
+By default, the string is treated as containing addresses (see
+`rfc2047-encoding-type')."
+  (with-temp-buffer
+    (insert string)
+    (rfc2047-encode-region (point-min) (point-max))
+    (buffer-string)))
+
+(defun rfc2047-encode (b e)
+  "Encode the word(s) in the region B to E.
+By default, the region is treated as containing addresses (see
+`rfc2047-encoding-type')."
+  (let* ((mime-charset (mm-find-mime-charset-region b e))
+        (cs (if (> (length mime-charset) 1)
+                ;; Fixme: Instead of this, try to break region into
+                ;; parts that can be encoded separately.
+                (error "Can't rfc2047-encode `%s'"
+                       (buffer-substring b e))
+              (setq mime-charset (car mime-charset))
+              (mm-charset-to-coding-system mime-charset)))
+        ;; Fixme: Better, calculate the number of non-ASCII
+        ;; characters, at least for 8-bit charsets.
+        (encoding (or (cdr (assq mime-charset
+                                 rfc2047-charset-encoding-alist))
+                      ;; For the charsets that don't have a preferred
+                      ;; encoding, choose the one that's shorter.
+                      (save-restriction
+                        (narrow-to-region b e)
+                        (if (eq (mm-qp-or-base64) 'base64)
+                            'B
+                          'Q))))
+        (start (concat
+                "=?" (downcase (symbol-name mime-charset)) "?"
+                (downcase (symbol-name encoding)) "?"))
+        (factor (case mime-charset
+                  ((iso-8859-5 iso-8859-7 iso-8859-8 koi8-r) 1)
+                  ((big5 gb2312 euc-kr) 2)
+                  (utf-8 4)
+                  (t 8)))
+        (pre (- b (save-restriction
+                    (widen)
+                    (rfc2047-point-at-bol))))
+        ;; encoded-words must not be longer than 75 characters,
+        ;; including charset, encoding etc.  This leaves us with
+        ;; 75 - (length start) - 2 - 2 characters.  The last 2 is for
+        ;; possible base64 padding.  In the worst case (iso-2022-*)
+        ;; each character expands to 8 bytes which is expanded by a
+        ;; factor of 4/3 by base64 encoding.
+        (length (floor (- 75 (length start) 4) (* factor (/ 4.0 3.0))))
+        ;; Limit line length to 76 characters.
+        (length1 (max 1 (floor (- 76 (length start) 4 pre)
+                               (* factor (/ 4.0 3.0)))))
+        (first t))
+    (if mime-charset
+       (save-restriction
+         (narrow-to-region b e)
+         (when (eq encoding 'B)
+           ;; break into lines before encoding
+           (goto-char (point-min))
+           (while (not (eobp))
+             (if first
+                 (progn
+                   (goto-char (min (point-max) (+ length1 (point))))
+                   (setq first nil))
+               (goto-char (min (point-max) (+ length (point)))))
+             (unless (eobp)
+               (insert ?\n)))
+           (setq first t))
+         (if (and (mm-multibyte-p)
+                  (mm-coding-system-p cs))
+             (mm-encode-coding-region (point-min) (point-max) cs))
+         (funcall (cdr (assq encoding rfc2047-encoding-function-alist))
+                  (point-min) (point-max))
+         (goto-char (point-min))
+         (while (not (eobp))
+           (unless first
+             (insert ? ))
+           (setq first nil)
+           (insert start)
+           (end-of-line)
+           (insert "?=")
+           (forward-line 1))))))
+
+(defun rfc2047-fold-field ()
+  "Fold the current header field."
+  (save-excursion
+    (save-restriction
+      (rfc2047-narrow-to-field)
+      (rfc2047-fold-region (point-min) (point-max)))))
+
+(defun rfc2047-fold-region (b e)
+  "Fold long lines in region B to E."
+  (save-restriction
+    (narrow-to-region b e)
+    (goto-char (point-min))
+    (let ((break nil)
+         (qword-break nil)
+         (first t)
+         (bol (save-restriction
+                (widen)
+                (rfc2047-point-at-bol))))
+      (while (not (eobp))
+       (when (and (or break qword-break)
+                  (> (- (point) bol) 76))
+         (goto-char (or break qword-break))
+         (setq break nil
+               qword-break nil)
+         (if (looking-at "[ \t]")
+             (insert ?\n)
+           (insert "\n "))
+         (setq bol (1- (point)))
+         ;; Don't break before the first non-LWSP characters.
+         (skip-chars-forward " \t")
+         (unless (eobp)
+           (forward-char 1)))
+       (cond
+        ((eq (char-after) ?\n)
+         (forward-char 1)
+         (setq bol (point)
+               break nil
+               qword-break nil)
+         (skip-chars-forward " \t")
+         (unless (or (eobp) (eq (char-after) ?\n))
+           (forward-char 1)))
+        ((eq (char-after) ?\r)
+         (forward-char 1))
+        ((memq (char-after) '(?  ?\t))
+         (skip-chars-forward " \t")
+         (if first
+             ;; Don't break just after the header name.
+             (setq first nil)
+           (setq break (1- (point)))))
+        ((not break)
+         (if (not (looking-at "=\\?[^=]"))
+             (if (eq (char-after) ?=)
+                 (forward-char 1)
+               (skip-chars-forward "^ \t\n\r="))
+           ;; Don't break at the start of the field.
+           (unless (= (point) b)
+             (setq qword-break (point)))
+           (skip-chars-forward "^ \t\n\r")))
+        (t
+         (skip-chars-forward "^ \t\n\r"))))
+      (when (and (or break qword-break)
+                (> (- (point) bol) 76))
+       (goto-char (or break qword-break))
+       (setq break nil
+             qword-break nil)
+       (if (looking-at "[ \t]")
+           (insert ?\n)
+         (insert "\n "))
+       (setq bol (1- (point)))
+       ;; Don't break before the first non-LWSP characters.
+       (skip-chars-forward " \t")
+       (unless (eobp)
+         (forward-char 1))))))
+
+(defun rfc2047-unfold-field ()
+  "Fold the current line."
+  (save-excursion
+    (save-restriction
+      (rfc2047-narrow-to-field)
+      (rfc2047-unfold-region (point-min) (point-max)))))
+
+(defun rfc2047-unfold-region (b e)
+  "Unfold lines in region B to E."
+  (save-restriction
+    (narrow-to-region b e)
+    (goto-char (point-min))
+    (let ((bol (save-restriction
+                (widen)
+                (rfc2047-point-at-bol)))
+         (eol (rfc2047-point-at-eol)))
+      (forward-line 1)
+      (while (not (eobp))
+       (if (and (looking-at "[ \t]")
+                (< (- (rfc2047-point-at-eol) bol) 76))
+           (delete-region eol (progn
+                                (goto-char eol)
+                                (skip-chars-forward "\r\n")
+                                (point)))
+         (setq bol (rfc2047-point-at-bol)))
+       (setq eol (rfc2047-point-at-eol))
+       (forward-line 1)))))
+
+(defun rfc2047-b-encode-region (b e)
+  "Base64-encode the header contained in region B to E."
+  (save-restriction
+    (narrow-to-region (goto-char b) e)
+    (while (not (eobp))
+      (base64-encode-region (point) (progn (end-of-line) (point)) t)
+      (if (and (bolp) (eolp))
+         (delete-backward-char 1))
+      (forward-line))))
+
+(defun rfc2047-q-encode-region (b e)
+  "Quoted-printable-encode the header in region B to E."
+  (save-excursion
+    (save-restriction
+      (narrow-to-region (goto-char b) e)
+      (let ((bol (save-restriction
+                  (widen)
+                  (rfc2047-point-at-bol))))
+       (quoted-printable-encode-region
+        b e nil
+        ;; = (\075), _ (\137), ? (\077) are used in the encoded word.
+        ;; Avoid using 8bit characters.
+        ;; This list excludes `especials' (see the RFC2047 syntax),
+        ;; meaning that some characters in non-structured fields will
+        ;; get encoded when they con't need to be.  The following is
+        ;; what it used to be.
+;;;     ;; Equivalent to "^\000-\007\011\013\015-\037\200-\377=_?"
+;;;     "\010\012\014\040-\074\076\100-\136\140-\177")
+        "-\b\n\f !#-'*+0-9A-Z\\^`-~\d")
+       (subst-char-in-region (point-min) (point-max) ?  ?_)
+       ;; The size of QP encapsulation is about 20, so set limit to
+       ;; 56=76-20.
+       (unless (< (- (point-max) (point-min)) 56)
+         ;; Don't break if it could fit in one line.
+         ;; Let rfc2047-encode-region break it later.
+         (goto-char (1+ (point-min)))
+         (while (and (not (bobp)) (not (eobp)))
+           (goto-char (min (point-max) (+ 56 bol)))
+           (search-backward "=" (- (point) 2) t)
+           (unless (or (bobp) (eobp))
+             (insert ?\n)
+             (setq bol (point)))))))))
+
+;;;
+;;; Functions for decoding RFC2047 messages
+;;;
+
+(eval-and-compile
+  (defconst rfc2047-encoded-word-regexp
+    "=\\?\\([^][\000-\040()<>@,\;:\\\"/?.=]+\\)\\?\\(B\\|Q\\)\
+\\?\\([!->@-~ +]*\\)\\?="))
+
+;; Fixme: This should decode in place, not cons intermediate strings.
+;; Also check whether it needs to worry about delimiting fields like
+;; encoding.
+
+;; In fact it's reported that (invalid) encoding of mailboxes in
+;; addr-specs is in use, so delimiting fields might help.  Probably
+;; not decoding a word which isn't properly delimited is good enough
+;; and worthwhile (is it more correct or not?), e.g. something like
+;; `=?iso-8859-1?q?foo?=@'.
+
+(defun rfc2047-decode-region (start end)
+  "Decode MIME-encoded words in region between START and END."
+  (interactive "r")
+  (let ((case-fold-search t)
+       b e)
+    (save-excursion
+      (save-restriction
+       (narrow-to-region start end)
+       (goto-char (point-min))
+       ;; Remove whitespace between encoded words.
+       (while (re-search-forward
+               (eval-when-compile
+                 (concat "\\(" rfc2047-encoded-word-regexp "\\)"
+                         "\\(\n?[ \t]\\)+"
+                         "\\(" rfc2047-encoded-word-regexp "\\)"))
+               nil t)
+         (delete-region (goto-char (match-end 1)) (match-beginning 6)))
+       ;; Decode the encoded words.
+       (setq b (goto-char (point-min)))
+       (while (re-search-forward rfc2047-encoded-word-regexp nil t)
+         (setq e (match-beginning 0))
+         (insert (rfc2047-parse-and-decode
+                  (prog1
+                      (match-string 0)
+                    (delete-region (match-beginning 0) (match-end 0)))))
+         ;; Remove newlines between decoded words, though such things
+         ;; essentially must not be there.
+         (save-restriction
+           (narrow-to-region e (point))
+           (goto-char e)
+           (while (re-search-forward "[\n\r]+" nil t)
+             (replace-match " "))
+           (goto-char (point-max)))
+         (when (and (mm-multibyte-p)
+                    mail-parse-charset
+                    (not (eq mail-parse-charset 'us-ascii))
+                    (not (eq mail-parse-charset 'gnus-decoded)))
+           (mm-decode-coding-region b e mail-parse-charset))
+         (setq b (point)))
+       (when (and (mm-multibyte-p)
+                  mail-parse-charset
+                  (not (eq mail-parse-charset 'us-ascii))
+                  (not (eq mail-parse-charset 'gnus-decoded)))
+         (mm-decode-coding-region b (point-max) mail-parse-charset))))))
+
+(defun rfc2047-decode-string (string)
+  "Decode the quoted-printable-encoded STRING and return the results."
+  (let ((m (mm-multibyte-p)))
+    (if (string-match "=\\?" string)
+       (with-temp-buffer
+         ;; Fixme: This logic is wrong, but seems to be required by
+         ;; Gnus summary buffer generation.  The value of `m' depends
+         ;; on the current buffer, not global multibyteness or that
+         ;; of the string.  Also the string returned should always be
+         ;; multibyte in a multibyte session, i.e. the buffer should
+         ;; be multibyte before `buffer-string' is called.
+         (when m
+           (mm-enable-multibyte))
+         (insert string)
+         (inline
+           (rfc2047-decode-region (point-min) (point-max)))
+         (buffer-string))
+      ;; Fixme: As above, `m' here is inappropriate.
+      (if (and m
+              mail-parse-charset
+              (not (eq mail-parse-charset 'us-ascii))
+              (not (eq mail-parse-charset 'gnus-decoded)))
+         (mm-decode-coding-string string mail-parse-charset)
+       (mm-string-as-multibyte string)))))
+
+(defun rfc2047-parse-and-decode (word)
+  "Decode WORD and return it if it is an encoded word.
+Return WORD if it is not not an encoded word or if the charset isn't
+decodable."
+  (if (not (string-match rfc2047-encoded-word-regexp word))
+      word
+    (or
+     (condition-case nil
+        (rfc2047-decode
+         (match-string 1 word)
+         (upcase (match-string 2 word))
+         (match-string 3 word))
+       (error word))
+     word)))                           ; un-decodable
+
+(defun rfc2047-pad-base64 (string)
+  "Pad STRING to quartets."
+  ;; Be more liberal to accept buggy base64 strings. If
+  ;; base64-decode-string accepts buggy strings, this function could
+  ;; be aliased to identity.
+  (case (mod (length string) 4)
+    (0 string)
+    (1 string) ;; Error, don't pad it.
+    (2 (concat string "=="))
+    (3 (concat string "="))))
+
+(defun rfc2047-decode (charset encoding string)
+  "Decode STRING from the given MIME CHARSET in the given ENCODING.
+Valid ENCODINGs are \"B\" and \"Q\".
+If your Emacs implementation can't decode CHARSET, return nil."
+  (if (stringp charset)
+      (setq charset (intern (downcase charset))))
+  (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)
+       (setq cs mail-parse-charset))
+      (mm-decode-coding-string
+       (cond
+       ((equal "B" encoding)
+        (base64-decode-string
+         (rfc2047-pad-base64 string)))
+       ((equal "Q" encoding)
+        (quoted-printable-decode-string
+         (mm-replace-chars-in-string string ?_ ? )))
+       (t (error "Invalid encoding: %s" encoding)))
+       cs))))
+
+(provide 'rfc2047)
+
+;;; rfc2047.el ends here
diff --git a/lisp/rfc2104.el b/lisp/rfc2104.el
new file mode 100644 (file)
index 0000000..5496a4f
--- /dev/null
@@ -0,0 +1,117 @@
+;;; rfc2104.el --- RFC2104 Hashed Message Authentication Codes
+;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <jas@pdc.kth.se>
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; This is a quick'n'dirty, low performance, implementation of RFC2104.
+;;;
+;;; Example:
+;;;
+;;; (require 'md5)
+;;; (rfc2104-hash 'md5 64 16 "Jefe" "what do ya want for nothing?")
+;;; "750c783e6ab0b503eaa86e310a5db738"
+;;;
+;;; (require 'sha-1)
+;;; (rfc2104-hash 'sha1-encode 64 20 "Jefe" "what do ya want for nothing?")
+;;; "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"
+;;;
+;;; 64 is block length of hash function (64 for MD5 and SHA), 16 is
+;;; resulting hash length (16 for MD5, 20 for SHA).
+;;;
+;;; Tested with Emacs 20.2 and XEmacs 20.3.
+;;;
+;;; Test case reference: RFC 2202.
+
+;;; Release history:
+;;;
+;;; 1998-08-16  initial release posted to gnu.emacs.sources
+;;; 1998-08-17  use append instead of char-list-to-string
+;;; 1998-08-26  don't require hexl
+;;; 1998-09-25  renamed from hmac.el to rfc2104.el, also renamed functions
+;;; 1999-10-23  included in pgnus
+;;; 2000-08-15  `rfc2104-hexstring-to-bitstring'
+;;; 2000-05-12  added sha-1 example, added test case reference
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+;; Magic character for inner HMAC round. 0x36 == 54 == '6'
+(defconst rfc2104-ipad ?\x36)
+
+;; Magic character for outer HMAC round. 0x5C == 92 == '\'
+(defconst rfc2104-opad ?\x5C)
+
+;; Not so magic character for padding the key. 0x00
+(defconst rfc2104-zero ?\x00)
+
+;; Alist for converting hex to decimal.
+(defconst rfc2104-hex-alist
+  '((?0 . 0)         (?a . 10)       (?A . 10)
+    (?1 . 1)         (?b . 11)       (?B . 11)
+    (?2 . 2)         (?c . 12)       (?C . 12)
+    (?3 . 3)         (?d . 13)       (?D . 13)
+    (?4 . 4)         (?e . 14)       (?E . 14)
+    (?5 . 5)         (?f . 15)       (?F . 15)
+    (?6 . 6)
+    (?7 . 7)
+    (?8 . 8)
+    (?9 . 9)))
+
+(defun rfc2104-hex-to-int (str)
+  (if str
+      (if (listp str)
+         (+ (* 16 (rfc2104-hex-to-int (cdr str)))
+            (cdr (assoc (car str) rfc2104-hex-alist)))
+       (rfc2104-hex-to-int (reverse (append str nil))))
+    0))
+
+(defun rfc2104-hexstring-to-bitstring (str)
+  (let (out)
+    (while (< 0 (length str))
+      (push (rfc2104-hex-to-int (substring str -2)) out)
+      (setq str (substring str 0 -2)))
+    (concat out)))
+
+(defun rfc2104-hash (hash block-length hash-length key text)
+  (let* (;; if key is longer than B, reset it to HASH(key)
+        (key (if (> (length key) block-length)
+                 (funcall hash key) key))
+        (k_ipad (append key nil))
+        (k_opad (append key nil)))
+    ;; zero pad k_ipad/k_opad
+    (while (< (length k_ipad) block-length)
+      (setq k_ipad (append k_ipad (list rfc2104-zero))))
+    (while (< (length k_opad) block-length)
+      (setq k_opad (append k_opad (list rfc2104-zero))))
+    ;; XOR key with ipad/opad into k_ipad/k_opad
+    (setq k_ipad (mapcar (lambda (c) (logxor c rfc2104-ipad)) k_ipad))
+    (setq k_opad (mapcar (lambda (c) (logxor c rfc2104-opad)) k_opad))
+    ;; perform outer hash
+    (funcall hash (concat k_opad (rfc2104-hexstring-to-bitstring
+                                 ;; perform inner hash
+                                 (funcall hash (concat k_ipad text)))))))
+
+(provide 'rfc2104)
+
+;;; rfc2104.el ends here
diff --git a/lisp/rfc2231.el b/lisp/rfc2231.el
new file mode 100644 (file)
index 0000000..bd88c71
--- /dev/null
@@ -0,0 +1,227 @@
+;;; rfc2231.el --- Functions for decoding rfc2231 headers
+
+;; Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(eval-when-compile (require 'gnus-clfns))
+
+(eval-when-compile (require 'cl))
+(require 'ietf-drums)
+(require 'rfc2047)
+(autoload 'mm-encode-body "mm-bodies")
+(autoload 'mail-header-remove-whitespace "mail-parse")
+(autoload 'mail-header-remove-comments "mail-parse")
+
+(defun rfc2231-get-value (ct attribute)
+  "Return the value of ATTRIBUTE from CT."
+  (cdr (assq attribute (cdr ct))))
+
+(defun rfc2231-parse-qp-string (string)
+  "Parse QP-encoded string using `rfc2231-parse-string'.
+N.B.  This is in violation with RFC2047, but it seem to be in common use."
+  (rfc2231-parse-string (rfc2047-decode-string string)))
+
+(defun rfc2231-parse-string (string)
+  "Parse STRING and return a list.
+The list will be on the form
+ `(name (attribute . value) (attribute . value)...)"
+  (with-temp-buffer
+    (let ((ttoken (ietf-drums-token-to-list ietf-drums-text-token))
+         (stoken (ietf-drums-token-to-list ietf-drums-tspecials))
+         (ntoken (ietf-drums-token-to-list "0-9"))
+         (prev-value "")
+         display-name mailbox c display-string parameters
+         attribute value type subtype number encoded
+         prev-attribute)
+      (ietf-drums-init (mail-header-remove-whitespace
+                       (mail-header-remove-comments string)))
+      (let ((table (copy-syntax-table ietf-drums-syntax-table)))
+       (modify-syntax-entry ?\' "w" table)
+       (modify-syntax-entry ?= " " table)
+       ;; The following isn't valid, but one should be liberal
+       ;; in what one receives.
+       (modify-syntax-entry ?\: "w" table)
+       (set-syntax-table table))
+      (setq c (char-after))
+      (when (and (memq c ttoken)
+                (not (memq c stoken)))
+       (setq type (downcase (buffer-substring
+                             (point) (progn (forward-sexp 1) (point)))))
+       ;; Do the params
+       (while (not (eobp))
+         (setq c (char-after))
+         (unless (eq c ?\;)
+           (error "Invalid header: %s" string))
+         (forward-char 1)
+         ;; If c in nil, then this is an invalid header, but
+         ;; since elm generates invalid headers on this form,
+         ;; we allow it.
+         (when (setq c (char-after))
+           (if (and (memq c ttoken)
+                    (not (memq c stoken)))
+               (setq attribute
+                     (intern
+                      (downcase
+                       (buffer-substring
+                        (point) (progn (forward-sexp 1) (point))))))
+             (error "Invalid header: %s" string))
+           (setq c (char-after))
+           (setq encoded nil)
+           (when (eq c ?*)
+             (forward-char 1)
+             (setq c (char-after))
+             (if (not (memq c ntoken))
+                 (setq encoded t
+                       number nil)
+               (setq number
+                     (string-to-number
+                      (buffer-substring
+                       (point) (progn (forward-sexp 1) (point)))))
+               (setq c (char-after))
+               (when (eq c ?*)
+                 (setq encoded t)
+                 (forward-char 1)
+                 (setq c (char-after)))))
+           ;; See if we have any previous continuations.
+           (when (and prev-attribute
+                      (not (eq prev-attribute attribute)))
+             (push (cons prev-attribute prev-value) parameters)
+             (setq prev-attribute nil
+                   prev-value ""))
+           (unless (eq c ?=)
+             (error "Invalid header: %s" string))
+           (forward-char 1)
+           (setq c (char-after))
+           (cond
+            ((eq c ?\")
+             (setq value
+                   (buffer-substring (1+ (point))
+                                     (progn (forward-sexp 1) (1- (point))))))
+            ((and (or (memq c ttoken)
+                      (> c ?\177)) ;; EXTENSION: Support non-ascii chars.
+                  (not (memq c stoken)))
+             (setq value (buffer-substring
+                          (point) (progn (forward-sexp) (point)))))
+            (t
+             (error "Invalid header: %s" string)))
+           (when encoded
+             (setq value (rfc2231-decode-encoded-string value)))
+           (if number
+               (setq prev-attribute attribute
+                     prev-value (concat prev-value value))
+             (push (cons attribute value) parameters))))
+
+       ;; Take care of any final continuations.
+       (when prev-attribute
+         (push (cons prev-attribute prev-value) parameters))
+
+       (when type
+         `(,type ,@(nreverse parameters)))))))
+
+(defun rfc2231-decode-encoded-string (string)
+  "Decode an RFC2231-encoded string.
+These look like \"us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A\"."
+  (with-temp-buffer
+    (let ((elems (split-string string "'")))
+      ;; The encoded string may contain zero to two single-quote
+      ;; marks.  This should give us the encoded word stripped
+      ;; of any preceding values.
+      (insert (car (last elems)))
+      (goto-char (point-min))
+      (while (search-forward "%" nil t)
+       (insert
+        (prog1
+            (string-to-number (buffer-substring (point) (+ (point) 2)) 16)
+          (delete-region (1- (point)) (+ (point) 2)))))
+      ;; Encode using the charset, if any.
+      (when (and (mm-multibyte-p)
+                (> (length elems) 1)
+                (not (equal (intern (downcase (car elems))) 'us-ascii)))
+       (mm-decode-coding-region (point-min) (point-max)
+                                (intern (downcase (car elems)))))
+      (buffer-string))))
+
+(defun rfc2231-encode-string (param value)
+  "Return and PARAM=VALUE string encoded according to RFC2231."
+  (let ((control (ietf-drums-token-to-list ietf-drums-no-ws-ctl-token))
+       (tspecial (ietf-drums-token-to-list ietf-drums-tspecials))
+       (special (ietf-drums-token-to-list "*'%\n\t"))
+       (ascii (ietf-drums-token-to-list ietf-drums-text-token))
+       (num -1)
+       spacep encodep charsetp charset broken)
+    (with-temp-buffer
+      (insert value)
+      (goto-char (point-min))
+      (while (not (eobp))
+       (cond
+        ((or (memq (following-char) control)
+             (memq (following-char) tspecial)
+             (memq (following-char) special))
+         (setq encodep t))
+        ((eq (following-char) ? )
+         (setq spacep t))
+        ((not (memq (following-char) ascii))
+         (setq charsetp t)))
+       (forward-char 1))
+      (when charsetp
+       (setq charset (mm-encode-body)))
+      (cond
+       ((or encodep charsetp)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (when (> (current-column) 60)
+           (insert ";\n")
+           (setq broken t))
+         (if (or (not (memq (following-char) ascii))
+                 (memq (following-char) control)
+                 (memq (following-char) tspecial)
+                 (memq (following-char) special)
+                 (eq (following-char) ? ))
+             (progn
+               (insert "%" (format "%02x" (following-char)))
+               (delete-char 1))
+           (forward-char 1)))
+       (goto-char (point-min))
+       (insert (symbol-name (or charset 'us-ascii)) "''")
+       (goto-char (point-min))
+       (if (not broken)
+           (insert param "*=")
+         (while (not (eobp))
+           (insert (if (>= num 0) " " "\n ")
+                   param "*" (format "%d" (incf num)) "*=")
+           (forward-line 1))))
+       (spacep
+       (goto-char (point-min))
+       (insert param "=\"")
+       (goto-char (point-max))
+       (insert "\""))
+       (t
+       (goto-char (point-min))
+       (insert param "=")))
+      (buffer-string))))
+
+(provide 'rfc2231)
+
+;;; rfc2231.el ends here
index fdb8d71..66ed642 100644 (file)
@@ -1,7 +1,8 @@
 ;;; score-mode.el --- mode for editing Gnus score files
-;; Copyright (C) 1996 Free Software Foundation, Inc.
 
-;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+;; Copyright (C) 1996, 2001 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
 
 ;; This file is part of GNU Emacs.
@@ -25,9 +26,8 @@
 
 ;;; Code:
 
-(require 'easymenu)
-(require 'timezone)
 (eval-when-compile (require 'cl))
+(eval-when-compile (require 'static))
 
 (defvar gnus-score-mode-hook nil
   "*Hook run in score mode buffers.")
 
 (defvar gnus-score-mode-map nil)
 (unless gnus-score-mode-map
-  (setq gnus-score-mode-map (copy-keymap emacs-lisp-mode-map))
+  (setq gnus-score-mode-map (make-sparse-keymap))
+  (set-keymap-parent gnus-score-mode-map emacs-lisp-mode-map)
   (define-key gnus-score-mode-map "\C-c\C-c" 'gnus-score-edit-exit)
   (define-key gnus-score-mode-map "\C-c\C-d" 'gnus-score-edit-insert-date)
   (define-key gnus-score-mode-map "\C-c\C-p" 'gnus-score-pretty-print))
 
+(defvar score-mode-syntax-table
+  (let ((table (copy-syntax-table lisp-mode-syntax-table)))
+    (modify-syntax-entry ?| "w" table)
+    table)
+  "Syntax table used in score-mode buffers.")
+
+(defvar score-mode-coding-system (static-if (boundp 'MULE)
+                                    '*ctext*
+                                  'ctext))
+
 ;;;###autoload
 (defun gnus-score-mode ()
   "Mode for editing Gnus score files.
@@ -55,7 +66,7 @@ This mode is an extended emacs-lisp mode.
   (kill-all-local-variables)
   (use-local-map gnus-score-mode-map)
   (gnus-score-make-menu-bar)
-  (set-syntax-table emacs-lisp-mode-syntax-table)
+  (set-syntax-table score-mode-syntax-table)
   (setq major-mode 'gnus-score-mode)
   (setq mode-name "Score")
   (lisp-mode-variables nil)
@@ -75,7 +86,7 @@ This mode is an extended emacs-lisp mode.
 (defun gnus-score-edit-insert-date ()
   "Insert date in numerical format."
   (interactive)
-  (princ (gnus-score-day-number (current-time)) (current-buffer)))
+  (princ (time-to-days (current-time)) (current-buffer)))
 
 (defun gnus-score-pretty-print ()
   "Format the current score file."
@@ -83,7 +94,8 @@ This mode is an extended emacs-lisp mode.
   (goto-char (point-min))
   (let ((form (read (current-buffer))))
     (erase-buffer)
-    (pp form (current-buffer)))
+    (let ((emacs-lisp-mode-syntax-table score-mode-syntax-table))
+      (pp form (current-buffer))))
   (goto-char (point-min)))
 
 (defun gnus-score-edit-exit ()
@@ -91,7 +103,7 @@ This mode is an extended emacs-lisp mode.
   (interactive)
   (unless (file-exists-p (file-name-directory (buffer-file-name)))
     (make-directory (file-name-directory (buffer-file-name)) t))
-  (save-buffer)
+  (save-buffer-as-coding-system score-mode-coding-system)
   (bury-buffer (current-buffer))
   (let ((buf (current-buffer)))
     (when gnus-score-edit-exit-function
@@ -99,11 +111,6 @@ This mode is an extended emacs-lisp mode.
     (when (eq buf (current-buffer))
       (switch-to-buffer (other-buffer (current-buffer))))))
 
-(defun gnus-score-day-number (time)
-  (let ((dat (decode-time time)))
-    (timezone-absolute-from-gregorian
-     (nth 4 dat) (nth 3 dat) (nth 5 dat))))
-
 (provide 'score-mode)
 
 ;;; score-mode.el ends here
diff --git a/lisp/sha1-el.el b/lisp/sha1-el.el
new file mode 100644 (file)
index 0000000..ab5804d
--- /dev/null
@@ -0,0 +1,444 @@
+;;; sha1-el.el --- SHA1 Secure Hash Algorithm in Emacs-Lisp.
+
+;; Copyright (C) 1999, 2001, 2003  Free Software Foundation, Inc.
+
+;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+;; Keywords: SHA1, FIPS 180-1
+
+;; This file is part of FLIM (Faithful Library about Internet Message).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This program is implemented from the definition of SHA-1 in FIPS PUB
+;; 180-1 (Federal Information Processing Standards Publication 180-1),
+;; "Announcing the Standard for SECURE HASH STANDARD".
+;; <URL:http://www.itl.nist.gov/div897/pubs/fip180-1.htm>
+;; (EXCEPTION; two optimizations taken from GnuPG/cipher/sha1.c)
+;;
+;; Test cases from FIPS PUB 180-1.
+;;
+;; (sha1 "abc")
+;; => a9993e364706816aba3e25717850c26c9cd0d89d
+;;
+;; (sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
+;; => 84983e441c3bd26ebaae4aa1f95129e5e54670f1
+;;
+;; (sha1 (make-string 1000000 ?a))
+;; => 34aa973cd4c4daa4f61eeb2bdbad27316534016f
+;;
+;; BUGS:
+;;  * It is assumed that length of input string is less than 2^29 bytes.
+;;  * It is caller's responsibility to make string (or region) unibyte.
+;;
+;; TODO:
+;;  * Rewrite from scratch!
+;;    This version is much faster than Keiichi Suzuki's another sha1.el,
+;;    but it is too dirty.
+
+;;; Code:
+
+(require 'hex-util)
+
+(autoload 'executable-find "executable")
+
+;;;
+;;; external SHA1 function.
+;;;
+
+(defgroup sha1 nil
+  "Elisp interface for SHA1 hash computation."
+  :group 'extensions)
+
+(defcustom sha1-maximum-internal-length 500
+  "*Maximum length of message to use lisp version of SHA1 function.
+If message is longer than this, `sha1-program' is used instead.
+
+If this variable is set to 0, use extarnal program only.
+If this variable is set to nil, use internal function only."
+  :type 'integer
+  :group 'sha1)
+
+(defcustom sha1-program '("sha1sum")
+  "*Name of program to compute SHA1.
+It must be a string \(program name\) or list of strings \(name and its args\)."
+  :type '(repeat string)
+  :group 'sha1)
+
+(defcustom sha1-use-external (condition-case ()
+                                (executable-find (car sha1-program))
+                              (error))
+  "*Use external SHA1 program.
+If this variable is set to nil, use internal function only."
+  :type 'boolean
+  :group 'sha1)
+
+(defun sha1-string-external (string)
+  ;; `with-temp-buffer' is new in v20, so we do not use it.
+  (save-excursion
+    (let (buffer)
+      (unwind-protect
+         (let (prog args)
+           (if (consp sha1-program)
+               (setq prog (car sha1-program)
+                     args (cdr sha1-program))
+             (setq prog sha1-program
+                   args nil))
+           (setq buffer (set-buffer
+                         (generate-new-buffer " *sha1 external*")))
+           (insert string)
+           (apply (function call-process-region)
+                  (point-min)(point-max)
+                  prog t t nil args)
+           ;; SHA1 is 40 bytes long in hexadecimal form.
+           (buffer-substring (point-min)(+ (point-min) 40)))
+       (and buffer
+            (buffer-name buffer)
+            (kill-buffer buffer))))))
+
+(defun sha1-region-external (beg end)
+  (sha1-string-external (buffer-substring-no-properties beg end)))
+
+;;;
+;;; internal SHA1 function.
+;;;
+
+(eval-when-compile
+  ;; optional second arg of string-to-number is new in v20.
+  (defconst sha1-K0-high 23170)                ; (string-to-number "5A82" 16)
+  (defconst sha1-K0-low  31129)                ; (string-to-number "7999" 16)
+  (defconst sha1-K1-high 28377)                ; (string-to-number "6ED9" 16)
+  (defconst sha1-K1-low  60321)                ; (string-to-number "EBA1" 16)
+  (defconst sha1-K2-high 36635)                ; (string-to-number "8F1B" 16)
+  (defconst sha1-K2-low  48348)                ; (string-to-number "BCDC" 16)
+  (defconst sha1-K3-high 51810)                ; (string-to-number "CA62" 16)
+  (defconst sha1-K3-low  49622)                ; (string-to-number "C1D6" 16)
+
+;;; original definition of sha1-F0.
+;;; (defmacro sha1-F0 (B C D)
+;;;   (` (logior (logand (, B) (, C))
+;;;         (logand (lognot (, B)) (, D)))))
+;;; a little optimization from GnuPG/cipher/sha1.c.
+  (defmacro sha1-F0 (B C D)
+    (` (logxor (, D) (logand (, B) (logxor (, C) (, D))))))
+  (defmacro sha1-F1 (B C D)
+    (` (logxor (, B) (, C) (, D))))
+;;; original definition of sha1-F2.
+;;; (defmacro sha1-F2 (B C D)
+;;;   (` (logior (logand (, B) (, C))
+;;;         (logand (, B) (, D))
+;;;         (logand (, C) (, D)))))
+;;; a little optimization from GnuPG/cipher/sha1.c.
+  (defmacro sha1-F2 (B C D)
+    (` (logior (logand (, B) (, C))
+              (logand (, D) (logior (, B) (, C))))))
+  (defmacro sha1-F3 (B C D)
+    (` (logxor (, B) (, C) (, D))))
+
+  (defmacro sha1-S1  (W-high W-low)
+    (` (let ((W-high (, W-high))
+            (W-low  (, W-low)))
+        (setq S1W-high (+ (% (* W-high 2) 65536)
+                          (/ W-low (, (/ 65536 2)))))
+        (setq S1W-low (+ (/ W-high (, (/ 65536 2)))
+                         (% (* W-low 2) 65536))))))
+  (defmacro sha1-S5  (A-high A-low)
+    (` (progn
+        (setq S5A-high (+ (% (* (, A-high) 32) 65536)
+                          (/ (, A-low) (, (/ 65536 32)))))
+        (setq S5A-low  (+ (/ (, A-high) (, (/ 65536 32)))
+                          (% (* (, A-low) 32) 65536))))))
+  (defmacro sha1-S30 (B-high B-low)
+    (` (progn
+        (setq S30B-high (+ (/ (, B-high) 4)
+                           (* (% (, B-low) 4) (, (/ 65536 4)))))
+        (setq S30B-low  (+ (/ (, B-low) 4)
+                           (* (% (, B-high) 4) (, (/ 65536 4))))))))
+
+  (defmacro sha1-OP (round)
+    (` (progn
+        (sha1-S5 sha1-A-high sha1-A-low)
+        (sha1-S30 sha1-B-high sha1-B-low)
+        (setq sha1-A-low (+ ((, (intern (format "sha1-F%d" round)))
+                             sha1-B-low sha1-C-low sha1-D-low)
+                            sha1-E-low
+                            (, (symbol-value
+                                (intern (format "sha1-K%d-low" round))))
+                            (aref block-low idx)
+                            (progn
+                              (setq sha1-E-low sha1-D-low)
+                              (setq sha1-D-low sha1-C-low)
+                              (setq sha1-C-low S30B-low)
+                              (setq sha1-B-low sha1-A-low)
+                              S5A-low)))
+        (setq carry (/ sha1-A-low 65536))
+        (setq sha1-A-low (% sha1-A-low 65536))
+        (setq sha1-A-high (% (+ ((, (intern (format "sha1-F%d" round)))
+                                 sha1-B-high sha1-C-high sha1-D-high)
+                                sha1-E-high
+                                (, (symbol-value
+                                    (intern (format "sha1-K%d-high" round))))
+                                (aref block-high idx)
+                                (progn
+                                  (setq sha1-E-high sha1-D-high)
+                                  (setq sha1-D-high sha1-C-high)
+                                  (setq sha1-C-high S30B-high)
+                                  (setq sha1-B-high sha1-A-high)
+                                  S5A-high)
+                                carry)
+                             65536)))))
+
+  (defmacro sha1-add-to-H (H X)
+    (` (progn
+        (setq (, (intern (format "sha1-%s-low" H)))
+              (+ (, (intern (format "sha1-%s-low" H)))
+                 (, (intern (format "sha1-%s-low" X)))))
+        (setq carry (/ (, (intern (format "sha1-%s-low" H))) 65536))
+        (setq (, (intern (format "sha1-%s-low" H)))
+              (% (, (intern (format "sha1-%s-low" H))) 65536))
+        (setq (, (intern (format "sha1-%s-high" H)))
+              (% (+ (, (intern (format "sha1-%s-high" H)))
+                    (, (intern (format "sha1-%s-high" X)))
+                    carry)
+                 65536)))))
+  )
+
+;;; buffers (H0 H1 H2 H3 H4).
+(defvar sha1-H0-high)
+(defvar sha1-H0-low)
+(defvar sha1-H1-high)
+(defvar sha1-H1-low)
+(defvar sha1-H2-high)
+(defvar sha1-H2-low)
+(defvar sha1-H3-high)
+(defvar sha1-H3-low)
+(defvar sha1-H4-high)
+(defvar sha1-H4-low)
+
+(defun sha1-block (block-high block-low)
+  (let (;; step (c) --- initialize buffers (A B C D E).
+       (sha1-A-high sha1-H0-high) (sha1-A-low sha1-H0-low)
+       (sha1-B-high sha1-H1-high) (sha1-B-low sha1-H1-low)
+       (sha1-C-high sha1-H2-high) (sha1-C-low sha1-H2-low)
+       (sha1-D-high sha1-H3-high) (sha1-D-low sha1-H3-low)
+       (sha1-E-high sha1-H4-high) (sha1-E-low sha1-H4-low)
+       (idx 16))
+    ;; step (b).
+    (let (;; temporary variables used in sha1-S1 macro.
+         S1W-high S1W-low)
+      (while (< idx 80)
+       (sha1-S1 (logxor (aref block-high (- idx 3))
+                        (aref block-high (- idx 8))
+                        (aref block-high (- idx 14))
+                        (aref block-high (- idx 16)))
+                (logxor (aref block-low  (- idx 3))
+                        (aref block-low  (- idx 8))
+                        (aref block-low  (- idx 14))
+                        (aref block-low  (- idx 16))))
+       (aset block-high idx S1W-high)
+       (aset block-low  idx S1W-low)
+       (setq idx (1+ idx))))
+    ;; step (d).
+    (setq idx 0)
+    (let (;; temporary variables used in sha1-OP macro.
+         S5A-high S5A-low S30B-high S30B-low carry)
+      (while (< idx 20) (sha1-OP 0) (setq idx (1+ idx)))
+      (while (< idx 40) (sha1-OP 1) (setq idx (1+ idx)))
+      (while (< idx 60) (sha1-OP 2) (setq idx (1+ idx)))
+      (while (< idx 80) (sha1-OP 3) (setq idx (1+ idx))))
+    ;; step (e).
+    (let (;; temporary variables used in sha1-add-to-H macro.
+         carry)
+      (sha1-add-to-H H0 A)
+      (sha1-add-to-H H1 B)
+      (sha1-add-to-H H2 C)
+      (sha1-add-to-H H3 D)
+      (sha1-add-to-H H4 E))))
+
+(defun sha1-binary (string)
+  "Return the SHA1 of STRING in binary form."
+  (let (;; prepare buffers for a block. byte-length of block is 64.
+       ;; input block is split into two vectors.
+       ;;
+       ;; input block: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ...
+       ;; block-high:  +-0-+       +-1-+       +-2-+       +-3-+
+       ;; block-low:         +-0-+       +-1-+       +-2-+       +-3-+
+       ;;
+       ;; length of each vector is 80, and elements of each vector are
+       ;; 16bit integers.  elements 0x10-0x4F of each vector are
+       ;; assigned later in `sha1-block'.
+       (block-high (eval-when-compile (make-vector 80 nil)))
+       (block-low  (eval-when-compile (make-vector 80 nil))))
+    (unwind-protect
+       (let* (;; byte-length of input string.
+              (len (length string))
+              (lim (* (/ len 64) 64))
+              (rem (% len 4))
+              (idx 0)(pos 0))
+         ;; initialize buffers (H0 H1 H2 H3 H4).
+         (setq sha1-H0-high 26437      ; (string-to-number "6745" 16)
+               sha1-H0-low  8961       ; (string-to-number "2301" 16)
+               sha1-H1-high 61389      ; (string-to-number "EFCD" 16)
+               sha1-H1-low  43913      ; (string-to-number "AB89" 16)
+               sha1-H2-high 39098      ; (string-to-number "98BA" 16)
+               sha1-H2-low  56574      ; (string-to-number "DCFE" 16)
+               sha1-H3-high 4146       ; (string-to-number "1032" 16)
+               sha1-H3-low  21622      ; (string-to-number "5476" 16)
+               sha1-H4-high 50130      ; (string-to-number "C3D2" 16)
+               sha1-H4-low  57840)     ; (string-to-number "E1F0" 16)
+         ;; loop for each 64 bytes block.
+         (while (< pos lim)
+           ;; step (a).
+           (setq idx 0)
+           (while (< idx 16)
+             (aset block-high idx (+ (* (aref string pos) 256)
+                                     (aref string (1+ pos))))
+             (setq pos (+ pos 2))
+             (aset block-low  idx (+ (* (aref string pos) 256)
+                                     (aref string (1+ pos))))
+             (setq pos (+ pos 2))
+             (setq idx (1+ idx)))
+           (sha1-block block-high block-low))
+         ;; last block.
+         (if (prog1
+                 (< (- len lim) 56)
+               (setq lim (- len rem))
+               (setq idx 0)
+               (while (< pos lim)
+                 (aset block-high idx (+ (* (aref string pos) 256)
+                                         (aref string (1+ pos))))
+                 (setq pos (+ pos 2))
+                 (aset block-low  idx (+ (* (aref string pos) 256)
+                                         (aref string (1+ pos))))
+                 (setq pos (+ pos 2))
+                 (setq idx (1+ idx)))
+               ;; this is the last (at most) 32bit word.
+               (cond
+                ((= rem 3)
+                 (aset block-high idx (+ (* (aref string pos) 256)
+                                         (aref string (1+ pos))))
+                 (setq pos (+ pos 2))
+                 (aset block-low  idx (+ (* (aref string pos) 256)
+                                         128)))
+                ((= rem 2)
+                 (aset block-high idx (+ (* (aref string pos) 256)
+                                         (aref string (1+ pos))))
+                 (aset block-low  idx 32768))
+                ((= rem 1)
+                 (aset block-high idx (+ (* (aref string pos) 256)
+                                         128))
+                 (aset block-low  idx 0))
+                (t ;; (= rem 0)
+                 (aset block-high idx 32768)
+                 (aset block-low  idx 0)))
+               (setq idx (1+ idx))
+               (while (< idx 16)
+                 (aset block-high idx 0)
+                 (aset block-low  idx 0)
+                 (setq idx (1+ idx))))
+             ;; last block has enough room to write the length of string.
+             (progn
+               ;; write bit length of string to last 4 bytes of the block.
+               (aset block-low  15 (* (% len 8192) 8))
+               (setq len (/ len 8192))
+               (aset block-high 15 (% len 65536))
+               ;; XXX: It is not practical to compute SHA1 of
+               ;;      such a huge message on emacs.
+               ;; (setq len (/ len 65536))     ; for 64bit emacs.
+               ;; (aset block-low  14 (% len 65536))
+               ;; (aset block-high 14 (/ len 65536))
+               (sha1-block block-high block-low))
+           ;; need one more block.
+           (sha1-block block-high block-low)
+           (fillarray block-high 0)
+           (fillarray block-low  0)
+           ;; write bit length of string to last 4 bytes of the block.
+           (aset block-low  15 (* (% len 8192) 8))
+           (setq len (/ len 8192))
+           (aset block-high 15 (% len 65536))
+           ;; XXX: It is not practical to compute SHA1 of
+           ;;      such a huge message on emacs.
+           ;; (setq len (/ len 65536))         ; for 64bit emacs.
+           ;; (aset block-low  14 (% len 65536))
+           ;; (aset block-high 14 (/ len 65536))
+           (sha1-block block-high block-low))
+         ;; make output string (in binary form).
+         (let ((result (make-string 20 0)))
+           (aset result  0 (/ sha1-H0-high 256))
+           (aset result  1 (% sha1-H0-high 256))
+           (aset result  2 (/ sha1-H0-low  256))
+           (aset result  3 (% sha1-H0-low  256))
+           (aset result  4 (/ sha1-H1-high 256))
+           (aset result  5 (% sha1-H1-high 256))
+           (aset result  6 (/ sha1-H1-low  256))
+           (aset result  7 (% sha1-H1-low  256))
+           (aset result  8 (/ sha1-H2-high 256))
+           (aset result  9 (% sha1-H2-high 256))
+           (aset result 10 (/ sha1-H2-low  256))
+           (aset result 11 (% sha1-H2-low  256))
+           (aset result 12 (/ sha1-H3-high 256))
+           (aset result 13 (% sha1-H3-high 256))
+           (aset result 14 (/ sha1-H3-low  256))
+           (aset result 15 (% sha1-H3-low  256))
+           (aset result 16 (/ sha1-H4-high 256))
+           (aset result 17 (% sha1-H4-high 256))
+           (aset result 18 (/ sha1-H4-low  256))
+           (aset result 19 (% sha1-H4-low  256))
+           result))
+      ;; do not leave a copy of input string.
+      (fillarray block-high nil)
+      (fillarray block-low  nil))))
+
+(defun sha1-string-internal (string)
+  (encode-hex-string (sha1-binary string)))
+
+(defun sha1-region-internal (beg end)
+  (sha1-string-internal (buffer-substring-no-properties beg end)))
+
+;;;
+;;; application interface.
+;;;
+
+(defun sha1-region (beg end)
+  (if (and sha1-use-external
+          sha1-maximum-internal-length
+          (> (abs (- end beg)) sha1-maximum-internal-length))
+      (sha1-region-external beg end)
+    (sha1-region-internal beg end)))
+
+(defun sha1-string (string)
+  (if (and sha1-use-external
+          sha1-maximum-internal-length
+          (> (length string) sha1-maximum-internal-length))
+      (sha1-string-external string)
+    (sha1-string-internal string)))
+
+;;;###autoload
+(defun sha1 (object &optional beg end)
+  "Return the SHA1 (Secure Hash Algorithm) of an object.
+OBJECT is either a string or a buffer.
+Optional arguments BEG and END denote buffer positions for computing the
+hash of a portion of OBJECT."
+  (if (stringp object)
+      (sha1-string object)
+    (save-excursion
+      (set-buffer object)
+      (sha1-region (or beg (point-min)) (or end (point-max))))))
+
+(provide 'sha1-el)
+
+;;; sha1-el.el ends here
diff --git a/lisp/sieve-manage.el b/lisp/sieve-manage.el
new file mode 100644 (file)
index 0000000..bda44dc
--- /dev/null
@@ -0,0 +1,615 @@
+;;; sieve-manage.el --- Implementation of the managesive protocol in elisp
+;; Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This library provides an elisp API for the managesieve network
+;; protocol.
+;;
+;; Currently only the CRAM-MD5 authentication mechanism is supported.
+;;
+;; The API should be fairly obvious for anyone familiar with the
+;; managesieve protocol, interface functions include:
+;;
+;; `sieve-manage-open'
+;; open connection to managesieve server, returning a buffer to be
+;; used by all other API functions.
+;;
+;; `sieve-manage-opened'
+;; check if a server is open or not
+;;
+;; `sieve-manage-close'
+;; close a server connection.
+;;
+;; `sieve-manage-authenticate'
+;; `sieve-manage-listscripts'
+;; `sieve-manage-deletescript'
+;; `sieve-manage-getscript'
+;; performs managesieve protocol actions
+;;
+;; and that's it.  Example of a managesieve session in *scratch*:
+;;
+;; (setq my-buf (sieve-manage-open "my.server.com"))
+;; " *sieve* my.server.com:2000*"
+;;
+;; (sieve-manage-authenticate "myusername" "mypassword" my-buf)
+;; 'auth
+;;
+;; (sieve-manage-listscripts my-buf)
+;; ("vacation" "testscript" ("splitmail") "badscript")
+;;
+;; References:
+;;
+;; draft-martin-managesieve-02.txt,
+;; "A Protocol for Remotely Managing Sieve Scripts",
+;; by Tim Martin.
+;;
+;; Release history:
+;;
+;; 2001-10-31 Committed to Oort Gnus.
+;; 2002-07-27 Added DELETESCRIPT.  Suggested by Ned Ludd.
+
+;;; Code:
+
+(require 'rfc2104)
+(or (fboundp 'md5)
+    (require 'md5))
+(eval-and-compile
+  (autoload 'starttls-open-stream "starttls")
+  (autoload 'starttls-negotiate "starttls"))
+
+;; User customizable variables:
+
+(defgroup sieve-manage nil
+  "Low-level Managesieve protocol issues."
+  :group 'mail
+  :prefix "sieve-")
+
+(defcustom sieve-manage-log "*sieve-manage-log*"
+  "Name of buffer for managesieve session trace."
+  :type 'string)
+
+(defcustom sieve-manage-default-user (user-login-name)
+  "Default username to use."
+  :type 'string)
+
+(defcustom sieve-manage-server-eol "\r\n"
+  "The EOL string sent from the server."
+  :type 'string)
+
+(defcustom sieve-manage-client-eol "\r\n"
+  "The EOL string we send to the server."
+  :type 'string)
+
+(defcustom sieve-manage-streams '(network starttls shell)
+  "Priority of streams to consider when opening connection to server.")
+
+(defcustom sieve-manage-stream-alist
+  '((network   sieve-manage-network-p          sieve-manage-network-open)
+    (shell     sieve-manage-shell-p            sieve-manage-shell-open)
+    (starttls  sieve-manage-starttls-p         sieve-manage-starttls-open))
+  "Definition of network streams.
+
+\(NAME CHECK OPEN)
+
+NAME names the stream, CHECK is a function returning non-nil if the
+server support the stream and OPEN is a function for opening the
+stream.")
+
+(defcustom sieve-manage-authenticators '(cram-md5 plain)
+  "Priority of authenticators to consider when authenticating to server.")
+
+(defcustom sieve-manage-authenticator-alist
+  '((cram-md5   sieve-manage-cram-md5-p       sieve-manage-cram-md5-auth)
+    (plain      sieve-manage-plain-p          sieve-manage-plain-auth))
+  "Definition of authenticators.
+
+\(NAME CHECK AUTHENTICATE)
+
+NAME names the authenticator.  CHECK is a function returning non-nil if
+the server support the authenticator and AUTHENTICATE is a function
+for doing the actual authentication.")
+
+(defcustom sieve-manage-default-port 2000
+  "Default port number for managesieve protocol."
+  :type 'integer)
+
+;; Internal variables:
+
+(defconst sieve-manage-local-variables '(sieve-manage-server
+                                        sieve-manage-port
+                                        sieve-manage-auth
+                                        sieve-manage-stream
+                                        sieve-manage-username
+                                        sieve-manage-password
+                                        sieve-manage-process
+                                        sieve-manage-client-eol
+                                        sieve-manage-server-eol
+                                        sieve-manage-capability))
+(defconst sieve-manage-default-stream 'network)
+(defconst sieve-manage-coding-system-for-read 'binary)
+(defconst sieve-manage-coding-system-for-write 'binary)
+(defvar sieve-manage-stream nil)
+(defvar sieve-manage-auth nil)
+(defvar sieve-manage-server nil)
+(defvar sieve-manage-port nil)
+(defvar sieve-manage-username nil)
+(defvar sieve-manage-password nil)
+(defvar sieve-manage-state 'closed
+  "Managesieve state.
+Valid states are `closed', `initial', `nonauth', and `auth'.")
+(defvar sieve-manage-process nil)
+(defvar sieve-manage-capability nil)
+
+;; Internal utility functions
+
+(defsubst sieve-manage-disable-multibyte ()
+  "Enable multibyte in the current buffer."
+  (when (fboundp 'set-buffer-multibyte)
+    (set-buffer-multibyte nil)))
+
+;; Uses the dynamically bound `reason' variable.
+(defvar reason)
+(defun sieve-manage-interactive-login (buffer loginfunc)
+  "Login to server in BUFFER.
+LOGINFUNC is passed a username and a password, it should return t if
+it where sucessful authenticating itself to the server, nil otherwise.
+Returns t if login was successful, nil otherwise."
+  (with-current-buffer buffer
+    (make-variable-buffer-local 'sieve-manage-username)
+    (make-variable-buffer-local 'sieve-manage-password)
+    (let (user passwd ret reason)
+      ;;      (condition-case ()
+      (while (or (not user) (not passwd))
+       (setq user (or sieve-manage-username
+                      (read-from-minibuffer
+                       (concat "Managesieve username for "
+                               sieve-manage-server ": ")
+                       (or user sieve-manage-default-user))))
+       (setq passwd (or sieve-manage-password
+                        (read-passwd
+                         (concat "Managesieve password for " user "@"
+                                 sieve-manage-server ": "))))
+       (when (and user passwd)
+         (if (funcall loginfunc user passwd)
+             (progn
+               (setq ret t
+                     sieve-manage-username user)
+               (if (and (not sieve-manage-password)
+                        (y-or-n-p "Store password for this session? "))
+                   (setq sieve-manage-password passwd)))
+           (if reason
+               (message "Login failed (reason given: %s)..." reason)
+             (message "Login failed..."))
+           (setq reason nil)
+           (setq passwd nil)
+           (sit-for 1))))
+      ;;       (quit (with-current-buffer buffer
+      ;;               (setq user nil
+      ;;                     passwd nil)))
+      ;;       (error (with-current-buffer buffer
+      ;;                (setq user nil
+      ;;                      passwd nil))))
+      ret)))
+
+(defun sieve-manage-erase (&optional p buffer)
+  (let ((buffer (or buffer (current-buffer))))
+    (and sieve-manage-log
+        (with-current-buffer (get-buffer-create sieve-manage-log)
+          (sieve-manage-disable-multibyte)
+          (buffer-disable-undo)
+          (goto-char (point-max))
+          (insert-buffer-substring buffer (with-current-buffer buffer
+                                            (point-min))
+                                   (or p (with-current-buffer buffer
+                                           (point-max)))))))
+  (delete-region (point-min) (or p (point-max))))
+
+(defun sieve-manage-open-1 (buffer)
+  (with-current-buffer buffer
+    (sieve-manage-erase)
+    (setq sieve-manage-state 'initial
+         sieve-manage-process
+         (condition-case ()
+             (funcall (nth 2 (assq sieve-manage-stream
+                                   sieve-manage-stream-alist))
+                      "sieve" buffer sieve-manage-server sieve-manage-port)
+           ((error quit) nil)))
+    (when sieve-manage-process
+      (while (and (eq sieve-manage-state 'initial)
+                 (memq (process-status sieve-manage-process) '(open run)))
+       (message "Waiting for response from %s..." sieve-manage-server)
+       (accept-process-output sieve-manage-process 1))
+      (message "Waiting for response from %s...done" sieve-manage-server)
+      (and (memq (process-status sieve-manage-process) '(open run))
+          sieve-manage-process))))
+
+;; Streams
+
+(defun sieve-manage-network-p (buffer)
+  t)
+
+(defun sieve-manage-network-open (name buffer server port)
+  (let* ((port (or port sieve-manage-default-port))
+        (coding-system-for-read sieve-manage-coding-system-for-read)
+        (coding-system-for-write sieve-manage-coding-system-for-write)
+        (process (open-network-stream name buffer server port)))
+    (when process
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-min))
+                 (not (sieve-manage-parse-greeting-1)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (sieve-manage-erase nil buffer)
+      (when (memq (process-status process) '(open run))
+       process))))
+
+(defun imap-starttls-p (buffer)
+  ;;  (and (imap-capability 'STARTTLS buffer)
+  (condition-case ()
+      (progn
+       (require 'starttls)
+       (call-process "starttls"))
+    (error nil)))
+
+(defun imap-starttls-open (name buffer server port)
+  (let* ((port (or port sieve-manage-default-port))
+        (coding-system-for-read sieve-manage-coding-system-for-read)
+        (coding-system-for-write sieve-manage-coding-system-for-write)
+        (process (starttls-open-stream name buffer server port))
+        done)
+    (when process
+      (while (and (memq (process-status process) '(open run))
+                 (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                 (goto-char (point-min))
+                 (not (sieve-manage-parse-greeting-1)))
+       (accept-process-output process 1)
+       (sit-for 1))
+      (sieve-manage-erase nil buffer)
+      (sieve-manage-send "STARTTLS")
+      (starttls-negotiate process))
+    (when (memq (process-status process) '(open run))
+      process)))
+
+;; Authenticators
+
+(defun sieve-manage-plain-p (buffer)
+  (sieve-manage-capability "SASL" "PLAIN" buffer))
+
+(defun sieve-manage-plain-auth (buffer)
+  "Login to managesieve server using the PLAIN SASL method."
+  (let* ((done (sieve-manage-interactive-login
+               buffer
+               (lambda (user passwd)
+                 (sieve-manage-send (concat "AUTHENTICATE \"PLAIN\" \""
+                                            (base64-encode-string
+                                             (concat (char-to-string 0)
+                                                     user
+                                                     (char-to-string 0)
+                                                     passwd))
+                                            "\""))
+                 (let ((rsp (sieve-manage-parse-okno)))
+                   (if (sieve-manage-ok-p rsp)
+                       t
+                     (setq reason (cdr-safe rsp))
+                     nil))))))
+    (if done
+       (message "sieve: Authenticating using PLAIN...done")
+      (message "sieve: Authenticating using PLAIN...failed"))))
+
+(defun sieve-manage-cram-md5-p (buffer)
+  (sieve-manage-capability "SASL" "CRAM-MD5" buffer))
+
+(defun sieve-manage-cram-md5-auth (buffer)
+  "Login to managesieve server using the CRAM-MD5 SASL method."
+  (message "sieve: Authenticating using CRAM-MD5...")
+  (let* ((done (sieve-manage-interactive-login
+               buffer
+               (lambda (user passwd)
+                 (sieve-manage-send "AUTHENTICATE \"CRAM-MD5\"")
+                 (sieve-manage-send
+                  (concat
+                   "\""
+                   (base64-encode-string
+                    (concat
+                     user " "
+                     (rfc2104-hash 'md5 64 16 passwd
+                                   (base64-decode-string
+                                    (prog1
+                                        (sieve-manage-parse-string)
+                                      (sieve-manage-erase))))))
+                   "\""))
+                 (let ((rsp (sieve-manage-parse-okno)))
+                   (if (sieve-manage-ok-p rsp)
+                       t
+                     (setq reason (cdr-safe rsp))
+                     nil))))))
+    (if done
+       (message "sieve: Authenticating using CRAM-MD5...done")
+      (message "sieve: Authenticating using CRAM-MD5...failed"))))
+
+;; Managesieve API
+
+(defun sieve-manage-open (server &optional port stream auth buffer)
+  "Open a network connection to a managesieve SERVER (string).
+Optional variable PORT is port number (integer) on remote server.
+Optional variable STREAM is any of `sieve-manage-streams' (a symbol).
+Optional variable AUTH indicates authenticator to use, see
+`sieve-manage-authenticators' for available authenticators.  If nil, chooses
+the best stream the server is capable of.
+Optional variable BUFFER is buffer (buffer, or string naming buffer)
+to work in."
+  (setq buffer (or buffer (format " *sieve* %s:%d" server (or port 2000))))
+  (with-current-buffer (get-buffer-create buffer)
+    (mapcar 'make-variable-buffer-local sieve-manage-local-variables)
+    (sieve-manage-disable-multibyte)
+    (buffer-disable-undo)
+    (setq sieve-manage-server (or server sieve-manage-server))
+    (setq sieve-manage-port (or port sieve-manage-port))
+    (setq sieve-manage-stream (or stream sieve-manage-stream))
+    (message "sieve: Connecting to %s..." sieve-manage-server)
+    (if (let ((sieve-manage-stream
+              (or sieve-manage-stream sieve-manage-default-stream)))
+         (sieve-manage-open-1 buffer))
+       ;; Choose stream.
+       (let (stream-changed)
+         (message "sieve: Connecting to %s...done" sieve-manage-server)
+         (when (null sieve-manage-stream)
+           (let ((streams sieve-manage-streams))
+             (while (setq stream (pop streams))
+               (if (funcall (nth 1 (assq stream
+                                         sieve-manage-stream-alist)) buffer)
+                   (setq stream-changed
+                         (not (eq (or sieve-manage-stream
+                                      sieve-manage-default-stream)
+                                  stream))
+                         sieve-manage-stream stream
+                         streams nil)))
+             (unless sieve-manage-stream
+               (error "Couldn't figure out a stream for server"))))
+         (when stream-changed
+           (message "sieve: Reconnecting with stream `%s'..."
+                    sieve-manage-stream)
+           (sieve-manage-close buffer)
+           (if (sieve-manage-open-1 buffer)
+               (message "sieve: Reconnecting with stream `%s'...done"
+                        sieve-manage-stream)
+             (message "sieve: Reconnecting with stream `%s'...failed"
+                      sieve-manage-stream))
+           (setq sieve-manage-capability nil))
+         (if (sieve-manage-opened buffer)
+             ;; Choose authenticator
+             (when (and (null sieve-manage-auth)
+                        (not (eq sieve-manage-state 'auth)))
+               (let ((auths sieve-manage-authenticators))
+                 (while (setq auth (pop auths))
+                   (if (funcall (nth 1 (assq
+                                        auth
+                                        sieve-manage-authenticator-alist))
+                                buffer)
+                       (setq sieve-manage-auth auth
+                             auths nil)))
+                 (unless sieve-manage-auth
+                   (error "Couldn't figure out authenticator for server"))))))
+      (message "sieve: Connecting to %s...failed" sieve-manage-server))
+    (when (sieve-manage-opened buffer)
+      (sieve-manage-erase)
+      buffer)))
+
+(defun sieve-manage-opened (&optional buffer)
+  "Return non-nil if connection to managesieve server in BUFFER is open.
+If BUFFER is nil then the current buffer is used."
+  (and (setq buffer (get-buffer (or buffer (current-buffer))))
+       (buffer-live-p buffer)
+       (with-current-buffer buffer
+        (and sieve-manage-process
+             (memq (process-status sieve-manage-process) '(open run))))))
+
+(defun sieve-manage-close (&optional buffer)
+  "Close connection to managesieve server in BUFFER.
+If BUFFER is nil, the current buffer is used."
+  (with-current-buffer (or buffer (current-buffer))
+    (when (sieve-manage-opened)
+      (sieve-manage-send "LOGOUT")
+      (sit-for 1))
+    (when (and sieve-manage-process
+              (memq (process-status sieve-manage-process) '(open run)))
+      (delete-process sieve-manage-process))
+    (setq sieve-manage-process nil)
+    (sieve-manage-erase)
+    t))
+
+(defun sieve-manage-authenticate (&optional user passwd buffer)
+  "Authenticate to server in BUFFER, using current buffer if nil.
+It uses the authenticator specified when opening the server.  If the
+authenticator requires username/passwords, they are queried from the
+user and optionally stored in the buffer.  If USER and/or PASSWD is
+specified, the user will not be questioned and the username and/or
+password is remembered in the buffer."
+  (with-current-buffer (or buffer (current-buffer))
+    (if (not (eq sieve-manage-state 'nonauth))
+       (eq sieve-manage-state 'auth)
+      (make-variable-buffer-local 'sieve-manage-username)
+      (make-variable-buffer-local 'sieve-manage-password)
+      (if user (setq sieve-manage-username user))
+      (if passwd (setq sieve-manage-password passwd))
+      (if (funcall (nth 2 (assq sieve-manage-auth
+                               sieve-manage-authenticator-alist)) buffer)
+         (setq sieve-manage-state 'auth)))))
+
+(defun sieve-manage-capability (&optional name value buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (if (null name)
+       sieve-manage-capability
+      (if (null value)
+         (nth 1 (assoc name sieve-manage-capability))
+       (when (string-match value (nth 1 (assoc name sieve-manage-capability)))
+         (nth 1 (assoc name sieve-manage-capability)))))))
+
+(defun sieve-manage-listscripts (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send "LISTSCRIPTS")
+    (sieve-manage-parse-listscripts)))
+
+(defun sieve-manage-havespace (name size &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send (format "HAVESPACE \"%s\" %s" name size))
+    (sieve-manage-parse-okno)))
+
+(eval-and-compile
+  (if (fboundp 'string-bytes)
+      (defalias 'sieve-string-bytes 'string-bytes)
+    (defalias 'sieve-string-bytes 'length)))
+
+(defun sieve-manage-putscript (name content &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send (format "PUTSCRIPT \"%s\" {%d+}%s%s" name
+                              (sieve-string-bytes content)
+                              sieve-manage-client-eol content))
+    (sieve-manage-parse-okno)))
+
+(defun sieve-manage-deletescript (name &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send (format "DELETESCRIPT \"%s\"" name))
+    (sieve-manage-parse-okno)))
+
+(defun sieve-manage-getscript (name output-buffer &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send (format "GETSCRIPT \"%s\"" name))
+    (let ((script (sieve-manage-parse-string)))
+      (sieve-manage-parse-crlf)
+      (with-current-buffer output-buffer
+       (insert script))
+      (sieve-manage-parse-okno))))
+
+(defun sieve-manage-setactive (name &optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (sieve-manage-send (format "SETACTIVE \"%s\"" name))
+    (sieve-manage-parse-okno)))
+
+;; Protocol parsing routines
+
+(defun sieve-manage-ok-p (rsp)
+  (string= (downcase (or (car-safe rsp) "")) "ok"))
+
+(defsubst sieve-manage-forward ()
+  (or (eobp) (forward-char)))
+
+(defun sieve-manage-is-okno ()
+  (when (looking-at (concat
+                    "^\\(OK\\|NO\\)\\( (\\([^)]+\\))\\)?\\( \\(.*\\)\\)?"
+                    sieve-manage-server-eol))
+    (let ((status (match-string 1))
+         (resp-code (match-string 3))
+         (response (match-string 5)))
+      (when response
+       (goto-char (match-beginning 5))
+       (setq response (sieve-manage-is-string)))
+      (list status resp-code response))))
+
+(defun sieve-manage-parse-okno ()
+  (let (rsp)
+    (while (null rsp)
+      (accept-process-output (get-buffer-process (current-buffer)) 1)
+      (goto-char (point-min))
+      (setq rsp (sieve-manage-is-okno)))
+    (sieve-manage-erase)
+    rsp))
+
+(defun sieve-manage-parse-capability-1 ()
+  "Accept a managesieve greeting."
+  (let (str)
+    (while (setq str (sieve-manage-is-string))
+      (if (eq (char-after) ? )
+         (progn
+           (sieve-manage-forward)
+           (push (list str (sieve-manage-is-string))
+                 sieve-manage-capability))
+       (push (list str) sieve-manage-capability))
+      (forward-line)))
+  (when (re-search-forward (concat "^OK" sieve-manage-server-eol) nil t)
+    (setq sieve-manage-state 'nonauth)))
+
+(defalias 'sieve-manage-parse-greeting-1 'sieve-manage-parse-capability-1)
+
+(defun sieve-manage-is-string ()
+  (cond ((looking-at "\"\\([^\"]+\\)\"")
+        (prog1
+            (match-string 1)
+          (goto-char (match-end 0))))
+       ((looking-at (concat "{\\([0-9]+\\)}" sieve-manage-server-eol))
+        (let ((pos (match-end 0))
+              (len (string-to-number (match-string 1))))
+          (if (< (point-max) (+ pos len))
+              nil
+            (goto-char (+ pos len))
+            (buffer-substring pos (+ pos len)))))))
+
+(defun sieve-manage-parse-string ()
+  (let (rsp)
+    (while (null rsp)
+      (accept-process-output (get-buffer-process (current-buffer)) 1)
+      (goto-char (point-min))
+      (setq rsp (sieve-manage-is-string)))
+    (sieve-manage-erase (point))
+    rsp))
+
+(defun sieve-manage-parse-crlf ()
+  (when (looking-at sieve-manage-server-eol)
+    (sieve-manage-erase (match-end 0))))
+
+(defun sieve-manage-parse-listscripts ()
+  (let (tmp rsp data)
+    (while (null rsp)
+      (while (null (or (setq rsp (sieve-manage-is-okno))
+                      (setq tmp (sieve-manage-is-string))))
+       (accept-process-output (get-buffer-process (current-buffer)) 1)
+       (goto-char (point-min)))
+      (when tmp
+       (while (not (looking-at (concat "\\( ACTIVE\\)?"
+                                       sieve-manage-server-eol)))
+         (accept-process-output (get-buffer-process (current-buffer)) 1)
+         (goto-char (point-min)))
+       (if (match-string 1)
+           (push (cons 'active tmp) data)
+         (push tmp data))
+       (goto-char (match-end 0))
+       (setq tmp nil)))
+    (sieve-manage-erase)
+    (if (sieve-manage-ok-p rsp)
+       data
+      rsp)))
+
+(defun sieve-manage-send (cmdstr)
+  (setq cmdstr (concat cmdstr sieve-manage-client-eol))
+  (and sieve-manage-log
+       (with-current-buffer (get-buffer-create sieve-manage-log)
+        (sieve-manage-disable-multibyte)
+        (buffer-disable-undo)
+        (goto-char (point-max))
+        (insert cmdstr)))
+  (process-send-string sieve-manage-process cmdstr))
+
+(provide 'sieve-manage)
+
+;; sieve-manage.el ends here
diff --git a/lisp/sieve-mode.el b/lisp/sieve-mode.el
new file mode 100644 (file)
index 0000000..e4945c9
--- /dev/null
@@ -0,0 +1,204 @@
+;;; sieve-mode.el --- Sieve code editing commands for Emacs
+;; Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file contain editing mode functions and font-lock support for
+;; editing Sieve scripts.  It sets up C-mode with support for
+;; sieve-style #-comments and a lightly hacked syntax table.  It was
+;; strongly influenced by awk-mode.el.
+;;
+;; Put something similar to the following in your .emacs to use this file:
+;;
+;; (load "~/lisp/sieve")
+;; (setq auto-mode-alist (cons '("\\.siv\\'" . sieve-mode) auto-mode-alist))
+;;
+;; References:
+;;
+;; RFC 3028,
+;; "Sieve: A Mail Filtering Language",
+;; by Tim Showalter.
+;;
+;; Release history:
+;;
+;; 2001-03-02 version 1.0 posted to gnu.emacs.sources
+;;            version 1.1 change file extension into ".siv" (official one)
+;;                        added keymap and menubar to hook into sieve-manage
+;; 2001-10-31 version 1.2 committed to Oort Gnus
+
+;;; Code:
+
+(autoload 'sieve-manage "sieve")
+(autoload 'sieve-upload "sieve")
+(autoload 'c-mode "cc-mode")
+(require 'easymenu)
+(eval-when-compile
+  (require 'font-lock))
+
+(defgroup sieve nil
+  "Sieve."
+  :group 'languages)
+
+(defcustom sieve-mode-hook nil
+  "Hook run in sieve mode buffers."
+  :group 'sieve
+  :type 'hook)
+
+;; Font-lock
+
+(defvar sieve-control-commands-face 'sieve-control-commands-face
+  "Face name used for Sieve Control Commands.")
+
+(defface sieve-control-commands-face
+  '((((type tty) (class color)) (:foreground "blue" :weight light))
+    (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
+    (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
+    (((class color) (background light)) (:foreground "Orchid"))
+    (((class color) (background dark)) (:foreground "LightSteelBlue"))
+    (t (:bold t)))
+  "Face used for Sieve Control Commands.")
+
+(defvar sieve-action-commands-face 'sieve-action-commands-face
+  "Face name used for Sieve Action Commands.")
+
+(defface sieve-action-commands-face
+  '((((type tty) (class color)) (:foreground "blue" :weight bold))
+    (((class color) (background light)) (:foreground "Blue"))
+    (((class color) (background dark)) (:foreground "LightSkyBlue"))
+    (t (:inverse-video t :bold t)))
+  "Face used for Sieve Action Commands.")
+
+(defvar sieve-test-commands-face 'sieve-test-commands-face
+  "Face name used for Sieve Test Commands.")
+
+(defface sieve-test-commands-face
+  '((((type tty) (class color)) (:foreground "magenta"))
+    (((class grayscale) (background light))
+     (:foreground "LightGray" :bold t :underline t))
+    (((class grayscale) (background dark))
+     (:foreground "Gray50" :bold t :underline t))
+    (((class color) (background light)) (:foreground "CadetBlue"))
+    (((class color) (background dark)) (:foreground "Aquamarine"))
+    (t (:bold t :underline t)))
+  "Face used for Sieve Test Commands.")
+
+(defvar sieve-tagged-arguments-face 'sieve-tagged-arguments-face
+  "Face name used for Sieve Tagged Arguments.")
+
+(defface sieve-tagged-arguments-face
+  '((((type tty) (class color)) (:foreground "cyan" :weight bold))
+    (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
+    (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
+    (((class color) (background light)) (:foreground "Purple"))
+    (((class color) (background dark)) (:foreground "Cyan"))
+    (t (:bold t)))
+  "Face used for Sieve Tagged Arguments.")
+
+
+(defconst sieve-font-lock-keywords
+  (eval-when-compile
+    (list
+     ;; control commands
+     (cons (regexp-opt '("require" "if" "else" "elsif" "stop"))
+          'sieve-control-commands-face)
+     ;; action commands
+     (cons (regexp-opt '("fileinto" "redirect" "reject" "keep" "discard"))
+          'sieve-action-commands-face)
+     ;; test commands
+     (cons (regexp-opt '("address" "allof" "anyof" "exists" "false"
+                        "true" "header" "not" "size" "envelope"))
+          'sieve-test-commands-face)
+     (cons "\\Sw+:\\sw+"
+          'sieve-tagged-arguments-face))))
+
+;; Syntax table
+
+(defvar sieve-mode-syntax-table nil
+  "Syntax table in use in sieve-mode buffers.")
+
+(if sieve-mode-syntax-table
+    ()
+  (setq sieve-mode-syntax-table (make-syntax-table))
+  (modify-syntax-entry ?\\ "\\" sieve-mode-syntax-table)
+  (modify-syntax-entry ?\n ">   " sieve-mode-syntax-table)
+  (modify-syntax-entry ?\f ">   " sieve-mode-syntax-table)
+  (modify-syntax-entry ?\# "<   " sieve-mode-syntax-table)
+  (modify-syntax-entry ?/ "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?* "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?+ "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?- "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?= "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?% "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?< "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?> "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?& "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?| "." sieve-mode-syntax-table)
+  (modify-syntax-entry ?_ "_" sieve-mode-syntax-table)
+  (modify-syntax-entry ?\' "\"" sieve-mode-syntax-table))
+
+;; Key map definition
+
+(defvar sieve-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-c\C-l" 'sieve-upload)
+    (define-key map "\C-c\C-c" 'sieve-upload-and-bury)
+    (define-key map "\C-c\C-m" 'sieve-manage)
+    map)
+  "Key map used in sieve mode.")
+
+;; Menu definition
+
+(defvar sieve-mode-menu nil
+  "Menubar used in sieve mode.")
+
+;; Code for Sieve editing mode.
+
+;;;###autoload
+(define-derived-mode sieve-mode c-mode "Sieve"
+  "Major mode for editing Sieve code.
+This is much like C mode except for the syntax of comments.  Its keymap
+inherits from C mode's and it has the same variables for customizing
+indentation.  It has its own abbrev table and its own syntax table.
+
+Turning on Sieve mode runs `sieve-mode-hook'."
+  (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
+  (set (make-local-variable 'paragraph-separate) paragraph-start)
+  (set (make-local-variable 'comment-start) "#")
+  (set (make-local-variable 'comment-end) "")
+  ;;(set (make-local-variable 'comment-start-skip) "\\(^\\|\\s-\\);?#+ *")
+  (set (make-local-variable 'comment-start-skip) "#+ *")
+  (unless (featurep 'xemacs)
+    (set (make-local-variable 'font-lock-defaults)
+        '(sieve-font-lock-keywords nil nil ((?_ . "w")))))
+  (easy-menu-add-item nil nil sieve-mode-menu))
+
+;; Menu
+
+(easy-menu-define sieve-mode-menu sieve-mode-map
+  "Sieve Menu."
+  '("Sieve"
+    ["Upload script" sieve-upload t]
+    ["Manage scripts on server" sieve-manage t]))
+
+(provide 'sieve-mode)
+
+;; sieve-mode.el ends here
diff --git a/lisp/sieve.el b/lisp/sieve.el
new file mode 100644 (file)
index 0000000..83dd4f3
--- /dev/null
@@ -0,0 +1,383 @@
+;;; sieve.el --- Utilities to manage sieve scripts
+;; Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This file contain utilities to facilate upload, download and
+;; general management of sieve scripts.  Currently only the
+;; Managesieve protocol is supported (using sieve-manage.el), but when
+;; (useful) alternatives become available, they might be supported as
+;; well.
+;;
+;; The cursor navigation was inspired by biff-mode by Franklin Lee.
+;;
+;; Release history:
+;;
+;; 2001-10-31 Committed to Oort Gnus.
+;; 2002-07-27 Fix down-mouse-2 and down-mouse-3 in manage-mode.  Fix menubar
+;;            in manage-mode.  Change some messages.  Added sieve-deactivate*,
+;;            sieve-remove.  Fixed help text in manage-mode.  Suggested by
+;;            Ned Ludd.
+;;
+;; Todo:
+;;
+;; * Namespace?  This file contains `sieve-manage' and
+;;   `sieve-manage-mode', but there is a sieve-manage.el file as well.
+;;   Can't think of a good solution though, this file need a *-mode,
+;;   and naming it `sieve-mode' would collide with sieve-mode.el.  One
+;;   solution would be to come up with some better name that this file
+;;   can use that doesn't have the managesieve specific "manage" in
+;;   it.  sieve-dired?  i dunno.  we could copy all off sieve.el into
+;;   sieve-manage.el too, but I'd like to separate the interface from
+;;   the protocol implementation since the backends are likely to
+;;   change (well).
+;;
+;; * Define servers?  We could have a customize buffer to create a server,
+;;   with authentication/stream/etc parameters, much like Gnus, and then
+;;   only use names of defined servers when interacting with M-x sieve-*.
+;;   Right now you can't use STARTTLS, which sieve-manage.el provides
+
+;;; Code:
+
+(require 'sieve-manage)
+(require 'sieve-mode)
+
+;; User customizable variables:
+
+(defgroup sieve nil
+  "Manage sieve scripts."
+  :group 'tools)
+
+(defcustom sieve-new-script "<new script>"
+  "Name of name script indicator."
+  :type 'string
+  :group 'sieve)
+
+(defcustom sieve-buffer "*sieve*"
+  "Name of sieve management buffer."
+  :type 'string
+  :group 'sieve)
+
+(defcustom sieve-template "\
+require \"fileinto\";
+
+# Example script (remove comment character '#' to make it effective!):
+#
+# if header :contains \"from\" \"coyote\" {
+#   discard;
+# } elsif header :contains [\"subject\"] [\"$$$\"] {
+#   discard;
+# } else {
+#  fileinto \"INBOX\";
+# }
+"
+  "Template sieve script."
+  :type 'string
+  :group 'sieve)
+
+;; Internal variables:
+
+(defvar sieve-manage-buffer nil)
+(defvar sieve-buffer-header-end nil)
+
+;; Sieve-manage mode:
+
+(defvar sieve-manage-mode-map nil
+  "Keymap for `sieve-manage-mode'.")
+
+(if sieve-manage-mode-map
+    ()
+  (setq sieve-manage-mode-map (make-sparse-keymap))
+  (suppress-keymap sieve-manage-mode-map)
+  ;; various
+  (define-key sieve-manage-mode-map "?" 'sieve-help)
+  (define-key sieve-manage-mode-map "h" 'sieve-help)
+  (define-key sieve-manage-mode-map "q" 'sieve-bury-buffer)
+  ;; activating
+  (define-key sieve-manage-mode-map "m" 'sieve-activate)
+  (define-key sieve-manage-mode-map "u" 'sieve-deactivate)
+  (define-key sieve-manage-mode-map "\M-\C-?" 'sieve-deactivate-all)
+  ;; navigation keys
+  (define-key sieve-manage-mode-map "\C-p" 'sieve-prev-line)
+  (define-key sieve-manage-mode-map [up] 'sieve-prev-line)
+  (define-key sieve-manage-mode-map "\C-n" 'sieve-next-line)
+  (define-key sieve-manage-mode-map [down] 'sieve-next-line)
+  (define-key sieve-manage-mode-map " " 'sieve-next-line)
+  (define-key sieve-manage-mode-map "n" 'sieve-next-line)
+  (define-key sieve-manage-mode-map "p" 'sieve-prev-line)
+  (define-key sieve-manage-mode-map "\C-m" 'sieve-edit-script)
+  (define-key sieve-manage-mode-map "f" 'sieve-edit-script)
+  (define-key sieve-manage-mode-map "o" 'sieve-edit-script-other-window)
+  (define-key sieve-manage-mode-map "r" 'sieve-remove)
+  (define-key sieve-manage-mode-map [(down-mouse-2)] 'sieve-edit-script)
+  (define-key sieve-manage-mode-map [(down-mouse-3)] 'sieve-manage-mode-menu))
+
+(easy-menu-define sieve-manage-mode-menu sieve-manage-mode-map
+  "Sieve Menu."
+  '("Manage Sieve"
+    ["Edit script" sieve-edit-script t]
+    ["Activate script" sieve-activate t]
+    ["Deactivate script" sieve-deactivate t]))
+
+(define-derived-mode sieve-manage-mode fundamental-mode "SIEVE"
+  "Mode used for sieve script management."
+  (setq mode-name "SIEVE")
+  (buffer-disable-undo (current-buffer))
+  (setq truncate-lines t)
+  (easy-menu-add-item nil nil sieve-manage-mode-menu))
+
+(put 'sieve-manage-mode 'mode-class 'special)
+
+;; This is necessary to allow correct handling of \\[cvs-mode-diff-map]
+;; in substitute-command-keys.
+;(fset 'sieve-manage-mode-map sieve-manage-mode-map)
+
+;; Commands used in sieve-manage mode:
+
+(defun sieve-activate (&optional pos)
+  (interactive "d")
+  (let ((name (sieve-script-at-point)) err)
+    (when (or (null name) (string-equal name sieve-new-script))
+      (error "No sieve script at point"))
+    (message "Activating script %s..." name)
+    (setq err (sieve-manage-setactive name sieve-manage-buffer))
+    (sieve-refresh-scriptlist)
+    (if (sieve-manage-ok-p err)
+       (message "Activating script %s...done" name)
+      (message "Activating script %s...failed: %s" name (nth 2 err)))))
+
+(defun sieve-deactivate-all (&optional pos)
+  (interactive "d")
+  (let ((name (sieve-script-at-point)) err)
+    (message "Deactivating scripts...")
+    (setq err (sieve-manage-setactive "" sieve-manage-buffer))
+    (sieve-refresh-scriptlist)
+    (if (sieve-manage-ok-p err)
+       (message "Deactivating scripts...done")
+      (message "Deactivating scripts...failed" (nth 2 err)))))
+
+(defalias 'sieve-deactivate 'sieve-deactivate-all)
+
+(defun sieve-remove (&optional pos)
+  (interactive "d")
+  (let ((name (sieve-script-at-point)) err)
+    (when (or (null name) (string-equal name sieve-new-script))
+      (error "No sieve script at point"))
+    (message "Removing sieve script %s..." name)
+    (setq err (sieve-manage-deletescript name sieve-manage-buffer))
+    (unless (sieve-manage-ok-p err)
+      (error "Removing sieve script %s...failed: " err))
+    (sieve-refresh-scriptlist)
+    (message "Removing sieve script %s...done" name)))
+
+(defun sieve-edit-script (&optional pos)
+  (interactive "d")
+  (let ((name (sieve-script-at-point)))
+    (unless name
+      (error "No sieve script at point"))
+    (if (not (string-equal name sieve-new-script))
+       (let ((newbuf (generate-new-buffer name))
+             err)
+         (setq err (sieve-manage-getscript name newbuf sieve-manage-buffer))
+         (switch-to-buffer newbuf)
+         (unless (sieve-manage-ok-p err)
+           (error "Sieve download failed: %s" err)))
+      (switch-to-buffer (get-buffer-create "template.siv"))
+      (insert sieve-template))
+    (sieve-mode)
+    (message "Press C-c C-l to upload script to server.")))
+
+(defmacro sieve-change-region (&rest body)
+  "Turns off sieve-region before executing BODY, then re-enables it after.
+Used to bracket operations which move point in the sieve-buffer."
+  `(progn
+     (sieve-highlight nil)
+     ,@body
+     (sieve-highlight t)))
+(put 'sieve-change-region 'lisp-indent-function 0)
+
+(defun sieve-next-line (&optional arg)
+  (interactive)
+  (unless arg
+    (setq arg 1))
+  (if (save-excursion
+       (forward-line arg)
+       (sieve-script-at-point))
+      (sieve-change-region
+       (forward-line arg))
+    (message "End of list")))
+
+(defun sieve-prev-line (&optional arg)
+  (interactive)
+  (unless arg
+    (setq arg -1))
+  (if (save-excursion
+       (forward-line arg)
+       (sieve-script-at-point))
+      (sieve-change-region
+       (forward-line arg))
+    (message "Beginning of list")))
+
+(defun sieve-help ()
+  "Display help for various sieve commands."
+  (interactive)
+  (if (eq last-command 'sieve-help)
+      ;; would need minor-mode for log-edit-mode
+      (describe-function 'sieve-mode)
+    (message (substitute-command-keys
+             "`\\[sieve-edit-script]':edit `\\[sieve-activate]':activate `\\[sieve-deactivate]':deactivate `\\[sieve-remove]':remove"))))
+
+(defun sieve-bury-buffer (buf &optional mainbuf)
+  "Hide the buffer BUF that was temporarily popped up.
+BUF is assumed to be a temporary buffer used from the buffer MAINBUF."
+  (interactive (list (current-buffer)))
+  (save-current-buffer
+    (let ((win (if (eq buf (window-buffer (selected-window))) (selected-window)
+                (get-buffer-window buf t))))
+      (when win
+       (if (window-dedicated-p win)
+           (condition-case ()
+               (delete-window win)
+             (error (iconify-frame (window-frame win))))
+         (if (and mainbuf (get-buffer-window mainbuf))
+             (delete-window win)))))
+    (with-current-buffer buf
+      (bury-buffer (unless (and (eq buf (window-buffer (selected-window)))
+                               (not (window-dedicated-p (selected-window))))
+                    buf)))
+    (when mainbuf
+      (let ((mainwin (or (get-buffer-window mainbuf)
+                        (get-buffer-window mainbuf 'visible))))
+       (when mainwin (select-window mainwin))))))
+
+;; Create buffer:
+
+(defun sieve-setup-buffer (server port)
+  (setq buffer-read-only nil)
+  (erase-buffer)
+  (buffer-disable-undo)
+  (insert "\
+Server  : " server ":" (or port "2000") "
+
+")
+  (set (make-local-variable 'sieve-buffer-header-end)
+       (point-max)))
+
+(defun sieve-script-at-point (&optional pos)
+  "Return name of sieve script at point POS, or nil."
+  (interactive "d")
+  (get-char-property (or pos (point)) 'script-name))
+
+(eval-and-compile
+  (defalias 'sieve-make-overlay (if (fboundp 'make-overlay)
+                                   'make-overlay
+                                 'make-extent))
+  (defalias 'sieve-overlay-put (if (fboundp 'overlay-put)
+                                  'overlay-put
+                                'set-extent-property))
+  (defalias 'sieve-overlays-at (if (fboundp 'overlays-at)
+                                  'overlays-at
+                                'extents-at)))
+
+(defun sieve-highlight (on)
+  "Turn ON or off highlighting on the current language overlay."
+  (sieve-overlay-put (car (sieve-overlays-at (point)))
+                    'face (if on 'highlight 'default)))
+
+(defun sieve-insert-scripts (scripts)
+  "Format and insert LANGUAGE-LIST strings into current buffer at point."
+  (while scripts
+    (let ((p (point))
+         (ext nil)
+         (script (pop scripts)))
+      (if (consp script)
+         (insert (format " ACTIVE %s" (cdr script)))
+       (insert (format "        %s" script)))
+      (setq ext (sieve-make-overlay p (point)))
+      (sieve-overlay-put ext 'mouse-face 'highlight)
+      (sieve-overlay-put ext 'script-name (if (consp script)
+                                             (cdr script)
+                                           script))
+      (insert "\n"))))
+
+(defun sieve-open-server (server &optional port)
+  ;; open server
+  (set (make-local-variable 'sieve-manage-buffer)
+       (sieve-manage-open server))
+  ;; authenticate
+  (sieve-manage-authenticate nil nil sieve-manage-buffer))
+
+(defun sieve-refresh-scriptlist ()
+  (interactive)
+  (with-current-buffer sieve-buffer
+    (setq buffer-read-only nil)
+    (delete-region (or sieve-buffer-header-end (point-max)) (point-max))
+    (goto-char (point-max))
+    ;; get list of script names and print them
+    (let ((scripts (sieve-manage-listscripts sieve-manage-buffer)))
+      (if (null scripts)
+         (insert (format (concat "No scripts on server, press RET on %s to "
+                                 "create a new script.\n") sieve-new-script))
+       (insert (format (concat "%d script%s on server, press RET on a script "
+                               "name edits it, or\npress RET on %s to create "
+                               "a new script.\n") (length scripts)
+                               (if (eq (length scripts) 1) "" "s")
+                               sieve-new-script)))
+      (save-excursion
+       (sieve-insert-scripts (list sieve-new-script))
+       (sieve-insert-scripts scripts)))
+    (sieve-highlight t)
+    (setq buffer-read-only t)))
+
+;;;###autoload
+(defun sieve-manage (server &optional port)
+  (interactive "sServer: ")
+  (switch-to-buffer (get-buffer-create sieve-buffer))
+  (sieve-manage-mode)
+  (sieve-setup-buffer server port)
+  (if (sieve-open-server server port)
+      (sieve-refresh-scriptlist)
+    (message "Could not open server %s" server)))
+
+;;;###autoload
+(defun sieve-upload (&optional name)
+  (interactive)
+  (unless name
+    (setq name (buffer-name)))
+  (when (or (get-buffer sieve-buffer) (call-interactively 'sieve-manage))
+    (let ((script (buffer-string)) err)
+      (with-current-buffer (get-buffer sieve-buffer)
+       (setq err (sieve-manage-putscript name script sieve-manage-buffer))
+       (if (sieve-manage-ok-p err)
+           (message (concat
+                     "Sieve upload done.  Use `C-c RET' to manage scripts."))
+         (message "Sieve upload failed: %s" (nth 2 err)))))))
+
+;;;###autoload
+(defun sieve-upload-and-bury (&optional name)
+  (interactive)
+  (sieve-upload name)
+  (bury-buffer))
+
+(provide 'sieve)
+
+;; sieve.el ends here
index f82ac2d..896e456 100644 (file)
@@ -1,8 +1,9 @@
 ;;; smiley.el --- displaying smiley faces
-;; Copyright (C) 1996,97,98 Free Software Foundation, Inc.
 
-;; Author: Wes Hardaker <hardaker@ece.ucdavis.edu>
-;; Keywords: fun
+;; Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Dave Love <fx@gnu.org>
+;; Keywords: news mail multimedia
 
 ;; This file is part of GNU Emacs.
 
 
 ;;; Commentary:
 
-;;
-;; comments go here.
-;;
-
-;;; Test smileys:  :-] :-o :-) ;-) :-\ :-| :-d :-P 8-| :-(
+;; A re-written, simplified version of Wes Hardaker's XEmacs smiley.el
+;; which might be merged back to smiley.el if we get an assignment for
+;; that.  We don't have assignments for the images smiley.el uses, but
+;; I'm not sure we need that degree of rococoness and defaults like a
+;; yellow background.  Also, using PBM means we can display the images
+;; more generally.  -- fx
 
-;; To use:
-;; (require 'smiley)
-;; (add-hook 'gnus-article-display-hook 'gnus-smiley-display t)
+;;; Test smileys:  :-) :-\ :-( :-/
 
-;; The smilies were drawn by Joe Reiss <jreiss@vt.edu>.
+;;; Code:
 
-(require 'annotations)
-(require 'messagexmas)
-(require 'cl)
-(require 'custom)
+(eval-when-compile (require 'cl))
+(require 'nnheader)
+(require 'gnus-art)
 
 (defgroup smiley nil
-  "Turn :-)'s into real images (XEmacs)."
+  "Turn :-)'s into real images."
   :group 'gnus-visual)
 
-(defcustom smiley-data-directory (message-xmas-find-glyph-directory "smilies")
+;; Maybe this should go.
+(defcustom smiley-data-directory (nnheader-find-etc-directory "smilies")
   "*Location of the smiley faces files."
   :type 'directory
   :group 'smiley)
 
-;; Notice the subtle differences in the regular expressions in the
-;; two alists below.
-
-(defcustom smiley-deformed-regexp-alist
-  '(("\\(\\^_?\\^;;;\\)\\W" 1 "WideFaceAse3.xbm")
-    ("\\(\\^_?\\^;;\\)\\W" 1 "WideFaceAse2.xbm")
-    ("\\(\\^_?\\^;\\)\\W" 1 "WideFaceAse1.xbm")
-    ("\\(\\^_?\\^\\)\\W" 1 "WideFaceSmile.xbm")
-    ("\\(;_;\\)\\W" 1 "WideFaceWeep.xbm")
-    ("\\(T_T\\)\\W" 1 "WideFaceWeep.xbm")
-    ("\\(:-*[<«]+\\)\\W" 1 "FaceAngry.xpm")
-    ("\\(:-+\\]+\\)\\W" 1 "FaceGoofy.xpm")
-    ("\\(:-*D\\)\\W" 1 "FaceGrinning.xpm")
-    ("\\(:-*[)>}»]+\\)\\W" 1 "FaceHappy.xpm")
-    ("\\(=[)>»]+\\)\\W" 1 "FaceHappy.xpm")
-    ("\\(:-*[/\\\"]\\)[^/]\\W" 1 "FaceIronic.xpm")
-    ("\\([8|]-*[|Oo%]\\)\\W" 1 "FaceKOed.xpm")
-    ("\\([:|]-*#+\\)\\W" 1 "FaceNyah.xpm")
-    ("\\(:-*[({]+\\)\\W" 1 "FaceSad.xpm")
-    ("\\(=[({]+\\)\\W" 1 "FaceSad.xpm")
-    ("\\(:-*[Oo\*]\\)\\W" 1 "FaceStartled.xpm")
-    ("\\(:-*|\\)\\W" 1 "FaceStraight.xpm")
-    ("\\(:-*p\\)\\W" 1 "FaceTalking.xpm")
-    ("\\(:-*d\\)\\W" 1 "FaceTasty.xpm")
-    ("\\(;-*[>)}»]+\\)\\W" 1 "FaceWinking.xpm")
-    ("\\(:-*[Vvµ]\\)\\W" 1 "FaceWry.xpm")
-    ("\\([:|]-*P\\)\\W" 1 "FaceYukky.xpm"))
-  "*Normal and deformed faces for smilies."
-  :type '(repeat (list regexp
-                      (integer :tag "Match")
-                      (string :tag "Image")))
-  :group 'smiley)
-
-(defcustom smiley-nosey-regexp-alist
-  '(("\\(:-+[<«]+\\)\\W" 1 "FaceAngry.xpm")
-    ("\\(:-+\\]+\\)\\W" 1 "FaceGoofy.xpm")
-    ("\\(:-+D\\)\\W" 1 "FaceGrinning.xpm")
-    ("\\(:-+[}»]+\\)\\W" 1 "FaceHappy.xpm")
-    ("\\(:-*)+\\)\\W" 1 "FaceHappy.xpm")
-    ("\\(=[)>]+\\)\\W" 1 "FaceHappy.xpm")
-    ("\\(:-+[/\\\"]+\\)\\W" 1 "FaceIronic.xpm")
-    ("\\([8|]-+[|Oo%]\\)\\W" 1 "FaceKOed.xpm")
-    ("\\([:|]-+#+\\)\\W" 1 "FaceNyah.xpm")
-    ("\\(:-+[({]+\\)\\W" 1 "FaceSad.xpm")
-    ("\\(=[({]+\\)\\W" 1 "FaceSad.xpm")
-    ("\\(:-+[Oo\*]\\)\\W" 1 "FaceStartled.xpm")
-    ("\\(:-+|\\)\\W" 1 "FaceStraight.xpm")
-    ("\\(:-+p\\)\\W" 1 "FaceTalking.xpm")
-    ("\\(:-+d\\)\\W" 1 "FaceTasty.xpm")
-    ("\\(;-+[>)}»]+\\)\\W" 1 "FaceWinking.xpm")
-    ("\\(:-+[Vvµ]\\)\\W" 1 "FaceWry.xpm")
-    ("\\(][:8B]-[)>]\\)\\W" 1 "FaceDevilish.xpm")
-    ("\\([:|]-+P\\)\\W" 1 "FaceYukky.xpm"))
-  "*Smileys with noses.  These get less false matches."
+;; The XEmacs version has a baroque, if not rococo, set of these.
+(defcustom smiley-regexp-alist
+  (if (file-exists-p (expand-file-name "WideFaceSmile.xbm"
+                                      smiley-data-directory))
+      ;; Use faces in ftp://ftp.gnus.org/pub/gnus/etc-0.27.tar.gz
+      '(;; ^_^ ^^
+       ("\\(\\^_?\\^\\)\\W" 1 "WideFaceSmile")
+       ;; ;-> ;-) ;-} ;> ;) :}
+       ("\\(;-?[>)}]+\\)\\W" 1 "FaceWinking")
+       ;; ^_^; ^^;
+       ("\\(\\^_?\\^;\\)\\W" 1 "WideFaceAse1")
+       ;; ^_^;; ^^;;
+       ("\\(\\^_?\\^;;\\)\\W" 1 "WideFaceAse2")
+       ;; ^_^;;; ^^;;;
+       ("\\(\\^_?\\^;;;\\)\\W" 1 "WideFaceAse3")
+       ;; ;_;
+       ("\\(;_;\\)\\W" 1 "WideFaceWeep")
+       ;; T_T
+       ("\\(T_T\\)\\W" 1 "WideFaceWeep")
+       ;; >_<
+       ("\\(>_<\\)\\W" 1 "WideFaceWeep")
+       ;; :-< :<
+       ("\\(:-?<\\)\\W" 1 "FaceAngry")
+       ;; :-] :]
+       ("\\(:-?\\]+\\)\\W" 1 "FaceGoofy")
+       ;; :-D :D
+       ("\\(:-?D\\)\\W" 1 "FaceGrinning")
+       ;; :-) :-> :-} :) :> :}
+       ("\\(:-?[)>}]+\\)\\W" 1 "FaceHappy")
+       ;; =)
+       ("\\(=)\\)\\W" 1 "FaceHappy")
+       ;; :-/ :-\ :/ :\  excludes urls etc.
+       ("\\(:-[/\\]\\)\\W" 1 "FaceIronic")
+       ("\\(:/\\)\\([\t\n ]\\|[^/]\\W\\)" 1 "FaceIronic")
+       ("\\(:\\\\\\)\\([\t\n ]\\|[^\\]\\W\\)" 1 "FaceIronic")
+       ;; 8-| 8-O 8-%
+       ;; excludes just numbers
+       ("[^.0-9]\\(8-[|O%]\\)\\W" 1 "FaceKOed")
+       ;; :-# :#
+       ("\\(:-?#\\)\\W" 1 "FaceNyah")
+       ;; :-( :-{ :( :{
+       ("\\(:-?[({]+\\)\\W" 1 "FaceSad")
+       ;; =( ={
+       ("\\(=[({]+\\)\\W" 1 "FaceSad")
+       ;; :-O :-o :O :o
+       ("\\(:-?[Oo]\\)\\W" 1 "FaceStartled")
+       ;; :-| :|
+       ("\\(:-?|\\)\\W" 1 "FaceStraight")
+       ;; :-p :p
+       ("\\(:-?p\\)\\W" 1 "FaceTalking")
+       ;; :-d
+       ("\\(:-d\\)\\W" 1 "FaceTasty")
+       ;; :-V :-v :V :v
+       ("\\(:-?[Vv]\\)\\W" 1 "FaceWry")
+       ;; :-P :P
+       ("\\(:-?P\\)\\W" 1 "FaceYukky")
+       ;; ]:-) ]:-> ]:-} ]8-) ]8-> ]8-} ]B-) ]B-> ]B-}
+       ;; ]:) ]:> ]:} ]8) ]8> ]8} ]B) ]B> ]B}
+       ("\\(\\][:8B]-?[)>}]\\)\\W" 1 "FaceDevilish"))
+    '(("\\(:-?)\\)\\W" 1 "smile")
+      ("\\(;-?)\\)\\W" 1 "blink")
+      ("\\(:-]\\)\\W" 1 "forced")
+      ("\\(8-)\\)\\W" 1 "braindamaged")
+      ("\\(:-|\\)\\W" 1 "indifferent")
+      ("\\(:-[/\\]\\)\\W" 1 "wry")
+      ("\\(:-(\\)\\W" 1 "sad")
+      ("\\(:-{\\)\\W" 1 "frown")))
+  "*A list of regexps to map smilies to images.
+The elements are (REGEXP MATCH FILE), where MATCH is the submatch in
+regexp to replace with IMAGE.  IMAGE is the name of a PBM file in
+`smiley-data-directory'."
   :type '(repeat (list regexp
-                      (integer :tag "Match")
-                      (string :tag "Image")))
-  :group 'smiley)
-
-(defcustom smiley-regexp-alist smiley-deformed-regexp-alist
-  "*A list of regexps to map smilies to real images.
-Defaults to the contents of `smiley-deformed-regexp-alist'.
-An alternative is `smiley-nosey-regexp-alist' that matches less
-aggressively.
-If this is a symbol, take its value."
-  :type '(radio (variable-item smiley-deformed-regexp-alist)
-               (variable-item smiley-nosey-regexp-alist)
-               symbol
-               (repeat (list regexp
-                             (integer :tag "Match")
-                             (string :tag "Image"))))
-  :group 'smiley)
-
-(defcustom smiley-flesh-color "yellow"
-  "*Flesh color."
-  :type 'string
-  :group 'smiley)
-
-(defcustom smiley-features-color "black"
-  "*Features color."
-  :type 'string
-  :group 'smiley)
-
-(defcustom smiley-tongue-color "red"
-  "*Tongue color."
-  :type 'string
-  :group 'smiley)
-
-(defcustom smiley-circle-color "black"
-  "*Circle color."
-  :type 'string
+                      (integer :tag "Regexp match number")
+                      (string :tag "Image name")))
+  :set (lambda (symbol value)
+        (set-default symbol value)
+        (smiley-update-cache))
+  :initialize 'custom-initialize-default
   :group 'smiley)
 
-(defcustom smiley-mouse-face 'highlight
-  "*Face used for mouse highlighting in the smiley buffer.
-
-Smiley buttons will be displayed in this face when the cursor is
-above them."
-  :type 'face
+(defcustom gnus-smiley-file-types
+  (let ((types (list "pbm")))
+    (when (gnus-image-type-available-p 'xpm)
+      (push "xpm" types))
+    (when (gnus-image-type-available-p 'xbm)
+      (push "xbm" types))
+    types)
+  "*List of suffixes on picon file names to try."
+  :type '(repeat string)
   :group 'smiley)
 
-(defvar smiley-glyph-cache nil)
-(defvar smiley-running-xemacs (string-match "XEmacs" emacs-version))
-
-(defvar smiley-map (make-sparse-keymap "smiley-keys")
- "Keymap to toggle smiley states.")
-
-(define-key smiley-map [(button2)] 'smiley-toggle-extent)
-(define-key smiley-map [(button3)] 'smiley-popup-menu)
-
-(defun smiley-popup-menu (e)
-  (interactive "e")
-  (popup-menu
-   `("Smilies" 
-     ["Toggle This Smiley" (smiley-toggle-extent ,e) t]
-     ["Toggle All Smilies" (smiley-toggle-extents ,e) t])))
-
-(defun smiley-create-glyph (smiley pixmap)
-  (and
-   smiley-running-xemacs
-   (or
-    (cdr-safe (assoc pixmap smiley-glyph-cache))
-    (let* ((xpm-color-symbols
-           (and (featurep 'xpm)
-                (append `(("flesh" ,smiley-flesh-color)
-                          ("features" ,smiley-features-color)
-                          ("tongue" ,smiley-tongue-color))
-                        xpm-color-symbols)))
-          (glyph (make-glyph
-                  (list
-                   (cons 'x (expand-file-name pixmap smiley-data-directory))
-                   (cons 'tty smiley)))))
-      (setq smiley-glyph-cache (cons (cons pixmap glyph) smiley-glyph-cache))
-      (set-glyph-face glyph 'default)
-      glyph))))
+(defvar smiley-cached-regexp-alist nil)
+
+(defun smiley-update-cache ()
+  (dolist (elt (if (symbolp smiley-regexp-alist)
+                  (symbol-value smiley-regexp-alist)
+                smiley-regexp-alist))
+    (let ((types gnus-smiley-file-types)
+         file type)
+      (while (and (not file)
+                 (setq type (pop types)))
+       (unless (file-exists-p
+                (setq file (expand-file-name (concat (nth 2 elt) "." type)
+                                             smiley-data-directory)))
+         (setq file nil)))
+      (when type
+       (let ((image (gnus-create-image file (intern type) nil
+                                       :ascent 'center)))
+         (when image
+           (push (list (car elt) (cadr elt) image)
+                 smiley-cached-regexp-alist)))))))
+
+(defvar smiley-mouse-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [down-mouse-2] 'ignore) ; override widget
+    (define-key map [mouse-2]
+      'smiley-mouse-toggle-buffer)
+    map))
 
 ;;;###autoload
-(defun smiley-region (beg end)
-  "Smilify the region between point and mark."
+(defun smiley-region (start end)
+  "Replace in the region `smiley-regexp-alist' matches with corresponding images.
+A list of images is returned."
   (interactive "r")
-  (smiley-buffer (current-buffer) beg end))
-
-(defun smiley-toggle-extent (event)
-  "Toggle smiley at given point"
-  (interactive "e")
-  (let* ((ant (event-glyph-extent event))
-        (pt (event-closest-point event))
-        ext)
-    (if (annotationp ant)
-       (when (extentp (setq ext (extent-property ant 'smiley-extent)))
-         (set-extent-property ext 'invisible nil)
-         (hide-annotation ant))
-      (when pt
-       (while (setq ext (extent-at pt (event-buffer event) nil ext 'at))
-         (when (annotationp (setq ant
-                                  (extent-property ext 'smiley-annotation)))
-           (reveal-annotation ant)
-           (set-extent-property ext 'invisible t)))))))
-
-(defun smiley-toggle-extents (e)
-  (interactive "e")
-  (map-extents
-   '(lambda (e void)
-      (let (ant)
-       (if (annotationp (setq ant (extent-property e 'smiley-annotation)))
-           (progn
-             (if (eq (extent-property e 'invisible) nil)
-                 (progn
-                   (reveal-annotation ant)
-                   (set-extent-property e 'invisible t)
-                   )
-               (hide-annotation ant)
-               (set-extent-property e 'invisible nil))))
-       nil))
-   (event-buffer e)))
-
-;;;###autoload
-(defun smiley-buffer (&optional buffer st nd)
-  (interactive)
-  (when (featurep 'x)
+  (when (gnus-graphic-display-p)
+    (unless smiley-cached-regexp-alist
+      (smiley-update-cache))
     (save-excursion
-      (when buffer
-       (set-buffer buffer))
-      (let ((buffer-read-only nil)
-           (alist (if (symbolp smiley-regexp-alist)
-                      (symbol-value smiley-regexp-alist)
-                    smiley-regexp-alist))
-           (case-fold-search nil)
-           entry regexp beg group file)
-       (map-extents
-        '(lambda (e void)
-           (when (or (extent-property e 'smiley-extent)
-                     (extent-property e 'smiley-annotation))
-             (delete-extent e)))
-        buffer st nd)
-       (goto-char (or st (point-min)))
-       (setq beg (point))
-       ;; loop through alist
-       (while (setq entry (pop alist))
-         (setq regexp (car entry)
-               group (cadr entry)
-               file (caddr entry))
+      (let ((beg (or start (point-min)))
+           group image images string)
+       (dolist (entry smiley-cached-regexp-alist)
+         (setq group (nth 1 entry)
+               image (nth 2 entry))
          (goto-char beg)
-         (while (re-search-forward regexp nd t)
-           (let* ((start (match-beginning group))
-                  (end (match-end group))
-                  (glyph (smiley-create-glyph (buffer-substring start end)
-                                              file)))
-             (when glyph
-               (mapcar 'delete-annotation (annotations-at end))
-               (let ((ext (make-extent start end))
-                     (ant (make-annotation glyph end 'text)))
-                 ;; set text extent params
-                 (set-extent-property ext 'end-open t)
-                 (set-extent-property ext 'start-open t)
-                 (set-extent-property ext 'invisible t)
-                 (set-extent-property ext 'keymap smiley-map)
-                 (set-extent-property ext 'mouse-face smiley-mouse-face)
-                 (set-extent-property ext 'intangible t)
-                 ;; set annotation params
-                 (set-extent-property ant 'mouse-face smiley-mouse-face)
-                 (set-extent-property ant 'keymap smiley-map)
-                 ;; remember each other
-                 (set-extent-property ant 'smiley-extent ext)
-                 (set-extent-property ext 'smiley-annotation ant)
-                 ;; Help
-                 (set-extent-property ext 'help-echo
-                                      "button2 toggles smiley, button3 pops up menu")
-                 (set-extent-property ant 'help-echo
-                                      "button2 toggles smiley, button3 pops up menu")
-                 (set-extent-property ext 'balloon-help
-                                      "Mouse button2 - toggle smiley
-Mouse button3 - menu")
-                 (set-extent-property ant 'balloon-help
-                                      "Mouse button2 - toggle smiley
-Mouse button3 - menu"))
-               (when (smiley-end-paren-p start end)
-                 (make-annotation ")" end 'text))
-               (goto-char end)))))))))
+         (while (re-search-forward (car entry) end t)
+           (goto-char (match-end group))
+           (unless (text-property-any (match-beginning group) (point)
+                                      'smilified t)
+             (setq string (match-string group))
+             (delete-region (match-beginning group) (match-end group))
+             (when image
+               (push image images)
+               (gnus-add-wash-type 'smiley)
+               (gnus-add-image 'smiley image)
+               (put-text-property (point)
+                                  (progn
+                                    (gnus-put-image image string 'smiley)
+                                    (point))
+                                  'smilified t)))))
+       (put-text-property beg (or end (point-max)) 'smilified nil)
+       images))))
 
-(defun smiley-end-paren-p (start end)
-  "Try to guess whether the current smiley is an end-paren smiley."
-  (save-excursion
-    (goto-char start)
-    (when (and (re-search-backward "[()]" nil t)
-              (= (following-char) ?\()
-              (goto-char end)
-              (or (not (re-search-forward "[()]" nil t))
-                  (= (char-after (1- (point))) ?\()))
-      t)))
-
-(defvar gnus-article-buffer)
 ;;;###autoload
-(defun gnus-smiley-display ()
-  "Display \"smileys\" as small graphical icons." 
-  (interactive)
+(defun smiley-buffer (&optional buffer)
+  "Run `smiley-region' at the buffer, specified in the argument or
+interactively. If there's no argument, do it at the current buffer"
+  (interactive "bBuffer to run smiley-region: ")
+  (save-excursion
+    (if buffer
+       (set-buffer (get-buffer buffer)))
+    (smiley-region (point-min) (point-max))))
+
+(defun smiley-toggle-buffer (&optional arg)
+  "Toggle displaying smiley faces in article buffer.
+With arg, turn displaying on if and only if arg is positive."
+  (interactive "P")
+  (gnus-with-article-buffer
+    (if (if (numberp arg)
+           (> arg 0)
+         (not (memq 'smiley gnus-article-wash-types)))
+       (smiley-region (point-min) (point-max))
+      (gnus-delete-images 'smiley))))
+
+(defun smiley-mouse-toggle-buffer (event)
+  "Toggle displaying smiley faces.
+With arg, turn displaying on if and only if arg is positive."
+  (interactive "e")
   (save-excursion
-    (set-buffer gnus-article-buffer)
-    (goto-char (point-min))
-    ;; We skip the headers.
-    (unless (search-forward "\n\n" nil t)
-      (goto-char (point-max)))
-    (smiley-buffer (current-buffer) (point))))
+    (save-window-excursion
+      (mouse-set-point event)
+      (smiley-toggle-buffer))))
 
 (provide 'smiley)
 
diff --git a/lisp/smime.el b/lisp/smime.el
new file mode 100644 (file)
index 0000000..908e696
--- /dev/null
@@ -0,0 +1,643 @@
+;;; smime.el --- S/MIME support library
+;; Copyright (c) 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: SMIME X.509 PEM OpenSSL
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This library perform S/MIME operations from within Emacs.
+;;
+;; Functions for fetching certificates from public repositories are
+;; provided, currently only from DNS.  LDAP support (via EUDC) is planned.
+;;
+;; It uses OpenSSL (tested with version 0.9.5a and 0.9.6) for signing,
+;; encryption and decryption.
+;;
+;; Some general knowledge of S/MIME, X.509, PKCS#12, PEM etc is
+;; probably required to use this library in any useful way.
+;; Especially, don't expect this library to buy security for you.  If
+;; you don't understand what you are doing, you're as likely to lose
+;; security than gain any by using this library.
+;;
+;; This library is not intended to provide a "raw" API for S/MIME,
+;; PKCSx or similar, it's intended to perform common operations
+;; done on messages encoded in these formats.  The terminology chosen
+;; reflect this.
+;;
+;; The home of this file is in Gnus CVS, but also available from
+;; http://josefsson.org/smime.html.
+
+;;; Quick introduction:
+
+;; Get your S/MIME certificate from VeriSign or someplace.  I used
+;; Netscape to generate the key and certificate request and stuff, and
+;; Netscape can export the key into PKCS#12 format.
+;;
+;; Enter OpenSSL.  To be able to use this library, it need to have the
+;; SMIME key readable in PEM format.  OpenSSL is used to convert the
+;; key:
+;;
+;; $ openssl pkcs12 -in mykey.p12 -clcerts -nodes > mykey.pem
+;; ...
+;;
+;; Now, use M-x customize-variable smime-keys and add mykey.pem as
+;; a key.
+;;
+;; Now you should be able to sign messages!  Create a buffer and write
+;; something and run M-x smime-sign-buffer RET RET and you should see
+;; your message MIME armoured and a signature.  Encryption, M-x
+;; smime-encrypt-buffer, should also work.
+;;
+;; To be able to verify messages you need to build up trust with
+;; someone.  Perhaps you trust the CA that issued your certificate, at
+;; least I did, so I export it's certificates from my PKCS#12
+;; certificate with:
+;;
+;; $ openssl pkcs12 -in mykey.p12 -cacerts -nodes > cacert.pem
+;; ...
+;;
+;; Now, use M-x customize-variable smime-CAs and add cacert.pem as a
+;; CA certificate.
+;;
+;; You should now be able to sign messages, and even verify messages
+;; sent by others that use the same CA as you.
+
+;; Bugs:
+;;
+;; Don't complain that this package doesn't do encrypted PEM files,
+;; submit a patch instead.  I store my keys in a safe place, so I
+;; didn't need the encryption.  Also, programming was made easier by
+;; that decision.  One might think that this even influenced were I
+;; store my keys, and one would probably be right. :-)
+;;
+;; Update: Mathias Herberts sent the patch.  However, it uses
+;; environment variables to pass the password to OpenSSL, which is
+;; slightly insecure. Hence a new todo: use a better -passin method.
+;;
+;; Cache password for e.g. 1h
+;;
+;; Suggestions and comments are appreciated, mail me at simon@josefsson.org.
+
+;; begin rant
+;;
+;; I would include pointers to introductory text on concepts used in
+;; this library here, but the material I've read are so horrible I
+;; don't want to recomend them.
+;;
+;; Why can't someone write a simple introduction to all this stuff?
+;; Until then, much of this resemble security by obscurity.
+;;
+;; Also, I'm not going to mention anything about the wonders of
+;; cryptopolitics.  Oops, I just did.
+;;
+;; end rant
+
+;;; Revision history:
+
+;; 2000-06-05  initial version, committed to Gnus CVS contrib/
+;; 2000-10-28  retrieve certificates via DNS CERT RRs
+;; 2001-10-14  posted to gnu.emacs.sources
+
+;;; Code:
+
+(require 'dig)
+(eval-when-compile (require 'cl))
+
+(defgroup smime nil
+  "S/MIME configuration.")
+
+(defcustom smime-keys nil
+  "*Map mail addresses to a file containing Certificate (and private key).
+The file is assumed to be in PEM format. You can also associate additional
+certificates to be sent with every message to each address."
+  :type '(repeat (list (string :tag "Mail address")
+                      (file :tag "File name")
+                      (repeat :tag "Additional certificate files"
+                              (file :tag "File name"))))
+  :group 'smime)
+
+(defcustom smime-CA-directory nil
+  "*Directory containing certificates for CAs you trust.
+Directory should contain files (in PEM format) named to the X.509
+hash of the certificate.  This can be done using OpenSSL such as:
+
+$ ln -s ca.pem `openssl x509 -noout -hash -in ca.pem`.0
+
+where `ca.pem' is the file containing a PEM encoded X.509 CA
+certificate."
+  :type '(choice (const :tag "none" nil)
+                directory)
+  :group 'smime)
+
+(defcustom smime-CA-file nil
+  "*Files containing certificates for CAs you trust.
+File should contain certificates in PEM format."
+  :type '(choice (const :tag "none" nil)
+                file)
+  :group 'smime)
+
+(defcustom smime-certificate-directory "~/Mail/certs/"
+  "*Directory containing other people's certificates.
+It should contain files named to the X.509 hash of the certificate,
+and the files themself should be in PEM format."
+;The S/MIME library provide simple functionality for fetching
+;certificates into this directory, so there is no need to populate it
+;manually.
+  :type 'directory
+  :group 'smime)
+
+(defcustom smime-openssl-program
+  (and (condition-case ()
+          (eq 0 (call-process "openssl" nil nil nil "version"))
+        (error nil))
+       "openssl")
+  "*Name of OpenSSL binary."
+  :type 'string
+  :group 'smime)
+
+;; OpenSSL option to select the encryption cipher
+
+(defcustom smime-encrypt-cipher "-des3"
+  "*Cipher algorithm used for encryption."
+  :type '(choice (const :tag "Triple DES" "-des3")
+                (const :tag "DES"  "-des")
+                (const :tag "RC2 40 bits" "-rc2-40")
+                (const :tag "RC2 64 bits" "-rc2-64")
+                (const :tag "RC2 128 bits" "-rc2-128"))
+  :group 'smime)
+
+(defcustom smime-crl-check nil
+  "*Check revocation status of signers certificate using CRLs.
+Enabling this will have OpenSSL check the signers certificate
+against a certificate revocation list (CRL).
+
+For this to work the CRL must be up-to-date and since they are
+normally updated quite often (ie. several times a day) you
+probably need some tool to keep them up-to-date. Unfortunately
+Gnus cannot do this for you.
+
+The CRL should either be appended (in PEM format) to your
+`smime-CA-file' or be located in a file (also in PEM format) in
+your `smime-certificate-directory' named to the X.509 hash of the
+certificate with .r0 as file name extension.
+
+At least OpenSSL version 0.9.7 is required for this to work."
+  :type '(choice (const :tag "No check" nil)
+                (const :tag "Check certificate" "-crl_check")
+                (const :tag "Check certificate chain" "-crl_check_all"))
+  :group 'smime)
+
+(defcustom smime-dns-server nil
+  "*DNS server to query certificates from.
+If nil, use system defaults."
+  :type '(choice (const :tag "System defaults")
+                string)
+  :group 'smime)
+
+(defvar smime-details-buffer "*OpenSSL output*")
+
+;; Use mm-util?
+(eval-and-compile
+  (defalias 'smime-make-temp-file
+    (if (fboundp 'make-temp-file)
+       'make-temp-file
+      (lambda (prefix &optional dir-flag) ;; Simple implementation
+       (expand-file-name
+        (make-temp-name prefix)
+        (if (fboundp 'temp-directory)
+            (temp-directory)
+          temporary-file-directory))))))
+
+;; Password dialog function
+
+(defun smime-ask-passphrase ()
+  "Asks the passphrase to unlock the secret key."
+  (let ((passphrase
+        (read-passwd
+         "Passphrase for secret key (RET for no passphrase): ")))
+    (if (string= passphrase "")
+       nil
+      passphrase)))
+
+;; OpenSSL wrappers.
+
+(defun smime-call-openssl-region (b e buf &rest args)
+  (case (apply 'call-process-region b e smime-openssl-program nil buf nil args)
+    (0 t)
+    (1 (message "OpenSSL: An error occurred parsing the command options.") nil)
+    (2 (message "OpenSSL: One of the input files could not be read.") nil)
+    (3 (message "OpenSSL: An error occurred creating the PKCS#7 file or when reading the MIME message.") nil)
+    (4 (message "OpenSSL: An error occurred decrypting or verifying the message.") nil)
+    (t (error "Unknown OpenSSL exitcode") nil)))
+
+(defun smime-make-certfiles (certfiles)
+  (if certfiles
+      (append (list "-certfile" (expand-file-name (car certfiles)))
+             (smime-make-certfiles (cdr certfiles)))))
+
+;; Sign+encrypt region
+
+(defun smime-sign-region (b e keyfile)
+  "Sign region with certified key in KEYFILE.
+If signing fails, the buffer is not modified.  Region is assumed to
+have proper MIME tags.  KEYFILE is expected to contain a PEM encoded
+private key and certificate as its car, and a list of additional
+certificates to include in its caar.  If no additional certificates is
+included, KEYFILE may be the file containing the PEM encoded private
+key and certificate itself."
+  (smime-new-details-buffer)
+  (let ((keyfile (or (car-safe keyfile) keyfile))
+       (certfiles (and (cdr-safe keyfile) (cadr keyfile)))
+       (buffer (generate-new-buffer (generate-new-buffer-name " *smime*")))
+       (passphrase (smime-ask-passphrase))
+       (tmpfile (smime-make-temp-file "smime")))
+    (if passphrase
+       (setenv "GNUS_SMIME_PASSPHRASE" passphrase))
+    (prog1
+       (when (prog1
+                 (apply 'smime-call-openssl-region b e (list buffer tmpfile)
+                        "smime" "-sign" "-signer" (expand-file-name keyfile)
+                        (append
+                         (smime-make-certfiles certfiles)
+                         (if passphrase
+                             (list "-passin" "env:GNUS_SMIME_PASSPHRASE"))))
+               (if passphrase
+                   (setenv "GNUS_SMIME_PASSPHRASE" "" t))
+               (with-current-buffer smime-details-buffer
+                 (insert-file-contents tmpfile)
+                 (delete-file tmpfile)))
+         (delete-region b e)
+         (insert-buffer-substring buffer)
+         (goto-char b)
+         (when (looking-at "^MIME-Version: 1.0$")
+           (delete-region (point) (progn (forward-line 1) (point))))
+         t)
+      (with-current-buffer smime-details-buffer
+       (goto-char (point-max))
+       (insert-buffer-substring buffer))
+      (kill-buffer buffer))))
+
+(defun smime-encrypt-region (b e certfiles)
+  "Encrypt region for recipients specified in CERTFILES.
+If encryption fails, the buffer is not modified.  Region is assumed to
+have proper MIME tags.  CERTFILES is a list of filenames, each file
+is expected to contain of a PEM encoded certificate."
+  (smime-new-details-buffer)
+  (let ((buffer (generate-new-buffer (generate-new-buffer-name " *smime*")))
+       (tmpfile (smime-make-temp-file "smime")))
+    (prog1
+       (when (prog1
+                 (apply 'smime-call-openssl-region b e (list buffer tmpfile)
+                        "smime" "-encrypt" smime-encrypt-cipher
+                        (mapcar 'expand-file-name certfiles))
+               (with-current-buffer smime-details-buffer
+                 (insert-file-contents tmpfile)
+                 (delete-file tmpfile)))
+         (delete-region b e)
+         (insert-buffer-substring buffer)
+         (goto-char b)
+         (when (looking-at "^MIME-Version: 1.0$")
+           (delete-region (point) (progn (forward-line 1) (point))))
+         t)
+      (with-current-buffer smime-details-buffer
+       (goto-char (point-max))
+       (insert-buffer-substring buffer))
+      (kill-buffer buffer))))
+
+;; Sign+encrypt buffer
+
+(defun smime-sign-buffer (&optional keyfile buffer)
+  "S/MIME sign BUFFER with key in KEYFILE.
+KEYFILE should contain a PEM encoded key and certificate."
+  (interactive)
+  (with-current-buffer (or buffer (current-buffer))
+    (smime-sign-region
+     (point-min) (point-max)
+     (if keyfile
+        keyfile
+       (smime-get-key-with-certs-by-email
+       (completing-read
+        (concat "Sign using which key? "
+                (if smime-keys (concat "(default " (caar smime-keys) ") ")
+                  ""))
+        smime-keys nil nil (car-safe (car-safe smime-keys))))))))
+
+(defun smime-encrypt-buffer (&optional certfiles buffer)
+  "S/MIME encrypt BUFFER for recipients specified in CERTFILES.
+CERTFILES is a list of filenames, each file is expected to consist of
+a PEM encoded key and certificate.  Uses current buffer if BUFFER is
+nil."
+  (interactive)
+  (with-current-buffer (or buffer (current-buffer))
+    (smime-encrypt-region
+     (point-min) (point-max)
+     (or certfiles
+        (list (read-file-name "Recipient's S/MIME certificate: "
+                              smime-certificate-directory nil))))))
+
+;; Verify+decrypt region
+
+(defun smime-verify-region (b e)
+  "Verify S/MIME message in region between B and E.
+Returns non-nil on success.
+Any details (stdout and stderr) are left in the buffer specified by
+`smime-details-buffer'."
+  (smime-new-details-buffer)
+  (let ((CAs (append (if smime-CA-file
+                        (list "-CAfile"
+                              (expand-file-name smime-CA-file)))
+                    (if smime-CA-directory
+                        (list "-CApath"
+                              (expand-file-name smime-CA-directory))))))
+    (unless CAs
+      (error "No CA configured"))
+    (if smime-crl-check
+       (add-to-list 'CAs smime-crl-check))
+    (if (apply 'smime-call-openssl-region b e (list smime-details-buffer t)
+              "smime" "-verify" "-out" "/dev/null" CAs)
+       t
+      (insert-buffer-substring smime-details-buffer)
+      nil)))
+
+(defun smime-noverify-region (b e)
+  "Verify integrity of S/MIME message in region between B and E.
+Returns non-nil on success.
+Any details (stdout and stderr) are left in the buffer specified by
+`smime-details-buffer'."
+  (smime-new-details-buffer)
+  (if (apply 'smime-call-openssl-region b e (list smime-details-buffer t)
+            "smime" "-verify" "-noverify" "-out" '("/dev/null"))
+      t
+    (insert-buffer-substring smime-details-buffer)
+    nil))
+
+(eval-when-compile
+  (defvar from))
+
+(defun smime-decrypt-region (b e keyfile)
+  "Decrypt S/MIME message in region between B and E with key in KEYFILE.
+On success, replaces region with decrypted data and return non-nil.
+Any details (stderr on success, stdout and stderr on error) are left
+in the buffer specified by `smime-details-buffer'."
+  (smime-new-details-buffer)
+  (let ((buffer (generate-new-buffer (generate-new-buffer-name " *smime*")))
+       CAs (passphrase (smime-ask-passphrase))
+       (tmpfile (smime-make-temp-file "smime")))
+    (if passphrase
+       (setenv "GNUS_SMIME_PASSPHRASE" passphrase))
+    (if (prog1
+           (apply 'smime-call-openssl-region b e
+                  (list buffer tmpfile)
+                  "smime" "-decrypt" "-recip" (expand-file-name keyfile)
+                  (if passphrase
+                      (list "-passin" "env:GNUS_SMIME_PASSPHRASE")))
+         (if passphrase
+             (setenv "GNUS_SMIME_PASSPHRASE" "" t))
+         (with-current-buffer smime-details-buffer
+           (insert-file-contents tmpfile)
+           (delete-file tmpfile)))
+       (progn
+         (delete-region b e)
+         (when (boundp 'from)
+           ;; `from' is dynamically bound in mm-dissect.
+           (insert "From: " from "\n"))
+         (insert-buffer-substring buffer)
+         (kill-buffer buffer)
+         t)
+      (with-current-buffer smime-details-buffer
+       (insert-buffer-substring buffer))
+      (kill-buffer buffer)
+      (delete-region b e)
+      (insert-buffer-substring smime-details-buffer)
+      nil)))
+
+;; Verify+Decrypt buffer
+
+(defun smime-verify-buffer (&optional buffer)
+  "Verify integrity of S/MIME message in BUFFER.
+Uses current buffer if BUFFER is nil. Returns non-nil on success.
+Any details (stdout and stderr) are left in the buffer specified by
+`smime-details-buffer'."
+  (interactive)
+  (with-current-buffer (or buffer (current-buffer))
+    (smime-verify-region (point-min) (point-max))))
+
+(defun smime-noverify-buffer (&optional buffer)
+  "Verify integrity of S/MIME message in BUFFER.
+Does NOT verify validity of certificate (only message integrity).
+Uses current buffer if BUFFER is nil. Returns non-nil on success.
+Any details (stdout and stderr) are left in the buffer specified by
+`smime-details-buffer'."
+  (interactive)
+  (with-current-buffer (or buffer (current-buffer))
+    (smime-noverify-region (point-min) (point-max))))
+
+(defun smime-decrypt-buffer (&optional buffer keyfile)
+  "Decrypt S/MIME message in BUFFER using KEYFILE.
+Uses current buffer if BUFFER is nil, and query user of KEYFILE if it's nil.
+On success, replaces data in buffer and return non-nil.
+Any details (stderr on success, stdout and stderr on error) are left
+in the buffer specified by `smime-details-buffer'."
+  (interactive)
+  (with-current-buffer (or buffer (current-buffer))
+    (smime-decrypt-region
+     (point-min) (point-max)
+     (expand-file-name
+      (or keyfile
+         (smime-get-key-by-email
+          (completing-read
+           (concat "Decipher using which key? "
+                   (if smime-keys (concat "(default " (caar smime-keys) ") ")
+                     ""))
+           smime-keys nil nil (car-safe (car-safe smime-keys)))))))))
+
+;; Various operations
+
+(defun smime-new-details-buffer ()
+  (with-current-buffer (get-buffer-create smime-details-buffer)
+    (erase-buffer)))
+
+(defun smime-pkcs7-region (b e)
+  "Convert S/MIME message between points B and E into a PKCS7 message."
+  (smime-new-details-buffer)
+  (when (smime-call-openssl-region b e smime-details-buffer "smime" "-pk7out")
+    (delete-region b e)
+    (insert-buffer-substring smime-details-buffer)
+    t))
+
+(defun smime-pkcs7-certificates-region (b e)
+  "Extract any certificates enclosed in PKCS7 message between points B and E."
+  (smime-new-details-buffer)
+  (when (smime-call-openssl-region
+        b e smime-details-buffer "pkcs7" "-print_certs" "-text")
+    (delete-region b e)
+    (insert-buffer-substring smime-details-buffer)
+    t))
+
+(defun smime-pkcs7-email-region (b e)
+  "Get email addresses contained in certificate between points B and E.
+A string or a list of strings is returned."
+  (smime-new-details-buffer)
+  (when (smime-call-openssl-region
+        b e smime-details-buffer "x509" "-email" "-noout")
+    (delete-region b e)
+    (insert-buffer-substring smime-details-buffer)
+    t))
+
+;; Utility functions
+
+(defun smime-get-certfiles (keyfile keys)
+  (if keys
+      (let ((curkey (car keys))
+           (otherkeys (cdr keys)))
+       (if (string= keyfile (cadr curkey))
+           (caddr curkey)
+         (smime-get-certfiles keyfile otherkeys)))))
+
+;; Use mm-util?
+(eval-and-compile
+  (defalias 'smime-point-at-eol
+    (if (fboundp 'point-at-eol)
+       'point-at-eol
+      'line-end-position)))
+
+(defun smime-buffer-as-string-region (b e)
+  "Return each line in region between B and E as a list of strings."
+  (save-excursion
+    (goto-char b)
+    (let (res)
+      (while (< (point) e)
+       (let ((str (buffer-substring (point) (smime-point-at-eol))))
+         (unless (string= "" str)
+           (push str res)))
+       (forward-line))
+      res)))
+
+;; Find certificates
+
+(defun smime-mail-to-domain (mailaddr)
+  (if (string-match "@" mailaddr)
+      (replace-match "." 'fixedcase 'literal mailaddr)
+    mailaddr))
+
+(defun smime-cert-by-dns (mail)
+  (let* ((dig-dns-server smime-dns-server)
+        (digbuf (dig-invoke (smime-mail-to-domain mail) "cert" nil nil "+vc"))
+        (retbuf (generate-new-buffer (format "*certificate for %s*" mail)))
+        (certrr (with-current-buffer digbuf
+                  (dig-extract-rr (smime-mail-to-domain mail) "cert")))
+        (cert (and certrr (dig-rr-get-pkix-cert certrr))))
+    (if cert
+       (with-current-buffer retbuf
+         (insert "-----BEGIN CERTIFICATE-----\n")
+         (let ((i 0) (len (length cert)))
+           (while (> (- len 64) i)
+             (insert (substring cert i (+ i 64)) "\n")
+             (setq i (+ i 64)))
+           (insert (substring cert i len) "\n"))
+         (insert "-----END CERTIFICATE-----\n"))
+      (kill-buffer retbuf)
+      (setq retbuf nil))
+    (kill-buffer digbuf)
+    retbuf))
+
+;; User interface.
+
+(defvar smime-buffer "*SMIME*")
+
+(defvar smime-mode-map nil)
+(put 'smime-mode 'mode-class 'special)
+
+(unless smime-mode-map
+  (setq smime-mode-map (make-sparse-keymap))
+  (suppress-keymap smime-mode-map)
+
+  (define-key smime-mode-map "q" 'smime-exit)
+  (define-key smime-mode-map "f" 'smime-certificate-info))
+
+(defun smime-mode ()
+  "Major mode for browsing, viewing and fetching certificates.
+
+All normal editing commands are switched off.
+\\<smime-mode-map>
+
+The following commands are available:
+
+\\{smime-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'smime-mode)
+  (setq mode-name "SMIME")
+  (setq mode-line-process nil)
+  (use-local-map smime-mode-map)
+  (buffer-disable-undo)
+  (setq truncate-lines t)
+  (setq buffer-read-only t))
+
+(defun smime-certificate-info (certfile)
+  (interactive "fCertificate file: ")
+  (let ((buffer (get-buffer-create (format "*certificate %s*" certfile))))
+    (switch-to-buffer buffer)
+    (erase-buffer)
+    (call-process smime-openssl-program nil buffer 'display
+                 "x509" "-in" (expand-file-name certfile) "-text")
+    (fundamental-mode)
+    (set-buffer-modified-p nil)
+    (toggle-read-only t)
+    (goto-char (point-min))))
+
+(defun smime-draw-buffer ()
+  (with-current-buffer smime-buffer
+    (let (buffer-read-only)
+      (erase-buffer)
+      (insert "\nYour keys:\n")
+      (dolist (key smime-keys)
+       (insert
+        (format "\t\t%s: %s\n" (car key) (cadr key))))
+      (insert "\nTrusted Certificate Authoritys:\n")
+      (insert "\nKnown Certificates:\n"))))
+
+(defun smime ()
+  "Go to the SMIME buffer."
+  (interactive)
+  (unless (get-buffer smime-buffer)
+    (save-excursion
+      (set-buffer (get-buffer-create smime-buffer))
+      (smime-mode)))
+  (smime-draw-buffer)
+  (switch-to-buffer smime-buffer))
+
+(defun smime-exit ()
+  "Quit the S/MIME buffer."
+  (interactive)
+  (kill-buffer (current-buffer)))
+
+;; Other functions
+
+(defun smime-get-key-by-email (email)
+  (cadr (assoc email smime-keys)))
+
+(defun smime-get-key-with-certs-by-email (email)
+  (cdr (assoc email smime-keys)))
+
+(provide 'smime)
+
+;;; smime.el ends here
diff --git a/lisp/spam-report.el b/lisp/spam-report.el
new file mode 100644 (file)
index 0000000..efd6778
--- /dev/null
@@ -0,0 +1,126 @@
+;;; spam-report.el --- Reporting spam
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Teodor Zlatanov <tzz@lifelogs.com>
+;; Keywords: network
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; This module addresses a few aspects of spam reporting under Gnus.  Page
+;;; breaks are used for grouping declarations and documentation relating to
+;;; each particular aspect.
+
+;;; Code:
+(require 'gnus)
+(require 'gnus-sum)
+
+(eval-and-compile
+  (autoload 'mm-url-insert "mm-url"))
+
+(defgroup spam-report nil
+  "Spam reporting configuration.")
+
+(defcustom spam-report-gmane-regex nil
+  "Regexp matching Gmane newsgroups, e.g. \"^nntp\\+.*:gmane\\.\"
+If you are using spam.el, consider setting gnus-spam-process-newsgroups
+or the gnus-group-spam-exit-processor-report-gmane group/topic parameter
+instead."
+  :type '(radio (const nil)
+               (regexp :format "%t: %v\n" :size 0 :value "^nntp\+.*:gmane\."))
+  :group 'spam-report)
+
+(defcustom spam-report-gmane-spam-header
+  "^X-Report-Spam: http://\\([^/]+\\)\\(.*\\)$"
+  "String matching Gmane spam-reporting header.  Two match groups are needed."
+  :type 'regexp
+  :group 'spam-report)
+
+(defcustom spam-report-gmane-use-article-number t
+  "Whether the article number (faster!) or the header should be used."
+  :type 'boolean
+  :group 'spam-report)
+
+(defcustom spam-report-url-ping-function
+  'spam-report-url-ping-plain
+  "Function to use for url ping spam reporting."
+  :type '(choice
+         (const :tag "Connect directly"
+                spam-report-url-ping-plain)
+         (const :tag "Use the external program specified in `mm-url-program'"
+                spam-report-url-ping-mm-url))
+  :group 'spam-report)
+
+(defun spam-report-gmane (&rest articles)
+  "Report an article as spam through Gmane"
+  (dolist (article articles)
+    (when (and gnus-newsgroup-name
+              (or (null spam-report-gmane-regex)
+                  (string-match spam-report-gmane-regex gnus-newsgroup-name)))
+      (gnus-message 6 "Reporting spam article %d to spam.gmane.org..." article)
+      (if spam-report-gmane-use-article-number
+         (spam-report-url-ping "spam.gmane.org"
+                               (format "/%s:%d"
+                                       (gnus-group-real-name gnus-newsgroup-name)
+                                       article))
+       (with-current-buffer nntp-server-buffer
+         (gnus-request-head article gnus-newsgroup-name)
+         (goto-char (point-min))
+         (if (re-search-forward spam-report-gmane-spam-header nil t)
+             (let* ((host (match-string 1))
+                    (report (match-string 2))
+                    (url (format "http://%s%s" host report)))
+               (gnus-message 7 "Reporting spam through URL %s..." url)
+               (spam-report-url-ping host report))
+           (gnus-message 3 "Could not find X-Report-Spam in article %d..."
+                         article)))))))
+
+(defun spam-report-url-ping (host report)
+  "Ping a host through HTTP, addressing a specific GET resource using
+the function specified by `spam-report-url-ping-function'."
+  (funcall spam-report-url-ping-function host report))
+
+(defun spam-report-url-ping-plain (host report)
+  "Ping a host through HTTP, addressing a specific GET resource."
+  (let ((tcp-connection))
+    (with-temp-buffer
+      (or (setq tcp-connection
+               (open-network-stream
+                "URL ping"
+                (buffer-name)
+                host
+                80))
+         (error "Could not open connection to %s" host))
+      (set-marker (process-mark tcp-connection) (point-min))
+      (process-send-string
+       tcp-connection
+       (format "GET %s HTTP/1.1\nUser-Agent: %s (spam-report.el)\nHost: %s\n\n"
+              report (gnus-emacs-version) host)))))
+
+(defun spam-report-url-ping-mm-url (host report)
+  "Ping a host through HTTP, addressing a specific GET resource. Use
+the external program specified in `mm-url-program' to connect to
+server."
+  (with-temp-buffer
+    (let ((url (concat "http://" host "/" report)))
+      (mm-url-insert url t))))
+
+(provide 'spam-report)
+
+;;; spam-report.el ends here.
diff --git a/lisp/spam-stat.el b/lisp/spam-stat.el
new file mode 100644 (file)
index 0000000..e85e057
--- /dev/null
@@ -0,0 +1,597 @@
+;;; spam-stat.el --- detecting spam based on statistics
+
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+
+;; Author: Alex Schroeder <alex@gnu.org>
+;; Keywords: network
+;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SpamStat
+
+;; This file is part of GNU Emacs.
+
+;; This is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This implements spam analysis according to Paul Graham in "A Plan
+;; for Spam".  The basis for all this is a statistical distribution of
+;; words for your spam and non-spam mails.  We need this information
+;; in a hash-table so that the analysis can use the information when
+;; looking at your mails.  Therefore, before you begin, you need tons
+;; of mails (Graham uses 4000 non-spam and 4000 spam mails for his
+;; experiments).
+;;
+;; The main interface to using spam-stat, are the following functions:
+;;
+;; `spam-stat-buffer-is-spam' -- called in a buffer, that buffer is
+;; considered to be a new spam mail; use this for new mail that has
+;; not been processed before
+;;
+;; `spam-stat-buffer-is-non-spam' -- called in a buffer, that buffer
+;; is considered to be a new non-spam mail; use this for new mail that
+;; has not been processed before
+;;
+;; `spam-stat-buffer-change-to-spam' -- called in a buffer, that
+;; buffer is no longer considered to be normal mail but spam; use this
+;; to change the status of a mail that has already been processed as
+;; non-spam
+;;
+;; `spam-stat-buffer-change-to-non-spam' -- called in a buffer, that
+;; buffer is no longer considered to be spam but normal mail; use this
+;; to change the status of a mail that has already been processed as
+;; spam
+;;
+;; `spam-stat-save' -- save the hash table to the file; the filename
+;; used is stored in the variable `spam-stat-file'
+;;
+;; `spam-stat-load' -- load the hash table from a file; the filename
+;; used is stored in the variable `spam-stat-file'
+;;
+;; `spam-stat-score-word' -- return the spam score for a word
+;;
+;; `spam-stat-score-buffer' -- return the spam score for a buffer
+;;
+;; `spam-stat-split-fancy' -- for fancy mail splitting; add
+;; the rule (: spam-stat-split-fancy) to `nnmail-split-fancy'
+;;
+;; This requires the following in your ~/.gnus file:
+;;
+;; (require 'spam-stat)
+;; (spam-stat-load)
+
+;;; Testing:
+
+;; Typical test will involve calls to the following functions:
+;;
+;; Reset: (spam-stat-reset)
+;; Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+;; Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+;; Save table: (spam-stat-save)
+;; File size: (nth 7 (file-attributes spam-stat-file))
+;; Number of words: (hash-table-count spam-stat)
+;; Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+;; Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+;; Reduce table size: (spam-stat-reduce-size)
+;; Save table: (spam-stat-save)
+;; File size: (nth 7 (file-attributes spam-stat-file))
+;; Number of words: (hash-table-count spam-stat)
+;; Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+;; Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+
+;;; Dictionary Creation:
+
+;; Typically, you will filter away mailing lists etc. using specific
+;; rules in `nnmail-split-fancy'.  Somewhere among these rules, you
+;; will filter spam.  Here is how you would create your dictionary:
+
+;; Reset: (spam-stat-reset)
+;; Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+;; Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+;; Repeat for any other non-spam group you need...
+;; Reduce table size: (spam-stat-reduce-size)
+;; Save table: (spam-stat-save)
+
+;;; Todo:
+
+;; Speed it up.  Integrate with Gnus such that it uses spam and expiry
+;; marks to call the appropriate functions when leaving the summary
+;; buffer and saves the hash table when leaving Gnus.  More testing:
+;; More mails, disabling SpamAssassin, double checking algorithm, find
+;; improved algorithm.
+
+;;; Thanks:
+
+;; Ted Zlatanov <tzz@lifelogs.com>
+;; Jesper Harder <harder@myrealbox.com>
+;; Dan Schmidt <dfan@dfan.org>
+;; Lasse Rasinen <lrasinen@iki.fi>
+;; Milan Zamazal <pdm@zamazal.org>
+
+\f
+
+;;; Code:
+
+(defgroup spam-stat nil
+  "Statistical spam detection for Emacs.
+Use the functions to build a dictionary of words and their statistical
+distribution in spam and non-spam mails.  Then use a function to determine
+whether a buffer contains spam or not."
+  :group 'gnus)
+
+(defcustom spam-stat-file "~/.spam-stat.el"
+  "File used to save and load the dictionary.
+See `spam-stat-to-hash-table' for the format of the file."
+  :type 'file
+  :group 'spam-stat)
+
+(defcustom spam-stat-install-hooks t
+  "Whether spam-stat should install its hooks in Gnus.
+This is set to nil if you use spam-stat through spam.el."
+  :type 'boolean
+  :group 'spam-stat)
+
+(defcustom spam-stat-unknown-word-score 0.2
+  "The score to use for unknown words.
+Also used for words that don't appear often enough."
+  :type 'number
+  :group 'spam-stat)
+
+(defcustom spam-stat-max-word-length 15
+  "Only words shorter than this will be considered."
+  :type 'integer
+  :group 'spam-stat)
+
+(defcustom spam-stat-max-buffer-length 10240
+  "Only the beginning of buffers will be analyzed.
+This variable says how many characters this will be."
+  :type 'integer
+  :group 'spam-stat)
+
+(defcustom spam-stat-split-fancy-spam-group "mail.spam"
+  "Name of the group where spam should be stored, if
+`spam-stat-split-fancy' is used in fancy splitting rules.  Has no
+effect when spam-stat is invoked through spam.el."
+  :type 'string
+  :group 'spam-stat)
+
+(defcustom spam-stat-split-fancy-spam-threshhold 0.9
+  "Spam score threshhold in spam-stat-split-fancy."
+  :type 'number
+  :group 'spam-stat)
+
+(defvar spam-stat-syntax-table
+  (let ((table (copy-syntax-table text-mode-syntax-table)))
+    (modify-syntax-entry ?- "w" table)
+    (modify-syntax-entry ?_ "w" table)
+    (modify-syntax-entry ?. "w" table)
+    (modify-syntax-entry ?! "w" table)
+    (modify-syntax-entry ?? "w" table)
+    (modify-syntax-entry ?+ "w" table)
+    table)
+  "Syntax table used when processing mails for statistical analysis.
+The important part is which characters are word constituents.")
+
+(defvar spam-stat-dirty nil
+  "Whether the spam-stat database needs saving.")
+
+(defvar spam-stat-buffer nil
+  "Buffer to use for scoring while splitting.
+This is set by hooking into Gnus.")
+
+(defvar spam-stat-buffer-name " *spam stat buffer*"
+  "Name of the `spam-stat-buffer'.")
+
+;; Functions missing in Emacs 20
+
+(when (memq nil (mapcar 'fboundp
+                       '(gethash hash-table-count make-hash-table
+                                 mapc puthash)))
+  (require 'cl)
+  (unless (fboundp 'puthash)
+    ;; alias puthash is missing from Emacs 20 cl-extra.el
+    (defalias 'puthash 'cl-puthash)))
+
+(eval-when-compile
+  (unless (fboundp 'with-syntax-table)
+    ;; Imported from Emacs 21.2
+    (defmacro with-syntax-table (table &rest body) "\
+Evaluate BODY with syntax table of current buffer set to a copy of TABLE.
+The syntax table of the current buffer is saved, BODY is evaluated, and the
+saved table is restored, even in case of an abnormal exit.
+Value is what BODY returns."
+      (let ((old-table (make-symbol "table"))
+           (old-buffer (make-symbol "buffer")))
+       `(let ((,old-table (syntax-table))
+              (,old-buffer (current-buffer)))
+          (unwind-protect
+              (progn
+                (set-syntax-table (copy-syntax-table ,table))
+                ,@body)
+            (save-current-buffer
+              (set-buffer ,old-buffer)
+              (set-syntax-table ,old-table))))))))
+
+;; Hooking into Gnus
+
+(defun spam-stat-store-current-buffer ()
+  "Store a copy of the current buffer in `spam-stat-buffer'."
+  (save-excursion
+    (let ((str (buffer-string)))
+      (set-buffer (get-buffer-create spam-stat-buffer-name))
+      (erase-buffer)
+      (insert str)
+      (setq spam-stat-buffer (current-buffer)))))
+
+(defun spam-stat-store-gnus-article-buffer ()
+  "Store a copy of the current article in `spam-stat-buffer'.
+This uses `gnus-article-buffer'."
+  (save-excursion
+    (set-buffer gnus-original-article-buffer)
+    (spam-stat-store-current-buffer)))
+
+;; Data -- not using defstruct in order to save space and time
+
+(defvar spam-stat (make-hash-table :test 'equal)
+  "Hash table used to store the statistics.
+Use `spam-stat-load' to load the file.
+Every word is used as a key in this table.  The value is a vector.
+Use `spam-stat-ngood', `spam-stat-nbad', `spam-stat-good',
+`spam-stat-bad', and `spam-stat-score' to access this vector.")
+
+(defvar spam-stat-ngood 0
+  "The number of good mails in the dictionary.")
+
+(defvar spam-stat-nbad 0
+  "The number of bad mails in the dictionary.")
+
+(defsubst spam-stat-good (entry)
+  "Return the number of times this word belongs to good mails."
+  (aref entry 0))
+
+(defsubst spam-stat-bad (entry)
+  "Return the number of times this word belongs to bad mails."
+  (aref entry 1))
+
+(defsubst spam-stat-score (entry)
+  "Set the score of this word."
+  (if entry
+      (aref entry 2)
+    spam-stat-unknown-word-score))
+
+(defsubst spam-stat-set-good (entry value)
+  "Set the number of times this word belongs to good mails."
+  (aset entry 0 value))
+
+(defsubst spam-stat-set-bad (entry value)
+  "Set the number of times this word belongs to bad mails."
+  (aset entry 1 value))
+
+(defsubst spam-stat-set-score (entry value)
+  "Set the score of this word."
+  (aset entry 2 value))
+
+(defsubst spam-stat-make-entry (good bad)
+  "Return a vector with the given properties."
+  (let ((entry (vector good bad nil)))
+    (spam-stat-set-score entry (spam-stat-compute-score entry))
+    entry))
+
+;; Computing
+
+(defun spam-stat-compute-score (entry)
+  "Compute the score of this word.  1.0 means spam."
+   ;; promote all numbers to floats for the divisions
+   (let* ((g (* 2.0 (spam-stat-good entry)))
+         (b (float (spam-stat-bad entry))))
+     (cond ((< (+ g b) 5)
+           .2)
+          ((= 0 spam-stat-ngood)
+           .99)
+          ((= 0 spam-stat-nbad)
+           .01)
+          (t
+           (max .01
+                (min .99 (/ (/ b spam-stat-nbad)
+                            (+ (/ g spam-stat-ngood)
+                               (/ b spam-stat-nbad)))))))))
+
+;; Parsing
+
+(defmacro with-spam-stat-max-buffer-size (&rest body)
+  "Narrows the buffer down to the first 4k characters, then evaluates BODY."
+  `(save-restriction
+     (when (> (- (point-max)
+                (point-min))
+             spam-stat-max-buffer-length)
+       (narrow-to-region (point-min)
+                        (+ (point-min) spam-stat-max-buffer-length)))
+     ,@body))
+
+(defun spam-stat-buffer-words ()
+  "Return a hash table of words and number of occurences in the buffer."
+  (with-spam-stat-max-buffer-size
+   (with-syntax-table spam-stat-syntax-table
+     (goto-char (point-min))
+     (let ((result (make-hash-table :test 'equal))
+          word count)
+       (while (re-search-forward "\\w+" nil t)
+        (setq word (match-string-no-properties 0)
+              count (1+ (gethash word result 0)))
+        (when (< (length word) spam-stat-max-word-length)
+          (puthash word count result)))
+       result))))
+
+(defun spam-stat-buffer-is-spam ()
+  "Consider current buffer to be a new spam mail."
+  (setq spam-stat-nbad (1+ spam-stat-nbad))
+  (maphash
+   (lambda (word count)
+     (let ((entry (gethash word spam-stat)))
+       (if entry
+          (spam-stat-set-bad entry (+ count (spam-stat-bad entry)))
+        (setq entry (spam-stat-make-entry 0 count)))
+       (spam-stat-set-score entry (spam-stat-compute-score entry))
+       (puthash word entry spam-stat)))
+   (spam-stat-buffer-words))
+  (setq spam-stat-dirty t))
+
+(defun spam-stat-buffer-is-non-spam ()
+  "Consider current buffer to be a new non-spam mail."
+  (setq spam-stat-ngood (1+ spam-stat-ngood))
+  (maphash
+   (lambda (word count)
+     (let ((entry (gethash word spam-stat)))
+       (if entry
+          (spam-stat-set-good entry (+ count (spam-stat-good entry)))
+        (setq entry (spam-stat-make-entry count 0)))
+       (spam-stat-set-score entry (spam-stat-compute-score entry))
+       (puthash word entry spam-stat)))
+   (spam-stat-buffer-words))
+  (setq spam-stat-dirty t))
+
+(defun spam-stat-buffer-change-to-spam ()
+  "Consider current buffer no longer normal mail but spam."
+  (setq spam-stat-nbad (1+ spam-stat-nbad)
+       spam-stat-ngood (1- spam-stat-ngood))
+  (maphash
+   (lambda (word count)
+     (let ((entry (gethash word spam-stat)))
+       (if (not entry)
+          (error "This buffer has unknown words in it.")
+        (spam-stat-set-good entry (- (spam-stat-good entry) count))
+        (spam-stat-set-bad entry (+ (spam-stat-bad entry) count))
+        (spam-stat-set-score entry (spam-stat-compute-score entry))
+        (puthash word entry spam-stat))))
+   (spam-stat-buffer-words))
+  (setq spam-stat-dirty t))
+
+(defun spam-stat-buffer-change-to-non-spam ()
+  "Consider current buffer no longer spam but normal mail."
+  (setq spam-stat-nbad (1- spam-stat-nbad)
+       spam-stat-ngood (1+ spam-stat-ngood))
+  (maphash
+   (lambda (word count)
+     (let ((entry (gethash word spam-stat)))
+       (if (not entry)
+          (error "This buffer has unknown words in it.")
+        (spam-stat-set-good entry (+ (spam-stat-good entry) count))
+        (spam-stat-set-bad entry (- (spam-stat-bad entry) count))
+        (spam-stat-set-score entry (spam-stat-compute-score entry))
+        (puthash word entry spam-stat))))
+   (spam-stat-buffer-words))
+  (setq spam-stat-dirty t))
+
+;; Saving and Loading
+
+(defun spam-stat-save (&optional force)
+  "Save the `spam-stat' hash table as lisp file."
+  (interactive)
+  (when (or force spam-stat-dirty)
+    (with-temp-buffer
+      (let ((standard-output (current-buffer))
+           (font-lock-maximum-size 0))
+       (insert "(setq spam-stat-ngood "
+               (number-to-string spam-stat-ngood)
+               " spam-stat-nbad "
+               (number-to-string spam-stat-nbad)
+               " spam-stat (spam-stat-to-hash-table '(")
+       (maphash (lambda (word entry)
+                  (prin1 (list word
+                               (spam-stat-good entry)
+                               (spam-stat-bad entry))))
+                spam-stat)
+       (insert ")))")
+       (write-file spam-stat-file)))
+    (setq spam-stat-dirty nil)))
+
+(defun spam-stat-load ()
+  "Read the `spam-stat' hash table from disk."
+  ;; TODO: maybe we should warn the user if spam-stat-dirty is t?
+  (load-file spam-stat-file)
+  (setq spam-stat-dirty nil))
+
+(defun spam-stat-to-hash-table (entries)
+  "Turn list ENTRIES into a hash table and store as `spam-stat'.
+Every element in ENTRIES has the form \(WORD GOOD BAD) where WORD is
+the word string, NGOOD is the number of good mails it has appeared in,
+NBAD is the number of bad mails it has appeared in, GOOD is the number
+of times it appeared in good mails, and BAD is the number of times it
+has appeared in bad mails."
+  (let ((table (make-hash-table :test 'equal)))
+    (mapc (lambda (l)
+           (puthash (car l)
+                    (spam-stat-make-entry (nth 1 l) (nth 2 l))
+                    table))
+         entries)
+    table))
+
+(defun spam-stat-reset ()
+  "Reset `spam-stat' to an empty hash-table.
+This deletes all the statistics."
+  (interactive)
+  (setq spam-stat (make-hash-table :test 'equal)
+       spam-stat-ngood 0
+       spam-stat-nbad 0)
+  (setq spam-stat-dirty t))
+
+;; Scoring buffers
+
+(defvar spam-stat-score-data nil
+  "Raw data used in the last run of `spam-stat-score-buffer'.")
+
+(defsubst spam-stat-score-word (word)
+  "Return score for WORD.
+The default score for unknown words is stored in
+`spam-stat-unknown-word-score'."
+  (spam-stat-score (gethash word spam-stat)))
+
+(defun spam-stat-buffer-words-with-scores ()
+  "Process current buffer, return the 15 most conspicuous words.
+These are the words whose spam-stat differs the most from 0.5.
+The list returned contains elements of the form \(WORD SCORE DIFF),
+where DIFF is the difference between SCORE and 0.5."
+  (with-spam-stat-max-buffer-size
+   (with-syntax-table spam-stat-syntax-table
+     (let (result word score)
+       (maphash        (lambda (word ignore)
+                 (setq score (spam-stat-score-word word)
+                       result (cons (list word score (abs (- score 0.5)))
+                                    result)))
+               (spam-stat-buffer-words))
+       (setq result (sort result (lambda (a b) (< (nth 2 b) (nth 2 a)))))
+       (setcdr (nthcdr 14 result) nil)
+       result))))
+
+(defun spam-stat-score-buffer ()
+  "Return a score describing the spam-probability for this buffer."
+  (setq spam-stat-score-data (spam-stat-buffer-words-with-scores))
+  (let* ((probs (mapcar (lambda (e) (cadr e)) spam-stat-score-data))
+        (prod (apply #'* probs)))
+    (/ prod (+ prod (apply #'* (mapcar #'(lambda (x) (- 1 x))
+                                      probs))))))
+
+(defun spam-stat-split-fancy ()
+  "Return the name of the spam group if the current mail is spam.
+Use this function on `nnmail-split-fancy'.  If you are interested in
+the raw data used for the last run of `spam-stat-score-buffer',
+check the variable `spam-stat-score-data'."
+  (condition-case var
+      (progn
+       (set-buffer spam-stat-buffer)
+       (goto-char (point-min))
+       (when (> (spam-stat-score-buffer) spam-stat-split-fancy-spam-threshhold)
+         (when (boundp 'nnmail-split-trace)
+           (mapc (lambda (entry)
+                   (push entry nnmail-split-trace))
+                 spam-stat-score-data))
+         spam-stat-split-fancy-spam-group))
+    (error (message "Error in spam-stat-split-fancy: %S" var)
+          nil)))
+
+;; Testing
+
+(defun spam-stat-process-directory (dir func)
+  "Process all the regular files in directory DIR using function FUNC."
+  (let* ((files (directory-files dir t "^[^.]"))
+        (max (/ (length files) 100.0))
+        (count 0))
+    (with-temp-buffer
+      (dolist (f files)
+       (when (and (file-readable-p f)
+                  (file-regular-p f)
+                   (> (nth 7 (file-attributes f)) 0))
+         (setq count (1+ count))
+         (message "Reading %s: %.2f%%" dir (/ count max))
+         (insert-file-contents f)
+         (funcall func)
+         (erase-buffer))))))
+
+(defun spam-stat-process-spam-directory (dir)
+  "Process all the regular files in directory DIR as spam."
+  (interactive "D")
+  (spam-stat-process-directory dir 'spam-stat-buffer-is-spam))
+
+(defun spam-stat-process-non-spam-directory (dir)
+  "Process all the regular files in directory DIR as non-spam."
+  (interactive "D")
+  (spam-stat-process-directory dir 'spam-stat-buffer-is-non-spam))
+
+(defun spam-stat-count ()
+  "Return size of `spam-stat'."
+  (interactive)
+  (hash-table-count spam-stat))
+
+(defun spam-stat-test-directory (dir)
+  "Test all the regular files in directory DIR for spam.
+If the result is 1.0, then all files are considered spam.
+If the result is 0.0, non of the files is considered spam.
+You can use this to determine error rates."
+  (interactive "D")
+  (let* ((files (directory-files dir t "^[^.]"))
+        (total (length files))
+        (score 0.0); float
+        (max (/ total 100.0)); float
+        (count 0))
+    (with-temp-buffer
+      (dolist (f files)
+       (when (and (file-readable-p f)
+                  (file-regular-p f)
+                   (> (nth 7 (file-attributes f)) 0))
+         (setq count (1+ count))
+         (message "Reading %.2f%%, score %.2f%%"
+                  (/ count max) (/ score count))
+         (insert-file-contents f)
+         (when (> (spam-stat-score-buffer) 0.9)
+           (setq score (1+ score)))
+         (erase-buffer))))
+    (message "Final score: %d / %d = %f" score total (/ score total))))
+
+;; Shrinking the dictionary
+
+(defun spam-stat-reduce-size (&optional count)
+  "Reduce the size of `spam-stat'.
+This removes all words that occur less than COUNT from the dictionary.
+COUNT defaults to 5"
+  (interactive)
+  (setq count (or count 5))
+  (maphash (lambda (key entry)
+            (when (< (+ (spam-stat-good entry)
+                        (spam-stat-bad entry))
+                     count)
+              (remhash key spam-stat)))
+          spam-stat))
+
+(defun spam-stat-install-hooks-function ()
+  "Install the spam-stat function hooks"
+  (interactive)
+  (add-hook 'nnmail-prepare-incoming-message-hook
+           'spam-stat-store-current-buffer)
+  (add-hook 'gnus-select-article-hook
+           'spam-stat-store-gnus-article-buffer))
+
+(when spam-stat-install-hooks
+  (spam-stat-install-hooks-function))
+
+(defun spam-stat-unload-hook ()
+  "Uninstall the spam-stat function hooks"
+  (interactive)
+  (remove-hook 'nnmail-prepare-incoming-message-hook
+              'spam-stat-store-current-buffer)
+  (remove-hook 'gnus-select-article-hook
+              'spam-stat-store-gnus-article-buffer))
+
+(provide 'spam-stat)
+
+;;; spam-stat.el ends here
diff --git a/lisp/spam.el b/lisp/spam.el
new file mode 100644 (file)
index 0000000..008f8e9
--- /dev/null
@@ -0,0 +1,1823 @@
+;;; spam.el --- Identifying spam
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;; Keywords: network
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; This module addresses a few aspects of spam control under Gnus.  Page
+;;; breaks are used for grouping declarations and documentation relating to
+;;; each particular aspect.
+
+;;; The integration with Gnus is not yet complete.  See various `FIXME'
+;;; comments, below, for supplementary explanations or discussions.
+
+;;; Several TODO items are marked as such
+
+;; TODO: spam scores, detection of spam in newsgroups, cross-server splitting,
+;; remote processing, training through files
+
+;;; Code:
+
+(require 'path-util)
+
+(eval-when-compile (require 'cl))
+
+(require 'gnus-sum)
+
+(require 'gnus-uu)                     ; because of key prefix issues
+;;; for the definitions of group content classification and spam processors
+(require 'gnus)
+(require 'message)             ;for the message-fetch-field functions
+
+;; for nnimap-split-download-body-default
+(eval-when-compile (require 'nnimap))
+
+;; autoload query-dig
+(eval-and-compile
+  (autoload 'query-dig "dig"))
+
+;; autoload spam-report
+(eval-and-compile
+  (autoload 'spam-report-gmane "spam-report"))
+
+;; autoload gnus-registry
+(eval-and-compile
+  (autoload 'gnus-registry-group-count "gnus-registry")
+  (autoload 'gnus-registry-add-group "gnus-registry")
+  (autoload 'gnus-registry-store-extra-entry "gnus-registry")
+  (autoload 'gnus-registry-fetch-extra "gnus-registry"))
+
+;; autoload query-dns
+(eval-and-compile
+  (autoload 'query-dns "dns"))
+
+;;; Main parameters.
+
+(defgroup spam nil
+  "Spam configuration.")
+
+(defcustom spam-directory "~/News/spam/"
+  "Directory for spam whitelists and blacklists."
+  :type 'directory
+  :group 'spam)
+
+(defcustom spam-move-spam-nonspam-groups-only t
+  "Whether spam should be moved in non-spam groups only.
+When t, only ham and unclassified groups will have their spam moved
+to the spam-process-destination.  When nil, spam will also be moved from
+spam groups."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-process-ham-in-nonham-groups nil
+  "Whether ham should be processed in non-ham groups."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-log-to-registry nil
+  "Whether spam/ham processing should be logged in the registry."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-split-symbolic-return nil
+  "Whether `spam-split' should work with symbols or group names."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-split-symbolic-return-positive nil
+  "Whether `spam-split' should ALWAYS work with symbols or group names.
+Do not set this if you use `spam-split' in a fancy split
+  method."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-process-ham-in-spam-groups nil
+  "Whether ham should be processed in spam groups."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-mark-only-unseen-as-spam t
+  "Whether only unseen articles should be marked as spam in spam groups.
+When nil, all unread articles in a spam group are marked as
+spam.  Set this if you want to leave an article unread in a spam group
+without losing it to the automatic spam-marking process."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-mark-ham-unread-before-move-from-spam-group nil
+  "Whether ham should be marked unread before it's moved.
+The article is moved out of a spam group according to ham-process-destination.
+This variable is an official entry in the international Longest Variable Name
+Competition."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-disable-spam-split-during-ham-respool nil
+  "Whether `spam-split' should be ignored while resplitting ham in a process
+destination.  This is useful to prevent ham from ending up in the same spam
+group after the resplit.  Don't set this to t if you have spam-split as the
+last rule in your split configuration."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-autodetect-recheck-messages nil
+  "Should spam.el recheck all meessages when autodetecting?
+Normally this is nil, so only unseen messages will be checked."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-whitelist (expand-file-name "whitelist" spam-directory)
+  "The location of the whitelist.
+The file format is one regular expression per line.
+The regular expression is matched against the address."
+  :type 'file
+  :group 'spam)
+
+(defcustom spam-blacklist (expand-file-name "blacklist" spam-directory)
+  "The location of the blacklist.
+The file format is one regular expression per line.
+The regular expression is matched against the address."
+  :type 'file
+  :group 'spam)
+
+(defcustom spam-use-dig t
+  "Whether `query-dig' should be used instead of `query-dns'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-blacklist nil
+  "Whether the blacklist should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-blacklist-ignored-regexes nil
+  "Regular expressions that the blacklist should ignore."
+  :type '(repeat (regexp :tag "Regular expression to ignore when blacklisting"))
+  :group 'spam)
+
+(defcustom spam-use-whitelist nil
+  "Whether the whitelist should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-whitelist-exclusive nil
+  "Whether whitelist-exclusive should be used by `spam-split'.
+Exclusive whitelisting means that all messages from senders not in the whitelist
+are considered spam."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-blackholes nil
+  "Whether blackholes should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-hashcash nil
+  "Whether hashcash payments should be detected by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-regex-headers nil
+  "Whether a header regular expression match should be used by `spam-split'.
+Also see the variables `spam-regex-headers-spam' and `spam-regex-headers-ham'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-regex-body nil
+  "Whether a body regular expression match should be used by `spam-split'.
+Also see the variables `spam-regex-body-spam' and `spam-regex-body-ham'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-bogofilter-headers nil
+  "Whether bogofilter headers should be used by `spam-split'.
+Enable this if you pre-process messages with Bogofilter BEFORE Gnus sees them."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-bogofilter nil
+  "Whether bogofilter should be invoked by `spam-split'.
+Enable this if you want Gnus to invoke Bogofilter on new messages."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-BBDB nil
+  "Whether BBDB should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-BBDB-exclusive nil
+  "Whether BBDB-exclusive should be used by `spam-split'.
+Exclusive BBDB means that all messages from senders not in the BBDB are
+considered spam."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-ifile nil
+  "Whether ifile should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-stat nil
+  "Whether `spam-stat' should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-use-spamoracle nil
+  "Whether spamoracle should be used by `spam-split'."
+  :type 'boolean
+  :group 'spam)
+
+(defcustom spam-install-hooks (or
+                              spam-use-dig
+                              spam-use-blacklist
+                              spam-use-whitelist
+                              spam-use-whitelist-exclusive
+                              spam-use-blackholes
+                              spam-use-hashcash
+                              spam-use-regex-headers
+                              spam-use-regex-body
+                              spam-use-bogofilter-headers
+                              spam-use-bogofilter
+                              spam-use-BBDB
+                              spam-use-BBDB-exclusive
+                              spam-use-ifile
+                              spam-use-stat
+                              spam-use-spamoracle)
+  "Whether the spam hooks should be installed.
+Default to t if one of the spam-use-* variables is set."
+  :group 'spam
+  :type 'boolean)
+
+(defcustom spam-split-group "spam"
+  "Group name where incoming spam should be put by `spam-split'."
+  :type 'string
+  :group 'spam)
+
+;;; TODO: deprecate this variable, it's confusing since it's a list of strings,
+;;; not regular expressions
+(defcustom spam-junk-mailgroups (cons
+                                spam-split-group
+                                '("mail.junk" "poste.pourriel"))
+  "Mailgroups with spam contents.
+All unmarked article in such group receive the spam mark on group entry."
+  :type '(repeat (string :tag "Group"))
+  :group 'spam)
+
+(defcustom spam-blackhole-servers '("bl.spamcop.net" "relays.ordb.org"
+                                   "dev.null.dk" "relays.visi.com")
+  "List of blackhole servers."
+  :type '(repeat (string :tag "Server"))
+  :group 'spam)
+
+(defcustom spam-blackhole-good-server-regex nil
+  "String matching IP addresses that should not be checked in the blackholes."
+  :type '(radio (const nil)
+               (regexp :format "%t: %v\n" :size 0))
+  :group 'spam)
+
+(defcustom spam-face 'gnus-splash-face
+  "Face for spam-marked articles."
+  :type 'face
+  :group 'spam)
+
+(defcustom spam-regex-headers-spam '("^X-Spam-Flag: YES")
+  "Regular expression for positive header spam matches."
+  :type '(repeat (regexp :tag "Regular expression to match spam header"))
+  :group 'spam)
+
+(defcustom spam-regex-headers-ham '("^X-Spam-Flag: NO")
+  "Regular expression for positive header ham matches."
+  :type '(repeat (regexp :tag "Regular expression to match ham header"))
+  :group 'spam)
+
+(defcustom spam-regex-body-spam '()
+  "Regular expression for positive body spam matches."
+  :type '(repeat (regexp :tag "Regular expression to match spam body"))
+  :group 'spam)
+
+(defcustom spam-regex-body-ham '()
+  "Regular expression for positive body ham matches."
+  :type '(repeat (regexp :tag "Regular expression to match ham body"))
+  :group 'spam)
+
+(defgroup spam-ifile nil
+  "Spam ifile configuration."
+  :group 'spam)
+
+(defcustom spam-ifile-path (exec-installed-p "ifile")
+  "File path of the ifile executable program."
+  :type '(choice (file :tag "Location of ifile")
+                (const :tag "ifile is not installed"))
+  :group 'spam-ifile)
+
+(defcustom spam-ifile-database-path nil
+  "File path of the ifile database."
+  :type '(choice (file :tag "Location of the ifile database")
+                (const :tag "Use the default"))
+  :group 'spam-ifile)
+
+(defcustom spam-ifile-spam-category "spam"
+  "Name of the spam ifile category."
+  :type 'string
+  :group 'spam-ifile)
+
+(defcustom spam-ifile-ham-category nil
+  "Name of the ham ifile category.
+If nil, the current group name will be used."
+  :type '(choice (string :tag "Use a fixed category")
+                (const :tag "Use the current group name"))
+  :group 'spam-ifile)
+
+(defcustom spam-ifile-all-categories nil
+  "Whether the ifile check will return all categories, or just spam.
+Set this to t if you want to use the `spam-split' invocation of ifile as
+your main source of newsgroup names."
+  :type 'boolean
+  :group 'spam-ifile)
+
+(defgroup spam-bogofilter nil
+  "Spam bogofilter configuration."
+  :group 'spam)
+
+(defcustom spam-bogofilter-path (exec-installed-p "bogofilter")
+  "File path of the Bogofilter executable program."
+  :type '(choice (file :tag "Location of bogofilter")
+                (const :tag "Bogofilter is not installed"))
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-header "X-Bogosity"
+  "The header that Bogofilter inserts in messages."
+  :type 'string
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-spam-switch "-s"
+  "The switch that Bogofilter uses to register spam messages."
+  :type 'string
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-ham-switch "-n"
+  "The switch that Bogofilter uses to register ham messages."
+  :type 'string
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-spam-strong-switch "-S"
+  "The switch that Bogofilter uses to unregister ham messages."
+  :type 'string
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-ham-strong-switch "-N"
+  "The switch that Bogofilter uses to unregister spam messages."
+  :type 'string
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-bogosity-positive-spam-header "^\\(Yes\\|Spam\\)"
+  "The regex on `spam-bogofilter-header' for positive spam identification."
+  :type 'regexp
+  :group 'spam-bogofilter)
+
+(defcustom spam-bogofilter-database-directory nil
+  "Directory path of the Bogofilter databases."
+  :type '(choice (directory
+                 :tag "Location of the Bogofilter database directory")
+                (const :tag "Use the default"))
+  :group 'spam-bogofilter)
+
+(defgroup spam-spamoracle nil
+  "Spam spamoracle configuration."
+  :group 'spam)
+
+(defcustom spam-spamoracle-database nil
+  "Location of spamoracle database file. When nil, use the default
+spamoracle database."
+  :type '(choice (directory :tag "Location of spamoracle database file.")
+                (const :tag "Use the default"))
+  :group 'spam-spamoracle)
+
+(defcustom spam-spamoracle-binary (executable-find "spamoracle")
+  "Location of the spamoracle binary."
+  :type '(choice (directory :tag "Location of the spamoracle binary")
+                (const :tag "Use the default"))
+  :group 'spam-spamoracle)
+
+;;; Key bindings for spam control.
+
+(gnus-define-keys gnus-summary-mode-map
+  "St" spam-bogofilter-score
+  "Sx" gnus-summary-mark-as-spam
+  "Mst" spam-bogofilter-score
+  "Msx" gnus-summary-mark-as-spam
+  "\M-d" gnus-summary-mark-as-spam)
+
+(defvar spam-old-ham-articles nil
+  "List of old ham articles, generated when a group is entered.")
+
+(defvar spam-old-spam-articles nil
+  "List of old spam articles, generated when a group is entered.")
+
+(defvar spam-split-disabled nil
+  "If non-nil, `spam-split' is disabled, and always returns nil.")
+
+(defvar spam-split-last-successful-check nil
+  "`spam-split' will set this to nil or a spam-use-XYZ check if it
+  finds ham or spam.")
+
+;; convenience functions
+(defun spam-xor (a b)
+  "Logical exclusive `or'."
+  (and (or a b) (not (and a b))))
+
+(defun spam-group-ham-mark-p (group mark &optional spam)
+  (when (stringp group)
+    (let* ((marks (spam-group-ham-marks group spam))
+          (marks (if (symbolp mark)
+                     marks
+                   (mapcar 'symbol-value marks))))
+      (memq mark marks))))
+
+(defun spam-group-spam-mark-p (group mark)
+  (spam-group-ham-mark-p group mark t))
+
+(defun spam-group-ham-marks (group &optional spam)
+  (when (stringp group)
+    (let* ((marks (if spam
+                     (gnus-parameter-spam-marks group)
+                   (gnus-parameter-ham-marks group)))
+          (marks (car marks))
+          (marks (if (listp (car marks)) (car marks) marks)))
+      marks)))
+
+(defun spam-group-spam-marks (group)
+  (spam-group-ham-marks group t))
+
+(defun spam-group-spam-contents-p (group)
+  (if (stringp group)
+      (or (member group spam-junk-mailgroups)
+         (memq 'gnus-group-spam-classification-spam
+               (gnus-parameter-spam-contents group)))
+    nil))
+
+(defun spam-group-ham-contents-p (group)
+  (if (stringp group)
+      (memq 'gnus-group-spam-classification-ham
+           (gnus-parameter-spam-contents group))
+    nil))
+
+(defvar spam-list-of-processors
+  '((gnus-group-spam-exit-processor-report-gmane spam spam-use-gmane)
+    (gnus-group-spam-exit-processor-bogofilter   spam spam-use-bogofilter)
+    (gnus-group-spam-exit-processor-blacklist    spam spam-use-blacklist)
+    (gnus-group-spam-exit-processor-ifile        spam spam-use-ifile)
+    (gnus-group-spam-exit-processor-stat         spam spam-use-stat)
+    (gnus-group-spam-exit-processor-spamoracle   spam spam-use-spamoracle)
+    (gnus-group-ham-exit-processor-ifile         ham spam-use-ifile)
+    (gnus-group-ham-exit-processor-bogofilter    ham spam-use-bogofilter)
+    (gnus-group-ham-exit-processor-stat          ham spam-use-stat)
+    (gnus-group-ham-exit-processor-whitelist     ham spam-use-whitelist)
+    (gnus-group-ham-exit-processor-BBDB          ham spam-use-BBDB)
+    (gnus-group-ham-exit-processor-copy          ham spam-use-ham-copy)
+    (gnus-group-ham-exit-processor-spamoracle    ham spam-use-spamoracle))
+  "The spam-list-of-processors list contains pairs associating a
+ham/spam exit processor variable with a classification and a
+spam-use-* variable.")
+
+(defun spam-group-processor-p (group processor)
+  (if (and (stringp group)
+          (symbolp processor))
+      (or (member processor (nth 0 (gnus-parameter-spam-process group)))
+         (spam-group-processor-multiple-p
+          group
+          (cdr-safe (assoc processor spam-list-of-processors))))
+    nil))
+
+(defun spam-group-processor-multiple-p (group processor-info)
+  (let* ((classification (nth 0 processor-info))
+        (check (nth 1 processor-info))
+        (parameters (nth 0 (gnus-parameter-spam-process group)))
+        found)
+    (dolist (parameter parameters)
+      (when (and (null found)
+                (listp parameter)
+                (eq classification (nth 0 parameter))
+                (eq check (nth 1 parameter)))
+       (setq found t)))
+    found))
+
+(defun spam-group-spam-processor-report-gmane-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-report-gmane))
+
+(defun spam-group-spam-processor-bogofilter-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-bogofilter))
+
+(defun spam-group-spam-processor-blacklist-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-blacklist))
+
+(defun spam-group-spam-processor-ifile-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-ifile))
+
+(defun spam-group-ham-processor-ifile-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-ifile))
+
+(defun spam-group-spam-processor-spamoracle-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-spamoracle))
+
+(defun spam-group-ham-processor-bogofilter-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-bogofilter))
+
+(defun spam-group-spam-processor-stat-p (group)
+  (spam-group-processor-p group 'gnus-group-spam-exit-processor-stat))
+
+(defun spam-group-ham-processor-stat-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-stat))
+
+(defun spam-group-ham-processor-whitelist-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-whitelist))
+
+(defun spam-group-ham-processor-BBDB-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-BBDB))
+
+(defun spam-group-ham-processor-copy-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-copy))
+
+(defun spam-group-ham-processor-spamoracle-p (group)
+  (spam-group-processor-p group 'gnus-group-ham-exit-processor-spamoracle))
+
+;;; Summary entry and exit processing.
+
+(defun spam-summary-prepare ()
+  (setq spam-old-ham-articles
+       (spam-list-articles gnus-newsgroup-articles 'ham))
+  (setq spam-old-spam-articles
+       (spam-list-articles gnus-newsgroup-articles 'spam))
+  (spam-mark-junk-as-spam-routine))
+
+;; The spam processors are invoked for any group, spam or ham or neither
+(defun spam-summary-prepare-exit ()
+  (unless gnus-group-is-exiting-without-update-p
+    (gnus-message 6 "Exiting summary buffer and applying spam rules")
+
+    ;; first of all, unregister any articles that are no longer ham or spam
+    ;; we have to iterate over the processors, or else we'll be too slow
+    (dolist (classification '(spam ham))
+      (let* ((old-articles (if (eq classification 'spam)
+                              spam-old-spam-articles
+                            spam-old-ham-articles))
+            (new-articles (spam-list-articles
+                           gnus-newsgroup-articles
+                           classification))
+            (changed-articles (gnus-set-difference old-articles new-articles)))
+       ;; now that we have the changed articles, we go through the processors
+       (dolist (processor-param spam-list-of-processors)
+         (let ((processor (nth 0 processor-param))
+               (processor-classification (nth 1 processor-param))
+               (check (nth 2 processor-param))
+               unregister-list)
+           (dolist (article changed-articles)
+             (let ((id (spam-fetch-field-message-id-fast article)))
+               (when (spam-log-unregistration-needed-p
+                      id 'process classification check)
+                 (push article unregister-list))))
+           ;; call spam-register-routine with specific articles to unregister,
+           ;; when there are articles to unregister and the check is enabled
+           (when (and unregister-list (symbol-value check))
+             (spam-register-routine classification check t unregister-list))))))
+
+    ;; find all the spam processors applicable to this group
+    (dolist (processor-param spam-list-of-processors)
+      (let ((processor (nth 0 processor-param))
+           (classification (nth 1 processor-param))
+           (check (nth 2 processor-param)))
+       (when (and (eq 'spam classification)
+                  (spam-group-processor-p gnus-newsgroup-name processor))
+         (spam-register-routine classification check))))
+
+    (if spam-move-spam-nonspam-groups-only
+       (when (not (spam-group-spam-contents-p gnus-newsgroup-name))
+         (spam-mark-spam-as-expired-and-move-routine
+          (gnus-parameter-spam-process-destination gnus-newsgroup-name)))
+      (gnus-message 5 "Marking spam as expired and moving it to %s"
+                   gnus-newsgroup-name)
+      (spam-mark-spam-as-expired-and-move-routine
+       (gnus-parameter-spam-process-destination gnus-newsgroup-name)))
+
+    ;; now we redo spam-mark-spam-as-expired-and-move-routine to only
+    ;; expire spam, in case the above did not expire them
+    (gnus-message 5 "Marking spam as expired without moving it")
+    (spam-mark-spam-as-expired-and-move-routine nil)
+
+    (when (or (spam-group-ham-contents-p gnus-newsgroup-name)
+             (and (spam-group-spam-contents-p gnus-newsgroup-name)
+                  spam-process-ham-in-spam-groups)
+             spam-process-ham-in-nonham-groups)
+      ;; find all the ham processors applicable to this group
+      (dolist (processor-param spam-list-of-processors)
+       (let ((processor (nth 0 processor-param))
+             (classification (nth 1 processor-param))
+             (check (nth 2 processor-param)))
+         (when (and (eq 'ham classification)
+                    (spam-group-processor-p gnus-newsgroup-name processor))
+           (spam-register-routine classification check)))))
+
+    (when (spam-group-ham-processor-copy-p gnus-newsgroup-name)
+      (gnus-message 5 "Copying ham")
+      (spam-ham-copy-routine
+       (gnus-parameter-ham-process-destination gnus-newsgroup-name)))
+
+    ;; now move all ham articles out of spam groups
+    (when (spam-group-spam-contents-p gnus-newsgroup-name)
+      (gnus-message 5 "Moving ham messages from spam group")
+      (spam-ham-move-routine
+       (gnus-parameter-ham-process-destination gnus-newsgroup-name))))
+
+  (setq spam-old-ham-articles nil)
+  (setq spam-old-spam-articles nil))
+
+(defun spam-mark-junk-as-spam-routine ()
+  ;; check the global list of group names spam-junk-mailgroups and the
+  ;; group parameters
+  (when (spam-group-spam-contents-p gnus-newsgroup-name)
+    (gnus-message 5 "Marking %s articles as spam"
+                 (if spam-mark-only-unseen-as-spam
+                     "unseen"
+                   "unread"))
+    (let ((articles (if spam-mark-only-unseen-as-spam
+                       gnus-newsgroup-unseen
+                     gnus-newsgroup-unreads)))
+      (dolist (article articles)
+       (gnus-summary-mark-article article gnus-spam-mark)))))
+
+(defun spam-mark-spam-as-expired-and-move-routine (&rest groups)
+  (if (and (car-safe groups) (listp (car-safe groups)))
+      (apply 'spam-mark-spam-as-expired-and-move-routine (car groups))
+    (gnus-summary-kill-process-mark)
+    (let ((articles gnus-newsgroup-articles)
+         (backend-supports-deletions
+          (gnus-check-backend-function
+           'request-move-article gnus-newsgroup-name))
+         article tomove deletep)
+      (dolist (article articles)
+       (when (eq (gnus-summary-article-mark article) gnus-spam-mark)
+         (gnus-summary-mark-article article gnus-expirable-mark)
+         (push article tomove)))
+
+      ;; now do the actual copies
+      (dolist (group groups)
+       (when (and tomove
+                  (stringp group))
+         (dolist (article tomove)
+           (gnus-summary-set-process-mark article))
+         (when tomove
+           (if (or (not backend-supports-deletions)
+                   (> (length groups) 1))
+               (progn
+                 (gnus-summary-copy-article nil group)
+                 (setq deletep t))
+             (gnus-summary-move-article nil group)))))
+
+      ;; now delete the articles, if there was a copy done, and the
+      ;; backend allows it
+      (when (and deletep backend-supports-deletions)
+       (dolist (article tomove)
+         (gnus-summary-set-process-mark article))
+       (when tomove
+         (let ((gnus-novice-user nil)) ; don't ask me if I'm sure
+           (gnus-summary-delete-article nil))))
+
+      (gnus-summary-yank-process-mark))))
+
+(defun spam-ham-copy-or-move-routine (copy groups)
+  (gnus-summary-kill-process-mark)
+  (let ((todo (spam-list-articles gnus-newsgroup-articles 'ham))
+       (backend-supports-deletions
+        (gnus-check-backend-function
+         'request-move-article gnus-newsgroup-name))
+       (respool-method (gnus-find-method-for-group gnus-newsgroup-name))
+       article mark todo deletep respool)
+
+    (when (member 'respool groups)
+      (setq respool t)                 ; boolean for later
+      (setq groups '("fake"))) ; when respooling, groups are dynamic so fake it
+
+    ;; now do the actual move
+    (dolist (group groups)
+      (when (and todo (stringp group))
+       (dolist (article todo)
+         (when spam-mark-ham-unread-before-move-from-spam-group
+           (gnus-summary-mark-article article gnus-unread-mark))
+         (gnus-summary-set-process-mark article))
+
+       (if respool                        ; respooling is with a "fake" group
+           (let ((spam-split-disabled
+                  (or spam-split-disabled
+                      spam-disable-spam-split-during-ham-respool)))
+             (gnus-summary-respool-article nil respool-method))
+         (if (or (not backend-supports-deletions) ; else, we are not respooling
+                 (> (length groups) 1))
+             (progn                ; if copying, copy and set deletep
+               (gnus-summary-copy-article nil group)
+               (setq deletep t))
+           (gnus-summary-move-article nil group))))) ; else move articles
+
+    ;; now delete the articles, unless a) copy is t, and there was a copy done
+    ;;                                 b) a move was done to a single group
+    ;;                                 c) backend-supports-deletions is nil
+    (unless copy
+      (when (and deletep backend-supports-deletions)
+       (dolist (article todo)
+         (gnus-summary-set-process-mark article))
+       (when todo
+         (let ((gnus-novice-user nil)) ; don't ask me if I'm sure
+           (gnus-summary-delete-article nil))))))
+
+  (gnus-summary-yank-process-mark))
+
+(defun spam-ham-copy-routine (&rest groups)
+  (if (and (car-safe groups) (listp (car-safe groups)))
+      (apply 'spam-ham-copy-routine (car groups))
+    (spam-ham-copy-or-move-routine t groups)))
+
+(defun spam-ham-move-routine (&rest groups)
+  (if (and (car-safe groups) (listp (car-safe groups)))
+      (apply 'spam-ham-move-routine (car groups))
+    (spam-ham-copy-or-move-routine nil groups)))
+
+(eval-and-compile
+  (defalias 'spam-point-at-eol (if (fboundp 'point-at-eol)
+                                  'point-at-eol
+                                'line-end-position)))
+
+(defun spam-get-article-as-string (article)
+  (let ((article-buffer (spam-get-article-as-buffer article))
+       article-string)
+    (when article-buffer
+      (save-window-excursion
+       (set-buffer article-buffer)
+       (setq article-string (buffer-string))))
+    article-string))
+
+(defun spam-get-article-as-buffer (article)
+  (let ((article-buffer))
+    (when (numberp article)
+      (save-window-excursion
+       (gnus-summary-goto-subject article)
+       (gnus-summary-show-article t)
+       (setq article-buffer (get-buffer gnus-article-buffer))))
+    article-buffer))
+
+;; disabled for now
+;; (defun spam-get-article-as-filename (article)
+;;   (let ((article-filename))
+;;     (when (numberp article)
+;;       (nnml-possibly-change-directory
+;;        (gnus-group-real-name gnus-newsgroup-name))
+;;       (setq article-filename (expand-file-name
+;;                             (int-to-string article) nnml-current-directory)))
+;;     (if (file-exists-p article-filename)
+;;     article-filename
+;;       nil)))
+
+(defun spam-fetch-field-from-fast (article)
+  "Fetch the `from' field quickly, using the internal gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (mail-header-from
+       (gnus-data-header (assoc article (gnus-data-list nil))))
+    nil))
+
+(defun spam-fetch-field-subject-fast (article)
+  "Fetch the `subject' field quickly, using the internal
+  gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (mail-header-subject
+       (gnus-data-header (assoc article (gnus-data-list nil))))
+    nil))
+
+(defun spam-fetch-field-message-id-fast (article)
+  "Fetch the `Message-ID' field quickly, using the internal
+  gnus-data-list function"
+  (if (and (numberp article)
+          (assoc article (gnus-data-list nil)))
+      (mail-header-message-id
+       (gnus-data-header (assoc article (gnus-data-list nil))))
+    nil))
+
+\f
+;;;; Spam determination.
+
+(defvar spam-list-of-checks
+  '((spam-use-blacklist         . spam-check-blacklist)
+    (spam-use-regex-headers     . spam-check-regex-headers)
+    (spam-use-regex-body        . spam-check-regex-body)
+    (spam-use-whitelist         . spam-check-whitelist)
+    (spam-use-BBDB              . spam-check-BBDB)
+    (spam-use-ifile             . spam-check-ifile)
+    (spam-use-spamoracle         . spam-check-spamoracle)
+    (spam-use-stat              . spam-check-stat)
+    (spam-use-blackholes        . spam-check-blackholes)
+    (spam-use-hashcash          . spam-check-hashcash)
+    (spam-use-bogofilter-headers . spam-check-bogofilter-headers)
+    (spam-use-bogofilter        . spam-check-bogofilter))
+  "The spam-list-of-checks list contains pairs associating a
+parameter variable with a spam checking function.  If the
+parameter variable is true, then the checking function is called,
+and its value decides what happens.  Each individual check may
+return nil, t, or a mailgroup name.  The value nil means that the
+check does not yield a decision, and so, that further checks are
+needed.  The value t means that the message is definitely not
+spam, and that further spam checks should be inhibited.
+Otherwise, a mailgroup name or the symbol 'spam (depending on
+spam-split-symbolic-return) is returned where the mail should go,
+and further checks are also inhibited.  The usual mailgroup name
+is the value of `spam-split-group', meaning that the message is
+definitely a spam.")
+
+(defvar spam-list-of-statistical-checks
+  '(spam-use-ifile
+    spam-use-regex-body
+    spam-use-stat
+    spam-use-bogofilter
+    spam-use-spamoracle)
+  "The spam-list-of-statistical-checks list contains all the mail
+splitters that need to have the full message body available.")
+
+;;;TODO: modify to invoke self with each check if invoked without specifics
+(defun spam-split (&rest specific-checks)
+  "Split this message into the `spam' group if it is spam.
+This function can be used as an entry in the variable `nnmail-split-fancy',
+for example like this: (: spam-split).  It can take checks as
+parameters.  A string as a parameter will set the
+spam-split-group to that string.
+
+See the Info node `(gnus)Fancy Mail Splitting' for more details."
+  (interactive)
+  (setq spam-split-last-successful-check nil)
+  (unless spam-split-disabled
+    (let ((spam-split-group-choice spam-split-group))
+      (dolist (check specific-checks)
+       (when (stringp check)
+         (setq spam-split-group-choice check)
+         (setq specific-checks (delq check specific-checks))))
+
+      (let ((spam-split-group spam-split-group-choice))
+       (save-excursion
+         (save-restriction
+           (dolist (check spam-list-of-statistical-checks)
+             (when (and (symbolp check) (symbol-value check))
+               (widen)
+               (gnus-message 8 "spam-split: widening the buffer (%s requires it)"
+                             (symbol-name check))
+               (return)))
+           ;;   (progn (widen) (debug (buffer-string)))
+           (let ((list-of-checks spam-list-of-checks)
+                 decision)
+             (while (and list-of-checks (not decision))
+               (let ((pair (pop list-of-checks)))
+                 (when (and (symbol-value (car pair))
+                            (or (null specific-checks)
+                                (memq (car pair) specific-checks)))
+                   (gnus-message 5 "spam-split: calling the %s function"
+                                 (symbol-name (cdr pair)))
+                   (setq decision (funcall (cdr pair)))
+                   ;; if we got a decision at all, save the current check
+                   (when decision
+                     (setq spam-split-last-successful-check (car pair)))
+
+                   (when (eq decision 'spam)
+                     (if spam-split-symbolic-return
+                         (setq decision spam-split-group)
+                       (gnus-error
+                        5
+                        (format "spam-split got %s but %s is nil"
+                                (symbol-name decision)
+                                (symbol-name spam-split-symbolic-return))))))))
+             (if (eq decision t)
+                 (if spam-split-symbolic-return-positive 'ham nil)
+               decision))))))))
+
+(defun spam-find-spam ()
+  "This function will detect spam in the current newsgroup using spam-split."
+  (interactive)
+
+  (let* ((group gnus-newsgroup-name)
+        (autodetect (gnus-parameter-spam-autodetect group))
+        (methods (gnus-parameter-spam-autodetect-methods group))
+        (first-method (nth 0 methods)))
+  (when (and autodetect
+            (not (equal first-method 'none)))
+    (mapcar
+     (lambda (article)
+       (let ((id (spam-fetch-field-message-id-fast article))
+            (subject (spam-fetch-field-subject-fast article))
+            (sender (spam-fetch-field-from-fast article)))
+        (unless (and spam-log-to-registry
+                     (spam-log-registered-p id 'incoming))
+          (let* ((spam-split-symbolic-return t)
+                 (spam-split-symbolic-return-positive t)
+                 (split-return
+                  (with-temp-buffer
+                    (gnus-request-article-this-buffer
+                     article
+                     group)
+                    (if (or (null first-method)
+                            (equal first-method 'default))
+                        (spam-split)
+                      (apply 'spam-split methods)))))
+            (if (equal split-return 'spam)
+                (gnus-summary-mark-article article gnus-spam-mark))
+
+            (when (and split-return spam-log-to-registry)
+              (when (zerop (gnus-registry-group-count id))
+                (gnus-registry-add-group
+                 id group subject sender))
+
+              (spam-log-processing-to-registry
+               id
+               'incoming
+               split-return
+               spam-split-last-successful-check
+               group))))))
+     (if spam-autodetect-recheck-messages
+        gnus-newsgroup-articles
+       gnus-newsgroup-unseen)))))
+
+(defvar spam-registration-functions
+  ;; first the ham register, second the spam register function
+  ;; third the ham unregister, fourth the spam unregister function
+  '((spam-use-blacklist  nil
+                        spam-blacklist-register-routine
+                        nil
+                        spam-blacklist-unregister-routine)
+    (spam-use-whitelist  spam-whitelist-register-routine
+                        nil
+                        spam-whitelist-unregister-routine
+                        nil)
+    (spam-use-BBDB      spam-BBDB-register-routine
+                        nil
+                        spam-BBDB-unregister-routine
+                        nil)
+    (spam-use-ifile     spam-ifile-register-ham-routine
+                        spam-ifile-register-spam-routine
+                        spam-ifile-unregister-ham-routine
+                        spam-ifile-unregister-spam-routine)
+    (spam-use-spamoracle spam-spamoracle-learn-ham
+                        spam-spamoracle-learn-spam
+                        spam-spamoracle-unlearn-ham
+                        spam-spamoracle-unlearn-spam)
+    (spam-use-stat      spam-stat-register-ham-routine
+                        spam-stat-register-spam-routine
+                        spam-stat-unregister-ham-routine
+                        spam-stat-unregister-spam-routine)
+    ;; note that spam-use-gmane is not a legitimate check
+    (spam-use-gmane      nil
+                        spam-report-gmane-register-routine
+                        ;; does Gmane support unregistration?
+                        nil
+                        nil)
+    (spam-use-bogofilter spam-bogofilter-register-ham-routine
+                        spam-bogofilter-register-spam-routine
+                        spam-bogofilter-unregister-ham-routine
+                        spam-bogofilter-unregister-spam-routine))
+  "The spam-registration-functions list contains pairs
+associating a parameter variable with the ham and spam
+registration functions, and the ham and spam unregistration
+functions")
+
+(defun spam-classification-valid-p (classification)
+  (or  (eq classification 'spam)
+       (eq classification 'ham)))
+
+(defun spam-process-type-valid-p (process-type)
+  (or  (eq process-type 'incoming)
+       (eq process-type 'process)))
+
+(defun spam-registration-check-valid-p (check)
+  (assoc check spam-registration-functions))
+
+(defun spam-unregistration-check-valid-p (check)
+  (assoc check spam-registration-functions))
+
+(defun spam-registration-function (classification check)
+  (let ((flist (cdr-safe (assoc check spam-registration-functions))))
+    (if (eq classification 'spam)
+       (nth 1 flist)
+      (nth 0 flist))))
+
+(defun spam-unregistration-function (classification check)
+  (let ((flist (cdr-safe (assoc check spam-registration-functions))))
+    (if (eq classification 'spam)
+       (nth 3 flist)
+      (nth 2 flist))))
+
+(defun spam-list-articles (articles classification)
+  (let ((mark-check (if (eq classification 'spam)
+                       'spam-group-spam-mark-p
+                     'spam-group-ham-mark-p))
+       list mark-cache-yes mark-cache-no)
+    (dolist (article articles)
+      (let ((mark (gnus-summary-article-mark article)))
+       (unless (memq mark mark-cache-no)
+         (if (memq mark mark-cache-yes)
+             (push article list)
+           ;; else, we have to actually check the mark
+           (if (funcall mark-check
+                        gnus-newsgroup-name
+                        mark)
+               (progn
+                 (push article list)
+                 (push mark mark-cache-yes))
+             (push mark mark-cache-no))))))
+    list))
+
+(defun spam-register-routine (classification
+                             check
+                             &optional unregister
+                             specific-articles)
+  (when (and (spam-classification-valid-p classification)
+            (spam-registration-check-valid-p check))
+    (let* ((register-function
+           (spam-registration-function classification check))
+          (unregister-function
+           (spam-unregistration-function classification check))
+          (run-function (if unregister
+                            unregister-function
+                          register-function))
+          (log-function (if unregister
+                            'spam-log-undo-registration
+                          'spam-log-processing-to-registry))
+          article articles)
+
+      (when run-function
+       ;; make list of articles, using specific-articles if given
+       (setq articles (or specific-articles
+                          (spam-list-articles
+                           gnus-newsgroup-articles
+                           classification)))
+       ;; process them
+       (gnus-message 5 "%s %d %s articles with classification %s, check %s"
+                     (if unregister "Unregistering" "Registering")
+                     (length articles)
+                     (if specific-articles "specific" "")
+                     (symbol-name classification)
+                     (symbol-name check))
+       (funcall run-function articles)
+       ;; now log all the registrations (or undo them, depending on unregister)
+       (dolist (article articles)
+         (funcall log-function
+                  (spam-fetch-field-message-id-fast article)
+                  'process
+                  classification
+                  check
+                  gnus-newsgroup-name))))))
+
+;;; log a ham- or spam-processor invocation to the registry
+(defun spam-log-processing-to-registry (id type classification check group)
+  (when spam-log-to-registry
+    (if (and (stringp id)
+            (stringp group)
+            (spam-process-type-valid-p type)
+            (spam-classification-valid-p classification)
+            (spam-registration-check-valid-p check))
+       (let ((cell-list (cdr-safe (gnus-registry-fetch-extra id type)))
+             (cell (list classification check group)))
+         (push cell cell-list)
+         (gnus-registry-store-extra-entry
+          id
+          type
+          cell-list))
+
+      (gnus-message 5 (format "%s called with bad ID, type, classification, check, or group"
+                             "spam-log-processing-to-registry")))))
+
+;;; check if a ham- or spam-processor registration has been done
+(defun spam-log-registered-p (id type)
+  (when spam-log-to-registry
+    (if (and (stringp id)
+            (spam-process-type-valid-p type))
+       (cdr-safe (gnus-registry-fetch-extra id type))
+      (progn
+       (gnus-message 5 (format "%s called with bad ID, type, classification, or check"
+                               "spam-log-registered-p"))
+       nil))))
+
+;;; check if a ham- or spam-processor registration needs to be undone
+(defun spam-log-unregistration-needed-p (id type classification check)
+  (when spam-log-to-registry
+    (if (and (stringp id)
+            (spam-process-type-valid-p type)
+            (spam-classification-valid-p classification)
+            (spam-registration-check-valid-p check))
+       (let ((cell-list (cdr-safe (gnus-registry-fetch-extra id type)))
+             found)
+         (dolist (cell cell-list)
+           (unless found
+             (when (and (eq classification (nth 0 cell))
+                        (eq check (nth 1 cell)))
+               (setq found t))))
+         found)
+      (progn
+       (gnus-message 5 (format "%s called with bad ID, type, classification, or check"
+                               "spam-log-unregistration-needed-p"))
+       nil))))
+
+
+;;; undo a ham- or spam-processor registration (the group is not used)
+(defun spam-log-undo-registration (id type classification check &optional group)
+  (when (and spam-log-to-registry
+            (spam-log-unregistration-needed-p id type classification check))
+    (if (and (stringp id)
+            (spam-process-type-valid-p type)
+            (spam-classification-valid-p classification)
+            (spam-registration-check-valid-p check))
+       (let ((cell-list (cdr-safe (gnus-registry-fetch-extra id type)))
+             new-cell-list found)
+         (dolist (cell cell-list)
+           (unless (and (eq classification (nth 0 cell))
+                        (eq check (nth 1 cell)))
+             (push cell new-cell-list)))
+         (gnus-registry-store-extra-entry
+          id
+          type
+          new-cell-list))
+      (progn
+       (gnus-message 5 (format "%s called with bad ID, type, check, or group"
+                               "spam-log-undo-registration"))
+       nil))))
+
+;;; set up IMAP widening if it's necessary
+(defun spam-setup-widening ()
+  (dolist (check spam-list-of-statistical-checks)
+    (when (symbol-value check)
+      (setq nnimap-split-download-body-default t))))
+
+\f
+;;;; Regex body
+
+(defun spam-check-regex-body ()
+  (let ((spam-regex-headers-ham spam-regex-body-ham)
+       (spam-regex-headers-spam spam-regex-body-spam))
+    (spam-check-regex-headers t)))
+
+\f
+;;;; Regex headers
+
+(defun spam-check-regex-headers (&optional body)
+  (let ((type (if body "body" "header"))
+       (spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group))
+       ret found)
+    (dolist (h-regex spam-regex-headers-ham)
+      (unless found
+       (goto-char (point-min))
+       (when (re-search-forward h-regex nil t)
+         (message "Ham regex %s search positive." type)
+         (setq found t))))
+    (dolist (s-regex spam-regex-headers-spam)
+      (unless found
+       (goto-char (point-min))
+       (when (re-search-forward s-regex nil t)
+         (message "Spam regex %s search positive." type)
+         (setq found t)
+         (setq ret spam-split-group))))
+    ret))
+
+\f
+;;;; Blackholes.
+
+(defun spam-reverse-ip-string (ip)
+  (when (stringp ip)
+    (mapconcat 'identity
+              (nreverse (split-string ip "\\."))
+              ".")))
+
+(defun spam-check-blackholes ()
+  "Check the Received headers for blackholed relays."
+  (let ((headers (nnmail-fetch-field "received"))
+       (spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group))
+       ips matches)
+    (when headers
+      (with-temp-buffer
+       (insert headers)
+       (goto-char (point-min))
+       (gnus-message 5 "Checking headers for relay addresses")
+       (while (re-search-forward
+               "\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)" nil t)
+         (gnus-message 9 "Blackhole search found host IP %s." (match-string 1))
+         (push (spam-reverse-ip-string (match-string 1))
+               ips)))
+      (dolist (server spam-blackhole-servers)
+       (dolist (ip ips)
+         (unless (and spam-blackhole-good-server-regex
+                      ;; match the good-server-regex against the reversed (again) IP string
+                      (string-match
+                       spam-blackhole-good-server-regex
+                       (spam-reverse-ip-string ip)))
+           (unless matches
+             (let ((query-string (concat ip "." server)))
+               (if spam-use-dig
+                   (let ((query-result (query-dig query-string)))
+                     (when query-result
+                       (gnus-message 5 "(DIG): positive blackhole check '%s'"
+                                     query-result)
+                       (push (list ip server query-result)
+                             matches)))
+                 ;; else, if not using dig.el
+                 (when (query-dns query-string)
+                   (gnus-message 5 "positive blackhole check")
+                   (push (list ip server (query-dns query-string 'TXT))
+                         matches)))))))))
+    (when matches
+      spam-split-group)))
+\f
+;;;; Hashcash.
+
+(condition-case nil
+    (progn
+      (require 'hashcash)
+
+      (defun spam-check-hashcash ()
+       "Check the headers for hashcash payments."
+       (mail-check-payment)))   ;mail-check-payment returns a boolean
+
+  (file-error (progn
+               (defalias 'mail-check-payment 'ignore)
+               (defalias 'spam-check-hashcash 'ignore))))
+\f
+;;;; BBDB
+
+;;; original idea for spam-check-BBDB from Alexander Kotelnikov
+;;; <sacha@giotto.sj.ru>
+
+;; all this is done inside a condition-case to trap errors
+
+(condition-case nil
+    (progn
+      (require 'bbdb)
+      (require 'bbdb-com)
+
+      (defun spam-enter-ham-BBDB (addresses &optional remove)
+       "Enter an address into the BBDB; implies ham (non-spam) sender"
+       (dolist (from addresses)
+         (when (stringp from)
+           (let* ((parsed-address (gnus-extract-address-components from))
+                  (name (or (nth 0 parsed-address) "Ham Sender"))
+                  (remove-function (if remove
+                                       'bbdb-delete-record-internal
+                                     'ignore))
+                  (net-address (nth 1 parsed-address))
+                  (record (and net-address
+                               (bbdb-search-simple nil net-address))))
+             (when net-address
+               (gnus-message 5 "%s address %s %s BBDB"
+                             (if remove "Deleting" "Adding")
+                             from
+                             (if remove "from" "to"))
+               (if record
+                   (funcall remove-function record)
+                 (bbdb-create-internal name nil net-address nil nil
+                                       "ham sender added by spam.el")))))))
+
+      (defun spam-BBDB-register-routine (articles &optional unregister)
+       (let (addresses)
+         (dolist (article articles)
+           (when (stringp (spam-fetch-field-from-fast article))
+             (push (spam-fetch-field-from-fast article) addresses)))
+         ;; now do the register/unregister action
+         (spam-enter-ham-BBDB addresses unregister)))
+
+      (defun spam-BBDB-unregister-routine (articles)
+       (spam-BBDB-register-routine articles t))
+
+      (defun spam-check-BBDB ()
+       "Mail from people in the BBDB is classified as ham or non-spam"
+       (let ((who (nnmail-fetch-field "from"))
+             (spam-split-group (if spam-split-symbolic-return
+                                   'spam
+                                 spam-split-group)))
+         (when who
+           (setq who (nth 1 (gnus-extract-address-components who)))
+           (if (bbdb-search-simple nil who)
+               t
+             (if spam-use-BBDB-exclusive
+                 spam-split-group
+               nil))))))
+
+  (file-error (progn
+               (defalias 'bbdb-search-simple 'ignore)
+               (defalias 'spam-check-BBDB 'ignore)
+               (defalias 'spam-BBDB-register-routine 'ignore)
+               (defalias 'spam-enter-ham-BBDB 'ignore)
+               (defalias 'bbdb-create-internal 'ignore)
+               (defalias 'bbdb-delete-record-internal 'ignore)
+               (defalias 'bbdb-records 'ignore))))
+
+\f
+;;;; ifile
+
+;;; check the ifile backend; return nil if the mail was NOT classified
+;;; as spam
+
+(defun spam-get-ifile-database-parameter ()
+  "Get the command-line parameter for ifile's database from
+  spam-ifile-database-path."
+  (if spam-ifile-database-path
+      (format "--db-file=%s" spam-ifile-database-path)
+    nil))
+
+(defun spam-check-ifile ()
+  "Check the ifile backend for the classification of this message."
+  (let ((article-buffer-name (buffer-name))
+       (spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group))
+       category return)
+    (with-temp-buffer
+      (let ((temp-buffer-name (buffer-name))
+           (db-param (spam-get-ifile-database-parameter)))
+       (save-excursion
+         (set-buffer article-buffer-name)
+         (apply 'call-process-region
+                (point-min) (point-max) spam-ifile-path
+                nil temp-buffer-name nil "-c"
+                (if db-param `(,db-param "-q") `("-q"))))
+       ;; check the return now (we're back in the temp buffer)
+       (goto-char (point-min))
+       (if (not (eobp))
+           (setq category (buffer-substring (point) (spam-point-at-eol))))
+       (when (not (zerop (length category))) ; we need a category here
+         (if spam-ifile-all-categories
+             (setq return category)
+           ;; else, if spam-ifile-all-categories is not set...
+           (when (string-equal spam-ifile-spam-category category)
+             (setq return spam-split-group)))))) ; note return is nil otherwise
+    return))
+
+(defun spam-ifile-register-with-ifile (articles category &optional unregister)
+  "Register an article, given as a string, with a category.
+Uses `gnus-newsgroup-name' if category is nil (for ham registration)."
+  (let ((category (or category gnus-newsgroup-name))
+       (add-or-delete-option (if unregister "-d" "-i"))
+       (db (spam-get-ifile-database-parameter))
+       parameters)
+    (with-temp-buffer
+      (dolist (article articles)
+       (let ((article-string (spam-get-article-as-string article)))
+         (when (stringp article-string)
+           (insert article-string))))
+      (apply 'call-process-region
+            (point-min) (point-max) spam-ifile-path
+            nil nil nil
+            add-or-delete-option category
+            (if db `(,db "-h") `("-h"))))))
+
+(defun spam-ifile-register-spam-routine (articles &optional unregister)
+  (spam-ifile-register-with-ifile articles spam-ifile-spam-category unregister))
+
+(defun spam-ifile-unregister-spam-routine (articles)
+  (spam-ifile-register-spam-routine articles t))
+
+(defun spam-ifile-register-ham-routine (articles &optional unregister)
+  (spam-ifile-register-with-ifile articles spam-ifile-ham-category unregister))
+
+(defun spam-ifile-unregister-ham-routine (articles)
+  (spam-ifile-register-ham-routine articles t))
+
+\f
+;;;; spam-stat
+
+(condition-case nil
+    (progn
+      (let ((spam-stat-install-hooks nil))
+       (require 'spam-stat))
+
+      (defun spam-check-stat ()
+       "Check the spam-stat backend for the classification of this message"
+       (let ((spam-split-group (if spam-split-symbolic-return
+                                   'spam
+                                 spam-split-group))
+             (spam-stat-split-fancy-spam-group spam-split-group) ; override
+             (spam-stat-buffer (buffer-name)) ; stat the current buffer
+             category return)
+         (spam-stat-split-fancy)))
+
+      (defun spam-stat-register-spam-routine (articles &optional unregister)
+       (dolist (article articles)
+         (let ((article-string (spam-get-article-as-string article)))
+           (with-temp-buffer
+             (insert article-string)
+             (if unregister
+                 (spam-stat-buffer-change-to-non-spam)
+             (spam-stat-buffer-is-spam))))))
+
+      (defun spam-stat-unregister-spam-routine (articles)
+       (spam-stat-register-spam-routine articles t))
+
+      (defun spam-stat-register-ham-routine (articles &optional unregister)
+       (dolist (article articles)
+         (let ((article-string (spam-get-article-as-string article)))
+           (with-temp-buffer
+             (insert article-string)
+             (if unregister
+                 (spam-stat-buffer-change-to-spam)
+             (spam-stat-buffer-is-non-spam))))))
+
+      (defun spam-stat-unregister-ham-routine (articles)
+       (spam-stat-register-ham-routine articles t))
+
+      (defun spam-maybe-spam-stat-load ()
+       (when spam-use-stat (spam-stat-load)))
+
+      (defun spam-maybe-spam-stat-save ()
+       (when spam-use-stat (spam-stat-save))))
+
+  (file-error (progn
+               (defalias 'spam-stat-load 'ignore)
+               (defalias 'spam-stat-save 'ignore)
+               (defalias 'spam-maybe-spam-stat-load 'ignore)
+               (defalias 'spam-maybe-spam-stat-save 'ignore)
+               (defalias 'spam-stat-register-ham-routine 'ignore)
+               (defalias 'spam-stat-unregister-ham-routine 'ignore)
+               (defalias 'spam-stat-register-spam-routine 'ignore)
+               (defalias 'spam-stat-unregister-spam-routine 'ignore)
+               (defalias 'spam-stat-buffer-is-spam 'ignore)
+               (defalias 'spam-stat-buffer-change-to-spam 'ignore)
+               (defalias 'spam-stat-buffer-is-non-spam 'ignore)
+               (defalias 'spam-stat-buffer-change-to-non-spam 'ignore)
+               (defalias 'spam-stat-split-fancy 'ignore)
+               (defalias 'spam-check-stat 'ignore))))
+
+\f
+
+;;;; Blacklists and whitelists.
+
+(defvar spam-whitelist-cache nil)
+(defvar spam-blacklist-cache nil)
+
+(defun spam-kill-whole-line ()
+  (beginning-of-line)
+  (let ((kill-whole-line t))
+    (kill-line)))
+
+;;; address can be a list, too
+(defun spam-enter-whitelist (address &optional remove)
+  "Enter ADDRESS (list or single) into the whitelist.
+With a non-nil REMOVE, remove them."
+  (interactive "sAddress: ")
+  (spam-enter-list address spam-whitelist remove)
+  (setq spam-whitelist-cache nil))
+
+;;; address can be a list, too
+(defun spam-enter-blacklist (address &optional remove)
+  "Enter ADDRESS (list or single) into the blacklist.
+With a non-nil REMOVE, remove them."
+  (interactive "sAddress: ")
+  (spam-enter-list address spam-blacklist remove)
+  (setq spam-blacklist-cache nil))
+
+(defun spam-enter-list (addresses file &optional remove)
+  "Enter ADDRESSES into the given FILE.
+Either the whitelist or the blacklist files can be used.  With
+REMOVE not nil, remove the ADDRESSES."
+  (if (stringp addresses)
+      (spam-enter-list (list addresses) file remove)
+    ;; else, we have a list of addresses here
+    (unless (file-exists-p (file-name-directory file))
+      (make-directory (file-name-directory file) t))
+    (save-excursion
+      (set-buffer
+       (find-file-noselect file))
+      (dolist (a addresses)
+       (when (stringp a)
+         (goto-char (point-min))
+         (if (re-search-forward (regexp-quote a) nil t)
+             ;; found the address
+             (when remove
+               (spam-kill-whole-line))
+           ;; else, the address was not found
+           (unless remove
+             (goto-char (point-max))
+             (unless (bobp)
+               (insert "\n"))
+             (insert a "\n")))))
+      (save-buffer))))
+
+;;; returns t if the sender is in the whitelist, nil or
+;;; spam-split-group otherwise
+(defun spam-check-whitelist ()
+  ;; FIXME!  Should it detect when file timestamps change?
+  (let ((spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group)))
+    (unless spam-whitelist-cache
+      (setq spam-whitelist-cache (spam-parse-list spam-whitelist)))
+    (if (spam-from-listed-p spam-whitelist-cache)
+       t
+      (if spam-use-whitelist-exclusive
+         spam-split-group
+       nil))))
+
+(defun spam-check-blacklist ()
+  ;; FIXME!  Should it detect when file timestamps change?
+  (let ((spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group)))
+    (unless spam-blacklist-cache
+      (setq spam-blacklist-cache (spam-parse-list spam-blacklist)))
+    (and (spam-from-listed-p spam-blacklist-cache) spam-split-group)))
+
+(defun spam-parse-list (file)
+  (when (file-readable-p file)
+    (let (contents address)
+      (with-temp-buffer
+       (insert-file-contents file)
+       (while (not (eobp))
+         (setq address (buffer-substring (point) (spam-point-at-eol)))
+         (forward-line 1)
+         ;; insert the e-mail address if detected, otherwise the raw data
+         (unless (zerop (length address))
+           (let ((pure-address (nth 1 (gnus-extract-address-components address))))
+             (push (or pure-address address) contents)))))
+      (nreverse contents))))
+
+(defun spam-from-listed-p (cache)
+  (let ((from (nnmail-fetch-field "from"))
+       found)
+    (while cache
+      (let ((address (pop cache)))
+       (unless (zerop (length address)) ; 0 for a nil address too
+         (setq address (regexp-quote address))
+         ;; fix regexp-quote's treatment of user-intended regexes
+         (while (string-match "\\\\\\*" address)
+           (setq address (replace-match ".*" t t address))))
+       (when (and address (string-match address from))
+         (setq found t
+               cache nil))))
+    found))
+
+(defun spam-filelist-register-routine (articles blacklist &optional unregister)
+  (let ((de-symbol (if blacklist 'spam-use-whitelist 'spam-use-blacklist))
+       (declassification (if blacklist 'ham 'spam))
+       (enter-function
+        (if blacklist 'spam-enter-blacklist 'spam-enter-whitelist))
+       (remove-function
+        (if blacklist 'spam-enter-whitelist 'spam-enter-blacklist))
+       from addresses unregister-list)
+    (dolist (article articles)
+      (let ((from (spam-fetch-field-from-fast article))
+           (id (spam-fetch-field-message-id-fast article))
+           sender-ignored)
+       (when (stringp from)
+         (dolist (ignore-regex spam-blacklist-ignored-regexes)
+           (when (and (not sender-ignored)
+                      (stringp ignore-regex)
+                      (string-match ignore-regex from))
+             (setq sender-ignored t)))
+         ;; remember the messages we need to unregister, unless remove is set
+         (when (and
+                (null unregister)
+                (spam-log-unregistration-needed-p
+                 id 'process declassification de-symbol))
+           (push from unregister-list))
+         (unless sender-ignored
+           (push from addresses)))))
+
+    (if unregister
+       (funcall enter-function addresses t) ; unregister all these addresses
+      ;; else, register normally and unregister what we need to
+      (funcall remove-function unregister-list t)
+      (dolist (article unregister-list)
+       (spam-log-undo-registration
+        (spam-fetch-field-message-id-fast article)
+        'process
+        declassification
+        de-symbol))
+      (funcall enter-function addresses nil))))
+
+(defun spam-blacklist-unregister-routine (articles)
+  (spam-blacklist-register-routine articles t))
+
+(defun spam-blacklist-register-routine (articles &optional unregister)
+  (spam-filelist-register-routine articles t unregister))
+
+(defun spam-whitelist-unregister-routine (articles)
+  (spam-whitelist-register-routine articles t))
+
+(defun spam-whitelist-register-routine (articles &optional unregister)
+  (spam-filelist-register-routine articles nil unregister))
+
+\f
+;;;; Spam-report glue
+(defun spam-report-gmane-register-routine (articles)
+  (when articles
+    (apply 'spam-report-gmane articles)))
+
+\f
+;;;; Bogofilter
+(defun spam-check-bogofilter-headers (&optional score)
+  (let ((header (nnmail-fetch-field spam-bogofilter-header))
+       (spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group)))
+    (when header                       ; return nil when no header
+      (if score                                ; scoring mode
+         (if (string-match "spamicity=\\([0-9.]+\\)" header)
+             (match-string 1 header)
+           "0")
+       ;; spam detection mode
+       (when (string-match spam-bogofilter-bogosity-positive-spam-header
+                           header)
+         spam-split-group)))))
+
+;; return something sensible if the score can't be determined
+(defun spam-bogofilter-score ()
+  "Get the Bogofilter spamicity score"
+  (interactive)
+  (save-window-excursion
+    (gnus-summary-show-article t)
+    (set-buffer gnus-article-buffer)
+    (let ((score (or (spam-check-bogofilter-headers t)
+                    (spam-check-bogofilter t))))
+      (message "Spamicity score %s" score)
+      (or score "0"))
+    (gnus-summary-show-article)))
+
+(defun spam-check-bogofilter (&optional score)
+  "Check the Bogofilter backend for the classification of this message"
+  (let ((article-buffer-name (buffer-name))
+       (db spam-bogofilter-database-directory)
+       return)
+    (with-temp-buffer
+      (let ((temp-buffer-name (buffer-name)))
+       (save-excursion
+         (set-buffer article-buffer-name)
+         (apply 'call-process-region
+                (point-min) (point-max)
+                spam-bogofilter-path
+                nil temp-buffer-name nil
+                (if db `("-d" ,db "-v") `("-v"))))
+       (setq return (spam-check-bogofilter-headers score))))
+    return))
+
+(defun spam-bogofilter-register-with-bogofilter (articles
+                                                spam
+                                                &optional unregister)
+  "Register an article, given as a string, as spam or non-spam."
+  (dolist (article articles)
+    (let ((article-string (spam-get-article-as-string article))
+         (db spam-bogofilter-database-directory)
+         (switch (if unregister
+                     (if spam
+                         spam-bogofilter-spam-strong-switch
+                       spam-bogofilter-ham-strong-switch)
+                   (if spam
+                       spam-bogofilter-spam-switch
+                     spam-bogofilter-ham-switch))))
+      (when (stringp article-string)
+       (with-temp-buffer
+         (insert article-string)
+
+         (apply 'call-process-region
+                (point-min) (point-max)
+                spam-bogofilter-path
+                nil nil nil switch
+                (if db `("-d" ,db "-v") `("-v"))))))))
+
+(defun spam-bogofilter-register-spam-routine (articles &optional unregister)
+  (spam-bogofilter-register-with-bogofilter articles t unregister))
+
+(defun spam-bogofilter-unregister-spam-routine (articles)
+  (spam-bogofilter-register-spam-routine articles t))
+
+(defun spam-bogofilter-register-ham-routine (articles &optional unregister)
+  (spam-bogofilter-register-with-bogofilter articles nil unregister))
+
+(defun spam-bogofilter-unregister-ham-routine (articles)
+  (spam-bogofilter-register-ham-routine articles t))
+
+
+\f
+;;;; spamoracle
+(defun spam-check-spamoracle ()
+  "Run spamoracle on an article to determine whether it's spam."
+  (let ((article-buffer-name (buffer-name))
+       (spam-split-group (if spam-split-symbolic-return
+                             'spam
+                           spam-split-group)))
+    (with-temp-buffer
+      (let ((temp-buffer-name (buffer-name)))
+       (save-excursion
+         (set-buffer article-buffer-name)
+         (let ((status
+                (apply 'call-process-region
+                       (point-min) (point-max)
+                       spam-spamoracle-binary
+                       nil temp-buffer-name nil
+                       (if spam-spamoracle-database
+                           `("-f" ,spam-spamoracle-database "mark")
+                         '("mark")))))
+           (if (eq 0 status)
+               (progn
+                 (set-buffer temp-buffer-name)
+                 (goto-char (point-min))
+                 (when (re-search-forward "^X-Spam: yes;" nil t)
+                   spam-split-group))
+             (error "Error running spamoracle" status))))))))
+
+(defun spam-spamoracle-learn (articles article-is-spam-p &optional unregister)
+  "Run spamoracle in training mode."
+  (with-temp-buffer
+    (let ((temp-buffer-name (buffer-name)))
+      (save-excursion
+       (goto-char (point-min))
+       (dolist (article articles)
+         (insert (spam-get-article-as-string article)))
+       (let* ((arg (if (spam-xor unregister article-is-spam-p)
+                       "-spam"
+                     "-good"))
+              (status
+               (apply 'call-process-region
+                      (point-min) (point-max)
+                      spam-spamoracle-binary
+                      nil temp-buffer-name nil
+                      (if spam-spamoracle-database
+                          `("-f" ,spam-spamoracle-database
+                            "add" ,arg)
+                        `("add" ,arg)))))
+         (when (not (eq 0 status))
+           (error "Error running spamoracle" status)))))))
+
+(defun spam-spamoracle-learn-ham (articles &optional unregister)
+  (spam-spamoracle-learn articles nil unregister))
+
+(defun spam-spamoracle-unlearn-ham (articles &optional unregister)
+  (spam-spamoracle-learn-ham articles t))
+
+(defun spam-spamoracle-learn-spam (articles &optional unregister)
+  (spam-spamoracle-learn articles t unregister))
+
+(defun spam-spamoracle-unlearn-spam (articles &optional unregister)
+  (spam-spamoracle-learn-spam articles t))
+
+\f
+;;;; Hooks
+
+;;;###autoload
+(defun spam-initialize ()
+  "Install the spam.el hooks and do other initialization"
+  (interactive)
+  (setq spam-install-hooks t)
+  ;; TODO: How do we redo this every time spam-face is customized?
+  (push '((eq mark gnus-spam-mark) . spam-face)
+       gnus-summary-highlight)
+  ;; Add hooks for loading and saving the spam stats
+  (add-hook 'gnus-save-newsrc-hook 'spam-maybe-spam-stat-save)
+  (add-hook 'gnus-get-top-new-news-hook 'spam-maybe-spam-stat-load)
+  (add-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load)
+  (add-hook 'gnus-summary-prepare-exit-hook 'spam-summary-prepare-exit)
+  (add-hook 'gnus-summary-prepare-hook 'spam-summary-prepare)
+  (add-hook 'gnus-get-new-news-hook 'spam-setup-widening)
+  (add-hook 'gnus-summary-prepare-hook 'spam-find-spam))
+
+(defun spam-unload-hook ()
+  "Uninstall the spam.el hooks"
+  (interactive)
+  (remove-hook 'gnus-save-newsrc-hook 'spam-maybe-spam-stat-save)
+  (remove-hook 'gnus-get-top-new-news-hook 'spam-maybe-spam-stat-load)
+  (remove-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load)
+  (remove-hook 'gnus-summary-prepare-exit-hook 'spam-summary-prepare-exit)
+  (remove-hook 'gnus-summary-prepare-hook 'spam-summary-prepare)
+  (remove-hook 'gnus-get-new-news-hook 'spam-setup-widening)
+  (remove-hook 'gnus-summary-prepare-hook 'spam-find-spam))
+
+(when spam-install-hooks
+  (spam-initialize))
+
+(provide 'spam)
+
+;;; spam.el ends here.
+
+(provide 'spam)
+
+;;; spam.el ends here
diff --git a/lisp/starttls.el b/lisp/starttls.el
new file mode 100644 (file)
index 0000000..85bb10d
--- /dev/null
@@ -0,0 +1,84 @@
+;;; starttls.el --- STARTTLS functions
+
+;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;; Created: 1999/11/20
+;; Keywords: TLS, SSL, OpenSSL, mail, news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This module defines some utility functions for STARTTLS profiles.
+
+;; Get "starttls" from ftp://ftp.opaopa.org/pub/elisp/.
+
+;; [RFC 2595] "Using TLS with IMAP, POP3 and ACAP"
+;;     by Chris Newman <chris.newman@innosoft.com> (1999/06)
+
+;;; Code:
+
+(defgroup starttls nil
+  "Support for `Transport Layer Security' protocol."
+  :version "21.1"
+  :group 'mail)
+
+(defcustom starttls-program "starttls"
+  "The program to run in a subprocess to open an TLSv1 connection."
+  :type 'string
+  :group 'starttls)
+
+(defcustom starttls-extra-args nil
+  "Extra arguments to `starttls-program'."
+  :type '(repeat string)
+  :group 'starttls)
+
+(defun starttls-negotiate (process)
+  (signal-process (process-id process) 'SIGALRM))
+
+(defun starttls-open-stream (name buffer host service)
+  "Open a TLS connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or `buffer-name') to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+  (let* ((process-connection-type nil)
+        (process (apply #'start-process
+                        name buffer starttls-program
+                        host (format "%s" service)
+                        starttls-extra-args)))
+    (process-kill-without-query process)
+    process))
+
+(defun starttls-open-ssl-stream (name buffer host service)
+  (let* ((starttls-extra-args
+         (cons "--force" starttls-extra-args)))
+    (starttls-open-stream name buffer host service)))
+
+(provide 'starttls)
+
+;;; starttls.el ends here
diff --git a/lisp/time-date.el b/lisp/time-date.el
new file mode 100644 (file)
index 0000000..7414ede
--- /dev/null
@@ -0,0 +1,196 @@
+;;; time-date.el --- Date and time handling functions
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
+;;     Masanobu Umeda <umerin@mse.kyutech.ac.jp>
+;; Keywords: mail news util
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'parse-time)
+
+(autoload 'timezone-make-date-arpa-standard "timezone")
+
+;;;###autoload
+(defun date-to-time (date)
+  "Parse a string that represents a date-time and return a time value."
+  (condition-case ()
+      (apply 'encode-time
+            (parse-time-string
+             ;; `parse-time-string' isn't sufficiently general or
+             ;; robust.  It fails to grok some of the formats that
+             ;; timezone does (e.g. dodgy post-2000 stuff from some
+             ;; Elms) and either fails or returns bogus values.  Lars
+             ;; reverted this change, but that loses non-trivially
+             ;; often for me.  -- fx
+             (timezone-make-date-arpa-standard date)))
+    (error (error "Invalid date: %s" date))))
+
+(defun time-to-seconds (time)
+  "Convert time value TIME to a floating point number.
+You can use `float-time' instead."
+  (+ (* (car time) 65536.0)
+     (cadr time)
+     (/ (or (nth 2 time) 0) 1000000.0)))
+
+;;;###autoload
+(defun seconds-to-time (seconds)
+  "Convert SECONDS (a floating point number) to a time value."
+  (list (floor seconds 65536)
+       (floor (mod seconds 65536))
+       (floor (* (- seconds (ffloor seconds)) 1000000))))
+
+;;;###autoload
+(defun time-less-p (t1 t2)
+  "Say whether time value T1 is less than time value T2."
+  (or (< (car t1) (car t2))
+      (and (= (car t1) (car t2))
+          (< (nth 1 t1) (nth 1 t2)))))
+
+;;;###autoload
+(defun days-to-time (days)
+  "Convert DAYS into a time value."
+  (let* ((seconds (* 1.0 days 60 60 24))
+        (rest (expt 2 16))
+        (ms (condition-case nil (floor (/ seconds rest))
+              (range-error (expt 2 16)))))
+    (list ms (condition-case nil (round (- seconds (* ms rest)))
+              (range-error (expt 2 16))))))
+
+;;;###autoload
+(defun time-since (time)
+  "Return the time elapsed since TIME.
+TIME should be either a time value or a date-time string."
+  (when (stringp time)
+    ;; Convert date strings to internal time.
+    (setq time (date-to-time time)))
+  (let* ((current (current-time))
+        (rest (when (< (nth 1 current) (nth 1 time))
+                (expt 2 16))))
+    (list (- (+ (car current) (if rest -1 0)) (car time))
+         (- (+ (or rest 0) (nth 1 current)) (nth 1 time)))))
+
+;;;###autoload
+(defalias 'subtract-time 'time-subtract)
+
+;;;###autoload
+(defun time-subtract (t1 t2)
+  "Subtract two time values.
+Return the difference in the format of a time value."
+  (let ((borrow (< (cadr t1) (cadr t2))))
+    (list (- (car t1) (car t2) (if borrow 1 0))
+         (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
+
+;;;###autoload
+(defun time-add (t1 t2)
+  "Add two time values.  One should represent a time difference."
+  (let ((high (car t1))
+       (low (if (consp (cdr t1)) (nth 1 t1) (cdr t1)))
+       (micro (if (numberp (car-safe (cdr-safe (cdr t1))))
+                  (nth 2 t1)
+                0))
+       (high2 (car t2))
+       (low2 (if (consp (cdr t2)) (nth 1 t2) (cdr t2)))
+       (micro2 (if (numberp (car-safe (cdr-safe (cdr t2))))
+                   (nth 2 t2)
+                 0)))
+    ;; Add
+    (setq micro (+ micro micro2))
+    (setq low (+ low low2))
+    (setq high (+ high high2))
+
+    ;; Normalize
+    ;; `/' rounds towards zero while `mod' returns a positive number,
+    ;; so we can't rely on (= a (+ (* 100 (/ a 100)) (mod a 100))).
+    (setq low (+ low (/ micro 1000000) (if (< micro 0) -1 0)))
+    (setq micro (mod micro 1000000))
+    (setq high (+ high (/ low 65536) (if (< low 0) -1 0)))
+    (setq low (logand low 65535))
+
+    (list high low micro)))
+
+;;;###autoload
+(defun date-to-day (date)
+  "Return the number of days between year 1 and DATE.
+DATE should be a date-time string."
+  (time-to-days (date-to-time date)))
+
+;;;###autoload
+(defun days-between (date1 date2)
+  "Return the number of days between DATE1 and DATE2.
+DATE1 and DATE2 should be date-time strings."
+  (- (date-to-day date1) (date-to-day date2)))
+
+;;;###autoload
+(defun date-leap-year-p (year)
+  "Return t if YEAR is a leap year."
+  (or (and (zerop (% year 4))
+          (not (zerop (% year 100))))
+      (zerop (% year 400))))
+
+;;;###autoload
+(defun time-to-day-in-year (time)
+  "Return the day number within the year of the date month/day/year."
+  (let* ((tim (decode-time time))
+        (month (nth 4 tim))
+        (day (nth 3 tim))
+        (year (nth 5 tim))
+        (day-of-year (+ day (* 31 (1- month)))))
+    (when (> month 2)
+      (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
+      (when (date-leap-year-p year)
+       (setq day-of-year (1+ day-of-year))))
+    day-of-year))
+
+;;;###autoload
+(defun time-to-days (time)
+  "The number of days between the Gregorian date 0001-12-31bce and TIME.
+TIME should be a time value.
+The Gregorian date Sunday, December 31, 1bce is imaginary."
+  (let* ((tim (decode-time time))
+        (month (nth 4 tim))
+        (day (nth 3 tim))
+        (year (nth 5 tim)))
+    (+ (time-to-day-in-year time)      ;       Days this year
+       (* 365 (1- year))               ;       + Days in prior years
+       (/ (1- year) 4)                 ;       + Julian leap years
+       (- (/ (1- year) 100))           ;       - century years
+       (/ (1- year) 400))))            ;       + Gregorian leap years
+
+(defun time-to-number-of-days (time)
+  "Return the number of days represented by TIME.
+The number of days will be returned as a floating point number."
+  (/ (+ (* 1.0 65536 (car time)) (cadr time)) (* 60 60 24)))
+
+;;;###autoload
+(defun safe-date-to-time (date)
+  "Parse a string that represents a date-time and return a time value.
+If DATE is malformed, return a time value of zeros."
+  (condition-case ()
+      (date-to-time date)
+    (error '(0 0))))
+
+(provide 'time-date)
+
+;;; time-date.el ends here
diff --git a/lisp/tls.el b/lisp/tls.el
new file mode 100644 (file)
index 0000000..9c5466f
--- /dev/null
@@ -0,0 +1,130 @@
+;;; tls.el --- TLS/SSL support via wrapper around GnuTLS
+
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <simon@josefsson.org>
+;; Keywords: comm, tls, gnutls, ssl
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This package implements a simple wrapper around "gnutls-cli" to
+;; make Emacs support TLS/SSL.
+;;
+;; Usage is the same as `open-network-stream', i.e.:
+;;
+;; (setq tmp (open-tls-stream "test" (current-buffer) "news.mozilla.org" 563))
+;; ...
+;; #<process test>
+;; (process-send-string tmp "mode reader\n")
+;; 200 secnews.netscape.com Netscape-Collabra/3.52 03615 NNRP ready ...
+;; nil
+;; (process-send-string tmp "quit\n")
+;; 205
+;; nil
+
+;; To use this package as a replacement for ssl.el by William M. Perry
+;; <wmperry@cs.indiana.edu>, you need to evaluate the following:
+;;
+;; (defalias 'open-ssl-stream 'open-tls-stream)
+
+;;; Code:
+
+(require 'pces)
+
+(eval-and-compile
+  (autoload 'format-spec "format-spec")
+  (autoload 'format-spec-make "format-spec"))
+
+(defgroup tls nil
+  "Transport Layer Security (TLS) parameters."
+  :group 'comm)
+
+(defcustom tls-program '("gnutls-cli -p %p %h"
+                        "gnutls-cli -p %p %h --protocols ssl3")
+  "List of strings containing commands to start TLS stream to a host.
+Each entry in the list is tried until a connection is successful.
+%s is replaced with server hostname, %p with port to connect to.
+The program should read input on stdin and write output to
+stdout.  Also see `tls-success' for what the program should output
+after successful negotiation."
+  :type '(repeat string)
+  :group 'tls)
+
+(defcustom tls-process-connection-type nil
+  "*Value for `process-connection-type' to use when starting TLS process."
+  :type 'boolean
+  :group 'tls)
+
+(defcustom tls-success "- Handshake was completed"
+  "*Regular expression indicating completed TLS handshakes.
+The default is what GNUTLS's \"gnutls-cli\" outputs."
+  :type 'regexp
+  :group 'tls)
+
+(defun open-tls-stream (name buffer host service)
+  "Open a TLS connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer-name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+  (let ((cmds tls-program) cmd done)
+    (message "Opening TLS connection to `%s'..." host)
+    (while (and (not done) (setq cmd (pop cmds)))
+      (message "Opening TLS connection with `%s'..." cmd)
+      (let* ((process-connection-type tls-process-connection-type)
+            (process (as-binary-process
+                      (start-process
+                       name buffer shell-file-name shell-command-switch
+                       (format-spec
+                        cmd
+                        (format-spec-make
+                         ?h host
+                         ?p (if (integerp service)
+                                (int-to-string service)
+                              service))))))
+            response)
+       (while (and process
+                   (memq (process-status process) '(open run))
+                   (save-excursion
+                     (set-buffer buffer) ;; XXX "blue moon" nntp.el bug
+                     (goto-char (point-min))
+                     (not (setq done (re-search-forward tls-success nil t)))))
+         (accept-process-output process 1)
+         (sit-for 1))
+       (message "Opening TLS connection with `%s'...%s" cmd
+                (if done "done" "failed"))
+       (if done
+           (setq done process)
+         (delete-process process))))
+    (message "Opening TLS connection to `%s'...%s"
+            host (if done "done" "failed"))
+    done))
+
+(provide 'tls)
+
+;;; tls.el ends here
diff --git a/lisp/utf7.el b/lisp/utf7.el
new file mode 100644 (file)
index 0000000..45e472a
--- /dev/null
@@ -0,0 +1,227 @@
+;;; utf7.el --- UTF-7 encoding/decoding for Emacs   -*-coding: iso-8859-1;-*-
+;; Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
+
+;; Author: Jon K Hellan <hellan@acm.org>
+;; Maintainer: bugs@gnus.org
+;; Keywords: mail
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; UTF-7 - A Mail-Safe Transformation Format of Unicode - RFC 2152
+;; This is a transformation format of Unicode that contains only 7-bit
+;; ASCII octets and is intended to be readable by humans in the limiting
+;; case that the document consists of characters from the US-ASCII
+;; repertoire.
+;; In short, runs of characters outside US-ASCII are encoded as base64
+;; inside delimiters.
+;; A variation of UTF-7 is specified in IMAP 4rev1 (RFC 2060) as the way
+;; to represent characters outside US-ASCII in mailbox names in IMAP.
+;; This library supports both variants, but the IMAP variation was the
+;; reason I wrote it.
+;; The routines convert UTF-7 -> UTF-16 (16 bit encoding of Unicode)
+;; -> current character set, and vice versa.
+;; However, until Emacs supports Unicode, the only Emacs character set
+;; supported here is ISO-8859.1, which can trivially be converted to/from
+;; Unicode.
+;; When decoding results in a character outside the Emacs character set,
+;; an error is thrown.  It is up to the application to recover.
+
+;; UTF-7 should be done by providing a coding system.  Mule-UCS does
+;; already, but I don't know if it does the IMAP version and it's not
+;; clear whether that should really be a coding system.  The UTF-16
+;; part of the conversion can be done with coding systems available
+;; with Mule-UCS or some versions of Emacs.  Unfortunately these were
+;; done wrongly (regarding handling of byte-order marks and how the
+;; variants were named), so we don't have a consistent name for the
+;; necessary coding system.  The code below doesn't seem to DTRT
+;; generally.  E.g.:
+;;
+;; (utf7-encode "a+£")
+;;   => "a+ACsAow-"
+;;
+;; $ echo "a+£"|iconv -f iso-8859-1 -t utf-7
+;; a+-+AKM
+;;
+;;  -- fx 
+
+
+;;; Code:
+
+(require 'base64)
+(eval-when-compile (require 'cl))
+(require 'mm-util)
+
+(defconst utf7-direct-encoding-chars " -%'-*,-[]-}"
+  "Character ranges which do not need escaping in UTF-7.")
+
+(defconst utf7-imap-direct-encoding-chars
+  (concat utf7-direct-encoding-chars "+\\~")
+  "Character ranges which do not need escaping in the IMAP variant of UTF-7.")
+
+(defconst utf7-utf-16-coding-system
+  (cond ((mm-coding-system-p 'utf-16-be-no-signature) ; Mule-UCS
+        'utf-16-be-no-signature)
+       ((and (mm-coding-system-p 'utf-16-be) ; Emacs 21.4 (?), Emacs 22
+             ;; Avoid versions with BOM.
+             (= 2 (length (encode-coding-string "a" 'utf-16-be))))
+        'utf-16-be)
+       ((mm-coding-system-p 'utf-16-be-nosig) ; ?
+        'utf-16-be-nosig))
+  "Coding system which encodes big endian UTF-16 without a BOM signature.")
+
+(defsubst utf7-imap-get-pad-length (len modulus)
+  "Return required length of padding for IMAP modified base64 fragment."
+  (mod (- len) modulus))
+
+(defun utf7-encode-internal (&optional for-imap)
+  "Encode text in (temporary) buffer as UTF-7.
+Use IMAP modification if FOR-IMAP is non-nil."
+  (let ((start (point-min))
+       (end (point-max)))
+    (narrow-to-region start end)
+    (goto-char start)
+    (let* ((esc-char (if for-imap ?& ?+))
+          (direct-encoding-chars
+           (if for-imap utf7-imap-direct-encoding-chars
+             utf7-direct-encoding-chars))
+          (not-direct-encoding-chars (concat "^" direct-encoding-chars)))
+      (while (not (eobp))
+       (skip-chars-forward direct-encoding-chars)
+       (unless (eobp)
+         (insert esc-char)
+         (let ((p (point))
+               (fc (following-char))
+               (run-length
+                (skip-chars-forward not-direct-encoding-chars)))
+           (if (and (= fc esc-char)
+                    (= run-length 1))  ; Lone esc-char?
+               (delete-backward-char 1) ; Now there's one too many
+             (utf7-fragment-encode p (point) for-imap))
+           (insert "-")))))))
+
+(defun utf7-fragment-encode (start end &optional for-imap)
+  "Encode text from START to END in buffer as UTF-7 escape fragment.
+Use IMAP modification if FOR-IMAP is non-nil."
+  (save-restriction
+    (narrow-to-region start end)
+    (funcall (utf7-get-u16char-converter 'to-utf-16))
+    (mm-with-unibyte-current-buffer
+      (base64-encode-region start (point-max)))
+    (goto-char start)
+    (let ((pm (point-max)))
+      (when for-imap
+       (while (search-forward "/" nil t)
+         (replace-match ",")))
+      (skip-chars-forward "^= \t\n" pm)
+      (delete-region (point) pm))))
+
+(defun utf7-decode-internal (&optional for-imap)
+  "Decode UTF-7 text in (temporary) buffer.
+Use IMAP modification if FOR-IMAP is non-nil."
+  (let ((start (point-min))
+       (end (point-max)))
+    (goto-char start)
+    (let* ((esc-pattern (concat "^" (char-to-string (if for-imap ?& ?+))))
+          (base64-chars (concat "A-Za-z0-9+"
+                                (char-to-string (if for-imap ?, ?/)))))
+      (while (not (eobp))
+       (skip-chars-forward esc-pattern)
+       (unless (eobp)
+         (forward-char)
+         (let ((p (point))
+               (run-length (skip-chars-forward base64-chars)))
+           (when (and (not (eobp)) (= (following-char) ?-))
+             (delete-char 1))
+           (unless (= run-length 0)    ; Encoded lone esc-char?
+             (save-excursion
+               (utf7-fragment-decode p (point) for-imap)
+               (goto-char p)
+               (delete-backward-char 1)))))))))
+
+(defun utf7-fragment-decode (start end &optional for-imap)
+  "Decode base64 encoded fragment from START to END of UTF-7 text in buffer.
+Use IMAP modification if FOR-IMAP is non-nil."
+  (save-restriction
+    (narrow-to-region start end)
+    (when for-imap
+      (goto-char start)
+      (while (search-forward "," nil 'move-to-end) (replace-match "/")))
+    (let ((pl (utf7-imap-get-pad-length (- end start) 4)))
+      (insert (make-string pl ?=))
+      (base64-decode-region start (+ end pl)))
+    (funcall (utf7-get-u16char-converter 'from-utf-16))))
+
+(defun utf7-get-u16char-converter (which-way)
+  "Return a function to convert between UTF-16 and current character set."
+  (if utf7-utf-16-coding-system
+      (if (eq which-way 'to-utf-16)
+         (lambda ()
+           (encode-coding-region (point-min) (point-max)
+                                 utf7-utf-16-coding-system))
+       (lambda ()
+         (decode-coding-region (point-min) (point-max)
+                               utf7-utf-16-coding-system)))
+    ;; Add test to check if we are really Latin-1.
+    (if (eq which-way 'to-utf-16)
+       'utf7-latin1-u16-char-converter
+      'utf7-u16-latin1-char-converter)))
+
+(defun utf7-latin1-u16-char-converter ()
+  "Convert latin 1 (ISO-8859.1) characters to 16 bit Unicode.
+Characters are converted to raw byte pairs in narrowed buffer."
+  (mm-encode-coding-region (point-min) (point-max) 'iso-8859-1)
+  (mm-disable-multibyte)
+  (goto-char (point-min))
+  (while (not (eobp))
+    (insert 0)
+    (forward-char)))
+
+(defun utf7-u16-latin1-char-converter ()
+  "Convert 16 bit Unicode characters to latin 1 (ISO-8859.1).
+Characters are in raw byte pairs in narrowed buffer."
+  (goto-char (point-min))
+  (while (not (eobp))
+    (if (= 0 (following-char))
+       (delete-char 1)
+      (error "Unable to convert from Unicode"))
+    (forward-char))
+  (mm-decode-coding-region (point-min) (point-max) 'iso-8859-1)
+  (mm-enable-multibyte))
+
+(defun utf7-encode (string &optional for-imap)
+  "Encode UTF-7 STRING.  Use IMAP modification if FOR-IMAP is non-nil."
+  (let ((default-enable-multibyte-characters t))
+    (with-temp-buffer
+      (insert string)
+      (utf7-encode-internal for-imap)
+      (buffer-string))))
+
+(defun utf7-decode (string &optional for-imap)
+  "Decode UTF-7 STRING.  Use IMAP modification if FOR-IMAP is non-nil."
+  (let ((default-enable-multibyte-characters nil))
+    (with-temp-buffer
+      (insert string)
+      (utf7-decode-internal for-imap)
+      (mm-enable-multibyte)
+      (buffer-string))))
+
+(provide 'utf7)
+
+;;; utf7.el ends here
diff --git a/lisp/uudecode.el b/lisp/uudecode.el
new file mode 100644 (file)
index 0000000..ffb2eee
--- /dev/null
@@ -0,0 +1,215 @@
+;;; uudecode.el -- elisp native uudecode
+
+;; Copyright (c) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: uudecode news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'path-util)
+
+(eval-and-compile
+  (defalias 'uudecode-char-int
+    (if (fboundp 'char-int)
+       'char-int
+      'identity)))
+
+(defcustom uudecode-decoder-program "uudecode"
+  "*Non-nil value should be a string that names a uu decoder.
+The program should expect to read uu data on its standard
+input and write the converted data to its standard output."
+  :type 'string
+  :group 'gnus-extract)
+
+(defcustom uudecode-decoder-switches nil
+  "*List of command line flags passed to `uudecode-decoder-program'."
+  :group 'gnus-extract
+  :type '(repeat string))
+
+(defcustom uudecode-use-external
+  (exec-installed-p uudecode-decoder-program)
+  "*Use external uudecode program."
+  :group 'gnus-extract
+  :type 'boolean)
+
+(defconst uudecode-alphabet "\040-\140")
+
+(defconst uudecode-begin-line "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
+(defconst uudecode-end-line "^end[ \t]*$")
+
+(defconst uudecode-body-line
+  (let ((i 61) (str "^M"))
+    (while (> (setq i (1- i)) 0)
+      (setq str (concat str "[^a-z]")))
+    (concat str ".?$")))
+
+(defvar uudecode-temporary-file-directory
+  (cond ((fboundp 'temp-directory) (temp-directory))
+       ((boundp 'temporary-file-directory) temporary-file-directory)
+       ("/tmp")))
+
+;;;###autoload
+(defun uudecode-decode-region-external (start end &optional file-name)
+  "Uudecode region between START and END using external program.
+If FILE-NAME is non-nil, save the result to FILE-NAME.  The program
+used is specified by `uudecode-decoder-program'."
+  (interactive "r\nP")
+  (let ((cbuf (current-buffer)) tempfile firstline status)
+    (save-excursion
+      (goto-char start)
+      (when (re-search-forward uudecode-begin-line nil t)
+       (forward-line 1)
+       (setq firstline (point))
+       (cond ((null file-name))
+             ((stringp file-name))
+             (t
+              (setq file-name (read-file-name "File to Name:"
+                                              nil nil nil
+                                              (match-string 1)))))
+       (setq tempfile (if file-name
+                          (expand-file-name file-name)
+                        (if (fboundp 'make-temp-file)
+                            (let ((temporary-file-directory
+                                   uudecode-temporary-file-directory))
+                              (make-temp-file "uu"))
+                          (expand-file-name
+                           (make-temp-name "uu")
+                           uudecode-temporary-file-directory))))
+       (let ((cdir default-directory)
+             default-process-coding-system)
+         (unwind-protect
+             (with-temp-buffer
+               (insert "begin 600 " (file-name-nondirectory tempfile) "\n")
+               (insert-buffer-substring cbuf firstline end)
+               (cd (file-name-directory tempfile))
+               (apply 'call-process-region
+                      (point-min)
+                      (point-max)
+                      uudecode-decoder-program
+                      nil
+                      nil
+                      nil
+                      uudecode-decoder-switches))
+           (cd cdir) (set-buffer cbuf)))
+       (if (file-exists-p tempfile)
+           (unless file-name
+             (goto-char start)
+             (delete-region start end)
+             (let (format-alist)
+               (insert-file-contents-literally tempfile)))
+         (message "Can not uudecode")))
+      (ignore-errors (or file-name (delete-file tempfile))))))
+
+;;;###autoload
+(defun uudecode-decode-region-internal (start end &optional file-name)
+  "Uudecode region between START and END without using an external program.
+If FILE-NAME is non-nil, save the result to FILE-NAME."
+  (interactive "r\nP")
+  (let ((done nil)
+       (counter 0)
+       (remain 0)
+       (bits 0)
+       (lim 0) inputpos result
+       (non-data-chars (concat "^" uudecode-alphabet)))
+    (save-excursion
+      (goto-char start)
+      (when (re-search-forward uudecode-begin-line nil t)
+       (cond ((null file-name))
+             ((stringp file-name))
+             (t
+              (setq file-name (expand-file-name
+                               (read-file-name "File to Name:"
+                                               nil nil nil
+                                               (match-string 1))))))
+       (forward-line 1)
+       (skip-chars-forward non-data-chars end)
+       (while (not done)
+         (setq inputpos (point))
+         (setq remain 0 bits 0 counter 0)
+         (cond
+          ((> (skip-chars-forward uudecode-alphabet end) 0)
+           (setq lim (point))
+           (setq remain
+                 (logand (- (uudecode-char-int (char-after inputpos)) 32)
+                         63))
+           (setq inputpos (1+ inputpos))
+           (if (= remain 0) (setq done t))
+           (while (and (< inputpos lim) (> remain 0))
+             (setq bits (+ bits
+                           (logand
+                            (-
+                             (uudecode-char-int (char-after inputpos)) 32)
+                            63)))
+             (if (/= counter 0) (setq remain (1- remain)))
+             (setq counter (1+ counter)
+                   inputpos (1+ inputpos))
+             (cond ((= counter 4)
+                    (setq result (cons
+                                  (concat
+                                   (char-to-string (lsh bits -16))
+                                   (char-to-string (logand (lsh bits -8) 255))
+                                   (char-to-string (logand bits 255)))
+                                  result))
+                    (setq bits 0 counter 0))
+                   (t (setq bits (lsh bits 6)))))))
+         (cond
+          (done)
+          ((> 0 remain)
+           (error "uucode line ends unexpectly")
+           (setq done t))
+          ((and (= (point) end) (not done))
+           ;;(error "uucode ends unexpectly")
+           (setq done t))
+          ((= counter 3)
+           (setq result (cons
+                         (concat
+                          (char-to-string (logand (lsh bits -16) 255))
+                          (char-to-string (logand (lsh bits -8) 255)))
+                         result)))
+          ((= counter 2)
+           (setq result (cons
+                         (char-to-string (logand (lsh bits -10) 255))
+                         result))))
+         (skip-chars-forward non-data-chars end))
+       (if file-name
+           (let (default-enable-multibyte-characters)
+             (with-temp-file file-name
+               (insert (apply 'concat (nreverse result)))))
+         (or (markerp end) (setq end (set-marker (make-marker) end)))
+         (goto-char start)
+         (insert (apply 'concat (nreverse result)))
+         (delete-region (point) end))))))
+
+;;;###autoload
+(defun uudecode-decode-region (start end &optional file-name)
+  "Uudecode region between START and END.
+If FILE-NAME is non-nil, save the result to FILE-NAME."
+  (if uudecode-use-external
+      (uudecode-decode-region-external start end file-name)
+    (uudecode-decode-region-internal start end file-name)))
+
+(provide 'uudecode)
+
+;;; uudecode.el ends here
diff --git a/lisp/webmail.el b/lisp/webmail.el
new file mode 100644 (file)
index 0000000..ab82462
--- /dev/null
@@ -0,0 +1,1152 @@
+;;; webmail.el --- interface of web mail
+;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: hotmail netaddress my-deja netscape
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Note: Now mail.yahoo.com provides POP3 service, the webmail
+;; fetching is not going to be supported.
+
+;; Note: You need to have `url' and `w3' installed for this backend to
+;; work. `w3' must be 4.0pre46+one-line-cookie patch or standalone
+;; `url'.
+
+;; Todo: To support more web mail servers.
+
+;; Known bugs:
+;; 1. Net@ddress may corrupt `X-Face'.
+
+;; Warning:
+;; Webmail is an experimental function, which means NO WARRANTY.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'nnoo)
+(require 'message)
+(require 'gnus-util)
+(require 'gnus)
+(require 'nnmail)
+(require 'mm-util)
+(require 'mm-url)
+(require 'mml)
+(eval-when-compile
+  (ignore-errors
+    (require 'url)
+    (require 'url-cookie)))
+;; Report failure to find w3 at load time if appropriate.
+(eval '(progn
+        (require 'url)
+        (require 'url-cookie)))
+
+;;;
+
+(defvar webmail-type-definition
+  '((hotmail
+     ;; Hotmail hate other HTTP user agents and use one line cookie
+     (paranoid agent cookie post)
+     (address . "www.hotmail.com")
+     (open-url "http://www.hotmail.com/")
+     (open-snarf . webmail-hotmail-open)
+     ;; W3 hate redirect POST
+     (login-url
+      "http://%s/cgi-bin/dologin?login=%s&passwd=%s&enter=Sign+in&sec=no&curmbox=ACTIVE&_lang=&js=yes&id=2&tw=-10000&beta="
+      webmail-aux user password)
+     ;;(login-snarf . webmail-hotmail-login)
+     ;;(list-url "%s" webmail-aux)
+     (list-snarf . webmail-hotmail-list)
+     (article-snarf . webmail-hotmail-article)
+     (trash-url
+      "%s&login=%s&f=33792&curmbox=ACTIVE&_lang=&foo=inbox&js=&page=&%s=on&_HMaction=MoveTo&tobox=trAsH&nullbox="
+      webmail-aux user id))
+    (yahoo
+     (paranoid agent cookie post)
+     (address . "mail.yahoo.com")
+     (open-url "http://mail.yahoo.com/")
+     (open-snarf . webmail-yahoo-open)
+     (login-url;; yahoo will not accept GET
+      content
+      ("%s" webmail-aux)
+      ".tries=&.src=ym&.last=&promo=&.intl=&.bypass=&.partner=&.chkP=Y&.done=&login=%s&passwd=%s"
+      user password)
+     (login-snarf . webmail-yahoo-login)
+     (list-url "%s&rb=Inbox&YN=1" webmail-aux)
+     (list-snarf . webmail-yahoo-list)
+     (article-snarf . webmail-yahoo-article)
+     (trash-url
+      "%s/ym/ShowFolder?YY=52107&inc=50&order=down&sort=date&pos=0&box=Inbox&DEL=Delete&destBox=&Mid=%s&destBox2="
+      webmail-aux id))
+    (netaddress
+     (paranoid cookie post)
+     (address . "www.netaddress.com")
+     (open-url "http://www.netaddress.com/")
+     (open-snarf . webmail-netaddress-open)
+     (login-url
+      content
+      ("%s" webmail-aux)
+      "LoginState=2&SuccessfulLogin=%%2Ftpl&NewServerName=www.netaddress.com&JavaScript=JavaScript1.2&DomainID=4&Domain=usa.net&NA31site=classic.netaddress.com&NA31port=80&UserID=%s&passwd=%s"
+      user password)
+     (login-snarf . webmail-netaddress-login)
+     (list-url
+      "http://www.netaddress.com/tpl/Mail/%s/List?FolderID=-4&SortUseCase=True"
+      webmail-session)
+     (list-snarf . webmail-netaddress-list)
+     (article-url "http://www.netaddress.com/")
+     (article-snarf . webmail-netaddress-article)
+     (trash-url
+      "http://www.netaddress.com/tpl/Message/%s/Move?FolderID=-4&Q=%s&N=&Sort=Date&F=-1"
+      webmail-session id))
+    (netscape
+     (paranoid cookie post agent)
+     (address . "webmail.netscape.com")
+     (open-url "http://ureg.netscape.com/iiop/UReg2/login/login?U2_LA=en&U2_BACK_FROM_CJ=true&U2_CS=iso-8859-1&U2_ENDURL=http://webmail.netscape.com/tpl/Subscribe/Step1&U2_NEW_ENDURL=http://webmail.netscape.com/tpl/Subscribe/Step1&U2_EXITURL=http://home.netscape.com/&U2_SOURCE=Webmail")
+     (open-snarf . webmail-netscape-open)
+     (login-url
+      content
+      ("http://ureg.netscape.com/iiop/UReg2/login/loginform")
+      "U2_USERNAME=%s&U2_PASSWORD=%s%s"
+      user password webmail-aux)
+     (login-snarf . webmail-netaddress-login)
+     (list-url
+      "http://webmail.netscape.com/tpl/Mail/%s/List?FolderID=-4&SortUseCase=True"
+      webmail-session)
+     (list-snarf . webmail-netaddress-list)
+     (article-url "http://webmail.netscape.com/")
+     (article-snarf . webmail-netscape-article)
+     (trash-url
+      "http://webmail.netscape.com/tpl/Message/%s/Move?FolderID=-4&Q=%s&N=&Sort=Date&F=-1"
+      webmail-session id))
+    (my-deja
+     (paranoid cookie post)
+     (address . "www.my-deja.com")
+     ;;(open-snarf . webmail-my-deja-open)
+     (login-url
+      content
+      ("http://mydeja.google.com/cgi-bin/deja/maillogin.py")
+      "userid=%s&password=%s"
+      user password)
+     (list-snarf . webmail-my-deja-list)
+     (article-snarf . webmail-my-deja-article)
+     (trash-url webmail-aux id))))
+
+(defvar webmail-variables
+  '(address article-snarf article-url list-snarf list-url
+           login-url login-snarf open-url open-snarf site articles
+           post-process paranoid trash-url))
+
+(defconst webmail-version "webmail 1.0")
+
+(defvar webmail-newmail-only nil
+  "Only fetch new mails.")
+
+(defvar webmail-move-to-trash-can t
+  "Move mail to trash can after fetch it.")
+
+;;; Internal variables
+
+(defvar webmail-address nil)
+(defvar webmail-paranoid nil)
+(defvar webmail-aux nil)
+(defvar webmail-session nil)
+(defvar webmail-article-snarf nil)
+(defvar webmail-article-url nil)
+(defvar webmail-list-snarf nil)
+(defvar webmail-list-url nil)
+(defvar webmail-login-url nil)
+(defvar webmail-login-snarf nil)
+(defvar webmail-open-snarf nil)
+(defvar webmail-open-url nil)
+(defvar webmail-trash-url nil)
+(defvar webmail-articles nil)
+(defvar webmail-post-process nil)
+
+(defvar webmail-buffer nil)
+(defvar webmail-buffer-list nil)
+
+(defvar webmail-type nil)
+
+(defvar webmail-error-function nil)
+
+(defvar webmail-debug-file "~/.emacs-webmail-debug")
+
+;;; Interface functions
+
+(defun webmail-debug (str)
+  (with-temp-buffer
+    (insert "\n---------------- A bug at " str " ------------------\n")
+    (mapcar #'(lambda (sym)
+               (if (boundp sym)
+                   (pp `(setq ,sym ',(eval sym)) (current-buffer))))
+           '(webmail-type user))
+    (insert "---------------- webmail buffer ------------------\n\n")
+    (insert-buffer-substring webmail-buffer)
+    (insert "\n---------------- end of buffer ------------------\n\n")
+    (append-to-file (point-min) (point-max) webmail-debug-file)))
+
+(defun webmail-error (str)
+  (if webmail-error-function
+      (funcall webmail-error-function str))
+  (message "%s HTML has changed or your w3 package is too old.(%s)"
+          webmail-type str)
+  (error "%s HTML has changed or your w3 package is too old.(%s)"
+        webmail-type str))
+
+(defun webmail-setdefault (type)
+  (let ((type-def (cdr (assq type webmail-type-definition)))
+       (vars webmail-variables)
+       pair)
+    (setq webmail-type type)
+    (dolist (var vars)
+      (if (setq pair (assq var type-def))
+         (set (intern (concat "webmail-" (symbol-name var))) (cdr pair))
+       (set (intern (concat "webmail-" (symbol-name var))) nil)))))
+
+(defun webmail-eval (expr)
+  (cond
+   ((consp expr)
+    (cons (webmail-eval (car expr)) (webmail-eval (cdr expr))))
+   ((symbolp expr)
+    (eval expr))
+   (t
+    expr)))
+
+(defun webmail-url (xurl)
+  (mm-with-unibyte-current-buffer
+    (cond
+     ((eq (car xurl) 'content)
+      (pop xurl)
+      (mm-url-fetch-simple (if (stringp (car xurl))
+                               (car xurl)
+                             (apply 'format (webmail-eval (car xurl))))
+                           (apply 'format (webmail-eval (cdr xurl)))))
+     ((eq (car xurl) 'post)
+      (pop xurl)
+      (mm-url-fetch-form (car xurl) (webmail-eval (cdr xurl))))
+     (t
+      (mm-url-insert (apply 'format (webmail-eval xurl)))))))
+
+(defun webmail-init ()
+  "Initialize buffers and such."
+  (if (gnus-buffer-live-p webmail-buffer)
+      (set-buffer webmail-buffer)
+    (setq webmail-buffer
+         (nnheader-set-temp-buffer " *webmail*"))
+    (mm-disable-multibyte)))
+
+(defvar url-package-name)
+(defvar url-package-version)
+(defvar url-cookie-multiple-line)
+(defvar url-confirmation-func)
+
+;; Hack W3 POST redirect.  See `url-parse-mime-headers'.
+;;
+;; Netscape uses "GET" as redirect method when orignal method is POST
+;; and status is 302, .i.e no security risks by default without
+;; confirmation.
+;;
+;; Some web servers (at least Apache used by yahoo) return status 302
+;; instead of 303, though they mean 303.
+
+(defun webmail-url-confirmation-func (prompt)
+  (cond
+   ((equal prompt (concat "Honor redirection with non-GET method "
+                         "(possible security risks)? "))
+    nil)
+   ((equal prompt "Continue (with method of GET)? ")
+    t)
+   (t (error prompt))))
+
+(defun webmail-refresh-redirect ()
+  "Redirect refresh url in META."
+  (goto-char (point-min))
+  (while (re-search-forward
+         "<meta[ \t\r\n]*http-equiv=\"Refresh\"[^>]*URL=\\([^\"]+\\)\""
+         nil t)
+    (let ((url (match-string 1)))
+      (erase-buffer)
+      (mm-with-unibyte-current-buffer
+       (mm-url-insert url)))
+    (goto-char (point-min))))
+
+(defun webmail-fetch (file subtype user password)
+  (save-excursion
+    (webmail-setdefault subtype)
+    (let ((url-package-name (if (memq 'agent webmail-paranoid)
+                               "Mozilla"
+                             url-package-name))
+         (url-package-version (if (memq 'agent webmail-paranoid)
+                                  "4.0"
+                                url-package-version))
+         (url-cookie-multiple-line (if (memq 'cookie webmail-paranoid)
+                                       nil
+                                     url-cookie-multiple-line))
+         (url-confirmation-func (if (memq 'post webmail-paranoid)
+                                    'webmail-url-confirmation-func
+                                  url-confirmation-func))
+         (url-http-silence-on-insecure-redirection t)
+         url-cookie-storage url-cookie-secure-storage
+         url-cookie-confirmation
+         item id (n 0))
+      (webmail-init)
+      (setq webmail-articles nil)
+      (when webmail-open-url
+       (erase-buffer)
+       (webmail-url webmail-open-url))
+      (if webmail-open-snarf (funcall webmail-open-snarf))
+      (when webmail-login-url
+       (erase-buffer)
+       (webmail-url webmail-login-url))
+      (if webmail-login-snarf
+         (funcall webmail-login-snarf))
+      (when webmail-list-url
+       (erase-buffer)
+       (webmail-url webmail-list-url))
+      (if webmail-list-snarf
+         (funcall webmail-list-snarf))
+      (while (setq item (pop webmail-articles))
+       (message "Fetching mail #%d..." (setq n (1+ n)))
+       (erase-buffer)
+       (mm-with-unibyte-current-buffer
+         (mm-url-insert (cdr item)))
+       (setq id (car item))
+       (if webmail-article-snarf
+           (funcall webmail-article-snarf file id))
+       (when (and webmail-trash-url webmail-move-to-trash-can)
+         (message "Move mail #%d to trash can..." n)
+         (condition-case err
+             (progn
+               (webmail-url webmail-trash-url)
+               (let (buf)
+                 (while (setq buf (pop webmail-buffer-list))
+                   (kill-buffer buf))))
+           (error
+            (let (buf)
+              (while (setq buf (pop webmail-buffer-list))
+                (kill-buffer buf)))
+            (error err))))))
+    (if webmail-post-process
+       (funcall webmail-post-process))))
+
+(defun webmail-encode-8bit ()
+  (goto-char (point-min))
+  (skip-chars-forward "^\200-\377")
+  (while (not (eobp))
+    (insert (format "&%d;" (mm-char-int (char-after))))
+    (delete-char 1)
+    (skip-chars-forward "^\200-\377")))
+
+;;; hotmail
+
+(defun webmail-hotmail-open ()
+  (goto-char (point-min))
+  (if (re-search-forward
+       "action=\"https?://\\([^/]+\\)/cgi-bin/dologin" nil t)
+      (setq webmail-aux (match-string 1))
+    (webmail-error "open@1")))
+
+(defun webmail-hotmail-login ()
+  (let (site)
+    (goto-char (point-min))
+    (if (re-search-forward
+        "https?://\\([^/]+hotmail\\.msn\\.com\\)/cgi-bin/" nil t)
+       (setq site (match-string 1))
+      (webmail-error "login@1"))
+    (goto-char (point-min))
+    (if (re-search-forward
+        "\\(/cgi-bin/HoTMaiL\\?[^\"]*a=b[^\"]*\\)" nil t)
+       (setq webmail-aux (concat "http://" site (match-string 1)))
+      (webmail-error "login@2"))))
+
+(defun webmail-hotmail-list ()
+  (goto-char (point-min))
+  (skip-chars-forward " \t\n\r")
+  (let (site url newp (total "0"))
+    (if (eobp)
+       (setq total "0")
+      (if (re-search-forward "\\([0-9]+\\) *<b>(\\([0-9]+\\) new)" nil t)
+         (message "Found %s (%s new)" (setq total (match-string 1))
+                  (match-string 2))
+       (if (re-search-forward "\\([0-9]+\\) new" nil t)
+           (message "Found %s new" (setq total (match-string 1)))
+         (webmail-error "list@0"))))
+    (unless (equal total "0")
+      (goto-char (point-min))
+      (if (re-search-forward
+          "https?://\\([^/]+hotmail\\.msn\\.com\\)/cgi-bin/" nil t)
+         (setq site (match-string 1))
+       (webmail-error "list@1"))
+      (goto-char (point-min))
+      (if (re-search-forward "disk=\\([^&]*\\)&" nil t)
+         (setq webmail-aux
+               (concat "http://" site "/cgi-bin/HoTMaiL?disk="
+                       (match-string 1)))
+       (webmail-error "list@2"))
+      (goto-char (point-max))
+      (while (re-search-backward
+             "newmail\\.gif\\|href=\"\\(/cgi-bin/getmsg\\?[^\"]+\\)\""
+             nil t)
+       (if (setq url (match-string 1))
+           (progn
+             (if (or newp (not webmail-newmail-only))
+                 (let (id)
+                   (if (string-match "msg=\\([^&]+\\)" url)
+                       (setq id (match-string 1 url)))
+                   (push (cons id (concat "http://" site url "&raw=0"))
+                         webmail-articles)))
+             (setq newp nil))
+         (setq newp t))))))
+
+;; Thank victor@idaccr.org (Victor S. Miller) for raw=0
+
+(defun webmail-hotmail-article (file id)
+  (goto-char (point-min))
+  (skip-chars-forward " \t\n\r")
+  (unless (eobp)
+    (if (not (search-forward "<pre>" nil t))
+       (webmail-error "article@3"))
+    (skip-chars-forward "\n\r\t ")
+    (delete-region (point-min) (point))
+    (if (not (search-forward "</pre>" nil t))
+       (webmail-error "article@3.1"))
+    (delete-region (match-beginning 0) (point-max))
+    (mm-url-remove-markup)
+    (mm-url-decode-entities-nbsp)
+    (goto-char (point-min))
+    (while (re-search-forward "\r\n?" nil t)
+      (replace-match "\n"))
+    (goto-char (point-min))
+    (insert "\n\n")
+    (if (not (looking-at "\n*From "))
+       (insert "From nobody " (current-time-string) "\n")
+      (forward-line))
+    (insert "X-Gnus-Webmail: " (symbol-value 'user)
+           "@" (symbol-name webmail-type) "\n")
+    (mm-append-to-file (point-min) (point-max) file)))
+
+(defun webmail-hotmail-article-old (file id)
+  (let (p attachment count mime hotmail-direct)
+    (save-restriction
+      (webmail-encode-8bit)
+      (goto-char (point-min))
+      (if (not (search-forward "<DIV>" nil t))
+         (if (not (search-forward "Reply&nbsp;All" nil t))
+             (webmail-error "article@1")
+           (setq hotmail-direct t))
+       (goto-char (match-beginning 0)))
+      (narrow-to-region (point-min) (point))
+      (if (not (search-backward "<table" nil t 2))
+         (webmail-error "article@1.1"))
+      (delete-region (point-min) (match-beginning 0))
+      (while (search-forward "<a href=" nil t)
+       (setq p (match-beginning 0))
+       (search-forward "</a>" nil t)
+       (delete-region p (match-end 0)))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities-nbsp)
+      (goto-char (point-min))
+      (delete-blank-lines)
+      (goto-char (point-min))
+      (when (search-forward "\n\n" nil t)
+       (backward-char)
+       (delete-region (point) (point-max)))
+      (goto-char (point-max))
+      (widen)
+      (insert "\n")
+      (setq p (point))
+      (while (re-search-forward
+             "<tt>\\|<div>\\|\\(http://[^/]+/cgi-bin/getmsg/\\([^\?]+\\)\?[^\"]*\\)\""
+             nil t)
+       (if (setq attachment (match-string 1))
+           (let ((filename (match-string 2))
+                 bufname);; Attachment
+             (delete-region p (match-end 0))
+             (save-excursion
+               (set-buffer (generate-new-buffer " *webmail-att*"))
+               (mm-url-insert attachment)
+               (push (current-buffer) webmail-buffer-list)
+               (setq bufname (buffer-name)))
+             (setq mime t)
+             (insert "<#part type="
+                     (or (and filename
+                              (string-match "\\.[^\\.]+$" filename)
+                              (mailcap-extension-to-mime
+                               (match-string 0 filename)))
+                         "application/octet-stream"))
+             (insert " buffer=\"" bufname "\"")
+             (insert " filename=\"" filename "\"")
+             (insert " disposition=\"inline\"")
+             (insert "><#/part>\n")
+             (setq p (point)))
+         (delete-region p (match-end 0))
+         (if hotmail-direct
+             (if (not (search-forward "</tt>" nil t))
+                 (webmail-error "article@1.2")
+               (delete-region (match-beginning 0) (match-end 0)))
+           (setq count 1)
+           (while (and (> count 0)
+                       (re-search-forward "</div>\\|\\(<div>\\)" nil t))
+             (if (match-string 1)
+                 (setq count (1+ count))
+               (if (= (setq count (1- count)) 0)
+                   (delete-region (match-beginning 0)
+                                  (match-end 0))))))
+         (narrow-to-region p (point))
+         (goto-char (point-min))
+         (cond
+          ((looking-at "<pre>")
+           (goto-char (match-end 0))
+           (if (looking-at "$") (forward-char))
+           (delete-region (point-min) (point))
+           (mm-url-remove-markup)
+           (mm-url-decode-entities-nbsp)
+           nil)
+          (t
+           (setq mime t)
+           (insert "<#part type=\"text/html\" disposition=inline>")
+           (goto-char (point-max))
+           (insert "<#/part>")))
+         (goto-char (point-max))
+         (setq p (point))
+         (widen)))
+      (delete-region p (point-max))
+      (goto-char (point-min))
+      ;; Some blank line to seperate mails.
+      (insert "\n\nFrom nobody " (current-time-string) "\n")
+      (insert "X-Gnus-Webmail: " (symbol-value 'user)
+             "@" (symbol-name webmail-type) "\n")
+      (if id
+         (insert (format "X-Message-ID: <%s@hotmail.com>\n" id)))
+      (unless (looking-at "$")
+       (if (search-forward "\n\n" nil t)
+           (forward-line -1)
+         (webmail-error "article@2")))
+      (narrow-to-region (point) (point-max))
+      (if mime
+         (insert "MIME-Version: 1.0\n"
+                 (prog1
+                     (mml-generate-mime)
+                   (delete-region (point-min) (point-max)))))
+      (goto-char (point-min))
+      (widen)
+      (let (case-fold-search)
+       (while (re-search-forward "^From " nil t)
+         (beginning-of-line)
+         (insert ">"))))
+    (mm-append-to-file (point-min) (point-max) file)))
+
+;;; yahoo
+
+(defun webmail-yahoo-open ()
+  (goto-char (point-min))
+  (if (re-search-forward "action=\"\\([^\"]+\\)\"" nil t)
+      (setq webmail-aux (match-string 1))
+    (webmail-error "open@1")))
+
+(defun webmail-yahoo-login ()
+  (goto-char (point-min))
+  (if (re-search-forward "http://[^/]+[0-9]\\.mail\\.yahoo\\.com/" nil t)
+      (setq webmail-aux (match-string 0))
+    (webmail-error "login@1"))
+  (if (re-search-forward "YY=[0-9]+" nil t)
+      (setq webmail-aux (concat webmail-aux "ym/ShowFolder?"
+                               (match-string 0)))
+    (webmail-error "login@2")))
+
+(defun webmail-yahoo-list ()
+  (let (url (newp t) (tofetch 0))
+    (goto-char (point-min))
+    (when (re-search-forward
+          "showing [0-9]+-\\([0-9]+\\) of \\([0-9]+\\)" nil t)
+      ;;(setq listed (match-string 1))
+      (message "Found %s mail(s)" (match-string 2)))
+    (if (string-match "http://[^/]+" webmail-aux)
+       (setq webmail-aux (match-string 0 webmail-aux))
+      (webmail-error "list@1"))
+    (goto-char (point-min))
+    (while (re-search-forward
+           "bgcolor=\"#eeeeee\"\\|href=\"\\(/ym/ShowLetter\\?MsgId=\\([^&]+\\)&[^\"]*\\)\""
+           nil t)
+      (if (setq url (match-string 1))
+         (progn
+           (when (or newp (not webmail-newmail-only))
+             (push (cons (match-string 2) (concat webmail-aux url "&toc=1"))
+                   webmail-articles)
+             (setq tofetch (1+ tofetch)))
+           (setq newp t))
+       (setq newp nil)))
+    (setq webmail-articles (nreverse webmail-articles))
+    (message "Fetching %d mail(s)" tofetch)))
+
+(defun webmail-yahoo-article (file id)
+  (let (p attachment)
+    (save-restriction
+      (goto-char (point-min))
+      (if (not (search-forward "value=\"Done\"" nil t))
+         (webmail-error "article@1"))
+      (if (not (search-forward "<table" nil t))
+         (webmail-error "article@2"))
+      (delete-region (point-min) (match-beginning 0))
+      (if (not (search-forward "</table>" nil t))
+         (webmail-error "article@3"))
+      (narrow-to-region (point-min) (match-end 0))
+      (while (search-forward "<a href=" nil t)
+       (setq p (match-beginning 0))
+       (search-forward "</a>" nil t)
+       (delete-region p (match-end 0)))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities-nbsp)
+      (goto-char (point-min))
+      (delete-blank-lines)
+      (goto-char (point-max))
+      (widen)
+      (insert "\n")
+      (setq p (point))
+      (while (re-search-forward "[^\"]*/ShowLetter/[^\?]+\?[^\"]*" nil t)
+       (setq attachment (match-string 0))
+       (let (bufname ct ctl cd description)
+         (if (not (search-forward "<table" nil t))
+             (webmail-error "article@4"))
+         (delete-region p (match-beginning 0))
+         (if (not (search-forward "</table>" nil t))
+             (webmail-error "article@5"))
+         (narrow-to-region p (match-end 0))
+         (mm-url-remove-markup)
+         (mm-url-decode-entities-nbsp)
+         (goto-char (point-min))
+         (delete-blank-lines)
+         (setq ct (mail-fetch-field "content-type")
+               ctl (ignore-errors (mail-header-parse-content-type ct))
+               ;;cte (mail-fetch-field "content-transfer-encoding")
+               cd (mail-fetch-field "content-disposition")
+               description (mail-fetch-field "content-description")
+               id (mail-fetch-field "content-id"))
+         (delete-region (point-min) (point-max))
+         (widen)
+         (save-excursion
+           (set-buffer (generate-new-buffer " *webmail-att*"))
+           (mm-url-insert (concat webmail-aux attachment))
+           (push (current-buffer) webmail-buffer-list)
+           (setq bufname (buffer-name)))
+         (insert "<#part")
+         (if (and ctl (not (equal (car ctl) "text/")))
+             (insert " type=\"" (car ctl) "\""))
+         (insert " buffer=\"" bufname "\"")
+         (if cd
+             (insert " disposition=\"" cd "\""))
+         (if description
+             (insert " description=\"" description "\""))
+         (insert "><#/part>\n")
+         (setq p (point))))
+      (delete-region p (point-max))
+      (goto-char (point-min))
+      ;; Some blank line to seperate mails.
+      (insert "\n\nFrom nobody " (current-time-string) "\n")
+      (insert "X-Gnus-Webmail: " (symbol-value 'user)
+             "@" (symbol-name webmail-type) "\n")
+      (if id
+         (insert (format "X-Message-ID: <%s@yahoo.com>\n" id)))
+      (unless (looking-at "$")
+       (if (search-forward "\n\n" nil t)
+           (forward-line -1)
+         (webmail-error "article@2")))
+      (narrow-to-region (point) (point-max))
+      (insert "MIME-Version: 1.0\n"
+             (prog1
+                 (mml-generate-mime)
+               (delete-region (point-min) (point-max))))
+      (goto-char (point-min))
+      (widen)
+      (let (case-fold-search)
+       (while (re-search-forward "^From " nil t)
+         (beginning-of-line)
+         (insert ">"))))
+    (mm-append-to-file (point-min) (point-max) file)))
+
+;;; netaddress
+
+(defun webmail-netscape-open ()
+  (goto-char (point-min))
+  (setq webmail-aux "")
+  (while (re-search-forward
+         "TYPE=hidden *NAME=\\([^ ]+\\) *VALUE=\"\\([^\"]+\\)"
+         nil t)
+    (setq webmail-aux (concat webmail-aux "&" (match-string 1) "="
+                             (match-string 2)))))
+
+(defun webmail-netaddress-open ()
+  (goto-char (point-min))
+  (if (re-search-forward "action=\"\\([^\"]+\\)\"" nil t)
+      (setq webmail-aux (concat (car webmail-open-url) (match-string 1)))
+    (webmail-error "open@1")))
+
+(defun webmail-netaddress-login ()
+  (webmail-refresh-redirect)
+  (goto-char (point-min))
+  (if (re-search-forward  "tpl/[^/]+/\\([^/]+\\)" nil t)
+      (setq webmail-session (match-string 1))
+    (webmail-error "login@1")))
+
+(defun webmail-netaddress-list ()
+  (webmail-refresh-redirect)
+  (let (item id)
+    (goto-char (point-min))
+    (when (re-search-forward
+          "(\\([0-9]+\\) unread, \\([0-9]+\\) total)" nil t)
+      (message "Found %s mail(s), %s unread"
+              (match-string 2) (match-string 1)))
+    (goto-char (point-min))
+    (while (re-search-forward
+           "MR\\[i\\]\\.R='\\([^']*\\)'\\|MR\\[i\\]\\.Q='\\([^']+\\)'" nil t)
+      (if (setq id (match-string 2))
+         (setq item
+               (cons id
+                     (format "%s/tpl/Message/%s/Read?Q=%s&FolderID=-4&SortUseCase=True&Sort=Date&Headers=True"
+                             (car webmail-article-url)
+                             webmail-session id)))
+       (if (or (not webmail-newmail-only)
+               (equal (match-string 1) "True"))
+           (push item webmail-articles))))
+    (setq webmail-articles (nreverse webmail-articles))))
+
+(defun webmail-netaddress-single-part ()
+  (goto-char (point-min))
+  (cond
+   ((looking-at "[\t\040\r\n]*<font face=[^>]+>[\t\040\r\n]*")
+    ;; text/plain
+    (replace-match "")
+    (while (re-search-forward "[\t\040\r\n]+" nil t)
+      (replace-match " "))
+    (goto-char (point-min))
+    (while (re-search-forward "<br>" nil t)
+      (replace-match "\n"))
+    (mm-url-remove-markup)
+    (mm-url-decode-entities-nbsp)
+    nil)
+   (t
+    (insert "<#part type=\"text/html\" disposition=inline>")
+    (goto-char (point-max))
+    (insert "<#/part>")
+    t)))
+
+(defun webmail-netaddress-article (file id)
+  (webmail-refresh-redirect)
+  (let (p p1 attachment count mime type)
+    (save-restriction
+      (webmail-encode-8bit)
+      (goto-char (point-min))
+      (if (not (search-forward "Trash" nil t))
+         (webmail-error "article@1"))
+      (if (not (search-forward "<form>" nil t))
+         (webmail-error "article@2"))
+      (delete-region (point-min) (match-beginning 0))
+      (if (not (search-forward "</form>" nil t))
+         (webmail-error "article@3"))
+      (narrow-to-region (point-min) (match-end 0))
+      (goto-char (point-min))
+      (while (re-search-forward "[\040\t\r\n]+" nil t)
+       (replace-match " "))
+      (goto-char (point-min))
+      (while (search-forward "<b>" nil t)
+       (replace-match "\n"))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities-nbsp)
+      (goto-char (point-min))
+      (delete-blank-lines)
+      (goto-char (point-min))
+      (while (re-search-forward "^\040+\\|\040+$" nil t)
+       (replace-match ""))
+      (goto-char (point-min))
+      (while (re-search-forward "\040+" nil t)
+       (replace-match " "))
+      (goto-char (point-max))
+      (widen)
+      (insert "\n\n")
+      (setq p (point))
+      (unless (search-forward "<!-- Data -->" nil t)
+       (webmail-error "article@4"))
+      (forward-line 14)
+      (delete-region p (point))
+      (goto-char (point-max))
+      (unless (re-search-backward
+              "[\040\t]*<br>[\040\t\r\n]*<br>[\040\t\r\n]*<form" p t)
+       (webmail-error "article@5"))
+      (delete-region (point) (point-max))
+      (goto-char p)
+      (while (search-forward
+             "<TABLE border=\"0\" WIDTH=\"98%\" cellpadding=0 cellspacing=0>"
+             nil t 2)
+       (setq mime t)
+       (unless (search-forward "</TABLE>" nil t)
+         (webmail-error "article@6"))
+       (setq p1 (point))
+       (if (search-backward "<IMG " p t)
+           (progn
+             (unless (re-search-forward "HREF=\"\\(/tpl/Attachment/[^/]+/\\([^/]+/[^\?]+\\)[^\"]+\\)\"" p1 t)
+               (webmail-error "article@7"))
+             (setq attachment (match-string 1))
+             (setq type (match-string 2))
+             (unless (search-forward "</TABLE>" nil t)
+               (webmail-error "article@8"))
+             (delete-region p (point))
+             (let (bufname);; Attachment
+               (save-excursion
+                 (set-buffer (generate-new-buffer " *webmail-att*"))
+                 (mm-url-insert (concat (car webmail-open-url) attachment))
+                 (push (current-buffer) webmail-buffer-list)
+                 (setq bufname (buffer-name)))
+               (insert "<#part type=" type)
+               (insert " buffer=\"" bufname "\"")
+               (insert " disposition=\"inline\"")
+               (insert "><#/part>\n")
+               (setq p (point))))
+         (delete-region p p1)
+         (narrow-to-region
+          p
+          (if (search-forward
+               "<TABLE border=\"0\" WIDTH=\"98%\" cellpadding=0 cellspacing=0>"
+               nil t)
+              (match-beginning 0)
+            (point-max)))
+         (webmail-netaddress-single-part)
+         (goto-char (point-max))
+         (setq p (point))
+         (widen)))
+      (unless mime
+       (narrow-to-region p (point-max))
+       (setq mime (webmail-netaddress-single-part))
+       (widen))
+      (goto-char (point-min))
+      ;; Some blank line to seperate mails.
+      (insert "\n\nFrom nobody " (current-time-string) "\n")
+      (insert "X-Gnus-Webmail: " (symbol-value 'user)
+             "@" (symbol-name webmail-type) "\n")
+      (if id
+         (insert (format "X-Message-ID: <%s@%s>\n" id webmail-address)))
+      (unless (looking-at "$")
+       (if (search-forward "\n\n" nil t)
+           (forward-line -1)
+         (webmail-error "article@2")))
+      (when mime
+       (narrow-to-region (point-min) (point))
+       (goto-char (point-min))
+       (while (not (eobp))
+         (if (looking-at "MIME-Version\\|Content-Type")
+             (delete-region (point)
+                            (progn
+                              (forward-line 1)
+                              (if (re-search-forward "^[^ \t]" nil t)
+                                  (goto-char (match-beginning 0))
+                                (point-max))))
+           (forward-line 1)))
+       (goto-char (point-max))
+       (widen)
+       (narrow-to-region (point) (point-max))
+       (insert "MIME-Version: 1.0\n"
+               (prog1
+                   (mml-generate-mime)
+                 (delete-region (point-min) (point-max))))
+       (goto-char (point-min))
+       (widen))
+      (let (case-fold-search)
+       (while (re-search-forward "^From " nil t)
+         (beginning-of-line)
+         (insert ">"))))
+    (mm-append-to-file (point-min) (point-max) file)))
+
+(defun webmail-netscape-article (file id)
+  (let (p p1 attachment count mime type)
+    (save-restriction
+      (webmail-encode-8bit)
+      (goto-char (point-min))
+      (if (not (search-forward "Trash" nil t))
+         (webmail-error "article@1"))
+      (if (not (search-forward "<form>" nil t))
+         (webmail-error "article@2"))
+      (delete-region (point-min) (match-beginning 0))
+      (if (not (search-forward "</form>" nil t))
+         (webmail-error "article@3"))
+      (narrow-to-region (point-min) (match-end 0))
+      (goto-char (point-min))
+      (while (re-search-forward "[\040\t\r\n]+" nil t)
+       (replace-match " "))
+      (goto-char (point-min))
+      (while (re-search-forward "<a href=[^>]*>[^<]*</a>" nil t)
+       (replace-match ""))
+      (goto-char (point-min))
+      (while (search-forward "<b>" nil t)
+       (replace-match "\n"))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities-nbsp)
+      (goto-char (point-min))
+      (delete-blank-lines)
+      (goto-char (point-min))
+      (while (re-search-forward "^\040+\\|\040+$" nil t)
+       (replace-match ""))
+      (goto-char (point-min))
+      (while (re-search-forward "\040+" nil t)
+       (replace-match " "))
+      (goto-char (point-max))
+      (widen)
+      (insert "\n\n")
+      (setq p (point))
+      (unless (search-forward "<!-- Data -->" nil t)
+       (webmail-error "article@4"))
+      (forward-line 14)
+      (delete-region p (point))
+      (goto-char (point-max))
+      (unless (re-search-backward
+              "<form name=\"Transfer2\"" p t)
+       (webmail-error "article@5"))
+      (delete-region (point) (point-max))
+      (goto-char p)
+      (while (search-forward
+             "<TABLE border=\"0\" WIDTH=\"98%\" cellpadding=0 cellspacing=0>"
+             nil t 2)
+       (setq mime t)
+       (unless (search-forward "</TABLE>" nil t)
+         (webmail-error "article@6"))
+       (setq p1 (point))
+       (if (search-backward "<IMG " p t)
+           (progn
+             (unless (re-search-forward "HREF=\"\\(/tpl/Attachment/[^/]+/\\([^/]+/[^\?]+\\)[^\"]+\\)\"" p1 t)
+               (webmail-error "article@7"))
+             (setq attachment (match-string 1))
+             (setq type (match-string 2))
+             (unless (search-forward "</TABLE>" nil t)
+               (webmail-error "article@8"))
+             (delete-region p (point))
+             (let (bufname);; Attachment
+               (save-excursion
+                 (set-buffer (generate-new-buffer " *webmail-att*"))
+                 (mm-url-insert (concat (car webmail-open-url) attachment))
+                 (push (current-buffer) webmail-buffer-list)
+                 (setq bufname (buffer-name)))
+               (insert "<#part type=" type)
+               (insert " buffer=\"" bufname "\"")
+               (insert " disposition=\"inline\"")
+               (insert "><#/part>\n")
+               (setq p (point))))
+         (delete-region p p1)
+         (narrow-to-region
+          p
+          (if (search-forward
+               "<TABLE border=\"0\" WIDTH=\"98%\" cellpadding=0 cellspacing=0>"
+               nil t)
+              (match-beginning 0)
+            (point-max)))
+         (webmail-netaddress-single-part)
+         (goto-char (point-max))
+         (setq p (point))
+         (widen)))
+      (unless mime
+       (narrow-to-region p (point-max))
+       (setq mime (webmail-netaddress-single-part))
+       (widen))
+      (goto-char (point-min))
+      ;; Some blank line to seperate mails.
+      (insert "\n\nFrom nobody " (current-time-string) "\n")
+      (insert "X-Gnus-Webmail: " (symbol-value 'user)
+             "@" (symbol-name webmail-type) "\n")
+      (if id
+         (insert (format "X-Message-ID: <%s@%s>\n" id webmail-address)))
+      (unless (looking-at "$")
+       (if (search-forward "\n\n" nil t)
+           (forward-line -1)
+         (webmail-error "article@2")))
+      (when mime
+       (narrow-to-region (point-min) (point))
+       (goto-char (point-min))
+       (while (not (eobp))
+         (if (looking-at "MIME-Version\\|Content-Type")
+             (delete-region (point)
+                            (progn
+                              (forward-line 1)
+                              (if (re-search-forward "^[^ \t]" nil t)
+                                  (goto-char (match-beginning 0))
+                                (point-max))))
+           (forward-line 1)))
+       (goto-char (point-max))
+       (widen)
+       (narrow-to-region (point) (point-max))
+       (insert "MIME-Version: 1.0\n"
+               (prog1
+                   (mml-generate-mime)
+                 (delete-region (point-min) (point-max))))
+       (goto-char (point-min))
+       (widen))
+      (let (case-fold-search)
+       (while (re-search-forward "^From " nil t)
+         (beginning-of-line)
+         (insert ">"))))
+    (mm-append-to-file (point-min) (point-max) file)))
+
+;;; my-deja
+
+(defun webmail-my-deja-open ()
+  (webmail-refresh-redirect)
+  (goto-char (point-min))
+  (if (re-search-forward "action=\"\\([^\"]+maillogin\\.py[^\"]*\\)\""
+                        nil t)
+      (setq webmail-aux (match-string 1))
+    (webmail-error "open@1")))
+
+(defun webmail-my-deja-list ()
+  (let (item id newp base)
+    (goto-char (point-min))
+    (when (re-search-forward "href=\"\\(\\([^\"]*\\)/mailnf\\.[^\"]*\\)\""
+                            nil t)
+      (let ((url (match-string 1)))
+       (setq base (match-string 2))
+       (erase-buffer)
+       (mm-url-insert url)))
+    (goto-char (point-min))
+    (when (re-search-forward
+          "(\\([0-9]+\\) Message.?-[^>]*\\([0-9]+\\) New"
+          nil t)
+      (message "Found %s mail(s), %s unread"
+              (match-string 1) (match-string 2)))
+    (goto-char (point-min))
+    (while (re-search-forward
+           "newmail\\.gif\\|href=\"[^\"]*\\(mailnf\\.[^\"]+act=view[^\"]+mid=\\([^\"&]+\\)[^\"]+\\)\""
+           nil t)
+      (if (setq id (match-string 2))
+         (when (and (or newp (not webmail-newmail-only))
+                    (not (assoc id webmail-articles)))
+           (push (cons id (setq webmail-aux
+                                (concat base "/" (match-string 1))))
+                 webmail-articles)
+           (setq newp nil))
+       (setq newp t)))
+    (setq webmail-articles (nreverse webmail-articles))))
+
+(defun webmail-my-deja-article-part (base)
+  (let (p)
+    (cond
+     ((looking-at "[\t\040\r\n]*<!--[^>]*>")
+      (replace-match ""))
+     ((looking-at "[\t\040\r\n]*</PRE>")
+      (replace-match ""))
+     ((looking-at "[\t\040\r\n]*<PRE>")
+      ;; text/plain
+      (replace-match "")
+      (save-restriction
+       (narrow-to-region (point)
+                         (if (re-search-forward "</?PRE>" nil t)
+                             (match-beginning 0)
+                           (point-max)))
+       (goto-char (point-min))
+       (mm-url-remove-markup)
+       (mm-url-decode-entities-nbsp)
+       (goto-char (point-max))))
+     ((looking-at "[\t\040\r\n]*<TABLE")
+      (save-restriction
+       (narrow-to-region (point)
+                         (if (search-forward "</TABLE>" nil t 2)
+                             (point)
+                           (point-max)))
+       (goto-char (point-min))
+       (let (name type url bufname)
+         (if (and (search-forward "File Name:" nil t)
+                  (re-search-forward "<FONT[^>]+>\\([^<]+\\)" nil t))
+             (setq name (match-string 1)))
+         (if (and (search-forward "File Type:" nil t)
+                  (re-search-forward "<FONT[^>]+>\\([^<]+\\)" nil t))
+             (setq type (match-string 1)))
+         (unless (re-search-forward "action=\"getattach\\.cgi/\\([^\"]+\\)"
+                                    nil t)
+           (webmail-error "article@5"))
+         (setq url (concat base "/getattach.cgi/" (match-string 1)
+                           "?sm=Download"))
+         (while (re-search-forward
+                 "type=hidden name=\"\\([^\"]+\\)\" value=\"\\([^\"]+\\)"
+                 nil t)
+           (setq url (concat url "&" (match-string 1) "="
+                             (match-string 2))))
+         (delete-region (point-min) (point-max))
+         (save-excursion
+           (set-buffer (generate-new-buffer " *webmail-att*"))
+           (mm-url-insert url)
+           (push (current-buffer) webmail-buffer-list)
+           (setq bufname (buffer-name)))
+         (insert "<#part type=\"" type "\"")
+         (if name (insert " filename=\"" name "\""))
+         (insert " buffer=\"" bufname "\"")
+         (insert " disposition=inline><#/part>"))))
+     (t
+      (insert "<#part type=\"text/html\" disposition=inline>")
+      (goto-char (point-max))
+      (insert "<#/part>")))))
+
+(defun webmail-my-deja-article (file id)
+  (let (base)
+    (goto-char (point-min))
+    (unless (string-match "\\([^\"]+\\)/mail" webmail-aux)
+      (webmail-error "article@0"))
+    (setq base (match-string 1 webmail-aux))
+    (when (re-search-forward
+          "href=\"[^\"]*\\(mailnf\\.[^\"]+act=move[^\"]+mid=\\([^\"&]+\\)[^\"]+\\)\""
+          nil t)
+      (setq webmail-aux (concat base "/" (match-string 1)))
+      (string-match "mid=[^\"&]+" webmail-aux)
+      (setq webmail-aux (replace-match "mid=%s" nil nil webmail-aux)))
+    (unless (search-forward "<HR noshade>" nil t)
+      (webmail-error "article@1"))
+    (delete-region (point-min) (point))
+    (unless (search-forward "<HR noshade>" nil t)
+      (webmail-error "article@2"))
+    (save-restriction
+      (narrow-to-region (point-min) (point))
+      (while (search-forward "\r\n" nil t)
+       (replace-match "\n"))
+      (mm-url-remove-markup)
+      (mm-url-decode-entities-nbsp)
+      (goto-char (point-min))
+      (while (re-search-forward "\n\n+" nil t)
+       (replace-match "\n"))
+      (goto-char (point-max)))
+    (save-restriction
+      (narrow-to-region (point) (point-max))
+      (goto-char (point-max))
+      (unless (search-backward "<HR noshade>" nil t)
+       (webmail-error "article@3"))
+      (unless (search-backward "</TT>" nil t)
+       (webmail-error "article@4"))
+      (delete-region (point) (point-max))
+      (goto-char (point-min))
+      (while (not (eobp))
+       (webmail-my-deja-article-part base))
+      (insert "MIME-Version: 1.0\n"
+             (prog1
+                 (mml-generate-mime)
+               (delete-region (point-min) (point-max)))))
+    (goto-char (point-min))
+    (insert "\n\nFrom nobody " (current-time-string) "\n")
+    (insert "X-Gnus-Webmail: " (symbol-value 'user)
+           "@" (symbol-name webmail-type) "\n")
+    (if (eq (char-after) ?\n)
+       (delete-char 1))
+    (mm-append-to-file (point-min) (point-max) file)))
+
+(provide 'webmail)
+
+;;; webmail.el ends here
diff --git a/lisp/yenc.el b/lisp/yenc.el
new file mode 100644 (file)
index 0000000..3fea50f
--- /dev/null
@@ -0,0 +1,120 @@
+;;; yenc.el --- elisp native yenc decoder
+;; Copyright (c) 2002 Free Software Foundation, Inc.
+
+;; Author: Jesper Harder <harder@ifa.au.dk>
+;; Keywords: yenc news
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Functions for decoding yenc encoded messages.
+;;
+;; Limitations:
+;;
+;; * Does not handle multipart messages.
+;; * No support for external decoders.
+;; * Doesn't check the crc32 checksum (if present).
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defconst yenc-begin-line
+  "^=ybegin.*$")
+
+(defconst yenc-decoding-vector
+  [214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
+       231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
+       248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+       16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
+       39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
+       62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
+       85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
+       106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
+       123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
+       140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
+       157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
+       174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
+       191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+       208 209 210 211 212 213])
+
+;;;###autoload
+(defun yenc-decode-region (start end)
+  "Yenc decode region between START and END using an internal decoder."
+  (interactive "r")
+  (let (work-buffer)
+    (unwind-protect
+       (save-excursion
+         (goto-char start)
+         (when (re-search-forward yenc-begin-line end t)
+           (let ((first (match-end 0))
+                 (header-alist (yenc-parse-line (match-string 0)))
+                 bytes last footer-alist char)
+             (when (re-search-forward "^=ypart.*$" end t)
+               (setq first (match-end 0)))
+             (when (re-search-forward "^=yend.*$" end t)
+               (setq last (match-beginning 0))
+               (setq footer-alist (yenc-parse-line (match-string 0)))
+               (let (default-enable-multibyte-characters)
+                 (setq work-buffer (generate-new-buffer " *yenc-work*")))
+               (while (< first last)
+                 (setq char (char-after first))
+                 (cond ((or (eq char ?\r)
+                            (eq char ?\n)))
+                       ((eq char ?=)
+                        (setq char (char-after (incf first)))
+                        (with-current-buffer work-buffer
+                          (insert-char (mod (- char 106) 256) 1)))
+                       (t
+                        (with-current-buffer work-buffer
+                          ;;(insert-char (mod (- char 42) 256) 1)
+                          (insert-char (aref yenc-decoding-vector char) 1))))
+                 (incf first))
+               (setq bytes (buffer-size work-buffer))
+               (unless (and (= (cdr (assq 'size header-alist)) bytes)
+                            (= (cdr (assq 'size footer-alist)) bytes))
+                 (message "Warning: Size mismatch while decoding."))
+               (goto-char start)
+               (delete-region start end)
+               (insert-buffer-substring work-buffer))))
+         (and work-buffer (kill-buffer work-buffer))))))
+
+;;;###autoload
+(defun yenc-extract-filename ()
+  "Extract file name from an yenc header."
+  (save-excursion
+    (when (re-search-forward yenc-begin-line nil t)
+      (cdr (assoc 'name (yenc-parse-line (match-string 0)))))))
+
+(defun yenc-parse-line (str)
+  "Extract file name and size from STR."
+  (let (result name)
+    (when (string-match "^=y.*size=\\([0-9]+\\)" str)
+      (push (cons 'size (string-to-number (match-string 1 str))) result))
+    (when (string-match "^=y.*name=\\(.*\\)$" str)
+      (setq name (match-string 1 str))
+      ;; Remove trailing white space
+      (when (string-match " +$" name)
+       (setq name (substring name 0 (match-beginning 0))))
+      (push (cons 'name name) result))
+    result))
+
+(provide 'yenc)
+
+;;; yenc.el ends here
diff --git a/make.bat b/make.bat
new file mode 100755 (executable)
index 0000000..ddd22a3
--- /dev/null
+++ b/make.bat
@@ -0,0 +1,285 @@
+@echo off\r
+\r
+rem Written by Frank Schmitt <ich@frank-schmitt.net>\r
+rem based on the work by David Charlap (shamino@writeme.com)\r
+rem .\r
+rem Clear PWD so emacs doesn't get confused\r
+set GNUS_PWD_SAVE=%PWD%\r
+set PWD=\r
+set ERROR=:\r
+\r
+if "%1" == "" goto usage\r
+\r
+rem Emacs 20.7 no longer includes emacs.bat. Use emacs.exe if the batch file is\r
+rem not present -- this also fixes the problem about too many parameters on Win9x.\r
+if exist %1\emacs.bat goto ebat\r
+if exist %1\emacs.exe goto eexe\r
+if exist %1\xemacs.exe goto xemacs\r
+goto noemacs\r
+\r
+:ebat\r
+set EMACS=emacs.bat\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using emacs.bat (If you've got en Emacs >= 20.3 please remove Emacs.bat,\r
+echo * it isn't needed anymore.\r
+echo ***************************************************************************\r
+echo.\r
+goto emacs\r
+\r
+:eexe\r
+set EMACS=emacs.exe\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using emacs.exe\r
+echo ***************************************************************************\r
+echo.\r
+goto emacs\r
+\r
+:emacs\r
+if not "%2" == "/copy" goto emacsnocopy\r
+if not exist %1\..\site-lisp mkdir %1\..\site-lisp\r
+if not exist %1\..\site-lisp\gnus mkdir %1\..\site-lisp\gnus\r
+if not exist %1\..\site-lisp\subdirs.el set subdirwarning=yes\r
+:emacsnocopy\r
+set EMACS_ARGS=-batch -q -no-site-file\r
+set GNUS_INFO_DIR=%1\..\info\r
+set GNUS_LISP_DIR=%1\..\site-lisp\gnus\lisp\r
+set GNUS_ETC_DIR=%1\..\site-lisp\gnus\etc\r
+goto lisp\r
+\r
+:xemacs\r
+set EMACS=xemacs.exe\r
+if not "%2" == "/copy" goto xemacsnocopy\r
+if not exist %1\..\..\site-packages\ mkdir %1\..\..\site-packages\\r
+if not exist %1\..\..\site-packages\info mkdir %1\..\..\site-packages\info\r
+if not exist %1\..\..\site-packages\lisp mkdir %1\..\..\site-packages\lisp\r
+if not exist %1\..\..\site-packages\etc mkdir %1\..\..\site-packages\etc\r
+:xemacsnocopy\r
+set EMACS_ARGS=-batch -no-autoloads\r
+set GNUS_INFO_DIR=%1\..\..\site-packages\info\r
+set GNUS_LISP_DIR=%1\..\..\site-packages\lisp\gnus\r
+set GNUS_ETC_DIR=%1\..\..\site-packages\etc\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using xemacs.exe\r
+echo ***************************************************************************\r
+echo.\r
+goto lisp\r
+\r
+:lisp\r
+set EMACSBATCH=call %1\%EMACS% %EMACS_ARGS%\r
+cd lisp\r
+if exist gnus-load.el del gnus-load.el\r
+echo.\r
+echo Stand by while generating autoloads.\r
+echo.\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-cus-load .\r
+if ErrorLevel 1 set ERROR=make-cus-load\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-auto-load .\r
+if ErrorLevel 1 set ERROR=%ERROR%,make-auto-load\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-make-load\r
+if ErrorLevel 1 set ERROR=%ERROR%,make-load\r
+echo.\r
+echo Stand by while compiling lisp files.\r
+echo.\r
+%EMACSBATCH% -l ./dgnushack.el -f dgnushack-compile\r
+if ErrorLevel 1 set ERROR=%ERROR%,compile\r
+\r
+if not "%2" == "/copy" goto infotest\r
+echo.\r
+echo Stand by while copying lisp files.\r
+echo.\r
+if not exist %GNUS_LISP_DIR% mkdir %GNUS_LISP_DIR%\r
+xcopy /R /Q /Y *.el* %GNUS_LISP_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-lisp\r
+goto infotest\r
+\r
+:infotest\r
+cd ..\texi\r
+if exist sieve del sieve\r
+makeinfo sieve.texi\r
+if exist sieve goto minfo\r
+REM It seems that makeinfo isn't available\r
+set EMACSINFO=%EMACSBATCH% -l infohack.el -f batch-makeinfo\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using infohack.el, if you've got makeinfo.exe put it in PATH.\r
+echo ***************************************************************************\r
+echo.\r
+goto info\r
+\r
+:minfo\r
+set EMACSINFO=makeinfo\r
+echo.\r
+echo ***************************************************************************\r
+echo * Using makeinfo\r
+echo ***************************************************************************\r
+echo.\r
+goto info\r
+\r
+:info\r
+echo.\r
+echo Stand by while generating info files.\r
+echo.\r
+%EMACSINFO% emacs-mime.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,emacs-mime.texi\r
+%EMACSINFO% gnus.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,gnus.texi\r
+%EMACSINFO% sieve.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,sieve.texi\r
+%EMACSINFO% pgg.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,pgg.texi\r
+%EMACSINFO% message.texi\r
+if ErrorLevel 1 set ERROR=%ERROR%,message.texi\r
+\r
+if not "%2" == "/copy" goto nocopy\r
+if not exist %GNUS_INFO_DIR% mkdir %GNUS_INFO_DIR%\r
+\r
+echo.\r
+echo Stand by while copying info files.\r
+echo.\r
+xcopy /R /Q /Y gnus       %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-info\r
+xcopy /R /Q /Y gnus-?     %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-x-info\r
+xcopy /R /Q /Y gnus-??    %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-gnus-xx-info\r
+xcopy /R /Q /Y message    %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-message-info\r
+if exist message-1 xcopy /R /Q /Y message-?  %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-message-x-info\r
+xcopy /R /Q /Y emacs-mime %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-emacs-mime-info\r
+xcopy /R /Q /Y sieve      %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-sieve-info\r
+xcopy /R /Q /Y pgg        %GNUS_INFO_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-pgg-info\r
+\r
+echo.\r
+echo ***************************************************************************\r
+echo * You should add the following lines to\r
+echo * %GNUS_INFO_DIR%\dir\r
+echo * if they aren't already there:\r
+echo *\r
+echo * * PGG: (pgg).   Emacs interface to various PGP implementations.\r
+echo * * Sieve: (sieve).       Managing Sieve scripts in Emacs.\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:etc\r
+cd ..\etc\r
+echo.\r
+echo Stand by while copying etc files.\r
+echo.\r
+if not exist %GNUS_ETC_DIR% mkdir %GNUS_ETC_DIR%\r
+xcopy /R /Q /Y gnus-tut.txt %GNUS_ETC_DIR%\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-tut-txt\r
+if not exist %GNUS_ETC_DIR%\gnus mkdir %GNUS_ETC_DIR%\gnus\r
+xcopy /R /Q /Y .\gnus\* %GNUS_ETC_DIR%\gnus\\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-gnus-*\r
+if not exist %GNUS_ETC_DIR%\smilies mkdir %GNUS_ETC_DIR%\smilies\r
+xcopy /R /Q /Y .\smilies\* %GNUS_ETC_DIR%\smilies\\r
+if ErrorLevel 1 set ERROR=%ERROR%,copy-etc-smilies-*\r
+goto warnings\r
+\r
+:nocopy\r
+echo.\r
+echo ***************************************************************************\r
+echo * You chose not to copy the files, therefore you should add the\r
+echo * following lines to the TOP of your [X]emacs customization file:\r
+echo *\r
+echo * (add-to-list 'load-path "/Path/to/gnus/lisp")\r
+echo * (if (featurep 'xemacs)\r
+echo *     (add-to-list 'Info-directory-list "c:/Path/to/gnus/texi/")\r
+echo *   (add-to-list 'Info-default-directory-list "c:/Path/to/gnus/texi/")\r
+echo * (require 'gnus-load)\r
+echo *\r
+echo * Replace c:/Path/to/gnus with the Path where your new Gnus is (that's here\r
+echo * and yes, you've got to use forward slashes).\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:warnings\r
+if not "%subdirwarning%" == "yes" goto warngnusload\r
+echo.\r
+echo ***************************************************************************\r
+echo * There's no subdirs.el file in your site-lisp directory, you should\r
+echo * therefor add the following line to the TOP of your Emacs\r
+echo * customization file:\r
+echo *\r
+echo * (add-to-list 'load-path "/Path/to/emacs-site-lisp-directory/gnus/lisp")\r
+echo * (require 'gnus-load)\r
+echo * Yes, it must be forward slashes.\r
+echo ***************************************************************************\r
+echo.\r
+goto warnerrors\r
+\r
+:warngnusload\r
+echo.\r
+echo ***************************************************************************\r
+echo * You should add the following line to the TOP of your Emacs\r
+echo * customization file:\r
+echo *\r
+echo * (require 'gnus-load)\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:warnerrors\r
+if "%ERROR%"==":" goto noerrors\r
+set errorlevel=1\r
+echo.\r
+echo ***************************************************************************\r
+echo * WARNING ERRORS OCCURRED!\r
+echo * You should look for error messages in the output of the called programs\r
+echo * and try to find out what exactly went wrong.\r
+echo * Errors occured in the following modules:\r
+echo * %ERROR%\r
+echo ***************************************************************************\r
+echo.\r
+goto done\r
+\r
+:noerrors\r
+set errorlevel=0\r
+\r
+:done\r
+cd ..\r
+goto end\r
+\r
+:noemacs\r
+echo.\r
+echo ***************************************************************************\r
+echo * Unable to find emacs.exe or xemacs.exe on the path you specified!\r
+echo * STOP!\r
+echo ***************************************************************************\r
+echo.\r
+goto usage\r
+\r
+:usage\r
+echo.\r
+echo ***************************************************************************\r
+echo * Usage: make.bat :[X]Emacs-exe-dir: [/copy]\r
+echo *\r
+echo * where: :[X]Emacs-exe-dir: is the directory your\r
+echo *           emacs.exe respectively xemacs.exe resides in,\r
+echo *           e.g. G:\Programme\XEmacs\XEmacs-21.4.11\i586-pc-win32\\r
+echo *           or G:\Emacs\bin\r
+echo *        /copy indicates that the compiled files should be copied to your\r
+echo *           emacs lisp, info, and etc site directories.\r
+echo *\r
+echo * Note: If you have Emacs/w3 you should set the environment variable\r
+echo *       W3DIR to the directory where w3 is installed eg.\r
+echo *                set W3DIR=d:\lisp\w3-4.0pre46\lisp\r
+echo ***************************************************************************\r
+echo.\r
+\r
+:end\r
+rem Restore environment variables\r
+set PWD=%GNUS_PWD_SAVE%\r
+set GNUS_PWD_SAVE=\r
+set EMACSBATCH=\r
+set GNUS_LISP_DIR=\r
+set GNUS_INFO_DIR=\r
+set GNUS_ETC_DIR=\r
+set subdirwarning=\r
+set ERROR=\r
index 31f90a0..f945dbf 100644 (file)
@@ -4,8 +4,6 @@
 # Created: 1993-05-16
 # Public domain
 
-# $Id: mkinstalldirs,v 1.8 1997/06/25 17:03:22 meyering Exp $
-
 errstatus=0
 
 for file
diff --git a/readme b/readme
deleted file mode 100644 (file)
index a232075..0000000
--- a/readme
+++ /dev/null
@@ -1,52 +0,0 @@
-This package contains a beta version of Gnus.  The lisp directory
-contains the source lisp files, and the texi directory contains a
-draft of the Gnus info pages.
-
-To use Gnus you first have to unpack the files, which you've obviously
-done, because you are reading this.
-
-You should definitely byte-compile the source files. To do that, you
-can simply say "./configure; make" in this directory.  If you are
-using XEmacs, you *must* say "make EMACS=xemacs".  In that case you
-may also want to pull down the package of nice glyphs from
-<URL:http://www.gnus.org/~larsi/etc.tar.gz>.  It should be installed
-into the "gnus-5.4.53/etc" directory.
-
-Then you have to tell Emacs where Gnus is. You might put something
-like
-
-   (setq load-path (cons (expand-file-name "~/gnus-5.4.53/lisp") load-path))
-
-in your .emacs file, or wherever you keep such things.  
-
-To enable reading the Gnus manual, you could say something like:
-
-  (setq Info-default-directory-list 
-        (cons "~/gnus-5.4.53/texi" Info-default-directory-list))
-
-Note that Gnus and GNUS can't coexist in a single Emacs. They both use
-the same function and variable names.  If you have been running GNUS
-in your Emacs, you should probably exit that Emacs and start a new one
-to fire up Gnus.
-
-Gnus does absolutely not work with anything older than Emacs 19.33 or
-XEmacs 19.14.  So you definitely need a new Emacs.
-
-Then you do a `M-x gnus', and everything should... uhm... it should
-work, but it might not. Set `debug-on-error' to t, and mail me the
-backtraces, or, better yet, find out why Gnus does something wrong,
-fix it, and send me the diffs. :-)
-
-There are four main things I want your help and input on:
-
-1) Startup. Does everything go smoothly, and why not?
-
-2) Any errors while you read news normally?
-
-3) Any errors if you do anything abnormal?
-
-4) Features you do not like, or do like, but would like to tweak a
-   bit, and features you would like to see.
-
-Send any comments and all your bug fixes/complaints to
-`bugs@gnus.org'. 
diff --git a/sample.lpath.el b/sample.lpath.el
new file mode 100644 (file)
index 0000000..95e40cc
--- /dev/null
@@ -0,0 +1,42 @@
+;; This is a sample of `~/.lpath.el' file.
+;;
+;; This file will be loaded from dgnushack.el at the compile time.  It
+;; is supposed to be used for telling old Emacsen where EMU, APEL or
+;; CUSTOM packages have already installed.
+;;
+;; For instance, if you would like to build T-gnus with Mule 2.3 based
+;; on Emacs 19.34, copy this file to `~/.lpath.el' and edit it suitably
+;; for your environment.
+
+(if (boundp 'MULE)
+    (let ((additional-load-path
+          (list
+           ;; Where is EMU packege?
+           "/usr/local/share/mule/19.34/site-lisp/"
+           ;; Where is APEL package?
+           "/usr/local/share/mule/site-lisp/apel/"
+           ;; Where is CUSTOM package?
+           "/usr/local/share/mule/site-lisp/custom/"
+
+           ;; Note that you have no need to specify paths of FLIM and
+           ;; SEMI if they are installed under the directory which is
+           ;; same as the parent directory of APEL.
+
+           ;; If you have installed Emacs/W3 package,
+           ;; uncomment and edit the following line appropriately.
+           ;; "/usr/local/share/mule/site-lisp/w3/"
+           )))
+      ;; No user serviceable parts beyond this point.
+\f
+      (let ((i (length additional-load-path))
+           p)
+       (while (> i 0)
+         (setq i (1- i)
+               p (nth i additional-load-path))
+         (if (file-directory-p p)
+             (progn
+               (if (string-match "/apel/?$" p)
+                   (setq load-path
+                         (cons (substring p 0 (1+ (match-beginning 0)))
+                               load-path)))
+               (setq load-path (cons p load-path))))))))
index a3b0c50..8c0289a 100644 (file)
-Mon Feb 23 18:05:09 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2004-01-04  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus.texi: Direntry not handled by Emacs 19.34.
+       * gnus.texi (Spam ELisp Package Configuration Examples): Markup fixes.
 
-1998-02-21  SL Baur  <steve@altair.xemacs.org>
+2004-01-03  Teodor Zlatanov  <tzz@lifelogs.com>
 
-       * gnus.texi: Add a direntry field.
-       * message.texi: Ditto.  (Data taken from Emacs 20.2 info/dir).
+       * gnus.texi (Spam ELisp Package Sequence of Events): explain more
+       about the sequence of events and what happens with read-only
+       backends
+       (Spam ELisp Package Global Variables): explain what happens with
+       read-only backends
+       (Spam ELisp Package Configuration Examples): added Reiner Steib
+       and Ted Zlatanov's setups
 
-Sun Feb 22 03:24:43 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2004-01-03  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus.texi (Score File Format): Addition.
+       * emacs-mime.texi (Display Customization): Add mm-enable-external.
 
-1998-02-18  Jason R Mastaler  <jason@4b.org>
+2004-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi: Corrected typo.
+       * gnus.texi (Category Syntax):
+       gnus-agent-cat-enable-undownloaded-faces.
 
-Thu Feb 19 02:20:29 1998  Francois Felix Ingrand  <felix@laas.fr>
+2004-01-03  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus.texi (Sorting): Fix order of args.
+       * message.texi, gnus.texi, gnus-faq.texi: Update copyright.
 
-Sun Feb 15 23:04:02 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus-faq.texi ([5.12]): Fix code example for FQDN in Message-Ids.
 
-       * gnus.texi (NNTP): Change.
+       * message.texi (Message Headers): Add message-header-synonyms.
 
-Sat Feb 14 17:46:33 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Other modes): New node.
+       (Oort Gnus): Refer to the above in "Dired integration".
 
-       * gnus.texi (Virtual Groups): Fix.
-       (NNTP): Addition.
-       (Really Various Summary Commands): Addition.
+2004-01-02  Teodor Zlatanov  <tzz@lifelogs.com>
 
-Fri Feb 13 18:23:19 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Top): updated menu with new manual nodes
+       (The problem of spam): more ranting
+       (Anti-Spam Basics): "spammers are wise to [filtering on From:]"
+       (SpamAssassin): mention spam.el
+       (Hashcash): do not a sentence end proposition with
+       (Filtering Spam Using The Spam ELisp Package): more and better
+       explanation, took lots of information out into subsections
+       (Spam ELisp Package Sequence of Events)
+       (Spam ELisp Package Filtering of Incoming Mail)
+       (Spam ELisp Package Global Variables): new or updated content all
+       around
+       (Spam ELisp Package Configuration Examples): promised new
+       section, empty for now
+       (Blacklists and Whitelists, BBDB Whitelists)
+       (Gmane Spam Reporting, Bogofilter, spam-stat spam filtering)
+       (SpamOracle): mention that spam/ham processor variables are being
+       obsoleted 
+       (Extending the Spam ELisp package): add some new documentation
+       for adding a new backend to spam.el
 
-       * gnus.texi (Mail Group Commands): Typo.
-       (NNTP): Addition.
-       (Mail and Procmail): Addition.
+2004-01-02  Reiner Steib  <Reiner.Steib@gmx.de>
 
-Mon Feb  9 16:30:30 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Foreign Groups): Add `gnus-group-read-ephemeral-group'.
+       (Oort Gnus): Ditto.
 
-       * gnus.texi (Article Date): Addition.
+2004-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Sun Feb  8 16:28:35 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.texi (Key Index): Untabified.
 
-       * gnus.texi (Newest Features): Addition.
+       * gnus.texi (RSS): kindex.
 
-Mon Feb  2 19:21:43 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
 
-       * gnus.texi (Agent Variables): Addition.
+       * gnus.texi (Summary Score Commands): Add `f' to
+       `gnus-score-find-trace'.
+       (Score File Editing): Added `V t'.
 
-Sun Feb  1 18:08:45 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2003-12-31  Steve Youngs  <sryoungs@bigpond.net.au>
+
+       * gnus.texi (XEmacs): Update list of Gnus XEmacs package
+       requirements. 
+
+2003-12-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Canceling and Superseding): Mention `Cancel-Lock'.
+
+2003-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Maildir): Filled.
+       (Key Index): Untabified.
+
+2003-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Parameters): Clarification.
+
+2003-12-29  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Agent Variables): Add.
+
+2003-12-23  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Oort Gnus): Mention change of `e' in draft groups.
+
+2003-12-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Parameters): Clarify.
+
+2003-12-11  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus.texi (Agent Parameters): Added references in Topic and
+       Group Parameters.  Added gnus-agent-cat-disable-undownloaded-faces
+       to the list of documented agent parameters.
+
+2003-12-11  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Mailing Lists): Fix typo.
+
+2003-12-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Fancy Mail Splitting): Close paren of a Lisp function.
+       (SpamAssassin): Ditto.
+
+2003-12-04  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (SpamAssassin, Fancy Mail Splitting): add
+       save-restriction before (widen) in the example.  From Kevin Ryde
+       <user42@zip.com.au>.
+
+2003-12-03  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi (Flowed text): Fix.
+
+2003-12-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Agent Variables): Fix.
+
+2003-12-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: Add missing mode to some @kindex'es.
+
+2003-11-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (RSS): Add nnrss-use-local.
+       (Foreign Groups): Add `G R'.
+
+2003-11-29  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex (subsection*{Notes}): Add `G R'.
+
+2003-11-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Hiding Headers): Update.
+
+2003-11-20  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Debugging IMAP): minor corrections
+
+2003-11-20  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Finding the Parent): nnml does supports fetching by
+       MID.
+
+2003-11-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Debugging IMAP): Add.
+
+2003-11-19  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Score Decays): Update the gnus-decay-score function.
+
+2003-11-17  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Troubleshooting): Update.
+
+2003-11-03  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): added
+       some clarifications
+
+2003-10-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Fancy Mail Splitting): added mention of
+       nnmail-split-fancy-match-partial-words
+
+2003-10-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Slashdot, SpamAssassin, Score File Format): Fix
+       overfull hbox.
+       (Topic Parameters): @group.
+       (Slashdot): Fix.
+
+2003-10-27  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): added
+       example of using a string as a parameter to spam-split in order
+       to override the default spam-split-group value
+
+2003-10-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex (subsection*{Notes}): do.
+
+       * gnus.texi (Exiting the Summary Buffer): Add keybinding.
+
+2003-10-23  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * emacs-mime.texi: Markup: Use @acronym for MML and MIME.
+
+       * message.texi: Ditto.
+
+       * gnus.texi: Ditto.
+
+2003-10-23  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi (MML Definition): Add format.
+
+2003-10-22  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package):
+       changed to use the new spam-initialize function
+
+2003-10-19  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.texi (Mailing Lists): Add Mail-Followup-To to index.
+
+       * gnus.texi (Group Parameters): Add Mail-Followup-To to index.
+       (Emacsen): Fixed typo.
+       (Oort Gnus): Mention message-forward-show-mml change (Sync with
+       GNUS-NEWS).
+
+2003-10-12  Adrian Aichner  <adrian@xemacs.org>
+
+       * gnus.texi (Mail Source Specifiers): uref fixes.
+
+2003-10-18  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Mail Splitting)
+       (Filtering Spam Using The Spam ELisp Package): Markup fixes.
+
+       * message.texi (Security): @url -> @uref.
+
+2003-10-18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi: Define gnusasis and gnusurl.
+
+2003-10-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Mail Splitting): Markup fix.
+
+2003-10-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Files and Directories): Update.
+
+2003-10-02  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): added
+       spam-process-ham-in-spam-groups and
+       spam-process-ham-in-nonham-groups variable descriptions
+
+2003-10-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Various Message Variables): Typo.
+
+       * gnus.texi (Oort Gnus): Typo.
+       (Filtering Spam Using The Spam ELisp Package): Just remember,
+       kids: There is no 'c' in 'supersede'.
+
+2003-09-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Reply): Fix typo.
+
+2003-09-22  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Fancy Mail Splitting, SpamAssassin): corrected fancy
+       split example to use current buffer, mentioned
+       nnimap-split-download-body
+
+2003-09-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi, gnus-faq.texi, message.texi: gnus -> Gnus.
+
+       * message.texi: Fixes.
+
+2003-09-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Fancy Mail Splitting): Make split-on-body work for
+       respooling.  Suggested by Harald Maier <maierh@myself.com>.
+       (Fancy Mail Splitting): Reformat.
+
+2003-09-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Posting Styles): Fix typo.  @itemize attribute names.
+
+2003-09-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * pgg.texi (Selecting an implementation, Caching passphrase)
+       (Initializing): Markup fix.
+
+2003-09-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Buffer Lines): Formatting fix.
+
+2003-09-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Creating a Virtual Server): Use nnml for the example.
+       nnspool doesn't work on ms-windows due to file name restrictions.
+
+2003-08-29  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Gmane Spam Reporting): added explanation of
+       spam-report-gmane-use-article-number
+
+2003-08-25  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Customizing Articles): xface -> x-face.
+
+2003-08-20  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (GroupLens): Move text around.
+
+2003-08-16  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Searching for Articles): Fix example.
+
+2003-08-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Kibozed Groups): Fix.
+
+2003-08-04  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Parameters): Add expiry-target.
+       (Archived Messages): Layout fix.
+
+2003-07-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Top): Menu fixes and additions.
+
+2003-07-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Encoding Customization): Fix.
+       (MML Definition): Typo.
+
+2003-07-17  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Sorting the Summary Buffer): Index.
+
+2003-07-15  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-faq.texi ([3.8]): Fixed example.
+
+2003-07-14  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package):
+       mentioned the spam-install-hooks mess
+
+2003-07-11  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Splitting in IMAP): Typos, tiny patch from Matthias
+       Andree <ma@dt.e-technik.uni-dortmund.de>.
+       (Splitting in IMAP): Mention Sieve.
+
+2003-07-10  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Security): Discuss the PGP 2.x compatibility
+       problem.
+
+2003-06-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * sieve.texi (Sieve Mode): Formatting fix.
+
+       * gnus.texi (Agent Basics, Group Parameters, Quassia Gnus): do.
+
+2003-06-24  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Summary Mail Commands): Make note of
+       Mail-Followup-To. 
+
+2003-06-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: Formatting fixes.
+
+2003-06-22  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Security): Mention S/MIME passphrases.
+
+2003-06-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: Add @command.
+
+       * texi2latex.el (latexi-translate-file): Add @command and @:.
+
+       * gnus.texi (Face): Use @uref.
+
+2003-06-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Sieve Commands, Agent Basics, SpamOracle): @xref
+       fixes.
+
+2003-06-18  Didier Verna  <didier@xemacs.org>
+
+       * gnus.texi (Face): New node.
+       * gnus.texi (Article Display): Reference it.
+       * gnus.texi (Customizing Articles): Ditto.
+       * gnus.texi (Image Enhancements): Put the Face node into the menu.
+
+2003-06-17  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * gnus.texi (Splitting Mail): Add "splitting" entry and concept
+       index entries.  Small patch from Karl Pfl\e,Ad\e(Bsterer
+       <sigurd@12move.de>.
+
+2003-06-15  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Daemons): Fixed typo.
+
+2003-06-15  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * message.texi (Message Headers): Extend
+       `message-subject-re-regexp' example.  From Niklas Morberg
+       <niklas.morberg@axis.com>.
+
+2003-06-11  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Bogofilter): revise docs to mention threshold is now
+       user-controllable
+
+2003-06-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi: Use two spaces consistently to end sentences.
+
+       * message.texi: do.
+
+       * gnus.texi: do.
+
+2003-06-09  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): new
+       SpamOracle node
+       (SpamOracle): document new SpamOracle code
+
+2003-06-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Article Buttons, Splitting in IMAP)
+       (Category Syntax, Picons): Preemptive strike by
+       alt.possesive.its.has.no.apostrophe.
+
+2003-06-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Fancy Mail Splitting): Explain some entries in
+       nnmail-split-abbrev-alist.
+
+2003-05-17  Adrian Aichner  <adrian@xemacs.org>
+
+       * emacs-mime.texi (Charset Translation): Ruthless typo fixing.
+       * gnus.texi (Top): Ditto.
+       * gnus.texi (Selecting a Group): Ditto.
+       * gnus.texi (Delayed Articles): Ditto.
+       * gnus.texi (Hiding Headers): Ditto.
+       * gnus.texi (Getting Mail): Ditto.
+       * gnus.texi (Comparing Mail Back Ends): Ditto.
+       * gnus.texi (IMAP): Ditto.
+       * gnus.texi (Required Back End Functions): Ditto.
+       * gnusref.tex (MIMESummary): Ditto.
+       * message.texi (Message Headers): Ditto.
+       * message.texi (Mail Variables): Ditto.
+       * pgg.texi (Prerequisites): Ditto.
+       * pgg.texi (Architecture): Ditto.
+       * pgg.texi (Backend methods): Ditto.
+       * sieve.texi (Managing Sieve): Ditto.
+
+2003-05-17  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex (subsection*{Notes}): Fix.
+
+2003-05-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Anti-Spam Basics): Removed mention of gnus-junk.
+
+2003-05-13  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Agent Variables, Score File Format)
+       (Troubleshooting, Editing IMAP ACLs, Conformity): a -> an.
+
+       * message.texi (Insertion Variables): do.
+
+2003-05-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP, Agent and IMAP, Oort Gnus): s/a/an/.  Tiny
+       patch from Niklas Morberg <niklas.morberg@axis.com>.
+
+2003-05-12  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus.texi (Agent Visuals): Add.
+
+2003-05-09  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.texi (Default user identity): Add.
+
+2003-05-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Selecting a Group): Mention nil value
+       gnus-large-newsgroup.
+
+2003-05-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (MIME Commands): Fix typo.
+
+2003-05-05  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex: Additions.
+
+       * gnus.texi (Oort Gnus): Fix typo.
+
+2003-05-03  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * gnus.texi (Agent Basics): Explain that some servers can be
+       agentized, whereas others aren't.
+
+2003-05-01  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Oort Gnus): Add prefix limit feature.
+       (Oort Gnus): Fix last commit.
+
+2003-05-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Emacsen): Update.
+
+2003-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Document nnimap-need-unselect-to-notice-new-mail.
+
+2003-05-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Wide Characters): Proportional -> fixed width.
+
+       * texi2latex.el (latexi-translate-file): Add @syncodeindex.
+
+       * gnus.texi: Markup and formatting improvements.
+       Use @syncodeindex for merging indexes to get the same font for
+       @defvar and @vindex entries.  Be more consistent about the case
+       of index entries.
+
+
+2003-04-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Top, Appendices): Fixed Gnus FAQ entry.
+
+       * gnus-faq.texi: Wrap long lines in menus.  Index.
+
+       * gnus.texi (Image Enhancements): Mention missing images support
+       of Emacs on MS Windows.
+       (Oort Gnus): Mention Gnus FAQ.
+
+2003-04-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): revised
+       documentation
+       (Gmane Spam Reporting, Anti-spam Hashcash Payments): new sections
+
+2003-04-30  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Oort Gnus): New features in Gnus 5.10 from GNUS-NEWS.
+
+2003-04-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): Index.
+       Add gnus-spam-mark.
+       (Various Summary Stuff): Add gnus-summary-display-arrow.
+
+       * gnus.texi: Fix typos.
+
+2003-04-27  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Group Parameters): Fix markup.
+       (Web Archive): Ditto.
+
+2003-04-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * texi2latex.el (latexi-translate-file): Support @display,
+       @group, @smallexample, @subsubheading.
+
+       * gnus.texi, gnus-faq.texi: Fix some of the worst overfull and
+       underfull hboxes.
+
+       * message.texi, gnus.texi: Use the second arg to @uref where it
+       makes sense to make HTML and PDF output look nicer.
+
+2003-04-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus-faq.texi: Make it compile in the LaTeX version.  Remove
+       redundant entries in @urefs.
+       (FAQ - Glossary): Remove the final @bye since it breaks the Gnus
+       manual.
+       ([1.2]): @subsection -> @subheading.
+
+       * texi2latex.el (latexi-translate-file): Support @r, @env,
+       @heading, @subheading, @TeX.
+
+       * gnus.texi, message.texi, emacs-mime.texi: Markup improvements
+       and fixes.
+
+2003-04-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Selecting a Group): Add gnus-large-ephemeral-newsgroup.
+       (Filling In Threads): Add gnus-fetch-old-ephemeral-headers.
+       (Terminology): Index.
+
+2003-04-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: nil -> @code{nil}.  Capitalize "Rmail" and "Babyl"
+       consistently.
+
+2003-04-22  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-faq.texi: Allow inclusion in `gnus.texi' again.
+
+2003-04-21  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus-faq.texi: New, the Gnus FAQ from http://my.gnus.org/FAQ.
+       From Frank Schmitt <ich@frank-schmitt.net>.
+
+       * gnus.texi (Server Variables): Added server parameters and index.
+
+2003-04-21  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@gmx.net>
+
+       * gnus.texi (Group Parameters): Pointer to
+       gnus-newsgroup-variables.
+
+2003-04-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Buffer Lines): Add
+       gnus-sum-thread-tree-false-root.
+
+2003-04-15  Michael Shields  <shields@msrl.com>
+
+       * gnus.texi (Group Parameters, Hiding Headers): Document that
+       the broken-reply-to group parameter now also affects header
+       hiding.
+       * gnus.texi (Summary Mail Commands): Suggest setting the
+       broken-reply-to parameter if you find yourself using `B r'.
+
+2003-04-16  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi (MML Definition): Add sender tag.
+
+2003-04-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Line Specification): Add.
+
+2003-04-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Security): Add text about PGP key snarf.
+
+2003-04-13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Misc Article): Addition.
+
+2003-04-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (Message Headers): Addition.
+
+2003-04-12  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Encoding Customization): Update default for
+       mm-body-charset-encoding-alist.
+
+2003-04-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Non-MIME): Add diff.
+
+2003-04-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Security): Fix typo.
+
+2003-04-06  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi: Changed ~/.gnus and .gnus.el to ~/.gnus.el
+
+2003-04-02  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Gnus Versions): Index.
+       (Summary Score Commands): Decribe keys in `*Score Trace*' buffer.
+
+2003-04-01  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Button Levels): Added
+       `gnus-button-ctan-directory-regexp'
+
+2003-04-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Indirect Functions): Fix examples for
+       nntp-via-rlogin-command-switches.
+
+2003-03-31  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Button Levels): New node.
+       (Article Buttons): Additions.
+
+2003-03-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Exiting Gnus): Removed gnus-unload.
+
+2003-03-31  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Add.
+
+2003-03-27  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Comparing Mail Back Ends): Note nnmaildir's
+       incompatibilities more prominently.
+
+2003-03-27  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Maildir): Note nnmail-expiry-target incompatibility.
+
+2003-03-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Adaptive Scoring): Fix.
+
+2003-03-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Direct Functions, Common Variables)
+       (Mail Source Specifiers, IMAP): Add TLS wherever SSL is mentioned
+       now.
+
+2003-03-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Information, Article Washing)
+       (Formatting Fonts, Group Parameters): Fix external xrefs.
+
+       * message.texi (Mailing Lists): do.
+
+2003-03-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Troubleshooting): Fix typo.
+       (Drafts): Mention how to restore special property, suggested by
+       Florian Weimer <fw@deneb.enyo.de>.
+
+2003-03-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Misc Article): Add.
+       (Agent Basics): Fix makeinfo warnings.
+
+       * message.texi (IDNA): New.
+
+2003-03-18  Kevin Greiner <kgreiner@xpediantsolutions.com>
+
+       * gnus.texi (Gnus Unplugged): Refer to new agent Group/Topic
+       parameters.
+       (Category Syntax): New description.
+       (Category Buffer): New command.
+       (Category Variables): New variables.
+       (Agent as Cache): Expanded description.
+       (Agent Expiry): Expanded description.
+       (Agent Variables): Fixed and new descriptions.
+
+       * infohack.el (batch-makeinfo): Provide local implementation of
+       subst-char-in-region as the built-in implementation is unreliable
+       on Windows XP (Intermittent failure results in build looping
+       forever).
+
+2003-03-18  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Maildir): Replace create-directory with
+       target-prefix.
+
+2003-03-18  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Maildir): More info for expire-group; add
+       distrust-Lines:.
+
+2003-03-17  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Comparing Mail Back Ends): nnmaildir fixes.
+
+2003-03-17  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Using MIME): Added gnus-mime-delete-part.
+
+2003-03-17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Required Back End Functions): Add.
+
+2003-03-17  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.texi: Fix setfilename.  Tiny patch by Frank Haun
+       <pille3003@fhaun.de>.
+
+2003-03-09  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Top): Added menu item for Maildir node.
+
+2003-03-11  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Paging the Article): Addition.
+
+2003-03-10  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Customizing Articles): Additions.
+
+2003-03-09  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Maildir): New node.
+
+2003-03-08  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex: Update.
+
+2003-03-03  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Mail and Post): Updated `gnus-user-agent'.
+       (Mail Source Customization): Added `mail-source-delete-incoming'
+       and `mail-source-delete-old-incoming-confirm'.
+
+2003-03-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Troubleshooting): Fix typo.
+       (Group Parameters): Markup fix.
+       (Article Hiding, Splitting Mail, Fancy Mail Splitting)
+       (Document Server Internals, Score Variables, Adaptive Scoring)
+       (X-Face, Hashcash): do.
+
+2003-02-28  Vasily Korytov <deskpot@myrealbox.com>
+
+       * gnus.texi: New values, 'to-list and 'cc-list, for
+       gnus-boring-article-headers.
+
+2003-02-28  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Extending the spam elisp package): added mention of
+       spam-list-of-statistical-checks
+
+2003-02-27  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Remove the dependence on ssl.el.
+
+2003-02-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Mail Variables): Add
+       message-sendmail-envelope-from.
+
+2003-02-24  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Mail and Post): Added `gnus-user-agent', removed
+       `gnus-version-expose-system'.
+
+2003-02-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: Markup fixes.
+
+       * message.texi: do.
+
+       * emacs-mime.texi: do.
+
+2003-02-20  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.texi (News Headers): Update description of Message-ID.
+
+2003-02-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Startup Files): Addition.
+
+2003-02-22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Source Specifiers): Addition.
+
+2003-02-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Files and Directories): New node.
+
+2003-02-21  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Mailing List): Fix.
+
+       * gnus.texi: Markup fixes.
+
+2003-02-18  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Washing): Mention `g'.
+       (Customizing Articles): Added cross reference.
+
+2003-02-12  Michael Shields  <shields@msrl.com>
+
+       * gnus.texi (Paging the Article): Document
+       gnus-article-boring-faces.
+       (Choosing Commands): Explain that SPACE in the summary buffer
+       is used for both selecting and scrolling.
+
+       * gnus.texi (Article Keymap): Say that SPACE and DEL in the
+       summary buffer are the same as switching to the article buffer
+       and using SPACE and DEL; since now that is the case.
+
+2003-02-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Topic Commands): Addition.
+
+2003-02-07  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (BBDB Whitelists, Blacklists and Whitelists):
+       corrected existing docs, added spam-use-whitelist-exclusive and
+       spam-use-BBDB-exclusive to list of variables
+
+2003-02-07  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (The problem of spam): Don't use @email for examples
+       -- it creates a mailto-link in HTML and PDF.
+
+2003-02-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Source Customization): Addition.
+
+2003-02-04  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.texi (Mail Variables): Added index entry for
+       `message-send-mail-partially-limit'
+
+2003-01-30  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Batching Agents): Index.
+       (Agent Commands): do.
+       (Delayed Articles): do.
+       (Drafts): do.
+       (Web Archive): do.
+       (Article Washing): do.
+       (Slave Gnusae): do.
+       (Agent Basics): do.
+       (Exiting Gnus): do.
+       (Article Date): do.
+       (X-Face): do.
+       (Exiting the Summary Buffer): do.
+       (Charsets): do.
+       (Mail Group Commands): do.
+
+       * gnus.texi: Mark-up fixes.
+
+2003-01-27  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi: replace `H' mark with `$' mark
+       (Blackholes): add spam-blackhole-good-server-regex variable
+
+2003-01-26  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.texi (Installation): Extension .sv is also used.
+
+2003-01-26  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Article Backlog): Update.
+
+2003-01-23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (NNTP): Addition.
+
+2003-01-23  Teodor Zlatanov  <tzz@bwh.harvard.edu>
+
+       * gnus.texi (Regular Expressions Header Matching): documentation
+       for new spam splitting functionality
+
+2003-01-23  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Signing and encrypting): Index.
+       (Smileys): Update.
+       (Toolbar): Move to XVarious because it's XEmacs specific.
+
+2003-01-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Picons): Update.
+
+2003-01-22  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.texi (Agent Expiry, Agent Variables): Don't use @pxref for
+       index entries.
+
+2003-01-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Add.
+       (Expiring in IMAP): Typo fixes.
+
+2003-01-22  Kevin Greiner  <kgreiner@xpediantsolutions.com>
+
+       * gnus.texi (Agent Regeneration): New node.
+       (gnus-select-article-hook): clarified.
+       (gnus-downloaded-mark): Added definition.
+       (gnus-undownloaded-mark): Updated definition to reference the new
+       %O spec.
+       (gnus-agent-catchup): Identified articles that are NOT marked as read.
+       (gnus-agent-fetch-group): New command.
+       (gnus-agent-fetch-series): New command.
+       (Agent Expiry): Added comment to document that
+       gnus-request-expire-articles may invoke gnus-agent-expire.
+       (gnus-agent-mark-unread-after-downloaded): New variable.
+       (gnus-agent-consider-all-articles): New variable.
+       (gnus-agent-max-fetch-size): New variable.
+
+2003-01-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex (subsection*{Notes}): do.
+
+       * gnus.texi (Article Hiding): Remove gnus-article-hide-pgp.
+       (Customizing Articles): Remove gnus-treat-strip-pgp.
+
+2003-01-21  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Various Summary Stuff): Add
+       gnus-summary-display-while-building.
+       (Group Parameters): Index gnus-parameters.
+       (Startup Files): Index gnus-site-init-file
+
+2003-01-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Buffer Lines): Additions to %B.
+
+       * gnus.texi: Markup fixes: use @code for nil and t, use @file for
+       files.
+
+       * message.texi: do.
+
+       * emacs-mime.texi: do.
+
+2003-01-19  Jesper Harder  <harder@ifa.au.dk>
+
+       * dir (File): Add pgg.
+
+       * gnus.texi (Selecting a Group): Index gnus-auto-select-subject
+
+       * emacs-mime.texi (Display Customization): Add mm-keep-viewer-alive-types
+
+2003-01-16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Summary Agent Commands): Addition.
+
+2003-01-16  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package):
+       clarified syntax of gnus-spam-process-destinations and
+       gnus-ham-process-destinations variables
+       (Extending the spam elisp package): fixed typo in node name
+       (Bogofilter): new functionality and variables noted
+       (Filtering Spam Using The Spam ELisp Package): added mention of
+       nnimap-split-download-body
+
+2003-01-15  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Don't use `path' in some cases.
+       From the GNU coding standards:
+
+           Please do not use the term ``pathname'' that is used in Unix
+           documentation; use ``file name'' (two words) instead.  We use
+           the term ``path'' only for search paths, which are lists of
+           directory names.
+
+       * message.texi: Ditto.
+
+2003-01-15  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (X-Face): Revert substantial part of last fix.
+       (Splitting in IMAP): Add.
+
+2003-01-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Window Layout): Fixed braces in example.
+
+2003-01-13  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Washing): Use new function names in
+       `deuglify.el'.  Addition.
+
+2003-01-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (X-Face): Fix.
+
+       * message.texi (Security): Fix.
+
+       * gnus.texi (Security): Fix.
+       (Signing and encrypting): Fix.
+
+2003-01-12  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using The Spam ELisp Package): removed
+       spam.el and spam-stat.el from the node and section names wherever
+       possible, since info indexing doesn't like `.' in the name
+
+2003-01-12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Display): Addition.
+
+2003-01-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (Header Commands): Addition.
+
+2003-01-10  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Washing): Added gnus-outlook-unwrap-lines,
+       gnus-outlook-repair-attribution, gnus-outlook-rearrange-citation.
+
+2003-01-11  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi: Change .gnus to .gnus.el.
+       (Agent Commands): Remove batch here.
+       (MIME Commands): Add.
+
+       * message.texi (Canceling News): Document canlock.
+
+2003-01-10  Alex Schroeder  <alex@emacswiki.org>
+
+       * gnus.texi (Creating a spam-stat dictionary): Explain how using
+       the Gnus Agent with nnimap might work to do this.
+       (Splitting mail using spam-stat): Use nnimap-split-fancy if you
+       use the nnimap back end.
+
+2003-01-10  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Filtering Spam Using spam.el): Trivial fix.
+
+2003-01-10  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Choosing Variables, Agent Caveats): Add.
+
+2003-01-09  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using spam.el, ifile spam filtering)
+       (spam-stat spam filtering): added new functionality and explained
+       old functionality better, especially where it has changed in
+       ham/spam/unclassified group exit processing.
+
+2003-01-09  Alex Schroeder  <alex@emacswiki.org>
+
+       * gnus.texi (Splitting mail using spam-stat): Fix typo.
+       (Creating a spam-stat dictionary, Splitting mail using spam-stat):
+       Fix markup in a few places.
+
+2003-01-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Positioning Point): %~ => ~*.
+
+2003-01-07  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * message.texi: Updated copyright line.
+       (Mailing Lists): Updated (renamed) function names.
+       (Header Commands): Updated (renamed) function names.
+       (Header Commands): Added message-to-list-only,
+       message-change-subject, message-cross-post-followup-to,
+       message-reduce-to-to-cc and message-add-archive-header.  Moved
+       message-sort-headers, message-insert-to, message-insert-newsgroups
+       and message-insert-disposition-notification-to from other
+       sections.
+       (Insertion): Added message-mark-inserted-region,
+       message-mark-insert-file.  Moved
+       message-insert-disposition-notification-to to section (Header
+       Commands).
+       (Various Commands): Moved message-insert-wide-reply,
+       message-insert-to, message-insert-newsgroups and
+       message-sort-headers to (Header Commands) section.
+       (Message Headers): Added message-subject-trailing-was-query.
+       (Insertion Variables): Added message-mark-insert-begin and
+       message-mark-insert-end.
+
+2003-01-08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Optional Back End Functions): Addition.
+       (Positioning Point): Changed to %~.
+
+2003-01-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (MIME Commands): Add.
+
+2003-01-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (Various Commands): Addition.
+
+2003-01-05  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Filtering Spam Using spam.el)
+       (Blacklists and Whitelists, BBDB Whitelists, Blackholes)
+       (Bogofilter, Ifile spam filtering, Extending spam.el): updated
+       documentation for the new spam.el functionality
+
+2003-01-05  Jesper Harder  <harder@ifa.au.dk>
+
+       * refcard.tex: Fix pagebreak.
+
+       * gnusref.tex: Additions and fixes.
+
+       * booklet.tex: Add missing sections.
+
+       * gnus.texi (Mail Group Commands): Fix typo.
+       (XEmacs): Add sh-script.
+       (Article Washing): Fix.
+
+2003-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Setting Process Marks): Addition.
+       (Group Line Specification): Addition.
+
+2003-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Line Specification): Addition.
+
+2003-01-03  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi: Fix typos.
+
+2003-01-02  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Troubleshooting): Add.
+
+2003-01-02  Reiner Steib  <Reiner.Steib@gmx.de>
+
+       * gnus.texi (Article Buttons): Regexps are case insensitive here.
+
+2003-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Summary Generation Commands): Addition.
+
+2003-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (Message Headers): Added example.
+       (Message Headers): Addition.
+
+2002-12-31  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.texi (Top): Add pointers to related manuals.  Suggested by
+       Reiner Steib.
+
+2002-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Saving Articles): Addition.
+
+2002-12-30  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Blackholes): added information on query-dig and
+       dig.el; users are told that using blackhole checks is OK now
+
+2002-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Loose Threads): add
+       gnus-summary-make-false-root-always.
+       (Finding the Parent): Change name of nnweb server.
+
+2002-12-22  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi: Fix typos.  Index variables.  Add
+       mm-automatic-external-display, mm-w3m-safe-url-regexp and
+       mm-external-terminal-program.
+
+2002-12-20  Jesper Harder  <harder@ifa.au.dk>
+
+       * message.texi (Message Headers): Add message-allow-no-recipients.
+       (Various Commands): Add TAB and message-tab-body-function.
+
+2002-12-19  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Optional Back End Functions):
+       nnchoke-request-update-info need not return the info object.
+
+2002-12-15  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex: Additions.
+
+2002-12-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Mail): Explain nil value of gnus-uu-digest-headers.
+
+2002-12-10  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.texi (Posting Styles): Clarify the `(header MATCH REGEXP)'
+       case.
+       (Back End Interface): Mention nnnotbackends.  Suggested by Jan
+       Rychter.
+
+2002-11-29  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.texi (MIME Commands): Document gnus-inhibit-mime-unbuttonizing.
+
+2002-11-27  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Expiring in IMAP): backend -> back end.
+       (Wide Characters): The default value of
+       gnus-use-correct-string-widths under Emacs is nil.
+       (Filtering Spam Using spam.el): backend -> back end.
+       (Extending spam.el): backend -> back end.
+       (Filtering Spam Using Statistics (spam-stat.el)): Fix typo.
+       (Creating a spam-stat dictionary): Fix typo.
+       (Creating a spam-stat dictionary): backend -> back end.
+
+2002-11-22  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi (Extending spam.el): fixed typos and wrong @items
+
+2002-11-21  Teodor Zlatanov  <tzz@lifelogs.com>
+
+       * gnus.texi:
+       added new keyboard commands
+
+       * gnus.texi: added extended section on spam
+
+2002-11-18  jas
+
+       * gnus.texi: Fix IMAP expiring typos.
+
+2002-11-18  kaig
+
+       * gnus.texi: *** empty log message ***
+
+2002-11-18  jas
+
+       * gnus.texi: More morse.
+
+       * gnus.texi (Article Washing): Add morse.
+
+2002-11-17  jas
+
+       * gnus.texi: Fix typo.
+
+       * gnus.texi (Expiring in IMAP): Add.
+       (Group Parameters): Add reference.
+
+2002-11-16  Kai Gro\e,A_\e(Bjohann  <kai.grossjohann@uni-duisburg.de>
+
+       * gnus.texi (Expiring Mail): Give summary on difference between
+       auto-expire and total-expire and provide information for choosing
+       between them.
+
+2002-11-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Article Washing): Add morse.
+
+2002-11-17  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Expiring in IMAP): Add.
+       (Group Parameters): Add reference.
+
+2002-10-24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (RSS): Add gnus-summary-mark-as-read-forward into the
+       example code. From Christoph Conrad <christoph.conrad@gmx.de>.
+
+2002-10-17  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Other Marks): Document gnus-downloadable-mark and
+       gnus-undownloaded-mark.  Adapted idea from Sriram Karra
+       <karra@shakti.homelinux.net>.
+       (Formatting Fonts): Say that guillemets are wrong.  (How to enter
+       guillemets in Texinfo files?)
+
+2002-10-12  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Movement): Add.
+
+2002-10-11  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Formatting Fonts): Fix for balloon help in GNU Emacs.
+
+2002-10-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Delayed Articles): Fix gnus-delay-initialize.
+
+2002-10-10  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Security): Fix.
+
+2002-10-04  Simon Josefsson  <jas@extundo.com>
+
+       * pgg.texi: Document sign parameter.
+
+       * gnus.texi: Add \gnuskey tex command.
+
+       * texi2latex.el (latexi-translate-file): Do PGG.  (Poor) support
+       of @set, @deffn, @defvar, @defun, @key.  Improve error.
+
+       * Makefile.in: Add PGG.
+
+       * pgg.texi: New file.
+
+2002-10-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Group Information): Mention prefix argument for
+       gnus-group-fetch-charter and gnus-group-fetch-control.
+       From Jesper Harder.
+
+2002-09-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Agent Variables): Add.
+
+2002-09-25  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Troubleshooting): Add.
+
+2002-09-23  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Maneuvering): Fix gnus-auto-select-next.
+
+2002-09-19  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (X-Face): Add GIF.
+
+2002-09-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (A note on namespaces): New.
+
+2002-09-16  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Splitting Mail): "By default, splitting is performed
+       on all incoming messages."  This sentence had a "not" too many.
+       Explicitly say that `nnmail-resplit-incoming' has effect only for
+       `directory' mail-sources entries.
+
+2002-09-15  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Mail Source Specifiers): Say "one-to-one
+       correspondence" in the description of `directory'.
+
+2002-09-11  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Top, Summary Buffer): Add info to "Delayed Articles"
+       menu line.
+
+2002-09-11  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Article Hiding): Add a document for
+       gnus-article-address-banner-alist.
+
+2002-09-11  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Splitting in IMAP): Fix.
+
+2002-09-10  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Other Marks): Fix.
+
+2002-09-09  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Splitting Mail): Typo.
+       (Comparing Mail Back Ends): Say "back end" instead of "backend".
+       (Terminology): Try to explain "back end" better.
+
+2002-09-09  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Article Buttons): Add.
+
+2002-09-09  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Splitting Mail): Document nnmail-resplit-incoming,
+       xref to Mail Source Specifiers.
+       (Mail Source Specifiers): Add index entry for
+       nnmail-scan-directory-mail-source-once.  Add index entry for
+       nnmail-resplit-incoming, with xref to Splitting Mail.
+
+2002-09-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Browse Foreign Server): Addition.
+       (Limiting): Addition.articles
+
+2002-09-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Source Specifiers): Fix.
+
+2002-09-03  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Direct Functions, Common Variables): Named ports like
+       "snews" doesn't work with some external tools.  Thanks to
+       "D. Watson" <djwatson@u.washington.edu> for noting this.
+
+2002-09-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Gnus Unplugged): Fix, agent is now enabled by default.
+       (Agent as Cache): New.
+
+2002-08-26  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Information): Add gnus-group-fetch-charter and
+       gnus-group-fetch-control.
+
+2002-08-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Posting Server): Document message-smtpmail-send-it.
+
+       * message.texi (Mail Variables): Add message-smtpmail-send-it.
+
+2002-08-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Source Specifiers): Fix :path default.
+
+2002-08-22  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Mail Commands): Add
+       gnus-summary-reply-broken-reply-to and
+       gnus-summary-reply-broken-reply-to-with-original.
+       (Setting Process Marks): Add gnus-uu-unmark-region
+       (Article Header): Fix typo.
+       (MIME Commands): Fix typo.
+       (MIME Commands): Index gnus-article-decode-mime-words,
+       gnus-article-decode-charset and gnus-mime-view-all-parts.
+
+2002-08-20  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Mail Source Specifiers): Mention variable
+       nnmail-resplit-incoming under `directory' specifier.
+
+2002-08-18  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Summary Buffer Lines): Document the %k specifier.
+
+2002-08-15  Jesper harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Group Line Specification): Add %C.
+       (Group Parameters): Comments can be displayed in the group line.
+
+2002-08-07  Jesper harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Non-MIME): Add yenc.
+       (yenc): New node.
+
+2002-08-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Summary Sorting): Document randomization.
+
+2002-07-28  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Web Searches): Added gmane and removed old
+       non-functioning search engines.  From Niklas Morberg
+       <niklas.morberg@axis.com>.
+
+2002-05-14  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Summary Buffer Lines): Fix typo.
+
+2002-07-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Summary Mail Commands): Trivial fix from Reiner Steib
+       <4uce.02.r.steib@gmx.net>.
+
+2002-07-18  Karl Kleinpaste  <karl@charcoal.com>
+
+       * gnus.texi (To From Newsgroups): Additional text regarding how to
+       regenerate overviews via server buffer, and note to news admins
+       about overview.fmt.
+
+2002-07-14  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Posting Styles): Fix example (it was using the To
+       header instead of the From header).  From Christopher Splinter
+       <cs@splinter.inka.de>.
+
+2002-07-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Top): Move hashcash down into spam chapter.
+       (Top): New spam menu.
+       (Various): Remove hashcash.
+       (Thwarting Email Spam): Split into introduction and "Anti-Spam
+       Basics" node.
+       (SpamAssassin): Add.
+       (Hashcash): Add.
+
+2002-06-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (NNTP): Doc fix.
+
+2002-07-02  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Washing Mail): Document the shortcoming of
+       nnmail-remove-leading-whitespace.
+
+2002-06-30  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.texi (News Headers): Include example for removing an
+       entry from message-required-news-headers.
+
+2002-06-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (NNTP): Add nntp-via-rlogin-command-switches.
+
+2002-06-27  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Mail Back End Variables): Document
+       nnmail-cache-ignore-groups.  Xref Fancy Mail Splitting.
+       (Fancy Mail Splitting): Mention nnmail-cache-ignore-groups and
+       why it is useful.
+
+2002-06-25  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Fancy Mail Splitting): Include all necessary
+       variables in the Lisp example.
+
+2002-06-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Pay Hashcash): Add.
+
+2002-06-03  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Splitting Mail): Add.
+
+2002-05-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Web Searches): Fix.  Trivial change from Niklas
+       Morberg <niklas.morberg@axis.com>.
+
+2002-05-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail): Add variable.
+
+2002-05-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Loose Threads): Add gnus-simplify-all-whitespace.
+
+2002-05-08  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Mail-To-News Gateways): The default
+       nngateway-header-transformation function inserts a "To" header,
+       not a "From" header.  From Jesper Harder <harder@ifa.au.dk>.
+
+2002-05-08  Josh Huber  <huber@alum.wpi.edu>
+
+       * message.texi (Security): Added a note about the signencrypt
+       style, and how to change it using `mml-signencrypt-style.'
+
+2002-05-04  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi (Encoding Customization): Fix.
+
+2002-05-04  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi: Move two chapters "Interface Functions" and
+       "Basic Functions" after the Decoding and Encoding chapters.  (No
+       text modified.)
+
+2002-05-04  Simon Josefsson  <jas@extundo.com>
+
+       * emacs-mime.texi (Top): Change scope of manual to include users.
+       (Customization): Rename to Display Customization.
+       (MML Definition): Add cross references.
+       (Encoding Customization): New section.
+       (Charset Translation): More info and cross references.
+
+2002-05-01  Josh Huber  <huber@alum.wpi.edu>
+
+       * gnus.texi (Signing and encrypting): Fix doc.  Also, add a
+       paragraph about replysign/replyencrypt/replysignencryped use.
+
+2002-05-01  Lars Magne Ingebrigtsen  <larsi@quimbies.gnus.org>
+
+       * message.texi (Message Headers): Remove colon from index
+       entries.
+
+2002-05-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Group Mail Splitting): Fix example.
+       (Article Buttons): Document that REGEXP can be a variable as well.
+
+       * message.texi (Message Headers): Fix example.
+
+2002-04-26  Steve Youngs  <youngs@xemacs.org>
+
+       * Makefile.in (infodir): Set to '@info_dir@' so we can separate
+       defaults for XEmacs and Emacs.
+
+2002-04-27  Jesper Harder  <harder@ifa.au.dk>
+
+       * emacs-mime.texi (Customization): Update info on HTML renderers.
+
+       * gnus.texi (Article Washing): Update information on HTML washing.
+       Fix typos.
+
+2002-04-09  Paul Jarc  <prj@po.cwru.edu>
+
+       * .cvsignore: added message-[0-9]*
+
+2002-04-08  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Group Parameters): Point to the message manual for a
+       full explanation of MFT.
+       * message.texi (Mailing Lists): Mention
+       message-gen-unsubscribed-mft.
+       From Karra <karra@cs.utah.edu>.
+
+2002-04-05  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Saving Articles): Add xref to Mail Group Commands
+       because people might be interested in `B c' for saving articles.
+       (Archived Messages): Ditto.
+
+2002-04-01  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnus.texi (Sorting Groups): Add gnus-group-sort-selected-groups.
+       (Article Washing): Fix typo.
+
+       * message.texi (Various Commands): Index message-elide-ellipsis.
+       Add message-sort-headers.
+       (Mail Variables): Add message-qmail-inject-args,
+       message-mailer-swallows-blank-line, message-sendmail-f-is-evil,
+       message-qmail-inject-program.
+       (Various Message Variables): Add message-auto-save-directory,
+       message-strip-special-text-properties, message-cancel-hook.
+       (News Headers): Index message-user-organization etc.
+       (Forwarding): Add message-forward-before-signature.
+       (Mailing Lists): Index message-subscribed-address-file.
+       (Wide Reply): Add message-wide-reply-confirm-recipients.
+       (Canceling News): Add message-cancel-message.
+       (Sending Variables): Add message-interactive.
+
+2002-03-25  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Spool): Add cindex for marks.
+       (Mail Folders): Add cindex for marks.
+
+2002-03-24  Raymond Scholz <rscholz@zonix.de>
+
+       * gnus.texi (Summary Buffer Lines): Fix doc.
+
+2002-03-24  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (booklet.dvi, booklet.pdf): Support booklet.
+
+2002-03-24  Felix Natter <fnatter@gmx.net>
+
+       * booklet.tex, bk-at.tex, bk-lt.tex, gnuslog-booklet.eps: New file.
+       * gnusref.tex, refcard.tex: Support booklet.
+
+2002-03-24  Jesper Harder  <harder@ifa.au.dk>
+
+       * gnusref.tex: Addition.
+
+       * gnus.texi: Don't use @sc in headings.
+       (Article Display): Fix.
+       (Signing and encrypting): Add mml-unsecure-message.
+       (IMAP): Remove @. to make texi2latex work.
+       (Thread Commands): Fix.
+       (Unavailable Servers): Add gnus-server-offline-server.
+       (Topic Sorting): Add gnus-topic-sort-groups.
+       (Limiting): Fix.
+       (Article Washing): Fix gnus-article-strip-headers-in-body, add
+       gnus-article-outlook-deuglify-article.
+       (Article Header):  Add gnus-article-remove-leading-whitespace.
+       (Customizing Articles): Add gnus-treat-leading-whitespace.
+       (Summary Score Commands): Add gnus-score-find-favourite-words.
+       (Mailing List): Index gnus-mailing-list-insinuate.
+       (Mail Group Commands): Add gnus-article-encrypt-body,
+       gnus-summary-create-article.  Don't use @var if not
+       metasyntactic. Index gnus-summary-edit-article-done.
+
+       * message.texi (Security): Add mml-unsecure-message.
+       (Mailing Lists): Index message-goto-mail-followup-to.
+
+2002-03-23  Jesper Harder <harder@ifa.au.dk>
+
+       * gnusref.tex, refcard.tex: Addition.
+
+2002-03-21  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.texi (Sending Variables): Fix typo.
+       Trivial change from Raymond Scholz <rscholz@zonix.de>
+
+2002-03-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Other Marks): Remove duplication.
+       Trivial change from David Aspinwall <aspinwall@timesten.com>
+
+2002-03-09  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi: Mention nnmaildir where appropriate; fix some typos.
+
+2002-03-01  Paul Jarc  <prj@po.cwru.edu>
+
+       * message.texi (Mailing Lists): 'use is the default for
+       message-use-mail-followup-to, not nil; 'use is also not t.
+       Mention why an unsubscribed list poster might use MFT, and how to
+       disable MFT for a single message.
+
+2002-02-25  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Splitting Mail): Addition.
+
+2002-02-23  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnusref.tex (subsection*{Notes}): Addition.
+       Suggested by Felix Natter <fnatter@gmx.net>
+
+2002-02-22  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Splitting Mail): Addition.
+
+2002-02-20  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Slave Gnusae): Addition.
+       From  David S. Goldberg <david.goldberg6@verizon.net>
+
+2002-02-18  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * emacs-mime.texi (mailcap): Addition.
+
+       * gnus.texi (Using MIME): Rename functions. Addition.
+
+2002-02-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Top): Change description of Posting Server node.
+       (Composing Messages): Ditto.
+       (Posting Server): Add some mail stuff.
+       (IMAP): Terminate @, from Emacs Gnus manual.
+       (Thwarting Email Spam): Use @sc.
+
+2002-02-16  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnusref.tex (subsection*{Notes}): Update.
+       From: Felix Natter <fnatter@gmx.net>
+
+2002-02-14  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Document Groups): Addition.
+
+2002-02-13  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * message.texi (Security): Fix @findex for the key `C-c C-m s p'.
+
+2002-02-13  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       Reinstate some changes to make latexpdf work.
+
+       * message.texi (Security): Don't use @key.
+       (Various Commands): Don't use @point.
+
+       * gnus.texi (Mail Source Specifiers): Use @uref.
+
+2002-02-13  Jesper Harder <harder@ifa.au.dk>
+
+       * message.texi, gnus.texi, emacs-mime.texi: Use small caps
+       consistently.  MIME, NOV, NNTP, HTML, IMAP are written with @sc
+       most places -- it looks better if it's the same *everywhere*.
+       @kbd instead of @code for key sequences. @file instead of @code
+       for files.
+
+       * message.texi (Various Commands): use the proper @point glyph.
+
+       * gnus.texi (Summary Mail Commands): \e,A_\e(B doesn't work.  A German
+       spelling reform changed the correct spelling to "muss" anyway (I
+       think).
+
+       * gnus.texi (Mail sources): \e,A'\e(B doesn't work. Use "section" instead.
+
+       * gnus.texi (Mail Source Specifiers): use @url.
+
+       * message.texi, emacs-mime.texi: update copyright year.
+
+2002-02-12  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Required Back End Functions): specify the lowest and
+       highest article numbers for empty groups for nnchoke-request-list
+       and nnchoke-request-group.
+
+2002-02-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.texi (Sending Variables): Addition.
+
+       * gnus.texi (Group Parameters): Add unread, not read.
+       (Archived Messages): Addition.
+
+2002-02-09  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Group Parameters): Addition.
+       From: Steinar Bang <steinar@bang.priv.no>
+
+2002-02-08  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Article Washing): Addition.
+       From: Michael Cook <michael.cook@cisco.com>
+
+2002-02-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Gnus Unplugged): Use (setq gnus-agent t).
+       (Example Setup): Ditto.
+       (Category Syntax): Require gnus-agent.
+
+2002-02-06  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Posting Styles): Addition.
+
+2002-02-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.texi (Mailing Lists): Addition.
+       * gnus.texi (Group Parameters): Addition.
+       From Sriram Karra <karra@cs.utah.edu>.
+
+2002-02-03  Karl Kleinpaste  <karl@charcoal.com>
+
+       * gnus.texi (Summary Score Commands): Added detail on "extra"
+       header scoring.
+       (Score File Format): ditto
+
+2002-02-01  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * emacs-mime.texi (Customization): Addition.
+
+2002-01-31  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Posting Styles): Addition. Suggested by
+       Michael Cook <michael@waxrat.com>.
+
+2002-01-30  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * emacs-mime.texi (Customization): Move emacs-w3m stuff backward;
+       added documentation for `mm-inline-text-html-with-w3m-keymap'.
+
+2002-01-28  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Agent Expiry): Addition.
+
+2002-01-28  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * emacs-mime.texi (Customization): Added documentation for
+       `mm-inline-text-html-with-images'.
+
+       * gnus.texi (Article Washing): Replace w3m to emacs-w3m.
+
+2002-01-26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Spool): Addition.
+
+2002-01-24  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * emacs-mime.texi (Customization): Added documentation for
+       `mm-inline-text-html-renderer'.
+
+2002-01-23  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Article Washing): Add URL about w3m.
+
+2002-01-22  Josh Huber  <huber@alum.wpi.edu>
+
+       * emacs-mime.texi (MML Definition): Added a few words about the
+       recipients option.
+       * message.texi (Security): Changed documentation to reflect use of
+       the new secure tag.
+
+2002-01-21  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Washing): Addition.
+
+2002-01-20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Document Groups): Added info on more doc types.
+       (More Threading): Move documentation here.
+
+2002-01-20  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Mailing Lists): Fix.  From Love
+       <lha@stacken.kth.se>.
+
+2002-01-20  Patric Mueller  <bhaak@gmx.net>
+
+       * gnus.texi (Group Timestamp): Typo fix.
+
+2002-01-19  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Selecting a Group): Addition.
+
+2002-01-19  Lars Magne Ingebrigtsen  <karra@cs.utah.edu>
+
+       * gnus.texi (Mail Spool): Note that the .marks files can be
+       removed.
+
+2002-01-17  Paul Jarc  <prj@po.cwru.edu>
+
+       * gnus.texi (Choosing a Mail Back End): mention nnmaildir.
+       (Comparing Mail Backends): briefly describe nnmaildir.
+
+2002-01-17  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Agent Commands): Use gnus-agent-batch instead of
+       gnus-agent-batch-fetch.
+
+2002-01-15 Tue  Jari Aalto  <jari.aalto@poboxes.com>
+
+       * gnus.texi (Really Various Summary Commands): Added commands how
+       to create nnvirtual group and and how to modify the nnvirtual
+       regexp
+
+2002-01-12  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Agent Caveats): Add agent cache.
+       (Agent Variables): Addition.
+
+2002-01-12  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Conformity): Fix typo.
+
+       * emacs-mime.texi (Flowed text, Standards): Add.
+
+2002-01-11  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.texi (Mailing Lists): Addition.
+       * gnus.texi (Group Parameters): Addition.
+       From Sriram Karra <karra@cs.utah.edu>.
+
+2002-01-10  Colin Marquardt  <c.marquardt@alcatel.de>
+
+       * gnus.texi (Changing Servers): Addition.
+
+2002-01-06  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Archived Messages): Rename
+       gnus-inews-mark-gcc-as-read to gnus-gcc-mark-as-read.
+
+       * Makefile.in (clean): Clean thumb*.
+
+2002-01-05  Harry Putnam  <reader@newsguy.com>
+
+       * gnus.texi (Score Variables): Clarify.
+
+2002-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Agent Expiry): Addition.
+       (Sorting the Summary Buffer): Addition.
+
+2002-01-05  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Conformity): Add MIME and Disposition Notifications.
+
+       * message.texi (Header Commands): Fix.  Add m-goto-from.
+       (Insertion): Add m-i-disposition-notification-to.
+
+2002-01-05  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (.latexi.pdf-x): Use thumbpdf.
+
+       * gnus.texi (Advanced Formatting): Double @'s. Use thumbpdf.
+       colorlinks=true.
+
+2002-01-05  Norman Walsh  <ndw@nwalsh.com>
+
+       * gnus-faq.texi: Fix typo.
+
+2002-01-05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Sorting the Summary Buffer): Addition.
+
+2002-01-04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Virtual Groups): Addition.
+
+2002-01-03  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Keymap): Addition.
+       (Summary Mail Commands): Fix.
+
+2002-01-02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Timestamp): Addition.  Example from Andras
+       BALI.
+       (X-Face): Addition.
+       (Advanced Formatting): Add example.
+
+2002-01-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Conformity): Add and fix.
+
+       * message.texi (Security): Mention gpg-temp-directory.
+
+       * gnus.texi (Article Washing): Link to Security section.
+       (Security): Fix.
+       (Signing and Encrypting): Renamed from Using GPG.
+       (IMAP): Fixes.
+
+2002-01-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Customizing Articles): Add crossreference links.  Add
+       gnus-body-boundary-delimiter.
+
+2002-01-01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Choosing Commands): Addition.
+       (Article Display): Update.
+       (Article Display): Addition.
+       (Article Header): New.
+       (Slow Terminal Connection): Addition.
+       (Predicate Specifiers): New.
+       (To From Newsgroups): Addition.
+       (Topic Commands): Addition.
+       Update the menus.
+       Fix some references b0rked up by the menu fixing.
+
+2001-12-31  Rui Zhu  <sprache@iname.com>
+
+       * emacs-mime.texi (Customization): Typo fix.
+
+2001-12-31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Display): Addition.
+
+       * emacs-mime.texi (Interface Functions): Addition.
 
        * gnus.texi (Using MIME): Addition.
 
-Tue Jan  6 07:22:41 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-12-30  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (X-Face): Made into own node.
+       (Article Display): New.
+
+       * emacs-mime.texi (Interface Functions): Addition.
+
+       * message.texi (Message Headers): Addition.
+
+2001-12-29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * emacs-mime.texi (Customization): Added example.
+
+       * gnus.texi (Selecting a Group): Addition.
+       (Tree Display): Addition.
+
+2001-12-26  Florian Weimer  <fw@deneb.enyo.de>
+
+       * gnus.texi (Using GPG): Remove obsolete reference to gpg-2comp.
+
+2001-12-26  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Summary Buffer Lines): Add xrefs.  Suggested by
+       Arcady Genkin <agenkin-dated-1010249095.131f22@thpoon.com>.
+
+2001-12-26  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (NNTP): Add a note for `nntp-prepare-post-hook'.
+
+2001-12-18  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog, gnus.texi, emacs-mime.texi: (oops) removed
+       buffer-file-coding-system
+
+2001-12-18 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * ChangeLog, gnus.texi, emacs-mime.texi: Local Variables `coding'
+       MUST be added!
+
+2001-12-17  Josh Huber  <huber@alum.wpi.edu>
+
+       * ChangeLog: changed coding to buffer-file-coding-system
+       * emacs-mime.texi: changed -*- magic cookie -*- to Local Variables
+       * gnus.texi: same
+       * gnus-ref.tex: same
+       * refcard.tex: same
+
+2001-12-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Saving Articles): Add muttprint.
+       (Article Commands): Mention muttprint.
+
+2001-12-15  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Virtual Groups): Fix.  From Raymond Scholz
+       <ray-2001@zonix.de>.
+
+2001-12-15 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi, emacs-mime.texi: Fix the header.
+
+2001-12-12  Didier Verna  <didier@lrde.epita.fr>
+
+       * gnus.texi (Misc Group Stuff): advertise `gnus-group-news'.
+       * gnus.texi (Summary Mail Commands): advertise
+       `gnus-summary-news-other-window'.
+
+2001-12-10  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Advanced Scoring Examples): Clarify that the
+       examples are rules, not complete score files.
+
+2001-12-09  Nevin Kapur  <nevin@jhu.edu>
+
+       * gnus.texi (Expiring Mail): Add.
+
+2001-12-05  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Splitting in IMAP): Typo.  From Colin Marquardt
+       <c.marquardt@alcatel.de>.
+
+2001-12-03 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * infohack.el (infohack): To process write-protected files safely,
+       make this buffer be writable after `find-file'.
+       From TSUCHIYA Masatoshi  <tsuchiya@namazu.org>
+
+2001-12-03 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Dependence.
+
+       * emacs-mime.texi: Add coding header.
+
+2001-12-01  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Group Line Specification, Summary Buffer Lines):
+       Cross reference Positioning Point.
+
+2001-11-25 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Limiting): Addition.
+
+2001-11-19  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Header Commands, Insertion): Use C-c C-f C-i for
+       Importance: instead of C-c C-u.  Move to Header Commands from
+       Insertion. Suggested by Per Abrahamsen <abraham@dina.kvl.dk>.
+
+2001-11-17  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Insertion): Use C-c C-u for Importance: instead of
+       C-c C-p (used by SC).
+
+2001-11-15  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Insertion): Add C-c C-p,
+       message-insert-importance-{low,high}.
+       (Various Commands): Fix typo.
+       (Insertion Variables): New section, all variables moved from
+       Commands->Insertion into this node, Variables->Insertion
+       Variables.
+
+2001-11-15 14:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Various Summary Stuff): Add gnus-newsgroup-variables.
+
+2001-11-15 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * message.texi (Security): @uref not @url.
+
+2001-11-15  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * sieve.texi (Standards): Changed @samp to @uref.
+
+       * message.texi (Security): Changed @code to @uref.
+
+       * gnus-faq.texi: Changed a lot of @file to @uref.
+
+       * emacs-mime.texi (Standards): Changed @samp to @uref.
+
+2001-11-13  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Article Washing): Add `W s'.
+
+2001-11-12  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Security, Using GPG):
+       * message.texi (Security):
+       * emacs-mime.texi (MML Definition): Add PGP.
+
+2001-11-09  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.texi (Movement): message-beginning-of-line.
+
+2001-11-07  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.texi (Examples): Add.
+       (Top): Add.
+
+       * gnus.texi (Saving Articles): Add gnus-summary-write-to-file.
+
+2001-11-07  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Misc Group Stuff): Add cross reference to Composing
+       Messages.  Suggested by "Golubev I. N." <gin@mo.msk.ru>.
+
+2001-11-04 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Use C-M- instead of M-C-.
+       * message.texi (Insertion): Ditto.
+       * sieve.texi (Managing Sieve): Ditto.
+       Suggested by Eli Zaretskii <eliz@is.elta.co.il>.
+
+2001-11-02  Simon Josefsson  <jas@extundo.com>
+
+       * dir (File): Add Sieve.
+
+       * gnus.texi (Sieve Commands): Add crossposting.
+
+2001-11-01 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * texi2latex.el (latexi-translate): Typo.
+       (latexi-translate-file): Nine in a herd is enough.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * sieve.texi (Installation): Workaround texi2latex bug (replacing
+       inside verbatim needs a \end{verbatim} earlier in the file).
+
+       * texi2latex.el (latexi-translate): Add sieve.
+
+2001-11-01 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Article Washing): Add a note.
+
+2001-11-01  Simon Josefsson  <jas@extundo.com>
+
+       * Makefile.in: Add sieve.
+
+       * gnus.texi (Misc Group Stuff):
+       (Group Parameters): Add Sieve Commands.
+       (top-level): Include Sieve manual after Emacs MIME.
+
+2001-10-31  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Group Parameters): Add integer `display'.
+       (IMAP): Fix.
+
+2001-10-31  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (NNTP): Added documentation for
+       `nntp-prepare-post-hook'.
+
+2001-10-29  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Customizing Articles): Sort list. Remove
+       duplicate. Suggested by Henrik Holm <henrik@tele.ntnu.no>.
+
+2001-10-27  Simon Josefsson  <jas@extundo.com>
+
+       * message.texi (Insertion): Fix message-yank*-prefix.
+
+2001-10-25  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Source Specifiers): More info on SSL, kerberos etc.
+       (IMAP): Ditto.  Suggested by Martin Blais <blais@discreet.com>.
+
+2001-10-23  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.texi (Posting Server): Use `native' instead of `nil' for
+       posting to native server.
+
+2001-10-22  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * dir (File): Add standard explanation header.
+
+2001-10-21  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Mail Source Specifiers): Explain more explicitly what
+       happens for the `directory' entries.  Say that mail from foo.spool
+       goes in the group foo.
+
+2001-10-19  Simon Josefsson  <jas@extundo.com>
+
+       * Makefile.in (clean): rm gnus.out.
+       (distclean): rm gnusconfig.tex (moved from "clean").
+
+       * gnus.texi (Using MIME): s/mime/MIME/ for PDF version.
+
+2001-10-19  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Finding the News): Disrecommend nnspool for Leafnode
+       users.
+
+2001-10-17 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Archived Messages): Add new line after @item.
+       From: Jesper Harder <harder@ifa.au.dk>
+
+2001-10-17 21:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Formatting Basics): Extended format specs.
+
+2001-10-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.texi (Summary Buffer Lines): Documment %( and %).
+
+2001-09-04 21:43:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Topic Sorting): Addition.
+
+2001-10-13 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * refcard.tex, gnusref.tex: Merge with the version
+       from Felix Natter <f.natter@ndh.net>
+
+2001-10-13 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * refcard.tex: Set version to Oort.
+
+       * gnusref.tex: New key bindings in Oort Gnus.
+
+2001-10-12 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (.dvi.ps): Use TEXPICTS.
+       (.latexi.dvi-x): Remove gnus.toc as well.
+
+       * gnuslogo-refcard.eps: Remove BeginProcSet.
+
+2001-10-12  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Misc Group Stuff): Add UTF-8.
+       (Misc Article): Document wash status characters.  Suggested by
+       david.goldberg6@verizon.net (David S. Goldberg).
+
+2001-10-10 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnusref.tex, refcard.tex: Use epsfig.
+
+       * gnuslogo-refcard.eps: Rename from gnuslog.refcard, and set a
+       suitable bounding box.
+
+       * Makefile.in (.dvi.ps): New rule.
+       (refcard.pdf): Use gnuslogo-refcard.eps.
+
+2001-10-09 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Add href and bookmarks for pdf version.
+
+2001-10-06 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (uninstall): Add uninstall.
+
+2001-10-05  Simon Josefsson  <jas@extundo.com>
+
+       * Makefile.in (clean): Add gnusconfig.tex.  Suggested by Henrik
+       Enberg <henrik@enberg.org>.
+
+2001-10-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Source Customization): Add.
+
+2001-10-04 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (dvi): Don't depend on tmps.
+
+2001-10-03 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * emacs-mime.texi (mailcap): rvplayer -> wavplayer.  Thanks to
+       Martin Kretzschmar <Martin.Kretzschmar@inf.tu-dresden.de>.
+
+2001-09-29  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Foreign Groups): Fix.  Add "mailman".
+       (Document Groups): Ditto.
+
+2001-09-28 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in (.texi): Remove $@ first.
+
+       * infohack.el (infohack-remove-unsupported): Remove @iflatex lines.
+       (infohack): Specify a coding-system to save info files.
+       From Katsumi Yamaoka  <yamaoka@jpl.org>
+
+2001-09-28 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnusconfig.tex.in: Use cmss if pfu is not found.
+
+2001-09-27 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * Makefile.in: Illustrated manual.
+       * gnus.texi: Put message.texi and emacs-mime.texi in the
+       illustrated manual.
+       * texi2latex.el: Ditto.
+
+2001-09-27 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Remove the extra white-space.
+
+2001-09-27 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnusconfig.tex.in: New.
+       * gnus.texi: Use it.
+       * pagestyle.sty: Don't set verbatim font.
+       * postamble.tex: Set in ...
+       * bembo.sty: Removed.
+       * Makefile.in (gnusconfig.tex): Check gnusconfig.tex.in.
+       (LATEX): Use configure.
+
+2001-09-26 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Limiting): Addition.
+
+2001-09-25 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Pterodactyl Gnus): Put @item in one line.
+
+2001-09-24 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: eps path fix.
+       * postamble.tex: Ditto.
+       * texi2latex.el: Ditto.
+
+       * Makefile.in: Move some to ps/Makefile.in.
+
+2001-09-24  Simon Josefsson  <jas@extundo.com>
+
+       * etc/*, herds/*, misc/*, picons/*, screen/*, smilies/*, xface/*:
+       New files, from pspackage.tar.gz.
+
+       * Makefile.in (distclean): Make veryclean.
+
+       * gnus.texi (Summary Mail Commands): Fix.
+       (Summary Post Commands): Fix.
+       (The Manual): Fix.
+
+2001-09-23 02:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Use "back end".
+
+2001-09-23  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Top): Move IMAP up from "Other Sources" to "Select
+       Methods".
+       (Charsets): Update default value.
+       (Finding the Parent): Add nnimap.
+       (Security): Add.
+       (Mailing List): Add.
+       (Archived Messages): Comment out XEmacs 19 stuff.
+       (Using GPG): Add reference to message manual.
+       (Direct Functions): Mention OpenSSL as well as SSLeay.
+       (Mail Source Specifiers): Add recent IMAP :stream and
+       :authentication.
+       (Agent Commands): Fix.
+       (GroupLens): Add URL and note about this being historical.
+       (Wide Characters): Update default value.
+       (Picon Requirements): Remove old XEmacs 19 stuff.
+
+2001-09-22  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Other Marks): Add Recent.
+
+2001-09-14  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Folders): Add.
+
+2001-09-11  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Delayed Articles): Fix.  Suggested by Paul Jarc
+       <prj@po.cwru.edu>.
+
+2001-09-08  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (MIME Commands): Add gnus-buttonized-mime-types.
+
+2001-09-08  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Topic Commands): Make this the first subsection of
+       `Group Topics'.  Rearrange keys to mention the most important keys
+       first and to have subsections.  Add some more explanation for
+       C-k/C-y.
+       (Group Buffer): Add comment from Alex Schroeder as todo item.
+
+2001-09-06  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Fancy Mail Splitting): Mention `delete' near the
+       explanation of `junk'.
+
+2001-09-04  Katsumi Yamaoka  <yamaoka@jpl.org>
+
+       * gnus.texi (Optional Backend Functions): The default function to
+       make a date format is `message-make-date', which should produce a
+       time zone.
+
+2001-09-04  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Optional Backend Functions): More detail about the
+       DATE arg for nnchoke-request-newgroups.  Reported by Paul Jarc.
+
+2001-09-01  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Hooking New Backends Into Gnus): Say where to put the
+       call for gnus-declare-backend.  Add an index entry for
+       gnus-declare-backend.  Suggested by Paul Jarc.
+
+2001-08-29  Simon Josefsson  <jas@extundo.com>
+       From Anders Jackson <jackson@hig.se>
+
+       * gnus.texi (Group Parameters): Fix.
+
+2001-08-27  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Archiving Mail): Add.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Mail Spool): Add marks.
+       (MH Spool): Doesn't use marks file.
+       (Mail Folders): Add marks.
+
+2001-08-25  Simon Josefsson  <jas@extundo.com>
+       From Henrik Enberg <henrik@enberg.org>
+
+       * gnus.texi (Group Parameters): Fix.
+
+2001-08-24 16:03:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Parameters): Fix.
+
+2001-08-24  Simon Josefsson  <jas@extundo.com>
+
+       * Makefile.in (latexps): Make tmps.
+
+2001-08-24  Simon Josefsson  <jas@extundo.com>
+       From Jesper Harder <harder@ifa.au.dk>
+
+       * Makefile.in (latexps): Escape {.
+
+       * splitindex: Ditto.
+
+2001-08-23 19:22:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Parameters): Fix.
+       (Group Parameters): Addition.
+       (Limiting): Addition.
+
+2001-08-21 23:55:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Score Variables): Fix.
+
+2001-08-20  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Delayed Articles): New section.  Documents
+       gnus-delay.el.
+       (Fancy Mail Splitting): Say that nnmail-cache-accepted-message-ids
+       must be non-nil for splitting with parents to work.
+
+2001-08-19 17:31:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Other Marks): Addition.
+       (Positioning Point): New.
+       (Tabulation): New.
+
+2001-08-19  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Getting Started Reading Mail): Use (nnml "") rather
+       than (nnml "private") as the example server specification.  This
+       way, the example group names a few paragraphs further down are
+       correct, and I expect that most people are going to use the empty
+       string as name, anyway.  Please holler if that is wrong.
+
+2001-08-18  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (Optional Backend Functions): Remove `set'
+       request-set-mark action.
+
+2001-08-18 00:40:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Wide Characters): New section.
+
+2001-08-17  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi: Replace 20,20 with 23,23 for
+       gnus-summary-line-format.
+
+2001-08-17 14:24:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Parameters): Document regexp substitution.
+       (Group Parameters): Addition.
+
+2001-08-11 23:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Nevin Kapur <nevin@jhu.edu>
+
+       * gnus.texi (September Gnus): Typo.
+
+2001-08-12  Simon Josefsson  <jas@extundo.com>
+       Suggested by Kai.Grossjohann@CS.Uni-Dortmund.DE
+
+       * gnus.texi (Other Marks): Add recent.
+       (Optional Backend Functions): Add forward and recent.
+
+2001-08-12  Kai Grossjohann  <grossjoh@ls6.informatik.uni-dortmund.de>
+
+       * gnus.texi (Window Layout): Renamed from `Windows
+       Configuration'.  After all, we're not talking about Microsoft.
+       Suggested by Barry Fishman.
+
+2001-08-11  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Summary Mail Commands): Remove duplicate explanation
+       of `S W'.  Reported by Norbert Koch.
+
+2001-08-09 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Benjamin Rutt <brutt@bloomington.in.us>
+
+       * gnus.texi (Troubleshooting): Addition.
+
+2001-08-09  Simon Josefsson  <jas@extundo.com>
+       From Benjamin Rutt <brutt@bloomington.in.us>
+
+       * gnus.texi (Mail Backend Variables): Fix.
+
+2001-08-04  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Summary Buffer Lines): Mention `gnus-goto-colon'.
+
+2001-08-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Backend Interface): Explain about article numbers.
+       Suggested by Paul Jarc.
+
+2001-08-02 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * emacs-mime.texi (Non-MIME): Addition.
+
+       * gnus.texi (Group Parameters): Addition.
+       (Mailing List): Addition.
+
+2001-08-01  Simon Josefsson  <jas@extundo.com>
+
+       * texi2latex.el (latexi-translate-file): Don't use point-at-bol.
+       (latexi-translate-file): Translate some more things, including
+       some hardcoded things that cause problems for LaTeX.  From Jesper
+       Harder <harder@ifa.au.dk>.
+
+2001-07-31  Simon Josefsson  <jas@extundo.com>
+
+       * bembo.sty: New file.
+
+       * texi2latex.el (latexi-translate-file): Support @noindent.
+
+       * gnus-faq.texi (Reading News FAQ): Fix (@email -> @samp).
+
+2001-07-28 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Janne Rinta-Manty <rintaman@cs.helsinki.fi>
+
+       * gnus.texi (Read Articles): Typo.
+
+2001-07-25 22:22:22  Raymond Scholz  <rscholz@zonix.de>
+
+       * gnus.texi (Fancy Mail Splitting): New variable
+        nnmail-split-fancy-with-parent-ignore-groups
+
+2001-07-24  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Duplicates): Make split method regexp more specific,
+       in case other `Gnus-Warning' headers are added in the future.
+       Suggested by Karl Kleinpaste.
+
+2001-07-23 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Karl Kleinpaste <karl@charcoal.com>
+
+       * gnus.texi (Summary Buffer Lines): Add %B.
+
+2001-07-20 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Jesper Harder <harder@myrealbox.com>
+
+       * message.texi (Insertion): Addition.
+
+2001-07-19 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Charsets): Addition.
+
+2001-07-17 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Searching for Articles): Raw articles.
+
+2001-07-16  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.texi (Insertion): Refer to gnus-cite-attribution-suffix.
+
+2001-07-13 12:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (RSS): Add.
+       From Christoph Conrad <cc@cli.de>.
+
+2001-07-13 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Incorporating Old Mail): Add index.
+
+2001-07-13 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Group Parameters): Add.
+
+2001-07-04  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Add.
+
+2001-07-04  Didier Verna  <didier@lrde.epita.fr>
+
+       * gnus.texi (Example Methods): use the new nntp-open-connection
+       methods in the examples.
+       * gnus.texi (NNTP): update for the new nntp-open-connection methods.
+       * gnus.texi (Direct Functions): new node.
+       * gnus.texi (Indirect Functions): new node.
+       * gnus.texi (Common Variables): new node.
+
+2001-06-27  Simon Josefsson  <jas@extundo.com>
+       From Ralph Schleicher <rs@nunatak.allgaeu.org>
+
+       * gnus.texi (MIME Commands): Add.
+
+2001-06-24  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Summary Score Commands): Say that some commands
+       create ADAPT files.
+
+2001-06-23  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Duplicates): Contents of Gnus-Warning header have
+       changed.  Reported by Peter J Acklam.
+
+2001-06-19  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Fix `imtest' discussion.
+
+       * gnus-faq.texi (Frequently Asked Questions): Fix URL.
+
+2001-06-17  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Group Line Specification): Explain why %t is only an
+       estimate.
+
+2001-06-16  Simon Josefsson  <jas@extundo.com>
+
+       * gnus.texi (IMAP): Add.
+
+2001-06-13 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Article Washing): Add.
+
+2001-06-11 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: behaviour -> behavior. Suggested by Eli Zaretskii
+       <eliz@is.elta.co.il>.
+
+2001-06-09 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Apply "overfull hbox" patch from Eli Zaretskii
+       <eliz@is.elta.co.il>.
+
+2001-06-07 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (RSS): Add.
+
+2001-05-31 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Setting Marks): Add.
+
+2001-05-27  Simon Josefsson  <simon@josefsson.org>
+
+       * message.texi (Insertion): Add message-yank-cited-prefix.
+
+2001-05-22  Simon Josefsson  <simon@josefsson.org>
+       From Jesper Harder <harder@ifa.au.dk>
+
+       * gnus.texi (Article Washing): Add.
+
+2001-05-16  Simon Josefsson  <simon@josefsson.org>
+       From Jesper Harder <harder@ifa.au.dk>
+
+       * texi2latex.el (latexi-translate-file): Also exchange ref.
+
+       * gnus.texi: Add \gnusref and \gnusuref.
+
+2001-05-16  Simon Josefsson  <simon@josefsson.org>
+       From Raymond Scholz <ray-2001@zonix.de>
+
+       * gnus.texi (Using MIME): Add and fix.
+
+2001-05-05  Florian Weimer  <fw@deneb.enyo.de>
+
+       * gnus.texi (IMAP): Remove double paragraph (suggest by Norbert
+       Koch), fix NNTP reference.
+
+2001-05-04 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       Suggested by Dan Christensen <jdc@uwo.ca>
+
+       * gnus.texi (Mail Group Commands): Add pxref.
+       (Group Maintenance): Ditto.
+       (Topic Commands): Ditto.
+       (Expiring Mail): Typo.
+
+2001-05-04 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Raymond Scholz <ray-2001@zonix.de>
+
+       * gnus.texi (Summary Buffer Lines): Mention the meaning of a
+       colon.
+
+2001-05-03 07:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Sriram Karra <karra@cs.utah.edu>.
+
+       * gnus.texi: Add default value.
+
+2001-05-03 06:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Using GPG): Use example environment.
+
+2001-05-02 17:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Expunging mailboxes): Typo.
+
+2001-04-15 19:38:54  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail and Post): Fix.
+
+2001-04-29 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Remove a few The's.
+       (RSS): New.
+
+2001-04-26  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Unread Articles): Say that dormants are similar to
+       ticked.
+
+2001-04-13  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Sorting Groups): Note `C-k' and `C-y' for manually
+       moving groups around.
+
+2001-04-07  Ryan Yeske <rcyeske@vcn.bc.ca>
+
+       * gnus.texi (Splitting in IMAP): Fix.
+
+2001-04-07  Jesper Harder <harder@ifa.au.dk>
+
+       * gnus.texi (More Threading): Fix.
+
+2001-04-01 00:32:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (S): Renamed.
+       (Summary Sorting): Addition.
+
+2001-03-31 00:40:44  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Other Marks): Additon.
+       (The End): Remove "The" from menus.
+
+2001-03-30 23:34:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Adaptive Scoring): Addition.
+       (Summary Mail Commands): Addition.
+
+2001-03-17  Matthias Wiehl  <mwiehl@gmx.de>
+
+       * message.texi (Security): Typos.
+
+2001-03-15  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Hiding Headers): Typos.  Reported by Sriram Karra
+       <karra@cs.utah.edu>.
+
+2001-03-11  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * message.texi (Message Headers): Update doc for
+       `message-generate-headers-first'.
+
+2001-03-14 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Nevin Kapur <nevin@jhu.edu>
+
+       * gnus.texi (Mail Source Specifiers): Fix.
+
+2001-03-04 09:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From "Yair Friedman (Jerusalem)" <YAIRFR@amdocs.com>
+
+       * infohack.el (infohack): Set max-lisp-eval-depth to 600+.
+
+2001-03-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+
+       * gnus.texi (Posting Styles): Posting styles have (NAME VALUE),
+       not (NAME . VALUE).
+
+2001-02-25 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+       From Michael Totschnig <michaelt@supernet.ca>.
+
+       * gnus.texi (Article Fontisizing): Fix.
+
+2001-02-23  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus.texi (Posting Server): Fix, due to change of default value
+       of `gnus-post-method' to `current'.
+
+2001-02-23 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi: Remove double words. From Gerd Moellmann.
+
+       * infohack.el (batch-makeinfo): New.
 
-       * gnus.texi (Batching Agents): New.
+       * Makefile.in (EMACSINFO): Use it.
 
-1998-01-04  Christoph Wedler  <wedler@fmi.uni-passau.de>
+2001-02-17 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Newest Features): Delete spaces after @end example.
-       In XEmacs, `texinfo-format-buffer' would bug out.
+       * gnus.texi (Posting Styles): Doc fix.
 
-Sun Jan  4 12:04:45 1998  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-16  Simon Josefsson  <sjosefsson@rsasecurity.com>
 
-       * gnus.texi (Conformity): Removed GNKSA.
+       * gnus.texi (Optional Backend Functions): Fix case.
 
-Sun Dec 14 11:06:23 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-14  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Adaptive Scoring): Addition.
+       * gnus.texi (Unread Articles): Say that Gnus itself never expires
+       ticked articles.  Suggested by M D Greenhow
+       mdg@greenhow36.clara.co.uk.
 
-1997-11-26  SL Baur  <steve@altair.xemacs.org>
+2001-02-13 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Insertion): Fix typo.
-       (Responses): Ditto.
-       (Reply): Ditto.
+       * gnus.texi (Saving Articles): Addition.
 
-Wed Nov 26 12:57:00 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-14 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Insertion): Addition.
+       * gnus.texi (Group Parameters): Addition.
 
-Wed Nov 26 12:55:15 1997  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+2001-02-11 13:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Insertion): Addition.
+       * gnus.texi (Choosing Commands): Move `G j' here.
 
-Wed Nov 26 12:36:08 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-09 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Responses): New.
-       (Appendices): New.
+       * gnus.texi (Pterodactyl Gnus): Added.
+       (Newest Features): Removed. Suggested by RMS.
 
-       * gnus.texi (Group Info): Fix.
+2001-02-08  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Tue Nov 25 17:53:55 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Group Parameters): Mention `G c' in addition to `G p'.
 
-       * gnus.texi (Article Date): Addition.
+2001-02-07  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Mon Nov 24 16:01:20 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (To From Newsgroups): Make it clear where to put the
+       sample code.  Suggested by Dan Jacobson.
 
-       * gnus.texi (Faces & Fonts): New.
+       * gnus.texi (Mail Source Specifiers, IMAP, Agent and IMAP):
+       Improve IMAP discussion.
 
-Mon Oct 13 00:08:06 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-07  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Agent Commands): Addition.
+       * message.texi (Message Headers): `message-generate-headers-first'.
 
-Sun Oct 12 16:50:23 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-02-06 19:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Article Washing): Addition.
-       (Group Highlighting): New.
-       (Canceling and Superseding): Addition.
+       * gnus.texi (Using GPG): Key binding.
 
-Wed Oct  1 18:37:55 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.texi (Security): Ditto.
 
-       * gnus.texi (Startup Files): Addition.
+2001-02-06 18:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Sat Sep 27 09:37:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Top): Add Using GPG.
 
-       * message.texi (Sending Variables): Fix.
+2001-02-02  David Masterson <dmasters@Rational.Com>
 
-       * gnus.texi (Choosing Commands): Addition.
+       * gnus.texi (The Server is Down): Add link to Group Levels.
 
-Sat Sep 27 05:56:44 1997  Hallvard B. Furuseth  <h.b.furuseth@usit.uio.no>
+2001-01-24  Simon Josefsson  <sj@extundo.com>
 
-       * gnus.texi: Various fixes.
+       * gnus.texi (Mail Source Specifiers): Add IMAP :program, fix POP
+       :program typo.
 
-Sat Sep 27 04:24:41 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-15 16:15:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * message.texi (Various Commands): Addition.
+       * gnus.texi (The Active File): Only old versionf of leafnode
+       doesn't do some.
 
-Wed Sep 24 02:38:21 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-23 23:28:08  Satomi Suzuki  <pan@mba.nifty.ne.jp>
 
-       * gnus.texi (Example Setup): Wrong info.
-       (SOUP Groups): Addition.
-       (Contributors): Addition.
+       * message.texi (message-ignored-news-headers): Add "X-Draft-From:".
+       (message-ignored-mail-headers): Ditto.
 
-1997-09-22  SL Baur  <steve@altair.xemacs.org>
+2001-01-21  Raymond Scholz <ray-2001@zonix.de>
 
-       * gnus.texi (Finding the Parent): Fix typo.
-       (NoCeM): Fix typos.
+       * message.texi: Rename X-Mailer and X-Newsreader to User-Agent.
 
-Tue Sep 23 07:05:48 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-19 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (NoCeM): Addition.
-       (Finding the Parent): Addition.
+       * infohack.el: New file.
 
-Mon Sep 22 06:13:00 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * Makefile.in: Use it.
 
-       * gnus.texi (Filling In Threads): Addition.
-       (Finding the Parent): Addition.
+2001-01-18 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Sun Sep 21 04:35:56 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Hiding Headers): Add.
 
-       * gnus.texi (NNTP): Addition.
-       (Hiding Headers): Addition.
-       (Symbolic Prefixes): New.
-       (Extended Interactive): New.
-       (Summary Score Commands): Addition.
+       * emacs-mime.texi: Set dircategory to Emacs.
 
-Sat Sep 20 20:53:43 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-16  Jesper Harder <harder@ifa.au.dk>
 
-       * gnus.texi (Startup Variables): Addition.
+       * gnus.texi (Group Line Specification): Add.
 
-1997-09-16  SL Baur  <steve@altair.xemacs.org>
+2001-01-15 16:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi: Correct typo.
+       * gnus.texi (Using GPG): Doc fix.
 
-Wed Sep 17 02:32:56 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-15  Simon Josefsson  <simon@josefsson.org>
 
-       * gnus.texi (Customizing Threading): Broken up into five nodes. 
-       (Article Washing): Addition.
+       * message.texi (Security): Requires OpenSSL 0.9.6+.
 
-       * message.texi (Various Commands): Add.
+2001-01-13  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Tue Sep 16 04:04:03 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Mail): Move explanation of
+       `message-send-mail-partially-limit' to message.texi
 
-       * gnus.texi (Example Setup): New.
+       * message.texi (Mail Variables): Ditto.
 
-Mon Sep 15 23:10:05 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-10 15:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Customizing Threading): Addition.
+       * gnus.texi (Article Washing): makeinfo 1.69 doesn't grok `anchor'.
 
-Sun Sep 14 21:59:07 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-07 18:18:53  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Outgoing Messages): New.
-       (Score File Format): Note.
-       (Subscription Methods): Fix.
-       (Starting Up): Fix.
-       (Threading): Add.
+       * gnus.texi (myself): Quote .
 
-Sat Jul 19 23:02:03 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-05  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Followups To Yourself): \\(_-_\\)?
+       * gnus.texi (Choosing Commands): Add xref for redisplaying the
+       group.  Suggestion from Galen Boyer <galenboyer@yahoo.com>.
+       (The Summary Buffer): Mention reselecting the current group in the
+       menu.  Suggestion from Galen Boyer <galenboyer@yahoo.com>.
+       (Followups To Yourself): Add Lisp example.
 
-Sat Jul 12 16:29:35 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-05 06:53:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Picon Configuration): Moved Picons to under XEmacs. 
-       (Smileys): New section.
+       * emacs-mime.texi (time-date): Addition.
+       (time-date): Addition.
 
-Fri Jul 11 11:58:20 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2001-01-04 22:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (NNTP): Addition.
+       * gnus.texi (Newest Features): uref, not url.
 
-Tue Jun 17 23:52:17 1997  Justin Sheehy  <dworkin@ccs.neu.edu>
+       * texi2latex.el (latexi-translate-file): Ignore anchor.
 
-       * gnus.texi (Group Parameters): Addition.
+2001-01-04  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Sun May 25 14:40:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Article Washing): Refer to `Customizing Articles' for
+       permanent changes.  Suggested by Russell Marks (russel dot marks
+       at ntlworld dot com).
 
-       * gnus.texi (Expiring Mail): Addition.
+2001-01-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Sat May 24 05:26:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Article Washing): Mention `C-u g' as a sort of
+       anti-washing.
 
-       * gnus.texi (Score File Format): Update.
+2001-01-01 11:40:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Tue May 20 21:56:03 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (extensions): Removed.
 
-       * gnus.texi (Document Server Internals): Typo.
+2000-12-31 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Sun May 18 05:59:24 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * texi2latex.el (latexi-translate-file): Understand uref.
 
-       * gnus.texi (Topic Commands): Addition.
+2000-12-30  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Sun May 11 20:09:24 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Selecting a Group): Explain in more detail, what a
+       prefix arg means for SPC.  Refer people to M-g command from
+       summary buffer.  Suggested by Paul Repacholi
+       <prep@prep.synonet.com> and Dan Jacobson <jidanni@kimo.com.tw>.
 
-       * gnus.texi (Article Hiding): Change.
+2000-12-29 21:43:20  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Thu May  8 23:48:36 1997  James Troup  <J.J.Troup@comp.brad.ac.uk>
+       * message.texi (Spelling): New.
 
-       * gnus.texi (Saving Articles): Typo.
+2000-12-29 10:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Wed May  7 19:00:48 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * texi2latex.el (latexi-translate-file): Support srcdir.
+       (latexi-translate-file): Understand ifnottex, dircategory, and
+       direntry. Set coding-system-for-write to iso-8859-1.
 
-       * gnus.texi (Saving Articles): Addition.
+       * Makefile.in: Fix for srcdir.
 
-Wed May  7 19:00:43 1997  Mark Boyns  <boyns@sdsu.edu>
+       * gnus.texi (NoCeM): Use file instead of uref.
+       (Mail Source Specifiers): Use subsubsection instead of
+       subsubheading.
 
-       * gnus.texi (Saving Articles): Addition.
+2000-12-29 01:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Thu May  1 14:06:57 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Top): Set version to Oort Gnus v0.01.
 
-       * gnus.texi (Score File Format): Fix.
+       * Makefile.in (install): The info files are in the current
+       directory.
 
-Sun Apr 27 11:11:43 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-12-29  Christopher Splinter  <chris@splinter.inka.de>
 
-       * gnus.texi (NNTP): Addition.
+       * gnus.texi (Customizing Articles): Added documentation for
+       `gnus-treat-hide-citation-maybe', `gnus-treat-date-iso8601' and
+       `gnus-treat-date-user-defined'.
 
-Sat Apr 12 16:51:32 1997  Robert Bihlmeyer  <robbe@orcus.priv.at>
+2000-12-29 00:38:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Thwarting Email Spam): Addition.
+       * gnus.texi (Posting Styles): Addition.
 
-Tue Apr 15 16:11:38 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-12-28 20:04:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * message.texi (Various Message Variables): Addition.
+       * message.texi (Buffer Entry): New section.
 
-       * gnus.texi (Thwarting Email Spam): Addition.
+2000-12-22  Christopher Splinter  <chris@splinter.inka.de>
 
-Sat Apr 12 00:26:47 1997  Francois Felix Ingrand  <felix@laas.fr>
+       * gnus.texi (Group Parameters): Add documentation for the `banner'
+       group parameter.
 
-       * gnus.texi (NoCeM): Addition.
+2000-12-22 11:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Thu Apr 10 21:25:14 1997  Hrvoje Niksic  <hniksic@srce.hr>
+       * gnus.texi (Adaptive Scoring): Use setq by Thomas Seck
+       <tmseck@web.de>.
 
-       * gnus.texi (Emacs/XEmacs Code): Addition.
+2000-12-21  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Thu Apr 10 20:45:47 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Article Washing): Doc addition by Paul Stevenson
+       <p.stevenson@surrey.ac.uk>.
 
-       * gnus.texi (Group Information): Fix.
+2000-12-10  Jim Meyering  <meyering@lucent.com>
 
-Wed Apr  2 11:48:44 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * Makefile.in (.texi): Use `-I $(srcdir)' with `makeinfo' so that
+       non-srcdir builds work.
 
-       * gnus.texi (Sorting): Use total score.
+2000-11-29 20:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Tue Apr  1 11:44:57 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Fancy Mail Splitting): Add.
 
-       * gnus.texi (Subscription Methods): Addition.
-       (Group Info): Addition.
-       (Gnus Utility Functions): New.
-       (Thwarting Email Spam): Addition.
+2000-11-20 08:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Mon Mar 31 16:15:54 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Archived Messages): Add.
 
-       * message.texi (Various Message Variables): Addition.
+2000-11-20 Jochen K\e,A|\e(Bpper <jochen@pc1.uni-duesseldorf.de>
 
-Sun Mar 23 02:16:19 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Security): Fix typo.
 
-       * gnus.texi (Thwarting Email Spam): New.
-       (Unavailable Servers): Fix.
+2000-11-20 00:00:00  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Wed Mar 19 15:45:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi: Add.
 
-       * gnus.texi (Various Summary Stuff): Addition.
-       (Mail Backend Variables): Addition.
+2000-11-12  Florian Weimer  <fw@deneb.enyo.de>
 
-Tue Mar 18 14:43:32 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.texi (Security): Fixed typo, change "PGP" to "OpenPGP".
 
-       * gnus.texi (Article Washing): Not addition.
+2000-11-12  David Edmondson  <dme@dme.org>
 
-Mon Mar 17 16:15:54 1997  Philippe Schnoebelen  <Philippe.Schnoebelen@lsv.ens-cachan.fr>
+       * gnus.texi: remove `gnus-cite-prefix-regexp'.
 
-       * Makefile (install): Install properly.
+       * message.texi (Insertion): move `gnus-cite-prefix-regexp' from
+       gnus.texi to here and rename to `message-cite-prefix-regexp'.
 
-Fri Mar 14 21:00:33 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-11-11  Simon Josefsson  <sj@extundo.com>
 
-       * gnus.texi (Group Parameters): Addition.
-       (Expiring Mail): Addition.
+       * message.texi (Security): Add.
 
-Wed Mar 12 06:57:14 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * emacs-mime.texi (MML Definition): Add sign, encrypt, keyfile and
+       certfile.
 
-       * gnus.texi (Various Various): Addition.
+2000-11-07  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Sat Mar  8 03:41:47 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Mail Group Commands): `gnus-move-split-methods' uses
+       group names as target, where `gnus-split-methods' uses file
+       names.  Suggested by Nevin Kapur.
 
-       * gnus.texi (Group Parameters): Added example.
-       (Duplicates): Fix.
+2000-11-07  Martin Buchholz <martin@xemacs.org>
 
-Fri Mar  7 10:49:43 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi: Doc fix.
 
-       * Makefile: New "install" target.
+2000-11-01  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Thu Mar  6 08:01:37 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Fancy Mail Splitting): Explain
+       `nnmail-split-fancy-with-parent'.
 
-       * gnus.texi (Mail and Procmail): Fix.
+2000-11-01 09:12:24  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Sun Mar  2 02:08:40 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Finding the News): @env is not supported in texinfo 3.12.
 
-       * gnus.texi (Startup Files): Addition.
-       (Score File Format): Fix.
+2000-10-31  Jorge Godoy <godoy@conectiva.com>
 
-Fri Feb 28 23:23:31 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi: gnus-gpg document.
 
-       * gnus.texi (Archived Messages): Clarify.
-       (Fuzzy Matching): New.
+2000-10-31  Simon Josefsson  <sj@extundo.com>
 
-Mon Feb 24 23:41:57 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (NNTP): Explain `port'.
 
-       * message.texi (Compatibility): New.
+2000-10-30  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Thu Feb 20 03:29:17 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Archived Messages): Explain what happens when group
+       names mentioned in `gnus-message-archive-group' contain a select
+       method.
 
-       * gnus.texi (Foreign Groups): Addition.
+2000-10-28  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Wed Feb 19 02:57:51 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Group Levels): Explain meaning of subscribed,
+       unsubscribed, zombie, killed groups.
 
-       * gnus.texi (Server Variables): New.
+2000-10-26  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Sun Feb 16 15:43:34 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Gnus Development): nnmail-delete-incoming -->
+       mail-source-delete-incoming.  Suggested by Karl Kleinpaste
+       <karl@charcoal.com>.
 
-       * gnus.texi (Mail Backend Variables): Fix.
+2000-10-18  Dave Love  <fx@gnu.org>
 
-       * message.texi (Various Message Variables): Addition.
+       * gnus.texi (NoCeM): Update.
 
-Mon Feb 10 07:18:16 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-10-17  Simon Josefsson  <simon@josefsson.org>
 
-       * gnus.texi (Article Commands): Addition.
+       * gnus.texi (IMAP): Add.
 
-Mon Feb  3 19:59:10 1997  Paul Franklin  <paul@cs.washington.edu>
+2000-10-05  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus-group.el (gnus-group-edit-group): Allow editing of bad
-       groups.
+       * gnus.texi (Windows Configuration): add examples; first example
+       suggested by Stein A. Str\e,Ax\e(Bmme <stromme@mi.uib.no>.  (The actual
+       Lisp code is also from him.)
 
-Wed Feb  5 02:00:46 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-10-07  Dave Love  <fx@gnu.org>
 
-       * message.texi (Mail Variables): Change.
+       * doclicense.texi: New file.
 
-Tue Feb  4 02:33:31 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-10-07 16:50:14  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Mail Aliases): New.
+       * Makefile.in: Use install-info.
 
-       * gnus.texi (Splitting Mail): Addition.
+2000-10-06 14:38:27  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Mon Feb  3 07:31:47 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.texi (Message Headers): Add.
 
-       * gnus.texi (Mode Lines): Addition.
+2000-10-04 09:23:49  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Mon Jan 27 17:51:29 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Article Hiding): Add.
+       (Using MIME): Add.
 
-       * gnus.texi (Highlighting and Menus): Removed
-       `gnus-display-type'. 
+2000-09-30  Simon Josefsson  <simon@josefsson.org>
 
-Sat Jan 25 08:09:30 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Agent and IMAP): Add.
+       (Splitting in IMAP): Fix.
 
-       * gnus.texi (The Active File): Addition.
+2000-09-29  Simon Josefsson  <simon@josefsson.org>
 
-Fri Jan 24 05:07:28 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Converting Kill Files): Fix URL.
+       (Posting Styles): Fix regexp.
+       (Mail Source Specifiers): Fix.
 
-       * gnus.texi (Summary Mail Commands): Addition.
-       (Required Backend Functions): Deletia.
-       (Article Washing): Addition.
-       (Summary Mail Commands): Addition.
+2000-09-29 12:53:27  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Mon Jan 20 22:19:40 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * Makefile.in: A workaround for @ifnottex.
 
-       * gnus.texi (Followups To Yourself): Fix.
+2000-09-29 12:36:13  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-Fri Jan 17 00:55:51 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi: Remove @c lines in the directory due to a bug in
+       makeinfo 1.68 (GNU texinfo 3.12).
 
-       * gnus.texi (NoCeM): Update.
+2000-09-22  Dave Love  <fx@gnu.org>
 
-Wed Jan 15 02:23:03 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * message.texi, gnus.texi, emacs-mime.texi: Convert to GFDL.
 
-       * gnus.texi (Mail Group Commands): Fix.
+2000-09-20 John H. Palmieri  <palmieri@math.washington.edu>
 
-Tue Jan  7 09:36:36 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (Mail Source Customization): Document of
+       mail-source-incoming-file-prefix.
 
-       * gnus.texi (Summary Buffer Lines): Correction.
+2000-09-20  Simon Josefsson  <simon@josefsson.org>
 
-Mon Jan  6 22:49:12 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (IMAP): Add examples.
 
-       * gnus.texi (NoCeM): Addition.
+2000-09-19  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-Fri Jan  3 18:13:02 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi (IMAP): Add pointer to description of ~/.authinfo file
+       format.
 
-       * message.texi (Various Commands): Addition.
+2000-09-17 Felix Natter  <f.natter@ndh.net>
 
-Thu Jan  2 16:12:27 1997  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnusref.tex: New version.
 
-       * gnus.texi (Optional Backend Functions): Fix.
+       * refcard.tex: New version.
 
-Mon Dec 16 13:53:28 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-09-17 18:03:52  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Exiting the Summary Buffer): Update.
+       * gnus.texi (Article Hiding): Doc fix as suggested by Felix Natter
+       <fnatter@gmx.net>.
 
-Fri Dec 13 01:04:41 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-06-22 Michael Totschnig <michaelt@supernet.ca>
 
-       * gnus.texi (Limiting): Addition.
+       * gnus.texi (Agent Basics): Doc fix.
 
-Sat Dec  7 21:10:23 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-09-14 Jason R. Mastaler <jason@mastaler.com>
 
-       * gnus.texi (Example Methods): Addition.
+       * gnus.texi (Mail Source Specifiers): Use $HOME.
 
-Fri Dec  6 12:38:14 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-08-14  Kai Grossjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Group Parameters): Update.
+       * gnus.texi (Mail Source Specifiers): Replace `@paragraph' with
+       `@subsubheading'.
 
-1996-11-30  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-08-14  Kai Grossjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Terminology): Addition.
+       * gnus.texi (Mail Source Specifiers): Try to document the
+       interface to the functions called via (among others) the
+       `:function' keyword.
 
-Wed Nov 27 03:13:05 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-08-13 20:00:35  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Selecting a Group): Addition.
+       * gnus.texi (Topic Commands): Fix typo.
 
-Tue Nov 26 12:42:47 1996  Martin Buchholz  <mrb@eng.sun.com>
+2000-08-13 20:20:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * message.texi: Typo fixes and stuff.
+       * gnus.texi (Topic Commands): Addition.
 
-Thu Nov 21 17:45:57 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-08-11  Kai Grossjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
-       * gnus.texi (Canceling and Superseding): Fix.
+       * gnus.texi (Expiring Mail): Extend documentation of variable
+       `nnmail-expiry-target' and of group parameter `expiry-target'.
+       Explain interaction between these.  Add Lisp example for setting
+       `nnmail-expiry-target'.
 
-Wed Nov 20 15:42:36 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-08-04  Andreas Oeldenberger <andreas.oeldenberger@gmx.net>
 
-       * gnus.texi (New Groups): Addition.
-       (Summary Sorting): Addition.
+       * message.texi (Forwarding): Fix.
 
-Tue Nov 19 20:54:16 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-07-15  Simon Josefsson  <simon@josefsson.org>
 
-       * gnus.texi (Scanning New Messages): Addition.
+       * gnus.texi (nnimap-authinfo-file):
+       (gnus-invalid-group-regexp): Add.
+       (Mail Source Specifiers): Fix.
+       (IMAP): Fix.
+       (Agent Basics): Fix.
 
-Sat Nov  9 06:04:22 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-07-12 19:37:19  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Group Parameters): Addition.
+       * gnus.texi (Article Washing): Add keystroke `t'.
 
-Fri Nov  8 04:01:06 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-07-12 15:49:34  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Article Fontisizing): New.
-       (Fancy Mail Splitting): Addition.
-       (Summary Post Commands): Addition.
-       (Mail Spool): Addition.
-       (Server Commands): Addition.
-       (Fancy Mail Splitting): Addition.
+       * Makefile.in: Add EMACS. Test -x "$(MAKEINFO)" does not work.
+       Use sed instead of perl (suggested by Nick V. Pakoulin).
 
-Wed Nov  6 06:39:44 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-07-03 00:24:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Misc Article): Addition.
-       (Emacsen): Updated.
+       * gnus.texi (Splitting Mail): Mention gnus-summary-respool-trace.
+       (Searching for Articles): Fix.
+       (Newest Features): Fix.
+
+2000-06-28  Simon Josefsson  <simon@josefsson.org>
+
+       * gnus.texi (Splitting in IMAP): Update.
+
+2000-05-19 15:18:32  Dmitry Yaitskov <dimas@home.com>
+
+       * message.texi (Reply): Doc fix.
+
+2000-05-17 00:50:29  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Listing Groups): Addition.
 
-Wed Nov  6 03:52:05 1996  C. R. Oldham  <cro@nca.asu.edu>
+2000-05-16 21:46:40  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
-       * Makefile (.texi.dvi): Fix rule.
+       * gnus.texi (Misc Group Stuff): Addition.
+       (Article Washing): Ditto.
 
-Tue Nov  5 10:45:39 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+2000-05-15 10:16:29  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Other Decode Variables): Addition.
-       (Mail-like Backends): New.
+       * gnus.texi (Mail Source Specifiers): Update maildir.
 
-Tue Nov  5 06:41:46 1996  Hrvoje Niksic  <hniksic@srce.hr>
+2000-05-07  Pavel Janik  <Pavel.Janik@inet.cz>
 
-       * gnus.texi (Score File Format): Added warning.
+       * gnus.texi: direntry added.
 
-Mon Oct 28 15:50:08 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * message.texi: direntry added.
 
-       * gnus.texi (Startup Variables): Addition.
+       * emacs-mime.texi: direntry added.
 
-Fri Oct 25 09:04:59 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+2000-05-02  Pavel Janik  <Pavel.Janik@inet.cz>
+
+       * gnus.texi (MIME comands): Spelling fix.
+
+2000-05-03 21:12:05  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
        * gnus.texi (Summary Mail Commands): Addition.
+       (Summary Post Commands): Ditto.
 
-Wed Oct 23 08:28:29 1996  Hrvoje Niksic  <hniksic@srce.hr>
+2000-04-27  Dave Love  <fx@gnu.org>
 
-       * gnus.texi (Fancy Mail Splitting): Removed trailing garbage. 
+       * gnus.texi (Article Washing): Update x-face bit.
 
-Tue Oct 22 07:36:02 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+2000-04-26  Florian Weimer  <fw@deneb.cygnus.argh.org>
 
-       * gnus.texi (Converting Kill Files): New.
+       * message.texi (Various Message Variables): Document
+       message-default-charset.
 
-Sat Oct 19 07:17:28 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * emacs-mime.texi (Charset Translation): New section.
 
-       * gnus.texi (Saving Articles): Addition.
+2000-04-26 02:30:06  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
-       * message.texi (Various Message Variables): Addition.
+       * gnus.texi (Posting Styles): Addition.
 
-Thu Oct 17 06:53:04 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+2000-04-24 17:09:17  Felix Natter  <f.natter@ndh.net>
 
-       * gnus.texi (Contributors): Added names.
+       * gnusref.tex: New version.
 
-Fri Oct 11 12:38:59 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+       * refcard.tex: New version.
 
-       * gnus.texi (Adaptive Scoring): Addition.
+2000-04-23 00:32:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Tue Oct  8 13:16:41 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+       * gnus.texi (Thread Commands): Add keystrokes.
+       (Various Summary Stuff): Addition.
 
-       * Makefile (all): Make custom.
+2000-04-22 21:12:25  Alan Shutko  <ats@acm.org>
 
-Wed Oct  2 01:32:49 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * Makefile.in: Add pdf support.
 
-       * gnus.texi (Group Timestamps): New.
+2000-04-21 12:07:20  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
-Tue Oct  1 01:34:45 1996  Lars Magne Ingebrigtsen  <larsi@hrym.ifi.uio.no>
+       * gnus.texi (Listing Groups): Addition.
 
-       * gnus.texi (Expiring Mail): Addition.
-       (Group Line Specification): Addition.
+2000-04-21 13:45:52  Pavel Janik  <Pavel.Janik@inet.cz>
+
+       * gnus.texi (Mail Source Specifiers): Example for :plugged.
+
+2000-04-20 20:37:48  Pavel Janik  <Pavel.Janik@inet.cz>
+
+       * gnus.texi (Limiting): Fix.
+
+2000-04-20 20:32:40  Dmitry Yaitskov  <dimas@home.com>
+
+       * gnus.texi (Charsets): Typo fix.
+
+2000-03-19  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (IMAP): Addition.
+
+2000-03-13 17:44:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Process/Prefix): Addition.
+
+2000-02-04  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (IMAP): Fix.
+
+2000-01-27 18:06:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Remember): Addition.
+
+2000-01-21  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (Splitting in IMAP): Addition.
+       (Mail Source Specifiers): Add fetchflag setting in example.
+
+2000-01-08 08:10:04  Martin Bialasinski  <agr30+news@uni-koeln.de>
+
+       * gnus.texi (Mail and Post): Example.
+
+2000-01-08 07:46:13  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Customizing w3): New.
+
+2000-01-08 07:46:06  Hamish Macdonald  <hamishm@lucent.com>
+
+       * gnus.texi (Customizing w3): Example.
+
+2000-01-06 17:55:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Charsets): Addition.
+
+2000-01-05 15:58:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Group Commands): Addition.
+       (Top): Added detailmenu.
+
+2000-01-03 01:31:02  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (MIME Commands): Fix.
+
+2000-01-03  Karl Kleinpaste <karl@justresearch.com>
+
+       * gnus.texi (Splitting in IMAP): Add '.' after @xref.
+
+2000-01-02 08:39:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi: Closing paren.
+       Doc fix.
+
+1999-12-28  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (Article Hiding): Addition.
+       (Splitting in IMAP): Addition.
+
+1999-12-17 12:12:41  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Mail Source Specifiers): Addition.
+
+1999-12-13 23:47:50  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Mail Source Specifiers): Addition.
+
+1999-12-07 00:19:31  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Web Archive): Addition.
+
+1999-12-06 05:17:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Slashdot): Addition.
+
+1999-12-05 00:54:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Source Specifiers): Removed backslashes.
+
+1999-12-04 07:35:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Setting Process Marks): Addition.
+
+1999-12-04 05:09:46  Manoj Srivastava  <srivasta@golden-gryphon.com>
+
+       * gnus.texi: Use defface instead of face-spec-set.
+
+1999-12-04 02:31:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (extension): Posting server fix.
+       Url update.
+
+1999-12-04 01:16:52  Yoshiki Hayashi  <t90553@m.ecc.u-tokyo.ac.jp>
+
+       * gnus.texi (group-buffer): Fix "theese".
+
+1999-12-04 01:13:51  Thomas Gellekum  <tg@ihf.rwth-aachen.de>
+
+       * gnus.texi (Height): Typo fix.
+
+1999-11-13  Adrian Aichner  <aichner@ecf.teradyne.com>
+
+       * xemacs.mak: New NMAKE file to support build and install of info
+       documentation on Windows NT, requiring the `texinfo' XEmacs
+       package.
+
+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>
+
+       * gnus.texi (Mail Source Specifiers): Add a note.
+
+1999-11-27 17:15:00  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi: Typo fixes and @sc.
+
+1999-11-26 16:59:29  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (On Writing Manuals): New.
+
+1999-11-23 17:23:37  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Mail Source Specifiers): Update.
+
+1999-11-23 05:07:59  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Web Archive): Add nnwarchive.
+
+1999-11-23 03:05:32  Shenghuo ZHU  <zsh@cs.rochester.edu>
+
+       * gnus.texi (Mail Source Specifiers): Add webmail.
+
+1999-11-19 12:15:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Slashdot): Addition.
+
+1999-11-17  Per Abrahamsen  <abraham@dina.kvl.dk>
+
+       * gnus.texi (Finding the Parent): Fix example.
+
+1999-11-16 10:09:44  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi: Addition.
+       (present): Addition.
+
+1999-11-13  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (Mail Source Specifiers): Fix. Added documentation for
+       IMAP mail-source keywords `fetchflag' and `dontexpunge'.
 
-Sat Sep 28 21:36:40 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+1999-11-12 18:00:56  Eli Zaretskii  <eliz@is.elta.co.il>
 
-       * gnus.texi (Foreign Groups): Addition.
+       * gnus.texi (Fancy Mail Splitting): Fix @vars.
 
-Mon Sep 23 22:17:44 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+1999-11-12 17:08:35  Gunnar Evermann  <ge204@eng.cam.ac.uk>
 
-       * gnus.texi (The Summary Buffer): Addition.
+       * gnus.texi (Splitting in IMAP): @@ fix.
 
-Mon Sep 23 18:25:38 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+1999-11-12 08:17:49  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Thread Commands): Correction.
-       (Group Information): Correction.
+       * gnus.texi (Mail Source Specifiers): Addition.
 
-Sat Sep 21 08:11:43 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-11-12 08:17:44  Ulf Betlehem  <flu@iki.fi>
 
-       * gnus.texi (New Groups): Split into three nodes.
-       (Group Parameters): Shortened.
-       (Browse Foreign Server): Corrected.
+       * gnus.texi (Mail Source Specifiers): Example.
 
-Thu Sep 19 18:45:15 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-11-12 05:26:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Mail and Procmail): Addition.
+       * gnus.texi (Slashdot): Addition.
 
-Wed Sep 18 07:33:11 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-11-11 04:32:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Other Marks): Edited.
-       (The Manual): New.
-       (Contributors): Updated.
-       (Asynchronous Fetching): Addition.
-       (New Features): Split.
-       ((ding) Gnus): Renamed.
-       (September Gnus): New.
-       (Red Gnus): New,
-       (Undo): New.
+       * message.texi (News Headers): Fix.
 
-Thu Sep 12 23:55:53 1996  Lars Magne Ingebrigtsen  <larsi@hrym.ifi.uio.no>
+       * gnus.texi (Browsing the Web): New.
+       (Slashdot): New.
+       (Ultimate): New.
+
+1999-11-10 11:32:00  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
        * gnus.texi (Archived Messages): Fix.
 
-Sat Sep  7 12:14:23 1996  Lars Magne Ingebrigtsen  <larsi@hymir.ifi.uio.no>
+1999-11-07 01:28:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Various Various): Addition.
+       * gnus.texi (MIME Commands): Addition.
 
-Fri Sep  6 07:57:26 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-11-06 23:09:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Startup Files): Addition.
-       (Splitting Mail): Addition.
-       (Sorting Groups): Addition.
-       (Topic Sorting): New.
-       (Really Various Summary Commands): Deletia.
-       (Summary Generation Commands): New.
-       (Setting Process Marks): Addition.
+       * gnus.texi (Customizing Articles): Fix.
 
-Thu Sep  5 07:34:27 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-11-05 22:34:23  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Terminology): Addition.
-       (Web Searches): Fix.
-       (Windows Configuration): Addition.
+       * gnus.texi (Posting Styles): Addition.
 
-Sun Sep  1 11:07:09 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-10-23  Simon Josefsson  <jas@pdc.kth.se>
 
-       * gnus.texi (XEmacs Enhancements): New.
+       * gnus.texi (Mail Source Specifiers): Add imap mail-source.
+       (IMAP): New subsection.
+       (SOUP): Typo.
 
-Sat Aug 31 02:55:50 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+1999-09-27 16:07:31  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Washing Mail): Addition.
+       * emacs-mime.texi (New Viewers): Fix.
 
-Fri Aug 30 09:10:17 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-10-29  David S. Goldberg  <dsg@mitre.org>
 
-       * gnus.texi (Washing Mail): New.
-       (Fancy Mail Splitting): Change.
+       * emacs-mime.texi (Customization): Document mm-inline-override-types
 
-Fri Aug 30 00:21:59 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+1999-09-25 10:58:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Foreign Groups): Change.
+       * message.texi (Forwarding): Updated.
 
-Thu Aug 29 23:51:45 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * emacs-mime.texi (New Viewers): New.
 
-       * gnus.texi (Daemons): Addition.
+1999-09-24 18:52:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Thu Aug 29 02:09:24 1996  François Pinard  <pinard@progiciels-bpi.ca>
+       * gnus.texi (Group Line Specification): Doc fix.
 
-       * gnus.texi (Web Searches): Typo.
+1999-09-24 18:06:33  Bill White  <billw@wolfram.com>
 
-Wed Aug 28 08:21:36 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Article Washing): Fix.
 
-       * gnus.texi (Server Commands): Addition.
-       (Really Various Summary Commands): Addition.
+1999-08-27 20:47:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Mon Aug 26 18:29:23 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Posting Styles): Doc fix.
 
-       * gnus.texi (Optional Backend Functions): Deletia.
-       (Asynchronous Fetching): Deletia and addition.
+1999-08-27 18:51:42  Robin S. Socha  <robin@socha.net>
 
-Sun Aug 25 23:39:03 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+       * gnus.texi: Typo fix.
 
-       * gnus.texi: Include the version number.
+1999-08-27 15:09:01  Jim Meyering  <meyering@ascend.com>
 
-Sun Aug 25 21:31:33 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+       * gnus.texi (The Active File): Typo fix.
 
-       * gnus.texi (Really Various Summary Commands): Addition.
+1999-08-27 15:00:23  Yoshiki Hayashi  <t90553@m.ecc.u-tokyo.ac.jp>
 
-Sat Aug 17 22:24:34 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Generic Marking Commands): Typo fixes.
 
-       * gnus.texi (Startup Files): Addition.
-       (Anything Groups): Addition.
+1999-08-27 14:46:21  Lee Willis  <lee@gbdirect.co.uk>
 
-Thu Aug 22 17:27:31 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Customizing Articles): More explanation.
 
-       * gnus.texi (Adaptive Scoring): Addition.
-       (Adaptive Scoring): Addition.
+1999-07-10  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus.texi (More Threading): Document new variable
+       `gnus-sort-gathered-threads-function'.
+
+1999-07-30  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi: Added `gnus-list-identifiers' stuff.
+
+1999-07-09 19:41:34  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Using MIME): Addition.
+       (Topic Commands): Addition.
+
+1999-07-06 05:37:46  Alexandre Oliva  <oliva@dcc.unicamp.br>
+
+        * gnus.texi (Fancy Mail Splitting): Document RESTRICT.
+
+1999-07-07 10:26:59  Robin S. Socha  <robin@socha.net>
+
+       * gnus.texi (Scoring Tips): Typo.
+
+1999-07-06 11:41:59  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Source Specifiers): Fix.
+       (Mail Source Customization): Deleted obsolete vars.
+
+1999-07-05 05:16:55  Laura Conrad  <lconrad@world.std.com>
+
+       * gnus.texi (Mail in a Newsreader): Rewrite.
+
+1999-07-04 04:33:50  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Posting Styles): Fix.
+       (Mail in a Newsreader): New.
+
+1999-06-13 02:29:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (MIME Commands): Addition.
+       (Article Miscellania): New.
+       (Customizing Articles): Addition.
+
+1999-06-12 00:13:25  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Comparing Mail Backends): Slight edits.
+
+1999-06-12 00:13:20  Karl Kleinpaste  <karl@justresearch.com>
+
+       * gnus.texi (Comparing Mail Backends): New.
+
+1999-06-11 21:47:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Score): Doc fix.
+       (The Active File): Addition.
+       (Document Groups): Addition.
+
+1999-04-18  Didier Verna  <verna@inf.enst.fr>
 
-Mon Aug 19 00:30:07 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Article treatment): document the new variable
+       `gnus-article-date-lapsed-new-header'.
+
+1999-04-26  Robert Bihlmeyer  <robbe@orcus.priv.at>
+
+       * gnus.texi (Posting Styles): Typo.
+
+1999-04-18 12:46:33  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Summary Score Commands): Typo.
+       (Choosing a Mail Backend): Addition.
+
+1999-04-18 09:24:51  Yoshiki Hayashi  <g740685@komaba.ecc.u-tokyo.ac.jp>
+
+       * gnus.texi (Startup Variables): Fix.
+
+1999-04-18 09:12:28  Starback  <starback@ling.uu.se>
+
+       * gnus.texi (Subscription Methods): Typo.
+
+1999-04-18 08:22:27  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Little Disk Space): Addition.
+
+1999-03-25  Erik Toubro Nielsen  <erik@ifad.dk>
+
+       * gnus.texi (gnus-thread-sort-functions). 'reverse' => 'not'
+
+1999-04-17 10:21:01  Jack Twilley  <jmt+usenet@nycap.rr.com>
 
        * gnus.texi (Fancy Mail Splitting): Addition.
-       (Splitting Mail): Addition.
-       (Group Parameters): Addition.
-       (Topic Variables): Addition.
-       (Mail Group Commands): Addition.
-       (Group Information): Addition.
-       (Article Washing): Addition.
 
-Sun Aug 18 18:06:49 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-04-07 06:13:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Web Searches): Change and addition.
+       * gnus.texi (Gnus Development): New.
 
-Sat Aug 17 22:24:34 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-03-06 20:12:50  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Startup Files): Addition.
-       (Anything Groups): Addition.
+       * gnus.texi (Generic Marking Commands): New.
 
-Thu Aug 15 17:59:12 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-03-01 16:41:42  Rob Browning  <rlb@cs.utexas.edu>
 
-       * gnus.texi (Followups To Yourself): Addition.
-       (Setting Process Marks): Addition.
-       (Process/Prefix): Addition.
-       (Startup Files): Addition.
-       (Mail-To-News Gateways): New.
+       * gnus.texi (Score Variables): Clarify.
 
-Wed Aug 14 15:02:14 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-26  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
 
-       * gnus.texi (Home Score File): Fix.
-       (Various Various): New.
+       * gnus.texi: Add ',' after @xrefs.
 
-Tue Aug 13 10:38:47 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-26 20:54:34  Jason R. Mastaler  <jason@4b.org>
 
-       * gnus.texi (Error Messaging): New.
-       (Mail Backend Variables): Fix.
-       (Foreign Groups): Added references.
-       (Sorting Groups): Addition.
+       * gnus.texi (Article Date): Added joke by Colin Rafferty
+       (colin@xemacs.org).
 
-Sun Aug 11 02:52:37 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-26 08:26:10  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (User-Defined Specs): Correction.
-       (Unavailable Servers): Addition.
-       (Moderation): New.
-       (Summary Mail Commands): Addition.
-       (Crosspost Handling): Addition.
+       * gnus.texi (Mail Source Specifiers): Fix.
 
-Sat Aug 10 00:13:39 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+Thu Feb 25 00:28:49 1999  Shenghuo ZHU  <zsh@cs.rochester.edu>
 
-       * gnus.texi (Summary Buffer Lines): Correction.
-       (Top): Name fix.
-       (Compilation ): Addition.
-       (Group Parameters): Addition.
-       (Troubleshooting): Addition.
+       * gnus.texi (Category Syntax): Typo fix.
 
-Fri Aug  9 07:17:59 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-21 11:42:54  Vladimir Volovich  <vvv@vvv.vsu.ru>
 
-       * gnus.texi (Selecting a Group): Addition.
-       (Score Decays): New.
-       (Score File Format): Addition.
-       (Changing Servers): Addition.
-       (Selecting a Group): Addition.
-       (Really Various Summary Commands): Addition.
+       * Makefile.in (.texi): Fix check for MAKEINFO.
 
-Thu Aug  8 05:39:31 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-20 17:33:55  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Read Articles): Addition.
-       (Foreign Groups): Addition.
-       (User-Defined Specs): Separated.
-       (Formatting Fonts): Ditto.
-       (Advanced Formatting): New.
-       (Formatting Basics): Addition.
-       (Formatting Variables): Split.
+       * gnus.texi (Mail Source Specifiers): Addition.
 
-Wed Aug  7 22:00:56 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+1999-02-11 19:19:02  Carsten Leonhardt  <leo@arioch.oche.de>
 
-       * gnus.texi (Hooking New Backends Into Gnus): New node.
+       * gnus.texi (Mail Source Specifiers): Document maildir.
 
-Wed Aug  7 01:02:08 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-09 16:21:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Setting Marks): Addition.
-       (Formatting Variables): Addition.
+       * gnus.texi (Charsets): New.
 
-Mon Aug  5 20:20:42 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-04 03:45:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Formatting Variables): Addition.
+       * emacs-mime.texi (Conversion): New.
 
-Sun Aug  4 07:15:28 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-03 03:04:18  Miguel de Icaza  <miguel@nuclecu.unam.mx>
 
-       * gnus.texi (Score File Format): Addition.
-       (Adaptive Scoring): Addition.
+       * gnus.texi (Fetching Mail): Typo fix.
 
-Sat Aug  3 17:35:36 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-02-02 22:28:42  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Group Parameters): Addition.
-       (Home Score File): New.
-       (Topic Parameters): New.
+       * gnus.texi (Mail Source Specifiers): Addition.
+
+1999-02-01 21:05:18  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Hiding): Addition.
+
+1999-01-28 08:08:28  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Washing Mail): Addition.
+
+1999-01-27 14:30:39  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Washing): Addition.
+
+1999-01-25 04:24:01  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (MIME): New.
+
+       * gnus.texi (Mail Sources): New.
+       (Mail Source Specifiers): New.
+       (Mail Source Customization): New.
+       (Fetching Mail): New.
 
-Wed Jul 31 15:34:12 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-01-23 09:47:16  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (are): Fix.
+       * gnus.texi (Article Washing): Removed.
+       (Customizing Articles): Addition.
 
-Wed Jul 31 15:32:57 1996  David S. Goldberg  <dsg@linus.mitre.org>
+1999-01-16 20:36:48  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (buffer-name): Addition.
+       * gnus.texi (Customizing Articles): Rewrite.
+       Remove mention of gnus-article-display-hook.
 
-Fri Aug  2 00:32:39 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-01-12 07:14:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi (Pick and Read): Addition.
-       (Article Hiding): Addition.
-       (Article Signature): Made into own node.
+       * gnus.texi (To From Newsgroups): Addition.
 
-Thu Aug  1 00:25:41 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1999-01-03 13:54:51  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * message.texi (Wide Reply): Addition.
-       (Bouncing): Addition.
+       * gnus.texi (Group Agent Commands): Addition.
 
-       * gnus.texi (Crosspost Handling): Made into own node.
-       (Duplicate Suppression): New.
-       (Document Server Internals): New.
-       (Changing Servers): New.
+1998-12-19 23:29:50  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-Wed Jul 31 15:37:44 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+       * gnus.texi (Splitting Mail): Addition.
+
+1998-12-13 08:54:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * message.texi (Insertion): Add.
+
+1998-12-03 13:34:48  James Troup  <james@nocrew.org>
+
+       * gnus.texi (MIME Commands): Typo fix.
+
+1998-12-03  Didier Verna  <verna@inf.enst.fr>
+
+       * gnus.texi (Group Parameters): update for the posting-style group
+       parameter.
+
+1998-12-02 01:04:22  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Emacsen): Addition.
+       (Picon Useless Configuration): Addition.
+
+1998-12-01 00:27:04  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * emacs-mime.texi (rfc2045): New.
+
+1998-11-29 00:03:43  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * emacs-mime.texi (Composing): New chapter.
+
+1998-11-25  Karl Eichwalder  <ke@gnu.franken.de>
+
+       * Makefile.in (install): Remove emacs-info, add emacs-mime.
+
+1998-11-25 10:56:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (To From Newsgroups): Addition.
+       (Anything Groups): Addition.
+       (Article Washing): Addition.
+       (MIME Commands): Addition.
+
+1998-11-19 04:05:15  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Really Various Summary Commands): Addition.
+
+1998-11-18 00:52:46  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (MIME Commands): Addition.
+       (Expiring Mail): Addition.
+
+1998-11-07 17:18:07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Gnus Reference Guide): Renamed.
+
+1998-10-26 22:03:08  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Washing): Fix.
+       (MIME Commands): Change.
+
+1998-10-25 01:51:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Headers): Addition.
+
+1998-10-24 08:37:12  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
-       * gnus.texi: Fix
+       * gnus.texi (Summary Buffer Lines): Addition.
+       (To): New.
+       (To): Addition.
 
-Mon Jul 29 10:12:24 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+1998-10-15 18:15:34  Simon Josefsson  <jas@pdc.kth.se>
+
+       * gnus.texi (Group Info): Must be list of ranges.
+
+1998-10-19 01:27:26  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Article Washing): Addition.
+
+1998-10-18 00:20:58  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Changing Servers): Addition.
+
+1998-10-17 21:34:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Windows Configuration): Addition.
+
+1998-10-01 07:55:35  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Splitting Mail): Fix.
+       (Washing Mail): Fix.
+
+1998-09-30 05:54:45  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Selecting a Group): Addition.
+
+1998-09-13 08:58:56  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * dir (File): Updated.
+
+1998-09-12 08:53:05  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * emacs-mime.texi: New file.
 
        * gnus.texi (Misc Article): Addition.
-       (Advanced Scoring Tips): New.
-       (Advanced Scoring Example): New.
-       (Advanced Scoring Syntax): New.
-       (Advanced Scoring): New.
 
+1998-09-11 08:52:50  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Group Score Commands): Fix.
+       (Saving Articles): Fix.
+       (Agent Expiry): Fix.
+       (Using MIME): Change.
+
+1998-09-10 03:19:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Windows Configuration): Addition.
+
+1998-09-06  Mike McEwan  <mike@lotusland.demon.co.uk>
+
+       * gnus.texi (Category Syntax): Added doc about agent categories
+       and download scoring.
+
+1998-09-05 17:36:14  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Sorting Groups): Change.
+       (Various Summary Stuff): Addition.
+
+1998-09-04 00:40:07  David S. Goldberg  <dsg@mitre.org>
+
+       * gnus.texi (Article Hiding): Verify.
+
+1998-08-31 11:46:57  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Folders): Addition.
+       (Group Parameters): Addition.
+       (MIME Commands): New.
+
+1998-08-27 07:29:17  Lars Magne Ingebrigtsen  <larsi@gnus.org>
+
+       * gnus.texi (Mail Folders): Addition.
+
+;; Local Variables:
+;; coding: iso-2022-7bit
+;; End:
diff --git a/texi/Makefile b/texi/Makefile
deleted file mode 100644 (file)
index ea5ef8f..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-TEXI2DVI=texi2dvi
-EMACS=emacs
-MAKEINFO=$(EMACS) -batch -q -no-site-file
-INFOSWI=-l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer
-XINFOSWI=-l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer
-LATEX=latex
-DVIPS=dvips
-PERL=perl
-INFODIR=/usr/local/info
-
-all: gnus message
-
-most: texi2latex.elc latex latexps
-
-.SUFFIXES: .texi .dvi .ps
-
-.texi:
-       $(MAKEINFO) -eval '(find-file "$<")' $(XINFOSWI)
-
-dvi: gnus.dvi message.dvi
-
-.texi.dvi :
-       $(PERL) -n -e 'print unless (/\@iflatex/ .. /\@end iflatex/)' $< > gnustmp.texi
-       $(TEXI2DVI) gnustmp.texi
-       cp gnustmp.dvi $*.dvi
-       rm gnustmp.*
-
-refcard.dvi: refcard.tex gnuslogo.refcard gnusref.tex
-       $(LATEX) refcard.tex
-
-clean:
-       rm -f gnus.*.bak *.ky *.cp *.fn *.cps *.kys *.log *.aux *.dvi *.vr \
-       *.tp *.toc *.pg gnus.latexi *.aux *.[cgk]idx \
-       gnus.ilg gnus.ind gnus.[cgk]ind gnus.idx \
-       gnus.tmptexi *.tmplatexi gnus.tmplatexi1 texput.log *.orig *.rej \
-       gnus.latexi*~* tmp/*.ps xface.tex picons.tex smiley.tex *.latexi
-
-makeinfo: 
-       makeinfo -o gnus gnus.texi      
-       makeinfo -o message message.texi        
-
-texi2latex.elc: texi2latex.el
-       $(EMACS) -batch -l bytecomp --eval '(byte-compile-file "texi2latex.el")'
-
-latex: gnus.texi texi2latex.elc
-       $(EMACS) -batch -q -no-site-file gnus.texi -l ./texi2latex.elc -f latexi-translate
-
-latexps: 
-       make texi2latex.elc
-       rm -f gnus.aux
-       egrep -v "label.*Index|chapter.*Index" gnus.latexi > gnus.tmplatexi1
-       $(LATEX) gnus.tmplatexi1
-       ./splitindex
-       makeindex -o gnus.kind gnus.kidx
-       makeindex -o gnus.cind gnus.cidx
-       makeindex -o gnus.gind gnus.gidx
-       sed 's/\\char 5E\\relax {}/\\symbol{"5E}/' < gnus.kind > gnus.tmpkind
-       mv gnus.tmpkind gnus.kind
-       egrep -v "end{document}" gnus.tmplatexi1 > gnus.tmplatexi
-       cat postamble.tex >> gnus.tmplatexi
-       $(LATEX) gnus.tmplatexi 
-       $(LATEX) gnus.tmplatexi 
-       $(DVIPS) -f gnus.dvi > gnus.ps
-
-pss:   
-       make latex
-       make latexps
-
-psout:
-       make latex
-       make latexboth
-       make out
-
-latexboth: 
-       rm -f gnus-manual-a4.ps.gz gnus-manual-standard.ps.gz 
-       make latexps
-       mv /local/tmp/larsi/gnus.ps /local/tmp/larsi/gnus-manual-a4.ps
-       gzip /local/tmp/larsi/gnus-manual-a4.ps 
-       sed 's/,a4paper//' gnus.latexi > gnus-standard.latexi 
-       mv gnus-standard.latexi gnus.latexi
-       make latexps
-       mv /local/tmp/larsi/gnus.ps /local/tmp/larsi/gnus-manual-standard.ps 
-       gzip /local/tmp/larsi/gnus-manual-standard.ps 
-
-out:
-       cp /local/tmp/larsi/gnus-manual-standard.ps.gz \
-       /local/tmp/larsi/gnus-manual-a4.ps.gz \
-       /local/ftp/pub/emacs/gnus/manual
-       mv /local/tmp/larsi/gnus-manual-standard.ps.gz \
-       /local/tmp/larsi/gnus-manual-a4.ps.gz \
-       /hom/larsi/www_docs/www.gnus.org/documents
-
-veryclean:
-       make clean
-       rm -f gnus.dvi gnus.ps
-
-distclean:
-       make clean
-       rm -f *.orig *.rej *.elc *~ gnus gnus-[0-9] gnus-[0-9][0-9]
-       rm -f message message-[0-9]
-
-install:
-       cp gnus gnus-[0-9] gnus-[0-9][0-9] $(INFODIR)
-       cp message $(INFODIR)
-
-
-tmps:
-       if [ ! -e tmp ]; then mkdir tmp; fi
-       make screens
-       make herdss
-       make etcs
-       make piconss
-       make xfaces
-       make smiley
-       make miscs
-
-herdss:
-       cd herds ; for i in new-herd-[0-9]*.gif; do echo $$i; giftopnm $$i | pnmcrop -white | pnmmargin -white 9 | pnmscale 2 | pnmconvol convol5.pnm  | ppmtopgm | pnmdepth 255 | pnmtops -width 100 -height 100 -noturn > ../tmp/`basename $$i .gif`.ps; done
-       cd herds ; giftopnm new-herd-section.gif | pnmscale 4 | pnmconvol convol11.pnm | ppmtopgm | pnmdepth 255 | pnmtops -noturn -width 100 -height 100 > ../tmp/new-herd-section.ps
-
-
-screens:
-       cd screen ; for i in *.gif; do echo $$i; giftopnm $$i | pnmmargin -black 1 | ppmtopgm | pnmtops -width 100 -height 100 -noturn > ../tmp/`basename $$i .gif`.ps; done    
-
-miscs:
-       giftopnm misc/larsi.gif | ppmtopgm | pnmtops -noturn > tmp/larsi.ps
-       tifftopnm misc/eseptember.tif | pnmscale 4 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/september.ps
-       tifftopnm misc/fseptember.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/fseptember.ps
-       tifftopnm misc/fred.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/fred.ps
-       tifftopnm misc/ered.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/red.ps
-
-etcs:
-       cd etc; for i in gnus-*.xpm; do echo $$i; xpmtoppm $$i | ppmtopgm | pnmdepth 255 | pnmtops -noturn > ../tmp/`basename $$i .xpm`.ps; done
-
-piconss:
-       cd picons; for i in *.xbm; do echo $$i; xbmtopbm $$i | pnmtops -noturn > ../tmp/picons-`basename $$i .xbm`.ps; done
-       cd picons; for i in *.gif; do echo $$i; giftopnm $$i | ppmtopgm | pnmtops -noturn > ../tmp/picons-`basename $$i .gif`.ps; done
-       for i in tmp/picons-*.ps; do echo "\\gnuspicon{$$i}"; done > picons.tex
-
-xfaces:
-       cd xface; for i in *.gif; do echo $$i; giftopnm $$i | ppmtopgm | pnmtops -noturn > ../tmp/xface-`basename $$i .gif`.ps; done
-       for i in tmp/xface-*.ps; do \
-               if [ -n "$$a" ]; then a=""; echo "{$$i}"; else \
-               a="h"; echo -n "\\gnusxface{$$i}"; fi done > xface.tex; \
-               if [ -n "$$a" ]; then echo "{$$i}" >> xface.tex; fi
-
-smiley:
-       cd smilies; tifftopnm BigFace.tif | ppmtopgm | pnmtops > ../tmp/BigFace.ps
-       cd smilies; for i in *.xpm; do echo $$i; sed "s/none/#FFFFFF/" $$i | xpmtoppm | ppmtopgm | pnmdepth 255 | pnmtops > ../tmp/smiley-`basename $$i .xpm`.ps; done
-       for i in tmp/smiley-*.ps; do \
-               if [ -n "$$a" ]; then a=""; echo "{$$i}"; else \
-               a="h"; echo -n "\\gnussmiley{$$i}"; fi done > smiley.tex; \
-               if [ -n "$$a" ]; then echo "{$$i}" >> smiley.tex; fi
-
-pspackage:
-       tar czvf pspackage.tar.gz gnus-faq.texi gnus.texi herds misc pagestyle.sty picons pixidx.sty postamble.tex ps screen smilies splitindex texi2latex.el xface Makefile README etc
-
-complete:
-       make texi2latex.elc
-       make tmps
-       make pss
index 2fc3cec..430c1b9 100644 (file)
-infodir = @infodir@
+infodir = @info_dir@
 prefix = @prefix@
 srcdir = @srcdir@
 subdir = texi
 top_srcdir = @top_srcdir@
 
+@SET_MAKE@
+VPATH=$(srcdir)
 TEXI2DVI=texi2dvi
-EMACS=emacs
+TEXI2PDF=texi2pdf
 MAKEINFO=@MAKEINFO@
-EMACSINFO=$(EMACS) -batch -q -no-site-file
-INFOSWI=-l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer
-XINFOSWI=-l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer
-LATEX=latex
+EMACS=@EMACS@
+EMACSCOMP=$(EMACS) -batch -q -no-site-file
+EMACSINFO=$(EMACSCOMP) -l $(srcdir)/infohack.el -f batch-makeinfo
+PDFLATEX=pdflatex
+LATEX=@LATEX@
 DVIPS=dvips
-PERL=perl
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+SHELL = /bin/sh
+PAPERTYPE=a4
+INFO_DEPS=gnus message emacs-mime sieve
+INFO_DEPS_JA=gnus-ja message-ja
+INFO_DEPS_INFO=gnus.info message.info emacs-mime.info sieve.info
+INFO_DEPS_JA_INFO=gnus-ja.info message-ja.info
 
-all: gnus message
+all: $(INFO_DEPS)
+all-info: $(INFO_DEPS_INFO)
+
+gnus.info: gnus.texi gnus-faq.texi
+message.info: message.texi
+emacs-mime.info: emacs-mime.texi
+sieve.info: sieve.texi
+
+ja: $(INFO_DEPS_JA)
+ja-info: $(INFO_DEPS_JA_INFO)
+
+gnus-ja.info: gnus-ja.texi gnus-faq-ja.texi
+message-ja.info: message-ja.texi
 
 most: texi2latex.elc latex latexps
 
-.SUFFIXES: .texi .dvi .ps
+%-ja: %-ja.texi
+       rm -f $@
+       $(EMACSINFO) $<
+
+%-ja.info: %-ja.texi
+       rm -f $@
+       $(EMACSINFO) $< t
+
+%.info: %.texi
+       @if test "x$(MAKEINFO)" = "xno" \
+         -o "$<" = "gnus-ja.texi" \
+         -o "$<" = "message-ja.texi"; then \
+         echo "rm -f $@"; echo "$(EMACSINFO) $< t"; \
+         rm -f $@; \
+         $(EMACSINFO) $< t; \
+       else \
+         echo "$(MAKEINFO) -I $(srcdir) -o $@ $<"; \
+         $(MAKEINFO) -I $(srcdir) -o $@ $<; \
+       fi
+
+.SUFFIXES: .texi .dvi .ps .pdf .latexi .dvi-x .pdf-x
 
 .texi:
-       if test $(MAKEINFO) = no; then \
-         $(EMACSINFO) -eval '(find-file "$<")' $(XINFOSWI); \
+       @if test "x$(MAKEINFO)" = "xno" \
+         -o "$<" = "gnus-ja.texi" \
+         -o "$<" = "message-ja.texi"; then \
+         echo "rm -f $@"; echo "$(EMACSINFO) $<"; \
+         rm -f $@; \
+         $(EMACSINFO) $<; \
        else \
-         makeinfo -o $* $<; \
+         echo "$(MAKEINFO) -I $(srcdir) -o $* $<"; \
+         $(MAKEINFO) -I $(srcdir) -o $* $<; \
        fi
 
-dvi: gnus.dvi message.dvi
+dvi: gnus.dvi message.dvi refcard.dvi emacs-mime.dvi sieve.dvi
+
+pdf: gnus.pdf message.pdf refcard.pdf emacs-mime.pdf sieve.pdf
 
 .texi.dvi :
-       $(PERL) -n -e 'print unless (/\@iflatex/ .. /\@end iflatex/)' $< > gnustmp.texi
-       $(TEXI2DVI) gnustmp.texi
+       sed -e '/@iflatex/,/@end iflatex/d' $< > gnustmp.texi
+       $(TEXI2DVI) -I $(srcdir) gnustmp.texi
        cp gnustmp.dvi $*.dvi
-       rm gnustmp.*
+       rm -f gnustmp.*
 
-refcard.dvi: refcard.tex gnuslogo.refcard gnusref.tex
-       $(LATEX) refcard.tex
+.dvi.ps :
+       TEXPICTS=$(srcdir) $(DVIPS) -t $(PAPERTYPE) -f $< > $@
+
+.texi.pdf :
+       sed -e '/@iflatex/,/@end iflatex/d' $< > gnustmp.texi
+       $(TEXI2PDF) -I $(srcdir) gnustmp.texi
+       cp gnustmp.pdf $*.pdf
+       rm -f gnustmp.*
+
+refcard.dvi: refcard.tex gnuslogo-refcard.eps gnusref.tex
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) refcard.tex
+
+refcard.pdf: refcard.tex gnuslogo-refcard.eps gnusref.tex
+       epstopdf $(srcdir)/gnuslogo-refcard.eps --outfile=gnuslogo-refcard.pdf
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) refcard.tex
+
+booklet.dvi: booklet.tex gnuslogo-refcard.eps gnusref.tex
+       if [ "$(PAPERTYPE)" == a4 ]; then \
+               TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) bk-a4.tex && \
+               mv bk-a4.dvi booklet.dvi ;\
+       else \
+               TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) bk-lt.tex && \
+               mv bk-lt.dvi booklet.dvi;\
+       fi
+
+booklet.pdf: booklet.tex gnuslogo-refcard.eps gnusref.tex
+       epstopdf $(srcdir)/gnuslogo-booklet.eps --outfile=gnuslogo-booklet.pdf
+       if [ "$(PAPERTYPE)" == a4 ]; then \
+               TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) bk-a4.tex &&\
+               mv bk-a4.pdf booklet.pdf ;\
+       else \
+               TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) bk-lt.tex &&\
+               mv bk-lt.pdf booklet.pdf ;\
+       fi
 
 clean:
-       rm -f gnus.*.bak *.ky *.cp *.fn *.cps *.kys *.log *.aux *.dvi *.vr \
-       *.tp *.toc *.pg gnus.latexi *.aux *.[cgk]idx \
-       gnus.ilg gnus.ind gnus.[cgk]ind gnus.idx \
-       gnus.tmptexi *.tmplatexi gnus.tmplatexi1 texput.log *.orig *.rej \
-       gnus.latexi*~* tmp/*.ps xface.tex picons.tex smiley.tex *.latexi
+       rm -f *.[cgk]idx *.aux *.cp *.cps *.dvi *.dvi-x *.fn *.ky       \
+       *.kys *.latexi *.log *.orig *.pdf *.pdf-x *.pg *.rej            \
+       *.tmplatexi *.toc *.tp *.vr gnus.*.bak gnus.[cgk]ind gnus.idx   \
+       gnus.ilg gnus.ind gnus.latexi*~* gnus.out gnus.tmplatexi1       \
+       gnustmp.texi picons.tex smiley.tex texput.log thumb*.png        \
+       thumbdta.tex xface.tex *.tpt gnus-manual-*.pdf gnus-manual-*.ps.gz
 
 makeinfo:
        makeinfo -o gnus gnus.texi
        makeinfo -o message message.texi
 
 texi2latex.elc: texi2latex.el
-       $(EMACS) -batch -l bytecomp --eval '(byte-compile-file "texi2latex.el")'
+       srcdir=$(srcdir)/../lisp $(EMACSCOMP) -l $(srcdir)/../lisp/dgnushack.el --eval '(byte-compile-file "$(srcdir)/texi2latex.el")'
 
-latex: gnus.texi texi2latex.elc
-       $(EMACS) -batch -q -no-site-file gnus.texi -l ./texi2latex.elc -f latexi-translate
+latex: gnus.latexi gnus-faq.latexi message.latexi emacs-mime.latexi sieve.latexi
 
-latexps:
-       make texi2latex.elc
-       rm -f gnus.aux
-       egrep -v "label.*Index|chapter.*Index" gnus.latexi > gnus.tmplatexi1
-       $(LATEX) gnus.tmplatexi1
-       ./splitindex
+gnus.latexi gnus-faq.latexi message.latexi emacs-mime.latexi sieve.latexi: $(srcdir)/gnus.texi $(srcdir)/gnus-faq.texi $(srcdir)/message.texi $(srcdir)/emacs-mime.texi $(srcdir)/sieve.texi texi2latex.elc
+       srcdir=$(srcdir) $(EMACSCOMP) -l ./texi2latex.elc -f latexi-translate
+
+.latexi.dvi-x:
+       make gnusconfig.tex
+       make tmps
+       rm -f gnus.aux gnus.toc
+       cp $< gnus.tmplatexi
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) gnus.tmplatexi
+       $(srcdir)/splitindex
+       makeindex -o gnus.kind gnus.kidx
+       makeindex -o gnus.cind gnus.cidx
+       makeindex -o gnus.gind gnus.gidx
+       sed 's/\\char 5E\\relax {}/\\symbol{"5E}/' < gnus.kind > gnus.tmpkind
+       mv gnus.tmpkind gnus.kind
+       egrep -v "end\{document\}" $< > gnus.tmplatexi
+       cat $(srcdir)/postamble.tex >> gnus.tmplatexi
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) gnus.tmplatexi
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(LATEX) gnus.tmplatexi
+       mv gnus.dvi $@
+
+.latexi.pdf-x:
+       make gnusconfig.tex
+       make tmps
+       cd ps; make pdf
+       rm -f gnus.aux gnus.toc
+       cp $< gnus.tmplatexi
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) gnus.tmplatexi
+       $(srcdir)/splitindex
        makeindex -o gnus.kind gnus.kidx
        makeindex -o gnus.cind gnus.cidx
        makeindex -o gnus.gind gnus.gidx
        sed 's/\\char 5E\\relax {}/\\symbol{"5E}/' < gnus.kind > gnus.tmpkind
        mv gnus.tmpkind gnus.kind
-       egrep -v "end{document}" gnus.tmplatexi1 > gnus.tmplatexi
-       cat postamble.tex >> gnus.tmplatexi
-       $(LATEX) gnus.tmplatexi
-       $(LATEX) gnus.tmplatexi
-       $(DVIPS) -f gnus.dvi > gnus.ps
-
-pss:
-       make latex
-       make latexps
-
-psout:
-       make latex
-       make latexboth
-       make out
-
-latexboth:
-       rm -f gnus-manual-a4.ps.gz gnus-manual-standard.ps.gz
-       make latexps
-       mv /local/tmp/larsi/gnus.ps /local/tmp/larsi/gnus-manual-a4.ps
-       gzip /local/tmp/larsi/gnus-manual-a4.ps
-       sed 's/,a4paper//' gnus.latexi > gnus-standard.latexi
-       mv gnus-standard.latexi gnus.latexi
-       make latexps
-       mv /local/tmp/larsi/gnus.ps /local/tmp/larsi/gnus-manual-standard.ps
-       gzip /local/tmp/larsi/gnus-manual-standard.ps
+       egrep -v "end\{document\}" $< > gnus.tmplatexi
+       cat $(srcdir)/postamble.tex >> gnus.tmplatexi
+       TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) gnus.tmplatexi
+       #thumbpdf gnus.pdf
+       #TEXINPUTS=$(srcdir):$$TEXINPUTS $(PDFLATEX) gnus.tmplatexi
+       mv gnus.pdf $@
+
+latexps: gnus.dvi-x
+       TEXPICTS=$(srcdir) $(DVIPS) -t a4 -f $< > gnus.ps
+
+latexpdf: gnus.pdf-x
+       mv gnus.pdf-x gnus.pdf
+
+gnus-manual-a4.latexi: gnus.latexi
+       cp $< $@
+
+gnus-manual-standard.latexi: gnus.latexi
+       sed 's/,a4paper/,letterpaper/' $< > $@
+
+gnus-manual-a4.ps.gz: gnus-manual-a4.dvi-x
+       TEXPICTS=$(srcdir) $(DVIPS) -t a4 -f $< | gzip -c > $@
+
+gnus-manual-standard.ps.gz: gnus-manual-standard.dvi-x
+       TEXPICTS=$(srcdir) $(DVIPS) -t letter -f $< | gzip -c > $@
+
+pdfs: gnus-manual-a4.pdf-x gnus-manual-standard.pdf-x
+       mv gnus-manual-a4.pdf-x gnus-manual-a4.pdf
+       mv gnus-manual-standard.pdf-x gnus-manual-standard.pdf
+
+pss: latexps
+
+complete: pss
+
+psout: latexboth out
+
+latexboth: gnus-manual-a4.ps.gz gnus-manual-standard.ps.gz
 
 out:
-       cp /local/tmp/larsi/gnus-manual-standard.ps.gz \
-       /local/tmp/larsi/gnus-manual-a4.ps.gz \
-       /local/ftp/pub/emacs/gnus/manual
-       mv /local/tmp/larsi/gnus-manual-standard.ps.gz \
-       /local/tmp/larsi/gnus-manual-a4.ps.gz \
-       /hom/larsi/www_docs/www.gnus.org/documents
-
-veryclean:
-       make clean
-       rm -f gnus.dvi gnus.ps
-
-distclean:
-       make clean
-       rm -f *.orig *.rej *.elc *~ gnus gnus-[0-9] gnus-[0-9][0-9]
-       rm -f message message-[0-9]
-
-install:
+       scp gnus-manual-*.ps.gz gnus-manual-*.pdf www@quimby:html/gnus/documents
+
+veryclean: clean
+       rm -f gnus.dvi gnus.ps texi2latex.elc
+       rm -f gnus-manual-a4.* gnus-manual-standard.*
+
+distclean: veryclean
+       rm -f *.orig *.rej *.elc *~ gnus-[0-9] gnus-[0-9][0-9] Makefile
+       rm -f message-[0-9]
+       rm -f $(INFO_DEPS)
+       rm -f gnus-ja-[0-9] gnus-ja-[0-9][0-9] message-ja-[0-9]
+       rm -f gnus.info-[0-9] gnus.info-[0-9][0-9] message.info-[0-9]
+       rm -f gnus-ja.info-[0-9] gnus-ja.info-[0-9][0-9] message-ja.info-[0-9]
+       rm -f $(INFO_DEPS_JA) $(INFO_DEPS_INFO) $(INFO_DEPS_JA_INFO)
+       rm -f gnusconfig.tex
+
+install: $(INFO_DEPS)
        $(SHELL) $(top_srcdir)/mkinstalldirs $(infodir)
-       @for file in gnus message; do \
-         for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+       @list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         for ifile in `echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
            if test -f $$ifile; then \
-             echo " $(INSTALL_DATA) $$d/$$ifile $(infodir)/$$ifile"; \
+             echo " $(INSTALL_DATA) $$ifile $(infodir)/$$ifile"; \
              $(INSTALL_DATA) $$ifile $(infodir)/$$ifile; \
            else : ; fi; \
          done; \
        done
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         list='$(INFO_DEPS)'; \
+         for file in $$list; do \
+           echo " install-info --info-dir=$(infodir) $(infodir)/$$file";\
+           install-info --info-dir=$(infodir) $(infodir)/$$file || :;\
+         done; \
+       else : ; fi
+
+uninstall:
+       @list='$(INFO_DEPS)'; \
+       list=$$list' $(INFO_DEPS_JA) $(INFO_DEPS_INFO) $(INFO_DEPS_JA_INFO)'; \
+       for file in $$list; do \
+         for ifile in `echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+           rm -f $(infodir)/$$ifile; \
+         done; \
+       done
+       @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+         list='$(INFO_DEPS)'; \
+         for file in $$list; do \
+           echo " install-info --delete --info-dir=$(infodir) $(infodir)/$$file";\
+           install-info --delete --info-dir=$(infodir) $(infodir)/$$file || :;\
+         done; \
+       else : ; fi
+
+install-ja: $(INFO_DEPS_JA)
+       $(MAKE) INFO_DEPS='$(INFO_DEPS_JA)' EMACS="$(EMACS)" \
+               infodir="$(infodir)" install
+
+install-info: $(INFO_DEPS_INFO)
+       $(MAKE) INFO_DEPS='$(INFO_DEPS_INFO)' EMACS="$(EMACS)" \
+               infodir="$(infodir)" install
+
+install-ja-info: $(INFO_DEPS_JA_INFO)
+       $(MAKE) INFO_DEPS='$(INFO_DEPS_JA_INFO)' EMACS="$(EMACS)" \
+               infodir="$(infodir)" install
 
 tmps:
-       if [ ! -e tmp ]; then mkdir tmp; fi
-       make screens
-       make herdss
-       make etcs
-       make piconss
-       make xfaces
-       make smiley
-       make miscs
-
-herdss:
-       cd herds ; for i in new-herd-[0-9]*.gif; do echo $$i; giftopnm $$i | pnmcrop -white | pnmmargin -white 9 | pnmscale 2 | pnmconvol convol5.pnm  | ppmtopgm | pnmdepth 255 | pnmtops -width 100 -height 100 -noturn > ../tmp/`basename $$i .gif`.ps; done
-       cd herds ; giftopnm new-herd-section.gif | pnmscale 4 | pnmconvol convol11.pnm | ppmtopgm | pnmdepth 255 | pnmtops -noturn -width 100 -height 100 > ../tmp/new-herd-section.ps
-
-
-screens:
-       cd screen ; for i in *.gif; do echo $$i; giftopnm $$i | pnmmargin -black 1 | ppmtopgm | pnmtops -width 100 -height 100 -noturn > ../tmp/`basename $$i .gif`.ps; done
-
-miscs:
-       giftopnm misc/larsi.gif | ppmtopgm | pnmtops -noturn > tmp/larsi.ps
-       tifftopnm misc/eseptember.tif | pnmscale 4 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/september.ps
-       tifftopnm misc/fseptember.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/fseptember.ps
-       tifftopnm misc/fred.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/fred.ps
-       tifftopnm misc/ered.tif | pnmscale 2 | ppmtopgm | pnmtops -noturn  -width 100 -height 100 > tmp/red.ps
-
-etcs:
-       cd etc; for i in gnus-*.xpm; do echo $$i; xpmtoppm $$i | ppmtopgm | pnmdepth 255 | pnmtops -noturn > ../tmp/`basename $$i .xpm`.ps; done
-
-piconss:
-       cd picons; for i in *.xbm; do echo $$i; xbmtopbm $$i | pnmtops -noturn > ../tmp/picons-`basename $$i .xbm`.ps; done
-       cd picons; for i in *.gif; do echo $$i; giftopnm $$i | ppmtopgm | pnmtops -noturn > ../tmp/picons-`basename $$i .gif`.ps; done
-       for i in tmp/picons-*.ps; do echo "\\gnuspicon{$$i}"; done > picons.tex
-
-xfaces:
-       cd xface; for i in *.gif; do echo $$i; giftopnm $$i | ppmtopgm | pnmtops -noturn > ../tmp/xface-`basename $$i .gif`.ps; done
-       for i in tmp/xface-*.ps; do \
+       cd ps; make all
+       for j in ps/picons-*.ps; do \
+               i=ps/`basename $$j .ps`; \
+               echo "\\gnuspicon{$$i}"; done > picons.tex
+       for j in ps/xface-*.ps; do \
+               i=ps/`basename $$j .ps`; \
                if [ -n "$$a" ]; then a=""; echo "{$$i}"; else \
                a="h"; echo -n "\\gnusxface{$$i}"; fi done > xface.tex; \
                if [ -n "$$a" ]; then echo "{$$i}" >> xface.tex; fi
-
-smiley:
-       cd smilies; tifftopnm BigFace.tif | ppmtopgm | pnmtops > ../tmp/BigFace.ps
-       cd smilies; for i in *.xpm; do echo $$i; sed "s/none/#FFFFFF/" $$i | xpmtoppm | ppmtopgm | pnmdepth 255 | pnmtops > ../tmp/smiley-`basename $$i .xpm`.ps; done
-       for i in tmp/smiley-*.ps; do \
+       for j in ps/smiley-*.ps; do \
+               i=ps/`basename $$j .ps`; \
                if [ -n "$$a" ]; then a=""; echo "{$$i}"; else \
                a="h"; echo -n "\\gnussmiley{$$i}"; fi done > smiley.tex; \
                if [ -n "$$a" ]; then echo "{$$i}" >> smiley.tex; fi
-
 pspackage:
+       cd ps; make clean
        tar czvf pspackage.tar.gz gnus-faq.texi gnus.texi herds misc pagestyle.sty picons pixidx.sty postamble.tex ps screen smilies splitindex texi2latex.el xface Makefile README etc
 
-complete:
-       make texi2latex.elc
-       make tmps
-       make pss
-
 Makefile: $(srcdir)/Makefile.in ../config.status
        cd .. \
          && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
+gnusconfig.tex: $(srcdir)/gnusconfig.tex.in ../config.status
+       cd .. \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/texi/TRANSLATION.ja b/texi/TRANSLATION.ja
new file mode 100644 (file)
index 0000000..5e0f759
--- /dev/null
@@ -0,0 +1,27 @@
+This file documents about translation policy.
+There is an ongoing project to make gnus-ja.texi.
+Any volunteers are welcomed.
+
+\e$BF|K\8lLu$K4X$9$kN.57$r@bL@$9$k%U%!%$%k$G$9!#\e(B
+gnus-ja.texi \e$B$r:n@.$9$k%W%m%8%'%/%H$,?J9TCf$G$9!#\e(B
+\e$B%W%m%8%'%/%H;22C<T$rJg=8$7$F$$$^$9!#\e(B
+\e$B;22C4uK><T$O\e(B Semi-gnus \e$B%^%K%e%"%k%W%m%8%'%/%H$N%Z!<%8\e(B
+http://www.komaba.ecc.u-tokyo.ac.jp/%7Eg740685/Semi-gnus/index.html
+\e$B$rFI$s$G$/$@$5$$!#\e(B
+
+\e$B0J2<$N\e(B2\e$B$D$OLu<T$N0l?M$+$D%W%m%8%'%/%H$N<g:K<T\e(B (\e$B$G$"$k$i$7$$\e(B) 
+Yoshiki Hayashi <g740685@komaba.ecc.u-tokyo.ac.jp> \e$B$NK]Lu$K4X$9$k5,B'\e(B
+\e$B$G$9!#$3$N5,B'$O$h$jNI$$$H;W$o$l$k$b$N$,8+$D$+$C$?>l9g$K$OJQ99$5$l$k2D\e(B
+\e$BG=@-$,$"$j$^$9!#$^$?!"$h$jNI$$0F$d!"B>$N5,B'$rIU$12C$($?$$>l9g$O!"\e(B
+semi-gnus-ja \e$B%a!<%j%s%0%j%9%H$K$=$N0F$r=q$/$+!"\e(Bjaist \e$B$N\e(B Open CVS \e$B$K=q\e(B
+\e$B$-9~$_8"8B$r;}$C$F$$$kJ}$OD>@\=q$-9~$_$r$7$F$/$@$5$$!#\e(B(CVS \e$B$N>l9g$G$b!"\e(B
+semi-gnus-ja \e$B$GJQ99$N9pCN$r$9$k;v$,K>$^$7$$$G$9!#\e(B) semi-gnus-ja \e$B%a!<%j\e(B
+\e$B%s%0%j%9%H$N2CF~$N;EJ}$KIU$$$F$b!">e5-$N\e(B URI \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+1. \e$B$J$k$Y$/%+%?%+%J$O;H$o$J$$$h$&$K$9$k!#\e(B
+   (\e$BF|K\8l$K$G$-$k$H$3$m$O$J$k$Y$/F|K\8l$K$9$k!#\e(B
+    \e$B>l9g$K$h$C$F$O?7$7$$8l$rDj5A$9$k;v$b$"$k!#\e(B)
+
+2. \e$B1Q8l$rIU2C$7$?J}$,J,$+$j$d$9$$$H;W$o$l$k8l6g$O!"\e(B
+   \e$BF|K\8l$ND>8e$K3g8L$NCf$KF~$l$k!#\e(B
+
diff --git a/texi/bk-a4.tex b/texi/bk-a4.tex
new file mode 100644 (file)
index 0000000..20d13ab
--- /dev/null
@@ -0,0 +1,20 @@
+% Reference Booklet for (ding) Gnus, A4 format.
+% To be processed with latex 2e
+\documentclass{article}
+
+\usepackage{supertabular}
+
+\newlength{\logowidth} \setlength{\logowidth}{6.861in}
+\newlength{\logoheight} \setlength{\logoheight}{7.013in}
+
+\def\Guide{Card}\def\guide{card}
+\def\logoscale{0.25}
+
+\usepackage{epsfig}
+
+\textwidth 4.9in \textheight 7.35in \topmargin -1.0in
+\oddsidemargin -0.5in \evensidemargin -0.5in
+\begin{document}
+\small%\footnotesize
+\input{booklet}
+\end{document}
diff --git a/texi/bk-lt.tex b/texi/bk-lt.tex
new file mode 100644 (file)
index 0000000..0329059
--- /dev/null
@@ -0,0 +1,20 @@
+% Reference Booklet for (ding) Gnus, Letter format.
+% To be processed with latex 2e
+\documentclass{article}
+
+\usepackage{supertabular}
+
+\newlength{\logowidth} \setlength{\logowidth}{6.861in}
+\newlength{\logoheight} \setlength{\logoheight}{7.013in}
+
+\def\Guide{Card}\def\guide{card}
+\def\logoscale{0.25}
+
+\usepackage{epsfig}
+
+\textwidth 4.5in \textheight 7.5in \topmargin -1.0in
+\oddsidemargin -0.5in \evensidemargin -0.5in
+\begin{document}
+\small%\footnotesize
+\input{booklet}
+\end{document}
diff --git a/texi/booklet.tex b/texi/booklet.tex
new file mode 100644 (file)
index 0000000..b6ee207
--- /dev/null
@@ -0,0 +1,172 @@
+% include file for the Reference Booklet (16 pages).
+\def\Guide{Booklet}\def\guide{booklet}
+\def\logoscale{0.5}
+\def\sec{\section}
+\def\subsec{\subsection}
+\def\subsubsec{\subsubsection}
+\def\blankpage{\vspace*{\fill}\par
+%\centerline{(This page intentionally left blank.)}
+\par\vspace*{\fill}\pagebreak}
+
+\input{gnusref}
+
+\setcounter{page}{0}
+\thispagestyle{empty}
+\vspace*{\fill}
+\Title
+\vspace{0.4in}
+\Logo{booklet}
+\vspace*{\fill}
+\pagebreak
+
+% TODO: how does this work ?
+%\tableofcontents
+
+\Notes
+%
+\section*{Group-Mode}
+\GroupModeGeneral
+    \subsection*{Group Subscribedness-Levels}
+    \GroupLevels
+    \subsection*{List Groups}
+    \ListGroups
+    \subsection*{Create/Edit Foreign Groups}
+    \CreateEditGroups
+    \subsection*{Unsubscribe, Kill and Yank Groups}
+    \SubscribeKillYankGroups
+    \subsection*{Mark Groups}
+    \MarkGroups
+    \subsection*{Group-Unplugged}
+    \GroupUnplugged
+% topics in group-mode
+    \subsection*{Group Topics}
+    \GroupTopicsGeneral
+    \subsubsection*{Topic Sorting}
+    \TopicSorting
+\pagebreak
+% summary-mode
+\section*{Summary-Mode}
+\SummaryModeGeneral
+    \subsection*{Select Articles}
+    \SelectArticles
+%
+    \subsection*{Threading}
+    \Threading
+%
+    \subsection*{Limiting}
+    \Limiting
+    \subsection*{Sort the Summary-Buffer}
+    \SortSummary
+    \subsection*{Score (Value) Commands}
+    \Scoring
+% 
+    \subsection*{MIME operations from the Summary-Buffer}
+    \MIMESummary
+    \subsection*{Extract Series (Uudecode etc)}
+    \ExtractSeries
+    \subsection*{Output Articles}
+    \OutputArticles
+%
+    \subsection*{Post, Followup, Reply, Forward, Cancel}
+    \PostReplyetc
+    \subsection*{Message-Composition}
+    \MsgCompositionGeneral
+        \subsubsection*{Jumping in message-buffer}
+        \MsgCompositionMovementArticle
+        \subsubsection*{Attachments/MML}
+        \MsgCompositionMML
+% marking articles
+    \subsection*{Mark Articles}
+    \MarkArticlesGeneral
+        \subsubsection*{Mark Based on Score}
+        \MarkByScore
+        \subsubsection*{The Process Mark}
+        \ProcessMark
+        \subsubsection*{Mark Indication-Characters}
+        \MarkCharacters
+%
+    \subsection*{Summary-Unplugged}
+    \SummaryUnplugged
+    \subsection*{Mail-Group Commands}
+    \MailGroups
+    \subsection*{Draft-Group Commands}
+    \DraftGroup
+% exiting
+    \subsection*{Exit the Summary-Buffer}
+    \ExitSummary
+%
+%
+\section*{Article Mode (reading)}
+\ArticleModeGeneral
+    \subsection*{Wash the Article-Buffer}
+    \WashArticle
+    \subsubsection*{Blank Lines and Whitespace}
+    \BlankAndWhitespace
+    \subsubsection*{Picons, X-faces, Smileys}
+    \Picons
+    \subsubsection*{Time and Date}
+    \TimeAndDate
+    \subsection*{Hide/Highlight Parts of the Article}
+    \HideHighlightArticle
+    \subsection*{MIME operations from the Article-Buffer (reading)}
+    \MIMEArticleMode
+%
+%
+\section*{Server Mode}
+\ServerMode
+    \subsection*{Unplugged-Server}
+    \ServerUnplugged
+%
+%
+\section*{Browse Server Mode}
+\BrowseServer
+
+%\pagebreak
+\vspace*{\fill}
+\Copyright
+
+%% \pagebreak
+%% \Notes
+%% \GroupLevels
+%% \Marks
+%% \General
+%% \ServerMode
+%% \BrowseServer
+%% \ArticleMode
+%% \pagebreak
+
+%% \GroupMode
+%% \ListGroups     
+%% \CreateGroups   
+%% \SortGroups     
+%% \SOUP           
+%% \MarkGroups     
+%% \Unsubscribe    
+%% \GroupTopics    
+%% \SummaryMode    
+%% \SortSummary    
+%% \Article        
+%% \MailGroup      
+%% \Limit          
+%% \GotoArticle    
+%% \MarkArticles   
+%% \MarkScore      
+%% \ProcessMark    
+%% \OutputArticles 
+%% \Send           
+%% \Exit           
+%% \Thread         
+%% \Score          
+%% \Wash           
+%% \Hide           
+%% \Highlight      
+%% \Extract        
+%% \PickAndRead    
+
+%% %\pagebreak
+%% %\sec{Personal Notes}
+%% %\blankpage
+
+%% \thispagestyle{empty}
+%% \vspace*{\fill}
+%% \CopyRight
diff --git a/texi/custom.texi b/texi/custom.texi
deleted file mode 100644 (file)
index 5b6fe4a..0000000
+++ /dev/null
@@ -1,695 +0,0 @@
-\input texinfo.tex
-
-@c %**start of header
-@setfilename custom
-@settitle The Customization Library
-@iftex
-@afourpaper
-@headings double
-@end iftex
-@c %**end of header
-
-@node Top, Introduction, (dir), (dir)
-@comment  node-name,  next,  previous,  up
-@top The Customization Library
-
-Version: 1.82
-
-@menu
-* Introduction::                
-* User Commands::               
-* The Customization Buffer::    
-* Declarations::                
-* Utilities::                   
-* The Init File::               
-* Wishlist::                    
-@end menu
-
-@node   Introduction, User Commands, Top, Top
-@comment  node-name,  next,  previous,  up
-@section Introduction
-
-This library allows customization of @dfn{user options}.  Currently two
-types of user options are supported, namely @dfn{variables} and
-@dfn{faces}.  Each user option can have four different values
-simultaneously:
-@table @dfn
-@item factory setting
-The value specified by the programmer.
-@item saved value
-The value saved by the user as the default for this variable.  This
-overwrites the factory setting when starting a new emacs.
-@item current value
-The value used by Emacs.  This will not be remembered next time you
-run Emacs.
-@item widget value
-The value entered by the user in a customization buffer, but not yet
-applied.
-@end table
-
-Variables also have a @dfn{type}, which specifies what kind of values
-the variable can hold, and how the value is presented in a customization
-buffer.  By default a variable can hold any valid expression, but the
-programmer can specify a more limited type when declaring the variable.
-
-The user options are organized in a number of @dfn{groups}.  Each group
-can contain a number user options, as well as other groups.  The groups
-allows the user to concentrate on a specific part of emacs.
-
-@node  User Commands, The Customization Buffer, Introduction, Top
-@comment  node-name,  next,  previous,  up
-@section User Commands
-
-The following commands will create a customization buffer:
-
-@table @code
-@item customize
-Create a customization buffer containing a specific group, by default
-the @code{emacs} group.
-
-@item customize-variable
-Create a customization buffer containing a single variable.  
-
-@item customize-face
-Create a customization buffer containing a single face.
-
-@item customize-apropos
-Create a customization buffer containing all variables, faces, and
-groups that match a user specified regular expression.
-@end table
-
-@node The Customization Buffer, Declarations, User Commands, Top
-@comment  node-name,  next,  previous,  up
-@section The Customization Buffer.
-
-The customization buffer allows the user to make temporary or permanent
-changes to how specific aspects of emacs works, by setting and editing
-user options.  
-
-The customization buffer contains three types of text:
-
-@table @dfn
-@item informative text
-where the normal editing commands are disabled.
-
-@item editable fields
-where you can edit with the usual emacs commands.  Editable fields are
-usually displayed with a grey background if your terminal supports
-colors, or an italic font otherwise.
-
-@item buttons
-which can be activated by either pressing the @kbd{@key{ret}} while
-point is located on the text, or pushing @kbd{mouse-2} while the mouse
-pointer is above the tex.  Buttons are usually displayed in a bold
-font. 
-@end table
-
-You can move to the next the next editable field or button by pressing
-@kbd{@key{tab}} or the previous with @kbd{M-@key{tab}}.  Some buttons
-have a small helpful message about their purpose, which will be
-displayed when you move to it with the @key{tab} key.  
-
-The buffer is divided into three part, an introductory text, a list of
-customization options, and a line of customization buttons.  Each part
-will be described in the following. 
-
-@menu
-* The Introductory Text::       
-* The Customization Options::   
-* The Variable Options::        
-* The Face Options::            
-* The Group Options::           
-* The State Button::            
-* The Customization Buttons::   
-@end menu
-
-@node  The Introductory Text, The Customization Options, The Customization Buffer, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection  The Introductory Text
-
-The start of the buffer contains a short explanation of what it is, and
-how to get help.  It will typically look like this:
-
-@example
-This is a customization buffer.
-Push RET or click mouse-2 on the word _help_ for more information.
-@end example
-
-Rather boring.  It is mostly just informative text, but the word
-@samp{help} is a button that will bring up this document when
-activated.  
-
-@node  The Customization Options, The Variable Options, The Introductory Text, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The Customization Options
-
-Each customization option looks similar to the following text:
-
-@example
- *** custom-background-mode: default 
- State: this item is unchanged from its factory setting.
- [ ] [?] The brightness of the background.
-@end example
-
-The option contains the parts described below.
-
-@table @samp
-@item ***
-The Level Button.  The customization options in the buffer are organized
-in a hierarchy, which is indicated by the number of stars in the level
-button.  The top level options will be shown as @samp{*}.  When they are
-expanded, the suboptions will be shown as @samp{**}.  The example option
-is thus a subsuboption.
-
-Activating the level buttons will toggle between hiding and exposing the
-content of that option.  The content can either be the value of the
-option, as in this example, or a list of suboptions.
-
-@item custom-background-mode
-This is the tag of the the option.  The tag is a name of a variable, a
-face, or customization group.  Activating the tag has an effect that
-depends on the exact type of the option.  In this particular case,
-activating the tag will bring up a menu that will allow you to choose
-from the three possible values of the `custom-background-mode'
-variable. 
-
-@item default
-After the tag, the options value is shown.  Depending on its type, you
-may be able to edit the value directly.  If an option should contain a
-file name, it is displayed in an editable field, i.e. you can edit it
-using the standard emacs editing commands.
-
-@item State: this item is unchanged from its factory setting.
-The state line.  This line will explain the state of the option,
-e.g. whether it is currently hidden, or whether it has been modified or
-not.  Activating the button will allow you to change the state, e.g. set
-or reset the changes you have made.  This is explained in detail in the
-following sections.
-
-@item [ ]
-The magic button.  This is an abbreviated version of the state line. 
-
-@item [?] 
-The documentation button.  If the documentation is more than one line,
-this button will be present.  Activating the button will toggle whether
-the complete documentation is shown, or only the first line.
-
-@item The brightness of the background.
-This is a documentation string explaining the purpose of this particular
-customization option.
-
-@end table
-
-@node  The Variable Options, The Face Options, The Customization Options, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The Variable Options
-
-The most common customization options are emacs lisp variables.  The
-actual editing of these variables depend on what type values the
-variable is expected to contain.  For example, a lisp variable whose
-value should be a string will typically be represented with an editable
-text field in the buffer, where you can change the string directly.  If
-the value is a list, each item in the list will be presented in the
-buffer buffer on a separate line, with buttons to insert new items in
-the list, or delete existing items from the list.  You may want to see 
-@ref{User Interface,,, widget, The Widget Library}, where some examples
-of editing are discussed.  
-
-You can either choose to edit the value directly, or edit the lisp
-value for that variable.  The lisp value is a lisp expression that
-will be evaluated when you start emacs.  The result of the evaluation
-will be used as the initial value for that variable.  Editing the
-lisp value is for experts only, but if the current value of the
-variable is of a wrong type (i.e. a symbol where a string is expected),
-the `edit lisp' mode will always be selected.
-
-You can see what mode is currently selected by looking at the state
-button.  If it uses parenthesises (like @samp{( )}) it is in edit lisp
-mode, with square brackets (like @samp{[ ]}) it is normal edit mode.
-You can switch mode by activating the state button, and select either
-@samp{Edit} or @samp{Edit lisp} from the menu.
-
-You can change the state of the variable with the other menu items:
-
-@table @samp
-@item Set
-When you have made your modifications in the buffer, you need to
-activate this item to make the modifications take effect.  The
-modifications will be forgotten next time you run emacs.
-
-@item Save
-Unless you activate this item instead!  This will mark the modification
-as permanent, i.e. the changes will be remembered in the next emacs
-session.
-
-@item Reset
-If you have made some modifications and not yet applied them, you can
-undo the modification by activating this item.
-
-@item Reset to Saved
-Activating this item will reset the value of the variable to the last
-value you marked as permanent with `Save'.
-
-@item Reset to Factory Settings
-Activating this item will undo all modifications you have made, and
-reset the value to the initial value specified by the program itself. 
-@end table
-
-By default, the value of large or complicated variables are hidden.   You
-can show the value by clicking on the level button.
-
-@node  The Face Options, The Group Options, The Variable Options, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The Face Options
-
-A face is an object that controls the appearance of some buffer text.
-The face has a number of possible attributes, such as boldness,
-foreground color, and more.  For each attribute you can specify whether
-this attribute is controlled by the face, and if so, what the value is.
-For example, if the attribute bold is not controlled by a face, using
-that face on some buffer text will not affect its boldness.  If the bold
-attribute is controlled by the face, it can be turned either on or of.
-
-It is possible to specify that a face should have different attributes
-on different device types.  For example, a face may make text red on a
-color device, and bold on a monochrome device.  You do this by
-activating `Edit All' in the state menu.
-
-The way this is presented in the customization buffer is to have a list
-of display specifications, and for each display specification a list of
-face attributes.  For each face attribute, there is a checkbox
-specifying whether this attribute has effect and what the value is.
-Here is an example:
-
-@example
- *** custom-invalid-face: (sample)
- State: this item is unchanged from its factory setting.
- [ ] Face used when the customize item is invalid.
- [INS] [DEL] Display: [ ] Type: [ ] X [ ] PM [ ] Win32 [ ] DOS [ ] TTY
-                      [X] Class: [X] Color [ ] Grayscale [ ] Monochrome
-                      [ ] Background: [ ] Light [ ] Dark
-             Attributes: [ ] Bold: off 
-                         [ ] Italic: off 
-                         [ ] Underline: off 
-                         [X] Foreground: yellow (sample)
-                         [X] Background: red (sample)
-                         [ ] Stipple:  
- [INS] [DEL] Display: all
-             Attributes: [X] Bold: on 
-                         [X] Italic: on 
-                         [X] Underline: on 
-                         [ ] Foreground: default (sample)
-                         [ ] Background: default (sample)
-                         [ ] Stipple:  
- [INS]
-@end example
-
-This has two display specifications.  The first will match all color
-displays, independently on what window system the device belongs to, and
-whether background color is dark or light.  For devices matching this
-specification, @samp{custom-invalid-face} will force text to be
-displayed in yellow on red, but leave all other attributes alone.
-
-The second display will simply match everything.  Since the list is
-prioritised, this means that it will match all non-color displays.  For
-these, the face will not affect the foreground or background color, but
-force the font to be both bold, italic, and underline.
-
-You can add or delete display specifications by activating the
-@samp{[INS]} and @samp{[DEL]} buttons, and modify them by clicking on
-the check boxes.  The first checkbox in each line in the display
-specification is special.  It specify whether this particular property
-will even be relevant.  By not checking the box in the first display, we
-match all device types, also device types other than those listed.
-
-After modifying the face, you can activate the state button to make the
-changes take effect.  The menu items in the state button menu is similar
-to the state menu items for variables described in the previous section.
-
-@node  The Group Options, The State Button, The Face Options, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The Group Options
-
-Since Emacs has approximately a zillion configuration options, they have
-been organized in groups.  Each group can contain other groups, thus
-creating a customization hierarchy.  The nesting of the customization
-within the visible part of this hierarchy is indicated by the number of
-stars in the level button.
-
-Since there is really no customization needed for the group itself, the
-menu items in the groups state button will affect all modified group
-members recursively.  Thus, if you activate the @samp{Set} menu item,
-all variables and faces that have been modified and belong to that group
-will be applied.  For those members that themselves are groups, it will
-work as if you had activated the @samp{Set} menu item on them as well.
-
-@node  The State Button, The Customization Buttons, The Group Options, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The State Line and The Magic Button
-
-The state line has two purposes.  The first is to hold the state menu,
-as described in the previous sections.  The second is to indicate the
-state of each customization item.  
-
-For the magic button, this is done by the character inside the brackets.
-The following states have been defined, the first that applies to the
-current item will be used:
-
-@table @samp
-@item -
-The option is currently hidden.  For group options that means the
-members are not shown, for variables and faces that the value is not
-shown.  You cannot perform any of the state change operations on a
-hidden customization option.
-
-@item *
-The value if this option has been modified in the buffer, but not yet
-applied.  
-
-@item +
-The item has has been set by the user.
-
-@item :
-The current value of this option is different from the saved value.   
-
-@item !
-The saved value of this option is different from the factory setting.
-
-@item @@
-The factory setting of this option is not known.  This occurs when you
-try to customize variables or faces that have not been explicitly
-declared as customizable.
-
-@item SPC
-The factory setting is still in effect.
-
-@end table
-
-For non-hidden group options, the state shown is the most severe state
-of its members, where more severe means that it appears earlier in the
-list above (except hidden members, which are ignored).
-
-@node  The Customization Buttons,  , The State Button, The Customization Buffer
-@comment  node-name,  next,  previous,  up
-@subsection The Customization Buttons
-
-The last part of the customization buffer looks like this:
-
-@example
-[Set] [Save] [Reset] [Done]
-@end example
-
-Activating the @samp{[Set]}, @samp{[Save]}, or @samp{[Reset]}
-button will affect all modified customization items that are visible in
-the buffer.  @samp{[Done]} will bury the buffer.
-
-@node   Declarations, Utilities, The Customization Buffer, Top
-@comment  node-name,  next,  previous,  up
-@section Declarations
-
-This section describes how to declare customization groups, variables,
-and faces.  It doesn't contain any examples, but please look at the file
-@file{cus-edit.el} which contains many declarations you can learn from.
-
-@menu
-* Declaring Groups::            
-* Declaring Variables::         
-* Declaring Faces::             
-* Usage for Package Authors::   
-@end menu
-
-All the customization declarations can be changes by keyword arguments.
-Groups, variables, and faces all share these common keywords:
-
-@table @code
-@item :group
-@var{value} should be a customization group. 
-Add @var{symbol} to that group. 
-@item :link
-@var{value} should be a widget type. 
-Add @var{value} to the extrenal links for this customization option.
-Useful widget types include @code{custom-manual}, @code{info-link}, and
-@code{url-link}. 
-@item :load
-Add @var{value} to the files that should be loaded nefore displaying
-this customization option.  The value should be iether a string, which
-should be a string which will be loaded with @code{load-library} unless
-present in @code{load-history}, or a symbol which will be loaded with
-@code{require}. 
-@item :tag
-@var{Value} should be a short string used for identifying the option in
-customization menus and buffers.  By default the tag will be
-automatically created from the options name.
-@end table
-
-@node  Declaring Groups, Declaring Variables, Declarations, Declarations
-@comment  node-name,  next,  previous,  up
-@subsection Declaring Groups
-
-Use @code{defgroup} to declare new customization groups. 
-
-@defun defgroup symbol members doc [keyword value]...
-Declare @var{symbol} as a customization group containing @var{members}. 
-@var{symbol} does not need to be quoted.
-
-@var{doc} is the group documentation.
-
-@var{members} should be an alist of the form ((@var{name}
-@var{widget})...) where @var{name} is a symbol and @var{widget} is a
-widget for editing that symbol.  Useful widgets are
-@code{custom-variable} for editing variables, @code{custom-face} for
-editing faces, and @code{custom-group} for editing groups.@refill
-
-Internally, custom uses the symbol property @code{custom-group} to keep
-track of the group members, and @code{group-documentation} for the
-documentation string. 
-
-The following additional @var{keyword}'s are defined:
-
-@table @code
-@item :prefix
-@var{value} should be a string.  If the string is a prefix for the name
-of a member of the group, that prefix will be ignored when creating a
-tag for that member.
-@end table
-@end defun
-
-@node  Declaring Variables, Declaring Faces, Declaring Groups, Declarations
-@comment  node-name,  next,  previous,  up
-@subsection Declaring Variables
-
-Use @code{defcustom} to declare user editable variables.
-
-@defun defcustom symbol value doc [keyword value]...
-Declare @var{symbol} as a customizable variable that defaults to @var{value}.
-Neither @var{symbol} nor @var{value} needs to be quoted.
-If @var{symbol} is not already bound, initialize it to @var{value}.
-
-@var{doc} is the variable documentation.
-
-The following additional @var{keyword}'s are defined:
-
-@table @code
-@item :type    
-@var{value} should be a widget type.
-@item :options
-@var{value} should be a list of possible members of the specified type.
-For hooks, this is a list of function names.
-@end table
-
-@xref{Sexp Types,,,widget,The Widget Library}, for information about
-widgets to use together with the @code{:type} keyword.
-@end defun
-
-Internally, custom uses the symbol property @code{custom-type} to keep
-track of the variables type, @code{factory-value} for the program
-specified default value, @code{saved-value} for a value saved by the
-user, and @code{variable-documentation} for the documentation string.
-
-Use @code{custom-add-option} to specify that a specific function is
-useful as an meber of a hook.
-
-@defun custom-add-option symbol option
-To the variable @var{symbol} add @var{option}.
-
-If @var{symbol} is a hook variable, @var{option} should be a hook
-member.  For other types variables, the effect is undefined."
-@end defun
-
-@node  Declaring Faces, Usage for Package Authors, Declaring Variables, Declarations
-@comment  node-name,  next,  previous,  up
-@subsection Declaring Faces
-
-Faces are declared with @code{defface}.
-
-@defun defface face spec doc [keyword value]... 
-
-Declare @var{face} as a customizable face that defaults to @var{spec}.
-@var{face} does not need to be quoted.
-
-If @var{face} has been set with `custom-set-face', set the face attributes
-as specified by that function, otherwise set the face attributes
-according to @var{spec}.
-
-@var{doc} is the face documentation.
-
-@var{spec} should be an alist of the form @samp{((@var{display} @var{atts})...)}.
-
-@var{atts} is a list of face attributes and their values.  The possible
-attributes are defined in the variable `custom-face-attributes'.
-Alternatively, @var{atts} can be a face in which case the attributes of
-that face is used.
-
-The @var{atts} of the first entry in @var{spec} where the @var{display}
-matches the frame should take effect in that frame.  @var{display} can
-either be the symbol `t', which will match all frames, or an alist of
-the form @samp{((@var{req} @var{item}...)...)}@refill
-
-For the @var{display} to match a FRAME, the @var{req} property of the
-frame must match one of the @var{item}.  The following @var{req} are
-defined:@refill
-
-@table @code
-@item type
-(the value of (window-system))@*
-Should be one of @code{x} or @code{tty}.
-
-@item class
-(the frame's color support)@*
-Should be one of @code{color}, @code{grayscale}, or @code{mono}.
-
-@item background
-(what color is used for the background text)@*
-Should be one of @code{light} or @code{dark}.
-@end table
-  
-Internally, custom uses the symbol property @code{factory-face} for the
-program specified default face properties, @code{saved-face} for
-properties saved by the user, and @code{face-doc-string} for the
-documentation string.@refill
-
-@end defun
-
-@node Usage for Package Authors,  , Declaring Faces, Declarations
-@comment  node-name,  next,  previous,  up
-@subsection Usage for Package Authors
-
-The recommended usage for the author of a typical emacs lisp package is
-to create one group identifying the package, and make all user options
-and faces members of that group.  If the package has more than around 20
-such options, they should be divided into a number of subgroups, with
-each subgroup being member of the top level group.
-
-The top level group for the package should itself be member of one or
-more of the standard customization groups.  There exists a group for
-each @emph{finder} keyword.  Press @kbd{C-c p} to see a list of finder
-keywords, and add you group to each of them, using the @code{:group}
-keyword. 
-
-@node  Utilities, The Init File, Declarations, Top
-@comment  node-name,  next,  previous,  up
-@section Utilities
-
-These utilities can come in handy when adding customization support. 
-
-@deffn Widget custom-manual
-Widget type for specifying the info manual entry for a customization
-option.  It takes one argument, an info address.
-@end deffn
-
-@defun custom-add-to-group group member widget
-To existing @var{group} add a new @var{member} of type @var{widget},
-If there already is an entry for that member, overwrite it.
-@end defun
-
-@defun custom-add-link symbol widget
-To the custom option @var{symbol} add the link @var{widget}.
-@end defun
-
-@defun custom-add-load symbol load
-To the custom option @var{symbol} add the dependency @var{load}.
-@var{load} should be either a library file name, or a feature name.
-@end defun
-
-@defun custom-menu-create symbol &optional name
-Create menu for customization group @var{symbol}.
-If optional @var{name} is given, use that as the name of the menu. 
-Otherwise make up a name from @var{symbol}.
-The menu is in a format applicable to @code{easy-menu-define}.
-@end defun
-
-@node  The Init File, Wishlist, Utilities, Top
-@comment  node-name,  next,  previous,  up
-@section The Init File
-
-When you save the customizations, call to @code{custom-set-variables},
-@code{custom-set-faces} are inserted into the file specified by
-@code{custom-file}.  By default @code{custom-file} is your @file{.emacs}
-file.  If you use another file, you must explicitly load it yourself.
-The two functions will initialize variables and faces as you have
-specified.
-
-@node  Wishlist,  , The Init File, Top
-@comment  node-name,  next,  previous,  up
-@section Wishlist
-
-@itemize @bullet
-@item
-The menu items should be grayed out when the information is
-missing.  I.e. if a variable doesn't have a factory setting, the user
-should not be allowed to select the @samp{Factory} menu item.
-
-@item 
-Better support for keyboard operations in the customize buffer.
-
-@item
-Integrate with @file{w3} so you can customization buffers with much
-better formatting.  I'm thinking about adding a <custom>name</custom>
-tag.  The latest w3 have some support for this, so come up with a
-convincing example.
-
-@item
-Add an `examples' section, with explained examples of custom type
-definitions. 
-
-@item
-Support selectable color themes.  I.e., change many faces by setting one
-variable.
-
-@item
-Support undo using lmi's @file{gnus-undo.el}.
-
-@item
-Make it possible to append to `choice', `radio', and `set' options.
-
-@item
-Make it possible to customize code, for example to enable or disable a
-global minor mode.
-
-@item
-Ask whether set or modified variables should be saved in
-@code{kill-buffer-hook}. 
-
-Ditto for @code{kill-emacs-query-functions}.
-
-@item
-Command to check if there are any customization options that
-does not belong to an existing group. 
-
-@item
-Optionally disable the point-cursor and instead highlight the selected
-item in XEmacs.  This is like the *Completions* buffer in XEmacs.
-Suggested by Jens Lautenbacher
-@samp{<jens@@lemming0.lem.uni-karlsruhe.de>}.@refill
-
-@item
-Empty customization groups should start open (harder than it looks).
-
-@item
-Make it possible to include a comment/remark/annotation when saving an
-option.
-
-@end itemize
-
-@contents
-@bye
index a169da0..57e9dec 100644 (file)
--- a/texi/dir
+++ b/texi/dir
@@ -1,9 +1,23 @@
 -*- Text -*-
 The Gnus-related top node.
+
+This is the file .../info/dir, which contains the topmost node of the
+Info hierarchy.  The first time you invoke Info you start off
+looking at that node, which is (dir)Top.
 \1f
 File: dir      Node: Top       This is the Gnus Info tree
+  This (the Directory node) gives a menu of major topics. 
+  Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h" 
+  gives a primer for first-timers, "mEmacs<Return>" visits the Emacs topic,
+  etc.
+  In Emacs, you can click mouse button 2 on a menu item or cross reference
+  to select it.
+  --- PLEASE ADD DOCUMENTATION TO THIS TREE. (See INFO topic first.) ---
 
 * Menu: 
 
-* Gnus: (gnus).                The news reader Gnus.
-* Message: (message).  The Message sending thingamabob.
+* Gnus: (gnus).                        The news reader Gnus.
+* Message: (message).          The Message sending thingamabob.
+* Emacs MIME: (emacs-mime).    Libraries for handling MIME.
+* Sieve: (sieve).              Managing Sieve scripts in Emacs.
+* PGG: (pgg).                  Emacs interface to various PGP implementations.
diff --git a/texi/doclicense.texi b/texi/doclicense.texi
new file mode 100644 (file)
index 0000000..d580caf
--- /dev/null
@@ -0,0 +1,368 @@
+@c -*-texinfo-*-
+@node GNU Free Documentation License, Intro, Copying, Top
+
+@appendix GNU Free Documentation License
+@center Version 1.1, March 2000
+
+@display
+Copyright (C) 2000  Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+@sp 1
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+written document ``free'' in the sense of freedom: to assure everyone
+the effective freedom to copy and redistribute it, with or without
+modifying it, either commercially or noncommercially.  Secondarily,
+this License preserves for the author and publisher a way to get
+credit for their work, while not being considered responsible for
+modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@sp 1
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work that contains a
+notice placed by the copyright holder saying it can be distributed
+under the terms of this License.  The ``Document'', below, refers to any
+such manual or work.  Any member of the public is a licensee, and is
+addressed as ``you''.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall subject
+(or to related matters) and contains nothing that could fall directly
+within that overall subject.  (For example, if the Document is in part a
+textbook of mathematics, a Secondary Section may not explain any
+mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, whose contents can be viewed and edited directly and
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup has been designed to thwart or discourage
+subsequent modification by readers is not Transparent.  A copy that is
+not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML designed for human modification.  Opaque formats include
+PostScript, PDF, proprietary formats that can be read and edited only
+by proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML produced by some word processors for output
+purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+@sp 1
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+@sp 1
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies of the Document numbering more than 100,
+and the Document's license notice requires Cover Texts, you must enclose
+the copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a publicly-accessible computer-network location containing a complete
+Transparent copy of the Document, free of added material, which the
+general network-using public has access to download anonymously at no
+charge using public-standard network protocols.  If you use the latter
+option, you must take reasonably prudent steps, when you begin
+distribution of Opaque copies in quantity, to ensure that this
+Transparent copy will remain thus accessible at the stated location
+until at least one year after the last time you distribute an Opaque
+copy (directly or through your agents or retailers) of that edition to
+the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+@sp 1
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+A. Use in the Title Page (and on the covers, if any) a title distinct
+   from that of the Document, and from those of previous versions
+   (which should, if there were any, be listed in the History section
+   of the Document).  You may use the same title as a previous version
+   if the original publisher of that version gives permission.@*
+B. List on the Title Page, as authors, one or more persons or entities
+   responsible for authorship of the modifications in the Modified
+   Version, together with at least five of the principal authors of the
+   Document (all of its principal authors, if it has less than five).@*
+C. State on the Title page the name of the publisher of the
+   Modified Version, as the publisher.@*
+D. Preserve all the copyright notices of the Document.@*
+E. Add an appropriate copyright notice for your modifications
+   adjacent to the other copyright notices.@*
+F. Include, immediately after the copyright notices, a license notice
+   giving the public permission to use the Modified Version under the
+   terms of this License, in the form shown in the Addendum below.@*
+G. Preserve in that license notice the full lists of Invariant Sections
+   and required Cover Texts given in the Document's license notice.@*
+H. Include an unaltered copy of this License.@*
+I. Preserve the section entitled ``History'', and its title, and add to
+   it an item stating at least the title, year, new authors, and
+   publisher of the Modified Version as given on the Title Page.  If
+   there is no section entitled ``History'' in the Document, create one
+   stating the title, year, authors, and publisher of the Document as
+   given on its Title Page, then add an item describing the Modified
+   Version as stated in the previous sentence.@*
+J. Preserve the network location, if any, given in the Document for
+   public access to a Transparent copy of the Document, and likewise
+   the network locations given in the Document for previous versions
+   it was based on.  These may be placed in the ``History'' section.
+   You may omit a network location for a work that was published at
+   least four years before the Document itself, or if the original
+   publisher of the version it refers to gives permission.@*
+K. In any section entitled ``Acknowledgements'' or ``Dedications'',
+   preserve the section's title, and preserve in the section all the
+   substance and tone of each of the contributor acknowledgements
+   and/or dedications given therein.@*
+L. Preserve all the Invariant Sections of the Document,
+   unaltered in their text and in their titles.  Section numbers
+   or the equivalent are not considered part of the section titles.@*
+M. Delete any section entitled ``Endorsements''.  Such a section
+   may not be included in the Modified Version.@*
+N. Do not retitle any existing section as ``Endorsements''
+   or to conflict in title with any Invariant Section.@*
+@sp 1
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+@sp 1
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections entitled ``History''
+in the various original documents, forming one section entitled
+``History''; likewise combine any sections entitled ``Acknowledgements'',
+and any sections entitled ``Dedications''.  You must delete all sections
+entitled ``Endorsements.''
+@sp 1
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+@sp 1
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, does not as a whole count as a Modified Version
+of the Document, provided no compilation copyright is claimed for the
+compilation.  Such a compilation is called an ``aggregate'', and this
+License does not apply to the other self-contained works thus compiled
+with the Document, on account of their being thus compiled, if they
+are not themselves derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one quarter
+of the entire aggregate, the Document's Cover Texts may be placed on
+covers that surround only the Document within the aggregate.
+Otherwise they must appear on covers around the whole aggregate.
+@sp 1
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License provided that you also include the
+original English version of this License.  In case of a disagreement
+between the translation and the original English version of this
+License, the original English version will prevail.
+@sp 1
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License.  However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+@sp 1
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.  See
+http://www.gnu.org/copyleft/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+
+@end enumerate
+
+@unnumberedsec ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+
+  Copyright (C)  @var{year}  @var{your name}.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.1
+  or any later version published by the Free Software Foundation;
+  with the Invariant Sections being @var{list their titles}, with the
+  Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}.
+  A copy of the license is included in the section entitled ``GNU
+  Free Documentation License''.
+@end group
+@end smallexample
+If you have no Invariant Sections, write ``with no Invariant Sections''
+instead of saying which ones are invariant.  If you have no
+Front-Cover Texts, write ``no Front-Cover Texts'' instead of
+``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
diff --git a/texi/emacs-mime.texi b/texi/emacs-mime.texi
new file mode 100644 (file)
index 0000000..8c51bde
--- /dev/null
@@ -0,0 +1,1793 @@
+\input texinfo
+
+@setfilename emacs-mime
+@settitle Emacs MIME Manual
+@synindex fn cp
+@synindex vr cp
+@synindex pg cp
+@dircategory Emacs
+@direntry
+* Emacs MIME: (emacs-mime).   The MIME de/composition library.
+@end direntry
+@iftex
+@finalout
+@end iftex
+@setchapternewpage odd
+
+@ifnottex
+
+This file documents the Emacs MIME interface functionality.
+
+Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+          Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end ifnottex
+
+@tex
+
+@titlepage
+@title Emacs MIME Manual
+
+@author by Lars Magne Ingebrigtsen
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1998, 1999, 2000, 2001, 2002, 2003 Free Software
+Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being none, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end titlepage
+@page
+
+@end tex
+
+@node Top
+@top Emacs MIME
+
+This manual documents the libraries used to compose and display
+@acronym{MIME} messages.
+
+This manual is directed at users who want to modify the behaviour of
+the @acronym{MIME} encoding/decoding process or want a more detailed
+picture of how the Emacs @acronym{MIME} library works, and people who want
+to write functions and commands that manipulate @acronym{MIME} elements.
+
+@acronym{MIME} is short for @dfn{Multipurpose Internet Mail Extensions}.
+This standard is documented in a number of RFCs; mainly RFC2045 (Format
+of Internet Message Bodies), RFC2046 (Media Types), RFC2047 (Message
+Header Extensions for Non-@acronym{ASCII} Text), RFC2048 (Registration
+Procedures), RFC2049 (Conformance Criteria and Examples).  It is highly
+recommended that anyone who intends writing @acronym{MIME}-compliant software
+read at least RFC2045 and RFC2047.
+
+@menu
+* Decoding and Viewing::  A framework for decoding and viewing.
+* Composing::             @acronym{MML}; a language for describing @acronym{MIME} parts.
+* Interface Functions::   An abstraction over the basic functions.
+* Basic Functions::       Utility and basic parsing functions.
+* Standards::             A summary of RFCs and working documents used.
+* Index::                 Function and variable index.
+@end menu
+
+
+@node Decoding and Viewing
+@chapter Decoding and Viewing
+
+This chapter deals with decoding and viewing @acronym{MIME} messages on a
+higher level.
+
+The main idea is to first analyze a @acronym{MIME} article, and then allow
+other programs to do things based on the list of @dfn{handles} that are
+returned as a result of this analysis.
+
+@menu
+* Dissection::             Analyzing a @acronym{MIME} message.
+* Non-MIME::               Analyzing a non-@acronym{MIME} message.
+* Handles::                Handle manipulations.
+* Display::                Displaying handles.
+* Display Customization::  Variables that affect display.
+* Files and Directories::  Saving and naming attachments.
+* New Viewers::            How to write your own viewers.
+@end menu
+
+
+@node Dissection
+@section Dissection
+
+The @code{mm-dissect-buffer} is the function responsible for dissecting
+a @acronym{MIME} article.  If given a multipart message, it will recursively
+descend the message, following the structure, and return a tree of
+@acronym{MIME} handles that describes the structure of the message.
+
+@node Non-MIME
+@section Non-MIME
+@vindex mm-uu-configure-list
+
+Gnus also understands some non-@acronym{MIME} attachments, such as
+postscript, uuencode, binhex, yenc, shar, forward, gnatsweb, pgp,
+diff.  Each of these features can be disabled by add an item into
+@code{mm-uu-configure-list}.  For example,
+
+@lisp
+(require 'mm-uu)
+(add-to-list 'mm-uu-configure-list '(pgp-signed . disabled))
+@end lisp
+
+@table @code
+@item postscript
+@findex postscript
+Postscript file.
+
+@item uu
+@findex uu
+Uuencoded file.
+
+@item binhex
+@findex binhex
+Binhex encoded file.
+
+@item yenc
+@findex yenc
+Yenc encoded file.
+
+@item shar
+@findex shar
+Shar archive file.
+
+@item forward
+@findex forward
+Non-@acronym{MIME} forwarded message.
+
+@item gnatsweb
+@findex gnatsweb
+Gnatsweb attachment.
+
+@item pgp-signed
+@findex pgp-signed
+@acronym{PGP} signed clear text.
+
+@item pgp-encrypted
+@findex pgp-encrypted
+@acronym{PGP} encrypted clear text.
+
+@item pgp-key
+@findex pgp-key
+@acronym{PGP} public keys.
+
+@item emacs-sources
+@findex emacs-sources
+@vindex mm-uu-emacs-sources-regexp
+Emacs source code.  This item works only in the groups matching
+@code{mm-uu-emacs-sources-regexp}.
+
+@item diff
+@vindex diff
+@vindex mm-uu-diff-groups-regexp
+Patches.  This is intended for groups where diffs of committed files
+are automatically sent to.  It only works in groups matching
+@code{mm-uu-diff-groups-regexp}.
+
+@end table
+
+@node Handles
+@section Handles
+
+A @acronym{MIME} handle is a list that fully describes a @acronym{MIME}
+component.
+
+The following macros can be used to access elements in a handle:
+
+@table @code
+@item mm-handle-buffer
+@findex mm-handle-buffer
+Return the buffer that holds the contents of the undecoded @acronym{MIME}
+part.
+
+@item mm-handle-type
+@findex mm-handle-type
+Return the parsed @code{Content-Type} of the part.
+
+@item mm-handle-encoding
+@findex mm-handle-encoding
+Return the @code{Content-Transfer-Encoding} of the part.
+
+@item mm-handle-undisplayer
+@findex mm-handle-undisplayer
+Return the object that can be used to remove the displayed part (if it
+has been displayed).
+
+@item mm-handle-set-undisplayer
+@findex mm-handle-set-undisplayer
+Set the undisplayer object.
+
+@item mm-handle-disposition
+@findex mm-handle-disposition
+Return the parsed @code{Content-Disposition} of the part.
+
+@item mm-handle-disposition
+@findex mm-handle-disposition
+Return the description of the part.
+
+@item mm-get-content-id
+Returns the handle(s) referred to by @code{Content-ID}.
+
+@end table
+
+
+@node Display
+@section Display
+
+Functions for displaying, removing and saving.
+
+@table @code
+@item mm-display-part
+@findex mm-display-part
+Display the part.
+
+@item mm-remove-part
+@findex mm-remove-part
+Remove the part (if it has been displayed).
+
+@item mm-inlinable-p
+@findex mm-inlinable-p
+Say whether a @acronym{MIME} type can be displayed inline.
+
+@item mm-automatic-display-p
+@findex mm-automatic-display-p
+Say whether a @acronym{MIME} type should be displayed automatically.
+
+@item mm-destroy-part
+@findex mm-destroy-part
+Free all resources occupied by a part.
+
+@item mm-save-part
+@findex mm-save-part
+Offer to save the part in a file.
+
+@item mm-pipe-part
+@findex mm-pipe-part
+Offer to pipe the part to some process.
+
+@item mm-interactively-view-part
+@findex mm-interactively-view-part
+Prompt for a mailcap method to use to view the part.
+
+@end table
+
+
+@node Display Customization
+@section Display Customization
+
+@table @code
+
+@item mm-inline-media-tests
+@vindex mm-inline-media-tests
+This is an alist where the key is a @acronym{MIME} type, the second element
+is a function to display the part @dfn{inline} (i.e., inside Emacs), and
+the third element is a form to be @code{eval}ed to say whether the part
+can be displayed inline.
+
+This variable specifies whether a part @emph{can} be displayed inline,
+and, if so, how to do it.  It does not say whether parts are
+@emph{actually} displayed inline.
+
+@item mm-inlined-types
+@vindex mm-inlined-types
+This, on the other hand, says what types are to be displayed inline, if
+they satisfy the conditions set by the variable above.  It's a list of
+@acronym{MIME} media types.
+
+@item mm-automatic-display
+@vindex mm-automatic-display
+This is a list of types that are to be displayed ``automatically'', but
+only if the above variable allows it.  That is, only inlinable parts can
+be displayed automatically.
+
+@item mm-automatic-external-display
+@vindex mm-automatic-external-display
+This is a list of types that will be displayed automatically in an
+external viewer.
+
+@item mm-keep-viewer-alive-types
+@vindex mm-keep-viewer-alive-types
+This is a list of media types for which the external viewer will not
+be killed when selecting a different article.
+
+@item mm-attachment-override-types
+@vindex mm-attachment-override-types
+Some @acronym{MIME} agents create parts that have a content-disposition of
+@samp{attachment}.  This variable allows overriding that disposition and
+displaying the part inline.  (Note that the disposition is only
+overridden if we are able to, and want to, display the part inline.)
+
+@item mm-discouraged-alternatives
+@vindex mm-discouraged-alternatives
+List of @acronym{MIME} types that are discouraged when viewing
+@samp{multipart/alternative}.  Viewing agents are supposed to view the
+last possible part of a message, as that is supposed to be the richest.
+However, users may prefer other types instead, and this list says what
+types are most unwanted.  If, for instance, @samp{text/html} parts are
+very unwanted, and @samp{text/richtext} parts are somewhat unwanted,
+you could say something like:
+
+@lisp
+(setq mm-discouraged-alternatives
+      '("text/html" "text/richtext")
+      mm-automatic-display
+      (remove "text/html" mm-automatic-display))
+@end lisp
+
+@item mm-inline-large-images
+@vindex mm-inline-large-images
+When displaying inline images that are larger than the window, XEmacs
+does not enable scrolling, which means that you cannot see the whole
+image.  To prevent this, the library tries to determine the image size
+before displaying it inline, and if it doesn't fit the window, the
+library will display it externally (e.g. with @samp{ImageMagick} or
+@samp{xv}).  Setting this variable to @code{t} disables this check and
+makes the library display all inline images as inline, regardless of
+their size.
+
+@item mm-inline-override-types
+@vindex mm-inline-override-types
+@code{mm-inlined-types} may include regular expressions, for example to
+specify that all @samp{text/.*} parts be displayed inline.  If a user
+prefers to have a type that matches such a regular expression be treated
+as an attachment, that can be accomplished by setting this variable to a
+list containing that type.  For example assuming @code{mm-inlined-types}
+includes @samp{text/.*}, then including @samp{text/html} in this
+variable will cause @samp{text/html} parts to be treated as attachments.
+
+@item mm-text-html-renderer
+@vindex mm-text-html-renderer
+This selects the function used to render @acronym{HTML}.  The predefined
+renderers are selected by the symbols @code{w3},
+@code{w3m}@footnote{See @uref{http://emacs-w3m.namazu.org/} for more
+information about emacs-w3m}, @code{links}, @code{lynx},
+@code{w3m-standalone} or @code{html2text}.  If @code{nil} use an
+external viewer.  You can also specify a function, which will be
+called with a @acronym{MIME} handle as the argument.
+
+@item mm-inline-text-html-with-images
+@vindex mm-inline-text-html-with-images
+Some @acronym{HTML} mails might have the trick of spammers using
+@samp{<img>} tags.  It is likely to be intended to verify whether you
+have read the mail.  You can prevent your personal informations from
+leaking by setting this option to @code{nil} (which is the default).
+It is currently ignored by Emacs/w3.  For emacs-w3m, you may use the
+command @kbd{t} on the image anchor to show an image even if it is
+@code{nil}.@footnote{The command @kbd{T} will load all images.  If you
+have set the option @code{w3m-key-binding} to @code{info}, use @kbd{i}
+or @kbd{I} instead.}
+
+@item mm-w3m-safe-url-regexp
+@vindex mm-w3m-safe-url-regexp
+A regular expression that matches safe URL names, i.e. URLs that are
+unlikely to leak personal information when rendering @acronym{HTML}
+email (the default value is @samp{\\`cid:}).  If @code{nil} consider
+all URLs safe.
+
+@item mm-inline-text-html-with-w3m-keymap
+@vindex mm-inline-text-html-with-w3m-keymap
+You can use emacs-w3m command keys in the inlined text/html part by
+setting this option to non-@code{nil}.  The default value is @code{t}.
+
+@item mm-external-terminal-program
+@vindex mm-external-terminal-program
+The program used to start an external terminal.
+
+@item mm-enable-external
+@vindex mm-enable-external
+Indicate whether external MIME handlers should be used.
+
+If @code{t}, all defined external MIME handlers are used.  If
+@code{nil}, files are saved to disk (@code{mailcap-save-binary-file}).
+If it is the symbol @code{ask}, you are prompted before the external
+@acronym{MIME} handler is invoked.
+
+When you launch an attachment through mailcap (@pxref{mailcap}) an
+attempt is made to use a safe viewer with the safest options--this isn't
+the case if you save it to disk and launch it in a different way
+(command line or double-clicking).  Anyhow, if you want to be sure not
+to launch any external programs, set this variable to @code{nil} or
+@code{ask}.
+
+@end table
+
+@node Files and Directories
+@section Files and Directories
+
+@table @code
+
+@item mm-default-directory
+@vindex mm-default-directory
+The default directory for saving attachments.  If @code{nil} use
+@code{default-directory}.
+
+@item mm-tmp-directory
+@vindex mm-tmp-directory
+Directory for storing temporary files.
+
+@item mm-file-name-rewrite-functions
+@vindex mm-file-name-rewrite-functions
+A list of functions used for rewriting file names of @acronym{MIME}
+parts.  Each function is applied successively to the file name.
+Ready-made functions include
+
+@table @code
+@item mm-file-name-delete-control
+@findex mm-file-name-delete-control
+Delete all control characters.
+
+@item mm-file-name-delete-gotchas
+@findex mm-file-name-delete-gotchas
+Delete characters that could have unintended consequences when used
+with flawed shell scripts, i.e. @samp{|}, @samp{>} and @samp{<}; and
+@samp{-}, @samp{.} as the first character.
+
+@item mm-file-name-delete-whitespace
+@findex mm-file-name-delete-whitespace
+Remove all whitespace.
+
+@item mm-file-name-trim-whitespace
+@findex mm-file-name-trim-whitespace
+Remove leading and trailing whitespace.
+
+@item mm-file-name-collapse-whitespace
+@findex mm-file-name-collapse-whitespace
+Collapse multiple whitespace characters.
+
+@item mm-file-name-replace-whitespace
+@findex mm-file-name-replace-whitespace
+@vindex mm-file-name-replace-whitespace
+Replace whitespace with underscores.  Set the variable
+@code{mm-file-name-replace-whitespace} to any other string if you do
+not like underscores.
+@end table
+
+The standard Emacs functions @code{capitalize}, @code{downcase},
+@code{upcase} and @code{upcase-initials} might also prove useful.
+
+@item mm-path-name-rewrite-functions
+@vindex mm-path-name-rewrite-functions
+List of functions used for rewriting the full file names of @acronym{MIME}
+parts.  This is used when viewing parts externally, and is meant for
+transforming the absolute name so that non-compliant programs can find
+the file where it's saved.
+
+@end table
+
+@node New Viewers
+@section New Viewers
+
+Here's an example viewer for displaying @code{text/enriched} inline:
+
+@lisp
+(defun mm-display-enriched-inline (handle)
+  (let (text)
+    (with-temp-buffer
+      (mm-insert-part handle)
+      (save-window-excursion
+        (enriched-decode (point-min) (point-max))
+        (setq text (buffer-string))))
+    (mm-insert-inline handle text)))
+@end lisp
+
+We see that the function takes a @acronym{MIME} handle as its parameter.  It
+then goes to a temporary buffer, inserts the text of the part, does some
+work on the text, stores the result, goes back to the buffer it was
+called from and inserts the result.
+
+The two important helper functions here are @code{mm-insert-part} and
+@code{mm-insert-inline}.  The first function inserts the text of the
+handle in the current buffer.  It handles charset and/or content
+transfer decoding.  The second function just inserts whatever text you
+tell it to insert, but it also sets things up so that the text can be
+``undisplayed'' in a convenient manner.
+
+
+@node Composing
+@chapter Composing
+@cindex Composing
+@cindex MIME Composing
+@cindex MML
+@cindex MIME Meta Language
+
+Creating a @acronym{MIME} message is boring and non-trivial.  Therefore,
+a library called @code{mml} has been defined that parses a language
+called @acronym{MML} (@acronym{MIME} Meta Language) and generates
+@acronym{MIME} messages.
+
+@findex mml-generate-mime
+The main interface function is @code{mml-generate-mime}.  It will
+examine the contents of the current (narrowed-to) buffer and return a
+string containing the @acronym{MIME} message.
+
+@menu
+* Simple MML Example::             An example @acronym{MML} document.
+* MML Definition::                 All valid @acronym{MML} elements.
+* Advanced MML Example::           Another example @acronym{MML} document.
+* Encoding Customization::         Variables that affect encoding.
+* Charset Translation::            How charsets are mapped from @sc{mule} to @acronym{MIME}.
+* Conversion::                     Going from @acronym{MIME} to @acronym{MML} and vice versa.
+* Flowed text::                    Soft and hard newlines.
+@end menu
+
+
+@node Simple MML Example
+@section Simple MML Example
+
+Here's a simple @samp{multipart/alternative}:
+
+@example
+<#multipart type=alternative>
+This is a plain text part.
+<#part type=text/enriched>
+<center>This is a centered enriched part</center>
+<#/multipart>
+@end example
+
+After running this through @code{mml-generate-mime}, we get this:
+
+@example
+Content-Type: multipart/alternative; boundary="=-=-="
+
+
+--=-=-=
+
+
+This is a plain text part.
+
+--=-=-=
+Content-Type: text/enriched
+
+
+<center>This is a centered enriched part</center>
+
+--=-=-=--
+@end example
+
+
+@node MML Definition
+@section MML Definition
+
+The @acronym{MML} language is very simple.  It looks a bit like an SGML
+application, but it's not.
+
+The main concept of @acronym{MML} is the @dfn{part}.  Each part can be of a
+different type or use a different charset.  The way to delineate a part
+is with a @samp{<#part ...>} tag.  Multipart parts can be introduced
+with the @samp{<#multipart ...>} tag.  Parts are ended by the
+@samp{<#/part>} or @samp{<#/multipart>} tags.  Parts started with the
+@samp{<#part ...>} tags are also closed by the next open tag.
+
+There's also the @samp{<#external ...>} tag.  These introduce
+@samp{external/message-body} parts.
+
+Each tag can contain zero or more parameters on the form
+@samp{parameter=value}.  The values may be enclosed in quotation marks,
+but that's not necessary unless the value contains white space.  So
+@samp{filename=/home/user/#hello$^yes} is perfectly valid.
+
+The following parameters have meaning in @acronym{MML}; parameters that have no
+meaning are ignored.  The @acronym{MML} parameter names are the same as the
+@acronym{MIME} parameter names; the things in the parentheses say which
+header it will be used in.
+
+@table @samp
+@item type
+The @acronym{MIME} type of the part (@code{Content-Type}).
+
+@item filename
+Use the contents of the file in the body of the part
+(@code{Content-Disposition}).
+
+@item charset
+The contents of the body of the part are to be encoded in the character
+set specified (@code{Content-Type}). @xref{Charset Translation}.
+
+@item name
+Might be used to suggest a file name if the part is to be saved
+to a file (@code{Content-Type}).
+
+@item disposition
+Valid values are @samp{inline} and @samp{attachment}
+(@code{Content-Disposition}).
+
+@item encoding
+Valid values are @samp{7bit}, @samp{8bit}, @samp{quoted-printable} and
+@samp{base64} (@code{Content-Transfer-Encoding}). @xref{Charset
+Translation}.
+
+@item description
+A description of the part (@code{Content-Description}).
+
+@item creation-date
+RFC822 date when the part was created (@code{Content-Disposition}).
+
+@item modification-date
+RFC822 date when the part was modified (@code{Content-Disposition}).
+
+@item read-date
+RFC822 date when the part was read (@code{Content-Disposition}).
+
+@item recipients
+Who to encrypt/sign the part to.  This field is used to override any
+auto-detection based on the To/CC headers.
+
+@item sender
+Identity used to sign the part.  This field is used to override the
+default key used.
+
+@item size
+The size (in octets) of the part (@code{Content-Disposition}).
+
+@item sign
+What technology to sign this @acronym{MML} part with (@code{smime}, @code{pgp}
+or @code{pgpmime})
+
+@item encrypt
+What technology to encrypt this @acronym{MML} part with (@code{smime},
+@code{pgp} or @code{pgpmime})
+
+@end table
+
+Parameters for @samp{text/plain}:
+
+@table @samp
+@item format
+Formatting parameter for the text, valid values include @samp{fixed}
+(the default) and @samp{flowed}.  Normally you do not specify this
+manually, since it requires the textual body to be formatted in a
+special way described in RFC 2646.  @xref{Flowed text}.
+@end table
+
+Parameters for @samp{application/octet-stream}:
+
+@table @samp
+@item type
+Type of the part; informal---meant for human readers
+(@code{Content-Type}).
+@end table
+
+Parameters for @samp{message/external-body}:
+
+@table @samp
+@item access-type
+A word indicating the supported access mechanism by which the file may
+be obtained.  Values include @samp{ftp}, @samp{anon-ftp}, @samp{tftp},
+@samp{localfile}, and @samp{mailserver}.  (@code{Content-Type}.)
+
+@item expiration
+The RFC822 date after which the file may no longer be fetched.
+(@code{Content-Type}.)
+
+@item size
+The size (in octets) of the file.  (@code{Content-Type}.)
+
+@item permission
+Valid values are @samp{read} and @samp{read-write}
+(@code{Content-Type}).
+
+@end table
+
+Parameters for @samp{sign=smime}:
+
+@table @samp
+
+@item keyfile
+File containing key and certificate for signer.
+
+@end table
+
+Parameters for @samp{encrypt=smime}:
+
+@table @samp
+
+@item certfile
+File containing certificate for recipient.
+
+@end table
+
+
+@node Advanced MML Example
+@section Advanced MML Example
+
+Here's a complex multipart message.  It's a @samp{multipart/mixed} that
+contains many parts, one of which is a @samp{multipart/alternative}.
+
+@example
+<#multipart type=mixed>
+<#part type=image/jpeg filename=~/rms.jpg disposition=inline>
+<#multipart type=alternative>
+This is a plain text part.
+<#part type=text/enriched name=enriched.txt>
+<center>This is a centered enriched part</center>
+<#/multipart>
+This is a new plain text part.
+<#part disposition=attachment>
+This plain text part is an attachment.
+<#/multipart>
+@end example
+
+And this is the resulting @acronym{MIME} message:
+
+@example
+Content-Type: multipart/mixed; boundary="=-=-="
+
+
+--=-=-=
+
+
+
+--=-=-=
+Content-Type: image/jpeg;
+ filename="~/rms.jpg"
+Content-Disposition: inline;
+ filename="~/rms.jpg"
+Content-Transfer-Encoding: base64
+
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof
+Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAwADABAREA/8QAHwAA
+AQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQR
+BRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RF
+RkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ip
+qrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEB
+AAA/AO/rifFHjldNuGsrDa0qcSSHkA+gHrXKw+LtWLrMb+RgTyhbr+HSug07xNqV9fQtZrNI
+AyiaE/NuBPOOOP0rvRNE880KOC8TbXXGCv1FPqjrF4LDR7u5L7SkTFT/ALWOP1xXgTuXfc7E
+sx6nua6rwp4IvvEM8chCxWxOdzn7wz6V9AaB4S07w9p5itow0rDLSY5Pt9K43xO66P4xs71m
+2QXiGCbA4yOVJ9+1aYORkdK434lyNH4ahCnG66VT9Nj15JFbPdX0MS43M4VQf5/yr2vSpLnw
+5ZW8dlCZ8KFXjOPX0/mK6rSPEGt3Angu44fNEReHYNvIH3TzXDeKNO8RX+kSX2ouZkicTIOc
+L+g7E810ulFjpVtv3bwgB3HJyK5L4quY/C9sVxk3ij/xx6850u7t1mtp/wDlpEw3An3Jr3Dw
+34gsbWza4nBlhC5LDsaW6+IFgupQyCF3iHH7gA7c9R9ay7zx6t7aX9jHC4smhfBkGCvHGfrm
+tLQ7hbnRrV1GPkAP1x1/Hr+Ncr8Vzjwrbf8AX6v/AKA9eQRyYlQk8Yx9K6XTNbkgia2ciSIn
+7p5Ga9Atte0LTLKO6it4i7dVRFJDcZ4PvXN+JvEMF9bILVGXJLSZ4zkjivRPDaeX4b08HOTC
+pOffmua+KkbS+GLVUGT9tT/0B68eeIpIFYjB70+OOVXyoOM9+M1eaWeCLzHPyHGO/NVWvJJm
+jQ8KGH1NfQWhXSXmh2c8eArRLwO3HSv/2Q==
+
+--=-=-=
+Content-Type: multipart/alternative; boundary="==-=-="
+
+
+--==-=-=
+
+
+This is a plain text part.
+
+--==-=-=
+Content-Type: text/enriched;
+ name="enriched.txt"
+
+
+<center>This is a centered enriched part</center>
+
+--==-=-=--
+
+--=-=-=
+
+This is a new plain text part.
+
+--=-=-=
+Content-Disposition: attachment
+
+
+This plain text part is an attachment.
+
+--=-=-=--
+@end example
+
+@node Encoding Customization
+@section Encoding Customization
+
+@table @code
+
+@item mm-body-charset-encoding-alist
+@vindex mm-body-charset-encoding-alist
+Mapping from @acronym{MIME} charset to encoding to use.  This variable is
+usually used except, e.g., when other requirements force a specific
+encoding (digitally signed messages require 7bit encodings).  The
+default is 
+
+@lisp
+((iso-2022-jp . 7bit)
+ (iso-2022-jp-2 . 7bit)
+ (utf-16 . base64)
+ (utf-16be . base64)
+ (utf-16le . base64))
+@end lisp
+
+As an example, if you do not want to have ISO-8859-1 characters
+quoted-printable encoded, you may add @code{(iso-8859-1 . 8bit)} to
+this variable.  You can override this setting on a per-message basis
+by using the @code{encoding} @acronym{MML} tag (@pxref{MML Definition}).
+
+@item mm-coding-system-priorities
+@vindex mm-coding-system-priorities
+Prioritize coding systems to use for outgoing messages.  The default
+is @code{nil}, which means to use the defaults in Emacs.  It is a list of
+coding system symbols (aliases of coding systems does not work, use
+@kbd{M-x describe-coding-system} to make sure you are not specifying
+an alias in this variable).  For example, if you have configured Emacs
+to prefer UTF-8, but wish that outgoing messages should be sent in
+ISO-8859-1 if possible, you can set this variable to
+@code{(iso-latin-1)}.  You can override this setting on a per-message
+basis by using the @code{charset} @acronym{MML} tag (@pxref{MML Definition}).
+
+@item mm-content-transfer-encoding-defaults
+@vindex mm-content-transfer-encoding-defaults
+Mapping from @acronym{MIME} types to encoding to use.  This variable is usually
+used except, e.g., when other requirements force a safer encoding
+(digitally signed messages require 7bit encoding).  Besides the normal
+@acronym{MIME} encodings, @code{qp-or-base64} may be used to indicate that for
+each case the most efficient of quoted-printable and base64 should be
+used.  You can override this setting on a per-message basis by using
+the @code{encoding} @acronym{MML} tag (@pxref{MML Definition}).
+
+@item mm-use-ultra-safe-encoding
+@vindex mm-use-ultra-safe-encoding
+When this is non-@code{nil}, it means that textual parts are encoded as
+quoted-printable if they contain lines longer than 76 characters or
+starting with "From " in the body.  Non-7bit encodings (8bit, binary)
+are generally disallowed.  This reduce the probability that a non-8bit
+clean MTA or MDA changes the message.  This should never be set
+directly, but bound by other functions when necessary (e.g., when
+encoding messages that are to be digitally signed).
+
+@end table
+
+@node Charset Translation
+@section Charset Translation
+@cindex charsets
+
+During translation from @acronym{MML} to @acronym{MIME}, for each
+@acronym{MIME} part which has been composed inside Emacs, an appropriate
+charset has to be chosen.
+
+@vindex mail-parse-charset
+If you are running a non-@sc{mule} Emacs, this process is simple: If the
+part contains any non-@acronym{ASCII} (8-bit) characters, the @acronym{MIME} charset
+given by @code{mail-parse-charset} (a symbol) is used.  (Never set this
+variable directly, though.  If you want to change the default charset,
+please consult the documentation of the package which you use to process
+@acronym{MIME} messages.
+@xref{Various Message Variables, , Various Message Variables, message,
+      Message Manual}, for example.)
+If there are only @acronym{ASCII} characters, the @acronym{MIME} charset US-ASCII is
+used, of course.
+
+@cindex MULE
+@cindex UTF-8
+@cindex Unicode
+@vindex mm-mime-mule-charset-alist
+Things are slightly more complicated when running Emacs with @sc{mule}
+support.  In this case, a list of the @sc{mule} charsets used in the
+part is obtained, and the @sc{mule} charsets are translated to @acronym{MIME}
+charsets by consulting the variable @code{mm-mime-mule-charset-alist}.
+If this results in a single @acronym{MIME} charset, this is used to encode
+the part.  But if the resulting list of @acronym{MIME} charsets contains more
+than one element, two things can happen: If it is possible to encode the
+part via UTF-8, this charset is used.  (For this, Emacs must support
+the @code{utf-8} coding system, and the part must consist entirely of
+characters which have Unicode counterparts.)  If UTF-8 is not available
+for some reason, the part is split into several ones, so that each one
+can be encoded with a single @acronym{MIME} charset.  The part can only be
+split at line boundaries, though---if more than one @acronym{MIME} charset is
+required to encode a single line, it is not possible to encode the part.
+
+When running Emacs with @sc{mule} support, the preferences for which
+coding system to use is inherited from Emacs itself.  This means that
+if Emacs is set up to prefer UTF-8, it will be used when encoding
+messages.  You can modify this by altering the
+@code{mm-coding-system-priorities} variable though (@pxref{Encoding
+Customization}).
+
+The charset to be used can be overridden by setting the @code{charset}
+@acronym{MML} tag (@pxref{MML Definition}) when composing the message.
+
+The encoding of characters (quoted-printable, 8bit etc) is orthogonal
+to the discussion here, and is controlled by the variables
+@code{mm-body-charset-encoding-alist} and
+@code{mm-content-transfer-encoding-defaults} (@pxref{Encoding
+Customization}).
+
+@node Conversion
+@section Conversion
+
+@findex mime-to-mml
+A (multipart) @acronym{MIME} message can be converted to @acronym{MML}
+with the @code{mime-to-mml} function.  It works on the message in the
+current buffer, and substitutes @acronym{MML} markup for @acronym{MIME}
+boundaries.  Non-textual parts do not have their contents in the buffer,
+but instead have the contents in separate buffers that are referred to
+from the @acronym{MML} tags.
+
+@findex mml-to-mime
+An @acronym{MML} message can be converted back to @acronym{MIME} by the
+@code{mml-to-mime} function.
+
+These functions are in certain senses ``lossy''---you will not get back
+an identical message if you run @code{mime-to-mml} and then
+@code{mml-to-mime}.  Not only will trivial things like the order of the
+headers differ, but the contents of the headers may also be different.
+For instance, the original message may use base64 encoding on text,
+while @code{mml-to-mime} may decide to use quoted-printable encoding, and
+so on.
+
+In essence, however, these two functions should be the inverse of each
+other.  The resulting contents of the message should remain equivalent,
+if not identical.
+
+
+@node Flowed text
+@section Flowed text
+@cindex format=flowed
+
+The Emacs @acronym{MIME} library will respect the @code{use-hard-newlines}
+variable (@pxref{Hard and Soft Newlines, ,Hard and Soft Newlines,
+emacs, Emacs Manual}) when encoding a message, and the
+``format=flowed'' Content-Type parameter when decoding a message.
+
+On encoding text, regardless of @code{use-hard-newlines}, lines
+terminated by soft newline characters are filled together and wrapped
+after the column decided by @code{fill-flowed-encode-column}.
+Quotation marks (matching @samp{^>* ?}) are respected.  The variable
+controls how the text will look in a client that does not support
+flowed text, the default is to wrap after 66 characters.  If hard
+newline characters are not present in the buffer, no flow encoding
+occurs.
+
+On decoding flowed text, lines with soft newline characters are filled
+together and wrapped after the column decided by
+@code{fill-flowed-display-column}.  The default is to wrap after
+@code{fill-column}.
+
+
+
+
+@node Interface Functions
+@chapter Interface Functions
+@cindex interface functions
+@cindex mail-parse
+
+The @code{mail-parse} library is an abstraction over the actual
+low-level libraries that are described in the next chapter.
+
+Standards change, and so programs have to change to fit in the new
+mold.  For instance, RFC2045 describes a syntax for the
+@code{Content-Type} header that only allows @acronym{ASCII} characters in the
+parameter list.  RFC2231 expands on RFC2045 syntax to provide a scheme
+for continuation headers and non-@acronym{ASCII} characters.
+
+The traditional way to deal with this is just to update the library
+functions to parse the new syntax.  However, this is sometimes the wrong
+thing to do.  In some instances it may be vital to be able to understand
+both the old syntax as well as the new syntax, and if there is only one
+library, one must choose between the old version of the library and the
+new version of the library.
+
+The Emacs @acronym{MIME} library takes a different tack.  It defines a
+series of low-level libraries (@file{rfc2047.el}, @file{rfc2231.el}
+and so on) that parses strictly according to the corresponding
+standard.  However, normal programs would not use the functions
+provided by these libraries directly, but instead use the functions
+provided by the @code{mail-parse} library.  The functions in this
+library are just aliases to the corresponding functions in the latest
+low-level libraries.  Using this scheme, programs get a consistent
+interface they can use, and library developers are free to create
+write code that handles new standards.
+
+The following functions are defined by this library:
+
+@table @code
+@item mail-header-parse-content-type
+@findex mail-header-parse-content-type
+Parse a @code{Content-Type} header and return a list on the following
+format:
+
+@lisp
+("type/subtype"
+ (attribute1 . value1)
+ (attribute2 . value2)
+ ...)
+@end lisp
+
+Here's an example:
+
+@example
+(mail-header-parse-content-type
+ "image/gif; name=\"b980912.gif\"")
+@result{} ("image/gif" (name . "b980912.gif"))
+@end example
+
+@item mail-header-parse-content-disposition
+@findex mail-header-parse-content-disposition
+Parse a @code{Content-Disposition} header and return a list on the same
+format as the function above.
+
+@item mail-content-type-get
+@findex mail-content-type-get
+Takes two parameters---a list on the format above, and an attribute.
+Returns the value of the attribute.
+
+@example
+(mail-content-type-get
+ '("image/gif" (name . "b980912.gif")) 'name)
+@result{} "b980912.gif"
+@end example
+
+@item mail-header-encode-parameter
+@findex mail-header-encode-parameter
+Takes a parameter string and returns an encoded version of the string.
+This is used for parameters in headers like @code{Content-Type} and
+@code{Content-Disposition}.
+
+@item mail-header-remove-comments
+@findex mail-header-remove-comments
+Return a comment-free version of a header.
+
+@example
+(mail-header-remove-comments
+ "Gnus/5.070027 (Pterodactyl Gnus v0.27) (Finnish Landrace)")
+@result{} "Gnus/5.070027  "
+@end example
+
+@item mail-header-remove-whitespace
+@findex mail-header-remove-whitespace
+Remove linear white space from a header.  Space inside quoted strings
+and comments is preserved.
+
+@example
+(mail-header-remove-whitespace
+ "image/gif; name=\"Name with spaces\"")
+@result{} "image/gif;name=\"Name with spaces\""
+@end example
+
+@item mail-header-get-comment
+@findex mail-header-get-comment
+Return the last comment in a header.
+
+@example
+(mail-header-get-comment
+ "Gnus/5.070027 (Pterodactyl Gnus v0.27) (Finnish Landrace)")
+@result{} "Finnish Landrace"
+@end example
+
+@item mail-header-parse-address
+@findex mail-header-parse-address
+Parse an address and return a list containing the mailbox and the
+plaintext name.
+
+@example
+(mail-header-parse-address
+ "Hrvoje Niksic <hniksic@@srce.hr>")
+@result{} ("hniksic@@srce.hr" . "Hrvoje Niksic")
+@end example
+
+@item mail-header-parse-addresses
+@findex mail-header-parse-addresses
+Parse a string with list of addresses and return a list of elements like
+the one described above.
+
+@example
+(mail-header-parse-addresses
+ "Hrvoje Niksic <hniksic@@srce.hr>, Steinar Bang <sb@@metis.no>")
+@result{} (("hniksic@@srce.hr" . "Hrvoje Niksic")
+     ("sb@@metis.no" . "Steinar Bang"))
+@end example
+
+@item mail-header-parse-date
+@findex mail-header-parse-date
+Parse a date string and return an Emacs time structure.
+
+@item mail-narrow-to-head
+@findex mail-narrow-to-head
+Narrow the buffer to the header section of the buffer.  Point is placed
+at the beginning of the narrowed buffer.
+
+@item mail-header-narrow-to-field
+@findex mail-header-narrow-to-field
+Narrow the buffer to the header under point.  Understands continuation
+headers.
+
+@item mail-header-fold-field
+@findex mail-header-fold-field
+Fold the header under point.
+
+@item mail-header-unfold-field
+@findex mail-header-unfold-field
+Unfold the header under point.
+
+@item mail-header-field-value
+@findex mail-header-field-value
+Return the value of the field under point.
+
+@item mail-encode-encoded-word-region
+@findex mail-encode-encoded-word-region
+Encode the non-@acronym{ASCII} words in the region.  For instance,
+@samp{Naïve} is encoded as @samp{=?iso-8859-1?q?Na=EFve?=}.
+
+@item mail-encode-encoded-word-buffer
+@findex mail-encode-encoded-word-buffer
+Encode the non-@acronym{ASCII} words in the current buffer.  This function is
+meant to be called narrowed to the headers of a message.
+
+@item mail-encode-encoded-word-string
+@findex mail-encode-encoded-word-string
+Encode the words that need encoding in a string, and return the result.
+
+@example
+(mail-encode-encoded-word-string
+ "This is naïve, baby")
+@result{} "This is =?iso-8859-1?q?na=EFve,?= baby"
+@end example
+
+@item mail-decode-encoded-word-region
+@findex mail-decode-encoded-word-region
+Decode the encoded words in the region.
+
+@item mail-decode-encoded-word-string
+@findex mail-decode-encoded-word-string
+Decode the encoded words in the string and return the result.
+
+@example
+(mail-decode-encoded-word-string
+ "This is =?iso-8859-1?q?na=EFve,?= baby")
+@result{} "This is naïve, baby"
+@end example
+
+@end table
+
+Currently, @code{mail-parse} is an abstraction over @code{ietf-drums},
+@code{rfc2047}, @code{rfc2045} and @code{rfc2231}.  These are documented
+in the subsequent sections.
+
+
+
+@node Basic Functions
+@chapter Basic Functions
+
+This chapter describes the basic, ground-level functions for parsing and
+handling.  Covered here is parsing @code{From} lines, removing comments
+from header lines, decoding encoded words, parsing date headers and so
+on.  High-level functionality is dealt with in the next chapter
+(@pxref{Decoding and Viewing}).
+
+@menu
+* rfc2045::      Encoding @code{Content-Type} headers.
+* rfc2231::      Parsing @code{Content-Type} headers.
+* ietf-drums::   Handling mail headers defined by RFC822bis.
+* rfc2047::      En/decoding encoded words in headers.
+* time-date::    Functions for parsing dates and manipulating time.
+* qp::           Quoted-Printable en/decoding.
+* base64::       Base64 en/decoding.
+* binhex::       Binhex decoding.
+* uudecode::     Uuencode decoding.
+* yenc::         Yenc decoding.
+* rfc1843::      Decoding HZ-encoded text.
+* mailcap::      How parts are displayed is specified by the @file{.mailcap} file
+@end menu
+
+
+@node rfc2045
+@section rfc2045
+
+RFC2045 is the ``main'' @acronym{MIME} document, and as such, one would
+imagine that there would be a lot to implement.  But there isn't, since
+most of the implementation details are delegated to the subsequent
+RFCs.
+
+So @file{rfc2045.el} has only a single function:
+
+@table @code
+@item rfc2045-encode-string
+@findex rfc2045-encode-string
+Takes a parameter and a value and returns a @samp{PARAM=VALUE} string.
+@var{value} will be quoted if there are non-safe characters in it.
+@end table
+
+
+@node rfc2231
+@section rfc2231
+
+RFC2231 defines a syntax for the @code{Content-Type} and
+@code{Content-Disposition} headers.  Its snappy name is @dfn{MIME
+Parameter Value and Encoded Word Extensions: Character Sets, Languages,
+and Continuations}.
+
+In short, these headers look something like this:
+
+@example
+Content-Type: application/x-stuff;
+ title*0*=us-ascii'en'This%20is%20even%20more%20;
+ title*1*=%2A%2A%2Afun%2A%2A%2A%20;
+ title*2="isn't it!"
+@end example
+
+They usually aren't this bad, though.
+
+The following functions are defined by this library:
+
+@table @code
+@item rfc2231-parse-string
+@findex rfc2231-parse-string
+Parse a @code{Content-Type} header and return a list describing its
+elements.
+
+@example
+(rfc2231-parse-string
+ "application/x-stuff;
+ title*0*=us-ascii'en'This%20is%20even%20more%20;
+ title*1*=%2A%2A%2Afun%2A%2A%2A%20;
+ title*2=\"isn't it!\"")
+@result{} ("application/x-stuff"
+    (title . "This is even more ***fun*** isn't it!"))
+@end example
+
+@item rfc2231-get-value
+@findex rfc2231-get-value
+Takes one of the lists on the format above and returns
+the value of the specified attribute.
+
+@item rfc2231-encode-string
+@findex rfc2231-encode-string
+Encode a parameter in headers likes @code{Content-Type} and
+@code{Content-Disposition}.
+
+@end table
+
+
+@node ietf-drums
+@section ietf-drums
+
+@dfn{drums} is an IETF working group that is working on the replacement
+for RFC822.
+
+The functions provided by this library include:
+
+@table @code
+@item ietf-drums-remove-comments
+@findex ietf-drums-remove-comments
+Remove the comments from the argument and return the results.
+
+@item ietf-drums-remove-whitespace
+@findex ietf-drums-remove-whitespace
+Remove linear white space from the string and return the results.
+Spaces inside quoted strings and comments are left untouched.
+
+@item ietf-drums-get-comment
+@findex ietf-drums-get-comment
+Return the last most comment from the string.
+
+@item ietf-drums-parse-address
+@findex ietf-drums-parse-address
+Parse an address string and return a list that contains the mailbox and
+the plain text name.
+
+@item ietf-drums-parse-addresses
+@findex ietf-drums-parse-addresses
+Parse a string that contains any number of comma-separated addresses and
+return a list that contains mailbox/plain text pairs.
+
+@item ietf-drums-parse-date
+@findex ietf-drums-parse-date
+Parse a date string and return an Emacs time structure.
+
+@item ietf-drums-narrow-to-header
+@findex ietf-drums-narrow-to-header
+Narrow the buffer to the header section of the current buffer.
+
+@end table
+
+
+@node rfc2047
+@section rfc2047
+
+RFC2047 (Message Header Extensions for Non-@acronym{ASCII} Text) specifies how
+non-@acronym{ASCII} text in headers are to be encoded.  This is actually rather
+complicated, so a number of variables are necessary to tweak what this
+library does.
+
+The following variables are tweakable:
+
+@table @code
+@item rfc2047-default-charset
+@vindex rfc2047-default-charset
+Characters in this charset should not be decoded by this library.
+This defaults to @code{iso-8859-1}.
+
+@item rfc2047-header-encoding-alist
+@vindex rfc2047-header-encoding-alist
+This is an alist of header / encoding-type pairs.  Its main purpose is
+to prevent encoding of certain headers.
+
+The keys can either be header regexps, or @code{t}.
+
+The values can be either @code{nil}, in which case the header(s) in
+question won't be encoded, or @code{mime}, which means that they will be
+encoded.
+
+@item rfc2047-charset-encoding-alist
+@vindex rfc2047-charset-encoding-alist
+RFC2047 specifies two forms of encoding---@code{Q} (a
+Quoted-Printable-like encoding) and @code{B} (base64).  This alist
+specifies which charset should use which encoding.
+
+@item rfc2047-encoding-function-alist
+@vindex rfc2047-encoding-function-alist
+This is an alist of encoding / function pairs.  The encodings are
+@code{Q}, @code{B} and @code{nil}.
+
+@item rfc2047-q-encoding-alist
+@vindex rfc2047-q-encoding-alist
+The @code{Q} encoding isn't quite the same for all headers.  Some
+headers allow a narrower range of characters, and that is what this
+variable is for.  It's an alist of header regexps / allowable character
+ranges.
+
+@item rfc2047-encoded-word-regexp
+@vindex rfc2047-encoded-word-regexp
+When decoding words, this library looks for matches to this regexp.
+
+@end table
+
+Those were the variables, and these are this functions:
+
+@table @code
+@item rfc2047-narrow-to-field
+@findex rfc2047-narrow-to-field
+Narrow the buffer to the header on the current line.
+
+@item rfc2047-encode-message-header
+@findex rfc2047-encode-message-header
+Should be called narrowed to the header of a message.  Encodes according
+to @code{rfc2047-header-encoding-alist}.
+
+@item rfc2047-encode-region
+@findex rfc2047-encode-region
+Encodes all encodable words in the region specified.
+
+@item rfc2047-encode-string
+@findex rfc2047-encode-string
+Encode a string and return the results.
+
+@item rfc2047-decode-region
+@findex rfc2047-decode-region
+Decode the encoded words in the region.
+
+@item rfc2047-decode-string
+@findex rfc2047-decode-string
+Decode a string and return the results.
+
+@end table
+
+
+@node time-date
+@section time-date
+
+While not really a part of the @acronym{MIME} library, it is convenient to
+document this library here.  It deals with parsing @code{Date} headers
+and manipulating time.  (Not by using tesseracts, though, I'm sorry to
+say.)
+
+These functions convert between five formats: A date string, an Emacs
+time structure, a decoded time list, a second number, and a day number.
+
+Here's a bunch of time/date/second/day examples:
+
+@example
+(parse-time-string "Sat Sep 12 12:21:54 1998 +0200")
+@result{} (54 21 12 12 9 1998 6 nil 7200)
+
+(date-to-time "Sat Sep 12 12:21:54 1998 +0200")
+@result{} (13818 19266)
+
+(time-to-seconds '(13818 19266))
+@result{} 905595714.0
+
+(seconds-to-time 905595714.0)
+@result{} (13818 19266 0)
+
+(time-to-days '(13818 19266))
+@result{} 729644
+
+(days-to-time 729644)
+@result{} (961933 65536)
+
+(time-since '(13818 19266))
+@result{} (0 430)
+
+(time-less-p '(13818 19266) '(13818 19145))
+@result{} nil
+
+(subtract-time '(13818 19266) '(13818 19145))
+@result{} (0 121)
+
+(days-between "Sat Sep 12 12:21:54 1998 +0200"
+              "Sat Sep 07 12:21:54 1998 +0200")
+@result{} 5
+
+(date-leap-year-p 2000)
+@result{} t
+
+(time-to-day-in-year '(13818 19266))
+@result{} 255
+
+(time-to-number-of-days
+ (time-since
+  (date-to-time "Mon, 01 Jan 2001 02:22:26 GMT")))
+@result{} 4.146122685185185
+@end example
+
+And finally, we have @code{safe-date-to-time}, which does the same as
+@code{date-to-time}, but returns a zero time if the date is
+syntactically malformed.
+
+The five data representations used are the following:
+
+@table @var
+@item date
+An RFC822 (or similar) date string.  For instance: @code{"Sat Sep 12
+12:21:54 1998 +0200"}.
+
+@item time
+An internal Emacs time.  For instance: @code{(13818 26466)}.
+
+@item seconds
+A floating point representation of the internal Emacs time.  For
+instance: @code{905595714.0}.
+
+@item days
+An integer number representing the number of days since 00000101.  For
+instance: @code{729644}.
+
+@item decoded time
+A list of decoded time.  For instance: @code{(54 21 12 12 9 1998 6 t
+7200)}.
+@end table
+
+All the examples above represent the same moment.
+
+These are the functions available:
+
+@table @code
+@item date-to-time
+Take a date and return a time.
+
+@item time-to-seconds
+Take a time and return seconds.
+
+@item seconds-to-time
+Take seconds and return a time.
+
+@item time-to-days
+Take a time and return days.
+
+@item days-to-time
+Take days and return a time.
+
+@item date-to-day
+Take a date and return days.
+
+@item time-to-number-of-days
+Take a time and return the number of days that represents.
+
+@item safe-date-to-time
+Take a date and return a time.  If the date is not syntactically valid,
+return a ``zero'' date.
+
+@item time-less-p
+Take two times and say whether the first time is less (i. e., earlier)
+than the second time.
+
+@item time-since
+Take a time and return a time saying how long it was since that time.
+
+@item subtract-time
+Take two times and subtract the second from the first.  I. e., return
+the time between the two times.
+
+@item days-between
+Take two days and return the number of days between those two days.
+
+@item date-leap-year-p
+Take a year number and say whether it's a leap year.
+
+@item time-to-day-in-year
+Take a time and return the day number within the year that the time is
+in.
+
+@end table
+
+
+@node qp
+@section qp
+
+This library deals with decoding and encoding Quoted-Printable text.
+
+Very briefly explained, qp encoding means translating all 8-bit
+characters (and lots of control characters) into things that look like
+@samp{=EF}; that is, an equal sign followed by the byte encoded as a hex
+string.
+
+The following functions are defined by the library:
+
+@table @code
+@item quoted-printable-decode-region
+@findex quoted-printable-decode-region
+QP-decode all the encoded text in the specified region.
+
+@item quoted-printable-decode-string
+@findex quoted-printable-decode-string
+Decode the QP-encoded text in a string and return the results.
+
+@item quoted-printable-encode-region
+@findex quoted-printable-encode-region
+QP-encode all the encodable characters in the specified region.  The third
+optional parameter @var{fold} specifies whether to fold long lines.
+(Long here means 72.)
+
+@item quoted-printable-encode-string
+@findex quoted-printable-encode-string
+QP-encode all the encodable characters in a string and return the
+results.
+
+@end table
+
+
+@node base64
+@section base64
+@cindex base64
+
+Base64 is an encoding that encodes three bytes into four characters,
+thereby increasing the size by about 33%.  The alphabet used for
+encoding is very resistant to mangling during transit.
+
+The following functions are defined by this library:
+
+@table @code
+@item base64-encode-region
+@findex base64-encode-region
+base64 encode the selected region.  Return the length of the encoded
+text.  Optional third argument @var{no-line-break} means do not break
+long lines into shorter lines.
+
+@item base64-encode-string
+@findex base64-encode-string
+base64 encode a string and return the result.
+
+@item base64-decode-region
+@findex base64-decode-region
+base64 decode the selected region.  Return the length of the decoded
+text.  If the region can't be decoded, return @code{nil} and don't
+modify the buffer.
+
+@item base64-decode-string
+@findex base64-decode-string
+base64 decode a string and return the result.  If the string can't be
+decoded, @code{nil} is returned.
+
+@end table
+
+
+@node binhex
+@section binhex
+@cindex binhex
+@cindex Apple
+@cindex Macintosh
+
+@code{binhex} is an encoding that originated in Macintosh environments.
+The following function is supplied to deal with these:
+
+@table @code
+@item binhex-decode-region
+@findex binhex-decode-region
+Decode the encoded text in the region.  If given a third parameter, only
+decode the @code{binhex} header and return the filename.
+
+@end table
+
+@node uudecode
+@section uudecode
+@cindex uuencode
+@cindex uudecode
+
+@code{uuencode} is probably still the most popular encoding of binaries
+used on Usenet, although @code{base64} rules the mail world.
+
+The following function is supplied by this package:
+
+@table @code
+@item uudecode-decode-region
+@findex uudecode-decode-region
+Decode the text in the region.
+@end table
+
+
+@node yenc
+@section yenc
+@cindex yenc
+
+@code{yenc} is used for encoding binaries on Usenet.  The following
+function is supplied by this package:
+
+@table @code
+@item yenc-decode-region
+@findex yenc-decode-region
+Decode the encoded text in the region.
+
+@end table
+
+
+@node rfc1843
+@section rfc1843
+@cindex rfc1843
+@cindex HZ
+@cindex Chinese
+
+RFC1843 deals with mixing Chinese and @acronym{ASCII} characters in messages.  In
+essence, RFC1843 switches between @acronym{ASCII} and Chinese by doing this:
+
+@example
+This sentence is in @acronym{ASCII}.
+The next sentence is in GB.~@{<:Ky2;S@{#,NpJ)l6HK!#~@}Bye.
+@end example
+
+Simple enough, and widely used in China.
+
+The following functions are available to handle this encoding:
+
+@table @code
+@item rfc1843-decode-region
+Decode HZ-encoded text in the region.
+
+@item rfc1843-decode-string
+Decode a HZ-encoded string and return the result.
+
+@end table
+
+
+@node mailcap
+@section mailcap
+
+The @file{~/.mailcap} file is parsed by most @acronym{MIME}-aware message
+handlers and describes how elements are supposed to be displayed.
+Here's an example file:
+
+@example
+image/*; gimp -8 %s
+audio/wav; wavplayer %s
+application/msword; catdoc %s ; copiousoutput ; nametemplate=%s.doc
+@end example
+
+This says that all image files should be displayed with @code{gimp},
+that WAVE audio files should be played by @code{wavplayer}, and that
+MS-WORD files should be inlined by @code{catdoc}.
+
+The @code{mailcap} library parses this file, and provides functions for
+matching types.
+
+@table @code
+@item mailcap-mime-data
+@vindex mailcap-mime-data
+This variable is an alist of alists containing backup viewing rules.
+
+@end table
+
+Interface functions:
+
+@table @code
+@item mailcap-parse-mailcaps
+@findex mailcap-parse-mailcaps
+Parse the @file{~/.mailcap} file.
+
+@item mailcap-mime-info
+Takes a @acronym{MIME} type as its argument and returns the matching viewer.
+
+@end table
+
+
+
+
+@node Standards
+@chapter Standards
+
+The Emacs @acronym{MIME} library implements handling of various elements
+according to a (somewhat) large number of RFCs, drafts and standards
+documents.  This chapter lists the relevant ones.  They can all be
+fetched from @uref{http://quimby.gnus.org/notes/}.
+
+@table @dfn
+@item RFC822
+@itemx STD11
+Standard for the Format of ARPA Internet Text Messages.
+
+@item RFC1036
+Standard for Interchange of USENET Messages
+
+@item RFC2045
+Format of Internet Message Bodies
+
+@item RFC2046
+Media Types
+
+@item RFC2047
+Message Header Extensions for Non-@acronym{ASCII} Text
+
+@item RFC2048
+Registration Procedures
+
+@item RFC2049
+Conformance Criteria and Examples
+
+@item RFC2231
+@acronym{MIME} Parameter Value and Encoded Word Extensions: Character Sets,
+Languages, and Continuations
+
+@item RFC1843
+HZ - A Data Format for Exchanging Files of Arbitrarily Mixed Chinese and
+@acronym{ASCII} characters
+
+@item draft-ietf-drums-msg-fmt-05.txt
+Draft for the successor of RFC822
+
+@item RFC2112
+The @acronym{MIME} Multipart/Related Content-type
+
+@item RFC1892
+The Multipart/Report Content Type for the Reporting of Mail System
+Administrative Messages
+
+@item RFC2183
+Communicating Presentation Information in Internet Messages: The
+Content-Disposition Header Field
+
+@item RFC2646
+Documentation of the text/plain format parameter for flowed text.
+
+@end table
+
+
+@node Index
+@chapter Index
+@printindex cp
+
+@summarycontents
+@contents
+@bye
+
+\f
+@c Local Variables:
+@c mode: texinfo
+@c coding: iso-8859-1
+@c End:
diff --git a/texi/etc/bar.xpm b/texi/etc/bar.xpm
new file mode 100644 (file)
index 0000000..2985065
--- /dev/null
@@ -0,0 +1,54 @@
+/* XPM */
+static char * picon-bar_xpm[] = {
+"6 48 2 1",
+"      c white s background",
+".     c black",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  ",
+"  ..  "};
diff --git a/texi/etc/gnus-group-catchup-current-up.xpm b/texi/etc/gnus-group-catchup-current-up.xpm
new file mode 100644 (file)
index 0000000..0504f9d
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"         ....                   ",
+"        .XXXX.             .... ",
+"        .XXXX.            .XXXX.",
+"         .XXX.            .XXXX.",
+" .........XX.              .XXX.",
+".ooooooooo..       .........XX. ",
+".o....ooooo...... .ooooooooo..  ",
+"X.   .ooooooooo.X..o....ooooo.  ",
+"X.   .oooo........X.   .ooooo.  ",
+".   .oooo.       .X.   .ooooo.  ",
+"    .oooo.       ..   .oooo.o.  ",
+"   .oooo.             .oooo.o.  ",
+"   ......            .ooooo.oo..",
+"  .ooooo.            ...... ..X.",
+"  .ooooo.           .ooooo.   ..",
+" .o..ooo.           ..oooo.     ",
+".ooo..ooo.XXXXXXXXX.o..ooo.XXXXX",
+"ooo.XX.oo.XXX......ooo..ooo.XXXX",
+"oo.XXX.oo.XXX..oooooo.XX.oo.XXXX",
+"..XXXX.oo.XXX..ooooo.XXX.oo.XXXX",
+"XXXXXXX.oo.XX.......XXX .oo.XXXX",
+"XXXXXXX.....X..XXXXXXXXXX.oo.XXX",
+"XXXXXXXXXXXXX.XXXXXXXXXXX.....XX",
+"XXXXXXXXXXXXXXXXXXXXXXXXX......X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/texi/etc/gnus-group-catchup-current.xpm b/texi/etc/gnus-group-catchup-current.xpm
new file mode 100644 (file)
index 0000000..bea4643
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"         ....                   ",
+"        .XXXX.             .... ",
+"        .XXXX.            .XXXX.",
+"         .XXX.            .XXXX.",
+" .........XX.              .XXX.",
+".ooooooooo..       .........XX. ",
+".o....ooooo...... .ooooooooo..  ",
+"X.   .ooooooooo.X..o....ooooo.  ",
+"X.   .oooo........X.   .ooooo.  ",
+".   .oooo.       .X.   .ooooo.  ",
+"    .oooo.       ..   .oooo.o.  ",
+"   .oooo.             .oooo.o.  ",
+"   ......            .ooooo.oo..",
+"  .ooooo.            ...... ..X.",
+"  .ooooo.           .ooooo.   ..",
+" .o..ooo.           ..oooo.     ",
+".ooo..ooo.XXXXXXXXX.o..ooo.XXXXX",
+"ooo.XX.oo.XXX......ooo..ooo.XXXX",
+"oo.XXX.oo.XXX..oooooo.XX.oo.XXXX",
+"..XXXX.oo.XXX..ooooo.XXX.oo.XXXX",
+"XXXXXXX.oo.XX.......XXX .oo.XXXX",
+"XXXXXXX.....X..XXXXXXXXXX.oo.XXX",
+"XXXXXXXXXXXXX.XXXXXXXXXXX.....XX",
+"XXXXXXXXXXXXXXXXXXXXXXXXX......X",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
diff --git a/texi/etc/gnus-group-describe-group-up.xpm b/texi/etc/gnus-group-describe-group-up.xpm
new file mode 100644 (file)
index 0000000..e0ffde7
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-describe-group_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #999999999999 s backgroundToolBarColor",
+"X     c #FFFFFFFFFFFF",
+"o     c #BFBFBFBFBFBF",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".......................XXXXX....",
+" ... ... ... ... ... XXX XXXXX..",
+"....................XXXXXXXXXXX.",
+"...................XXXXXXXXXXXXX",
+"..................XXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+"................XXXXXXXXXXXXXXXX",
+" ... ... ... ... XXX XXX XXX XXX",
+".................XXXXXXXXXXXXXXX",
+".................XXXXXXXXXXXXXXX",
+".......    .......XXXXXXXXXXXXXX",
+" ... . oooo  ... ..X XXX XXX XXX",
+"..... o...oo .......XXXXXXXXXXX.",
+".... .o....o. .......XXXXXXXXX..",
+".... o . ...  .........XXXXX....",
+" ...  o .. .  .. ... ... ... ...",
+"...  o   . .  ..................",
+"..  X . . .  ...................",
+".  o .   .  ....................",
+"   o       . ... ... ... ... ...",
+" o     .........................",
+"o .   ...o......................",
+"     ..........................."};
diff --git a/texi/etc/gnus-group-exit-up.xpm b/texi/etc/gnus-group-exit-up.xpm
new file mode 100644 (file)
index 0000000..1b8982f
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-exit-gnus_xpm[] = {
+"32 32 4 1",
+"      c #FFFFFFFFFFFF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #BFBFBFBFBFBF",
+"                      .         ",
+"            ..      ..          ",
+"           . ..    ...          ",
+"   ...       ..    .  .         ",
+"  . . ...   .  . .... .....     ",
+"   . .. ....  ..... .. . . ..   ",
+"       .  . .. . ... .. . .     ",
+"         .   ......             ",
+"         .... ... ...           ",
+"     .... ......... ...         ",
+"    .. . . .X.. ..  ....        ",
+"     .    .X.  .. .  . ...      ",
+"         .X. . . ..    . .      ",
+"        .X.  ..  ..      .      ",
+".. . . ..X.. .. .... . ..  .. . ",
+"ooooooo.X.ooo..ooo..oo ooooooooo",
+"oooo oo.X.ooo.ooooo..oooooooo oo",
+"o oooo.X.ooooooo ooo.ooooooooooo",
+"oooooo.X.ooooooooooooooo ooooooo",
+"ooo oo.X.ooo ooooooooooooooooooo",
+"oooooo.X.oooooooooo  oooooo  ooo",
+"ooooo.X.ooooooooooooooo  ooooooo",
+"o ooo.X.oooooo ooooooooooooooooo",
+"ooooo.X.oooo  o  ooooooooo ooooo",
+"ooooo.X.ooooooooooo oooo  o  ooo",
+"oo....X...ooooooo  o  oooooooooo",
+"o..XX...XX..ooo.o.oo.oo oooooooo",
+".XX.XX..X.XX...ooo.oo  o  oooooo",
+"X.XX.XXXXXXXXXX..oooo.o.oooooo o",
+".................o.o oo.oooo  o ",
+"oooooo ooo.oo oo.o  .  ooooooooo",
+"oooo  o  oo  o  oooooooooooooooo"};
diff --git a/texi/etc/gnus-group-get-new-news-this-group-up.xpm b/texi/etc/gnus-group-get-new-news-this-group-up.xpm
new file mode 100644 (file)
index 0000000..918fd2e
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-get-new-news-this-group_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" ..........                     ",
+" .XXXXXXXX.                     ",
+" .XXXXXXXX.                     ",
+" .XXXXXXXX.         ....        ",
+" .XXXXXXXX.        .oooo.       ",
+" .XXXXXXX....     .oooooo.      ",
+" .XXXXXXX..  .    .oooooo.      ",
+" .XXXXXXXX...o.   .oooooo.      ",
+" .XXXXXXXX..ooo.   .oooo.       ",
+" .XXXXXXXX. .ooo.   .oo.        ",
+" .XXXXXXXX.  .ooo.....o....     ",
+" .XXXXXXXX.   .oooooooooooo.    ",
+" ..........   .oooooooooooo.    ",
+"               .oooooooooooo.   ",
+"                .oooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 .ooooooo.oo.   ",
+"                 ............   ",
+"                .oooooo.   .    ",
+"                .ooooooo.. .    ",
+"                .ooooooo.  .    ",
+"                .oooo.oo...     ",
+"                .oooo.oooo.     ",
+"                .ooo. .ooo.     ",
+"                ..... .....     ",
+"                 .o.   .o.      ",
+"                 .o.   .o.      "};
diff --git a/texi/etc/gnus-group-get-new-news-up.xpm b/texi/etc/gnus-group-get-new-news-up.xpm
new file mode 100644 (file)
index 0000000..d324784
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-get-new-news_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"..........                      ",
+".XXXXXXXX.                      ",
+".XXXXXXXX.                      ",
+".XXXXXXXX.         ....         ",
+".XXXXXXXX.        .oooo.        ",
+".XXXXXXX....     .oooooo.       ",
+".XXXXXXX..  .    .oooooo.       ",
+".XXXXXXXX...o.   .oooooo.       ",
+".XXXXXXXX..ooo.   .oooo.        ",
+".XXXXXXXX. .ooo.   .oo.         ",
+".XXXXXXXX.  .ooo.....o....      ",
+".XXXXXXXX.   .oooooooooooo.     ",
+"..........   .oooooooooooo.     ",
+"              .oooooooooooo.    ",
+"               .ooooooooooo.    ",
+"                .o.......oo.....",
+"                .o.XXXXX.oo.XXX.",
+"                .o.XXXX.ooo.XXX.",
+"                .o.XXXX.oo.XXXX.",
+"                .o.XXX.ooo.XXXX.",
+"                .o.XXX.oo.XXXXX.",
+"                ...XX...o.XXXXX.",
+"               .oo.X.   .XXXXXX.",
+"               .oo.XX.. .XXXXXX.",
+"               .oo....  ........",
+"               .oooo.o..o.      ",
+"               .oooo.oooo.      ",
+"               .ooo. .ooo.      ",
+"               ..... .....      ",
+"                .o.   .o.       ",
+"                .o.   .o.       "};
diff --git a/texi/etc/gnus-group-kill-group-up.xpm b/texi/etc/gnus-group-kill-group-up.xpm
new file mode 100644 (file)
index 0000000..e728bf5
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-killfile_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXXXXXXXX..         ",
+"      .XXXXXXXXXXXXXX.X.        ",
+"      .XXXXXXX...XXXX.XX.       ",
+"      .XXXXXX.....XXX.....      ",
+"      .XXXXX..X.X..XXXXXX.      ",
+"      .XXXXX.......XXXXXX.      ",
+"      .XXXXX...X...XXXXXX.      ",
+"      .XXXXXX.....XXXXXXX.      ",
+"      .XXXXXXX.X.XXXXXXXX.      ",
+"      .XXXXXXX.X.XXXXXXXX.      ",
+"      .XXXX.XX...X.XXXXXX.      ",
+"      .XXX..XXXXXX..XXXXX.      ",
+"      .XXXXX..XX..XXXXXXX.      ",
+"      .XXXXXXX..XXXXXXXXX.      ",
+"      .XXXXXXX..XXXXXXXXX.      ",
+"      .XXXXX..XX..XXXXXXX.      ",
+"      .XXX..XXXXXX..XXXXX.      ",
+"      .XXXX.XXXXXX.XXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-group-subscribe-up.xpm b/texi/etc/gnus-group-subscribe-up.xpm
new file mode 100644 (file)
index 0000000..15f7d43
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-unsubscribe_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXX.XXXXX..         ",
+"      .XX.X.XXX.XXXXX.X.        ",
+"      .XXX.XXXX.XXXXX.XX.       ",
+"      .XX.X.XXX.XXXXX.....      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-group-unsubscribe-up.xpm b/texi/etc/gnus-group-unsubscribe-up.xpm
new file mode 100644 (file)
index 0000000..7c7ce5b
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-subscribe_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXX.XXXXX..         ",
+"      .XXXXXX.X.XXXXX.X.        ",
+"      .XXXXX.XX.XXXXX.XX.       ",
+"      .XX.X.XXX.XXXXX.....      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXX.X.XXXXXXXXX.      ",
+"      .XXXXX.XX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXX.X.XXXXXXXXX.      ",
+"      .XXXXX.XX.XXXXXXXXX.      ",
+"      .XX.X.XXX.XXXXXXXXX.      ",
+"      .XXX.XXXX.XXXXXXXXX.      ",
+"      ..........XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      .XXXXXXXX.XXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-caesar-message-up.xpm b/texi/etc/gnus-summary-caesar-message-up.xpm
new file mode 100644 (file)
index 0000000..6f56aa9
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-rot13_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ................          ",
+"      .XXXXXXXXXXXXXX..         ",
+"      .XX..XX...XXX...X.        ",
+"      .X.XX.X.XX.X.XX.XX.       ",
+"      .X.XX.X.X.XX.XX.....      ",
+"      .X....X.XX.X.XXXXXX.      ",
+"      .X.XX.X...XXX...XXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XX.XXXXX.XXXX.XXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .X..X.XX..XX...XXXX.      ",
+"      .X..X.X.XX.X.XX.XXX.      ",
+"      .X.X..X.XX.X...XXXX.      ",
+"      .X.X..X.XX.X.XXXXXX.      ",
+"      .X.XX.XX..XX.XXXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      .XXXX..XXXXXXXXXXXX.      ",
+"      .XXX....XXXXXXXXXXX.      ",
+"      .XX..XX.........XXX.      ",
+"      .XX..XX.........XXX.      ",
+"      .XXX....XXX.X.X.XXX.      ",
+"      .XXXX..XXXX.X.X.XXX.      ",
+"      .XXXXXXXXXXXX.XXXXX.      ",
+"      .XXXXXXXXXXXXXXXXXX.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-cancel-article-up.xpm b/texi/etc/gnus-summary-cancel-article-up.xpm
new file mode 100644 (file)
index 0000000..fa7c639
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-cancel-post_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+" ... ... ... ... ....... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ...    .... ... ...",
+"...............  XX ............",
+".............  XXXX  ...........",
+"...........  XXXX  X ...........",
+" ... ....  XXXXX   X ... ... ...",
+"........ XXXXXXX  XXX ..........",
+"........ XXXXXX oXXXX ..........",
+"........o XXXXXXXoXXXX .........",
+" ... ...oo XXXXXXXX    . ... ...",
+".........oo XXXXX  oooo.........",
+"..........oo     o..............",
+"..........ooooooo...............",
+" ... ... ... oo. ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................"};
diff --git a/texi/etc/gnus-summary-catchup-and-exit-up.xpm b/texi/etc/gnus-summary-catchup-and-exit-up.xpm
new file mode 100644 (file)
index 0000000..a5d8ba6
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-catchup_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"               ......           ",
+"           ..  .XXXX.           ",
+"          .X.  .XXXX.           ",
+"        ..XX...XXXXX....        ",
+"      ..XXXXX..XXXXX.XX...      ",
+"      ..XXXXX..XXXX.XXXX..      ",
+"       .XXXX........XXXX.       ",
+"       ..XXX.XXXXX.......       ",
+"       ..XXX.XXXXX..XXX.        ",
+"       .X.XX.XXXXX.XXXX.        ",
+"       ...XX.XXXXX.XXXX.        ",
+"        ...X.XXXXX.X...         ",
+"         .X.........XX.         ",
+"         .  .XX.XX.XX.          ",
+"ooooooooo....XX.XX....oooooooooo",
+"oooooooooo. .......  .oooooooooo",
+"oooooooooo.X.XX.X .X.ooooooooooo",
+"oooooooooo. .X .  . .ooooooooooo",
+"oooooooooo...........ooooooooooo",
+"oooooooooo...X..XX...ooooooooooo",
+"oooooooooo...X ..X...ooooooooooo",
+"oooooooooo..........oooooooooooo",
+"oooooooooooo.......ooooooooooooo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/texi/etc/gnus-summary-catchup-up.xpm b/texi/etc/gnus-summary-catchup-up.xpm
new file mode 100644 (file)
index 0000000..9de9baf
--- /dev/null
@@ -0,0 +1,37 @@
+/* XPM */
+static char * icon-catchup2_xpm[] = {
+"32 32 2 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".................  .............",
+" ... ... ... ...   . ... ... ...",
+"................  ..............",
+"............... ................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+".............  ..........  .....",
+" ... ... ...   . ... ...   . ...",
+"............  ..........  ......",
+"........... ........... ........",
+"............  .......... .......",
+" ... ... ... . . ... ... ... ...",
+"...............  .....          ",
+"................      ... ......",
+"........  ..... ... ...... .....",
+" ... ..   .. . . . .  .. .     .",
+".......  .... .... ... .. . ... ",
+"...... ...... ... .....  ... ...",
+"......    .. .... ......   .. ..",
+" ... ... .       ... ..  ..   ..",
+"........... ....      . ....   .",
+".......... ..... .....      .. .",
+".......... ..... ....... ...    "};
diff --git a/texi/etc/gnus-summary-exit-up.xpm b/texi/etc/gnus-summary-exit-up.xpm
new file mode 100644 (file)
index 0000000..d1ab26a
--- /dev/null
@@ -0,0 +1,37 @@
+/* XPM */
+static char * icon-exit-summary_xpm[] = {
+"32 32 2 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................",
+" ... ......              ... ...",
+"........  .......        .......",
+"........ ...........     .......",
+"........  ..........     .......",
+" ... ... ... .......     ... ...",
+"................ ...     .......",
+"....................     .......",
+"........  ..........     .......",
+" ... ... ... .......     ... ...",
+"........  .......  .     .......",
+"........ .......   .     .......",
+"........  .......  .     .......",
+" ... ... ... .......     ... ...",
+"........  ..........     .......",
+"........ ...........     .......",
+"................ ...     .......",
+" ... ....... .......     ... ...",
+"........  ..........     .......",
+"........  ........   . . .......",
+"........ ....   . . . . ........",
+" ... .. ..       . . . . ... ...",
+"................................",
+"................................",
+"................................",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................................",
+"................................"};
diff --git a/texi/etc/gnus-summary-followup-up.xpm b/texi/etc/gnus-summary-followup-up.xpm
new file mode 100644 (file)
index 0000000..3cee12e
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-followup_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"        .XXXX...XXXXXXX.        ",
+"         .X..XX.XXXXXXXX.       ",
+"         ..XXXX..XXXXXXX.       ",
+" .     ..XXXX..X.XXXXXXXX.   .  ",
+"     ..XXXXX...X.XXXXXXXX.      ",
+"   ..XXXXXXX..XXX.XXXXXXXX.     ",
+"  .XXXXXXXX.XXXXX.XXXXXXXX.     ",
+" ..XXXXXXXXXXXXXX.XXXXXXXXX. .  ",
+"  .XXXXXXXXXXXXXXX.XXXXXXX..    ",
+"   .XXXXXXXXXXXXXXX.XXXX..      ",
+"   .XXXXXXXXXXXXXXX.XX..        ",
+" .  .XXXXXXXXXXXXXXX..   .   .  ",
+"    .XXXXXXXXXXXXXXX.           ",
+"     .XXXXXXXXXXXXXXX.          ",
+"     .XXXXXXXXXXXXXXX.          ",
+" .    .XXXXXXXXXXXXXXX.  .   .  ",
+"      .XXXXXXXXXXXXXXX.         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/texi/etc/gnus-summary-followup-with-original-up.xpm b/texi/etc/gnus-summary-followup-with-original-up.xpm
new file mode 100644 (file)
index 0000000..baffb6b
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-followup-w-orig_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                 ..             ",
+"                ...             ",
+" .   .   .   .  ..   .   .   .  ",
+"               .                ",
+"                                ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"             ..                 ",
+"           ..XX.                ",
+"         ..XXXX.                ",
+" .     ..XXX...X.    .   .   .  ",
+"     ..XXX..XX..X.              ",
+"   ..XXX..XXX...X.              ",
+"   .XX..XXXXX...XX.             ",
+" . ...XXXXXX.XX.XX.  .   .   .  ",
+"   .XXXXXXXXXXXX.XX.            ",
+"  .XXXXXXXXXXXXX.XX.            ",
+"  .XXXXXXXXXXXXXX.XX.           ",
+" . .XXXXXXXXXXXXX.XX.    .   .  ",
+"   .XXXXXXXXXXXXXX.XX.          ",
+"    .XXXXXXXXXXXXX.XX.          ",
+"    .XXXXXXXXXXXXXX.XX.         ",
+" .   .XXXXXXXXXXXXX.XX.  .   .  ",
+"     .XXXXXXXXXXXXXX.XX.        ",
+"      .XXXXXXXXXXXXX.XX.        "};
diff --git a/texi/etc/gnus-summary-mail-copy-up.xpm b/texi/etc/gnus-summary-mail-copy-up.xpm
new file mode 100644 (file)
index 0000000..e73e6d5
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-copy_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+" ..........................     ",
+" ...XXXXXXXXXXXXXXXXXXX..X.     ",
+" .XX..XXXXXXXXXXXXXXX..XXX.     ",
+" .XXXX..XXXXXXXXXXX..XXXXX.     ",
+" .XXXXXX..XXXXXXX..XXXXXXX.     ",
+" .XXXXXXXX..XXX..XXXXXXXXX.     ",
+" .XXXXXXXX.X...XX.XXXXXXXX.     ",
+" .XXXXXX..XXXXXXXX..XXXXXX.     ",
+" .XXXXX.XXXXXXXXXXXX.XXXXX.     ",
+" .XX..........................  ",
+" .XX.X.XXXXXXXXXXXXXXXXXXX..X.  ",
+" .X..XX..XXXXXXXXXXXXXXX..XXX.  ",
+" ..X.XXXX..XXXXXXXXXXX..XXXXX.  ",
+" ....XXXXXX..XXXXXXX..XXXXXXX.  ",
+"    .XXXXXXXX..XXX..XXXXXXXXX.  ",
+"    .XXXXXXXX.X...X.XXXXXXXXX.  ",
+"    .XXXXXXX.XXXXXXX..XXXXXXX.  ",
+"    .XXXXX..XXXXXXXXXX.XXXXXX.  ",
+"    .XXXX.XXXXXXXXXXXXX.XXXXX.  ",
+"    .XXX.XXXXXXXXXXXXXXX..XXX.  ",
+"    .X..XXXXXXXXXXXXXXXXXX.XX.  ",
+"    ..XXXXXXXXXXXXXXXXXXXXX...  ",
+"    ..........................  ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-delete-up.xpm b/texi/etc/gnus-summary-mail-delete-up.xpm
new file mode 100644 (file)
index 0000000..932d8f2
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-mail-delete_xpm[] = {
+"32 32 4 1",
+"      c #BEBEBEBEBEBE s backgroundToolBarColor",
+"X     c #000000000000",
+"o     c #E7E7E7E7E7E7",
+"O     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"    XXXXX                       ",
+"   XX   XX                      ",
+"  XX     XX          XXX        ",
+"  X       X        XXooXX  X    ",
+"  XX     XXX     XXooXX   XX    ",
+"   XX   XXXXX   XXXXX    XOXXX  ",
+"    XXXXX   XXXXXX      XOOXOOXX",
+"             XOX       XOOOXOOOX",
+"    XXXXX   XXXXXX     XOOOXOOOO",
+"   XX   XXXXX   XXXXXX  XOOXOOOO",
+"  XX     XXX     XXXXXXXOOOXOOOO",
+"  X       X        XOOOOOOXOOOOO",
+"  XX     XX       XOOOOOOOXOOOOO",
+"   XX   XX       XOOOOOOOXXOOOOO",
+"    XXXXX       XOOOOOXXXOOOOOOO",
+"               XOOOXXXOOOOOOOOOO",
+"              XOXXXOOOOOOOOOOOOX",
+"             XXXOOOOOOOOOOOOOOX ",
+"              XXOOOOOOOOOOOOOX  ",
+"                XXOOOOOOOOOOOX  ",
+"                  XOOOOOOOOOX   ",
+"                   XXOOOOOOX    ",
+"                     XXOOOX     ",
+"                       XXOX     ",
+"                         X      ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-forward-up.xpm b/texi/etc/gnus-summary-mail-forward-up.xpm
new file mode 100644 (file)
index 0000000..19db803
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-forward_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"   ...                          ",
+"  .   .                         ",
+"  .   .               .         ",
+"       .             ...        ",
+"      ...          ...XX.       ",
+"     . . .        .XX.XXX.      ",
+"    .  .  .      .XX.XXXX..     ",
+"    . .   .     .XXX.XXXXX..    ",
+"    . .   .    .XXX.XXXXXXX.    ",
+"    ..    .  ..XXXX.XXXXXXXX.   ",
+"    .     . .XXXXXX.XXXXXXXXX.  ",
+"         . .XXXXXX.XXXXXXXXXX.  ",
+"          .XXXXXXX............. ",
+"         .XXXXXXX.XXXXXXXXXXX.  ",
+"        .XXXXXXX..XXXXXXXXX..   ",
+"      ..XXXXX....XXXXXXXXX.     ",
+"     .XXX.....XXXXXXXXXXX.      ",
+"     ....XXXX.XXXXXXXXXX.       ",
+"    ..XXXXXXX.XXXXXXXXX.        ",
+"    .XXXXXXX.XXXXXXXXX.         ",
+"     .XXXXXX.XXXXXXX..          ",
+"     ..XXXXX.XXXXXX.            ",
+"      ..XXXX.XXXXX.             ",
+"       .XXXX.XXXX.              ",
+"        .XXX.XXX.               ",
+"         .X.XX..                ",
+"          ..X.                  ",
+"          ...                   ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-get-up.xpm b/texi/etc/gnus-summary-mail-get-up.xpm
new file mode 100644 (file)
index 0000000..ffdb84c
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-get_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"       ...         ...          ",
+"      .   .       .   .         ",
+"     .     .     .     .        ",
+"    .       . . .       ..      ",
+"    .       .. ..       ..      ",
+"    .XXXXXXX.   .XXXXXXX.       ",
+"     .XXXXX.     .XXXXX.        ",
+"     ..XXX..     ..XXX..        ",
+"       ...         ...          ",
+"                                ",
+"    ..........................  ",
+"    ...XXXXXXXXXXXXXXXXXXX..X.  ",
+"    .XX..XXXXXXXXXXXXXXX..XXX.  ",
+"    .XXXX..XXXXXXXXXXX..XXXXX.  ",
+"    .XXXXXX..XXXXXXX..XXXXXXX.  ",
+"    .XXXXXXXX..XXX..XXXXXXXXX.  ",
+"    .XXXXXXX.XX...X.XXXXXXXXX.  ",
+"    .XXXXX..XXXXXXXX..XXXXXXX.  ",
+"    .XXXX.XXXXXXXXXXXX.XXXXXX.  ",
+"    .XXX.XXXXXXXXXXXXXX.XXXXX.  ",
+"    .X..XXXXXXXXXXXXXXXX..XXX.  ",
+"    ..XXXXXXXXXXXXXXXXXXXX.XX.  ",
+"    .XXXXXXXXXXXXXXXXXXXXXX...  ",
+"    ..........................  ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-originate-up.xpm b/texi/etc/gnus-summary-mail-originate-up.xpm
new file mode 100644 (file)
index 0000000..8ba8bc2
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-originate_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"               .............    ",
+"               .XXXXXXXXXX.X.   ",
+"               .XXXXXXXXXX.XX.  ",
+"               .XXXXXXXXXX....  ",
+"   ..................XXXXXXXX.  ",
+"   .X. X X X X X X .X..XXXXXX.  ",
+"   ..................XXXXXXXX.  ",
+"               .XXXXXXXXXXXXX.  ",
+"               .XXXXXXXXXXXXX.  ",
+"               .XX.......XXXX.  ",
+"  ..............XXXXXXXXXXXXX.  ",
+"  ...XXXXXXXXXX.XX..X..X.XXXX.  ",
+"  .XX..XXXXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXXX..XXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXXXXX..XXXX.XXXXXXXXXXXXX.  ",
+"  .XXXXXXXX..XX.XXXXXXXXXXXXX.  ",
+"  .XXXXXXX.XX...XXXXXXXXXXXXX.  ",
+"  .XXXXX..XXXXX.XXXXXXX..X.XX.  ",
+"  .XXXX.XXXXXXX.XXXXXXXXXXXXX.  ",
+"  .XXX.XXXXXXXX.XXXXXXXXXXXXX.  ",
+"  .X..XXXXXXXXX.XXXXXXXXXXXXX.  ",
+"  ..XXXXXXXXXXX...............  ",
+"  .XXXXXXXXXXXXXXXXXXXXXX...    ",
+"  ..........................    ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-reply-up.xpm b/texi/etc/gnus-summary-mail-reply-up.xpm
new file mode 100644 (file)
index 0000000..20fe672
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-mail-reply_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+"                    ...         ",
+"                   .XXX..       ",
+"                  .XXXXXX..     ",
+"              ... .XXXXXXXX.    ",
+"            ..XXX.XX.XXXXXX.    ",
+"          ..XXXX.XXX.XXXXX.     ",
+"        ..XXXXXX.XX.XXXXX.      ",
+"      ..XXXXXXX.XX.XXXXXX.      ",
+"     .XXXXXXXX.XXX.XXXXX...     ",
+"   ..XX..XX.XX.XXXXXXXX.XXX..   ",
+"   ...XXXXXXX.XX.XXXXX.XX..X.   ",
+"   .XX..XXXX.XXX.XXXXX...XXX.   ",
+"   .XXXX..XX.XX.XXXXX..XXXXX.   ",
+"   .XXXXXX...XXXXXX..XXXXXXX.   ",
+"   .XXXXXXXX..XXX..XXXXXXXXX.   ",
+"   .XXXXXXX.XX...X.XXXXXXXXX.   ",
+"   .XXXXX..XXXXXXXX..XXXXXXX.   ",
+"   .XXXX.XXXXXXXXXXXX.XXXXXX.   ",
+"   .XXX.XXXXXXXXXXXXXX.XXXXX.   ",
+"   .X..XXXXXXXXXXXXXXXX..XXX.   ",
+"   ..XXXXXXXXXXXXXXXXXXXX.XX.   ",
+"   .XXXXXXXXXXXXXXXXXXXXXX...   ",
+"   ..........................   ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-mail-save-up.xpm b/texi/etc/gnus-summary-mail-save-up.xpm
new file mode 100644 (file)
index 0000000..fd4824b
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-mail_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"       ........................ ",
+"       ...XXXXXXXXXXXXXXXXXX... ",
+"       .XX..XXXXXXXXXXXXXX..XX. ",
+"       .XXXX..XXXXXXXXXX..XXXX. ",
+"       .XXXXXX..XXXXXX..XXXXXX. ",
+"       .XXXXXXX...XX..XXXXXXXX. ",
+"       .XXXXX..XXX..XX..XXXXXX. ",
+"       .XXXX.XXXXXXXXXXX.XXXXX. ",
+"       .XXX.XXXXXXXXXXXXX..XXX. ",
+"       .X..XXXXXXXXXXXXXXXX..X. ",
+"  ..................XXXXXXXXX.. ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXXXX. ",
+"  .oo.OOOOOOOOOO.oo............ ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo............oo.            ",
+"  .oooooooooooooooo.            ",
+"  .oooooooooooooooo.            ",
+"  .oo............oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/texi/etc/gnus-summary-next-unread-up.xpm b/texi/etc/gnus-summary-next-unread-up.xpm
new file mode 100644 (file)
index 0000000..e525816
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-next-unread_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"        .XXXX...XXXXXXX.        ",
+"         .X..XX.XXXXXXXX.       ",
+"         ..XXXX..XXXXXXX.       ",
+" .     ..XXXX..X.XXXXXXXX.   .  ",
+"     ..XXXXX...X.XXXXXXXX.      ",
+"   ..XXXXXXX..XXX.XXXXXXXX.     ",
+"  .XXXXXXXX.XXXXX.XXXXXXXX.     ",
+" ..XXXXXXXXXXXXXX.XXXXXXXXX. .  ",
+"  .XXXXXXXXXXXXXXX.XXXXXXX..    ",
+"   .XX.....XXXXXXX.....X..      ",
+"   .X.ooooo.XXXXX.oooo..        ",
+" .  .oXooooo.XXX.oXooooo..   .  ",
+"    .ooooooo.X.X.ooooooo.       ",
+"    .ooooooo..X..ooooooo.       ",
+"    ..oooooo.XXX.ooooooo.       ",
+" .   ..oooo.XXXXX.oooo.. .   .  ",
+"      .....XXXXXXX.....         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/texi/etc/gnus-summary-post-news-up.xpm b/texi/etc/gnus-summary-post-news-up.xpm
new file mode 100644 (file)
index 0000000..46be7c1
--- /dev/null
@@ -0,0 +1,38 @@
+/* XPM */
+static char * icon-post_xpm[] = {
+"32 32 3 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXXX. .   .  ",
+"       .XXXXXXXXXXXXXXX.        ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+" .   .   .XXXXXXXXXXXXXXX.   .  ",
+"         .XXXXXXXXXXXXXXX.      ",
+"          .XXXXXXXXXXXXXXX.     ",
+"          .XXXXXXXXXXXXXXX.     ",
+" .   .   . .XXXXXXXXXXXXXXX. .  ",
+"           .XXXXXXXXXXXXXX..    ",
+"            .XXXXXXXXXX...      ",
+"            .XXXXXXXXX.         ",
+" .   .   .   .XXXXXX..   .   .  ",
+"             .XXX...            ",
+"              ....              ",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-summary-prev-unread-up.xpm b/texi/etc/gnus-summary-prev-unread-up.xpm
new file mode 100644 (file)
index 0000000..b2088fb
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-prev-unread_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+" .   .   .   .   .   .   .   .  ",
+"                                ",
+"                                ",
+"                 ...            ",
+" .   .   .   . ..XX. .   .   .  ",
+"             ..XXXX..           ",
+"           ..XXXX..X.           ",
+"         ..XXXXX...X.           ",
+" .   . ..XXXXXXX..XXX.   .   .  ",
+"     ..XXXXXXXX.XXXXX.          ",
+"      .XXXXXXXXXXXXXXX.         ",
+"      .XXXXXXXXXXXXXXX.         ",
+" .   . .XXXXXXXXXXXXXX.  .   .  ",
+"        .XXXX...XXXXXX.....     ",
+"       ...o..XX.XXXXX.oooo..    ",
+"      .oo..XXXX..XXX.oXooooo.   ",
+" .   .o..XXXX..X.X.X.ooooooo..  ",
+"     ..XXXXX...X..X..ooooooo.   ",
+"   ..XXXXXXX..XX.XXX.ooooooo.   ",
+"  .XXXXXXXX.XXXXX.XXX.oooo..    ",
+" ..XXXXXXXXXXXXXX.XXXX.....  .  ",
+"  .XXXXXXXXXXXXXXX.XXXX.        ",
+"   .XXXXXXXXXXXXXX.XX..         ",
+"   .XXXXXXXXXXXXXXX..           ",
+" .  .XXXXXXXXXXXXXXX.    .   .  ",
+"    .XXXXXXXXXXXXXXX.           ",
+"     .XXXXXXXXXXXXXXX.          ",
+"     .XXXXXXXXXXXXXXX.          ",
+" .   .XXXXXXXXXXXXXXXX.  .   .  ",
+"      .XXXXXXXXXXXXXXX.         ",
+"       .XXXXXXXXXXXXXXX.        "};
diff --git a/texi/etc/gnus-summary-reply-up.xpm b/texi/etc/gnus-summary-reply-up.xpm
new file mode 100644 (file)
index 0000000..255f7a1
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-follow-up_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                   .            ",
+"                  .X..          ",
+"             ... .XXXX.         ",
+"           ..XXX.XXXXXX..       ",
+"         ..XXXX.XXXXXXXXX.      ",
+"       ..XXXXX.XXXXXXXXX..      ",
+"     ..XXXXXXX.XXXXXXXX....     ",
+"   ..XXXXXXXX.XXXXXXXXX.oXX..   ",
+"  .X..X.X.X..XXXXXXXXX..o...o.  ",
+"  ..XXXXXXX.XXXXXXXXX..ooXXX..  ",
+"  .X...XXXX.XXXXXXXX..ooX...X.  ",
+"  .XXXX.XX.XXXXXXXX..oX..XXXX.  ",
+"  .XXXXX..XXXXXXXX..oX.XXXXXX.  ",
+"  .XXXXXXX..XXXXX..X..XXXXXXX.  ",
+"oo.XXXXXXXXX.XXX....XXXXXXXXX.oo",
+"oo.XXXXXXXXX...X...XXXXXXXXXX.oo",
+"oo.XXXXXXXX.XX...XX.XXXXXXXXX.oo",
+"oo.XXXXXXX.XXXXXXXXX.XXXXXXXX.oo",
+"oo.XXXXXX.XXXXXXXXXXX.XXXXXXX.oo",
+"oo.XXXX..XXXXXXXXXXXXX..XXXXX.oo",
+"oo.XXX.XXXXXXXXXXXXXXXXX.XXXX.oo",
+"oo.XX.XXXXXXXXXXXXXXXXXXX.XXX.oo",
+"oo...XXXXXXXXXXXXXXXXXXXXX....oo",
+"oo..XXXXXXXXXXXXXXXXXXXXXXXX..oo",
+"oo............................oo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/texi/etc/gnus-summary-reply-with-original-up.xpm b/texi/etc/gnus-summary-reply-with-original-up.xpm
new file mode 100644 (file)
index 0000000..1135bfa
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-follow-up-incl_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                ...             ",
+"               .X.X.            ",
+"              .XX.XX..          ",
+"             .XXX.XXXX.         ",
+"           ..XXX.XXXXXX..       ",
+"         ..X.XXX.XXXXXXX..      ",
+"       ..XX.XXXX.XXXXX....      ",
+"     ..XXX.XXXXX.X....XX...     ",
+"   ..XXX..XXXX....XXXXX.oXX..   ",
+"  .XXXX.XXXXXX.XXXXXXX..oXXXo.  ",
+"  ..XX.XXX.....XXXXXX..ooXXX..  ",
+"  .X......XXX.XXXXXX..ooX...X.  ",
+"  .XXXX.XXXXX.XXXXX..oX..XXXX.  ",
+"  .XXXXX..XX.XXXXX..oX.XXXXXX.  ",
+"  .XXXXXXX...XXXX..X..XXXXXXX.  ",
+"oo.XXXXXXXXX..XX....XXXXXXXXX.oo",
+"oo.XXXXXXXXX...X...XXXXXXXXXX.oo",
+"oo.XXXXXXXX.XX...XX.XXXXXXXXX.oo",
+"oo.XXXXXXX.XXXXXXXXX.XXXXXXXX.oo",
+"oo.XXXXXX.XXXXXXXXXXX.XXXXXXX.oo",
+"oo.XXXX..XXXXXXXXXXXXX..XXXXX.oo",
+"oo.XXX.XXXXXXXXXXXXXXXXX.XXXX.oo",
+"oo.XX.XXXXXXXXXXXXXXXXXXX.XXX.oo",
+"oo...XXXXXXXXXXXXXXXXXXXXX....oo",
+"oo..XXXXXXXXXXXXXXXXXXXXXXXX..oo",
+"oo............................oo",
+"oooooooooooooooooooooooooooooooo",
+"oooooooooooooooooooooooooooooooo"};
diff --git a/texi/etc/gnus-summary-save-article-file-up.xpm b/texi/etc/gnus-summary-save-article-file-up.xpm
new file mode 100644 (file)
index 0000000..ea30122
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-text_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"          ................      ",
+"          .XXXXXXXXXXXXX.X.     ",
+"          .XXXXXXXXXXXXX.XX.    ",
+"          .XXXXXXXXXXXXX.XXX.   ",
+"          .XXXXXXXXXXXXX.....   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"          .XXXXXXXXXXXXXXXXX.   ",
+"  ..................XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXX.   ",
+"  .oo............oo.XXXXXXXX.   ",
+"  .oooooooooooooooo.XXXXXXXX.   ",
+"  .oooooooooooooooo.XXXXXXXX.   ",
+"  .oo............oo..........   ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/texi/etc/gnus-summary-save-article-up.xpm b/texi/etc/gnus-summary-save-article-up.xpm
new file mode 100644 (file)
index 0000000..fd4824b
--- /dev/null
@@ -0,0 +1,41 @@
+/* XPM */
+static char * icon-save-mail_xpm[] = {
+"32 32 6 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #FFFFFFFFFFFF",
+"o     c #999999999999",
+"O     c #E5E5E5E5E5E5",
+"+     c #666666666666",
+"                                ",
+"                                ",
+"                                ",
+"       ........................ ",
+"       ...XXXXXXXXXXXXXXXXXX... ",
+"       .XX..XXXXXXXXXXXXXX..XX. ",
+"       .XXXX..XXXXXXXXXX..XXXX. ",
+"       .XXXXXX..XXXXXX..XXXXXX. ",
+"       .XXXXXXX...XX..XXXXXXXX. ",
+"       .XXXXX..XXX..XX..XXXXXX. ",
+"       .XXXX.XXXXXXXXXXX.XXXXX. ",
+"       .XXX.XXXXXXXXXXXXX..XXX. ",
+"       .X..XXXXXXXXXXXXXXXX..X. ",
+"  ..................XXXXXXXXX.. ",
+"  .oo.OOOOOOOOOO.oo.XXXXXXXXXX. ",
+"  .oo.OOOOOOOOOO.oo............ ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo.OOOOOOOOOO.oo.            ",
+"  .oo............oo.            ",
+"  .oooooooooooooooo.            ",
+"  .oooooooooooooooo.            ",
+"  .oo............oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"  .oo.+++++++.OO.oo.            ",
+"   .o.+++++++.OO.oo.            ",
+"    ................            ",
+"                                "};
diff --git a/texi/etc/gnus-uu-decode-uu-up.xpm b/texi/etc/gnus-uu-decode-uu-up.xpm
new file mode 100644 (file)
index 0000000..568315c
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-decode-view_xpm[] = {
+"32 32 4 1",
+"      c #BFBFBFBFBFBF s backgroundToolBarColor",
+".     c #000000000000",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"       ...................      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XX.............XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.oooo.oooooo.XX.      ",
+"       .XX.oo..o..o.oo.XX.      ",
+"       .XX.o.oo.oo.ooo.XX.      ",
+"       .XX.ooo.ooooooo.XX.      ",
+"       .XX.oo.oo.ooooo.XX.      ",
+"       .XX.oo....ooooo.XX.      ",
+"       .XX.oooooo.oooo.XX.      ",
+"       .XX.ooooooo.ooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.ooooooooooo.XX.      ",
+"       .XX.............XX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       .XXXXXXXXXXXXXXXXX.      ",
+"       ...................      ",
+"                                ",
+"                                ",
+"                                "};
diff --git a/texi/etc/gnus-uu-post-news-up.xpm b/texi/etc/gnus-uu-post-news-up.xpm
new file mode 100644 (file)
index 0000000..f4a7e3a
--- /dev/null
@@ -0,0 +1,39 @@
+/* XPM */
+static char * icon-post-pic_xpm[] = {
+"32 32 4 1",
+"      c #000000000000",
+".     c #BFBFBFBFBFBF s backgroundToolBarColor",
+"X     c #999999999999",
+"o     c #FFFFFFFFFFFF",
+" ... ... ... ... ... ... ... ...",
+"................................",
+"................ ...............",
+"..............  .  .............",
+" ... ... ...  .. ..  ... ... ...",
+"..........  .........  .........",
+"........  .............  .......",
+".......                   ......",
+" ... .. XXXXXXXXXXXXXXXXX .. ...",
+"....... XXXXXXXXXXXXXXXXX ......",
+"....... XX             XX ......",
+"....... XX ooooooooooo XX ......",
+" ... .. XX ooooooooooo XX .. ...",
+"....... XX ooooooooooo XX ......",
+"....... XX oooo oooooo XX ......",
+"....... XX oo  o  o oo XX ......",
+" ... .. XX o oo oo ooo XX .. ...",
+"....... XX ooo ooooooo XX ......",
+"....... XX oo oo ooooo XX ......",
+"....... XX oo    ooooo XX ......",
+" ... .. XX oooooo oooo XX .. ...",
+"....... XX ooooooo ooo XX ......",
+"....... XX ooooooooooo XX ......",
+"....... XX ooooooooooo XX ......",
+" ... .. XX ooooooooooo XX .. ...",
+"....... XX ooooooooooo XX ......",
+"....... XX             XX ......",
+"....... XXXXXXXXXXXXXXXXX ......",
+" ... .. XXXXXXXXXXXXXXXXX .. ...",
+".......                   ......",
+"................................",
+"................................"};
diff --git a/texi/etc/gnus.xpm b/texi/etc/gnus.xpm
new file mode 100644 (file)
index 0000000..b51c903
--- /dev/null
@@ -0,0 +1,283 @@
+/* XPM */
+static char *gnus[] = {
+/* width height num_colors chars_per_pixel */
+"   271   273        3            1",
+/* colors */
+". s thing c #bf9900",
+"# s shadow c #ffcc00",
+"a c None",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............#######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........................#######aaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................######aaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................######aaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............................#######aaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................aaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................aaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................#######aaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................aaaaaaaaaaaaaaaa....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................########aaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......................aaaaaaaaaaaaaa........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.................................#######aaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................aaaaaaaaaaa............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................########aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................aaaaaaaaa..............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................aaaaaaa................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............................aaaaa..................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......######.......................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................aaaa...................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#######aa....................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................aa.....................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaa.................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................a......................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaa................#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaa...............#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaa...............#######aaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaa..............#######aaaaa",
+"aaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaa..............#######aaaaa",
+"aaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa.............#######aaaaa",
+"aaaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............####....................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaa............########aaaaa",
+"aaaaaaa.........aaaaaaaaaaaaaaaaaaaaaaaaaaa.............########...................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaa...........aaaaaaaaaaaaaaaaaaaaaaa.............############..................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaaa..........aaaaaaaaaaaaaaaaaaaaaa.............##############..................................................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaa...........########aaaaa",
+"aaaaaaaa...........aaaaaaaaaaaaaaaaaaaa............##################.......................##########................................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaa..........########aaaaa",
+"aaaaaaaa............aaaaaaaaaaaaaaaaaa............####################....................###############..............................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaa............aaaaaaaaaaaaaaaa..............#####################.................#####################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa..aaaaa###aaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaa.............aaaaaaaaaaaaaa..............#######################...............#######################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa..aaaaa##aaaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaaa.............aaaaaaaaaaa...............##########aa#############.............#########################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaa..........#######aaaaaa",
+"aaaaaaaaa.............aaaaaaaaa................#########aaaaaaa###########............##########################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa................aaaa..................#######aaaaaaaaaa###########..........############################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa.....................................######aaaaaaaaaaaaa###########.........#############################..........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaa....................................######aaaaaaaaaaaaaaaa#########........###############################.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........########aaaaaa",
+"aaaaaaaaaa.................................#######aaaaaaaaaaaaaaaaaa#########.......#######aaaaaaaaaaa##############..........................aaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaaa................................#######aaaaaaaaaaaaaaaaaaaa########......#####aaaaaaaaaaaaaaaaa############..........................aaaaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaaa...............................########aaaaaaaaaaaaaaaaaaaaa########....#####aaaaaaaaaaaaaaaaaaaaa##########..........................aaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaa#..............................########aaaaaaaaaaaaaaaaaaaaaaaa#.####...#####aaaaaaaaaaaaaaaaaaaaaaa##########...........................aaaaaaaaaaaaaaaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#######aaaaaaa",
+"aaaaaaaaa#.............................########aaaaaaaaaaaaaaaaaaaaaaaaa...###..######aaaaaaaaaaaaaaaaaaaaaaaa##########...........................aaaaaaaaaaaaaaaaaaa......a#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###...........................#########aaaaaaaaaaaaaaaaaaaaaaaa....##########aaaaaaaaaaaaaaaaaaaaaaaaaa##########............................aaaaaaaaaaaaaaa........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###..........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....#########aaaaaaaaaaaaaaaaaaaaaaaaaaaa##########...............................aaaaaaaa...........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........########aaaaaaa",
+"aaaaaaaa###.........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....a#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaa##########................................................##aaaaaa...aaaaaaaaaaaaaaaaaaaaa......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaaa####........................#########aaaaaaaaaaaaaaaaaaaaaaaaa....aaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...............................................##aaaaaa....aaaaaaaaaaaaaaaaaaa.......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaaa####.......................########aaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########..............................................##aaaaa.....aaaaaaaaaaaaaaaaaa.......a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa######....................#########aaaaaaaaaaaaaaaaaaaaaaaaaa.....a#aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########............................................##aaaaaa......aaaaaaaaaaaaaaa.........a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa######...................#########aaaaaaaaaaaaaaaaaaaaaaaaaa......##aaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...........................................##aaaaa.......aaaaaaaaaaaaa..........aa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaa",
+"aaaaaa#######.................#########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a###aaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.........................................###aaaaa.........aaaaaaa..............a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........########aaaaaaaa",
+"aaaaaaa#######...............#########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########........................................##aaaaa...............................a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaa########............##########aaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.......................................##aaaaa...............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaaa##########.......###########aaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.....................................###aaaaa..............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#######aaaaaaaaa",
+"aaaaaaaaa##########################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########....................................##aaaaa...............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........########aaaaaaaaa",
+"aaaaaaaaa#########################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########..................................###aaaaa..............................#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaa#######################aaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...............................####aaaaa..............................######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaaa#####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.............................#####aaaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaa",
+"aaaaaaaaaaa###################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########...........................######aaaa..............................######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......########aaaaaaaaaa",
+"aaaaaaaaaaaa#################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########.........................######aaaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaaa",
+"aaaaaaaaaaaaa###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaa#########.......................#######aaaa.............................#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aaaaaaaaaaaaaaaa#########....................#########aaaa............................########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaaaaaaaaaaaaa#########..................#########aaaaa..........................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........aaaaaaaaaaaaaaa###########.............###########aaaaa.........................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............aaaaaaaaaaaaaaa##############....###############aaaaaaa.......................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............aaaaaaaaaaaaaaa##############################aaaaaaaaa.....................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaaaaaaaaaaaa############################aaaaaaaaaaa...................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa................aaaaaaaaaaaaaaaa##########################aaaaaaaaaaaa#................#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaa.................aaaaaaaaaaaaaaaa########################aaaaaaaaaaaaa##..............#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaa...................aaaaaaaaaaaaaaaa######################aaaaaaaaaaaaa#####.........###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaa....................aaaaaaaaaaaaaaaaa###################aaaaaaaaaaaaaaa########..##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaaaaa....................aaaaaaaaaaaaaaaaaaa################aaaaaaaaaaaaaaaa###########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaa......................aaaaaaaaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaa##########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa.......aaaaaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa........a###a.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaaaa........a####a.........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#####aaaaaaaaaaaaaaaaaaaaaaaaaaa........a#####aaa.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....a####aaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaa#.....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaa##....................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaa..........######aaaaa#####..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a####aaaaaaaaaaaaaaaaaaaaaaaaa...........#####aaaaa#######..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaaa...........#####aaaaaa#######..................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaaa...........######aaaaa#########.................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaaa...........######aaaaa###########................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaa##########...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......####aaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaaaa#########...............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....####aaaaaaaaaaaaaaaaaaaaaa............#######aaaaaaaaaaaa########..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......###aaaaaaaaaaaaaaaaaaaaa............#########aaaaaaaaaaaaa#######..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......###aaaaaaaaaaaaaaaaaaa.............#########aaaaaaaaaaaaaaa#######.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaaaa.............#########aaaaaaaaaaaaaaaaa######.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaa..............#########aaaaaaaaaaaaaaaaaaa#####.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaa...............#########aaaaaaaaaaaaaaaaaaaa#####.............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........aaaaaaaaaaaaa...............#########aaaaaaaaaaaaaaaaaaaaaa#####............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...............aaaaa..................########aaaaaaaaaaaaaaaaaaaaaaaaa####............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................................########aaaaaaaaaaaaaaaaaaaaaaaaaa####...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....................................########aaaaaaaaaaaaaaaaaaaaaaaaaaaa###...........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaa####..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa................................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa............................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...........................#########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........................##########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......................###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#...................############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#........#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##................#############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.......##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###............##############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#......###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####.........###############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#......###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######..###################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa########################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#.....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#....####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##################aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#....###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##############aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#...####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###########aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##..####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....a#aaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaa#######aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#aaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaa#######aa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#aaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaaa########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#aaaaaaaaaaaaaaaaaaaaa#####aaaaaaaaa########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#aaaaaaaaaaaaaaaaaaaa#######aaaaaaa#########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......##aaaaaaaaaaaaaaaaaaa########a..aa##########a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........##aaaaaaaaaaaaaaaaaa#########....##########a........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#aaaaaaaaaaaaaaaaaa#########......#########........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#aaaaaaaaaaaaaaaaaa#########......########a........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........##aaaaaaaaaaaaaaaaa#########.......#######.........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........##aaaaaaaaaaaaaaaaa########.........#####.........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........###aaaaaaaaaaaaaaaa########........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........###aaaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........###aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........####aaaaaaaaaaaaaaa#########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa#########......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......a######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa#######........................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa########.......................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......a#######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaa#######.........a..............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaa#######a........aaa............aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....aa######aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa#######........aaaaa..........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaa#######a.......aaaaaaa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....aaa#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa######a........aaaaaaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaa#######........aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaa#######a......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaa#######.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaa#######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaa######aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaa######a.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaa#####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaa####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaa#####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaa####aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaa####aa.......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaa###aaa......aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaa####aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaa####aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaa###aaa.....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaa###aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaa####aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaa###aaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaa###aaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaa....aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa........#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa......#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa....#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...#####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a####aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa###aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa##aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+};
diff --git a/texi/gnus-faq-ja.texi b/texi/gnus-faq-ja.texi
new file mode 100644 (file)
index 0000000..fe833d1
--- /dev/null
@@ -0,0 +1,440 @@
+@c Insert  "\input texinfo" at 1st line before texing this file alone.
+@c -*-texinfo-*-
+@c Copyright (C) 1998 Keiichi Suzuki
+@setfilename gnus-faq-ja.info
+
+@node Frequently Asked Questions
+@section \e$BIQHK$K?R$M$i$l$k<ALd\e(B
+
+\e$B$3$l$O\e(B T-gnus \e$B$KBP$9$kNI$/$"$k<ALd$H!"$=$l$KBP$9$k2sEz=8$G$9!#$b$7$"$J$?\e(B
+\e$B$,%&%'%V%V%i%&%6!<$r;}$C$F$$$k$J$i!"%O%$%Q!<%F%-%9%HHG$,\e(B
+@file{http://www.mdcnet.co.jp/%7Ekeiichi/semi-gnus-faq-ja.shtml} \e$B$G<j$K\e(B
+\e$BF~$j!"$*$=$i$/$"$J$?$,$3$l$r<u$1<h$C$F$+$i99?7$5$l$F$$$k$G$7$g$&!#\e(B
+
+@menu
+* Introduction::          Gnus \e$B$N>R2p!#\e(B
+* Installation FAQ::      Gnus \e$B$NF3F~!#\e(B
+* Customization FAQ::     Gnus \e$B$N%+%9%?%^%$%:!#\e(B
+* Reading News FAQ::      \e$B%K%e!<%9$rFI$`;v$K4X$9$k<ALd!#\e(B
+* Reading Mail FAQ::      \e$B%a!<%k$rFI$`;v$K4X$9$k<ALd!#\e(B
+* Mailing list FAQ::      \e$B%a!<%j%s%0%j%9%H$K4X$9$k<ALd!#\e(B
+@end menu
+
+
+@node Introduction
+@subsection \e$B>R2p\e(B
+\e$B$3$NJ8=q$O\e(B T-gnus \e$B$KBP$9$k$h$/$"$k<ALd$H!"$=$l$KBP$9$k2sEz=8$G$9!#\e(B
+
+T-gnus \e$B$O\e(B Emacs \e$B>e$GF0:n$9$k%M%C%H%K%e!<%9!&%j!<%@!<\e(B / \e$BEE;R%a!<%k!&%f!<\e(B
+\e$B%6!<!&%(%$%8%'%s%H\e(B (MUA) \e$B$G$9!#\e(BT-gnus \e$B$N%*%j%8%J%k$H$J$C$F$$$k\e(B Gnus \e$B$O!"\e(B
+\e$B8=:_\e(B6\e$B<~G/$r7^$(!"$=$N4V\e(B Emacs \e$B$NI8=`%Q%C%1!<%8$H$7$F$bG[I[$5$l$F$-$^$7$?!#\e(B
+Pterodactyl Gnus \e$B$O:G?7$N\e(B(\e$B$=$7$F:G9b$N\e(B)\e$B$b$N$G$9!#\e(B Gnus \e$B$N%*%j%8%J%k!&%P!<\e(B
+\e$B%8%g%s$O\e(B Masanobu UMEDA \e$B$K$h$k\e(BGNUS \e$B$G$9!#\e(B 1994\e$BG/$N=)$,G&$S4s$k:"!"\e(B Lars
+Magne Ingebrigtsen \e$B$O\e(B Gnus \e$B$r=q$-D>$=$&$H7h0U$7$^$7$?!#\e(B
+
+\e$B$7$+$7!"\e(B Gnus \e$BC1FH$G$O\e(B MIME \e$B2=$5$l$?5-;v!&%a!<%k$rFI$`$3$H$O$G$-$^$;$s!#\e(B
+\e$B$=$3$G!"\e(B Emacs \e$B>e$G\e(B MIME \e$B%5%]!<%H$r$9$k$?$a$N%Q%C%1!<%8$G$"$k\e(B SEMI \e$B$r;H\e(B
+\e$BMQ$7$F0lIt$N?M$?$A$,\e(B Gnus \e$B$r;HMQ$9$k$h$&$K$J$j$^$7$?!#$7$+$7!"$3$l$K$O\e(B
+Gnus \e$B$K\e(B patch \e$B$r$"$F$kI,MW$,$"$k>e$K%*%j%8%J%k$N\e(B Gnus (\e$B$3$A$i$b\e(B
+Quassia-Gnus \e$B$H8F$P$l3+H/ESCf$G$7$?\e(B)\e$B$NJQ99FbMF$K$h$C$F$O$=$N\e(B patch \e$B<+BN\e(B
+\e$B$b:n$jD>$5$J$1$l$P$J$j$^$;$s$G$7$?!#$=$s$J\e(B 1997\e$BG/$N\e(B11\e$B7n!"<i2,CNI'\e(B
+<morioka@@jaist.ac.jp> \e$B$O<~0O\e(B(\e$B9%$-<T$?$A\e(B)\e$B$N4|BT$K2!$5$l\e(B SEMI \e$B$KBP1~$7$?!"\e(B
+\e$BB?9q8l$N$?$a$N\e(B Gnus\e$B!"\e(B Semi-gnus \e$B$r8x3+$7$?$N$G$9!#\e(B
+
+T-gnus \e$B$N%=!<%9!&%3!<%I$O8=:_\e(B CVS \e$B$G4IM}$5$l$F$*$j!"M-;V$NJ}!9$K$h$C$FF|!9\e(B
+\e$B2~A1$,$J$5$l$F$$$^$9!#\e(B
+
+T-gnus \e$B$N:GBg$N6/$_$O%*%j%8%J%k$N\e(B Gnus \e$B$+$i0z$-7Q$,$l$?!"6/NO$J%+%9%?%^\e(B
+\e$B%$%:5!G=$H\e(B SEMI \e$B$,$b$?$i$96/NO$J\e(BMIME \e$B%5%]!<%H$K$"$j$^$9!#:G=i$N0lJM$G$O\e(B
+\e$B$3$N%+%9%?%^%$%:5!G=$NK-IY$5$KB?>/62I]$r46$8$k$+$bCN$l$^$;$s!"$7$+$7!"$"\e(B
+\e$B$J$?$,$=$N5!G=$rI,MW$K$J$k$^$G$OJ#;($J5!G=$N$[$H$s$I$rL5;k$9$k$3$H$,$G$-\e(B
+\e$B$^$9!#\e(B \e$B$b$7!"$"$J$?$,$^$"$^$"$NNL$N%a%$%k$r<u$1<h$k\e(B(\e$B$$$/$D$b$N%a!<%j%s%0\e(B
+\e$B%j%9%H$K;22C$7$F$$$k\e(B)\e$B!"$^$?$O!"Hs>o$KN.NL$NB?$$%a!<%j%s%0%j%9%H$K;22C$7\e(B
+\e$B$F$$$k$N$G$"$l$P!"$"$J$?$O\e(B T-gnus \e$B$G%a%$%k$rFI$`$?$a$ND4::$r$O$8$a$?$/$J\e(B
+\e$B$k$G$7$g$&!#\e(B
+
+\e$B$3$N\e(B FAQ \e$B$O!"NkLZ7=0l$K$h$C$FJ]<i$5$l$F$$$^$9!#\e(B \e$B$3$N\e(B FAQ \e$B$N4pAC$H$J$C$F\e(B
+\e$B$$$k%*%j%8%J%k\e(B Gnus \e$B$N\e(B FAQ \e$B$rJ]<i$5$l$F$$$k\e(B Justin Sheehy \e$B;a$K46<U$rJ{$2!"\e(B
+\e$B$^$?\e(B Justin Sheehy \e$B;a0JA0$K\e(B Gnus FAQ \e$B$G$9$P$i$7$$:n6H$r$5$l$F$$$?!"\e(BSteve
+Baur \e$B;a!"\e(B Per Abrahamsen \e$B;a$K46<U$7$^$9!#\e(B
+
+\e$BB>$NJ}K!\e(B(\e$B%a%$%k!"%M%C%H%K%e!<%9Ey\e(B)\e$B$G>pJs$rF@$h$&$H$9$kA0$K!"$^$:$3$N\e(B FAQ
+\e$B$r8+$F$_$F$/$@$5$$!#\e(B
+
+\e$B$3$N>pJs$O\e(B Semi-gnus (Ja) \e$B%a%$%j%s%0!&%j%9%H$N1g=u$r<u$1$FJT=8$7$?$b$N$G!"\e(B
+\e$BJ8@U$O;d!"NkLZ7=0l$K$"$j$^$9!#\e(B
+
+@node Installation FAQ
+@subsection \e$BF3F~\e(B
+
+@itemize @bullet
+@item
+Q1.1: \e$B:G?7$N%P!<%8%g%s$O\e(B?
+
+\e$B8=:_$N3+H/HG$N:G?7%P!<%8%g%s$O\e(B T-gnus 6.16 (tag: t-gnus-6_16-quimby) \e$B$G\e(B
+\e$B$9!#\e(B
+
+T-gnus 6.16 \e$B$r;HMQ$9$k$?$a$K$OJL%Q%C%1!<%8$N\e(B FLIM 1.4 \e$B$H\e(B SEMI 1.14 \e$B$,I,\e(B
+\e$BMW$G$9!#\e(B \e$B$=$NB>!"\e(B APEL \e$B$,I,MW$K$J$j$^$9$,!"I,MW$J%P!<%8%g%s\e(B
+\e$B$O\e(B FLIM / SEMI \e$B%Q%C%1!<%8Fb$N\e(B README \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+T-gnus \e$B$N%P!<%8%g%s$O!"I,MW$J\e(B SEMI \e$B$*$h$S\e(B FLIM \e$B$N%P!<%8%g%s$K?<$/4X78$7\e(B
+\e$B$F$$$^$9!#\e(B \e$BI,$:\e(B T-gnus \e$B$N%P!<%8%g%s$K$"$C$?\e(B SEMI \e$B$*$h$S\e(B FLIM \e$B$r;HMQ$7$F\e(B
+\e$B$/$@$5$$!#\e(B
+
+@item
+Q1.2: \e$BF~<jJ}K!$O\e(B?
+
+CVS \e$B$K$h$kG[I[$r<g$H$7!"\e(Banonymous ftp \e$B$K$h$kG[I[$O$=$l$rJL$N7A$GG[I[$7$F\e(B
+\e$B$$$k$@$1$N$b$N$H$$$&0LCV$E$1$K$J$C$F$$$^$9!#\e(B
+
+CVS \e$B$G$N<hF@\e(B
+
+\e$B=i$a$F\e(B CVS \e$B$G<hF@$9$k$H$-$O0J2<$N$h$&$K$7$^$9!#\e(B
+
+@itemize @bullet
+@item login
+\e$B<!$NJ}K!$G%m%0%$%s$7$^$9!#\e(B% \e$B$O%W%m%s%W%H$G$9!#\e(B
+
+% cvs -d :pserver:anonymous@@cvs.m17n.org:/cvs/root login
+
+  CVS password: [CR] # NULL string
+
+@item checkout
+T-gnus \e$B$r%A%'%C%/%"%&%H$7$^$9!#<B:]$K$O!"\e(B-r t-gnus-6_14 \e$B$N$h$&$K%?%0$rIU\e(B
+\e$B$1$F<B9T$7$^$9!#\e(B
+
+% cvs -d :pserver:anonymous@@cvs.m17n.org:/cvs/root \
+   checkout [-r TAG] gnus
+
+@end itemize
+
+2\e$B2sL\$+$i$O!"\e(B
+
+% cvs -d :pserver:anonymous@@cvs.m17n.org:/cvs/root \
+   update [-r TAG] gnus
+
+\e$B$K$h$j<hF@$7$^$9!#\e(B
+
+anonymous ftp \e$B$G$N<hF@\e(B
+
+anonymous ftp \e$B$G$O0J2<$N>l=j$+$i<hF@$G$-$^$9!#\e(B
+
+@file{ftp://ftp.jpl.org/pub/elisp/t-gnus-6.16/}
+
+SEMI, FLIM, APEL \e$B$N<hF@\e(B
+
+SEMI, FLIM, APEL \e$B$O!"\e(Banonymous ftp \e$B$G0J2<$N>l=j$+$i<hF@$7$^$9!#\e(B
+
+@table @var
+@item SEMI
+@file{ftp://ftp.m17n.org/pub/mule/semi/semi-1.13-for-flim-1.12/}
+
+@item FLIM
+@file{ftp://ftp.m17n.org/pub/mule/flim/flim-1.13/}
+
+@item APEL
+@file{ftp://ftp.m17n.org/pub/mule/apel/}
+
+@end table
+
+@item
+Q1.3: \e$BI,MW$J\e(B Emacs \e$B$N%P!<%8%g%s$O\e(B?
+
+T-gnus \e$B$,8x<0$KBP1~$7$F$$$k\e(B Emacs \e$B$N%P!<%8%g%s$O<!$NDL$j$G$9!#\e(B
+
+@itemize @bullet
+@item
+Emacs 19.34 \e$B$H$=$l0J>e$N\e(B Mule \e$B5!G=IU$-!#\e(B
+
+@item
+XEmacs 21.1.1 \e$B0J>e$N\e(B Mule \e$B5!G=IU$-\e(B
+
+@item
+Meadow 1.00 \e$B0J>e!#\e(B(Mule for Windows \e$B$G$OF0$-$^$;$s!#\e(B)
+
+@end itemize
+
+\e$B$H$O8@$&$b$N$N!"\e(BT-gnus \e$B$O%P!<%8%g%s\e(B 21.1.1 \e$BL$K~$N\e(B XEmacs, \e$BNc$($P\e(B 20.4 \e$B$G\e(B
+\e$B$b;H$($k$+$b$7$l$^$;$s!#>\$7$$$3$H$O\e(B T-gnus \e$B$NG[I[$K4^$^$l$F$$$k\e(B README
\e$B%U%!%$%k$rFI$s$G2<$5$$!#\e(B
+
+@item
+Q1.4: T-gnus \e$B$r\e(B GNU Emacs \e$B$H\e(B XEmacs \e$B$NN>J}$GF0$+$9$3$H$O$G$-$^$9$+\e(B?
+
+\e$B%=!<%9!&%l%Y%k\e(B( *.el )\e$B$G$O2DG=$G$9!#\e(B
+
+\e$B$7$+$7!"%P%$%H!&%3%s%Q%$%k$7$?%U%!%$%k\e(B ( *.elc ) \e$B$O6&M-$G$-$^$;$s$N$G!"\e(B
+\e$B$=$l$>$l;HMQ$9$k\e(B emacs \e$B$G%P%$%H%3%s%Q%$%k$9$kI,MW$,$"$j$^$9!#\e(B
+
+@item
+Q1.5: T-gnus \e$B$K$D$$$F$N>pJs8;$O\e(B?
+
+@table @var
+
+@item \e$B%K%e!<%9%0%k!<%W\e(B
+
+fj.news.reader.gnus \e$B$,$"$j$^$9$,!"\e(B T-gnus \e$B$K4X$7$F$N<ALd$G2sEz$rF@$i$l$k\e(B
+\e$B$H$9$l$P!"$[$H$s$I\e(B Semi-gnus-ja \e$B%a%$%j%s%0!&%j%9%H$N%a%s%P!<$G$7$g$&!#\e(B
+
+@item \e$B%a!<%j%s%0%j%9%H\e(B
+
+\e$B>\$7$/$O!"\e(B@xref{Mailing list FAQ, \e$B%a!<%j%s%0%j%9%H\e(B}, \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+\e$B8=:_!"$3$l$,$b$C$H$b3N<B$J>pJs8;$G$7$g$&!#\e(B T-gnus \e$B$r;H$&$N$G$"$l$P!"@'Hs\e(B
+\e$B;22C$9$k$3$H$r$*$9$9$a$7$^$9!#\e(B
+
+\e$B%@%$%8%'%9%HHG%5!<%S%9$O$"$j$^$;$s!#\e(B
+
+@item WWW
+
+\e$B8x<0$N\e(B Semi-gnus \e$B%[!<%`%Z!<%8$,$G$-$kM=Dj$G$9!#<9I.<TJg=8Cf$G$9!#\e(B
+
+@end table
+
+@item
+Q1.6: T-gnus \e$B$HO"7H$9$k%Q%C%1!<%8$O\e(B?
+
+@table @var
+
+@item SEMI
+
+T-gnus \e$B$G$O\e(B TM \e$B$O;HMQ$G$-$^$;$s!#Be$o$j$K\e(B SEMI \e$B$r;HMQ$7$^$9!#\e(B
+T-gnus \e$B$r;HMQ$9$k$?$a$K$O\e(B SEMI, FLIM, APEL \e$B$OI,?\$G$9!#\e(B
+
+.emacs \e$B$N\e(B gnus \e$B$N=i4|@_Dj$h$jA0$K0J2<$N@_Dj$r=q$$$F2<$5$$\e(B:
+
+@lisp
+(load "mime-setup")
+@end lisp
+
+@item Insidious Big Brother Database
+
+BBDB \e$B$O\e(B Netscape \e$B$GM-L>$J\e(B Jamie Zawinski <jwz@@netscape.com> \e$B$N:n$G!"\e(BGNU
+Emacs \e$BMQ$N\e(Brolodex-like \e$B$J%G!<%?%Y!<%9%W%m%0%i%`$G$9!#\e(B Jamie \e$B$O\e(B BBDB \e$B$N\e(B
+Web \e$B%Z!<%8$r;}$C$F$$$^$9!#\e(B @file{http://people.netscape.com/jwz/bbdb/}\e$B$3\e(B
+\e$B$l$O!"<!$N$H$3$m$K$b$"$j$^$9!#\e(B
+@file{ftp://ftp.xemacs.org/pub/xemacs/bbdb/} gnus-bbdb \e$B$O\e(B Brian Edmonds
+\e$B$N<!$N$H$3$m$+$i$bF~<j$G$-$^$9!#\e(B
+@file{http://www.cs.ubc.ca/spider/edmonds/usenet/gnus/gnus-bbdb.el}\e$B$3$l\e(B
+\e$B$O!"\e(B BBDB \e$B$N?7$7$$%P!<%8%g%sMQ$G!"FbMF$,\e(B gnus-bbdb.el \e$B$G$9!#\e(B
+
+Jamie \e$B$O8x<0$K$O\e(B BBDB \e$B$N%a%$%s%F%J!<%7%C%W$r\e(B Matt Simmons \e$B$K0z$-EO$7$F$$\e(B
+\e$B$^$9!#\e(B \e$BH`$N?7$7$$%P!<%8%g%s$OB8:_$7$^$9$,!"$"$/$^$G$b!HHs8x<0!I$J$b$N$G\e(B
+\e$B$9!#\e(B \e$B$3$l$O<!$N>l=j$K$"$j$^$9!#\e(B
+@file{http://www.netcom.com/%7Esimmonmt/index.html}
+
+T-gnus \e$B$G;HMQ$9$k>l9g$K$O!"I,$:\e(B Q2.1 \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@item gnus-offline
+gnus-offline \e$B$O!";T@nC#:H\e(B <t-ichi@@po.shiojiri.ne.jp> \e$B$N:n$G!"\e(B T-gnus \e$B$r\e(B
+\e$B$$$o$f$k!V%*%U%i%$%s;HMQ!W\e(B(\e$B%K%e!<%95-;v!"%a%$%k$NAw<u?.$r0l3g$7$F9T$$!"\e(B
+\e$B$=$l$i$N%a%C%;!<%8$NFI$_=q$-$O%5!<%P!<$KL$@\B3$N>uBV$G9T$&\e(B)\e$B$9$k$3$H$rMF\e(B
+\e$B0W$K$9$k$?$a$N%Q%C%1!<%8$G$9!#\e(BT-gnus (tag: t-gnus-6_14) \e$B$K$OI8=`$G4^$^$l\e(B
+\e$B$F$$$^$9!#\e(B
+
+@end table
+
+@item
+Q1.7: Draft \e$B$KJ]B8$7$?%a%C%;!<%8$r3+$/$HJ8;z$,2=$1$F$7$^$$$^$9!#\e(B
+
+gnus \e$B$,FI$_9~$_$K;HMQ$7$F$$$k$b$N$H0c$&%3!<%G%#%s%0%7%9%F%`$GJ]B8$5$l$F\e(B
+\e$B$$$k;v$,860x$G$9!#0J2<$N@_Dj$G2r7h$9$k$O$:$G$9!#\e(B
+
+@lisp
+(add-hook 'message-setup-hook
+          (lambda ()
+            (set-buffer-file-coding-system 'iso-2022-7bit)))
+@end lisp
+
+Q2.2 \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item
+Q1.8: T-gnus \e$B$N5/F0$rAa$/$9$k$K$O\e(B?
+
+\e$B9XFI$7$F$$$J$$%0%k!<%W$r\e(B ``kill'' (*Group* \e$B%P%C%U%!!<$G\e(B C-k) \e$B$7$F$"$k$3\e(B
+\e$B$H$r3NG'$7$F$/$@$5$$!#$=$7$F!">o$K\e(B ``.newsrc'' \e$B$r>.$5$/J]$D$h$&$K$7$F$/\e(B
+\e$B$@$5$$!#\e(B
+
+@end itemize
+
+@node Customization FAQ
+@subsection \e$B%+%9%?%^%$%:$K4X$9$k\e(B FAQ
+
+@itemize @bullet
+@item
+Q2.1: T-gnus \e$B$N%P!<%8%g%s$r$"$2$?$i\e(B BBDB \e$B$,F0$+$J$/$J$C$F$7$^$$$^$7$?!#\e(B
+
+Semi-gnus 6.8 \e$B0J9_$N%P!<%8%g%s$G$O!"%*%j%8%J%k$N\e(B bbdb-gnus.el \e$B$OF0:n$7$^\e(B
+\e$B$;$s!#\e(B \e$B<!$N$h$&$KBP1~$7$F$/$@$5$$!#\e(B
+
+bbdb-gnus.el \e$B$G!"\e(B gnus-article-buffer \e$B$NBe$j$K\e(B
+gnus-original-article-buffer \e$B$r;2>H$9$k$h$&$K$9$k!#\e(B
+
+\e$B$b$7!"%*%j%8%J%k$N\e(B Gnus (September \e$B0J9_\e(B) \e$B$r;H$C$F$$$k$N$G$"$l$P!"$3$NJ}\e(B
+\e$BK!$,NI$$$G$7$g$&!#\e(B
+
+\e$B$3$NJ}K!!"$*$h$S\e(B bbdb-user-mail-names \e$B$KBP1~$7$?\e(B BBDB 2.00.01 \e$B$KBP$9\e(B
+\e$B$k\e(B patch \e$B!"4pK\E*$J@_DjNc$,!"\e(B
+@file{http://www.mdcnet.co.jp/~keiichi/bbdb.shtml} \e$B$K$"$j$^$9!#\e(B
+
+@item
+Q2.2: hook \e$B$r@_Dj$7$?$i\e(B T-gnus \e$B$NF0:n$,$*$+$7$/$J$C$?\e(B
+
+\e$BDL>o$NJQ?t$G$bF1MM$G$9$,!"\e(B T-gnus \e$B$G$OB?$/$N\e(B hook \e$B$K=i4|CM$,@_Dj$5$l$F$$\e(B
+\e$B$^$9!#\e(B
+
+\e$B$3$NCM$rJQ99$7$h$&$H$7$F!"JQ?t$,Dj5A$5$l$F$$$k%U%!%$%k$r%m!<%I$9$kA0$K\e(B
+setq / add-hook \e$BEy$r9T$&$H!"$3$l$i$N=i4|CM$,@_Dj$5$l$:!"\e(B T-gnus \e$B$,@5>o$K\e(B
+\e$BF0:n$7$J$/$J$k>l9g$,$"$j$^$9!#\e(B(\e$BFC$K\e(B T-gnus \e$B$N%P!<%8%g%s$,JQ$C$?>l9g\e(B)
+
+\e$B$3$l$rKI$0$?$a$K$b!"\e(B T-gnus \e$B$K4X$9$k@_Dj$O$G$-$k$@$1\e(B ~/.gnus.el \e$BFb$G9T$&\e(B
+\e$B$h$&$K$7$F$/$@$5$$!#\e(B
+
+@item
+Q2.3: \e$B08@h$K$h$C$F\e(B Signature \e$B$rJQ99$9$k$K$O\e(B?
+
+SEMI \e$B$K$O\e(B signature.el \e$B$H$$$&$3$N$?$a$N%D!<%k$,IUB0$7$F$$$^$9!#;HMQJ}K!\e(B
+\e$B$O0J2<$N$H$*$j$G$9!#\e(B
+
+tm \e$B$N\e(B info \e$B$NFbMF$r\e(B SEMI \e$B$K9g$o$;$FJQ99$7$?$b$N$G$9!#\e(B
+
+SEMI \e$B$K$O\e(B *signature* \e$B$H$$$&\e(B signature \e$B$N<+F0@ZBX$(\e(B tool \e$B$,ImB0$7$F$*$j!"\e(B
+`semi-setup.el' \e$B$O$3$N@_Dj$b9T$J$$$^$9!#\e(Bmessage header \e$B$N\e(B field \e$B$K9g$o$;\e(B
+\e$B$F\e(B signature \e$B$N<+F0@ZBX$r9T$J$$$?$$>l9g$O\e(B `~/.emacs' \e$B$K0J2<$N$h$&$J$b$N\e(B
+\e$B$rF~$l$F2<$5$$!#!J>\$7$/$O\e(B signature.el \e$B$N@bL@=q$r;2>H$7$F2<$5$$!K\e(B
+
+@lisp
+(setq signature-file-alist
+      '((("Newsgroups" . "jokes")       . "~/.signature-jokes")
+        (("Newsgroups" . ("zxr" "nzr")) . "~/.signature-sun")
+        (("To" . ("ishimaru" "z-suzuki")) . "~/.signature-sun")
+        (("To" . "tea")                 . "~/.signature-jokes")
+        (("To" . ("sim" "oku" "takuo")) . "~/.signature-formal")
+        ))
+@end lisp
+
+@defvar mime-setup-use-signature
+
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B0J30$N;~!"\e(B@file{signature.el} \e$B$r;H$$$^$9!#=i4|CM$O\e(B
+@code{t} \e$B$G$9!#\e(B
+@end defvar
+
+@defvar mime-setup-signature-key-alist
+
+\e$B3F\e(B major-mode \e$B$K$*$$$F\e(B signature \e$BA^F~L?Na$r@_Dj$9$Y$-\e(B key \e$B$r;XDj$7$^$9!#\e(B
+\e$B=i4|CM$O\e(B
+
+@lisp
+       ((mail-mode . "\C-c\C-w"))
+@end lisp
+
+\e$B$G$9!#\e(B
+
+\e$B$3$l$rJQ99$7$?$$>l9g$O!"4X?t\e(B set-alist \e$B$J$I$r;H$C$F$3$NJQ?t$r=q$-49$(\e(B
+\e$B$F2<$5$$!#\e(B
+
+@lisp
+(set-alist 'mime-setup-signature-key-alist
+          'news-reply-mode "\C-c\C-w")
+@end lisp
+
+@end defvar
+
+@defvar mime-setup-default-signature-key
+
+\e$B$"$k\e(B major-mode \e$B$K$*$$$F\e(B signature \e$BA^F~L?Na$r@_Dj$9$Y$-\e(B key \e$B$,8+$D$+$i$J\e(B
+\e$B$$>l9g!"$3$NJQ?t$K@_Dj$5$l$?\e(B key \e$B$,MQ$$$i$l$^$9!#=i4|CM$O!"\e(B
+@code{"\C-c\C-s"} \e$B$G$9!#\e(B
+@end defvar
+
+gnus-posting-style \e$B$r;HMQ$9$k;v$b$G$-$^$9!#\e(B
+
+@end itemize
+
+@node Reading News FAQ
+@subsection \e$B%K%e!<%9$rFI$`\e(B
+
+@node Reading Mail FAQ
+@subsection \e$B%a!<%k$rFI$`\e(B
+
+@node Mailing list FAQ
+@subsection \e$B%a!<%j%s%0%j%9%H\e(B
+
+@itemize @bullet
+@item
+Q5.1: \e$B%a%$%j%s%0!&%j%9%H$+$iC&B`$9$k$K$O\e(B?
+
+@table @var
+@item \e$BF|K\8lMQ\e(B
+@file{semi-gnus-ja-unsubscribe@@meadowy.org} \e$B$K6u$N%a%$%k$rAw$C$F2<$5$$!#\e(B
+(Subject \e$B$bITMW$G$9!#\e(B)
+
+@item \e$B1Q8lMQ\e(B
+@file{semi-gnus-en-unsubscribe@@meadowy.org} \e$B$K6u$N%a%$%k$rAw$C$F2<$5$$!#\e(B
+(Subject \e$B$bITMW$G$9!#\e(B)
+
+@end table
+
+@item
+Q5.2: \e$B%a%$%j%s%0!&%j%9%H$K;22C$9$k$K$O\e(B?
+
+T-gnus \e$B$G$O!"MxMQ<T$H0];}<T$H$$$&=>Mh$NB?$/$N%Q%C%1!<%8$G:NMQ$5$l$F$$$k\e(B
+\e$B3+H/BN@)$O<h$C$F$$$^$;$s!#\e(B \e$B$=$N$?$a!"%a!<%j%s%0%j%9%H$H$7$F$bMxMQ<TMQ!"\e(B
+\e$B3+H/<TMQ$H$$$&6hJL$r9T$C$F$$$^$;$s!#\e(B
+
+@table @var
+@item \e$BF|K\8lMQ\e(B
+@file{semi-gnus-ja-help@@meadowy.org} \e$B$K6u$N%a!<%k$rAw$C$F!"Aw$i$l$F$/$k\e(B
+\e$B%a!<%k$N;X<($K=>$C$F$/$/$@$5$$!#\e(B(Subject \e$B$bITMW$G$9!#\e(B)
+
+@item \e$B1Q8lMQ\e(B
+@file{semi-gnus-en-help@@meadowy.org} \e$B$K6u$N%a!<%k$rAw$C$F!"Aw$i$l$F$/$k\e(B
+\e$B%a!<%k$N;X<($K=>$C$F$/$@$5$$!#\e(B(Subject \e$B$bITMW$G$9!#\e(B)
+
+@end table
+
+@item
+Q5.3: T-gnus \e$B$K4X$9$kJ}?K7hDj$O\e(B?
+
+T-gnus \e$B$N3+H/Ey$K4X$9$kJ}?K$N7hDj$OA4$F\e(B Semi-gnus-ja/en \e$B%a!<%j%s%0%j%9%H\e(B
+\e$BFb$G9T$o$l$^$9!#\e(B \e$B3F%a%s%P!<$+$i$NDs0F$O%"%s%1!<%H$N7A$GDs0F$5$l7h5D$5$l\e(B
+\e$B$^$9$,!"$=$NJ}K!$O<!$N<j=g$G9T$o$l$^$9!#\e(B
+
+@enumerate
+@item
+\e$B$3$N<j=g$O!"8xE*$J;^$N:n@.$d!";^$N4IM}K!!"\e(Bsnapshot \e$B$N07$$$J$I$N!"8xE*$J\e(B
+\e$B0F7o$K4X$7$F!"C10l$NJ}?K$r7hDj$5$l$k>l9g$KE,MQ$5$l$k!#\e(B \e$B;dE*$J;^$dHG$K4X\e(B
+\e$B$7$F$OE,MQ$5$l$J$$!#\e(B
+
+@item
+\e$B8xE*$J0F7o$NDs0F$*$h$S5DO@$O\e(B semi-gnus-ja@@meadowy.org \e$B$b$7$/\e(B
+\e$B$O\e(B semi-gnus-en@@meadowy.org \e$B$G9T$&!#\e(B
+
+@item
+\e$B:G=*E*$JJ}?K$O%"%s%1!<%H7k2L$NB??t0U8+$r:NMQ$9$k!#\e(B
+
+@item
+\e$BDs0F<T$O%"%s%1!<%H$N2sEz4|8B$r@_$1$k$3$H$,$G$-$k!#$3$l$O#1F|0J>e$G$J$1$l\e(B
+\e$B$P$J$i$J$$!#\e(B
+
+@item
+\e$BDs0F<T$,%"%s%1!<%H$N2sEz4|8B$r;XDj$7$J$+$C$?>l9g!"Ds0FF|$h$j#1=54V8e$r2s\e(B
+\e$BEz4|8B$H$9$k!#\e(B
+
+@item
+\e$BDs0F<T$O!"%"%s%1!<%H$N2sEz4|8BFb$K!"$3$N%"%s%1!<%H$K#5L>0J>e$N2sEz$,$"$C\e(B
+\e$B$?;~E@$G%"%s%1!<%H$N=*N;$r@k8@$G$-$k!#\e(B \e$B$3$N>l9g!"%"%s%1!<%H$NB??t0U8+$r\e(B
+\e$B7kO@$H$9$k!#\e(B
+
+@item
+\e$B2sEz4|8B$,2a$.$F$b!"#5L>0J>e$N2sEz$,$J$$>l9g$O!"Ds0F<T$,$=$N7kO@$r7hDj$9\e(B
+\e$B$k$3$H$,$G$-$k!#\e(B
+
+@item
+\e$B;22C<T$O%"%s%1!<%H$N2sEz4|8BFb$K%"%s%1!<%H$N2sEz4|8B$N1dD9$rMW5a$G$-$k!#\e(B
+\e$BDs0F<T$,$3$l$rG'$a$k$+#5?M0J>e$N;22C<T$,$3$l$rG'$a$?>l9g!"2sEz4|8B$O1dD9\e(B
+\e$B$5$l$k!#\e(B
+@end enumerate
+
+@end itemize
index abc9054..f6e4cf8 100644 (file)
 @c Insert  "\input texinfo" at 1st line before texing this file alone.
 @c -*-texinfo-*-
-@c Copyright (C) 1995 Free Software Foundation, Inc.
+@c Copyright (C) 1995, 2001, 2003, 2004 Free Software Foundation, Inc.
 @setfilename gnus-faq.info
 
+@c Frequently Asked Questions, FAQ - Introduction, Emacs for Heathens, Top
+
 @node Frequently Asked Questions
+@comment  node-name,  next,  previous,  up
+
+@c @chapter Frequently Asked Questions
 @section Frequently Asked Questions
+@cindex FAQ
+@cindex Frequently Asked Questions
 
-This is the Gnus Frequently Asked Questions list.
-If you have a Web browser, the official hypertext version is at
-@file{http://www.ccs.neu.edu/software/gnus/}, and has
-probably been updated since you got this manual.
+@c - Uncomment @chapter, comment @section
+@c - run (texinfo-every-node-update)
+@c - revert it.
 
 @menu
-* Installation FAQ::      Installation of Gnus.
-* Customization FAQ::     Customizing Gnus.
-* Reading News FAQ::      News Reading Questions.
-* Reading Mail FAQ::      Mail Reading Questions.
+* FAQ - Introduction::                    About Gnus and this FAQ.
+* FAQ 1 - Installation::                  Installation of Gnus.
+* FAQ 2 - Startup / Group buffer::        Start up questions and the first
+                                          buffer Gnus shows you.
+* FAQ 3 - Getting messages::              Making Gnus read your mail and news.
+* FAQ 4 - Reading messages::              How to efficiently read messages.
+* FAQ 5 - Composing messages::            Composing mails or Usenet postings.
+* FAQ 6 - Old messages::                  Importing, archiving, searching
+                                          and deleting messages.
+* FAQ 7 - Gnus in a dial-up environment:: Reading mail and news while offline.
+* FAQ 8 - Getting help::                  When this FAQ isn't enough.
+* FAQ 9 - Tuning Gnus::                   How to make Gnus faster.
+* FAQ - Glossary::                        Terms used in the FAQ explained.
 @end menu
 
 
-@node Installation FAQ
+@subheading Abstract
+
+ This is the new Gnus Frequently Asked Questions list.  If you have a
+Web browser, the official hypertext version is at
+@uref{http://my.gnus.org/FAQ/}, the Docbook source is available from
+@uref{http://sourceforge.net/projects/gnus/}.
+
+ Please submit features and suggestions to the 
+ @email{faq-discuss@@my.gnus.org,FAQ discussion list}.
+ The list is protected against junk mail with
+ @uref{http://smarden.org/qconfirm/index.html,qconfirm, qconfirm}. As
+ a subscriber, your submissions will automatically pass. You can
+ also subscribe to the list by sending a blank email to
+ @email{faq-discuss-subscribe@@my.gnus.org}
+ and
+ @uref{http://mail1.kens.com/cgi-bin/ezmlm-browse?command=monthbythread%26list=faq-discuss,browse
+ the archive, browse the archive}. 
+@node FAQ - Introduction, FAQ 1 - Installation, Frequently Asked Questions, Frequently Asked Questions
+@comment  node-name,  next,  previous,  up
+@heading Introduction
+
+This is the Gnus Frequently Asked Questions list.
+
+Gnus is a Usenet Newsreader and Electronic Mail User Agent implemented
+ as a part of Emacs. It's been around in some form for almost a decade
+ now, and has been distributed as a standard part of Emacs for much of
+ that time. Gnus 5 is the latest (and greatest) incarnation. The
+ original version was called GNUS, and was written by Masanobu UMEDA.
+ When autumn crept up in '94, Lars Magne Ingebrigtsen grew bored and
+ decided to rewrite Gnus.
+
+ Its biggest strength is the fact that it is extremely
+ customizable. It is somewhat intimidating at first glance, but
+ most of the complexity can be ignored until you're ready to take
+ advantage of it. If you receive a reasonable volume of e-mail
+ (you're on various mailing lists), or you would like to read
+ high-volume mailing lists but cannot keep up with them, or read
+ high volume newsgroups or are just bored, then Gnus is what you
+ want.
+
+ This FAQ was maintained by Justin Sheehy until March 2002. He
+ would like to thank Steve Baur and Per Abrahamsen for doing a wonderful
+ job with this FAQ before him. We would like to do the same - thanks,
+ Justin!
+
+ If you have a Web browser, the official hypertext version is at:@*
+ @uref{http://my.gnus.org/FAQ/}.
+ This version is much nicer than the unofficial hypertext
+ versions that are archived at Utrecht, Oxford, Smart Pages, Ohio
+ State, and other FAQ archives. See the resources question below
+ if you want information on obtaining it in another format.
+
+ The information contained here was compiled with the assistance
+ of the Gnus development mailing list, and any errors or
+ misprints are the my.gnus.org team's fault, sorry.
+
+
+@ifnottex
+@node FAQ 1 - Installation, FAQ 2 - Startup / Group buffer, FAQ - Introduction, Frequently Asked Questions
+@end ifnottex
 @subsection Installation
 
-@itemize @bullet
-@item
-Q1.1  What is the latest version of Gnus?
+@menu
+* [1.1]::   What is the latest version of Gnus?
+* [1.2]::   What's new in 5.10.0?
+* [1.3]::   Where and how to get Gnus?
+* [1.4]::   What to do with the tarball now? 
+* [1.5]::   Which version of Emacs do I need?
+* [1.6]::   How do I run Gnus on both Emacs and XEmacs?
+@end menu
 
-The latest (and greatest) version is 5.0.10.  You might also run
-across something called @emph{September Gnus}.  September Gnus
-is the alpha version of the next major release of Gnus.  It is currently
-not stable enough to run unless you are prepared to debug lisp.
 
-@item
-Q1.2  Where do I get Gnus?
+@ifnottex
+@node [1.1], [1.2], FAQ 1 - Installation, FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.1: 
 
-Any of the following locations:
+What is the latest version of Gnus?
 
-@itemize @minus
-@item
-@file{ftp://ftp.ifi.uio.no/pub/emacs/gnus/gnus.tar.gz}
+Answer: 
 
-@item
-@file{ftp://ftp.pilgrim.umass.edu/pub/misc/ding/}
+ Jingle please: Gnus 5.10.0 is released, get it while it's
+ hot! As well as the step in version number is rather
+ small, Gnus 5.10 has tons of new features which you
+ shouldn't miss, however if you are cautious, you might
+ prefer to stay with 5.8.8 respectively 5.9 (they are
+ basically the same) until some bugfix releases are out.
+@ifnottex
+@node [1.2], [1.3], [1.1], FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.2: 
 
-@item
-@file{gopher://gopher.pilgrim.umass.edu/11/pub/misc/ding/}
+What's new in 5.10.0?
 
-@item
-@file{ftp://aphrodite.nectar.cs.cmu.edu/pub/ding-gnus/}
+Answer: 
 
-@item
-@file{ftp://ftp.solace.mh.se:/pub/gnu/elisp/}
+ First of all, you should have a look into the file
+ GNUS-NEWS in the toplevel directory of the Gnus tarball,
+ there the most important changes are listed. Here's a
+ short list of the changes I find especially
+ important/interesting:
 
-@end itemize
+
+@itemize @bullet{}
 
 @item
-Q1.3  Which version of Emacs do I need?
+ Major rewrite of the Gnus agent, Gnus agent is now
+ active by default.
+@item
+ Many new article washing functions for dealing with
+ ugly formatted articles.
+@item
+ Anti Spam features.
+@item
+ message-utils now included in Gnus.
+@item
+ New format specifiers for summary lines, e.g. %B for
+ a complex trn-style thread tree.
+@end itemize
+@ifnottex
+@node [1.3], [1.4], [1.2], FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.3: 
+
+Where and how to get Gnus?
+
+Answer: 
+
+ The latest released version of Gnus isn't included in
+ Emacs 21 and until now it also isn't available through the
+ package system of XEmacs 21.4, therefor you should get the
+ Gnus tarball from
+ @uref{http://www.gnus.org/dist/gnus.tar.gz}
+ or via anonymous FTP from 
+ @uref{ftp://ftp.gnus.org/pub/gnus/gnus.tar.gz}.
+@ifnottex
+@node [1.4], [1.5], [1.3], FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.4: 
+
+ What to do with the tarball now?
+
+Answer: 
+
+ Untar it via @samp{tar xvzf gnus.tar.gz} and do the common 
+ @samp{./configure; make; make install} circle.
+ (under MS-Windows either get the Cygwin environment from
+ @uref{http://www.cygwin.com}
+ which allows you to do what's described above or unpack the
+ tarball with some packer (e.g. Winace from
+ @uref{http://www.winace.com})
+ and use the batch-file make.bat included in the tarball to install
+ Gnus. If you don't want to (or aren't allowed to) install Gnus
+ system-wide, you can install it in your home directory and add the
+ following lines to your ~/.xemacs/init.el or ~/.emacs:
 
-At least GNU Emacs 19.28, or XEmacs 19.12 is recommended.  GNU Emacs
-19.25 has been reported to work under certain circumstances, but it
-doesn't @emph{officially} work on it.  19.27 has also been reported to
-work.  Gnus has been reported to work under OS/2 as well as Unix.
+@example
+(add-to-list 'load-path "/path/to/gnus/lisp")
+(if (featurep 'xemacs)
+    (add-to-list 'Info-directory-list "/path/to/gnus/texi/")
+  (add-to-list 'Info-default-directory-list "/path/to/gnus/texi/"))
+@end example
 
+@noindent
+ Make sure that you don't have any Gnus related stuff
+ before this line, on MS Windows use something like
+ "C:/path/to/lisp" (yes, "/").
+@ifnottex
+@node [1.5], [1.6], [1.4], FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.5: 
+
+Which version of Emacs do I need?
+
+Answer: 
+
+ Gnus 5.10.0 requires an Emacs version that is greater
+ than or equal to Emacs 20.7 or XEmacs 21.1.
+@ifnottex
+@node [1.6],  , [1.5], FAQ 1 - Installation
+@end ifnottex
+@subsubheading Question 1.6: 
+
+How do I run Gnus on both Emacs and XEmacs?
+
+Answer: 
+
+ You can't use the same copy of Gnus in both as the Lisp
+ files are byte-compiled to a format which is different
+ depending on which Emacs did the compilation. Get one copy
+ of Gnus for Emacs and one for XEmacs.
+@ifnottex
+@node FAQ 2 - Startup / Group buffer, FAQ 3 - Getting messages, FAQ 1 - Installation, Frequently Asked Questions
+@end ifnottex
+@subsection Startup / Group buffer
 
-@item
-Q1.4  Where is timezone.el?
+@menu
+* [2.1]::   Every time I start Gnus I get a message
+            "Gnus auto-save file exists. Do you want to read it?", 
+            what does this mean and how to prevent it? 
+* [2.2]::   Gnus doesn't remember which groups I'm subscribed to, what's this? 
+* [2.3]::   How to change the format of the lines in Group buffer? 
+* [2.4]::   My group buffer becomes a bit crowded, is there a way to sort my
+            groups into categories so I can easier browse through them?
+* [2.5]::   How to manually sort the groups in Group buffer? How to sort the
+            groups in a topic? 
+@end menu
 
-Upgrade to XEmacs 19.13.  In earlier versions of XEmacs this file was
-placed with Gnus 4.1.3, but that has been corrected.
+@ifnottex
+@node [2.1], [2.2], FAQ 2 - Startup / Group buffer, FAQ 2 - Startup / Group buffer
+@end ifnottex
+@subsubheading Question 2.1: 
+
+ Every time I start Gnus I get a message "Gnus auto-save
+ file exists. Do you want to read it?", what does this mean
+ and how to prevent it?
+
+Answer: 
+
+ This message means that the last time you used Gnus, it
+ wasn't properly exited and therefor couldn't write its
+ informations to disk (e.g. which messages you read), you
+ are now asked if you want to restore those informations
+ from the auto-save file.
+
+ To prevent this message make sure you exit Gnus
+ via @samp{q} in group buffer instead of
+ just killing Emacs.
+@ifnottex
+@node [2.2], [2.3], [2.1], FAQ 2 - Startup / Group buffer
+@end ifnottex
+@subsubheading Question: 2.2 
+
+ Gnus doesn't remember which groups I'm subscribed to,
+ what's this?
+
+Answer: 
+
+ You get the message described in the q/a pair above while
+ starting Gnus, right? It's an other symptom for the same
+ problem, so read the answer above.
+@ifnottex
+@node [2.3], [2.4], [2.2], FAQ 2 - Startup / Group buffer
+@end ifnottex
+@subsubheading Question 2.3: 
+
+ How to change the format of the lines in Group buffer?
+
+Answer: 
+
+ You've got to tweak the value of the variable
+ gnus-group-line-format. See the manual node "Group Line
+ Specification" for information on how to do this. An
+ example for this (guess from whose .gnus :-)):
 
+@example
 
-@item
-Q1.5  When I run Gnus on XEmacs 19.13 I get weird error messages.
+(setq gnus-group-line-format "%P%M%S[%5t]%5y : %(%g%)\n")
+            
+@end example
+@ifnottex
+@node [2.4], [2.5], [2.3], FAQ 2 - Startup / Group buffer
+@end ifnottex
+@subsubheading Question 2.4: 
+
+ My group buffer becomes a bit crowded, is there a way to
+ sort my groups into categories so I can easier browse
+ through them?
+
+Answer: 
+
+ Gnus offers the topic mode, it allows you to sort your
+ groups in, well, topics, e.g. all groups dealing with
+ Linux under the topic linux, all dealing with music under
+ the topic music and all dealing with scottish music under
+ the topic scottish which is a subtopic of music.
+
+ To enter topic mode, just hit t while in Group buffer. Now
+ you can use @samp{T n} to create a topic
+ at point and @samp{T m} to move a group to
+ a specific topic. For more commands see the manual or the
+ menu. You might want to include the %P specifier at the
+ beginning of your gnus-group-line-format variable to have
+ the groups nicely indented.
+@ifnottex
+@node [2.5],  , [2.4], FAQ 2 - Startup / Group buffer
+@end ifnottex
+@subsubheading Question 2.5: 
+
+ How to manually sort the groups in Group buffer? How to
+ sort the groups in a topic?
+
+Answer: 
+
+ Move point over the group you want to move and
+ hit @samp{C-k}, now move point to the
+ place where you want the group to be and
+ hit @samp{C-y}.
+@ifnottex
+@node FAQ 3 - Getting messages, FAQ 4 - Reading messages, FAQ 2 - Startup / Group buffer, Frequently Asked Questions
+@end ifnottex
+@subsection Getting messages
 
-You're running an old version of Gnus.  Upgrade to at least version
-5.0.4.
+@menu
+* [3.1]::   I just installed Gnus, started it via M-x gnus but it only says
+            "nntp (news) open error", what to do? 
+* [3.2]::   I'm working under Windows and have no idea what ~/.gnus means. 
+* [3.3]::   My news server requires authentication, how to store user name
+            and password on disk? 
+* [3.4]::   Gnus seems to start up OK, but I can't find out how to
+            subscribe to a group. 
+* [3.5]::   Gnus doesn't show all groups / Gnus says I'm not allowed to
+            post on this server as well as I am, what's that?
+* [3.6]::   I want Gnus to fetch news from several servers, is this possible? 
+* [3.7]::   And how about local spool files? 
+* [3.8]::   OK, reading news works now, but I want to be able to read my mail
+            with Gnus, too. How to do it? 
+* [3.9]::   And what about IMAP? 
+* [3.10]::  At the office we use one of those MS Exchange servers,
+            can I use Gnus to read my mail from it? 
+* [3.11]::  Can I tell Gnus not to delete the mails on the server
+            it retrieves via POP3? 
+@end menu
 
+@ifnottex
+@node [3.1], [3.2], FAQ 3 - Getting messages, FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.1: 
 
-@item
-Q1.6  How do I unsubscribe from the Mailing List?
+ I just installed Gnus, started it via 
+ @samp{M-x gnus} 
+ but it only says "nntp (news) open error", what to do?
 
-Send an e-mail message to @file{ding-request@@ifi.uio.no} with the magic word
-@emph{unsubscribe} somewhere in it, and you will be removed.
+Answer: 
 
-If you are reading the digest version of the list, send an e-mail message
-to @*
-@file{ding-rn-digests-d-request@@moe.shore.net}
-with @emph{unsubscribe} as the subject and you will be removed.
+ You've got to tell Gnus where to fetch the news from. Read
+ the documentation for information on how to do this. As a
+ first start, put those lines in ~/.gnus:
 
+@example
+(setq gnus-select-method '(nntp "news.yourprovider.net"))
+(setq user-mail-address "you@@yourprovider.net")
+(setq user-full-name "Your Name")
+@end example
+@ifnottex
+@node [3.2], [3.3], [3.1], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.2: 
+
+ I'm working under Windows and have no idea what ~/.gnus means.
+
+Answer: 
+
+ The ~/ means the home directory where Gnus and Emacs look for the
+configuration files. However, you don't really need to know what this
+means, it suffices that Emacs knows what it means :-) You can type
+@samp{C-x C-f ~/.gnus RET } (yes, with the forward slash, even on
+Windows), and Emacs will open the right file for you. (It will most
+likely be new, and thus empty.)  However, I'd discourage you from
+doing so, since the directory Emacs chooses will most certainly not be
+what you want, so let's do it the correct way.  The first thing you've
+got to do is to create a suitable directory (no blanks in directory
+name please) e.g. @file{c:\myhome}. Then you must set the environment
+variable HOME to this directory. To do this under Win9x or Me include
+the line
 
-@item
-Q1.7  How do I run Gnus on both Emacs and XEmacs?
+@example
 
-The basic answer is to byte-compile under XEmacs, and then you can
-run under either Emacsen.  There is, however, a potential version
-problem with easymenu.el with Gnu Emacs prior to 19.29.
+SET HOME=C:\myhome
+           
+@end example
 
-Per Abrahamsen <abraham@@dina.kvl.dk> writes :@*
-The internal easymenu.el interface changed between 19.28 and 19.29 in
-order to make it possible to create byte compiled files that can be
-shared between Gnu Emacs and XEmacs.  The change is upward
-compatible, but not downward compatible. 
-This gives the following compatibility table:
+@noindent
+ in your autoexec.bat and reboot. Under NT, 2000 and XP,
+ hit Winkey+Pause/Break to enter system options (if it
+ doesn't work, go to Control Panel -> System). There you'll
+ find the possibility to set environment variables, create
+ a new one with name HOME and value @file{c:\myhome}, a reboot is
+ not necessary.
+
+ Now to create ~/.gnus, say
+ @samp{C-x C-f ~/.gnus RET C-x C-s}.
+ in Emacs. 
+@ifnottex
+@node [3.3], [3.4], [3.2], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.3: 
+
+ My news server requires authentication, how to store
+ user name and password on disk?
+
+Answer: 
+
+ Create a file ~/.authinfo which includes for each server a line like this
 
 @example
-Compiled with:  | Can be used with:
-----------------+--------------------------------------
-19.28           | 19.28         19.29
-19.29           |               19.29           XEmacs
-XEmacs          |               19.29           XEmacs
+machine news.yourprovider.net login YourUserName password YourPassword
 @end example
 
-If you have Gnu Emacs 19.28 or earlier, or XEmacs 19.12 or earlier, get
-a recent version of auc-menu.el from
-@file{ftp://ftp.iesd.auc.dk/pub/emacs-lisp/auc-menu.el}, and install it
-under the name easymenu.el somewhere early in your load path.
+@noindent
+.
+ Make sure that the file isn't readable to others if you
+ work on a OS which is capable of doing so. (Under Unix
+ say 
 
+@example
+chmod 600 ~/.authinfo
+@end example
 
-@item
-Q1.8 What resources are available?
-
-There is the newsgroup Gnu.emacs.gnus. Discussion of Gnus 5.x is now
-taking place there. There is also a mailing list, send mail to
-@file{ding-request@@ifi.uio.no} with the magic word @emph{subscribe}
-somewhere in it.
-
-@emph{NOTE:} the traffic on this list is heavy so you may not want to be
-on it (unless you use Gnus as your mailer reader, that is). The mailing
-list is mainly for developers and testers.
-
-Gnus has a home World Wide Web page at@*
-@file{http://www.ifi.uio.no/~larsi/ding.html}.
-   
-Gnus has a write up in the X Windows Applications FAQ at@*
-@file{http://www.ee.ryerson.ca:8080/~elf/xapps/Q-III.html}.
-   
-The Gnus manual is also available on the World Wide Web. The canonical
-source is in Norway at@*
-@file{http://www.ifi.uio.no/~larsi/ding-manual/gnus_toc.html}.
-
-There are three mirrors in the United States:
-@enumerate
-@item
-@file{http://www.miranova.com/gnus-man/}
+@noindent
+ in a shell.)
+@ifnottex
+@node [3.4], [3.5], [3.3], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.4: 
+
+ Gnus seems to start up OK, but I can't find out how to
+ subscribe to a group.
+
+Answer: 
+
+ If you know the name of the group say @samp{U
+ name.of.group RET} in group buffer (use the
+ tab-completion Luke). Otherwise hit ^ in group buffer,
+ this brings you to the server buffer. Now place point (the
+ cursor) over the server which carries the group you want,
+ hit @samp{RET}, move point to the group
+ you want to subscribe to and say @samp{u}
+ to subscribe to it.
+@ifnottex
+@node [3.5], [3.6], [3.4], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.5: 
+
+ Gnus doesn't show all groups / Gnus says I'm not allowed to
+ post on this server as well as I am, what's that?
+
+Answer: 
+
+ Some providers allow restricted anonymous access and full
+ access only after authorization. To make Gnus send authinfo
+ to those servers append 
 
-@item
-@file{http://www.pilgrim.umass.edu/pub/misc/ding/manual/gnus_toc.html}
+@example
+force yes
+@end example
 
-@item
-@file{http://www.rtd.com/~woo/gnus/}
+@noindent
+ to the line for those servers in ~/.authinfo.
+@ifnottex
+@node [3.6], [3.7], [3.5], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.6: 
 
-@end enumerate
+ I want Gnus to fetch news from several servers, is this possible?
 
-PostScript copies of the Gnus Reference card are available from@*
-@file{ftp://ftp.cs.ualberta.ca/pub/oolog/gnus/}.  They are mirrored at@*
-@file{ftp://ftp.pilgrim.umass.edu/pub/misc/ding/refcard/} in the
-United States. And@*
-@file{ftp://marvin.fkphy.uni-duesseldorf.de/pub/gnus/}
-in Germany.
-   
-An online version of the Gnus FAQ is available at@*
-@file{http://www.miranova.com/~steve/gnus-faq.html}. Off-line formats
-are also available:@*
-ASCII: @file{ftp://ftp.miranova.com/pub/gnus/gnus-faq}@*
-PostScript: @file{ftp://ftp.miranova.com/pub/gnus/gnus-faq.ps}.
+Answer: 
 
+ Of course. You can specify more sources for articles in the
+ variable gnus-secondary-select-methods. Add something like
+ this in ~/.gnus:
 
-@item
-Q1.9  Gnus hangs on connecting to NNTP server
+@example
+(add-to-list 'gnus-secondary-select-methods 
+            '(nntp "news.yourSecondProvider.net"))
+(add-to-list 'gnus-secondary-select-methods 
+            '(nntp "news.yourThirdProvider.net"))          
+@end example
+@ifnottex
+@node [3.7], [3.8], [3.6], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.7: 
 
-I am running XEmacs on SunOS and Gnus prints a message about Connecting
-to NNTP server and then just hangs.
+ And how about local spool files?
 
-Ben Wing <wing@@netcom.com> writes :@*
-I wonder if you're hitting the infamous @emph{libresolv} problem.
-The basic problem is that under SunOS you can compile either
-with DNS or NIS name lookup libraries but not both.  Try
-substituting the IP address and see if that works; if so, you
-need to download the sources and recompile.
+Answer: 
 
+ No problem, this is just one more select method called
+ nnspool, so you want this:
 
-@item
-Q1.10  Mailcrypt 3.4 doesn't work
+@example
+(add-to-list 'gnus-secondary-select-methods '(nnspool ""))
+@end example
 
-This problem is verified to still exist in Gnus 5.0.9 and Mailcrypt 3.4.
-The answer comes from Peter Arius
-<arius@@immd2.informatik.uni-erlangen.de>.
+@noindent
+ Or this if you don't want an NNTP Server as primary news source:
 
-I found out that mailcrypt uses
-@code{gnus-eval-in-buffer-window}, which is a macro.
-It seems as if you have
-compiled mailcrypt with plain old GNUS in load path, and the XEmacs byte
-compiler has inserted that macro definition into
-@file{mc-toplev.elc}.
-The solution is to recompile @file{mc-toplev.el} with Gnus 5 in
-load-path, and it works fine.
+@example
+(setq gnus-select-method '(nnspool ""))
+@end example
 
-Steve Baur <steve@@miranova.com> adds :@*
-The problem also manifests itself if neither GNUS 4 nor Gnus 5 is in the
-load-path.
+@noindent
+ Gnus will look for the spool file in /usr/spool/news, if you
+ want something different, change the line above to something like this:
 
+@example
+(add-to-list 'gnus-secondary-select-methods
+             '(nnspool "" (nnspool-directory "/usr/local/myspoolddir")))
+@end example
 
-@item
-Q1.11  What other packages work with Gnus?
+@noindent
+ This sets the spool directory for this server only.
+ You might have to specify more stuff like the program used
+ to post articles, see the Gnus manual on how to do this.
+@ifnottex
+@node [3.8], [3.9], [3.7], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.8: 
+
+ OK, reading news works now, but I want to be able to read my mail
+ with Gnus, too. How to do it?
+
+Answer: 
+
+ That's a bit harder since there are many possible sources
+ for mail, many possible ways for storing mail and many
+ different ways for sending mail. The most common cases are
+ these: 1: You want to read your mail from a pop3 server and
+ send them directly to a SMTP Server 2: Some program like
+ fetchmail retrieves your mail and stores it on disk from
+ where Gnus shall read it. Outgoing mail is sent by
+ Sendmail, Postfix or some other MTA. Sometimes, you even
+ need a combination of the above cases.
+
+ However, the first thing to do is to tell Gnus in which way
+ it should store the mail, in Gnus terminology which back end
+ to use. Gnus supports many different back ends, the most
+ commonly used one is nnml. It stores every mail in one file
+ and is therefor quite fast. However you might prefer a one
+ file per group approach if your file system has problems with
+ many small files, the nnfolder back end is then probably the
+ choice for you. To use nnml add the following to ~/.gnus:
 
-@itemize @minus
-@item
-Mailcrypt.
+@example
+(add-to-list 'gnus-secondary-select-methods '(nnml ""))
+@end example
 
-Mailcrypt is an Emacs interface to PGP.  It works, it installs
-without hassle, and integrates very easily.  Mailcrypt can be
-obtained from@*
-@file{ftp://cag.lcs.mit.edu/pub/patl/mailcrypt-3.4.tar.gz}.
+@noindent
+ As you might have guessed, if you want nnfolder, it's
 
-@item
-Tools for Mime.
-
-Tools for Mime is an Emacs MUA interface to MIME.  Installation is
-a two-step process unlike most other packages, so you should
-be prepared to move the byte-compiled code somewhere.  There
-are currently two versions of this package available.  It can
-be obtained from@*
-@file{ftp://ftp.jaist.ac.jp/pub/GNU/elisp/}.
-Be sure to apply the supplied patch.  It works with Gnus through
-version 5.0.9.  In order for all dependencies to work correctly
-the load sequence is as follows:
-@lisp
-  (load "tm-setup")
-  (load "gnus")
-  (load "mime-compose")
-@end lisp
-
-@emph{NOTE:} Loading the package disables citation highlighting by
-default.  To get the old behavior back, use the @kbd{M-t} command.
+@example
+(add-to-list 'gnus-secondary-select-methods '(nnfolder ""))
+@end example
 
-@end itemize
+ Now we need to tell Gnus, where to get it's mail from. If
+ it's a POP3 server, then you need something like this:
 
-@end itemize
+@example
+(eval-after-load "mail-source"
+  '(add-to-list 'mail-sources '(pop :server "pop.YourProvider.net"
+                                    :user "yourUserName"
+                                    :password "yourPassword")))
+@end example
 
+@noindent
+ Make sure ~/.gnus isn't readable to others if you store
+ your password there. If you want to read your mail from a
+ traditional spool file on your local machine, it's
 
-@node Customization FAQ
-@subsection Customization
+@example
+(eval-after-load "mail-source"
+  '(add-to-list 'mail-sources '(file :path "/path/to/spool/file")))
+@end example
 
-@itemize @bullet
-@item
-Q2.1  Custom Edit does not work under XEmacs
+@noindent
+ If it's a Maildir, with one file per message as used by
+ postfix, Qmail and (optionally) fetchmail it's
 
-The custom package has not been ported to XEmacs.
+@example
+(eval-after-load "mail-source"
+  '(add-to-list 'mail-sources '(maildir :path "/path/to/Maildir/"
+                                        :subdirs ("cur" "new")))
+@end example
 
+@noindent
+ And finally if you want to read your mail from several files
+ in one directory, for example because procmail already split your
+ mail, it's
 
-@item
-Q2.2  How do I quote messages?
+@example
+(eval-after-load "mail-source"
+  '(add-to-list 'mail-sources '(directory :path "/path/to/procmail-dir/"
+                                          :suffix ".prcml"))
+@end example
 
-I see lots of messages with quoted material in them.  I am wondering
-how to have Gnus do it for me.
+@noindent
+ Where :suffix ".prcml" tells Gnus only to use files with the
+ suffix .prcml.
 
-This is Gnus, so there are a number of ways of doing this.  You can use
-the built-in commands to do this.  There are the @kbd{F} and @kbd{R}
-keys from the summary buffer which automatically include the article
-being responded to.  These commands are also selectable as @i{Followup
-and Yank} and @i{Reply and Yank} in the Post menu.
+ OK, now you only need to tell Gnus how to send mail. If you
+ want to send mail via sendmail (or whichever MTA is playing
+ the role of sendmail on your system), you don't need to do
+ anything. However, if you want to send your mail to an
+ SMTP Server you need the following in your ~/.gnus
 
-@kbd{C-c C-y} grabs the previous message and prefixes each line with
-@code{ail-indentation-spaces} spaces or @code{mail-yank-prefix} if that is
-non-nil, unless you have set your own @code{mail-citation-hook}, which will
-be called to do the job.
+@example
+(setq send-mail-function 'smtpmail-send-it)
+(setq message-send-mail-function 'smtpmail-send-it)
+(setq smtpmail-default-smtp-server "smtp.yourProvider.net")
+@end example
+@ifnottex
+@node [3.9], [3.10], [3.8], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.9: 
 
-You might also consider the Supercite package, which allows for pretty
-arbitrarily complex quoting styles.  Some people love it, some people
-hate it.
+ And what about IMAP?
 
+Answer: 
 
-@item
-Q2.3 How can I keep my nnvirtual:* groups sorted?
+ There are two ways of using IMAP with Gnus. The first one is
+ to use IMAP like POP3, that means Gnus fetches the mail from
+ the IMAP server and stores it on disk. If you want to do
+ this (you don't really want to do this) add the following to
+ ~/.gnus
 
-How can I most efficiently arrange matters so as to keep my nnvirtual:*
-(etc) groups at the top of my group selection buffer, whilst keeping
-everything sorted in alphabetical order.
-   
-If you don't subscribe often to new groups then the easiest way is to
-first sort the groups and then manually kill and yank the virtuals
-wherever you want them.
+@example
+(add-to-list 'mail-sources '(imap :server "mail.mycorp.com"
+                                  :user "username"
+                                  :pass "password"
+                                  :stream network
+                                  :authentication login
+                                  :mailbox "INBOX"
+                                  :fetchflag "\\Seen"))
+@end example
 
+@noindent
+ You might have to tweak the values for stream and/or
+ authentification, see the Gnus manual node "Mail Source
+ Specifiers" for possible values.
 
-@item
-Q2.4  Any good suggestions on stuff for an all.SCORE file?
+ If you want to use IMAP the way it's intended, you've got to
+ follow a different approach. You've got to add the nnimap
+ back end to your select method and give the information
+ about the server there.
 
-Here is a collection of suggestions from the Gnus mailing list.
+@example
+(add-to-list 
+ 'gnus-secondary-select-methods
+ '(nnimap "Give the baby a name"
+         (nnimap-address "imap.yourProvider.net")
+         (nnimap-port 143)
+         (nnimap-list-pattern "archive.*")))
+@end example
 
-@enumerate
-@item
-From ``Dave Disser'' <disser@@sdd.hp.com>@*
-I like blasting anything without lowercase letters.  Weeds out most of
-the make $$ fast, as well as the lame titles like ``IBM'' and ``HP-UX''
-with no further description.
-@lisp
- (("Subject"
-  ("^\\(Re: \\)?[^a-z]*$" -200 nil R)))
-@end lisp
+@noindent
+ Again, you might have to specify how to authenticate to the
+ server if Gnus can't guess the correct way, see the Manual
+ Node "IMAP" for detailed information.
+@ifnottex
+@node [3.10], [3.11], [3.9], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.10: 
+
+ At the office we use one of those MS Exchange servers, can I use
+ Gnus to read my mail from it?
+
+Answer: 
+
+ Offer your administrator a pair of new running shoes for
+ activating IMAP on the server and follow the instructions
+ above.
+@ifnottex
+@node [3.11],  , [3.10], FAQ 3 - Getting messages
+@end ifnottex
+@subsubheading Question 3.11: 
+
+ Can I tell Gnus not to delete the mails on the server it
+ retrieves via POP3?
+
+Answer: 
+
+ First of all, that's not the way POP3 is intended to work,
+ if you have the possibility, you should use the IMAP
+ Protocol if you want your messages to stay on the
+ server. Nevertheless there might be situations where you
+ need the feature, but sadly Gnus itself has no predefined
+ functionality to do so.
+
+ However this is Gnus county so there are possibilities to
+ achieve what you want. The easiest way is to get an external
+ program which retrieves copies of the mail and stores them
+ on disk, so Gnus can read it from there. On Unix systems you
+ could use e.g. fetchmail for this, on MS Windows you can use
+ Hamster, an excellent local news and mail server.
+
+ The other solution would be, to replace the method Gnus
+ uses to get mail from POP3 servers by one which is capable
+ of leaving the mail on the server. If you use XEmacs, get
+ the package mail-lib, it includes an enhanced pop3.el,
+ look in the file, there's documentation on how to tell
+ Gnus to use it and not to delete the retrieved mail. For
+ GNU Emacs look for the file epop3.el which can do the same
+ (If you know the home of this file, please send me an
+ e-mail). You can also tell Gnus to use an external program
+ (e.g. fetchmail) to fetch your mail, see the info node
+ "Mail Source Specifiers" in the Gnus manual on how to do
+ it.
+
+@ifnottex
+@node FAQ 4 - Reading messages, FAQ 5 - Composing messages, FAQ 3 - Getting messages, Frequently Asked Questions
+@end ifnottex
+@subsection Reading messages
 
-@item
-From ``Peter Arius'' <arius@@immd2.informatik.uni-erlangen.de>@*
-The most vital entries in my (still young) all.SCORE:
-@lisp
-(("xref"
-  ("alt.fan.oj-simpson" -1000 nil s))
- ("subject"
-  ("\\<\\(make\\|fast\\|big\\)\\s-*\\(money\\|cash\\|bucks?\\)\\>" -1000 nil r)
-  ("$$$$" -1000 nil s)))
-@end lisp
+@menu
+* [4.1]::   When I enter a group, all read messages are gone.
+            How to view them again? 
+* [4.2]::   How to tell Gnus to show an important message every time
+            I enter a group, even when it's read? 
+* [4.3]::   How to view the headers of a message? 
+* [4.4]::   How to view the raw unformatted message? 
+* [4.5]::   How can I change the headers Gnus displays by default at the
+            top of the article buffer? 
+* [4.6]::   I'd like Gnus NOT to render HTML-mails but show me the
+            text part if it's available. How to do it? 
+* [4.7]::   Can I use some other browser than w3 to render my HTML-mails? 
+* [4.8]::   Is there anything I can do to make poorly formatted mails
+            more readable? 
+* [4.9]::   Is there a way to automatically ignore posts by specific authors
+            or with specific words in the subject? And can I highlight more
+            interesting ones in some way? 
+* [4.10]::  How can I disable threading in some (e.g. mail-) groups, or set
+            other variables specific for some groups? 
+* [4.11]::  Can I highlight messages written by me and follow-ups to those? 
+* [4.12]::  The number of total messages in a group which Gnus displays in
+            group buffer is by far to high, especially in mail groups.
+            Is this a bug? 
+* [4.13]::  I don't like the layout of summary and article buffer,
+            how to change it?  Perhaps even a three pane display? 
+* [4.14]::  I don't like the way the Summary buffer looks, how to tweak it? 
+* [4.15]::  How to split incoming mails in several groups? 
+@end menu
 
-@item
-From ``Per Abrahamsen'' <abraham@@dina.kvl.dk>@*
-@lisp
-(("subject"
-  ;; CAPS OF THE WORLD, UNITE
-  ("^..[^a-z]+$" -1 nil R)
-  ;; $$$ Make Money $$$ (Try work)
-  ("$" -1 nil s)
-  ;; I'm important! And I have exclamation marks to prove it!
-  ("!" -1 nil s)))
-@end lisp
+@ifnottex
+@node [4.1], [4.2], FAQ 4 - Reading messages, FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.1: 
 
-@item
-From ``heddy boubaker'' <boubaker@@cenatls.cena.dgac.fr>@*
-I  would like to contribute with mine.
-@lisp
-(
- (read-only t)
- ("subject"
-  ;; ALL CAPS SUBJECTS
-  ("^\\([Rr][Ee]: +\\)?[^a-z]+$" -1 nil R)
-  ;; $$$ Make Money $$$
-  ("$$" -10 nil s)
-  ;; Empty subjects are worthless!
-  ("^ *\\([(<]none[>)]\\|(no subject\\( given\\)?)\\)? *$" -10 nil r)
-  ;; Sometimes interesting announces occur!
-  ("ANN?OU?NC\\(E\\|ING\\)" +10 nil r)
-  ;; Some people think they're on mailing lists
-  ("\\(un\\)?sub?scribe" -100 nil r)
-  ;; Stop Micro$oft NOW!!
-  ("\\(m\\(icro\\)?[s$]\\(oft\\|lot\\)?-?\\)?wind?\\(ows\\|aube\\|oze\\)?[- ]*\\('?95\\|NT\\|3[.]1\\|32\\)" -1001 nil r)
-  ;; I've nothing to buy
-  ("\\(for\\|4\\)[- ]*sale" -100 nil r)
-  ;; SELF-DISCIPLINED people
-  ("\\[[^a-z0-9 \t\n][^a-z0-9 \t\n]\\]" +100 nil r)
-  )
- ("from"
-  ;; To keep track of posters from my site
-  (".dgac.fr" +1000 nil s))
- ("followup"
-  ;; Keep track of answers to my posts
-  ("boubaker" +1000 nil s))
- ("lines"
-  ;; Some people have really nothing to say!!
-  (1 -10 nil <=))
- (mark -100)
- (expunge -1000)
- )
-@end lisp
+ When I enter a group, all read messages are gone. How to view them again?
 
-@item
-From ``Christopher Jones'' <cjones@@au.oracle.com>@*
-The sample @file{all.SCORE} files from Per and boubaker could be
-augmented with:
-@lisp
-       (("subject"
-         ;; No junk mail please!
-         ("please ignore" -500 nil s)
-         ("test" -500 nil e))
-       )
-@end lisp
+Answer: 
 
-@item
-From ``Brian Edmonds'' <edmonds@@cs.ubc.ca>@*
-Augment any of the above with a fast method of scoring down
-excessively cross posted articles.
-@lisp
- ("xref"
-  ;; the more cross posting, the exponentially worse the article
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+" -1 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -2 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -4 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -8 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -16 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -32 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -64 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -128 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -256 nil r)
-  ("^xref: \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+ \\S-+" -512 nil r))
-@end lisp
-
-@end enumerate
+ If you enter the group by saying 
+ @samp{RET}
+ in summary buffer with point over the group, only unread and ticked messages are loaded. Say
+ @samp{C-u RET}
+ instead to load all available messages. If you want only the e.g. 300 newest say
+ @samp{C-u 300 RET}
 
+ Loading only unread messages can be annoying if you have threaded view enabled, say
 
-@item
-Q2.5  What do I use to yank-through when replying?
+@example
+(setq gnus-fetch-old-headers 'some)
+@end example
+
+@noindent
+ in ~/.gnus to load enough old articles to prevent teared threads, replace 'some with t to load
+ all articles (Warning: Both settings enlarge the amount of data which is 
+ fetched when you enter a group and slow down the process of entering a group).
+
+ If you already use Gnus 5.10.0, you can say 
+ @samp{/o N} 
+ In summary buffer to load the last N messages, this feature is not available in 5.8.8
+
+ If you don't want all old messages, but the parent of the message you're just reading,
+ you can say @samp{^}, if you want to retrieve the whole thread
+ the message you're just reading belongs to, @samp{A T} is your friend.
+@ifnottex
+@node [4.2], [4.3], [4.1], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.2: 
+
+ How to tell Gnus to show an important message every time I
+ enter a group, even when it's read?
+
+Answer: 
+
+ You can tick important messages. To do this hit
+ @samp{u} while point is in summary buffer
+ over the message. When you want to remove the mark, hit
+ either @samp{d} (this deletes the tick
+ mark and set's unread mark) or @samp{M c}
+ (which deletes all marks for the message).
+@ifnottex
+@node [4.3], [4.4], [4.2], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.3: 
+
+ How to view the headers of a message?
+
+Answer: 
+
+ Say @samp{t} 
+ to show all headers, one more
+ @samp{t} 
+ hides them again.
+@ifnottex
+@node [4.4], [4.5], [4.3], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.4: 
+
+ How to view the raw unformatted message?
+
+Answer: 
+
+ Say 
+ @samp{C-u g} 
+ to show the raw message
+ @samp{g} 
+ returns to normal view.
+@ifnottex
+@node [4.5], [4.6], [4.4], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.5: 
+
+ How can I change the headers Gnus displays by default at
+ the top of the article buffer?
+
+Answer: 
+
+ The variable gnus-visible-headers controls which headers
+ are shown, its value is a regular expression, header lines
+ which match it are shown. So if you want author, subject,
+ date, and if the header exists, Followup-To and MUA / NUA
+ say this in ~/.gnus:
+@example
+(setq gnus-visible-headers 
+      "^\\(From:\\|Subject:\\|Date:\\|Followup-To:\
+\\|X-Newsreader:\\|User-Agent:\\|X-Mailer:\\)")
+@end example
+@ifnottex
+@node [4.6], [4.7], [4.5], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.6: 
+
+ I'd like Gnus NOT to render HTML-mails but show me the
+ text part if it's available. How to do it?
+
+Answer: 
 
-You should probably reply and followup with @kbd{R} and @kbd{F}, instead
-of @kbd{r} and @kbd{f}, which solves your problem.  But you could try
-something like:
+ Say
 
 @example
-(defconst mail-yank-ignored-headers
-  "^.*:"
-  "Delete these headers from old message when it's inserted in a reply.")
+(eval-after-load "mm-decode"
+ '(progn 
+      (add-to-list 'mm-discouraged-alternatives "text/html")
+      (add-to-list 'mm-discouraged-alternatives "text/richtext")))
 @end example
 
+@noindent
+ in ~/.gnus. If you don't want HTML rendered, even if there's no text alternative add
 
-@item
-Q2.6  I don't like the default WWW browser
+@example
+(setq mm-automatic-display (remove "text/html" mm-automatic-display))
+@end example
 
-Now when choosing an URL Gnus starts up a W3 buffer, I would like it
-to always use Netscape (I don't browse in text-mode ;-).
+@noindent
+ too.
+@ifnottex
+@node [4.7], [4.8], [4.6], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.7: 
 
-@enumerate
-@item
-Activate `Customize...' from the `Help' menu.
+ Can I use some other browser than w3 to render my HTML-mails?
 
-@item
-Scroll down to the `WWW Browser' field.
+Answer: 
 
-@item
-Click `mouse-2' on `WWW Browser'.
+ Only if you use Gnus 5.10.0 or younger. In this case you've got the
+ choice between w3, w3m, links, lynx and html2text, which
+ one is used can be specified in the variable
+ mm-text-html-renderer, so if you want links to render your
+ mail say
 
-@item
-Select `Netscape' from the pop up menu.
+@example
+(setq mm-text-html-renderer 'links)
+@end example
+@ifnottex
+@node [4.8], [4.9], [4.7], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.8: 
+
+ Is there anything I can do to make poorly formatted mails
+ more readable?
+
+Answer: 
+
+ Gnus offers you several functions to "wash" incoming mail,
+ you can find them if you browse through the menu, item Article->Washing. The most
+ interesting ones are probably "Wrap long lines" (
+ @samp{W w}
+ ), "Decode ROT13" (
+ @samp{W r}
+ ) and "Outlook Deuglify" which repairs the dumb quoting used
+ by many users of Microsoft products (
+ @samp{W Y f} gives you full deuglify.
+ See @samp{W Y C-h} or
+ have a look at the menus for other deuglifications).
+ Outlook deuglify is only available since Gnus 5.10.0.
+@ifnottex
+@node [4.9], [4.10], [4.8], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.9: 
+
+ Is there a way to automatically ignore posts by specific
+ authors or with specific words in the subject? And can I
+ highlight more interesting ones in some way?
+
+Answer: 
+
+ You want Scoring. Scoring means, that you define rules
+ which assign each message an integer value. Depending on
+ the value the message is highlighted in summary buffer (if
+ it's high, say +2000) or automatically marked read (if the
+ value is low, say -800) or some other action happens.
+
+ There are basically three ways of setting up rules which assign
+ the scoring-value to messages. The first and easiest way is to set
+ up rules based on the article you are just reading. Say you're
+ reading a message by a guy who always writes nonsense and you want
+ to ignore his messages in the future. Hit
+ @samp{L}, to set up a rule which lowers the score.
+ Now Gnus asks you which the criteria for lowering the Score shall
+ be. Hit @samp{?} twice to see all possibilities,
+ we want @samp{a} which means the author (the from
+ header). Now Gnus wants to know which kind of matching we want.
+ Hit either @samp{e} for an exact match or
+ @samp{s} for substring-match and delete afterwards
+ everything but the name to score down all authors with the given
+ name no matter which email address is used. Now you need to tell
+ Gnus when to apply the rule and how long it should last, hit e.g.
+ @samp{p} to apply the rule now and let it last
+ forever. If you want to raise the score instead of lowering it say
+ @samp{I} instead of @samp{L}.
+
+ You can also set up rules by hand. To do this say @samp{V
+ f} in summary buffer. Then you are asked for the name
+ of the score file, it's name.of.group.SCORE for rules valid in
+ only one group or all.Score for rules valid in all groups. See the
+ Gnus manual for the exact syntax, basically it's one big list
+ whose elements are lists again. the first element of those lists
+ is the header to score on, then one more list with what to match,
+ which score to assign, when to expire the rule and how to do the
+ matching. If you find me very interesting, you could e.g. add the
+ following to your all.Score:
 
-@item
-Press `C-c C-c'
+@example
+(("references" ("hschmi22.userfqdn.rz-online.de" 500 nil s))
+ ("message-id" ("hschmi22.userfqdn.rz-online.de" 999 nil s)))
+@end example
 
-@end enumerate
+@noindent
+ This would add 999 to the score of messages written by me
+ and 500 to the score of messages which are a (possibly
+ indirect) answer to a message written by me. Of course
+ nobody with a sane mind would do this :-)
+
+ The third alternative is adaptive scoring. This means Gnus
+ watches you and tries to find out what you find
+ interesting and what annoying and sets up rules
+ which reflect this. Adaptive scoring can be a huge help
+ when reading high traffic groups. If you want to activate
+ adaptive scoring say
 
-If you are using XEmacs then to specify Netscape do
-@lisp
-  (setq gnus-button-url 'gnus-netscape-open-url)
-@end lisp
+@example
+(setq gnus-use-adaptive-scoring t)
+@end example
 
+@noindent
+ in ~/.gnus.
+@ifnottex
+@node [4.10], [4.11], [4.9], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.10: 
+
+ How can I disable threading in some (e.g. mail-) groups, or
+ set other variables specific for some groups?
+
+Answer: 
+
+ While in group buffer move point over the group and hit
+ @samp{G c}, this opens a buffer where you
+ can set options for the group. At the bottom of the buffer
+ you'll find an item that allows you to set variables
+ locally for the group. To disable threading enter
+ gnus-show-threads as name of variable and nil as
+ value. Hit button done at the top of the buffer when
+ you're ready.
+@ifnottex
+@node [4.11], [4.12], [4.10], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.11: 
+
+ Can I highlight messages written by me and follow-ups to
+ those?
+
+Answer: 
+
+ Stop those "Can I ..." questions, the answer is always yes
+ in Gnus Country :-). It's a three step process: First we
+ make faces (specifications of how summary-line shall look
+ like) for those postings, then we'll give them some
+ special score and finally we'll tell Gnus to use the new
+ faces. You can find detailed instructions on how to do it on
+ @uref{http://my.gnus.org/Members/dzimmerm/HowTo%2C2002-07-25%2C1027619165012198456/view,my.gnus.org}
+@ifnottex
+@node [4.12], [4.13], [4.11], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.12: 
+
+ The number of total messages in a group which Gnus
+ displays in group buffer is by far to high, especially in
+ mail groups. Is this a bug?
+
+Answer: 
+
+ No, that's a matter of design of Gnus, fixing this would
+ mean reimplementation of major parts of Gnus'
+ back ends. Gnus thinks "highest-article-number -
+ lowest-article-number = total-number-of-articles". This
+ works OK for Usenet groups, but if you delete and move
+ many messages in mail groups, this fails. To cure the
+ symptom, enter the group via @samp{C-u RET} 
+ (this makes Gnus get all messages), then
+ hit @samp{M P b} to mark all messages and
+ then say @samp{B m name.of.group} to move
+ all messages to the group they have been in before, they
+ get new message numbers in this process and the count is
+ right again (until you delete and move your mail to other
+ groups again).
+@ifnottex
+@node [4.13], [4.14], [4.12], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.13: 
+
+ I don't like the layout of summary and article buffer, how
+ to change it? Perhaps even a three pane display?
+
+Answer: 
+
+ You can control the windows configuration by calling the
+ function gnus-add-configuration. The syntax is a bit
+ complicated but explained very well in the manual node
+ "Window Layout". Some popular examples:
+
+ Instead 25% summary 75% article buffer 35% summary and 65%
+ article (the 1.0 for article means "take the remaining
+ space"):
 
-@item
-Q2.7 What, if any, relation is between ``ask-server'' and ``(setq
-gnus-read-active-file 'some)''?
+@example
+(gnus-add-configuration 
+ '(article (vertical 1.0
+                    (summary .35 point)
+                    (article 1.0))))
+@end example
+
+ A three pane layout, Group buffer on the left, summary
+ buffer top-right, article buffer bottom-right:
+
+@example
+(gnus-add-configuration
+ '(article
+   (horizontal 1.0
+              (vertical 25
+                        (group 1.0))
+              (vertical 1.0
+                        (summary 0.25 point)
+                        (article 1.0)))))
+(gnus-add-configuration
+ '(summary
+   (horizontal 1.0
+              (vertical 25
+                        (group 1.0))
+              (vertical 1.0
+                        (summary 1.0 point)))))              
+@end example
+@ifnottex
+@node [4.14], [4.15], [4.13], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.14: 
+
+ I don't like the way the Summary buffer looks, how to tweak it?
+
+Answer: 
+
+ You've got to play around with the variable
+ gnus-summary-line-format. It's value is a string of
+ symbols which stand for things like author, date, subject
+ etc. A list of the available specifiers can be found in the
+ manual node "Summary Buffer Lines" and the often forgotten
+ node "Formatting Variables" and it's sub-nodes. There
+ you'll find useful things like positioning the cursor and
+ tabulators which allow you a summary in table form, but
+ sadly hard tabulators are broken in 5.8.8.
+
+ Since 5.10.0, Gnus offers you some very nice new specifiers,
+ e.g. %B which draws a thread-tree and %&user-date which
+ gives you a date where the details are dependent of the
+ articles age. Here's an example which uses both:
 
-In order for Gnus to show you the complete list of newsgroups, it will
-either have to either store the list locally, or ask the server to
-transmit the list. You enable the first with
+@example
+(setq gnus-summary-line-format 
+      ":%U%R %B %s %-60=|%4L |%-20,20f |%&user-date; \n")
+@end example
 
-@lisp
-        (setq gnus-save-killed-list t)
-@end lisp
+@noindent
+ resulting in:
+
+@smallexample
+:O     Re: [Richard Stallman] rfc2047.el          |  13 |Lars Magne Ingebrigt |Sat 23:06
+:O     Re: Revival of the ding-patches list       |  13 |Lars Magne Ingebrigt |Sat 23:12
+:R  >  Re: Find correct list of articles for a gro|  25 |Lars Magne Ingebrigt |Sat 23:16
+:O  \->  ...                                      |  21 |Kai Grossjohann      | 0:01
+:R  >  Re: Cry for help: deuglify.el - moving stuf|  28 |Lars Magne Ingebrigt |Sat 23:34
+:O  \->  ...                                      | 115 |Raymond Scholz       | 1:24
+:O    \->  ...                                    |  19 |Lars Magne Ingebrigt |15:33
+:O     Slow mailing list                          |  13 |Lars Magne Ingebrigt |Sat 23:49
+:O     Re: `@@' mark not documented                |  13 |Lars Magne Ingebrigt |Sat 23:50
+:R  >  Re: Gnus still doesn't count messages prope|  23 |Lars Magne Ingebrigt |Sat 23:57
+:O  \->  ...                                      |  18 |Kai Grossjohann      | 0:35
+:O    \->  ...                                    |  13 |Lars Magne Ingebrigt | 0:56
+@end smallexample
+@ifnottex
+@node [4.15],  , [4.14], FAQ 4 - Reading messages
+@end ifnottex
+@subsubheading Question 4.15: 
+
+ How to split incoming mails in several groups?
+
+Answer: 
+
+ Gnus offers two possibilities for splitting mail, the easy
+ nnmail-split-methods and the more powerful Fancy Mail
+ Splitting. I'll only talk about the first one, refer to
+ the manual, node "Fancy Mail Splitting" for the latter.
+
+ The value of nnmail-split-methods is a list, each element
+ is a list which stands for a splitting rule. Each rule has
+ the form "group where matching articles should go to",
+ "regular expression which has to be matched", the first
+ rule which matches wins. The last rule must always be a
+ general rule (regular expression .*) which denotes where
+ articles should go which don't match any other rule. If
+ the folder doesn't exist yet, it will be created as soon
+ as an article lands there. By default the mail will be
+ send to all groups whose rules match. If you 
+ don't want that (you probably don't want), say
 
-and the second with
+@example
+(setq nnmail-crosspost nil)
+@end example
 
-@lisp
-        (setq gnus-read-active-file t)
-@end lisp
+@noindent
+ in ~/.gnus.
 
-If both are disabled, Gnus will not know what newsgroups exists. There
-is no option to get the list by casting a spell.
+ An example might be better than thousand words, so here's
+ my nnmail-split-methods. Note that I send duplicates in a
+ special group and that the default group is spam, since I
+ filter all mails out which are from some list I'm
+ subscribed to or which are addressed directly to me
+ before. Those rules kill about 80% of the Spam which
+ reaches me (Email addresses are changed to prevent spammers
+ from using them):
 
+@example
+(setq nnmail-split-methods
+  '(("duplicates" "^Gnus-Warning:.*duplicate")
+    ("XEmacs-NT" "^\\(To:\\|CC:\\).*localpart@@xemacs.bla.*")
+    ("Gnus-Tut" "^\\(To:\\|CC:\\).*localpart@@socha.bla.*")
+    ("tcsh" "^\\(To:\\|CC:\\).*localpart@@mx.gw.bla.*")
+    ("BAfH" "^\\(To:\\|CC:\\).*localpart@@.*uni-muenchen.bla.*")
+    ("Hamster-src"
+     "^\\(CC:\\|To:\\).*hamster-sourcen@@yahoogroups.\\(de\\|com\\).*")
+    ("Tagesschau" "^From: tagesschau <localpart@@www.tagesschau.bla>$")
+    ("Replies" "^\\(CC:\\|To:\\).*localpart@@Frank-Schmitt.bla.*")
+    ("EK"
+     "^From:.*\\(localpart@@privateprovider.bla\\|localpart@@workplace.bla\\).*")
+    ("Spam"
+     "^Content-Type:.*\\(ks_c_5601-1987\\|EUC-KR\\|big5\\|iso-2022-jp\\).*")
+    ("Spam"
+     "^Subject:.*\\(This really work\\|XINGA\\|ADV:\\|XXX\\|adult\\|sex\\).*")
+    ("Spam"
+     "^Subject:.*\\(\=\?ks_c_5601-1987\?\\|\=\?euc-kr\?\\|\=\?big5\?\\).*")
+    ("Spam" "^X-Mailer:\\(.*BulkMailer.*\\|.*MIME::Lite.*\\|\\)")
+    ("Spam"
+     "^X-Mailer:\\(.*CyberCreek Avalanche\\|.*http\:\/\/GetResponse\.com\\)")
+    ("Spam"
+     "^From:.*\\(verizon\.net\\|prontomail\.com\\|money\\|ConsumerDirect\\).*")
+    ("Spam" "^Delivered-To: GMX delivery to spamtrap@@gmx.bla$")
+    ("Spam" "^Received: from link2buy.com")
+    ("Spam" "^CC: .*azzrael@@t-online.bla")
+    ("Spam" "^X-Mailer-Version: 1.50 BETA")
+    ("Uni" "^\\(CC:\\|To:\\).*localpart@@uni-koblenz.bla.*")
+    ("Inbox"
+     "^\\(CC:\\|To:\\).*\\(my\ name\\|address@@one.bla\\|adress@@two.bla\\)")
+    ("Spam" "")))
+@end example
 
-@item
-Q2.8  Moving between groups is slow.
+@ifnottex
+@node FAQ 5 - Composing messages, FAQ 6 - Old messages, FAQ 4 - Reading messages, Frequently Asked Questions
+@end ifnottex
+@subsection Composing messages
 
-Per Abrahamsen <abraham@@dina.kvl.dk> writes:@*
+@menu
+* [5.1]::   What are the basic commands I need to know for sending mail and
+            postings? 
+* [5.2]::   How to enable automatic word-wrap when composing messages? 
+* [5.3]::   How to set stuff like From, Organization, Reply-To, signature...? 
+* [5.4]::   Can I set things like From, Signature etc group based on the
+            group I post too? 
+* [5.5]::   Is there a spell-checker? Perhaps even on-the-fly spell-checking? 
+* [5.6]::   Can I set the dictionary based on the group I'm posting to? 
+* [5.7]::   Is there some kind of address-book, so I needn't remember all
+            those email addresses? 
+* [5.8]::   Sometimes I see little images at the top of article buffer.
+            What's that and how can I send one with my postings, too? 
+* [5.9]::   Sometimes I accidentally hit r instead of f in newsgroups.
+            Can Gnus warn me, when I'm replying by mail in newsgroups? 
+* [5.10]::  How to tell Gnus not to generate a sender header? 
+* [5.11]::  I want Gnus to locally store copies of my send mail and news,
+            how to do it? 
+* [5.12]::  People tell me my Message-IDs are not correct,
+            why aren't they and how to fix it? 
+@end menu
+
+@ifnottex
+@node [5.1], [5.2], FAQ 5 - Composing messages, FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.1: 
+
+ What are the basic commands I need to know for sending mail and postings?
+
+Answer: 
+
+ To start composing a new mail hit @samp{m}
+ either in Group or Summary buffer, for a posting, it's
+ either @samp{a} in Group buffer and
+ filling the Newsgroups header manually
+ or @samp{a} in the Summary buffer of the
+ group where the posting shall be send to. Replying by mail
+ is
+ @samp{r} if you don't want to cite the
+ author, or import the cited text manually and
+ @samp{R} to cite the text of the original
+ message. For a follow up to a newsgroup, it's
+ @samp{f} and @samp{F}
+ (analog to @samp{r} and
+ @samp{R}.
+
+ Enter new headers above the line saying "--text follows
+ this line--", enter the text below the line. When ready
+ hit @samp{C-c C-c}, to send the message,
+ if you want to finish it later hit @samp{C-c
+ C-d} to save it in the drafts group, where you
+ can start editing it again by saying @samp{D
+ e}.
+@ifnottex
+@node [5.2], [5.3], [5.1], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.2: 
+
+ How to enable automatic word-wrap when composing messages?
+
+Answer: 
+
+ Say
+
+@example
+(add-hook 'message-mode-hook
+      (lambda ()
+           (setq fill-column 72)
+           (turn-on-auto-fill)))
+@end example
 
-Do you call @code{define-key} or something like that in one of the
-summary mode hooks?  This would force Emacs to recalculate the keyboard
-shortcuts.  Removing the call should speed up @kbd{M-x gnus-summary-mode
-RET} by a couple of orders of magnitude.  You can use
+@noindent
+ in ~/.gnus. You can reformat a paragraph by hitting
+ @samp{M-q} (as usual)
+@ifnottex
+@node [5.3], [5.4], [5.2], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.3: 
 
-@lisp
-(define-key gnus-summary-mode-map KEY COMMAND)
-@end lisp
+ How to set stuff like From, Organization, Reply-To, signature...?
 
-in your @file{.gnus} instead.
+Answer: 
 
-@end itemize
+ There are other ways, but you should use posting styles
+ for this. (See below why).
+ This example should make the syntax clear:
+
+@example
+(setq gnus-posting-styles
+  '((".*"
+     (name "Frank Schmitt")
+     (address "me@@there.bla")
+     (organization "Hamme net, kren mer och nimmi")
+     (signature-file "~/.signature")
+     ("X-SampleHeader" "foobar")
+     (eval (setq some-variable "Foo bar")))))
+@end example
+
+@noindent
+ The ".*" means that this settings are the default ones
+ (see below), valid values for the first element of the
+ following lists are signature, signature-file,
+ organization, address, name or body. The attribute name
+ can also be a string. In that case, this will be used as
+ a header name, and the value will be inserted in the
+ headers of the article; if the value is `nil', the header
+ name will be removed. You can also say (eval (foo bar)),
+ then the function foo will be evaluated with argument bar
+ and the result will be thrown away.
+@ifnottex
+@node [5.4], [5.5], [5.3], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.4: 
+
+ Can I set things like From, Signature etc group based on the group I post too?
+
+Answer: 
+
+ That's the strength of posting styles. Before, we used ".*"
+ to set the default for all groups. You can use a regexp
+ like "^gmane" and the following settings are only applied
+ to postings you send to the gmane hierarchy, use
+ ".*binaries" instead and they will be applied to postings
+ send to groups containing the string binaries in their
+ name etc.
+
+ You can instead of specifying a regexp specify a function
+ which is evaluated, only if it returns true, the
+ corresponding settings take effect. Two interesting
+ candidates for this are message-news-p which returns t if
+ the current Group is a newsgroup and the corresponding
+ message-mail-p.
+
+ Note that all forms that match are applied, that means in
+ the example below, when I post to
+ gmane.mail.spam.spamassassin.general, the settings under
+ ".*" are applied and the settings under message-news-p and
+ those under "^gmane" and those under
+ "^gmane\\.mail\\.spam\\.spamassassin\\.general$". Because
+ of this put general settings at the top and specific ones
+ at the bottom.
+
+@example
+(setq gnus-posting-styles
+  '((".*"  ;;default
+     (name "Frank Schmitt")
+     (organization "Hamme net, kren mer och nimmi")
+     (signature-file "~/.signature"))
+    ((message-news-p)  ;;Usenet news?
+     (address "mySpamTrap@@Frank-Schmitt.bla")
+     ("Reply-To" "hereRealRepliesOnlyPlease@@Frank-Schmitt.bla"))
+    ((message-mail-p)  ;;mail?
+     (address "usedForMails@@Frank-Schmitt.bla"))
+    ("^gmane" ;;this is mail, too in fact
+     (address "usedForMails@@Frank-Schmitt.net")
+     ("Reply-To" nil))
+    ("^gmane.mail.spam.spamassassin.general$"
+     (eval (setq mail-envelope-from "Azzrael@@rz-online.de"))
+     (address "Azzrael@@rz-online.de"))))
+@end example
+@ifnottex
+@node [5.5], [5.6], [5.4], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.5: 
 
+ Is there a spell-checker? Perhaps even on-the-fly spell-checking?
 
-@node Reading News FAQ
-@subsection Reading News
+Answer: 
 
+You can use ispell.el to spell-check stuff in Emacs. So the first
+thing to do is to make sure that you've got either
 @itemize @bullet
 @item
-Q3.1  How do I convert my kill files to score files?
+@uref{http://fmg-www.cs.ucla.edu/fmg-members/geoff/ispell.html,ispell}
+or 
+@item
+@uref{http://aspell.sourceforge.net/,aspell} 
+@end itemize
+@noindent
+installed and in your Path.
+
+Then you need
+@uref{http://www.kdstevens.com/~stevens/ispell-page.html,ispell.el,ispell.el}
+and for on-the-fly spell-checking
+@uref{http://www-sop.inria.fr/mimosa/personnel/Manuel.Serrano/flyspell/flyspell.html,flyspell.el,flyspell.el}.
+Ispell.el is shipped with Gnus Emacs and available through the Emacs
+package system, flyspell.el is shipped with Emacs and part of XEmacs
+text-modes package which is available through the package system, so
+there should be no need to install them manually.
+
+ Ispell.el assumes you use ispell, if you choose aspell say
 
-A kill-to-score translator was written by Ethan Bradford
-<ethanb@@ptolemy.astro.washington.edu>.  It is available from@*
-@file{http://baugi.ifi.uio.no/~larsi/ding-various/gnus-kill-to-score.el}.
+@example
+(setq ispell-program-name "aspell")
+@end example
 
+@noindent
+ in your Emacs configuration file.
 
-@item
-Q3.2 My news server has a lot of groups, and killing groups is painfully
-slow.
+ If you want your outgoing messages to be spell-checked, say
 
-Don't do that then.  The best way to get rid of groups that should be
-dead is to edit your newsrc directly.  This problem will be addressed
-in the near future.
+@example
+(add-hook 'message-send-hook 'ispell-message)
+@end example
 
+@noindent
+ In your ~/.gnus, if you prefer on-the-fly spell-checking say
 
-@item
-Q3.3  How do I use an NNTP server with authentication?
+@example
+(add-hook 'message-mode-hook (lambda () (flyspell-mode 1)))
+@end example
+@ifnottex
+@node [5.6], [5.7], [5.5], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.6: 
 
-Put the following into your .gnus:
-@lisp
- (add-hook 'nntp-server-opened-hook 'nntp-send-authinfo)
-@end lisp
+ Can I set the dictionary based on the group I'm posting to?
 
+Answer: 
 
-@item
-Q3.4  Not reading the first article.
+ Yes, say something like
 
-How do I avoid reading the first article when a group is selected?
+@example
+(add-hook 'gnus-select-group-hook
+          (lambda ()
+            (cond
+             ((string-match
+               "^de\\." (gnus-group-real-name gnus-newsgroup-name))
+              (ispell-change-dictionary "deutsch8"))
+             (t
+              (ispell-change-dictionary "english")))))
+@end example
 
-@enumerate
-@item
-Use @kbd{RET} to select the group instead of @kbd{SPC}.
+@noindent
+ in ~/.gnus. Change "^de\\." and "deutsch8" to something
+ that suits your needs.
+@ifnottex
+@node [5.7], [5.8], [5.6], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.7:
 
-@item
-@code{(setq gnus-auto-select first nil)}
+ Is there some kind of address-book, so I needn't remember
+ all those email addresses?
 
-@item
-Luis Fernandes <elf@@mailhost.ee.ryerson.ca>writes:@*
-This is what I use...customize as necessary...
+Answer: 
 
-@lisp
-;;; Don't auto-select first article if reading sources, or archives or
-;;; jobs postings, etc. and just display the summary buffer
-(add-hook 'gnus-select-group-hook
-         (function
-          (lambda ()
-            (cond ((string-match "sources" gnus-newsgroup-name)
-                   (setq gnus-auto-select-first nil))
-                          ((string-match "jobs" gnus-newsgroup-name)
-                               (setq gnus-auto-select-first nil))
-                  ((string-match "comp\\.archives" gnus-newsgroup-name)
-                   (setq gnus-auto-select-first nil))
-                  ((string-match "reviews" gnus-newsgroup-name)
-                   (setq gnus-auto-select-first nil))
-                  ((string-match "announce" gnus-newsgroup-name)
-                   (setq gnus-auto-select-first nil))
-                  ((string-match "binaries" gnus-newsgroup-name)
-                   (setq gnus-auto-select-first nil))
-                  (t
-                   (setq gnus-auto-select-first t))))))
-@end lisp
+ There's an very basic solution for this, mail aliases.
+ You can store your mail addresses in a ~/.mailrc file using a simple
+ alias syntax:
 
-@item
-Per Abrahamsen <abraham@@dina.kvl.dk> writes:@*
-Another possibility is to create an @file{all.binaries.all.SCORE} file
-like this:
+@example
+alias al       "Al <al@@english-heritage.bla>"
+@end example
 
-@lisp
-((local
-  (gnus-auto-select-first nil)))
-@end lisp
+@noindent
+ Then typing your alias (followed by a space or punctuation
+ character) on a To: or Cc: line in the message buffer will
+ cause Gnus to insert the full address for you. See the
+ node "Mail Aliases" in Message (not Gnus) manual for
+ details.
 
-and insert 
-@lisp
-       (setq gnus-auto-select-first t)
-@end lisp
+ However, what you really want is the Insidious Big Brother 
+ Database bbdb. Get it through the XEmacs package system or from
+ @uref{http://bbdb.sourceforge.net/,bbdb's homepage}.
+ Now place the following in ~/.gnus, to activate bbdb for Gnus:
 
-in your @file{.gnus}.
+@example
+(require 'bbdb)
+(bbdb-initialize 'gnus 'message)
+@end example
 
-@end enumerate
+@noindent
+ Now you probably want some general bbdb configuration,
+ place them in ~/.emacs:
 
-@item
-Q3.5  Why aren't BBDB known posters marked in the summary buffer?
+@example
+(require 'bbdb)
+;;If you don't live in Northern America, you should disable the 
+;;syntax check for telephone numbers by saying
+(setq bbdb-north-american-phone-numbers-p nil)
+;;Tell bbdb about your email address:
+(setq bbdb-user-mail-names
+      (regexp-opt '("Your.Email@@here.bla"
+                    "Your.other@@mail.there.bla")))
+;;cycling while completing email addresses
+(setq bbdb-complete-name-allow-cycling t)
+;;No popup-buffers
+(setq bbdb-use-pop-up nil)
+@end example
 
-Brian Edmonds <edmonds@@cs.ubc.ca> writes:@*
-Due to changes in Gnus 5.0, @file{bbdb-gnus.el} no longer marks known
-posters in the summary buffer.  An updated version, @file{gnus-bbdb.el}
-is available at the locations listed below.  This package also supports
-autofiling of incoming mail to folders specified in the BBDB.  Extensive
-instructions are included as comments in the file.
+@noindent
+ Now you should be ready to go. Say @samp{M-x bbdb RET
+ RET} to open a bbdb buffer showing all
+ entries. Say @samp{c} to create a new
+ entry, @samp{b} to search your BBDB and
+ @samp{C-o} to add a new field to an
+ entry. If you want to add a sender to the BBDB you can
+ also just hit `:' on the posting in the summary buffer and
+ you are done. When you now compose a new mail,
+ hit @samp{TAB} to cycle through know
+ recipients.
+@ifnottex
+@node [5.8], [5.9], [5.7], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.8: 
+
+ Sometimes I see little images at the top of article
+ buffer. What's that and how can I send one with my
+ postings, too?
+
+Answer: 
+
+ Those images are called X-Faces. They are 48*48 pixel b/w
+ pictures, encoded in a header line. If you want to include
+ one in your posts, you've got to convert some image to a
+ X-Face. So fire up some image manipulation program (say
+ Gimp), open the image you want to include, cut out the
+ relevant part, reduce color depth to 1 bit, resize to
+ 48*48 and save as bitmap. Now you should get the compface
+ package from 
+ @uref{ftp://ftp.cs.indiana.edu:/pub/faces/,this site}.
+ and create the actual X-face by saying
 
-Send mail to @file{majordomo@@edmonds.home.cs.ubc.ca} with the following
-line in the body of the message: @emph{get misc gnus-bbdb.el}.
+@example
+cat file.xbm | xbm2ikon |compface > file.face
+cat ./file.face | sed 's/\\/\\\\/g' | sed 's/\"/\\\"/g' > ./file.face.quoted
+@end example
 
-Or get it from the World Wide Web:@*
-@file{http://www.cs.ubc.ca/spider/edmonds/gnus-bbdb.el}.
+@noindent
+If you can't use compface, there's an online X-face converter at@*
+@uref{http://www.dairiki.org/xface/}.  If you use MS Windows, you
+could also use the WinFace program from
+@uref{http://www.xs4all.nl/~walterln/winface/}.
 
-@end itemize
+Now you only have to tell Gnus to include the X-face in your postings
+by saying
 
+@example
+(setq message-default-headers
+        (with-temp-buffer
+          (insert "X-Face: ")
+          (insert-file-contents "~/.xemacs/xface")
+          (buffer-string)))
+@end example
 
-@node Reading Mail FAQ
-@subsection Reading Mail
+@noindent
+ in ~/.gnus.
+@ifnottex
+@node [5.9], [5.10], [5.8], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.9: 
 
-@itemize @bullet
-@item
-Q4.1 What does the message ``Buffer has changed on disk'' mean in a mail
-group?
+ Sometimes I accidentally hit r instead of f in
+ newsgroups. Can Gnus warn me, when I'm replying by mail in
+ newsgroups?
 
-Your filter program should not deliver mail directly to your folders,
-instead it should put the mail into spool files.  Gnus will then move
-the mail safely from the spool files into the folders.  This will
-eliminate the problem.  Look it up in the manual, in the section
-entitled ``Mail & Procmail''.
+Answer: 
 
+ Put this in ~/.gnus:
 
-@item
-Q4.2  How do you make articles un-expirable?
+@example
+(setq gnus-confirm-mail-reply-to-news t)
+@end example
 
-I am using nnml to read news and have used
-@code{gnus-auto-expirable-newsgroups} to automagically expire articles
-in some groups (Gnus being one of them).  Sometimes there are
-interesting articles in these groups that I want to keep.  Is there any
-way of explicitly marking an article as un-expirable - that is mark it
-as read but not expirable?
+@noindent
+ if you already use Gnus 5.10.0, if you still use 5.8.8 or
+ 5.9 try this instead:
+
+@example
+(defadvice gnus-summary-reply (around reply-in-news activate)
+       (interactive)
+        (when (or (not (gnus-news-group-p gnus-newsgroup-name))
+                  (y-or-n-p "Really reply? "))
+         ad-do-it))
+@end example
+@ifnottex
+@node [5.10], [5.11], [5.9], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.10: 
 
-Use @kbd{u}, @kbd{!}, @kbd{d} or @kbd{M-u} in the summary buffer. You
-just remove the @kbd{E} mark by setting some other mark. It's not
-necessary to tick the articles.
+ How to tell Gnus not to generate a sender header?
 
+Answer: 
 
-@item
-Q4.3  How do I delete bogus nnml: groups?
+ Since 5.10.0 Gnus doesn't generate a sender header by
+ default. For older Gnus' try this in ~/.gnus:
 
-My problem is that I have various mail (nnml) groups generated while
-experimenting with Gnus. How do I remove them now? Setting the level to
-9 does not help. Also @code{gnus-group-check-bogus-groups} does not
-recognize them.
+@example
+(eval-after-load "message"
+      '(add-to-list 'message-syntax-checks '(sender . disabled)))
+@end example
+@ifnottex
+@node [5.11], [5.12], [5.10], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.11: 
+
+ I want gnus to locally store copies of my send mail and
+ news, how to do it?
+
+Answer: 
+
+ You must set the variable gnus-message-archive-group to do
+ this. You can set it to a string giving the name of the
+ group where the copies shall go or like in the example
+ below use a function which is evaluated and which returns
+ the group to use.
 
-Removing mail groups is tricky at the moment. (It's on the to-do list,
-though.) You basically have to kill the groups in Gnus, shut down Gnus,
-edit the active file to exclude these groups, and probably remove the
-nnml directories that contained these groups as well. Then start Gnus
-back up again.
+@example
+(setq gnus-message-archive-group
+       '((if (message-news-p)
+             "nnml:Send-News"
+           "nnml:Send-Mail")))
+@end example
+@ifnottex
+@node [5.12],  , [5.11], FAQ 5 - Composing messages
+@end ifnottex
+@subsubheading Question 5.12: 
+
+ People tell me my Message-IDs are not correct, why
+ aren't they and how to fix it?
+
+Answer: 
+
+ The message-ID is an unique identifier for messages you
+ send. To make it unique, Gnus need to know which machine
+ name to put after the "@@". If the name of the machine
+ where Gnus is running isn't suitable (it probably isn't
+ at most private machines) you can tell Gnus what to use
+ by saying
+@example
+(setq message-user-fqdn "yourmachine.yourdomain.tld")
+@end example
+@noindent
+ in ~/.gnus.  If you use Gnus 5.9 or ealier, you can use this
+instead:
+@example
+(eval-after-load "message"
+  '(let (myfqdn "yourmachine.yourdomain.tld");; <-- Edit this!
+     (if (boundp 'message-user-fqdn)
+         (setq message-user-fqdn fqdn)
+       (gnus-message 1 "Redefining `message-make-fqdn'.")
+       (defun message-make-fqdn ()
+         "Return user's fully qualified domain name."
+         fqdn))))
+@end example
 
+ If you have no idea what to insert for
+ "yourmachine.yourdomain.tld", you've got several
+ choices. You can either ask your provider if he allows
+ you to use something like
+ yourUserName.userfqdn.provider.net, or you can use
+ somethingUnique.yourdomain.tld if you own the domain
+ yourdomain.tld, or you can register at a service which
+ gives private users a FQDN for free, e.g. 
+ @uref{http://www.stura.tu-freiberg.de/~dlx/addfqdn.html}.
+ (Sorry but this website is in German, if you know of an
+ English one offering the same, drop me a note).
+
+ Finally you can tell Gnus not to generate a Message-ID
+ for News at all (and letting the server do the job) by saying
 
-@item
-Q4.4  What happened to my new mail groups?
+@example
+(setq message-required-news-headers
+  (remove' Message-ID message-required-news-headers))
+@end example
 
-I got new mail, but I have
-never seen the groups they should have been placed in.
+@noindent
+ you can also tell Gnus not to generate Message-IDs for mail by saying
 
-They are probably there, but as zombies. Press @kbd{A z} to list
-zombie groups, and then subscribe to the groups you want with @kbd{u}.
-This is all documented quite nicely in the user's manual.
+@example
+(setq message-required-mail-headers
+  (remove' Message-ID message-required-mail-headers))
+@end example
 
+@noindent
+ , however some mail servers don't generate proper
+ Message-IDs, too, so test if your Mail Server behaves
+ correctly by sending yourself a Mail and looking at the Message-ID.
 
-@item
-Q4.5  Not scoring mail groups
+@ifnottex
+@node FAQ 6 - Old messages, FAQ 7 - Gnus in a dial-up environment, FAQ 5 - Composing messages, Frequently Asked Questions
+@end ifnottex
+@subsection Old messages
+
+@menu
+* [6.1]::   How to import my old mail into Gnus? 
+* [6.2]::   How to archive interesting messages? 
+* [6.3]::   How to search for a specific message? 
+* [6.4]::   How to get rid of old unwanted mail? 
+* [6.5]::   I want that all read messages are expired (at least in some
+            groups). How to do it? 
+* [6.6]::   I don't want expiration to delete my mails but to move them
+            to another group. 
+@end menu
+
+@ifnottex
+@node [6.1], [6.2], FAQ 6 - Old messages, FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.1: 
+
+ How to import my old mail into Gnus?
+
+Answer: 
+
+ The easiest way is to tell your old mail program to
+ export the messages in mbox format. Most Unix mailers
+ are able to do this, if you come from the MS Windows
+ world, you may find tools at
+ @uref{http://mbx2mbox.sourceforge.net/}.
+
+ Now you've got to import this mbox file into Gnus. To do
+ this, create a nndoc group based on the mbox file by
+ saying @samp{G f /path/file.mbox RET} in
+ Group buffer. You now have read-only access to your
+ mail. If you want to import the messages to your normal
+ Gnus mail groups hierarchy, enter the nndoc group you've
+ just created by saying @samp{C-u RET}
+ (thus making sure all messages are retrieved), mark all
+ messages by saying @samp{M P b} and
+ either copy them to the desired group by saying
+ @samp{B c name.of.group RET} or send them
+ through nnmail-split-methods (respool them) by saying
+ @samp{B r}.
+@ifnottex
+@node [6.2], [6.3], [6.1], FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.2: 
+
+ How to archive interesting messages?
+
+Answer: 
+
+ If you stumble across an interesting message, say in
+ gnu.emacs.gnus and want to archive it there are several
+ solutions. The first and easiest is to save it to a file
+ by saying @samp{O f}. However, wouldn't
+ it be much more convenient to have more direct access to
+ the archived message from Gnus? If you say yes, put this
+ snippet by Frank Haun <pille3003@@fhaun.de> in
+ ~/.gnus:
 
-How do you @emph{totally} turn off scoring in mail groups?
+@example
+(defun my-archive-article (&optional n)
+  "Copies one or more article(s) to a corresponding `nnml:' group, e.g.
+`gnus.ding' goes to `nnml:1.gnus.ding'. And `nnml:List-gnus.ding' goes
+to `nnml:1.List-gnus-ding'.
+
+Use process marks or mark a region in the summary buffer to archive
+more then one article."
+  (interactive "P")
+  (let ((archive-name
+         (format
+          "nnml:1.%s"
+          (if (featurep 'xemacs)
+              (replace-in-string gnus-newsgroup-name "^.*:" "")
+            (replace-regexp-in-string "^.*:" "" gnus-newsgroup-name)))))
+    (gnus-summary-copy-article n archive-name)))
+@end example
+
+@noindent
+ You can now say @samp{M-x
+ my-archive-article} in summary buffer to
+ archive the article under the cursor in a nnml
+ group. (Change nnml to your preferred back end)
+
+ Of course you can also make sure the cache is enabled by saying
 
-Use an nnbabyl:all.SCORE (or nnmh, or nnml, or whatever) file containing:
+@example
+(setq gnus-use-cache t)
+@end example
+
+@noindent
+ then you only have to set either the tick or the dormant
+ mark for articles you want to keep, setting the read
+ mark will remove them from cache.
+@ifnottex
+@node [6.3], [6.4], [6.2], FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.3: 
+
+ How to search for a specific message?
+
+Answer: 
+
+ There are several ways for this, too. For a posting from
+ a Usenet group the easiest solution is probably to ask
+ @uref{http://groups.google.com,groups.google.com},
+ if you found the posting there, tell Google to display
+ the raw message, look for the message-id, and say
+ @samp{M-^ the@@message.id RET} in a
+ summary buffer.
+ Since Gnus 5.10.0 there's also a Gnus interface for
+ groups.google.com which you can call with
+ @samp{G W}) in group buffer.
+
+ Another idea which works for both mail and news groups
+ is to enter the group where the message you are
+ searching is and use the standard Emacs search
+ @samp{C-s}, it's smart enough to look at
+ articles in collapsed threads, too. If you want to
+ search bodies, too try @samp{M-s}
+ instead. Further on there are the
+ gnus-summary-limit-to-foo functions, which can help you,
+ too.
+
+ Of course you can also use grep to search through your
+ local mail, but this is both slow for big archives and
+ inconvenient since you are not displaying the found mail
+ in Gnus. Here comes nnir into action. Nnir is a front end
+ to search engines like swish-e or swish++ and
+ others. You index your mail with one of those search
+ engines and with the help of nnir you can search trough
+ the indexed mail and generate a temporary group with all
+ messages which met your search criteria. If this sound
+ cool to you get nnir.el from
+ @uref{ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/}
+ or @uref{ftp://ftp.is.informatik.uni-duisburg.de/pub/src/emacs/}.
+ Instructions on how to use it are at the top of the file.
+@ifnottex
+@node [6.4], [6.5], [6.3], FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.4: 
+
+ How to get rid of old unwanted mail?
+
+Answer: 
+
+ You can of course just mark the mail you don't need
+ anymore by saying @samp{#} with point
+ over the mail and then say @samp{B DEL}
+ to get rid of them forever. You could also instead of
+ actually deleting them, send them to a junk-group by
+ saying @samp{B m nnml:trash-bin} which
+ you clear from time to time, but both are not the intended
+ way in Gnus.
+
+ In Gnus, we let mail expire like news expires on a news
+ server. That means you tell Gnus the message is
+ expirable (you tell Gnus "I don't need this mail
+ anymore") by saying @samp{E} with point
+ over the mail in summary buffer. Now when you leave the
+ group, Gnus looks at all messages which you marked as
+ expirable before and if they are old enough (default is
+ older than a week) they are deleted. 
+@ifnottex
+@node [6.5], [6.6], [6.4], FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.5: 
+
+ I want that all read messages are expired (at least in
+ some groups). How to do it?
+
+Answer: 
+
+ If you want all read messages to be expired (e.g. in
+ mailing lists where there's an online archive), you've
+ got two choices: auto-expire and
+ total-expire. Auto-expire means, that every article
+ which has no marks set and is selected for reading is
+ marked as expirable, Gnus hits @samp{E}
+ for you every time you read a message. Total-expire
+ follows a slightly different approach, here all article
+ where the read mark is set are expirable.
+
+ To activate auto-expire, include auto-expire in the
+ Group parameters for the group. (Hit @samp{G
+ c} in summary buffer with point over the
+ group to change group parameters). For total-expire add
+ total-expire to the group-parameters.
+
+ Which method you choose is merely a matter of taste:
+ Auto-expire is faster, but it doesn't play together with
+ Adaptive Scoring, so if you want to use this feature,
+ you should use total-expire.
+
+ If you want a message to be excluded from expiration in
+ a group where total or auto expire is active, set either
+ tick (hit @samp{u}) or dormant mark (hit
+ @samp{u}), when you use auto-expire, you
+ can also set the read mark (hit
+ @samp{d}).
+@ifnottex
+@node [6.6],  , [6.5], FAQ 6 - Old messages
+@end ifnottex
+@subsubheading Question 6.6: 
+
+ I don't want expiration to delete my mails but to move them
+ to another group.
+
+Answer: 
+
+ Say something like this in ~/.gnus:
 
 @example
-((adapt ignore)
- (local (gnus-use-scoring nil))
- (exclude-files "all.SCORE"))
+(setq nnmail-expiry-target "nnml:expired")
 @end example
 
+@noindent
+ (If you want to change the value of nnmail-expiry-target
+ on a per group basis see the question "How can I disable
+ threading in some (e.g. mail-) groups, or set other
+ variables specific for some groups?")
+
+@ifnottex
+@node FAQ 7 - Gnus in a dial-up environment, FAQ 8 - Getting help, FAQ 6 - Old messages, Frequently Asked Questions
+@end ifnottex
+@subsection Gnus in a dial-up environment
+
+@menu
+* [7.1]::   I don't have a permanent connection to the net, how can I
+            minimize the time I've got to be connected? 
+* [7.2]::   So what was this thing about the Agent? 
+* [7.3]::   I want to store article bodies on disk, too. How to do it? 
+* [7.4]::   How to tell Gnus not to try to send mails / postings while
+            I'm offline? 
+@end menu
+
+
+@ifnottex
+@node [7.1], [7.2], FAQ 7 - Gnus in a dial-up environment, FAQ 7 - Gnus in a dial-up environment
+@end ifnottex
+@subsubheading Question 7.1: 
+
+ I don't have a permanent connection to the net, how can
+ I minimize the time I've got to be connected?
+
+Answer: 
+
+ You've got basically two options: Either you use the
+ Gnus Agent (see below) for this, or you can install
+ programs which fetch your news and mail to your local
+ disk and Gnus reads the stuff from your local
+ machine.
+
+ If you want to follow the second approach, you need a
+ program which fetches news and offers them to Gnus, a
+ program which does the same for mail and a program which
+ receives the mail you write from Gnus and sends them
+ when you're online.
+
+Let's talk about Unix systems first: For the news part, the easiest
+solution is a small nntp server like
+@uref{http://www.leafnode.org/,Leafnode} or
+@uref{http://infa.abo.fi/~patrik/sn/,sn}, of course you can also
+install a full featured news server like
+@uref{http://www.isc.org/products/INN/,inn}.
+
+Then you want to fetch your Mail, popular choices are
+@itemize @bullet
+@item
+@uref{http://www.catb.org/~esr/fetchmail/,fetchmail} and
+@item
+@uref{http://www.qcc.ca/~charlesc/software/getmail-3.0/,getmail}.
 @end itemize
+You should tell those to write the mail to your disk and Gnus to read
+it from there. Last but not least the mail sending part: This can be
+done with every MTA like @uref{http://www.sendmail.org/,sendmail},
+@uref{http://www.qmail.org/,postfix}, @uref{http://www.exim.org/,exim}
+or @uref{http://www.qmail.org/,qmail}.
+
+ On windows boxes I'd vote for 
+ @uref{http://www.tglsoft.de/,Hamster}, 
+ it's a small freeware, open-source program which fetches
+ your mail and news from remote servers and offers them
+ to Gnus (or any other mail and/or news reader) via nntp
+ respectively POP3 or IMAP. It also includes a smtp
+ server for receiving mails from Gnus.
+@ifnottex
+@node [7.2], [7.3], [7.1], FAQ 7 - Gnus in a dial-up environment
+@end ifnottex
+@subsubheading Question 7.2: 
+
+ So what was this thing about the Agent?
+
+Answer: 
+
+ The Gnus agent is part of Gnus, it allows you to fetch
+ mail and news and store them on disk for reading them
+ later when you're offline. It kind of mimics offline
+ newsreaders like e.g. Forte Agent. If you want to use
+ the Agent place the following in ~/.gnus if you are
+ still using 5.8.8 or 5.9 (it's the default since 5.10.0):
+
+@example
+(setq gnus-agent t)
+@end example
+
+ Now you've got to select the servers whose groups can be
+ stored locally. To do this, open the server buffer
+ (that is press @samp{^} while in the
+ group buffer). Now select a server by moving point to
+ the line naming that server. Finally, agentize the
+ server by typing @samp{J a}. If you
+ make a mistake, or change your mind, you can undo this
+ action by typing @samp{J r}. When
+ you're done, type 'q' to return to the group buffer.
+ Now the next time you enter a group on a agentized
+ server, the headers will be stored on disk and read from
+ there the next time you enter the group.
+@ifnottex
+@node [7.3], [7.4], [7.2], FAQ 7 - Gnus in a dial-up environment
+@end ifnottex
+@subsubheading Question 7.3: 
+
+ I want to store article bodies on disk, too. How to do it?
+
+Answer: 
+
+ You can tell the agent to automatically fetch the bodies
+ of articles which fulfill certain predicates, this is
+ done in a special buffer which can be reached by
+ saying @samp{J c} in group
+ buffer. Please refer to the documentation for
+ information which predicates are possible and how
+ exactly to do it. 
+
+ Further on you can tell the agent manually which
+ articles to store on disk. There are two ways to do
+ this: Number one: In the summary buffer, process mark a
+ set of articles that shall be stored in the agent by
+ saying @samp{#} with point over the
+ article and then type @samp{J s}. The
+ other possibility is to set, again in the summary
+ buffer, downloadable (%) marks for the articles you
+ want by typing @samp{@@} with point over
+ the article and then typing @samp{J u}.
+ What's the difference? Well, process marks are erased as
+ soon as you exit the summary buffer while downloadable
+ marks are permanent. You can actually set downloadable
+ marks in several groups then use fetch session ('J s' in
+ the GROUP buffer) to fetch all of those articles. The
+ only downside is that fetch session also fetches all of
+ the headers for every selected group on an agentized
+ server. Depending on the volume of headers, the initial
+ fetch session could take hours.
+@ifnottex
+@node [7.4],  , [7.3], FAQ 7 - Gnus in a dial-up environment
+@end ifnottex
+@subsubheading Question 7.4: 
+
+ How to tell Gnus not to try to send mails / postings
+ while I'm offline?
+
+Answer: 
+
+ All you've got to do is to tell Gnus when you are online
+ (plugged) and when you are offline (unplugged), the rest
+ works automatically. You can toggle plugged/unplugged
+ state by saying @samp{J j} in group
+ buffer. To start Gnus unplugged say @samp{M-x
+ gnus-unplugged} instead of
+ @samp{M-x gnus}. Note that for this to
+ work, the agent must be active.
+
+@ifnottex
+@node FAQ 8 - Getting help, FAQ 9 - Tuning Gnus, FAQ 7 - Gnus in a dial-up environment, Frequently Asked Questions
+@end ifnottex
+@subsection Getting help
+
+@menu
+* [8.1]::   How to find information and help inside Emacs? 
+* [8.2]::   I can't find anything in the Gnus manual about X
+            (e.g. attachments, PGP, MIME...), is it not documented? 
+* [8.3]::   Which websites should I know? 
+* [8.4]::   Which mailing lists and newsgroups are there? 
+* [8.5]::   Where to report bugs? 
+* [8.6]::   I need real-time help, where to find it? 
+@end menu
+
+@ifnottex
+@node [8.1], [8.2], FAQ 8 - Getting help, FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.1: 
+
+ How to find information and help inside Emacs?
+
+Answer: 
+
+ The first stop should be the Gnus manual (Say
+ @samp{C-h i d m Gnus RET} to start the
+ Gnus manual, then walk through the menus or do a
+ full-text search with @samp{s}). Then
+ there are the general Emacs help commands starting with
+ C-h, type @samp{C-h ? ?} to get a list
+ of all available help commands and their meaning. Finally
+ @samp{M-x apropos-command} lets you
+ search through all available functions and @samp{M-x
+ apropos} searches the bound variables.
+@ifnottex
+@node [8.2], [8.3], [8.1], FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.2: 
+
+ I can't find anything in the Gnus manual about X
+ (e.g. attachments, PGP, MIME...), is it not documented?
+
+Answer: 
+
+ There's not only the Gnus manual but also the manuals
+ for message, emacs-mime, sieve and pgg. Those packages
+ are distributed with Gnus and used by Gnus but aren't
+ really part of core Gnus, so they are documented in
+ different info files, you should have a look in those
+ manuals, too.
+@ifnottex
+@node [8.3], [8.4], [8.2], FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.3: 
+
+ Which websites should I know?
+
+Answer: 
+
+ The two most important ones are the
+ @uref{http://www.gnus.org,official Gnus website}.
+ and it's sister site 
+ @uref{http://my.gnus.org,my.gnus.org (MGO)},
+ hosting an archive of lisp snippets, howtos, a (not
+ really finished) tutorial and this FAQ.
+
+ Tell me about other sites which are interesting.
+@ifnottex
+@node [8.4], [8.5], [8.3], FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.4: 
+
+ Which mailing lists and newsgroups are there?
+
+Answer: 
+
+ There's the newsgroup gnu.emacs.gnus (pull it from
+ e.g. news.gnus.org) which deals with general questions
+ and the ding mailing list (ding@@gnus.org) dealing with
+ development of Gnus. You can read the ding list via
+ NNTP, too under the name gnus.ding from news.gnus.org.
+
+ If you want to stay in the big8,
+ news.software.newssreaders is also read by some Gnus
+ users (but chances for qualified help are much better in
+ the above groups) and if you speak German, there's
+ de.comm.software.gnus.
+@ifnottex
+@node [8.5], [8.6], [8.4], FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.5: 
+
+ Where to report bugs?
+
+Answer: 
+
+Say @samp{M-x gnus-bug}, this will start a message to the
+@email{bugs@@gnus.org,gnus bug mailing list} including information
+about your environment which make it easier to help you.
+@ifnottex
+@node [8.6],  , [8.5], FAQ 8 - Getting help
+@end ifnottex
+@subsubheading Question 8.6: 
+
+ I need real-time help, where to find it?
+
+Answer: 
+
+ Point your IRC client to irc.my.gnus.org channel
+ #mygnus. Don't be afraid if people there speak German,
+ they are willing and capable of switching to
+ English when people from outside Germany enter.
+
+@ifnottex
+@node FAQ 9 - Tuning Gnus, FAQ - Glossary, FAQ 8 - Getting help, Frequently Asked Questions
+@end ifnottex
+@subsection Tuning Gnus
+
+@menu
+* [9.1]::   Starting Gnus is really slow, how to speed it up? 
+* [9.2]::   How to speed up the process of entering a group? 
+* [9.3]::   Sending mail becomes slower and slower, what's up? 
+@end menu
+
+@ifnottex
+@node [9.1], [9.2], FAQ 9 - Tuning Gnus, FAQ 9 - Tuning Gnus
+@end ifnottex
+@subsubheading Question 9.1: 
+
+ Starting Gnus is really slow, how to speed it up?
+
+Answer: 
+
+ The reason for this could be the way Gnus reads it's
+ active file, see the node "The Active File" in the Gnus
+ manual for things you might try to speed the process up.
+ An other idea would be to byte compile your ~/.gnus (say
+ @samp{M-x byte-compile-file RET ~/.gnus
+ RET} to do it). Finally, if you have require
+ statements in your .gnus, you could replace them with
+ eval-after-load, which loads the stuff not at startup
+ time, but when it's needed. Say you've got this in your
+ ~/.gnus:
+
+@example
+(require 'message)
+(add-to-list 'message-syntax-checks '(sender . disabled))
+@end example
+
+@noindent
+ then as soon as you start Gnus, message.el is loaded. If
+ you replace it with
 
+@example
+(eval-after-load "message"
+      '(add-to-list 'message-syntax-checks '(sender . disabled)))
+@end example
+
+@noindent
+ it's loaded when it's needed.
+@ifnottex
+@node [9.2], [9.3], [9.1], FAQ 9 - Tuning Gnus
+@end ifnottex
+@subsubheading Question 9.2: 
+
+ How to speed up the process of entering a group?
+
+Answer: 
+
+ A speed killer is setting the variable
+ gnus-fetch-old-headers to anything different from nil,
+ so don't do this if speed is an issue. To speed up
+ building of summary say
+
+@example
+(gnus-compile)
+@end example
+
+@noindent
+ at the bottom of your ~/.gnus, this will make gnus
+ byte-compile things like
+ gnus-summary-line-format. 
+ then you could increase the value of gc-cons-threshold
+ by saying something like
+
+@example
+(setq gc-cons-threshold 3500000)
+@end example
+
+@noindent
+ in ~/.emacs. If you don't care about width of CJK
+ characters or use Gnus 5.10.0 or younger together with a
+ recent GNU Emacs, you should say
 
+@example
+(setq gnus-use-correct-string-widths nil) 
+@end example
+
+@noindent
+ in ~/.gnus (thanks to Jesper harder for the last
+ two suggestions). Finally if you are still using 5.8.8
+ or 5.9 and experience speed problems with summary
+ buffer generation, you definitely should update to
+ 5.10.0 since there quite some work on improving it has
+ been done.
+@ifnottex
+@node [9.3],  , [9.2], FAQ 9 - Tuning Gnus
+@end ifnottex
+@subsubheading Question 9.3: 
+
+ Sending mail becomes slower and slower, what's up?
+
+Answer: 
+
+ The reason could be that you told Gnus to archive the
+ messages you wrote by setting
+ gnus-message-archive-group. Try to use a nnml group
+ instead of an archive group, this should bring you back
+ to normal speed.
+
+@ifnottex
+@node FAQ - Glossary,  , FAQ 9 - Tuning Gnus, Frequently Asked Questions
+@end ifnottex
+@subsection Glossary
+
+@table @dfn
+
+@item ~/.gnus
+ When the term ~/.gnus is used it just means your Gnus
+ configuration file. You might as well call it ~/.gnus.el or
+ specify another name.
+
+@item Back End
+ In Gnus terminology a back end is a virtual server, a layer
+ between core Gnus and the real NNTP-, POP3-, IMAP- or
+ whatever-server which offers Gnus a standardized interface
+ to functions like "get message", "get Headers" etc.
+
+@item Emacs
+ When the term Emacs is used in this FAQ, it means either GNU
+ Emacs or XEmacs.
+
+@item Message
+ In this FAQ message means a either a mail or a posting to a
+ Usenet Newsgroup or to some other fancy back end, no matter
+ of which kind it is.
+
+@item MUA
+ MUA is an acronym for Mail User Agent, it's the program you
+ use to read and write e-mails.
+
+@item NUA
+ NUA is an acronym for News User Agent, it's the program you
+ use to read and write Usenet news.
+@end table
+
+@c @bye
diff --git a/texi/gnus-ja.texi b/texi/gnus-ja.texi
new file mode 100644 (file)
index 0000000..6d80aa6
--- /dev/null
@@ -0,0 +1,27439 @@
+\input texinfo
+
+@setfilename gnus-ja
+@settitle T-gnus 6.16 Manual
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex pg cp
+@dircategory Emacs
+@direntry
+* Gnus-ja: (gnus-ja).         The newsreader gnus (Japanese).
+@end direntry
+@iftex
+@finalout
+@end iftex
+@setchapternewpage odd
+
+@iftex
+@iflatex
+\documentclass[twoside,a4paper,openright,11pt]{book}
+\usepackage[latin1]{inputenc}
+\usepackage{pagestyle}
+\usepackage{epsfig}
+\usepackage{pixidx}
+\input{gnusconfig.tex}
+
+\ifx\pdfoutput\undefined
+\else
+\usepackage[pdftex,bookmarks,colorlinks=true]{hyperref}
+\usepackage{thumbpdf}
+\pdfcompresslevel=9
+\fi
+
+\makeindex
+\begin{document}
+
+\newcommand{\gnusversionname}{T-gnus v6.16}
+\newcommand{\gnuschaptername}{}
+\newcommand{\gnussectionname}{}
+
+\newcommand{\gnusbackslash}{/}
+
+\newcommand{\gnusref}[1]{``#1'' on page \pageref{#1}}
+\ifx\pdfoutput\undefined
+\newcommand{\gnusuref}[1]{\gnustt{#1}}
+\else
+\newcommand{\gnusuref}[1]{\href{#1}{\gnustt{#1}}}
+\fi
+\newcommand{\gnusxref}[1]{See ``#1'' on page \pageref{#1}}
+\newcommand{\gnuspxref}[1]{see ``#1'' on page \pageref{#1}}
+
+\newcommand{\gnuskindex}[1]{\index{#1}}
+\newcommand{\gnusindex}[1]{\index{#1}}
+
+\newcommand{\gnustt}[1]{{\gnusselectttfont{}#1}}
+\newcommand{\gnuscode}[1]{\gnustt{#1}}
+\newcommand{\gnusasis}[1]{\gnustt{#1}}
+\newcommand{\gnusurl}[1]{\gnustt{#1}}
+\newcommand{\gnuscommand}[1]{\gnustt{#1}}
+\newcommand{\gnusenv}[1]{\gnustt{#1}}
+\newcommand{\gnussamp}[1]{``{\fontencoding{OT1}\gnusselectttfont{}#1}''}
+\newcommand{\gnuslisp}[1]{\gnustt{#1}}
+\newcommand{\gnuskbd}[1]{`\gnustt{#1}'}
+\newcommand{\gnuskey}[1]{`\gnustt{#1}'}
+\newcommand{\gnusfile}[1]{`\gnustt{#1}'}
+\newcommand{\gnusdfn}[1]{\textit{#1}}
+\newcommand{\gnusi}[1]{\textit{#1}}
+\newcommand{\gnusr}[1]{\textrm{#1}}
+\newcommand{\gnusstrong}[1]{\textbf{#1}}
+\newcommand{\gnusemph}[1]{\textit{#1}}
+\newcommand{\gnusvar}[1]{{\fontsize{10pt}{10}\selectfont\textsl{\textsf{#1}}}}
+\newcommand{\gnussc}[1]{\textsc{#1}}
+\newcommand{\gnustitle}[1]{{\huge\textbf{#1}}}
+\newcommand{\gnusversion}[1]{{\small\textit{#1}}}
+\newcommand{\gnusauthor}[1]{{\large\textbf{#1}}}
+\newcommand{\gnusresult}[1]{\gnustt{=> #1}}
+\newcommand{\gnusacronym}[1]{\textsc{#1}}
+\newcommand{\gnusemail}[1]{\textit{#1}}
+
+\newcommand{\gnusbullet}{{${\bullet}$}}
+\newcommand{\gnusdollar}{\$}
+\newcommand{\gnusampersand}{\&}
+\newcommand{\gnuspercent}{\%}
+\newcommand{\gnushash}{\#}
+\newcommand{\gnushat}{\symbol{"5E}}
+\newcommand{\gnusunderline}{\symbol{"5F}}
+\newcommand{\gnusnot}{$\neg$}
+\newcommand{\gnustilde}{\symbol{"7E}}
+\newcommand{\gnusless}{{$<$}}
+\newcommand{\gnusgreater}{{$>$}}
+\newcommand{\gnusbraceleft}{{$>$}}
+\newcommand{\gnusbraceright}{{$>$}}
+
+\newcommand{\gnushead}{\raisebox{-1cm}{\epsfig{figure=ps/gnus-head,height=1cm}}}
+\newcommand{\gnusinteresting}{
+\marginpar[\mbox{}\hfill\gnushead]{\gnushead}
+}
+
+\newcommand{\gnuscleardoublepage}{\ifodd\count0\mbox{}\clearpage\thispagestyle{empty}\mbox{}\clearpage\else\clearpage\fi}
+
+\newcommand{\gnuspagechapter}[1]{
+{\mbox{}}
+}
+
+\newdimen{\gnusdimen}
+\gnusdimen 0pt
+
+\newcommand{\gnuschapter}[2]{
+\gnuscleardoublepage
+\ifdim \gnusdimen = 0pt\setcounter{page}{1}\pagestyle{gnus}\pagenumbering{arabic} \gnusdimen 1pt\fi
+\chapter{#2}
+\renewcommand{\gnussectionname}{}
+\renewcommand{\gnuschaptername}{#2}
+\thispagestyle{empty}
+\hspace*{-2cm}
+\begin{picture}(500,500)(0,0)
+\put(480,350){\makebox(0,0)[tr]{#1}}
+\put(40,300){\makebox(500,50)[bl]{{\Huge\bf{#2}}}}
+\end{picture}
+\clearpage
+}
+
+\newcommand{\gnusfigure}[3]{
+\begin{figure}
+\mbox{}\ifodd\count0\hspace*{-0.8cm}\else\hspace*{-3cm}\fi\begin{picture}(440,#2)
+#3
+\end{picture}
+\caption{#1}
+\end{figure}
+}
+
+\newcommand{\gnusicon}[1]{
+\marginpar[\mbox{}\hfill\raisebox{-1.5cm}{\epsfig{figure=ps/#1-up,height=1.5cm}}]{\raisebox{-1cm}{\epsfig{figure=ps/#1-up,height=1cm}}}
+}
+
+\newcommand{\gnuspicon}[1]{
+\margindex{\epsfig{figure=#1,width=2cm}}
+}
+
+\newcommand{\gnusxface}[2]{
+\margindex{\epsfig{figure=#1,width=1cm}\epsfig{figure=#2,width=1cm}}
+}
+
+\newcommand{\gnussmiley}[2]{
+\margindex{\makebox[2cm]{\hfill\epsfig{figure=#1,width=0.5cm}\hfill\epsfig{figure=#2,width=0.5cm}\hfill}}
+}
+
+\newcommand{\gnusitemx}[1]{\mbox{}\vspace*{-\itemsep}\vspace*{-\parsep}\item#1}
+
+\newcommand{\gnussection}[1]{
+\renewcommand{\gnussectionname}{#1}
+\section{#1}
+}
+
+\newenvironment{codelist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{asislist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{kbdlist}%
+{\begin{list}{}{
+\labelwidth=0cm
+}
+}{\end{list}}
+
+\newenvironment{dfnlist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{stronglist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{samplist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{varlist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newenvironment{emphlist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
+\newlength\gnusheadtextwidth
+\setlength{\gnusheadtextwidth}{\headtextwidth}
+\addtolength{\gnusheadtextwidth}{1cm}
+
+\newpagestyle{gnuspreamble}%
+{
+{
+\ifodd\count0
+{
+\hspace*{-0.23cm}\underline{\makebox[\gnusheadtextwidth]{\mbox{}}\textbf{\hfill\roman{page}}}
+}
+\else
+{
+\hspace*{-3.25cm}\underline{\makebox[\gnusheadtextwidth]{\textbf{\roman{page}\hfill\mbox{}}}
+}
+}
+\fi
+}
+}
+{
+\ifodd\count0
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\else
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\hfill \mbox{}
+\fi
+}
+
+\newpagestyle{gnusindex}%
+{
+{
+\ifodd\count0
+{
+\hspace*{-0.23cm}\underline{\makebox[\gnusheadtextwidth]{\textbf{\gnuschaptername\hfill\arabic{page}}}}
+}
+\else
+{
+\hspace*{-3.25cm}\underline{\makebox[\gnusheadtextwidth]{\textbf{\arabic{page}\hfill\gnuschaptername}}}
+}
+\fi
+}
+}
+{
+\ifodd\count0
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\else
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\hfill \mbox{}
+\fi
+}
+
+\newpagestyle{gnus}%
+{
+{
+\ifodd\count0
+{
+\makebox[12cm]{\hspace*{3.1cm}\underline{\makebox[\gnusheadtextwidth]{\textbf{\arabic{chapter}.\arabic{section}} \textbf{\gnussectionname\hfill\arabic{page}}}}}
+}
+\else
+{
+\makebox[12cm]{\hspace*{-2.95cm}\underline{\makebox[\gnusheadtextwidth]{\textbf{\arabic{page}\hfill\gnuschaptername}}}}
+}
+\fi
+}
+}
+{
+\ifodd\count0
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\else
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
+\hfill \mbox{}
+\fi
+}
+
+\pagenumbering{roman}
+\pagestyle{gnuspreamble}
+
+@end iflatex
+@end iftex
+
+@iftex
+@iflatex
+\begin{titlepage}
+{
+
+%\addtolength{\oddsidemargin}{-5cm}
+%\addtolength{\evensidemargin}{-5cm}
+\parindent=0cm
+\addtolength{\textheight}{2cm}
+
+\gnustitle{\gnustitlename}\hfill\gnusversion{\gnusversionname}\\
+\rule{15cm}{1mm}\\
+\vfill
+\hspace*{0cm}\epsfig{figure=ps/gnus-big-logo,height=15cm}
+\vfill
+\rule{15cm}{1mm}\\
+\gnusauthor{by Lars Magne Ingebrigtsen}
+\newpage
+}
+
+\mbox{}
+\vfill
+
+\thispagestyle{empty}
+
+Copyright \copyright{} 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004
+Free Software Foundation, Inc.
+
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+\e$B$3$NJ8=q$r!"%U%j!<%=%U%H%&%'%":bCDH/9T$N\e(B GNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q\e(B
+\e$BBh\e(B 1.1 \e$BHG$^$?$O$=$l0J9_$NHG$,Dj$a$k>r7o$N2<$GJ#@=!"G[I[!"$"$k$$$OJQ99$9\e(B
+\e$B$k$3$H$r5v2D$7$^$9!#JQ99IT2DItJ,$O;XDj$7$^$;$s!#!V\e(BA GNU Manual\e$B!W$OI=I=;f\e(B
+\e$B%F%-%9%H!"0J2<$N\e(B (a) \e$B$ON"I=;f%F%-%9%H$G$9!#$3$NMxMQ5vBz7@Ls=q$NJ#<L$O\e(B
+\e$B!V\e(BEmacs manual\e$B!W$N!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$H$$$&>O$K4^$^$l$F$$$^\e(B
+\e$B$9!#\e(B
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+(a) FSF \e$B$NN"I=;f%F%-%9%H\e(B:\e$B!V$"$J$?$K$O$3$N\e(B GNU Manual \e$B$r\e(B GNU \e$B%=%U%H%&%'%"\e(B
+\e$B$N$h$&$KJ#@=$7$?$jJQ99$9$k<+M3$,$"$j$^$9!#J#@=$O%U%j!<%=%U%H%&%'%":bCD$K\e(B
+\e$B$h$C$F=PHG$5$l$^$7$?!#\e(B(\e$B%U%j!<%=%U%H%&%'%":bCD$O\e(B) GNU \e$B$N3+H/$N$?$a$KI,MW\e(B
+\e$B$J;q6b$r=8$a$F$$$^$9!#!W\e(B
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+
+\e$B$3$NJ8=q$O!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$K4p$E$$$FG[I[$5$l$?<}=8Cx:nJ*\e(B
+\e$B$N0lIt$G$9!#$b$7$"$J$?$,$3$NJ8=q$r<}=8Cx:nJ*$+$iJ,N%$7$FG[I[$7$?$$$H$-$O!"\e(B
+\e$B7@Ls=q$NBh\e(B 6 \e$B9`$K5-=R$5$l$F$$$k$h$&$K!"J8=q$K7@Ls=q$NJ#<L$rIU2C$9$k$3$H\e(B
+\e$B$K$h$C$F!"9T$J$&$3$H$,$G$-$^$9!#\e(B
+\newpage
+\end{titlepage}
+@end iflatex
+@end iftex
+
+@ifnottex
+
+This file documents gnus, the GNU Emacs newsreader.
+
+\e$B$3$N%U%!%$%k$O\e(B GNU Emacs \e$B$N%K%e!<%9%j!<%@$G$"$k\e(B gnus \e$B$K4X$9$k@bL@=q$G$9!#\e(B
+
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+        Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+\e$B$3$NJ8=q$r!"%U%j!<%=%U%H%&%'%":bCDH/9T$N\e(B GNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q\e(B
+\e$BBh\e(B 1.1 \e$BHG$^$?$O$=$l0J9_$NHG$,Dj$a$k>r7o$N2<$GJ#@=!"G[I[!"$"$k$$$OJQ99$9\e(B
+\e$B$k$3$H$r5v2D$7$^$9!#JQ99IT2DItJ,$O;XDj$7$^$;$s!#!V\e(BA GNU Manual\e$B!W$OI=I=;f\e(B
+\e$B%F%-%9%H!"0J2<$N\e(B (a) \e$B$ON"I=;f%F%-%9%H$G$9!#$3$NMxMQ5vBz7@Ls=q$NJ#<L$O\e(B
+\e$B!V\e(BEmacs manual\e$B!W$N!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$H$$$&>O$K4^$^$l$F$$$^\e(B
+\e$B$9!#\e(B
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+(a) FSF \e$B$NN"I=;f%F%-%9%H\e(B:\e$B!V$"$J$?$K$O$3$N\e(B GNU Manual \e$B$r\e(B GNU \e$B%=%U%H%&%'%"\e(B
+\e$B$N$h$&$KJ#@=$7$?$jJQ99$9$k<+M3$,$"$j$^$9!#J#@=$O%U%j!<%=%U%H%&%'%":bCD$K\e(B
+\e$B$h$C$F=PHG$5$l$^$7$?!#\e(B(\e$B%U%j!<%=%U%H%&%'%":bCD$O\e(B) GNU \e$B$N3+H/$N$?$a$KI,MW\e(B
+\e$B$J;q6b$r=8$a$F$$$^$9!#!W\e(B
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+
+\e$B$3$NJ8=q$O!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$K4p$E$$$FG[I[$5$l$?<}=8Cx:nJ*\e(B
+\e$B$N0lIt$G$9!#$b$7$"$J$?$,$3$NJ8=q$r<}=8Cx:nJ*$+$iJ,N%$7$FG[I[$7$?$$$H$-$O!"\e(B
+\e$B7@Ls=q$NBh\e(B 6 \e$B9`$K5-=R$5$l$F$$$k$h$&$K!"J8=q$K7@Ls=q$NJ#<L$rIU2C$9$k$3$H\e(B
+\e$B$K$h$C$F!"9T$J$&$3$H$,$G$-$^$9!#\e(B
+@end ifnottex
+
+@tex
+
+@titlepage
+@title T-gnus 6.16 Manual
+
+@author by Lars Magne Ingebrigtsen
+@author by members of Semi-gnus mailing-list
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003
+        Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+\e$B$3$NJ8=q$r!"%U%j!<%=%U%H%&%'%":bCDH/9T$N\e(B GNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q\e(B
+\e$BBh\e(B 1.1 \e$BHG$^$?$O$=$l0J9_$NHG$,Dj$a$k>r7o$N2<$GJ#@=!"G[I[!"$"$k$$$OJQ99$9\e(B
+\e$B$k$3$H$r5v2D$7$^$9!#JQ99IT2DItJ,$O;XDj$7$^$;$s!#!V\e(BA GNU Manual\e$B!W$OI=I=;f\e(B
+\e$B%F%-%9%H!"0J2<$N\e(B (a) \e$B$ON"I=;f%F%-%9%H$G$9!#$3$NMxMQ5vBz7@Ls=q$NJ#<L$O\e(B
+\e$B!V\e(BEmacs manual\e$B!W$N!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$H$$$&>O$K4^$^$l$F$$$^\e(B
+\e$B$9!#\e(B
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+(a) FSF \e$B$NN"I=;f%F%-%9%H\e(B:\e$B!V$"$J$?$K$O$3$N\e(B GNU Manual \e$B$r\e(B GNU \e$B%=%U%H%&%'%"\e(B
+\e$B$N$h$&$KJ#@=$7$?$jJQ99$9$k<+M3$,$"$j$^$9!#J#@=$O%U%j!<%=%U%H%&%'%":bCD$K\e(B
+\e$B$h$C$F=PHG$5$l$^$7$?!#\e(B(\e$B%U%j!<%=%U%H%&%'%":bCD$O\e(B) GNU \e$B$N3+H/$N$?$a$KI,MW\e(B
+\e$B$J;q6b$r=8$a$F$$$^$9!#!W\e(B
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+
+\e$B$3$NJ8=q$O!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$K4p$E$$$FG[I[$5$l$?<}=8Cx:nJ*\e(B
+\e$B$N0lIt$G$9!#$b$7$"$J$?$,$3$NJ8=q$r<}=8Cx:nJ*$+$iJ,N%$7$FG[I[$7$?$$$H$-$O!"\e(B
+\e$B7@Ls=q$NBh\e(B 6 \e$B9`$K5-=R$5$l$F$$$k$h$&$K!"J8=q$K7@Ls=q$NJ#<L$rIU2C$9$k$3$H\e(B
+\e$B$K$h$C$F!"9T$J$&$3$H$,$G$-$^$9!#\e(B
+
+@end titlepage
+@page
+
+@end tex
+
+@node Top
+@top The gnus Newsreader
+
+@ifinfo
+
+T-gnus \e$B$r;H$&$3$H$K$h$C$F\e(B Emacs \e$B$G%K%e!<%9\e(B (news) \e$B$r\e(B (\e$B$=$l$K%a!<\e(B
+\e$B%k\e(B (mail) \e$B$b\e(B) \e$BFI$`$3$H$,$G$-$^$9!#%K%e!<%9$O\e(B @acronym{NNTP}\e$B!"%m!<%+%k%9\e(B
+\e$B%W!<%k!"\e(Bmbox \e$B%U%!%$%k$J$I$N$"$i$f$k6K0-$J<jCJ$r6n;H$7$F<j$KF~$l$k$3$H$,\e(B
+\e$B$G$-$^$9!#1?;n$7$r$7$F$_$h$&$H;W$&$J$i$P!"A4$F$rF1;~$KMQ$$$k$3$H$b$G$-$^\e(B
+\e$B$9!#\e(B
+
+T-gnus \e$B$O\e(B @acronym{SEMI} API \e$B$K4p$E$/\e(B @acronym{MIME} \e$B5!G=$rDs6!$7$^$9!#\e(B
+\e$B$=$&$$$&Lu$G!"\e(BT-gnus \e$B$OBg$-$J3($,F~$C$F$$$?$j$5$^$6$^$J7A<0$rMQ$$$?$j$7\e(B
+\e$B$F$$$k$A$g$C$HJQ$o$C$?5-;v$rFI$`8"Mx$rMJ8n$7$^$9!#\e(BT-gnus \e$B$O\e(B MULE API \e$B$K\e(B
+\e$B4p$E$/9q:]2=!&CO0h2=!"$*$h$S!"B?;z2=5!G=$rDs6!$7$^$9!#$h$C$F!"\e(BT-gnus \e$B$O\e(B
+\e$B$5$^$6$^$J8@8l7w$r:9JL$7$^$;$s!#$"$"!"%/%j%s%4%s$NJ}$O\e(B Unicode Next
+Generation \e$B$r$*BT$A$/$@$5$$!#\e(B
+
+\e$B$3$N@bL@=q$O\e(B T-gnus 6.16 \e$B$KBP1~$7$^$9!#\e(B
+
+@end ifinfo
+
+@iftex
+
+@iflatex
+\tableofcontents
+\gnuscleardoublepage
+@end iflatex
+
+Gnus \e$B$O\e(B GNU Emacs \e$B$N@h?JE*$G!"@bL@$N$"$k!"%+%9%?%^%$%:2DG=$G!"3HD%2DG=$J!"\e(B
+\e$B%j%"%k%?%$%`$G$J$$%K%e!<%9%j!<%@!<$G$9!#\e(B
+
+\e$B$*$*$C$H!#IT;W5D$J$3$H$K0JA0$K$b;w$?$h$&$J$3$H$rJ9$$$?$3$H$,$"$k$h$&$J5$\e(B
+\e$B$,$7$^$9!#??;w$r$7$?$HHsFq$5$l$J$$$&$A$K@bL@$r;O$a$^$7$g$&\e(B:
+
+Gnus \e$B$O%a%C%;!<%8$rFI$`$3$H$K4X$9$k<B83>l$G$9!#\e(BGnus \e$B$O$9$Y$F$r%K%e!<%9%0\e(B
+\e$B%k!<%W$N$h$&$KI=<($7$^$9!#\e(BGnus \e$B$G%a!<%k$rFI$_!"%G%#%l%/%H%j!<$r%V%i%&%:\e(B
+\e$B$7!"\e(B@code{ftp} \e$B$r$9$k$3$H$,$G$-$^$9!#$"$"!"$=$l$K!"%K%e!<%9$rFI$`$3$H$5\e(B
+\e$B$($G$-$^$9\e(B!
+
+Emacs \e$B$,J8>O$rJT=8$9$k?M$KNO$rM?$($k$h$&$K!"\e(Bgnus \e$B$O%K%e!<%9$rFI$`?M$KNO\e(B
+\e$B$rM?$($h$&$H$7$F$$$^$9!#\e(BGnus \e$B$OMxMQ<T$,<B9T2DG=$J$3$H$K@)8B$r@_$1$^$;$s!#\e(B
+\e$BMxMQ<T$,<+J,$GK>$`F0:n$r$9$k$h$&$K\e(B gnus \e$B$r3HD%$9$k$3$H$r>)Ne$7$F$$$^$9!#\e(B
+\e$B%W%m%0%i%`$,?M$rA`:n$9$k$Y$-$G$O$"$j$^$;$s!#?M$,%W%m%0%i%`$r;H$&\e(B (\e$B$b$7$/\e(B
+\e$B$OMtMQ$9$k\e(B) \e$B$3$H$K$h$C$F!"$d$j$?$$$3$H$r$G$-$k$h$&$K$J$C$F$$$k$Y$-$J$N$G\e(B
+\e$B$9!#\e(B
+
+@end iftex
+
+@menu
+* Starting Up::                 \e$B%K%e!<%9$r8+$D$1$k$N$K$O6lO+$,H<$&$+$bCN$l$J$$\e(B
+* Group Buffer::                \e$B%0%k!<%W$rA*Br$7!"9XFI$7!":o=|$9$k\e(B
+* Summary Buffer::              \e$B5-;v$rFI$_!"J]B8$7!"Ej9F$9$k\e(B
+* Article Buffer::              \e$B5-;v$rI=<($7!"07$&\e(B
+* Composing Messages::          \e$B%a!<%k$H%K%e!<%9$rAw$k$?$a$N>pJs\e(B
+* Select Methods::              Gnus \e$B$OA4$F$N%a%C%;!<%8$r$$$m$$$m$JA*BrJ}K!$GFI$`\e(B
+* Scoring::                     \e$B5-;v$KCM$r$D$1$k\e(B
+* Various::                     \e$B0lHLE*$J@_Dj\e(B
+* The End::                     \e$B$5$i$P!"$=$7$F$5$h$&$J$i\e(B
+* Appendices::                  \e$BMQ8l!"\e(BEmacs \e$BF~Lg!"\e(B@acronym{FAQ}\e$B!"Nr;K!"FbIt9=B$\e(B
+* Index::                       \e$BJQ?t!"4X?t!"35G0$N:w0z\e(B
+* Key Index::                   \e$B%-!<:w0z\e(B
+
+Other related manuals
+
+* Message:(message).            \e$B%a%C%;!<%8$N:n@.\e(B
+* Emacs-MIME:(emacs-mime).      Composing messages; @acronym{MIME}-specific parts.
+* Sieve:(sieve).                Managing Sieve scripts in Emacs.
+* PGG:(pgg).                    @acronym{PGP/MIME} with Gnus.
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Starting Gnus
+
+* Finding the News::            \e$B%K%e!<%9$r<hF@$9$kJ}K!$rA*$V\e(B
+* The First Time::              \e$B:G=i$K5/F0$7$?$H$-$K\e(B gnus \e$B$O2?$r$9$k$+\e(B
+* The Server is Down::          \e$B$I$&$9$l$P$=$N$h$&$J$H$-$K%a!<%k$r<j$KF~$l$k$3$H$,$G$-$k$+\e(B
+* Slave Gnusae::                \e$BF1;~$K0l$D0J>e$N\e(B gnus \e$B$r:nF0$5$;$k$3$H$,$G$-$k\e(B
+* Fetching a Group::            \e$B%0%k!<%W$rFI$`$?$a$@$1$K\e(B gnus \e$B$r5/F0$9$k\e(B
+* New Groups::                  Gnus \e$B$,?7$7$$%0%k!<%W$KBP$7$F2?$r$9$k$+\e(B
+* Changing Servers::            \e$B$"$k%5!<%P$+$iJL$N%5!<%P$X0\$j$?$$$+$b$7$l$J$$\e(B
+* Startup Files::               \e$B$d$C$+$$$J%9%?!<%H%"%C%W%U%!%$%k\e(B -- @file{.newsrc}
+* Auto Save::                   \e$B%/%i%C%7%e$+$i$N2sI|\e(B
+* The Active File::             \e$BCY$$2s@~$+$i$N%U%!%$%k$N<hF@$K$O;~4V$,$+$+$k\e(B
+* Startup Variables::           \e$BJQ99$7$?$$$H;W$&$+$b$7$l$J$$JQ?t\e(B
+
+New Groups
+
+* Checking New Groups::         \e$B$I$N%0%k!<%W$,?7$7$$$+$r7hDj$9$k\e(B
+* Subscription Methods::        \e$B?7$7$$%0%k!<%W$KBP$7$F\e(B gnus \e$B$O2?$r$9$Y$-$+\e(B
+* Filtering New Groups::        Gnus \e$B$KFCDj$N?7$7$$%0%k!<%W$rL5;k$5$;$k\e(B
+
+Group Buffer
+
+* Group Buffer Format::         \e$BI=<($5$l$F$$$k>pJs$HJQ99$NJ}K!\e(B
+* Group Maneuvering::           \e$B%0%k!<%W%P%C%U%!$r0\F0$9$k%3%^%s%I\e(B
+* Selecting a Group::           \e$B<B:]$K%K%e!<%9$rFI$`\e(B
+* Subscription Commands::       \e$B9XFI!"9XFICf;_!">C5n\e(B
+* Group Data::                  \e$B%0%k!<%W$N>pJs$rJQ99$9$k\e(B
+* Group Levels::                \e$B%l%Y%k\e(B? \e$B$=$l$C$F2?\e(B?
+* Group Score::                 \e$B$"$J$?$N9%$-$J%0%k!<%W$r8+$D$1=P$9J}K!\e(B
+* Marking Groups::              \e$B%0%k!<%W$K0u$r$D$1$F$*$$$F!"8e$G=hM}$G$-$^$9\e(B
+* Foreign Groups::              \e$B%0%k!<%W$N:n@.$H=$@5\e(B
+* Group Parameters::            \e$B%0%k!<%WKh$K0c$C$?%Q%i%a!<%?$r;}$?$;$i$l$^$9\e(B
+* Listing Groups::              Gnus \e$B$O%0%k!<%W$r$$$m$$$m$JJ,$1J}$GI=<($G$-$^$9\e(B
+* Sorting Groups::              \e$B%0%k!<%W$N=gHV$NG[CVBX$(\e(B
+* Group Maintenance::           \e$B$-$l$$$J\e(B @file{.newsrc} \e$B$NJ]$AJ}\e(B
+* Browse Foreign Server::       \e$B%5!<%P$r354Q$G$-$k!#2?$,FI$a$k$N$+8+$F$_$h$&\e(B
+* Exiting Gnus::                \e$B%K%e!<%9FI$`$N$r$d$a$F!";E;v$r$7$h$&\e(B
+* Group Topics::                \e$B%0%k!<%W$r@Z$j:.$<$F!"%H%T%C%/$4$H$KJ,3d$9$k\e(B
+* Misc Group Stuff::            \e$BB>$K$G$-$k$3$H\e(B
+
+Group Buffer Format
+
+* Group Line Specification::    \e$B%0%k!<%W%P%C%U%!$N8+$(J}$r7h$a$k\e(B
+* Group Mode line Specification::  \e$B%0%k!<%W%P%C%U%!$N%b!<%I9T\e(B
+* Group Highlighting::          \e$B%0%k!<%W%P%C%U%!$K$-$l$$$K?'$r$D$1$k\e(B
+
+Group Topics
+
+* Topic Commands::              \e$BD64JC1BPOC7?L?Na\e(B
+* Topic Variables::             Lisp \e$B$G%H%T%C%/$r%+%9%?%^%$%:$9$kJ}K!\e(B
+* Topic Sorting::               \e$B%H%T%C%/KhJL!9$KJB$YBX$($k\e(B
+* Topic Topology::              \e$BA4@$3&$NCO?^\e(B
+* Topic Parameters::            \e$B$"$k%H%T%C%/$NA4$F$N%0%k!<%W$KE,MQ$5$l$k%Q%i%a!<%?\e(B
+
+Misc Group Stuff
+
+* Scanning New Messages::       Gnus \e$B$K?7$7$$%a%C%;!<%8$,E~Ce$7$?$+$I$&$+$rJ9$/\e(B
+* Group Information::           \e$B%0%k!<%W$H\e(B gnus \e$B$K4X$9$k>pJs$H%X%k%W\e(B
+* Group Timestamp::             Gnus \e$B$K:G8e$K$$$D%0%k!<%W$rFI$s$@$+$r5-O?$5$;$k\e(B
+* File Commands::               Gnus \e$B$N%U%!%$%k$NFI$_=q$-\e(B
+* Sieve Commands::              Sieve \e$B%9%/%j%W%H$N4IM}\e(B
+
+Summary Buffer
+
+* Summary Buffer Format::       \e$B35N,%P%C%U%!$N304Q$r7hDj$9$k\e(B
+* Summary Maneuvering::         \e$B35N,%P%C%U%!$rF0$-2s$k\e(B
+* Choosing Articles::           \e$B5-;v$rFI$`\e(B
+* Paging the Article::          \e$BFI$s$G$$$k5-;v$r%9%/%m!<%k$9$k\e(B
+* Reply Followup and Post::     \e$B5-;v$rEj9F$9$k\e(B
+* Delayed Articles::            \e$B5-;v$r8e$GAw$k\e(B
+* Marking Articles::            \e$B5-;v$K4{FI$d4|8B@Z$l:o=|2DG=Ey$N0u$rIU$1$k\e(B
+* Limiting::                    \e$B35N,%P%C%U%!$K@)8B$r2C$($k$3$H$,$G$-$k\e(B
+* Threading::                   \e$B%9%l%C%I$,$I$N$h$&$K:n$i$l$k$+\e(B
+* Sorting the Summary Buffer::  \e$B%9%l%C%I$H5-;v$,$I$N$h$&$KJB$S$+$($i$l$k$+\e(B
+* Asynchronous Fetching::       Gnus \e$B$O5-;v$r@h$K<hF@$9$k$3$H$,$G$-$k\e(B
+* Article Caching::             \e$B%-%c%C%7%e$K5-;v$rCy$a$F$*$1$k\e(B
+* Persistent Articles::         \e$B5-;v$r4|8B@Z$l>C5n$7$J$/$5$;$k\e(B
+* Article Backlog::             \e$B4{$KFI$s$@5-;v$r;D$7$F$*$/\e(B
+* Saving Articles::             \e$B5-;v$NJ]B8$r%+%9%?%^%$%:$9$kJ}K!\e(B
+* Decoding Articles::           Gnus \e$B$O0lO"$N\e(B (uu)encode \e$B$5$l$?5-;v$r07$($k\e(B
+* Article Treatment::           \e$B5-;v%P%C%U%!$O$*K>$_$I$*$j$KL\Cc6lCc$K$G$-$k\e(B
+@c * MIME Commands::               Doing MIMEy things with the articles.
+@c * Charsets::                    Character set issues.
+* Article Commands::            \e$B5-;v%P%C%U%!$G$$$m$$$m$J$3$H$r$9$k\e(B
+* Summary Sorting::             \e$B$$$m$$$m$JJ}K!$G35N,%P%C%U%!$rJB$YBX$($k\e(B
+* Finding the Parent::          \e$B;R5-;v$,C5$;$J$$$C$F\e(B? \e$B?F5-;v$r<hF@$7$J$5$$\e(B
+* Alternative Approaches::      \e$B=i4|@_Dj$G$J$$35N,$r;H$C$FFI$`\e(B
+* Tree Display::                \e$B$b$C$H;k3PE*$J%9%l%C%I$NI=<(\e(B
+* Mail Group Commands::         \e$B$$$/$D$+$NL?Na$O%a!<%k%0%k!<%W$@$1$G;H$&$3$H$,$G$-$k\e(B
+* Various Summary Stuff::       \e$BB>$N$I$N>l=j$K$b9g$o$J$+$C$?$b$N\e(B
+* Exiting the Summary Buffer::  \e$B%0%k!<%W%P%C%U%!$KLa$k!"$^$?$O8=:_$N%0%k!<%W$r:F$SA*Br$9$k\e(B
+* Crosspost Handling::          \e$B%/%m%9%]%9%H$5$l$?5-;v$,$I$N$h$&$K07$o$l$k$+\e(B
+* Duplicate Suppression::       \e$B%/%m%9%]%9%H$N07$$$K<:GT$7$?$H$-$NBeBX<jCJ\e(B
+@c * Security::                    Decrypt and Verify.
+* Mailing List::                \e$B%a!<%j%s%0%j%9%H%^%$%J!<%b!<%I\e(B
+
+Summary Buffer Format
+
+* Summary Buffer Lines::        \e$B35N,%P%C%U%!$,$I$N$h$&$K8+$($k$Y$-$+$r;XDj$G$-$k\e(B
+* To From Newsgroups::          \e$B<+J,<+?H$NL>A0$rI=<($7$J$$J}K!\e(B
+* Summary Buffer Mode Line::    \e$B%b!<%I9T$N8+$(J}$r7h$a$i$l$k\e(B
+* Summary Highlighting::        \e$B35N,%P%C%U%!$r$-$l$$$GAGE($K$9$k\e(B
+
+Choosing Articles
+
+* Choosing Commands::           \e$B5-;v$rA*Br$9$k$?$a$NL?Na\e(B
+* Choosing Variables::          \e$B$3$l$i$NL?Na$K1F6A$r5Z$\$9JQ?t\e(B
+
+Reply, Followup and Post
+
+* Summary Mail Commands::       \e$B%a!<%k$rAw$k\e(B
+* Summary Post Commands::       \e$B%K%e!<%9$rAw$k\e(B
+* Summary Message Commands::    \e$BB>$N%a%C%;!<%84XO"$NL?Na\e(B
+* Canceling and Superseding::
+
+Marking Articles
+
+* Unread Articles::             \e$BL$FI5-;v$X$N0u\e(B
+* Read Articles::               \e$B4{FI5-;v$X$N0u\e(B
+* Other Marks::                 \e$B9XFIEY$K1F6A$7$J$$0u\e(B
+
+Marking Articles
+
+* Setting Marks::               \e$B0u$NIU$1J}$H>C$7J}\e(B
+* Generic Mark Commands::       \e$B0u$r$I$N$h$&$K%+%9%?%^%$%:$9$k$+\e(B
+* Setting Process Marks::       \e$B8e$N<B9T$N$?$a$N5-;v$N0u$NIU$1J}\e(B
+
+Threading
+
+* Customizing Threading::       \e$BJQ992DG=$J%9%l%C%I$K1F6A$9$kJQ?t\e(B
+* Thread Commands::             \e$B35N,%P%C%U%!$G$N%9%l%C%I$K4p$E$$$?L?Na\e(B
+
+Customizing Threading
+
+* Loose Threads::               Gnus \e$B$,L5B+G{%9%l%C%I$r=8$a$FBg$-$J%9%l%C%I$K$9$kJ}K!\e(B
+* Filling In Threads::          \e$B%9%l%C%I$rKd$a$k\e(B
+* More Threading::              \e$B%9%l%C%I$r$$$8$/$k$5$i$KB?$/$NJQ?t\e(B
+* Low-Level Threading::         \e$B$3$l$G=*$o$C$?$H;W$C$?$G$7$g$&\e(B@dots{} \e$B$G$b$"$J$?$O4V0c$C$F$$$?\e(B!
+
+Decoding Articles
+
+* Uuencoded Articles::          \e$B5-;v$r\e(B uuencode \e$B$9$k\e(B
+* Shell Archives::              shar \e$B5-;v$r2rE`$9$k\e(B
+* PostScript Files::            \e$B%]%9%H%9%/%j%W%H$rJ,3d$9$k\e(B
+* Other Files::                 \e$BIaDL$NJ]B8$H\e(B binhex.
+* Decoding Variables::          \e$B9,$;$JI|9f2=$N$?$a$NJQ?t\e(B
+* Viewing Files::               \e$BI|9f2=$N7k2L$r8+$?$$\e(B?
+
+Decoding Variables
+
+* Rule Variables::              \e$B%U%!%$%k$,$I$N$h$&$KI=<($5$l$k$+$r7h$a$kJQ?t\e(B
+* Other Decode Variables::      \e$BB>$NI|9f2=$NJQ?t\e(B
+* Uuencoding and Posting::      uuencode \e$B$9$k$N$r%+%9%?%^%$%:$9$kJQ?t\e(B
+
+Article Treatment
+
+* Article Highlighting::        \e$B5-;v$r2LJ*%5%i%@$N$h$&$K8+$($k$h$&$K$7$?$$\e(B
+* Article Fontisizing::         \e$B6/D4$5$l$?J8$rAGE($K$9$k\e(B
+* Article Hiding::              \e$BFCDj$N>pJs$O>C$75n$j$?$$$H$b;W$&\e(B
+* Article Washing::             \e$B?M@8$r$b$C$H$h$/$9$k$?$/$5$s$N5$$NMx$$$?4X?t\e(B
+* Article Header::              \e$B%X%C%@!<$r$$$m$$$mJQ7A$5$;$k\e(B
+* Article Buttons::             URL \e$B$d\e(B Message-ID \e$B$d%"%I%l%9$J$I$r%/%j%C%/$9$k\e(B
+* Article Button Levels::       \e$B%\%?%s$N8+$(J}$r@)8f$9$k\e(B
+* Article Date::                \e$B$0$:$0$:8@$&$J!"@$3&;~$@\e(B!
+* Article Display::             X-Face, Picons, Smileys \e$B$rI=<($9$k\e(B
+* Article Signature::           \e$B=pL>$C$F2?\e(B?
+* Article Miscellanea::         \e$BB>$N$$$m$$$m$J$b$N\e(B
+
+Alternative Approaches
+
+* Pick and Read::               \e$B$^$:!"5-;v$K0u$rIU$1$F!"$=$l$+$iFI$`\e(B
+* Binary Groups::               \e$B$9$Y$F$N5-;v$r<+F0\e(B-\e$BI|9f2=$9$k\e(B
+
+Various Summary Stuff
+
+* Summary Group Information::   \e$B>pJs;X8~$NL?Na\e(B
+* Searching for Articles::      \e$BJ#?t5-;vL?Na\e(B
+* Summary Generation Commands::
+* Really Various Summary Commands::  \e$B$"$N$d$C$+$$$JB>$KE,9g$7$J$$L?Na\e(B
+
+Article Buffer
+
+* Hiding Headers::              \e$B$I$N%X%C%@!<$rI=<($9$k$+$r7h$a$k\e(B
+* Using MIME::                  @acronym{MIME} \e$B5-;v$H$7$F8+$;$k\e(B
+* Customizing Articles::        \e$B5-;v$N8+1I$($r;EN)$F$k\e(B
+* Article Keymap::              \e$B5-;v%P%C%U%!$G;H$($k%-!<A`:n\e(B
+* Misc Article::                \e$B$=$NB>\e(B
+
+Composing Messages
+
+* Mail::                        \e$B%a!<%k$HJVEz\e(B
+* Posting Server::              \e$B$I$N%5!<%P!<$rDL$7$F%K%e!<%9$rEj9F$^$?$O%a!<%k$rAw?.$9$k$Y$-$+\e(B?
+* Mail and Post::               \e$BF1;~$K%a!<%k$r=P$7JVEz$9$k\e(B
+* Archived Messages::           \e$BAw$C$?%a%C%;!<%8$r\e(B gnus \e$B$,Cy$a$F$*$/$H$3$m\e(B
+* Posting Styles::              \e$B$"$J$?$,C/$G$"$k$+$r;XDj$9$k$h$j4JC1$JJ}K!\e(B
+* Drafts::                      \e$B%a%C%;!<%8$N1d4|$H5qH]$5$l$?%a%C%;!<%8\e(B
+* Rejected Articles::           \e$B%5!<%P!<$,$"$J$?$N5-;v$r9%$-$G$J$$$H$-$K2?$,5/$3$k\e(B?
+@c * Signing and encrypting::      How to compose secure messages.
+
+Select Methods
+
+* Server Buffer::               \e$B;v<B>e$N%5!<%P!<$r:n$C$FJT=8$9$k\e(B
+* Getting News::                USENET \e$B%K%e!<%9$r\e(B gnus \e$B$GFI$`\e(B
+* Getting Mail::                \e$B8D?ME*$J%a!<%k$r\e(B gnus \e$B$GFI$`\e(B
+* Browsing the Web::            \e$B2a>j$J%&%'%V$N;q8;$+$i%a%C%;!<%8$r<hF@$9$k\e(B
+* IMAP::                        gnus \e$B$r\e(B @acronym{IMAP} \e$B$N%/%i%$%"%s%H$H$7$F;H$&\e(B
+* Other Sources::               \e$B%G%#%l%/%H%j!<!"%U%!%$%k!"\e(BSOUP \e$B%Q%1%C%H$rFI$`\e(B
+* Combined Groups::             \e$BJ#?t$N%0%k!<%W$r0l$D$N%0%k!<%W$K7k9g$9$k\e(B
+* Gnus Unplugged::              \e$B%K%e!<%9$H%a!<%k$r%*%U%i%$%s$GFI$`\e(B
+
+Server Buffer
+
+* Server Buffer Format::        \e$B$3$N%P%C%U%!$N308+$r%+%9%?%^%$%:$G$-$k\e(B
+* Server Commands::             \e$B%5!<%P!<$rA`$kL?Na\e(B
+* Example Methods::             \e$B%5!<%P!<;XDj$NNc\e(B
+* Creating a Virtual Server::   \e$B%;%C%7%g%s$NNc\e(B
+* Server Variables::            \e$B$I$NJQ?t$r@_Dj$9$k$+\e(B
+* Servers and Methods::         \e$B%5!<%P!<L>$rA*BrJ}K!$H$7$F;H$&;v$,$G$-$k\e(B
+* Unavailable Servers::         \e$B@\B3$7$h$&$H;n$_$?%5!<%P!<$N$$$/$D$+$,Mn$A$F$$$k$+$b$7$l$J$$\e(B
+
+Getting News
+
+* NNTP::                        @acronym{NNTP} \e$B%5!<%P!<$+$i%K%e!<%9$rFI$`\e(B
+* News Spool::                  \e$B%m!<%+%k%9%W!<%k$+$i%K%e!<%9$rFI$`\e(B
+
+@acronym{NNTP}
+
+* Direct Functions::            \e$B%5!<%P!<$KD>@\@\B3$9$k\e(B
+* Indirect Functions::          \e$B%5!<%P!<$K4V@\E*$K@\B3$9$k\e(B
+* Common Variables::            \e$B$$$/$D$+$N@\B3MQ$N4X?t$,;2>H$9$kJQ?t\e(B
+
+Getting Mail
+
+* Mail in a Newsreader::        \e$B%K%e!<%9%j!<%@$G%a!<%k\e(B (\e$BBg;v$JA0CV$-\e(B)
+* Getting Started Reading Mail::  \e$B4JC1$JNAM}K\$N$h$&$JNc\e(B
+* Splitting Mail::              \e$B$I$N$h$&$K%a!<%k%0%k!<%W$r:n@.$9$k$+\e(B
+* Mail Sources::                Gnus \e$B$K$I$3$+$i%a!<%k$r<h$C$F$/$k$+$rCN$i$;$k\e(B
+* Mail Back End Variables::     \e$B%a!<%k$N07$$$r%+%9%?%^%$%:$9$k$?$a$NJQ?t\e(B
+* Fancy Mail Splitting::        Gnus \e$B$OF~$C$FMh$?%a!<%k$r!"?H$NLS$N$h$@$D$h$&$JJ,3d$r$9$k$3$H$,$G$-$k\e(B
+* Group Mail Splitting::        \e$B%a!<%kJ,3d$r6nF0$9$k$?$a$K%0%k!<%W%+%9%?%^%$%:$r;H$&\e(B
+* Incorporating Old Mail::      \e$B$"$J$?$,;}$C$F$$$k8E$$%a!<%k$r$I$&$9$k$+\e(B?
+* Expiring Mail::               \e$BM_$7$/$J$$%a!<%k$r<h$j=|$/\e(B
+* Washing Mail::                \e$B<hF@$7$?%a!<%k$+$iMW$i$J$$$b$N$r<h$j=|$/\e(B
+* Duplicates::                  \e$B=EJ#$7$?%a!<%k$r07$&\e(B
+* Not Reading Mail::            \e$BB>$N%U%!%$%k$rFI$`$?$a$K%a!<%k%P%C%/%(%s%I$r;H$&\e(B
+* Choosing a Mail Back End::    Gnus \e$B$O?'!9$J%a!<%kMM<0$rFI$`;v$,$G$-$k\e(B
+
+Mail Sources
+
+* Mail Source Specifiers::      \e$B%a!<%k$N85$,$I$3$+$r;XDj$9$k\e(B
+* Mail Source Customization::   \e$B@$$NCf$K1F6A$9$k$$$/$D$+$NJQ?t\e(B
+* Fetching Mail::               \e$B%a!<%k%=!<%9;X<(;R$r;HMQ$9$k\e(B
+
+Choosing a Mail Back End
+
+* Unix Mail Box::               (\e$B$H$F$b\e(B) \e$BI8=`E*$J\e(B Un*x mbox \e$B$r;H$&\e(B
+* Rmail Babyl::                 Emacs \e$B$N%W%m%0%i%`$O\e(B Rmail \e$B$N\e(B Babyl \e$B%U%)!<%^%C%H$r;H$&\e(B
+* Mail Spool::                  \e$B$"$J$?$N%a!<%k$r;dE*$J%9%W!<%k$KN/$a$k\e(B?
+* MH Spool::                    mhspool \e$B$N$h$&$J%P%C%/%(%s%I\e(B
+* Maildir::                     \e$B$b$&0l$D$N#1%U%!%$%k\e(B/\e$B#1%a%C%;!<%87A<0\e(B
+* Mail Folders::                \e$B$=$l$>$l$N%0%k!<%W$KBP$7$F0l$D$N%U%!%$%k$r;}$D\e(B
+* Comparing Mail Back Ends::    \e$BF@<:$N?<$$F6;!\e(B
+
+Browsing the Web
+
+* Archiving Mail::
+* Web Searches::                \e$BJ8;zNs$K%^%C%A$9$k5-;v$+$i%0%k!<%W$r:n$k\e(B
+* Slashdot::                    Slashdot \e$B$N%3%a%s%H$rFI$`\e(B
+* Ultimate::                    Ultimate Bulletin Board \e$B%7%9%F%`\e(B
+* Web Archive::                 \e$B%&%'%V$KJ]4I$5$l$?%a!<%j%s%0%j%9%H$rFI$`\e(B
+* Web Newspaper::               \e$B%&%'%V$KJ]4I$5$l$??7J9$rFI$`\e(B
+* RSS::                         RDF Site Summary \e$B$rFI$`\e(B
+* Customizing w3::              Gnus \e$B$+$i\e(B Emacs/W3 \e$B$rA`:n$9$k\e(B
+
+@acronym{IMAP}
+
+* Splitting in IMAP::           nnimap \e$B$G%a!<%k$rJ,3d$9$k\e(B
+* Expiring in IMAP::            nnimap \e$B$K$h$k%a!<%k$N4|8B@Z$l>C5n\e(B
+* Editing IMAP ACLs::           \e$B%a!<%k%\%C%/%9$X$NB>$NMxMQ<T$N;HMQ$r@)8B\e(B/\e$B5v2D$9$k\e(B
+* Expunging mailboxes::         ``\e$B%a!<%k%\%C%/%905=L\e(B'' \e$B%\%?%s$HEy2A$J$b$N\e(B
+* A note on namespaces::        gnus \e$B$G\e(B @acronym{IMAP} \e$BL>A06u4V$r;H$&\e(B(\e$B;H$o$J$$\e(B)\e$BJ}K!\e(B
+* Debugging IMAP::              \e$B$b$N$4$H$,F/$+$J$$$H$-$K$9$k$Y$-$3$H\e(B
+
+Other Sources
+
+* Directory Groups::            \e$B%G%#%l%/%H%j!<$r%K%e!<%9%0%k!<%W$N$h$&$KFI$`\e(B
+* Anything Groups::             Dired?  \e$BC/$,\e(B dired \e$B$J$s$F;H$&$N\e(B?
+* Document Groups::             \e$B8DJL$N%U%!%$%k72$O%0%k!<%W$NAG\e(B
+* SOUP::                        @sc{soup} \e$B%Q%1%C%H$r\e(B ``\e$B%*%U%i%$%s\e(B'' \e$B$GFI$`\e(B
+* Mail-To-News Gateways::       \e$B%a!<%k$+$i%K%e!<%9$X$N%2!<%H%&%'%$$rDL$7$F5-;v$rEj9F$9$k\e(B
+
+Document Groups
+
+* Document Server Internals::   \e$B$"$J$?FH<+$NJ8=q<oJL$rDI2C$9$kJ}K!\e(B
+
+SOUP
+
+* SOUP Commands::               @sc{soup} \e$B%Q%1%C%H$r:n@.!"Aw=P$9$kL?Na\e(B
+* SOUP Groups::                 @sc{soup} \e$B%Q%1%C%H$rFI$`%P%C%/%(%s%I\e(B
+* SOUP Replies::                @code{nnsoup} \e$B$K%a!<%k$H%K%e!<%9$r0z$-7Q$,$;$kJ}K!\e(B
+
+Combined Groups
+
+* Virtual Groups::              \e$B$?$/$5$s$N%0%k!<%W$N5-;v$r7k9g$9$k\e(B
+* Kibozed Groups::              \e$B%K%e!<%9%9%W!<%k$NCf$+$i$N5-;v$r8!:w$9$k\e(B
+
+Gnus Unplugged
+
+* Agent Basics::                \e$B$3$l$i$O$I$&F0$/$N$+\e(B
+* Agent Categories::            \e$B2?$r%@%&%s%m!<%I$9$k$+$r\e(B gnus \e$B%(!<%8%'%s%H$K65$($kJ}K!\e(B
+* Agent Commands::              \e$B3F%P%C%U%!!<$G$N?7$7$$L?Na\e(B
+* Agent Visuals::               \e$B%(!<%8%'%s%H$,35N,%P%C%U%!$KJQ2=$r$b$?$i$9$+$b$7$l$J$$J}K!\e(B
+* Agent as Cache::              \e$B%(!<%8%'%s%H$OBg$-$J%-%c%C%7%e$G$b$"$k\e(B
+* Agent Expiry::                \e$B8E$$5-;v$r>C$9J}K!\e(B
+* Agent Regeneration::          \e$BDL?.@ZCG$dB>$N;v8N$+$i2sI|$9$kJ}K!\e(B
+* Agent and IMAP::              \e$B%(!<%8%'%s%H$r\e(B @acronym{IMAP} \e$B$G;H$&J}K!\e(B
+* Outgoing Messages::           \e$BEj9F!"%a!<%k$r=P$9$H$-$K$J$K$,5/$3$k$N$+\e(B?
+* Agent Variables::             \e$B%+%9%?%^%$%:$O3Z$7\e(B
+* Example Setup::               \e$B%*%U%i%$%s?M4V$N$?$a$N\e(B @file{~/.gnus.el} \e$B$NNc\e(B
+* Batching Agents::             @code{cron} \e$B%8%g%V$K$h$k%K%e!<%9<hF@J}K!\e(B
+* Agent Caveats::               \e$B$"$J$?$,M=A[$9$k$3$H$H!"$=$l$,<B:]$K$9$k$3$H\e(B
+* Control Agents::              Offline \e$B$r%3%s%H%m!<%k$9$k\e(B gnus-offline
+
+Agent Categories
+
+* Category Syntax::             \e$BJ,N`$H$O$I$s$J$b$N$+\e(B
+* Category Buffer::             \e$BJ,N`$r4IM}$9$k%P%C%U%!!<\e(B
+* Category Variables::          \e$B%+%9%?%^%$%6\e(B"\e$B$i\e(B"\e$B%9\e(B
+
+Agent Commands
+
+* Group Agent Commands::        \e$B%0%k!<%W$N@_Dj$H$=$l$i$NFbMF$N<hF@\e(B
+* Summary Agent Commands::      \e$B<jF0$GA*Br$7$?5-;v$r<hF@$9$k\e(B
+* Server Agent Commands::       \e$B%(!<%8%'%s%H$G%5%]!<%H$5$l$k%5!<%P!<$NA*Br\e(B
+
+Scoring
+
+* Summary Score Commands::      \e$B8=:_$N%0%k!<%W$N$?$a$N%9%3%"EPO?$rDI2C$9$k\e(B
+* Group Score Commands::        \e$B0lHLE*$J%9%3%"L?Na\e(B
+* Score Variables::             \e$B$"$J$?$N%9%3%"$r%+%9%?%^%$%:$9$k\e(B (\e$B$^$!!"$J$s$FMQ8l\e(B (Scoring) \e$B$G$7$g$&\e(B)
+* Score File Format::           \e$B%9%3%"%U%!%$%k$K2?$rF~$l$k$+\e(B
+* Score File Editing::          \e$B<j$G%9%3%"%U%!%$%k$rJT=8$9$k;v$b$G$-$k\e(B
+* Adaptive Scoring::            \e$BBg;P\e(B (Big Sister) Gnus \e$B$O$"$J$?$,2?$rFI$s$@$+CN$C$F$$$k\e(B
+* Home Score File::             \e$B?7$7$$%9%3%"EPO?$,$I$3$X9T$/$+$r$I$N$h$&$K;XDj$9$k$+\e(B
+* Followups To Yourself::       \e$B?M$,$"$J$?$KJVEz$7$?$H$-$K\e(B gnus \e$B$K5$IU$+$;$k\e(B
+* Scoring On Other Headers::    \e$BI8=`$G$O$J$$%X%C%@!<$K%9%3%"$rIU$1$k\e(B
+* Scoring Tips::                \e$B$I$&$d$C$F8z2LE*$K%9%3%"$rIU$1$k$+\e(B
+* Reverse Scoring::             \e$B8E$$$b$N$N;R$G$"$k$H$$$&LdBj$OLdBj$G$O$J$$\e(B
+* Global Score Files::          \e$BCO$r$D$+$_!"<*$r@Z$jNv$/%9%3%"%U%!%$%k\e(B
+* Kill Files::                  \e$B$=$l$i$O$^$@$3$3$K$"$k$,!"L5;k$9$k;v$,$G$-$k\e(B
+* Converting Kill Files::       \e$B>C5n%U%!%$%k$r%9%3%"%U%!%$%k$KJQ49$9$k\e(B
+* GroupLens::                   \e$B$I$l$rFI$`$N$,9%$-$+$NM=8@$rF@$k\e(B
+* Advanced Scoring::            \e$B%9%3%"$NK!B'$r:n$k$?$a$KO@M}I=8=$r;H$&\e(B
+* Score Decays::                \e$B%9%3%"$r8O$l$F$$$+$;$k$N$OLr$KN)$D;v$b$"$k\e(B
+
+GroupLens
+
+* Using GroupLens::             \e$B$I$N$h$&$K\e(B gnus \e$B$K\e(B GroupLens \e$B$r;H$o$;$k$h$&$K$9$k$+\e(B
+* Rating Articles::             GropLens \e$B$K$"$J$?$,$I$N$h$&$KCM$rIU$1$k$+$rCN$i$;$k\e(B
+* Displaying Predictions::      GropuLens \e$B$K$h$C$FM?$($i$l$?M=8@$rI=<($9$k\e(B
+* GroupLens Variables::         GoupLens \e$B$r%+%9%?%^%$%:$9$k\e(B
+
+Advanced Scoring
+
+* Advanced Scoring Syntax::     \e$BDj5A\e(B
+* Advanced Scoring Examples::   \e$B$I$N$h$&$K8+$($k$+\e(B
+* Advanced Scoring Tips::       \e$B$=$l$r:GBg8BMxMQ$9$k\e(B
+
+Various
+
+* Process/Prefix::              \e$BB?$/$N07$$L?Na$G;H$o$l$k=,47\e(B
+* Interactive::                 Gnus \e$B$KB?$/$N<ALd$r?R$M$5$;$k\e(B
+* Symbolic Prefixes::           \e$B$$$/$D$+$N\e(B gnus \e$B$N4X?t$KA*Br8"$rDs6!$9$kJ}K!\e(B
+* Formatting Variables::        \e$B%P%C%U%!$,$I$N$h$&$K8+$($k$Y$-$+$r;XDj$9$k;v$,$G$-$k\e(B
+* Window Layout::               Gnus \e$B%P%C%U%!%&%#%s%I%&$r@_Dj$9$k\e(B
+* Faces and Fonts::             \e$B%U%'%$%9$,$I$N$h$&$K8+$($k$+$rJQ99$9$k\e(B
+* Compilation::                 \e$B$I$N$h$&$K$7$F\e(B gnus \e$B$NB.EY$r>e$2$k$+\e(B
+* Mode Lines::                  \e$B%b!<%I9T$K>pJs$rI=<($9$k\e(B
+* Highlighting and Menus::      \e$B%P%C%U%!$rAGE($G?4CO$h$/8+$;$k\e(B
+* Buttons::                     \e$B4JC1$J==Jb$G%"%-%l%9g'$rF@$k\e(B
+* Daemons::                     Gnus \e$B$O$"$J$?$NN"$GJ*;v$r<B9T$9$k;v$,$G$-$k\e(B
+* NoCeM::                       Spam \e$B$dB>$NB@$j$d$9$$?);v$rHr$1$kJ}K!\e(B
+* Undo::                        \e$B$$$/$D$+$NF0:n$O85$KLa$9;v$,$G$-$k\e(B
+* Predicate Specifiers::        \e$B=R8l$r@_Dj$9$k\e(B
+* Moderation::                  \e$B$"$J$?$,%b%G%l!<%?!<$@$C$?$i$I$&$9$k$+\e(B
+* Image Enhancements::          \e$B:G?7$N\e(B Emacs/XEmacs \e$B$O3($rI=<($G$-$k\e(B
+* Fuzzy Matching::              \e$BBg$-$JLJLS$C$F2?\e(B?
+* Thwarting Email Spam::        \e$BM>7W$J>&6HE*EE;R%a!<%k$rHr$1$kJ}K!\e(B
+* Other modes::                 \e$BB>$N%b!<%I$H$NAj8_:nMQ\e(B
+* Various Various::             \e$BK\Ev$K$$$m$$$m$J$b$N\e(B
+
+Formatting Variables
+
+* Formatting Basics::           \e$B=qK!;EMMJQ?t$O4pK\E*$K=qK!;XDjJ8;zNs$G$"$k\e(B
+* Mode Line Formatting::        \e$B%b!<%I9T$N=qK!;EMMJQ?t$K4X$9$k$$$/$D$+$N5,B'\e(B
+* Advanced Formatting::         \e$B?'!9$JJ}K!$G=PNO$r=$@5$9$k\e(B
+* User-Defined Specs::          Gnus \e$B$K$"$J$?<+?H$N4X?t$r8F$P$;$k\e(B
+* Formatting Fonts::            \e$B;EMM$rB?:L$GAGE($K8+$;$k\e(B
+* Positioning Point::           \e$BA`:n$N8e$G%]%$%s%H$r0\F0$9$k\e(B
+* Tabulation::                  \e$B=PNO$N@0Ns\e(B
+* Wide Characters::             \e$BI}$,9-$$J8;z$r07$&\e(B
+
+Image Enhancements
+
+* X-Face::                      \e$B%U%!%s%-!<$J$A$C$A$c$JGr9u$N3($rI=<($9$k\e(B
+* Face::                        \e$B$h$j%U%!%s%-!<$G$A$C$A$c$J%+%i!<$N3($rI=<($9$k\e(B
+* Smileys::                     \e$BI=<($5$l$k$Y$/@8$^$l$?9,$;$=$&$J4i$rI=<($9$kJ}K!\e(B
+* Picons::                      \e$B$"$J$?$,FI$s$G$$$k$b$N$N3($rI=<($9$kJ}K!\e(B
+* XVarious::                    \e$B$=$NB>$N\e(B XEmacs \e$B$G\e(B Gnus \e$B$JJQ?t\e(B
+
+Thwarting Email Spam
+
+* The problem of spam::         \e$BGX7J!"$=$7$F2r7h\e(B
+* Anti-Spam Basics::            \e$B$?$/$5$s$N\e(B spam \e$B$r8:$i$94JC1$JJ}K!\e(B
+* SpamAssassin::                Spam \e$BBP:v%D!<%k$N;H$$J}\e(B
+* Hashcash::                    CPU \e$B;~4V$rHq$d$7$F\e(B spam \e$BB`<#$9$k\e(B
+* Filtering Spam Using The Spam ELisp Package::
+* Filtering Spam Using Statistics with spam-stat::
+
+Filtering Spam Using The Spam ELisp Package
+
+* Spam ELisp Package Sequence of Events::
+* Spam ELisp Package Filtering of Incoming Mail::
+* Spam ELisp Package Global Variables::
+* Spam ELisp Package Configuration Examples::
+* Blacklists and Whitelists::
+* BBDB Whitelists::
+* Gmane Spam Reporting::
+* Anti-spam Hashcash Payments::
+* Blackholes::
+* Regular Expressions Header Matching::
+* Bogofilter::
+* ifile spam filtering::
+* spam-stat spam filtering::
+* SpamOracle::
+* Extending the Spam ELisp package::
+
+Filtering Spam Using Statistics with spam-stat
+
+* Creating a spam-stat dictionary::
+* Splitting mail using spam-stat::
+* Low-level interface to the spam-stat dictionary::
+
+Appendices
+
+* XEmacs::                      XEmacs \e$B$G%$%s%9%H!<%k$9$k$?$a$NMW7o\e(B
+* History::                     \e$B$I$&$d$C$F\e(B gnus \e$B$,:#F|$N$h$&$K$J$C$?$+\e(B
+* On Writing Manuals::          \e$B$J$<$3$l$,=i?4<TMQ$N0FFb$G$J$$$+\e(B
+* Terminology::                 \e$B2f!9$OK\Ev$KFq$7$$!"8l$N$h$&$J8l$r;H$&\e(B
+* Customization::               \e$B$"$J$?$NMW5a$K1h$C$F\e(B gnus \e$B$r;EN)$F$k\e(B
+* Troubleshooting::             \e$B>e<j$/9T$+$J$+$C$?$H$-$K;n$9$+$b$7$l$J$$$3$H\e(B
+* Gnus Reference Guide::        \e$B?'!9$J5;=QE*$J$b$N\e(B
+* Emacs for Heathens::          Emacs \e$B$NMQ8l$N<jC;$JF3F~\e(B
+* Frequently Asked Questions::  Gnus \e$B$N\e(B FAQ
+
+History
+
+* Gnus Versions::               \e$B$I$s$J%P!<%8%g%s$N\e(B Gnus \e$B$,%j%j!<%9$5$l$F$$$k$+\e(B
+* Other Gnus Versions::         \e$B%j%j!<%9$5$l$F$$$kB>$N%P!<%8%g%s$N\e(B Gnus
+* Why?::                        Gnus \e$B$NL\E*$O2?\e(B?
+* Compatibility::               Gnus \e$B$O\e(B @sc{gnus} \e$B$H$I$l$/$i$$8_49@-$,$"$k$N\e(B?
+* Conformity::                  Gnus \e$B$OA4$F$NI8=`$rK~$?$=$&$H$9$k\e(B
+* Emacsen::                     Gnus \e$B$O$$$/$D$+$N8=BeE*$J\e(B Emacs \e$B4D6-$G<B9T$G$-$k\e(B
+* Gnus Development::            Gnus \e$B$,3+H/$5$l$F$$$kJ}K!\e(B
+* Contributors::                \e$BBgNL$N?M!9\e(B
+* New Features::                Gnus \e$B$N?7$7$$;v$K4X$9$k<j$,$+$j\e(B
+
+New Features
+
+* ding Gnus::                   \e$B:G=i$N?7$7$$\e(B Gnus \e$B$G$"$k\e(B Gnus 5.0/5.1 \e$B$N?7$7$$;v\e(B
+* September Gnus::              \e$B8x<0$K\e(B Gnus 5.2/5.3 \e$B$H$7$FCN$i$l$F$$$k$b$N\e(B
+* Red Gnus::                    \e$B;0HVL\$N:G>e$N$b$N\e(B---Gnus 5.4/5.5
+* Quassia Gnus::                2 \e$B$+$1$k\e(B 2 \e$B$O\e(B 4\e$B!"$b$7$/$O\e(B Gnus 5.6/5.7
+* Pterodactyl Gnus::            \e$B8^HVL\!"\e(BP \e$B$G;O$^$k!"$b$7$/$O\e(B Gnus 5.8/5.9 \e$B$H$7$FCN$i$l$F$$$k$b$N\e(B
+* Oort Gnus::                   \e$B5pBg$J!#1s$/MZ$+$J!#\e(BGnus 5.10\e$B!#\e(B
+
+Customization
+
+* Slow/Expensive Connection::   \e$B%m!<%+%k$N\e(B Emacs \e$B$rN)$A>e$2$F!"B>$N$H$3$m$+$i%K%e!<%9$rF@$k;v$,$G$-$k\e(B
+* Slow Terminal Connection::    \e$B1s3V\e(B Emacs \e$B$r<B9T$9$k\e(B
+* Little Disk Space::           \e$BBg$-$J5/F0%U%!%$%k$r;}$D;v$O$^$:$$\e(B
+* Slow Machine::                \e$BB.$$5!3#$rGc$*$&$H46$8$k$G$"$m$&\e(B
+
+Gnus Reference Guide
+
+* Gnus Utility Functions::      \e$B;HMQ$G$-$k6&DL$N4X?t$HJQ?t\e(B
+* Back End Interface::          Gnus \e$B$O$I$&$d$C$F%5!<%P!<$HDL?.$9$k$N$+\e(B
+* Score File Syntax::           \e$B%9%3%"%U%!%$%k5,3J$N\e(B BNF \e$BDj5A\e(B
+* Headers::                     Gnus \e$B$O%X%C%@!<$rFbItE*$K$I$N$h$&$K3JG<$9$k$+\e(B
+* Ranges::                      \e$B$?$/$5$s$N?t$r3JG<$9$kJXMx$J7A<0\e(B
+* Group Info::                  \e$B%0%k!<%W>pJs7A<0\e(B
+* Extended Interactive::        \e$B5-9f@\F,<-$J$I\e(B
+* Emacs/XEmacs Code::           Gnus \e$B$OA4$F$N6aBe\e(B Emacsen \e$B$GF0:n$9$k\e(B
+* Various File Formats::        Gnus \e$B$N;HMQ$9$k%U%!%$%k$N7A<0\e(B
+
+Back End Interface
+
+* Required Back End Functions::  \e$B<BAu$7$J$1$l$P$J$i$J$$4X?t\e(B
+* Optional Back End Functions::  \e$B<BAu$7$J$/$F$b$h$$4X?t\e(B
+* Error Messaging::             \e$B%a%C%;!<%8$d%(%i!<Js9p$rF@$kJ}K!\e(B
+* Writing New Back Ends::       \e$B8E$$%P%C%/%(%s%I$N3HD%\e(B
+* Hooking New Back Ends Into Gnus::  Gnus \e$BB&$G$7$J$1$l$P$J$i$J$$$3$H\e(B
+* Mail-like Back Ends::         \e$B%a!<%kIw%P%C%/%(%s%I$N$?$a$N=u8@\e(B
+
+Various File Formats
+
+* Active File Format::          \e$B;HMQ2DG=$J5-;v%0%k!<%W$N>pJs\e(B
+* Newsgroups File Format::      \e$B%0%k!<%W$N5-=R\e(B
+
+Emacs for Heathens
+
+* Keystrokes::                  \e$BJ8>O$rF~NO$7$FL?Na$r<B9T$9$k\e(B
+* Emacs Lisp::                  \e$BHw$(IU$1$N\e(B Emacs \e$B%W%m%0%i%_%s%08@8l\e(B
+
+@end detailmenu
+@end menu
+
+@node Starting Up
+@chapter gnus \e$B$N5/F0\e(B
+@cindex starting up
+
+@kindex M-x gnus
+@findex gnus
+\e$B%7%9%F%`4IM}<T$,E,@Z$J@_Dj$r$7$F$$$?$J$i$P!"\e(Bgnus \e$B$r5/F0$7$F%K%e!<%9$rFI\e(B
+\e$B$`$N$OHs>o$K4JC1$G$9!#$=$&!"\e(BEmacs \e$B$G\e(B @kbd{M-x gnus} \e$B$HBG$D$@$1$G$9!#\e(B
+
+@findex gnus-other-frame
+@kindex M-x gnus-other-frame
+\e$BJL$N%U%l!<%`\e(B (frame) \e$B$G\e(B gnus \e$B$r5/F0$7$?$$$H$-$O!"L?\e(B
+\e$BNa\e(B @kbd{M-x gnus-other-frame} \e$B$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+\e$B3+;O;~$K2?$+$,$&$^$/$$$+$J$$$H$-$O\e(B @file{~/.gnus.el} \e$B%U%!%$%k$NCf$GJQ?t\e(B
+\e$B$r$$$/$D$+$$$8$/$j$^$o$5$J$1$l$P$J$i$J$$$G$7$g$&!#$3$N%U%!%$%k\e(B
+\e$B$O\e(B @file{~/.emacs} \e$B$H;w$F$$$^$9$,!"$3$A$i$O\e(B gnus \e$B$,5/F0$9$k$H$-$KFI$_9~\e(B
+\e$B$^$l$^$9!#\e(B
+
+\e$B$3$N@bL@=q$G$h$/$o$+$i$J$$MQ8l$,$G$F$-$?$H$-$O!"MQ8l$N\e(B
+\e$B9`\e(B (@pxref{Terminology}) \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@menu
+* Finding the News::            \e$B%K%e!<%9$r<hF@$9$kJ}K!$rA*$V\e(B
+* The First Time::              \e$B:G=i$K5/F0$7$?$H$-$K\e(B gnus \e$B$O2?$r$9$k$+\e(B
+* The Server is Down::          \e$B$I$&$9$l$P$=$N$h$&$J$H$-$K%a!<%k$r<j$KF~$l$k$3$H$,$G$-$k$+\e(B
+* Slave Gnusae::                \e$BF1;~$K0l$D0J>e$N\e(B gnus \e$B$r:nF0$5$;$k$3$H$,$G$-$k\e(B
+* Fetching a Group::            \e$B%0%k!<%W$rFI$`$?$a$@$1$K\e(B gnus \e$B$r5/F0$9$k\e(B
+* New Groups::                  Gnus \e$B$,?7$7$$%0%k!<%W$KBP$7$F2?$r$9$k$+\e(B
+* Changing Servers::            \e$B$"$k%5!<%P$+$iJL$N%5!<%P$X0\$j$?$$$+$b$7$l$J$$\e(B
+* Startup Files::               \e$B$d$C$+$$$J%9%?!<%H%"%C%W%U%!%$%k\e(B -- @file{.newsrc}
+* Auto Save::                   \e$B%/%i%C%7%e$+$i$N2sI|\e(B
+* The Active File::             \e$BCY$$2s@~$+$i$N%U%!%$%k$N<hF@$K$O;~4V$,$+$+$k\e(B
+* Startup Variables::           \e$BJQ99$7$?$$$H;W$&$+$b$7$l$J$$JQ?t\e(B
+@end menu
+
+@node Finding the News
+@section \e$B%K%e!<%9$r8+$D$1$k\e(B
+@cindex finding news
+
+@vindex gnus-select-method
+@c @head
+\e$BJQ?t\e(B @code{gnus-select-method} \e$B$O\e(B gnus \e$B$,$I$3$G%K%e!<%9$rC5$9$Y$-$+$r<(\e(B
+\e$B$7$^$9!#$3$NJQ?t$O$O$8$a$NMWAG$,\e(B @dfn{\e$BJ}K!\e(B}\e$B!"FsHVL\$NMWAG\e(B
+\e$B$,\e(B @dfn{\e$B>l=j\e(B} \e$B$rI=$9%j%9%H$G$"$kI,MW$,$"$j$^$9!#$3$NJ}K!$O$"$J$?$N4pK\J}\e(B
+\e$BK!\e(B (native method) \e$B$K$J$j$^$9!#$3$NJ}K!$G<h$C$F$3$J$$%0%k!<%W$OA4$F30\e(B
+\e$BIt\e(B (foreign) \e$B%0%k!<%W$G$9!#\e(B
+
+\e$B$?$H$($P!"\e(B@acronym{NNTP} \e$B%5!<%P!<\e(B @samp{news.somewhere.edu} \e$B$+$iKhF|\e(B (\e$BLt\e(B
+\e$B$N$h$&$K\e(B) \e$B0lDj$NNL$N%K%e!<%9$r@]<h$7$?$$$N$G$"$l$P!"\e(B
+
+@lisp
+(setq gnus-select-method '(nntp "news.somewhere.edu"))
+@end lisp
+
+@noindent
+\e$B$N$h$&$K$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B%m!<%+%k!&%9%W!<%k$N%G%#%l%/%H%j$rFI$_9~$_$?$$>l9g$O!"\e(B
+
+@lisp
+(setq gnus-select-method '(nnspool ""))
+@end lisp
+
+@noindent
+\e$B$N$h$&$K$G$-$^$9!#\e(B
+
+\e$B%m!<%+%k$N%9%W!<%k$r;H$($k$N$G$"$l$P!"$+$J$j$N3NN($G$=$NJ}$,$:$C$HB.$$$G\e(B
+\e$B$7$g$&$7!"$=$l$r;H$&$Y$-$G$7$g$&!#$G$b!"$b$7$"$J$?$N%5!<%P!<\e(B
+\e$B$,\e(B Leafnode \e$B$G$"$k$J$i$P%m!<%+%k%9%W!<%k$r;H$C$F$O$$$1$^$;$s!#$3$N>l9g\e(B
+\e$B$O\e(B @code{(nntp "localhost")} \e$B$K$7$^$7$g$&!#\e(B
+
+@vindex gnus-nntpserver-file
+@cindex NNTPSERVER
+@cindex @acronym{NNTP} server
+\e$B$b$7$3$NJQ?t$,@_Dj$5$l$F$$$J$1$l$P!"\e(Bgnus \e$B$O\e(B @env{NNTPSERVER} \e$B4D6-JQ?t$r\e(B
+\e$BFI$_$K$$$-$^$9!#$b$7$=$NJQ?t$,@_Dj$5$l$F$$$J$1$l$P!"\e(B
+gnus \e$B$O\e(B @code{gnus-nntpserver-file} (\e$B@_Dj$5$l$F$$$J$$>l9g\e(B
+\e$B$O\e(B @file{/etc/nntpserver}) \e$B$,$3$N7o$K4X$7$F2?$+$r8@$C$F$$$J$$$+$rD4$Y$^\e(B
+\e$B$9!#$b$7$=$l$b<:GT$7$?$J$i!"\e(Bgnus \e$B$O\e(B Emacs \e$B$,F0:n$7$F$$$k%5!<%P!<\e(B
+\e$B$r\e(B @acronym{NNTP} \e$B%5!<%P!<$H$7$F;H$*$&$H$7$^$9!#?oJ,$JEv$F?dNL$G$9$1$I$M!#\e(B
+
+@vindex gnus-nntp-server
+@code{gnus-nntp-server} \e$B$,@_Dj$5$l$F$$$k$H!"$3$NJQ?t\e(B
+\e$B$O\e(B @code{gnus-select-method} \e$B$r>e=q$-$7$^$9!#$G$9$+$i!"\e(B
+@code{gnus-nntp-server} \e$B$O\e(B @code{nil} \e$B$K@_Dj$9$k$Y$-$G!"=i4|@_Dj$G$b$=$N\e(B
+\e$B$h$&$K$J$C$F$$$^$9!#\e(B
+
+@vindex gnus-secondary-servers
+@vindex gnus-nntp-server
+Gnus \e$B$K\e(B @acronym{NNTP} \e$B%5!<%P!<$NL>A0$NF~NO$rBPOCE*$K;XDj$9$k$3$H$b$G$-\e(B
+\e$B$^$9!#\e(B@code{gnus} \e$B$K?tCM$G$J$$@\F,0z?t$rEO$9$H\e(B (\e$BNc\e(B: @kbd{C-u M-x gnus})\e$B!"\e(B
+gnus \e$B$O\e(B @code{gnus-secondary-servers} \e$B%j%9%H\e(B (\e$B$b$7B8:_$9$k$J$i$P\e(B) \e$B$+$i%5!<\e(B
+\e$B%P!<$rA*$V$3$H$,$G$-$k$h$&$K$7$^$9!#$?$@C1$K@\B3$7$?$$$H;W$C$?%5!<%P!<$N\e(B
+\e$BL>A0$rBG$D$3$H$b$G$-$^$9!#\e(B(\e$B$3$l$O\e(B @code{gnus-nntp-server} \e$B$r@_Dj$7!"$3$l\e(B
+\e$B$O8e$N\e(B Emacs \e$B$N%;%C%7%g%s$G\e(B @kbd{M-x gnus} \e$B$H$9$k$H!"\e(Bgnus \e$B$OF1$8%5!<%P!<\e(B
+\e$B$K@\B3$7$h$&$H$9$k$H$$$&$3$H$G$9!#\e(B)
+
+@findex gnus-group-browse-foreign-server
+@kindex B (\e$B%0%k!<%W\e(B)
+\e$B$7$+$7!"IaCJF|>oE*$K$O0l$D$N\e(B @acronym{NNTP} \e$B%5!<%P$r;H$$!"0c$C$?%5!<%P!<\e(B
+\e$B$K$O6=L#$N$"$k%0%k!<%W$,>/$7$7$+$J$$>l9g!"%0%k!<%W%P%C%U%!$G\e(B @kbd{B} \e$BL?\e(B
+\e$BNa$r;H$&$3$H$NJ}$,NI$$$G$7$g$&!#$=$l$O!"A*Br2DG=$J%0%k!<%W$rI=<($7!"$=$N\e(B
+\e$BCf$+$i$I$l$G$b9%$-$J$b$N$r9XFI$9$k$3$H$,$G$-$^$9!#$3$l\e(B
+\e$B$O\e(B @file{.newsrc} \e$B$NJ];}$r$:$C$H$d$j$d$9$/$7$^$9!#\e(B
+@xref{Foreign Groups, \e$B30It%0%k!<%W\e(B}.
+
+@vindex gnus-secondary-select-methods
+@c @head
+\e$B30It%0%k!<%W$KBP$9$k>/$70c$C$?$d$jJ}$O!"JQ\e(B
+\e$B?t\e(B @code{gnus-secondary-select-methods} \e$B$r@_Dj$9$kJ}K!$G$9!#$3$NJQ?t$KI=\e(B
+\e$B$5$l$F$$$kA*BrJ}K!$O!"B?$/$NE@$G\e(B @code{gnus-select-method} \e$B%5!<%P!<$NBr\e(B
+\e$BJ}K!$HF1$8$h$&$K07$o$l$^$9!#5/F0Cf$K%"%/%F%#%V%U%!%$%k$rC5$7$K$$$-\e(B (\e$B$b$7\e(B
+\e$BMW5a$5$l$F$$$l$P\e(B)\e$B!"$3$l$i$N%5!<%P!<>e$K$G$-$??7$7$$%K%e!<%9%0%k!<%W$O85!9\e(B
+\e$B$N%0%k!<%W$HF1$8$h$&$K9XFI\e(B (\e$B$b$7$/$OHs9XFI\e(B) \e$B$5$l$^$9!#\e(B
+
+\e$B$?$H$($P!"%a!<%k$rFI$`$?$a$K\e(B @code{nnmbox} \e$B%P%C%/%(%s%I\e(B (back end) \e$B$r;H\e(B
+\e$B$$$?$$$H$-$O!"IaDL!"$3$NJQ?t$r!"\e(B
+
+@lisp
+(setq gnus-secondary-select-methods '((nnmbox "")))
+@end lisp
+
+@noindent
+\e$B$H@_Dj$7$^$9!#\e(B
+
+@node The First Time
+@section \e$B0lHV=i$a\e(B
+@cindex first time usage
+
+\e$B5/F0MQ%U%!%$%k$,B8:_$7$J$$$H$-$O!"\e(Bgnus \e$B$O%G%#%U%)%k%H$G$I$N%0%k!<%W$,9X\e(B
+\e$BFI$5$l$F$$$k$Y$-$+$r7hDj$7$h$&$H$7$^$9!#\e(B
+
+@vindex gnus-default-subscribed-newsgroups
+\e$BJQ?t\e(B @code{gnus-default-subscribed-newsgroups} \e$B$,@_Dj$5$l$F$$$k$H!"\e(B
+gnus \e$B$O$=$N%j%9%H$NCf$N%0%k!<%W$r9XFI$7!";D$j$r:o=|$7$^$9!#%7%9%F%`4IM}\e(B
+\e$B<T$O$3$NJQ?t$r2?$+Lr$KN)$D$b$N$K@_Dj$7$F$*$/$3$H$,K>$^$l$^$9!#\e(B
+
+\e$B$=$&$G$J$$$H$-$O!"\e(Bgnus \e$B$O>/$7$NG$0U$N%0%k!<%W$r9XFI$7$^$9\e(B (\e$BNc\e(B:
+@samp{*.newusers})\e$B!#\e(B(@dfn{\e$BG$0U\e(B}\e$B$O$3$3$G$O!"\e(B@dfn{Lars \e$B$5$s$,FI$`$Y$-$G$"\e(B
+\e$B$k$H9M$($k$b$N\e(B}\e$B$H$$$&$h$&$KDj5A$5$l$F$$$^$9\e(B)
+
+\e$B$^$?!"$?$$$F$$$N6&DL$NLdBj$N2r7h$N<j=u$1$K$J$k$h$&!"\e(Bgnus \e$B$K4X$9$kJ8=q$N\e(B
+\e$B%0%k!<%W$b9XFI$9$k$3$H$K$J$k$G$7$g$&!#\e(B
+
+@code{gnus-default-subscribed-newsgroups} \e$B$,\e(B @code{t} \e$B$N$H$-$O!"\e(Bgnus \e$B$O\e(B
+\e$B?7$7$$%0%k!<%W$r07$&$N$KIaDL$N4X?t$r;H$$!"FCJL$J$3$H$O2?$b$7$^$;$s!#\e(B
+
+@node The Server is Down
+@section \e$B%5!<%P!<$,Mn$A$F$$$k\e(B
+@cindex server errors
+
+\e$B=i4|@_Dj\e(B (default) \e$B$N%5!<%P!<$,Mn$A$F$$$k$H$-$O!"EvA3\e(B gnus \e$B$N5/F0$K$$$/\e(B
+\e$B$D$+$NLdBj$,H/@8$7$^$9!#$7$+$7!"%K%e!<%9%0%k!<%W$NB>$K$$$/$D$+%a!<%k$N%0\e(B
+\e$B%k!<%W$,$"$l$P!"$=$l$K$b$+$+$o$i$:\e(B gnus \e$B$r5/F0$7$?$$$H;W$&$+$b$7$l$^$;$s!#\e(B
+
+Gnus \e$B$O!"?.Mj$G$-$k%W%m%0%i%`$N0l$D$H$7$F!"%5!<%P!<$H@\B3$G$-$J$$$H$-$O\e(B
+\e$B4pK\A*BrJ}K!$J$7$GB3$1$k$+$I$&$+$r?R$M$^$9!#$3$l$O<B:]$K$O%5!<%P!<$,B8:_\e(B
+\e$B$7$J$$$H$-\e(B (\e$BNc$($P!"%"%I%l%9$r4V0c$($?>l9g\e(B) \e$B$d%5!<%P!<$,2?$i$+$NM}M3$G0l\e(B
+\e$B;~E*$KD4;R$,$*$+$7$/$J$C$F$$$k$H$-$K5/$3$j$^$9!#$b$7$=$N$^$^B39T$9$k$3$H\e(B
+\e$B$K$7$F!"30It%0%k!<%W$,0l$D$bL5$$>l9g!"<B$O%0%k!<%W%P%C%U%!$G$O$[$H$s$I2?\e(B
+\e$B$b$G$-$J$$$H$$$&$3$H$K5$$,$D$/$G$7$g$&!#$G$b!"$M$'!"$=$l$O$"$J$?$NLdBj$G\e(B
+\e$B$9!#%O%O%O%C!#\e(B
+
+@findex gnus-no-server
+@kindex M-x gnus-no-server
+@c @head
+\e$B%5!<%P!<$,40A4$KMn$A$F$$$k$N$rCN$C$F$$$k$+!"%5!<%P!<$G$o$:$i$&$3$H$J$/%a!<\e(B
+\e$B%k$@$1$rFI$_$?$$$H$-$O!"\e(Bgnus \e$B$r5/F0$9$k$N$K!"\e(B@code{gnus-no-server} \e$BL?Na\e(B
+\e$B$r;H$&$3$H$,$G$-$^$9!#5^$$$G$$$k$H$-$K$b$T$C$?$j$G$7$g$&!#$3$NL?Na$OK\Mh\e(B
+\e$B$N%5!<%P!<$K$O@\B3$7$^$;$s!=!=$=$NBe$o$j$K!"%l%Y%k\e(B 1 \e$B$H\e(B 2 \e$B$K$"$k$9$Y$F$N\e(B
+\e$B%0%k!<%W$r3hF0>uBV$K$7$^$9\e(B (\e$B4pK\%0%k!<%W$G$J$$%0%k!<%W$O$=$NFs$D$N%l%Y%k\e(B
+\e$B$K$7$F$*$/$N$,K>$^$7$$$G$7$g$&\e(B)\e$B!#\e(B@ref{Group Levels} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@node Slave Gnusae
+@section gnus \e$B$r%9%l!<%V$K$9$k\e(B
+@cindex slave
+
+\e$B$"$J$?$OFs$D0J>e$N\e(B Emacs \e$B$H!"Fs$D0J>e$N\e(B gnus \e$B$rF1;~$KF0$+$7$?$$$H;W$&$+\e(B
+\e$B$b$7$l$^$;$s!#0c$C$?\e(B @file{.newsrc} \e$B%U%!%$%k$r;H$C$F$$$k$J$i\e(B (\e$BNc$($P!"\e(B
+\e$BFs$D$N0c$C$?%5!<%P!<$+$iFI$_9~$`$?$a$K!"Fs$D$N0c$C$?\e(B gnus \e$B$rF0:n$5$;$F$$\e(B
+\e$B$k>l9g\e(B)\e$B!"$^$C$?$/LdBj$O$"$j$^$;$s!#$=$l$r9T$($PNI$$$@$1$G$9!#\e(B
+
+\e$BLdBj$O!"F1$8\e(B @file{.newsrc} \e$B%U%!%$%k$r;H$&Fs$D$N\e(B gnus \e$B$rF0$+$=$&$H$7$?$H\e(B
+\e$B$-$K5/$3$j$^$9!#\e(B
+
+\e$B$3$NLdBj$KBP=h$9$k$?$a$K!"\e(Bgnus \e$B%?%o!<$N%7%s%/%?%s%/$K$$$k2f!9$O?7$7$$35\e(B
+\e$BG0$K$?$I$j$D$-$^$7$?!#\e(B@dfn{\e$B%^%9%?!<\e(B} \e$B$H\e(B @dfn{\e$B%9%l!<%V\e(B} \e$B$G$9!#\e(B(\e$B2f!9$O$3$N\e(B
+\e$B35G0$KFC5v$r?=@A$7$^$7$?!#$=$7$F!"$=$N8@MU$NCx:n8"$rF@$^$7$?!#$*8_$$$K4X\e(B
+\e$BO"$7$F$3$l$i$N8@MU$r;H$$$?$$$J$i!"0l2s;H$&Kh$K!";d$K\e(B $1 \e$B$rAw$i$J$1$l$P$J\e(B
+\e$B$j$^$;$s!#$b$C$A$m$s!"\e(B@dfn{\e$B%3%s%T%e!<%?!<%"%W%j%1!<%7%g%s$N%^%9%?!<!?%9\e(B
+\e$B%l!<%V4X78\e(B} \e$B$N;HMQNA$O$b$C$H9b$/$J$j$^$9!#\e(B)
+
+@findex gnus-slave
+\e$B$H$K$+$/!"\e(B@kbd{M-x gnus} (\e$B$b$7$/$O!"IaCJ$d$C$F$$$kJ}K!\e(B) \e$B$G\e(B gnus \e$B$rIaDL$K\e(B
+\e$B5/F0$7$^$9!#$=$N8e$N%9%l!<%V\e(B gnus \e$B$O$=$l$>$l\e(B @kbd{M-x gnus-slave} \e$B$G5/F0\e(B
+\e$B$7$^$9!#%9%l!<%V$OIaDL$N\e(B @file{.newsrc} \e$B$OJ]B8$7$^$;$s$,!"Be$o$j\e(B
+\e$B$K\e(B @dfn{\e$B%9%l!<%V%U%!%$%k\e(B} \e$B$K%9%l!<%V$N5/F0Cf$K$I$N$h$&$J%0%k!<%W$,FI$^$l\e(B
+\e$B$?$+$H$$$&>pJs$@$1$rJ]B8$7$^$9!#%^%9%?!<\e(B gnus \e$B$,5/F0$9$k$H$-!"$=$l$O$=$l\e(B
+\e$B$i$N%9%l!<%V%U%!%$%k$rFI$_9~$_\e(B (\e$B$=$7$F>C$7\e(B)\e$B!"$=$l$i$+$i$9$Y$F$N>pJs$r<h\e(B
+\e$B$j9~$_$^$9!#\e(B(\e$B%9%l!<%V%U%!%$%k$O!":G=*E*$JJQ99$,M%@h$5$l$k$h$&$K$=$l$i$,\e(B
+\e$B:n$i$l$?=gHV$GFI$^$l$^$9!#\e(B)
+
+\e$B$b$A$m$s!"%9%l!<%V%U%!%$%k$+$i$N>pJs$OIaDL$N\e(B (\e$B$9$J$o$A!"%^%9%?!<\e(B
+\e$B$N\e(B) @file{.newsrc} \e$B%U%!%$%k$h$j$bM%@h$5$l$^$9!#\e(B
+
+\e$B%9%l!<%V$r5/F0$9$k$H$-$K$b$7%^%9%?!<$N\e(B @file{.newsrc*} \e$B%U%!%$%k72$,%;!<\e(B
+\e$B%V$5$l$F$$$J$+$C$?$i!"<+F0J]B8$5$l$?%U%!%$%k$rFI$`$+$I$&$+$r?R$M$i$l$k$+\e(B
+\e$B$b$7$l$^$;$s!#\e(B``yes'' \e$B$HEz$($k$H!"%^%9%?!<$K%;!<%V$5$l$F$$$J$$JQ99$O%9%l!<\e(B
+\e$B%V$KH?1G$5$l$^$;$s!#\e(B``no'' \e$B$HEz$($k$H!"%^%9%?!<$GFI$^$l$?$$$/$D$+$N5-;v\e(B
+\e$B$,!"%9%l!<%V$G$OL$FI$G$"$k$H8+$J$5$l$k$+$b$7$l$^$;$s!#\e(B
+
+@node Fetching a Group
+@section \e$B%0%k!<%W$r<hF@$9$k\e(B
+@cindex fetching a group
+
+@findex gnus-fetch-group
+\e$B;~!9!"!H$3$N%0%k!<%W$rFI$_$?$$$N$G$"$C$F!"\e(Bgnus \e$B$,5/F0$7$F$$$k$+$I$&$+$r\e(B
+\e$B5$$K$7$?$/$J$$!#!I$H$$$&$3$H$,$G$-$l$PJXMx$J$3$H$,$"$j$^$9!#$3$l$O!"MxMQ\e(B
+\e$B<T$h$j$b%W%m%0%i%`$N%3!<%I$r=q$/?M$KJXMx$J5!G=$G$9$,!"$I$A$i$K$7$m!"%3%^\e(B
+\e$B%s%I\e(B @code{gnus-fetch-group} \e$B$O$3$N5!G=$rDs6!$7$^$9!#$=$N%3%^%s%I$O!"%0\e(B
+\e$B%k!<%W$NL>A0$r0z?t$H$7$F$H$j$^$9!#\e(B
+
+@node New Groups
+@section \e$B?7$7$$%0%k!<%W\e(B
+@cindex new groups
+@cindex subscription
+
+@vindex gnus-check-new-newsgroups
+\e$B?7$7$$%K%e!<%9%0%k!<%W$rA4$/8+$J$$$GK~B-$G$"$k$J$i$P!"\e(B
+@code{gnus-check-new-newsgroups} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+\e$B$3$l$r@_Dj$7$?>l9g!"5/F0$K$+$+$k;~4V$,C;$/$J$j$^$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$K@_Dj$5$l$F$$$F$b!"%0%k!<%W%P%C%U%!$G\e(B @kbd{U} \e$B$r2!$;$P$$\e(B
+\e$B$D$G$b?7$7$$%0%k!<%W$r9XFI$9$k$3$H$,$G$-$^$9\e(B (@pxref{Group Maintenance})\e$B!#\e(B
+\e$B=i4|@_Dj$G$O$3$NJQ?t$O\e(B @code{ask-server} \e$B$G$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{always} \e$B$K@_Dj$5$l$F$$$k$H!"L?Na\e(B @kbd{g} \e$B$r<B9T$7$?$H$-$G\e(B
+\e$B$b\e(B gnus \e$B$O%P%C%/%(%s%I$K?7$7$$%0%k!<%W$rC5$9$3$H$r5a$a$^\e(B
+\e$B$9\e(B (@pxref{Scanning New Messages})\e$B!#\e(B
+
+@menu
+* Checking New Groups::         \e$B$I$N%0%k!<%W$,?7$7$$$+$r7hDj$9$k\e(B
+* Subscription Methods::        \e$B?7$7$$%0%k!<%W$KBP$7$F\e(B gnus \e$B$O2?$r$9$Y$-$+\e(B
+* Filtering New Groups::        Gnus \e$B$KFCDj$N?7$7$$%0%k!<%W$rL5;k$5$;$k\e(B
+@end menu
+
+@node Checking New Groups
+@subsection \e$B?7$7$$%0%k!<%W$rD4$Y$k\e(B
+
+Gnus \e$B$O!"IaDL$O%0%k!<%W$,?7$7$$$+$I$&$+$r!"9XFI$7$F$$$k%0%k!<%W$H:o=|$5\e(B
+\e$B$l$F$$$k%0%k!<%W$N%j%9%H$H%"%/%F%#%V%U%!%$%k$rHf3S$9$k$3$H$K$h$j7hDj$7$F\e(B
+\e$B$$$^$9!#$3$NJ}K!$OFC$KB.$$$H$$$&$o$1$G$O$"$j$^$;$s!#\e(B
+@code{gnus-check-new-newsgroups} \e$B$,\e(B @code{ask-server} \e$B$G$"$k$H!"\e(Bgnus \e$B$O\e(B
+\e$B%5!<%P!<$K!":G8e$K@\B3$7$F$+$i?7$7$$%0%k!<%W$,$G$-$F$$$k$+$I$&$+$r?R$M$^\e(B
+\e$B$9!#$3$NJ}K!$OB.$$$7!"0B>e$,$j$G$9!#$3$l$K$h$j!":o=|$5$l$?%0%k!<%W$N%j%9\e(B
+\e$B%H$rJ];}$7$F$*$/$3$H$+$i$+$i40A4$K3+J|$5$l$^$9!#$G$9$+$i!"\e(B
+@code{gnus-save-killed-list} \e$B$r\e(B @code{nil} \e$B$K$9$k$3$H$,$G$-$k$G$7$g$&!#\e(B
+\e$B$=$&$9$l$P!"5/F0!"=*N;$NN>J}!"$=$7$FA4BN$K$o$?$C$F;~4V$r@aLs$G$-$^$9!#%G%#\e(B
+\e$B%9%/>CHqNL$b>/$J$/$J$j$^$9!#$=$l$J$i!"$I$&$7$F$3$l$,=i4|@_Dj$G$O$J$$$N$G\e(B
+\e$B$7$g$&\e(B? \e$B;DG0$J$,$i!"$9$Y$F$N%5!<%P!<$,$3$NL?Na$rM}2r$9$k$o$1$G$O$J$$$N$G\e(B
+\e$B$9!#\e(B
+
+\e$B;d$O:#$"$J$?$,2?$r9M$($F$$$k$+$rEv$F$i$l$^$9!#$I$&$9$l$P%5!<%P!<\e(B
+\e$B$,\e(B @code{ask-server} \e$B$rM}2r$9$k$+$,$o$+$k$N$G$7$g$&\e(B? \e$B$(!"0c$&$N$G$9\e(B
+\e$B$+\e(B? \e$B$"$!!"NI$+$C$?!#$H$$$&$N$O!"3N<B$JEz$OB8:_$7$J$$$N$G$9!#;d$K8@$($k$3\e(B
+\e$B$H$O!"$3$NJQ?t$r\e(B @code{ask-server} \e$B$K@_Dj$7$F!"?tF|4V?7$7$$%0%k!<%W$,8=\e(B
+\e$B$l$k$+$I$&$+$rD4$Y$F$/$@$5$$!"$H$$$&$3$H$@$1$G$9!#$b$7$$$/$D$+$N%0%k!<%W\e(B
+\e$B$,8=$l$?$J$i!"$=$l$GF0:n$7$F$$$^$9!#0l$D$b8=$l$J$1$l$P!"$=$l$OF0:n$7$F$$\e(B
+\e$B$^$;$s!#;d$O!"\e(Bgnus \e$B$K%5!<%P!<$,\e(B @code{ask-server} \e$B$rM}2r$9$k$+$I$&$+$r?d\e(B
+\e$BNL$5$;$k4X?t$r=q$/$3$H$b$G$-$^$9$,!"$=$l$OC1$K?dNL$7$F$$$k$K$9$.$^$;$s!#\e(B
+\e$B$G$9$+$i!"$=$N4X?t$r=q$/$3$H$O$J$$$G$7$g$&!#B>$NJ}K!$H$7$F$O!"%5!<%P!<\e(B
+\e$B$K\e(B @code{telnet} \e$B$r$7$F!"\e(B@code{HELP} \e$B$HBG$A!"%5!<%P!<$,M}2r$9$k%3%^%s%I\e(B
+\e$B$NCf$K\e(B @samp{NEWGROUPS} \e$B$,$"$k$+$I$&$+$rD4$Y$k$3$H$b$G$-$^$9!#$b$7$"$l$P!"\e(B
+\e$B$*$=$i$/F0:n$9$k$G$7$g$&\e(B (\e$B$7$+$7!"E,@Z$K5!G=$rDs6!$9$k$3$H$J\e(B
+\e$B$/\e(B @samp{NEWGROUPS} \e$B$r%j%9%H$K4^$a$k%5!<%P!<$b$"$j$^$9\e(B)\e$B!#\e(B
+
+\e$B$3$NJQ?t$O!"A*BrJ}K!$N%j%9%H$G$"$k$3$H$b$G$-$^$9!#$=$N$H$-$O!"\e(Bgnus \e$B$OL?\e(B
+\e$BNa\e(B @code{ask-server} \e$B$r$=$l$>$l$NA*BrJ}K!$KBP$7$F<B9T$7!"IaDL$NJ}K!$G9X\e(B
+\e$BFI\e(B (\e$B$b$7$/$O!"Hs9XFI\e(B) \e$B$7$^$9!#$3$l$NI{:nMQ$O!"5/F0$K$+$J$j;~4V$,$+$+$k$N\e(B
+\e$B$G!"BT$C$F$$$k4V$KbTA[$G$-$k$3$H$G$9!#1J5W$N9,J!$rC#@.$9$k$?$a$K!"%^%s%H\e(B
+\e$B%i\e(B ``dingnusdingnusdingnus'' \e$B$r;H$C$F$/$@$5$$!#\e(B
+
+@node Subscription Methods
+@subsection \e$B9XFIJ}K!\e(B
+
+@vindex gnus-subscribe-newsgroup-method
+\e$B?7$7$$%0%k!<%W$KAx6x$7$?$H$-$K\e(B gnus \e$B$,2?$r$9$k$+$O!"JQ\e(B
+\e$B?t\e(B @code{gnus-subscribe-newsgroup-method} \e$B$K$h$C$F7hDj$5$l$^$9!#\e(B
+
+\e$B$3$NJQ?t$O4X?t$r4^$s$G$$$kI,MW$,$"$j$^$9!#$3$N4X?t$O?7$7$$%0%k!<%W$NL>A0\e(B
+\e$B$rM#0l$N0z?t$H$7$F8F$P$l$^$9!#\e(B
+
+\e$B$$$/$D$+$N<j7Z$J%W%l%O%V4X?t$O!"0J2<$N$h$&$K$J$C$F$$$^$9!#\e(B
+
+@table @code
+@item gnus-subscribe-zombies
+@vindex gnus-subscribe-zombies
+\e$B$9$Y$F$N?7$7$$%0%k!<%W$r%>%s%S\e(B (zombie) \e$B$K$7$^$9!#$3$l$,=i4|@_Dj$K$J$C$F\e(B
+\e$B$$$^$9!#8e$G%>%s%S$r\e(B (@kbd{A z} \e$B$K$h$C$F\e(B) \e$B354Q$7$?$j!"\e(B(@kbd{S z} \e$B$K$h$C\e(B
+\e$B$F\e(B) \e$BE,@Z$KA4$F$r:o=|$7$?$j!"\e(B(@kbd{u} \e$B$K$h$C$F\e(B) \e$B9XFI$7$?$j$G$-$^$9!#\e(B
+
+@item gnus-subscribe-randomly
+@vindex gnus-subscribe-randomly
+\e$BG$0U$N=gHV$G$9$Y$F$N?7$7$$%0%k!<%W$r9XFI$7$^$9!#<B:]$K$O!"$9$Y$F$N?7$7$$\e(B
+\e$B%0%k!<%W$O%0%k!<%W%P%C%U%!$N!X0lHV>e!Y$K2C$($i$l$^$9!#\e(B
+
+@item gnus-subscribe-alphabetically
+@vindex gnus-subscribe-alphabetically
+\e$B$9$Y$F$N?7$7$$%0%k!<%W$r%"%k%U%!%Y%C%H=g$K9XFI$7$^$9!#\e(B
+
+@item gnus-subscribe-hierarchically
+@vindex gnus-subscribe-hierarchically
+\e$B$9$Y$F$N?7$7$$%0%k!<%W$r3,AXE*$K9XFI$7$^$9!#$3$N4X?t\e(B
+\e$B$H\e(B @code{gnus-subscribe-alphabetically} \e$B$N0c$$$O>/$7$7$+$"$j$^$;$s!#\e(B
+@code{gnus-subscribe-alphabetically} \e$B$O?7$7$$%0%k!<%W$r87L)$K%"%k%U%!%Y%C\e(B
+\e$B%H=g$K$J$i$Y$^$9$,!"$3$N4X?t$O%0%k!<%W$r$=$N3,AX$NCf$KF~$l$^$9!#$G$9$+$i!"\e(B
+@samp{rec} \e$B$N3,AX$r\e(B @samp{comp} \e$B$N3,AX$NA0$K;}$C$F$-$?$$>l9g!"$3$N4X?t$O\e(B
+\e$B$=$NG[CV$r$0$A$c$0$A$c$K$O$7$^$;$s!#$b$7$/$O!"$=$N$h$&$J$b$N$G$9!#\e(B
+
+@item gnus-subscribe-interactively
+@vindex gnus-subscribe-interactively
+\e$B?7$7$$%0%k!<%W$rBPOCE*$K9XFI$7$^$9!#$3$l$O\e(B gnus \e$B$,\e(B @strong{\e$BA4$F\e(B} \e$B$N%0%k!<\e(B
+\e$B%W$KBP$7$F?R$M$k$3$H$r0UL#$7$F$$$^$9!#9XFI$9$k%0%k!<%W$O3,AXE*$K9XFI$5$l\e(B
+\e$B$^$9!#\e(B
+
+@item gnus-subscribe-killed
+@vindex gnus-subscribe-killed
+\e$B$9$Y$F$N?7$7$$%0%k!<%W$r:o=|$7$^$9!#\e(B
+
+@item gnus-subscribe-topics
+@vindex gnus-subscribe-topics
+\e$B%0%k!<%W$r9gCW$9$k\e(B @code{subscribe} \e$B%H%T%C%/%Q%i%a!<%?$N$"$k%0%k!<%W$KF~\e(B
+\e$B$l$^$9\e(B (@pxref{Topc Parameters})\e$B!#Nc$($P!"0J2<$N$h$&\e(B
+\e$B$J\e(B @code{subscribe} \e$B%Q%i%a!<%?\e(B
+
+@example
+"nnslashdot"
+@end example
+
+\e$B$O$=$N@55,I=8=$K9gCW$9$kA4$F$N%0%k!<%W$O$=$N%H%T%C%/$N2<$G9XFI$5$l$k$H$$\e(B
+\e$B$&$3$H$G$9!#\e(B
+
+\e$B%0%k!<%W$K9gCW$9$k%H%T%C%/$,L5$$>l9g!"%0%k!<%W$O:G>e0L$N%H%T%C%/$G9XFI$5\e(B
+\e$B$l$^$9!#\e(B
+@end table
+
+@vindex gnus-subscribe-hierarchical-interactive
+\e$B>e$NJQ?t$HNI$/4X78$7$?JQ?t$O!"\e(B
+@code{gnus-subscribe-hierarchical-interactive} \e$B$G$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O3,AXE*$JJ}K!$G?7$7$$%0%k!<%W$r9XFI$9$k$+\e(B
+\e$B$I$&$+$r?R$M$^$9!#\e(Bgnus \e$B$O$=$l$>$l$N3,AX$G!"$=$l$r2<$K9_$j$k$+$I$&$+$r?R\e(B
+\e$B$M$^$9!#\e(B
+
+\e$B$h$/$"$k4V0c$$$O!"?tCJMnA0$NJQ\e(B
+\e$B?t\e(B (@code{gnus-subscribe-newsgroup-method}) \e$B$r\e(B @code{gnus-subscribe-herarchical-interactive} \e$B$K\e(B
+\e$B@_Dj$9$k$3$H$G$9!#$3$l$O8m$j$G$9!#$3$l$OF0:n$7$^$;$s!#$3$l$O$*$a$G$?$$?M\e(B
+\e$B$N$9$k$3$H$G$9!#$G$9$+$i!"@dBP$K$7$J$$$G$/$@$5$$!#\e(B
+
+@node Filtering New Groups
+@subsection \e$B?7$7$$%0%k!<%W$rA*JL$9$k\e(B
+
+\e$B$I$N?7$7$$%0%k!<%W$,9XFI\e(B (\e$B$b$7$/$O!"L5;k\e(B) \e$B$5$l$k$Y$-$+$r4IM}$9$k2wE,$G<j\e(B
+\e$B7Z$JJ}K!$O!"%U%!%$%k\e(B @file{.newsrc} \e$B$N@hF,$K\e(B @dfn{options} \e$B9T$rA^F~$9$k\e(B
+\e$B$3$H$G$9!#<!$O!"Nc$G$9!#\e(B
+
+@example
+options -n !alt.all !rec.all sci.all
+@end example
+
+@vindex gnus-subscribe-options-newsgroup-method
+\e$B$3$N9T$O!"L@$i$+$K$^$8$a$GM}CNE*$G2J3XE*$J?M4V\e(B (\e$B$b$7$/$OC1$J$k8E$/B`6~$J\e(B
+\e$B?M4V\e(B) \e$B$,=q$$$?$b$N$G$9!#$J$<$J$i!"$3$l$O\e(B @samp{alt} \e$B$H\e(B @samp{rec} \e$B$G;O$^\e(B
+\e$B$kL>A0$r;}$D%0%k!<%W$OA4$FL5;k$5$l!"\e(B@samp{sci} \e$B$G;O$^$kL>A0$r;}$D%0%k!<\e(B
+\e$B%W$OA4$F9XFI$9$k!"$H$$$&$3$H$rI=$7$F$$$k$+$i$G$9!#\e(BGnus \e$B$O$3$l$i$N%0%k!<\e(B
+\e$B%W$r9XFI$9$k$N$K!"IaDL$N9XFIJ}K!$rMQ$$$^$;$s!#Be$o$j$K!"\e(B
+@code{gnus-subscribe-options-newsgroup-method} \e$B$,MQ$$$i$l$^$9!#$3$NJQ?t\e(B
+\e$B$O=i4|@_Dj$G$O\e(B @code{gnus-subscribe-alphabetically} \e$B$G$9!#\e(B
+
+@vindex gnus-options-not-subscribe
+@vindex gnus-options-subscribe
+\e$B%U%!%$%k\e(B @file{.newsrc} \e$B$r$$$8$j$?$/$J$$>l9g$O!"\e(B
+@code{gnus-options-subscribe} \e$B$H\e(B @code{gnus-options-not-subscribe} \e$B$NFs\e(B
+\e$B$D$NJQ?t$@$1$r@_Dj$9$k$3$H$b$G$-$^$9!#$3$NFs$D$NJQ?t$O%U%!%$\e(B
+\e$B%k\e(B @file{.newsrc} \e$B$N\e(B @samp{optinos -n} \e$B9T$HA4$/F1$8$3$H$r$7$^$9!#$I$A$i\e(B
+\e$B$NJQ?t$b@55,I=8=$G!"?7$7$$%0%k!<%W$OA0<T$K9gCW$9$l$PL5>r7o$K9XFI$5$l!"8e\e(B
+\e$B<T$K9gCW$9$k$HL5;k$5$l$^$9!#\e(B
+
+@vindex gnus-auto-subscribed-groups
+\e$B$5$i$K$3$3$G$*$;$C$+$$$r$9$kJQ?t$O!"\e(B
+@code{gnus-auto-subscribed-groups} \e$B$G$9!#$=$l\e(B
+\e$B$O\e(B @code{gnus-options-subscribe} \e$B$HA4$/F1$8$h$&$KF0:n$7$^$9$N$G!"K\Ev$O\e(B
+\e$BM>J,$J$b$N$G$9!#$7$+$7!";d$O$3$NFs$D$,$"$C$?J}$,NI$$$H;W$$$^$7$?!#$b$&0l\e(B
+\e$BJ}$NJQ?t$O%f!<%6$,$$$8$/$k$N$K;H$o$l$k$N$KBP$7$F!"$3$NJQ?t$O$$$/$D$+$N4p\e(B
+\e$BK\E*$J5,B'$r@_Dj$9$k$?$a$N$b$N$G$9!#=i4|@_Dj$G$O$3$NJQ?t$O%a!<%k%P%C%/%(\e(B
+\e$B%s%I\e(B (@code{nnml}, @code{nnbabyl}, @code{nnfolder}, @code{nnmbox},
+@code{nnmh} \e$B$*$h$S\e(B @code{nnmaildir}) \e$B$+$i$G$-$kA4$F$N?7$7$$%0%k!<%W$r9X\e(B
+\e$BFI$9$k$h$&$K$J$C$F$$$^$9!#$=$l$,7y$G$"$l$P!"$3$NJQ?t$r\e(B @code{nil} \e$B$K@_Dj\e(B
+\e$B$7$F$/$@$5$$!#\e(B
+
+\e$B$3$N@55,I=8=$K9gCW$9$k?7$7$$%0%k!<%W\e(B
+\e$B$O\e(B @code{gnus-subscribe-options-newsgroup-method} \e$B$r;H$C$F9XFI$5$l$^$9!#\e(B
+
+@node Changing Servers
+@section \e$B%5!<%P!<$r49$($k\e(B
+@cindex changing servers
+
+\e$B$H$-$I$-!"$"$k\e(B @acronym{NNTP} \e$B%5!<%P!<$+$iJL$N%5!<%P!<$X0\F0$7$J$1$l$P$J\e(B
+\e$B$i$J$$$3$H$,$"$j$^$9!#$3$N$h$&$J$3$H$O$a$C$?$K$*$-$^$;$s$,!"$*$=$i$/$"$J\e(B
+\e$B$?$,;E;v$rJQ$($?$j!";H$C$F$$$k%5!<%P!<$,$H$F$bIT0BDj$G!"JL$N$b$N$K>h$j49\e(B
+\e$B$($?$$$H$$$&$H$-$KI,MW$K$J$k$G$7$g$&!#\e(B
+
+\e$B%5!<%P!<$rJQ99$9$k$N$O$H$F$b4JC1$G$9$h$M\e(B? @code{gnus-select-method} \e$B$r?7\e(B
+\e$B$7$$%5!<%P!<$r;X$7<($9$h$&$KJQ99$9$l$P$$$$$@$1$G$9$M\e(B?
+
+@emph{\e$B0c$$$^$9\e(B!}
+
+\e$B5-;v$NHV9f$O0c$C$?\e(B @acronym{NNTP} \e$B%5!<%P!<$G$b\e(B (\e$B$I$&$K$+$7$F\e(B) \e$BF1$8$K$7$F\e(B
+\e$B$"$k!"$H$$$&$3$H$O$"$j$^$;$s!#$=$7$F!"\e(Bgnus \e$B$,$I$N5-;v$rFI$s$@$+$r5-O?$9\e(B
+\e$B$kM#0l$NJ}K!$O!"5-;vHV9f$r5-O?$9$k$3$H$G$9!#$G$9$+$i!"\e(B
+@code{gnus-select-method} \e$B$rJQ99$7$?$H$-$O!"%U%!%$%k\e(B @file{.newsrc} \e$B$O0U\e(B
+\e$BL#$,$J$/$J$j$^$9!#\e(B
+
+Gnus \e$B$O%U%!%$%k\e(B @file{.newsrc} \e$B$r$"$k%5!<%P!<MQ$+$iJL$N%5!<%P!<MQ$KJQ49\e(B
+\e$B$9$k4X?t$rFs!";0MQ0U$7$F$$$^$9!#$=$l$i$K$O0l$D6&DLE@$,$"$j$^$9\e(B---\e$B<B9T$K\e(B
+\e$B$J$,!<!<$$;~4V$,$+$+$k$3$H$G$9!#$*$=$i$/!"$I$&$7$F$bI,MW$K$J$C$?$H$-0J30\e(B
+\e$B$K$3$N4X?t$r;H$*$&$H$O;W$o$J$$$G$7$g$&!#\e(B
+
+@kindex M-x gnus-change-server
+@findex gnus-change-server
+\e$B$b$7N>J}$N%5!<%P!<$K@\B3$G$-$k$J$i!"\e(Bgnus \e$B$O$"$J$?$,FI$s$@5-;vA4$F$KBP$7\e(B
+\e$B$F%X%C%@!<\e(B (headers) \e$B$rMW5a$7$F!"\e(B@code{Message-ID} \e$B$rHf3S$7!"FI$s$@5-;v\e(B
+\e$B$H5-;v$N0u$r?7$7$/5-O?$7$^$9!#%3%^%s%I\e(B @kbd{M-x gnus-change-server} \e$B$O$3\e(B
+\e$B$l$r$9$Y$F$N4pK\%0%k!<%W$KBP$7$F9T$$$^$9!#$=$N%3%^%s%I$O0\F0@h$NJ}K!$NF~\e(B
+\e$BNO$rB%$7$^$9!#\e(B
+
+@kindex M-x gnus-group-move-group-to-server
+@findex gnus-group-move-group-to-server
+\e$B8D!9$N%0%k!<%W$rL?Na\e(B @kbd{M-x gnus-group-move-group-to-server} \e$B$G0\\e(B
+\e$BF0$9$k$3$H$b$G$-$^$9!#$3$l$O$"$k%5!<%P!<$+$iJL$N%5!<%P!<$X0l$D\e(B
+\e$B$N\e(B (\e$B30It\e(B) \e$B%0%k!<%W$r0\F0$7$?$$$H$-$KLr$KN)$A$^$9!#\e(B
+
+@kindex M-x gnus-group-clear-data-on-native-groups
+@findex gnus-group-clear-data-on-native-groups
+\e$B8E$$%5!<%P!<$H?7$7$$%5!<%P!<$NN>J}$K@\B3$9$k$3$H$,$G$-$J$$$H$-!"0u$HFI$s\e(B
+\e$B$@HO0O$O$9$Y$F0UL#$,L5$/$J$j$^$9!#$=$N$h$&$J$H$-$O!"%3%^%s%I\e(B @kbd{M-x
+gnus-group-clear-data-on-native-groups} \e$B$r;H$C$F!"4pK\%0%k!<%W$K4X$9$k%G!<\e(B
+\e$B%?$r$9$Y$F>C5n$9$k$3$H$,$G$-$^$9!#$3$N%3%^%s%I$OCm0U$7$F;H$C$F$/$@$5$$!#\e(B
+
+@kindex M-x gnus-group-clear-data
+@findex gnus-group-clear-data
+\e$B8=:_$N%0%k!<%W$NA4$F$N%G!<%?$r%/%j%"$7$^$9!=!=%^!<%/$H4{FI5-;v$N%j%9%H$r\e(B
+\e$B>C$75n$j$^$9\e(B (@code{gnus-group-clear-data})\e$B!#\e(B
+
+\e$B%5!<%P!<$rJQ99$7$?8e$G!"%-%c%C%7%e3,AX$r0\F0$5$;$J$1$l$P\e(B@strong{\e$B$J$j$^$;\e(B
+\e$B$s\e(B}\e$B!#$H$$$&$N$O!"%-%c%C%7%e5-;v$O4V0c$C$?5-;vHV9f$K$J$C$F$*$j!"$=$l\e(B
+\e$B$O\e(B gnus \e$B$,$I$N5-;v$rFI$s$@$H$_$J$9$+$K1F6A$7$^$9!#\e(B
+@code{gnus-group-clear-data-on-native-groups} \e$B$O$=$l$r<+F0$G9T$J$C$F$7$^\e(B
+\e$B$&$+$I$&$+$r?R$M$^$9!#\e(B@code{gnus-group-clear-data} \e$B$G\e(B
+\e$B$O\e(B @kbd{M-x gnus-cache-move-cache} \e$B$,;H$($^$9\e(B (\e$B$G$b5$$rIU$1$F!"$=$l$O$9\e(B
+\e$B$Y$F$N%0%k!<%W$N%-%c%C%7%e$r0\F0$7$F$7$^$$$^$9$+$i\e(B)\e$B!#\e(B
+
+@node Startup Files
+@section \e$B5/F0%U%!%$%k\e(B
+@cindex startup files
+@cindex .newsrc
+@cindex .newsrc.el
+@cindex .newsrc.eld
+
+\e$B:#$d!"$"$J$?$O%U%!%$%k\e(B @file{.newsrc} \e$B$K$D$$$F$9$Y$FCN$C$F$$$^$9!#$9$Y$F\e(B
+\e$B$N9XFI>pJs$OEAE}E*$K$3$N%U%!%$%k$KC_@Q$5$l$^$9!#\e(B
+
+@sc{gnus} \e$B$G$OJ*;v$,>/!9J#;($K$J$C$F$$$^$9!#%U%!%$%k\e(B @file{.newsrc} \e$B$r:G\e(B
+\e$B?7$N$b$N$K$9$k$@$1$G$O$J$/!"%U%!%$%k\e(B @file{.newsrc} \e$B$K$O9g$o$J$$>pJs$rJ]\e(B
+\e$BB8$7$F$*$/$?$a$K\e(B @file{.newsrc.el} \e$B$H8F$P$l$k%U%!%$%k$r;H$$$^$9!#\e(B(\e$B<B:]\e(B
+\e$B$O!"%U%!%$%k\e(B @file{.newsrc} \e$B$NA4$F$N>pJs$rJ#@=$7$FJ];}$7$F$$$^\e(B
+\e$B$9!#\e(B) @sc{gnus}\e$B$O$3$l$i$NCf$G0lHV:G8e$KJ]B8$5$l$?$b$N$r;H$$$^$9!#$3$l$r\e(B
+\e$B$9$k$3$H$K$h$j!"\e(B@sc{gnus} \e$B$HB>$N%K%e!<%9%j!<%@!<$r@Z$jBX$($F;H$&$3$H$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+\e$B$3$l$O$A$g$C$H$P$+$JJ}K!$J$N$G!"\e(Bgnus \e$B$O$b$C$HNI$$J}K!$rJT$_=P$7$^$7$?!#\e(B
+@file{.newsrc} \e$B$H\e(B @file{.newsrc.el} \e$B%U%!%$%k$K2C$($F!"\e(B
+gnus \e$B$O\e(B @file{.newsrc.eld} \e$B$H8F$P$l$k%U%!%$%k$b;}$C$F$$$^$9!#\e(BGnus \e$B$O$3$l\e(B
+\e$B$i$NCf$G0lHV?7$7$$%U%!%$%k$rFI$_$^$9$,!"%U%!%$%k\e(B @file{.newsrc.el} \e$B$K=q\e(B
+\e$B$-9~$`$3$H$O$"$j$^$;$s!#%U%!%$%k\e(B @file{.newsrc.eld} \e$B$O@dBP$K>C$9$Y$-$G$O\e(B
+\e$B$"$j$^$;$s!#\e(B---\e$B$=$l$O%U%!%$%k\e(B @file{.newsrc} \e$B$K$O$J$$$?$/$5$s$N>pJs$rJ]\e(B
+\e$B;}$7$F$$$^$9!#\e(B
+
+@vindex gnus-save-newsrc-file
+@vindex gnus-read-newsrc-file
+@code{gnus-save-newsrc-file} \e$B$r\e(B @code{nil} \e$B$K$9$k$3$H$K$h$C$F%U%!%$\e(B
+\e$B%k\e(B @file{.newsrc} \e$B$K=q$-9~$`$N$r;_$a$k$3$H$,$G$-$^$9!#$=$&$9$l$P!"$=$N%U%!\e(B
+\e$B%$%k$r:o=|$9$k$3$H$,$G$-!"%G%#%9%/MFNL$r@aLs$9$k$3$H$,$G$-!"\e(Bgnus \e$B$N=*N;\e(B
+\e$B$,B.$/$J$j$^$9!#$7$+$7!"$=$&$9$k$HB>$N%K%e!<%9%j!<%@!<$r;H$($J$/$J$j$^$9!#\e(B
+\e$B$G$b!"$A$g$C$H!"C/$+$=$&$7$?$$?M$,$$$k$G$7$g$&$+!#F1$8$h$&\e(B
+\e$B$K\e(B @code{gnus-read-newsrc-file} \e$B$r\e(B @code{nil} \e$B$K$9$k$3$H$K$h$C\e(B
+\e$B$F\e(B @file{.newsrc} \e$B$H$9$Y$F$N\e(B @file{.newsrc-SERVER} \e$B$r:n$i$J$$$h$&$K$J$j\e(B
+\e$B$^$9!#$b$7$"$J$?$,;~!9\e(B Netscape \e$B$r;H$&$N$J$i$P!"$3$&$9$k$N$,ET9g$,NI$$$G\e(B
+\e$B$7$g$&!#\e(B
+
+@vindex gnus-save-killed-list
+@code{gnus-save-killed-list} (\e$B=i4|@_Dj$G$O\e(B @code{t}) \e$B$,\e(B @code{nil} \e$B$G$"\e(B
+\e$B$k$H!"\e(Bgnus \e$B$O:o=|$5$l$?%0%k!<%W$r5/F0%U%!%$%k$KJ]B8$7$^$;$s!#$3$l$O!"\e(B(\e$B5/\e(B
+\e$BF0;~$H=*N;;~$N\e(B) \e$B;~4V$H!"\e(B(\e$B%G%#%9%/$N\e(B) \e$BMFNL$r@aLs$7$^$9!#$3$&$9$k$H!"\e(B
+gnus \e$B$,$I$N%0%k!<%W$,?7$7$$$+$N5-O?$r;}$C$F$$$J$$$3$H$K$J$j$^$9$N$G!"?7\e(B
+\e$B$7$$%0%k!<%W$N<+F09XFIJ}K!$O0UL#$,L5$/$J$j$^$9!#$3$NJQ?t$r\e(B @code{nil} \e$B$K\e(B
+\e$B$7$?$H$-$O!"\e(B@code{gnus-check-new-newsgroups} \e$B$r>o\e(B
+\e$B$K\e(B @code{nil} \e$B$+\e(B @code{ask-server} \e$B$K$7$F$*$/$Y$-$G$7$g\e(B
+\e$B$&\e(B (@pxref{New Groups})\e$B!#$3$NJQ?t$O@55,I=8=$G$"$k$3$H$b$G$-$^$9!#$=$N$h\e(B
+\e$B$&$J>l9g$O!"%U%!%$%k$rJ]B8$9$kD>A0$K$=$N@55,I=8=$K9gCW$7$J$$$9$Y$F$N%0%k!<\e(B
+\e$B%W$r>C5n$7$^$9!#$3$l$O!"$9$Y$F$N%5!<%P!<$,\e(B @code{ask-server} \e$B$rM}2r$9$k\e(B
+\e$B$o$1$G$O$J$$!"$H$$$C$?$h$&$J!"FCDj$N$"$$$^$$$J>u67$N$H$-$KLr$KN)$D$G$7$g\e(B
+\e$B$&!#\e(B
+
+@vindex gnus-startup-file
+@vindex gnus-backup-startup-file
+@vindex version-control
+\e$BJQ?t\e(B @code{gnus-startup-file} \e$B$O5/F0%U%!%$%k$,$I$3$K$"$k$+$r;XDj$7$^$9!#\e(B
+\e$B=i4|CM$O\e(B @file{~/.newsrc} \e$B$G!"$=$l$,$I$N$h$&$J$b$N$G$"$l!"KvHx\e(B
+\e$B$K\e(B @samp{.eld} \e$B$r$D$1$?$b$N$,\e(B gnus (El Dingo) \e$B$N5/F0%U%!%$%k$K$J$j$^$9!#\e(B
+\e$B$3$N%U%!%$%k$N%P!<%8%g%s@)8f$r$7$?$$$H$-\e(B
+\e$B$O\e(B @code{gnus-backup-startup-file} \e$B$r%;%C%H$7$F2<$5$$!#$=$l\e(B
+\e$B$O\e(B @code{version-control} \e$BJQ?t$HF1$8CM$r<h$j$^$9!#\e(B
+
+@vindex gnus-save-newsrc-hook
+@vindex gnus-save-quick-newsrc-hook
+@vindex gnus-save-standard-newsrc-hook
+@code{gnus-save-newsrc-hook} \e$B$O\e(B newsrc \e$B%U%!%$%k$NCf$N$I$l$+$rJ]B8$9$kA0\e(B
+\e$B$K<B9T$5$l$k$N$KBP$7!"\e(B@code{gnus-save-quick-newsrc-hook} \e$B$O%U%!%$\e(B
+\e$B%k\e(B @file{.newsrc.eld} \e$B$rJ]B8$9$kA0$K<B9T$5$l!"\e(B
+@code{gnus-save-standard-newsrc-hook} \e$B$O%U%!%$%k\e(B @file{.newsrc} \e$B$rJ]B8$9\e(B
+\e$B$kA0$K<B9T$5$l$^$9!#8e$NFs$D$OIaDL$OHG4IM}$rF~$l$?$j@Z$C$?$j$9$k$N$K;H$o\e(B
+\e$B$l$^$9!#=i4|@_Dj$G$O!"5/F0%U%!%$%k$rJ]B8$9$k$H$-$KHG4IM}$KF~$j$^$9!#%P%C\e(B
+\e$B%/%"%C%W%U%!%$%k$N:n@.$r;_$a$?$$$H$-$O!"<!$N$h$&$K$7$F$/$@$5$$!#\e(B
+
+@lisp
+(defun turn-off-backup ()
+  (set (make-local-variable 'backup-inhibited) t))
+
+(add-hook 'gnus-save-quick-newsrc-hook 'turn-off-backup)
+(add-hook 'gnus-save-standard-newsrc-hook 'turn-off-backup)
+@end lisp
+
+@vindex gnus-init-file
+@vindex gnus-site-init-file
+Gnus \e$B$,5/F0$9$k$H!"\e(B@code{gnus-site-init-file} (\e$B=i4|@_Dj$G\e(B
+\e$B$O\e(B @file{.../site-lisp/gnus}) \e$B$H\e(B @code{gnus-init-file} (\e$B=i4|@_Dj$G\e(B
+\e$B$O\e(B @file{~/.gnus}) \e$B$N%U%!%$%k$rFI$_9~$_$^$9!#$3$l$i$OIaDL\e(B
+\e$B$N\e(B Emacs Lisp \e$B%U%!%$%k$G!"\e(B@file{~/.emacs} \e$B$d\e(B @file{site-init} \e$B%U%!%$%k\e(B
+\e$B$r\e(B gnus \e$B4X78$N$b$N$GMp;($K$7$J$$$h$&$K$9$k$?$a$K;H$&$3$H$,$G$-$^$9!#\e(B
+Gnus \e$B$O$3$l$i$HF1$8L>A0$N%U%!%$%k$K!"@\Hx8l\e(B @file{.elc} \e$B$H\e(B @file{.el} \e$B$,\e(B
+\e$BIU$$$F$$$k$b$N$bD4$Y$^$9!#8@$$49$($l$P!"\e(B
+@code{gnus-init-file} \e$B$r\e(B @file{~/.gnus} \e$B$K@_Dj$9$k$H!"\e(B
+gnus \e$B$O\e(B @file{~/.gnus.elc}, @file{~/.gnus.el} \e$B$rC5$7!":G8e\e(B
+\e$B$K\e(B @file{~/.gnus} \e$B$r\e(B (\e$B$3$N=gHV$K\e(B) \e$BC5$7$^$9!#\e(B
+
+@node Auto Save
+@section \e$B<+F0J]B8\e(B
+@cindex dribble file
+@cindex auto-save
+
+\e$B2?$+\e(B gnus \e$B$N%G!<%?$rJQ99$9$k$3$H\e(B (\e$B5-;v$rFI$`!"0u$rIU$1$k!"%0%k!<%W$r:o=|\e(B
+\e$B$^$?$O9XFI$9$k\e(B) \e$B$r$7$?$H$-!"JQ99$OFCJL$J\e(B@dfn{\e$B%I%j%V%k%P%C%U%!\e(B (dribble
+buffer)} \e$B$K=q$-9~$^$l$^$9!#$3$N%P%C%U%!$O\e(BEmacs \e$B$,IaDL$9$k$h$&$K<+F0J]B8\e(B
+\e$B$5$l$^$9!#%U%!%$%k\e(B @file{.newsrc} \e$B$rJ]B8$9$kA0$K\e(B Emacs\e$B$,Mn$A$?$H$-$O!"$9\e(B
+\e$B$Y$F$NJQ99$r$3$N%U%!%$%k$+$i2sI|$9$k$3$H$,$G$-$k$G$7$g$&!#\e(B
+
+\e$B5/F0;~$K\e(B gnus \e$B$,$3$N%U%!%$%k$NB8:_$rH/8+$9$k$H!"\e(Bgnus \e$B$O$=$l$rFI$_9~$`$+\e(B
+\e$B$I$&$+$rMxMQ<T$K?R$M$^$9!#K\Ev$N5/F0%U%!%$%k$,J]B8$5$l$l$P!"<+F0J]B8%U%!\e(B
+\e$B%$%k$O:o=|$5$l$^$9!#\e(B
+
+@vindex gnus-use-dribble-file
+@code{gnus-use-dribble-file} \e$B$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O%I%j%V%k%P%C\e(B
+\e$B%U%!$r$D$/$C$?$j!"0];}$7$?$j$7$^$;$s!#=i4|CM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@vindex gnus-dribble-directory
+Gnus \e$B$O%I%j%V%k%U%!%$%k$r\e(B @code{gnus-dribble-directory} \e$B$KCV$-$^$9!#%G%#\e(B
+\e$B%U%)%k%H$G$O$=$N$h$&$K$J$C$F$$$^$9$,!"$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"\e(B
+gnus \e$B$O%U%!%$%k\e(B@file{.newsrc} \e$B$NCV$+$l$F$$$k%G%#%l%/%H%j\e(B (\e$B$3$l$OIaDL$OMx\e(B
+\e$BMQ<T$N%[!<%`%G%#%l%/%H%j$G$9\e(B) \e$B$KF~$C$F$$$C$F%I%j%V%k%U%!%$%k$r:n$j$^$9!#\e(B
+\e$B%I%j%V%k%U%!%$%k$O\e(B @file{.newsrc} \e$B$HF1$85v2DB0@-$rM?$($i$l$^$9!#\e(B
+
+@vindex gnus-always-read-dribble-file
+\e$B$b$7\e(B @code{gnus-always-read-dribble-file} \e$B$,\e(B @code{nil} \e$B$G$J$1$l$P!"\e(B
+gnus \e$B$OMxMQ<T$K?R$M$k;vL5$/!"%I%j%V%k%U%!%$%k$r5/F0;~$KFI$_9~$_$^$9!#\e(B
+
+@node The Active File
+@section \e$B%"%/%F%#%V%U%!%$%k\e(B
+@cindex active file
+@cindex ignored groups
+
+Gnus \e$B$O5/F0$7$?$H$-$d!"<B:]$K?7$7$$5-;v$,E~Ce$7$F$$$k$+$r7hDj$7$h$&$H$9\e(B
+\e$B$k$H$-$K!"%"%/%F%#%V%U%!%$%k$rFI$_9~$_$^$9!#$3$l$O$H$F$bBg$-$J%U%!%$%k$G!"\e(B
+\e$B$=$N%5!<%P!<$N3hF0Cf$N%0%k!<%W$H5-;v$N$9$Y$F$N%j%9%H$,F~$C$F$$$^$9!#\e(B
+
+@vindex gnus-ignored-newsgroups
+\e$B%"%/%F%#%V%U%!%$%k$r8!::$9$kA0$K!"\e(Bgnus \e$B$O@55,I=\e(B
+\e$B8=\e(B @code{gnus-ignored-newsgroups} \e$B$K9g$&$9$Y$F$N9T$r:o=|$7$^$9!#$3$l$O<g\e(B
+\e$B$K56$NL>A0$r;}$D%0%k!<%W$rGS=|$9$k$?$a$K;H$o$l$F$-$^$7$?$,!"6=L#$NL5$$%0\e(B
+\e$B%k!<%W$N3,AX$rL5;k$9$k$?$a$K;H$&$3$H$b$G$-$^$9!#$7$+$7!"$3$l$O$*4+$a$G$-\e(B
+\e$B$^$;$s!#K\Ev$N$3$H$r8@$&$H!"A4$/;?@.$G$-$^$;$s!#Be$o$j$K!"$=$N$h$&$JMQES\e(B
+\e$B$KMQ$$$i$l$kJQ?t$N35N,$rCN$k$?$a$K!"\e(B@ref{New Groups} \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@c This variable is
+@c @code{nil} by default, and will slow down active file handling somewhat
+@c if you set it to anything else.
+
+@vindex gnus-read-active-file
+@c @head
+\e$B%"%/%F%#%V%U%!%$%k$OHf3SE*Bg$-$/$J$k798~$,$"$k$N$G!"CY$$2s@~$r;H$C$F$$$k\e(B
+\e$B$H$-$O!"%"%/%F%#%V%U%!%$%k$rFI$_9~$^$J$$$h$&\e(B
+\e$B$K\e(B @code{gnus-read-active-file} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+\e$B$3$NJQ?t$O=i4|@_Dj$G$O\e(B @code{some} \e$B$G$9!#\e(B
+
+\e$B$=$N$h$&$J;~$O!"\e(Bgnus \e$B$O<B:]$K9XFI$5$l$F$$$k%0%k!<%W$K4X$9$k>pJs$@$1$rF@\e(B
+\e$B$F$d$C$F$$$3$&$H$7$^$9!#\e(B
+
+\e$B5$$rIU$1$F$[$7$$$N$O!"$"$J$?$,;3$[$I$N$?$/$5$s$N%0%k!<%W$r9XFI$7$F$$$k$H\e(B
+\e$B$-$K$3$NJQ?t$r\e(B @code{nil} \e$B@_Dj$9$k$H!"\e(Bgnus \e$B$OB.$/$J$k$I$3$m$+!"CY$/$J$C\e(B
+\e$B$F$7$^$&$H$$$&$3$H$G$9!#8=>u$G$O!"%K%e!<%9$r\e(B 2400bps \e$B0J>e$N%b%G%`$rDL$7\e(B
+\e$B$FFI$s$G$$$k$N$G$J$$8B$j!"\e(Bgnus \e$B$NB.EY$O$+$J$jCY$/$J$k$G$7$g$&!#\e(B
+
+\e$B$3$NJQ?t$O\e(B @code{some} \e$B$H$$$&CM$b<h$k$3$H$,$G$-$^$9!#$=$N;~$O!"\e(Bgnus \e$B$O8=\e(B
+\e$B>u$N>pJs$r9XFI$5$l$F$$$k%0%k!<%W$N$b$N$@$1$rF@$h$&$H$7$^$9!#$$$/$D$+$N%5!<\e(B
+\e$B%P!<\e(B (\e$BL?Na\e(B @code{LIST ACTIVE group} \e$B$r;H$&$3$H$N$G$-$k!":G?71T$N\e(B INN \e$B%5!<\e(B
+\e$B%P!<\e(B) \e$B$G$O!"Hs>o$KAa$/$J$k$G$7$g$&$,!"B>$N%5!<%P!<$G$OB.$/$O$"$j$^$;$s!#\e(B
+\e$B$I$N$h$&$K$;$h!"CY$$2s@~$G$O\e(B @code{some} \e$B$O\e(B @code{nil} \e$B$h$j$bB.$/!"$=$l\e(B
+\e$B$O$b$A$m$s\e(B@code{t} \e$B$h$j$bB.$/$J$j$^$9!#\e(B
+
+\e$B$$$/$D$+$N%K%e!<%9%5!<%P!<\e(B (\e$BNc$($P8E$$\e(B Leafnode \e$B$d8E$$\e(B INN) \e$B$K$OL?\e(B
+\e$BNa\e(B @code{LIST ACTIVE group} \e$B$,$"$j$^$;$s!#$=$&$$$&%5!<%P!<$K\e(B
+\e$B$O\e(B @code{nil} \e$B$r$3$NJQ?t$NCM$K@_Dj$9$k$N$,!"$*$=$i$/$b$C$H$bM-8z$G$7$g$&!#\e(B
+
+\e$B$b$7$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O40A4$K$,$s$8$,$i$a$NJ}K!$G%0\e(B
+\e$B%k!<%W$N>pJs$rF@$h$&$H$7$^$9!#$=$7$F!"$3$l$O$"$^$jB.$/$"$j$^$;$s!#$b$7$=\e(B
+\e$B$l$,\e(B @code{some} \e$B$G\e(B @acronym{NNTP} \e$B%5!<%P!<$r;H$C$F$$$k$H$-$O!"\e(Bgnus \e$B$O$G\e(B
+\e$B$-$k$@$1B.$/L?Na$r=P$7!"0l7b$G$9$Y$F$NJVEz$rFI$_9~$_$^$9!#$3$NJ}$,IaDL$O\e(B
+\e$B$h$jNI$$7k2L$r$b$?$i$7$^$9$,!"%5!<%P!<$,L?Na\e(B @code{LIST ACTIVE group} \e$B$r\e(B
+\e$BM}2r$7$J$$$J$i!"%5!<%P!<$K$H$C$F$O$"$^$jNI$$$H$O8@$($^$;$s!#\e(B
+
+Gnus \e$B$N5/F0$K$"$^$j$K;~4V$,$+$+$k$H;W$C$?$J$i!"$3$NJQ?t$K$3$l$i$N;0$D$N\e(B
+\e$B0c$C$?CM$r;n$7$F$_$F!"$I$l$,0lHVNI$$$+$rC5$7$F$/$@$5$$!#\e(B
+
+@code{some} \e$B$+\e(B @code{nil} \e$B$r;H$&$N$G$"$l$P!"$I$A$i$K$7$mB.EY$r>e$2$k$?$a\e(B
+\e$B$K$9$Y$F$N6=L#$NL5$$%0%k!<%W$rI,$::o=|$9$k$Y$-$G$7$g$&!#\e(B
+
+\e$B$3$NJQ?t$OFs<!\e(B (secondary) \e$BA*BrJ}K!$N%"%/%F%#%V%U%!%$%k<hF@$K$b1F6A$9$k\e(B
+\e$B$3$H$K5$$rIU$1$F$/$@$5$$!#\e(B
+
+@node Startup Variables
+@section \e$B5/F0JQ?t\e(B
+
+@table @code
+@item gnus-load-hook
+@vindex gnus-load-hook
+Gnus \e$B$,FI$_9~$^$l$F$$$k$H$-$K<B9T$5$l$k%U%C%/$G$9!#2?EY\e(B gnus \e$B$r5/F0$7$F\e(B
+\e$B$b!"\e(BEmacs \e$B$,5/F0$7$F$+$i=*N;$9$k$^$G$KIaDL$O$3$N%U%C%/$O0l2s$7$+<B9T$5$l\e(B
+\e$B$J$$$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+
+@item gnus-before-startup-hook
+@vindex gnus-before-startup-hook
+Gnus \e$B$N5/F0$K@.8y$7$?8e$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-startup-hook
+@vindex gnus-startup-hook
+Gnus \e$B$,5/F0$5$l$?8e$K!"0lHV:G8e$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-started-hook
+@vindex gnus-started-hook
+Gnus \e$B$N5/F0$K@.8y$7$?8e$K!"0lHV:G8e$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-setup-news-hook
+@vindex gnus-setup-news-hook
+
+\e$B%U%!%$%k\e(B @file{.newsrc} \e$B$rFI$_9~$s$@8e$G!"%0%k!<%W%P%C%U%!$r:n@.$9$kA0$K\e(B
+\e$B<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-check-bogus-newsgroups
+@vindex gnus-check-bogus-newsgroups
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O5/F0;~$KD4$Y$F$9$Y$F$N56%0%k!<%W$r:o=|\e(B
+\e$B$7$^$9!#\e(B@dfn{\e$B56%0%k!<%W\e(B (bogus group)} \e$B$O$"$J$?$N\e(B @file{.newsrc} \e$B%U%!%$\e(B
+\e$B%k$K$OB8:_$9$k$1$l$I!"%K%e!<%9%5!<%P!<$K$O<B:]$K$OB8:_$7$J$$!"$H$$$&%0%k!<\e(B
+\e$B%W$N$3$H$G$9!#56%0%k!<%W$rD4$Y$k$N$K$O$+$J$j;~4V$,$+$+$j$^$9$N$G!";~4V$H\e(B
+\e$B;q8;$r@aLs$9$k$?$a$K!"$3$N5!G=$O;H$o$J$$$[$&$,$$$$$G$7$g$&!#$=$7$F!"Be$o\e(B
+\e$B$j$K%0%k!<%W%P%C%U%!$G;~!956%0%k!<%W$rD4$Y$k$N$,NI$$$G$7$g\e(B
+\e$B$&\e(B (@pxref{Group Maintenance})\e$B!#\e(B
+
+@item gnus-inhibit-startup-message
+@vindex gnus-inhibit-startup-message
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"5/F0;~$N%a%C%;!<%8$OI=<($5$l$^$;$s!#$=$N$h$&$K\e(B
+\e$B$9$l$P!";E;v$NBe$o$j$K%K%e!<%9$rFI$s$G$$$k$N$r>e;J$K5$IU$+$l$K$/$/$J$k$G\e(B
+\e$B$7$g$&!#$3$NJQ?t$O\e(B @file{~/.gnus.el} \e$B$,%m!<%I$5$l$kA0$K;H$o$l$^$9$N$G!"\e(B
+@file{.emacs} \e$B$K@_Dj$9$k$Y$-$G$"$kE@$rCm0U$7$F$/$@$5$$!#\e(B
+
+@item gnus-no-groups-message
+@vindex gnus-no-groups-message
+\e$B%0%k!<%W$,0l$D$bB8:_$7$J$$$H$-$K\e(B gnus \e$B$,I=<($9$k%a%C%;!<%8$G$9!#\e(B
+
+@item gnus-play-startup-jingle
+@vindex gnus-play-startup-jingle
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"5/F0;~$K\e(B gnus \e$B$NC;$$6J$r1iAU$7$^$9!#\e(B
+
+@item gnus-startup-jingle
+@vindex gnus-startup-jingle
+\e$B>e$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H$-$K1iAU$5$l$kC;$$6J$G$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{Tuxdemoon.Jingle4.au} \e$B$G$9!#\e(B
+@end table
+
+@node Group Buffer
+@chapter \e$B%0%k!<%W%P%C%U%!\e(B
+@cindex group buffer
+
+@c Alex Schroeder suggests to rearrange this as follows:
+@c
+@c <kensanata> ok, just save it for reference.  I'll go to bed in a minute.
+@c   1. Selecting a Group, 2. (new) Finding a Group, 3. Group Levels,
+@c   4. Subscription Commands, 5. Group Maneuvering, 6. Group Data,
+@c   7. Group Score, 8. Group Buffer Format
+@c <kensanata> Group Levels should have more information on levels 5 to 9.  I
+@c   suggest to split the 4th paragraph ("Gnus considers groups...") as follows:
+@c <kensanata> First, "Gnus considers groups... (default 9)."
+@c <kensanata> New, a table summarizing what levels 1 to 9 mean.
+@c <kensanata> Third, "Gnus treats subscribed ... reasons of efficiency"
+@c <kensanata> Then expand the next paragraph or add some more to it.
+@c    This short one sentence explains levels 1 and 2, therefore I understand
+@c    that I should keep important news at 3 and boring news at 4.
+@c    Say so!  Then go on to explain why I should bother with levels 6 to 9.
+@c    Maybe keep those that you don't want to read temporarily at 6,
+@c    those that you never want to read at 8, those that offend your
+@c    human rights at 9...
+
+\e$B%0%k!<%W%P%C%U%!\e(B (@dfn{group buffer}) \e$B$OM-8z$J%0%k!<%W$rA4It\e(B (\e$B$"$k$$$O0l\e(B
+\e$BIt$r\e(B) \e$B0lMwI=<($7$^$9!#$3$l$O\e(B gnus \e$B$r5/F0$7$?$H$-$K:G=i$KI=<($5$l$k%P%C%U%!\e(B
+\e$B$G!"\e(Bgnus \e$B$,@8$-$F$$$k8B$j7h$7$F>C$5$l$k$3$H$O$"$j$^$;$s!#\e(B
+
+@iftex
+@iflatex
+\gnusfigure{The Group Buffer}{320}{
+\put(75,50){\epsfig{figure=ps/group,height=9cm}}
+\put(120,37){\makebox(0,0)[t]{Buffer name}}
+\put(120,38){\vector(1,2){10}}
+\put(40,60){\makebox(0,0)[r]{Mode line}}
+\put(40,58){\vector(1,0){30}}
+\put(200,28){\makebox(0,0)[t]{Native select method}}
+\put(200,26){\vector(-1,2){15}}
+}
+@end iflatex
+@end iftex
+
+@menu
+* Group Buffer Format::         \e$BI=<($5$l$F$$$k>pJs$HJQ99$NJ}K!\e(B
+* Group Maneuvering::           \e$B%0%k!<%W%P%C%U%!$r0\F0$9$k%3%^%s%I\e(B
+* Selecting a Group::           \e$B<B:]$K%K%e!<%9$rFI$`\e(B
+* Subscription Commands::       \e$B9XFI!"9XFICf;_!">C5n\e(B
+* Group Data::                  \e$B%0%k!<%W$N>pJs$rJQ99$9$k\e(B
+* Group Levels::                \e$B%l%Y%k\e(B? \e$B$=$l$C$F2?\e(B?
+* Group Score::                 \e$B$"$J$?$N9%$-$J%0%k!<%W$r8+$D$1=P$9J}K!\e(B
+* Marking Groups::              \e$B%0%k!<%W$K0u$r$D$1$F$*$$$F!"8e$G=hM}$G$-$^$9\e(B
+* Foreign Groups::              \e$B%0%k!<%W$N:n@.$H=$@5\e(B
+* Group Parameters::            \e$B%0%k!<%WKh$K0c$C$?%Q%i%a!<%?$r;}$?$;$i$l$^$9\e(B
+* Listing Groups::              Gnus \e$B$O%0%k!<%W$r$$$m$$$m$JJ,$1J}$GI=<($G$-$^$9\e(B
+* Sorting Groups::              \e$B%0%k!<%W$N=gHV$NG[CVBX$(\e(B
+* Group Maintenance::           \e$B$-$l$$$J\e(B @file{.newsrc} \e$B$NJ]$AJ}\e(B
+* Browse Foreign Server::       \e$B%5!<%P$r354Q$G$-$k!#2?$,FI$a$k$N$+8+$F$_$h$&\e(B
+* Exiting Gnus::                \e$B%K%e!<%9FI$`$N$r$d$a$F!";E;v$r$7$h$&\e(B
+* Group Topics::                \e$B%0%k!<%W$r@Z$j:.$<$F!"%H%T%C%/$4$H$KJ,3d$9$k\e(B
+* Misc Group Stuff::            \e$BB>$K$G$-$k$3$H\e(B
+@end menu
+
+@node Group Buffer Format
+@section \e$B%0%k!<%W%P%C%U%!$N7A<0\e(B
+
+@menu
+* Group Line Specification::    \e$B%0%k!<%W%P%C%U%!$N8+$(J}$r7h$a$k\e(B
+* Group Mode line Specification::  \e$B%0%k!<%W%P%C%U%!$N%b!<%I9T\e(B
+* Group Highlighting::          \e$B%0%k!<%W%P%C%U%!$K$-$l$$$K?'$r$D$1$k\e(B
+@end menu
+
+@node Group Line Specification
+@subsection \e$B%0%k!<%W9T$N;EMM\e(B
+@cindex group buffer format
+
+\e$B%0%k!<%W%P%C%U%!$N=i4|@_Dj7A<0$O$-$l$$$G$D$^$s$J$$$1$I!"$3$l$O7/$N9%$-$J\e(B
+\e$B$h$&$K!"%5%$%3!<$K%@%5$/$9$k$3$H$b$G$-$^$9!#\e(B
+
+\e$B$3$l$,%0%k!<%W9T$NNc$G$9!#\e(B
+
+@example
+     25: news.announce.newusers
+ *    0: alt.fan.andrea-dworkin
+@end example
+
+\e$B$H$C$F$b4JC1$G$7$g\e(B?
+
+@samp{news.announce.newusers} \e$B$K$O\e(B 25 \e$B$NL$FI5-;v$,$"$k$N$,$o$+$j$^$9!#\e(B
+@samp{alt.fan.andrea-dworkin} \e$B$K$OL$FI5-;v$O$J$$$1$l$I$b!"0u$r$D$1$?5-;v\e(B
+\e$B$,$$$/$D$+$"$j$^$9\e(B (\e$B9TF,$N$A$C$A$c$J%"%9%?%j%9%/$,8+$($k\e(B?)\e$B!#\e(B
+
+@vindex gnus-group-line-format
+\e$B$3$N7A<0$O\e(B @code{gnus-group-line-format} \e$BJQ?t$r$$$8$k$3$H$G!"$I$s$JIw$K\e(B
+\e$B$G$bJQ$($i$l$^$9!#$3$NJQ?t$O\e(B @code{format} \e$B$N;EMMIw$KF0:n$7$^$9!#$D$^\e(B
+\e$B$j\e(B (\e$B$"$N%/%=\e(B) C \e$B8@8l$r;H$&?M$?$A$N$?$a!"\e(Bprintf \e$B$N;EMM$H$[$\F1$8$G$9!#\e(B
+@xref{Formatting Variables}.
+
+@samp{%M%S%5y:%B%(%g%)\n} \e$B$H$$$&CM$G>e5-$N9T$r@8@.$7$^$9!#\e(B
+
+\e$B%3%m%s$O!"$3$N9T$NCf$KI,$:L5$/$F$O$$$1$^$;$s!#%+!<%=%k$O!"2?$+$NA`:n$r$7\e(B
+\e$B$?8e$O>o$K%3%m%s$N$H$3$m$K0\F0$9$k$+$i$G$9!#\e(B@xref{Positioning Point}. \e$BB>\e(B
+\e$B$K$O2?$bI,MW$G$O$"$j$^$;$s!=!=%0%k!<%WL>$5$($b$G$9!#I=<($5$l$F$$$kJ8;z$O\e(B
+\e$BA4$F$?$@$N2hLL$N>~$j$G$"$j!"\e(Bgnus \e$B$,$=$l$rD4$Y$k$3$H$O$"$j$^$;$s!#\e(BGnus \e$B$O\e(B
+\e$BI,MW$H$9$kA4$F$N<B>pJs$r!"%F%-%9%HB0@-$r;H$C$F21$($F$$$^$9!#\e(B
+
+(\e$B$b$77/$,!"$9$4$/%X%s$J!"AG@2$i$7$$!"I=7W;;Iw$N%l%$%"%&%H$r:n$C$?$H$7$?\e(B
+\e$B$i!"$_$s$J!"7/$O2q7W$N;E;v$,K;$7$/$C$F!"%K%e!<%9$rFI$s$G;~4V$rL5BL;H$$$7\e(B
+\e$B$?$j$J$s$+$7$F$J$$!"$C$F?.$8$F$/$l$k$h!#\e(B)
+
+\e$B0J2<$,;HMQ$G$-$k%U%)!<%^%C%HJ8;z$N%j%9%H$G$9!#\e(B
+
+@table @samp
+@item M
+\e$B$=$N%0%k!<%W$,0u$N$D$$$?5-;v$@$1$N$H$-$O!"%"%9%?%j%9%/J8;z!#\e(B
+
+@item S
+\e$B$=$N%0%k!<%W$,9XFI$5$l$F$$$k$+$I$&$+!#\e(B
+
+@item L
+\e$B9XFIEY$N%l%Y%k!#\e(B
+
+@item N
+\e$BL$FI5-;v$N?t!#\e(B
+
+@item I
+\e$BJ]N15-;v$N?t!#\e(B
+
+@item T
+\e$B0uIU$-5-;v$N?t!#\e(B
+
+@item R
+\e$B4{FI5-;v$N?t!#\e(B
+
+@item U
+\e$B$^$@FI$^$l$?$3$H$,L5$$5-;v$N?t!#\e(B
+
+@item t
+\e$B?dDjA45-;v?t\e(B (\e$B$3$l$O<B:]$O\e(B @var{max-number} - @var{min-number} + 1)\e$B!#\e(B
+
+gnus \e$B$,$3$N?dDj$r;H$&$N$O!"\e(B@acronym{NNTP} \e$B%W%m%H%3%k$OG=N($NNI\e(B
+\e$B$$\e(B @var{max-number} \e$B$H\e(B @var{min-number} \e$B$X$N%"%/%;%9$rDs6!$9$k$b$N$N!"K\\e(B
+\e$BEv$NL$FI5-;v$N?t$rF@$k$K$OI,$:$7$bG=N(E*$G$O$J$$$+$i$G$9!#%R%9%F%j%C%/$J\e(B
+\e$B%l!<%:%s\e(B (\e$BLuCm\e(B: \e$BNr;KE*$JM}M3$N%b%8$j$+\e(B?) \e$B$K$h$j!"%a!<%k%P%C%/%(%s%I$K$*\e(B
+\e$B$$$F$b!"8BDj$5$l$?F1$8%$%s%?!<%U%'!<%9$r;H$C$F!"K\Ev$NL$FI5-;v$N?t$rG=N(\e(B
+\e$BE*$KF@$k$3$H$O$G$-$k$+$b$7$l$^$;$s!#$3$N@)8B$r\e(B Gnus \e$B$+$i<h$jJ'$&$3$H$O%P%C\e(B
+\e$B%/%(%s%I$N%$%s%?!<%U%'!<%9$rJQ99$9$k$3$H$r0UL#$7!"$=$l$O3Z$J;E;v$G$O$"$j\e(B
+\e$B$^$;$s!#$"$J$?$,$3$N;E;v$r$d$j$?$$$J$i$P!"$I$&$>\e(B Gnus \e$B%a!<%j%s%0%j%9%H$K\e(B
+\e$BO"Mm$7$F2<$5$$!#\e(B
+
+@item y
+\e$BL$FI$G$b!"0uIU$-$G$b!"J]N1$G$b$J$$5-;v$N?t!#\e(B
+
+@item i
+\e$B0uIU$-5-;v$HJ]N15-;v$N?t!#\e(B
+
+@item g
+\e$B%0%k!<%WL>$N%U%k%M!<%`!#\e(B
+
+@item G
+\e$B%0%k!<%WL>!#\e(B
+
+@item C
+\e$B%0%k!<%W%Q%i%a!<%?$K%3%a%s%H$NMWAG$,L5$$>l9g$N%3%a%s\e(B
+\e$B%H\e(B (@pxref{Group Parameters}) \e$B$^$?$O%0%k!<%WL>!#\e(B
+
+@item D
+\e$B%K%e!<%9%0%k!<%W$N@bL@!#$3$l$i$,8=$l$kA0$K!"%0%k!<%W$N@bL@$rFI$`I,MW$,$"\e(B
+\e$B$j$^$9!#$=$l$K$O\e(B @code{gnus-read-active-file} \e$B$r@_Dj$9$k$+!"%0%k!<%W%P%C\e(B
+\e$B%U%!$G\e(B @kbd{M-d} \e$B%3%^%s%I$r;H$C$F2<$5$$!#\e(B
+
+@item o
+\e$B;J2q<TIU$-$N>l9g\e(B @samp{m}\e$B!#\e(B
+
+@item O
+\e$B;J2q<TIU$-$N>l9g\e(B @samp{(m)}\e$B!#\e(B
+
+@item s
+\e$BA*BrJ}K!!#\e(B
+
+@item B
+\e$B$=$N%0%k!<%W$N35N,%P%C%U%!!<$,3+$$$F$$$k$+$I$&$+!#\e(B
+
+@item n
+\e$B$I$3$+$i$NA*Br$+!#\e(B
+
+@item z
+\e$B30ItA*BrJ}K!$,;H$o$l$F$$$k>l9g!"\e(B@samp{<%s:%n>} \e$B$HF1$8J8;zNs!#\e(B
+
+@item P
+\e$B%H%T%C%/\e(B (@pxref{Group Topics}) \e$B$N%l%Y%k$K1~$8$?;z2<$2!#\e(B
+
+@item c
+@vindex gnus-group-uncollapsed-levels
+\e$BC;$$\e(B (\e$B>JN,$7$?\e(B) \e$B%0%k!<%WL>!#\e(B@code{gnus-group-uncollapsed-levels} \e$BJQ?t$O!"\e(B
+\e$B$I$N%l%Y%k$^$G%0%k!<%WL>$rA4It;D$9$+$r<($7$^$9!#=i4|CM$O\e(B 1 \e$B$G$9!=!=$3\e(B
+\e$B$N0UL#$O!"\e(B@samp{gnu.emacs.gnus} \e$B$N$h$&$J%0%k!<%WL>\e(B
+\e$B$r\e(B @samp{g.e.gnus} \e$B$KC;=L$9$k$H$$$&$3$H$G$9!#\e(B
+
+@item m
+@vindex gnus-new-mail-mark
+@cindex %
+\e$B$=$N%0%k!<%W$K:G6a?7Ce%a!<%k$,FO$$$F$$$k>l9g\e(B
+\e$B$O\e(B @samp{%} (@code{gnus-new-mail-mark})\e$B!#\e(B
+
+@item p
+@samp{#} (@code{gnus-process-mark}) \e$B$G!"$=$N%0%k!<%W$K%W%m%;%9%^!<%/$,IU\e(B
+\e$B$$$F$$$k$3$H$r<($7$^$9!#\e(B
+
+@item d
+\e$B:G8e$K$$$D$3$N%0%k!<%W$rFI$s$@$+$r<($9J8;zNs\e(B (@pxref{Group Timestamp})\e$B!#\e(B
+
+@item u
+\e$BMxMQ<TDj5A;XDj!#%U%)!<%^%C%HJ8;zNsCf$G!"$3$N<!$NJ8;z$O%"%k%U%!%Y%C%HJ8;z\e(B
+\e$B$G$J$1$l$P$$$1$^$;$s!#\e(B
+Gnus \e$B$O\e(B @code{gnus-user-format-function-}@samp{X} \e$B4X?t$r8F$S=P$7$^$9!#$3\e(B
+\e$B$3$G\e(B @samp{X} \e$B$O\e(B @samp{%u} \e$B$KB3$$$F$$$kJ8;z$G$9!#$3$N4X?t$O0z?t$K!"0l$D\e(B
+\e$B$N%@%_!<%Q%i%a!<%?$rEO$5$l$^$9!#$3$N4X?t$O!"B>$N3F;XDjJ8;z$N>pJs$HF1MM$K!"\e(B
+\e$B%P%C%U%!$KA^F~$5$l$kJ8;zNs$rJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+@end table
+
+@cindex *
+\e$BA4$F$N!V!A$N?t!W$N;XDj$G!"$b$7$=$N>pJs$,MxMQ$G$-$J$$>l9g$K$O%"%9%?%j%9\e(B
+\e$B%/\e(B (@samp{*}) \e$B$,Kd$a$i$l$^$9!=!=Nc$($P!"5/F0$5$l$F$$$J$$30It%0%k!<%W$d!"\e(B
+\e$BIT@5$J4pK\%0%k!<%W$N>l9g$G$9!#\e(B
+
+@node Group Mode line Specification
+@subsection \e$B%0%k!<%W%b!<%I9T$N;EMM\e(B
+@cindex group mode line
+
+@vindex gnus-group-mode-line-format
+\e$B%b!<%I9T\e(B
+\e$B$O\e(B @code{gnus-group-mode-line-format} (@pxref{Mode Line Formatting}) \e$B$r\e(B
+\e$B@_Dj$9$k$3$H$GJQ99$G$-$^$9!#$3$$$D$O;XDjJ8;z$r$"$s$^$j$?$/$5$sCN$C$F$^$;\e(B
+\e$B$s!#\e(B
+
+@table @samp
+@item S
+\e$B4pK\%K%e!<%9%5!<%P!<!#\e(B
+@item M
+\e$B4pK\A*BrJ}K!!#\e(B
+@end table
+
+@node Group Highlighting
+@subsection \e$B%0%k!<%W$N%O%$%i%$%H\e(B
+@cindex highlighting
+@cindex group highlighting
+
+@vindex gnus-group-highlight
+\e$B%0%k!<%W%P%C%U%!$N%O%$%i%$%H$O\e(B @code{gnus-group-highlight} \e$BJQ?t$K$h$C$F\e(B
+\e$B@)8f$5$l$F$$$^$9!#$3$l$O\e(B @code{(@var{form} . @var{face})} \e$B$N$h$&$J$b$N$r\e(B
+\e$BMWAG$K;}$DO"A[%j%9%H$G$9!#\e(B@var{form} \e$B$,2?$+\e(B @code{nil} \e$B0J30$KI>2A$5$l$k\e(B
+\e$B$b$N$J$i!"$=$N9T$KBP$7$F\e(B @var{face} \e$B$,;HMQ$5$l$^$9!#\e(B
+
+\e$B0J2<$,$3$NJQ?t$NCM$NNc$G$9!#$3$l$OGX7J$,0E$$@_Dj$G$O$-$l$$$K8+$($k$+$bCN\e(B
+\e$B$l$^$;$s!#\e(B
+
+@lisp
+(cond (window-system
+       (setq custom-background-mode 'light)
+       (defface my-group-face-1
+         '((t (:foreground "Red" :bold t))) "First group face")
+       (defface my-group-face-2
+         '((t (:foreground "DarkSeaGreen4" :bold t))) "Second group face")
+       (defface my-group-face-3
+         '((t (:foreground "Green4" :bold t))) "Third group face")
+       (defface my-group-face-4
+         '((t (:foreground "SteelBlue" :bold t))) "Fourth group face")
+       (defface my-group-face-5
+         '((t (:foreground "Blue" :bold t))) "Fifth group face")))
+
+(setq gnus-group-highlight
+      '(((> unread 200) . my-group-face-1)
+        ((and (< level 3) (zerop unread)) . my-group-face-2)
+        ((< level 3) . my-group-face-3)
+        ((zerop unread) . my-group-face-4)
+        (t . my-group-face-5)))
+@end lisp
+
+@ref{Faces and Fonts} \e$B$b;2>H$7$F$/$@$5$$!#\e(B
+
+\e$B$3$N\e(B form \e$B$,I>2A$5$l$k$H$-$KF0E*$KB+G{$5$l$F$$$kJQ?t$K$O0J2<$N$b$N$,$"$j\e(B
+\e$B$^$9!#\e(B
+
+@table @code
+@item group
+\e$B%0%k!<%WL>!#\e(B
+@item unread
+\e$B$=$N%0%k!<%W$NL$FI5-;v$N?t!#\e(B
+@item method
+\e$BA*BrJ}K!!#\e(B
+@item mailp
+\e$B$=$N%0%k!<%W$,%a!<%k$N%0%k!<%W$+$I$&$+!#\e(B
+@item level
+\e$B$=$N%0%k!<%W$N%l%Y%k!#\e(B
+@item score
+\e$B$=$N%0%k!<%W$N%9%3%"!#\e(B
+@item ticked
+\e$B$=$N%0%k!<%WCf$N0u$NIU$$$?5-;v$N?t!#\e(B
+@item total
+\e$B$=$N%0%k!<%WCf$NA45-;v?t!#$b$C$H@53N$K8@$&$H!"\e(B@var{max-number} \e$B%^%$%J%9\e(B
+@var{min_number} \e$B%W%i%9\e(B 1.
+@item topic
+\e$B%H%T%C%/%^%$%J!<%b!<%I$r;HMQ$7$F$$$k;~!"$3$NJQ?t$OA^F~$5$l$F$$$k8=:_$N%H\e(B
+\e$B%T%C%/$KB+G{$5$l$^$9!#\e(B
+@end table
+
+\e$B$3$N\e(B form \e$B$,I>2A\e(B (@code{eval}) \e$B$5$l$k$H$-$O!"%]%$%s%H$OLdBj$N%0%k!<%W$N\e(B
+\e$B9TF,$K$"$j$^$9!#=>$C$F!"DL>o$N\e(B gnus \e$B$N4X?t$N$[$H$s$I$r;H$C$F$=$N%0%k!<%W\e(B
+\e$B$N>pJs$r<h$C$F$/$k$3$H$,$G$-$^$9!#\e(B
+
+@vindex gnus-group-update-hook
+@findex gnus-group-highlight-line
+@code{gnus-group-update-hook} \e$B$O%0%k!<%W9T$,JQ99$5$l$?$H$-$K8F$S=P$5$l$^\e(B
+\e$B$9!#$3$l$O\e(B @code{gnus-visual} \e$B$,\e(B @code{nil} \e$B$N$H$-$O8F$S=P$5$l$^$;$s!#$3\e(B
+\e$B$N%U%C%/$O=i4|@_Dj$G$O\e(B @code{gnus-group-highlight-line} \e$B$r8F$S=P$7$^$9!#\e(B
+
+@node Group Maneuvering
+@section \e$B%0%k!<%WA`:n\e(B
+@cindex group movement
+
+\e$BA4$F$N0\F0%3%^%s%I$O?t;z@\F,0z?t$rM}2r$9$k$N$G!"4|BT$9$kDL$j$NF0:n$r$7$^\e(B
+\e$B$9!#$?$V$s$M!#\e(B
+
+@table @kbd
+@item n
+@kindex n (\e$B%0%k!<%W\e(B)
+@findex gnus-group-next-unread-group
+\e$B<!$NL$FI5-;v$N$"$k%0%k!<%W$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-next-unread-group})\e$B!#\e(B
+
+@item p
+@itemx DEL
+@kindex DEL (\e$B%0%k!<%W\e(B)
+@kindex p (\e$B%0%k!<%W\e(B)
+@findex gnus-group-prev-unread-group
+\e$B0l$DA0$NL$FI5-;v$N$"$k%0%k!<%W$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-prev-unread-group})\e$B!#\e(B
+
+@item N
+@kindex N (\e$B%0%k!<%W\e(B)
+@findex gnus-group-next-group
+\e$B<!$N%0%k!<%W$K0\F0$7$^$9\e(B (@code{gnus-group-next-group})\e$B!#\e(B
+
+@item P
+@kindex P (\e$B%0%k!<%W\e(B)
+@findex gnus-group-prev-group
+\e$B0l$DA0$N%0%k!<%W$K0\F0$7$^$9\e(B (@code{gnus-group-prev-group})\e$B!#\e(B
+
+@item M-n
+@kindex M-n (\e$B%0%k!<%W\e(B)
+@findex gnus-group-prev-unread-group-same-level
+\e$B0l$DA0$NF1$8%l%Y%k\e(B (\e$B$b$7$/$O$=$l$h$j>.$5$$%l%Y%k\e(B) \e$B$NL$FI%0%k!<%W$K0\F0$7\e(B
+\e$B$^$9\e(B (@code{gnus-group-prev-unread-group-same-level})\e$B!#\e(B
+
+@item M-p
+@kindex M-p (\e$B%0%k!<%W\e(B)
+@findex gnus-group-next-unread-group-same-level
+\e$B<!$NF1$8%l%Y%k\e(B(\e$B$b$7$/$O$=$l$h$j>.$5$$%l%Y%k\e(B)\e$B$NL$FI%0%k!<%W$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-next-unread-group-same-level})\e$B!#\e(B
+@end table
+
+\e$B<!$N;0$D$NL?Na$O%0%k!<%W$K%8%c%s%W$9$k$?$a$N$b$N$G$9\e(B:
+
+@table @kbd
+@item j
+@kindex j (\e$B%0%k!<%W\e(B)
+@findex gnus-group-jump-to-group
+\e$B%0%k!<%W$K%8%c%s%W$7$^$9\e(B (\e$B$=$l$,8+$($k$h$&$K$J$C$F$$$J$+$C$?$i8+$($k$h$&\e(B
+\e$B$K$7$^$9\e(B) (@code{gnus-group-jump-to-group})\e$B!#\e(Bkill \e$B$5$l$F$$$k%0%k!<%W$b!"\e(B
+\e$B@8$-$F$$$k%0%k!<%W$HF1MM$K%8%c%s%W$G$-$^$9!#\e(B
+
+@item ,
+@kindex , (\e$B%0%k!<%W\e(B)
+@findex gnus-group-best-unread-group
+\e$B:G$b>.$5$$%l%Y%k$NL$FI%0%k!<%W$K%8%c%s%W$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-best-unread-group})\e$B!#\e(B
+
+@item .
+@kindex . (\e$B%0%k!<%W\e(B)
+@findex gnus-group-first-unread-group
+\e$B:G=i$NL$FI5-;v$N$"$k%0%k!<%W$K%8%c%s%W$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-first-unread-group})\e$B!#\e(B
+@end table
+
+@vindex gnus-group-goto-unread
+@code{gnus-group-goto-unread} \e$B$r\e(B @code{nil} \e$B$K$9$k$H!"A4$F$N0\F0%3%^%s%I\e(B
+\e$B$O!"<!$NL$FI%0%k!<%W$G$O$J$/<!$N%0%k!<%W$K0\F0$9$k$h$&$K$J$j$^$9!#$=$N%3\e(B
+\e$B%^%s%I$,<!$NL$FI%0%k!<%W$K0\F0$9$k!"$H8@$$D%$C$F$$$F$b!"$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@node Selecting a Group
+@section \e$B%0%k!<%W$NA*Br\e(B
+@cindex group selection
+
+@table @kbd
+@item SPACE
+@kindex SPACE (\e$B%0%k!<%W\e(B)
+@findex gnus-group-read-group
+\e$B8=:_$N%0%k!<%W$rA*Br$7!"35N,%P%C%U%!$K@Z$jBX$($F:G=i$NL$FI5-;v$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-group-read-group})\e$B!#$b$7$=$N%0%k!<%W$KL$FI5-;v$,L5$$!"$b\e(B
+\e$B$7$/$O$3$NL?Na$K?t;z0J30$N%W%l%U%#%C%/%9$rM?$($k$H!"\e(Bgnus \e$B$O%5!<%P$+$i$3\e(B
+\e$B$N%0%k!<%W$NA4$F$N8E$$5-;v$r<hF@$7$h$&$H$7$^$9!#\e(B@var{n} \e$B$N?t;z@\F,0z?t$r\e(B
+\e$BM?$($k$H!"\e(Bgnus \e$B$N<hF@$9$k5-;v?t$O\e(B @var{n} \e$B$K$J$j$^$9!#\e(B@var{n} \e$B$,@5$N?t$G\e(B
+\e$B$"$l$P\e(B gnus \e$B$O?7$7$$J}$+$i\e(B @var{n} \e$B8D$N5-;v$r<hF@$7!"\e(B@var{n} \e$B$,Ii$N?t$G\e(B
+\e$B$"$l$P\e(B gnus \e$B$O8E$$J}$+$i\e(B @code{abs(@var{n})} \e$B8D$N5-;v$r<hF@$7$^$9!#\e(B
+
+\e$B$7$?$,$C$F!"\e(B@kbd{SPC} \e$B$G$OIaDL$K%0%k!<%W$KF~$j!"\e(B@kbd{C-u SPC} \e$B$G$O8E$$5-\e(B
+\e$B;v$,8=$l$^$9!#\e(B@kbd{C-u 4 2 SPC} \e$B$G$O\e(B 42 \e$B8D$N:G?7$N5-;v$r<hF@$7!"\e(B@kbd{C-u
+- 4 2 SPC} \e$B$G$O\e(B 42 \e$B8D$N:G$b8E$$5-;v$r<hF@$7$^$9!#\e(B
+
+\e$B%0%k!<%W$K$$$k\e(B (\e$B35N,%P%C%U%!$K$$$k\e(B) \e$B$H$-$O!"\e(B@kbd{M-g} \e$B$G?7$7$$5-;v$r<hF@\e(B
+\e$B$G$-$k$7!"\e(B@kbd{C-u M-g} \e$B$G$O8E$$5-;v$rI=<($9$k$3$H$,$G$-$^$9!#\e(B
+
+@item RET
+@kindex RET (\e$B%0%k!<%W\e(B)
+@findex gnus-group-select-group
+\e$B8=:_$N%0%k!<%W$rA*Br$7!"35N,%P%C%U%!$K@Z$jBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-select-group})\e$B!#\e(B@code{gnus-group-read-group} \e$B$HF1$8\e(B
+\e$B0z?t$r<h$j$^$9!=!=M#0l$N0c$$$O!"%0%k!<%W$KF~$C$?$H$-$K:G=i$NL$FI5-;v$rI=\e(B
+\e$B<($7$J$$!"$H$$$&$3$H$G$9!#\e(B
+
+@item M-RET
+@kindex M-RET (\e$B%0%k!<%W\e(B)
+@findex gnus-group-quick-select-group
+\e$B$3$l$O>e5-$N%3%^%s%I$HF1$8F0:n$r$7$^$9$,!"!V%4%?%4%?!W$O:GDc8B$K$7$h$&$H\e(B
+\e$B$7$^$9\e(B (@code{gnus-group-quick-select-group})\e$B!#%9%3%"!&\e(Bkill \e$B$N=hM}$O9T$o\e(B
+\e$B$l$:!"%O%$%i%$%H$b5-;v>C5n$b$7$^$;$s!#$3$l$O!"$"$J$?$,K\Ev$K5^$$$G$$$F!"\e(B
+\e$B$I$C$+$N$d$?$i$G$C$+$$%0%k!<%W$KF~$i$J$1$l$P$$$1$J$$$H$-$KLr$KN)$D$+$b$7\e(B
+\e$B$l$^$;$s!#$^$?!"@\F,<-$K\e(B 0 \e$B$rM?$($l$P\e(B (\e$B$9$J$o$A\e(B @kbd{0 M-RET})\e$B!"\e(Bgnus \e$B$O\e(B
+\e$B35N,%P%C%U%!$r:n$m$&$H$5$($7$^$;$s!#$3$l$O35N,%P%C%U%!$r:n$kA0$K%9%l%C%I\e(B
+\e$BI=<($r@Z$jBX$($?$$$H$-Lr$KN)$A$^$9\e(B (@pxref{Summary Generation Commands})\e$B!#\e(B
+
+@item M-SPACE
+@kindex M-SPACE (\e$B%0%k!<%W\e(B)
+@findex gnus-group-visible-select-group
+\e$B$3$l$O\e(B @kbd{RET} \e$B%3%^%s%I$HF1$8F0:n$r$9$k$5$i$K$b$&0l$D$N%3%^%s%I$G$9$,!"\e(B
+\e$B$3$N%3%^%s%I$O5-;v>C5n$HJ]N15-;v$r1#$9=hM}$r9T$$$^$;\e(B
+\e$B$s\e(B (@code{gnus-group-visible-select-group})\e$B!#\e(B
+
+@item C-M-RET
+@kindex C-M-RET (\e$B%0%k!<%W\e(B)
+@findex gnus-group-select-group-ephemerally
+\e$B:G8e$K$3$N%3%^%s%I$O!"8=:_$N%0%k!<%W$r0lEY8B$j!"$=$NFbMF$K0l@Z$N=hM}$r$9\e(B
+\e$B$k$3$H$N$J$$$h$&$KA*Br$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-select-group-ephemerally})\e$B!#%9%l%C%II=<($5$($b9T$o\e(B
+\e$B$l$^$;$s!#$3$NJ}K!$GA*Br$7$?8e$K$3$N%0%k!<%W$KBP$7$F9T$C$?$3$H$OA4$F!"$=\e(B
+\e$B$N8e$K1F6A$rM?$($k$3$H$O$"$j$^$;$s!#\e(B
+@end table
+
+@vindex gnus-large-newsgroup
+@code{gnus-large-newsgroup} \e$BJQ?t$O!"2?$rBg$-$J%0%k!<%W$H9M$($k$Y$-$+\e(B
+\e$B$r\e(B gnus \e$B$KM?$($^$9!#\e(B@code{nil} \e$B$@$C$?$i!"$I$N%0%k!<%W$bBg$-$$$H9M$($^$;\e(B
+\e$B$s!#%G%#%U%)%k%HCM$O\e(B 200 \e$B$G$9!#%0%k!<%W$K\e(B (\e$BL$FI$H0uIU$-$N\e(B) \e$B5-;v$,$3$N?t\e(B
+\e$B0J>e$"$l$P!"\e(Bgnus \e$B$O$=$N%0%k!<%W$KF~$kA0$KMxMQ<T$K3NG'$r5a$a$^$9!#MxMQ<T\e(B
+\e$B$O%5!<%P$+$i$$$/$D$N5-;v$r<hF@$9$k$+$r;XDj$G$-$^$9!#$b$7MxMQ<T$,Ii$N\e(B
+\e$B?t\e(B (@var{-n}) \e$B$r;XDj$9$l$P!"8E$$J}$+$i\e(B @var{n} \e$B8D$N5-;v$r<hF@$7$^$9!#@5\e(B
+\e$B$N?t$G$"$l$P!"?7$7$/E~Ce$7$?J}$+$i\e(B @var{n} \e$B8D$N5-;v$r<hF@$7$^$9!#\e(B
+
+@vindex gnus-large-ephemeral-newsgroup
+@code{gnus-large-ephemeral-newsgroup} \e$B$O\e(B @code{gnus-large-newsgroup} \e$B$H\e(B
+\e$BF1$8$G$9$,!"0l;~%K%e!<%9%0%k!<%W$N$?$a$K$@$1;H$o$l$^$9!#\e(B
+
+@vindex gnus-select-group-hook
+@vindex gnus-auto-select-first
+@vindex gnus-auto-select-subject
+\e$B$b$7\e(B @code{gnus-auto-select-first} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"\e(B
+@kbd{SPACE} \e$B%3%^%s%I$G%0%k!<%W$KF~$C$?$H$-$K<+F0E*$K5-;v$rA*Br$7$^$9!#$I\e(B
+\e$B$N5-;v$,A*Br$5$l$k$+$O!"JQ?t\e(B @code{gnus-auto-select-subject} \e$B$G@)8f$5$l\e(B
+\e$B$^$9!#$3$NJQ?t$K@_Dj$G$-$kM-8z$JCM$O\e(B:
+
+@table @code
+@item unread
+\e$B:G=i$NL$FI5-;v$NI=Bj$N9T$K%]%$%s%H$r0\F0$5$;$^$9!#\e(B
+
+@item first
+\e$B:G=i$N5-;v$NI=Bj$N9T$K%]%$%s%H$r0\F0$5$;$^$9!#\e(B
+
+@item unseen
+\e$B$^$@FI$^$l$?$3$H$,L5$$:G=i$N5-;v$NI=Bj$N9T$K%]%$%s%H$r0\F0$5$;$^$9!#\e(B
+
+@item unseen-or-unread
+\e$B$^$@FI$^$l$?$3$H$,L5$$:G=i$N5-;v$,$"$l$P!"$=$N5-;v$NI=Bj$N9T$K%]%$%s%H$r\e(B
+\e$B0\F0$5$;!"L5$+$C$?$i:G=i$NL$FI5-;v$NI=Bj$N9T$K%]%$%s%H$r0\F0$5$;$^$9!#\e(B
+
+@item best
+\e$B%9%3%"$,:G$b9b$$L$FI5-;v$NI=Bj$N9T$K%]%$%s%H$r0\F0$5$;$^$9!#\e(B
+@end table
+
+\e$B$3$NJQ?t$O4X?t$G$"$k$3$H$b$G$-$^$9!#$=$N>l9g!"$=$N4X?t$OI=Bj$N9T$K%]%$%s\e(B
+\e$B%H$r0\F0$5$;$k$?$a$K8F$P$l$^$9!#\e(B
+
+\e$B$b$7$"$k%0%k!<%W$G<+F05-;vA*Br$r$d$a$?$$$N$G$"$l$P\e(B (\e$BNc$($P$G$C$+$$5-;v$N\e(B
+\e$B$"$k%P%$%J%j%0%k!<%W$G$O!"$H$+\e(B)\e$B!"%0%k!<%W$,A*Br$5$l$?$H$-$K8F$S=P$5$l\e(B
+\e$B$k\e(B @code{gnus-select-group-hook} \e$B$NCf$GJQ\e(B
+\e$B?t\e(B @code{gnus-auto-select-first} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+
+@node Subscription Commands
+@section \e$B9XFI@)8f%3%^%s%I\e(B
+@cindex subscription
+
+@table @kbd
+@item S t
+@itemx u
+@kindex S t (\e$B%0%k!<%W\e(B)
+@kindex u (\e$B%0%k!<%W\e(B)
+@findex gnus-group-unsubscribe-current-group
+@c @icon{gnus-group-unsubscribe}
+\e$B8=:_$N%0%k!<%W$N9XFI$r@Z$jBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-unsubscribe-current-group})\e$B!#\e(B
+
+@item S s
+@itemx U
+@kindex S s (\e$B%0%k!<%W\e(B)
+@kindex U (\e$B%0%k!<%W\e(B)
+@findex gnus-group-unsubscribe-group
+\e$B%0%k!<%W$r9XFI$9$k$+$I$&$+$r3NG'$7!"9XFI$7$^$9!#$9$G$K9XFI$9$k$h$&$K$J$C\e(B
+\e$B$F$$$k>l9g$K$O!"9XFI$r;_$a$^$9\e(B (@code{gnus-group-unsubscribe-group})\e$B!#\e(B
+
+@item S k
+@itemx C-k
+@kindex S k (\e$B%0%k!<%W\e(B)
+@kindex C-k (\e$B%0%k!<%W\e(B)
+@findex gnus-group-kill-group
+@c @icon{gnus-group-kill-group}
+\e$B8=:_$N%0%k!<%W$r\e(B kill \e$B$7$^$9\e(B (@code{gnus-group-kill-group})\e$B!#\e(B
+
+@item S y
+@itemx C-y
+@kindex S y (\e$B%0%k!<%W\e(B)
+@kindex C-y (\e$B%0%k!<%W\e(B)
+@findex gnus-group-yank-group
+\e$B:G8e$K\e(B kill \e$B$7$?%0%k!<%W$r\e(B yank \e$B$7$^$9\e(B (@code{gnus-group-yank-group})\e$B!#\e(B
+
+@item C-x C-t
+@kindex C-x C-t (\e$B%0%k!<%W\e(B)
+@findex gnus-group-transpose-groups
+\e$BFs$D$N%0%k!<%W$N=g=x$rCV$-49$($^$9\e(B (@code{gnus-group-transpose-groups})\e$B!#\e(B
+\e$B$3$l$O%[%s%H$O9XFI%3%^%s%I$G$O$"$j$^$;$s$,!"\e(Bkill \e$B$H\e(B yank \e$B$r2?EY$+B3$1$k\e(B
+\e$BBe$o$j$K$3$N%3%^%s%I$,;H$($^$9!#\e(B
+
+@item S w
+@itemx C-w
+@kindex S w (\e$B%0%k!<%W\e(B)
+@kindex C-w (\e$B%0%k!<%W\e(B)
+@findex gnus-group-kill-region
+\e$B%j!<%8%g%sFb$NA4$F$N%0%k!<%W$r\e(B kill \e$B$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-kill-region})\e$B!#\e(B
+
+@item S z
+@kindex S z (\e$B%0%k!<%W\e(B)
+@findex gnus-group-kill-all-zombies
+\e$BA4$F$N%>%s%S%0%k!<%W$r\e(B kill \e$B$7$^$9\e(B (@code{gnus-group-kill-all-zombies})\e$B!#\e(B
+
+@item S C-k
+@kindex S C-k (\e$B%0%k!<%W\e(B)
+@findex gnus-group-kill-level
+\e$B$"$k%l%Y%k$N%0%k!<%W$rA4$F\e(B kill \e$B$7$^$9\e(B (@code{gnus-group-kill-level})\e$B!#\e(B
+kill \e$B$7$?8e!"$3$l$i$N%0%k!<%W$r\e(B yank \e$B$GLa$9$3$H$O$G$-$J$$$N$G!"$3$N%3%^\e(B
+\e$B%s%I$O$$$/$i$+Cm0U$7$F;H$C$F$/$@$5$$!#$3$N%3%^%s%I$,K\Ev$KJXMx$K$J$k$N$O!"\e(B
+@file{.newsrc} \e$B$K<N$F$A$c$$$?$$L$9XFI$N%0%k!<%W$,$?$/$5$s$"$k$H$-$@$1$G\e(B
+\e$B$9!#%l%Y%k\e(B 7 \e$B$G\e(B @kbd{S C-k} \e$B$r9T$&$H!"\e(B@file{.newsrc} \e$B%U%!%$%kCf$K%a%C%;!<\e(B
+\e$B%8HV9f$,$J$$L$9XFI%0%k!<%W$rA4$F\e(B kill \e$B$7$^$9!#\e(B
+@end table
+
+@ref{Group Levels} \e$B$b;2>H$7$F$/$/$@$5$$!#\e(B
+
+@node Group Data
+@section \e$B%0%k!<%W%G!<%?\e(B
+
+@table @kbd
+@item c
+@kindex c (\e$B%0%k!<%W\e(B)
+@findex gnus-group-catchup-current
+@vindex gnus-group-catchup-group-hook
+@c @icon{gnus-group-catchup-current}
+\e$B$=$N%0%k!<%WFb$NA4$F$NL50u$N5-;v$r4{FI$K$9\e(B
+\e$B$k\e(B (@code{gnus-group-catchup-current})\e$B!#%0%k!<%W%P%C%U%!$+$i4{FI$K$7$?>l\e(B
+\e$B9g$O\e(B @code{gnus-group-catchup-group-hook} \e$B$,8F$S=P$5$l$^$9!#\e(B
+
+@item C
+@kindex C (\e$B%0%k!<%W\e(B)
+@findex gnus-group-catchup-current-all
+\e$B$=$N%0%k!<%W$NA45-;v$r!"0uIU$-$N5-;v$b4^$a$F4{FI$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-catchup-current-all})\e$B!#\e(B
+
+@item M-c
+@kindex M-c (\e$B%0%k!<%W\e(B)
+@findex gnus-group-clear-data
+\e$B8=:_$N%0%k!<%W$NA4$F$N%G!<%?$r%/%j%"$7$^$9!=!=%^!<%/$H4{FI5-;v$N%j%9%H$r\e(B
+\e$B>C$75n$j$^$9\e(B (@code{gnus-group-clear-data})\e$B!#\e(B
+
+@item M-x gnus-group-clear-data-on-native-groups
+@kindex M-x gnus-group-clear-data-on-native-groups
+@findex gnus-group-clear-data-on-native-groups
+\e$B$b$7\e(B @acronym{NNTP} \e$B%5!<%P$rJL$N$b$N$K@Z$jBX$($?$H$9$k$H!"A4$F$N%^!<%/$H\e(B
+\e$B4{FI>pJs$O$b$&Lr$K$ON)$A$^$;$s!#$3$N%3%^%s%I$r;H$C$F4pK\%0%k!<%W$NA4$F$N\e(B
+\e$B%G!<%?$r%/%j%"$9$k$3$H$,$G$-$^$9!#Cm0U$7$F;H$C$F$M!#\e(B
+@end table
+
+@node Group Levels
+@section \e$B%0%k!<%W%l%Y%k\e(B
+@cindex group level
+@cindex level
+
+\e$BA4$F$N%0%k!<%W$O\e(B @dfn{\e$B9XFIEY\e(B} (@dfn{subscribedness}) \e$B$N%l%Y%k$r;}$A$^$9!#\e(B
+\e$BNc$($P!"$"$k%0%k!<%W$,%l%Y%k\e(B 2 \e$B$@$H$9$l$P!"$=$l$O%l%Y%k\e(B 5 \e$B$N%0%k!<%W$h$j\e(B
+\e$B$b!V$h$j9XFI$7$F$$$k!W$H$$$&$3$H$G$9!#\e(BGnus \e$B$KBP$7$F!"$"$k%l%Y%k$+$=$l$h\e(B
+\e$B$j>.$5$$%l%Y%k$N%0%k!<%W$N$_0lMwI=<($9$k$h$&$KMj$`$3$H$b$G$-$k\e(B
+\e$B$7\e(B (@pxref{Listing Groups})\e$B!"$"$k%l%Y%k$+$=$l$h$j>.$5$$%l%Y%k$N%0%k!<%W\e(B
+\e$B$N?7Ce5-;v$N$_$r3NG'$9$k$3$H$b$G$-$^$9\e(B(@pxref{Scanning New Messages})\e$B!#\e(B
+
+\e$BK:$l$J$$$G\e(B: \e$B%0%k!<%W$N%l%Y%k$,Bg$-$$$[$I!"=EMWEY$ODc$/$J$k$H$$$&$3$H!#\e(B
+
+@table @kbd
+@item S l
+@kindex S l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-set-current-level
+\e$B8=:_$N%0%k!<%W$N%l%Y%k$r@_Dj$9$k!#?t;z%W%l%U%#%C%/%9$,M?$($i$l$k$H!"$=$3\e(B
+\e$B$+$i\e(B @var{n} \e$B8D$N%0%k!<%W$N%l%Y%k$,@_Dj$5$l$^$9!#%l%Y%k$rF~NO$9$k$?$a$N\e(B
+\e$B%W%m%s%W%H$,=P$^$9!#\e(B
+@end table
+
+@vindex gnus-level-killed
+@vindex gnus-level-zombie
+@vindex gnus-level-unsubscribed
+@vindex gnus-level-subscribed
+Gnus \e$B$O%l%Y%k\e(B 1 \e$B$+$i\e(B @code{gnus-level-subscribed} (\e$B$3$NCM$r4^$`\e(B) (\e$B=i4|CM\e(B
+\e$B$O\e(B 5) \e$B$^$G$N%0%k!<%W$r9XFI!"\e(B@code{gnus-level-subscribed} (\e$B$3$NCM$r4^$^$J\e(B
+\e$B$$\e(B) \e$B$+$i\e(B@code{gnus-level-unsubscribed} (\e$B$3$NCM$r4^$`\e(B) (\e$B=i4|CM$O\e(B 7) \e$B$^$G\e(B
+\e$B$N%0%k!<%W$rHs9XFI!"\e(B@code{gnus-level-zombie} \e$B$r%>%s%S\e(B (\e$BJb$/;S\e(B) (\e$B=i4|CM\e(B
+\e$B$O\e(B 8)\e$B!"\e(B@code{gnus-level-killed} \e$B$r\e(B kill \e$B$5$l$F$$$k\e(B (\e$B40A4$K;`$s$G\e(B
+\e$B$k\e(B) (\e$B=i4|CM$O\e(B 9) \e$B$HH=CG$7$^$9!#\e(BGnus \e$B$O9XFI$HHs9XFI$N%0%k!<%W$OA4$/F1MM$K\e(B
+\e$B07$$$^$9$,!"%>%s%S$H\e(B kill \e$B%0%k!<%W$O!"$I$N5-;v$rFI$s$@$+!"B8:_$9$k$+$J$I\e(B
+\e$B$N>pJs$r0l@Z;}$A$^$;$s!#$3$N;`$s$G$k%0%k!<%W$H@8$-$F$k%0%k!<%W$N6hJL$O!"\e(B
+\e$BJL$K$=$l$,$-$l$$$@$+$i$H$+8-$$$+$i$H$$$&$o$1$G$O$J$/!"=c?h$K8zN(E*$JM}M3\e(B
+\e$B$N$?$a$G$9!#\e(B
+
+\e$B%a!<%kMQ$N%0%k!<%W$O\e(B (\e$B$b$7$"$l$P\e(B) \e$BHs>o$K>.$5$$%l%Y%k\e(B (\e$BNc$($P\e(B 1 \e$B$+\e(B 2) \e$B$K\e(B
+\e$B$7$F$*$/$3$H$r$*4+$a$7$^$9!#\e(B
+
+\e$B<!$N\e(B gnus \e$B$N%G%#%U%)%k%H$NF0:n$N@bL@$O!"$3$H$K$h$k$H!"$3$l$i$N%l%Y%k$NA4\e(B
+\e$B$F$rM}2r$9$k=u$1$K$J$k$+$b$7$l$^$;$s!#%G%#%U%)%k%H$G$O!"\e(Bgnus \e$B$O9VFI$7$F\e(B
+\e$B$$$k6u$G$J$$%0%k!<%W$rI=<($7$^$9$,!"\e(B@kbd{L} \e$B$rC!$/$3$H$K$h$C$F6u$N%0%k!<\e(B
+\e$B%W$dHs9VFI$N%0%k!<%W$bI=<($5$;$k$3$H$,$G$-$^$9!#$D$^$j!"Hs9VFI$N%0%k!<%W\e(B
+\e$B$O1#$5$l$F$$$k!"$H8@$C$F$bNI$$$G$7$g$&!#\e(B
+
+\e$B%>%s%S$H\e(B kill \e$B%0%k!<%W$O!"%G%#%U%)%k%H$G$O1#$5$l$F$$$kE@$GHs9VFI$N%0%k!<\e(B
+\e$B%W$K;w$F$$$^$9!#$7$+$7!"\e(Bgnus \e$B$,%K%e!<%9%5!<%P!<$KBP$7$F%>%s%S$H\e(B kill \e$B%0\e(B
+\e$B%k!<%W$K4X$9$k>pJs\e(B (\e$B5-;v?t!"L$FI5-;v?t\e(B) \e$B$NLd$$9g$o$;$r$7$J$$E@$G!"9XFI$*\e(B
+\e$B$h$SHs9XFI$N%0%k!<%W$H$O0c$C$F$$$^$9!#$U$D$&!"$"$J$?$O6=L#$NL5$$%0%k!<%W\e(B
+\e$B$r\e(B @kbd{C-k} \e$B$G\e(B kill \e$B$7$^$9$h$M!#$b$7!"$[$H$s$I$N%0%k!<%W$,\e(B kill \e$B$5$l$F\e(B
+\e$B$$$k$H!"\e(Bgnus \e$B$OB.$/$J$j$^$9!#\e(B
+
+\e$B$J$<\e(B gnus \e$B$O%>%s%S$H\e(B kill \e$B%0%k!<%W$r6hJL$9$k$N$G$7$g$&\e(B?  \e$B$($($H!"%5!<%P!<\e(B
+\e$B$K?7$7$$%0%k!<%W$,$G$-$k$H!"\e(Bgnus \e$B$O%G%#%U%)%k%H$G$=$l$r%>%s%S$K$7$^$9!#\e(B
+\e$B$3$l$O!"$"$J$?$,$U$D$&$O?7$7$$%0%k!<%W$KHQ$o$5$l$J$$$3$H$r0UL#$7$^$9$,!"\e(B
+\e$B$"$J$?$O\e(B @kbd{A z} \e$B$G?7$7$$%0%k!<%W$N%j%9%H$rF@$k$3$H$,$G$-$^$9!#$"$J$?\e(B
+\e$B$O9%$_$N$b$N$r9VFI$7!"MW$i$J$$$b$N$O\e(B kill \e$B$9$l$PNI$$$N$G$9!#\e(B
+(@kbd{A k} \e$B$G\e(B kill \e$B$5$l$?%0%k!<%W$N%j%9%H$rI=<($7$^$9!#\e(B)
+
+\e$B$b$7%l%Y%kJQ?t$GM7$S$?$$$N$G$"$l$P!"B?>/Cm0U$r$7$F$^$o$kI,MW$,$"$j$^$9!#\e(B
+\e$B0lC6$=$l$r@_Dj$7$?$i!"FsEY$H$=$l$K?($i$J$$$G$/$@$5$$!#$5$i$K8@$($P!"<+J,\e(B
+\e$B$G2?$r$d$C$F$$$k$+$r@53N$KM}2r$7$F$$$J$$8B$j!"0l@Z?($i$J$$$G$/$@$5$$!#\e(B
+
+@vindex gnus-level-default-unsubscribed
+@vindex gnus-level-default-subscribed
+\e$B?H6a$K4X78$9$kFs$D$NJQ?t$O\e(B @code{gnus-level-default-subscribed} (\e$B=i4|CM\e(B
+\e$B$O\e(B 3) \e$B$H\e(B @code{gnus-level-default-unsubscribed} (\e$B=i4|CM$O\e(B 6) \e$B$G$9!#$3$l\e(B
+\e$B$i$O?7$7$$%0%k!<%W$,\e(B (\e$BHs\e(B) \e$B9XFI$5$l$?$H$-$N%l%Y%k$G$9!#$b$A$m$s!"$3$l\e(B
+\e$B$iFs$D$NJQ?t$NCM$O!"0UL#$N$"$k@5$7$$HO0O$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+@vindex gnus-keep-same-level
+@code{gnus-keep-same-level} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"0\F0%3%^%s%I$N$$\e(B
+\e$B$/$D$+$OF10l\e(B (\e$B$"$k$$$O$=$l$h$j>.$5$$\e(B) \e$B%l%Y%k$N%0%k!<%W$N$_$N0\F0$K$J$j$^\e(B
+\e$B$9!#FC$K!"$"$k%0%k!<%W$N:G8e$N5-;v$+$i<!$N%0%k!<%W$K0\$k$H$-!"<!$NF1\e(B
+\e$B0l\e(B (\e$B$"$k$$$O$=$l$h$j>.$5$$\e(B) \e$B%l%Y%k$N%0%k!<%W$K0\F0$7$^$9!#$3$l$O;D$j$N%0\e(B
+\e$B%k!<%W$rFI$`$h$j@h$K!"$h$j=EMW$J%0%k!<%W$rFI$s$G$*$-$?$$$H$-$K$OJXMx$+$b\e(B
+\e$B$7$l$^$;$s!#\e(B
+
+\e$B$b$7$3$NCM$,\e(B @code{best} \e$B$@$C$?$i!":G$b=EMW$J\e(B (\e$B:G$b%l%Y%k$NCM$,>.$5\e(B
+\e$B$$\e(B) \e$B%0%k!<%W$K0\F0$7$^$9!#\e(B
+
+@vindex gnus-group-default-list-level
+\e$B=i4|@_Dj$G$O\e(B @code{gnus-group-default-list-level} \e$B$HF1$8$+$=$l$h$j>.$5$$\e(B
+\e$B%l%Y%k$N%0%k!<%W$,!"%0%k!<%W%P%C%U%!$K0lMwI=<($5$l$^$9!#\e(B
+
+@vindex gnus-group-list-inactive-groups
+@code{gnus-group-list-inactive-groups} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"L$FI\e(B
+\e$B$N%0%k!<%W$K0l=o$K%"%/%F%#%V$G$J$$%0%k!<%W$bI=<($7$^$9!#$3$NJQ?t$O=i4|@_\e(B
+\e$BDj$G$O\e(B @code{t} \e$B$G$9!#$b$7$3$l$,\e(B @code{nil} \e$B$G$"$l$P!"%"%/%F%#%V$G$J$$%0\e(B
+\e$B%k!<%W$OI=<($5$l$^$;$s!#\e(B
+
+@vindex gnus-group-use-permanent-levels
+@code{gnus-group-use-permanent-levels} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"0lC6\e(B
+\e$B%l%Y%k$r\e(B @kbd{g} \e$B$d\e(B @kbd{l} \e$B$N%W%l%U%#%C%/%9$KM?$($k$H!"$=$N8e$NA4$F$N%3\e(B
+\e$B%^%s%I$K$*$$$F$=$N%l%Y%k$,!V:nMQ$9$k!W%l%Y%k$K$J$j$^$9!#\e(B
+
+@vindex gnus-activate-level
+Gnus \e$B$ODL>o!"\e(B@code{gnus-activate-level} \e$B$+$=$l$h$j>.$5$$%l%Y%k$N%0%k!<%W\e(B
+\e$B$N$_$r5/F0$7$^$9\e(B (\e$B$D$^$j%5!<%P$KLd$$9g$o$;$r$9$k\e(B)\e$B!#9XFI$7$F$$$J$$%0%k!<\e(B
+\e$B%W$r5/F0$7$?$/$J$1$l$P!"$3$NJQ?t$rNc$($P\e(B 5 \e$B$K@_Dj$9$k$H$h$$$+$b$7$l$^$;\e(B
+\e$B$s!#%G%#%U%)%k%H$O\e(B 6 \e$B$G$9!#\e(B
+
+@node Group Score
+@section \e$B%0%k!<%W$N%9%3%"\e(B
+@cindex group score
+@cindex group rank
+@cindex rank
+
+\e$BIaDL$O=EMW$J%0%k!<%W$O9b%l%Y%k$K$7$F$*$/$G$7$g$&$1$l$I$b!"$3$NJ}K!$G$O>/!9\e(B
+\e$B@)8B$,$-$D$$$G$9$h$M!#$R$g$C$H$7$?$i!"%0%k!<%W$r$I$l$/$i$$IQHK$KFI$`$+$K\e(B
+\e$B$h$C$F%0%k!<%W%P%C%U%!$r%=!<%H$7$?$$$J$"!"$J$s$F;W$o$J$$\e(B? \e$BM}$K$+$J$C$F$k\e(B
+\e$B$G$7$g\e(B?
+
+@dfn{\e$B%0%k!<%W%9%3%"\e(B} (@dfn{group score}) \e$B$O$=$N$?$a$N$b$N$G$9!#\e(BGnus \e$B$K0J\e(B
+\e$B2<$G@bL@$5$l$F$$$k5!9=$G!"$=$l$>$l$N%0%k!<%W$KBP$7$F%9%3%"$r;XDj$5$;$k$3\e(B
+\e$B$H$,$G$-$^$9!#$=$7$F%0%k!<%W%P%C%U%!$r$3$N%9%3%"$r4p$K%=!<%H$9$k$3$H$,$G\e(B
+\e$B$-$^$9!#$"$k$$$O!"%9%3%"=g$G%=!<%H$7$F$=$N8e%l%Y%k$G%=!<%H$9$k$3$H$b$G$-\e(B
+\e$B$^$9!#\e(B(\e$B%l%Y%k$H%9%3%"$r$R$H$^$H$a$K$7$F!"%0%k!<%W\e(B
+\e$B$N\e(B @dfn{\e$B%i%s%/\e(B} (@dfn{rank}) \e$B$H8F$S$^$9!#%l%Y%k$,\e(B 4 \e$B$G%9%3%"$,\e(B 1 \e$B$N%0%k!<\e(B
+\e$B%W$O!"%l%Y%k$,\e(B 5 \e$B$G%9%3%"$,\e(B 300 \e$B$N%0%k!<%W$h$j$b9b$$%i%s%/$H$J$j$^$9!#\e(B
+(\e$B%l%Y%k$NJ}$,=EMWEY$,9b$/!"%9%3%"$NJ}$O=EMWEY$,Dc$/$J$j$^$9!#\e(B))
+
+@findex gnus-summary-bubble-group
+\e$BIQHK$KFI$`%0%k!<%W$K!"$a$C$?$KFI$^$J$$%0%k!<%W$h$j$b9b$$%9%3%"$rM?$($?$$\e(B
+\e$B$H$-$O!"\e(B@code{gnus-summary-exit-hook} \e$B%U%C%/\e(B
+\e$B$K\e(B @code{gnus-summary-bubble-group} \e$B4X?t$rDI2C$9$k$3$H$,$G$-$^$9!#$3$l$G\e(B
+\e$B%P%V%k%=!<%H$N<B9T7k2L$,\e(B (\e$B%=!<%H$N8e$G\e(B) \e$BF@$i$l$k$G$7$g$&!#35N,%b!<%I$r=*\e(B
+\e$BN;$9$k$?$S$K$3$N3hF0$r$5$;$?$$$N$G$"$l$P!"F1$8%U%C%/\e(B
+\e$B$K\e(B @code{gnus-group-sort-groups-by-rank} \e$B$+\e(B @code{gnus-group-sort-groups-by-score} \e$B$r\e(B
+\e$BDI2C$G$-$^$9$,!"$$$/$i$+CY$/$J$k$G$7$g$&!#\e(B
+
+@node Marking Groups
+@section \e$B%0%k!<%W$X$N0u\e(B
+@cindex marking groups
+
+\e$B$b$7$$$/$D$+$N%0%k!<%W$KBP$7$F2?$i$+$NL?Na$r<B9T$7$?$$>l9g$G!"$=$l$i$,%0\e(B
+\e$B%k!<%W%P%C%U%!$KO"B3$7$F$"$k>l9g$K$O!"DL>oDL$jL?Na$KBP$7$F?t;z@\F,<-$rM?\e(B
+\e$B$($k$@$1$G$9!#$=$&$9$l$P$[$H$s$I$N%0%k!<%WL?Na$O!"$3$l$i$N%0%k!<%W$KBP$7\e(B
+\e$B$F$"$J$?$NL?Na$K=>$$$^$9!#\e(B
+
+\e$B$7$+$7$=$l$i$N%0%k!<%W$,=gHV$KJB$s$G$$$J$$>l9g$K$*$$$F$b!"$$$/$D$+$N%0%k!<\e(B
+\e$B%W$KBP$7$FL?Na$r<B9T$9$k$3$H$,$G$-$^$9!#C1$K;O$a$K%W%m%;%90u$G%0%k!<%W$K\e(B
+\e$B0u$r$D$1$F$*$-!"$=$7$FL?Na$r<B9T$9$k$@$1$G$9!#\e(B
+
+@table @kbd
+@item #
+@kindex # (\e$B%0%k!<%W\e(B)
+@itemx M m
+@kindex M m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-mark-group
+\e$B8=:_$N%0%k!<%W$K0u$r$D$1$k\e(B (@code{gnus-group-mark-group})\e$B!#\e(B
+
+@item M-#
+@kindex M-# (\e$B%0%k!<%W\e(B)
+@itemx M u
+@kindex M u (\e$B%0%k!<%W\e(B)
+@findex gnus-group-unmark-group
+\e$B8=:_$N%0%k!<%W$+$i0u$r:o=|$9$k\e(B (@code{gnus-group-unmark-group})\e$B!#\e(B
+
+@item M U
+@kindex M U (\e$B%0%k!<%W\e(B)
+@findex gnus-group-unmark-all-groups
+\e$BA4$F$N%0%k!<%W$+$i0u$r:o=|$9$k\e(B (@code{gnus-group-unmark-all-groups})\e$B!#\e(B
+
+@item M w
+@kindex M w (\e$B%0%k!<%W\e(B)
+@findex gnus-group-mark-region
+\e$B%]%$%s%H$H%^!<%/$N4V$NA4$F$N%0%k!<%W$K0u$r$D$1\e(B
+\e$B$k\e(B (@code{gnus-group-mark-region})\e$B!#\e(B
+
+@item M b
+@kindex M b (\e$B%0%k!<%W\e(B)
+@findex gnus-group-mark-buffer
+\e$B%P%C%U%!Fb$NA4$F$N%0%k!<%W$K0u$r$D$1$k\e(B (@code{gnus-group-mark-buffer})\e$B!#\e(B
+
+@item M r
+@kindex M r (\e$B%0%k!<%W\e(B)
+@findex gnus-group-mark-regexp
+\e$B$"$k@55,I=8=$K9gCW$9$kA4$F$N%0%k!<%W$K0u$r$D$1\e(B
+\e$B$k\e(B (@code{gnus-group-mark-regexp})\e$B!#\e(B
+@end table
+
+@ref{Process/Prefix} \e$B$b;2>H$7$F$/$@$5$$!#\e(B
+
+@findex gnus-group-universal-argument
+\e$B%W%m%;%90u$,IU$1$i$l$F$$$kA4$F$N%0%k!<%W$KBP$7$F2?$+$NL?Na$r<B9T$7$?$$$H\e(B
+\e$B$-$O!"\e(B@kbd{M-&} (@code{gnus-group-universal-argument}) \e$BL?Na$r;H$&$3$H$,\e(B
+\e$B$G$-$^$9!#%W%m%s%W%H$+$i<B9T$7$?$$L?Na$rF~NO$7$^$9!#\e(B
+
+@node Foreign Groups
+@section \e$B30It%0%k!<%W\e(B
+@cindex foreign groups
+
+\e$B0J2<$G$O!"0lHLE*$J30It%0%k!<%W$N:n@.!"JQ99$r9T$&%0%k!<%W%b!<%I$NL?Na$r$$\e(B
+\e$B$/$D$+!"$*$h$SFCJL$JL\E*$N%0%k!<%W$r4JC1$K:n@.$9$kL?Na$r>R2p$7$^$9!#$3$l\e(B
+\e$B$i$NL?Na$OA4$F!"?75,$K:n@.$7$?%0%k!<%W$r%]%$%s%H0LCV$KA^F~$7$^\e(B
+\e$B$9!=!=\e(B@code{gnus-subscribe-newsgroup-method} \e$B$O;2>H$5$l$^$;$s!#\e(B
+
+@table @kbd
+@item G m
+@kindex G m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-group
+@cindex making groups
+\e$B?7$7$$%0%k!<%W$r:n@.$7$^$9\e(B (@code{gnus-group-make-group})\e$B!#\e(BGnus \e$B$O%W%m%s\e(B
+\e$B%W%H$rI=<($7$F!"L>A0$HJ}K!$H!">l9g$K$h$C$F$O\e(B @dfn{address} \e$B$NF~NO$r5a$a\e(B
+\e$B$F$-$^$9!#$h$j4JC1$K\e(B @acronym{NNTP} \e$B%0%k!<%W$r9XFI$9$kJ}K!$K$D$$$F$O!"\e(B
+@ref{Browse Foreign Server} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item G M
+@kindex G M (\e$B%0%k!<%W\e(B)
+@findex gnus-group-read-ephemeral-group
+\e$B0l;~%K%e!<%9%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-read-ephemeral-group})\e$B!#\e(B Gnus \e$B$O%W%m%s%W%H$rI=<($7\e(B
+\e$B$F!"L>A0!"J}K!$*$h$S\e(B @dfn{address} \e$B$NF~NO$r5a$a$^$9!#\e(B
+
+@item G n
+@kindex G n (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-shimbun-group
+@cindex making groups
+@cindex emacs-w3m
+@cindex nnshimbun
+@cindex web newspaper
+\e$B?7$7$$\e(B @code{nnshimbun} \e$B%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-shimbun-group})\e$B!#\e(Bgnus \e$B$O%W%m%s%W%H$rI=<($7$F!"\e(B
+\e$B%5!<%P!<$N%"%I%l%9$r<($9%7%s%\%kL>$H5-;v%0%k!<%WL>$NF~NO$r5a$a$F$-$^$9!#\e(B
+\e$B$3$l$r;H$&$K$O\e(B @uref{http://emacs-w3m.namazu.org/, emacs-w3m} \e$B$,I,MW$G$9!#\e(B
+@code{nnshimbun} \e$B$K4X$9$k>\:Y\e(B
+\e$B$O\e(B (@pxref{Nnshimbun, , Nnshimbun, emacs-w3m-ja, Emacs-w3m-ja}) \e$B$r;2>H$7\e(B
+\e$B$F2<$5$$!#\e(B
+
+@item G r
+@kindex G r (\e$B%0%k!<%W\e(B)
+@findex gnus-group-rename-group
+@cindex renaming groups
+\e$B8=:_$N%0%k!<%W$NL>A0$r!"2?$+JL$N$b$N$KJQ99$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-rename-group})\e$B!#$3$l$O$"$k<o$N%0%k!<%W!=!=<g$K%a!<\e(B
+\e$B%k%0%k!<%W$KBP$7$F$N$_M-8z$G$9!#$3$N%3%^%s%I$O%P%C%/%(%s%I$K$h$C$F$OHs>o\e(B
+\e$B$KCY$$$3$H$bM-$jF@$^$9!#\e(B
+
+@item G c
+@kindex G c (\e$B%0%k!<%W\e(B)
+@cindex customizing
+@findex gnus-group-customize
+\e$B%0%k!<%W%Q%i%a!<%?$r%+%9%?%^%$%:$9$k\e(B (@code{gnus-group-customize})\e$B!#\e(B
+
+@item G e
+@kindex G e (\e$B%0%k!<%W\e(B)
+@findex gnus-group-edit-group-method
+@cindex renaming groups
+\e$B8=:_$N%0%k!<%W$NA*BrJ}K!$r=$@5$9$k$?$a$N%P%C%U%!$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-edit-group-method})\e$B!#\e(B
+
+@item G p
+@kindex G p (\e$B%0%k!<%W\e(B)
+@findex gnus-group-edit-group-parameters
+\e$B%0%k!<%W%Q%i%a!<%?$r=$@5$9$k$?$a$N%P%C%U%!$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-edit-group-parameters})\e$B!#\e(B
+
+@item G E
+@kindex G E (\e$B%0%k!<%W\e(B)
+@findex gnus-group-edit-group
+\e$B%0%k!<%W>pJs$r=$@5$9$k$?$a$N%P%C%U%!$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-edit-group})\e$B!#\e(B
+
+@item G d
+@kindex G d (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-directory-group
+@cindex nndir
+\e$B%G%#%l%/%H%j%0%k!<%W$r:n@.$7$^$9\e(B (@pxref{Directory Groups})\e$B!#%G%#%l%/%H\e(B
+\e$B%jL>$r%W%m%s%W%H$GF~NO$7$^$9\e(B (@code{gnus-group-make-directory-group})\e$B!#\e(B
+
+@item G h
+@kindex G h (\e$B%0%k!<%W\e(B)
+@cindex help group
+@findex gnus-group-make-help-group
+
+Gnus \e$B%X%k%W%0%k!<%W$r:n@.$7$^$9\e(B (@code{gnus-group-make-help-group})\e$B!#\e(B
+
+@item G a
+@kindex G a (\e$B%0%k!<%W\e(B)
+@cindex (ding) archive
+@cindex archive group
+@findex gnus-group-make-archive-group
+@vindex gnus-group-archive-directory
+@vindex gnus-group-recent-archive-directory
+Gnus \e$B%"!<%+%$%V%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-archive-group})\e$B!#=i4|@_Dj$G$O:G$b:G6a$N5-;v$r\e(B
+\e$B;X$7$F$$$k%0%k!<%W$,:n@.$5$l$^$9\e(B
+\e$B$,\e(B (@code{gnus-group-recent-archive-directory})\e$B!"@\F,0z?t$rM?$($k$HA4$F\e(B
+\e$B$N5-;v$r4^$`%0%k!<%W$,\e(B @code{gnus-group-archive-directory} \e$B$r4p$K:n@.$5\e(B
+\e$B$l$^$9!#\e(B
+
+@item G k
+@kindex G k (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-kiboze-group
+@cindex nnkiboze
+kiboze \e$B%0%k!<%W$r:n@.$7$^$9!#%W%m%s%W%H$GL>A0$H!"\e(Bkiboze \e$B%0%k!<%W$K!V4^$a\e(B
+\e$B$?$$!W%0%k!<%W$K9g$&@55,I=8=$H!"%X%C%@!<$K9g$&J8;zNs$NAH$rF~NO$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-kiboze-group})\e$B!#\e(B@xref{Kibozed Groups}.
+
+@item G D
+@kindex G D (\e$B%0%k!<%W\e(B)
+@findex gnus-group-enter-directory
+@cindex nneething
+\e$BG$0U$N%G%#%l%/%H%j$r\e(B @code{nneething} \e$B%P%C%/%(%s%I%K%e!<%9%0%k!<%W$G$"$k\e(B
+\e$B$+$N$h$&$KFI$_9~$_$^$9\e(B (@code{gnus-group-enter-directory})\e$B!#\e(B
+@xref{Anything Groups}.
+
+@item G f
+@kindex G f (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-doc-group
+@cindex ClariNet Briefs
+@cindex nndoc
+\e$B%U%!%$%k$J$I$r$b$H$K%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-doc-group})\e$B!#$3$N%3%^%s%I$K@\F,<-$rM?$($?>l9g!"\e(B
+\e$B%U%!%$%kL>$H%U%!%$%k%?%$%W$r%W%m%s%W%H$GF~NO$7$^$9!#8=:_%5%]!<%H$5$l$F$$\e(B
+\e$B$k%U%!%$%k%?%$%W$O\e(B @code{mbox}, @code{babyl}, @code{digest}, @code{news},
+@code{rnews}, @code{mmdf}, @code{forward}, @code{rfc934},
+@code{rfc822-forward}, @code{mime-parts}, @code{standard-digest},
+@code{slack-digest}, @code{clari-briefs}, @code{nsmail}, @code{outlook},
+@code{oe-dbx} \e$B$*$h$S\e(B @code{mailman} \e$B$G$9!#@\F,<-$J$7$G$3$N%3%^%s%I$r<B9T\e(B
+\e$B$9$k$H!"\e(Bgnus \e$B$O%U%!%$%k%?%$%W$r?dB,$7$^$9!#\e(B
+@xref{Document Groups}.
+
+@item G u
+@kindex G u (\e$B%0%k!<%W\e(B)
+@vindex gnus-useful-groups
+@findex gnus-group-make-useful-group
+@code{gnus-useful-groups} \e$B$K$"$k%0%k!<%W$N0l$D$r$D$/$j$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-useful-group})\e$B!#\e(B
+
+@item G w
+@kindex G w (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-web-group
+@cindex Google
+@cindex nnweb
+@cindex gmane
+\e$B%&%'%V8!:w7k2L$r$b$H$K0l;~E*$J%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-web-group})\e$B!#$3$N%3%^%s%I$K@\F,<-$rM?$($k$H!"\e(B
+\e$B0l;~E*$G$O$J$/8GDj$7$?%0%k!<%W$r:n@.$7$^$9!#%W%m%s%W%H$G8!:w%(%s%8%s$N<o\e(B
+\e$BN`\e(B (search engine type) \e$B$H8!:wJ8;zNs$rF~NO$7$^$9!#M-8z$J8!:w%(%s%8%s$N<o\e(B
+\e$BN`$K$O\e(B @code{google}, @code{dejanews}, @code{gmane} \e$B$,$"$j$^$9!#\e(B
+@xref{Web Searches}.
+
+\e$B$b$7!"\e(B@code{google} \e$B8!:w%(%s%8%s$rMQ$$$k>l9g$K$O!"\e(B
+@samp{shaving group:alt.sysadmin.recovery} \e$B$N$h$&$J9gCW$9$kJ8;zNs$rMQ$$\e(B
+\e$B$k$3$H$K$h$C$F!"8!:wBP>]$rFCDj$N%0%k!<%W$K8BDj$9$k$3$H$,2DG=$G$9!#\e(B
+
+@item G R
+@kindex G R (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-rss-group
+@acronym{RSS} feed \e$B$K4p$E$/%0%k!<%W$r:n$j$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-rss-group})\e$B!#\e(BURL \e$B$NF~NO$rB%$5$l$^$9!#\e(B
+@xref{RSS}.
+
+@item G DEL
+@kindex G DEL (\e$B%0%k!<%W\e(B)
+@findex gnus-group-delete-group
+\e$B$3$N4X?t$O8=:_$N%0%k!<%W$r:o=|$7$^$9\e(B (@code{gnus-group-delete-group})\e$B!#\e(B
+\e$B@\F,<-$,M?$($i$l$k$H!"$3$N4X?t$O$=$N%0%k!<%WFb$NA45-;v$rK\Ev$K:o=|$7!"%0\e(B
+\e$B%k!<%W<+?H$r$3$N@$$+$i6/@)E*$KKu;&$7$F$7$^$$$^$9!#@\F,<-$O!"$"$J$?$,2?$r\e(B
+\e$B$d$m$&$H$7$F$$$k$+!"K\Ev$K<+?.$,$"$k$H$-$K$N$_;H$C$F$/$@$5$$!#$^$"!"$3$N\e(B
+\e$B%3%^%s%I$O\e(B (@code{nntp} \e$B%0%k!<%W$N$h$&$J\e(B) \e$BFI$_=P$7@lMQ%0%k!<%W$K$O;H$($^\e(B
+\e$B$;$s$1$I!#\e(B
+
+@item G V
+@kindex G V (\e$B%0%k!<%W\e(B)
+@findex gnus-group-make-empty-virtual
+\e$B?7$7$$!"?7A/$J!"6u$N\e(B @code{nnvirtual} \e$B%0%k!<%W$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-make-empty-virtual})\e$B!#\e(B@xref{Virtual Groups}.
+
+@item G v
+@kindex G v (\e$B%0%k!<%W\e(B)
+@findex gnus-group-add-to-virtual
+\e$B8=:_$N%0%k!<%W$r\e(B @code{nnvirtual} \e$B%0%k!<%W$KDI2C$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-add-to-virtual})\e$B!#$3$l$O%W%m%;%90u\e(B/\e$B@\F,0z?t$N=,47$K\e(B
+\e$B=>$$$^$9!#\e(B
+@end table
+
+\e$B$5$^$6$^$JA*BrJ}K!$K4X$9$k$5$i$J$k>pJs$O\e(B @ref{Select Methods} \e$B$r;2>H$7$F\e(B
+\e$B2<$5$$!#\e(B
+
+@vindex gnus-activate-foreign-newsgroups
+\e$B$b$7\e(B @code{gnus-activate-foreign-newsgroups} \e$B$,@5$N?t$G$"$l$P!"\e(Bgnus \e$B$O5/\e(B
+\e$BF0;~$K!"$3$N?t$+$=$l$h$j$b>.$5$$%l%Y%k$N30It%0%k!<%W$rA4$F%A%'%C%/$7$^$9!#\e(B
+\e$B$3$l$OFC$K0c$C$?\e(B @acronym{NNTP} \e$B%5!<%P$+$i$?$/$5$s$N%0%k!<%W$r9XFI$7$F$$\e(B
+\e$B$k>l9g$J$I!"$7$P$i$/;~4V$,$+$+$k$+$b$7$l$^$;$s!#\e(B@ref{Group Levels} \e$B$b;2\e(B
+\e$B>H$7$F2<$5$$!#\e(B@code{gnus-activate-level} \e$B$b30It%K%e!<%9%0%k!<%W$N3h@-2=\e(B
+\e$B$K1F6A$r5Z$\$7$^$9!#\e(B
+
+@node Group Parameters
+@section \e$B%0%k!<%W%Q%i%a!<%?\e(B
+@cindex group parameters
+
+\e$B%0%k!<%W%Q%i%a!<%?$O!"$"$kFCDj$N%0%k!<%W$K8GM-$J>pJs$r3JG<$7$^$9!#0J2<$O\e(B
+\e$B%0%k!<%W%Q%i%a!<%?%j%9%H$NNc$G$9\e(B:
+
+@example
+((to-address . "ding@@gnus.org")
+ (auto-expire . t))
+@end example
+
+\e$B$=$l$>$l$NMWAG$O!XE@BP!Y\e(B(dotted pair)\e$B!=!=$D$^$jE@\e(B (dot) \e$B$NA0$K80!"E@$N8e\e(B
+\e$B$m$KCM$,$"$k$b$N!"$G9=@.$5$l$^$9!#A4$F$N%Q%i%a!<%?$O$3$N7A<0$r<h$j$^$9$,!"\e(B
+@emph{\e$BNc30\e(B}\e$B$H$7$F6I=jJQ?t$N;XDj$OE@BP$G$O$J$/DL>o$N%j%9%H$K$J$j$^$9!#\e(B
+
+\e$B$$$/$D$+$N%Q%i%a!<%?$OBP1~$9$k%+%9%?%^%$%:2DG=$JJQ?t$r;}$C$F$$$^$9!#$=$l\e(B
+\e$B$i$O@55,I=8=$HCM$NO"A[%j%9%H$G$9!#\e(B
+
+\e$B0J2<$OMxMQ2DG=$J%0%k!<%W%Q%i%a!<%?$G$9\e(B:
+
+@table @code
+@item to-address
+@cindex to-address
+\e$B%U%)%m!<%"%C%W$H%K%e!<%9$X$NEj9F$r$9$k$H$-$K;HMQ$5$l$k%"%I%l%9!#\e(B
+
+@example
+(to-address . "some@@where.com")
+@end example
+
+\e$B$3$l$O<g$K!"JD$8$?%a!<%j%s%0%j%9%H$rI=$o$9%a!<%k%0%k!<%W$K$*$$$FJXMx$J$b\e(B
+\e$B$N$G$9!=!=$9$J$o$A%a!<%j%s%0%j%9%H$KEj9F$9$k?M$OA4$F$=$l$r9XFI$7$F$$$k$O\e(B
+\e$B$:!"$H$$$&%a!<%j%s%0%j%9%H$N$3$H$G$9!#$3$N%Q%i%a!<%?$r;HMQ$9$k$H!"%a!<%k\e(B
+\e$B$O$=$N%a!<%j%s%0%j%9%H$K$7$+Ej9F$5$l$J$$$3$H$,J]>Z$5$l$k$N$G!";22C<T$O$"\e(B
+\e$B$J$?$N%U%)%m!<%"%C%W5-;v$rFsDL<u$1<h$k$3$H$O$"$j$^$;$s!#\e(B
+
+@code{to-address} \e$B$r;XDj$9$k$H!"$=$N%0%k!<%W$,30It%0%k!<%W$G$"$k$+$I$&$+\e(B
+\e$B$K4X$o$i$:M-8z$K$J$j$^$9!#Nc$($P\e(B @samp{fa.4ad-l} \e$B$H$$$&%0%k!<%W$,%5!<%P\e(B
+\e$B>e$K$"$C$?$H$7$^$7$g$&!#$3$l$OK\Ev$N%K%e!<%9%0%k!<%W$G$9$,!"%5!<%P$O%a!<\e(B
+\e$B%k%K%e!<%9%2!<%H%&%'%$$rDL$7$F5-;v$r<u$1IU$1$^$9!#$D$^$j$3$N%0%k!<%W$KBP\e(B
+\e$B$7$FD>@\Ej9F$9$k$3$H$OIT2DG=$G!"Be$o$j$K$=$N%a!<%j%s%0%j%9%H$K%a!<%k$rAw\e(B
+\e$B?.$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+@code{gnus-parameter-to-address-alist} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item to-list
+@cindex to-list
+\e$B$=$N%0%k!<%W$G\e(B @kbd{a} \e$B$r2!$7$?$H$-$K;HMQ$5$l$k%"%I%l%9!#\e(B
+
+@example
+(to-list . "some@@where.com")
+@end example
+
+\e$B$3$l$O%U%)%m!<%"%C%W$r$7$?$H$-$O40A4$KL5;k$5$l$^$9!=!=Nc30$O$=$l$,%K%e!<\e(B
+\e$B%9%0%k!<%W$rI=$o$7$F$$$k$H$-$O!"\e(B@kbd{f} \e$B$r2!$7$?$H$-$K%a!<%k%0%k!<%W$N%k!<\e(B
+\e$B%k$,E,MQ$5$l$k$H$$$&$3$H$G$9!#\e(B
+
+\e$B$b$7\e(B @kbd{a} \e$B%3%^%s%I$r%a!<%k%0%k!<%W$G<B9T$7$?$H$-$K!"\e(B@code{to-list} \e$B%0\e(B
+\e$B%k!<%W%Q%i%a!<%?$b\e(B @code{to-address} \e$B$b%0%k!<%W%Q%i%a!<%?$bL5$1$l$P!"\e(B
+@code{to-list} \e$B%0%k!<%W%Q%i%a!<%?$O!"\e(B
+@code{gnus-add-to-list} \e$B$,\e(B @code{t} \e$B$K@_Dj$5$l$F$$$l$P%a%C%;!<%8Aw?.;~$K\e(B
+\e$B<+F0E*$KIU2C$5$l$^$9!#\e(B
+@vindex gnus-add-to-list
+
+@findex gnus-mailing-list-mode
+@cindex mail list groups
+\e$B$b$7$3$N%0%k!<%W%Q%i%a!<%?$,@_Dj$5$l$F$$$k$H!"35N,%P%C%U%!$KF~$C$?$H$-\e(B
+\e$B$K\e(B @code{gnus-mailing-list-mode} \e$B$,M-8z$K$J$j$^$9!#\e(B
+
+@code{gnus-parameter-to-list-alist} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@anchor{subscribed}
+@item subscribed
+@cindex subscribed
+@cindex Mail-Followup-To
+@findex gnus-find-subscribed-addresses
+\e$B$b$7$3$N%Q%i%a!<%?$,\e(B @code{t} \e$B$K@_Dj$5$l$F$$$k$H!"\e(Bgnus \e$B$O$"$J$?$,$3$N%0\e(B
+\e$B%k!<%W$r\e(B to-address \e$B$H\e(B to-list \e$B%Q%i%a!<%?$N%"%I%l%9$G9XFI$7$F$$$k%a!<%j\e(B
+\e$B%s%0%j%9%H$G$"$k$H2r<a$7$^$9!#$3$N>pJs$r\e(B gnus \e$B$KM?$($k$3$H$O!"$"$J$?$,$=\e(B
+\e$B$l$i$N%a!<%j%s%0%j%9%H$KEj9F$9$k$H$-$K@5$7$$\e(B Mail-Followup-To \e$B%X%C%@!<$r\e(B
+\e$B@8@.$9$k$?$a$N\e(B (\e$B$[$s$N\e(B) \e$BBh0lJb$G$9!#FsJbL\$O\e(B @file{.gnus.el} \e$B$K0J2<$rF~\e(B
+\e$B$l$k$3$H$G$9!#\e(B
+
+@lisp
+(setq message-subscribed-address-functions
+      '(gnus-find-subscribed-addresses))
+@end lisp
+
+\e$BMxMQ$G$-$k\e(B MFT \e$BBP1~5!G=$r40A4$K07$&$K$O!"$3$3\e(B (@pxref{Mailing Lists, ,
+Mailing Lists, message-ja, The Message Manual}) \e$B$r8+$F2<$5$$!#\e(B
+
+@item visible
+@cindex visible
+\e$B%0%k!<%W%Q%i%a!<%?$N%j%9%HCf$K\e(B @code{(visible . t)} \e$B$H$$$&MWAG$,$"$l$P!"\e(B
+\e$B$=$N%0%k!<%W$O%0%k!<%W%P%C%U%!$K$*$$$F!"L$FI5-;v$,$"$k$+$I$&$+$K4X$o$i$:!"\e(B
+\e$B>o$KI=<($5$l$^$9!#\e(B
+
+@item broken-reply-to
+@cindex broken-reply-to
+@code{(broken-reply-to . t)} \e$B$H$$$&MWAG$,$"$l$P!"$=$N%0%k!<%W$G\e(B
+\e$B$O\e(B @code{Reply-To} \e$B$OL5;k$5$l!"\e(B
+@code{reply-to} \e$B$,\e(B @code{gnus-boring-article-headers} \e$B$NItJ,$G$"$l$P!"%X%C\e(B
+\e$B%@!<$,1#$5$l$k$H$$$&0UL#$G$9!#$3$l$O$"$k\e(B listserv \e$B$K$h$k%a!<%j%s%0%j%9%H\e(B
+\e$B$r9XFI$7$F$$$F!"$=$l$,\e(B @code{Reply-To} \e$BMs$r\e(B listserv \e$B<+?H$KJV$9$h$&$K$D\e(B
+\e$B$1$i$l$F$$$k>l9g$KM-8z$G$7$g$&!#$3$l$O$*$+$7$J?6$kIq$$$G$9!#$@$+$i$3$l$,\e(B
+\e$BMW$k$s$G$9\e(B!
+
+@item to-group
+@cindex to-group
+@code{(to-group . "some.group.name")} \e$B$H$$$&MWAG$O!"$=$N%0%k!<%W$X$NEj9F\e(B
+\e$B$OA4$F\e(B @code{some.group.name} \e$B$KAw$i$l$k!"$H$$$&0UL#$G$9!#\e(B
+
+@item newsgroup
+@cindex newsgroup
+\e$B%0%k!<%W%Q%i%a!<%?%j%9%H$K\e(B @code{(newsgroup . t)} \e$B$,$"$l$P!"\e(Bgnus \e$B$OA4$F\e(B
+\e$B$N1~Ez$r%K%e!<%95-;v$KBP$9$k1~Ez$G$"$k$+$N$h$&$K07$$$^$9!#$3$l$O<B:]$K$O\e(B
+\e$B%K%e!<%9%0%k!<%W$N%_%i!<$G$"$k%a!<%k%0%k!<%W$KBP$7$FM-8z$G$9!#\e(B
+
+@item gcc-self
+@cindex gcc-self
+\e$B%0%k!<%W%Q%i%a!<%?%j%9%H$K\e(B @code{(gcc-self . t)} \e$B$,$"$l$P!"?7$7$/:n@.$9\e(B
+\e$B$k%a%C%;!<%8$O8=:_$N%0%k!<%W$K\e(B @code{Gcc} \e$B$5$l$^$9!#$b\e(B
+\e$B$7\e(B @code{(gcc-self . none)} \e$B$,$"$l$P!"\e(B@code{Gcc:} \e$BMs$O@8@.$5$l$:!"\e(B
+@code{(gcc-self . "string")} \e$B$,$"$l$P$3$NJ8;zNs$O$=$N$^$^\e(B @code{gcc} \e$BMs\e(B
+\e$B$KA^F~$5$l$^$9!#$3$N%Q%i%a!<%?$O0J2<$G@bL@$9$kA4$F$N\e(B @code{Gcc} \e$B$N=i4|5,\e(B
+\e$BB'$h$j$bM%@h$5$l$^$9\e(B (@pxref{Archived Messages})\e$B!#\e(B
+
+@strong{\e$B7Y9p\e(B}: @code{nntp} (\e$B$^$?$O$=$N<o$N\e(B) \e$B%0%k!<%W$N%Q%i%a!<%?%j%9%H\e(B
+\e$B$K\e(B @code{(gcc-self . t)} \e$B$r2C$($k$3$H$K8zNO$O$"$j$^$;$s!#\e(B@code{nntp} \e$B%5!<\e(B
+\e$B%P!<$O5-;v$r<u$1F~$l$^$;$s!#\e(B
+
+@item auto-expire
+@cindex auto-expire
+\e$B%0%k!<%W%Q%i%a!<%?$K\e(B @code{(auto-expire . t)} \e$B$N$h$&$JMWAG$,$"$l$P!"A4$F\e(B
+\e$B$N4{FI5-;v$O;~8B>C5n$5$l$k$h$&$K0u$rIU$1$i$l$^$9!#B>$NJ}K!$O!"\e(B
+@xref{Expiring Mail}.
+
+@code{gnus-auto-expirable-newsgroups} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item total-expire
+@cindex total-expire
+\e$B%0%k!<%W%Q%i%a!<%?$K\e(B @code{(total-expire . t)} \e$B$N$h$&$JMWAG$,$"$l$P!"4{\e(B
+\e$BFI5-;v$O!";~8B>C5n$N0u$,$D$$$F$$$J$/$H$bA4$F;~8B>C5n=hM}$r;\$5$l$^$9!#Cm\e(B
+\e$B0U$7$F;HMQ$7$F$/$@$5$$!#L$FI5-;v!"0uIU$-5-;v!"J]N15-;v$O;~8B>C5n$5$l$^$;\e(B
+\e$B$s!#\e(B
+
+@code{gnus-total-expirable-newsgroups} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item expiry-wait
+@cindex expiry-wait
+@vindex nnmail-expiry-wait-function
+\e$B%0%k!<%W%Q%i%a!<%?$K\e(B @code{(expiry-wait . 10)} \e$B$N$h$&$JMWAG$,$"$l$P!"$3\e(B
+\e$B$NCM$O5-;v$r;~8B>C5n$9$k$H$-\e(B
+\e$B$K\e(B @code{nnmail-expiry-wait} \e$B$H\e(B @code{nnmail-expiry-wait-function} \e$B$N@_\e(B
+\e$BDj\e(B (@pxref{Expiring Mail}) \e$B$h$j$bM%@h$5$l$^$9!#$3$NCM$O;~8B>C5n$NF|\e(B
+\e$B?t\e(B (\e$B@0?t$G$"$kI,MW$O$J$$\e(B) \e$B$+$b$7$/$O\e(B @code{never} \e$B$+\e(B @code{immediate} \e$B$N\e(B
+\e$B%7%s%\%k$r;XDj$G$-$^$9!#\e(B
+
+@item expiry-target
+@cindex expiry-target
+\e$B;~8B>C5n$5$l$k%a%C%;!<%8$N2L$F$k>l=j!#$3$N%Q%l%a!<%?\e(B
+\e$B$O\e(B @code{nnmail-expiry-target} \e$B$r>e=q$-$7$^$9!#\e(B
+
+@item score-file
+@cindex score file group parameter
+@code{(score-file . "file")} \e$B$N$h$&$JMWAG$O!"\e(B@file{file} \e$B$r8=:_$N%0%k!<\e(B
+\e$B%W$KE,MQ$5$l$k%9%3%"%U%!%$%k$K$7$^$9!#E,MQ$5$l$k%9%3%"EPO?$OA4$F$3$N%U%!\e(B
+\e$B%$%k$KF~$j$^$9!#\e(B
+
+@item adapt-file
+@cindex adapt file group parameter
+@code{(adapt-file . "file")} \e$B$N$h$&$JMWAG$O!"\e(B@file{file} \e$B$r8=:_$N%0%k!<\e(B
+\e$B%W$NE,1~%U%!%$%k$K$7$^$9!#A4$F$NE,1~%9%3%"EPO?$O$3$N%U%!%$%k$KF~$j$^$9!#\e(B
+
+@item admin-address
+@cindex admin-address
+\e$B%a!<%j%s%0%j%9%H$+$iC&2q$9$k$H$-$O!"C&2qDLCN%a!<%k$r$=$N%a!<%j%s%0%j%9%H\e(B
+\e$B<+?H$KAw?.$7$F$O$$$1$^$;$s!#Be$o$j$K4IM}MQ%"%I%l%9$K%a%C%;!<%8$rAw?.$7$^\e(B
+\e$B$9!#$3$N%Q%i%a!<%?$K$O$I$3$+JXMx$J4IM}MQ%"%I%l%9$r=q$$$F$*$/$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+@item display
+@cindex display
+@code{(display . MODE)} \e$B$N$h$&$JMWAG$O!"%0%k!<%W$KF~$k$H$-$K$I$N5-;v$rI=\e(B
+\e$B<($9$k$+$r;XDj$7$^$9!#M-8z$JCM$O!"\e(B
+
+@table @code
+@item all
+\e$BL$FI!"4{FI5-;v$NN>J}$rA4$FI=<($7$^$9!#\e(B
+
+@item an integer
+\e$B$=$N%0%k!<%W$N:G8e$N\e(B @var{integer} \e$B8D$N5-;v$rI=<($7$^$9!#$3$l\e(B
+\e$B$O\e(B @kbd{C-u @var{integer}} \e$B$G$=$N%0%k!<%W$KF~$k$N$HF1$8$G$9!#\e(B
+
+@item default
+\e$B=i4|@_Dj$G$NI=<(5-;v$rI=<($7$^$9!#$3$l$ODL>o$OL$FI5-;v$H0uIU$-5-;v$G$9!#\e(B
+
+@item \e$BG[Ns\e(B
+\e$B=R8l$rK~B-$9$k$h$&$K5-;v$rI=<($7$^$9!#\e(B
+
+\e$B$$$/$D$+Nc$r5s$2$^$9\e(B:
+
+@table @code
+@item [unread]
+\e$BL$FI$N5-;v$@$1$rI=<($7$^$9!#\e(B
+
+@item [not expire]
+\e$B4|8B@Z$l>C5n2DG=$J5-;v0J30$N$9$Y$F$rI=<($7$^$9!#\e(B
+
+@item [and (not reply) (not expire)]
+\e$B4|8B@Z$l>C5n2DG=$H$9$G$KJV?.$7$?5-;v0J30$N$9$Y$F$rI=<($7$^$9!#\e(B
+@end table
+
+\e$BMxMQ$G$-$k1i;;;R$O\e(B @code{not}, @code{and} \e$B$*$h$S\e(B @code{or} \e$B$G$9!#=R8l\e(B
+\e$B$O\e(B @code{tick}, @code{unsend}, @code{undownload}, @code{unread},
+@code{dormant}, @code{expire}, @code{reply}, @code{killed},
+@code{bookmark}, @code{score}, @code{save}, @code{cache}, @code{forward},
+@code{unseen} \e$B$*$h$S\e(B @code{recent} \e$B$r4^$_$^$9!#\e(B
+@end table
+
+@code{display} \e$B%Q%i%a!<%?$O!"35N,%P%C%U%!$r;XDj$7$?0lIt$NAH$@$1$K@)8B$9\e(B
+\e$B$k$h$&$KF/$-$^$9!#@)8B$r%9%?%C%/$+$i<h$j=P$9$N$O\e(B @kbd{/ w} \e$B%3%^%s%I$G$G\e(B
+\e$B$-$^$9\e(B (@pxref{Limiting})\e$B!#\e(B
+
+@item comment
+@cindex comment
+@code{(comment . "This is a comment")} \e$B$N$h$&$JMWAG$O!"$=$N%0%k!<%W$KBP\e(B
+\e$B$9$kG$0U$N%3%a%s%H$G$9!#%0%k!<%W9T$KI=<($9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Group Line Specification})\e$B!#\e(B
+
+@ignore
+@item charset
+@cindex charset
+Elements that look like @code{(charset . iso-8859-1)} will make
+@code{iso-8859-1} the default charset; that is, the charset that will be
+used for all articles that do not specify a charset.
+
+See also @code{gnus-group-charset-alist}.
+
+@item ignored-charsets
+@cindex ignored-charsets
+Elements that look like @code{(ignored-charsets x-unknown iso-8859-1)}
+will make @code{iso-8859-1} and @code{x-unknown} ignored; that is, the
+default charset will be used for decoding articles.
+
+See also @code{gnus-group-ignored-charsets-alist}.
+@end ignore
+@item posting-style
+@cindex posting-style
+\e$B$3$N%0%k!<%W$NDI2C$NEj9FMM<0$r$3$3$KJ]B8$9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Posting Styles})\e$B!#=q<0$O\e(B @code{gnus-posting-style} \e$BO"A[%j%9%H\e(B
+\e$B$HF1$8$G$9$,!"$3$3$K$O%0%k!<%WL>$K9gCW$9$k@55,I=8=$O$"$j$^$;$s\e(B (\e$BEvA3$G\e(B
+\e$B$9\e(B)\e$B!#$3$N%0%k!<%W$NMM<0$NMWAG$O\e(B @code{gnus-posting-styles} \e$B$G8+$D$+$C$?\e(B
+\e$B$b$N$h$j$bM%@h$5$l$^$9!#\e(B
+
+\e$BNc$($P!"$3$N%0%k!<%W$N$_!"$+$C$3$$$$L>A0$H=pL>$K$7$?$$$J$i!"\e(B
+@code{gnus-posting-styles} \e$B$r$$$8$i$:$K!"$3$N$h$&$J$b$N$r%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$KF~$l$k$3$H$,$G$-$^$9\e(B:
+
+@example
+(posting-style
+  (name "Funky Name")
+  ("X-My-Header" "Funky Value")
+  (signature "Funky Signature"))
+@end example
+
+@item post-method
+@cindex post-method
+\e$B$b$7$3$l$,@_Dj$5$l$F$$$k$H!"%a%C%;!<%8$rAw?.$9$k$?$a$NA*BrJ}K!$H$7\e(B
+\e$B$F\e(B @code{gnus-post-method} \e$B$NBe$o$j$K;H$o$l$^$9!#\e(B
+
+@item banner
+@cindex banner
+@code{(banner . @var{regex})} \e$B$N$h$&$J9`L\$O!"5-;v$N$9$Y$F$N>l=j$G@55,I=\e(B
+\e$B8=\e(B @var{regex} \e$B$K%^%C%A$9$k$b$N$r:o=|$7$^$9!#\e(B@var{regex} \e$B$NBe$o$j$K%7%s\e(B
+\e$B%\%k\e(B @code{signature} (\e$B:G8e$N=pL>$r:o\e(B
+\e$B=|\e(B) \e$B$dO"A[%j%9%H\e(B @code{gnus-article-banner-alist} \e$B$N3FMWAG$r;H$&$3$H$b$G\e(B
+\e$B$-$^$9!#\e(B
+
+@item sieve
+@cindex sieve
+\e$B$3$N%Q%i%a!<%?$O!"F~$C$F$-$?%a!<%k$,$3$N%0%k!<%W$KCV$/$KCM$9$k$+$I$&$+$r\e(B
+\e$BD4$Y$k\e(B Sieve (\e$B$U$k$$\e(B) \e$B%F%9%H$r;}$A$^$9!#$3$N%0%k!<%W%Q%i%a!<%?$r85\e(B
+\e$B$K\e(B @samp{fileinto "group.name";} \e$B$H$$$&%F%9%H>r7o$rK\BN$K;}$D!"\e(B
+Sieve \e$B$N\e(B @samp{IF} \e$B@)8f9=B$BN$,:n$i$l$^$9!#\e(B
+
+\e$BNc$($P!"$b$7\e(B @samp{INBOX.list.sieve} \e$B%0%k!<%W$,\e(B @code{(sieve address
+"sender" "sieve-admin@@extundo.com")} \e$B$H$$$&%0%k!<%W%Q%i%a!<%?$r;}$C$F$$\e(B
+\e$B$?$J$i$P!"%0%k!<%W%Q%i%a!<%?$r\e(B Sieve \e$B%9%/%j%W%H$KJQ49$9$k\e(B (@pxref{Sieve
+Commands}) \e$B$H$-$K!"0J2<$N\e(B Sieve \e$B%3!<%I$,:n$i$l$^$9\e(B:
+
+@example
+if address \"sender\" \"sieve-admin@@extundo.com\" @{
+        fileinto \"INBOX.list.sieve\";
+@}
+@end example
+
+Sieve \e$B8@8l$O\e(B RFC 3028 \e$B$G=R$Y$i$l$F$$$^\e(B
+\e$B$9\e(B (@pxref{Top, Emacs Sieve, Top, sieve, Emacs Sieve})\e$B!#\e(B
+
+@item (agent parameters)
+\e$B%(!<%8%'%s%H$r;H$&$h$&$K$7$F$"$k$H!"8D!9$N%0%k!<%W$G%(!<%8%'%s%H$N?6$kIq\e(B
+\e$B$$$r@)8f$9$k$I$N%Q%i%a!<%?$b@_Dj$9$k$3$H$,$G$-$^$9!#%(!<%8%'%s%H%Q%i%a!<\e(B
+\e$B%?$K$D$$$F$O\e(B @ref{Category Syntax} \e$B$r;2>H$7$F2<$5$$!#$?$$$F$$$N%f!<%6$O!"\e(B
+\e$B@_Dj$KMW$9$k6lO+$r:G>.8B$K$9$k$?$a$K!"%(!<%8%'%s%H%+%F%4%j!<$+%0%k!<%W%H\e(B
+\e$B%T%C%/$N$I$A$i$+$G%(!<%8%'%s%H%Q%i%a!<%?$r@_Dj$9$k$3$H$rA*$V$G$7$g$&!#\e(B
+
+@item (@var{variable} @var{form})
+\e$B%0%k!<%W$KF~$k$H$-$K!"$=$N%0%k!<%W%m!<%+%k$NJQ?t$r@_Dj$9$k%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$r;HMQ$9$k$3$H$,$G$-$^$9!#\e(B@samp{news.answers} \e$B$K$*$$$F%9%l%C%II=<($r9T\e(B
+\e$B$$$?$/$J$$$H$-$O!"$=$N%0%k!<%W$K%0%k!<%W%Q%i%a!<%?\e(B
+\e$B$K\e(B @code{(gnus-show-threads nil)} \e$B$H=q$1$^$9!#\e(B
+@code{gnus-show-threads} \e$B$O!"$=$N35N,%P%C%U%!$NCf$N%m!<%+%kJQ?t$K$J$j!"\e(B
+form \e$B$N\e(B @code{nil} \e$B$O$=$3$GI>2A$5$l$^$9!#\e(B
+
+\e$B$3$N5!G=$O!"JQ?t$r35N,%P%C%U%!$G%m!<%+%k$K@_Dj$9$k$3$H$KCm0U$7$F2<$5$$!#\e(B
+\e$B$G$b!"$$$/$D$+$NJQ?t$O5-;v%P%C%U%!$+\e(B (\e$BJV?.!"%U%)%m!<!"$"$k$$$O?75,$K:n$i\e(B
+\e$B$l$?%a%C%;!<%8$N\e(B) \e$B%a%C%;!<%8%P%C%U%!$GI>2A$5$l$^$9!#Be$o$j$K!"LdBj$NJQ?t\e(B
+\e$B$r\e(B @code{gnus-newsgroup-variables} \e$B$K2C$($k$3$H$,=u$1$K$J$k$+$b$7$l$^$;\e(B
+\e$B$s!#$7$?$,$C$F!"%0%k!<%W%Q%i%a!<%?$r2p$7$F\e(B @code{message-from-style} \e$B$r\e(B
+\e$B@_Dj$7$?$$$J$i$P!"\e(B@file{~/.gnus}\e$B%U%!%$%k$N$I$3$+B>$N$H$3$m$K!"<!$N=R8l$,\e(B
+\e$BI,MW$K$J$k$+$b$7$l$^$;$s\e(B:
+
+@lisp
+(add-to-list 'gnus-newsgroup-variables 'message-from-style)
+@end lisp
+
+@vindex gnus-list-identifiers
+\e$B$3$N5!G=$NMQES$N0l$D$O!"5-;v$NBjL>Ms$+$i%a!<%j%s%0%j%9%H$NI8<1%?%0$r$O$.\e(B
+\e$B<h$k$3$H$G$9!#$b$7%K%e!<%9%0%k!<%W\e(B
+
+@example
+nntp+news.gnus.org:gmane.text.docbook.apps
+@end example
+
+\e$B$,!"$9$Y$F$N5-;v$NBjL>$K\e(B @samp{DOC-BOOK-APPS:} \e$B$H$$$&%?%0$r;}$C$F$$$k$J\e(B
+\e$B$i$P!"$=$N%0%k!<%W$N%0%k!<%W%Q%i%a!<%?$K\e(B @code{(gnus-list-identifiers
+"DOCBOOK-APPS:")} \e$B$rF~$l$k$3$H$K$h$C$F!"$=$N%0%k!<%W$N35N,%P%C%U%!$KI=<(\e(B
+\e$B$5$l$k5-;v$NBjL>$+$i%?%0$r$O$.<h$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$3$l$O$b$7I,MW$G$"$l$P!"%0%k!<%WKh$N%U%C%/4X?t$H$7$F$b;HMQ$G$-$^$9!#$b$7\e(B
+\e$B$"$k%0%k!<%W$KF~$C$?$H$-$K%S!<%W2;$rLD$i$7$?$1$l$P!"$=$N%0%k!<%W$N%Q%i%a!<\e(B
+\e$B%?$K\e(B @code{(dummy-variable (ding))} \e$B$_$?$$$J$b$N$r=q$$$F$*$/$3$H$b$G$-$^\e(B
+\e$B$9!#\e(B@code{dummy-variable} \e$B$H$$$&JQ?t$K\e(B @code{(ding)} \e$B$NI>2A7k2L$,@_Dj$5\e(B
+\e$B$l$^$9$,!"$^$"!"C/$b5$$K$7$J$$$G$7$g\e(B?
+@end table
+
+\e$B%0%k!<%W%Q%i%a!<%?$N=$@5$K$O\e(B @kbd{G p} \e$B$+\e(B @kbd{G c} \e$BL?Na$r;H$C$F$/$@$5\e(B
+\e$B$$\e(B (@kbd{G p} \e$B$O\e(B Lisp \e$B%Y!<%9$N!"\e(B@kbd{G c} \e$B$O\e(B Custom \e$B$U$&$N%$%s%?!<%U%'!<\e(B
+\e$B%9$rDs6!$7$^$9\e(B)\e$B!#%H%T%C%/%Q%i%a!<%?$K$D$$$FFI$s$G$_$k$3$H$bLLGr$$$G$7$g\e(B
+\e$B$&\e(B (@pxref{Topic Parameters})\e$B!#\e(B
+
+@vindex gnus-parameters
+\e$B%0%k!<%W%Q%i%a!<%?$O\e(B @code{gnus-parameters} \e$BJQ?t$r2p:_$7$F@_Dj$9$k$3$H$b\e(B
+\e$B$G$-$^$9!#$G$b$$$/$D$+$N%Q%i%a!<%?!"Nc$($P\e(B @code{visible} \e$B$O8zNO$rH/4x$7\e(B
+\e$B$^$;$s!#Nc$G$9!#\e(B
+
+@lisp
+(setq gnus-parameters
+      '(("mail\\..*"
+         (gnus-show-threads nil)
+         (gnus-use-scoring nil)
+         (gnus-summary-line-format
+          "%U%R%z%I%(%[%d:%ub%-23,23f%]%) %s\n")
+         (gcc-self . t)
+         (display . all))
+
+        ("^nnimap:\\(foo.bar\\)$"
+         (to-group . "\\1"))
+
+        ("mail\\.me"
+         (gnus-use-scoring  t))
+
+        ("list\\..*"
+         (total-expire . t)
+         (broken-reply-to . t))))
+@end lisp
+
+\e$BJ8;zNs$NCM$O!"\e(B@code{to-group} \e$B$NNc$,<($9$h$&$K!"@55,I=8=$K$h$kCV$-49$($r\e(B
+\e$B<u$1$k$3$H$,$"$j$^$9!#\e(B
+
+@node Listing Groups
+@section \e$B%0%k!<%W$N0lMwI=<(\e(B
+@cindex group listing
+
+\e$B$3$l$i$N%3%^%s%I$O!"MxMQ$G$-$k%0%k!<%W$r$$$m$$$m$K@Z$jJ,$1$FI=<($7$^$9!#\e(B
+
+@table @kbd
+@item l
+@itemx A s
+@kindex A s (\e$B%0%k!<%W\e(B)
+@kindex l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-groups
+\e$BL$FI5-;v$r;}$DA4$F$N%0%k!<%W$rI=<($7$^$9\e(B (@code{gnus-group-list-groups})\e$B!#\e(B
+\e$B?t;z@\F,0z?t$r;H$&$H!"$3$N%3%^%s%I$O0z?t$N?t$+$=$l$h$j$b>.$5$$%l%Y%k$N%0\e(B
+\e$B%k!<%W$N$_$rI=<($7$^$9!#=i4|@_Dj$G$O!"$3$l$O%l%Y%k\e(B 5 (\e$B$D$^\e(B
+\e$B$j\e(B @code{gnus-group-default-list-level}) \e$B$+$=$l$h$j>.$5$$%l%Y%k\e(B (\e$B$9$J$o\e(B
+\e$B$A9XFI$7$F$$$k%0%k!<%W$N$_\e(B) \e$B$rI=<($7$^$9!#\e(B
+
+@item L
+@itemx A u
+@kindex A u (\e$B%0%k!<%W\e(B)
+@kindex L (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-all-groups
+\e$BL$FI5-;v$N$"$k$J$7$K4X$o$i$:!"A4$F$N%0%k!<%W$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-group-list-all-groups})\e$B!#?t;z@\F,0z?t$r;HMQ$9$k$H!"$3$N%3\e(B
+\e$B%^%s%I$O0z?t$N?t$+$=$l$h$j$b>.$5$$%l%Y%k$N%0%k!<%W$N$_$rI=<($7$^$9!#=i4|\e(B
+\e$B@_Dj$G$O\e(B 7 \e$B$+$=$l$h$j$b>.$5$$%l%Y%k$N%0%k!<%W\e(B (\e$B$9$J$o$A9XFI!"Hs9XFI$N%0\e(B
+\e$B%k!<%W$N$_\e(B) \e$B$,I=<($5$l$^$9!#\e(B
+
+@item A l
+@kindex A l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-level
+\e$B$"$kFCDj$N%l%Y%k$NL$FI5-;v$N$"$k%0%k!<%W$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-group-list-level})\e$B!#@\F,<-$rM?$($k$H!"L$FI5-;v$N$J$$%0%k!<\e(B
+\e$B%W$b4^$a$FI=<($7$^$9!#\e(B
+
+@item A k
+@kindex A k (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-killed
+kill \e$B$5$l$?%0%k!<%W$rA4$FI=<($7$^$9\e(B (@code{gnus-group-list-killed})\e$B!#@\\e(B
+\e$BF,0z?t$rM?$($k$H!"8=:_9XFI!"Hs9XFI$H$J$C$F$$$J$$A4$F$NMxMQ2DG=$J%0%k!<%W\e(B
+\e$B$rI=<($7$^$9!#$3$l$O%5!<%P$+$i%"%/%F%#%V%U%!%$%k$rFI$`$3$H$K$J$k$G$7$g$&!#\e(B
+
+@item A z
+@kindex A z (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-zombies
+\e$BA4$F$N%>%s%S%0%k!<%W$rI=<($7$^$9\e(B (@code{gnus-group-list-zombies})\e$B!#\e(B
+
+@item A m
+@kindex A m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-matching
+\e$B@55,I=8=$K9gCW$9$kL>A0$r;}$D%0%k!<%W$G!"L$FI5-;v$N$"$k9XFI%0%k!<%W$rA4$F\e(B
+\e$BI=<($7$^$9\e(B (@code{gnus-group-list-matching})\e$B!#\e(B
+
+@item A M
+@kindex A M (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-all-matching
+\e$B@55,I=8=$K9gCW$9$k%0%k!<%W$rI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-list-all-matching})\e$B!#\e(B
+
+@item A A
+@kindex A A (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-active
+\e$B:#@\B3$7$F$$$k%5!<%P$N%"%/%F%#%V%U%!%$%k$K$"$k%0%k!<%W$r!"K\Ev$KA4ItI=<(\e(B
+\e$B$7$^$9\e(B (@code{gnus-group-list-active})\e$B!#$3$l$O$7$P$i$/;~4V$,$+$+$k$3$H$b\e(B
+\e$BM-$jF@$^$9!#$?$V$s\e(B @kbd{A M} \e$B$r<B9T$7$F!"9gCW$5$;$?$$ItJ,$r\e(B @samp{.} \e$B$H\e(B
+\e$B$7$FA4$F$N9gCW$9$k%j%9%H$rI=<($5$;$?J}$,NI$$$G$7$g$&!#$^$?!"$3$N%3%^%s%I\e(B
+\e$B$O\e(B (\e$B$^$@\e(B) \e$BB8:_$7$J$$%0%k!<%W$bI=<($9$k$+$bCN$l$^$;$s!=!=$3$l$O\e(B kill \e$B$5$l\e(B
+\e$B$?%0%k!<%W$G$"$k$+$N$h$&$KI=<($5$l$^$9!#=PNO$OB?>/3d$j0z$$$F<u$1<h$C$F$M!#\e(B
+
+@item A a
+@kindex A a (\e$B%0%k!<%W\e(B)
+@findex gnus-group-apropos
+\e$B@55,I=8=$K9gCW$9$kL>A0$r;}$D%0%k!<%W$rA4$FI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-apropos})\e$B!#\e(B
+
+@item A d
+@kindex A d (\e$B%0%k!<%W\e(B)
+@findex gnus-group-description-apropos
+\e$B@55,I=8=$K9gCW$9$kL>A0$+@bL@J8$r;}$D%0%k!<%W$rA4$FI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-description-apropos})\e$B!#\e(B
+
+@item A c
+@kindex A c (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-cached
+\e$B%-%c%C%7%e5-;v$r;}$D%0%k!<%W$rA4$FI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-list-cached})\e$B!#\e(B
+
+@item A ?
+@kindex A ? (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-dormant
+\e$BJ]N15-;v$r;}$D%0%k!<%W$rA4$FI=<($9$k\e(B (@code{gnus-group-list-dormant})\e$B!#\e(B
+
+@item A /
+@kindex A / (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-limit
+\e$B8=:_$NA*Br$5$l$?HO0O$K8BDj$7$?%0%k!<%W$rI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-list-limit})\e$B!#\e(B
+
+@item A f
+@kindex A f (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-flush
+\e$B8=:_$NA*Br$5$l$?%0%k!<%W$r=q$-=P$9\e(B (@code{gnus-group-list-flush})\e$B!#\e(B
+
+@item A p
+@kindex A p (\e$B%0%k!<%W\e(B)
+@findex gnus-group-list-plus
+\e$B8=:_$NA*Br$5$l$?%0%k!<%W$r2C$($?%0%k!<%W$rI=<($9\e(B
+\e$B$k\e(B (@code{gnus-group-list-plus})\e$B!#\e(B
+@end table
+
+@vindex gnus-permanently-visible-groups
+@cindex visible group parameter
+@code{gnus-permanently-visible-groups} \e$B@55,I=8=$K9gCW$9$k%0%k!<%W$O!"L$\e(B
+\e$BFI5-;v$,$"$k$+$J$$$+$K4X$o$i$:>o$KI=<($5$l$^$9!#$"$k$$$O%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$K$*$$$F\e(B @code{visible} \e$BMWAG$rDI2C$9$k$3$H$G$bF1MM$N8z2L$rF@$k$3$H$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+@vindex gnus-list-groups-with-ticked-articles
+\e$B0uIU$-$N5-;v$N$_$r;}$D%0%k!<%W$ODL>o%0%k!<%W%P%C%U%!$KI=<($5$l$^$9!#$b\e(B
+\e$B$7\e(B @code{gnus-list-groups-with-ticked-articles} \e$B$,\e(B @code{nil} \e$B$G$"$l$P!"\e(B
+\e$B$=$N%0%k!<%W$O40A4$K6u$N%0%k!<%W$G$"$k$+$N$h$&$K07$o$l$^$9!#=i4|CM\e(B
+\e$B$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@node Sorting Groups
+@section \e$B%0%k!<%W$N%=!<%H\e(B
+@cindex sorting groups
+
+@kindex C-c C-s (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups
+@vindex gnus-group-sort-function
+@kbd{C-c C-s} (@code{gnus-group-sort-groups}) \e$BL?Na$O!"%0%k!<%W%P%C%U%!\e(B
+\e$B$r\e(B @code{gnus-group-sort-function} \e$BJQ?t$GM?$($i$l$k4X?t$K=>$C$FJB$YBX$(\e(B
+\e$B$^$9!#MxMQ2DG=$JJB$YBX$(4X?t\e(B (sorting function) \e$B$K$O0J2<$N$b$N$,$"$j$^\e(B
+\e$B$9\e(B:
+
+@table @code
+@item gnus-group-sort-by-alphabet
+@findex gnus-group-sort-by-alphabet
+\e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^$9!#$3$l$,=i4|@_Dj$G$9!#\e(B
+
+@item gnus-group-sort-by-real-name
+@findex gnus-group-sort-by-real-name
+\e$B%0%k!<%W$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB\e(B
+\e$B$YJQ$($^$9!#\e(B
+
+@item gnus-group-sort-by-level
+@findex gnus-group-sort-by-level
+\e$B%0%k!<%W%l%Y%k$GJB$YBX$($^$9!#\e(B
+
+@item gnus-group-sort-by-score
+@findex gnus-group-sort-by-score
+\e$B%0%k!<%W$N%9%3%"$GJB$YBX$($^$9!#\e(B@xref{Group Score}.
+
+@item gnus-group-sort-by-rank
+@findex gnus-group-sort-by-rank
+\e$B%0%k!<%W$N%9%3%"$GJB$YBX$(!"<!$K%0%k!<%W%l%Y%k$GJB$YBX$($^$9!#%l%Y%k$H%9\e(B
+\e$B%3%"$O!"$R$H$^$H$a$K$7$F\e(B @dfn{\e$B%i%s%/\e(B} \e$B$H8F$P$l$^$9!#\e(B@xref{Group Score}.
+
+@item gnus-group-sort-by-unread
+@findex gnus-group-sort-by-unread
+\e$BL$FI5-;v$N?t$GJB$YBX$($^$9!#\e(B
+
+@item gnus-group-sort-by-method
+@findex gnus-group-sort-by-method
+\e$BA*BrJ}K!$N%"%k%U%!%Y%C%H=g$GJB$YBX$($^$9!#\e(B
+
+@item gnus-group-sort-by-server
+@findex gnus-group-sort-by-server
+\e$B%5!<%P!<L>$N%"%k%U%!%Y%C%H=g$GJB$YBX$($^$9!#\e(B
+@end table
+
+@code{gnus-group-sort-function} \e$B$OJB$YBX$(4X?t$N%j%9%H$G$"$C$F$b9=$$$^$;\e(B
+\e$B$s!#$3$N>l9g!"$b$C$H$b=EMW$JJB$YBX$($N80$r;}$D4X?t$O:G8e$G$J$/$F$O$J$j$^\e(B
+\e$B$;$s!#\e(B
+
+\e$B$"$k<o$NJB$YBX$(MQ$K$O!"D>@\JB$YBX$($kL?Na$b$$$/$D$+$"$j$^$9!#\e(B
+
+@table @kbd
+@item G S a
+@kindex G S a (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-alphabet
+\e$B%0%k!<%W%P%C%U%!$r%0%k!<%WL>$N%"%k%U%!%Y%C%H=g$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-alphabet})\e$B!#\e(B
+
+@item G S u
+@kindex G S u (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-unread
+\e$B%0%k!<%W%P%C%U%!$rL$FI5-;v$N?t$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-unread})\e$B!#\e(B
+
+@item G S l
+@kindex G S l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-level
+\e$B%0%k!<%W%P%C%U%!$r%0%k!<%W%l%Y%k$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-level})\e$B!#\e(B
+
+@item G S v
+@kindex G S v (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-score
+\e$B%0%k!<%W%P%C%U%!$r%0%k!<%W$N%9%3%"$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-score})\e$B!#\e(B@xref{Group Score}.
+
+@item G S r
+@kindex G S r (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-rank
+\e$B%0%k!<%W%P%C%U%!$r%0%k!<%W$N%i%s%/$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-rank})\e$B!#\e(B@xref{Group Score}.
+
+@item G S m
+@kindex G S m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-method
+\e$B%0%k!<%W%P%C%U%!$r%P%C%/%(%s%I$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-groups-by-method})\e$B!#\e(B
+
+@item G S n
+@kindex G S n (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-groups-by-real-name
+\e$B%0%k!<%W%P%C%U%!$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C\e(B
+\e$B%H=g$KJB$YBX$($^$9\e(B (@code{gnus-group-sort-groups-by-real-name})\e$B!#\e(B
+@end table
+
+\e$B0J2<$NA4$F$NL?Na$O%W%m%;%9\e(B/\e$B@\F,<-$N=,47$K=>$$$^\e(B
+\e$B$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+\e$B%7%s%\%k@\F,<-\e(B (@pxref{Symbolic Prefixes}) \e$B$,M?$($i$l$?$H$-$O!"$3$l$iA4\e(B
+\e$B$F$NL?Na$O5U=g$GJB$S49$($^$9!#\e(B
+
+\e$B$^$?!"%0%k!<%W$N0lIt$rJB$YBX$($k$3$H$b$G$-$^$9!#\e(B
+
+@table @kbd
+@item G P a
+@kindex G P a (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-alphabet
+\e$B%0%k!<%W$r%0%k!<%WL>$N%"%k%U%!%Y%C%H=g$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-alphabet})\e$B!#\e(B
+
+@item G P u
+@kindex G P u (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-unread
+\e$B%0%k!<%W$rL$FI5-;v$N?t$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-unread})\e$B!#\e(B
+
+@item G P l
+@kindex G P l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-level
+\e$B%0%k!<%W$r%0%k!<%W%l%Y%k$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-level})\e$B!#\e(B
+
+@item G P v
+@kindex G P v (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-score
+\e$B%0%k!<%W$r%0%k!<%W$N%9%3%"$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-score})\e$B!#\e(B
+@xref{Group Score}.
+
+@item G P r
+@kindex G P r (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-rank
+\e$B%0%k!<%W$r%0%k!<%W$N%i%s%/$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-rank})\e$B!#\e(B@xref{Group Score}.
+
+@item G P m
+@kindex G P m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-method
+\e$B%0%k!<%W$r%P%C%/%(%s%I$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-group-sort-selected-groups-by-method})\e$B!#\e(B
+
+@item G P n
+@kindex G P n (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups-by-real-name
+\e$B%0%k!<%W$rK\Ev$N\e(B (\e$BA0$K2?$bIU$$$F$$$J$$\e(B) \e$B%0%k!<%WL>$G%"%k%U%!%Y%C%H=g$KJB\e(B
+\e$B$YBX$($^$9\e(B (@code{gnus-group-sort-selected-groups-by-real-name})\e$B!#\e(B
+
+@item G P s
+@kindex G P s (\e$B%0%k!<%W\e(B)
+@findex gnus-group-sort-selected-groups
+\e$B%0%k!<%W$r\e(B @code{gnus-group-sort-function} \e$B$K=>$C$FJB$YBX$($^$9!#\e(B
+@end table
+
+\e$B:G8e$K!"\e(B@kbd{C-k} \e$B$H\e(B @kbd{C-y} \e$B$r;H$C$F!"<jF0$G%0%k!<%W$r$"$A$3$A$K0\F0\e(B
+\e$B$G$-$k$3$H$b$*K:$l$J$/!#\e(B
+
+@node Group Maintenance
+@section \e$B%0%k!<%W$N4IM}\e(B
+@cindex bogus groups
+
+@table @kbd
+@item b
+@kindex b (\e$B%0%k!<%W\e(B)
+@findex gnus-group-check-bogus-groups
+\e$BIT@5$J%0%k!<%W$r8+$D$1$F!":o=|$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-check-bogus-groups})\e$B!#\e(B
+
+@item F
+@kindex F (\e$B%0%k!<%W\e(B)
+@findex gnus-group-find-new-groups
+\e$B?7$7$$%0%k!<%W$r8+$D$1$F!"$=$l$i$r=hM}$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-find-new-groups})\e$B!#0l2s$N\e(B @kbd{C-u} \e$B$N8e$G2!$5$l$k\e(B
+\e$B$H!"%5!<%P!<$K?7$7$$%0%k!<%W$r?R$M$k$?$a$KJ}K!\e(B @code{ask-server} \e$B$r;H$$\e(B
+\e$B$^$9!#Fs2s$N\e(B @kbd{C-u} \e$B$N8e$G2!$5$l$k$H!"%5!<%P!<$K?7$7$$%0%k!<%W$r?R$M\e(B
+\e$B$k$?$a$K:G$b40A4$G$"$k$H;W$o$l$kJ}K!$rMQ$$!"?7$7$$%0%k!<%W$r%>%s%S$H$7$F\e(B
+\e$B9XFI$7$^$9!#\e(B
+
+@item C-c C-x
+@kindex C-c C-x (\e$B%0%k!<%W\e(B)
+@findex gnus-group-expire-articles
+\e$B8=:_$N%0%k!<%W$N%(%/%9%Q%$%"5-;v$KBP$7$F\e(B (\e$B$b$7$"$l$P\e(B) \e$BA4$F%(%/%9%Q%$%"=h\e(B
+\e$BM}$r9T$$$^$9\e(B (@code{gnus-group-expire-articles})\e$B!#$3$l$O!"$=$N%0%k!<%W$K\e(B
+\e$B$7$P$i$/B8:_$7$F$$$?4|8B@Z$l:o=|2DG=$J$9$Y$F$N5-;v$r>C5n$9$k$H$$$&$3$H$G\e(B
+\e$B$9!#\e(B(@pxref{Expiring Mail})\e$B!#\e(B
+
+@item C-c C-M-x
+@kindex C-c C-M-x (\e$B%0%k!<%W\e(B)
+@findex gnus-group-expire-all-groups
+\e$BA4$F$N%0%k!<%W$NA4$F$N4|8B@Z$l:o=|2DG=$J5-;v$KBP$7$F!"%(%/%9%Q%$%"=hM}$r\e(B
+\e$B9T$$$^$9!#\e(B(@code{gnus-group-expire-all-groups})\e$B!#\e(B
+@end table
+
+@node Browse Foreign Server
+@section \e$B30It%5!<%P$N1\Mw\e(B
+@cindex foreign servers
+@cindex browsing servers
+
+@table @kbd
+@item B
+@kindex B (\e$B%0%k!<%W\e(B)
+@findex gnus-group-browse-foreign-server
+\e$BA*BrJ}K!$H%5!<%PL>$rJ9$+$l$^$9!#\e(BGnus \e$B$O$3$N%5!<%P$K@\B3$7!"$=$3$K$"$k\e(B
+\e$B%0%k!<%W$r1\Mw$7$h$&$H$7$^$9\e(B (@code{gnus-group-browse-foreign-server})\e$B!#\e(B
+@end table
+
+@findex gnus-browse-mode
+\e$BMxMQ2DG=$J%0%k!<%W$N%j%9%H$r;}$C$??7$7$$%P%C%U%!$,8=$l$^$9!#$3$N%P%C%U%!\e(B
+\e$B$O\e(B @code{gnus-browse-mode} \e$B$r;HMQ$7$^$9!#$3$N%P%C%U%!$ODL>o$N%0%k!<%W%P%C\e(B
+\e$B%U%!$K$A$g$C$H\e(B (\e$B$H$$$&$+!"$H$C$F$b\e(B) \e$B;w$F$$$^$9!#\e(B
+
+\e$B0J2<$,1\Mw%b!<%I\e(B (browse mode) \e$B$G;HMQ$G$-$k%-!<A`:n$N%j%9%H$G$9\e(B:
+
+@table @kbd
+@item n
+@kindex n (\e$B1\Mw\e(B)
+@findex gnus-group-next-group
+\e$B<!$N%0%k!<%W$K0\F0$7$^$9\e(B (@code{gnus-group-next-group})\e$B!#\e(B
+
+@item p
+@kindex p (\e$B1\Mw\e(B)
+@findex gnus-group-prev-group
+\e$B0l$DA0$N%0%k!<%W$K0\F0$7$^$9\e(B (@code{gnus-group-prev-group})\e$B!#\e(B
+
+@item SPACE
+@kindex SPACE (\e$B1\Mw\e(B)
+@findex gnus-browse-read-group
+\e$B8=:_$N%0%k!<%W$KF~$j!":G=i$K5-;v$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-browse-read-group})\e$B!#\e(B
+
+@item RET
+@kindex RET (\e$B1\Mw\e(B)
+@findex gnus-browse-select-group
+\e$B8=:_$N%0%k!<%W$KF~$j$^$9\e(B (@code{gnus-browse-select-group})\e$B!#\e(B
+
+@item u
+@kindex u (\e$B1\Mw\e(B)
+@findex gnus-browse-unsubscribe-current-group
+\e$B8=:_$N%0%k!<%W$rHs9XFI$K$9$k!"$D$^$j$3$N>l9g$O9XFI$9$k$3$H$K$J$k$N$@$1$l\e(B
+\e$B$I\e(B (@code{gnus-browse-unsubscribe-current-group})\e$B!#\e(B
+
+@item l
+@itemx q
+@kindex q (\e$B1\Mw\e(B)
+@kindex l (\e$B1\Mw\e(B)
+@findex gnus-browse-exit
+\e$B1\Mw%b!<%I\e(B (browse mode) \e$B$r=*N;$7$^$9\e(B (@code{gnus-browse-exit})\e$B!#\e(B
+
+@item d
+@kindex d (\e$B1\Mw\e(B)
+@findex gnus-browse-describe-group
+\e$B8=:_$N%0%k!<%W$r9XFI$K$7$^$9\e(B (@code{gnus-browse-describe-group})\e$B!#\e(B
+
+@item ?
+@kindex ? (\e$B1\Mw\e(B)
+@findex gnus-browse-describe-briefly
+\e$B1\Mw%b!<%I\e(B (browse mode) \e$B$r4JC1$K@bL@$7$^$9\e(B (\e$B$^$"!"Bg$7$F@bL@$9$k$3$H$b\e(B
+\e$B$J$$$s$@$1$I$5\e(B) (@code{gnus-browse-describe-briefly})\e$B!#\e(B
+@end table
+
+@node Exiting gnus
+@section Gnus \e$B$N=*N;\e(B
+@cindex exiting gnus
+
+\e$B$=$&!"\e(Bgnus \e$B$O:G8e\e(B (\e$B%5%$%3!<\e(B) \e$B$G$9\e(B (\e$BLuCm\e(B: \e$B$/!"6l$7$$!#\e(B
+\e$B86J8$O\e(B ``Yes, gnus is ex(c)iting.'')\e$B!#\e(B
+
+@table @kbd
+@item z
+@kindex z (\e$B%0%k!<%W\e(B)
+@findex gnus-group-suspend
+Gnus \e$B$rCfCG$7$^$9\e(B (@code{gnus-group-suspend})\e$B!#$3$l$O\e(B gnus \e$B$r<B:]$K$O=*\e(B
+\e$BN;$5$;$:!"%0%k!<%W%P%C%U%!0J30$NA4$F$N%P%C%U%!$r>C$9$@$1$G$9!#KM$O$3$l$N\e(B
+\e$B$&$l$7$5$,$h$/$o$+$s$J$$$s$@$1$I!"C/$+J,$+$k?M$$$k\e(B?
+
+@item q
+@kindex q (\e$B%0%k!<%W\e(B)
+@findex gnus-group-exit
+@c @icon{gnus-group-exit}
+Gnus \e$B$r=*N;$7$^$9\e(B(@code{gnus-group-exit})\e$B!#\e(B
+
+@item Q
+@kindex Q (\e$B%0%k!<%W\e(B)
+@findex gnus-group-quit
+@file{.newsrc} \e$B%U%!%$%k$r%;!<%V$;$:$K\e(B gnus \e$B$r=*N;$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-quit})\e$B!#%I%j%V%k%U%!%$%k$O%;!<%V$5$l$^$9$1\e(B
+\e$B$I\e(B (@pxref{Auto Save})\e$B!#\e(B
+@end table
+
+@vindex gnus-exit-gnus-hook
+@vindex gnus-suspend-gnus-hook
+@vindex gnus-after-exiting-gnus-hook
+Gnus \e$B$rCfCG$9$k$H$-$O\e(B @code{gnus-suspend-gnus-hook} \e$B$,8F$S=P$5$l$^$9!#\e(B
+Gnus\e$B$r=*N;$9$k$H$-$O\e(B @code{gnus-exit-gnus-hook} \e$B$,8F$S=P$5$l!"$5$i\e(B
+\e$B$K\e(B gnus \e$B$r=*N;$9$k$H$-$N:G8e$H$7\e(B
+\e$B$F\e(B @code{gnus-after-exiting-gnus-hook} \e$B$,8F$S=P$5$l$^$9!#\e(B
+
+Note:
+
+@quotation
+\e$B%_%9\e(B Lisa Cannifax \e$B$O1Q8l$N<x6HCf!"8e$m$K:B$C$F$$$k>/G/$,H`=w$N%W%i%9%F%#%C\e(B
+\e$B%/$N0X;R$NGX1[$7$K!"1tI.$G7+$jJV$7@~$rIA$/$N$K$D$i$l$F!"B-$,$7$S$l$F=E$/\e(B
+\e$B$J$j!"0U<1$,[/[0$H$7$F$-$^$7$?!#\e(B
+@end quotation
+
+@node Group Topics
+@section Group Topics
+@cindex topics
+
+\e$B$b$7$"$J$?$,$?!<$/$5$s$N%0%k!<%W$rFI$s$G$$$k$N$G$"$l$P!"%0%k!<%W$r%H%T%C\e(B
+\e$B%/Kh$K3,AXJ,$1$G$-$k$HJXMx$G$7$g$&!#\e(BEmacs \e$B$N%0%k!<%W$r$3$C$A$X!"%;%C%/%9\e(B
+\e$B$N%0%k!<%W$r$"$C$A$X!"$G!";D$j$r\e(B (\e$B$(\e(B? \e$B%0%k!<%W$,Fs$D$/$i$$$7$+$J$$\e(B
+\e$B$N\e(B?) \e$B<YKb$K$J$i$J$$$h$&$K$=$NB>$N%;%/%7%g%s$KF~$l$^$7$g$&!#$"$k$$\e(B
+\e$B$O\e(B Emacs \e$B%;%C%/%9$N%0%k!<%W$r\e(B Emacs \e$B%0%k!<%W!"%;%C%/%9%0%k!<%W$N$I$A$i$+\e(B
+\e$B$NI{%H%T%C%/$H$9$k$3$H$5$($b$G$-$^$9!=!=$"$k$$$ON>J}$K\e(B! \e$B$9$s$4$$$G$7$g$&\e(B!
+
+@iftex
+@iflatex
+\gnusfigure{Group Topics}{400}{
+\put(75,50){\epsfig{figure=ps/group-topic,height=9cm}}
+}
+@end iflatex
+@end iftex
+
+\e$B$3$l$,Nc$G$9\e(B:
+
+@example
+Gnus
+  Emacs -- \e$B$3$$$D$O$9$2!<$<\e(B!
+     3: comp.emacs
+     2: alt.religion.emacs
+    \e$B$($C$A$J\e(B Emacs
+     452: alt.sex.emacs
+       0: comp.talk.emacs.recovery
+  \e$B$=$NB>\e(B
+     8: comp.binaries.fractals
+    13: comp.sources.unix
+@end example
+
+@findex gnus-topic-mode
+@kindex t (\e$B%0%k!<%W\e(B)
+\e$B$3$N\e(B@emph{\e$BAG@2$i$7$$\e(B}\e$B5!G=$r;H$&$K$O!"\e(B@code{gnus-topic} \e$B%^%$%J!<%b!<%I\e(B
+\e$B$r\e(B (\e$B2?$H\e(B!) \e$BC1$K%9%$%C%A%*%s$9$k$@$1!=!=%0%k!<%W%P%C%U%!$G!"\e(B@kbd{t} \e$B$r2!\e(B
+\e$B$7$F$/$@$5$$\e(B (\e$B$3$l$O%H%0%k%3%^%s%I$G$9\e(B)\e$B!#\e(B
+
+\e$B$5$"$d$C$F$_$h$&!#$H$K$+$/;n$7$F$_$F!#7/$,La$C$F$/$k$^$G!"KM$O$3$3$GBT$C\e(B
+\e$B$F$k$+$i$5!#%i%i!"%?%i%i%s\e(B@dots{}\e$B!"$$$$6J$@$M!"$3$l\e(B@dots{}\e$B%i!"%i!"\e(B
+\e$B%i\e(B@dots{}\e$B$(\e(B? \e$BLa$C$F$-$?\e(B? \e$B$h$7!"$8$c<!$O\e(B @kbd{l} \e$B$r2!$7$F$_$F!#$[$i!#$3$l\e(B
+\e$B$GA4$F$N%0%k!<%W$,\e(B @samp{misc} \e$B$N2<$KI=<($5$l$^$7$?!#6=J3$7$F%/%i%/%i$7\e(B
+\e$B$F$3$J$$\e(B? \e$B%"%D$/$C$F!"$$$^$$$^$7$$$/$i$$$G$7$g\e(B?
+
+\e$B$3$l$r$:$C$HM-8z$K$7$?$1$l$P!"%0%k!<%W%b!<%I$N%U%C%/$K$3$N%^%$%J!<%b!<%I\e(B
+\e$B$rDI2C$7$F$/$@$5$$!#0J2<$N9T$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$F!"$M!#\e(B
+
+@lisp
+(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
+@end lisp
+
+@menu
+* Topic Commands::              \e$BD64JC1BPOC7?L?Na\e(B
+* Topic Variables::             Lisp \e$B$G%H%T%C%/$r%+%9%?%^%$%:$9$kJ}K!\e(B
+* Topic Sorting::               \e$B%H%T%C%/KhJL!9$KJB$YBX$($k\e(B
+* Topic Topology::              \e$BA4@$3&$NCO?^\e(B
+* Topic Parameters::            \e$B$"$k%H%T%C%/$NA4$F$N%0%k!<%W$KE,MQ$5$l$k%Q%i%a!<%?\e(B
+@end menu
+
+@node Topic Commands
+@subsection \e$B%H%T%C%/L?Na\e(B
+@cindex topic commands
+
+\e$B%H%T%C%/%^%$%J!<%b!<%I$,M-8z$G$"$k$H$-$O!"\e(B@kbd{T} \e$B%5%V%^%C%W$,?7$7$/MxMQ\e(B
+\e$B$G$-$k$h$&$K$J$j$^$9!#$5$i$KI8=`%-!<$NCf$G$b!"Dj5A$,$A$g$C$HJQ$o$k$b$N$,\e(B
+\e$B>/$7$"$j$^$9!#\e(B
+
+\e$B$@$$$?$$$K$*$$$F!"<!$N$h$&$J%H%T%C%/$NA`:n$,2DG=$G$9!#$^$:Bh0l$K!"$"$J$?\e(B
+\e$B$O%H%T%C%/$r:n$k$3$H$rK>$`$G$7$g$&!#BhFs$K!"$"$J$?$O%0%k!<%W$r%H%T%C%/$K\e(B
+\e$BF~$l$F!"$=$l$i$r$"$J$?$N9%$_$N=g=x$K$J$k$^$G!"$"$A$3$A$K0\F0$9$k$3$H$rK>\e(B
+\e$B$`$G$7$g$&!#Bh;0$K9T$J$&A`:n$O!"$=$l$i$N0l@Z9g@Z$rI=<($7$?$j1#$9$3$H$G$7$g\e(B
+\e$B$&!#B>$N%0%k!<%W$N35MW$r8+$d$9$/$9$k$?$a$K!"$"$J$?$OI{%H%T%C%/$d%0%k!<%W\e(B
+\e$B$K$h$C$F$O!"%H%T%C%/$,1#$l$k$h$&$K$7$?$$$H;W$&$+$b$7$l$^$;$s$M!#\e(B
+
+\e$B$3$3$K$O!"$"$J$?$N9%$`$d$jJ}$G%H%T%C%/$r@_Dj$9$k$?$a$KI,MW$K$J$j$=$&$J!"\e(B
+\e$B4pK\E*$J%-!<$N%j%9%H$,$"$j$^$9!#\e(B
+
+@table @kbd
+@item T n
+@kindex T n (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-create-topic
+\e$B?7$7$$%H%T%C%/L>$NF~NO$rB%$7!"$=$l$r:n@.$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-create-topic})\e$B!#\e(B
+
+@item T TAB
+@itemx TAB
+@kindex T TAB (\e$B%H%T%C%/\e(B)
+@kindex TAB (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-indent
+\e$B8=:_$N%H%T%C%/$N\e(B ``\e$B;z2<$2\e(B'' \e$B$r9T$$!"$=$NA0$N%H%T%C%/$NI{%H%T%C%/$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-indent})\e$B!#@\F,0z?t$rM?$($k$H!"H?BP$K$=$N%H%T%C%/$N\e(B
+\e$B;z2<$2$r2sI|\e(B (un-indent) \e$B$7$^$9!#\e(B
+
+@item M-TAB
+@kindex M-TAB (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-unindent
+\e$B8=:_$N%H%T%C%/$N\e(B ``\e$B;z2<$22sI|\e(B'' (un-indent) \e$B$r9T$$!"$=$l$,8=:_$N?F$N?F$N\e(B
+\e$BI{%H%T%C%/$K$J$k$h$&$K$7$^$9\e(B (@code{gnus-topic-unindent})\e$B!#\e(B
+@end table
+
+\e$B0J2<$NFs$D$N%-!<$O!"%0%k!<%W$H%H%T%C%/$r$"$A$3$A0\F0$9$k$?$a$K;H$o$l$^$9!#\e(B
+\e$B$=$l$i$O!"$h$/CN$i$l$F$$$k%+%C%H!u%Z!<%9%H$N$h$&$KF0:n$7$^$9!#\e(B
+@kbd{C-k} \e$B$O%+%C%H!"\e(B@kbd{C-y} \e$B$O%Z!<%9%H$G$9!#$b$A$m$s!"\e(BEmacs \e$B$G$O%+%C%H\e(B
+\e$B!u%Z!<%9%H$G$O$J$/$F\e(B kill & yank \e$B$H$$$&MQ8l$r;H$$$^$9$,!#\e(B
+
+@table @kbd
+@item C-k
+@kindex C-k (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-kill-group
+\e$B%0%k!<%W$"$k$$$O%H%T%C%/$r\e(B kill \e$B$7$^$9\e(B (@code{gnus-topic-kill-group})\e$B!#\e(B
+\e$B%H%T%C%/Fb$K$"$C$?%0%k!<%W$bA4$F!"%H%T%C%/$H0l=o$K:o=|$5$l$^$9!#\e(B
+
+@item C-y
+@kindex C-y (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-yank-group
+\e$BD>A0$N\e(B kill \e$B$5$l$?%0%k!<%W$"$k$$$O%H%T%C%/$r\e(B yank \e$B$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-yank-group})\e$B!#A4$F$N%H%T%C%/$O!"A4$F$N%0%k!<%W$NA0\e(B
+\e$B$K\e(B yank \e$B$5$l$k$3$H$K5$$r$D$1$F$/$@$5$$!#\e(B
+
+\e$B$G$9$+$i!"$"$k%H%T%C%/$r%H%T%C%/$N%j%9%H$N@hF,$K0\F0$9$k$K$O!"C1$K$=$3\e(B
+\e$B$G\e(B @kbd{C-k} \e$B$rC!$-$^$9!#$3$l$O%+%C%H!u%Z!<%9%H$N%+%C%H$KAjEv$7$^$9!#$=\e(B
+\e$B$&$7$?$i%+!<%=%k$r%P%C%U%!$N@hF,\e(B (``Gnus'' \e$B%H%T%C%/$N??2<\e(B) \e$B$K0\F0$7$F!"\e(B
+@kbd{C-y} \e$B$rC!$$$F2<$5$$!#$3$l$O%+%C%H!u%Z!<%9%H$N%Z!<%9%H$KAjEv$7$^$9!#\e(B
+\e$B$J$"$s$@!"4JC1$8$c$s!#\e(B
+
+@kbd{C-k} \e$B$H\e(B @kbd{C-y} \e$B$O%H%T%C%/$HF1MM$K%0%k!<%W$K$b;H$($^$9!#$9$J$o$A!"\e(B
+\e$B$"$J$?$O%0%k!<%W$HF1$8$h$&$K%H%T%C%/$N0\F0$b$G$-$k$N$G$9!#\e(B
+@end table
+
+\e$B$"$J$?$NK>$_$N$^$^$K%H%T%C%/$r;H$($k$h$&$K$7$?8e$G!"$"$J$?$O%H%T%C%/$r1#\e(B
+\e$B$7$?$j:F$S8+$($k$h$&$K$7$h$&$H;W$&$G$7$g$&!#$=$N$?$a$K0J2<$N%-!<$rMQ0U$7\e(B
+\e$B$F$$$^$9!#\e(B
+
+@table @kbd
+@item RET
+@kindex RET (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-select-group
+@itemx SPACE
+\e$B%0%k!<%W$rA*Br$9$k$+!"$"$k$$$O%H%T%C%/$r@^$j$?$?$_$^\e(B
+\e$B$9\e(B (@code{gnus-topic-select-group})\e$B!#%0%k!<%W$N>e$G$3$N%3%^%s%I$r<B9T$9\e(B
+\e$B$k$H!"DL>oDL$j$=$N%0%k!<%W$KF~$j$^$9!#%H%T%C%/9T$N>e$G9T$&$H!"$=$N%H%T%C\e(B
+\e$B%/$O\e(B (\e$B4{$KI=<($5$l$F$$$k$H$-$O\e(B) \e$B@^$j$?$?$^$l$k$+!"\e(B(\e$B4{$K@^$j$?$?$^$l$F$$\e(B
+\e$B$k$H$-$O\e(B) \e$BE83+$5$l$^$9!#$D$^$j%H%T%C%/$KBP$7$F$O$3$l$O%H%0%k%3%^%s%I$G$9!#\e(B
+\e$B$5$i$K!"?t;z%W%l%U%#%C%/%9$rM?$($k$H!"$=$N%l%Y%k\e(B (\e$B$H$=$l$h$j$b>.$5$$%l%Y\e(B
+\e$B%k\e(B) \e$B$N%0%k!<%W$,I=<($5$l$^$9!#\e(B
+@end table
+
+\e$B$5$F$*<!$O!"B>$N%3%^%s%I$N%j%9%H$G$9!#=g=x$K$OFC$K0UL#$O$"$j$^$;$s!#\e(B
+
+@table @kbd
+@item T m
+@kindex T m (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-move-group
+\e$B8=:_$N%0%k!<%W$r!"$I$3$+B>$N%H%T%C%/$K0\F0$5$;$^\e(B
+\e$B$9\e(B (@code{gnus-topic-move-group})\e$B!#$3$N%3%^%s%I$O%W%m%;%90u\e(B/\e$B@\F,0z?t$N=,\e(B
+\e$B47$K=>$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item T j
+@kindex T j (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-jump-to-topic
+\e$B%H%T%C%/$K%8%c%s%W$7$^$9\e(B (@code{gnus-topic-jump-to-topic})\e$B!#\e(B
+
+@item T c
+@kindex T c (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-copy-group
+\e$B8=:_$N%0%k!<%W$r!"$I$3$+B>$N%H%T%C%/$K%3%T!<$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-copy-group})\e$B!#$3$N%3%^%s%I$O%W%m%;%90u\e(B/\e$B@\F,0z?t$N=,\e(B
+\e$B47$K=>$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item T h
+@kindex T h (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-hide-topic
+\e$B8=:_$N%H%T%C%/$r1#$7$^$9!#$b$7%W%l%U%#%C%/%9$,M?$($i$l$?$J$i!"$=$N%H%T%C\e(B
+\e$B%/$r1J5W$K1#$7$^$9!#\e(B
+
+@item T s
+@kindex T s (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-show-topic
+\e$B8=:_$N%H%T%C%/$rI=<($7$^$9!#$b$7%W%l%U%#%C%/%9$,M?$($i$l$?$J$i!"$=$N%H%T%C\e(B
+\e$B%/$r1J5W$KI=<($7$^$9!#\e(B
+
+@item T D
+@kindex T D (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-remove-group
+\e$B%0%k!<%W$r8=:_$N%H%T%C%/$+$i:o=|$7$^$9\e(B (@code{gnus-topic-remove-group})\e$B!#\e(B
+\e$B$3$NL?Na$O<g$K$$$/$D$+$N%H%T%C%/$KF1$8%0%k!<%W$,$"$C$F!"$=$l$r%H%T%C%/$N\e(B
+\e$B0l$D$+$i<h$j=|$-$?$$$H$-$KLrN)$A$^$9!#$"$J$?$O%0%k!<%W$rA4$F$N%H%T%C%/$+\e(B
+\e$B$i<h$j=|$-$?$$$H;W$&$+$bCN$l$^$;$s$,!"$=$N>l9g$O!"\e(Bgnus \e$B$O$"$J$?$,<!2s\e(B
+\e$B$K\e(B gnus \e$B$r5/F0$7$?$H$-$K$=$l$r%k!<%H%H%T%C%/$KIU$12C$($^$9!#<B:]$N$H$3$m!"\e(B
+\e$BA4$F$N?7$7$$%0%k!<%W\e(B (\e$B$b$A$m$s!"$=$l$O$I$N%H%T%C%/$K$bB0$7$F$$$^$;$s\e(B) \e$B$O\e(B
+\e$B%k!<%H%H%T%C%/$K8=$o$l$^$9!#\e(B
+
+\e$B$3$NL?Na$O%W%m%;%90u\e(B/\e$B@\F,0z?t$N=,47$K=>$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item T M
+@kindex T M (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-move-matching
+\e$B@55,I=8=$K%^%C%A$9$kA4$F$N%0%k!<%W$r!"$"$k%H%T%C%/$K0\F0$5$;$^\e(B
+\e$B$9\e(B (@code{gnus-topic-move-matching})\e$B!#\e(B
+
+@item T C
+@kindex T C (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-copy-matching
+\e$B@55,I=8=$K%^%C%A$9$kA4$F$N%0%k!<%W$r!"$"$k%H%T%C%/$K%3%T!<$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-copy-matching})\e$B!#\e(B
+
+@item T H
+@kindex T H (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-toggle-display-empty-topics
+\e$B6u$N%H%T%C%/$NI=<(!&HsI=<($r@Z$jBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-toggle-display-empty-topics})\e$B!#\e(B
+
+@item T #
+@kindex T # (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-mark-topic
+\e$B8=:_$N%H%T%C%/$K$"$k%0%k!<%WA4$F$K%W%m%;%9%^!<%/$r$D$1$^\e(B
+\e$B$9\e(B (@code{gnus-topic-mark-topic})\e$B!#@\F,<-$,M?$($i$l$J$$>l9g!"$3$N%3%^%s\e(B
+\e$B%I$OI{%H%T%C%/$KBP$7$F:F5"E*$KF/$-$^$9!#\e(B
+
+@item T M-#
+@kindex T M-# (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-unmark-topic
+\e$B8=:_$N%H%T%C%/$K$"$kA4$F$N%0%k!<%W$+$i%W%m%;%9%^!<%/$r>C$7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-unmark-topic})\e$B!#@\F,<-$,M?$($i$l$J$$>l9g!"$3$N%3%^\e(B
+\e$B%s%I$OI{%H%T%C%/$KBP$7$F:F5"E*$KF/$-$^$9!#\e(B
+
+@item C-c C-x
+@kindex C-c C-x (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-expire-articles
+(\e$B$b$7$"$l$P\e(B) \e$B8=:_$N%0%k!<%W$+%H%T%C%/$+$NA4$F$N;~8B>C5n2DG=5-;v$r;~8B>C\e(B
+\e$B5n$7$^$9\e(B (@code{gnus-topic-expire-articles})\e$B!#\e(B(@pxref{Expiring Mail})\e$B!#\e(B
+
+@item T r
+@kindex T r (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-rename
+\e$B%H%T%C%/$NL>A0$rJQ99$7$^$9\e(B (@code{gnus-topic-rename})\e$B!#\e(B
+
+@item T DEL
+@kindex T DEL (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-delete
+\e$B6u$N%H%T%C%/$r:o=|$7$^$9\e(B (@code{gnus-topic-delete})\e$B!#\e(B
+
+@item A T
+@kindex A T (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-list-active
+Gnus \e$B$,CN$C$F$$$k%H%T%C%/2=$5$l$?%0%k!<%W$rA4$FI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-topic-list-active})\e$B!#\e(B
+
+@item T M-n
+@kindex T M-n (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-goto-next-topic
+\e$B<!$N%H%T%C%/$K0\F0$7$^$9\e(B (@code{gnus-topic-goto-next-topic})\e$B!#\e(B
+
+@item T M-p
+@kindex T M-p (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-goto-previous-topic
+\e$BA0$N%H%T%C%/$K0\F0$7$^$9\e(B (@code{gnus-topic-goto-previous-topic})\e$B!#\e(B
+
+@item G p
+@kindex G p (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-edit-parameters
+@cindex group parameters
+@cindex topic parameters
+@cindex parameters
+\e$B%H%T%C%/%Q%i%a!<%?$r=$@5$7$^$9\e(B (@code{gnus-topic-edit-parameters})\e$B!#\e(B
+@xref{Topic Parameters}.
+@end table
+
+@node Topic Variables
+@subsection \e$B%H%T%C%/JQ?t\e(B
+@cindex topic variables
+
+\e$BA0$N9`$G$O!"$I$N%H%T%C%/$rI=<($9$k$+$r\e(B gnus \e$B$K8@$&J}K!$r@bL@$7$^$7$?!#\e(B
+\e$B$3$N9`$G$O!"$=$l$>$l$N%H%T%C%/$N2?$rI=<($9$k$+$r\e(Bgnus \e$B$K8@$&J}K!$r@bL@$7\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-topic-line-format
+\e$B%H%T%C%/9T$=$l<+BN$O!"\e(B@code{gnus-topic-line-format} \e$BJQ?t$NCM$K=>$C$F:n@.\e(B
+\e$B$5$l$^$9\e(B (@pxref{Formatting Variables})\e$B!#M-8z$JMWAG$O!"\e(B
+
+@table @samp
+@item i
+\e$B;z2<$2!#\e(B
+@item n
+\e$B%H%T%C%/L>!#\e(B
+@item v
+\e$B8+$($k$+$I$&$+!#\e(B
+@item l
+\e$B%l%Y%k!#\e(B
+@item g
+\e$B%H%T%C%/Cf$N%0%k!<%W$N?t!#\e(B
+@item a
+\e$B%H%T%C%/Cf$NL$FI5-;v$N?t!#\e(B
+@item A
+\e$B%H%T%C%/$HA4$F$NI{%H%T%C%/$NL$FI5-;v$N?t!#\e(B
+@end table
+
+@vindex gnus-topic-indent-level
+\e$B3FI{%H%T%C%/\e(B (\e$B$HI{%H%T%C%/Fb$N%0%k!<%W\e(B) \e$B$O!"%H%T%C%/%l%Y%k?t\e(B
+\e$B$N\e(B @code{gnus-topic-indent-level} \e$BG\$N6uGrJ,$N;z2<$2$,9T$o$l$^$9!#=i4|CM\e(B
+\e$B$O\e(B 2 \e$B$G$9!#\e(B
+
+@vindex gnus-topic-mode-hook
+@code{gnus-topic-mode-hook} \e$B$O%H%T%C%/%^%$%J!<%b!<%I%P%C%U%!$G8F$S=P$5$l\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-topic-display-empty-topics
+@code{gnus-topic-display-empty-topics} \e$B$O%H%T%C%/$NCf$KL$FI5-;v$,L5$$>l\e(B
+\e$B9g$G$b$=$N%H%T%C%/$rI=<($9$k$h$&$K$7$^$9!#=i4|CM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@node Topic Sorting
+@subsection \e$B%H%T%C%/$NJB$YBX$(\e(B
+@cindex topic sorting
+
+\e$B0J2<$K<($9L?Na$G!"3F%H%T%C%/Kh$KJL!9$K%0%k!<%W$rJB$YBX$($k$3$H$,$G$-$^$9\e(B:
+
+@table @kbd
+@item T S a
+@kindex T S a (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-alphabet
+\e$B8=:_$N%H%T%C%/$r%0%k!<%WL>$N%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-alphabet})\e$B!#\e(B
+
+@item T S u
+@kindex T S u (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-unread
+\e$B8=:_$N%H%T%C%/$rL$FI5-;v$N?t$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-unread})\e$B!#\e(B
+
+@item T S l
+@kindex T S l (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-level
+\e$B8=:_$N%H%T%C%/$r%0%k!<%W$N%l%Y%k$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-level})\e$B!#\e(B
+
+@item T S v
+@kindex T S v (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-score
+\e$B8=:_$N%H%T%C%/$r%0%k!<%W$N%9%3%"$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-score})\e$B!#\e(B@xref{Group Score}.
+
+@item T S r
+@kindex T S r (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-rank
+\e$B8=:_$N%H%T%C%/$r%0%k!<%W$N%i%s%/$GJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-rank})\e$B!#\e(B@xref{Group Score}.
+
+@item T S m
+@kindex T S m (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-method
+\e$B8=:_$N%H%T%C%/$r%P%C%/%(%s%I$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-method})\e$B!#\e(B
+
+@item T S e
+@kindex T S e (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups-by-server
+\e$B8=:_$N%H%T%C%/$r%5!<%P!<$NL>A0$G%"%k%U%!%Y%C%H=g$KJB$YBX$($^\e(B
+\e$B$9\e(B (@code{gnus-topic-sort-groups-by-server})\e$B!#\e(B
+
+@item T S s
+@kindex T S s (\e$B%H%T%C%/\e(B)
+@findex gnus-topic-sort-groups
+\e$B8=:_$N%H%T%C%/$r!"JQ?t\e(B @code{gnus-group-sort-function} \e$B$GM?$($i$l$k4X?t\e(B
+\e$B$K=>$C$FJB$YBX$($^$9\e(B (@code{gnus-topic-sort-groups})\e$B!#\e(B
+@end table
+
+\e$B@\F,0z?t$,M?$($i$l$?$i!"$3$l$i$9$Y$F$N%3%^%s%I$O5U=g$NJB$YBX$($r9T$J$$$^\e(B
+\e$B$9!#%0%k!<%W$N%=!<%H$K$D$$$F$N$5$i$J$k>pJs$O\e(B @ref{Sorting Groups} \e$B$r;2>H\e(B
+\e$B$7$F2<$5$$!#\e(B
+
+@node Topic Topology
+@subsection \e$B%H%T%C%/$N0LAj9=B$\e(B
+@cindex topic topology
+@cindex topology
+
+\e$B$=$l$G$O!"%0%k!<%W%P%C%U%!$NNc$r8+$F$$$-$^$7$g$&!#\e(B
+
+@example
+Gnus
+  Emacs -- \e$B$3$$$D$O$9$2!<$<\e(B!
+     3: comp.emacs
+     2: alt.religion.emacs
+    \e$B$($C$A$J\e(B Emacs
+     452: alt.sex.emacs
+       0: comp.talk.emacs.recovery
+  \e$B$=$NB>\e(B
+     8: comp.binaries.fractals
+    13: comp.sources.unix
+@end example
+
+\e$B$D$^$j!"$3$3$G$O0l$D$N%H%C%W%l%Y%k$N%H%T%C%/\e(B (@samp{Gnus}) \e$B$,$"$j!"$=$N\e(B
+\e$B2<$KFs$D$N%H%T%C%/$,$"$j!"$=$N$&$A$N0lJ}$NI{%H%T%C%/Cf$K0l$DI{%H%T%C%/$,\e(B
+\e$B$"$j$^$9\e(B (\e$B%H%C%W%l%Y%k%H%T%C%/$O>o$K0l$D$7$+$"$j$^$;$s\e(B)\e$B!#$3$N9=B$$O!"0J\e(B
+\e$B2<$N$h$&$KI=8=$G$-$^$9\e(B:
+
+@lisp
+(("Gnus" visible)
+ (("Emacs -- \e$B$3$$$D$O$9$2!<$<\e(B!" visible)
+  (("\e$B$($C$A$J\e(B Emacs" visible)))
+ (("\e$B$=$NB>\e(B" visible)))
+@end lisp
+
+@vindex gnus-topic-topology
+\e$B$3$l$O<B$K!">e5-$NI=<($r9T$&$?$a$N!"JQ?t\e(B @code{gnus-topic-topology} \e$B$NCM\e(B
+\e$B$=$N$b$N$J$N$G$9!#$3$NJQ?t$O\e(B @file{.newsrc.eld} \e$B%U%!%$%k$KJ]B8$5$l!"<j$G\e(B
+\e$B$$$8$/$j2s$7$F$O$$$1$^$;$s!=!=K\Ev$K$d$j$?$$$H$-$OJL$G$9$,!#$3$NJQ?t\e(B
+\e$B$O\e(B @file{.newsrc.eld} \e$B%U%!%$%k$+$iFI$_9~$^$l$k$N$G!"$=$NB>$N%9%?!<%H%"%C\e(B
+\e$B%W%U%!%$%k$N@_Dj$K$OA4$/1F6A$rM?$($^$;$s!#\e(B
+
+\e$B$3$N9=B$$O!"$I$N%H%T%C%/$,$I$N%H%T%C%/$NI{%H%T%C%/$G$"$k$+$H!"$I$N%H%T%C\e(B
+\e$B%/$,I=<($5$l$F$$$k$+$r<($7$F$$$^$9!#8=:_$OFs$D$N@_Dj\e(B
+\e$BCM!=!=\e(B@code{visible} \e$B$H\e(B @code{invisible} \e$B$,5v$5$l$F$$$^$9!#\e(B
+
+@node Topic Parameters
+@subsection \e$B%H%T%C%/%Q%i%a!<%?\e(B
+@cindex topic parameters
+
+\e$B%H%T%C%/Fb$NA4$F$N%0%k!<%W$O%0%k!<%W%Q%i%a!<%?$r!"$=$N?F\e(B (\e$B$H@hAD\e(B) \e$B$N%H%T%C\e(B
+\e$B%/%Q%i%a!<%?$+$i7Q>5$7$^$9!#%0%k!<%W%Q%i%a!<%?$H$7$F@5$7$$$b$N$OA4$F!"%H\e(B
+\e$B%T%C%/%Q%i%a!<%?$H$7$F$b@5$7$$$b$N$G$9\e(B(@pxref{Group Parameters})\e$B!#%(!<%8%'\e(B
+\e$B%s%H$r;H$&$h$&$K$7$F$"$k$H!"$9$Y$F$N%(!<%8%'%s%H%Q%i%a!<%?\e(B (@ref{Category
+Syntax} \e$B$N\e(B Agent Parameters \e$B$r;2>H\e(B (\e$BLuCm\e(B: \e$BI,MW$J$i\e(B Index \e$B$r;H$C$F\e(B)) \e$B$OM-\e(B
+\e$B8z$J%H%T%C%/%Q%i%a!<%?$G$b$"$j$^$9!#\e(B
+
+\e$B$5$i$K!"0J2<$N%Q%i%a!<%?$O%H%T%C%/%Q%i%a!<%?$H$7$F$N$_M-8z$G$9\e(B:
+
+@table @code
+@item subscribe
+\e$B%H%T%C%/$G?7$7$$%0%k!<%W$r9XFI$7$F$$$k>l\e(B
+\e$B9g\e(B (@pxref{Subscription Methods})\e$B!"\e(B@code{subscribe} \e$B%H%T%C%/%Q%i%a!<%?$O\e(B
+\e$B$I$N%0%k!<%W$,$I$N%H%T%C%/$K9T$/$+$r;XDj$7$^$9!#CM$O$=$N%H%T%C%/$K9T$/%0\e(B
+\e$B%k!<%W$K9gCW$9$k@55,I=8=$G$"$kI,MW$,$"$j$^$9!#\e(B
+
+@item subscribe-level
+\e$B%H%T%C%/$G?7$7$$%0%k!<%W$r9XFI$7$F$$$k>l\e(B
+\e$B9g\e(B (@code{subscribe} \e$B%Q%i%a!<%?$r;2>H\e(B)\e$B!"$=$N%0%k!<%W$N9XFIEY$N%l%Y%k\e(B
+\e$B$O\e(B @code{gnus-level-default-subscribed} \e$B$NBe$o$j\e(B
+\e$B$K\e(B @code{subscribe-level} \e$B%H%T%C%/%Q%i%a!<%?$NCM$K$J$j$^$9!#\e(B
+@end table
+
+\e$B%0%k!<%W%Q%i%a!<%?$O\e(B (\e$B$b$A$m$s\e(B) \e$B%H%T%C%/%Q%i%a!<%?$h$j$bM%@h$5$l!"I{%H%T%C\e(B
+\e$B%/$N%H%T%C%/%Q%i%a!<%?$O?F%H%T%C%/$N%H%T%C%/%Q%i%a!<%?$h$j$bM%@h$5$l$^$9!#\e(B
+\e$BJ,$+$k$h$M!#$4$/IaDL$N7Q>5%k!<%k$G$9\e(B (\e$B%k!<%k\e(B (@dfn{Rules}) \e$B$O$3$3$G$OL>\e(B
+\e$B;l$G$"$C$F!"F0;l$N!V@~$r0z$/!W$G$O$"$j$^$;$s!#$3$N%k!<%k$K$OH?BP$7$?$/$J\e(B
+\e$B$k$+$bCN$l$J$$$1$I!"$=$l$O$4<+M3$K\e(B)\e$B!#\e(B
+
+@example
+@group
+Gnus
+  Emacs
+     3: comp.emacs
+     2: alt.religion.emacs
+   452: alt.sex.emacs
+    \e$BB)H4$-\e(B
+     452: alt.sex.emacs
+       0: comp.talk.emacs.recovery
+  \e$B$=$NB>\e(B
+     8: comp.binaries.fractals
+    13: comp.sources.unix
+   452: alt.sex.emacs
+@end group
+@end example
+
+@samp{Emacs} \e$B%H%T%C%/$O%H%T%C%/%Q%i%a!<\e(B
+\e$B%?\e(B @code{(score-file . "emacs.SCORE")} \e$B$r;}$C$F$$$^$9!#\e(B
+@samp{\e$BB)H4$-\e(B} \e$B%H%T%C%/$O%H%T%C%/%Q%i%a!<\e(B
+\e$B%?\e(B @code{(score-file . "relief.SCORE")} \e$B$r;}$A!"\e(B
+@samp{\e$B$=$NB>\e(B} \e$B%H%T%C%/$O%H%T%C%/%Q%i%a!<\e(B
+\e$B%?\e(B @code{(score-file . "emacs.SCORE")} \e$B$r;}$C$F$$$^$9!#\e(B
+\e$B$5$i$K!"\e(B@samp{alt.religion.emacs} \e$B$O%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B @code{(score-file . "religion.SCORE")} \e$B$r;}$C$F$$$^$9!#\e(B
+
+\e$B$5$F!"$3$3$G\e(B @samp{\e$BB)H4$-\e(B} \e$B%H%T%C%/$N\e(B @samp{alt.sex.emacs} \e$B%0%k!<%W$KF~$C\e(B
+\e$B$?$H$-!"\e(B@file{relief.SCORE} \e$B$,4pK\%9%3%"%U%!%$%k$H$J$j$^$9!#$b\e(B
+\e$B$7\e(B @samp{Emacs} \e$B%H%T%C%/$NF1$8%0%k!<%W$KF~$k$H!"\e(B@file{emacs.SCORE} \e$B$,4p\e(B
+\e$BK\%9%3%"%U%!%$%k$K$J$k$G$7$g$&!#\e(B
+@samp{alt.religion.emacs} \e$B%0%k!<%W$KF~$l$P!"\e(B@file{religion.SCORE} \e$B$,4pK\\e(B
+\e$B%9%3%"%U%!%$%k$K$J$k$G$7$g$&!#\e(B
+
+\e$B$3$l$C$F$H$C$F$b4JC1$G<+L@$N$3$H$N$h$&$K8+$($k$G$7$g\e(B? \e$B$^$"!"$=$NDL$j$G$9!#\e(B
+\e$B$G$9$,LdBj$,$"$k>l9g$b$"$j$^$9!#FC$K\e(B@code{total-expiry} \e$B%Q%i%a!<%?$K4X$7\e(B
+\e$B$F$G$9!#Nc$($P$"$k%a!<%k%0%k!<%W$rFs$D$N%H%T%C%/$NCf$K!"0lJ}\e(B
+\e$B$O\e(B @code{total-expiry} \e$B$"$j$G!"$b$&0lJ}$O$=$l$J$7$G;}$C$F$$$k$H$7$^$7$g\e(B
+\e$B$&!#$3$3$G\e(B @kbd{M-x gnus-expire-all-expirable-groups} \e$B$r<B9T$9$k$H!"2?$,\e(B
+\e$B5/$3$k$G$7$g$&$+\e(B? Gnus \e$B$O!"$"$J$?$,$I$A$i$N%H%T%C%/$+$i5-;v$r%(%/%9%Q%$\e(B
+\e$B%"$7$?$$$N$+$rCN$kJ}K!$,$J$$$?$a!":G0-$N;vBV$,H/@8$9$k$+$b$7$l$^$;$s!#<B\e(B
+\e$B:]!";d$O$3$N$H$-2?$,5/$3$k$N$+$O!VL$Dj5A\e(B @dfn{undefined}\e$B!W$G$"$k!"$H$3$3\e(B
+\e$B$K@k8@$7$^$9!#$3$N<j$N$3$H$r$d$j$?$$>l9g$K$O==J,Cm0U$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+@node Misc Group Stuff
+@section \e$B$=$NB>$N%0%k!<%W4XO"\e(B
+
+@menu
+* Scanning New Messages::       Gnus \e$B$K?7$7$$%a%C%;!<%8$,E~Ce$7$?$+$I$&$+$rJ9$/\e(B
+* Group Information::           \e$B%0%k!<%W$H\e(B gnus \e$B$K4X$9$k>pJs$H%X%k%W\e(B
+* Group Timestamp::             Gnus \e$B$K:G8e$K$$$D%0%k!<%W$rFI$s$@$+$r5-O?$5$;$k\e(B
+* File Commands::               Gnus \e$B$N%U%!%$%k$NFI$_=q$-\e(B
+* Sieve Commands::              Sieve \e$B%9%/%j%W%H$N4IM}\e(B
+@end menu
+
+@table @kbd
+@item ^
+@kindex ^ (\e$B%0%k!<%W\e(B)
+@findex gnus-group-enter-server-mode
+\e$B%5!<%P%P%C%U%!%b!<%I$KF~$k\e(B (@code{gnus-group-enter-server-mode})\e$B!#\e(B
+@xref{Server Buffer}.
+
+@item a
+@kindex a (\e$B%0%k!<%W\e(B)
+@findex gnus-group-post-news
+\e$B%a%C%;!<%8\e(B (\e$B%G%#%U%)%k%H$O%K%e!<%9\e(B) \e$B$N:n@.$r3+;O$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-post-news})\e$B!#$b$7@\F,<-$,M?$($i$l$?$i8=:_0LCV$N%0%k!<\e(B
+\e$B%W$KEj9F$7$^$9!#$b$7@\F,<-$,\e(B 1 \e$B$@$C$?$i!"$I$N%0%k!<%W$KEj9F$9$k$+$r?R$M\e(B
+\e$B$^$9!#$3$N4X?t$NL>A0$+$iO"A[$5$l$k$3$H$H$ON"J"$K!"@\F,<-$G%a!<%k%0%k!<%W\e(B
+\e$B$,;XDj$5$l$?>l9g$O!"%K%e!<%9$NBe$o$j$K%a!<%k$NMM<0$,MQ0U$5$l$^$9!#\e(B
+@xref{Composing Messages}.
+
+@item m
+@kindex m (\e$B%0%k!<%W\e(B)
+@findex gnus-group-mail
+\e$B%a!<%k$r$I$3$+$KAw$j$^$9\e(B (@code{gnus-group-mail})\e$B!#$b$7@\F,<-$,M?$($i$l\e(B
+\e$B$?$i8=:_0LCV$N%0%k!<%W$NEj9FMM<0\e(B (posting style) \e$B$r;H$$$^$9!#$b$7@\F,<-\e(B
+\e$B$,\e(B 1 \e$B$@$C$?$i!"$I$N%0%k!<%W$NEj9FMM<0$r;H$&$+$r?R$M$^$9!#\e(B
+@xref{Composing Messages}.
+
+@item i
+@kindex i (\e$B%0%k!<%W\e(B)
+@findex gnus-group-news
+\e$B%K%e!<%9$N:n@.$r3+;O$7$^$9\e(B (@code{gnus-group-news})\e$B!#$b$7@\F,<-$,M?$($i\e(B
+\e$B$l$?$i8=:_0LCV$N%0%k!<%W$KEj9F$7$^$9!#$b$7@\F,<-$,\e(B 1 \e$B$@$C$?$i!"$I$N%0%k!<\e(B
+\e$B%W$KEj9F$9$k$+$r?R$M$^$9!#\e(B@xref{Composing Messages}.
+
+\e$B$3$N4X?t$O!"$?$H$(%a!<%k%0%k!<%W$G;H$o$l$?$H$7$F$b!"<B:]$K$O%K%e!<%9$NMM\e(B
+\e$B<0$rMQ0U$7$^$9!#$3$l$O!"%a%C%;!<%8$r<B:]$K$O%M%C%H%o!<%/7PM3$GAw$i$:$K!"\e(B
+\e$B%a!<%k%0%k!<%W$K\e(B ``\e$BEj9F\e(B'' \e$B$9$k$N$KJXMx$G$9\e(B; \e$B$=$l$i$OEv$N%0%k!<%W$KC1$KD>\e(B
+\e$B@\%;!<%V$5$l$^$9!#BP1~$9$k%P%C%/%(%s%I$,Ej9F$N$?$a$N%a%=%C\e(B
+\e$B%I\e(B (request-post method) \e$B$r;}$C$F$$$J$1$l$P$J$j$^$;$s$,!#\e(B
+@end table
+
+\e$B0J2<$O%0%k!<%W%P%C%U%!$N$?$a$NJQ?t$G$9\e(B:
+
+@table @code
+@item gnus-group-mode-hook
+@vindex gnus-group-mode-hook
+\e$B%0%k!<%W%P%C%U%!$,:n@.$5$l$?;~$K8F$S=P$5$l$^$9!#\e(B
+
+@item gnus-group-prepare-hook
+@vindex gnus-group-prepare-hook
+\e$B%0%k!<%W%P%C%U%!$,@8@.$5$l$?$"$H$K8F$S=P$5$l$^$9!#$3$l$O%P%C%U%!$r2?$+JQ\e(B
+\e$B$J!"<+A3$8$c$J$$J}K!$G=$@5$7$?$$$H$-$K;H$o$l$k$+$b$7$l$^$;$s!#\e(B
+
+@item gnus-group-prepared-hook
+@vindex gnus-group-prepare-hook
+\e$B%0%k!<%W%P%C%U%!$,@8@.$5$l$?8e$N0lHV:G8e$K8F$S=P$5$l$^$9!#Nc$($P%]%$%s%H\e(B
+\e$B$r$I$3$+$K0\F0$5$;$?$$$H$-$J$I$K;H$($^$9!#\e(B
+
+@item gnus-permanently-visible-groups
+@vindex gnus-permanently-visible-groups
+\e$B$3$N@55,I=8=$K%^%C%A$9$k%0%k!<%W$O!"$=$l$,6u$G$"$k$+$I$&$+$K4X$o$i$:!">o\e(B
+\e$B$K%0%k!<%W%P%C%U%!$KI=<($5$l$^$9!#\e(B
+
+@item gnus-group-name-charset-method-alist
+@vindex gnus-group-name-charset-method-alist
+\e$B%0%k!<%WL>MQ$NA*BrJ}K!$HJ8;z=89g$NO"A[%j%9%H$G$9!#$3$l$O1Q;z$G$O$J$$%0%k!<\e(B
+\e$B%WL>$rI=<($9$k$?$a$K;H$$$^$9!#\e(B
+
+\e$BNc\e(B:
+@lisp
+(setq gnus-group-name-charset-method-alist
+    '(((nntp "news.com.cn") . cn-gb-2312)))
+@end lisp
+
+@item gnus-group-name-charset-group-alist
+@cindex UTF-8 group names
+@vindex gnus-group-name-charset-group-alist
+\e$B%0%k!<%WL>MQ$N%0%k!<%WL>$N@55,I=8=$HJ8;z=89g$NO"A[%j%9%H$G$9!#$3$l$O1Q;z\e(B
+\e$B$G$O$J$$%0%k!<%WL>$rI=<($9$k$?$a$K;H$$$^$9!#%G%#%U%)%k%HCM$O!"\e(BUTF-8 \e$B$,%5\e(B
+\e$B%]!<%H$5$l$F$$$k>l9g$O\e(B @code{((".*" utf-8))}\e$B!"$=$l0J30$N>l9g\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+\e$BNc\e(B:
+@lisp
+(setq gnus-group-name-charset-group-alist
+    '(("\\.com\\.cn:" . cn-gb-2312)))
+@end lisp
+@end table
+
+@node Scanning New Messages
+@subsection \e$B?7Ce%a%C%;!<%8$rC5$9\e(B
+@cindex new messages
+@cindex scanning new news
+
+@table @kbd
+@item g
+@kindex g (\e$B%0%k!<%W\e(B)
+@findex gnus-group-get-new-news
+@c @icon{gnus-group-get-new-news}
+\e$B%5!<%P$N?7Ce5-;v$r%A%'%C%/$7$^$9!#?t;z%W%l%U%#%C%/%9$r;HMQ$9$k$H!"$3$NL?\e(B
+\e$BNa$O0z?t\e(B @var{arg} \e$B$+$=$l$h$j>.$5$$%l%Y%k$N%0%k!<%W$N$_$r%A%'%C%/$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-get-new-news})\e$B!#?t;z0J30$N%W%l%U%#%C%/%9$rM?$($k$H!"\e(B
+\e$B$3$NL?Na$O$=$N%P%C%/%(%s%I$+$i%"%/%F%#%V%U%!%$%k$r6/@)E*$KA4ItFI$_D>$7$^\e(B
+\e$B$9!#\e(B
+
+@item M-g
+@kindex M-g (\e$B%0%k!<%W\e(B)
+@findex gnus-group-get-new-news-this-group
+@vindex gnus-goto-next-group-when-activating
+@c @icon{gnus-group-get-new-news-this-group}
+\e$B8=:_$N%0%k!<%W$K?7Ce5-;v$,$"$k$+$I$&$+$r%A%'%C%/$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-get-new-news-this-group})\e$B!#\e(B
+@code{gnus-goto-next-group-when-activating} \e$B$O$3$NL?Na$,<!$N%0%k!<%W0LCV\e(B
+\e$B$X0\F0$9$k$+$I$&$+$r7h$a$^$9!#=i4|CM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@findex gnus-activate-all-groups
+@cindex activating groups
+@item C-c M-g
+@kindex C-c M-g (\e$B%0%k!<%W\e(B)
+\e$BL5>r7o$KA4$F$N%0%k!<%W$r5/F0$7$^$9\e(B (@code{gnus-activate-all-groups})\e$B!#\e(B
+
+@item R
+@kindex R (\e$B%0%k!<%W\e(B)
+@cindex restarting
+@findex gnus-group-restart
+Gnus \e$B$r%j%9%?!<%H$7$^$9\e(B (@code{gnus-group-restart})\e$B!#$3$l\e(B
+\e$B$O\e(B @file{.newsrc} \e$B%U%!%$%k$r%;!<%V$7!"A4$F$N%5!<%P$N@\B3$rJD$8!"A4$F\e(B
+\e$B$N\e(B gnus \e$B%i%s%?%$%`JQ?t$r%/%j%"$7$?8e!"\e(Bgnus \e$B$r$b$&0lEY:G=i$+$i3+;O$7$^$9!#\e(B
+@end table
+
+@vindex gnus-get-new-news-hook
+@code{gnus-get-new-news-hook} \e$B$O?7Ce%K%e!<%9$r%A%'%C%/$9$kD>A0$K<B9T$5$l\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-after-getting-new-news-hook
+@code{gnus-after-getting-new-news-hook} \e$B?7Ce%K%e!<%9$r%A%'%C%/$7$?8e$K<B\e(B
+\e$B9T$5$l$^$9!#\e(B
+
+@node Group Information
+@subsection \e$B%0%k!<%W>pJs\e(B
+@cindex group information
+@cindex information on groups
+
+@table @kbd
+@item H f
+@kindex H f (\e$B%0%k!<%W\e(B)
+@findex gnus-group-fetch-faq
+@vindex gnus-group-faq-directory
+@cindex @acronym{FAQ}
+@cindex ange-ftp
+\e$B8=:_$N%0%k!<%W$N\e(B @acronym{FAQ} \e$B$r<hF@$7$h$&$H$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-fetch-faq})\e$B!#\e(B
+gnus \e$B$O\e(B @acronym{FAQ} \e$B$r\e(B@code{gnus-group-faq-directory} \e$B$+$i<hF@$7$h$&$H\e(B
+\e$B$7$^$9!#$3$l$ODL>o%j%b!<%H%^%7%s>e$N%G%#%l%/%H%j$G$9!#$3$NJQ?t$O%G%#%l%/\e(B
+\e$B%H%j$N%j%9%H$G$"$C$F$b9=$$$^$;$s!#$3$N>l9g!"$3$N%3%^%s%I$K%W%l%U%#%C%/%9\e(B
+\e$B$rM?$($k$3$H$G$$$/$D$+$N%5%$%H$NCf$+$iA*$V$3$H$,$G$-$^$9!#%U%!%$%k$N<hF@\e(B
+\e$B$K$O\e(B @code{ange-ftp} (\e$B$^$?$O\e(B @code{efs}) \e$B$,;HMQ$5$l$^$9!#\e(B
+
+\e$B$b$7:G=i$N%5%$%H$+$i$N<hF@$,<:GT$7$?>l9g!"\e(B
+gnus \e$B$O\e(B @code{gnus-group-faq-directory} \e$B$NCM$rA4$F!"0l$D0l$D%*!<%W%s$7$F\e(B
+\e$B$_$h$&$H$7$^$9!#\e(B
+
+@item H c
+@kindex H c (\e$B%0%k!<%W\e(B)
+@findex gnus-group-fetch-charter
+@vindex gnus-group-charter-alist
+@cindex charter
+\e$B8=:_$N%0%k!<%W$N7{>O$r\e(B web \e$B%V%i%&%6$G3+$3$&$H$7$^\e(B
+\e$B$9\e(B (@code{gnus-group-fetch-charter})\e$B!#@\F,0z?t$,M?$($i$l$k$H%0%k!<%WL>$r\e(B
+\e$B?R$M$^$9!#\e(B
+
+gnus \e$B$O\e(B @code{gnus-group-charter-alist} \e$B$r;H$C$F7{>O$N=j:_$rC5$7$^$9!#=j\e(B
+\e$B:_$,$o$+$i$J$+$C$?$i!"\e(Bgnus \e$B$O$=$N%0%k!<%W$N%3%s%H%m!<%k%a%C%;!<%8$r<hF@\e(B
+\e$B$7$^$9!#$=$l$K$O7{>O$r4^$s$G$$$k$3$H$,$"$j$^$9$+$i!#\e(B
+
+@item H C
+@kindex H C (\e$B%0%k!<%W\e(B)
+@findex gnus-group-fetch-control
+@vindex gnus-group-fetch-control-use-browse-url
+@cindex control message
+\e$B$=$N%0%k!<%W$N%3%s%H%m!<%k%a%C%;!<%8$r\e(B @code{ftp.isc.org} \e$B$N5-O?8K$+$i<h\e(B
+\e$BF@$7$^$9\e(B (@code{gnus-group-fetch-control})\e$B!#@\F,0z?t$,M?$($i$l$k$H%0%k!<\e(B
+\e$B%WL>$r?R$M$^$9!#\e(B
+
+@code{gnus-group-fetch-control-use-browse-url} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"\e(B
+gnus \e$B$O\e(B @code{browse-url} \e$B$r;H$C$F%3%s%H%m!<%k%a%C%;!<%8$r3+$-$^$9!#$=$&\e(B
+\e$B$G$J$$>l9g$O\e(B @code{ange-ftp} \e$B$r;H$C$F<hF@$5$l!"0l;~%0%k!<%W$KI=<($5$l$^\e(B
+\e$B$9!#\e(B
+
+\e$B%3%s%H%m!<%k%a%C%;!<%8$O05=L$5$l$F$$$k$3$H$KCm0U$7$F2<$5$$!#$3$N%3%^%s%I\e(B
+\e$B$r;H$&$K$O\e(B @code{auto-compression-mode} \e$B$r\e(B on \e$B$K$7$F$*$/I,MW$,$"$j$^\e(B
+\e$B$9\e(B (@pxref{Compressed Files, ,Compressed Files, emacs, The Emacs
+Manual})\e$B!#\e(B
+
+@item H d
+@itemx C-c C-d
+@c @icon{gnus-group-describe-group}
+@kindex H d (\e$B%0%k!<%W\e(B)
+@kindex C-c C-d (\e$B%0%k!<%W\e(B)
+@cindex describing groups
+@cindex group description
+@findex gnus-group-describe-group
+\e$B8=:_$N%0%k!<%W$N@bL@$rI=<($9$k\e(B (@code{gnus-group-describe-group})\e$B!#%W%l\e(B
+\e$B%U%#%C%/%9$rM?$($k$H!"@bL@J8$r%5!<%P$+$i6/@)E*$K:FFI$_9~$_$7$^$9!#\e(B
+
+@item M-d
+@kindex M-d (\e$B%0%k!<%W\e(B)
+@findex gnus-group-describe-all-groups
+\e$BA4$F$N%0%k!<%W$N@bL@$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-group-describe-all-groups})\e$B!#%W%l%U%#%C%/%9$rM?$($k$H!"@b\e(B
+\e$BL@J8%U%!%$%k$r%5!<%P$+$i6/@)E*$K:FFI$_9~$_$7$^$9!#\e(B
+
+@item H v
+@itemx V
+@kindex V (\e$B%0%k!<%W\e(B)
+@kindex H v (\e$B%0%k!<%W\e(B)
+@cindex version
+@findex gnus-version
+\e$B8=:_$N\e(B gnus \e$B$N%P!<%8%g%sHV9f$rI=<($7$^$9\e(B (@code{gnus-version})\e$B!#\e(B
+
+@item ?
+@kindex ? (\e$B%0%k!<%W\e(B)
+@findex gnus-group-describe-briefly
+\e$B$H$F$bC;$$%X%k%W%a%C%;!<%8$rM?$($^\e(B
+\e$B$9\e(B (@code{gnus-group-describe-briefly})\e$B!#\e(B
+
+@item C-c C-i
+@kindex C-c C-i (\e$B%0%k!<%W\e(B)
+@cindex info
+@cindex manual
+@findex gnus-info-find-node
+Gnus \e$B$N\e(B info \e$B%N!<%I$K0\F0$7$^$9\e(B (@code{gnus-info-find-node})\e$B!#\e(B
+@end table
+
+@node Group Timestamp
+@subsection \e$B%0%k!<%W$NF|IU\e(B
+@cindex timestamps
+@cindex group timestamps
+
+Gnus \e$B$K!"$"$J$?$,:G8e$K$$$D%0%k!<%W$rFI$s$@$+$r5-O?$5$;$k$HJXMx$+$b$7$l\e(B
+\e$B$^$;$s!#$3$N3hF0$r;O$a$5$;$k$K$O!"\e(B
+@code{gnus-group-set-timestamp} \e$B$r\e(B @code{gnus-select-group-hook} \e$B$KDI2C\e(B
+\e$B$7$F$/$@$5$$!#\e(B
+
+@lisp
+(add-hook 'gnus-select-group-hook 'gnus-group-set-timestamp)
+@end lisp
+
+\e$B$3$l$r9T$C$?8e!"$"$J$?$,%0%k!<%W$KF~$k$?$S$K$=$l$,5-O?$5$l$^$9!#\e(B
+
+\e$B$3$N>pJs$O$5$^$6$^$JJ}K!$GI=<($G$-$^$9!=!=$b$C$H$b4JC1$J$N$O!"%0%k!<%W9T\e(B
+\e$B%U%)!<%^%C%H$G\e(B @samp{%d} \e$B;XDj$r;H$&J}K!$G$9\e(B:
+
+@lisp
+(setq gnus-group-line-format
+      "%M\%S\%p\%P\%5y: %(%-40,40g%) %d\n")
+@end lisp
+
+\e$B$3$N7k2L$H$7$F!"3F9T$O0J2<$N$h$&$KI=<($5$l$^$9\e(B:
+
+@example
+*        0: mail.ding                                19961002T012943
+         0: custom                                   19961002T012713
+@end example
+
+\e$B8+$FJ,$+$k$H$*$j!"F|IU$O%3%s%Q%/%H$J\e(B ISO 8601 \e$B7A<0$GI=<($5$l$^$9!#\e(B
+\e$B$3$l$G$O$A$g$C$H$"$s$^$j$J$N$G!"0J2<$N$h$&$J46$8$K$9$k$HF|IU$@$1\e(B
+\e$B$rI=<($G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-group-line-format
+      "%M\%S\%p\%P\%5y: %(%-40,40g%) %6,6~(cut 2)d\n")
+@end lisp
+
+\e$B$b$C$H6E$C$?F|IU$N7A<0$r$*K>$_$J$i!"%f!<%6!<Dj5A$K$h$k%U%)!<%^%C%H$N;EMM\e(B
+\e$B$r;H$&$3$H$,$G$-$^$9!#0J2<$N$h$&$J$b$N$O$&$^$/$$$/$G$7$g$&\e(B:
+
+@lisp
+(setq gnus-group-line-format
+      "%M\%S\%p\%P\%5y: %(%-40,40g%) %ud\n")
+(defun gnus-user-format-function-d (headers)
+  (let ((time (gnus-group-timestamp gnus-tmp-group)))
+    (if time
+        (format-time-string "%b %d  %H:%M" time)
+      "")))
+@end lisp
+
+@node File Commands
+@subsection \e$B%U%!%$%kL?Na\e(B
+@cindex file commands
+
+@table @kbd
+@item r
+@kindex r (\e$B%0%k!<%W\e(B)
+@findex gnus-group-read-init-file
+@vindex gnus-init-file
+@cindex reading init file
+\e$B=i4|2=%U%!%$%k$N:FFI$_9~$_$r9T$&\e(B (@code{gnus-init-file}\e$B!"$3$N%G\e(B
+\e$B%U%)%k%H$O\e(B @file{~/.gnus.el}) (@code{gnus-group-read-init-file})\e$B!#\e(B
+
+@item s
+@kindex s (\e$B%0%k!<%W\e(B)
+@findex gnus-group-save-newsrc
+@cindex saving .newsrc
+@file{.newsrc.eld} \e$B%U%!%$%k\e(B (\e$B$H!"$b$7$=$&$7$?$1$l$P\e(B @file{.newsrc} \e$B%U%!\e(B
+\e$B%$%k\e(B) \e$B$r%;!<%V$9$k\e(B (@code{gnus-group-save-newsrc})\e$B!#\e(B
+
+@c @item Z
+@c @kindex Z (\e$B%0%k!<%W\e(B)
+@c @findex gnus-group-clear-dribble
+@c \e$B%I%j%V%k%U%!%$%k$r%/%j%"$9$k\e(B
+@c (@code{gnus-group-clear-dribble})\e$B!#\e(B
+@end table
+
+@node Sieve Commands
+@subsection Sieve \e$B%3%^%s%I\e(B
+@cindex group sieve commands
+
+Sieve \e$B$O%5!<%P!<B&$G;H$o$l$k%a!<%k%U%#%k%?!<8@8l$G$9!#\e(Bgnus \e$B$G$O!"3F%0%k!<\e(B
+\e$B%W$KE,MQ$5$l$k\e(B sieve \e$B$N5,B'$r;XDj$9$k!"\e(B@code{sieve} \e$B%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B (@pxref{Group Parameters}) \e$B$r;H$&$3$H$,$G$-$^$9!#\e(Bguns \e$B$O$=$l$i$9$Y$F\e(B
+\e$B$N%0%k!<%W%Q%i%a!<%?$r!"%5!<%P!<$G;H$&$3$H$b2DG=$J@5$7$$\e(B Sieve \e$B%9%/%j%W\e(B
+\e$B%H$KK]Lu$9$k!"Fs$D$N%3%^%s%I$rDs6!$7$^$9!#\e(B
+
+@vindex gnus-sieve-file
+@vindex gnus-sieve-region-start
+@vindex gnus-sieve-region-end
+\e$B:n@.$5$l$?\e(B Sieve \e$B%9%/%j%W%H$O\e(B @code{gnus-sieve-file} (\e$B%G%#%U%)%k%H\e(B
+\e$B$O\e(B @file{~/.sieve}) \e$B$KCV$+$l$^$9!#\e(Bgnus \e$B$,:n$k%3!<%I$OFs$D$N6h@Z$j5-\e(B
+\e$B9f\e(B @code{gnus-sieve-region-start} \e$B$H\e(B @code{gnus-sieve-region-end} \e$B$N4V$K\e(B
+\e$BCV$+$l$k$N$G!"$3$l$i$N6h@Z$j5-9f$N30$KDI2C$N\e(B Sieve \e$B%3!<%I$r=q$$$F$b!"<!\e(B
+\e$B2s\e(B Sieve \e$B%9%/%j%W%H$r:F:n@.$9$k$H$-$K>C$5$l$F$7$^$&$3$H$O$"$j$^$;$s!#\e(B
+
+@vindex gnus-sieve-crosspost
+\e$BJQ?t\e(B @code{gnus-sieve-crosspost} \e$B$O\e(B Sieve \e$B%9%/%j%W%H$,$I$N$h$&$K:n$i$l$k\e(B
+\e$B$+$r@)8f$7$^$9!#$b$7Hs\e(B-@code{nil} (\e$B%G%#%U%)%k%H\e(B) \e$B$@$C$?$i5-;v$O5,B'$K%^%C\e(B
+\e$B%A$9$k$9$Y$F$N%0%k!<%W$KCV$+$l$^$9!#$=$&$G$J$$>l9g!"5-;v$O:G=i$N5,B'$K%^%C\e(B
+\e$B%A$9$k%0%k!<%W$@$1$KCV$+$l$^$9!#Nc$($P%0%k!<%W%Q%i%a!<%?\e(B @samp{(sieve
+address "sender" "owner-ding@@hpc.uh.edu")} \e$B$O!"\e(B
+@code{gnus-sieve-crosspost} \e$B$,\e(B @code{nil} \e$B$@$C$?$i0J2<$N\e(B Sieve \e$B%3!<%I$N\e(B
+\e$BCGJR$r:n$j$^$9!#\e(B(@code{gnus-sieve-crosspost} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?>l9g\e(B
+\e$B$O!"9T$,4^$`\e(B @code{stop} \e$B$N8F$S=P$7$,:o=|$5$l$k$3$H0J30$OF1$8$G$9!#\e(B)
+
+@example
+if address "sender" "owner-ding@@hpc.uh.edu" @{
+        fileinto "INBOX.ding";
+        stop;
+@}
+@end example
+
+@xref{Top, Emacs Sieve, Top, sieve, Emacs Sieve}.
+
+@table @kbd
+@item D g
+@kindex D g (\e$B%0%k!<%W\e(B)
+@findex gnus-sieve-generate
+@vindex gnus-sieve-file
+@cindex generating sieve script
+@code{sieve} \e$B%0%k!<%W%Q%i%a!<%?$+$i\e(B Sieve \e$B%9%/%j%W%H$r:F:n@.$7$F!"\e(B
+@code{gnus-sieve-file} \e$B$K=q$-9~$_$^$9!#0JA0$NFbMF$OJ]B8$5$l$^$;$s!#\e(B
+
+@item D u
+@kindex D u (\e$B%0%k!<%W\e(B)
+@findex gnus-sieve-update
+@vindex gnus-sieve-file
+@cindex updating sieve script
+@code{sieve} \e$B%0%k!<%W%Q%i%a!<%?$r85$K\e(B @code{gnus-sieve-file} \e$B$N\e(B gnus \e$B$,\e(B
+\e$B4IM}$7$F$$$kItJ,$r:F:n@.$7$F%U%!%$%k$K%;!<%V$7!"\e(B@code{sieveshell} \e$B%W%m%0\e(B
+\e$B%i%`$r;H$C$F%5!<%P!<$K%"%C%W%m!<%I$7$^$9!#\e(B
+@end table
+
+@node Summary Buffer
+@chapter \e$B35N,%P%C%U%!\e(B
+@cindex summary buffer
+
+\e$B35N,%P%C%U%!\e(B (summary buffer) \e$B$G$O$=$l$>$l$N5-;v$,0l9T$GI=<($5$l$^$9!#$=\e(B
+\e$B$NCf$rF0$-2s$j!"5-;v$rFI$_!"Ej9F$7!"JVEz$r$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B35N,%P%C%U%!$K0\$k0lHVIaDL$NJ}K!$O!"%0%k!<%W%P%C%U%!$G%0%k!<%W$rA*Br$9$k\e(B
+\e$B$3$H$G$9\e(B (@pxref{Selecting a Group})\e$B!#\e(B
+
+\e$B35N,%P%C%U%!$OK>$`$@$1$?$/$5$s3+$$$?>uBV$K$7$F$*$/$3$H$,$G$-$^$9!#\e(B
+
+@menu
+* Summary Buffer Format::       \e$B35N,%P%C%U%!$N304Q$r7hDj$9$k\e(B
+* Summary Maneuvering::         \e$B35N,%P%C%U%!$rF0$-2s$k\e(B
+* Choosing Articles::           \e$B5-;v$rFI$`\e(B
+* Paging the Article::          \e$BFI$s$G$$$k5-;v$r%9%/%m!<%k$9$k\e(B
+* Reply Followup and Post::     \e$B5-;v$rEj9F$9$k\e(B
+* Delayed Articles::            \e$B5-;v$r8e$GAw$k\e(B
+* Marking Articles::            \e$B5-;v$K4{FI$d4|8B@Z$l:o=|2DG=Ey$N0u$rIU$1$k\e(B
+* Limiting::                    \e$B35N,%P%C%U%!$K@)8B$r2C$($k$3$H$,$G$-$k\e(B
+* Threading::                   \e$B%9%l%C%I$,$I$N$h$&$K:n$i$l$k$+\e(B
+* Sorting the Summary Buffer::  \e$B%9%l%C%I$H5-;v$,$I$N$h$&$KJB$S$+$($i$l$k$+\e(B
+* Asynchronous Fetching::       Gnus \e$B$O5-;v$r@h$K<hF@$9$k$3$H$,$G$-$k\e(B
+* Article Caching::             \e$B%-%c%C%7%e$K5-;v$rCy$a$F$*$1$k\e(B
+* Persistent Articles::         \e$B5-;v$r4|8B@Z$l>C5n$7$J$/$5$;$k\e(B
+* Article Backlog::             \e$B4{$KFI$s$@5-;v$r;D$7$F$*$/\e(B
+* Saving Articles::             \e$B5-;v$NJ]B8$r%+%9%?%^%$%:$9$kJ}K!\e(B
+* Decoding Articles::           Gnus \e$B$O0lO"$N\e(B (uu)encode \e$B$5$l$?5-;v$r07$($k\e(B
+* Article Treatment::           \e$B5-;v%P%C%U%!$O$*K>$_$I$*$j$KL\Cc6lCc$K$G$-$k\e(B
+@c * MIME Commands::               Doing MIMEy things with the articles.
+@c * Charsets::                    Character set issues.
+* Article Commands::            \e$B5-;v%P%C%U%!$G$$$m$$$m$J$3$H$r$9$k\e(B
+* Summary Sorting::             \e$B$$$m$$$m$JJ}K!$G35N,%P%C%U%!$rJB$YBX$($k\e(B
+* Finding the Parent::          \e$B;R5-;v$,C5$;$J$$$C$F\e(B? \e$B?F5-;v$r<hF@$7$J$5$$\e(B
+* Alternative Approaches::      \e$B=i4|@_Dj$G$J$$35N,$r;H$C$FFI$`\e(B
+* Tree Display::                \e$B$b$C$H;k3PE*$J%9%l%C%I$NI=<(\e(B
+* Mail Group Commands::         \e$B$$$/$D$+$NL?Na$O%a!<%k%0%k!<%W$@$1$G;H$&$3$H$,$G$-$k\e(B
+* Various Summary Stuff::       \e$BB>$N$I$N>l=j$K$b9g$o$J$+$C$?$b$N\e(B
+* Exiting the Summary Buffer::  \e$B%0%k!<%W%P%C%U%!$KLa$k!"$^$?$O8=:_$N%0%k!<%W$r:F$SA*Br$9$k\e(B
+* Crosspost Handling::          \e$B%/%m%9%]%9%H$5$l$?5-;v$,$I$N$h$&$K07$o$l$k$+\e(B
+* Duplicate Suppression::       \e$B%/%m%9%]%9%H$N07$$$K<:GT$7$?$H$-$NBeBX<jCJ\e(B
+@c * Security::                    Decrypt and Verify.
+* Mailing List::                \e$B%a!<%j%s%0%j%9%H%^%$%J!<%b!<%I\e(B
+@end menu
+
+@node Summary Buffer Format
+@section \e$B35N,%P%C%U%!$NMM<0\e(B
+@cindex summary buffer format
+
+@iftex
+@iflatex
+\gnusfigure{The Summary Buffer}{180}{
+\put(0,0){\epsfig{figure=ps/summary,width=7.5cm}}
+\put(445,0){\makebox(0,0)[br]{\epsfig{figure=ps/summary-article,width=7.5cm}}}
+}
+@end iflatex
+@end iftex
+
+@menu
+* Summary Buffer Lines::        \e$B35N,%P%C%U%!$,$I$N$h$&$K8+$($k$Y$-$+$r;XDj$G$-$k\e(B
+* To From Newsgroups::          \e$B<+J,<+?H$NL>A0$rI=<($7$J$$J}K!\e(B
+* Summary Buffer Mode Line::    \e$B%b!<%I9T$N8+$(J}$r7h$a$i$l$k\e(B
+* Summary Highlighting::        \e$B35N,%P%C%U%!$r$-$l$$$GAGE($K$9$k\e(B
+@end menu
+
+@findex std11-extract-address-components
+@findex mail-extract-address-components
+@findex gnus-extract-address-components
+@vindex gnus-extract-address-components
+Gnus \e$B$OJQ?t\e(B @code{gnus-extract-address-components} \e$B$NCM$r\e(B @code{From} \e$B%X%C\e(B
+\e$B%@!<$NL>A0$H%"%I%l%9$NItJ,$r<j$KF~$l$k$?$a$N4X?t$H$7$F;H$$$^$9!#$9$G$KDj\e(B
+\e$B5A$5$l$F$$$k4X?t$,;0$DB8:_$7$^$9\e(B:
+@code{gnus-extract-address-components} \e$B$O=i4|CM$G$9$,!"$H$F$b4JC1$K3d$j\e(B
+\e$B@Z$C$?2r7hK!$G!"Hs>o$KB.$/F0:n$7$^$9!#\e(B
+@code{mail-extract-address-components} \e$B$ONI$/F0:n$7$^$9$,!"$d$dCY$/$J$j\e(B
+\e$B$^$9!#$=$7$F!"\e(B@code{std11-extract-address-components} \e$B$O$H$F$bNI$/F0:n$7\e(B
+\e$B$^$9$,!"CY$/$J$j$^$9!#%G%#%U%)%k%H$N4X?t$O\e(B 5% \e$B$N3d9g$G4V0c$C$FEz$($^$9!#\e(B
+\e$B$b$7$3$l$K2fK}$J$i$J$$$N$G$"$l$P!"B>$N4X?t$rBe$o$j$K;H$&$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-extract-address-components
+      'mail-extract-address-components)
+@end lisp
+
+@vindex gnus-summary-same-subject
+@code{gnus-summary-same-subject} \e$B$O:#FI$s$G$$$k5-;v$,!"$=$NA0$N5-;v$HF1\e(B
+\e$B$8I=Bj\e(B (subject) \e$B$G$"$k$3$H$r<($9J8;zNs$G$9!#$3$NJ8;zNs$O;EMM$,$3$l$rMW\e(B
+\e$B5a$9$k$H$-$K;H$o$l$^$9!#=i4|@_Dj$G$O\e(B @code{""} \e$B$G$9!#\e(B
+
+@node Summary Buffer Lines
+@subsection \e$B35N,%P%C%U%!$N9T\e(B
+
+@vindex gnus-summary-line-format
+\e$BJQ?t\e(B @code{gnus-summary-line-format} \e$B$NCM$rJQ$($k$3$H$K$h$C$F!"35N,%P%C\e(B
+\e$B%U%!$G$N9T$NMM<0\e(B (format) \e$B$rJQ99$9$k$3$H$,$G$-$^$9!#$$$/$D$+$N3H\e(B
+\e$BD%\e(B (@pxref{Formatting Variables}) \e$B$r=|$$$F!"IaDL$N\e(B @code{format} \e$BJ8;zNs\e(B
+\e$B$HF1$8$h$&$KF0:n$7$^$9!#\e(B
+
+\e$B9T$K$O>o$K%3%m%s$+%]%$%s%H0LCV$N%^!<%+!<$,B8:_$7$F$$$J$1$l$P$J$j$^$;$s!#\e(B
+\e$BA`:n$7$?8e$K!"%+!<%=%k$O$$$D$b%3%m%s$+%]%$%s%H0LCV$N%^!<%+!<$N>l=j$K0\F0\e(B
+\e$B$7$^$9!#\e(B(\e$B$b$A$m$s!"$3$NF0:n$rJQ$($k$3$H$,$G$-$J$$$H$7$?$i\e(B Gnus \e$B$K$O$"$k\e(B
+\e$B$^$8$-$3$H$G$9!#4X?t\e(B @code{gnus-goto-colon} \e$B$r!"$"$J$?$,9%$-$J%+!<%=%k$N\e(B
+\e$BF0$-$K$J$k$h$&$K!"?7$?$K=q$1$PNI$$$N$G$9!#\e(B) @xref{Positioning Point}.
+
+\e$B=i4|CM$NJ8;zNs$O\e(B @samp{%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n} \e$B$G$9!#\e(B
+
+\e$B0J2<$NMM<0;X<(J8;z$H3HD%MM<0;X<($r;H$&$3$H$,$G$-$^$9\e(B:
+
+@table @samp
+@item N
+\e$B5-;v?t!#\e(B
+@item S
+\e$BI=Bj$NJ8;zNs!#\e(B@code{gnus-list-identifiers} \e$B$N@_Dj$K$h$C$F%a!<%j%s%0%j%9\e(B
+\e$B%H$NI8<1$,:o=|$5$l$^$9!#\e(B@xref{Article Hiding}.
+@item s
+\e$B%9%l%C%I\e(B (thread) \e$B$N4p5-;v$G$"$k$H$-$+D>A0$N5-;v$,0c$&I=Bj$N$H$-$O$=$NBj\e(B
+\e$BL>$G!"$=$l0J30$O\e(B @code{gnus-summary-same-subject}\e$B!#\e(B
+(@code{gnus-summary-same-subject} \e$B$N=i4|CM$O\e(B @code{""}\e$B!#\e(B)
+@item F
+\e$B40A4$J\e(B @code{From} \e$BMs!#\e(B
+@item n
+\e$BL>A0\e(B (@code{From} \e$BMs$h$j\e(B)\e$B!#\e(B
+@item f
+\e$BL>A0!"\e(B@code{To} \e$B%X%C%@!<$+\e(B @code{Newsgroups} \e$B%X%C%@!<$G\e(B
+\e$B$9\e(B (@pxref{To From Newsgroups})\e$B!#\e(B
+@item a
+\e$BL>A0\e(B (@code{From} \e$BMs$h$j\e(B)\e$B!#$3$l$H\e(B @code{n} \e$B$H$N0c$$$O!"$3$l$OJQ\e(B
+\e$B?t\e(B @code{gnus-extract-address-components} \e$B$G;XDj$5$l$F$$$k4X?t$r;H$C$FL>\e(B
+\e$BA0$r<hF@$9$k$3$H$G$9!#$3$NJ}$,CY$$$G$9$,!"$*$=$i$/$h$j40A4$K6a$$$G$7$g$&!#\e(B
+@item A
+\e$BL>A0\e(B (@code{From} \e$BMs$h$j\e(B)\e$B!#$3$l$O\e(B @code{a} \e$B$HF1$8$h$&$KF0:n$7$^$9!#\e(B
+@item L
+\e$B5-;v$N9T?t!#\e(B
+@item c
+\e$B5-;v$NJ8;z?t!#$3$NL>A0;XDj;R$O\e(B (nnfolder \e$B$N$h$&$J\e(B) \e$B$$$/$D$+$NA*BrJ}K!$r\e(B
+\e$B%5%]!<%H$7$^$;$s!#\e(B
+@item k
+\e$B@07A$5$l$?5-;v$NJ8;z?t\e(B; \e$BNc$($P\e(B @samp{1.2k} \e$B$d\e(B @samp{0.4M}\e$B!#\e(B
+@item I
+\e$B%9%l%C%I$N%l%Y%k$K$h$k;z2<$2\e(B (@pxref{Customizing Threading})\e$B!#\e(B
+@item B
+\e$BJ#;($J\e(B trn \e$BMM<0$N%9%l%C%ILZ\e(B (tree)\e$B!#$I$N$h$&$J1~Ez$,9T$J$o$l$?$+$N5-O?$r\e(B
+\e$BI=<($7$^$9!#%9%l%C%I$O$3$N$h$&$KIA$+$l$k$G$7$g$&\e(B:
+
+@example
+>
++->
+| +->
+| | \->
+| |   \->
+| \->
++->
+\->
+@end example
+
+\e$B0J2<$N%*%W%7%g%s$G8+1I$($r%+%9%?%^%$%:$9$k$3$H$,$G$-$^$9!#%G%#%U%)%k%H\e(B
+\e$B$N\e(B @acronym{ASCII} \e$BJ8;z$r@~IA2hMQ$N?^0F$GCV$-49$($k$3$H$K$h$C$F!"%9%l%C\e(B
+\e$B%II=<($r<B$K9*L/$K8+$;$k$3$H$,$G$-$k$3$H$K5$IU$$$F2<$5$$!#\e(B
+@table @code
+@item gnus-sum-thread-tree-root
+@vindex gnus-sum-thread-tree-root
+\e$B%9%l%C%I$N:,\e(B (root) \e$B$K;H$o$l$^$9!#\e(B@code{nil} \e$B$@$C$?$i!"Be$o$j$KBjL>$r;H\e(B
+\e$B$$$^$9!#%G%#%U%)%k%H$O\e(B @samp{> } \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-false-root
+@vindex gnus-sum-thread-tree-false-root
+\e$B%9%l%C%I$N$K$;$N:,$K;H$o$l$^$9\e(B (@pxref{Loose Threads})\e$B!#\e(B@code{nil} \e$B$@$C\e(B
+\e$B$?$i!"Be$o$j$KBjL>$r;H$$$^$9!#%G%#%U%)%k%H$O\e(B @samp{> } \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-single-indent
+@vindex gnus-sum-thread-tree-single-indent
+\e$BC10l$N%a%C%;!<%8$N%9%l%C%I$K;H$o$l$^$9!#\e(B@code{nil} \e$B$@$C$?$i!"Be$o$j$KBj\e(B
+\e$BL>$r;H$$$^$9!#%G%#%U%)%k%H$O\e(B @samp{} \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-vertical
+@vindex gnus-sum-thread-tree-vertical
+\e$B=D@~$NIA2h$K;H$o$l$^$9!#%G%#%U%)%k%H$O\e(B @samp{| } \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-indent
+@vindex gnus-sum-thread-tree-indent
+\e$B9T2<$2\e(B (indenting) \e$B$K;H$o$l$^$9!#%G%#%U%)%k%H$O\e(B @samp{  } \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-leaf-with-other
+@vindex gnus-sum-thread-tree-leaf-with-other
+\e$B7;Do$,$$$kMU$C$Q$K;H$o$l$^$9!#%G%#%U%)%k%H$O\e(B @samp{+-> } \e$B$G$9!#\e(B
+
+@item gnus-sum-thread-tree-single-leaf
+@vindex gnus-sum-thread-tree-single-leaf
+\e$B7;Do$,$$$J$$MU$C$Q$K;H$o$l$^$9!#%G%#%U%)%k%H$O\e(B @samp{\-> } \e$B$G$9!#\e(B
+@end table
+
+@item T
+\e$B5-;v$,K\5-;v$G$"$l$P2?$bI=<($;$:!"$=$&$G$J$$>l9g$O$?$/$5$s$N6uGr$G$9\e(B (\e$B8e\e(B
+\e$B$N$b$N$r$9$Y$F2hLL$N30$KDI$$=P$7$F$7$^$$$^$9\e(B)\e$B!#\e(B
+@item [
+\e$B3+$-3g8L!#IaDL$O\e(B @samp{[} \e$B$G$9$,!"M\;R5-;v$K$O\e(B @samp{<} \e$B$K$9$k$3$H$,$G$-\e(B
+\e$B$^$9\e(B (@pxref{Customizing Threading})\e$B!#\e(B
+@item ]
+\e$BJD$83g8L!#IaDL$O\e(B @samp{[} \e$B$G$9$,!"M\;R5-;v$K$O\e(B @samp{<} \e$B$K$9$k$3$H$,$G$-\e(B
+\e$B$^$9!#\e(B
+@item >
+\e$B$=$l$>$l$N%9%l%C%I$N%l%Y%k$KBP$7$F0l$D$N6uGr!#\e(B
+@item <
+\e$BFs==0z$/%9%l%C%I%l%Y%k$N6uGr!#\e(B
+@item U
+\e$BL$FI!#\e(B@xref{Read Articles}.
+
+@item R
+\e$B$3$NJ6$i$o$7$$L>A0;XDj;R$O\e(B @dfn{secondary mark} \e$B$K$h$C$FDj5A$5$l$^$9!#$3\e(B
+\e$B$N%^!<%/$O5-;v$,4{$KJVEz:Q$_$N$b$N$+!"%-%c%C%7%e$5$l$?$b$N$+!"$"$k$$$OJ]\e(B
+\e$BB8$5$l$?$b$N$+$rI=$7$^$9!#\e(B@xref{Other Marks}.
+
+@item i
+\e$B?t;z$H$7$F$N%9%3%"\e(B (@pxref{Scoring})\e$B!#\e(B
+@item z
+@vindex gnus-summary-zcore-fuzz
+\e$B$3$l$O!"\e(Bzcore \e$B$G=i4|@_Dj$N%l%Y%k$h$j$b>e$G$"$l$P\e(B @samp{+} \e$B$G!"=i4|@_Dj$N\e(B
+\e$B%l%Y%k$h$j$b2<$G$"$l$P\e(B @samp{-} \e$B$G$9!#\e(B
+@code{gnus-summary-default-score} \e$B$H$N:9\e(B
+\e$B$,\e(B @code{gnus-summary-zcore-fuzz} \e$B$h$j$b>.$5$$$H!"$3$N;EMM$O;H$o$l$^$;$s!#\e(B
+@item V
+\e$B%9%l%C%IA4BN$N%9%3%"!#\e(B
+@item x
+@code{Xref}.
+@item D
+@code{\e$BF|IU\e(B} (@code{Date})\e$B!#\e(B
+@item d
+@code{DD-MM}\e$BMM<0$K$h$k\e(B@code{\e$BF|IU\e(B}\e$B!#\e(B
+@item o
+@var{YYYYMMDD}@code{T}@var{HHMMSS}\e$BMM<0$K$h$k\e(B@code{\e$BF|IU\e(B}\e$B!#\e(B
+@item M
+@code{Message-ID}.
+@item r
+@code{References}.
+@item t
+\e$B8=:_$NI{%9%l%C%I$N5-;v$N?t!#$3$N;EMM$r;H$&$H35N,%P%C%U%!$N@8@.$,4vJ,CY$/\e(B
+\e$B$J$j$^$9!#\e(B
+@item e
+\e$B5-;v$K;R5-;v$,$"$k$H!"\e(B@samp{=} (@code{gnus-not-empty-thread-mark}) \e$B$,I=\e(B
+\e$B<($5$l$^$9!#\e(B
+@item P
+\e$B9T?t!#\e(B
+@item O
+\e$B%@%&%s%m!<%I$N0u!#\e(B
+@item &user-date;
+\e$B7P2a;~4V$NMM<0!#$$$m$$$m$JMM<0$,\e(B @code{gnus-user-date-format-alist} \e$B$GDj\e(B
+\e$B5A$5$l$F$$$^$9!#\e(B
+@item u
+\e$BMxMQ<TDj5A;XDj;R!#%U%)!<%^%C%HJ8;zNs$NCf$N<!$NJ8;z$,1Q;z$G$"$kI,MW$,$"$j\e(B
+\e$B$^$9!#$3$l$K$h$j\e(B gnus \e$B$O4X\e(B
+\e$B?t\e(B @code{gnus-user-format-function-}@var{x} \e$B$r8F$S=P$7$^$9$,!"$3$3\e(B
+\e$B$G\e(B @var{x} \e$B$O\e(B @samp{%u} \e$B$N<!$NJ8;z$G$9!#4X?t$K$O8=:_$N5-;v$N%X%C%@!<$,\e(B
+\e$B0z?t$H$7$FEO$5$l$^$9!#4X?t$OJ8;zNs$rJV$7!"B>$N35N,;XDj$HF1MM$K35N,$KA^F~\e(B
+\e$B$5$l$^$9!#\e(B
+@end table
+
+@samp{%(} \e$B$H\e(B @samp{%)} \e$B$N4V$K$"$k%F%-%9%H$O!"$=$3$K%^%&%9$,$"$k$H$-\e(B
+\e$B$K\e(B @code{gnus-mouse-face} \e$B$G%O%$%i%$%H$5$l$^$9!#$=$&$$$&NN0h$O0l$D$@$1$G\e(B
+\e$B$9!#\e(B
+
+@samp{%U} (\e$B>uBV\e(B), @samp{%R} (\e$BJVEz:Q$_\e(B), @samp{%z} (zcore) \e$B$N07$$$K$O5$$r\e(B
+\e$BIU$1$kI,MW$,$"$j$^$9!#8zN($N$?$a$K!"\e(Bgnus \e$B$O$3$l$i$NJ8;z$,$I$N7e$K8=$l$k\e(B
+\e$B$+$r7W;;$7!"!X%O!<%I!&%3!<%I!Y$7$^$9!#$3$l$O!"2DJQD9$N;EMM$N8e$G$O!"$3$l\e(B
+\e$B$i$O0UL#$r;}$?$J$$$H$$$&$3$H$G$9!#$^$!!"$5$9$,$KBaJa$O$5$l$J$$$G$7$g$&$,!"\e(B
+\e$B35N,%P%C%U%!$OJQ$K$J$j$^$9!#$=$l$G$b==J,Ha$7$$$G$7$g$&$1$I!#\e(B
+
+\e$B8-$$A*Br$O$3$l$i$N;XDj$r$G$-$k$@$1:8$K;}$C$F$/$k$3$H$G$9!#\e(B(\e$B$G$b!"$=$&$$\e(B
+\e$B$&$3$H$O$9$Y$F$KEv$F$O$^$k$N$G$O$J$$$G$7$g$&$+!#4WOC5YBj!#\e(B)
+
+\e$B$3$N@)8B$O>-Mh$NHG$G$OL5$/$J$k$+$bCN$l$^$;$s!#\e(B
+
+@node To From Newsgroups
+@subsection To From Newsgroups
+@cindex To
+@cindex Newsgroups
+
+\e$B$$$/$D$+$N%0%k!<%W$G$O\e(B (\e$BFC$K%"!<%+%$%V%0%k!<%W\e(B), @code{From} \e$B%X%C%@!<$O\e(B
+\e$B$"$^$j6=L#$r0z$-$^$;$s!#$=$3$NA4$F$N5-;v$O$"$J$?$K$h$C$F=q$+$l$?$b$N$G$9\e(B
+\e$B$+$i!#Be$o$j$K!"\e(B@code{To} \e$B$d\e(B @code{Newsgroups} \e$B%X%C%@!<$N>pJs$rI=<($9$k\e(B
+\e$B$?$a$K$O!";0$D$N$3$H$r7h$a$kI,MW$,$"$j$^$9\e(B: \e$B$I$N>pJs$r=8$a$k$+\e(B, \e$B$I$3$KI=\e(B
+\e$B<($9$k$+\e(B, \e$B$$$DI=<($9$k$+!#\e(B
+
+@enumerate
+@item
+@vindex gnus-extra-headers
+\e$BDI2C$N%X%C%@!<$N>pJs$O\e(B @code{gnus-extra-headers} \e$B$K$h$j@)8f$5$l$^$9!#$3\e(B
+\e$B$l$O%X%C%@!<$N%7%s%\%k$N%j%9%H$G$9!#Nc$($P\e(B:
+
+@lisp
+(setq gnus-extra-headers
+      '(To Newsgroups X-Newsreader))
+@end lisp
+
+\e$B$3$l$O!"\e(Bgnus \e$B$,$3$l$i$N;0$D$N%X%C%@!<$r<hF@$7$h$&$H$7!"8e$NMF0W$J<hF@$N\e(B
+\e$B$?$a$K%X%C%@!<9=B$$KJ]B8$9$k$H$$$&7k2L$K$J$j$^$9!#\e(B
+
+@item
+@findex gnus-extra-header
+\e$B$3$l$i$NDI2C$N%X%C%@!<$NCM$O\e(B @code{gnus-extra-function} \e$B4X?t$rDL$8$F07$&\e(B
+\e$B$3$H$,$G$-$^$9!#$3$l$O\e(B @code{X-Newsreader} \e$B%X%C%@!<$r;H$&=q<09T$N;EMM$G\e(B
+\e$B$9\e(B:
+
+@example
+"%~(form (gnus-extra-header 'X-Newsreader))@@"
+@end example
+
+@item
+@vindex gnus-ignored-from-addresses
+@code{gnus-ignored-from-addresses} \e$BJQ?t$O$$$D\e(B @samp{%f} \e$B35N,9T;EMM\e(B
+\e$B$,\e(B @code{To}, @code{Newsreader} \e$B$d\e(B @code{From} \e$B%X%C%@!<$rJV$;$PNI$$$+$r\e(B
+\e$B7h$a$^$9!#$3$N@55,I=8=$,\e(B @code{From} \e$B%X%C%@!<$NFbMF$H9gCW$9$k$H!"\e(B
+@code{To} \e$B$d\e(B @code{Newsreader} \e$B%X%C%@!<$,Be$o$j$K;EMM$5$l$^$9!#\e(B
+
+@end enumerate
+
+@vindex nnmail-extra-headers
+\e$B4XO"$7$?JQ?t$O\e(B @code{nnmail-extra-headers} \e$B$G!"\e(B
+overview (@acronym{NOV}) \e$B%U%!%$%k$K$$$DDI2C$N%X%C%@!<$r4^$a$k$+$r@)8f$7\e(B
+\e$B$^$9!#8E$$\e(B overview \e$B%U%!%$%k$,$"$k>l9g$O!"$3$NJQ?t$rJQ99$7$?8e$K%5!<%P!<\e(B
+\e$B%P%C%U%!$K\e(B @kbd{^} \e$B$GF~$C$FE,@Z$J%a!<%k%5!<%P!<\e(B (\e$BNc$(\e(B
+\e$B$P\e(B nnml) \e$B$G\e(B @kbd{g} \e$B$r2!$7!":F@8@.$9$kI,MW$,$"$j$^$9!#\e(B
+
+@vindex gnus-summary-line-format
+gnus \e$B$K!"\e(B@code{gnus-summary-line-format} \e$BJQ?t$N\e(B @code{%n} \e$B;EMM\e(B
+\e$B$r\e(B @code{%f} \e$B;EMM$KJQ99$9$k$3$H$G!"%G!<%?$rI=<($9$k$h$&$K;X<($9$kI,MW$,\e(B
+\e$B$"$j$^$9!#\e(B
+
+\e$BMWLs$9$k$H!"IaDL$O0J2<$N$h$&$J$b$N$r\e(B @file{~/.gnus.el} \e$B$KCV$/$3$H$K$J$j\e(B
+\e$B$^$9\e(B:
+
+@lisp
+(setq gnus-extra-headers
+      '(To Newsgroups))
+(setq nnmail-extra-headers gnus-extra-headers)
+(setq gnus-summary-line-format
+      "%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n")
+(setq gnus-ignored-from-addresses
+      "Your Name Here")
+@end lisp
+
+(\e$B>e5-$NCM$O\e(B gnus \e$B$N%G%#%U%)%k%HCM$G$9!#$"$J$?$NLr$KN)$D$h$&$KJQ$($F2<$5\e(B
+\e$B$$!#\e(B)
+
+\e$B%K%e!<%94IM}?M!"$^$?$O%K%e!<%94IM}?M$r@bF@$7$F%5%]!<%H$NDI2C$r$7$F$b$i$*\e(B
+\e$B$&$H;W$C$F$$$k%f!<%6!<$N$_$J$5$s$X$N$4Cm0U\e(B:
+
+\e$B>e5-$N$3$H$O!":n@.$5$l$k\e(B @acronym{NOV} \e$B%U%!%$%k$rA`:n$G$-$k%a!<%k%0%k!<\e(B
+\e$B%W$G$O$?$$$F$$$N>l9gLrN)$A$^$9!#$7$+$7!"4IM}?M$r@bF@$7$F\e(B (\e$BFC$K\e(B INN \e$B$NIa\e(B
+\e$BDL$N<BAu$K$*$$$F\e(B) \e$B0J2<$N$b$N$r\e(B
+
+@example
+Newsgroups:full
+@end example
+
+@file{overview.fmt} \e$B%U%!%$%k$N:G8e$KDI2C$7$F$b$&$i$&$3$H$,$G$-$l$P!"%a!<\e(B
+\e$B%k%0%k!<%W$G$NDI2C%X%C%@!<$N$h$&$K$=$l$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+@node Summary Buffer Mode Line
+@subsection \e$B35N,%P%C%U%!$N%b!<%I9T\e(B
+
+@vindex gnus-summary-mode-line-format
+\e$B35N,$N%b!<%I9T$NMM<0$bJQ99$9$k$3$H$,$G$-$^$9\e(B (@pxref{Mode Line
+Formatting})\e$B!#\e(B@code{gnus-summary-mode-line-format} \e$B$r2?$G$b9%$-$J$b$N$K\e(B
+\e$BJQ99$7$F$/$@$5$$!#=i4|CM$O\e(B @samp{Gnus: %%b [%A] %Z} \e$B$G$9!#\e(B
+
+\e$B0J2<$,$"$J$?$,M7$V$3$H$N$G$-$k$=$l$>$l$NMWAG$G$9\e(B:
+
+@table @samp
+@item G
+\e$B%0%k!<%WL>!#\e(B
+@item p
+\e$B@\F,8l$r<h$j=|$$$?L>A0!#\e(B
+@item A
+\e$B8=:_$N5-;vHV9f!#\e(B
+@item z
+\e$B8=:_$N5-;v%9%3%"!#\e(B
+@item V
+Gnus \e$B%P!<%8%g%s!#\e(B
+@item U
+\e$B$=$N%0%k!<%W$G$NL$FI5-;v$N?t!#\e(B
+@item e
+\e$B35N,%P%C%U%!$KI=<($5$l$F$$$J$$L$FI5-;v$N?t!#\e(B
+@item Z
+\e$BL$FI$HL$A*Br$N5-;v$N?t$H$H$b$KI=$5$l$kJ8;zNs$G!"L$FI$+$DL$A*Br$N5-;v$,$"\e(B
+\e$B$k>l9g$O\e(B @samp{<%U(+%e) more>} \e$B$G!"L$FI5-;v$N$_$N>l9g\e(B
+\e$B$O\e(B @samp{<%U more>} \e$B$G$9!#\e(B
+@item g
+\e$BC;=L%0%k!<%WL>!#Nc$($P!"\e(B@samp{rec.arts.anime} \e$B$O\e(B @samp{r.a.anime} \e$B$KC;=L\e(B
+\e$B$5$l$^$9!#\e(B
+@item S
+\e$B8=:_$N5-;v$NI=Bj!#\e(B
+@item u
+\e$BMxMQ<TDj5A$N;EMM\e(B (@pxref{User-Defined Specs})\e$B!#\e(B
+@item s
+\e$B8=:_$N%9%3%"%U%!%$%k$NL>A0\e(B (@pxref{Scoring})\e$B!#\e(B
+@item d
+\e$BJ]N15-;v$N?t\e(B (@pxref{Unread Articles})\e$B!#\e(B
+@item t
+\e$B2D;k0uIU$-5-;v$N?t\e(B (@pxref{Unread Articles})\e$B!#\e(B
+@item r
+\e$B$=$N0lO"$NF0:n$N4V$K4{FI$H$7$F0u$,$D$$$?5-;v$N?t!#\e(B
+@item E
+\e$B%9%3%"%U%!%$%k$K$h$C$FKu>C$5$l$?5-;v$N?t!#\e(B
+@end table
+
+@node Summary Highlighting
+@subsection \e$B35N,$N%O%$%i%$%H\e(B
+
+@table @code
+@item gnus-visual-mark-article-hook
+@vindex gnus-visual-mark-article-hook
+\e$B$3$N%U%C%/$O5-;v$rA*Br$7$?8e$K<B9T$5$l$^$9!#$3$l$O2?$i$+$NJ}K!$G5-;v$r%O\e(B
+\e$B%$%i%$%H$9$k$h$&$K0U?^$5$l$F$$$^$9!#$b\e(B
+\e$B$7\e(B @code{gnus-visual} \e$B$,\e(B @code{nil} \e$B$G$"$k>l9g$O<B9T$5$l$^$;$s!#\e(B
+
+@item gnus-summary-update-hook
+@vindex gnus-summary-update-hook
+\e$B$3$N%U%C%/$O35N,9T$,JQ99$5$l$?$H$-$K8F$P$l$^$9!#$b\e(B
+\e$B$7\e(B @code{gnus-visual} \e$B$,\e(B @code{nil} \e$B$G$"$k>l9g$O<B9T$5$l$^$;$s!#\e(B
+
+@item gnus-summary-selected-face
+@vindex gnus-summary-selected-face
+\e$B$3$l$O35N,%P%C%U%!$G$N8=:_$N5-;v$r%O%$%i%$%H$9$k$?$a$K;H$o$l$k%U%'%$\e(B
+\e$B%9\e(B (face) (\e$B$b$7$/$O!"$$$/$i$+$N?M!9$,\e(B @dfn{\e$B%U%)%s%H\e(B} (font) \e$B$H8F$V$h$&$J\e(B
+\e$B$b$N\e(B) \e$B$G$9!#\e(B
+
+@item gnus-summary-highlight
+@vindex gnus-summary-highlight
+\e$B35N,9T$O$3$NJQ?t$K$7$?$,$C$F%O%$%i%$%H$5$l$^$9!#$3$NJQ?t$OMWAG\e(B
+\e$B$,\e(B @code{(@var{form} . @var{face})} \e$B$N7A<0$N%j%9%H$G$9!#Nc$($P!"$b$70uIU\e(B
+\e$B$-$N5-;v$r%$%?%j%C%/!"9b$$%9%3%"$N5-;v$r%\!<%k%I$K$7$?$1$l$P!"$3$NJQ?t$r\e(B
+\e$B<!$N$h$&$K$G$-$^$9!#\e(B
+
+@lisp
+(((eq mark gnus-ticked-mark) . italic)
+ ((> score default) . bold))
+@end lisp
+
+\e$B$4A[A|$N$H$*$j!"$b$7\e(B @var{form} \e$B$,\e(B @code{nil} \e$B$G$J$$CM$rJV$9$H!"\e(B
+@var{face} \e$B$,$=$N9T$KE,MQ$5$l$^$9!#\e(B
+@end table
+
+@node Summary Maneuvering
+@section \e$B35N,4V$N0\F0\e(B
+@cindex summary movement
+
+\e$B$9$Y$F$ND>@\0\F0L?Na$O?tCM@\F,0z?t$r<u$1IU$1!"$"$J$?$N4|BT$K$h$/$7$?$,$C\e(B
+\e$B$FF0:n$9$k$G$7$g$&!#\e(B
+
+\e$B$3$l$i$NL?Na$O$I$l$b5-;v$rA*Br$7$^$;$s!#\e(B
+
+@table @kbd
+@item G M-n
+@item M-n
+@kindex M-n (\e$B35N,\e(B)
+@kindex G M-n (\e$B35N,\e(B)
+@findex gnus-summary-next-unread-subject
+\e$B35N,9T$N<!$NL$FI5-;v$K0\$k\e(B (@code{gnus-summary-next-unread-subject})\e$B!#\e(B
+
+@item G M-p
+@itemx M-p
+@kindex M-p (\e$B35N,\e(B)
+@kindex G M-p (\e$B35N,\e(B)
+@findex gnus-summary-prev-unread-subject
+\e$B35N,9T$NA0$NL$FI5-;v$K0\$k\e(B (@code{gnus-summary-prev-unread-subject})\e$B!#\e(B
+
+@item G g
+@kindex G g (\e$B35N,\e(B)
+@findex gnus-summary-goto-subject
+\e$B5-;vHV9f$+\e(B @code{Message-ID} \e$B$r?R$M!"$=$l$+$i$=$N5-;v$rI=<($9$k$3$HL5$/!"\e(B
+\e$B35N,9T$K9T$/\e(B (@code{gnus-summary-goto-subject})\e$B!#\e(B
+@end table
+
+Gnus \e$B$,<!$N%0%k!<%W$K0\F0$9$k$3$H$r3NG'$r$9$k$?$a$K!"%-!<$r2!$9$3$H$rMW\e(B
+\e$B5a$9$k$H$-$,$"$j$^$9!#$=$N;~$O!"\e(B@kbd{C-n} \e$B$H\e(B @kbd{C-p} \e$B$r;H$C$F!"%0%k!<\e(B
+\e$B%W%P%C%U%!$KLa$k$3$HL5$/<!$KFI$`%0%k!<%W$rC5$9$3$H$,$G$-$^$9!#\e(B
+
+\e$B35N,$N0\F0$K4XO"$7$?JQ?t\e(B:
+
+@table @code
+@vindex gnus-auto-select-next
+@item gnus-auto-select-next
+\e$B$b$70\F0L?Na$N0l$D\e(B (@kbd{n} \e$B$N$h$&$J\e(B) \e$B$r=P$7!"8=:_$N5-;v$N8e$KL$FI$,L5$1\e(B
+\e$B$l$P!"\e(Bgnus \e$B$O<!$N%0%k!<%W$K0\F0$9$k$3$H$r>)$a$^$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{t} \e$B$G<!$N%0%k!<%W$,6u$G$"$k$H!"\e(Bgnus \e$B$O35N,%b!<%I$r=*N;$7$F!"%0\e(B
+\e$B%k!<%W%P%C%U%!$KLa$j$^$9!#$3$NJQ?t$,\e(B @code{t} \e$B$d\e(B @code{nil} \e$B$G$J$1$l\e(B
+\e$B$P\e(B gnus \e$B$O$=$l$rA*Br$7$^$9!#FCJL$J>l9g$H$7$F!"$3$NJQ?t\e(B
+\e$B$,\e(B @code{quietly} \e$B$G$"$k$H!"\e(Bgnus \e$B$O3NG'$r$;$:$K!"<!$N%0%k!<%W$rA*Br$7$^\e(B
+\e$B$9!#$3$NJQ?t$,\e(B @code{almost-quietly} \e$B$G$"$k$H!"%0%k!<%W$N0lHV:G8e$N5-;v\e(B
+\e$B$rFI$s$G$$$?$H$-$K8B$jF1$8$3$H$,5/$3$j$^$9!#:G8e$K!"$b$7$3$NJQ?t\e(B
+\e$B$,\e(B @code{slightly-quietly} \e$B$G$"$k$H!"L?Na\e(B @kbd{Z n} \e$B$O3NG'$r$;$:$K<!$N%0\e(B
+\e$B%k!<%W$K0\$j$^$9!#\e(B@ref{Group Levels} \e$B$b;2>H$7$F$/$@$5$$!#\e(B
+
+@item gnus-auto-select-same
+@vindex gnus-auto-select-same
+@code{nil} \e$B$G$J$$$H!"$9$Y$F$N0\F0L?Na$O8=:_$N5-;v$HF1$8I=Bj$N5-;v$K0\F0\e(B
+\e$B$7$h$&$H$7$^$9!#\e(B(@dfn{\e$BF1$8\e(B} \e$B$O$3$3$G$O\e(B @dfn{\e$BBgBNF1$8\e(B} \e$B$H$$$&0UL#$+$bCN$l\e(B
+\e$B$^$;$s!#>\:Y$O\e(B @code{gnus-summary-gather-subject-limit} \e$B$r8+$F$/$@$5\e(B
+\e$B$$\e(B (@pxref{Customizing Threading} \e$B$b;2>H$7$F$/$@$5$$\e(B)\e$B!#\e(B) \e$BF1$8I=Bj$N5-;v\e(B
+\e$B$,L5$$$H$-$O:G=i$NL$FI5-;v$K0\F0$7$^$9!#\e(B
+
+\e$B$3$NJQ?t$O!"%9%l%C%II=<($r9T$C$F$$$k$H$-$O$"$^$jLr$KN)$?$J$$$G$7$g$&!#\e(B
+
+@item gnus-summary-check-current
+@vindex gnus-summary-check-current
+@code{nil} \e$B$G$J$$$H!"$9$Y$F$N!XL$FI!Y0\F0L?Na$O!"<!\e(B (\e$B$b$7$/$OA0\e(B) \e$B$N5-;v\e(B
+\e$B$K0\F0$7$^$;$s!#$=$NBe$o$j$K!"$=$l$i$O8=:_$N5-;v$rA*$S$^$9!#\e(B
+
+@item gnus-auto-center-summary
+@vindex gnus-auto-center-summary
+@code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O35N,%P%C%U%!$G$N%]%$%s%H$r>o$K??Cf$KJ]$A$^$9!#\e(B
+\e$B$3$l$r$9$k$H!"$H$F$b$3$.$l$$$K$J$j$^$9$,!"CY$$%M%C%H%o!<%/@\B3$G$"$C$?$j!"\e(B
+\e$BC1$K$3$N\e(B Emacsism \e$B$G$J$$9T0Y$r9%$-$K$J$l$J$$$N$G$"$l$P!"IaDL$N\e(B Emacs \e$B$N\e(B
+\e$B%9%/%m!<%k$K$9$k$?$a$K!"$3$NJQ?t$r\e(B @code{nil} \e$B$K$9$k$3$H$,$G$-$^$9!#$3$l\e(B
+\e$B$O35N,%P%C%U%!$N?eJ?J}8~$N??Cf$X$N:F0\F0$b6X;_$7$^$9$N$G!"Hs>o$KD9$$%9%l%C\e(B
+\e$B%I$rFI$`$H$-$OITJX$+$b$7$l$^$;$s!#\e(B
+@end table
+
+@node Choosing Articles
+@section \e$B5-;v$NA*Br\e(B
+@cindex selecting articles
+
+@menu
+* Choosing Commands::           \e$B5-;v$rA*Br$9$k$?$a$NL?Na\e(B
+* Choosing Variables::          \e$B$3$l$i$NL?Na$K1F6A$r5Z$\$9JQ?t\e(B
+@end menu
+
+@node Choosing Commands
+@subsection \e$BL?Na$NA*Br\e(B
+
+\e$B0J2<$N0\F0%3%^%s%I$O$I$l$b?tCM@\F,0z?t$r<u$1IU$1$:!"5-;v$rA*Br$7!"I=<($7\e(B
+\e$B$^$9!#\e(B
+
+\e$B?7$7$$5-;v$r<h$j9~$s$@$j!"%0%k!<%W$r:FI=<($7$?$$$H$-$O\e(B @ref{Exiting the
+Summary Buffer} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@table @kbd
+@item SPACE
+@kindex SPACE (\e$B35N,\e(B)
+@findex gnus-summary-next-page
+\e$B8=:_$N5-;v$+!"$=$l$,4{$KFI$^$l$F$$$k>l9g$O<!$NL$FI5-;v$rA*Br$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-next-page})\e$B!#\e(B
+
+\e$B$9$G$K5-;v%&%#%s%I%&$r3+$$$F$$$k$H$-$K:FEY\e(B @kbd{SPACE} \e$B$r2!$9$H!"$=$N5-\e(B
+\e$B;v$O%9%/%m!<%k$5$l$^$9!#%K%e!<%9%0%k!<%WA4BN$r\e(B @kbd{SPACE} \e$B$GJXMx$KDLFI\e(B
+\e$B$G$-$^$9!#\e(B@xref{Paging the Article}.
+
+@item G n
+@itemx n
+@kindex n (\e$B35N,\e(B)
+@kindex G n (\e$B35N,\e(B)
+@findex gnus-summary-next-unread-article
+@c @icon{gnus-summary-next-unread}
+\e$B<!$NL$FI5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-next-unread-article})\e$B!#\e(B
+
+@item G p
+@itemx p
+@kindex p (\e$B35N,\e(B)
+@findex gnus-summary-prev-unread-article
+@c @icon{gnus-summary-prev-unread}
+\e$BA0$NL$FI5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-prev-unread-article})\e$B!#\e(B
+
+@item G N
+@itemx N
+@kindex N (\e$B35N,\e(B)
+@kindex G N (\e$B35N,\e(B)
+@findex gnus-summary-next-article
+\e$B<!$N5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-next-article})\e$B!#\e(B
+
+@item G P
+@itemx P
+@kindex P (\e$B35N,\e(B)
+@kindex G P (\e$B35N,\e(B)
+@findex gnus-summary-prev-article
+\e$BA0$N5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-prev-article})\e$B!#\e(B
+
+@item G C-n
+@kindex G C-n (\e$B35N,\e(B)
+@findex gnus-summary-next-same-subject
+\e$BF1$8I=Bj$N<!$N5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-next-same-subject})\e$B!#\e(B
+
+@item G C-p
+@kindex G C-p (\e$B35N,\e(B)
+@findex gnus-summary-prev-same-subject
+\e$BF1$8I=Bj$NA0$N5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-prev-same-subject})\e$B!#\e(B
+
+@item G f
+@itemx .
+@kindex G f (\e$B35N,\e(B)
+@kindex . (\e$B35N,\e(B)
+@findex gnus-summary-first-unread-article
+\e$B:G=i$NL$FI5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-first-unread-article})\e$B!#\e(B
+
+@item G b
+@item ,
+@kindex G b (\e$B35N,\e(B)
+@kindex , (\e$B35N,\e(B)
+@findex gnus-summary-best-unread-article
+\e$B:G9b%9%3%"$NL$FI5-;v$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-best-unread-article})\e$B!#$b$7@\F,0z?t$,M?$($i$l$?$J\e(B
+\e$B$i$P!"%G%#%U%)%k%H$N%9%3%"$h$jBg$-$$%9%3%"$r;}$D:G=i$NL$FI5-;v$K0\F0$7$^\e(B
+\e$B$9!#\e(B
+
+@item G l
+@itemx l
+@kindex l (\e$B35N,\e(B)
+@kindex G l (\e$B35N,\e(B)
+@findex gnus-summary-goto-last-article
+\e$BD>A0$N5-;v$K0\F0$7$^$9\e(B (@code{gnus-summary-goto-last-article})\e$B!#\e(B
+
+@item G o
+@kindex G o (\e$B35N,\e(B)
+@findex gnus-summary-pop-article
+\e$B35N,$NMzNr\e(B (history) \e$B$+$i:G8e$N5-;v$r0l$D<h$j=P$7$FA*Br$7$^$9!#\e(B
+(@code{gnus-summary-pop-article})\e$B!#$3$NL?Na$,>e$NL?Na$H0c$&$N$O!"\e(B
+@kbd{l} \e$B$,:G=*Fs$D$N5-;v$N4V$r0\F0$9$k$N$KBP$7$F!"$3$l$O9%$-$J$@$1A0$N5-\e(B
+\e$B;v$rMzNr$+$iA*$S=P$9$3$H$,$G$-$kE@$G$9!#2?$i$+$N$3$l$K4X78$7$?$3$H\e(B
+\e$B$O\e(B (\e$B$b$7$3$l$i$NL?Na$r$?$/$5$s;H$&$N$G$"$l$P\e(B)\e$B!"\e(B
+@ref{Article Backlog} \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@item G j
+@item j
+@kindex j (\e$B35N,\e(B)
+@kindex G j (\e$B35N,\e(B)
+@findex gnus-summary-goto-article
+\e$B5-;vHV9f$+\e(B @code{Message-ID} \e$B$r?R$M!"$=$l$+$i$=$N5-;v$K9T$/!#\e(B
+(@code{gnus-summary-goto-article})\e$B!#\e(B
+@end table
+
+@node Choosing Variables
+@subsection \e$BA*$V$?$a$NJQ?t\e(B
+
+\e$B5-;v$r0\F0$7!"A*Br$9$k$N$K4XO"$7$?$$$/$D$+$NJQ?t\e(B:
+
+@table @code
+@item gnus-auto-extended-newsgroup
+@vindex gnus-auto-extend-newsgroup
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"$9$Y$F$N0\F0L?Na$O!"$b$7$=$N5-;v$,35N,%P%C\e(B
+\e$B%U%!$KI=<($5$l$F$$$J$$>l9g$G$b!"A0\e(B (\e$B$b$7$/$O<!\e(B) \e$B$N5-;v$K0\F0$7$h$&$H$7$^\e(B
+\e$B$9!#$=$NL?Na$N8e$G!"\e(Bgnus \e$B$O%5!<%P!<$+$i5-;v$r<hF@$7$F!"5-;v%P%C%U%!$KI=\e(B
+\e$B<($7$^$9!#\e(B
+
+@item gnus-select-article-hook
+@vindex gnus-select-article-hook
+\e$B$3$N%U%C%/$O5-;v$,A*Br$5$l$?$H$-$K>o$K8F$P$l$^$9!#=i4|@_Dj$G$O!"A*Br$5$l\e(B
+\e$B$?5-;v$N2<$K1#$l$F$$$k%9%l%C%I$r8+$;$k$h$&$K$J$C$F$$$^$9!#$"$J$?$,FI$s$@\e(B
+\e$B$=$l$>$l$N5-;v$r%(!<%8%'%s%H$K%;!<%V$5$;$?$$>l9g$O!"$3$N%U%C%/\e(B
+\e$B$K\e(B @code{gnus-agent-fetch-selected-article} \e$B$rDI2C$9$k$3$H$G!"$=$l$r9T$J\e(B
+\e$B$&$G$7$g$&!#\e(B
+
+@item gnus-mark-article-hook
+@vindex gnus-mark-article-hook
+@findex gnus-summary-mark-unread-as-read
+@findex gnus-summary-mark-read-and-unread-as-read
+@findex gnus-unread-mark
+\e$B$3$N%U%C%/$O5-;v$,A*Br$5$l$?$H$-$K>o$K8F$P$l$^$9!#$=$l$O5-;v$K4{FI$N0u$r\e(B
+\e$BIU$1$k$?$a$K$"$j$^$9!#=i4|CM\e(B
+\e$B$O\e(B @code{gnus-summary-mark-read-and-unread-as-read} \e$B$G!"$[$H$s$I$9$Y$F$N\e(B
+\e$BFI$s$@5-;v$N0u$r\e(B @code{gnus-read-mark} \e$B$KJQ99$7$^$9!#$3$N4X?t$K1F6A$5$l\e(B
+\e$B$J$$5-;v$O!"2D;k!"J]N1!"4|8B@Z$l:o=|2DG=5-;v$@$1$G$9!#$b$7!"L$FI$K4{FI$N\e(B
+\e$B0u$rIU$1$?$$$@$1$G$"$l$P!"Be$o$j\e(B
+\e$B$K\e(B @code{gnus-summary-mark-unread-as-read} \e$B$r;H$&$3$H$,$G$-$^$9!#$=$l$O!"\e(B
+@code{gnus-low-score-mark} \e$B$d\e(B @code{gnus-del-mark} (\e$B$J$I$J$I\e(B) \e$B$N0u$r$=$N\e(B
+\e$B$^$^;D$7$^$9!#\e(B
+@end table
+
+@node Paging the Article
+@section \e$B5-;v$N%9%/%m!<%k\e(B
+@cindex article scrolling
+
+@table @kbd
+@item SPACE
+@kindex SPACE (\e$B35N,\e(B)
+@findex gnus-summary-next-page
+@kbd{SPACE} \e$B$O5-;v$r0l%Z!<%8@h$K%9%/%m!<%k$7$^$9!#5-;v$N:G8e$K$$$k>l9g$O\e(B
+\e$B<!$N5-;v$rA*Br$7$^$9\e(B (@code{gnus-summary-next-page})\e$B!#\e(B
+
+@vindex gnus-article-boring-faces
+@vindex gnus-article-skip-boring
+@code{gnus-article-skip-boring} \e$B$,Hs\e(B-@code{nil} \e$B$G!"$+$D5-;v$N;D$j$K0zMQ\e(B
+\e$B$H=pL>$7$+L5$$>l9g!"$=$l$O%9%-%C%W$5$l!"Be$o$j$K<!$N5-;v$,I=<($5$l$^$9!#\e(B
+@code{gnus-article-boring-faces} \e$B$G!"$D$^$i$J$$$H;W$&$b$N$r%+%9%?%^%$%:\e(B
+\e$B$9$k$+!"$^$?$O\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$K$h$C$F!"$3$N5!G=$rF/$+$J$$$h$&\e(B
+\e$B$K$9$k$3$H$,$G$-$^$9!#$I$s$J$K$&$s$6$j$9$k$b$N$G$b!"\e(B@kbd{C-M-v} \e$B$r;H$&$3\e(B
+\e$B$H$K$h$C$F!"<jF0$G5-;v$N%Z!<%8$r8+$k$3$H$O$G$-$^$9!#\e(B
+
+@item DEL
+@kindex DEL (\e$B35N,\e(B)
+@findex gnus-summary-prev-page
+\e$B8=:_$N5-;v$r0l%Z!<%8A0$K%9%/%m!<%k$7$^$9\e(B (@code{gnus-summary-prev-page})\e$B!#\e(B
+
+@item RET
+@kindex RET (\e$B35N,\e(B)
+@findex gnus-summary-scroll-up
+\e$B8=:_$N5-;v$r0l9T@h$K%9%/%m!<%k$7$^$9\e(B (@code{gnus-summary-scroll-up})\e$B!#\e(B
+
+@item M-RET
+@kindex M-RET (\e$B35N,\e(B)
+@findex gnus-summary-scroll-down
+\e$B8=:_$N5-;v$r0l9T8e$m$X%9%/%m!<%k$7$^$9\e(B (@code{gnus-summary-scroll-down})\e$B!#\e(B
+
+@item A g
+@itemx g
+@kindex A g (\e$B35N,\e(B)
+@kindex g (\e$B35N,\e(B)
+@findex gnus-summary-show-article
+@vindex gnus-summary-show-article-charset-alist
+\e$B8=:_$N5-;v$r\e(B (\e$B:F\e(B) \e$B<hF@$7$^$9!#$b$7@\F,0z?t$,M?$($i$l$k$H!"8=:_$N5-;v$r<h\e(B
+\e$BF@$7$^$9$,!"5-;v$r07$&4X?t$O<B9T$7$^$;$s!#$3$l$O!"%5!<%P!<$+$i$-$?$^$^$N!"\e(B
+\e$B!X@8$N!Y5-;v$rM?$($^$9!#\e(B
+
+\e$B@\F,0z?t$rM?$($k$H!"<jF0$GJ8;z=89g$NA`:n$r9T$&$3$H$,$G$-$^$9!#\e(B
+@kbd{C-u 0 g cn-gb-2312 RET} \e$B$K$h$j!"%a%C%;!<%8$O$"$?$+\e(B
+\e$B$b\e(B @code{cn-gb-2312} \e$BJ8;z=89g$GId9f2=$5$l$?$+$N$h$&$KI|9f2=$5$l$^$9!#$3\e(B
+\e$B$l$O!"0J2<$N$h$&$J5-=R$H$H$b$K\e(B @kbd{C-u 1 g} \e$B$r9T$&$N$HF1$8$G$9!#\e(B
+
+@lisp
+(setq gnus-summary-show-article-charset-alist
+      '((1 . cn-gb-2312)
+        (2 . big5)))
+@end lisp
+
+@item A <
+@itemx <
+@kindex < (\e$B35N,\e(B)
+@kindex A < (\e$B35N,\e(B)
+@findex gnus-summary-beginning-of-article
+\e$B5-;v$N:G=i$^$G%9%/%m!<%k$7$^$9!#\e(B
+(@code{gnus-summary-beginning-of-article})\e$B!#\e(B
+
+@item A >
+@itemx >
+@kindex > (\e$B35N,\e(B)
+@kindex A > (\e$B35N,\e(B)
+@findex gnus-summary-end-of-article
+\e$B5-;v$N:G8e$^$G%9%/%m!<%k$7$^$9\e(B (@code{gnus-summary-end-of-article})\e$B!#\e(B
+
+@item A s
+@itemx s
+@kindex A s (\e$B35N,\e(B)
+@kindex s (\e$B35N,\e(B)
+@findex gnus-summary-isearch-article
+\e$B5-;v%P%C%U%!$G%$%s%/%j%a%s%?%k%5!<%A\e(B (isearch) \e$B$r9T$$$^\e(B
+\e$B$9\e(B (@code{gnus-summary-isearch-article})\e$B!#\e(B
+
+@item h
+@kindex h (\e$B35N,\e(B)
+@findex gnus-summary-select-article-buffer
+\e$B5-;v%P%C%U%!$rA*Br$7$^$9\e(B (@code{gnus-summary-select-article-buffer})\e$B!#\e(B
+@end table
+
+@node Reply Followup and Post
+@section \e$BJVEz!"%U%)%m!<%"%C%W!"Ej9F\e(B
+
+@menu
+* Summary Mail Commands::       \e$B%a!<%k$rAw$k\e(B
+* Summary Post Commands::       \e$B%K%e!<%9$rAw$k\e(B
+* Summary Message Commands::    \e$BB>$N%a%C%;!<%84XO"$NL?Na\e(B
+* Canceling and Superseding::
+@end menu
+
+@node Summary Mail Commands
+@subsection \e$B35N,$G$N%a!<%k$NL?Na\e(B
+@cindex mail
+@cindex composing mail
+
+\e$B%a!<%k%a%C%;!<%8$r:n@.$9$k$?$a$NL?Na\e(B:
+
+@table @kbd
+@item S r
+@item r
+@kindex S r (\e$B35N,\e(B)
+@kindex r (\e$B35N,\e(B)
+@findex gnus-summary-reply
+@c @icon{gnus-summary-mail-reply}
+@c @icon{gnus-summary-reply}
+\e$B8=:_$N5-;v$r=q$$$??M$KJVEz$N%a!<%k$rAw$j$^$9\e(B (@code{gnus-summary-reply})\e$B!#\e(B
+
+@item S R
+@itemx R
+@kindex R (\e$B35N,\e(B)
+@kindex S R (\e$B35N,\e(B)
+@findex gnus-summary-reply-with-original
+@c @icon{gnus-summary-reply-with-original}
+\e$B8=:_$N5-;v$r=q$$$??M$K!"K\5-;v$r4^$s$@JVEz$N%a!<%k$r=P$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-reply-with-original})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z\e(B
+\e$B?t$N=,47$r;H$$$^$9!#\e(B
+
+@item S w
+@kindex S w (\e$B35N,\e(B)
+@findex gnus-summary-wide-reply
+\e$B8=:_$N5-;v$r=q$$$??M$KBP$7$F!"9-$$JVEz\e(B (wide reply) \e$B$r$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-wide-reply})\e$B!#\e(B@dfn{\e$B9-$$JVEz\e(B} \e$B$H$O%X%C%@!<\e(B
+\e$B$N\e(B @code{To}, @code{From}, (\e$B$b$7$/$O\e(B @code{Reply-to}) \e$B$H\e(B @code{Cc}) \e$B$N$9\e(B
+\e$B$Y$F$N?M$KJVEz$r$9$k$3$H$G$9!#\e(B@code{Mail-Followup-To} \e$B$,$"$l$P!"Be$o$j$K\e(B
+\e$B$=$l$,;H$o$l$^$9!#\e(B
+
+@item S W
+@kindex S W (\e$B35N,\e(B)
+@findex gnus-summary-wide-reply-with-original
+\e$B8=:_$N5-;v$KK\5-;v$r4^$s$@9-$$JVEz$N%a!<%k$rAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-wide-reply-with-original})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\\e(B
+\e$BF,0z?t$N=,47$r;H$$$^$9!#\e(B
+
+@item S v
+@kindex S v (\e$B35N,\e(B)
+@findex gnus-summary-very-wide-reply
+\e$B8=:_$N5-;v$r=q$$$??M$KBP$7$F!"Hs>o$K9-$$JVEz\e(B (very wide reply) \e$B$r$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-very-wide-reply})\e$B!#\e(B@dfn{\e$BHs>o$K9-$$JVEz\e(B} \e$B$H$O!"%W\e(B
+\e$B%m%;%9\e(B/\e$B@\F,0z?t$G;XDj$5$l$?$9$Y$F$N5-;v$N%X%C%@!<$N\e(B @code{To},
+@code{From}, (\e$B$b$7$/$O\e(B @code{Reply-to}) \e$B$H\e(B @code{Cc}) \e$B$N$9$Y$F$N?M$KJVEz\e(B
+\e$B$r$9$k$3$H$G$9!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$r;H$$$^$9!#\e(B
+
+@item S V
+@kindex S V (\e$B35N,\e(B)
+@findex gnus-summary-very-wide-reply-with-original
+\e$B8=:_$N5-;v$KK\5-;v$r4^$s$@Hs>o$K9-$$JVEz$N%a!<%k$rAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-very-wide-reply-with-original})\e$B!#$3$NL?Na$O%W%m%;\e(B
+\e$B%9\e(B/\e$B@\F,0z?t$N=,47$r;H$$$^$9!#\e(B
+
+@item S B r
+@kindex S B r (\e$B35N,\e(B)
+@findex gnus-summary-reply-broken-reply-to
+\e$B8=:_$N5-;v$r=q$$$??M$KBP$7$FJVEz$r$7$^$9$,\e(B @code{Reply-To} \e$B%U%#!<%k%I$O\e(B
+\e$BL5;k$7$^$9\e(B (@code{gnus-summary-reply-broken-reply-to})\e$B!#%a!<%j%s%0%j%9%H\e(B
+\e$B$,$=$N%j%9%H$r;X$9\e(B @code{Reply-To} \e$B$r2a$C$F@_Dj$9$k$?$a$K$3$l$,I,MW$J$N\e(B
+\e$B$G$"$l$P!"$"$J$?$O$?$V$sBe$o$j$K\e(B @code{broken-reply-to} \e$B%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$r@_Dj$9$kI,MW$,$"$j!"$=$l$OF0:n$9$k$G$7$g$&!#\e(B
+
+@item S B R
+@kindex S B R (\e$B35N,\e(B)
+@findex gnus-summary-reply-broken-reply-to-with-original
+\e$B8=:_$N5-;v$r=q$$$??M$KBP$7$FK\5-;v$r4^$s$@JVEz$r$7$^$9\e(B
+\e$B$,\e(B @code{Reply-To} \e$B%U%#!<%k%I$OL5;k$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-reply-broken-reply-to-with-original})\e$B!#\e(B
+
+@item S o m
+@itemx C-c C-f
+@kindex S o m (\e$B35N,\e(B)
+@kindex C-c C-f (\e$B35N,\e(B)
+@findex gnus-summary-mail-forward
+@c @icon{gnus-summary-mail-forward}
+\e$BC/$+B>$N?M$K8=:_$N5-;v$rE>Aw$7$^$9\e(B (@code{gnus-summary-mail-forward})\e$B!#\e(B
+\e$B@\F,0z?t$,$"$k$H!"E>Aw5-;v$N40A4$J%X%C%@!<$r<h$j9~$_$^$9!#\e(B
+
+@item S m
+@itemx m
+@kindex m (\e$B35N,\e(B)
+@kindex S m (\e$B35N,\e(B)
+@findex gnus-summary-mail-other-window
+@c @icon{gnus-summary-mail-originate}
+\e$B%a!<%k$r:n@.$7$^$9\e(B (@code{gnus-summary-mail-other-window})\e$B!#%G%#%U%)%k%H\e(B
+\e$B$G$O8=:_$N%0%k!<%W$NEj9FMM<0\e(B (posting style) \e$B$r;H$$$^$9!#$b$7@\F,<-$,M?\e(B
+\e$B$($i$l$?$i$=$l$O;H$$$^$;$s!#$b$7@\F,<-$,\e(B 1 \e$B$@$C$?$i!"$I$N%0%k!<%W$NEj9F\e(B
+\e$BMM<0$r;H$&$+$r?R$M$^$9!#\e(B
+
+@item S i
+@itemx i
+@kindex i (\e$B35N,\e(B)
+@kindex S i (\e$B35N,\e(B)
+@findex gnus-summary-news-other-window
+\e$B%K%e!<%9$r:n@.$7$^$9\e(B (@code{gnus-summary-news-other-window})\e$B!#%G%#%U%)%k\e(B
+\e$B%H$G$O8=:_$N%0%k!<%W$KEj9F$7$^$9!#$b$7@\F,<-$,M?$($i$l$?$i8=:_$N%0%k!<%W\e(B
+\e$BL>$O;H$o$l$^$;$s!#$b$7@\F,<-$,\e(B 1 \e$B$@$C$?$i!"$I$N%0%k!<%W$KEj9F$9$k$+$r?R\e(B
+\e$B$M$^$9!#\e(B
+
+\e$B$3$N4X?t$O!"$?$H$(%a!<%k%0%k!<%W$G;H$o$l$?$H$7$F$b!"<B:]$K$O%K%e!<%9$NMM\e(B
+\e$B<0$rMQ0U$7$^$9!#$3$l$O!"%a%C%;!<%8$r<B:]$K$O%M%C%H%o!<%/7PM3$GAw$i$:$K!"\e(B
+\e$B%a!<%k%0%k!<%W$K\e(B ``\e$BEj9F\e(B'' \e$B$9$k$N$KJXMx$G$9\e(B; \e$B$=$l$i$OEv$N%0%k!<%W$KC1$KD>\e(B
+\e$B@\%;!<%V$5$l$^$9!#BP1~$9$k%P%C%/%(%s%I$,Ej9F$N$?$a$N%a%=%C\e(B
+\e$B%I\e(B (request-post method) \e$B$r;}$C$F$$$J$1$l$P$J$j$^$;$s$,!#\e(B
+
+@item S D b
+@kindex S D b (\e$B35N,\e(B)
+@findex gnus-summary-resend-bounced-mail
+@cindex bouncing mail
+\e$B%a!<%k$rAw$C$?$N$K!"2?$i$+$NM}M3\e(B (\e$B%"%I%l%9$N4V0c$$!"E>Aw$NITD4\e(B) \e$B$GLa$C$F\e(B
+\e$B$-$?$H$-$K!"$3$NL?Na$r;H$C$FLa$C$F$-$?%a!<%k$r$b$&0l2sAw$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B (@code{gnus-summary-resend-bonced-mail})\e$B!#$b$&0lEY%a!<%k$rAw$kA0$K%X%C\e(B
+\e$B%@!<$rJT=8$G$-$k$h$&$K!"%a!<%k%P%C%U%!$K$=$N%a!<%k$,8=$l$k$G$7$g$&!#$3$N\e(B
+\e$BL?Na$K@\F,0z?t$rM?$($F!"La$C$F$-$?%a!<%k$,C/$+$X$NJVEz$G$"$C$?>l9g!"\e(B
+gnus \e$B$O$=$N%a!<%k$r<hF@$7$F!"$=$l$N%X%C%@!<$N@:L)D4::$,$G$-$k$h$&$K2hLL\e(B
+\e$B$KI=<($7$^$9!#$^!"$3$l$O$H$F$b$h$/<:GT$7$^$9$1$I!#\e(B
+
+@item S D r
+@kindex S D r (\e$B35N,\e(B)
+@findex gnus-summary-resend-message
+\e$B>e$NL?Na$H:.F1$7$J$$$h$&$K!"\e(B@code{gnus-summary-resend-message} \e$B$O8=:_$N\e(B
+\e$B%a%C%;!<%8$rAw$k@h$N%"%I%l%9$NF~NO$rB%$7!"$=$l$+$i$=$N>l=j$K%a!<%k$rAw$j\e(B
+\e$B$^$9!#%a%C%;!<%8$N%X%C%@!<$OJQ99$5$l$^$;$s!=!=$7$+$7!"\e(B
+@code{Resent-To}, @code{Resent-From} \e$BEy$N%X%C%@!<$,IU$12C$($i$l$^$9!#$3\e(B
+\e$B$l$O!"\e(B(\e$B$*$=$i$/\e(B) \e$B$"$J$?<+?H$r\e(B @code{To} \e$BMs$K=q$$$?K\?M$K$b%a!<%k$rAw$C$F\e(B
+\e$B$7$^$&$H$$$&$3$H$G$9!#$3$l$O:.Mp$r>7$/$G$7$g$&!#$G$9$+$i!"$b$A$m$s!"K\Ev\e(B
+\e$B$K\e(B \e$B<Y0-\e(B \e$B$J5$J,$N$H$-$K$@$1$3$l$r;H$&$G$7$g$&!#\e(B
+
+\e$B$3$NL?Na$O<g$K!"$"$J$?$,$$$/$D$+$N%a!<%k%"%+%&%s%H$r;}$C$F$$$F!"<+J,<+?H\e(B
+\e$B$N0c$C$?%"%+%&%s%H$K%a!<%k$rE>Aw$7$?$$$H$-$KMQ$$$i$l$^$9!#\e(B(\e$B$b$7$"$J$?\e(B
+\e$B$,\e(B @code{root} \e$B$G$"$j!"\e(B@code{postmaster} \e$B$G$b$"$j!"\e(B
+@code{root} \e$B$K\e(B @code{postmaster} \e$B$X$N%a!<%k$r<u$1<h$C$?>l9g$O!"$=$l\e(B
+\e$B$r\e(B @code{postmaster} \e$B$K$b:FAw$9$kI,MW$,$"$k$7$g$&!#Ca=x$,$J$1$l$P$J$j$^\e(B
+\e$B$;$s\e(B! (Ordnung muss sein!))
+
+\e$B$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$K=>$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item S O m
+@kindex S O m (\e$B35N,\e(B)
+@findex gnus-summary-digest-mail-forward
+\e$B8=:_$N0lO"$N5-;v\e(B (@pxref{Decoding Articles}) \e$B$NMWLs$r:n$j!"%a!<%k$G$=$N\e(B
+\e$B7k2L$rAw$j$^$9\e(B (@code{gnus-summary-digest-mail-forward})\e$B!#$3$NL?Na$O%W%m\e(B
+\e$B%;%9\e(B/\e$B@\F,0z?t$N=,47$K=>$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item S M-c
+@kindex S M-c (\e$B35N,\e(B)
+@findex gnus-summary-mail-crosspost-complaint
+@cindex crossposting
+@cindex excessive crossposting
+\e$B8=:_$N5-;v$N=q$-<j$K!"2a>j%/%m%9%]%9%H$X$N6l>p$N%a!<%k$rAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mail-crosspost-complaint})\e$B!#\e(B
+
+@findex gnus-crosspost-complaint
+\e$B$3$NL?Na$O!"8=:_\e(B Usenet \e$B$K2#9T$7$F$$$k!"%/%m%9%]%9%H$N@$3&E*N.9T$KBP$7$F\e(B
+\e$BH?7b$r9T$&<jCJ$H$7$FDs6!$5$l$F$$$^$9!#$3$l$OJQ\e(B
+\e$B?t\e(B @code{gnus-crosspost-complaint} \e$B$r=xJ8$K$7$F!"JVEz$r:n@.$7$^$9!#$3$N\e(B
+\e$BL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B (@pxref{Process/Prefix}) \e$B$K=>$$!"$=$l$>$l\e(B
+\e$B$N%a!<%k$rAw$kA0$KAw?.$9$k$+$I$&$+$N3NG'$r$7$^$9!#\e(B
+@end table
+
+\e$B$^$?\e(B @xref{Header Commands, ,\e$B%X%C%@!<L?Na\e(B, message-ja, The Message
+Manual}, \e$B$K$5$i$J$k>pJs$,$"$j$^$9!#\e(B
+
+@node Summary Post Commands
+@subsection \e$B35N,$NEj9FL?Na\e(B
+@cindex post
+@cindex composing news
+
+\e$B%K%e!<%9$N5-;v$rEj9F$9$k$?$a$NL?Na\e(B:
+
+@table @kbd
+@item S p
+@itemx a
+@kindex a (\e$B35N,\e(B)
+@kindex S p (\e$B35N,\e(B)
+@findex gnus-summary-post-news
+@c @icon{gnus-summary-post-news}
+\e$BEj9F$9$k$?$a$N5-;v$r:n@.$7$^$9\e(B (@code{gnus-summary-post-news})\e$B!#%G%#%U%)\e(B
+\e$B%k%H$G$O8=:_$N%0%k!<%W$KEj9F$7$^$9!#$b$7@\F,<-$,M?$($i$l$?$i8=:_$N%0%k!<\e(B
+\e$B%WL>$O;H$o$l$^$;$s!#$b$7@\F,<-$,\e(B 1 \e$B$@$C$?$i!"Be$o$j$KJL$N$I$N%0%k!<%W$K\e(B
+\e$BEj9F$9$k$+$r?R$M$^$9!#\e(B
+
+@item S f
+@itemx f
+@kindex f (\e$B35N,\e(B)
+@kindex S f (\e$B35N,\e(B)
+@findex gnus-summary-followup
+@c @icon{gnus-summary-followup}
+\e$B8=:_$N5-;v$N%U%)%m!<%"%C%W$rEj9F$7$^$9\e(B (@code{gnus-summary-followup})\e$B!#\e(B
+
+@item S F
+@itemx F
+@kindex S F (\e$B35N,\e(B)
+@kindex F (\e$B35N,\e(B)
+@c @icon{gnus-summary-followup-with-original}
+@findex gnus-summary-followup-with-original
+\e$BK\5-;v$r<h$j9~$s$G!"8=:_$N5-;v$K%U%)%m!<%"%C%W$r$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-followup-with-original})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,\e(B
+\e$B0z?t$N=,47$rMQ$$$^$9!#\e(B
+
+@item S n
+@kindex S n (\e$B35N,\e(B)
+@findex gnus-summary-followup-to-mail
+\e$B%a!<%k$N%a%C%;!<%8$r<u$1<h$C$F$$$?$H$7$F$b!"8=:_$N5-;v$N%U%)%m!<%"%C%W$r\e(B
+\e$B%K%e!<%9$KEj9F$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-followup-to-mail})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N\e(B
+\e$B=,47$rMQ$$$^$9!#\e(B
+
+@item S N
+@kindex S N (\e$B35N,\e(B)
+@findex gnus-summary-followup-to-mail-with-original
+\e$B%a!<%k$N%a%C%;!<%8$r<u$1<h$C$F$$$?$H$7$F$b!"K\5-;v$r0zMQ$7$F!"8=:_$N5-;v\e(B
+\e$B$N%U%)%m!<%"%C%W$r%K%e!<%9$KEj9F$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-followup-to-mail-with-original}). \e$B$3$NL?Na$O%W%m\e(B
+\e$B%;%9\e(B/\e$B@\F,0z?t$N=,47$rMQ$$$^$9!#\e(B
+
+@item S o p
+@kindex S o p (\e$B35N,\e(B)
+@findex gnus-summary-post-forward
+\e$B8=:_$N5-;v$r%K%e!<%9%0%k!<%W$KE>Aw$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-post-forward})\e$B!#@\F,0z?t$,M?$($i$l$?$H$-$O!"E>Aw\e(B
+\e$B5-;v$N%X%C%@!<$r40A4$K<h$j9~$_$^$9!#\e(B
+
+@item S O p
+@kindex S O p (\e$B35N,\e(B)
+@findex gnus-summary-digest-post-forward
+@cindex digests
+@cindex making digests
+\e$B8=:_$N0lO"$N5-;v$rMWLs$7$F!"$=$N7k2L$r%K%e!<%9%0%k!<%W$KAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-digest-post-forward})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z\e(B
+\e$B?t$N=,47$rMQ$$$^$9!#\e(B
+
+@item S u
+@kindex S u (\e$B35N,\e(B)
+@findex gnus-uu-post-news
+@c @icon{gnus-uu-post-news}
+\e$B%U%!%$%k$r\e(B Uuencode \e$B$7!"J,3d$7$F!"AH$K$7$FEj9F$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-post-news})\e$B!#\e(B(@pxref{Uuencoding and Posting})\e$B!#\e(B
+@end table
+
+\e$B$^$?\e(B @xref{Header Commands, ,\e$B%X%C%@!<L?Na\e(B, message-ja, The Message
+Manual}, \e$B$K$5$i$J$k>pJs$,$"$j$^$9!#\e(B
+
+@c FIXME this is not implemented
+@node Summary Message Commands
+@subsection \e$B35N,%a%C%;!<%8L?Na\e(B
+
+@table @kbd
+@item S y
+@kindex S y (\e$B35N,\e(B)
+@findex gnus-summary-yank-message
+\e$B8=:_$N5-;v$r4{$KB8:_$9$k\e(B Message \e$B:n@.%P%C%U%!$KE=$jIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summaryyank-message})\e$B!#$3$NL?Na$OE=$jIU$1$?$$%a%C%;!<%8%P%C\e(B
+\e$B%U%!$NF~NO$rB%$7!"%W%m%;%9\e(B/\e$B@\F,<-$N=,47$rM}2r$7$^\e(B
+\e$B$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+@end table
+
+@node Canceling and Superseding
+@subsection \e$B5-;v$r<h$j>C$9\e(B
+@cindex canceling articles
+@cindex superseding articles
+
+\e$B2?$+$r=q$$$?8e$G!"K\Ev$K!"K\Ev$K!"$[\e(B \e$B$s\e(B \e$B$H\e(B \e$B$&\e(B \e$B$K$=$l$rEj9F$7$F$$$J$1$l$P\e(B
+\e$B$J$!$H;W$C$?$3$H$O$"$j$^$;$s$+!#\e(B
+
+\e$B$(!<$H!"%a!<%k$O<h$j>C$9$3$H$O$G$-$J$$$N$G$9$,!"%K%e!<%9$NEj9F$O<h$j>C$9\e(B
+\e$B$3$H$,$G$-$^$9!#\e(B
+
+@findex gnus-summary-cancel-article
+@kindex C (\e$B35N,\e(B)
+@c @icon{gnus-summary-cancel-article}
+\e$B<h$j>C$7$?$$5-;v$r8+$D$1$F$/$@$5$$\e(B (\e$B<h$j>C$9$3$H$,$G$-$k$N$O<+J,$N5-;v$@\e(B
+\e$B$1$G$9!#JQ$J$3$H$O;n$5$J$$$G$/$@$5$$\e(B)\e$B!#$=$l$+$i!"\e(B
+@kbd{C} \e$B$+\e(B @kbd{S c} \e$B$r2!$7$F$/$@$5\e(B
+\e$B$$\e(B (@code{gnus-summary-cancel-article})\e$B!#$"$J$?$N5-;v$,<h$j>C$5$l$^\e(B
+\e$B$9!=!=@$3&Cf$N5!3#$,$"$J$?$N5-;v$r<h$j>C$7$^$9!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,\e(B
+\e$B0z?t$N=,47$rMQ$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+\e$B$7$+$7!"Cm0U$7$F$[$7$$$N$O$9$Y$F$N%5%$%H\e(B (site) \e$B$,<h$j>C$7$r07$C$F$$$k$o\e(B
+\e$B$1$G$O$J$$$3$H$G$9!#$G$9$+$i!"$?$$$F$$$N%5%$%H$,LdBj$N5-;v$r<h$j>C$7$F$b!"\e(B
+\e$B$"$A$3$A$G$"$J$?$N5-;v$O@8$-;D$k$+$b$7$l$^$;$s!#\e(B
+
+Gnus \e$B$O!"<h$j>C$9$H$-$K!X8=:_!Y$NA*BrJ}K!$r;H$$$^$9!#I8=`$NEj9FJ}K!$r;H\e(B
+\e$B$$$?$$$N$G$"$l$P!"J8;z@\F,0z?t\e(B @samp{a} \e$B$r;H$C$F$/$@$5\e(B
+\e$B$$\e(B (@pxref{Symbolic Prefixes})\e$B!#\e(B
+
+Gnus \e$B$O\e(B @code{Cancel-Lock} \e$B%X%C%@!<\e(B (@pxref{Canceling News, Canceling
+News, , message, Message Manual}) \e$B$r;H$C$F!"$"$J$?$@$1$,$"$J$?$N%a%C%;!<\e(B
+\e$B%8$r%-%c%s%;%k$G$-$k$3$H$rJ]>Z$7$^$9!#\e(B
+
+\e$B$b$72?$+4V0c$$$r$7$?$N$K5$IU$$$F!"D{@5$r$7$?$$$N$G$"$l$P!"\e(B
+@dfn{\e$BBeBX\e(B} (@dfn{superseding}) \e$B5-;v$rEj9F$7$FK\5-;v$rCV$-49$($k$3$H$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+@findex gnus-summary-supersede-article
+@kindex S (\e$B35N,\e(B)
+\e$BK\5-;v$N$H$3$m$X0\F0$7$F!"\e(B@kbd{S s} \e$B$r2!$7$F$/$@$5\e(B
+\e$B$$\e(B (@code{gnus-summary-supersede-article})\e$B!#IaDL$NJ}K!$G$=$l$rAw$kA0$K!"\e(B
+\e$B5-;v$r9%$-$J$h$&$KJT=8$9$k$3$H$,$G$-$^$9!#BeBX$K4X$7$F$b!"<h$j>C$7$HF1$8\e(B
+\e$B$3$H$,Ev$F$O$^$j$^$9!#$3$A$i$NJ}$,$b$C$H$h$/Ev$F$O$^$k$+$b$7$l$^$;\e(B
+\e$B$s\e(B: \e$B$$$/$D$+$N%5%$%H$OBeBX$r<u$1IU$1$^$;$s!#$3$l$i$N%5%$%H$G$O!"$"$J$?$,\e(B
+\e$B$[$H$s$IF1$85-;v$rFs2sEj9F$7$?$h$&$K$J$j$^$9!#\e(B
+
+\e$B$b$7$5$C$-5-;v$rEj9F$7$?$P$+$j$G$9$0$KJQ99$7$?$/$J$?>l9g!"5-;v$,:G=i$K$"\e(B
+\e$B$J$?$N%5%$%H$K8=$l$kA0$K<h$j>C$7\e(B/\e$BBeBX$r$9$k$?$a$N9*L/$J<jCJ$,$"$j$^$9!#\e(B
+\e$B$^$:!"Ej9F%P%C%U%!\e(B (@code{*sent ... *} \e$B$N$h$&$K$J$C$F$$$^$9\e(B) \e$B$KLa$j$^$9!#\e(B
+\e$B$=$3$K$O$"$J$?$,$A$g$&$IEj9F$7$?5-;v$,$"$j!"$9$Y$F$N%X%C%@!<$,$=$N$^$^$"\e(B
+\e$B$j$^$9!#$=$l$i$NCf$N\e(B @code{Message-ID} \e$B$H$$$&8l$N$H$3$m$rJQ99$9$k$3$H$K\e(B
+\e$B$h$C$F\e(B @code{Message-ID} \e$B%X%C%@!<$r\e(B @code{Cancel} \e$B$b$7$/\e(B
+\e$B$O\e(B @code{Supersedes} \e$B$KJQ99$7$F$/$@$5$$!#\e(B
+
+\e$B$A$g$C$H3P$($F$*$$$F$/$@$5$$\e(B: 'supersede' (\e$BBeBX\e(B) \e$B$H$$$&8l$NCf$K\e(B 'c' \e$B$OL5\e(B
+\e$B$$$H$$$&$3$H$r!#\e(B
+
+@node Delayed Articles
+@section \e$BCY1d5-;v\e(B
+@cindex delayed sending
+@cindex send delayed
+
+\e$B$H$-$H$7$F!"$"$J$?$O%a%C%;!<%8$NAw?.$r@h1d$P$7$K$7$?$$$H;W$&$3$H$O$"$j$^\e(B
+\e$B$;$s$+!#Nc$($P!"$"$J$?$,Bg@Z$J$@$l$+$NCB@8F|$r;W$$=P$9$?$a$K!"$A$g$&$I$=\e(B
+\e$B$NF|$KFO$/%a%C%;!<%8$rMQ0U$7$?$$$H;W$C$?$H$7$^$7$g$&!#\e(B
+@code{gnus-delay} \e$B%Q%C%1!<%8$O$3$l$K$&$C$F$D$1$G$9!#@_Dj$O4JC1$G$9\e(B:
+
+@lisp
+(gnus-delay-initialize)
+@end lisp
+
+@findex gnus-delay-article
+\e$BIaCJ$O%a%C%;!<%8$rAw?.$9$k$N$K\e(B Message \e$B%b!<%I$G\e(B @kbd{C-c C-c} \e$B%3%^%s%I$r\e(B
+\e$B;H$$$^$9$h$M!#@h1d$P$7$K$9$k$K$O!"Be$o$j$K\e(B @kbd{C-c C-j}
+(@code{gnus-delay-article}) \e$B$r;H$C$F2<$5$$!#$=$&$9$k$H!"$I$N$/$i$$CY$i$;\e(B
+\e$B$k$+$r?R$M$F$-$^$9!#2DG=$JJV;v$O<!$NDL$j$G$9\e(B:
+
+@itemize @bullet
+@item
+\e$B4|4V!#@0?t$H0l$D$NJ8;z$G;XDj$7$^$9!#Nc$($P\e(B @code{42d} \e$B$O\e(B 42 \e$BF|CY$i$;$k$3\e(B
+\e$B$H$r0UL#$7$^$9!#;H$&$3$H$,$G$-$kJ8;z$O\e(B @code{m} (\e$BJ,\e(B)\e$B!"\e(B@code{h} (\e$B;~\e(B)\e$B!"\e(B
+@code{d} (\e$BF|\e(B), @code{w} (\e$B=5\e(B), @code{M} (\e$B7n\e(B) \e$B$*$h$S\e(B @code{Y} (\e$BG/\e(B) \e$B$G$9!#\e(B
+
+@item
+\e$BF|IU!#\e(B@code{YYYY-MM-DD} \e$B$N$h$&$J7A<0$G;XDj$7$^$9!#!#%a%C%;!<%8$NAw?.$O$=\e(B
+\e$B$NF|$NFCDj$N;~9o\e(B (\e$B%G%#%U%)%k%H$O\e(B 8 \e$B;~\e(B) \e$B$^$GCY$i$;$i$l$^$9!#\e(B
+@code{gnus-delay-default-hour} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item
+\e$B;~9o!#\e(Bam/pm \e$B$r4^$^$J$$\e(B 24 \e$B;~4V@)$N!"\e(B@code{hh:mm} \e$B$N7A<0$GM?$($^$9!#Aw?.\e(B
+\e$B$5$l$k$N$O:#F|$N$=$N;~9o$G$9$,!"$9$G$K$=$N;~9o$r2a$.$F$7$^$C$F$$$?>l9g$O\e(B
+\e$BMbF|$N$=$N;~9o$K$J$j$^$9!#$G$9$+$i!"D+$N\e(B 10 \e$B;~$K\e(B @code{11:15} \e$B$r;XDj$7$?\e(B
+\e$B>l9g$O\e(B 1\e$B;~4V\e(B15\e$BJ,8e$KAw?.$5$l$k$3$H$K$J$j$^$9!#$7$+$7\e(B @code{9:20} \e$B$r;XDj\e(B
+\e$B$7$?>l9g$OMbF|$N;~9o$r0UL#$7$^$9!#\e(B
+@end itemize
+
+@code{gnus-delay-article} \e$B$NF0:n$O!"0J2<$N?t8D$NJQ?t$K1F6A$5$l$^$9\e(B:
+
+@table @code
+@item gnus-delay-default-hour
+@vindex gnus-delay-default-hour
+\e$BFCDj$NF|IU$r;XDj$7$?>l9g$K!"%a%C%;!<%8$,$=$NF|$N2?;~$KAw?.$5$l$k$+$rM?$(\e(B
+\e$B$^$9!#2DG=$JCM$O\e(B 0 \e$B$+$i\e(B 23 \e$B$^$G$N@0?t$G$9!#\e(B
+
+@item gnus-delay-default-delay
+@vindex gnus-delay-default-delay
+\e$B%G%#%U%)%k%H$NCY1d$rM?$($kJ8;zNs$G$9!#A0=R$N$I$s$J7A<0$G$b2DG=$G$9!#\e(B
+
+@item gnus-delay-group
+@vindex gnus-delay-group
+\e$BCY1d5-;v$O!"%I%i%U%H%5!<%P!<$N$3$N%0%k!<%W$K4|8B$,Mh$k$^$GJ]4I$5$l$^$9!#\e(B
+\e$B$?$V$s$"$J$?$O$3$l$rJQ99$9$kI,MW$OL5$$$G$7$g$&!#%G%#%U%)%k%H$NCM\e(B
+\e$B$O\e(B @code{"delayed"} \e$B$G$9!#\e(B
+
+@item gnus-delay-header
+@vindex gnus-delay-header
+\e$B$=$l$>$l$N5-;v$,Aw?.$5$l$kF|;~$O%X%C%@!<$K5-O?$5$l$^$9!#$3$NJQ?t$O%X%C%@!<\e(B
+\e$BL>$NJ8;zNs$G$9!#$?$V$s$"$J$?$O$3$l$rJQ99$9$kI,MW$OL5$$$G$7$g$&!#%G%#%U%)\e(B
+\e$B%k%H$NCM$O\e(B @code{"X-Gnus-Delayed"} \e$B$G$9!#\e(B
+@end table
+
+\e$BAw?.$N@h1d$P$7$O$3$s$J$U$&$K9T$J$o$l$^$9\e(B: @code{gnus-delay-article} \e$B%3%^\e(B
+\e$B%s%I$G!"$"$J$?$O$I$N$/$i$$CY$i$;$k$+$r;XDj$7$^$9!#\e(Bgnus \e$B$O%a%C%;!<%8$rAw\e(B
+\e$B?.$9$kF|;~$r7W;;$7$F\e(B @code{X-Gnus-Delayed} \e$B%X%C%@!<$K5-O?$7!"$=$N%a%C%;!<\e(B
+\e$B%8$r\e(B @code{nndraft:delayed} \e$B%0%k!<%W$KG<$a$^$9!#\e(B
+
+@findex gnus-delay-send-queue
+\e$B$=$7$F!"$"$J$?$,?7Ce%K%e!<%9$r<hF@$7$h$&$H$9$k$H$-$O$$$D$b!"\e(Bgnus \e$B$OAw?.\e(B
+\e$B$9$k4|8B$KC#$7$?5-;v$r$=$N%0%k!<%W$GC5$7$F!"$=$l$i$rAw?.$7$^$9!#$3$l$K$O\e(B
+\e$B4X?t\e(B @code{gnus-delay-send-queue} \e$B$,;H$o$l$^$9!#%G%#%U%)%k%H$G$O$3$N4X?t\e(B
+\e$B$O\e(B @code{gnus-get-new-news-hook} \e$B$KDI2C$5$l$^$9$,!"$b$A$m$s$"$J$?$O$3$l\e(B
+\e$B$rJQ99$9$k$3$H$,$G$-$^$9!#$*$=$i$/$"$J$?$O!"%I%i%U%H$NAw?.$K%G!<%b%s$r;H\e(B
+\e$B$$$?$$$H;W$&$N$G$O$J$$$G$7$g$&$+\e(B? \e$B$=$l$K$O!"%G!<%b%s$K4X\e(B
+\e$B?t\e(B @code{gnus-delay-send-queue} \e$B$r<B9T$;$h!"$H8@$&$@$1$GNI$$$N$G$9!#\e(B
+
+@table @code
+@item gnus-delay-initialize
+@findex gnus-delay-initialize
+\e$B%G%#%U%)%k%H$G$O$3$N4X?t\e(B
+\e$B$O\e(B @code{gnus-delay-send-queue} \e$B$N\e(B @code{gnus-get-new-news-hook} \e$B$X$NDI\e(B
+\e$B2C$r9T$J$$$^$9!#$G$9$,!"$3$l$OBhFs%*%W%7%g%s0z?t\e(B @code{no-check} \e$B$r<u$1\e(B
+\e$BIU$1$^$9!#$b$7$=$l$,Hs\e(B-@code{nil} \e$B$@$C$?\e(B
+\e$B$i\e(B @code{gnus-get-new-news-hook} \e$B$OJQ99$5$l$^$;$s!#Bh0l%*%W%7%g%s0z?t$O\e(B
+\e$BL5;k$5$l$^$9!#\e(B
+
+\e$BNc$($P\e(B @code{(gnus-delay-initialize nil t)} \e$B$O2?$b$7$J$$$3$H$r0UL#$7$^$9!#\e(B
+\e$B$"$J$?$OCY1d5-;v$NAw?.$K%G!<%b%s$r;H$$$?$$$N$G$7$g$&$M!#$G$b!"$=$l$r@_Dj\e(B
+\e$B$9$k$3$H$rK:$l$J$$$G2<$5$$$M!#\e(B:-)
+@end table
+
+@node Marking Articles
+@section \e$B5-;v$K0u$rIU$1$k\e(B
+@cindex article marking
+@cindex article ticking
+@cindex marks
+
+\e$B5-;v$KIU$1$i$l$k0u$O$$$/$D$+$"$j$^$9!#\e(B
+
+\e$B5-;v$N\e(B @dfn{\e$B9XFIEY\e(B} (\e$B$*$)!"$9$s$4$$?78l6g$@\e(B!) \e$B$r7hDj$9$k0u$,$"$j$^$9!#1Q\e(B
+\e$B;z$N0u$O0lHLE*$K$O\e(B @dfn{\e$B4{FI\e(B}\e$B$r0UL#$7!"1Q;z$G$J$$J8;z$O0lHLE*\e(B
+\e$B$K\e(B @dfn{\e$BL$FI\e(B}\e$B$r0UL#$7$^$9!#\e(B
+
+\e$B2C$($F!"9XFIEY$K1F6A$7$J$$0u$b$"$j$^$9!#\e(B
+
+@menu
+* Unread Articles::             \e$BL$FI5-;v$X$N0u\e(B
+* Read Articles::               \e$B4{FI5-;v$X$N0u\e(B
+* Other Marks::                 \e$B9XFIEY$K1F6A$7$J$$0u\e(B
+@end menu
+
+@ifinfo
+\e$B$3$l$i$N0u$rA`:n$9$k2a>j$J$/$i$$$NL?Na$,$"$j$^$9\e(B:
+@end ifinfo
+
+@menu
+* Setting Marks::               \e$B0u$NIU$1J}$H>C$7J}\e(B
+* Generic Mark Commands::       \e$B0u$r$I$N$h$&$K%+%9%?%^%$%:$9$k$+\e(B
+* Setting Process Marks::       \e$B8e$N<B9T$N$?$a$N5-;v$N0u$NIU$1J}\e(B
+@end menu
+
+@node Unread Articles
+@subsection \e$BL$FI5-;v\e(B
+
+\e$B0J2<$N0u$O$$$m$$$m$JJ}K!$G5-;v$KL$FI$N\e(B (\e$B$h$&$J\e(B) \e$B0u$rIU$1$^$9!#\e(B
+
+@table @samp
+@item !
+@vindex gnus-ticked-mark
+\e$B2D;k5-;v\e(B (Ticked) \e$B$H$7$F0u$r$D$1$^$9\e(B (@code{gnus-ticked-mark})\e$B!#\e(B
+
+@dfn{\e$B2D;k5-;v\e(B}\e$B$H$O!">o$K2D;k>uBV$G$"$k5-;v$N$3$H$G$9!#$*$b$7$m$$$H;W$&5-\e(B
+\e$B;v$,$"$C$?>l9g$d!"C1$KFI$`$N$r@h$K1d$P$7$?$$$H$-$d!"8e$GJVEz$r$7$?$$$H$-\e(B
+\e$B$K!"IaDL$O2D;k0u$rIU$1$^$9!#$7$+$7!"5-;v$O4|8B@Z$l>C5n$5$l$k$3$H$b$"$j$^\e(B
+\e$B$9\e(B (\e$B%K%e!<%9%5!<%P!<$N%=%U%H%&%'%"$,%K%e!<%9%5!<%P!<>e$N5-;v$r>C5n!"\e(B
+gnus \e$B<+BN$O2D;k5-;v$r4|8B@Z$l>C5n$7$^$;$s\e(B) \e$B$N$G!"1J1s$K5-;v$rJ]B8$7$F$*\e(B
+\e$B$-$?$$>l9g$O!"$=$N5-;v$r1JB3$K$9$kI,MW$,$"$j$^\e(B
+\e$B$9\e(B (@pxref{Persistent Articles})\e$B!#\e(B
+
+@item ?
+@vindex gnus-dormant-mark
+\e$BJ]N1$H$7$F0u$rIU$1$^$9\e(B (@code{gnus-dormant-mark})\e$B!#\e(B
+
+@dfn{\e$BJ]N15-;v\e(B}\e$B$O%U%)%m!<%"%C%W$,$"$C$?$H$-$K$@$135N,%P%C%U%!$K8=$l$^$9!#\e(B
+\e$B%U%)%m!<%"%C%W$,L5$$$H$-$bI=<($5$;$?$$$H$-$O!"L?Na\e(B @kbd{/ D} \e$B$r;H$&$3$H\e(B
+\e$B$,$G$-$^$9!#$=$l0J30$O\e(B (\e$B8+$($k$+$I$&$+$OJL$K$7$F\e(B)\e$B!"2D;k5-;v\e(B (Ticked) \e$B$H\e(B
+\e$B;w$?$h$&$J$b$N$G$9!#\e(B
+
+@item SPACE
+@vindex gnus-unread-mark
+\e$BL$FI$H$7$F0u$rIU$1$^$9\e(B (@code{gnus-unread-mark})\e$B!#\e(B
+
+@dfn{\e$BL$FI5-;v\e(B}\e$B$O:#$^$GA4$/FI$^$l$F$$$J$$5-;v$N$3$H$G$9!#\e(B
+@end table
+
+@node Read Articles
+@subsection \e$B4{FI5-;v\e(B
+@cindex expirable mark
+
+\e$B0J2<$N$9$Y$F$N0u$O5-;v$K4{FI$N0u$rIU$1$^$9!#\e(B
+
+@table @samp
+@item r
+@vindex gnus-del-mark
+\e$BMxMQ<T$,<jF0$d$=$N$h$&$J$b$N$GL?Na\e(B @kbd{d} \e$B$K$h$C$F4{FI$N0u$rIU$1$?5-;v\e(B
+\e$B$G$9\e(B (@code{gnus-del-mark})\e$B!#\e(B
+
+@item R
+@vindex gnus-read-mark
+\e$B<B:]$KFI$^$l$?5-;v\e(B (@code{gnus-read-mark})\e$B!#\e(B
+
+@item O
+@vindex gnus-ancient-mark
+\e$BA02s$N%;%C%7%g%s$G4{FI$N0u$rIU$1$F!":#$O\e(B@dfn{\e$B8E$/\e(B}\e$B$J$C$F$7$^$C$?5-;v!#\e(B
+
+@item K
+@vindex gnus-killed-mark
+\e$B:o=|$N0u\e(B (@code{gnus-killed-mark})\e$B!#\e(B
+
+@item X
+@vindex gnus-kill-file-mark
+\e$B:o=|%U%!%$%k$K$h$C$F:o=|$N0u$,$D$$$?5-\e(B
+\e$B;v\e(B (@code{gnus-kill-file-mark})\e$B!#\e(B
+
+@item Y
+@vindex gnus-low-score-mark
+\e$BDc$9$.$k%9%3%"$N$?$a$K4{FI$N0u$,$D$$$?5-\e(B
+\e$B;v\e(B (@code{gnus-low-score-mark})\e$B!#\e(B
+
+@item C
+@vindex gnus-catchup-mark
+\e$B%-%c%C%A%"%C%W$K$h$C$F4{FI$N0u$,$D$$$?5-\e(B
+\e$B;v\e(B (@code{gnus-catchup-mark})\e$B!#\e(B
+
+@item G
+@vindex gnus-canceled-mark
+\e$B<h$j>C$5$l$?5-;v\e(B (@code{gnus-canceled-mark})\e$B!#\e(B
+
+@item F
+@vindex gnus-souped-mark
+@sc{soup} \e$B$5$l$F$$$k5-;v\e(B (@code{gnus-souped-mark})\e$B!#\e(B@xref{SOUP}.
+
+@item Q
+@vindex gnus-sparse-mark
+\e$B$^$P$i$K;2>H$5$l$?5-;v\e(B (@code{gnus-sparse-mark})\e$B!#\e(B
+@xref{Customizing Threading}.
+
+@item M
+@vindex gnus-duplicate-mark
+\e$B=EJ#M^@)$K$h$j4{FI$N0u$N$D$$$?5-;v\e(B (@code{gnus-duplicate-mark})\e$B!#\e(B
+@xref{Duplicate Suppression}.
+@end table
+
+\e$B$3$l$i$N$9$Y$F$N0u$O!"K\Ev$O$?$@5-;v$,4{FI$H$7$F0u$,$D$$$F$$$k$3$H$r0UL#\e(B
+\e$B$9$k$@$1$G$9!#E,1~%9%3%"%j%s%0$r$7$?$H$-$K$O0c$C$?$h$&$K2r<a$5$l$^$9$1$l\e(B
+\e$B$I!#\e(B
+
+\e$B$b$&0l$D!"FCJL$J0u$,$"$j$^$9\e(B:
+
+@table @samp
+@item E
+@vindex gnus-expirable-mark
+\e$B4|8B@Z$l:o=|2DG=$H$7$F0u$N$D$$$?5-;v\e(B (@code{gnus-expirable-mark})\e$B!#\e(B
+
+\e$B5-;v$r\e(B @dfn{\e$B4|8B@Z$l:o=|2DG=\e(B} \e$B$H$7$F0u$rIU$1$k\e(B (\e$B$b$7$/$O!"<+F0E*$K$=$N$h\e(B
+\e$B$&$K0u$rIU$1$k\e(B) \e$B$3$H$O!"IaDL$N%0%k!<%W$G$O$"$^$j0UL#$,$"$j$^$;$s!=!=MxMQ\e(B
+\e$B<T$O%K%e!<%:5-;v$N4|8B$K$h$k:o=|$r@)8f$7$F$$$^$;$s!#$7$+$7!"Nc$($P%a!<%k\e(B
+\e$B%0%k!<%W$G$O!"\e(B@dfn{\e$B4|8B@Z$l:o=|2DG=\e(B} \e$B$H$7$F0u$N$D$$$?5-;v$O!"$$$D$G\e(B
+\e$B$b\e(B gnus \e$B$K$h$C$F:o=|$5$l$k$3$H$,$"$j$^$9!#\e(B
+@end table
+
+@node Other Marks
+@subsection \e$BB>$N0u\e(B
+@cindex process mark
+@cindex bookmarks
+
+\e$B5-;v$,FI$^$l$?$+$I$&$+$K$O4X78$7$J$$0u$,$$$/$D$+$"$j$^$9!#\e(B
+
+@itemize @bullet
+
+@item
+\e$B8=:_$N5-;v$K$7$*$j$r64$`$3$H$,$G$-$^$9!#$"$J$?$OG-$NG"$N=,47$K4X$9$kD9$$\e(B
+\e$BO@J8$rFI$s$G$$$F!"$=$l$rFI$_=*$o$kA0$KM<?)$r?)$Y$k$?$a$K2H$K5"$i$J$1$l$P\e(B
+\e$B$J$i$J$+$C$?$H$7$^$7$g$&!#$=$N$H$-$K!"5-;v$K$7$*$j$r64$`$3$H$,$G$-!"<!$K\e(B
+\e$B$=$N5-;v$K=P$/$o$7$?$H$-$K!"\e(Bgnus \e$B$O$=$N$7$*$j$N$H$3$m$X0\F0$9$k$G$7$g$&!#\e(B
+@xref{Setting Marks}.
+
+@item
+@vindex gnus-replied-mark
+\e$BJVEz$r$7$?$+%U%)%m!<%"%C%W$r$7$?\e(B (\e$BNc$($PEz$($?\e(B) \e$B5-;v$O!"$9$Y$FFs7eL\\e(B
+\e$B$K\e(B @samp{A} \e$B$N0u$,IU$-$^$9\e(B (@code{gnus-replied-mark})\e$B!#\e(B
+
+@item
+@vindex gnus-forwarded-mark
+\e$BE>Aw$7$?5-;v$O!"$9$Y$FFs7eL\$K\e(B @samp{F} \e$B$N0u$,IU$-$^\e(B
+\e$B$9\e(B (@code{gnus-forwarded-mark})\e$B!#\e(B
+
+@item
+@vindex gnus-cached-mark
+\e$B5-;v%-%c%C%7%e$KCy$a$i$l$F$$$k5-;v$O!"Fs7eL\$K\e(B @samp{*} \e$B$N0u$,IU$-$^\e(B
+\e$B$9\e(B (@code{gnus-replied-mark})\e$B!#\e(B@xref{Article Caching}.
+
+@item
+@vindex gnus-saved-mark
+(\e$B2?$i$+$NJ}K!$K$h$C$F!(I,$:$7$b=!65E*$H$$$&$o$1$G$O$J$/\e(B) \e$B!XJ]B8$5$l$?!Y\e(B
+\e$B5-;v$O!"Fs7eL\$K\e(B @samp{S} \e$B$N0u$,IU$-$^$9\e(B (@code{gnus-saved-mark})\e$B!#\e(B
+
+@vindex gnus-recent-mark
+\e$B$=$N%5!<%P!<$G$^$@FI$^$l$F$$$J$$5-;v$O!"Fs7eL\$K\e(B @samp{N} \e$B$N0u$,IU$-$^\e(B
+\e$B$9\e(B (@code{gnus-recent-mark})\e$B!#$?$$$F$$$N%5!<%P!<$O$3$N0u$r%5%]!<%H$;$:!"\e(B
+\e$B$=$N>l9g$OC1$KI=<($5$l$^$;$s!#\e(B@code{gnus-unseen-mark} \e$B$H8+Hf$Y$F2<$5$$!#\e(B
+
+@item
+@vindex gnus-unseen-mark
+\e$B$^$@\e(B gnus \e$B$GFI$^$l$?$3$H$,$J$$5-;v$O!"Fs7eL\$K\e(B @samp{.} \e$B$N0u$,IU$-$^\e(B
+\e$B$9\e(B (@code{gnus-unseen-mark})\e$B!#\e(B@code{gnus-recent-mark} \e$B$H8+Hf$Y$F2<$5$$!#\e(B
+
+@item
+@vindex gnus-downloaded-mark
+gnus \e$B%(!<%8%'%s%H\e(B (@pxref{Agent Basics}) \e$B$r;H$C$F$$$k$H$-!"5-;v\e(B
+\e$B$O\e(B unplugged (\e$B%*%U%i%$%s\e(B) \e$B$G8+$k$?$a$K%@%&%s%m!<%I$5$l$F$$$k$+$b$7$l$^$;\e(B
+\e$B$s!#\e(B@samp{%O} \e$B$N;EMM$r;H$C$F$$$k$H!"$=$l$i$N5-;v$K$O$=$N;EMM\e(B
+\e$B$K\e(B @samp{+} \e$B$N0u$,IU$-$^$9!#\e(B(\e$BJQ?t\e(B @code{gnus-downloaded-mark} \e$B$G$I$NJ8;z\e(B
+\e$B$r;H$&$+$r@)8f$7$^$9!#\e(B)
+
+@item
+@vindex gnus-undownloaded-mark
+gnus \e$B%(!<%8%'%s%H\e(B (@pxref{Agent Basics}) \e$B$r;H$C$F$$$k$H$-!"$$$/$D$+$N5-\e(B
+\e$B;v$O%@%&%s%m!<%I$5$l$F$$$J$$$+$b$7$l$^$;$s!#\e(BUnplugged (\e$B%*%U%i%$%s\e(B) \e$B$N>u\e(B
+\e$BBV$G$O$=$N$h$&$J5-;v$r8+$k$3$H$,$G$-$^$;$s!#\e(B@samp{%O} \e$B$N;EMM$r;H$C$F$$$k\e(B
+\e$B$H!"$=$l$i$N5-;v$K$O$=$N;EMM$K\e(B @samp{-} \e$B$N0u$,IU$-$^$9!#\e(B(\e$BJQ\e(B
+\e$B?t\e(B @code{gnus-undownloaded-mark} \e$B$G$I$NJ8;z$r;H$&$+$r@)8f$7$^$9!#\e(B)
+
+@item
+@vindex gnus-downloadable-mark
+gnus \e$B%(!<%8%'%s%H\e(B (@pxref{Agent Basics}) \e$B$O$$$/$D$+$N5-;v$r<+F0E*$K%@%&\e(B
+\e$B%s%m!<%I$7$^$9$,!"<+F0E*$K%@%&%s%m!<%I$5$l$J$$5-;v$K$b%@%&%s%m!<%I$N$?$a\e(B
+\e$B$NL@<(E*$J0u$rIU$1$k$3$H$O2DG=$G$9!#$=$N$h$&$JL@<(E*$K0u$,IU$1$i$l$?5-;v\e(B
+\e$B$K$O!":G=i$N7e$K\e(B @samp{%} \e$B$N0u$,IU$-$^$9!#\e(B(\e$BJQ\e(B
+\e$B?t\e(B @code{gnus-downloadable-mark} \e$B$G$I$NJ8;z$r;H$&$+$r@)8f$7$^$9!#\e(B)
+
+@item
+@vindex gnus-not-empty-thread-mark
+@vindex gnus-empty-thread-mark
+\e$B$b$7\e(B @samp{%e} \e$B$N;EMM$,;H$o$l$k$H!"%9%l%C%I$,$"$k$+$I$&$+$O!";07eL\\e(B
+\e$B$K\e(B @code{gnus-not-empty-thread-mark} \e$B$H\e(B @code{gnus-empty-thread-mark} \e$B$N\e(B
+\e$B$=$l$>$l$K$h$C$F0u$,IU$-$^$9!#\e(B
+
+@item
+@vindex gnus-process-mark
+\e$B:G8e$K\e(B @dfn{\e$B%W%m%;%90u\e(B} \e$B$,$"$j$^$9\e(B(@code{gnus-process-mark})\e$B!#$$$m$$$m$J\e(B
+\e$B<oN`$NL?Na$,%W%m%;%90u$,$"$k$H$=$l$KBP$7$F<B9T$5$l$^$9!#Nc$($P!"\e(B
+@kbd{X u} (@code{gnus-uu-decode-uu}) \e$B$O%W%m%;%90u$NIU$$$?$9$Y$F$N5-;v\e(B
+\e$B$r\e(B uudecode \e$B$7$F!"I=<($7$^$9!#%W%m%;%90u$NIU$$$?5-;v$OFs7eL\\e(B
+\e$B$K\e(B @samp{#} \e$B$,$"$j$^$9!#\e(B
+@end itemize
+
+\e$B$3$l$i$N!XHs9XFIEY!Y$N0u$O=i4|@_Dj$G$O$?$$$F$$Fs7eL\$K8=$l$k$H$$$&$3$H$K\e(B
+\e$B5$IU$$$?$+$b$7$l$^$;$s!#$G$9$+$i!"%-%c%C%7%e$5$l$F$$$F!"J]B8$5$l$F$$$F!"\e(B
+\e$BJVEz$r$7$?5-;v$K%W%m%;%90u$,IU$$$F$$$k>l9g!"$I$N$h$&$K$J$k$N$G$7$g$&\e(B?
+
+\e$B$?$$$7$?$3$H$O$"$j$^$;$s!#M%@h=g0L$O<!$N$h$&$K$J$C$F$$$^$9\e(B: \e$B%W%m%;\e(B
+\e$B%9\e(B \e$B"*\e(B \e$B%-%c%C%7%e\e(B \e$B"*\e(B \e$BJVEz:Q$_\e(B \e$B"*\e(B \e$BJ]B8!#$G$9$+$i!"$"$k5-;v$,%-%c%C%7%e$KF~$C\e(B
+\e$B$F$$$F!"JVEz$5$l$F$$$?>l9g!"%-%c%C%7%e0u$,$"$k$@$1$G!"JVEz:Q$_0u$O$"$j$^\e(B
+\e$B$;$s!#\e(B
+
+@node Setting Marks
+@subsection \e$B0u$rIU$1$k\e(B
+@cindex setting marks
+
+\e$B$9$Y$F$N0u$D$1L?Na$O?tCM@\F,0z?t$r<u$1IU$1$^$9!#\e(B
+
+@table @kbd
+@item M c
+@itemx M-u
+@kindex M c (\e$B35N,\e(B)
+@kindex M-u (\e$B35N,\e(B)
+@findex gnus-summary-clear-mark-forward
+@cindex mark as read
+\e$B8=:_$N5-;v$+$i!"$9$Y$F$N9XFIEY0u$r>C5n$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-clear-mark-forward})\e$B!#MW$9$k$K!"5-;v$KL$FI$N0u$r\e(B
+\e$BIU$1$^$9!#\e(B
+
+@item M t
+@itemx !
+@kindex ! (\e$B35N,\e(B)
+@kindex M t (\e$B35N,\e(B)
+@findex gnus-summary-tick-article-forward
+\e$B8=:_$N5-;v$K2D;k5-;v0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-tick-article-forward})\e$B!#\e(B@xref{Article Caching}.
+
+@item M ?
+@itemx ?
+@kindex ? (\e$B35N,\e(B)
+@kindex M ? (\e$B35N,\e(B)
+@findex gnus-summary-mark-as-dormant
+\e$B8=:_$N5-;v$KJ]N15-;v0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mark-as-read-forward})\e$B!#\e(B@xref{Article Caching}.
+
+@item D
+@kindex D (\e$B35N,\e(B)
+@findex gnus-summary-mark-as-read-backward
+\e$B8=:_$N5-;v$K4{FI$N0u$rIU$1!"A0$N9T$K%]%$%s%H$r0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mark-as-read-backward})\e$B!#\e(B
+
+@item M k
+@itemx k
+@kindex k (\e$B35N,\e(B)
+@kindex M k (\e$B35N,\e(B)
+@findex gnus-summary-kill-same-subject-and-select
+\e$B8=:_$N5-;v$HF1$8I=Bj$r;}$D$9$Y$F$N5-;v$r4{FI$H$7$F0u$rIU$1!"<!$NL$FI5-;v\e(B
+\e$B$rA*Br$7$^$9\e(B (@code{gnus-summary-kill-same-subject-and-select})\e$B!#\e(B
+
+@item M K
+@itemx C-k
+@kindex M K (\e$B35N,\e(B)
+@kindex C-k (\e$B35N,\e(B)
+@findex gnus-summary-kill-same-subject
+\e$B8=:_$N5-;v$HF1$8I=Bj$r;}$D$9$Y$F$N5-;v$r4{FI$H$7$F0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-kill-same-subject})\e$B!#\e(B
+
+@item M C
+@kindex M C (\e$B35N,\e(B)
+@findex gnus-summary-catchup
+@c @icon{gnus-summary-catchup}
+\e$B$9$Y$F$NL$FI5-;v$K4{FI$N0u$rIU$1$^$9\e(B (@code{gnus-summary-catchup})\e$B!#\e(B
+
+@item M C-c
+@kindex M C-c (\e$B35N,\e(B)
+@findex gnus-summary-catchup-all
+\e$B%0%k!<%W$N$9$Y$F$N5-;v$K!=!=2D;k5-;v$dJ]N15-;v$G$5$($b!"4{FI$N0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-catchup-all})\e$B!#\e(B
+
+@item M H
+@kindex M H (\e$B35N,\e(B)
+@findex gnus-summary-catchup-to-here
+\e$B8=:_$N%0%k!<%W$N!"8=:_0LCV$H$=$l0JA0$N5-;v$r4{FI$H$7$F0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-catchup-to-here})\e$B!#\e(B
+
+@item M h
+@kindex M h (\e$B35N,\e(B)
+@findex gnus-summary-catchup-from-here
+\e$B8=:_$N%0%k!<%W$N!"8=:_0LCV$H$=$l0J9_$N5-;v$r4{FI$H$7$F0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-catchup-from-here})\e$B!#\e(B
+
+@item C-w
+@kindex C-w (\e$B35N,\e(B)
+@findex gnus-summary-mark-region-as-read
+\e$B%]%$%s%H$H%^!<%/$N4V$N5-;v$K4{FI$N0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mark-region-as-read})\e$B!#\e(B
+
+@item M V k
+@kindex M V k (\e$B35N,\e(B)
+@findex gnus-summary-kill-below
+\e$B=i4|@_Dj$N%9%3%"\e(B (\e$B$b$7$/$O?tCM@\F,0z?t\e(B) \e$B$h$j$bDc$$%9%3%"$N5-;v$r:o=|$7$^\e(B
+\e$B$9!#\e(B
+
+@item M e
+@itemx E
+@kindex M e (\e$B35N,\e(B)
+@kindex E (\e$B35N,\e(B)
+@findex gnus-summary-mark-as-expirable
+\e$B8=:_$N5-;v$r4|8B@Z$l:o=|2DG=$H$7$F0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mark-as-expirable})\e$B!#\e(B
+
+@item M b
+@kindex M b (\e$B35N,\e(B)
+@findex gnus-summary-set-bookmark
+\e$B8=:_$N5-;v$K$7$*$j$r@_Dj$7$^$9\e(B (@code{gnus-summary-set-bookmark})\e$B!#\e(B
+
+@item M B
+@kindex M B (\e$B35N,\e(B)
+@findex gnus-summary-remove-bookmark
+\e$B8=:_$N5-;v$N$7$*$j$r:o=|$7$^$9\e(B (@code{gnus-summary-remobe-bookmark})\e$B!#\e(B
+
+@item M V c
+@kindex M V c (\e$B35N,\e(B)
+@findex gnus-summary-clear-above
+\e$B=i4|@_Dj$N%9%3%"\e(B (\e$B$b$7$/$O?tCM@\F,0z?t\e(B) \e$B$h$j$bBg$-$$%9%3%"$r;}$D5-;v$N$9\e(B
+\e$B$Y$F$N0u$r>C5n$7$^$9\e(B (@code{gnus-summary-clar-above})\e$B!#\e(B
+
+@item M V u
+@kindex M V u (\e$B35N,\e(B)
+@findex gnus-summary-tick-above
+\e$B=i4|@_Dj$N%9%3%"\e(B (\e$B$b$7$/$O?tCM@\F,0z?t\e(B) \e$B$h$j$bBg$-$$%9%3%"$r;}$D$9$Y$F$N\e(B
+\e$B5-;v$K2D;k0u$rIU$1$^$9\e(B (@code{gnus-summary-tick-above})\e$B!#\e(B
+
+@item M V m
+@kindex M V m (\e$B35N,\e(B)
+@findex gnus-summary-mark-above
+\e$B0u$NF~NO$rB%$7!"=i4|@_Dj$N%9%3%"\e(B (\e$B$b$7$/$O?tCM@\F,0z?t\e(B) \e$B$h$j$bBg$-$J%9%3\e(B
+\e$B%"$r;}$D$9$Y$F$N5-;v$K$=$N0u$rIU$1$^$9\e(B (@code{gnus-summary-mark-above})\e$B!#\e(B
+@end table
+
+@vindex gnus-summary-goto-unread
+\e$BJQ?t\e(B @code{gnus-summary-goto-unread} \e$B$O0u$,IU$1$i$l$?8e$K$I$N$h$&$JF0:n\e(B
+\e$B$,$J$5$l$k$+$r7hDj$7$^$9!#$b$7\e(B @code{nil} \e$B$G$J$$$H!"%]%$%s%H$O<!\e(B/\e$BA0$NL$\e(B
+\e$BFI5-;v$K0\F0$7$^$9!#$b$7\e(B @code{nil} \e$B$G$"$k$H!"%]%$%s%H$O0l9T>e$+2<$K9T$/\e(B
+\e$B$@$1$G$9!#FCJL$J>l9g$H$7$F!"$3$NJQ?t$,\e(B @code{never} \e$B$G$"$k$H!"$9$Y$F$N0u\e(B
+\e$B$rIU$1$kL?Na$H\e(B (@kbd{SPACE} \e$B$N$h$&$J\e(B) \e$BB>$NL?Na$O<!$N5-;v$,L$FI$G$"$m$&$,\e(B
+\e$BL5$+$m$&$,$=$N5-;v$K0\F0$7$^$9!#=i4|CM\e(B @code{t} \e$B$G$9!#\e(B
+
+@node Generic Marking Commands
+@subsection Generic Marking Commands
+
+\e$B5-;v$K2D;k0u$rIU$1$kL?Na\e(B (@kbd{!}) \e$B$K<!$N5-;v$K0\F0$7$F$b$i$$$?$$$H$$$&\e(B
+\e$B?M$,$$$^$9!#<!$NL$FI5-;v$K0\F0$7$F$b$i$$$?$$$H;W$&?M$b$$$^$9!#$^$?!"B>$N\e(B
+\e$B8=:_$N5-;v$KN1$^$C$F$b$i$$$?$$?M$b$$$k$G$7$g$&!#$=$7$F!"$^$@A0$N\e(B (\e$BL$\e(B
+\e$BFI\e(B) \e$B5-;v$K9T$C$F$[$7$$?M$,$$$k$H$OJ9$$$?$3$H$O$"$j$^$;$s$,!"$=$&$7$?$$$H\e(B
+\e$B;W$&?M$b4V0c$$$J$/$$$k$H;W$$$^$9!#\e(B
+
+\e$B$3$N8^$D$NF0:n$r8^$D$N0c$C$?0uIU$1L?Na$H3]$1;;$9$k$H!"$I$NL?Na$,2?$r$9$Y\e(B
+\e$B$-$+$NHs>o$KJ#;($JJQ?t$NAH$r$b$D$3$H$K$J$j$^$9!#\e(B
+
+\e$B$3$NHa7`$+$iF($l$k$?$a$K!"\e(Bgnus \e$B$O$3$l$i$9$Y$F$N0c$C$?$3$H$r$9$kL?Na$rDs\e(B
+\e$B6!$7$^$9!#$3$l$i$O35N,%P%C%U%!$N\e(B @kbd{M M} \e$B%^%C%W$K$"$j$^$9!#A4$F$r$_$k\e(B
+\e$B$?$a$K$O\e(B @kbd{M M C-h} \e$B$rF~NO$7$F$/$@$5$$\e(B---\e$B$3$N%^%K%e%"%k$G0lMw$r=P$9$K\e(B
+\e$B$OB?2a$.$^$9!#\e(B
+
+\e$B$3$l$i$NL?Na$rD>@\;H$&$3$H$O$G$-$^$9$,!"$[$H$s$I$NMxMQ<T$O35N,%b!<%I$N%-!<\e(B
+\e$B%^%C%W$r8r49$9$kJ}$r9%$`$G$7$g$&!#Nc$($P!"\e(B@kbd{!} \e$BL?Na$K<!$NL$FI5-;v$NBe\e(B
+\e$B$o$j$K<!$N5-;v$K0\F0$7$F$[$7$$$H$9$k$H!"$3$N$h$&$J$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'my-alter-summary-map)
+(defun my-alter-summary-map ()
+  (local-set-key "!" 'gnus-summary-put-mark-as-ticked-next))
+@end lisp
+
+@noindent
+\e$B$b$7$/$O!"\e(B
+
+@lisp
+(defun my-alter-summary-map ()
+  (local-set-key "!" "MM!n"))
+@end lisp
+
+@node Setting Process Marks
+@subsection \e$B%W%m%;%90u$rIU$1$k\e(B
+@cindex setting process marks
+
+\e$B%W%m%;%90u$O35N,%P%C%U%!!<$K\e(B @code{#} \e$B$H$7$FI=<($5$l!"B>$N%3%^%s%I$G=hM}\e(B
+\e$B$5$;$k5-;v$K0u$rIU$1$k$?$a$K;H$o$l$^$9!#Nc$($P!";M$D$N5-;v$K$K0u$rIU$1$F\e(B
+\e$B$+$i\e(B @kbd{*} \e$B%3%^%s%I$r;H$&$H!"\e(Bgnus \e$B$O$=$l$i;M$D$N5-;v$r%-%c%C%7%e$KF~$l\e(B
+\e$B$^$9!#>\$7$/$O\e(B @ref{Process/Prefix} \e$B$r$I$&$>!#\e(B
+
+@table @kbd
+@item M P p
+@itemx #
+@kindex # (\e$B35N,\e(B)
+@kindex M P p (\e$B35N,\e(B)
+@findex gnus-summary-mark-as-processable
+\e$B8=:_$N5-;v$K%W%m%;%90u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-mark-as-processable})\e$B!#\e(B
+@findex gnus-summary-unmark-as-processable
+
+@item M P u
+@itemx M-#
+@kindex M P u (\e$B35N,\e(B)
+@kindex M-# (\e$B35N,\e(B)
+\e$B$b$78=:_$N5-;v$K%W%m%;%90u$,$"$l$P<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-summary-unmark-as-processable})\e$B!#\e(B
+
+@item M P U
+@kindex M P U (\e$B35N,\e(B)
+@findex gnus-summary-unmark-all-processable
+\e$B$9$Y$F$N5-;v$+$i%W%m%;%90u$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-summary-unmark-all-processable})\e$B!#\e(B
+
+@item M P i
+@kindex M P i (\e$B35N,\e(B)
+@findex gnus-uu-invert-processable
+\e$B%W%m%;%90u$NIU$$$F$$$k5-;v$H$=$&$G$J$$5-;v$r5U$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-by-regexp})\e$B!#\e(B
+
+@item M P R
+@kindex M P R (\e$B35N,\e(B)
+@findex gnus-uu-mark-by-regexp
+\e$B@55,I=8=$K$h$C$F5-;v$K0u$rIU$1$^$9\e(B (@code{gnus-uu-mark-by-regexp})\e$B!#\e(B
+
+@item M P G
+@kindex M P G (\e$B35N,\e(B)
+@findex gnus-uu-unmark-by-regexp
+@code{Subject} \e$B$,@55,I=8=$K%^%C%A$9$k5-;v$+$i0u$r:o=|$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-unmark-by-regexp})\e$B!#\e(B
+
+@item M P r
+@kindex M P r (\e$B35N,\e(B)
+@findex gnus-uu-mark-region
+\e$B%j!<%8%g%s$N5-;v$K0u$rIU$1$^$9\e(B (@code{gnus-uu-mark-region})\e$B!#\e(B
+
+@item M P g
+@kindex M P g (\e$B35N,\e(B)
+@findex gnus-uu-unmark-region
+\e$B%j!<%8%g%s$N5-;v$+$i0u$r:o=|$7$^$9\e(B (@code{gnus-uu-unmark-region})\e$B!#\e(B
+
+@item M P t
+@kindex M P t (\e$B35N,\e(B)
+@findex gnus-uu-mark-thread
+\e$B8=:_$N\e(B (\e$BI{\e(B) \e$B%9%l%C%I$N$9$Y$F$N5-;v$K0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-thread})\e$B!#\e(B
+
+@item M P T
+@kindex M P T (\e$B35N,\e(B)
+@findex gnus-uu-unmark-thread
+\e$B8=:_$N\e(B (\e$BI{\e(B) \e$B%9%l%C%I$N$9$Y$F$N5-;v$+$i0u$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-uu-unamrk-thread})\e$B!#\e(B
+
+@item M P v
+@kindex M P v (\e$B35N,\e(B)
+@findex gnus-uu-mark-over
+\e$B@\F,0z?t$h$j$bBg$-$J%9%3%"$r;}$D$9$Y$F$N5-;v$K0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-over})\e$B!#\e(B
+
+@item M P s
+@kindex M P s (\e$B35N,\e(B)
+@findex gnus-uu-mark-series
+\e$B8=:_$N0lO"$N5-;v$K0u$rIU$1$^$9\e(B (@code{gnus-uu-mark-series})\e$B!#\e(B
+
+@item M P S
+@kindex M P S (\e$B35N,\e(B)
+@findex gnus-uu-mark-sparse
+\e$B4{$K$$$/$D$+0u$NIU$$$?5-;v$r;}$D0lO"$N5-;v72A4$F$K0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-sparse})\e$B!#\e(B
+
+@item M P a
+@kindex M P a (\e$B35N,\e(B)
+@findex gnus-uu-mark-all
+\e$B0lO"$N5-;v$,=P$F$/$k=gHV$K$=$l$KB0$9$k$9$Y$F$N5-;v$K0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-all})\e$B!#\e(B
+
+@item M P b
+@kindex M P b (\e$B35N,\e(B)
+@findex gnus-uu-mark-buffer
+\e$B%P%C%U%!$N$9$Y$F$N5-;v$r8=$l$F$$$k=gHV$K0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-buffer})\e$B!#\e(B
+
+@item M P k
+@kindex M P k (\e$B35N,\e(B)
+@findex gnus-summary-kill-process-mark
+\e$B8=:_$N%W%m%;%90u$r%9%?%C%/$K@Q$s$G!"$9$Y$F$N5-;v$rL50u$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-kill-process-mark})\e$B!#\e(B
+
+@item M P y
+@kindex M P y (\e$B35N,\e(B)
+@findex gnus-summary-yank-process-mark
+\e$B%9%?%C%/$+$iA02s$N%W%m%;%90u$r<h$j=P$7$F!"$=$l$rI|85$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-yank-process-mark})\e$B!#\e(B
+
+@item M P w
+@kindex M P w (\e$B35N,\e(B)
+@findex gnus-summary-save-process-mark
+\e$B8=:_$N%W%m%;%90u$r%9%?%C%/$K@Q$_$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-process-mark})\e$B!#\e(B
+@end table
+
+\e$B$=$7$F!"$I$&$d$C$F5-;v$NK\J8\e(B (body) \e$B$NFbMF$r4p$K%W%m%;%90u$rIU$1$k$+$O!"\e(B
+@ref{Searching for Articles} \e$B$N\e(B @kbd{&} \e$BL?Na$r;2>H$7$F2<$5$$!#\e(B
+
+@node Limiting
+@section \e$B@)8B$r$9$k\e(B
+@cindex  limiting
+
+\e$B35N,%P%C%U%!$,8=:_%0%k!<%W$K$"$k5-;v$N0lIt$@$1$rI=<($9$k$h$&$K@)8B$G$-$l\e(B
+\e$B$PJXMx$J$3$H$,$"$j$^$9!#B?$/$N@)8BL?Na$,;}$D8z2L$O35N,%P%C%U%!$+$i>/\e(B
+\e$B$7\e(B (\e$B$b$7$/$OB?$/\e(B) \e$B$N5-;v$r35N,%P%C%U%!$+$i:o=|$9$k$3$H$G$9!#\e(B
+
+\e$B$9$Y$F$N@)8BL?Na$O%5!<%P!<$+$i4{$K<hF@$5$l$?5-;v$N0lItJ,$K:nMQ$7$^$9!#$3\e(B
+\e$B$l$i$NL?Na$O$I$l$b%5!<%P!<$KDI2C$N5-;v$rMW5a$7$^$;$s!#\e(B
+
+@table @kbd
+@item / /
+@itemx / s
+@kindex / / (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-subject
+\e$B35N,%P%C%U%!$r$$$/$D$+$NI=Bj$H9gCW$9$k$b$N$@$1$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-subject})\e$B!#$b$7@\F,<-$,M?$($i$l$l$P!"9g\e(B
+\e$BCW$9$k5-;v$r=|30$7$^$9!#\e(B
+
+@item / a
+@kindex / a (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-author
+\e$B35N,%P%C%U%!$r2??M$+$NCx<T$K9gCW$9$k$b$N$@$1$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-author})\e$B!#$b$7@\F,<-$,M?$($i$l$l$P!"9gCW\e(B
+\e$B$9$k5-;v$r=|30$7$^$9!#\e(B
+
+@item / x
+@kindex / x (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-extra
+``\e$BDI2C\e(B'' \e$B$N%X%C%@!<$N0l$D$K9gCW$9$k5-;v$K35N,%P%C%U%!$r@)8B$7$^\e(B
+\e$B$9\e(B (@pxref{To From Newsgroups}) (@code{gnus-summary-limit-to-extra})\e$B!#$b\e(B
+\e$B$7@\F,<-$,M?$($i$l$l$P!"9gCW$9$k5-;v$r=|30$7$^$9!#\e(B
+
+@item / u
+@itemx x
+@kindex / u (\e$B35N,\e(B)
+@kindex x (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-unread
+\e$B35N,%P%C%U%!$r4{FI$N0u$,IU$$$F$$$J$$5-;v$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-unread})\e$B!#$b$7@\F,0z?t$,M?$($i$l$l$P!"%P%C\e(B
+\e$B%U%!$r87L)$KL$FI5-;v$N$_$K@)8B$7$^$9!#$3$l$O!"2D;k$HJ]N1$N5-;v$O4^$^$l$J\e(B
+\e$B$$$H$$$&$3$H$G$9!#\e(B
+
+@item / m
+@kindex / m (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-marks
+\e$B0u$r?R$M$F!"$=$N0u$,IU$$$F$$$k5-;v$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-marks})\e$B!#\e(B
+
+@item / t
+@kindex / t (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-age
+\e$B?t;z$r?R$M$F!"35N,%P%C%U%!$r$=$N?t;z$NF|$h$j8E$$\e(B (\e$B$b$7$/$OF1$8\e(B) \e$B5-;v$K@)\e(B
+\e$B8B$7$^$9\e(B (@code{gnus-summary-limit-to-age})\e$B!#$b$7@\F,0z?t$,M?$($i$l$l$P!"\e(B
+\e$B$=$N?t;z$NF|$h$j$b?7$7$$5-;v$K@)8B$7$^$9!#\e(B
+
+@item / n
+@kindex / n (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-articles
+\e$B35N,%P%C%U%!$r8=:_$N5-;v$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-articles})\e$B!#%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$r;H\e(B
+\e$B$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item / w
+@kindex / w (\e$B35N,\e(B)
+@findex gnus-summary-pop-limit
+\e$BA0$N@)8B$r%9%?%C%/$+$i<h$j=P$7$F!"I|85$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-pop-limit})\e$B!#$b$7@\F,0z?t$rM?$($i$l$l$P!"$9$Y$F$N\e(B
+\e$B@)8B$r%9%?%C%/$+$i<h$j=P$7$^$9!#\e(B
+
+@item / .
+@kindex / . (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-unseen
+\e$B35N,%P%C%U%!$r$^$@FI$^$l$?$3$H$,L5$$5-;v$K@)8B$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-to-unseen})\e$B!#\e(B
+
+@item / v
+@kindex / v (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-score
+\e$B35N,%P%C%U%!$r$"$k%9%3%"$HF1$8$+!"$=$l$h$jBg$-$J%9%3%"$r;}$D5-;v$K@)8B$7\e(B
+\e$B$^$9\e(B (@code{gnus-summary-limit-to-score})\e$B!#\e(B
+
+@item / p
+@kindex / p (\e$B35N,\e(B)
+@findex gnus-summary-limit-to-display-predicate
+\e$B35N,%P%C%U%!$r\e(B @code{display} \e$B%0%k!<%W%Q%i%a!<%?$N=R8l$rK~B-$5$;$k$h$&$K\e(B
+\e$B@)8B$7$^$9\e(B (@code{gnus-summary-limit-to-display-predicate})\e$B!#$3$N=R8l$K\e(B
+\e$B4X$9$k>\:Y$O\e(B @ref{Group Parameters} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item / E
+@itemx M S
+@kindex M S (\e$B35N,\e(B)
+@kindex / E (\e$B35N,\e(B)
+@findex gnus-summary-limit-include-expunged
+\e$B$9$Y$F$N>C5n$5$l$?5-;v$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-include-expunged})\e$B!#\e(B
+
+@item / D
+@kindex / D (\e$B35N,\e(B)
+@findex gnus-summary-limit-include-dormant
+\e$B$9$Y$F$NJ]N15-;v$rI=<($7$^$9\e(B (@code{gnus-summary-limit-include-dormant})\e$B!#\e(B
+
+@item / *
+@kindex / * (\e$B35N,\e(B)
+@findex gnus-summary-limit-include-cached
+\e$B$9$Y$F$N%-%c%C%7%e$KF~$C$F$$$k5-;v$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-include-cached})\e$B!#\e(B
+
+@item / d
+@kindex / d (\e$B35N,\e(B)
+@findex gnus-summary-limit-exclude-dormant
+\e$B$9$Y$F$NJ]N15-;v$r1#$7$^$9\e(B (@code{gnus-summary-limit-exclude-dormant})\e$B!#\e(B
+
+@item / M
+@kindex / M (\e$B35N,\e(B)
+@findex gnus-summary-limit-exclude-marks
+\e$BA4$F$N0uIU$-5-;v$r=|30$7$^$9\e(B (@code{gnus-summary-limit-exclude-marks})\e$B!#\e(B
+
+@item / T
+@kindex / T (\e$B35N,\e(B)
+@findex gnus-summary-limit-include-thread
+\e$B8=:_$N%9%l%C%I$N$9$Y$F$N5-;v$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-include-thread})\e$B!#\e(B
+
+@item / c
+@kindex / c (\e$B35N,\e(B)
+@findex gnus-summary-limit-exclude-childless-dormant
+\e$B;R5-;v$NL5$$$9$Y$F$NJ]N15-;v$r1#$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-exclude-childless-dormant})\e$B!#\e(B
+
+@item / C
+@kindex / C (\e$B35N,\e(B)
+@findex gnus-summary-limit-mark-excluded-as-read
+\e$B$9$Y$F$NL$FI$N$_$N0u$N5-;v$r4{FI$H$7$F0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-limit-mark-excluded-as-read})\e$B!#$b$7@\F,0z?t$,M?$(\e(B
+\e$B$i$l$l$P!"2D;k$HJ]N1$N$_$N0u$N5-;v$b4{FI$H$7$F0u$rIU$1$^$9!#\e(B
+
+@item / N
+@kindex / N (\e$B35N,\e(B)
+@findex gnus-summary-insert-new-articles
+\e$B$9$Y$F$N?7$7$$5-;v$r35N,%P%C%U%!$KA^F~$7$^$9!#$b\e(B
+\e$B$7\e(B @var{back-end}@code{-get-new-mail} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"?7$7$$%a!<\e(B
+\e$B%k$NE~Mh$rD4$Y$k$H$$$&$3$H$G$9!#\e(B
+
+@item / o
+@kindex / o (\e$B35N,\e(B)
+@findex gnus-summary-insert-old-articles
+\e$B$9$Y$F$N8E$$5-;v$r35N,%P%C%U%!$KA^F~$7$^$9!#$b$7?t;z$N@\F,<-$,M?$($i$l$l\e(B
+\e$B$P!"$=$N?t$N5-;v$r<h$j9~$_$^$9!#\e(B
+@end table
+
+@node Threading
+@section \e$B%9%l%C%I\e(B
+@cindex threading
+@cindex article threading
+
+Gnus \e$B$O=i4|@_Dj$G5-;v$r%9%l%C%I$K$7$^$9!#\e(B@dfn{\e$B%9%l%C%I$K$9$k\e(B} \e$B$H$O!"$"$k\e(B
+\e$B5-;v$X$N1~Ez$r1~Ez$7$?5-;v$ND>8e$KCV$/!=!=3,AXE*N.57$G\e(B \e$B$H$$$&$3$H$G$9!#\e(B
+
+\e$B%9%l%C%I$O5-;v$N\e(B @code{References} \e$BMs$rD4$Y$k$3$H$K$h$C$F9T$o$l$^$9!#40\e(B
+\e$BA4$J@$3&$G$O!"$3$l$@$1$GNI$$LZ$r:n$j>e$2$k$N$K==J,$J$N$G$9$,!"IT1?$J$3$H\e(B
+\e$B$K!"\e(B@code{References} \e$BMs$O$7$P$7$P2u$l$F$$$k$+!";~$K$OC1$K$J$$$H$$$&$3$H\e(B
+\e$B$,$"$j$^$9!#IT;W5D$J%K%e!<%9$NA}?#$,LdBj$rA}$d$7$^$9$N$G!"4n$P$7$$7k2L$r\e(B
+\e$BF@$k$?$a$K$OB>$NH/8+K!$r:NMQ$7$J$1$l$P$J$j$^$;$s!#2a>j$JBP:vK!$OB8:_$7$F\e(B
+\e$B$$$F!"$=$N62$k$Y$->\:Y$O\e(B @ref{Customizing Threading} \e$B$K>\$7$/=q$$$F$"$j\e(B
+\e$B$^$9!#\e(B
+
+\e$B$^$:!"35G0$N354Q$G$9\e(B:
+
+@table @dfn
+@item \e$B:,K\\e(B (root)
+\e$B%9%l%C%I$G0lHVD:E@$K$"$k5-;v$G$9!(%9%l%C%I$N:G=i$N5-;v$G$9!#\e(B
+
+@item \e$B%9%l%C%I\e(B (thread)
+\e$BLZ$N$h$&$J5-;v$N9=@.$G$9!#\e(B
+
+@item \e$BItJ,%9%l%C%I\e(B (sub-thread)
+\e$BLZ$N$h$&$J9=B$$N\e(B (\e$B$h$j\e(B) \e$B>.$5$JItJ,$G$9!#\e(B
+
+@item \e$BL5B+G{%9%l%C%I\e(B (loose threads)
+\e$B5-;v$N4|8B@Z$l:o=|$d!":,K\$,4{$KA02s$N%;%C%7%g%s$GFI$^$l$?$3$H$K$h$j35N,\e(B
+\e$B%P%C%U%!$KI=<($5$l$J$$!"Ey$NM}M3$K$h$j!"%9%l%C%I$O$7$P$7$P:,K\$r<:$$$^$9!#\e(B
+\e$B$=$N$h$&$J$H$-$K$O!"IaDL$OB?$/$NItJ,%9%l%C%I$,$"$C$F!"K\Ev$O0l$D$N%9%l%C\e(B
+\e$B%I$KB0$7$F$$$k$N$G$9$,!":,K\$K$O$D$J$,$C$F$$$J$$!"$H$$$&$3$H$K$J$j$^$9!#\e(B
+\e$B$3$&$$$&%9%l%C%I$,L5B+G{%9%l%C%I$H8F$P$l$F$$$^$9!#\e(B
+
+@item \e$B%9%l%C%I=8$a\e(B (thread gathering)
+\e$B$^$P$i%9%l%C%I$rBg$-$J%9%l%C%I$K=8$a$h$&$H$9$k;n$_$G$9!#\e(B
+
+@item \e$B$^$P$i%9%l%C%I\e(B (sparse threads)
+\e$BL5$$5-;v$,!X?dB,$5$l$?!Y%9%l%C%I$G!"35N,%P%C%U%!$K6u9T$GI=<($5$l$^$9!#\e(B
+@end table
+
+@menu
+* Customizing Threading::       \e$BJQ992DG=$J%9%l%C%I$K1F6A$9$kJQ?t\e(B
+* Thread Commands::             \e$B35N,%P%C%U%!$G$N%9%l%C%I$K4p$E$$$?L?Na\e(B
+@end menu
+
+@node Customizing Threading
+@subsection \e$B%9%l%C%I$r%+%9%?%^%$%:$9$k\e(B
+@cindex customizing threading
+
+@menu
+* Loose Threads::               Gnus \e$B$,L5B+G{%9%l%C%I$r=8$a$FBg$-$J%9%l%C%I$K$9$kJ}K!\e(B
+* Filling In Threads::          \e$B%9%l%C%I$rKd$a$k\e(B
+* More Threading::              \e$B%9%l%C%I$r$$$8$/$k$5$i$KB?$/$NJQ?t\e(B
+* Low-Level Threading::         \e$B$3$l$G=*$o$C$?$H;W$C$?$G$7$g$&\e(B@dots{} \e$B$G$b$"$J$?$O4V0c$C$F$$$?\e(B!
+@end menu
+
+@node Loose Threads
+@subsubsection \e$BL5B+G{%9%l%C%I\e(B
+@cindex <
+@cindex >
+@cindex loose threads
+
+@table @code
+@item gnus-summary-make-false-root
+@vindex gnus-summary-make-false-root
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$OA4$F$N$D$J$,$C$F$$$J$$ItJ,LZ$r0l$D$NBg\e(B
+\e$B$-$JLZ$K$7$F!"D:>e$K$_$;$+$1$N:,K\$r:n$j$^$9!#\e(B(\e$B$A$g$C$HBT$C$F$/$@$5$$!#\e(B
+\e$BD:>e$K:,85\e(B (root) \e$B$G$9$C$F\e(B? \e$B$($(!"$=$&$J$N$G$9!#\e(B) \e$B$D$J$,$C$F$$$J$$ItJ,LZ\e(B
+\e$B$OK\Ev$N:,K\$,4|8B@Z$l:o=|$5$l$?$+!"A02s$N%;%C%7%g%s$G:,K\$rFI$s$@$j:o=|\e(B
+\e$B$7$?$H$-$K$G$-$^$9!#\e(B
+
+\e$BK\Ev$N%9%l%C%I$,L5$$$H$-$O!"\e(Bgnus \e$B$O2?$+$G$C$A>e$2$r$9$kI,MW$,$"$j$^$9!#\e(B
+\e$B$3$NJQ?t$O\e(B gnus \e$B$,;H$&$Y$-$4$^$+$7$NJ}K!$r<($7$F$$$^$9!#CM$H$7$F$H$k$3$H\e(B
+\e$B$,$G$-$k;M$D$N8uJd$,$"$j$^$9!#\e(B
+
+@iftex
+@iflatex
+\gnusfigure{The Summary Buffer}{390}{
+\put(0,0){\epsfig{figure=ps/summary-adopt,width=7.5cm}}
+\put(445,0){\makebox(0,0)[br]{\epsfig{figure=ps/summary-empty,width=7.5cm}}}
+\put(0,400){\makebox(0,0)[tl]{\epsfig{figure=ps/summary-none,width=7.5cm}}}
+\put(445,400){\makebox(0,0)[tr]{\epsfig{figure=ps/summary-dummy,width=7.5cm}}}
+}
+@end iflatex
+@end iftex
+
+@cindex adopting articles
+
+@table @code
+@item \e$BM\;R\e(B (adopt)
+Gnus \e$B$O:G=i$N8I;y$r?F$K$7$^$9!#$3$N?F$O$9$Y$F$NB>$N5-;v$rM\;R$K$7$^$9!#\e(B
+\e$B$3$NM\;R5-;v$O!"I8=`$N3Q3g8L\e(B (@samp{[]}) \e$B$NBe$o$j$K!"@h$N@m$C$?3g\e(B
+\e$B8L\e(B (@samp{<>}) \e$B$G0uIU$1$i$l$^$9!#$3$l$,=i4|@_Dj$NJ}K!$G$9!#\e(B
+
+@item \e$B$_$;$+$1\e(B (dummy)
+@vindex gnus-summary-dummy-line-format
+@vindex gnus-summary-make-false-root-always
+Gnus \e$B$O?F$N$U$j$r$9$k$_$;$+$1$N35N,9T$r$D$/$j$^$9!#$_$;$+$1$N9T$O$I$NK\\e(B
+\e$BEv$N5-;v$K$bBP1~$7$^$;$s$N$G!"$=$l$rA*Br$9$k$3$H$O!"$_$;$+$1$N5-;v$N8e$N\e(B
+\e$B:G=i$NK\Ev$N5-;v$rA*Br$r$9$k$@$1$K$J$j$^$9!#$_$;$+$1$N:,K\$NMM<0$r;XDj\e(B
+\e$B$9$k$?$a$K!"\e(B@code{gnus-summary-dummy-line-format} \e$B$,;H$o$l$^$9!#$3$l$O$?$C\e(B
+\e$B$?0l$D$@$1$N%U%)!<%^%C%H$N;EMM$r<u$1IU$1$^$9\e(B: @samp{S} \e$B$G!"$3$l$O5-;v$N\e(B
+\e$BI=Bj$G$9!#\e(B@xref{Formatting Variables}. \e$B$?$H$(=8$a$k$b$N$,L5$/$F$b!"$9$Y\e(B
+\e$B$F$N%9%l%C%I$K$_$;$+$1$N:,K\$r;}$?$;$?$$>l9g$O!"\e(B
+@code{gnus-summary-make-false-root-always} \e$B$r\e(B @code{t} \e$B$K@_Dj$7$F2<$5$$!#\e(B
+
+@item \e$B6u\e(B (empty)
+Gnus \e$B$O<B:]$K$O$I$N5-;v$b?F$K$O$;$:!"C1$K:G=i$N8I;y$r=|$$$F$9$Y$F$N8I;y\e(B
+\e$B$NI=BjMs$r6u$N$^$^$K$7$^$9!#\e(B
+(\e$B<B:]$O!"\e(B@code{gnus-summary-same-subject} \e$B$rI=Bj$H$7$F;H$$$^\e(B
+\e$B$9\e(B (@pxref{Summary Buffer Format})\e$B!#\e(B)
+
+@item none
+\e$BA4$/$I$N5-;v$b?F$K$7$^$;$s!#%9%l%C%I$r=8$a$F!"0l$D$N5-;v$N8e$KB>$N5-;v$r\e(B
+\e$BI=<($9$k$@$1$G$9!#\e(B
+
+@item nil
+\e$BL5B+G{%9%l%C%I$r=8$a$^$;$s!#\e(B
+@end table
+
+@item gnus-summary-gather-subject-limit
+@vindex gnus-summary-gather-subject-limit
+\e$BL5B+G{%9%l%C%I$O5-;v$NI=Bj$rHf3S$9$k$3$H$K$h$C$F=8$a$i$l$^$9!#$b$7$3$NJQ\e(B
+\e$B?t$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$OL5B+G{%9%l%C%I$r0l$D$NBg$-$JD6%9%l%C%I\e(B
+\e$B$K=8$a$kA0$K!"L5B+G{%9%l%C%I$NI=Bj$,40A4$K0lCW$9$k$3$H$rMW5a$7$^$9!#$3$l\e(B
+\e$B$O!"D9$$I=Bj$N9T$r@Z$jMn$H$7$F$7$^$&4VH4$1$J%K%e!<%9%j!<%@!<$,B8:_$9$k8=\e(B
+\e$B:_$G$O!"$"$^$j$K87$7$$MW5a$+$bCN$l$^$;$s!#$b$7$=$&;W$&$N$J$i!"$3$NJQ?t$r\e(B
+\e$BNc$($P\e(B 20 \e$B$K@_Dj$7$F!"I=Bj$N:G=i$N\e(B 20 \e$BJ8;z$@$1$,0lCW$9$k$3$H$rMW5a$9$k$h\e(B
+\e$B$&$K$9$k$3$H$,$G$-$^$9!#$3$NJQ?t$rK\Ev$KDc$$?t;z$K@_Dj$9$k$H!"\e(Bgnus \e$B$,L\\e(B
+\e$B$KF~$kA4$F$r0l$D$N%9%l%C%I$K=8$a$k$N$r8+$k$3$H$,$G$-$k$G$7$g$&!#$=$7$F!"\e(B
+\e$B$=$l$O$"$^$jM-MQ$G$O$"$j$^$;$s!#\e(B
+
+@cindex fuzzy article gathering
+\e$B$3$NJQ?t$rFCJL$JCM\e(B @code{fuzzy} \e$B$K@_Dj$9$l$P!"\e(Bgnus \e$B$OI=Bj$K$"$$$^$$$JJ8\e(B
+\e$B;zNsHf3S%"%k%4%j%:%`$r;H$$$^$9\e(B (@pxref{Fuzzy Matching})\e$B!#\e(B
+
+@item gnus-simplify-subject-fuzzy-regexp
+@vindex gnus-simplify-subject-fuzzy-regexp
+\e$B$3$l$O@55,I=8=$+!"$"$$$^$$I=Bj;XDj$,;H$o$l$F$$$k$H$-$KI=Bj$+$i9gCW$7$?$b\e(B
+\e$B$N$,<h$j=|$+$l$k!"@55,I=8=$N%j%9%H$G$"$k$3$H$,$G$-$^$9!#\e(B
+
+@item gnus-simplify-ignored-prefixes
+@vindex gnus-simplify-igonored-prefixes
+\e$B$b$7\e(B @code{gnus-summary-gather-subject-limit} \e$B$r\e(B 10 \e$B$/$i$$$KDc$/@_Dj$7$?\e(B
+\e$B$J$i$P!"$3$NJQ?t$r2?$+0UL#$N$"$k$b$N$K@_Dj$9$k$3$H$r9M$($k$G$7$g$&\e(B:
+
+@c Written by Michael Ernst <mernst@cs.rice.edu>
+@lisp
+(setq gnus-simplify-ignored-prefixes
+      (concat
+       "\\`\\[?\\("
+       (mapconcat
+        'identity
+        '("looking"
+          "wanted" "followup" "summary\\( of\\)?"
+          "help" "query" "problem" "question"
+          "answer" "reference" "announce"
+          "How can I" "How to" "Comparison of"
+          ;; ...
+          )
+        "\\|")
+       "\\)\\s *\\("
+       (mapconcat 'identity
+                  '("for" "for reference" "with" "about")
+                  "\\|")
+       "\\)?\\]?:?[ \t]*"))
+@end lisp
+
+\e$B$3$N@55,I=8=$K9gCW$9$k$9$Y$F$N8l$O!"Fs$D$NI=Bj$rHf3S$9$kA0$K<h$j=|$+$l$^\e(B
+\e$B$9!#\e(B
+
+@item gnus-simplify-subject-functions
+@vindex gnus-simplify-subject-functions
+@code{nil} \e$B$G$J$$$H!"$3$NJQ?t\e(B
+\e$B$O\e(B @code{gnus-summary-gather-subject-limit} \e$B$r>e=q$-$7$^$9!#$3$NJQ?t$OJ8\e(B
+\e$B;zNs\e(B @code{Subject} \e$B$rH?I|$7$F4JC1$J7A$K$?$I$jCe$/$?$a$KE,MQ$9$k4X?t$N%j\e(B
+\e$B%9%H$G$"$kI,MW$,$"$j$^$9!#\e(B
+
+\e$B$3$N%j%9%H$KF~$l$FLr$KN)$D$h$&$J4X?t$O<!$N$h$&$J$b$N$G$9\e(B:
+
+@table @code
+@item gnus-simplify-subject-re
+@findex gnus-simplify-subject-re
+\e$BA0$NJ}$K$"$k\e(B @samp{Re:} \e$B$r<h$j=|$-$^$9!#\e(B
+
+@item gnus-simplify-subject-fuzzy
+@findex gnus-simplify-subject-fuzzy
+\e$B$"$$$^$$$K4JC1$K$7$^$9!#\e(B
+
+@item gnus-simplify-whitespace
+@findex gnus-simplify-whitespace
+\e$BM>J,$J6uGr\e(B (whitespace) \e$B$r<h$j=|$-$^$9!#\e(B
+
+@item gnus-simplify-all-whitespace
+@findex gnus-simplify-all-whitespace
+\e$B$9$Y$F$N6uGr\e(B (whitespace) \e$B$r<h$j=|$-$^$9!#\e(B
+@end table
+
+\e$B$b$A$m$s!"$"$J$?<+?H$N4X?t$r=q$/$3$H$b$G$-$^$9!#\e(B
+
+@item gnus-summary-gather-exclude-subject
+@vindex gnus-summary-gather-exclude-subject
+\e$BL5B+G{%9%l%C%I=8$a$OI=Bj$N$_$K9T$o$l$^$9$N$G!"FC\e(B
+\e$B$K\e(B @samp{} \e$B$d\e(B @samp{(none)}\e$B$N$h$&$JNI$/$"$kI=Bj$N$H$-$O!"B?$/$N4V0c$$$r\e(B
+\e$B5/$3$92DG=@-$,$"$j$^$9!#$3$N>u67$r>/$7$h$/$9$k$?$a$K!"$I$NI=Bj$,=8$a$k2a\e(B
+\e$BDx$+$i=|$+$l$k$+$r7h$a$k@55,I=\e(B
+\e$B8=\e(B @code{gnus-summary-gather-exclude-subject} \e$B$r;H$&$3$H$,$G$-$^$9!#%G%#\e(B
+\e$B%U%)%k%H$O\e(B @samp{^ *$\\|^(none)$} \e$B$G$9!#\e(B
+
+@item gnus-summary-thread-gathering-function
+@vindex gnus-summmary-thread-gathering-function
+Gnus \e$B$O\e(B @code{Subject} \e$BMs$r8+$k$3$H$K$h$C$F%9%l%C%I$r=8$a$^$9!#$3$l$O!"\e(B
+\e$B7k2LE*$KA4$/4X78$NL5$$5-;v$,F1$8!X%9%l%C%I!Y$K4^$^$l$k$3$H$,$"$k$H$$$&$3\e(B
+\e$B$H$G!"$3$l$O:.Mp$N85$G$9!#BeBX<jCJ$O!"9gCW$9$k$b$N$r8+$D$1$k$?$a\e(B
+\e$B$K\e(B @code{References} \e$BMs$K$"$k\e(B @code{Message-ID} \e$B$r$9$Y$FC5$9$3$H$G$9!#$3\e(B
+\e$B$l$O4X78$NL5$$5-;v$,=8$a$i$l$?%9%l%C%I$K4^$^$l$k$3$H$OA4$/L5$$$3$H$rJ]>Z\e(B
+\e$B$7$^$9$,!"$3$o$l$?%K%e!<%9%j!<%@!<$GEj9F$7$?5-;v$OE,@Z$K=8$a$i$l$J$$$H$$\e(B
+\e$B$&$3$H$G$b$"$j$^$9!#A*Br8"$O$"$J$?$K$"$j$^$9!=!=1VIB$+%3%l%i$+!#\e(B
+
+@table @code
+@item gnus-gather-threads-by-subject
+@findex gnus-gather-threads-by-subject
+\e$B$3$N4X?t$O%G%#%U%)%k%H$N<}=84X?t$G!"GSB>E*$K\e(B @code{Subject} \e$B$r8+$^$9!#\e(B
+
+@item gnus-gather-threads-by-references
+\e$B$3$N4X?t$OGSB>E*$K\e(B @code{References} \e$BMs$r8+$^$9!#\e(B
+@end table
+
+@code{References} \e$B$K$h$C$F=8$a$k$3$H$r;n$7$F$_$?$$$N$G$"$l$P!"<!$N$h$&$K\e(B
+\e$B$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-summary-thread-gathering-function
+      'gnus-gather-threads-by-references)
+@end lisp
+@end table
+
+@node Filling In Threads
+@subsubsection \e$B%9%l%C%I$rKd$a$k\e(B
+
+@table @code
+@item gnus-fetch-old-headers
+@vindex gnus-fetch-old-headers
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O8E$$%9%l%C%I$r$b$C$H8E$$%X%C%@!<!=!=4{\e(B
+\e$BFI0u$NIU$$$F$$$k5-;v$N%X%C%@!<$r<hF@$9$k$3$H$GBg$-$/$7$h$&$H$7$^$9!#$b$7\e(B
+\e$B$G$-$k$@$1>/$J$$35N,9T$rI=<($7$?$$$1$l$I!"$G$-$k$@$1$?$/$5$s$NHsL)%9%l%C\e(B
+\e$B%I$K@\B3$7$F$*$-$?$$$H$-$O!"$3$NJQ?t$r\e(B @code{some} \e$B$+?t;z$K@_Dj$9$k$3$H\e(B
+\e$B$,$G$-$^$9!#$b$7?t;z$K@_Dj$7$?$H$-$O!"$=$l$h$jB?$$DI2C$N%X%C%@!<$O<hF@$5\e(B
+\e$B$l$^$;$s!#$I$A$i$N>l9g$G$b!"8E$$%X%C%@!<$N<hF@$,F0:n$9$k$N$O!";H$C$F$$$k\e(B
+\e$B%P%C%/%(%s%I\e(B(back end) \e$B$,\e(B overview \e$B%U%!%$%k$r;H$C$F$$$k$+$I$&$+$G$9!=!=\e(B
+\e$B$3$l$OIaDL$O\e(B @code{nntp}, @code{nnspool}, @code{nnml} \e$B$*$h\e(B
+\e$B$S\e(B @code{nnmaildir}\e$B$G$9!#%9%l%C%I$N%k!<%H$,%5!<%P!<$K$h$C$F4|8B@Z$l:o=|\e(B
+\e$B$5$l$?$H$-$O!"\e(Bgnus \e$B$O$I$&$7$h$&$b$J$$$3$H$r3P$($F$*$$$F$/$@$5$$!#\e(B
+
+\e$B$3$NJQ?t$O\e(B @code{invisible} \e$B$K@_Dj$9$k$3$H$b$G$-$^$9!#$3$l$O;k3PE*$J8z2L\e(B
+\e$B$O2?$b$"$j$^$;$s$,!"L?Na\e(B @kbd{A T} \e$B$r$h$/;H$&$N$G$"$l$PLr$KN)$D$G$7$g\e(B
+\e$B$&\e(B (@pxref{Finding the Parent})\e$B!#\e(B
+
+@item gnus-fetch-old-ephemeral-headers
+@vindex gnus-fetch-old-ephemeral-headers
+@code{gnus-fetch-old-headers} \e$B$HF1$8$G$9$,!"0l;~%K%e!<%9%0%k!<%W$N$?$a$K\e(B
+\e$B$@$1;H$o$l$^$9!#\e(B
+
+@item gnus-build-sparse-threads
+@vindex gnus-build-sparse-threads
+\e$B8E$$%X%C%@!<$r<hF@$9$k$HCY$/$J$k$3$H$,$"$j$^$9!#F1$8$h$&$JDcDB6b$N8z2L$r\e(B
+\e$BF@$k$?$a$K!"$3$NJQ?t$r\e(B @code{some} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#$=$&$9$k$H!"\e(B
+gnus \e$B$OA4$F$N5-;v$N40A4$J\e(B @code{References} \e$BMs$r8+$F!"F1$8%9%l%C%I$KB0$9\e(B
+\e$B$k5-;v$r$D$J$4$&$H$7$^$9!#$3$l$O\e(B gnus \e$B$,5-;v$,%9%l%C%I$+$i<:$o$l$F$$$k$H\e(B
+\e$B?dB,$7$?$H$3$m$N%9%l%C%II=<($K\e(B@dfn{\e$B$:$l\e(B}\e$B$r;D$9$G$7$g$&!#\e(B(\e$B$3$l$i$N$:$l$O\e(B
+\e$BIaDL$N35N,9T$N$h$&$K8=$l$^$9!#$b$7$:$l$rA*Br$7$?$H$-$O!"\e(Bgnus \e$B$O$=$NEv$N\e(B
+\e$B5-;v$r<hF@$7$h$&$H$7$^$9!#\e(B) \e$B$3$NJQ?t$,\e(B @code{t} \e$B$G$"$k$H!"\e(Bgnus \e$B$OA4$F$N\e(B
+\e$B!X$:$l!Y$r%9%l%C%I$rJd40$9$k$N$KLr$KN)$D$+$r9MN8$;$:$KI=<($7$^$9!#:G8e$K!"\e(B
+\e$B$3$NJQ?t$,\e(B @code{more} \e$B$G$"$k$H!"\e(Bgnus \e$B$O$I$3$K$b$D$J$,$C$F$$$J$$;^MU$N$^\e(B
+\e$B$P$i$J@a$r@Z$jMn$H$7$^$;$s!#$3$NJQ?t$O%G%#%U%)%k%H$G$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item gnus-read-all-available-headers
+@vindex gnus-read-all-available-headers
+\e$B$3$l$O$I$A$i$+$H8@$($P$"$^$jLr$KN)$?$J$$JQ?t$G$9!#%K%e!<%9$G$O$J$$%0%k!<\e(B
+\e$B%W$K$*$$$F35N,%P%C%U%!$,$H$F$bBg$-$/$J$j!"$7$+$b?F5-;v$rC)$k$3$H$,$G$-$J\e(B
+\e$B$$>l9g$K;H$&$3$H$rA[Dj$7$F$$$^$9!#$=$l$O<g$K\e(B @code{nnultimate} \e$B%0%k!<%W\e(B
+\e$B$N$h$&$J!"%&%'%V$K4p$E$$$?%0%k!<%W$G$9!#\e(B
+
+\e$B$3$l$r;H$o$J$$>l9g$O%G%#%U%)%k%H$N\e(B @code{nil} \e$B$N$^$^$K$7$F$*$/$N$,L5Fq$G\e(B
+\e$B$9!#;H$$$?$$>l9g$O%0%k!<%WL>$K9gCW$9$k@55,I=8=$+!"$9$Y$F$N%0%k!<%WL>$K9g\e(B
+\e$BCW$9$k\e(B @code{t} \e$B$K$7$F2<$5$$!#\e(B
+@end table
+
+@node More Threading
+@subsubsection \e$B$b$C$H%9%l%C%I$r\e(B
+
+@table @code
+@item gnus-show-threads
+@vindex gnus-show-threads
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"%9%l%C%I$O:n$i$l$:!"$3$3$K$"$k;D$j$N$9$Y\e(B
+\e$B$F$NJQ?t$OA4$/8z2L$,L5$/$J$j$^$9!#%9%l%C%I:n$j$r;_$a$k$H%0%k!<%W$NA*Br$,\e(B
+\e$B>/$7B.$/$J$j$^$9$,!"5-;v$rFI$`$N$,$b$C$HCY$/!"ITJX$K$J$k$3$H$O3N<B$G$9!#\e(B
+
+@item gnus-thread-hide-subtree
+@vindex gnus-thread-hide-subtree
+\e$B$3$l$,\e(B @code{nil} \e$B$G$J$$$H!"$9$Y$F$N%9%l%C%I$O35N,%P%C%U%!$,@8@.$5$l$?$H\e(B
+\e$B$-$K1#$l$^$9!#\e(B
+
+\e$B$3$l$O=R8l;X<(;R$G$"$k$3$H$b$G$-$^$9\e(B (@pxref{Predicate Specifiers})\e$B!#Mx\e(B
+\e$BMQ$G$-$k=R8l\e(B
+\e$B$O\e(B @code{gnus-article-unread-p} \e$B$H\e(B @code{gnus-article-unseen-p} \e$B$G$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@lisp
+(setq gnus-thread-hide-subtree
+      '(or gnus-article-unread-p
+           gnus-article-unseen-p))
+@end lisp
+
+(\e$B$3$l$O$+$J$j$P$+$2$?Nc$G$9!#$J$<$J$i$9$Y$F$N$^$@FI$^$l$?$3$H$,L5$$5-;v\e(B
+\e$B$OL$FI$G$b$"$k$+$i$J$N$G$9$,!"<g;]$O5b$_<h$C$F2<$5$$!#\e(B)
+
+@item gnus-thread-expunge-below
+@vindex gnus-thread-expunge-below
+\e$B$3$N?t;z$h$j>/$J$$Am9gE*%9%3%"\e(B (@code{gnus-thread-score-function}) \e$B$r;}\e(B
+\e$B$D$9$Y$F$N%9%l%C%I$O>C5n$5$l$^$9!#$3$NJQ?t$O%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B @code{nil} \e$B$G!"$3$l$O$I$N%9%l%C%I$b>C5n$5$l$J$$$H$$$&$3$H$G$9!#\e(B
+
+@item gnus-thread-hide-killed
+@vindex gnus-thread-hide-killed
+\e$B$b$7%9%l%C%I$r:o=|$7$F!"$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"ItJ,LZ$O1#$5$l$^\e(B
+\e$B$9!#\e(B
+
+@item gnus-thread-ignore-subject
+@vindex gnus-thread-ignore-subject
+\e$B;~!9!"C/$+$,%9%l%C%I$N??Cf$GI=Bj$rJQ99$9$k$3$H$,$"$j$^$9!#$b$7$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$J$$$H!"$3$l$,%G%#%U%)%k%H$G$9$,!"I=Bj$NJQ99$OL5;k$5$l$^\e(B
+\e$B$9!#$b$7\e(B @code{nil} \e$B$@$H!"I=Bj$NJQ99$r$9$k$HJL$N%9%l%C%I$K$J$j$^$9!#\e(B
+
+@item gnus-thread-indent-level
+@vindex gnus-thread-indent-level
+\e$B$3$N?t;z$OItJ,%9%l%C%I$,$I$l$/$i$$;z2<$2\e(B (indent) \e$B$5$l$k$Y$-$+$r7h$a$^$9!#\e(B
+\e$B%G%#%U%)%k%H$O\e(B 4 \e$B$G$9!#\e(B
+
+@item gnus-sort-gathered-threads-function
+@vindex gnus-sort-gathered-threads-function
+\e$B$H$-$I$-!"FC$K%a!<%j%s%0%j%9%H$G!"<j85$K%a!<%k$,E~Ce$9$k=gHV$OI,$:$7$b%a!<\e(B
+\e$B%j%s%0%j%9%H$KE~Ce$7$?=gHV$HF1$8$G$OL5$$$3$H$,$"$j$^$9!#=>$C$F!"I{%9%l%C\e(B
+\e$B%I$r=i4|@_Dj$N\e(B @code{gnus-thread-sort-by-number} \e$B$GJB$S49$($k$H!"1~Ez$N\e(B
+\e$BJ}$,$=$l$,1~Ez$7$F$$$k5-;v$h$j@h$K8=$l$k$3$H$,$"$j$^$9!#%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$dE,@Z$J%U%C%/\e(B (\e$BNc$($P\e(B @code{gnus-summary-generate-hook}) \e$B$G$3$NJQ?t$r\e(B
+\e$BBe$o$j$NCM\e(B (\e$BNc$($P!"\e(B@code{gnus-thread-sort-by-date}) \e$B$K@_Dj$9$k$3$H$G!"\e(B
+\e$B$=$N$h$&$J>l9g$K!"$h$jO@M}E*$JI{%9%l%C%I$N=gHV$r@8@.$9$k$3$H$,$G$-$^$9!#\e(B
+@end table
+
+@node Low-Level Threading
+@subsubsection \e$BDc%l%Y%k$K$*$1$k%9%l%C%I:n@.\e(B
+
+@table @code
+@item gnus-parse-headers-hook
+@vindex gnus-parse-headers-hook
+\e$B$9$Y$F$N%X%C%@!<$r2r@O$9$kA0$K<B9T$5$l$k%U%C%/$G$9!#%G%#%U%)%k%H$NCM\e(B
+\e$B$O\e(B @code{(gnus-set-summary-default-charset)} \e$B$G$9!#$3$l$OJQ\e(B
+\e$B?t\e(B @code{gnus-newsgroup-default-charset-alist} \e$B$G;XDj$5$l$F$$$kCM$+$i35\e(B
+\e$BN,%P%C%U%!$N\e(B @code{default-mime-charset} \e$B$r@_Dj$7$^$9!#\e(B
+
+@item gnus-alter-header-function
+@vindex gnus-alter-header-function
+\e$B$3$l$,\e(B @code{nil} \e$B$G$J$$$H!"%X%C%@!<9=B$$N8r49$r2DG=$K$9$k$h$&$K$3$N4X?t\e(B
+\e$B$,8F$P$l$^$9!#4X?t$O0l$D$N0z?t!"5-;v%X%C%@!<$N%Y%/%H%k!"$H$H$b$K8F$P$l!"\e(B
+\e$B$=$l$,2?$i$+$NJ}K!$G8r49$5$l$^$9!#Nc$($P!"\e(B(\e$B@\F,8l$d$=$NB>$N$b$N$rIU$12C\e(B
+\e$B$($k$3$H$K$h$k\e(B) \e$BBN7OE*$JJ}K!$G\e(B @code{Message-ID} \e$B$r8r49$9$k%a!<%k$+$i\e(B
+\e$B%K%e!<%9$X$N%2!<%H%&%'%$$,$"$k>l9g!"\e(B@code{Message-ID} \e$B$,$b$C$H0UL#$N$"$k\e(B
+\e$B$b$N$K$9$k$?$a$K!"$3$NJQ?t$r@_Dj$7$F85$KLa$9$3$H$,$G$-$^$9!#$3$l$O0l$D$N\e(B
+\e$BNc$G$9\e(B:
+
+@lisp
+(setq gnus-alter-header-function 'my-alter-message-id)
+
+(defun my-alter-message-id (header)
+  (let ((id (mail-header-id header)))
+    (when (string-match
+           "\\(<[^<>@@]*\\)\\.?cygnus\\..*@@\\([^<>@@]*>\\)" id)
+      (mail-header-set-id
+       (concat (match-string 1 id) "@@" (match-string 2 id))
+       header))))
+@end lisp
+@end table
+
+@node Thread Commands
+@subsection \e$B%9%l%C%I$NL?Na\e(B
+@cindex thread commands
+
+@table @kbd
+@item T k
+@itemx C-M-k
+@kindex T k (\e$B35N,\e(B)
+@kindex C-M-k (\e$B35N,\e(B)
+@findex gnus-summary-kill-thread
+\e$B8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$K4{FI$N0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-kill-thread})\e$B!#$b$7@\F,0z?t$,@5$G$"$k$H!"Be$o$j$K\e(B
+\e$B$9$Y$F$N0u$r<h$j=|$-$^$9!#@\F,0z?t$,Ii$G$"$k$H!"Be$o$j$K5-;v$r2D;k$K$7$^\e(B
+\e$B$9!#\e(B
+
+@item T l
+@itemx C-M-l
+@kindex T l (\e$B35N,\e(B)
+@kindex C-M-l (\e$B35N,\e(B)
+@findex gnus-summary-lower-thread
+\e$B8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$N%9%3%"$r2<$2$^\e(B
+\e$B$9\e(B (@code{gnus-summary-lower-thread})\e$B!#\e(B
+
+@item T i
+@kindex T i (\e$B35N,\e(B)
+@kindex gnus-summary-raise-thread
+\e$B8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$N%9%3%"$r>e$2$^\e(B
+\e$B$9\e(B (@code{gnus-summary-raise-thread})\e$B!#\e(B
+
+@item T #
+@kindex T # (\e$B35N,\e(B)
+@findex gnus-uu-mark-thread
+\e$B%W%m%;%90u$r8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$KIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-uu-mark-thread})\e$B!#\e(B
+
+@item T M-#
+@kindex T M-# (\e$B35N,\e(B)
+@findex gnus-uu-unmark-thread
+\e$B8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$+$i%W%m%;%90u$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-uu-unmark-thread})\e$B!#\e(B
+
+@item T T
+@kindex T T (\e$B35N,\e(B)
+@findex gnus-summary-toggle-threads
+\e$B%9%l%C%II=<($r@Z$jBX$($^$9\e(B (@code{gnus-summary-toggle-threads})\e$B!#\e(B
+
+@item T s
+@kindex T s (\e$B35N,\e(B)
+@findex gnus-summary-show-thread
+\e$B$b$7$"$l$P!"8=:_$N5-;v$N2<$K1#$l$F$$$k%9%l%C%I$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-show-thread})\e$B!#\e(B
+
+@item T h
+@kindex T h (\e$B35N,\e(B)
+@findex gnus-summary-hide-thread
+\e$B8=:_$N\e(B (\e$BItJ,\e(B) \e$B%9%l%C%I$r1#$7$^$9\e(B (@code{gnus-summary-hide-thread})\e$B!#\e(B
+
+@item T S
+@kindex T S (\e$B35N,\e(B)
+@findex gnus-summary-show-all-threads
+\e$B$9$Y$F$N1#$5$l$F$$$k%9%l%C%I$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-show-all-threads})\e$B!#\e(B
+
+@item T H
+@kindex T H (\e$B35N,\e(B)
+@findex gnus-summary-hide-all-threads
+\e$B$9$Y$F$N%9%l%C%I$r1#$7$^$9\e(B (@code{gnus-summary-hide-all-threads})\e$B!#\e(B
+
+@item T t
+@kindex T t (\e$B35N,\e(B)
+@findex gnus-summary-rethread-current
+\e$B8=:_$N5-;v$N%9%l%C%I$r$b$&0lEY:n$jD>$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-rethread-current})\e$B!#$3$l$O35N,%P%C%U%!$,%9%l%C%I\e(B
+\e$BI=<($5$l$F$$$J$$$H$-$G$bF0:n$7$^$9!#\e(B
+
+@item T ^
+@kindex T ^ (\e$B35N,\e(B)
+@findex gnus-summary-reparent-thread
+\e$B8=:_$N5-;v$r0uIU$-\e(B (\e$B$b$7$/$OA0$N\e(B) \e$B5-;v$N;R5-;v$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-reparent-thread})\e$B!#\e(B
+@end table
+
+\e$B0J2<$NL?Na$O%9%l%C%I0\F0L?Na$G$9!#$3$l$i$O$9$Y$F?tCM@\F,0z?t$r<u$1IU$1$^\e(B
+\e$B$9!#\e(B
+
+@table @kbd
+@item T n
+@kindex T n (\e$B35N,\e(B)
+@itemx C-M-f
+@kindex C-M-f (\e$B35N,\e(B)
+@itemx M-down
+@kindex M-down (\e$B35N,\e(B)
+@findex gnus-summary-next-thread
+\e$B<!$N%9%l%C%I$K0\F0$7$^$9\e(B (@code{gnus-summary-next-thread})\e$B!#\e(B
+
+@item T p
+@kindex T p (\e$B35N,\e(B)
+@itemx C-M-b
+@kindex C-M-b (\e$B35N,\e(B)
+@itemx M-up
+@kindex M-up (\e$B35N,\e(B)
+@findex gnus-summary-prev-thread
+\e$BA0$N%9%l%C%I$K0\F0$7$^$9\e(B (@code{gnus-summary-prev-thread})\e$B!#\e(B
+
+@item T d
+@kindex T d (\e$B35N,\e(B)
+@findex gnus-summary-down-thread
+\e$B%9%l%C%I$r9_2<$7$^$9\e(B (@code{gnus-summary-down-thread})\e$B!#\e(B
+
+@item T u
+@kindex T u (\e$B35N,\e(B)
+@findex gnus-summary-up-thread
+\e$B%9%l%C%I$r>e>:$7$^$9\e(B (@code{gnus-summary-up-thread})\e$B!#\e(B
+
+@item T o
+@kindex T o (\e$B35N,\e(B)
+@findex gnus-summary-top-thread
+\e$B%9%l%C%I$ND:>e$K0\F0$7$^$9\e(B (@code{gnus-summary-top-thread})\e$B!#\e(B
+@end table
+
+@vindex gnus-thread-operation-ignore-subject
+\e$B%9%l%C%I$r:n@.$9$k$H$-$KI=Bj$rL5;k$9$k$H!"<+A3$K%9%l%C%I$K$O$$$/$D$+$N0c$C\e(B
+\e$B$?I=Bj$,$"$k$3$H$K$J$j$^$9!#$=$l$+\e(B
+\e$B$i\e(B @kbd{T k} (@code{gnus-summary-kill-thread}) \e$B$N$h$&$JL?Na$rH/$9$k$H$-\e(B
+\e$B$K!"A4BN$N%9%l%C%I$r:o=|$9$k$N$G$O$J$/!"8=:_$N5-;v$HF1$8I=Bj$r;}$DItJ,$@\e(B
+\e$B$1$r:o=|$7$?$$$H$-$,$"$k$+$b$7$l$^$;$s!#$b$7$3$NH/A[$,NI$$$H;W$&$N$G$"$l\e(B
+\e$B$P!"\e(B@code{gnus-thread-operation-ignore-subject} \e$B$r$$$8$/$k$3$H$,$G$-$^$9!#\e(B
+\e$B$3$l$,\e(B @code{nil} \e$B$G$J$$$H\e(B (\e$B$3$l$,%G%#%U%)%k%H$G$9$,\e(B)\e$B!"%9%l%C%I$NL?Na$r\e(B
+\e$B<B9T$7$F$$$k$H$-$KI=Bj$OL5;k$5$l$^$9!#$3$NJQ?t$,\e(B @code{fuzzy} \e$B$G$"$k$H!"\e(B
+\e$B$"$$$^$$$KEy$7$$I=Bj$r;}$D5-;v$@$1$,4^$^$l$^$9\e(B (@pxref{Fuzzy Matching})\e$B!#\e(B
+
+@node Sorting the Summary Buffer
+@section \e$BJB$SBX$(\e(B
+
+@findex gnus-thread-sort-by-total-score
+@findex gnus-thread-sort-by-date
+@findex gnus-thread-sort-by-score
+@findex gnus-thread-sort-by-subject
+@findex gnus-thread-sort-by-author
+@findex gnus-thread-sort-by-number
+@findex gnus-thread-sort-by-random
+@vindex gnus-thread-sort-functions
+@findex gnus-thread-sort-by-most-recent-number
+@findex gnus-thread-sort-by-most-recent-date
+\e$B$b$7%9%l%C%I$N35N,I=<($r;H$C$F$$$k$N$G$"$l$P!"\e(B
+@code{gnus-thread-sort-functions} \e$B$r@_Dj$9$k$3$H$G%9%l%C%I$rJB$SBX$($k$3\e(B
+\e$B$H$,$G$-$^$9!#$=$l$O!"C1FH$N4X?t!"4X?t$N%j%9%H!"4X?t$H\e(B @code{(\e$B4X?t$G$J$$\e(B
+\e$B$b$N\e(B)} \e$B$NMWAG$G$"$k$3$H$,$G$-$^$9!#%G%#%U%)%k%H$G$O!"JB$SBX$($O5-;vHV9f\e(B
+\e$B$K$h$C$F$J$5$l$^$9!#4{$K:n$i$l$F$$$kJB$SBX$(=R8l4X?t\e(B
+\e$B$O\e(B @code{gnus-thread-sort-by-number}, @code{gnus-thread-sort-by-author},
+@code{gnus-thread-sort-by-subject}, @code{gnus-thread-sort-by-date},
+@code{gnus-thread-sort-by-score},
+@code{gnus-thread-sort-by-most-recent-number},
+@code{gnus-thread-sort-by-most-recent-date},
+@code{gnus-thread-sort-by-random} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-thread-sort-by-total-score} \e$B$G$9!#\e(B
+
+\e$B3F4X?t$OFs$D$N%9%l%C%I$r$H$j!":G=i$N%9%l%C%I$,B>$N%9%l%C%I$h$j@h$KJB$SBX\e(B
+\e$B$($i$l$k$Y$-$G$"$l$P!"\e(B@code{nil} \e$B$G$J$$CM$r$+$($7$^$9!#IaDL!"JB$SBX$($O\e(B
+\e$BK\Ev$O$=$l$>$l$N%9%l%C%I$N:,K\$r8+$k$@$1$K$h$j$J$5$l$k$3$H$K5$$rIU$1$F$/\e(B
+\e$B$@$5$$!#$b$7Fs$D0J>e$N4X?t$r;H$&>l9g!"M%@hE*JB$SBX$(%-!<$O%j%9%H$N:G8e$N\e(B
+\e$B4X?t$G$9!#$*$=$i$/$$$D$b\e(B @code{gnus-thread-sort-by-number} \e$B$rJB$SBX$(4X\e(B
+\e$B?t$N%j%9%H!=!=:G=i$,9%$^$7$$\e(B \e$B$KF~$l$F$*$/$Y$-$G$7$g$&!#$3$l$OB>$NJB$SBX\e(B
+\e$B$(4p=`$K4X$7$FEy$7$$%9%l%C%I$O5-;v$,>e$,$C$F$$$/=gHV$KI=<($5$l$k$3$H$rJ]\e(B
+\e$B>Z$7$^$9!#\e(B
+
+\e$B%9%3%"$N5U=g!"I=Bj!"$=$7$F:G8e$KHV9f!"$N=g$KJB$SBX$($?$$$N$G$"$l$P!"<!$N\e(B
+\e$B$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-thread-sort-functions
+      '(gnus-thread-sort-by-number
+        gnus-thread-sort-by-subject
+        (not gnus-thread-sort-by-total-score)))
+@end lisp
+
+\e$B:G9b%9%3%"$N%9%l%C%I$,35N,%P%C%U%!$N:G=i$KI=<($5$l$^$9!#%9%l%C%I$,F1$8%9\e(B
+\e$B%3%"$N>l9g$O!"1Q;z=g$KJB$S$+$($i$l$^$9!#%9%3%"$HI=Bj$,F1$8%9%l%C%I$OHV9f\e(B
+\e$B$GJB$SBX$($i$l!"\e(B(\e$BIaDL$O\e(B) \e$B5-;v$,E~Ce$7$?=gHV$K$J$j$^$9!#\e(B
+
+\e$B%9%3%"!"E~Ce$N5U=g$KJB$SBX$($?$$$N$G$"$l$P!"<!$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-thread-sort-functions
+      '((lambda (t1 t2)
+          (not (gnus-thread-sort-by-number t1 t2)))
+        gnus-thread-sort-by-score))
+@end lisp
+
+@vindex gnus-thread-score-function
+\e$BJQ?t\e(B @code{gnus-thread-score-function} (\e$B%G%#%U%)%k%H$O\e(B @code{+}) \e$B$KF~$C\e(B
+\e$B$F$$$k4X?t$O%9%l%C%I$NAm9g$N%9%3%"$r7W;;$9$k$?$a$KMQ$$$i$l$^$9!#Lr$KN)$D\e(B
+\e$B4X?t$O!"\e(B@code{max}, @code{min}, \e$B$b$7$/$OFs>h!"$b$7$/$O$"$J$?$N9%4q?4$r$/\e(B
+\e$B$9$0$k$h$&$J2?$+$G$7$g$&!#\e(B
+
+@findex gnus-article-sort-functions
+@findex gnus-article-sort-by-date
+@findex gnus-article-sort-by-score
+@findex gnus-article-sort-by-subject
+@findex gnus-article-sort-by-author
+@findex gnus-article-sort-by-random
+@findex gnus-article-sort-by-number
+\e$B2?$+4qL/$JM}M3$J$I$G%9%l%C%II=<($r;H$C$F$$$J$$$N$J$i!"JQ\e(B
+\e$B?t\e(B @code{gnus-article-sort-functions} \e$B$r$$$8$/$kI,MW$,$"$j$^$9!#$3$l\e(B
+\e$B$O\e(B @code{gnus-thread-sort-functions} \e$B$HHs>o$K;w$F$$$^$9$,!"5-;v$NHf3S$K\e(B
+\e$B$O>/!90c$C$?4X?t$r;H$$$^$9!#;HMQ2DG=$JJB$SBX$(=R8l4X?t\e(B
+\e$B$O\e(B @code{gnus-article-sort-by-number},
+@code{gnus-article-sort-by-author},
+@code{gnus-article-sort-by-subject}, @code{gnus-article-sort-by-date},
+@code{gnus-article-sort-by-random} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-article-sort-by-score} \e$B$G$9!#\e(B
+
+\e$B%9%l%C%I$r;H$C$F$$$J$$I=Bj$N35N,I=<($rJB$SBX$($?$$$N$G$"$l$P!"<!$N$h$&$J\e(B
+\e$B$3$H$r$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-article-sort-functions
+      '(gnus-article-sort-by-number
+        gnus-article-sort-by-subject))
+@end lisp
+
+@node Asynchronous Fetching
+@section \e$BHsF14|5-;v<hF@\e(B
+@cindex asynchronous article fetching
+@cindex article pre-fetch
+@cindex pre-fetch
+
+\e$B$b$7%K%e!<%9$r1s$/$N\e(B @acronym{NNTP} \e$B%5!<%P!<$+$i<hF@$7$F$$$k$N$G$"$l$P!"\e(B
+\e$B%M%C%H%o!<%/$NBT$A;~4V$,5-;v$rFI$`$3$H$O9|$N@^$l$k$3$H$K$7$F$7$^$&$+$b$7\e(B
+\e$B$l$^$;$s!#\e(B@kbd{n} \e$B$r2!$7$F<!$N5-;v$,8=$l$k$^$G!"$7$P$i$/BT$?$J$1$l$P$J$j\e(B
+\e$B$^$;$s!#$I$&$7$FA0$N5-;v$rFI$s$G$$$k4V$K\e(B gnus \e$B$,@h$K9T$C$F5-;v$r<hF@$7$J\e(B
+\e$B$$$N$G$7$g$&\e(B? \e$BK\Ev$K!"$=$&$7$?J}$,NI$$$N$G$O$J$$$N$G$7$g$&$+!#\e(B
+
+\e$B$^$:!"$$$/$D$+$N7Y9p$G$9!#HsF14|5-;v<hF@!"FC$K\e(B gnus \e$B$,$=$l$r9T$C$F$$$kJ}\e(B
+\e$BK!$K$O$$$/$D$+$NMn$H$77j$,$"$j$^$9!#\e(B
+
+\e$BNc$($P!"$"$J$?$OC;$$5-;v\e(B 1 \e$B$rFI$s$G$$$F!"5-;v\e(B 2 \e$B$O$H$F$bD9$/$"$J$?$O$=$l\e(B
+\e$B$rFI$`$3$H$K$O6=L#$,L5$$$H$7$^$7$g$&!#\e(BGnus \e$B$O$3$N$3$H$O$o$+$i$J$$$N$G!"\e(B
+\e$B@h$K9T$C$F5-;v\e(B 2 \e$B$r<hF@$7$^$9!#$"$J$?$O5-;v\e(B 3 \e$B$rFI$`$3$H$K$7$^$9$,!"\e(B
+gnus \e$B$O5-;v\e(B 2 \e$B$r<hF@$7$F$$$k:GCf$J$N$G!"@\B3$OIu:?$5$l$F$$$^$9!#\e(B
+
+\e$B$3$N>u67$rHr$1$k$?$a$K!"\e(Bgnus \e$B$O%5!<%P!<$KFs$D$N\e(B (\e$B$=$l$O\e(B 2 \e$B$H?t$($F$/$@$5\e(B
+\e$B$$\e(B) \e$B@\B3$rD%$k$3$H$,$G$-$^$9!#$3$l$O$"$^$j$7$FNI$$$3$H$G$O$J$$$H9M$($k?M\e(B
+\e$B$b$$$k$G$7$g$&$,!";d$K$O<B:]$NBeBX<jCJ$,8+$D$+$i$J$$$N$G$9!#M>J,$J@\B3$r\e(B
+\e$B$9$k$?$a$K$O2?$i$+$N;~4V$,$+$+$j$^$9$N$G!"\e(Bgnus \e$B$N5/F0$OCY$/$J$j$^$9!#\e(B
+
+Gnus \e$B$O$"$J$?$,FI$`$G$"$m$&5-;v$h$j$b$?$/$5$s$N5-;v$r<hF@$7$^$9!#$3$l$O\e(B
+\e$B5-;v$N@h\e(B-\e$B<hF@$r;H$o$J$$$H$-$h$j$b!"$"$J$?$N%^%7%s$H\e(B @acronym{NNTP} \e$B%5!<\e(B
+\e$B%P!<4V$K$b$C$HIi2Y$,$+$+$k$H$$$&$3$H$K$J$k$G$7$g$&!#%5!<%P!<<+?H$b$b$C$H\e(B
+\e$BIi2Y$,$+$+$k$h$&$K$J$j$^$9!=!=M>J,$J5-;v$NMW5a$H!"M>J,$J@\B3$G!#\e(B
+
+\e$B$O$$!"$3$l$GK\Ev$O$3$N$h$&$J$3$H$r$9$Y$-$GL5$$;v$,J,$+$C$?$G$7$g\e(B
+\e$B$&\e(B@dots{} \e$BK\Ev$K$=$&$7$?$$$H;W$o$J$$8B$j$O!#\e(B
+
+@vindex gnus-asynchronous
+\e$B$3$l$,J}K!$G$9\e(B: @code{gnus-asynchronous} \e$B$r\e(B @code{t} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+\e$B;D$j$N$3$H$O<+F0E*$K5/$3$j$^$9!#\e(B
+
+@vindex gnus-use-article-prefetch
+@code{gnus-use-article-prefetch} \e$B$r@_Dj$9$k$3$H$K$h$j!"$I$l$/$i$$$N5-;v\e(B
+\e$B$,@h$K<hF@$5$l$k$Y$-$+$rA`:n$9$k$3$H$,$G$-$^$9!#$3$l$O%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B 30 \e$B$G!"%0%k!<%W$N5-;v$rFI$s$G$$$k$H$-$K!"%P%C%/%(%s%I$,<!$N\e(B 30 \e$B5-;v$r\e(B
+\e$B@h\e(B-\e$B<hF@$9$k$H$$$&$3$H$G$9!#$3$NJQ?t$,\e(B @code{t} \e$B$G$"$k$H!"%P%C%/%(%s%I$O\e(B
+\e$B@)8BL5$/<hF@$G$-$k$9$Y$F$N5-;v$r@h\e(B-\e$B<hF@$7$h$&$H$7$^$9!#$3$l\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$H!"@h\e(B-\e$B<hF@$O9T$o$l$^$;$s!#\e(B
+
+@vindex gnus-async-prefetch-article-p
+@findex gnus-async-read-p
+\e$B$*$=$i$/!"@h\e(B-\e$B<hF@$r$7$?$/$J$$5-;v$,$$$/$D$+$"$k$G$7$g$&!=!=Nc$($P!"4{FI\e(B
+\e$B5-;v!#JQ?t\e(B @code{gnus-async-prefetch-article-p} \e$B$O5-;v$,@h$K<hF@$5$l$k$Y\e(B
+\e$B$-$+$I$&$+$r@)8f$7$^$9!#$3$N4X?t$OLdBj$N5-;v$,@h\e(B-\e$B<hF@$5$l$k$Y$-$G$"$l\e(B
+\e$B$P\e(B @code{nil} \e$B$G$J$$CM$r$+$($9$Y$-$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-async-read-p} \e$B$G!"$=$l$O4{FI5-;v$K$O\e(B @code{nil} \e$B$r$+$($7$^\e(B
+\e$B$9!#$3$N4X?t$O5-;v$N%G!<%?9=B$$rM#0l$N0z?t$H$7$F8F$P$l$^$9!#\e(B
+
+\e$BNc$($P!"$b$7\e(B 100 \e$B9T$h$j$bC;$$L$FI5-;v$N$_$r@h$K<hF@$7$?$$$N$G$"$l$P!"<!\e(B
+\e$B$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(defun my-async-short-unread-p (data)
+  "Return non-nil for short, unread articles."
+  (and (gnus-data-unread-p data)
+       (< (mail-header-lines (gnus-data-header data))
+          100)))
+
+(setq gnus-async-prefetch-article-p 'my-async-short-unread-p)
+@end lisp
+
+\e$B$3$l$i$N4X?t$O2?EY$b2?EY$b8F$P$l$^$9$N$G!"\e(Bgnus \e$B$rCY$/$7$9$.$J$$$h$&$K!"\e(B
+\e$BC;$/4EH~$G$"$k$N$,9%$^$7$$$G$9!#$*$=$i$/!"$3$N$h$&$J$b$N$r%P%$%H%3%s%Q%$\e(B
+\e$B%k\e(B (byte-compile) \e$B$9$k$N$ONI$$CeA[$G$7$g$&!#\e(B
+
+@vindex gnus-prefetched-article-deletion-strategy
+\e$B5-;v$OHsF14|%P%C%U%!$+$iCY$+$lAa$+$l:o=|$5$l$J$1$l$P$J$j$^$;$s!#\e(B
+@code{gnus-prefetched-article-deletion-strategy} \e$B$O$$$D5-;v$r:o=|$9$k$+\e(B
+\e$B$r;XDj$7$F$$$^$9!#$3$l$O0J2<$NMWAG$r4^$`$h$&$J%j%9%H$G$9\e(B:
+
+@table @code
+@item read
+\e$B5-;v$,FI$^$l$?$H$-$K:o=|$7$^$9!#\e(B
+
+@item exit
+\e$B%0%k!<%W$rH4$1$?$H$-$K5-;v$r:o=|$7$^$9!#\e(B
+@end table
+
+\e$B%G%#%U%)%k%H$NCM$O\e(B @code{(read exit)} \e$B$G$9!#\e(B
+
+@c @vindex gnus-use-header-prefetch
+@c @code{gnus-use-header-prefetch} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"<!$N%0%k!<%W$+$i\e(B
+@c \e$B5-;v$r@h$K<hF@$7$^$9!#\e(B
+
+@node Article Caching
+@section \e$B5-;v$N%-%c%C%7%e\e(B
+@cindex article caching
+@cindex caching
+
+\e$B$b$7\e(B@emph{\e$BHs>o$K\e(B}\e$BCY$$\e(B @acronym{NNTP} \e$B@\B3$G$"$k$J$i$P!"5-;v%-%c%C%7%e$r\e(B
+\e$B$9$k$3$H$r9M$($k$+$b$7$l$^$;$s!#$=$&$9$k$H!"$=$l$>$l$N5-;v$O$"$J$?$N%[!<\e(B
+\e$B%`%G%#%l%/%H%j$N2<$K%m!<%+%k$KN/$a$i$^$9!#4{$K?dB,$5$l$F$$$k$+$bCN$l$^$;\e(B
+\e$B$s$,!"$3$l$O\e(B @emph{\e$B5pBg$J\e(B}\e$B%G%#%9%/%9%Z!<%9$r?)$$!"\e(Bi\e$B%N!<%I$bHs>o$KB.$/?)\e(B
+\e$B$$$D$V$92DG=@-$,$"$k$?$a!"$=$l$O$"$J$?$NF,$r1K$,$;$k;v$K$J$k$+$b$7$l$^$;\e(B
+\e$B$s!#%&%)%C%+$NCf$G!#\e(B
+
+\e$B$G$bCm0U?<$/;H$o$l$l$P!"$=$l$O5-;v$rJ]B8$9$k4JC1$JJ}K!$K$J$jF@$^$9!#\e(B
+
+@vindex gnus-use-long-file-name
+@vindex gnus-cache-directory
+@vindex gnus-use-cache
+\e$B%-%c%C%7%e$r<B9T$9$k$?$a$K$O!"\e(B@code{gnus-use-cache} \e$B$r\e(B @code{t} \e$B$K@_Dj$7\e(B
+\e$B$^$9!#%G%#%U%)%k%H$G$O!"$9$Y$F$N2D;k$^$?$OJ]N1$H$7$F0u$NIU$$$F$$$k5-;v$O\e(B
+\e$B%m!<%+%k$N%-%c%C%7%e$KJ#<L$5$l$^$9!#$3$N%-%c%C%7%e$,J?$i$J9=B$$+3,AXE*$G\e(B
+\e$B$"$k$+$O!"$$$D$b$I$*$j!"JQ?t\e(B @code{gnus-use-long-file-name} \e$B$G@)8f$5$l$^\e(B
+\e$B$9!#\e(B
+
+\e$B2D;k$+J]N15-;v$r:FA*Br$7$?>l9g$O!"%5!<%P!<$NBe$o$j$K%-%c%C%7%e$+$i<hF@$5\e(B
+\e$B$l$^$9!#%-%c%C%7%e$K$"$k5-;v$O4|8B@Z$l:o=|$5$l$^$;$s$N$G!"5-;v$,B0$7$F$$\e(B
+\e$B$k$H$3$m$K;D$7$?$^$^$G5-;v$rJ]B8$9$kJ}K!$H$7$F;H$&;v$,$G$-$k$+$b$7$l$^$;\e(B
+\e$B$s!#J]B8$7$?$$5-;v$r$9$Y$FJ]N1$N0u$rIU$1$F!"8e$O?4G[$OMW$j$^$;$s!#\e(B
+
+\e$B5-;v$K4{FI$N0u$,IU$$$?$H$-$K!"$=$l$O%-%c%C%7%e$+$i:o=|$5$l$k$N$G$7$g$&$+!#\e(B
+
+@vindex gnus-cache-remove-articles
+@vindex gnus-cache-enter-articles
+\e$B%-%c%C%7%e\e(B \e$B$XF~$k\e(B/\e$B$+$i:o=|$5$l$k\e(B \e$B$OJQ\e(B
+\e$B?t\e(B @code{gnus-cache-enter-articles} \e$B$H\e(B @code{gnus-cache-remove-articles} \e$B$K\e(B
+\e$B$h$C$F@)8f$5$l$^$9!#$3$l$i$ON>J}$H$b%7%s%\%k$N%j%9%H$G$9!#A0<T$O%G%#%U%)\e(B
+\e$B%k%H$G$O\e(B @code{(ticked dormant)} \e$B$G!"2D;k$HJ]N15-;v$O%-%c%C%7%e$KF~$l$i\e(B
+\e$B$l$k$H$$$&;v$G$9!#8e<T$O%G%#%U%)%k%H$G$O\e(B @code{(read)} \e$B$G!"4{FI$N0u$,IU\e(B
+\e$B$$$?5-;v$O%-%c%C%7%e$+$i:o=|$5$l$k$H$$$&;v$G$9!#$*$=$i$/$3$l$i$NFs$D$N%j\e(B
+\e$B%9%H$O\e(B @code{ticked}, @code{dormant}, @code{unread} \e$B$*$h\e(B
+\e$B$S\e(B @code{read} \e$B$+$i$J$k$G$7$g$&!#\e(B
+
+@findex gnus-jog-cache
+\e$B$=$l$G!"$I$&$d$C$FBgNL$N5-;v<hF@$HCyC_<B8=$5$l$k$N$G$7$g$&$+!#L?\e(B
+\e$BNa\e(B @code{gnus-jog-cache} \e$B$OA4$F$N9XFI%0%k!<%W$KBP$7$F!"$9$Y$F$NL$FI5-;v\e(B
+\e$B$rMW5a$7!"%9%3%"$rIU$1!"%-%c%C%7%e$KJ]B8$7$^$9!#$3$NL?Na$r<B:]$K!"<B:]$K\e(B
+\e$B<B:]$K<B:]$K!";H$&$N$O!"\e(B1) @acronym{NNTP} \e$B%5!<%P!<$H$N@\B3$,K\Ev$K!"K\Ev\e(B
+\e$B$K!"K\Ev$KCY$/\e(B 2) \e$BK\Ev$K!"K\Ev$K!"K\Ev$K5pBg$J%G%#%9%/$r;}$C$F$$$k$H$-$@\e(B
+\e$B$1$K$9$k$Y$-$G$9!#$3$l$O??LLL\$K$$$C$F$$$^$9!#%@%&%s%m!<%I$5$l$k5-;v$N?t\e(B
+\e$B$r>/$J$/$9$k0l$D$NJ}K!$O!"M_$7$/$J$$5-;v$N%9%3%"$rDc$/$7!"4{FI$N0u$rIU$1\e(B
+\e$B$k;v$G$9!#$=$&$7$?>l9g!"$=$l$i$O$3$NL?Na$G$O%@%&%s%m!<%I$5$l$^$;$s!#\e(B
+
+@vindex gnus-uncacheable-groups
+@vindex gnus-cacheable-groups
+\e$B$$$/$D$+$N%0%k!<%W$G$O%-%c%C%7%e$r$7$?$/$J$$$H$$$&$N$ONI$/$"$k;v$G$9!#Nc\e(B
+\e$B$($P!"\e(B@code{nnml} \e$B%a!<%k%G%#%l%/%H%j!<$,%[!<%`%G%#%l%/%H%j!<$N2<$K$"$l$P!"\e(B
+\e$B$=$l$r$"$J$?$N%[!<%`%G%#%l%/%H%j!<$N2<$NJL$N>l=j$K%-%c%C%7%e$9$k$N$O0UL#\e(B
+\e$B$NL5$$;v$G$9!#$"$J$?$,FsG\$NMFNL$r;H$&;v$,NI$$$H46$8$J$$8B$j$O!#\e(B
+
+\e$B%-%c%C%7%e$r@)8B$9$k$?$a$K!"\e(B@code{gnus-cacheable-groups} \e$B$r%-%c%C%7%e$9\e(B
+\e$B$k%0%k!<%W$NO"A[%j%9%H!"Nc$($P\e(B @samp{^nntp} \e$B$H$9$k$+!"@55,I=\e(B
+\e$B8=\e(B @code{gnus-uncacheable-groups} \e$B$rNc$($P!"\e(B@samp{^nnml} \e$B$K@_Dj$7$F2<$5\e(B
+\e$B$$!#N>J}$NJQ?t$N=i4|CM$O\e(B @code{nil} \e$B$G$9!#$b$7%0%k!<%W$,N>J}$N@55,I=8=$K\e(B
+\e$B9gCW$9$k$H!"$=$N%0%k!<%W$O%-%c%C%7%e$5$l$^$;$s!#\e(B
+
+@findex gnus-cache-generate-nov-databases
+@findex gnus-cache-generate-active
+@vindex gnus-cache-active-file
+\e$B%-%c%C%7%e$O$I$N5-;v$,4^$^$l$F$$$k$+$N>pJs$r%"%/%F%#%V%U%!%$\e(B
+\e$B%k\e(B (@code{gnus-cache-active-file}) \e$B$KN/$a$^$9!#$3$N%U%!%$%k\e(B (\e$B$b$7$/$O%-%c%C\e(B
+\e$B%7%e$NB>$NItJ,\e(B) \e$B$,2?$i$+$NM}M3$G$0$A$c$0$A$c$K$J$C$F$7$^$C$?>l9g!"\e(B
+gnus \e$B$OJ*;v$r@5$7$/$9$k$?$a$KFs$D$N4X?t$r$*4+$a$7$^$9!#\e(B
+@kbd{M-x gnus-cache-generate-nov-databases} \e$B$O$9$Y$F$N\e(B @acronym{NOV} \e$B%U%!\e(B
+\e$B%$%k$r\e(B (\e$B:F\e(B) \e$B:n@.$7!"\e(B@kbd{gnus-cache-generate-active} \e$B$O%"%/%F%#%V%U%!%$\e(B
+\e$B%k$r\e(B (\e$B:F\e(B) \e$B:n@.$7$^$9!#\e(B
+
+@findex gnus-cache-move-cache
+@code{gnus-cache-move-cache} \e$B$O$9$Y$F$N\e(B @code{gnus-cache-directory} \e$B$r$I\e(B
+\e$B$3$+JL$N>l=j$K0\F0$7$^$9!#$"$J$?$O$I$3$K0\F0$5$;$k$+$r?R$M$i$l$^$9!#$=$l$C\e(B
+\e$B$F$+$C$3$$$$$G$7$g\e(B?
+
+@node Persistent Articles
+@section \e$B1JB35-;v\e(B
+@cindex persistent articles
+\e$B5-;v$N%-%c%C%7%e$H6a$$4X78$K$"$k$b$N$K!"\e(B@dfn{\e$B1JB35-;v\e(B}\e$B$,$"$j$^$9!#<B:]!"\e(B
+\e$B$=$l$O%-%c%C%7%e$NJL$N8+J}$G!";d$N0U8+$G$O$=$NJ}$,$b$C$HLr$KN)$A$^$9!#\e(B
+
+\e$BNc$($P!"%K%e!<%9%0%k!<%W$rFI$s$G$$$F!"$=$N$^$^1J1s$KJ]B8$7$FHkB"$7$?$$!"\e(B
+\e$B$$$/$D$+$N2ACM$"$kJu@P$K=P2q$C$?$H$7$^$7$g$&!#IaDL$O$=$l$r%U%!%$%k$KJ]B8\e(B
+\e$B$7$^$9\e(B (\e$BB?$/$NJ]B8L?Na$N0l$D$r;H$C$F\e(B)\e$B!#$=$l$NLdBj$O!"C1$K$"$N!"7y$J$@$1\e(B
+\e$B$G$9!#M}A[E*$K$O!"5-;v$O%0%k!<%W$G$"$J$?$,8+$D$1$?>l=j$K1J1s$K;D$C$F$$$k\e(B
+\e$B$Y$-$G$7$g$&!#%K%e!<%9%5!<%P!<$K$*$1$k4|8B:o=|$K$O1F6A$5$l$J$$$G!#\e(B
+
+\e$B$3$l$,\e(B@dfn{\e$B1JB35-;v\e(B}\e$B$G$9!=!=5-;v$O:o=|$5$l$^$;$s!#$=$l$OIaDL$N%-%c%C%7%e\e(B
+\e$BL?Na$r;H$C$F<BAu$5$l$F$$$^$9$,!"1JB35-;v$N4IM}$r$9$k$?$a$KFs$D$NL@<(E*$J\e(B
+\e$BL?Na$r;H$$$^$9\e(B:
+
+@table @kbd
+@item *
+@kindex * (\e$B35N,\e(B)
+@findex gnus-cache-enter-article
+\e$B8=:_$N5-;v$r1JB3$K$7$^$9\e(B (@code{gnus-cache-enter-article})\e$B!#\e(B
+
+@item M-*
+@kindex M-* (\e$B35N,\e(B)
+@findex gnus-cache-remove-article
+\e$B8=:_$N5-;v$r1JB35-;v$+$i<h$j=|$-$^$9\e(B (@code{gnus-cache-remove-articles})\e$B!#\e(B
+\e$B$3$l$OIaDL$O5-;v$r:o=|$7$^$9!#\e(B
+@end table
+
+\e$B$3$NL?Na$ON>J}$H$b%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$rM}2r$7$^$9!#\e(B
+
+\e$B$b$71JB35-;v$K$@$16=L#$,$"$k$N$G$7$?$i!"2D;k5-;v\e(B (\e$B$d$=$NB>$N$b$N\e(B) \e$B$,%-%c%C\e(B
+\e$B%7%e$KF~$k$N$rHr$1$k$?$a$K!"\e(B@code{gnus-use-cache} \e$B$r\e(B @code{passive} \e$B$K@_\e(B
+\e$BDj$9$k$N$,NI$$$G$7$g$&\e(B:
+
+@lisp
+(setq gnus-use-cache 'passive)
+@end lisp
+
+@node Article Backlog
+@section \e$B5-;v$N%P%C%/%m%0\e(B
+@cindex backlog
+@cindex article backlog
+\e$B$b$7CY$$@\B3$7$+$J$$>l9g$G!"%-%c%C%7%e$r;H$&$H$$$&H/A[$O$"$^$jL%NOE*$G$O\e(B
+\e$B$J$$$H$-\e(B (\e$B<B:]$=$&$J$N$G$9$,\e(B)\e$B!"\e(B@dfn{\e$B%P%C%/%m%0\e(B} \e$B$K@Z$jBX$($k;v$K$h$C$F\e(B
+\e$B>u67$r2?$H$+$9$k$3$H$,$G$-$^$9!#$3$l$O4{$KFI$s$@5-;v$r:F<hF@$7$J$/$FNI$$\e(B
+\e$B$h$&$K!"\e(Bgnus \e$B$,4{$KFI$s$@5-;v$r0l;~J]B8$7$F$*$/$H$3$m$G$9!#$3$l$O$b$A$m\e(B
+\e$B$s!"$"$J$?$K:G6aFI$s$@5-;v$r:F$SA*Br$9$kJJ$,$"$k$H$-$@$1$KLrN)$A$^$9!#$b\e(B
+\e$B$7@dBP$K$=$l$r$7$J$$$N$G$"$l$P!"%P%C%/%m%0$r$9$k$3$H$O\e(B gnus \e$B$r>/$7CY$/$7!"\e(B
+\e$B%a%b%j!<$N;HMQNL$r$$$/$i$+A}$d$7$^$9!#\e(B
+
+@vindex gnus-keep-backlog
+\e$B$b$7\e(B @code{gnus-keep-backlog} \e$B$r?t;z\e(B @var{n} \e$B$K@_Dj$9$k$H!"\e(Bgnus \e$B$O:GBg\e(B
+\e$B$G\e(B @var{n} \e$B$N8E$$5-;v$r8e$N:F<hF@$N$?$a$K%P%C%U%!$KN/$a$F$*$-$^$9!#$3$N\e(B
+\e$BJQ?t$,\e(B @code{nil} \e$B$G$O$J$/!"?t;z$G$b$J$$>l9g!"\e(Bgnus \e$B$O\e(B@emph{\e$BA4$F\e(B}\e$B$N4{FI5-\e(B
+\e$B;v$r$?$/$o$($^$9!#$3$l$O$"$J$?$N\e(B Emacs \e$B$,!"K=H/$7$F$"$J$?$N%^%7%s$,Mn$A\e(B
+\e$B$k$^$G@)8B$J$/KD$l>e$,$k$H$$$&$3$H$G$9!#;d$O$"$J$?J}A4$F$,855$$G$$$i$l$k\e(B
+\e$B$h$&$K$3$3$K=q$-2C$($^$7$?!#\e(B
+
+\e$B%G%#%U%)%k%HCM$O\e(B 20 \e$B$G$9!#\e(B
+
+@node Saving Articles
+@section \e$B5-;v$NJ]B8\e(B
+@cindex saving articles
+
+Gnus \e$B$O$?$/$5$s$NJ}K!$G5-;v$rJ]B8$9$k;v$,$G$-$^$9!#0J2<$N$b$N$OHs>o$KN(\e(B
+\e$BD>$JJ}K!\e(B (\e$BNc$($P!"5-;v$,J]B8$9$kA0$K$[$H$s$I2?$b$J$5$l$J$$\e(B) \e$B$G5-;v$rJ]B8\e(B
+\e$B$9$k$?$a$N@bL@$G$9!#0c$C$?<jCJ\e(B (uudecode\e$B$9$k!"\e(Bshar \e$B%U%!%$%k$rE83+$9\e(B
+\e$B$k\e(B) \e$B$K$D$$$F$O\e(B@code{gnus-uu} \e$B$r;H$&$N$,NI$$$G$7$g\e(B
+\e$B$&\e(B (@pxref{Decoding Articles})\e$B!#\e(B
+
+\e$B$3$3$K:\$C$F$$$k%3%^%s%I$OBP>]$,%U%!%$%k$G$9!#%0%k!<%W$KJ]B8$7$?$$>l9g\e(B
+\e$B$O\e(B @kbd{B c} (@code{gnus-summary-copy-article}) \e$B%3%^%s%I$r;2>H$7$F2<$5\e(B
+\e$B$$\e(B (@pxref{Mail Group Commands})\e$B!#\e(B
+
+@vindex gnus-save-all-headers
+@code{gnus-save-all-headers} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O5-;v$rJ]B8$9\e(B
+\e$B$kA0$KK>$^$7$/$J$$%X%C%@!<$r>C5n$7$^$;$s!#\e(B
+
+@vindex gnus-saved-headers
+\e$B$b$7>e$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"@55,I=\e(B
+\e$B8=\e(B @code{gnus-saved-headers} \e$B$K9gCW$9$k$9$Y$F$N%X%C%@!<$O;D$5$l!";D$j$N\e(B
+\e$B$b$N$OJ]B8$9$kA0$K:o=|$5$l$^$9!#\e(B
+
+@table @kbd
+@item O o
+@itemx o
+@kindex O o (\e$B35N,\e(B)
+@kindex o (\e$B35N,\e(B)
+@findex gnus-summary-save-article
+@c @icon{gnus-summary-save-article}
+\e$B%G%#%U%)%k%H$N5-;vJ]B8$rMQ$$$F8=:_$N5-;v$rJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article})\e$B!#\e(B
+
+@item O m
+@kindex O m (\e$B35N,\e(B)
+@findex gnus-summary-save-article-mail
+\e$B8=:_$N5-;v$r%a!<%k$NMM<0$GJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-mail})\e$B!#\e(B
+
+@item O r
+@kindex O r (\e$B35N,\e(B)
+@findex gnus-summary-save-article-rmail
+\e$B8=:_$N5-;v$r\e(B Rmail \e$B$NMM<0$GJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-rmail})\e$B!#\e(B
+
+@item O f
+@kindex O f (\e$B35N,\e(B)
+@findex gnus-summary-save-article-file
+@c @icon{gnus-summary-save-article-file}
+\e$B8=:_$N5-;v$rIaDL$N%U%!%$%k\e(B (plain file) \e$BMM<0$GJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-file})\e$B!#\e(B
+
+@item O F
+@kindex O F (\e$B35N,\e(B)
+@findex gnus-summary-write-article-file
+\e$B8=:_$N5-;v$rIaDL$N%U%!%$%kMM<0$GJ]B8$7!"0JA0$N%U%!%$%k$NFbMF$r>e=q$-$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-write-article-file})\e$B!#\e(B
+
+@item O b
+@kindex O b (\e$B35N,\e(B)
+@findex gnus-summary-save-article-body-file
+\e$B8=:_$N5-;v$NK\J8\e(B (body) \e$B$rIaDL$N%U%!%$%kMM<0$GJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-body-file})\e$B!#\e(B
+
+@item O h
+@kindex O h (\e$B35N,\e(B)
+@findex gnus-summary-save-article-folder
+\e$B8=:_$N5-;v$r\e(B mh \e$B$N%U%)%k%@!<$NMM<0$GJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-folder})\e$B!#\e(B
+
+@item O v
+@kindex O v (\e$B35N,\e(B)
+@findex gnus-summary-save-article-vm
+\e$B8=:_$N5-;v$r\e(B VM \e$B%U%)%k%@!<$KJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-save-article-vm})\e$B!#\e(B
+
+@item O p
+@itemx |
+@kindex O p (\e$B35N,\e(B)
+@kindex | (\e$B35N,\e(B)
+@findex gnus-summary-pipe-output
+\e$B8=:_$N5-;v$r%Q%$%W$KJ]B8$7$^$9!#$&!<$s$H!"$"$N$)!";d$,8@$*$&$H$7$F$$$k;v\e(B
+\e$B$O!=!=8=:_$N5-;v$r%W%m%;%9$K%Q%$%W$9$k$H$$$&$3$H$G\e(B
+\e$B$9\e(B (@code{gnus-summary-pipe-output})\e$B!#%7%s%\%k@\F,<-\e(B (@pxref{Symbolic
+Prefixes}) \e$B$,M?$($i$l$k$H!"%Q%$%W$X$N=PNO$K40A4$J%X%C%@!<$r4^$a$^$9!#\e(B
+
+@item O P
+@kindex O P (\e$B35N,\e(B)
+@findex gnus-summary-muttprint
+@vindex gnus-summary-muttprint-program
+\e$B8=:_$N5-;v$r\e(B muttprint \e$B$KJ]B8$7$^$9!#$3$l$O30It%W%m%0%i\e(B
+\e$B%`\e(B @uref{http://muttprint.sourceforge.net/, Muttprint} \e$B$r;H$C$F5-;v$r0u\e(B
+\e$B:~$7$^$9!#%W%m%0%i%`L>$H;HMQ$9$k%*%W%7%g%s$O!"JQ\e(B
+\e$B?t\e(B @code{gnus-summary-muttprint-program} \e$B$G;XDj$5$l$^$9!#\e(B
+(@code{gnus-summary-muttprint})\e$B!#\e(B
+@end table
+
+@vindex gnus-prompt-before-saving
+\e$B$9$Y$F$N$3$l$i$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$r;H$$$^\e(B
+\e$B$9\e(B (@pxref{Process/Prefix})\e$B!#$b$7$3$l$i$N4X?t$r;H$C$F$?$/$5$s$N5-;v$rJ]\e(B
+\e$BB8$7$?>l9g!"$=$l$>$l$N$9$Y$F$N5-;v$KBP$7$F%U%!%$%kL>$NF~NO$rMW5a$5$l$k;v\e(B
+\e$B$KK0$-K0$-$9$k$G$7$g$&!#F~NOB%?JF0:n$OJQ\e(B
+\e$B?t\e(B @code{gnus-prompt-before-saving} \e$B$K$h$C$F@)8f$5$l$^$9!#$3$l$O%G%#%U%)\e(B
+\e$B%k%H$G$O\e(B @code{always} \e$B$G!"$"$J$?$,CN$C$F$$$F7y$,$C$F$$$k!"2a>j$JB%?JF0\e(B
+\e$B:n$r$7$^$9!#Be$o$j$K$3$NJQ?t$r\e(B @code{t} \e$B$K@_Dj$9$k$H!"$"$J$?$,J]B8$9$k$=\e(B
+\e$B$l$>$l$N0lO"$N5-;v$KBP$7$F0l2s$@$1B%$5$l$^$9!#K\Ev$K\e(B gnus \e$B$K$9$Y$F$N;W9M\e(B
+\e$B$r$5$;$?$$$N$G$"$l$P!"$3$NJQ?t$r\e(B @code{nil} \e$B$K$9$k$3$H$5$($G$-$^$9!#$=$7\e(B
+\e$B$F!"5-;v$rJ]B8$9$k$?$a$N%U%!%$%k$rB%$5$l$k;v$O$"$j$^$;$s!#\e(BGnus \e$B$OC1=c$K\e(B
+\e$B$9$Y$F$N5-;v$r%G%#%U%)%k%H$N%U%!%$%k$KJ]B8$7$^$9!#\e(B
+
+@vindex gnus-default-article-saver
+Gnus \e$B$,$"$J$?$NK>$`$H$*$j$K$J$k$h$&$K!"JQ\e(B
+\e$B?t\e(B @code{gnus-default-article-saver} \e$B$r%+%9%?%^%$%:$9$k;v$,$G$-$^$9!#2<\e(B
+\e$B$NO;$D$N4{@=4X?t$r;H$&;v$,$G$-$^$9$7!"<+J,<+?H$N4X?t$r:n$k;v$b$G$-$^$9!#\e(B
+
+@table @code
+@item gnus-summary-save-in-rmail
+@findex gnus-summary-save-in-rmail
+@vindex gnus-rmail-save-name
+@findex gnus-plain-save-name
+\e$B$3$l$O%G%#%U%)%k%H$NMM<0!"\e(B@dfn{Babyl} \e$B$G$9!#JQ\e(B
+\e$B?t\e(B @code{gnus-ramil-save-name} \e$B$KF~$C$F$$$k4X?t$r!"5-;v$rJ]B8$9$k$?$a$N\e(B
+\e$B%U%!%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-plain-save-name} \e$B$G$9!#\e(B
+
+@item gnus-summary-save-in-mail
+@findex gnus-summary-save-in-mail
+@vindex gnus-mail-save-name
+Unix \e$B%a!<%k\e(B (mbox) \e$B%U%!%$%k$KJ]B8$7$^$9!#JQ\e(B
+\e$B?t\e(B @code{gnus-mail-save-name} \e$B$KF~$C$F$$$k4X?t$r!"5-;v$rJ]B8$9$k$?$a$N%U%!\e(B
+\e$B%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-plain-save-name} \e$B$G$9!#\e(B
+
+@item gnus-summary-save-in-file
+@findex gnus-summary-save-in-file
+@vindex gnus-file-save-name
+@findex gnus-numeric-save-name
+\e$B5-;v$rDL>o$N%U%!%$%k$N8e$KDI2C$7$^$9!#JQ?t\e(B @code{gnus-file-save-name} \e$B$K\e(B
+\e$BF~$C$F$$$k4X?t$r!"5-;v$rJ]B8$9$k$?$a$N%U%!%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^\e(B
+\e$B$9!#%G%#%U%)%k%H$O\e(B @code{gnus-numeric-save-name} \e$B$G$9!#\e(B
+
+@item gnus-summary-write-to-file
+@findex gnus-summary-write-to-file
+\e$B5-;v$r%9%H%l!<%H$KDL>o$N%U%!%$%k$KJ]B8$7$^$9!#$=$N%U%!%$%k$,B8:_$7$F$$$?\e(B
+\e$B$i>e=q$-$5$l$^$9!#JQ?t\e(B @code{gnus-file-save-name} \e$B$KF~$C$F$$$k4X?t$r!"5-\e(B
+\e$B;v$rJ]B8$9$k$?$a$N%U%!%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-numeric-save-name} \e$B$G$9!#\e(B
+
+@item gnus-summary-save-body-in-file
+@findex gnus-summary-save-body-in-file
+\e$B5-;v$NK\BN$rDL>o$N%U%!%$%k$N8e$KDI2C$7$^$9!#JQ\e(B
+\e$B?t\e(B @code{gnus-file-save-name} \e$B$KF~$C$F$$$k4X?t$r!"5-;v$rJ]B8$9$k$?$a$N%U%!\e(B
+\e$B%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-numeric-save-name} \e$B$G$9!#\e(B
+
+@item gnus-summary-save-in-folder
+@findex gnus-summary-save-in-folder
+@findex gnus-folder-save-name
+@findex gnus-Folder-save-name
+@vindex gnus-folder-save-name
+@cindex rcvstore
+@cindex MH folders
+MH \e$B%i%$%V%i%j!<$N\e(B @code{rcvstore} \e$B$rMQ$$$k;v$K$h$C$F5-;v$r\e(B MH \e$B%U%)%k%@!<\e(B
+\e$B$KJ]B8$7$^$9!#JQ?t\e(B @code{gnus-folder-save-name} \e$B$KF~$C$F$$$k4X?t$r!"5-;v\e(B
+\e$B$rJ]B8$9$k%U%!%$%kL>$r<hF@$9$k$?$a$K;HMQ$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{gnus-folder-save-name} \e$B$G$9$,!"\e(B@code{gnus-Folder-save-name} \e$B$b\e(B
+\e$B;H$&;v$,$G$-$F!"$3$A$i$O@hF,$,BgJ8;z!";D$j$,>.J8;z$K$J$C$?L>A0$r$D$/$j$^\e(B
+\e$B$9!#\e(B
+
+@item gnus-summary-save-in-vm
+@findex gnus-summary-save-in-vm
+\e$B5-;v$r\e(B VM \e$B%U%)%k%@!<$KJ]B8$7$^$9!#$3$N@_Dj$r;H$&$?$a$K$O\e(B VM \e$B%a!<%k%j!<%@!<\e(B
+\e$B$,I,MW$G$9!#\e(B
+@end table
+
+@vindex gnus-article-save-directory
+\e$B$3$l$i$NA4$F$N4X?t$O:G8e$N0l$D$r=|$$$F!"4D6-JQ?t\e(B @env{SAVEDIR} \e$B$K$h$C$F\e(B
+\e$B=i4|2=$5$l$k\e(B @code{gnus-article-save-directory} \e$B$K5-;v$rJ]B8$7$^$9!#$3$l\e(B
+\e$B$O%G%#%U%)%k%H$G$O\e(B @file{~/News/} \e$B$G$9!#\e(B
+
+\e$B>e$K$"$k$h$&$K!"5-;v$rJ]B8$9$k$?$a$N%U%!%$%k$NE,@Z$JL>A0$r8+$D$1$k$?$a$K!"\e(B
+\e$B4X?t$O0c$C$?4X?t$rMQ$$$^$9!#0J2<$OL>A0$r@8@.$9$k$?$a$K;HMQ2DG=$J4X?t$N%j\e(B
+\e$B%9%H$G$9\e(B:
+
+@table @code
+@item gnus-Numeric-save-name
+@findex gnus-Numeric-save-name
+@file{~/News/Alt.andera-dworkin/45} \e$B$N$h$&$J%U%!%$%kL>!#\e(B
+
+@item gnus-numeric-save-name
+@findex gnus-numeric-save-name
+@file{~/News/alt.andera-dworkin/45} \e$B$N$h$&$J%U%!%$%kL>!#\e(B
+
+@item gnus-Plain-save-name
+@findex gnus-Plain-save-name
+@file{~/News/Alt.andera-dworkin} \e$B$N$h$&$J%U%!%$%kL>!#\e(B
+
+@item gnus-plain-save-name
+@findex gnus-plain-save-name
+@file{~/News/alt.andera-dworkin} \e$B$N$h$&$J%U%!%$%kL>!#\e(B
+
+@item gnus-sender-save-name
+@findex gnus-sender-save-name
+@file{~/News/larsi} \e$B$N$h$&$J%U%!%$%kL>!#\e(B
+@end table
+
+@vindex gnus-split-methods
+\e$BO"A[%j%9%H\e(B @code{gnus-split-methods} \e$B$K@55,I=8=$rJ|$j9~$`;v$K$h$C$F!"\e(B
+gnus \e$B$K5-;v$rJ]B8$9$k>l=j$rDs0F$9$k;v$,$G$-$^$9!#Nc$($P!"\e(Bgnus \e$B$K4XO"$7$?\e(B
+\e$B5-;v$r%U%!%$%k\e(B @file{gnus-stuff} \e$B$K!"\e(BVM \e$B$K4XO"$7$?5-;v\e(B
+\e$B$r\e(B @file{vm-stuff} \e$BJ]B8$7$?$1$l$P!"$3$NJQ?t$r0J2<$N$h$&$K$9$k;v$,$G$-$^\e(B
+\e$B$9\e(B:
+
+@lisp
+(("^Subject:.*gnus\\|^Newsgroups:.*gnus" "gnus-stuff")
+ ("^Subject:.*vm\\|^Xref:.*vm" "vm-stuff")
+ (my-choosing-function "../other-dir/my-stuff")
+ ((equal gnus-newsgroup-name "mail.misc") "mail-stuff"))
+@end lisp
+
+\e$B$3$l$O$=$l$>$l$NMWAG$,!"Fs$D$NMWAG!=!=\e(B@dfn{\e$B9gCW\e(B} \e$B$H\e(B @dfn{\e$B%U%!%$%k\e(B} \e$B$r;}\e(B
+\e$B$D%j%9%H$G$"$k%j%9%H$G$"$k$H$$$&;v$,$o$+$j$^$9!#9gCW$OJ8;zNs\e(B (\e$B$3$N>l9g$O\e(B
+\e$B5-;v$N%X%C%@!<$K9gCW$9$k@55,I=8=$H$7$F;H$o$l$^$9\e(B) \e$B$*$h$S!"%7%s%\%k\e(B (\e$B%0%k!<\e(B
+\e$B%WL>$r0z?t$H$7$F!"4X?t$H$7$F8F$P$l$^$9\e(B) \e$B$*$h$S!"%j%9%H\e(B (\e$B$3$l$OI>\e(B
+\e$B2A\e(B (@code{eval}) \e$B$5$l$^$9\e(B) \e$B$G$"$k$3$H$,$G$-$^$9!#$b$7$3$l$i$NF0:n$N0l$D\e(B
+\e$B$G$b\e(B @code{nil} \e$B$G$J$$7k2L$rJV$9$H!"\e(B@dfn{\e$B%U%!%$%k\e(B}\e$B$,%G%#%U%)%k%H$NB%?J$H\e(B
+\e$B$7$F;H$o$l$^$9!#2C$($F!"8F$P$l$?4X?t$+<0$,J8;zNs$+J8;zNs$N%j%9%H$rJV$7$?\e(B
+\e$B$H$-$O!"1i;;$N7k2L<+BN$,;H$o$l$^$9!#\e(B
+
+\e$B4pK\E*$K$O!"8=:_$N5-;v$rJ]B8$9$k$N$K;H$o$l$k2DG=@-$N$"$k%U%!%$%kL>$N%j%9\e(B
+\e$B%H$r<j$KF~$l$k;v$K$J$j$^$9!#\e(B(\e$B$9$Y$F$N!X9gCW!Y$,;H$o$l$^$9!#\e(B) \e$B$=$l$+$iK\\e(B
+\e$BEv$KL>A0$H$7$F;H$$$?$$$b$N$rB%$5$l!"$3$NJQ?t$rE,MQ$9$k;v$K$h$jF@$i$l$?7k\e(B
+\e$B2L$+$i%U%!%$%kL>Jd40$r$7$FF~NO$7$^$9!#\e(B
+
+\e$B$3$NJQ?t$O%G%#%U%)%k%H$G$O\e(B @code{((gnus-article-archive-name))} \e$B$G!"\e(B
+gnus \e$B$,J]B8$9$k5-;v$N\e(B @code{Archive-name} \e$B9T$rD4$Y$F!"$=$l$r%U%!%$%kL>$N\e(B
+\e$BDs0F$H$7$F;H$&$H$$$&;v$G$9!#\e(B
+
+\e$B$3$l$O%U%!%$%kL>$r>/$7$-$l$$$K$9$k4X?t$NNc$G$9!#\e(B
+@samp{nnml:mail.whatever} \e$B$N$h$&$J%a!<%k%0%k!<%W$,$?$/$5$s$"$k$N$G$"$l$P!"\e(B
+\e$BJ]B8$9$k$?$a$N%U%!%$%kL>$r:n$kA0$K$3$l$i$N%0%k!<%WL>$N:G=i$r@Z$jMn$H$9I,\e(B
+\e$BMW$,$"$k$+$b$7$l$^$;$s!#<!$NJ*$O$^$5$K$=$l$r$7$^$9\e(B:
+
+@lisp
+(defun my-save-name (group)
+  (when (string-match "^nnml:mail." group)
+    (substring group (match-end 0))))
+
+(setq gnus-split-methods
+      '((gnus-article-archive-name)
+        (my-save-name)))
+@end lisp
+
+@vindex gnus-use-long-file-name
+\e$B:G8e$K\e(B @code{gnus-use-long-file-name} \e$B$H$$$&JQ?t$,$"$j$^$9!#$3$l\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$H!"$9$Y$F$N>e5-$N4X?t$O%0%k!<%WL>$N$9$Y$F$N%T%j%*\e(B
+\e$B%I\e(B (@samp{.}) \e$B$r%9%i%C%7%e\e(B (@samp{/}) \e$B$GCV$-49$($^$9!=!=$3$l$O4X?t$O$9$Y\e(B
+\e$B$F$N%U%!%$%k$r0lHV>e$N%G%#%l%/%H%j!<$KCV$/$N$G$O$J$/!"3,AXE*$J%G%#%l%/%H\e(B
+\e$B%j!<$r:n$k$H$$$&;v$G$9\e(B (@file{~/News/alt.andrea-dworkin} \e$B$NBe$o$j\e(B
+\e$B$K\e(B @file{~/News/alt/andrea-dworkin}\e$B!#\e(B) \e$B$3$NJQ?t$O$?$$$F$$$N%7%9%F%`$K$*\e(B
+\e$B$$$F%G%#%U%)%k%H$G\e(B @code{t} \e$B$G$9!#$7$+$7!"Nr;KE*$JM}M3$+\e(B
+\e$B$i\e(B Xenix \e$B$H\e(B usg-unix-v \e$B%^%7%s$G$O%G%#%U%)%k%H$G\e(B @code{nil} \e$B$G$9!#\e(B
+
+\e$B$3$N4X?t$O:o=|$H%9%3%"$N%U%!%$%kL>$K1F6A$7$^$9!#$3$NJQ?t$,%j%9%H$G!"%j%9\e(B
+\e$B%H$KMWAG\e(B @code{not-score} \e$B$,$"$k$H!"D9$$%U%!%$%kL>$O%9%3%"%U%!%$%k$K$O;H\e(B
+\e$B$o$l$:!"%j%9%H$KMWAG\e(B @code{not-save} \e$B$,$"$k$H!"D9$$%U%!%$%kL>$OJ]B8$K$O\e(B
+\e$B;H$o$l$:!"MWAG\e(B @code{not-kill} \e$B$,$"$k$H!"D9$$%U%!%$%kL>$O:o=|%U%!%$%k$K\e(B
+\e$B$O;H$o$l$^$;$s!#\e(B
+
+\e$B$b$75-;v$r%9%W!<%k$N$h$&$J3,AX$KJ]B8$7$?$$$N$G$"$l$P!"<!$N$h$&$K$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-use-long-file-name '(not-save)) ; @r{to get a hierarchy}
+(setq gnus-default-article-saver
+      'gnus-summary-save-in-file) ; @r{no encoding}
+@end lisp
+
+\e$B$=$l$+$i\e(B @kbd{o} \e$B$K$h$C$F5-;v$rJ]B8$9$k$@$1$G$9!#$=$l$+$i$3$N3,AX$rC;L?\e(B
+\e$B$J\e(B @code{nneething} \e$B%0%k!<%W$K$h$C$FFI$`;v$,$G$-$^$9!=!=%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{G D} \e$B$H$7!"0lHV>e$N%G%#%l%/%H%j!<$r0z?t\e(B (@file{~/News/}) \e$B$H$7$F\e(B
+\e$BEO$7$^$9!#\e(B
+
+@node Decoding Articles
+@section \e$B5-;v$NI|9f2=\e(B
+@cindex decoding articles
+
+\e$B$H$-$I$-MxMQ<T$O2?$i$+$NJ}K!$GId9f2=$5$l$?5-;v\e(B (\e$B$b$7$/$O5-;v72\e(B) \e$B$rEj9F$7\e(B
+\e$B$^$9!#\e(BGnus \e$B$O$"$J$?$N$?$a$K$=$l$i$rI|9f2=$9$k;v$,$G$-$^$9!#\e(B
+
+@menu
+* Uuencoded Articles::          \e$B5-;v$r\e(B uuencode \e$B$9$k\e(B
+* Shell Archives::              shar \e$B5-;v$r2rE`$9$k\e(B
+* PostScript Files::            \e$B%]%9%H%9%/%j%W%H$rJ,3d$9$k\e(B
+* Other Files::                 \e$BIaDL$NJ]B8$H\e(B binhex.
+* Decoding Variables::          \e$B9,$;$JI|9f2=$N$?$a$NJQ?t\e(B
+* Viewing Files::               \e$BI|9f2=$N7k2L$r8+$?$$\e(B?
+@end menu
+
+@cindex series
+@cindex article series
+\e$B$3$l$i$9$Y$F$N4X?t$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B (@pxref{Process/Prefix}) \e$B$r!"\e(B
+\e$B!X0l$D$N5-;v!Y$r!X0l$D$N72!Y$H2r<a$9$k3HD%$r$7$F!"$I$N5-;v$KA`:n$r$9$k$+\e(B
+\e$B$r8+$D$1$k$?$a$K;H$$$^$9!#\e(BGnus \e$B$O<+J,<+?H$G$I$N5-;v$,$=$N72$KB0$7$F$$$k\e(B
+\e$B$+$rH=CG$7!"$9$Y$F$N5-;v$rI|9f2=$7$F!"$=$N7k2L$N%U%!%$%k$r\e(B \e$BE83+\e(B/\e$B1\Mw\e(B/\e$BJ]\e(B
+\e$BB8\e(B \e$B$9$k$3$H$,$G$-$^$9!#\e(B
+
+Gnus \e$B$O0J2<$N4JC1$J5,B'$KB'$C$F$I$N5-;v$,72$KB0$9$k$N$+$r?dB,$7$^$9\e(B: \e$BI=\e(B
+\e$BBj$O9T$N:G8e$NFs$D$N?t;z$r=|$$$F\e(B (\e$B$[$H$s$I\e(B) \e$BF1$8$G$"$kI,MW$,$"$j$^$9!#\e(B
+(\e$B6uGr$OBgBNL5;k$5$l$^$9$,!#\e(B)
+
+\e$BNc$($P\e(B: @samp{cat.gif (2/3)} \e$B$H$$$&$h$&$JI=Bj$rA*$V$H!"\e(Bgnus \e$B$O@55,I=\e(B
+\e$B8=\e(B @samp{^cat.gif ([0-9]+/[0-9]+).*$} \e$B$K9gCW$9$k$9$Y$F$N5-;v$r8+$D$1$h$&\e(B
+\e$B$H$7$^$9!#\e(B
+
+@samp{cat.gif (2/3) Part 6 of a series} \e$B$N$h$&$JI8=`$G$J$$I=Bj$O$I$N<+F0\e(B
+\e$B1\MwL?Na$K$h$C$F$bE,@Z$KG'<1$5$l$J$$$?$a!"<j$G5-;v$K\e(B @kbd{#} \e$B$N0u$rIU$1\e(B
+\e$B$J$1$l$P$J$j$^$;$s!#\e(B
+
+@node Uuencoded Articles
+@subsection uuencode \e$B$5$l$?5-;v\e(B
+@cindex uudecode
+@cindex uuencoded articles
+
+@table @kbd
+@item X u
+@kindex X u (\e$B35N,\e(B)
+@findex gnus-uu-decode-uu
+@c @icon{gnus-uu-decode-uu}
+\e$B8=:_$N72$r\e(B uudecode \e$B$7$^$9\e(B (@code{gnus-uu-decode-uu})\e$B!#\e(B
+
+@item X U
+@kindex X U (\e$B35N,\e(B)
+@findex gnus-uu-decode-uu-and-save
+\e$B8=:_$N72$r\e(B uudecode \e$B$7$FJ]B8$7$^$9\e(B (@code{gnus-uu-decode-uu-and-save})\e$B!#\e(B
+
+@item X v u
+@kindex X v u (\e$B35N,\e(B)
+@findex gnus-uu-decode-uu-view
+\e$B8=:_$N72$r\e(B uudecode \e$B$7$F!"I=<($7$^$9\e(B (@code{gnus-uu-decode-uu-view})\e$B!#\e(B
+
+@item X v U
+@kindex X v U (\e$B35N,\e(B)
+@findex gnus-uu-decode-uu-and-save-view
+\e$B8=:_$N5-;v$r\e(B uudecode \e$B$7$F!"I=<($7$FJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-decode-uu-and-save-view})\e$B!#\e(B
+@end table
+
+\e$B$3$l$i$9$Y$F$O%W%m%;%90u$K$h$C$F0uIU$1$i$l$?5-;v$NB8:_$KBP$7$FH?1~$9$k$H\e(B
+\e$B$$$&$3$H$r3P$($F$*$$$F$/$@$5$$!#Nc$($P!"$b$7%K%e!<%9%0%k!<%WA4BN$rI|9f2=\e(B
+\e$B$7$FJ]B8$7$?$$$N$G$"$l$P!"IaDL\e(B
+\e$B$O\e(B @kbd{M P a} (@code{gnus-uu-mark-all}) \e$B$H$7!"$=$l$+\e(B
+\e$B$i\e(B @kbd{X U} (@code{gnus-uu-decode-uu-and-save}) \e$B$H$7$^$9!#\e(B
+
+\e$B$3$NA4$F$O!"GrF|$N2<$KL@Gr$K%-!<$rBG$C$F$$$?\e(B @sc{gnus 4.1} \e$B$N$H$-$H\e(B
+\e$B$O\e(B @code{gnus-uu} \e$B$NF0:n$,A4$/0c$C$F$$$^$9!#$3$NHG$N\e(B @code{gnus-uu} \e$B$OIa\e(B
+\e$BDL$O2?$+$NJ}K!\e(B (@pxref{Setting Process Marks}) \e$B$G5-;v$K0u$rIU$1$F!"$=$l\e(B
+\e$B$+$i\e(B @kbd{X u} \e$B$r2!$9;v$rA0Ds$H$7$F$$$^$9!#\e(B
+
+@vindex gnus-uu-notify-files
+\e$BCm0U\e(B: @code{gnus-uu-notify-files} \e$B$K9gCW$9$kL>A0!"\e(B
+@samp{[Cc][Ii][Nn][Dd][Yy][0-9]+.\\(gif\\|jpg\\)} \e$B$K%O!<%I%3!<%I$5$l$k!"\e(B
+\e$B$r;}$D5-;v$rI|9f2=$7$h$&$H$7$?$H$-$O!"\e(B@code{gnus-uu} \e$B$OLdBj$N5-;v$r$A$g\e(B
+\e$B$&$I1\Mw$7$?;v$rCN$i$;$k$?$a$K!"<+F0E*$K\e(B @samp{comp.unix.wizards} \e$B$K5-;v\e(B
+\e$B$rEj9F$7$^$9!#$3$N5!G=$r;H$o$J$$$h$&$K$9$k;v$O$G$-$^$;$s!#\e(B
+
+@node Shell Archives
+@subsection \e$B%7%'%k%"!<%+%$%V\e(B
+@cindex unshar
+@cindex shell archives
+@cindex shared articles
+
+\e$B%7%'%k%"!<%+%$%V\e(B (\e$B!X\e(Bshar \e$B%U%!%$%k!Y\e(B) \e$B$O%=!<%9$rG[I[$9$k$?$a$N?M5$$N$"$k\e(B
+\e$BJ}K!$G$7$?$,!":#F|$G$O$=$s$J$K;H$o$l$F$$$^$;$s!#$H$K$+$/$3$l$i$r07$&$?$a\e(B
+\e$B$NL?Na$,$"$j$^$9\e(B:
+
+@table @kbd
+@item X s
+@kindex X s (\e$B35N,\e(B)
+@findex gnus-uu-decode-unshar
+\e$B8=:_$N72$r2rE`$7$^$9\e(B (@code{gnus-uu-decode-unshar})\e$B!#\e(B
+
+@item X S
+@kindex X S (\e$B35N,\e(B)
+@findex gnus-uu-decode-unshar-and-save
+\e$B8=:_$N72$r2rE`$7J]B8$7$^$9\e(B (@code{gnus-uu-decode-unshar-and-save})\e$B!#\e(B
+
+@item X v s
+@kindex X v s (\e$B35N,\e(B)
+@findex gnus-uu-decode-unshar-view
+\e$B8=:_$N72$r2rE`$7I=<($7$^$9\e(B (@code{gnus-uu-decode-unshar-view})\e$B!#\e(B
+
+@item X v S
+@kindex X v S (\e$B35N,\e(B)
+@findex gnus-uu-decode-unshar-and-save-view
+\e$B8=:_$N72$r2rE`$7!"I=<($7$FJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-decode-unshar-and-save-view})\e$B!#\e(B
+@end table
+
+@node PostScript Files
+@subsection \e$B%]%9%H%9%/%j%W%H%U%!%$%k\e(B
+@cindex PostScript
+
+@table @kbd
+@item X p
+@kindex X p (\e$B35N,\e(B)
+@findex gnus-uu-decode-postscript
+\e$B8=:_$N%]%9%H%9%/%j%W%H72$rE83+$7$^$9\e(B (@code{gnus-uu-decode-postscript})\e$B!#\e(B
+
+@item X P
+@kindex X P (\e$B35N,\e(B)
+@findex gnus-uu-decode-postscript-and-save
+\e$B8=:_$N%]%9%H%9%/%j%W%H72$rE83+$7$FJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-decode-postscript-and-save})\e$B!#\e(B
+
+@item X v p
+@kindex X v p (\e$B35N,\e(B)
+@findex gnus-uu-decode-postscript-view
+\e$B8=:_$N%]%9%H%9%/%j%W%H72$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-decode-postscript-view})\e$B!#\e(B
+
+@item X v P
+@kindex X v P (\e$B35N,\e(B)
+@findex gnus-uu-decode-ostscript-and-save-view
+\e$B8=:_$N%]%9%H%9%/%j%W%H72$rI=<($7J]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-uu-decode-postscript-and-save-view})\e$B!#\e(B
+@end table
+
+@node Other Files
+@subsection \e$BB>$N%U%!%$%k\e(B
+
+@table @kbd
+@item X o
+@kindex X o (\e$B35N,\e(B)
+@findex gnus-uu-decode-save
+\e$B8=:_$N72$rJ]B8$7$^$9\e(B (@code{gnus-uu-decode-save})\e$B!#\e(B
+
+@item X b
+@kindex X b (\e$B35N,\e(B)
+@findex gnus-uu-decode-binhex
+\e$B8=:_$N5-;v$r\e(B binhex \e$B2rE`$7$^$9\e(B (@code{gnus-uu-decode-binhex})\e$B!#$3$l$OK\\e(B
+\e$BEv$OF0:n$7$^$;$s!#\e(B
+@end table
+
+@node Decoding Variables
+@subsection \e$BI|9f2=$N$?$a$NJQ?t\e(B
+
+\e$B7AMF;l$G$9!#F0;l$G$O$"$j$^$;$s!#\e(B
+
+@menu
+* Rule Variables::              \e$B%U%!%$%k$,$I$N$h$&$KI=<($5$l$k$+$r7h$a$kJQ?t\e(B
+* Other Decode Variables::      \e$BB>$NI|9f2=$NJQ?t\e(B
+* Uuencoding and Posting::      uuencode \e$B$9$k$N$r%+%9%?%^%$%:$9$kJQ?t\e(B
+@end menu
+
+@node Rule Variables
+@subsubsection \e$B5,B'JQ?t\e(B
+@cindex rule variables
+
+Gnus \e$B$O%U%!%$%k$r1\Mw$9$k$N$r7hDj$9$k$N$K\e(B@dfn{\e$B5,B'JQ?t\e(B}\e$B$rMQ$$$^$9!#$3$l\e(B
+\e$B$i$NJQ?t$O$9$Y$F0J2<$N$h$&$JMM<0$G$9!#\e(B
+
+@lisp
+      (list '(regexp1 command2)
+            '(regexp2 command2)
+            ...)
+@end lisp
+
+@table @code
+@item gnus-uu-user-view-rules
+@vindex gnus-uu-user-view-rules
+@cindex sox
+\e$B$3$NJQ?t$O%U%!%$%k$r1\Mw$9$k$H$-$K:G=i$KD4$Y$i$l$^$9!#Nc$($P!"$b\e(B
+\e$B$7\e(B @file{.au} \e$B2;%U%!%$%k$rJQ49$9$k$?$a$K\e(B @code{sox} \e$B$r;H$$$?$$$H$-$O!"<!\e(B
+\e$B$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-uu-user-view-rules
+      (list '("\\\\.au$\" "sox %s -t .aiff > /dev/audio")))
+@end lisp
+
+@item gnus-uu-user-view-rules-end
+@vindex gnus-uu-user-view-rules-end
+\e$B$3$NJQ?t$O\e(B gnus \e$B$,MxMQ<T$H%G%#%U%)%k%H$N1\Mw5,B'$+$i9gCW$9$k$b$N$r8+$D$1\e(B
+\e$B$i$l$J$+$C$?$H$-$KD4$Y$i$l$^$9!#\e(B
+
+@item gnus-uu-user-archive-rules
+@vindex gnus-uu-user-archive-rules
+\e$B$3$NJQ?t$O%"!<%+%$%V$rE83+$9$k$H$-$K$I$NL?Na$,;H$o$l$k$Y$-$+$r7h$a$k$?$a\e(B
+\e$B$K;H$&;v$,$G$-$^$9!#\e(B
+@end table
+
+@node Other Decode Variables
+@subsubsection \e$BB>$NI|9f2=$NJQ?t\e(B
+
+@table @code
+@vindex gnus-uu-grabbed-file-functions
+
+@item gnus-uu-grabbed-file-functions
+\e$B$3$N%j%9%H$N$9$Y$F$N4X?t$O$=$l$>$l$N%U%!%$%k$,>e<j$/I|9f2=$5$l$?D>8e$K8F\e(B
+\e$B$P$l$^$9!=!=$G$9$+$i!"$9$0$K%U%!%$%k$r0\F0$d1\Mw$7$?$j$9$k$3$H$,$G$-!"2?\e(B
+\e$B$+$r$9$kA0$K$9$Y$F$N%U%!%$%k$,I|9f2=$5$l$k$N$rBT$DI,MW$O$"$j$^$;$s!#$3$N\e(B
+\e$B%j%9%H$KF~$l$k;v$N$G$-$k4{@=4X?t$O\e(B:
+
+@table @code
+@item gnus-uu-grab-view
+@findex gnus-uu-grab-view
+\e$B%U%!%$%k$r1\Mw$7$^$9!#\e(B
+
+@item gnus-uu-grab-move
+@findex gnus-uu-grab-move
+\e$B%U%!%$%k$r0\F0$7$^$9\e(B (\e$B$b$7J]B84X?t$r;H$C$F$$$k$N$G$"$l$P\e(B)\e$B!#\e(B
+@end table
+
+@item gnus-uu-be-dangerous
+@vindex gnus-uu-be-dangerous
+\e$BI|9f2=$N:GCf$KJQ$J>u67$,5/$3$C$?$H$-$K2?$r$9$k$+$r;XDj$7$^$9!#$b\e(B
+\e$B$7\e(B @code{nil} \e$B$G$"$k$H!"$G$-$k$@$1J]<iE*$K$J$j$^$9!#$b$7\e(B @code{t} \e$B$G$"$k\e(B
+\e$B$H!"F0:n$7$J$$$b$N$OL5;k$7$F!"8=B8$9$k%U%!%$%k$r>e=q$-$7$^$9!#$=$NB>$N>l\e(B
+\e$B9g$O!"$=$l$>$l$N$H$-$K?R$M$^$9!#\e(B
+
+@item gnus-uu-ignore-files-by-name
+@vindex gnus-uu-ignore-files-by-name
+\e$B$3$N@55,I=8=$K9gCW$9$kL>A0$N%U%!%$%k$O1\Mw$5$l$^$;$s!#\e(B
+
+@item gnus-uu-ignore-files-by-type
+@vindex gnus-uu-ignore-files-by-type
+\e$B$3$NJQ?t$K9gCW$9$k\e(B @acronym{MIME} \e$B$N7?$r;}$D%U%!%$%k$O1\Mw$5$l$^$;$s!#\e(B
+gnus \e$B$O%U%!%$%kL>$K4p$E$$$F7?$r?dB,$7$F$$$k;v$KCm0U$7$F$/$@$5$$!#\e(B
+@code{gnus-uu} \e$B$O\e(B (\e$B$^$@\e(B) @acronym{MIME} \e$B%Q%C%1!<%8$G$O$"$j$^$;$s$N$G!"$3\e(B
+\e$B$l$O>/$7JQ$G$9!#\e(B
+
+@item gnus-uu-tmp-dir
+@vindex gnus-uu-tmp-dir
+@code{gnus-uu} \e$B$,$=$N;E;v$r$9$k>l=j$G$9!#\e(B
+
+@item gnus-uu-do-not-unpack-archives
+@vindex gnus-uu-do-not-unpack-archives
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$OI=<($9$k$?$a$N%U%!%$%k$rC5$9$?$a\e(B
+\e$B$K%"!<%+%$%V$NCf$^$G$OF~$C$F$$$+$J$$$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-view-and-save
+@vindex gnus-uu-view-and-save
+@code{nil} \e$B$G$J$$$N$O!"MxMQ<T$O%U%!%$%k$r1\Mw$7$?8e$K>o$KJ]B8$9$k$+$I$&\e(B
+\e$B$+$r?R$M$i$l$k$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-ignore-default-view-rules
+@vindex gnus-uu-ignore-default-view-rules
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$O%G%#%U%)%k%H$N1\Mw5,B'$rL5;k$9$k\e(B
+\e$B$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-ignore-default-archive-rules
+@vindex gnus-uu-ignore-default-archive-rules
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$O%G%#%U%)%k%H$N%"!<%+%$%VE83+L?Na\e(B
+\e$B$rL5;k$9$k$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-kill-carriage-return
+@vindex gnus-uu-kill-carriage-return
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$O5-;v$+$i$9$Y$F$N%-%c%j%C%8%j%?!<\e(B
+\e$B%s\e(B (carriage return) \e$B$r<h$j5n$k$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-unmark-articles-not-decoded
+@vindex gnus-uu-unmark-articles-not-decoded
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$OI|9f2=$K<:GT$7$?5-;v$KL$FI$N0u$r\e(B
+\e$BIU$1$k$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-correct-stripped-uucode
+@vindex gnus-uu-correct-stripped-uucode
+@code{nil} \e$B$G$J$$$H$$$&$N$O!"\e(B@code{gnus-uu} \e$B$OB3$/6uGr$,:o=|$5$l$F$7$^$C\e(B
+\e$B$F$$$k\e(B uuencode \e$B$5$l$?%U%!%$%k$r=$I|$7$h$&$H\e(B @emph{\e$B;n$9\e(B} \e$B$H$$$&;v$G$9!#\e(B
+
+@item gnus-uu-pre-uudecode-hook
+@vindex gnus-uu-pre-uudecode-hook
+@code{uudecode} \e$B$K%a%C%;!<%8$rAw$kA0$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-uu-view-with-metamail
+@vindex gnus-uu-view-with-metamail
+@cindex metamail
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$O5,B'JQ?t$GDj5A$5$l$?1\MwL?Na$rL5\e(B
+\e$B;k$7$F!"%U%!%$%kL>$K4p$E$$$?\e(B @acronym{MIME} \e$BFbMF$N7?$K<h$jBX$($k$H$$$&;v\e(B
+\e$B$G$9!#$=$N7k2L$O1\Mw$N$?$a$K\e(B @code{metamail} \e$B$K$+$1$i$l$^$9!#\e(B
+
+@item gnus-uu-save-in-digest
+@vindex gnus-uu-save-in-digest
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$,I|9f2=$r$7$J$$$GJ]B8$r$9$k$h$&$K\e(B
+\e$B8@$o$l$?$H$-$K!"MWLs$rJ]B8$9$k$H$$$&;v$G$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k\e(B
+\e$B$H!"\e(B@code{gnus-uu} \e$B$O2?$b>~$j$r$7$J$$$GA4$F$r%U%!%$%k$KJ]B8$7$^$9!#MWLs\e(B
+\e$B$O\e(B RFC1153 \e$B=`$8$F$$$^$9!=!=0UL#$N$"$kNL$r;XDj$7$F!"HV9f$rH/9T$9$k4JC1$J\e(B
+\e$BJ}K!$,8+$D$+$i$J$+$C$?$N$G!"C1=c$K$=$l$i$O@Z$jMn$H$7$F$$$^$9!#\e(B
+@end table
+
+@node Uuencoding and Posting
+@subsubsection uuencode \e$B$HEj9F\e(B
+
+@table @code
+@item gnus-uu-post-include-before-composing
+@vindex gnus-uu-post-include-before-composing
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$,5-;v$r:n@.$9$kA0$KId9f2=$9$k%U%!\e(B
+\e$B%$%k$r?R$M$k$H$$$&;v$G$9!#$3$NJQ?t$,\e(B @code{t} \e$B$G$"$k$H!"\e(B@kbd{C-c C-i} \e$B$K\e(B
+\e$B$h$C$FId9f2=$5$l$?%U%!%$%k$r<h$j9~$`$+!"5-;v$rEj9F$9$k$H$-$K<h$j9~$`$+!"\e(B
+\e$B$I$A$i$+$r$9$k;v$,$G$-$^$9!#\e(B
+
+@item gnus-uu-post-length
+@vindex gnus-uu-post-length
+\e$B5-;v$N:GBg$ND9$5$G$9!#Id9f2=$5$l$?%U%!%$%k$OA4BN$N%U%!%$%k$rEj9F$9$k$N$K\e(B
+\e$BI,MW$JNL$N%U%!%$%k$KJ,3d$5$l$^$9!#\e(B
+
+@item gnus-uu-post-threaded
+@vindex gnus-uu-post-threaded
+@code{nil} \e$B$G$J$$$N$O!"\e(B@code{gnus-uu} \e$B$,Id9f2=$5$l$?%U%!%$%k$r%9%l%C%I$G\e(B
+\e$BEj9F$9$k$H$$$&;v$G$9!#$3$l$O$"$^$j8-$$J}K!$G$O$J$$$+$bCN$l$^$;$s!#$H$$$&\e(B
+\e$B$N$O!":#$^$G;d$,8+$?Cf$G\e(B uuencode \e$B$5$l$?5-;v$r=8$a$k$N$K!"%9%l%C%I$rDI$C\e(B
+\e$B$F$$$/;v$N$G$-$kB>$NI|9fAuCV$,B8:_$7$J$$$+$i$G$9!#\e(B(\e$B$(!<$H!";d$O$=$l$r$9\e(B
+\e$B$k0l$D$N%Q%C%1!<%8$r8+$?;v$,$"$j$^$9!=!=\e(B@code{gnus-uu} \e$B$G$9!#$7$+$7$J$<\e(B
+\e$B$+!"$=$l$,?t$N$&$A$KF~$k$H$O;W$($J$$$N$G$9\e(B@dots{}) \e$B%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item gnus-uu-post-separate-description
+@vindex gnus-uu-post-separate-description
+@code{nil} \e$B$G$J$$$N$O!"5-=R$OJL$N5-;v$GEj9F$5$l$k$H$$$&;v$G$9!#:G=i$N5-\e(B
+\e$B;v$OIaDL$O\e(B (0/x) \e$B$N$h$&$KHV9f$,IU$1$i$l$^$9!#$b$7$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$H!"MxMQ<T$N=q$$$?5-=R$O:G=i$N%U%!%$%k$N;O$a$K<h$j9~\e(B
+\e$B$^$l!"\e(B(1/x) \e$B$NHV9f$,IU$1$i$l$^$9!#%G%#%U%)%k%H$O\e(B @code{t} \e$B$G$9!#\e(B
+@end table
+
+@node Viewing Files
+@subsection \e$B%U%!%$%k$N1\Mw\e(B
+@cindex viewing files
+@cindex pseudo-articles
+
+\e$BI|9f2=$7$?8e$G%U%!%$%k$,2?$i$+$N%"!<%+%$%V$G$"$k>l9g!"\e(Bgnus \e$B$O%"!<%+%$%V\e(B
+\e$B$rE83+$7$h$&$H;n$_!"%"!<%+%$%V$NCf$K1\Mw$G$-$k%U%!%$%k$,$"$k$+$rD4$Y$^$9!#\e(B
+\e$BNc$($P!"\e(Bgzip \e$B$5$l$?\e(B tar \e$B%U%!%$%k\e(B @file{pics.tar.gz} \e$B$,$"$C$F!"%U%!%$\e(B
+\e$B%k\e(B @file{pic1.jpg} \e$B$H\e(B @file{pic2.gif} \e$B$r4^$s$G$$$k>l9g!"\e(Bgnus \e$B$O<g%U%!%$\e(B
+\e$B%k$r2rE`$7$F\e(B tar \e$B$rE83+$7!"$=$l$+$iFs$D$N3($r1\Mw$7$^$9!#$3$NE83+$N2aDx\e(B
+\e$B$O:F5"E*$J$N$G!"%"!<%+%$%V$K%"!<%+%$%V$N%"!<%+%$%V$,$"$k$H!"$=$l$O$9$Y$F\e(B
+\e$BE83+$5$l$^$9!#\e(B
+
+\e$B:G8e$K!"\e(Bgnus \e$B$OIaDL$O$=$l$>$l$NCj=P$5$l$?5-;v$4$H$K\e(B@dfn{\e$B5?;w5-;v\e(B}\e$B$r35N,\e(B
+\e$B%P%C%U%!$KA^F~$7$^$9!#$3$l$i$N!X5-;v!Y$K0\F0$7$?>l9g$O!"<B9T$9$kL?Na\e(B (\e$BIa\e(B
+\e$BDL$O\e(Bgnus \e$B$,Ds0F$r$7$^$9\e(B) \e$B$rF~NO$9$k$h$&$KB%$5$l!"$=$l$+$iL?Na$,<B9T$5$l\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-view-pseudo-asynchronously
+@code{gnus-view-pseudo-asynchronously} \e$B$,\e(B @code{nil} \e$B$G$"$k$H!"\e(BEmacs \e$B$O\e(B
+\e$B@h$X?J$`A0$K1\Mw$,=*$o$k$^$GBT$A$^$9!#\e(B
+
+@vindex gnus-view-pseudos
+@code{gnus-view-pseudos} \e$B$,\e(B @code{automatic} \e$B$G$"$k$H!"\e(Bgnus \e$B$O35N,%P%C%U%!\e(B
+\e$B$K5?;w5-;v$rA^F~$7$^$;$s$,!"$=$l$i$r$9$0$K1\Mw$7$^$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{not-confirm} \e$B$G$"$k$H!"MxMQ<T$O1\Mw$,:Q$`A0$K3NG'$5$($b5a$a$i$l\e(B
+\e$B$^$;$s!#\e(B
+
+@vindex gnus-view-pseudos-separately
+@code{gnus-view-pseudos-separately} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"0l$D$N5?;w5-\e(B
+\e$B;v$,1\Mw$5$l$k$=$l$>$l$N%U%!%$%k$KBP$7$F:n@.$5$l$^$9!#\e(B@code{nil} \e$B$G$"$k\e(B
+\e$B$H!"F1$81\MwL?Na$r;H$&$9$Y$F$NL?Na$,$=$NL?Na$N0z?t$N%j%9%H$H$7$FEO$5$l$^\e(B
+\e$B$9!#\e(B
+
+@vindex gnus-insert-pseudo-articles
+@code{gnus-insert-pseudo-articles} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"I|9f2=$N$H$-\e(B
+\e$B$K5?;w5-;v$rA^F~$7$^$9!#%G%#%U%)%k%H$G$O\e(B @code{t}\e$B$G$9!#\e(B
+
+\e$B$=$l$G!"$=$N$h$&$J46$8$G$9!#\e(B@emph{\e$B<B<A%5!<%P!<\e(B} \e$B$+$i\e(B
+\e$B$N\e(B @emph{\e$B<B<A%0%k!<%W\e(B} \e$B$N\e(B @emph{\e$B5?;w5-;v\e(B} \e$BFI$s$G$$$^$9!#$=$7$F9M$($^\e(B
+\e$B$9\e(B: \e$B$I$&$7$FA4$F$,8=<B$G$O$J$/$J$C$F$7$^$C$?$N$@$m$&$+\e(B? \e$B$I$&$7$F$3$3$KMh\e(B
+\e$B$F$7$^$C$?$N$@$m$&$+\e(B?
+
+@node Article Treatment
+@section \e$B5-;v$N07$$\e(B
+
+\e$B$3$N5pBg$J@bL@J8=q$rFI$s$G$-$F!"?M!9$,=q$$$?;v$rFI$`!"$H$$$C$?$h$&$J%K%e!<\e(B
+\e$B%:%j!<%@!<$NK\Ev$NL\E*$r40A4$KK:$l$F$7$^$C$?$+$bCN$l$^$;$s!#5-;v$rFI$`;v\e(B
+\e$B$G$9!#;DG0$J;v$K!"?M!9$O=q$/;v$OHs>o$K6l<j$H$7$F$$$^$9$N$G!"5-;v$rFI$_$d\e(B
+\e$B$9$/$9$k$?$a$N4X?t$HJQ?t$,;3$N$h$&$K$"$j$^$9!#\e(B
+
+@menu
+* Article Highlighting::        \e$B5-;v$r2LJ*%5%i%@$N$h$&$K8+$($k$h$&$K$7$?$$\e(B
+* Article Fontisizing::         \e$B6/D4$5$l$?J8$rAGE($K$9$k\e(B
+* Article Hiding::              \e$BFCDj$N>pJs$O>C$75n$j$?$$$H$b;W$&\e(B
+* Article Washing::             \e$B?M@8$r$b$C$H$h$/$9$k$?$/$5$s$N5$$NMx$$$?4X?t\e(B
+* Article Header::              \e$B%X%C%@!<$r$$$m$$$mJQ7A$5$;$k\e(B
+* Article Buttons::             URL \e$B$d\e(B Message-ID \e$B$d%"%I%l%9$J$I$r%/%j%C%/$9$k\e(B
+* Article Button Levels::       \e$B%\%?%s$N8+$(J}$r@)8f$9$k\e(B
+* Article Date::                \e$B$0$:$0$:8@$&$J!"@$3&;~$@\e(B!
+* Article Display::             X-Face, Picons, Smileys \e$B$rI=<($9$k\e(B
+* Article Signature::           \e$B=pL>$C$F2?\e(B?
+* Article Miscellanea::         \e$BB>$N$$$m$$$m$J$b$N\e(B
+@end menu
+
+@node Article Highlighting
+@subsection \e$B5-;v$N%O%$%i%$%H\e(B
+@cindex highlighting
+
+\e$B5-;v%P%C%U%!$r2LJ*%5%i%@$N$h$&$K$7$?$$$@$1$G$J$/!"2Z$d$+$J2LJ*%5%i%@$N$h\e(B
+\e$B$&$K8+$($k$h$&$K$7$?$$$G$7$g$&!#\e(B
+
+@table @kbd
+@item W H a
+@kindex W H a (\e$B35N,\e(B)
+@findex gnus-article-highlight
+@findex gnus-article-maybe-highlight
+\e$B8=:_$N5-;v$r$b$C$H%O%$%i%$%H\e(B (highlight) \e$B$7$^$9!#$3$N4X?t$O!"%X%C%@!<!"\e(B
+\e$B0zMQJ8!"=pL>$r%O%$%i%$%H$7!"K\BN\e(B (body) \e$B$HF,\e(B (head) \e$B$K%\%?%s$r2C$($^$9!#\e(B
+
+@item W H h
+@kindex W H h (\e$B35N,\e(B)
+@findex gnus-article-highlight-headers
+@vindex gnus-header-face-alist
+\e$B%X%C%@!<$r%O%$%i%$%H$7$^$9\e(B (@code{gnus-article-highlight-headers})\e$B!#%O%$\e(B
+\e$B%i%$%H$OJQ?t\e(B @code{gnus-header-face-alist} \e$B$K$7$?$,$C$F$J$5$l!"$=$l$O$=\e(B
+\e$B$l$>$l$NMWAG$,\e(B @code{(@var{\e$B@55,I=8=\e(B} @var{\e$BL>A0\e(B} @var{\e$BFbMF\e(B})} \e$B$H$$$&MM<0\e(B
+\e$B$N%j%9%H$G$9!#\e(B
+@var{\e$B@55,I=8=\e(B}\e$B$O%X%C%@!<$K9gCW$9$k@55,I=8=!"\e(B@var{\e$BL>A0\e(B}\e$B$O%X%C%@!<$NL>A0$r\e(B
+\e$B%O%$%i%$%H$9$k$N$K;H$o$l$k%U%'%$%9\e(B (face) (@pxref{Faces and Fonts})\e$B!"\e(B
+@var{\e$BFbMF\e(B}\e$B$O%X%C%@!<$NCM$r%O%$%i%$%H$9$k%U%'%$%9$G$9!#:G=i$K9gCW$7$?$b$N\e(B
+\e$B$,;H$o$l$^$9!#\e(B@var{\e$B@55,I=8=\e(B}\e$B$O\e(B @samp{^} \e$B$,IU$1$i$l$k$Y$-$G$O$J$$;v$KCm0U\e(B
+\e$B$7$F$/$@$5$$!=!=\e(Bgnus \e$B$,$=$l$rIU$12C$($^$9!#\e(B
+
+@item W H c
+@kindex W H c (\e$B35N,\e(B)
+@findex gnus-article-highlight-citation
+\e$B0zMQ$5$l$?J8$r%O%$%i%$%H$7$^$9\e(B (@code{gnus-article-highlight-citation})\e$B!#\e(B
+
+\e$B0zMQ%O%$%i%$%H$r%+%9%?%^%$%:$9$k$$$/$D$+$NJQ?t$O\e(B:
+
+@table @code
+@vindex gnus-cite-parse-max-size
+
+@item gnus-cite-parse-max-size
+\e$B5-;v$NBg$-$5$,$3$NJQ?t\e(B (\e$B%G%#%U%)%k%H$G$O\e(B 25000) \e$B$h$jBg$-$$5-;v$O!"0zMQ%O\e(B
+\e$B%$%i%$%H$O9T$o$l$^$;$s!#\e(B
+
+@item gnus-cite-max-prefix
+@vindex gnus-cite-max-prefix
+\e$B0zMQ@\F,8l$N:GBg$ND9$5$G$9\e(B (\e$B%G%#%U%)%k%H$G$O\e(B 20 \e$B$G$9\e(B)\e$B!#\e(B
+
+@item gnus-cite-face-list
+@vindex gnus-cite-face-list
+\e$B0zMQ$r%O%$%i%$%H$9$k$?$a$K;H$o$l$k%U%'%$%9$N%j%9%H$G$9\e(B (@pxref{Faces and
+Fonts})\e$B!#F1$8%a%C%;!<%8$NCf$KJ#?t$N5-;v$+$i$N0zMQ$,$"$k$H!"\e(Bgnus \e$B$O$=$l$>\e(B
+\e$B$l$N5-;v$+$i$N0zMQ$r$=$lMQ$N%U%'%$%9$GI=<($7$h$&$H$7$^$9!#$3$l$K$h$j!"C/\e(B
+\e$B$,2?$r=q$$$?$+$,J,$+$j$d$9$/$J$k$G$7$g$&!#\e(B
+
+@item gnus-supercite-regexp
+@vindex gnus-supercite-regexp
+\e$BIaDL$N\e(B Supercite \e$BB0@-9T$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item gnus-supercite-secondary-regexp
+@vindex gnus-supercite-secondary-regexp
+\e$B0z$-Nv$+$l$?\e(B Supercite \e$BB0@-9T$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item gnus-cite-minimum-match-count
+@vindex gnus-cite-minimum-match-count
+\e$B$=$l$,0zMQ$G$"$k$H7hDj$9$kA0$KD4$Y$J$1$l$P$J$i$J$$:G>.$NF10l@\F,8l$G$9!#\e(B
+
+@item gnus-cite-attribution-prefix
+@vindex gnus-cite-attribution-prefix
+\e$BB0@-9T$N;O$^$j$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item gnus-cite-attribution-suffix
+@vindex gnus-cite-attribution-suffix
+\e$BB0@-9T$N:G8e$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item gnus-cite-attribution-face
+@vindex gnus-cite-attribution-face
+\e$BB0@-9T$K;H$o$l$k%U%'%$%9$G$9!#$=$NB0@-$KB0$9$kJ8$N$?$a$N%U%'%$%9$HM;9g$5\e(B
+\e$B$l$^$9!#\e(B
+@end table
+
+@item W H s
+@kindex W H s (\e$B35N,\e(B)
+@vindex gnus-signature-separator
+@vindex gnus-signature-face
+@findex gnus-article-highlight-signature
+\e$B=pL>\e(B (signature) \e$B$r%O%$%i%$%H$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-highlight-signature})\e$B!#\e(B
+@code{gnus-signature-separator} (@pxref{Article Signature}) \e$B$N8e$NA4$F$N\e(B
+\e$B$b$N$O=pL>$H9M$($i$l!"\e(B@code{gnus-signature-face} \e$B$G%O%$%i%$%H$5$l$^$9!#\e(B
+\e$B$=$l$O%G%#%U%)%k%H$G$O\e(B @code{italic} \e$B$G$9!#5-;v$r<+F0E*$K%O%$%i%$%H$9$k\e(B
+\e$BJ}K!$K$D$$$F$O\e(B @xref{Customizing Articles} \e$B$r;2>H$7$F2<$5$$!#\e(B
+@end table
+
+@node Article Fontisizing
+@subsection \e$B5-;v$N%U%)%s%HJQ99\e(B
+@cindex emphasis
+@cindex article emphasis
+
+@cindex gnus-article-emphasize
+@kindex W e (\e$B35N,\e(B)
+\e$B?M!9$O$h$/%K%e!<%9$N5-;v$G\e(B @samp{_\e$B$3$l\e(B_} \e$B$d\e(B @samp{*\e$B$3$l\e(B*} \e$B$^$?\e(B
+\e$B$O\e(B @samp{/\e$B$3$l\e(B/} \e$B$N$h$&$J$b$N$r;H$C$FC18l$r6/D4$7$^$9!#\e(BGnus \e$B$O5-;v$rL?\e(B
+\e$BNa\e(B @kbd{W e} (@code{gnus-article-emphasize}) \e$B$K$+$1$k;v$K$h$C$FAGE($K8+\e(B
+\e$B$($k$h$&$K$G$-$^$9!#\e(B
+
+@vindex gnus-emphasis-alist
+\e$B6/D4$,$I$N$h$&$K1i;;$5$l$k$+$OJQ?t\e(B @code{gnus-emphasis-alist} \e$B$K$h$C$F@)\e(B
+\e$B8f$5$l$^$9!#$3$l$O:G=i$NMWAG$,9gCW$9$k$Y$-@55,I=8=$G$"$kO"A[%j%9%H$G$9!#\e(B
+\e$BFsHVL\$NMWAG$O$I$N@55,I=8=$N%0%k!<%W$,6/D48lA4BN$r8+$D$1$k$?$a$K;H$o$l$k\e(B
+\e$B$+$r<($9?t;z$G$9!#;0HVL\$O$I$N@55,I=8=$N%0%k!<%W$,I=<($5$l%O%$%i%$%H$5$l\e(B
+\e$B$k$+$r7h$a$k?t;z$G$9!#\e(B
+(\e$B$3$NFs$D$N%0%k!<%W$N4V$N5-;v$O1#$5$l$^$9!#\e(B) \e$B;MHVL\$O%O%$%i%$%H$N%U%'%$\e(B
+\e$B%9$G$9!#\e(B
+
+@lisp
+(setq gnus-emphasis-alist
+      '(("_\\(\\w+\\)_" 0 1 gnus-emphasis-underline)
+        ("\\*\\(\\w+\\)\\*" 0 1 gnus-emphasis-bold)))
+@end lisp
+
+@cindex slash
+@cindex asterisk
+@cindex underline
+@cindex /
+@cindex *
+
+@vindex gnus-emphasis-underline
+@vindex gnus-emphasis-bold
+@vindex gnus-emphasis-italic
+@vindex gnus-emphasis-underline-bold
+@vindex gnus-emphasis-underline-italic
+@vindex gnus-emphasis-bold-italic
+@vindex gnus-emphasis-underline-bold-italic
+\e$B=i4|@_Dj$G$O<7$D$N5,B'$,$"$j!"$=$l$i$O0J2<$N%U%'%$%9$rMQ$$$^\e(B
+\e$B$9\e(B: @code{gnus-emphasis-bold}, @code{gnus-emphasis-italic},
+@code{gnus-emphasis-underline}, @code{gnus-emphasis-bold-italic},
+@code{gnus-emphasis-underline-italic},
+@code{gnus-emphasis-underline-bold},
+@code{gnus-emphasis-underline-bold-italic}\e$B!#\e(B
+
+\e$B$3$l$i$N%U%'%$%9$rJQ99$7$?$$$N$G$"$l$P!"\e(B
+@kbd{M-x customize} \e$B$+\e(B @code{copy-face} \e$B$r;H$&;v$,$G$-$^$9!#Nc$($P!"\e(B
+@code{gnus-emphasis-italic} \e$B$KBe$o$j$K@V$N%U%'%$%9$r;H$&$h$&$K$7$?$$$H$-\e(B
+\e$B$O!"<!$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(copy-face 'red 'gnus-emphasis-italic)
+@end lisp
+
+@vindex gnus-group-highlight-words-alist
+\e$BG$0U$N8l$r6/D4I=<($5$;$?$$$H$-$O!"\e(B
+@code{gnus-group-highlight-words-alist} \e$BJQ?t$r;H$&$3$H$,$G$-$^$9!#$3$l\e(B
+\e$B$O\e(B @code{gnus-emphasis-alist} \e$B$HF1$89=J8$r;H$$$^$9!#\e(B
+@code{highlight-words} \e$B%0%k!<%W%Q%i%a!<%?$r;H$&$3$H$b$G$-$^$9!#\e(B
+
+\e$B5-;v$r<+F0E*$K%U%)%s$HJQ99$5$;$k$?$a$K$O\e(B @ref{Customizing Articles} \e$B$r;2\e(B
+\e$B>H$7$F2<$5$$!#\e(B
+
+@node Article Hiding
+@subsection \e$B5-;v$r1#$9\e(B
+@cindex article hiding
+
+\e$B$b$7$/$O!"$=$l$>$l$N5-;v$NFCDj$N$b$N$r1#$7$?$$$+$b$7$l$^$;$s!#$?$$$F$$$N\e(B
+\e$B5-;v$K$OIaDL$O$"$j$9$.$k$/$i$$:n$j$+$($k$b$N$,$"$j$^$9!#\e(B
+
+@table @kbd
+@item W W a
+@kindex W W a (\e$B35N,\e(B)
+@findex gnus-article-hide
+\e$B5-;v%P%C%U%!$G$?$/$5$s$N1#F?$r$7$^$9\e(B (@kbd{gnus-article-hide})\e$B!#FC$K!"$3\e(B
+\e$B$N4X?t$O%X%C%@!<!"\e(B@acronym{PGP}\e$B!"0zMQJ8$H=pL>$r1#$7$^$9!#\e(B
+
+@item W W h
+@kindex W W h (\e$B35N,\e(B)
+@findex gnus-article-hide-headers
+\e$B%X%C%@!<$r1#$7$^$9\e(B (@code{gnus-article-hide-headers})\e$B!#\e(B
+@xref{Hiding Headers}.
+
+@item W W b
+@kindex W W b (\e$B35N,\e(B)
+@findex gnus-article-hide-boring-headers
+\e$B$"$^$j6=L#$N$b$F$J$$%X%C%@!<$r1#$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-hide-boring-headers})\e$B!#\e(B@xref{Hiding Headers}.
+
+@item W W s
+@kindex W W s (\e$B35N,\e(B)
+@findex gnus-article-hide-signature
+\e$B=pL>$r1#$7$^$9\e(B (@code{gnus-article-hide-signature})\e$B!#\e(B
+@xref{Article Signature}.
+
+@item W W l
+@kindex W W l (\e$B35N,\e(B)
+@findex gnus-article-hide-list-identifiers
+@vindex gnus-list-identifiers
+@code{gnus-list-identifiers} \e$B$G;XDj$5$l$F$$$k%a!<%j%s%0%j%9%H$NI8<1$r:o\e(B
+\e$B=|$7$^$9!#$3$l$i$O$$$/$D$+$N%a!<%j%s%0%j%9%H$N%5!<%P!<$,A4$F\e(B
+\e$B$N\e(B @code{Subject} \e$B%X%C%@!<$N:G=i$K$D$1$kJ8;zNs$G$9\e(B---\e$BNc$($P!"\e(B
+@samp{[zebra 4711]}\e$B!#J8;zNs$N=i$a$K$"$k\e(B @samp{Re: } \e$B$O!":o=|$r9T$J$&A0$K\e(B
+\e$BD7$S1[$5$l$^$9!#\e(B@code{gnus-list-identifiers} \e$B$K\e(B @code{\\(..\\)} \e$B$r4^$a$F\e(B
+\e$B$O$$$1$^$;$s!#\e(B
+
+@table @code
+@item gnus-list-identifiers
+@vindex gnus-list-identifiers
+\e$BI=Bj$+$i:o=|$5$l$k$Y$-I8<1$N%j%9%H$K9gCW$9$k@55,I=8=$G$9!#$3$l$O@55,I=8=\e(B
+\e$B$N%j%9%H$G$"$k$3$H$b$G$-$^$9!#\e(B
+@end table
+
+@item W W P
+@kindex W W P (\e$B35N,\e(B)
+@findex gnus-article-hide-pem
+@acronym{PEM} (privacy enhanced messages (\e$B%W%i%$%P%7!<3HD%%a%C%;!<\e(B
+\e$B%8\e(B)) \e$BItJ,$r1#$7$^$9\e(B (@code{gnus-article-hide-pem})\e$B!#\e(B
+
+@item W W B
+@kindex W W B (\e$B35N,\e(B)
+@findex gnus-article-strip-banner
+@vindex gnus-article-banner-alist
+@vindex gnus-article-address-banner-alist
+@cindex banner
+@cindex OneList
+@cindex stripping advertisements
+@cindex advertisements
+@code{banner} \e$B%0%k!<%W%Q%i%a!<%?$G;XDj$5$l$?%P%J!<$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-article-strip-banner})\e$B!#$3$l$O<g$K!"$$$/$D$+$N%a!<%j%s%0\e(B
+\e$B%j%9%H$d;J2q<TIU$-$N%0%k!<%W$,A4$F$N5-;v$KDI2C$9$k!"15F+$7$$%P%J!<$H\e(B/\e$B$b\e(B
+\e$B$7$/$O=pL>$r1#$9$?$a$K;HMQ$5$l$^$9!#$3$N4X?t$r;H$&J}K!\e(B
+\e$B$O\e(B @code{banner} \e$B%0%k!<%W%Q%i%a!<%?\e(B (@pxref{Group Parameters}) \e$B$r%P%J!<\e(B
+\e$B$r<h$j=|$-$?$$%0%k!<%W$KDI2C$7$^$9!#%Q%i%a!<%?$O!">C5n$5$l$k%F%-%9%H$K9g\e(B
+\e$BCW$9$k@55,I=8=$H$7$F2r<a$5$l$kJ8;zNs$+!"\e(B(\e$B:G8e$N\e(B) \e$B=pL>$,>C5n$5$l$k$H$$$&\e(B
+\e$B0UL#$G$"$k%7%s%\%k\e(B @code{signature} \e$B$^$?\e(B
+\e$B$O\e(B @code{gnus-article-banner-alist} \e$B$N@55,I=8=$KBP1~$7$?%7%s%\%k$G$"$k$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+\e$B%0%k!<%W$K$+$+$o$i$:!"5-;v$NAw?.<T\e(B
+\e$B$,\e(B @code{gnus-article-address-banner-alist} \e$B$K@_Dj$5$l$?!"$"$k%a!<%k%"%I\e(B
+\e$B%l%9$r;}$C$F$$$k$H$-$@$1!"9-9p$N$h$&$J$b$N$r1#$9$3$H$,$G$-$^$9!#\e(B
+
+@table @code
+@item gnus-article-address-banner-alist
+@vindex gnus-article-address-banner-alist
+\e$B%a!<%k%"%I%l%9$H%P%J!<$NO"A[%j%9%H$G$9!#$=$l$>$l$NMWAG\e(B
+\e$B$O\e(B @code{(@var{address} . @var{banner})} \e$B$N7A<0$r;}$A!"$3$3\e(B
+\e$B$G\e(B @var{address} \e$B$O\e(B From \e$B%X%C%@!<$K$"$k%a!<%k%"%I%l%9$K%^%C%A$9$k@55,I=\e(B
+\e$B8=!"\e(B@var{banner} \e$B$O%7%s%\%k\e(B @code{signature}\e$B!"\e(B
+@code{gnus-article-banner-alist} \e$B$NMWAG!"@55,I=8=$^$?$O\e(B @code{nil} \e$B$N$&\e(B
+\e$B$A$N0l$D$G$9!#\e(B@var{address} \e$B$,Cx<T$N%a!<%k%"%I%l%9$K%^%C%A$9$k$H!"9-9p$N\e(B
+\e$B$h$&$J$b$N$r>C$7$^$9!#Nc$($P!"Aw?.<T$,\e(B @samp{hail@@yoo-hoo.co.jp} \e$B$H$$$&\e(B
+\e$B%a!<%k%"%I%l%9$r;}$C$F$$$F!"H`$,Aw?.$9$k$9$Y$F$N5-;v$K\e(B @samp{Do You
+Yoo-hoo!?} \e$B$N$h$&$J$b$N$,$"$k>l9g!"0J2<$NMWAG$G$=$l$i$r>C$9$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+@lisp
+("@@yoo-hoo\\.co\\.jp\\'" . "\n_+\nDo You Yoo-hoo!\\?\n.*\n.*\n")
+@end lisp
+@end table
+
+@item W W c
+@kindex W W c (\e$B35N,\e(B)
+@findex gnus-article-hide-citation
+\e$B0zMQ$r1#$7$^$9\e(B (@code{gnus-article-hide-citation})\e$B!#1#JC$r%+%9%?%^%$%:$9\e(B
+\e$B$k$$$/$D$+$NJQ?t$O\e(B:
+
+@table @code
+@item gnus-cited-opend-text-button-line-format
+@itemx gnus-cited-closed-text-button-line-format
+@vindex gnus-cited-closed-text-button-line-format
+@vindex gnus-cited-opend-text-button-line-format
+
+Gnus \e$B$O$I$3$N0zMQJ8$,1#$5$l$F$$$k$+$r<($9$?$a$K%\%?%s$rIU$12C$(!"J8>O$N\e(B
+\e$B1#JC$r@Z$jBX$($i$l$k$h$&$K$7$^$9!#$3$NJQ?t$NMM<0$O$3$l$i$N%U%)!<%^%C%H$N\e(B
+\e$B$h$&$JJQ?t$K$h$C$F;XDj$5$l$^$9\e(B (@pxref{Formatting Variables})\e$B!#<!$N;XDj\e(B
+\e$B$OM-8z$G$9\e(B:
+
+@table @samp
+@item b
+\e$B1#$5$l$?J8$N:G=i$N%]%$%s%H$G$9!#\e(B
+@item e
+\e$B1#$5$l$?J8$N:G8e$N%]%$%s%H$G$9!#\e(B
+@item l
+\e$B1#$5$l$?%j!<%8%g%s$NJ8;z$N?t$G$9!#\e(B
+@item n
+\e$B1#$5$l$?J8$N9T$N?t$G$9!#\e(B
+@end table
+
+@item gnus-cited-lines-visible
+@vindex gnus-cited-lines-visible
+\e$B0zMQJ8$N:G=i$+$i$NI=<($5$l$k9T?t$G$9!#\e(B
+@end table
+
+@item W W C
+@kindex W W C (\e$B35N,\e(B)
+@findex gnus-article-hide-citation-in-followups
+\e$B:,K\$G$J$$5-;v$N0zMQJ8$r1#$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-hide-citation-in-followups})\e$B!#$3$l$OBPOCE*L?Na$H\e(B
+\e$B$7$F$O$"$^$jLr$KN)$?$J$$$+$b$7$l$^$;$s$,!"<+F0E*$K5/$3$k<j7Z$J4X?t$G$"$k\e(B
+\e$B$G$7$g$&\e(B (@pxref{Customizing Articles})\e$B!#\e(B
+
+@item W W C-c
+@kindex W W C-c (\e$B35N,\e(B)
+@findex gnus-article-hide-citation-maybe
+
+\e$B0J2<$NFs$D$NJQ?t$K4p$E$$$F0zMQ$r1#$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-hide-citation-maybe}):
+
+@table @code
+@item gnus-cite-hide-percentage
+@vindex gnus-cite-hide-percentage
+\e$B$b$70zMQJ8$,$3$NJQ?t\e(B (\e$B=i4|CM$O\e(B 50) \e$B$h$jBg$-$$3d9g$G$"$l$P!"0zMQJ8$r1#$7\e(B
+\e$B$^$9!#\e(B
+
+@item gnus-cite-hide-absolute
+@vindex gnus-cite-hide-absolute
+\e$B1#$5$l$k0zMQJ8$O>/$J$/$H$b$3$ND9$5\e(B (\e$B=i4|CM\e(B 10) \e$B$G$J$1$l$P$J$j$^$;$s!#\e(B
+@end table
+@end table
+
+\e$B$3$l$i$NA4$F$N!X1#JC!YL?Na$O@Z$jBX$(L?Na$G$9$,!"$3$l$i$NL?Na$KIi$N@\F,0z\e(B
+\e$B?t$rM?$($k$H!"$=$l$i$OA0$K1#$5$l$F$$$?$b$N$rI=<($7$^$9!#@5$N@\F,0z?t$rM?\e(B
+\e$B$($l$P!"$=$l$i$O>o$K1#$7$^$9!#\e(B
+
+\e$B0zMQ%+%9%?%^%$%:$N$?$a$NB>$NJQ?t$N>pJs$N$?$a\e(B
+\e$B$K\e(B @ref{Article Highlighting} \e$B$b;2>H$7$F$/$@$5$$!#\e(B
+
+\e$B<+F0E*$K5-;v$NMWAG$r1#$9$?$a$NJ}K!$O\e(B @ref{Customizing Articles} \e$B$r;2>H\e(B
+\e$B$7$F2<$5$$!#\e(B
+
+@node Article Washing
+@subsection \e$B5-;v@vBu\e(B
+@cindex washing
+@cindex article washing
+
+\e$B;d$?$A$O$3$l$r$b$C$H$b$JM}M3$N2<$G!X5-;v@vBu!Y\e(B(article washing) \e$B$H8F$s$G\e(B
+\e$B$$$^$9!#$9$J$o$A!"%-!<\e(B @kbd{A} \e$B$O;H$o$l$F$$$k$N$G!"Be$o$j$K\e(B
+\e$B%-!<\e(B @kbd{W} \e$B$r;H$&I,MW$,$"$k$N$G$9!#\e(B
+
+\e$B;d$?$A$O\e(B @dfn{\e$B@vBu\e(B} \e$B$r!X2?$+$N2?$+$r2?$+JL$N$b$N$KJQ49$9$k!Y$HDj5A$7$F$$\e(B
+\e$B$^$9$,!"IaDL$O$b$C$HNI$/8+$($k2?$+$KMn$ACe$-$^$9!#$=$l$K$b$C$H$-$l$$$G$9!"\e(B
+\e$B$?$V$s!#\e(B
+
+gnus \e$B$,5-;v$rI=<($9$k4{Dj$N$d$jJ}$rJQ$($?$$$H$-\e(B
+\e$B$O\e(B @ref{Customizing Articles} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@table @kbd
+@item C-u g
+\e$B$3$l$O5-;v@vBu$G$O$J$/$F!"$=$N5U$G$9!#$3$l$r%?%$%W$9$k$H!"%G%#%9%/$d%5!<\e(B
+\e$B%P!<$K$"$k$,$^$^$N5-;v$,8+$($^$9!#\e(B
+
+@item g
+\e$B8=:_$N5-;v$N:FI=<($r6/@)$7$^$9\e(B (@code{gnus-summary-show-article})\e$B!#$3$l\e(B
+\e$B$b$^$?K\Ev$N@vBu$G$O$"$j$^$;$s!#$3$l$r%?%$%W$9$k$H!"0JA0$KE,MQ$5$l$?BPOC\e(B
+\e$BE*$J@vBu5!G=$O$4GK;;$K$5$l!"$9$Y$F$N%G%#%U%)%k%H$N07$$\e(B (treatments) \e$B$r<u\e(B
+\e$B$1$?5-;v$,I=<($5$l$^$9\e(B (@pxref{Customizing Articles})\e$B!#\e(B
+
+@item W l
+@kindex W l (\e$B35N,\e(B)
+@findex gnus-summary-stop-page-breaking
+\e$B%Z!<%8$N6h@Z$j$r8=:_$N5-;v$+$i<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-summary-stop-page-breaking})\e$B!#%Z!<%8$N6h@Z$j$KIU$$$F\e(B
+\e$B$O\e(B @ref{Misc Article} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item W r
+@kindex W r (\e$B35N,\e(B)
+@findex gnus-summary-caesar-message
+@c @icon{gnus-summary-caesar-message}
+\e$B5-;v%P%C%U%!$G%+%(%5%kJQ49\e(B (Caesar rotate) (rot13) \e$B$r$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-caesar-message})\e$B!#%+%(%5%kJQ49$+\e(B rot13 \e$B$rMQ$$$FFI\e(B
+\e$B$`;v$N$G$-$k!"H=FIIT2DG=$J5-;v$G$9\e(B (\e$BE57?E*$K$O!"967bE*$J>iCL$J$I$G$9!#\e(B)
+
+\e$BIaDL$O\e(B ``rot13'' \e$B$H8F$P$l$F$$$^$9!#$=$l$O%"%k%U%!%Y%C%H$N0LCV$,\e(B 13 \e$B8D2s\e(B
+\e$BE>$9$k$+$i$G$9!#Nc$($P!"\e(B@samp{B} (2 \e$BHVL\$NJ8;z\e(B) \e$B"*\e(B @samp{O} (15 \e$BHVL\$NJ8\e(B
+\e$B;z\e(B)\e$B!#$3$l$O;~!9!X%+%(%5%kJQ49!Y$H8F$P$l$k;v$b$"$j$^$9!#$H$$$&$N$O!"%+%(\e(B
+\e$B%5%k$,$3$N7A<0$N!"$(!<$H!"$A$g$C$H4JC1$J0E9f2=$r:NMQ$7$?$H$$$&1=$,$"$k$+\e(B
+\e$B$i$G$9!#\e(B
+
+@item W m
+@kindex W m (\e$B35N,\e(B)
+@findex gnus-summary-morse-message
+\e$B5-;v%P%C%U%!$r%b!<%k%9I|9f$7$^$9\e(B (@code{gnus-summary-morse-message})\e$B!#\e(B
+
+@item W t
+@item t
+@kindex W t (\e$B35N,\e(B)
+@kindex t (\e$B35N,\e(B)
+@findex gnus-summary-toggle-header
+\e$B5-;v%P%C%U%!$K$9$Y$F$N%X%C%@!<$rI=<($9$k$+$I$&$+$r@Z$jBX$($^\e(B
+\e$B$9\e(B (@code{gnus-summary-toggle-header})\e$B!#\e(B
+
+@item W v
+@kindex W v (\e$B35N,\e(B)
+@findex gnus-summary-verbose-headers
+\e$B5-;v%P%C%U%!$K$9$Y$F$N%X%C%@!<$r1J1s$KI=<($9$k$+$I$&$+$r@Z$jBX$($^\e(B
+\e$B$9\e(B (@code{gnus-summary-verbose-headers})\e$B!#\e(B
+
+@item W m
+@kindex W m (\e$B35N,\e(B)
+@findex gnus-summary-toggle-mime
+\e$BI=<($9$kA0$K5-;v$K\e(B @acronym{MIME} \e$B=hM}$r<B9T$9$k$+$I$&$+$r@Z$j49$($^\e(B
+\e$B$9\e(B (@code{gnus-summary-toggle-mime})\e$B!#\e(B
+
+@item W o
+@kindex W o (\e$B35N,\e(B)
+@findex gnus-article-treat-overstrike
+\e$B%*!<%P!<%9%H%i%$%/$r=hM}$7$^$9\e(B (@code{gnus-article-treat-overstrike})\e$B!#\e(B
+
+@item W d
+@kindex W d (\e$B35N,\e(B)
+@findex gnus-article-treat-dumbquotes
+@vindex gnus-article-dumbquotes-map
+@cindex Smartquotes
+@cindex M****s*** sm*rtq**t*s
+@cindex Latin 1
+@code{gnus-article-dumbquotes-map} \e$B$K1~$8$F!"%^"#"#"#%="#\e(B
+\e$B"#\e(B sm*rtq**t*s \e$B$r=hM}$7$^$9!#$3$N4X?t$OJ8;z$,\e(B sm*rtq**t* \e$B$+$I$&$+$r?dB,\e(B
+\e$B$7$^$9$N$G!"BPOCE*$K$N$_;HMQ$5$l$k$Y$-$G$"$k$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+
+Sm*rtq**t*s \e$B$O$b$C$HB?$/$N0zMQJ8;z$rDs6!$9$k$?$a$K!"%^"#"#"#%="#"#$,>!<j\e(B
+\e$B$KJ8;z%^%C%W$r3HD%$7$?$b$N$G$9!#$b$7!"%"%]%9%H%m%U%#\e(B (') \e$B$d0zMQ5-9f$J$I\e(B
+\e$B$,$"$k$Y$-$H$3$m$K\e(B @code{\222} \e$B$d\e(B @code{\264} \e$B$N$h$&$J$b$N$,8+$($F$7$^$C\e(B
+\e$B$?$i!"@vBu$7$F$_$F2<$5$$!#\e(B
+
+@item W Y f
+@kindex W Y f (\e$B35N,\e(B)
+@findex gnus-article-outlook-deuglify-article
+@cindex Outlook Express
+\e$B$$$+$l$?\e(B Outlook (Express) \e$B$N5-;v$r40A4$K=9$/$J$/$9$k$3$H\e(B (\e$BLu\e(B
+\e$BCm\e(B: de-ugly-fy) (sm*rtq**t*s \e$B$r=hM}!"9T$N@^$jJV$7$r2r=|!"B0@-9T$N=$I|$H\e(B
+\e$B0zMQ9T$NJB$YBX$(\e(B) \e$B$r$7$^$9!#\e(B
+(@code{gnus-article-outlook-deuglify-article})\e$B!#\e(B
+
+@item W Y u
+@kindex W Y u (\e$B35N,\e(B)
+@findex gnus-article-outlook-unwrap-lines
+@vindex gnus-outlook-deuglify-unwrap-min
+@vindex gnus-outlook-deuglify-unwrap-max
+\e$B@^$jJV$5$l$?0zMQ9T$N$h$&$K8+$($k9T$N@^$jJV$7$r2r$-$^$9!#@^$jJV$7$,2r$+$l\e(B
+\e$B$?9T$N:G>.$*$h$S:GBg$ND9$5$rI=\e(B
+\e$B$9\e(B @code{gnus-outlook-deuglify-unwrap-min} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-outlook-deuglify-unwrap-max} \e$B$rD4@0$9$k$3$H$K$h$C$F!"$I$N\e(B
+\e$B9T$N@^$jJV$7$,2r$+$l$k$+$r@)8f$9$k$3$H$,$G$-$^$9!#\e(B
+(@code{gnus-article-outlook-unwrap-lines})\e$B!#\e(B
+
+@item W Y a
+@kindex W Y a (\e$B35N,\e(B)
+@findex gnus-article-outlook-repair-attribution
+\e$B2u$l$?B0@-9T$r=$I|$7$^$9!#\e(B
+(@code{gnus-article-outlook-repair-attribution})\e$B!#\e(B
+
+@item W Y c
+@kindex W Y c (\e$B35N,\e(B)
+@findex gnus-article-outlook-rearrange-citation
+\e$B2u$l$?0zMQ$r!"%F%-%9%H$rJB$YD>$9$3$H$K$h$C$F=$I|$7$^$9!#\e(B
+(@code{gnus-article-outlook-rearrange-citation})\e$B!#\e(B
+
+@item W w
+@kindex W w (\e$B35N,\e(B)
+@findex gnus-article-fill-cited-article
+\e$B8l$N@^$jJV$7$r$7$^$9\e(B (@code{gnus-article-fill-cited-articles})\e$B!#\e(B
+
+\e$B@^$jJV$7$r$9$k$H$-$K!"I}$r;XDj$9$k$?$a$KL?Na$K?tCM@\F,0z?t$rM?$($k;v$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+@item W Q
+@kindex W Q (\e$B35N,\e(B)
+@findex gnus-article-fill-long-lines
+\e$BD9$$9T$r@^$jJV$7$^$9\e(B (@code{gnus-article-fill-mode-lines})\e$B!#\e(B
+
+@item W C
+@kindex W C (\e$B35N,\e(B)
+@findex gnus-article-capitalize-sentences
+\e$B$=$l$>$l$NJ,$N:G=i$N8l$rBgJ8;z$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-capitalize-sentences})\e$B!#\e(B
+
+@item W c
+@kindex W c (\e$B35N,\e(B)
+@findex gnus-article-remove-cr
+CRLF \e$B$NAH\e(B (\e$B$9$J$o$A!"9T$N:G8e$N\e(B @samp{^M}) \e$B$r\e(B LF \e$B$KJQ49$7$^$9\e(B (\e$B$3$l\e(B
+\e$B$O\e(B DOS \e$B$N9TKv$N@$OC$r$7$^$9\e(B)\e$B!"$=$7$F$=$l$+$i;D$j$N\e(B CR \e$B$r\e(B LF \e$B$KJQ49$7$^\e(B
+\e$B$9\e(B (\e$B$3$l$O\e(B MAC \e$B$N9TKv$N@$OC$r$7$^$9\e(B) (@code{gnus-article-remove-cr})\e$B!#\e(B
+
+@ignore
+@kindex W q (Summary)
+@findex gnus-article-de-quoted-unreadable
+Treat quoted-printable (@code{gnus-article-de-quoted-unreadable}).
+Quoted-Printable is one common @acronym{MIME} encoding employed when
+sending non-@acronym{ASCII} (i.e., 8-bit) articles.  It typically
+makes strings like @samp{d\e,Ai\e(Bj\e,A`\e(B vu} look like @samp{d=E9j=E0 vu}, which
+doesn't look very readable to me.  Note that this is usually done
+automatically by Gnus if the message in question has a
+@code{Content-Transfer-Encoding} header that says that this encoding
+has been done.  If a prefix is given, a charset will be asked for.
+
+@item W 6
+@kindex W 6 (Summary)
+@findex gnus-article-de-base64-unreadable
+Treat base64 (@code{gnus-article-de-base64-unreadable}).  Base64 is
+one common @acronym{MIME} encoding employed when sending
+non-@acronym{ASCII} (i.e., 8-bit) articles.  Note that this is
+usually done automatically by Gnus if the message in question has a
+@code{Content-Transfer-Encoding} header that says that this encoding
+has been done.  If a prefix is given, a charset will be asked for.
+
+@end ignore
+@item W Z
+@kindex W Z (\e$B35N,\e(B)
+@findex gnus-article-decode-HZ
+HZ \e$B$^$?$O\e(B HZP \e$B$r=hM}$7$^$9!#\e(BHZ (\e$B$^$?$O\e(B HZP) \e$B$OCf9q8l$N5-;v$rEAAw$9$k$H$-\e(B
+\e$B$K;H$o$l$k0lHLE*$JId9f$G$9!#$3$l$O\e(B @samp{~@{<:Ky2;S@{#,NpJ)l6HK!#~@}} \e$B$N\e(B
+\e$B$h$&$JE57?E*$JJ8;zNs$r:n$j$^$9!#\e(B
+
+@item W u
+@kindex W u (\e$B35N,\e(B)
+@findex gnus-article-unsplit-urls
+URL \e$B$K4^$^$l$k2~9T$r:o=|$7$^$9!#$$$/$D$+$N%a%$%i!<$O!"9T$rC;$/$9$k$?$a$K\e(B
+\e$B=P$F$$$/%a!<%k$K2~9T$rA^F~$7$^$9$,!"$3$l$OD9$$\e(B URL \e$B$rJ#?t$N9T$KJ,3d$7$F\e(B
+\e$B$7$^$$$^$9!#2~9T$r:o=|$9$k$3$H$K$h$C$F!"$=$l$i$N\e(B URL \e$B$rI|5l$5$;$^\e(B
+\e$B$9\e(B (@code{gnus-article-unsplit-urls})\e$B!#\e(B
+
+@item W h
+@kindex W h (\e$B35N,\e(B)
+@findex gnus-article-wash-html
+@acronym{HTML} \e$B$r=hM}$7$^$9!#Ev3:%a%C%;!<%8$,\e(B @acronym{HTML} \e$B$G$"$k$3$H\e(B
+\e$B$r<($9\e(B @code{Content-Type} \e$B%X%C%@!<$r;}$C$F$$$?$J$i$P!"$=$l$O\e(B gnus \e$B$K$h$C\e(B
+\e$B$F<+F0E*$K9T$J$o$l$k$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+\e$B@\F,<-$,M?$($i$l$k$H!"2?$NJ8;z=89g\e(B (charset) \e$B$H$7$F07$&$+$r?R$M$i$l$^$9!#\e(B
+
+@vindex gnus-article-wash-function
+\e$B%G%#%U%)%k%H$G$O\e(B @acronym{HTML} \e$B$NJQ49$K\e(B @code{mm-text-html-renderer}
+(@pxref{Display Customization, ,Display Customization, emacs-mime, The
+Emacs MIME Manual}) \e$B$G@_Dj$5$l$?4X?t$r;H$$$^$9$,!"$3$l$OJQ\e(B
+\e$B?t\e(B @code{gnus-article-wash-function} \e$B$G@)8f$5$l$^$9!#;H$&$3$H$,$G$-$k!"\e(B
+\e$B$"$i$+$8$aMQ0U$5$l$?4X?t$O0J2<$NDL$j$G$9!#\e(B
+
+@table @code
+@item w3
+Emacs/W3 \e$B$r;H$$$^$9!#\e(B
+
+@item w3m
+@uref{http://emacs-w3m.namazu.org/, emacs-w3m} \e$B$r;H$$$^$9!#\e(B
+
+@item links
+@uref{http://links.sf.net/, Links} \e$B$r;H$$$^$9!#\e(B
+
+@item lynx
+@uref{http://lynx.isc.org/, Lynx} \e$B$r;H$$$^$9!#\e(B
+
+@item html2text
+html2text (\e$B%7%s%W%k$J\e(B @acronym{HTML} \e$B%3%s%P!<%?!<!"\e(Bgnus \e$B$K4^$^$l$F$$\e(B
+\e$B$k\e(B) \e$B$r;H$$$^$9!#\e(B
+@end table
+
+@item W b
+@kindex W b (\e$B35N,\e(B)
+@findex gnus-article-add-buttons
+\e$B%/%j%C%/$G$-$k%\%?%s$r5-;v$K2C$($^$9\e(B (@code{gnus-article-add-buttons})\e$B!#\e(B
+@xref{Article Buttons}.
+
+@item W B
+@kindex W B (\e$B35N,\e(B)
+@findex gnus-article-add-buttons-to-head
+\e$B%/%j%C%/$G$-$k%\%?%s$r5-;v$N%X%C%@!<$K2C$($^\e(B
+\e$B$9\e(B (@code{gnus-article-add-buttons-to-head})\e$B!#\e(B
+
+@item W p
+@kindex W p (\e$B35N,\e(B)
+@findex gnus-article-verify-x-pgp-sig
+\e$B=pL>IU$-%3%s%H%m!<%k%a%C%;!<%8$NG'>Z$r9T$J$$$^\e(B
+\e$B$9\e(B (@code{gnus-article-verify-x-pgp-sig})\e$B!#\e(B
+@code{newgroup} \e$B$d\e(B @code{checkgroups} \e$B$H$$$C$?%3%s%H%m!<%k%a%C%;!<%8$O!"\e(B
+\e$BDL>o$=$N%K%e!<%9%0%k!<%W3,AX$N%a%$%s%F%$%J!<$K$h$C$F=pL>$5$l$F$$$^$9!#G'\e(B
+\e$B>Z$r9T$J$&$?$a$K$O!"%a%$%s%F%$%J!<$N\e(B @acronym{PGP} \e$B8x3+80$r$"$J$?$N%-!<\e(B
+\e$B%j%s%0$KDI2C$7$J$1$l$P$J$j$^$;$s!#\e(B@footnote{\e$BB?$/$N%K%e!<%9%0%k!<%W3,AX$N\e(B
+\e$B%a%$%s%F%$%J!<$N\e(B @acronym{PGP} \e$B$N80\e(B
+\e$B$O\e(B @uref{ftp://ftp.isc.org/pub/pgpcontrol/README.html} \e$B$+$iF~<j$9$k$3$H\e(B
+\e$B$,$G$-$^$9!#\e(B}
+
+@ignore
+@item W s
+@kindex W s (Summary)
+@findex gnus-summary-force-verify-and-decrypt
+Verify a signed (@acronym{PGP}, @acronym{PGP/MIME} or
+@acronym{S/MIME}) message
+(@code{gnus-summary-force-verify-and-decrypt}). @xref{Security}.
+
+@end ignore
+@item W a
+@kindex W a (\e$B35N,\e(B)
+@findex gnus-article-strip-headers-in-body
+\e$B5-;v$NK\BN$N@hF,$+$i\e(B @code{X-No-Archive} \e$B%X%C%@!<$N$h$&$J%X%C%@!<$r<h$j\e(B
+\e$B=|$-$^$9\e(B (@code{gnus-article-strip-headers-in-body})\e$B!#\e(B
+
+@item W E l
+@kindex W E l (\e$B35N,\e(B)
+@findex gnus-article-strip-leading-blank-lines
+\e$B5-;v$N;O$a$+$i$N$9$Y$F$N6uGr9T$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-article-strip-leading-blank-lines})\e$B!#\e(B
+
+@item W E m
+@kindex W E m (\e$B35N,\e(B)
+@findex gnus-article-strip-multiple-blank-lines
+\e$B$9$Y$F$N6uGr9T$r6u9T$GCV$-49$(!"$9$Y$F$NJ#?t$N6u9T$r0l$D$N6u9T$GCV$-49$(\e(B
+\e$B$^$9\e(B (@code{gnus-article-strip-multiple-blank-lines})\e$B!#\e(B
+
+@item W E t
+@kindex W E t (\e$B35N,\e(B)
+@findex gnus-article-remove-trailing-blank-lines
+\e$B5-;v$N:G8e$N$9$Y$F$N6uGr9T$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-article-remove-trailing-blank-lines})\e$B!#\e(B
+
+@item W E a
+@kindex W E a (\e$B35N,\e(B)
+@findex gnus-article-strip-blank-lines
+\e$B>e$N;0$D$NL?Na$r$9$Y$F9T$$$^$9\e(B (@code{gnus-article-strip-blank-lines})\e$B!#\e(B
+
+@item W E A
+@kindex W E A (\e$B35N,\e(B)
+@findex gnus-article-strip-all-blank-lines
+\e$B$9$Y$F$N6uGr9T$r<h$j=|$-$^$9\e(B (@code{gnus-article-strip-all-blank-lines})\e$B!#\e(B
+
+@item W E s
+@kindex W E s (\e$B35N,\e(B)
+@findex gnus-article-strip-leading-space
+\e$B5-;v$NK\BN$N$9$Y$F$N9T$N;O$a$+$i$N$9$Y$F$N6uGr$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-article-strip-leading-space})\e$B!#\e(B
+
+@item W E e
+@kindex W E e (\e$B35N,\e(B)
+@findex gnus-article-strip-trailing-space
+\e$B5-;v$NK\J8$NA4$F$N9T$N:G8e$+$i6uGr$r>C5n$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-strip-trailing-space})\e$B!#\e(B
+@end table
+
+\e$B5-;v$N@vBu$r<+F0E*$K$9$k$?$a$NJ}K!$O\e(B @ref{Customizing Articles} \e$B$r;2>H$7\e(B
+\e$B$F2<$5$$!#\e(B
+
+@node Article Header
+@subsection \e$B5-;v%X%C%@!<\e(B
+
+\e$B$3$l$i$N%3%^%s%I$O5-;v%X%C%@!<$r$$$m$$$mJQ7A$5$;$^$9!#\e(B
+
+@table @kbd
+@item W G u
+@kindex W G u (\e$B35N,\e(B)
+@findex gnus-article-treat-unfold-headers
+\e$B@^$jJV$5$l$?%X%C%@!<9T$r0l9T$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-treat-unfold-headers})\e$B!#\e(B
+
+@item W G n
+@kindex W G n (\e$B35N,\e(B)
+@findex gnus-article-treat-fold-newsgroups
+@code{Newsgroups} \e$B$H\e(B @code{Followup-To} \e$B%X%C%@!<$r@^$jJV$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-treat-fold-newsgroups})\e$B!#\e(B
+
+@item W G f
+@kindex W G f (\e$B35N,\e(B)
+@findex gnus-article-treat-fold-headers
+\e$B$9$Y$F$N%a%C%;!<%8%X%C%@!<$r@^$jJV$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-treat-fold-headers})\e$B!#\e(B
+
+@item W E w
+@kindex W E w (\e$B35N,\e(B)
+@findex gnus-article-remove-leading-whitespace
+\e$B$9$Y$F$N%X%C%@!<$+$iM>7W$J6uGr$r<h$j=|$-$^\e(B
+\e$B$9\e(B (@code{gnus-article-remove-leading-whitespace})\e$B!#\e(B
+@end table
+
+@node Article Buttons
+@subsection \e$B5-;v$N%\%?%s\e(B
+@cindex buttons
+
+\e$B$h$/5-;v$NCf$KB>$N$b$N$X$N;2>H$,F~$l$i$l$k;v$,$"$j$^$9!#$=$7$F!"\e(Bgnus \e$B$,\e(B
+\e$B$=$l$K4X$9$k;v$r!"$=$l$i$N;2>H$N>e$G\e(B @kbd{RET} \e$B$rBG$D$+!"%^%&%9$N??Cf$N\e(B
+\e$B%\%?%s$r;H$&;v$K$h$C$F!":G>.8B$NEXNO$G<hF@$9$k;v$,$G$-$l$PAGE($G$7$g$&!#\e(B
+
+@vindex gnus-button-man-handler
+Gnus \e$B$O%G%#%U%)%k%H$GFCDj$NI8=`$N;2>H$K\e(B@dfn{\e$B%\%?%s\e(B}\e$B$rIU$1$^$9\e(B: \e$B$A$c$s$H\e(B
+\e$B$7$?\e(B URL\e$B!"%a!<%k%"%I%l%9!"\e(BMessage-ID\e$B!"\e(BInfo \e$B$X$N%j%s%/!"\e(Bman \e$B%Z!<%8!"$=$l\e(B
+\e$B$K4XO"$9$k\e(B Emacs \e$B$^$?$O\e(B Gnus \e$B$N;29MJ88%$G$9!#$3$l$OFs$D$NJQ?t$K$h$C$F@)\e(B
+\e$B8f$5$l$F$$$F!"$=$N0l$D$O5-;v$NK\BN$r07$$!"$b$&0l$D$O5-;v$N%X%C%@!<$r07$$\e(B
+\e$B$^$9!#\e(B
+
+@table @code
+@item gnus-button-alist
+@vindex gnus-button-alist
+\e$B$=$l$>$l$NF~NOMWAG$,<!$N$h$&$JMM<0$NO"A[%j%9%H$G$9\e(B:
+
+@lisp
+(@var{regexp} @var{button-par} @var{use-p} @var{function} @var{data-par})
+@end lisp
+
+@table @var
+@item regexp
+\e$B$3$N@55,I=8=\e(B (\e$BBgJ8;z$H>.J8;z$O6hJL$5$l$J$$\e(B) \e$B$K9gCW$9$k$9$Y$F$NJ8$O30It;2\e(B
+\e$B>H$G$"$k$H$_$J$5$l$^$9!#$3$l$OKd$a9~$^$l$?\e(B URL \e$B$K9gCW$9$kE57?E*$J@55,I=\e(B
+\e$B8=$G$9\e(B @samp{<URL:\\([^\n\r>]*\\)>}\e$B!#$3$l$O$^$?@55,I=8=$NCM$r;}$DJQ?t$G\e(B
+\e$B$"$C$F$b$h$/!"M-MQ$JJQ?t$H$7$F\e(B @code{gnus-button-url-regexp} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-button-mid-or-mail-regexp} \e$B$,$"$j$^$9!#\e(B
+
+@item button-par
+Gnus \e$B$O9gCW$7$?$b$N$N$I$NItJ,$,%O%$%i%$%H$5$l$k$N$+$rCN$i$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#$3$l$O@55,I=8=$N$I$NI{I=8=$,%O%$%i%$%H$5$l$k$+$r;XDj$9$kHV9f$G$9!#\e(B
+\e$BA4$F$r%O%$%i%$%H$7$?$$$N$J$i!"$3$3$G\e(B 0 \e$B$r;H$C$F$/$@$5$$!#\e(B
+
+@item use-p
+\e$B$3$N<0$O\e(B @code{\e$BI>2A\e(B} \e$B$5$l!"7k2L$,\e(B @code{nil} \e$B$G$J$1$l$P!"$3$l$O9gCW$G$"\e(B
+\e$B$k$H$_$J$5$l$^$9!#$3$l$O4V0c$C$?9gCW$rHr$1$k$?$a$KFCJL$JA*JL$r$7$?$$$H$-\e(B
+\e$B$KLr$KN)$A$^$9!#$3$3$G$O$7$P$7$P\e(B @code{gnus-button-@var{*}-level} \e$B$N$h$&\e(B
+\e$B$JL>A0$NJQ?t$,;H$o$l$^$9$,!"B>$N$I$s$J7A<0$G$b;H$&$3$H$,$G$-$^$9!#\e(B
+
+@c @code{use-p} is @code{eval}ed only if @code{regexp} matches.
+
+@item function
+\e$B$3$N4X?t\e(B (function) \e$B$O$3$N%\%?%s$r%/%j%C%/$7$?$H$-$K8F$P$l$^$9!#\e(B
+
+@item data-par
+@var{button-par} \e$B$N$h$&$K!"$3$l$OItJ,I=8=$NHV9f$G$9$,!"$3$l$O9gCW$N$I$N\e(B
+\e$BItJ,$,\e(B @var{function} \e$B$K%G!<%?$H$7$FAw$i$l$k$+$r;XDj$7$^$9!#\e(B
+@end table
+
+\e$B$G$9$+$i!"\e(BURL \e$B$r%\%?%s$K$9$k40A4$JF~NOMWAG$O\e(B
+
+@lisp
+("<URL:\\([^\n\r>]*\\)>" 0 t gnus-button-url 1)
+@end lisp
+
+@item gnus-header-button-alist
+@vindex gnus-header-button-alist
+\e$B$=$l$,5-;v$N%X%C%@!<$@$1$KE,MQ$5$l!"$=$l$>$l$NF~NOMWAG$,$I$N%X%C%@!<$K%\\e(B
+\e$B%?%s2=$rE,MQ$9$k$+$r<($9DI2C$NMWAG$,$"$k;v$r=|$-!"$3$l$OB>$NO"A[%j%9%H$H\e(B
+\e$BF1$8$h$&$J$b$N$G$9\e(B:
+
+@lisp
+(@var{header} @var{regexp} @var{button-par} @var{use-p} @var{function} @var{data-par})
+@end lisp
+
+@var{header} \e$B$O@55,I=8=$G$9!#\e(B
+
+@subsubsection \e$B4XO"$9$kJQ?t$H4X?t\e(B
+
+@item gnus-button-@var{*}-level
+@xref{Article Button Levels}.
+
+@c Stuff related to gnus-button-browse-level
+
+@item gnus-button-url-regexp
+@vindex gnus-button-url-regexp
+\e$BKd$a9~$^$l$?\e(B URL \e$B$K9gCW$9$k@55,I=8=$G$9!#$=$l$O>e$NJQ?t$N%G%#%U%)%k%H$N\e(B
+\e$BCM$G;H$o$l$^$9!#\e(B
+
+@c Stuff related to gnus-button-man-level
+
+@item gnus-button-man-handler
+@vindex gnus-button-man-handler
+Man \e$B%Z!<%8$NI=<($K;H$&4X?t$G$9!#\e(BMan \e$B%Z!<%8$NL>A0$NJ8;zNs$G!">/$J$/$H$b0l\e(B
+\e$B$D$N0z?t$r<u$1IU$1$J$1$l$P$J$j$^$;$s!#\e(B
+
+@c Stuff related to gnus-button-message-level
+
+@item gnus-button-mid-or-mail-regexp
+@vindex gnus-button-mid-or-mail-regexp
+Message-ID \e$B$+%a!<%k%"%I%l%9$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item gnus-button-prefer-mid-or-mail
+@vindex gnus-button-prefer-mid-or-mail
+\e$B$3$NJQ?t$O\e(B @samp{foo123@@bar.invalid} \e$B$N$h$&$JJ8;zNs$N%\%?%s$,2!$5$l$?$H\e(B
+\e$B$-$K!"2?$r9T$J$&$+$r7h$a$kJQ?t$G$9!#$3$N$h$&$JJ8;zNs$O\e(B Message-ID \e$B$+%a!<\e(B
+\e$B%k%"%I%l%9$N$$$:$l$+$G$9!#$b$7\e(B @code{mid} \e$B$+\e(B @code{mail} \e$B$H$$$&%7%s%\%k\e(B
+\e$B$N$&$A$N0l$D$@$C$?$i!"\e(Bgnus \e$B$O>o$K$=$l$>$lJ8;zNs$,\e(B Message-ID \e$B$^$?$O%a!<\e(B
+\e$B%k%"%I%l%9$G$"$k$H2>Dj$7$^$9!#$3$NJQ?t$,\e(B @code{ask} \e$B$K@_Dj$5$l$k$H!"\e(B
+gnus \e$B$O$$$D$b%f!<%6$,2?$r$7$?$$$+$r?R$M$^$9!#$=$l$,4X?t$@$C$?>l9g!"$?$C\e(B
+\e$B$?0l$D$N0z?t$G$"$kJ8;zNs$,M?$($i$l$F8F$P$l$^$9!#$=$N4X?t$O\e(B @code{mid}\e$B!"\e(B
+@code{mail}\e$B!"\e(B@code{invalid} \e$B$^$?$O\e(B @code{ask} \e$B$rJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+\e$B%G%#%U%)%k%HCM$O4X?t\e(B @code{gnus-button-mid-or-mail-heuristic} \e$B$G$9!#\e(B
+
+@item gnus-button-mid-or-mail-heuristic
+@findex gnus-button-mid-or-mail-heuristic
+\e$B$=$N0z?t$,\e(B Message-ID \e$B$+%a!<%k%"%I%l%9$G$"$k$+$r?dDj$9$k4X?t$G$9!#\e(B
+Message-ID \e$B$@$C$?$i\e(B @code{mid} \e$B$r!"%a!<%k%"%I%l%9$@$C$?$i\e(B @code{mail} \e$B$r!"\e(B
+\e$BIT3N$+$@$C$?$i\e(B @code{ask} \e$B$r!"$=$7$FL58z$JJ8;zNs$@$C$?\e(B
+\e$B$i\e(B @code{invalid} \e$B$rJV$7$^$9!#\e(B
+
+@item gnus-button-mid-or-mail-heuristic-alist
+@vindex gnus-button-mid-or-mail-heuristic-alist
+\e$B4X?t\e(B @code{gnus-button-mid-or-mail-heuristic} \e$B$G;H$o$l$k\e(B @code{(RATE
+. REGEXP)} \e$BBP$NO"A[%j%9%H$G$9!#\e(B
+
+@c Stuff related to gnus-button-tex-level
+
+@item gnus-button-ctan-handler
+@findex gnus-button-ctan-handler
+CTAN \e$B%j%s%/$NI=<($K;H$&4X?t$G$9!#\e(BURL \e$BL>$NJ8;zNs$r0z?t$H$7$F!"0l$D<u$1IU\e(B
+\e$B$1$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item gnus-ctan-url
+@vindex gnus-ctan-url
+@code{gnus-button-ctan-handler} \e$B$G;H$o$l$k\e(B CTAN (Comprehensive TeX
+Archive Network) \e$B%"!<%+%$%V$N%G%#%l%/%H%j$G$9!#\e(B
+
+@c Misc stuff
+
+@item gnus-article-button-face
+@vindex gnus-article-button-face
+\e$B%\%?%s$K;H$o$l$k%U%'%$%9$G$9!#\e(B
+
+@item gnus-article-mouse-face
+@vindex gnus-article-mouse-face
+\e$B%^%&%9$N%+!<%=%k$,%\%?%s$N>e$K$"$k$H$-$K;H$o$l$k%U%'%$%9$G$9!#\e(B
+@end table
+
+\e$B5-;v$r<+F0E*$K%\%?%s2=$9$kJ}K!$O\e(B @ref{Customizing Articles} \e$B$r;2>H$7$F2<\e(B
+\e$B$5$$!#\e(B
+
+@node Article Button Levels
+@subsection Article button levels
+@cindex button levels
+\e$BJQ?t\e(B @code{gnus-button-@var{*}-level} \e$B$N9b$$CM$K$h$C$F!"$h$jB?$/$N%\%?%s\e(B
+\e$B$,8=$l$^$9!#%l%Y%k$,%<%m$@$C$?$i%\%?%s$OI=<($5$l$^$;$s!#%G%#%U%)%k%H\e(B
+\e$BCM\e(B (\e$B$=$l$O\e(B 5) \e$B$G$O!"$H$F$b$?$/$5$s$N%\%?%s$r$9$G$K8+$F$$$k$O$:$G$9!#9b$$\e(B
+\e$B%l%Y%k$G$O$h$jB?$/$N%\%?%s$r8+$k$3$H$K$J$j$^$9$,!"B?$/$NMW$i$J$$$b$N$b$"\e(B
+\e$B$k$+$b$7$l$^$;$s!#$=$l$i$rHr$1$k$?$a$K!"FCDj$N%0%k!<%W$KBP$7$FJQ\e(B
+\e$B?t\e(B @code{gnus-button-@var{*}-level} \e$B$r@_Dj$7$F$bNI$$$G$7$g\e(B
+\e$B$&\e(B (@pxref{Group Parameters})\e$B!#JQ?t\e(B @code{gnus-parameters} \e$B$NNc$G$9\e(B:
+
+@lisp
+;; @r{\e$B$$$/$D$+$N%0%k!<%W$G\e(B @code{gnus-button-*-level} \e$B$rA}$d$9\e(B:}
+(setq gnus-parameters
+      '(("\\<\\(emacs\\|gnus\\)\\>" (gnus-button-emacs-level 10))
+        ("\\<unix\\>"               (gnus-button-man-level 10))
+        ("\\<tex\\>"                (gnus-button-tex-level 10))))
+@end lisp
+
+@table @code
+@item gnus-button-browse-level
+@vindex gnus-button-browse-level
+Message-ID\e$B!"%a!<%k%"%I%l%9$*$h$S%K%e!<%9$N\e(B URL \e$B$K4X$9$k;29MJ88%$NI=<($r\e(B
+\e$B@)8f$7$^$9!#4XO"$9$kJQ?t$H4X?t$K$O\e(B @code{gnus-button-url-regexp}\e$B!"\e(B
+@code{browse-url} \e$B$*$h$S\e(B @code{browse-url-browser-function} \e$B$,$"$j$^$9!#\e(B
+
+@item gnus-button-emacs-level
+@vindex gnus-button-emacs-level
+Emacs \e$B$^$?$O\e(B gnus \e$B$N;29MJ88%$NI=<($r@)8f$7$^$9!#4XO"$9$k4X?t$O!"\e(B
+@code{gnus-button-handle-custom},
+@code{gnus-button-handle-describe-function},
+@code{gnus-button-handle-describe-variable},
+@code{gnus-button-handle-symbol},
+@code{gnus-button-handle-describe-key},
+@code{gnus-button-handle-apropos},
+@code{gnus-button-handle-apropos-command},
+@code{gnus-button-handle-apropos-variable},
+@code{gnus-button-handle-apropos-documentation} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-button-handle-library} \e$B$G$9!#\e(B
+
+@item gnus-button-man-level
+@vindex gnus-button-man-level
+(Unix \e$B$N\e(B) man \e$B%Z!<%8$NI=<($r@)8f$7$^$9!#\e(B
+@code{gnus-button-man-handler} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item gnus-button-message-level
+@vindex gnus-button-message-level
+Message-ID\e$B!"%a!<%k%"%I%l%9$*$h$S%K%e!<%9$N\e(B URL \e$B$NI=<($r@)8f$7$^$9!#4XO"\e(B
+\e$B$9$kJQ?t$H4X?t$K\e(B
+\e$B$O\e(B @code{gnus-button-mid-or-mail-regexp},
+@code{gnus-button-prefer-mid-or-mail},
+@code{gnus-button-mid-or-mail-heuristic} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-button-mid-or-mail-heuristic-alist} \e$B$,$"$j$^$9!#\e(B
+
+@item gnus-button-tex-level
+@vindex gnus-button-tex-level
+@TeX{} \e$B$^$?$O\e(B LaTex \e$B$K4X$9$k;29MJ88%!"Nc$($P\e(B CTAN \e$B$N\e(B URL\e$B!"$NI=<($r@)8f$7\e(B
+\e$B$^$9!#JQ?t\e(B @code{gnus-ctan-url},
+@code{gnus-button-ctan-handler},
+@code{gnus-button-ctan-directory-regexp} \e$B$*$h$S\e(B
+@code{gnus-button-handle-ctan-bogus-regexp} \e$B$r;2>H$7$F2<$5$$!#\e(B
+@end table
+
+@node Article Date
+@subsection \e$B5-;v$NF|IU\e(B
+
+\e$BF|IU$OJ9$$$?;v$NL5$$2?$+JUnA$J;~4VBS\e(B (timezone) \e$B$G:n@.$5$l$F$$$k;v$,NI$/\e(B
+\e$B$"$k$N$G!"5-;v$,Aw$i$l$?$H$-$K2?;~$G$"$C$?$+$rCN$k;v$,$G$-$k$N$OHs>o$KNI\e(B
+\e$B$$;v$G$7$g$&!#\e(B
+
+@table @kbd
+@item W T u
+@kindex W T u (\e$B35N,\e(B)
+@findex gnus-article-date-ut
+UT (\e$BJLL>\e(B GMT, ZULU) \e$B$GF|IU$rI=<($7$^$9\e(B (@code{gnus-article-date-ut})\e$B!#\e(B
+
+@item W T i
+@kindex W T i (\e$B35N,\e(B)
+@findex gnus-article-date-iso-8601
+@cindex ISO 8601
+\e$BF|IU$r9q:]E*$J7A<0!"\e(BISO 8601 \e$B$GI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-article-date-iso8601})\e$B!#\e(B
+
+@item W T l
+@kindex W T l (\e$B35N,\e(B)
+@findex gnus-article-date-local
+\e$BF|IU$rMxMQ<T$NCO0h$N;~4VBS$GI=<($7$^$9\e(B (@code{gnus-article-date-local})\e$B!#\e(B
+
+@item W T p
+@kindex W T p (\e$B35N,\e(B)
+@findex gnus-article-date-english
+\e$BF|IU$r1Q8l$GH/2;$G$-$k7A<0$GI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-article-date-english})\e$B!#\e(B
+
+@item W T s
+@kindex W T s (\e$B35N,\e(B)
+@vindex gnus-article-time-format
+@findex gnus-article-date-user
+@findex format-time-string
+\e$BF|IU$rMxMQ<TDj5A$NMM<0$r;H$C$FI=<($7$^$9\e(B (@code{gnus-article-date-user})\e$B!#\e(B
+\e$B$=$NMM<0$OJQ?t\e(B @code{gnus-article-time-format} \e$B$G;XDj$5$l!"\e(B
+@code{format-time-string} \e$B$KEO$5$l$kJ8;zNs$G$9!#MM<0;XDj$r$9$k;v$,$G$-$k\e(B
+\e$B0lMw$OJQ?t$N@bL@J8$r8+$F$/$@$5$$!#\e(B
+
+@item W T e
+@kindex W T e (\e$B35N,\e(B)
+@findex gnus-article-date-lapsed
+@findex gnus-start-date-timer
+@findex gnus-stop-date-timer
+\e$B5-;v$,Ej9F$5$l$F$+$i:#$^$G$I$l$/$i$$$N;~4V$,7P2a$7$?$+$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-article-date-lapsed})\e$B!#$3$s$J$U$&$K!#\e(B
+
+@example
+X-Sent: 6 weeks, 4 days, 1 hour, 3 minutes, 8 seconds ago
+@end example
+
+@vindex gnus-article-date-lapsed-new-header
+@code{gnus-article-date-lapsed-new-header} \e$B$NCM$G$3$N%X%C%@!<$r4{B8\e(B
+\e$B$N\e(B Date \e$B$N2<$KDI2C$9$k$+!"CV$-BX$($k$+$r;XDj$7$^$9!#\e(B
+
+gnus \e$B$G%a!<%k$rFI$`$3$H$NM-Mx$JE@$O!"C1=c$J%P%0$rAG@2$i$7$$IT>rM}$KCV$-\e(B
+\e$B49$($k$3$H$G$9!#\e(B
+
+\e$B$3$N9T$,O"B3$7$F99?7$5$l$k$h$&$K$7$?$$$N$G$"$l$P!"\e(B
+
+@lisp
+(gnus-start-date-timer)
+@end lisp
+
+\e$B$r$"$J$?$N\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$k$+!"2?$+$N%U%C%/$G<B9T$9$k\e(B
+\e$B$h$&$K$9$k;v$,$G$-$^$9!#%?%$%^!<$r;_$a$?$$$N$G$"$l$P!"L?\e(B
+\e$BNa\e(B @code{gnus-stop-date-timer} \e$B$r;H$&;v$,$G$-$^$9!#\e(B
+
+@item W T o
+@kindex W T o (\e$B35N,\e(B)
+@findex gnus-article-date-original
+\e$BK\Mh$NF|IU$rI=<($7$^$9\e(B (@code{gnus-article-date-original})\e$B!#$3$l$O$"$J$?\e(B
+\e$B$,IaDL$OB>$NJQ494X?t$r;H$C$F$$$F!"$=$l$,40A4$K4V0c$C$?;v$r$7$F$$$k$N$G$O\e(B
+\e$B$J$$$+$H?4G[$7$F$$$k$H$-$KLr$KN)$A$^$9!#Nc$($P!"5-;v$,\e(B 1854\e$BG/$KEj9F$5$l\e(B
+\e$B$?$H$J$C$F$$$k$H$7$^$7$g$&!#$7$+$7!"$=$N$h$&$J;v$O\e(B @emph{\e$B40A4$K\e(B }\e$BIT2DG=\e(B
+\e$B$G$9!#;d$,?.MQ$G$-$^$;$s$+\e(B? *\e$B$/$9$/$9\e(B(\e$B>P\e(B)*
+@end table
+
+\e$B<+F0E*$K9%$`=q<0$GF|IU$rI=<($9$kJ}K!$O\e(B @ref{Customizing Articles} \e$B$r;2>H\e(B
+\e$B$7$F2<$5$$!#\e(B
+
+@node Article Display
+@subsection Article Display
+@cindex picons
+@cindex x-face
+@cindex smileys
+
+\e$B$3$l$i$N%3%^%s%I$O!"$$$m$s$J<h$k$KB-$i$J$$%.%_%C%/\e(B (gimmicks) \e$B$NI=<($r!"\e(B
+\e$B$=$l$i$r%5%]!<%H$7$F$$$k\e(B Emacs \e$B$N5-;v%P%C%U%!$KDI2C$7$^$9!#\e(B
+
+@code{X-Face} \e$B%X%C%@!<$O>.$5$JGr9u2hA|$G!"%a%C%;!<%8%X%C%@!<$+$i6!5k$5$l\e(B
+\e$B$^$9\e(B (@pxref{X-Face})\e$B!#\e(B
+
+@code{Face} \e$B%X%C%@!<$O>.$5$J%+%i!<2hA|$G!"%a%C%;!<%8%X%C%@!<$+$i6!5k$5$l\e(B
+\e$B$^$9\e(B (@pxref{Face})\e$B!#\e(B
+
+\e$B%9%^%$%j!<$O!"?M!9$,%a%C%;!<%8$K;6$i$+$7$?$,$k>.$5$J\e(B @samp{:-)} \e$B%7%s%\%k\e(B
+\e$B$G$9!#\e(B
+
+\e$B0lJ}\e(B Picon \e$B$O$"$J$?<+?H$N%7%9%F%`$K0MB8$7!"\e(Bgnus \e$B$O%X%C%@!<$K%^%C%A$9$k$"\e(B
+\e$B$J$?$N;}$AJ*$rC5$7$F$_$^$9\e(B (@pxref{Picons})\e$B!#\e(B
+
+\e$B$3$l$i$9$Y$F$N5!G=$O%H%0%k$G$9!#$b$7$9$G$K$=$l$i$,B8:_$7$F$$$?$J$i$P!"$=\e(B
+\e$B$l$i$O:o=|$5$l$^$9!#\e(B
+
+@table @kbd
+@item W D x
+@kindex W D x (\e$B35N,\e(B)
+@findex gnus-article-display-x-face
+@code{X-Face} \e$B$r\e(B @code{From} \e$B%X%C%@!<$KI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-article-display-x-face})\e$B!#\e(B
+
+@item W D d
+@kindex W D d (\e$B35N,\e(B)
+@findex gnus-article-display-face
+@code{Face} \e$B$r\e(B @code{From} \e$B%X%C%@!<$KI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-article-display-face})\e$B!#\e(B
+
+@item W D s
+@kindex W D s (\e$B35N,\e(B)
+@findex gnus-treat-smiley
+\e$B%9%^%$%j!<$rI=<($7$^$9\e(B (@code{gnus-treat-smiley})\e$B!#\e(B
+
+@item W D f
+@kindex W D f (\e$B35N,\e(B)
+@findex gnus-treat-from-picon
+@code{From} \e$B%X%C%@!<$r\e(B Picon \e$B2=$7$^$9\e(B (@code{gnus-treat-from-picon})\e$B!#\e(B
+
+@item W D m
+@kindex W D m (\e$B35N,\e(B)
+@findex gnus-treat-mail-picon
+\e$B$9$Y$F$N%a!<%k%X%C%@!<\e(B (\e$B$9$J$o$A\e(B @code{Cc}\e$B!"\e(B@code{To}) \e$B$r\e(B Picon \e$B2=$7$^\e(B
+\e$B$9\e(B (@code{gnus-treat-mail-picon})\e$B!#\e(B
+
+@item W D n
+@kindex W D n (\e$B35N,\e(B)
+@findex gnus-treat-newsgroups-picon
+\e$B$9$Y$F$N%K%e!<%9%X%C%@!<\e(B (\e$B$9$J$o\e(B
+\e$B$A\e(B @code{Newsgroups} \e$B$H\e(B @code{Followup-To}) \e$B$r\e(B Picon \e$B2=$7$^\e(B
+\e$B$9\e(B (@code{gnus-treat-newsgroups-picon})\e$B!#\e(B
+
+@item W D D
+@kindex W D D (\e$B35N,\e(B)
+@findex gnus-article-remove-images
+\e$B5-;v%P%C%U%!$+$i$9$Y$F$N2hA|$r:o=|$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-remove-images})\e$B!#\e(B
+@end table
+
+@node Article Signature
+@subsection \e$B5-;v$N=pL>\e(B
+@cindex signatures
+@cindex article signature
+
+@vindex gnus-signature-separator
+\e$B$=$l$>$l$N5-;v$OFs$D$NItJ,$KJ,$1$i$l$^$9!=!=8+=P$7\e(B (header) \e$B$HK\\e(B
+\e$BBN\e(B (body) \e$B$G$9!#K\BN$O=pL>ItJ,$HJ8>OItJ,$KJ,$1$i$l$^$9!#$I$l$,=pL>$H$_$J\e(B
+\e$B$5$l$k$+$r7h$a$kJQ?t$O\e(B @code{gnus-signature-separator} \e$B$G$9!#$3$l$OIaDL\e(B
+\e$B$O\e(B son-of-RFC 1036 \e$B$G;X<($5$l$F$$$kI8=`$N\e(B @samp{^-- $} \e$B$G$9!#$7$+$7!"B?\e(B
+\e$B$/$N?M$,I8=`$G$J$$=pL>J,N%$rMQ$$$^$9$N$G!"$3$NJQ?t$O0l$D0l$D;n$5$l$k!"@5\e(B
+\e$B5,I=8=$N%j%9%H$G$"$k$3$H$b$G$-$^$9!#\e(B(\e$BC5:w$OK\BN$N:G8e$+$i;O$a$X$H$J$5$l\e(B
+\e$B$^$9!#\e(B) \e$B$h$/$"$j$=$&$JCM$O\e(B:
+
+@lisp
+(setq gnus-signature-separator
+      '("^-- $"         ; @{\e$BI8=`\e(B}
+        "^-- *$"        ; @{\e$BIaDL$N2u$7J}\e(B}
+        "^-------*$"    ; @{\e$BB?$/$N?M$OD9!<!<$$2#K@$N\e(B}
+                        ; @{\e$B9T$r;H$$$^$9!#$"$!\e(B!}
+        "^ *--------*$" ; @{\e$BFsG\$N$"$!$!\e(B!}
+        "^________*$"   ; @{\e$B2<@~$b?M5$$,$"$j$^$9\e(B}
+        "^========*$")) ; @{\e$B<YF;\e(B!}
+@end lisp
+
+\e$B$"$J$?$,42MF$G$"$l$P$"$k$[$I!"4V0c$C$?7k2L$rF@$k;v$K$J$k$G$7$g$&!#\e(B
+
+@vindex gnus-signature-limit
+@code{gnus-signature-limit} \e$B$O5-;v$rI=<($9$k$H$-$K$I$l$,=pL>$H$_$J$5$l$k\e(B
+\e$B$+$X$N@)8B$rDs6!$7$^$9!#\e(B
+
+@enumerate
+@item
+\e$B$3$l$,@0?t$G$"$l$P!"=pL>$O$3$N@0?t$h$j\e(B (\e$BJ8;z$G\e(B) \e$BD9$/$J$C$F$$$F$O$$$1$^$;\e(B
+\e$B$s!#\e(B
+@item
+\e$B$3$l$,IbF0>.?tE@?t$G$"$l$P!"=pL>$O$=$N?t;z$h$j\e(B (\e$B9T$G\e(B) \e$BD9$/$J$C$F$$$F$O$$\e(B
+\e$B$1$^$;$s!#\e(B
+@item
+\e$B$3$l$,4X?t$G$"$l$P!"$=$N4X?t$O0z?t$J$7$G8F$P$l!"$=$l$,\e(B @code{nil} \e$B$rJV$;\e(B
+\e$B$P!"%P%C%U%!$K$O=pL>$,$"$j$^$;$s!#\e(B
+@item
+\e$B$3$l$,J8;zNs$G$"$l$P!"$=$l$O@55,I=8=$H$7$F;H$o$l$^$9!#$b$7$=$l$,9gCW$9$l\e(B
+\e$B$P!"$=$NEv$NJ8;zNs$O=pL>$G$O$"$j$^$;$s!#\e(B
+@end enumerate
+
+\e$B$3$NJQ?t$OMWAG$,>e$K5s$2$i$l$?7?$N%j%9%H$G$"$k;v$b$G$-$^$9!#$3$l$ONc$G$9\e(B:
+
+@lisp
+(setq gnus-signature-limit
+      '(200.0 "^---*Forwarded article"))
+@end lisp
+
+\e$B$3$l$O=pL>J,N%J*$N8e$K\e(B 200 \e$B$rD6$($k9T$+!"=pL>J,N%J*$N8e$NJ8>O$,@55,I=\e(B
+\e$B8=\e(B @samp{^---*Forwarded article} \e$B$K9gCW$9$l$P!"7k6I$=$l$O=pL>$G$O$J$$$H\e(B
+\e$B$$$&;v$G$9!#\e(B
+
+@node Article Miscellanea
+@subsection \e$B5-;v$$$m$$$m\e(B
+
+@table @kbd
+@item A t
+@kindex A t (\e$B35N,\e(B)
+@findex gnus-article-babel
+\e$B5-;v$r$"$k8@8l$+$iJL$N$b$N$XJQ49$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-babel})\e$B!#\e(B
+@end table
+
+@c node `MIME Commands' and node `Charsets' is stripped, which is
+@c pGnus specific.
+
+@node Article Commands
+@section \e$B5-;vL?Na\e(B
+
+@table @kbd
+@item A P
+@cindex PostScript
+@cindex printing
+@kindex A P (\e$B35N,\e(B)
+@vindex gnus-ps-print-article
+@findex gnus-summary-print-article
+\e$B5-;v%P%C%U%!$N%]%9%H%9%/%j%W%H\e(B (PostScript) \e$B%$%a!<%8$r:n@.$7$F0u:~$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-print-article})\e$B!#\e(B@code{gnus-ps-print-hook} \e$B$,%P%C\e(B
+\e$B%U%!$r0u:~$9$kD>A0$K<B9T$5$l$k$G$7$g$&!#B>$K!"\e(BMuttprint \e$B$r;H$C$F0u:~$9$k\e(B
+\e$B$3$H$b$G$-$^$9\e(B (@pxref{Saving Articles})\e$B!#\e(B
+@end table
+
+@node Summary Sorting
+@section \e$B35N,$NJB$SBX$(\e(B
+@cindex summary sorting
+
+\e$B;d$O$I$&$7$F$"$J$?$,$=$&$7$?$$$N$+$O$o$+$i$J$$$N$G$9$,!"$=$l$G$b$"$J$?$O\e(B
+\e$B$?$/$5$s$NJ}K!$G35N,%P%C%U%!$rJB$SBX$($k;v$,$G$-$^$9!#\e(B
+
+@table @kbd
+@item C-c C-s C-n
+@kindex C-c C-s C-n (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-number
+\e$B5-;vHV9f$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-number})\e$B!#\e(B
+
+@item C-c C-s C-a
+@kindex C-c C-s C-a (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-author
+\e$BCx<T$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-author})\e$B!#\e(B
+
+@item C-c C-s C-s
+@kindex C-c C-s C-s (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-subject
+\e$BI=Bj$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-subject})\e$B!#\e(B
+
+@item C-c C-s C-d
+@kindex C-c C-s C-d (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-date
+\e$BF|IU$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-date})\e$B!#\e(B
+
+@item C-c C-s C-l
+@kindex C-c C-s C-l (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-lines
+\e$B9T$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-lines})\e$B!#\e(B
+
+@item C-c C-s C-c
+@kindex C-c C-s C-c (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-chars
+\e$B5-;v$ND9$5$GJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-chars})\e$B!#\e(B
+
+@item C-c C-s C-i
+@kindex C-c C-s C-i (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-score
+\e$B%9%3%"$K$h$C$FJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-score})\e$B!#\e(B
+
+@item C-c C-s C-r
+@kindex C-c C-s C-r (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-random
+\e$B%i%s%@%`$KJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-random})\e$B!#\e(B
+
+@item C-c C-s C-o
+@kindex C-c C-s C-o (\e$B35N,\e(B)
+@findex gnus-summary-sort-by-original
+\e$B%G%#%U%)%k%H$NJ}K!$GJB$SBX$($^$9\e(B (@code{gnus-summary-sort-by-original})\e$B!#\e(B
+@end table
+
+\e$B$3$l$i$N4X?t$O%9%l%C%I$r;H$C$F$$$k$H$-$H;H$C$F$$$J$$$H$-$NN>J}$GF0:n$7$^\e(B
+\e$B$9!#8e<T$N>l9g$O!"$9$Y$F$N35N,9T$,0l9T0l9TJB$SBX$($i$l$^$9!#A0<T$N>l9g$O!"\e(B
+\e$B:,K\$H:,K\$r4pK\$H$7$FJB$SBX$($i$l!"$=$l$O$"$J$?$,5a$a$F$$$k;v$H$O0[\e(B
+\e$B$J$C$F$$$k$+$b$7$l$^$;$s!#%9%l%C%I$r;H$&;v$r@Z$jBX$($k$K$O\e(B @kbd{T T} \e$B$r\e(B
+\e$BBG$C$F$/$@$5$$\e(B (@pxref{Thread Commands})\e$B!#\e(B
+
+@node Finding the Parent
+@section \e$B?F5-;v$rC5$9\e(B
+@cindex parent articles
+@cindex referring articles
+
+@table @kbd
+@item ^
+@kindex ^ (\e$B35N,\e(B)
+@findex gnus-summary-refer-parent-article
+\e$B8=:_$N5-;v$N?F5-;v$rFI$_$?$/$F!"$=$l$,35N,%P%C%U%!$KI=<($5$l$F$$$J$/$F$b!"\e(B
+\e$B$*$=$i$/$=$l$O2DG=$G$7$g$&!#$H$$$&$N$O!"8=:_$N%0%k!<%W\e(B
+\e$B$,\e(B @acronym{NNTP} \e$B$G<hF@$5$l$F$$$F!"?F$,$^$@4|8B>C5n$5$l$F$$$J$$>e!"8=:_\e(B
+\e$B$N5-;v$N\e(B @code{References} \e$B$,$V$A2u$5$l$F$$$J$1$l$P!"$?$@!"\e(B
+@kbd{^} \e$B$+\e(B @kbd{A r} \e$B$r2!$;$PNI$$$@$1$G\e(B
+\e$B$9\e(B (@code{gnus-summary-refer-parent-article})\e$B!#$b$7A4$F$,>e<j$/9T$1$P!"\e(B
+\e$B?F5-;v$r<hF@$G$-$k$G$7$g$&!#$b$7?F5-;v$,4{$K35N,%P%C%U%!$KI=<($5$l$F$$$k\e(B
+\e$B$N$G$"$l$P!"%]%$%s%H$,$=$N5-;v$K0\F0$9$k$G$7$g$&!#\e(B
+
+\e$B@5$N?tCM@\F,0z?t$rM?$($i$l$l$P!"AD@h$^$GB?$/$N5-;v$rLa$C$F<hF@$7$^$9!#Ii\e(B
+\e$B$N?t;z@\F,0z?t$,M?$($i$l$l$P!"$=$NAD@h$N5-;v$@$1$r<hF@$7$^$9!#$G$9$+$i!"\e(B
+@kbd{3 ^} \e$B$H$9$l$P!"\e(Bgnus \e$B$O8=:_$N5-;v$N?F$H!"ADIcJl$H!"A=ADIcJl$r<hF@$7\e(B
+\e$B$^$9!#\e(B@kbd{-3 ^} \e$B$H$9$l$P!"\e(Bgnus \e$B$O8=:_$N5-;v$NA=ADIcJl$@$1$r<hF@$7$^$9!#\e(B
+
+@item A R (\e$B35N,\e(B)
+@findex gnus-summary-refer-references
+@kindex A R (\e$B35N,\e(B)
+\e$B5-;v$N\e(B @code{References} \e$BMs$K$"$kA4$F$N5-;v$r<hF@$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-refer-references})\e$B!#\e(B
+
+@item A T (\e$B35N,\e(B)
+@findex gnus-summary-refer-thread
+@kindex A T (\e$B35N,\e(B)
+\e$B8=:_$N5-;v$,=P$F$-$F$$$k%9%l%C%I$N!"40A4$J%9%l%C%I$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-refer-thread})\e$B!#$3$NL?Na$OF0:n$9$k$?$a$K8=:_$N%0\e(B
+\e$B%k!<%W$N$9$Y$F$N%X%C%@!<$r<hF@$7$J$1$l$P$J$j$^$;$s$N$G!"IaDL$O>/$7;~4V$,\e(B
+\e$B$+$+$j$^$9!#$b$7!"$3$l$r$7$P$7$P9T$&$N$G$"$l$P!"\e(B
+@code{gnus-fetch-old-headers} \e$B$r\e(B @code{invisible} \e$B$K@_Dj$9$k$3$H$r9M$($?\e(B
+\e$B$[$&$,NI$$$G$7$g$&\e(B (@pxref{Filling In Threads})\e$B!#$3$l$OIaDL$O;k3PE*$J8z\e(B
+\e$B2L$O$"$j$^$;$s$,!"$3$NL?Na$NF0:n$r$+$J$jB.$/$9$k$G$7$g$&!#$b$A$m$s!"%0%k!<\e(B
+\e$B%W$KF~$k$N$O>/$7CY$/$J$j$^$9!#\e(B
+
+@vindex gnus-refer-thread-limit
+\e$BJQ?t\e(B @code{gnus-refer-thread-limit} \e$B$O$3$NL?Na$r<B9T$9$k$H$-$K$I$N$/$i$$\e(B
+\e$B8E$$\e(B (\e$B$9$J$o$A!"8=:_$N5-;v$G:G=i$KI=<($5$l$?$h$j$bA0$N5-;v\e(B) \e$B%X%C%@!<$r<h\e(B
+\e$BF@$9$k$+$r;XDj$7$^$9!#%G%#%U%)%k%H$O\e(B 200 \e$B$G$9!#$b$7\e(B @code{t} \e$B$G$"$l$P!"\e(B
+\e$B<hF@2DG=$J$9$Y$F$N%X%C%@!<$r<hF@$7$^$9!#$3$NJQ?t$OL?Na\e(B @code{A T} \e$B$K?tCM\e(B
+\e$B@\F,0z?t$rM?$($k;v$K$h$j>e=q$-$9$k;v$,$G$-$^$9!#\e(B
+
+@item M-^ (\e$B35N,\e(B)
+@findex gnus-summary-refer-article
+@kindex M-^ (\e$B35N,\e(B)
+@cindex Message-ID
+@cindex fetching by Message-ID
+\e$B$I$N%0%k!<%W$KB0$7$F$$$k$+$K4X$o$i$:!"G$0U$N5-;v$r\e(B @acronym{NNTP} \e$B%5!<%P!<\e(B
+\e$B$K?R$M$k;v$,$G$-$^$9!#\e(B
+@kbd{M-^} (@code{gnus-summary-refer-article}) \e$B$O\e(B @code{Message-ID}\e$B!"$=$l\e(B
+\e$B$O$"$ND9$/!"$J$+$J$+FI$`;v$N$G$-$J\e(B
+\e$B$$\e(B @samp{<38o6up$6f2@@hymir.ifi.uio.no>} \e$B$N$h$&$J;2>H$r$"$J$?$K?R$M$^$9!#\e(B
+\e$B$"$J$?$O$9$Y$F$r@53N$KBG$A9~$^$J$1$l$P$J$j$^$;$s!#;DG0$J$,$i!"$"$$$^$$$J\e(B
+\e$B8!:w$O$G$-$J$$$N$G$9!#\e(B
+@end table
+
+\e$B%K%e!<%9$G$J$$A*BrJ}K!$+$i\e(B @code{Message-ID} \e$B$G<hF@$9$k$H$-$K$O8=:_$NA*\e(B
+\e$BBrJ}K!$,;H$o$l$^$9$,!"$3$NL?Na$K@\F,0z?t$rM?$($k;v$G$3$l$r>e=q$-$9$k;v$,\e(B
+\e$B$G$-$^$9!#\e(B
+
+@vindex gnus-refer-article-method
+\e$B$b$7$"$J$?$NFI$s$G$$$k%0%k!<%W$,\e(B @code{Message-ID} \e$B$G$N<hF@$,$"$^$jNI$/\e(B
+\e$B$G$-$J$$$h$&$J%0%k!<%W\e(B (@code{nnspool} \e$B$J$I\e(B) \e$B$G$"$k>l9g!"\e(B
+@code{gnus-refer-article-method} \e$B$r\e(B @acronym{NNTP} \e$B$K@_Dj$9$k;v$,$G$-$^\e(B
+\e$B$9!#$*$=$i$/!"$"$J$?$,2qOC$7$F$$$k\e(B @acronym{NNTP} \e$B%5!<%P!<$,$"$J$?$NFI$s\e(B
+\e$B$G$$$k%9%W!<%k$r99?7$7$F$$$k$HHs>o$KNI$$$G$7$g$&!#$7$+$7!"$=$l$O$I$&$7$F\e(B
+\e$B$bI,MW$J$o$1$G$O$"$j$^$;$s!#\e(B
+
+\e$B$=$l$OA*BrJ}K!$N%j%9%H$G$"$k$3$H$b$G$-!"FCJL$J%7%s%\%k\e(B @code{current} \e$B$G\e(B
+\e$B$"$k$3$H$b$G$-$^$9!#8e<T$O!"8=:_$NA*BrJ}K!$r;H$&$H$$$&0UL#$G$9!#%j%9%H$N\e(B
+\e$B>l9g$O!"\e(Bgnus \e$B$O9g$&$b$N$rH/8+$9$k$^$G%j%9%H$NA4$F$NJ}K!$r;n$7$^$9!#\e(B
+
+\e$B$3$l$O8=:_$NJ}K!$r;n$7$F!"$=$l$,<:GT$7$?>l9g$K$O\e(B Google \e$B$K?V$/@_Dj$NNc$G\e(B
+\e$B$9\e(B:
+
+@lisp
+(setq gnus-refer-article-method
+      '(current
+        (nnweb "google" (nnweb-type google))))
+@end lisp
+
+\e$B$[$H$s$I$N%a!<%k%P%C%/%(%s%I$O\e(B @code{Message-ID} \e$B$G$N<hF@$,2DG=$G$9$,!"\e(B
+\e$B$"$^$jM%2m$JJ}K!$G$d$C$F$$$k$o$1$G$O$"$j$^$;$s!#\e(B@code{nnmbox},
+@code{nnbabyl}, @code{nnmaildir} \e$B$*$h$S\e(B @code{nnml} \e$B$O$I$N%0%k!<%W$+$i$N\e(B
+\e$B5-;v$b0LCV$rF@$k$3$H$,$G$-$^$9$,!"\e(B@code{nnfolder} \e$B$H\e(B @code{nnimap} \e$B$O8=\e(B
+\e$B:_$N%0%k!<%W$KEj9F$7$?5-;v$N0LCV$7$+F@$k;v$,$G$-$^$;$s!#\e(B(\e$B$=$NB>$N$b$N$O\e(B
+\e$B;~4V$,$+$+$j$9$.$^$9!#\e(B) @code{nnmh} \e$B$G$OA4$/IT2DG=$G$9!#\e(B
+
+@node Alternative Approaches
+@section \e$BBeBX<jCJ\e(B
+
+\e$B0c$C$??M$O0c$C$?J}K!$r;H$C$F%K%e!<%9$rFI$b$&$H$7$^$9!#$3$l$O\e(B gnus \e$B$G$b$=\e(B
+\e$B$&$G$"$k$N$G!"2f!9$O35N,%P%C%U%!!<$N$?$a$N%^%$%J!<%b!<%I\e(B (minor mode) \e$B$K\e(B
+\e$B>/$7$NA*Br;h$rM?$($F$"$j$^$9!#\e(B
+
+@menu
+* Pick and Read::               \e$B$^$:!"5-;v$K0u$rIU$1$F!"$=$l$+$iFI$`\e(B
+* Binary Groups::               \e$B$9$Y$F$N5-;v$r<+F0\e(B-\e$BI|9f2=$9$k\e(B
+@end menu
+
+@node Pick and Read
+@subsection \e$BA*$s$GFI$`\e(B
+@cindex pick and read
+
+\e$B$$$/$D$+$N%K%e!<%9%j!<%@!<\e(B (@code{nn} \e$B$d!"$"$N$)!"\e(BVM/CMS \e$B$G\e(B
+\e$B$N\e(B @code{Netnews} \e$B$J$I\e(B) \e$B$OFsAj$NFI$`$?$a$N3&LL$r;H$$$^$9!#MxMQ<T$O$^$:35\e(B
+\e$BN,%P%C%U%!$GFI$_$?$$5-;v$K0u$rIU$1$^$9!#$=$l$+$i!"5-;v%P%C%U%!$@$1$rI=<(\e(B
+\e$B$7$F5-;v$rFI$_$^$9!#\e(B
+
+@vindex gnus-pick-mode
+@kindex M-x gnus-pick-mode
+Gnus \e$B$O$3$l$r$9$k$?$a$N35N,%P%C%U%!%^%$%J!<%b!<%I$rDs6!$7$^$9!=!=\e(B
+@code{gnus-pick-mode} \e$B$G$9!#$3$l$O4pK\E*$K$O4JC1$K0u$rIU$1$i$l$k$h$&$K>/\e(B
+\e$B$7$N%W%m%;%90uL?Na$,0lBG80L?Na$K$J$j!"35N,%P%C%U%!$X@Z$jBX$($k$?$a$NDI2C\e(B
+\e$BL?Na$r0l$DDs6!$7$^$9!#\e(B
+
+\e$B$3$l$,\e(B pick mode \e$B$r;H$C$?$H$-$K;HMQ2DG=$J%-!<$G$9\e(B:
+
+@table @kbd
+@item .
+@kindex . (\e$BA*Br\e(B)
+@findex gnus-pick-article-or-thread
+\e$B8=:_$N9T$N5-;v$+%9%l%C%I$rA*Br$7$^\e(B
+\e$B$9\e(B (@code{gnus-pickd-article-or-thread})\e$B!#$b$7JQ\e(B
+\e$B?t\e(B @code{gnus-thread-hide-subtree} \e$B$,\e(B true \e$B$G$"$l$P!"$3$N%-!<$O%9%l%C%I\e(B
+\e$B$N:G=i$N5-;v$G;H$o$l$?$H$-$O%9%l%C%IA4BN$rA*Br$7$^$9!#$=$&$G$J$1$l$P!"$=\e(B
+\e$B$l$O$=$N5-;v$@$1$rA*Br$7$^$9!#$b$7?tCM@\F,0z?t$rM?$($i$l$l$P$=$N%9%l%C%I\e(B
+\e$B$+5-;v$X$H@8$s$G$$$-!"$=$l$rA*Br$7$^$9!#\e(B(\e$B9T?t$OIaDL$O35N,A*Br9T$N:G=i$K\e(B
+\e$BI=<($5$l$F$$$^$9!#\e(B)
+
+@item SPACE
+@kindex SPACE (\e$BA*Br\e(B)
+@findex gnus-pick-next-page
+\e$B35N,%P%C%U%!$r0l%Z!<%8<!$K%9%/%m!<%k$7$^$9\e(B (@code{gnus-pick-next-page})\e$B!#\e(B
+\e$B$b$7%P%C%U%!$N:G8e$G$"$l$P!"A*Br5-;v$rFI$_;O$a$^$9!#\e(B
+
+@item u
+@kindex u (\e$BA*Br\e(B)
+@findex gnus-pick-unmark-article-or-thread
+\e$B%9%l%C%I$+5-;v$rL$A*Br$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-pick-unmark-article-or-thread})\e$B!#JQ\e(B
+\e$B?t\e(B @code{gnus-thread-hide-subtree} \e$B$,\e(B true \e$B$G$"$l$P!"$3$N%-!<$O%9%l%C%I\e(B
+\e$B$N:G=i$G;H$o$l$l$P%9%l%C%I$rL$A*Br$K$7$^$9!#$=$&$G$J$$>l9g$O$=$l$O5-;v$@\e(B
+\e$B$1$rL$A*Br$K$7$^$9!#$=$N9T$K$"$k%9%l%C%I$+5-;v$rL$A*Br$K$9$k$?$a$K$3$N%-!<\e(B
+\e$B$K?tCM@\F,0z?t$rM?$($k;v$,$G$-$^$9!#\e(B
+
+@item RET
+@kindex RET (\e$BA*Br\e(B)
+@findex gnus-pick-start-reading
+@vindex gnus-pick-display-summary
+\e$BA*Br$5$l$?5-;v$rFI$_;O$a$^$9\e(B (@code{gnus-pick-start-reading})\e$B!#@\F,0z?t\e(B
+\e$B$rM?$($i$l$l$P!"$^$:$9$Y$F$NL$A*Br5-;v$K4{FI$N0u$rIU$1$^$9!#\e(B
+@code{gnus-pick-display-summary} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"35N,%P%C%U%!$O\e(B
+\e$BFI$s$G$$$k4V$bI=<($5$l$^$9!#\e(B
+@end table
+
+\e$BA4$F$NIaDL$N35N,%b!<%IL?Na$OA*Br%b!<%I\e(B (pick-mode)\e$B$G$b;HMQ2DG=$G$9$,!"\e(B
+@kbd{u} \e$B$ONc30$G$9!#$7$+$7!"F1$84X\e(B
+\e$B?t\e(B @code{gnus-summary-tick-article-forward} \e$B$K3d$jEv$F$i$l$F$$\e(B
+\e$B$k\e(B @kbd{!} \e$B$r;H$&;v$,$G$-$^$9!#\e(B
+
+\e$B$3$l$,NI$$9M$($@$H;W$&$N$G$"$l$P!"<!$N$h$&$K$9$k;v$,$G$-$^$9\e(B:
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'gnus-pick-mode)
+@end lisp
+
+@vindex gnus-pick-mode-hook
+@code{gnus-pick-minor-mode-hook} \e$B$O\e(B pick \e$B%^%$%J!<%b!<%I%P%C%U%!$G<B9T$5\e(B
+\e$B$l$^$9!#\e(B
+
+@vindex gnus-summary-pick-line-format
+pick \e$B%b!<%I$G$N35N,9T$NMM<0$OI8=`$NMM<0$H$O>/$70c$$$^$9!#$=$l$>$l$N9T$N\e(B
+\e$B:G=i$K9T?t$,I=<($5$l$^$9!#\e(BPick \e$B%b!<%I$N9T$NMM<0$OJQ\e(B
+\e$B?t\e(B @code{gnus-summary-pick-line-format} \e$B$G@)8f$5$l$^\e(B
+\e$B$9\e(B (@pxref{Formatting Variables})\e$B!#$3$l\e(B
+\e$B$O\e(B @code{gnus-summary-line-format} \e$B$HF1$8MM<0;XDj$r<u$1IU$1$^\e(B
+\e$B$9\e(B (@pxref{Summary Buffer Lines})\e$B!#\e(B
+
+@node Binary Groups
+@subsection \e$B%P%$%J%j!<%0%k!<%W\e(B
+@cindex binary groups
+
+@findex gnus-binary-mode
+@kindex M-x gnus-binary-mode
+\e$B$b$7B?$/$N;~4V$r%P%$%J%j!<%0%k!<%W\e(B (binary group) \e$B$G2a$4$7$F$$$k$N$J$i!"\e(B
+\e$B$$$D$b\e(B @kbd{X u}, @kbd{n}, @kbd{RET} \e$B$rC!$/$N$,7y$K$J$C$F$$$k$G$7$g$&!#\e(B
+@kbd{M-x gnus-binary-mode} \e$B$O5-;v$rIaDL$NJ}K!$GI=<($9$kBe$o$j$K!"IaDL\e(B
+\e$B$N\e(B gnus \e$B$N5-;vA*Br4X?t$r5-;v72$r\e(B uudecode \e$B$7$=$N7k2L$rI=<($9$k$h$&$KJQ99\e(B
+\e$B$9$k!"35N,%P%C%U%!$N$?$a$N%^%$%J!<%b!<%I$G$9!#\e(B
+
+@kindex g (\e$B%P%$%J%j!<\e(B)
+@findex gnus-binary-show-article
+\e$B<B:]$O!"$3$N%b!<%I$K$7$?$H$-$K!"8=<B$N5-;v$r8+$k$?$a$NM#0l$NL?Na\e(B
+\e$B$,\e(B @kbd{g} \e$B$G$9\e(B (@code{gnus-binary-show-article})\e$B!#\e(B
+
+@vindex gnus-binary-mode-hook
+@code{gnus-binary-mode-hook} \e$B$,%P%$%J%j!<%^%$%J!<%b!<%I%P%C%U%!$G8F$P$l\e(B
+\e$B$^$9!#\e(B
+
+@node Tree Display
+@section \e$BLZI=<(\e(B
+@cindex trees
+
+@vindex gnus-use-trees
+\e$B$b$7IaDL$N\e(B gnus \e$B$N35N,I=<($r9%$-$G$J$$$J$i$P!"\e(B
+@code{gnus-use-trees} \e$B$r\e(B @code{t} \e$B$K@_Dj$7$F$_$k$HNI$$$+$b$7$l$^$;$s!#$3\e(B
+\e$B$l$O\e(B (\e$B%G%#%U%)%k%H$G\e(B) \e$BDI2C$N\e(B @dfn{\e$BLZ%P%C%U%!\e(B} (tree buffer) \e$B$r:n@.$7$^$9!#\e(B
+\e$BLZ%P%C%U%!$G$O$9$Y$F$N35N,%b!<%IL?Na$r<B9T$9$k;v$,$G$-$^$9!#\e(B
+
+\e$B$b$A$m$s!"LZI=<($r%+%9%?%^%$%:$9$kJQ?t$,>/$7$"$j$^$9\e(B:
+
+@table @code
+@item gnus-tree-mode-hook
+@vindex gnus-tree-mode-hook
+\e$B$9$Y$F$NLZ%b!<%I%P%C%U%!$G<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-tree-mode-line-format
+@vindex gnus-tree-mode-line-format
+\e$BLZ%b!<%I%P%C%U%!$G$N%b!<%I9T$N$?$a$N%U%)!<%^%C%HJ8;zNs$G$9\e(B (@pxref{Mode
+Line Formatting})\e$B!#%G%#%U%)%k%H$O\e(B @samp{Gnus: %%b %S %Z} \e$B$G$9!#;HMQ2DG=\e(B
+\e$B$J;XDj$O\e(B @pxref{Summary Buffer Mode Line} \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@item gnus-selected-tree-face
+@vindex gnus-selected-tree-face
+\e$BLZ%P%C%U%!$GA*Br$5$l$?5-;v$r%O%$%i%$%H$9$k$?$a$K;H$o$l$k%U%'%$%9$G$9!#%G%#\e(B
+\e$B%U%)%k%H$G$O\e(B @code{modeline} \e$B$G$9!#\e(B
+
+@item gnus-tree-line-format
+@vindex gnus-tree-line-format
+\e$BLZ$N@a$N$?$a$N%U%)!<%^%C%HJ8;zNs$G$9!#$G$b$3$NL>A0$O>/$78m$C$?L>>N$G\e(B
+\e$B$9!=!=$=$l$O9T$G$O$J$/!"$?$@@a$rDj5A$9$k$@$1$G$9!#%G%#%U%)%k%H$NCM\e(B
+\e$B$O\e(B @samp{%(%[%3,3n%]%)} \e$B$G!"$=$l$OEj9F<T$NL>A0$N:G=i$N;0J8;z$rI=<($7$^$9!#\e(B
+\e$B$9$Y$F$N@a$,F1$8D9$5$G$"$k$N$O=EMW$G$9$N$G!"\e(B@samp{%4,4n} \e$B$N$h$&$J;XDj\e(B
+\e$B$r\e(B @emph{\e$B;H$o$J$1$l$P$J$i$J$$\e(B} \e$B$N$G$9!#\e(B
+
+\e$BM-8z$J;XDj$O\e(B:
+
+@table @samp
+@item n
+\e$BEj9F<T$NL>A0!#\e(B
+@item f
+@code{From} \e$BMs!#\e(B
+@item N
+\e$B5-;v$NHV9f!#\e(B
+@item [
+\e$B3+$-3g8L!#\e(B
+@item ]
+\e$BJD$83g8L!#\e(B
+@item s
+\e$BI=Bj!#\e(B
+@end table
+
+@xref{Formatting Variables}.
+
+\e$BI=<($K4XO"$7$?JQ?t$O\e(B:
+
+@table @code
+@item gnus-tree-brackets
+@vindex gnus-tree-brackets
+\e$B$3$l$O!XK\Ev$N!Y5-;v$H!X$^$P$i5-;v!Y$K0c$$$rIU$1$k$?$a$K;H$o$l$^$9!#MM<0\e(B
+\e$B$O\e(B @code{((@var{\e$BK\Ev$N3+\e(B} . @var{\e$BK\Ev$NJD\e(B}) (@var{\e$B$^$P$i3+\e(B} . @var{\e$B$^$P\e(B
+\e$B$iJD\e(B}) (@var{\e$B56$N3+\e(B} . @var{\e$B56$NJD\e(B}))} \e$B$H$J$C$F$$$F!"%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{((?[ . ?]) (?( . ?)) (?@{ . ?@}) (?< . ?>))} \e$B$G$9!#\e(B
+
+@item gnus-tree-parent-child-edges
+@vindex gnus-tree-parent-child-edges
+\e$B$3$l$O?F$N@a$r;R$K@\B3$9$k$?$a$K;H$o$l$kJ8;z$r4^$s$@%j%9%H$G$9!#%G%#%U%)\e(B
+\e$B%k%H$O\e(B @code{(?- ?\\ ?|)} \e$B$G$9!#\e(B
+@end table
+
+@item gnus-tree-minimize-window
+@vindex gnus-tree-minimize-winodw
+\e$B$b$7$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"B>$N\e(B gnus \e$B%&%#%s%I%&$,$b$C$H>l=j$r<h\e(B
+\e$B$l$k$h$&$K\e(B gnus \e$B$OLZ%P%C%U%!$r$G$-$k$@$1>.$5$/$7$^$9!#$b$7$3$NJQ?t$,?t;z\e(B
+\e$B$G$"$k$H!"LZ%P%C%U%!$O$=$N?t;z$h$jBg$-$/$J$k;v$O$"$j$^$;$s!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{t} \e$B$G$9!#%U%l!<%`$G$$$/$D$+$N%&%#%s%I%&$,2#$KJB$s$GI=<($5$l$F$$\e(B
+\e$B$F!"LZ%P%C%U%!$,$=$N$&$A$N0l$D$G$"$k>l9g!"LZ%&%#%s%I%&$r:G>.2=$9$k$3$H$O\e(B
+\e$B$=$NNY$KI=<($5$l$F$$$k$9$Y$F$N%&%#%s%I%&$NBg$-$5$rJQ99$9$k;v$KCm0U$7$F$/\e(B
+\e$B$@$5$$!#\e(B
+
+\e$B0J2<$N%U%C%/$rDI2C$7$F!"$$$D$G$bLZ%&%#%s%I%&$r:G>.2=$7$F$bNI$$$G$7$g$&!#\e(B
+
+@lisp
+(add-hook 'gnus-configure-windows-hook
+          'gnus-tree-perhaps-minimize)
+@end lisp
+
+@item gnus-generate-tree-function
+@vindex gnus-generate-tree-function
+@findex gnus-generate-horizontal-tree
+@findex gnus-generate-vertical-tree
+\e$B<B:]$K%9%l%C%I$NLZ$r:n@.$9$k4X?t$G$9!#Fs$D$N4{Dj5A$N;HMQ2DG=$J4X?t\e(B
+\e$B$O\e(B: @code{gnus-generate-horizontal-tree} \e$B$H\e(B @code{gnus-generate-vertical-tree} (\e$B$3\e(B
+\e$B$l$,%G%#%U%)%k%H$G$9\e(B) \e$B$G$9!#\e(B
+@end table
+
+\e$B?eJ?LZ%P%C%U%!\e(B (horizontal tree buffer) \e$B$NNc$G$9\e(B:
+
+@example
+@{***@}-(***)-[odd]-[Gun]
+     |      \[Jan]
+     |      \[odd]-[Eri]
+     |      \(***)-[Eri]
+     |            \[odd]-[Paa]
+     \[Bjo]
+     \[Gun]
+     \[Gun]-[Jor]
+@end example
+
+\e$BF1$8%9%l%C%I$,?bD>LZ%P%C%U%!\e(B (vertical tree buffer) \e$B$GI=<($5$l$?$b$N$G$9\e(B:
+
+@example
+@{***@}
+  |--------------------------\-----\-----\
+(***)                         [Bjo] [Gun] [Gun]
+  |--\-----\-----\                          |
+[odd] [Jan] [odd] (***)                   [Jor]
+  |           |     |--\
+[Gun]       [Eri] [Eri] [odd]
+                          |
+                        [Paa]
+@end example
+
+\e$B$b$7?eJ?LZ$r;H$C$F$$$k$N$J$i!"35N,%P%C%U%!$GLZ$rNY$j9g$o$;$GI=<($G$-$l$P\e(B
+\e$B4r$7$$$G$7$g$&!#<!$N$h$&$J$b$N$r%U%!%$%k\e(B @file{~/.gnus.el} \e$B$K2C$($k;v$,\e(B
+\e$B$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-use-trees t
+      gnus-generate-tree-function 'gnus-generate-horizontal-tree
+      gnus-tree-minimize-window nil)
+(gnus-add-configuration
+ '(article
+   (vertical 1.0
+             (horizontal 0.25
+                         (summary 0.75 point)
+                         (tree 1.0))
+             (article 1.0))))
+@end lisp
+
+@xref{Window Layout}.
+
+@node Mail Group Commands
+@section \e$B%a!<%k%0%k!<%WL?Na\e(B
+@cindex mail group commands
+
+\e$B$$$/$D$+$NL?Na$O%a!<%k%0%k!<%W$N$_$G0UL#$r;}$A$^$9!#$3$l$i$NL?Na$,8=:_$N\e(B
+\e$B%0%k!<%W$GM-8z$G$J$$$J$i!"$=$l$i$OBgA{$.$r$7$F$"$J$?$KCN$i$;$k$G$7$g$&!#\e(B
+
+\e$B$9$Y$F$N$3$l$i$NL?Na$O\e(B (\e$B4|8B:o=|$HJT=8L?Na$O=|$/\e(B) \e$B%W%m%;%9\e(B/\e$B@\F,0z?t$N=,\e(B
+\e$B47$r;H$$$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@table @kbd
+@item B e
+@kindex B e (\e$B35N,\e(B)
+@findex gnus-summary-expire-articles
+\e$B8=:_$N%0%k!<%W$N$9$Y$F$N4|8B:o=|2DG=$J5-;v$K$D$$$F!"4|8B:o=|$N=h\e(B
+\e$BM}\e(B (@code{gnus-summary-expire-articles}) \e$B$r9T$J$$$^$9!#$3$l$O!"$=$N%0%k!<\e(B
+\e$B%W$K$7$P$i$/B8:_$7$F$$$?4|8B@Z$l:o=|2DG=$J$9$Y$F$N5-;v$r>C5n$9$k$H$$$&$3\e(B
+\e$B$H$G$9!#\e(B(@pxref{Expiring Mail})\e$B!#\e(B
+
+@item B C-M-e
+@kindex B C-M-e (\e$B35N,\e(B)
+@findex gnus-summary-expire-articles-now
+\e$B%0%k!<%W$N$9$Y$F$N4|8B:o=|2DG=$J5-;v$r:o=|$7$^\e(B
+\e$B$9\e(B (@code{gnus-summay-expire-articles-now})\e$B!#$3$l$O8=:_$N%0%k!<%W$N3:Ev\e(B
+\e$B$9$k\e(B @strong{\e$BA4$F\e(B}\e$B$N4|8B:o=|5-;v$O1J1s$K6u$NBg$-$J\e(B @file{/dev/null} \e$B$X>C\e(B
+\e$B$(5n$k$H$$$&;v$G$9!#\e(B
+
+@item B DEL
+@kindex B DEL (\e$B35N,\e(B)
+@findex gnus-summary-delete-article
+@c @icon{gnus-summary-mail-delete}
+\e$B%a!<%k5-;v$r:o=|$7$^$9!#$3$l$O!X$"$J$?$N%G%#%9%/$+$i:#$+$i1J1s$K:o=|$7$F!"\e(B
+\e$BFsEY$HLa$i$J$$!Y$N!X:o=|!Y$G$9!#Cm0U$7$F;H$C$F$/$@$5\e(B
+\e$B$$\e(B (@code{gnus-summary-delete-article})\e$B!#\e(B
+
+@item B m
+@kindex B m (\e$B35N,\e(B)
+@cindex move mail
+@findex gnus-summary-move-article
+@vindex gnus-preserve-marks
+\e$B$"$k%a!<%k%0%k!<%W$+$iJL$N$H$3$m$X5-;v$r0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-move-article})\e$B!#\e(B@code{gnus-preserve-marks} \e$B$NCM\e(B
+\e$B$,\e(B @code{nil} \e$B$G$O$J$$$J$i$P\e(B (\e$B$3$l$,=i4|CM$G$9$,\e(B)\e$B!"%^!<%/$OJ]B8$5$l$^$9!#\e(B
+
+@item B c
+@kindex B c (\e$B35N,\e(B)
+@cindex copy mail
+@findex gnus-summary-copy-article
+@c @icon{gnus-summary-mail-copy}
+\e$B$"$k%0%k!<%W\e(B (\e$B%a!<%k%0%k!<%W$dB>$N$b$N\e(B) \e$B$+$i%a!<%k%0%k!<%W$K5-;v$rJ#@=$7\e(B
+\e$B$^$9\e(B (@code{gnus-summary-copy-article})\e$B!#\e(B@code{gnus-preserve-marks} \e$B$NCM\e(B
+\e$B$,\e(B @code{nil} \e$B$G$O$J$$$J$i$P\e(B (\e$B$3$l$,=i4|CM$G$9$,\e(B)\e$B!"%^!<%/$OJ]B8$5$l$^$9!#\e(B
+
+@item B B
+@kindex B B (\e$B35N,\e(B)
+@cindex crosspost mail
+@findex gnus-summary-crosspost-article
+\e$B8=:_$N5-;v$rB>$N%0%k!<%W$K%/%m%9%]%9%H$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-crosspost-article})\e$B!#$3$l$OB>$N%0%k!<%W5-;v$N?7$7\e(B
+\e$B$$J#@=$r:n@.$7!"5-;v$N\e(B Xref \e$BMs$bE,@Z$K99?7$5$l$^$9!#\e(B
+
+@item B i
+@kindex B i (\e$B35N,\e(B)
+@findex gnus-summary-import-article
+\e$BG$0U$N%U%!%$%k$r8=:_$N%a!<%k%0%k!<%W$K<h$j9~$_$^\e(B
+\e$B$9\e(B (@code{gnus-summary-import-article})\e$B!#$"$J$?$O%U%!%$%kL>$H!"\e(B
+@code{From} \e$BMs$H\e(B @code{Subject} \e$BMs$NF~NO$rB%$5$l$^$9!#\e(B
+
+@item B I
+@kindex B I (\e$B35N,\e(B)
+@findex gnus-summary-create-article
+\e$B6u$N5-;v$r8=:_$N%a!<%k%0%k!<%W$K:n$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-create-article})\e$B!#\e(B@code{From} \e$B%X%C%@!<\e(B
+\e$B$H\e(B @code{Subject} \e$B%X%C%@!<$NFbMF$r?R$M$i$l$^$9!#\e(B
+
+@item B r
+@kindex B r (\e$B35N,\e(B)
+@findex gnus-summary-respool-article
+@vindex gnus-summary-respool-default-method
+\e$B%a!<%k5-;v$r%9%W!<%k$7D>$7$^$9\e(B (@code{gnus-summary-move-article})\e$B!#\e(B
+@code{gnus-summary-respool-default-method} \e$B$,:F%9%W!<%k$9$k$H$-$N%G%#%U%)\e(B
+\e$B%k%H$NA*BrJ}K!$H$7$F;HMQ$5$l$^$9!#$3$NJQ?t$O%G%#%U%)%k%H$G\e(B @code{nil} \e$B$G!"\e(B
+\e$B$3$l$O8=:_$N%0%k!<%W$NA*BrJ}K!$,Be$o$j$K;H$o$l$k$H$$$&;v$G$9!#\e(B
+@code{gnus-preserve-marks} \e$B$NCM$,\e(B @code{nil} \e$B$G$O$J$$$J$i$P\e(B (\e$B$3$l$,=i4|\e(B
+\e$BCM$G$9$,\e(B)\e$B!"%^!<%/$OJ]B8$5$l$^$9!#\e(B
+
+@item B w
+@itemx e
+@kindex B w (\e$B35N,\e(B)
+@kindex e (\e$B35N,\e(B)
+@findex gnus-summary-edit-article
+@kindex C-c C-c (\e$B5-;v\e(B)
+@findex gnus-summary-edit-article-done
+\e$B8=:_$N5-;v$rJT=8$7$^$9\e(B (@code{gnus-summary-edit-article})\e$B!#JT=8$r=*N;$7\e(B
+\e$B$FJQ99$r1J1s$K$9$k$?$a\e(B
+\e$B$K\e(B @kbd{C-c C-c} (@code{gnus-summary-edit-article-done}) \e$B$rBG$A$^$9!#$b\e(B
+\e$B$7L?Na\e(B @kbd{C-c C-c} \e$B$K?tCM@\F,0z?t$rM?$($k$H!"\e(Bgnus \e$B$O5-;v$r:F%O%$%i%$%H\e(B
+\e$B$7$^$;$s!#\e(B
+
+@item B q
+@kindex B q (\e$B35N,\e(B)
+@findex gnus-summary-respool-query
+\e$B$b$75-;v$r:F%9%W!<%k$7$?$$$H$-$O!":F%9%W!<%k$r$9$kA0$K$I$N%0%k!<%W$K5-;v\e(B
+\e$B$,0\$k$+$K6=L#$,$"$k$G$7$g$&!#$3$NL?Na$G$=$l$,$o$+$j$^\e(B
+\e$B$9\e(B (@code{gnus-summary-respool-query})\e$B!#\e(B
+
+@item B t
+@kindex B t (\e$B35N,\e(B)
+@findex gnus-summary-respool-trace
+\e$BF1MM$K!"$3$NL?Na$O:FN/$a9~$_$r$9$k$H$-$K;H$o$l$?A4$F$NFC5iJ,3dJ}<0$r!"$b\e(B
+\e$B$7$=$l$,$"$l$PI=<($7$^$9\e(B (@code{gnus-summary-respool-trace})\e$B!#\e(B
+
+@item B p
+@kindex B p (\e$B35N,\e(B)
+@findex gnus-summary-article-posted-p
+\e$B0lIt$N?M$O$"$J$?$NEj9F$X$N%U%)%m!<%"%C%W$r$9$k$H$-$K!"\e(B``\e$B?F@Z$J\e(B'' \e$BJ#@=$r\e(B
+\e$BAw$k798~$,$"$j$^$9!#$3$l$i$OIaDL$O$=$3$K\e(B @code{Newsgroups} \e$BMs$,IU$$$F$$\e(B
+\e$B$k$N$G$9$,!"$$$D$b$=$&$G$"$k$H$O8B$j$^$;$s!#$3$NL?\e(B
+\e$BNa\e(B (@code{gnus-summary-article-posted-p}) \e$B$O8=:_$N5-;v$r$"$J$?$N%K%e!<%9\e(B
+\e$B%5!<%P!<$+$i\e(B (\e$B$H$$$&$h$j$O!"$`$7\e(B
+\e$B$m\e(B @code{gnus-refer-article-method} \e$B$d\e(B @code{gnus-select-method} \e$B$+\e(B
+\e$B$i\e(B) \e$B<hF@$7$h$&$H$7!"5-;v$rH/8+$G$-$?$+$I$&$+$rJs9p$7$^$9!#$=$l$,5-;v$rH/\e(B
+\e$B8+$7$J$+$C$?$H$7$F$b!"$=$l$O$H$K$+$/Ej9F$5$l$F$$$k$+$b$7$l$^$;$s!=!=%a!<\e(B
+\e$B%k$NEAC#$O%K%e!<%9$NEAC#$h$j$b$:$C$HB.$/!"%K%e!<%9$NJ#@=$,$^$@E~Ce$7$F$$\e(B
+\e$B$J$$$@$1$+$b$7$l$J$$$N$G$9!#\e(B
+
+@c @item K E
+@c @kindex K E (Summary)
+@c @findex gnus-article-encrypt-body
+@c @vindex gnus-article-encrypt-protocol
+@c Encrypt the body of an article (@code{gnus-article-encrypt-body}).
+@c The body is encrypted with the encryption protocol specified by the
+@c variable @code{gnus-article-encrypt-protocol}.
+@end table
+
+@vindex gnus-move-split-methods
+@cindex moving articles
+\e$B$b$7!"5,B'E*$K5-;v$r0\F0\e(B (\e$B$b$7$/$OJ#@=\e(B) \e$B$9$k$N$G$"$l$P!"\e(Bgnus \e$B$K5-;v$r$I\e(B
+\e$B$3$KF~$l$l$PNI$$$+Ds0F$5$;$?$$$H;W$&$G$7$g$&!#\e(B
+@code{gnus-move-split-methods} \e$B$O\e(B @code{gnus-split-methods} \e$B$HF1$89=J8$r\e(B
+\e$B;H$&JQ?t$G$9\e(B (@pxref{Saving Articles})\e$B!#$"$J$?$,BEEv$@$H;W$&$h$&$JDs0F$r\e(B
+\e$B$9$k$h$&$K$=$NJQ?t$r%+%9%?%^%$%:$9$k;v$,$G$-$^$9!#\e(B
+(@code{gnus-split-methods} \e$B$,%U%!%$%kL>$r;H$&$N$KBP$7\e(B
+\e$B$F\e(B @code{gnus-move-split-methods} \e$B$O%0%k!<%WL>$r;H$&$3$H$KCm0U$7$F2<$5\e(B
+\e$B$$!#\e(B)
+
+@lisp
+(setq gnus-move-split-methods
+      '(("^From:.*Lars Magne" "nnml:junk")
+        ("^Subject:.*gnus" "nnfolder:important")
+        (".*" "nnml:misc")))
+@end lisp
+
+@node Various Summary Stuff
+@section \e$B$$$m$$$m$J35N,$NJ*7o\e(B
+
+@menu
+* Summary Group Information::   \e$B>pJs;X8~$NL?Na\e(B
+* Searching for Articles::      \e$BJ#?t5-;vL?Na\e(B
+* Summary Generation Commands::
+* Really Various Summary Commands::  \e$B$"$N$d$C$+$$$JB>$KE,9g$7$J$$L?Na\e(B
+@end menu
+
+@table @code
+@vindex gnus-summary-display-while-building
+@item gnus-summary-display-while-building
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"9=C[Cf$N35N,%P%C%U%!$r99?7$7$J$,$iI=<($7$^$9!#\e(B
+@code{t} \e$B$@$C$?>l9g$O!"9T$,A^F~$5$l$kEY$KKh2s%P%C%U%!$r99?7$7$^$9!#CM$,\e(B
+\e$B@0?t\e(B @var{n} \e$B$G$"$C$?>l9g$O!"\e(B@var{n} \e$B9TKh$KI=<($r99?7$7$^$9!#%G%#%U%)%k\e(B
+\e$B%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@vindex gnus-summary-display-arrow
+@item gnus-summary-display-arrow
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"8=:_$N5-;v$r;X$7<($9$?$a$K%U%j%s%8$KLp0u$rI=<($7\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-summary-mode-hook
+@item gnus-summary-mode-hook
+\e$B35N,%b!<%I%P%C%U%!$r:n@.$9$k$H$-$K$3$N%U%C%/$,8F$P$l$^$9!#\e(B
+
+@vindex gnus-summary-generate-hook
+@item gnus-summary-generate-hook
+\e$B$3$l$O%9%l%C%I:n@.$H35N,%P%C%U%!:n@.$NA0$K<B9T$9$k:G8e$N$b$N$H$7$F8F$P$l\e(B
+\e$B$^$9!#$3$l$O%K%e!<%9%0%k!<%W$N;}$C$F$$$k%G!<%?$K4p$E$$$F%9%l%C%I$NJQ?t$r\e(B
+\e$B%+%9%?%^%$%:$9$k$?$a$KHs>o$KJXMx$G$9!#$3$N%U%C%/$O$[$H$s$I$N35N,%P%C%U%!\e(B
+\e$BJQ?t$,@_Dj$5$l$?8e$K8F$P$l$^$9!#\e(B
+
+@vindex gnus-summary-prepare-hook
+@item gnus-summary-prepare-hook
+\e$B$=$l$O35N,%P%C%U%!$,:n@.$5$l$?8e$K8F$P$l$^$9!#Nc$($P!"$=$l$O2?$+B>$N<Y0-\e(B
+\e$B$JJ}K!$G9T$r%O%$%i%$%H$7$?$j!"%P%C%U%!$N8+$(J}$r=$@5$7$?$j$9$k$N$K;H$C$?\e(B
+\e$B$j$9$k$+$bCN$l$^$;$s!#\e(B
+
+@vindex gnus-summary-prepared-hooi
+@item gnus-summary-prepared-hook
+\e$B35N,%P%C%U%!$,:n@.$5$l$?8e$G0lHV:G8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@vindex gnus-summary-ignore-duplicates
+@item gnus-summary-ignore-duplicates
+Gnus \e$B$,F1$8\e(B @code{Message-ID} \e$B$r;}$DFs$D$N5-;v$rH/8+$7$?$H$-$O!"2?$+;W$$\e(B
+\e$B@Z$C$?;v$r$7$J$1$l$P$J$j$^$;$s!#JL$N5-;v$,F1$8\e(B @code{Message-ID} \e$B$r;}$D\e(B
+\e$B;v$O5v$5$l$F$$$^$;$s$,!"$=$l$O2?$i$+$N=P=j$+$i%a!<%k$rFI$s$G$$$k$H$-$K5/\e(B
+\e$B$3$k$+$b$7$l$^$;$s!#\e(BGnus \e$B$O$3$NJQ?t$K$h$C$F2?$,5/$3$k$+$r%+%9%?%^%$%:$G\e(B
+\e$B$-$k$h$&$K$J$C$F$$$^$9!#$b$7$=$l$,\e(B @code{nil} (\e$B$3$l$,%G%#%U%)%k%H$G\e(B
+\e$B$9\e(B) \e$B$G$"$l$P!"\e(Bgnus \e$B$O\e(B @code{Message-ID} \e$B$rIU$1BX$($F\e(B (\e$BI=<($N$?$a$@$1\e(B
+\e$B$K\e(B) \e$B5-;v$rB>$N5-;v$HF1$8$h$&$KI=<($7$^$9!#$3$NJQ?t$,\e(B @code{t} \e$B$G$"$k$H!"\e(B
+\e$B$=$l$O5-;v$rI=<($7$^$;$s\e(B---\e$B:G=i$+$iB8:_$7$J$+$C$?$+$N$h$&$K!#\e(B
+
+@vindex gnus-alter-articles-to-read-function
+@item gnus-alter-articles-to-read-function
+\e$B$3$NJQ?t$K@_Dj$7$?4X?t$G!"A*Br$9$k5-;v$N%j%9%H$rJQ99$9$k$3$H$,$G$-$^$9!#\e(B
+\e$B4X?t$OFs$D$N0z?t\e(B (\e$B%0%k!<%WL>$HA*Br$9$k5-;v$N%j%9%H\e(B) \e$B$r<u$1IU$1$^$9!#\e(B
+
+\e$BNc$($P0J2<$N4X?t$O!"%-%c%C%7%e5-;v$N%j%9%H$r$"$k%0%k!<%W$N%j%9%H$@$1$KDI\e(B
+\e$B2C$7$^$9!#\e(B
+
+@lisp
+(defun my-add-cached-articles (group articles)
+  (if (string= group "some.group")
+      (append gnus-newsgroup-cached articles)
+    articles))
+@end lisp
+
+@vindex gnus-newsgroup-variables
+@item gnus-newsgroup-variables
+\e$B%K%e!<%9%0%k!<%W\e(B (\e$B$=$N35N,%P%C%U%!$N\e(B) \e$B$N%m!<%+%kJQ?t!"$^$?$OJQ?t$H$=$l$i\e(B
+\e$B$N%G%#%U%)%k%HCM\e(B (\e$B%G%#%U%)%k%HCM$,\e(B @code{nil} \e$B$G$J$$>l9g\e(B) \e$B$N\e(B cons \e$B%;%k$N\e(B
+\e$B%j%9%H$G!"$=$N35N,%P%C%U%!$,3h$-$F$$$k4V$O%0%m!<%P%kJQ?t$K$J$j$^$9!#$3$l\e(B
+\e$B$i$NJQ?t$O!"JL$N%P%C%U%!$G$=$l$i\e(B (\e$B%0%k!<%W%Q%i%a!<%?\e(B) \e$B$N8z2L$,JQ99$5$l$F\e(B
+\e$B$$$F$b!"\e(B(\e$B$=$N%0%k!<%W$N\e(B) \e$B%0%k!<%W%Q%i%a!<%?$NJQ?t$r@_Dj$9$k$?$a$K;H$&$3\e(B
+\e$B$H$,$G$-$^$9!#Nc$G$9\e(B:
+
+@lisp
+(setq gnus-newsgroup-variables
+     '(message-use-followup-to
+       (gnus-visible-headers .
+         "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^To:")))
+@end lisp
+@end table
+
+@node Summary Group Information
+@subsection \e$B35N,%0%k!<%W>pJs\e(B
+
+@table @kbd
+@item H f
+@kindex H f (\e$B35N,\e(B)
+@findex gnus-summary-fetch-faq
+@vindex gnus-group-faq-directory
+\e$B8=:_$N%0%k!<%W$N\e(B @acronym{FAQ} (frequently asked questions (\e$BIQHK$K$5$l$k\e(B
+\e$B<ALd\e(B) \e$B$N%j%9%H\e(B) \e$B$r<hF@$7$h$&$H$7$^$9\e(B (@code{gnus-summary-fetch-faq})\e$B!#\e(B
+gnus \e$B$OIaDL$O1s3V%^%7%s$N%G%#%l%/%H%j$G$"\e(B
+\e$B$k\e(B @code{gnus-group-faq-directory} \e$B$+$i\e(B @acronym{FAQ} \e$B$r<hF@$7$h$&$H$7$^\e(B
+\e$B$9!#$3$NJQ?t$O%G%#%l%/%H%j!<$N%j%9%H$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"$3$N\e(B
+\e$BL?Na$K@\F,0z?t$rM?$($k;v$G$$$m$$$m$J%5%$%H\e(B (site) \e$B$+$iA*$V;v$,$G$-$^$9!#\e(B
+\e$B$*$=$i$/\e(B @code{ange-ftp} \e$B$b$7$/$O\e(B @code{efs} \e$B$,%U%!%$%k$N<hF@$K;H$o$l$k\e(B
+\e$B$G$7$g$&!#\e(B
+
+@item H d
+@kindex H d (\e$B35N,\e(B)
+@findex gnus-summary-describe-group
+\e$B8=:_$N%0%k!<%W$K4X$9$kC;$$5-=R$rM?$($^\e(B
+\e$B$9\e(B (@code{gnus-summary-describe-group})\e$B!#@\F,0z?t$,M?$($i$l$k$H!"%5!<%P!<\e(B
+\e$B$+$i6/@)E*$K5-=R$N:FFI$_9~$_$r$7$^$9!#\e(B
+
+@item H h
+@kindex H h (\e$B35N,\e(B)
+@findex gnus-summary-describe-briefly
+\e$B:G=EMW35N,BG80$NHs>o$KC;$$5-=R$rM?$($^\e(B
+\e$B$9\e(B (@code{gnus-summary-describe-briefly})\e$B!#\e(B
+
+@item H i
+@kindex H i (\e$B35N,\e(B)
+@findex gnus-info-find-node
+Gnus \e$B$N\e(B info \e$B$N@a\e(B (node) \e$B$K0\F0$7$^$9\e(B (@code{gnus-info-find-node})\e$B!#\e(B
+@end table
+
+@node Searching for Articles
+@subsection \e$B5-;v$rC5$9\e(B
+
+@table @kbd
+@item M-s
+@kindex M-s (\e$B35N,\e(B)
+@findex gnus-summary-search-article-forward
+\e$BD>8e$K$"$kA4$F$N\e(B (\e$B@8$N\e(B) \e$B5-;v$r@55,I=8=$G8!:w$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-search-article-forward})\e$B!#\e(B
+
+@item M-r
+@kindex M-r (\e$B35N,\e(B)
+@findex gnus-summary-search-article-backward
+\e$BA0$K$"$kA4$F$N\e(B (\e$B@8$N\e(B) \e$B5-;v$r@55,I=8=$G8!:w$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-search-article-backward})\e$B!#\e(B
+
+@item &
+@kindex & (\e$B35N,\e(B)
+@findex gnus-summary-execute-command
+\e$B$3$NL?Na$O$"$J$?$K%X%C%@!<ItJ,$H$=$NItJ,$K9gCW$9$k@55,I=8=!"9gCW$7$?>l9g\e(B
+\e$B$K<B9T$5$l$kL?Na$NF~NO$rB%?J$7$^$9\e(B (@code{gnus-summary-execute-command})\e$B!#\e(B
+\e$B$b$7%X%C%@!<$,6uJ8;zNs$J$i$P!"5-;vA4BN$rC5$7$^$9!#$b$7@\F,0z?t$rM?$($i$l\e(B
+\e$B$l$P!"Be$o$j$K8e$m8~$-$KC5$7$^$9!#\e(B
+
+\e$BNc$($P\e(B @kbd{& RET \e$BJ8;zNs\e(B RET #} \e$B$O!"%X%C%@!<$+K\J8$K\e(B @samp{\e$BJ8;zNs\e(B} \e$B$r;}\e(B
+\e$B$D$9$Y$F$N5-;v$K%W%m%;%90u$rIU$1$^$9!#\e(B
+
+@item M-&
+@kindex M-& (\e$B35N,\e(B)
+@findex gnus-summary-universal-argument
+\e$B%W%m%;%90u$K$h$C$F0uIU$1$i$l$?A4$F$N5-;v$NA`:n$r<B9T$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-universal-argument})\e$B!#\e(B
+@end table
+
+@node Summary Generation Commands
+@subsection \e$B35N,@8@.L?Na\e(B
+
+@table @kbd
+@item Y g
+@kindex Y g (\e$B35N,\e(B)
+@findex gnus-summary-prepare
+\e$B8=:_$N35N,%P%C%U%!$r:F:n@.$7$^$9\e(B (@code{gnus-summary-prepare})\e$B!#\e(B
+
+@item Y c
+@kindex Y c (\e$B35N,\e(B)
+@findex gnus-summary-insert-cached-articles
+\e$B$9$Y$F$N\e(B (\e$B8=:_$N%0%k!<%W$K\e(B) \e$B%-%c%C%7%e$5$l$?5-;v$r35N,%P%C%U%!$KA^F~$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-insert-cached-articles})\e$B!#\e(B
+
+@item Y d
+@kindex Y d (\e$B35N,\e(B)
+@findex gnus-summary-insert-dormant-articles
+\e$B$9$Y$F$N\e(B (\e$B8=:_$N%0%k!<%W$N\e(B) \e$BJ]N15-;v$r35N,%P%C%U%!$KA^F~$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-insert-dormant-articles})\e$B!#\e(B
+@end table
+
+@node Really Various Summary Commands
+@subsection \e$BK\Ev$K$$$m$$$m$J35N,L?Na\e(B
+
+@table @kbd
+@item A D
+@itemx C-d
+@kindex C-d (\e$B35N,\e(B)
+@kindex A D (\e$B35N,\e(B)
+@findex gnus-summary-enter-digest-group
+\e$B$b$78=:_$N%0%k!<%W$,B>$N5-;v$N=8$^$j$G$"$k$J$i$P\e(B (\e$BNc$($P!"E&MW\e(B (digest))\e$B!"\e(B
+\e$B$=$N$h$&$J5-;v$G$G$-$F$$$k%0%k!<%W$KF~$k$?$a$K$3$NL?Na$r;H$&$+$b$7$l$^$;\e(B
+\e$B$s\e(B(@code{gnus-summary-enter-digest-group})\e$B!#\e(BGnus \e$B$O$3$NL?Na$K@\F,0z?t$r\e(B
+\e$BM?$($J$$8B$j!"$I$N$h$&$J7?$N5-;v$,8=:_I=<($5$l$F$$$k$+$r?dB,$7$h$&$H$7!"\e(B
+\e$B$=$l$O6/@)E*$K!XE&MW!Y$H$$$&2r<a$K$J$j$^$9!#4pK\E*$K!"B>$NMM<0$+$i$J$kB>\e(B
+\e$B$N%a%C%;!<%8$N=89g$G$"$C$?$H$-$O!"\e(B@kbd{C-d} \e$B$H$9$k$3$H$K$h$j$b$C$HJXMx$J\e(B
+\e$BJ}K!$G$=$l$i$N%a%C%;!<%8$rFI$`;v$,$G$-$k$h$&$K$J$j$^$9!#\e(B
+
+@item C-M-d
+@kindex C-M-d (\e$B35N,\e(B)
+@findex gnus-summary-read-document
+\e$B$3$NL?Na$O>e$N$b$N$KHs>o$K;w$F$$$^$9$,!"$$$/$D$+$NJ8=q$r0l$D$NBg!<$-$$%0\e(B
+\e$B%k!<%W$K=8$a$^$9\e(B (@code{gnus-summary-read-read-document})\e$B!#$=$l$O$$$/$D\e(B
+\e$B$+$N\e(B @code{nndoc} \e$B%0%k!<%W$r$=$l$>$l$NJ8=q$N$?$a$K3+$-!"$=$l$+$i$3$l$i\e(B
+\e$B$N\e(B @code{nndoc} \e$B%0%k!<%W$N>e$K\e(B @code{nnvirtual} \e$B%0%k!<%W$r3+$/;v$K$h$C$F\e(B
+\e$B$3$N;v$r2DG=$K$7$F$$$^$9!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$rM}2r$7$^\e(B
+\e$B$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item C-t
+@kindex C-t (\e$B35N,\e(B)
+@findex gnus-summary-togle-truncation
+\e$B35N,9T$N@ZCG$r@Z$jBX$($^$9\e(B (@code{gnus-summary-toggle-truncation})\e$B!#$3$l\e(B
+\e$B$O$*$=$i$/35N,%P%C%U%!$N9TCf1{I=<(4X?t$r:.Mp$5$;$^$9$N$G!"5-;v$rFI$s$G$$\e(B
+\e$B$k4V$K@ZCG$r@Z$C$F$$$k$N$ONI$$9M$($G$O$J$$$G$7$g$&!#\e(B
+
+@item =
+@kindex = (\e$B35N,\e(B)
+@findex gnus-summary-expand-window
+\e$B35N,%P%C%U%!$N%&%#%s%I%&$r3HBg$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-expand-window})\e$B!#@\F,0z?t$rM?$($i$l$l$P!"\e(B
+@code{\e$B5-;v\e(B} \e$B%&%#%s%I%&$r3HBg$7$^$9!#\e(B
+
+@item C-M-e
+@kindex C-M-e (\e$B35N,\e(B)
+@findex gnus-summary-edit-parameters
+\e$B8=:_$N%0%k!<%W$N%0%k!<%W$NG^2pJQ?t\e(B (parameter) (@pxref{Group
+Parameters}) \e$B$rJT=8$7$^$9\e(B (@code{gnus-summary-edit-parameters})\e$B!#\e(B
+
+@item C-M-a
+@kindex C-M-a (\e$B35N,\e(B)
+@findex gnus-summary-customize-parameters
+\e$B8=:_$N%0%k!<%W$N%0%k!<%W%Q%i%a!<%?\e(B (@pxref{Group Parameters}) \e$B$r%+%9%?%^\e(B
+\e$B%$%:$7$^$9\e(B (@code{gnus-summary-customize-parameters})\e$B!#\e(B
+@end table
+
+@node Exiting the Summary Buffer
+@section \e$B35N,%P%C%U%!$rH4$1$k\e(B
+@cindex summary exit
+@cindex exiting groups
+
+\e$BIaDL$O35N,%P%C%U%!$+$iH4$1$k$H!"%0%k!<%W$NA4$F$N>pJs$r99?7$7$F%0%k!<%W%P%C\e(B
+\e$B%U%!$KLa$j$^$9!#\e(B
+
+@table @kbd
+@item Z Z
+@itemx Z Q
+@itemx q
+@kindex Z Z (\e$B35N,\e(B)
+@kindex Z Q (\e$B35N,\e(B)
+@findex q (\e$B35N,\e(B)
+@findex gnus-summary-exit
+@vindex gnus-summary-exit-hook
+@vindex gnus-summary-prepare-exit-hook
+@vindex gnus-group-no-more-groups-hook
+@c @icon{gnus-summary-exit}
+\e$B8=:_$N%0%k!<%W$r=P$F!"%0%k!<%W$NA4$F$N>pJs$r99?7$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-exit})\e$B!#H4$1=P$k$?$a$N$?$$$F$$$N;v$r$9$kA0\e(B
+\e$B$K\e(B @code{gnus-summary-prepare-exit-hook} \e$B$,8F$P$l!"$=$l$O%G%#%U%)%k%H\e(B
+\e$B$G\e(B @code{gnus-summary-expire-articles} \e$B$r8F$S$^$9!#H4$1=P$k2aDx$rDI$($?\e(B
+\e$B8e$K\e(B @code{gnus-summary-exit-hook} \e$B$,8F$P$l$^$9!#\e(B(\e$BL$FI$N\e(B) \e$B%0%k!<%W$,;D$C\e(B
+\e$B$F$$$J$$$H$-$K%0%k!<%W%b!<%I$KLa$k$H$-\e(B
+\e$B$K\e(B @code{gnus-group-no-more-groups-hook} \e$B$,<B9T$5$l$^$9!#\e(B
+
+@item Z E
+@itemx Q
+@kindex Z E (\e$B35N,\e(B)
+@findex Q (\e$B35N,\e(B)
+@findex gnus-summary-exit-no-update
+\e$B%0%k!<%W$N$I$N>pJs$b99?7$;$:$K8=:_$N%0%k!<%W$rH4$1=P$^\e(B
+\e$B$9\e(B (@code{gnus-summary-exit-no-update})\e$B!#\e(B
+
+@item Z c
+@itemx c
+@kindex Z c (\e$B35N,\e(B)
+@kindex c (\e$B35N,\e(B)
+@findex gnus-summary-catchup-and-exit
+@c @icon{gnus-summary-catchup-and-exit}
+\e$B%0%k!<%W$NA4$F$NJ]N1$G$J$$5-;v\e(B (unticked article) \e$B$K4{FI$N0u$rIU$1$F!"$=\e(B
+\e$B$l$+$iH4$1$^$9\e(B (@code{gnus-summary-catchup-and-exit})\e$B!#\e(B
+
+@item Z C
+@kindex Z C (\e$B35N,\e(B)
+@findex gnus-summary-catchup-all-and-exit
+\e$BJ]N15-;v$b4^$a$F!"A4$F$N5-;v$K4{FI$N0u$rIU$1$F!"$=$l$+$iH4$1$^\e(B
+\e$B$9\e(B (@code{gnus-summary-catchup-all-and-exit})\e$B!#\e(B
+
+@item Z n
+@kindex Z n (\e$B35N,\e(B)
+@findex gnus-summary-catchup-and-goto-next-group
+\e$BA4$F$N5-;v$K4{FI$N0u$rIU$1$F<!$N%0%k!<%W$X0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-catchup-and-goto-next-group})\e$B!#\e(B
+
+@item Z R
+@itemx C-x C-s
+@kindex Z R (\e$B35N,\e(B)
+@kindex C-x C-s (\e$B35N,\e(B)
+@findex gnus-summary-reselect-current-group
+\e$B8=:_$N%0%k!<%W$r=P$F!"$=$l$+$iF~$jD>$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-reselect-current-group})\e$B!#$b$7@\F,0z?t$rM?$($i$l\e(B
+\e$B$l$P!"4{FI$HL$FI$NN>J}$NA4$F$N5-;v$rA*Br$7$^$9!#\e(B
+
+@item Z G
+@itemx M-g
+@kindex Z G (\e$B35N,\e(B)
+@kindex M-g (\e$B35N,\e(B)
+@findex gnus-summary-rescan-group
+@c @icon{gnus-summary-mail-get}
+\e$B%0%k!<%W$rH4$1!"%0%k!<%W$N?7$7$$5-;v$rD4$Y!"%0%k!<%W$rA*Br$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-rescan-group})\e$B!#$b$7@\F,0z?t$rM?$($i$l$l$P!"4{FI\e(B
+\e$B$HL$FI$NN>J}$NA4$F$N5-;v$rA*Br$7$^$9!#\e(B
+
+@item Z N
+@kindex Z N (\e$B35N,\e(B)
+@findex gnus-summary-next-group
+\e$B%0%k!<%W$rH4$1$F!"<!$N%0%k!<%W$X0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-next-group})\e$B!#\e(B
+
+@item Z P
+@kindex Z P (\e$B35N,\e(B)
+@findex gnus-summary-prev-group
+\e$B%0%k!<%W$rH4$1$F!"A0$N%0%k!<%W$X0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-summary-prev-group})\e$B!#\e(B
+
+@item Z s
+@kindex Z s (\e$B35N,\e(B)
+@findex gnus-summary-save-newsrc
+\e$B8=:_$N4{FI\e(B/\e$B0uIU$-5-;v$N?t$r%I%j%V%k%P%C%U%!\e(B (dribble buffer) \e$B$KJ]B8$7!"\e(B
+\e$B$=$l$+$i%I%j%V%k%P%C%U%!$rJ]B8$7$^$9\e(B (@code{gnus-summary-save-newsrc})\e$B!#\e(B
+\e$B$b$7@\F,0z?t$rM?$($i$l$l$P!"%U%!%$%k\e(B @file{.newsrc} \e$B$bJ]B8$7$^$9!#$3$NL?\e(B
+\e$BNa$r;H$&$H!"99?7$J$7$GH4$1=P$k;v\e(B (@kbd{Q} \e$BL?Na\e(B) \e$B$O0UL#$,L5$/$J$j$^$9!#\e(B
+@end table
+
+@vindex gnus-exit-group-hook
+\e$B8=:_$N%0%k!<%W$r!"%0%k!<%W$NA4$F$N>pJs$r99?7$7$FH4$1$k$H$-\e(B
+\e$B$K\e(B @code{gnus-exit-group-hook} \e$B$,8F$P$l$^$9!#\e(B
+@kbd{Q} \e$BL?Na\e(B (@code{gnus-summary-exit-no-update}) \e$B$G$O!"$3$N%U%C%/$r8F$S\e(B
+\e$B$^$;$s!#\e(B
+
+@findex gnus-summary-wake-up-the-dead
+@findex gnus-dead-summary-mode
+@vindex gnus-kill-summary-on-exit
+\e$B$"$J$?$K%0%k!<%W$rH4$1$F!"$=$l$+$i9M$($rJQ$($kJJ$,$"$k$N$G$"$l$P!"\e(B
+@code{gnus-kill-summary-on-exit} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$N$,NI$$$+$b$7\e(B
+\e$B$l$^$;$s!#$b$7$=$&$9$l$P!"\e(Bgnus \e$B$O$=$l$+$iH4$1=P$k$H$-$K35N,%P%C%U%!$r:o\e(B
+\e$B=|$7$^$;$s!#\e(B(\e$B2?$H$$$&6C$-\e(B!) \e$B$=$NBe$o$j$K!"$=$l$O%P%C%U%!$NL>A0\e(B
+\e$B$r\e(B @samp{*Dead Summary ... *} \e$B$N$h$&$J$b$N$KJQ99$7!"\e(B
+@code{gnus-dead-summary-mode} \e$B$H8F$P$l$k%^%$%J!<%b!<%I$rF3F~$7$^$9!#:#$d!"\e(B
+\e$B$=$N%P%C%U%!$K@Z$jBX$($l$P!"A4$F$N%-!<$,4X\e(B
+\e$B?t\e(B @code{gnus-summary-wake-up-the-dead} \e$B$K3d$jEv$F$i$l$F$$$k$3$H$K5$IU$/\e(B
+\e$B$G$7$g$&!#;`$s$@35N,%P%C%U%!\e(B (dead summary buffer) \e$B$G$I$l$+$N%-!<$rC!$/\e(B
+\e$B;v$H!"@8$-$?IaDL$N35N,%P%C%U%!$K$J$k$G$7$g$&!#\e(B
+
+\e$B;`$s$@35N,%P%C%U%!$OF1;~$K0l$D$7$+B8:_$9$k;v$O$G$-$^$;$s!#\e(B
+
+@vindex gnus-use-cross-reference
+\e$B35N,%P%C%U%!$rH4$1=P$k$H!"8=:_$N%0%k!<%W$N%G!<%?$O99?7$5$l$^$9\e(B (\e$B$I$N5-;v\e(B
+\e$B$rFI$s$G!"$I$N5-;v$KJVEz$7$?$+!"$J$I$J$I!#\e(B) \e$B$b$7JQ\e(B
+\e$B?t\e(B @code{gnus-use-cross-reference} \e$B$,\e(B @code{t} \e$B$G$"$k$H\e(B (\e$B$=$l$,%G%#%U%)\e(B
+\e$B%k%H$G$9\e(B)\e$B!"$=$N%0%k!<%W$KAj8_;2>H$5$l$?\e(B (cross referenced) \e$B5-;v$O4{FI$N\e(B
+\e$B0u$,IU$-!"$=$l$,Aj8_Ej9F\e(B (cross post) \e$B$5$l$?B>$N9XFI$7$F$$$k%0%k!<%W$G$b\e(B
+\e$B4{FI$N0u$,IU$-$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$b\e(B @code{t} \e$B$G$J$1$l$P!"5-;v\e(B
+\e$B$O9XFI$HL$9XFI$NN>J}$N%0%k!<%W$G4{FI$N0u$,IU$-$^\e(B
+\e$B$9\e(B (@pxref{Crosspost Handling})\e$B!#\e(B
+
+@node Crosspost Handling
+@section \e$BAj8_Ej9F$N07$$\e(B
+
+@cindex velveeta
+@cindex spamming
+\e$BAj8_Ej9F\e(B (cross post) \e$B$5$l$?5-;v$K4{FI$N0u$rIU$1$k;v$O!"F1$85-;v$rFs2s0J\e(B
+\e$B>eFI$^$J$$$G$9$`$H$$$&;v$rJ]>Z$7$^$9!#$b$A$m$s!"$@$l$+$,$=$l$r$$$/$D$+$N\e(B
+\e$B%0%k!<%W$KJL!9$KEj9F$7$J$$8B$j$O!#F1$85-;v$r$$$/$D$+$N%0%k!<%W$KEj9F$9$k\e(B
+\e$B;v\e(B (\e$BAj8_Ej9F$G$J$/$F\e(B) \e$B$O\e(B @dfn{spamming} \e$B$H8F$P$l!"$"$J$?$O$=$N$h$&$JA~$`\e(B
+\e$B$Y$-HH:a$r9T$J$&$b$N$KBP$7$F!"K!N'$K$h$C$FIT2w$J5-;v$rAw$k$3$H$,5AL3$E$1\e(B
+\e$B$i$l$F$$$^$9!#\e(Bspam \e$B$rA*JL$9$k$?$a$K$O!"\e(BNoCeM \e$B$N<h07$r;n$7$F$_$kI,MW$,$"\e(B
+\e$B$k$+$b$7$l$^$;$s\e(B (@pxref{NoCeM})\e$B!#\e(B
+
+\e$B3P$($F$/$@$5$$\e(B: \e$BAj8_Ej9F$O9=$$$^$;$s$,!"F1$85-;v$rJL!9$K$$$/$D$+$N%0%k!<\e(B
+\e$B%W$KEj9F$9$k$N$O5v$5$l$^$;$s!#BgNL$NAj8_Ej9F\e(B (@dfn{velveeta}) \e$B$O$I$&$7$F\e(B
+\e$B$bHr$1$i$l$k$Y$-$G!"2a>jAj8_Ej9F$KBP$7$FITK~$r8@$&$?$a$KL?\e(B
+\e$BNa\e(B @code{gnus-summary-mail-crosspost-complaint} \e$B$r;H$&$3$H$5$($G$-$^$9!#\e(B
+
+@cindex cross-posting
+@cindex Xref
+@cindex @acronym{NOV}
+\e$BAj8_Ej9F$r\e(B gnus \e$B$,@5$7$/07$($J$$$h$&$K$J$k860x$N0l$D$O!"\e(B@acronym{NOV} \e$B9T\e(B
+\e$B$K\e(B @code{Xref} \e$BMs$r4^$^$J$$!"\e(B@sc{xover} (\e$B$3$l$OHs>o$KNI$$$G$9!"$H$$$&$N\e(B
+\e$B$O$=$l$OB.EY$r$H$F$bB.$/$9$k$+$i$G$9\e(B) \e$B$N;HMQ2DG=$J\e(B @acronym{NNTP} \e$B%5!<%P!<\e(B
+\e$B$r;H$C$F$$$k$3$H$G$9!#$3$l$O320-$J$N$G$9$,!"$"$!!"Ha$7$$$+$J!"Hs>o$KNI$/\e(B
+\e$B$"$k;v$G$9!#\e(BGnus \e$B$O$"$J$?$,FI$s$@A4$F$N5-;v$K\e(B @code{Xref} \e$B9T$rEPO?$9$k;v\e(B
+\e$B$G!"@5$7$$;v$r$7$h$&$H$7$^$9$,!"5-;v$r:o=|$9$k$+!"FI$^$J$$$G4{FI$N0u$rIU\e(B
+\e$B$1$k$H!"\e(Bgnus \e$B$O$3$l$i$N5-;v$K\e(B @code{Xref} \e$B$N9T$r$N$>$-$^$o$k5!2q$rF@$k;v\e(B
+\e$B$,L5$/!"Aj8_;2>H5!9=$rMQ$$$k;v$,$G$-$^$;$s!#\e(B
+
+@cindex LIST overview.fmt
+@cindex overview.fmt
+\e$B$"$J$?$N\e(B @acronym{NNTP} \e$B%5!<%P!<$,$=$N354Q%U%!%$\e(B
+\e$B%k\e(B (overview file) \e$B$K\e(B @code{Xref} \e$BMs$r4^$s$G$$$k$+$rD4$Y$k$K$O!"\e(B
+@samp{telnet your.nntp.server nntp} \e$B$H$7$F!"\e(B@code{inn} \e$B%5!<%P!<\e(B
+\e$B$G\e(B @samp{More READER} \e$B$H$7!"$=$l$+$i\e(B @samp{LIST overview.fmt} \e$B$H$9$k;v$r\e(B
+\e$B;n$7$F$/$@$5$$!#$3$l$OF0:n$7$J$$$G$7$g$&$,!"$b$7F0:n$7$F!"<hF@$7$?:G8e$N\e(B
+\e$B9T$,\e(B @samp{Xref:full} \e$B$G$J$$$J$i$P!"%K%e!<%9$N4IM}<T$,354Q%U%!%$%k$K\e(B
+@code{Xref} \e$BMs$r4^$`$h$&$K$9$k$^$G!"%K%e!<%94IM}<T$K6+$S!"5c$-IU$/;v$rB3\e(B
+\e$B$1$k$Y$-$G$7$g$&!#\e(B
+
+@vindex gnus-nov-is-evil
+Gnus \e$B$K$$$D$G$b@5$7$$\e(B @code{Xref} \e$B$r<hF@$9$k$h$&$K$5$;$?$$$N$G$"$l$P!"\e(B
+@code{gnus-nov-is-evil} \e$B$r\e(B @code{t} \e$B$K$9$kI,MW$,$"$j!"$=$l$OHs>o$KB.EY$r\e(B
+\e$BCY$/$7$^$9!#\e(B
+
+\e$B$^!"?M@8$O$=$N$h$&$J$b$N$G$9!#\e(B
+
+\e$BBeBX<jCJ$KIU$$$F$O\e(B @ref{Duplicate Suppression} \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@node Duplicate Suppression
+@section \e$B=EJ#$NM^@)\e(B
+
+\e$B%G%#%U%)%k%H$G$O\e(B gnus \e$B$OAj8_Ej9F5!9=$rMxMQ$9$k;v$K$h$C$F!"F1$85-;v\e(B
+\e$B$rFs2s0J>eFI$^$J$$$h$&$K$7$h$&$H$7$^$9\e(B (@pxref{Crosspost Handling})\e$B!#$7\e(B
+\e$B$+$7!"$=$NC1=c$G8z2LE*$JJ}K!$O!"$$$m$$$m$JM}M3$K$h$j!"K~B-$9$k7k2L$r$b$?\e(B
+\e$B$i$5$J$$$+$bCN$l$^$;$s!#\e(B
+
+@enumerate
+@item
+@acronym{NNTP} \e$B%5!<%P!<$O\e(B @code{Xref} \e$BMs$N@8@.$K<:GT$9$k$+$bCN$l$^$;$s!#\e(B
+\e$B$3$l$O0-$$;v$G!"$"$^$j5/$3$j$^$;$s!#\e(B
+
+@item
+@acronym{NNTP} \e$B%5!<%P!<$O\e(B @file{.overview} \e$B%G!<%?%Y!<%9$K\e(B @code{Xref} \e$BMs\e(B
+\e$B$r4^$a$k$N$K<:GT$9$k$+$bCN$l$^$;$s!#$3$l$O0-$$;v$G!"Hs>o$KNI$/$"$k;v$G$9!"\e(B
+\e$B$"$!Ha$7$$!#\e(B
+
+@item
+\e$BF1$8%0%k!<%W\e(B (\e$B$b$7$/$O$$$/$D$+$N4XO"$7$?%0%k!<%W\e(B) \e$B$r0c$C\e(B
+\e$B$?\e(B @acronym{NNTP} \e$B%5!<%P!<$+$iFI$s$G$$$k$+$b$7$l$^$;$s!#\e(B
+
+@item
+\e$B%0%k!<%W$KEj9F$5$l$?5-;v$H=EJ#$9$k%a!<%k$r<u$1<h$C$?$+$b$7$l$^$;$s!#\e(B
+@end enumerate
+
+@code{Xref} \e$B$N07$$$K<:GT$9$k>u67$OB>$K$b$"$j$^$9$,!"$3$l$i;M$D$,$H$F$bNI\e(B
+\e$B$/$"$k>u67$G$9!#\e(B
+
+\e$B$b$7!"K\Ev$K$b$7$b\e(B @code{Xref} \e$B$N07$$$K<:GT$7$?$i!"\e(B@dfn{\e$B=EJ#M^@)\e(B}\e$B$K@Z$j\e(B
+\e$BBX$($k;v$r9M$($k$+$b$7$l$^$;$s!#$=$&$9$l$P!"\e(Bgnus \e$B$O$"$J$?$,FI$s$@A4$F$N\e(B
+\e$B5-;v$+$=$&$G$J$1$l$P!"4{FI$N0u$,IU$$$?A4$F$N5-;v$N\e(B @code{Message-ID} \e$B$r\e(B
+\e$B5-21$7!"$=$l$+$i!"KbK!$N$h$&$K!"$=$N8e$N$=$l$i$H=P2q$C$?A4$F$N>l9g$K!"4{\e(B
+\e$BFI$N0u$rIU$1$^$9!=!=\e(B@emph{\e$BA4$F\e(B}\e$B$N%0%k!<%W$G!#$3$N5!9=$r;H$&$N$OHs>o$KHs\e(B
+\e$B8zN(E*$G$9$,!"2aEY$KHs8zN($J$o$1$G$O$"$j$^$;$s!#$b$A$m$sF1$85-;v$r0l2s0J\e(B
+\e$B>eFI$`$[$&$,9%$^$7$$$G$9!#\e(B
+
+\e$B=EJ#M^@)$O$"$^$jA!:Y$J$b$N$G$O$"$j$^$;$s!#$I$A$i$+$H$$$&$H!"BgDH$N$h$&$J\e(B
+\e$B$b$N$G$9!#$=$l$OHs>o$KC1=c$JJ}K!$GF0:n$7$F$$$^$9!=!=$b$75-;v$K4{FI$N0u$r\e(B
+\e$BIU$1$l$P!"$=$l$O$3$N\e(B Message-ID \e$B$r%-%c%C%7%e$K2C$($^$9!#<!$K$3\e(B
+\e$B$N\e(B Message-ID \e$B$K$G$"$C$?$H$-$O!"\e(B@samp{M} \e$B0u$K$h$C$F5-;v$K4{FI$N0u$rIU$1\e(B
+\e$B$^$9!#$=$l$O$=$N5-;v$,$I$N%0%k!<%W$K$"$k$+$O5$$K$7$^$;$s!#\e(B
+
+@table @code
+@item gnus-suppress-duplicates
+@vindex gnus-suppress-duplicates
+@code{nil} \e$B$G$J$1$l$P!"=EJ#M^@)$r$7$^$9!#\e(B
+
+@item gnus-save-duplicate-list
+@vindex gnus-save-duplicate-list
+@code{nil} \e$B$G$J$1$l$P!"=EJ#$N%j%9%H$r%U%!%$%k$KJ]B8$7$^$9!#$3$l$O5/F0$H\e(B
+\e$B=*N;$N;~4V$rD9$/$7$^$9$N$G!"=i4|>uBV$G$O\e(B @code{nil} \e$B$G$9!#$7$+$7!"$3$l$O\e(B
+\e$BC10l$N\e(B gnus \e$B$N<B9T4|$GFI$^$l$?=EJ#5-;v$@$1$,M^@)$5$l$k$H$$$&;v$G$9!#\e(B
+
+@item gnus-duplicate-list-length
+@vindex gnus-duplicate-list-length
+\e$B$3$NJQ?t$O$I$N$/$i$$B?$/$N\e(B @code{Message-ID} \e$B$r=EJ#M^@)%j%9%H$KJ]$C$F$*\e(B
+\e$B$/$+$b7hDj$7$^$9!#%G%#%U%)%k%H$O\e(B 10000 \e$B$G$9!#\e(B
+
+@item gnus-duplicate-file
+@vindex gnus-duplicate-file
+\e$B=EJ#M^@)$N%j%9%H$rC_@Q$7$F$*$/%U%!%$%k$NL>A0$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @file{~/News/suppression} \e$B$G$9!#\e(B
+@end table
+
+\e$B2?EY$b\e(B gnus \e$B$r=*N;$7$F5/F0$9$k798~$,$"$k$N$G$"$l$P!"$*$=$i\e(B
+\e$B$/\e(B @code{gnus-save-duplicate-list} \e$B$r\e(B @code{t} \e$B$K$9$k$N$ONI$$9M$($G$7$g\e(B
+\e$B$&!#$b$7\e(B gnus \e$B$rB3$1$F2?=54V$bAv$i$;$F$*$/$N$G$"$l$P!"$=$l\e(B
+\e$B$r\e(B @code{nil} \e$B$K$9$k$+$b$7$l$^$;$s!#0lJ}$G!"%j%9%H$rJ]B8$9$k;v$O5/F0$H=*\e(B
+\e$BN;$r$:$C$HCY$/$7$^$9$N$G!"$h$/\e(B gnus \e$B$r=*N;$7$F5/F0$9$k$N$G$"$l$P!"\e(B
+@code{gnus-save-duplicate-list} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$Y$-$G$"$k$H$$$&\e(B
+\e$B;v$K$J$j$^$9!#$&!<$`!#;d$O$"$J$?$,$I$&$9$k$+$KG$$;$?$$!"$H;W$$$^$9!#\e(B
+
+@ignore
+@node Security
+@section Security
+
+Gnus is able to verify signed messages or decrypt encrypted messages.
+The formats that are supported are @acronym{PGP}, @acronym{PGP/MIME}
+and @acronym{S/MIME}, however you need some external programs to get
+things to work:
+
+@enumerate
+@item
+To handle @acronym{PGP} and @acronym{PGP/MIME} messages, you have to
+install an OpenPGP implementation such as GnuPG.  The Lisp interface
+to GnuPG included with Gnus is called PGG (@pxref{Top, ,PGG, pgg, PGG
+Manual}), but Mailcrypt and gpg.el are also supported.
+
+@item
+To handle @acronym{S/MIME} message, you need to install OpenSSL.  OpenSSL 0.9.6
+or newer is recommended.
+
+@end enumerate
+
+More information on how to set things up can be found in the message
+manual (@pxref{Security, ,Security, message, Message Manual}).
+
+@table @code
+@item mm-verify-option
+@vindex mm-verify-option
+Option of verifying signed parts.  @code{never}, not verify;
+@code{always}, always verify; @code{known}, only verify known
+protocols.  Otherwise, ask user.
+
+@item mm-decrypt-option
+@vindex mm-decrypt-option
+Option of decrypting encrypted parts.  @code{never}, no decryption;
+@code{always}, always decrypt; @code{known}, only decrypt known
+protocols.  Otherwise, ask user.
+
+@item mml1991-use
+@vindex mml1991-use
+Symbol indicating elisp interface to OpenPGP implementation for
+@acronym{PGP} messages.  The default is @code{pgg}, but
+@code{mailcrypt} and @code{gpg} are also supported although
+deprecated.
+
+@item mml2015-use
+@vindex mml2015-use
+Symbol indicating elisp interface to OpenPGP implementation for
+@acronym{PGP/MIME} messages.  The default is @code{pgg}, but
+@code{mailcrypt} and @code{gpg} are also supported although
+deprecated.
+
+@end table
+
+@cindex snarfing keys
+@cindex importing PGP keys
+@cindex PGP key ring import
+Snarfing OpenPGP keys (i.e., importing keys from articles into your
+key ring) is not supported explicitly through a menu item or command,
+rather Gnus do detect and label keys as @samp{application/pgp-keys},
+allowing you to specify whatever action you think is appropriate
+through the usual @acronym{MIME} infrastructure.  You can use a
+@file{~/.mailcap} entry (@pxref{mailcap, , mailcap, emacs-mime, The
+Emacs MIME Manual}) such as the following to import keys using GNU
+Privacy Guard when you click on the @acronym{MIME} button
+(@pxref{Using MIME}).
+
+@example
+application/pgp-keys; gpg --import --interactive --verbose; needsterminal
+@end example
+
+This happens to also be the default action defined in
+@code{mailcap-mime-data}.
+
+@end ignore
+@node Mailing List
+@section \e$B%a!<%j%s%0%j%9%H\e(B
+@cindex mailing list
+@cindex RFC 2396
+
+@kindex A M (\e$B35N,\e(B)
+@findex gnus-mailing-list-insinuate
+Gnus \e$B$O\e(B RFC 2369 \e$B$G4{Dj$5$l$?3F<o$N%a!<%j%s%0%j%9%H$G;H$o$l$k%U%#!<%k%I\e(B
+\e$B$rM}2r$7$^$9!#$3$l$rM-8z$K$9$k$K$O\e(B @code{to-list} \e$B%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B (@pxref{Group Parameters}) \e$B$rDI2C$7$F!"35N,%P%C%U%!\e(B
+\e$B$G\e(B @kbd{A M} (@code{gnus-mailing-list-insinuate}) \e$B$r;H$C$F2<$5$$!#\e(B
+
+\e$B$3$l$K$h$C$F35N,%P%C%U%!$G$N0J2<$NL?Na$,;H$($k$h$&$K$J$j$^$9!#\e(B
+
+@table @kbd
+@item C-c C-n h
+@kindex C-c C-n h (\e$B35N,\e(B)
+@findex gnus-mailing-list-help
+List-Help \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$N%X%k%W$r<h$j4s$;$k$?$a\e(B
+\e$B$N%a%C%;!<%8$rAw?.$7$^$9!#\e(B
+
+@item C-c C-n s
+@kindex C-c C-n s (\e$B35N,\e(B)
+@findex gnus-mailing-list-subscribe
+List-Subscribe \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$N9VFI$r;O$a$k$?$a\e(B
+\e$B$N%a%C%;!<%8$rAw?.$7$^$9!#\e(B
+
+@item C-c C-n u
+@kindex C-c C-n u (\e$B35N,\e(B)
+@findex gnus-mailing-list-unsubscribe
+List-Unsubscribe \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$N9VFI$r$d$a$k$?\e(B
+\e$B$a$N%a%C%;!<%8$rAw?.$7$^$9!#\e(B
+
+@item C-c C-n p
+@kindex C-c C-n p (\e$B35N,\e(B)
+@findex gnus-mailing-list-post
+List-Post \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$KEj9F$7$^$9!#\e(B
+
+@item C-c C-n o
+@kindex C-c C-n o (\e$B35N,\e(B)
+@findex gnus-mailing-list-owner
+List-Owner \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$N4IM}<T08$F$K%a%C%;!<\e(B
+\e$B%8$rAw?.$7$^$9!#\e(B
+
+@item C-c C-n a
+@kindex C-c C-n a (\e$B35N,\e(B)
+@findex gnus-mailing-list-owner
+List-Archive \e$B%U%#!<%k%I$,$"$C$?$i!"%a!<%j%s%0%j%9%H$N%"!<%+%$%V$r1\Mw$7\e(B
+\e$B$^$9!#\e(B
+@end table
+
+@node Article Buffer
+@chapter \e$B5-;v%P%C%U%!\e(B
+@cindex article buffer
+
+\e$B5-;v$O0l$D$7$+$J$$5-;v%P%C%U%!$KI=<($5$l$^$9!#A4$F$N35N,%P%C%U%!\e(B
+\e$B$O\e(B (gnus \e$B$K6&M-$7$J$$$h$&$K;X<($7$J$$8B$j\e(B) \e$BF1$85-;v%P%C%U%!$r6&M-$7$^$9!#\e(B
+
+@menu
+* Hiding Headers::              \e$B$I$N%X%C%@!<$rI=<($9$k$+$r7h$a$k\e(B
+* Using MIME::                  @acronym{MIME} \e$B5-;v$H$7$F8+$;$k\e(B
+* Customizing Articles::        \e$B5-;v$N8+1I$($r;EN)$F$k\e(B
+* Article Keymap::              \e$B5-;v%P%C%U%!$G;H$($k%-!<A`:n\e(B
+* Misc Article::                \e$B$=$NB>\e(B
+@end menu
+
+@node Hiding Headers
+@section \e$BM>J,$J%X%C%@!<$r1#$9\e(B
+@cindex hiding headers
+@cindex deleting headers
+
+\e$B3F5-;v$NF,$NItJ,$O%X%C%@!<\e(B(@dfn{head})\e$B$H8F$P$l$^$9\e(B (\e$B;D$j$NItJ,$O%\\e(B
+\e$B%G%#\e(B (@dfn{body})\e$B$G$9!#$9$G$K$*5$$E$-$G$7$g$&$,\e(B)\e$B!#\e(B
+
+@vindex gnus-show-all-headers
+\e$B%X%C%@!<$K$O$?$/$5$s$NJXMx$J>pJs$,4^$^$l$F$$$^$9!#5-;v$r=q$$$??M$NL>A0!"\e(B
+\e$B$=$l$,=q$+$l$?F|IU!"5-;v$NI=Bj$J$I$G$9!#$3$l$O$H$F$bNI$$$s$G$9$,!"%X%C%@!<\e(B
+\e$B$K$OBgItJ,$N?M$K$O8+$?$/$b$J$$>pJs!=!=5-;v$,$"$J$?$N$H$3$m$KCe$/$^$G$I$s\e(B
+\e$B$J%7%9%F%`$r7PM3$7$F$-$?$+!"\e(B@code{Message-ID}, @code{References} \e$B$J$I$J\e(B
+\e$B$I!D$b$&$d$s$J$C$A$c$&$/$i$$!=!=$b$?$/$5$s4^$^$l$F$$$^$9!#$?$V$s$"$J$?$O\e(B
+\e$B$3$l$i$N9T$O$$$/$D$+<h$j=|$$$F$7$^$$$?$$$H;W$&$G$7$g$&!#$b$7$3$l$i$N9T$r\e(B
+\e$BA4$F5-;v%P%C%U%!Fb$K;D$7$F$*$-$?$1$l$P!"\e(B@code{gnus-show-all-headers} \e$B$r\e(B
+@code{t} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+
+Gnus \e$B$O%X%C%@!<$rA*$jJ,$1$k$?$a$KFs$D$NJQ?t$rMQ0U$7$F$$$^$9!#\e(B
+
+@table @code
+@item gnus-visible-headers
+@vindex gnus-visible-headers
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B0J30$G$"$l$P!"$I$N%X%C%@!<$r5-;v%P%C%U%!$K;D$7$?$$\e(B
+\e$B$+$r;XDj$9$k@55,I=8=$G$"$k$H$_$J$5$l$^$9!#$3$NJQ?t$K%^%C%A$7$J$$%X%C%@!<\e(B
+\e$B$OA4$F1#$5$l$^$9!#\e(B
+
+\e$BNc$($P!"5-;v$r=q$$$??M$NL>A0$HI=Bj$N$_$r8+$?$1$l$P!"$3$&;XDj$7$^$9!#\e(B
+
+@lisp
+(setq gnus-visible-headers "^From:\\|^Subject:")
+@end lisp
+
+\e$B$3$NJQ?t$O!"I=<($5$;$?$$%X%C%@!<$K%^%C%A$9$k@55,I=8=$r%j%9%H$G;X\e(B
+\e$BDj$9$k$3$H$b$G$-$^$9!#\e(B
+
+@item gnus-ignored-headers
+@vindex gnus-ignored-headers
+\e$B$3$NJQ?t$O\e(B @code{gnus-visible-headers} \e$B$NH?BP$G$9!#$3$NJQ?t$,@_Dj$5$l$F\e(B
+\e$B$$$l$P\e(B (\e$B$+$D\e(B @code{gnus-visible-headers} \e$B$,\e(B @code{nil} \e$B$G$"$l$P\e(B)\e$B!"$3$l$O\e(B
+\e$B1#$7$?$$%X%C%@!<9TA4$F$K%^%C%A$9$k@55,I=8=$G$"$k$H$_$J$5$l$^$9!#$3$NJQ?t\e(B
+\e$B$K%^%C%A$7$J$$A4$F$N%X%C%@!<9T$OI=<($5$l$^$9!#\e(B
+
+\e$BNc$($P!"C1$K\e(B @code{References} \e$BMs$H\e(B @code{Xref} \e$BMs$N$_$r>C$75n$j$?$1$l$P!"\e(B
+\e$B0J2<$N$h$&$K$7$^$9\e(B:
+
+@lisp
+(setq gnus-ignored-headers "^References:\\|^Xref:")
+@end lisp
+
+\e$B$3$NJQ?t$O>C$7$?$$%X%C%@!<$K%^%C%A$9$k@55,I=8=$N%j%9%H$G$b9=$$$^\e(B
+\e$B$;$s!#\e(B
+
+\e$B$J$*!"\e(B@code{gnus-visible-headers} \e$B$,\e(B @code{nil} \e$B0J30$N>l9g$O!"$3\e(B
+\e$B$NJQ?t$K$O8z2L$,L5$$$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+@end table
+
+@vindex gnus-sorted-header-list
+Gnus \e$B$O%X%C%@!<$NJB$YBX$(\e(B (sort) \e$B$b9T$$$^$9\e(B (\e$B$3$l$O%G%#%U%)%k%H$G9T$o$l\e(B
+\e$B$^$9\e(B)\e$B!#$3$NJB$YBX$($O\e(B @code{gnus-sorted-header-list} \e$BJQ?t$r@_Dj$9$k$3$H\e(B
+\e$B$G@)8f$9$k$3$H$,$G$-$^$9!#$3$l$O%X%C%@!<$r$I$&$$$&=g=x$GI=<($9$k$+$r;XDj\e(B
+\e$B$9$k@55,I=8=$N%j%9%H$G$9!#\e(B
+
+\e$BNc$($P!"5-;v$NCx<TL>$r:G=i$K!"<!$KI=Bj$rI=<($7$?$1$l$P!"$3$s$JIw\e(B
+\e$B$K$J$k$G$7$g$&!#\e(B
+
+@lisp
+(setq gnus-sorted-header-list '("^From:" "^Subject:"))
+@end lisp
+
+\e$BI=<($9$k$h$&$K$J$C$F$$$k%X%C%@!<$G$3$NJQ?t$K;XDj$5$l$F$$$J$$$b$N\e(B
+\e$B$O!"$3$NJQ?t$K;XDj$5$l$F$$$kA4$F$N%X%C%@!<$N8e$K!"E,Ev$J=g=x$GI=\e(B
+\e$B<($5$l$k$G$7$g$&!#\e(B
+
+@findex gnus-article-hide-boring-headers
+@vindex gnus-boring-article-headers
+@code{gnus-article-hide-boring-headers} \e$B$r\e(B@code{head} \e$B$K@_Dj$9$k$3$H$K$h$C\e(B
+\e$B$F!"$b$C$H$D$^$i$J$$%X%C%@!<$r1#$9$3$H$,$G$-$^$9!#$3$N4X?t$,2?$r$9$k$+\e(B
+\e$B$O\e(B @code{gnus-boring-article-headers} \e$BJQ?t$K0MB8$7$^$9!#$3$NJQ?t$O%j%9%H\e(B
+\e$B$G$9$,!"$3$N%j%9%H$K$O<B:]$N%X%C%@!<$NL>A0$,F~$k$N$G$O$"$j$^$;$s!#Be$o$j\e(B
+\e$B$K\e(B gnus \e$B$,%A%'%C%/$7$F;k3&$+$i>C$75n$k$?$a$N$5$^$6$^$J!V$D$^$i$J$$>r7o!W\e(B
+@dfn{boring conditions} \e$B$N%j%9%H$r;XDj$7$^$9!#\e(B
+
+\e$B$3$N>r7o$K$O0J2<$N$h$&$J$b$N$,$"$j$^$9!#\e(B
+
+@table @code
+@item empty
+\e$B6u$N%X%C%@!<$rA4$F>C5n$7$^$9!#\e(B
+@item followup-to
+@code{Followup-To} \e$BMs$,\e(B @code{Newsgroups} \e$BMs$HF10l$G$"$k>l9g$K$O>C5n$7$^\e(B
+\e$B$9!#\e(B
+@item reply-to
+@code{Reply-To} \e$BMs$,\e(B @code{From} \e$BMs$HF1$8%"%I%l%9$r<($7$F$$$k$+!"\e(B
+@code{broken-reply-to} \e$B%0%k!<%W%Q%i%a!<%?$,@_Dj$5$l$F$$$k>l9g$K$O>C5n$7\e(B
+\e$B$^$9!#\e(B
+@item newsgroups
+@code{Newsgroups} \e$BMs$,8=:_$N%0%k!<%WL>$7$+4^$s$G$$$J$$>l9g$K$O>C5n$7$^$9!#\e(B
+@item to-address
+@code{To} \e$BMs$,8=:_$N%0%k!<%W$N\e(B @code{to-address} \e$B%Q%i%a!<%?$HF1$8$b$N$7\e(B
+\e$B$+4^$s$G$$$J$$>l9g$K$O>C5n$7$^$9!#\e(B
+@item to-list
+@code{To} \e$BMs$,8=:_$N%0%k!<%W$N\e(B @code{to-list} \e$B%Q%i%a!<%?$HF1$8$b$N$7$+4^\e(B
+\e$B$s$G$$$J$$>l9g$K$O>C5n$7$^$9!#\e(B
+@item cc-list
+@code{CC} \e$BMs$,8=:_$N%0%k!<%W$N\e(B @code{to-list} \e$B%Q%i%a!<%?$HF1$8$b$N$7$+4^\e(B
+\e$B$s$G$$$J$$>l9g$K$O>C5n$7$^$9!#\e(B
+@item date
+\e$B$=$N5-;v$,2a5n;0F|0JFb$N$b$N$G$"$l$P!"\e(B@code{Date} \e$BMs$r>C5n$7$^$9!#\e(B
+@item long-to
+@code{To} \e$BMs$,$"$^$j$K$bD9$$>l9g$K$O>C5n$7$^$9!#\e(B
+@item many-to
+@code{To} \e$BMs$,0l$D$h$j$bB?$1$l$P!"$=$l$i$rA4$F>C5n$7$^$9!#\e(B
+@end table
+
+\e$B$3$l$i$N;0$D$NMWAG$rF~$l$?$1$l$P!"$3$s$JIw$K$J$j$^$9\e(B:
+
+@lisp
+(setq gnus-boring-article-headers
+      '(empty followup-to reply-to))
+@end lisp
+
+\e$B$3$l$O$3$NJQ?t$N%G%#%U%)%k%HCM$G$b$"$j$^$9!#\e(B
+
+@node Using MIME
+@section MIME \e$B$r;H$&\e(B
+@cindex @acronym{MIME}
+
+\e$B%Q%s%H%^%$%`\e(B (mime) \e$B$H$O!"0UL#$bL5$/6uCf$G<j$r?6$k$b$N$H$7$F9-$/\e(B
+\e$BCN$i$l$F$*$j!"$=$N4V4Q5R$O$"$/$S$r$7$J$,$i$\$s$d$j$H$7$F$^$9!#\e(B
+
+\e$B0lJ}!"\e(B@acronym{MIME} \e$B$H$O!"0UL#$bL5$/5-;v$rId9f2=$9$kI8=`$G$"$j!"$=$N\e(B
+\e$B$?$a$KA4$F$N%K%e!<%9%j!<%@$,62I]$G;`$s$G$7$^$&$b$N$G$9!#\e(B
+
+@acronym{MIME} \e$B$O$=$N5-;v$,$I$s$JJ8;z=89g$r;HMQ$7$F$$$k$+!"$=$NJ8;z$r$I\e(B
+\e$B$&Id9f2=$7$F$$$k$+$r;XDj$9$k$3$H$,$G$-!"$5$i$K$O3($d$=$NB>$N$_$@$i$J$b$N\e(B
+\e$B$rL5<Y5$$J3J9%$N5-;v$KKd$a9~$`$3$H$5$(2DG=$K$7$^$9!#\e(B
+
+@vindex gnus-show-mime
+@vindex gnus-article-display-method-for-mime
+@findex gnus-article-display-mime-message
+gnus \e$B$O\e(B @code{gnus-article-display-method-for-mime} \e$B$K5-;v$r2!$7IU$1$k$3\e(B
+\e$B$H$G\e(B @acronym{MIME} \e$B$r07$$$^$9!#$3$N=i4|CM\e(B
+\e$B$O\e(B @code{gnus-article-display-mime-message} \e$B$G$9!#$3$N4X?t\e(B
+\e$B$O\e(B @acronym{SEMI} MIME-View \e$B%W%m%0%i%`$r8F$S=P$7$F<B:]$N=hM}$r9T$$$^$9!#\e(B
+@acronym{SEMI} MIME-View \e$B$K4X$9$k>\$7$$>pJs$O!"%^%K%e%"%k$r;2>H$7$F$/$@\e(B
+\e$B$5$$\e(B (\e$B$^$@$J$$$1$I\e(B (;_;))\e$B!#\e(B
+
+@acronym{MIME} \e$B$r>o$K;HMQ$7$?$1$l$P!"\e(B
+@code{gnus-show-mime} \e$B$r\e(B @code{t} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+@code{gnus-show-mime} \e$B$r@_Dj$7$F$$$k$H!"1?$,0-$$$H5-;v%P%C%U%!$K$O8N>c$7\e(B
+\e$B$?$h$&$J2hLL$,8+$($k$3$H$b$"$k$G$7$g$&!#$3$l$OHr$1$h$&$,$"$j$^$;$s!#\e(B
+
+GNUS \e$B$d\e(B Gnus \e$B$G$O!"$3$N$?$A$N0-$$LdBj$G6C$+$5$l$J$$$h$&$K$9$k$K$O!"35N,\e(B
+\e$B%P%C%U%!$K$*$$$F@Z$jBX$(5!G=$r;H$&$H$$$&$N$,:GA1$+$bCN$l$^$;$s\e(B (\e$BNc$($P!"\e(B
+@samp{alt.sing-a-long} \e$B%0%k!<%W$KF~$k$H!"$"$J$?$N5$$E$+$J$$$&$A\e(B
+\e$B$K\e(B @acronym{MIME} \e$B$O5-;vCf$N%5%&%s%I%U%!%$%k$rI|9f$7$F!"2?$d$i2x$7$2$JD9\e(B
+\e$B$$D9$$2N$,$"$J$?$N%9%T!<%+!<$+$iBg2;6A$GN.$l=P$7!"$"$J$?$O%\%j%e!<%`%\%?\e(B
+\e$B%s$r8+$D$1$i$l$:!"$H$$$&$N$O$=$s$J$b$N$O$b$H$b$H$D$$$F$J$$$+$i$G!"$_$s$J\e(B
+\e$B$O$"$J$?$NJ}$rbK$_$O$8$a!"$"$J$?$O%W%m%0%i%`$r;_$a$h$&$H$9$k$1$I$G$-$J$/\e(B
+\e$B$F!"%\%j%e!<%`$r@)8f$9$k%W%m%0%i%`$b8+$D$1$i$l$J$/$F!"$=$7$FIt20Cf$NA40w\e(B
+\e$B$OFMA3$"$J$?$N$3$H$r7ZJN$N4c:9$7$G8+$k$h$&$K$J$C$F$7$^$$!"$"$J$?$O$A$g$C\e(B
+\e$B$HLLGr$/$J$$;W$$$r$9$k!"$H$+\e(B)\e$B!#\e(B
+
+\e$B8=<B$N=PMh;v$H<B:_$N?MJ*$KN`;w$7$F$$$k$+$b$7$l$^$;$s$,!"$3$l$OA4$F%[%s%H\e(B
+\e$B$N$3$H$G$9!#$2$[$2$[!#\e(B
+
+\e$B$^$"!"$=$&$$$&Lu$G!"\e(Bgnus \e$B$G$O\e(B @code{metamail-buffer} \e$B$r;H$&$N$r;_$a$?Lu\e(B
+\e$B$G$9!#$=$&$$$&Lu$G!":#$G$O>o$K\e(B @code{gnus-show-mime} \e$B$r\e(B @code{nil} \e$B0J30\e(B
+\e$B$K$7$F$*$-!"<~$j$K?M$,$$$J$$;~$r8+7W$i$C$F5-;v%P%C%U%!$K8=$o$l$k%\%?%s$r\e(B
+\e$B2!$7$^$7$g$&!#\e(B
+
+@c Also @xref{MIME Commands}.
+
+@node Customizing Articles
+@section \e$B5-;v$N%+%9%?%^%$%:\e(B
+@cindex article customization
+
+\e$B5-;v$,$I$N$h$&$KB8:_$7$F$$$k$+$r%+%9%?%^%$%:$9$k$?$a$N$?$/$5$s$N4X?t$G$9!#\e(B
+\e$B$3$l$i$N4X?t$rBPOCE*$K8F$V$3$H$b$G$-$^$9$7\e(B (@pxref{Article Washing})\e$B!"5-\e(B
+\e$B;v$rA*Br$7$?$H$-$K<+F0E*$KA*Br$9$k$3$H$b$G$-$^$9!#\e(B
+
+\e$B<+F0E*$K8F$P$l$k$h$&$K$9$k$?$a$K$O!"BP1~$9$k\e(B ``treatment'' \e$BJQ?t$r@_Dj$7\e(B
+\e$B$^$9!#Nc$($P!"%X%C%@!<$r1#$9$?$a$K$O!"\e(B@code{gnus-treat-hide-headers} \e$B$r\e(B
+\e$B@_Dj$7$^$9!#0J2<$O@_Dj$G$-$kJQ?t$N0lMw$G$9$,!"$^$:$3$l$i$NJQ?t$N<h$jF@$k\e(B
+\e$BCM$r5DO@$7$^$9!#\e(B
+
+\e$BCm0U\e(B: \e$B$$$/$D$+$NCM$O!"M-8z$JCM$G$9$,!"$[$H$s$I0UL#$rL5$7$^$;$s!#0UL#$N$"\e(B
+\e$B$kCM$O2<$N0lMw$rD4$Y$F$/$@$5$$!#\e(B
+
+@enumerate
+@item
+@code{nil}: \e$B$3$N07$$$r$7$^$;$s!#\e(B
+
+@item
+@code{t}: \e$B$3$N07$$$rA4$F$NK\J8$NItJ,$G9T$$$^$9!#\e(B
+
+@item
+@code{head}: \e$B%X%C%@!<$G$=$N07$$$r$7$^$9!#\e(B
+
+@item
+@code{last}: \e$B$3$N07$$$r:G8e$NItJ,$G9T$$$^$9!#\e(B
+
+@item
+\e$B@0?t\e(B: \e$B$3$N07$$$r$3$NHV9f$h$jC;$$A4$F$NK\J8$NItJ,$G9T$$$^$9!#\e(B
+
+@item
+\e$BJ8;zNs$N%j%9%H\e(B: \e$B$3$N%j%9%H$N$J$+$N@55,I=8=$K9gCW$9$kL>A0$N%0%k!<%W$GFI$^\e(B
+\e$B$l$?5-;v$NA4$F$NK\J8$NItJ,$G$3$N07$$$r9T$$$^$9!#\e(B
+
+@item
+\e$B:G=i$NMWAG$,J8;zNs$G$J$$%j%9%H$G$9\e(B:
+
+\e$B%j%9%H$O:F5"E*$KI>2A$5$l$^$9!#%j%9%H$N:G=i$NMWAG$O=R8l$G$9!#0J2<$N=R8l$,\e(B
+\e$BG'<1$5$l$^$9\e(B: @code{or}, @code{and}, @code{not}, @code{typep}\e$B!#$3$l$,Nc\e(B
+\e$B$G$9\e(B:
+
+@lisp
+(or last
+    (typep "text/x-vcard"))
+@end lisp
+
+@end enumerate
+
+@c FIXTGNUS Is this true?
+\e$B$3$3$G\e(B @dfn{\e$B0lItJ,\e(B} \e$B$H$$$&8l$,;H$o$l$F$$$k$3$H$K5$IU$$$?$H;W$$$^$9!#$3$l\e(B
+\e$B$O%a%C%;!<%8$K$O\e(B @acronym{MIME} \e$B%^%k%A%Q!<%H5-;v$,$"$j!"$$$/$D$+$NItJ,$K\e(B
+\e$BJ,3d$5$l$F$$$k$+$b$7$l$J$$$H$$$&;v<B$rH?1G$7$F$$$^$9!#%^%k%A%Q!<%H$G$J$$\e(B
+\e$B5-;v$O0l$D$NItJ,$N$_$G$"$k$H$_$J$5$l$^$9!#\e(B
+
+@vindex gnus-article-treat-types
+\e$B$3$N07$$$OA4$F$N%^%k%A%Q!<%H$NItJ,$KE,MQ$5$l$k$N$G$h$&$+\e(B? \e$B$O$$!"$=$&$7$?\e(B
+\e$B$1$l$P$=$&$J$j$^$9!#$G$9$,!"=i4|@_Dj$G$O!"\e(B@samp{text/plain} \e$BItJ,$,07$$$r\e(B
+\e$B<u$1$^$9!#$3$l$O\e(B @code{gnus-article-treat-types} \e$BJQ?t$G@)8f$5$l!"$3$l$O\e(B
+\e$B3FItJ,$N7?$K9gCW$9$k@55,I=8=$N%j%9%H$G$9!#@)8fJQ?t$NCM$,!">e$G@bL@$5$l$F\e(B
+\e$B$$$k$h$&$K=R8l$N%j%9%H$G$"$k$H$-$O!"$3$NJQ?t$OL5;k$5$l$^$9!#\e(B
+
+\e$B0J2<$N07$$$N%*%W%7%g%s$,;HMQ2DG=$G$9!#$3$l$r%+%9%?%^%$%:$9$k$?$a$N:G$b4J\e(B
+\e$BC1$JJ}K!$O\e(B @code{gnus-article-treat} \e$B%+%9%?%^%$%:%0%k!<%W$rD4::$9$k$3$H\e(B
+\e$B$G$9!#4]3g8L$NCf$NCM$ODs0F$5$l$F$$$k0UL#$N$"$kCM$G$9!#B>$N$b$N$b2DG=$G$9\e(B
+\e$B$,!"$[$H$s$I$N?M$O$*$=$i$/$3$3$K0lMwI=<($5$l$F$$$k$b$N$G==J,$G$7$g$&!#\e(B
+
+@table @code
+@item gnus-treat-buttonize (t, integer)
+@item gnus-treat-buttonize-head (head)
+
+@xref{Article Buttons}.
+
+@item gnus-treat-capitalize-sentences (t, integer)
+@item gnus-treat-overstrike (t, integer)
+@item gnus-treat-strip-cr (t, integer)
+@item gnus-treat-strip-headers-in-body (t, integer)
+@item gnus-treat-strip-leading-blank-lines (t, integer)
+@item gnus-treat-strip-multiple-blank-lines (t, integer)
+@item gnus-treat-strip-pem (t, last, integer)
+@item gnus-treat-strip-trailing-blank-lines (t, last, integer)
+@item gnus-treat-unsplit-urls (t, integer)
+@item gnus-treat-wash-html (t, integer)
+@item gnus-treat-decode-article-as-default-mime-charset (t, integer)
+
+@xref{Article Washing}.
+
+@item gnus-treat-date-english (head)
+@item gnus-treat-date-iso8601 (head)
+@item gnus-treat-date-lapsed (head)
+@item gnus-treat-date-local (head)
+@item gnus-treat-date-original (head)
+@item gnus-treat-date-user-defined (head)
+@item gnus-treat-date-ut (head)
+
+@xref{Article Date}.
+
+@item gnus-treat-from-picon (head)
+@item gnus-treat-mail-picon (head)
+@item gnus-treat-newsgroups-picon (head)
+
+@xref{Picons}.
+
+@item gnus-treat-display-smileys (t, integer)
+
+@item gnus-treat-body-boundary (head)
+
+@vindex gnus-body-boundary-delimiter
+\e$B%X%C%@!<$HK\J8$N4V$K6-3&@~$rDI2C$7$^$9!#6-3&@~$K\e(B
+\e$B$O\e(B @code{gnus-body-boundary-delimiter} \e$B$K@_Dj$5$l$?J8;zNs$,;H$o$l$^$9!#\e(B
+
+@xref{Smileys}.
+
+@item gnus-treat-display-x-face (head)
+
+@xref{X-Face}.
+
+@item gnus-treat-display-face (head)
+
+@xref{Face}.
+
+@item gnus-treat-emphasize (t, head, integer)
+@item gnus-treat-fill-article (t, integer)
+@item gnus-treat-fill-long-lines (t, integer)
+@item gnus-treat-hide-boring-headers (head)
+@item gnus-treat-hide-citation (t, integer)
+@item gnus-treat-hide-citation-maybe (t, integer)
+@item gnus-treat-hide-headers (head)
+@item gnus-treat-hide-signature (t, last)
+@item gnus-treat-strip-banner (t, last)
+@item gnus-treat-strip-list-identifiers (head)
+
+@xref{Article Hiding}.
+
+@item gnus-treat-highlight-citation (t, integer)
+@item gnus-treat-highlight-headers (head)
+@item gnus-treat-highlight-signature (t, last, integer)
+
+@xref{Article Highlighting}.
+
+@item gnus-treat-play-sounds
+@item gnus-treat-translate
+@item gnus-treat-x-pgp-sig (head)
+
+@item gnus-treat-unfold-headers (head)
+@item gnus-treat-fold-headers (head)
+@item gnus-treat-fold-newsgroups (head)
+@item gnus-treat-leading-whitespace (head)
+
+@xref{Article Header}.
+@end table
+
+@vindex gnus-part-display-hook
+\e$B$b$A$m$s!"\e(B@code{gnus-part-display-hook} \e$B$+$i8F$P$l$k<+J,<+?H$N4X?t$r=q$/\e(B
+\e$B$3$H$b$G$-$^$9!#4X?t$O$=$NItJ,$KHO0O$,69$a$i$l$?>uBV$G8F$P$l!"$[$H$s$I$J\e(B
+\e$B$s$G$b9%$-$J$3$H$r$G$-$^$9!#%P%C%U%!$KJ]B8$7$F$*$+$J$1$l$P$J$i$J$$>pJs$O\e(B
+\e$B$"$j$^$;$s\e(B---\e$B2?$G$bJQ$($k$3$H$,$G$-$^$9!#$7$+$7!"%X%C%@!<$r>C$7$F$O$$$1\e(B
+\e$B$^$;$s!#\e(B
+
+@node Article Keymap
+@section \e$B5-;v$N%-!<A`:n\e(B
+
+\e$B35N,%P%C%U%!$K$*$1$k%-!<A`:n$N$[$H$s$I$O5-;v%P%C%U%!$G$b;HMQ$G$-\e(B
+\e$B$^$9!#$3$l$i$O35N,%P%C%U%!$G$=$N%-!<$r2!$7$?$+$N$h$&$KF0:n$7$^$9!#\e(B
+\e$B$D$^$j!"<B$O5-;v$rFI$s$G$$$k4V!"35N,%P%C%U%!$rI=<($5$;$F$*$/I,MW\e(B
+\e$B$b$J$$$H$$$&$3$H$G$9!#A4$F$NA`:n$O5-;v%P%C%U%!$+$i9T$&$3$H$,$G$-\e(B
+\e$B$k$N$G$9!#\e(B
+
+\e$B$=$l$i$K2C$($F$$$/$D$+$N%-!<A`:n$,MxMQ$G$-$^$9!#\e(B
+
+@table @kbd
+@item SPACE
+@kindex SPACE (\e$B5-;v\e(B)
+@findex gnus-article-next-page
+\e$B0lJGA0$K$a$/$j$^$9\e(B (@code{gnus-article-next-page})\e$B!#\e(B@kbd{h SPACE h} \e$B$H$^$C\e(B
+\e$B$?$/F1$8$G$9!#\e(B
+
+@item DEL
+@kindex DEL (\e$B5-;v\e(B)
+@findex gnus-article-prev-page
+\e$B0lJG8e$m$KLa$7$^$9\e(B (@code{gnus-article-prev-page})\e$B!#\e(B@kbd{h DEL h} \e$B$H$^$C\e(B
+\e$B$?$/F1$8$G$9!#\e(B
+
+@item C-c ^
+@kindex C-c ^ (\e$B5-;v\e(B)
+@findex gnus-article-refer-article
+\e$B%+!<%=%k0LCV$,\e(B @code{Message-ID} \e$B$N6aJU$K$"$k$H$-$K\e(B @kbd{C-c ^} \e$B$r2!\e(B
+\e$B$9$H!"\e(Bgnus \e$B$O%5!<%P!<$+$i$=$N5-;v$r<h$C$F$3$h$&$H$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-refer-article})\e$B!#\e(B
+
+@item C-c C-m
+@kindex C-c C-m (\e$B5-;v\e(B)
+@findex gnus-article-mail
+\e$B%+!<%=%k0LCV$N6a$/$K$"$k%"%I%l%9$KJV?.$rAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-article-mail})\e$B!#@\F,0z?t$rM?$($k$H!"$=$N%a!<%k$K0zMQ$7$^\e(B
+\e$B$9!#\e(B
+
+@item s
+@kindex s (\e$B5-;v\e(B)
+@findex gnus-article-show-summary
+\e$B%P%C%U%!$r:F9=@.$7$F!"35N,%P%C%U%!$r8+$($k$h$&$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-show-summary})\e$B!#\e(B
+
+@item ?
+@kindex ? (\e$B5-;v\e(B)
+@findex gnus-article-describe-briefly
+\e$BMxMQ$G$-$k%-!<A`:n$N$4$/4JC1$J@bL@$r=P$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-describe-briefly})\e$B!#\e(B
+
+@item TAB
+@kindex TAB (\e$B5-;v\e(B)
+@findex gnus-article-next-button
+\e$B<!$N%\%?%s$,$"$l$P$=$3$K0\F0$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-next-button})\e$B!#$3$l$O%\%?%s5!G=$r%*%s$K$7$F$$$k$H\e(B
+\e$B$-$N$_0UL#$r;}$A$^$9!#\e(B
+
+@item M-TAB
+@kindex M-TAB (\e$B5-;v\e(B)
+@findex gnus-article-prev-button
+\e$B0l$DA0$N%\%?%s$,$"$l$P$=$3$K0\F0$7$^$9\e(B (@code{gnus-article-prev-button})\e$B!#\e(B
+
+@item R
+@kindex R (\e$B5-;v\e(B)
+@findex gnus-article-reply-with-original
+\e$B8=:_$N5-;v$KK\5-;v$r4^$s$@JVEz$N%a!<%k$rAw$j$^\e(B
+\e$B$9\e(B (@code{gnus-article-reply-with-original})\e$B!#@\F,<-$rM?$($k$H9-$$JV\e(B
+\e$BEz\e(B (wide reply) \e$B$K$J$j$^$9!#$b$7NN0h$,3h@-2=$5$l$F$$$?$J$i$P!"$=$NNN0h$K\e(B
+\e$B$"$k%F%-%9%H$@$1$r\e(B yank \e$B$7$^$9!#\e(B
+
+@item F
+@kindex F (\e$B5-;v\e(B)
+@findex gnus-article-followup-with-original
+\e$B8=:_$N5-;v$KK\5-;v$r4^$s$G%U%)%m!<%"%C%W$r$7$^\e(B
+\e$B$9\e(B (@code{gnus-article-followup-with-original})\e$B!#@\F,<-$rM?$($k$H9-$$JV\e(B
+\e$BEz\e(B (wide reply) \e$B$K$J$j$^$9!#$b$7NN0h$,3h@-2=$5$l$F$$$?$J$i$P!"$=$NNN0h$K\e(B
+\e$B$"$k%F%-%9%H$@$1$r\e(B yank \e$B$7$^$9!#\e(B
+@end table
+
+@node Misc Article
+@section \e$B5-;v$N$=$NB>\e(B
+
+@table @code
+@item gnus-single-article-buffer
+@vindex gnus-single-article-buffer
+@code{nil} \e$B0J30$G$"$l$P!"A4$F$N%0%k!<%W$KBP$7$FF1$85-;v%P%C%U%!$r;HMQ$7\e(B
+\e$B$^$9\e(B (\e$B$3$l$O%G%#%U%)%k%H$G$9\e(B)\e$B!#\e(B@code{nil} \e$B$G$"$l$P!"3F%0%k!<%WKh$N8GM-$N\e(B
+\e$B5-;v%P%C%U%!$r;}$D$h$&$K$J$j$^$9!#\e(B
+
+@c FIXMETGNUS Default value is nil for T-gnus.
+@vindex gnus-article-decode-hook
+@item gnus-article-decode-hook
+@cindex @acronym{MIME}
+@acronym{MIME} \e$B5-;v$rI|9f2=$9$k$H$-$K;HMQ$5$l$k%U%C%/$G$9!#\e(B
+
+@vindex gnus-article-prepare-hook
+@item gnus-article-prepare-hook
+\e$B$3$N%U%C%/$O5-;v$,5-;v%P%C%U%!$K=q$-9~$^$l$?D>8e$K8F$S=P$5$l$^$9!#$3$l$O\e(B
+\e$B<g$K!"2?$+5-;v$NFbMF$K0MB8$9$k=hM}$r$9$k4X?t$N$?$a$KMQ0U$5$l$F$$$^$9!#$D\e(B
+\e$B$^$j5-;v%P%C%U%!$NFbMF$rJQ99$9$k$h$&$JL\E*$G;H$&$Y$-$G$O$J$$$G$7$g$&!#\e(B
+
+@item gnus-article-mode-hook
+@vindex gnus-article-mode-hook
+\e$B5-;v%b!<%I%P%C%U%!$G8F$S=P$5$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-article-mode-syntax-table
+@vindex gnus-article-mode-syntax-table
+\e$B5-;v%P%C%U%!$GMQ$$$i$l$k%7%s%?%C%/%9%F!<%V%k$G$9!#$3$l\e(B
+\e$B$O\e(B @code{text-mode-syntax-table} \e$B$r$b$H$K=i4|2=$5$l$^$9!#\e(B
+
+@vindex gnus-article-over-scroll
+@item gnus-article-over-scroll
+\e$BHs\e(B-@code{nil} \e$B$K$9$k$3$H$K$h$C$F!"$=$l0J>e%9%/%m!<%k$9$k?7$7$$%F%-%9%H$,\e(B
+\e$BL5$/$F$b5-;v%P%C%U%!$r%9%/%m!<%k$9$k$3$H$r2DG=$K$7$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B(\e$BLuCm\e(B: \e$B5-;v$N:G2<9T$,8+$($F$$$k$H$-$K!"\e(B@code{nil} \e$B$G\e(B
+\e$B$O\e(B @kbd{RET} \e$B$G$=$l0J>e%9%/%m!<%k$7$J$$$,!"Hs\e(B-@code{nil} \e$B$K$9$k$H5-;v$,\e(B
+\e$B8+$($J$/$J$k$^$G%9%/%m!<%k$9$k!#\e(B)
+
+@vindex gnus-article-mode-line-format
+@item gnus-article-mode-line-format
+\e$B$3$NJQ?t$O\e(B @code{gnus-summary-mode-line-format} \e$B$HF1$89T$K=>$C$?MM<0J8;z\e(B
+\e$BNs$G$9\e(B (@pxref{Mode Line Formatting})\e$B!#$3$l$O0J2<$NFs$D$N3HD%$r=|$$$F!"\e(B
+\e$B$=$NJQ?t$HF1$8MM<0;XDj$r<uIU$1$^$9!#\e(B
+
+@table @samp
+@item w
+\e$B5-;v$N!V@vBu>uBV!W\e(B@dfn{wash status}\e$B!#$3$l$O5-;v$KBP$7$F9T$o$l$?$G$"$m$&\e(B
+\e$B@vBuA`:n$r<($90lJ8;z$+$i$J$kC;$$J8;zNs$K$J$j$^$9!#J8;z$H$=$l$i$N0UL#$O\e(B:
+
+@table @samp
+@item c
+\e$B5-;v%P%C%U%!$K$*$$$F!"0zMQ$5$l$?J8$,1#$5$l$F$$$k$+$b$7$l$J$$>l9g$KI=<($5\e(B
+\e$B$l$^$9!#\e(B
+
+@item h
+\e$B5-;v%P%C%U%!$K$*$$$F!"%X%C%@!<$,1#$5$l$F$$$k>l9g$KI=<($5$l$^$9!#\e(B
+
+@c @item p
+@c Displayed when article is digitally signed or encrypted, and Gnus has
+@c hidden the security headers.  (N.B. does not tell anything about
+@c security status, i.e. good or bad signature.)
+
+@item s
+\e$B5-;v%P%C%U%!$K$*$$$F!"=pL>$,1#$5$l$F$$$k>l9g$KI=<($5$l$^$9!#\e(B
+
+@item o
+\e$B5-;v%P%C%U%!$K=E$MBG$AJ8;z$,$"$k>l9g$KI=<($5$l$^$9!#\e(B
+
+@item e
+\e$B5-;v%P%C%U%!$K6/D4$5$l$?J8;zNs$,$"$k>l9g$KI=<($5$l$^$9!#\e(B
+@end table
+
+@c FIXMETGNUS Does this work?
+@item m
+\e$B5-;v$N\e(B @acronym{MIME} \e$BItJ,$N?t$G$9!#\e(B
+@end table
+
+@vindex gnus-break-pages
+
+@item gnus-break-pages
+\e$B2~JG\e(B @dfn{page breaking} \e$B$r9T$&$+$I$&$+$r@)8f$7$^$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"5-;vCf$KJG6h@Z$jJ8;z$,8=$l$?>l=j$4$H$KJGJ,3d\e(B
+\e$B$7$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$l$PJGJ,$1$O9T$o$l$^$;$s!#\e(B
+
+@item gnus-page-delimiter
+@vindex gnus-page-delimiter
+\e$B$3$l$,>e$G?($l$?6h@Z$jJ8;z$G$9!#%G%#%U%)%k%H$G$O\e(B @samp{^L} (\e$B%U%)!<%`\e(B
+\e$B%U%#!<%I!"2~JG\e(B) \e$B$G$9!#\e(B
+
+@cindex IDNA
+@cindex \e$B9q:]2=%I%a%$%sL>\e(B
+@vindex gnus-use-idna
+@item gnus-use-idna
+\e$B$3$NJQ?t$O\e(B @samp{From:}\e$B!"\e(B@samp{To:} \e$B$*$h$S\e(B @samp{Cc:} \e$B%X%C%@!<$K$"$k9q:]\e(B
+\e$B2=%I%a%$%sL>$r!"\e(Bgnus \e$B$,\e(B IDNA \e$B%G%3!<%I$9$k$+$I$&$+$r@)8f$7$^$9!#$3$l$K\e(B
+\e$B$O\e(B @uref{http://www.gnu.org/software/libidn/, GNU Libidn} \e$B$,I,MW$G!"$3$N\e(B
+\e$BJQ?t$O$=$l$r%$%s%9%H!<%k$7$F$"$k>l9g$@$1M-8z$K$J$j$^$9!#\e(B
+@end table
+
+@node Composing Messages
+@chapter \e$B%a%C%;!<%8$N:n@.\e(B
+@cindex composing messages
+@cindex messages
+@cindex mail
+@cindex sending mail
+@cindex reply
+@cindex followup
+@cindex post
+@c @cindex using gpg
+@c @cindex using s/mime
+@c @cindex using smime
+
+@kindex C-c C-c (\e$BEj9F\e(B)
+\e$BEj9F$N$?$a$NL?Na$r$9$k$H!"$"$J$?$O%a%C%;!<%8%P%C%U%!$K0\F0$7$^$9!#\e(B
+\e$B$=$3$G$O!"5-;v$r9%$-$J$h$&$KJT=8$9$k;v$,$G$-$^$9!#\e(B
+\e$B$=$N8e$G\e(B @kbd{C-c C-c} \e$B$r2!$9;v$K$h$C$F!"5-;v$rAw?.$7$^\e(B
+\e$B$9\e(B (@pxref{Top, , Overview, message-ja, Message Manual})\e$B!#5-;v$O$"$J$?$N\e(B
+\e$B@_Dj$K4p$E$$$FAw?.$5$l$^$9\e(B (@pxref{Posting Server})\e$B!#\e(B
+
+@menu
+* Mail::                        \e$B%a!<%k$HJVEz\e(B
+* Posting Server::              \e$B$I$N%5!<%P!<$rDL$7$F%K%e!<%9$rEj9F$^$?$O%a!<%k$rAw?.$9$k$Y$-$+\e(B?
+* Mail and Post::               \e$BF1;~$K%a!<%k$r=P$7JVEz$9$k\e(B
+* Archived Messages::           \e$BAw$C$?%a%C%;!<%8$r\e(B gnus \e$B$,Cy$a$F$*$/$H$3$m\e(B
+* Posting Styles::              \e$B$"$J$?$,C/$G$"$k$+$r;XDj$9$k$h$j4JC1$JJ}K!\e(B
+* Drafts::                      \e$B%a%C%;!<%8$N1d4|$H5qH]$5$l$?%a%C%;!<%8\e(B
+* Rejected Articles::           \e$B%5!<%P!<$,$"$J$?$N5-;v$r9%$-$G$J$$$H$-$K2?$,5/$3$k\e(B?
+@c * Signing and encrypting::      How to compose secure messages.
+@end menu
+
+\e$BEj9F$9$k$Y$-$G$J$+$C$?5-;v$r:o=|$9$k$?$a$N>pJs$K$D$$$F\e(B @ref{Canceling
+and Superseding} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@node Mail
+@section \e$B%a!<%k\e(B
+
+\e$B=P$F9T$/%a!<%k$r%+%9%?%^%$%:$9$kJQ?t$G$9\e(B:
+
+@table @code
+@item gnus-uu-digest-headers
+@vindex gnus-uu-digest-headers
+\e$BMWLs%a%C%;!<%8\e(B (digested message) \e$B$K4^$^$l$k%X%C%@!<$K9gCW$9$k@55,I=8=$N\e(B
+\e$B%j%9%H$G$9!#%X%C%@!<$O9gCW$7$?=g$K<h$j9~$^$l$^$9!#\e(B@code{nil} \e$B$@$C$?$i!"\e(B
+\e$B$9$Y$F$N%X%C%@!<$r4^$_$^$9!#\e(B
+
+@item gnus-add-to-list
+@vindex gnus-add-to-list
+@code{nil} \e$B$G$J$1$l$P!"\e(B@kbd{a} \e$B$r$7$?$H$-$K!"\e(B@code{to-list} \e$B%0%k!<%W%Q%i\e(B
+\e$B%a!<%?$r$=$l$N$J$$%a!<%k%0%k!<%W$KIU$12C$($^$9!#\e(B
+
+@item gnus-confirm-mail-reply-to-news
+@vindex gnus-confirm-mail-reply-to-news
+\e$B$3$l$O!"3NG'$,I,MW$G$"$k>l9g$KHs\e(B-@code{nil} \e$B$rJV$9!"M#0l$N%Q%i%a!<%?$H$7\e(B
+\e$B$F%0%k!<%WL>$r<u$1<h$k4X?t$G$"$k$3$H$b$G$-$^$9!#$"$k$$$O!"3NG'$r5a$a$k$Y\e(B
+\e$B$-%0%k!<%WL>$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+\e$B%a!<%k$GJV?.$9$k5$$OL5$$$N$K;~$?$^$>$s$6$$$K\e(B R \e$B$r2!$7$F$7$^$&JJ$,$"$k$J\e(B
+\e$B$i$P!"$3$NJQ?t$O$=$s$J$"$J$?$N$?$a$K$"$j$^$9!#\e(B
+
+@item gnus-confirm-treat-mail-like-news
+@vindex gnus-confirm-treat-mail-like-news
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"\e(Bgnus \e$B$O%a!<%k$X$NJV?.;~$K\e(B
+\e$B$b\e(B @code{gnus-confirm-mail-reply-to-news} \e$B$K4p$E$$$?3NG'$r5a$a$^$9!#$3$l\e(B
+\e$B$O%a!<%j%s%0%j%9%H$r%K%e!<%:%0%k!<%W$N$h$&$K07$&$N$KJXMx$G$9!#\e(B
+@end table
+
+@node Posting Server
+@section \e$BEj9F$9$k%5!<%P!<\e(B
+
+\e$B:G?7$N\e(B (\e$B$b$A$m$s!"Hs>o$KCNE*$J\e(B) \e$B5-;v$rAw$j=P$9$?$a$K!"$"$NKbK!$N$h$&\e(B
+\e$B$J\e(B @kbd{C-c C-c} \e$B%-!<$r2!$7$?;~!"$=$l$O$I$3$K$$$/$N$G$7$g$&\e(B?
+
+\e$B?R$M$F$/$l$F$"$j$,$H$&!#$"$J$?$r:($_$^$9!#\e(B
+
+\e$B$=$l$OHs>o$KJ#;($K$J$jF@$^$9!#\e(B
+
+@vindex gnus-post-method
+
+\e$B%K%e!<%9$rEj9F$9$k$H$-!"DL>o\e(B Message \e$B$O\e(B @code{message-send-news} \e$B$r8F$S\e(B
+\e$B=P$7$^$9\e(B (@pxref{News Variables, , News Variables, message-ja, Message
+Manual})\e$B!#IaDL$O!"\e(Bgnus \e$B$O9VFIMQ$HF1$8A*BrJ}K!$r;H$C$FEj9F$7$^$9\e(B (\e$B$3$N$3\e(B
+\e$B$H$O!"$"$J$?$,$?$/$5$s$N%0%k!<%W$r0[$J$C$?%5!<%P!<$G9VFI$7$F$$$k>l9g$K!"\e(B
+\e$B$?$V$sET9g$,NI$$$N$G$9\e(B)\e$B!#$7$+$7!"$"$J$?$,9VFI$7$F$$$k$=$N%5!<%P!<$,Ej9F\e(B
+\e$B$r5v2D$;$:!"FI$`$3$H$N$_$r5v2D$7$F$$$k$N$J$i$P!"$*$=$i$/$"$J$?$N\e(B (\e$BHs>o$K\e(B
+\e$BCNE*$G$H$s$G$b$J$/6=L#?<$$\e(B) \e$B5-;v$rEj9F$9$k$?$a$K!"B>$N%5!<%P!<$r;H$$$?$$\e(B
+\e$B$H;W$&$G$7$g$&!#\e(B@code{gnus-post-method} \e$B$rB>$NJ}K!$K@_Dj$9$k;v$,$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-post-method '(nnspool ""))
+@end lisp
+
+\e$B$5$F!"$3$N@_Dj$r$7$?8e$G%5!<%P!<$,$"$J$?$N5-;v$r5qH]$7$?$j!"%5!<%P!<$,Mn\e(B
+\e$B$A$F$$$?$j$7$?$i!"$I$&$7$?$i$h$$$N$G$7$g$&\e(B? \e$B$3$NJQ?t$r>e=q$-$9$k$?$a$K!"\e(B
+\e$BL?Na\e(B @kbd{C-c C-c} \e$B$K%<%m$G$J$$?t$N@\F,0z?t$rM?$($k;v$G!"Ej9F\e(B
+\e$B$K\e(B ``current'' (\e$B8=:_$N\e(B) \e$B%5!<%P!<$r;H$o$;$k;v!"$9$J$o$A%G%#%U%)%k%H$NF0\e(B
+\e$B:n\e(B (\e$BLuCm\e(B: @code{gnus-post-method} \e$B$N%G%#%U%)%k%HCM$O\e(B @code{current}) \e$B$K\e(B
+\e$BLa$9;v$,$G$-$^$9!#\e(B
+
+\e$B$b$7!"%<%m$r@\F,0z?t$r$=$NL?Na$KM?$($?$J$i\e(B (\e$B$9$J$o$A!"\e(B@kbd{C-u 0 C-c
+C-c})\e$B!"\e(Bgnus \e$B$OEj9F$K$I$NJ}K!$r;H$&$+$r$"$J$?$K?R$M$^$9!#\e(B
+
+@code{gnus-post-method} \e$B$rA*BrJ}K!$N%j%9%H$K$9$k;v$b$G$-$^$9!#$=$N>l9g$O!"\e(B
+gnus \e$B$O>o$KEj9F$K$I$NJ}K!$r;H$&$+$r$"$J$?$K?R$M$^$9!#\e(B
+
+\e$B:G8e$K!"$"$J$?$,$$$D$G$b4pK\$NA*BrJ}K!$r;H$C$FEj9F$7$?$$$N$J$i$P!"$3$NJQ\e(B
+\e$B?t$r\e(B @code{native} \e$B$K$7$F2<$5$$!#\e(B
+
+\e$B%a!<%k$rAw?.$9$k$H$-$K!"\e(BMessage \e$B$O\e(B @code{message-send-mail-function} \e$B$r\e(B
+\e$B8F$S=P$7$^$9!#%G%#%U%)%k%H$N4X\e(B
+\e$B?t\e(B @code{message-send-mail-with-sendmail} \e$B$O5-;v$r=gHVBT$A$KF~\e(B
+\e$B$l\e(B (queuing) \e$B$?$jAw?.$9$k$?$a$K!"%P%$%J%j!<$G\e(B @code{sendmail} \e$B$K%Q%$%W$7\e(B
+\e$B$^$9!#%m!<%+%k%7%9%F%`$,\e(B @code{sendmail} \e$B$G%a!<%k$rAw?.$9$k$h$&$K@_Dj$5\e(B
+\e$B$l$F$$$J$/$F$b!"$"$J$?$,1s3V\e(B @acronym{SMTP} \e$B%5!<%P!<$K@\B3$9$k8"Mx$r;}$C\e(B
+\e$B$F$$$k$J$i$P!"\e(B
+@code{message-send-mail-function} \e$B$r\e(B @code{smtpmail-send-it} \e$B$K@_Dj$9$k\e(B
+\e$B$3$H$,$G$-$^$9!#\e(B@code{smtpmail} \e$B%Q%C%1!<%8$r;H$&$?$a$K@5$7$$@_Dj$,$J$5$l\e(B
+\e$B$F$$$k$+$I$&$+3NG'$7$F2<$5$$!#Nc$G$9\e(B:
+
+@lisp
+(setq message-send-mail-function 'smtpmail-send-it
+      smtpmail-default-smtp-server "YOUR SMTP HOST")
+;; @r{FLIM \e$BHG$N\e(B smtpmail.el \e$B$N$?$a$K!"0J2<$NJQ?t$r@_Dj$9$kI,MQ$,$"$j$^$9!#\e(B}
+;; @r{\e$B$I$A$i$N\e(B smtpmail.el \e$B$,;H$o$l$k$+$O\e(B `load-path' \e$B$K0M$j$^$9!#\e(B}
+(setq smtp-default-smtp-server "YOUR SMTP HOST")
+@end lisp
+
+\e$B$3$l$H;w$?$b$N$K\e(B @code{message-smtpmail-send-it} \e$B$,$"$j$^$9!#\e(B
+ISP \e$B$,\e(B @acronym{POP}-before-@acronym{SMTP} \e$B$NG'>Z$rMW5a$7$F$$$k>l9g$KM-\e(B
+\e$BMQ$G$9!#4X?t\e(B @code{mail-source-touch-pop} \e$B$N@bL@J8$r8+$F$/$@$5$$!#\e(B
+
+\e$BB>$N2DG=$J\e(B @code{message-send-mail-function} \e$B$NA*Br;h\e(B
+\e$B$O\e(B @code{message-send-mail-with-mh},
+@code{message-send-mail-with-qmail} \e$B$*$h$S\e(B @code{feedmail-send-it} \e$B$r4^\e(B
+\e$B$_$^$9!#\e(B
+
+@node Mail and Post
+@section \e$B%a!<%k$HEj9F\e(B
+
+\e$B$3$l$O%a!<%k$r=P$9;v$HEj9F$9$k;v$NN>J}$K4XO"$9$kJQ?t$N%j%9%H$G$9\e(B:
+
+@table @code
+@item gnus-mailing-list-groups
+@findex gnus-mailing-list-groups
+@cindex mailing lists
+
+\e$B$b$7$"$J$?$N%K%e!<%9%5!<%P!<$,K\Ev$K%a!<%j%s%0%j%9%H$+\e(B
+\e$B$i\e(B @acronym{NNTP} \e$B%5!<%P!<$X$N%2!<%H%&%'%$$rDs6!$7$F$$$k$N$G$"$l$P!"$=$l\e(B
+\e$B$i$N%0%k!<%W$OLdBj$J$/FI$a$k$G$7$g$&!#$7$+$74JC1$K$O$=$l$i$KEj9F\e(B/\e$B%U%)%m!<\e(B
+\e$B%"%C%W$9$k$3$H$O$G$-$^$;$s!#0l$D$N2r7hK!$O%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B (@pxref{Group Parameters}) \e$B$K\e(B @code{to-address} \e$B$r2C$($k;v$G$9!#4JC1\e(B
+\e$B$K$G$-$k$N$O!"\e(B@code{gnus-mailing-list-groups} \e$B$r!"K\Ev$K%a!<%j%s%0%j%9%H\e(B
+\e$B$G$"$k$h$&$J%0%k!<%W$K9gCW$9$k@55,I=8=$K@_Dj$9$k$3$H$G$9!#$=$N8e$O!"$9$/\e(B
+\e$B$J$/$H$b!"%a!<%j%s%0%j%9%H$X$N%U%)%m!<%"%C%W$O$?$$$F$$$N$H$-$KF0:n$7$^$9!#\e(B
+\e$B$3$l$i$N%0%k!<%W$KEj9F$9$k;v$O\e(B (@kbd{a}) \e$B$=$l$G$b6lDK$r0z$-5/$3$9$G$7$g\e(B
+\e$B$&$1$I!#\e(B
+
+@item gnus-user-agent
+@vindex gnus-user-agent
+@cindex User-Agent
+
+\e$B$3$NJQ?t$O!"$I$N>pJs$,\e(B User-Agent \e$B%X%C%@!<$KDDNs$5$l$k$+$r@)8f$7$^$9!#\e(B
+\e$B$=$l$O<!$N%7%s%\%k$^$?$OJ8;zNs$N$&$A$N$I$l$+$G$"$k$3$H$,$G$-$^$9\e(B:
+@code{gnus} (Gnus \e$B$N%P!<%8%g%s$N$_\e(B)\e$B!"\e(B
+@code{emacs-gnus} (Emacs \e$B$H\e(B Gnus \e$B$N%P!<%8%g%s$@$1\e(B)\e$B!"\e(B
+@code{emacs-gnus-config} (@code{emacs-gnus} \e$B$HF1$8!\%7%9%F%`9=@.\e(B)\e$B!"\e(B
+@code{emacs-gnus-type} (@code{emacs-gnus}) \e$B$HF1$8!\%7%9%F%`%?%$%W\e(B)\e$B!"\e(B
+@code{gnus-mime-edit} (Gnus \e$B$H\e(B MIME Edit \e$B$J$I$N%P!<%8%g%s\e(B)\e$B!"$^$?$O9%$_$N\e(B
+\e$BJ8;zNs!#$3$l$rJ8;zNs$K$9$k$H$-$O!"@5$7$$%U%)!<%^%C%H$K$J$C$F$$$k$3$H$r3N\e(B
+\e$B$+$a$F2<$5$$\e(B (RFC2616 \e$B;2>H\e(B)\e$B!#\e(B
+@end table
+
+\e$B$"$J$?$O<+J,$,Aw$k%a%C%;!<%8$NDV$j$rD4$Y$kI,MW$,$"$k$+$b$7$l$^$;$s!#$b$7\e(B
+\e$B$/$O!"$b$7<j$GDV$jD4$Y$r$7$?$/$J$$$N$G$"$l$P!"<+F0DV$jD4$Y\e(B
+\e$B$r\e(B @code{ispell} \e$B%Q%C%1!<%8$r;H$&;v$K$h$C$FIU$12C$($k;v$,$G$-$^$9\e(B:
+
+@cindex ispell
+@findex ispell-message
+@lisp
+(add-hook 'message-send-hook 'ispell-message)
+@end lisp
+
+\e$B$b$7$"$J$?$,\e(B @code{ispell} \e$B$N<-=q$r%0%k!<%W$K1~$8$F@Z$jBX$($?$$$J$i$P!"\e(B
+\e$B0J2<$N$h$&$K$9$l$PNI$$$G$7$g$&!#\e(B
+
+@lisp
+(add-hook 'gnus-select-group-hook
+          (lambda ()
+            (cond
+             ((string-match
+               "^de\\." (gnus-group-real-name gnus-newsgroup-name))
+              (ispell-change-dictionary "deutsch"))
+             (t
+              (ispell-change-dictionary "english")))))
+@end lisp
+
+\e$B$"$J$?$NI,MW$K1~$8$FJQ99$7$F2<$5$$!#\e(B
+
+@node Archived Messages
+@section \e$B%a%C%;!<%8$NJ]4I\e(B
+@cindex archived messages
+@cindex sent messages
+
+Gnus \e$B$O$"$J$?$,Aw$C$?%a!<%k$H%K%e!<%9$rCy$a$F$*$/$?$a$N$$$/$D$+$N0c$C$?\e(B
+\e$BJ}K!$rDs6!$7$^$9!#%G%#%U%)%k%H$NJ}K!$O%a%C%;!<%8$rJ]B8$9$k$?$a\e(B
+\e$B$K\e(B @dfn{\e$B;v<B>e$N=q8K%5!<%P!<\e(B}(archive virtual server) \e$B$r;H$$$^$9!#$3$l$r\e(B
+\e$B40A4$K6X;_$7$?$$$N$G$"$l$P!"\e(B
+\e$BJQ?t\e(B @code{gnus-message-archive-group} \e$B$O\e(B @code{nil} \e$B$K$J$k$Y$-$G!"$3$l\e(B
+\e$B$,%G%#%U%)%k%H$G$9!#\e(B
+
+\e$B$"$J$?$,FI$s$G6=L#$r;}$C$?%a%C%;!<%8$r%0%k!<%W$KJ]B8$9$k$K\e(B
+\e$B$O\e(B @kbd{B c} (@code{gnus-summary-copy-article}) \e$B%3%^%s%I$r;2>H$7$F2<$5\e(B
+\e$B$$\e(B (@pxref{Mail Group Commands})\e$B!#\e(B
+
+@vindex gnus-message-archive-method
+@code{gnus-message-archive-method} \e$B$OAw$C$?%a%C%;!<%8$rC_@Q$9$k$?$a$K$I\e(B
+\e$B$N;v<B>e$N%5!<%P!<$r\e(B gnus \e$B$,;H$&$Y$-$+$r;XDj$7$^$9!#%G%#%U%)%k%H$O\e(B:
+
+@lisp
+(nnfolder "archive"
+          (nnfolder-directory   "~/Mail/archive")
+          (nnfolder-active-file "~/Mail/archive/active")
+          (nnfolder-get-new-mail nil)
+          (nnfolder-inhibit-expiry t))
+@end lisp
+
+\e$B$7$+$7!"$I$N%a!<%kA*BrJ}K!$G$b;H$&;v$,$G$-$^\e(B
+\e$B$9\e(B (@code{nnml}, @code{nnmbox} \e$B$J$I$J$I\e(B)\e$B!#$7$+$7\e(B @code{nnfolder} \e$B$O$3$N\e(B
+\e$B$h$&$J;v$r$9$k$N$K$H$F$b9%$^$7$$A*BrJ}K!$G$9!#%G%#%U%)%k%H$N%G%#%l%/%H%j!<\e(B
+\e$BA*Br$r9%$-$G$J$$$J$i$P!"<!$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-message-archive-method
+      '(nnfolder "archive"
+                 (nnfolder-inhibit-expiry t)
+                 (nnfolder-active-file "~/News/sent-mail/active")
+                 (nnfolder-directory "~/News/sent-mail/")))
+@end lisp
+
+@vindex gnus-message-archive-group
+@cindex Gcc
+Gnus \e$B$O30$X=P$F9T$/A4$F$N%a%C%;!<%8$K!"0l$D$+$=$l0J>e$N$=$N%5!<%P!<$N%0\e(B
+\e$B%k!<%W$X8~$+$&\e(B @code{Gcc} \e$BMs$rA^F~$7$^$9!#$I$N%0%k!<%W$r;H$&$+$OJQ\e(B
+\e$B?t\e(B @code{gnus-message-archive-group} \e$B$K$h$C$F7h$^$j$^$9!#\e(B
+
+\e$B$3$NJQ?t$O<!$N$h$&$J;v$r$9$k$?$a$K;H$o$l$^$9\e(B:
+
+@table @asis
+@item \e$BJ8;zNs\e(B
+\e$B%a%C%;!<%8$O$=$N%0%k!<%W$KJ]B8$5$l$^$9!#\e(B
+
+\e$B$"$J$?$O%0%k!<%WL>$KA*BrJ}K!$r4^$a$k$3$H$,$G$-$^$9$,!"$=$&$9$k$H$=$N%a%C\e(B
+\e$B%;!<%8$O\e(B @code{gnus-message-archive-method} \e$B$G;XDj$7$?A*BrJ}K!$G$O$J$/$F!"\e(B
+\e$BBe$o$j$K%0%k!<%WL>$NA*BrJ}K!$GJ]B8$5$l$k$3$H$KCm0U$7$^$7$g$&!#>e$K<($7$?\e(B
+\e$B$h$&$K\e(B @code{gnus-message-archive-method} \e$B$O!"%G%#%U%)%k%HCM$r;}$D$b$N$G\e(B
+\e$B$"$k$H9M$($F2<$5$$!#$G$9$+\e(B
+\e$B$i\e(B @code{gnus-message-archive-group} \e$B$r\e(B @code{"foo"} \e$B$K$7$F$*$1$P!"30$X\e(B
+\e$B=P$F9T$/%a%C%;!<%8$O\e(B @samp{nnfolder+archive:foo} \e$B$KJ]B8$5$l$^$9$,!"$b$7\e(B
+\e$B$"$J$?$,\e(B @code{"nnml:foo"} \e$B$H$$$&CM$r;H$&$H!"\e(B@samp{nnml:foo} \e$B$KJ]B8$5$l\e(B
+\e$B$^$9!#\e(B
+
+@item \e$BJ8;zNs$N%j%9%H\e(B
+\e$B%a%C%;!<%8$O$=$l$i$NA4$F$N%0%k!<%W$KJ]B8$5$l$^$9!#\e(B
+
+@item \e$B@55,I=8=!"4X?t!"MM<0$NO"A[%j%9%H\e(B
+\e$B%-!<$,!X9gCW!Y$9$k$H!"7k2L$,;H$o$l$^$9!#\e(B
+
+@item @code{nil}
+\e$B%a%C%;!<%8$NJ]B8$O9T$o$l$^$;$s!#$3$l$,%G%#%U%)%k%H$G$9!#\e(B
+@end table
+
+\e$B;n$7$F$_$^$7$g$&\e(B:
+
+@samp{MisK} \e$B$H8F$P$l$k0l$D$N%0%k!<%W$KJ]B8$9$k$J$i$P\e(B:
+@lisp
+(setq gnus-message-archive-group "MisK")
+@end lisp
+
+\e$BFs$D$N%0%k!<%W!"\e(B@samp{MisK} \e$B$H\e(B @samp{safe} \e$B$KJ]B8$9$k$J$i$P\e(B:
+@lisp
+(setq gnus-message-archive-group '("MisK" "safe"))
+@end lisp
+
+\e$B$I$N%0%k!<%W$K$$$k$+$K$h$C$F0c$C$?%0%k!<%W$KJ]B8$9$k$J$i\e(B:
+@lisp
+(setq gnus-message-archive-group
+      '(("^alt" "sent-to-alt")
+        ("mail" "sent-to-mail")
+        (".*" "sent-to-misc")))
+@end lisp
+
+\e$B$b$C$HJ#;($J$b$N\e(B:
+@lisp
+(setq gnus-message-archive-group
+      '((if (message-news-p)
+            "misc-news"
+          "misc-mail")))
+@end lisp
+
+\e$BA4$F$N%K%e!<%9%a%C%;!<%8$r0l$D$N%U%!%$%k$KJ]B8$7$F!"%a!<%k%a%C%;!<%8$r0l\e(B
+\e$B7n$K$D$-0l$D$N%U%!%$%k$KJ]B8$9$k$K$O\e(B:
+
+@lisp
+(setq gnus-message-archive-group
+      '((if (message-news-p)
+            "misc-news"
+          (concat "mail." (format-time-string
+                           "%Y-%m" (current-time))))))
+@end lisp
+
+@c (XEmacs 19.13 \e$B$K$O\e(B @code{format-time-string} \e$B$O$"$j$^$;$s$N$G!"$=\e(B
+@c \e$B$N\e(B @code{gnus-message-archive-group} \e$B$N$?$a$K0c$C$?CM$r;H$o$J$1$l$P$J$j\e(B
+@c \e$B$^$;$s!#\e(B)
+
+\e$B:#$d!"%a%C%;!<%8$rAw$k$H!"$=$l$OE,@Z$J%0%k!<%W$KJ]B8$5$l$^$9!#\e(B(\e$B$b$7FCDj\e(B
+\e$B$N%a%C%;!<%8$KBP$7$FJ]B8$r$7$?$/$J$$$N$G$"$l$P!"A^F~$5$l$?\e(B @code{Gcc} \e$BMs\e(B
+\e$B$r<h$j=|$$$F$/$@$5$$!#\e(B) \e$BJ]4I%0%k!<%W$O<!$K\e(B gnus \e$B$r5/F0$7$?$H$-$+!"<!$K%0\e(B
+\e$B%k!<%W%P%C%U%!$G\e(B @kbd{F} \e$B$r2!$7$?$H$-$K%0%k!<%W%P%C%U%!$K8=$l$^$9!#B>$N\e(B
+\e$B%0%k!<%W$HF1$8$h$&$K$=$N%0%k!<%W$KF~$C$F!"5-;v$rFI$`;v$,$G$-$^$9!#$=$N%0\e(B
+\e$B%k!<%W$,K\Ev$KBg$-$/$J$C$F7y$K$J$C$?$i!"$J$K$+NI$$$b$N$K$=$NL>A0$rJQ99$9\e(B
+\e$B$k;v$,$G$-$^$9\e(B (\e$B%0%k!<%W%P%C%U%!$G\e(B @kbd{G r} \e$B$r;H$&;v$K$h$C$F\e(B) \e$B!=!=\e(B
+@samp{misc-mail-september-1995} \e$B$dB>$N$b$K!#?7$7$$%a%C%;!<%8$O8E$$\e(B (\e$B:#$O\e(B
+\e$B6u$K$J$C$?\e(B) \e$B%0%k!<%W$KN/$a$i$l$^$9!#\e(B
+
+\e$B0J>e$,Aw$C$?%a%C%;!<%8$rJ]4I$9$k%G%#%U%)%k%H$NJ}K!$G$9!#\e(BGnus \e$B$O%G%#%U%)\e(B
+\e$B%k%H$NJ}K!$r9%$-$G$O$J$$?M$K$O0c$C$?$d$jJ}$r4+$a$F$$$^$9!#$=$N$h$&$J>l9g\e(B
+\e$B$O!"\e(B@code{gnus-message-archive-group} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$Y$-$G$9!#\e(B
+\e$B$3$l$OJ]4I$r$7$J$$$h$&$K$7$^$9!#\e(B
+
+@table @code
+@item gnus-outgoing-message-group
+@vindex gnus-outgoing-message-group
+\e$BA4$F$N30$K$$$/%a%C%;!<%8$O$3$N%0%k!<%W$KF~$l$i$l$^$9!#$b$7A4$F$N30$K9T$/\e(B
+\e$B%a!<%k$H5-;v$r%0%k!<%W\e(B @samp{nnml:archive} \e$B$KJ]4I$7$?$$$N$G$"$l$P!"$3$N\e(B
+\e$BJQ?t$r$=$NCM$K@_Dj$9$k;v$,$G$-$^$9!#$3$NJQ?t$O%0%k!<%WL>$N%j%9%H$G$"$k;v\e(B
+\e$B$b$G$-$^$9!#\e(B
+
+\e$B$b$7$=$l$>$l$N%a%C%;!<%8$r$I$N%0%k!<%W$KF~$l$k$+$r$b$C$H@)8f$7$?$$$N$G$"\e(B
+\e$B$l$P!"$3$NJQ?t$r8=:_$N%K%e!<%9%0%k!<%WL>$rD4$Y$F!"E,@Z$J%0%k!<%WL>\e(B (\e$B$b$7\e(B
+\e$B$/$OL>A0$N%j%9%H\e(B) \e$B$rJV$94X?t$K@_Dj$9$k;v$,$G$-$^$9!#\e(B
+
+\e$B$3$NJQ?t$O\e(B @code{gnus-message-archive-group} \e$B$NBe$o$j$K;H$&;v$,$G$-$^$9\e(B
+\e$B$,!"8e<T$NJ}$,9%$^$7$$J}K!$G$9!#\e(B
+
+@item gnus-gcc-mark-as-read
+@vindex gnus-gcc-mark-as-read
+\e$B$b$7Hs\e(B@code{nil}\e$B$J$i!"\e(B@code{Gcc} \e$B$N5-;v$K4{FI$N0u$rIU$1$^$9!#\e(B
+
+@c @item gnus-gcc-externalize-attachments
+@c @vindex gnus-gcc-externalize-attachments
+@c If @code{nil}, attach files as normal parts in Gcc copies; if a regexp
+@c and matches the Gcc group name, attach files as external parts; if it is
+@c @code{all}, attach local files as external parts; if it is other
+@c non-@code{nil}, the behavior is the same as @code{all}, but it may be
+@c changed in the future.
+@end table
+
+@node Posting Styles
+@section \e$BEj9FMM<0\e(B
+@cindex posting styles
+@cindex styles
+
+\e$B$=$l$i$O$9$Y$FJQ?t$G!"$=$l$O;d$NF,$r1K$,$;$^$9!#\e(B
+
+\e$B$=$l$G!"$J$<$I$N%0%k!<%W$KEj9F$9$k$+$K$h$C$F0c$C\e(B
+\e$B$?\e(B @code{Organization} \e$B$H=pL>$rK>$`$N$G$7$g$&$+\e(B? \e$B$=$7$F!"$"$J$?$O2HDm$N\e(B
+\e$B%^%7%s$H?&>l$N%^%7%s$NN>J}$+$iEj9F$7$F!"0c$C$?\e(B @code{From} \e$B9T$d$=$NB>$N\e(B
+\e$B$b$N$rK>$`$N$G$9$+\e(B?
+
+@vindex gnus-posting-styles
+\e$B$=$N$h$&$J;v$r$9$kJ}K!$N0l$D$OJQ99$5$l$kI,MW$N$"$kJQ?t$rJQ99$9$k8-$$%U%C\e(B
+\e$B%/$r=q$/;v$G$9!#$=$l$O>/$7B`6~$J$N$G!"MxMQ<T$K$3$l$i$N;v$r<j7Z$JO"A[%j%9\e(B
+\e$B%H$G;XDj$9$k$H$$$&$9$P$i$7$$CeA[$K$?$I$jCe$$$??M$,$$$^$7$?!#$3$l$OJQ\e(B
+\e$B?t\e(B @code{gnus-posting-styles} \e$B$NNc$G$9\e(B:
+
+@lisp
+((".*"
+   (signature "Peace and happiness")
+   (organization "What me?"))
+ ("^comp"
+  (signature "Death to everybody"))
+ ("comp.emacs.i-love-it"
+  (organization "Emacs is it")))
+@end lisp
+
+\e$B$3$NNc$+$i?dB,$5$l$k$h$&$K!"$3$NO"A[%j%9%H$O$$$/$D$+\e(B
+\e$B$N\e(B @dfn{\e$BMM<0\e(B} (style) \e$B$+$i$J$C$F$$$^$9!#$=$l$>$l$NMM<0$O:G=i$NMWAG$,2?$i\e(B
+\e$B$+$N7A$G\e(B ``\e$B9gCW\e(B'' \e$B$7$?$H$-$KE,MQ$5$l$^$9!#O"A[%j%9%HA4BN$O:G=i$+$i:G8e$^\e(B
+\e$B$GH?I|$7$F<B9T$5$l!"$=$l$>$l$N9gCW$,E,MQ$5$l$^$9!#$3$l$O!"8e$NMM<0$NB0@-\e(B
+\e$B$,A0$K9gCW$7$?MM<0$NB0@-$r>e=q$-$9$k$H8@$&;v$G$9!#$G$9$+$i!"\e(B
+@samp{comp.programming.literate} \e$B$O!"=p\e(B
+\e$BL>\e(B @samp{Death to everybody} \e$B$H\e(B @code{Organization} \e$B%X%C\e(B
+\e$B%@!<\e(B @samp{What me?} \e$B$r;}$A$^$9!#\e(B
+
+\e$B$=$l$>$l$NMM<0$N:G=i$NMWAG$O\e(B @code{\e$B9gCW\e(B} (match) \e$B$H8F$P$l$^$9!#$b$7$=$l\e(B
+\e$B$,J8;zNs$G$"$l$P!"\e(Bgnus \e$B$O$=$l$r%0%k!<%WL>$K@55,I=8=$H$7$F9gCWA`:n$r9T$$\e(B
+\e$B$^$9!#\e(B@code{(header \e$B9gCW\e(B \e$B@55,I=8=\e(B)} \e$B$H$$$&MM<0$G$"$l$P!"\e(Bgnus \e$B$O85$N5-;v\e(B
+\e$B$NCf$+$iL>A0$,9gCW$9$k%X%C%@!<$rC5$7!"$=$l$r@55,I=8=$HHf3S$7$^$9!#9gCW$H\e(B
+\e$B@55,I=8=$OJ8;zNs$G$9!#\e(B(\e$B85$N5-;v$H$OJV?.$^$?$O%U%)%m!<%"%C%W$7$h$&$H$7$F\e(B
+\e$B$$$k$b$N$G$9!#JV?.$"$k$$$O%U%)%m!<%"%C%W$r:n@.$7$F$$$J$1$l$P!"9gCW$9$k$b\e(B
+\e$B$N$O2?$b$"$j$^$;$s!#\e(B) \e$B$b$7\e(B @code{\e$B9gCW\e(B} \e$B$,4X?t$N%7%s%\%k$G$"$l$P!"$=$N4X\e(B
+\e$B?t$,0z?tL5$7$G8F$P$l$^$9!#$=$l$,JQ?t$N%7%s%\%k$G$"$l$P!"$=$NJQ?t$,;2>H$5\e(B
+\e$B$l$^$9!#$=$l$,%j%9%H$G$"$l$P!"$=$N%j%9%H$,\e(B @code{\e$BI>2A\e(B} \e$B$5$l$^$9!#$I$N>l\e(B
+\e$B9g$G$b!"$3$l$,\e(B @code{nil}\e$B$G$J$$CM$r5"$;$P!"MM<0$O\e(B @code{\e$B9gCW$7$?\e(B} \e$B$H8@$$\e(B
+\e$B$^$9!#\e(B
+
+\e$B$=$l$>$l$NMM<0$OG$0U$NNL$N\e(B @dfn{\e$BB0@-\e(B} \e$B$r;}$D;v$,$G$-$^$9!#$=$l$>$l$NB0@-\e(B
+\e$B$O\e(B @code{(@var{name} @var{value})} \e$B$NBP$K$h$j@.$jN)$C$F$$$^$9!#B0@-L>$O!"\e(B
+\e$B0J2<$N$I$l$+$G$"$k;v$,$G$-$^$9!#\e(B
+
+@itemize @bullet
+@item @code{signature}
+@item @code{signature-file}
+@item @code{x-face-file}
+@item @code{address}, @code{user-mail-address} \e$B$r>e=q$-$7$^$9\e(B
+@item @code{name}, @code{(user-full-name)} \e$B$r>e=q$-$7$^$9\e(B
+@item @code{body}
+@end itemize
+
+\e$BB0@-L>$OJ8;zNs$^$?$O%7%s%\%k$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"$3$l$O%X%C%@!<\e(B
+\e$BL>$H$7$F;H$o$l!"$=$NCM$,5-;v$N%X%C%@!<$KA^F~$5$l$^$9!#$b$7B0@-L>\e(B
+\e$B$,\e(B @code{nil} \e$B$@$C$?$i$=$N%X%C%@!<L>$O:o=|$5$l$^$9!#$b$7B0@-L>\e(B
+\e$B$,\e(B @code{eval} \e$B$@$C$?$i$=$NMM<0$,I>2A$5$l!"7k2L$O<N$F$i$l$^$9!#\e(B
+
+\e$BB0@-CM$OJ8;zNs\e(B (\e$B$=$N$^$^;H$o$l$^$9\e(B)\e$B!"0z?t$NL5$$4X?t\e(B (\e$BJV$jCM$,;H$o$l$^$9\e(B)\e$B!"\e(B
+\e$BJQ?t\e(B (\e$B$=$NCM$,;H$o$l$^$9\e(B) \e$B$^$?$O%j%9%H\e(B (\e$B$=$l$O\e(B @code{\e$BI>2A\e(B} \e$B$5$l$F!"JV$j\e(B
+\e$BCM$,;H$o$l$^$9\e(B) \e$B$G$"$k;v$,$G$-$^$9!#4X?t$O%;%C%H%"%C%W$5$l$?%a%C%;!<%8%P%C\e(B
+\e$B%U%!$G8F$P$l\e(B (@code{eval} \e$B$5$l\e(B) \e$B$^$9!#8=:_$N5-;v$N%X%C%@!<$OJQ\e(B
+\e$B?t\e(B @code{message-reply-headers} \e$B$+$iF@$i$l$^$9!#$3$l$O\e(B number subject
+from date id references chars lines xref extra \e$B$N3F%X%C%@!<$+$i@.$k%Y%/\e(B
+\e$B%H%k$G$9!#\e(B
+
+@vindex message-reply-headers
+
+\e$B$b$7!":n@.$7$h$&$H$7$F$$$k%a%C%;!<%8$,%K%e!<%95-;v$+%a!<%k%a%C%;!<%8$G$"\e(B
+\e$B$k$+$rD4$Y$?$$$H$-$O!"Fs$D$N4X\e(B
+\e$B?t\e(B @code{message-news-p} \e$B$H\e(B @code{message-mail-p} \e$B$r;H$&$3$H$K$h$C$FCN$k\e(B
+\e$B;v$,$G$-$^$9!#\e(B
+
+@findex message-mail-p
+@findex message-news-p
+
+\e$B$=$7$F!"$3$l$ONc$G$9\e(B:
+
+@lisp
+(setq gnus-posting-styles
+      '((".*"
+         (signature-file "~/.signature")
+         (name "User Name")
+         ("X-Home-Page" (getenv "WWW_HOME"))
+         (organization "People's Front Against MWM"))
+        ("^rec.humor"
+         (signature my-funny-signature-randomizer))
+        ((equal (system-name) "gnarly")  ;; @r{\e$BMM<0\e(B}
+         (signature my-quote-randomizer))
+        (message-news-p        ;; @r{\e$B4X?t%7%s%\%k\e(B}
+         (signature my-news-signature))
+        (window-system         ;; @r{\e$BJQ?t%7%s%\%k\e(B}
+         ("X-Window-System" (format "%s" window-system)))
+        ;; @r{Lars \e$B$5$s$KJV;v$r$9$k$H$-$O\e(B}
+        ;; @r{Organization \e$B%X%C%@!<$rIU$1$h$&!#\e(B}
+        ((header "to" "larsi.*org")
+         (Organization "Somewhere, Inc."))
+        ((posting-from-work-p) ;; @r{\e$B%f!<%6!<$,Dj5A$7$?4X?t\e(B}
+         (signature-file "~/.work-signature")
+         (address "user@@bar.foo")
+         (body "You are fired.\n\nSincerely, your boss.")
+         (organization "Important Work, Inc"))
+        ("nnml:.*"
+         (From (save-excursion
+                 (set-buffer gnus-article-buffer)
+                 (message-fetch-field "to"))))
+        ("^nn.+:"
+         (signature-file "~/.mail-signature"))))
+@end lisp
+
+@samp{nnml:.*} \e$B$N5,B'$O!"$"$J$?$,=P$9$9$Y$F$NJV;v$N\e(B @code{To} \e$B%"%I%l%9\e(B
+\e$B$r\e(B @code{From} \e$B%"%I%l%9$H$7$F;H$&$3$H$r0UL#$7$^$9!#$3$l$O!"$"$J$?$,$?$/\e(B
+\e$B$5$s$N%a!<%j%s%0%j%9%H$K;22C$7$F$$$k>l9g$KJXMx$G$7$g$&!#\e(B
+
+\e$BJQ?t\e(B @code{gnus-named-posting-styles} \e$B$r@_Dj$9$k$3$H$G!"$h$/MxMQ$9$kEj9F\e(B
+\e$BMM<0$KL>A0$r$D$1$i$l$^$9!#35N,%P%C%U%!$G\e(B @kbd{S P} \e$B$H$9$k$3$H$G!"Ej9F;~\e(B
+\e$B$KG$0U$NMM<0$rA*Br$7$^$9!#\e(B@code{gnus-named-posting-styles} \e$B$OL>A0$HMM<0\e(B
+\e$B$+$i$J$kO"A[%j%9%H$G$9!#\e(B@code{gnus-posting-styles} \e$B$K4^$^$l$kB0@-L>\e(B
+\e$B$,\e(B @code{import} \e$B$@$C$?$i!"$=$NCM$G\e(B @code{gnus-named-posting-styles} \e$B$r\e(B
+\e$B0z$$$F!"B0@-CM$r$=$3$KE83+$7$^$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@lisp
+(setq gnus-named-posting-styles
+      '(("Default"
+         (signature-file "~/.signature")
+         (name "User Name")
+         ("X-Home-Page" (getenv "WWW_HOME"))
+         (organization "People's Front Against MWM"))
+        ("Emacs"
+         (import "Default")
+         (organization "The Church of Emacs"))))
+@end lisp
+
+"Emacs" \e$B$HL>IU$1$i$l$?MM<0$O!"\e(B@code{organization} \e$B0J30$NB0@-\e(B
+\e$B$r\e(B "Default" \e$B$+$i0z$-7Q$.$^$9!#\e(B
+
+
+@node Drafts
+@section \e$B2<=q$-\e(B
+@cindex drafts
+
+\e$B$b$7%a%C%;!<%8\e(B (\e$B%a!<%k$b$7$/$O%K%e!<%9\e(B) \e$B$r=q$$$F$$$k$H$-$K!"FMA3%*!<%V%s\e(B
+\e$B$K%9%F!<%-$,F~$C$F$$$k\e(B (\e$B$b$7$/$O$"$J$?$,$H!<$C$F$b$9$4$$:Z?)<g5A<T$G!"2?\e(B
+\e$B$+$N%Z!<%9%H$,%U!<%I%W%m%;%C%5!<$KF~$C$F$$$k\e(B) \e$B;v$r;W$$=P$7$?$J$i!"=q$$$F\e(B
+\e$B$$$k%a%C%;!<%8$rJ]B8$9$kJ}K!$,$"$l$PNI$$$H;W$&$G$7$g$&!#$=$&$9$l$P!"$$$D\e(B
+\e$B$+JL$NF|$KJT=8$rB3$1$k;v$,$G$-!"$=$l$,40@.$7$?$H;W$C$?$H$-$KAw$k;v$,$G$-\e(B
+\e$B$^$9!#\e(B
+
+\e$B$($'!"?4G[$7$J$$$G$/$@$5$$!#\e(BGnus \e$B$N%a!<%k$HEj9FL?Na$r;H$&2?$i$+$N%a%C%;!<\e(B
+\e$B%8$r=q$-;O$a$?$H$-$K<j$KF~$k%P%C%U%!$O!"<+F0E*$KFCJL$J\e(B @dfn{draft} \e$B%0%k!<\e(B
+\e$B%W$K4XO"IU$1$i$l$^$9!#IaDL$NJ}K!$G%P%C%U%!$rJ]B8$9$l$P\e(B (\e$B$?$H$($P!"\e(B
+@kbd{C-x C-s})\e$B!"$=$N5-;v$O$=$3$KJ]B8$5$l$^$9!#\e(B(\e$B<+F0J]B8%U%!%$%k$b2<=q$-\e(B
+\e$B%0%k!<%W\e(B (draft group) \e$B$K9T$-$^$9!#\e(B)
+
+@cindex nndraft
+@vindex nndraft-directory
+\e$B2<=q$-%0%k!<%W$O\e(B @samp{nndraft:drafts} \e$B$H8F$P$l$kFCJL$J%0%k!<%W$G$9\e(B (\e$B$b\e(B
+\e$B$7$"$J$?$,A4$F$rCN$i$J$1$l$P$J$i$J$$$N$G$"$l$P!"$=$l$O\e(B @code{nndraft} \e$B%0\e(B
+\e$B%k!<%W$H$7$F<BAu$5$l$F$$$^$9\e(B)\e$B!#JQ?t\e(B @code{nndraft-directory} \e$B$O$=$N%U%!\e(B
+\e$B%$%k$r\e(B @code{nndraft} \e$B$,$I$3$KJ]4I$9$k$Y$-$+$r;XDj$7$^$9!#$3$N%0%k!<%W$,\e(B
+\e$BFCJL$G$"$k$H$$$&$N$O!"$=$NCf$N5-;v$r1J2D;k$K$7$?$j4{FI$N0u$rIU$1$?$j$G$-\e(B
+\e$B$J$$$+$i$G$9!=!=%0%k!<%W$NA4$F$N5-;v$O1J5W$KL$FI$G$9!#\e(B
+
+\e$B$b$7%0%k!<%W$,B8:_$7$J$$$J$i!"$=$l$O:n@.$5$l!"9XFI$5$l$^$9!#%0%k!<%W%P%C\e(B
+\e$B%U%!$+$i$=$l$r>C$75n$kM#0l$NJ}K!$O!"$=$l$rL$9XFI$K$9$k$3$H$G$9!#2<=q$-%0\e(B
+\e$B%k!<%W$NFCJL$NFC@-$O%0%k!<%WFC@-\e(B (@pxref{Group Parameters}) \e$B$K$h$C$F@8$8!"\e(B
+\e$B$=$l$,<:$o$l$F$7$^$&$HB>$N%0%k!<%W$N$h$&$K?6$kIq$&$h$&$K$J$j$^$9!#$3$l$O\e(B
+\e$B0J2<$N%3%^%s%I$,;H$($J$$$3$H$r0UL#$7$^$9!#$=$N%0%k!<%W$NFCJL$NFC@-$rI|3h\e(B
+\e$B$5$;$k4JC1$JJ}K!$O!"\e(B@kbd{C-k} \e$B$G$=$N%0%k!<%W$r:o=|$7$F$+$i\e(B gnus \e$B$r:F5/F0\e(B
+\e$B$9$k$3$H$G$9!#$=$N%0%k!<%W$NFbMFJ*$O<:$o$l$^$;$s!#\e(B
+
+@c @findex gnus-dissociate-buffer-from-draft
+@c @kindex C-c M-d (Mail)
+@c @kindex C-c M-d (Post)
+@c @findex gnus-associate-buffer-with-draft
+@c @kindex C-c C-d (Mail)
+@c @kindex C-c C-d (Post)
+@c If you're writing some super-secret message that you later want to
+@c encode with PGP before sending, you may wish to turn the auto-saving
+@c (and association with the draft group) off.  You never know who might be
+@c interested in reading all your extremely valuable and terribly horrible
+@c and interesting secrets.  The @kbd{C-c M-d}
+@c (@code{gnus-dissociate-buffer-from-draft}) command does that for you.
+@c If you change your mind and want to turn the auto-saving back on again,
+@c @kbd{C-c C-d} (@code{gnus-associate-buffer-with-draft} does that.
+@c
+@c @vindex gnus-use-draft
+@c To leave association with the draft group off by default, set
+@c @code{gnus-use-draft} to @code{nil}.  It is @code{t} by default.
+
+@findex gnus-draft-edit-message
+@kindex D e (\e$B2<=q$-\e(B)
+\e$B5-;v$NJT=8$rB3$1$?$$$H$-$O!"2<=q$-%0%k!<%W$KF~$C\e(B
+\e$B$F\e(B @kbd{D e} (@code{gnus-draft-edit-message}) \e$B$r2!$9$@$1$G$9!#$"$J$?$,;D\e(B
+\e$B$7$?>uBV$N%P%C%U%!$K0\F0$7$^$9!#\e(B
+
+\e$B5qH]$5$l$?5-;v$b$3$N2<=q$-%0%k!<%W$KF~$l$i$l$^\e(B
+\e$B$9\e(B (@pxref{Rejected Articles})\e$B!#\e(B
+
+@findex gnus-draft-send-all-messages
+@kindex D s (Draft)
+@findex gnus-draft-send-message
+@kindex D S (Draft)
+\e$B$=$l0J>eJT=8$7$J$$$GEj9F\e(B (\e$B$b$7$/$O%a!<%k\e(B) \e$B$7$?$$5qH]$5$l$?%a%C%;!<%8$,$?\e(B
+\e$B$/$5$s$"$k$N$G$"$l$P!"L?Na\e(B @kbd{D s} \e$B$r;H$&;v$,$G$-$^$9!#$3$NL?Na$O%W%m\e(B
+\e$B%;%9\e(B/\e$B@\F,0z?t$N=,47$rM}2r$7$^$9\e(B (@pxref{Process/Prefix})\e$B!#L?\e(B
+\e$BNa\e(B @kbd{D S} (@code{gnus-draft-send-all-messages}) \e$B$O%P%C%U%!$NA4$F$N%a%C\e(B
+\e$B%;!<%8$rAw$j=P$7$^$9!#\e(B
+
+@findex gnus-draft-toggle-sending
+@kindex D t (Draft)
+\e$BAw$j$?$/$J$$%a%C%;!<%8$,$$$/$D$+$"$k$N$G$"$l$P!"L?\e(B
+\e$BNa\e(B @kbd{D t} (@code{gnus-draft-toggle-sending}) \e$B$r;H$C$F%a%C%;!<%8$rG[Aw\e(B
+\e$BIT2D$N0u$rIU$1$k;v$,$G$-$^$9!#$3$l$O@Z$jBX$(L?Na$G$9!#\e(B
+
+@node Rejected Articles
+@section \e$B5qH]$5$l$?5-;v\e(B
+@cindex rejected articles
+
+\e$B;~!9%K%e!<%9%5!<%P!<$O5-;v$r5qH]$7$^$9!#$*$=$i$/%5!<%P!<$O$"$J$?$N4i$r9%\e(B
+\e$B$-$G$O$J$$$N$G$7$g$&!#$*$=$i$/Mn$A9~$s$G$$$k$N$G$7$g$&!#$*$=$i\e(B
+\e$B$/\e(B @emph{\e$B0-Kb\e(B (demon) \e$B$,$$$k$N$G$7$g$&\e(B}\e$B!#$*$=$i$/0zMQJ8$rF~$l$9$.$?$N$G\e(B
+\e$B$7$g$&!#$*$=$i$/%G%#%9%/$,0lGU$@$C$?$N$G$7$g$&!#$*$=$i$/%5!<%P!<$,Mn$A$F\e(B
+\e$B$$$?$N$G$7$g$&!#\e(B
+
+\e$B$3$l$i$N>u67$O!"$b$A$m$s!"40A4$K\e(B gnus \e$B$N07$($kHO0O30$G$9!#\e(B(Gnus \e$B$O!"$b$A\e(B
+\e$B$m$s!"$"$J$?$N308+$r0&$7$F$*$j!"$$$D$b5!7y$,NI$/!"Cf$rHt$S2s$kE7;H$,$$$F!"\e(B
+\e$B$I$l$/$i$$0zMQJ8$,4^$^$l$F$$$h$&$H5$$K$;$:!"0lGU$K$J$C$?$j!"Mn$C$3$A$?$j\e(B
+\e$B$7$^$;$s!#\e(B) \e$B$G$9$+$i!"\e(Bgnus \e$B$O$3$l$i$N5-;v$r8e$G%5!<%P!<$N5$J,$,$h$/$J$k\e(B
+\e$B$^$GJ]B8$7$^$9!#\e(B
+
+\e$B5qH]$5$l$?5-;v$O<+F0E*$KFCJL$J2<=q$-%0%k!<%W\e(B (@pxref{Drafts}) \e$B$KF~$l$i$l\e(B
+\e$B$^$9!#%5!<%P!<$,La$C$F$-$?$J$i!"IaDL$O$=$N%0%k!<%W$KF~$C$FA4$F$N5-;v$rAw\e(B
+\e$B$j$^$9!#\e(B
+
+@ignore
+@node Signing and encrypting
+@section Signing and encrypting
+@cindex using gpg
+@cindex using s/mime
+@cindex using smime
+
+Gnus can digitally sign and encrypt your messages, using vanilla
+@acronym{PGP} format or @acronym{PGP/MIME} or @acronym{S/MIME}.  For
+decoding such messages, see the @code{mm-verify-option} and
+@code{mm-decrypt-option} options (@pxref{Security}).
+
+@vindex gnus-message-replysign
+@vindex gnus-message-replyencrypt
+@vindex gnus-message-replysignencrypted
+Often, you would like to sign replies to people who send you signed
+messages.  Even more often, you might want to encrypt messages which
+are in reply to encrypted messages.  Gnus offers
+@code{gnus-message-replysign} to enable the former, and
+@code{gnus-message-replyencrypt} for the latter.  In addition, setting
+@code{gnus-message-replysignencrypted} (on by default) will sign
+automatically encrypted messages.
+
+Instructing @acronym{MML} to perform security operations on a
+@acronym{MIME} part is done using the @kbd{C-c C-m s} key map for
+signing and the @kbd{C-c C-m c} key map for encryption, as follows.
+
+@table @kbd
+
+@item C-c C-m s s
+@kindex C-c C-m s s (Message)
+@findex mml-secure-message-sign-smime
+
+Digitally sign current message using @acronym{S/MIME}.
+
+@item C-c C-m s o
+@kindex C-c C-m s o (Message)
+@findex mml-secure-message-sign-pgp
+
+Digitally sign current message using @acronym{PGP}.
+
+@item C-c C-m s p
+@kindex C-c C-m s p (Message)
+@findex mml-secure-message-sign-pgp
+
+Digitally sign current message using @acronym{PGP/MIME}.
+
+@item C-c C-m c s
+@kindex C-c C-m c s (Message)
+@findex mml-secure-message-encrypt-smime
+
+Digitally encrypt current message using @acronym{S/MIME}.
+
+@item C-c C-m c o
+@kindex C-c C-m c o (Message)
+@findex mml-secure-message-encrypt-pgp
+
+Digitally encrypt current message using @acronym{PGP}.
+
+@item C-c C-m c p
+@kindex C-c C-m c p (Message)
+@findex mml-secure-message-encrypt-pgpmime
+
+Digitally encrypt current message using @acronym{PGP/MIME}.
+
+@item C-c C-m C-n
+@kindex C-c C-m C-n (Message)
+@findex mml-unsecure-message
+Remove security related @acronym{MML} tags from message.
+
+@end table
+
+@xref{Security, ,Security, message, Message Manual}, for more information.
+
+@end ignore
+@node Select Methods
+@chapter \e$BA*BrJ}K!\e(B
+@cindex foreign groups
+@cindex select methods
+
+@dfn{\e$B30It%0%k!<%W\e(B} (foreign group) \e$B$H$O!"IaDL\e(B (\e$B$b$7$/$O%G%#%U%)%k%H\e(B) \e$B$N\e(B
+\e$BJ}K!$GFI$^$l$J$$%0%k!<%W$N;v$G$9!#Nc$($P!"$=$l$O0c$C$?\e(B @acronym{NNTP} \e$B%5!<\e(B
+\e$B%P!<$N%0%k!<%W$G$"$C$?$j!";v<B>e$N%0%k!<%W$G$"$C$?$j!"8D?ME*$J%a!<%k%0%k!<\e(B
+\e$B%W$G$"$C$?$j$9$k$G$7$g$&!#\e(B
+
+\e$B30It%0%k!<%W\e(B (\e$B$b$7$/$O!"K\Ev$KA4$F%0%k!<\e(B
+\e$B%W\e(B) \e$B$O\e(B @dfn{\e$BL>A0\e(B} \e$B$H\e(B @dfn{\e$BA*BrJ}K!\e(B} \e$B$G;XDj$5$l$^$9!#8e<T$r@h$KNc$K=P$9$H!"\e(B
+\e$BA*BrJ}K!$O:G=i$NMWAG$,$I$N%P%C%/%(%s%I$r;H$&$+\e(B (\e$B$?$H$($P!"\e(B@code{nntp},
+@code{nnspool}, @code{nnml}) \e$B$G!"Fs$D$a$NMWAG$,\e(B @dfn{\e$B%5!<%P!<L>\e(B} \e$B$G$"$k\e(B
+\e$BO"A[%j%9%H$G$9!#A*BrJ}K!$K$O!"$=$NEv$N%P%C%/%(%s%I$K$H$C$FFCJL$N0UL#$r;}\e(B
+\e$B$DCM$G$"$kDI2C$NMWAG$,$"$k$+$bCN$l$^$;$s!#\e(B
+
+\e$BA*BrJ}K!$O\e(B @dfn{\e$B;v<B>e$N%5!<%P!<\e(B} \e$B$rDj5A$9$k$H8@$&$3$H$,$G$-$k$+$b$7$l$^\e(B
+\e$B$;$s\e(B---\e$B$G$9$+$i;d$?$A$O$A$g$&$I$=$l$r$7$^$7\e(B
+\e$B$?\e(B (@pxref{Server Buffer})\e$B!#\e(B
+
+\e$B%0%k!<%W$N\e(B @dfn{\e$BL>A0\e(B} \e$B$O%P%C%/%(%s%I$,%0%k!<%W$rG'<1$9$kL>A0$G$9!#\e(B
+
+\e$B$?$H$($P!"\e(B@acronym{NNTP} \e$B%5!<%P!<$N%0%k!<%W\e(B @samp{soc.motss} \e$B$OL>\e(B
+\e$BA0\e(B @samp{soc.motss} \e$B$HA*BrJ}K!\e(B @code{(nntp "some.where.edu")} \e$B$r;}$A$^$9!#\e(B
+@code{nntp} \e$B%P%C%/%(%s%I$O$3$N%0%k!<%W$r\e(B @samp{soc.motss} \e$B$H$7$FCN$C$F$$\e(B
+\e$B$k$@$1$G$9$,!"\e(Bgnus \e$B$O$3$N%0%k!<%W\e(B
+\e$B$r\e(B @samp{nntp+some.where.edu:soc.motss}\e$B$H8F$S$^$9!#\e(B
+
+\e$B$b$A$m$s!"0c$C$?J}K!$OA4$F$=$lFCM-$N$b$N$,$"$j$^$9!#\e(B
+
+@menu
+* Server Buffer::               \e$B;v<B>e$N%5!<%P!<$r:n$C$FJT=8$9$k\e(B
+* Getting News::                USENET \e$B%K%e!<%9$r\e(B gnus \e$B$GFI$`\e(B
+* Getting Mail::                \e$B8D?ME*$J%a!<%k$r\e(B gnus \e$B$GFI$`\e(B
+* Browsing the Web::            \e$B2a>j$J%&%'%V$N;q8;$+$i%a%C%;!<%8$r<hF@$9$k\e(B
+* IMAP::                        gnus \e$B$r\e(B @acronym{IMAP} \e$B$N%/%i%$%"%s%H$H$7$F;H$&\e(B
+* Other Sources::               \e$B%G%#%l%/%H%j!<!"%U%!%$%k!"\e(BSOUP \e$B%Q%1%C%H$rFI$`\e(B
+* Combined Groups::             \e$BJ#?t$N%0%k!<%W$r0l$D$N%0%k!<%W$K7k9g$9$k\e(B
+* Gnus Unplugged::              \e$B%K%e!<%9$H%a!<%k$r%*%U%i%$%s$GFI$`\e(B
+@end menu
+
+@node Server Buffer
+@section \e$B%5!<%P!<%P%C%U%!\e(B
+
+\e$BEAE}E*$K!"\e(B@dfn{\e$B%5!<%P!<\e(B} \e$B$O$=$l$K@\B3$7$F!"$=$l$+$i>pJs$rMW5a$9$k%^%7%s\e(B
+\e$B$+%=%U%H%&%'%"$G$9!#\e(Bgnus \e$B$OK\Ev$N$I$s$J%5!<%P!<$K$bD>@\$K$O@\B3$;$:!"%P%C\e(B
+\e$B%/%(%s%I$+B>$N$b$N$rDL$7$F$9$Y$F$N=hM}$r9T$J$$$^$9!#$7$+$7!"$=$l$O<B:]$N\e(B
+\e$BG^BN$H\e(B gnus \e$B$N4V$KC1$K0l$D$+$=$l0J>e$N3,AX$rCV$/$3$H$G$"$C$F!"$=$l$>$l$N\e(B
+\e$B%P%C%/%(%s%I$,$^$5$K5?;wE*$J%5!<%P!<$KAjEv$9$k$H8@$C$F$bNI$$$G$7$g$&!#\e(B
+
+\e$BNc$($P\e(B @code{nntp} \e$B%P%C%/%(%s%I$O!"0[$J$k$$$/$D$+$N<B:_$9\e(B
+\e$B$k\e(B @acronym{NNTP} \e$B%5!<%P!<!"$"$k$$$OF1$8<B:_$9$k\e(B @acronym{NNTP} \e$B%5!<%P!<\e(B
+\e$B$N0[$J$k%]!<%H$K@\B3$9$k$?$a$KMQ$$$i$l$^$9!#$"$J$?$O!"$I$N%P%C%/%(%s%I$r\e(B
+\e$B;H$&$+!"$=$7$F$I$s$J%Q%i%a!<%?$r@_Dj$9$k$+$rA*BrJ}\e(B
+\e$BK!\e(B (@dfn{select method}) \e$B$G;XDj$7$^$9!#\e(B
+
+\e$BA*BrJ}K!$N;XDj$O!"$H$-$K6K$a$FLLE]$J$b$N$K$J$j$^$9!#$=$&$@$J$"!"Nc$($P!"\e(B
+@acronym{NOV} \e$B%X%C%@!<$r<h$j4s$;$h$&$H$9$k$H8G$^$C$F$7$^$$!"A*Br$N:n6H$,\e(B
+\e$B8N>c$,$A$J\e(B @acronym{NNTP} \e$B%5!<%P!<\e(B @samp{news.funet.fi} \e$B$N%]!<%H\e(B 13 \e$B$rFI\e(B
+\e$B$_$?$$>l9g$H$+!#$&$*$C$[$s!#$H$K$+$/$G$9$M!"$3$N%5!<%P!<$r;H$&$=$l$>$l$N\e(B
+\e$B%0%k!<%W$K$D$$$F$=$&$$$&$3$H$r@_Dj$7$J$1$l$P$J$i$J$$$H$7$?$i!"BgJQ$J:n6H\e(B
+\e$B$K$J$C$F$7$^$&$G$7$g$&!#$=$3$G\e(B gnus \e$B$O!"$=$&$$$&:n6H$r%5!<%P!<%P%C%U%!$G\e(B
+\e$B9T$J$&$?$a$K!"A*BrJ}K!$KL>A0$rIU$1$k<jCJ$r@_$1$F$$$k$N$G$9!#\e(B
+
+\e$B%5!<%P!<%P%C%U%!$KF~$k$?$a$K$O!"%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{^} (@code{gnus-group-enter-server-mode}) \e$B%3%^%s%I$r;H$C$F2<$5$$!#\e(B
+
+@menu
+* Server Buffer Format::        \e$B$3$N%P%C%U%!$N308+$r%+%9%?%^%$%:$G$-$k\e(B
+* Server Commands::             \e$B%5!<%P!<$rA`$kL?Na\e(B
+* Example Methods::             \e$B%5!<%P!<;XDj$NNc\e(B
+* Creating a Virtual Server::   \e$B%;%C%7%g%s$NNc\e(B
+* Server Variables::            \e$B$I$NJQ?t$r@_Dj$9$k$+\e(B
+* Servers and Methods::         \e$B%5!<%P!<L>$rA*BrJ}K!$H$7$F;H$&;v$,$G$-$k\e(B
+* Unavailable Servers::         \e$B@\B3$7$h$&$H;n$_$?%5!<%P!<$N$$$/$D$+$,Mn$A$F$$$k$+$b$7$l$J$$\e(B
+@end menu
+
+@vindex gnus-server-mode-hook
+\e$B%5!<%P!<%P%C%U%!$r:n@.$9$k$H$-$K\e(B @code{gnus-server-mode-hook} \e$B$,<B9T$5$l\e(B
+\e$B$^$9!#\e(B
+
+@node Server Buffer Format
+@subsection \e$B%5!<%P!<%P%C%U%!$NI=<(MM<0\e(B
+@cindex server buffer format
+
+@vindex gnus-server-line-format
+\e$B%5!<%P!<%P%C%U%!$N9T$N308+$r!"JQ?t\e(B @code{gnus-server-line-format} \e$BJQ?t$r\e(B
+\e$BJQ99$9$k;v$K$h$C$FJQ$($k;v$,$G$-$^$9!#$3$l$O\e(B @code{format} \e$B$N$h$&$JJQ?t\e(B
+\e$B$G!"$9$3$7C1=c$J3HD%$,$J$5$l$F$$$^$9\e(B:
+
+@table @samp
+@item h
+\e$B$I$N$h$&$K%K%e!<%9$,<hF@$5$l$k$+\e(B---\e$B%P%C%/%(%s%I$NL>A0!#\e(B
+
+@item n
+\e$B%5!<%P!<$NL>A0!#\e(B
+
+@item w
+\e$B$I$3$+$i%K%e!<%9$,<hF@$5$l$k$Y$-$+\e(B---\e$B%"%I%l%9!#\e(B
+
+@item s
+\e$B%5!<%P!<$N@\B3$N\e(B \e$B3+$$$?\e(B/\e$BJD$8$?\e(B/\e$B5qH]$5$l$?\e(B \e$B>uBV!#\e(B
+@end table
+
+@vindex gnus-server-mode-line-format
+\e$B%b!<%I9T$bJQ?t\e(B @code{gnus-server-mode-line-format} \e$B$r;H$&;v$K$h$C$F%+%9\e(B
+\e$B%?%^%$%:$9$k;v$,$G$-$^$9\e(B (@pxref{Mode Line Formatting})\e$B!#0J2<$N;XDj$OM}\e(B
+\e$B2r$5$l$^$9\e(B:
+
+@table @samp
+@item S
+\e$B%5!<%P!<L>!#\e(B
+
+@item M
+\e$B%5!<%P!<J}K!!#\e(B
+@end table
+
+@pxref{Formatting Variables} \e$B$b;2>H$7$F$/$@$5$$!#\e(B
+
+@node Server Commands
+@subsection \e$B%5!<%P!<L?Na\e(B
+@cindex server commands
+
+@table @kbd
+@item a
+@kindex a (\e$B%5!<%P!<\e(B)
+@findex gnus-server-add-server
+\e$B?7$7$$%5!<%P!<$rDI2C$7$^$9\e(B (@code{gnus-server-add-server})\e$B!#\e(B
+
+@item e
+@kindex e (\e$B%5!<%P!<\e(B)
+@findex gnus-server-edit-server
+\e$B%5!<%P!<$rJT=8$7$^$9\e(B (@code{gnus-server-edit-server})\e$B!#\e(B
+
+@item SPACE
+@kindex SPACE (\e$B%5!<%P!<\e(B)
+@findex gnus-server-read-server
+\e$B8=:_$N%5!<%P!<$r$6$C$HD/$a$^$9\e(B (@code{gnus-server-read-server})\e$B!#\e(B
+
+@item q
+@kindex q (\e$B%5!<%P!<\e(B)
+@findex gnus-server-exit
+\e$B%0%k!<%W%P%C%U%!$KLa$j$^$9\e(B (@code{gnus-server-exit})\e$B!#\e(B
+
+@item k
+@kindex k (\e$B%5!<%P!<\e(B)
+@findex gnus-server-kill-server
+\e$B8=:_$N%5!<%P!<$r@Z$j$^$9\e(B (kill) (@code{gnus-server-kill-server})\e$B!#\e(B
+
+@item y
+@kindex y (\e$B%5!<%P!<\e(B)
+@findex gnus-server-yank-server
+\e$B@h$[$I@Z$i$l$?\e(B (killed) \e$B%5!<%P!<$rE=$jIU$1$^$9\e(B (yank)
+(@code{gnus-server-yank-server})\e$B!#\e(B
+
+@item c
+@kindex c (\e$B%5!<%P!<\e(B)
+@findex gnus-server-copy-server
+\e$B8=:_$N%5!<%P!<$rJ#<L$7$^$9\e(B (@code{gnus-server-copy-server})\e$B!#\e(B
+
+@item l
+@kindex l (\e$B%5!<%P!<\e(B)
+@findex gnus-server-list-servers
+\e$BA4$F$N%5!<%P!<$N0lMw$r5s$2$^$9\e(B (@code{gnus-server-list-servers})\e$B!#\e(B
+
+@item s
+@kindex s (\e$B%5!<%P!<\e(B)
+@findex gnus-server-scan-server
+\e$B%5!<%P!<$K$=$N;q8;$+$i?7$7$$5-;v$rD4$Y$k$h$&$KMW5a$7$^\e(B
+\e$B$9\e(B (@code{gnus-server-scan-server})\e$B!#$3$l$O<g$K%a!<%k%5!<%P!<$KBP$7$F0U\e(B
+\e$BL#$r;}$A$^$9!#\e(B
+
+@item g
+@kindex g (\e$B%5!<%P!<\e(B)
+@findex gnus-server-regenerate-server
+\e$B%5!<%P!<$,A4$F$N%G!<%?9=B$$r:F:n@.$9$k$h$&$K5a$a$^\e(B
+\e$B$9\e(B (@code{gnus-server-regenerate-server})\e$B!#$3$l$OF14|$+$i$O$:$l$F$7$^$C\e(B
+\e$B$?%a!<%k%P%C%/%(%s%I$,$"$k$H$-$KLr$KN)$A$^$9!#\e(B
+@end table
+
+@node Example Methods
+@subsection \e$BJ}K!$NNc\e(B
+
+\e$B$[$H$s$I$NA*BrJ}K!$OHs>o$K4JC1$G!"<+J,<+?H$r$h$/@bL@$7$F$$$^$9\e(B:
+
+@lisp
+(nntp "news.funet.fi")
+@end lisp
+
+\e$BD>@\%9%W!<%k$+$iFI$`$N$O$b$C$H4JC1$G$9\e(B:
+
+@lisp
+(nnspool "")
+@end lisp
+
+\e$B8+$?$H$*$j!"A*BrJ}K!$N:G=i$NMWAG$O%P%C%/%(%s%I$NL>A0$G!"FsHVL\\e(B
+\e$B$O\e(B @dfn{\e$B%"%I%l%9\e(B} (address)\e$B!"$b$7$/$O$=$&8F$S$?$$$N$G$"$l$P!"\e(B
+@dfn{\e$BL>A0\e(B} \e$B$G$9!#\e(B
+
+\e$B$3$l$i$NFs$D$NMWAG$N8e$K$O!"G$0U$N?t\e(B
+\e$B$N\e(B @code{(@var{\e$BJQ?t\e(B} @var{\e$BMM<0\e(B})} \e$B$NBP$rF~$l$k;v$,$G$-$^$9!#\e(B
+
+\e$B:G=i$NNc$KLa$j$^$7$g$&\e(B---\e$B$=$N%^%7%s$N%]!<%H\e(B 15 \e$B$+$iFI$_$?$+$C$?$H;W$C$F\e(B
+\e$B$/$@$5$$!#$3$l$,$=$N;~$K!"$J$k$Y$-A*BrJ}K!$G$9\e(B:
+
+@lisp
+(nntp "news.funet.fi" (nntp-port-number 15))
+@end lisp
+
+\e$B$I$NJQ?t$,4XO"$9$k$+$r8+$D$1$k$?$a$K!"$=$l$>$l$N%P%C%/%(%s%I$N@bL@J8=q$r\e(B
+\e$BFI$`$Y$-$G$7$g$&$,!"$3$l$O\e(B @code{nnmh} \e$B$NNc$G$9!#\e(B
+
+@code{nnml} \e$B$O%9%W!<%k$N$h$&$J9=B$$GFI$`%a!<%k%P%C%/%(%s%I$G$9!#Nc$($P!"\e(B
+\e$B@\?($r?^$j$?$$Fs$D$N9=B$$,$"$k$H$7$^$7$g$&\e(B: \e$B0l$D$O$"$J$?$N;dE*$J%a!<%k%9\e(B
+\e$B%W!<%k$G!"B>J}$O8xE*$J$b$N$G$9!#$3$l$O;dE*$J%a!<%k$N$?$a$K;HMQ2DG=$J;XDj\e(B
+\e$B$G$9\e(B:
+
+@lisp
+(nnmh "private" (nnmh-directory "~/private/mail/"))
+@end lisp
+
+(\e$B$=$&$9$k$H$3$N%5!<%P!<$O\e(B @samp{private} \e$B$H8F$P$l$^$9$,!"$"$J$?$O4{$K?d\e(B
+\e$BB,$7$F$$$?$+$b$7$l$^$;$s!#\e(B)
+
+\e$B$3$l$O8xE*%9%W!<%k$N$?$a$NJ}K!$G$9\e(B:
+
+@lisp
+(nnmh "public"
+      (nnmh-directory "/usr/information/spool/")
+      (nnmh-get-new-mail nil))
+@end lisp
+
+@cindex proxy
+@cindex firewall
+
+\e$BKIJI\e(B (firewall) \e$B$NCf$K$$$F!"KIJI%^%7%s$+$i$N\e(B @acronym{NNTP} \e$B%5!<%P!<$X$N\e(B
+\e$B@\B3$7$+$J$$$N$G$"$l$P!"\e(Bgnus \e$B$KKIJI%^%7%s$K\e(B @code{rlogin} \e$B$7$F!"$=$3$+\e(B
+\e$B$i\e(B @acronym{NNTP} \e$B%5!<%P!<$K\e(B telnet \e$B$r$9$k$h$&$K;X<($9$k;v$,$G$-$^$9!#\e(B
+\e$B$3$l$r$9$k;v$O>/$7$P$+$i$7$$$G$9$,!";v<B>e$N%5!<%P!<$NDj5A$O$*$=$i$/$3$N\e(B
+\e$B$h$&$J$b$N$K$J$k$Y$-$G$9\e(B:
+
+@lisp
+(nntp "firewall"
+      (nntp-open-connection-function nntp-open-via-rlogin-and-telnet)
+      (nntp-via-address "the.firewall.machine")
+      (nntp-address "the.real.nntp.host")
+      (nntp-end-of-line "\n"))
+@end lisp
+
+\e$B$b$7!"$9$P$i$7$$\e(B @code{ssh} \e$B%W%m%0%i%`$r!"%b%G%`@~$+$i$N05=L$5$l$?@\B3$r\e(B
+\e$BDs6!$9$k$?$a$K;H$$$?$$$N$G$"$l$P!">e5-$NNc$K0J2<$N@_Dj$r2C$($k$3$H$,$G$-\e(B
+\e$B$^$9!#\e(B
+
+@lisp
+      (nntp-via-rlogin-command "ssh")
+@end lisp
+
+@code{nntp-via-rlogin-command-switches} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+\e$B$b$7$"$J$?$,KIJI$NCf$K$$$?$H$7$F$b!"\e(B"runsocks" \e$B$N$h$&$J%i%C%Q!<%3%^%s%I\e(B
+\e$B$rDL$7$F30$N@$3&$rD>@\%"%/%;%9$G$-$k$N$J$i$P!"0J2<$N$h$&$K\e(B socks \e$B$rDL$7\e(B
+\e$B$F%K%e!<%9%5!<%P!<$H\e(B telnet \e$B@\B3$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(nntp "outside"
+      (nntp-pre-command "runsocks")
+      (nntp-open-connection-function nntp-open-via-telnet)
+      (nntp-address "the.news.server")
+      (nntp-end-of-line "\n"))
+@end lisp
+
+\e$B$3$l$O$b$A$m$s!"<+F0G'>Z$rDs6!$9$k$?$a$K\e(B @code{ssh-agent} \e$B$rE,@Z$K@_Dj$7\e(B
+\e$B$J$1$l$P$J$j$^$;$s!#05=L$5$l$?@\B3$rF@$k$?$a$K$O!"\e(B@code{ssh}\e$B$N%U%!%$\e(B
+\e$B%k\e(B @file{config} \e$B$G\e(B @samp{Compression} \e$B%*%W%7%g%s$,$"$kI,MW$,$"$j$^$9!#\e(B
+
+@node Creating a Virtual Server
+@subsection \e$B;v<B>e$N%5!<%P!<$r:n@.$9$k\e(B
+
+\e$B$b$7$"$J$?$,1JB35-;v$r;H$C$F$?$/$5$s$N5-;v$r%-%c%C%7%e$KJ]B8$7$F$$$k$N$G\e(B
+\e$B$"$l$P!"%-%c%C%7%e$rFI$`$?$a$N;v<B>e$N%5!<%P!<$r:n$kI,MW$,$"$k$+$b$7$l$^\e(B
+\e$B$;$s!#\e(B
+
+\e$B:G=i$K!"?7$7$$%5!<%P!<$rIU$12C$($kI,MW$,$"$j$^$9!#L?Na\e(B @kbd{a} \e$B$,$=$l$r\e(B
+\e$B$7$^$9!#$*$=$i$/%-%c%C%7%e$rFI$`$?$a$K$O\e(B @code{nnml} \e$B$r;H$&$N$,0lHVNI$$\e(B
+\e$B$G$7$g$&!#\e(B@code{nnspool} \e$B$d\e(B @code{nnmh} \e$B$b;H$&;v$,$G$-$^$9$1$I!#\e(B
+
+@kbd{a nnml RET cache RET} \e$B$HBG$C$F$/$@$5$$!#\e(B
+
+\e$B$9$k$H\e(B @samp{cache} \e$B$H8F$P$l$k!"\e(B@code{nnml} \e$B$N;v<B>e$N%5!<%P!<$,$G$-$k$O\e(B
+\e$B$:$G$9!#<!$O$=$l$rJT=8$7$F!"@5$7$$Dj5A$rM?$($k$@$1$G$9!#%5!<%P!<$rJT=8$9\e(B
+\e$B$k$?$a$K\e(B @kbd{e} \e$B$rBG$C$F$/$@$5$$!#0J2<$N$b$N$r4^$`%P%C%U%!$KF~$k$G$7$g\e(B
+\e$B$&!#\e(B
+
+@lisp
+(nnml "cache")
+@end lisp
+
+\e$B$=$l$r<!$N$b$N$KJQ99$7$F$/$@$5$$\e(B:
+
+@lisp
+(nnml "cache"
+      (nnml-directory "~/News/cache/")
+      (nnml-active-file "~/News/cache/active"))
+@end lisp
+
+\e$B%5!<%P!<%P%C%U%!$KLa$k$?$a$K\e(B @kbd{C-c C-c} \e$B$HBG$C$F$/$@$5$$!#:#$d$3$N;v\e(B
+\e$B<B>e$N%5!<%P!<$G\e(B @kbd{RET} \e$B$r2!$9$H!"1\Mw%P%C%U%!$KF~$k$Y$-$G!"I=<($5$l\e(B
+\e$B$F$$$k$I$N%0%k!<%W$K$G$bF~$k;v$,$G$-$k$O$:$G$9!#\e(B
+
+@node Server Variables
+@subsection \e$B%5!<%P!<JQ?t\e(B
+@cindex server variables
+@cindex server parameters
+
+\e$BJQ?t$rDj5A$9$k0l$D$N$d$C$+$$$JE@$O\e(B (\e$B%P%C%/%(%s%I$H\e(B Emacs \e$B0lHL$NN>J}$G\e(B)\e$B!"\e(B
+\e$BJQ?t$NDj5A$,%m!<%I$5$l$F$$$k4V$K!"$$$/$D$+$NJQ?t$OB>$NJQ?t$G=i4|2=$5\e(B
+\e$B$l$k$H$$$&;v$G$9!#$b$7\e(B ``\e$B4p$H$J$k\e(B'' \e$BJQ?t$,%m!<%I$5$l$?8e$KJQ99$7$F$b!"\e(B
+``\e$BF3$-=P$5$l$?\e(B'' \e$BJQ?t$OJQ99$5$l$^$;$s!#\e(B
+
+\e$B$3$l$OIaDL$O%G%#%l%/%H%j!<$d%U%!%$%k$NJQ?t$K1F6A$7$^$9!#Nc$($P!"\e(B
+@code{nnml-directory} \e$B$O%G%#%U%)%k%H$G\e(B @file{~/Mail} \e$B$G$9$,!"A4$F\e(B
+\e$B$N\e(B @code{nnml} \e$B%G%#%l%/%H%j!<JQ?t$O$=$NJQ?t$K$h$C$F=i4|2=$5$l$k$N$G!"\e(B
+@code{nnml-active-file} \e$B$O\e(B @file{~/Mail/active} \e$B$K$J$j$^$9!#$b$7?7$7$$;v\e(B
+\e$B<B>e$N\e(B @code{nnml} \e$B%5!<%P!<$rDj5A$7$?>l9g!"\e(B@code{nnml-directory} \e$B$r@_Dj\e(B
+\e$B$9$k$@$1$G$O=<J,$G$O\e(B@emph{\e$B$"$j$^$;$s\e(B}---\e$B$"$J$?$OK>$s$@>uBV$K$J$k$h$&$K!"\e(B
+\e$BA4$F$N%U%!%$%kJQ?t$rL@<(E*$K@_Dj$7$J$1$l$P$J$j$^$;$s!#$=$l$>$l$N%P%C%/%(\e(B
+\e$B%s%I$KBP$9$k40A4$JJQ?t$N%j%9%H$r8+$k$?$a$K$O!"$3$N%^%K%e%"%k$N8e$KB3$/$=\e(B
+\e$B$l$>$l$N%P%C%/%(%s%I$NItJ,$rFI$s$G$/$@$5$$!#$G$b!"\e(B@code{nnml} \e$B$NDj5A$NNc\e(B
+\e$B$O$3$3$K$"$j$^$9\e(B:
+
+@lisp
+(nnml "public"
+      (nnml-directory "~/my-mail/")
+      (nnml-active-file "~/my-mail/active")
+      (nnml-newsgroups-file "~/my-mail/newsgroups"))
+@end lisp
+
+\e$B%5!<%P!<JQ?t$O$7$P$7$P\e(B @dfn{\e$B%5!<%P!<%Q%i%a!<%?\e(B} \e$B$H8F$P$l$^$9!#\e(B
+
+@node Servers and Methods
+@subsection \e$B%5!<%P!<$HJ}K!\e(B
+
+\e$BIaDL$KA*BrJ}K!$r;H$&$H$3$m$G$"$l$P$I$3$G$b\e(B (\e$BNc$($P!"30It%5!<%P!<$r354Q$7\e(B
+\e$B$F$$$k$H$-$N%0%k!<%WA*BrJ}K!$G$"$k\e(B @code{gnus-secondary-select-method})\e$B!"\e(B
+\e$BBe$o$j$K;v<B>e$N%5!<%P!<L>$r;H$&;v$,$G$-$^$9!#$3$N$3$H$K$h$j$?$/$5$s%-!<\e(B
+\e$B%\!<%I$rC!$+$J$/$F$9$`2DG=@-$,$"$j$^$9!#$=$7$F!"A4$F$K$o$?$C$F!"$=$NJ}$,\e(B
+\e$BNI$$$G$9!#\e(B
+
+@node Unavailable Servers
+@subsection \e$B;HMQIT2DG=$J%5!<%P!<\e(B
+
+\e$B$b$7%5!<%P!<$K@\B3IT2DG=$G$"$k$J$i$P!"\e(Bgnus \e$B$O%5!<%P!<$r\e(B @code{\e$B5qH]\e(B} \e$B$H$7\e(B
+\e$B$F0u$rIU$1$^$9!#$3$l$O$=$N8e$N$=$N%5!<%P!<$H$N@\B3$r$O$+$k$I$N$h$&$J;n$_\e(B
+\e$B$bL5;k$5$l$k$H$$$&;v$G$9!#\e(BGnus \e$B$O@\B3$,3+$1$J$$$3$H$,K\Ev$G$"$k$+$I$&$+\e(B
+\e$B$r>/$7$b3N$+$a$:!"\e(B``It can't be opend,'' (\e$B@\B3$r3+$/;v$,$G$-$^$;$s\e(B) \e$B$H9p\e(B
+\e$B$2$^$9!#\e(B
+
+\e$B$=$l$O9T57$,0-$$$H;W$&;v$,$"$k$+$b$7$l$^$;$s$,!"$=$l$O$?$$$F$$$N$H$-$K$O\e(B
+\e$BNI$$J}K!$G$9!#Nc$($P!"%5!<%P!<\e(B @samp{nephelococcdyia.com} \e$B$K\e(B 10 \e$B8D9XFI$7\e(B
+\e$B$F$$$k%0%k!<%W$,$"$k$H$7$^$7$g$&!#%5!<%P!<$O$I$3$+Hs>o$K1s$/$K$"$j!"%^%7\e(B
+\e$B%s$O$H$F$bCY$$$N$G!"$=$l$,:#F|$O$"$J$?$H$N@\B3$r5qH]$9$k$+$I$&$+$rD4$Y$k\e(B
+\e$B$@$1$G0lJ,$+$+$j$^$9!#$b$7\e(B gnus \e$B$,$=$l$r\e(B 10 \e$B2s;n$9$h$&$K$J$C$F$$$?$J$i!"\e(B
+\e$B$"$J$?$OHs>o$K$&$k$5$/;W$&$G$7$g$&!#$G$9$+$i!"\e(Bgnus \e$B$O$=$l$r;n$=$&$H$O$7\e(B
+\e$B$^$;$s!#0lEY\e(B ``connection refused'' (\e$B@\B3$O5qH]$5$l$^$7$?\e(B) \e$B$r<u$1<h$k$H!"\e(B
+\e$B$=$l$O%5!<%P!<$,\e(B ``down'' (\e$BMn$A$F$$$k\e(B) \e$B$G$"$k$H$_$J$7$^$9!#\e(B
+
+\e$B$=$l$G!"0l;~E*$K$=$N%^%7%s$N5!7y$,0-$$$@$1$@$C$?$i2?$,5/$3$k$N$G$7$g\e(B
+\e$B$&\e(B? \e$B%^%7%s$,I|3h$7$?$+$I$&$+$r$I$&$9$l$PD4$Y$k;v$,$G$-$k$N$G$7$g$&\e(B?
+
+\e$B%5!<%P!<%P%C%U%!$KHt$S0\$C$F\e(B (@pxref{Server Buffer})\e$B!"0J2<$NL?Na$G$D$D$/\e(B
+\e$B$@$1$G$G$-$^$9\e(B:
+
+@table @kbd
+@item O
+@kindex O (\e$B%5!<%P!<\e(B)
+@findex gnus-server-open-server
+\e$B8=:_$N9T$N%5!<%P!<$H$N@\B3$r3NN)$7$h$&$H$7$^\e(B
+\e$B$9\e(B (@code{gnus-server-open-server})\e$B!#\e(B
+
+@item C
+@kindex C (\e$B%5!<%P!<\e(B)
+@findex gnus-server-close-server
+\e$B%5!<%P!<$N@\B3\e(B (\e$B$b$7$"$l$P\e(B) \e$B$rJD$8$^$9\e(B (@code{gnus-server-close-server})\e$B!#\e(B
+
+@item D
+@kindex D (\e$B%5!<%P!<\e(B)
+@findex gnus-server-deny-server
+\e$B8=:_$N%5!<%P!<$K@\B3IT2DG=$N0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-server-open-all-server})\e$B!#\e(B
+
+@item M-c
+@kindex M-c (\e$B%5!<%P!<\e(B)
+@findex gnus-server-close-to-all-servers
+\e$B%P%C%U%!$K$"$kA4$F$N%5!<%P!<$H$N@\B3$rJD$8$^\e(B
+\e$B$9\e(B (@code{gnus-server-close-all-servers})\e$B!#\e(B
+
+@item R
+@kindex R (\e$B%5!<%P!<\e(B)
+@findex gnus-server-remove-denials
+Gnus \e$B$,$I$l$+$N%5!<%P!<$+$i@\B35qH]$r<u$1$?$+$I$&$+$NA4$F$N0u$r>C5n$7$^\e(B
+\e$B$9\e(B (@code{gnus-server-remove-denials})\e$B!#\e(B
+
+@item L
+@kindex L (\e$B%5!<%P!<\e(B)
+@findex gnus-server-offline-server
+\e$B%5!<%P!<$N>uBV$r%*%U%i%$%s$K$7$^$9\e(B (@code{gnus-server-offline-server})\e$B!#\e(B
+@end table
+
+@node Getting News
+@section \e$B%K%e!<%9$N<hF@\e(B
+@cindex reading news
+@cindex news back ends
+
+\e$B%K%e!<%9%j!<%@!<$OIaDL$O%K%e!<%9$rFI$`;v$K;H$o$l$^$9!#\e(BGnus \e$B$O8=:_$O%K%e!<\e(B
+\e$B%:$r<hF@$9$k$?$a$KFs$D$@$1$NJ}K!$rDs6!$7$F$$$^$9\e(B---@acronym{NNTP} \e$B%5!<%P!<\e(B
+\e$B$+!"%m!<%+%k%9%W!<%k$+$iFI$`;v$,$G$-$^$9!#\e(B
+
+@menu
+* NNTP::                        @acronym{NNTP} \e$B%5!<%P!<$+$i%K%e!<%9$rFI$`\e(B
+* News Spool::                  \e$B%m!<%+%k%9%W!<%k$+$i%K%e!<%9$rFI$`\e(B
+@end menu
+
+@node NNTP
+@subsection NNTP
+@cindex nntp
+
+@acronym{NNTP} \e$B%5!<%P!<$N30It%0%k!<%W$r9XFI$9$k$N$OHf3SE*4JC1$G$9!#C1\e(B
+\e$B$K\e(B @code{nntp} \e$B$rJ}K!$H$7$F;XDj$7!"\e(B@acronym{NNTP} \e$B%5!<%P!<$N%"%I%l\e(B
+\e$B%9\e(B (address) \e$B$r!"$&!<$s!"%"%I%l%9$H$7$F;XDj$9$k$@$1$G$9!#\e(B
+
+\e$B$b$7\e(B @acronym{NNTP} \e$B%5!<%P!<$,I8=`$G$J$$%]!<%H\e(B (port) \e$B$K0LCV$7$F$$$k$H$-\e(B
+\e$B$O!"A*BrJ}K!$N;0HVL\$NMWAG$r$3$N%]!<%H$N?t;z$K@_Dj$9$k;v$G@5$7$$%]!<%H$K\e(B
+\e$B@\B3$9$k;v$,$G$-$k$G$7$g$&!#$=$N$?$a$K%0%k!<%W>pJs$rJT=8$7$J$1$l$P$J$j$^\e(B
+\e$B$;$s\e(B (@pxref{Foreign Groups})\e$B!#\e(B
+
+\e$B30It%0%k!<%W$NL>A0$O4pK\%0%k!<%W$HF1$8$G$b9=$$$^$;$s!#<B:]!"$"$J$?$N\e(B
+\e$B;W$&$^$^$KF1$8%0%k!<%W$r2DG=$J8B$j$N0c$C$?%5!<%P!<$+$i9XFI$9$k;v$,$G$-$^\e(B
+\e$B$9!#L>A0$N>WFM$O5/$3$j$^$;$s!#\e(B
+
+\e$B0J2<$NJQ?t$O;v<B>e$N\e(B @code{nntp} \e$B%5!<%P!<$r:n$k$?$a$K;H$o$l$^$9\e(B:
+
+@table @code
+@item nntp-server-opened-hook
+@vindex gnus-server-opend-hook
+@cindex @sc{mode reader}
+@cindex authinfo
+@cindex authentification
+@cindex nntp authentification
+@findex nntp-send-authinfo
+@findex nntp-send-mode-reader
+\e$B$O@\B3$,$G$-$?8e$K<B9T$5$l$^$9!#$=$l$O\e(B @acronym{NNTP} \e$B%5!<%P!<$K@\?($7$?\e(B
+\e$B8e$K$=$l$KL?Na$rAw$k$?$a$K;H$o$l$k;v$,$G$-$^$9!#%G%#%U%)%k%H$G$O4X\e(B
+\e$B?t\e(B @code{nntp-send-mode-reader} \e$B$K$h$jL?Na\e(B @code{MODE READER} \e$B$,%5!<%P!<\e(B
+\e$B$KAw$i$l$^$9!#$=$N4X?t$O>o$K$3$N%U%C%/$K$"$k$Y$-$G$9!#\e(B
+
+@item nntp-authinfo-function
+@vindex nntp-authinfo-function
+@findex nntp-send-authoinfo
+@vindex nntp-authinfo-file
+\e$B$3$N4X?t$O\e(B @acronym{NNTP} \e$B%5!<%P!<$K\e(B @samp{AUTHINFO} \e$B$rAw$k$?$a$K;H$o$l\e(B
+\e$B$^$9!#%G%#%U%)%k%H$N4X?t$O\e(B @code{nntp-send-authinfo} \e$B$G!"\e(B
+@file{~/.authinfo} (\e$B$b$7$/$OJQ?t\e(B @code{nntp-authinfo-file} \e$B$K@_Dj$7$?$I\e(B
+\e$B$N$h$&$J$b$N$G$b\e(B) \e$B$r;HMQ2DG=$J5-:\$rD4$Y$k$?$a$KC5$7$^$9!#$b$70l$D$b8+$D\e(B
+\e$B$+$i$J$+$C$?$i!"$"$J$?$K%m%0%$%sL>$H%Q%9%o!<%I$NF~NO$rB%?J$7$^$9!#%U%!%$\e(B
+\e$B%k\e(B @file{~/.authinfo} \e$B$NMM<0$O\e(B (\e$B$[$H$s$I\e(B) @code{ftp} \e$B$N%U%!%$\e(B
+\e$B%k\e(B @file{~/.netrc} \e$B$HF1$8$G!"$=$l$O\e(B @code{ftp} \e$B$N%^%K%e%"%k%Z!<%8$KDj5A\e(B
+\e$B$5$l$F$$$^$9$,!"$3$3$N$b$N$O82Cx$J;v<B$G$9\e(B:
+
+@enumerate
+@item
+\e$B%U%!%$%k$O0l$D0J>e$N9T$r4^$_!"$=$l$>$l$O0l$D$N%5!<%P!<$rDj5A$7$^$9!#\e(B
+
+@item
+\e$B$=$l$>$l$N9T$OG$0U$N?t$N\e(B \e$B6h@Z$j0u\e(B/\e$BCM\e(B \e$B$NBP$r4^$`;v$,$G$-$^$9!#\e(B
+
+\e$BM-8z$J6h@Z$j0u$O\e(B @samp{machine}, @samp{login}, @samp{password},
+@samp{default} \e$B$G$9!#2C$($F!"\e(Bgnus \e$B$O\e(B @file{.netrc}/@code{ftp} \e$B$N9=J8$N86\e(B
+\e$B7?$K$O8=$l$J$$Fs$D$N?7$7$$6h@Z$j0u!"L>IU$1\e(B
+\e$B$F\e(B @samp{port} \e$B$H\e(B @samp{force} \e$B$rF3F~$7$^$9!#\e(B
+(\e$B$3$l$,\e(B @file{.authinfo} \e$B%U%!%$%k$NMM<0$,\e(B @file{.netrc} \e$B%U%!%$%k$NMM<0$+\e(B
+\e$B$i0o$l$kM#0l$NJ}K!$G$9!#\e(B) @samp{port} \e$B$O%5!<%P!<$N$I$N%]!<%H$rG'>Z$KMQ$$\e(B
+\e$B$k$+$r<($7!"\e(B@samp{force} \e$B$O0J2<$G@bL@$7$^$9!#\e(B
+
+@end enumerate
+
+\e$B$3$l$,$=$N%U%!%$%k$NNc$G$9\e(B:
+
+@example
+machine news.uio.no login larsi password geheimnis
+machine nntp.ifi.uio.no login larsi force yes
+@end example
+
+\e$B6h@Z$j0u\e(B/\e$BCM\e(B \e$B$NBP$O$I$N$h$&$J=gHV$G$G$b8=$l$k;v$,$G$-$^$9!#Nc$($P!"\e(B
+@samp{machine} \e$B$O:G=i$K8=$l$kI,MW$O$"$j$^$;$s!#\e(B
+
+\e$B$3$NNc$G$O!"%m%0%$%sL>$H%Q%9%o!<%I$NN>J}$,A0<T$N%5!<%P!<$K$OM?$($i$l$F$$\e(B
+\e$B$k$N$KBP$7$F!"8e<T$O%m%0%$%sL>$@$1$r5s$2$F$$$F!"MxMQ<T$O%Q%9%o!<%I$NF~NO\e(B
+\e$B$rB%?J$5$l$^$9!#8e<T$O\e(B @samp{force} \e$B%?%0$b;}$C$F$$$F!"$=$l$O@\B3;~\e(B
+\e$B$K\e(B @var{nntp} \e$B%5!<%P!<$KG'>Z>pJs\e(B (authinfo) \e$B$,Aw$i$l$k$H$$$&;v$G$9!#%G%#\e(B
+\e$B%U%)%k%H\e(B (\e$B$9$P$o$A!"\e(B@samp{force} \e$B%?%0$,L5$$$H$-\e(B) \e$B$G$O\e(B @var{nntp} \e$B%5!<%P!<\e(B
+\e$B$,G'>Z>pJs$r?R$M$J$$8B$j$=$l$r\e(B @var{nntp} \e$B%5!<%P!<$KAw$j$^$;$s!#\e(B
+
+@samp{machine} \e$B9T$K9gCW$7$J$$A4$F$N%5!<%P!<$KE,MQ$5$l\e(B
+\e$B$k\e(B @samp{default} \e$B9T$rDI2C$9$k;v$b$G$-$^$9!#\e(B
+
+@example
+default force yes
+@end example
+
+\e$B$3$l$O0JA0$K=q$+$l$F$$$J$$A4$F$N%5!<%P!<$KL?Na\e(B @samp{AUTHINFO} \e$B$r6/@)E*\e(B
+\e$B$KAw$j$^$9!#\e(B
+
+\e$B%U%!%$%k\e(B @file{~/.authinfo} \e$B$r@$3&Cf$,FI$a$k$h$&$J@_Dj$KJ|CV$7$J$$$h$&$K\e(B
+\e$BCm0U$7$F$/$@$5$$!#\e(B
+
+@item nntp-server-action-alist
+@vindex nntp-server-action-alist
+\e$B$3$l$O%5!<%P!<$N7?$K9gCW$9$k@55,I=8=$H!"9gCW$,5/$3$C$?$H$-$K<h$i$l$kF0:n\e(B
+\e$B$NO"A[%j%9%H$G$9!#Nc$($P!"\e(Bgnus \e$B$K\e(B innd \e$B$K@\B3$7$?$H$-$KKh2s%S!<%W2;$rLD\e(B
+\e$B$i$5$;$?$$\e(B (beep) \e$B$N$G$"$l$P!"<!$N$h$&$K$9$k;v$,$G$-$^$9\e(B:
+
+@lisp
+(setq nntp-server-action-list
+      '(("innd" (ding))))
+@end lisp
+
+\e$B$^$!!"$=$N$h$&$J;v$O$7$?$/$J$$$G$7$g$&$1$I!#\e(B
+
+\e$B%G%#%U%)%k%H$NCM$O\e(B
+
+@lisp
+'(("nntpd 1\\.5\\.11t"
+   (remove-hook 'nntp-server-opened-hook
+                'nntp-send-mode-reader)))
+@end lisp
+
+\e$B$G!"$3$l$O\e(B nntpd 1.5.11t \e$B$K$OL?Na\e(B @code{MODE READER} \e$B$rAw$i$J$$;v$r3N<B\e(B
+\e$B$K$7$^$9!#$J$<$J$i!"$=$NL?Na$O$=$N%5!<%P!<$r8G$^$i$;$k$H;d$OJ9$$$F$$$k$+\e(B
+\e$B$i$G$9!#\e(B
+
+@item nntp-maximum-request
+@vindex nntp-maximum-request
+\e$B$b$7\e(B @acronym{NNTP} \e$B%5!<%P!<$,\e(B @acronym{NOV} \e$B%X%C%@!<$N5!G=$rDs6!$7$F$$\e(B
+\e$B$J$$$N$G$"$l$P!"$3$N%P%C%/%(%s%I$OL?Na\e(B @code{head} \e$B$r$$$/$D$bAw$C$F!"%X%C\e(B
+\e$B%@!<$r=8$a$^$9!#$3$NF0:n$rB.$/$9$k$?$a$K!"%P%C%/%(%s%I$OJVEz$rBT$?$:$K$3\e(B
+\e$B$NL?Na$r$?$/$5$sAw$j!"$=$l$+$iA4$F$NJVEz$rFI$_$^$9!#$3$l$OJQ\e(B
+\e$B?t\e(B @code{nntp-maximum-request} \e$B$K$h$C$F@)8f$5$l!"%G%#%U%)%k%H$G\e(B 400 \e$B$G$9!#\e(B
+\e$B$b$7%M%C%H%o!<%/$,8N>c$,$A$G$"$k$J$i!"$3$NJQ?t$r\e(B 1 \e$B$K@_Dj$9$k$Y$-$G$7$g\e(B
+\e$B$&!#\e(B
+
+@item nntp-connection-timeout
+@vindex nntp-connection-timeout
+\e$BDj4|E*$K@\B3$9$k30It\e(B @code{nntp} \e$B%0%k!<%W$,$?$/$5$s$"$k$J$i!"E,@Z$K1~Ez\e(B
+\e$B$7$J$$\e(B @code{nntp} \e$B%5!<%P!<$,$"$C$?$j!"$"$k%5!<%P!<$O>o<1E*$J;~4VFb$G$O\e(B
+\e$BJVEz$G$-$J$$$/$i$$Ii2Y$,$+$+$C$F$$$k!"$J$I$NLdBj$,$"$k$G$7$g$&!#$3$l$O:$$C\e(B
+\e$B$?LdBj$K$J$k$3$H$,$"$j$^$9$,!"\e(B@code{nntp-connection-timeout} \e$B$r@_Dj$9$k\e(B
+\e$B;v$K$h$j$"$kDxEY2r>C$9$k;v$,$G$-$^$9!#$3$l$O@\B3$r$"$-$i$a$k$^$($K!"\e(B
+@code{nntp} \e$B%P%C%/%(%s%I$,2?ICBT$D$+$r<($9@0?t$G$9!#$b$7$3$l\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$H!"$3$l$,=i4|@_Dj$G$9$,!";~4V@Z$l@ZCG$O$J$5$l$^$;$s!#\e(B
+
+@c @item nntp-command-timeout
+@c @vindex nntp-command-timeout
+@c @cindex PPP connections
+@c @cindex dynamic IP addresses
+@c If you're running Gnus on a machine that has a dynamically assigned
+@c address, Gnus may become confused.  If the address of your machine
+@c changes after connecting to the @acronym{NNTP} server, Gnus will simply sit
+@c waiting forever for replies from the server.  To help with this
+@c unfortunate problem, you can set this command to a number.  Gnus will
+@c then, if it sits waiting for a reply from the server longer than that
+@c number of seconds, shut down the connection, start a new one, and resend
+@c the command.  This should hopefully be transparent to the user.  A
+@c likely number is 30 seconds.
+@c
+@c @item nntp-retry-on-break
+@c @vindex nntp-retry-on-break
+@c If this variable is non-@code{nil}, you can also @kbd{C-g} if Gnus
+@c hangs.  This will have much the same effect as the command timeout
+@c described above.
+
+@item nntp-server-hook
+@vindex nntp-server-hook
+\e$B$3$N%U%C%/$O\e(B @acronym{NNTP} \e$B%5!<%P!<$K@\B3$9$k:G8e$N0lJb$H$7$F<B9T$5$l$^\e(B
+\e$B$9!#\e(B
+
+@item nntp-buggy-select
+@vindex nntp-buggy-select
+\e$B$"$J$?$NA*Br$N0lO"$N:n6H$,8N>c$,$A$G$"$k$H$-$K$3$l$r\e(B @code{nil} \e$B$G$J$$CM\e(B
+\e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+
+@item nntp-nov-is-evil
+@vindex nntp-nov-is-evil
+@acronym{NNTP} \e$B%5!<%P!<$,\e(B @acronym{NOV} \e$B5!G=$rDs6!$7$F$$$J$1$l$P$3$NJQ?t\e(B
+\e$B$r\e(B @code{t} \e$B$K@_Dj$9$k;v$,$G$-$^$9$,!"\e(B@code{nntp} \e$B$OIaDL\e(B
+\e$B$O\e(B @acronym{NOV} \e$B$,;H$o$l$k$+$I$&$+$r<+F0E*$KD4$Y$^$9!#\e(B
+
+@item nntp-xover-commands
+@vindex nntp-xover-commands
+@cindex @acronym{NOV}
+@cindex XOVER
+\e$B%5!<%P!<$+$i\e(B @acronym{NOV} \e$B9T$r<hF@$9$k$?$a$NL?Na$H$7$F;H$o$l$kJ8;zNs$N\e(B
+\e$B%j%9%H$G$9!#$3$NJQ?t$N%G%#%U%)%k%H$NCM$O\e(B @code{("XOVER" "XOVERVIEW")} \e$B$G\e(B
+\e$B$9!#\e(B
+
+@item nntp-nov-gap
+@vindex nntp-nov-gap
+@code{nntp} \e$B$OIaDL$O%5!<%P!<$K\e(B @acronym{NOV} \e$B9T$N$?$a$N0l$D$NBg$-$JMW5a\e(B
+\e$B$rAw$j$^$9!#%5!<%P!<$O0l$D$N5pBg$J!"9T$N%j%9%H$G1~Ez$7$^$9!#$7$+$7!"$b$7\e(B
+\e$B%0%k!<%W$N\e(B 2-5000 \e$B$N5-;v$rFI$s$G!"\e(B1 \e$B$H\e(B 5001 \e$B$rFI$_$?$$$@$1$J$i!"\e(B
+@code{nntp} \e$B$OI,MWL5$$\e(B 4999 \e$B$N\e(B @acronym{NOV} \e$B9T$r<hF@$9$k;v$K$J$j$^$9!#\e(B
+\e$B$3$NJQ?t$O\e(B @code{XOVER} \e$BMW5a$,$I$l$/$i$$Bg$-$JFs$D$NO"B3$7$?5-;v72$N4V$N\e(B
+\e$B$X$@$?$j\e(B (gap) \e$B$^$GJ,3d$5$l$J$$$GAw$i$l$k$+$r7hDj$7$^$9!#%M%C%H%o!<%/$,\e(B
+\e$BB.$$>l9g$O!"$3$NJQ?t$rK\Ev$K>.$5$J?t;z$K@_Dj$9$k$H$*$=$i$/<hF@$,CY$/$J$k\e(B
+\e$B$H$$$&;v$KCm0U$7$F$/$@$5$$!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"\e(B
+@code{nntp} \e$B$OMW5a$rJ,3d$7$^$;$s!#%G%#%U%)%k%H$O\e(B 5 \e$B$G$9!#\e(B
+
+@item nntp-prepare-server-hook
+@vindex nntp-prepare-server-hook
+@acronym{NNTP} \e$B%5!<%P!<$K@\B3$r;n$_$kA0$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item nntp-warn-about-losing-connection
+@vindex nntp-warn-about-losing-connection
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"%5!<%P!<$,@\B3$rJD$8$?$H$-$K>/$7;(2;$,$?\e(B
+\e$B$F$i$l$^$9!#\e(B
+
+@item nntp-record-commands
+@vindex nntp-record-commands
+\e$B$b$7\e(B @code{nil} \e$B$G$J$$$H!"\e(B@code{nntp} \e$B$O\e(B @acronym{NNTP} \e$B%5!<%P!<$KAw$C$?\e(B
+\e$B$9$Y$F$NL?Na$r\e(B (\e$B;~9o$H6&$K\e(B) @samp{*nntp-log*} \e$B%P%C%U%!$K5-O?$7$^$9!#$3$l\e(B
+\e$B$OF0:n$7$F$$$J$$$H;W$o$l$k\e(B gnus/@acronym{NNTP} \e$B@\B3$r%G%#%P%C%0$7$F$$$k\e(B
+\e$B$H$-$KLr$KN)$A$^$9!#\e(B
+
+@item nntp-open-connection-function
+@vindex nntp-open-connection-function
+\e$B$I$N$h$&$K\e(B nntp \e$B%5!<%P!<$H@\B3$9$k$+$r%+%9%?%^%$%:$9$k$3$H$,$G$-$^$9!#%Q\e(B
+\e$B%i%a!<%?\e(B @code{nntp-open-connection-function} \e$B$r@_Dj$9$k$H!"\e(Bgnus \e$B$O@\B3\e(B
+\e$B$r3NN)$9$k$?$a$K$=$N4X?t$r;H$$$^$9!#$=$N$?$a$K8^$D$N4X?t$,$"$i$+$8$aMQ0U\e(B
+\e$B$5$l$F$$$^$9!#$=$l$i$OFs<oN`$KJ,N`$9$k$3$H$,$G$-!"D>@\@\B3$9$k$?$a$N4X?t\e(B
+\e$B72\e(B (\e$B;0$D\e(B) \e$B$H4V@\E*$K@\B3$9$k$?$a$N$b$N\e(B (\e$BFs$D\e(B) \e$B$,$"$j$^$9!#\e(B
+
+@item nntp-prepare-post-hook
+@vindex nntp-prepare-post-hook
+\e$B5-;v$r%]%9%H$9$kD>A0$K<B9T$5$l$k%U%C%/$G$9!#$b$75-;v\e(B
+\e$B$K\e(B @code{Message-ID} \e$B%X%C%@!<$,L5$/$F%K%e!<%9%5!<%P!<$,?d>)\e(B ID \e$B$rDs6!$7\e(B
+\e$B$F$/$l$k$J$i$P!"$3$N%U%C%/$,<B9T$5$l$kA0$K$=$l$,5-;v$K2C$($i$l$^$9!#$3$l\e(B
+\e$B$O!"$b$7$"$J$?$,\e(B gnus \e$B$,\e(B @code{Message-ID} \e$B%X%C%@!<$rIU$1$J$$$h$&$K$7$F\e(B
+\e$B$$$F$b!"\e(B@code{Cancel-Lock} \e$B%X%C%@!<$r:n$k$?$a$KMxMQ$9$k$3$H$,$G$-$^$9!#\e(B
+\e$B$=$l$K$O$3$&$9$l$PNI$$$G$7$g$&\e(B:
+
+@lisp
+(add-hook 'nntp-prepare-post-hook 'canlock-insert-header)
+@end lisp
+
+\e$B$9$Y$F$N%5!<%P!<$,?d>)\e(B ID \e$B$r%5%]!<%H$7$F$$$k$o$1$G$O$J$$$3$H$KCm0U$7$F2<\e(B
+\e$B$5$$!#$3$l$ONc$($P\e(B INN 2.3.0 \e$B0J>e$GF0:n$7$^$9!#\e(B
+
+@item nntp-read-timeout
+@vindex nntp-read-timeout
+Nntp \e$B$,=PNO$,=*N;$7$?$3$H$r3NG'$9$k$?$a$KBT$D$Y$-;~4V$G$9!#CM$rC;$/$9$l\e(B
+\e$B$PH?1~$,B.$/$J$j$^$9$,\e(B CPU \e$B$r?)$$$^$9!#%G%#%U%)%k%H$O\e(B 0.1 \e$BIC$G$9!#%5!<%P!<\e(B
+\e$B$KCY$$2s@~$G@\B3$7$F$$$k>l9g$O\e(B (\e$B$=$7$F\e(B Emacs \e$B$,\e(B CPU \e$B%Q%o!<$r?)$&$N$rK>$^\e(B
+\e$B$J$1$l$P\e(B)\e$B!"$3$l$rNc$($P\e(B 1 \e$B$K$7$F$b9=$$$^$;$s!#\e(B
+
+@item nntp-list-options
+@vindex nntp-list-options
+LIST \e$B%3%^%s%I$N%*%W%7%g%s$K;H$C$F!"\e(B(\e$B%5!<%P!<$N\e(B) \e$B%j%9%H=PNO$r@_Dj$7$?%K%e!<\e(B
+\e$B%9%0%k!<%W$@$1$K@)8B$9$k$?$a$N!"%K%e!<%9%0%k!<%WL>$N%j%9%H$G$9!#$=$l$>$l\e(B
+\e$B$N%K%e!<%9%0%k!<%WL>$K$O\e(B @dfn{fj.*} \e$B$d\e(B @dfn{japan.*} \e$B$N$h$&$J!"%7%'%k7A\e(B
+\e$B<0$N%o%$%k%I%+!<%I$r;H$&$3$H$,$G$-$^$9!#$b$79,1?$K$b%5!<%P!<$,$=$N$h$&$J\e(B
+\e$B%*%W%7%g%s$r<u$1IU$1$F$/$l$l$P!"\e(Bgnus \e$B$rB.$/F0:n$5$;$k$3$H$,$G$-$k$+$b$7\e(B
+\e$B$l$^$;$s!#$3$l$O!"0J2<$N$h$&$K%5!<%P!<JQ?t$H$7$F;H$&$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+             (nntp-list-options ("fj.*" "japan.*"))))
+@end lisp
+
+@item nntp-options-subscribe
+@vindex nntp-options-subscribe
+\e$B9gCW$7$?$iL5>r7o$G9VFI$9$k%K%e!<%9%0%k!<%WL>$N@55,I=8=$G$9!#@55,I=8=$NJ8\e(B
+\e$B;zNs$G$O\e(B @dfn{$} \e$B$NBe$o$j$K\e(B @dfn{ } \e$B$r;H$C$F2<$5$$!#%5!<%P!<$,\e(B LIST \e$B%3%^\e(B
+\e$B%s%I$N%*%W%7%g%s$K%7%'%k7A<0$N%o%$%k%I%+!<%I$r<u$1IU$1$F$/$l$J$$>l9g$G$b!"\e(B
+@code{nntp-list-options} \e$B$HF1MM$N8z2L$,$"$k$G$7$g$&!#$3$l$O!"0J2<$N$h$&\e(B
+\e$B$K%5!<%P!<JQ?t$H$7$F;H$&$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+             (nntp-options-subscribe "^fj\\.\\|^japan\\.")))
+@end lisp
+
+@item nntp-options-not-subscribe
+@vindex nntp-options-not-subscribe
+\e$B9gCW$7$J$+$C$?$iL5>r7o$G9VFI$9$k%K%e!<%9%0%k!<%WL>$N@55,I=8=$G$9!#@55,I=\e(B
+\e$B8=$NJ8;zNs$G$O\e(B @dfn{$} \e$B$NBe$o$j$K\e(B @dfn{ } \e$B$r;H$C$F2<$5$$!#%5!<%P!<\e(B
+\e$B$,\e(B LIST \e$B%3%^%s%I$N%*%W%7%g%s$K%7%'%k7A<0$N%o%$%k%I%+!<%I$r<u$1IU$1$F$/$l\e(B
+\e$B$J$$>l9g$G$b!"\e(B@code{nntp-list-options} \e$B$HF1MM$N8z2L$,$"$k$G$7$g$&!#$3$l\e(B
+\e$B$O!"0J2<$N$h$&$K%5!<%P!<JQ?t$H$7$F;H$&$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+             (nntp-options-not-subscribe "\\.binaries\\.")))
+@end lisp
+@end table
+
+@menu
+* Direct Functions::            \e$B%5!<%P!<$KD>@\@\B3$9$k\e(B
+* Indirect Functions::          \e$B%5!<%P!<$K4V@\E*$K@\B3$9$k\e(B
+* Common Variables::            \e$B$$$/$D$+$N@\B3MQ$N4X?t$,;2>H$9$kJQ?t\e(B
+@end menu
+
+@node Direct Functions
+@subsubsection \e$BD>@\@\B3$9$k$?$a$N4X?t\e(B
+@cindex direct connection functions
+
+\e$B$3$l$i$N4X?t$O!"$"$J$?$N%^%7%s$H\e(B @acronym{NNTP}\e$B%5!<%P!<$r@\B3$9$k$?$a$K\e(B
+\e$BD>@\8F$P$l$^$9!#$^$?!"$=$l$i$NF0:n$O$=$l$i$,6&DL$K;2>H$9$kJQ?t$K1F6A$5$l\e(B
+\e$B$^$9\e(B (@pxref{Common Variables})\e$B!#\e(B
+
+@table @code
+@findex nntp-open-network-stream
+@item nntp-open-network-stream
+\e$B$3$l$O%G%#%U%)%k%H$G!"C1=c$K1s3V%7%9%F%`$N%]!<%H$J$I$K@\B3$7$^$9!#\e(B
+
+@findex nntp-open-tls-stream
+@item nntp-open-tls-stream
+@dfn{\e$B0BA4$J\e(B} \e$B%A%c%s%M%k$r;H$C$F%5!<%P!<$K@\B3$7$^$9!#$3$l$r;H$&$?$a$K\e(B
+\e$B$O\e(B @uref{http://www.gnu.org/software/gnutls/, GNUTLS} \e$B$r%$%s%9%H!<%k$7$F\e(B
+\e$B$*$+$J$1$l$P$J$j$^$;$s!#$=$l$+$i%5!<%P!<$r<!$N$h$&$KDj5A$7$^$9\e(B:
+
+@lisp
+;; @r{\e$B%]!<%H\e(B 563 \e$B$,\e(B "nntps" \e$B$H$7$F\e(B @file{/etc/services} \e$B$GDj5A:Q$_$G$"$C$F$b\e(B}
+;; @r{@samp{gnutls-cli -p} \e$B$G$=$NL>A0$O;H$($^$;$s!#\e(B}
+;;
+(nntp "snews.bar.com"
+      (nntp-open-connection-function nntp-open-tls-stream)
+      (nntp-port-number )
+      (nntp-address "snews.bar.com"))
+@end lisp
+
+@findex nntp-open-ssl-stream
+@item nntp-open-ssl-stream
+@dfn{\e$B0BA4$J\e(B} \e$B%A%c%s%M%k$r;H$C$F%5!<%P!<$K@\B3$7$^$9!#$3$l$r;H$&$?$a$K\e(B
+\e$B$O\e(B @uref{http://www.openssl.org, OpenSSL} \e$B$^$?\e(B
+\e$B$O\e(B @uref{ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL, SSLeay} \e$B$r%$%s%9%H!<%k$7\e(B
+\e$B$F$*$+$J$1$l$P$J$j$^$;$s!#$=$l$+$i%5!<%P!<$r<!$N$h$&$KDj5A$7$^$9\e(B:
+
+@lisp
+;; @r{\e$B%]!<%H\e(B 563 \e$B$,\e(B "snews" \e$B$H$7$F\e(B @file{/etc/services} \e$B$GDj5A:Q$_$G$"$C$F$b\e(B}
+;; @r{@samp{openssl s_client -port} \e$B$G$=$NL>A0$O;H$($^$;$s!#\e(B}
+;;
+(nntp "snews.bar.com"
+      (nntp-open-connection-function nntp-open-ssl-stream)
+      (nntp-port-number 563)
+      (nntp-address "snews.bar.com"))
+@end lisp
+
+@findex nntp-open-telnet-stream
+@item nntp-open-telnet-stream
+\e$BC1$K\e(B @samp{telnet} \e$B$7$F\e(B @acronym{NNTP} \e$B%5!<%P!<$K@\B3$7$^$9!#$"$J$?$O!"\e(B
+\e$B%G%#%U%)%k%H$N\e(B @code{nntp-open-network-stream} \e$B$,$=$l$r$9$k$N$K$b$+$+$o\e(B
+\e$B$i$:!"$J$<$3$N4X?t$,$"$k$N$+IT;W5D$K;W$&$+$b$7$l$^$;$s!#$=$NM}M3\e(B (\e$B$N0l\e(B
+\e$B$D\e(B) \e$B$O!"$b$7$"$J$?$,KIJI$NCf$K$$$?$H$7$F$b\e(B @code{runsocks} \e$B$N$h$&$J%3%^\e(B
+\e$B%s%I%i%C%Q!<$N$*$+$2$G30$N@$3&$rD>@\%"%/%;%9$G$-$k$J$i$P!"$"$J$?$O$=$l$r\e(B
+\e$B$3$N$h$&$K;H$&$3$H$,$G$-$k$N$G$9\e(B:
+
+@lisp
+(nntp "socksified"
+      (nntp-pre-command "runsocks")
+      (nntp-open-connection-function nntp-open-telnet-stream)
+      (nntp-address "the.news.server"))
+@end lisp
+
+Emacs \e$B$N%;%C%7%g%sA4BN$r%i%C%W$7$F!"%G%#%U%)%k%H$N%a%=%C%I$r;H$&$H$$$&$N\e(B
+\e$B$O!"NI$$0F$G$O$"$j$^$;$s!#\e(B
+@end table
+
+@node Indirect Functions
+@subsubsection \e$B4V@\E*$K@\B3$9$k$?$a$N4X?t\e(B
+@cindex indirect connection functions
+
+\e$B$3$l$i$N4X?t$O!"<B:]$K\e(B @acronym{NNTP} \e$B%5!<%P!<$K@\B3$9$kA0$KCf4V$N%[%9%H\e(B
+\e$B$K@\B3$9$k$?$a$K4V@\E*$K8F$P$l$^$9!#$9$Y$F$N$3$l$i$N4X?t$H4XO"$9$kJQ?t\e(B
+\e$B$O\e(B ``via'' \e$B@\B3$NCg4V$KB0$7$F$$$k$H$b8@$($k$N$G!"$=$l$rL@3N$K$9$k$?$a$K\e(B
+\e$B$9$Y$F\e(B ``via'' \e$B$H$$$&@\F,<-$,IU$1$i$l$^$9!#$^$?!"$=$l$i$NF0:n$O$=$l$i$,\e(B
+\e$B6&DL$K;2>H$9$kJQ?t$K1F6A$5$l$^$9\e(B (@pxref{Common Variables})\e$B!#\e(B
+
+@table @code
+@item nntp-open-via-rlogin-and-telnet
+@findex nntp-open-via-rlogin-and-telnet
+\e$B1s3V%7%9%F%`$K\e(B @samp{rlogin} \e$B$7$F!"$=$3$+$iK\Ev\e(B
+\e$B$N\e(B @acronym{NNTP} \e$B%5!<%P!<$K\e(B @samp{telnet} \e$B$7$^$9!#$3$l$O!"Nc$($P$"$J$?\e(B
+\e$B$,;O$a$KKIJI%^%7%s$K@\B3$7$J$1$l$P$J$i$J$$>l9g$KJXMx$G$9!#\e(B
+
+@code{nntp-open-via-rlogin-and-telnet}-\e$BMQ$NJQ?t\e(B:
+
+@table @code
+@item nntp-via-rlogin-command
+@vindex nntp-via-rlogin-command
+\e$BCf4V$N%[%9%H$K%m%0%$%s$9$k$?$a$K;H$o$l$k%3%^%s%I$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @samp{rsh} \e$B$G$9$,!"\e(B@samp{ssh} \e$B$,?M5$$N$"$kBeBX<jCJ$G$9!#\e(B
+
+@item nntp-via-rlogin-command-switches
+@vindex nntp-via-rlogin-command-switches
+@code{nntp-via-rlogin-command} \e$B$N%3%^%s%I$N%9%$%C%A$H$7$F;H$o$l$kJ8;zNs\e(B
+\e$B$N%j%9%H$G$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G$9!#$b\e(B
+\e$B$7\e(B @samp{ssh} \e$B$r\e(B @code{nntp-via-rlogin-command} \e$B$NCM$H$7$F;H$&$J$i$P!"%G!<\e(B
+\e$B%?@\B3$r05=L$9$k$?$a$K\e(B @samp{("-C")} \e$B$r;H$&$3$H$,$G$-$^$9!#$"$k$$$O!"$b\e(B
+\e$B$7Cf4V$N%[%9%H$G\e(B telnet \e$B%3%^%s%I$,5?;wC<Kv$rI,MW$H$9$k$J$i$P!"$3$l\e(B
+\e$B$r\e(B @samp{("-t" "-e" "none")} \e$B$^$?$O\e(B @samp{("-C" "-t" "-e" "none")} \e$B$K$7\e(B
+\e$B$F2<$5$$!#\e(B
+@end table
+
+@item nntp-open-via-telnet-and-telnet
+@findex nntp-open-via-telnet-and-telnet
+\e$BK\<AE*$K$OF1$8$3$H$J$N$G$9$,!"Cf4V$N%[%9%H$K@\B3$9$k$?$a\e(B
+\e$B$K\e(B @samp{rlogin} \e$B$NBe$o$j$K\e(B @samp{telnet} \e$B$r;H$$$^$9!#\e(B
+
+@code{nntp-open-via-telnet-and-telnet}-\e$BMQ$NJQ?t\e(B:
+
+@table @code
+@item nntp-via-telnet-command
+@vindex nntp-via-telnet-command
+\e$BCf4V$N%[%9%H$K\e(B @code{telnet} \e$B$9$k$?$a$K;H$o$l$k%3%^%s%I$G$9!#%G%#%U%)%k\e(B
+\e$B%H$O\e(B @samp{telnet} \e$B$G$9!#\e(B
+
+@item nntp-via-telnet-switches
+@vindex nntp-via-telnet-switches
+@code{nntp-via-telnet-command} \e$B$N%3%^%s%I$N%9%$%C%A$H$7$F;H$o$l$kJ8;zNs\e(B
+\e$B$N%j%9%H$G$9!#%G%#%U%)%k%H$O\e(B @samp{("-8")} \e$B$G$9!#\e(B
+
+@item nntp-via-user-password
+@vindex nntp-via-user-password
+\e$BCf4V$N%[%9%H$K%m%0%$%s$9$k$H$-$K;H$o$l$k%Q%9%o!<%I$G$9!#\e(B
+
+@item nntp-via-envuser
+@vindex nntp-via-envuser
+\e$B$b$7Hs\e(B@code{nil}\e$B$J$i!"Cf4V$N\e(B @code{telnet} \e$B$N%;%C%7%g%s\e(B (\e$B%/%i%$%"%s%H$H\e(B
+\e$B%5!<%P!<$NN>J}\e(B) \e$B$G\e(B @code{ENVIRON} \e$B%*%W%7%g%s$r%5%]!<%H$7!"%m%0%$%sL>$NF~\e(B
+\e$BNO$rMW5a$7$^$;$s!#$3$l$ONc$($P\e(B Solaris \e$B$N\e(B @code{telnet} \e$B$GF0:n$7$^$9!#\e(B
+
+@item nntp-via-shell-prompt
+@vindex nntp-via-shell-prompt
+\e$BCf4V$N%[%9%H$G$N%7%'%k$N%W%m%s%W%H$K9gCW$9$k@55,I=8=$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @samp{bash\\|\$ *\r?$\\|> *\r?} \e$B$G$9!#\e(B
+@end table
+@end table
+
+\e$B$3$l$i$O>e5-$N4X?t$,;2>H$9$kIU2CE*$JJQ?t$G$9\e(B:
+
+@table @code
+@item nntp-via-user-name
+@vindex nntp-via-user-name
+\e$BCf4V$N%[%9%H$K@\B3$9$k$H$-$K;H$&MxMQ<TL>$G$9!#\e(B
+
+@item nntp-via-address
+@vindex nntp-via-address
+\e$B@\B3$9$kCf4V$N%[%9%H$N%"%I%l%9$G$9!#\e(B
+@end table
+
+@node Common Variables
+@subsubsection \e$B6&DL$NJQ?t\e(B
+
+\e$B0J2<$NJQ?t$O!"$9$Y$F$N!"$^$?$O$$$/$D$+$N$"$i$+$8$aMQ0U$5$l$F$$$k4X?t$NF0\e(B
+\e$B:n$K1F6A$r5Z$\$7$^$9!#@_Dj$5$l$F$$$J$1$l$P!"$9$Y$F$N4X?t$,1F6A$5$l$^$9!#\e(B
+
+@table @code
+@item nntp-pre-command
+@vindex nntp-pre-command
+\e$BAG$N@\B3MQ$N4X\e(B
+\e$B?t\e(B (@code{nntp-open-network-stream}\e$B!"\e(B@code{nntp-open-tls-stream} \e$B$*$h\e(B
+\e$B$S\e(B @code{nntp-open-ssl-stream} \e$B$@$1$@$H;W$&\e(B) \e$B$G$O$J$$$b$N$rDL$7$F@\B3$9\e(B
+\e$B$k$H$-$K;H$&%3%^%s%I%i%C%Q!<$G$9!#Nc$($P$"$J$?$O\e(B @samp{SOCKS} \e$B%i%C%Q!<$r\e(B
+\e$B3d$jEv$F$k$G$7$g$&!#\e(B
+
+@item nntp-address
+@vindex nntp-address
+@acronym{NNTP} \e$B%5!<%P!<$N%"%I%l%9$G$9!#\e(B
+
+@item nntp-port-number
+@vindex nntp-port-number
+\e$B@\B3$9$k\e(B @acronym{NNTP} \e$B%5!<%P!<$N%]!<%HHV9f$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @samp{nntp} \e$B$G$9!#\e(B@acronym{TLS}/@acronym{SSL} \e$B$r2p$7\e(B
+\e$B$?\e(B @acronym{NNTP} \e$B$r;H$&$K$O!"%]!<%H$NL>A0$G$O$J$/$F@0?t\e(B (\e$B$D$^\e(B
+\e$B$j\e(B @samp{snews} \e$B$d\e(B @samp{nntps} \e$B$G$O$J$/$F\e(B @samp{563}) \e$B$r;XDj$9$kI,MW$,\e(B
+\e$B$"$j$^$9!#30It$N\e(B @acronym{TLS}/@acronym{SSL} \e$B%D!<%k$O%]!<%H$NL>A0$G$OF0\e(B
+\e$B:n$7$J$$$+$i$G$9!#\e(B
+
+@item nntp-end-of-line
+@vindex nntp-end-of-line
+@acronym{NNTP} \e$B%5!<%P!<$H$*OC$r$7$F$$$k$H$-$K9T$N=*$o$j$N0u$H$7$F;H$o$l\e(B
+\e$B$kJ8;zNs$G$9!#$3$l$O%G%#%U%)%k%H$G\e(B @samp{\r\n} \e$B$G$9$,!"AG$G$O$J$$@\B3MQ\e(B
+\e$B$N4X?t$r;H$C$F$$$k$H$-$O\e(B @samp{\n} \e$B$G$"$k$Y$-$G$9!#\e(B
+
+@item nntp-telnet-command
+@vindex nntp-telnet-command
+@samp{telnet} \e$B$rDL$7$F\e(B @acronym{NNTP} \e$B%5!<%P!<$H@\B3$9$k$H$-$K;H$&%3%^%s\e(B
+\e$B%I$G$9!#$3$l$OCf4V$N%[%9%H$H@\B3$9$k$?$a$N$b$N$G$O\e(B @emph{\e$B$"$j$^$;$s\e(B}\e$B!#$3\e(B
+\e$B$l$OC1$KK\Ev$N\e(B @acronym{NNTP} \e$B%5!<%P!<$H@\B3$9$k$?$a$N$b$N$G$9!#%G%#%U%)\e(B
+\e$B%k%H$O\e(B @samp{telnet} \e$B$G$9!#\e(B
+
+@item nntp-telnet-switches
+@vindex nntp-telnet-switches
+@code{nntp-telnet-command} \e$B$KEO$9%9%$%C%A$N%j%9%H$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @samp{("-8")} \e$B$G$9!#\e(B
+@end table
+
+@node News Spool
+@subsection \e$B%K%e!<%9%9%W!<%k\e(B
+@cindex nnspool
+@cindex new spool
+
+\e$B%m!<%+%k%9%W!<%k$+$i30It%0%k!<%W$r9XFI$9$k;v$OHs>o$K4JC1$G!"Lr$KN)$A$^$9!#\e(B
+\e$B$?$H$($P!"Hs>o$KBg$-$J5-;v$,$"$k%0%k!<%W\e(B---\e$BNc$(\e(B
+\e$B$P\e(B @samp{alt.binaries.pictures.furniture} \e$B$rFI$`B.EY$,B.$/$J$j$^$9!#\e(B
+
+\e$B$H$K$+$/!"\e(B@code{nnspool} \e$B$rJ}K!$H$7$F!"\e(B@code{""} (\e$B$b$7$/$O2?$G$b\e(B) \e$B$r%"%I\e(B
+\e$B%l%9$H$7$F;XDj$9$k$@$1$G$9!#\e(B
+
+\e$B$b$7%m!<%+%k%9%W!<%k$K$D$J$0;v$,2DG=$J$i!"$*$=$i$/$=$l$r4pK\A*BrJ}K!$H$7\e(B
+\e$B$F;H$&$Y$-$G$7$g$&\e(B (@pxref{Finding the News})\e$B!#$=$l$OIaDL\e(B
+\e$B$O\e(B @code{nntp} \e$BA*BrJ}K!$h$jB.$$$G$9$,!"$=$&$G$J$$$+$b$7$l$^$;$s!#$=$l$O\e(B
+\e$B>u67$K0MB8$7$^$9!#2?$,$"$J$?$N%5%$%H$G0lHVNI$$$+$r8+$D$1$k$?$a$K!"$$$m$$\e(B
+\e$B$m$H;n$7$F$_$J$1$l$P$J$j$^$;$s!#\e(B
+
+@table @code
+@item nnspool-inews-program
+@vindex nnspool-inews-program
+\e$B5-;v$rEj9F$9$k$?$a$K;H$o$l$k%W%m%0%i%`$G$9!#\e(B
+
+@item nnspool-inews-switches
+@vindex nnspool-inews-switches
+\e$B5-;v$rEj9F$9$k$H$-$K\e(B inews \e$B%W%m%0%i%`$KM?$($i$l$k%Q%i%a!<%?$G$9!#\e(B
+
+@item nnspool-spool-directory
+@code{nnspool} \e$B$,5-;v$rC5$9$H$3$m$G$9!#$3$l$OIaDL\e(B
+\e$B$O\e(B @file{/usr/spool/news/} \e$B$G$9!#\e(B
+
+@item nnspool-nov-directory
+@vindex nnspool-nov-directory
+@code{nnspool} \e$B$,\e(B @acronym{NOV} \e$B%U%!%$%k$rC5$9$H$3$m$G$9!#$3$l$OIaDL\e(B
+\e$B$O\e(B @file{/usr/spool/news/over.view/} \e$B$G$9!#\e(B
+
+@item nnspool-lib-dir
+@vindex nnspool-lib-dir
+\e$B%K%e!<%9$N%i%$%V%i%j!<%G%#%l%/%H%j!<$N>l=j$G$9\e(B (\e$B%G%#%U%)%k%H\e(B
+\e$B$G\e(B @file{/usr/lib/news/} \e$B$G$9\e(B)\e$B!#\e(B
+
+@item nnspool-active-file
+@vindex nnspool-active-file
+\e$B%"%/%F%#%V%U%!%$%k$NL>A0$G$9!#\e(B
+
+@item nnspool-newsgroups-file
+@vindex nnspool-newsgroups-file
+\e$B%0%k!<%W5-=R%U%!%$%k$NL>A0$G$9!#\e(B
+
+@item nnspool-history-file
+@vindex nnspool-history-file
+\e$B%K%e!<%9MzNr%U%!%$%k$NL>A0$G$9!#\e(B
+
+@item nnspool-active-times-file
+@vindex nnspool-active-times-file
+\e$B8=>uF|IU%U%!%$%k$X$NL>A0$G$9!#\e(B
+
+@item nnspool-nov-is-evil
+@vindex nnspool-nov-is-evil
+@code{nil} \e$B$G$J$$$H!"\e(B@code{nnspool} \e$B$O$=$l$,8+$D$1$?$I$s\e(B
+\e$B$J\e(B @acronym{NOV} \e$B%U%!%$%k$b;H$*$&$H$O$7$^$;$s!#\e(B
+
+@item nnspool-sift-nov-with-sed
+@vindex nnspool-sift-nov-with-sed
+@cindex sed
+@code{nil} \e$B$G$J$$$H!"$3$l$,%G%#%U%)%k%H$G$9$,!"354Q%U%!%$%k\e(B (overview)
+\e$B$+$i4XO"$9$kItJ,$rF@$k$?$a$K\e(B @code{sed} \e$B$r;H$$$^$9!#$b$7\e(B @code{nil} \e$B$@$H!"\e(B
+@code{nnspool} \e$B$O%U%!%$%kA4BN$r%P%C%U%!$KFI$_9~$s$G!"$=$3$G<B9T$7$^$9!#\e(B
+@end table
+
+@node Getting Mail
+@section \e$B%a!<%k<hF@\e(B
+@cindex reading mail
+@cindex mail
+
+\e$B%K%e!<%9%j!<%@!<$G%a!<%k$rFI$`\e(B---\e$B$=$l$OL@Gr$KD6<+A3E*$J;v$G$O$J$$$N$G$9\e(B
+\e$B$+\e(B? \e$B$$$d!"$b$A$m$s$G$-$^$9!#\e(B
+
+@menu
+* Mail in a Newsreader::        \e$B%K%e!<%9%j!<%@$G%a!<%k\e(B (\e$BBg;v$JA0CV$-\e(B)
+* Getting Started Reading Mail::  \e$B4JC1$JNAM}K\$N$h$&$JNc\e(B
+* Splitting Mail::              \e$B$I$N$h$&$K%a!<%k%0%k!<%W$r:n@.$9$k$+\e(B
+* Mail Sources::                Gnus \e$B$K$I$3$+$i%a!<%k$r<h$C$F$/$k$+$rCN$i$;$k\e(B
+* Mail Back End Variables::     \e$B%a!<%k$N07$$$r%+%9%?%^%$%:$9$k$?$a$NJQ?t\e(B
+* Fancy Mail Splitting::        Gnus \e$B$OF~$C$FMh$?%a!<%k$r!"?H$NLS$N$h$@$D$h$&$JJ,3d$r$9$k$3$H$,$G$-$k\e(B
+* Group Mail Splitting::        \e$B%a!<%kJ,3d$r6nF0$9$k$?$a$K%0%k!<%W%+%9%?%^%$%:$r;H$&\e(B
+* Incorporating Old Mail::      \e$B$"$J$?$,;}$C$F$$$k8E$$%a!<%k$r$I$&$9$k$+\e(B?
+* Expiring Mail::               \e$BM_$7$/$J$$%a!<%k$r<h$j=|$/\e(B
+* Washing Mail::                \e$B<hF@$7$?%a!<%k$+$iMW$i$J$$$b$N$r<h$j=|$/\e(B
+* Duplicates::                  \e$B=EJ#$7$?%a!<%k$r07$&\e(B
+* Not Reading Mail::            \e$BB>$N%U%!%$%k$rFI$`$?$a$K%a!<%k%P%C%/%(%s%I$r;H$&\e(B
+* Choosing a Mail Back End::    Gnus \e$B$O?'!9$J%a!<%kMM<0$rFI$`;v$,$G$-$k\e(B
+@end menu
+
+@node Mail in a Newsreader
+@subsection \e$B%K%e!<%9%j!<%@$G%a!<%k\e(B
+
+\e$B$"$J$?$,EAE}E*$J%a!<%k%j!<%@$+$i\e(B gnus \e$B$K>h$j49$($k$3$H$r7hCG$7$?$J$i$P!"\e(B
+\e$B$"$J$?$O$$$m$$$m$J%+%k%A%c!<%7%g%C%/$r<u$1$k$3$H$G$7$g$&!#\e(B
+
+gnus \e$B$OEAE}E*$J%a!<%k%j!<%@$N$h$&$J$U$k$^$$$r$7$^$;$s!#$"$J$?$,K>$`$J\e(B
+\e$B$i$=$N$h$&$K$b$G$-$^$9$,!"$=$l$O9|@^$jB;$N$/$?$S$lLY$1$G$9!#\e(B
+
+gnus \e$B$O$U$D$&F1$8<jK!$G$9$Y$F$N%0%k!<%W$r07$$$^$9!#$"$J$?$O$"$k%0%k!<\e(B
+\e$B%W$rA*$s$G?7$7$$\e(B/\e$BL$FI$N5-;v$rFI$`!"$=$7$FFI$s$@5-;v$O4{FI$H$7$F%^!<%/\e(B
+\e$B$5$l$k!#$"$J$?$,L\$K$9$k$N$O\e(B (\e$B$"$J$?$,0U?^E*$K?R$M$J$1$l$P\e(B) \e$B$=$l$@$1$G\e(B
+\e$B$9!#$3$l$C$F$H$F$b%K%e!<%9%j!<%@E*$G$7$g!#\e(B
+
+\e$B$"$J$?$O5-;v$r>C$9$?$a$KFCJL$JA`:n$O$7$^$;$s!#\e(B
+
+\e$B$3$N$3$H$O4{FI$N5-;v$O$9$Y$F>C$5$l$F$7$^$&$3$H$r0UL#$9$k$N$+$C$F\e(B? \e$B$=$j$c\e(B
+\e$B$"$s$^$j$G$9$h$M\e(B!
+
+\e$B$=$&$G$O$"$j$^$;$s!#8E$$5-;v$O$$$m$s$J;EAH$_$K$h$C$F\e(B @dfn{expire} \e$B$5$l\e(B
+\e$B$k$N$G$9!#%K%e!<%95-;v$O%K%e!<%9$N4IM}?M\e(B (\e$B$,4IM}$7$F$$$k%5!<%P\e(B) \e$B$K$h$C\e(B
+\e$B$F\e(B expire \e$B$N=hM}$,@)8f$5$l!"%a!<%k$N\e(B expire \e$B$N=hM}$O$"$J$?$,@)8f$7$^$9!#\e(B
+\e$B%a!<%k$N\e(B expire \e$B$K$D$$$F$O\e(B @ref{Expiring Mail} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+\e$B$7$P$i$/%a!<%k$H%K%e!<%9$NN>J}$r;H$C$F$_$l$P!"5-;v$N<h$j07$$$K$D$$$FG[\e(B
+\e$BAw$N5!9=$,9T$J$&$3$H$O$o$:$+$G$"$k$3$H$K5$$,IU$-$^$9!#\e(B
+
+\e$BB?$/$N?M$?$A$OJ#?t$N%a!<%j%s%0%j%9%H$r9VFI$7$F$$$^$9!#$=$l$i\e(B
+\e$B$O\e(B @acronym{SMTP} \e$B$GG[Aw$5$l$k!"%a!<%k!"$G$9!#$=$l$i$N5-;v$r$H$F$bCm0U?<\e(B
+\e$B$/FI$s$G$$$k$K$b$+$+$o$i$:!"2?=54V$bJV;v$,L5$$$3$H$,$"$k$G$7$g$&!#;d$?$A\e(B
+\e$B$O$=$&$$$&5-;v$r%;!<%V$9$kI,MW$O$"$j$^$;$s!#$J$<$J$i$P!"$b$&0lEYFI$`I,MW\e(B
+\e$B$,@8$8$F$b!"$=$l$i$O$I$3$+$KJ]B8$5$l$F$$$k$+$i$G$9!#\e(B
+
+\e$B$"$k?M$?$A$O>.?M?t$KMxMQ$5$l$F$$$k%m!<%+%k%K%e!<%9%0%k!<%W$r9VFI$7$F$$$^\e(B
+\e$B$9!#$=$l$i$O\e(B @acronym{NNTP} \e$B$GG[Aw$5$l$k!"%K%e!<%9!"$G$9!#;d$?$A$O<+J,$N\e(B
+\e$B;E;v$KLrN)$F$k$?$a$K!"$=$l$i$NKDBg$J5-;v$NCGJR$rFI$s$@$jJV;v$r$7$J$1$l$P\e(B
+\e$B$J$j$^$;$s!#$=$7$F$=$l$i$OJ]B8$5$l$F$$$J$$$+$b$7$l$^$;$s$+$i!"6=L#$N$"$k\e(B
+\e$B5-;v$r8D?M%a!<%k$HF1$8$h$&$KJ]B8$7$J$1$l$P$J$i$J$$$G$7$g$&!#\e(B
+
+\e$BG[Aw$N;EAH$_$N0c$$$O$I$&$G$b$h$$$3$H$G!"Bg;v$J$N$O$$$+$K<gBj$K6=L#$r;}$C\e(B
+\e$B$F$$$k$+$H!"$b$&0lEYFI$_$?$$$H$-$K$$$+$K4JC1$K8F$S=P$;$k$+$J$N$G$9!#\e(B
+
+gnus \e$B$O%a!<%k$r%K%e!<%9%0%k!<%W$N$h$&$K\e(B ``\e$B%0%k!<%W\e(B'' \e$B$KJB$YJQ$($F!"3F!9\e(B
+\e$B$N%0%k!<%W\e(B (\e$B%a!<%k$+%K%e!<%9\e(B) \e$B$rJL8D$K07$&$?$a$NK-IY$J5!G=$rDs6!$7$^$9!#\e(B
+
+\e$B$"$k?M$?$A$O\e(B gnus (\e$B$($C$X$s\e(B) \e$B$N$d$j$+$?$KK~B-$G$-$J$/$F!"\e(Bgnus \e$B$,%a!<%k\e(B
+\e$B%j!<%@$K$J$k$3$H$rM_$7$^$9!#\e(Bgnus \e$B$r$b$C$H%a!<%k%j!<%@E*$J$b$N$K$9$k$?\e(B
+\e$B$a$KJ\BG$D$3$H$O2DG=$G$O$"$k$N$G$9$,!"A0$K$b8@$C$?$h$&$K4JC1$G$O$"$j$^\e(B
+\e$B$;$s!#$$$o$f$k%a!<%k%j!<%@$,9%$_$J$i$P\e(B @sc{vm} \e$B$r;H$$$^$7$g$&!#$3$l$O\e(B
+\e$BM%=($J!"87L)$J0UL#$G$N%a!<%k%j!<%@$G$9!#\e(B
+
+\e$B6<$+$9$o$1$G$O$J$$$N$G$9$,!"$O$C$-$j$5$;$F$*$-$?$$$N$O!"$"$J$?$K5-;v$K\e(B
+\e$B$D$$$F$N?7$7$$$d$jJ}$r=$F@$7$FM_$7$$$H$$$&$3$H$G$9!#$"$J$?$,\e(B gnus \e$B$N$d\e(B
+\e$B$jJ}$r<u$1F~$l$F$/$l$?6G$K$O!"$-$C$H$"$J$?$O\e(B gnus \e$B$,9%$-$K$J$k$3$H@A$1\e(B
+\e$B9g$$$G$9!#\e(B
+
+(\e$B>/$/$H$b!";d$,\e(B gnus \e$B$KF~$l$?!"\e(BEmacs \e$B$N%5%V%j%_%J%kG>L#A9@vBu4X?t$rGd$C\e(B
+\e$B$F$/$l$??M$O$=$l$rJ]>Z$7$F$$$^$9!#$"$J$?$bF12=$7$^$9!#$"$J$?$O\e(B gnus \e$B$r0&\e(B
+\e$B$7$^$9!#$"$J$?$O\e(B gnus \e$B$G$N%a!<%k$NJ}K!$r0&$7$^$9!#@dBP$K!#\e(B)
+
+@node Getting Started Reading Mail
+@subsection \e$B%a!<%k$rFI$`;v$r;O$a$k\e(B
+
+Gnus \e$B$r;H$C$F?7$7$$%a!<%k$rFI$`;v$OHs>o$K4JC1$G$9!#$"$J$?$N%a!<%k%P%C%/\e(B
+\e$B%(%s%I$N$"$J$?$NA*Br$r\e(B @code{gnus-secondary-select-methods} \e$B$KJ|$j9~$`$@\e(B
+\e$B$1$G!"$"$H$N$3$H$O<+F0E*$K5/$3$j$^$9!#\e(B
+
+\e$BNc$($P!"\e(B@code{nnml} (\e$B$3$l$O\e(B ``\e$B0l%a!<%k0l%U%!%$%k\e(B'' \e$B%P%C%/%(%s%I$G$9\e(B) \e$B$r\e(B
+\e$B;H$$$?$$$J$i!"<!$N$b$N$r$"$J$?$N\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$k;v$,\e(B
+\e$B$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-secondary-select-methods '((nnml "")))
+@end lisp
+
+\e$B:#$d!"<!$K\e(B gnus \e$B$r5/F0$7$?$H$-$K$O!"$3$N%P%C%/%(%s%I$O?7$7$$5-;v$r5a$a!"\e(B
+\e$B$=$l$O$"$J$?$N%9%W!<%k%U%!%$%k$+$iA4$F$N%a%C%;!<%8$r%G%#%l%/%H%j!<!"%G%#\e(B
+\e$B%U%)%k%H$G$O\e(B @file{~/Mail/} \e$B$K0\F0$7$^$9!#:n@.$5$l$??7$7$$%0%k!<\e(B
+\e$B%W\e(B (@samp{mail.misc}) \e$B$,9XFI$5$l!"B>$N%0%k!<%W$HF1$8$h$&$KFI$`;v$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+\e$B$"$J$?$O$*$=$i$/%a!<%k$r$$$/$D$+$N%0%k!<%W$KJ,3d$7$?$$$G$7$g$&$1$I\e(B:
+
+@lisp
+(setq nnmail-split-methods
+      '(("junk" "^From:.*Lars Ingebrigtsen")
+        ("crazy" "^Subject:.*die\\^Organization:.*flabby")
+        ("other" "")))
+@end lisp
+
+\e$B$3$l$O7k2L$H$7$F;0$D$N?7$7$$\e(B @code{nnml} \e$B%a!<%k%0%k!<%W$r:n$j$^\e(B
+\e$B$9\e(B: @samp{nnml:junk}, @samp{nnml:crazy}, @samp{nnml:other} \e$B$G$9!#:G=i\e(B
+\e$B$NFs$D$N%0%k!<%W$K9g$o$J$$%a!<%k$OA4$F:G8e$N%0%k!<%W$KF~$l$i$l$^$9!#\e(B
+
+\e$B$3$l$O\e(B gnus \e$B$G%a!<%k$rFI$`$?$a$K=<J,$G$"$k$O$:$G$9!#%^%K%e%"%k$N$3$NItJ,\e(B
+\e$B$NB>$N9`$r=OFI$9$kI,MW$,$"$k$+$b$7$l$^$;$s$,!#FC\e(B
+\e$B$K\e(B @ref{Choosing a Mail Back End} \e$B$H\e(B @ref{Expiring Mail} \e$B$r!#\e(B
+
+@node Splitting Mail
+@subsection \e$B%a!<%k$NJ,3d\e(B
+@cindex splitting mail
+@cindex mail splitting
+@cindex mail filtering (splitting)
+
+@vindex nnmail-split-methods
+\e$BJQ?t\e(B @code{nnmail-split-methods} \e$B$OF~$C$F$/$k%a!<%k$r$I$N$h$&$K%0%k!<%W\e(B
+\e$BJ,$1$9$k$+$r;XDj$7$^$9!#\e(B
+
+@lisp
+(setq nnmail-split-methods
+  '(("mail.junk" "^From:.*Lars Ingebrigtsen")
+    ("mail.crazy" "^Subject:.*die\\|^Organization:.*flabby")
+    ("mail.other" "")))
+@end lisp
+
+\e$B$3$NJQ?t$O%j%9%H$N%j%9%H$G!"$3$l$i$N%j%9%H$N:G=i$N$=$l$>$l$NMWAG$,%a!<%k\e(B
+\e$B%0%k!<%W$NL>A0$G\e(B (\e$B$H$3$m$G!"$=$l$i$O\e(B @samp{mail} \e$B$G;O$^$kI,MW$O$"$j$^$;\e(B
+\e$B$s\e(B)\e$B!"Fs$D$a$NMWAG$,$=$l$>$l$N%a!<%k$N%X%C%@!<$+$i$=$l$,$I$N%0%k!<%W$KB0\e(B
+\e$B$9$k$+$r7hDj$9$k@55,I=8=$G$9!#:G=i$NJ8;zNs$O!"\e(B@code{replace-match} \e$B$K$h$C\e(B
+\e$B$F!"9gCW$7$?J8>O$+$i$NI{I=8=$rA^F~$9$k$?$a$K;H$o$l$k$h$&$J!"\e(B
+@code{samp\\1} \e$B$NMM<0$r4^$`$+$b$7$l$^$;$s!#$?$H$($P\e(B:
+
+@lisp
+("list.\\1" "From:.* \\(.*\\)-list@@majordomo.com")
+@end lisp
+
+\e$BFsHVL\$NMWAG$O4X?t$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"$=$l$OK!B'$N:G=i$NMWAG\e(B
+\e$B$r0z?t$H$7$F!"%X%C%@!<$KHO0O$r69$a$F\e(B (narrowed to headers) \e$B8F$P$l$^$9!#\e(B
+\e$B$=$l$O!"%a!<%k$,$=$N%0%k!<%W$KB0$9$k$H9M$($k$N$G$"$l$P!"\e(B@code{nil} \e$B$G$J\e(B
+\e$B$$CM$r5"$9I,MW$,$"$j$^$9!#\e(B
+
+\e$B$3$l$i$N:G8e$O>o$KAm9gE*$J$b$N$G$"$k$Y$-$G!"B>$N@55,I=8=$K9gCW$7$J$$%a!<\e(B
+\e$B%k$K9gCW$9$k$?$a$K!"$3$N@55,I=8=$O\e(B @emph{\e$B$$$D$b\e(B} @samp{*}\e$B$G$"$k$Y$-$G$9!#\e(B
+(\e$B$3$l$i$NK!B'$OO"A[%j%9%H$N=i$a$+$i=*$o$j$^$G=gHV$K<B9T$5$l$^$9!#Aj8_Ej\e(B
+\e$B9F\e(B (crosspost) \e$B$r;HMQ2DG=$K$7$F$$$J$$8B$j!":G=i$N9gCW$7$?K!B'$,\e(B ``\e$B>!$A$^\e(B
+\e$B$9\e(B''\e$B!#Aj8_Ej9F$r;HMQ2DG=$K$7$F$$$k>l9g!"A4$F$N9gCW$7$?K!B'$,\e(B ``\e$B>!$A$^\e(B
+\e$B$9\e(B''\e$B!#\e(B)
+
+\e$B$b$7$"$J$?<+?H$G$3$l$r$$$8$/$j$^$o$7$?$$$H$-$O!"$"$J$?$NA*$s$@4X?t$r$3$N\e(B
+\e$BJQ?t$K@_Dj$9$k;v$,$G$-$^$9!#$3$N4X?t$OF~$C$FMh$?%a!<%k%a%C%;!<%8$N%X%C%@!<\e(B
+\e$B$KHO0O$r69$a$i$l$?%P%C%U%!$G0z?t$J$7$G8F$P$l$^$9!#$3$N4X?t$O!"$=$l$,$3$N\e(B
+\e$B%a!<%k%a%C%;!<%8$r1?$V$Y$-$G$"$k!"$H9M$($k%0%k!<%WL>$N%j%9%H$rJV$9$Y$-$G\e(B
+\e$B$9!#\e(B
+
+\e$BA4$F$N%a!<%k%P%C%/%(%s%I$O!"F~$C$FMh$?IOK3$G=c?h$J%X%C%@!<$rMpK=$K07$C$F\e(B
+\e$B$bNI$$;v$KCm0U$7$F$/$@$5$$!#$=$l$i$O$9$Y$F\e(B @code{Lines} \e$B%X%C%@!<$rDI2C$7\e(B
+\e$B$^$9!#$$$/$D$+$O\e(B @code{X-Gnus-Group} \e$B%X%C%@!<$r2C$($^$9!#$?$$$F$$$N$b$N\e(B
+\e$B$O\e(B Unix \e$B$N\e(B mbox \e$B$N\e(B @code{From<SPACE>} \e$B9T$r2?$+JL$NL>A0$KJQ$($^$9!#\e(B
+
+@vindex nnmail-crosspost
+\e$B%a!<%k%P%C%/%(%s%I$O$9$Y$FAj8_Ej9F$N5!G=$rDs6!$7$F$$$^$9!#$$$/$D$+$N@55,\e(B
+\e$BI=8=$,9gCW$9$k$H!"%a!<%k$OA4$F$N%0%k!<%W$K\e(B ``\e$BAj8_Ej9F\e(B'' \e$B$5$l$^$9!#\e(B
+@code{nnmail-crosspost} \e$B$O$3$N5!G=$r;H$&$+$I$&$+$r;XDj$7$^$9!#$I$N5-;v$b\e(B
+\e$BAm9g$N\e(B (@samp{*}) \e$B%0%k!<%W$KAj8_Ej9F$5$l$J$$;v$KCm0U$7$F$/$@$5$$!#\e(B
+
+@vindex nnmail-crosspost-link-function
+@cindex crosspost
+@cindex links
+@code{nnmh} \e$B$H\e(B @code{nnml} \e$B$OAj8_Ej9F$5$l$?5-;v$K%O!<%I%j%s%/\e(B (hardlink)
+\e$B$r:n$k;v$K$h$C$FAj8_Ej9F$r9T$$$^$9!#$7$+$7!"A4$F$N%U%!%$%k%7%9%F%`$,%O!<\e(B
+\e$B%I%j%s%/$N5!G=$rDs6!$7$F$$$k$o$1$G$O$"$j$^$;$s!#$b$7$"$J$?$,$=$N>l9g$KEv\e(B
+\e$B$F$O$^$k$N$G$"$l$P!"\e(B
+@code{nnmail-crosspost-link-function} \e$B$r\e(B @code{copy-file} \e$B$K@_Dj$7$F$/$@\e(B
+\e$B$5$$!#\e(B(\e$B$3$NJQ?t$O%G%#%U%)%k%H$G\e(B @code{add-name-to-file} \e$B$G$9!#\e(B)
+
+@kindex M-x nnmail-split-history
+@findex nnmail-split-history
+\e$BA0$N%a!<%kJ,3d$,%a%C%;!<%8$r$I$3$KF~$l$?$+$r8+$?$$>l9g$O!"L?Na\e(B @kbd{M-x
+nnmail-split-history} \e$B$r;H$&;v$,$G$-$^$9!#$3$l$+$i%9%W!<%k$7D>$=$&$H$9$k\e(B
+\e$B%a%C%;!<%8$,$I$3$KF~$k$+$r8+$?$$>l9g$O!"\e(B
+@code{gnus-summary-respool-trace} \e$B$H4XO"$9$kL?\e(B
+\e$BNa\e(B (@pxref{Mail Group Commands}) \e$B$r;H$&;v$,$G$-$^$9!#\e(B
+
+@vindex nnmail-split-header-length-limit
+@code{nnmail-split-header-length-limit} \e$B$N@)8B$h$jD9$$%X%C%@!<9T$O!"J,3d\e(B
+\e$B4X?t$N=hM}BP>]$+$i=|30$5$l$^$9!#\e(B
+
+@vindex nnmail-mail-splitting-charset
+@vindex nnmail-mail-splitting-decodes
+(\e$BLuCm\e(B: \e$B%*%j%8%J%k$N\e(B Gnus \e$B$H$O;EMM$,HyL/$K0[$J$k$3$H$KCm0U$7$F2<$5$$\e(B) \e$B%G%#\e(B
+\e$B%U%)%k%H$G$OJ,3d%3!<%I$O\e(B @acronym{MIME} \e$B%(%s%3!<%I$5$l$?%X%C%@!<$r%G%3!<\e(B
+\e$B%I$9$k$N$G!"Hs\e(B-@acronym{ASCII} \e$BJ8;zNs$K%^%C%A$5$;$k$3$H$,$G$-$^$9!#JQ\e(B
+\e$B?t\e(B @code{nnmail-mail-splitting-charset} \e$B$,\e(B @acronym{MIME} \e$BJ8;z=8\e(B
+\e$B9g\e(B (mime-charset) \e$B$G$"$C$?$i$=$l!"\e(B@acronym{MIME} \e$BJ8;z=89g$G$O$J$$\e(B
+\e$BHs\e(B-@code{nil} \e$B$JCM$@$C$?$i$=$N$H$-$N\e(B @code{default-mime-charset} \e$B$NCM$G!"\e(B
+(@acronym{MIME} \e$B%(%s%3!<%I$5$l$?$b$N$G$O$J$$\e(B) \e$BHs\e(B-@acronym{ASCII} \e$B%S%C%H\e(B
+\e$B%Q%?!<%s$b%G%3!<%I$7$^$9!#$3$NF0:n\e(B
+\e$B$O\e(B @code{nnmail-mail-splitting-decodes} \e$B$r\e(B @code{nil} \e$B$K$9$k$3$H$K$h$C$F\e(B
+\e$B40A4$K;_$a$k$3$H$,$G$-!"@8$N%X%C%@!<$N%G!<%?$r85$K5-;v$K%^%C%A$5$;$?$$>l\e(B
+\e$B9g$K$OM-8z$G$7$g$&!#\e(B
+
+@vindex nnmail-resplit-incoming
+\e$B%G%#%U%)%k%H$G$OF~$C$F$/$k$9$Y$F$N%a%C%;!<%8$KBP$7$FJ,3d$,F/$-$^$9!#$b\e(B
+\e$B$7\e(B @code{mail-sources} \e$BJQ\e(B
+\e$B?t\e(B (@pxref{Mail Source Specifiers}) \e$B$K\e(B @code{directory} \e$B$N9`$r@_Dj$7$F$b!"\e(B
+\e$B$7$+$7!"%G%#%U%)%k%H$G$OJ,3d$O\e(B @emph{\e$B5/$3$j$^$;$s\e(B}\e$B!#JQ\e(B
+\e$B?t\e(B @code{nnmail-resplit-incoming} \e$B$rHs\e(B-@code{nil} \e$B$JCM$K@_Dj$9$k$3$H$K$h$C\e(B
+\e$B$F!"$3$N>l9g$G$bJ,3d$r5/$3$5$;$k$3$H$,$G$-$^$9!#\e(B(\e$B$3$NJQ?t$OB>$N<oN`$N9`\e(B
+\e$BL\$KBP$7$F$O8z2L$,$"$j$^$;$s!#\e(B)
+
+Gnus \e$B$O$"$J$?$K<+J,<+?H$KD7$MJV$C$F$/$k$h$&$J2DG=@-$N$"$kA4$F$N5!2q$rDs\e(B
+\e$B6!$7$^$9!#Nc$($P!"$"$J$?$N>e;J$+$i$/$kA4$F$N%a!<%k$r4^$s$@%0%k!<%W$r:n$C\e(B
+\e$B$?$H$7$^$7$g$&!#$=$l$+$i!"6vH/E*$K$=$N%0%k!<%W$N9XFI<h$j;_$a$,5/$3$C$?$H\e(B
+\e$B$7$^$9!#\e(BGnus \e$B$O$=$l$G$b>e;J$+$i$NA4$F$N%a!<%k$rL$9XFI$N%0%k!<%W$KF~$l$^\e(B
+\e$B$9$N$G!">e;J$,\e(B ''\e$B7nMKF|$^$G$K$=$NJs9p=q$r=`Hw$7$J$$$H<s$@\e(B!'' \e$B$H$$$&%a!<\e(B
+\e$B%k$r$"$J$?$KAw$C$F$b!"$"$J$?$O$=$l$r8+$k;v$O$J$/!"2PMKF|$K$J$C$FK\Ev$OMb\e(B
+\e$B7n$N2HDB$rJ'$&$?$a$K6u$N%\%H%k$r=8$a$k$Y$-$G$"$C$F$b!"$^$@M-5k$G8[$o$l$F\e(B
+\e$B$$$k$H?.$8$F$$$k$+$b$7$l$^$;$s!#\e(B
+
+@node Mail Sources
+@subsection Mail Sources
+
+\e$B$$$m$s$J$H$3$m$+$i%a!<%k$r<hF@$9$k$3$H$,$G$-$^$9\e(B---\e$B%a!<%k%9%W!<%k!"\e(B
+@acronym{POP} \e$B%a!<%k%5!<%P!<!"\e(Bprocmail \e$B%G%#%l%/%H%j!<!"\e(Bmaildir \e$B$J$I$,Nc\e(B
+\e$B$H$7$F$"$j$^$9!#\e(B
+
+@menu
+* Mail Source Specifiers::      \e$B%a!<%k$N85$,$I$3$+$r;XDj$9$k\e(B
+* Mail Source Customization::   \e$B@$$NCf$K1F6A$9$k$$$/$D$+$NJQ?t\e(B
+* Fetching Mail::               \e$B%a!<%k%=!<%9;X<(;R$r;HMQ$9$k\e(B
+@end menu
+
+@node Mail Source Specifiers
+@subsubsection \e$B%a!<%k%=!<%9;X<(;R\e(B
+@cindex @acronym{POP}
+@cindex mail server
+@cindex procmail
+@cindex mail spool
+@cindex mail source
+
+@dfn{\e$B%a!<%k%=!<%9;X<(;R\e(B} \e$B$K\e(B @code{\e$B%a!<%k%=!<%9\e(B} (@pxref{Fetching Mail})
+\e$B$r@_Dj$9$k$3$H$G!"\e(Bgnus \e$B$K%a!<%k$r<hF@$9$kJ}K!$r65$($k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@lisp
+(pop :server "pop3.mailserver.com" :user "myname")
+@end lisp
+
+\e$B8fMw$NDL$j!"%a!<%k%=!<%9;X<(;R$O%j%9%H$G!":G=i$NMWAG$O\e(B @dfn{\e$B%a!<%k%=!<%9\e(B
+\e$B$N7?\e(B}\e$B!"$=$N<!$OG$0U$N?t$N\e(B @dfn{\e$B%-!<%o!<%I\e(B} \e$B$H$J$j$^$9!#L@<(E*$K;XDj$5$l\e(B
+\e$B$F$$$J$$%-!<%o!<%I$O=i4|CM$K$J$j$^$9!#\e(B
+
+\e$B0J2<$N%a!<%k%=!<%9$N7?$r;HMQ2DG=$G$9\e(B:
+
+@table @code
+@item file
+\e$BC1FH$N%U%!%$%k$+$i%a!<%k$r<hF@$7$^$9!#IaDL$O%a!<%k%9%W!<%k$G$9!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :path
+\e$B%U%!%$%k$NL>A0$G$9!#=i4|CM$O\e(B @env{MAIL} \e$B4D6-JQ?t$NCM\e(B
+\e$B$+\e(B @code{rmail-spool-directory} \e$B$NCM\e(B (\e$BIaDL\e(B
+\e$B$O\e(B @file{usr-mail/spool/user-name} \e$B$N$h$&$J$b$N\e(B) \e$B$G$9!#\e(B
+
+@item :prescript
+@itemx :postscript
+\e$B%a!<%k$r<hF@$9$kA08e$K<B9T$9$k%9%/%j%W%H$G$9!#\e(B
+@end table
+
+\e$B%U%!%$%k%a!<%k%=!<%9$NNc\e(B:
+
+@lisp
+(file :path "/usr/spool/mail/user-name")
+@end lisp
+
+\e$B$b$7$/$O!"%G%#%U%)%k%H$N%U%!%$%kL>$r;H$&$H\e(B:
+
+@lisp
+(file)
+@end lisp
+
+\e$B%a!<%k%9%W!<%k%U%!%$%k$,%m!<%+%k%^%7%s$KL5$$>l9g$O!"\e(B
+@acronym{POP} \e$B$d\e(B @acronym{IMAP} \e$B$J$I$G%a!<%k$r<hF@$9$k$N$,:GA1$G$9!#$3$3\e(B
+\e$B$G$O\e(B ange-ftp \e$B$N%U%!%$%kL>$O;HMQ$G$-$^$;$s\e(B---\e$B%a!<%k$r0\F0$7$F$$$k$H$-$K\e(B
+\e$B%a!<%k%9%W!<%k$r%m%C%/$9$kJ}K!$,$"$j$^$;$s!#\e(B
+
+\e$BE,@Z$J%5!<%P!<$r@_CV$9$k$3$H$,IT2DG=$J$i!"JQ$o$j$K\e(B  ssh \e$B$r;H$&$3$H$,$G$-\e(B
+\e$B$^$9!#\e(B
+
+@lisp
+(setq mail-sources
+      '((file :prescript "ssh host bin/getmail >%t")))
+@end lisp
+
+@samp{getmail} \e$B%9%/%j%W%H$O0J2<$N$h$&$J$b$N$K$J$j$^$9\e(B:
+
+@example
+#!/bin/sh
+#  getmail - move mail from spool to stdout
+#  flu@@iki.fi
+
+MOVEMAIL=/usr/lib/emacs/20.3/i386-redhat-linux/movemail
+TMP=$HOME/Mail/tmp
+rm -f $TMP; $MOVEMAIL $MAIL $TMP >/dev/null && cat $TMP
+@end example
+
+\e$BL\E*$K9g$&$h$&$K;HMQ$7$?$$\e(B @samp{movemail} \e$B$K9g$o$;$F%9%/%j%W%H$r=q$-49\e(B
+\e$B$($F$/$@$5$$!#\e(B
+
+@item directory
+@vindex nnmail-scan-directory-mail-source-once
+\e$B%G%#%l%/%H%j!<Cf$NJ#?t$N%U%!%$%k$+$i%a!<%k$r<hF@$7$^$9!#$3$l$OIaDL\e(B
+\e$B$O\e(B procmail \e$B$K?7$7$$%a!<%k$r$$$/$D$+$N%U%!%$%k$KJ,3d$5$;$F$$$k$H$-$K;HMQ\e(B
+\e$B$5$l$^$9!#$9$J$o$A!"$=$N%G%#%l%/%H%j!<$K$"$k%U%!%$%k$H%0%k!<%W$O0lBP0l$G\e(B
+\e$BBP1~$7$F$$$k$N$G!"%U%!%$%k\e(B @file{foo.bar.spool} \e$B$K$"$k%a!<%k$O!"%0%k!<\e(B
+\e$B%W\e(B @code{foo.bar} \e$B$KCV$+$l$^$9\e(B (\e$B%5%U%#%C%/%9\e(B @code{.spool} \e$B$OJQ992DG=$G\e(B
+\e$B$9\e(B)\e$B!#\e(B@code{nnmail-scan-directory-mail-source-once} \e$B$r\e(B @code{nil} \e$B0J30$K\e(B
+\e$B$9$k$H!"\e(Bgnus \e$B$O?7$7$$%a!<%k%=!<%9$r0l2s$@$1D4$Y$k$h$&$K$J$j$^$9!#$3$l$O!"\e(B
+\e$B;XDj$7$?%l%Y%k$N%a!<%k%0%k!<%W$@$1$rD4$Y$?$$$H$-$K!"$H$j$o$1JXMx$G$9!#\e(B
+
+@vindex nnmail-resplit-incoming
+@code{nnmail-resplit-incoming} \e$B$H$$$&JQ?t$b$"$j!"$3$l$rHs\e(B-@code{nil} \e$B$K\e(B
+\e$B$9$k$HDL>o$NJ,3d=hM}$,%G%#%l%/%H%j!<Cf$N$9$Y$F$N%U%!%$%k$KBP$7$F9T$J$o$l\e(B
+\e$B$^$9\e(B (@pxref{Splitting Mail})\e$B!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :path
+\e$B%U%!%$%k$N$"$k%G%#%l%/%H%j!<$NL>A0$G$9!#$3$l$K$O=i4|CM$O$"$j$^$;$s!#\e(B
+
+@item :suffix
+\e$B$3$N@\Hx8l$G=*$o$k%U%!%$%k$@$1$,;HMQ$5$l$^$9!#=i4|CM$O\e(B @samp{.spool} \e$B$G\e(B
+\e$B$9!#\e(B
+
+@item :predicate
+\e$B$3$N=R8l$,\e(B @code{nil} \e$B$G$J$$CM$rJV$9%U%!%$%k$N$_$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{identity} \e$B$G$9!#$3$l$ODI2C$NA*JL4o$H$7$F;HMQ$5$l$^$9\e(B---\e$B@5$7$$@\\e(B
+\e$BHx8l\e(B @emph{\e$B$H\e(B} \e$B$3$N=R8l$rK~B-$9$k%U%!%$%k$@$1$,9MN8$5$l$^$9!#\e(B
+
+@item :prescript
+@itemx :postscript
+\e$B%a!<%k$N<hF@$NA0\e(B/\e$B8e$K<B9T$5$l$k%9%/%j%W%H$G$9!#\e(B
+@end table
+
+\e$B%G%#%l%/%H%j!<%a!<%k%=!<%9$NNc$G$9\e(B:
+
+@lisp
+(directory :path "/home/user-name/procmail-dir/"
+           :suffix ".prcml")
+@end lisp
+
+@item pop
+@acronym{POP} \e$B%5!<%P!<$+$i%a!<%k$r<hF@$7$^$9!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :server
+@acronym{POP} \e$B%5!<%P!<$NL>A0$G$9!#=i4|CM$O\e(B @env{MAILHOST} \e$B4D6-JQ?t$+$i<h\e(B
+\e$BF@$5$l$^$9!#\e(B
+
+@item :port
+@acronym{POP} \e$B%5!<%P!<$N%]!<%HHV9f$G$9!#$3$l$O?tCM\e(B (\e$BNc$(\e(B
+\e$B$P\e(B @samp{:port 1234}) \e$B$+J8;zNs\e(B (\e$BNc$($P\e(B @samp{:port "pop3"}) \e$B$G$9!#$b$7J8\e(B
+\e$B;zNs$J$i\e(B Unix \e$B%7%9%F%`$K$*$1$k\e(B @file{/etc/services} \e$B$K:\$C$F$$$k%5!<%S%9\e(B
+\e$BL>$G$J$1$l$P$J$j$^$;$s!#=i4|CM$O\e(B @samp{pop3} \e$B$G$9!#%7%9%F%`$K$h$C$F\e(B
+\e$B$O\e(B @samp{"pop-3"} \e$B$H$7$J$1$l$P$J$i$J$$$+$b$7$l$^$;$s!#\e(B
+
+@item :user
+@acronym{POP} \e$B%5!<%P!<$KM?$($kMxMQ<TL>$G$9!#=i4|CM$O%m%0%$%sL>$G$9!#\e(B
+
+@item :password
+@acronym{POP} \e$B%5!<%P!<$KM?$($k%Q%9%o!<%I$G$9!#;XDj$5$l$J$$>l9g$O!"MxMQ<T\e(B
+\e$B$OF~NO$r5a$a$i$l$^$9!#\e(B
+
+@item :program
+@acronym{POP} \e$B%5!<%P!<$+$i%a!<%k$r<hF@$9$k$?$a$K;HMQ$5$l$k%W%m%0%i%`$G$9!#\e(B
+\e$B$3$l$O\e(B @code{format} \e$B$N$h$&$JJ8;zNs$G$"$k$Y$-$G$9!#Nc$G$9\e(B:
+
+@example
+fetchmail %u@@%s -P %p %t
+@end example
+
+\e$BM-8z$J=q<0;HMQ;X<(J8;z$O\e(B:
+
+@table @samp
+@item t
+\e$B%a!<%k$,0\F0$5$l$k%U%!%$%k$NL>A0$G$9!#$3$l$O>o$K$3$NJ8;zNs$K4^$^$l$F$$$J\e(B
+\e$B$1$l$P$J$j$^$;$s!#\e(B
+
+@item s
+\e$B%5!<%P!<$NL>A0$G$9!#\e(B
+
+@item P
+\e$B%5!<%P!<$N%]!<%HHV9f$G$9!#\e(B
+
+@item u
+\e$B;HMQ$9$kMxMQ<TL>$G$9!#\e(B
+
+@item p
+\e$B;HMQ$9$k%Q%9%o!<%I$G$9!#\e(B
+@end table
+
+\e$B$3$l$i$N;EMM$G;H$o$l$kCM$OBP1~$9$k%-!<%o!<%I$KM?$($?CM$+$i<h$i$l$^$9!#\e(B
+
+@item :prescript
+\e$B%a!<%k$r<hF@$9$kA0$K<B9T$5$l$k%9%/%j%W%H$G$9!#9=J8$O\e(B @code{:program} \e$B%-!<\e(B
+\e$B%o!<%I$HF1$8$G$9!#$3$l$O<B9T$5$l$k4X?t$G$"$k$3$H$b$G$-$^$9!#\e(B
+
+@item :postscript
+\e$B%a!<%k$r<hF@$7$?8e$K<B9T$5$l$k%9%/%j%W%H$G$9!#9=J8$O\e(B @code{:program} \e$B%-!<\e(B
+\e$B%o!<%I$HF1$8$G$9!#$3$l$O<B9T$5$l$k4X?t$G$"$k$3$H$b$G$-$^$9!#\e(B
+
+@item :function
+@acronym{POP} \e$B%5!<%P!<$+$i%a!<%k$r<hF@$9$k$?$a$K;H$&4X?t$G$9!#$=$N4X?t$O\e(B
+\e$B0l$D$N%Q%i%a!<%?$H$H$b$K8F$P$l$^$9\e(B---\e$B%a!<%k$,$=$3$X0\F0$5$l$k$Y$-%U%!%$\e(B
+\e$B%k$G$9!#\e(B
+
+@item :authentication
+\e$B$3$l$O\e(B @code{password} \e$B$+%7%s%\%k\e(B @code{apop} \e$B$G!"$I$NG'>ZJ}<0$r;H$&$+$r\e(B
+\e$B7h$a$k$b$N$N$I$A$i$+$G$9!#=i4|@_Dj$O\e(B @code{password} \e$B$G$9!#\e(B
+
+@item :connection
+\e$B%5!<%P!<$K@\B3$9$k$H$-$K;H$&%9%H%j!<%`$G!"\e(B@code{ssl}, @code{tls} \e$B$^$?$O\e(B
+\e$B$=$l0J30$r;XDj$G$-$^$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G!"0BA4$G$O$J$$@\B3$r\e(B
+\e$BMQ$$$^$9!#\e(BSSL/TLS \e$B$G$O30It%W%m%0%i%`$H%i%$%V%i%j$,I,MW$G$"$k$3$H$KCm0U$7\e(B
+\e$B$F2<$5$$\e(B:
+
+@itemize @bullet
+@item
+@dfn{ssl:} @acronym{SSL} \e$B$r;H$$$^$9!#\e(BOpenSSL (@samp{openssl} \e$B%W%m%0%i\e(B
+\e$B%`\e(B) \e$B$+\e(B SSLeay (@samp{s_client}) \e$B$H30It%i%$%V%i%j\e(B @samp{ssl.el} \e$B$,I,MW$G\e(B
+\e$B$9!#\e(B
+@item
+@dfn{starttls:} STARTTLS (@acronym{SSL} \e$B$KN`;w\e(B) \e$B$r;H$$$^$9!#30It%i%$%V%i\e(B
+\e$B%j\e(B @samp{starttls.el} \e$B$H\e(B @samp{starttls} \e$B%W%m%0%i%`$,I,MW$G$9!#\e(B
+@samp{starttls}.
+@end itemize
+
+@item :leave
+\e$BHs\e(B-@code{nil} \e$B$G%a!<%k$r%5!<%P!<$K;D$7!"%a%C%;!<%8$N<hF@$K\e(B UIDL \e$B$r;H$$$^\e(B
+\e$B$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+@end table
+
+@code{:program} \e$B$H\e(B @code{:function} \e$B%-!<%o!<%I$,;XDj$5$l$F$$$J$$$H!"\e(B
+@code{pop3-movemail} \e$B$,;HMQ$5$l$^$9!#\e(B
+
+\e$B$3$l$O$$$/$D$+$NNc$G$9!#=i4|MxMQ<TL>$G!"=i4|\e(B @acronym{POP} \e$B%5!<%P!<$+$i\e(B
+\e$B<hF@$7!"=i4|<hF@J}K!$r;HMQ$7$^$9\e(B:
+
+@lisp
+(pop)
+@end lisp
+
+\e$B;XL>$5$l$?%5!<%P!<$+$i;XL>$5$l$?MxMQ<T$H%Q%9%o!<%I$G<hF@$7$^$9\e(B:
+
+@lisp
+(pop :server "my.pop.server"
+     :user "user-name" :password "secret")
+@end lisp
+
+\e$B%a!<%k$N0\F0$K\e(B @samp{movemail} \e$B$r;H$$$^$9\e(B:
+
+@lisp
+(pop :program "movemail po:%u %t %p")
+@end lisp
+
+@item maildir
+Maildir \e$B$+$i%a!<%k$r<hF@$7$^$9!#$3$l$O8=:_\e(B qmail \e$B$H\e(B postfix \e$B$G$N$_$G%5%]!<\e(B
+\e$B%H$5$l$F$$$k\e(B mailbox \e$B7A<0$G!"FCJL$N%G%#%l%/%H%j!<$N$=$l$>$l$N%U%!%$%k$,\e(B
+\e$B@53N$K\e(B 1 \e$B%a!<%k$H$J$C$F$$$^$9!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :path
+\e$B%a!<%k$,J]B8$5$l$k%G%#%l%/%H%j!<$NL>A0$G$9!#=i4|CM$O4D6-JQ\e(B
+\e$B?t\e(B @env{MAILDIR} \e$B$+$i<hF@$7$?CM$+!"$^$?$O\e(B @file{~/Maildir/} \e$B$G$9!#\e(B
+@item :subdirs
+Maildir \e$B$N%5%V%G%#%l%/%H%j$G$9!#=i4|CM$O\e(B @samp{("new" "cur")} \e$B$G$9!#\e(B
+
+@c Gnus \e$B$G<hF@$9$kA0$K!"$H$-$I$-\e(B pop3 \e$B%G!<%b%s$G%a!<%k$rC5$9$J$i!"0J2<$N:G\e(B
+@c \e$B=i$NNc$N$h$&$K!"\e(Bmaildir \e$B$NCf$N\e(B @code{cur} \e$B%G%#%l%/%H%j!<$+$i$b%a!<%k$r<h\e(B
+@c \e$BF@$9$kI,MW$,$"$j$^$9!#\e(B
+
+\e$B%j%b!<%H%^%7%s$+$i%a!<%k$r<h$j4s$;$k$3$H$b=PMh$^$9!#\e(B
+(\e$B$H$$$&$N$b!"\e(Bmaildir \e$B$O%m%C%/$NLdBj$r5$$K$;$:$K:Q$`$+$i!#\e(B)
+@end table
+
+Maildir \e$B%a!<%k%=!<%9$NNc$r$U$?$D\e(B:
+
+@lisp
+(maildir :path "/home/user-name/Maildir/"
+         :subdirs ("cur" "new"))
+@end lisp
+
+@lisp
+(maildir :path "/user@@remotehost.org:~/Maildir/"
+         :subdirs ("new"))
+@end lisp
+
+@item imap
+@acronym{IMAP} \e$B%5!<%P!<$+$i%a!<%k$r<hF@$7$^$9!#2?$i$+$NM}M3\e(B
+\e$B$G\e(B @acronym{IMAP} \e$B$r0U?^$5$l$?$h$&$J%M%C%H%o!<%/>e$G%a!<%k$rFI$`%W%m%H%3\e(B
+\e$B%k$H$7$F07$$$?$/$J$$$H$-$O!"\e(Bgnus \e$B$G$O\e(B @acronym{POP} \e$B%5!<%P!<$HF1MM$K07$&\e(B
+\e$B$3$H$,$G$-!"M?$($i$l$?\e(B @acronym{IMAP} \e$B%a!<%k%\%C%/%9$+$i5-;v$r<hF@$7$^$9!#\e(B
+\e$B>\$7$/$O\e(B @xref{IMAP} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+Kerberos, GSSAPI, @acronym{TLS}/@acronym{SSL} \e$B$*$h$S\e(B STARTTLS \e$B$N$?$a$N30\e(B
+\e$BIt%W%m%0%i%`$H%i%$%V%i%j$,I,MW$G$"$k$3$H$KN10U$7$F2<$5$$!#\e(B@xref{IMAP}.
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :server
+@acronym{IMAP} \e$B%5!<%P!<$NL>A0!#=i4|CM$O4D6-JQ?t\e(B @env{MAILHOST} \e$B$+$iF@$^\e(B
+\e$B$9!#\e(B
+
+@item :port
+@acronym{IMAP} \e$B%5!<%P!<$N%]!<%HHV9f!#IaDL$O=i4|CM$O\e(B @samp{143} \e$B$G!"\e(B
+@acronym{TLS}/@acronym{SSL} \e$B@\B3$K$O\e(B @samp{993} \e$B$G$9!#\e(B
+
+@item :user
+@acronym{IMAP} \e$B%5!<%P!<$KEO$9MxMQ<TL>$G$9!#=i4|CM$O%m%0%$%sL>$G$9!#\e(B
+
+@item :password
+@acronym{IMAP} \e$B%5!<%P!<$KEO$9%Q%9%o!<%I$G$9!#;XDj$5$l$F$$$J$$$H$-$O!"Mx\e(B
+\e$BMQ<T$OF~NO$rB%$5$l$^$9!#\e(B
+
+@item :stream
+\e$B%5!<%P!<$K@\B3$9$k$H$-$K;H$&%9%H%j!<%`!#\e(B@code{imap-stream-alist} \e$B$K$"$k\e(B
+\e$B%7%s%\%k$NCf$N$R$H$D$r@_Dj$7$^$9!#8=>u$G$O\e(B @samp{gssapi},
+@samp{kerberos4}, @samp{starttls}, @samp{tls}, @samp{ssl},
+@samp{shell} \e$B$^$?$O=i4|CM$N\e(B @samp{network} \e$B$K$J$j$^$9!#\e(B
+
+@item :authentication
+\e$B%5!<%P!<$G$NG'>Z$K$I$NG'>ZK!$r;H$&$+!#$3$l\e(B
+\e$B$O\e(B @code{imap-authenticator-alist} \e$B$N%7%s%\%k$N0l$D$r@_Dj$7$^$9!#8=>u$G\e(B
+\e$B$O\e(B @samp{gssapi}, @samp{kerberos4}, @samp{digest-md5}, @samp{cram-md5},
+@samp{anonymous} \e$B$^$?$O=i4|CM$N\e(B @samp{login} \e$B$K$J$j$^$9!#\e(B
+
+@item :program
+:stream \e$B$K\e(B `shell' \e$B$,@_Dj$5$l$F$$$k$H$-$O!"$3$NCM$,JQ\e(B
+\e$B?t\e(B @code{imap-shell-program} \e$B$K3d$jEv$F$i$l$^$9!#$3$l$O\e(B @code{format} \e$B$U\e(B
+\e$B$&$NJ8;zNs\e(B (\e$B$^$?$OJ8;zNs$N%j%9%H\e(B) \e$B$G$J$1$l$P$J$j$^$;$s!#Nc$r<($7$^$7$g$&!#\e(B
+
+@example
+ssh %s imapd
+@end example
+
+\e$BM-8z$J\e(B format \e$B;X<(;R$O0J2<$NDL$j$G$9!#\e(B
+
+@table @samp
+@item s
+\e$B%5!<%P!<$NL>A0!#\e(B
+
+@item l
+@code{imap-default-user} \e$B$G@_Dj$5$l$?%f!<%6L>!#\e(B
+
+@item p
+\e$B%5!<%P!<$N%]!<%HHV9f!#\e(B
+@end table
+
+\e$B$3$l$i$N;XDj$K;H$o$l$kCM$O!"BP1~$9$k%-!<%o!<%I$KM?$($?CM$+$i<h$C$F$-$^$9!#\e(B
+
+@item :mailbox
+\e$B%a!<%k$r<hF@$9$k%a!<%k%\%C%/%9$NL>A0!#=i4|CM$O\e(B @samp{INBOX} \e$B$G!"$3$l$OIa\e(B
+\e$BDL$OF~$C$F$/$k%a!<%k$r<u$1<h$k%a!<%k%\%C%/%9$G$9!#\e(B
+
+@item :predicate
+\e$B<hF@$9$k5-;v$r7hDj$9$k$?$a$K;H$o$l$k=R8l!#=i4|CM$N!"\e(B@samp{UNSEEN
+UNDELETED} \e$B$O$*$=$i$/$?$$$F$$$N?M$K$O:GNI$NA*Br$G$7$g$&$,!"$H$-$I\e(B
+\e$B$-\e(B @acronym{IMAP} \e$B%/%i%$%"%s%H$G%a!<%k%\%C%/%9$rGA$-!"$$$/$D$+$N5-;v$K4{\e(B
+\e$BFI\e(B (\e$B$b$7$/$O!"\e(BSEEN) \e$B$N0u$rIU$1$k$J$i!"\e(B@samp{1:*} \e$B$K@_Dj$9$kI,MW$,$"$k$+\e(B
+\e$B$b$7$l$^$;$s!#$=$&$9$l$P!"%a!<%k%\%C%/%9$NA4$F$N5-;v$O0u$NG!2?$K4X$o$i$:\e(B
+\e$B<hF@$5$l$^$9!#=R8l$N40A4$J0lMw$O!"\e(BRFC2060 \e$B$N\e(B 6.4.4 \e$B@a$rFI$s$G$/$@$5$$!#\e(B
+
+@item :fetchflag
+\e$B%5!<%P!<$G!"<hF@$7$?5-;v$K0u$rIU$1$kJ}K!!#=i4|CM$N\e(B @samp{\Deleted} \e$B$O$=\e(B
+\e$B$l$i$K>C5n$N0u$rIU$1$^$9$,!"B>$K\e(B @samp{\Seen} \e$B$G$OC1$K4{FI$N0u$rIU$1$^$9!#\e(B
+\e$B$3$l$i$O:G$b$"$j$=$&$JFs$D$NA*Br$G$9$,!"B>$N0u$b\e(B RFC2060 \e$B$N\e(B 2.3.2 \e$B@a$GDj\e(B
+\e$B5A$5$l$F$$$^$9!#\e(B
+
+@item :dontexpunge
+@code{nil} \e$B$G$J$+$C$?$i!"5-;v$r<hF@$7$?8e$G!"$=$l$i$K>C5n$N0u$,IU$$$F$$\e(B
+\e$B$F$b:o=|$7$^$;$s!#\e(B
+@end table
+
+@acronym{IMAP} \e$B%a!<%k%=!<%9$NNc\e(B:
+
+@lisp
+(imap :server "mail.mycorp.com"
+      :stream kerberos4
+      :fetchflag "\\Seen")
+@end lisp
+
+@item webmail
+@uref{http://www.hotmail.com/}, @uref{http://webmail.netscape.com/},
+@uref{http://www.netaddress.com/}, @uref{http://www.yahoo.com/} \e$B$J$I$N%&%'\e(B
+\e$B%V%a!<%k%5!<%P!<$+$i%a!<%k$r<hF@$7$^$9!#\e(B
+
+\e$BCm\e(B: \e$B%&%'%V%a!<%k$O%/%C%-!<$KBg$-$/0MB8$7$^$9!#\e(Burl "4.0pre.46" \e$B$r;H$&>l9g\e(B
+\e$B$O\e(B "one-line-cookie" \e$B%Q%C%A$rEv$F$kI,MW$,$"$j$^$9!#\e(B
+
+\e$B7Y9p\e(B: \e$B%a!<%k$,<:$o$l$k$+$b$7$l$^$;$s!#L5J]>Z$G$9!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :subtype
+\e$B%&%'%V%a!<%k%5!<%P!<$N7?$G$9!#=i4|CM$O\e(B @code{hotmail} \e$B$G$9!#B>$N8uJd\e(B
+\e$B$O\e(B @code{netscape}, @code{netaddress}, @code{my-deja} \e$B$G$9!#\e(B
+
+@item :user
+\e$B%&%'%V%a!<%k%5!<%P!<$NMxMQ<TL>$G$9!#=i4|CM$O%m%0%$%sL>$G$9!#\e(B
+
+@item :password
+\e$B%&%'%V%a!<%k%5!<%P!<$N%Q%9%o!<%I$G$9!#;XDj$7$J$$>l9g$O!"MxMQ<T$KF~NO$rB%\e(B
+\e$B$7$^$9!#\e(B
+
+@item :dontexpunge
+@code{nil} \e$B$G$J$+$C$?$i!"L$FI$N5-;v$@$1$r<hF@$7$F!"$=$l$i$r$4$_H"$N%U%)\e(B
+\e$B%k%@!<$K0\F0$7$^$;$s!#\e(B
+@end table
+
+\e$B%&%'%V%a!<%k$N%=!<%9$NNc$G$9\e(B:
+
+@lisp
+(webmail :subtype 'hotmail
+         :user "user-name"
+         :password "secret")
+@end lisp
+@end table
+
+@table @dfn
+@item Common Keywords
+\e$B6&DL%-!<%o!<%I$O$I$s$J7?$N%a!<%k%=!<%9$K$b;H$&$3$H$,$G$-$^$9!#\e(B
+
+\e$B%-!<%o!<%I\e(B:
+
+@table @code
+@item :plugged
+@code{nil} \e$B$G$J$+$C$?$i!"\e(Bgnus \e$B$,\e(B @dfn{unplugged} \e$B$G$"$C$F$b%a!<%k$r<hF@\e(B
+\e$B$7$^$9!#$b$7$"$J$?$,%G%#%l%/%H%j$r%a!<%k%=!<%9$K;H$C$F$$$k$J$i$P!"$3$NNc\e(B
+\e$B$N$h$&$K;XDj$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq mail-sources
+      '((directory :path "/home/pavel/.Spool/"
+                   :suffix ""
+                   :plugged t)))
+@end lisp
+
+\e$B$"$J$?$,\e(B @dfn{unplugged} \e$B$G$"$C$F$b\e(B gnus \e$B$O%a!<%k$r<hF@$7$^$9!#$3$l$O!"\e(B
+\e$B%m!<%+%k$N%a!<%k$H%K%e!<%9$r;H$&>l9g$KJXMx$G$9!#\e(B
+@end table
+@end table
+
+@subsubsection \e$B4X?t%$%s%?!<%U%'!<%9\e(B
+
+\e$B>e5-$N$$$/$D$+$N%-!<%o!<%I$O!"<B9T$9$k$?$a$N\e(B Lisp \e$B4X?t$r;XDj$7$^$9!#4X?t\e(B
+\e$B$,<B9T$5$l$F$$$k4V$@$1!"$=$l$>$l$N%-!<%o!<%I\e(B @code{:foo} \e$B$NCM$H$7\e(B
+\e$B$F\e(B Lisp \e$BJQ?t\e(B @code{foo} \e$B$,;H$o$l$^$9!#Nc$($P!"0J2<$N%a!<%k%=!<%9$N@_DjNc\e(B
+\e$B$K$D$$$F9M$($F$_$F2<$5$$!#\e(B
+
+@lisp
+(setq mail-sources '((pop :user "jrl"
+                          :server "pophost" :function fetchfunc)))
+@end lisp
+
+\e$B4X?t\e(B @code{fetchfunc} \e$B$,<B9T$5$l$F$$$k$H$-!"\e(B@code{user} \e$B$H$$$&%7%s%\%k$N\e(B
+\e$BCM$O\e(B @code{"jrl"} \e$B$K$J$j!"\e(B@code{server} \e$B$H$$$&%7%s%\%k$NCM\e(B
+\e$B$O\e(B @code{"pophost"} \e$B$K$J$j$^$9!#\e(B
+@code{port}, @code{password}, @code{program}, @code{prescript},
+@code{postscript}, @code{function} \e$B$*$h$S\e(B @code{authentication} \e$B$NCM$b$^\e(B
+\e$B$?!"$=$l$i$N4{DjCM$K$J$j$^$9!#\e(B
+
+\e$B$=$l$>$l$N7?$N%a!<%k%=!<%9$N$?$a$N%-!<%o!<%I$N%j%9%H$K$D$$$F$O!">e5-$r;2\e(B
+\e$B>H$7$F2<$5$$!#\e(B
+
+@node Mail Source Customization
+@subsubsection \e$B%a!<%k%=!<%9$N%+%9%?%^%$%:\e(B
+
+\e$B0J2<$O%a!<%k$N<hF@J}K!$K1F6A$9$kJQ?t$N0lMw$G$9!#IaDL$O$3$l$i$O$I$l$b@_Dj\e(B
+\e$B$9$kI,MW$O$J$$$G$7$g$&!#\e(B
+
+@table @code
+@item mail-source-crash-box
+@vindex mail-source-crash-box
+\e$B%a!<%k$rA`:n$7$F$$$k4V$KJ]B8$5$l$F$$$k>l=j$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/.emacs-mail-crash-box} \e$B$G$9!#\e(B
+
+@item mail-source-delete-incoming
+@vindex mail-source-delete-incoming
+@code{nil} \e$B$G$J$1$l$P!"F~$C$FMh$?%U%!%$%k$O!"$=$l$r=hM}$7$?8e$K>C5n$5$l\e(B
+\e$B$^$9!#\e(B@code{t} \e$B$G$O%U%!%$%k$r$?$@$A$K>C5n$7!"\e(B@code{nil} \e$B$G$O$$$+$J$k%U%!\e(B
+\e$B%$%k$b>C$7$^$;$s!#@5$N?t$@$C$?>l9g$O!"$=$NF|?t0J>e$K8E$$%U%!%$%k$r>C5n$7\e(B
+\e$B$^$9\e(B (\e$B$3$l$O?7Ce%a!<%k$r<u$1<h$k$H$-$@$19T$J$o$l$^$9\e(B)\e$B!#\e(B
+@code{mail-source-delete-incoming} \e$B$r\e(B @code{nil} \e$B$K$7$F$*$$$F!"\e(B
+@code{mail-source-delete-old-incoming} \e$B$r%U%C%/$^$?$O<jF0$G8F$s$G$bNI$$\e(B
+\e$B$G$9!#\e(B
+
+@item mail-source-delete-old-incoming-confirm
+@vindex mail-source-delete-old-incoming-confirm
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"8E$$\e(B incoming (\e$B%a!<%k$NE~Ce;~$K;H$o$l$?\e(B) \e$B%U%!%$\e(B
+\e$B%k$r>C5n$9$k$H$-$K3NG'$r5a$a$^$9!#$3$NJQ?t\e(B
+\e$B$O\e(B @code{mail-source-delete-incoming} \e$B$,@5$N?t$G$"$k>l9g$@$1;H$o$l$^$9!#\e(B
+
+@item mail-source-ignore-errors
+@vindex mail-source-ignore-errors
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"%a!<%k%=!<%9$+$i%a!<%k$rFI$`$H$-$N%(%i!<$rL5;k$7\e(B
+\e$B$^$9!#\e(B
+
+@item mail-source-directory
+@vindex mail-source-directory
+\e$B%U%!%$%k$,\e(B (\e$B$b$7$"$l$P\e(B) \e$BJ]B8$5$l$k%G%#%l%/%H%j!<$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/Mail/} \e$B$G$9!#8=;~E@$G$O!"$3$l$,;H$o$l$kM#0l$N$b$N$OA0$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$C$?>l9g!"F~$C$F$-$?%U%!%$%k$,J]B8$5$l$k>l=j$N;XDj$G$9!#\e(B
+
+@item mail-source-incoming-file-prefix
+@vindex mail-source-incoming-file-prefix
+\e$BF~$C$F$-$?%a!<%k$rJ]B8$9$k%U%!%$%k$N%W%l%U%#%C%/%9$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{Incoming} \e$B$G!"$3$N>l9g%U%!%$%k\e(B
+\e$B$O\e(B @file{Incoming30630D_} \e$B$d\e(B @file{Incoming298602ZD} \e$B$N$h$&$K$J$j$^$9!#\e(B
+@code{mail-source-delete-incoming} \e$B$,\e(B @code{nil} \e$B$N>l9g$@$1$G$9$,!#\e(B
+
+@item mail-source-default-file-modes
+@vindex mail-source-default-file-modes
+\e$BA4$F$N?7$7$$%a!<%k%U%!%$%k$O$3$N%U%!%$%k%b!<%I$K$J$j$^$9!#=i4|CM\e(B
+\e$B$O\e(B 384 \e$B$G$9!#\e(B
+
+@item mail-source-movemail-program
+@vindex mail-source-movemail-program
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i?7Ce%a!<%k$N<h$j9~$`$?$a$N%W%m%0%i%`$NL>A0!#\e(B
+@code{nil} \e$B$@$C$?$i\e(B @var{exec-directory} \e$B$K$"$k\e(B @code{movemail}\e$B!#\e(B
+@end table
+
+@node Fetching Mail
+@subsubsection \e$B%a!<%k$N<hF@\e(B
+
+@vindex mail-sources
+@vindex nnmail-spool-file
+\e$B<B:]$K\e(B gnus \e$B$K$I$3$+$i?7$7$$%a!<%k$r<hF@$9$k$+$r65$($k$K$O!"\e(B
+@code{mail-sources} \e$B$r%a!<%k%=!<%9;X<(;R$N%j%9%H$K@_Dj$9$k$3$H$G\e(B
+\e$B$9\e(B (@pxref{Mail Source Specifiers})\e$B!#\e(B
+
+\e$B$3$NJQ?t\e(B (\e$B$H5l<0$N\e(B @code{nnmail-spool-file}) \e$B$,\e(B @code{nil} \e$B$G$"$l$P!"%a!<\e(B
+\e$B%k%P%C%/%(%s%I$O7h$7$F<+J,<+?H$G$O%a!<%k$r<hF@$7$h$&$H$7$^$;$s!#\e(B
+
+\e$B%m!<%+%k$N%9%W!<%k$H\e(B @acronym{POP} \e$B%a!<%k%5!<%P!<$NN>J}$+$i%a!<%k$r<hF@\e(B
+\e$B$7$?$$$J$i!"$3$N$h$&$K$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq mail-sources
+      '((file)
+        (pop :server "pop3.mail.server"
+             :password "secret")))
+@end lisp
+
+\e$B$b$7$/$O!"$3$l$i$N%-!<%o!<%I$N=i4|CM$r;H$$$?$/$J$1$l$P\e(B:
+
+@lisp
+(setq mail-sources
+      '((file :path "/var/spool/mail/user-name")
+        (pop :server "pop3.mail.server"
+             :user "user-name"
+             :port "pop3"
+             :password "secret")))
+@end lisp
+
+\e$B%a!<%k%P%C%/%(%s%I$r;H$&$H$-$O!"\e(Bgnus \e$B$OA4$F$N%a!<%k$r\e(B inbox \e$B$+$i5[$$>e$2\e(B
+\e$B$F!"%[!<%`%G%#%l%/%H%j!<$KJ|$jEj$2$^$9!#$"$J$?$,%a!<%k%P%C%/%(%s%I$r;H$C\e(B
+\e$B$F$$$J$$>l9g$O!"\e(Bgnus \e$B$O0lDL$b%a!<%k$r0\F0$7$^$;$s\e(B---\e$B:G=i$KKbK!$N8F$S=P$7\e(B
+\e$B$r$?$/$5$s$7$J$1$l$P$J$j$^$;$s!#$^$:8^3Q7A$rIA$-!"O9?$$K2P$rIU$1!";3MS$r\e(B
+\e$B@8$1lS$H$7$FJ{$2=*$($?8e$G!"\e(Bgnus \e$B$,$"$J$?$N%a!<%k$r0\F0$7$F$bK\Ev$K$"$^\e(B
+\e$B$j6C$$$F$O$$$1$^$;$s!#\e(B
+
+@node Mail Back End Variables
+@subsection \e$B%a!<%k%P%C%/%(%s%IJQ?t\e(B
+
+\e$B$3$l$i$NJQ?t$O\e(B (\e$B$?$$$F$$$N>l9g\e(B) \e$BA4$F$N0c$C$?%a!<%k%P%C%/%(%s%I$K4XO"$7$^\e(B
+\e$B$9!#\e(B
+
+@table @code
+@vindex nnmail-read-incoming-hook
+@item nnmail-read-incoming-hook
+\e$B%a!<%k%P%C%/%(%s%I$O?7$7$$%a!<%k$rFI$_9~$s$@8e$K$3$N%U%C%/$r8F$S$^$9!#$b\e(B
+\e$B$7$=$&$7$?$$$H;W$&$J$i!"$3$N%U%C%/$r%a!<%k4F;k%W%m%0%i%`$KCN$i$;$k$?$a$K\e(B
+\e$B;H$&;v$,$G$-$^$9!#\e(B
+
+@vindex nnmail-split-hook
+@item nnmail-split-hook
+@findex gnus-article-decode-encoded-words
+@cindex RFC1522 decoding
+@cindex RFC2047 decoding
+\e$B$=$l$>$l$N%a%C%;!<%8$,$=$N%X%C%@!<$K4p$E$$$FJ,3d$,$J$5$l$kD>A0$K$=$l$,J]\e(B
+\e$BB8$5$l$F$$$k%P%C%U%!$G<B9T$5$l$k%U%C%/$G$9!#$3$N%U%C%/$O$=$l$,E,9g$9$k$H\e(B
+\e$B9M$($k$h$&$K<+M3$K%P%C%U%!$NFbMF$rJT=8$9$k;v$,$G$-$^$9\e(B---\e$B%P%C%U%!$OJ,3d\e(B
+\e$B$,=*$o$C$?8e$G>C5n$5$l!"%P%C%U%!$G9T$o$l$?JQ99$O$I$N%U%!%$%k$K$b8=$l$^$;\e(B
+\e$B$s!#\e(B@code{gnus-article-decode-rfc1522} \e$B$,$3$N%U%C%/$K2C$($k;v$,E,@Z$J4X\e(B
+\e$B?t$N0l$D$G$9!#\e(B
+
+@vindex nnmail-pre-get-new-mail-hook
+@vindex nnmail-post-get-new-mail-hook
+@item nnmail-pre-get-new-mail-hook
+@itemx nnmail-post-get-new-mail-hook
+\e$B$3$l$i$OF~$C$F$/$k%a!<%k$r07$&$H$-$K<B9T$5$l$kLr$KN)$DFs$D$N%U%C%/$G\e(B
+\e$B$9\e(B---@code{nnmail-pre-get-new-mail-hook} (\e$B$3$l$O?7$7$$%a!<%k$r07$&D>A0$K\e(B
+\e$B8F$P$l$^$9\e(B) \e$B$H\e(B @code{nnmail-post-get-new-mail-hook} (\e$B$3$l$O%a!<%k$N07$$\e(B
+\e$B$,=*$o$C$?$H$-$K8F$P$l$^$9\e(B) \e$B$G$9!#<!$N$b$N$O!"$3$NFs$D$N%U%C%/$r;H$C$F?7\e(B
+\e$B$7$$%a!<%k%U%!%$%k$KM?$($i$l$k=i4|%U%!%$%k%b!<%I$rJQ99$9$kNc$G$9\e(B:
+
+@lisp
+(add-hook 'nnmail-pre-get-new-mail-hook
+          (lambda () (set-default-file-modes 511)))
+
+(add-hook 'nnmail-post-get-new-mail-hook
+          (lambda () (set-default-file-modes 551)))
+@end lisp
+
+@item nnmail-use-long-file-names
+@vindex nnmail-use-long-file-names
+@code{nil} \e$B$G$J$$$J$i!"%a!<%k%P%C%/%(%s%I$OD9$$%U%!%$%kL>$H%G%#%l%/%H%j!<\e(B
+\e$BL>$r;H$$$^$9!#\e(B@samp{mail.misc} \e$B$N$h$&$J%0%k!<%WL>$O\e(B @file{mail.misc} \e$B$H\e(B
+\e$B$$$&%G%#%l%/%H%j!<\e(B (@code{nnml} \e$B%P%C%/%(%s%I$,;H$o$l$F$$$k$H$_$J$9$H\e(B) \e$B$+\e(B
+\e$B%U%!%$%k\e(B (@code{nnfolder} \e$B%P%C%/%(%s%I$,;H$o$l$F$$$k$H$_$J$9$H\e(B) \e$B$H$$$&7k\e(B
+\e$B2L$K$J$j$^$9!#$b$7$=$l$,\e(B @code{nil} \e$B$G$"$k$J$i!"F1$8%0%k!<%W\e(B
+\e$B$O\e(B @file{mail/misc} \e$B$H$$$&7k2L$K$J$j$^$9!#\e(B
+
+@item nnmail-delete-file-function
+@vindex nnmail-delete-file-function
+@findex delete-file
+\e$B%U%!%$%k$r>C5n$9$k$?$a$K8F$P$l$k4X?t$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{delete-file} \e$B$G$9!#\e(B
+
+@item nnmail-cache-accepted-message-ids
+@vindex nnmail-cache-accepted-message-ids
+@code{nil} \e$B$G$J$$$H!"%P%C%/%(%s%I$KF~$C$FMh$?5-;v\e(B (\e$BNc$($P!"\e(B@code{Gcc} \e$B$K\e(B
+\e$B$h$C$F\e(B) \e$B$N\e(B @code{Message-ID} \e$B$r%a!<%k=EJ#H/8+%U%!%$%k$KF~$l$^$9!#%G%#%U%)\e(B
+\e$B%k%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item nnmail-cache-ignore-groups
+@vindex nnmail-cache-ignore-groups
+\e$B@55,I=8=$+@55,I=8=$N%j%9%H$G$9!#@55,I=8=$K%0%k!<%WL>$,%^%C%A$9$k\e(B
+\e$B$H\e(B @code{Message-ID} \e$B%-%c%C%7%e$K5-O?$5$l$^$;$s!#\e(B
+
+\e$BNc$($PFC5iJ,3d\e(B (@pxref{Fancy Mail Splitting}) \e$B$r4X\e(B
+\e$B?t\e(B @code{nnmail-split-fancy-with-parent} \e$B$H$H$b$K;H$C$F$$$k>l9g$KLrN)$D\e(B
+\e$B$G$7$g$&!#\e(B
+@end table
+
+@node Fancy Mail Splitting
+@subsection \e$BFC5i%a!<%kJ,3d\e(B
+@cindex mail splitting
+@cindex fancy mail splitting
+
+@vindex nnmail-split-fancy
+@findex nnmail-split-fancy
+\e$BHf3SE*C1=c$JI8=`$N%a!<%kJ,3d;XDj$NJ}K!$G$O$"$J$?$NK>$`;v$,$G$-$J$$>l9g!"\e(B
+@code{nnmail-split-methods} \e$B$r\e(B @code{nnmail-split-fancy} \e$B$K@_Dj$9$k;v$,\e(B
+\e$B$G$-$^$9!#$=$l$+$iJQ?t\e(B @code{nnmail-split-fancy} \e$B$GM7$V;v$,$G$-$^$9!#\e(B
+
+\e$B$^$:$3$NJQ?t$NCM$NNc$r8+$F$_$^$7$g$&\e(B:
+
+@lisp
+;; @r{\e$B%a!<%k%G!<%b%s\e(B (mailer deamon) \e$B$OIaDL$N%0%k!<%W$K$OAj8_Ej9F$5$l$^\e(B}
+;; @r{\e$B$;$s!#7Y9p$OK\Ev$N%(%i!<$H$O0c$C$?%0%k!<%W$KF~$l$i$l$^$9!#\e(B}
+(| ("from" mail (| ("subject" "warn.*" "mail.warning")
+                   "mail.misc"))
+   ;; @r{\e$B%(%i!<$G$J$$%a%C%;!<%8$OA4$F$N4XO"$7$?%0%k!<%W$KAj8_Ej9F$5$l$^\e(B}
+   ;; @r{\e$B$9$,!"\e(B(ding) \e$B%j%9%H$HB>$N\e(B (ding) \e$B4XO"$N%a!<%k$N$?$a$N%0%k!<%W$K\e(B}
+   ;; @r{\e$B$OAj8_Ej9F$7$^$;$s!#\e(B}
+   (& (| (any "ding@@ifi\\.uio\\.no" "ding.list" "ding.list")
+         ("subject "ding" "ding.misc"))
+      ;; @r{\e$BB>$N%a!<%j%s%0%j%9%H\e(B@dots{}}
+      (any "procmail@@informatik\\.rwth-aachen\\.de" "procmail.list")
+      (any "SmartList@@informatik\\.rwth-aachen\\.de" "SmartList.list")
+      ;; @r{\e$B0J2<$N$I$A$i$N%a!<%j%s%0%j%9%H$bF1$8@\F,<-$J$N$G!"\e(Bbugs-}
+      ;; @r{\e$B$@$1$KEj9F$5$l$?$b$N$,\e(B mypkg.list \e$B$KAj8_Ej9F$5$l$J$$$h\e(B}
+      ;; @r{\e$B$&$K$7$F$$$^$9!#$7$+$7K\Ev$KAj8_Ej9F$5$l$?5-;v$rAj8_Ej9F\e(B}
+      ;; @r{\e$B$9$k$3$H$O5v$7$F$$$^$9!#\e(B}
+      (any "bugs-mypackage@@somewhere" "mypkg.bugs")
+      (any "mypackage@@somewhere\" - "bugs-mypackage" "mypkg.list")
+      ;; @r{\e$B?M!9\e(B@dots{}}
+      (any "larsi@@ifi\\.uio\\.no" "people.Lars_Magne_Ingebrigtsen"))
+   ;; @r{\e$B9gCW$7$J$+$C$?%a!<%k$OA4$F$rJa$^$($k%0%k!<%W$X9T$-$^$9!#\e(B}
+   "misc.misc")
+@end lisp
+
+\e$B$3$NJQ?t$O\e(B @dfn{\e$BJ,3d\e(B} \e$B$NMM<0$K$J$C$F$$$^$9!#J,3d$O\e(B (\e$B$"$k$$$O\e(B) \e$B$=$l$>$l$N\e(B
+\e$BJ,3d$,B>$NJ,3d$r4^$`:F5"E*9=B$$G$9!#$3$l$O;HMQ2DG=$JJ,3d9=J8$G$9\e(B:
+
+@table @code
+
+@item group
+\e$B$b$7J,3d$,J8;zNs$G$"$k$H!"$=$l$O%0%k!<%WL>$H$7$F$_$J$5$l$^$9!#IaDL$N@55,\e(B
+\e$BI=8=$N9gCW$,$J$5$l$^$9!#Nc$O2<$NJ}$r8+$F2<$5$$!#\e(B
+
+@item (@var{field} @var{value} [- @var{restrict} [@dots{}] ] @var{split})
+\e$B$b$7J,3d$,%j%9%H$G!":G=i$NMWAG$,J8;zNs$G$"$j!"%X%C%@!<\e(B @var{field} (\e$B@55,\e(B
+\e$BI=8=\e(B) \e$B$,\e(B @var{value} (\e$B$3$l$b@55,I=8=\e(B) \e$B$r4^$s$G$$$k>l9g!"%a%C%;!<%8\e(B
+\e$B$r\e(B @var{split} \e$B$G;XDj$5$l$?$H$3$m$KC_@Q$7$^$9!#\e(B@var{restrict} (\e$B$^$?B>$N\e(B
+\e$B@55,I=8=\e(B) \e$B$,\e(B @var{field} \e$B$N8e$G!"9gCW$7$?\e(B @var{value} \e$B$N:G8e$NA0$N$$$/$D\e(B
+\e$B$+$NJ8;zNs$K9gCW$7$?$i!"\e(B@var{split} \e$B$OL5;k$5$l$^$9!#\e(B@var{restrict} \e$B$NJD\e(B
+\e$BJq$N$I$l$b$,9gCW$7$J$1$l$P\e(B @var{split} \e$B$,<B9T$5$l$^$9!#\e(B
+
+@item (| @var{split} @dots{})
+\e$BJ,3d$,%j%9%H$G!":G=i$NMWAG$,\e(B @code{|} (\e$B?bD>K@\e(B) \e$B$G$"$k$H!"$=$l$>$l\e(B
+\e$B$N\e(B @var{split} \e$B$r$=$N$&$A$N0l$D$,9gCW$9$k$^$G<B9T$7$^$9!#\e(B@var{split} \e$B$O\e(B
+\e$B%a!<%k%a%C%;!<%8$,0l$D0J>e$N%0%k!<%W$KC_@Q$5$l$?$H$-$K\e(B ``\e$B9gCW$7$?\e(B'' \e$B$H$7\e(B
+\e$B$^$9!#\e(B
+
+@item (& @var{split} @dots{})
+\e$BJ,3d$,%j%9%H$G!":G=i$NMWAG$,\e(B @code{&} \e$B$G$"$k$H!"%j%9%H$NA4$F\e(B
+\e$B$N\e(B @var{split} (\e$BJ#?t\e(B) \e$B$r<B9T$7$^$9!#\e(B
+
+@item junk
+\e$B$b$7J,3d$,%7%s%\%k\e(B @code{junk} \e$B$G$"$k$H!"$=$N%a%C%;!<%8$rJ]B8$7$^$;\e(B
+\e$B$s\e(B (\e$B$9$J$o$A!">C5n$7$F$7$^$$$^$9\e(B)\e$B!#Hs>o$KCm0U$7$F;H$C$F2<$5$$!#\e(B
+
+@item (: @var{function} @var{arg1} @var{arg2} @dots{})
+\e$B$b$7J,3d$,%j%9%H$G!":G=i$NMWAG$,\e(B @code{:} \e$B$G$"$k$H!"FsHVL\$NMWAG\e(B
+\e$B$,\e(B @var{args} \e$B$r0z?t$H$7$F4X?t$H$7$F8F$P$l$^$9!#4X?t$O\e(B @var{split} \e$B$rJV\e(B
+\e$B$9$Y$-$G$9!#\e(B
+
+@cindex body split
+\e$BNc$($P0J2<$N4X?t$O!"5-;v$N%\%G%#$K4p$E$$$?J,3d$K;H$($k$G$7$g$&\e(B:
+
+@lisp
+(defun split-on-body ()
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char (point-min))
+      (when (re-search-forward "Some.*string" nil t)
+        "string.group"))))
+@end lisp
+
+@var{function} \e$B$,Av$i$5$l$k$H$-!"%P%C%U%!$O%a%C%;!<%8$NItJ,$K69$a$i$l$^\e(B
+\e$B$9!#$=$l$,>e5-$NNc$G\e(B @code{save-excursion} \e$B$H\e(B @code{save-restriction} \e$B$N\e(B
+\e$B8e$G\e(B @code{(widen)} \e$B$,8F$P$l$kI,MW$,$"$kM}M3$G$9!#$5$i$K\e(B nnimap \e$B%P%C%/%(\e(B
+\e$B%s%I$N>l9g!"%G%#%U%)%k%H$G$O5-;v$N%\%G%#$,%@%&%s%m!<%I$5$l$J$$$3$H$KCm0U\e(B
+\e$B$7$F2<$5$$!#$=$l$r$9$k$?$a$K$O\e(B @code{nnimap-split-download-body} \e$B$r\e(B t \e$B$K\e(B
+\e$B@_Dj$9$kI,MW$,$"$j$^$9\e(B (@pxref{Splitting in IMAP})\e$B!#\e(B
+
+@item (! @var{func} @var{split})
+\e$BJ,3d$,%j%9%H$G!":G=i$NMWAG$,\e(B @code{!} \e$B$G$"$k$H\e(B @var{split} \e$B$,<B9T$5$l!"\e(B
+@var{func} \e$B$O\e(B @var{split} \e$B$N7k2L$r0z?t$H$7$F8F$P$l$^$9!#\e(B@var{func} \e$B$OJ,\e(B
+\e$B3d$rJV$9$Y$-$G$9!#\e(B
+
+@item nil
+\e$B$b$7J,3d$,\e(B @code{nil} \e$B$G$"$l$P!"$=$l$OL5;k$5$l$^$9!#\e(B
+
+@end table
+
+\e$B$3$l$i$NJ,3d$G!"\e(B@var{fileld} \e$B$O40A4$J%U%#!<%k%IL>$K9gCW$7$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#\e(B@var{value} \e$B$O4pAC%b!<%I\e(B (fundamental mode) \e$B9=J8%F!<%V%k\e(B (syntax
+table) \e$B$K=>$C$F40A4$K9gCW$7$J$1$l$P$J$j$^$;$s!#@55,I=8=$G%U%#!<%k%IL>$+\e(B
+\e$B8l$NItJ,$K9gCW$5$;$k$?$a$K\e(B @code{.*} \e$B$r;H$&;v$,$G$-$^$9!#8@$$49$($l$P!"\e(B
+\e$BA4$F$N\e(B @var{value} \e$B$O\e(B @samp{\<} \e$B$H\e(B @samp{\>} \e$B$NBP$G0O$^$l$^$9!#\e(B
+
+@vindex nnmail-split-abbrev-alist
+@var{field} \e$B$H\e(B @var{value} \e$B$O\e(B Lisp \e$B%7%s%\%k\e(B (symbol) \e$B$G$"$k;v$b$G$-!"$=\e(B
+\e$B$N>l9g$=$l$i$O\e(B @code{nnmail-split-abbrev-alist} \e$B$G;XDj$5$l$F$$$k$h$&$KE8\e(B
+\e$B3+$5$l$^$9!#$3$l$O%;%k$N\e(B @sc{car} \e$B$,%-!<$r4^$s$G$$$F!"\e(B@sc{cdr} \e$B$,4XO"IU\e(B
+\e$B$1$i$l$?CM$r;}$C$F$$$k%3%s%9%;%k\e(B (cons cell) \e$B$NO"A[%j%9%H$G$9!#0J2<$N9`\e(B
+\e$BL\$,!"$"$i$+$8$a\e(B @code{nnmail-split-abbrev-alist} \e$B$KDj5A$5$l$F$$$^$9\e(B:
+
+@table @code
+@item from
+@samp{From}\e$B!"\e(B@samp{Sender} \e$B$*$h$S\e(B @samp{Resent-From} \e$B$N3F%U%#!<%k%I$K9g\e(B
+\e$BCW$7$^$9!#\e(B
+@item to
+@samp{To}\e$B!"\e(B@samp{Cc}\e$B!"\e(B@samp{Apparently-To}\e$B!"\e(B@samp{Resent-To} \e$B$*$h\e(B
+\e$B$S\e(B @samp{Resent-Cc} \e$B$N3F%U%#!<%k%I$K9gCW$7$^$9!#\e(B
+@item any
+@code{from} \e$B$H\e(B @code{to} \e$B$rE}9g$7$?$b$N$G$9!#\e(B
+@end table
+
+@vindex nnmail-split-fancy-syntax-table
+@code{nnmail-split-fancy-syntax-table} \e$B$,$3$l$i$NA4$F$NJ,3d$,<B9T$5$l$F\e(B
+\e$B$$$k$H$-$KM-8z$J9=J8%F!<%V%k$G$9!#\e(B
+
+\e$B%X%C%@!<$N$$$/$D$+$N>pJs$K4p$E$$$F!"\e(Bgnus \e$B$KF0E*$K%0%k!<%W$r:n$i$;$?$$$N\e(B
+\e$B$G$"$l$P\e(B (\e$BNc$($P!"%0%k!<%WL>$G\e(B @code{replace-match} \e$B$N$h$&$JBeMQ$r$9$k\e(B)\e$B!"\e(B
+\e$B<!$N$h$&$J;v$,$G$-$^$9!#\e(B
+
+@example
+(any "debian-\\b\\(\\w+\\)@@lists.debian.org" "mail.debian.\\1")
+@end example
+
+\e$B$3$NNc$G$O!"\e(B@samp{debian-foo@@lists.debian.org} \e$B$KAw$i$l$?%a!<%k\e(B
+\e$B$O\e(B @samp{mail.debian.foo} \e$B$H$$$&Iw$K$J$j$^$9!#\e(B
+
+\e$B$b$7J8;zNs$,MWAG\e(B @samp{\&} \e$B$r4^$s$G$$$k$H!"Be$o$j$KA0$G9gCW$7$?J8;zNs$,\e(B
+\e$B;H$o$l$^$9!#F1MM$K!"MWAG\e(B @samp{\\1} \e$B$+$i\e(B @samp{\\9} \e$B$^$G$O%0%k!<%WIU\e(B
+\e$B$1\e(B 1 \e$B$+$i\e(B 9 \e$B$^$G$G9gCW$7$?J8;zNs$GBeBX$5$l$^$9!#\e(B
+
+@vindex nnmail-split-fancy-match-partial-words
+@code{nnmail-split-fancy-match-partial-words} \e$B$O!"FC5iJ,3d$GItJ,E*$J8l$,\e(B
+\e$B9gCW$9$k$+$I$&$+$r@)8f$7$^$9!#\e(B
+
+\e$BDL>o\e(B @code{nnmail-split-fancy} \e$B$GM?$($i$l$k@55,I=8=$O!"0E$K8l$N6h@Z$j$r\e(B
+\e$BI=$9\e(B @code{\<...\>} \e$B0u$G0O$^$l$F$$$^$9!#$3$NJQ?t$,??$G$"$k$H!"$=$l$i$O2?\e(B
+\e$B$K$h$C$F$b0E$K0O$^$l$^$;$s!#\e(B
+
+@example
+(any "joe" "joemail")
+@end example
+
+\e$B$3$NNc$G!"DL>o\e(B @samp{joedavis@@foo.org} \e$B$+$iMh$?%a%C%;!<%8\e(B
+\e$B$O\e(B @samp{joemail} \e$B$K3JG<$5$l$^$;$s!#$7$+$7!"\e(B
+@code{nnmail-split-fancy-match-partial-words} \e$B$r\e(B t \e$B$K@_Dj$9$k$H9gCW$,5/\e(B
+\e$B$-$^$9!#MW$9$k$K!"8l$r6h@Z$k>r7o$,:o=|$5$l!"Be$o$j$K9gCW$,$h\e(B
+\e$B$j\e(B grep \e$B$i$7$/$J$k$N$G$9!#\e(B
+
+@findex nnmail-split-fancy-with-parent
+\e$B4X?t\e(B @code{nnmail-split-fancy-with-parent} \e$B$O!"%U%)%m!<%"%C%W5-;v$r?F5-\e(B
+\e$B;v$HF1$8%0%k!<%W$K?6$jJ,$1$k$?$a$K;H$$$^$9!#%a!<%k$N?6$jJ,$1$r0l@87|L?@_\e(B
+\e$BDj$7$F$_$F$b40`z$K$O$G$-$J$$$3$H$,$"$j$^$9$M!#Nc$($P!">e;J$+$i8D?M08$F$N\e(B
+\e$B%a!<%k$,FO$$$?$H$7$^$9!#<+J,$,7H$C$F$$$k%W%m%8%'%/%H$H$OJL$NOC$G$9!#$1$l\e(B
+\e$B$I!VB>$N%a!<%k$H6hJL$G$-$k$h$&$K$3$l$3$l$3$&$$$&8@MU$rI=Bj$K=q$$$F$/$@$5\e(B
+\e$B$$!W$H>e;J$K8~$+$C$F;X?^$9$k$o$1$K$O$$$-$^$;$s$+$i!"7k6I<+J,$N<j$rHQ$o$7\e(B
+\e$B$F$R$H$D$R$H$D%a!<%k$r@5$7$$%0%k!<%W$K?6$jJ,$1$k$O$a$K$J$j$^$9!#$=$s$J$H\e(B
+\e$B$-$K$3$N4X?t$r;H$&$H!"$3$NLLE]$J:n6H$r0l%9%l%C%I$K$D$-0l2s$-$j$G:Q$^$9$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+\e$B$3$N5!G=$rMxMQ$9$k$?$a$K$O!"$^$:JQ\e(B
+\e$B?t\e(B @code{nnmail-treat-duplicates} \e$B$*$h\e(B
+\e$B$S\e(B @code{nnmail-cache-accepted-message-ids} \e$B$NCM$rHs\e(B-code{nil} \e$B$K@_Dj$9\e(B
+\e$B$kI,MW$,$"$j$^$9!#$=$l$,$G$-$?\e(B
+\e$B$i\e(B @code{nnmail-split-fancy-with-parent} \e$B$r;H$C$F$_$F$/$@$5$$!#%3%m%s$r\e(B
+\e$B;H$C$F$3$s$JIw$K=q$-$^$9\e(B:
+
+@lisp
+(setq nnmail-treat-duplicates 'warn     ; @r{\e$B$^$?$O\e(B @code{delete}}
+      nnmail-cache-accepted-message-ids t
+      nnmail-split-fancy
+      '(| (: nnmail-split-fancy-with-parent)
+          ;; @r{\e$B;D$j$N?6$jJ,$1J}$O$3$3$K=q$/\e(B}
+        ))
+@end lisp
+
+\e$B$3$N5!G=$O<B:]!"<!$NMM$KF/$$$F$$$^$9\e(B: \e$BJQ?t\e(B
+@code{nnmail-treat-duplicates} \e$B$NCM$,Hs\e(B-@code{nil} \e$B$N>l9g!"\e(BGnus \e$B$O8+$D$1\e(B
+\e$B$?A45-;v$N%a%C%;!<%8\e(B ID \e$B$rJQ?t\e(B @code{nnmail-message-id-cache-file} \e$B$,;X\e(B
+\e$BDj$9$k%U%!%$%k$K5-O?$7$^$9!#$3$N$H$-!"$=$l$>$l$N5-;v$,B8:_$9$k%0%k!<%W$N\e(B
+\e$BL>A0$rJ;5-$7$^$9\e(B (\e$B$?$@$7%a!<%k$N>l9g$@$1!"$5$b$J$1$l$P%0%k!<%WL>$OD4$Y$^\e(B
+\e$B$;$s\e(B)\e$B!#$5$F!"$$$h$$$h%a!<%k$N?6$jJ,$1$,;O$^$k$H!"4X?t\e(B
+@code{nnmail-split-fancy-with-parent} \e$B$O!"BP>]$H$J$k3F5-;v$N\e(B References
+(\e$B$H\e(B In-Reply-To) \e$B%X%C%@$rD4$Y!"\e(B@code{nnmail-message-id-cache-file} \e$B$K;X\e(B
+\e$BDj$5$l$F$$$k%U%!%$%k$K$=$l$i$N%a%C%;!<%8\e(B ID \e$B$,$"$k$+$I$&$+D4$Y$^$9!#?F5-\e(B
+\e$B;v$,8+$D$+$k$H!"$=$N%0%k!<%WL>$,@55,I=\e(B
+\e$B8=\e(B @code{nnmail-split-fancy-with-parent-ignore-groups} \e$B$K%^%C%A$7$J$1$l\e(B
+\e$B$P!"$3$N4X?t$OBP1~$9$k%0%k!<%WL>$rJV$9$o$1$G$9!#$3$3$G!"JQ\e(B
+\e$B?t\e(B @code{nnmail-message-id-cache-length} \e$B$NCM$r4{DjCM$h$j$b4v$i$+Bg$-$J\e(B
+\e$BCM$K@_Dj$9$k$3$H$r$*4+$a$7$^$9!#$=$&$9$k$H!":#D4$Y$i$l$?%a%C%;!<%8\e(B ID \e$BC#\e(B
+\e$B$O:#$7$P$i$/%-%c%C%7%e$NCf$KB8B3$G$-$^$9\e(B (5000 \e$B$K@_Dj$9$k$H%-%c%C%7%e%U%!\e(B
+\e$B%$%k$NBg$-$5$O$@$$$?$$\e(B 300 \e$B%-%m%P%$%H$0$i$$$K$J$k$_$?$$$G$9\e(B)\e$B!#\e(B
+@vindex nnmail-cache-accepted-message-ids
+\e$B$5$i$K!"JQ?t\e(B @code{nnmail-cache-accepted-message-ids} \e$B$NCM$r\e(B
+\e$BHs\e(B-@code{nil} \e$B$K@_Dj$9$l$P!"\e(Bgnus \e$B$O0\F0$5$l$?5-;v$N%a%C%;!<%8\e(B ID \e$B$r$b5-\e(B
+\e$BO?$9$k$N$G!"%U%)%m!<%"%C%W5-;v$O?F5-;v$N0\F0@h$HF1$8%0%k!<%W$KF~$k$h$&$K\e(B
+\e$B$J$j$^$9!#\e(B
+
+\e$B$"$k%0%k!<%W$r%-%c%C%7%e$K5-O?$7$?$/$J$$>l9g$O!"JQ\e(B
+\e$B?t\e(B @code{nnmail-cache-ignore-groups} \e$B$b;2>H$7$F2<$5$$!#Nc$($P!"30$K=P$9\e(B
+\e$B$9$Y$F$N%a%C%;!<%8$,\e(B ``outgoing'' \e$B%0%k!<%W$G=q$+$l$F$$$k$J$i$P!"\e(B
+@code{nnmail-cache-ignore-groups} \e$B$r$=$N%0%k!<%WL>$K%^%C%A$9$k$h$&$K@_Dj\e(B
+\e$B$9$k$N$,NI$$$G$9!#$5$b$J$$$H$"$J$?$N$9$Y$F$N%a%C%;!<%8$KBP$9$kJV;v$,!":G\e(B
+\e$B8e$O\e(B ``outgoing'' \e$B%0%k!<%W$KF~$C$F$7$^$&$G$7$g$&!#\e(B
+
+@node Group Mail Splitting
+@subsection \e$B%0%k!<%W%a!<%kJ,3d\e(B
+@cindex mail splitting
+@cindex group mail splitting
+
+@findex gnus-group-split
+\e$B$?!<$/$5$s$N%a!<%j%s%0%j%9%H$r9XFI$7$F$$$k$1$l$I!"<j$G%a!<%kJ,3d5,B'$r0]\e(B
+\e$B;}$7$?$/$J$$$H$-$O!"%0%k!<%W%a!<%kJ,3d$H$$$&$b$N$,$"$J$?$N$?$a$K$"$j$^$9!#\e(B
+\e$B%0%k!<%W%Q%i%a!<%?$+%0%k!<%W%+%9%?%^%$%:\e(B
+\e$B$G\e(B @code{to-list}, @code{to-address} \e$B$NN>J}$b$7$/$O$I$A$i$+$r@_Dj$7\e(B
+\e$B$F\e(B @code{nnmail-split-methods} \e$B$r\e(B @code{gnus-group-split} \e$B$K@_Dj$9$k$@$1\e(B
+\e$B$G$9!#J,3d4X?t$OA4$F$N%0%k!<%W$G$3$l$i$N%Q%i%a!<%?$rAv::$7!"$=$l$K=>$C$F\e(B
+\e$BJ,3d$7$^$9!#$9$J$o$A!"%a!<%k%0%k!<%W$N%Q%i%a!<\e(B
+\e$B%?\e(B @code{to-list} \e$B$+\e(B @code{to-address} \e$B$G;XDj$5$l$?%"%I%l%9$+$iEj9F$5$l\e(B
+\e$B$?$b$N$+!"$=$N%"%I%l%9$XEj9F$5$l$?%a%C%;!<%8$,$=$N%0%k!<%W$KJ]B8$5$l$^$9!#\e(B
+
+\e$B$H$-$K$O!"%a!<%j%s%0%j%9%H$K$OJ#?t$N%"%I%l%9$,$"$j!"%a!<%kJ,3d$K$=$l$iA4\e(B
+\e$B$F$rG'<1$5$;$kI,MW$,$"$k$+$b$7$l$^$;$s\e(B: @code{extra-aliases} \e$B%0%k!<%W%Q\e(B
+\e$B%i%a!<%?$rDI2C$N%"%I%l%9$N%j%9%H$K@_Dj$9$k$@$1$G=*$j$G$9!#@55,I=8=$r;H$$\e(B
+\e$B$?$1$l$P!"\e(B@code{split-regexp} \e$B$r@_Dj$7$F$/$@$5$$!#\e(B
+
+\e$B$3$l$i$NA4$F$N%0%k!<%W$N%Q%i%a!<%?$O!"\e(B@code{nnmail-split-fancy} \e$BJ,3d$r:n\e(B
+\e$B@.$9$k$?$a$K;HMQ$5$l!"$=$l$O\e(B @var{field} \e$B$,\e(B @samp{any} \e$B$G!"\e(B
+@var{value} \e$B$,\e(B @code{to-list}, @code{to-address},
+@code{extra-aliases} \e$B$N$9$Y$F!"\e(B@code{split-regexp} \e$B$NA4$F$N9gCW$K9gCW$9\e(B
+\e$B$kC1FH$N@55,I=8=!"\e(B@var{split} \e$B$,%0%k!<%W$NL>A0$K$J$j$^$9!#\e(B@var{restrict}
+\e$B$b;HMQ$G$-$^$9\e(B: @code{split-exclude} \e$B%Q%i%a!<%?$r@55,I=8=$N%j%9%H$K@_Dj\e(B
+\e$B$9$k$@$1$G$9!#\e(B
+
+\e$B$3$l$i$NA4$F$N%Q%i%a!<%?$r;H$C$F@5$7$$J,3d$,@8@.$5$l$J$$$H$-$d!"2?$+0c$C\e(B
+\e$B$?$b$N$,I,MW$J$H$-$O!"%Q%i%a!<\e(B
+\e$B%?\e(B @code{split-spec} \e$B$r\e(B @code{nnmail-split-fancy} \e$BJ,3d$K@_Dj$9$k$3$H$,$G\e(B
+\e$B$-$^$9!#$3$N>l9g$O!"B>$NA0$K=q$$$?A4$F$N%Q%i%a!<%?\e(B
+\e$B$O\e(B @code{gnus-group-split} \e$B$KL5;k$5$l$^$9!#FC$K!"\e(B
+@code{split-spec} \e$B$O\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$,$G$-!"$=$N>l9g$O%0%k!<%W\e(B
+\e$B$O\e(B @code{gnus-group-split} \e$B$KL5;k$5$l$^$9!#\e(B
+
+@vindex gnus-group-split-default-catch-all-group
+@code{gnus-group-split} \e$B$O$=$l$>$l$N%0%k!<%W$K0l$D$NJ,3d$r4^$`C10l\e(B
+\e$B$N\e(B @code{&} \e$BFC5iJ,3d$rDj5A$9$k$3$H$G9gCW$9$kA4$F$N%0%k!<%W$KAj8_Ej9F$r$7\e(B
+\e$B$^$9!#%a%C%;!<%8$,$I$NJ,3d$K$b9gCW$7$J$1$l$P!"$I$l$+$N%0%k!<%W\e(B
+\e$B$G\e(B @var{split-spec} \e$B$,\e(B @code{catch-all} \e$B$K@_Dj$5$l$F$$$J$$>l9g\e(B
+\e$B$O\e(B @code{gnus-group-split-default-catch-all-group} \e$B$G;XDj$5$l$F$$$k%0%k!<\e(B
+\e$B%W$KJ]B8$5$l$^$9!#\e(B@code{split-spec} \e$B$,\e(B @code{catch-all} \e$B$K@_Dj$5$l$F$$$k\e(B
+\e$B%0%k!<%W$,$"$k>l9g$O!"$=$N%0%k!<%W$,A4$F$rJa3M$9$k%0%k!<%W$H$7$F;HMQ$5$l\e(B
+\e$B$^$9!#$3$NJQ?t$O$7$P$7$PC1$K%0%k!<%W$r;XDj$9$k$?$a$K;H$o$l$^$9$,!"G$0U$N\e(B
+\e$BJ#;($JFC5iJ,3d$r$b@_Dj$9$k\e(B (\e$B7k6I!"%0%k!<%WL>$OFC5iJ,3d$J$N$G$9\e(B) \e$B$N$G!"8D\e(B
+\e$B?M$N%a!<%k%U%)%k%@!<$N$I$N%a!<%j%s%0%j%9%H$K$bEv$F$O$^$i$J$$%a!<%k$rJ,3d\e(B
+\e$B$9$k$N$KJXMx$G$7$g$&!#$J$*$3$NFC5iJ,3d$O!"\e(B@code{|} \e$BJ,3d%j%9%H$N:G8e$NMW\e(B
+\e$BAG\e(B - \e$B%0%k!<%W%Q%i%a!<%?$+$iCj=P$5$l$?5,B'$r;}$D\e(B @code{&} \e$BJ,3d$r4^$`\e(B - \e$B$H\e(B
+\e$B$7$FDI2C$5$l$k$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+
+\e$B$=$m$=$mNc$r=P$9$Y$-$G$7$g$&!#0J2<$N%0%k!<%W%Q%i%a!<%?$,Dj5A$5$l$F$$$k$H\e(B
+\e$B$7$^$9\e(B:
+
+@example
+nnml:mail.bar:
+((to-address . "bar@@femail.com")
+ (split-regexp . ".*@@femail\\.com"))
+nnml:mail.foo:
+((to-list . "foo@@nowhere.gov")
+ (extra-aliases "foo@@localhost" "foo-redist@@home")
+ (split-exclude "bugs-foo" "rambling-foo")
+ (admin-address . "foo-request@@nowhere.gov"))
+nnml:mail.others:
+((split-spec . catch-all))
+@end example
+
+@code{nnmail-split-methods} \e$B$r\e(B @code{gnus-group-split} \e$B$K@_Dj$9$k$H!"\e(B
+@code{nnmail-split-fancy} \e$B$,A*Br$5$l$F!"JQ\e(B
+\e$B?t\e(B @code{nnmail-split-fancy} \e$B$,0J2<$N$h$&$K@_Dj$5$l$F$$$k$+$N$h$&$K?6Iq\e(B
+\e$B$$$^$9\e(B:
+
+@lisp
+(| (& (any "\\(bar@@femail\\.com\\|.*@@femail\\.com\\)" "mail.bar")
+      (any "\\(foo@@nowhere\\.gov\\|foo@@localhost\\|foo-redist@@home\\)"
+           - "bugs-foo" - "rambling-foo" "mail.foo"))
+   "mail.others")
+@end lisp
+
+@findex gnus-group-split-fancy
+\e$BA4$F$N%a!<%k%0%k!<%W$G%0%k!<%WJ,3d$r;HMQ$7$?$/$O$J$$$H$-$O!"\e(B
+@code{nnmail-split-fancy} \e$BJ,3d$r<!$N$h$&$K;HMQ$9$k$3$H$G$$$/$D$+$N%0%k!<\e(B
+\e$B%W$@$1$K;H$&$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(: gnus-group-split-fancy @var{groups} @var{no-crosspost} @var{catch-all})
+@end lisp
+
+@var{groups} \e$B$O=PNO$NJ,3d$r@8@.$9$k$?$a$K%Q%i%a!<%?$,Av::$5$l$k%0%k!<%W\e(B
+\e$BL>$N%j%9%H$+@55,I=8=$G$9!#\e(B@var{no-crosspost} \e$B$OAj8_Ej9F$r;HMQ6X;_$K$k$?\e(B
+\e$B$a$K;H$&$3$H$,$G$-$^$9!#$=$N>l9g!"C10l$N\e(B @code{|} \e$BJ,3d$,=PNO$5$l$^$9!#\e(B
+@var{catch-all} \e$B$O\e(B @code{gnus-group-split-default-catch-all-group} \e$B$N$h\e(B
+\e$B$&$K!":G8e$N<jCJ$H$7$F;H$o$l$kFC5iJ,3d$G$9!#\e(B
+@var{catch-all} \e$B$,\e(B @code{nil} \e$B$G$"$k$+!"\e(B@code{split-regexp} \e$B$,$I$l$+$NA*\e(B
+\e$BBr$5$l$?%0%k!<%W6uJ8;zNs$K9gCW$9$k$H!"A4Ja3MJ,3d$O9T$o$l$^$;$s!#$=$&$G$J\e(B
+\e$B$$>l9g!"%0%k!<%W$K\e(B @code{split-spec} \e$B$,\e(B @code{catch-all} \e$B$K@_Dj$5$l$F$$\e(B
+\e$B$k$b$N$,$"$k$H!"$3$N%0%k!<%W$,\e(B @var{catch-all} \e$B0z?t$r>e=q$-$7$^$9!#\e(B
+
+@findex gnus-group-split-setup
+\e$BIT1?$J$3$H$K!"A4$F$N%0%k%W$H%Q%i%a!<%?$rAv::$9$k$3$H$OHs>o$KCY$$$G$9!#FC\e(B
+\e$B$KA4$F$N%a%C%;!<%8$KBP$7$F$J$5$l$k$3$H$r9M$($k$H!#$1$l$I$b!"@dK>$7$J$$\e(B
+\e$B$G\e(B! \e$B4X?t\e(B @code{gnus-group-split-setup} \e$B$,\e(B @code{gnus-group-split} \e$B$r$h$j\e(B
+\e$B$:$C$H8zN(E*$JJ}K!$G;H$&$3$H$,$G$-$^$9!#$=$l\e(B
+\e$B$O\e(B @code{nnmail-split-methods} \e$B$r\e(B @code{nnmail-split-fancy} \e$B$K@_Dj$7!"\e(B
+@code{nnmail-split-fancy} \e$B$r\e(B @code{gnus-group-split-fancy} \e$B$G@8@.$5$l$?\e(B
+\e$BJ,3d$K@_Dj$7$^$9!#$3$&$7$F$I$s$J$KJ,3d$9$k%a%C%;!<%8$,$?$/$5$s$"$C$F$b!"\e(B
+\e$B%0%k!<%W%Q%i%a!<%?$O0lEY$@$1Av::$5$l$^$9!#\e(B
+
+@findex gnus-group-split-update
+\e$B$7$+$7!"%0%k!<%W%Q%i%a!<%?$rJQ99$9$k$H!"\e(B@code{nnmail-split-fancy} \e$B$r<j$G\e(B
+\e$B99?7$7$J$1$l$P$J$j$^$;$s!#\e(B@code{gnus-group-split-update} \e$B$r<B9T$9$k$3$H\e(B
+\e$B$G$=$l$r9T$($^$9!#<+F0E*$K99?7$5$l$kJ}$,9%$_$J$i!"\e(B
+@code{gnus-group-split-setup} \e$B$K$=$l$r<B9T$9$k$h$&$K65$($k$@$1$G$9!#Nc$(\e(B
+\e$B$P!"\e(B@file{~/.gnus.el} \e$B$K0J2<$N$b$N$rDI2C$7$F$/$@$5$$\e(B:
+
+@lisp
+(gnus-group-split-setup @var{auto-update} @var{catch-all})
+@end lisp
+
+@var{auto-update} \e$B$,\e(B @code{nil} \e$B$GL5$$$H!"\e(B
+@code{gnus-group-split-update} \e$B$,\e(B @code{nnmail-pre-get-new-mail-hook} \e$B$K\e(B
+\e$BDI2C$5$l!"FsEY$H\e(B @code{nnmail-split-fancy} \e$B$N99?7$r?4G[$9$kI,MW$O$"$j$^\e(B
+\e$B$;$s!#\e(B@var{catch-all} \e$B$r>JN,$7$J$$>l9g$O\e(B (\e$B$=$l$O%*%W%7%g%s\e(B
+\e$B$G\e(B @code{nil} \e$B$HEy\e(B
+\e$B2A\e(B)\e$B!"\e(B@code{gnus-group-split-default-catch-all-group} \e$B$O$=$NCM$K@_Dj$5$l\e(B
+\e$B$^$9!#\e(B
+
+@vindex gnus-group-split-updated-hook
+@code{nnmail-split-fancy} \e$B$,\e(B @code{gnus-group-split-update} \e$B$G@_Dj$5$l$?\e(B
+\e$B8e$GJQ99$9$kI,MW$,$"$k$H$-$N$?$a$K!"$3$N4X?t\e(B
+\e$B$O\e(B @code{gnus-group-split-update-hook} \e$B$r=*N;$9$kD>A0$K<B9T$7$^$9!#\e(B
+
+@node Incorporating Old Mail
+@subsection \e$B8E$$%a!<%k$r<h$j9~$`\e(B
+@cindex incorporating old mail
+@cindex import old mail
+
+\e$B$?$$$F$$$N?M$O?'!9$J%U%!%$%k%U%)!<%^%C%H$GC_@Q$5$l$?$?$/$5$s$N8E$$%a!<%k\e(B
+\e$B$,$"$k$G$7$g$&!#$b$7\e(B gnus \e$B$K?h$J\e(B gnus \e$B%a!<%k%P%C%/%(%s%I$N0l$D$r;H$&$h$&\e(B
+\e$B$K@_Dj$7$?$N$G$"$l$P!"$*$=$i$/8E$$%a!<%k$r%a!<%k%0%k!<%W$K<h$j9~$_$?$$$H\e(B
+\e$B;W$&$G$7$g$&!#\e(B
+
+\e$B$=$l$r$9$k;v$O$H$F$b4JC1$G$9!#\e(B
+
+\e$BNc$r5s$2$^$7$g$&\e(B: @code{nnml} (@pxref{Mail Spool}) \e$B$r;H$C$F%a!<%k$rFI$s\e(B
+\e$B$G$$$F!"\e(B@code{nnmail-split-methods} \e$B$rK~B-$G$-$kCM$K@_Dj$7$F$$$^$9!#8E\e(B
+\e$B$$\e(B Unix mbox \e$B%U%!%$%k$,=EMW$@$1$l$I8E$$%a!<%k$GK~$?$5$l$F$$$^$9!#$"$J$?\e(B
+\e$B$O$=$l$r\e(B @code{nnml} \e$B%0%k!<%W$K0\F0$7$?$$$H;W$C$F$$$^$9!#\e(B
+
+\e$BJ}K!$G$9\e(B:
+
+@enumerate
+@item
+\e$B%0%k!<%W%P%C%U%!$K9T$-$^$9!#\e(B
+
+@item
+@kbd{G f} \e$B$HBG$C$F!"\e(Bmbox \e$B%U%!%$%k$+$i\e(B @code{nndoc} \e$B%0%k!<%W$r:n@.$9$k$h\e(B
+\e$B$&$KB%$5$l$?$H$-$K\e(B mbox \e$B$N%U%!%$%kL>A0$rM?$($^$9\e(B (@pxref{Foreign
+Groups})\e$B!#\e(B
+
+@item
+@kbd{SPACE} \e$B$rBG$C$F!"?7$7$/:n$i$l$?%0%k!<%W$KF~$j$^$9!#\e(B
+
+@item
+@kbd{M P b} \e$B$rBG$C$F!"%0%k!<%W%P%C%U%!$NA4$F$N5-;v$K<B9T0u$rIU$1$^\e(B
+\e$B$9\e(B (@pxref{Setting Process Marks})\e$B!#\e(B
+
+@item
+@kbd{B r} \e$B$rBG$C$FA4$F$N%W%m%;%90u$NIU$$$?:F%9%W!<%k$7!"B%$5$l$?$H$-\e(B
+\e$B$K\e(B @samp{nnml} \e$B$HEz$($^$9\e(B (@pxref{Mail Group Commands})\e$B!#\e(B
+@end enumerate
+
+mbox \e$B%U%!%$%k$NA4$F$N%a!<%k%a%C%;!<%8$b:#$d$"$J$?$N\e(B @code{nnml} \e$B%0%k!<%W\e(B
+\e$B$K9-$,$C$F$$$^$9!#$=$l$i$KF~$C$F!"JQ$J8N>c$b$J$/J*;v$,>e<j$/9T$C$F$$$k$+\e(B
+\e$B$I$&$+$rD4$Y$F$/$@$5$$!#$b$7Bg>fIW$J$h$&$G$"$l$P!"\e(Bmbox \e$B%U%!%$%k$r>C$9;v\e(B
+\e$B$r9M$($k$+$b$7$l$^$;$s$,!";d$OA4$F$N%a!<%k$,$"$k$Y$-$H$3$m$KG<$^$C$F$$$k\e(B
+\e$B$N$r40A4$K3NG'$9$k$^$G$O!"$=$&$O$7$^$;$s!#\e(B
+
+@node Expiring Mail
+@subsection \e$B%a!<%k$N4|8B@Z$l>C5n\e(B
+@cindex article expiry
+
+\e$BEAE}E*$J%a!<%k%j!<%@!<$O!"2?$+!"4{FI$N0u$rIU$1$k$H5-;v$r:o=|$9$k798~$,$"\e(B
+\e$B$j$^$9!#\e(BGnus \e$B$O%a!<%k$rFI$`;v$KBP$7$F!"4pK\E*$KA4$/0c$C$?J}K!$r<h$j$^$9!#\e(B
+
+Gnus \e$B$O4pK\E*$K%a!<%k$rHf3SE*FCJL$JJ}K!$G<u$1<h$i$l$?%K%e!<%9$G$"$k$H$_\e(B
+\e$B$J$7$^$9!#$=$l$O<B:]$K%a!<%k$rJQ99$7$?$j!"%a!<%k%a%C%;!<%8$r>C$98"NO$,$"\e(B
+\e$B$k$H$O9M$($^$;$s!#%a!<%k%0%k!<%W$KF~$C$F!"5-;v$K\e(B ``\e$B4{FI\e(B'' \e$B$N0u$rIU$1$?$j!"\e(B
+\e$BB>$NN.57$G@Z$C$?$j$7$F$b!"%a!<%k5-;v$O$^$@%7%9%F%`$KB8:_$7$F$$$^$9!#7+$j\e(B
+\e$BJV$7$^$9\e(B: gnus \e$B$O$"$J$?$N8E$$!"4{FI%a!<%k$r>C5n$7$^$;$s!#$b$A$m$s!"$"$J\e(B
+\e$B$?$,$=$&$7$m$HMj$^$J$$8B$j$NOC$G$9$,!#\e(B
+
+Gnus \e$B$KK>$^$7$/$J$$%a!<%k$r:o=|$5$;$k$?$a$K$O!"5-;v$r\e(B @dfn{\e$B4|8B@Z$l>C5n\e(B
+\e$B2DG=\e(B} (expirable) \e$B$H$7$F0u$rIU$1$J$1$l$P$J$j$^$;$s!#\e(B(\e$B%G%#%U%)%k%H$N%-!<\e(B
+\e$B3d$jEv$F$G$O!"\e(B@kbd{E} \e$B$r%?%$%W$7$J$1$l$P$J$i$J$$$3$H$r0UL#$7$^$9!#\e(B) \e$B$7$+\e(B
+\e$B$7$J$,$i!"$3$l$O5-;v$,B(:B$K>C$(5n$k$H$$$&;v$G$O$"$j$^$;$s!#0lHLE*$K!"%a!<\e(B
+\e$B%k5-;v$O<!$N$h$&$J>l9g$K%7%9%F%`$K$h$C$F:o=|$5$l$^$9\e(B 1) \e$B4|8B@Z$l>C5n2DG=\e(B
+\e$B$N0u$rIU$1$i$l$k\e(B 2) \e$B0l=54V0J>e7P$C$?5-;v$G$"$k!#$b$75-;v$r4|8B@Z$l>C5n2D\e(B
+\e$BG=$K$7$J$1$l$P!"$=$l$OCO9v$,E`$j$D$/$^$G%7%9%F%`$K;D$j$D$E$1$^$9!#$3$l$O\e(B
+\e$B$b$&0lEY6/D4IU$-$G7+$jJV$5$l$k$KB-$k$b$N$G$9\e(B: ``\e$B$b$7\e(B'' \e$B$"$J$?$,5-;v\e(B
+\e$B$r\e(B ``\e$B4|8B@Z$l>C5n2DG=\e(B'' \e$B$G$"$k$H\e(B ``\e$B$7$J$$\e(B'' \e$B$J$i!"\e(Bgnus \e$B$O\e(B ``\e$B7h$7$F\e(B'' \e$B$=\e(B
+\e$B$l$i$N\e(B ``\e$B5-;v\e(B'' \e$B$r>C5n$7$^$;$s!#\e(B
+
+\e$B<j:n6H$G5-;v$K4|8B@Z$l>C5n2DG=$N0u$rIU$1$J$1$l$P$J$i$J$$$o$1$G$O$"$j$^$;\e(B
+\e$B$s!#\e(Bgnus \e$B$O\e(B ``auto-expire'' \e$B$*$h$S\e(B ``total-expire'' \e$B$H8F$P$l$kFs$D$N5!G=\e(B
+\e$B$rDs6!$7$F!"$"$J$?$N<j=u$1$r$7$^$9!#$+$$$D$^$s$G8@$($P!"\e(B
+``auto-expire'' \e$B$O$"$J$?$,5-;v$rA*Br$7$?$H$-$K\e(B gnus \e$B$,\e(B @kbd{E} \e$B$rC!$$$F\e(B
+\e$B$/$l$k$3$H$r0UL#$7$^$9!#$=$7$F\e(B ``total-expire'' \e$B$O!"$9$Y$F$N4{FI$N5-;v$O\e(B
+\e$B4|8B@Z$l>C5n2DG=$G$"$k$H\e(B gnus \e$B$,2r<a$9$k$3$H$r0UL#$7$^$9!#$7$?$,$C\e(B
+\e$B$F\e(B @samp{E} \e$B$N0u$,IU$1$i$l$?5-;v$K2C$($F!"\e(B@samp{r}, @samp{R}, @samp{O},
+@samp{K}, @samp{Y} \e$B$J$I$N0u$,IU$1$i$l$?5-;v$b4|8B@Z$l>C5n2DG=$G$"$k$H2r\e(B
+\e$B<a$5$l$^$9!#\e(B
+
+Auto-expire \e$B$^$?$O\e(B total-expire \e$B$O!"$$$D;HMQ$5$l$k$Y$-$G$9$+\e(B? \e$B%a!<%j%s%0\e(B
+\e$B%j%9%H$r9XFI$7$F$$$k$[$H$s$I$N?M!9$O!"$=$l$>$l$N%j%9%H$r$=$l<+?H$N%0%k!<\e(B
+\e$B%W$KJ,3d$7!"$=$l$i$N%0%k!<%W$KBP$7$F\e(B auto-expire \e$B$^$?$O\e(B total-expire \e$B$r\e(B
+\e$BM-8z$K$7$^$9!#\e(B(@xref{Splitting Mail}, \e$B$=$l$>$l$N%j%9%H$N$=$l<+?H$N%0%k!<\e(B
+\e$B%W$X$NJ,3d$K$D$$$F$N$5$i$J$k>pJs!#\e(B)
+
+Auto-expire \e$B$^$?$O\e(B total-expire \e$B$N$I$A$i$,NI$$$G$9$+\e(B? \e$B$=$l$OEz$($K$/$$$G\e(B
+\e$B$9!#35$7$F8@$($P!"$?$V$s\e(B auto-expire \e$B$,B.$$$G$7$g$&!#\e(Bauto-expire \e$B$NJL$N\e(B
+\e$BMxE@$O$h$jB?$/$N%^!<%/$r;H$($k\e(B - \e$B:F$SFI$`$3$H$K$J$C$F$$$k\e(B (be supposed
+to stick around \e$B$N0ULu\e(B) \e$B5-;v$K$D$$$F$O!":#$^$G$I$*$j2D;k\e(B (tick)\e$B!"J]\e(B
+\e$BN1\e(B (dormant) \e$B$^$?$O4{FI\e(B (read) \e$B$NCf$+$iA*$V$3$H$,$G$-$k\e(B - \e$B$H$$$&$3$H$G$9!#\e(B
+\e$B$7$+$7\e(B total-expire \e$B$G$O\e(B dormant \e$B$H\e(B ticked \e$B$+$i$7$+A*$Y$^$;$s!#\e(B
+total-expire \e$B$NMxE@$O!"E,1~%9%3%"IU$1\e(B (@pxref{Adaptive Scoring}) \e$B$GNI9%\e(B
+\e$B$KF/$/$3$H$G$9!#\e(BAuto-expire \e$B$ODL>o$N%9%3%"IU$1$G$OF0:n$7$^$9$,!"E,1~%9%3\e(B
+\e$B%"IU$1$G$O$@$a$G$9!#\e(B
+
+@vindex gnus-auto-expirable-newsgroups
+\e$B@55,I=8=\e(B @code{gnus-auto-expirable-newsgroups} \e$B$K9gCW$9$k%0%k!<%W$OA4$F\e(B
+\e$B$N4{FI5-;v$K<+F0E*$K4|8B@Z$l>C5n2DG=$N0u$,IU$1$i$l$^$9!#A4$F$N4|8B@Z$l>C\e(B
+\e$B5n2DG=$N0u$NIU$$$?5-;v$O35N,%P%C%U%!$N:G=i$N7e$K\e(B @samp{E} \e$B$,I=<($5$l$^$9!#\e(B
+
+\e$B%G%#%U%)%k%H$G$O<+F04|8B@Z$l>C5n2DG=$r;HMQ$9$k$H!"\e(Bgnus \e$B$O$"$J$?$,FI$s$@\e(B
+\e$BA4$F$N5-;v$r!"$=$l$,4{FI$G$"$C$?$+L$FI$G$"$C$?$+$K4X$o$i$:!"4|8B@Z$l>C5n\e(B
+\e$B2DG=$H$7$F0u$rIU$1$^$9!#4{FI$N0u$NIU$$$?5-;v$,<+F0E*$K4|8B@Z$l>C5n2DG=$H\e(B
+\e$B$7$F0uIU$1$i$l$k$N$rHr$1$k$?$a$K!"0J2<$N$h$&$J$b$N\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$K=q$/;v$,$G$-$^$9\e(B:
+
+@vindex gnus-mark-article-hook
+@lisp
+(remove-hook 'gnus-mark-article-hook
+             'gnus-summary-mark-read-and-unread-as-read)
+(add-hook 'gnus-mark-article-hook 'gnus-summary-mark-unread-as-read)
+@end lisp
+
+\e$B<+F04|8B@Z$l>C5n2DG=%0%k!<%W$r:n$k;v$O!"A4$F$N4{FI5-;v$,4|8B@Z$l>C5n$5$l\e(B
+\e$B$k;v$G$O$J$$;v$K5$$rIU$1$F$/$@$5$$\e(B---\e$B4|8B@Z$l>C5n2DG=$H$7$F0u$NIU$$$?5-\e(B
+\e$B;v$@$1$,4|8B@Z$l>C5n$5$l$^$9!#L?Na\e(B @kbd{d}\e$B$,<+F0E*$K5-;v$r4|8B@Z$l>C5n2D\e(B
+\e$BG=$K$9$k$N$G$OL5$$$H$$$&;v$K$b5$$rIU$1$F$/$@$5$$\e(B---\e$BH><+F0$N!"<+F04|8B@Z\e(B
+\e$B$l>C5n2DG=%0%k!<%W$G5-;v$r4{FI$K0uIU$1$k$3$H$@$1$,5-;v$r4|8B@Z$l>C5n2DG=\e(B
+\e$B$K$7$^$9!#\e(B
+
+@lisp
+(setq gnus-auto-expirable-newsgroups
+      "mail.nosense-list\\|mail.nice-list")
+@end lisp
+
+\e$B<+F04|8B@Z$l>C5n$r<B9T$9$kB>$NJ}K!$O!"%0%k!<%W$N%0%k!<%W%Q%i%a!<%?$H$7$F!"\e(B
+\e$BMWAG\e(B @code{auto-expirable} \e$B$r;}$D;v$G$9!#\e(B
+
+\e$B$b$7E,1~%9%3%"IU$1\e(B (@pxref{Adaptive Scoring}) \e$B$H<+F04|8B@Z$l>C5n$r;HMQ$7\e(B
+\e$B$F$$$k$J$i!"LdBj$,5/$3$k$G$7$g$&!#<+F04|8B@Z$l>C5n$HE,1~%9%3%"IU$1$O$"$^\e(B
+\e$B$jNI$/Aj8_:nMQ$7$^$;$s!#\e(B
+
+@vindex nnmail-expiry-wait
+\e$BJQ?t\e(B @code{nnmail-expiry-wait} \e$B$O4|8B@Z$l>C5n2DG=5-;v$,$I$l$/$i$$$N4|4V\e(B
+\e$B@8B8$7$F$$$k$+$N%G%#%U%)%k%H$N;~4V@_Dj$rDs6!$7$^$9!#\e(BGnus \e$B$O%a%C%;!<%8$,\e(B
+\e$BAw$i$l$?$H$-$G$O$J$/!"$=$l$,\e(B @emph{\e$BE~Ce\e(B} \e$B$7$F$+$i$NF|$r7W;;$7$^$9!#%G%#\e(B
+\e$B%U%)%k%H$O\e(B 7 \e$BF|4V$G$9!#\e(B
+
+Gnus \e$B$O5-;v$,$I$N%0%k!<%W$KB0$7$F$$$k$+$K4p$E$$$F!"$=$l$,$I$N$/$i$$@8B8\e(B
+\e$B$9$k$+$r@.8y$K@_Dj$9$k4X?t$bDs6!$7$F$$$^$9!#%0%k!<\e(B
+\e$B%W\e(B @samp{mail.private} \e$B$O4|8B$r\e(B 1\e$B%v7n$K!"%0%k!<%W\e(B @samp{mail.junk} \e$B$G$O\e(B
+\e$B4|8B$r\e(B 1 \e$BF|$K!"$=$NB>$N$b$N$K$O4|8B$r\e(B 6 \e$BF|4V$K$9$k$K$O\e(B:
+
+@vindex nnmail-expiry-wait-function
+@lisp
+(setq nnmail-expiry-wait-function
+      (lambda (group)
+       (cond ((string= group "mail.private")
+               31)
+             ((string= group "mail.junk")
+               1)
+             ((string= group "important")
+              'never)
+             (t
+               6))))
+@end lisp
+
+\e$B$3$N4X?t$KM?$($i$l$k%0%k!<%WL>$O\e(B ``\e$BAu>~L5$7\e(B'' \e$B$N%0%k!<%WL>$G$9\e(B---
+@samp{nnml:} \e$B$d$=$NB>$N;w$?$h$&$J$b$N$OIU$-$^$;$s!#\e(B
+
+\e$BJQ?t\e(B @code{nnmail-expiry-wait} \e$B$H4X\e(B
+\e$B?t\e(B @code{nnmail-expiry-wait-function} \e$B$O?t;z\e(B (\e$B@0?t$G$"$kI,MW$O$"$j$^$;\e(B
+\e$B$s\e(B) \e$B$+%7%s%\%k\e(B @code{immediate} \e$B$+\e(B @code{never} \e$B$N$I$A$i$+$G$"$k;v$,$G$-\e(B
+\e$B$^$9!#\e(B
+
+\e$B4|8B@Z$l4|4V$rA*BrE*$KJQ99$9$k$?$a$K%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B @code{expiry-wait} \e$B$r;H$&;v$b$G$-$^$9\e(B (@pxref{Group Parameters})\e$B!#\e(B
+
+@vindex nnmail-expiry-target
+\e$B5-;v$N4|8B@Z$l>C5n$NIaDL$NF0:n$O$=$l$i$r>C5n$9$k$3$H$G$9!#$7$+$7!">l9g$K\e(B
+\e$B$h$C$F$O$=$l$i$r>C5n$9$k$h$j$bJL$N%0%k!<%W$K0\F0$7$?J}$,M-0U5A$+$b$7$l$^\e(B
+\e$B$;$s!#JQ?t\e(B @code{nnmail-expiry-target} (\e$B$H%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B @code{expiry-target}) \e$B$O$3$l$r@)8f$7$^$9!#$3$NJQ?t$NCM$O$9$Y$F$N%0%k!<\e(B
+\e$B%W$KBP$9$k%G%#%U%)%k%H$K$J$j$^$9$,!"FCDj$N%0%k!<%W$4$H$K%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$r;H$C$F;XDj$9$l$P>e=q$-$9$k$3$H$,$G$-$^$9!#%G%#%U%)%k%H$NCM\e(B
+\e$B$O\e(B @code{delete} \e$B$G$9$,!"J8;zNs\e(B (\e$B5-;v$r0\F0$9$k@h$N%0%k!<%WL>\e(B) \e$B$^$?$O0\\e(B
+\e$BF0@h$N%0%k!<%WL>$+\e(B @code{delete} \e$B$rJV$94X?t\e(B (\e$B5-;v$KHO0O$r69$a$?%P%C%U%!\e(B
+\e$B$G!"$=$N5-;v$,B8:_$7$F$$$k%0%k!<%WL>$,0z?t$H$7$FM?$($i$l$^$9\e(B) \e$B$K$9$k$3$H\e(B
+\e$B$,$G$-$^$9!#\e(B
+
+\e$B%0%k!<%WL>$r;XDj$9$k>l9g$NNc\e(B:
+@lisp
+(setq nnmail-expiry-target "nnml:expired")
+@end lisp
+
+@findex nnmail-fancy-expiry-target
+@vindex nnmail-fancy-expiry-targets
+gnus \e$B$K$OJQ?t\e(B @code{nnmail-fancy-expiry-targets} \e$B$K=>$C$F%a!<%k$r4|8B@Z\e(B
+\e$B$l>C5n$9$k$?$a$N4X?t\e(B @code{nnmail-fancy-expiry-target} \e$B$,$"$j$^$9!#$3$l\e(B
+\e$B$ONc$G$9\e(B:
+
+@lisp
+ (setq nnmail-expiry-target 'nnmail-fancy-expiry-target
+       nnmail-fancy-expiry-targets
+       '((to-from "boss" "nnfolder:Work")
+         ("subject" "IMPORTANT" "nnfolder:IMPORTANT.%Y.%b")
+         ("from" ".*" "nnfolder:Archive-%Y")))
+@end lisp
+
+\e$B$3$N@_Dj$K$h$C$F!"BjL>$K\e(B @code{IMPORTANT} \e$B$r;}$A!"\e(B
+@code{YYYY} \e$BG/\e(B @code{MMM} \e$B7n$KH/?.$5$l$?$$$+$J$k%a!<%k$b!"%0%k!<\e(B
+\e$B%W\e(B @code{nnfolder:IMPORTANT.YYYY.MMM} \e$B$K4|8B@Z$l>C5n\e(B (\e$BLuCm\e(B: \e$B<B:]$NF0:n$O\e(B
+\e$BJ]B8\e(B) \e$B$5$l$^$9!#$b$7\e(B From \e$B$^$?$O\e(B To \e$B%X%C%@!<$,J8;zNs\e(B @code{boss} \e$B$r4^$s\e(B
+\e$B$G$$$?$i\e(B @code{nnfolder:Work} \e$B$K4|8B@Z$l>C5n$5$l$^$9!#$=$l0J30$N$9$Y$F$N\e(B
+\e$B%a!<%k$O\e(B @code{nnfolder:Archive-YYYY} \e$B$K4|8B@Z$l>C5n$5$l$^$9!#\e(B
+
+@vindex nnmail-keep-last-article
+@code{nnmail-keep-last-article} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$O%a!<%k%K%e!<\e(B
+\e$B%9%0%k!<%W$N:G8e$N5-;v$r7h$7$F4|8B@Z$l>C5n$7$^$;$s!#$3$l$O\e(B procmail \e$B$NMx\e(B
+\e$BMQ<T$N?M@8$r3Z$K$9$k$?$a$G$9!#\e(B
+
+@vindex gnus-total-expirable-newsgroups
+\e$B$H$3$m$G\e(B: \e$B$=$3$K$"$k!"\e(Bgnus \e$B$,7h$7$F4|8B@Z$l>C5n2DG=$G$J$$5-;v$r4|8B@Z$l\e(B
+\e$B>C5n$9$k;v$O$J$$!"$H$$$&$N$O13$G$9!#\e(B@code{total-expire} \e$B$r%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$KF~$l$k$H!"5-;v$O4|8B@Z$l>C5n$N0u$,IU$-$^$;$s$,!"A4$F$N5-;v$O4|8B@Z$l\e(B
+\e$B>C5n2aDx$KF~$l$i$l$^$9!#Hs>o$KCm0U$7$F;H$C$F$/$@$5$$!#$5$i$K$b$C$H4m81$J\e(B
+\e$B$b$N$OJQ?t\e(B @code{gnus-total-expirable-newsgroups} \e$B$G$9!#$3$N@55,I=8=$K9g\e(B
+\e$BCW$9$kA4$F$N%0%k!<%W$OA4$F$N4{FI5-;v$,4|8B@Z$l>C5n2DG=$N2aDx$KFM$C9~$^$l\e(B
+\e$B$^$9!#$3$l$O!"Ev$N%0%k!<%W$N\e(B @emph{\e$BA4$F\e(B} \e$B$N8E$$%a!<%k5-;v$O>/$78e$G:o=|\e(B
+\e$B$5$l$k$H$$$&;v$G$9!#Hs>o$KCm0U$7$F;H$C$F!"$"$J$?$,;HMQ$7$?@55,I=8=$,4V0c$C\e(B
+\e$B$?%0%k!<%W$K9gCW$7$F!"$"$J$?$NA4$F$N=EMW$J%a!<%k$,>C$($F$7$^$C$?$H8@$C$F!"\e(B
+\e$B;d$N$H$3$m$K5c$-IU$$$FMh$J$$$G$/$@$5$$!#\e(B@emph{\e$BCK\e(B}\e$B$K$J$j$J$5$$\e(B! \e$B$b$7$/$O!"\e(B
+@emph{\e$B=w\e(B} \e$B$K$J$j$J$5$$\e(B! \e$B$"$J$?$,5$;}$A$h$$$H46$8$kA4$F$N$b$N$H\e(B! \e$B$G$9$+$i\e(B
+\e$B$=$3$K\e(B!
+
+\e$B$?$$$F$$$N?M$O$[$H$s$I$N%a!<%k%0%k!<%W$r\e(B total-expirable (\e$BA4BN4|8B@Z$l>C\e(B
+\e$B5n2DG=\e(B) \e$B$K$7$^$9$,!#\e(B
+
+@vindex gnus-inhibit-user-auto-expire
+@code{gnus-inhibit-user-auto-expire} \e$B$,\e(B @code{nil} \e$B$G$J$1$l$P!"%0%k!<%W\e(B
+\e$B$,<+F0;~8B>C5n$,;HMQ$5$l$k$h$&$K$J$C$F$$$F$b!"MxMQ<T$N0uIU$1L?Na$O5-;v$K\e(B
+\e$B;~8B>C5n2DG=$N0u$rIU$1$^$;$s!#\e(B
+
+@node Washing Mail
+@subsection \e$B%a!<%k@vBu\e(B
+@cindex mail washing
+@cindex list server brain damage
+@cindex incoming mail treatment
+
+\e$B%a%$%i!<\e(B (mailer) \e$B$d%j%9%H%5!<%P!<\e(B (list server) \e$B$OK\Ev$KK\Ev$KGO</$2$?\e(B
+\e$B;v$r$9$k$3$H$G0-L>9b$$$G$9!#\e(B``\e$B$o$!!"\e(BRFC822 \e$B$O2f!9$N%5!<%P!<$rDL$C$F$$$/\e(B
+\e$B%a%C%;!<%8$NA4$F$N9T$N:G8e$K\e(B @code{wE aRe ElIte!!!!!1!!} \e$B$r2C$($k;v$rL@\e(B
+\e$B<(E*$K6X;_$O$7$F$$$J$$$>!#$5$!!"$d$C$F$_$h$&\e(B!!!!1'' \e$B$($'!"$=$N$H$*$j$G$9\e(B
+\e$B$,!"\e(BRFC822 \e$B$OG=NO$NDc$$?M$K$h$C$FFI$^$l$k$h$&$K$O=q$+$l$F$$$^$;$s!#L@Gr\e(B
+\e$B$J;v$O$=$3$G$O5DO@$5$l$F$$$^$;$s!#$G$9$+$i!#$=$&$$$&$3$H$G$9!#\e(B
+
+\e$BLdBjE@\e(B: \e$B%I%$%DHG\e(B Microsoft Exchange \e$B$OJVEz$NI=Bj$K\e(B @samp{Re: } \e$B$NBe$o$j\e(B
+\e$B$K\e(B @samp{AW: } \e$B$rIU$12C$($^$9!#;d$O$3$l$KF0MI$7$FO5Gb$7$F$$$k$U$j$r$9$k\e(B
+\e$B$3$H$b$G$-$^$7$?$,!"$=$&$9$k5$NO$,$"$j$^$;$s$G$7$?!#$=$l$O>P$&$Y$-;v$G$9!#\e(B
+
+Gnus \e$B$O5-;v$rI=<($9$k$H$-$K$=$l$r@vBu$9$k$?$a$K2aEY$N4X?t$rDs6!$7$F$$$^\e(B
+\e$B$9$,!"%a!<%k$r%G%#%9%/$KJ]B8$9$kA0$KA*JL$r$9$k$3$H$,$G$-$?J}$,NI$$$G$7$g\e(B
+\e$B$&!#$=$NL\E*$N$?$a$K!";0$D$N%U%C%/$H$=$N%U%C%/$KF~$l$k;v$N$G$-$k?'!9$J4X\e(B
+\e$B?t$,$"$j$^$9!#\e(B
+
+@table @code
+@item nnmail-prepare-incoming-hook
+@vindex nnmail-prepare-incoming-hook
+\e$B$3$N%U%C%/$O%a!<%k$K2?$+$r$9$kA0$K8F$P$l!"4pK\E*$J!"%a!<%k$rA]$$$F$-$l$$\e(B
+\e$B$K$9$k=j:n$N$?$a$K$"$j$^$9!#$=$l$OA4$F$N?7$7$$!"F~$C$F$-$?%a!<%k$r4^$s$G\e(B
+\e$B$$$k%P%C%U%!$G8F$P$l$^$9!#;H$&;v$N$G$-$k4X?t$O\e(B:
+
+@table @code
+@item nnheader-ms-strip-cr
+@findex nnheader-ms-strip-cr
+\e$B$=$l$>$l$N9T$+$i!":G8e$K$"$k%-%c%j%C%8%j%?!<%s\e(B (carriage return) \e$B$r<h$j\e(B
+\e$B=|$-$^$9!#$3$l$O\e(B MS \e$B$N%^%7%s>e$GF0:n$7$F$$$k\e(B Emacs \e$B$N%G%#%U%)%k%H$G$9!#\e(B
+@end table
+
+@item nnmail-prepare-incoming-header-hook
+@vindex nnmail-prepare-incoming-header-hook
+\e$B$3$N%U%C%/$O$=$l$>$l$N%X%C%@!<$KHO0O$r69$a$i$l$F\e(B (narrowed) \e$B8F$P$l$^$9!#\e(B
+\e$B%X%C%@!<$r$-$l$$$K$9$k$H$-$K;H$&;v$,$G$-$^$9!#;H$&;v$N$G$-$k4X?t$O\e(B:
+
+@table @code
+@item nnmail-remove-leading-whitespace
+@findex nnmail-remove-leading-whitespace
+\e$B%X%C%@!<$K$=$l$,NI$/8+$($k$h$&$K\e(B ``\e$BM-MQ$J\e(B'' \e$B%j%9%H%5!<%P!<$,A0$NJ}$KIU$1\e(B
+\e$B2C$($?6uGr$rL5$/$7$^$9!#$"$!$!!#\e(B
+
+(\e$B$3$N4X?t$O$9$Y$F$N%a%C%;!<%8$N%\%G%#Cf$K$"$k%X%C%@!<\e(B (\e$B%\%G%#Cf$N%a%C%;!<\e(B
+\e$B%8$,;}$C$F$$$k%X%C%@!<9T$N$h$&$J$b$N\e(B) \e$B$KBP$7$F$bF0:n$9$k$N$G!";HMQ$K:]$7\e(B
+\e$B$F$O@x:_E*$J4m81$rUT$s$G$$$^$9!#$7$?$,$C$F%P%0$r=$@5$9$k$h$j$O!"J8=q$GFC\e(B
+\e$BD'$r<($9$N$,!"$b$A$m$s@5$7$$2r7h$NF;$G$9!#\e(B)
+
+@item nnmail-remove-list-identifiers
+@findex nnmail-remove-list-identifiers
+\e$B$$$/$D$+$N%j%9%H%5!<%P!<$OF10l<1JL;R$rIU$12C$($^$9\e(B---\e$BNc$($P!"\e(B
+@samp{(idm)}---\e$B$rA4$F$N\e(B @code{Subject} \e$B%X%C%@!<$N:G=i$KIU$1$^$9!#$=$l$O!"\e(B
+\e$B@P4o;~Be$N%a!<%k%X%C%@!<$r;H$C$F$$$k?M$K$ONI$$;v$@$H;W$$$^$9!#$3$N4X?t$O\e(B
+\e$B@55,I=8=\e(B @code{nnmail-list-identifiers} \e$B$K9gCW$9$kJ8;zNs$r<h$j=|$-$^$9!#\e(B
+\e$B$=$l$O@55,I=8=$N%j%9%H$G$"$k;v$b$G$-$^$9!#\e(B
+@code{nnmail-list-identifiers} \e$B$K\e(B @code{\\(..\\)} \e$B$r4^$a$F$O$$$1$^$;$s!#\e(B
+
+\e$BNc$($P!"\e(B@samp{(idm)} \e$B$H\e(B @samp{nagnagnag} \e$BF10l<1JL;R$r<h$j=|$-$?$$$N$J$i\e(B:
+
+@lisp
+(setq nnmail-list-identifiers
+      '("(idm)" "nagnagnag"))
+@end lisp
+
+\e$B$3$l$O\e(B @code{gnus-list-identifiers} \e$B$GHsGK2uE*$K9T$&$3$H$b$G$-$^$9!#\e(B
+@xref{Article Hiding}.
+
+@item nnmail-remove-tabs
+@findex nnmail-remove-tabs
+\e$BA4$F$N\e(B @samp{TAB} \e$BJ8;z$r\e(B @samp{SPACE} \e$BJ8;z$KJQ49$7$^$9!#\e(B
+
+@item nnmail-fix-eudora-headers
+@findex nnmail-fix-eudra-headers
+@cindex Eudora
+Eudora \e$B$O2u$l$?\e(B @code{References} \e$B%X%C%@!<$r:n@.$7$^$9$,!"\e(B
+@code{In-Reply-To} \e$B%X%C%@!<$K$O$A$c$s$H$7$?$b$N$rF~$l$^$9!#$3$N4X?t\e(B
+\e$B$O\e(B @code{References} \e$B%X%C%@!<$r<h$j=|$-$^$9!#\e(B
+@end table
+
+@item nnmail-prepare-incoming-message-hook
+@vindex nnmail-prepare-incoming-message-hook
+\e$B$3$N%U%C%/$O$=$l$>$l$N%a%C%;!<%8$KHO0O$r69$a$i$l$F8F$P$l$^$9!#;H$&;v$N$G\e(B
+\e$B$-$k4X?t$O\e(B:
+
+@table @code
+@item article-de-quoted-unreadable
+@findex article-de-quoted-unreadable
+Quoted Readable \e$BId9f2=$rI|9f2=$7$^$9!#\e(B
+@end table
+@end table
+
+@node Duplicates
+@subsection \e$B=EJ#\e(B
+
+@vindex nnmail-treat-duplicates
+@vindex nnmail-message-id-cache-length
+@vindex nnmail-message-id-cache-file
+@cindex duplicate mails
+\e$B$$$/$D$+$N%a!<%j%s%0%j%9%H$N%a%s%P!<$J$i!";~!9F1$8%a!<%k$rFs$D<u$1<h$k;v\e(B
+\e$B$,$"$j$^$9!#$3$l$O$H$F$b$&$k$5$/46$8$k$3$H$b$"$j$^$9$N$G!"\e(B
+@code{nnmail} \e$B$O$=$l$,H/8+$9$k$+$b$7$l$J$$=EJ#$rD4$Y$F07$$$^$9!#$3$l$r$9\e(B
+\e$B$k$?$a$K!"8E$$\e(B @code{Message-ID} \e$B$rJ]B8$7$^\e(B
+\e$B$9\e(B---@code{nnmail-messagge-id-cache-file} \e$B$K!#$3$l$O%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B @file{~/.nnmail-cache} \e$B$G$9!#$=$l$KJ]B8$5$l$k:GBg?t\e(B
+\e$B$N\e(B @code{Message-ID} \e$B$OJQ?t\e(B @code{nnmail-message-id-cache-length} \e$B$K@)8f\e(B
+\e$B$5$l!"$=$l$O%G%#%U%)%k%H$G\e(B 1000 \e$B$G$9!#\e(B(\e$B$G$9$+$i!"\e(B
+1000 @code{Message-ID} \e$B$,N/$a$i$l$^$9!#\e(B) \e$B$3$l$,62$m$7$$$H;W$C$?$J$i!"\e(B
+@code{nnmail-treat-duplicates} \e$B$r\e(B @code{warn} (\e$B%G%#%U%)%k%H$G$O$=$N$h$&\e(B
+\e$B$K$J$C$F$$$^$9$,\e(B) \e$B$K@_Dj$9$k;v$,$G$-!"$=$&$9$l$P!"\e(B@code{nnmail} \e$B$O=EJ#%a!<\e(B
+\e$B%k$r>C5n$7$^$;$s!#$=$NBe$o$j$K!"%a!<%k$N@hF,$K$3$l$O0c$C$?%a%C%;!<%8$N=E\e(B
+\e$BJ#$G$"$k$H$$$&7Y9p$rA^F~$7$^$9!#\e(B
+
+\e$B$3$NJQ?t$O4X?t$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"4X?t\e(B
+\e$B$O\e(B @code{Message-ID} \e$B$r0z?t$H$7$F!"Ev$N%a%C%;!<%8$KHO0O$r69$a$i$l$?%P%C\e(B
+\e$B%U%!$+$i8F$P$l$^$9!#$3$N4X?t$O\e(B @code{nil}, @code{warn}, @code{delete} \e$B$N\e(B
+\e$B$I$l$+$rJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$BJQ?t$r\e(B @code{nil} \e$B$K@_Dj$9$k;v$K$h$C$F!"$3$N5!G=$r40A4$K;H$o$J$$$h$&$K$9\e(B
+\e$B$k;v$,$G$-$^$9!#\e(B
+
+\e$B$b$7A4$F$N=EJ#%a!<%k$rFCJL$J\e(B @dfn{duplicate} \e$B%0%k!<%W$KF~$l$?$$$N$G$"$l\e(B
+\e$B$P!"IaDL$N%a!<%kJ,3dJ}K!$r;H$C$F$=$l$r$9$k$3$H$,$G$-$^$9\e(B:
+
+@lisp
+(setq nnmail-split-fancy
+      '(| ;; @r{\e$B=EJ#%a%C%;!<%8$OJ,N%$5$l$?%0%k!<%W$X9T$-$^$9!#\e(B}
+        ("gnus-warning" "duplicat\\(e\\|ion\\) of message" "duplicate")
+        ;; @r{\e$B%G!<%b%s$d%]%9%H%^%9%?!<$d;w$?$h$&$J$b$N$+$i$N\e(B}
+        ;; @r{\e$B%a%C%;!<%8$OB>$N$H$3$m$X!#\e(B}
+        (any mail "mail.misc")
+        ;; @r{\e$BB>$NK!B'!#\e(B}
+        [ ... ] ))
+@end lisp
+
+\e$B$b$7$/$O<!$N$h$&$J$b$N\e(B:
+@lisp
+(setq nnmail-split-methods
+      '(("duplicates" "^Gnus-Warning:.*duplicate")
+        ;; @r{\e$BB>$NK!B'!#\e(B}
+        [...]))
+@end lisp
+
+\e$B$9$P$i$7$$5!G=$,$"$j$^$9\e(B: \e$B$b$7<u$1<j$,%a!<%k$r\e(B gnus \e$B$GFI$s$G$$$k;v$rCN$C\e(B
+\e$B$F$$$F!"\e(B@code{nnmail-treat-duplicates} \e$B$,\e(B @code{delete} \e$B$K@_Dj$7$F$"$k$H!"\e(B
+\e$B$"$J$?$NCN$C$F$$$k!"$=$N?M$,4{$K<u$1<h$C$?%a!<%k$N\e(B @code{Message-ID} \e$B$r\e(B
+\e$B;H$C$F!"9M$($k8B$j$?$/$5$s$NIn?+$rAw$k;v$,$G$-$^$9!#$=$N3Z$7$5$r9M$($F$_\e(B
+\e$B$F$/$@$5$$\e(B! \e$B$=$N?M$O$=$l$i$r7h$7$F$_$k;v$O$"$j$^$;$s\e(B! \e$B$o$)\e(B!
+
+@node Not Reading Mail
+@subsection \e$B%a!<%k$rFI$`$N$G$O$J$$\e(B
+
+\e$B%a!<%k%P%C%/%(%s%I$r;H$$;O$a$k$H!"$=$l$i$K$O$"$J$?$,$=$l$i$G%a!<%k$rFI$_\e(B
+\e$B$?$$$H;W$C$F$$$k$H2>Dj$9$k$H$$$&$&$k$5$$JJ$,$"$j$^$9!#$3$l$O$b$C$H$b$G$J\e(B
+\e$B$$;v$G$O$J$$$+$b$7$l$^$;$s$,!"$"$J$?$NK>$`;v$G$O$J$$$+$b$7$l$^$;$s!#\e(B
+
+\e$B$b$7\e(B @code{mail-sources} \e$B$H\e(B @code{nnmail-spool-file} \e$B$r\e(B @code{nil} \e$B$K@_\e(B
+\e$BDj$9$k$H!"$I$N%P%C%/%(%s%I$bF~$C$F$/$k%a!<%k$rFI$b$&$H;n$_$k;v$O$J$/!"K>\e(B
+\e$B$`;v$N<j=u$1$K$J$k$G$7$g$&!#\e(B
+
+@vindex nnbabyl-get-new-mail
+@vindex nnmbox-get-new-mail
+@vindex nnml-get-new-mail
+@vindex nnmh-get-new-mail
+@vindex nnfolder-get-new-mail
+\e$BNc$($P!"\e(B@code{nnml} \e$B$G%a!<%k$rFI$`;v$KHs>o$KK~B-$7$F$$$F!"8E\e(B
+\e$B$$\e(B Rmail \e$B%U%!%$%k$,\e(B @code{nnbabyl} \e$B$G1#$5$l$F$$$k$N$r$5$C$H8+$?$$$@$1$J\e(B
+\e$B$i!"$3$l$OM>J,$G$7$g$&!#$9$Y$F$N%P%C%/%(%s%I$O\e(B \e$B%P%C%/%(%s%I\e(B-
+@code{get-new-mail} \e$B$H$$$&JQ?t$r;}$C$F$$$^$9!#$b$7\e(B @code{nnbabyl} \e$B$N%a!<\e(B
+\e$B%kFI$_9~$_$r;HMQIT2D$K$7$?$$$N$G$"$l$P!"%0%k!<%W$N;v<B>e$N%5!<%P!<\e(B
+\e$B$r\e(B @code{nnbabyl-get-new-mail} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$h$&$KJT=8$7$^$9!#\e(B
+
+\e$BA4$F$N%a!<%k%P%C%/%(%s%I$OF~$C$F$/$k%a!<%k$rFI$_9~$`$H$-$K!"J]B8$5$l$k$Y\e(B
+\e$B$-5-;v$KHO0O$r69$a$F\e(B @code{nn}*@code{-prepare-save-mail-hook} \e$B$r8F$S$^$9!#\e(B
+
+@node Choosing a Mail Back End
+@subsection \e$B%a!<%k%P%C%/%(%s%I$rA*$V\e(B
+
+Gnus \e$B$O%a!<%k%0%k!<%W$rF0:n$9$k$h$&$K$9$k$H%a!<%k%9%W!<%k$rFI$_9~$_$^$9!#\e(B
+\e$B%a!<%k%U%!%$%k$O$^$:$"$J$?$N%[!<%`%G%#%l%/%H%j!<$KJ#<L$5$l$^$9!#$=$N8e$K\e(B
+\e$B2?$,5/$3$k$+$O%a!<%k$r$I$NMM<0$GN/$a$?$$$+$K$h$C$FJQ$o$j$^$9!#\e(B
+
+\e$BI8=`$N\e(B gnus \e$B$G$OO;$D$N0c$C$?%a!<%k%P%C%/%(%s%I$,$"$j!"8DJL$K$5$i$J$k%P%C\e(B
+\e$B%/%(%s%I$r;HMQ2DG=$G$9!#$[$H$s$I$N?M$,;H$&%a!<%k%P%C%/%(%s%I$O\e(B (\e$B$=$l$,$?\e(B
+\e$B$V$s:GB.$@$+$i\e(B) @code{nnml} \e$B$G$9\e(B (@pxref{Mail Spool})\e$B!#\e(B
+
+@menu
+* Unix Mail Box::               (\e$B$H$F$b\e(B) \e$BI8=`E*$J\e(B Un*x mbox \e$B$r;H$&\e(B
+* Rmail Babyl::                 Emacs \e$B$N%W%m%0%i%`$O\e(B Rmail \e$B$N\e(B Babyl \e$B%U%)!<%^%C%H$r;H$&\e(B
+* Mail Spool::                  \e$B$"$J$?$N%a!<%k$r;dE*$J%9%W!<%k$KN/$a$k\e(B?
+* MH Spool::                    mhspool \e$B$N$h$&$J%P%C%/%(%s%I\e(B
+* Maildir::                     \e$B$b$&0l$D$N#1%U%!%$%k\e(B/\e$B#1%a%C%;!<%87A<0\e(B
+* Mail Folders::                \e$B$=$l$>$l$N%0%k!<%W$KBP$7$F0l$D$N%U%!%$%k$r;}$D\e(B
+* Comparing Mail Back Ends::    \e$BF@<:$N?<$$F6;!\e(B
+@end menu
+
+@node Unix Mail Box
+@subsubsection Unix \e$B%a!<%k%\%C%/%9\e(B
+@cindex nnmbox
+@cindex unix mail box
+
+@vindex nnmbox-active-file
+@vindex nnmbox-mbox-file
+@dfn{nnmbox} \e$B%P%C%/%(%s%I$O%a!<%k$rC_B"$9$k$?$a$KI8=`$N\e(B Un*x mbox \e$B%U%!%$\e(B
+\e$B%k$rMQ$$$^$9!#\e(B@code{nnmbox} \e$B$O$=$l$>$l$N%a!<%k5-;v$K$=$l$,$I$N%0%k!<%W$K\e(B
+\e$BB0$7$F$$$k$+$r<($9DI2C$N%X%C%@!<$r2C$($^$9!#\e(B
+
+\e$B;v<B>e$N%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item nnmbox-mbox-file
+@vindex nnmbox-mbox-file
+\e$BMxMQ<T$N%[!<%`%G%#%l%/%H%j!<$N%a!<%k%\%C%/%9$NL>A0!#4{DjCM\e(B
+\e$B$O\e(B @file{~/mbox} \e$B$G$9!#\e(B
+
+@item nnmbox-activate-file
+@vindex nnmbox-active-file
+\e$B%a!<%k%\%C%/%9$N%"%/%F%#%V%U%!%$%k$NL>A0!#4{DjCM\e(B
+\e$B$O\e(B @file{~/.mbox-active} \e$B$G$9!#\e(B
+
+@item nnmbox-get-new-mail
+@vindex nnmbox-get-new-mail
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnmbox} \e$B$OF~$C$FMh$?%a!<%k$rFI$_9~$s$G%0%k!<\e(B
+\e$B%W$KJ,3d$7$^$9!#4{DjCM$O\e(B @code{t} \e$B$G$9!#\e(B
+@end table
+
+@node Rmail Babyl
+@subsubsection Rmail Babyl
+@cindex nnbabyl
+@cindex Rmail mbox
+
+@vindex nnbabyl-active-file
+@vindex nnbabyl-mbox-file
+@dfn{nnbabyl} \e$B%P%C%/%(%s%I$O%a!<%k$rC_B"$9$k$?$a$K\e(B Babyl \e$B%a!<%k%\%C%/\e(B
+\e$B%9\e(B (\e$BJLL>\e(B @dfn{Rmail mbox}) \e$B$r;H$$$^$9!#\e(B@code{nnbabyl} \e$B$O$=$l$>$l$N5-;v$K\e(B
+\e$B$=$l$,$I$N%0%k!<%W$KB0$7$F$$$k$+$r<($9DI2C$N%X%C%@!<$r2C$($^$9!#\e(B
+
+\e$B;v<B>e$N%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item nnbabyl-mbox-file
+@vindex nnbabyl-mbox-file
+Rmail mbox \e$B%U%!%$%k$NL>A0!#4{DjCM$O\e(B @file{~/RMAIL} \e$B$G$9!#\e(B
+
+@item nnbabyl-active-file
+@vindex nnbabyl-active-file
+rmail box \e$B$N$?$a$N%"%/%F%#%V%U%!%$%k$NL>A0!#4{DjCM\e(B
+\e$B$O\e(B @file{~/.rmail-active} \e$B$G$9!#\e(B
+
+@item nnbabyl-get-new-mail
+@vindex nnbabyl-get-new-mail
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnbabyl} \e$B$OF~$C$F$/$k%a!<%k$rFI$_9~$_$^$9!#\e(B
+\e$B4{DjCM$O\e(B @code{t} \e$B$G$9!#\e(B
+@end table
+
+@node Mail Spool
+@subsubsection \e$B%a!<%k%9%W!<%k\e(B
+@cindex nnml
+@cindex mail @acronym{NOV} spool
+
+@dfn{nnml} \e$B%9%W!<%k%a!<%kMM<0$OB>$NCN$i$l$?MM<0$H$O8_49@-$,$"$j$^$;$s!#\e(B
+\e$B$=$l$O>/$7Cm0U$7$F;H$o$l$k$Y$-$G$9!#\e(B
+
+@vindex nnml-directory
+\e$B$b$7$3$N%P%C%/%(%s%I$r;H$&$H!"\e(Bgnus \e$B$OF~$C$F$/$k%a!<%k$r!"$=$l$>$l$N%a!<\e(B
+\e$B%k$r\e(B 1 \e$B%U%!%$%k$H$7$F%U%!%$%k$KJ,3d$7!"5-;v$rJQ\e(B
+\e$B?t\e(B @code{nnml-directory} \e$B$G;XDj$5$l$?%G%#%l%/%H%j!<$N2<$NBP1~$9$k%G%#%l\e(B
+\e$B%/%H%j!<$KF~$l$^$9!#%G%#%U%)%k%H$NCM$O\e(B @file{~/Mail/} \e$B$G$9!#\e(B
+
+\e$BA0$b$C$F%G%#%l%/%H%j!<$r:n$C$F$*$/I,MW$O$"$j$^$;$s!#$=$l$NLLE]$O\e(B gnus \e$B$,\e(B
+\e$B8+$F$/$l$^$9!#\e(B
+
+\e$B$b$7$"$J$?$N%"%+%&%s%H$KC_@Q$G$-$k%U%!%$%k$N?t$K87L)$J@)8B$,$"$k$J$i!"$3\e(B
+\e$B$N%P%C%/%(%s%I$r;H$&$Y$-$G$O$"$j$^$;$s!#$=$l$>$l$N%a!<%k$O$=$l<+?H$N%U%!\e(B
+\e$B%$%k$rF@$^$9$N$G!"?t=54V$G$?$/$5$s$N\e(B i\e$B%N!<%I$r@jM-$9$k2DG=@-$O==J,$K$"$j\e(B
+\e$B$^$9!#JL$K$3$l$,LdBj$G$J$/!"?F@Z$J%7%9%F%`4IM}<T$,!"5$$,68$C$?$h$&\e(B
+\e$B$K\e(B ``\e$BC/$,;d$N\e(B i\e$B%N!<%I$r?)$$$D$V$7$F$$$k$s$@\e(B? \e$BC/$@\e(B? \e$BC/\e(B!?'' \e$B$H6+$S$J$,$iJb\e(B
+\e$B$-2s$k;v$,LdBj$G$J$$$J$i!"$3$l$,$*$=$i$/;H$&;v$N$G$-$k0lHVB.$$MM<0$G$"$k\e(B
+\e$B$H$$$&$3$H$OCN$C$F$*$/$Y$-$G$7$g$&!#?7$7$$%a!<%k$rFI$`$?$a$@$1$KBg$-\e(B
+\e$B$J\e(B mbox \e$B%U%!%$%k$r=E$$B-<h$j$GC5$9I,MW$O$"$j$^$;$s!#\e(B
+
+@code{nnml} \e$B$O5-;vJ,3d$K4X$7$F$O$*$=$i$/0lHVCY$$%P%C%/%(%s%I$G$7$g$&!#$=\e(B
+\e$B$l$OB?$/$N%U%!%$%k$r:n$i$J$1$l$P$J$i$:!"$=$l$OF~$C$F$/$k%a!<%k$N$?$a\e(B
+\e$B$N\e(B @acronym{NOV} \e$B%G!<%?%Y!<%9$b:n@.$7$J$1$l$P$J$j$^$;$s!#$3$l$N$?$a$K!"\e(B
+\e$B%a!<%k$rFI$`;v$K4X$7$F$O$?$V$s:GB.$N%P%C%/%(%s%I$K$J$j$^$9!#\e(B
+
+@cindex self contained nnml servers
+@cindex marks
+\e$B0u%U%!%$%k\e(B (\e$BLuCm\e(B: marks file) \e$B$,;H$o$l$k$H\e(B (\e$B$=$l$,%G%#%U%)%k%H$G$9$,\e(B)\e$B!"\e(B
+@code{nnml} \e$B%5!<%P!<$O\e(B @code{tar} \e$B$J$I$r;H$C$F%P%C%/%"%C%W$7$?$j!"8e$G$"\e(B
+\e$B$J$?$,IU$1$?0u$,$9$Y$FJ]$?$l$?>uBV$G\e(B gnus \e$B$KLa$9\e(B (\e$BK\Mh$N\e(B @code{nnml} \e$B%5!<\e(B
+\e$B%P!<$K$h$C$FDI2C$9$k\e(B) \e$B$3$H$,$G$-$kFC<A$r;}$D$h$&$K$J$j$^$9!#%0%k!<%W$N0u\e(B
+\e$B$O$=$l$>$l$N\e(B @code{nnml} \e$B%0%k!<%W$N%G%#%l%/%H%jFb$N!"DL\e(B
+\e$B>o\e(B @file{.marks} \e$B%U%!%$%k\e(B (@code{nnml-marks-file-name} \e$B$r;2>H\e(B) \e$B$K3JG<$5\e(B
+\e$B$l$^$9!#$^$?!"8D!9$N\e(B @code{nnml} \e$B%0%k!<%W$K$D$$$F$b%P%C%/%"%C%W$9$k$3$H\e(B
+\e$B$,2DG=$G!"\e(B(\e$B%P%C%/%"%C%W$r\e(B nnml \e$B%G%#%l%/%$%H%j$KLa$7$?8e$G\e(B) @kbd{G m} \e$B%-!<\e(B
+\e$B$r;H$C$F$=$N%0%k!<%W$r85$KLa$7$^$9!#\e(B
+
+\e$B$b$72?$i$+$NM}M3$K$h$C$F\e(B @file{.marks} \e$B%U%!%$%k$,$*$+$7$/$J$C$F$$$k$H;W$C\e(B
+\e$B$?$H$-$O!"C1$K$=$l$iA4It$r>C$7$F$7$^$&$3$H$,$G$-$^$9!#\e(Bgnus \e$B$O<!2s5/F0$9\e(B
+\e$B$k$H$-$K!"$=$l$i$r@5$7$/:F:n@.$9$k$G$7$g$&!#\e(B
+
+\e$B;v<B>e$N%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item nnml-directory
+@vindex nnml-directory
+\e$BA4$F$N\e(B @code{nnml} \e$B%G%#%l%/%H%j!<$O$3$N%G%#%l%/%H%j!<$N2<$KCV$+$l$^$9!#\e(B
+\e$B4{DjCM$O\e(B @code{message-directory} \e$B$NCM\e(B (\e$B$=$N4{DjCM$O\e(B @file{~/Mail}) \e$B$G$9!#\e(B
+
+@item nnml-active-file
+@vindex nnml-active-file
+@code{nnml} \e$B%5!<%P!<$N$?$a$N%"%/%F%#%V%U%!%$%k!#4{DjCM\e(B
+\e$B$O\e(B @file{~/Mail/active} \e$B$G$9!#\e(B
+
+@item nnml-newsgroups-file
+@vindex nnml-newgroups-file
+@code{nnml} \e$B%0%k!<%W5-=R%U%!%$%k!#\e(B@xref{Newsgroups File Format}. \e$B4{DjCM\e(B
+\e$B$O\e(B @file{~/Mail/newsgroups} \e$B$G$9!#\e(B
+
+@item nnml-get-new-mail
+@vindex nnml-get-new-mail
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnml} \e$B$OF~$C$FMh$?%a!<%kFI$_9~$_$^$9!#4{Dj\e(B
+\e$BCM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item nnml-nov-is-evil
+@vindex nnml-nov-is-evil
+@code{nil} \e$B$G$J$1$l$P!"$3$N%P%C%/%(%s%I$O$I$N\e(B @acronym{NOV} \e$B%U%!%$%k$bL5\e(B
+\e$B;k$7$^$9!#4{DjCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item nnml-nov-file-name
+@vindex nnml-nov-file-name
+@acronym{NOV} \e$B%U%!%$%k$NL>A0!#%G%#%U%)%k%H$O\e(B @file{.overview} \e$B$G$9!#\e(B
+
+@item nnml-prepare-save-mail-hook
+@vindex nnml-prepare-save-mail-hook
+\e$BJ]B8$9$kA0$K5-;v$KHO0O$r69$a$F<B9T$9$k%U%C%/$G$9!#\e(B
+
+@item nnml-marks-is-evil
+@vindex nnml-marks-is-evil
+\e$BHs\e(B@code{nil} \e$B$G$"$k$H!"$3$N%P%C%/%(%s%I$O$$$+$J$k\e(B @sc{\e$B0u\e(B} \e$B%U%!%$%k$bL5;k\e(B
+\e$B$7$^$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item nnml-marks-file-name
+@vindex nnml-marks-file-name
+@dfn{\e$B0u\e(B} \e$B%U%!%$%k$NL>A0$G$9!#%G%#%U%)%k%H$O\e(B @file{.marks} \e$B$G$9!#\e(B
+
+@item nnml-use-compressed-files
+@vindex nnml-use-compressed-files
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i\e(B @code{nnml} \e$B$O05=L$5$l$?%a%C%;!<%8%U%!%$%k$r;H$&\e(B
+\e$B$3$H$r9MN8$KF~$l$^$9!#\e(B
+@end table
+
+@findex nnml-generate-nov-databases
+@code{nnml} \e$B%0%k!<%W$H\e(B @acronym{NOV} \e$B%U%!%$%k$,40A4$KNI$$>uBV$G$J$/$J$C\e(B
+\e$B$F$7$^$C$?$J$i!"\e(B@kbd{M-x nnml-generate-nov-databases} \e$B$HBG$D;v$K$h$C$F!"\e(B
+\e$B40A4$K99?7$9$k;v$,$G$-$^$9!#$3$NL?Na$O!"$=$l$>$lA4$F$N%U%!%$%k$r8+$k;v$K\e(B
+\e$B$h$C$F\e(B @code{nnml} \e$B3,AXA4BN$r%H%m!<%k5{LV$G$5$i$$$^$9$N$G!"$=$l$,=*$o$k\e(B
+\e$B$^$G$K$O;~4V$,$+$+$k$+$b$7$l$^$;$s!#$3$N5!G=$X$N$h$jNI$$%$%s%?!<%U%'!<%9\e(B
+\e$B$O%5!<%P!<%P%C%U%!$G8+$D$+$k$G$7$g$&\e(B (@pxref{Server Commands})\e$B!#\e(B
+
+@node MH Spool
+@subsubsection MH \e$B%9%W!<%k\e(B
+@cindex nnmh
+@cindex mh-e mail spool
+
+@code{nnmh} \e$B$O!"\e(B@acronym{NOV} \e$B%G!<%?%Y!<%9$r:n$i$J$$$3$H$H%"%/%F%#%V%U%!\e(B
+\e$B%$%k$d0u%U%!%$%k$rJ];}$7$J$$;v$r=|$$$F!"\e(B@code{nnml} \e$B$H;w$F$$$^$9!#$=$N$3\e(B
+\e$B$H$O\e(B @code{nnmh} \e$B$r\e(B @code{nnml} \e$B$h$j\e(B @emph{\e$B$+$J$j\e(B} \e$BCY$$%P%C%/%(%s%I$K$7\e(B
+\e$B$F$$$^$9$,!"$=$l$O\e(B procmail \e$B$N%9%/%j%W%H$r=q$/$?$a$K$:$C$H$d$j$d$9$/$J$C\e(B
+\e$B$F$b$$$^$9!#\e(B
+
+\e$B;v<B>e$N%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item nnmh-directory
+@vindex nnmh-directory
+\e$BA4$F$N\e(B @code{nnmh} \e$B%G%#%l%/%H%j!<$O$3$N%G%#%l%/%H%j!<$N2<$KCV$+$l$^$9!#\e(B
+\e$B4{DjCM$O\e(B @code{message-directory} \e$B$NCM\e(B (\e$B$=$N4{DjCM$O\e(B @file{~/Mail}) \e$B$G$9!#\e(B
+
+@item nnmh-get-new-mail
+@vindex nnmh-get-new-mail
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnmh} \e$B$OF~$C$F$/$k%a!<%k$rFI$_9~$_$^$9!#4{\e(B
+\e$BDjCM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item nnmh-be-safe
+@vindex nnmh-be-safe
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnmh} \e$B$O%U%)%k%@!<$K$"$k5-;v$,<B:]\e(B
+\e$B$K\e(B gnus \e$B$,9M$($F$$$k$b$N$HF1$8$G$"$k$+$rD4$Y$k$H$$$&GO</$2$?;v$r$d$j$^$9!#\e(B
+\e$B$=$l$OF|IU$HL\$KF~$kA4$F$N>pJs$rD4$Y$^$9$N$G!"$3$l$r\e(B @code{t} \e$B$K@_Dj$9$k\e(B
+\e$B;v$O?<9o$JB.EYDc2<$,5/$3$k$H$$$&;v$G$9!#$b$7\e(B @code{nnmh} \e$B5-;v$rFI$`$N\e(B
+\e$B$K\e(B gnus \e$B0J30$N$b$N$r;H$C$F$$$J$$$N$G$"$l$P!"$3$NJQ?t$r\e(B @code{t} \e$B$K@_Dj$9\e(B
+\e$B$kI,MW$O$"$j$^$;$s!#4{DjCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+@end table
+
+@node Maildir
+@subsubsection Maildir
+@cindex nnmaildir
+@cindex maildir
+
+@code{nnmaildir} \e$B$O\e(B Gnus \e$B$N%0%k!<%W$KBP1~$7$?3F!9\e(B
+\e$B$N\e(B maildir \e$B$K\e(B maildir \e$B%U%)!<%^%C%H$G%a!<%k$r3JG<$7$^$9!#$3$N%U%)!<%^%C\e(B
+\e$B%H$O\e(B @uref{http://cr.yp.to/proto/maildir.html} \e$B$*$h\e(B
+\e$B$S\e(B @uref{http://www.qmail.org/man/man5/maildir.html} \e$B$GJ8=q2=$5$l$F$$$^\e(B
+\e$B$9!#$^$?\e(B @code{nnmaildir} \e$B$O\e(B maildir \e$B$NCf$N\e(B @file{.nnmaildir/} \e$B%G%#%l%/\e(B
+\e$B%H%j$KFCJL$J>pJs$r3JG<$7$^$9!#\e(B
+
+Maildir \e$B%U%)!<%^%C%H$O%m%C%/$rI,MW$H$7$J$$F1;~G[Aw$H9VFI$r2DG=$K$9$k$?$a\e(B
+\e$B$K@_7W$5$l$^$7$?!#B>$N%P%C%/%(%s%I$G$O!"%a!<%k$r2?$i$+$N%9%W!<%k$KEO$7$F\e(B
+\e$B$=$N%9%W!<%k$+$i%0%k!<%W$KJ,3d$9$k$?$a$K\e(B Gnus \e$B$r@_Dj$7$J$1$l$P$J$i$J$$$G\e(B
+\e$B$7$g$&!#$=$l$O:#$^$GDL$j\e(B @code{nnmaildir} \e$B$G9T$J$&$3$H$,$G$-$^$9$,!"$b$C\e(B
+\e$B$H0lHLE*$J@_Dj$O\e(B Gnus \e$B$N%0%k!<%W$H$7$F8=$o$l$k\e(B maildir \e$B$K%a!<%k$rD>@\G[\e(B
+\e$BAw$9$k$3$H$G$9!#\e(B
+
+@code{nnmaildir} \e$B$O40A4$K?.Mj$G$-$k$3$H$rL\;X$7$F$$$^$9\e(B: @kbd{C-g} \e$B$O%a\e(B
+\e$B%b%j!<Cf$N%G!<%?$r2u$7$^$;$s$7!"\e(B@code{SIGKILL} \e$B$,%U%!%$%k$NCf$N%G!<%?$r\e(B
+\e$B2u$9$3$H$O$"$j$^$;$s!#\e(B
+
+@code{nnmaildir} \e$B$O5-;v$N0u$H\e(B @acronym{NOV} \e$B%G!<%?$r$=$l$>$l$N\e(B maildir
+\e$B$K3JG<$7$^$9!#$=$l$K$h$C$F!"$"$k\e(B Gnus \e$B$N4D6-$+$iJL$N>l=j$K\e(B maildir \e$BA4BN\e(B
+\e$B$r%3%T!<$9$k$3$H$,$G$-!"0u$OJ]B8$5$l$^$9!#\e(B
+
+\e$B2>A[%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item directory
+\e$B$=$l$>$l$N\e(B @code{nnmaildir} \e$B%5!<%P!<\e(B (\e$B0l$D$r1[$($k%5!<%P!<$,I,MW$@$H$O$H\e(B
+\e$B$F$b;W$($^$;$s$,\e(B) \e$B$KBP$7$F%G%#%l%/%H%j$r:n$j!"$=$l$r\e(B maildir \e$B$^$?\e(B
+\e$B$O\e(B maildir \e$B$X$N%7%s%\%j%C%/%j%s%/$H$7$F<BAu$9$kI,MW$,$"$j$^$9\e(B (\e$BB>$NL\E*\e(B
+\e$B$N$?$a$K$9$G$K;H$o$l$F$$$k%G%#%l%/%H%j$rA*$s$G$O$$$1$^$;$s\e(B)\e$B!#$=$l$>$l\e(B
+\e$B$N\e(B maildir \e$B$O!"$=$N%5!<%P!<$N%K%e!<%9%0%k!<%W$H$7$F\e(B Gnus \e$B$K8=$l!"%7%s%\\e(B
+\e$B%j%C%/%j%s%/$N%U%!%$%kL>$,$=$N%0%k!<%W$NL>A0$K$J$j$^$9!#%G%#%l%/%H%j$K$"\e(B
+\e$B$k\e(B @samp{.} \e$B$G;O$^$k$I$s$J%U%!%$%kL>$bL5;k$5$l$^$9!#%G%#%l%/%H%j$O:G=i\e(B
+\e$B$K\e(B Gnus \e$B$r5/F0$7$?$H$-$H%0%k!<%W%P%C%U%!$G\e(B @kbd{g} \e$B$r%?%$%W$7$?$H$-$O$$\e(B
+\e$B$D$G$bAv::$5$l!"$I$l$+$N\e(B maildir \e$B$,:o=|$^$?$ODI2C$5$l$?$H$-\e(B
+\e$B$K\e(B @code{nnmaildir} \e$B$ODLCN$7$^$9!#\e(B
+
+@code{directory} \e$B%Q%i%a!<%?$NCM$O\e(B Lisp \e$B<0$G$J$1$l$P$J$j$^$;$s!#\e(B
+@code{eval} \e$B$G=hM}$5$l$?8e$G!"\e(B@code{expand-file-name} \e$B$K$h$C$F$3$N%5!<%P!<\e(B
+\e$B$N$?$a$N%G%#%l%/%H%j$N%Q%9$r3MF@$7$^$9!#$=$N7k2LF@$i$l$?J8;zNs$,!"%5!<%P!<\e(B
+\e$B$,JD$8$i$l$k$^$G;H$o$l$^$9\e(B (\e$B$b$7!"<0$d\e(B @code{eval} \e$B$rCN$i$J$/$G$b?4G[$4\e(B
+\e$BL5MQ\e(B; \e$BC1$J$kJ8;zNs$GF0:n$7$^$9\e(B)\e$B!#$3$N%Q%i%a!<%?$OG$0U$G$O$J$/!"@_Dj$7$J\e(B
+\e$B$1$l$P$J$j$^$;$s!#\e(B@code{"~/Mail"} \e$B$d$=$l$N%5%V%G%#%l%/%H%j$r;H$&$3$H$O?d\e(B
+\e$B>)$G$-$^$;$s!#$$$/$D$+$N\e(B Gnus \e$B$NB>$NItJ,$,$=$l$r%G%#%U%)%k%H$G$$$m$s$J$b\e(B
+\e$B$N$K;H$&$N$G!"\e(B@code{nnmaildir} \e$B$G$b$=$l$r;H$&$H:.Mp$9$k$+$b$7$l$^$;$s!#\e(B
+@code{"~/.nnmaildir"} \e$B$,0lHLE*$JCM$G$9!#\e(B
+
+@item target-prefix
+\e$B$3$l$O\e(B Lisp \e$B<0$G$J$1$l$P$J$j$^$;$s!#\e(B@code{eval} \e$B$G=hM}$5$l$?8e$G!"\e(B
+@code{expand-file-name} \e$B$K$h$C$F?7$7$$\e(B maildir \e$B$,@8@.$5$l$k%G%#%l%/%H%j\e(B
+\e$B$NL>A0$r3MF@$7$^$9!#<0$O%5!<%P!<$,3+DL$7$?$H$-$@$1\e(B @code{eval} \e$B$5$l!"$=\e(B
+\e$B$N7k2LF@$i$l$?J8;zNs$,!"%5!<%P!<$,JD$8$i$l$k$^$G;H$o$l$^$9!#\e(B
+
+@code{nnmaildir} \e$B%5!<%P!<$K%0%k!<%W$r:n$k$H!"$=$NL>A0$NF,\e(B
+\e$B$K\e(B @code{target-prefix} \e$B$,IU2C$5$l$?\e(B maildir \e$B$H!"$=$N\e(B maildir \e$B$r;X$7<($9\e(B
+\e$B%7%s%\%j%C%/%j%s%/$,AG$N%0%k!<%WL>$NL>A0$G:n@.$5$l$^$9!#$7$?$,$C$F!"\e(B
+@code{directory} \e$B$,\e(B @code{"~/.nnmaildir"} \e$B$G!"\e(B
+@code{target-prefix} \e$B$,\e(B @code{"../maildirs/"} \e$B$@$C$?>l9g$K\e(B @code{foo} \e$B$H\e(B
+\e$B$$$&%0%k!<%W$r:n$k$H!"\e(B@code{nnmaildir} \e$B$O\e(B maildir \e$B$H$7\e(B
+\e$B$F\e(B @file{~/.nnmaildir/../maildirs/foo} \e$B$r!"\e(B@file{../maildirs/foo} \e$B$X$N%7\e(B
+\e$B%s%\%j%C%/%j%s%/$H$7$F\e(B @file{~/.nnmaildir/foo} \e$B$r:n@.$7$^$9!#\e(B
+
+\e$BF1$8\e(B @code{directory} \e$B$K\e(B maildirs \e$B$H%7%s%\%j%C%/%j%s%/$NN>J}$r:n@.$9$k$?\e(B
+\e$B$a$K!"%9%i%C%7%e$r4^$^$J$$J8;zNs$r\e(B @code{target-prefix} \e$B$K@_Dj$9$k$3$H$,\e(B
+\e$B$G$-$^$9!#$3$N>l9g$O!"L>A0$,\e(B @code{target-prefix} \e$B$G;O$^\e(B
+\e$B$k\e(B @code{directory} \e$B$G8+$D$+$k$I$N\e(B maildir \e$B$b!"%0%k!<%W$H$O8+$J$5$l$^$;\e(B
+\e$B$s\e(B (\e$B$,!"$=$l$i$r;X$7<($9%7%s%\%j%C%/%j%s%/$,%0%k!<%W$K$J$j$^$9\e(B)\e$B!#\e(B
+
+\e$BFCJL$J>l9g$H$7$F\e(B @code{target-prefix} \e$B$,\e(B @code{""} (\e$B%G%#%U%)%k%H\e(B) \e$B$@$C$?\e(B
+\e$B$i!"%0%k!<%W$r:n$k$H$-$K!"\e(B@code{directory} \e$B$K$*$$$FBP1~$9$k%7%s%\%j%C%/\e(B
+\e$B%j%s%/$r;}$?$J$$\e(B maildir \e$B$,:n@.$5$l$^$9!#$=$N$h$&$J%0%k!<%W$KBP$7$F\e(B
+\e$B$O!"\e(B@code{force} \e$B0z?t$rM?$($J$$$H\e(B @code{gnus-group-delete-group} \e$B$,;H$(\e(B
+\e$B$J$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@item directory-files
+\e$B$3$l$O\e(B @code{directory-files} \e$B$HF1$8%$%s%?!<%U%'!<%9$N4X\e(B
+\e$B?t\e(B (\e$B$^$?$O\e(B @code{directory-files} \e$B$=$N$b$N\e(B) \e$B$G$J$1$l$P$J$j$^$;$s!#$3$l\e(B
+\e$B$O\e(B maildir \e$BMQ$N%5!<%P!<$N\e(B @code{directory} \e$B$rAv::$9$k$?$a$K;H$o$l$^$9!#\e(B
+\e$B$3$N%Q%i%a!<%?$OG$0U$G$9!#%G%#%U%)%k%HCM$O!"\e(B
+@code{nnheader-directory-files-is-safe} \e$B$,\e(B @code{nil} \e$B$@$C$?\e(B
+\e$B$i\e(B @code{nnheader-directory-files-safe} \e$B$G!"$=$l0J30$N>l9g\e(B
+\e$B$O\e(B @code{directory-files} \e$B$G\e(B
+\e$B$9\e(B (@code{nnheader-directory-files-is-safe} \e$B$O%5!<%P!<$,3+DL$7$?$H$-$K0l\e(B
+\e$B2s$@$18!::$5$l$^$9$,!"%G%#%l%/%H%j$,Av::$5$l$k$H$-$KKh2s%A%'%C%/$5$;$?$$\e(B
+\e$B$N$J$i$P!"$=$l$r9T$J$&4X?t$r$"$J$?$,<+A0$GMQ0U$9$kI,MW$,$"$j$^$9\e(B)\e$B!#\e(B
+
+@item get-new-mail
+\e$BHs\e(B-@code{nil} \e$B$K$7$F$*$/$H!"$$$D$b$NDL$j$K%0%k!<%W$N\e(B maildir \e$B<+BN$K$*$$\e(B
+\e$B$F?7Ce%a!<%k$rAv::$7$?8e$G!"$3$N%5!<%P!<\e(B
+\e$B$O\e(B @code{nnmail-split-methods} \e$B$+\e(B @code{nnmail-split-fancy} \e$B$K$h\e(B
+\e$B$k\e(B @code{mail-sources} \e$B$+$i!"=>Mh$N\e(B Gnus \e$B$NJ}K!$G%a!<%k$r<h$j9~$_$^$9!#\e(B
+\e$B%G%#%U%)%k%HCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@code{mail-sources} \e$B$H\e(B @code{nnmaildir} \e$B%0%k!<%W$NN>J}$GF1$8\e(B maildir \e$B$r\e(B
+\e$B;H$C$F$O\e(B @emph{\e$B$$$1$^$;$s\e(B}\e$B!#$=$N7k2L$O1?NI$/M-1W$K$J$k$+$b$7$l$^$;$s$,!"\e(B
+\e$B$=$s$J0U?^$G$O@_7W$5$l$F$$$^$;$s!#>-Mh$O0c$&7k2L$r$b$?$i$92DG=@-$,$"$j$^\e(B
+\e$B$9!#$"$J$?$NJ,3d5,B'$,?7$7$$%0%k!<%W$r:n$k$h$&$K$J$C$F$$$k>l9g$O!"\e(B
+@code{create-directory} \e$B%5!<%P!<%Q%i%a!<%?$rM?$($k$3$H$rK:$l$J$$$G2<$5$$!#\e(B
+@end table
+
+@subsubsection \e$B%0%k!<%W%Q%i%a!<%?\e(B
+
+@code{nnmaildir} \e$B$O$$$/$D$+$N%0%k!<%W%Q%i%a!<%?$r;H$$$^$9!#$3$l$i$N$9$Y\e(B
+\e$B$F$rL5;k$7$F$b0BA4$G$9!#%G%#%U%)%k%H$N\e(B @code{nnmaildir} \e$B$NF0:n$O!"B>$N%a!<\e(B
+\e$B%k%P%C%/%(%s%I$N%G%#%U%)%k%H\e(B (\e$B5-;v$,0l=54V8e$K>C5n$5$l$k!"$J$I\e(B) \e$B$HF1$8$G\e(B
+\e$B$9!#4|8B@Z$l>C5n$N%Q%i%a!<%?$r=|$$$F!"$3$N5!G=$O$9$Y\e(B
+\e$B$F\e(B @code{nnmaildir} \e$B$KFCM-$G$9!#$7$?$,$C$F!"JL$N%P%C%/%(%s%I$G$9$G$K9T$C\e(B
+\e$B$F$$$kF0:n$rC1$KF'=1$5$;$h$&$H$$$&$N$G$"$l$P!"$3$l$rL5;k$9$k$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+\e$B$3$l$i$N%Q%i%a!<%?$N$&$A$N$I$l$G$b!"$=$NCM$,%Y%/%H%k$G$"$k>l9g$O!"%*%j%8\e(B
+\e$B%J%k$NCM$KBe$o$C$F!"Bh0l$NMWAG$,\e(B Lisp \e$B<0$H$7$FI>2A$5$l$?7k2L$,;H$o$l$^$9!#\e(B
+\e$BCM$,%Y%/%H%k$G$J$$>l9g$O!"$=$NCM$=$N$b$N$,\e(B Lisp \e$B<0$H$7$FI>2A$5$l$^$9!#\e(B
+(\e$B$=$N$?$a!"$3$l$i$N%Q%i%a!<%?$OB>$H$O0c$&L>A0!"0c$&$1$l$I$b;w$?0UL#$r;}\e(B
+\e$B$DB>$N%P%C%/%(%s%I$G%5%]!<%H$5$l$F$$$kF1MM$N%Q%i%a!<%?!"$r;H$$$^$9!#\e(B)
+(\e$B?t!"J8;zNs!"\e(B@code{nil}\e$B!"$*$h$S\e(B @code{t} \e$B$K$D$$$F$O!"\e(B@code{eval} \e$B$N4XM?\e(B
+\e$B$r:F$SL5;k$9$k$3$H$,$G$-$^$9!#B>$NCM$K$D$$$F!"$=$l$,E,@Z$J>l9g$K$O!"M>J,\e(B
+\e$B$J%/%*!<%H$r;H$$!"$+$D%Y%/%H%k$GCM$rJq$`$3$H$rK:$l$J$$$G2<$5$$!#\e(B)
+
+@table @code
+@item expire-age
+\e$B5-;v$,>C5n$5$l$k$^$G$N<wL?$NIC?t$r@0?t$G!"$^$?$O%7%s%\%k\e(B @code{never} \e$B$G\e(B
+\e$B5-;v$,4|8B@Z$l>C5n$5$l$F$O$J$i$J$$$3$H$r;XDj$7$^$9!#$3$N%Q%i%a!<%?$,@_Dj\e(B
+\e$B$5$l$F$$$J$$$H!"$$$D$b$N\e(B @code{nnmail-expiry-wait}(@code{-function}) \e$BJQ\e(B
+\e$B?t\e(B (@code{expiry-wait}(@code{-function}) \e$B%0%k!<%W%Q%i%a!<%?$G>e=q$-$5$l\e(B
+\e$B$k\e(B) \e$B$r:G8e$N$h$j$I$3$m$K$7$^$9!#\e(B3\e$BF|$NCM$,M_$7$$$J$i$P!"\e(B@code{[(* 3 24 60
+60)]} \e$B$N$h$&$J$b$N$r;H$C$F2<$5$$!#\e(B@code{nnmaildir} \e$B$O<0$rI>2A$7$F!"$=$N\e(B
+\e$B7k2L$r;H$$$^$9!#5-;v$N<wL?$O5-;v%U%!%$%k$NJQ99;~9o$r4pE@$K7WB,$5$l$^$9!#\e(B
+\e$BDL>o$3$l$O5-;v$,G[Aw$5$l$?;~9o$HF1$8$G$9$,!"5-;v$NJT=8$O$=$l$r<c$/$7$^$9!#\e(B
+(\e$B4|8B@Z$l>C5n0J30$N\e(B) \e$B5-;v$N0\F0$b$^$?!"5-;v$r<c$/$7$F$7$^$&$G$7$g$&!#\e(B
+
+@item expire-group
+\e$B$3$l$,J8;zNs\e(B (@code{"backend+server.address.string:group.name"} \e$B$N$h$&$J\e(B
+\e$B40A4$J\e(B Gnus \e$B$N%0%k!<%WL>\e(B) \e$B$G!"$+$D$=$N%Q%i%a!<%?$,F1$8L>A0$N%0%k!<%W$KB0\e(B
+\e$B$5$J$$>l9g!"4|8B@Z$l>C5n$,9T$J$o$l$k:]$K!"5-;v$O>C5n$5$l$kA0$K;XDj$5$l$?\e(B
+\e$B%0%k!<%W$K0\F0$5$;$i$l$^$9!#\e(B@emph{\e$B$3$l$,\e(B @code{nnmaildir} \e$B%0%k!<%W$K@_Dj\e(B
+\e$B$5$l$k$H!"0\F0@h$N%0%k!<%W$K$*$$$F!"5-;v$,85$N%0%k!<%W$K$"$C$?$H$-$H$A$g\e(B
+\e$B$&$IF1$8$@$18E$/$J$j$^$9!#\e(B} \e$B$7$?$,$C$F!"0\F0@h$N%0%k!<%W$K$*$1\e(B
+\e$B$k\e(B @code{expire-age} \e$B$K$OCm0U$7$F2<$5$$!#$3$l$,%Q%i%a!<%?$,B0$9$k$N$HF1\e(B
+\e$B$8%0%k!<%W$NL>A0$K@_Dj$5$l$k$H!"5-;v$O$^$C$?$/4|8B@Z$l>C5n$5$l$^$;$s!#%Y\e(B
+\e$B%/%H%k<0$r;H$&$H!":G=i$NMWAG$,0l2s!"$=$l$>$l$N5-;v$K$D$$$FI>2A$5$l$^$9!#\e(B
+\e$B$7$?$,$C$F!"5-;v$r$I$3$KCV$/$+$r7h$a$k$?$a$K!"$=$N<0\e(B
+\e$B$O\e(B @code{nnmaildir-article-file-name} \e$B$J$I$K>H2q$9$k$3$H$,$G$-$^$9!#\e(B
+@emph{\e$B$3$N%Q%i%a!<%?$,@_Dj$5$l$F$$$J$$$H!"\e(B
+@code{nnmaildir} \e$B$O\e(B @code{expiry-target} \e$B%0%k!<%W%Q%i%a!<%?\e(B
+\e$B$d\e(B @code{nnmail-expiry-target} \e$BJQ?t$r8\$_$^$;$s!#\e(B}
+
+@item read-only
+\e$B$3$l$,\e(B @code{t} \e$B$K@_Dj$5$l$F$$$k$H!"\e(B@code{nnmaildir} \e$B$O$=$N5-;v$r$3$N%0\e(B
+\e$B%k!<%W$GFI$_=P$7@lMQ$H$7$F07$$$^$9!#$3$N0UL#$O!"5-;v$O\e(B @file{new/} \e$B$+\e(B
+\e$B$i\e(B @file{cur/} \e$B$K2~L>$5$l$J$$!"5-;v$O\e(B @file{cur/} \e$B$G$O$J\e(B
+\e$B$/\e(B @file{new/} \e$B$G$N$_8+$D$+$k!"5-;v$O>C5n$5$l$J$$!"5-;v$OJT=8$G$-$J$$!"\e(B
+\e$B$H$$$&$3$H$G$9!#\e(B@file{new/} \e$B$OB>$N\e(B maildir \e$B$N\e(B @file{new/} \e$B%G%#%l%/%H%j!"\e(B
+\e$BNc$($P$_$s$J$,6=L#$,$"$k%a!<%j%s%0%j%9%H$r4^$s$G$$$k%7%9%F%`$G6&DL$N%a!<\e(B
+\e$B%k%\%C%/%9!"$X$N%7%s%\%j%C%/%j%s%/$G$"$k$HA[Dj$5$l$^$9!#\e(B@file{new/} \e$B0J30\e(B
+\e$B$N\e(B maildir \e$B$K$"$k$9$Y$F$N$b$N$O!"FI$_=P$7@lMQ$H$7$F07$o$l\e(B @emph{\e$B$^$;$s\e(B}\e$B!#\e(B
+\e$B$7$?$,$C$F6&M-$N%a!<%k%\%C%/%9$KBP$7$F$O!"$"$J$?<+?H$N\e(B maildir \e$B$r@_Dj$9\e(B
+\e$B$k\e(B (\e$B$^$?$O\e(B \e$B6&M-$N%a!<%k%\%C%/%9$K=q$-9~$_8"8B$r;}$D\e(B) \e$BI,MW$,0MA3$H$7$F$"\e(B
+\e$B$j$^$9!#$"$J$?$N\e(B maildir \e$B$O5-;v$NM>J,$J%3%T!<$r$^$C$?$/4^$^$J$$$G$7$g$&!#\e(B
+
+@item directory-files
+@code{directory-files} \e$B$HF1$8%$%s%?!<%U%'!<%9$N4X?t$G$9!#5-;v$r8+$D$1$k\e(B
+\e$B$?$a$K!"$3$N%0%k!<%W$KBP1~$9$k\e(B maildir \e$B$N%G%#%l%/%H%j$rAv::$9$k$?$a$K;H\e(B
+\e$B$o$l$^$9!#%G%#%U%)%k%H$O%5!<%P!<$N\e(B @code{directory-files} \e$B%Q%i%a!<%?$G@_\e(B
+\e$BDj$5$l$F$$$k4X?t$G$9!#\e(B
+
+@item distrust-Lines:
+\e$BHs\e(B-@code{nil} \e$B$G$"$k$H!"\e(B@code{nnmaildir} \e$B$O\e(B @code{Lines:} \e$B%X%C%@!<%U%#!<\e(B
+\e$B%k%I$r;H$&Be$o$j$K$$$D$b5-;v$N9T?t$r?t$($^$9!#\e(B@code{nil} \e$B$@$C$?>l9g$O!"\e(B
+\e$B$"$l$P$=$N%X%C%@!<%U%#!<%k%I$,;H$o$l$^$9!#\e(B
+
+@item always-marks
+@code{['(read expire)]} \e$B$N$h$&$J0u%7%s%\%k$N%j%9%H$G$9!#\e(BGnus \e$B$,5-;v$N0u\e(B
+\e$B$r\e(B @code{nnmaildir} \e$B$K?R$M$k$H$-$O$$$D$G$b!"%U%!%$%k%7%9%F%`$K3JG<$5$l$F\e(B
+\e$B$$$k0u$,2?$G$"$k$+$H$OL54X78$K!"\e(B@code{nnmaildir} \e$B$O$9$Y$F$N5-;v$,$3$l$i\e(B
+\e$B$N0u$r;}$C$F$$$k$HEz$($^$9!#$3$l$O9=A[$r;n$9$?$a$N5!G=$G!"$*$=$i$/7k6I$O\e(B
+\e$B:o=|$5$l$k$G$7$g$&!#$=$l$O\e(B Gnus \e$BK\BN$G9T$o$l$k$+!"$"$k$$$OM-1W$G$J$1$l$P\e(B
+\e$BJ|4~$5$l$k$Y$-$G$9!#\e(B
+
+@item never-marks
+@code{['(tick expire)]} \e$B$N$h$&$J0u%7%s%\%k$N%j%9%H$G$9!#\e(BGnus \e$B$,5-;v$N0u\e(B
+\e$B$r\e(B @code{nnmaildir} \e$B$K?R$M$k$H$-$O$$$D$G$b!"%U%!%$%k%7%9%F%`$K3JG<$5$l$F\e(B
+\e$B$$$k0u$,2?$G$"$k$+$H$OL54X78$K!"\e(B@code{nnmaildir} \e$B$O$3$l$i$N0u$r;}$C$F$$\e(B
+\e$B$k5-;v$OL5$$$HEz$($^$9!#\e(B@code{never-marks} \e$B$O\e(B @code{always-marks} \e$B$r>e=q\e(B
+\e$B$-$7$^$9!#$3$l$O9=A[$r;n$9$?$a$N5!G=$G!"$*$=$i$/7k6I$O:o=|$5$l$k$G$7$g$&!#\e(B
+\e$B$=$l$O\e(B Gnus \e$BK\BN$G9T$o$l$k$+!"$"$k$$$OM-1W$G$J$1$l$PJ|4~$5$l$k$Y$-$G$9!#\e(B
+
+@item nov-cache-size
+@acronym{NOV} \e$B%a%b%j!<%-%c%C%7%e$N%5%$%:$r;XDj$9$k@0?t$G$9!#%9%T!<%I%"%C\e(B
+\e$B%W$N$?$a$K!"\e(B@code{nnmaildir} \e$B$O$=$l$>$l$N%0%k!<%W$N8BDj$5$l$??t$N5-;v$K\e(B
+\e$BBP$7$F!"%a%b%j!<>e$K\e(B @acronym{NOV} \e$B%G!<%?$rJ];}$7$^$9!#\e(B(\e$B$3$l$O$?$V$sM-MQ\e(B
+\e$B$G$O$J$/!">-Mh$O$*$=$i$/:o=|$5$l$k$G$7$g$&\e(B)\e$B!#$3$N%Q%i%a!<%?$NCM$O!"%5!<\e(B
+\e$B%P!<$,3+DL$7$?8e$G:G=i$K%0%k!<%W$,8+$i$l$?$H$-!"$9$J$o$A0lHL$K$O:G=i\e(B
+\e$B$K\e(B Gnus \e$B$r5/F0$7$?$H$-!"$@$1CmL\$5$l$^$9!#%5!<%P!<$,JD$8$i$l$F:F$S3+DL$5\e(B
+\e$B$l$k$^$G$O!"\e(B@acronym{NOV} \e$B%-%c%C%7%e$N%5%$%:$OJQ99$5$l$^$;$s!#%G%#%U%)%k\e(B
+\e$B%H$O35N,%P%C%U%!$KI=<($5$l$k5-;v$N?t$N8+@Q$j\e(B (@code{tick} \e$B0u$,$"$C\e(B
+\e$B$F\e(B @code{read} \e$B$,L5$$5-;v$N?t$K>/!9$NM>J,$r2C$($?$b$N\e(B) \e$B$G$9!#\e(B
+@end table
+
+@subsubsection \e$B5-;v$N<1JL\e(B
+\e$B5-;v$O$=$l$>$l$N\e(B maildir \e$B$N\e(B @file{cur/} \e$B%G%#%l%/%H%j$K3JG<$5$l$^$9!#3F!9\e(B
+\e$B$N5-;v$K$O\e(B @code{uniq:info} \e$B$N$h$&$JL>A0$,IU$1$i$l$^$9!#$3$3\e(B
+\e$B$G\e(B @code{uniq} \e$B$O%3%m%s$r4^$_$^$;$s!#\e(B@code{nnmaildir} \e$B$O\e(B @code{:info} \e$B$N\e(B
+\e$BItJ,$rJ];}$7$^$9$,L5;k$7$^$9!#\e(B(\e$BB>$N\e(B maildir \e$B%j!<%@!<$O0lHL$K0u$r3JG<$9$k\e(B
+\e$B$?$a$K$3$NItJ,$r;H$$$^$9!#\e(B) @code{uniq} \e$B$NItJ,$O5-;v$r%f%K!<%/$K<1JL$7!"\e(B
+maildir \e$B$N\e(B @file{.nnmaildir/} \e$B%5%V%G%#%l%/%H%j$N?'!9$J>l=j$K5-;v$K4XO"$7\e(B
+\e$B$?>pJs$r3JG<$9$k$?$a$K;H$o$l$^$9!#35N,%P%C%U%!$G5-;v$rMW5a$7$?8e$G!"5-;v\e(B
+\e$B$N40A4$J%Q%9L>$,\e(B @code{nnmaildir-article-file-name} \e$BJQ?t$+$iF@$i$l$^$9!#\e(B
+
+@subsubsection NOV \e$B%G!<%?\e(B
+@code{uniq} \e$B$K$h$C$F<1JL$5$l$k5-;v$O!"$=$N\e(B @acronym{NOV} \e$B%G!<%?\e(B (\e$B35N,%P%C\e(B
+\e$B%U%!$N9T$r@8@.$9$k$?$a$K;H$o$l$k\e(B) \e$B$r\e(B @file{.nnmaildir/nov/uniq} \e$B$K3JG<$7\e(B
+\e$B$^$9!#\e(B@code{nnmaildir-generate-nov-databases} \e$B4X?t$O$"$j$^$;$s!#\e(B(\e$B$=$NI,\e(B
+\e$BMW$O$"$^$j$"$j$^$;$s!#5-;v$N\e(B @acronym{NOV} \e$B%G!<%?$O5-;v\e(B
+\e$B$+\e(B @code{nnmail-extra-headers} \e$B$,JQ2=$7$?$H$-$K<+F0E*$K99?7$5$l$^\e(B
+\e$B$9!#\e(B) \e$BBP1~$9$k\e(B @acronym{NOV} \e$B%U%!%$%k$r$?$@>C$9$3$H$K$h$C$FC10l$N5-;v\e(B
+\e$B$N\e(B @acronym{NOV} \e$B%G!<%?$N@8@.$r\e(B @code{nnmaildir} \e$B$K6/@)$9$k$3$H$O$G$-$^\e(B
+\e$B$9!#$7$+$7\e(B @emph{\e$B$4MQ?4\e(B}\e$B!#$3$l$O\e(B @code{nnmaildir} \e$B$,$3$N5-;v$K?7$7$$5-;v\e(B
+\e$BHV9f$r3d$j?6$i$;!"\e(B@code{seen} \e$B0u!"%(!<%8%'%s%H!"$*$h$S%-%c%C%7%e$K$H$C$F\e(B
+\e$BLLE]$J$3$H$K$J$j$^$9!#\e(B
+
+@subsubsection \e$B5-;v$N0u\e(B
+@file{.nnmaildir/marks/flag/uniq} \e$B%U%!%$%k$,$"$k>l9g$K!"\e(B@code{uniq} \e$B$K$h$C\e(B
+\e$B$F<1JL$5$l$k5-;v$O!"\e(B@code{flag} \e$B0u$r;}$D$b$N$H9M$($i$l$^$9!#\e(B
+Gnus \e$B$,\e(B @code{nnmaildir} \e$B$K%0%k!<%W$N0u$r?R$M$k$H!"\e(B@code{nnmaildir} \e$B$O$=\e(B
+\e$B$N$h$&$J%U%!%$%k$rC5$7$F!"8+$D$1$?0u$N%;%C%H$rJs9p$7$^$9!#\e(B
+Gnus \e$B$,\e(B @code{nnmaildir} \e$B$K0u$N%;%C%H$N3JG<$rMW5a$9$k$H!"\e(B
+@code{nnmaildir} \e$B$OI,MW$JBP1~$9$k%U%!%$%k$r@8@.$7!"$^$?$O>C5n$7$^$9!#\e(B(\e$B<B\e(B
+\e$B:]$O!"$=$l$>$l$N0u$N$?$a$K?7$7$$%U%!%$%k$r:n$k$N$G$O$J$/!"\e(Bi\e$B%N!<%I\e(B \e$B$r@aLs\e(B
+\e$B$9$k$?$a$KC1$K\e(B @file{.nnmaildir/markfile} \e$B$X$N%O!<%I%j%s%/$rD%$j$^$9!#\e(B)
+
+@file{.nnmaildir/marks/} \e$B$K?7$7$$%G%#%l%/%H%j$r:n$k$3$H$K$h$C$F!"?7$7$$\e(B
+\e$B0u$rAOB$$9$k$3$H$,$G$-$^$9!#0u$rJ];}$7$D$D\e(B maildir \e$B$r\e(B tar \e$B$G$^$H$a$F%5!<\e(B
+\e$B%P!<$+$i$=$l$r:o=|$7!"8e$G\e(B tar \e$B$r$[$I$/$3$H$,$G$-$^$9!#0u%U%!%$%k$r:n@.\e(B
+\e$B$^$?$O>C5n$9$k$3$H$K$h$C$F!"$"$J$?<+?H$,0u$rDI2C$^$?$O:o=|$9$k$3$H$,$G$-\e(B
+\e$B$^$9!#\e(BGnus \e$B$,F0:n$7$F$$$F\e(B @code{nnmaildir} \e$B%5!<%P!<$,3+DL$7$F$$$k$H$-$K\e(B
+\e$B$3$l$r9T$J$&>l9g$O!":G=i$K$9$Y$F$N\e(B @code{nnmaildir} \e$B%0%k!<%W$N35N,%P%C%U%!\e(B
+\e$B$+$iB`=P$7$F%0%k!<%W%P%C%U%!$G\e(B @kbd{s} \e$B$r%?%$%W$7!"$=$N8e%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{g} \e$B$+\e(B @kbd{M-g} \e$B$r%?%$%W$9$k$N$,:GNI$G$9!#$=$&$7$J$$$H\e(B Gnus \e$B$OJQ\e(B
+\e$B99$rB*$($F$/$l$:$K!"$=$l$i$r85$KLa$7$F$7$^$&$+$b$7$l$^$;$s!#\e(B
+
+@node Mail Folders
+@subsubsection \e$B%a!<%k%U%)%k%@!<\e(B
+@cindex nnfolder
+@cindex mbox folders
+@cindex mail folders
+
+@code{nnfolder} \e$B$O$=$l$>$l$N%a!<%k%0%k!<%W$r0c$C$?%U%!%$%k$KC_B"$9$k%P%C\e(B
+\e$B%/%(%s%I$G$9!#$=$l$>$l$N%U%!%$%k$OI8=`$N\e(B Un*x mbox \e$BMM<0$G$9!#\e(B
+@code{nnfolder} \e$B$O5-;vHV9f$HE~CeF|$r5-O?$7$F$*$/$?$a$NDI2C$N%X%C%@!<$r2C\e(B
+\e$B$($^$9!#\e(B
+
+@cindex self contained nnfolder servers
+@cindex marks
+\e$B0u%U%!%$%k\e(B (\e$BLuCm\e(B: marks file) \e$B$,;H$o$l$k$H\e(B (\e$B$=$l$,%G%#%U%)%k%H$G$9$,\e(B)\e$B!"\e(B
+@code{nnfolder} \e$B%5!<%P!<$O\e(B @code{tar} \e$B$J$I$r;H$C$F%P%C%/%"%C%W$7$?$j!"8e\e(B
+\e$B$G$"$J$?$,IU$1$?0u$,$9$Y$FJ]$?$l$?>uBV$G\e(B gnus \e$B$KLa$9\e(B (\e$BK\Mh\e(B
+\e$B$N\e(B @code{nnfolder} \e$B%5!<%P!<$K$h$C$FDI2C$9$k\e(B) \e$B$3$H$,$G$-$kFC<A$r;}$D$h$&\e(B
+\e$B$K$J$j$^$9!#%0%k!<%W$N0u$O\e(B @code{nnfolder} \e$B%G%#%l%/%H%jFb$N!"\e(Bmbox \e$B%U%!%$\e(B
+\e$B%k$KDL>o\e(B @file{.mrk} (@code{nnfolder-marks-file-name} \e$B$r;2>H\e(B) \e$B$,IU2C$5$l\e(B
+\e$B$?L>A0$N%U%!%$%k$K3JG<$5$l$^$9!#$^$?!"8D!9$N\e(B @code{nnfolder} \e$B%0%k!<%W$K\e(B
+\e$B$D$$$F$b%P%C%/%"%C%W$9$k$3$H$,2DG=$G!"\e(B(\e$B%P%C%/%"%C%W$r\e(B nnfolder \e$B%G%#%l%/\e(B
+\e$B%$%H%j$KLa$7$?8e$G\e(B) @kbd{G m} \e$B%-!<$r;H$C$F$=$N%0%k!<%W$r85$KLa$7$^$9!#\e(B
+
+\e$B;v<B>e$N%5!<%P!<$N@_Dj\e(B:
+
+@table @code
+@item nnfolder-directory
+@vindex nnfolder-directory
+\e$BA4$F$N\e(B @code{nnfolder} \e$B%a!<%k%\%C%/%9$O$3$N%G%#%l%/%H%j!<$N2<$KCV$+$l$^\e(B
+\e$B$9!#4{DjCM$O\e(B @code{message-directory} \e$B$NCM\e(B (\e$B$=$N4{DjCM\e(B
+\e$B$O\e(B @file{~/Mail}) \e$B$G$9!#\e(B
+
+@item nnfolder-active-file
+@vindex nnfolder-active-file
+\e$B%"%/%F%#%V%U%!%$%k$NL>A0!#4{DjCM$O\e(B @file{~/Mail/active} \e$B$G$9!#\e(B
+
+@item nnfolder-newgroups-file
+@vindex nnfolder-newsgroups-file
+\e$B%0%k!<%W5-=R%U%!%$%k$NL>A0!#\e(B@xref{Newsgroups File Format}. \e$B4{DjCM\e(B
+\e$B$O\e(B @file{~/Mail/newsgroups"} \e$B$G$9!#\e(B
+
+@item nnfolder-get-new-mail
+@vindex nnfolder-get-new-mail
+@code{nil} \e$B$G$J$1$l$P!"\e(B@code{nnfolder} \e$B$OF~$C$F$/$k%a!<%k$rFI$_9~$_$^$9!#\e(B
+\e$B4{DjCM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item nnfolder-save-buffer-hook
+@vindex nnfolder-save-buffer-hook
+@cindex backup files
+\e$B%U%)%k%@!<$rJ]B8$9$kA0$K<B9T$5$l$k%U%C%/$G$9!#\e(B@code{nnfolder} \e$B%P%C%U%!$K\e(B
+\e$BBP$7$F$5$($b\e(B Emacs \e$B$ODL>o$N%P%C%/%"%C%W$NJQL>$r$9$k;v$KCm0U$7$F2<$5$$!#\e(B
+\e$B$3$N5!G=$rL58z$K$7$?$$$N$G$"$l$P!"%U%!%$%k\e(B @file{.emacs} \e$B$G<!$N$h$&$J;v\e(B
+\e$B$r$9$k;v$,$G$-$^$9\e(B:
+
+@lisp
+(defun turn off-backup ()
+  (set (make-local-variable 'backup-inhibited) t))
+
+(add-hook 'nnfolder-save-buffer-hook 'turn-off-backup)
+@end lisp
+
+@item nnfolder-delete-mail-hook
+@vindex nnfolder-delete-mail-hook
+\e$B$3$l$+$i>C5n$5$l$k%a%C%;!<%8$KHO0O$r69$a$i$l$F<B9T$5$l$k%U%C%/$G$9!#$3$N\e(B
+\e$B4X?t$OJL$N$H$3$m$K%a%C%;!<%8$r%3%T!<$7$?$j!">C5n$9$k$^$($K2?$i$+$N>pJs$r\e(B
+\e$B<h$j=P$9$?$a$K;H$C$?$j$9$k$3$H$,$G$-$^$9!#\e(B
+
+@item nnfolder-nov-is-evil
+@vindex nnfolder-nov-is-evil
+\e$B$b$7Hs\e(B@code{nil}\e$B$J$i!"$3$N%P%C%/%(%s%I$O\e(B @acronym{NOV} \e$B%U%!%$%k$rL5;k$7\e(B
+\e$B$^$9!#4{DjCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item nnfolder-nov-file-suffix
+@vindex nnfolder-nov-file-suffix
+@acronym{NOV} \e$B%U%!%$%k$N3HD%;R$G$9!#%G%#%U%)%k%H$O\e(B @file{.nov} \e$B$G$9!#\e(B
+
+@item nnfolder-nov-directory
+@vindex nnfolder-nov-directory
+@acronym{NOV} \e$B%U%!%$%k$,3JG<$5$l$k%G%#%l%/%H%j$G$9!#\e(B@code{nil} \e$B$@$C$?\e(B
+\e$B$i\e(B @code{nnfolder-directory} \e$B$,;H$o$l$^$9!#\e(B
+
+@item nnfolder-marks-is-evil
+@vindex nnfolder-marks-is-evil
+\e$BHs\e(B@code{nil} \e$B$G$"$k$H!"$3$N%P%C%/%(%s%I$O$$$+$J$k\e(B @sc{\e$B0u\e(B} \e$B%U%!%$%k$r$b\e(B
+\e$BL5;k$7$^$9!#%G%#%U%)%k%H$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item nnfolder-marks-file-suffix
+@vindex nnfolder-marks-file-suffix
+@sc{\e$B0u\e(B} \e$B%U%!%$%k$N3HD%;R$G$9!#%G%#%U%)%k%H$O\e(B @file{.mrk} \e$B$G$9!#\e(B
+
+@item nnfolder-marks-directory
+@vindex nnfolder-marks-directory
+@sc{\e$B0u\e(B} \e$B%U%!%$%k$,3JG<$5$l$k%G%#%l%/%H%j$G$9!#\e(B@code{nil} \e$B$@$C$?\e(B
+\e$B$i\e(B @code{nnfolder-directory} \e$B$,;H$o$l$^$9!#\e(B
+@end table
+
+@findex nnfolder-generate-active-file
+@kindex M-x nnfolder-generate-active-file
+@code{nnfolder} \e$B$GFI$_$?$$$H;W$&!"$?$/$5$s$N\e(B @code{nnfolder} \e$B$N$h$&$J%U%!\e(B
+\e$B%$%k$r;}$C$F$$$k$N$G$"$l$P!"\e(B
+@code{nnfolder} \e$B$K\e(B @code{nnfolder-directory} \e$B$K$"$kA4$F$N$=$N$h$&$J%U%!\e(B
+\e$B%$%k$K5$IU$+$;$k$?$a$K!"L?Na\e(B @kbd{M-x nnfolder-generate-active-file} \e$B$r\e(B
+\e$B;H$&;v$,$G$-$^$9!#$3$l$OD9$$%U%!%$%kL>$r;H$C$F$$$k$H$-$K$N$_F0:n$7$^$9$,!#\e(B
+
+@node Comparing Mail Back Ends
+@subsubsection \e$B%a!<%k%P%C%/%(%s%I$NHf3S\e(B
+
+\e$B$^$:!"MQ8l$H$7$F!"\e(B@dfn{\e$B%P%C%/%(%s%I\e(B} (back end) \e$B$ODc<!$N@\B3J}K!$N$?$a$N\e(B
+\e$BIaDL$N8l$G$9\e(B---\e$B$b$7K>$`$J$i!"F)2aE*$G$"$j!"$=$l$O2?$+$r@.$7?k$2$k$b$N$G\e(B
+\e$B$9!#$=$N$3$3$m$O!"%a!<%k$O$I$3$+$i$+Mh$J$1$l$P$J$i$:!"E,@Z$J%P%C%/%(%s%I\e(B
+\e$B$NA*Br$O!"%a!<%k$r\e(B gnus \e$B$N$9$06a$/$K<hF@$9$k$?$a$KMW5a$5$l$k!"$H$$$&$b$N\e(B
+\e$B$G$9!#\e(B
+
+\e$BF1$835G0$,\e(B Usenet \e$B<+?H$K$bB8:_$7$^$9!#5-;v$X$N@\?($O:#F|$G$O!"IaDL\e(B
+\e$B$O\e(B @acronym{NNTP} \e$B$G$J$5$l$^$9$,!"@N!9$NM+]5$J?<Lk$N;~Be$O!"3'$O5-;v$,B8\e(B
+\e$B:_$9$k%^%7%s\e(B (\e$B:#F|$G$O\e(B @acronym{NNTP} \e$B%5!<%P!<$H8F$V$b$N\e(B) \e$B$G%j!<%@!<$rF0\e(B
+\e$B$+$7!"%j!<%@!<$+$i$N@\B3$O!"D>@\5-;v$N%G%#%l%/%H%j!<%9%W!<%k$KF'$_9~$`$H\e(B
+\e$B$$$&$b$N$G$7$?!#$=$l$G$b!"$?$^$?$^%5!<%P!<\e(B (\e$B$b$7$/$O!"\e(BNFS \e$B$G%9%W!<%k$,FI\e(B
+\e$B$a$k$h$&$J>l9g\e(B) \e$B$K$$$k$h$&$J>l9g$O!"$3$l$i$NJ}K!$rA*$V$?$a\e(B
+\e$B$K\e(B @code{nntp} \e$B$d\e(B @code{nnspool} \e$B%P%C%/%(%s%I$N$I$A$i$+$rA*$V$3$H$,$G$-\e(B
+\e$B$^$7$?!#\e(B
+
+\e$B%a!<%k%P%C%/%(%s%I$rA*Br$9$k$3$H$N%4!<%k$O!"85$N7A<0$r07$&$N$KE,$7$?J}K!\e(B
+\e$B$H!">-Mh;HMQ$9$k$?$a$KJXMx$J7A<0$K%a!<%k$r;D$9$3$H$NN>J}$rF1;~$KI=8=$9$k\e(B
+\e$B$3$H$G$9!#$=$l$>$l$K$ONI$$E@$H0-$$E@$,$$$/$D$+$"$j$^$9\e(B:
+
+@table @code
+@item nnmbox
+
+UNIX \e$B%7%9%F%`$ONr;KE*$KC10l$N!"Hs>o$K0lHLE*$J!">e<j$/Dj5A$5$l$?7A<0$r;}$C\e(B
+\e$B$F$$$^$9!#A4$F$N%a%C%;!<%8$OC10l$N\e(B @dfn{\e$B%9%W!<%k%U%!%$%k\e(B} \e$B$KE~Ce$7!"@55,\e(B
+\e$BI=8=\e(B @samp{^From_} \e$B$K9gCW$9$k9T$G6h@Z$i$l$F$$$^$9!#\e(B(\e$B;d$N\e(B @samp{_} \e$B$N5-\e(B
+\e$B9f$N;HMQ$O%9%Z!<%9$r0UL#$9$k$?$a$G!"$3$NNc$G$O$3$l$O\e(B RFC \e$B$G;XDj$5$l$F$$\e(B
+\e$B$k\e(B @samp{From:} \e$B%X%C%@!<$GL5$$$3$H$rL@$i$+$K$9$k$?$a$G$9!#\e(B) Emacs \e$B$O!"$=\e(B
+\e$B$l$K\e(B gnus \e$B$b!"Nr;KE*$K\e(B Unix \e$B4D6-$+$i9-$^$j$^$7$?$N$G!"85$N\e(B mailbox \e$B7A<0\e(B
+\e$B$r$"$^$j$0$A$c$0$A$c$K$7$J$$$H$$$&$N$O!":G$b4JAG$JJ}K!$G$9!#$G$9$+$i!"$3\e(B
+\e$B$N%P%C%/%(%s%I$rA*$V$H!"K\Ev$N%9%W!<%k$+$i%a!<%k$r<hF@$7$F!"\e(Bgnus \e$B$N9%$`\e(B
+\e$B%G%#%l%/%H%j!<$K%a!<%k$r0\F0$9$k$?$a$N\e(B gnus \e$B$N<g$J3hF0$O!"C1$K!"<B9T2aDx\e(B
+\e$B$G2?$b\e(B (\e$BI>2A$G$-$k\e(B) \e$BJQ99$r$;$:$KJ#@=$9$k$3$H$G$9!#$=$l$O\e(B gnus \e$B$N4D6-$N;H\e(B
+\e$BMQ2DG=HO0O$K%a!<%k$r0\F0$9$k\e(B ``\e$B:G$b6r$+$J\e(B''\e$BJ}K!$G$9!#$3$l$ODj$a$i$l$?>l\e(B
+\e$B=j$K0\F0$9$k$N$rB.$/$7$^$9$,!"\e(Bgnus \e$B$,$I$3$K2?$,$"$k$+$rD4$Y$k$H$-$O!"2r\e(B
+\e$B@O$,CY$/$J$j$^$9!#\e(B
+
+@item nnbabyl
+
+\e$B$`$+$7$`$+$7!"\e(BTOPS \e$B$H8F$P$l$k%*%Z%l!<%F%#%s%0%7%9%F%`$d!";w$?$h$&$J$b$N\e(B
+\e$B$r<B9T$7$F$$$k\e(B DEC-10 \e$B$H\e(B DEC-20 \e$B$H$$$&$b$N$,$"$j!"IaDL$N\e(B (\e$BM#0l$N\e(B?) \e$B%a!<\e(B
+\e$B%k$rFI$`4D6-$O\e(B Babyl \e$B$H8F$P$l$k$b$N$G$7$?!#$=$N%7%9%F%`$KCe$$$?%a!<%k$,\e(B
+\e$B$I$N$h$&$J7A<0$K$J$C$F$$$?$+$OCN$j$^$;$s$,!"\e(BBabyl \e$B$O%a!<%k$,JQ49$5$l$k!"\e(B
+\e$B$=$lMQ$NFbIt7A<0$r;}$C$F$*$j!"<g$K!"\e(BBabyl \e$BFCM-$N%X%C%@!<$H>uBV%S%C%H$r%U%!\e(B
+\e$B%$%k$N$=$l$>$l$N%a%C%;!<%8$N@hF,$K2C$($k$3$H$r$7$F$$$^$7$?!#\e(B
+Rmail \e$B$O\e(B Emacs \e$B$N:G=i$N%a!<%k%j!<%@!<$G!"\e(BRichard Stallman \e$B$K$h$C$F=q$+$l!"\e(B
+Stallman \e$B$O$=$N\e(B TOPS/Babyl \e$B4D6-$N=P?H$G$"$k$?$a!"\e(BRmail \e$B$r4{$KB8:_$7$F$$\e(B
+\e$B$?%a!<%k%U%!%$%k$N0lB2$rM}2r$9$kMM$K=q$-$^$7$?!#\e(BGnus (\e$B$3$NLdBj$K4X$7$F\e(B
+\e$B$O\e(B VM \e$B$b\e(B) \e$B$3$N7A<0$r%5%]!<%H$7B3$1$F$$$^$9!#$=$l$O!"$=$N%a!<%i!<FCM-$N%X%C\e(B
+\e$B%@!<\e(B/\e$B%S%C%H$H$$$&$b$N$,$J$+$J$+<A$,NI$$$H9M$($i$l$F$$$k$+$i$G$9!#\e(B
+Rmail \e$B<+?H$b$b$A$m$s$^$@B8:_$7$F$$$F!"$^$@\e(B Stallman \e$B$K$h$C$F0];}$5$l$F$$\e(B
+\e$B$^$9!#\e(B
+
+\e$B>e$N7A<0$NN>J}$O%a!<%k$r%U%!%$%k%7%9%F%`$NC1FH$N%U%!%$%k$KF~$l!"%a!<%k$r\e(B
+\e$B8+$k$?$S$K!"%U%!%$%kA4BN$r2r@O$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item nnml
+
+@code{nnml} \e$B$O$[$H$s$I\e(B @code{nnspool} \e$B@\B3$N\e(B Usenet \e$B%7%9%F%`$rA`:n$7$F$$\e(B
+\e$B$k$h$&$J46$8$N$9$k%P%C%/%(%s%I$G$9!#\e(B(\e$B<B:]$N$H$3$m!"$9$4$/0JA0$K!"\e(B
+@code{nnml} \e$B$O\e(B @code{nnspool} \e$B$+$i;^J,$+$l$7$?$b$N$@$H;W$$$^$9!#\e(B)
+\e$B%a!<%k$O85$N%9%W!<%k%U%!%$%k$+$i<h$j=P$5$l!"$=$l$+$i8D!9$N%U%!%$%k\e(B
+\e$B$K\e(B 1:1 \e$B$GJ,$1$i$l$^$9!#\e(BUsenet \e$BMM<0$N%"%/%F%#%V%U%!%$%k\e(B (INN \e$B$d\e(B CNews \e$B$K\e(B
+\e$B4p$E$$$?%K%e!<%9%7%9%F%`$G\e(B (\e$BNc$($P\e(B) @file{/var/lib/news/active} \e$B$d!"F0\e(B
+\e$B;l\e(B @samp{NNTP LIST} \e$B$GJV$5$l$k$b$N$KN`;w$7$?$b$N\e(B) \e$B$r0];}$7!":#$+$i$@$H$+\e(B
+\e$B$J$jA0$K\e(B @acronym{NNTP} \e$B%5!<%P!<$N$?$a$KDj5A$5$l$F$$$k!"\e(B
+@dfn{overview} \e$B%U%!%$%k$b!"%0%k!<%W$XF~$k$H$-$N8zN($N$?$a$K:n@.$7$^$9!#\e(B
+\e$B%a!<%kJ,3d$G$O!"$?$/$5$s$N%U%!%$%k$N:n@.$H!"\e(B@code{nnml} \e$B%"%/%F%#%V%U%!%$\e(B
+\e$B%k$N99?7!"%a%C%;!<%8Kh$N\e(B overview \e$B$X$NDI2C$N$?$a$KCY$/$J$j$^$9$,!";HMQ;~\e(B
+\e$B$K$O%"%/%F%#%V%U%!%$%k$H\e(B overview \e$B$G$N:w0z5!G=$K$h$j!"$H$F$D$b$J$/B.$/$J\e(B
+\e$B$j$^$9!#\e(B
+
+@code{nnml} \e$B$O\e(B @dfn{inode} \e$B$rHs>o$K$?$/$5$s>CHq$7$^$9!#$9$J$o$A!"%U%!%$\e(B
+\e$B%k%7%9%F%`$G?7$7$$%U%!%$%k$rF~$l$k$?$a$N2DG=$J>l=j$rDj5A$9$k;q8;$r$?$/$5\e(B
+\e$B$s@jM-$7$^$9!#%7%9%F%`4IM}<T$O!"$+$C$A$j$7$?6&M-%U%!%$%k%7%9%F%`$G$NBgNL\e(B
+\e$B$N\e(B inode \e$B$N@jM-$r2w$/;W$$$^$;$s!#$7$+$7!"%U%!%$%k%7%9%F%`$,<+J,<+?H$N$b\e(B
+\e$B$N$G$"$k8D?M%^%7%s>e$G@83h$7$F$$$k$J$i!"\e(B@code{nnml} \e$B$OHs>o$KBg$-$JMxE@$,\e(B
+\e$B$"$j$^$9!#\e(B
+
+\e$B$^$?!"\e(BFAT16 \e$B$N\e(B Windows \e$B$N@$3&$K@8$-$F$$$k$J$i!"LdBj$,$"$k$G$7$g$&!#$?$/\e(B
+\e$B$5$s$N>.$5$J%U%!%$%k$GB?$/$N>l=j$r<h$i$l$F$7$^$$$^$9!#\e(B
+
+@item nnmh
+
+Rand MH \e$B%a!<%k1\Mw%7%9%F%`$O\e(B UNIX \e$B%7%9%F%`$K$+$J$jD9$$4VB8:_$7$F$$$^$9!#\e(B
+\e$B%a%C%;!<%8$N%9%W!<%k%U%!%$%k$r8D!9$N%U%!%$%k$KJ,3d$9$k$3$H$K$h$jA`:n$7$^\e(B
+\e$B$9$,!":w0z5!G=$,>/$7$+!"A4$/$J$$$+$H$$$&DxEY$G$9\e(B -- @code{nnmh} \e$B$O0UL#E*\e(B
+\e$B$K$O\e(B ``@code{nnml} \e$B$K%"%/%F%#%V%U%!%$%k$H\e(B overview \e$B$N$J$$$b$N\e(B'' \e$B$HEy2A$G\e(B
+\e$B$9!#$3$l$O5DO@$N$"$k$H$3$m$G$9$,!":G0-$NA*Br$G$9!#$H$$$&$N$O!"8D!9$N%U%!\e(B
+\e$B%$%k$N:n@.$NCY$5$,!"%0%k!<%W$G2?$,?7$7$$$+$rCN$k$H$-$N2r@O$N$?$a$N;HMQ$N\e(B
+\e$BCY$5$,7k$SIU$/$+$i$G$9!#\e(B
+
+@item nnfolder
+
+\e$B4pK\E*$K\e(B @code{nnfolder} \e$B$N8z2L$O%0%k!<%WKh$N\e(B @code{nnmbox} (\e$B>e$G@bL@$5\e(B
+\e$B$l$F$$$k:G=i$NJ}K!\e(B) \e$B$G$9!#$9$J$o$A!"\e(B@code{nnmbox} \e$B<+?H$O\e(B @emph{\e$BA4$F\e(B} \e$B$N\e(B
+\e$B%a!<%k$r0l$D$N%U%!%$%k$KF~$l$^$9\e(B; @code{nnfolder} \e$B$O%a!<%k%0%k!<%W$=$l$>\e(B
+\e$B$l$,\e(B Unix mail box \e$B%U%!%$%k$r;}$D$h$&$K>/$7:GE,2=$r$7$^$9!#\e(B
+@code{nnmobx} \e$B$h$j$b!"$=$l$>$l$N%0%k!<%W$rJL$K2r@O$9$k$N$GB.$/!"$=$N$&$(\e(B
+\e$B%a!<%k$r0\F0$5$;$k$N$K:G>.8B$NO+NO$rMW5a$9$kC1=c$J\e(B Unix mail box \e$B7A<0$r\e(B
+\e$BDs6!$7$^$9!#2C$($F!"\e(Bgnus \e$B$,$=$l$>$l$NJL$N%0%k!<%W$K$I$N$/$i$$$N%a%C%;!<\e(B
+\e$B%8$,$"$k$+$rD4$Y$k$?$a$N\e(B ``\e$B%"%/%F%#%V\e(B'' \e$B%U%!%$%k$r0];}$7$^$9!#\e(B
+
+\e$B$b$7$?$/$5$s$NNL$N%a%C%;!<%8$r<u$1<h$k$3$H$,M=A[$5$l$k%0%k!<%W$,$"$k$J$i!"\e(B
+@code{nnfolder} \e$B$O:GA1$NA*Br$G$O$"$j$^$;$s$,!"$=$l$J$j$NNL$N%a!<%k$7$+<u\e(B
+\e$B$1<h$i$J$$$J$i!"$*$=$i$/\e(B @code{nnfolder} \e$B$OA4$F$NCf$G0lHVE,$7$?%P%C%/%(\e(B
+\e$B%s%I$G$7$g$&!#\e(B
+
+@item nnmaildir
+
+\e$B4|8B@Z$l>C5n$dB>$N$3$H$,$i$r@_Dj$9$k$N$K!"\e(B@code{nnmaildir} \e$B$OB>$N%a!<%k\e(B
+\e$B%P%C%/%(%s%I$H$O>/!90[$J$C$?!"8_49@-$NL5$$%0%k!<%W%Q%i%a!<%?$r;H$$$^$9!#\e(B
+
+@code{nnmaildir} \e$B$OBgJ}\e(B @code{nnml} \e$B$H;w$?$b$N$G$9$,!"$$$/$i$+82Cx$J0c$$\e(B
+\e$B$,$"$j$^$9!#$=$l$>$l$N%a%C%;!<%8$OJL!9$N%U%!%$%k$K3JG<$5$l$^$9$,!"%U%!%$\e(B
+\e$B%kL>$O\e(B gnus \e$B$N5-;vHV9f$H4X78$,$"$j$^$;$s!#$^\e(B
+\e$B$?\e(B @code{nnmaildir} \e$B$O\e(B @code{nnml} \e$B$N\e(B overview \e$B$KAjEv$9$k%U%!%$%k$r5-;v\e(B
+\e$B$4$H$K0l$D3JG<$9$k$N$G!"\e(B@code{nnml} \e$B$NLsFsG\$NNL$N\e(B i\e$B%N!<%I$r;H$$$^$9!#\e(B
+(@code{df -i} \e$B$r;H$C$F\e(B i\e$B%N!<%I$N3d$jEv$F$,$I$l$[$I$?$/$5$s$"$k$+$rD4$Y$F\e(B
+\e$B2<$5$$!#\e(B) \e$B$=$N$?$a$KCY$/$J$C$?$jB?$/$N>l=j$r<h$C$F$7$^$&$h$&$J$i$P!"\e(B
+@uref{http://www.namesys.com/, ReiserFS} \e$B$dB>$NHs%V%m%C%/9=B$$N%U%!%$%k\e(B
+\e$B%7%9%F%`$X$NE>49$r8!F$$7$F2<$5$$!#\e(B
+
+maildir \e$B$O<u?.G[Aw$N$?$a$N%m%C%/$rI,MW$H$7$J$$$N$G!"$"$J$?$,%0%k!<%W$H$7\e(B
+\e$B$F;H$C$F$$$k\e(B maildir \e$B$O!"G[Aw$5$l$F$-$?%a!<%k$rD>@\<u$1<h$k$?$a\e(B
+\e$B$N\e(B maildir \e$B$K$9$k$3$H$b$G$-$^$9!#$3$l$O!"%a!<%k$,G[Aw$5$l$F$/$k2aDx$G0[\e(B
+\e$B$J$k%a!<%k%\%C%/%9$K;EJ,$5$l$k$h$&$K$J$C$F$$$k$N$J$i$P!"\e(Bgnus \e$B$N%a!<%kJ,\e(B
+\e$B3d$r>JN,$G$-$k$3$H$r0UL#$7$^$9!#\e(B@code{mail-sources} \e$B$K$*$1\e(B
+\e$B$k\e(B @code{directory} \e$B$N9`$K$O;w$?8z2L$,$"$j$^$9$,!"G[Aw$5$l$F$/$k%a!<%k$r\e(B
+\e$B%9%W!<%k$9$k$?$a$N%a!<%k%\%C%/%9$N0lB7$$\e(B (mbox \e$B7A<0$G$O$=$N$?$a$K%a%C%;!<\e(B
+\e$B%8$NK\J8$,2u$l$k\e(B) \e$B$H!"B>$N\e(B (\e$B2?$G$"$l$"$J$?$N9%$_$N7A<0$N\e(B) \e$B%0%k!<%W$H$7$F\e(B
+\e$B;H$o$l$kAH$,I,MW$G$9!#\e(Bmaildir \e$B$O\e(B @code{new/} \e$B%5%V%G%#%l%/%H%j$KCV$+$l$k\e(B
+\e$BAH$_9~$_%9%W!<%k$G$9!#%a!<%kJ,3d$,Fs=E%A%'%C%/$N$h$&$J07$$$r<u$1$J$$Be$o\e(B
+\e$B$j$K!"%a!<%k$r\e(B @code{new/} \e$B$+$i\e(B @code{cur/} \e$B$K0\F0$9$k$3$H$K!":#$N$H$3$m\e(B
+\e$B$O5$$rIU$1$F2<$5$$!#\e(B
+
+@code{nnmaildir} \e$B$O%0%k!<%W$N5-;v$N0u$r!"$=$l$KBP1~$9$k\e(B maildir \e$B$K3JG<$7\e(B
+\e$B$^$9!#\e(Bgnus \e$B$N30$+$i$=$l$i$r4JC1$KA`:n$G$-$k$h$&$K$9$k$?$a$K!"$=$N$h$&$K\e(B
+\e$B:n$i$l$F$$$k$N$G$9!#\e(Bmaildir \e$B$r\e(B tar \e$B$G$^$H$a$F$+$iJL$N$I$3$+$GE83+$7$F$b!"\e(B
+\e$B0u$O$=$N$^$^$G$9!#\e(B@code{nnml} \e$B$b0u$r3JG<$7$^$9$,!"\e(B
+@code{nnmaildir} \e$B$G\e(B gnus \e$B$N30$+$i$=$l$i$r;H$&$h$&$K4JC1$G$O$"$j$^$;$s!#\e(B
+
+@code{nnmaildir} \e$B$OB.EY$r>e$2$k$?$a$K$+$J$j$NNL$N%a%b%j$r;H$$$^$9!#\e(B
+(@code{nnml} \e$B$N>l9g$O%U%!%$%k$K3JG<$7!"\e(B@code{nnmh} \e$B$G$O2?EY$b5-;v%U%!%$\e(B
+\e$B%k$r2r@O$7$FF@$k$b$N$4$H$r!"$=$l$O%a%b%j>e$KJ];}$7$^$9!#\e(B) \e$B$3$l$,$"$J$?$K\e(B
+\e$B$H$C$FLdBj$J$i$P!"\e(B@code{nov-cache-size} \e$B%0%k!<%W%Q%i%a!<%?$r2?$+>.$5$J\e(B
+\e$BCM\e(B (0 \e$B$O$*$=$i$/$@$a$@$,\e(B 1 \e$B$@$C$?$i$?$V$sF0$/\e(B) \e$B$K@_Dj$9$k$3$H$K$h$C$F!"\e(B
+\e$B>/$J$$%a%b%j$r;H$&$h$&$K$9$k$3$H$,$G$-$^$9!#$3$N%-%c%C%7%e5!9=$O!"$*$=$i\e(B
+\e$B$/>-Mh$O:o=|$5$l$k$G$7$g$&!#\e(B
+
+\e$B5/F0$OB>$N%P%C%/%(%s%I$h$j$b\e(B @code{nnmaildir} \e$B$,CY$$$G$7$g$&!#%U%!%$%k%7\e(B
+\e$B%9%F%`$K0MB8$7$F$$$kItJ,0J30$N$9$Y$F$OB.$$$G$7$g$&!#\e(B
+
+@code{nnmaildir} \e$B$O\e(B @code{nnoo} \e$B$r;H$o$J$$$N$G!"\e(B@code{nnmaildir} \e$B$+$iGI\e(B
+\e$B@8$7$?%P%C%/%(%s%I$r=q$/$N$K\e(B @code{nnoo} \e$B$O;H$($^$;$s!#\e(B
+@end table
+
+@node Browsing the Web
+@section Browsing the Web
+@cindex web
+@cindex browsing the web
+@cindex www
+@cindex http
+
+\e$B%&%'%V$K4p$E$$$?5DO@$N>l$O$I$s$I$s9-$^$C$F$$$^$9!#B?$/$NJ,Ln$G!"%&%'%V$N\e(B
+\e$B7G<(HD$O:G$b=EMW$J>l$K$J$j!"%a!<%j%s%0%j%9%H$d%K%e!<%9%0%k!<%W$N=EMW@-$r\e(B
+\e$BfJ$i$;$F$$$^$9!#M}M3$O4JC1$G$9\e(B---\e$B?7$7$$MxMQ<T$,;H$$0W$$$+$i$G$9!#$?$@>l\e(B
+\e$B=j$r%/%j%C%/$9$k$@$1$G!"5DO@$N>l$,$"$j$^$9!#%a!<%j%s%0%j%9%H$G$O!"LLE]$J\e(B
+\e$B9XFI<jB3$-$r$7$J$1$l$P$J$i$:!"$[$H$s$I$N?M$O%K%e!<%9%0%k!<%W$,$I$3$K$"$k\e(B
+\e$B$+$9$iCN$j$^$;$s!#\e(B
+
+\e$B$3$N6Z=q$-$NLdBj$O!"%&%'%V%V%i%&%6!<$O%K%e!<%9%j!<%@!<$H$7$F$O$"$^$jNI$/\e(B
+\e$B$J$$$H$$$&$3$H$G$9!#$I$s$J5-;v$rFI$s$@$+$r5-O?$7$^$;$s!#6=L#$N$"$kI=Bj$K\e(B
+\e$B%9%3%"$rIU$1$k$3$H$,$G$-$^$;$s!#%*%U%i%$%s$GFI$`$3$H$,$G$-$^$;$s!#2?EY$b\e(B
+\e$B%/%j%C%/$9$k$3$H$rMW5a$7!":G8e$K$O$"$J$?$O7y$K$J$j$^$9!#\e(B
+
+\e$B$=$l$G\e(B---\e$B%&%'%V%V%i%&%6!<$,7G<(HD$rFI$`$N$KE,$7$F$$$J$$$N$J$i!"$I$&$7$F\e(B
+\e$BBe$o$j$K\e(B gnus \e$B$r;H$o$J$$$N$G$7$g$&\e(B?
+
+Gnus \e$B$O$3$l$i$N%=!<%9$X$N3&LL$rDs6!$9$k%P%C%/%(%s%I72$r>/$7Hw$($D$D$"$j\e(B
+\e$B$^$9!#\e(B
+
+@menu
+* Archiving Mail::
+* Web Searches::                \e$BJ8;zNs$K%^%C%A$9$k5-;v$+$i%0%k!<%W$r:n$k\e(B
+* Slashdot::                    Slashdot \e$B$N%3%a%s%H$rFI$`\e(B
+* Ultimate::                    Ultimate Bulletin Board \e$B%7%9%F%`\e(B
+* Web Archive::                 \e$B%&%'%V$KJ]4I$5$l$?%a!<%j%s%0%j%9%H$rFI$`\e(B
+* Web Newspaper::               \e$B%&%'%V$KJ]4I$5$l$??7J9$rFI$`\e(B
+* RSS::                         RDF Site Summary \e$B$rFI$`\e(B
+* Customizing w3::              Gnus \e$B$+$i\e(B Emacs/W3 \e$B$rA`:n$9$k\e(B
+@end menu
+
+@samp{Web Newspaper} \e$B$r=|$/$9$Y$F$N%&%'%V%=!<%9$O!"F0:n$5$;$k$?$a\e(B
+\e$B$K\e(B Emacs/W3 \e$B$H\e(B url \e$B%i%$%V%i%j$,I,MW$G$9!#\e(B
+
+\e$B$3$l$i$N%&%'%V%=!<%9$N0lHV$NLdBj$OD94|4V$OF0:n$7$J$$2DG=@-$,9b$$$3$H$G$9!#\e(B
+@acronym{HTML} \e$B%G!<%?$+$i>pJs$r=8$a$k$N$O$;$$$<$$?dB,$G!"9=B$$,JQ2=$7$?\e(B
+\e$B$H$-$K$O!"\e(Bgnus \e$B%P%C%/%(%s%I$OF0:n$7$^$;$s!#$G$b!"$"$kDxEY?7$7$$%P!<%8%g\e(B
+\e$B%s$N%P%C%/%(%s%I$r;H$C$F$$$l$PBg>fIW$N$O$:$G$9!#\e(B
+
+\e$B$3$l$i$N%&%'%VJ}K!$K6&DL$9$k$3$H$O!"%&%'%V%=!<%9$O$7$P$7$PMn$A$F$$$?$j!"\e(B
+\e$B;HMQ2DG=$G$J$+$C$?$j!"C1=c$K3Z$7$`$K$OCY$9$.$k$3$H$,$"$k!"$H$$$&$3$H$G$9!#\e(B
+\e$B$=$&$$$&>l9g$K$O!"\e(BGnu Agent (@pxref{Gnus Unplugged}) \e$B$K5-;v$N%@%&%s%m!<\e(B
+\e$B%I$rG$$;$F!"%m!<%+%k%G%#%9%/$+$i9%$-$J$H$-$KFI$`$h$&$K$9$k$3$H$,$G$-$^$9!#\e(B
+\e$B$3$l$G!"\e(BWorld Wide Wait \e$B$H$O$*$5$i$P$G$9!#\e(B
+
+@node Archiving Mail
+@subsection \e$B%a!<%k$NJ]B8\e(B
+@cindex archiving mail
+@cindex backup of mail
+
+\e$B$$$/$D$+$N%P%C%/%(%s%I!"FC$K\e(B @code{nnml}, @code{nnfolder} \e$B$*$h\e(B
+\e$B$S\e(B @code{nnmaildir} \e$B$O!"$=$l$>$l$N%0%k!<%W$N5-;v$N0u$rK\Ev$KJ];}$7$^$9!#\e(B
+\e$B$3$l$i$N%5!<%P!<$G!"%0%k!<%W$N0u$rJ]$A$D$DJ]B8$7$?$j85$KLa$9$N$O$+$J$j4J\e(B
+\e$BC1$G$9!#\e(B
+
+(\e$B$G$b!"%0%k!<%W%l%Y%k$H%0%k!<%W%Q%i%a!<%?$r$bJ];}$9$k$K$O!":#$^$G$H$*\e(B
+\e$B$j\e(B @file{.newsrc.eld} \e$B$N?@$K!"Iq$$$H@8lS$rJ{$2$J$1$l$P$J$j$^$;$s$,!#\e(B)
+
+@code{nnml}, @code{nnfolder} \e$B$^$?$O\e(B @code{nnmaildir} \e$B%5!<%P!<$K$^$k$4$H\e(B
+\e$BJ]B8$9$k$K$O!"%5!<%P!<$N%G%#%l%/%H%j$r:F5"E*$K%3%T!<$7$^$9!#\e(Bgnus \e$B$r=*N;\e(B
+\e$B$9$kI,MW$OL5$$$N$G!"J]B8$O\e(B @code{cron} \e$B$d$=$l$KN`$9$k$b$N$,9T$J$&$3$H$,\e(B
+\e$B$G$-$^$9!#%G!<%?$rI|5"$5$;$k$K$O%G%#%l%/%H%jLZ\e(B (tree) \e$B$r85$KLa$9$3$H$G9T\e(B
+\e$B$J$$!"$=$N%G%#%l%/%H%j$r;X$7<($9$h$&$K\e(B gnus \e$B$N%5!<%P!<$NDj5A$KDI2C$7$^$9!#\e(B
+@ref{Article Backlog}, @ref{Asynchronous Fetching} \e$B$*$h$S$=$NB>$O!"%G!<\e(B
+\e$B%?$r>e=q$-$7$F<YKb$r$9$k$+$b$7$l$J$$$N$G!"$"$J$?$O%G!<%?$rI|5"$5$;$kA0\e(B
+\e$B$K\e(B gnus \e$B$r=*N;$9$kI,MW$,$"$k$+$b$7$l$^$;$s!#\e(B
+
+\e$B8D!9$N\e(B @code{nnml}, @code{nnfolder} \e$B$^$?$O\e(B @code{nnmaildir} \e$B$N%0%k!<%W$r!"\e(B
+\e$B0u$rJ];}$7$D$DJ]B8$9$k$3$H$b$G$-$^$9!#\e(B@code{nnml} \e$B$+\e(B @code{nnmaildir} \e$B$G\e(B
+\e$B$O!"$=$N%0%k!<%W$N%G%#%l%/%H%j$K$"$k$9$Y$F$N%U%!%$%k$r%3%T!<$7$^$9!#\e(B
+@code{nnfolder} \e$B$G$O!"4pK\$N%U%)%k%@!<%U%!%$%k\e(B (@file{FOO}) \e$B$H0u%U%!%$\e(B
+\e$B%k\e(B (@file{FOO.mrk}) \e$B$NN>J}$r%3%T!<$9$kI,MW$,$"$j$^$9!#%0%k!<%W$r85$KLa$9\e(B
+\e$B$N$O!"%0%k!<%W%P%C%U%!$G\e(B @kbd{G m} \e$B%-!<$r;H$$$^$9!#$=$N:G8e$N<j=g$K$h$C\e(B
+\e$B$F!"\e(Bgnus \e$B$O?7$7$$%G%#%l%/%H%j$,$G$-$?$3$H$rCN$j$^$9!#\e(B@code{nnmaildir} \e$B$O\e(B
+\e$B<+F0E*$K?7$7$$%G%#%l%/%H%j$rCN$k$N$G!"$=$N>l9g\e(B @kbd{G m} \e$B$OITMW$G$9!#\e(B
+
+@node Web Searches
+@subsection \e$B%&%'%V8!:w\e(B
+@cindex nnweb
+@cindex Google
+@cindex dejanews
+@cindex gmane
+@cindex Usenet searches
+@cindex searching the Usenet
+
+\e$B$=$l$O!"$J$s$H$$$&$+!"\e(BUsenet \e$B$+$iJ8;zNs$K%^%C%A$9$k5-;v$r8!:w$9$k$N$O$H\e(B
+\e$B$F$bAG@2$i$7$$$s$@$1$I!"$=$N!"$"$N%&%'%V%V%i%&%6!<$C$F$d$D$r;H$C$F!"$=$s\e(B
+\e$B$G$b$C$F!"@kEA$rFI$^$;$i$l$k$C$F$$$&$N$O!"$=$N!"$J$s$H$$$&$+!"$[$s$H$&\e(B
+\e$B$K\e(B @emph{\e$B!VITMM$M!W\e(B} \e$B$H$$$&$+!"$=$l$G!"\e(Bgnus \e$B$G$O%V%i%&%6!<$r;H$o$:$K!"$=\e(B
+\e$B$N!"\e(B@emph{\e$BD6$+$C$3$h$/\e(B}\e$B$=$l$,$G$-$k!"$C$F$3$H$G$9!#\e(B
+
+@code{nnweb} \e$B%P%C%/%(%s%I$O!"6/NO$J8!:w%(%s%8%s$KBP$7$F4JC1$J%$%s%?!<%U%'!<\e(B
+\e$B%9$rDs6!$7$^$9!#\e(B@code{nnweb} \e$B%0%k!<%W$r:n@.$7!"8!:w%Q%?!<%s$rF~NO$7!"$=\e(B
+\e$B$7$F$=$N%0%k!<%W$KF~$C$FB>$NIaDL$N%0%k!<%W$N$h$&$K5-;v$rFI$_$^$9!#%0%k!<\e(B
+\e$B%W%P%C%U%!\e(B (@pxref{Foreign Groups}) \e$B$N\e(B @kbd{G w} \e$BL?Na$K$h$C$F$*<j7Z$K$3\e(B
+\e$B$l$,$G$-$^$9!#\e(B
+
+@code{nnweb} \e$B%0%k!<%W$O!"8GDj%0%k!<%W$K$J$m$&$H$O$7$^$;$s\e(B --- \e$B$3$N%0%k!<\e(B
+\e$B%W$G$O5-;vHV9f$O$4$/0l;~E*$J$b$N$H$7$F07$$$^$9!#$D$^$j!"\e(B@code{nnweb} \e$B%0\e(B
+\e$B%k!<%W$KF~$k$?$S$K\e(B(\e$B$?$H$(8!:w%Q%?!<%s$rJQ99$7$F$$$J$/$H$b\e(B)\e$B!"5-;v$N=g=x$,\e(B
+\e$B0c$C$F$$$k$+$b$7$l$^$;$s!#$^$?!"=EJ#M^\e(B
+\e$B@)\e(B (@pxref{Duplicate Suppression}) \e$B$r;H$C$F$b$&$^$/F/$+$J$$$G$7$g$&!#$H\e(B
+\e$B$$$&$N$O!"\e(B@code{nnweb} \e$B$O8!:w%(%s%8%s\e(B (\e$BNc$($P\e(B Google) \e$B$r;H$C$F5-;v$rFI$_\e(B
+\e$B9~$`$^$G$O!"\e(B@code{Message-ID} \e$B$rCN$k$3$H$O$G$-$J$$$+$i$G$9!#$"$J$?$,FI$s\e(B
+\e$B$@5-;v$r21$($F$*$/$?$a$NM#0l$NJ}K!$O!"\e(B@code{Date} \e$B%X%C%@!<$r$b$H$K%9%3%"\e(B
+\e$B$rIU$1$k$3$H$@$1$G$9\e(B --- \e$B$D$^$j$"$J$?$,$=$N%0%k!<%W$r:G8e$KFI$s$@F|IU$h\e(B
+\e$B$j!"A0$KEj9F$5$l$?5-;v$rA4$F4{FI$K$9$k!"$H$$$&$3$H$G$9!#\e(B
+
+\e$B$b$78!:w%(%s%8%s$N=PNO7A<0$,JQ99$5$l$k$H!"\e(B@code{nnweb} \e$B$O$=$l$r$&$^$/2r\e(B
+\e$B<a$G$-$:!"=hM}$O<:GT$9$k$G$7$g$&!#$b$7%&%'%VDs6!<TC#$,$=$s$J$3$H$r$7$?$i!"\e(B
+\e$BH`$i$r7c$7$/@U$a$k$Y$-$G$7$g$&\e(B --- \e$B$=$l$O9-9p$G6b$r2T$0$N$,H`$i\e(B
+\e$B$N\e(B @emph{\e$BB8:_M}M3\e(B} \e$B$G$"$j!"<R2q$K%5!<%S%9$rDs6!$9$k$3$H$G$O$J$$$+$i$G$9!#\e(B
+@code{nnweb} \e$B$OA4$F$N5-;v$+$i9-9p$r@v$$N.$7$F$7$^$&$N$G!"Ds6!<T$?$A$,%`\e(B
+\e$B%+$D$$$F$$$k$H;W$o$l$k$+$bCN$l$^$;$s!#$^$"8+$F$F$/$@$5$$!#\e(B
+
+@code{nnweb} \e$B$r;H$&$K$O!"\e(B@code{url} \e$B$H\e(B @code{w3} \e$B%Q%C%1!<%8$r%$%s%9%H!<\e(B
+\e$B%k$7$F$*$+$J$/$F$J$J$j$^$;$s!#\e(B
+
+\e$B0J2<$O2>A[%5!<%P!<JQ?t$G$9!#\e(B
+
+@table @code
+@item nnweb-type
+@vindex nnweb-type
+\e$B$I$N8!:w%(%s%8%s$r;H$C$F$$$k$+!#8=:_%5%]!<%H$5$l$F$$$k<oN`$O!"\e(B
+@code{google}, @code{dejanews} \e$B$=$7$F\e(B @code{gmane} \e$B$G$9!#\e(B
+@code{dejanews} \e$B$O\e(B @code{google} \e$B$NJLL>$K$J$C$F$$$k$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@item nnweb-search
+@vindex nnweb-search
+\e$B8!:w%(%s%8%s$KM?$($k8!:wJ8;zNs!#\e(B
+
+@item nnweb-max-hits
+@vindex nnweb-max-hits
+\e$BI=<($9$k8!:w7k2L$N:GBg?t!#=i4|CM$O\e(B 999 \e$B$G$9!#\e(B
+
+@item nnweb-type-definition
+@vindex nnweb-type-definition
+\e$B7?!&Dj5AO"A[%j%9%H!#$3$NO"A[%j%9%H$O!"$5$^$6$^$J8!:w%(%s%8%s$N<oN`$KBP$7\e(B
+\e$B$F!"\e(B@code{nnweb} \e$B$,$I$&$9$Y$-$+$rM?$($^$9!#0J2<$K<($9MWAG$rM?$($J$/$F$O\e(B
+\e$B$J$j$^$;$s!#\e(B
+
+@table @code
+@item article
+\e$B5-;v$rI|9f2=$7!"\e(Bgnus \e$B$,M}2r$G$-$k7A$GDs6!$9$k4X?t!#\e(B
+
+@item map
+\e$B5-;vHV9f$+$i%a%C%;!<%8%X%C%@!<$H\e(B URL \e$B$rF@$kO"A[%j%9%H$r:n@.$9$k4X?t!#\e(B
+
+@item search
+\e$B8!:w%(%s%8%s$K8!:wJ8;zNs$rAw$k4X?t!#\e(B
+
+@item address
+\e$BA0=R$N4X?t$,8!:wJ8;zNs$rAw$k$Y$-%"%I%l%9!#\e(B
+
+@item id
+@code{Message-ID} \e$B$r$b$H$K5-;v$r<hF@$9$k$?$a$N\e(B URL \e$B7A<0J8;zNs!#\e(B
+@end table
+@end table
+
+@node Slashdot
+@subsection Slashdot
+@cindex Slashdot
+@cindex nnslashdot
+
+@uref{http://slashdot.org/, Slashdot} \e$B$O?M5$$N$"$k%K%e!<%9%5%$%H$G!"%K%e!<\e(B
+\e$B%95-;v$N8e$K3hH/$J5DO@$,$J$5$l$F$$$^$9!#\e(B@code{nnslashdot} \e$B$G$OJXMx$JJ}K!\e(B
+\e$B$G$3$N2q5D<<$rFI$`$3$H$,$G$-$^$9!#\e(B
+
+\e$B$3$3$+$iFI$`$?$a$N0lHV4JC1$JJ}K!$O0J2<$N$h$&$J$b$N\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$k$3$H$G$9!#\e(B
+
+@lisp
+(setq gnus-secondary-select-methods
+      '((nnslashdot "")))
+@end lisp
+
+\e$B$3$l$O\e(B gnus \e$B$K\e(B @code{nnslashdot} \e$B%P%C%/%(%s%I$K?7$7$$%3%a%s%H$H%0%k!<%W\e(B
+\e$B$r?R$M$k$h$&$K$7$^$9!#\e(B@kbd{F} \e$BL?Na$O$=$l$>$l$N?7$7$$%K%e!<%95-;v$r?7$7\e(B
+\e$B$$\e(B gnus \e$B$N%0%k!<%W$H$7$F9XFI$7!"$3$l$i$N%0%k!<%W$KF~$k$3$H$G%3%a%s%H$rFI\e(B
+\e$B$`$3$H$,$G$-$^$9!#\e(B(\e$B=i4|@_Dj$N9XFIJ}K!$G$O!"?7$7$$%0%k!<%W$r%>%s%S$H$7$F\e(B
+\e$B9XFI$9$k$3$H$KCm0U$7$F$/$@$5$$!#B>$NJ}K!$b;H$($^\e(B
+\e$B$9\e(B (@pxref{Subscription Methods})\e$B!#\e(B
+
+\e$B$b$7$"$J$?$,8E$$\e(B @code{nnslashdot} \e$B%0%k!<%W$r:o=|$7$?$$$N$J$i$P!"\e(B
+@kbd{G DEL} \e$B$,:G$b<j7Z$JF;6q$G$9\e(B (@pxref{Foreign Groups})\e$B!#\e(B
+
+@code{nnslashdot} \e$B%3%a%s%H$K%U%)%m!<%"%C%W\e(B (\e$B$^$?$O?7$7$$%3%a%s%H$NEj9F\e(B)
+\e$B$r$9$k$H$-$O!">/$7\e(B @acronym{HTML} \e$B$KJQ49$5$l$^$9!#FC$K!"\e(B@samp{> } \e$B$G0zMQ\e(B
+\e$B$5$l$?%F%-%9%H$O$=$NBe$o$j$K\e(B @samp{blockquote} \e$B$G0zMQ$5$l!"=pL>$K$O$=$l\e(B
+\e$B$>$l$N9T$N:G8e$K\e(B @samp{br} \e$B$,DI2C$5$l$^$9!#$=$l0J30$O!"%a%C%;!<%8%P%C%U%!\e(B
+\e$B$KD>@\\e(B @acronym{HTML} \e$B$r=q$/$3$H$,$G$-$^$9!#\e(BSlashdot \e$B$O$$$/$D\e(B
+\e$B$+\e(B @acronym{HTML} \e$B$rA*JL$9$k$3$H$K5$$r$D$1$F$/$@$5$$!#\e(B
+
+\e$B0J2<$NJQ?t$G?6$kIq$$$rJQ$($k$3$H$,$G$-$^$9\e(B:
+
+@table @code
+@item nnslashdot-threaded
+@code{nnslashdot} \e$B$,%0%k!<%W$r%9%l%C%I$GI=<($9$k$+$I$&$+!#=i4|CM\e(B
+\e$B$O\e(B @code{t} \e$B$G$9!#%9%l%C%I$rI=<($G$-$k$?$a$K$O!"\e(B@code{nnslashdot} \e$B$O%0%k!<\e(B
+\e$B%W$KF~$k:]$K$=$NA4$F$N%3%a%s%H$r<hF@$9$kI,MW$,$"$j$^$9!#%9%l%C%II=<($,MW\e(B
+\e$B5a$5$l$F$$$J$$$H!"\e(B@code{nnslashdot} \e$B$OMxMQ<T$,M_$7$$%3%a%s%H$@$1$r<hF@$7\e(B
+\e$B$^$9!#%9%l%C%I$NJ}$,$-$l$$$G$9$,!"%9%l%C%IL5$7I=<($h$j!"$:$C$H$:$C$HCY$/\e(B
+\e$B$J$j$^$9!#\e(B
+
+@item nnslashdot-login-name
+@vindex nnslashdot-login-name
+\e$BEj9F;~$K;H$&%m%0%$%sL>$G$9!#\e(B
+
+@item nnslashdot-password
+@vindex nnslashdot-password
+\e$BEj9F;~$K;H$&%Q%9%o!<%I$G$9!#\e(B
+
+@item nnslashdot-directory
+@vindex nnslashdot-directory
+@code{nnslashdot} \e$B$,%U%!%$%k$rJ]B8$9$k>l=j$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/News/slashdot/} \e$B$G$9!#\e(B
+
+@item nnslashdot-active-url
+@vindex nnslashdot-active-url
+\e$B%K%e!<%95-;v$H%3%a%s%H$r<hF@$9$k$?$a$K;H$o$l$k\e(B @acronym{URL} \e$B$NJ8;zNs$G\e(B
+\e$B$9!#=i4|CM$O\e(B @samp{http://slashdot.org/search.pl?section=&min=%d} \e$B$G$9!#\e(B
+
+@item nnslashdot-comments-url
+@vindex nnslashdot-comments-url
+\e$B%3%a%s%H$r<hF@$9$k$?$a$K;HMQ$5$l$k\e(B @acronym{URL} \e$BJ8;zNs$G$9!#\e(B
+
+@item nnslashdot-article-url
+@vindex nnslashdot-article-url
+\e$B%K%e!<%95-;v$r<hF@$9$k$?$a$K;H$o$l$k\e(B @acronym{URL} \e$BJ8;zNs$G$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{http://slashdot.org/article.pl?sid=%s&mode=nocomment} \e$B$G$9!#\e(B
+
+@item nnslashdot-threshold
+@vindex nnslashdot-threshold
+\e$B%9%3%"$N$7$-$$CM$G$9!#=i4|CM$O\e(B -1 \e$B$G$9!#\e(B
+
+@item nnslashdot-group-number
+@vindex nnslashdot-group-number
+\e$B:G?7$N\e(B 10 \e$B$K2C$($F99?7$rB3$1$k8E$$%0%k!<%W$N?t$G$9!#=i4|CM$O\e(B 0 \e$B$G$9!#\e(B
+@end table
+
+@node Ultimate
+@subsection Ultimate
+@cindex nnultimate
+@cindex Ultimate Bulletin Board
+
+@uref{http://www.ultimatebb.com/, The Ultimate Bulletin Board} \e$B$O$*$=$i\e(B
+\e$B$/0lHVNI$/;H$o$l$F$$$k%&%'%V7G<(HD%7%9%F%`$G$7$g$&!#$H$F$b@0A3$H$7$FNI$$\e(B
+\e$B3&LL$G!"\e(Bgnus \e$B$,%0%k!<%W$r:G?7$N>uBV$KJ]$C$F$*$/$?$a$K>pJs$rF@$k$3$H$,2D\e(B
+\e$BG=$G$9!#\e(B
+
+@code{nnultimate} \e$B$r;O$a$k$?$a$N0lHV4JC1$JJ}K!$O%0%k!<%W%P%C%U%!$G0J2<$N\e(B
+\e$B$h$&$J$b$N$r$9$k$3$H$G$9\e(B: @kbd{B nnultimate RET
+http://www.tcj.com/messboard.ubbcgi/ RET}\e$B!#\e(B(\e$B6=L#$N$"$k2q5D<<\e(B
+\e$B$N\e(B @acronym{URL} (@samp{Ultimate.cgi} \e$BEy$r:G8e$K4^$s$G$$$J$$$b$N\e(B) \e$B$KJQ$(\e(B
+\e$B$F$/$@$5$$!#\e(BUltimate \e$B%&%'%V%5%$%H$K$O$?$/$5$s5s$2$i$l$F$$$^$9!#\e(B) \e$B$=$l$+\e(B
+\e$B$i%5!<%P!<%P%C%U%!$G6=L#$N$"$k%0%k!<%W$r9XFI$7!"%0%k!<%W%P%C%U%!$+$i$=$l\e(B
+\e$B$i$rFI$s$G$/$@$5$$!#\e(B
+
+\e$B0J2<$N\e(B @code{nnutimate} \e$BJQ?t$rJQ992DG=$G$9\e(B:
+
+@table @code
+@item nnultimate-directory
+@vindex nnultimate-directory
+@code{nnultimate} \e$B$,%U%!%$%k$rJ]B8$9$k%G%#%l%/%H%j!<$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/News/ultimate/} \e$B$G$9!#\e(B
+@end table
+
+@node Web Archive
+@subsection Web Archive
+@cindex nnwarchive
+@cindex Web Archive
+
+\e$B%a!<%j%s%0%j%9%H$NCf$K$ONc$($P!"\e(B
+@uref{http://www.egroups.com/} \e$B$d\e(B @uref{http://www.mail-archive.com/} \e$B$N\e(B
+\e$B$h$&$K%&%'%V%5!<%P!<$K$7$+%"!<%+%$%V$,L5$$$b$N$b$"$j$^$9!#$H$F$b@0A3$H$7\e(B
+\e$B$FNI$$3&LL$G!"\e(Bgnus \e$B$,%0%k!<%W$r:G?7$N>uBV$KJ]$C$F$*$/$?$a$K>pJs$rF@$k$3\e(B
+\e$B$H$,2DG=$G$9!#\e(B
+
+@findex gnus-group-make-warchive-group
+@code{nnwarchive} \e$B$r;O$a$k$?$a$N0lHV4JC1$JJ}K!$O%0%k!<%W%P%C%U%!$G0J2<$N\e(B
+\e$B$h$&$J$b$N$r$9$k$3$H$G$9\e(B: @kbd{M-x gnus-group-make-warchive-group RET
+@var{an_egroup} RET egroups RET www.egroups.com RET
+@var{your@@email.address} RET}\e$B!#\e(B(@var{an_egroup} \e$B$r9XFI$7$F$$$k%a!<%j%s\e(B
+\e$B%0%j%9%H$K!"\e(B@var{your@@emailaddress} \e$B$rEE;R%a!<%k%"%I%l%9$KCV$-49$($F2<\e(B
+\e$B$5$$!#\e(B) \e$B$^$?$O\e(B @kbd{B nnwarchive RET mail-archive RET} \e$B$G%P%C%/%(%s%I$r\e(B
+\e$B%V%i%&%:$7$F2<$5$$!#\e(B
+
+\e$B0J2<$N\e(B @code{nnwarchive} \e$BJQ?t$rJQ$($k$3$H$,2DG=$G$9\e(B:
+
+@table @code
+@item nnwarchive-directory
+@vindex nnwarchive-directory
+@code{nnwarchive} \e$B$,%U%!%$%k$rJ]B8$9$k%G%#%l%/%H%j!<$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/News/warchive} \e$B$G$9!#\e(B
+
+@item nnwarchive-login
+@vindex nnwarchive-login
+\e$B%&%'%V%5!<%P!<$G$N%"%+%&%s%HL>$G$9!#\e(B
+
+@item nnwarchive-passwd
+@vindex nnwarchive-passwd
+\e$B%&%'%V%5!<%P!<$G$N%"%+%&%s%H$N%Q%9%o!<%I$G$9!#\e(B
+@end table
+
+@node Web Newspaper
+@subsection Web Newspaper
+@cindex emacs-w3m
+@cindex nnshimbun
+@cindex Web Newspaper
+
+\e$B%&%'%V$K4p$E$$$?%P%C%/%(%s%I$G$"$k\e(B @samp{nnshimbun} \e$B$O!"\e(B2003\e$BG/\e(B6\e$B7n\e(B18\e$BF|$r\e(B
+\e$B0J$F\e(B emacs-w3m \e$B%Q%C%1!<%8$K0\@R$5$l$^$7$?!#:#$^$G$N$h$&$K\e(B T-gnus \e$B$G%&%'\e(B
+\e$B%V$N?7J9$r1\Mw$7$?$$$N$G$"$l$P!":G?7HG$N\e(B emacs-w3m \e$B$r%$%s%9%H!<%k$9$kI,\e(B
+\e$BMW$,$"$j$^$9!#$=$N:]!"\e(B@emph{\e$BI,$:\e(B} T-gnus \e$BM3Mh\e(B
+\e$B$N\e(B @file{nnshimbun.el} \e$B$H\e(B @file{nnshimbun.elc} \e$B%U%!%$%k$r>C$7$F2<$5$$!#\e(B
+Emacs-w3m \e$B$O30It%3%^%s%I\e(B w3m \e$B$X$N\e(B Emacs \e$B$N%$%s%?!<%U%'!<%9$G$9!#>\:Y>pJs\e(B
+\e$B$K$D$$$F$O0J2<$N%Z!<%8$rK,$M$F$_$F2<$5$$!#\e(B
+
+@example
+@c Don't use @uref{} here, or old texinfmt will neglect @example. :-(
+http://emacs-w3m.namazu.org/
+http://w3m.sourceforge.net/
+@end example
+
+@c This comment line is needed to prevent texinfmt bug. :-(
+\e$B$"$J$?$N%7%9%F%`$K$9$G$K\e(B emacs-w3m \e$B$,%$%s%9%H!<%k$5$l$F$$$k$N$J$i$P!"\e(B
+(@pxref{Nnshimbun, , Nnshimbun, emacs-w3m-ja, Emacs-w3m-ja}) \e$B$r;2>H$7$F\e(B
+\e$B2<$5$$!#\e(B
+
+@node RSS
+@subsection RSS
+@cindex nnrss
+@cindex RSS
+
+\e$B$$$/$D$+$N%5%$%H$O\e(B RDF site summary (@acronym{RSS}) \e$B$r;}$C$F$$$^$9!#\e(B
+@acronym{RSS} \e$B$O!"%K%e!<%9$K4XO"$9$k%5%$%H\e(B (BBC \e$B$d\e(B CNN \e$B$N$h$&$J\e(B) \e$B$N<gMW\e(B
+\e$B9`L\$rMWLs$9$k$?$a$N%U%)!<%^%C%H$G$9!#$7$+$74pK\E*$K!"%j%9%H$N$h$&$J$b$N\e(B
+\e$B$J$i2?$G$b!"\e(B@acronym{RSS} feed \e$B$H$7$FDs6!$9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B: weblogs\e$B!"\e(Bchangelogs \e$B$"$k$$$O\e(B wiki (\e$BNc$(\e(B
+\e$B$P\e(B @url{http://cliki.net/recent-changes.rdf}) \e$B$X$N:G6a$NJQ99!#\e(B
+
+@acronym{RSS} \e$B$O$H$F$b5,B'E*$+$DNI<A$J%$%s%?!<%U%'!<%9$G!"\e(Bgnus \e$B$,%0%k!<\e(B
+\e$B%W$r>o$K?7$7$/$7$F$*$/$?$a$N>pJs$rF@$k$3$H$,$G$-$^$9!#\e(B
+
+@kindex G R (\e$B35N,\e(B)
+Feed \e$B$r9VFI$9$k$K$O!"35N,%P%C%U%!$+$i\e(B @kbd{G R} \e$B$r;H$C$F2<$5$$\e(B---feed \e$B$N\e(B
+\e$B=j:_$NF~NO$r5a$a$i$l$k$G$7$g$&!#\e(B
+
+\e$B4JC1$K\e(B @code{nnrss} \e$B$r$O$8$a$kJ}K!$O!"%0%k!<%W%P%C%U%!$G\e(B @kbd{B nnrss
+RET y} \e$B$N$h$&$J$3$H$r>'$(!"$=$7$F%0%k!<%W$r9VFI$9$k$3$H$G$9!#\e(B
+
+\e$B0J2<$N\e(B @code{nnrss} \e$BJQ?t$,JQ992DG=$G$9\e(B:
+
+@table @code
+@item nnrss-directory
+@vindex nnrss-directory
+@code{nnrss} \e$B$,%U%!%$%k$r=q$-9~$`%G%#%l%/%H%j!<$G!"%G%#%U%)%k%H\e(B
+\e$B$O\e(B @file{~/News/rss/} \e$B$G$9!#\e(B
+
+@item nnrss-use-local
+@vindex nnrss-use-local
+@findex nnrss-generate-download-script
+@code{nnrss-use-local} \e$B$r\e(B @code{t} \e$B$K@_Dj$9$k$H!"\e(B
+@code{nnrss} \e$B$O\e(B @code{nnrss-directory} \e$B$K$"$k%m!<%+%k%U%!%$%k$+$i\e(B feed
+\e$B$rFI$_$^$9!#\e(B@code{nnrss-generate-download-script}\e$B%3%^%s%I$r;H$&$3$H$K$h$C\e(B
+\e$B$F!"\e(B@command{wget} \e$B$r;H$C$?%@%&%s%m!<%I!&%9%/%j%W%H$r:n$k$3$H$,$G$-$^$9!#\e(B
+@end table
+
+\e$B35N,%P%C%U%!$K@bL@$rI=<($5$;$?$$$J$i$P!"0J2<$N%3!<%I$,Lr$KN)$D$G$7$g$&!#\e(B
+
+@lisp
+(add-to-list 'nnmail-extra-headers nnrss-description-field)
+(setq gnus-summary-line-format "%U%R%z%I%(%[%4L: %-15,15f%]%) %s%uX\n")
+
+(defun gnus-user-format-function-X (header)
+  (let ((descr
+         (assq nnrss-description-field (mail-header-extra header))))
+    (if descr (concat "\n\t" (cdr descr)) "")))
+@end lisp
+
+\e$B0J2<$N%3!<%I$O!"35N,%P%C%U%!$+$iD>@\\e(B nnrss \e$B$N\e(B url \e$B$r%*!<%W%s$9$k$N$KJXMx\e(B
+\e$B$+$b$7$l$^$;$s!#\e(B
+@lisp
+(require 'browse-url)
+
+(defun browse-nnrss-url( arg )
+  (interactive "p")
+  (let ((url (assq nnrss-url-field
+                   (mail-header-extra
+                    (gnus-data-header
+                     (assq (gnus-summary-article-number)
+                           gnus-newsgroup-data))))))
+    (if url
+        (progn
+          (browse-url (cdr url))
+          (gnus-summary-mark-as-read-forward 1))
+      (gnus-summary-scroll-up arg))))
+
+(eval-after-load "gnus"
+  #'(define-key gnus-summary-mode-map
+      (kbd "<RET>") 'browse-nnrss-url))
+(add-to-list 'nnmail-extra-headers nnrss-url-field)
+@end lisp
+
+@node Customizing w3
+@subsection w3 \e$B$N%+%9%?%^%$%:\e(B
+@cindex w3
+@cindex html
+@cindex url
+@cindex Netscape
+
+Gnus \e$B$O%&%'%V%Z!<%8$r<hF@$9$k$?$a$K\e(B url \e$B%i%$%V%i%j$r!"%&%'%V%Z!<%8$rI=<(\e(B
+\e$B$9$k$?$a$K\e(B Emacs/W3 \e$B$r;H$$$^$9!#\e(BEmacs/W3 \e$B$N$3$H$O$=$N%^%K%e%"%k$K5-:\$5\e(B
+\e$B$l$F$$$^$9$,!"$3$3$G$O\e(B Gnus \e$B$N%f!<%6$K$H$C$F$h$jE,@Z$J$$$/$D$+$N;vJA$r=R\e(B
+\e$B$Y$k$3$H$K$7$^$9!#\e(B
+
+\e$BNc$($P!"$h$/$"$k<ALd$K\e(B Emacs/W3 \e$B$K\e(B @code{browse-url} \e$B$N5!G=\e(B (Netscape \e$B$N\e(B
+\e$B$h$&$J30It%W%i%&%6!<$r;H$&$h$&$K@_Dj$5$l$F$$$k\e(B) \e$B$r;H$C$F%j%s%/$r;2>H$5$;\e(B
+\e$B$k$K$O$I$&$7$?$i$h$$$+!"$H$$$&$N$,$"$j$^$9!#0J2<$O0l$D$NJ}K!$G$9!#\e(B
+
+@lisp
+(eval-after-load "w3"
+  '(progn
+    (fset 'w3-fetch-orig (symbol-function 'w3-fetch))
+    (defun w3-fetch (&optional url target)
+      (interactive (list (w3-read-url-with-default)))
+      (if (eq major-mode 'gnus-article-mode)
+          (browse-url url)
+        (w3-fetch-orig url target)))))
+@end lisp
+
+\e$B$3$l$r$"$J$?$N\e(B .emacs \e$B%U%!%$%k$K=q$-9~$`$3$H$K$h$C$F!"\e(BGnus \e$B$N5-;v%P%C%U%!\e(B
+\e$B$G\e(B @acronym{HTML} \e$B%j%s%/$rC!$1$P!"\e(B@code{browse-url} \e$B$r;H$C$F$=$N%j%s%/$r\e(B
+\e$B;2>H$9$k$h$&$K$J$k$G$7$g$&!#\e(B
+
+@node IMAP
+@section IMAP
+@cindex nnimap
+@cindex @acronym{IMAP}
+
+@acronym{IMAP} \e$B$O%a!<%k\e(B (\e$B$b$7$/$O!"%K%e!<%9!"$b$7$/$O\e(B @dots{}) \e$B$rFI$`$?\e(B
+\e$B$a$N%M%C%H%o!<%/%W%m%H%3%k$G$9!#8=BeIw$N\e(B @acronym{NNTP} \e$B$H9M$($F$/$@$5$$!#\e(B
+@acronym{IMAP} \e$B%5!<%P!<$X$N@\B3$O%K%e!<%9%5!<%P!<$X$N@\B3$HHs>o$K;w$F$$\e(B
+\e$B$F!"$=$N%5!<%P!<$N%M%C%H%o!<%/%"%I%l%9$r;XDj$9$k$@$1$K$J$C$F$$$^$9!#\e(B
+
+@acronym{IMAP} \e$B$K$OFs$D$NFC<A$,$"$j$^$9!#0l$D$O!"\e(B
+@acronym{IMAP} \e$B$O\e(B @acronym{POP} \e$B$G$G$-$k$3$H$OA4It$G$-$k!"$=$l$f\e(B
+\e$B$(\e(B @acronym{POP++} \e$B$N$h$&$K$b8+$($k$H$$$&$3$H!#Fs$DL\$O!"\e(B
+@acronym{IMAP} \e$B$O\e(B @acronym{NNTP} \e$B$,%K%e!<%9$rCyB"$9$k%W%m%H%3%k$G$"$k$h\e(B
+\e$B$&$K!"%a!<%k$rCyB"$9$k%W%m%H%3%k$G$"$k$H$$$&$3$H$G$9!#$7$+$7$J$,\e(B
+\e$B$i\e(B @acronym{IMAP} \e$B$O\e(B @acronym{NNTP} \e$B$h$jB?$/$N5!G=$rDs6!$7$^$9!#%K%e!<%9\e(B
+\e$B$OFI$`$@$1$G$9$,!"%a!<%k$OFI$_=q$-$,$G$-$^$9!#\e(B
+
+@acronym{IMAP} \e$B$r\e(B @acronym{POP++} \e$B$N$h$&$K;H$$$?$$$H$-$O!"\e(B
+@code{mail-sources} \e$B$K\e(B imap \e$B$rEPO?$7$F2<$5$$!#$3$l$K$h$C\e(B
+\e$B$F\e(B gnus \e$B$O\e(B @acronym{IMAP} \e$B%5!<%P!<$+$i%a!<%k$r<h$j9~$s$G!"%m!<%+%k%G%#%9\e(B
+\e$B%/$KCyB"$7$^$9!#$3$3$G$O$=$N;H$$J}$N@bL@$O$7$^$;$s$N$G!"\e(B
+@ref{Mail Sources} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@acronym{IMAP} \e$B$r%a!<%k$rCyB"$9$k%W%m%H%3%k$H$7$F;H$$$?$$$H$-$O!"\e(B
+@code{gnus-secondary-select-methods} \e$B$K\e(B nnimap \e$B$rEPO?$7$F2<$5$$!#$3$l$K\e(B
+\e$B$h$C$F\e(B gnus \e$B$O\e(B @acronym{IMAP} \e$B%5!<%P!<$KCyB"$5$l$F$$$k%a!<%k$rA`:n$9$k$h\e(B
+\e$B$&$K$J$j$^$9!#$3$l$,$3$3$G@bL@$9$k;H$$J}$G$9!#\e(B
+
+\e$B$$$/$D$+$N\e(B @acronym{IMAP} \e$B%5!<%P!<$r\e(B @file{~/.gnus.el} \e$B$G@_Dj$9$k$H!"$?\e(B
+\e$B$V$s0J2<$N$h$&$J$b$N$K$J$k$G$7$g$&!#\e(B(\e$BCm\e(B: @acronym{TLS}/@acronym{SSL} \e$B$G\e(B
+\e$B$O30It%W%m%0%i%`$H%i%$%V%i%j$,I,MW$G$9!#0J2<$r;2>H$7$F2<$5$$!#\e(B)
+
+@lisp
+(setq gnus-secondary-select-methods
+      '((nnimap "simpleserver") ; @r{\e$BIaDL$N@_Dj\e(B}
+        ; @r{SSH \e$B%]!<%H$r%U%)%o!<%I$7$?%5!<%P!<\e(B:}
+        (nnimap "dolk"
+                (nnimap-address "localhost")
+                (nnimap-server-port 1430))
+        ; @r{\e$B%m!<%+%k%[%9%H$G1?E>$7$F$$$k\e(B UW \e$B%5!<%P!<\e(B:}
+        (nnimap "barbar"
+                (nnimap-server-port 143)
+                (nnimap-address "localhost")
+                (nnimap-list-pattern ("INBOX" "mail/*")))
+        ; @r{\e$BF?L>$G;H$($k\e(B cyrus \e$B$N8x=0%5!<%P!<\e(B:}
+        (nnimap "cyrus.andrew.cmu.edu"
+                (nnimap-authenticator anonymous)
+                (nnimap-list-pattern "archive.*")
+                (nnimap-stream network))
+        ; @r{\e$BI8=`$G$O$J$$%]!<%H$N\e(B @acronym{SSL} \e$B%5!<%P!<\e(B:}
+        (nnimap "vic20"
+                (nnimap-address "vic20.somewhere.com")
+                (nnimap-server-port 9930)
+                (nnimap-stream ssl))))
+@end lisp
+
+\e$B?7$7$$%5!<%P!<$rDj5A$7$?8e$G!"\e(B@kbd{U} \e$B$N$h$&$J\e(B gnus \e$B$NDL>o$N%3%^%s%I$r%0\e(B
+\e$B%k!<%W%P%C%U%!$G;H$&\e(B (@pxref{Subscription Commands}) \e$B$+!"$^$?$O%5!<%P!<\e(B
+\e$B%P%C%U%!\e(B (@pxref{Server Buffer}) \e$B$r2p$7$F!"$=$N%5!<%P!<$N%0%k!<%W$r9VFI\e(B
+\e$B$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B0J2<$NJQ?t$O2>A[\e(B @code{nnimap} \e$B%5!<%P!<$r:n@.$9$k$?$a$K;H$&$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+@table @code
+@item nnimap-address
+@vindex nnimap-address
+
+\e$B1s3V\e(B @acronym{IMAP} \e$B%5!<%P!<$N%"%I%l%9$G$9!#;XDj$5$l$F$$$J$$>l9g$O2>A[%5!<\e(B
+\e$B%P!<$N$b$N$K$J$j$^$9!#\e(B
+
+@item nnimap-server-port
+@vindex nnimap-server-port
+\e$B@\B3$r;n$_$k%5!<%P!<$N%]!<%H$G$9!#%G%#%U%)%k%H$O%]!<%H\e(B 143\e$B!"$^$?\e(B
+\e$B$O\e(B @acronym{TLS}/@acronym{SSL} \e$B$G$O\e(B 993 \e$B$G$9!#\e(B
+
+\e$B$3$l$O@0?t$G$J$1$l$P$J$j$^$;$s!#0J2<$O%5!<%P!<;XDj$NNc$G$9!#\e(B
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-server-port 4711))
+@end lisp
+
+@item nnimap-list-pattern
+@vindex nnimap-list-pattern
+\e$B;HMQ2DG=$J%a!<%k%\%C%/%9$r@)8B$9$k$?$a$NJ8;zNs$+%j%9%H$G$9!#$3$l$O!"%5!<\e(B
+\e$B%P!<$KHs>o$KB?$/$N%a!<%k%\%C%/%9$,$"$k$1$l$I!"6=L#$N$"$k$b$N$O>/$7$@$1$G\e(B
+\e$B$"$k$H$-$K;HMQ$7$^$9!#%5!<%P!<$K$O%[!<%`%G%#%l%/%H%j!<\e(B
+\e$B$r\e(B @acronym{IMAP} \e$B7PM3$G=P$9$b$N$b$"$j$^$9$N$G!"$=$N>l9g$O$*$=$i$/%a!<%k\e(B
+\e$B%\%C%/%9$r\e(B @file{~/Mail/*} \e$B$K@)8B$7$?$$$G$7$g$&!#\e(B
+
+\e$BJ8;zNs$O\e(B REFERENCE \e$B$H>e$NJ8;zNs$H$N\e(B cons \e$B$G$"$k$3$H$b$G$-$^$9!#$I\e(B
+\e$B$N\e(B REFERENCE \e$B$,;HMQ$5$l$k$+$O%5!<%P!<FCM-$G$9$,!"%o%7%s%H%sBg3X$N%5!<%P!<\e(B
+\e$B$G$O!"%a!<%k%\%C%/%9$HO"7k$5$l$?%G%#%l%/%H%j!<$G$9!#\e(B
+
+\e$B0J2<$O%5!<%P!<;XDj$NNc$G$9!#\e(B
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-list-pattern ("INBOX" "Mail/*" "alt.sex.*"
+                               ("~friend/Mail/" . "list/*"))))
+@end lisp
+
+@item nnimap-stream
+@vindex nnimap-stream
+\e$B%5!<%P!<$K@\B3$9$k$H$-$K;H$o$l$k%9%H%j!<%`$N7?$G$9!#=i4|@_Dj$G\e(B
+\e$B$O\e(B nnimap \e$B$O\e(B @acronym{TLS}/@acronym{SSL} \e$B$r=|$/0J2<$N$9$Y$F$r<+F0E*$K8!\e(B
+\e$BCN$7$F$=$l$r;H$$$^$9!#\e(B(@acronym{TLS}/@acronym{SSL} \e$B$r;H\e(B
+\e$B$&\e(B @acronym{IMAP} \e$B$O\e(B STARTTLS \e$B$GCV$-49$($i$l$F$$$^$9!#$3$l$O<+F08!=P$G$-\e(B
+\e$B$^$9$,!"$^$@9-HO0O$KG[Hw$5$l$F$$$^$;$s!#\e(B)
+
+\e$B0J2<$O%5!<%P!<;XDj$NNc$G$9!#\e(B
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-stream ssl))
+@end lisp
+
+@code{nnimap-stream} \e$B$NCM$O%7%s%\%k$G$J$1$l$P$J$i$J$$$3$H$KCm0U$7$F2<$5\e(B
+\e$B$$\e(B!
+
+@itemize @bullet
+@item
+@dfn{gssapi:} GSSAPI (\e$BIaDL$O\e(B Kerberos 5) \e$B$r;H$$$^$9!#\e(B@samp{gsasl} \e$B$^$?\e(B
+\e$B$O\e(B @samp{imtest} \e$B%W%m%0%i%`$,I,MW$G$9!#\e(B
+@item
+@dfn{kerberos4:} Kerberos 4 \e$B$r;H$$$^$9!#\e(B@samp{imtest} \e$B%W%m%0%i%`$,I,MW$G\e(B
+\e$B$9!#\e(B
+@item
+@dfn{starttls:} STARTTLS (@acronym{TLS}/@acronym{SSL} \e$B$KN`;w\e(B) \e$B$r;H$$$^$9!#\e(B
+\e$B30It%i%$%V%i%j\e(B @samp{starttls.el} \e$B$H\e(B @samp{starttls} \e$B%W%m%0%i%`$,I,MW$G\e(B
+\e$B$9!#\e(B
+@item
+@dfn{tls:} @acronym{TLS} \e$B$r;H$$$^$9!#\e(BGNUTLS (@samp{gnutls-cli} \e$B%W%m%0%i\e(B
+\e$B%`\e(B) \e$B$,I,MW$G$9!#\e(B
+@item
+@dfn{ssl:} @acronym{SSL} \e$B$r;H$$$^$9!#\e(BOpenSSL (@samp{openssl} \e$B%W%m%0%i\e(B
+\e$B%`\e(B) \e$B$+\e(B SSLeay (@samp{s_client}) \e$B$,I,MW$G$9!#\e(B
+@item
+@dfn{shell:} \e$B%7%'%kL?Na$r;H$C$F\e(B @acronym{IMAP} \e$B@\B3$r3+;O$7$^$9!#\e(B
+@item
+@dfn{network:} \e$B@8$N!"\e(BTCP/IP \e$B$N%M%C%H%o!<%/@\B3$G$9!#\e(B
+@end itemize
+
+@vindex imap-kerberos4-program
+@samp{imtest} \e$B%W%m%0%i%`$O\e(B Cyrus IMAPD \e$B$K4^$^$l$F$$$^$9!#$b$7$"$J$?\e(B
+\e$B$,\e(B 2.0.14 \e$BL$K~$N\e(B Cyrus IMAPD \e$B$K4^$^$l$F$$$k\e(B @samp{imtest} (\e$B%P!<%8%g\e(B
+\e$B%s\e(B 1.5.x \e$B$H\e(B 1.6.x) \e$B$r;H$C$F$$$k$J$i!"\e(B
+@code{imap-process-connection-type} \e$B$r$$$8$j2s$7$F!"\e(B
+@file{imap.el} \e$B$,\e(B @samp{imtest} \e$B$HDL?.$9$k$H$-$K%Q%$%W$G$O$J$/\e(B
+\e$B$F\e(B pty \e$B$r;H$&$h$&$K$5$;$kI,MW$,$"$j$^$9!#$=$&$9$k$H$"$J$?\e(B
+\e$B$O\e(B @acronym{IMAP} \e$B%3%^%s%I$N9T$ND9$5$N@)8B$KG:$^$5$l$k$G$7$g$&!#$=$l$O%a!<\e(B
+\e$B%k%\%C%/%9$K$?$/$5$s$N5-;v$,$"$k$H$-$K\e(B Gnus \e$B$rL54|8B$K%O%s%0$5$;$F$7$^$&\e(B
+\e$B$+$b$7$l$^$;$s!#JQ?t\e(B @code{imap-kerberos4-program} \e$B$O\e(B imtest \e$B%W%m%0%i%`\e(B
+\e$B$KEO$9%Q%?%a!<%?$r4^$_$^$9!#\e(B
+
+@acronym{TLS} \e$B@\B3$G$O\e(B GNUTLS \e$BM3Mh$N\e(B @code{gnutls-cli} \e$B%W%m%0%i%`$,I,MW\e(B
+\e$B$G$9!#$3$l$O\e(B @uref{http://www.gnu.org/software/gnutls/} \e$B$+$i<j$KF~$l$k$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+@vindex imap-gssapi-program
+\e$B$3$N%Q%i%a!<%?$O!"I{%7%'%k$G\e(B GSSAPI \e$BG'>Z$K$h$k\e(B @acronym{IMAP} \e$B@\B3$r5/F0\e(B
+\e$B$9$k$?$a$N%3%^%s%I9T$N%j%9%H$r;XDj$7$^$9!#$3$l$i$O@\B3$,3NN)$9$k$^$G!"$^\e(B
+\e$B$?$O%j%9%H$,;H$$?T$/$5$l$k$^$G!"=g$0$j$K;n$5$l$^$9!#%G%#%U%)%k%H$G$O!"\e(B
+@uref{http://www.gnu.org/software/gsasl/} \e$B$K$"$k\e(B GNU SASL \e$B$K$h\e(B
+\e$B$k\e(B @samp{gsasl} \e$B$H!"\e(BCyrus IMAPD \e$B$K$h$k\e(B @samp{imtest} \e$B%W%m%0%i\e(B
+\e$B%`\e(B (@code{imap-kerberos4-program} \e$B;2>H\e(B) \e$B$,;n$5$l$^$9!#\e(B
+
+@vindex imap-ssl-program
+@acronym{SSL} \e$B@\B3$N$?$a$N\e(B OpenSSL \e$B%W%m%0%i%`\e(B
+\e$B$O\e(B @uref{http://www.openssl.org/} \e$B$+$iF~<j$G$-$^$9!#\e(BOpenSSL \e$B$O0JA0\e(B
+\e$B$O\e(B SSLeay \e$B$H$7$FCN$i$l$F$$$?$b$N$G!"\e(Bnnimap \e$B$O$=$l$b%5%]!<%H$7$^$9!#$7$+\e(B
+\e$B$7!"\e(BSSLeay \e$B$N:G?7HG$G$"$k\e(B 0.9.x \e$B$K$O=EBg$J%P%0$,$"$k$?$a;H$($^$;$s!#0JA0\e(B
+\e$B$NHG!"FC$K\e(B SSLeay 0.8.x \e$B$O;H$($k$3$H$,$o$+$C$F$$$^$9!#JQ\e(B
+\e$B?t\e(B @code{imap-ssl-program} \e$B$O\e(B OpenSSL/SSLeay \e$B$KEO$9%Q%?%a!<%?$r4^$_$^$9!#\e(B
+
+@vindex imap-shell-program
+@vindex imap-shell-host
+@acronym{IMAP} \e$B@\B3$K\e(B @code{shell} \e$B%9%H%j!<%`$r;H$&>l9g!"JQ\e(B
+\e$B?t\e(B @code{imap-shell-program} \e$B$O2?$N%W%m%0%i%`$r8F$V$+$r;XDj$7$^$9!#\e(B
+
+@item nnimap-authenticator
+@vindex nnimap-authenticator
+
+\e$B%5!<%P!<$K@\B3$9$k$?$a$K;H$o$l$kG'>Z$G$9!#=i4|@_Dj$G$O!"\e(Bnnimap \e$B$O%5!<%P!<\e(B
+\e$B$,;HMQ2DG=$J0lHV0BA4$JG'>Z$r;HMQ$7$^$9!#\e(B
+
+\e$B0J2<$O%5!<%P!<;XDj$NNc$G$9!#\e(B
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-authenticator anonymous))
+@end lisp
+
+@code{nnimap-authenticator} \e$B$NCM$O%7%s%\%k$G$J$1$l$P$J$i$J$$$3$H$KCm0U$7\e(B
+\e$B$F2<$5$$\e(B!
+
+@itemize @bullet
+@item
+@dfn{gssapi:} GSSAPI (\e$BIaDL$O\e(B Kerberos 5) \e$BG'>Z$G$9!#30It%W%m%0%i\e(B
+\e$B%`\e(B @code{gsasl} \e$B$^$?$O\e(B @code{imtest} \e$B$,I,MW$G$9!#\e(B
+@item
+@dfn{kerberos4:} Kerberos 4 \e$B$K$h$kG'>Z$G$9!#30It%W%m%0%i\e(B
+\e$B%`\e(B @code{imtest} \e$B$,I,MW$G$9!#\e(B
+@item
+@dfn{digest-md5:} DIGEST-MD5 \e$B$G0E9f2=$5$l$?\e(B \e$BMxMQ<TL>\e(B/\e$B%Q%9%o!<%I\e(B \e$B$G$9!#30\e(B
+\e$BIt%i%$%V%i%j\e(B @file{digest-md5.el} \e$B$,I,MW$G$9!#\e(B
+@item
+@dfn{cram-md5:} CRAM-MD5 \e$B$G0E9f2=$5$l$?\e(B \e$BMxMQ<TL>\e(B/\e$B%Q%9%o!<%I\e(B \e$B$G$9!#\e(B
+@item
+@dfn{login:} LOGIN \e$B7PM3$G$N@8$N\e(B \e$BMxMQ<TL>\e(B/\e$B%Q%9%o!<%I\e(B \e$B$G$9!#\e(B
+@item
+@dfn{anonymous:} \e$BEE;R%a!<%k%"%I%l%9$r%Q%9%o!<%I$H$7$FM?$(!"\e(B
+``anonymous'' \e$B$H$7$F%m%0%$%s$7$^$9!#\e(B
+@end itemize
+
+@item nnimap-expunge-on-close
+@cindex expunging
+@vindex nnimap-expunge-on-close
+
+\e$B%Q%k%a%K%G%9$H0c$C$F!"\e(B@acronym{IMAP} \e$B$N@_7W<TC#$O!"B8:_$7$F$$$J$$$b$N$,\e(B
+\e$B<B:]$K$OB8:_$7$F$$$k$H7h$a$^$7$?!#$b$C$H>\$7$/@bL@$9$k$H!"\e(B
+@acronym{IMAP} \e$B$O<B:]$K$O5-;v$r>C5n$7$J$$!"5-;v$K\e(B @code{Deleted} \e$B$H$$$&\e(B
+\e$B0u$rIU$1$k35G0$,$"$j!"$3$l\e(B (\e$B$($C$H!"\e(B@code{Deleted} \e$B$H$$$&0u$rIU$1$k$3$H\e(B
+\e$B$G$9\e(B) \e$B$,\e(B nnimap \e$B$,\e(B Gnus \e$B$G5-;v$r>C5n$9$k$H$-$K$9$k$3$H$G\e(B
+\e$B$9\e(B (@kbd{B DEL} \e$B$J$I$G\e(B)\e$B!#\e(B(\e$BLuCm\e(B: \e$B%Q%k%a%K%G%9$O5*85A0\e(B 5 \e$B@$5*$N%.%j%7%"\e(B
+\e$B$N\e(B Elea \e$BGI$NE/3X<T\e(B)
+
+\e$B5-;v$r\e(B @code{Deleted} \e$B%U%i%0$G0u$rIU$1$?$H$-$K$OK\Ev$O>C5n$5$l$F$$$J$$$N\e(B
+\e$B$G!"<B:]$K>C5n$9$k$?$a$NJ}K!$,I,MW$H$J$j$^$9!#=[4D$7$F$$$k$h$&$K46$8$^$9\e(B
+\e$B$+\e(B?
+
+\e$BEAE}E*$K!"\e(Bnnimap \e$B$O%a!<%k%\%C%/%9$rJD$8$k$H$-$K\e(B @code{Deleted} \e$B$H$$$&0u\e(B
+\e$B$NIU$$$?A4$F$N5-;v$r>C5n$7$F$-$^$7$?$,!":#$O%5!<%P!<JQ?t$K$h$j@_Dj2DG=$G\e(B
+\e$B$9!#\e(B
+
+\e$BA*Br;h$O\e(B:
+
+@table @code
+@item always
+\e$B=i4|@_Dj$N?6Iq$$!"%a!<%k%\%C%/%9$rJD$8$k$H$-$K\e(B ``Deleted'' \e$B$H0u$NIU$$$?\e(B
+\e$B5-;v$r>C5n$7$^$9!#\e(B
+@item never
+\e$B7h$7$F5-;v$r>C5n$7$^$;$s!#8=:_$O!">C5n$N0u$,IU$$$?5-;v$r\e(B nnimap \e$B$GI=<($9\e(B
+\e$B$kJ}K!$O$"$j$^$;$s$,!"B>$N\e(B @acronym{IMAP} \e$B%/%i%$%"%s%H$O$G$O$G$-$k$+$b$7\e(B
+\e$B$l$^$;$s!#<j$G\e(B EXPUNGE \e$B%3%^%s%I$rH/9T$7$?$$$H$-\e(B
+\e$B$O\e(B @xref{Expunging mailboxes}.
+@item ask
+\e$B%a!<%k%\%C%/%9$rJD$8$k$H$-$K!"\e(Bnnimap \e$B$,>C5n$5$l$?5-;v$r:o=|$9$k$+$I$&$+\e(B
+\e$B$r?R$M$^$9!#\e(B
+@end table
+
+@item nnimap-importantize-dormant
+@vindex nnimap-importantize-dormant
+
+\e$BHs\e(B-@code{nil} (\e$B%G%#%U%)%k%H\e(B) \e$B$@$C$?$i!"B>$N\e(B @acronym{IMAP} \e$B%/%i%$%"%s%H\e(B
+\e$B$N$?$a$KJ]N15-;v$r0uIU$-$H$7$F$b0u$rIU$1$^$9!#\e(Bgnus \e$B$NFbIt$G$O!"J]N15-;v\e(B
+\e$B$O85!9$9$G$KJ]N15-;v$H$7$F$N$_0u$,IU$1$i$l$F$$$^$9!#$3$l$O!"B>\e(B
+\e$B$N\e(B @acronym{IMAP} \e$B%/%i%$%"%s%H$K$*$1$kJ]N15-;v$r!"$"$?$+$b0uIU$-$N$h$&$K\e(B
+\e$B$-$oN)$?$;$^$9!#\e(B(\e$BJL$N8@$$J}$r$9$k$H!"\e(Bgnus \e$B$OFs$D$N0u$rIU$1!"\e(B
+@acronym{IMAP} \e$B$O$?$C$?0l$D$@$H$$$&$3$H$G$9!#\e(B)
+
+\e$B$?$V$s$3$l$r$$$8$j$^$o$9$N$O!"$"$J$?$,%f!<%6C10L$NJ]N1%U%i%0$rIU$1$h$&$H\e(B
+\e$B$9$k$@$1$NM}M3$K$h$k$G$7$g$&!#$3$s$J46$8$G\e(B:
+
+@lisp
+(setcdr (assq 'dormant nnimap-mark-to-flag-alist)
+        (format "gnus-dormant-%s" (user-login-name)))
+(setcdr (assq 'dormant nnimap-mark-to-predicate-alist)
+        (format "KEYWORD gnus-dormant-%s" (user-login-name)))
+@end lisp
+
+\e$B$3$N>l9g!"$"$J$?$O%f!<%6C10L$NJ]N1%U%i%0$r!"B>$N%f!<%6$K0uIU$-$H$7$F8+$i\e(B
+\e$B$l$?$/$J$$$H;W$C$F$$$^$9!#\e(B
+
+@item nnimap-expunge-search-string
+@cindex expunging
+@vindex nnimap-expunge-search-string
+
+\e$B$3$NJQ?t$K$O!"4|8B@Z$l>C5n$9$k$N$,K>$^$7$$5-;v$rC5$9$H$-$K%5!<%P!<$KAw$C\e(B
+\e$B$?\e(B @acronym{IMAP} \e$B$N8!:w%3%^%s%I$,F~$C$F$$$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{"UID %s NOT SINCE %s"} \e$B$G!"$3$3$G:G=i$N\e(B @code{%s} \e$B$O\e(B UID \e$B$GCV$-\e(B
+\e$B49$($i$l!"FsHVL\$N\e(B @code{%s} \e$B$OF|IU$GCV$-49$($i$l$^$9!#\e(B
+
+\e$B$?$V$s;H$$$b$N$K$J$kJL$NCM$O\e(B @code{"UID %s NOT SENTSINCE %s"} \e$B$G!"\e(B
+nnimap \e$B$K5-;v$NFbItE*$JF|IU$NBe$o$j$K\e(B Date: \e$B$r;H$&$h$&$K$5$;$^$9!#$5$i$J\e(B
+\e$B$k>pJs$d;H$&$3$H$,$G$-$kJ8;zNs$K$D$$$F$O!"\e(BRFC 2060 \e$B$N%;%/%7%g%s\e(B 6.4.4 \e$B$r\e(B
+\e$B8+$F$/$@$5$$!#\e(B
+
+@item nnimap-authinfo-file
+@vindex nnimap-authinfo-file
+
+\e$B%5!<%P$K%m%0%$%s$9$k$?$a$K;H$&G'>Z>pJs\e(B (authinfo) \e$B$r4^$`%U%!%$%k$G$9!#$=\e(B
+\e$B$N7A<0$O\e(B (\e$B$[$H$s$I\e(B) @code{ftp} \e$B$N\e(B @file{~/.netrc} \e$B%U%!%$%k$HF1$8$G$9!#87\e(B
+\e$BL)$JDj5A$O!"JQ?t\e(B @code{nntp-authinfo-file} \e$B$r8+$F2<$5$$!#$=$7\e(B
+\e$B$F\e(B @ref{NNTP} \e$B$b8+$F2<$5$$!#\e(B
+
+@item nnimap-need-unselect-to-notice-new-mail
+@vindex nnimap-need-unselect-to-notice-new-mail
+
+\e$B?7Ce%a!<%k$rC5$9A0$K%a!<%k%\%C%/%9$rL$A*Br$K$7$^$9!#2?$i$+$N>u67$N85$G!"\e(B
+\e$B4v$i$+$N%5!<%P!<$,!"$3$l$rI,MW$H$9$k$h$&$G$9!#\e(BCourier 1.7.1 \e$B$O$=$&$@$H$$\e(B
+\e$B$&Js9p$,$"$j$^$7$?!#\e(B
+@end table
+
+@menu
+* Splitting in IMAP::           nnimap \e$B$G%a!<%k$rJ,3d$9$k\e(B
+* Expiring in IMAP::            nnimap \e$B$K$h$k%a!<%k$N4|8B@Z$l>C5n\e(B
+* Editing IMAP ACLs::           \e$B%a!<%k%\%C%/%9$X$NB>$NMxMQ<T$N;HMQ$r@)8B\e(B/\e$B5v2D$9$k\e(B
+* Expunging mailboxes::         ``\e$B%a!<%k%\%C%/%905=L\e(B'' \e$B%\%?%s$HEy2A$J$b$N\e(B
+* A note on namespaces::        gnus \e$B$G\e(B @acronym{IMAP} \e$BL>A06u4V$r;H$&\e(B(\e$B;H$o$J$$\e(B)\e$BJ}K!\e(B
+* Debugging IMAP::              \e$B$b$N$4$H$,F/$+$J$$$H$-$K$9$k$Y$-$3$H\e(B
+@end menu
+
+@node Splitting in IMAP
+@subsection IMAP \e$B$G$NJ,3d\e(B
+@cindex splitting imap mail
+
+\e$BJ,3d$O\e(B gnus \e$B$NMxMQ<T$,2?G/$b$N4V0&$7$F$-$?$b$N$G!":#$d;D$j$N@$3&$bDI$$$D\e(B
+\e$B$3$&$H$7$F$$$^$9!#$O$$!"A[A|$7$F$/$@$5$$!"\e(B@acronym{IMAP} \e$B%5!<%P!<$NCf$K\e(B
+\e$B%5!<%P!<B&$GJ,3d$G$-$k$b$N$O$"$^$jB?$/$J$/!"$7$+$b$=$l$i$OI8=`$G$J$$%W%m\e(B
+\e$B%H%3%k$r;H$C$F$$$k$h$&$G$9!#$3$l$O!"\e(Bgnus \e$B$N\e(B @acronym{IMAP} \e$B%5%]!<%H$O<+\e(B
+\e$BJ,<+?H$GJ,3d$r$7$J$1$l$P$J$i$J$$$H$$$&$3$H$G$9!#\e(B
+
+\e$B$=$7$F<B:]$K$7$^$9!#\e(B
+
+(\e$B$D$$$G$K8@$($P!"$_$s$J$,L48+$F$$$?$N$G$7$g$&$M!#$=$N7k2L\e(B Sieve \e$B$O;T>l@j\e(B
+\e$BM-N($rA}$7$F!"$$$/$D$b$N\e(B IMAP \e$B%5!<%P!<$K$h$C$F%5%]!<%H$5$l$k$h$&$K$J$j$^\e(B
+\e$B$7$?!#9,$$$K\e(B gnus \e$B$b$=$l$r%5%]!<%H$7$^$9!#\e(B@xref{Sieve Commands}.)
+
+\e$B4XO"$9$kJQ?t$O;0$D$G$9\e(B:
+
+@table @code
+@item nnimap-split-crosspost
+@cindex splitting, crosspost
+@cindex crosspost
+@vindex nnimap-split-crosspost
+
+@code{nil} \e$B$G$J$1$l$P!"$$$/$D$+$NJ,3dJ}K!$,%a!<%k$H9gCW$7$?$H$-$KAj8_Ej\e(B
+\e$B9F$r$7$^$9!#\e(B@code{nil} \e$B$J$i$P!"\e(B@code{nnimap-split-rule} \e$B$G:G=i$K8+$D$+$C\e(B
+\e$B$?$b$N$,;H$o$l$^$9!#\e(B
+
+Nnmail \e$B$GBP1~$9$k$b$N\e(B: @code{nnmail-crosspost}.
+
+@item nnimap-split-inbox
+@cindex splitting, inbox
+@cindex inbox
+@vindex nnimap-split-inbox
+
+\e$BJ,3d$N85$H$J$k\e(B @acronym{IMAP} \e$B$N%a!<%k%\%C%/%9$NL>A0$r;XDj$7$?J8;zNs$+J8\e(B
+\e$B;zNs$N%j%9%H$G$9!#=i4|CM$O\e(B @code{nil} \e$B$G!"J,3d$O;HMQ$7$J$$$h$&$K$J$C$F$$\e(B
+\e$B$^$9\e(B!
+
+@lisp
+(setq nnimap-split-inbox
+      '("INBOX" ("~/friend/Mail" . "lists/*") "lists.imap"))
+@end lisp
+
+Nnmail \e$B$KBP1~$9$k$b$N$O$"$j$^$;$s!#\e(B
+
+@item nnimap-split-rule
+@cindex splitting, rules
+@vindex nnimap-split-rule
+
+@code{nnimap-split-inbox} \e$B$G8+$D$+$C$??7$7$$%a!<%k$O$3$NJQ?t$K=>$C$FJ,3d\e(B
+\e$B$5$l$^$9!#\e(B
+
+\e$B$3$NJQ?t$O%j%9%H$N%j%9%H$+$i@.$j$^$9!#I{%j%9%H$N:G=i$NMWAG\e(B
+\e$B$O\e(B @acronym{IMAP} \e$B$N%a!<%k%\%C%/%9$G!"Fs$D$a$NMWAG$N@55,I=8=$K9gCW$7$?5-\e(B
+\e$B;v$N0\F0@h$r;XDj$7$^$9!#$o$+$j$^$7$?$+\e(B? \e$B$$$$$(!";d$b$o$+$j$^$;$s!#Nc$,I,\e(B
+\e$BMW$G$9!#\e(B
+
+@lisp
+(setq nnimap-split-rule
+      '(("INBOX.nnimap"
+         "^Sender: owner-nnimap@@vic20.globalcom.se")
+        ("INBOX.junk"    "^Subject:.*MAKE MONEY")
+        ("INBOX.private" "")))
+@end lisp
+
+\e$B$3$l$O\e(B nnimap \e$B%a!<%j%s%0%j%9%H$+$i$NA4$F$N5-;v$r%a!<%k%\%C%/\e(B
+\e$B%9\e(B INBOX.nnimap \e$B$KF~$l!"\e(BSubject: \e$B9T$K\e(B MAKE MONEY \e$B$N$"$kA4$F$N5-;v\e(B
+\e$B$r\e(B INBOX.junk \e$B$KF~$l!"$=$NB>A4$F$N$b$N$r\e(B INBOX.private \e$B$KF~$l$^$9!#\e(B
+
+\e$B:G=i$NJ8;zNs$O!"\e(Breplace-match \e$B$G9gCW$7$?%F%-%9%H$+$iI{I=8=$rA^F~$9$k$H$-\e(B
+\e$B$K;HMQ$5$l$k$N$HF1$8$h$&$J!"\e(B@samp{\\1} \e$B7A<0$r4^$`$3$H$,$G$-$^$9!#Nc$($P\e(B:
+
+@lisp
+("INBOX.lists.\\1"     "^Sender: owner-\\([a-z-]+\\)@@")
+@end lisp
+
+\e$B:G=i$NMWAG$r%7%s%\%k\e(B @code{junk} \e$B$K$7$F!"%^%C%A$9$k%a%C%;!<%8$rC1$K>C$9\e(B
+\e$B$Y$-$G$"$k$3$H$rI=$9$3$H$b$G$-$^$9!#5$$rIU$1$F;H$C$F2<$5$$!#\e(B
+
+\e$BFs$DL\$NMWAG$O4X?t$G$"$k$3$H$b$G$-$^$9!#$=$N>l9g$O!"5-;v$N%X%C%@!<$,$"$k\e(B
+\e$B%P%C%U%!$G!"$=$N5,B'$N:G=i$NMWAG$r0z?t$H$7$F8F$P$l$^$9!#%a!<%k$,$=$N%0%k!<\e(B
+\e$B%W$KB0$9$k$H9M$($k>l9g$O!"\e(B@code{nil} \e$B$G$J$$CM$rJV$9I,MW$,$"$j$^$9!#\e(B
+
+Nnmail \e$B$NMxMQ<T$O:G8e$N@55,I=8=$OA4$F$N5-;v$K9gCW$9$k$h$&$K6u$G$J$/$F$O\e(B
+\e$B$J$i$J$$$3$H$r3P$($F$$$k$+$b$7$l$^$;$s\e(B (\e$B>e$NNc$N$h$&$K\e(B)\e$B!#$3$l\e(B
+\e$B$O\e(B nnimap \e$B$G$OI,MW$G$O$"$j$^$;$s!#@55,I=8=$N$I$l$K$b9gCW$7$J$$5-;v\e(B
+\e$B$O\e(B inbox \e$B$+$i0\F0$5$l$^$;$s!#\e(B(inbox \e$B$KL$FI5-;v$rBgNL$KCV$$$F$*$/$H!"J,3d\e(B
+\e$B$N%3!<%I$O?7$7$$%a!<%k$r<hF@$9$k$H$-$K$=$l$iA4$F$rD4$Y$k$N$G!"<B9TB.EY$K\e(B
+\e$B1F6A$9$k2DG=@-$,$"$j$^$9!#\e(B)
+
+\e$B$3$l$i$N5,B'$OO"A[%j%9%H$N:G=i$+$i=*$j$K8~$+$C$F<B9T$5$l$^$9!#Aj8_Ej9F$,\e(B
+\e$B;HMQ2DG=$K$J$C$F$$$J$$$+$.$j!":G=i$K9gCW$7$?5,B'$,\e(B ``\e$B>!$A\e(B'' \e$B$^$9!#Aj8_Ej\e(B
+\e$B9F$r$7$F$$$k>l9g$O!"A4$F$N9gCW$7$?5,B'$,\e(B ``\e$B>!$A\e(B'' \e$B$^$9!#\e(B
+
+\e$B$3$NJQ?t$O$=$NCM$H$7$F4X?t$r;}$D$3$H$b$G$-$^$9!#$=$N4X?t$O5-;v$N%X%C%@$N\e(B
+\e$BItJ,$KHO0O$,69$a$i$l$?>uBV$G8F$P$l!"5-;v$N0\F0@h$@$H;W$&%0%k!<%W$rJV$9$b\e(B
+\e$B$N$G$J$1$l$P$J$j$^$;$s!#\e(B@code{nnimap-split-fancy} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+\e$BJ,3d%3!<%I$OI,MW$J$i%a!<%k%\%C%/%9$r:n@.$7$^$9!#\e(B
+
+\e$B0[$J$k2>A[%5!<%P!<Kh$K0c$&J,3d$N5,B'$r;H$C$?$j!"$=$l$I$3$m$+F1$8%5!<%P!<\e(B
+\e$B$N0[$J$k\e(B inbox \e$BKh$K0c$&J,3d$N5,B'$r;H$&$3$H$,$G$-$k$h$&$K$9$k$?$a$K!"$3\e(B
+\e$B$NJQ?t$N9=J8$O0J2<$N$h$&$K3HD%$5$l$F$$$^$9!#\e(B
+
+@lisp
+(setq nnimap-split-rule
+      '(("my1server"    (".*"    (("ding"    "ding@@gnus.org")
+                                  ("junk"    "From:.*Simon")))
+        ("my2server"    ("INBOX" nnimap-split-fancy))
+        ("my[34]server" (".*"    (("private" "To:.*Simon")
+                                  ("junk"    my-junk-func)))))
+@end lisp
+
+\e$B2>A[%5!<%P!<L>$O<B:]$K$O@55,I=8=$J$N$G!"F1$85,B'$r$$$/$D$+$N%5!<%P!<$KE,\e(B
+\e$BMQ$G$-$k$G$7$g$&!#$3$NNc$G$O%5!<\e(B
+\e$B%P!<\e(B @code{my3server} \e$B$H\e(B @code{my4server} \e$B$,F1$85,B'$r;H$$$^$9!#F1MM\e(B
+\e$B$K\e(B inbox \e$BJ8;zNs$b@55,I=8=$G$9!#>e5-$NJ,3d$N5,B'$N<BNc$O!"4X?t!"$^$?$O%0\e(B
+\e$B%k!<%W$N@55,I=8=$+%0%k!<%W$N4X?t!"$NN>J}$G$9!#\e(B
+
+Nnmail \e$B$GBP1~$9$k$b$N\e(B: @code{nnmail-split-methods}.
+
+@item nnimap-split-predicate
+@cindex splitting
+@vindex nnimap-split-predicate
+
+\e$B$3$N=R8l$K%^%C%A$9$k\e(B @code{nnimap-split-inbox} \e$B$K$"$k%a!<%k$OJ,3d$5$l$^\e(B
+\e$B$9!#$3$l$OJ8;zNs$G4{DjCM$O\e(B @samp{UNSEEN UNDELETED} \e$B$G$9!#\e(B
+
+\e$B$b$7$"$J$?$,\e(B inbox \e$B$K$"$k%a!<%k$rFI$`$?$a$KJL$N\e(B @acronym{IMAP} \e$B%/%i%$%"\e(B
+\e$B%s%H$r;H$C$F$$$k$,!"9XFIEY$K4X$o$i$:$K$9$Y$F$N5-;v$r\e(B gnus \e$B$KJ,3d$5$;$?$$\e(B
+\e$B$J$i$P!"$3$l$OLr$KN)$D$+$b$7$l$^$;$s!#$=$N>l9g$O\e(B @samp{UNDELETED} \e$B$KJQ$(\e(B
+\e$B$l$PNI$$$G$7$g$&!#\e(B
+
+@item nnimap-split-fancy
+@cindex splitting, fancy
+@findex nnimap-split-fancy
+@vindex nnimap-split-fancy
+
+\e$B$b$7$"$J$?$,FC5iJ,3d$r;H$$$?$$$J$i$P!"\e(B@code{nnimap-split-rule} \e$B$NCM\e(B
+\e$B$r\e(B @code{nnmail-split-fancy} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+@xref{Fancy Mail Splitting}.
+
+\e$B$7$+$7\e(B nnmail \e$B$H\e(B nnimap \e$B$H$G0[$J$kFC5iJ,3dJ}<0$r;}$D$h$&$K$9$k$K$O!"\e(B
+@code{nnimap-split-rule} \e$B$NCM$r\e(B @code{nnimap-split-fancy} \e$B$K@_Dj$7$F!"\e(B
+nnimap \e$BFCM-$NFC5iJ,3dJ}<0$r\e(B @code{nnimap-split-fancy} \e$B$KDj5A$7$F2<$5$$!#\e(B
+
+\e$BNc\e(B:
+
+@lisp
+(setq nnimap-split-rule 'nnimap-split-fancy
+      nnimap-split-fancy ...)
+@end lisp
+
+Nnmail \e$B$GBP1~$9$k$b$N\e(B: @code{nnmail-split-fancy}.
+
+@item nnimap-split-download-body
+@findex nnimap-split-download-body
+@vindex nnimap-split-download-body
+
+\e$BJ,3d$7$F$$$k$H$-$K$9$Y$F$N5-;v$r%@%&%s%m!<%I$9$k$K$OHs\e(B-@code{nil} \e$B$K@_Dj\e(B
+\e$B$7$F2<$5$$!#$3$l$OIaDL$OI,MW$G$O$J$/!"J*;v$rAjEv$KCY$/$7$F$7$^$&$G$7$g$&!#\e(B
+\e$B5-;v$rJ,3d$9$k$?$a$KK\J8$rJ,@O$9$k9bEY$J4X?t$r;H$$$?$$>l9g$K$O!"I,MW$+$b\e(B
+\e$B$7$l$^$;$s!#\e(B
+@end table
+
+@node Expiring in IMAP
+@subsection IMAP \e$B$G$N4|8B@Z$l>C5n\e(B
+@cindex expiring imap mail
+
+@code{nnimap} \e$B$O40A4$J\e(B @code{nnmail} \e$BM3Mh$N%P%C%/%(%s%I$G$O$"$j$^$;$s$,!"\e(B
+\e$B$?$$$F$$$N4|8B@Z$l>C5n\e(B (@pxref{Expiring Mail}) \e$B$NI8=`5!G=$r%5%]!<%H$7$^\e(B
+\e$B$9!#\e(B@acronym{IMAP} \e$B$NJ,3d\e(B (@pxref{Splitting in IMAP}) \e$B$G\e(B
+\e$B$O\e(B @code{nnmail} \e$B$NJQ?t$rJ#@=$7$J$$\e(B (\e$BNc$($P\e(B @var{nnimap-expiry-wait} \e$B$r\e(B
+\e$B@8@.$7$J$$\e(B) \e$BE@$,0c$&$N$G$9$,!"\e(B@code{nnmail} \e$B$NJQ?t$rN.MQ$7$^$9!#0J2<\e(B
+\e$B$O\e(B @code{nnimap} \e$B$N4|8B@Z$l>C5n=hM}$G;H$o$l$kJQ?t$G$9!#\e(B
+
+\e$B4|8B@Z$l>C5n$N0u$,$I$N$h$&$KE,@Z$K\e(B @acronym{IMAP} \e$B%5!<%P!<$K5-O?$5$l$k$+\e(B
+\e$B$K$D$$$F$b$3$3$G8@5Z$7$F$*$-$^$7$g$&!#4|8B@Z$l>C5n$N0u$O\e(B @code{imap} \e$B%/\e(B
+\e$B%i%$%"%s%HFCM-$N0u$G$"$k\e(B @code{gnus-expire} \e$B$KJQ49$5$l!"%a%C%;!<%8$K5-O?\e(B
+\e$B$5$l$^$9!#$3$l$O!"B>$N%/%i%$%"%s%H$O%a%C%;!<%8$N%/%i%$%"%s%HFCM-$N%U%i%0\e(B
+\e$B$r8+$k$+$b$7$l$J$$$N$KBP$7$F!"\e(BGnus \e$B$O$?$V$s\e(B @code{gnus-expire} \e$B$N0u$rE,\e(B
+\e$B@Z$K07$$M}2r$9$k$@$1$G$"$k$3$H$r0UL#$7$^$9!#$^$?$3$l$O%5!<%P!<$,!"%/%i%$\e(B
+\e$B%"%s%HFCM-$N%U%i%0$N%a%C%;!<%8$X$N915WE*$JJ]B8$r%5%]!<%H$7$J$1$l$P$J$i$J\e(B
+\e$B$$$3$H$b0UL#$7$^$9!#9,$$$K!"$?$$$F$$$O%5%]!<%H$7$^$9!#\e(B
+
+@table @code
+@item nnmail-expiry-wait
+@item nnmail-expiry-wait-function
+
+\e$B$3$l$i$NJQ?t$O40A4$K%5%]!<%H$5$l$F$$$^$9!#4|8B@Z$l>C5n$NCM$O!"?t!"%7%s%\\e(B
+\e$B%k$N\e(B @code{immediate} \e$B$^$?$O\e(B @code{never} \e$B$G$9!#\e(B
+
+@item nnmail-expiry-target
+
+\e$B$3$NJQ?t$O%5%]!<%H$5$l$F$$$F!"FbItE*$K$O$3$l$r07$&\e(B @code{nnmail} \e$B4X?t$r\e(B
+\e$B8F$V$3$H$K$h$C$F<BAu$5$l$F$$$^$9!#$b$79T$-@h$,F1$8%5!<%P!<\e(B
+\e$B$N\e(B @acronym{IMAP} \e$B%0%k!<%W$@$C$?$i!"5-;v$ODI2C$5$l$kBe$o$j$K%3%T!<$5$l\e(B
+\e$B$k\e(B (\e$B%"%C%W%m!<%I$7D>$5$l$k\e(B) \e$B$H$$$&:GE,2=$b4^$_$^$9!#\e(B
+@end table
+
+@node Editing IMAP ACLs
+@subsection IMAP \e$B$N\e(B ACL \e$B$rJT=8$9$k!#\e(B
+@cindex editing imap acls
+@cindex Access Control Lists
+@cindex Editing @acronym{IMAP} ACLs
+@kindex G l (\e$B%0%k!<%W\e(B)
+@findex gnus-group-nnimap-edit-acl
+
+ACL \e$B$O\e(B Access Control List (\e$B;HMQ@)8B0lMw\e(B) \e$B$NN,$G$9!#\e(B@acronym{IMAP} \e$B$G\e(B
+\e$B$O\e(B ACL \e$B$OB>$NMxMQ<T$K$h$k$"$J$?$N%a!<%k%\%C%/%9$N;HMQ$r@)8B\e(B (\e$B$b$7$/$O5v\e(B
+\e$B2D\e(B) \e$B$9$k$?$a$K;H$o$l$F$$$^$9!#\e(B@acronym{IMAP} \e$B%5!<%P!<A4$F$K$3$N5!G=$,$"\e(B
+\e$B$k$o$1$G$O$J$/!"L5$$%5!<%P!<$G$3$l$i$N4X?t$r;H$&$H%(%i!<$,H/@8$7$^$9!#\e(B
+
+\e$B%a!<%k%\%C%/%9$X$N\e(B ACL \e$B$rJT=8$9$k$?$a$K$O!"\e(B
+@kbd{G l} (@code{gnus-group-edit-nnimap-acl}) \e$B$rF~NO$7$^$9!#$=$&$9$k$H!"\e(B
+\e$B>\$7$$;X<($H$H$b$K\e(B ACL \e$BJT=8%&%#%s%I%&$,8=$l$^$9!#\e(B
+
+\e$B;HMQ$NNc\e(B:
+
+@itemize @bullet
+@item
+\e$B%a!<%j%s%0%j%9%H$N%a!<%k%\%C%/%9$G\e(B ``anyone'' \e$B$K\e(B ``lrs'' \e$B5v\e(B
+\e$B2D\e(B (lookup, read, seen/unseen \e$B%U%i%0$NJ];}\e(B) \e$B$rM?$($k$3$H$G!"F1$8%5!<%P!<\e(B
+\e$B$NB>$NMxMQ<T$,$=$l$r9XFI$9$k$3$H$J$/FI$`$3$H$,$G$-$^$9!#\e(B
+@item
+\e$B>/$J$/$H$b\e(B Cyrus \e$B$N%5!<%P!<$K$*$$$F$O!"\e(B``plussing'' \e$B$,F0:n$9$k$?$a$K\e(B (\e$B$D\e(B
+\e$B$^$j!"\e(Buser+mail@@domain \e$B$,\e(B INBOX.mailbox \e$B$H$$$&\e(B @acronym{IMAP} \e$B$N%a!<%k\e(B
+\e$B%\%C%/%9$K$J$k\e(B)\e$B!"MxMQ<T\e(B ``anyone'' \e$B$KEj9F\e(B ("p") \e$B$N5v2D$rM?$($kI,MW$,$"$j\e(B
+\e$B$^$9!#\e(B
+@end itemize
+
+@node Expunging mailboxes
+@subsection \e$B%a!<%k%\%C%/%9$N:o=|\e(B
+@cindex expunging
+
+@cindex expunge
+@cindex manual expunging
+@kindex G x (\e$B%0%k!<%W\e(B)
+@findex gnus-group-nnimap-expunge
+
+@code{nnimap-expunge-on-close} \e$B$K\e(B @code{never} \e$B$r@_Dj$7$F$$$l$P!"%a!<%k\e(B
+\e$B%\%C%/%9$NA4$F$N>C5n$5$l$?5-;v$r<jF0$G:o=|$9$kI,MW$,$"$k$G$7$g$&!#\e(B
+@kbd{G x} \e$B$,$^$5$K$3$N$3$H$r$7$^$9!#\e(B
+
+\e$B8=;~E@$G$O!">C5n$5$l$?5-;v$rI=<($9$kJ}K!$O$"$j$^$;$s!#$?$@>C5n$G$-$k$@$1\e(B
+\e$B$G$9!#\e(B
+
+@node A note on namespaces
+@subsection \e$BL>A06u4V$K4X$9$kCm0U\e(B
+@cindex @acronym{IMAP} namespace
+@cindex namespaces
+
+@acronym{IMAP} \e$B%W%m%H%3%k$K$OL>A06u4V\e(B (namespaces) \e$B$H8F$P$l$k35G0$,$"$j!"\e(B
+\e$B0J2<$N\e(B RFC2060 \e$B$NJ8=q$G5-=R$5$l$F$$$^$9!#\e(B
+
+@example
+5.1.2.  \e$B%a!<%k%\%C%/%9L>A06u4VL?L>5,B'\e(B
+
+   \e$B=,47$K$h$j\e(B "#" \e$B$G;O$^$C$F$$$k$9$Y$F$N%a!<%k%\%C%/%9L>$N:G=i$N3,AXMWAG\e(B
+   \e$B$O!";D$j$NL>A0$N\e(B "\e$BL>A06u4V\e(B" \e$B$r<($7$F$$$k!#$3$l$O!"$=$l$>$lFH<+$NL>A0\e(B
+   \e$B6u4V$r;}$D0[$J$k%a!<%k%\%C%/%9J]4I$N4V$G$N!"[#Kf$5$r<h$j=|$/$3$H$r2D\e(B
+   \e$BG=$K$9$k!#\e(B
+
+      \e$BNc$($P\e(B USENET \e$B%K%e!<%9%0%k!<%W$X$N%"%/%;%9$rDs6!$9$k<BAu$O!"\e(BUSENET
+      \e$B%K%e!<%9%0%k!<%WL>A06u4V$rB>$N%a!<%k%\%C%/%9$+$iJ,N%$9$k$?$a$K!"\e(B
+      "#news" \e$BL>A06u4V$rMQ$$$F$b$h$$!#$3$&$7$F\e(B comp.mail.misc \e$B%K%e!<%9%0\e(B
+      \e$B%k!<%W$O\e(B "#news.comp.mail.misc" \e$B$H$$$&%a!<%k%\%C%/%9L>$r;}$A!"L>A0\e(B
+      "comp.mail.misc" \e$B$OJL$N%*%V%8%'%/%H\e(B (\e$BNc$($P!"%f!<%6$N8D?M%a!<%k%\%C\e(B
+      \e$B%/%9\e(B) \e$B$r;X$9$3$H$O$"$j$&$k!#\e(B
+
+(\e$BLuCp\e(B: http://kame.zit.to/~obata/imap/rfc/rfc2060ja.txt \e$B$h$jE>:\\e(B)
+@end example
+
+\e$B$3$3$K$O\e(B gnus \e$B$K$*$1$k\e(B @acronym{IMAP} \e$B$N<BAu$KBP$9$k4X78$rJ]>Z$9$kJ8=q$,\e(B
+\e$BL5$$$N$G$9$,!"$$$/$D$+$N%5!<%P!<$O\e(B gnus \e$B$N%a!<%k%\%C%/%9$NL>A0$N;H$$J}$G\e(B
+\e$B$OF0:n$7$J$$$d$jJ}$GL>A06u4V@\F,<-$r;H$C$F$$$^$9!#\e(B
+
+\e$B6qBNE*$K$O!"%o%7%s%H%sBg3X$N\e(B @acronym{IMAP} \e$B%5!<%P!<\e(B
+\e$B$O\e(B @code{#driver.mbx/read-mail} \e$B$N$h$&$J%a!<%k%\%C%/%9L>$r;H$C$F$$$F!"$=\e(B
+\e$B$l$O\e(B @sc{create} \e$B$H\e(B @sc{append} \e$B%3%^%s%I$G$@$1M-8z$G$9!#%a!<%k%\%C%/%9$,\e(B
+\e$B:n$i$l$?8e\e(B (\e$B$^$?$O%a%C%;!<%8$,%a!<%k%\%C%/%9$KDI2C$5$l$?8e\e(B) \e$B$G$O!"$=$l$O\e(B
+\e$BL>A06u4V@\F,<-$rIU$1$:$K%"%/%;%9!"$9$J$o$A\e(B @code{read-mail} \e$B$5$l$J$1$l$P\e(B
+\e$B$J$j$^$;$s!#\e(Bgnus \e$B$O%f!<%6!<$,\e(B CREATE \e$B$H\e(B APPEND \e$B%3%^%s%I$@$1$GF~NO$7$?%a!<\e(B
+\e$B%k%\%C%/%9L>$rJ]>Z$G$-$J$$$N$G!"@dBP$KL>A06u4V@\F,<-$,IU$$$?%a!<%k%\%C%/\e(B
+\e$B%9L>$r\e(B gnus \e$B$G;H$C$F$O$$$1$^$;$s!#\e(B
+
+@code{#driver.*/} \e$B@\F,<-$K$D$$$F$N$5$i$J$k;H$$J}$N>pJs$O\e(B UoW IMAPD \e$B$NJ8\e(B
+\e$B=q$r8+$F2<$5$$!#$=$l$i$O6/NO$J9)6q$J$N$G!"$I$s$J8z2L$,$"$k$+$,3N$+$J>l9g\e(B
+\e$B$@$1;H$C$F2<$5$$!#\e(B
+
+@node Debugging IMAP
+@subsection IMAP \e$B$N%G%P%C%0\e(B
+@cindex IMAP debugging
+@cindex protocol dump (IMAP)
+
+@acronym{IMAP} \e$B$O\e(B @acronym{NNTP} \e$B$d\e(B @acronym{POP3} \e$B$h$j$b$C$HJ#;($J%W%m\e(B
+\e$B%H%3%k$G$9!#<BAu>e$N%P%0$,L5$$$H$O8@$$@Z$l$J$$$N$G!";d$?$A$O!"$9$0$K$=$l\e(B
+\e$B$i$rD>$9$?$a$K:GA1$r?T$/$7$^$9!#$"$J$?$,4qL/$J?6$kIq$$$K=P2q$C$?$H$7$?$i!"\e(B
+\e$B%5!<%P!<$+\e(B gnus \e$B$N$I$A$i$+$K%P%0$,$"$k2DG=@-$,$"$j$^$9!#\e(B
+
+\e$B$"$J$?$,0lHLE*$J%M%C%H%o!<%/!&%W%m%H%3%k$K@:DL$7$F$$$k$J$i$P!"\e(BGnus \e$B$H%5!<\e(B
+\e$B%P!<$N4V$G$d$j$H$j$5$l$k%W%m%H%3%k!&%@%s%W$rFI$`$3$H$K$h$C$F!"$*$=$i$/$$\e(B
+\e$B$/$D$+$N<j3]$+$j$rCj=P$9$k$3$H$,$G$-$k$G$7$g$&!#@:DL$7$F$$$J$/$F$b!"%W%m\e(B
+\e$B%H%3%k!&%@%s%W$r\e(B IMAP \e$B$K4X$9$k%P%0Js9p$K4^$a$l$P!"$=$NLdBj$N2r7h$K$H$C$F\e(B
+\e$B=EMW$J%G!<%?$G;d$?$A$r=u$1$^$9!#$7$?$,$C$F!"\e(Bgnus \e$B$N\e(B IMAP \e$B%P%0$rJs9p$9$k\e(B
+\e$B$H$-$K!"%W%m%H%3%k!&%@%s%W$r4^$a$k$3$H$r6/$/>)Ne$7$^$9!#\e(B
+
+@vindex imap-log
+\e$B%W%m%H%3%k!&%@%s%W$O!"$=$l$rM-8z$K$7$F$$$k$H$?$/$5$s$N%G!<%?$r@8@.$9$k$N\e(B
+\e$B$G!"%G%#%U%)%k%H$G$OL58z$K$J$C$F$$$^$9!#M-8z$K$9$k$K$O!"0J2<$N$h$&\e(B
+\e$B$K\e(B @code{imap-log} \e$B$r@_Dj$7$F2<$5$$\e(B:
+
+@lisp
+(setq imap-log t)
+@end lisp
+
+\e$B$3$l$O\e(B @code{imap.el} \e$B%Q%C%1!<%8$K!"%5!<%P!<$H$N$d$j$H$j$r2?$G$b5-O?$5$;\e(B
+\e$B$^$9!#$=$N5-O?$O\e(B @samp{*imap-log*} \e$B$H$$$&%P%C%U%!$K3JG<$5$l$^$9!#$H$-$H\e(B
+\e$B$7$F\e(B @code{BAD} \e$B$H$$$&;%$,IU$1$i$l$k!"%(%i!<%a%C%;!<%8$rC5$7$F2<$5$$!#$G\e(B
+\e$B$b!"%P%0$rDs=P$9$k$H$-$O!"$9$Y$F$N%G!<%?$r4^$a$k$h$&$K$7$F2<$5$$!#\e(B
+
+@node Other Sources
+@section \e$B$=$NB>$N%0%k!<%W8;\e(B
+
+Gnus \e$B$O$?$@C1$K%K%e!<%9$d%a!<%k$rFI$`0J>e$N$3$H$,$G$-$^$9!#0J2<\e(B
+\e$B$K<($9J}K!$K$h$C$F!"\e(Bgnus \e$B$G%G%#%l%/%H%j!<$d%U%!%$%k$r!"$"$?$+$b\e(B
+\e$B%K%e!<%9%0%k!<%W$G$"$k$+$N$h$&$K1\Mw$9$k$3$H$,$G$-$k$h$&$K$J$j$^\e(B
+\e$B$9!#\e(B
+
+@menu
+* Directory Groups::            \e$B%G%#%l%/%H%j!<$r%K%e!<%9%0%k!<%W$N$h$&$KFI$`\e(B
+* Anything Groups::             Dired?  \e$BC/$,\e(B dired \e$B$J$s$F;H$&$N\e(B?
+* Document Groups::             \e$B8DJL$N%U%!%$%k72$O%0%k!<%W$NAG\e(B
+* SOUP::                        @sc{soup} \e$B%Q%1%C%H$r\e(B ``\e$B%*%U%i%$%s\e(B'' \e$B$GFI$`\e(B
+* Mail-To-News Gateways::       \e$B%a!<%k$+$i%K%e!<%9$X$N%2!<%H%&%'%$$rDL$7$F5-;v$rEj9F$9$k\e(B
+@end menu
+
+@node Directory Groups
+@subsection \e$B%G%#%l%/%H%j!<%0%k!<%W\e(B
+@cindex nndir
+@cindex directory groups
+
+\e$B$b$7!"$?$/$5$s$N5-;v$,8DJL$N%U%!%$%k$H$7$FF~$C$F$$$k%G%#%l%/%H%j!<$,$"$l\e(B
+\e$B$P!"$=$l$r%K%e!<%9%0%k!<%W$H$7$F07$&$3$H$,$G$-$^$9!#$b$A$m$s!"%U%!%$%k$O\e(B
+\e$B?t;z$N%U%!%$%kL>$r$b$C$F$$$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$B$3$3$G\e(B Emacs \e$B$NAG@2$i$7$$%Q%C%1!<%8$NCf$G$b:G$bAG@2$i$7\e(B
+\e$B$$\e(B @code{ange-ftp} (\e$B$H$=$N8e7Q$N\e(B @code{efs}) \e$B$K$D$$$F?($l$kNI$$5!2q$G$7$g\e(B
+\e$B$&!#;d$,\e(B @code{nndir} \e$B$r=q$$$?$H$-$O!"$3$l\e(B --- \e$B%G%#%l%/%H%j!<$rFI$`%P%C\e(B
+\e$B%/%(%s%I$K$D$$$F$O$"$^$j9M$($F$$$^$;$s$G$7$?!#$H$s$G$b$J$$$3$H$@$M!#\e(B
+
+@code{ange-ftp} \e$B$O$3$N>p67$r7`E*$KJQ2=$5$;$^$7$?!#Nc$($P!"\e(B
+@code{ange-ftp} \e$B%U%!%$%k\e(B
+\e$BL>\e(B @file{/ftp.hpc.uh.edu:/pub/emacs/ding-list/} \e$B$r%G%#%l%/%H%j!<L>$H$7$F\e(B
+\e$BF~NO$7$?$H$9$k$H!"\e(B@code{ange-ftp} \e$B$"$k$$$O\e(B @code{efs} \e$B$O<B$K!"\e(B
+@samp{\e$B%7%J\e(B} \e$B$N8~$3$&$N%G%#%l%/%H%j!<$r%K%e!<%9%0%k!<%W$H$7$FFI$`$3$H$r2D\e(B
+\e$BG=$K$9$k$N$G$9!#$*!<$$!"J,;6%K%e!<%9$h\e(B!
+
+@code{nndir} \e$B$O\e(B @acronym{NOV} \e$B%U%!%$%k$,B8:_$9$l$P$=$l$rMxMQ$7$^$9!#\e(B
+
+@code{nndir} \e$B$O\e(B ``\e$BFI$_=P$7@lMQ\e(B'' \e$B$N%P%C%/%(%s%I$G$9\e(B --- \e$B$3$NA*BrJ}K!$G$O!"\e(B
+\e$B5-;v$N:o=|$d4|8B@Z$l>C5n$r9T$J$&$3$H$O$G$-$^$;$s!#\e(B@code{nndir} \e$B$,;H$($k\e(B
+\e$B$b$N$J$i2?$G$b\e(B @code{nnmh} \e$B$"$k$$$O\e(B @code{nnml} \e$B$r;H$&$3$H$,$G$-$k$N$G!"\e(B
+\e$B$b$7FI$_=P$7@lMQ$G$O$J$$\e(B @code{nndir} \e$B$,I,MW$@$H;W$C$?$i!"$3$l$i$N$I$A$i\e(B
+\e$B$+$NJ}K!$K@Z$jBX$($k$3$H$b$G$-$^$9!#\e(B
+
+@node Anything Groups
+@subsection \e$B$J$s$G$b%0%k!<%W\e(B
+@cindex nneething
+
+(\e$B0l$D$N%9%W!<%kIw%G%#%l%/%H%j!<$H2r<a$G$-$k\e(B) @code{nndir} \e$B%P%C%/%(%s%I$+\e(B
+\e$B$i\e(B @code{nneething} \e$B$^$G$O!"$[$s$N$9$0$=$3$G$9!#$=$l$O$$$+$J$k%G%#%l%/%H\e(B
+\e$B%j!<$G$b%K%e!<%9%0%k!<%W$K8+$;$+$1$F$7$^$&!"$H$$$&$b$N$G$9!#IT;W5D$G$9!"\e(B
+\e$B$G$b??<B$G$9!#\e(B
+
+@code{nneething} \e$B$K%G%#%l%/%H%j!<$rM?$($k$H!"$=$N%G%#%l%/%H%j!<$rAv::$7!"\e(B
+\e$B3F%U%!%$%k$K5-;vHV9f$r3d$jEv$F$^$9!#$3$N$h$&$J%0%k!<%W$KF~$C$?$H$-$O!"\e(B
+@code{nneething} \e$B$O\e(B gnus \e$B$,;H$&\e(B ``\e$B%X%C%@!<\e(B'' \e$B$r:n$i$J$/$F$O$J$j$^$;$s!#\e(B
+\e$B$D$^$k$H$3$m!"\e(Bgnus \e$B$O%K%e!<%9%j!<%@$J$s$G$9!#K:$l$F$k$+$b$7$l$J$$$N$GG0\e(B
+\e$B$N$?$a!#\e(B@code{nneething} \e$B$O$3$l$rFsCJ3,$G=hM}$7$^$9!#:G=i$K!"LdBj$H$J$k\e(B
+\e$B%U%!%$%k$r$=$l$>$lA':w$7$F$^$o$j$^$9!#$b$7$=$N%U%!%$%k$,5-;v$N$h$&$K8+$(\e(B
+\e$B$?$J$i\e(B (\e$B$9$J$o$A!":G=i$N?t9T$,%X%C%@!<$N$h$&$K8+$($?$i\e(B) \e$B$=$l$r%X%C%@$H$7\e(B
+\e$B$F;H$$$^$9!#$b$7$=$l$,%X%C%@!<$N$J$$$?$@$NE,Ev$J%U%!%$%k\e(B (\e$BNc$($P\e(B C \e$B$N%=!<\e(B
+\e$B%9%U%!%$%k\e(B) \e$B$G$"$C$?$J$i!"\e(B@code{nneething} \e$B$O%X%C%@!<$r5u6u$+$i:n$j=P$7\e(B
+\e$B$^$9!#$3$l$O%U%!%$%k$N=jM-<T!"L>A0!"F|IU$r;H$$!"$3$l$i$NMWAG$KBP$7$F$G$-\e(B
+\e$B$k$3$H$r2?$G$b$d$j$^$9!#\e(B
+
+\e$B$3$l$O$"$J$?$K$H$C$F$OA4$F<+F0E*$K5/$3$k$3$H$G!"$"$J$?$O%K%e!<%9%0%k!<%W\e(B
+\e$B$K$H$F$bNI$/;w$?2?$+$r8+$;$i$l$k$3$H$K$J$k$G$7$g$&!#$[$s$H$&$K@#J,0c$o$J\e(B
+\e$B$$!"%K%e!<%9%0%k!<%W$N$h$&$J$b$N$r!#5-;v$rA*Br$9$k$H!"$=$l$O$$$D$b$N$h$&\e(B
+\e$B$K!"5-;v%P%C%U%!$KI=<($5$l$k$G$7$g$&!#\e(B
+
+\e$B%G%#%l%/%H%j!<$rI=$o$7$F$$$k9T$rA*Br$9$k$H!"\e(Bgnus \e$B$O$"$J$?$r$3\e(B
+\e$B$N\e(B @code{nneething} \e$B%0%k!<%W$N$?$a$N?7$7$$35N,%P%C%U%!$KO"$l$F9T$/$G$7$g\e(B
+\e$B$&!#0J2<F1MM$G!"$b$7$"$J$?$,$=$&$7$?$1$l$P!"$3$NJ}K!$GA4%G%#%9%/$r6n$1=d\e(B
+\e$B$k$3$H$,$G$-$^$9!#$G$9$,!"\e(Bgnus \e$B$OK\Ev$O\e(B dired \e$B$G$O$J$/!"$=$N$h$&$K0U?^$5\e(B
+\e$B$l$?$b$N$G$b$J$$!"$H$$$&$3$H$O3P$($F$*$$$F$/$@$5$$!#\e(B
+
+\e$B$3$3$G$NF0:n$K$OA4BNE*$KFs$D$N%b!<%I$,$"$j$^$9\e(B --- \e$B0l;~%b!<%I$H8GDj%b!<\e(B
+\e$B%I$G$9!#0l;~E*$JA`:n$r9T$J$C$F$$$k$H$-$O\e(B(\e$B$9$J$o$A!"%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{G D} \e$B$H$9$k\e(B)\e$B!"\e(Bgnus \e$B$O$I$N%U%!%$%k$rFI$s$@$+!"$I$N%U%!%$%k$,?7$7\e(B
+\e$B$$$+!"$J$I$N>pJs$r21$($F$*$-$^$;$s!#$b$7\e(B @kbd{G m} \e$B$GIaDL$K8G\e(B
+\e$BDj\e(B @code{nneething} \e$B%0%k!<%W$r:n$k$H!"\e(Bgnus \e$B$O5-;vHV9f$H%U%!%$%kL>$NBP1~\e(B
+\e$BI=$r21$($F$*$-!"$3$N%0%k!<%W$rB>$N%0%k!<%W$HF1MM$K07$&$3$H$,$G$-$k$h$&$K\e(B
+\e$B$J$j$^$9!#8GDj\e(B @code{nneething} \e$B%0%k!<%W$r:nF0$5$;$k$H!"L$FI5-;v$,$$$/$D\e(B
+\e$B4^$^$l$F$$$k$+$rCN$i$5$l$?$j!"$J$I$J$I!#\e(B
+
+\e$B$$$/$D$+$NJQ?t$,$"$j$^$9!#\e(B
+
+@table @code
+@item nneething-map-file-directory
+@vindex nneething-map-file-directory
+\e$BA4$F$N8GDj\e(B @code{nneething} \e$B%0%k!<%W$NBP1~I=$O$3$N%G%#%l%/%H%j!<$K3JG<$5\e(B
+\e$B$l$^$9!#$3$N=i4|@_DjCM$O\e(B @file{~/.nneething/} \e$B$G$9!#\e(B
+
+@item nneething-exclude-files
+@vindex nneething-exclude-files
+\e$B$3$N@55,I=8=$K%^%C%A$9$k%U%!%$%k$O$9$Y$FL5;k$5$l$^$9!#<+F0J]B8%U%!%$%k$J\e(B
+\e$B$I$r=|$/$N$KJXMx$K;H$($^$9!#$=$7$F$=$l$,$^$5$K=i4|@_Dj$G9T$J$o$l$kF0:n$G\e(B
+\e$B$9!#\e(B
+
+@item nneething-include-files
+@vindex nneething-include-files
+\e$B$=$N%U%!%$%k$r%0%k!<%W$K4^$a$k$+$r<($9@55,I=8=$G$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$J$1$l$P!"$3$N@55,I=8=$K9gCW$9$k%U%!%$%k$@$1$,4^$^$l$^$9!#\e(B
+
+@item nneething-map-file
+@vindex nneething-map-file
+\e$BBP1~I=%U%!%$%k$NL>A0!#\e(B
+@end table
+
+@node Document Groups
+@subsection \e$BJ8=q%0%k!<%W\e(B
+@cindex nndoc
+@cindex documentation group
+@cindex help group
+
+@code{nndoc} \e$B$O0l$D$N%U%!%$%k$r%K%e!<%9%0%k!<%W$H$7$FFI$`$3$H$r$G$-$k$h\e(B
+\e$B$&$K$9$k!"$A$g$C$H5$$NMx$$$?$d$D$G$9!#$$$/$D$+$N%U%!%$%k<oJL$,%5%]!<%H$5\e(B
+\e$B$l$F$$$^$9!#\e(B
+
+@table @code
+@cindex Babyl
+@cindex Rmail mbox
+
+@item babyl
+Babyl (Rmail) \e$B7A<0$N%a!<%k%\%C%/%9!#\e(B
+@cindex mbox
+@cindex Unix mbox
+
+@item mbox
+\e$BI8=`\e(B Unix mbox \e$B%U%!%$%k!#\e(B
+
+@cindex MMDF mail box
+@item mmdf
+MMDF \e$B7A<0$N%a!<%k%\%C%/%9!#\e(B
+
+@item news
+\e$B$$$/$D$+$N%K%e!<%95-;v$,O"7k$5$l$?0l$D$N%U%!%$%k!#\e(B
+
+@item rnews
+@cindex rnews batch files
+rnews \e$B$N%P%C%AE>Aw7A<0!#\e(B
+@cindex forwarded messages
+
+@item forward
+\e$BE>Aw$5$l$?5-;v!#\e(B
+
+@item nsmail
+Netscape \e$B$N%a!<%k%\%C%/%9!#\e(B
+
+@item mime-parts
+@acronym{MIME} \e$BItJ,%a%C%;!<%8\e(B (multipart)\e$B!#\e(B
+
+@item standard-digest
+\e$BI8=`\e(B (RFC 1153) \e$B$^$H$aAw$j7A<0!#\e(B
+
+@item mime-digest
+@acronym{MIME} \e$B$N$^$H$aAw$j%a%C%;!<%8!#\e(B
+
+@item lanl-gov-announce
+\e$B%m%9%"%i%b%99qN)8&5f=j\e(B (LANL) Gov Announce \e$B$+$i$NH/I=%a%C%;!<%8!#\e(B
+
+@item rfc822-forward
+RFC822 \e$B$GE>Aw$5$l$?%a%C%;!<%8!#\e(B
+
+@item outlook
+Outlook \e$B$N%a!<%k%\%C%/%9!#\e(B
+
+@item oe-dbx
+Outlook Express \e$B$N\e(B dbx \e$B%a!<%k%\%C%/%9!#\e(B
+
+@item exim-bounce
+Exim MTA \e$B$+$iD7$MJV$5$l$?%a%C%;!<%8!#\e(B
+
+@item forward
+\e$BHs8x<0$N5,B'$GE>Aw$5$l$?%a%C%;!<%8!#\e(B
+
+@item rfc934
+RFC934 \e$B7A<0$GE>Aw$5$l$?%a%C%;!<%8!#\e(B
+
+@item mailman
+mailman \e$B$N$^$H$aAw$j!#\e(B
+
+@item clari-briefs
+Clarinet \e$B$N%K%e!<%99`L\$rMWLs$7$?$^$H$aAw$j!#\e(B
+
+@item slack-digest
+\e$BHsI8=`$^$H$aAw$j7A<0\e(B --- \e$B$@$$$?$$$O$&$^$/%^%C%A$9$k$,!"$G$b07$$$O2<<j!#\e(B
+
+@item mail-in-mail
+\e$B:G8e$N<jCJ!#\e(B
+@end table
+
+\e$B$^$?!"FCJL$J\e(B ``\e$B%U%!%$%k<oJL\e(B'' @code{guess} \e$B$r;H$&$3$H$b$G$-$^$9!#$3$l\e(B
+\e$B$O\e(B @code{nndoc} \e$B$OCmL\$7$F$$$k%U%!%$%k$N<oJL$r?dB,$7$h$&$H$9$k!"$H$$$&0U\e(B
+\e$BL#$G$9!#\e(B@code{digest} \e$B$O\e(B @code{nndoc} \e$B$K$=$N%U%!%$%k$,$I$N$^$H$aAw$j7A<0\e(B
+\e$B$+$r?dB,$5$;$k$H$$$&0UL#$G$9!#\e(B
+
+@code{nndoc} \e$B$O%U%!%$%k$r=q$-49$($h$&$H$7$?$j!"M>J,$J%X%C%@!<$rA^F~$7$h\e(B
+\e$B$&$H$7$?$j$O$7$^$;$s\e(B --- \e$BC1=c$K!"%U%!%$%k$r$=$N%0%k!<%W$N<g@.J,$H$7$F;H\e(B
+\e$B$($k$h$&$K$9$k!"$H$$$&$h$&$J$b$N$G$9!#$=$l$@$1$N$3$H$G$9!#\e(B
+
+\e$B$b$7$"$J$?$,8E$$J]B85-;v$r;}$C$F$$$F!"$=$l$r?7$7$/$F$+$C$3$$$$\e(B gnus \e$B$N%a!<\e(B
+\e$B%k%P%C%/%(%s%I$KDI2C$7$?$$$H$$$&$H$-$O!"$*$=$i$/\e(B @code{nndoc} \e$B$,=u$1$K$J\e(B
+\e$B$j$^$9!#Nc$($P$"$J$?$,%a!<%k$r8E$$\e(B @file{RMAIL} \e$B$G;}$C$F$$$F!"$=$l$r$"$J\e(B
+\e$B$?$N?7$7$$\e(B @code{nnml} \e$B%0%k!<%W$KJ,G[$7$?$$$H$7$^$9!#$"$J$?$O$=$N%U%!%$\e(B
+\e$B%k$r\e(B @code{nndoc} \e$B$r;H$C$F3+$$$F\e(B (\e$B%0%k!<%W%P%C%U%!$G\e(B @kbd{G f} \e$BL?Na$r;H\e(B
+\e$B$&\e(B (@pxref{Foreign Groups}))\e$B!"%P%C%U%!Fb$NA45-;v$K%W%m%;%9%^!<%/$rIU\e(B
+\e$B$1\e(B (\e$BNc$($P\e(B @kbd{M P b})\e$B!"$=$7$F\e(B @code{nnml} \e$B$r;H$C$F:F%9%W!<\e(B
+\e$B%k\e(B (@kbd{B r}) \e$B$7$^$9!#A4$F$,$&$^$/9T$1$P!"\e(B@file{RMAIL} \e$B%U%!%$%kFb$NA4$F\e(B
+\e$B$N%a!<%k$O$?$/$5$s$N\e(B  @code{nnml} \e$B%G%#%l%/%H%j!<$NCf$K$bJ]B8$5$l$^$9!#$=\e(B
+\e$B$7$F$"$J$?$O$"$NLq2p$J\e(B @file{RMAIL} \e$B$r:o=|$9$k$3$H$b$G$-$^$9!#$"$J$?$K%,%C\e(B
+\e$B%D$,$"$l$P\e(B!
+
+\e$B2>A[%5!<%P!<JQ?t!#\e(B
+
+@table @code
+@item nndoc-article-type
+@vindex nndoc-article-type
+\e$B$3$l$O\e(B @code{mbox}, @code{babyl}, @code{digest}, @code{news},
+@code{rnews}, @code{mmdf}, @code{forward}, @code{rfc934},
+@code{rfc822-forward}, @code{mime-parts}, @code{standard-digest},
+@code{slack-digest}, @code{clari-briefs}, @code{nsmail}, @code{outlook},
+@code{oe-dbx}, @code{mailman} \e$B$*$h$S\e(B @code{mail-in-mail} \e$B$^$?\e(B
+\e$B$O\e(B @code{guess} \e$B$N$$$:$l$+$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+@item nndoc-post-type
+@vindex nndoc-post-type
+\e$B$3$NJQ?t$O\e(B gnus \e$B$K$=$N%0%k!<%W$,%K%e!<%9%0%k!<%W$+%a!<%k%0%k!<%W$+$r65$(\e(B
+\e$B$^$9!#@5Ev$JCM$OFs$D$"$j$^$9!#\e(B@code{mail} (\e$B=i4|@_Dj\e(B)\e$B$+\e(B @code{news}\e$B$G$9!#\e(B
+@end table
+
+@menu
+* Document Server Internals::   \e$B$"$J$?FH<+$NJ8=q<oJL$rDI2C$9$kJ}K!\e(B
+@end menu
+
+@node Document Server Internals
+@subsubsection \e$BJ8=q%5!<%P!<$NFbIt\e(B
+
+@code{nndoc} \e$B$GG'<1$5$l$k?7$7$$J8=q<oJL$rDI2C$9$k$3$H$OFq$7$/$"$j$^$;$s!#\e(B
+\e$B$=$NJ8=q$,$I$N$h$&$K8+$($k$N$+$r4s$;=8$a$F!"$=$NJ8=q<oJL$rG'<1$9$k=R8l4X\e(B
+\e$B?t$r=q$-!"$=$7$F\e(B @code{nndoc} \e$B$K7R$2$k$@$1$G$9!#\e(B
+
+\e$B$^$:!"$3$l$,J8=q<oJLDj5A$NNc$G$9!#\e(B
+
+@example
+(mmdf
+ (article-begin .  "^\^A\^A\^A\^A\n")
+ (body-end .  "^\^A\^A\^A\^A\n"))
+@end example
+
+\e$B$3$NDj5A$OC1$K!"M#0l$NL>A0\e(B (@dfn{name}) \e$B$H$=$l$KB3$/@55,I=8=$H2>A[JQ?t@_\e(B
+\e$BDj$NNs$+$i$J$j$^$9!#0J2<$,$3$l$K;H$($kJQ?t$G$9\e(B --- \e$BJQ?t$N?t$K05E]$5$l$J\e(B
+\e$B$$$G$/$@$5$$!#$[$H$s$I$NJ8=q<oJL$O$4$/$o$:$+$N@_Dj$GDj5A$G$-$^$9!#\e(B
+
+@table @code
+@item first-article
+\e$B$3$l$,$"$l$P!"\e(B@code{nndoc} \e$B$O$3$N@55,I=8=$K%^%C%A$9$k2?$+$,8+$D$+$k$^$G!"\e(B
+\e$BA4$F$N%F%-%9%H$rFI$_Ht$P$7$^$9!#%^%C%A$9$kA0$NA4$F$N%F%-%9%H$O40A4$KL5;k\e(B
+\e$B$5$l$^$9!#\e(B
+
+@item article-begin
+\e$B$3$N@_Dj$OA4$F$NJ8=q<oJLDj5A$K$*$$$FI,$:$J$/$F$O$J$j$^$;$s!#$3$l$O3F5-;v\e(B
+\e$B$N;O$^$j$,$I$N$h$&$K8+$($k$+$r;XDj$7$^$9!#\e(B
+
+@item head-begin-function
+\e$B$3$l$,$"$k>l9g!"$3$l$O5-;v$N@hF,$K%]%$%s%H$r0\F0$5$;$k4X?t$G$J$/$F$O$J$j\e(B
+\e$B$^$;$s!#\e(B
+
+@item nndoc-head-begin
+\e$B$3$l$,$"$k>l9g!"$3$l$O5-;v$N%X%C%@!<$K%^%C%A$9$k@55,I=8=$G$J$/$F$O$J$j$^\e(B
+\e$B$;$s!#\e(B
+
+@item nndoc-head-end
+\e$B$3$l$O5-;v$N%X%C%@!<$N:G8e$K%^%C%A$7$J$/$F$O$J$j$^$;$s!#$3$N=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{^$} --- \e$B6u9T$G$9!#\e(B
+
+@item body-begin-function
+\e$B$3$l$,$"$k>l9g!"$3$N4X?t$O5-;v$N%\%G%#$N3+;O0LCV$K%]%$%s%H$r0\F0$5$;$k4X\e(B
+\e$B?t$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+@item body-begin
+\e$B$3$l$O5-;v$N%\%G%#$N3+;O0LCV$K%^%C%A$7$J$/$F$O$J$j$^$;$s!#$3$N=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{^\n} \e$B$G$9!#\e(B
+
+@item body-end-function
+\e$B$3$l$,$"$k>l9g!"$3$N4X?t$O5-;v$N%\%G%#$N:G8e$N0LCV$K%]%$%s%H$r0\F0$5$;$k\e(B
+\e$B4X?t$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+@item body-end
+\e$B$3$l$,$"$l$P!"5-;v$N%\%G%#$N:G8e$K%^%C%A$7$J$/$F$O$J$j$^$;$s!#\e(B
+
+@item file-end
+\e$B$3$l$,$"$k>l9g!"$3$l$O%U%!%$%k$N:G8e$K%^%C%A$7$J$/$F$O$J$j$^$;$s!#$3$N@5\e(B
+\e$B5,I=8=$N8e$m$N%F%-%9%H$OA4$F!"40A4$KL5;k$5$l$^$9!#\e(B
+@end table
+
+\e$B$3$N$h$&$K!"$3$l$i$NJQ?t$r;H$C$F\e(B @code{nndoc} \e$B$OJ8=q%U%!%$%k$r!"$=$l$>$l\e(B
+\e$B%X%C%@!<$H%\%G%#$r;}$C$?5-;v$NO"$J$j$H$7$F2rK6$9$k$3$H$,$G$-$^$9!#$7$+$7!"\e(B
+\e$BA4$F$NJ8=q<oJL$,A4$F$3$N$h$&$J%K%e!<%9Iw$K$J$C$F$k$o$1$G$O$J$$$N$G!"$5$i\e(B
+\e$B$K$$$/$D$+$NJQ?t\e(B --- \e$B%X%C%@!<$d%\%G%#$r\e(B gnus \e$B$N<qL#$K9g$&$h$&$KJQ7A$5$;\e(B
+\e$B$kJQ?t$,I,MW$K$J$j$^$9!#\e(B
+
+@table @code
+@item prepare-body-function
+\e$B$3$l$,$"$l$P!"$3$N4X?t$O5-;v$,MW5a$5$l$?$H$-$K8F$S=P$5$l$^$9!#$3$l$O%\%G%#\e(B
+\e$B$N3+;O0LCV$N%]%$%s%H$H$H$b$K8F$S=P$5$l!"J8=q$NFbMF$N0lIt$,Id9f2=$5$l$F$$\e(B
+\e$B$k>l9g$KM-MQ$G$9!#\e(B
+
+@item article-transform-function
+\e$B$3$l$,$"$l$P!"$3$N4X?t$O5-;v$,MW5a$5$l$?$H$-$K8F$S=P$5$l$^$9!#$3$l$O!"5-\e(B
+\e$B;v$N%X%C%@!<$H%\%G%#$NN>J}$K$h$j9-HO0O$JJQ7A$r9T$J$&$?$a$K;H$o$l$k$b$N$G\e(B
+\e$B$9!#\e(B
+
+@item generate-head-function
+\e$B$3$l$,$"$l$P!"$3$N4X?t$O\e(B gnus \e$B$,M}2r$G$-$k%X%C%@!<$r@8@.$9$k$?$a$K8F$S=P\e(B
+\e$B$5$l$^$9!#$3$l$O5-;vHV9f$r%Q%i%a!<%?$H$7$F8F$S=P$5$l!"LdBj$N5-;v$N$-$l$$\e(B
+\e$B$J%X%C%@!<$r@8@.$9$k$3$H$r5a$a$i$l$^$9!#$3$l$OA4$F$N5-;v$N%X%C%@!<$,MW5a\e(B
+\e$B$5$l$k$H$-$K8F$S=P$5$l$^$9!#\e(B
+@end table
+
+\e$B;d$,:n$C$?Cf$G:G$bJ#;($JNc\e(B --- \e$BI8=`$^$H$aAw$j7A<0$r8+$F$_$^$7$g$&!#\e(B
+
+@example
+(standard-digest
+ (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
+ (article-begin . ,(concat "\n\n" (make-string 30 ?-) "\n\n+"))
+ (prepare-body-function . nndoc-unquote-dashes)
+ (body-end-function . nndoc-digest-body-end)
+ (head-end . "^ ?$")
+ (body-begin . "^ ?\n")
+ (file-end . "^End of .*digest.*[0-9].*\n\\*\\*\\|^End of.*Digest *$")
+ (subtype digest guess))
+@end example
+
+70 \e$BJ8;z$N%@%C%7%e\e(B(`-')\e$B$N9T$h$jA0$OA4$FL5;k$5$l$k$H$$$&$N$,J,$+$j$^$9!#$^\e(B
+\e$B$?\e(B @samp{^End of} \e$B$G;O$^$k9T$h$j8e$m$bA4$FL5;k$5$l$^$9!#3F5-;v$O\e(B 30 \e$BJ8;z\e(B
+\e$B$N%@%C%7%e$N9T$G;O$^$j!"%X%C%@!<$H%\%G%#$N6h@Z$j$N9T$O0l8D$N%9%Z!<%9$r4^\e(B
+\e$B$`$3$H$,$"$j!"$=$7$F%\%G%#$O$=$l$,EO$5$l$kA0\e(B
+\e$B$K\e(B @code{nndoc-unquote-dashes} \e$B$rDL$5$l$^$9!#\e(B
+
+\e$B$"$J$?FH<+$NJ8=qDj5A$r\e(B @code{nndoc} \e$B$K@\B3$9$k$K$O!"\e(B
+@code{nndoc-add-type} \e$B4X?t$r;HMQ$7$^$9!#$3$l$OFs$D$N%Q%i%a!<%?$r$H$j$^\e(B
+\e$B$9\e(B --- \e$B0l$DL\$O$=$NDj5A<+?H$G!"Fs$DL\$N\e(B (\e$B>JN,2DG=$J\e(B) \e$B%Q%i%a!<%?$O$3$NDj\e(B
+\e$B5A$r!"J8=q<oJLDj5AO"A[%j%9%H$N$I$3$KCV$/$+$r;XDj$7$^$9!#$3$NO"A[%j%9%H$O\e(B
+\e$B=gHV$KAv::$5$l!"M?$($i$l$?<oJL\e(B @var{type} \e$B$KBP$7\e(B
+\e$B$F\e(B @code{nndoc-@var{type}-type-p} \e$B$,8F$S=P$5$l$^$9!#$3$N$h$&$KJ8=q\e(B
+\e$B$,\e(B @code{mmdf} \e$B<oJL$G$"$k$+$I$&$+$rD4$Y$k$?$a\e(B
+\e$B$K\e(B @code{nndoc-mmdf-type-p} \e$B$,8F$S=P$5$l!"$=$7$F0J2<F1MM$KB3$-$^$9!#$3$l\e(B
+\e$B$i$N<oJL=R8l4X?t$O!"$=$NJ8=q$,$=$N<oJL$G$J$$>l9g$O\e(B @code{nil} \e$B$rJV$7!"$=\e(B
+\e$B$N<oJL$G$"$k>l9g$O\e(B @code{t} \e$B$rJV$7!"$=$N<oJL$+$b$7$l$J$$$H$-$O?t;z$rJV$5\e(B
+\e$B$J$/$F$O$J$j$^$;$s!#9b$$?t;z$O9b$$2DG=@-$r0UL#$7!"Dc$$?t;z$ODc$$2DG=@-$r\e(B
+\e$B0UL#$7$^$9!#\e(B@samp{0} \e$B$O@5$7$$CM$NCf$G$b$C$H$bDc$$?t;z$G$9!#\e(B
+
+@node SOUP
+@subsection SOUP
+@cindex SOUP
+@cindex offline
+
+PC \e$B$N@$3&$N?M!9$O$h$/!"\e(B``\e$B%*%U%i%$%s\e(B'' \e$B%K%e!<%9%j!<%@$K$D$$$FOC$r$7$F$$$^\e(B
+\e$B$9!#$3$l$O%j!<%@$H%K%e!<%9G[Aw$r9gBN$5$;$?!"<B:_$9$k%b%s%9%?!<$G$9!#FbB"\e(B
+\e$B%b%G%`%W%m%0%i%`IU$-$G$M!#$-$c$O$O\e(B!
+
+\e$B$b$A$m$s!"2f$i$,\e(B Unix \e$B%-%A%,%$$N?M4V6!$O\e(B @code{uucp} \e$B$@$H\e(B
+\e$B$+\e(B @code{nntpd} \e$B$N$h$&$J$b$N$r;H$$!"?@$NNN0h$?$k%a!<%k!"%K%e!<%9$NG[Aw$r\e(B
+\e$B@5$7$/@_Dj$9$k$N$G$9!#$=$7$FKM$?$A$O$?$@IaDL$N%K%e!<%9%j!<%@$r;H$$$^$9!#\e(B
+
+\e$B$7$+$7!"$"$J$?$,$H$F$bCY$$%b%G%`$r;}$C$F$$$F$3$l$i$r@5$7$/@_Dj$9$k$3$H$K\e(B
+\e$B6=L#$,L5$1$l$P!"G>$_$=$K3Z$r$5$;$kJ}$r$9$k$N$b;~$K$OJXMx$G$9!#\e(B
+
+@sc{soup} \e$B$H8F$P$l$k%U%!%$%k7A<0$O%K%e!<%9$H%a!<%k$r%5!<%P!<$+$i2H$N%^%7\e(B
+\e$B%s$X$HE>Aw$7!"$=$l$r$^$?La$9$?$a$K3+H/$5$l$^$7$?!#$A$g$C$HLLE]$/$5$$$+$b\e(B
+\e$B$7$l$J$$$1$I$M!#\e(B
+
+\e$B$O$8$a$K$$$/$D$+MQ8l$r!#\e(B
+
+@table @dfn
+@item server
+\e$B$3$l$O30$N@$3&$K7R$,$C$F$$$F!"$"$J$?$,%K%e!<%9$H%a!<%k$rAw<u?.$9$k%^%7%s\e(B
+\e$B$G$9!#\e(B
+
+@item home machine
+\e$B$3$l$O$"$J$?$,<B:]$KFI$s$@$jJV;v$r=q$$$?$j$7$?$$%^%7%s$G$9!#$3$l$OIaDL!"\e(B
+\e$BB>$N@$3&$H$$$+$J$k7A$G$b@\B3$5$l$F$$$^$;$s!#\e(B
+
+@item packet
+\e$B%a%C%;!<%8$HL?Na$r4^$s$@$b$N!#%Q%1%C%H$K$OFs<oN`$"$j$^$9!#\e(B
+
+@table @dfn
+@item message packets
+\e$B$3$l$O%5!<%P!<$G:n$i$l$k%Q%1%C%H$G!"IaDL$O$"$J$?$,FI$`$?$a$N$?$/$5$s$N%a%C\e(B
+\e$B%;!<%8$,4^$^$l$F$$$^$9!#$3$l$i$O=i4|@_Dj$G$O\e(B @file{SoupoutX.tgz} \e$B$H$$$&\e(B
+\e$BL>A0$G$9!#$3$3$G\e(B @var{x} \e$B$O?t;z$G$9!#\e(B
+
+@item response packets
+(\e$BJV?.%Q%1%C%H\e(B) \e$B$3$N%Q%1%C%H$O<+Bp%^%7%s$G:n$i$l$k%Q%1%C%H$G!"IaDL$O$"$J\e(B
+\e$B$?$N=q$$$?JV;v$,4^$^$l$F$$$^$9!#$3$l$i$O=i4|@_Dj$G\e(B
+\e$B$O\e(B @file{SoupinX.tgz} \e$B$H$$$&L>A0$G$9!#$3$3$G\e(B @var{x} \e$B$O?t;z$G$9!#\e(B
+@end table
+@end table
+
+@enumerate
+
+@item
+\e$B$^$:\e(B @sc{soup} \e$B%Q%1%C%H$r:n$k$?$a$K%5!<%P!<$K%m%0%$%s$7$^$9!#\e(B
+@sc{soup} \e$B$N$?$a$N@lMQ$N%V%D\e(B (@code{awk} \e$B%W%m%0%i%`$N$h$&$J\e(B) \e$B$r;H$C$F$b\e(B
+\e$BNI$$$7!"\e(Bgnus \e$B$N\e(B @sc{soup} \e$BL?Na$r;H$C$F%Q%1%C%H$r:n$C$F$bNI$$$G\e(B
+\e$B$9\e(B (@kbd{O s} \e$B$"$k$$$O\e(B @kbd{G s b} \e$B$=$7$F\e(B @kbd{G s p})
+
+(@pxref{SOUP Commands})\e$B!#\e(B
+
+@item
+\e$B%Q%1%C%H$r<+Bp$KE>Aw$7$^$9!#EE<V$G!"A%$G!"<+F0<V$G!"$"$k$$$O%b%G%`$G!"2?\e(B
+\e$B$G$b$$$$$G$9!#\e(B
+
+@item
+\e$B%Q%1%C%H$r$"$J$?$N%[!<%`%G%#%l%/%H%j!<$KCV$-$^$9!#\e(B
+
+@item
+Gnus \e$B$r$"$J$?$N<+Bp%^%7%s$G$+$CHt$P$7$F!"\e(B@code{nnsoup} \e$B%P%C%/%(%s%I$r4p\e(B
+\e$BK\%5!<%P!<$"$k$$$OFs<!%5!<%P!<$H$7$F;HMQ$7$^$9!#\e(B
+
+@item
+\e$B5-;v$d%a!<%k$rFI$s$GI,MW$J$d$D$KJV;v$r=q$$$F%U%)%m!<%"%C%W5-;v$r=q$-$^\e(B
+\e$B$9\e(B (@pxref{SOUP Replies})\e$B!#\e(B
+
+@item
+@kbd{G s r} \e$BL?Na$r<B9T$7$F!"$3$l$i$NJV;v$r\e(B @sc{soup} \e$B%Q%1%C%H$K:-Jq$7$^\e(B
+\e$B$9!#\e(B
+
+@item
+\e$B$3$N%Q%1%C%H$r%5!<%P!<$KE>Aw$7$^$9!#\e(B
+
+@item
+Gnus \e$B$+$i\e(B @kbd{G s s} \e$BL?Na$r;H$C$F$3$N%Q%1%C%H$+$i%a!<%k$r=P$7$^$9!#\e(B
+
+@item
+\e$B$"$H$O$3$l$r;`$L$^$GB3$1$^$9!#\e(B
+
+@end enumerate
+
+\e$B$D$^$j4pK\E*$KFs<TJ,3d%7%9%F%`$,$G$-$?$3$H$K$J$j$^\e(B
+\e$B$9\e(B --- @code{nnsoup} \e$B$rFI$`$?$a$K!"\e(Bgnus \e$B$r\e(B @sc{soup} \e$B%Q%1%C%H$N:-Jq$HAw\e(B
+\e$B=P$K;H$$$^$9!#\e(B
+
+@menu
+* SOUP Commands::               @sc{soup} \e$B%Q%1%C%H$r:n@.!"Aw=P$9$kL?Na\e(B
+* SOUP Groups::                 @sc{soup} \e$B%Q%1%C%H$rFI$`%P%C%/%(%s%I\e(B
+* SOUP Replies::                @code{nnsoup} \e$B$K%a!<%k$H%K%e!<%9$r0z$-7Q$,$;$kJ}K!\e(B
+@end menu
+
+@node SOUP Commands
+@subsubsection SOUP \e$BL?Na\e(B
+
+\e$B$3$l$i$NL?Na$O\e(B @sc{soup} \e$B%Q%1%C%H$N:n@.$HA`:n$r9T$J$&$b$N$G$9!#\e(B
+
+@table @kbd
+@item G s b
+@kindex G s b (\e$B%0%k!<%W\e(B)
+@findex gnus-group-brew-soup
+\e$B8=:_$N%0%k!<%W$NA4$F$NL$FI5-;v$r:-Jq$9\e(B
+\e$B$k\e(B (@code{gnus-group-brew-soup})\e$B!#$3$N%3%^%s%I$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B
+\e$B$K=>$$$^$9!#\e(B
+
+@item G s w
+@kindex G s w (\e$B%0%k!<%W\e(B)
+@findex gnus-soup-save-areas
+\e$BA4$F$N\e(B @sc{soup} \e$B%G!<%?%U%!%$%k$rJ]B8$7$^\e(B
+\e$B$9\e(B (@code{gnus-soup-save-areas})\e$B!#\e(B
+
+@item G s s
+@kindex G s s (\e$B%0%k!<%W\e(B)
+@findex gnus-soup-send-replies
+\e$BJV?.%Q%1%C%H$+$iA4$F$NJV?.$rAw=P$9$k\e(B (@code{gnus-soup-send-replies})\e$B!#\e(B
+
+@item G s p
+@kindex G s p (\e$B%0%k!<%W\e(B)
+@findex gnus-soup-pack-packet
+\e$BA4$F$N%U%!%$%k$r\e(B  @sc{soup} \e$B%Q%1%C%H$K:-Jq$9\e(B
+\e$B$k\e(B (@code{gnus-soup-pack-packet})\e$B!#\e(B
+
+@item G s r
+@kindex G s r (\e$B%0%k!<%W\e(B)
+@findex nnsoup-pack-replies
+\e$BA4$F$NJV?.$rJV?.%Q%1%C%H$K:-Jq$9$k\e(B (@code{nnsoup-pack-replies})\e$B!#\e(B
+
+@item O s
+@kindex O s (\e$B35N,\e(B)
+@findex gnus-soup-add-article
+\e$B$3$N35N,%b!<%IL?Na$O!"8=:_$N5-;v$r\e(B @sc{soup} \e$B%Q%1%C%H$KDI2C$7$^\e(B
+\e$B$9\e(B (@code{gnus-soup-add-article})\e$B!#$3$l$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$K=>$$$^\e(B
+\e$B$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+@end table
+
+gnus \e$B$,$3$l$i$N<BBN$r$I$3$KCV$/$+$r%+%9%?%^%$%:$9$k$$$/$D$+$NJQ?t$,$"$j\e(B
+\e$B$^$9!#\e(B
+
+@table @code
+@item gnus-soup-directory
+@vindex gnus-soup-directory
+@sc{soup} \e$B%Q%1%C%H$r:n@.Cf$K\e(B gnus \e$B$,Cf4V%U%!%$%k$rJ]B8$9$k%G%#%l%/%H%j!<!#\e(B
+\e$B=i4|@_DjCM$O\e(B @file{~/SoupBrew/}\e$B!#\e(B
+
+@item gnus-soup-replies-directory
+@vindex gnus-soup-replies-directory
+\e$BJV?.%Q%1%C%HAw?.Cf$K\e(B gnus \e$B$,;HMQ$9$k0l;~%G%#%l%/%H%j!<!#\e(B
+@file{~/SoupBrew/SoupReplies/} \e$B$,=i4|@_DjCM!#\e(B
+
+@item gnus-soup-prefix-file
+@vindex gnus-soup-prefix-file
+gnus \e$B$,:G8e$K;H$C$?@\F,0z?t$rJ]B8$9$k%U%!%$%kL>!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{gnus-prefix}\e$B!#\e(B
+
+@item gnus-soup-packer
+@vindex gnus-soup-packer
+@sc{soup} \e$B%Q%1%C%H$r:-Jq$9$kL?NaJ8;zNs$N7A<0!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{tar cf - %s | gzip > $HOME/Soupout%d.tgz}\e$B!#\e(B
+
+@item gnus-soup-unpacker
+@vindex gnus-soup-unpacker
+@sc{soup} \e$B%Q%1%C%H$r<h$j=P$9L?NaJ8;zNs$N7A<0!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{gunzip -c %s | tar xvf -}\e$B!#\e(B
+
+@item gnus-soup-packet-directory
+@vindex gnus-soup-packet-directory
+gnus \e$B$,JV?.%Q%1%C%H$rC5$7$K9T$/>l=j!#=i4|@_DjCM$O\e(B @file{~/}\e$B!#\e(B
+
+@item gnus-soup-packet-regexp
+@vindex gnus-soup-packet-regexp
+@code{gnus-soup-packet-directory} \e$BFb$N\e(B @sc{soup} \e$B%Q%1%C%H$K%^%C%A$9$k@5\e(B
+\e$B5,I=8=!#\e(B
+@end table
+
+@node SOUP Groups
+@subsubsection SOUP \e$B%0%k!<%W\e(B
+@cindex nnsoup
+
+@code{nnsoup} \e$B$O\e(B @sc{soup} \e$B%Q%1%C%H$rFI$`$?$a$N%P%C%/%(%s%I$G$9!#$3$l$O\e(B
+\e$BF~$C$F$-$?%Q%1%C%H$rFI$_!"$=$l$r<h$j=P$7$F!"$"$J$?$,2K$J$H$-$KFI$`%G%#%l\e(B
+\e$B%/%H%j!<$KE83+$7$^$9!#\e(B
+
+\e$B$3$l$i$O$3$N?6$kIq$$$r%+%9%?%^%$%:$G$-$kJQ?t$G$9!#\e(B
+
+@table @code
+@item nnsoup-tmp-directory
+@vindex nnsoup-tmp-directory
+@code{nnsoup} \e$B$,\e(B @sc{soup} \e$B%Q%1%C%H$r<h$j=P$9$H$-!"$3$N%G%#%l%/%H%jFb$G\e(B
+\e$B9T$J$&\e(B (\e$B=i4|@_Dj$O\e(B @file{/tmp/})\e$B!#\e(B
+
+@item nnsoup-directory
+@vindex nnsoup-directory
+\e$B$=$7$F\e(B @code{nnsoup} \e$B$,$=$l$>$l$N%a%C%;!<%8$H:w0z%U%!%$%k$r$3$N%G%#%l%/\e(B
+\e$B%H%j!<$K0\F0$5$;$k!#=i4|@_Dj$O\e(B @file{~/SOUP/}\e$B!#\e(B
+
+@item nnsoup-replies-directory
+@vindex nnsoup-replies-directory
+\e$BA4$F$NJV?.$O!"JV?.%Q%1%C%H$K:-Jq$5$l$kA0$K$3$N%G%#%l%/%H%j!<$K3JG<$5$l$k!#\e(B
+\e$B=i4|@_Dj$O\e(B @file{~/SOUP/replies/}\e$B!#\e(B
+
+@item nnsoup-replies-format-type
+@vindex nnsoup-replies-format-type
+\e$BJV?.%Q%1%C%H$N\e(B @sc{soup} \e$B7A<0!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{?n} (rnews) \e$B$G!"$3$NJQ?t$K$O?($k$Y$-$G$O$J$$$H;d$O;W$$$^$9!#$?\e(B
+\e$B$V$sJ8=q$KL@5-$9$Y$-$G$5$($J$+$C$?$M!#$A$'$C\e(B! \e$B$b$&<jCY$l$+!#\e(B
+
+@item nnsoup-replies-index-type
+@vindex nnsoup-replies-index-type
+\e$BJV?.%Q%1%C%H$N:w0z$N<oN`!#=i4|@_DjCM$O\e(B @samp{?n} \e$B$G!"0UL#$O\e(B ``\e$B$J$7\e(B''\e$B!#$3\e(B
+\e$B$l$b$$$8$k$s$8$c$J$$$h\e(B!
+
+@item nnsoup-active-file
+@vindex nnsoup-active-file
+@code{nnsoup} \e$B$,$?$/$5$s$N>pJs$r3JG<$9$k>l=j!#$3$l$O\e(B @code{nntp} \e$B$N0UL#\e(B
+\e$B$G$N\e(B ``\e$B%"%/%F%#%V%U%!%$%k\e(B'' \e$B$G$O$J$/!"\e(BEmacs Lisp \e$B$N%U%!%$%k$G$9!#$3$N%U%!\e(B
+\e$B%$%k$rL5$/$7$F$7$^$C$?$j!"2?$+2u$7$F$7$^$C$?$i!"$"$J$?$O;`$K$^$9!#=i4|@_\e(B
+\e$BDjCM$O\e(B @file{~/SOUP/active} \e$B$G$9!#\e(B
+
+@item nnsoup-packer
+@vindex nnsoup-packer
+\e$BJV?.\e(B @sc{soup} \e$B%Q%1%C%H$r:-Jq$9$kL?NaJ8;zNs$N7A<0!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{tar cf - %s | gzip > $HOME/Soupin%d.tgz}\e$B!#\e(B
+
+@item nnsoup-unpacker
+@vindex nnsoup-unpacker
+\e$BF~$C$F$/$k\e(B @sc{soup} \e$B%Q%1%C%H$r<h$j=P$9$?$a$NL?NaJ8;zNs$N7A<0!#=i4|@_Dj\e(B
+\e$BCM$O\e(B @samp{gunzip -c %s | tar xvf -}\e$B!#\e(B
+
+@item nnsoup-packet-directory
+@vindex nnsoup-packet-directory
+\e$BF~$C$F$-$?%Q%1%C%H$r\e(B @code{nnsoup} \e$B$,C5$9>l=j!#=i4|@_DjCM$O\e(B @file{~/}\e$B!#\e(B
+
+@item nnsoup-packet-regexp
+@vindex nnsoup-packet-regexp
+\e$BF~$C$F$-$?\e(B @sc{soup} \e$B%Q%1%C%H$K%^%C%A$9$k@55,I=8=!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{Soupout}\e$B!#\e(B
+
+@item nnsoup-always-save
+@vindex nnsoup-always-save
+@code{nil} \e$B0J30$G$"$l$P!"%a%C%;!<%8$rEj9F$7$?8e$KJV?.%P%C%U%!$rJ]B8$9$k!#\e(B
+@end table
+
+@node SOUP Replies
+@subsubsection SOUP \e$BJV?.\e(B
+
+\e$BC1$K\e(B @code{nnsoup} \e$B$r;H$&$@$1$G$O!"\e(B@sc{soup} \e$BJV?.%Q%1%C%HCf$N$"$J$?$NEj\e(B
+\e$B9F$H%a!<%k$NAw?.$,!"KbK!$N$h$&$K<+F0E*$K=*N;$9$k$o$1$G$O$"$j$^$;$s!#$=$l\e(B
+\e$B$r5/$3$9$K$O$b$&$A$g$C$HF/$+$J$/$F$O$$$1$^$;$s!#\e(B
+
+@findex nnsoup-set-variables
+@code{nnsoup-set-variables} \e$BL?Na$O!"$"$J$?$NA4$F$N%U%)%m!<%"%C%W5-;v$HJV\e(B
+\e$B?.$r\e(B @sc{soup} \e$B%7%9%F%`$K3N<B$K=*N;$5$;$k$h$&$K!"E,@Z$JJQ?t$r@_Dj$7$^$9!#\e(B
+
+\e$BFCJL$K!"$3$l$,<B:]$K9T$o$l$k$3$H$G$9!#\e(B
+
+@lisp
+(setq message-send-news-function 'nnsoup-request-post)
+(setq message-send-mail-function 'nnsoup-request-mail)
+@end lisp
+
+\e$B$=$l$@$1$G$9!"$[$s$H$K!#$b$7\e(B @sc{soup} \e$B%7%9%F%`$K%K%e!<%9$@$1$rF~$l$?$+$C\e(B
+\e$B$?$i!":G=i$N9T$@$1$r;H$C$F$/$@$5$$!#$b$7%a!<%k$@$1$r\e(B @sc{soup} \e$B$5$;$?$+$C\e(B
+\e$B$?$i!"FsHVL\$r;H$C$F$/$@$5$$!#\e(B
+
+@node Mail-To-News Gateways
+@subsection \e$B%a!<%k$+$i%K%e!<%9$X$N%2!<%H%&%'%$\e(B
+@cindex mail-to-news gateways
+@cindex gateways
+
+\e$B$b$7$"$J$?$N%m!<%+%k$N\e(B @code{nntp} \e$B%5!<%P!<$,!"2?$i$+$NM}M3$GEj9F$r5v2D\e(B
+\e$B$7$F$$$J$1$l$P!"?t$"$k%a!<%k$+$i%K%e!<%9$X$N%2!<%H%&%'%$$r;H$C$FEj9F$9$k\e(B
+\e$B$3$H$,$G$-$^$9!#\e(B@code{nngateway} \e$B%P%C%/%(%s%I$O$3$N%$%s%?!<%U%'!<%9$rDs\e(B
+\e$B6!$7$^$9!#\e(B
+
+\e$B$3$N%P%C%/%(%s%I$+$i$O2?$bFI$_=P$;$J$$$3$H$KCm0U$7$F$/$@$5$$\e(B --- \e$B$3$l$O\e(B
+\e$BEj9F$9$k$?$a$@$1$K;H$o$l$^$9!#\e(B
+
+\e$B0J2<$O%5!<%P!<JQ?t$G$9!#\e(B
+
+@table @code
+@item nngateway-address
+@vindex nngateway-address
+\e$B$3$l$,%a!<%k!&%K%e!<%9%2!<%H%&%'%$$N%"%I%l%9$G$9!#\e(B
+
+@item nngateway-header-transformation
+@vindex nngateway-header-transformation
+\e$B%K%e!<%9%X%C%@!<$O!"%a!<%k!&%K%e!<%9%2!<%H%&%'%$$,<u$1IU$1$i$l$k$h$&$K!"\e(B
+\e$B4qL/$J7A$KJQ7A$7$F$*$+$J$/$F$O$J$i$J$$;~$,$"$j$^$9!#$3$NJQ?t$O$I$s$JJQ7A\e(B
+\e$B=hM}$,8F$S=P$5$l$k$Y$-$+$r<($7$F$*$j!"=i4|@_DjCM\e(B
+\e$B$O\e(B @code{nngateway-simple-header-transformation} \e$B$K$J$C$F$$$^$9!#$3$N4X\e(B
+\e$B?t$OJQ7A$9$k%X%C%@!<$KNN0h@)8B\e(B(narrow)\e$B$5$l$F8F$S=P$5$l!"0l8D$N0z\e(B
+\e$B?t\e(B --- \e$B%2!<%H%&%'%$$N%"%I%l%9$rM?$($i$l$^$9!#\e(B
+
+\e$B=i4|@_DjCM$N4X?t$OC1$K?7$7$$\e(B @code{To} \e$B%X%C%@!<$r!"\e(B@code{Newsgroups} \e$B%X%C\e(B
+\e$B%@!<$H%2!<%H%&%'%$%"%I%l%9$r$b$H$KA^F~$7$^$9!#Nc$($P!"0J2<$N$h$&\e(B
+\e$B$J\e(B@code{Newsgroups} \e$B%X%C%@!<\e(B
+
+@example
+Newsgroups: alt.religion.emacs
+@end example
+
+\e$B$r;}$D5-;v$K$O!"<!$N$h$&$J\e(B @code{To} \e$B%X%C%@!<$,A^F~$5$l$^$9!#\e(B
+
+@example
+To: alt-religion-emacs@@GATEWAY
+@end example
+
+\e$B0J2<$N4{@=4X?t$,B8:_$7$^$9\e(B:
+
+@findex nngateway-simple-header-transformation
+
+@table @code
+@item nngateway-simple-header-transformaton
+@var{newsgroup}@@@code{nngateway-address} \e$B$N$h$&$J\e(B @code{To} \e$B%X%C%@!<$r\e(B
+\e$B$D$/$j$^$9!#\e(B
+
+@findex nngateway-mail2news-header-transformation
+
+@item nngateway-mail2news-header-transformation
+@code{nngateway-address} \e$B$N$h$&$J\e(B @code{To} \e$B%X%C%@!<$r$D$/$j$^$9!#\e(B
+
+\e$B$3$3$KNc$,$"$j$^$9!#\e(B
+
+@lisp
+(setq gnus-post-method
+      '(nngateway
+        "mail2news@@replay.com"
+        (nngateway-header-transformation
+         nngateway-mail2news-header-transformation)))
+@end lisp
+@end table
+@end table
+
+\e$B$D$^$j!"$3$l$r;H$&$K$O!"$3$s$JIw$K$9$k$@$1$G$9!#\e(B
+
+@lisp
+(setq gnus-post-method '(nngateway "GATEWAY.ADDRESS"))
+@end lisp
+
+@node Combined Groups
+@section \e$B7k9g%0%k!<%W\e(B
+
+Gnus \e$B$O!"A4$F$N%0%k!<%W$N<oN`$r:.9g$7$F!"Bg$-$J%0%k!<%W$K7k9g$9$k$3$H$,\e(B
+\e$B$G$-$^$9!#\e(B
+
+@menu
+* Virtual Groups::              \e$B$?$/$5$s$N%0%k!<%W$N5-;v$r7k9g$9$k\e(B
+* Kibozed Groups::              \e$B%K%e!<%9%9%W!<%k$NCf$+$i$N5-;v$r8!:w$9$k\e(B
+* Namazu Groups::               Namazu \e$B$r;H$C$F%a!<%k$N;3$+$i5-;v$r<h$j=P$9\e(B
+@end menu
+
+@node Virtual Groups
+@subsection \e$B2>A[%0%k!<%W\e(B
+@cindex nnvirtual
+@cindex virtual groups
+
+nnvirtual \e$B%0%k!<%W\e(B (@dfn{nnvirtual group}) \e$B$O<B$OB>$N%0%k!<%W$N=89g0J>e\e(B
+\e$B$N2?J*$G$b$"$j$^$;$s!#\e(B
+
+\e$BNc$($P!"$b$7>.$5$J%0%k!<%W$r$?$/$5$sFI$`$N$,7y$K$J$C$F$-$?$i!"$=$l$i$r0l\e(B
+\e$B$D$NBg$-$J%0%k!<%W$KF~$l$F!"7y$K$J$k$/$i$$5pBg$G<j$KIi$($J$$%0%k!<%W$rFI\e(B
+\e$B$`$3$H$,$G$-$^$9!#$3$l$,%3%s%T%e!<%?!<$N3Z$7$_$@$M\e(B!
+
+\e$BA*BrJ}K!$H$7$F\e(B @code{nnvirtual} \e$B$r;XDj$7$F$/$@$5$$!#%"%I%l%9$O!"$=$l$r9=\e(B
+\e$B@.$9$k%0%k!<%W$K%^%C%A$9$k@55,I=8=$G$9!#\e(B
+
+\e$B2>A[%0%k!<%WFb$GIU$1$i$l$?A4$F$N0u$O!"$=$N9=@.%0%k!<%W$N5-;v$K$/$C$D$1$i\e(B
+\e$B$l$^$9!#$D$^$j!"$b$72>A[%0%k!<%WFb$G5-;v$K2D;k5-;v$N0u$r$D$1$k$H!"$=$N5-\e(B
+\e$B;v$O$b$H$b$H$N9=@.%0%k!<%W$NCf$G$b2D;k5-;v$K$J$j$^$9!#\e(B(\e$B$=$7$F5U$b@.$jN)\e(B
+\e$B$A$^$9\e(B --- \e$B9=@.%0%k!<%WFb$GIU$1$?0u$O2>A[%0%k!<%WFb$G$bI=<($5$l$^$9!#\e(B)
+\e$B6u$N2>A[%0%k!<%W$r:n$k$K$O!"%0%k!<%W%P%C%U%!$G\e(B @kbd{G V}
+(@code{gnus-group-make-empty-virtual}) \e$B$r<B9T$7!"\e(B@kbd{M-e}
+(@code{gnus-group-edit-group-method}) \e$B$G%a%=%C%I$N@55,I=8=$rJT=8$7$F2<$5\e(B
+\e$B$$!#\e(B
+
+\e$B$3$l$,!"\e(BAndrea Dworkin \e$B$K4X$9$kA4$F$N%K%e!<%9%0%k!<%W$r!"0l$D$N5pBg$G%7\e(B
+\e$B%"%o%;$J%K%e!<%9%0%k!<%W$K$^$H$a$k\e(B @code{nnvirtual} \e$BJ}K!$NNc$G$9!#\e(B
+
+@lisp
+(nnvirtual "^alt\\.fan\\.andrea-dworkin$\\|^rec\\.dworkin.*")
+@end lisp
+
+\e$B9=@.%0%k!<%W$O4pK\%0%k!<%W$G$b30It%0%k!<%W$G$b9=$$$^$;$s!#A4$FLdBjL5$/F0\e(B
+\e$B$/$O$:$G$9$,!"$b$7$"$J$?$N%3%s%T%e!<%?!<$,GzH/$G$b$7$F$7$^$C$?$i!"$=$l$O\e(B
+\e$B$?$V$s;d$,0-$$$s$G$7$g$&$M!#\e(B
+
+\e$B$$$/$D$+$N%5!<%P!<$+$iF1$8%0%k!<%W$r=8$a$k$3$H$O!"MxMQ<T\e(B
+\e$B$,\e(B Distribution \e$B%X%C%@!<$r;H$C$FG[I[HO0O$r@)8B$7$F$$$k>l9g$O!"Hs>o$KNI$$\e(B
+\e$B$+$bCN$l$^$;$s!#$b$7$"$J$?$,\e(B @samp{soc.motss} \e$B$r!"F|K\$N%5!<%P!<$H%N%k%&%'!<\e(B
+\e$B$N%5!<%P!<$NN>J}$+$iFI$_$?$1$l$P!"%0%k!<%W$N@55,I=8=$H$7$F0J2<$NCM$,;H$(\e(B
+\e$B$^$9!#\e(B
+
+@example
+"^nntp\\+server\\.jp:soc\\.motss$\\|^nntp\\+server\\.no:soc\\.motss$"
+@end example
+
+(\e$B$G$b$A$g$C$HCm0U!#\e(B@kbd{G m} \e$B$G%0%k!<%W$r:n@.$9$k$H$-$O!"%P%C%/%9%i%C%7%e\e(B
+\e$B$rFs=E$KIU$1$F$O$$$1$^$;$s!#$=$7$FJ8;zNs$N:G=i$H:G8e$N0zMQ5-9f$b<h$jJ'$C\e(B
+\e$B$F$/$@$5$$!#\e(B)
+
+\e$B$3$l$O$A$g$C$H$&$^$/F0:n$9$k$O$:$G$9\e(B --- \e$BN>J}$N%0%k!<%W$N5-;v$OA4It40A4\e(B
+\e$B$K0l$D$N%0%k!<%W$K$J$j!"=EJ#$bL5$$$O$:$G$9!#%9%l%C%II=<(\e(B (\e$B$H$=$NB>\e(B) \e$B$bDL\e(B
+\e$B>oDL$j$&$^$/F0:n$9$k$G$7$g$&$1$I!"5-;v$NJB$V=g=x$K$OLdBj$,$"$k$+$b$7$l$^\e(B
+\e$B$;$s!#F|IU$K$h$kJB$YBX$($O$3$3$G$O;EMM30$H$J$k$+$b$7$l$^$;\e(B
+\e$B$s\e(B (@pxref{Selecting a Group})\e$B!#\e(B
+
+\e$B$J$*!"$3$3$G0l$D$@$1@)8B$,$"$j$^$9\e(B --- \e$B2>A[%0%k!<%W$K4^$^$l$k%0%k!<%W$O\e(B
+\e$BA4$F@8$-$F$$$k\e(B(\e$B$9$J$o$A!"9XFI$^$?$OHs9XFI$N\e(B)\e$B>uBV$G$J$/$F$O$J$j$^$;$s!#:o\e(B
+\e$B=|$"$k$$$O%>%s%S%0%k!<%W$O\e(B @code{nnvirtual} \e$B%0%k!<%W$N9=@.%0%k!<%W$K$J$k\e(B
+\e$B$3$H$O$G$-$^$;$s!#\e(B
+
+@vindex nnvirtual-always-rescan
+@code{nnvirtual-always-rescan} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"\e(B
+@code{nnvirtual} \e$B$O2>A[%0%k!<%W$KF~$C$?$H$->o$K!"L$FI5-;v$rAv::$7$^$9!#\e(B
+\e$B$3$NJQ?t$,\e(B @code{nil} (\e$B$3$l$,=i4|@_Dj\e(B)\e$B$G$"$C$F!"2>A[%0%k!<%W$r:n@.$7$?8e\e(B
+\e$B$K9=@.%0%k!<%WFb$N5-;v$rFI$s$@>l9g$O!"$=$N9=@.%0%k!<%W$GFI$^$l$?5-;v$O!"\e(B
+\e$B2>A[%0%k!<%W$KF~$C$?$H$-$KI=<($5$l$k$G$7$g$&!#$b$76&DL$N9=@.%0%k!<%W$r;}\e(B
+\e$B$DFs$D$N2>A[%0%k!<%W$,$"$k>l9g$K$b$3$N1F6A$,$"$j$^$9!#$=$N>l9g$O$3$NJQ?t\e(B
+\e$B$r\e(B @code{t} \e$B$K$7$?J}$,NI$$$G$9!#$"$k$$$O2>A[%0%k!<%W$KF~$k;~$K!"Kh2s$=$N\e(B
+\e$B%0%k!<%W$N>e$G\e(B @code{M-g} \e$B$rC!$$$F$bNI$$$G$9\e(B --- \e$B$3$l$O$[$\F1MM$N8z2L$,\e(B
+\e$B$"$j$^$9!#\e(B
+
+@code{nnvirtual} \e$B$O%a!<%k$H%K%e!<%9$NN>J}$N%0%k!<%W$r9=@.%0%k!<%W$H$9$k\e(B
+\e$B;v$,$G$-$^$9!#\e(B@code{nnvirtual} \e$B%0%k!<%W$N5-;v$KJVEz$9$k$H$-$O!"\e(B
+@code{nnvirtual} \e$B$O5-;v$N=P=j$N9=@.%0%k!<%W$N%P%C%/%(%s%I$K$=$l$,%K%e!<\e(B
+\e$B%9$N%P%C%/%(%s%I$G$"$k$+%a!<%k$N%P%C%/%(%s%I$G$"$k$+$r?R$M$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#$7$+$7!"\e(B@kbd{^} \e$B$r$7$?$H$-$K$O!"IaDL$O9=@.%P%C%/%(%s%I$,$3$l$rCN$k\e(B
+\e$B3N$+$JJ}K!$O$J$/!"$=$N>l9g$O!"\e(B@code{nnvirtual} \e$B$O\e(B gnus \e$B$K5-;v$O%K%e!<%9\e(B
+\e$B$G$J$$%P%C%/%(%s%I$+$iMh$?$H9p$2$k;v$K$J$j$^$9!#\e(B(\e$B0BA4$N$?$a$K!#\e(B)
+
+\e$B$3$N$h$&$J>l9g$O!"%a%C%;!<%8%P%C%U%!$G$N\e(B @kbd{C-c C-n} \e$B$,1~Ez$7$h$&$H$7\e(B
+\e$B$F$$$k5-;v$+$i\e(B @code{Newsgroups} \e$B9T$rH4$-=P$7$FA^F~$7$^$9!#\e(B
+
+@code{nnvirtual} \e$B%0%k!<%W$O!"9=@.%0%k!<%W$+$i5-;v$H0u0J30$O7Q>5$7$^$;$s!#\e(B
+\e$BNc$($P%0%k!<%W%Q%i%a!<%?$b$=$&$J$N$G$9$,!"$=$l$i$O7Q>5$5$l$^$;$s!#\e(B
+
+@node Kibozed Groups
+@subsection Kiboze \e$B%0%k!<%W\e(B
+@cindex nnkiboze
+@cindex kibozing
+
+@dfn{Kiboze} \e$B$9$k!"$H$O!"\e(B``\e$B%K%e!<%9%9%W!<%kA4It\e(B (\e$B$"$k$$$O$=$N0lIt\e(B) \e$B$+\e(B
+\e$B$i\e(B grep \e$B$9$k$3$H\e(B'' \e$B$H\e(B @acronym{OED} (\e$B%*%C%/%9%U%)!<%IBg<-E5\e(B) \e$B$K$h$C$FDj\e(B
+\e$B5A$5$l$F$$$^$9!#\e(B@code{nnkiboze} \e$B$O$3$l$r$"$J$?$N$?$a$K9T$C$F$/$l$k%P%C%/\e(B
+\e$B%(%s%I$G$9!#4r$7$$$M\e(B! \e$B$3$l$G$I$s$J\e(B @acronym{NNTP} \e$B%5!<%P!<$G$b!"Lr$KN)$?\e(B
+\e$B$J$$MW5a$G;_$^$C$F$7$^$&$^$G9s;H$9$k$3$H$,$G$-$k$M!#$"$"!"$J$s$F9,$;$J$s\e(B
+\e$B$@\e(B!
+
+@kindex G k (\e$B%0%k!<%W\e(B)
+kiboze \e$B%0%k!<%W$r:n@.$9$k$K$O!"%0%k!<%W%P%C%U%!$G\e(B @kbd{G k} \e$BL?Na$r;H$$$^\e(B
+\e$B$9!#\e(B
+
+@code{nnkiboze} \e$BJ}K!$K$*$1$k%"%I%l%9Ms$O!"\e(B@code{nnvirtual} \e$B$HF1MM$K!"\e(B
+@code{nnkiboze} \e$B$K\e(B ``\e$B4^$a$?$$\e(B'' \e$B%0%k!<%W$K%^%C%A$9$k@55,I=8=$G$9!#$3$3\e(B
+\e$B$,\e(B @code{nnkiboze} \e$B$H\e(B @code{nnvirtual} \e$B%P%C%/%(%s%I$N:G$bN`;w$7$F$$$kE@\e(B
+\e$B$G$9!#\e(B
+
+\e$B$3$N9=@.%0%k!<%W$rNs5s$9$k@55,I=8=$K2C$($F!"\e(B@code{nnkiboze} \e$B%0%k!<%W$K$O!"\e(B
+\e$B%0%k!<%WFb$N$I$N5-;v$r4^$a$k$+$r7h$a$k%9%3%"%U%!%$%k$,$J$/$F$O$J$j$^$;\e(B
+\e$B$s\e(B (@pxref{Scoring})\e$B!#\e(B
+
+@kindex M-x nnkiboze-generate-groups
+@findex nnkiboze-generate-groups
+\e$B$"$J$?$NM_$7$$\e(B @code{nnkiboze} \e$B%0%k!<%W$r:n@.$7$?8e$K$O!"\e(B
+@kbd{M-x nnkiboze-generate-groups} \e$B$r<B9T$7$J$1$l$P$J$j$^$;$s!#$3$NL?Na\e(B
+\e$B$O;~4V$,$+$+$j$^$9!#$H$C$F$b$+$+$j$^$9!#$9$4$/!"$9$4!<$/$+$+$j$^$9!#\e(B
+Gnus \e$B$O$=$N\e(B @code{nnkiboze} \e$B%0%k!<%W$N0lIt$H$J$k$Y$-5-;v$,$"$k$+$I$&$+$r\e(B
+\e$BD4$Y$k$?$a$K!"A4It$N9=@.%0%k!<%W$NA4It$N5-;v$KBP$7$F%X%C%@!<$r<hF@$7!"$=\e(B
+\e$B$l$iA4$F$KBP$7$F%9%3%"=hM}$r<B9T$7$J$/$F$O$J$i$J$$$N$G$9!#\e(B
+
+\e$B9=@.%0%k!<%W$N?t$rM^$($k$h$&$K!"8BDj$7$?@55,I=8=$r;H$C$F$/$@$5$$!#$5$b$J\e(B
+\e$B$$$H!"$"$J$?$N$H$3$m$N%7%9%F%`4IM}<T$rE\$i$;$F$7$^$C$F!"\e(B
+@acronym{NNTP} \e$B%5!<%P!<$+$i$"$J$?$rDI$$=P$7$FFsEY$HF~$l$J$$$h$&$K$7$F$7\e(B
+\e$B$^$&$+$bCN$l$^$;$s!#IT47$l$J?M$,$h$/$d$k$3$H$G$9!#\e(B
+
+@code{nnkiboze} \e$B$N9=@.%0%k!<%W$O@8$-$F$$$kI,MW$O$"$j$^$;$s\e(B --- \e$B;`$s$G$F\e(B
+\e$B$bNI$$$7!"30It%0%k!<%W$G$b9=$$$^$;$s!#L5@)8B$G$9!#\e(B
+
+@vindex nnkiboze-directory
+@code{nnkiboze} \e$B%0%k!<%W$N@8@.$K$h$C$F!"Fs$D$N%U%!%$\e(B
+\e$B%k\e(B @code{nnkiboze-directory} \e$BFb$K:n@.$5$l$^$9!#$3$N=i4|@_DjCM\e(B
+\e$B$O\e(B @file{~/News/kiboze/} \e$B$G$9!#0lJ}$N%U%!%$%k$O$=$N%0%k!<%W$NA45-;v\e(B
+\e$B$N\e(B @acronym{NOV} \e$B%X%C%@!<9T$r4^$s$G$$$F!"$b$&0lJ}$O9=@.5-;v$r8+$D$1$k$?\e(B
+\e$B$a$K$I$N%0%k!<%W$,8!:w$5$l$?$+$N>pJs$r3JG<$9$k!"\e(B@file{.newsrc} \e$B$NJd=u%U%!\e(B
+\e$B%$%k$G$9!#\e(B
+
+@code{nnkiboze} \e$B%0%k!<%WFb$N4{FI$H$J$C$?5-;v$O!"$=$N5-;v\e(B
+\e$B$N\e(B @acronym{NOV} \e$B9T$,\e(B @acronym{NOV} \e$B%U%!%$%k$+$i:o=|$5$l$^$9!#\e(B
+
+@node Namazu Groups
+@subsection Namazu \e$B$r;H$C$F%a!<%k$N;3$+$i5-;v$r<h$j=P$9\e(B
+@cindex namazu
+
+\e$B%a!<%k$OF|!9Cy$^$C$F$$$/$P$+$j$G$9!#N.NL$NB?$$%a!<%j%s%0%j%9%H$r9XFI$7\e(B
+\e$B$F$$$k>l9g$K$O!"FC$K!#$G$b!"BgDq$N>l9g!"2ACM$"$k5-;v$O$4$/>/?t$G!"$=$N\e(B
+\e$B5-;v$rBgNL$N5-;v$N;3$+$i8+$D$1=P$9$N$O!"$H$F$b:$Fq$J$3$H$G$9!#\e(B
+
+\e$B$3$&$$$C$?$3$H$3$=!"%3%s%T%e!<%?$,$7$F$/$l$k$Y$-;E;v$G$9$h$M!#\e(BGnus \e$B$O!"\e(B
+Namazu \e$B$r;H$C$F!"%a!<%k$N;3$+$i$"$J$?$N9%$-$J%-!<%o!<%I$r4^$`5-;v$r8+\e(B
+\e$B$D$1=P$9J}K!$rDs6!$7$^$9!#\e(B
+
+\e$B:G=i$KHa$7$$$*CN$i$;$,$R$H$D!#\e(B@file{gnus-namazu.el} \e$B$O!"8=;~E@$G$O!"\e(B
+@code{nnml} \e$B%P%C%/%(%s%I$"$k$$$O\e(B @code{nnmh} \e$B%P%C%/%(%s%I$K$h$C$FJ]B8\e(B
+\e$B$5$l$F$$$k5-;v$H!"\e(B@code{gnus-cache-enter-article} \e$B$K$h$C$F1JB32=$5$l$?\e(B
+\e$B5-;v$7$+!"<h$j07$&$3$H$,$G$-$^$;$s!#\e(B@code{nnimap} \e$B%P%C%/%(%s%I\e(B
+\e$B$d\e(B @code{nnmbox} \e$B%P%C%/%(%s%I$r;H$C$F$$$k?M$O!"$4$a$s$J$5$$!#\e(B
+
+\e$B$=$l$G$O5$$r<h$jD>$7$F!"$^$:!"\e(BNamazu \e$B$r;H$($k$h$&$K$7$^$7$g$&!#>\$7$$\e(B
+\e$B$3$H$O!"<!$N%Z!<%8$GCN$k$3$H$,$G$-$^$9!#\e(B
+
+@example
+  @uref{http://namazu.org/}
+@end example
+
+@findex gnus-namazu-create-index
+\e$B<!$K!"$"$J$?$NHkB"$N%a!<%k$H1JB35-;v$N;3$N:w0z$r:n$k$?$a$K!"\e(B
+@kbd{M-x gnus-namazu-create-index} \e$B$H$7$F$/$@$5$$!#$5$"!"$3$l$G=`Hw$,\e(B
+\e$B$G$-$?$O$:$G$9!#\e(B
+
+@kindex C-c C-n (\e$B%0%k!<%W\e(B)
+@kindex C-c C-n (\e$B35N,\e(B)
+@findex gnus-namazu-search
+\e$B%0%k!<%W%P%C%U%!$G\e(B@kbd{C-c C-n}\e$B$HF~NO$9$k$H!"8!:w<0$r?R$M$i$l$^$9$+$i!"\e(B
+\e$BE,Ev$JC18l$rF~NO$7$F$/$@$5$$!#Nc$($P\e(B:
+
+@example
+  @kbd{C-c C-n gnus namazu RET}
+@end example
+
+\e$B$3$&$9$k$H!"\e(Bgnus \e$B$H\e(B namazu \e$B$NAPJ}$N%-!<%o!<%I$rF1;~$K4^$`%a!<%k$rA4$F\e(B
+\e$BC5$7=P$7!"$=$l$i$N%a!<%k$+$i$J$k2>A[%0%k!<%W$r:n@.$7$^$9\e(B (@pxref{Virtual
+Groups})\e$B!#\e(B
+
+@kbd{C-c C-n}\e$B$K$h$C$F8F$S=P$5$l$kL?Na\e(B @code{gnus-namazu-search} \e$B$O!"\e(B
+gnus \e$B$NDL>o$N?t;z@\F,<-$d!"%W%m%;%9@\F,<-$rM}2r$7$^$9!#$G$9$+$i!"$"$J\e(B
+\e$B$?$,!"$"$k%0%k!<%W$@$1$rBP>]$H$7$F8!:w$r<B9T$7$?$$$J$i$P!"$=$N%0%k!<%W\e(B
+\e$B$N9T$K0\F0$7$F!"<!$N$h$&$K8!:w$9$k$3$H$,$G$-$^$9!#\e(B
+
+@example
+  @kbd{1 C-c C-n namazu RET}
+@end example
+
+\e$B$^$?!"35N,%P%C%U%!$+$i!"$$$-$J$j8!:w$9$k$3$H$b$G$-$^$9!#$3$N>l9g!"8!:w\e(B
+\e$BBP>]$O!"<+F0E*$K$=$N%0%k!<%W$K8BDj$5$l$^$9!#Nc$($P!"$"$J$?$,$"$k%0%k!<\e(B
+\e$B%W$r1\MwCf$K!"$=$N%0%k!<%W$K$*$1$k<+J,$N2a5n$r?6$jJV$j$?$/$J$C$?$i!"<!\e(B
+\e$B$N$h$&$K$9$l$PNI$$$N$G$9!#\e(B
+
+@example
+  @kbd{C-c C-n +from:"Your E-Mail Address" RET}
+@end example
+
+@vindex gnus-namazu-index-update-interval
+Namazu \e$B$O!";vA0$K=`Hw$5$l$?:w0z$rMQ$$$F8!:w$r9T$&$h$&$K@_7W$5$l$?8!:w\e(B
+\e$B%(%s%8%s$J$N$G!":w0z$KEPO?$5$l$F$$$J$$%U%!%$%k$O40A4$KL5;k$5$l$^$9!#$D\e(B
+\e$B$^$j!"Dj4|E*$K\e(B @code{mknmz} \e$B$r8F$S=P$7$F!"?7$?$J%a!<%k$N:w0z$rDI2C$7$J\e(B
+\e$B$$$H!"?7$7$$%a!<%k$O$$$D$^$G$?$C$F$b8!:wBP>]$K$J$i$J$$$3$H$K$J$j$^$9!#\e(B
+@file{gnus-namazu.el} \e$B$O!"\e(B@code{gnus-namazu-index-update-interval} \e$B$K\e(B
+\e$B;XDj$5$l$?4|4VKh$K<+F0E*$K:w0z$r99?7$9$k5!G=$rDs6!$7$F$$$^$9!#%G%#%U%)%k\e(B
+\e$B%H$N@_Dj$G$O!"\e(B3\e$BF|$*$-$K:w0z$r99?7$9$k$h$&$K$J$C$F$$$^$9$,!"$b$C$HIQHK\e(B
+\e$B$K\e(B (\e$BNc$($P\e(B1\e$BF|$*$-\e(B) \e$B$K99?7$9$k$h$&$K$7$?$$$J$i$P!"0J2<$N@_Dj\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B$KDI2C$7$F$/$@$5$$!#\e(B
+
+
+@example
+(setq gnus-namazu-index-update-interval 86400)
+@end example
+
+\e$B5U$K!":w0z$N99?7$r<+F0E*$K9T$$$?$/$J$$$J$i$P!"0J2<$N;XDj\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B$KDI2C$7$F$/$@$5$$!#\e(B
+
+@example
+(setq gnus-namazu-index-update-interval nil)
+@end example
+
+@findex{gnus-namazu-update-all-indices}
+\e$B$3$N>l9g!":w0z$r<jF0$G99?7$9$k$?$a$K\e(B @kbd{M-x
+gnus-namazu-update-all-indices} \e$B$H$9$kI,MW$,$"$k$+$b$7$l$^$;$s!#\e(B
+
+@node Gnus Unplugged
+@section Gnus \e$B$N@Z$jN%$7\e(B
+@cindex offline
+@cindex unplugged
+@cindex agent
+@cindex gnus agent
+@cindex gnus unplugged
+
+\e$B$$$K$7$($N;~Be\e(B(\e$B$*$h$=\e(B 1988 \e$BG/\e(B2\e$B7n:"\e(B)\e$B!"?M!9$O%K%e!<%9%j!<%@!<$r!"Bg$-$J%^\e(B
+\e$B%7%s$N>e$G%M%C%H%o!<%/$K1JB3E*$K@\B3$7$FAv$i$;$F$$$^$7$?!#%K%e!<%9$NG[Aw\e(B
+\e$B$O%K%e!<%9%5!<%P!<$K$h$C$F<h$j07$o$l!"A4$F$N%K%e!<%9%j!<%@!<$,$9$Y$-$3$H\e(B
+\e$B$O!"%K%e!<%9$rFI$`$3$H$G$"$C$?$N$G$9!#?.$8$i$l$J$$$+$b$7$l$^$;$s$,!#\e(B
+
+\e$B:#F|$G$O!"B?$/$N?M!9$O<+Bp$G%K%e!<%9$d%a!<%k$rFI$_!"%M%C%H%o!<%/$K@\B3$9\e(B
+\e$B$k$?$a$K%b%G%`$NN`$r;H$$$^$9!#EEOCBe$N@A5a=q$,G|Bg$J$b$N$K>e$i$J$$$h$&$K!"\e(B
+\e$BA4$F$N%K%e!<%9$H%a!<%k$r5[$$>e$2!"EEOC$r@Z$j!"?t;~4V3]$1$FFI$_!"$=$7$FAw\e(B
+\e$B$j$?$$JV?.$rA4$FAw?.$9$k!"$H$$$&<jCJ$r;}$D$3$H$ONI$$$3$H$G$"$j$^$7$g$&!#\e(B
+\e$B$"$H$O$3$N<j=g$r7+$jJV$9$N$G$9!#\e(B
+
+\e$B$b$A$m$s!"$3$l$r9T$&$?$a$K%K%e!<%9%5!<%P!<$r;H$&$3$H$b$G$-$^$9!#;d\e(B
+\e$B$O\e(B @code{inn} \e$B$r\e(B @code{slurp}, @code{pop}, @code{sendmail} \e$B$H0l=o$K$3$3\e(B
+\e$B?tG/;H$C$F$-$^$7$?$,!"$7$+$7$3$l$OB`6~$J;E;v$G$9!#$b$7$"$k%^%7%s>e$G%K%e!<\e(B
+\e$B%9$rFI$`?M$,$"$J$?$7$+$$$J$1$l$P!"%K%e!<%9%5!<%P!<$N5!G=$r%K%e!<%9%j!<%@!<\e(B
+\e$B$KG$$;$k$h$&$K$9$k$3$H$OM}$K$+$J$C$F$$$^$9!#\e(B
+
+Gnus \e$B$r\e(B ``\e$B%*%U%i%$%s\e(B'' \e$B$N%K%e!<%9%j!<%@!<$H$7$F;EN)$F$k$N$O6K$a$F4JC1$G\e(B
+\e$B$9!#<B:]!"$"$J$?$O2?$b@_Dj$9$kI,MW$,L5$$$N$G$9!#\e(B
+
+\e$B$b$A$m$s!"$3$l$r%*%U%i%$%s%K%e!<%9%j!<%@!<$H$7$F;H$&$K$O!"$$$/$D$+?7$7$$\e(B
+\e$BL?Na$r3P$($J$/$F$O$J$j$^$;$s!#\e(B
+
+@menu
+* Agent Basics::                \e$B$3$l$i$O$I$&F0$/$N$+\e(B
+* Agent Categories::            \e$B2?$r%@%&%s%m!<%I$9$k$+$r\e(B gnus \e$B%(!<%8%'%s%H$K65$($kJ}K!\e(B
+* Agent Commands::              \e$B3F%P%C%U%!!<$G$N?7$7$$L?Na\e(B
+* Agent Visuals::               \e$B%(!<%8%'%s%H$,35N,%P%C%U%!$KJQ2=$r$b$?$i$9$+$b$7$l$J$$J}K!\e(B
+* Agent as Cache::              \e$B%(!<%8%'%s%H$OBg$-$J%-%c%C%7%e$G$b$"$k\e(B
+* Agent Expiry::                \e$B8E$$5-;v$r>C$9J}K!\e(B
+* Agent Regeneration::          \e$BDL?.@ZCG$dB>$N;v8N$+$i2sI|$9$kJ}K!\e(B
+* Agent and IMAP::              \e$B%(!<%8%'%s%H$r\e(B @acronym{IMAP} \e$B$G;H$&J}K!\e(B
+* Outgoing Messages::           \e$BEj9F!"%a!<%k$r=P$9$H$-$K$J$K$,5/$3$k$N$+\e(B?
+* Agent Variables::             \e$B%+%9%?%^%$%:$O3Z$7\e(B
+* Example Setup::               \e$B%*%U%i%$%s?M4V$N$?$a$N\e(B @file{~/.gnus.el} \e$B$NNc\e(B
+* Batching Agents::             @code{cron} \e$B%8%g%V$K$h$k%K%e!<%9<hF@J}K!\e(B
+* Agent Caveats::               \e$B$"$J$?$,M=A[$9$k$3$H$H!"$=$l$,<B:]$K$9$k$3$H\e(B
+* Control Agents::              Offline \e$B$r%3%s%H%m!<%k$9$k\e(B gnus-offline
+@end menu
+
+@node Agent Basics
+@subsection \e$B%(!<%8%'%s%H$N4pAC\e(B
+
+\e$B$^$:!"$$$/$D$+$NMQ8l$rJRIU$1$F$*$-$^$7$g$&!#\e(B
+
+\e$B%M%C%H%o!<%/$H$NDL?.$,@Z$l$F$$$k$H$-\e(B (\e$B$=$7$F%(!<%8%'%s%H$,$=$l$rCN$i$5$l\e(B
+\e$B$F$$$k$H$-\e(B)\e$B!"\e(Bgnus \e$B%(!<%8%'%s%H$O@Z$jN%$5$l$F$$$k\e(B (@dfn{unplugged}) \e$B$H8@\e(B
+\e$B$$$^$9!#%M%C%H%o!<%/$NDL?.$,I|3h$7\e(B (\e$B$=$7$F\e(B gnus \e$B$,$=$l$rCN$l$P\e(B)\e$B!"%(!<%8%'\e(B
+\e$B%s%H$O:9$79~$^$l$F$$$k\e(B (@dfn{plugged}) \e$B$H8@$$$^$9!#\e(B
+
+\e$B%m!<%+%k\e(B (@dfn{local}) \e$B%^%7%s$H$O!"$"$J$?$,?($C$F$$$k%^%7%s$G!"%M%C%H%o!<\e(B
+\e$B%/$K7QB3E*$K@\B3$5$l$F$$$k$b$N$G$O$"$j$^$;$s!#\e(B
+
+\e$B%@%&%s%m!<%I\e(B (@dfn{downloading}) \e$B$H$O%M%C%H%o!<%/$+$i2?$+$r$"$J$?$N%m!<\e(B
+\e$B%+%k%^%7%s$K<h$C$F$/$k$3$H$r0UL#$7$^$9!#%"%C%W%m!<\e(B
+\e$B%I\e(B (@dfn{uploading}) \e$B$O$=$N5U$r$9$k$3$H$G$9!#\e(B
+
+\e$B$4B8CN$N$h$&$K\e(B gnus \e$B$O$"$J$?$,%I%8$rF'$`$9$Y$F$N5!2q$rDs6!$7$^$9!#$=$l$r\e(B
+\e$B=@Fp@-$H8@$&?M$b$$$^$9!#$5$i$K\e(B gnus \e$B$OBg$$$K%+%9%?%^%$%:2DG=$G!"$=$l$O%f!<\e(B
+\e$B%6$,!"\e(Bgnus \e$B$,$I$N$h$&$KF0:n$9$k$+$K$D$$$FH/8@8"$r;}$C$F$$$k$3$H$r0UL#$7\e(B
+\e$B$^$9!#B>$N%K%e!<%9%j!<%@!<$OM-L5$r8@$o$:$"$J$?$K%I%8$rF'$^$;$k$+$b$7$l$^\e(B
+\e$B$;$s$,!"\e(Bgnus \e$B$G$O$"$J$?$KA*Br8"$,$"$j$^$9\e(B!
+
+Gnus \e$B$O<B:]$K$O\e(B plugged \e$B$^$?$O\e(B unplugged \e$B$N$I$A$i$N>uBV$K$b$"$j$^$;$s!#\e(B
+\e$B$b$C$H@53N$K8@$($P!"%5!<%P!<$4$H$K$=$l$>$l$N>uBV$r;}$A$^$9!#$3$l$O!"$$$/\e(B
+\e$B$D$+$N%5!<%P!<$,@\B3$G$-$J$$$H$-$K!"B>$N%5!<%P!<$O@\B3$G$-$k$3$H$r0UL#$7\e(B
+\e$B$^$9!#$5$i$K!"\e(B Agent \e$B$K$h$C$F$$$/$D$+$N%5!<%P!<$r$9$Y$FL5;k$9$k$3$H$,$G\e(B
+\e$B$-$^$9\e(B (\e$B$=$N0UL#$O!"$=$l$i$,$$$D$b\e(B plugged \e$B$K$J$C$F$$$k$N$H;w$F$$$k$H$$\e(B
+\e$B$&$3$H$G$9\e(B)\e$B!#\e(B
+
+Agent \e$B$r@Z$jN%$7$F$b!"$J$<\e(B gnus \e$B$,%M%C%H$K@\B3$7$F$$$k$N$+$,$$$V$+$7$/;W\e(B
+\e$B$o$l$?$H$-!"9T$&$Y$-<!$N%9%F%C%W$O%5!<%P!<$,$9$Y$F%(!<%8%'%s%H2=$5$l$F$$\e(B
+\e$B$k$+$I$&$+$r4Q;!$9$k$3$H$G$9!#%(!<%8%'%s%H2=$5$l$F$$$J$$%5!<%P!<$,$"$C$?\e(B
+\e$B$i!"$"$J$?$OHH?M$r8+$D$1$?$N$G$9!#\e(B
+
+\e$B$b$&0l$D$N>uBV$O\e(B @dfn{offline} \e$B$G$9!#%5!<%P!<$O$H$-$I$-E~C#2DG=$G$O$J$/\e(B
+\e$B$J$j$^$9!#\e(BGnus \e$B$,$3$N$3$H$rCN$k$H!"$=$N%5!<%P!<$r\e(B offline \e$B$N>uBV$K@Z$j49\e(B
+\e$B$($F$bNI$$$+$I$&$+$r?R$M$^$9!#$O$$!"$HEz$($?$J$i$P!"\e(B(offline \e$B$KLa$7$FNI\e(B
+\e$B$$$+$H\e(B gnus \e$B$,?R$M$?>l9g0J30$O\e(B) \e$B%5!<%P!<$OB?>/\e(B unplugged \e$B$@$C$?$H$-$N$h\e(B
+\e$B$&$K?6$kIq$$$^$9!#\e(B
+
+\e$B%(!<%8%'%s%H$r;H$C$?E57?E*$J\e(B gnus \e$B$NBPOCA`:n$r8+$F$_$^$7$g$&!#\e(B
+
+@itemize @bullet
+
+@item
+@findex gnus-unplugged
+Gnus \e$B$r\e(B @code{gnus-unplugged} \e$B$G5/F0$7$^$9!#$3$l$O\e(B gnus \e$B%(!<%8%'%s%H$r@Z\e(B
+\e$B$jN%$5$l$F$$$k>uBV$G5/F0$7$^$9!#$3$N>uBV$G$O!"$9$G$K<hF@$7$F$$$k%K%e!<%9\e(B
+\e$B5-;v$OA4$FFI$`$3$H$,$G$-$^$9!#\e(B
+
+@item
+\e$B$=$7$F!"?7$7$$%K%e!<%9$,E~Ce$7$F$$$k$+$I$&$+$rD4$Y$k$3$H$K$7$^$9!#$"$J$?\e(B
+\e$B$O\e(B (PPP \e$B$+2?$+$r;H$C$F\e(B) \e$B$"$J$?$N%^%7%s$r%M%C%H%o!<%/$K@\B3$7!"\e(Bgnus \e$B$r:9\e(B
+\e$B$79~$`$?$a$K\e(B @kbd{J j} \e$B$rC!$-!"$=$7$FIaDL$O?7Ce%a!<%k$r8!::$9$k$?$a\e(B
+\e$B$K\e(B @kbd{g} \e$B$r;H$$$^$9!#\e(Bgnus \e$B%(!<%8%'%s%H$,@Z$jN%$5$l$F$$\e(B
+\e$B$k\e(B (@dfn{unplugged}) \e$B$H$-$N?7Ce%a!<%k$N8!::$K$D$$$F\e(B
+\e$B$O\e(B @ref{Mail Source Specifiers} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item
+\e$B$=$7$F!"$=$N>l$G$9$0$K?7$7$$%K%e!<%9$rFI$`$3$H$b$G$-$^$9$7!"%K%e!<%9$r%m!<\e(B
+\e$B%+%k%^%7%s$K%@%&%s%m!<%I$9$k$3$H$b$G$-$^$9!#8e<T$r<B9T$7$?$1$l$P!"\e(B
+@kbd{g} \e$B$r2!$7$F?7Ce%a!<%k$r8!::$7$F$+$i\e(B @kbd{J s} \e$B$GA4%0%k!<%W$+$iE,@Z\e(B
+\e$B$J5-;v$rA4$F<hF@$7$^$9!#\e(B(Gnus \e$B$K$I$N5-;v$r%@%&%s%m!<%I$7$?$$$+$r;XDj$9$k\e(B
+\e$B$K$O\e(B @ref{Agent Categories} \e$B$r;2>H$7$F$/$@$5$$!#\e(B)
+
+@item
+\e$B5-;v$r<hF@$7$?8e$O\e(B @kbd{J j} \e$B$r2!$7$F!"\e(Bgnus \e$B$r:F$S@Z$jN%$7>uBV$K$5$;!"\e(B
+PPP \e$B4X78\e(B(\e$B$J$I\e(B)\e$B$rJD$8$^$9!#$=$&$7$F%K%e!<%9$r%*%U%i%$%s$GFI$`$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+@item
+\e$B$=$7$FBhFs%9%F%C%W$KLa$j$^$9!#\e(B
+@end itemize
+
+\e$B0J2<$K%(!<%8%'%s%H$r=i$a$F\e(B(\e$B$+$=$3$i$K\e(B)\e$B;H$&$H$-$KI,MW$J$$$/$D$+$N:n6H$r<(\e(B
+\e$B$7$^$9!#\e(B
+
+@itemize @bullet
+
+@item
+\e$B$I$N%5!<%P!<$r%(!<%8%'%s%H$GLLE]$r8+$k$+$r7h$a$^$9!#$b$7%a!<%k%P%C%/%(%s\e(B
+\e$B%I$,$"$l$P!"$=$l$r%(!<%8%'%s%H$KLLE]$r8+$5$;$k$N$O$*$=$i$/L50UL#$G$7$g$&!#\e(B
+\e$B%5!<%P!<%P%C%U%!!<$K0\F0$7\e(B (\e$B%0%k!<%W%P%C%U%!!<$G\e(B @kbd{^})\e$B!"%(!<%8%'%s%H\e(B
+\e$B$K07$C$FM_$7$$%5!<%P!<\e(B(\e$BJ#?t2D\e(B)\e$B$G\e(B @kbd{J a} \e$B$r2!$9\e(B (@pxref{Server Agent
+Commands}) \e$B$+!"$^$?$O%(!<%8%'%s%H$K07$C$FM_$7$/$J$$$N$K<+F0E*$KDI2C$5$l\e(B
+\e$B$?%5!<%P!<$G\e(B @kbd{J r} \e$B$r2!$7$^$9!#%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B @code{gnus-select-method} \e$B$H\e(B @code{gnus-secondary-select-methods} \e$B$K\e(B
+\e$B$"$k$9$Y$F$N\e(B @code{nntp} \e$B$H\e(B @code{nnimap} \e$B%5!<%P!<$,%(!<%8%'%s%H2=$5$l$^\e(B
+\e$B$9!#\e(B
+
+@item
+\e$B%@%&%s%m!<%IJ}?K$r7hDj$7$^$9!#$"$J$?$NJ}?K$r<BAu$9$k$?$a$K%(!<%8%'%s%HJ,\e(B
+\e$BN`!"%H%T%C%/%Q%i%a!<%?!"%0%k!<%W%Q%i%a!<%?$N$I$l$r;H$&$+$r$$$C$?$s7h$a$F\e(B
+\e$B$7$^$($P!"$3$l$O$+$J$j4JC1$G$9!#$"$J$?$,\e(B gnus \e$B$N=i?4<T$J$i$P!"$?$V$sJ,N`\e(B
+\e$B$G;O$a$k$N$,:GNI$G$7$g$&!"\e(B@xref{Agent Categories}.
+
+\e$B%H%T%C%/%Q%i%a!<%?\e(B (@pxref{Topic Parameters}) \e$B$H%(!<%8%'%s%HJ,\e(B
+\e$BN`\e(B (@pxref{Agent Categories}) \e$B$NN>J}$O!"B??t$N%0%k!<%W$KE,MQ$9$kJ}?K$N@_\e(B
+\e$BDj$rMQ0U$7$F$$$^$9!#$I$l$r;H$&$+$O40A4$K$"$J$?$N@UG$$G$9!#N>J}$r:.$<$F;H\e(B
+\e$B$&>l9g$O!"%H%T%C%/%Q%i%a!<%?$OJ,N`$rL58z$K$9$k$3$H$r9MN8$KF~$l$J$1$l$P$J\e(B
+\e$B$i$J$$$G$7$g$&!#$"$J$?$NJ}?K$K$=$0$o$J$$>/?t$N%0%k!<%W$,$"$k$N$J$i$P!"$=\e(B
+\e$B$l$i$N@_Dj$rJQ99$9$k$?$a$K%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B (@pxref{Group Parameters}) \e$B$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+@item
+\e$B$($($H\e(B@dots{}\e$B!"0J>e$G$9!#\e(B
+@end itemize
+
+@node Agent Categories
+@subsection \e$B%(!<%8%'%s%HJ,N`\e(B
+
+\e$B%K%e!<%9G[Aw5!9=$H%K%e!<%9%j!<%@!<$rE}9g$9$k0l$D$NBg$-$JM}M3$O!"$I$N5-;v\e(B
+\e$B$r%@%&%s%m!<%I$9$k$+$K$D$$$F!"$h$jNI$$@)8f$r2DG=$H$9$k$3$H$G$9!#G|Bg$JNL\e(B
+\e$B$N5-;v$r%@%&%s%m!<%I$7$F$b$"$^$j0UL#$O$J$/!"$=$l$i$rFI$s$G$b$"$^$jLLGr$/\e(B
+\e$B$J$$$3$H$,J,$+$k$@$1$G$9!#2?$r%@%&%s%m!<%I$9$k$+$NA*Br$O$b$C$H?5=E$G$"$k\e(B
+\e$B$Y$-$G$"$j!"$=$N5-;v$,LLGr$$$HJ,$+$C$?;~E@$G!"%@%&%s%m!<%I$9$k$?$a$N0u$r\e(B
+\e$B<jF0$GIU$1$k$Y$-$J$N$G$9!#\e(B
+
+\e$B2?$r%@%&%s%m!<%I$9$k$+$r@)8f$9$k$?$a$N$h$jM-8z$JJ}K!$N0l$D$O!"J,\e(B
+\e$BN`\e(B (@dfn{category}) \e$B$r:n@.$7$F!"$=$7$F$=$NJ,N`$K$$$/$D$+\e(B (\e$B$"$k$$$OA4\e(B
+\e$BIt\e(B) \e$B$N%0%k!<%W$r3d$jEv$F$k$3$H$G$9!#B>$NJ,N`$KB0$5$J$$%0%k!<%W\e(B
+\e$B$O\e(B @code{\e$B=i4|\e(B} \e$BJ,N`$KB0$7$^$9!#\e(BGnus \e$B$OJ,N`$N:n@.$H4IM}$N$?$a$NFH<+$N%P%C\e(B
+\e$B%U%!!<$r;}$C$F$$$^$9!#\e(B
+
+\e$B$b$7$=$&$7$?$1$l$P!"%0%k!<%W%Q%i%a!<%?\e(B (@pxref{Group Parameters}) \e$B$H%H%T%C\e(B
+\e$B%/%Q%i%a!<%?\e(B (@pxref{Topic Parameters}) \e$B$r!"%(!<%8%'%s%H$r@)8f$9$kBeBX<j\e(B
+\e$BCJ$K;H$&$3$H$,$G$-$^$9!#<B:]$K0c$&$N$O!"%0%k!<%W$H%H%T%C%/%Q%i%a!<%?$,2?\e(B
+\e$B$G$b$+$s$G$b\e(B (kitchen sink) \e$B4^$`$N$KBP$7$F!"J,N`$O%(!<%8%'%s%H$KFC2=$7$F\e(B
+\e$B$$$k\e(B (\e$B$7$?$,$C$F$"$^$j3X$P$J$/$F$bNI$$\e(B) \e$B$H$$$&$3$H$@$1$G$9!#\e(B
+
+\e$B%(!<%8%'%s%H%Q%i%a!<%?$OJ#?t$N0c$&>l=j$G@_Dj$9$k$3$H$,$G$-$k$N$G!"$I$N%=!<\e(B
+\e$B%9$,?.MQ$G$-$k$+$r7h$a$k$?$a$N5,B'$r@_$1$^$7$?!#$3$N5,B'$O!"%Q%i%a!<%?$N\e(B
+\e$B%=!<%9$,<!$N=g=x$GD4$Y$i$l$k$3$H$rDj$a$^$9\e(B: \e$B%0%k!<%W%Q%i%a!<%?!"%H%T%C%/\e(B
+\e$B%Q%i%a!<%?!"%(!<%8%'%s%HJ,N`!"$=$7$F:G8e$O%+%9%?%^%$%:$G$-$kJQ?t72$G$9!#\e(B
+\e$B$7$?$,$C$F!"9-$$HO0O$GF0:n$r5/$3$5$;$k$?$a$K$3$l$i$N%=!<%9$r$9$Y$F:.9g$9\e(B
+\e$B$k$3$H$,$G$-$^$9!#$I$3$K@_Dj$rCV$$$?$N$+$rK:$l$F$7$^$C$?$+$i$H$$$C$F!";d\e(B
+\e$B$r@U$a$J$$$G2<$5$$$h!#\e(B
+
+@menu
+* Category Syntax::             \e$BJ,N`$H$O$I$s$J$b$N$+\e(B
+* Category Buffer::             \e$BJ,N`$r4IM}$9$k%P%C%U%!!<\e(B
+* Category Variables::          \e$B%+%9%?%^%$%6\e(B"\e$B$i\e(B"\e$B%9\e(B
+@end menu
+
+@node Category Syntax
+@subsubsection \e$BJ,N`$NJ8K!\e(B
+
+\e$BJ,N`$O!"L>A0!"$=$NJ,N`$KB0$9$k%0%k!<%W$N%j%9%H!"$*$h$S%+%9%?%^%$%:2DG=$J\e(B
+\e$BJQ?t$r>e=q$-$9$kB?$/$NG$0U$J%Q%i%a!<%?$+$i@.$j$^$9!#%(!<%8%'%s%H%Q%i%a!<\e(B
+\e$B%?$N40A4$J%j%9%H$r0J2<$K<($7$^$9!#\e(B
+
+@cindex Agent Parameters
+@table @code
+@item gnus-agent-cat-name
+\e$BJ,N`$NL>A0!#\e(B
+
+@item gnus-agent-cat-groups
+\e$B$3$NJ,N`$K$"$k%0%k!<%W$N%j%9%H!#\e(B
+
+@item gnus-agent-cat-predicate
+(\e$BDL>o\e(B) \e$B$I$N5-;v$r%@%&%s%m!<%I$9$k$N$,E,Ev$+$H$$$&Bg$^$+$JNX3T$rM?$($k=R\e(B
+\e$B8l!#$=$7$F\e(B
+
+@item gnus-agent-cat-score-file
+(\e$BDL>o\e(B) \e$B$I$N5-;v$r%@%&%s%m!<%I$9$k$+$r7h$a$k$H$-$N$h$j$-$a$N:Y$+$$%9%3%"\e(B
+\e$B5,B'!#\e(B(\e$B$3$N%@%&%s%m!<%I%9%3%"\e(B (@dfn{download score}) \e$B$ODL>o$N%9%3%"$H$O\e(B
+\e$BI,$:$7$b4X78$,L5$$$3$H$KCm0U$7$F$/$@$5$$!#\e(B)
+
+@item gnus-agent-cat-enable-expiration
+\e$B$3$N%0%k!<%W$N8E$$5-;v$r%(!<%8%'%s%H$,4|8B@Z$l>C5n$9$Y$-$+$I$&$+$r<($9\e(B
+\e$B%V!<%kJQ?t!#BgDq$N%0%k!<%W$O%G%#%9%/6u4V$rO2Hq$7$J$$$?$a$K4|8B@Z$l>C5n$5\e(B
+\e$B$l$k$Y$-$G$9!#$$$d!"<B:]$K$O\e(B gnus.* \e$B3,AX$O4|8B@Z$l>C5n$5$l$k$Y$-$G$O$J\e(B
+\e$B$$%0%k!<%W$@$1$r4^$s$G$$$k$H8@$C$F$b!"$?$V$s:9$7;Y$($"$j$^$;$s!#\e(B
+
+@item gnus-agent-cat-days-until-old
+\e$B4{FI$N5-;v$r4|8B@Z$l>C5n$7$F$b:9$7;Y$($J$$$3$H$rH=CG$9$kA0$K!"%(!<%8%'%s\e(B
+\e$B%H$,BT$C$F$$$k$Y$-F|?t$r<($9@0?t!#\e(B
+
+@item gnus-agent-cat-low-score
+@code{gnus-agent-low-score} \e$B$r>e=q$-$9$k@0?t!#\e(B
+
+@item gnus-agent-cat-high-score
+@code{gnus-agent-high-score} \e$B$r>e=q$-$9$k@0?t!#\e(B
+
+@item gnus-agent-cat-length-when-short
+@code{gnus-agent-short-article} \e$B$r>e=q$-$9$k@0?t!#\e(B
+
+@item gnus-agent-cat-length-when-long
+@code{gnus-agent-long-article} \e$B$r>e=q$-$9$k@0?t!#\e(B
+
+@c @item gnus-agent-cat-disable-undownloaded-faces
+@c \e$B%@%&%s%m!<%I$5$l$F$$$J$$5-;v$r\e(B gnus-summary-*-undownloaded-face \e$B$r;H$C$F\e(B
+@c \e$B35N,%P%C%U%!$KI=<($9$Y$-\e(B @emph{\e$B$G$O$J$$\e(B} \e$B$3$H$r<($9%7%s%\%k!#CM\e(B
+@c \e$B$,\e(B @code{nil} \e$B$@$H!"B>$N%7%s%\%k$,$=$l$i$rM^@)$7$F$$$F$b!"%@%&%s%m!<%I$5\e(B
+@c \e$B$l$F$$$J$$5-;vMQ$N%U%'!<%9$r;H$($k$h$&$K$J$j$^$9!#\e(B
+
+@item gnus-agent-cat-enable-undownloaded-faces
+\e$B%@%&%s%m!<%I$5$l$F$$$J$$5-;v$r\e(B gnus-summary-*-undownloaded-face \e$B$r;H$C$F\e(B
+\e$B35N,%P%C%U%!$KI=<($9$Y$-$G$"$k$3$H$r<($9%7%s%\%k!#CM$,\e(B @code{nil} \e$B$@$H!"\e(B
+\e$BB>$N%7%s%\%k$,$=$l$i$rM-8z$K$7$F$$$F$b!"%@%&%s%m!<%I$5$l$F$$$J$$5-;vMQ$N\e(B
+\e$B%U%'!<%9$r;H$o$J$$$h$&$K$J$j$^$9!#\e(B
+@end table
+
+\e$B$$$C$?$sJ,N`$,:n$i$l$?$i!"J,N`$NL>A0$rJQ$($k$3$H$O$G$-$^$;$s!#\e(B
+
+\e$B$=$l$>$l$NJ,N`$O!"$=$NJ,N`$N8B$i$l$?%a%s%P!<$G$"$k%0%k!<%W$N%j%9%H$r0];}\e(B
+\e$B$7$^$9!#8B$i$l$?5,B'$O<+F0E*$K<99T$5$l$^$9!#?7$7$$J,N`$K%0%k!<%W$rDI2C$9\e(B
+\e$B$k$H!"$=$l$O8E$$J,N`$+$i<+F0E*$K<h$j=|$+$l$^$9!#\e(B
+
+\e$B=R8l$N0lHVC1=c$J7A<0$O\e(B @code{true} \e$B$d\e(B @code{false} \e$B$N$h$&$JC1FH$N=R8l$+\e(B
+\e$B$i$J$j$^$9!#$3$l$i$NFs$D$O$=$l$>$l!"A4$F$N2DG=$J5-;v$r%@%&%s%m!<%I$9$k$+!"\e(B
+\e$BA4$/2?$b$7$J$$$+!"$G$9!#$3$l$i$NFs$D$NFCJL$J=R8l$N>l9g$O!"DI2C$N%9%3%"5,\e(B
+\e$BB'$OM>J,$G$9!#\e(B
+
+@code{high} \e$B$d\e(B @code{low} \e$B$H$$$&=R8l$O2<$G@bL@$5$l$F$$$k$h$&$K!"\e(B
+@code{gnus-agent-high-score} \e$B$H\e(B @code{gnus-agent-low-score} \e$B$H$N5-;v$N%9\e(B
+\e$B%3%"$H$N4X78$K$h$j5-;v$r%@%&%s%m!<%I$7$^$9!#\e(B
+
+\e$B%@%&%s%m!<%I$,E,@Z$+$I$&$+$N!"$5$i$K:Y$+$$@)8f$rF@$k$?$a$K!"=R8l$OO@M}1i\e(B
+\e$B;;;R$,4V$K;6$j$P$a$i$l$?=R8l$NAH$_9g$o$;$+$i$J$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$*$=$i$/$$$/$D$+$NNc$,$=$N$^$^;H$($^$9!#\e(B
+
+\e$B0J2<$O4JC1$J=R8l$G$9!#\e(B(\e$B$3$l$O=i4|@_Dj$N=R8l$G$9!#$D$^$j!"B>$N$I$NJ,N`$K\e(B
+\e$B$b4^$^$l$J$$A4$F$N%0%k!<%W$KBP$7$F;HMQ$5$l$^$9!#\e(B)
+
+@lisp
+short
+@end lisp
+
+\e$B$H$C$F$b4JC1$G$7$g\e(B? \e$B$3$N=R8l$O!"5-;v$,C;$$\e(B(``\e$BC;$$\e(B'' \e$B2ACM$,$"$k\e(B) \e$B>l9g$K8B\e(B
+\e$B$j??$K$J$j$^$9!#\e(B
+
+\e$B$3$l$O$b$C$HJ#;($J=R8l$G$9!#\e(B
+
+@lisp
+(or high
+    (and
+     (not low)
+     (not long)))
+@end lisp
+
+\e$B$3$N0UL#$O!"9b$$%9%3%"$r;}$C$F$$$k$+!"$"$k$$$O%9%3%"$,Dc$/$J$/$F$+$DD9$/\e(B
+\e$B$J$$!"$H$$$&5-;v$r%@%&%s%m!<%I$9$k!"$H$$$&$3$H$G$9!#$o$+$k$@$m!#\e(B
+
+\e$B;H$C$F$b$h$$O@M}1i;;;R$O!"\e(B@code{or}, @code{and}, @code{not} \e$B$G$9!#\e(B(\e$B$b$7\e(B
+\e$B;H$$$?$1$l$P!"$h$j\e(B ``C'' \e$BIw$N1i;;;R\e(B @samp{|}, @code{&}, @code{!} \e$B$rBe$j\e(B
+\e$B$K;H$&$3$H$,$G$-$^$9!#\e(B)
+
+\e$B0J2<$N=R8l$O$"$i$+$8$aDj5A$5$l$F$$$^$9$,!"$3$l$i$N$I$l$b$"$J$?$N$d$j$?$$\e(B
+\e$B$3$H$K0lCW$7$J$1$l$P!"<+J,$GFH<+$N$b$N$r=q$/$3$H$b$G$-$^$9!#\e(B
+
+\e$B$=$l$>$l$N$3$l$i$N=R8l$rI>2A$9$k$H$-!"L>A0$,IU$1$i$l$?Dj?t$O!"E,@Z$J%Q%i\e(B
+\e$B%a!<%?$N85$K\e(B @code{gnus-agent-find-parameter} \e$B$r8F$V$3$H$K$h$C$F7hDj$5$l\e(B
+\e$B$?CM$GB+G{$5$l$^$9!#Nc$(\e(B
+\e$B$P\e(B gnus-agent-short-article \e$B$O\e(B @code{(gnus-agent-find-parameter group
+'agent-short-article)} \e$B$KB+G{$5$l$^$9!#$3$l$O!"$"$J$?$,$"$J$?$NJ,N`$G=R\e(B
+\e$B8l$r;XDj$7$F$+$i!"$=$N=R8l$r8D!9$N%0%k!<%W$K$D$$$FD4@0$G$-$k$3$H$r0UL#$7\e(B
+\e$B$^$9!#\e(B
+
+@table @code
+@item short
+\e$B5-;v$,\e(B @code{gnus-agent-short-article} \e$B9T$h$jC;$+$1$l$P??!#=i4|@_DjCM\e(B
+\e$B$O\e(B 100\e$B!#\e(B
+
+@item long
+\e$B5-;v$,\e(B @code{gnus-agent-long-article} \e$B9T$h$jD9$1$l$P??!#=i4|@_DjCM$O\e(B 200\e$B!#\e(B
+
+@item low
+\e$B5-;v$N%@%&%s%m!<%I%9%3%"$,\e(B @code{gnus-agent-low-score} \e$B0J2<$G$"$l$P??!#\e(B
+\e$B=i4|@_DjCM$O\e(B 0\e$B!#\e(B
+
+@item high
+\e$B5-;v$N%@%&%s%m!<%I%9%3%"$,\e(B @code{gnus-agent-high-score} \e$B0J>e$G$"$l$P??!#\e(B
+\e$B=i4|@_DjCM$O\e(B 0\e$B!#\e(B
+
+@item spam
+gnus \e$B%(!<%8%'%s%H$,$=$N5-;v$r\e(B spam \e$B$@$H8+Pv$7$?$i??!#$3$NH/8+E*<jK!$O!"\e(B
+\e$B:#8eJQ99$5$l$k$+$b$7$l$^$;$s$,!"8=;~E@$G$O!"$3$l$O%A%'%C%/%5%`$r7W;;$75-\e(B
+\e$B;v$,0lCW$9$k$+$I$&$+$rD4$Y$F$$$^$9!#\e(B
+
+@item true
+\e$B>o$K??!#\e(B
+
+@item false
+\e$B>o$K56!#\e(B
+@end table
+
+\e$B$"$J$?$,<+J,$NFH<+$N=R8l4X?t$r:n@.$7$?$1$l$P!"$3$l$rCN$C$F$*$$$F$/$@$5\e(B
+\e$B$$\e(B:
+\e$B4X?t$O0z?tL5$7$G8F$S=P$5$l$^$9$,!"\e(B
+@code{gnus-headers} \e$B$H\e(B @code{gnus-score} \e$BF0E*JQ?t$K$OJXMx$JCM$,B+G{$5$l\e(B
+\e$B$^$9!#\e(B
+
+\e$BNc$($P!"0lDj$NF|IU0J>eA0$KEj9F$5$l$?5-;v\e(B (\e$BNc$($P!"\e(B
+@code{gnus-agent-expire-days} \e$B0JA0$KEj9F$5$l$?$b$N\e(B) \e$B$r%@%&%s%m!<%I$7$J$$\e(B
+\e$B$H$9$k$3$H$b$G$-$^$9!#$=$N>l9g!"0J2<$N$h$&$J4X?t$r=q$/$G$7$g$&\e(B:
+
+@lisp
+(defun my-article-old-p ()
+  "Say whether an article is old."
+  (< (time-to-days (date-to-time (mail-header-date gnus-headers)))
+     (- (time-to-days (current-time)) gnus-agent-expire-days)))
+@end lisp
+
+\e$B$=$&$9$k$H!"=R8l$O$3$N$h$&$KDj5A$7$^$9\e(B:
+
+@lisp
+(not my-article-old-p)
+@end lisp
+
+\e$B$b$7$/$O!"\e(B@file{~/.gnus.el} \e$B$d2?$+B>$N$b$N$G$b!"4{Dj\e(B
+\e$B$N\e(B @code{gnus-category-predicate-list} \e$B$K<+J,$N=R8l$rDI2C$9$k$3$H$b$G$-\e(B
+\e$B$^$9!#\e(B
+
+@lisp
+(require 'gnus-agent)
+(setq gnus-category-predicate-alist
+      (append gnus-category-predicate-alist
+              '((old . my-article-old-p))))
+@end lisp
+
+\e$B$=$7$F!"C1$K<!$N$h$&$K=R8l$r;XDj$7$^$9\e(B:
+
+@lisp
+(not old)
+@end lisp
+
+\e$B>e$N$h$&$J$b$N$r;H$&$H$-$O!"@$$NCf$K$O@5$7$/@_Dj$5$l$F$$$J$$%7%9%F%`\e(B/\e$B%a\e(B
+\e$B!<%i!<$,$"$j!"5-;v$NF|IU$O$$$DEj9F$5$l$?$+$r>o$K3N<B$K<($9$o$1$G$O$"$j$^\e(B
+\e$B$;$s!#$"$!!"$=$l$rA4$/5$$K$7$J$$?M$b$$$^$9!#\e(B
+
+\e$B>e$N=R8l$O$=$NJ,N`$KB0$9$k\e(B @emph{\e$BA4$F\e(B} \e$B$N%0%k!<%W$KE,MQ$5$l$^$9!#$7$+$7!"\e(B
+\e$BJ,N`Cf$N8D!9$N%0%k!<%W$KFCDj$N=R8l$rK>$s$@$j!"BUBF2a$.$F?7$7$$J,N`$r@_Dj\e(B
+\e$B$G$-$J$$$H$-$O!"%0%k!<%W$N8D!9$N=R8l$r%0%k!<%W%Q%i%a!<%?$G<!$N$h$&$K$9$k\e(B
+\e$B$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(agent-predicate . short)
+@end lisp
+
+\e$B$3$l$O\e(B agent \e$BJ,N`$N%G%#%U%)%k%H$HEy2A$J%0%k!<%W\e(B/\e$B%H%T%C%/%Q%i%a!<%?$G$9!#\e(B
+\e$B$3$N$h$&$J0l8l$N=R8l$r;XDj$7$F$$$k$H$-$O!"\e(B@code{agent-predicate} \e$B;X<($O\e(B
+\e$B%I%C%HBP5-K!$G$"$kI,MW$,$"$k$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+
+\e$B>e$N$b$N$HEy2A$JD9$$J}$NNc$O\e(B:
+
+@lisp
+(agent-predicate or high (and (not low) (not long)))
+@end lisp
+
+\e$BJ,N`$N;XDj$GMW5a$5$l$k30$N4]3g8L$O$3$3$G$OF~NO$5$l$F$*$i$:!"%I%C%HBP$N5-\e(B
+\e$BK!$G$b$J$/!"=R8l$NCM$O%j%9%H$"$k$H$_$J$5$l$^$9!#\e(B
+
+\e$B$5$F!"%@%&%s%m!<%I%9%3%"$NJ8K!$ODL>o$N%9%3%"%U%!%$%k$NJ8K!$HF1$8$G$9$,!"\e(B
+\e$BNc30$H$7$F!"<B:]$K5-;v<+?H$rD4$Y$kI,MW$,$"$kMWAG$O6X;_$5$l$F$$$^$9!#$D$^\e(B
+\e$B$j!"0J2<$N%X%C%@!<$N$_$,%9%3%"IU$1$G$-$^$9\e(B: @code{Subject}, @code{From},
+@code{Date}, @code{Message-ID}, @code{References}, @code{Chars},
+@code{Lines} and @code{Xref}.
+
+\e$B=R8l$HF1MM!"%0%k!<%W$K4X$7$F\e(B @code{\e$B%@%&%s%m!<%I%9%3%"5,B'\e(B} \e$B$N;XDj$N;HMQ\e(B
+\e$B$O!"$=$3$NA4$F$N%0%k!<%W$KE,MQ2DG=$J$iJ,N`$NDj5A!"%0%k!<%W$KFCM-$J$i%0\e(B
+\e$B%k!<%W%Q%i%a!<%?!"$N$I$A$i$+$K$G$-$^$9!#\e(B
+
+\e$BN>J}$N>l=j$G!"\e(B@code{\e$B%@%&%s%m!<%I%9%3%"5,B'\e(B} \e$B$O0J2<$N;0$D$N7A<0$r<h$k$3$H\e(B
+\e$B$,$G$-$^$9\e(B:
+
+@enumerate
+@item
+\e$B%9%3%"5,B'\e(B
+
+\e$B>e$G=q$+$l$F$$$k$h$&$K!"%9%3%"IU$1%-!<%o!<%I$N0lItJ,$7$+;H$($J$$$3$H$r=|\e(B
+\e$B$1$P!"$3$l$OIaDL$N\e(B gnus \e$B%9%3%"%U%!%$%k$N9=J8$HF1$8$G$9!#\e(B
+
+\e$BNc\e(B:
+
+@itemize @bullet
+@item
+\e$BJ,N`;XDj\e(B
+
+@lisp
+(("from"
+       ("Lars Ingebrigtsen" 1000000 nil s))
+("lines"
+       (500 -100 nil <)))
+@end lisp
+
+@item
+\e$B%0%k!<%W\e(B/\e$B%H%T%C%/%Q%i%a!<%?;XDj\e(B
+
+@lisp
+(agent-score ("from"
+                   ("Lars Ingebrigtsen" 1000000 nil s))
+             ("lines"
+                   (500 -100 nil <)))
+@end lisp
+
+\e$B$^$?!"$3$3$G0lHV30$N3g8L$,>JN,$5$l$F$$$k$3$H$KCm0U$7$F$/$@$5$$!#\e(B
+@end itemize
+
+@item
+\e$B%(!<%8%'%s%H%9%3%"%U%!%$%k\e(B
+
+\e$B$3$l$i$N%9%3%"%U%!%$%k$O>e$G=R$Y$i$l$F$$$k;HMQ2DG=$J%9%3%"IU$1%-!<%o!<\e(B
+\e$B%I\e(B @emph{\e$B$N$_\e(B} \e$B$G$"$kI,MW$,$"$j$^$9!#\e(B
+
+\e$BNc\e(B:
+
+@itemize @bullet
+@item
+\e$BJ,N`;XDj\e(B
+
+@lisp
+("~/News/agent.SCORE")
+@end lisp
+
+\e$B$b$7$/$O!"$?$V$s\e(B
+
+@lisp
+("~/News/agent.SCORE" "~/News/agent.group.SCORE")
+@end lisp
+
+@item
+\e$B%0%k!<%W%Q%i%a!<%?;XDj\e(B
+
+@lisp
+(agent-score "~/News/agent.SCORE")
+@end lisp
+
+\e$B>e$NMM$K!"DI2C$N%9%3%"%U%!%$%k$r;XDj$9$k$3$H$,$G$-$^$9!#$^$?3g8L$K$D$$$F\e(B
+\e$B8@$o$J$1$l$P$$$1$^$;$s$+\e(B?
+@end itemize
+
+@item
+@code{\e$BIaDL\e(B} \e$B$N%9%3%"%U%!%$%k$N;HMQ\e(B
+
+\e$B0l$D$N%0%k!<%W$GFs$D$N%9%3%"5,B'$r0];}$7$?$/$J$/!"%0%k!<%W$NK>$_\e(B
+\e$B$N\e(B @code{\e$B%@%&%s%m!<%I\e(B} \e$B$N4p=`$,\e(B @code{\e$BFI$`\e(B} \e$B4p=`$HF1$8$J$i!"%(!<%8%'%s%H\e(B
+\e$B$K2?$r%@%&%s%m!<%I$9$k$+$r7h$a$k:]$K\e(B @code{\e$BIaDL\e(B} \e$B$N%9%3%"%U%!%$%k$r;2>H\e(B
+\e$B$9$k$h$&$K$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$BJ,N`Dj5A$+!"%0%k!<%W%Q%i%a!<%?$N$3$l$i$N;X<($O%(!<%8%'%s%H$K%0%k!<%W$KE,\e(B
+\e$BMQ2DG=$JA4$F$N%9%3%"%U%!%$%k$rFI$^$;!"%9%3%"IU$1%-!<%o!<%I$N;HMQ2DG=$JIt\e(B
+\e$BJ,=89g$KL5$$$b$N$r\e(B @emph{\e$BA*JL$7$FH4$-<h$j$^$9\e(B}\e$B!#\e(B
+
+@itemize @bullet
+@item
+\e$BJ,N`;XDj\e(B
+
+@lisp
+file
+@end lisp
+
+@item
+\e$B%0%k!<%W%Q%i%a!<%?;XDj\e(B
+
+@lisp
+(agent-score . file)
+@end lisp
+@end itemize
+@end enumerate
+
+@node Category Buffer
+@subsubsection \e$BJ,N`%P%C%U%!!<\e(B
+
+\e$BDL>o$OA4$F$NJ,N`$OJ,N`%P%C%U%!!<$+$i4IM}$7$^$9!#\e(B(\e$B%0%k!<%W%P%C%U%!!<\e(B
+\e$B$+$i\e(B @kbd{J c} \e$BL?Na$K$h$C$F\e(B) \e$B=i$a$F$3$l$KF~$C$?$H$-!"=i4|@_Dj$N\e(B
+\e$BJ,N`$@$1$,I=<($5$l$^$9!#\e(B
+
+\e$B0J2<$NL?Na$,$3$N%P%C%U%!!<$G;HMQ$G$-$^$9!#\e(B
+
+@table @kbd
+@item q
+@kindex q (\e$BJ,N`\e(B)
+@findex gnus-category-exit
+\e$B%0%k!<%W%P%C%U%!!<$KLa$k\e(B (@code{gnus-category-exit})\e$B!#\e(B
+
+@item e
+@kindex e (\e$BJ,N`\e(B)
+@findex gnus-category-customize-category
+\e$BA*Br$5$l$?J,N`$N%Q%i%a!<%?$r0l3g$7$F@_Dj$9$k$?$a$K!"%+%9%?%^%$%:%P%C%U%!\e(B
+\e$B$r;H$$$^$9\e(B (@code{gnus-category-customize-category})\e$B!#\e(B
+
+Use a customization buffer to set all of the selected category's
+parameters at one time (@code{gnus-category-customize-category}).
+
+@item k
+@kindex k (\e$BJ,N`\e(B)
+@findex gnus-category-kill
+\e$B8=:_$NJ,N`$r>C5n$9$k\e(B (@code{gnus-category-kill})\e$B!#\e(B
+
+@item c
+@kindex c (\e$BJ,N`\e(B)
+@findex gnus-category-copy
+\e$B8=:_$NJ,N`$rJ#@=$9$k\e(B (@code{gnus-category-copy})\e$B!#\e(B
+
+@item a
+@kindex a (\e$BJ,N`\e(B)
+@findex gnus-category-add
+\e$B?7$7$$J,N`$rDI2C$9$k\e(B (@code{gnus-category-add})\e$B!#\e(B
+
+@item p
+@kindex p (\e$BJ,N`\e(B)
+@findex gnus-category-edit-predicate
+\e$B8=:_$NJ,N`$N=R8l$rJT=8$9$k\e(B (@code{gnus-category-edit-predicate})\e$B!#\e(B
+
+@item g
+@kindex g (\e$BJ,N`\e(B)
+@findex gnus-category-edit-groups
+\e$B8=:_$NJ,N`$KB0$9$k%0%k!<%W$N0lMw$rJT=8$9\e(B
+\e$B$k\e(B (@code{gnus-category-edit-groups})\e$B!#\e(B
+
+@item s
+@kindex s (\e$BJ,N`\e(B)
+@findex gnus-category-edit-score
+\e$B8=:_$NJ,N`$N%@%&%s%m!<%I%9%3%"5,B'$rJT=8$9\e(B
+\e$B$k\e(B (@code{gnus-category-edit-score})\e$B!#\e(B
+
+@item l
+@kindex l (\e$BJ,N`\e(B)
+@findex gnus-category-list
+\e$BA4$F$NJ,N`$rI=<($9$k\e(B (@code{gnus-category-list})\e$B!#\e(B
+@end table
+
+@node Category Variables
+@subsubsection \e$BJ,N`JQ?t\e(B
+
+@table @code
+@item gnus-category-mode-hook
+@vindex gnus-category-mode-hook
+\e$BJ,N`%P%C%U%!!<$G<B9T$9$k%U%C%/!#\e(B
+
+@item gnus-category-line-format
+@vindex gnus-category-line-format
+\e$BJ,N`%P%C%U%!!<$N9TMM<0\e(B (@pxref{Formatting Variables})\e$B!#M-8z$JMWAG$O!"\e(B
+
+@table @samp
+@item c
+\e$BJ,N`$NL>A0!#\e(B
+
+@item g
+\e$BJ,N`$KB0$9$k%0%k!<%W$N?t!#\e(B
+@end table
+
+@item gnus-category-mode-line-format
+@vindex gnus-category-mode-line-format
+\e$BJ,N`%b!<%I9T$NMM<0\e(B (@pxref{Mode Line Formatting})\e$B!#\e(B
+
+@item gnus-agent-short-article
+@vindex gnus-agent-short-article
+\e$B$3$NJQ?t$h$j>/$J$$9T?t$N5-;v$OC;$$!#=i4|@_DjCM$O\e(B 100\e$B!#\e(B
+
+@item gnus-agent-long-article
+@vindex gnus-agent-long-article
+\e$B$3$NJQ?t$h$jB?$$9T?t$N5-;v$OD9$$!#=i4|@_DjCM$O\e(B 200\e$B!#\e(B
+
+@item gnus-agent-low-score
+@vindex gnus-agent-low-score
+\e$B$3$NCM$h$j>.$5$$%9%3%"$r;}$D5-;v$ODc%9%3%"$G$"$k!#=i4|@_DjCM$O\e(B 0\e$B!#\e(B
+
+@item gnus-agent-high-score
+@vindex gnus-agent-high-score
+\e$B$3$NCM$h$jBg$-$$%9%3%"$r;}$D5-;v$O9b%9%3%"$G$"$k!#=i4|@_DjCM$O\e(B 0\e$B!#\e(B
+
+@item gnus-agent-expire-days
+@vindex gnus-agent-expire-days
+\e$B4|8B@Z$l>C5n$K$U$5$o$7$/$J$k$^$G4{FI5-;v$r%(!<%8%'%s%H$N%m!<%+%k%G%#%9%/\e(B
+\e$B$KN1$a$F$*$/F|?t\e(B (\e$B$G$bL>A0$,F1$8$@$C$?$i!"$3$l$O$=$N%5!<%P!<$K$*$1$k4|8B\e(B
+\e$B@Z$l>C5n$r0UL#$7$^$;$s!#$=$l$OC1$K5-;v$N%m!<%+%k$JJ#@=$r>C$9$3$H$r0UL#$7\e(B
+\e$B$^$9\e(B)\e$B!#$5$i$KM}2r$9$Y$-Bg;v$J$3$H$O!"5-;v$,FI$^$l$?;~$G$O$J$/%m!<%+%k%G%#\e(B
+\e$B%9%/$K5-;v$,=q$+$l$?;~$+$i7W?t$,;O$^$k$H$$$&$3$H$G$9!#%G%#%U%)%k%H$O\e(B 7\e$BF|!#\e(B
+
+@item gnus-agent-enable-expiration
+@vindex gnus-agent-enable-expiration
+\e$B%0%k!<%W$N5-;v$,!"%G%#%U%)%k%H$G4|8B@Z$l>C5n$5$l$k$+!"L54|8B$KJ];}$5$l$k\e(B
+\e$B$+$r7hDj$7$^$9!#%G%#%U%)%k%H$O\e(B @code{ENABLE} \e$B$G!"K>$`$J$i$P4|8B@Z$l>C5n\e(B
+\e$B$r$5$;$J$$$h$&$K$7$J$1$l$P$J$i$J$$$3$H$r0UL#$7$^$9!#0lJ}!"$3$l\e(B
+\e$B$r\e(B @code{DISABLE} \e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#$=$N>l9g!"A*Br$5$l$?%0%k!<%W\e(B
+\e$B$G$N4|8B@Z$l>C5n$rM-8z$K$7$J$1$l$P$J$j$^$;$s!#\e(B
+@end table
+
+@node Agent Commands
+@subsection \e$B%(!<%8%'%s%HL?Na\e(B
+@findex gnus-agent-toggle-plugged
+@kindex J j (Agent)
+
+\e$BA4$F$N\e(B gnus \e$B%(!<%8%'%s%HL?Na$O\e(B @kbd{J} \e$B%5%V%^%C%W$K$"$j$^$9!#\e(B
+@kbd{J j} (@code{gnus-agent-toggle-plugged}) \e$BL?Na$OA4$F$N%b!<%I\e(B
+\e$B$GF0:n$7!"\e(Bgnus \e$B%(!<%8%'%s%H$N@Z$jN%$7\e(B/\e$B:9$79~$_>uBV$r@Z$jBX$($^$9!#\e(B
+
+@menu
+* Group Agent Commands::        \e$B%0%k!<%W$N@_Dj$H$=$l$i$NFbMF$N<hF@\e(B
+* Summary Agent Commands::      \e$B<jF0$GA*Br$7$?5-;v$r<hF@$9$k\e(B
+* Server Agent Commands::       \e$B%(!<%8%'%s%H$G%5%]!<%H$5$l$k%5!<%P!<$NA*Br\e(B
+@end menu
+
+@node Group Agent Commands
+@subsubsection \e$B%0%k!<%W%(!<%8%'%s%HL?Na\e(B
+
+@table @kbd
+@item J u
+@kindex J u (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-agent-fetch-groups
+\e$B8=:_$N%0%k!<%W$NE,3J$J5-;v$rA4$F<hF@$9\e(B
+\e$B$k\e(B (@code{gnus-agent-fetch-groups})\e$B!#\e(B
+
+@item J c
+@kindex J c (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-enter-category-buffer
+\e$B%(!<%8%'%s%HJ,N`%P%C%U%!!<$KF~$k\e(B (@code{gnus-enter-category-buffer})\e$B!#\e(B
+
+@item J s
+@kindex J s (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-agent-fetch-session
+\e$BA4%0%k!<%W$NE,3J$J5-;v$rA4$F<hF@$9$k\e(B (@code{gnus-agent-fetch-session})\e$B!#\e(B
+
+@item J S
+@kindex J S (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-group-send-queue
+\e$B=gHVBT$A\e(B (queue) \e$B%0%k!<%W$K$"$kAw?.2DG=$J%a%C%;!<%8$rA4$FAw?.$9\e(B
+\e$B$k\e(B (@code{gnus-group-send-queue})\e$B!#\e(B@xref{Drafts}.
+
+@item J a
+@kindex J a (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-agent-add-group
+\e$B8=:_$N%0%k!<%W$r%(!<%8%'%s%HJ,N`$KDI2C$9$k\e(B (@code{gnus-agent-add-group})\e$B!#\e(B
+\e$B$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,<-$N=,47$rM}2r$7$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item J r
+@kindex J r (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-agent-remove-group
+\e$B8=:_$N%0%k!<%W$r!"$b$7B8:_$7$F$$$l$P!"$=$NJ,N`$+$i>C5n$7$^\e(B
+\e$B$9\e(B (@code{gnus-agent-remove-group})\e$B!#$3$NL?Na$O%W%m%;%9\e(B/\e$B@\F,<-$N=,47$rM}\e(B
+\e$B2r$7$^$9!#\e(B(@pxref{Process/Prefix})\e$B!#\e(B
+
+@item J Y
+@kindex J Y (\e$B%(!<%8%'%s%H\e(B \e$B%0%k!<%W\e(B)
+@findex gnus-agent-synchronize-flags
+\e$B%j%b!<%H%5!<%P!<$,\e(B @dfn{unplugged} \e$B$N$H$-$KJQ99$5$l$?%U%i%0$,$"$l$PF14|\e(B
+\e$B$5$;$^$9!#\e(B
+@end table
+
+@node Summary Agent Commands
+@subsubsection \e$B35N,%(!<%8%'%s%HL?Na\e(B
+
+@table @kbd
+@item J #
+@kindex J # (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-mark-article
+\e$B5-;v$K%@%&%s%m!<%I$9$k$h$&$K0u$rIU$1$k\e(B (@code{gnus-agent-mark-article})\e$B!#\e(B
+
+@item J M-#
+@kindex J M-# (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-unmark-article
+\e$B5-;v$+$i%@%&%s%m!<%I$9$k0u$r>C5n$9$k\e(B (@code{gnus-agent-unmark-article})\e$B!#\e(B
+
+@cindex %
+@item @@
+@kindex @@ (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-toggle-mark
+\e$B5-;v$r%@%&%s%m!<%I$9$k$+$I$&$+$r@Z$jBX$(\e(B
+\e$B$k\e(B (@code{gnus-agent-toggle-mark})\e$B!#%G%#%U%)%k%H$G$O%@%&%s%m!<%I$N0u\e(B
+\e$B$O\e(B @samp{%}\e$B!#\e(B
+
+@item J c
+@kindex J c (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-catchup
+\e$B%-%c%C%7%e$5$l$F$$$J$$!"%@%&%s%m!<%I$5$l$F$$$J$$!"$^$?$O%@%&%s%m!<%I$G$-\e(B
+\e$B$J$$$9$Y$F$N5-;v$r4{FI$K$9$k\e(B (@code{gnus-agent-catchup})\e$B!#\e(B
+
+@item J S
+@kindex J S (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-fetch-group
+\e$B$3$N%0%k!<%W$N$9$Y$F$NK>$^$7$$5-;v\e(B (@pxref{Agent Categories} \e$B;2>H\e(B) \e$B$r%@\e(B
+\e$B%&%s%m!<%I$9$k!#\e(B(@code{gnus-agent-fetch-group})\e$B!#\e(B
+
+@item J s
+@kindex J s (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-fetch-series
+\e$B$3$N%0%k!<%W$N$9$Y$F$N%W%m%;%90u$,IU$$$?5-;v$r%@%&%s%m!<%I$9$k!#\e(B
+(@code{gnus-agent-fetch-series})\e$B!#\e(B
+
+@item J u
+@kindex J u (\e$B%(!<%8%'%s%H\e(B \e$B35N,\e(B)
+@findex gnus-agent-summary-fetch-group
+\e$B8=:_$N%0%k!<%W$N%@%&%s%m!<%I2DG=$J5-;v$r!"$9$Y$F%@%&%s%m!<%I$9\e(B
+\e$B$k\e(B (@code{gnus-agent-summary-fetch-group})\e$B!#\e(B
+@end table
+
+@node Server Agent Commands
+@subsubsection \e$B%5!<%P!<%(!<%8%'%s%HL?Na\e(B
+
+@table @kbd
+@item J a
+@kindex J a (\e$B%(!<%8%'%s%H\e(B \e$B%5!<%P!<\e(B)
+@findex gnus-agent-add-server
+\e$B8=:_$N%5!<%P!<$r!"\e(Bgnus \e$B%(!<%8%'%s%H$G07$o$l$k%5!<%P!<$N0lMw$KDI2C$9\e(B
+\e$B$k\e(B (@code{gnus-agent-add-server})\e$B!#\e(B
+
+@item J r
+@kindex J r (\e$B%(!<%8%'%s%H\e(B \e$B%5!<%P!<\e(B)
+@findex gnus-agent-remove-server
+\e$B8=:_$N%5!<%P!<$r!"\e(Bgnus \e$B%(!<%8%'%s%H$G07$o$l$k%5!<%P!<$N0lMw$+$i:o=|$9\e(B
+\e$B$k\e(B (@code{gnus-agent-remove-server})\e$B!#\e(B
+@end table
+
+@node Agent Visuals
+@subsection \e$B%(!<%8%'%s%H$N;k3P8z2L\e(B
+
+\e$B%*%U%i%$%s\e(B (unplugged) \e$B$N$H$-$K35N,$r3+$$$?>l9g$K!"\e(Bgnus \e$B$,8=:_%(!<%8%'%s\e(B
+\e$B%H$K3JG<$5$l$F$$$k%X%C%@!<$h$j$bB?$/$N5-;v$,$"$k$3$H$r!"$=$N%0%k!<%W\e(B
+\e$B$N\e(B active (\e$BLuCm\e(B: \e$B2?HV$+$i2?HV$^$G$N5-;v$,$"$k$+$r<($94IM}>pJs\e(B) \e$B$NHO0O$+\e(B
+\e$B$iCN$C$F$$$k>l9g!"I=Bj$,\e(B @samp{[Undownloaded article #####]} \e$B$N$h$&$K$J$C\e(B
+\e$B$F$$$k$$$/$D$+$N5-;v$r8+$k$+$b$7$l$^$;$s!#$=$l$i$O8+Ev$?$i$J$$%X%C%@!<$N\e(B
+\e$B$?$a$N7jKd$a\e(B (placeholders) \e$B$G$9!#0u\e(B (mark) \e$B$r@_Dj$9$k$3$H$O$H$b$+$/!"$=\e(B
+\e$B$l$i$N7jKd$a$N0l$D$G$G$-$k$3$H$OB?$/$O$"$j$^$;$s!#:G=*E*$K\e(B gnus \e$B$,%0%k!<\e(B
+\e$B%W$N%X%C%@!<$r<h$C$FMh$k5!2q$rF@$?$H$-$K!"$=$l$i$N7jKd$a$O<B:]$N%X%C%@!<\e(B
+\e$B$G<+F0E*$KCV$-49$($i$l$k$G$7$g$&!#5$$K$J$k$J$i$P!"$=$l$i$N7jKd$a$rFI$_Ht\e(B
+\e$B$P$9$?$a$K!"35N,%P%C%U%!$NF0:n$rA`:n$9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B (@code{gnus-auto-goto-ignores} \e$B;2>H\e(B)\e$B!#\e(B
+
+\e$B$9$Y$F$N?M$K$H$C$FL@Gr$+$b$7$l$^$;$s$,!"%*%U%i%$%s$N$H$-$KMxMQ$G$-$k$N$O!"\e(B
+\e$B0JA0$K:9$79~$^$l$F$$$?4V\e(B (plugged) \e$B$K%(!<%8%'%s%H$K<h$j9~$^$l$?%X%C%@!<\e(B
+\e$B$H5-;v$@$1$G$9!#8@$$49$($k$H!V:9$79~$^$l$F$$$?4V$K<h$j9~$`$3$H$rK:$l$k$H!"\e(B
+\e$B%*%U%i%$%s$N%;%C%7%g%s$rK~B-$G$-$k$b$N$K$9$k$K$OB-$j$J$$!W$H$$$&$3$H$G$9!#\e(B
+\e$B$3$NM}M3$N$?$a$K!"%(!<%8%'%s%H$O35N,%P%C%U%!$KFs$D$N;k3P8z2L$r2C$($^$9!#\e(B
+\e$B$3$l$i$N8z2L$O!"%*%U%i%$%s$N$H$-$K$I$N5-;v$,MxMQ$G$-$k$+$r$$$D$bCN$i$;$k\e(B
+\e$B$?$a$K!"%@%&%s%m!<%I$N>uBV$rI=<($7$^$9!#\e(B
+
+\e$BBh0l$N;k3P8z2L$O\e(B @samp{%O} \e$B;EMM$G$9!#$3$N;X<(;R$r4^$a$k$?$a\e(B
+\e$B$K\e(B @code{gnus-summary-line-format} \e$B$r%+%9%?%^%$%:$9$k$H!"5-;v$N%@%&%s%m!<\e(B
+\e$B%I$N>uBV$r<($9C10l$NJ8;z$,2C$o$k$G$7$g$&!#%(!<%8%'%s%H$+%-%c%C%7%e$N$I$A\e(B
+\e$B$i$+$K<h$j9~$^$l$?5-;v$O!"\e(B@code{gnus-downloaded-mark} (\e$B%G%#%U%)%k%H\e(B
+\e$B$O\e(B @samp{+}) \e$B$rI=<($7$^$9!#$=$l$i0J30$N$9$Y$F$N5-;v\e(B
+\e$B$O\e(B @code{gnus-undownloaded-mark} (\e$B%G%#%U%)%k%H$O\e(B @samp{-}) \e$B$rI=<($7$^$9!#\e(B
+\e$B%(!<%8%'%s%H2=$5$l$F$$$J$$%0%k!<%W$r3+$/$H!"6uGr\e(B (@samp{ }) \e$B$,I=<($5$l$^\e(B
+\e$B$9!#\e(B
+
+\e$BBhFs$N;k3P8z2L$O%@%&%s%m!<%I$5$l$F$$$J$$$3$H$r<($9%U%'!<%9$G$9!#B?$/\e(B
+\e$B$N\e(B gnus \e$B$N%f!<%6$K9%46$H7y0-$r$b$?$i$9$G$"$m$&!"5-;v$N%9%3%"$r;0CJ\e(B
+\e$B3,\e(B (low, normal, high) \e$B$GI=<($9$k%U%'!<%9$,$"$j$^$9!#LdBj$O!"%U%'!<%9$N\e(B
+\e$BA*Br$,>r7o8!::$H%U%'!<%9L>$N%j%9%H\e(B (@code{gnus-summary-highlight} \e$B;2\e(B
+\e$B>H\e(B) \e$B$G@)8f$5$l$k$3$H$G$9!#$=$l$>$l$N>r7o$O!"$=$l$,%j%9%H$NCf$K8=$l$k=g$K\e(B
+\e$B8!::$5$l$k$N$G!"8e$N>r7o$h$j$bA0$N>r7o$,M%@h$5$l$^$9!#$3$l$,0UL#$9$k$9$Y\e(B
+\e$B$F$O!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$K2D;k5-;v\e(B (ticked) \e$B$N0u$rIU$1$F$b!"$=\e(B
+\e$B$N5-;v$O2D;k5-;v$N%U%'!<%9$G$O$J$/$F!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<\e(B
+\e$B%9$GI=<($7B3$1$i$l$k$H$$$&$3$H$G$9!#\e(B
+
+(\e$B5-;v$rFI$`$?$S$KF1$85-;v$r%@%&%s%m!<%I$7$J$$$h$&$K$9$k$?$a!"$^$?$O@\B3\e(B
+\e$B;~4V$r:G>.$K$9$k$?$a$K\e(B) \e$B%(!<%8%'%s%H$r%-%c%C%7%e$H$7$F;H$&>l9g$O!"%@%&%s\e(B
+\e$B%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$O$*$=$i$/NI$$9M$($N$h$&$K;W$($k$G$7$g$&!#\e(B
+\e$B%@%&%s%m!<%I$5$l$?5-;v$KBP$7$F$9$Y$F$N;E;v\e(B (\e$B0u$rIU$1$k!"FI$`!":o=|$9\e(B
+\e$B$k\e(B) \e$B$r9T$J$($P!"$$$D$bDL>o$N%U%'!<%9$,8=$l$k$+$i$G$9!#\e(B
+
+\e$B$H$-$?$^%(!<%8%'%s%H$r;H$&%f!<%6$K$H$C$F$O!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v\e(B
+\e$B$N%U%'!<%9$O!"$I$&$7$h$&$b$J$/$R$I$$9M$($G$"$k$h$&$K;W$($k$+$b$7$l$^$;$s!#\e(B
+\e$BO@E@$O!"H`$i$NBgDq$N5-;v$O%(!<%8%'%s%H$K<h$j9~$^$l$F$$$J$$$N$G!"B?$/$NDL\e(B
+\e$B>o$N%U%'!<%9$,!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$N1"$K2b$s$G$7$^$&\e(B
+\e$B$3$H$G$9!#$3$l$,$"$J$?$N6-6x$J$i$P!"$"$J$?$K$OFs$D$NA*Br;h$,$"$j$^$9!#Bh\e(B
+\e$B0l$K!"\e(B@code{gnus-summary-*-undownloaded-face} \e$B$N%U%'!<%972$K4X$o$k;0$D$N\e(B
+\e$B%3%s%9%;%k$r>C5n$9$k$?$a$K\e(B @code{gnus-summary-highlight} \e$B$r%+%9%?%^%$%:\e(B
+\e$B$9$k$3$H$K$h$C$F!"%@%&%s%m!<%I$5$l$F$$$J$$5-;v$N%U%'!<%9$r40A4$KM^@)$9$k\e(B
+\e$B$3$H$,$G$-$^$9!#BhFs$K!"$b$C$H@vN}$5$l$?%"%W%m!<%A$,9%$_$J$i$P!"\e(B
+@code{agent-disable-undownloaded-faces} \e$B%0%k!<%W%Q%i%a!<%?$r\e(B t \e$B$K@_Dj$7\e(B
+\e$B$F$bNI$$$G$7$g$&!#$3$N%Q%i%a!<%?$OB>$N$9$Y$F$N%(!<%8%'%s%H%Q%i%a!<%?$HF1\e(B
+\e$BMM$K!"%(!<%8%'%s%HJ,N`\e(B (@pxref{Agent Categories})\e$B!"%0%k!<%W%H%T%C\e(B
+\e$B%/\e(B (@pxref{Topic Parameters})\e$B!"$"$k$$$O8D!9$N%0%k!<%W\e(B (@pxref{Group
+Parameters}) \e$B$KBP$7$F@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+
+@node Agent as Cache
+@subsection \e$B%-%c%C%7%e$H$7$F$N%(!<%8%'%s%H\e(B
+
+gnus \e$B$,\e(B @dfn{plugged} \e$B$G$"$k$H$-$K!"$9$G$K%(!<%8%'%s%H$K3JG<$5$l$F$$$k%X%C\e(B
+\e$B%@!<$d5-;v$r%@%&%s%m!<%I$9$k$N$O8zN(E*$G$O$"$j$^$;$s!#$=$3$G\e(B gnus \e$B$ODL>o\e(B
+\e$B%X%C%@!<$r0l2s$@$1%@%&%s%m!<%I$7$F%(!<%8%'%s%H$K3JG<$7$^$9!#\e(B
+@dfn{plugged} \e$B$+\e(B @dfn{unplugged} \e$B$K$+$+$o$i$:!"$=$l$i$N%X%C%@!<$O8e$K35\e(B
+\e$BN,%P%C%U%!$r@8@.$9$k$H$-$K;H$o$l$^$9!#%G%#%U%)%k%H$G$O5-;v$O\e(B (\e$B$=$l$O@x:_\e(B
+\e$BE*$K%G%#%9%/6u4V$rO2Hq$9$k$G$"$m$&$+$i\e(B) \e$B%(!<%8%'%s%H$K%-%c%C%7%e$5$l$^$;\e(B
+\e$B$s$,!"$9$G$K%(!<%8%'%s%H$K%@%&%s%m!<%I$7$?5-;v$,$"$k$J$i$P!"\e(Bgnus \e$B$O%5!<\e(B
+\e$B%P!<$+$i:F$S5-;v$r%@%&%s%m!<%I$;$:$K!"<j85$K3JG<$5$l$?%3%T!<$r;H$$$^$9!#\e(B
+
+\e$B$"$J$?$,$=$&K>$`$N$G$"$l$P!"\e(B@dfn{plugged} \e$B$J4|4V$O>o$K%X%C%@!<$H5-;v$r%@\e(B
+\e$B%&%s%m!<%I$9$k$h$&$K!"%(!<%8%'%s%H\e(B (@code{gnus-agent-cache} \e$B;2\e(B
+\e$B>H\e(B @ref{Agent Variables}) \e$B$r@_Dj$9$k$3$H$,$G$-$^$9!#\e(Bgnus \e$B$O$[$H$s$I3N$+\e(B
+\e$B$K$b$C$HCY$/$J$j$^$9$,!"%5!<%P!<$H$NF14|$OJ]$?$l$^$9!#\e(Bnntp \e$B$+\e(B nnimap \e$B%P%C\e(B
+\e$B%/%(%s%I$r;H$C$F$$$k>l9g$O!"$?$V$s$3$N:G8e$NE@$O0UL#$r$J$5$J$$$G$7$g$&!#\e(B
+
+@node Agent Expiry
+@subsection \e$B%(!<%8%'%s%H4|8B@Z$l>C5n\e(B
+
+@vindex gnus-agent-expire-days
+@findex gnus-agent-expire
+@kindex M-x gnus-agent-expire
+@kindex M-x gnus-agent-expire-group
+@findex gnus-agent-expire-group
+@cindex agent expiry
+@cindex Gnus agent expiry
+@cindex expiry
+
+\e$B%(!<%8%'%s%H%P%C%/%(%s%I\e(B @code{nnagent} \e$B$O4|8B@Z$l>C5n$r07$$$^$;$s!#$($(\e(B
+\e$B$H!">/$J$/$H$bB>$N%P%C%/%(%s%I$N$h$&$K$=$l$r07$$$^$;$s!#$=$NBe$o$j$K!"FC\e(B
+\e$BJL$J\e(B @code{gnus-agent-expire} \e$B$H\e(B @code{gnus-agent-expire-group} \e$BL?Na\e(B
+\e$B$,\e(B @code{gnus-agent-expire-days} \e$B$NF|?t$h$j$b8E$$4{FI5-;v$r$9$Y$F>C5n$7\e(B
+\e$B$^$9!#$3$l$i$O$"$J$?$,%G%#%9%/MFNL$r;H$$@Z$j$=$&$@$H;W$C$?$H$-$K$$$D$G$b\e(B
+\e$B<B9T$9$k$3$H$,$G$-$^$9!#$I$A$i$bFC$KB.$/$b$J$/8zN(E*$G$b$J$/!"$=$l$i$N0l\e(B
+\e$B$D$r$$$C$?$s;O$a$F$7$^$C$?$i\e(B (@kbd{C-g} \e$B$d$=$NB>$G\e(B) \e$BCfCG$9$k$3$H$b$"$^$j\e(B
+\e$BNI$$$3$H$G$O$"$j$^$;$s!#\e(B
+
+\e$BNc$($P\e(B @code{gnus-request-expire-articles} \e$B$N$h$&$JB>$N4X?t$O!"%(!<%8%'\e(B
+\e$B%s%H$r%0%k!<%W$KF14|$5$;$k$?$a$K\e(B @code{gnus-agent-expire} \e$B$r<B9T$9$k$+$b\e(B
+\e$B$7$l$J$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+\e$B%(!<%8%'%s%H%Q%i%a!<%?\e(B @code{agent-enable-expiration} \e$B$O!"A*Br$7$?%0%k!<\e(B
+\e$B%W$G$N4|8B@Z$l>C5n$rM^@)$9$k$?$a$K;H$o$l$k$+$b$7$l$^$;$s!#\e(B
+
+@vindex gnus-agent-expire-all
+@code{gnus-agent-expire-all} \e$B$,\e(B @code{nil} \e$B$G$J$1$l$P!"%(!<%8%'%s%H$N4|\e(B
+\e$B8B@Z$l>C5n%3%^%s%I72$O$9$Y$F$N5-;v\e(B --- \e$BL$FI!"4{FI!"2D;k!"J]N15-;v$r>C5n\e(B
+\e$B$7$^$9!#$b$7\e(B @code{nil} (\e$B$3$l$,=i4|@_DjCM\e(B) \e$B$G$"$l$P!"4{FI5-;v$N$_$,>C5n\e(B
+\e$B$NBP>]$H$J$j!"L$FI!"2D;k!"J]N15-;v$O$5$i$KL54|8B$KJ];}$7$^$9!#\e(B
+
+\e$B4|8B@Z$l>C5n$5$l$F$$$k$O$:$J$N$K;D$C$F$$$k5-;v$r8+$D$1$?$J$i$P!"$?$V$s$$\e(B
+\e$B$/$D$+$N\e(B gnus \e$B%(!<%8%'%s%H%U%!%$%k$,2u$l$F$$$^$9!#\e(B
+@code{gnus-agent-regenerate} \e$B$H\e(B @code{gnus-agent-regenerate-group} \e$B$O!"\e(B
+\e$B5/$3$j$&$kLdBj$r=$I|$9$k$?$a$NFCJL$J%3%^%s%I$G$9!#\e(B
+
+@node Agent Regeneration
+@subsection \e$B%(!<%8%'%s%H$r:n$jD>$9\e(B
+
+@cindex agent regeneration
+@cindex Gnus agent regeneration
+@cindex regeneration
+
+@code{nnagent} \e$B$K$h$C$F;H$o$l$k%m!<%+%k$N%G!<%?9=B$$O!"$"$kNc30E*$J>r7o\e(B
+\e$B$K$h$C$F$*$+$7$/$J$C$F$7$^$&$+$b$7$l$^$;$s!#$3$l$,5/$3$k$H!"\e(B
+@code{nnagent} \e$B$N5!G=@-$,2<$,$k$+$b$7$l$J$$$7!"<:GT$7$5$($9$k$+$b$7$l$^\e(B
+\e$B$;$s!#$3$NLdBj$N2r7h:v$O!"FbIt$NL7=b$r$9$Y$F:o=|$9$k$3$H$K$h$C$F!"%m!<%+\e(B
+\e$B%k$N%G!<%?9=B$$r=$I|$9$k$3$H$G$9!#\e(B
+
+\e$BNc$($P!"5-;v$r%(!<%8%'%s%H$K%@%&%s%m!<%I$7$F$$$k4V$K%5!<%P!<$X$N@\B3$,@Z\e(B
+\e$B$l$F$7$^$&>l9g!"%m!<%+%k$N%G!<%?9=B$$O@\B3$,@Z$l$kA0$K5-;v$,<sHxNI$/%@%&\e(B
+\e$B%s%m!<%I$5$l$?$+$I$&$+$rCN$j$^$;$s!#\e(B@code{gnus-agent-regenerate} \e$B$^$?\e(B
+\e$B$O\e(B @code{gnus-agent-regenerate-group} \e$B$r<B9T$9$k$H!"$=$N$h$&$J5-;v$rFs2s\e(B
+\e$B%@%&%s%m!<%I$7$J$/$F$b:Q$`$h$&$K%G!<%?9=B$$r99?7$7$^$9!#\e(B
+
+@findex gnus-agent-regenerate
+@kindex M-x gnus-agent-regenerate
+\e$B%3%^%s%I\e(B @code{gnus-agent-regenerate} \e$B$O!"$9$Y$F$N%(!<%8%'%s%H2=$5$l$?%0\e(B
+\e$B%k!<%W$G\e(B @code{gnus-agent-regenerate-group} \e$B$r<B9T$7$^$9!#$I$N%P%C%U%!>e\e(B
+\e$B$G$b\e(B @code{gnus-agent-regenerate} \e$B$r<B9T$9$k$3$H$,$G$-$^$9$,!":G=i$K$9$Y\e(B
+\e$B$F$N35N,%P%C%U%!$rJD$8$k$3$H$r6/$/4+$a$^$9!#\e(B
+
+@findex gnus-agent-regenerate-group
+@kindex M-x gnus-agent-regenerate-group
+\e$B%3%^%s%I\e(B @code{gnus-agent-regenerate-group} \e$B$O!"%m!<%+%k\e(B
+\e$B$N\e(B @acronym{NOV} (\e$B%X%C%@!<\e(B) \e$B%G!<%?%Y!<%9$r=$I|$9$k$?$a$K!"8D!9$N5-;v$N%m!<\e(B
+\e$B%+%k$J%3%T!<$r;H$$$^$9!#$=$N8e$=$l$O!"$I$N5-;v$,%m!<%+%k$K3JG<$5$l$k$+$r\e(B
+\e$BN"IU$1$k$?$a$NFbIt%G!<%?9=B$$r99?7$7$^$9!#0z?t$rM?$($k$H!"%(!<%8%'%s%H$N\e(B
+\e$BCf$N5-;v$KL$FI$N0u$rIU$1$^$9!#\e(B
+
+@node Agent and IMAP
+@subsection \e$B%(!<%8%'%s%H$r\e(B IMAP \e$B$G;H$&J}K!\e(B
+
+\e$B%(!<%8%'%s%H$O\e(B nnimap \e$B$r4^$`\e(B gnus \e$B$N$I$s$J%P%C%/%(%s%I$G$bF0:n$7$^$9!#$7\e(B
+\e$B$+$7\e(B @acronym{NNTP} \e$B$H\e(B @acronym{IMAP} \e$B$K$O$$$/$D$+$N35G0$N0c$$$,$"$k$N$G!"\e(B
+\e$B$3$N9`$G$O\e(B gnus \e$B%(!<%8%'%s%H$r\e(B @acronym{IMAP} \e$B$N\e(B @dfn{unplugged} \e$B$J%b!<\e(B
+\e$B%I$N%/%i%$%"%s%H$H$7$F1_3j$K;H$($k$h$&$K$9$k$?$a$N!"$$$/$D$+$N>pJs$rDs6!\e(B
+\e$B$7$^$9!#\e(B
+
+\e$B?4$KN1$a$F$*$/:G=i$N$3$H$O!"A4$F$N%U%i%0\e(B (read, ticked \e$B$J$I\e(B) \e$B$O\e(B nntp \e$B$N\e(B
+\e$B>l9g$K$*$1$k\e(B @file{.newsrc} \e$B$G$O$J$/$F\e(B @acronym{IMAP} \e$B%5!<%P!<$KJ];}$5$l\e(B
+\e$B$k$H$$$&$3$H$G$9!#$7$?$,$C$F!"\e(Bgnus \e$B$O\e(B @dfn{unplugged} \e$B$N$H$-$N%U%i%0$NJQ\e(B
+\e$B2=$r3P$($F$*$$$F!":F$S@\B3$7$?$H$-$K$=$l$i$N%U%i%0$rF14|$5$;$kI,MW$,$"$j\e(B
+\e$B$^$9!#\e(B
+
+gnus \e$B$O%(!<%8%'%s%H$N85$G\e(B nnimap \e$B%0%k!<%W$rFI$`$H$-!"%U%i%0$NJQ2=$K@d$(\e(B
+\e$B$:Cm0U$7$F$$$^$9!#$"$J$?$,:F$S@\B3$7$?$H$-!"\e(Bgnus \e$B$O$"$J$?$,2?$i$+$N%U%i\e(B
+\e$B%0$rJQ99$7$?$+$I$&$+$rD4$Y$F!"$"$J$?$,$=$l$i$r%5!<%P!<$HF14|$5$;$?$$$+$I\e(B
+\e$B$&$+$r?R$M$^$9!#$3$N5sF0$O\e(B @code{gnus-agent-synchronize-flags} \e$B$G%+%9%?\e(B
+\e$B%^%$%:$9$k$3$H$,$G$-$^$9!#\e(B
+
+@vindex gnus-agent-synchronize-flags
+\e$B$b$7\e(B @code{gnus-agent-synchronize-flags} \e$B$,\e(B @code{nil} \e$B$@$C$?$i!"%(!<%8%'\e(B
+\e$B%s%H$O<+F0E*$K%U%i%0$rF14|$5$;$k$3$H$O$7$^$;$s!#$b$7$=$l$,=i4|CM\e(B
+\e$B$N\e(B @code{ask} \e$B$@$C$?$i!"%(!<%8%'%s%H$O$"$J$?$,:F@\B3$7$?$H$-$K$"$J$?$,2?\e(B
+\e$B$i$+$NJQ99$r9T$J$C$F$$$?$+$I$&$+$rD4$Y$F!"$=$l$i$rF14|$5$;$?$$$+$I$&$+$r\e(B
+\e$B?R$M$^$9!#$b$7$=$l$i0J30$NCM$@$C$?>l9g$O!"A4$F$N%U%i%0$O<+F0E*$KF14|$5$;\e(B
+\e$B$i$l$^$9!#\e(B
+
+\e$B$b$7$"$J$?$,!":F@\B3$7$?$H$-$K<+F0$G%U%i%0$rF14|$5$;$?$/$J$$$J$i!"<jF0$G\e(B
+\e$B$=$l$r9T$J$&$3$H$b$G$-$^$9!#$3$l$K$O%0%k!<%W%P%C%U%!$N\e(B @kbd{J Y} \e$B%-!<$K\e(B
+\e$B3d$jEv$F$i$l$?\e(B @code{gnus-agent-synchronize-flags} \e$B%3%^%s%I$r;H$$$^$9!#\e(B
+
+\e$B$"$J$?$,!"\e(B@dfn{unplugged} \e$B$N$H$-$N\e(B @acronym{IMAP} \e$B%/%i%$%"%s%H$K4|BT$9$k\e(B
+\e$B$G$"$m$&$$$/$D$+$N5!G=$O!"8=:_$N%(!<%8%'%s%H$K$O@9$j9~$^$l$F$$$^$;$s!#$=\e(B
+\e$B$l$i$O0J2<$NDL$j$G$9!#\e(B
+
+@itemize @bullet
+
+@item
+@dfn{unplugged} \e$B$N$H$-$N\e(B nnimap \e$B%0%k!<%W$X$N%3%T!<$H0\F0!#\e(B
+
+@item
+@dfn{unplugged} \e$B$N$H$-$N\e(B nnimap \e$B%0%k!<%W$N:n@.$H:o=|!#\e(B
+@end itemize
+
+\e$B5;=QE*Cm<a\e(B: \e$BA4$F$N%m!<%+%k$J%U%i%0$r0lEY$K%5!<%P!<$K\e(B ``\e$B2!$79~$`\e(B'' \e$BF14|$O\e(B
+\e$B$G$-$^$;$s$,!"%f!<%6$,0l$D$:$D%U%i%0$r99?7$9$k$3$H$O2DG=$G$9!#$7$?$,$C$F!"\e(B
+\e$B$"$J$?$,5-;v$N0l$D$N%U%i%0$r%;%C%H$7$F!"$=$N%0%k!<%W$rH4$1=P$F$+$i:FEY$=\e(B
+\e$B$N%0%k!<%W$rA*Br$7$F$=$N%U%i%0$r>C$;$P!"$"$J$?$,\e(B ``\e$BF14|\e(B'' \e$B$NA`:n$r9T$J$C\e(B
+\e$B$?$H$-$K!"$=$N%U%i%0$O%;%C%H$5$l$F%5!<%P!<$+$i$O:o=|$5$l$^$9!#\e(B
+@c FIXMETGNUS Does it make sense?
+"The queued flag" \e$B$K4X$9$kF0:n$O!"%(!<%8%'%s%H%G%#%l%/%H%j$K$"$k%5!<%P!<\e(B
+\e$BKh$N\e(B @code{flags} \e$B%U%!%$%k$NCf$G8+$D$+$k$G$7$g$&!#$=$l$i$O$"$J$?$,%U%i%0\e(B
+\e$B$rF14|$5$;$?$H$-$K6u$K$J$j$^$9!#\e(B
+
+@node Outgoing Messages
+@subsection \e$B:9=PMQ%a%C%;!<%8\e(B
+
+Gnus \e$B$,@Z$jN%$5$l$F$$$k$H$-!"A4$F$N:9=PMQ%a%C%;!<%8\e(B (\e$B%a!<%k$H%K%e!<%9$N\e(B
+\e$BN>J}\e(B) \e$B$O2<=q$-%0%k!<%W\e(B ``queue'' (@pxref{Drafts}) \e$B$K3JG<$5$l$^$9!#Ej9F$7\e(B
+\e$B$?8e$G$b!"$3$3$G$=$N%a%C%;!<%8$r8+$?$jJT=8$9$k$N$O0U$N$^$^$G$9!#\e(B
+
+Gnus \e$B$,:F$S:9$79~$^$l$?$H$-!"%a%C%;!<%8$rAw?.$9$k$?$a$K!"FCJL$JL?Na$r;H$C\e(B
+\e$B$F2<=q$-%0%k!<%W$+$iAw$k$3$H$b!"%0%k!<%W%P%C%U%!Fb$G\e(B @kbd{J S} \e$B$r;H$C$F!"\e(B
+\e$B2<=q$-%0%k!<%WFb$NA4$F$NAw?.2DG=%a%C%;!<%8Aw?.$9$k$3$H$b$G$-$^$9!#\e(B
+
+@node Agent Variables
+@subsection \e$B%(!<%8%'%s%HJQ?t\e(B
+
+@table @code
+@item gnus-agent-directory
+@vindex gnus-agent-directory
+Gnus \e$B%(!<%8%'%s%H$,%U%!%$%k$r3JG<$9$k>l=j!#=i4|@_DjCM\e(B
+\e$B$O\e(B @file{~/News/agent/}\e$B!#\e(B
+
+@item gnus-agent-handle-level
+@vindex gnus-agent-handle-level
+\e$B$3$NJQ?t$NCM$h$j9b$$%l%Y%k\e(B (@pxref{Group Levels}) \e$B$N%0%k!<%W$O!"%(!<%8%'\e(B
+\e$B%s%H$+$i$OL5;k$5$l$^$9!#=i4|@_DjCM$O\e(B @code{gnus-level-subscribed} \e$B$G!"$3\e(B
+\e$B$l$O=i4|@_Dj$G$O!"9XFI$7$F$$$k%0%k!<%W$N$_$,%(!<%8%'%s%H$N=hM}$NBP>]$H$J\e(B
+\e$B$k$H$$$&$3$H$G$9!#\e(B
+
+@item gnus-agent-plugged-hook
+@vindex gnus-agent-plugged-hook
+\e$B%M%C%H%o!<%/$K@\B3$5$l$?$H$-$K<B9T$5$l$k%U%C%/!#\e(B
+
+@item gnus-agent-unplugged-hook
+@vindex gnus-agent-unplugged-hook
+\e$B%M%C%H%o!<%/$+$i@ZCG$5$l$?$H$-$K<B9T$5$l$k%U%C%/!#\e(B
+
+@item gnus-agent-fetched-hook
+@vindex gnus-agent-fetched-hook
+\e$B5-;v$r<h$j9~$_=*$o$C$?$H$-$K<B9T$5$l$k%U%C%/!#\e(B
+
+@item gnus-agent-cache
+@vindex gnus-agent-cache
+plugged \e$B$N$H$-$K!"%m!<%+%k$K;}$C$F$$$k\e(B @acronym{NOV} \e$B$H5-;v$r;H$&$+$I$&\e(B
+\e$B$+$r@)8f$9$kJQ?t$G!"Nc$($P%(!<%8%'%s%H$r%-%c%C%7%e$H$7$F;H$&$K$OI,?\$G$9!#\e(B
+\e$B%G%#%U%)%k%H$G$OHs\e(B-@code{nil} \e$B$G!"%(!<%8%'%s%H$r%-%c%C%7%e$H$7$F;H$$$^$9!#\e(B
+
+@item gnus-agent-go-online
+@vindex gnus-agent-go-online
+@code{gnus-agent-go-online} \e$B$,\e(B @code{nil} \e$B$@$C$?$i!"%(!<%8%'%s%H$O%*%U%i\e(B
+\e$B%$%s>uBV$N%5!<%P!<$r%*%s%i%$%s>uBV$K$7$^$;$s!#\e(B@code{ask} \e$B$@$C$?$i!"$=$l\e(B
+\e$B$,%G%#%U%)%k%H$G$9$,!"%(!<%8%'%s%H$O:F@\B3$9$k$H$-$K%*%U%i%$%s>uBV$N%5!<\e(B
+\e$B%P!<$r%*%s%i%$%s>uBV$K$9$k$+$I$&$+$r?R$M$^$9!#$=$l0J30$NCM$@$C$?$i!"%*%U\e(B
+\e$B%i%$%s>uBV$N%5!<%P!<$O<+F0E*$K%*%s%i%$%s>uBV$K$J$j$^$9!#\e(B
+
+@item gnus-agent-mark-unread-after-downloaded
+@vindex gnus-agent-mark-unread-after-downloaded
+@code{gnus-agent-mark-unread-after-downloaded} \e$B$,\e(B \e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"\e(B
+\e$B%@%&%s%m!<%I$7$?8e$G5-;v$KL$FI$N0u$rIU$1$^$9!#$3$l$ODL>o!"?7$7$/%@%&%s%m!<\e(B
+\e$B%I$5$l$?5-;v$rL@3N$KL$FI$K$9$k$?$a$N0BA4$J9T0Y$G$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-agent-consider-all-articles
+@vindex gnus-agent-consider-all-articles
+@code{gnus-agent-consider-all-articles} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"%(!<%8%'\e(B
+\e$B%s%H$O$9$Y$F$N5-;v$K$D$$$F!"$=$l$i$r%@%&%s%m!<%I$9$kI,MW$,$"$k$+$I$&$+$r\e(B
+\e$B%(!<%8%'%s%H$N=R8l$K7hDj$5$;$^$9!#\e(B@code{nil} \e$B$@$C$?>l9g!"$=$l$,%G%#%U%)\e(B
+\e$B%k%H$G$9$,!"%(!<%8%'%s%H$OL$FI$N5-;v$r%@%&%s%m!<%I$9$k$+$I$&$+$@$1$r=R8l\e(B
+\e$B$K7hDj$5$;$^$9!#$3$l$rM-8z$K$9$k$K$O!"8e$G%(!<%8%'%s%H$,4|8B@Z$l>C5n$9$k\e(B
+\e$B5-;v$r2?EY$b7+$jJV$7%@%&%s%m!<%I$7$J$$$h$&$K!"%(!<%8%'%s%H$N4|8B@Z$l>C5n\e(B
+\e$B$N@_Dj\e(B (@pxref{Category Variables}) \e$B$r8+D>$9I,MW$b$"$k$+$b$7$l$^$;$s!#\e(B
+
+@item gnus-agent-max-fetch-size
+@vindex gnus-agent-max-fetch-size
+\e$B%(!<%8%'%s%H$O!"<hF@$7$?5-;v$r8D!9$N%U%!%$%k$KF~$l$k$?$a$N2r@O$r9T$J$&A0\e(B
+\e$B$K!"$=$l$i$r0l;~E*$J%P%C%U%!!<$X<h$j9~$_$^$9!#:GBg$N%P%C%U%!%5%$%:$rD62a\e(B
+\e$B$7$J$$$h$&$K$9$k$?$a$K!"5-;v$,$9$Y$F<hF@$5$l$k$^$G!"%(!<%8%'%s%H$O<hF@$H\e(B
+\e$B2r@O$r8r8_$K9T$J$$$^$9!#\e(B@code{gnus-agent-max-fetch-size} \e$B$O!"7+$jJV$7$,\e(B
+\e$B$I$l$/$i$$IQHK$K5/$-$k$+$r@)8f$9$k$?$a$N!"%5%$%:$N8B3&$r5,Dj$7$^$9!#Bg$-\e(B
+\e$B$JCM$O@-G=$r2~A1$7$^$9!#>.$5$JCM$O!"K|$,0l<hF@$7$F$$$k4V$K@\B3$,@Z$l$?>l\e(B
+\e$B9g$K!"CY$l;~4V$r:G>.$K$7$^$9\e(B (\e$B%0%k!<%W$N>uBV$r99?7$9$k$?$a\e(B
+\e$B$K\e(B @code{gnus-agent-regenerate-group} \e$B$r<B9T$9$kI,MW$,$"$k$+$b$7$l$^$;\e(B
+\e$B$s!#$G$b!"@\B3$,@Z$l$kA0$K2r@O$5$l$?$9$Y$F$N5-;v$O!"\e(Bunplugged \e$B$N4|4V$KMx\e(B
+\e$BMQ$9$k$3$H$,$G$-$k$G$7$g$&!#\e(B)\e$B!#7+$jJV$7$KAx6x$9$k$3$H$ODA$7$$$N$G!"%G%#\e(B
+\e$B%U%)%k%H$O\e(B 10M \e$B$G$9\e(B
+
+@item gnus-server-unopen-status
+@vindex gnus-server-unopen-status
+\e$B$?$V$s%(!<%8%'%s%HJQ?t$G$O$J$$$,%(!<%8%'%s%H$KL)@\$K4XO"$9$k$3$NJQ?t$O!"\e(B
+gnus \e$B$,%5!<%P!<$K@\B3$G$-$J$H$-$K2?$,5/$-$?$+$rJ*8l$j$^$9!#%(!<%8%'%s%H\e(B
+\e$B$,3h@-2=$5$l$k$H!"%G%#%U%)%k%H$N\e(B @code{nil} \e$B$G$O!"%f!<%6!<$,%5!<%P!<$H$N\e(B
+\e$B@\B3$r@d$D$+%(!<%8%'%s%H$r\e(B unplug \e$B$K$9$k$+$r\e(B gnus \e$B$K?R$M$5$;$^$9!#%(!<%8%'\e(B
+\e$B%s%H$,IT3h@-2=$5$l$k$H!"\e(Bgnus \e$B$O$$$D$bC1$K%5!<%P!<$H$N@\B3$r@d$A$^$9!#$3\e(B
+\e$B$NJQ?t$NB>$NA*Br;h$K$O\e(B @code{denied} \e$B$H\e(B @code{offline} \e$B$,$"$j!"%(!<%8%'\e(B
+\e$B%s%H$,;H$o$l$k>l9g$O8e<T$@$1$,M-8z$G$9!#\e(B
+
+@item gnus-auto-goto-ignores
+@vindex gnus-auto-goto-ignores
+\e$BBgDq$N?M$O!"%(!<%8%'%s%HJQ?t$G$O$J$$$,L)@\$K4XO"$9$k$b$&0l$D$NJQ?t$r$3$3\e(B
+\e$B$GC5$9$G$7$g$&!#$3$NJQ?t$O!"%@%&%s%m!<%I$5$l$F$$$J$$\e(B (\e$B%X%C%@!<$@$1$,%(!<\e(B
+\e$B%8%'%s%H$K3JG<$5$l$?\e(B)\e$B!"$=$7$F<h$j9~$^$l$F$$$J$$\e(B (\e$B5-;v$b%X%C%@!<$b3JG<$5\e(B
+\e$B$l$F$$$J$$\e(B) \e$B5-;v$r$I$&A`:n$9$k$+$r35N,%P%C%U%!$KEA$($^$9!#\e(B
+
+\e$B@5Ev$JCM$O\e(B @code{nil} (\e$B$I$N5-;v$bA`:n$9$k\e(B)\e$B!"\e(B
+@code{undownloaded} (@dfn{unplugged} \e$B$J4|4V$NA`:n$O<h$j9~$^$l$F$$$J$$5-\e(B
+\e$B;v$rL5;k$9$k$3$H\e(B)\e$B!"\e(B@code{always-undownloaded} (\e$BA`:n$O<h$j9~$^$l$F$$$J$$\e(B
+\e$B5-;v$r>o$KL5;k$9$k$3$H\e(B)\e$B!"\e(B@code{unfetched} (\e$BA`:n$O%X%C%@!<$,<h$j9~$^$l$F\e(B
+\e$B$$$J$$5-;v$rL5;k$9$k$3$H\e(B) \e$B$G$9!#\e(B(\e$BLuCm\e(B: \e$B$&!<$`\e(B Kevin \e$B$5$s$O2?$r8@$C$F$k$s\e(B
+\e$B$@\e(B?)
+@end table
+
+@node Example Setup
+@subsection \e$B@_DjNc\e(B
+
+\e$B$b$7$"$J$?$,$3$N%^%K%e%"%k$rFI$_$?$/$J$/$F!"$4$/I8=`E*$J@_Dj$,$5$l$F$$$k\e(B
+\e$B$H$9$k$J$i!"$"$J$?$N\e(B @file{~/.gnus.el} \e$B%U%!%$%k$K0J2<$N$h$&$J@_Dj$r$9$k\e(B
+\e$B$H$3$m$+$i;O$a$i$l$k$G$7$g$&!#\e(B
+
+@lisp
+;;; @r{gnus \e$B$,$I$N$h$&$K%K%e!<%9$r<hF@$9$k$+$rDj5A$9$k!#$3$3$G$O\e(B}
+;;; @r{ISP \e$B$N%5!<%P!<$+$i\e(B @acronym{NNTP} \e$B$G<h$C$F$/$k$3$H$K$9$k!#\e(B}
+(setq gnus-select-method '(nntp "news.your-isp.com"))
+
+;;; @r{Gnus \e$B$,$I$N$h$&$K%a!<%k$rFI$`$+$rDj5A$9$k!#\e(BISP \e$B$N\e(B @acronym{POP}}
+;;; @r{\e$B%5!<%P!<$+$i%a!<%k$rFI$`$3$H$K$9$k!#\e(B}
+(setq mail-sources '((pop :server "pop.your-isp.com")))
+
+;;; @r{Gnus \e$B$,%a!<%k$r$I$N$h$&$K3JG<$9$k$+$r;XDj$9$k!#\e(Bnnml \e$B%0%k!<%W\e(B}
+;;; @r{\e$B$r;H$&!#\e(B}
+(setq gnus-secondary-select-methods '((nnml "")))
+
+;;; @r{Gnus \e$B$r%*%U%i%$%s%K%e!<%9%j!<%@!<$K$9$k!#\e(B}
+;;; (gnus-agentize) ; @r{\e$B5l<0$N@_Dj!#\e(B}
+;;; (setq gnus-agent t) ; @r{\e$B8=:_$N%G%#%U%)%k%H!#\e(B}
+@end lisp
+
+\e$B4pK\E*$K$O$3$l$@$1$GNI$$$O$:$G$9!#$3$l$r$"$J$?$N\e(B @file{~/.gnus.el} \e$B%U%!\e(B
+\e$B%$%k$KF~$l$F!"$"$J$?$NMWK>$K9g$o$;$FJT=8$7!"\e(BPPP (\e$B$d2?$+\e(B) \e$B$r5/F0$7$F!"\e(B
+@kbd{M-x gnus} \e$B$HBG80$7$F$/$@$5$$!#\e(B
+
+\e$B$"$J$?$,=i$a$F\e(B gnus \e$B$r<B9T$9$k$7$?$H$-$O!"$$$/$D$+$N%K%e!<%9%0%k!<%W$,=i\e(B
+\e$B4|@_Dj$H$7$F<+F0E*$K9XFI$5$l$^$9!#$*$=$i$/$b$C$H$?$/$5$s$N%0%k!<%W$r9XFI\e(B
+\e$B$7$?$/$J$k$G$7$g$&$1$I!"$=$N$?$a$K$O!"\e(B@kbd{A A} \e$BL?Na$G\e(B @acronym{NNTP} \e$B%5!<\e(B
+\e$B%P!<$KA4%0%k!<%W$N0lMw$rLd$$9g$o$;$J$1$l$P$J$j$^$;$s!#$3$l$ODL>o$H$F$b;~\e(B
+\e$B4V$,$+$+$j$^$9$,!"0lEY$@$1$7$+<B9T$9$kI,MW$O$"$j$^$;$s!#\e(B
+
+\e$B$7$P$i$/$NFI$_9~$_$H2r@O$N8e$K!"%0%k!<%W$N0lMw$rDs<($5$;$i$l$k$G$7$g$&!#\e(B
+@kbd{u} \e$BL?Na$GFI$_$?$$%0%k!<%W$r9XFI$7$^$9!#FI$_$?$$%0%k!<%W$rA4It9XFI$7\e(B
+\e$B$?$i!"\e(B@kbd{l} \e$B$G:o=|%0%k!<%W$rA4$F2hLL$+$i>C5n$7$^$9!#\e(B(@kbd{A k} \e$B$G:o=|\e(B
+\e$B%0%k!<%W$OA4$FLa$C$F$-$^$9!#\e(B)
+
+\e$B$5$F!"$3$3$G$=$N>l$G%0%k!<%W$rFI$`$3$H$b$G$-$^$9$7!"$"$k$$\e(B
+\e$B$O\e(B @kbd{J s} \e$BL?Na$G5-;v$r%@%&%s%m!<%I$9$k$3$H$b$G$-$^$9!#$"$H$O$3$N%^%K%e\e(B
+\e$B%"%k$N;D$j$rFI$s$G!"$=$NB>$N2?I42/$N9`L\$+$i%+%9%?%^%$%:$7$?$$$3$H$r8+$D\e(B
+\e$B$1=P$7$F$/$@$5$$!#\e(B
+
+@node Batching Agents
+@subsection \e$B0l3g%(!<%8%'%s%H=hM}\e(B
+@findex gnus-agent-batch
+
+Gnus \e$B%(!<%8%'%s%H$K5-;v$r<hF@$5$;$k$N$O\e(B (\e$B$=$7$F$"$J$?$N=q$$$?2?$+$N%a%C\e(B
+\e$B%;!<%8$rEj9F$9$k$N$O\e(B)\e$B!"0lC6J*;v$r@5$7$/@_Dj$7$F$7$^$($PHs>o$K4JC1$G$9!#\e(B
+\e$B0J2<$N%7%'%k%9%/%j%W%H$OI,MW$J$3$H$rA4$F$d$C$F$/$l$k$G$7$g$&!#\e(B
+
+\e$B0J2<$N<vJ8$r%3%^%s%I%i%$%s$G;H$&$3$H$K$h$C$F!"40A4$J%P%C%A%3%^%s%I$rAv$i\e(B
+\e$B$;$k$3$H$,$G$-$^$9\e(B:
+
+@example
+#!/bin/sh
+emacs -batch -l ~/.emacs -f -l ~/.gnus.el gnus-agent-batch >/dev/null 2>&1
+@end example
+
+@node Control Agents
+@subsection gnus-agent \e$B4D6-$r\e(B Control \e$B$9$k\e(B
+\e$B$3$3$^$GFI$s$GMh$i$l$F!"%(!<%8%'%s%H$,Hs>o$KJXMx$J5!G=$G$"$k;v$,J,$+$C$?\e(B
+\e$B$H;W$$$^$9!#$?$@!"ITK~$JE@$,$"$k$H$9$k$H!"Kh2s\e(B @kbd{J j} \e$B$d\e(B @kbd{J S} \e$BEy\e(B
+\e$B$r%-!<$G:n6H$7$J$1$l$P$J$i$J$$$3$H$G$7$g$&!#%*%s%i%$%s$HF1$8$h$&$JA`:n$G\e(B
+\e$B$d$j$H$j$G$-$?$i!"$H9M$($?;v$O$"$j$^$;$s$+\e(B?
+gnus-offline \e$B$O$=$N5!G=$rDs6!$7$^$9!#\e(B(\e$BI.<T$N<qL#$G\e(B gnus-agent \e$B$r;HMQ$9$k\e(B
+\e$B;v$r?d>)$7$^$9!#\e(B@code{MIEE} \e$B$K$D$$$F$O8e=R;2>H\e(B)
+
+*Group* \e$B%P%C%U%!$G\e(B @kbd{g} \e$B$r2!$9;v$G\e(B
+
+@lisp
+ (Dialup \e$B$NI,MW$J4D6-$G$O\e(B Dialup) ->
+  Mail \e$B$N<hF@\e(B ->
+  Spool \e$B$KN/$C$?\e(B message \e$B$NAw?.\e(B ->
+  News \e$B$NAw?.\e(B ->
+  \e$BITMW$J5-;v$N\e(B expire
+@end lisp
+
+\e$B$^$G$r9T$$$^$9!#\e(B
+
+\e$B%$%s%9%H!<%k$O$$$?$C$F4JC1!#\e(B(\e$B$3$3$^$G$G\e(B gnus-agent \e$B$N@_Dj$O=*$C$F$$$k$H\e(B
+\e$B2>Dj$7$^\e(B
+\e$B$9\e(B) @file{~/.emacs} \e$B$N\e(B gnus-agent \e$B$N@_Dj$N$A$g$$$HA0$K\e(B
+
+@lisp
+(load "gnus-ofsetup")
+(gnus-setup-for-offline)
+(load gnus-offline-setting-file)
+@end lisp
+
+@acronym{POP} \e$B$H$$$l!"\e(BEmacs \e$B$r:F5/F0$7$F$/$@$5$$!#$9$k$H!"$5$^$6$^$J<ALd\e(B
+\e$B$r$5$l$k$H;W$$$^$9!#$=$3$G$O!"$"$J$?$N4D6-$K$"$C$?Ez$($r$7$F$/$@$5$$!#<A\e(B
+\e$BLd$,=*$k$H!"@_DjMQ$N%U%!%$%k\e(B @file{~/.gnus-offline.el} \e$B$,:n@.$5$l$^$9!#\e(B
+\e$B$3$3$K!"I,MW$J@_DjA4$F$,=q$+$l$F$$$^$9!#\e(BGnus \e$B$N5/F0$,=*$j!"\e(B(\e$BB?\e(B
+\e$BJ,\e(B @acronym{POP} \e$B%5!<%P!<$N%Q%9%o!<%I$rJ9$+$l$k$H;W$$$^$9$,\e(B) *Group* \e$B%P%C\e(B
+\e$B%U%!$K$J$C$?$i!"\e(B@kbd{J j} \e$B$d\e(B @kbd{J S} \e$BEy$NA`:n$OI,MW$"$j$^$;$s!#\e(B
+News/Mail \e$B$r?75,$G<hF@$7$?$1$l$P!"\e(B*Group* \e$B%P%C%U%!$G\e(B @kbd{g} \e$B$r2!$9$@$1\e(B
+\e$B$G$9!#\e(B
+
+@code{MIEE} = Message Intercepting and Entrusting Emacs library.
+Message \e$B$r2#<h$j$7$F!"\e(Boffline \e$B$G\e(B post/send \e$B$9$k$?$a$NHFMQ%i%$%V%i%j$G$9!#\e(B
+
+\e$B$3$N\e(B @code{MIEE} \e$B$r;H$&$H\e(B @code{gnus-offline} \e$B$rMQ$$$F\e(B@code{nnspool} \e$B$b\e(B
+\e$B%3%s%H%m!<%k$9$k;v$,$G$-$^$9\e(B(\e$B$3$3$G$O=R$Y$^$;$s$,!D\e(B)\e$B!#\e(B(\e$B$b$A$m\e(B
+\e$B$s\e(B @code{gnus-agent} + @code{MIEE} \e$B$H$$$&AH9g$;$b2DG=$G\e(B
+\e$B$9\e(B) @code{MIEE} \e$B$O\e(B @uref{http://www.shiojiri.ne.jp/%7Et-ichi/lisp/miee.el} \e$B$+\e(B
+\e$B$i<h$C$FMh$k;v$,$G$-$^$9!#\e(B@code{gnus-setup-for-offline} \e$B$G@_Dj$7$?>l9g$K\e(B
+\e$B$O!"\e(B@code{MIEE} \e$B$N@_Dj$O$$$C$5$$$7$J$/$F$b$+$^$$$^$;$s!#\e(B
+
+@table @code
+@vindex gnus-offline-articles-to-fetch
+@item gnus-offline-articles-to-fetch
+\e$B$3$NJQ?t$O<hF@$9$k5-;v$N<oN`$r;XDj$7$^$9!#\e(B'mail \e$B$N>l9g$O!"\e(BMail \e$B$@$1$r<h\e(B
+\e$BF@$7$^$9!#\e(B'news \e$B$N>l9g$O!"\e(BNews \e$B$@$1$r<hF@$7$^$9!#\e(B'both \e$B$N>l9g$O!"\e(B
+Mail/News \e$BN>J}$r<hF@$7$^$9!#\e(B
+
+@vindex gnus-offline-load-hook
+@item gnus-offline-load-hook
+\e$B$3$NJQ?t$O\e(B @code{gnus-offline} \e$B$,\e(B load \e$B$5$l$kA0$KI>2A$5$l$k\e(B hook \e$B$G$9!#\e(B
+
+@vindex gnus-offline-before-online-hook
+@item gnus-offline-before-online-hook
+\e$B$3$NJQ?t$O\e(B Gnus \e$B$,\e(B Online(Plugged) \e$B>uBV$K$J$kD>A0$KI>2A$5$l$k\e(B hook \e$B$G$9!#\e(B
+
+@vindex gnus-offline-after-online-hook
+@item gnus-offline-after-online-hook
+\e$B$3$NJQ?t$O\e(B Gnus \e$B$,\e(B Offline(UnPlugged) \e$B>uBV$K$J$C$?8e$KI>2A$5$l$k\e(B hook \e$B$G\e(B
+\e$B$9!#\e(B
+
+@vindex gnus-offline-interval-time
+@item gnus-offline-interval-time
+\e$B$3$NJQ?t$G;XDj$5$l$?4V\e(B
+\e$B3V\e(B (\e$BIC?t\e(B) \e$B$G\e(B @code{gnus-offline-articles-to-fetch} \e$B$G;XDj$5$l\e(B
+\e$B$?\e(B article \e$B$r<hF@$7$^$9!#F0:n$K$O\e(B@code{gnus-daemon} \e$B$r;HMQ$7$F$$$^$9!#\e(B
+
+@vindex gnus-offline-dialup-function
+@item gnus-offline-dialup-function
+\e$B$3$NJQ?t$G;XDj$5$l$?4X?t$,\e(B dialup \e$B;~$K<B9T$5$l!"\e(BDialup \e$B$7%5!<%P!<$K@\B3\e(B
+\e$B$7$^$9!#\e(B
+
+@vindex gnus-offline-hangup-function
+@item gnus-offline-hangup-function
+\e$B$3$NJQ?t$G;XDj$5$l$?4X?t$,\e(B hangup \e$B;~$K<B9T$5$l!"%5!<%P!<$H$N2s@~$r@ZCG$7\e(B
+\e$B$^$9!#\e(B
+@end table
+
+@node Agent Caveats
+@subsection \e$B%(!<%8%'%s%H$NLdBjE@\e(B
+
+Gnus Agent \e$B$O$h$/$"$kB>$N%*%U%i%$%s%K%e!<%9%j!<%@!<$N$h$&$K$OF0:n$7$^$;\e(B
+\e$B$s!#$3$l$i$OA[A|E*$J?M$+$i$NNI$/$"$k<ALd$G$9\e(B:
+
+@table @dfn
+@item \e$B@\B3$5$l$F$$$k$H$-$K5-;v$rFI$s$@$i!"$=$l$O\e(B Agent \e$B$KF~$k$N$G$9$+\e(B?
+
+@strong{\e$B$$$$$(\e(B}\e$B!#$3$NF0:n$rK>$`$N$J$i$P!"\e(B
+@code{gnus-select-article-hook} \e$B$K\e(B @code{gnus-agent-fetch-selected-article} \e$B$r\e(B
+\e$B2C$($F2<$5$$!#\e(B
+
+@item \e$B@\B3$5$l$F$$$k$H$-$K5-;v$rFI$s$G!"\e(BAgent \e$B$K5-;v$,B8:_$7$F$$$k>l9g!"\e(B
+\e$B$b$&0l2s%@%&%s%m!<%I$5$l$k$N$G$9$+\e(B?
+
+@strong{\e$B$$$$$(\e(B}\e$B!"$?$@$7\e(B @code{gnus-agent-cache} \e$B$,\e(B @code{nil} \e$B$G$J$+$C$?\e(B
+\e$B$i!"$G$9$,!#\e(B
+@end table
+
+\e$BMWLs$9$k$H!"\e(Bgnus \e$B$,@Z$jN%$5$l$F$$$k$H$-$O%m!<%+%k$KJ]B8$5$l$?5-;v$r8+$k\e(B
+\e$B$@$1$G$9!#@\B3$5$l$F$$$k$H$-$O\e(B ISP \e$B$HOC$7!"$+$D%m!<%+%k$K;}$C$F$$$k5-;v\e(B
+\e$B$b;H$&$+$b$7$l$^$;$s!#\e(B
+
+@node Scoring
+@chapter \e$B%9%3%"\e(B
+@cindex scoring
+
+\e$BB>$N?M!9$O\e(B @dfn{\e$B:o=|%U%!%$%k\e(B} \e$B$r;H$$$^$9$,!"$3$3\e(B gnus \e$B%?%o!<$O:o=|$h$j$b\e(B
+\e$B%9%3%"$NJ}$r9%$_$^$9$N$G!"B>$H3JF.$9$k$h$j$O@Z$jBX$($k;v$K$7$^$7$?!#$=$l\e(B
+\e$B$i$O40A4$K0c$&;v$r$7$^$9$N$G!"??$CD>$0$K:B$C$FCm0U$rJ'$C$F$/$@$5$$\e(B!
+
+@vindex gnus-summary-below
+\e$BA4$F$N5-;v$O%9%3%"$N=i4|CM$r;}$C$F$*\e(B
+\e$B$j\e(B (@code{gnus-summary-default-score})\e$B!"$3$l$O%G%#%U%)%k%H$G\e(B 0 \e$B$G$9!#$3\e(B
+\e$B$N%9%3%"$OBPOCE*$d!"%9%3%"%U%!%$%k\e(B (score file) \e$B$NJ}K!$K$h$j!">e$2$i$l$?\e(B
+\e$B$j2<$2$i$l$?$j$7$^$9!#\e(B@code{gnus-summary-mark-below} \e$B$h$j$bDc$$%9%3%"$N\e(B
+\e$B5-;v$K$O4{FI$N0u$,IU$-$^$9!#\e(B
+
+Gnus \e$B$O35N,%P%C%U%!$r:n@.$9$kA0$K!"8=:_$N%0%k!<%W$KE,MQ$5$l$k$I$s\e(B
+\e$B$J\e(B @dfn{\e$B%9%3%"%U%!%$%k\e(B} \e$B$bFI$_9~$_$^$9!#\e(B
+
+\e$B8=:_$N5-;v$K4p$E$$$F%9%3%"$NEPO?$rA^F~$9$k$$$/$D$+$NL?Na$,35N,%P%C%U%!$K\e(B
+\e$B$"$j$^$9!#Nc$($P!"\e(Bgnus \e$B$KFCDj$NI=Bj$N5-;v$N%9%3%"$r2<$2$?$j>e$2$?$j$9$k\e(B
+\e$B$h$&$K5a$a$k;v$,$G$-$^$9!#\e(B
+
+\e$BFs<oN`$N%9%3%"EPO?$,$"$j$^$9\e(B: \e$B1JB3$H0l;~E*$G$9!#0l;~E*%9%3%"EPO?$O<+J,<+\e(B
+\e$B?H$G4|8B$,$/$k$H:o=|$9$kEPO?$G$9!#Nc$($P!"0l=54V0J>e;H$o$l$F$$$J$$$I$s$J\e(B
+\e$BEPO?$b!"%9%3%"%U%!%$%k$NBg$-$5$r>.$5$/$9$k$?$a$K!"@E$+$K:o=|$5$l$^$9!#\e(B
+
+@menu
+* Summary Score Commands::      \e$B8=:_$N%0%k!<%W$N$?$a$N%9%3%"EPO?$rDI2C$9$k\e(B
+* Group Score Commands::        \e$B0lHLE*$J%9%3%"L?Na\e(B
+* Score Variables::             \e$B$"$J$?$N%9%3%"$r%+%9%?%^%$%:$9$k\e(B (\e$B$^$!!"$J$s$FMQ8l\e(B (Scoring) \e$B$G$7$g$&\e(B)
+* Score File Format::           \e$B%9%3%"%U%!%$%k$K2?$rF~$l$k$+\e(B
+* Score File Editing::          \e$B<j$G%9%3%"%U%!%$%k$rJT=8$9$k;v$b$G$-$k\e(B
+* Adaptive Scoring::            \e$BBg;P\e(B (Big Sister) Gnus \e$B$O$"$J$?$,2?$rFI$s$@$+CN$C$F$$$k\e(B
+* Home Score File::             \e$B?7$7$$%9%3%"EPO?$,$I$3$X9T$/$+$r$I$N$h$&$K;XDj$9$k$+\e(B
+* Followups To Yourself::       \e$B?M$,$"$J$?$KJVEz$7$?$H$-$K\e(B gnus \e$B$K5$IU$+$;$k\e(B
+* Scoring On Other Headers::    \e$BI8=`$G$O$J$$%X%C%@!<$K%9%3%"$rIU$1$k\e(B
+* Scoring Tips::                \e$B$I$&$d$C$F8z2LE*$K%9%3%"$rIU$1$k$+\e(B
+* Reverse Scoring::             \e$B8E$$$b$N$N;R$G$"$k$H$$$&LdBj$OLdBj$G$O$J$$\e(B
+* Global Score Files::          \e$BCO$r$D$+$_!"<*$r@Z$jNv$/%9%3%"%U%!%$%k\e(B
+* Kill Files::                  \e$B$=$l$i$O$^$@$3$3$K$"$k$,!"L5;k$9$k;v$,$G$-$k\e(B
+* Converting Kill Files::       \e$B>C5n%U%!%$%k$r%9%3%"%U%!%$%k$KJQ49$9$k\e(B
+* GroupLens::                   \e$B$I$l$rFI$`$N$,9%$-$+$NM=8@$rF@$k\e(B
+* Advanced Scoring::            \e$B%9%3%"$NK!B'$r:n$k$?$a$KO@M}I=8=$r;H$&\e(B
+* Score Decays::                \e$B%9%3%"$r8O$l$F$$$+$;$k$N$OLr$KN)$D;v$b$"$k\e(B
+@end menu
+
+@node Summary Score Commands
+@section \e$B35N,%9%3%"L?Na\e(B
+@cindex score commands
+
+\e$B%9%3%"EPO?$rJQ99$9$k%9%3%"L?Na$O<B:]$KK\Ev$N%9%3%"%U%!%$%k$r=$@5$9$k$o$1\e(B
+\e$B$G$O$"$j$^$;$s!#$=$l$O$"$^$j$KHs8zN($G$9!#\e(BGnus \e$B$O0JA0$K%m!<%I$5$l$?%9%3\e(B
+\e$B%"%U%!%$%k$N%-%c%C%7%e$rJ];}$7$F$*$j!"$=$N0l$D$O\e(B @dfn{\e$B8=:_$N%9%3%"%U%!%$\e(B
+\e$B%kO"A[%j%9%H\e(B} (current score file alist) \e$B$H9M$($i$l$F$$$^$9!#%9%3%"L?Na\e(B
+\e$B$OC1=c$K$3$N%j%9%H$KEPO?$rA^F~$7$F!"%0%k!<%W$+$i=P$k$H!"$3$N%j%9%H$OJ]B8\e(B
+\e$B$5$l$^$9!#\e(B
+
+\e$B8=:_\e(B (current) \e$B$N%9%3%"%U%!%$%k$O!"<B:]$K$=$N$h$&$J%9%3%"%U%!%$%k$,B8:_\e(B
+\e$B$7$F$$$J$$>l9g$G$b!"=i4|@_Dj$G%0%k!<%W$N%m!<%+%k%9%3%"%U%!%$%k$K$J$C$F$$\e(B
+\e$B$^$9!#%9%3%"L?Na$r2?$+B>$N%9%3%"%U%!%$%k\e(B (\e$BNc!"\e(B@file{all.SCORE}) \e$B$KA^F~$7\e(B
+\e$B$?$$$J$i!"$^$:$3$N%9%3%"%U%!%$%k$r8=:_$N$b$N$K$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$B0lHLE*$J%9%3%"L?Na$O<B:]$K$O%9%3%"%U%!%$%k$rJQ99$7$^$;$s\e(B:
+
+@table @kbd
+@item V s
+@kindex V s (\e$B35N,\e(B)
+@findex gnus-summary-set-score
+\e$B8=:_$N5-;v$N%9%3%"$r@_Dj$7$^$9\e(B (@code{gnus-summary-set-score})\e$B!#\e(B
+
+@item V S
+@kindex V S (\e$B35N,\e(B)
+@findex gnus-summary-current-score
+\e$B8=:_$N5-;v$N%9%3%"$rI=<($7$^$9\e(B (@code{gnus-summary-current-score})\e$B!#\e(B
+
+@item V t
+@kindex V t (\e$B35N,\e(B)
+@findex gnus-score-find-trace
+\e$B8=:_$N5-;v$K;H$o$l$F$$$kA4$F$N%9%3%"K!B'\e(B (score rule) \e$B$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-score-find-trace})\e$B!#\e(B@code{*Score Trace*} \e$B%P%C%U%!\e(B
+\e$B$G!"\e(B@kbd{e} \e$B$r%?%$%W$7$F8=:_9T$N%9%3%"K!B'$KBP1~$9$k%9%3%"%U%!%$%k$rJT=8\e(B
+\e$B$9$k$3$H$,$G$-!"\e(B@kbd{f} \e$B$G$O%9%3%"%U%!%$%k$N%U%)!<%^%C\e(B
+\e$B%H\e(B (@code{gnus-score-pretty-print}) \e$B$HJT=8$r9T$J$&$3$H$,$G$-$^$9!#\e(B
+
+@item V w
+@kindex V w (\e$B35N,\e(B)
+@findex gnus-score-find-favourite-words
+\e$B%9%3%"$K;H$o$l$F$$$k8l$N%j%9%H$rI=<($7$^\e(B
+\e$B$9\e(B (@code{gnus-score-find-favourite-words})\e$B!#\e(B
+
+@item V R
+@kindex V R (\e$B35N,\e(B)
+@findex gnus-summary-rescore
+\e$B8=:_$N35N,$G%9%3%"2aDx$r<B9T$7$^$9\e(B (@code{gnus-summay-rescore})\e$B!#$3$l\e(B
+\e$B$O\e(B gnus \e$B$N8e$m$G$$$m$$$m$H%9%3%"%U%!%$%k$GM7$s$G!"$=$l$N8z2L$r8+$?$$$H$-\e(B
+\e$B$KLrN)$D$+$b$7$l$^$;$s!#\e(B
+
+@item V c
+@kindex V c (\e$B35N,\e(B)
+@findex gnus-score-change-score-file
+\e$B0c$C$?%9%3%"%U%!%$%k$r8=:_$N$b$N$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-score-change-score-file})\e$B!#\e(B
+
+@item V e
+@kindex V e (\e$B35N,\e(B)
+@findex gnus-score-edit-current-scores
+\e$B8=:_$N%9%3%"%U%!%$%k$rJT=8$7$^$9\e(B (@code{gnus-score-edit-current-scores})\e$B!#\e(B
+@code{gnus-score-mode} \e$B%P%C%U%!$K0\F0$9$k;v$K$J$k$G$7$g$&\e(B (@pxref{Score
+File Editing})\e$B!#\e(B
+
+@item V f
+@kindex V f (\e$B35N,\e(B)
+@findex gnus-score-edit-file
+\e$B%9%3%"%U%!%$%k$rJT=8$7$F!"$3$N%9%3%"%U%!%$%k$r8=:_$N$b$N$K$7$^\e(B
+\e$B$9\e(B (@code{gnus-score-edit-file})\e$B!#\e(B
+
+@item V F
+@kindex V F (\e$B35N,\e(B)
+@findex gnus-score-flush-cache
+\e$B8=:_$N%9%3%"%-%c%C%7%e$r=q$-9~$_$^$9\e(B (@code{gnus-score-flush-cache})\e$B!#$3\e(B
+\e$B$l$O%9%3%"%U%!%$%k$rJT=8$7$?8e$KLr$KN)$A$^$9!#\e(B
+
+@item V C
+@kindex V C (\e$B35N,\e(B)
+@findex gnus-score-customize
+\e$B;k3PE*$G4r$7$$J}K!$G%9%3%"%U%!%$%k$r%+%9%?%^%$%:$7$^\e(B
+\e$B$9\e(B (@code{gnus-score-customize})\e$B!#\e(B
+@end table
+
+\e$B$3$l$i$NL?Na$N;D$j$O%m!<%+%k%9%3%"%U%!%$%k$r=$@5$7$^$9!#\e(B
+
+@table @kbd
+@item V m
+@kindex V m (\e$B35N,\e(B)
+@findex gnus-score-set-mark-below
+\e$B%9%3%"$NF~NO$rB%?J$7!"$=$l$h$j$bDc$$%9%3%"$NA4$F$N5-;v$K4{FI$N0u$rIU$1$^\e(B
+\e$B$9\e(B (@code{gnus-score-set-mark-below})\e$B!#\e(B
+
+@item V x
+@kindex V x (\e$B35N,\e(B)
+@findex gnus-score-set-expunge-below
+\e$B%9%3%"$NF~NO$rB%?J$7!"$=$N%9%3%"$h$jDc$$A4$F$N5-;v$r:o=|$9$k$?$a$N%9%3%"\e(B
+\e$BK!B'$r8=:_$N%9%3%"%U%!%$%k$KIU$12C$($^\e(B
+\e$B$9\e(B (@code{gnus-score-set-expunge-below})\e$B!#\e(B
+@end table
+
+\e$B<B:]$K%9%3%"EPO?$r$9$k$?$a$N%-!<BG$A9~$_$OHs>o$K5,B'@5$7$$K!B'$K=>$$$^$9\e(B
+\e$B$N$G!"$=$l$i$NL?NaA4$F$rI=$K>e$2$kI,MW$O$"$j$^$;$s!#\e(B(\e$B$?!<$/$5$s$"$j$^$9!#\e(B)
+
+@findex gnus-summary-increase-score
+@findex gnus-summary-lower-score
+
+@enumerate
+@item
+\e$B:G=i$N%-!<$O%9%3%"$rA}$d$9$?$a$N\e(B @kbd{I} (i \e$B$NBgJ8;z\e(B) \e$B$+!"%9%3%"$r2<$2$k\e(B
+\e$B$?$a$N\e(B @kbd{L} \e$B$G$9!#\e(B
+@item
+\e$BFsHVL\$N%-!<$O$I$N%X%C%@!<$K%9%3%"$r$7$?$$$+$rI=$7$^$9!#0J2<$N%-!<$,;HMQ\e(B
+\e$B2DG=$G$9\e(B:
+
+@table @kbd
+@item a
+\e$BCx<T\e(B (author) \e$B$NL>A0$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item s
+\e$BI=Bj\e(B (subject) \e$B$N9T$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item x
+@code{Xref} \e$B9T$K%9%3%"$rIU$1$^$9\e(B---\e$B$9$J$o$A!"Aj8_Ej9F9T$G$9!#\e(B
+
+@item r
+@code{References} \e$B9T$K%9%3%"$r$D$1$^$9!#\e(B
+
+@item d
+\e$BF|IU\e(B (date) \e$B$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item l
+\e$B9T?t\e(B (number of lines) \e$B$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item i
+@code{Messsage-ID} \e$B%X%C%@!<$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item e
+``\e$BDI2C\e(B'' \e$B$N%X%C%@!<\e(B (\e$B$9$J$o$A!"\e(B(@code{gnus-extra-headers} \e$B$K@_Dj$5$l$F$$\e(B
+\e$B$F!"\e(B@acronym{NNTP} \e$B%5!<%P!<$,\e(B overview \e$B$K$=$l$i$N>pJs$r5-O?$7$F$$$k\e(B) \e$B$K\e(B
+\e$B%9%3%"$rIU$1$^$9!#\e(B
+
+@item f
+\e$B%U%)%m!<%"%C%W\e(B (followup) \e$B$K%9%3%"$rIU$1$^$9\e(B---\e$B$3$l$OCx<TL>$H$N9gCW$r$7!"\e(B
+\e$B$3$NCx<T$X$N%U%)%m!<%"%C%W$K%9%3%"$r2C$($^$9!#\e(B(\e$B$3$N%-!<$r;H$&$3$H$K$h$C\e(B
+\e$B$F\e(B @file{ADAPT} \e$B%U%!%$%k$,@8@.$5$l$^$9!#\e(B)
+
+@item b
+\e$BK\BN\e(B (body) \e$B$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item h
+\e$B%X%C%@!<\e(B (head) \e$B$K%9%3%"$rIU$1$^$9!#\e(B
+
+@item t
+\e$B%9%l%C%I$K%9%3%"$rIU$1$^$9!#\e(B(\e$B$3$N%-!<$r;H$&$3$H$K$h$C$F\e(B @file{ADAPT} \e$B%U%!\e(B
+\e$B%$%k$,@8@.$5$l$^$9!#\e(B)
+@end table
+
+@item
+\e$B;0HVL\$N%-!<$O9gCW$9$k7?$G$9!#$I$N9gCW$N7?$,M-8z$+$O$I$N%X%C%@!<$K%9%3%"\e(B
+\e$B$rIU$1$h$&$H$7$F$$$k$+$K0M$j$^$9!#\e(B
+
+@table @code
+@item \e$BJ8;zNs\e(B (strings)
+
+@table @kbd
+@item e
+\e$B@53N$J\e(B (exact) \e$B9gCW$G$9!#\e(B
+
+@item s
+\e$BJ8;zNs$N0lIt$N\e(B (substring) \e$B9gCW$G$9!#\e(B
+
+@item f
+\e$B$"$$$^$$$J\e(B (fuzzy) \e$B9gCW$G$9\e(B (@pxref{Fuzzy Matching})\e$B!#\e(B
+
+@item r
+\e$B@55,I=8=\e(B (regexp) \e$B$N9gCW$G$9!#\e(B
+@end table
+
+@item \e$BF|IU\e(B (date)
+
+@table @kbd
+@item b
+\e$BF|IU$NA0\e(B (before) \e$B$G$9!#\e(B
+
+@item a
+\e$BF|IU$N8e\e(B (after) \e$B$G$9!#\e(B
+
+@item n
+\e$B$=$NF|IU$G$9!#\e(B
+@end table
+
+@item \e$B?t;z\e(B (number)
+
+@table @kbd
+@item <
+\e$B?t;z$h$j>.$5$$$b$N$G$9!#\e(B
+
+@item =
+\e$B?t;z$HEy$7$$$b$N$G$9!#\e(B
+
+@item >
+\e$B?t;z$h$jBg$-$$$b$N$G$9!#\e(B
+@end table
+@end table
+
+@item
+\e$B;M$D$a$GDL>o$O:G8e$N%-!<$G$9!#$3$l$,0l;~E*\e(B (\e$B$9$J$o$A4|8B@Z$l>C5n\e(B) \e$B$N%9%3\e(B
+\e$B%"EPO?$+!"1JB3E*$J\e(B (\e$B$9$J$o$A4|8B@Z$l>C5n$G$J$$\e(B) \e$B%9%3%"EPO?$G$"$k$+$H$$$&\e(B
+\e$B$3$H!"$b$7$/$O$9$0$K$J$5$l$k$Y$-$+!"%9%3%"%U%!%$%k$KDI2C$9$k;v$O$7$J$$$+\e(B
+\e$B$H$$$&;v$r;XDj$7$^$9!#\e(B
+
+@table @kbd
+@item t
+\e$B0l;~E*$J\e(B (temporary) \e$B%9%3%"EPO?$G$9!#\e(B
+
+@item p
+\e$B1JB3E*$J\e(B (permanent) \e$B%9%3%"EPO?$G$9!#\e(B
+
+@item i
+\e$BB(:B$N\e(B (immediate) \e$B%9%3%"IU$1$G$9!#\e(B
+@end table
+
+@item
+\e$B$b$7\e(B `e' (\e$BDI2C$N\e(B (extra)) \e$B%X%C%@!<$G%9%3%"IU$1$r9T$J$C$F$$$k$H!"$I$NL>A0\e(B
+\e$B$N%X%C%@!<$G9T$J$&$+$r?R$M$i$l$^$9!#$3$l$O\e(B @code{gnus-extra-headers} \e$B$K\e(B
+\e$B$"$kL>A0$G$J$1$l$P$J$j$^$;$s!#\e(B@samp{TAB} \e$B$K$h$kJd40$,$G$-$^$9!#\e(B
+@end enumerate
+
+\e$B$G$9$+$i!"8=:_$NCx<T$K@53N$J9gCW$G1JB3E*$K%9%3%"$rA}$d$7$?$$$H$7$^$7$g\e(B
+\e$B$&\e(B:
+@kbd{I a e p}\e$B!#I=Bj$K4p$E$$$F%9%3%"$r2<$2$?$/$F!"J8;zNs$NItJ,$N9gCW$r;H\e(B
+\e$B$$!"0l;~E*$J%9%3%"EPO?$r$7$?$$$N$G$"$l$P\e(B: @kbd{L s s t}\e$B!#Hs>o$K4JC1$G$9!#\e(B
+
+\e$BJ*;v$rJ#;($K$9$k$N$O!"C;=LBG80$,B8:_$9$k$+$i$G$9!#FsHVL\$+;0HVL\$NJ8;z$K\e(B
+\e$BBgJ8;z$r;H$&$H!"\e(Bgnus \e$B$O;D$k0l$D$+Fs$D$NBG80$K=i4|CM$r;H$$$^$9!#=i4|CM\e(B
+\e$B$O\e(B ``\e$BJ8;zNs$N0lIt\e(B'' \e$B$H\e(B ``\e$B0l;~E*\e(B'' \e$B$G$9!#$G$9$+$i!"\e(B
+@kbd{I A} \e$B$O\e(B @kbd{I a s t} \e$B$HF1$8$G!"\e(B@kbd{I a R} \e$B$O\e(B @kbd{I a r t} \e$B$HF1$8\e(B
+\e$B$G$9!#\e(B
+
+\e$B$3$l$i$N4X?t$O?t;z@\F,0z?t$H!"%7%s%\%k@\F,0z?t$r<u$1IU$1$^\e(B
+\e$B$9\e(B (@pxref{Symbolic Prefixes})\e$B!#?t;z@\F,0z?t$O$I$N$/$i$$5-;v$N%9%3%"$r2<\e(B
+\e$B$2$k\e(B (\e$B$b$7$/$O>e$2$k\e(B) \e$B$+$r;XDj$7$^$9!#%7%s%\%k@\F,0z?t\e(B @code{a} \e$B$OL?Na$,\e(B
+\e$B8=:_$N%9%3%"%U%!%$%k$G$O$J$/%U%!%$%k\e(B @file{all.SCORE} \e$B$r;H$&;v$r;XDj$7$^\e(B
+\e$B$9!#\e(B
+
+@vindex gnus-score-mimic-keymap
+@code{gnus-score-mimic-keymap} \e$B$O$3$l$i$NL?Na$,%-!<%^%C%W$G$"$k$+$N$h$&\e(B
+\e$B$K?6$kIq$&$+$I$&$+$r;XDj$7$^$9!#\e(B
+
+@node Group Score Commands
+@section \e$B%0%k!<%W%9%3%"L?Na\e(B
+@cindex group score commands
+
+\e$B;DG0$J$,$i!"$^$@$?$/$5$s$O$"$j$^$;$s!#\e(B
+
+@table @kbd
+@item W f
+@kindex W f (\e$B%0%k!<%W\e(B)
+@findex gnus-score-flush-cache
+Gnus \e$B$O2?EY$b%9%3%"O"A[%j%9%H$rFI$_9~$`$N$rHr$1$k$?$a$K!"$=$l$N%-%c%C%7%e\e(B
+\e$B$rJ];}$7$F$$$^$9!#$3$NL?Na$O%-%c%C%7%e$r=q$-=P$7$^\e(B
+\e$B$9\e(B (@code{gnus-score-flush-cache})\e$B!#\e(B
+@end table
+
+\e$B0J2<$N$h$&$J;v$r$9$k;v$K$h$C$F!"%3%^%s%I9T$+$i%9%3%"IU$1$r$9$k;v$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+@findex gnus-batch-score
+@cindex batch scoring
+@example
+& emacs -batch -l ~/.emacs -l ~/.gnus.el -f gnus-batch-score
+@end example
+
+@node Score Variables
+@section \e$B%9%3%"JQ?t\e(B
+@cindex score variables
+
+@table @code
+@item gnus-use-scoring
+@vindex gnus-use-scoring
+@code{nil} \e$B$G$"$l$P!"\e(Bgnus \e$B$O%9%3%"%U%!%$%k$rD4$Y$:!"0lHLE*$K!"%9%3%"4XO"\e(B
+\e$B$N;E;v$rA4$/$7$^$;$s!#$3$l$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-kill-killed
+@vindex gnus-kill-killed
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$l$P!"\e(Bgnus \e$B$O4{$K:o=|2aDx$r<B9T$5$l$?5-;v$K7h\e(B
+\e$B$7$F%9%3%"%U%!%$%k$rE,MQ$7$^$;$s!#$3$l$O$?$/$5$s$N;~4V$r@aLs$9$k$G$7$g$&\e(B
+\e$B$,!"$b$7:o=|%U%!%$%k$r%0%k!<%W$KE,MQ$7$F$$$k$H$-$K!":o=|%U%!%$%k$rJQ99$7!"\e(B
+\e$B$b$C$HB?$/$N5-;v$r:o=|$9$k$?$a$K$=$l$r:F<B9T$7$F$b!"$=$l$OF0:n$7$J$$$H$$\e(B
+\e$B$&;v$K$J$j$^$9!#$=$l$r$9$k$?$a$K$O$3$NJQ?t$r\e(B @code{t} \e$B$K<B9T$7$J$1$l$P$J\e(B
+\e$B$j$^$;$s!#\e(B(\e$B$3$l$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B)
+
+@item gnus-kill-files-directory
+@vindex gnus-kill-files-directory
+\e$BA4$F$N:o=|$H%9%3%"$N%U%!%$%k$O$3$N%G%#%l%/%H%j!<$KC_@Q$5$l!"$=$l$O=i4|@_\e(B
+\e$BDj$G4D6-JQ?t\e(B @env{SAVEDIR} \e$B$K$h$C$F=i4|2=$5$l$^$9!#$3$l$O=i4|@_Dj\e(B
+\e$B$G\e(B @file{~/News/} \e$B$G$9!#\e(B
+
+@item gnus-score-file-suffix
+@vindex gnus-score-file-suffix
+\e$B%9%3%"%U%!%$%k$K$?$I$jCe$/$?$a$K%0%k!<%WL>$K2C$($k@\Hx8l$G$9\e(B (\e$B=i4|CM\e(B
+\e$B$G\e(B @file{SCORE} \e$B$G$9!#\e(B)
+
+@item gnus-score-uncacheable-files
+@vindex gnus-score-uncacheable-files
+@cindex score cache
+\e$BA4$F$N%9%3%"%U%!%$%k$OIaDL$O%9%3%"%U%!%$%k$N2a>jFI$_9~$_$rHr$1$k$?$a$K\e(B
+\e$B%-%c%C%7%e$5$l$^$9!#$7$+$7!"$3$l$K$h$j$"$J$?$N\e(B Emacs \e$B$,Bg$-$/HnBg2=$9$k\e(B
+\e$B$N$G$"$l$P!":F$SI,MW$H$5$l$J$$$h$&$J%9%3%"%U%!%$%k$r=|5n$9$k$?$a$K$3$N@5\e(B
+\e$B5,I=8=$r;H$&;v$,$G$-$^$9!#\e(B@file{all.SCORE} \e$B$N%-%c%C%7%e$r;_$a$k$N$O0-$$\e(B
+\e$B9M$($G$9$,!"\e(B@file{comp.infosystems.www.authoring.misc.ADAPT} \e$B$r%-%c%C%7%e\e(B
+\e$B$7$J$$$N$ONI$$9M$($G$7$g$&!#<B:]$N$H$3$m!"$3$NJQ?t$O=i4|@_Dj\e(B
+\e$B$G\e(B @samp{ADAPT$} \e$B$G!"E,1~%9%3%"%U%!%$%k$O%-%c%C%7%e$5$l$^$;$s!#\e(B
+
+@item gnus-save-score
+@vindex gnus-save-score
+\e$B$b$7K\Ev$KJ#;($J%9%3%"%U%!%$%k$r;}$C$F$$$F!"$?$/$5$s$N0l3g%9%3%"$r$9$k$N\e(B
+\e$B$G$"$l$P!"$3$NJQ?t$r\e(B @code{t} \e$B$K@_Dj$9$k$HNI$$$+$b$7$l$^$;$s!#$3$l\e(B
+\e$B$O\e(B gnus \e$B$K%9%3%"$r\e(B @file{.newsrc.eld} \e$B%U%!%$%k$KJ]B8$9$k$h$&$K$5$;$^$9!#\e(B
+
+\e$B$3$l$r\e(B @code{t} \e$B$K@_Dj$7$J$1$l$P!"<jF0%9%3\e(B
+\e$B%"\e(B (@kbd{V s} (@code{gnus-summary-set-score}) \e$B$G@_Dj$5$l$?$h$&$J$b$N\e(B) \e$B$O\e(B
+\e$B%0%k!<%W0\F0;~$KJ]B8$5$l$^$;$s!#\e(B
+
+@item gnus-score-interactive-default-score
+@vindex gnus-score-interactive-default-score
+\e$BA4$F$NBPOCE*%9%3%">e$2\e(B/\e$B2<$2L?Na$K$h$C$F;H$o$l$k>e$2\e(B/\e$B2<$2$9$k%9%3%"$G$9!#\e(B
+\e$B%G%#%U%)%k%H$O\e(B 1000 \e$B$G!"2a>j$@$H;W$&$+$b$7$l$^$;$s$,!"$3$l$OE,1~%9%3%"IU\e(B
+\e$B$1$r$9$kM>CO$NB8:_$9$k;v$r3N<B$K$9$k$?$a$G$9!#<j$GEPO?$5$l$?%G!<%?$rE,1~\e(B
+\e$B%9%3%"$G$N>.$5$JJQ99$G>e=q$-$5$l$?$/$O$"$j$^$;$s!#\e(B
+
+@item gnus-summary-default-score
+@vindex gnus-summary-default-score
+\e$B5-;v$N%9%3%"$N=i4|CM$G!"=i4|@_Dj$G$O\e(B 0 \e$B$K$J$C$F$$$^$9!#\e(B
+
+@item gnus-summary-expunge-below
+@vindex gnus-summary-expunge-below
+\e$B$3$NJQ?t$h$jDc$$%9%3%"$r;}$D5-;v$O35N,$N9T$KI=<($5$l$^$;$s!#$3$l$O=i4|@_\e(B
+\e$BDj$G\e(B @code{nil} \e$B$G!"$3$l$O$I$N5-;v$b1#$5$l$J$$$H$$$&;v$G$9!#$3$NJQ?t$O3F\e(B
+\e$B35N,%P%C%U%!$K8GM-$G!"\e(B@code{gnus-summary-mode-hook} \e$B$K$h$C$F@_Dj$5$l$k$Y\e(B
+\e$B$-$G$9!#\e(B
+
+@item gnus-score-over-mark
+@vindex gnus-score-over-mark
+\e$B=i4|@_Dj$N%9%3%"$h$jBg$-$J%9%3%"$r;}$D5-;v$KBP$7$F\e(B (\e$B;07eL\$K\e(B) \e$B;H$o$l$k0u\e(B
+\e$B$G$9!#=i4|@_Dj$O\e(B @samp{+} \e$B$G$9!#\e(B
+
+@item gnus-score-below-mark
+@vindex gnus-score-below-mark
+\e$B=i4|@_Dj$N%9%3%"$h$j>.$5$J%9%3%"$r;}$D5-;v$KBP$7$F\e(B (\e$B;07eL\$K\e(B) \e$B;H$o$l$k0u\e(B
+\e$B$G$9!#=i4|@_Dj$O\e(B @samp{-} \e$B$G$9!#\e(B
+
+@item gnus-score-find-score-files-function
+@vindex gnus-score-find-score-files-function
+\e$B8=:_$N%0%k!<%W$N%9%3%"%U%!%$%k$r8+$D$1$k$?$a$K;H$o$l$k4X?t$G$9!#$3$N4X?t\e(B
+\e$B$O%0%k!<%WL>$r0z?t$H$7$F8F$P$l$^$9!#\e(B
+
+\e$B;HMQ2DG=$J4{Dj4X?t$O\e(B:
+
+@table @code
+@item gnus-score-find-single
+@findex gnus-score-find-single
+\e$B%0%k!<%W<+?H$N%9%3%"%U%!%$%k$@$1$rE,MQ$7$^$9!#\e(B
+
+@item gnus-score-find-bnews
+@findex gnus-score-find-bnews
+bnews \e$B9=J8$r;H$C$F!"A4$F$N9gCW$9$k%9%3%"%U%!%$%k$rE,MQ$7$^$9!#$3$l$,=i4|\e(B
+\e$B@_Dj$G$9!#Nc$($P!"8=:_$N%0%k!<%W$,\e(B @samp{gnu.emacs.gnus} \e$B$J$i$P!"\e(B
+@file{gnu.all.SCORE}, @file{not.alt.SCORE} \e$B$H\e(B @file{gnu.all.SCORE} \e$B$,$9\e(B
+\e$B$Y$FE,MQ$5$l$^$9!#MW$9$k$K!"%9%3%"%U%!%$%kL>\e(B
+\e$B$N\e(B @samp{all} \e$B$,\e(B @samp{.*} \e$B$KJQ49$5$l!"$=$l$+$i@55,I=8=$N9gCW$,$J$5$l$^\e(B
+\e$B$9!#\e(B
+
+\e$B$3$l$O!"A4$F$N%0%k!<%W$KE,MQ$7$?$$%9%3%"EPO?$,$$$/$D$+$"$k>l9g$O!"$=$l$i\e(B
+\e$B$NEPO?$r\e(B @file{all.SCORE} \e$B%U%!%$%k$KF~$l$k$H$$$&$3$H$G$9!#\e(B
+
+Gnus \e$B$O0lHLE*$J%9%3%"%U%!%$%k$rFCDj$N%9%3%"%U%!%$%k8~$1$N$b$N$h$jA0$KE,\e(B
+\e$BMQ$7$h$&$H;n$_$^$9$,!"%9%3%"%U%!%$%k$O$[$H$s$IL5:n0Y$N=gHV$GE,MQ$5$l$^$9!#\e(B
+\e$B$3$l$O%9%3%"%U%!%$%kL>$NMWAG$N?t$rD4$Y$k;v$K$h$C$F$J$5$l$^$9\e(B---
+@samp{all} \e$BMWAG$r<h$j=|$$$F!#\e(B
+
+@item gnus-score-find-hierarchical
+@findex gnus-score-find-hierarchical
+\e$BA4$F$N?F%0%k!<%W$+$i$NA4$F$N%9%3%"%U%!%$%k$rE,MQ$7$^$9!#$3$l\e(B
+\e$B$O\e(B @file{all.SCORE} \e$B$N$h$&$J%9%3%"%U%!%$%k$r;}$D;v$O$G$-$J$$$1$l$I!"\e(B
+@file{SCORE}, @file{comp.SCORE} \e$B$H\e(B @file{comp.emacs.SCORE} \e$B$r!"$=$l$>$l\e(B
+\e$B$N%5!<%P!<$KBP$7$F;}$D;v$,$G$-$k$H$$$&;v$G$9!#\e(B
+@end table
+
+\e$B$3$NJQ?t$O4X?t$N%j%9%H$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"$3$l$i$NA4$F$N4X?t\e(B
+\e$B$,%0%k!<%WL>$r0z?t$H$7$F8F$P$l!"%9%3%"%U%!%$%k$NJV$5$l$?A4$F$N%j%9%H$,E,\e(B
+\e$BMQ$5$l$^$9!#$3$l$i$N4X?t$OD>@\%9%3%"O"A[%j%9%H$N%j%9%H$N%j%9%H$rJV$9;v$b\e(B
+\e$B$G$-$^$9!#$=$N>l9g$O!"$=$l$i$N%U%!%$%k$G$J$$%9%3%"O"A[%j%9%H$rJV$94X?t$O!"\e(B
+\e$BJV$5$l$k:G8e$N%9%3%"%U%!%$%k$,%m!<%+%k%9%3%"%U%!%$%k$G$"$k;v$r3N<B$K$9$k\e(B
+\e$B$?$a$K!"$*$=$i$/\e(B ``\e$BK\Ev$N\e(B'' \e$B%9%3%"%U%!%$%k4X?t$h$j$bA0$KCV$+$l$k$Y$-$G$7$g\e(B
+\e$B$&!#$U$%!#\e(B
+
+\e$BNc$($P!"%5!<%P!<$rFCDj$7$J$$A4BN%9%3%"%U%!%$%k$r;H$C$F!"?F%0%k!<%W$K=`$8\e(B
+\e$B$?%9%3%"IU$1$r9T$J$&$J$i$P!"<!$NCM$r;H$($PNI$$$G$7$g$&!#\e(B
+
+@example
+(list (lambda (group) ("all.SCORE"))
+      'gnus-score-find-hierarchical)
+@end example
+
+@item gnus-score-expiry-days
+@vindex gnus-score-expiry-days
+\e$B$3$NJQ?t$O;H$o$l$F$$$J$$%9%3%"%U%!%$%kEPO?$,4|8B@Z$l:o=|$5$l$k$^$G$I$N$/\e(B
+\e$B$i$$$NF|$,7P$D$Y$-$+$r;XDj$7$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"%9%3%"\e(B
+\e$B%U%!%$%kEPO?$O:o=|$5$l$^$;$s!#=i4|CM$O\e(B 7 \e$B$G$9!#\e(B
+
+@item gnus-update-score-entry-dates
+@vindex gnus-update-score-entry-dates
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"0l;~E*$K9gCW$7$?%9%3%"EPO?$OF|IU$,99?7$5\e(B
+\e$B$l$^$9!#\e(B(\e$B$3$l$O\e(B gnus \e$B$,4|8B@Z$l>C5n$rA`:n$7$F$$$kJ}K!$G$9\e(B---\e$BA4$F$N9gCW$7\e(B
+\e$B$J$$EPO?$O8E$/$J$j$9$.!"9gCW$9$kEPO?$r?7A/$G<c$$$^$^$G$9!#\e(B) \e$B$7$+$7!"$3$N\e(B
+\e$BJQ?t$r\e(B @code{nil} \e$B$K@_Dj$9$k$H!"9gCW$9$kEPO?$G$5$($b8E$/$J$j!"$"$N7y$J;`\e(B
+\e$B?@$HD>LL$9$k;v$K$J$k$G$7$g$&!#\e(B
+
+@item gnus-score-after-write-file-function
+@vindex gnus-score-after-write-file-function
+\e$B$=$3$G$A$g$&$I=q$+$l$?%9%3%"%U%!%$%k$NL>A0$H6&$K8F$P$l$k4X?t$G$9!#\e(B
+
+@item gnus-score-thread-simplify
+@vindex gnus-score-thread-simplify
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"5-;vI=Bj$O%9%l%C%I$HF1$8J}K!$GI=Bj%9%3%"\e(B
+\e$B$N$?$a$KC1=c2=$5$l$^$9\e(B---\e$B8=:_\e(B
+\e$B$N\e(B @code{gnus-simplify-subject-functions} \e$B$NCM$K$h$C$F!#%9%3%"EPO?\e(B
+\e$B$,\e(B @code{\e$BJ8;zNsItJ,\e(B} \e$B$+\e(B @code{\e$B@53N$J\e(B} \e$B9gCW$r;H$C$F$$$k$H!"9gCW$b$3$NJ}K!\e(B
+\e$B$GC1=c2=$5$l$^$9!#\e(B
+@end table
+
+@node Score File Format
+@section \e$B%9%3%"%U%!%$%kMM<0\e(B
+@cindex score file format
+
+\e$B%9%3%"%U%!%$%k$OIaDL$OC1=c$JMM<0$N$b$N$@$1$r4^$`\e(B @code{emacs-lisp} \e$B%U%!\e(B
+\e$B%$%k$G$9!#L5F\Ce$JMxMQ<T$O$3$l$rJT=8$7$J$$$G$/$@$5$$!#A4$F$O35N,%P%C%U%!\e(B
+\e$B$+$iJQ99$5$l$k$G$7$g$&!#\e(B
+
+\e$B$H$K$+$/!"$=$l$r<+J,$G$$$8$C$F$_$?$/$J$C$?$N$J$i!"Nc$,$"$j$^$9\e(B:
+
+@lisp
+(("from"
+  ("Lars Ingebrigtsen" -10000)
+  ("Per Abrahamsen")
+  ("larsi\\|lmi" -50000 nil R))
+ ("subject"
+  ("Ding is Badd" nil 728373))
+ ("xref"
+  ("alt.politics" -1000 728372 s))
+ ("lines"
+  (2 -100 nil <))
+ (mark 0)
+ (expunge -1000)
+ (mark-and-expunge -10)
+ (read-only nil)
+ (orphan -10)
+ (adapt t)
+ (files "/hom/larsi/News/gnu.SCORE")
+ (exclude-files "all.SCORE")
+ (local (gnus-newsgroup-auto-expire t)
+        (gnus-summary-make-false-root empty))
+ (eval (ding)))
+@end lisp
+
+\e$B$3$NNc$O$?$$$F$$$N%9%3%"%U%!%$%k$NMWAG$r@bL@$7$F$$$^$9!#0c$C$?J}K!$K$D$$\e(B
+\e$B$F$O!"\e(B@ref{Advanced Scoring} \e$B$r8+$F$/$@$5$$!#\e(B
+
+\e$B$3$l$O\e(B Lisp \e$B%3!<%I$N$h$&$K8+$($^$9$,!"<B:]$O$3$3$K$"$k$b$N$O2?\e(B
+\e$B$b\e(B @code{\e$BI>2A\e(B} (eval) \e$B$5$l$^$;$s!#$7$+$7!"\e(BLisp \e$B%j!<%@!<$,$3$NMM<0$rFI$_\e(B
+\e$B9~$`$N$K;H$o$l$^$9$N$G!"0UL#E*$KM-8z$G$J$$$H$7$F$b!"J8K!E*$K$OM-8z$G$9!#\e(B
+
+\e$B$3$NO"A[%j%9%H$G$OO;$D$N%-!<$r;H$&;v$,$G$-$^$9!#\e(B
+
+@table @code
+@item \e$BJ8;zNs\e(B (STRING)
+\e$B$b$7%-!<$,J8;zNs$G$"$k$H!"$=$l$O9gCW$,<B9T$5$l$k%X%C%@!<$NL>A0$G$9!#%9%3\e(B
+\e$B%"$O$3$l$i$NH,$D$N%X%C%@!<$@$1$K<B9T$5$l$^$9\e(B: @code{From},
+@code{Subject}, @code{References}, @code{Message-ID}, @code{Xref},
+@code{Lines}, @code{Chars}@code{Date} \e$B$G$9!#$3$l$i$N%X%C%@!<$K2C$($F!"\e(B
+gnus \e$B$K5-;vA4BN$r<hF@$7$F\e(B,\e$B5-;v$N$h$jBg$-$JItJ,$G9gCW$r9T$&$h$&$K$9$k;0$D\e(B
+\e$B$NJ8;zNs$,$"$j$^$9\e(B: @code{Body} \e$B$O5-;v$NK\BN\e(B (Body) \e$B$G9gCW$r<B9T$7!"\e(B
+@code{Head} \e$B$O5-;v$N%X%C%@!<\e(B (Head) \e$B$G9gCW$r<B9T$7!"\e(B@code{All} \e$B$O5-;vA4\e(B
+\e$BBN$G9gCW$r<B9T$7$^$9!#:G8e$N$3$l$i$N;0$D$N%-!<$r;H$&;v$O%0%k!<%W$KF~$k$H\e(B
+\e$B$-$KB.EY$r\e(B @emph{\e$B$+$J$j\e(B} \e$BCY$/$9$k;v$K5$$rIU$1$F$/$@$5$$!#%9%3%"$rIU$1$k\e(B
+\e$B;v$N$G$-$k:G8e$N\e(B ``\e$B%X%C%@!<\e(B'' \e$B$O\e(B @code{Followup} \e$B$G$9!#$3$l$i$N%9%3%"EP\e(B
+\e$BO?$O$=$l$K9gCW$9$k5-;v$X$NA4$F$N%U%)%m!<%"%C%W$N$?$a$N?7$7$$%9%3%"EPO?$,\e(B
+\e$BIU$12C$($i$l$k\e(B
+
+\e$B$3$N%-!<$KB3$/$N$OG$0U$N?t$N%9%3%"EPO?$G!"$=$l$>$l$N%9%3%"EPO?$O0l$D$+$i\e(B
+\e$B;M$D$^$G$NMWAG$r;}$A$^$9!#\e(B
+@enumerate
+
+@item
+\e$B:G=i$NMWAG$O\e(B @dfn{\e$B9gCWMWAG\e(B} \e$B$G$9!#$?$$$F$$$N%X%C%@!<$G$O$3$l$OJ8;zNs$G$9\e(B
+\e$B$,!"\e(BLines \e$B$H\e(B Chars \e$B%X%C%@!<$G$O$3$l$O@0?t$G$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item
+\e$B$b$7FsHVL\$NMWAG$,B8:_$9$k$J$i!"$=$l$O?t;z$G$"$k$Y$-$G\e(B
+\e$B$9\e(B---@dfn{\e$B%9%3%"MWAG\e(B}\e$B!#$3$N?t;z$OIi$NL58BBg$+$i@5$NL58BBg$^$G$N4V$N@0?t\e(B
+\e$B$G$"$k$Y$-$G$9!#$b$79gCW$,@.8y$9$l$P!"$3$N?t;z$,5-;v$N%9%3%"$K2C$($i$l$^\e(B
+\e$B$9!#$b$7$3$NMWAG$,B8:_$7$F$$$J$1$l$P!"?t\e(B
+\e$B;z\e(B @code{gnus-score-interactive-default-score}\e$B$,Be$o$j$K;H$o$l$^$9!#$3$l\e(B
+\e$B$O=i4|@_Dj$G\e(B 1000 \e$B$G$9!#\e(B
+
+@item
+\e$B$b$7;0HVL\$NMWAG$,B8:_$7$F$$$k$H!"$=$l$O?t;z$G$"$k$Y$-$G\e(B
+\e$B$9\e(B---@dfn{\e$BF|IUMWAG\e(B} \e$B$G$9!#$3$NF|IU$O:G8e$K$3$N%9%3%"EPO?$,9gCW$7$?;~9o$r\e(B
+\e$B<($7!"$3$l$O%9%3%"EPO?$N4|8B@Z$l>C5n5!9=$N5!G=$N$?$a$K;H$o$l$^$9!#$3$NMW\e(B
+\e$BAG$,B8:_$7$F$$$J$1$l$P!"%9%3%"EPO?$O1JB3$7$^$9!#F|IU$O5*85A0\e(B 1\e$BG/\e(B12\e$B7n\e(B31\e$BF|\e(B
+\e$B$+$i7P2a$7$?F|$K$A$N?t$GI=$5$l$^$9!#\e(B
+
+@item
+\e$B$b$7;MHVL\$NMWAG$,B8:_$7$F$$$k$H!"$=$l$O%7%s%\%k$G$"$k$Y$-$G\e(B
+\e$B$9\e(B---@dfn{\e$B7?MWAG\e(B} \e$B$G$9!#$3$NMWAG$O$3$N%9%3%"EPO?$,5-;v$K9gCW$9$k$+$I$&$+\e(B
+\e$B$rD4$Y$k$N$K$I$N4X?t$,;H$o$l$k$Y$-$G$"$k$+$r;XDj$7$^$9!#\e(B
+
+@table @dfn
+@item From, Subject, References, Xref, Message-ID
+\e$B$?$$$F$$$N%X%C%@!<$N7?$KBP$7$F!"\e(B@code{r} \e$B$H\e(B @code{R} (\e$B@55,I=\e(B
+\e$B8=\e(B) (regexp) \e$B$d!"\e(B@code{s} \e$B$H\e(B @code{S} (\e$BJ8;zNs$N0lIt\e(B) (substring) \e$B7?!"\e(B
+@code{e} \e$B$H\e(B @code{E} (\e$B@53N$J9gCW\e(B) (exact match)\e$B!"\e(B
+@code{w} (\e$B8l$N9gCW\e(B) (word match) \e$B7?$,B8:_$7$^$9!#$b$7$3$NMWAG$,B8:_$7$J\e(B
+\e$B$$$H!"\e(Bgnus \e$B$OJ8;zNs$N0lIt$N9gCW$,MQ$$$i$l$k$Y$-$G$"$k$H$_$J$7$^$9!#\e(B
+@code{R}, @code{S}, @code{E} \e$B$O9gCW$,BgJ8;z$H>.J8;z$r6hJL$9$kJ}K!$G9T$o\e(B
+\e$B$l$k$H$$$&E@$GB>$N$b$N$H0[$J$j$^$9!#A4$F$N$3$l$i$N0lJ8;z7?$OK\Ev\e(B
+\e$B$O\e(B @code{regexp}, @code{exact}, @code{word} \e$B7?$NC;=L7A$G!"$b$7$=$&$7$?$$\e(B
+\e$B$H;W$($P$3$A$i$rBe$o$j$K;H$&;v$,$G$-$^$9!#\e(B
+
+@item Extra
+\e$BI8=`$N\e(B overview \e$B%X%C%@!<$NJ8;zNs$HF1MM!"\e(B@code{gnus-extra-headers} \e$B$r;H$C\e(B
+\e$B$F$$$k$H!"$=$l$i$N%X%C%@!<$NCM$K%9%3%"$rIU$1$k$3$H$,$G$-$^$9!#$3$N>l9g%9\e(B
+\e$B%3%"EPO?$N\e(B 5 \e$BHVL\$NMWAG$,%9%3%"$rIU$1$k%X%C%@!<$NL>A0$K$J$j$^$9!#\e(B
+@acronym{NNTP} \e$B%5!<%P!<$,\e(B overview \e$B$K\e(B @samp{NNTP-Posting-Host} \e$B$r5-O?$7\e(B
+\e$B$F$$$k$J$i$P!"\e(B@file{all.SCORE} \e$B%U%!%$%k$N0J2<$NEPO?$O!"C10l$N%[%9%H$+\e(B
+\e$B$i\e(B spam \e$B$N967b$,$"$k>l9g$KM-8z$G$9!#\e(B
+
+@lisp
+("111.222.333.444" -1000 nil s
+ "NNTP-Posting-Host")
+@end lisp
+
+@item Lines, Chars
+\e$B$3$l$i$NFs$D$N%X%C%@!<$O0c$C$?9gCW$N7?$r;H$$$^$9\e(B: @code{<}, @code{>},
+@code{=}, @code{>=}, @code{<=} \e$B$G$9!#\e(B
+
+\e$B$3$l$i$N=R8l$O$b$7\e(B
+
+@example
+(PREDICATE HEADER MATCH)
+@end example
+
+\e$B$NI>2A$,\e(B @code{nil} \e$B$G$J$$$H!"??$H$J$j$^$9!#Nc$($P!">e5i9g\e(B
+\e$BCW\e(B @code{("lines" 4 <)} (@pxref{Advanced Scoring}) \e$B$O7k2L$H$7$F0J2<$N<0\e(B
+\e$B$K$J$j$^$9!#\e(B
+
+@lisp
+(< header-value 4)
+@end lisp
+
+\e$B$b$7$/$OB>$NJ}K!$K$7$^$7$g$&\e(B: @code{<} \e$B$r\e(B @code{Lines} \e$B$G\e(B 4 \e$B$r9gCW$H$7$F\e(B
+\e$B;H$C$F$$$k$H$-$O!"5-;v$,\e(B 4 \e$B9T$h$j$b>/$J$$$H$-$K%9%3%"$,DI2C$5$l$^$9!#\e(B(\e$B:.\e(B
+\e$BMp$7$F!"H?BP$G$O$J$$$+$H9M$(0W$$$G$9!#$G$b!"$=$&$G$O$J$$$N$G$9!#;d$,;W$&\e(B
+\e$B$K!#\e(B)
+
+\e$B9gCW$,\e(B @code{Lines} \e$B$G$J$5$l$F$$$k$H!"$$$/$D$+$N%P%C%/%(%s\e(B
+\e$B%I\e(B (@code{nndir}\e$B$N$h$&$J$b$N\e(B) \e$B$O\e(B @code{Lines} \e$B%X%C%@!<$r:n@.$7$J$$$?$a$K\e(B
+\e$BA4$F$N5-;v$,\e(B 0 \e$B9T$G$"$k$H$7$F07$o$l$k;v$K5$$rIU$1$F$/$@$5$$!#$3$l$O$b$7\e(B
+\e$B>/$7$N9T$7$+$J$$5-;v$N%9%3%"$r2<$2$F$$$k$N$J$i!"JQ$J7k2L$,5/$3$jF@$k;v$K\e(B
+\e$B$J$j$^$9!#\e(B
+
+@item Date
+Date (\e$BF|IU\e(B) \e$B%X%C%@!<$K$O;0$D$N$J$s$H$J$/$P$+$2$F$$$k9gCW$N7?$,$"$j$^$9\e(B:
+@code{before}, @code{at}, @code{after} \e$B$G$9!#;d$OK\Ev$K$3$l$,LrN)$D$h$&\e(B
+\e$B$J5!2q$rA[A|$G$-$J$$$N$G$9$,!"$3$N4X?t$rDs6!$7$J$$$N$b$J$s$H$J$/$P$+$2$F\e(B
+\e$B$$$^$9!#$=$&$7$?>l9g$N$?$a$K$"$k$N$G$9!#$$$DI,MW$K$J$k$+$OC/$K$b$o$+$j$^\e(B
+\e$B$;$s!#E>$P$L@h$N>s!#C;5$$OB;5$!#K\$r%+%P!<$GH=CG$7$F$O9T$1$^$;$s!#=i$a$F\e(B
+\e$B$N%G!<%H$G%(%C%A$7$F$O$$$1$^$;$s!#\e(B(\e$B$7$+$7!";d$O>/$J$/$H$b0l?M!"0zMQ$7$^\e(B
+\e$B$9$,!"\e(B``\e$B$3$N4X?t$O7g$+$;$J$$$b$N$G$"$k;v$,$o$+$C$?\e(B'' \e$B$H8@$C$??M$,$$$k$H\e(B
+\e$BJ9$$$F$$$^$9!#\e(B)
+
+(\e$BLuCm\e(B: \e$B86E5$N\e(B "Once burnt, twice shy" \e$B$r\e(B "\e$BC;5$$OB;5$\e(B" \e$B$H$7$^$7$?$,!"$b$C\e(B
+\e$B$HE,@Z$JLu$,$"$l$P$*CN$i$;2<$5$$!#\e(B)
+
+@cindex ISO8601
+@cindex date
+\e$B$b$C$HLrN)$D9gCW$N7?$O\e(B @code{\e$B@55,I=8=\e(B} \e$B$G$9!#$=$l$K$h$C$FF|IUJ8;zNs$K@5\e(B
+\e$B5,I=8=$rMQ$$$F9gCW$5$;$k;v$,$G$-$^$9!#F|IU$O$^$:\e(B ISO8601 \e$BC;=LMM\e(B
+\e$B<0\e(B (compact format) \e$B$KI8=`2=$5$l$^\e(B
+\e$B$9\e(B---@var{YYYYMMDD}@code{T}@var{HHMMSS} \e$B$G$9!#Nc$($P!"$b$7A4$F$NG/\e(B
+\e$B$N\e(B 4\e$B7n\e(B1\e$BF|\e(B \e$B$KEj9F$5$l$?A4$F$N5-;v$K$,<#$5$;$?$$$N$G$"$l$P!"\e(B
+@samp{....0401.........} \e$B$r9gCWJ8;zNs$H$7$F;H$&;v$,$G$-$^$9!#\e(B(\e$BF|IU$O85!9\e(B
+\e$B$NI8=`;~$GJ]B8$5$l$F$$$^$9$N$G!"$=$N5-;v$,Ej9F$5$l$?$H$3$m$G\e(B 4\e$B7n\e(B1\e$BF|\e(B \e$B$KEj\e(B
+\e$B9F$5$l$?5-;v$K9gCW$9$k;v$KCm0U$7$F$/$@$5$$!#I8=`;~$O0l2H$K$H$C$FHs>o$KM-\e(B
+\e$B1W$J3Z$7$_$G$7$g$&\e(B?)
+
+@item Head, Body, All
+\e$B$3$l$i$N;0$D$N9gCW$N%-!<$O\e(B @code{From} \e$B%X%C%@!<\e(B (\e$B$J$I\e(B) \e$B$HF1$89gCW$N7?$r\e(B
+\e$B;H$$$^$9!#\e(B
+
+@item Followup
+\e$B$3$N9gCW$N%-!<$O>/$7FCJL$G!"$=$l$O\e(B @code{From} \e$B%X%C%@!<$K9gCW$7!"9gCW$7\e(B
+\e$B$?5-;v$@$1$G$J$/$=$N5-;v$X$NA4$F$N%U%)%m!<%"%C%W$N%9%3%"$K$b1F6A$7$^$9!#\e(B
+\e$B$3$l$O$?$H$($P!"$"$J$?<+?H$N5-;v$X$N%U%)%m!<%"%C%W$N%9%3%"$rA}$d$7$?$j!"\e(B
+\e$BNI$/CN$i$l$?LdBj;y$X$N%U%)%m!<%"%C%W5-;v$N%9%3%"$r2<$2$?$j$9$k$N$K;H$o$l\e(B
+\e$B$^$9!#\e(B@code{From} \e$B%X%C%@!<$,;H$&$N$HF1$87?$N9gCW$r;H$$$^$9!#\e(B(\e$B$3$N9gCW%-!<\e(B
+\e$B$r;H$&$H!"%U%!%$%k\e(B @file{ADAPT} \e$B$r:n$k;v$K$J$j$^$9!#\e(B)
+
+@item Thread
+\e$B$3$N9gCW%-!<$O\e(B @code{Followup} \e$B9gCW%-!<$HF1$89T$KF0:n$7$^$9!#\e(B
+@code{Message-ID} @var{x} \e$B$G;O$^$C$F$$$k\e(B (\e$BI{\e(B)\e$B%9%l%C%I$K%9%3%"$rIU$1$?$$\e(B
+\e$B$N$G$"$l$P!"\e(B@samp{thread} \e$B9gCW$rIU$12C$($^$9!#$3$l$O\e(B @code{Reference} \e$B%X%C\e(B
+\e$B%@!<$K\e(B @var{x} \e$B$r;}$D$=$l$>$l$N5-;v$K?7$7$$\e(B @samp{thread} \e$B9gCW$rDI2C$7$^\e(B
+\e$B$9!#\e(B(\e$B$3$l$i$N?7$7$$\e(B @samp{thread} \e$B9gCW$O$3$l$i$N9gCW$9$k5-;v\e(B
+\e$B$N\e(B @code{Message-ID} \e$B$r;H$$$^$9!#\e(B) \e$B$3$l$O%9%l%C%I$N$$$/$D$+$N5-;v$,40A4\e(B
+\e$B$J\e(B @code{References} \e$B%X%C%@!<$r;}$C$F$$$J$+$C$?$H$7$F$b!"%9%l%C%IA4BN$N\e(B
+\e$B%9%3%"$r>e$2\e(B/\e$B2<$2$G$-$k;v$rJ]>Z$7$^$9!#$3$l$r;H$&$H!"%9%l%C%I$N5-;v$K7h\e(B
+\e$BDjE*$G$J$$%9%3%"$,IU$/$+$b$7$l$J$$$H$$$&$3$H$KCm0U$7$F$/$@$5$$!#\e(B(\e$B$3$N9g\e(B
+\e$BCW%-!<$r;H$&$H!"%U%!%$%k\e(B @file{ADAPT} \e$B$r:n$k;v$K$J$j$^$9!#\e(B)
+@end table
+@end enumerate
+
+@cindex score file atoms
+@item mark
+\e$B$3$NEPO?$NCM$O?t;z$G$"$k$Y$-$G$9!#$3$N?t;z$h$jDc$$%9%3%"$N5-;v$K$O4{FI$N\e(B
+\e$B0u$,IU$-$^$9!#\e(B
+
+@item expunge
+\e$B$3$NEPO?$NCM$O?t;z$G$"$k$Y$-$G$9!#$3$N?t;z$h$jDc$$%9%3%"$N5-;v$O35N,%P%C\e(B
+\e$B%U%!$+$i:o=|$5$l$^$9!#\e(B
+
+@item mark-and-expunge
+\e$B$3$NEPO?$NCM$O?t;z$G$"$k$Y$-$G$9!#$3$N?t;z$h$jDc$$%9%3%"$N5-;v$K$O4{FI$N\e(B
+\e$B0u$,IU$-!"35N,%P%C%U%!$+$i:o=|$5$l$^$9!#\e(B
+
+@item thread-mark-and-expunge
+\e$B$3$NEPO?$NCM$O?t;z$G$"$k$Y$-$G$9!#%9%3%"$NAm7W$,$3$N?t;z$h$jDc$$%9%l%C%I\e(B
+\e$B$K$O4{FI$N0u$,IU$-!"35N,%P%C%U%!$+$i:o=|$5$l$^$9!#\e(B
+@code{gnus-thread-score-function} \e$B$O%9%l%C%I$N%9%3%"$NAm7W$r$I$N$h$&$K7W\e(B
+\e$B;;$9$k$+$r;XDj$7$^$9!#\e(B
+
+@item files
+\e$B$3$NEPO?$NCM$OG$0U$N?t$N%U%!%$%kL>$G$"$k$Y$-$G$9!#$3$l$i$N%U%!%$%k$b%9%3\e(B
+\e$B%"%U%!%$%k$G$"$k$H$_$J$5$l!"$3$l$,$5$l$?$N$HF1$8$h$&$JJ}K!$GFI$_9~$^$l$^\e(B
+\e$B$9!#\e(B
+
+@item exclude-files
+\e$B$3$NEPO?$N<j$,$+$j$OG$0U$N?t$N%U%!%$%kL>$G$"$k$Y$-$G$9!#$3$l$i$N%U%!%$%k\e(B
+\e$B$O2?$i$+$NM}M3$GIaDL$OFI$_9~$^$l$k$h$&$K$J$C$F$$$?$H$7$F$b!"FI$_9~$^$l$^\e(B
+\e$B$;$s!#\e(B
+
+@item eval
+\e$B$3$NEPO?$NCM$O\e(B @code{\e$BI>2A\e(B} \e$B$5$l$^$9!#$3$NMWAG$OA4BNE*%9%3%"%U%!%$%k$r07$C\e(B
+\e$B$F$$$k$H$-$OL5;k$5$l$^$9!#\e(B
+
+@item read-only
+\e$BFI$_9~$_@lMQ%9%3%"%U%!%$%k$O99?7$5$l$?$jJ]B8$5$l$?$j$7$^$;$s!#A4BNE*%9%3\e(B
+\e$B%"%U%!%$%k$O$3$N%"%H%`$r;HMQ$9$k$Y$-$G$9\e(B (@pxref{Global Score Files})\e$B!#\e(B
+(\e$BCm0U\e(B: @dfn{\e$BA4BNE*\e(B} \e$B$O$3$3$G$OK\Ev$K\e(B @dfn{\e$BA4BNE*\e(B} \e$B$H$$$&0UL#$G$9!#8D?ME*\e(B
+\e$B$JA4$F$N%0%k!<%W$KE,MQ$9$k%9%3%"%U%!%$%k$N;v$G$O$"$j$^$;$s!#\e(B)
+
+@item orphan
+\e$B$3$NEPO?$NCM$O?t;z$G$"$k$Y$-$G$9!#?F5-;v$r;}$?$J$$5-;v$O%9%3%"$K$3$N?t;z\e(B
+\e$B$,2C$($i$l$^$9!#\e(B@samp{comp.lang.c} \e$B$N$h$&$JNL$NB?$$%K%e!<%9%0%k!<%W$rDI\e(B
+\e$B$$$+$1$F$$$k$H$7$F$/$@$5$$!#$*$=$i$/Fs!";0$N%9%l%C%I$H?7$7$$%9%l%C%I$@$1\e(B
+\e$B$rDI$$$?$$$G$7$g$&!#\e(B
+
+\e$B0J2<$N;0$D$N%9%3%"%U%!%$%kEPO?$K$h$C$F$=$l$r$9$k;v$,$G$-$^$9\e(B:
+
+@example
+        (orphan -500)
+        (mark-and-expunge -100)
+@end example
+
+\e$B:G=i$K$3$N%0%k!<%W$KF~$C$?$H$-$O!"?7$7$$%9%l%C%I$@$1$r8+$^$9!#$=$l$+$i$*\e(B
+\e$B$b$7$m$$$H;W$C$?%9%l%C%I$N%9%3%"$r>e$2\e(B (@kbd{I T} \e$B$b$7$/$O\e(B @kbd{I S} \e$B$K\e(B
+\e$B$h$C$F\e(B)\e$B!";D$j$rL5;k\e(B (@kbd{C y}) \e$B$7$^$9!#<!$K%0%k!<%W$KF~$C$?$H$-$O!"$*$b\e(B
+\e$B$7$m$$%9%l%C%I$N?7$7$$5-;v$HA4$/?7$7$$%9%l%C%I$r8+$k;v$K$J$j$^$9!#\e(B
+
+\e$B$9$J$o$A\e(B---orphan (\e$B8I;y\e(B) \e$B%9%3%"%"%H%`$OIaDL$N%9%3%"K!B'$G$OH/8+$G$-$J$$\e(B
+\e$B6=L#?<$$%9%l%C%I$,>/$7B8:_$7$9$kNL$NB?$$%0%k!<%W$N$?$a$K$"$j$^$9!#\e(B
+
+@item adapt
+\e$B$3$NEPO?$OE,1~%9%3%"$r@)8f$7$^$9!#$b$7$3$l$,\e(B @code{t} \e$B$G$"$k$H!"=i4|@_Dj\e(B
+\e$B$NE,1~%9%3%"K!B'$,;H$o$l$^$9!#$b$7$3$l$,\e(B @code{ignore} \e$B$G$"$k$H!"$3$N%0\e(B
+\e$B%k!<%W$K$OE,1~%9%3%"$O<B9T$5$l$^$;$s!#$b$7%j%9%H$G$"$k$H!"$=$N%j%9%H$OE,\e(B
+\e$B1~%9%3%"K!B'$H$7$FMQ$$$i$l$^$9!#$b$7$=$l$,B8:_$7$J$$$+!"\e(B
+@code{t} \e$B$d\e(B @code{ignore} \e$B$G$J$$B>$N$b$N$G$"$l$P!"=i4|@_Dj$NE,1~%9%3%"K!\e(B
+\e$BB'$,;H$o$l$^$9!#$?$$$F$$$N%0%k!<%W$KE,1~%9%3%"$r;H$$$?$$$N$G$"$l$P!"\e(B
+@code{gnus-use-adaptive-scorint} \e$B$r\e(B @code{t} \e$B$K@_Dj$7!"\e(B@code{(adapt
+ignore)} \e$B$rE,1~%9%3%"$r$7$?$/$J$$%0%k!<%W$KA^F~$9$k$G$7$g$&!#>/$7$N%0%k!<\e(B
+\e$B%W$G$@$1E,1~%9%3%"$r9T$$$?$$$N$G$"$l$P!"\e(B
+@code{gnus-use-adaptive-scoring} \e$B$r\e(B @code{nil} \e$B$K@_Dj$7!"\e(B
+@code{(adaptive t)} \e$B$r$=$l$r9T$$$?$$%0%k!<%W$N%9%3%"%U%!%$%k$KA^F~$9$k$G\e(B
+\e$B$7$g$&!#\e(B
+
+@item adaptive-file
+\e$BA4$F$NE,1~%9%3%"EPO?$O$3$NEPO?$K$h$C$FL>$E$1$i$l$?%U%!%$%k$KF~$j$^$9!#$=\e(B
+\e$B$l$O%0%k!<%W$KF~$k$H$-$K$bE,MQ$5$l$^$9!#$3$N%"%H%`$OB?$/$N%0%k!<%W$KF1$8\e(B
+\e$BE,1~%9%3%"%U%!%$%k$rMQ$$$k;v$K$h$C$F!"J#?t$N%0%k!<%W$K0lEY$KE,1~%9%3%"$r\e(B
+\e$BIU$1$?$$$H$-$KJXMx$G$7$g$&!#\e(B
+
+@item local
+@cindex local variables
+\e$B$3$NEPO?$NCM$O\e(B @code{(@var{var} @var{value})} \e$BBP$N%j%9%H$G$"$k$Y$-$G$9!#\e(B
+\e$B$=$l$>$l$N\e(B @var{var} \e$B$O8=:_$N35N,%P%C%U%!$N%P%C%U%!8GM-$K$J$j!";XDj$5$l\e(B
+\e$B$?CM\e(B (value) \e$B$K@_Dj$5$l$^$9!#$3$l$OJXMx$J!"$b$7>/$7JQ$@$H$7$F$b!"%U%C%/\e(B
+\e$B$r$"$^$j9%$^$J$$$$$/$D$+$N%0%k!<%W$GJQ?t$r@_Dj$9$kJ}K!$G$9!#\e(B
+@var{value} \e$B$OI>2A$5$l$J$$;v$KCm0U$7$F$/$@$5$$!#\e(B
+@end table
+
+@node Score File Editing
+@section \e$B%9%3%"%U%!%$%kJT=8\e(B
+
+\e$BIaDL$OA4$F$N%9%3%"L?Na$r35N,%P%C%U%!$+$iH/9T$7$^$9$,!"<j$G$=$l$i$rJT=8$7\e(B
+\e$B$?$$5$$K6n$i$l$k$+$b$7$l$^$;$s$N$G!"$=$l$N$?$a$N%b!<%I$rDs6!$7$F$$$^$9!#\e(B
+
+\e$B$=$l$OC1=c$K>/$7%+%9%?%^%$%:$5$l$?\e(B @code{emacs-lisp} \e$B%b!<%I$G!"0J2<$NDI\e(B
+\e$B2C$NL?Na$,B8:_$7$^$9\e(B:
+
+@table @kbd
+@item C-c C-c
+@kindex C-c C-c (\e$B%9%3%"\e(B)
+@findex gnus-score-edit-done
+\e$B$"$J$?$,9T$C$?JQ99$rJ]B8$7$F35N,%P%C%U%!$KLa$j$^\e(B
+\e$B$9\e(B (@code{gnus-score-edit-done})\e$B!#\e(B
+
+@item C-c C-d
+@kindex C-c C-d (\e$B%9%3%"\e(B)
+@findex gnus-score-edit-insert-date
+\e$B8=:_$NF|IU$r?t;zMM<0$GA^F~$7$^$9\e(B (@code{gnus-score-edit-insert-date})\e$B!#\e(B
+\e$B$b$7$3$l$,$I$N$h$&$J$b$N$G$"$m$&$H9M$($F$$$k$N$G$"$l$P!"$3$l$OK\Ev$KF|$N\e(B
+\e$B?t;z$G$9!#\e(B
+
+@item C-c C-p
+@kindex C-c C-p (\e$B%9%3%"\e(B)
+@findex gnus-score-pretty-print
+\e$BE,1~%9%3%"%U%!%$%k$O@0$($i$l$F$$$J$$N.57$GJ]B8$5$l$^$9!#$b$7$3$l$i$N%U%!\e(B
+\e$B%$%k$NFb$N0l$D$rFI$_$?$$$H;W$C$F$$$k$N$G$"$l$P!"$^$:\e(B @dfn{\e$BAGE($JI=<(\e(B} \e$B$r\e(B
+\e$B$7$?$$$G$7$g$&!#$3$NL?Na\e(B (@code{gnus-score-pretty-print}) \e$B$,$"$J$?$N$?$a\e(B
+\e$B$K$=$l$r$7$^$9!#\e(B
+@end table
+
+\e$B$3$N%b!<%I$r;H$&$?$a$K$O\e(B @kbd{M-x gnus-score-mode} \e$B$HBG$C$F$/$@$5$$!#\e(B
+
+@vindex gnus-score-mode-hook
+@code{gnus-score-menu-hook} \e$B$,%9%3%"%b!<%I%P%C%U%!$G<B9T$5$l$^$9!#\e(B
+
+\e$B35N,%P%C%U%!$G$O!"\e(B@kbd{V f}\e$B!"\e(B@kbd{V e} \e$B$*$h$S\e(B @kbd{V t} \e$B$N$h$&$JL?Na$G%9\e(B
+\e$B%3%"%U%!%$%k$NJT=8$r;O$a$k;v$,$G$-$^$9!#\e(B
+
+@node Adaptive Scoring
+@section \e$BE,1~@-%9%3%"\e(B
+@cindex adaptive scoring
+
+\e$B$3$l$i$N%9%3%"IU$1$O$"$J$?$rM+]5$K$5$;$F$7$^$&$+$b$7$l$J$$$N$G!"\e(B
+gnus \e$B$K$O$3$l$i$rA4$F<+F0E*$K\e(B --- \e$B$^$k$GKbK!$G$b;H$C$?$h$&$K:n@.\e(B
+\e$B$9$kJ}K!$,$"$j$^$9!#$$$d$`$7$m!"?M9)L5G=$K$h$C$F!"$H$$$&J}$,@53N\e(B
+\e$B$+$J!#\e(B
+
+@vindex gnus-use-adaptive-scoring
+\e$B5-;v$rFI$s$@$H$-!"$"$k$$$O5-;v$K4{FI$N0u$r$D$1$?$H$-!"5-;v$r:o=|$7$?$H$-\e(B
+\e$B$K!"$=$N0u$r;D$7$F$*$$$F$/$@$5$$!#%0%k!<%W$+$i=P$k$H$-$K\e(B gnus \e$B$O!"$=$l$i\e(B
+\e$B$N0u$NJU$j$rSL$.2s$j!"2?$N0u$r8+$D$1$?$+$K0MB8$7$F%9%3%"MWAG$rDI2C$7$^$9!#\e(B
+\e$B$3$N5!G=\e(B
+\e$B$O\e(B @code{gnus-use-adaptive-scoring} \e$B$r\e(B @code{t} \e$B$+\e(B @code{(line)} \e$B$K@_Dj\e(B
+\e$B$9$k$3$H$GM-8z$K$J$j$^$9!#$b$7%9%3%"$r!"I=Bj$K8=$l$k8DJL$NC18l$r$b$H$KE,\e(B
+\e$B1~$5$;$?$1$l$P!"$3$NJQ?t$r\e(B @code{(word)} \e$B$K@_Dj$7$F$/$@$5$$!#N>J}$NE,1~\e(B
+\e$BJ}K!$r;H$$$?$1$l$P!"$3$NJQ?t$r\e(B@code{(wordline)} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+
+@vindex gnus-default-adaptive-score-alist
+@code{gnus-default-adaptive-score-alist} \e$BJQ?t$r%+%9%?%^%$%:$9$k$3$H$G!"\e(B
+\e$B%9%3%"IU$1$N=hM}$r40A4$K@)8f$G$-$^$9!#Nc$($P!"$3$N$h$&$J46$8$K$J$j$^$9!#\e(B
+
+@lisp
+(setq gnus-default-adaptive-score-alist
+      '((gnus-unread-mark)
+        (gnus-ticked-mark (from 4))
+        (gnus-dormant-mark (from 5))
+        (gnus-del-mark (from -4) (subject -1))
+        (gnus-read-mark (from 4) (subject 2))
+        (gnus-expirable-mark (from -1) (subject -1))
+        (gnus-killed-mark (from -1) (subject -3))
+        (gnus-kill-file-mark)
+        (gnus-ancient-mark)
+        (gnus-low-score-mark)
+        (gnus-catchup-mark (from -1) (subject -1))))
+@end lisp
+
+\e$B8+$F$*J,$+$j$N$h$&$K!"$3$NO"A[%j%9%H$N3FMWAG$O!"%-!<$H$7$F0u\e(B (\e$BJQ?tL>$+$b\e(B
+\e$B$7$/$O\e(B ``\e$BK\Ev$N\e(B'' \e$B0u\e(B --- \e$B$D$^$jJ8;z\e(B)\e$B$r;}$A$^$9!#$3$N%-!<$N8e$K$OG$0U$N?t\e(B
+\e$B$N%X%C%@!<\e(B/\e$B%9%3%"$NAH$,B3$-$^$9!#$b$7$=$N%-!<$N8e$K%X%C%@!<\e(B/\e$B%9%3%"$NAH$,\e(B
+\e$B0l$D$b$J$1$l$P!"$=$N%-!<$,5-;v$N0u$H$7$F$D$$$F$$$k5-;v$KBP$7$F$OE,1~@-%9\e(B
+\e$B%3%"$O<B9T$5$l$^$;$s!#Nc$($P>e5-$NNc$G$O!"\e(B@code{gnus-unread-mark} \e$B$,$D$$\e(B
+\e$B$F$$$k5-;v$OE,1~@-%9%3%"$NEPO?9`L\$K$O$J$j$^$;$s!#\e(B
+
+\e$B3F5-;v$O$?$@0l$D$N0u$7$+;}$AF@$J$$$N$G!"$=$l$>$l$N5-;v$K$O$3$l$i$N5,B'$N\e(B
+\e$B$&$A$?$@0l$D$7$+E,MQ$5$l$^$;$s!#\e(B
+
+@code{gnus-del-mark} \e$B$rNc$K<h$j$^$7$g$&\e(B --- \e$B$3$NO"A[%j%9%H$G$N0UL#$O!"$3\e(B
+\e$B$N0u\e(B (\e$B$9$J$o$A\e(B @samp{e} \e$B$N0u\e(B)\e$B$,$D$$$F$$$k5-;v$OA4$F!"\e(B@code{From} \e$B%X%C%@!<\e(B
+\e$B$r$b$H$K\e(B -4 \e$B2<$2$i$l\e(B @code{Subject} \e$B$G\e(B -1 \e$B2<$2$i$l$k%9%3%"EPO?$,DI2C$5$l\e(B
+\e$B$^$9!#$3$l$r$"$J$?$NJP8+$K9g$o$;$FJQ99$7$F$/$@$5$$!#\e(B
+
+\e$B$b$7\e(B 10 \e$B8D$N5-;v$KF1$8\e(B subject \e$B$G\e(B @code{gnus-del-mark} \e$B$N0u$,$D$$$F$$$?\e(B
+\e$B$H$9$k$H!"$3$N0u$KBP$9$k5,B'$O==2sE,MQ$5$l$^$9!#$=$l$O$D$^$j!"$=\e(B
+\e$B$N\e(B subject \e$B$O\e(B -1 \e$B$N==G\$N%9%3%"$rF@$^$9!#$=$NCM$O!";d$,Bg$-$/8m2r$7$F$$\e(B
+\e$B$J$$$+$.$j!"\e(B-10 \e$B$N$O$:$G$9!#\e(B
+
+\e$B$b$7<+F04|8B@Z$l>C5n\e(B (\e$B%a!<%k\e(B) \e$B%0%k!<%W\e(B (@pxref{Expiring Mail})\e$B$,$"$l$P!"\e(B
+\e$B4{FI5-;v$K$OA4$F\e(B @samp{E} \e$B0u$,$D$1$i$l$^$9!#$3$l$O$*$=$i$/!"E,1~@-%9%3%"\e(B
+\e$BIU$1$r$A$g$C$H$P$+$jIT2DG=$K$9$k$N$G!"<+F04|8B@Z$l>C5n$HE,1~@-%9%3%"$O0l\e(B
+\e$B=o$K$O$&$^$/$d$C$F$$$1$^$;$s!#\e(B
+
+\e$B%9%3%"$r$D$1$i$l$k%X%C%@!<$K$O\e(B @code{from}, @code{subject},
+@code{message-id}, @code{references}, @code{xref}, @code{lines},
+@code{chars}, @code{date} \e$B$,$"$j$^$9!#$5$i$K\e(B @code{followup} \e$B$K$b%9%3%"\e(B
+\e$BIU$1$G$-$^$9!#$3$l$O8=:_$N5-;v$N\e(B @code{Message-ID} \e$B$r;HMQ$7\e(B
+\e$B$F\e(B @code{References} \e$B%X%C%@!<$K%^%C%A!"$9$J$o$A$3$l$KB3$$$?%9%l%C%I$K%^%C\e(B
+\e$B%A$9$kE,1~@-%9%3%"EPO?$r:n@.$7$^$9!#\e(B
+
+\e$B$3$N5!9=$r;H$&$J$i$P!"$H$-$I$-5-;v$r4{FI$K$7$F$7$^$&>.$5$JJQ99$rHr$1$k$?\e(B
+\e$B$a$K!"%9%3%"%U%!%$%k$N\e(B @code{mark} \e$B%"%H%`$r2?$+>.$5$$CM\e(B --- \e$B$3$H$K$h$l\e(B
+\e$B$P\e(B -300 \e$B$/$i$$$K@_Dj$7$F$*$$$?J}$,NI$$$G$9!#\e(B
+
+\e$BE,1~@-%9%3%"$r0l=54V$+$=$3$i;H$C$F$/$k$H!"\e(Bgnus \e$B$O$=$lAj1~$KD465$5$l!"$"\e(B
+\e$B$J$?$,2?$b8@$o$J$/$F$b!"$"$J$?$N9%$-$JEj9F<T$r6/D4$7!"$"$^$j9%$-$G$O$J$$\e(B
+\e$BEj9F<T$r>C5n$9$k$h$&$K$J$k$O$:$G$9!#\e(B
+
+\e$B$I$N%0%k!<%W$K$*$$$FE,1~@-%9%3%"$r:nF0$5$;$k$+$O!"%9%3%"%U%!%$\e(B
+\e$B%k\e(B (@pxref{Score File Format}) \e$B$r;H$&$3$H$K$h$C$F@)8f$G$-$^$9!#$^$?$3$l\e(B
+\e$B$r;H$C$F!"0c$C$?%0%k!<%W$KBP$7$F0c$C$?5,B'$r;H$&$h$&$K$b$G$-$^$9!#\e(B
+
+@vindex gnus-adaptive-file-suffix
+\e$BE,1~@-%9%3%"EPO?9`L\$O!"%0%k!<%WL>$K\e(B @code{gnus-adaptive-file-suffix} \e$B$r\e(B
+\e$BIU2C$7$?L>A0$N%U%!%$%k$KF~$l$i$l$^$9!#=i4|@_DjCM$O\e(B @file{ADAPT} \e$B$G$9!#\e(B
+
+@vindex gnus-score-exact-adapt-limit
+\e$BE,1~@-%9%3%"$r9T$&$H$-$O!"ItJ,J8;zNs0lCW$d%U%!%8!<$J0lCW$r9T$C$?J}$,!"$*\e(B
+\e$B$=$i$/$[$H$s$I$N>l9g$K$*$$$FNI$$7k2L$,F@$i$l$k$G$7$g$&!#$7$+$7!"%X%C%@!<\e(B
+\e$B$N0lCW$7$?ItJ,$,C;$$>l9g!"0U?^$KH?$9$k$h$&$JF0:n$r$9$k2DG=@-$,Bg$-$/$J$k\e(B
+\e$B$N$G!"\e(B@code{gnus-score-exact-adapt-limit} \e$B$h$jC;$$D9$5$7$+0lCW$7$J$$>l9g\e(B
+\e$B$O40A40lCW$,9T$o$l$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$l$P!"$3$NLdBj$,5/$3$i\e(B
+\e$B$J$$$h$&$K>o$K40A40lCW$,9T$o$l$^$9!#\e(B
+
+@vindex gnus-default-adaptive-word-score-alist
+\e$B>e$G=R$Y$?$h$&$K!"8DJL$NC18l$KBP$7$F$b%X%C%@!<A4BN$KBP$7$F$bE,1~$r9T$&$3\e(B
+\e$B$H$,$G$-$^$9!#C18l$KBP$7$FE,1~$r9T$C$?>l9g!"\e(B
+@code{gnus-default-adaptive-word-score-alist} \e$BJQ?t$K$h$C$F!"3FC18l$KBP$7\e(B
+\e$B$F$"$k0u$X$I$s$J%9%3%"$rM?$($k$+$r;XDj$7$^$9!#\e(B
+
+@lisp
+(setq gnus-default-adaptive-word-score-alist
+      `((,gnus-read-mark . 30)
+        (,gnus-catchup-mark . -10)
+        (,gnus-killed-mark . -20)
+        (,gnus-del-mark . -15)))
+@end lisp
+
+\e$B$3$l$,=i4|@_DjCM$G$9!#C18l$KBP$9$kE,1~$rM-8z$K$9$k$H!"\e(B
+@code{gnus-read-mark} \e$B$N0u$N$D$$$?5-;v$NI=Bj$K8=$l$kA4$F$NC18l$,!"%9%3%"\e(B
+\e$B$K\e(B 30 \e$BE@DI2C$9$k$H$$$&%9%3%"5,B'$r@8$_=P$7$^$9!#\e(B
+
+@vindex gnus-default-ignored-adaptive-words
+@vindex gnus-ignored-adaptive-words
+@code{gnus-default-ignored-adaptive-words} \e$B$N%j%9%H$K8=$l$kC18l$OL5;k$5\e(B
+\e$B$l$^$9!#L5;k$7$?$$C18l$rDI2C$7$?$$$H$-$O!"$3$NJQ?t$G$O$J\e(B
+\e$B$/\e(B @code{gnus-ignored-adaptive-words} \e$B%j%9%H$NJ}$r;H$C$F$/$@$5$$!#\e(B
+
+@vindex gnus-adaptive-word-length-limit
+\e$BC;$$C18l$G$OE,1~@-%9%3%"$r:nF0$5$;$k$Y$-$G$O$J$$$H;W$&?M$b$$$k$G$7$g$&!#\e(B
+\e$B$b$7$=$&$J$i\e(B @code{gnus-adaptive-word-length-limit} \e$B$K@0?t$r@_Dj$9$k$3$H\e(B
+\e$B$,$G$-!"$3$N?tCM$h$jC;$$C18l$OL5;k$5$l$^$9!#$3$NJQ?t$N=i4|@_DjCM\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@vindex gnus-adaptive-word-syntax-table
+\e$B%9%3%"IU$1$,=*N;$7$?$H$-!"\e(B@code{gnus-adaptive-word-syntax-table} \e$B$NJ8K!\e(B
+\e$BI=$,$=$N1F6A$r<u$1$^$9!#$3$l$OI8=`$NJ8K!I=$H;w$F$$$^$9$,!"C18l$N9=@.MWAG\e(B
+\e$B$H$J$i$J$$J8;z$N?t$b9MN8$7$^$9!#\e(B
+
+@vindex gnus-adaptive-word-minimum
+\e$B$b$7\e(B @code{gnus-adaptive-word-minimum} \e$B$K?t;z$,@_Dj$5$l$F$$$k$H!"C18lE,\e(B
+\e$B1~@-%9%3%"IU$1=hM}$K$*$$$F!"5-;v$N%9%3%"$,$3$N?t;z$h$j$b>.$5$/$J$k$3$H$O\e(B
+\e$B$"$j$^$;$s!#=i4|@_DjCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@vindex gnus-adaptive-word-no-group-words
+@code{gnus-acaptive-word-no-group-words} \e$B$,\e(B @code{t} \e$B$K@_Dj$5$l$F$$$k$H!"\e(B
+gnus \e$B$O%0%k!<%WL>$NA4$F$N8l$K$D$$$F!"C18lE,1~@-%9%3%"$r$7$^$;$s!#$[$H$s\e(B
+\e$B$I$NI=Bj$,\e(B @samp{emacs} \e$B$H$$$&8l$r4^$s$G$$$k\e(B @samp{comp.editor.emacs} \e$B$N\e(B
+\e$B$h$&$J%0%k!<%W$GJXMx$G$9!#\e(B
+
+\e$B$3$N5!9=$r$7$P$i$/;H$C$F$_$?8e$K$O!"$"$J$?$,$I$s$JC18l$,9%$-$G$I$s$JC18l\e(B
+\e$B$,7y$$$+$r!"$3$N5,B'$rDL$7$F?GCG$9$kMxMQ<T@:?@J,@OL?\e(B
+\e$BNa\e(B @code{gnus-psychoanalyze-user} \e$B$r=q$$$F$_$k$HNI$$$+$b$7$l$^$;$s!#$$$d!"\e(B
+\e$BNI$/$J$$$+$J!#\e(B
+
+\e$BC18lE,1~@-%9%3%"IU$1$OHs>o$K<B83E*$J$b$N$G$"$C$F!":#8eJQ99$5$l$k$G$"$m$&\e(B
+\e$B$H$$$&$3$H$O?4$KN1$a$F$*$$$F$/$@$5$$!#Bh0l0u>]$G$O!"$3$l$O8=>u$G$OA4$/;H\e(B
+\e$B$$J*$K$J$i$J$$$h$&$K;W$($^$9!#$3$l$r$b$C$H;H$($k$h$&$K$9$k$?$a$K$O!"\e(B(\e$B$h\e(B
+\e$B$j87L)$JE}7WE*<jK!$r4,$-E:$($K$7$F\e(B) \e$B$5$i$J$k:n6H$,I,MW$H$J$k$G$7$g$&!#\e(B
+
+@node Home Score File
+@section \e$B%[!<%`%9%3%"%U%!%$%k\e(B
+
+\e$B?7$7$$%9%3%"%U%!%$%kEPO?9`L\$,F~$l$i$l$k%9%3%"%U%!%$%k$O!"%[!<%`%9%3%"%U%!\e(B
+\e$B%$%k\e(B @dfn{home score file} \e$B$H8F$P$l$^$9!#$3$l$ODL>o\e(B (\e$B=i4|@_Dj$G\e(B) \e$B$=$N%0\e(B
+\e$B%k!<%WMQ$N%9%3%"%U%!%$%k$K$J$j$^$9!#Nc$($P!"\e(B@samp{gnu.emacs.gnus} \e$BMQ$N%[!<\e(B
+\e$B%`%9%3%"%U%!%$%k$O\e(B @file{gnu.emacs.gnus.SCORE} \e$B$H$J$k$o$1$G$9!#\e(B
+
+\e$B$7$+$7$J$,$i!"$3$l$O$"$J$?$N$*K>$_$G$O$J$$$+$b$7$l$^$;$s!#$?$/$5$s$N%0%k!<\e(B
+\e$B%W4V$G6&DL$N%[!<%`%9%3%"%U%!%$%k$r6&M-$9$k$HJXMx$J$H$-$,B?$$$G$7$g\e(B
+\e$B$&\e(B --- \e$BNc$($PA4$F$N\e(B @samp{emacs} \e$B%0%k!<%W$GF1$8%[!<%`%9%3%"%U%!%$%k$r;H\e(B
+\e$B$&$3$H$b$G$-$^$9!#\e(B
+
+@vindex gnus-home-score-file
+\e$B$3$l$r@)8f$9$kJQ?t$,\e(B @code{gnus-home-score-file} \e$B$G$9!#$3$l$O0J2<$NCM$r\e(B
+\e$B<h$jF@$^$9!#\e(B
+
+@enumerate
+@item
+\e$BJ8;zNs!#$3$N>l9g$3$N%U%!%$%k$,A4$F$N%0%k!<%W$G%[!<%`%9%3%"%U%!%$%k$H$7$F\e(B
+\e$B;HMQ$5$l$^$9!#\e(B
+
+@item
+\e$B4X?t!#$3$N4X?t$N7k2L$,%[!<%`%9%3%"%U%!%$%k$H$7$F;HMQ$5$l$^$9!#$3$N4X?t$O\e(B
+\e$B%0%k!<%W$NL>A0$r0z?t$H$7$F8F$S=P$5$l$^$9!#\e(B
+
+@item
+\e$B%j%9%H!#$3$N%j%9%H$NMWAG$O0J2<$NCM$r<h$jF@$^$9!#\e(B
+
+@enumerate
+@item
+@code{(@var{regexp} @var{file-name})}\e$B!#\e(B@var{regexp} \e$B$,%0%k!<%WL>$K%^%C%A\e(B
+\e$B$9$l$P!"\e(B@var{file-name} \e$B$,%[!<%`%9%3%"%U%!%$%k$H$7$F;HMQ$5$l$^$9!#\e(B
+
+@item
+\e$B4X?t!#$3$N4X?t$,\e(B @code{nil} \e$B0J30$rJV$;$P!"$=$NJV5QCM$,%[!<%`%9%3%"%U%!%$\e(B
+\e$B%k$H$7$F;HMQ$5$l$^$9!#\e(B
+
+@item
+\e$BJ8;zNs!#$3$NJ8;zNs$r%[!<%`%9%3%"%U%!%$%k$H$7$F;HMQ$7$^$9!#\e(B
+@end enumerate
+
+\e$B$3$N%j%9%H$NCf$+$i%^%C%A$9$k$b$N$r!":G=i$+$i8e$m$NJ}$K8~$+$C$FC5$7$F$$$-\e(B
+\e$B$^$9!#\e(B
+
+@end enumerate
+
+\e$B$H$$$&$o$1$G!"C1$K0l8D$N%9%3%"%U%!%$%k$r;H$$$?$$>l9g$O!"0J2<$N$h$&$K$9$l\e(B
+\e$B$P$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-home-score-file
+      "my-total-score-file.SCORE")
+@end lisp
+
+\e$B$b$7A4\e(B @samp{gnu} \e$B%0%k!<%W$KBP$7$F\e(B @file{gnu.SCORE} \e$B$r!"A4\e(B @samp{rec} \e$B%0\e(B
+\e$B%k!<%W$KBP$7$F\e(B @file{rec.SCORE} (\e$BEy!9\e(B) \e$B$r;H$$$?$1$l$P!"$3$N$h$&$K$G$-$^\e(B
+\e$B$9!#\e(B
+
+@findex gnus-hierarchial-home-score-file
+@lisp
+(setq gnus-home-score-file
+      'gnus-hierarchial-home-score-file)
+@end lisp
+
+\e$B$3$l$OJXMx$J$h$&$K$"$i$+$8$aDs6!$5$l$F$$$k4X?t$G$9!#B?$N4X?t$O0J2<$N0J2<\e(B
+\e$B$N$b$N$r4^$_$^$9!#\e(B
+
+@table @code
+@item gnus-current-home-scre-file
+@findex gnus-current-home-score-file
+``\e$B8=:_$N\e(B'' \e$BI8=`%9%3%"%U%!%$%k$rJV$7$^$9!#$3$l$O%9%3%"L?Na$K%9%3%"%U%!%$\e(B
+\e$B%k$N\e(B ``\e$B:GFbIt\e(B'' \e$B9gCW$X$NEPO?$r2C$($k$h$&$K$7$^$9!#\e(B
+@end table
+
+\e$B$b$7\e(B @samp{emacs} \e$B%0%k!<%WMQ$N%9%3%"%U%!%$%k$H!"$=$l$H$OJL\e(B
+\e$B$N\e(B @samp{comp} \e$B%0%k!<%WMQ$N%9%3%"%U%!%$%k$r;H$$!"B>$NA4It$N%0%k!<%W$G$O\e(B
+\e$B$=$l$>$lFH<+$N%9%3%"%U%!%$%k$r;H$$$?$$$N$G$"$l$P!"\e(B
+
+@lisp
+(setq gnus-home-score-file
+      ;; @r{\e$B@55,I=8=\e(B @code{"\\.emacs"} \e$B$K9gCW$9$k$9$Y$F$N%0%k!<%W\e(B}
+      '(("\\.emacs" "emacs.SCORE")
+        ;; @r{\e$B$9$Y$F$N\e(B comp \e$B%0%k!<%W$rC10l$N%9%3%"%U%!%$%k$G\e(B}
+        ("^comp" "comp.SCORE")))
+@end lisp
+
+@vindex gnus-home-adapt-file
+@code{gnus-home-adapt-file} \e$B$O\e(B @code{gnus-home-score-file} \e$B$HA4$/F1$8$h\e(B
+\e$B$&$KF0:n$7$^$9$,!"$3$l$OBe$o$j$K2?$r%[!<%`E,MQ%9%3%"%U%!%$%k$K$9$k$+$r;X\e(B
+\e$BDj$7$^$9!#?7$7$$E,MQ%U%!%$%kEPO?9`L\$OA4$F!"$3$NJQ?t$G;XDj$5$l$k%U%!%$%k\e(B
+\e$B$KF~$l$i$l$^$9!#CM$K$OF1$8J8K!$,5v$5$l$^$9!#\e(B
+
+@code{gnus-home-score-file} \e$B$H\e(B @code{gnus-home-adapt-file} \e$B$N;HMQ$K2C$(\e(B
+\e$B$F!"%0%k!<%W%Q%i%a!<%?\e(B (@pxref{Group Parameters}) \e$B$H%H%T%C%/%Q%i%a!<\e(B
+\e$B%?\e(B (@pxref{Topic Parameters}) \e$B$r;H$C$F$[$\F1MM$N$3$H$,$G$-$^$9!#%0%k!<%W!"\e(B
+\e$B%H%T%C%/%Q%i%a!<%?$O$3$NJQ?t$h$j$bM%@h$5$l$^$9!#\e(B
+
+@node Followups To Yourself
+@section \e$B<+J,<+?H$X$N%U%)%m!<%"%C%W\e(B
+
+Gnus \e$B$O8=:_$N%P%C%U%!!<$+$i\e(B @code{Message-ID} \e$B%X%C%@!<$r8+$D$1=P$9$?$a$K\e(B
+\e$BFs$D$NL?Na$rDs6!$7$F$$$^$9!#$=$7$F\e(B gnus \e$B$O!"B>$N5-;v$K$*$1\e(B
+\e$B$k\e(B @code{References} \e$B%X%C%@!<Cf$K$3$N\e(B @code{Message-ID} \e$B$r;H$C$F$$$kF@E@\e(B
+\e$B$r!"%9%3%"5,B'$H$7$FDI2C$7$^$9!#$3$l$O<B<AE*$K!"$=$N5-;v$XJVEz$7$?5-;v$G!"\e(B
+\e$B8=:_$N%P%C%U%!!<$K$"$k$b$NA4$F$KBP$7$F%9%3%"$rA}2C$5$;$^$9!#$3$l$O$"$J$?\e(B
+\e$B$N8@$C$?$3$H$KBP$7$F$_$s$J$,Ez$($F$/$l$?$H$-!"$9$0$K$=$l$KL\$r8~$1$?$$$H\e(B
+\e$B$-$K$H$F$bJXMx$G$9$M!#\e(B
+
+@table @code
+@item gnus-score-followup-article
+@findex gnus-score-followup-article
+\e$B$3$l$O$"$J$?<+?H$N5-;v$KD>@\%U%)%m!<%"%C%W$7$?5-;v$K%9%3%"$r2C;;$7$^$9!#\e(B
+
+@item gnus-score-followup-thread
+@findex gnus-score-followup-thread
+\e$B$3$l$O$"$J$?$N5-;v$h$j\e(B ``\e$B2<\e(B'' \e$B$N%9%l%C%I$K8=$l$k5-;vA4$F$KBP$7$F%9%3%"$r\e(B
+\e$B2C;;$7$^$9!#\e(B
+@end table
+
+@vindex message-sent-hook
+\e$B$3$l$iFs$D$N4X?t$O!"4pK\E*$K$O$I$A$i$b\e(B @code{message-sent-hook} \e$B$N$h$&$J\e(B
+\e$B%U%C%/$NCf$G;H$&$?$a$N$b$N$G$9!#Nc$($P$3$N$h$&$K\e(B:
+@lisp
+(add-hook 'message-sent-hook 'gnus-score-followup-thread)
+@end lisp
+
+\e$B$"$J$?$N<+J,$N\e(B @code{Message-ID} \e$B$r$8$C$/$j$HD/$a$F$_$k$H!"$O$8$a$NFs!"\e(B
+\e$B;0J8;z$O>o$KF1$8$G$"$k$3$H$K5$$,$D$/$G$7$g$&!#0J2<$NFs$D$O;d$N$b$N$G$9!#\e(B
+
+@example
+<x6u3u47icf.fsf@@eyesore.no>
+<x6sp9o7ibw.fsf@@eyesore.no>
+@end example
+
+\e$B$D$^$j$3$N%^%7%s>e$G$N\e(B ``\e$B;d$N\e(B'' \e$B$N<1JL$O\e(B @samp{x6} \e$B$G$"$k$H$$$&$3$H$G$9!#\e(B
+\e$B$3$l$O;H$($^$9\e(B --- \e$B0J2<$N5,B'$O;d<+?H$X$N%U%)%m!<%"%C%WA4$F$KBP$7$F%9%3\e(B
+\e$B%"$rA}2C$5$;$k$G$7$g$&!#\e(B
+
+@lisp
+("references"
+ ("<x6[0-9a-z]+\\.fsf\\(_-_\\)?@@.*eyesore\\.no>"
+  1000 nil r))
+@end lisp
+
+``\e$B$"$J$?$N\e(B'' \e$B$,:G=i$NFsJ8;z$K$J$k$+:G=i$N;0J8;z$K$J$k$+$O%7%9%F%`$K0MB8\e(B
+\e$B$7$^$9!#\e(B
+
+@node Scoring On Other Headers
+@section \e$BB>$N%X%C%@!<$K%9%3%"$rIU$1$k\e(B
+@cindex scoring on other headers
+
+gnus \e$B$,\e(B ``\e$BEAE}E*\e(B'' \e$B$J%X%C%@!<\e(B -- @samp{From}, @samp{Subject} \e$B$J$I\e(B -- \e$B$K\e(B
+\e$B%9%3%"$rIU$1$k$N$O$H$F$bB.$$$G$9!#$G$9$,!"B>$N%X%C%@!<$K%9%3%"$rIU$1$k$K\e(B
+\e$B$O\e(B @code{head} \e$B$N%9%3%"$N$?$a$N5,B'$r=q$/I,MW$,$"$j!"$=$l$O9gCW$rC5$9$?\e(B
+\e$B$a$K\e(B gnus \e$B$,Kh2s%P%C%/%(%s%I$+$iC1FH$N5-;v$r<h$j4s$;$J$1$l$P$J$i$J$$$3$H\e(B
+\e$B$r0UL#$7$^$9!#$3$l$OBg$-$J%0%k!<%W$G$OD9$$;~4V$,$+$+$j$^$9!#\e(B
+
+\e$B$5$F!"%K%e!<%9%0%k!<%W$G$O$J$/$F%a!<%k%0%k!<%W$G$3$l$r9T$J$&$N$O$5$[$IBg\e(B
+\e$BJQ$G$O$J$/!"$=$N$?$a$N$9$0$l$?<jCJ$,MQ0U$5$l$F$$$^$9!#$3$N%^%K%e%"%k\e(B
+\e$B$N\e(B @ref{To From Newsgroups} \e$B$N9`$G$O$3$N5!9=$,$I$&F/$/$+$,>\$7$/@bL@$5$l\e(B
+\e$B$F$$$^$9$,!"$3$3$G$O\e(B @code{nnml} \e$B$G\e(B @samp{To} \e$B$H\e(B @samp{Cc} \e$B%X%C%@!<$K%9\e(B
+\e$B%3%"$rIU$1$kJ}K!$ND4M}$NNc$r5s$2$^$7$g$&!#\e(B
+
+\e$B0J2<$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KCV$$$F2<$5$$!#\e(B
+
+@lisp
+(setq gnus-extra-headers '(To Cc Newsgroups Keywords)
+      nnmail-extra-headers gnus-extra-headers)
+@end lisp
+
+gnus \e$B$r:F5/F0$7$F!"\e(B@kbd{M-x nnml-generate-nov-databases} \e$B%3%^%s%I\e(B
+\e$B$G\e(B @code{nnml} \e$B$N\e(B overview \e$B%U%!%$%k$r:n$jD>$7$^$9!#$b$7$"$J$?$,$?$/$5$s\e(B
+\e$B$N%a!<%k$r;}$C$F$$$k$H!"$3$l$K$OD9$$;~4V$,$+$+$j$^$9!#\e(B
+
+\e$B$=$7$F\e(B @kbd{I e s p To RET <your name> RET} \e$B$N$h$&$K$9$k$H!"$"$J$?\e(B
+\e$B$O\e(B @samp{To} \e$B$H\e(B @samp{Cc} \e$B%X%C%@!<$K\e(B ``extra headers'' \e$B$H$7$F%9%3%"$rIU\e(B
+\e$B$1$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$o$+$C$?$+$J\e(B? \e$B4JC1$@$h$M!#\e(B
+
+@node Scoring Tips
+@section \e$B%9%3%"IU$1$N1|5A\e(B
+@cindex scoring tips
+
+@table @dfn
+@item \e$B%/%m%9%]%9%H\e(B
+@cindex crossposts
+@cindex scoring crossposts
+\e$B%/%m%9%]%9%H$N%9%3%"$rDc$/$7$?$1$l$P!"%^%C%A$5$;$k$Y$-9T\e(B
+\e$B$O\e(B @code{Xref} \e$B%X%C%@!<$G$9!#\e(B
+
+@lisp
+("xref" (" talk.politics.misc:" -1000))
+@end lisp
+
+@item \e$BJ#?t$N%/%m%9%]%9%H\e(B
+\e$B$"$k?t!"Nc$($P;0$D0J>e$N%0%k!<%W$K%/%m%9%]%9%H$5$l$F$$$k5-;v$N%9%3%"$rDc\e(B
+\e$B$/$7$?$1$l$P!"\e(B
+
+@lisp
+("xref"
+  ("[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+"
+   -1000 nil r))
+@end lisp
+
+@item \e$BK\J8$X$N%^%C%A\e(B
+\e$B$3$l$O0lHLE*$K$O$"$^$jNI$$9M$($G$O$"$j$^$;$s\e(B --- \e$B$=$l$O$H$F$bD9;~4V$+$+$C\e(B
+\e$B$F$7$^$&$+$i$G$9!#<B:]\e(B gnus \e$B$O!"$=$l$>$l$N5-;v$r8DJL$K%5!<%P!<$+$i<hF@$7\e(B
+\e$B$F$3$J$1$l$P$J$i$J$$$N$G$9!#$G$b!"$"$J$?$O$=$l$G$b$d$j$?$$$+$bCN$l$^$;$s\e(B
+\e$B$M!#%^%C%A$5$;$k%-!<$O;0$D\e(B(@code{Head}, @code{Body}, @code{All}) \e$B$"$k$N\e(B
+\e$B$G$9$,!"%9%3%"%U%!%$%kKh$K0l$DA*$s$G$=$l$K8GDj$7$?J}$,NI$$$G$9!#$b$7Fs$D\e(B
+\e$B$r;H$&$H!"$=$l$>$l$N5-;v$O\e(B @emph{\e$BFs2s\e(B} \e$B<hF@$5$l$F$7$^$$$^$9!#$b\e(B
+\e$B$7\e(B @code{Head} \e$B$+$i$A$g$C$H$@$1!"\e(B@code{Body} \e$B$+$i$A$g$C$H$@$1%^%C%A$5$;\e(B
+\e$B$?$$!"$H$$$&$N$G$"$l$P!"AGD>$K\e(B @code{All} \e$B$r;H$C$FA4It%^%C%A$5$;$F$/$@$5\e(B
+\e$B$$!#\e(B
+
+@item \e$B4{FI$N0uIU$1\e(B
+\e$B$"$k0lDj?t;z0J2<$N%9%3%"$r;}$D5-;v$K$O!"$*$=$i$/4{FI$N0u$r$D$1$F$7$^$$$?\e(B
+\e$B$/$J$k$G$7$g$&!#$3$l$O\e(B @file{all.SCORE} \e$B%U%!%$%k$K0J2<$N$b$N$rF~$l$F$*$/\e(B
+\e$B$3$H$K$h$C$F:G$b4JC1$K<B8=$G$-$^$9!#\e(B
+
+@lisp
+((mark -100))
+@end lisp
+
+@code{expunge} \e$B$r;H$C$FF1MM$N$3$H$r9M$($k$3$H$b$G$-$^$9!#\e(B
+
+@item \e$BH]DjJ8;z%/%i%9\e(B
+\e$B$b$7\e(B @code{[^abcd]*} \e$B$_$?$$$J$b$N$r;XDj$9$k$H!"$?$V$s4|BTDL$j$N7k2L$OF@\e(B
+\e$B$i$l$J$$$G$7$g$&!#$3$l$O2~9TJ8;z$K$b%^%C%A$7$F$7$^$$!"$(!<$H!"L$CN$N@$3&\e(B
+\e$B$^$GB3$/$+$b$7$l$^$;$s!#Be$o$j$K\e(B@code{[^abcd\n]*} \e$B$r;H$C$F$/$@$5$$!#\e(B
+@end table
+
+@node Reverse Scoring
+@section \e$B5U%9%3%"\e(B
+@cindex reverse scoring
+
+\e$B$b$7!"I=Bj%X%C%@!<$K\e(B @samp{Sex with Emacs} \e$B$H$$$&J8;z$,$"$k5-;v$@$1$r;D\e(B
+\e$B$7$F!"$=$NB>$N5-;vA4$F$r>C5n$7$F$7$^$$$?$1$l$P!"%9%3%"%U%!%$%k$K0J2<$N$h\e(B
+\e$B$&$J$b$N$rF~$l$k$3$H$b$G$-$^$9!#\e(B
+
+@lisp
+(("subject"
+  ("Sex with Emacs" 2))
+ (mark 1)
+ (expunge 1))
+@end lisp
+
+\e$B$=$7$F\e(B @samp{Sex with Emacs} \e$B$K%^%C%A$9$kA4$F$N5-;v$r=8$a$F!";D$j$r=3Ht\e(B
+\e$B$P$9$?$a$K4{FI$N0u$r$D$1!">C5n$7$^$9!#\e(B
+
+@node Global Score Files
+@section \e$B%0%m!<%P%k%9%3%"%U%!%$%k\e(B
+@cindex global score files
+
+\e$B4V0c$$$J$/!"B>$N%K%e!<%9%j!<%@!<$O\e(B ``\e$B%0%m!<%P%k:o=|%U%!%$\e(B
+\e$B%k\e(B (global kill file)'' \e$B$r;}$C$F$$$^$9!#$3$l$OIaDL!"A4$F$N%0%k!<%W$KE,MQ\e(B
+\e$B$5$l$k!"%f!<%6$N%[!<%`%G%#%l%/%H%j!<$K3JG<$5$l$F$$$k0l$D$N:o=|%U%!%$%k0J\e(B
+\e$B>e$N2?J*$G$b$"$j$^$;$s!#$O$s\e(B! \e$B$A$C$]$1$J%K%e!<%9%j!<%@!<$@$M!#<e$9$.!#\e(B
+
+\e$BKM$,$3$3$GOC$7$F$$$k$N$O%0%m!<%P%k%9%3%"%U%!%$%k$G$9!#A4@$3&Cf$+$i$N!";j\e(B
+\e$B$k=j$+$i$N%f!<%6$K$h$k%9%3%"%U%!%$%k!"@$3&$N9q!9$rA4$F!"5pBg$J0l$D$N9,$;\e(B
+\e$B$J%9%3%"%U%!%$%kF1LA$KCD7k$5$;$k%9%3%"%U%!%$%k\e(B !Ange-score! \e$B?7$7$/$F%F%9\e(B
+\e$B%H$7$F$$$J$$\e(B!
+
+@vindex gnus-global-score-files
+\e$BB>$N?M$N%9%3%"%U%!%$%k$r;H$&$?$a$K$7$J$1$l$P$J$i$J$$$3$H$O!"\e(B
+@code{gnus-global-score-files} \e$BJQ?t$r@_Dj$9$k$3$H$@$1$G$9!#$=$l$>$l$N%9\e(B
+\e$B%3%"%U%!%$%kKh$K!"$"$k$$$O$=$l$>$l$N%9%3%"%U%!%$%k%G%#%l%/%H%jKh$KBP$7$F\e(B
+\e$B0l$D$N9`L\$K$J$j$^$9!#\e(BGnus \e$B$O$I$N%9%3%"%U%!%$%k$r$I$N%0%k!<%W$K;H$&$N$,\e(B
+\e$BE,@Z$G$"$k$+$r<+J,$G7hDj$7$^$9!#\e(B
+
+\e$BNc$($P\e(B @file{/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE} \e$B$N\e(B
+\e$B%9%3%"%U%!%$%k$H\e(B @file{/ftp@@ftp.some-where:/pub/score} \e$B%G%#%l%/%H%j$K$"\e(B
+\e$B$kA4$F$N%9%3%"%U%!%$%k$r;H$$$?$1$l$P!"\e(B
+
+@lisp
+(setq gnus-global-score-files
+      '("/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE"
+        "/ftp@@ftp.some-where:/pub/score/"))
+@end lisp
+
+@findex gnus-score-search-global-directories
+@noindent
+\e$B$I$&$@$$!"4JC1$@$m$&\e(B? \e$B%G%#%l%/%H%jL>$O\e(B @samp{/} \e$B$G=*$o$i$J$/$F$O$J$j$^$;\e(B
+\e$B$s!#$3$l$i$N%G%#%l%/%H%j$OIaDL$O!"0l2s$N\e(B gnus \e$B;HMQ4|4VCf$K0l2s$@$1$7$+FI\e(B
+\e$B$_9~$_$^$;$s!#$b$71s3V%G%#%l%/%H%j$r<jF0$G:FFI$_9~$_$9$kI,MW$,=P$F$-$?$i!"\e(B
+@code{gnus-score-search-global-directories} \e$BL?Na$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+\e$B$?$@$78=;~E@$G$O!"$3$N%*%W%7%g%s$r;H$&$H%0%k!<%W$KF~$k$N$,$$$/$i$+CY$/$J\e(B
+\e$B$j$^$9!#\e(B(\e$B$D$^$j\e(B --- \e$B$+$J$j!"$G$9$1$I\e(B)
+
+\e$B$b$7%9%3%"%U%!%$%k$r!"B>$N?M$?$A$K;H$C$F$b$i$&$h$&$K0];}$7$?$/$J$C$F$-$?\e(B
+\e$B$i!"C1$K$"$J$?$N%9%3%"%U%!%$%k$rF?L>\e(B FTP \e$B$KCV$$$F!"@$3&Cf$K8xI=$7$F$/$@\e(B
+\e$B$5$$!#5U;J2q<T$K$J$l$k$h\e(B! \e$B$=$N8e$KB3$$$F4V0c$$$J$/5/$3$k5U;J2q<T@oAh!"$9\e(B
+\e$B$J$o$A?M!9$N6&46$r>!$A<h$k$?$a$N5U;J2q<T$N@o$$$K;22C$9$k$3$H$G!"H`$i$N%9\e(B
+\e$B%3%"%U%!%$%k$K4V0c$C$?A0Ds$r;H$o$;$k$h$&$KM6F3$9$k$N$@\e(B! \e$B$d$C$?\e(B! \e$B$3$l$G%M%C\e(B
+\e$B%H$O5_$o$l$k\e(B!
+
+\e$B0J2<$K!"5U;J2q<T$J$j$?$,$j$N$?$a$NHk5;$r$$$/$D$+!"B(@J$G=R$Y$^$9!#\e(B
+
+@itemize @bullet
+
+@item
+\e$BHs>o$KB?$/$N>l=j$K%/%m%9%]%9%H$5$l$F$$$k5-;v$O4V0c$$$J$/6}$G$"$k!#\e(B
+@item
+\e$B0l8D$NITE,@Z$J5-;v$r8:E@$9$k$K$O!"\e(B@code{Message-ID} \e$B$G8:E@$9$k!#\e(B
+@item
+\e$BFC$KAG@2$i$7$$Ej9F<T$?$A$O1JB3E*$J<gLrC#$H$7$F2C;;$9$k!#\e(B
+@item
+\e$B$=$N%0%k!<%W$N7{>OL5;k$NEj9F$rIQHK$K7+$jJV$9Ej9F<T$O!"@dLG$5$;$F$7$^$C$F\e(B
+\e$B:9$7;Y$($J$$!#\e(B
+@item
+@code{mark} \e$B$H\e(B @code{expunge} \e$B%"%H%`$r@_Dj$7!"1x$i$o$7$$5-;v$r40A4$KAr$j\e(B
+\e$B5n$k!#\e(B
+
+@item
+\e$B>C5n$N%9%3%"9`L\$r;H$C$F%U%!%$%k$NBg$-$5$r>.$5$/M^$($k!#$G$b$*$=$i$/$O!"\e(B
+\e$B%5%$%H$K$h$C$F8E$$5-;v$rD94|4VJ]B8$9$k$h$&$K!"4|8B@Z$l>C5n$N4|4V$OD9$/<h\e(B
+\e$B$k$G$7$g$&$1$l$I$b!#\e(B
+@end itemize
+
+@dots{} \e$B2L$?$7$FB>$N%K%e!<%9%j!<%@!<$O>-Mh!"%0%m!<%P%k%9%3%"%U%!%$%k$r%5\e(B
+\e$B%]!<%H$9$k$G$7$g$&$+\e(B? @emph{\e$B$&$U$U\e(B}\e$B!#$=$&!"$I$&9M$($F$_$?$C$F!"\e(BBlue
+Wave \e$B$d\e(B xrn \e$B$d\e(B 1stReader \e$B$H$+$$$C$?%K%e!<%9%j!<%@!<$O%9%3%"$r%5%]!<%H$9\e(B
+\e$B$k$Y$-$@$M!#:#$O8GBC$r0{$s$G8+<i$k$3$H$K$7$^$7$g$&$+\e(B?
+
+@node Kill Files
+@section \e$B>C5n%U%!%$%k\e(B
+@cindex kill files
+
+Gnus \e$B$O$^$@!"$"$N$&$6$C$?$$8E$$>C5n%U%!%$%k$r%5%]!<%H$7$F$$$^$9!#<B:]>C\e(B
+\e$B5n%U%!%$%k$N9`L\$O$b$&>C$7$F$b$h$$$N$G$9$,!"$=$l$O\e(B Daniel Quinlan \e$B$,%9%3\e(B
+\e$B%"%U%!%$%k$r9M$(=P$9A0$K;d$,=q$$$?$b$N$J$N$G!"$=$N%3!<%I$O$^$@;D$C$F$$$^\e(B
+\e$B$9!#\e(B
+
+\e$BMW$9$k$K!">C5n=hM}$O%9%3%"=hM}$h$j$b$+$J$jCY$$$N$G\e(B (\e$B;d$N8@$$$?$$$N\e(B
+\e$B$O\e(B @emph{\e$B$b$N$9$4$/\e(B})\e$B!"$"$J$?$N>C5n%U%!%$%k$O%9%3%"%U%!%$%k$K=q$-49$($?\e(B
+\e$BJ}$,NI$$$+$b$7$l$^$;$s!#\e(B
+
+\e$B$$$:$l$K$;$h!">C5n%U%!%$%k$OIaDL$N\e(B @code{emacs-lisp} \e$B%U%!%$%k$G$9!#$3$N\e(B
+\e$B%U%!%$%k$NCf$K$O$I$s$J7A<0$G$bF~$l$k$3$H$,$G$-$^$9!#$D$^$j>C5n%U%!%$%k$r\e(B
+\e$B%0%k!<%W$KF~$C$?$H$-$K<B9T$9$k0l<o$N86;OE*$J%U%C%/4X?t$N$h$&$K;H$&$3$H$,\e(B
+\e$B$G$-$^$9!#$^$"$=$l$,$"$^$j$$$$J}K!$G$O$J$$$H$7$F$b$M!#\e(B
+
+\e$BDL>o$N>C5n%U%!%$%k$O0J2<$N$h$&$K$J$j$^$9!#\e(B
+
+@lisp
+(gnus-kill "From" "Lars Ingebrigtsen")
+(gnus-kill "Subject" "ding")
+(gnus-expunge "X")
+@end lisp
+
+\e$B$3$l$O;d$,=q$$$?A4$F$N5-;v$K4{FI$N0u$r$D$1!"35N,%P%C%U%!$+$i0u$N$D$$$?5-\e(B
+\e$B;v$r:o=|$7$^$9!#$H$C$F$bJXMx$G$9!#$"$J$?$b$=$&;W$&$G$7$g!#\e(B
+
+\e$BB>$N%W%m%0%i%`$G$OA4$/0c$&>C5n%U%!%$%k$N9=J8$r;H$C$F$$$^$9!#$b\e(B
+\e$B$7\e(B gnus \e$B$,\e(B @code{rn} \e$B$N>C5n%U%!%$%k$i$7$-$b$N$K=P2q$C$?$i!"2?$H$+$=$l$r\e(B
+\e$B2r<a$7$h$&$H$7$^$9!#\e(B
+
+@sc{gnus} \e$B>C5n%U%!%$%k$rJT=8$9$k$?$a$NFs$D$N35N,%P%C%U%!4X?t$,$"$j$^$9!#\e(B
+
+@table @kbd
+@item M-k
+@kindex M-k (\e$B35N,\e(B)
+@findex gnus-summary-edit-local-kill
+\e$B$=$N%0%k!<%W$N>C5n%U%!%$%k$rJT=8$9\e(B
+\e$B$k\e(B (@code{gnus-summary-edit-local-kill})\e$B!#\e(B
+
+@item M-K
+@kindex M-K (\e$B35N,\e(B)
+@findex gnus-summary-edit-global-kill
+\e$B0lHL>C5n%U%!%$%k$rJT=8$9$k\e(B (@code{gnus-summary-edit-global-kill})\e$B!#\e(B
+@end table
+
+\e$B>C5n%U%!%$%k$rJT=8$9$kFs$D$N%0%k!<%W%b!<%I4X?t$,$"$j$^$9!#\e(B
+
+@table @kbd
+@item M-k
+@kindex M-k (\e$B%0%k!<%W\e(B)
+@findex gnus-group-edit-local-kill
+\e$B$=$N%0%k!<%W$N>C5n%U%!%$%k$rJT=8$9$k\e(B (@code{gnus-group-edit-local-kill})\e$B!#\e(B
+
+@item M-K
+@kindex M-K (\e$B%0%k!<%W\e(B)
+@findex gnus-group-edit-global-kill
+\e$B0lHL>C5n%U%!%$%k$rJT=8$9$k\e(B (@code{gnus-group-edit-global-kill})\e$B!#\e(B
+@end table
+
+\e$B>C5n%U%!%$%kJQ?t!#\e(B
+
+@table @code
+@item gnus-kill-file-name
+@vindex gnus-kill-file-name
+@samp{soc.motss} \e$B%0%k!<%WMQ$N>C5n%U%!%$%k$ODL\e(B
+\e$B>o\e(B @file{soc.motss.KILL} \e$B$H$$$&L>A0$G$9!#$3$N%U%!%$%kL>$rF@$k$?$a$K%0%k!<\e(B
+\e$B%WL>$KIU2C$5$l$k@\Hx<-$O!"\e(B@code{gnus-kill-file-name} \e$BJQ?t$GM?$($i$l$^$9!#\e(B
+``\e$B%0%m!<%P%k\e(B'' \e$B>C5n%U%!%$%k$O\e(B (\e$B%9%3%"%U%!%$%k$N0UL#$G\e(B
+\e$B$N\e(B ``\e$B%0%m!<%P%k\e(B'' \e$B$8$c$J$$$h!"$b$A$m$s\e(B) \e$BC1$K\e(B @file{KILL}\e$B$H$$$&L>A0$G$9!#\e(B
+
+@vindex gnus-kill-save-kill-file
+@item gnus-kill-save-kill-file
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B0J30$G$"$l$P!"\e(Bgnus \e$B$O=hM}$N8e$K>C5n%U%!%$%k$rJ]B8\e(B
+\e$B$7$^$9!#$3$l$O4|8B@Z$l:o=|$r9T$&>C5n$r;H$C$F$$$k$H$-$KI,MW$G$9!#\e(B
+
+@item gnus-apply-kill-hook
+@vindex gnus-apply-kill-hook
+@findex gnus-apply-kill-file-unless-scored
+@findex gnus-apply-kill-file
+\e$B%0%k!<%W$K>C5n%U%!%$%k$rE,MQ$9$k$?$a$K8F$S=P$5$l$k%U%C%/!#$3$l$O=i4|@_Dj\e(B
+\e$B$G$O\e(B @code{(gnus-apply-kill-file)} \e$B$G$9!#$b$7F1$8%0%k!<%W$KBP$7$F%9%3%"\e(B
+\e$B%U%!%$%k$,$"$k>l9g$K$O>C5n%U%!%$%k$rL5;k$7$?$1$l$P!"$3$N%U%C%/\e(B
+\e$B$r\e(B @code{(gnus-apply-kill-file-unless-scored)} \e$B$K@_Dj$7$^$9!#>C5n%U%!%$\e(B
+\e$B%k$r=hM}$5$;$?$/$J$1$l$P!"$3$NJQ?t$r\e(B@code{nil} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+
+@item gnus-kill-file-mode-hook
+@vindex gnus-kill-file-mode-hook
+\e$B>C5n%U%!%$%k%b!<%I%P%C%U%!Fb$G8F$S=P$5$l$k%U%C%/!#\e(B
+@end table
+
+@node Converting Kill Files
+@section \e$B>C5n%U%!%$%k$NJQ49\e(B
+@cindex kill files
+@cindex converting kill files
+
+\e$B$"$J$?$,8E$$>C5n%U%!%$%k$r$I$C$5$j;}$C$F$$$k$N$G$"$l$P!"$=$l$i$r%9%3%"%U%!\e(B
+\e$B%$%k$KJQ49$7$?$/$J$k$G$7$g$&!#$b$7$=$l$i$,\e(B ``\e$BIaDL$N\e(B'' \e$B$d$D$G$"$l$P!"\e(B
+@file{gnus-kill-to-score.el} \e$B%Q%C%1!<%8$r;H$&$3$H$,$G$-$^$9!#$=$&$G$J$1\e(B
+\e$B$l$P!"<j$GJQ49$7$J$1$l$P$J$i$J$$$G$7$g$&!#\e(B
+
+\e$B>C5n%U%!%$%k$+$i%9%3%"%U%!%$%k$X$NJQ49%Q%C%1!<%8$O!"I8=`$G$O\e(Bgnus \e$B$K$O4^\e(B
+\e$B$^$l$^$;$s!#\e(B
+@uref{http://www.stud.ifi.uio.no/~larsi/ding-various/gnus-kill-to-score.el} \e$B$+\e(B
+\e$B$iF~<j$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$b$7$"$J$?$N>C5n%U%!%$%k$,Hs>o$KJ#;($J$b$N$G$"$l$P\e(B --- \e$B$=$l\e(B
+\e$B$K\e(B @code{gnus-kill} \e$B7A<00J30$N$b$N$,$?$/$5$s4^$^$l$F$$$l$P!"$=$l$i$r<j$G\e(B
+\e$BJQ49$7$J$1$l$P$J$j$^$;$s!#$"$k$$$OC1$K$=$l$i$r!"$=$N$^$^$K$7$F$*$$$F$/$@\e(B
+\e$B$5$$!#\e(BGnus \e$B$O0JA0F1MM$K$=$l$i$r;H$C$F$/$l$k$G$7$g$&!#\e(B
+
+@node GroupLens
+@section GroupLens
+@cindex GroupLens
+
+@sc{\e$BCm0U\e(B:} \e$B;DG0$J$3$H$K\e(B GroupLens \e$B5!9=$OJD:?$5$l$F$$$k$h$&$J$N$G!"$3$N9`\e(B
+\e$B$O<g$H$7$FNr;KE*$J6=<q$N$?$a$K=q$+$l$F$$$^$9!#\e(B
+
+@uref{http://www.cs.umn.edu/Research/GroupLens/, GroupLens} \e$B$O!"KhF|:n@.\e(B
+\e$B$5$l$kB?$/$NNL$N%K%e!<%95-;v$+$i<A$NNI$$5-;v$rB>$N?M$H6&$K8+$D$1$k$N$r=u\e(B
+\e$B$1$k$?$a$N6&F1A*JL5!9=$G$9!#\e(B
+
+\e$B$3$l$rC#@.$9$k$?$a$K!"\e(BGroupLens \e$B5!9=$O$"$J$?$,4{$KFI$s$@5-;v$KBP$9$k0U8+\e(B
+\e$B$r!"F1$8$h$&$J;v$r$7$?B>$N?M$N0U8+$H7k9g$7$F!"$=$l$>$l$NL$FI%K%e!<%95-;v\e(B
+\e$B$K8D?M2=$5$l$?M=8@$rM?$($^$9!#\e(BGroupLens \e$B$rCg?M$N$h$&$J$b$N$@$H8+$J$7$F$/\e(B
+\e$B$@$5$$!#\e(BGroupLens \e$B$O$"$J$?$,$I$N$h$&$K5-;v$N2ACM$rIU$1$k$+$r8+$F!"F1$8$h\e(B
+\e$B$&$K5-;v$N2ACM$rIU$1$k?M$rC5$7$^$9!#0lEY$"$J$?$N0U8+$H0lCW$9$k?M$rH/8+$9\e(B
+\e$B$l$P!"M=8@$N7A$G!"$=$l$i$N?M$,5-;v$r$I$&;W$&$+$r$"$J$?$K9p$2$^$9!#$"$J$?\e(B
+\e$B$O$3$NM=8@$r5-;v$rFI$_$?$$$+$I$&$+$r7hDj$9$k$N$KLrN)$F$k;v$,$G$-$^$9!#\e(B
+
+@menu
+* Using GroupLens::             \e$B$I$N$h$&$K\e(B gnus \e$B$K\e(B GroupLens \e$B$r;H$o$;$k$h$&$K$9$k$+\e(B
+* Rating Articles::             GropLens \e$B$K$"$J$?$,$I$N$h$&$KCM$rIU$1$k$+$rCN$i$;$k\e(B
+* Displaying Predictions::      GropuLens \e$B$K$h$C$FM?$($i$l$?M=8@$rI=<($9$k\e(B
+* GroupLens Variables::         GoupLens \e$B$r%+%9%?%^%$%:$9$k\e(B
+@end menu
+
+@node Using GroupLens
+@subsection GroupLens \e$B$r;H$&\e(B
+
+GroupLens \e$B$r;H$&$?$a$K$O!"8=:_$A$^$?$KB8:_$9$kM#0l$N\e(B better bit \e$B$G$"\e(B
+\e$B$k\e(B @uref{http://www.cs.umn.edu/Research/GroupLens/bbb.html, Better Bit
+Bureau (BBB)} \e$B$KI.L>\e(B (pseudonym) \e$B$rEPO?$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$BEPO?$7$?8e$G!"$$$/$D$+$NJQ?t$r@_Dj$9$kI,MW$,$"$j$^$9!#\e(B
+
+@table @code
+@item gnus-use-grouplens
+@vindex gnus-use-grouplens
+\e$B$3$NJQ?t$r\e(B @code{nil} \e$B$G$J$$CM$K@_Dj$9$k$H!"\e(BGnus \e$B$,A4$F$N\e(B GroupLens \e$B4XO"\e(B
+\e$B4X?t$r%U%C%/$9$k$h$&$K$J$j$^$9!#\e(B
+
+@item grouplens-pseudonym
+@vindex grouplens-pseudonym
+\e$B$3$NJQ?t$O\e(B Better Bit Bureau \e$B$KEPO?$7$?$H$-$K$b$i$C$?I.L>$K@_Dj$5$l$k$Y\e(B
+\e$B$-$G$9!#\e(B
+
+@item grouplens-newsgroups
+@vindex grouplens-newsgroups
+GroupLens \e$B$NM=8@$rF@$?$$$H;W$&%0%k!<%W$N%j%9%H$G$9!#\e(B
+@end table
+
+\e$B$3$l$,5/$->e$,$C$F\e(B GroupLens \e$B$r<B9T$9$k$?$a$KI,MW$J:GDc8B$N@_Dj$G$9!#0l\e(B
+\e$BEYEPO?$9$k$H!"\e(BGroupLens \e$B$O$"$J$?$KB>$N?M$,9M$($kJ?6Q$K4p$E$$$?%9%3%"$r$"\e(B
+\e$B$J$?$KDs6!$9$k$3$H$r;O$a$^$9!#$7$+$7!"\e(BGroupLens \e$B$NK\Ev$NMx1W$r<u$1$k$?$a\e(B
+\e$B$K$O!"<+J,<+?H$G5-;v$NCMIU$1$r;O$a$J$1$l$P$J$j$^$;$s!#$=$&$9$k$H!"\e(B
+GroupLens \e$B$,$"$J$?$KDs6!$9$k%9%3%"$O$"$J$?$,IaCJG<F@$9$k$h$&$J0U8+$r;}$C\e(B
+\e$B$??M$,4{$KCM$rIU$1$?4p$E$$$F8D?M2=$5$l$^$9!#\e(B
+
+@node Rating Articles
+@subsection Rating Articles
+
+GroupLens \e$B$G$O!"5-;v$O\e(B 1 \e$B$+$i\e(B 5 \e$B$^$G$G$=$l$r4^$s$@HO0O$GCM$rIU$1$i$l$^$9!#\e(B
+1 \e$B$OBS0h$NL5BL8/$$$N$h$&$J$b$N$@$H9M$($i$l!"\e(B5 \e$B$O5-;v$,K\Ev$KNI$$$H9M$($i\e(B
+\e$B$l$k$$$&;v$r0UL#$7$^$9!#$"$J$?$,<+J,<+?H$K?R$M$k4pK\E*$J<ALd$O!"\e(B
+``1 \e$B$+$i\e(B 5 \e$B$NHO0O$NCf$G!"$3$l$HF1$8$h$&$J5-;v$r$b$C$HFI$_$?$$$@$m$&\e(B
+\e$B$+\e(B?'' \e$B$G$9!#\e(B
+
+GroupLens \e$B$G!"5-;v$NCM$rEPO?$9$k$?$a$N;M$D$NJ}K!$,$"$j$^$9!#\e(B
+
+@table @kbd
+@item r
+@kindex r (GroupLens)
+@findex bbb-summary-rate-article
+\e$B$3$N4X?t$O\e(B 1 \e$B$+$i\e(B 5 \e$B$NHO0O$NCMIU$1$NF~NO$rB%?J$7$^$9!#\e(B
+
+@item k
+@kindex k (GroupLens)
+@findex grouplens-score-thread
+\e$B$3$N4X?t$OCMIU$1$NF~NO$rB%?J$7!"%9%l%C%I$NA4$F$N5-;v$rCMIU$1$^$9!#$3$l\e(B
+\e$B$O\e(B rec.humor \e$B$K$"$k$h$&$J$"$ND9$$4VB3$/%9%l%C%I$KBP$7$FHs>o$KLr$KN)$A$^\e(B
+\e$B$9!#\e(B
+@end table
+
+\e$B<!$NFs$D$NL?Na!"\e(B@kbd{n} \e$B$H\e(B @kbd{,} \e$B$O!"$"$J$?$,FI$s$G$$$k5-;v$N%9%3%"$K\e(B
+\e$B$J$k?tCM@\F,0z?t$r$H$j$^$9!#\e(B
+
+@table @kbd
+@item 1-5 n
+@kindex n (GroupLens)
+@findex grouplens-next-unread-article
+\e$B5-;v$NCM$rIU$1$F!"<!$NL$FI5-;v$K0\F0$7$^$9!#\e(B
+
+@item 1-5 ,
+@kindex , (GroupLens)
+@findex grouplens-best-unread-article
+\e$B5-;v$NCM$rIU$1$F<!$N0lHV9b$$%9%3%"$NL$FI5-;v$K0\F0$7$^$9!#\e(B
+@end table
+
+\e$B$b$78=:_$N5-;v$K%9%3%"\e(B 4 \e$B$rIU$1!"<!$N5-;v$K0\F0$7$?$$$N$G$"$l$P!"\e(B
+@kbd{4 n} \e$B$HC!$$$F$/$@$5$$!#\e(B
+
+@node Displaying Predictions
+@subsection \e$BM=8@I=<(\e(B
+
+GroupLens \e$B$O$"$J$?$,%K%e!<%95-;v$r$I$l$/$i$$5$$KF~$k$+$NM=8@$r$7$^$9!#\e(B
+GroupLens \e$B$+$i$NM=8@$O\e(B 1 \e$B$+$i\e(B 5 \e$B$NHO0O$K$"$j!"\e(B1 \e$B$,:G0-$G\e(B 5 \e$B$,:GNI$G$9!#\e(B
+GroupLens \e$B$+$i$NM=8@$rJQ?t\e(B @code{gnus-grouplens-override-scoring} \e$B$K$h$C\e(B
+\e$B$F@)8f$5$l$k;0$D$NFb$N0l$D$K$h$C$F;H$&;v$,$G$-$^$9!#\e(B
+
+@vindex gnus-grouplens-override-scoring
+grouplens \e$B$GM=8@$rI=<($9$k$?$a$K;0$D$NJ}K!$,$"$j$^$9!#\e(BGroupLens \e$B$N%9%3%"\e(B
+\e$B$rIaDL$N\e(B gnus \e$B%9%3%"5!9=$K9W8%$9$k$+!">e=q$-$9$k$+$rA*$V;v$,$G$-$^$9!#>e\e(B
+\e$B=q$-$,=i4|@_Dj$G$9!#$7$+$7!"\e(Bgnus \e$B$N%9%3%"$r\e(B grouplens \e$B$N%9%3%"$KB-$9$N$r\e(B
+\e$B9%$`?M$b$$$^$9!#J,N%%9%3%"$N?6$kIq$$$rF@$k$?$a$K$O!"\e(B
+@code{gnus-grouplens-override-scoring} \e$B$r\e(B @code{'separate} \e$B$K@_Dj$9$kI,\e(B
+\e$BMW$,$"$j$^$9!#\e(BGroupLens \e$B$NM=8@$H\e(B grouplens \e$B%9%3%"$r7k9g$9$k$?$a$K$O$=$l\e(B
+\e$B$r\e(B @code{'override} \e$B$K@_Dj$7!"%9%3%"$r7k9g$9$k$?$a$K\e(B
+\e$B$O\e(B @code{gnus-grouplens-override-scoring} \e$B$r\e(B @code{'combine} \e$B$K@_Dj$7$^\e(B
+\e$B$9!#7k9gIU2C5!G=$rMQ$$$k$H$-$O!"\e(B
+@code{grouplens-prediction-offset} \e$B$*$h\e(B
+\e$B$S\e(B @code{grouplens-score-scale-factor} \e$B$NCM$r@_Dj$7$?$$$H;W$&$G$7$g$&!#\e(B
+
+@vindex grouplens-prediction-display
+\e$B$I$A$i$N>l9g$G$b!"\e(BGroupLens \e$B$OFs!";0$NM=8@$,$I$N$h$&I=<($5$l$?$$$+$NA*Br\e(B
+\e$B$rM?$($^$9!#M=8@$NI=<($OJQ?t\e(B @code{grouplens-prediction-display} \e$B$K$h$C\e(B
+\e$B$F@)8f$5$l$^$9!#\e(B
+
+\e$B0J2<$N$b$N$,$=$NJQ?t$GM-8z$JCM$G$9!#\e(B
+
+@table @code
+@item prediction-spot
+\e$BM=8@$,9b$$$[$I!"1&$NJ}$K\e(B @samp{*} \e$B$,I=<($5$l$^$9!#\e(B
+
+@item confidence-interval
+\e$B?t;z$N3N?.\e(B (confidence) \e$B4V3V$G$9!#\e(B
+
+@item prediction-bar
+\e$BM=8@$,9b$$$[$I!"K@$,D9$/$J$j$^$9!#\e(B
+
+@item confidence-bar
+\e$B?t;z3N?.$G$9!#\e(B
+
+@item confidence-spot
+\e$B3N?.$,9b$$$[$IE@$,Bg$-$/$J$j$^$9!#\e(B
+
+@item prediction-num
+\e$BIaDL$N@N$J$,$i$N?tCM$G$9!#\e(B
+
+@item confidence-plus-minus
+\e$BM=8@$N\e(B +/- \e$B3N?.$G$9!#\e(B
+@end table
+
+@node GroupLens Variables
+@subsection GroupLens \e$BJQ?t\e(B
+
+@table @code
+@item gnus-summary-grouplens-line-format
+GropuLens \e$B3HD%$N35N,%P%C%U%!$G;H$o$l$k35N,9TMM<0$G$9!#IaDL$N35N,9TMM<0$,\e(B
+\e$B<u$1IU$1$k$b$N$HF1$8;XDj$r<u$1IU$1$^$9\e(B (@pxref{Summary Buffer Lines})\e$B!#\e(B
+\e$B=i4|@_Dj$O\e(B@samp{%U%R%z%l%I%(%[%4L: %-23,23n%]%) %s\n} \e$B$G$9!#\e(B
+
+@item grouplens-bbb-host
+bbbd \e$B%5!<%P!<$,<B9T$5$l$F$$$k%[%9%H$G$9!#\e(B@samp{goruplens.cs.umn.edu} \e$B$,\e(B
+\e$B=i4|@_Dj$G$9!#\e(B
+
+@item grouplens-bbb-port
+bbbd \e$B%5!<%P!<$,<B9T$5$l$F$$$k%[%9%H$N%]!<%H$G$9!#=i4|CM$O\e(B 9000 \e$B$G$9!#\e(B
+
+@item grouplens-score-offset
+\e$BM=8@$+$i:9$70z$-$5$l$kCM$G$9!#$D$^$j!"0UL#$N$"$k%9%3%"$K$9$k$?$a$KM=8@$N\e(B
+\e$BCM$+$i$3$N?t;z$r0z$-;;$7$^$9!#=i4|CM$O\e(B 0 \e$B$G$9!#\e(B
+
+@item grouplens-score-scale-factor
+\e$BMxMQ<T$O$3$NJQ?t$r;H$C$F\e(B GroupLens \e$B$N%9%3%"$r3HBg$9$k;v$,$G$-$^$9!#3]$1\e(B
+\e$B;;$NMWAG$O:9$70z$-$N8e$KE,MQ$5$l$^$9!#=i4|CM$O\e(B 1 \e$B$G$9!#\e(B
+@end table
+
+@node Advanced Scoring
+@section \e$B>e5i%9%3%"IU$1\e(B
+
+\e$BI=Bj$d\e(B From \e$B%X%C%@!<$K%9%3%"$rIU$1$k$N$O==J,AGE($G$9$,!"$"$k?MFCDj$NBj$K\e(B
+\e$B4X$7$F8@$C$F$$$k;v$K$@$1K\Ev$K6=L#$,$"$k>l9g$O$I$&$9$l$PNI$$$N$G$7$g\e(B
+\e$B$&\e(B? \e$B$b$7$/$O!"\e(BA \e$B$5$s$,\e(B B \e$B$5$s$K%U%)%m!<%"%C%W$7$F$$$k$H$-$K8@$C$F$$$k;v\e(B
+\e$B$rFI$_$?$/$J$$$1$l$I!"\e(BC\e$B$5$s$K%U%)%m!<%"%C%W$7$F$$$k$H$-$O2?$r8@$C$F$$$k\e(B
+\e$B$+$rCN$j$?$$$H$$$&>l9g$O\e(B?
+
+\e$B>e5i%9%3%"K!B'$r;H$&;v$G!"G$0U$NJ#;($J%9%3%"$NIU$1J}$r:n@.$9$k;v$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+@menu
+* Advanced Scoring Syntax::     \e$BDj5A\e(B
+* Advanced Scoring Examples::   \e$B$I$N$h$&$K8+$($k$+\e(B
+* Advanced Scoring Tips::       \e$B$=$l$r:GBg8BMxMQ$9$k\e(B
+@end menu
+
+@node Advanced Scoring Syntax
+@subsection \e$B>e5i%9%3%"IU$19=J8\e(B
+
+\e$BIaDL$N%9%3%"K!B'$OK!B'$N:G=i$NMWAG$KJ8;zNs$,$"$j$^$9!#>e5i%9%3%"IU$1K!B'\e(B
+\e$B$O:G=i$NMWAG$K%j%9%H$,$"$j$^$9!#FsHVL\$N%j%9%H$O:G=i$NMWAG\e(B
+\e$B$,\e(B @code{nil} \e$B$G$J$$CM$KI>2A$5$l$?$H$-$KE,MQ$5$l$^$9!#\e(B
+
+\e$B$3$l$i$N%j%9%H$O;0$D$NO@M}:nMQ;R$+$i$J$C$F$*$j!"$=$l$i$O0lJ}8~:nMQ;R$G!"\e(B
+\e$B?'!9$J9gCW:nMQ;R$G$9!#\e(B
+
+\e$BO@M}:nMQ;R\e(B:
+
+@table @code
+@item &
+@itemx and
+\e$B$3$NO@M}:nMQ;R$O$=$l$>$l$N0z?t$r\e(B @code{false} \e$B$KI>2A$5$l$k$b$N$r8+$D$1$k\e(B
+\e$B$^$GI>2A$7!"$=$l$+$iDd;_$7$^$9!#A4$F$N0z?t$,\e(B @code{true} \e$B$NCM$KI>2A$5$l\e(B
+\e$B$?>l9g$O!"$3$N:nMQ;R$O\e(B @code{true} \e$B$rJV$7$^$9!#\e(B
+
+@item |
+@itemx or
+\e$B$3$NO@M}:nMQ;R$O$=$l$>$l$N0z?t$r\e(B @code{true} \e$B$KI>2A$5$l$k$b$N$r8+$D$1$k\e(B
+\e$B$^$GI>2A$7$^$9!#$b$7$I$N0z?t$b\e(B @code{true} \e$B$G$J$$$H!"$3$N:nMQ;R\e(B
+\e$B$O\e(B @code{false} \e$B$rJV$7$^$9!#\e(B
+
+@item !
+@itemx not
+@itemx \e,A,\e(B
+\e$B$3$NO@M}:nMQ;R$OC10l$N0z?t$N$_$r$H$j$^$9!#$=$l$O$=$N0z?t$NCM$NO@M}H]Dj$r\e(B
+\e$BJV$7$^$9!#\e(B
+@end table
+
+\e$B0z?t$r%9%3%"IU$1$5$l$F$$$k8=:_$N5-;v$NAD@h$KE,MQ$9$k\e(B @dfn{\e$B4V@\:nMQ;R\e(B} \e$B$,\e(B
+\e$B$"$j$^$9!#Nc$($P!"\e(B@code{1-} \e$B$O8=:_$N5-;v$N?F$K$b%9%3%"K!B'$rE,MQ$7$^$9!#\e(B
+@code{2-} \e$B$O8=:_$N5-;v$NADIcJl$K%9%3%"K!B'$rE,MQ$7$^$9!#Be$o$j$K!"\e(B
+@code{^^} \e$B$r=q$/;v$b$G$-!"$3$N;~!"\e(B@code{^} (\e$B%-%c%i%C%H\e(B) (carat) \e$B$N?t$O$I\e(B
+\e$B$N$/$i$$AD@h$N5-;v$^$G$5$+$N$\$k$+$r<($7$^$9!#\e(B
+
+\e$B:G8e$K!"9gCW:nMQ;R$,$"$j$^$9!#$3$l$i$,K\Ev$N;E;v$r$9$k$b$N$G$9!#9gCW:nMQ\e(B
+\e$B;R$O%X%C%@!<L>$NJ8;zNs$G!"$=$N8e$K9gCW$H9gCW$N7?$,B3$-$^$9!#E57?E*$J9gCW\e(B
+\e$B:nMQ;R$O\e(B @samp{("form" "Lars Ingebrigtsen" s)} \e$B$N$h$&$J$b$N$G$9!#%X%C%@!<\e(B
+\e$BL>$OC1=c$J%9%3%"IU$1$r$9$k$H$-$N$b$N$HF1$8$G!"9gCW$N7?$bF1$8$G$9!#\e(B
+
+@node Advanced Scoring Examples
+@subsection \e$B>e5i%9%3%"IU$1$NNc\e(B
+
+\e$B0J2<$NNc$O%9%3%"%U%!%$%k$N5,B'$G$"$k$3$H$K$4Cm0U2<$5$$!#40`z$J%9%3%"%U%!\e(B
+\e$B%$%k$r:n$k$K$O!"JL$N3g8L$NAH$G$=$l$i$r0O$s$G2<$5$$!#\e(B
+
+Lars \e$B$,\e(B Gnus \e$B$K4X$7$FOC$r$7$F$$$k$H$-$KH`$K$h$C$F=q$+$l$?5-;v$N%9%3%"$r\e(B
+\e$BA}$d$7$?$$$H$7$^$7$g$&\e(B:
+
+@example
+@group
+((&
+  ("from" "Lars Ingebrigtsen")
+  ("subject" "Gnus"))
+ 1000)
+@end group
+@end example
+
+\e$B$M!"$H$F$bC1=c$G$7$g\e(B?
+
+\e$BD9$$5-;v$r=q$$$F$$$k$H$-$O!";~!92?$+AGE($J;v$r8@$$$^$9\e(B:
+
+@example
+((&
+  ("from" "Lars Ingebrigtsen")
+  (|
+   ("subject" "Gnus")
+   ("lines" 100 >)))
+ 1000)
+@end example
+
+\e$B$7$+$7!"H`$,\e(B Reig Eigil Logge \e$B$K$h$C$F=q$+$l$?$b$N$KH?1~$7$F$$$k$H$-$O!"\e(B
+\e$BH`$,=q$$$?$b$N$rFI$_$?$/$"$j$^$;$s\e(B:
+
+@example
+((&
+  ("from" "Lars Ingebrigtsen")
+  (1- ("from" "Reig Eigir Logge")))
+ -100000)
+@end example
+
+Redmondo \e$B$,>C$($?7$2<$K$D$$$F=q$$$?$H$-$K%U%)%m!<%"%C%W$7$?A4$F$N?M$O%9\e(B
+\e$B%3%"$,>e$2$i$l$^$9$,!"$=$l$OH`$i$,Gr$$7$2<$K$D$$$F8l$C$F$$$k$H$-$N$_$G$9!#\e(B
+\e$B$7$+$7!"\e(BLars \e$B$,7$2<$K$D$$$FOC$r$7$F$$$k$H$-$O!"$?$$$F$$$"$^$j$*$b$7$m$/\e(B
+\e$B$"$j$^$;$s\e(B:
+
+@example
+((&
+  (1-
+   (&
+    ("from" "redmondo@@.*no" r)
+    ("body" "disappearing.*socks" t)))
+  (! ("from" "Lars Ingebrigtsen"))
+  ("body" "white.*socks"))
+ 1000)
+@end example
+
+\e$B2DG=@-$OL58BBg$G$9!#\e(B
+
+@node Advanced Scoring Tips
+@subsection \e$B>e5i%9%3%"$N$A$g$C$H$7$?Hk7m\e(B
+
+@code{&} \e$B$H\e(B @code{|} \e$BO@M}:nMQ;R$O!"C;=L2sO)O@M}$r9T$$$^$9!#$9$J$o$A!"$=\e(B
+\e$B$N:nMQ$N7k2L$,L@$i$+$K$J$C$F;~E@$G!"0z?t$r<B9T2aDx$K$+$1$k;v$r;_$a$^$9!#\e(B
+\e$BNc$($P!"\e(B@code{&} \e$B$N0z?t$NI>2A$,\e(B @code{false} \e$B$K$J$k$H!";D$j$N0z?t$rI>2A\e(B
+\e$B$9$kL\E*$OB8:_$7$J$/$J$j$^$9!#$3$l$OCY$$9g\e(B
+\e$BCW\e(B (@samp{body} \e$B$d\e(B @samp{header}) \e$B$r:G8e$K;}$C$F$-$F!"B.$$9g\e(B
+\e$BCW\e(B (@samp{from} \e$B$d\e(B @samp{subject}) \e$B$r:G=i$K;}$C$F$/$k$Y$-$G$"$k$H$$$&;v\e(B
+\e$B$r0UL#$7$^$9!#\e(B
+
+\e$B4V@\:nMQ;R\e(B (@code{1-} \e$B$J$I\e(B) \e$B$O$=$l$i$N0z?t$r%9%l%C%I$N0l@$BeA0$K:nMQ$9$k\e(B
+\e$B$h$&$K$7$^$9!#<!$N$h$&$J;v$r$9$l$P\e(B:
+
+@example
+...
+(1-
+ (1-
+  ("from" "lars")))
+...
+@end example
+
+\e$B$3$l$O\e(B ``\e$B8=:_$N5-;v$NADIcJl$N\e(B from \e$B%X%C%@!<$K%9%3%"$rIU$1$k\e(B'' \e$B$H$$$&;v$r\e(B
+\e$B0UL#$7$^$9!#4V@\$O$H$F$bB.$$$G$9$,!"<!$NJ}$h$j$b\e(B:
+
+@example
+(1-
+ (&
+  ("from" "Lars")
+  ("subject" "Gnus")))
+@end example
+
+\e$B<!$NJ}$,NI$$$G$9\e(B:
+
+@example
+(&
+ (1- ("from" "Lars"))
+ (1- ("subject" "Gnus")))
+@end example
+
+@node Score Decays
+@section \e$B%9%3%"IeGT\e(B
+@cindex score decays
+@cindex decays
+
+\e$B%9%3%"$O:F8=L5$/KD$l>e$,$k798~$,$"$k;v$K5$IU$/$+$b$7$l$^$;$s!#FC$K!"E,1~\e(B
+\e$B%9%3%"$r;H$C$F$$$k$H$-$O!#%9%3%"$,Bg$-$/$J$j$9$.$k$H!"$=$l$i$O0UL#$r<:$$\e(B
+\e$B$^$9\e(B---\e$B$=$l$i$OC1$K:GBg$rDL$j1[$7$F$7$^$C$F!"$=$l$r0UL#$N$"$kJ}K!$G;H$&\e(B
+\e$B;v$OFq$7$/$J$j$^$9!#\e(B
+
+@vindex gnus-decay-scores
+@findex gnus-decay-score
+@vindex gnus-decay-score-function
+Gnus \e$B$O$3$NLdBj$N2r7h$r=u$1$k$?$a$K%9%3%"$rIe$i$;$k5!9=$rDs6!$7$^$9!#%9\e(B
+\e$B%3%"%U%!%$%k$OFI$_9~$^$l!"\e(B@code{gnus-decay-scores} \e$B$,\e(B @code{nil} \e$B$G$J$$\e(B
+\e$B$H!"\e(Bgnus \e$B$O%9%3%"%U%!%$%k$rIeGT5!9=$rDL$7!"A4$F$N1JB3$G$J$$%9%3%"K!B'$N\e(B
+\e$B%9%3%"$r2<$2$^$9!#IeGT<+?H$O4X?t\e(B @code{gnus-decay-score-function} \e$B$K$h$C\e(B
+\e$B$F<B9T$5$l!"=i4|@_Dj$O\e(B @code{gnus-decay-score} \e$B$G$9!#0J2<$O$=$N4X?t$NDj\e(B
+\e$B5A$G$9\e(B:
+
+@lisp
+(defun gnus-decay-score (score)
+  "Decay SCORE according to `gnus-score-decay-constant'
+and `gnus-score-decay-scale'."
+  (let ((n (- score
+              (* (if (< score 0) -1 1)
+                 (min (abs score)
+                      (max gnus-score-decay-constant
+                           (* (abs score)
+                              gnus-score-decay-scale)))))))
+    (if (and (featurep 'xemacs)
+             ;; XEmacs' floor can handle only the floating point
+             ;; number below the half of the maximum integer.
+             (> (abs n) (lsh -1 -2)))
+        (string-to-number
+         (car (split-string (number-to-string n) "\\.")))
+      (floor n))))
+@end lisp
+
+@vindex gnus-score-decay-scale
+@vindex gnus-score-decay-constant
+@code{gnus-score-decay-constant} \e$B$O=i4|CM$H$7$F\e(B 3 \e$B$r;}$A$G!"\e(B
+@code{gnus-score-decay-scale} \e$B$O=i4|CM$H$7$F\e(B 0.05 \e$B$r;}$A$^$9!#$3$l$O0J2<\e(B
+\e$B$N$h$&$J;v$r0z$-5/$3$7$^$9\e(B:
+
+@enumerate
+@item
+-3 \e$B$+$i\e(B 3 \e$B$N4V$N%9%3%"$O$3$N4X?t$,8F$P$l$?$H$-$K\e(B 0 \e$B$K@_Dj$5$l$^$9!#\e(B
+
+@item
+3 \e$B$+$i\e(B 60 \e$B$^$G$N4V$NBg$-$5$N%9%3%"$O;0$D8:$i$5$l$^$9!#\e(B
+
+@item
+60 \e$B$h$jBg$-$$%9%3%"$O%9%3%"$N\e(B 5% \e$B$K8:$i$5$l$^$9!#\e(B
+@end enumerate
+
+\e$B$b$7$3$NIeGT4X?t$r9%$-$G$J$$$J$i!"<+J,<+?H$N4X?t$r=q$$$F$/$@$5$$!#$=$l$O\e(B
+\e$BIeGT$9$k$Y$-%9%3%"$rM#0l$N0z?t$H$7$F8F$P$l!"@0?t$G$"$k$Y$-?7$7$$%9%3%"$r\e(B
+\e$BJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+
+Gnus \e$B$O0lF|$K0l2s%9%3%"$rIeGT$5$;$h$&$H$7$^$9!#Nc$($P!"$b$7\e(B gnus \e$B$r;MF|\e(B
+\e$B4V<B9T$7$F$$$J$$$H!"\e(Bgnus \e$B$O;M2s%9%3%"$rIe$i$;$^$9!#\e(B
+
+@iftex
+@iflatex
+@chapter Message
+@include message-ja.texi
+@chapter Sieve
+@include sieve.texi
+@end iflatex
+@end iftex
+
+@node Various
+@chapter \e$B$$$m$$$m\e(B
+
+@menu
+* Process/Prefix::              \e$BB?$/$N07$$L?Na$G;H$o$l$k=,47\e(B
+* Interactive::                 Gnus \e$B$KB?$/$N<ALd$r?R$M$5$;$k\e(B
+* Symbolic Prefixes::           \e$B$$$/$D$+$N\e(B gnus \e$B$N4X?t$KA*Br8"$rDs6!$9$kJ}K!\e(B
+* Formatting Variables::        \e$B%P%C%U%!$,$I$N$h$&$K8+$($k$Y$-$+$r;XDj$9$k;v$,$G$-$k\e(B
+* Window Layout::               Gnus \e$B%P%C%U%!%&%#%s%I%&$r@_Dj$9$k\e(B
+* Faces and Fonts::             \e$B%U%'%$%9$,$I$N$h$&$K8+$($k$+$rJQ99$9$k\e(B
+* Compilation::                 \e$B$I$N$h$&$K$7$F\e(B gnus \e$B$NB.EY$r>e$2$k$+\e(B
+* Mode Lines::                  \e$B%b!<%I9T$K>pJs$rI=<($9$k\e(B
+* Highlighting and Menus::      \e$B%P%C%U%!$rAGE($G?4CO$h$/8+$;$k\e(B
+* Buttons::                     \e$B4JC1$J==Jb$G%"%-%l%9g'$rF@$k\e(B
+* Daemons::                     Gnus \e$B$O$"$J$?$NN"$GJ*;v$r<B9T$9$k;v$,$G$-$k\e(B
+* NoCeM::                       Spam \e$B$dB>$NB@$j$d$9$$?);v$rHr$1$kJ}K!\e(B
+* Undo::                        \e$B$$$/$D$+$NF0:n$O85$KLa$9;v$,$G$-$k\e(B
+* Predicate Specifiers::        \e$B=R8l$r@_Dj$9$k\e(B
+* Moderation::                  \e$B$"$J$?$,%b%G%l!<%?!<$@$C$?$i$I$&$9$k$+\e(B
+* Image Enhancements::          \e$B:G?7$N\e(B Emacs/XEmacs \e$B$O3($rI=<($G$-$k\e(B
+* Fuzzy Matching::              \e$BBg$-$JLJLS$C$F2?\e(B?
+* Thwarting Email Spam::        \e$BM>7W$J>&6HE*EE;R%a!<%k$rHr$1$kJ}K!\e(B
+* Other modes::                 \e$BB>$N%b!<%I$H$NAj8_:nMQ\e(B
+* Various Various::             \e$BK\Ev$K$$$m$$$m$J$b$N\e(B
+@end menu
+
+@node Process/Prefix
+@section \e$B%W%m%;%9\e(B/\e$B@\F,0z?t\e(B
+@cindex process/prefix convention
+
+\e$BB?$/$N4X?t!"$=$NCf$G$b5-;v$N0\F0!"I|9f2=!"J]B8$r$9$k$?$a$N4X?t$O!"\e(B
+@dfn{\e$B%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B} \e$B$H$7$FCN$i$l$F$$$k$b$N$r;H$$$^$9!#\e(B
+
+\e$B$3$l$OMxMQ<T$,$I$N5-;v$KL?Na$r<B9T$7$?$$$+$r8+$D$1$k$?$a$NJ}K!$G$9!#\e(B
+
+\e$B$=$l$O$3$N$h$&$J46$8$G$9\e(B:
+
+\e$B$b$7?tCM@\F,0z?t$,\e(B N \e$B$G$"$k$H!"8=:_$N5-;v$+$i;O$a$F!"<!$N\e(B N \e$B5-;v$K:n6H$r\e(B
+\e$B<B9T$7$^$9!#$b$7?tCM@\F,0z?t$,Ii$G$"$k$H!"8=:_$N5-;v$+$i;O$a$F!"A0\e(B
+\e$B$N\e(B N \e$B5-;v$K:n6H$r<B9T$7$^$9!#\e(B
+
+@vindex transient-mark-mode
+@code{transient-mark-mode} \e$B$,\e(B @code{nil} \e$B$G$J$/!"%j!<%8%g%s$,A`:n$5$l$F\e(B
+\e$B$$$k$H!"%j!<%8%g%s$K$"$kA4$F$N5-;v$K:n6H$,$J$5$l$^$9!#\e(B
+
+\e$B$b$7@\F,0z?t$,L5$$$1$l$I!"$$$/$D$+$N5-;v$O%W%m%;%90u$,IU$$$F$$$k$H$$$&>l\e(B
+\e$B9g$O!"%W%m%;%90u$NIU$$$F$$$k5-;v$K:n6H$,<B9T$5$l$^$9!#\e(B
+
+\e$B?tCM@\F,0z?t$d%W%m%;%90u$NIU$$$F$$$k5-;v$,L5$$>l9g$O!"8=:_$N5-;v$K$@$1:n\e(B
+\e$B6H$r<B9T$7$^$9!#\e(B
+
+\e$B$3$l$OK\Ev$KHs>o$K4JC1$G$9$,!"6CC2$rHr$1$i$l$k$h$&$K>\:Y$rL@$i$+$K$7$F$*\e(B
+\e$B$/I,MW$,$"$k$N$G$9!#\e(B
+
+\e$B%W%m%;%90u$KH?1~$9$k5-;v$O8=:_$N%W%m%;%90u$NIU$$$F$$$k5-;v$N%j%9%H$r%9%?%C\e(B
+\e$B%/$K@Q$_!"A4$F$N%W%m%;%90u$N5-;v$N%j%9%H$r>C5n$7$^$9!#A02s$N@_Dj\e(B
+\e$B$r\e(B @kbd{M P y} \e$B$GI|5l$5$;$k;v$,$G$-$^$9\e(B (@pxref{Setting Process Marks})\e$B!#\e(B
+
+@vindex gnus-summary-goto-unread
+\e$BB?$/$N?M!9$r6C$+$;!"62$,$i$;$k$H;W$o$l$k$3$H$O!"Nc$($P!"\e(B@kbd{3 d} \e$B$OK\Ev\e(B
+\e$B$K\e(B @kbd{d} @kbd{d} @kbd{d} \e$B$HF1$8;v$r$9$k;v$G$9!#$=$l$>$l$N\e(B @kbd{d} (\e$B$3\e(B
+\e$B$l$O8=:_$N5-;v$K4{FI$N0u$rIU$1$^$9\e(B) \e$B$O=i4|@_Dj$G$O0u$rIU$1$?8e$K<!$NL$FI\e(B
+\e$B5-;v$K0\F0$9$k$N$G!"\e(B@kbd{3 d} \e$B$O35N,%P%C%U%!$,$I$N$h$&$G$"$C$F$b!"<!\e(B
+\e$B$N;0$D$NL$FI5-;v$r4{FI$K$7$^$9!#$b$C$HJ,$+$j$d$9$$F0:n$N$?$a$K\e(B
+\e$B$O\e(B @code{gnus-summary-goto-unread} \e$B$r\e(B @code{nil} \e$B$K@_Dj$7$F$/$@$5$$!#\e(B
+
+\e$BB?$/$N%3%^%s%I$O%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$r;H$$$^$;$s!#$H$$$&$3$H$O!"$3$N\e(B
+\e$B%^%K%e%"%k$G$O$C$-$j$H=R$Y$F$$$^$9!#%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47$r;H$o$J$$%3\e(B
+\e$B%^%s%I$KE,MQ$9$k$K$O!"\e(B@kbd{M-&} \e$B%3%^%s%I$r;H$$$^$7$g$&!#Nc$($P!"$=$N%0%k!<\e(B
+\e$B%W$N$9$Y$F$N5-;v$r4|8B@Z$l:o=|2DG=$H$7$F0u$rIU$1$k$K\e(B
+\e$B$O\e(B @kbd{M P b M-& E} \e$B$H$7$^$9!#\e(B
+
+@node Interactive
+@section \e$BBPOCE*\e(B
+@cindex interaction
+
+@table @code
+@item gnus-novice-user
+@vindex gnus-novice-user
+\e$B$b$7$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"$"$J$?$O\e(B Usenet \e$B$N@$3&$K?7$7$/F~$C$F\e(B
+\e$BMh$??M$G$"$k$+!"Hs>o$K?5=E$J?M$G!"$3$l$OK\Ev$KNI$$;v$G$9!#2?$+4m81$J;v$r\e(B
+\e$B$9$kA0$K!"\e(B``\e$BK\Ev$K$3$l$r$7$?$$$N$G$9$+\e(B?'' \e$B$H$$$&$h$&$J<ALd$r<u$1$^$9!#\e(B
+\e$B$3$l$O=i4|@_Dj$G$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-expert-user
+@vindex gnus-expert-user
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$H!"$"$J$?$O\e(B gnus \e$B$+$i$[$H$s$I<ALd$r<u$1$k;v\e(B
+\e$B$O$"$j$^$;$s!#$3$l$OC1=c$K$"$J$?$,$I$N$h$&$JJQ$J;v$r$7$F$$$F$b!"2?$r$7$F\e(B
+\e$B$$$k$+$r$o$+$C$F$$$k$H8+$J$7$^$9!#\e(B
+
+@item gnus-interactive-catchup
+@vindex gnus-interactive-catcup
+@code{nil} \e$B$G$J$$$H!"%0%k!<%W$KDI$$$D$/\e(B (catchup) \e$BA0$K!"3NG'$rMW5a$7$^$9!#\e(B
+\e$B$3$l$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-interactive-exit
+@vindex gnus-interactive-exit
+Gnus \e$B$r=*N;$9$kA0$K3NG'$rMW5a$7$^$9!#$3$NJQ?t$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B
+@end table
+
+@node Symbolic Prefixes
+@section \e$B%7%s%\%k$N@\F,0z?t\e(B
+@cindex symbolic prefixes
+
+\e$BHs>o$KB?$/$N\e(B Emacs \e$B$NL?Na$O\e(B (\e$B?tCM\e(B) \e$B@\F,0z?t$KH?1~$7$^$9!#Nc$($P!"\e(B
+@kbd{C-u 4 C-f} \e$B$O%]%$%s%H$r\e(B 4 \e$BJ8;z@h$K0\F0$7!"\e(B
+@kbd{C-u 9 0 0 I s s p} \e$B$O1JB3\e(B @code{Suject} \e$BJ8;zNs$N0lIt%9%3%"K!B'\e(B
+\e$B$N\e(B 900 \e$B$r8=:_$N5-;v$K2C$($^$9!#\e(B
+
+\e$B$3$l$OAGE($GNI$$$N$G$9$,!"L?Na$K$b$&>/$7DI2C$N>pJs$rM?$($?$$$H$-$O$I$&$9\e(B
+\e$B$l$PNI$$$N$G$7$g$&\e(B? \e$B$(!<$H!"$?$$$F$$$NL?Na$,$7$F$$$k;v$O!"\e(B``\e$B@8$N\e(B'' \e$B@\F,\e(B
+\e$B0z?t$rFCJL$JJ}K!$G2r<a$9$k;v$G$9!#Nc$($P!"\e(B@kbd{C-u 0 C-x C-s} \e$B$O8=:_$N5-\e(B
+\e$B;v$rJ]B8$9$k$H$-$K%P%C%/%"%C%W%U%!%$%k$r:n$i$J$$$GM_$7$$$H$$$&$3$H$r0UL#\e(B
+\e$B$7$^$9!#$G$b!"%P%C%/%"%C%W%U%!%$%k$r:n$i$J$$$GJ]B8$7!"F1;~$K\e(B Emacs \e$B$K8w$C\e(B
+\e$B$FM_$7$/!"AGE($J2;3Z$r1iAU$7$FM_$7$$$H$-$O$I$&$9$l$PNI$$$G$7$g$&\e(B? \e$B$=$l$O\e(B
+\e$BIT2DG=$G!"$*$=$i$/$=$l$,IT2DG=$G$"$C$F$b$"$J$?$O9,$;$G$7$g$&!#\e(B
+
+@kindex M-i (\e$B35N,\e(B)
+@findex gnus-symbolic-argument
+\e$B;d$O$=$&$G$O$"$j$^$;$s!#$G$9$+$i!";d$OFs$D$a$N@\F,0z\e(B
+\e$B?t\e(B---@dfn{\e$B%7%s%\%k@\F,0z?t\e(B} \e$B$r2C$($^$7$?!#@\F,%-!<\e(B
+\e$B$O\e(B @kbd{M-i} (@code{gnus-symbolic-argument}) \e$B$G!"<!$K2!$5$l$kJ8;z$,CM$G\e(B
+\e$B$9!#K>$`$@$1B?$/$N\e(B @kbd{M-i} \e$B@\F,8l$r@Q$_=E$M$k;v$,$G$-$^$9!#\e(B
+@kbd{M-i a C-M-u} \e$B$O\e(B ``\e$BL?Na\e(B @kbd{C-M-u} \e$B$K%7%s%\%k@\F,0z?t\e(B @code{a} \e$B$rM?\e(B
+\e$B$($k\e(B'' \e$B$H$$$&$3$H$G$9!#\e(B@kbd{M-i a M-i b C-M-u} \e$B$OL?Na\e(B @kbd{C-M-u} \e$B$K%7%s\e(B
+\e$B%\%k@\F,0z?t\e(B @code{a} @code{b} \e$B$rM?$($k\e(B'' \e$B$H$$$&;v$G$9!#<q;]$OJ,$+$C$?$G\e(B
+\e$B$7$g$&!#\e(B
+
+\e$B%7%s%\%k@\F,0z?t$r<u$1IU$1$J$$L?Na$K$=$l$rBG80$9$k;v$O2?$b0-$$;v$r$7$^$;\e(B
+\e$B$s$,!"NI$$;v$b2?$b$7$^$;$s!#8=:_$N$H$3$m!"$"$^$jB?$/$N4X?t$,%7%s%\%k@\F,\e(B
+\e$B0z?t$rLrN)$F$F$$$k$o$1$G$O$"$j$^$;$s!#\e(B
+
+\e$B$b$7$I$N$h$&$K\e(B gnus \e$B$,$3$l$r<BAu$7$F$$$k$+$K6=L#$,$"$k$J$i!"\e(B
+@ref{Extended Interactive} \e$B$r8+$F$/$@$5$$!#\e(B
+
+@node Formatting Variables
+@section \e$B=qK!;EMMJQ?t\e(B
+@cindex formatting variables
+
+\e$B$3$N%^%K%e%"%k$rDL$7$F!"$"$J$?$O$*$=$i\e(B
+\e$B$/\e(B @code{gnus-group-line-format} \e$B$^$?\e(B
+\e$B$O\e(B @code{gnus-summary-mode-line-format} \e$B$N$h$&$K8F$P$l$k$?$/$5$s$NJQ?t$,\e(B
+\e$B$"$k;v$K5$IU$$$?$G$7$g$&!#$3$l$i$O\e(B gnus \e$B$,?'!9$J%P%C%U%!$G$I$N$h$&$K9T$r\e(B
+\e$B=PNO$9$k$+$r@)8f$7$^$9!#Hs>o$K$?$/$5$s$N$b$N$,$"$j$^$9!#9,1?$J;v$K!"$=$l\e(B
+\e$B$i$O$9$Y$FF1$89=J8$r;H$$$^$9$N$G!"$"$^$j7y$JL\$K$O2q$o$J$$$G$7$g$&!#\e(B
+
+\e$B=qK!;EMM\e(B (format) \e$B;XDj$NNc$,$"$j$^$9\e(B (\e$B%0%k!<%W%P%C%U%!$h$j\e(B):
+@samp{%M%S%5y: %(%g%)\n}\e$B!#$=$l$O<B:]$KHs>o$K=9$/!"$?$/$5$s$N%Q!<%;%s%H5-\e(B
+\e$B9f$,$I$3$K$G$b$"$j$^$9!#\e(B
+
+@menu
+* Formatting Basics::           \e$B=qK!;EMMJQ?t$O4pK\E*$K=qK!;XDjJ8;zNs$G$"$k\e(B
+* Mode Line Formatting::        \e$B%b!<%I9T$N=qK!;EMMJQ?t$K4X$9$k$$$/$D$+$N5,B'\e(B
+* Advanced Formatting::         \e$B?'!9$JJ}K!$G=PNO$r=$@5$9$k\e(B
+* User-Defined Specs::          Gnus \e$B$K$"$J$?<+?H$N4X?t$r8F$P$;$k\e(B
+* Formatting Fonts::            \e$B;EMM$rB?:L$GAGE($K8+$;$k\e(B
+* Positioning Point::           \e$BA`:n$N8e$G%]%$%s%H$r0\F0$9$k\e(B
+* Tabulation::                  \e$B=PNO$N@0Ns\e(B
+* Wide Characters::             \e$BI}$,9-$$J8;z$r07$&\e(B
+@end menu
+
+\e$B8=:_$N$H$3$m!"\e(Bgnus \e$B$O0J2<$N=qK!;EMMJQ?t$r;H$$$^$9\e(B:
+@code{gnus-group-line-format}, @code{gnus-summary-line-format},
+@code{gnus-server-line-format}, @code{gnus-topic-line-format},
+@code{gnus-group-mode-line-format}, @code{gnus-summary-mode-line-format},
+@code{gnus-article-mode-line-format}, @code{gnus-server-mode-line-format},
+@code{gnus-summary-pick-line-format}\e$B!#\e(B
+
+\e$B$3$l$iA4$F$N=qK!;EMMJQ?t$OG$0U$N\e(B elisp \e$B<0$G$"$k;v$b$G$-$^$9!#$=$N>l9g$O!"\e(B
+\e$B$=$l$i$OMW5a$5$l$k9T$KA^F~$9$k$?$a$K\e(B @code{\e$BI>2A\e(B} \e$B$5$l$^$9!#\e(B
+
+@kindex M-x gnus-update-format
+@findex gnus-update-format
+Gnus \e$B$O$"$J$?<+?H$N=qK!;EMM;XDj$r:n$k<jEA$$$r$9$kL?Na$rHw$($F$$$^$9!#\e(B
+@kbd{M-x gnus-update-format} \e$B$O8=:_$N<0$r\e(B @code{\e$BI>2A\e(B} \e$B$7!"Ev$N;XDj$r99?7\e(B
+\e$B$7!"7k2L$N\e(B Lisp \e$B<0$r<B9T$7$F9T$r:n@.$9$k;v$r<B83$G$-$k%P%C%U%!$K0\F0$7$^\e(B
+\e$B$9!#\e(B
+
+@node Formatting Basics
+@subsection \e$B=qK!;EMM$N4pK\\e(B
+
+\e$B$=$l$>$l$NMWAG\e(B @samp{%} \e$B$OEv$N%P%C%U%!$,:n@.$5$l$k$H$-$K2?$i$+$NJ8;zNs$d\e(B
+\e$BB>$N$b$N$GCV$-49$($i$l$^$9!#\e(B@samp{%5y} \e$B$O\e(B ``@samp{y} \e$B;XDj$rA^F~$7!"\e(B5 \e$BJ8\e(B
+\e$B;z$N>l=j$rF@$k$?$a$K6uGr$rF~$l$J$5$$\e(B'' \e$B$H$$$&;v$G$9!#\e(B
+
+\e$BIaDL$N\e(B C \e$B$d\e(B Emacs Lisp \e$B$N=qK!;EMM\e(B (format) \e$BJ8;zNs$HF1$8$h$&$K!"\e(B
+@samp{%} \e$B$H=qK!;EMM$N7?$NJ8;z$N4V$N?tCM=$>~;R$O>o$K>/$J$/$H$b$=$ND9$5$K\e(B
+\e$B$J$k$h$&$K!"=PNO$K\e(B @dfn{\e$B5M$a\e(B} \e$B$l$i$l$^$9!#\e(B@samp{%5y} \e$B$O$=$NItJ,$r>o\e(B
+\e$B$K\e(B (\e$B>/$J$/$H$b\e(B) 5 \e$BJ8;z$ND9$5$K$J$k$h$&$K!":8$K6uGr$r5M$a$^$9!#$b\e(B
+\e$B$7\e(B @samp{%-5y} \e$B$H$9$l$P!"Be$o$j$K1&B&$K5M$a9~$_$^$9!#\e(B
+
+\e$BFC$KD9$$CM$+$i$=$NItJ,$rJ]8n$9$k$?$a$K!"D9$5$r@)8B$7$?$$$H$b;W$&$G$7$g$&!#\e(B
+\e$B$=$N$?$a$K$O!"\e(B@samp{%4,6y} \e$B$H$9$k;v$,$G$-$F!"$3$l$O$=$NNN0h$O7h$7$F\e(B 6 \e$BJ8\e(B
+\e$B;z$rD6$($kD9$5$K$O$J$i$:!"\e(B4 \e$BJ8;z$h$j>/$J$$D9$5$K$J$i$J$$$H$$$&;v$G$9!#\e(B
+
+gnus \e$B$O\e(B @samp{%&user-date;} \e$B$N$h$&$J!"$$$/$D$+$N3HD%MM<0;X<($b%5%]!<%H$7\e(B
+\e$B$^$9!#\e(B
+
+@node Mode Line Formatting
+@subsection \e$B%b!<%I9T=qK!;EMM\e(B
+
+\e$B%b!<%I9T=qK!;EMMJQ?t\e(B (\e$B$9$J$o$A!"\e(B@code{gnus-summary-mode-line-format}) \e$B$O\e(B
+\e$B0J2<$NFs$D$N0c$$0J30$O!"%P%C%U%!9T$K4p$E$/=qK!;EMMJQ?t\e(B
+\e$B$H\e(B (@pxref{Formatting Basics}) \e$BF1$8$h$&$J5,B'$K=>$$$^$9\e(B:
+
+@enumerate
+
+@item
+\e$B:G8e$K2~9T\e(B (@samp{\n}) \e$B$,$"$C$F$O$J$j$^$;$s!#\e(B
+
+@item
+\e$BFCJL$J\e(B @samp{%%b} \e$B;XDj$r%P%C%U%!L>$rI=<($9$k$?$a$K;H$&$3$H$,$G$-$^$9!#$(!<\e(B
+\e$B$H!"K\Ev$O$=$l$O;XDj$G$O$J$$$N$G$9\e(B---@samp{%%} \e$B$OC1$K=qK!;EMM$,5!3#E*$K\e(B
+\e$B@Z$jNv$/$N$r@Z$jH4$1$F\e(B @samp{%} \e$B$r$=$N$^$^EO$9$?$a$NJ}K!$G!"\e(B
+Emacs \e$B$,\e(B @samp{%b} \e$B$r<u$1<h$k$H!"\e(BEmacs \e$B$N%b!<%I9TI=<($NItJ,$,$=$l\e(B
+\e$B$r\e(B ``\e$B%P%C%U%!L>$rI=<($7$J$5$$\e(B'' \e$B$H2r<a$7$^$9!#\e(BEmacs \e$B$,M}2r$9$k%b!<%I9T;X\e(B
+\e$BDj$N40A4$J0lMw$r8+$k$?$a$K$O!"JQ?t\e(B @code{mode-line-format} \e$B$N@bL@J8$r8+\e(B
+\e$B$F2<$5$$!#\e(B
+
+@end enumerate
+
+@node Advanced Formatting
+@subsection \e$B>e5i=qK!;EMM\e(B
+
+\e$B2?$i$+$NJ}K!$GNN0h$r8e$G=hM}$9$k$N$OIQHK$KLr$KN)$A$^$9!#ItJ,$r5M$a9~$`!"\e(B
+\e$B@)8B$9$k!"@Z$j<h$k$3$H$HFCDj$NCM$rM^@)$9$k;v$O!"\e(B@dfn{\e$B%A%k%@=$>~;R\e(B} \e$B$r;H\e(B
+\e$B$&;v$K$h$jC#@.$5$l$^$9!#$h$/$"$k%A%k%@;XDj$O$3$N$h$&$K8+$($k$+$b$7$l$^$;\e(B
+\e$B$s\e(B @samp{%~(cut 3)~(ignore "0")y}\e$B!#\e(B
+
+\e$B$3$l$i$OM-8z$J=$>~;R$G$9\e(B:
+
+@table @code
+@item pad
+@itemx pad-left
+\e$BMW5a$5$l$?D9$5$K$J$k$^$G!"NN0h$K6uGr$r:8B&$+$i5M$a9~$_$^$9!#\e(B
+
+@item pad-right
+\e$BMW5a$5$l$?D9$5$K$J$k$^$G!"NN0h$K6uGr$r1&B&$+$i5M$a9~$_$^$9!#\e(B
+
+@item max
+@itemx max-left
+\e$B;XDj$5$l$?D9$5$K$J$k$h$&$K!"J8;z$r:8B&$+$i@Z$j<h$j$^$9!#\e(B
+
+@item max-right
+\e$B;XDj$5$l$?D9$5$K$J$k$h$&$K!"J8;z$r1&B&$+$i@Z$j<h$j$^$9!#\e(B
+
+@item cut
+@itemx cut-left
+\e$B;XDj$5$l$??t$NJ8;z$r:8B&$+$i@Z$jMn$H$7$^$9!#\e(B
+
+@item cut-right
+\e$B;XDj$5$l$??t$NJ8;z$r1&B&$+$i@Z$jMn$H$7$^$9!#\e(B
+
+@item ignore
+\e$BNN0h$,;XDj$5$l$?CM$HEy$7$1$l$P\e(B (equal)\e$B!"6uJ8;zNs$rJV$7$^$9!#\e(B
+
+@item form
+@samp{@@} \e$B;XDj$,;H$o$l$?$H$-$K!";XDj$5$l$?<0$rNN0h$NCM$H$7$F;H$$$^$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@lisp
+"~(form (current-time-string))@@"
+@end lisp
+@end table
+
+\e$BNc$r=P$7$F$_$^$7$g$&!#35N,%b!<%I9T$G$N\e(B @samp{%o} \e$B;XDj$O>.7?$N\e(B ISO0861 \e$BMM\e(B
+\e$B<0$NF|IU$rJV$7$^$9\e(B---@samp{19960809T230410} \e$B$G$9!#$3$l$OH/2;$7$K$/$$$N$G!"\e(B
+\e$B@$5*$rI=$9?t$H;~4V$r:o$.Mn$H$7$F!"\e(B6 \e$BJ8;z$NF|IU$r;D$7$?$$$H;W$$$^$9!#$=$l\e(B
+\e$B$O\e(B @samp{%~(cut-left 2)~(max-right 6)~(pad 6)o} \e$B$H$J$k$G$7$g$&!#\e(B(\e$B@Z$jMn\e(B
+\e$B$H$7\e(B (cutting) \e$B$O\e(B \e$B:GBg8B\e(B (maxing) \e$B$h$j@h$K$J$5$l$^$9$N$G!"7e$GAGE($K8+$(\e(B
+\e$B$k$h$&$K$9$k$?$a$KF|IU$,\e(B 6 \e$BJ8;z$h$j>/$J$/L5$/$J$i$J$$;v$rJ]>Z$9$k$?$a$K\e(B
+\e$B5M$a9~$_\e(B (padding) \e$B$,I,MW$K$J$j$^$9!#\e(B)
+
+\e$BL5;k\e(B (ignore) \e$B$,:G=i$K$J$5$l$^$9!#$=$l$+$i@Z$jMn$H$7\e(B (cut) \e$B$,9T$o$l$^$9!#\e(B
+\e$B$=$7$F!"$=$l$+$i:G8e$NA`:n!"5M$a9~$_\e(B (pad) \e$B$,9T$o$l$^$9!#\e(B
+
+@vindex gnus-compile-user-specs
+\e$B$b$7$"$J$?$,6/$$8D@-$N;}$A<g$G\e(B @code{gnus-compile-user-specs} \e$B$r\e(B
+@code{nil} \e$B$K$7$F$$$F\e(B (\e$B=i4|CM$O\e(B@code{t})\e$B!"$3$l$i$N>e5i;2>H$r$?$/$5$s;H$C\e(B
+\e$B$F$$$k$J$i!"\e(BT-gnus \e$B$,$H$F$bCY$/$J$k$N$,$o$+$k$G$7$g$&!#$3$l$O$"$J$?$,9T\e(B
+\e$B$N308+$KK~B-$7$?$H$-$K\e(B @kbd{M-x gnus-compile} \e$B$r<B9T$9$k;v$G3JCJ$KB.EYDc\e(B
+\e$B2<$r8:$i$9;v$,$G$-$^$9!#\e(B@xref{Compilation}.
+
+@node User-Defined Specs
+@subsection \e$BMxMQ<TDj5A$N;XDj\e(B
+
+\e$BA4$F$N;XDj$OMxMQ<TDj5A\e(B---@samp{u} \e$B$N;XDj$rA^F~$9$k;v$,$G$-$^$9!#=qK!;EMM\e(B
+\e$BJ8;zNs$N<!$NJ8;z$O%"%k%U%!%Y%C%H$G$"$kI,MW$,$"$j$^$9!#\e(BGnus \e$B$O4X\e(B
+\e$B?t\e(B @code{gnus-user-format-function-}@samp{X} \e$B$r8F$S!"$3$3\e(B
+\e$B$G\e(B @samp{X} \e$B$O\e(B @samp{%u} \e$B$KB3$/%"%k%U%!%Y%C%H$G$9!#4X?t$K$OC10l$N0z?t$,\e(B
+\e$BM?$($i$l$^$9\e(B---\e$B0z?t$N0UL#$O4X?t$,$I$N%P%C%U%!$+$i8F$P$l$F$$$k$+$K$h$C$F\e(B
+\e$BJQ$o$j$^$9!#4X?t$OJ8;zNs$rJV$9$Y$-$G!"$=$l$OB>$N;XDj$+$i$N>pJs$HA4$/F1$8\e(B
+\e$B$h$&$K%P%C%U%!$KA^F~$5$l$^$9!#4X?t$O0UL#$NL5$$CM$H6&$K8F$P$l$k;v$b$"$j$(\e(B
+\e$B$^$9$N$G!"$=$l$NBP:v$r$9$k$Y$-$G$9!#\e(B
+
+gnus \e$B$O\e(B @samp{%u&foo;} \e$B$N$h$&$J3HD%MxMQ<TDj5A;X<($b%5%]!<%H$7$^$9!#\e(B
+gnus \e$B$O4X?t\e(B @code{gnus-user-format-function-}@samp{foo} \e$B$r8F$S=P$7$^$9!#\e(B
+
+\e$B?7$7$$4X?t$rDj5A$7$J$$$G$b!"%A%k%@=$>~\e(B
+\e$B;R\e(B (@pxref{Advanced Formatting}) \e$B$r;H$C$F$[$H$s$IF1$8;v$rC#@.$9$k;v$,$G\e(B
+\e$B$-$^$9!#Nc$G$9\e(B: @samp{%~(form (count-lines (point-min) (point)))@@}\e$B!#\e(B
+\e$B$3$3$GM?$($i$l$?<0$OI>2A$5$l$F!"8=:_$N9T?t$r$b$?$i$7!"$=$l$+$iA^F~$5$l$^\e(B
+\e$B$9!#\e(B
+
+@node Formatting Fonts
+@subsection \e$B=qK!;EMM%U%)%s%H\e(B
+
+\e$B%O%$%i%$%H$N$?$a$N;XDj$,$"$j!"$=$l$i$OA4$F$N=qK!;EMMJQ?t$K$h$C$F6&M-$5$l\e(B
+\e$B$F$$$^$9!#\e(B@samp{%(} \e$B$H\e(B @samp{%)} \e$B;XDj$N4V$NJ8>O$OFCJL\e(B
+\e$B$J\e(B @code{mouse-face} \e$B%W%m%Q%F%#$,@_Dj$5$l!"$=$l$O$=$3$K%^%&%9$N%]%$%s%?!<\e(B
+\e$B$r$"$o$;$?$H$-$K\e(B (@code{gnus-mouse-face} \e$B$K$h$C$F\e(B) \e$B%O%$%i%$%H$5$l$k$3$H\e(B
+\e$B$K$J$j$^$9!#\e(B
+
+@samp{%@{} \e$B$H\e(B @samp{%@}} \e$B;XDj$N4V$NJ8>O$O\e(B @code{gnus-face-0} \e$B$r;H$C$FIa\e(B
+\e$BDL$N%U%'%$%9$,@_Dj$5$l!"$=$l$O=i4|@_Dj$G\e(B @code{bold} \e$B$G$9!#$b\e(B
+\e$B$7\e(B @samp{%@{1} \e$B$H$7$?$J$i!"Be$o$j$K\e(B @code{gnus-face-1} \e$B$rF@!"0J2<F1MM$G\e(B
+\e$B$9!#M_$7$$$@$1$?$/$5$s$N%U%'%$%9$r:n$C$F$/$@$5$$!#F1$8;v\e(B
+\e$B$,\e(B @code{mouse-face} \e$B;XDj$K$b8@$($^\e(B
+\e$B$9\e(B---@samp{hello} \e$B$,\e(B @code{gnus-mouse-face-3} \e$B$G%^%&%9!]%O%$%i%$%H$5$l$k\e(B
+\e$B$?$a$K$O!"\e(B@samp{%3(hello%)} \e$B$H$9$k;v$,$G$-$^$9!#\e(B
+
+@samp{%<<} \e$B$H\e(B @samp{%>>} \e$B;X<(;R$N4V$N%F%-%9%H$OFCJL\e(B
+\e$B$J\e(B @code{balloon-help} \e$B%W%m%Q%F%#$,\e(B @code{gnus-balloon-face-0} \e$B$K@_Dj$5\e(B
+\e$B$l$^$9!#\e(B@samp{%1<<} \e$B$H$9$k$H!"\e(B@code{gnus-balloon-face-1} \e$B$rF@$F!"B>$bF1\e(B
+\e$BMM$G$9!#\e(B@code{gnus-balloon-face-*} \e$BJQ?t$OJ8;zNs$+J8;zNs$rJV$94X?t$r;X$9\e(B
+\e$B%7%s%\%k$N$I$A$i$+$G$"$kI,MW$,$"$j$^$9!#%^%&%9$,%W%m%Q%F%#$N@_Dj$5$l$F$$\e(B
+\e$B$k%F%-%9%H$N>e$rDL2a$9$k$H!"%P%k!<%s%&%#%s%I%&$,8=$l$F!"J8;zNs$rI=<($7$^\e(B
+\e$B$9!#$3$l$N>\$7$$>pJs$O\e(B @ref{Tooltips, ,Tooltips, emacs, The Emacs
+Manual} (GNU Emacs) \e$B$^$?$O\e(B @code{balloon-help-mode} (XEmacs) \e$B$N@bL@J8;z\e(B
+\e$BNs$r;2>H$7$F$/$@$5$$!#\e(B(\e$B5;=QE*$JM}M3$N$?$a$K!"%.%#%a\e(B (guillemets:
+@footnote{guillemets (\e$BJ)8l\e(B) \e$B$O%.%e%a$H$bI=5-$5$l$^$9!#F|K\8l$N!V!W$KEv$?\e(B
+\e$B$k$b$N$G!"8}F,I=8=$rI=5-$7$?$j!"6/D4$7$?$$C18l$r0O$`!"2?$+$+$i$N0zMQItJ,\e(B
+\e$B$r0O$`!"=qJ*Ey$N%?%$%H%k$r5-$9EyMM!9$K;H$o$l$^$9!#\e(B}) \e$B$O$3$N@a$G\e(B
+\e$B$O\e(B @samp{<<} \e$B$*$h$S\e(B @samp{>>} \e$B$H$7$F6a;w$5$l$^$7$?!#\e(B)
+
+\e$B$3$l$O%0%k!<%W%P%C%U%!$NBeBX<jK!$G$9\e(B:
+
+@lisp
+;; @r{\e$B;0$D$N%U%'%$%9$N7?$r:n$k!#\e(B}
+(setq gnus-face-1 'bold)
+(setq gnus-face-3 'italic)
+
+;; @r{\e$B2f!9$O5-;v$N?t$r%\!<%k%I$GNP$N%U%'%$%9\e(B}
+;; @r{\e$B$K$7$?$$$N$G!"\e(B@code{my-green-bold} \e$B$H8F$P$l$k\e(B}
+;; @r{\e$B?7$7$$%U%'%$%9$r:n$C$?!#\e(B}
+(copy-face 'bold 'my-green-bold)
+;; @r{\e$B?'$r@_Dj$9$k!#\e(B}
+(set-face-foreground 'my-green-bold "ForestGreen")
+(setq gnus-face-2 'my-green-bold)
+
+;; @r{\e$B?7$7$$>eEy$N=qK!;EMM$r@_Dj$9$k!#\e(B}
+(setq gnus-group-line-format
+      "%M%S%3@{%5y%@}%2[:%] %(%1@{%g%@}%)\n")
+@end lisp
+
+\e$B$"$J$?$,$3$N0F$r;H$C$F40A4$KFI$a$J$/$FHs>o$K2<IJ$JI=<($r:n$k;v$,$G$-$k$H\e(B
+\e$B3N?.$7$F$$$^$9!#3Z$7$s$G$/$@$5$$\e(B!
+
+@samp{%(} \e$B;XDj\e(B (\e$B$d$=$NN`$N$b$N\e(B) \e$B$O%b!<%I9TJQ?t$G$OA4$/0UL#$r$J$5$J$$;v$K\e(B
+\e$BCm0U$7$F$/$@$5$$!#\e(B
+
+@node Positioning Point
+@subsection \e$B%]%$%s%H$N0\F0\e(B
+
+gnus \e$B$ODL>o$[$H$s$I$N%P%C%U%!$G!"%]%$%s%H$r3F9T$N$"$i$+$8$a7h$a$i$l$?>l\e(B
+\e$B=j$K0\F0$7$^$9!#%G%#%U%)%k%H$G$O!"%]%$%s%H$O9T$N:G=i$N%3%m%s$K0\F0$7$^$9!#\e(B
+\e$B$"$J$?$O$3$N?6$k$^$$$r!";0$D$N0c$&J}K!$G%+%9%?%^%$%:$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$^$?!"$"$J$?$O%3%m%s$r9T$N$I$N>l=j$K$G$b0\F0$9$k$3$H$,$G$-$^$9!#\e(B
+
+@findex gnus-goto-colon
+\e$B$"$J$?$O%3%m%s$N0LCV$K%]%$%s%H$r0\F0$5$;$k$?$a$N4X?t$rDj5A$7D>$9$3$H$,$G\e(B
+\e$B$-$^$9!#$=$N4X?t$O\e(B @code{gnus-goto-colon} \e$B$H8F$P$l$F$$$^$9!#\e(B
+
+\e$B$G$b!"$b$7$"$J$?$,9T$K%3%m%s$r4^$a$?$/$J$$$J$i$P!"$3$l$r07$&$?$a$N$*$=$i\e(B
+\e$B$/:G$b<j$4$m$JJ}K!$O\e(B @samp{%*} \e$B;X<(;R$r;H$&$3$H$G$9!#$"$J$?$N9T$N=qK!;E\e(B
+\e$BMM$NDj5A$K\e(B @samp{%*} \e$B$rF~$l$F$*$1$P!"\e(Bgnus \e$B$O$=$3$K%]%$%s%H$rCV$-$^$9!#\e(B
+
+@node Tabulation
+@subsection \e$B@0Ns\e(B
+
+\e$B$"$J$?$ODL>o$O!"1d$P$7$?$j=L$a$?$j$7$FJ8;zNs$r%G%#%9%W%l%$$KJB$Y$k$3$H$,\e(B
+\e$B$G$-$^$9!#$G$bBg$-$5$,0c$&0[$J$kJ8;zNs$rO"7k$5$;$k>l9g$O!"C1$KJ8;zNs$r=P\e(B
+\e$BNO$7$F$7$^$&$N$,$h$j<j$4$m$G$"$k$3$H$,B?$$$O$:$G!"$7$+$7$=$&$9$k$H$=$N8e\e(B
+\e$B$KB3$/%F%-%9%H$rJB$Y$k$N$KG:$`$3$H$K$J$j$^$9!#\e(B
+
+\e$B$=$l$r9T$J$&$?$a!"\e(Bgnus \e$B$O@0Ns;R\e(B (tabulator) \e$B$N;XDj\e(B @samp{%=} \e$B$rHw$($F$$\e(B
+\e$B$^$9!#$3$l$K$OFs$D$N7A\e(B
+\e$B<0\e(B @dfn{hard tabulators} \e$B$H\e(B @dfn{soft tabulators} \e$B$,$"$j$^$9!#\e(B
+
+@samp{%50=} \e$B$OJ8;zNs$,\e(B 50\e$B7e$+$i;O$^$k$h$&$K6uGrJ8;z$r5M$a9~$_$^$9!#$b\e(B
+\e$B$7\e(B 50\e$B7e$h$j8e$m$K$9$G$K%F%-%9%H$,$"$k>l9g$O2?$bA^F~$7$^$;$s!#$3$l$O2:$d\e(B
+\e$B$+\e(B (soft) \e$B$J@0Ns;R$G$9!#\e(B
+
+@samp{%-50=} \e$B$b$^$?!"J8;zNs$,\e(B 50\e$B7e$+$i;O$^$k$h$&$K6uGrJ8;z$r5M$a9~$_$^$9!#\e(B
+\e$B$G$9$,!"$b$7\e(B 50\e$B7e$h$j8e$m$K$9$G$K%F%-%9%H$,$"$k>l9g!"\e(B50\e$B7e$h$j8e$m$K$"$k\e(B
+\e$B2a>j$J%F%-%9%H$O:o=|$5$l$^$9!#$3$l$O87L)\e(B (hard) \e$B$J@0Ns;R$G$9!#\e(B
+
+@node Wide Characters
+@subsection Wide Characters
+
+\e$BB?$/$NCO0h$K$*$$$F!"8GDjI}%U%)%s%H$OF1$8I}$NJ8;z$r;}$C$F$$$^$9!#$7$+$7$$\e(B
+\e$B$/$D$+$NCO0h!"$h$/CN$i$l$F$$$kEl%"%8%"$N9q!9$G$O!"%i%F%sJ8;z$HI}$N9-$$J8\e(B
+\e$B;z$,:.:_$7$F;H$o$l$F$$$^$9!#\e(B
+
+\e$B@07A$K$*$$$F!"\e(Bgnus \e$B$OJ8;zNs$,\e(B 10\e$B8D$NJ8;z$NI}$@$H$7$?$i!"%9%/%j!<%s$G\e(B
+\e$B$b\e(B 10\e$B8DJ,$N%i%F%sJ8;z$NI}$K$J$k$H2>Dj$7$^$9$,!"$=$l$OLdBj$G$9!#$+$N9q!9\e(B
+\e$B$G$O!"$=$l$O@5$7$/$"$j$^$;$s!#\e(B
+
+@vindex gnus-use-correct-string-widths
+\e$B$=$l$r5_:Q$9$k$?$a$K!"$"$J$?\e(B
+\e$B$O\e(B @code{gnus-use-correct-string-widths} \e$B$r\e(B @code{t} \e$B$K@_Dj$9$k$3$H$,$G\e(B
+\e$B$-$^$9!#$3$l$O%P%C%U%!$N@8@.$rCY$/$7$^$9$,!"$h$jH~$7$$7k2L$rF@$k$3$H$,$G\e(B
+\e$B$-$k$G$7$g$&!#4{DjCM$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@node Window Layout
+@section \e$B%&%#%s%I%&$NG[CV\e(B
+@cindex window layout
+
+\e$B$$$(!"\e(BX \e$B$K4X$9$k;v$O$"$j$^$;$s$N$G!"$*$H$J$7$/$7$F2<$5$$!#\e(B
+
+@vindex gnus-use-full-window
+\e$B$b$7\e(B @code{gnus-use-full-window} \e$B$,\e(B @code{nil} \e$B$G$J$$$H!"\e(Bgnus \e$B$OA4$F$NB>\e(B
+\e$B$N%&%#%s%I%&$r>C$7$F!"\e(BEmacs \e$B$N2hLLA4BN$r@jM-$7$^$9!#$3$l$O=i4|@_Dj\e(B
+\e$B$G\e(B @code{t} \e$B$G$9!#\e(B
+
+\e$B$3$NJQ?t$r\e(B @code{nil} \e$B$K@_Dj$9$k$N$O$=$l$J$j$KF0:n$7$^$9$,!"LdBj$b$"$j$^\e(B
+\e$B$9!#4m81$r3P8g$N>e$G;H$C$F$/$@$5$$!#\e(B
+
+@vindex gnus-buffer-configuration
+@code{gnus-buffer-configuration} \e$B$O$=$l$>$l$N\e(B gnus \e$B$N%P%C%U%!$,$I$N$/$i\e(B
+\e$B$$$N6u4V$rM?$($i$l$k$Y$-$+$r8=$7$^$9!#$3$l$O$3$NJQ?t$NH4?h$G$9\e(B:
+
+@lisp
+((group (vertical 1.0 (group 1.0 point)
+                      (if gnus-carpal (group-carpal 4))))
+ (article (vertical 1.0 (summary 0.25 point)
+                        (article 1.0))))
+@end lisp
+
+\e$B$3$l$OO"A[%j%9%H$G$9!#\e(B@dfn{\e$B%-!<\e(B} \e$B$O2?$i$+$NF0:n$dB>$N$b$N$rG$L?$9$k%7%s\e(B
+\e$B%\%k$G$9!#Nc$($P!"%0%k!<%W%P%C%U%!$rI=<($9$k$H$-$O!"%&%#%s%I%&@_Dj4X?t\e(B
+\e$B$O\e(B @code{group} \e$B$r%-!<$H$7$F;H$$$^$9!#;HMQ2DG=$JL>A0$N40A4$J0lMw$O2<$K5s\e(B
+\e$B$2$i$l$F$$$^$9!#\e(B
+
+@dfn{\e$BCM\e(B} (\e$B$9$J$o$A!"\e(B@dfn{\e$BJ,3d\e(B}) \e$B$O$=$l$>$l$N%P%C%U%!$,$I$l$/$i$$$r@j$a$k\e(B
+\e$B$Y$-$+$r;XDj$7$^$9!#\e(B@code{article} \e$BJ,3d$rNc$K<h$k$H\e(B -
+
+@lisp
+(article (vertical 1.0 (summary 0.25 point)
+                       (article 1.0)))
+@end lisp
+
+\e$B$3$N\e(B @dfn{\e$BJ,3d\e(B} \e$B$O35N,%P%C%U%!\e(B (summary buffer) \e$B$,2hLL$N>e$N\e(B 25% \e$B$r@j$a\e(B
+\e$B$k$Y$-$G!"$=$l$O5-;v%P%C%U%!\e(B (article buffer) \e$B$N>e$KG[CV$5$l$^$9!#$*5$$E\e(B
+\e$B$-$NDL$j!"\e(B100% + 25% \e$B$O<B:]$O\e(B 125% \e$B$G$9\e(B (\e$B$($'!"3'$5$s$N7W;;$O$3$NMM$K$J$C\e(B
+\e$B$?$H;W$$$^$9!#\e(B) \e$B$7$+$7!"FCJL$J?t;z\e(B @code{1.0} \e$B$O!";D$j$N%P%C%U%!$,I,MW$J\e(B
+\e$B$b$N$r<h$j5n$C$?8e$K!";HMQ2DG=$J;D$j$N6u4VA4$F$r5[$$<h$k!"$H$$$&;v$r9g?^\e(B
+\e$B$9$k$?$a$K;H$o$l$^$9!#0l$D$NJ,3d$K$D$-!"\e(B@code{1.0} \e$B$NBg$-$5;XDj$N%P%C%U%!\e(B
+\e$B$O0l$D$@$1$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+\e$B%]%$%s%H$O>JN,2DG=$J;0$DL\$NMWAG!"\e(B@code{point} \e$B$r;}$D%P%C%U%!$KCV$+$l$^\e(B
+\e$B$9!#\e(B@code{frame} \e$BJ,3d$G$O!"%?%0\e(B @code{frame-focus} \e$B$,9=@.MWAG$G$"$k\e(B (\e$B$9\e(B
+\e$B$J$o$A!"\e(B@code{point} \e$B%?%0$,B8:_$9$k$+$I$&$+$K$h$C$F!"%j%9%H$N;0HVL\$+;M\e(B
+\e$BHVL\$+$KB8:_$9$kMWAG\e(B) \e$BMUJ,3d$r;}$D:G8e$NI{J,3d$,>GE@$rF@$k;v$K$J$j$^$9!#\e(B
+
+\e$B<!$O$b$C$HJ#;($JNc$G$9\e(B:
+
+@lisp
+(article (vertical 1.0 (group 4)
+                       (summary 0.25 point)
+                       (if gnus-carpal (summary-carpal 4))
+                       (article 1.0)))
+@end lisp
+
+\e$B$b$7Bg$-$5;XDj$,IbF0>.?tE@?t$NBe$o$j$K@0?t$G$"$C$?$J$i!"$=$l$O3d9g$G$O$J\e(B
+\e$B$/!"$I$N$/$i$$B?$/$N9T$r%P%C%U%!$,@j$a$k$Y$-$+$r;XDj$9$k$?$a$K;H$o$l$^$9!#\e(B
+
+\e$B$b$7\e(B @dfn{\e$BJ,3d\e(B} \e$B$,\e(B @code{\e$BI>2A\e(B} \e$B$5$l$k$b$N$N$h$&$K8+$($k$H$-$O\e(B (\e$BL@3N$K$9\e(B
+\e$B$k$H\e(B---\e$BJ,3d$N\e(B @code{car} \e$B$,4X?t$+86;O4X?t\e(B (subr) \e$B$G$"$k$H$-$O\e(B)\e$B!"$3$NJ,3d\e(B
+\e$B$O\e(B @code{\e$BI>2A\e(B} \e$B$5$l$^$9!#7k2L$,\e(B @code{nil} \e$B$G$J$$$J$i!"$=$l$OJ,3d$H$7$F\e(B
+\e$BMQ$$$i$l$^$9!#$3$l$O!"\e(B@code{gnus-carpal} \e$B$,\e(B @code{nil} \e$B$G$"$l$P;0$D$N%P%C\e(B
+\e$B%U%!$,!"\e(B@code{gnus-carpal} \e$B$,\e(B @code{nil} \e$B$G$J$$$J$i!";M$D$N%P%C%U%!$,B8\e(B
+\e$B:_$9$k$H$$$&;v$G$9!#\e(B
+
+\e$B$^$@J#;($G$O$J$$$G$9$C$F\e(B? \e$B$=$l$G$O!"Bg$-$5$K$3$l$r;n$7$F$_$F2<$5$$\e(B:
+
+@lisp
+(article (horizontal 1.0
+             (vertical 0.5
+                 (group 1.0)
+                 (gnus-carpal 4))
+             (vertical 1.0
+                 (summary 0.25 point)
+                 (summary-carpal 4)
+                 (article 1.0))))
+@end lisp
+
+\e$B$*$)$C$H!#Fs$D$N%P%C%U%!$KIT;W5D$J\e(B 100% \e$B%?%0$,IU$$$F$$$^$9!#$=$7$F!"$"\e(B
+\e$B$N\e(B @code{horizontal} \e$B$C$F$$$&$b$N$O2?$G$7$g$&\e(B?
+
+\e$B$b$7J,3d$N0l$D$N:G=i$NMWAG$,\e(B @code{horizontal} \e$B$G$"$C$?$J$i!"\e(Bgnus \e$B$O%&%#\e(B
+\e$B%s%I%&$r?eJ?$KJ,3d$7!"Fs$D$N%&%#%s%I%&$r2#$KJB$Y$^$9!#$3$l$i$N$=$l$>$l$N\e(B
+\e$B>.JR$NCf$G$O!"A4$F$rIaDL$NN.57$G9T$&;v$,$G$-$^$9!#\e(B@code{horizontal} \e$B$N8e\e(B
+\e$B$N?t;z$O!"$3$N>.JR$K2hLL$N$I$l$/$i$$$N3d9g$,M?$($i$l$k$+$r;XDj$7$^$9!#\e(B
+
+\e$B$=$l$>$l$NJ,3d$G$O!"\e(B100% \e$B$N%?%0$r;}$DMWAG$,\e(B @emph{\e$BI,$:\e(B} \e$B0l$D$"$kI,MW$,$"\e(B
+\e$B$j$^$9!#J,3d$O7h$7$F@53N$K$O9T$o$l$^$;$s$N$G!"$3$N%P%C%U%!$,J,3d$+$i;D$5\e(B
+\e$B$l$?A4$F$N9T$r@jNN$7$^$9!#\e(B
+
+\e$B$b$&>/$7@5<0$K$9$k$?$a$K!"$3$3$KM-8z$JJ,3d$,$I$N$h$&$K$J$k$+$NDj5A$,$"$j\e(B
+\e$B$^$9\e(B:
+
+@example
+split      = frame | horizontal | vertical | buffer | form
+frame      = "(frame " size *split ")"
+horizontal = "(horizontal " size *split ")"
+vertical   = "(vertical " size *split ")"
+buffer     = "(" buf-name " " size *[ "point" ] *[ "frame-focus"] ")"
+size       = number | frame-params
+buf-name   = group | article | summary ...
+@end example
+
+\e$B@)8B$K$O!"\e(B@code{frame} \e$B$O:G>e0L$NJ,3d$H$7$F$7$+8=$l$k;v$,$G$-$J$$$H$$$&\e(B
+\e$B$b$N$,$"$j$^$9!#\e(B@var{form} \e$B$OM-8z$JJ,3d$rJV$9\e(B Emacs Lisp \e$B$N<0\e(B (form) \e$B$G\e(B
+\e$B$J$1$l$P$J$j$^$;$s!#$=$l$>$l$NJ,3d$O40A4$K:F5"E*$G!"G$0U$N?t\e(B
+\e$B$N\e(B @code{vertical} \e$B$H\e(B @code{horizontal} \e$BJ,3d$r4^$`;v$,$G$-$^$9!#\e(B
+
+@vindex gnus-window-min-width
+@vindex gnus-window-min-height
+@cindex window height
+@cindex window width
+\e$B@5$7$$Bg$-$5$r8+$D$1$k$N$O>/$7J#;($G$9!#$I$N%&%#%s%I%&\e(B
+\e$B$b\e(B @code{gnus-window-min-height} (\e$B=i4|CM\e(B 1) \e$B$NJ8;z$N9b$5$h$j$b>.$5$/$F$O\e(B
+\e$B$J$i$:!">/$J$/$H$b\e(B @code{gnus-window-min-width} (\e$B=i4|CM\e(B 1) \e$B$NJ8;zI}$G$J\e(B
+\e$B$/$F$O$J$j$^$;$s!#\e(BGnus \e$B$OJ,3d$rE,MQ$9$kA0$K$3$l$r6/@)$7$h$&$H;n$_$^$9!#\e(B
+\e$B$b$7IaDL$N\e(B Emacs \e$B$N%&%#%s%I%&$NI}\e(B/\e$B9b$5@)8B$r;H$$$?$$$J$i!"$3$NFs$D$NJQ?t\e(B
+\e$B$r\e(B @code{nil} \e$B$K$9$k$@$1$GNI$$$G$9!#\e(B
+
+\e$B$b$7\e(B Emacs \e$B$NMQ8l$K$J$8$s$G$$$J$$$N$J$i!"\e(B
+@code{horizontal} \e$B$H\e(B @code{vertical} \e$BJ,3d$O!"4|BT$9$k$b$N$HH?BP$NF0:n$r\e(B
+\e$B$9$k$G$7$g$&!#\e(B@code{horizontal} \e$BJ,3d$NCf$N%&%#%s%I%&$O2#$KJB$s$GI=<($5$l!"\e(B
+@code{vertical} \e$BJ,3d$NCf$N%&%#%s%I%&$O>e2<$KI=<($5$l$^$9!#\e(B
+
+@findex gnus-configure-frame
+\e$B%&%#%s%I%&$N@_CV$K4X$7$F<B83$r$7$F$_$?$$$N$G$"$l$P!"$h$$J}K!$OJ,3d$GD>\e(B
+\e$B@\\e(B @code{gnus-configure-frame} \e$B$r8F$V$3$H$G$9!#$3$l$O%P%C%U%!$rJ,3d$9$k\e(B
+\e$B$H$-$KA4$F$NK\Ev$N;E;v$r$9$k4X?t$G$9!#2<$N$b$N$O\e(B 5 \e$B%&%#%s%I%&$N$H$F$b$P\e(B
+\e$B$+$2$?@_Dj$G$9!#Fs$D$r%0%k!<%W%P%C%U%!$K!";0$D$r5-;v%P%C%U%!$N$?$a$K=<$F\e(B
+\e$B$^$9!#\e(B(\e$B$=$l$O$P$+$2$F$$$k$H8@$C$?$G$7$g!#\e(B) \e$B$b$72<$NJ8$r\e(B @code{\e$BI>2A\e(B} \e$B$9$k\e(B
+\e$B$H!"IaDL$N\e(B gnus \e$B$N7PO)$r;H$o$J$$$G!"$9$0$K$=$l$,$I$N$h$&$K8+$($k$+$N9M$(\e(B
+\e$B$rF@$k;v$,$G$-$^$9!#K~B-$9$k$^$G$=$l$GM7$s$G!"$=$l$+\e(B
+\e$B$i\e(B @code{gnus-add-configuration} \e$B$r;H$C$F?7$7$$A[A|$r%P%C%U%!@_Dj%j%9%H\e(B
+\e$B$K2C$($F2<$5$$!#\e(B
+
+@lisp
+(gnus-configure-frame
+ '(horizontal 1.0
+    (vertical 10
+      (group 1.0)
+      (article 0.3 point))
+    (vertical 1.0
+      (article 1.0)
+      (horizontal 4
+        (group 1.0)
+        (article 10)))))
+@end lisp
+
+\e$B$$$/$D$+$N%U%l!<%`$bM_$7$$$+$b$7$l$^$;$s!#4JC1$G$9\e(B---@code{frame} \e$BJ,3d$r\e(B
+\e$B;H$&$@$1$G$9\e(B:
+
+@lisp
+(gnus-configure-frame
+ '(frame 1.0
+         (vertical 1.0
+                   (summary 0.25 point frame-focus)
+                   (article 1.0))
+         (vertical ((height . 5) (width . 15)
+                    (user-position . t)
+                    (left . -1) (top . 1))
+                   (picon 1.0))))
+
+@end lisp
+
+\e$B$3$NJ,3d$N7k2L$O!":G=i\e(B (\e$B$b$7$/$O!"\e(B``\e$B<g$J\e(B'') \e$B%U%l!<%`$O8+47$l$?35N,\e(B/\e$B5-;v\e(B
+\e$B%&%#%s%I%&@_Dj$G!">.$5$JDI2C$N%U%l!<%`$,\e(B picon \e$B$rI=<($9$k$?$a$K:n$i$l$k\e(B
+\e$B$H$$$&;v$K$J$j$^$9!#$4Mw$NDL$j!"IaDL$N\e(B @code{1.0} \e$B:G>e0L;XDj$NBe$o$j$K!"\e(B
+\e$B$=$l$>$l$NDI2C$NJ,3d$,%U%l!<%`%Q%i%a!<%?O"A[%j%9%H$rBg$-$5;XDj$H$7$F;}$?\e(B
+\e$B$J$1$l$P$J$j$^$;$s\e(B (@pxref{Frame Parameters, , Frame Parameters, elisp,
+The GNU Emacs Lisp Reference Manual})\e$B!#\e(BXEmacs \e$B$G$O!"%U%l!<%`%W%m%Q%F%#%j\e(B
+\e$B%9%H$b;H$($^$9\e(B---\e$BNc$($P!"\e(B@code{(height 5 width 15 left -1 top 1)} \e$B$O$=$N\e(B
+\e$B$h$&$J%Q%i%a!<%?%j%9%H$G$9!#\e(B
+@code{gnus-buffer-configuration} \e$B$K;HMQ2DG=$JA4$F$N%-!<$N0lMw$O$=$N=i4|\e(B
+\e$BCM$G8+$D$1$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B%-!<\e(B @code{message} \e$B$O\e(B @code{gnus-group-mail} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-summary-mail-other-window} \e$B$NN>J}$G;H$o$l$k;v$KCm0U$7$F2<\e(B
+\e$B$5$$!#$b$7Fs$D$r6hJL$9$k$[$&$,K>$^$7$$$J$i!"$3$N$h$&$JJ*$r;H$&;v$,$G$-$^\e(B
+\e$B$9\e(B:
+
+@lisp
+(message (horizontal 1.0
+                     (vertical 1.0 (message 1.0 point))
+                     (vertical 0.24
+                               (if (buffer-live-p gnus-summary-buffer)
+                                   '(summary 0.5))
+                               (group 1.0))))
+@end lisp
+
+\e$BJ#?t$N%U%l!<%`$X$NNI$/$"$kMWK>$O!"%a!<%k$H%K%e!<%9$N:n@.$K$OJL$N%U%l!<%`\e(B
+\e$B$r;H$$!"85$N%U%l!<%`$O$=$N$^$^$K;D$9$H$$$&$b$N$G$9!#$3$l$NC#@.$K$O!"0J2<\e(B
+\e$B$N$h$&$J$b$N$G$G$-$^$9!#\e(B
+
+@lisp
+(message
+  (frame 1.0
+         (if (not (buffer-live-p gnus-summary-buffer))
+             (car (cdr (assoc 'group gnus-buffer-configuration)))
+           (car (cdr (assoc 'summary gnus-buffer-configuration))))
+         (vertical ((user-position . t) (top . 1) (left . 1)
+                    (name . "Message"))
+                   (message 1.0 point))))
+@end lisp
+
+@findex gnus-add-configuration
+\e$BJQ?t\e(B @code{gnus-buffer-configuration} \e$B$O$H$F$bD9$/J#;($J$N$G!"C10l$N@_Dj\e(B
+\e$B$NJQ99$r4JC1$K$9$k$?$a$N4X?t$,$"$j$^$9\e(B: @code{gnus-add-configuration} \e$B$G\e(B
+\e$B$9!#$b$7!"Nc$($P!"\e(B@code{article} \e$B$N@_Dj$rJQ$($?$$$N$J$i!"<!$N$h$&$K$G$-\e(B
+\e$B$^$9\e(B:
+
+@lisp
+(gnus-add-configuration
+ '(article (vertical 1.0
+               (group 4)
+               (summary .25 point)
+               (article 1.0))))
+@end lisp
+
+\e$BIaDL$O$3$l$i$N\e(B @code{gnus-add-configuration} \e$B8F$S=P$7$r%U%!%$\e(B
+\e$B%k\e(B @file{~/.gnus.el} \e$B$KF~$l$k$+!"2?$i$+$N5/F0;~$N%U%C%/$KF~$l$k$G$7$g\e(B
+\e$B$&\e(B---\e$B$=$l$i$O\e(B gnus \e$B$,FI$_9~$^$l$?8e$K<B9T$5$l$k$Y$-$G$9!#\e(B
+
+@vindex gnus-always-force-window-configuration
+\e$B$b$7@_Dj$G8@5Z$5$l$?A4$F$N%&%#%s%I%&$,4{$K8+$($F$$$k$N$G$"$l$P!"\e(Bgnus \e$B$O\e(B
+\e$B%&%#%s%I%&$N@_Dj$rJQ99$7$^$;$s!#$b$7>o$K\e(B ``\e$B@5$7$$\e(B'' \e$B%&%#%s%I%&@_Dj$r6/@)\e(B
+\e$B$7$?$$$N$G$"$l$P!"\e(B
+@code{gnus-always-force-window-configuration} \e$B$r\e(B @code{nil} \e$B$G$J$$CM$K@_\e(B
+\e$BDj$9$k;v$,$G$-$^$9!#\e(B
+
+\e$BLZI=<($r;H$C$F$$$F\e(B (@pxref{Tree Display})\e$B!"LZ%&%#%s%I%&$O?bD>J}8~$KJL$N\e(B
+\e$B%&%#%s%I%&$GI=<($5$l$k$J$i!"%&%#%s%I%&$NBg$-$5$,JQ99$5$l$k$3$H$rHr$1$k$?\e(B
+\e$B$a$K\e(B @code{gnus-tree-minimize-window} \e$B$r$$$8$k$N$,NI$$$G$7$g$&!#\e(B
+
+@subsection \e$B%&%#%s%I%&@_Dj$NNc\e(B
+
+@itemize @bullet
+@item
+\e$B:8B&$r69$a$F%0%k!<%W%P%C%U%!$K!#1&B&$rJ,3d$7$F35N,%P%C%U%!\e(B (\e$B>e\e(B 1/6) \e$B$H\e(B
+\e$B5-;v%P%C%U%!\e(B (\e$B2<\e(B) \e$B$K!#\e(B
+
+@ifinfo
+@example
++---+---------+
+| G | Summary |
+| r +---------+
+| o |         |
+| u | Article |
+| p |         |
++---+---------+
+@end example
+@end ifinfo
+
+@lisp
+(gnus-add-configuration
+ '(article
+   (horizontal 1.0
+               (vertical 25 (group 1.0))
+               (vertical 1.0
+                         (summary 0.16 point)
+                         (article 1.0)))))
+
+(gnus-add-configuration
+ '(summary
+   (horizontal 1.0
+               (vertical 25 (group 1.0))
+               (vertical 1.0 (summary 1.0 point)))))
+@end lisp
+@end itemize
+
+@node Faces and Fonts
+@section \e$B%U%'%$%9$H%U%)%s%H\e(B
+@cindex faces
+@cindex fonts
+@cindex colors
+
+\e$B%U%)%s%H$H%U%'%$%9$rO.$k$N$OHs>o$KFq$7$+$C$?$N$G$9$,!":#F|$G$OHs>o$K4JC1\e(B
+\e$B$G$9!#C1$K\e(B @kbd{M-x customize-face} \e$B$H$d$C$F!"JQ$($?$$%U%'%$%9$rA*$S=P$7\e(B
+\e$B$F!"I8=`$N%+%9%?%^%$%:%$%s%?!<%U%'!<%9$r;H$C$FJQ99$9$k;v$,$G$-$^$9!#\e(B
+
+@node Compilation
+@section \e$B%3%s%Q%$%k\e(B
+@cindex compilation
+@cindex byte-compilation
+
+@findex gnus-compile
+
+\e$B$"$N9T=qK!;EMM;XDjJQ?t$r3P$($F$$$^$9\e(B
+\e$B$+\e(B? @code{gnus-summary-line-format}, @code{gnus-group-line-format} \e$B$J$I\e(B
+\e$B$J$I$G$9!#DL>o\e(B T-gnus \e$B$O$3$l$i$NJQ?t$r%P%$%H%3%s%Q%$%k$7$F;H$&$N$G!"B.EY\e(B
+\e$BDc2<$O:G>.8B$K?)$$;_$a$i$l$^$9!#$7$+\e(B
+\e$B$7\e(B @code{gnus-compile-user-specs} \e$B$r\e(B @code{nil} (\e$B=i4|CM$O\e(B @code{t}) \e$B$K$7\e(B
+\e$B$?>l9g$O!"IT1?$J;v$K$=$l$i$rJQ99$9$k$HBgJQ=EBg$JB.EYDc2<$r0z$-5/$3$9;v$K\e(B
+\e$B$J$j$^$9!#\e(B(\e$B$3$l$i$NJQ?t$N=i4|CM$O$=$l$i$K4XO"IU$1$i$l$?%P%$%H%3%s%Q%$%k\e(B
+\e$B$5$l$?4X?t$r;}$C$F$$$^$9$,!"MxMQ<T:n@.$N$b$N$O$b$A$m$s$=$&$G$O$"$j$^$;$s!#\e(B)
+
+\e$B$3$l$r2~A1$9$k$?$a$K!"JQ?t$rO.$j$^$o$7$F!"\e(B(\e$B$J$s$H$J$/\e(B) \e$BK~B-$7$?$H46$8$?\e(B
+\e$B8e$G!"\e(B@kbd{M-x gnus-compile} \e$B$r<B9T$9$k;v$,$G$-$^$9!#$3$l$O?7$7$$;XDj$,\e(B
+\e$B%P%$%H%3%s%Q%$%k$5$l!"$b$&0lEY:G9bB.EY$KI|5"$G$-$k$H$$$&;v$G$9!#$?$@\e(B
+\e$B$7\e(B T-gnus \e$B$O$3$l$i$N%P%$%H%3%s%Q%$%k$5$l$?;XDj$r%U%!%$\e(B
+\e$B%k\e(B @file{.newsrc.eld} \e$B$KJ]B8$7$^$;$s!#\e(B
+
+@table @code
+@item gnus-compile-user-specs
+@vindex gnus-compile-user-specs
+\e$B$3$NCM$r\e(B @code{nil} \e$B0J30$K$7$F$*$/$H!"MxMQ<T$,:n@.$7$?9T=qK!;EMMJQ?t$r<+\e(B
+\e$BF0E*$K%3%s%Q%$%k$7$^$9!#=i4|CM$O\e(B @code{t} \e$B$G!"\e(B
+@code{gnus-*-line-format-spec} \e$B$N3FFbItJQ?t$NCM$K1F6A$7$^$9!#\e(B
+@end table
+
+@node Mode Lines
+@section \e$B%b!<%I9T\e(B
+@cindex mode lines
+
+@vindex gnus-update-mode-lines
+@code{gnus-updated-mode-lines} \e$B$O$I$N%P%C%U%!$,$=$N%b!<%I9T$r>o$K:G?7$N\e(B
+\e$B$b$N$K$7$F$*$/$+$r;XDj$7$^$9!#$=$l$O%7%s%\%k$N%j%9%H$G$9!#;H$&;v$N$G$-$k\e(B
+\e$B%7%s%\%k$O\e(B @code{group}, @code{article}, @code{summary}, @code{server},
+@code{browse}, @code{tree} \e$B$J$I$G$9!#$b$7BP1~$9$k%7%s%\%k$,B8:_$9$k$H!"\e(B
+gnus \e$B$O3:Ev$9$k$G$"$m$&>pJs$G%b!<%I9T$r99?7$7$^$9!#$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$J$i!"2hLL$N:FIA2h$O$b$C$HB.$$$G$7$g$&!#\e(B
+
+@cindex display-time
+
+@vindex gnus-mode-non-string-length
+\e$B=i4|@_Dj$G$O!"\e(Bgnus \e$B$O35N,%P%C%U%!$H5-;v%P%C%U%!$N%b!<%I9T$K8=:_$N5-;v$N\e(B
+\e$B>pJs$rI=<($7$^$9!#\e(BGnus \e$B$,I=<($7$?$$>pJs\e(B (\e$BNc$($P!"5-;v$NI=Bj\e(B) \e$B$O$7$P$7$P\e(B
+\e$B%b!<%I9T$h$j$bD9$$$3$H$,$"$k$N$G!"$I$3$+$G@Z$jMn$H$5$l$J$1$l$P$J$j$^$;$s!#\e(B
+\e$BJQ?t\e(B @code{gnus-mode-non-string-length} \e$B$O$=$N9T$NB>$NMWAG\e(B (\e$B$9$J$o$A!">p\e(B
+\e$BJs$G$J$$ItJ,\e(B) \e$B$,$I$N$/$i$$$ND9$5$G$"$k$+$r;XDj$7$^$9!#$b$7%b!<%I9T$KDI2C\e(B
+\e$B$NMWAG$rF~$l$?$J$i!"$3$NJQ?t$r=$@5$9$kI,MW$,$"$j$^$9\e(B:
+
+@c Hook written by Francesco Potorti` <pot@cnuce.cnr.it>
+@lisp
+(add-hook 'display-time-hook
+          (lambda () (setq gnus-mode-non-string-length
+                           (+ 21
+                              (if line-number-mode 5 0)
+                              (if column-number-mode 4 0)
+                              (length display-time-string)))))
+@end lisp
+
+\e$B$b$7$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$J$i\e(B (\e$B$3$l$,=i4|CM$G$9$,\e(B)\e$B!"%b!<%I9T$O@Z\e(B
+\e$B$jMn$H$5$l$:!"5M$a9~$_$b$5$l$^$;$s!#=i4|@_Dj$O!"%P%C%U%!$N40A4$J%Q!<%;%s\e(B
+\e$B%HI=<($5$($b%b!<%I9T$+$iDI$$$d$i$l$k2DG=@-$b$"$j$^$9$N$G!"$*$=$i$/K>$^$7\e(B
+\e$B$$@_Dj$G$O$J$$$H$$$&;v$KCm0U$7$F2<$5$$!#MxMQ<T$,<+J,$N@_Dj$K9g$&$h$&$K$3\e(B
+\e$B$NJQ?t$rE,@Z$K@_Dj$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+@node Highlighting and Menus
+@section \e$B%O%$%i%$%H$H%a%K%e!<\e(B
+@cindex visual
+@cindex highlighting
+@cindex menus
+
+@vindex gnus-visual
+\e$BJQ?t\e(B @code{gnus-visual} \e$B$O$?$$$F$$$N\e(B gnus \e$B$rAGE($K$9$kItJ,$NA`:n$r$7$^$9!#\e(B
+@code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O%a%K%e!<$r:n$C$?$j!"AGE($J?'$d%U%)%s%H$r;H$C\e(B
+\e$B$?$j$7$h$&$H$7$^$;$s!#$3$l$O%U%!%$%k\e(B @file{gnus-vis.el} \e$B$rFI$_9~$`;v$b6X\e(B
+\e$B;_$7$^$9!#\e(B
+
+\e$B$3$NJQ?t$O;HMQ2DG=$J;k3PE*%W%m%Q%F%#$N%j%9%H$G$"$k;v$,$G$-$^$9!#0J2<$NMW\e(B
+\e$BAG$OM-8z$G!"=i4|@_Dj$G$9$Y$F4^$^$l$F$$$^$9\e(B:
+
+@table @code
+@item group-highlight
+\e$B%0%k!<%W%P%C%U%!$G%O%$%i%$%H$r$7$^$9!#\e(B
+@item summary-highlight
+\e$B35N,%P%C%U%!$G%O%$%i%$%H$r$7$^$9!#\e(B
+@item article-highlight
+\e$B5-;v%P%C%U%!$G%O%$%i%$%H$r$7$^$9!#\e(B
+@item highlight
+\e$BA4$F$N%P%C%U%!$G%O%$%i%$%H$r$9$k$h$&$K$7$^$9!#\e(B
+@item group-menu
+\e$B%0%k!<%W%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item summary-menu
+\e$B35N,%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item article-menu
+\e$B5-;v%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item browse-menu
+\e$B%V%i%&%:%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item server-menu
+\e$B%5!<%P!<%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item score-menu
+\e$B%9%3%"%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@item menu
+\e$BA4$F$N%P%C%U%!$G%a%K%e!<$r:n@.$7$^$9!#\e(B
+@end table
+
+\e$B$G$9$+$i!"5-;v%P%C%U%!$@$1$r%O%$%i%$%H$7$?$/!"A4$F$N%P%C%U%!$G%a%K%e!<$r\e(B
+\e$B:n$j$?$$>l9g$O!"$3$N$h$&$K$9$k;v$,$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-visual '(article-highlight menu))
+@end lisp
+
+\e$B$b$7%O%$%i%$%H$@$1$G!"%a%K%e!<$NN`$OM_$7$/$J$$$H$-$O!"<!$N$h$&$K$G$-$^$9\e(B:
+
+@lisp
+(setq gnus-visual '(highlight))
+@end lisp
+
+@code{gnus-visual} \e$B$,\e(B @code{t} \e$B$G$"$k$H!"%O%$%i%$%H$H%a%K%e!<$OA4$F\e(B
+\e$B$N\e(B gnus \e$B$N%P%C%U%!$G;HMQ$5$l$^$9!#\e(B
+
+\e$BB>$NA4$F$N%P%C%U%!$N308+$K1F6A$9$kAm9gE*$JJQ?t$O\e(B:
+
+@table @code
+@item gnus-mouse-face
+@vindex gnus-mouse-face
+\e$B$3$l$O\e(B gnus \e$B$G%^%&%9$N%O%$%i%$%H$K;H$o$l$k%U%'%$%9\e(B (\e$B$9$J$o$A!"%U%)%s\e(B
+\e$B%H\e(B) \e$B$G$9!#\e(B@code{gnus-visual} \e$B$,\e(B @code{nil} \e$B$G$"$k$H!"%^%&%9%O%$%i%$%H$O\e(B
+\e$B$J$5$l$^$;$s!#\e(B
+@end table
+
+\e$BA4$/0c$C$?%a%K%e!<$r:n@.$9$k$?$a$K4XO"$9$k%U%C%/$,$"$j$^$9\e(B:
+
+@table @code
+@item gnus-article-menu-hook
+@vindex gnus-article-menu-hook
+\e$B5-;v%b!<%I\e(B (article mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-group-menu-hook
+@vindex gnus-group-menu-hook
+\e$B%0%k!<%W%b!<%I\e(B (group mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-summary-menu-hook
+@vindex gnus-summary-menu-hook
+\e$B35N,%b!<%I\e(B (summary mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-server-menu-hook
+@vindex gnus-server-menu-hook
+\e$B%5!<%P!<%b!<%I\e(B (server mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-browse-menu-hook
+@vindex gnus-browse-menu-hook
+\e$B354Q%b!<%I\e(B (browse mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+
+@item gnus-score-menu-hook
+@vindex gnus-score-menu-hook
+\e$B%9%3%"%b!<%I\e(B (score mode) \e$B%a%K%e!<$r:n@.$7$?8e$K8F$P$l$k%U%C%/$G$9!#\e(B
+@end table
+
+@node Buttons
+@section \e$B%\%?%s\e(B
+@cindex buttons
+@cindex mouse
+@cindex click
+
+\e$B:G6a$G$O!":G?7N.9T$N%^%&%9\e(B @dfn{mouse} \e$BAuCV$,!"$A$c$s$H$7$?A`:nK!$r3X$S\e(B
+\e$B$?$,$i$J$$%J%&$J%d%s%0$N4V$GBg?M5$$G$9!#$=$l$G$O!";d$,\e(B Tops 20 \e$B%7%9%F%`\e(B
+\e$B>e$G\e(B Emacs \e$B$r;H$C$F$$$?:"$N\e(B '89 \e$BG/$N2F$r;W$$5/$3$7$F$_$^$7$g$&!#\e(B300 \e$B?M$N\e(B
+\e$BMxMQ<T$,!"0l$D$N%^%7%s>e$G!"$_$s$J$,\e(B Simula \e$B%3%s%Q%$%i$rAv$i$;$F$$$^$7$?!#\e(B
+\e$B$"$"!"$P$+$P$+$7$$\e(B!
+
+\e$B$[$s$H$K$=$&$@$M!#\e(B
+
+@vindex gnus-carpal
+\e$B$^$:$G$9$M!"\e(B@code{gnus-carpal} \e$B$r\e(B @code{t} \e$B$K@_Dj$9$k$3$H$K$h$C$F!"%/%j%C\e(B
+\e$B%/$9$k$@$1$G2?$G$b$G$-$k%\%?%s$@$i$1$N%P%C%U%!$r\e(B gnus \e$B$KI=<($5$;$k$3$H$,\e(B
+\e$B$G$-$^$9!#$H$C$F$b4JC1$G$9!"$[$s$H$K!#;X05NEK!$N@h@8$K65$($F$"$2$F!#\e(B(\e$BLu\e(B
+\e$BCm\e(B: carpal \e$B$H$O<j<s$N9|$N$3$H\e(B)
+
+@table @code
+@item gnus-carpal-mode-hook
+@vindex gnus-carpal-mode-hook
+\e$BA4$F$N<j<s%b!<%I%P%C%U%!$G<B9T$9$k%U%C%/!#\e(B
+
+@item gnus-carpal-button-face
+@vindex gnus-carpal-button-face
+\e$B%\%?%s$K;H$o$l$k%U%'%$%9!#\e(B
+
+@item gnus-carpal-header-face
+@vindex gnus-carpal-header-face
+\e$B<j<s%P%C%U%!$N%X%C%@!<$G;HMQ$5$l$k%U%'%$%9!#\e(B
+
+@item gnus-carpal-group-buffer-buttons
+@vindex gnus-carpal-group-buffer-buttons
+\e$B%0%k!<%W%P%C%U%!$N%\%?%s!#\e(B
+
+@item gnus-carpal-summary-buffer-buttons
+@vindex gnus-carpal-summary-buffer-buttons
+\e$B35N,%P%C%U%!$N%\%?%s!#\e(B
+
+@item gnus-carpal-server-buffer-buttons
+@vindex gnus-carpal-server-buffer-buttons
+\e$B%5!<%P!<%P%C%U%!$N%\%?%s!#\e(B
+
+@item gnus-carpal-browse-buffer-buttons
+@vindex gnus-carpal-browse-buffer-buttons
+\e$B1\Mw%P%C%U%!$N%\%?%s!#\e(B
+@end table
+
+\e$BA4$F$N\e(B @code{buttons} \e$BJQ?t$O%j%9%H$G$9!#$3$N%j%9%H$NMWAG$O!"\e(B
+@code{car} \e$B$,I=<($5$l$kJ8$G\e(B @code{cdr} \e$B$,4X?t%7%s%\%k$N\e(B cons \e$B%;%k$+!"$b\e(B
+\e$B$7$/$O$?$@$NJ8;zNs$N$I$A$i$+$G$9!#\e(B
+
+@node Daemons
+@section \e$B%G!<%b%s\e(B
+@cindex demons
+@cindex daemons
+
+Gnus\e$B!"$=$l$O\e(B(\e$B8@$$EA$($K$h$l$P\e(B)\e$B$+$D$F=q$+$l$?$$$+$J$k%W%m%0%i%`$h$j$bBg$-\e(B
+\e$B$/!"$"$J$?$,$d$C$FM_$7$$$H;W$&$5$^$6$^$J4qL/$J$3$H$r!"$"$J$?$N$$$J$$$H$3\e(B
+\e$B$m$G9T$C$F$/$l$k$b$N$G$9!#Nc$($P!"$"$J$?$O;~$?$^?7Ce%a!<%k$r%A%'%C%/$7$F\e(B
+\e$B$b$i$$$?$$$+$bCN$l$^$;$s!#$"$k$$$O\e(B Emacs \e$B$r$7$P$i$/J|$C$F$*$$$?$H$-A4$F\e(B
+\e$B$N%5!<%P$N@\B3$r@ZCG$7$F$b$i$$$?$/$J$k$+$b$7$l$^$;$s!#B>$K$b2?$+$=$&$$$C\e(B
+\e$B$?$3$H$G$9!#\e(B
+
+Gnus \e$B$O$5$^$6$^$J@)8f;R\e(B @dfn{handlers} \e$B$rDj5A$9$k$3$H$K$h$C$F$=$N$h$&$J\e(B
+\e$B$3$H$r2DG=$K$7$^$9!#3F@)8f;R$O;0$D$NMWAG$+$i@.$j$^$9!#\e(B
+@var{\e$B4X?t\e(B}, @var{\e$B;~4V\e(B}, @var{\e$B6uE>\e(B} \e$B%Q%i%a!<%?$G$9!#\e(B
+
+\e$B0J2<$O\e(B Emacs \e$B$,2?$b$7$J$$6uE>>uBV$,;0==J,B3$$$?$H$-$K@\B3$r@ZCG$9$k@)8f\e(B
+\e$B;R$NNc$G$9!#\e(B
+
+@lisp
+(gnus-demon-close-connections nil 30)
+@end lisp
+
+\e$B0J2<$O\e(B Emacs \e$B$,2?$b$7$F$$$J$$$H$-!"0l;~4VKh$K\e(B @acronym{PGP} \e$B%X%C%@!<$rAv\e(B
+\e$B::$9$k@)8f;R$G$9!#\e(B
+
+@lisp
+(gnus-demon-scan-pgp 60 t)
+@end lisp
+
+\e$B$3$N\e(B @var{\e$B;~4V\e(B} \e$B%Q%i%a!<%?$H$=$7$F\e(B @var{\e$B6uE>\e(B} \e$B%Q%i%a!<%?$O!"4qL/$G$+$DAG\e(B
+\e$B@2$i$7$$J}K!$G0l=o$KF0:n$7$^$9!#4pK\E*$K$O!"\e(B@var{\e$B6uE>\e(B} \e$B$,\e(B @code{nil} \e$B$N\e(B
+\e$B;~$K$O$3$N4X?t$O\e(B @var{\e$B;~4V\e(B} \e$BJ,Kh$K8F$S=P$5$l$^$9!#\e(B
+
+\e$B$b$7\e(B @var{\e$B6uE>\e(B} \e$B$,\e(B @code{t} \e$B$G$"$l$P!"$3$N4X?t$O\e(B Emacs \e$B$,2?$b$7$F$$$J$$\e(B
+\e$B;~$K8B$j!"\e(B@var{\e$B;~4V\e(B} \e$BJ,8e$K8F$S=P$5$l$^$9!#0lC6\e(B Emacs \e$B$,$:$C$H6uE>>uBV$K\e(B
+\e$B$J$C$?8e$O!"$3$N4X?t$O\e(B @var{\e$B;~4V\e(B} \e$BJ,Kh$K8F$S=P$5$l$^$9!#\e(B
+
+@var{\e$B6uE>\e(B} \e$B$,?t$G\e(B @var{\e$B;~4V\e(B} \e$B$b?t$G$"$k>l9g!"$3$N4X?t$O!"\e(BEmacs \e$B$N6uE>>u\e(B
+\e$BBV$,\e(B @var{\e$B6uE>\e(B} \e$BJ,B3$$$?;~$K8B$j!"\e(B@var{\e$B;~4V\e(B} \e$BJ,Kh$K8F$S=P$5$l$^$9!#\e(B
+
+@var{\e$B6uE>\e(B} \e$B$,?t$G\e(B @var{\e$B;~4V\e(B} \e$B$,\e(B @code{nil} \e$B$N>l9g!"$3$N4X?t$O!"\e(BEmacs \e$B$N\e(B
+\e$B6uE>>uBV$,\e(B @var{\e$B6uE>\e(B} \e$BJ,B3$/EY$K0lEY8F$S=P$5$l$^$9!#\e(B
+
+\e$B$=$7$F\e(B @var{\e$B;~4V\e(B} \e$B$,J8;zNs$N>l9g$O!"\e(B@samp{07:31} \e$B$N$h$&$J7A<0$G$J$1$l$P\e(B
+\e$B$J$i$:!"$3$N4X?t$OKhF|$=$N:"$N;~4V$K$J$k$H0lEY8F$S=P$5$l$^$9!#$b$A$m$s!"\e(B
+@var{\e$B6uE>\e(B} \e$B%Q%i%a!<%?$GF0:n$,JQ$o$j$^$9!#\e(B
+
+@vindex gnus-demon-timestep
+(\e$B$3$3$G\e(B ``\e$BJ,\e(B'' \e$B$H8@$C$?$H$-!"$=$l$O<B:]$K\e(B
+\e$B$O\e(B @code{gnus-demon-timestep} \e$BIC$N$3$H$G$9!#$3$l$O=i4|@_Dj$G$O\e(B 60 \e$B$G$9!#\e(B
+\e$B$b$7$3$NJQ?t$rJQ99$9$k$H!"A4$F$N@)8f;R$N7W;~$K1F6A$rM?$($^$9!#\e(B)
+
+\e$B$H$$$&$o$1$G!"@)8f;R$rDI2C$7$?$1$l$P!"\e(B@file{~/.gnus.el} \e$B%U%!%$%k$K!"0J2<\e(B
+\e$B$N$h$&$J$b$N$r=q$/$3$H$,$G$-$^$9!#\e(B
+
+@findex gnus-demon-add-handler
+@lisp
+(gnus-demon-add-handler 'gnus-demon-close-connections 30 t)
+@end lisp
+
+@findex gnus-demon-add-nocem
+@findex gnus-demon-add-scanmail
+@findex gnus-demon-add-rescan
+@findex gnus-demon-add-scan-timestamps
+@findex gnus-demon-add-disconnection
+\e$B$3$N$?$a$N4{@=4X?t$,$$$/$D$+:n@.$5$l$F$$$^$9!#\e(B@code{gnus-demon-add-nocem},
+@code{gnus-demon-add-disconnection},
+@code{gnus-demon-add-nntp-close-connection},
+@code{gnus-demon-add-scan-timestamps}, @code{gnus-demon-add-rescan},
+@code{gnus-demon-add-scanmail} \e$B$G\e(B
+\e$B$9!#$3$l$i$NG=NO$,M_$7$1$l$P!"C1$K$3$l$i$N4X?t$r\e(B @file{~/.gnus.el} \e$B$KF~\e(B
+\e$B$l$F$/$@$5$$!#\e(B
+
+@findex gnus-demon-init
+@findex gnus-demon-cancel
+@vindex gnus-demon-handlers
+\e$B$b$7\e(B @code{gnus-demon-handlers} \e$B$G@)8f;R$rD>@\DI2C$7$?>l9g$K$O!"$=$l$r8z\e(B
+\e$B$+$;$k$?$a$K\e(B @code{gnus-demon-init} \e$B$r<B9T$7$F$/$@$5$$!#A4$F$N%G!<%b%s$r\e(B
+\e$B<h$j>C$9$K$O!"\e(B@code{gnus-demon-cancel} \e$B4X?t$r;H$&$3$H$,$G$-$^$9!#\e(B
+
+\e$B%G!<%b%s$NDI2C$O!"$d$j$9$.$k$N$O$H$C$F$b$*9T57$N$h$/$J$$$3$H$G$9!#A4$F$N\e(B
+\e$B%5!<%P!<$+$iA4$F$N%K%e!<%9$H%a!<%k$rFsICKh$KD4$Y$^$o$94X?t$rIU$12C$($A$c$C\e(B
+\e$B$?$j$9$k$H!"$I$s$JN)GI$J%7%9%F%`$G$b4V0c$$$J$/$*J'$$H"$K$7$F$7$^$$$^$9!#\e(B
+\e$B$=$&F0$/$s$@$b$s!#\e(B
+
+@node NoCeM
+@section NoCeM
+@cindex nocem
+@cindex spam
+
+@dfn{Spam} \e$B$H$O!"F1$85-;v$r2?2s$b2?2s$b2?2s$bEj9F$9$k$3$H$G$9!#\e(BSpam \e$B$O0-\e(B
+\e$B$$$3$H$G$9!#\e(BSpam \e$B$O6'0-$G$9!#\e(B
+
+Spam \e$B$ODL>o0lF|$+$=$3$i$G!"$5$^$6$^$JH?\e(B spam \e$B5!4X$+$i<h$j>C$7$5$l$^$9!#\e(B
+\e$B$3$l$i$N5!4X$ODL>o0l=o$K!"\e(B@dfn{NoCeM} \e$B%a%C%;!<%8$bAw?.$7$^$9!#\e(B
+@dfn{NoCeM} \e$B$O\e(B ``no see-'em'' (\e$BH`$i$r8+$?$/$J$$\e(B)\e$B$HH/2;$5$l!"0UL#$O$=$NL>\e(B
+\e$BA0$NDL$j$G$9\e(B --- \e$B$3$N%a%C%;!<%8$O!":a$rHH$7$F$$$k5-;v$r!"$D$^$j!">C$7$F\e(B
+\e$B$7$^$$$^$9!#\e(B
+
+\e$B$I$&$;$=$N5-;v$,<h$j>C$7$5$l$F$7$^$&$N$J$i!"$3$l$i\e(B NoCeM \e$B%a%C%;!<%8$O2?\e(B
+\e$B$K;H$o$l$k$N$G$7$g$&\e(B? \e$B$"$k%5%$%H$G$O<h$j>C$7%a%C%;!<%8$r0z$-<u$1$:!"$"$k\e(B
+\e$B%5%$%H$G$OFCDj$N?t?M$+$i$N<h$j>C$7%a%C%;!<%8$N$_$7$+0z$-<u$1$^$;$s!#$=$l\e(B
+\e$B$G!"$"$J$?$O\e(B NoCeM \e$B%a%C%;!<%8$r;H$$$?$/$J$k$+$b$7$l$J$$$o$1$G$9!#$3$l$i\e(B
+\e$B$O\e(B @samp{alt.nocem.misc} \e$B%K%e!<%9%0%k!<%W$GG[I[$5$l$F$$$^$9!#\e(B
+
+Gnus \e$B$O$3$N%0%k!<%W$N%a%C%;!<%8$r<+F0E*$KFI$_!"2r<a$9$k$3$H$,$G$-!"$3$l\e(B
+\e$B$G\e(B spam \e$B$r>C$75n$j$^$9!#\e(B
+
+\e$B$b$A$m$s!"$3$l$i$r%+%9%?%^%$%:$9$k$?$a$NJQ?t$,$$$/$D$+$"$j$^$9!#\e(B
+
+@table @code
+@item gnus-use-nocem
+@vindex gnus-use-nocem
+\e$B$3$NJQ?t$r\e(B @code{t} \e$B$K@_Dj$9$k$3$H$G3hF0$r3+;O$5$;$^$9!#=i4|@_Dj$G\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@item gnus-nocem-groups
+@vindex gnus-nocem-groups
+Gnus \e$B$O$3$N%0%k!<%W%j%9%H$+$i\e(B NoCeM \e$B%a%C%;!<%8$rC5$7$^$9!#=i4|@_DjCM\e(B
+\e$B$O\e(B @code{("news.lists.filters" "news.admin.net-abuse.bulletins"
+"alt.nocem.misc" "news.admin.net-abuse.announce")} \e$B$G$9!#\e(B
+
+@item gnus-nocem-issuers
+@vindex gnus-nocem-issuers
+NoCeM \e$B%a%C%;!<%8$rH/9T$9$k?M$O$?$/$5$s$$$^$9!#$3$N%j%9%H$G$O!"C/$N8@$&$3\e(B
+\e$B$H$K=>$$$?$$$+$r;XDj$7$^$9!#=i4|@_DjCM$O\e(B @code{(("Automoose-1"
+"clewis@@ferret.ocunix.on.ca" "cosmo.roadkill" "SpamHippo"
+"hweede@@snafu.de")} \e$B$G$9!#H`$i$O$_$s$J!"N)GI$G9b7i$J;TL1$G$9!#\e(B
+
+\e$B$3$N%j%9%H$K4^$a$i$l$kM-L>$JH?\e(B spam \e$B2H$?$A\e(B
+\e$B$O\e(B @uref{http://www.xs4all.nl/~rosalind/nocemreg/nocemreg.html} \e$B$K:\$C$F\e(B
+\e$B$$$^$9!#\e(B
+
+\e$B$3$l$iA4$F$N?M!9$N\e(B NoCeM \e$B%a%C%;!<%8$KN10U$9$kI,MW$O$"$j$^$;$s\e(B --- \e$B8@$&$3\e(B
+\e$B$H$rJ9$-$?$$?M$@$1$G$$$$$s$G$9!#$^$?$=$N?M$+$i$N\e(B NoCeM\e$B%a%C%;!<%8A4$F$r<u\e(B
+\e$B$1F~$l$kI,MW$b$"$j$^$;$s!#\e(BNoCeM \e$B%a%C%;!<%8$K$O$=$l$>$l<oJL\e(B @dfn{type} \e$B%X%C\e(B
+\e$B%@!<$,$D$$$F$*$j!"$3$l$O$=$N%a%C%;!<%8$N87L)$JDj5A$rM?$($F$$$^$9\e(B(\e$BB?>/$O\e(B
+\e$B87L)$J!"DxEY$M!#$?$$$F$$$O>/$@$1$I\e(B)\e$B!#NI$/;H$o$l$k<oJL$K$O!"\e(B
+@samp{spam}, @samp{spew}, @samp{mmf}, @samp{binary}, @samp{troll} \e$B$,$"$j\e(B
+\e$B$^$9!#$3$l$r;XDj$9$k$K$O!"%j%9%H$NCf$G\e(B @code{(@var{\e$BH/9T<T\e(B} @var{\e$B>r\e(B
+\e$B7o\e(B} @dots{})} \e$BMWAG$r;H$&I,MW$,$"$j$^$9!#3F>r7o$OJ8;zNs\e(B (\e$B;H$$$?$$<oJL$K%^%C\e(B
+\e$B%A$9$k@55,I=8=\e(B) \e$B$+!"$^$?$O\e(B @code{(not @var{\e$BJ8;zNs\e(B})} \e$B$H$$$&7A<0$N%j%9%H\e(B
+\e$B$G$9!#$3$N>l9g$O\e(B @var{\e$BJ8;zNs\e(B} \e$B$O;H$$$?$/$J$$<oJL$K%^%C%A$9$k@55,I=8=$G$9\e(B
+
+\e$BNc$($P!"\e(BChris Lewis \e$B$+$i$N\e(B NoCeM \e$B%a%C%;!<%8$G!"\e(B@samp{troll} \e$B%a%C%;!<%80J\e(B
+\e$B30$NA4$F$rM_$7$$>l9g$K$O!"\e(B
+
+@lisp
+("clewis@@ferret.ocunix.on.ca" ".*" (not "troll"))
+@end lisp
+
+\e$B0lJ}!"H`$N\e(B @samp{spam} \e$B$H\e(B @samp{spew} \e$B%a%C%;!<%80J30$O2?$b$7$?$/$J$1$l$P!"\e(B
+\e$B0J2<$N$h$&$K$G$-$^$9!#\e(B
+
+@lisp
+("clewis@@ferret.ocunix.on.ca" (not ".*") "spew" "spam")
+@end lisp
+
+\e$B$3$N;XDj$O:8$+$i1&$KE,MQ$5$l$^$9!#\e(B
+
+@item gnus-nocem-verifyer
+@vindex gnus-nocem-verifyer
+@findex mc-verify
+\e$B$3$l$O\e(B NoCeM \e$BH/9T<T$,C/$G$"$k$+$H8@$C$F$$$k$+$r>ZL@$9$k4X?t$G$J$/$F$O$J\e(B
+\e$B$j$^$;$s!#=i4|@_Dj$G$O\e(B @code{mc-verify} \e$B$G$"$j!"$3$l$O\e(B Mailcrypt \e$B4X?t$G\e(B
+\e$B$9!#$b$7$3$l$,Hs>o$KCY$/$F!"$"$J$?$,>ZL@7k2L$r5$$K$7$J$$\e(B (\e$B$3$l$O$?$V$s4m\e(B
+\e$B81$G$9\e(B) \e$B$N$G$"$l$P!"$3$NJQ?t$r\e(B @code{nil} \e$B$K$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$b$7=pL>:Q$_$N\e(B NoCeM \e$B%a%C%;!<%8$r>ZL@:Q$_!"L$=pL>$N%a%C%;!<%8$rL$>Z\e(B
+\e$BL@\e(B (\e$B$G$b$=$l$r;H$&\e(B) \e$B$H$7$?$$$N$J$i!"0J2<$N$h$&$K$9$k$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+(setq gnus-nocem-verifyer 'my-gnus-mc-verify)
+
+(defun my-gnus-mc-verify ()
+  (not (eq 'forged
+           (ignore-errors
+             (if (mc-verify)
+                 t
+               'forged)))))
+@end lisp
+
+\e$B$^$"!"$3$l$O$?$V$s4m81$G$7$g$&$1$I$M!#\e(B
+
+@item gnus-nocem-directory
+@vindex gnus-nocem-directory
+\e$B$3$l$O\e(B gnus \e$B$,\e(B NoCeM \e$B%-%c%C%7%e%U%!%$%k$rJ]B8$9$k>l=j$G$9!#=i4|@_DjCM\e(B
+\e$B$O\e(B @file{~/News/NoCeM/} \e$B$G$9!#\e(B
+
+@item gnus-nocem-expiry-wait
+@vindex gnus-nocem-expiry-wait
+\e$B8E$$\e(B NoCeM \e$B9`L\$r%-%c%C%7%e$+$i>C$9$^$G$NF|?t!#=i4|@_DjCM$O\e(B 15 \e$B$G$9!#$3\e(B
+\e$B$l$rC;$/$9$k$[$I\e(B gnus \e$B$OB.$/$J$j$^$9$,!"8E$$\e(B spam \e$B$r8+$k$3$H$K$J$C$F$7$^\e(B
+\e$B$&$+$b$7$l$^$;$s!#\e(B
+
+@item gnus-nocem-check-from
+@vindex gnus-nocem-check-from
+\e$BHs\e(B@code{nil} \e$B$G$O!"5-;v$N%\%G%#$K$"$kH/9T?M$N@5Ev@-$rD4$Y$^$9!#$=$&$G$J\e(B
+\e$B$$>l9g$O!"Cx<T$,@5$7$$H/9T?M$G$J$/$F$b5$$K$;$:$K5-;v$r<h$j9~$_$^$9$,!"$b\e(B
+\e$B$7$"$J$?$,@5$7$$H/9T?M$r8+J,$1$i$l$k$J$i$P!"$=$&$7$?J}$,$H$F$bB.$/$J$k$G\e(B
+\e$B$7$g$&!#\e(B
+
+@item gnus-nocem-check-article-limit
+@vindex gnus-nocem-check-article-limit
+\e$BHs\e(B@code{nil} \e$B$G!"A4$F$N\e(B NoCeM \e$B%0%k!<%W$K$*$1$k%A%'%C%/$9$k5-;v$N:GBg?t$r\e(B
+\e$B;XDj$7$^$9!#\e(BNoCeM \e$B%0%k!<%W$O5pBg$K$J$k$3$H$,$"$j!"$=$&$J$k$H=hM}$,$H$F$b\e(B
+\e$BCY$/$J$j$^$9!#\e(B
+@end table
+
+NoCeM \e$B$r;H$&$H!"$b$7$+$9$k$H%a%b%j6t$$$K$J$k$+$b$7$l$^$;$s!#$"$J$?$,$?$/\e(B
+\e$B$5$s$N@8$-$?%0%k!<%W\e(B (\e$B$D$^$j9XFI$"$k$$$OHs9XFI%0%k!<%W\e(B) \e$B$r;}$C$F$$$k$N$J\e(B
+\e$B$i!"\e(BEmacs \e$B%W%m%;%9$OBg$-$/$J$C$F$7$^$&$G$7$g$&!#$b$7$3$l$,LdBj$G$"$l$P!"\e(B
+\e$BHs9XFI$N%0%k!<%W$rA4It\e(B (\e$B$"$k$$$O$=$NB?$/$r\e(B) \e$B>C$75n$C$F$7$^$C$?J}$,NI$$$G\e(B
+\e$B$9\e(B (@pxref{Subscription Commands})\e$B!#\e(B
+
+@node Undo
+@section \e$B$d$jD>$7\e(B
+@cindex undo
+
+\e$B<B9T$7$?$3$H$N$d$jD>$7$,$G$-$k$H!"$H$F$bJXMx$G$9!#IaDL$N\e(B Emacs \e$B%P%C%U%!\e(B
+\e$B$G$O!"$3$l$O==J,4JC1$G$9\e(B --- \e$BC1$K\e(B @code{undo} \e$B%\%?%s$r2!$9$@$1$G$9!#$7$+\e(B
+\e$B$7\e(B gnus \e$B$N%P%C%U%!$G$O!"$3$l$O4JC1$G$O$"$j$^$;$s!#\e(B
+
+Gnus \e$B$,%P%C%U%!!<Fb$KI=<($7$F$$$k$b$N$O!"\e(Bgnus \e$B$K$H$C$F$OA4$/2?$N2ACM$b$"\e(B
+\e$B$j$^$;$s\e(B --- \e$B$3$l$O$_$s$J!"MxMQ<T$K4qNo$K8+$($k$h$&$K%G%6%$%s$5$l$F$$$k\e(B
+\e$B$?$@$N%G!<%?$J$N$G$9!#\e(B@kbd{C-k} \e$B$G%0%k!<%W%P%C%U%!$+$i%0%k!<%W$r>C5n$9$k\e(B
+\e$B$N$O!"$=$N9T$O>C$(5n$j$^$9$,!"$=$l$O<B:]$NF0:n\e(B --- \e$BLdBj$N%0%k!<%W\e(B
+\e$B$r\e(B gnus \e$B$NFbIt9=B$BN$+$i:o=|$9$k$3$H!"$NC1$J$kI{:nMQ$G$7$+$"$j$^$;$s!#$3\e(B
+\e$B$l$i$N$d$jD>$7$O!"DL>o$N\e(B Emacs \e$B$N\e(B @code{undo} \e$B4X?t$G$O9T$J$&$3$H$,$G$-$^\e(B
+\e$B$;$s!#\e(B
+
+Gnus \e$B$O!"MxMQ<T$,2?$r$9$k$+$r21$($F$*$-!"$=$NMxMQ<T$NF0:n$N5U$r9T$J$&F0\e(B
+\e$B:n$rDs6!$9$k$3$H$K$h$C$F!"$3$l$r2?$H$+5_:Q$7$h$&$H$7$^$9!#$=$7$FMxMQ<T\e(B
+\e$B$,\e(B @code{undo} \e$B%-!<$r2!$7$?$H$-!"\e(Bgnus \e$B$O$=$N0l$D<jA0$NF0:n$"$k$$$OF0:n72\e(B
+\e$B$N5U$N%3!<%I$r<B9T$7$^$9!#$7$+$7!"A4$F$NF0:n$,4JC1$K2D5U$G$"$k$o$1$G$O$J\e(B
+\e$B$$$N$G!"\e(Bgnus \e$B$O8=:_!"$d$jD>$72DG=$J%-!<4X?t$O6O$+$7$+Ds6!$7$F$$$^$;$s!#\e(B
+\e$B$3$l$i$O!"%0%k!<%W$N:o=|!"%0%k!<%W$NE=$jIU$1!"%0%k!<%W$N4{FI5-;v$N%j%9%H\e(B
+\e$B$NJQ99!"$=$l$@$1$J$s$G$9!#>-Mh$O$b$C$H4X?t$,DI2C$5$l$k$+$b$7$l$^$;$s$,!"\e(B
+\e$B4X?t$NDI2C$O$=$l$>$lJ]B8$9$k$Y$-%G!<%?$rA}$d$9$3$H$K$J$k$N$G!"\e(Bgnus \e$B$O7h\e(B
+\e$B$7$F40A4$d$jD>$72DG=$K$O$J$i$J$$$G$7$g$&!#\e(B
+
+@findex gnus-undo-mode
+@vindex gnus-use-undo
+@findex gnus-undo
+\e$B$d$jD>$75!G=$O\e(B @code{gnus-undo-mode} \e$B%^%$%J!<%b!<%I$K$h$C$FDs6!$5$l$^$9!#\e(B
+\e$B$3$l$O\e(B @code{gnus-use-undo} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P;HMQ$5$l!"$3$l$,=i\e(B
+\e$B4|@_Dj$G$9!#\e(B@kbd{C-M-_} \e$B%-!<$,\e(B @code{gnus-undo} \e$BL?Na$r<B9T$7$^$9!#$3$l$O\e(B
+\e$BDL>o$N\e(B Emacs \e$B$N\e(B @code{undo} \e$BL?Na$K$A$g$C$H$@$1;w$F$$$k$H;W$o$l$k$G$7$g$&!#\e(B
+
+@node Predicate Specifiers
+@section \e$B=R8l$N@_Dj\e(B
+@cindex predicate specifiers
+
+\e$B$$$/$D$+$N\e(B gnus \e$B$NJQ?t\e(B
+\e$B$O\e(B @dfn{\e$B=R8l;X<(;R\e(B} (@dfn{predicate specifiers}) \e$B$G$9!#$3$l$O=R8l$N;EMM\e(B
+\e$B$KM;DL$r8z$+$;$k$3$H$,$G$-$kFCJL$J7A<0$G$9!#\e(B
+
+\e$B$3$l$i$N;X<(;R$O4X?t$K$h$k%j%9%H!"%7%s%\%k$^$?$O%j%9%H$G$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@lisp
+(or gnus-article-unseen-p
+    gnus-article-unread-p)
+@end lisp
+
+\e$BMxMQ$G$-$k%7%s%\%k$O\e(B @code{or}\e$B!"\e(B@code{and} \e$B$*$h$S\e(B @code{not} \e$B$G$9!#4X?t\e(B
+\e$B$O$9$Y$F0l$D$N%Q%i%a!<%?$r<u$1<h$j$^$9!#\e(B
+
+@findex gnus-make-predicate
+\e$BFbItE*$K!"\e(Bgnus \e$B$O8F$V$3$H$,$G$-$k4X?t$r:n$k$?$a$K!"$3$l$i$N;X<(;R$K$D$$\e(B
+\e$B$F\e(B @code{gnus-make-predicate} \e$B$r;H$$$^$9!#$3$N4X?t$X$N$3$NF~NO%Q%i%a!<%?\e(B
+\e$B$O!"=R8l;X<(;R$N$9$Y$F$N4X?t$KEO$5$l$^$9!#\e(B
+
+@node Moderation
+@section \e$B;J2qLr\e(B
+@cindex moderation
+
+\e$B$b$7$"$J$?$,;J2q<T\e(B (\e$B%b%G%l!<%?!<\e(B) \e$B$J$i$P!"\e(B@file{gnus-mdrtn.el} \e$B%Q%C%1!<\e(B
+\e$B%8$r;H$&$3$H$,$G$-$^$9!#$3$l$OI8=`\e(B gnus \e$B%Q%C%1!<%8$K$O4^$^$l$^$;$s!#\e(B
+@samp{larsi@@gnus.org} \e$B$K!"$I$N%0%k!<%W$N;J2q$r9T$J$&$N$+$r=R$Y$?%a!<%k\e(B
+\e$B$r=q$$$F$/$@$5$$!#$=$&$9$l$P%3%T!<$r<j$KF~$l$i$l$^$9!#\e(B
+
+\e$B;J2q<TMQ%Q%C%1!<%8$O35N,%P%C%U%!$N%^%$%J!<%b!<%I$H$7$F<BAu$5$l$F$$$^$9!#\e(B
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'gnus-moderate)
+@end lisp
+
+\e$B$r$"$J$?$N\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$F$/$@$5$$!#\e(B
+
+\e$B$"$J$?$,\e(B @samp{rec.zoofle} \e$B$N;J2q<T$@$H$9$k$H!"$3$l$O0J2<$N$h$&$KF0:n$9\e(B
+\e$B$k$h$&$K$J$C$F$$$^$9!#\e(B
+
+@enumerate
+@item
+@samp{Newsgroups:.*rec.zoofle} \e$B$K%^%C%A$9$k<u?.%a!<%k$rJ,N%$7$^$9!#$3$l\e(B
+\e$B$OEj9F$5$l$h$&$H$7$F$$$k5-;v$rA4$F$"$k%a!<%k%0%k!<%W\e(B --- \e$BNc$(\e(B
+\e$B$P\e(B @samp{nnml:rec.zoofle} \e$B$KF~$l$^$9!#\e(B
+
+@item
+\e$B$"$J$?$O;~@^$3$N%0%k!<%W$KF~$j!"\e(B@kbd{e} (edit-and-post) \e$B$"$k$$\e(B
+\e$B$O\e(B @kbd{s} (just send unedited) \e$BL?Na$r;H$C$F5-;v$rEj9F$7$^$9!#\e(B
+
+@item
+@samp{rec.zoofle} \e$B%K%e!<%9%0%k!<%W$rFI$s$G$$$kESCf$G!"$b$7$"$J$?$,>5G'$7\e(B
+\e$B$F$$$J$$5-;v$r$?$^$?$^8+$D$1$?$H$7$?$i!"\e(B@kbd{c} \e$BL?Na$G<h$j>C$7$G$-$^$9!#\e(B
+@end enumerate
+
+\e$BFs$D$N%0%k!<%W$G;J2q<T%b!<%I$r;H$&$H$9$l$P!"$3$&$J$j$^$9!#\e(B
+
+@lisp
+(setq gnus-moderated-list
+      "^nnml:rec.zoofle$\\|^rec.zoofle$")
+@end lisp
+
+@node Image Enhancements
+@section \e$B2hA|$N3HD%\e(B
+
+XEmacs \e$B$=$l$K\e(B Emacs 21@footnote{MS \e$B%&%#%s%I%&%:$N\e(B Emacs 21 \e$B$O$^$@2hA|$r\e(B
+\e$B%5%]!<%H$7$F$$$^$;$s!#\e(B} \e$B$O3($d$=$NB>$N$b$N$rI=<($9$k$3$H$,$G$-$k$N$G!"\e(B
+gnus \e$B$O$3$l$rMxMQ$9$k$3$H$K$7$^$9!#\e(B
+
+@menu
+* X-Face::                      \e$B%U%!%s%-!<$G$A$C$A$c$JGr9u$N3($rI=<($9$k\e(B
+* Face::                        \e$B$h$j%U%!%s%-!<$G$A$C$A$c$J%+%i!<$N3($rI=<($9$k\e(B
+* Smileys::                     \e$BI=<($5$l$k$Y$/@8$^$l$?9,$;$=$&$J4i$rI=<($9$kJ}K!\e(B
+* Picons::                      \e$B$"$J$?$,FI$s$G$$$k$b$N$N3($rI=<($9$kJ}K!\e(B
+* XVarious::                    \e$B$=$NB>$N\e(B XEmacs \e$B$G\e(B Gnus \e$B$JJQ?t\e(B
+@end menu
+
+@node X-Face
+@subsection X-Face
+@cindex x-face
+
+@code{X-Face} \e$B%X%C%@!<$O!"%a%C%;!<%8$NCx<T$rI=$o$9$3$H$K$J$C$F$$$k\e(B 48\e$B!_\e(B
+48 \e$B2hAG$NGr9u\e(B (1 bit \e$B$N?<$5\e(B) \e$B$N3($rIA$-$^$9!#$3$l$O?J2=$7B3$1$k$"$^$?$N\e(B
+\e$B%a!<%k$H%K%e!<%9%j!<%@!<$K$h$C$F%5%]!<%H$5$l$k$G$7$g$&!#\e(B
+
+@cindex x-face
+@findex gnus-article-display-x-face
+@vindex gnus-article-x-face-command
+@vindex gnus-article-x-face-too-ugly
+@iftex
+@iflatex
+\include{xface}
+@end iflatex
+@end iftex
+@c @anchor{X-Face}
+
+@code{X-Face} \e$B%X%C%@!<$NI|9f$K$O!"\e(BEmacs \e$B$,\e(B @samp{compface} \e$B$r%5%]!<\e(B
+\e$B%H\e(B (XEmacs \e$B$N$[$H$s$I$,%5%]!<%H\e(B) \e$B$7$F$$$k$+!"$"$J$?$N%7%9%F%`\e(B
+\e$B$K\e(B @samp{compface} \e$B$,%$%s%9%H!<%k$5$l$F$$$kI,MW$,$"$j$^$9!#$b$7$I$A$i$+\e(B
+\e$B$,??$J$i$P!"\e(Bgnus \e$B$O%G%#%U%)%k%H$G\e(B @code{X-Face} \e$B%X%C%@!<$rI=<($7$^$9!#\e(B
+
+\e$B$3$l$r@)8f$9$k$N$OJQ?t\e(B @code{gnus-article-x-face-command} \e$B$G$9!#$3$NJQ?t\e(B
+\e$B$,J8;zNs$J$i$P!"$3$NJ8;zNs$,%5%V%7%'%k$G<B9T$5$l$^$9!#4X?t$J$i$P!"$3$N4X\e(B
+\e$B?t$,4i$r0z?t$H$7$F8F$P$l$^$9!#$b\e(B
+\e$B$7\e(B @code{gnus-article-x-face-too-ugly} (\e$B$3$l$O@55,I=8=$G\e(B
+\e$B$9\e(B) \e$B$,\e(B @code{From} \e$BMs$K9gCW$9$l$P!"4i$OI=<($5$l$^$;$s!#\e(B
+
+Emacs 20 \e$B$G$N%G%#%U%)%k%H$NF0:n$O\e(B @code{display} \e$B%W%m%0%i\e(B
+\e$B%`\e(B @footnote{@code{display} \e$B$O\e(B ImageMagick \e$B%Q%C%1!<%8$K4^$^$l$F$$$^$9!#\e(B
+@code{uncompface} \e$B$H\e(B @code{icontopbm} \e$B$NN>%W%m%0%i%`$K$D$$$F$O!"\e(B
+`compface' \e$B$d\e(B GNU/Linux \e$B%7%9%F%`$K$*$1$k\e(B `faces-xface' \e$B$N$h$&$J%Q%C%1!<\e(B
+\e$B%8$rC5$7$F2<$5$$!#\e(B} \e$B$r%U%)!<%/$7$F8+$h$&$H$7$^$9!#\e(B
+
+XEmacs \e$B$+@E;_2h$r%5%]!<%H$7$F$$$k\e(B Emacs 21+ \e$B$G$N%G%#%U%)%k%H$NF0:n\e(B
+\e$B$O\e(B @code{From} \e$BMs$NA0$K4i$rI=<($9$k$3$H$G$9!#\e(B(XEmacs \e$B$,\e(B X-Face \e$B5!G=IU$-\e(B
+\e$B$G%3%s%Q%$%k$5$l$F$$$k$HNI$$$G$7$g$&!=!=$=$l$OI=<($r>/$7Aa$/$7$^$9!#$b$7\e(B
+\e$B:,K\E*\e(B X-Face \e$B5!G=$,$J$$$N$G$"$l$P!"\e(Bgnus \e$B$O\e(B @code{pbmplus} \e$B$d$=$NCg4V$N\e(B
+\e$B30It%W%m%0%i%`$r;H$C$F\e(B @code{X-Face} \e$BMs$rJQ49$7$h$&$H;n$_$^$9\e(B @footnote{
+GNU/Linux \e$B%7%9%F%`$G$O\e(B @code{netpbm}\e$B!"\e(B@code{libgr-progs} \e$B$^$?\e(B
+\e$B$O\e(B @code{compface} \e$B$N$h$&$JL>A0$N%Q%C%1!<%8$rC5$7$F2<$5$$!#\e(B}\e$B!#\e(B)
+
+(\e$BCm\e(B: \e$BJQ?t\e(B/\e$B4X?tL>$K$O\e(B @code{xface} \e$B$G$O$J$/\e(B @code{x-face} \e$B$,;H$o$l$^$9!#\e(B)
+
+gnus \e$B$O!"30$K=P$9%a%C%;!<%8$K\e(B X-Face \e$B%X%C%@!<$r4JC1$KA^F~$9$k$?$a$N!"JX\e(B
+\e$BMx$J4X?t$HJQ?t$r>/$7$P$+$jDs6!$7$^$9!#\e(B
+
+@findex gnus-random-x-face
+@vindex gnus-convert-pbm-to-x-face-command
+@vindex gnus-x-face-directory
+@code{gnus-random-x-face} \e$B$O\e(B @code{gnus-x-face-directory} \e$B$K$"$k$9$Y$F\e(B
+\e$B$N\e(B @samp{pbm} \e$B$r$/$^$J$/C5$7$F%i%s%@%`$K0l$D$rA*$S<h$j!"%7%'%k%3%^%s\e(B
+\e$B%I\e(B @code{gnus-convert-pbm-to-x-face-command} \e$B$r;H$C$F$=$l$r\e(B X-Face \e$B$N7A\e(B
+\e$B<0$KJQ49$7$^$9!#\e(B@samp{pbm} \e$B%U%!%$%k$O\e(B 48\e$B!_\e(B48 \e$B2hAG$NBg$-$5$G$J$1$l$P$J$j\e(B
+\e$B$^$;$s!#$=$l$O\e(B X-Face \e$B%X%C%@!<$N%G!<%?$rJ8;zNs$GJV$7$^$9!#\e(B
+
+@findex gnus-insert-random-x-face-header
+@code{gnus-insert-random-x-face-header} \e$B$O\e(B @code{gnus-random-x-face} \e$B$r\e(B
+\e$B8F$s$G!"%i%s%@%`$K@8@.$5$l$?%G!<%?$K$h$k\e(B X-Face \e$B%X%C%@!<$rA^F~$7$^$9!#\e(B
+
+@findex gnus-x-face-from-file
+@vindex gnus-convert-image-to-x-face-command
+@code{gnus-x-face-from-file} \e$B$O%Q%i%a!<%?$H$7$F\e(B GIF \e$B%U%!%$%k$r<u$1<h$j!"\e(B
+\e$B%7%'%k%3%^%s%I\e(B @code{gnus-convert-image-to-x-face-command} \e$B$r;H$C$F$=$N\e(B
+\e$B%U%!%$%k$r\e(B X-Face \e$B$N7A<0$KJQ49$7$^$9!#\e(B
+
+\e$B0lHVL\$O0lHLE*$K;H$&$G$"$m$&4X?t$G$9!#0J2<$N$h$&$J$b$N\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$K=q$$$F2<$5$$\e(B:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(X-Face . gnus-random-x-face))))
+@end lisp
+
+\e$B:G8e$N4X?t$r;H$&$N$O!"$3$N$h$&$K$J$k$G$7$g$&\e(B:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(X-Face . (lambda ()
+                                (gnus-x-face-from-file
+                                 "~/My-face.gif"))))))
+@end lisp
+
+@node Face
+@subsection Face
+@cindex face
+
+@c #### FIXME: faces and x-faces'implementations should really be harmonized.
+
+@code{Face} \e$B%X%C%@!<$O!"K\<AE*$K$h$j%U%!%s%-!<$J\e(B @code{X-Face} \e$B$NJQ7A$G\e(B
+\e$B$9!#$=$l$i$O!"%a%C%;!<%8$r=q$$$??M$r>]D'$7$F$$$k$3$H$,4|BT$5$l$k!"\e(B
+48\e$B!_\e(B48 \e$B2hAG$N%+%i!<2hA|$rIA$-$^$9!#\e(B
+
+@cindex face
+@findex gnus-article-display-face
+@code{Face} \e$B%X%C%@!<$NFbMF$O!"\e(Bbase64 \e$B$G%(%s%3!<%I$5$l$?\e(B PNG \e$B$N2hA|$G$J$1\e(B
+\e$B$l$P$J$j$^$;$s!#@53N$J;EMM$K$D$$$F!"\e(B
+@uref{http://quimby.gnus.org/circus/face/} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+\e$BAw?.$9$k%a%C%;!<%8$K4JC1$K\e(B Face \e$B%X%C%@!<$rA^F~$G$-$k$h$&$K$9$k$?$a$K!"\e(B
+Gnus \e$B$O\e(B 2\e$B!A\e(B3 \e$B$N4X?t$HJQ?t$rDs6!$7$^$9!#\e(B
+
+@findex gnus-convert-png-to-face
+@code{gnus-convert-png-to-face} \e$B$O\e(B 726-byte \e$B0J2<$N\e(B 48\e$B!_\e(B48 \e$B$N\e(B PNG \e$B$N2hA|\e(B
+\e$B$rFI$_9~$s$G!"$=$l$r\e(B Face \e$B$KJQ49$7$^$9!#\e(B
+
+@findex gnus-face-from-file
+@vindex gnus-convert-image-to-face-command
+@code{gnus-face-from-file} \e$B$O\e(B JPEG \e$B$N%U%!%$%kL>$r%Q%i%a!<%?$H$7$F<u$1<h\e(B
+\e$B$j!"\e(Bshell \e$B%3%^%s%I\e(B @code{gnus-convert-image-to-face-command} \e$B$r;H$C$F$=\e(B
+\e$B$N%U%!%$%k$r\e(B Face \e$B%U%)!<%^%C%H$KJQ49$7$^$9!#\e(B
+
+\e$B$3$N4X?t$NBeI=E*$J;H$$J}$r5s$2$F$*$-$^$7$g$&!#0J2<$N$h$&$J$b$N\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$KF~$l$F2<$5$$\e(B:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(Face . (lambda ()
+                              (gnus-face-from-file "~/face.jpg"))))))
+@end lisp
+
+@node Smileys
+@subsection \e$B%9%^%$%j!<\e(B
+@cindex smileys
+
+@iftex
+@iflatex
+\gnusfig{-3cm}{0.5cm}{\epsfig{figure=ps/BigFace,height=20cm}}
+\input{smiley}
+@end iflatex
+@end iftex
+
+\e$B%9%^%$%j!<\e(B @dfn{smiley} \e$B$O\e(B gnus \e$B$H$OJL$N%Q%C%1!<%8$G$9$,!"%9%^%$%j!<$r;H$C\e(B
+\e$B$F$$$k%Q%C%1!<%8$O8=:_\e(B gnus \e$B$@$1$G$9$N$G!"$3$3$G@bL@$7$^$9!#\e(B
+
+\e$B0l8@$G8@$($P\e(B --- gnus \e$B$G%9%^%$%j!<$r;H$&$K$O!"0J2<\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B%U%!%$%k$K=q$$$F$/$@$5$$!#\e(B
+
+@lisp
+(setq gnus-treat-display-smileys t)
+@end lisp
+
+\e$B%9%^%$%j!<$O!"J8;z$N4i%^!<%/\e(B --- @samp{:-)}, @samp{8-)}, @samp{:-(} \e$B$J$I\e(B
+\e$B$H$$$C$?$b$N\e(B --- \e$B$r3($KBP1~$5$;!"J8;z$N4i%^!<%/$NBe$o$j$K$=$N3($rI=<($7\e(B
+\e$B$^$9!#$3$NJQ49$OJ8;z$K%^%C%A$9$k@55,I=8=$H$=$l$N%U%!%$%kL>$X$NBP1~$N%j%9\e(B
+\e$B%H$G@)8f$5$l$^$9!#\e(B
+
+@vindex smiley-regexp-alist
+\e$B;H$o$l$kO"A[%j%9%H$O!"JQ?t\e(B @code{smiley-regexp-alist} \e$B$G@_Dj$7$^$9!#3FMW\e(B
+\e$BAG$N:G=i$N9`L\$O%^%C%A$5$;$?$$@55,I=8=$G!"FsHVL\$NMWAG$O3($GCV$-49$($?$$\e(B
+\e$B%0%k!<%W$K%^%C%A$9$k@55,I=8=!"$=$7$F;0HVL\$NMWAG$OI=<($5$;$?$$%U%!%$%k$N\e(B
+\e$BL>A0$G$9!#\e(B
+
+\e$B0J2<$NJQ?t$O!"%9%^%$%j!<$,$3$l$i$N%U%!%$%k$rC5$9>l=j$r%+%9%?%^%$%:$7$^$9\e(B:
+
+@table @code
+@item smiley-data-directory
+@vindex smiley-data-directory
+\e$B%9%^%$%j!<$,4i%U%!%$%k$rC5$9>l=j!#\e(B
+
+@item gnus-smiley-file-types
+@vindex gnus-smiley-file-types
+\e$B%9%^%$%j!<$N%U%!%$%kL>$H$7$F;n$7$F$_$k3HD%;R$N%j%9%H$G$9!#\e(B
+@end table
+
+@node Picons
+@subsection Picons
+
+@iftex
+@iflatex
+\include{picons}
+@end iflatex
+@end iftex
+
+\e$B$=$l$G!D!"$"$J$?$O$3$N%K%e!<%9%j!<%@!<$r$5$i$K$b$C$HCY$/$7$?$$$C$F$o$1$@\e(B
+\e$B$M\e(B! \e$B$3$l$O$=$&$9$k$N$K$T$C$?$j$JJ}K!$G$9!#$5$i$K$3$l$O!"$"$J$?$,%K%e!<%9\e(B
+\e$B$rFI$s$G$$$k$s$@$H$$$&$3$H$r!"$"$J$?$N8*1[$7$K8+$D$a$F$$$k?M$K0u>]$E$1$k\e(B
+\e$B$?$a$NAG@2$i$7$$J}K!$G$b$"$j$^$9!#\e(B
+
+Picon \e$B$H$O$J$s$G$7$g$&\e(B? Picons \e$B%&%'%V%5%$%H$+$iD>@\0zMQ$7$^$7$g$&!#\e(B
+
+@iftex
+@iflatex
+\margindex{}
+@end iflatex
+@end iftex
+
+@quotation
+@dfn{Picon} \e$B$H$O!"\e(B``\e$B8D?M%"%$%3%s\e(B (personal icons)'' \e$B$NN,$G$9!#$3$l$O!"%M%C\e(B
+\e$B%H>e$NMxMQ<T$d%I%a%$%s$rI=8=$9$k$N$K;H$o$l$k$?$a$N>.$5$J2hA|$G!"%G!<%?%Y!<\e(B
+\e$B%9$r;}$?$;$F!"$"$kEE;R%a!<%k%"%I%l%9$,$"$C$?$i!"$=$l$KE,@Z$J2hA|$r8+$D$1\e(B
+\e$B$i$l$k$h$&$K$7$F$*$/$b$N$G$9!#MxMQ<T$H%I%a%$%s0J30$K$b!"\e(BUsenet \e$B%K%e!<%9\e(B
+\e$B%0%k!<%W$dE75$M=Js$N$?$a$N\e(Bpicon \e$B%G!<%?%Y!<%9$,$"$j$^$9!#\e(Bpicon \e$B$OGr9u\e(B
+\e$B$N\e(B @code{XBM} \e$B7A<0$G$b%+%i!<$N\e(B @code{XPM} \e$B7A<0$G$b\e(B @code{GIF} \e$B7A<0$G$b9=\e(B
+\e$B$$$^$;$s!#\e(B
+@end quotation
+
+@vindex gnus-picon-databases
+Picon \e$B%G!<%?%Y!<%9$NF~<j$H%$%s%9%H!<%k$N<j=g$K$D$$$F$O!"%&%'%V%V%i%&%6!<\e(B
+\e$B$G\e(B @uref{http://www.cs.indiana.edu/picons/ftp/index.html} \e$B$rK,$M$F$_$F2<\e(B
+\e$B$5$$!#\e(B
+
+\e$B$b$7\e(B Debian GNU/Linux \e$B$r;H$C$F$$$k$N$J$i!"\e(B@samp{apt-get install
+picons.*} \e$B$H8@$($P\e(B gnus \e$B$,8+$D$1$k$3$H$,$G$-$k\e(B picon \e$B$,%$%s%9%H!<%k$5$l\e(B
+\e$B$^$9!#\e(B
+
+Picon \e$B$NI=<($,$G$-$k$h$&$K$9$k$?$a$K$O!"\e(Bpicon \e$B%G!<%?%Y!<%9$,$"$k%G%#%l%/\e(B
+\e$B%H%j$,!"$?$@C1$K\e(B @code{gnus-picon-databases} \e$B$K@_Dj$5$l$F$$$k$h$&$K$7$F\e(B
+\e$B2<$5$$!#\e(B
+
+\e$B$b$N$4$H$N=j:_$r4IM}$9$k$?$a$K!"0J2<$NJQ?t$r@_$1$F$$$^$9!#\e(B
+
+@table @code
+@item gnus-picon-database
+@vindex gnus-picon-database
+Picon \e$B%G!<%?%Y!<%9$N>l=j$G$9!#$3$l$O\e(B @file{news}, @file{domains},
+@file{users} (\e$B$J$I$J$I\e(B) \e$B$N%5%V%G%#%l%/%H%j!<$,4^$^$l$F$$$k%G%#%l%/%H%j!<\e(B
+\e$B$N%j%9%H$G$9!#\e(B@code{("/usr/lib/picon" "/usr/local/faces")} \e$B$,%G%#%U%)%k\e(B
+\e$B%H$G$9!#\e(B
+
+@item gnus-picon-news-directories
+@vindex gnus-picon-news-directories
+@code{gnus-picon-database} \e$B$+$i%K%e!<%9%0%k!<%WMQ$N%U%'!<%9$rC5$9$?$a$N\e(B
+\e$B%5%V%G%#%l%/%H%j!<$N%j%9%H$G$9!#%G%#%U%)%k%H$O\e(B @code{("news")} \e$B$G$9!#\e(B
+
+@item gnus-picon-user-directories
+@vindex gnus-picon-user-directories
+@code{gnus-picon-database} \e$B$+$i%f!<%6$N%U%'!<%9$rC5$9$?$a$N%5%V%G%#%l%/\e(B
+\e$B%H%j!<$N%j%9%H$G$9!#\e(B@code{("local" "users" "usenix" "misc")} \e$B$,%G%#%U%)\e(B
+\e$B%k%H$G$9!#\e(B
+
+@item gnus-picon-domain-directories
+@vindex gnus-picon-domain-directories
+@code{gnus-picon-database} \e$B$+$i%I%a%$%sL>$N%U%'!<%9$rC5$9$?$a$N%5%V%G%#\e(B
+\e$B%l%/%H%j!<$N%j%9%H$G$9!#%G%#%U%)%k%H$O\e(B @code{("domains")} \e$B$G$9!#$3$N%j%9\e(B
+\e$B%H$K\e(B @samp{"unknown"} \e$B$rDI2C$7$F$*$-$?$/$J$k?M$b$$$k$G$7$g$&!#\e(B
+
+@item gnus-picon-file-types
+@vindex gnus-picon-file-types
+Picon \e$B$N%U%!%$%kL>$H$7$F;n$7$F$_$k3HD%;R$N=gHV%j%9%H$G$9!#%G%#%U%)%k%H$O!"\e(B
+@code{("xpm" "gif" "xbm")} \e$B$+$i\e(B Emacs \e$B$KAH$_9~$^$l$F$$$J$$$b$N$r=|30$7$?\e(B
+\e$B$b$N$G$9!#\e(B
+@end table
+
+@node XVarious
+@subsection \e$B$5$^$6$^$J\e(B XEmacs \e$BJQ?t\e(B
+
+@table @code
+@item gnus-xmas-glyph-directory
+@vindex gnus-xmas-glyph-directory
+\e$B$3$l$O\e(B gnus \e$B$,3($rC5$9>l=j$G$9!#\e(BGnus \e$B$ODL>o$3$N%G%#%l%/%H%j$r<+F08!=P$7\e(B
+\e$B$^$9$,!"$b$7I8=`E*$G$J$$%G%#%l%/%H%j!<9=B$$r;}$C$F$$$k>l9g$O!"$3$l$r<jF0\e(B
+\e$B$G@_Dj$9$k$3$H$,$G$-$^$9!#\e(B
+
+@item gnus-xmas-logo-color-alist
+@vindex gnus-xmas-logo-color-alist
+\e$B$3$l$OO"A[%j%9%H$G!"%-!<$O<oJL%7%s%\%k!"CM$O%?%$%H%kJG3(J8;z$NA0LL?'$HGX\e(B
+\e$B7J?'$G$9!#\e(B
+
+@item gnus-xmas-logo-color-style
+@vindex gnus-xmas-logo-color-style
+\e$B$3$l$OA05-$NO"A[%j%9%H$G?'$r8!:w$9$k$N$K;H$o$l$k%-!<$G$9!#M-8z$JCM$K\e(B
+\e$B$O\e(B @code{flame}, @code{pine}, @code{moss}, @code{irish}, @code{sky},
+@code{tin}, @code{velvet}, @code{grape}, @code{labia}, @code{berry},
+@code{neutral}, @code{september} \e$B$,$"$j$^$9!#\e(B
+
+@item gnus-xmas-modeline-glyph
+@vindex gnus-xmas-modeline-glyph
+\e$BA4$F$N\e(B gnus \e$B%b!<%I9T$GI=<($5$l$k3(J8;z!#$3$l$O=i4|@_Dj$G$O$A$$$5$J\e(B
+\e$B%L!<\e(B (gnu) \e$B$NF,$G$9!#\e(B
+@end table
+
+@subsubsection \e$B%D!<%k%P!<\e(B
+
+@table @code
+@item gnus-use-toolbar
+@vindex gnus-use-toolbar
+@code{nil} \e$B$J$i$P%D!<%k%P!<$rI=<($7$^$;$s!#\e(B@code{nil} \e$B0J30$N>l9g$O!"\e(B
+@code{default-toolbar}, @code{top-toolbar}, @code{bottom-toolbar},
+@code{right-toolbar}, @code{left-toolbar} \e$B$N$I$l$+$G$J$/$F$O$J$j$^$;$s!#\e(B
+
+@item gnus-group-toolbar
+@vindex gnus-group-toolbar
+\e$B%0%k!<%W%P%C%U%!Fb$N%D!<%k%P!<$G$9!#\e(B
+
+@item gnus-summary-toolbar
+@vindex gnus-summary-toolbar
+\e$B35N,%P%C%U%!Fb$N%D!<%k%P!<$G$9!#\e(B
+
+@item gnus-summary-mail-toolbar
+@vindex gnus-summary-mail-toolbar
+\e$B%a!<%k%0%k!<%W$N35N,%P%C%U%!Fb$N%D!<%k%P!<$G$9!#\e(B
+@end table
+
+@iftex
+@iflatex
+\margindex{}
+@end iflatex
+@end iftex
+
+@node Fuzzy Matching
+@section \e$B%U%!%8!<$J0lCW\e(B
+@cindex fuzzy matching
+
+Gnus \e$B$O!"%9%3%"IU$1!"%9%l%C%I$N7A@.!"%9%l%C%IHf3S$J$I$r9T$&$H$-$K!"\e(B
+@code{Subject} \e$B9T$N%U%!%8!<$J0lCW\e(B @dfn{fuzzy matching} \e$BJ}K!$rDs6!$7$F$$\e(B
+\e$B$^$9!#\e(B
+
+\e$B@55,I=8=0lCW$H$O0c$C$F!"%U%!%8!<$J0lCW$O$H$C$F$b%U%!%8!<$G$9!#$"$^$j$K$b\e(B
+\e$B%U%!%8!<$9$.$F!"2?$,%U%!%8!<\e(B @dfn{fuzziness} \e$B$G$"$k$+$H$$$&Dj5A$5$($"$j\e(B
+\e$B$^$;$s$7!"<BAu$b2?EY$bJQ99$5$l$F$$$^$9!#\e(B
+
+\e$B4pK\E*$K$O!"$3$l$OHf3S$NA0$K9T$+$i<YKbJ*$r<h$j=|$3$&$H$7$^$9!#\e(B
+@samp{Re: } \e$B$dA^F~6g$N0u$d6uGrJ8;zEy!9$OJ8;zNs$+$i=|5n$5$l!"$=$N7k2L$rHf\e(B
+\e$B3S$7$^$9!#$3$l$O$[$H$s$I$N>l9gBEEv$J7k2L$r=P$7$^$9\e(B --- \e$B$?$H$(%K%e!<%9%j!<\e(B
+\e$B%@!<$N2>LL$r$+$V$C$?J8;zNs@Z$j9o$_5!$G@8@.$5$l$?J8;zNs$,:9$7=P$5$l$F$b!"\e(B
+\e$B$G$9!#\e(B
+
+@node Thwarting Email Spam
+@section spam \e$B%a!<%k$NN"$r$+$/\e(B
+@cindex email spam
+@cindex spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+\e$B$3$3:G6a$N\e(B USENET \e$B$G$O!"@kEA$N%O%2%?%+$I$b$,!"H`$i$N:>5=$d@=IJ$r2!$7IU$1\e(B
+\e$B$k$?$a$NEE;R%a!<%k%"%I%l%9$rC5$=$&$H$7$F!"5$0c$$$N$h$&$K%K%e!<%9>e$r$&$m\e(B
+\e$B$D$$$F\e(B grep \e$B$7$^$/$C$F$$$^$9!#$3$l$KBP$9$kH?F0$H$7$F!"B?$/$N?M!9\e(B
+\e$B$,\e(B @code{From} \e$B9T$KL50UL#$J%"%I%l%9$rF~$l$O$8$a$k$h$&$K$J$C$F$7$^$$$^$7\e(B
+\e$B$?!#$3$l$OHs@8;:E*$J$3$H$@$H;d$O;W$$$^$9\e(B --- \e$B$"$J$?$,=q$$$?$3$H$KBP$9$k\e(B
+\e$BJV?.$H$7$F@5Ev$J%a!<%k$rAw$k$3$H$rLLE]$K$5$;!"$^$?C/$,=q$$$?$b$N$J$N$+$r\e(B
+\e$BJ,$+$j$E$i$/$7$^$9!#$3$s$J=q$-49$($O7k6I$O!"2!$7IU$1@kEA%a!<%k$=$l<+?H$h\e(B
+\e$B$j$bBg$-$J6<0R$H$J$k$+$b$7$l$^$;$s!#\e(B
+
+\e$B;d$K$H$C$F$N\e(B spam \e$B%a!<%k$N:GBg$NLdBj$O!"13$N8}<B$GF~$C$F$/$k$+$i$G$9!#;d\e(B
+\e$B$,\e(B @kbd{g} \e$B$r2!$7$?$H$9$k$H!"\e(Bgnus \e$B$O==DL$N?7Ce%a!<%k$,$"$j$^$9$HM[5$$K;d\e(B
+\e$B$K65$($F$/$l$^$9!#;d$O\e(B ``\e$B$*$*$C!"$o!<$$\e(B! \e$BKM$C$F9,$;\e(B!'' \e$B$H8@$C$F%a!<%k%0\e(B
+\e$B%k!<%W$rA*Br$7$^$9!#$7$+$7$=$3$K$O!"Fs$D$N%M%:%_9V$H!"<7$D$N9-\e(B
+\e$B9p\e(B (``\e$B:G?7\e(B! \e$B4q@W$NA}LS%H%K%C%/!"$U$5$U$5$G$D$d$D$d$NH1$r!"$"$J$?$N$D$^@h\e(B
+\e$B$^$G\e(B!'') \e$B$H!"2y$$2~$a?@$r?.$8$h!"$H$$$&0l$D$N%a!<%k$,$"$k$@$1$J$N$G$9!#\e(B
+
+\e$B$3$l$OITL{2w$G$9!#$"$J$?$,$=$l$K4X$7$F$G$-$k$3$H$,$"$j$^$9!#\e(B
+
+@menu
+* The problem of spam::         \e$BGX7J!"$=$7$F2r7h\e(B
+* Anti-Spam Basics::            \e$B$?$/$5$s$N\e(B spam \e$B$r8:$i$94JC1$JJ}K!\e(B
+* SpamAssassin::                Spam \e$BBP:v%D!<%k$N;H$$J}\e(B
+* Hashcash::                    CPU \e$B;~4V$rHq$d$7$F\e(B spam \e$BB`<#$9$k\e(B
+* Filtering Spam Using The Spam ELisp Package::
+* Filtering Spam Using Statistics with spam-stat::
+@end menu
+
+@node The problem of spam
+@subsection Spam \e$B$NLdBj\e(B
+@cindex email spam
+@cindex spam filtering approaches
+@cindex filtering approaches, spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+\e$B=i$a$K\e(B spam \e$B$NGX7J$+$i!#\e(B
+
+\e$B$"$J$?$,EE;R%a!<%k$r;H$C$F$$$k$J$i$P!"\e(Bspam (\e$B@lLgMQ8l$H$7$F$O\e(B Unsolicited
+Commercial E-mail -- \e$BK>$^$l$J$$>&MQEE;R%a!<%k\e(B -- \e$B$NF,J8\e(B
+\e$B;z\e(B @acronym{UCE}) \e$B$N$3$H$O$h$/CN$C$F$$$k$G$7$g$&!#4JC1$K8@$($P$=$l$O;f$N\e(B
+\e$B%a!<%k$KHf$Y$FEE;R%a!<%k$NG[Aw$,$H$F$b0B$/$D$/$?$a$KB8:_$7!"Hs>o$K>.$5$J\e(B
+\e$B3d9g$N?M!9$,\e(B UCE \e$B$K1~Ez$9$k$@$1$G9-9p<g$KMx1W$r$b$?$i$9$N$G$9!#HiFy$J$3\e(B
+\e$B$H$K:G$b0lHLE*$J\e(B spam \e$B$N0l$D$O!"$5$i$K\e(B spam \e$B$r=uD9$9$k$?$a$NEE;R%a!<%k%"\e(B
+\e$B%I%l%9$N%G!<%?%Y!<%9$rDs6!$7$^$9!#\e(BSpam \e$B$NAw?.<T$O$U$D\e(B
+\e$B$&\e(B @emph{spammers} \e$B$H8F$P$l$^$9$,!"\e(B@emph{vermin}\e$B!"\e(B@emph{scum}\e$B!"\e(B
+@emph{sociopaths} \e$B$*$h$S\e(B @emph{morons} \e$B$N$h$&$JMQ8l$b$h$/;H$o$l$F$$$^$9!#\e(B
+
+Spam \e$B$O<o!9$5$^$6$^$J=P$I$3$m$+$i$d$C$FMh$^$9!#M-MQ$J%a%C%;!<%8$r<N$F$:\e(B
+\e$B$K$9$Y$F$N\e(B spam \e$B$rC1$K;OKv$9$k$3$H$OIT2DG=$G$9!#NI$$Nc$O\e(B TMDA (\e$BLuCm\e(B: \e$BAw\e(B
+\e$B?.$9$kEY$K%f%K!<%/$J%"%I%l%9$r;H$&\e(B) \e$B%7%9%F%`$G!"$=$l$O$"$J$?$,CN$i$J$$Aw\e(B
+\e$B?.<T$K!"H`$i$NEE;R%a!<%k$,FO$/A0$KH`$i$,@5Ev$JAw?.<T$G$"$k$3$H$N3NG'$r5a\e(B
+\e$B$a$^$9!#@5Ev$J=P$I$3$m$+$i$NEE;R%a!<%k$,\e(B TMDA \e$B%7%9%F%`$K$h$C$F$=$l$i$N=P\e(B
+\e$B$I$3$m$,3NG'$G$-$J$$!"$^$?$O9T$J$o$l$J$$>l9g$O<N$F$i$l$F$7$^$&$+$b$7$l$J\e(B
+\e$B$$$H$$$&%^%$%J%9LL$O!"\e(BTMDA \e$B$N5;=QE*$JB&LL$KN)$AF~$i$J$/$F$bL@Gr$G$9!#$b\e(B
+\e$B$&0l$D$N\e(B TMDA \e$B$NLdBj$O!"EE;R%a!<%k$NG[Aw$H=hM}$X$N4pK\E*$JM}2r$r%f!<%6!<\e(B
+\e$B$K5a$a$F$$$k$3$H$G$9!#\e(B
+
+Spam \e$B$N=|5n\e(B (filtering) \e$B$X$N:G$bC1=c$J<h$jAH$_$O!"%a!<%k%5!<%P!<$G!"$"$k\e(B
+\e$B$$$OF~$C$F$-$?%a!<%k$rJ,N`$9$k$H$-$K_I2a$9$k$3$H\e(B (filtering) \e$B$G$9!#Kh\e(B
+\e$BF|\e(B @samp{random-address@@vmadmin.com} \e$B$+$i\e(B 200\e$BDL$N\e(B spam \e$B%a%C%;!<%8$r<u$1\e(B
+\e$B<h$k$N$J$i$P!"\e(B@samp{vmadmin.com} \e$B$rAK;_$9$l$P$h$m$7$$!#\e(B
+@samp{\e$B%P%$%"%0%i\e(B} \e$B$K4X$9$k%a%C%;!<%8$r\e(B 200\e$BDL<u$1<h$k$N$J$i$P!"\e(B
+@samp{\e$B%P%$%"%0%i\e(B} \e$B$r4^$`$9$Y$F$N%a%C%;!<%8$r<N$F$F$7$^$($P$h$m$7$$!#Nc$(\e(B
+\e$B$P!"Cf9q$+$i$?$/$5$s$N\e(B spam \e$B$,$d$C$FMh$k$N$J$i$P!"Cf9q$N\e(B IP \e$B$+$iMh$k$9$Y\e(B
+\e$B$F$N%a!<%k$r_I2a$9$l$P$h$m$7$$!#\e(B
+
+\e$B$3$l$O!";DG0$J$,$i@5Ev$JEE;R%a!<%k$r<N$F$k$?$a$N$9$0$l$?J}K!$G$9!#Nc$($P!"\e(B
+\e$B$H$F$b<(:6$KIY$s$GM-1W$J\e(B RISKS \e$B%@%$%8%'%9%H$O!"$=$l$,\e(B spam \e$B%a%C%;!<%8$H\e(B
+\e$B6&DL$N8l$r\e(B @strong{\e$B4^$s$G\e(B} \e$B$$$k$?$a$K!"G.?4$9$.$k%a!<%k_I2a4o$K$h$C$FAK\e(B
+\e$B;_$5$l$F$7$^$$$^$9!#$"$J$?$K@\?($7$h$&$H$9$kCO0hA4BN$rIu$89~$a$F$7$^$&4m\e(B
+\e$B81$bL@$i$+$G$9!#$G$9$+$i!"$"$J$?$KA*Br8"$,$"$k$N$J$i$P!"$=$s$J$3$H$O$7$J\e(B
+\e$B$$$G2<$5$$!#$=$l$G$b$J$*8IN)$7$?4D6-$G$O!"Cm0U?<$/;H$&$3$H$K$h$C$FD>@\$N\e(B
+\e$B_I2a$OM-1W$K$J$jF@$^$9!#\e(B
+
+\e$B$b$&0l$D$NEE;R%a!<%k_I2a$X$N<h$jAH$_$OJ,;67?\e(B spam \e$B=hM}$G!"\e(BDCC (\e$BLuCm\e(B:
+Distributed Checksum Clearinghouse --
+@uref{http://www.rhyolite.com/anti-spam/dcc/}) \e$B$,$=$N$h$&$J%7%9%F%`$rF3\e(B
+\e$BF~$7$F$$$^$9!#K\<AE*$K$O!"@$3&Cf$N\e(B @var{N} \e$B8D$N%7%9%F%`$,!"%,!<%J!"%(%9\e(B
+\e$B%H%K%"$"$k$$$O%+%j%U%)%k%K%"$K$"$k%^%7%s\e(B @var{X} \e$B$,\e(B spam \e$BEE;R%a!<%k$rAw\e(B
+\e$B=P$7$F$$$k$3$H$rG'$a$?$i!"$=$l$i\e(B @var{N} \e$B8D$N%7%9%F%`$O\e(B @var{X} \e$B$^$?\e(B
+\e$B$O\e(B @var{X} \e$B$+$i$d$C$FMh$?\e(B spam \e$B%a!<%k$r%G!<%?%Y!<%9$K5-F~$7$^$9!#\e(BSpam \e$B8!\e(B
+\e$B=P$N4p=`$OJQ$o$j$^$9!#$=$l$OAw$i$l$?%a%C%;!<%8$N?t$d%a%C%;!<%8$NFbMF$J$I\e(B
+\e$B$G$"$k$+$b$7$l$^$;$s!#%a%C%;!<%8$,\e(B spam \e$B$+$I$&$+$rJ,;6=hM}%7%9%F%`$N%f!<\e(B
+\e$B%6$,CN$j$?$$>l9g!"H`$O$=$l$i$N\e(B @var{N} \e$B8D$N%7%9%F%`$N$&$A$N0l$D$rD4$Y$^\e(B
+\e$B$9!#\e(B
+
+\e$BJ,;67?\e(B spam \e$B=hM}$OF1;~$KB?$/$N%a%C%;!<%8$rAw$k\e(B spammers \e$B$HHs>o$K$h$/@o$C\e(B
+\e$B$F$/$l$^$9$,!"$=$l$O%f!<%6!<$,$+$J$jJ#;($J%A%'%C%/$r@_Dj$9$k$3$H$r5a$a$^\e(B
+\e$B$9!#>&MQ$H!"%U%j!<$JJ,;67?\e(B spam \e$B=hM}%7%9%F%`$,$"$j$^$9!#J,;67?\e(B spam \e$B=hM}\e(B
+\e$B$O!"$=$l<+BN$N4m81$b$O$i$s$G$$$^$9!#Nc$($P!"@5Ev$JAw?.<T$,\e(B spam \e$B$rAw$C$?\e(B
+\e$B$+$I$GHsFq$5$l!"H`$i$N%&%'%V%5%$%H$d%a!<%j%s%0%j%9%H$,$=$N;v7o$N$?$a$K;C\e(B
+\e$B$/$N4VJD:?$5$l$F$7$^$&!"$H$+!#\e(B
+
+Spam \e$B_I2a$X$NE}7WE*$J<h$jAH$_$b$^$?Ia5Z$7$F$$$^$9!#$=$l$O2a5n$N\e(B spam \e$B%a%C\e(B
+\e$B%;!<%8$NE}7WJ,@O$K4p$E$$$F$$$^$9!#DL>o$=$NJ,@O$O!"$*$=$i$/C18l$NBP$+;0$D\e(B
+\e$B$NC18l$NAH9g$;$N9g@.$K$h$k!"C18l$N=P8=IQEY$NC1=c$J7W?t$G$9!#\e(BSpam \e$B$NE}7W\e(B
+\e$BJ,@O$O$[$H$s$I$N>l9g$K$H$F$b$h$/F/$/$N$G$9$,!";~$H$7$F@5Ev$JEE;R%a!<%k\e(B
+\e$B$r\e(B spam \e$B$H$7$FJ,N`$7$F$7$^$&$3$H$,$"$j$^$9!#J,@O$K$O;~4V$,$+$+$j$^$9!#$9\e(B
+\e$B$Y$F$N%a%C%;!<%8$rJ,@O$7$J$1$l$P$J$j$^$;$s!#$=$7$F%f!<%6!<$O\e(B spam \e$B$rJ,@O\e(B
+\e$B$9$k$?$a$N%G!<%?%Y!<%9$rMQ0U$7$J$1$l$P$J$j$^$;$s!#%5!<%P!<$G$NE}7WJ,@O$O\e(B
+\e$B?M5$$rF@$F$$$^$9!#$3$l$K$O!"%f!<%6!<$OC1$K%a!<%k$rFI$a$PNI$$$H$$$&D9=j$H!"\e(B
+\e$B$7$+$7%5!<%P!<$K$=$l$,2a$C$F%a!<%k$rJ,N`$7$?$3$H$rEA$($k$N$,:$Fq$@$H$$$&\e(B
+\e$BC;=j$,$"$j$^$9!#\e(B
+
+\e$BM>?M$N8@$rBT$?$:$H$b!"\e(Bspam \e$B$H$N@o$$$O3Z$G$O$"$j$^$;$s!#%^%^$+$i$NEE;R%a!<\e(B
+\e$B%k$H%P%$%"%0%i9-9p$r6hJL$9$kKbK!$N%9%$%C%A$O$"$j$^$;$s!#?M!9$O\e(B
+\e$BHs\e(B-spam \e$B$H\e(B spam \e$B$r6hJL$9$k$N$K<j$r>F$$$F$$$k$H$$$&$N$K!#$=$l$O!"\e(B
+spammers \e$B$,7|L?$K$=$l$i$r%^%^$@$H;W$o$;$h$&$H$7$F$$$k$N$,K\<A$@$+$i$G$9!#\e(B
+Spamming \e$B$O!"@$3&$,H`$i$K285A$,$"$k$H;W$C$F$$$k?M!9$N0lCD$+$i$N!"J"N)$?\e(B
+\e$B$7$/!"L5@UG$$G!"$P$+$2$?9T0Y$G$9!#0J2<$N3F9`$,\e(B spam \e$B$J$k1VIB$H$N@o$$$N=u\e(B
+\e$B$1$K$J$k$3$H$rK>$_$^$9!#\e(B
+
+@node Anti-Spam Basics
+@subsection Spam \e$BB`<#$N4pAC\e(B
+@cindex email spam
+@cindex spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+Spam \e$B$KBP=h$9$k0l$D$NJ}K!$O!"\e(Bgnus \e$B$KA4$F$N\e(B spam \e$B$r\e(B @samp{spam} \e$B%a!<%k%0\e(B
+\e$B%k!<%W$KJ,N%$5$;$F$7$^$&$3$H$G$9\e(B (@pxref{Splitting Mail})\e$B!#\e(B
+
+\e$B:G=i$K!"$"$J$?$KE~C#@-$N$"$k@5$7$$%a!<%k%"%I%l%9$r0l$DA*$S!"$=$l$rA4$F$N\e(B
+\e$B$"$J$?$N%K%e!<%95-;v$N\e(B @code{From} \e$B%X%C%@!<$KF~$l$^$9!#\e(B(\e$B$3$3$G$O\e(B
+@samp{larsi@@trym.ifi.uio.no} \e$B$rA*$S$^$7$?$,!"\e(B
+@samp{larsi+usenet@@ifi.uio.no} \e$B7A<0$N$?$/$5$s$N%"%I%l%9$NJ}$,NI$$A*Br$G\e(B
+\e$B$9!#$"$J$?$N%5%$%H$N\e(B sendmail \e$B$N@_Dj$,%a!<%k%"%I%l%9$N%m!<%+%kIt$H$7$F$I\e(B
+\e$B$s$J%-!<%o!<%I$r<u$1IU$1$k$+$O!"$"$J$?$N%5%$%H$N%7%9%F%`4IM}<T$KJ9$$$F$/\e(B
+\e$B$@$5$$!#\e(B)
+
+@lisp
+(setq message-default-news-headers
+      "From: Lars Magne Ingebrigtsen <larsi@@trym.ifi.uio.no>\n")
+@end lisp
+
+\e$B$=$7$F\e(B @code{nnmail-split-fancy} \e$B$K0J2<$NJ,N%5,B'$rF~$l$^\e(B
+\e$B$9\e(B (@pxref{Fancy Mail Splitting})\e$B!#\e(B
+
+@lisp
+(...
+ (to "larsi@@trym.ifi.uio.no"
+     (| ("subject" "re:.*" "misc")
+        ("references" ".*@@.*" "misc")
+        "spam"))
+ ...)
+@end lisp
+
+\e$B$3$N0UL#$O!"$3$N%"%I%l%9$KFO$$$?A4$F$N%a!<%k$r$^$:5?$$$^$9$,!"\e(B
+@samp{Re:} \e$B$G;O$^$k\e(B @code{Subject} \e$B$,$D$$$F$$$k$+!"\e(B@code{References} \e$B%X%C\e(B
+\e$B%@!<$,$D$$$F$$$l$P$*$=$i$/\e(B OK \e$B$@$m$&!"$H$$$&$3$H$G$9!#;D$j$OA4$F\e(B
+@samp{spam} \e$B%0%k!<%W$K9T$-$^$9!#\e(B(\e$B$3$N%"%$%G%"$O$*$=$i$/\e(B Tim Pierce \e$B;a$K\e(B
+\e$B$h$k$b$N$G$9!#\e(B)
+
+\e$B$3$l$K2C$($F!"B?$/$N%a!<%k\e(B spam \e$B20$O!"$"$J$?$N$H$3$m$N\e(B @acronym{SMTP} \e$B%5!<\e(B
+\e$B%P!<$HD>@\OC$7!"\e(B@code{To} \e$B%X%C%@!<$K$"$J$?$N%a!<%k%"%I%l%9$,L@<($5$l$J$$\e(B
+\e$B$h$&$K$7$^$9!#$J$s$G$=$s$J$3$H$r$9$k$N$+$O$o$+$j$^$;$s$,\e(B --- \e$B$*$=$i$/;d\e(B
+\e$B$?$A$NN"$r$+$/5!9=$NN"$r$+$/$?$a$+$J\e(B? \e$B$I$A$i$K$7$F$b!"BP=h$O4JC1$J$3$H$G\e(B
+\e$B$9\e(B --- \e$B$"$J$?08$F$G$J$$$b$N$rA4It\e(B @samp{spam} \e$B%0%k!<%W$K$$$l$k$@$1$G$9!#\e(B
+\e$B$3$l$O$*9%$_J,N%5,B'$N:G8e$K$3$s$JIw$KF~$l$k$3$H$G$G$-$^$9!#\e(B
+
+@lisp
+(
+ ...
+ (to "larsi" "misc")
+ "spam")
+@end lisp
+
+\e$B;d$N7P83$G$O!"$3$l$G;v<B>eA4$F$,@5$7$$%0%k!<%W$KJ,N`$5$l$^$9!#$^$"!"$=$l\e(B
+\e$B$G$b$H$-$I$-\e(B @samp{spam} \e$B%0%k!<%W$r%A%'%C%/$7$F!"@5$7$$%a!<%k$,$"$k$+%A%'%C\e(B
+\e$B%/$7$J$/$F$O$$$1$^$;$s$1$I$M!#$b$7$"$J$?$O<+J,$,NI$$%M%C%H%o!<%/;TL1$G$"\e(B
+\e$B$k$H;W$C$F$$$k$J$i!"$=$l$>$l$N2!$7IU$1@kEA%a!<%k$N4X78Ev6I$K6l>p$rAw$jIU\e(B
+\e$B$1$k$3$H$5$($b$G$-$^$9\e(B --- \e$B2K$J$H$-$K$G$b$M!#\e(B
+
+\e$B$3$l$G;d$N$H$3$m$G$OF0$$$F$$$^$9!#$3$l$G$_$s$J$O4JC1$JJ}K!$G;d$KO"Mm$r<h\e(B
+\e$B$k$3$H$,$G$-\e(B (\e$BIaDL$K\e(B @kbd{r} \e$B$r2!$9$@$1$G$G$-$k\e(B)\e$B!";d$O\e(B spam \e$B$KHQ$o$5$l$k\e(B
+\e$B$3$H$OA4$/$"$j$^$;$s!#F@!9>uBV$G$9!#;d$N0U8+$H$7$F$O!"\e(B@code{From} \e$B%X%C%@!<\e(B
+\e$B$r56B$$7$FB8:_$7$J$$%I%a%$%s$KAw$i$;$k$N$O%-%?%J%$$G$9!#\e(B
+
+\e$B$3$N<jK!$K$OCm0U$7$F2<$5$$!#\e(BSpammers \e$B$O$=$l$K5$IU$$$F$$$^$9!#\e(B
+
+@node SpamAssassin
+@subsection SpamAssassin, Vipul's Razor, DCC, etc
+@cindex SpamAssassin
+@cindex Vipul's Razor
+@cindex DCC
+
+Spam \e$B$rHr$1$k$?$a$NA09`$N%R%s%H$,==J,$@$C$?F|!9$O2a$.5n$j$^$7$?!#:#$G$O\e(B
+\e$B<u$1<h$C$?$?$/$5$s$N\e(B spam \e$B$r8:$i$9$?$a$NB?$/$NF;6q$,$"$j$^$9!#$3$N9`$O?7\e(B
+\e$B5lCV$-49$($K$h$C$F$9$0$K;~BeCY$l$K$J$C$F$7$^$&$G$7$g$&$,!"9,$$$J$3$H$K$[\e(B
+\e$B$H$s$I$NF;6q$ON`;w$N%$%s%?!<%U%'!<%9$r;}$C$F$$$^$9!#$3$N9`$ONc$H$7\e(B
+\e$B$F\e(B SpamAssassin \e$B$r;H$C$F$$$^$9$,!"B>$N$[$H$s$I$NF;6q$K$b4JC1$KE,9g$9$k$O\e(B
+\e$B$:$G$9!#\e(B
+
+\e$B$3$N9`$O\e(B @code{spam.el} \e$B%Q%C%1!<%8$H$O4X78L5$$$3$H$KCm0U$7$F2<$5$$!#$=$l\e(B
+\e$B$O<!$N9`$GO@$8$i$l$^$9!#$9$Y$F$N\e(B @code{spam.el} \e$B$N5!G=$K4X?4$,L5$$$N$J$i\e(B
+\e$B$P!"$3$l$i$NC1=c$J%l%7%T$G4V$K9g$o$;$k$3$H$,$G$-$^$9!#\e(B
+
+\e$B$b$7$"$J$?$,;H$&F;6q$,%a!<%k%5!<%P!<$K%$%s%9%H!<%k$5$l$F$$$J$$$J$i$P!"$"\e(B
+\e$B$J$?<+?H$,$=$l$r8F$S=P$9I,MW$,$"$j$^$9!#0J2<$K\e(B @code{:postscript} \e$B%a!<%k\e(B
+\e$B%=!<%9;X<(;R\e(B (@pxref{Mail Source Specifiers}) \e$B$r;H$&>l9g$N9M$(J}$r<($7$^\e(B
+\e$B$9!#\e(B
+
+@lisp
+(setq mail-sources
+      '((file :prescript "formail -bs spamassassin < /var/mail/%u")
+        (pop :user "jrl"
+             :server "pophost"
+             :postscript
+             "mv %t /tmp/foo; formail -bs spamc < /tmp/foo > %t")))
+@end lisp
+
+\e$B$$$C$?$s!"%a!<%k$r<u$1$k%9%W!<%k$r$I$&$K$+$7$F=hM}$9$k!"Nc$($P\e(B@: \e$B%a!<%k\e(B
+\e$B$K\e(B spam \e$B$G$"$k$3$H$rI=<($9$k%X%C%@!<$r4^$a$k!"$h$&$K$9$l$P!"$=$l$r$U$k$$\e(B
+\e$BMn$H$9=`Hw$O40N;$G$9!#;H$&$N$OIaDL$NJ,3dJ}<0\e(B (@pxref{Splitting Mail}) \e$B$G\e(B
+\e$B$9\e(B:
+
+@lisp
+(setq nnmail-split-methods '(("spam"  "^X-Spam-Flag: YES")
+                             ...))
+@end lisp
+
+\e$B$^$?$OFC5iJ,3dJ}<0\e(B (@pxref{Fancy Mail Splitting}) \e$B$G$9\e(B:
+
+@lisp
+(setq nnmail-split-methods 'nnmail-split-fancy
+      nnmail-split-fancy '(| ("X-Spam-Flag" "YES" "spam")
+                             ...))
+@end lisp
+
+\e$B$$$/$i$+$N?M$?$A$O\e(B @code{:prescript} \e$B$r;H$C$F%a!<%k$r$$$m$s$J%W%m%0%i%`\e(B
+\e$B$K%Q%$%W$9$k$3$H$r7y$&$+$b$7$l$^$;$s\e(B (\e$B$b$72?$+$N%W%m%0%i%`$K%P%0$,$"$C$?\e(B
+\e$B$i!"$9$Y$F$N%a!<%k$r<:$C$F$7$^$&$+$b$7$l$^$;$s\e(B)\e$B!#$"$J$?$,$=$l$i$N0l?M$J\e(B
+\e$B$i$P!"JL$N2r$OJ,3d$9$k$H$-$K30It$NF;6q$r8F$V$3$H$G$9!#FC5iJ,3dJ}<0$NNc$G\e(B
+\e$B$9\e(B:
+
+@lisp
+(setq nnmail-split-fancy '(| (: kevin-spamassassin)
+                             ...))
+(defun kevin-spamassassin ()
+  (save-excursion
+    (widen)
+    (if (eq 1 (call-process-region (point-min) (point-max)
+                                   "spamc" nil nil nil "-c"))
+        "spam")))
+@end lisp
+
+\e$B$5$i$K\e(B nnimap \e$B%P%C%/%(%s%I$N>l9g!"%G%#%U%)%k%H$G$O5-;v$N%\%G%#$,%@%&%s%m!<\e(B
+\e$B%I$5$l$J$$$3$H$KCm0U$7$F2<$5$$!#$=$l$r$9$k$?$a$K$O!"\e(B
+@code{nnimap-split-download-body} \e$B$r\e(B t \e$B$K@_Dj$9$kI,MW$,$"$j$^\e(B
+\e$B$9\e(B (@pxref{Splitting in IMAP})\e$B!#\e(B
+
+\e$B0J>e$,$3$l$K4X$9$k$3$H$G$9!#$$$/$D$+$N\e(B spam \e$B$O$I$&$7$F$bAGDL$j$7$F$7$^$&\e(B
+\e$B$N$G!"\e(Bspam \e$B$rFI$`$O$a$K$J$C$?$H$-$K8F$V$?$a$N5$$NMx$$$?4X?t$,M_$7$$$G$7$g\e(B
+\e$B$&!#$3$l$,$=$N5$$NMx$$$?4X?t$G$9\e(B:
+
+@lisp
+ (defun my-gnus-raze-spam ()
+  "Submit SPAM to Vipul's Razor, then mark it as expirable."
+  (interactive)
+  (gnus-summary-show-raw-article)
+  (gnus-summary-save-in-pipe "razor-report -f -d")
+  (gnus-summary-mark-as-expirable 1))
+@end lisp
+
+@node Hashcash
+@subsection Hashcash
+@cindex hashcash
+
+Spam \e$B$H@o$&$?$a$N?7$7$$5;K!$O!"%a%C%;!<%8$rAw?.$9$k:]$K$$$/$P$/$+$NIiC4\e(B
+\e$B$rAw?.<T$K6/$$$^$9!#$3$l$O%$%s%?!<%M%C%HI8=`$N0lIt$G$O$J$$$N$G!"@$3&Cf$N\e(B
+\e$B$9$Y$F$N?M$,$3$N5;K!$r;H$&$3$H$OEv$F$K$G$-$J$$$H$$$&L@$i$+$J7gE@$,$"$j$^\e(B
+\e$B$9$,!">.5,LO$J6&F1BN$G$OLr$KN)$D$G$7$g$&!#\e(B
+
+\e$BA09`$NF;6qN`$,<B:]$K$&$^$/F/$$$?$H$7$F$b!"$=$l$i$O?7$7$$7A<0$N\e(B spam \e$B$,8=\e(B
+\e$B$l$k$?$S$K$7$g$C$A$e$&99?7$+$D@0Hw$5$l$k$3$H$K$h$C$F$N$_F0:n$7$^$9!#$3$N\e(B
+\e$B$3$H$O!">.$5$J%Q!<%;%s%F!<%8$N\e(B spam \e$B$,$$$D$bAGDL$j$7$F$7$^$&$3$H$r0UL#$7\e(B
+\e$B$^$9!#$=$l$O$^$?!"$I$3$+$G$@$l$+$,$=$l$i$NF;6q$r99?7$9$k$?$a$K!"$?$/$5$s\e(B
+\e$B$N\e(B spam \e$B$rFI$^$J$1$l$P$J$i$J$$$3$H$r$b0UL#$7$^$9!#\e(BHashcash \e$B$O$=$l$r2sHr\e(B
+\e$B$7$^$9$,!"Be$o$j$K$"$J$?$,EE;R%a!<%k$GO"Mm$9$k$9$Y$F$N?M$?$A$K!"$J$k$Y$/\e(B
+\e$B$=$N;EAH$_$r;H$C$F$b$i$&I,MW$,$"$j$^$9!#$"$J$?$O<BMQ\e(B (pragmatic) \e$B$H65\e(B
+\e$B>r\e(B (dogmatic) \e$B$NFs$D$N<h$jAH$_$r9M$($k$3$H$,$G$-$^$9!#$=$l$i$N<h$jAH$_$K\e(B
+\e$B$OMxE@$b$"$l$PITMx$JE@$b$"$j$^$9$,!"$=$l$O@$$NCf$G$OIaDL$N$3$H$G!"$=$l$i\e(B
+\e$B$rO"78$5$;$?$b$N$,B>$N$P$i$P$i$J$b$N$h$j6/NO$J$N$G$9!#\e(B
+
+@cindex X-Hashcash
+\e$B!V$$$/$P$/$+$NIiC4!W$H$O\e(B CPU \e$B;~4V$r>CHq$9$k$3$H$G!"6qBNE*$K$O0lDj?t$N%S%C\e(B
+\e$B%H$^$G%O%C%7%e$N>WFM\e(B (hash collision) \e$B$r7W;;$9$k$3$H$G$9!#$=$N7k2L$H$7$F\e(B
+\e$B$N\e(B hashcash \e$B%/%C%-!<$O\e(B @samp{X-Hashcash:} \e$B%X%C%@!<$KA^F~$5$l$^$9!#$b$C$H\e(B
+\e$B>\$7$$$3$H!"$=$7$F$3$N5!G=$r;H$&$?$a$K%$%s%9%H!<%k$9$kI,MW$,$"$k30It%"%W\e(B
+\e$B%j%1!<%7%g%s$N\e(B @code{hashcash} \e$B$K$D$$$F\e(B
+\e$B$O\e(B @uref{http://www.cypherspace.org/~adam/hashcash/} \e$B$r;2>H$7$F2<$5$$!#\e(B
+\e$B$5$i$J$k>pJs$,\e(B @uref{http://www.camram.org/} \e$B$G8+$D$+$k$G$7$g$&!#\e(B
+
+\e$BAw?.$9$k%a%C%;!<%8$N$=$l$>$l$K$D$$$F\e(B hashcash \e$B$r8F$\$&$H;W$&$J$i!"$3$s$J\e(B
+\e$B$U$&$K$7$F2<$5$$\e(B:
+
+@lisp
+(require 'hashcash)
+(add-hook 'message-send-hook 'mail-add-payment)
+@end lisp
+
+@file{hashcash.el} \e$B%i%$%V%i%j\e(B
+\e$B$O\e(B @uref{http://users.actrix.gen.nz/mycroft/hashcash.el} \e$B$+3+H/HG\e(B
+\e$B$N\e(B gnus \e$B$N\e(B contrib \e$B%G%#%l%/%H%j$K$"$j$^$9!#\e(B
+
+\e$B$$$/$D$+$NDI2C$NJQ?t$N@_Dj$b$7$J$1$l$P$J$j$^$;$s\e(B:
+
+@table @code
+@item hashcash-default-payment
+@vindex hashcash-default-payment
+\e$B$3$NJQ?t$O%O%C%7%e$N>WFM$r@.$9%G%#%U%)%k%H$N%S%C%H?t$r<($7$^$9!#5,DjCM\e(B
+\e$B$O\e(B 0 \e$B$G!"2?$b9T$J$o$l$J$$$3$H$r0UL#$7$^$9!#Ds0F$5$l$F$$$kM-8z$JCM\e(B
+\e$B$O\e(B 17 \e$B$+$i\e(B 29 \e$B$^$G$N?t$G$9!#\e(B
+
+@item hashcash-payment-alist
+@vindex hashcash-payment-alist
+\e$B2??M$+$N<u<h?M$O!"$"$J$?$K%G%#%U%)%k%H$h$jB?$/$N\e(B CPU \e$B;~4V$rHq$d$9$3$H$r\e(B
+\e$BMW5a$9$k$+$b$7$l$^$;$s!#$3$NJQ?t$O\e(B @samp{(@var{addr} @var{amount})} \e$B$N7A\e(B
+\e$B<0$NMWAG$N%j%9%H$G!"\e(B@var{addr} \e$B$O<u<h?M\e(B (\e$B%a!<%k%"%I%l%9$+%K%e!<%9%0%k!<\e(B
+\e$B%W\e(B)\e$B!"\e(B@var{amount} \e$B$OI,MW$H$5$l$k>WFM$N%S%C%H?t$G$9!#$3$l$O$^\e(B
+\e$B$?\e(B @samp{(@var{addr} @var{string} @var{amount})} \e$B$NMWAG$r;}$D$3$H$b2DG=\e(B
+\e$B$G!"\e(B@var{string} \e$B$OJ8;zNs\e(B (\e$BDL>o$O%a!<%k%"%I%l%9$+%K%e!<%9%0%k!<%WL>\e(B) \e$B$H\e(B
+\e$B$7$F;H$o$l$^$9!#\e(B
+
+@item hashcash
+@vindex hashcash
+@code{hashcash} \e$B%P%$%J%j$,%$%s%9%H!<%k$5$l$F$$$k>l=j$r<($7$^$9!#\e(B
+@end table
+
+\e$B:#$N$H$3$m\e(B gnus \e$B$K\e(B hashcash \e$B%/%C%-!<$rG'>Z$9$k<jCJ$O$"$j$^$;$s!#$"$J$?$,\e(B
+\e$B<j:n6H$G%a!<%k$r$U$k$$$K$+$1$k%9%/%j%W%H$r%+%9%?%^%$%:$9$k$3$H$,5a$a$i$l\e(B
+\e$B$F$$$^$9!#$7$+$7!"$3$NJ,Ln$K$*$1$k2~NI$OM-MQ$J9W8%$K$J$k$G$7$g$&!#\e(B
+
+@node Filtering Spam Using The Spam ELisp Package
+@subsection Spam ELisp \e$B%Q%C%1!<%8$r;H$C$?\e(B Spam \e$B$N_I2a\e(B
+@cindex spam filtering
+@cindex spam
+
+@file{spam.el} \e$B$N??$NL\E*$O\e(B spam \e$B8!=P$H_I2a$N$?$a$N41@)%;%s%?!<\e(B
+\e$B$r\e(B gnus \e$B$NCf$K;}$D$3$H$G$9!#$=$N$?$a$K\e(B @file{spam.el} \e$B$OFs$D$N$3$H$r9T$J\e(B
+\e$B$$$^$9\e(B: \e$B?7$7$$%a!<%k$r_I2a$7!"\e(Bspam \e$B$^$?$O\e(B ham \e$B$H$7$FCN$i$l$k%a!<%k$rJ,@O\e(B
+\e$B$9$k$3$H$G$9!#\e(B@dfn{Ham} \e$B$O\e(B @file{spam.el} \e$B$N$$$?$k=j$G\e(B spam \e$B$G$O$J$$%a%C\e(B
+\e$B%;!<%8$r<($9$?$a$K;H$&L>A0$G$9!#\e(B
+
+\e$BBh0l$K!"\e(B@code{spam.el} \e$B$r<+F0FI$_9~$_\e(B (autoload) \e$B$7$F\e(B @code{spam.el} \e$B$N\e(B
+\e$B3F%U%C%/$r%$%s%9%H!<%k$9$k$?$a$K!"4X\e(B
+\e$B?t\e(B @code{spam-initialize} \e$B$r\e(B @strong{\e$B<B9T$7$J$1$l$P$J$j$^$;$s\e(B}\e$B!#0l$DNc30\e(B
+\e$B$,$"$j$^$9\e(B: \e$B$b$7\e(B @code{spam-use-stat} \e$B$N@_Dj$r;H$&\e(B (@pxref{spam-stat
+spam filtering}) \e$B$N$G$"$l$P!"$=$l$r\e(B @code{spam-initialize} \e$B$h$jA0\e(B
+\e$B$K\e(B on \e$B$K$7$F$*$+$J$1$l$P$J$j$^$;$s\e(B:
+
+@example
+(setq spam-use-stat t) ;; \e$BI,MW$J$i\e(B
+(spam-initialize)
+@end example
+
+\e$B$G$O\e(B @file{spam.el} \e$B$rFI$_9~$`$H2?$,5/$-$k$G$7$g$&$+\e(B?
+
+\e$BBh0l$K\e(B @code{spam-initialize} \e$B$K$h$C$F$$$/$D$+$N%U%C%/$,F0:n$9$k$h$&$K$J\e(B
+\e$B$j$^$9!#\e(B@code{spam-stat} \e$B$,$=$l$i$N%G!<%?%Y!<%9$r%;!<%V$G$-$k$h$&$K$9$k\e(B
+\e$B%U%C%/$H!"%0%k!<%W$KF~$k$H$-$HH4$1$k$H$-$K6=L#?<$$J*;v$r5/$3$9%U%C%/$,$"\e(B
+\e$B$j$^$9!#%$%Y%s%H$N%7!<%1%s%9$K$D$$$F$N>\:Y$O8e=R\e(B (@pxref{Spam ELisp
+Package Sequence of Events})\e$B!#\e(B
+
+\e$B0J2<$N%-!<%\!<%IL?Na$,;H$($k$h$&$K$J$j$^$9\e(B:
+
+@table @kbd
+@item M-d
+@itemx M s x
+@itemx S x
+@kindex M-d
+@kindex S x
+@kindex M s x
+@findex gnus-summary-mark-as-spam
+@code{gnus-summary-mark-as-spam}\e$B!#\e(B
+
+\e$B8=:_$N5-;v$K\e(B spam \e$B$H$7$F0u$rIU$1!"$=$l$r\e(B @samp{$} \e$B0u$GI=<($7$^$9!#\e(B
+Spam \e$B5-;v$r8+$?$H$-$O$$$D$G$b!"%0%k!<%W$rH4$1$kA0$KI,$:\e(B @kbd{M-d} \e$B$G$=$N\e(B
+\e$B35N,9T$K0u$rIU$1$k$h$&$K$7$F2<$5$$!#$3$l$O\e(B @emph{spam} \e$B%0%k!<%W$NL$FI5-\e(B
+\e$B;v$KBP$7$F$O<+F0E*$K9T$J$o$l$^$9!#\e(B
+
+@item M s t
+@itemx S t
+@kindex M s t
+@kindex S t
+@findex spam-bogofilter-score
+@code{spam-bogofilter-score}\e$B!#\e(B
+
+\e$B$3$N%3%^%s%I$,$A$c$s$HF/$/$?$a$K$O\e(B Bogofilter \e$B$r%$%s%9%H!<%k$7$J$1$l$P$J\e(B
+\e$B$j$^$;$s!#\e(B
+
+@xref{Bogofilter}.
+
+@end table
+
+\e$B$^$?!"\e(B@file{spam.el} \e$B$rFI$_9~$`$H!"$=$NJQ?t72$r%+%9%?%^%$%:$9$k$3$H$,$G\e(B
+\e$B$-$k$h$&$K$J$j$^$9!#\e(B@samp{spam} \e$BJQ?t%0%k!<%W$K$D$$\e(B
+\e$B$F\e(B @code{customize-group} \e$B$r;n$7$F$_$F2<$5$$!#\e(B
+
+@menu
+* Spam ELisp Package Sequence of Events::
+* Spam ELisp Package Filtering of Incoming Mail::
+* Spam ELisp Package Global Variables::
+* Spam ELisp Package Configuration Examples::
+* Blacklists and Whitelists::
+* BBDB Whitelists::
+* Gmane Spam Reporting::
+* Anti-spam Hashcash Payments::
+* Blackholes::
+* Regular Expressions Header Matching::
+* Bogofilter::
+* ifile spam filtering::
+* spam-stat spam filtering::
+* SpamOracle::
+* Extending the Spam ELisp package::
+@end menu
+
+@node Spam ELisp Package Sequence of Events
+@subsubsection Spam ELisp Package Sequence of Events
+@cindex spam filtering
+@cindex spam filtering sequence of events
+@cindex spam
+
+\e$BI,$:$3$N9`$rFI$s$G2<$5$$!#\e(B@code{spam.el} \e$B$NF0:n$rM}2r$9$k$?$a$K!#FI$_Ht\e(B
+\e$B$P$7!"B.FI!"<P$aFI$_$O876X$G$9!#\e(B
+
+\e$B$"$J$?$,0U?^$9$k$J$i$P\e(B @code{spam.el} \e$B$H\e(B Gnus \e$B$NB>$NItJ,$N4V$KFs$D$N@\E@\e(B
+\e$B$,$"$j$^$9\e(B: spam \e$B$N$?$a$N?7Ce%a!<%k$N8!::!"$*$h$S%0%k!<%W$rH4$1$k>l9g$G\e(B
+\e$B$9!#\e(B
+
+\e$B?7Ce%a!<%k$N<hF@$OFs$D$N$&$A$N0lJ}$G9T$J$o$l$^$9!#$d$C$FCe$?%a!<%k$rJ,3d\e(B
+\e$B$7$?$j!"%0%k!<%W$KF~$k$H$-$K?7$7$$5-;v$r\e(B ham \e$B$H\e(B spam \e$B$KJ,N`$9$k$3$H$,$G\e(B
+\e$B$-$^$9!#\e(B
+
+\e$B$d$C$FMh$?%a!<%k$NJ,3d$O!"\e(B@code{nnml} \e$B$d\e(B @code{nnimap} \e$B$N$h$&$J!"?7$7$$\e(B
+\e$B%a!<%k$,\e(B @dfn{Spool File} \e$B$H8F$P$l$k0l$D$N%U%!%$%k$K$J$k%P%C%/%(%s%I$K!"\e(B
+\e$B$h$jE,$7$F$$$^$9!#\e(B
+@xref{Spam ELisp Package Filtering of Incoming Mail} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@code{nntp} \e$B$N$h$&$J%P%C%/%(%s%I$K$O$d$C$FMh$k%a!<%k$N%9%W!<%k$,L5$$$N$G!"\e(B
+\e$BBe$o$j$N5!9=$r;H$o$J$1$l$P$J$j$^$;$s!#$3$l$O!"%5!<%P!<$,$d$C$FMh$?%a!<%k\e(B
+\e$B$NJ,3d$rC4Ev$7$F$$$F!"\e(BGnus \e$B$,$5$i$KJ,3d$r9T$J$o$J$$%P%C%/%(%s%I$G$b5/$-\e(B
+\e$B$k$+$b$7$l$^$;$s!#%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B @code{spam-autodetect} \e$B$H\e(B @code{spam-autodetect-methods} (\e$BIaDL\e(B @kbd{G
+c} and @kbd{G p} \e$B$GA`:n2D\e(B)\e$B!"$=$7$FBP1~$9$kJQ\e(B
+\e$B?t\e(B @code{gnus-spam-autodetect-methods} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-spam-autodetect-methods} (@kbd{M-x customize-variable} \e$B$G\e(B
+\e$BA`:n2D\e(B) \e$B$G$9!#\e(B
+
+@code{spam-autodetect} \e$B$,;H$o$l$k>l9g!"$=$l$O%0%k!<%W$KF~$k=hM}$K0z$C$+\e(B
+\e$B$1$i$l$^$9!#$7$?$,$C$F!"$^$@FI$^$l$?$3$H$,L5$$!"$^$?$OL$FI$N5-;v$,$"$k%0\e(B
+\e$B%k!<%W$KF~$k$3$H$O!"$d$C$FMh$?%a!<%k$N8!::$NBe$o$j$K$J$j$^$9!#$^$@FI$^$l\e(B
+\e$B$?$3$H$,L5$$5-;v!"$^$?$O$9$Y$F$NL$FI$N5-;v$,=hM}$5$l$k$+$I$&$+$O!"\e(B
+@code{spam-autodetect-recheck-messages} \e$B$K$h$C$F7h$^$j$^$9!#\e(Bt \e$B$K@_Dj$5$l\e(B
+\e$B$k$H!"L$FI$N%a%C%;!<%8$,:F8!::$5$l$^$9!#\e(B
+
+@code{spam-autodetect} \e$B$O!"%f!<%6$K\e(B spam \e$B_I2a$NB?>/$N4IM}$rB(9oG'$a$^$9!#\e(B
+\e$B%f!<%6$O3F%0%k!<%W$N\e(B spam \e$B$N<jCJ$r$h$jB?$/4IM}$9$k$3$H$,$G$-$k$G$7$g$&!#\e(B
+\e$B$7$?$,$C$F!"\e(B@samp{suspect} \e$B%0%k!<%W$G\e(B @code{spam-use-blacklist} \e$B$*$h\e(B
+\e$B$S\e(B @code{spam-use-bogofilter} \e$B$N<jCJ$,M-8z$K$J$C$F$$$F$b!"\e(B
+\e$BNc$($P\e(B @samp{ding} \e$B%0%k!<%W$O<+F08!CN<jCJ$H$7$F\e(B @code{spam-use-BBDB} \e$B$r\e(B
+\e$B;}$D$3$H$,$G$-$^$9!#\e(BSpam \e$B$H$7$F8!CN$5$l$k$9$Y$F$N5-;v$K\e(B
+\e$B$O\e(B spam \e$B0u\e(B @samp{$}\e$B$,IU$1$i$l!"%0%k!<%W$rH4$1$k$H$-$KDL>o$N\e(B spam \e$B$H$7$F\e(B
+\e$B=hM}$5$l$^$9!#H`$,\e(B @code{spam-split} \e$B$G9T$J$C$F$bNI$$$h$&$K!"%f!<%6$O8!\e(B
+\e$B::$N\e(B @emph{sequence} \e$B$r$h$j>/$J$/4IM}$7$^$9!#\e(B
+
+\e$B?7$?$KJ,3d$5$l$?%a!<%k$,%0%k!<%W$KF~$C$?!"$^$?$O%a%C%;!<%8$,\e(B ham \e$B$^$?\e(B
+\e$B$O\e(B spam \e$B$H$7$F<+F08!CN$5$l$?>l9g!"8e$K\e(B spam \e$B=hM}$r9T$J$o$;$k$?$a$K!"$=$l\e(B
+\e$B$i$N%0%k!<%W$r\e(B (\e$BI,MW$J$iF~$C$?8e$G\e(B) \e$BH4$1=P$J$/$F$O$J$j$^$;$s!#%0%k!<%W$,\e(B
+\e$B$=$N\e(B @code{spam-content} \e$B%Q%i%a!<%?\e(B (@pxref{Spam ELisp Package Global
+Variables}) \e$B$K4p$E$$$F\e(B ham \e$B$^$?$O\e(B spam \e$B%0%k!<%W$H9M$($i$l$k$+!"L$J,N`$+\e(B
+\e$B$I$&$+$O=EMW$G$9!#\e(BSpam \e$B%0%k!<%W$O!"$=$3$KF~$k$H!"$^$@FI$^$l$?$3$H$,L5$$!"\e(B
+\e$B$^$?$OL$FI$N5-;v$K\e(B spam \e$B$N0u$,IU$1$i$l$k\e(B (\e$BJQ\e(B
+\e$B?t\e(B @code{spam-mark-only-unseen-as-spam} \e$B$K0MB8\e(B) \e$B$H$$$&DI2C$NFC@-$r;}$A$^\e(B
+\e$B$9!#$3$N$h$&$K!"J,3d$5$l$F\e(B spam \e$B%0%k!<%W$KF~$l$i$l$?5-;v$K$O!"$"$J$?$,$=\e(B
+\e$B$N%0%k!<%W$KF~$C$?$H$-$K<+F0E*$K\e(B spam \e$B$N0u$,IU$1$i$l$^$9!#\e(B
+
+\e$B$7$?$,$C$F!"%0%k!<%W$rH4$1$k$H\e(B @code{spam-processors} \e$B$,\e(B (\e$B2?$G$"$l@_Dj$5\e(B
+\e$B$l$F$$$l$P\e(B) \e$BE,MQ$5$l!"=hM}$5$l$?%a!<%k$O5-;v$NJ,N`$K4p$E$$\e(B
+\e$B$F\e(B @code{ham-process-destination} \e$B$+\e(B @code{spam-process-destination} \e$B$K\e(B
+\e$B0\F0$5$;$i$l$^$9!#\e(B@code{ham-process-destination} \e$B$^$?\e(B
+\e$B$O\e(B @code{spam-process-destination} \e$B$N$I$A$i$+$,\e(B (\e$BLuCp\e(B: \e$B0\F0@h$H$7$F\e(B) \e$BE,\e(B
+\e$B@Z$G!"$=$l$i$,\e(B nil \e$B$@$C$?>l9g!"$=$N5-;v$O8=:_$N%0%k!<%W$K;D$5$l$^$9!#\e(B
+
+\e$B$I$l$+$N%0%k!<%W$G\e(B spam \e$B$,8+$D$+$C$?$i\e(B (\e$BHs\e(B-spam \e$B%0%k!<%W$K8B$C\e(B
+\e$B$F\e(B @code{spam-move-spam-nonspam-groups-only} \e$B$GJQ992D\e(B)\e$B!"%0%k!<%W$rH4$1$k\e(B
+\e$B$H$-$K3h$-$F$$$k\e(B @code{spam-processors} (@pxref{Spam ELisp Package
+Global Variables}) \e$B$G=hM}$5$l$^$9!#$5$i$K!"8e$G%H%l!<%K%s%0$^$?$O:o=|$9\e(B
+\e$B$k$?$a$K!"\e(Bspam \e$B$O\e(B @code{spam-process-destination} (@pxref{Spam ELisp
+Package Global Variables}) \e$B$K0\F0$5$;$i$l$^$9!#\e(BSpam \e$B$,:F;0=hM}$5$l$k$3$H\e(B
+\e$B$rK>$^$J$$$J$i$P!"\e(B@file{gnus-registry.el} \e$B%Q%C%1!<%8$rFI$_9~$_!"\e(B
+@code{spam-log-to-registry} \e$BJQ?t$rM-8z$K$7$J$1$l$P$J$j$^$;$s!#$3$N$h$&\e(B
+\e$B$K\e(B spam \e$B$O$I$3$G$b8!CN$5$l=hM}$5$l$^$9!#$=$l$O$[$H$s$I$N?M!9$,K>$`$b$N$G\e(B
+\e$B$9!#\e(B@code{spam-process-destination} \e$B$,\e(B nil \e$B$@$C$?>l9g!"\e(Bspam \e$B$K$O4|8B@Z$l\e(B
+\e$B>C5n$N0u$,IU$1$i$l$^$9!#IaDL$=$l$O@5$7$$9T$J$$$G$9!#\e(B
+
+Spam \e$B$,0\F0$G$-$J$$>l9g\e(B (\e$BNc$($P\e(B NNTP \e$B$N$h$&$JFI$_9~$_@lMQ%P%C%/%(%s%I$N\e(B
+\e$B$?$a$K\e(B)\e$B!"$=$l$O%3%T!<$5$l$^$9!#\e(B
+
+Ham \e$B%0%k!<%W$G\e(B @code{ham-marks} \e$B%Q%i%a!<%?$G7hDj$5$l$k\e(B ham \e$B%a!<%k$,8+$D\e(B
+\e$B$+$C$?$i!"%0%k!<%W$rH4$1$k$H$-$K3h$-$F$$$k\e(B ham @code{spam-processor} \e$B$G\e(B
+\e$B=hM}$5$l$^$9!#$5$i$K!"JQ?t\e(B @code{spam-process-ham-in-spam-groups} \e$B$*$h\e(B
+\e$B$S\e(B @code{spam-process-ham-in-nonham-groups} \e$B$K$h$C$F!"$I$3$G8+$D$+$C\e(B
+\e$B$?\e(B ham \e$B$G$b=hM}$G$-$k$h$&$KF0:n$rJQ99$9$k$3$H$,$G$-$^$9!#\e(BHam \e$B$,:F;0=hM}\e(B
+\e$B$5$l$k$3$H$rK>$^$J$$$J$i$P!"\e(B@file{gnus-registry.el} \e$B%Q%C%1!<%8$rFI$_9~$_!"\e(B
+@code{spam-log-to-registry} \e$BJQ?t$rM-8z$K$7$J$1$l$P$J$j$^$;$s!#$3$N$h$&\e(B
+\e$B$K\e(B ham \e$B$OI,MW$J>l9g$@$18!CN$5$l=hM}$5$l$^$9!#$=$l$O$[$H$s$I$N?M!9$,K>$`\e(B
+\e$B$b$N$G$9!#$3$l$K4X$9$k>\:Y$O\e(B @xref{Spam ELisp Package Configuration
+Examples}.
+
+Ham \e$B$,0\F0$G$-$J$$>l9g\e(B (\e$BNc$($P\e(B NNTP \e$B$N$h$&$JFI$_9~$_@lMQ%P%C%/%(%s%I$N$?\e(B
+\e$B$a$K\e(B)\e$B!"$=$l$O%3%T!<$5$l$^$9!#\e(B
+
+\e$B$3$l$i$9$Y$F$,$o$1$,$o$+$i$J$/$F$b!"?4G[$OL5MQ$G$9\e(B (\e$BLuCm\e(B: \e$B$G$bLuJ8$,@53N\e(B
+\e$B$G$O$J$$$+$b$7$l$J$$$N$G!"JQ$@$H;W$C$?$i86J8$r;2>H$N$3$H\e(B :-p)\e$B!#$9$0$K$=\e(B
+\e$B$l$O?@7P%$%s%?!<%U%'!<%9>e$K\e(B Lisp \e$B<0$r%?%$%W$9$k$h$&$K<+A3$J$3$H$K$J$j$^\e(B
+\e$B$9\e(B... \e$B$(!+$4$a$s!"$=$l$K$O$^$@\e(B 50\e$BG/Aa$$$G$9$M!#$?$@;d$?$A$r?.Mj$7$F2<$5\e(B
+\e$B$$!#$=$l$O<N$F$?$b$N$G$O$"$j$^$;$s!#\e(B
+
+@node Spam ELisp Package Filtering of Incoming Mail
+@subsubsection Spam ELisp Package Filtering of Incoming Mail
+@cindex spam filtering
+@cindex spam filtering incoming mail
+@cindex spam
+
+\e$BF~$C$F$/$k%a!<%k$r_I2a$9$kL\E*$G\e(B @file{spam.el} \e$B$r;H$&$K$O!"FC5iJ,3d%j%9\e(B
+\e$B%H\e(B @code{nnmail-split-fancy} \e$B$^$?$O\e(B @code{nnimap-split-fancy} \e$B$K0J2<$rDI\e(B
+\e$B2C$7$J$1$l$P$J$j$^$;$s\e(B:
+
+@example
+(: spam-split)
+@end example
+
+\e$BFC5iJ,3d$O!"%a!<%k$N<h$j9~$_$K\e(B nnmail \e$B$+\e(B nnimap \e$B$N$I$A$i$N%P%C%/%(%s%I$r\e(B
+\e$B;H$C$F$$$k$+$K1~$8$F!"\e(B@code{nnmail-split-fancy} \e$B$^$?\e(B
+\e$B$O\e(B @code{nnimap-split-fancy} \e$B$+$i8F$P$l$k$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@code{spam-split} \e$B4X?t$OF~$C$F$/$k%a!<%k$r=hM}$7!"\e(Bspam \e$B$H;W$o$l$k%a!<%k\e(B
+\e$B$rJQ?t\e(B @code{spam-split-group} \e$B$GM?$($i$l$kL>A0$N%0%k!<%W$KAw$j$^$9!#%G%#\e(B
+\e$B%U%)%k%H$G$O$=$N%0%k!<%WL>$O\e(B @samp{spam} \e$B$G$9$,!"\e(B
+@code{spam-split-group} \e$B$r%+%9%?%^%$%:$9$k$3$H$,2DG=$G$9!#\e(B
+@code{spam-split-group} \e$B$NFbMF$,\e(B @emph{\e$B@dBP\e(B} \e$B%0%k!<%WL>$G$"$k$3$H!"Nc$(\e(B
+\e$B$P\e(B @samp{your-server} \e$B$H$$$&\e(B @code{nnimap} \e$B%5!<%P!<$N>l9g$O!"\e(B
+@samp{spam} \e$BJQ?t$,:G=*E*$K\e(B @samp{nnimap+your-server:spam} \e$B$K$J$k$3$H$r3N\e(B
+\e$B$+$a$F2<$5$$!#=>$C$F\e(B @samp{nnimap+server:spam} \e$B$H$$$&CM$O4V0c$$$G!"$=$l\e(B
+\e$B$O<B:]$K$O\e(B @samp{nnimap+your-server:nnimap+server:spam} \e$B$H$$$&%0%k!<%W$K\e(B
+\e$B$J$j!"$=$l$,F/$/$+F/$+$J$$$+$O!"$"$J$?$N%5!<%P!<$,4qL/$J%0%k!<%WL>$KBP$7\e(B
+\e$B$F42MF$+$I$&$+$K0MB8$9$k$G$7$g$&!#\e(B
+
+\e$B$^$?!"\e(B@code{spam-split} \e$B$K%Q%i%a!<%?!"Nc$(\e(B
+\e$B$P\e(B @samp{spam-use-regex-headers} \e$B$^$?$O\e(B @samp{"maybe-spam"} \e$B$rM?$($k$3$H\e(B
+\e$B$b$G$-$^$9!#$J$<$3$l$,M-MQ$J$N$G$7$g$&$+\e(B?
+
+\e$B$3$l$i$N\e(B (@code{spam-use-regex-headers} \e$B$H\e(B @code{spam-use-blackholes} \e$B$N\e(B
+\e$B@_Dj$K$h$k\e(B) \e$BJ,3d$N5,B'$r8+$F2<$5$$\e(B:
+
+@example
+ nnimap-split-fancy '(|
+                      (any "ding" "ding")
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail")
+@end example
+
+\e$B$5$F!"LdBj$O\e(B ding \e$B08$F$N%a%C%;!<%8$r$9$Y$F\e(B ding \e$B%U%)%k%@!<$KF~$l$h$&$H$7\e(B
+\e$B$F$$$k$3$H$G$9!#$G$b$=$l$O\e(B ding \e$B%a!<%j%s%0%j%9%H08$F$KAw$i$l$?\e(B spam (\e$BNc\e(B
+\e$B$($P\e(B SpamAssassin \e$B$H\e(B @code{spam-use-regex-headers} \e$B$K$h$C$F8!=P$5$l\e(B
+\e$B$k\e(B spam) \e$B$r5v$7$F$7$^$&$G$7$g$&!#0lJ}!"$$$/$D$+$N\e(B ding \e$B08$F$N%a%C%;!<%8\e(B
+\e$B$O%V%i%C%/%[!<%k%j%9%H$K:\$C$F$$$k%a!<%k%5!<%P!<$+$i$d$C$FMh$k$N$G!"\e(B
+ding \e$B$N5,B'$h$jA0$K\e(B @code{spam-split} \e$B$rH/F0$9$k$3$H$,$G$-$^$;$s!#\e(B
+
+SpamAssassin \e$B%X%C%@!<$K\e(B ding \e$B$N5,B'$rCV$-49$($5$;$k$3$H$O$G$-$^$9$,!"B>\e(B
+\e$B$N$9$Y$F$N\e(B @code{spam-split} \e$B$N5,B'\e(B (\e$BBhFs$N@55,I=8=%X%C%@!<8!::$r4^\e(B
+\e$B$`\e(B) \e$B$O\e(B ding \e$B$N5,B'$N8e$K$J$C$F$7$^$&$G$7$g$&!#\e(B
+
+@example
+ nnimap-split-fancy '(|
+;;; spam-use-regex-headers \e$B$G8!=P$5$l$?$9$Y$F$N\e(B spam \e$B$O\e(B "regex-spam" \e$B$X!#\e(B
+                      (: spam-split "regex-spam" 'spam-use-regex-headers)
+                      (any "ding" "ding")
+;;; spam-split \e$B$G8!=P$5$l$?B>$N$9$Y$F$N\e(B spam \e$B$O\e(B spam-split-group \e$B$X!#\e(B
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail")
+@end example
+
+\e$B4pK\E*$K!"$3$l$OFC$K$"$J$?$NI,MW$K0MB8$7$?FCDj$N\e(B @code{spam-split} \e$B8!\e(B
+\e$B::$r5/F0$5$;!"$=$l$i$N8!::$N7k2L$OFCDj$N\e(B spam \e$B%0%k!<%W$r;X$7<($7$^$9!#$9\e(B
+\e$B$Y$F$N%a!<%k$r$9$Y$F$N\e(B spam \e$B%F%9%H$KEj$2$kI,MW$O$"$j$^$;$s!#$3$l$,NI$$JL\e(B
+\e$B$NM}M3$O!"5,B'$r;}$C$F$$$k%a!<%j%s%0%j%9%H$X$N%a%C%;!<%8$KBP$7$F!";q8;=8\e(B
+\e$BLsE*$J%V%i%C%/%[!<%k!&%A%'%C%/$r<B9T$9$kI,MW$,$J$$$H$$$&$3$H$G$9!#$5$i\e(B
+\e$B$K\e(B nnmail \e$BJ,3d$KBP$7$F\e(B nnimap \e$BJ,3d$N$?$a$N!"0[$J$k\e(B spam \e$B8!::$r;XDj$9$k$3\e(B
+\e$B$H$b$G$-$^$9!#5$$,68$&!<!#\e(B
+
+\e$B8!::$HF1;~$KL@$i$+$K\e(B @code{spam-split} \e$B$r<B9T$9$k$H$7$F$b!":#$^$G$H$*\e(B
+\e$B$j\e(B @code{spam-use-regex-headers} \e$B$r\e(B @code{t} \e$B$K@_Dj$9$k$h$&$J8!::$r9T$C\e(B
+\e$B$F$$$J$1$l$P$J$j$^$;$s!#$J$<$J$i\e(B @file{spam.el} \e$B$rFI$_9~$`$H$-$K!"$"$J$?\e(B
+\e$B$,2?$N\e(B @code{spam-use-xyz} \e$BJQ?t$r@_Dj$7$F$$$k$+$K1~$8$?!"$$$/$D$+$N>r7o\e(B
+\e$BIU$-$NFI$_9~$_$,9T$o$l$k$+$i$G$9!#\e(B
+
+@emph{@acronym{IMAP} \e$BMxMQ<T$X$NCm0U\e(B}
+
+\e$B%X%C%@!<$@$1$G$O$J$/$F%a%C%;!<%8A4BN$K4p$E$$$FJ,3d$r9T$J$$$?$$>l9g$O!"%V!<\e(B
+\e$B%kJQ?t\e(B @code{nnimap-split-download-body} \e$B$,@_Dj$5$l$kI,MW$,$"$j$^$9!#%G%#\e(B
+\e$B%U%)%k%H$G$O!"\e(Bnnimap \e$B%P%C%/%(%s%I$O%a%C%;!<%8%X%C%@!<$@$1$r<h$j9~$_$^$9!#\e(B
+@code{spam-check-bogofilter}\e$B!"\e(B@code{spam-check-ifile} \e$B$^$?\e(B
+\e$B$O\e(B @code{spam-check-stat} (\e$B$=$l$i$NJ,3d4o$O%a%C%;!<%8$NK\J8A4BN$+$i>pJs\e(B
+\e$B$rF@$k\e(B) \e$B$r;H$&$J$i$P!"$3$NJQ?t$r@_Dj$7$J$1$l$P$J$j$^$;$s!#$=$l\e(B
+\e$B$O\e(B @acronym{IMAP} \e$B$NF0:n$rCY$/$7$F$7$^$$!"%f!<%6$rBeI=$9$k$N$K$U$5$o$7$$\e(B
+\e$B7hDj$G$O$J$$$N$G!"%G%#%U%)%k%H$G$O@_Dj$5$l$F$$$^$;$s!#\e(B
+
+@xref{Splitting in IMAP}.
+
+@emph{TODO: spam.el \e$B$O$9$Y$F$NE}7W%G!<%?%Y!<%9$r%H%l!<%K%s%0$9$k$?$a$N0l\e(B
+\e$BDjITJQ$NJ}K!$rDs6!$9$kI,MW$,$"$j$^$9!#$$$/$D$+$O$=$N5!G=$r<+A0$G;}$C$F$$\e(B
+\e$B$^$9$,!"$=$&$G$J$$$b$N$b$"$j$^$9!#\e(B}
+
+@node Spam ELisp Package Global Variables
+@subsubsection Spam ELisp Package Global Variables
+@cindex spam filtering
+@cindex spam filtering variables
+@cindex spam variables
+@cindex spam
+
+@vindex gnus-spam-process-newsgroups
+Ham \e$B%W%m%;%C%5!<$H\e(B spam \e$B%W%m%;%C%5!<$N35G0$OHs>o$K=EMW$G$9!#$"$k%0%k!<%W\e(B
+\e$B$N\e(B ham \e$B%W%m%;%C%5!<$H\e(B spam \e$B%W%m%;%C%5!<$O!"\e(B@code{spam-process} \e$B%0%k!<%W\e(B
+\e$B%Q%i%a!<%?$+\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$G@_Dj$9$k$3$H$,$G\e(B
+\e$B$-$^$9!#8e$GF1MM$N%a!<%k$r\e(B spam \e$B$G$O$J$$$H2r<a$G$-$k$h$&$K$9$k$?$a$K!"\e(B
+ham \e$B%W%m%;%C%5!<$OHs\e(B spam (@emph{ham}) \e$B$G$"$k$3$H$,$o$+$C$F$$$k%a!<%k$r\e(B
+\e$B<u$1<h$C$F!"2?$i$+$NJ}K!$G=hM}$7$^$9!#\e(BSpam \e$B%W%m%;%C%5!<$O!"8e$GF1MM\e(B
+\e$B$N\e(B spam \e$B$,8!=P$5$l$k$h$&$K!"\e(Bspam \e$B$G$"$k$3$H$,$o$+$C$F$$$k%a!<%k$r<u$1<h$C\e(B
+\e$B$F=hM}$7$^$9!#\e(B
+
+Spam \e$B$^$?$O\e(B ham \e$B%W%m%;%C%5!<$r;XDj$9$k7A<0$r!"$+$D$F$O%7%s%\%k$GI=$7$F$$\e(B
+\e$B$?$N$G$9$,!"8=:_$O\e(B cons \e$B%;%k$K$J$C$F$$$^$9!#>\$7$/$O8D!9$N\e(B spam \e$B%W%m%;%C\e(B
+\e$B%5!<$N9`$r;2>H$7$F2<$5$$!#\e(B
+
+@vindex gnus-spam-newsgroup-contents
+gnus \e$B$O$"$J$?$,<u$1<h$C$?\e(B spam \e$B$+$i3X$S$^$9!#$"$J$?$O0l$D0J>e$N\e(B spam \e$B%0\e(B
+\e$B%k!<%W$K\e(B spam \e$B5-;v$r=8$a$F!"JQ?t\e(B @code{spam-junk-mailgroups} \e$B$rE,@Z$K@_\e(B
+\e$BDj$b$7$/$O%+%9%?%^%$%:$7$J$1$l$P$J$j$^$;$s!#$^$?!"\e(Bspam \e$B$r4^$a$k%0%k!<%W\e(B
+\e$B$r!"$=$N%0%k!<%W%Q%i%a!<\e(B
+\e$B%?\e(B @code{spam-contents} \e$B$r\e(B @code{gnus-group-spam-classification-spam} \e$B$K\e(B
+\e$B@_Dj$9$k$+!"$^$?$O$=$l$KBP1~$9$kJQ\e(B
+\e$B?t\e(B @code{gnus-spam-newsgroup-contents} \e$B$r%+%9%?%^%$%:$9$k$3$H$K$h$C$F@k\e(B
+\e$B8@$9$k$3$H$,$G$-$^$9!#\e(B@code{spam-contents} \e$B%0%k!<%W%Q%i%a!<%?\e(B
+\e$B$H\e(B @code{gnus-spam-newsgroup-contents} \e$BJQ?t$O!"$=$l$i$N<oJL\e(B
+\e$B$r\e(B @code{gnus-group-spam-classification-ham} \e$B$K@_Dj$9$k$3$H$K$h$C$F!"\e(B
+@emph{ham} \e$B%0%k!<%W$G$"$k$3$H$r@k8@$9$k$?$a$K;H$&$3$H$b$G$-$^$9!#%0%k!<\e(B
+\e$B%W$,\e(B @code{spam-junk-mailgroups}, @code{spam-contents} \e$B$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-newsgroup-contents} \e$B$G$"$k$3$H$r<($9J,N`$,9T$J$o$l$F\e(B
+\e$B$$$J$$$H!"$=$l$i$O\e(B @emph{\e$BL$J,N`\e(B} \e$B$G$"$k$H2r<a$5$l$^$9!#$9$Y$F$N%0%k!<%W\e(B
+\e$B$O%G%#%U%)%k%H$G$OL$J,N`$G$9!#\e(B
+
+@vindex gnus-spam-mark
+@cindex $
+Spam \e$B%0%k!<%W$G$O!"%G%#%U%)%k%H$G$9$Y$F$N%a%C%;!<%8$,\e(B spam \e$B$G$"$k$H2r<a\e(B
+\e$B$5$l$^$9\e(B: \e$B$=$N%0%k!<%W$KF~$k$H!"$=$l$i\e(B
+\e$B$K\e(B @samp{$} \e$B0u\e(B (@code{gnus-spam-mark}) \e$B$,IU$-$^$9!#%a%C%;!<%8$r8+$F0lC6\e(B
+\e$B$=$l$K\e(B spam \e$B$N0u$rIU$1$F$b!"8e$G<h$j>C$;$P!"$=$N8e$=$N%0%k!<%W$KF~$C$?$H\e(B
+\e$B$-$K!"$=$l$K$O\e(B spam \e$B0u$OIU$-$^$;$s!#$?$@\e(B
+\e$B$7\e(B @code{spam-mark-only-unseen-as-spam} \e$B%Q%i%a!<%?$r\e(B @code{nil} \e$B$K$9$l$P!"\e(B
+\e$B$=$&$$$&F0:n$r$d$a$5$;$k!"$D$^$j$9$Y$F$NL$FI%a%C%;!<%8$K\e(B spam \e$B0u$,IU$/$h\e(B
+\e$B$&$K$9$k$3$H$,$G$-$^$9!#$=$N%0%k!<%W$N35N,%P%C%U%!$K$$$k$H$-!"$d$C$Q\e(B
+\e$B$j\e(B spam \e$B$G$O$J$+$C$?$9$Y$F$N\e(B \e$B5-;v$+$i\e(B @samp{$} \e$B0u$r>C$5$J$1$l$P$J$j$^$;\e(B
+\e$B$s!#\e(B@samp{$} \e$B0u$r>C$9$K$O\e(B @kbd{M-u} \e$B$G$=$N5-;v$r\e(B ``\e$BL$FI\e(B'' \e$B$K$9$k$+!"$"$k\e(B
+\e$B$$$O\e(B @kbd{d} \e$B$G\e(B spam \e$B$G$O$J$$$b$N$H$7$FFI$s$@$3$H$r@k8@$9$l$PNI$$$G$7$g\e(B
+\e$B$&!#%0%k!<%W$rH4$1$k$H$-!"$9$Y$F$N\e(B spam \e$B0u\e(B (@samp{$}) \e$B$,IU$$$?5-;v\e(B
+\e$B$O\e(B spam \e$B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r\e(B spam \e$B$NI8K\$H$7$F3X=,$7$^$9!#\e(B
+
+\e$B%a%C%;!<%8$OB>$N$$$m$$$m$JJ}K!$K$h$C$F$b>C5n$5$l$k$+$b$7$l$^$;$s$7!"\e(B
+@code{ham-marks} \e$B%0%k!<%W%Q%i%a!<%?$,8e=R$N$h$&$K>e=q$-$5$l$J$1$l$P!"Dc\e(B
+\e$B$$%9%3%"$N$?$a$N\e(B @samp{Y} \e$B0u$HF1MM!"%G%#%U%)%k%H$N4{FI$+L@<(E*$J>C5n$N$?\e(B
+\e$B$a$N\e(B @samp{R} \e$B$H\e(B @samp{r} \e$B0u!"<+F0$^$?$OL@<(E*$J:o=|$N$?$a\e(B
+\e$B$N\e(B @samp{X} \e$B$H\e(B @samp{K} \e$B0u!"$=$l$i$9$Y$F$,\e(B spam \e$B$H$OL54X78$G$"$k$H2r<a$5\e(B
+\e$B$l$^$9!#$3$N2>Dj$O!"K\J*$N\e(B spam \e$B$r8!=P$9$k$?$a$K>C5n\e(B (kill) \e$B%U%!%$%k$+%9\e(B
+\e$B%3%"%U%!%$%k$rFCJL$K;H$C$F$$$k>l9g$O4V0c$C$F$$$k$+$b$7$l$^$;$s!#$=$&$G$"\e(B
+\e$B$l$P\e(B @code{ham-marks} \e$B%0%k!<%W%Q%i%a!<%?$rD4@0$9$k$Y$-$G$9!#\e(B
+
+@defvar ham-marks
+\e$B$3$N%0%k!<%W$^$?$O%H%T%C%/%Q%i%a!<%?$r\e(B ham \e$B$G$"$k$H2r<a$7$?$$0u$N%j%9%H\e(B
+\e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#%G%#%U%)%k%H$G$O!">C5n\e(B (deleted)\e$B!"4{FI\e(B (read)\e$B!"\e(B
+\e$B:o=|\e(B (killed)\e$B!"\e(Bkill \e$B%U%!%$%k$K$"$k$b$N\e(B (kill-filed) \e$B$*$h$SDc$$%9%3\e(B
+\e$B%"\e(B (low-score\e$B!"4{FI$@$1$l$I$b\e(B spam \e$B$G$O$J$$$H9M$($k\e(B) \e$B0u$N%j%9%H$G$9!#\e(B
+Ham \e$B0u$N%j%9%H$K2D;k\e(B (tick) \e$B0u$r4^$a$k$3$H$,LrN)$D$3$H$b$"$j$^$9!#L$FI0u\e(B
+\e$B$r\e(B ham \e$B0u$K$9$k$3$H$O!"DL>o$=$l$,J,N`$,B-$j$F$$$J$$$3$H$rI=$9$N$G!"4+$a\e(B
+\e$B$i$l$^$;$s!#$7$+$7!"$"$J$?$,$=$l$r9T$J$&$3$H$O$G$-$k$7!";d$?$A$KITK~$O$"\e(B
+\e$B$j$^$;$s!#\e(B
+@end defvar
+
+@defvar spam-marks
+\e$B$3$N%0%k!<%W$^$?$O%H%T%C%/%Q%i%a!<%?$r\e(B spam \e$B$G$"$k$H2r<a$7$?$$0u$N%j%9%H\e(B
+\e$B$K@_Dj$9$k$3$H$,$G$-$^$9!#%G%#%U%)%k%H$G$O\e(B spam \e$B0u$@$1$r;}$D%j%9%H$G$9!#\e(B
+\e$B$=$l$rJQ99$9$k$3$H$O4+$a$^$;$s$,!"K\Ev$K$=$&$7$?$$$N$J$i$4>!<j$K!#\e(B
+@end defvar
+
+\e$B%0%k!<%W$rH4$1$k$H$-$K\e(B (\e$B$=$N%0%k!<%W$,\e(B @emph{\e$B2?\e(B} \e$B$G$"$C$F$b\e(B)\e$B!"$=\e(B
+\e$B$N\e(B @code{spam-contents} \e$B$NJ,N`$K$+$+$o$i$:!"\e(Bspam \e$B0u$,IU$$$F$$$k$9$Y$F$N\e(B
+\e$B5-;v$O\e(B spam \e$B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r\e(B spam \e$B$NI8K\$H$7$F3X=,$7$^$9!#\e(B
+\e$B0U?^E*$K$?$/$5$s$N>C5n$r9T$J$&$H!"$?$^$K$=$l$O8+$F$$$J$$\e(B @samp{K} \e$B0u$,IU\e(B
+\e$B$$$?5-;v$G=*$o$k$+$b$7$l$^$;$s!#$=$7$F$=$l$i$O6vA3$K\e(B spam \e$B$r4^$s$G$$$k$+\e(B
+\e$B$b$7$l$^$;$s!#:G$bNI$$$N$O!"K\Ev$N\e(B spam \e$B$K\e(B @samp{$} \e$B$,IU$$$F$$$F!"B>$K2?\e(B
+\e$B$bL5$$$3$H$r3N$+$a$k$3$H$G$9!#\e(B
+
+@vindex gnus-ham-process-destinations
+@emph{Spam} \e$B%0%k!<%W$rH4$1$k$H$-$K!"\e(Bspam \e$B0u$,IU$$$F$$$k$9$Y$F$N5-;v\e(B
+\e$B$K$O\e(B spam \e$B%W%m%;%C%5!<$G=hM}$7$?8e$G4|8B@Z$l>C5n$N0u$,IU$1$i$l$^$9!#$3$l\e(B
+\e$B$O\e(B @emph{\e$BL$J,N`\e(B} \e$B$^$?$O\e(B @emph{ham} \e$B%0%k!<%W$KBP$7$F$O9T$J$o$l$^$;$s!#$5\e(B
+\e$B$i$K\e(B spam \e$B%0%k!<%W$K$"$k$I$N\e(B @strong{ham} \e$B5-;v$b!"\e(B
+@code{ham-process-destination} \e$B%0%k!<%W%Q%i%a!<%?\e(B
+\e$B$+\e(B @code{gnus-ham-process-destinations} \e$BJQ?t$N$I$A$i$+$K9gCW$9$k>l=j$K0\\e(B
+\e$B$5$l$^$9!#$=$l$i$O%0%k!<%WL>$K9gCW$9$k@55,I=8=$N%j%9%H$G\e(B
+\e$B$9\e(B (@code{customize-variable gnus-ham-process-destinations} \e$B$K$h$C$F$3$N\e(B
+\e$BJQ?t$r%+%9%?%^%$%:$9$k$N$,:G$b4JC1$G$9\e(B)\e$B!#JQ?t$r<j$G%+%9%?%^%$%:$9$kJ}$,\e(B
+\e$B9%$-$J?M$N$?$a$K8@$C$F$*$/$H!"$=$l$i$OIaDL$N\e(B Lisp \e$B$N\e(B list \e$B$G!"$=$l$>$l$N\e(B
+\e$B%K%e!<%9%0%k!<%W$N;EMM@_Dj$O\e(B @code{(REGEXP PROCESSOR)} \e$B$N7A<0$NCM$r;}$A\e(B
+\e$B$^$9!#:G=*E*$J>l=j$O\e(B (\e$BC1?t$^$?$OJ#?t$N\e(B) \e$B%0%k!<%WL>$G$9!#\e(B
+@code{ham-process-destination} \e$B%Q%i%a!<%?$,@_Dj$5$l$F$$$J$$$H!"\e(Bham \e$B5-;v\e(B
+\e$B$O$=$3$KN1$aCV$+$l$^$9!#\e(B
+@code{spam-mark-ham-unread-before-move-from-spam-group} \e$B%Q%i%a!<%?$,@_Dj\e(B
+\e$B$5$l$F$$$k$H!"\e(Bham \e$B5-;v$O0\F0$5$;$i$l$kA0$KL$FI$N0u$,IU$1$i$l$^$9!#\e(B
+
+Ham \e$B$,0\F0$G$-$J$$>l9g\e(B (\e$BNc$($P\e(B NNTP \e$B$N$h$&$JFI$_9~$_@lMQ%P%C%/%(%s%I$N$?\e(B
+\e$B$a$K\e(B)\e$B!"$=$l$O%3%T!<$5$l$^$9!#\e(B
+
+\e$B%0%k!<%W$^$?$O@55,I=8=$4$H$KJ#?t$N0\F0@h$r;XDj$G$-$k$3$H$KCmL\$7$F2<$5$$\e(B!
+\e$B$3$l$K$h$C$F\e(B ham \e$B5-;v$r@55,$N%a!<%k%0%k!<%W$H\e(B @emph{ham \e$B%H%l!<%K%s%0\e(B} \e$B%0\e(B
+\e$B%k!<%W$KAw$k$3$H$,$G$-$^$9!#\e(B
+
+@emph{Ham} \e$B%0%k!<%W$rH4$1$k$H$-$K!"\e(Bham \e$B0u$,IU$$$F$$$k$9$Y$F$N5-;v\e(B
+\e$B$O\e(B ham \e$B%W%m%;%C%5!<$KAw$i$l!"$=$l$i$r\e(B spam \e$B$G$O$J$$I8K\$H$7$F3X=,$7$^$9!#\e(B
+
+@vindex spam-process-ham-in-spam-groups
+\e$BJQ?t\e(B @code{spam-process-ham-in-spam-groups} \e$B$O%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(BSpam \e$B%0%k!<%W$G8+$D$+$C$?\e(B ham \e$B$,%W%m%;%C%5!<$KAw$i$l\e(B
+\e$B$k$h$&$K$7$?$$>l9g$O\e(B @code{t} \e$B$K$7$F2<$5$$!#DL>o$3$l$O9T$J$o$l$^$;$s!#$"\e(B
+\e$B$J$?$,<+J,$G\e(B ham \e$B5-;v$r\e(B ham \e$B%0%k!<%W$KAw$C$F!"$=$3$G=hM}$9$k$3$H$,4|BT$5\e(B
+\e$B$l$F$$$^$9!#\e(B
+
+@vindex spam-process-ham-in-nonham-groups
+\e$BJQ?t\e(B @code{spam-process-ham-in-nonham-groups} \e$B$O%G%#%U%)%k%H$G\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(BHam \e$B$G$O$J$$\e(B (spam \e$B$^$?$OL$J,N`$N\e(B) \e$B%0%k!<%W$G8+$D$+$C\e(B
+\e$B$?\e(B ham \e$B$,%W%m%;%C%5!<$KAw$i$l$k$h$&$K$7$?$$>l9g$O\e(B @code{t} \e$B$K$7$F2<$5$$!#\e(B
+\e$BDL>o$3$l$O9T$J$o$l$^$;$s!#$"$J$?$,<+J,$G\e(B ham \e$B5-;v$r\e(B ham \e$B%0%k!<%W$KAw$C$F!"\e(B
+\e$B$=$3$G=hM}$9$k$3$H$,4|BT$5$l$F$$$^$9!#\e(B
+
+@vindex gnus-spam-process-destinations
+@emph{Ham} \e$B$^$?$O\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<%W$rH4$1$k$H$-$K!"$9$Y$F\e(B
+\e$B$N\e(B @strong{spam} \e$B5-;v$O!"\e(B@code{spam-process-destination} \e$B%0%k!<%W%Q%i%a!<\e(B
+\e$B%?$+\e(B @code{gnus-spam-process-destinations} \e$BJQ?t$N$I$A$i$+$K9gCW$9$k>l=j\e(B
+\e$B$K0\$5$l$^$9!#$=$l$i$O%0%k!<%WL>$K9gCW$9$k@55,I=8=$N%j%9%H$G\e(B
+\e$B$9\e(B (@code{customize-variable gnus-spam-process-destinations} \e$B$K$h$C$F$3\e(B
+\e$B$NJQ?t$r%+%9%?%^%$%:$9$k$N$,:G$b4JC1$G$9\e(B)\e$B!#JQ?t$r<j$G%+%9%?%^%$%:$9$kJ}\e(B
+\e$B$,9%$-$J?M$N$?$a$K8@$C$F$*$/$H!"$=$l$i$OIaDL$N\e(B Lisp \e$B$N\e(B list \e$B$G!"$=$l$>$l\e(B
+\e$B$N%K%e!<%9%0%k!<%W$N;EMM@_Dj$O\e(B @code{(REGEXP GROUP)} \e$B$N7A<0$NCM$r;}$A$^\e(B
+\e$B$9!#:G=*E*$J>l=j$O\e(B (\e$BC1?t$^$?$OJ#?t$N\e(B) \e$B%0%k!<%WL>$G$9!#\e(B
+@code{spam-process-destination} \e$B%Q%i%a!<%?$,@_Dj$5$l$F$$$J$$$H!"\e(Bspam \e$B5-\e(B
+\e$B;v$OC1$K4|8B@Z$l>C5n$5$l$^$9!#%0%k!<%WL>$O40A47A$G$"$k$3$H!"$9$J$o$A%0%k!<\e(B
+\e$B%W%P%C%U%!$G%0%k!<%WL>$NA0$K\e(B @samp{nntp:servername} \e$B$N$h$&$J$b$N$,8+$($k\e(B
+\e$B>l9g$O!"$3$3$G$b$=$l$r;H$&I,MW$,$"$j$^$9!#\e(B
+
+Spam \e$B$,0\F0$G$-$J$$>l9g\e(B (\e$BNc$($P\e(B NNTP \e$B$N$h$&$JFI$_9~$_@lMQ%P%C%/%(%s%I$N\e(B
+\e$B$?$a$K\e(B)\e$B!"$=$l$O%3%T!<$5$l$^$9!#\e(B
+
+\e$B%0%k!<%W$^$?$O@55,I=8=$4$H$KJ#?t$N0\F0@h$r;XDj$G$-$k$3$H$KCmL\$7$F2<$5$$\e(B!
+\e$B$3$l$K$h$C$F\e(B spam \e$B5-;v$r@55,$N%a!<%k%0%k!<%W\e(B
+\e$B$H\e(B @emph{spam \e$B%H%l!<%K%s%0\e(B} \e$B%0%k!<%W$KAw$k$3$H$,$G$-$^$9!#\e(B
+
+@vindex spam-log-to-registry
+Ham \e$B$H\e(B spam \e$B$K4X$9$kLdBj$O!"\e(BGnus \e$B$,%G%#%U%)%k%H$G$O$3$N=hM}$rDI@W$7$F$/\e(B
+\e$B$l$J$$$3$H$G$9!#=hM}$5$l$?5-;v$rDI@W$7!"$+$DJ#?t2s$K$o$?$C$F=hM}$9$k$3$H\e(B
+\e$B$r2sHr$9$k$?$a$K\e(B @code{spam.el} \e$B$,\e(B @code{gnus-registry.el} \e$B$r;H$&$h$&$K!"\e(B
+@code{spam-log-to-registry} \e$BJQ?t$rM-8z$K$7$F$/$@$5$$!#EPO??t$r@)8B$9$k$H!"\e(B
+\e$B@)8B$,L5$$>l9g$N$h$&$KF0:n$7$J$$$3$H$r3P$($F$*$$$F2<$5$$!#\e(B
+
+@vindex spam-mark-only-unseen-as-spam
+Spam \e$B%0%k!<%W$K$"$k!"$^$@FI$^$l$?$3$H$,L5$$5-;v$@$1$K\e(B spam \e$B$N0u$rIU$1$?\e(B
+\e$B$$>l9g$O!"$3$NJQ?t$r%;%C%H$7$F2<$5$$!#%G%#%U%)%k%H$G$O%;%C%H$5$l$F$$$^$9!#\e(B
+\e$B$3$l$r\e(B nil \e$B$K$9$k$H!"L$FI$N5-;v$K$b\e(B spam \e$B0u$,IU$1$i$l$^$9!#\e(B
+
+@vindex spam-mark-ham-unread-before-move-from-spam-group
+Ham \e$B$,\e(B spam \e$B%0%k!<%W$+$i0\F0$5$l$kA0$K0u$r>C$7$?$$>l9g$O!"$3$NJQ?t$r%;%C\e(B
+\e$B%H$7$F2<$5$$!#$3$l$O\e(B ham \e$B$K0u$rIU$1$k$?$a$K2D;k\e(B (tick) \e$B0u$N$h$&$J$b$N$r\e(B
+\e$B;H$&>l9g$K!"$H$F$bLr$KN)$A$^$9!#5-;v$O$"$?$+$b$=$l$,%a!<%k%5!<%P$r=P$?$P\e(B
+\e$B$+$j$N$h$&$K!"L50u$G\e(B ham \e$B=hM}>l$KCV$+$l$k$G$7$g$&!#\e(B
+
+@vindex spam-autodetect-recheck-messages
+\e$B$3$NJQ?t$O\e(B @code{spam.el} \e$B$,\e(B spam \e$B$N<+F08!CN$r9T$J$&>l9g$K!"$^$@FI$^$l$?\e(B
+\e$B$3$H$,L5$$5-;v$@$1!"$^$?$O$9$Y$F$NL$FI5-;v$N\e(B spam \e$B8!::$r9T$J$&$+$I$&$+$r\e(B
+\e$B;X<($7$^$9!#$3$l$O$=$N$^$^$K$7$F$*$/$3$H$r4+$a$^$9!#\e(B
+
+@node Spam ELisp Package Configuration Examples
+@subsubsection Spam ELisp Package Configuration Examples
+@cindex spam filtering
+@cindex spam filtering configuration examples
+@cindex spam configuration examples
+@cindex spam
+
+@subsubheading Ted's setup
+
+From Ted Zlatanov <tzz@@lifelogs.com>.
+@example
+
+;; for gnus-registry-split-fancy-with-parent and spam autodetection
+;; see gnus-registry.el for more information
+(gnus-registry-initialize)
+(spam-initialize)
+
+;; I like control-S for marking spam
+(define-key gnus-summary-mode-map "\C-s" 'gnus-summary-mark-as-spam)
+
+(setq
+ spam-log-to-registry t ;; for spam autodetection
+ spam-use-BBDB t
+ spam-use-regex-headers t               ; catch X-Spam-Flag (SpamAssassin)
+ ;; all groups with "spam" in the name contain spam
+ gnus-spam-newsgroup-contents '(("spam" gnus-group-spam-classification-spam))
+ ;; see documentation for these
+ spam-move-spam-nonspam-groups-only nil
+ spam-mark-only-unseen-as-spam t
+ spam-mark-ham-unread-before-move-from-spam-group t
+ nnimap-split-rule 'nnimap-split-fancy
+ ;; understand what this does before you copy it to your own setup!
+ nnimap-split-fancy '(|
+                      ;; trace references to parents and put in their group
+                      (: gnus-registry-split-fancy-with-parent)
+                      ;; this will catch server-side SpamAssassin tags
+                      (: spam-split 'spam-use-regex-headers)
+                      (any "ding" "ding")
+                      ;; note that spam by default will go to "spam"
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail"))
+
+;; my parameters, set with `G p'
+
+;; all nnml groups, and all nnimap groups except
+;; "nnimap+mail.lifelogs.com:train" and
+;; "nnimap+mail.lifelogs.com:spam": any spam goes to nnimap training,
+;; because it must have been detected manually
+
+((spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; all NNTP groups
+;; autodetect spam with the blacklist and ham with the BBDB
+((spam-autodetect-methods spam-use-blacklist spam-use-BBDB)
+;; send all spam to the training group
+ (spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; only some NNTP groups, where I want to autodetect spam
+((spam-autodetect . t))
+
+;; my nnimap "nnimap+mail.lifelogs.com:spam" group
+
+;; this is a spam group
+((spam-contents gnus-group-spam-classification-spam)
+
+ ;; any spam (which happens when I enter for all unseen messages,
+ ;; because of the gnus-spam-newsgroup-contents setting above), goes to
+ ;; "nnimap+mail.lifelogs.com:train" unless I mark it as ham
+
+ (spam-process-destination "nnimap+mail.lifelogs.com:train")
+
+ ;; any ham goes to my "nnimap+mail.lifelogs.com:mail" folder, but
+ ;; also to my "nnimap+mail.lifelogs.com:trainham" folder for training
+
+ (ham-process-destination "nnimap+mail.lifelogs.com:mail" 
+                          "nnimap+mail.lifelogs.com:trainham")
+ ;; in this group, only '!' marks are ham
+ (ham-marks
+  (gnus-ticked-mark))
+ ;; remembers senders in the blacklist on the way out - this is
+ ;; definitely not needed, it just makes me feel better
+ (spam-process (gnus-group-spam-exit-processor-blacklist)))
+
+;; Later, on the IMAP server I use the "train" group for training
+;; SpamAssassin to recognize spam, and the "trainham" group for
+;; recognizing ham - but Gnus has nothing to do with it.
+
+@end example
+
+@subsubheading Using @file{spam.el} on an IMAP server with a statistical filter on the server
+
+From Reiner Steib <reiner.steib@@gmx.de>.
+
+My provider has set up bogofilter (in combination with @acronym{DCC}) on
+the mail server (@acronym{IMAP}).  Recognized spam goes to
+@samp{spam.detected}, the rest goes through the normal filter rules,
+i.e. to @samp{some.folder} or to @samp{INBOX}.  Training on false
+positives or negatives is done by copying or moving the article to
+@samp{training.ham} or @samp{training.spam} respectively.  A cron job on
+the server feeds those to bogofilter with the suitable ham or spam
+options and deletes them from the @samp{training.ham} and
+@samp{training.spam} folders.
+
+With the following entries in @code{gnus-parameters}, @code{spam.el}
+does most of the job for me:
+
+@lisp
+   ("nnimap:spam\\.detected"
+    (gnus-article-sort-functions '(gnus-article-sort-by-chars))
+    (ham-process-destination "nnimap:INBOX" "nnimap:training.ham")
+    (spam-contents gnus-group-spam-classification-spam))
+   ("nnimap:\\(INBOX\\|other-folders\\)"
+    (spam-process-destination . "nnimap:training.spam")
+    (spam-contents gnus-group-spam-classification-ham))
+@end lisp
+
+@itemize 
+
+@item @b{The Spam folder:}
+
+In the folder @samp{spam.detected}, I have to check for false positives
+(i.e. legitimate mails, that were wrongly judged as spam by
+bogofilter or DCC).
+
+Because of the @code{gnus-group-spam-classification-spam} entry, all
+messages are marked as spam (with @code{$}).  When I find a false
+positive, I mark the message with some other ham mark (@code{ham-marks},
+@ref{Spam ELisp Package Global Variables}).  On group exit, those
+messages are copied to both groups, @samp{INBOX} (were I want to have
+the article) and @samp{training.ham} (for training bogofilter) and
+deleted from the @samp{spam.detected} folder.
+
+The @code{gnus-article-sort-by-chars} entry simplifies detection of
+false positives for me.  I receive lots of worms (sweN, @dots{}), that all
+have a similar size.  Grouping them by size (i.e. chars) makes finding
+other false positives easier.  (Of course worms aren't @i{spam}
+(@acronym{UCE}, @acronym{UBE}) strictly speaking.  Anyhow, bogofilter is
+an excellent tool for filtering those unwanted mails for me.)
+
+@item @b{Ham folders:}
+
+In my ham folders, I just hit @kbd{S x}
+(@code{gnus-summary-mark-as-spam}) whenever I see an unrecognized spam
+mail (false negative).  On group exit, those messages are moved to
+@samp{training.ham}.
+@end itemize
+
+@subsubheading Reporting spam articles in Gmane groups with @code{spam-report.el}
+
+From Reiner Steib <reiner.steib@@gmx.de>.
+
+With following entry in @code{gnus-parameters}, @kbd{S x}
+(@code{gnus-summary-mark-as-spam}) marks articles in @code{gmane.*}
+groups as spam and reports the to Gmane at group exit:
+
+@lisp
+   ("^gmane\\."
+    (spam-process (gnus-group-spam-exit-processor-report-gmane)))
+@end lisp
+
+Additionally, I use `(setq spam-report-gmane-use-article-number nil)'
+because I don't read the groups directly from news.gmane.org, but
+through my local news server (leafnode).  I.e. the article numbers are
+not the same as on news.gmane.org, thus @code{spam-report.el} has to check
+the @code{X-Report-Spam} header to find the correct number.
+
+@node Blacklists and Whitelists
+@subsubsection \e$B%V%i%C%/%j%9%H$H%[%o%$%H%j%9%H\e(B
+@cindex spam filtering
+@cindex whitelists, spam filtering
+@cindex blacklists, spam filtering
+@cindex spam
+
+@defvar spam-use-blacklist
+
+\e$BF~$C$F$/$k%a!<%k$rJ,3d$9$k$H$-$K%V%i%C%/%j%9%H$r;H$$$?$$>l9g$O!"$3$NJQ?t\e(B
+\e$B$r\e(B @code{t} \e$B$K@_Dj$7$F2<$5$$!#Aw?.<T$,%V%i%C%/%j%9%H$K:\$C$F$$$k%a%C%;!<\e(B
+\e$B%8$O\e(B @code{spam-split-group} \e$B$KAw$i$l$^$9!#$3$l$O!"Aw?.<T$,\e(B spammer \e$B$G$"\e(B
+\e$B$k$3$H$,Dj5A$5$l$F$$$k%a!<%k$KBP$7$F$@$1F0:n$9$k!"L@<(E*$J_I2a4o$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-use-whitelist
+
+\e$BF~$C$F$/$k%a!<%k$rJ,3d$9$k$H$-$K%[%o%$%H%j%9%H$r;H$$$?$$>l9g$O!"$3$NJQ?t\e(B
+\e$B$r\e(B @code{t} \e$B$K@_Dj$7$F2<$5$$!#Aw?.<T$,%[%o%$%H%j%9%H$K:\$C$F$$$J$$%a%C%;!<\e(B
+\e$B%8$O!"<!$N\e(B spam-split \e$B5,B'$KAw$i$l$^$9!#$3$l$O!"%[%o%$%H%j%9%H$K:\$C$F$$\e(B
+\e$B$J$$C/$+$N%a%C%;!<%8$O\e(B spam \e$B$H$b\e(B ham \e$B$H$b8+$J$5$l$J$$$3$H$r0UL#$9$k!"L@\e(B
+\e$B<(E*$J_I2a4o$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-use-whitelist-exclusive
+
+\e$BAw?.<T$,%[%o%$%H%j%9%H$K:\$C$F$$$J$$$9$Y$F$N%a%C%;!<%8$,\e(B spam \e$B$@$H8+$J$5\e(B
+\e$B$l$k$3$H$r0UL#$9$k0EL[$N_I2a4o$H$7$F%[%o%$%H%j%9%H$r;H$$$?$$>l9g$O!"$3$N\e(B
+\e$BJQ?t$r\e(B @code{t} \e$B$K$7$F2<$5$$!#Cm0U$7$F;H$C$F2<$5$$!#\e(B
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-blacklist
+
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bspam \e$B0u$,IU$$\e(B
+\e$B$?5-;v$NAw?.<T$,%V%i%C%/%j%9%H$KDI2C$5$l$^$9!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-spam-exit-processor-blacklist} \e$B$NBe$o$j$K!"\e(B
+@code{'(spam spam-use-blacklist)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0\e(B
+\e$B:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-whitelist
+
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bham \e$B0u$,IU$$\e(B
+\e$B$?\e(B @emph{ham} \e$B%0%k!<%W$N5-;v$NAw?.<T$,%[%o%$%H%j%9%H$KDI2C$5$l$^$9!#$3\e(B
+\e$B$N\e(B ham \e$B%W%m%;%C%5!<$O\e(B @emph{spam} \e$B$+\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<%W$K$O8z2L$r5Z\e(B
+\e$B$\$5$J$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-ham-exit-processor-whitelist} \e$B$NBe$o$j$K!"\e(B
+@code{'(ham spam-use-whitelist)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0\e(B
+\e$B:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+
+@end defvar
+
+\e$B%V%i%C%/%j%9%H$O!"$"$J$?$,\e(B spam \e$B$NAw?.<T$@$H9M$($k%"%I%l%9$K9gCW$9$k@55,\e(B
+\e$BI=8=$N%j%9%H$G$9!#Nc$($P\e(B @samp{vmadmin.com} \e$B$NC/$+$i$G$bMh$k%a!<%k$rAK;_\e(B
+\e$B$9$k$K$O!"$"$J$?$N%V%i%C%/%j%9%H$K\e(B @samp{vmadmin.com} \e$B$rF~$l$F2<$5$$!#6u\e(B
+\e$B$N%V%i%C%/%j%9%H$G;O$a$^$7$g$&!#%V%i%C%/%j%9%H$N3F9`L\$O\e(B Emacs \e$B$N@55,I=\e(B
+\e$B8=%7%s%?%C%/%9$r;H$$$^$9!#\e(B
+
+\e$B5U$K!"%[%o%$%H%j%9%H$O2?$N%"%I%l%9$,@5Ev$@$H9M$($i$l$k$+$r9p$2$^$9!#%[%o\e(B
+\e$B%$%H%j%9%H$K$"$k%"%I%l%9$+$i$d$C$FMh$?$9$Y$F$N%a%C%;!<%8$O!"Hs\e(B-spam \e$B$@$H\e(B
+\e$B8+$J$5$l$^$9!#\e(B@ref{BBDB Whitelists} \e$B$b8+$F2<$5$$!#%[%o%$%H%j%9%H$N3F9`L\\e(B
+\e$B$O\e(B Emacs \e$B$N@55,I=8=%7%s%?%C%/%9$r;H$$$^$9!#\e(B
+
+\e$B%V%i%C%/%j%9%H$H%[%o%$%H%j%9%H$N%U%!%$%k$N=j:_$O!"\e(B
+@code{spam-directory} \e$BJQ?t\e(B (\e$B%G%#%U%)%k%H$O\e(B @file{~/News/spam}) \e$B$^$?\e(B
+\e$B$OD>@\\e(B @code{spam-whitelist} \e$B$H\e(B @code{spam-blacklist} \e$BJQ?t$G%+%9%?%^%$%:\e(B
+\e$B$9$k$3$H$,$G$-$^$9!#%[%o%$%H%j%9%H$H%V%i%C%/%j%9%H$N%U%!%$%k$O!"%G%#%U%)\e(B
+\e$B%k%H$G$O\e(B @code{spam-directory} \e$B$N%G%#%l%/%H%j$K$"$j!"$=$l$>\e(B
+\e$B$l\e(B @file{whitelist} \e$B$H\e(B @file{blacklist} \e$B$H$$$&L>A0$,IU$1$i$l$^$9!#\e(B
+
+@node BBDB Whitelists
+@subsubsection BBDB \e$B%[%o%$%H%j%9%H\e(B
+@cindex spam filtering
+@cindex BBDB whitelists, spam filtering
+@cindex BBDB, spam filtering
+@cindex spam
+
+@defvar spam-use-BBDB
+
+@code{spam-use-whitelist} (@pxref{Blacklists and Whitelists}) \e$B$K;w$F$$$^\e(B
+\e$B$9$,!"%[%o%$%H%j%9%H$N%"%I%l%9$N8;$H$7$F!"@55,I=8=$G$O$J$$\e(B BBDB \e$B$r;H$$$^\e(B
+\e$B$9!#\e(B@code{spam-use-BBDB} \e$B$r$A$c$s$HF0:n$5$;$k$K$O\e(B BBDB \e$B$r\e(B load \e$B$7$J$1$l\e(B
+\e$B$P$J$j$^$;$s!#$=$NAw?.<T$,\e(B BBDB \e$B$K:\$C$F$$$J$$%a%C%;!<%8$O!"<!\e(B
+\e$B$N\e(B spam-split \e$B5,B'$KAw$i$l$^$9!#$3$l$O!"\e(BBBDB \e$B$K:\$C$F$$$J$$C/$+$N%a%C%;!<\e(B
+\e$B%8$O\e(B spam \e$B$H$b\e(B ham \e$B$H$b8+$J$5$l$J$$$3$H$r0UL#$9$k!"L@<(E*$J_I2a4o$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-use-BBDB-exclusive
+
+\e$BAw?.<T$,\e(B BBDB \e$B$K:\$C$F$$$J$$$9$Y$F$N%a%C%;!<%8$,\e(B spam \e$B$@$H8+$J$5$l$k$3$H\e(B
+\e$B$r0UL#$9$k0EL[$N_I2a4o$H$7$F\e(B BBDB \e$B$r;H$$$?$$>l9g$O!"$3$NJQ?t\e(B
+\e$B$r\e(B @code{t} \e$B$K$7$F2<$5$$!#Cm0U$7$F;H$C$F2<$5$$!#\e(BBBDB \e$B$K:\$C$F$$$kAw?.<T\e(B
+\e$B$@$1$,DL9T$r5v$5$l!"B>$N$9$Y$F$O\e(B spammers \e$B$H$7$FJ,N`$5$l$^$9!#\e(B
+
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-BBDB
+
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bham \e$B0u$,IU$$\e(B
+\e$B$?\e(B @emph{ham} \e$B%0%k!<%W$N5-;v$NAw?.<T$,\e(B BBDB \e$B$KDI2C$5$l$^$9!#$3$N\e(B ham \e$B%W\e(B
+\e$B%m%;%C%5!<$O\e(B @emph{spam} \e$B$+\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<%W$K$O8z2L$r5Z$\$5$J$$$3\e(B
+\e$B$H$KCm0U$7$F2<$5$$!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-ham-exit-processor-BBDB} \e$B$NBe$o$j$K!"\e(B
+@code{'(ham spam-use-BBDB)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0:n$9$k\e(B
+\e$B$3$H$OJ]>Z$5$l$^$9!#\e(B
+
+@end defvar
+
+@node Gmane Spam Reporting
+@subsubsection Gmane Spam \e$BJs9p\e(B
+@cindex spam reporting
+@cindex Gmane, spam reporting
+@cindex Gmane, spam reporting
+@cindex spam
+
+@defvar gnus-group-spam-exit-processor-report-gmane
+
+\e$B%0%k!<%W%Q%i%a!<%?$+JQ?t\e(B @code{gnus-spam-process-newsgroups} \e$B$r%+%9%?%^\e(B
+\e$B%$%:$7$F!"$3$N%7%s%\%k$r%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$(\e(B
+\e$B$F2<$5$$!#$3$l$,2C$($i$l$k$H!"\e(Bspam \e$B0u$,IU$$$?5-;v$N%0%k!<%W$,\e(B HTTP \e$B7PM3\e(B
+\e$B$G\e(B Gmane \e$B$N4IM}<T$KJs9p$5$l$^$9!#\e(B
+
+Gmane \e$B$O\e(B @uref{http://gmane.org} \e$B$G8+$D$1$k$3$H$,$G$-$^$9!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-spam-exit-processor-report-gmane} \e$B$NBe$o$j$K!"\e(B
+@code{'(spam spam-use-gmane)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0:n$9\e(B
+\e$B$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+
+@end defvar
+
+@defvar spam-report-gmane-use-article-number
+
+\e$B$3$NJQ?t$O%G%#%U%)%k%H$G\e(B @code{t} \e$B$G$9!#$"$J$?<+?H$,%K%e!<%9%5!<%P!<$r1?\e(B
+\e$B1D$7$F$$$k!"$9$J$o$A%m!<%+%k$J5-;vHV9f$,\e(B Gmane \e$B$N5-;vHV9f$H9g$o$J$$>l9g\e(B
+\e$B$O!"\e(B@code{nil} \e$B$K@_Dj$7$F2<$5$$!#\e(B
+@code{spam-report-gmane-use-article-number} \e$B$,\e(B @code{nil} \e$B$G$"$k$H!"\e(B
+@file{spam-report.el} \e$B$O\e(B Gmane \e$B$,Ds6!$9$k\e(B @code{X-Report-Spam} \e$B%X%C%@!<\e(B
+\e$B$r;H$$$^$9!#\e(B
+
+@end defvar
+
+@node Anti-spam Hashcash Payments
+@subsubsection \e$BHs\e(B-spam Hashcash \e$B0u\e(B
+@cindex spam filtering
+@cindex hashcash, spam filtering
+@cindex spam
+
+@defvar spam-use-hashcash
+
+@code{spam-use-whitelist} (@pxref{Blacklists and Whitelists}) \e$B$K;w$F$$$^\e(B
+\e$B$9$,!"Aw?.<T$N%"%I%l%9$NBe$o$j$K!"7iGr$J%a%C%;!<%8$N$?$a$N\e(B hashcash \e$B$N\e(B
+\e$B0u\e(B (tokens) \e$B$r;H$$$^$9!#\e(B@code{spam-use-hashcash} \e$B$,@5$7$/F/$/$h$&$K$9$k\e(B
+\e$B$?$a$K!"\e(B@file{hashcash.el} \e$B$rFI$_9~$s$G$*$+$J$1$l$P$J$j$^$;$s!#\e(B
+Hashcash \e$B0u$,L5$$%a%C%;!<%8$O<!$N\e(B spam-\e$BJ,3d\e(B (spam-split) \e$B5,B'$KAw$i$l$^\e(B
+\e$B$9!#$3$l$O\e(B hashcash \e$B0u$,8+Ev$?$i$J$$%a%C%;!<%8$O\e(B spam \e$B$H$b\e(B ham \e$B$H$b8+$J\e(B
+\e$B$5$l$J$$$3$H$r0UL#$9$k!"L@<(E*$J_I2a4o$G$9!#\e(B
+
+@end defvar
+
+@node Blackholes
+@subsubsection \e$B%V%i%C%/%[!<%k\e(B
+@cindex spam filtering
+@cindex blackholes, spam filtering
+@cindex spam
+
+@defvar spam-use-blackholes
+
+\e$B$3$N%*%W%7%g%s$O%G%#%U%)%k%H$GL58z$K$J$C$F$$$^$9!#$3$N%*%W%7%g%s$r%;%C%H\e(B
+\e$B$9$k$H!"\e(Bgnus \e$B$K%V%i%C%/%[!<%k7?$NJ,;6\e(B spam \e$B=hM}%7%9%F%`\e(B (\e$BNc$($P\e(B DCC) \e$B$r\e(B
+\e$BD4$Y$5$;$k$3$H$,$G$-$^$9!#JQ?t\e(B @code{spam-blackhole-servers} \e$B$O!"\e(Bgnus \e$B$,\e(B
+\e$B0U8+$r5a$a$k%V%i%C%/%[!<%k!&%5!<%P!<$N%j%9%H$r;}$A$^$9!#8=:_$N%j%9%H$O$+\e(B
+\e$B$J$j9-HO0O$KEO$C$F$$$^$9$,!"$b$7;~BeCY$l$J%5!<%P!<$r4^$s$G$$$?$i;d$?$A$K\e(B
+\e$BCN$i$;$k$?$a$K!"3NG'$7$F2<$5$$!#\e(B
+
+\e$B%V%i%C%/%[!<%k!&%A%'%C%/$O\e(B @file{dig.el} \e$B%Q%C%1!<%8$r;H$$$^$9!#$7$+\e(B
+\e$B$7\e(B @code{spam-use-dig} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$l$P!"$h$jNI$$@-G=$N$?$a\e(B
+\e$B$K\e(B @file{dns.el} \e$B$rBe$o$j$K;H$&$3$H$r\e(B @file{spam.el} \e$B$K;X<($9$k$3$H$,$G\e(B
+\e$B$-$^$9!#8=>u$G$O\e(B @code{spam-use-dig} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$3$H$O!"$$\e(B
+\e$B$/?M$+$N%f!<%6!<$,;H$($J$$$+$b$7$l$J$$$N$G!"$=$l$,2DG=$J@-G=2~A1$G$"$k$K\e(B
+\e$B$b$+$+$o$i$:?d>)$5$l$^$;$s!#$7$+$7!"$=$l$,F0$/$+$I$&$+$r3N$+$a$k$3$H$O$G\e(B
+\e$B$-$^$9!#\e(B
+
+@end defvar
+
+@defvar spam-blackhole-servers
+
+\e$B%V%i%C%/%[!<%k!&%A%'%C%/$N$?$a$K0U8+$r5a$a$k%5!<%P!<$N%j%9%H$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-blackhole-good-server-regex
+
+\e$B%V%i%C%/%[!<%k!&%5!<%P!<$N%j%9%H$H>H9g$5$l$F$O$J$i$J$$\e(B IP \e$B$N@55,I=8=!#\e(B
+@code{nil} \e$B$K@_Dj$5$l$k$HL58z$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-use-dig
+
+@file{dns.el} \e$B%Q%C%1!<%8$NBe$o$j$K\e(B @file{dig.el} \e$B%Q%C%1!<%8$r;H$$$^$9!#\e(B
+\e$B%G%#%U%)%k%H$N@_Dj$G$"$k\e(B @code{t} \e$B$,?d>)$5$l$^$9!#\e(B
+
+@end defvar
+
+\e$B%V%i%C%/%[!<%k!&%A%'%C%/$OF~$C$FMh$k%a!<%k$KBP$7$F$@$19T$J$o$l$^$9!#%V%i%C\e(B
+\e$B%/%[!<%k$K\e(B spam \e$B$^$?$O\e(B ham \e$B%W%m%;%C%5!<$O$"$j$^$;$s!#\e(B
+
+@node Regular Expressions Header Matching
+@subsubsection \e$B@55,I=8=$K$h$k%X%C%@!<$N9gCW8!::\e(B
+@cindex spam filtering
+@cindex regular expressions header matching, spam filtering
+@cindex spam
+
+@defvar spam-use-regex-headers
+
+\e$B$3$N%*%W%7%g%s$O%G%#%U%)%k%H$GL58z$K$J$C$F$$$^$9!#$3$N%*%W%7%g%s$r%;%C%H\e(B
+\e$B$9$k$H!"\e(Bgnus \e$B$K@55,I=8=$N%j%9%H$H%a%C%;!<%8%X%C%@!<$r>H9g$5$;$k$3$H$,$G\e(B
+\e$B$-$^$9!#JQ?t\e(B @code{spam-regex-headers-spam} \e$B$*$h\e(B
+\e$B$S\e(B @code{spam-regex-headers-ham} \e$B$,@55,I=8=$N%j%9%H$r;}$A$^$9!#%a%C%;!<\e(B
+\e$B%8$,\e(B spam \e$B$^$?$O\e(B ham \e$B$+$I$&$+$r7h$a$k$?$a$K!"\e(BGnus \e$B$O%a%C%;!<%8%X%C%@!<$N\e(B
+\e$B$=$l$>$l$r8!::$7$^$9!#\e(B
+
+@end defvar
+
+@defvar spam-regex-headers-spam
+
+\e$B%a%C%;!<%8%X%C%@!<$NCf$G0lCW$7$?;~$K!"$=$l$,L@$i$+$K\e(B spam \e$B$G$"$k$3$H$r8+\e(B
+\e$BJ,$1$k$?$a$N@55,I=8=$N%j%9%H$G$9!#\e(B
+
+@end defvar
+
+@defvar spam-regex-headers-ham
+
+\e$B%a%C%;!<%8%X%C%@!<$NCf$G0lCW$7$?;~$K!"$=$l$,L@$i$+$K\e(B ham \e$B$G$"$k$3$H$r8+\e(B
+\e$BJ,$1$k$?$a$N@55,I=8=$N%j%9%H$G$9!#\e(B
+
+@end defvar
+
+\e$B@55,I=8=$K$h$k%X%C%@!<$N8!::$O!"F~$C$F$-$?%a!<%k$KBP$7$F$@$19T$J$o$l$^$9!#\e(B
+\e$B@55,I=8=$N$?$a$KFCM-$J\e(B spam \e$B$^$?$O\e(B ham \e$B%W%m%;%C%5!<$O$"$j$^$;$s!#\e(B
+
+@node Bogofilter
+@subsubsection Bogofilter
+@cindex spam filtering
+@cindex bogofilter, spam filtering
+@cindex spam
+
+@defvar spam-use-bogofilter
+
+Eric Raymond \e$B$N?WB.$J\e(B Bogofilter \e$B$r\e(B @code{spam-split} \e$B$K;HMQ$7$?$$>l9g$O!"\e(B
+\e$B$3$NJQ?t$r%;%C%H$7$F$/$@$5$$!#\e(B
+
+Spam \e$B5-;v$@$1$N\e(B @samp{$} \e$B0u$r4XO"IU$1$k:G>.$N@$OC$K$h$C$F!"\e(BBogofilter \e$B%H\e(B
+\e$B%l!<%K%s%0$O$9$Y$F$+$J$j<+F0E*$K$J$j$^$9!#3F%+%F%4%j!<$N\e(B spam \e$B$+$=$&$G$J\e(B
+\e$B$$?tI4$N5-;v$rF~<j$9$k$^$G!"$3$l$r$d$i$J$1$l$P$J$j$^$;$s!#35N,%b!<%I$K$*\e(B
+\e$B$1$k%G%P%C%0$N$?$a$N!"$"$k$$$O9%4q?4$N$?$a$N%3%^%s%I\e(B @kbd{S t} \e$B$O!"8=:_\e(B
+\e$B$N5-;v$N\e(B @emph{spamicity} (\e$BLuCm\e(B: spam \e$BEY\e(B?) \e$B%9%3%"\e(B (0.0\e$B!A\e(B1.0) \e$B$rI=<($7$^\e(B
+\e$B$9!#\e(B
+
+Bogofilter \e$B$O!"$"$k0lDj$NogCM$K4p$E$$$F!"%a%C%;!<%8$,\e(B spam \e$B$+$I$&$+$r8+\e(B
+\e$B6K$a$^$9!#ogCM$O%+%9%?%^%$%:$G$-$^$9!#\e(BBogofilter \e$B$N%I%-%e%a%s%H$rD4$Y$F\e(B
+\e$B2<$5$$!#\e(B
+
+Path \e$B$K\e(B @code{bogofilter} \e$B$N<B9T%U%!%$%k$,L5$$>l9g!"\e(BBogofilter \e$B$N=hM}$O\e(B
+\e$B<h$j>C$5$l$^$9!#\e(B
+
+@code{spam-use-bogofilter-headers} \e$B$r;H$&>l9g$O!"$3$l$rM-8z$K$7$F$O$$$1\e(B
+\e$B$^$;$s!#\e(B
+
+@end defvar
+
+@defvar spam-use-bogofilter-headers
+
+\e$B%a%C%;!<%8%X%C%@!<$@$1$rD4$Y$k$?$a$K\e(B Eric Raymond \e$B$N?WB.\e(B
+\e$B$J\e(B Bogofilter \e$B$r\e(B @code{spam-split} \e$B$K;HMQ$7$?$$>l9g$O!"$3$NJQ?t$r%;%C%H\e(B
+\e$B$7$F$/$@$5$$!#$3$l$O\e(B @code{spam-use-bogofilter} \e$B$HF1$8$h$&$KF0:n$7$^$9$,!"\e(B
+\e$B$"$i$+$8$a\e(B @code{X-Bogosity} \e$B%X%C%@!<$,%a%C%;!<%8$KB8:_$7$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#DL>o$3$l$O\e(B procmail \e$B$N5;K!$+!"2?$+$=$l$K;w$?$b$N$G9T$J$&$3$H$K$J$k\e(B
+\e$B$G$7$g$&!#\e(BBogofilter \e$B$N%$%s%9%H!<%k$K4X$9$kJ8=q$rD4$Y$F2<$5$$!#\e(B
+
+@code{spam-use-bogofilter} \e$B$r;H$&>l9g$O!"$3$l$rM-8z$K$7$F$O$$$1$^$;$s!#\e(B
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-bogofilter
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bspam \e$B0u$,IU$$\e(B
+\e$B$?5-;v$,\e(B bogofilter \e$B$N\e(B spam \e$B%G!<%?%Y!<%9$K2C$($i$^$9!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-spam-exit-processor-bogofilter} \e$B$NBe$o$j$K!"\e(B
+@code{'(spam spam-use-bogofilter)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$K\e(B
+\e$BF0:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-bogofilter
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bham \e$B0u$,IU$$\e(B
+\e$B$?\e(B @emph{ham} \e$B%0%k!<%W$N5-;v$,Hs\e(B-spam \e$B5-;vMQ$N\e(B Bogofilter \e$B%G!<%?%Y!<%9$K\e(B
+\e$BDI2C$5$l$^$9!#$3$N\e(B ham \e$B%W%m%;%C%5!<$O\e(B @emph{spam} \e$B$+\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<\e(B
+\e$B%W$K$O8z2L$r5Z$\$5$J$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-ham-exit-processor-bogofilter} \e$B$NBe$o$j$K!"\e(B
+@code{'(ham spam-use-bogofilter)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0\e(B
+\e$B:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+@defvar spam-bogofilter-database-directory
+
+\e$B$3$l$O\e(B Bogofilter \e$B$,$=$N%G!<%?%Y!<%9$r3JG<$9$k%G%#%l%/%H%j$G$9!#%G%#%U%)\e(B
+\e$B%k%H$G$O@_Dj$5$l$F$$$J$$$N$G!"\e(BBogofilter \e$B$O$=$l<+?H$N%G%#%U%)%k%H$N%G!<\e(B
+\e$B%?%Y!<%9!&%G%#%l%/%H%j$r;H$$$^$9!#\e(B
+
+@end defvar
+
+Bogofilter \e$B$N%a!<%kJ,N`4o$O!"0U?^$HL\E*$NE@$G\e(B @command{ifile} \e$B$K;w$F$$$^\e(B
+\e$B$9!#\e(BSpam \e$B$H\e(B ham \e$B$N%W%m%;%C%5!<$,Ds6!$5$l!"2C$($F\e(B spam-\e$BJ,\e(B
+\e$B3d\e(B (spam-split) \e$B$K$b\e(B Bogofilter \e$B$,;H$o$l$k$Y$-$G$"$k$3$H!"$^$?$O$9$G$K5-\e(B
+\e$B;v$K;H$o$l$?$3$H$r<($9\e(B @code{spam-use-bogofilter} \e$B$*$h\e(B
+\e$B$S\e(B @code{spam-use-bogofilter-headers} \e$BJQ?t$,Ds6!$5$l$^$9!#$3$N5!G=$r8!::\e(B
+\e$B$9$k$?$a$K\e(B Bogofilter \e$B$N%P!<%8%g%s\e(B 0.9.2.1 \e$B$,;H$o$l$^$7$?!#\e(B
+
+@node ifile spam filtering
+@subsubsection ifile \e$B$K$h$k\e(B spam \e$B$N_I2a\e(B
+@cindex spam filtering
+@cindex ifile, spam filtering
+@cindex spam
+
+@defvar spam-use-ifile
+
+Bogofilter \e$B$K;w$?E}7WJ,@O4o$G$"\e(B
+\e$B$k\e(B @command{ifile} \e$B$r\e(B @code{spam-split} \e$B$K;H$$$?$$>l9g$O!"$3$NJQ?t$rM-8z\e(B
+\e$B$K$7$F2<$5$$!#\e(B
+
+@end defvar
+
+@defvar spam-ifile-all-categories
+
+@code{spam-use-ifile} \e$B$K!"C1$J$k\e(B spam/\e$BHs\e(B-spam \e$B$G$O$J$/$F\e(B ifile \e$B$N$9$Y$F\e(B
+\e$B$N%+%F%4%j!<$rM?$($F$b$i$$$?$$$J$i$P!"$3$NJQ?t$rM-8z$K$7$F2<$5$$!#$3$l$r\e(B
+\e$B;H$&>l9g$O!"$=$NJ88%$K=q$+$l$F$$$k$h$&$K\e(B ifile \e$B$r%H%l!<%K%s%0$7$F$*$+$J\e(B
+\e$B$1$l$P$J$j$^$;$s!#\e(B
+
+@end defvar
+
+@defvar spam-ifile-spam-category
+
+ifile \e$B$K4X$9$k8B$j!"$3$l$O\e(B spam \e$B%a%C%;!<%8$N%+%F%4%j!<$G$9!#<B:]$K;H$o$l\e(B
+\e$B$kJ8;zNs$OL54X78$G$9$,!"$?$V$s$"$J$?$O\e(B @samp{spam} \e$B$NCM$r;D$7$F$*$-$?$$\e(B
+\e$B$G$7$g$&!#\e(B
+@end defvar
+
+@defvar spam-ifile-database-path
+
+\e$B$3$l$O\e(B ifile \e$B%G!<%?%Y!<%9$N%U%!%$%kL>$G$9!#%G%#%U%)%k%H$G$ODj5A$5$l$F$$\e(B
+\e$B$J$$$N$G!"\e(Bifile \e$B$O$=$l<+?H$N%G%#%U%)%k%H$N%G!<%?%Y!<%9L>$r;H$$$^$9!#\e(B
+
+@end defvar
+
+ifile \e$B$N%a!<%kJ,N`4o$O!"0U?^$HL\E*$NE@$G\e(B Bogofilter \e$B$K;w$F$$$^$9!#\e(B
+Spam \e$B$H\e(B ham \e$B$N%W%m%;%C%5!<!"$=$l$K\e(B spam-\e$BJ,3d\e(B (spam-split) \e$B$K\e(B ifile \e$B$,;H\e(B
+\e$B$o$l$k$Y$-$G$"$k$3$H$r<($9\e(B @code{spam-use-ifile} \e$BJQ?t$rDs6!$7$^$9!#$3$N\e(B
+\e$B5!G=$r8!::$9$k$?$a$K\e(B ifile \e$B$N%P!<%8%g%s\e(B 1.2.1 \e$B$,;H$o$l$^$7$?!#\e(B
+
+@node spam-stat spam filtering
+@subsubsection spam-\e$BE}7W\e(B (spam-stat) \e$B$K$h$k\e(B spam \e$B$N_I2a\e(B
+@cindex spam filtering
+@cindex spam-stat, spam filtering
+@cindex spam-stat
+@cindex spam
+
+@xref{Filtering Spam Using Statistics with spam-stat}.
+
+@defvar spam-use-stat
+
+Emacs Lisp \e$B$K$h$kE}7WJ,@O4o$G$"$k\e(B spam-stat.el \e$B$r\e(B @code{spam-split} \e$B$K;H\e(B
+\e$B$o$;$?$$$J$i$P!"$3$NJQ?t$rM-8z$K$7$F2<$5$$!#\e(B
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-stat
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bspam \e$B0u$,IU$$\e(B
+\e$B$?5-;v$,\e(B spam \e$B5-;vMQ$N\e(B spam-stat \e$B%G!<%?%Y!<%9$KDI2C$5$l$^$9!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-spam-exit-processor-stat} \e$B$NBe$o$j$K!"\e(B
+@code{'(spam spam-use-stat)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0:n$9\e(B
+\e$B$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-stat
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bham \e$B0u$,IU$$\e(B
+\e$B$?\e(B @emph{ham} \e$B%0%k!<%W$N5-;v$,Hs\e(B-spam \e$B5-;vMQ$N\e(B spam-stat \e$B%G!<%?%Y!<%9$K\e(B
+\e$BDI2C$5$l$^$9!#$3$N\e(B ham \e$B%W%m%;%C%5!<$O\e(B @emph{spam} \e$B$+\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<\e(B
+\e$B%W$K$O8z2L$r5Z$\$5$J$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-ham-exit-processor-stat} \e$B$NBe$o$j$K!"\e(B
+@code{'(ham spam-use-stat)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0:n$9$k\e(B
+\e$B$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+\e$B$3$l$O\e(B @file{spam.el} \e$B$,\e(B @file{spam-stat.el} \e$B$HF/$-9g$&$3$H$r2DG=$K$7$^\e(B
+\e$B$9!#\e(B@file{spam-stat.el} \e$B$O\e(B (Lisp \e$B$@$1$N\e(B) spam \e$BFbIt%G!<%?%Y!<%9$rDs6!$7$^\e(B
+\e$B$9$,!"$=$l$O\e(B ifile \e$B$d\e(B Bogofilter \e$B$H0c$C$F30It%W%m%0%i%`$rI,MW$H$7$^$;$s!#\e(B
+Spam \e$B$H\e(B ham \e$B$N%W%m%;%C%5!<$H\e(B @code{spam-split} \e$B$N$?$a\e(B
+\e$B$N\e(B @code{spam-use-stat} \e$BJQ?t$,Ds6!$5$l$^$9!#\e(B
+
+@node SpamOracle
+@subsubsection Gnus \e$B$G\e(B SpamOracle \e$B$r;H$&$K$O\e(B
+@cindex spam filtering
+@cindex SpamOracle
+@cindex spam
+
+\e$B5$7Z$K\e(B spam \e$B$r_I2a$9$k0l$D$N$d$jJ}$O\e(B SpamOracle \e$B$r;H$&$3$H$G$9!#E}7WE*$K\e(B
+\e$B%a!<%k$r_I2a$9$k$?$a$NF;6q$G$"$k\e(B SpamOracle \e$B$O!"\e(BXavier Leroy \e$B$K$h$C$F=q\e(B
+\e$B$+$l$^$7$?!#$3$l$OJL$K%$%s%9%H!<%k$9$kI,MW$,$"$j$^$9!#\e(B
+
+Gnus \e$B$G\e(B SpamOracle \e$B$r;H$&$K$O!"$$$/$D$+$N$d$jJ}$,$"$j$^$9!#$9$Y$F$N>l9g\e(B
+\e$B$K!"%a!<%k$O\e(B @emph{mark} \e$B%b!<%I$GF0:n$7$F$$$k\e(B SpamOracle \e$B$K%Q%$%W$5$l$^\e(B
+\e$B$9!#$9$k$H\e(B SpamOracle \e$B$O!"$=$N%a!<%k$r\e(B spam \e$B$@$H8+$J$7$?$+$I$&$+$r<(\e(B
+\e$B$9\e(B @samp{X-Spam} \e$B%X%C%@!<$r5-F~$7$^$9!#\e(B
+
+\e$B<B8=2DG=$J0l$D$O!"\e(BSpamOracle \e$B$r\e(B @code{:prescript} \e$B$H$7$F\e(B @ref{Mail
+Source Specifiers} \e$B$+$iAv$i$;$k$3$H$G$9!#$3$NJ}K!$K$O!"%f!<%6\e(B
+\e$B$,\e(B @emph{X-Spam} \e$B%X%C%@!<$r8+$k$3$H$,$G$-$k$H$$$&MxE@$,$"$j$^$9!#\e(B
+
+\e$B$b$C$H$b<j7Z$JJ}K!$O!"\e(B@file{spam.el} (@pxref{Filtering Spam Using The
+Spam ELisp Package}) \e$B$,\e(B SpamOracle \e$B$r8F$V$h$&$K$9$k$3$H$G$9!#\e(B
+
+@vindex spam-use-spamoracle
+@file{spam.el} \e$B$,\e(B SpamOracle \e$B$r;H$($k$h$&$K$9$k$K$O!"JQ\e(B
+\e$B?t\e(B @code{spam-use-spamoracle} \e$B$r\e(B @code{t} \e$B$K$7$F!"\e(B@ref{Filtering Spam
+Using The Spam ELisp Package} \e$B$N9`$G=R$Y$i$l$F$$$k$h$&\e(B
+\e$B$K\e(B @code{nnmail-split-fancy} \e$B$+\e(B @code{nnimap-split-fancy} \e$B$r@_Dj$7$F2<$5\e(B
+\e$B$$!#$3$NNc$G$O\e(B @code{nnimap} \e$B%5!<%P!<$N\e(B @samp{INBOX} \e$B$,\e(B SpamOracle \e$B$K$h$C\e(B
+\e$B$F_I2a$5$l$^$9!#\e(BSpam \e$B$@$H8+$J$5$l$?%a!<%k$O\e(B @code{spam-split-group}\e$B!"$3\e(B
+\e$B$N>l9g$O\e(B @samp{Junk} \e$B$K0\F0$5$;$i$l$^$9!#\e(BHam \e$B$J%a%C%;!<%8\e(B
+\e$B$O\e(B @samp{INBOX} \e$B$K;D$j$^$9\e(B:
+
+@example
+(setq spam-use-spamoracle t
+      spam-split-group "Junk"
+      nnimap-split-inbox '("INBOX")
+      nnimap-split-rule 'nnimap-split-fancy
+      nnimap-split-fancy '(| (: spam-split) "INBOX"))
+@end example
+
+@defvar spam-use-spamoracle
+Gnus \e$B$K\e(B SpamOracle \e$B$r;H$C$F\e(B spam \e$B$N_I2a$r$5$;$?$$>l9g$K\e(B @code{t} \e$B$K$7$F\e(B
+\e$B2<$5$$!#\e(B
+@end defvar
+
+@defvar spam-spamoracle-binary
+Gnus \e$B$O%f!<%6$N\e(B PATH \e$B$G8+$D$+$C$?\e(B @file{spamoracle} \e$B$H$$$&\e(B SpamOracle \e$B$N\e(B
+\e$B%P%$%J%j$r;H$$$^$9!#$3$l$K$O%+%9%?%^%$%:2DG=$JJQ\e(B
+\e$B?t\e(B @code{spam-spamoracle-binary} \e$B$r;H$$$^$9!#\e(B
+@end defvar
+
+@defvar spam-spamoracle-database
+SpamOracle \e$B$O$=$N2r@O7k2L$r%G!<%?%Y!<%9$H$7$F3JG<$9$k$?$a$K!"%G%#%U%)%k\e(B
+\e$B%H$G\e(B @file{~/.spamoracle.db} \e$B%U%!%$%k$r;H$$$^$9!#$3$l$OJQ\e(B
+\e$B?t\e(B @code{spam-spamoracle-database} \e$B$G@)8f$5$l!"%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#$=$l$O!"%G%#%U%)%k%H$N\e(B SpamOracle \e$B%G!<%?%Y!<%9$,;H$o\e(B
+\e$B$l$k$3$H$r0UL#$7$^$9!#%G!<%?%Y!<%9$,$I$3$+FCJL$J>l=j$K$"$k>l9g$O!"\e(B
+@code{spam-spamoracle-database} \e$B$r$=$N%Q%9$K@_Dj$7$F2<$5$$!#\e(B
+@end defvar
+
+SpamOracle \e$B$O%a%C%;!<%8$,\e(B spam \e$B$+\e(B ham \e$B$+$r8+6K$a$k$?$a$KE}7WE*$J<jK!$r;H\e(B
+\e$B$$$^$9!#4V0c$$$d8+F($7$N>/$J$$NI$$7k2L$rF@$k$?$a$K!"\e(BSpamOracle \e$B$O%H%l!<\e(B
+\e$B%K%s%0$rI,MW$H$7$^$9!#\e(BSpamOracle \e$B$O\e(B spam \e$B%a!<%k$NFCD'$r3X$S$^$9!#\e(B
+@emph{add} \e$B%b!<%I\e(B (\e$B%H%l!<%K%s%0!&%b!<%I\e(B) \e$B$r;H$C$F!"NI$$%a!<\e(B
+\e$B%k\e(B (ham) \e$B$H\e(B spam \e$B$r\e(B SpamOracle \e$B$KM?$($J$1$l$P$J$j$^$;$s!#$3$l$O!"35N,%P%C\e(B
+\e$B%U%!$G\e(B @kbd{|} \e$B$r2!$9$3$H$K$h$C$F%a!<%k$r\e(B SpamOracle \e$B$N%W%m%;%9$K%Q%$%W\e(B
+\e$B$9$k$+!"$^$?$O\e(B @file{spam.el} \e$B$N\e(B spam \e$B$*$h$S\e(B ham \e$B%W%m%;%C%5!<$r;H$&$3$H\e(B
+\e$B$K$h$C$F9T$J$&$3$H$,$G$-$^$9!"\e(B@xref{Filtering Spam Using The Spam ELisp
+Package}.
+
+@defvar gnus-group-spam-exit-processor-spamoracle
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(Bspam \e$B0u$,IU$$\e(B
+\e$B$?5-;v$,\e(B spam \e$B$N%5%s%W%k$H$7$F\e(B SpamOracle \e$B$KAw$i$l$^$9!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-spam-exit-processor-spamoracle} \e$B$NBe$o$j$K!"\e(B
+@code{'(spam spam-use-spamoracle)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$K\e(B
+\e$BF0:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-spamoracle
+\e$B$3$N%7%s%\%k$r!"%0%k!<%W%Q%i%a!<%?$N%+%9%?%^%$%:$K$h$C$F%0%k!<%W\e(B
+\e$B$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($k$+!"$^$?\e(B
+\e$B$O\e(B @code{gnus-spam-process-newsgroups} \e$BJQ?t$K2C$($F2<$5$$!#$3$N%7%s%\%k\e(B
+\e$B$,%0%k!<%W$N\e(B @code{spam-process} \e$B%Q%i%a!<%?$K2C$($i$l$k$H!"\e(B@emph{ham} \e$B%0\e(B
+\e$B%k!<%W$K$"$k\e(B ham \e$B0u$,IU$$$?5-;v$,\e(B ham \e$B$N5-;v$N%5%s%W%k$H$7\e(B
+\e$B$F\e(B SpamOracle \e$B$KAw$i$l$^$9!#$3$N\e(B ham \e$B%W%m%;%C%5!<\e(B
+\e$B$O\e(B @emph{spam} \e$B$+\e(B @emph{\e$BL$J,N`\e(B} \e$B%0%k!<%W$K$O8z2L$r5Z$\$5$J$$$3$H$KCm0U$7\e(B
+\e$B$F2<$5$$!#\e(B
+
+@emph{\e$B7Y9p\e(B}
+
+\e$BGQ$l$?\e(B @code{gnus-group-ham-exit-processor-spamoracle} \e$B$NBe$o$j$K!"\e(B
+@code{'(ham spam-use-spamoracle)} \e$B$r;H$&$3$H$r?d>)$7$^$9!#$9$Y$FF1Ey$KF0\e(B
+\e$B:n$9$k$3$H$OJ]>Z$5$l$^$9!#\e(B
+@end defvar
+
+@emph{\e$BNc\e(B:} \e$B$3$l$i$O\e(B ham \e$B%0%k!<%W$H$7$FJ,N`$5$l$?!"$D$^$j\e(B ham \e$B$N5-;v$7$+\e(B
+\e$B$J$$%0%k!<%W$N%0%k!<%W%Q%i%a!<%?$G$9!#\e(B
+
+@example
+ ((spam-contents gnus-group-spam-classification-ham)
+  (spam-process ((ham spam-use-spamoracle)
+                 (spam spam-use-spamoracle))))
+@end example
+
+\e$B$3$N%0%k!<%W$G$O\e(B @code{spam-use-spamoracle} \e$B$,\e(B ham \e$B$H\e(B spam \e$BN>J}$N=hM}$r\e(B
+\e$B9T$J$$$^$9!#$3$N%0%k!<%W$K\e(B spam \e$B5-;v$,$"$C$F\e(B (SpamOracle \e$B$,==J,$J%5%s%W\e(B
+\e$B%k$r?)$Y$5$;$F$b$i$C$F$$$J$1$l$P!"$=$&$J$j$^$9$M\e(B)\e$B!"$+$D%f!<%6$,$$$/$D$+\e(B
+\e$B$N5-;v$K\e(B spam \e$B$N0u$rIU$1$?$J$i$P!"$=$l$i$N5-;v$O\e(B SpamOracle \e$B$K$h$C$F=hM}\e(B
+\e$B$5$l$^$9!#$=$N%W%m%;%C%5!<$O!"?7$7$$\e(B spam \e$B$N%5%s%W%k$H$7$F\e(B SpamOracle \e$B$K\e(B
+\e$B5-;v$rAw$j$^$9!#\e(B
+
+@node Extending the Spam ELisp package
+@subsubsection Spam ELisp \e$B%Q%C%1!<%8$N3HD%\e(B
+@cindex spam filtering
+@cindex spam elisp package, extending
+@cindex extending the spam elisp package
+
+\e$B?7$7$$%P%C%/%(%s%I\e(B blackbox \e$B$rDI2C$7$?$$$"$J$?$O!"F~$C$F$/$k%a!<%k$r_I2a\e(B
+\e$B$9$k$?$a$K0J2<$rMQ0U$7$F2<$5$$\e(B:
+
+@enumerate
+
+@item
+\e$B%3!<%I\e(B
+
+@lisp
+(defvar spam-use-blackbox nil
+  "Blackbox \e$B$r;H$&$H$-$O\e(B t \e$B$K$9$k!#\e(B")
+@end lisp
+
+@code{spam-list-of-checks} \e$B$K\e(B
+
+@example
+    (spam-use-blackbox . spam-check-blackbox)
+@end example
+
+\e$B$rDI2C!#\e(B@code{spam-list-of-processors} \e$B$K\e(B
+
+@example
+    (gnus-group-ham-exit-processor-blackbox     ham spam-use-blackbox)
+    (gnus-group-spam-exit-processor-blackbox    spam spam-use-blackbox)
+@end example
+
+\e$B$rDI2C!#\e(B@code{spam-registration-functions} \e$B$K\e(B
+
+@example
+    (spam-use-blackbox  spam-blackbox-register-routine
+                 nil
+                 spam-blackbox-unregister-routine
+                 nil)
+@end example
+
+\e$B$rDI2C!#\e(B
+
+\e$B<j;O$a$K\e(B bogofilter \e$B$NEPO?\e(B/\e$B:o=|%k!<%A%s$r;H$C$FEPO?\e(B/\e$B:o=|%k!<%A%s$r!"$^$?\e(B
+\e$B$O$b$C$H\e(B Blackbox \e$B$KE,@Z$JB>$NEPO?\e(B/\e$B:o=|%k!<%A%s$r=q$$$F2<$5$$!#\e(B
+
+@item
+\e$B4X?t\e(B
+
+@code{spam-check-blackbox} \e$B4X?t$r=q$$$F2<$5$$!#$=$l\e(B
+\e$B$OB>$N=,47$KJo$C$F\e(B @samp{nil} \e$B$+\e(B @code{spam-split-group} \e$B$rJV$5$J$1$l$P\e(B
+\e$B$J$j$^$;$s!#$"$J$?$K$G$-$k$3$H$NNc$O!"4{B8$N\e(B @code{spam-check-*} \e$B4X?t$r\e(B
+\e$B;2>H$7$F$/$@$5$$!#$^$?!"$"$J$?$,$=$&$G$J$$M}M3$r40A4$KM}2r$7$F$$$J$$$J$i\e(B
+\e$B$P!"%F%s%W%l!<%H$Ksv$jIU$$$F2<$5$$!#\e(B
+
+\e$B%V%i%C%/%\%C%/%9$,!"$=$l$,F0:n$9$k$?$a$K%a%C%;!<%8A4BN$rI,MW$H$9$kE}7WE*\e(B
+\e$B%a!<%kJ,@O4o$G$"$k$N$J$i$P!"\e(B
+@code{spam-list-of-statistical-checks} \e$B$K\e(B @code{spam-use-blackbox} \e$B$rDI\e(B
+\e$B2C$9$k$3$H$rK:$l$J$$$G2<$5$$!#\e(B
+@end enumerate
+
+Spam \e$B$H\e(B ham \e$B%a%C%;!<%8$r=hM}$9$k$K$O!"0J2<$rMQ0U$7$F2<$5$$\e(B:
+
+@enumerate
+
+@item
+\e$B%3!<%I\e(B
+
+Spam \e$B$^$?$O\e(B ham \e$B$N%W%m%;%C%5!<$rMQ0U$9$kI,MW$O$"$j$^$;$s!#\e(B
+Blackbox \e$B$,\e(B spam \e$B$^$?$O\e(B ham \e$B$N=hM}$r%5%]!<%H$9$k>l9g$@$1!"$=$l$i$rMQ0U$7\e(B
+\e$B$F2<$5$$!#\e(B
+
+\e$B$5$i$K\e(B ham \e$B$H\e(B spam \e$B$N%W%m%;%C%5!<$OC10l$NJQ?t$G$O$J$/$5$l$D$D$"$j!"Be$o\e(B
+\e$B$j$K\e(B @code{'(spam spam-use-blackbox)} \e$B$^$?\e(B
+\e$B$O\e(B @code{'(ham spam-use-blackbox)} \e$B$N7A<0$,?d>)$5$l$^$9!#:#$N$H$3\e(B
+\e$B$m\e(B spam/ham \e$B%W%m%;%C%5!<JQ?t$O$^$@$"$A$3$A$K$"$j$^$9$,!"D9$/$O$"$j$^$;$s!#\e(B
+
+@lisp
+(defvar gnus-group-spam-exit-processor-blackbox "blackbox-spam"
+  "\e$B35N,$r=P$k$H$-$K8F$P$l$k\e(B blackbox \e$B$N\e(B spam \e$B%W%m%;%C%5!<!#\e(B
+Spam \e$B%0%k!<%W$@$1$KE,MQ$5$l$k!#\e(B")
+
+(defvar gnus-group-ham-exit-processor-blackbox "blackbox-ham"
+  "\e$B35N,$r=P$k$H$-$K8F$P$l$k\e(B blackbox \e$B$N\e(B ham \e$B%W%m%;%C%5!<!#\e(B
+Spam \e$B$G$O$J$$\e(B (\e$BL$J,N`$^$?$O\e(B ham) \e$B%0%k!<%W$@$1$KE,MQ$5$l$k!#\e(B")
+
+@end lisp
+
+@item
+Gnus \e$B$N%Q%i%a!<%?\e(B
+
+@code{gnus.el} \e$B$K$"$k%0%k!<%W%Q%i%a!<%?\e(B @code{spam-process} \e$B$K\e(B
+
+@example
+                   (const :tag "Spam: Blackbox"   (spam spam-use-blackbox))
+                   (const :tag "Ham: Blackbox"    (ham spam-use-blackbox))
+@end example
+
+\e$B$r2C$($F2<$5$$!#$=$l$r%Q%i%a!<%?$HJQ?t$N%+%9%?%^%$%:$NFs2s$K$D$$$F9T$J$&\e(B
+\e$B$3$H$r3N$+$a$F2<$5$$!#\e(B
+
+@code{gnus.el} \e$B$N%0%k!<%W%Q%i%a!<%?\e(B @code{spam-autodetect-methods} \e$B$K\e(B
+
+@example
+          (variable-item spam-use-blackbox)
+@end example
+
+\e$B$r2C$($F2<$5$$!#\e(B
+
+@end enumerate
+
+@node Filtering Spam Using Statistics with spam-stat
+@subsection Spam \e$B$N_I2a$K\e(B spam-stat \e$B$K$h$kE}7W$r;H$&\e(B
+@cindex Paul Graham
+@cindex Graham, Paul
+@cindex naive Bayesian spam filtering
+@cindex Bayesian spam filtering, naive
+@cindex spam filtering, naive Bayesian
+
+Paul Graham \e$B$O!"E}7W$r;H$C$?\e(B spam \e$B$N_I2a$K4X$9$kM%$l$?%(%C%;%$$r=q$-$^$7\e(B
+\e$B$?\e(B: @uref{http://www.paulgraham.com/spam.html,A Plan for Spam}\e$B!#$=$3$GH`\e(B
+\e$B$O\e(B SpamAssassin \e$B$K$h$C$F;H$o$l$F$$$k$h$&$J%k!<%k%Y!<%9$N_I2a$K8GM-$J7g4Y\e(B
+\e$B$K$D$$$F=R$Y$F$$$^$9!#Nc$($P\e(B: \e$BC/$+$,%k!<%k$r=q$+$J$1$l$P$J$i$J$$$7!"B>$N\e(B
+\e$B$9$Y$F$N?M$O$3$l$i$N%k!<%k$r%$%s%9%H!<%k$7$J$1$l$P$J$j$^$;$s!#$"$J$?$O$$\e(B
+\e$B$D$bCY$l$r$H$C$F$7$^$$$^$9!#$=$l$h$j$b!"$=$l$,\e(B spam \e$B$^$?$OHs\e(B-spam \e$B$K2?$H\e(B
+\e$B$J$/;w$F$$$k$+$I$&$+$K4p$E$$$F%a!<%k$r_I2a$9$k$[$&$,$O$k$+$KNI$$$@$m$&$H\e(B
+\e$BH`$O<gD%$7$^$9!#$3$l$rB,Dj$9$k0l$D$N<jCJ$OC18l$NJ,I[$G$9!#$=$N8eH`$O!"?7\e(B
+\e$BCe%a!<%k$,$"$J$?$NB>$N\e(B spam \e$B%a!<%k$K;w$F$$$k$+$I$&$+$r%A%'%C%/$9$kJ}K!$N\e(B
+\e$B5-=R$K?J$_$^$9!#\e(B
+
+\e$B4pK\E*$J0F$O$3$l$G$9\e(B: \e$B$"$J$?$N%a!<%k$NFs$D$N%3%l%/%7%g%s$r:n$j$^$9!#0l$D\e(B
+\e$B$O\e(B spam\e$B!"$b$&0l$D$OHs\e(B-spam \e$B$G!#N>J}$N%3%l%/%7%g%s$K$*$1$k3FC18l$N=P8=IQ\e(B
+\e$BEY$r?t$($F!"%3%l%/%7%g%s$N%a!<%k$NAm?t$G=E$_IU$1$r9T$J$$!"$3$N>pJs$r<-=q\e(B
+\e$B$K3JG<$7$^$9!#?7Ce%a!<%k$N$9$Y$F$NC18l$K$D$$$F!"\e(Bspam \e$B$+Hs\e(B-spam \e$B%a!<%k$K\e(B
+\e$BB0$9$k3NN($r7hDj$7$^$9!#\e(B15 \e$B$N:G$b82Cx$JC18l$r;H$C$F!"$=$N%a!<%k\e(B
+\e$B$,\e(B spam \e$B$G$"$k$3$H$N3NN($NAm7W$r7W;;$7$^$9!#$3$N3NN($,$"$kogCM$h$j9b$+$C\e(B
+\e$B$?$i!"$=$N%a!<%k$O\e(B spam \e$B$G$"$k$H9M$($i$l$^$9!#\e(B
+
+gnus \e$B$O$3$N<o$N_I2a$r%5%]!<%H$7$^$9!#$7$+$7$=$l$K$O$$$/$D$+$N@_Dj$,I,MW\e(B
+\e$B$G$9!#Bh0l$K!"$"$J$?$N%a!<%k$NFs$D$N%3%l%/%7%g%s$,MW$j$^$9!#0l$D$O\e(B spam\e$B!"\e(B
+\e$B$b$&0l$D$OHs\e(B-spam \e$B$G!#$=$7$F!"$=$l$i$NFs$D$N%3%l%/%7%g%s$r;H$C$F<-=q$r:n\e(B
+\e$B$j!"$=$l$r%;!<%V$7$F2<$5$$!#$=$7$FFC$K:G8e$K!"$"$J$?$NFC5iJ,3d$N5,B'$G$3\e(B
+\e$B$N<-=q$r;H$C$F2<$5$$!#\e(B
+
+@menu
+* Creating a spam-stat dictionary::
+* Splitting mail using spam-stat::
+* Low-level interface to the spam-stat dictionary::
+@end menu
+
+@node Creating a spam-stat dictionary
+@subsubsection spam-\e$BE}7W\e(B (spam-stat) \e$B<-=q$r:n$k\e(B
+
+\e$BE}7W$K4p$E$$$?\e(B spam \e$B_I2a$r;O$a$k$K$O!"$"$J$?$OFs$D$N%a!<%k$N%3%l%/%7%g%s\e(B
+\e$B$K4p$E$$$?E}7W$r:n$i$J$1$l$P$J$j$^$;$s!#0l$D$O\e(B spam \e$B$b$&0l$D$OHs\e(B-spam \e$B$G!#\e(B
+\e$B$=$7$F$=$l$i$NE}7W$O!"8e$GMxMQ$9$k$?$a$K<-=q$K3JG<$5$l$^$9!#$=$l$i$NE}7W\e(B
+\e$B$r0UL#$N$"$k$b$N$K$9$k$?$a$K!"N>J}$N%3%l%/%7%g%s$K$D$-?tI4DL$N%a!<%k$,I,\e(B
+\e$BMW$G$9!#\e(B
+
+\e$B:#$N$H$3$m\e(B gnus \e$B$O\e(B nnml \e$B%P%C%/%(%s%I$G$@$1<-=q$N<+F0@8@.$r%5%]!<%H$7$^$9!#\e(B
+nnml \e$B%P%C%/%(%s%I$O0lDL$N%a!<%k$K$D$-0l$D$N%U%!%$%k$G!"$9$Y$F$N%a!<%k$r\e(B
+\e$B%G%#%l%/%H%j$K3JG<$7$^$9!#0J2<$r;H$C$F2<$5$$!#\e(B
+
+@defun spam-stat-process-spam-directory
+\e$B$3$N%G%#%l%/%H%j$K$"$k$9$Y$F$N%U%!%$%k$K$D$$$F\e(B spam \e$B$NE}7W$r@8@.$7$^$9!#\e(B
+\e$B$9$Y$F$N%U%!%$%k$O0l$D$N\e(B spam \e$B%a!<%k$H$7$F07$o$l$^$9!#\e(B
+@end defun
+
+@defun spam-stat-process-non-spam-directory
+\e$B$3$N%G%#%l%/%H%j$K$"$k$9$Y$F$N%U%!%$%k$K$D$$$FHs\e(B-spam \e$B$NE}7W$r@8@.$7$^$9!#\e(B
+\e$B$9$Y$F$N%U%!%$%k$O0l$D$N\e(B spam \e$B$G$O$J$$%a!<%k$H$7$F07$o$l$^$9!#\e(B
+@end defun
+
+\e$BIaDL$O\e(B @file{~/Mail/mail/spam} \e$B$N$h$&$J%G%#%l%/%H%j\e(B (\e$BDL\e(B
+\e$B>o\e(B @samp{nnml:mail.spam} \e$B%0%k!<%W$KBP1~\e(B) \e$B$KBP$7\e(B
+\e$B$F\e(B @code{spam-stat-process-spam-directory} \e$B$r8F$V$G$7$g$&!#$^\e(B
+\e$B$?\e(B @file{~/Mail/mail/misc} \e$B$N$h$&$J%G%#%l%/%H%j\e(B (\e$BDL\e(B
+\e$B>o\e(B @samp{nnml:mail.misc} \e$B%0%k!<%W$KBP1~\e(B) \e$B$KBP$7\e(B
+\e$B$F\e(B @code{spam-stat-process-non-spam-directory} \e$B$r8F$V$G$7$g$&!#\e(B
+
+\e$B$"$J$?$,\e(B @acronym{IMAP} \e$B$r;H$C$F$$$k$J$i%a!<%k$r%m!<%+%k$K$O;}$C$F$$$J$$\e(B
+\e$B$N$G!"$=$l$OF0$+$J$$$G$7$g$&!#0l$D$N2r7h:v$O!"\e(Bgnus \e$B%(!<%8%'%s%H$G5-;v$r\e(B
+\e$B%-%c%C%7%e$9$k$3$H$G$9!#$=$&$9$l\e(B
+\e$B$P\e(B @code{spam-stat-process-spam-directory} \e$B$H$7\e(B
+\e$B$F\e(B @file{"~/News/agent/nnimap/mail.yourisp.com/personal_spam"} \e$B$N$h$&$J\e(B
+\e$B$b$N$,;H$($^$9!#\e(B@xref{Agent as Cache}.
+
+@defvar spam-stat
+\e$B$3$NJQ?t$O$9$Y$F$NE}7W$N%O%C%7%e%F!<%V%k\e(B -- \e$B2f!9$,<-=q$H8@$C$F$$$k$b\e(B
+\e$B$N\e(B -- \e$B$r;}$A$^$9!#$3$N%O%C%7%e%F!<%V%k$O!"APJ}$N%3%l%/%7%g%s$N$9$Y$F$NC1\e(B
+\e$B8l$K$D$$$F\e(B spam \e$B$*$h$SHs\e(B-spam \e$B%a!<%k$K$*$1$k=P8=IQEY$rI=$9%Y%/%H%k$r3JG<\e(B
+\e$B$7$^$9!#\e(B
+@end defvar
+
+\e$BE}7W$r:G=i$+$i:n$jD>$7$?$$$H$-$O!"<-=q$r%j%;%C%H$9$kI,MW$,$"$j$^$9!#\e(B
+
+@defun spam-stat-reset
+@code{spam-stat} \e$B%O%C%7%e%F!<%V%k$r%j%;%C%H$7!"$9$Y$F$NE}7W$r:o=|$7$^$9!#\e(B
+@end defun
+
+\e$B9T$J$C$?$i<-=q$r%;!<%V$7$J$1$l$P$J$j$^$;$s!#<-=q$O$+$J$jBg$-$/$J$k$+$b$7\e(B
+\e$B$l$^$;$s!#<-=q$rDI2C99?7$7$J$$>l9g\e(B (\e$B8@$$49$($k$H!"Nc$($PKh7n0l2s:n$jD>$9\e(B
+\e$B>l9g\e(B)\e$B!"IQHK$K8=$l$J$$$+!"$^$?$O\e(B spam \e$B$+Hs\e(B-spam \e$B$N$I$A$i$KB0$9$k$+$,$O$C\e(B
+\e$B$-$j$7$J$$$9$Y$F$NC18l$r:o=|$9$k$3$H$K$h$C$F!"<-=q$N%5%$%:$r>.$5$/$9$k$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+@defun spam-stat-reduce-size
+\e$B<-=q$N%5%$%:$r>.$5$/$7$^$9!#$3$l$O<-=q$rDI2C99?7$7$?$/$J$$>l9g$@$1;H$C$F\e(B
+\e$B2<$5$$!#\e(B
+@end defun
+
+@defun spam-stat-save
+\e$B<-=q$r%;!<%V$7$^$9!#\e(B
+@end defun
+
+@defvar spam-stat-file
+\e$B<-=q$N3JG<$K;H$&%U%!%$%kL>$G$9!#%G%#%U%)%k%H$O\e(B @file{~/.spam-stat.el} \e$B$G\e(B
+\e$B$9!#\e(B
+@end defvar
+
+@node Splitting mail using spam-stat
+@subsubsection spam-\e$BE}7W\e(B (spam-stat) \e$B$r;H$C$F%a!<%k$rJ,3d$9$k\e(B
+
+@code{spam-stat} \e$B$r;H$C$F%a!<%k$rJ,3d$9$k$?$a$K!"\e(B@file{~/.gnus.el} \e$B%U%!\e(B
+\e$B%$%k$K0J2<$rDI2C$9$kI,MW$,$"$j$^$9!#\e(B
+
+@lisp
+(require 'spam-stat)
+(spam-stat-load)
+@end lisp
+
+\e$B$3$l$OI,MW$J\e(B gnus \e$B$N%3!<%I$H$"$J$?$,:n$C$?<-=q$r\e(B load \e$B$7$^$9!#\e(B
+
+\e$B<!$K!"FC5iJ,3d$N5,B'$rE,9g$5$;$kI,MW$,$"$j$^$9\e(B: \e$B$I$&$d$C\e(B
+\e$B$F\e(B @code{spam-stat} \e$B$r;H$&$+$r7h$a$F2<$5$$!#0J2<$NNc$O\e(B nnml \e$B%P%C%/%(%s%I\e(B
+\e$BMQ$G$9!#\e(Bnnimap \e$B%P%C%/%(%s%I$G$b$^$C$?$/F1MM$KF0:n$7$^$9!#C1\e(B
+\e$B$K\e(B @code{nnmail-split-fancy} \e$B$NBe$o$j$K\e(B @code{nnimap-split-fancy} \e$B$r;H$C\e(B
+\e$B$F2<$5$$!#\e(B
+
+\e$B$G$O\e(B @samp{mail.misc} \e$B$H\e(B @samp{mail.spam} \e$B$NFs$D$N%0%k!<%W$@$1$,$"$k:G$b\e(B
+\e$BC1=c$J;vNc$G$O$I$&$J$k$+!#0J2<$N<0$O%a!<%k$,\e(B spam \e$B$G$"$k$+!"$^$?$O$=$l\e(B
+\e$B$,\e(B @samp{mail.misc} \e$B$K9T$/$Y$-$@$H8@$C$F$$$^$9!#$b$7\e(B spam \e$B$@$C$?\e(B
+\e$B$i\e(B @code{spam-stat-split-fancy} \e$B$O\e(B @samp{mail.spam} \e$B$rJV$7$^$9!#\e(B
+
+@lisp
+(setq nnmail-split-fancy
+      `(| (: spam-stat-split-fancy)
+          "mail.misc"))
+@end lisp
+
+@defvar spam-stat-split-fancy-spam-group
+Spam \e$BMQ$N%0%k!<%W$G$9!#%G%#%U%)%k%H$O\e(B @samp{mail.spam} \e$B$G$9!#\e(B
+@end defvar
+
+\e$BFCDj$NBjL>$r;}$D%a!<%k$rB>$N%0%k!<%W$KF~$l$k_I2a$r$b9T$J$$$?$$$J$i$P!"0J\e(B
+\e$B2<$N<0$r;H$C$F2<$5$$!#@55,I=8=$K9gCW$7$J$$%a!<%k$@$1$r\e(B spam \e$B$+$b$7$l$J$$\e(B
+\e$B$H9M$($^$9!#\e(B
+
+@lisp
+(setq nnmail-split-fancy
+      `(| ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          (: spam-stat-split-fancy)
+          "mail.misc"))
+@end lisp
+
+\e$B:G=i$K\e(B spam \e$B$N_I2a$r$7$?$$>l9g!"<-=q$r:n$k$H$-$K==J,$KCm0U$7$J$1$l$P$J$j\e(B
+\e$B$^$;$s!#\e(B
+@code{spam-stat-split-fancy} \e$B$O\e(B @samp{mail.emacs} \e$B$H\e(B @samp{mail.misc} \e$B$N\e(B
+\e$B$I$A$i$N%a!<%k$bHs\e(B-spam \e$B$G$"$k$H2r<a$7$J$1$l$P$J$i$J$$$N$G!"<-=q$r:n$k$H\e(B
+\e$B$-$NHs\e(B-spam \e$B%3%l%/%7%g%s$KN>J}$H$bF~$C$F$$$J$1$l$P$J$i$J$$$3$H$KCm0U$7$F\e(B
+\e$B2<$5$$!#\e(B
+
+@lisp
+(setq nnmail-split-fancy
+      `(| (: spam-stat-split-fancy)
+          ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          "mail.misc"))
+@end lisp
+
+\e$B$3$l$rEAE}E*$J_I2a$HAH$_9g$o$;$k$3$H$b$G$-$^$9!#$3$3$G$O2f!9$O$9$Y$F\e(B
+\e$B$N\e(B HTML \e$B$@$1$N%a!<%k$r\e(B @samp{mail.spam.filtered} \e$B%0%k!<%W$KF~$l$k$b$N$H\e(B
+\e$B$7$^$7$g$&!#\e(B@code{spam-stat-split-fancy} \e$B$O$=$l$i$N%a!<%k$r8+$J$$$N$G!"\e(B
+\e$B<-=q$r:n$k$H$-$K!"\e(B@samp{mail.spam.filtered} \e$B$N%a!<%k$,\e(B spam \e$B$^$?$O\e(B
+\e$BHs\e(B-spam \e$B%3%l%/%7%g%s$N$I$A$i$K$bF~$k$Y$-$G$O$J$$$3$H$KCm0U$7$F2<$5$$\e(B!
+
+@lisp
+(setq nnmail-split-fancy
+      `(| ("Content-Type" "text/html" "mail.spam.filtered")
+          (: spam-stat-split-fancy)
+          ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          "mail.misc"))
+@end lisp
+
+@node Low-level interface to the spam-stat dictionary
+@subsubsection spam-\e$BE}7W\e(B (spam-stat) \e$B<-=q$X$NDc3,AX%$%s%?!<%U%'!<%9\e(B
+
+@code{spam-stat} \e$B$r;H$&$?$a$N<g%$%s%?!<%U%'!<%9$O0J2<$N4X?t$G$9\e(B:
+
+@defun spam-stat-buffer-is-spam
+Spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9!#=hM}A0$N?7\e(B
+\e$BCe%a!<%k$KBP$7$F;H$C$F2<$5$$!#\e(B
+@end defun
+
+@defun spam-stat-buffer-is-no-spam
+\e$BHs\e(B-spam \e$B$G$"$k$H9M$($i$l$k?7Ce%a!<%k$,$"$k%P%C%U%!$G8F$P$l$^$9!#=hM}A0$N\e(B
+\e$B?7Ce%a!<%k$KBP$7$F;H$C$F2<$5$$!#\e(B
+@end defun
+
+@defun spam-stat-buffer-change-to-spam
+Spam \e$B$G$O$J$$DL>o$N%a!<%k$@$H$O$b$O$d9M$($i$l$J$$%a!<%k$,$"$k%P%C%U%!$G\e(B
+\e$B8F$P$l$^$9!#$9$G$KHs\e(B-spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L\e(B
+\e$B$NJQ99$K;H$C$F2<$5$$!#\e(B
+@end defun
+
+@defun spam-stat-buffer-change-to-non-spam
+\e$BDL>o$N%a!<%k$G$O$J$$\e(B spam \e$B$@$H$O$b$O$d9M$($i$l$J$$%a!<%k$,$"$k%P%C%U%!$G\e(B
+\e$B8F$P$l$^$9!#$9$G$K\e(B spam \e$B$G$"$k$b$N$H$7$F=hM}$5$l$F$7$^$C$?%a!<%k$NCO0L$N\e(B
+\e$BJQ99$K;H$C$F2<$5$$!#\e(B
+@end defun
+
+@defun spam-stat-save
+\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$K%;!<%V$7$^$9!#JQ?t\e(B @code{spam-stat-file} \e$B$G\e(B
+\e$B@_Dj$5$l$?%U%!%$%kL>$,;H$o$l$^$9!#\e(B
+@end defun
+
+@defun spam-stat-load
+\e$B%O%C%7%e%F!<%V%k$r%U%!%$%k$+$i\e(B load \e$B$7$^$9!#JQ\e(B
+\e$B?t\e(B @code{spam-stat-file} \e$B$G@_Dj$5$l$?%U%!%$%kL>$,;H$o$l$^$9!#\e(B
+@end defun
+
+@defun spam-stat-score-word
+\e$BC18l$N\e(B spam \e$B%9%3%"$rJV$7$^$9!#\e(B
+@end defun
+
+@defun spam-stat-score-buffer
+\e$B%P%C%U%!$N\e(B spam \e$B%9%3%"$rJV$7$^$9!#\e(B
+@end defun
+
+@defun spam-stat-split-fancy
+\e$BFC5i%a!<%kJ,3d$N$?$a$K$3$N4X?t$r;H$C$F2<$5$$!#\e(B
+@code{nnmail-split-fancy} \e$B$K5,B'\e(B @samp{(: spam-stat-split-fancy)} \e$B$rDI2C\e(B
+\e$B$7$^$9!#\e(B
+@end defun
+
+\e$B$=$l$r;H$&A0$K!"I,$:<-=q$,\e(B load \e$B$5$l$F$$$k$h$&$K$7$F2<$5$$!#$3$l$K\e(B
+\e$B$O\e(B @file{~/.gnus.el} \e$B%U%!%$%k$K0J2<$,I,MW$G$9\e(B:
+
+@lisp
+(require 'spam-stat)
+(spam-stat-load)
+@end lisp
+
+\e$BBeI=E*$J%F%9%H$O0J2<$N4X?t8F=P$7$rI,MW$H$7$^$9\e(B:
+
+@example
+Reset: (setq spam-stat (make-hash-table :test 'equal))
+Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+Save table: (spam-stat-save)
+File size: (nth 7 (file-attributes spam-stat-file))
+Number of words: (hash-table-count spam-stat)
+Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+Reduce table size: (spam-stat-reduce-size)
+Save table: (spam-stat-save)
+File size: (nth 7 (file-attributes spam-stat-file))
+Number of words: (hash-table-count spam-stat)
+Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+@end example
+
+\e$B<-=q$r@8@.$9$kJ}K!\e(B:
+
+@example
+Reset: (setq spam-stat (make-hash-table :test 'equal))
+Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+Repeat for any other non-spam group you need...
+Reduce table size: (spam-stat-reduce-size)
+Save table: (spam-stat-save)
+@end example
+
+@node Other modes
+@section \e$BB>$N%b!<%I$H$NAj8_:nMQ\e(B
+
+@subsection Dired
+@cindex dired
+
+@code{gnus-dired-minor-mode} \e$B$O\e(B dired \e$B%P%C%U%!$G;H$($k$$$/$D$+$NJXMx$J5!\e(B
+\e$BG=$rDs6!$7$^$9!#$3$l$O<!$N<0$GM-8z$K$J$j$^$9\e(B:
+
+@lisp
+(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
+@end lisp
+
+@table @kbd
+@item C-c C-m C-a
+@findex gnus-dired-attach
+Dired \e$B$G0u$rIU$1$?$b$N$rE:IU%U%!%$%k$H$7$FAw?.$7$^\e(B
+\e$B$9\e(B (@code{gnus-dired-attach})\e$B!#\e(BMessage \e$B%P%C%U%!$G3NG'$r5a$a$i$l$^$9!#\e(B
+
+@item C-c C-m C-l
+@findex gnus-dired-find-file-mailcap
+\e$BE,@Z$J\e(B mailcap \e$B9`L\$K=>$C$F%U%!%$%k$r3+$-$^\e(B
+\e$B$9\e(B (@code{gnus-dired-find-file-mailcap})\e$B!#@\F,<-$rIU$1$k$H!"%U%!%$%k$r?7\e(B
+\e$B$7$$%P%C%U%!$G3+$-$^$9!#\e(B
+
+@item C-c C-m C-p
+@findex gnus-dired-print
+mailcap \e$B9`L\$K=>$C$F%U%!%$%k$r0u:~$7$^$9\e(B (@code{gnus-dired-print})\e$B!#0u:~\e(B
+\e$B%3%^%s%I$,L5$$>l9g$O\e(B PostScript \e$B2hA|$K0u:~$7$^$9!#\e(B
+@end table
+
+@node Various Various
+@section \e$B$$$m$$$m$N$$$m$$$m\e(B
+@cindex mode lines
+@cindex highlights
+
+@table @code
+@item gnus-home-directory
+@vindex gnus-home-directory
+\e$B$9$Y$F$N\e(B gnus \e$B$N%U%!%$%kL>$H%G%#%l%/%H%jL>$NJQ?t$O!"$3$l$K$h$C$F=i4|2=$5\e(B
+\e$B$l$^$9!#%G%#%U%)%k%HCM$O\e(B @file{~/} \e$B$G$9!#\e(B
+
+@item gnus-directory
+@vindex gnus-directory
+gnus \e$B$,3JG<$9$k$?$/$5$s$N%U%!%$%kL>$H%G%#%l%/%H%jL>$NJQ?t$O!"$3$l$K$h$C\e(B
+\e$B$F=i4|2=$5$l$^$9!#%G%#%U%)%k%HCM$O\e(B @env{SAVEDIR} \e$B4D6-JQ?t$NCM$+!"$=$NJQ\e(B
+\e$B?t$,@_Dj$5$l$F$$$J$$>l9g$O\e(B @file{~/News/} \e$B$G$9!#\e(B
+
+@file{~/.gnus.el} \e$B%U%!%$%k$,FI$^$l$?$H$-$O\e(B gnus \e$B$N$[$H$s$I$O$9$G$KFI$_9~\e(B
+\e$B$^$l$F$$$k$H$$$&$3$H$KCm0U$7$F$/$@$5$$!#$3$l$O$D$^$j!"$3$NJQ?t\e(B
+\e$B$r\e(B @file{~/.gnus.el} \e$B$NCf$G@_Dj$7$F$b!"$3$NJQ?t$K$h$C$F=i4|2=$5$l$kB>$N\e(B
+\e$B%G%#%l%/%H%jJQ?t$O@5$7$/@_Dj$5$l$J$$$@$m$&$H$$$&$3$H$G$9!#$3$NJQ?t$OBe$o\e(B
+\e$B$j$K\e(B @file{.emacs} \e$B$G@_Dj$7$F$/$@$5$$!#\e(B
+
+@item gnus-default-directory
+@vindex gnus-default-directory
+\e$B>e5-$NJQ?t$K$OA4$/4X78$"$j$^$;$s\e(B --- \e$B$3$NJQ?t$OA4$F$N\e(B gnus \e$B%P%C%U%!!<$N\e(B
+\e$B%G%#%U%)%k%H%G%#%l%/%H%j!<$r$I$&$9$Y$-$+$r@_Dj$7$^$9!#$b\e(B
+\e$B$7\e(B @kbd{C-x C-f} \e$B$N$h$&$JL?Na$r<B9T$9$k$H!"8=:_$N%P%C%U%!!<$N%G%#%U%)%k\e(B
+\e$B%H%G%#%l%/%H%j!<$r5/E@$K$7$?%W%m%s%W%H$,=P$F$/$k$G$7$g$&!#\e(B
+
+\e$B$3$NJQ?t$,\e(B @code{nil} (\e$B$3$l$,=i4|@_DjCM\e(B) \e$B$G$"$l$P!"\e(Bgnus \e$B$r5/F0$7$?$H$-$K\e(B
+\e$B$"$J$?$,$$$?%P%C%U%!!<$N%G%#%U%)%k%H%G%#%l%/%H%j!<$,%G%#%U%)%k%H%G%#%l%/\e(B
+\e$B%H%j!<$K$J$k$G$7$g$&!#\e(B
+
+@item gnus-verbose
+@vindex gnus-verbose
+\e$B$3$NJQ?t$O\e(B 0 \e$B$+$i\e(B 10 \e$B$^$G4V$N@0?t$G$9!#Bg$-$$?t;z$[$I$?$/$5$s$N%a%C%;!<\e(B
+\e$B%8$,I=<($5$l$^$9!#$3$NJQ?t$,\e(B 0 \e$B$G$"$l$P\e(B gnus \e$B$O2?$N%a%C%;!<%8$b8+$;$^$;\e(B
+\e$B$s!#$3$l$,\e(B 7 (\e$B=i4|@_DjCM\e(B) \e$B$G$"$l$PFC$K=EMW$J%a%C%;!<%8$,I=<($5$l!"\e(B10 \e$B$G\e(B
+\e$B$"$l$P\e(B gnus \e$B$O7h$7$F$*C}$j$r;_$a$:!"$?$/$5$s$N%a%C%;!<%8$G$"$J$?$K$a$^$$\e(B
+\e$B$r5/$3$5$;$k$G$7$g$&!#\e(B
+
+@item gnus-verbose-backends
+@vindex gnus-verbose-backends
+\e$B$3$NJQ?t$O\e(B @code{gnus-verbose} \e$B$HF1MM$KF0:n$7$^$9$,!"\e(Bgnus \e$BK\BN$G$O$J\e(B
+\e$B$/\e(B gnus \e$B$N%P%C%/%(%s%I$KBP$7$FE,MQ$5$l$^$9!#\e(B
+
+@item nnheader-max-head-length
+@vindex nnheader-max-head-length
+\e$B%P%C%/%(%s%I$,5-;v$N%X%C%@!<$r$^$C$9$0FI$s$G$$$k$H$-$O!"$G$-$k8B$j>/$J$$\e(B
+\e$BNL$@$1$rFI$b$&$HEXNO$7$^$9!#$3$NJQ?t\e(B (\e$B=i4|@_DjCM\e(B 4096) \e$B$O!"%P%C%/%(%s%I\e(B
+\e$B$,%X%C%@!<$HK\J8$N4V$N6h@Z$j9T$r8+$D$1$k$^$G$KFI$_9~$b$&$H$9$k@dBP:GBgD9\e(B
+\e$B$r;XDj$7$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$l$P!"FI$_9~$_>e8B$O$"$j$^$;$s!#\e(B
+\e$B$b$7\e(B @code{t} \e$B$G$"$l$P!"%P%C%/%(%s%I$O5-;v$rItJ,ItJ,$GFI$_9~$b$&$H$O$;$:!"\e(B
+\e$B5-;vA4BN$rFI$_9~$_$^$9!#$3$l$O\e(B @code{ange-ftp} \e$B$d\e(B @code{efs} \e$B$N$"$k%P!<\e(B
+\e$B%8%g%s$G0UL#$r$b$A$^$9!#\e(B
+
+@item nnheader-head-chop-length
+@vindex nnheader-head-chop-length
+\e$B$3$NJQ?t\e(B (\e$B=i4|@_DjCM\e(B 2048) \e$B$O!"A05-$NA`:n$r9T$C$F$$$k$H$-$K!"$I$l$/$i$$\e(B
+\e$B$NBg$-$5$NC10L$G3F5-;v$rFI$_9~$`$+$r@_Dj$7$^$9!#\e(B
+
+@item nnheader-file-name-translation-alist
+@vindex nnheader-file-name-translation-alist
+@cindex file names
+@cindex invalid characters in file names
+@cindex characters in file names
+\e$B$3$l$O%U%!%$%kL>$NJ8;z$r$I$N$h$&$KJQ49$9$k$+$r;XDj$9$kO"A[%j%9%H$G$9!#Nc\e(B
+\e$B$($P!"$b$7\e(B @samp{:} \e$B$,$"$J$?$N%7%9%F%`$G$O%U%!%$%kL>$NJ8;z$H$7$F$O;H$($J\e(B
+\e$B$$>l9g\e(B (\e$B$"$J$?$O\e(B OS/2 \e$B%f!<%6$G$9\e(B)\e$B!"0J2<$N$h$&$K$9$k$3$H$,$G$-$^$9!#\e(B
+
+@lisp
+@group
+(setq nnheader-file-name-translation-alist
+      '((?: . ?_)))
+@end group
+@end lisp
+
+\e$B<B:]$K$O!"$3$l$O\e(B OS/2 \e$B$H\e(B (\e$B$/$=\e(B) MS Windows \e$B%7%9%F%`>e$G$N$3$NJQ?t$N=i4|\e(B
+\e$B@_DjCM$G$9!#\e(B
+
+@item gnus-hidden-properties
+@vindex gnus-hidden-properties
+\e$B$3$l$O\e(B ``\e$BIT2D;k\e(B'' \e$B%F%-%9%H$r1#$9$?$a$K;H$o$l$kB0@-$N%j%9%H$G$9!#$[$H$s$I\e(B
+\e$B$N%7%9%F%`$G$O=i4|@_DjCM$O\e(B @code{(invisible t intangible t)} \e$B$G!"$3$l$O\e(B
+\e$BIT2D;k%F%-%9%H$r8+$($J$/$7$F?($l$J$/$7$^$9!#\e(B
+
+@item gnus-parse-headers-hook
+@vindex gnus-parse-headers-hook
+\e$B%X%C%@!<$r2r<a$9$kA0$K8F$S=P$5$l$k%U%C%/!#$3$l$ONc$($P!"<hF@$7$?%X%C%@!<\e(B
+\e$B$NE}7W>pJs$r<h$k$H$+!"$"$k$$$O$"$k<o$N%X%C%@!<$r<h$j=|$/$3$H$K;H$&$3$H$,\e(B
+\e$B$G$-$^$9!#$^$"!";d$O2?$G$3$s$J$b$N$,M_$7$$$+$h$/$o$+$s$J$$$s$@$1$I$M!#\e(B
+
+@item gnus-shell-command-separator
+@vindex gnus-shell-command-separator
+\e$BFs$D$N%7%'%kL?Na$r6h@Z$k$N$K;HMQ$5$l$kJ8;zNs!#=i4|@_DjCM\e(B
+\e$B$O\e(B @samp{;} \e$B$G$9!#\e(B
+
+@item gnus-invalid-group-regexp
+@vindex gnus-invalid-group-regexp
+
+\e$B%f!<%6$K%0%k!<%WL>$r3NG'$9$k$H$-$K;H$&!"\e(B``\e$B;H$($J$$\e(B'' \e$B%0%k!<%WL>$K%^%C%A\e(B
+\e$B$9$k@55,I=8=$G$9!#4{DjCM$O\e(B gnus \e$B$NFbItF0:n\e(B (\e$BA*BrJ}K!$H%0%k!<%W$N6-3&$K!"\e(B
+\e$BDL>o\e(B @samp{:} \e$B$r;H$C$F$$$k\e(B) \e$B$r$a$A$c$a$A$c$K$7$F$7$^$&$+$b$7$l$J$$!"$$$/\e(B
+\e$B$D$+$N\e(B @strong{\e$BK\Ev$K\e(B} \e$B;H$($J$$%0%k!<%WL>$rJa$^$($^$9!#\e(B
+
+@acronym{IMAP} \e$B%f!<%6$O%0%k!<%WL>$K\e(B @samp{/} \e$B$r;H$$$?$$$H;W$&$G$7$g$&$1\e(B
+\e$B$l$I!#\e(B
+@end table
+
+@node The End
+@chapter \e$B=*$o$j\e(B
+
+\e$B$O$$!"0J>e$,%^%K%e%"%k$G$9\e(B---\e$B$"$J$?$O$b$&<+J,<+?H$N?M@8$rAw$k;v$,$G$-$^\e(B
+\e$B$9!#O"Mm$r$H$C$F2<$5$$!#$"$J$?$NG-$K:#F|$O!"$H$$$C$F$*$$$F2<$5$$!#\e(B
+
+\e$B$*$*!"\e(B@strong{\e$B?@$h\e(B}---\e$B$5$h$J$i$rBQ$($k;v$O$G$-$^$;$s!#\e(B(\e$B$9$9$j5c$-!#\e(B)
+
+Ol' Charles Reznikoff \e$B$O$=$l$rHs>o$K$h$/8=$7$F$$$^$9$N$G!"$3$3$OH`$N$?$a\e(B
+\e$B$K>y$j$^$9\e(B:
+
+@quotation
+@strong{Te Deum}
+
+@sp 1
+Not because of victories @*
+I sing,@*
+having none,@*
+but for the common sunshine,@*
+the breeze,@*
+the largess of the spring.
+
+@sp 1
+Not for victory@*
+but for the day's work done@*
+as well as I was able;@*
+not for a seat upon the dais@*
+but at the common table.@*
+@end quotation
+
+\e$B;nLu\e(B:
+
+@quotation
+@strong{Te Deum}
+
+@sp 1
+\e$B>!Mx$7$?$+$i$G$O$J$/\e(B @*
+\e$B;d$O2N$&\e(B @*
+\e$B2?$bL5$$$1$l$I\e(B @*
+\e$B$"$NF|8w$d\e(B @*
+\e$BB)?a$d\e(B @*
+\e$B=U$NBg$-$5$N$?$a$K\e(B @*
+
+@sp 1
+\e$B>!Mx$N$?$a$G$O$J$/\e(B @*
+\e$B0lF|$NO+F/$N$?$a$K\e(B @*
+\e$B$^$?!"$=$l$rC#@.$G$-$?$3$H$K\e(B @*
+\e$B9b:B$N>e$N@J$N$?$a$G$O$J$/\e(B @*
+\e$BIaDL$N%F!<%V%k$N$H$3$m$G\e(B @*
+@end quotation
+
+@node Appendices
+@chapter \e$BIUO?\e(B
+
+@menu
+* XEmacs::                      XEmacs \e$B$G%$%s%9%H!<%k$9$k$?$a$NMW7o\e(B
+* History::                     \e$B$I$&$d$C$F\e(B gnus \e$B$,:#F|$N$h$&$K$J$C$?$+\e(B
+* On Writing Manuals::          \e$B$J$<$3$l$,=i?4<TMQ$N0FFb$G$J$$$+\e(B
+* Terminology::                 \e$B2f!9$OK\Ev$KFq$7$$!"8l$N$h$&$J8l$r;H$&\e(B
+* Customization::               \e$B$"$J$?$NMW5a$K1h$C$F\e(B gnus \e$B$r;EN)$F$k\e(B
+* Troubleshooting::             \e$B>e<j$/9T$+$J$+$C$?$H$-$K;n$9$+$b$7$l$J$$$3$H\e(B
+* Gnus Reference Guide::        \e$B?'!9$J5;=QE*$J$b$N\e(B
+* Emacs for Heathens::          Emacs \e$B$NMQ8l$N<jC;$JF3F~\e(B
+* Frequently Asked Questions::  Gnus \e$B$N\e(B FAQ
+@end menu
+
+@node XEmacs
+@section XEmacs
+@cindex XEmacs
+@cindex installing under XEmacs
+
+XEmacs \e$B$O%Q%C%1!<%8$N=/=8$H$7$FG[I[$5$l$F$$$^$9!#\e(Bgnus \e$B$N\e(B XEmacs \e$B%Q%C%1!<\e(B
+\e$B%8$,I,MW$H$9$k$b$N$O2?$G$"$l!"$"$J$?$O%$%s%9%H!<%k$9$Y$-$G$9!#:#$N$H$3$m\e(B
+\e$BI,MW$J$N$O\e(B @samp{gnus}, @samp{mail-lib}, @samp{xemacs-base},
+@samp{eterm}, @samp{sh-script}, @samp{net-utils}, @samp{os-utils},
+@samp{dired}, @samp{mh-e}, @samp{sieve}, @samp{ps-print}, @samp{w3},
+@samp{pgg}, @samp{mailcrypt}, @samp{ecrypto} \e$B$*$h$S\e(B @samp{sasl} \e$B$G$9!#\e(B
+
+@node History
+@section \e$BNr;K\e(B
+
+@cindex history
+@sc{gnus} \e$B$OG_ED@/?.;a$K$h$C$F=q$+$l$^$7$?!#\e(B94\e$BG/$N2F$,G&$S4s$C$F$/$k$3\e(B
+\e$B$m!"\e(BLars Magne Ingebrigtsen \e$B$OK0$-$F$-$F!"\e(BGnus \e$B$r=q$-D>$=$&$H7h?4$7$^$7\e(B
+\e$B$?!#\e(B
+
+\e$B$3$NL5Ni$r9T$C$??MJ*$rD4$Y$F$_$?$$$N$J$i!"$"$J$?$N\e(B (\e$B$/$=\e(B!) \e$B%&%'%V%V%i%&\e(B
+\e$B%6!<$r\e(B @uref{http://quimby.gnus.org/} \e$B$K8~$1$k;v$,$G$-$^$9!#\e(B
+\e$B$3$l$O?7$7$/$F?h$JHG$N\e(B gnus \e$B$NBh0lG[I[>l=j$G!"\e(BNewsrc \e$B$r$V$C2u$7$F?M!9$r\e(B
+\e$B7cE\$5$l$k%5%$%H$H$7$FCN$i$l$F$$$^$9!#\e(B
+
+\e$B:G=i$N%"%k%U%!HG$N3+H/4|4V$K!"?7$7$$\e(B Gnus \e$B$O\e(B ``(ding) Gnus'' \e$B$H8F$P$l$F\e(B
+\e$B$$$^$7$?!#\e(B@dfn{(ding)} \e$B$O$b$A$m$s!"\e(B@dfn{ding is not Gnus} \e$B$NC;=L7A$G!"$3\e(B
+\e$B$l$OA4$/40A4$J13$G$9$,!"$@$l$,$=$s$J$3$H$r5$$K$9$k$G$7$g$&$+\e(B? (\e$B$H$3$m$G!"\e(B
+\e$B$3$NC;=L7A$N\e(B ``Gnus'' \e$B$O$*$=$i$/G_ED$5$s$N0U?^DL$j\e(B ``\e$B%K%e!<%9\e(B'' \e$B$HH/2;$5\e(B
+\e$B$l$k$Y$-$G!"$=$&$9$k$H$b$C$HE,@Z$JL>A0$K$J$j$^$9!#$=$&;W$$$^$;$s$+\e(B?)
+
+\e$B$I$A$i$K$;$h!"A4$F$N%(%M%k%.!<$r?7$7$$855$$NNI$$L>A0$rIU$1$k$N$K;H$$2L$?\e(B
+\e$B$7$?8e!"$=$NL>A0$O\e(B @emph{\e$B$"$^$j$K\e(B} \e$B855$$,NI$9$.$k$H$$$&;v$K$J$j!"$=$l\e(B
+\e$B$r\e(B ``Gnus'' \e$B$H:F$SL?L>$7$^$7$?!#$G$b!":#2s$OBgJ8;z$H>.J8;z$r:.$<$F$$$^$9!#\e(B
+``Gnus'' \e$B$H\e(B ``@sc{gnus}'' \e$B$G$9!#?7$7$$$b$N\e(B \e$B$H\e(B \e$B8E$$$b$N!#\e(B
+
+@menu
+* Gnus Versions::               \e$B$I$s$J%P!<%8%g%s$N\e(B Gnus \e$B$,%j%j!<%9$5$l$F$$$k$+\e(B
+* Other Gnus Versions::         \e$B%j%j!<%9$5$l$F$$$kB>$N%P!<%8%g%s$N\e(B Gnus
+* Why?::                        Gnus \e$B$NL\E*$O2?\e(B?
+* Compatibility::               Gnus \e$B$O\e(B @sc{gnus} \e$B$H$I$l$/$i$$8_49@-$,$"$k$N\e(B?
+* Conformity::                  Gnus \e$B$OA4$F$NI8=`$rK~$?$=$&$H$9$k\e(B
+* Emacsen::                     Gnus \e$B$O$$$/$D$+$N8=BeE*$J\e(B Emacs \e$B4D6-$G<B9T$G$-$k\e(B
+* Gnus Development::            Gnus \e$B$,3+H/$5$l$F$$$kJ}K!\e(B
+* Contributors::                \e$BBgNL$N?M!9\e(B
+* New Features::                Gnus \e$B$N?7$7$$;v$K4X$9$k<j$,$+$j\e(B
+@end menu
+
+@node Gnus Versions
+@subsection Gnus Versions
+@cindex ding Gnus
+@cindex September Gnus
+@cindex Red Gnus
+@cindex Quassia Gnus
+@cindex Pterodactyl Gnus
+@cindex Oort Gnus
+@cindex No Gnus
+@cindex Gnus versions
+
+\e$B:G=i$N\e(B ``\e$BE,@Z$J\e(B'' Gnus 5 \e$B$N%j%j!<%9$O\e(B 1995\e$BG/\e(B11\e$B7n$K\e(B Emacs 19.30 \e$B$NG[I[$K\e(B
+\e$B4^$^$l$?$H$-$K$J$5$l$^$7$?\e(B (132 \e$B$N\e(B (ding) Gnus \e$B$N%j%j!<%9\e(B \e$BB-$9$3$H\e(B
+\e$B$N\e(B Gnus5.0 \e$B$N\e(B 15 \e$B%j%j!<%9\e(B)\e$B!#\e(B
+
+1996\e$BG/\e(B3\e$B7n$K<!$N@$Be$N\e(B Gnus (\e$BJLL>\e(B ``September Gnus'' (99 \e$B%j%j!<%9$N8e\e(B
+\e$B$G\e(B)) \e$B$,\e(B ''Gnus 5.2`` \e$B$H$$$&L>A0$G%j%j!<%9$5$l$^$7$?\e(B (40 \e$B%j%j!<%9\e(B)\e$B!#\e(B
+
+1996\e$BG/$N\e(B 7\e$B7n\e(B28\e$BF|$K\e(B Red Gnus \e$B$N:n6H$,;O$^$j!"$=$l$O\e(B 1997\e$BG/\e(B1\e$B7n\e(B25\e$BF|\e(B
+\e$B$K\e(B (84 \e$B%j%j!<%9$N8e$G\e(B) ``Gnus 5.4'' \e$B$H$7$F%j%j!<%9$5$l$^$7$?\e(B (67 \e$B%j%j!<\e(B
+\e$B%9\e(B)\e$B!#\e(B
+
+1997\e$BG/\e(B9\e$B7n\e(B13\e$BF|$K!"\e(BQuassia Gnus \e$B$,3+;O$5$l!"\e(B37 \e$B%j%j!<%9B3$-$^$7$?!#$=$l\e(B
+\e$B$O\e(B ``Gnus 5.6'' \e$B$H$7$F\e(B 1998\e$BG/\e(B3\e$B7n\e(B8\e$BF|$K%j%j!<%9$5$l$^$7$?\e(B (46 \e$B%j%j!<%9\e(B)\e$B!#\e(B
+
+1998\e$BG/\e(B8\e$B7n\e(B29\e$BF|$K\e(B Gnus 5.6 \e$B$+$i\e(B Pterodactyl Gnus \e$B$,@8$^$l!"\e(B1999\e$BG/\e(B12\e$B7n\e(B3\e$BF|\e(B
+\e$B$K\e(B (99 \e$B%j%j!<%9$H\e(B CVS \e$B%j%]%8%H%j$G$N:n6H$N8e\e(B) ``Gnus 5.8'' \e$B$H$7$F%j%j!<\e(B
+\e$B%9$5$l$^$7$?!#\e(B
+
+2000\e$BG/\e(B10\e$B7n\e(B26\e$BF|$K\e(B Oort Gnus \e$B$,3+;O$5$l$^$7$?!#\e(B
+
+\e$B$b$7@\F,<-$r;}$C$?HG$N\e(B Gnus -- ``(ding) Gnus'', ``September Gnus'',
+``Red Gnus'', ``Quassia Gnus'', ``Pterodactyl Gnus'', ``Oort Gnus''
+-- \e$B$K=P2q$C$F$b!":.Mp$7$J$$$G$/$@$5$$!#$"$J$?$,62$,$C$F$$$k;v$rCN$i$l$F\e(B
+\e$B$O$$$1$^$;$s!#8e$m$K2<$,$j$J$5$$!#$f$C$/$j$H!#B>$K2?$r$7$F$b!"Av$C$F$O$$\e(B
+\e$B$1$^$;$s!#$=$l$,FO$+$/$J$k$^$G!"@E$+$KJb$-5n$j$J$5$$!#E,@Z$K%j%j!<%9$5$l\e(B
+\e$B$?HG$N\e(B Gnus \e$B$r8+$D$1$F!"Be$o$j$K$=$l$K4s$jE:$C$F2<$5$$!#\e(B
+
+@node Other Gnus Versions
+@subsection \e$BB>$N\e(B gnus \e$B$N%P!<%8%g%s\e(B
+@cindex Semi-gnus
+
+Lars \e$B$5$s$,D4@=$7$F%j%j!<%9$7$?\e(B Gnus \e$B$K2C$($F!"F|K\$G$O\e(B Semi-gnus \e$B$N3+H/\e(B
+\e$B$,9T$J$o$l$F$$$^$9!#$3$l$O\e(B @acronym{SEMI} \e$B$H$$$&\e(B @acronym{MIME} \e$B$N5!G=$r\e(B
+\e$B<B8=$9$k$?$a$N%i%$%V%i%j$r;H$&$3$H$rA0Ds$H$7$F$$$^$9!#\e(B
+
+\e$B$3$l$i$N\e(B gnus \e$B$O\e(B Gnus 5.6 \e$B$H\e(B Pterodactyl Gnus \e$B$r85$K$7$F$$$^$9!#$=$l$i\e(B
+\e$B$O\e(B ``Semi-gnus'' \e$B$HAm>N$5$l!"\e(BT-gnus, Nana-gnus \e$B$*$h$S\e(B Chaos \e$B$N0[$J$C$?7O\e(B
+\e$BE}$,$"$j$^$9!#$3$l$i$O6/NO$J\e(B @acronym{MIME} \e$B$N5!G=$H3F9q8lBP1~$N5!G=$rDs\e(B
+\e$B6!$9$k$b$N$G!"FC$KF|K\?M$N%f!<%6$K$H$C$FBg;v$J$b$N$G$9!#\e(B
+
+@node Why?
+@subsection \e$B$J$<\e(B?
+
+Gnus \e$B$NL\E*$O2?$G$9$+\e(B?
+
+\e$B;d$O!"$"$J$?$N9M$(IU$/;v$rA4$F$G$-$k\e(B ``\e$B$9$P$i$7$$\e(B'' ``\e$B$+$C$3$$$$\e(B'' ``\e$B$$\e(B
+\e$B$+$9\e(B'' ``\e$B$O$d$j$N\e(B'' \e$B%K%e!<%9%j!<%@$rDs6!$7$?$$$H;W$$$^$9!#$3$l$O;d$NBg85\e(B
+\e$B$NF05!$G$9$,!"\e(BGnus \e$B$N:n6H$r$7$F$$$k4V$K!"$3$N@$Be$N%K%e!<%9%j!<%@!<$OK\\e(B
+\e$BEv$K@P4o;~Be$KB0$7$F$$$k$H$$$&;v$,L@$i$+$K$J$j$^$7$?!#%K%e!<%9%j!<%@!<$O!"\e(B
+\e$B%$%s%?!<%M%C%H$NMD;y4|$+$i$[$H$s$IH/E8$7$F$$$^$;$s$G$7$?!#$b$78=:_$NA}2C\e(B
+\e$BN($GNL$,A}2C$7$D$E$1$l$P!"A4$F$N8=:_$N%K%e!<%9%j!<%@!<$OA4$/Lr$KN)$?$J$/\e(B
+\e$B$J$k$G$7$g$&!#0lF|$K\e(B 1000 \e$B$d$b$C$H$?$/$5$s$N?7$7$$5-;v$N$"$k%K%e!<%9%0%k!<\e(B
+\e$B%W$r07$&$K$O$I$&$9$l$PNI$$$N$G$7$g$&\e(B? \e$BEj9F$r$9$kI4K|$d$=$l$h$jB?$$?M!9$K\e(B
+\e$BCY$l$J$$$h$&$KIU$$$F$$$/$K$O$I$&$9$l$PNI$$$N$G$7$g$&\e(B?
+
+Gnus \e$B$O$3$l$i$N<ALd$KK\Ev$N2r7h$rDs0F$7$^$9$,!";d$O\e(B Gnus \e$B$,%K%e!<%9$rFI\e(B
+\e$B$_!"<hF@$9$k$?$a$N?7$7$$J}K!$r<B83$9$k>l$H$7$F;H$o$l$FM_$7$$$G$9!#G_ED$5\e(B
+\e$B$s$N%K%e!<%9%j!<%@!<$r%P%C%/%(%s%I$+$iJ,N%$9$k$H$$$&8-L@$JJ}?K$r3HD%$9$k\e(B
+\e$B;v$K$h$C$F!"\e(BGnus \e$B$O%a!<%k$r<hF@$7$?$j!"0c$C$?$H$3$m$+$i%K%e!<%9$r<hF@$9\e(B
+\e$B$k$?$a$N?7$7$$%P%C%/%(%s%I$r=q$-$?$$?M$N$?$a$K!"4JC1$GC1=c$J%$%s%?!<%U%'!<\e(B
+\e$B%9$rDs6!$7$F$$$^$9!#;d$O!"Lr$KN)$D$G$"$m$&$H$$$&ItJ,$K$9$Y$F!"%+%9%?%^%$\e(B
+\e$B%:$N$?$a$N%U%C%/$r2C$($^$7$?!#$=$l$r$9$k;v$K$h$C$F!"C58!$7!"H/L@$7$?$$A4\e(B
+\e$B$F$N?M$r>7$$$F$$$k$N$G$9!#\e(B
+
+\e$B$*$=$i$/\e(B Gnus \e$B$O40@.$9$k;v$O$J$$$N$+$b$7$l$^$;$s!#\e(B
+@kbd{C-u 100 M-x all-hail-emacs} \e$B$H\e(B @kbd{C-u 100 M-x all-hail-xemacs} \e$B$G\e(B
+\e$B$9!#\e(B
+
+@node Compatibility
+@subsection \e$B8_49@-\e(B
+
+@cindex compatibility
+Gnus \e$B$O\e(B @sc{gnus} \e$B$H40A4$K8_49@-$,$"$k$h$&$K@_7W$5$l$F$$$^$9!#$[$H$s$IA4\e(B
+\e$B$F$N%-!<%P%$%s%G%#%s%0$O$=$N$^$^;D$C$F$$$^$9!#$b$A$m$s!"B?$/$N%-!<%P%$%s\e(B
+\e$B%G%#%s%0$,DI2C$5$l$^$7$?$,!"0l$D$+Fs$D$N$"$$$^$$$J>l9g$r=|$$$F!"8E$$%P%$\e(B
+\e$B%s%G%#%s%0$,JQ99$5$l$?;v$O$"$j$^$;$s!#\e(B
+
+\e$B2f!9$N%b%C%H!<$O\e(B:
+@quotation
+@cartouche
+@center \e$B9]E4$N9|AH$_$N6u9b$/!#\e(B
+@end cartouche
+@end quotation
+\e$B$G$9!#\e(B
+
+\e$BA4$F$NL?Na$O$=$NL>A0$,JQ$o$C$F$$$^$;$s!#$$$/$D$+$NFbIt4X?t$OL>A0$rJQ$($^\e(B
+\e$B$7$?!#\e(B
+
+@code{gnus-uu} \e$B%Q%C%1!<%8$O7`E*$KJQ2=$7$F$$$^$9!#\e(B@xref{Decoding
+Articles}.
+
+\e$B0l$D$N<gMW$J8_49@-$N<ALd$O!"$$$/$D$+$N35N,%P%C%U%!$,B8:_$9$k;v$G$9!#A4$F\e(B
+\e$B$N%0%k!<%W$rFI$_9~$`$H$-$K4XO"$9$kJQ?t$O$=$l$,B0$9$k35N,%P%C%U%!$N%P%C%U%!\e(B
+\e$B8GM-$G$9!#B?$/$N=EMW$JJQ?t$O$=$l$NA4BN$NHG$K$bJ#@=$5$l$^$9$,!"35N,%P%C%U%!\e(B
+\e$B$GL?Na$,<B9T$5$l$k$H!"$3$NJQ99$O!"$"$J$?$,Cm0U$7$F$$$J$$$H!"@5$7$/$J$$CM\e(B
+\e$B$K$J$k$+$bCN$l$^$;$s!#\e(B
+
+@sc{gnus} \e$B$NFbIt$NCN<1$K0MB8$7$?A4$F$N%3!<%I$O<B9T$G$-$J$$$G$7$g$&!#Fs$D\e(B
+\e$BNc$r5s$2$^$9\e(B: @code{gnus-newsrc-alist} \e$B$NJB$SBX$(\e(B (\e$B$b$7$/$O!"<B:]$O2?$i\e(B
+\e$B$+$NJ}K!$G$=$l$rJQ99$9$k;v\e(B) \e$B$O@dBP$K6X;_$5$l$F$$$^$9!#\e(BGnus \e$B$O$3$NO"A[%j\e(B
+\e$B%9%H$NEPO?$r;X$7<($9%O%C%7%e%F!<%V%k$rJ];}$7$F$*$j\e(B (\e$B$=$l$OB?$/$N4X?t$NB.\e(B
+\e$BEY$r>e$2$^$9\e(B)\e$B!"D>@\O"A[%j%9%H$rJQ99$9$k;v$O0[>o$J7k2L$r$b$?$i$9$G$7$g$&!#\e(B
+
+@cindex hilit19
+@cindex highlighting
+\e$B8E$$\e(B hilit19 \e$B$N%3!<%I$OA4$/F0:n$7$^$;$s!#<B:]$N$H$3$m!"$*$=$i$/A4$F\e(B
+\e$B$N\e(B hilit \e$B%3!<%I$rA4$F$N\e(B Gnus \e$B$N%U%C\e(B
+\e$B%/\e(B (@code{gnus-group-prepare-hook} \e$B$H\e(B @code{gnus-summary-prepare-hook}) \e$B$+\e(B
+\e$B$i<h$j=|$/$Y$-$G$7$g$&!#\e(BGnus \e$B$O%O%$%i%$%H$N$?$a$N$$$m$$$m$JE}9g$5$l$?4X\e(B
+\e$B?t$rDs6!$7$^$9!#$3$l$i$O$b$C$HB.$/$b$C$H@53N$G$9!#A4$F$N?M$N?M@8$r3Z$K$9\e(B
+\e$B$k$?$a$K!"\e(BGnus \e$B$O=i4|@_Dj$GA4$F$N\e(B hilit \e$B%U%C%/$+$iA4$F$N\e(B hilit \e$B8F$S=P$7\e(B
+\e$B$r<h$j=|$-$^$9!#$-$?$J$$$b$N\e(B! \e$B$H$s$G$1\e(B!
+
+@code{expire-kill} \e$B$N$h$&$J%Q%C%1!<%8$O$b$&F0:n$7$^$;$s!#<B:]!"\e(BGnus \e$B$r;H\e(B
+\e$B$$;O$a$?$H$-$K$O!"$*$=$i$/A4$F$N8E$$\e(B @sc{gnus} \e$B%Q%C%1!<%8\e(B (\e$B$HB>$N%3!<\e(B
+\e$B%I\e(B) \e$B$r>C5n$9$k$Y$-$G$7$g$&!#\e(B@sc{gnus} \e$B$K<B9T$5$;$k$?$a$K=q$$$?%3!<%I$O!"\e(B
+Gnus \e$B$,4{$K<B9T$7$F$$$k$H$$$&;v$ONI$/$"$k;v$G$9!#\e(B(\e$B$/$9$/$9!#\e(B)
+
+\e$BJ*;v$r<B9T$9$k8E$$J}K!$O$^$@;HMQ$G$-$^$9$,!"?7$7$$J}K!$@$1$,$3$N%^%K%e%"\e(B
+\e$B%k$K5-:\$5$l$F$$$^$9!#$b$7$3$N%^%K%e%"%k$rFI$s$G$$$k4V$K2?$+$r$9$k?7$7$$\e(B
+\e$BJ}K!$rH/8+$7$F$b!"8E$$J}K!$r;_$a$J$1$l$P$J$i$J$$$H$$$&;v$G$O$"$j$^$;$s!#\e(B
+
+Gnus \e$B$OA4$F$N\e(B @sc{gnus} \e$B5/F0%U%!%$%k$rM}2r$7$^$9!#\e(B
+
+@kindex M-x gnus-bug
+@findex gnus-bug
+@cindex reporting bugs
+@cindex bugs
+\e$BA4BN$H$7$F!"\e(B@sc{gnus} \e$B$NFbIt$K0MB8$7$?%3!<%I$r$[$H$s$I=q$$$F$$$J$$IaDL$N\e(B
+\e$BMxMQ<T$OLdBj$K6l$7$`;v$O$J$$$G$7$g$&!#LdBj$,5/$3$l$P!"KbK!$NL?\e(B
+\e$BNa\e(B @kbd{M-x gnus-bug} \e$B$r<B9T$9$k;v$K$h$C$F;d$KCN$i$;$F2<$5$$!#\e(B
+
+@vindex gnus-bug-create-help-buffer
+@emph{\e$BHs>o$K\e(B} \e$B$h$/%P%0Js9p$rAw$kJJ$,$"$k$N$G$"$l$P!"$7$P$i$/$9$k$HLr$KN)\e(B
+\e$B$D\e(B help \e$B%P%C%U%!$,$&$k$5$$$H46$8$k$+$b$7$l$^$;$s!#$=$&$G$"$l$P!"$=$l$,I=\e(B
+\e$B<($5$l$k$N$rHr$1$k$?$a$K!"\e(B
+@code{gnus-bug-create-help-buffer} \e$B$r\e(B @code{nil} \e$B$K@_Dj$7$F2<$5$$!#\e(B
+
+@node Conformity
+@subsection \e$B0lCW@-\e(B
+
+\e$B$3$l$O!"M}M3L5$-H?93!"$8$c$J$$$G$9$h!"1|$5$s!#2f!9$OA4$F$NCN$i$l$F$$$kI8\e(B
+\e$B=`$K1h$C$F$$$^$9!#$b$A$m$s!"2f!9$,;?@.$G$-$J$$I8=`$H\e(B/\e$B$b$7$/$O=,47$O=|$-\e(B
+\e$B$^$9$,!#\e(B
+
+@table @strong
+@item RFC (2)822
+@cindex RFC 822
+@cindex RFC 2822
+\e$B$3$NI8=`$X$NCN$i$l$F$$$k0cH?$O$"$j$^$;$s!#\e(B
+
+@item RFC 1036
+@cindex RFC 1036
+\e$B$3$NI8=`$bCN$i$l$F$$$k0cH?$O$"$j$^$;$s!#\e(B
+
+@item Son-of RFC 1036
+@cindex Son-of RFC 1036
+\e$B$3$l$K$O$$$/$D$+$N0cH?$,$"$j$^$9!#\e(B
+
+@table @emph
+@item X-Newsreader
+@item User-Agent
+\e$B$3$l$O\e(B ``\e$B$D$^$i$J$$%X%C%@!<\e(B'' \e$B$H9M$($i$l$F$$$^$9$,!";d$O>CHq<T$N>pJs$G$"\e(B
+\e$B$k$H8+$J$7$F$$$^$9!#\e(B@code{tin} \e$B$H\e(B @code{Netscape} \e$B$+$iAw$i$l$F$/$kHs>o$K\e(B
+\e$BB?$/$NMM<0$K1h$C$F$$$J$$5-;v$r8+$?8e$G!";d$O$=$l$i$r5-;v$rEj9F$9$k$?$a$K\e(B
+\e$B$O;H$o$J$$J}$,NI$$$H$$$&;v$rCN$j$^$7$?!#$b$7\e(B @code{X-Newsreader} \e$B%X%C%@!<\e(B
+\e$B$,L5$1$l$P;d$O$=$N>pJs$rF@$k;v$O$J$+$C$?$G$7$g$&!#\e(B
+@end table
+
+@item USEFOR
+@cindex USEFOR
+USEFOR \e$B$O!"\e(BIETF \e$B$N\e(B working group \e$B$,\e(B Son-of-RFC 1036 \e$B$K4p$E$$$F!"\e(B
+RFC 1036 \e$B$N8e7Q$H$7$F=q$$$F$$$k$b$N$G$9!#%K%e!<%95-;v$NMM<0$KBP$7$F!"$$\e(B
+\e$B$m$$$m$JJQ99$rDs0F$7$?\e(B draft \e$B$r:n@.$7$^$7$?!#\e(BGnus \e$B%?%o!<\e(B
+\e$B$O\e(B draft \e$B$,\e(B RFC \e$B$H$7$FG'$a$i$l$?$H$-$KJQ99$N<BAu$rD4$Y$k$3$H$K$J$k$G$7$g\e(B
+\e$B$&!#\e(B
+
+@item MIME - RFC 2045-2049 etc
+@cindex @acronym{MIME}
+@acronym{MIME} \e$B4XO"$N$9$Y$F$N\e(B RFC \e$B$,%5%]!<%H$5$l$F$$$^$9!#\e(B
+
+@item Disposition Notifications - RFC 2298
+Message Mode \e$B$O<u?.<T$K3+Iu3NG'$rMW5a$9$k$3$H$,$G$-$^$9!#\e(B
+
+@ignore
+@item PGP - RFC 1991 and RFC 2440
+@cindex RFC 1991
+@cindex RFC 2440
+RFC 1991 is the original @acronym{PGP} message specification,
+published as an informational RFC.  RFC 2440 was the follow-up, now
+called Open PGP, and put on the Standards Track.  Both document a
+non-@acronym{MIME} aware @acronym{PGP} format.  Gnus supports both
+encoding (signing and encryption) and decoding (verification and
+decryption).
+
+@item PGP/MIME - RFC 2015/3156
+RFC 2015 (superseded by 3156 which references RFC 2440 instead of RFC
+1991) describes the @acronym{MIME}-wrapping around the RF 1991/2440 format.
+Gnus supports both encoding and decoding.
+
+@item S/MIME - RFC 2633
+RFC 2633 describes the @acronym{S/MIME} format.
+
+@end ignore
+
+@item IMAP - RFC 1730/2060, RFC 2195, RFC 2086, RFC 2359, RFC 2595, RFC 1731
+RFC 1730 \e$B$O\e(B @acronym{IMAP} \e$B%P!<%8%g%s\e(B 4 \e$B$G!"\e(BRFC 2060 (@acronym{IMAP}
+4 \e$B2~Dj\e(B 1) \e$B$GB?>/99?7$5$l$F$$$^$9!#\e(B
+RFC 2195 \e$B$O\e(B @acronym{IMAP} \e$B$N\e(B CRAM-MD5 \e$BG'>Z$K$D$$$F=R$Y$F$$$^$9!#\e(B
+RFC 2086 \e$B$O\e(B @acronym{IMAP} \e$B$N;HMQ@)8B0lMw\e(B (ACL) \e$B$K$D$$$F=R$Y$F$$$^$9!#\e(B
+RFC 2359 \e$B$O\e(B @acronym{IMAP} \e$B$N%W%m%H%3%k$N3HD%$K$D$$$F=R$Y$F$$$^$9!#\e(B
+RFC 2595 \e$B$O\e(B @acronym{IMAP} \e$B$K$*$1$kE,@Z$J\e(B @acronym{TLS} \e$B$NE}\e(B
+\e$B9g\e(B (STARTTLS) \e$B$K$D$$$F=R$Y$F$$$^$9!#\e(B
+RFC 1731 \e$B$O\e(B @acronym{IMAP} \e$B$N\e(B GSSAPI/Kerberos4 \e$B$N<jK!$K$D$$$F=R$Y$F$$$^\e(B
+\e$B$9!#\e(B
+@end table
+
+\e$B>e$K=q$+$l$F$$$kJ8>O$K4X$9$k;v$G!"\e(BGnus \e$B$,$=$l$rK~$?$7$F$$$J$$$h$&$JF0:n\e(B
+\e$B$r$7$F$$$k;v$K5$IU$$$?$i!"$?$a$i$o$:$K\e(B Gnus \e$B%?%o!<$H2f!9$KCN$i$;$F2<$5$$!#\e(B
+
+@node Emacsen
+@subsection Emacsen
+@cindex Emacsen
+@cindex XEmacs
+@cindex Mule
+@cindex Emacs
+
+T-gnus \e$B$O0J2<$N$b$N$GF0:n$7$^$9\e(B:
+
+@itemize @bullet
+
+@item
+Emacs 19.34 \e$B$H$=$l0J>e$N\e(B Mule \e$B5!G=IU$-!#\e(B
+
+@item
+XEmacs 21.1.1 \e$B0J>e$N\e(B Mule \e$B5!G=IU$-\e(B
+
+@item
+Meadow 1.00 \e$B0J>e!#\e(B(Mule for Windows \e$B$G$OF0$-$^$;$s!#\e(B)
+@end itemize
+
+\e$B$3$N\e(B Gnus \e$B$NHG$O$3$l$h$j8E$$$I$s$J\e(B Emacsen \e$B$G$b40A4$KF0:n$7$J$$$G$7$g$&!#\e(B
+\e$B>/$J$/$H$b!"?.Mj$G$-$kF0:n$O$7$J$$$G$7$g$&!#8E$$HG$N\e(B gnus \e$B$O8E\e(B
+\e$B$$\e(B Emacs \e$B$NHG$G$bF0:n$9$k$G$7$g$&!#$H$O8@$&$b$N$N!"\e(BT-gnus \e$B$O%P!<%8%g\e(B
+\e$B%s\e(B 21.1.1 \e$BL$K~$N\e(B XEmacs, \e$BNc$($P\e(B 20.4 \e$B$G$b;H$($k$+$b$7$l$^$;$s!#>\$7$$$3\e(B
+\e$B$H$O\e(B T-gnus \e$B$NG[I[$K4^$^$l$F$$$k\e(B README \e$B%U%!%$%k$rFI$s$G2<$5$$!#\e(B
+
+\e$B$$$m$$$m$J%W%i%C%H%U%)!<%`$N\e(B Gnus \e$B$N4V$K$O$$$/$D$+$NGyA3$H$7$?0c$$$,$"$j\e(B
+\e$B$^$9\e(B---XEmacs \e$B$O$b$C$H2hA|5!G=\e(B (\e$B%m%4$H%D!<%k%P!<\e(B) \e$B$rFCD'$K$7$F$$$^$9\e(B--\e$B$7\e(B
+\e$B$+$7!"$=$NB>$O!"A4$F$N\e(B Emacsen \e$B$G$[$H$s$IF1$8$O$:$G$9!#\e(B
+
+@node Gnus Development
+@subsection Gnus \e$B$N3+H/\e(B
+
+Gnus \e$B$OFs$D$NCJ3,$N=[4D$G3+H/$5$l$F$$$^$9!#:G=i$NCJ3,\e(B
+\e$B$O\e(B @samp{ding@@gnus.org} \e$B$G$N$?$/$5$s$N5DO@$,$"$j!"$=$3$GJQ99$d?7$7$$5!\e(B
+\e$BG=$rDs0F$7$^$9!#$3$NCJ3,$O\e(B @dfn{\e$B%"%k%U%!\e(B} \e$BCJ3,$H8F$P$l$^$9!#$H$$$&$N$O!"\e(B
+\e$B$3$NCJ3,$G%j%j!<%9$5$l$?\e(B Gnusae \e$B$O\e(B @dfn{\e$B%"%k%U%!%j%j!<%9\e(B} \e$B$b$7$/$O\e(B (\e$BB>\e(B
+\e$B$NCDBN$G$O$h$jNI$/;H$o$l$k\e(B) @dfn{\e$B%9%J%C%W%7%g%C%H\e(B} \e$B$H8F$P$l$k$b$N$@$+$i\e(B
+\e$B$G$9!#$3$NCJ3,$G$O!"\e(Bgnus \e$B$OIT0BDj$G$"$k$H9M$($i$l$F$*$j!"0lHL$NMxMQ<T$K\e(B
+\e$B$h$C$F;H$o$l$k$b$N$G$O$"$j$^$;$s!#\e(BGnus \e$B%"%k%U%!%j%j!<%9\e(B
+\e$B$O\e(B ``Red Gnus'' \e$B$d\e(B ``Quassia Gnus'' \e$B$N$h$&$JL>A0$K$J$C$F$$$^$9!#\e(B
+
+50-100 \e$B$/$i$$$N%j%j!<%9$N8e$G!"\e(BGnus \e$B$O\e(B @dfn{\e$BE`7k\e(B} \e$B$5$l$?$H@k8@$5$l!"%P%0\e(B
+\e$B=$@5$N$_$,E,MQ$5$l$^$9!#\e(BGnus \e$B$O@\F,<-$,<h$l!"$=$NBe$o$j\e(B
+\e$B$K\e(B ``Gnus 5.6.32'' \e$B$N$h$&$K8F$P$l$^$9!#$3$l$iIaDL$N?M$,;H$&$3$H$N$G$-$k\e(B
+\e$B$b$N$H9M$($i$l!"<g$K\e(B @samp{gnu.emacs.gnus} \e$B%K%e!<%9%0%k!<%W$G5DO@$5$l$F\e(B
+\e$B$$$^$9!#\e(B
+
+@cindex Incoming*
+@vindex mail-source-delete-incoming
+\e$B%"%k%U%!\e(B Gnusae \e$B$H%j%j!<%9$5$l$?\e(B Gnusae \e$B$G$OJQ?t$N=i4|CM$,0c$&$b$N$,$"$j\e(B
+\e$B$^$9!#FC$K!"\e(B@code{mail-source-delete-incoming} \e$B$O%"%k%U%!\e(B gnusae \e$B$G\e(B
+\e$B$O\e(B @code{nil} \e$B$G!"%j%j!<%9$5$l$?\e(B gnusae \e$B$G$O\e(B @code{t} \e$B$G$9!#$3$l$O%a!<%k\e(B
+\e$B$r07$C$F$$$k:]$K!"%"%k%U%!%j%j!<%9$Nsrsw$K$h$j%a!<%k$r<:$J$&$3$H$rHr$1$k\e(B
+\e$B$?$a$G$9!#\e(B
+
+ding \e$B%a!<%j%s%0%j%9%H$H\e(B Gnus \e$B%K%e!<%9%0%k!<%W$K$*$1$k5DO@$NJ,N%$O=c?h$K\e(B
+\e$B8x=0$N4X?4$K$h$C$F$J$5$l$F$$$k$o$1$G$O$"$j$^$;$s!#%"%k%U%!\e(B Gnus \e$B%j%j!<%9\e(B
+\e$B$,\e(B (\e$B$H$-$I$-\e(B) \e$B$9$k$+$b$7$l$J$$62$m$7$$$3$H$r8x=0$N>l$G=q$/$N$O!"3'$r62$l\e(B
+\e$B$5$;$k$H$$$&$N$b;v<B$G$9$,!"$b$C$H=EMW$J$3$H$O!"F3F~$5$l$??7$7$$<B83E*$J\e(B
+\e$B5!G=$K$D$$$FOC$9$3$H$O0lHL$N;HMQ<T$r:.Mp$5$;$k2DG=@-$,$"$j$^$9!#?7$7$$5!\e(B
+\e$BG=$OIQHK$KF3F~$5$l!"$$$8$/$i$l!"IT==J,$G$"$k$HH=CG$5$l!"$=$&$9$k$H<N$F$i\e(B
+\e$B$l$k$+!"40A4$K=q$-49$($i$l$k$+$N$I$A$i$+$G$9!#%a!<%j%s%0%j%9%H$rFI$s$G$$\e(B
+\e$B$k?M$OIaDL$O$3$NB.$$JQ99$KIU$$$F$$$-$^$9$,!"%K%e!<%9%0%k!<%W$N?M$b$=$&$G\e(B
+\e$B$"$k$H$_$J$9$3$H$O$G$-$^$;$s!#\e(B
+
+@node Contributors
+@subsection \e$B9W8%<T\e(B
+@cindex contributors
+
+\e$B?7$7$$\e(B Gnus \e$B$NHG$O\e(B (ding) \e$B%a!<%j%s%0%j%9%H$NA4$F$N?M$N=u$1$,L5$1$l$P$G$-\e(B
+\e$B$J$+$C$?$G$7$g$&!#0lG/0J>e!";d$OKhF|$H$F$b$?$/$5$s$NAGE($J%P%0%l%]!<%H$r\e(B
+\e$B<u$1<h$j!"$=$N$=$l$>$l$,;d$r4n$S$GK~$?$7$^$7$?!#0&Io!#$3$N%j%9%H$N?M!9$O\e(B
+\e$BG&BQ$rD6$($F;d$N\e(B ``\e$B$"$!!"$=$l$O$9$P$i$7$$9M$($@\e(B <type type>\e$B!"$&$s!";d$O\e(B
+\e$BBT$?$:$K$=$l$r$9$0%j%j!<%9$7$h$&\e(B <ship off>\e$B!"$=$l$OA4$/F0:n$7$J$$\e(B <type
+type>\e$B!"$&$s!";d$O$9$0$K=P$=$&\e(B <ship off> \e$B$$$d!"E;$&!"$=$l$OA4$/F0:n$7$J\e(B
+\e$B$$$>\e(B''' \e$B$H$$$&%j%j!<%9$K4X$9$k<g5A$rJQ$($F;n$7$F$-$??M!9$G$9!#\e(B
+Micro$oft---\e$B$"$!!#%"%^%A%e%"!#;d$O\e(B @emph{\e$B$b$C$H\e(B} \e$B0-$$!#\e(B(\e$B$b$7$/$O!"\e(B
+``\e$B$h$j0-$$\e(B''? ``\e$B$b$C$H0-$$\e(B''? ``\e$B:G0-\e(B''?)
+
+\e$B;d$O$3$N5!2q$K$3$N3X2q$K\e(B@dots{} \e$B$*$*$C$H!"0c$C$?!#\e(B
+
+@itemize @bullet
+
+@item
+\e$BG_ED@/?.\e(B---\e$B85$N\e(B @sc{gnus} \e$B$r=q$$$??M$G$9!#\e(B
+
+@item
+Shenghuo Zhu---uudecode.el, mm-uu.el, rfc1843.el, webmail.el,
+nnwarchive \e$B$H\e(B @acronym{MIME} \e$B$HB>$N7A<0$NId9f2=\e(B/\e$BI|9f2=$d%P%0=$@5!"?7$7$$\e(B
+\e$B5!G=$J$I$N$[$s$H$&$KB?$/$N$b$N!#\e(B
+
+@item
+Per Abrahamsen--custom\e$B!"%9%3%"!"%O%$%i%$%H$H\e(B @sc{soup} \e$B%3!<%I\e(B (\e$BB>$NB?$/\e(B
+\e$B$N;v$H6&$K\e(B)\e$B!#\e(B
+
+@item
+Luis Fernandes---\e$B%G%6%$%s$H%0%i%U%#%C%/!#\e(B
+
+@item
+Joe Reiss---\e$B%9%^%$%j!<$N4i$N:n<T!#\e(B
+
+@item
+Justin Sheehy---@acronym{FAQ} \e$B$N%a%$%s%F%$%J!<!#\e(B
+
+@item
+Erik Naggum---\e$B1g=u!"9M$(!"%5%]!<%H!"%3!<%I$H$=$NB>!#\e(B
+
+@item
+Wes Hardaker---@file{gnus-picon.el} \e$B$H\e(B @dfn{picon} \e$B$NItJ,$N%^%K%e%"\e(B
+\e$B%k\e(B (@pxref{Picons})\e$B!#\e(B
+
+@item
+Kim-Minh Kaplan---picon \e$B%3!<%I$KCV$1$k99$J$k:n6H!#\e(B
+
+@item
+Brad Miller---@file{gnus-gl.el} \e$B$H\e(B Grouplens \e$B$NItJ,$N%^%K%e%"\e(B
+\e$B%k\e(B (@pxref{GroupLens})\e$B!#\e(B
+
+@item
+Sudish Joseph---\e$B?t$(@Z$l$J$$$[$I$N%P%0$N=$@5!#\e(B
+
+@item
+Ilja Weis---@file{gnus-topic.el}\e$B!#\e(B
+
+@item
+Steven L. Baur---\e$B$?$/$5$s$N$?$/$5$s$N$?$/$5$s$N%P%0$NH/8+$H=$@5!#\e(B
+
+@item
+Vladimir Alexiev---refcard \e$B$H%j%U%!%l%s%9$N>.:};R!#\e(B
+
+@item
+Felix Lee & Jamie Zawinski---\e$B;d$O\e(B Felix Lee \e$B$H\e(B JWZ \e$B$N\e(B XGnus \e$BG[I[$+$i$$$/\e(B
+\e$B$D$+$NItJ,$rEp$_$^$7$?!#\e(B
+
+@item
+Scott Byer---@file{nnfolder.el} \e$B$N3HD%$H2~D{!#\e(B
+
+@item
+Peter Mutsaers---\e$B8E;v5-;v$N%9%3%"%3!<%I!#\e(B
+
+@item
+Ken Raebburn---@acronym{POP} \e$B%a!<%k%5%]!<%H!#\e(B
+
+@item
+Hallvard B Furuseth---\e$B$$$m$$$m$J>.$5$JJ*$dItJ,!"FC$K\e(B .newsrc \e$B%U%!%$%k$r\e(B
+\e$B07$&ItJ,!#\e(B
+
+@item
+Brian Edmonds---@file{gnus-bbdbb.el}\e$B!#\e(B
+
+@item
+David Moore--@file{nnvirtual.el} \e$B$N2~D{$HB?$/$NB>$N;v!#\e(B
+
+@item
+Kevin Davidson---@dfn{ding} \e$B$NL>A0$r;W$$IU$-$^$7$?!#$G$9$+$i!"H`$r@U$a$F\e(B
+\e$B2<$5$$!#\e(B
+
+@item
+Fran\e,Ag\e(Bois Pinard---\e$BB?$/$N!"B?$/$N6=L#?<$/40A4$J%P%0%l%]!<%H$H\e(B autoconf \e$B$N\e(B
+\e$B%5%]!<%H!#\e(B
+@end itemize
+
+\e$B$3$N%^%K%e%"%k\e(B (Gnus \e$B1Q8lHG\e(B) \e$B$O\e(B Adrian Aichner \e$B$H\e(B Ricardo Nassif, Mark
+Borges \e$B$K$h$C$F9;@5$5$l!"\e(BJost Krieger \e$B$K$h$C$F0lItJ,$r9;@5$5$l$^$7$?!#\e(B
+
+\e$B0J2<$N?M!9$OB?$/$N%Q%C%A$HDs0F$G9W8%$7$^$7$?\e(B:
+
+Christopher Davis,
+Andrew Eskilsson,
+Kai Grossjohann,
+Kevin Greiner,
+Jesper Harder,
+Paul Jarc,
+Simon Josefsson,
+David K\e,Ae\e(Bgedal,
+Richard Pieri,
+Fabrice Popineau,
+Daniel Quinlan,
+Michael Shields,
+Reiner Steib,
+Jason L. Tibbitts, III,
+Jack Vinson,
+\e$B;32,\e(B \e$B9nH~\e(B,
+and
+Teodor Zlatanov.
+
+\e$B$=$l$H!"0J2<$N?M$K$b%Q%C%A$d$=$NB>$N$b$N$r46<U$7$^$9\e(B:
+
+Jari Aalto,
+Adrian Aichner,
+Vladimir Alexiev,
+Russ Allbery,
+Peter Arius,
+Matt Armstrong,
+Marc Auslander,
+Miles Bader,
+Frank Bennett,
+Alexei V. Barantsev,
+Robert Bihlmeyer,
+Chris Bone,
+Mark Borges,
+Mark Boyns,
+Rob Browning,
+Lance A. Brown,
+Kees de Bruin,
+Martin Buchholz,
+Joe Buehler,
+Kevin Buhr,
+Alastair Burt,
+Joao Cachopo,
+Zlatko Calusic,
+Massimo Campostrini,
+Castor,
+David Charlap,
+Dan Christensen,
+Kevin Christian,
+Jae-you Chung, @c ?
+James H. Cloos, Jr.,
+Laura Conrad,
+Michael R. Cook,
+Glenn Coombs,
+Andrew J. Cosgriff,
+Neil Crellin,
+Frank D. Cringle,
+Geoffrey T. Dairiki,
+Andre Deparade,
+Ulrik Dickow,
+Dave Disser,
+Rui-Tao Dong, @c ?
+Joev Dubach,
+Michael Welsh Duggan,
+Dave Edmondson,
+Paul Eggert,
+Mark W. Eichin,
+Karl Eichwalder,
+\e$B1]JB!!;LCR\e(B,
+Michael Ernst,
+Luc Van Eycken,
+Sam Falkner,
+Nelson Jose dos Santos Ferreira,
+Sigbjorn Finne,
+Sven Fischer,
+Paul Fisher,
+Decklin Foster,
+Gary D. Foster,
+Paul Franklin,
+Guy Geens,
+Arne Georg Gleditsch,
+David S. Goldberg,
+Michelangelo Grigni,
+Dale Hagglund,
+D. Hall,
+Magnus Hammerin,
+\e$BH>ED\e(B \e$B7u0l\e(B,
+Raja R. Harinath,
+\e$BNS\e(B \e$BK'<y\e(B,
+P. E. Jareth Hein,
+\e$B5W=E\e(B Kenji,
+Scott Hofmann,
+Marc Horowitz,
+Gunnar Horrigmo,
+Richard Hoskins,
+Brad Howes,
+Miguel de Icaza,
+Fran\e,Ag\e(Bois Felix Ingrand,
+\e$B;T@n\e(B \e$BC#\e(B
+\e$B:H\e(B, \e$B@P@n\e(B \e$B0lO:\e(B,
+Lee Iverson,
+\e$B4d<<\e(B \e$B85E5\e(B,
+Rajappa Iyer,
+Andreas Jaeger,
+Adam P. Jenkins,
+Randell Jesup,
+Fred Johansen,
+Gareth Jones,
+Greg Klanderman,
+Karl Kleinpaste,
+Michael Klingbeil,
+Peter Skov Knudsen,
+\e$B>.NS\e(B \e$B=$J?\e(B,
+Petr Konecny,
+\e$B>.4X\e(B \e$B5HB'\e(B,
+Thor Kristoffersen,
+Jens Lautenbacher,
+Martin Larose,
+Seokchan Lee, @c Lee
+Joerg Lenneis,
+Carsten Leonhardt,
+James LewisMoss,
+Christian Limpach,
+Markus Linnala,
+Dave Love,
+Mike McEwan,
+Tonny Madsen,
+Shlomo Mahlab,
+Nat Makarevitch,
+Istvan Marko,
+David Martin,
+Jason R. Mastaler,
+Gordon Matzigkeit,
+Timo Metzemakers,
+Richard Mlynarik,
+Lantz Moore,
+\e$B<i2,\e(B \e$BCNI'\e(B,
+Erik Toubro Nielsen,
+Hrvoje Niksic,
+Andy Norman,
+Fred Oberhauser,
+C. R. Oldham,
+Alexandre Oliva,
+Ken Olstad,
+\e$BBg@>\e(B \e$B2m\e(B
+\e$B@2\e(B, \e$B>.Ln\e(B \e$B=(5.\e(B,
+Ettore Perazzoli,
+William Perry,
+Stephen Peters,
+Jens-Ulrik Holger Petersen,
+Ulrich Pfeifer,
+Matt Pharr,
+Andy Piper,
+John McClary Prevost,
+Bill Pringlemeir,
+Mike Pullen,
+Jim Radford,
+Colin Rafferty,
+Lasse Rasinen,
+Lars Balker Rasmussen,
+Joe Reiss,
+Renaud Rioboo,
+Roland B. Roberts,
+Bart Robinson,
+Christian von Roques,
+Markus Rost,
+Jason Rumney,
+Wolfgang Rupprecht,
+Jay Sachs,
+Dewey M. Sasser,
+Conrad Sauerwald,
+Loren Schall,
+Dan Schmidt,
+Ralph Schleicher,
+Philippe Schnoebelen,
+Andreas Schwab,
+Randal L. Schwartz,
+Justin Sheehy,
+Danny Siu,
+Matt Simmons,
+Paul D. Smith,
+Jeff Sparkes,
+Toby Speight,
+Michael Sperber,
+Darren Stalder,
+Richard Stallman,
+Greg Stark,
+Sam Steingold,
+Paul Stevenson,
+Jonas Steverud,
+Paul Stodghill,
+\e$B?\F#\e(B \e$B@60l\e(B,
+Kurt Swanson,
+Samuel Tardieu,
+Teddy,
+\e$B8MBt\e(B \e$B>=I'\e(B,
+Chuck Thompson,
+Philippe Troin,
+James Troup,
+Trung Tran-Duc,
+Jack Twilley,
+Aaron M. Ucko,
+Aki Vehtari,
+Didier Verna,
+Vladimir Volovich,
+Jan Vroonhof,
+Stefan Waldherr,
+Pete Ware,
+Barry A. Warsaw,
+Christoph Wedler,
+Joe Wells,
+Lee Willis,
+and
+Lloyd Zusman.
+
+\e$B$=$l$>$l$N?M!9$,9T$C$?;v$N40A4$J354Q$rF@$k$?$a$K!"\e(BChangeLog \e$B$,\e(B Gnus \e$B$N%"\e(B
+\e$B%k%U%!G[I[$K$O4^$^$l$F$$$F!"K-IY$JFI$_J*$rM?$($k$G$7$g$&!#\e(B(550KB \e$B$H$$$/\e(B
+\e$B$i$+\e(B)\e$B!#\e(B
+
+\e$B;d$,K:$l$?A4$F$N?M$K<U:a$7$^$9!#4V0c$$$J$/$?$/$5$s$N?M$rK:$l$F$$$k;v$G$7$g\e(B
+\e$B$&!#\e(B
+
+\e$B$o$!!"$3$l$O$J$s$H$bB?$$?M$N%j%9%H$@$J$!!#$*$=$i$/<B:]$K\e(B Gnus \e$BF~$k$H$$$&\e(B
+\e$B;v$K0c$$$J$$$G$7$g$&!#$=$l$KC/$,46<U$7$?$G$7$g$&\e(B!
+
+@node New Features
+@subsection \e$B?7$7$$5!G=\e(B
+@cindex new features
+
+@menu
+* ding Gnus::                   \e$B:G=i$N?7$7$$\e(B Gnus \e$B$G$"$k\e(B Gnus 5.0/5.1 \e$B$N?7$7$$;v\e(B
+* September Gnus::              \e$B8x<0$K\e(B Gnus 5.2/5.3 \e$B$H$7$FCN$i$l$F$$$k$b$N\e(B
+* Red Gnus::                    \e$B;0HVL\$N:G>e$N$b$N\e(B---Gnus 5.4/5.5
+* Quassia Gnus::                2 \e$B$+$1$k\e(B 2 \e$B$O\e(B 4\e$B!"$b$7$/$O\e(B Gnus 5.6/5.7
+* Pterodactyl Gnus::            \e$B8^HVL\!"\e(BP \e$B$G;O$^$k!"$b$7$/$O\e(B Gnus 5.8/5.9 \e$B$H$7$FCN$i$l$F$$$k$b$N\e(B
+* Oort Gnus::                   \e$B5pBg$J!#1s$/MZ$+$J!#\e(BGnus 5.10\e$B!#\e(B
+@end menu
+
+\e$B$3$N%j%9%H$O!"$b$A$m$s!"\e(B@emph{\e$B$?$$$F$$$N\e(B} \e$B=EMW$J?7$7$$5!G=$K4X$9\e(B
+\e$B$k\e(B @emph{\e$BC;$$\e(B}\e$B354Q$G$7$+$"$j$^$;$s!#$$$$$(!"K\Ev$O$=$&$G$O$"$j$^$;$s!#$b$C\e(B
+\e$B$H$b$C$H$?$/$5$s$N$b$N$,$"$j$^$9!#$O$$!"2f!9$OAOB$@-$N40A4$J8z2L$r46$8$F\e(B
+\e$B$$$k$N$G$9!#\e(B
+
+@node ding Gnus
+@subsubsection (ding) Gnus
+
+Gnus 5.0/5.1 \e$B$N?7$7$$5!G=\e(B:
+
+@itemize @bullet
+
+@item
+\e$BA4$F$N%P%C%U%!$N304Q$O%U%)!<%^%C%H$N$h$&$JJQ?t\e(B (@pxref{Group Buffer
+Format} \e$B$H\e(B @pxref{Summary Buffer Format}) \e$B$K$h$C$F@_Dj$rJQ$($k;v$,$G$-$k\e(B
+\e$B$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B%m!<%+%k%9%W!<%k$H!"$$$/$D$+$N\e(B @acronym{NNTP} \e$B%5!<%P!<$rF1;~$K;H$&;v$,$G\e(B
+\e$B$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Select Methods})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W$r;v<B>e$N%0%k!<%W$K7k9g$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Virtual
+Groups})\e$B!#\e(B
+
+@item
+\e$BB?$/$N0c$C$?%a!<%kMM<0\e(B (@pxref{Getting Mail}) \e$B$rFI$a$k$h$&$K$J$j$^$7$?!#\e(B
+\e$BA4$F$N%a!<%k%P%C%/%(%s%I$OJXMx$J%a!<%k4|8B@Z$l>C5n5!9=$r<BAu$7$F$$$^\e(B
+\e$B$9\e(B (@pxref{Expiring Mail})\e$B!#\e(B
+
+@item
+Gnus \e$B$O:,$C$3\e(B (root) \e$B$r<:$C$?%9%l%C%I$r=8$a$k$?$a$N$$$m$$$m$J@oN,\e(B (\e$B$=$l\e(B
+\e$B$K$h$C$F$^$P$i$JI{%9%l%C%I$r0l$D$N%9%l%C%I$K$9$k\e(B) \e$B$r;H$C$?$j!"0lC6La$C$F\e(B
+\e$B40A4$J%9%l%C%I$r$/$_>e$2$k$N$K==J,$J%X%C%@!<$r<hF@$7$9$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Customizing Threading})\e$B!#\e(B
+
+@item
+\e$B@Z$i$l$?%0%k!<%W\e(B (killed group) \e$B$O$0%k!<%W%P%C%U%!$KI=<($9$k;v$,$G$-$F!"\e(B
+\e$B$=$l$bFI$`;v$,$G$-$^$9\e(B (@pxref{Listing Groups})\e$B!#\e(B
+
+@item
+Gnus \e$B$OItJ,E*%0%k!<%W99?7$r$9$k;v$,$G$-$^$9\e(B---2,3 \e$B$N%0%k!<%W$N?7$7$$5-;v\e(B
+\e$B$rD4$Y$k$?$a$K%"%/%F%#%V%U%!%$%kA4BN$r<hF@$9$kI,MW$O$"$j$^$;\e(B
+\e$B$s\e(B (@pxref{The Active File})\e$B!#\e(B
+
+@item
+Gnus \e$B$O%0%k!<%W$NCJ3,E*9XFIEY$r<BAu$7$^$7$?\e(B (@pxref{Group Levels})\e$B!#\e(B
+
+@item
+\e$BG$0U$N?t$N4p=`$K=>$C$F5-;v$K%9%3%"$rIU$1$k;v$,$G$-$^$9\e(B (@pxref{Scoring})\e$B!#\e(B
+\e$B$"$J$?$N$?$a$K5-;v$r$I$N$h$&$K%9%3%"$rIU$1$k$+$r\e(B Gnus \e$B$K8+$D$1$5$;$k;v$b\e(B
+\e$B$G$-$^$9\e(B (@pxref{Adaptive Scoring})\e$B!#\e(B
+
+@item
+Gnus \e$B$OIaDL$N\e(B Emacs \e$B$NJ}K!$G<+F0J]B8$5$l$k%I%j%V%k%P%C%U%!$rJ];}$7$F$$$^\e(B
+\e$B$9$N$G!"$"$J$?$N%^%7%s$,Mn$C$3$A$?$H$-$G$b$"$^$j%G!<%?$r<:$o$J$$$G$7$g\e(B
+\e$B$&\e(B (@pxref{Auto Save})\e$B!#\e(B
+
+@item
+Gnus \e$B$O:#$d%U%!%$%k\e(B @file{.emacs} \e$B$r$0$A$c$0$A$c$K$9$k;v$rHr$1$k$?$a$K@l\e(B
+\e$BMQ$N5/F0%U%!%$%k\e(B (@file{~/.gnus.el}) \e$B$r;}$D$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B%0%k!<%W$H5-;v$NN>J}$K%W%m%;%90u$rIU$1$k$3$H$,$G$-!"A4$F$N0u$NIU$$$?9`L\\e(B
+\e$B$K1i;;$r$9$k;v$,$G$-$^$9\e(B (@pxref{Process/Prefix})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W$N0lIt$r\e(B grep \e$B$7$F!"$=$N7k2L$+$i%0%k!<%W$r:n$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Kibozed Groups})\e$B!#\e(B
+
+@item
+\e$B$(!<$H!"A4$F$K$7$?$,$C$F!"%0%k!<%W$N0lMw$r5s$2$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Listing Groups})\e$B!#\e(B
+
+@item
+\e$B30It%5!<%P!<$r354Q$7$F!"$=$l$i$N%5!<%P!<$N%0%k!<%W$r9XFI$9$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Browse Foreign Server})\e$B!#\e(B
+
+@item
+Gnus \e$B$O%5!<%P!<$H$NFs$D@\B3$G!"5-;v$rHsF14|$K$H$C$F$/$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Asynchronous Fetching})\e$B!#\e(B
+
+@item
+\e$B5-;v$r%m!<%+%k$K%-%c%C%7%e$9$k;v$,$G$-$^$9\e(B (@pxref{Article Caching})\e$B!#\e(B
+
+@item
+uudecode \e$B$N4X?t$,3HD%$5$l!"0lHL2=$5$l$^$7$?\e(B (@pxref{Decoding Articles})\e$B!#\e(B
+
+@item
+\e$B2a5n$N\e(B @sc{gnus} \e$B$N$"$^$jCN$i$l$F$$$J$$5!G=$N\e(B uuencode \e$B$5$l$?5-;v$r$^$@\e(B
+\e$BEj9F$9$k;v$,$G$-$^$9\e(B (@pxref{Uuencoding and Posting})\e$B!#\e(B
+
+@item
+\e$B?F5-;v\e(B (\e$B$HB>$N5-;v\e(B) \e$B$N<hF@$O:#$d!"<B:]$KFMA38N>c$9$k;vL5$/F0:n$9$k$h$&$K\e(B
+\e$B$J$j$^$7$?\e(B (@pxref{Finding the Parent})\e$B!#\e(B
+
+@item
+Gnus \e$B$O\e(B @acronym{FAQ} \e$B$H%0%k!<%W$N5-=R$r<hF@$9$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Group Information})\e$B!#\e(B
+
+@item
+\e$B5-;v$r%O%$%i%$%H$7!"%+%9%?%^%$%:$9$k;v$,$G$-$^$9\e(B (@pxref{Customizing
+Articles})\e$B!#\e(B
+
+@item
+URL \e$B$HB>$N30It;2>H$,%\%?%s$K$J$k$h$&$K$J$j$^$7$?\e(B (@pxref{Article
+Buttons})\e$B!#\e(B
+
+@item
+Gnus \e$B$N%&%#%s%I%&$H%U%l!<%`$N@_Dj$G$?$/$5$s$NJQ$J;v$r$G$-$k$h$&$K$J$j$^\e(B
+\e$B$7$?\e(B (@pxref{Window Layout})\e$B!#\e(B
+
+@item
+\e$B%-!<%\!<%I$r;H$&Be$o$j$K!"%\%?%s$r%/%j%C%/$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Buttons})\e$B!#\e(B
+@end itemize
+
+@node September Gnus
+@subsubsection September Gnus
+
+@iftex
+@iflatex
+\gnusfig{-28cm}{0cm}{\epsfig{figure=ps/september,height=20cm}}
+@end iflatex
+@end iftex
+
+Gnus 5.2/5.3 \e$B$N?7$7$$5!G=\e(B:
+
+@itemize @bullet
+
+@item
+\e$B?7$7$$%a%C%;!<%8:n@.%b!<%I$,;H$o$l$^$9!#\e(B
+@code{mail-mode}, @code{rnews-reply-mode} \e$B$H\e(B @code{gnus-msg} \e$B$NA4$F$N8E\e(B
+\e$B$$%+%9%?%^%$%:JQ?t$O:#$d5l<0$K$J$j$^$7$?!#\e(B
+
+@item
+Gnus \e$B$O\e(B @dfn{\e$B$^$P$i\e(B} \e$B%9%l%C%I$r:n@.$9$k;v$,$G$-$k$h$&$K$J$j$^$7$?\e(B---\e$B%9%l%C\e(B
+\e$B%I$N<:$o$l$?5-;v$,$"$k$H$3$m$O6u$N@a$GI=8=$5$l$k$h$&$K$J$C$F$$$^\e(B
+\e$B$9\e(B (@pxref{Customizing Threading})\e$B!#\e(B
+
+@lisp
+(setq gnus-build-sparse-threads 'some)
+@end lisp
+
+@item
+\e$B30$K=P$F$$$/5-;v$OFCJL$JJ]4I%5!<%P!<$KJ]B8$5$l$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Archived Messages})\e$B!#\e(B
+
+@item
+\e$B5-;v$,;2>H$5$l$?$H$-$K!"%9%l%C%I$NItJ,:n@.$,5/$3$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+Gnus \e$B$O\e(B GroupLens \e$B$NM=8@$r;H$&;v$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{GroupLens})\e$B!#\e(B
+
+@item
+Picons (personal icons) (\e$B8D?M%"%$%3%s\e(B) \e$B$,\e(B XEmacs \e$B$GI=<($G$-$k$h$&$K$J$j\e(B
+\e$B$^$7$?\e(B (@pxref{Picons})\e$B!#\e(B
+
+@item
+@code{trn} \e$B$N$h$&$JLZ%P%C%U%!$,I=<($5$l$k$h$&$K$J$j$^$7$?\e(B (@pxref{Tree
+Display})\e$B!#\e(B
+
+@lisp
+(setq gnus-use-trees t)
+@end lisp
+
+@item
+@code{nn} \e$B$N$h$&$J<h$C$FFI$`%^%$%J!<%b!<%I$,35N,%P%C%U%!$G;H$&;v$,$G$-$k\e(B
+\e$B$h$&$K$J$j$^$7$?\e(B (@pxref{Pick and Read})\e$B!#\e(B
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'gnus-pick-mode)
+@end lisp
+
+@item
+\e$B%P%$%J%j!<%0%k!<%W$GFCJL$J%P%$%J%j!<%^%$%J!<%b!<%I$r;H$&;v$,$G$-$k$h$&$K\e(B
+\e$B$J$j$^$7$?\e(B (@pxref{Binary Groups})\e$B!#\e(B
+
+@item
+Group \e$B$,@^$j>v$_%H%T%C%/3,AX$K%0%k!<%WJ,$1$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Group Topics})\e$B!#\e(B
+
+@lisp
+(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
+@end lisp
+
+@item
+Gnus \e$B$,<:GT%a!<%k$r:FAw$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Summary Mail
+Commands})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W$,%9%3%"$r;}$D;v$,$G$-$k$h$&$K$J$j!"K,$l$k2s?t$K4p$E$$$FJB$SBX$(\e(B
+\e$B$r$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Group Score})\e$B!#\e(B
+
+@lisp
+(add-hook 'gnus-summary-exit-hook 'gnus-summary-bubble-group)
+@end lisp
+
+@item
+\e$B%0%k!<%W$K%W%m%;%90u$rIU$1$i$l$k$h$&$K$J$j!"%0%k!<%W$N$0%k!<%W$KL?Na$,<B\e(B
+\e$B9T$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Marking Groups})\e$B!#\e(B
+
+@item
+\e$B;v<B>e$N%0%k!<%W$G%-%c%C%7%e$,$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{nndoc} \e$B$OA4$F$N=8G[G[Aw!"%a!<%k%\%C%/%9!"\e(Brnews \e$B%K%e!<%90l3g!"\e(B
+ClariNet \e$BC;<}=8!"$=$7$FA4$F$N$=$NB>$rM}2r$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Document Groups})\e$B!#\e(B
+
+@item
+Gnus \e$B$O\e(B SOUP \e$B%Q%1%C%H$r:n@.\e(B/\e$BFI$_9~$_$r$9$k$?$a$N?7$7$$%P%C%/%(%s\e(B
+\e$B%I\e(B (@code{nnsoup}) \e$B$r;}$C$F$$$^$9!#\e(B
+
+@item
+Gnus \e$B%-%c%C%7%e$,$:$C$HB.$/$J$j$^$7$?!#\e(B
+
+@item
+\e$B%0%k!<%W$rB?$/$N4p=`$K=>$C$FJB$SBX$($G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Sorting Groups})\e$B!#\e(B
+
+@item
+\e$B%"%I%l%9$N%j%9%H$H4|8B@Z$l>C5n$N;~4V$r@_Dj$9$k?7$7$$%0%k!<%W%Q%i%a!<%?$,\e(B
+\e$BF3F~$5$l$^$7$?\e(B (@pxref{Group Parameters})\e$B!#\e(B
+
+@item
+\e$BA4$F$N%U%)!<%^%C%H;XDj$,;H$o$l$k%U%'%$%9$r;XDj$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Formatting Fonts})\e$B!#\e(B
+
+@item
+@kbd{M P} \e$BI{%^%C%W$K%W%m%;%90u$NIU$$$?5-;v$N@_Dj\e(B/\e$B:o=|\e(B/\e$B<B9T$N$?$a$N$$$/$D\e(B
+\e$B$+$NL?Na$,$"$j$^$9\e(B (@pxref{Setting Process Marks})\e$B!#\e(B
+
+@item
+\e$B9-$$HO0O$N4p=`$K4p$E$$$F!"35N,%P%C%U%!$,2DG=$J5-;v$NItJ,$NI=<($K@)8B$G$-\e(B
+\e$B$k$h$&$K$J$j$^$7$?!#$3$l$i$NL?Na$O\e(B @kbd{/} \e$BI{%^%C%W$N%-!<$K%P%$%s%I$5$l\e(B
+\e$B$F$$$^$9\e(B (@pxref{Limiting})\e$B!#\e(B
+
+@item
+@kbd{*} \e$BL?Na$K$h$C$F!"5-;v$r1JB3$K$9$k;v$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Persistent Articles})\e$B!#\e(B
+
+@item
+\e$B5-;v$NMWAG$r1#$9A4$F$N4X?t$O@Z$jBX$(4X?t$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B5-;v$N%X%C%@!<$,%\%?%s$K$9$k;v$,$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Article
+Washing})\e$B!#\e(B
+
+@item
+\e$BA4$F$N%a!<%k%P%C%/%(%s%I$G\e(B @code{Message-ID} \e$B$K$h$k5-;v$N<hF@$r;HMQ$G$-\e(B
+\e$B$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B=EJ#%a!<%k$rE,@Z$K07$&;v$,$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Duplicates})\e$B!#\e(B
+
+@item
+\e$BA4$F$N35N,%b!<%IL?Na$,5-;v%P%C%U%!$+$iD>@\;HMQ$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Article Keymap})\e$B!#\e(B
+
+@item
+\e$B%U%l!<%`$,\e(B @code{gnus-buffer-configuration} \e$B$NItJ,$K$J$k;v$,$G$-$^\e(B
+\e$B$9\e(B (@pxref{Window Layout})\e$B!#\e(B
+
+@item
+\e$B%G!<%b%s$N%W%m%;%9$G%a!<%k$r:FAv::$9$k$3$H$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Daemons})\e$B!#\e(B
+@iftex
+@iflatex
+\marginpar[\mbox{}\hfill\epsfig{figure=ps/fseptember,height=5cm}]{\epsfig{figure=ps/fseptember,height=5cm}}
+@end iflatex
+@end iftex
+
+@item
+Gnus \e$B$O\e(B spam \e$B$r:,@d$d$7$K$9$k$?$a$K\e(B NoCeM \e$B%U%!%$%k$r;H$&;v$,$G$-$k$h$&$K\e(B
+\e$B$J$j$^$7$?\e(B (@pxref{NoCeM})\e$B!#\e(B
+
+@lisp
+(setq gnus-use-nocem t)
+@end lisp
+
+@item
+\e$B%0%k!<%W$r1J5W2D;k$K$9$k;v$,$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Listing
+Groups})\e$B!#\e(B
+
+@lisp
+(setq gnus-permanently-visible-groups "^nnml:")
+@end lisp
+
+@item
+\e$B%+%9%?%^%$%:$r4JC1$K$9$k$?$a$KB?$/$N?7$7$$%U%C%/$,F3F~$5$l$^$7$?!#\e(B
+
+@item
+Gnus \e$B$O\e(B @code{Mail-Copies-To} \e$B%X%C%@!<$KCm0U$rJ'$&$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{References} \e$B%X%C%@!<$r=8$a$k;v$K$h$j%9%l%C%I$r=8$a$k;v$,$G$-$k$h$&\e(B
+\e$B$K$J$j$^$7$?\e(B (@pxref{Customizing Threading})\e$B!#\e(B
+
+@lisp
+(setq gnus-summary-thread-gathering-function
+      'gnus-gather-threads-by-references)
+@end lisp
+
+@item
+\e$B4{FI5-;v$O:F<hF@$rHr$1$k$?$a$KFCJL$J%P%C%/%m%0%P%C%U%!$KCy$a$i$l$k$h$&$K\e(B
+\e$B$J$j$^$7$?\e(B (@pxref{Article Backlog})\e$B!#\e(B
+
+@lisp
+(setq gnus-keep-backlog 50)
+@end lisp
+
+@item
+\e$B4JC1$J07$$$N$?$a$K!"8=:_$N5-;v$N$-$l$$$JJ#@=$,$$$D$bJL%P%C%U%!$KC_@Q$5$l\e(B
+\e$B$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+Gnus \e$B$,$I$3$K5-;v$rJ]B8$9$k$+$rDs0F$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Saving
+Articles})\e$B!#\e(B
+
+@item
+Gnus \e$B$OJ]B8$9$k$H$-$KF1$8$/$i$$$NB%?J$r$7$J$/$F$bNI$$$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Saving Articles})\e$B!#\e(B
+
+@lisp
+(setq gnus-prompt-before-saving t)
+@end lisp
+
+@item
+@code{uu} \e$B$O5-;v$r<hF@$7$F$$$k4V$KHsF14|$GI|9f2=$5$l$?%U%!%$%k$r1\Mw$G$-\e(B
+\e$B$k$h$&$K$J$j$^$7$?\e(B (@pxref{Other Decode Variables})\e$B!#\e(B
+
+@lisp
+(setq gnus-uu-grabbed-file-functions 'gnus-uu-grab-view)
+@end lisp
+
+@item
+\e$B0zMQ$5$l$?J8>O$KBP$7$F!"5-;v%P%C%U%!$G$N@^$jJV$7$,E,@Z$KF0:n$9$k$h$&$K$J\e(B
+\e$B$j$^$7$?\e(B (@pxref{Article Washing})\e$B!#\e(B
+
+@item
+\e$B1#$5$l$?0zMQJ8$O1#$9;v$r@Z$jBX$($k%\%?%s$r2C$(!"$I$N$/$i$$$N0zMQJ8$r1#$9\e(B
+\e$B$+$r%+%9%?%^%$%:$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Article Hiding})\e$B!#\e(B
+
+@lisp
+(setq gnus-cited-lines-visible 2)
+@end lisp
+
+@item
+\e$BB`6~$J%X%C%@!<$r1#$9;v$,$G$-$^$9\e(B (@pxref{Article Hiding})\e$B!#\e(B
+
+@item
+\e$B%9%3%"$N=i4|CM$,%a%K%e!<%P!<$+$i@_Dj$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B=P$F9T$/5-;v$N99$J$k9=J8%A%'%C%/$,$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+@end itemize
+
+@node Red Gnus
+@subsubsection Red Gnus
+
+Gnus 5.4/5.5 \e$B$N?7$7$$5!G=\e(B:
+
+@iftex
+@iflatex
+\gnusfig{-5.5cm}{-4cm}{\epsfig{figure=ps/red,height=20cm}}
+@end iflatex
+@end iftex
+
+@itemize @bullet
+
+@item
+@file{nntp.el} \e$B$OHsF14|$NN.57$G40A4$K2~D{$5$l$^$7$?!#\e(B
+
+@item
+\e$B%9%3%"IU$1$O\e(B @code{and}, @code{or}, @code{not} \e$B$N$h$&$JO@M}1i;;;R$H!"?F\e(B
+\e$B$N:FJ}8~$G<B9T$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Advanced Scoring})\e$B!#\e(B
+
+@item
+\e$B5-;v$N@vBu>uBV$,5-;v%b!<%I9T$KI=<($5$l$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Misc Article})\e$B!#\e(B
+
+@item
+@file{gnus.el} \e$B$,B?$/$N>.$5$$%U%!%$%k$KJ,3d$5$l$^$7$?!#\e(B
+
+@item
+Message-ID \e$B$K4p$E$$$?!"=EJ#5-;v$NM^@)$,$J$5$l$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Duplicate Suppression})\e$B!#\e(B
+
+@lisp
+(setq gnus-suppress-duplicates t)
+@end lisp
+
+@item
+\e$B$I$N%9%3%"$HE,1~%U%!%$%k$,%[!<%`$N%9%3%"$HE,1~%U%!%$%k$G$"$k$+$r;XDj$9\e(B
+\e$B$k\e(B (@pxref{Home Score File}) \e$B?7$7$$JQ?t$,2C$($i$l$^$7$?!#\e(B
+
+@item
+@code{nndoc} \e$B$,4JC1$K3HD%2DG=$K$J$k$h$&$K2~D{$5$l$^$7\e(B
+\e$B$?\e(B (@pxref{Document Server Internals})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W$O?F$N%H%T%C%/$+$i%0%k!<%W%Q%i%a!<%?$r7Q>5$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Topic Parameters})\e$B!#\e(B
+
+@item
+\e$B5-;vJT=8$,2~D{$5$l!"<B:]$K;HMQ2DG=$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B=pL>$,$b$C$HCNE*$JJ}K!$GG'<1$5$l$k$h$&$K$J$j$^$7$?\e(B (@pxref{Article
+Signature})\e$B!#\e(B
+
+@item
+\e$B35N,%T%C%/%b!<%I$,$b$C$H\e(B @code{nn} \e$B$N$h$&$K$J$j$^$7$?!#9T?t$,I=<($5$l$F!"\e(B
+\e$BL?Na\e(B @kbd{.} \e$B$,5-;v$r<h$k$?$a$K;H$&;v$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@code{Pick and Read})\e$B!#\e(B
+
+@item
+\e$B$"$k%5!<%P!<$+$iJL$N%5!<%P!<$X\e(B @file{.newsrc.eld} \e$B$r0\F0$9$kL?Na$,2C$($i\e(B
+\e$B$l$^$7$?\e(B (@pxref{Changing Servers})\e$B!#\e(B
+
+@item
+\e$B:#$d!"%P%C%U%!$N9T$r:n@.$9$k$H$-$K!"M^@)$5$l$k\e(B ``\e$B$*$b$7$m$/$J$$\e(B'' \e$BItJ,$r\e(B
+\e$B;XDj$9$kJ}K!$,$"$j$^$9\e(B (@pxref{Advanced Formatting})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W%P%C%U%!$G$N$$$/$D$+$NL?Na$O\e(B @kbd{C-M-_} \e$B$G85$KLa$9;v$,$G$-$k$h\e(B
+\e$B$&$K$J$j$^$7$?\e(B (@pxref{Undo})\e$B!#\e(B
+
+@item
+\e$B?7$7$$%9%3%"$N7?\e(B @code{w} \e$B$r;H$&;v$G!"8l$K%9%3%"IU$1$r$9$k;v$,2DG=$K$J$j\e(B
+\e$B$^$7$?\e(B (@pxref{Score File Format})\e$B!#\e(B
+
+@item
+\e$BI=Bj$K0l8l0l8l$r4p$K$7$FE,1~%9%3%"$r$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Adaptive Scoring})\e$B!#\e(B
+
+@lisp
+(setq gnus-use-adaptive-scoring '(word))
+@end lisp
+
+@item
+\e$B%9%3%"$,IeGT$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Score Decays})\e$B!#\e(B
+
+@lisp
+(setq gnus-decay-scores t)
+@end lisp
+
+@item
+\e$BF|IU$N%X%C%@!<$K@55,I=8=$r;H$C$F%9%3%"IU$1$r<B9T$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+\e$BF|IU$O$^$:C;=L\e(B ISO 8601 \e$BMM<0$G@55,2=$5$l$^$9\e(B (@pxref{Score File Format})\e$B!#\e(B
+
+@item
+\e$B4pK\%5!<%P!<$N5-;v$K4X$9$kA4$F$N%G!<%?$r<h$j=|$/L?Na$,2C$($i$l$^$7\e(B
+\e$B$?\e(B (@pxref{Changing Servers})\e$B!#\e(B
+
+@item
+\e$BJ8=q$N=89g$rFI$`$?$a$N?7$7$$L?Na\e(B (@code{nndoc} \e$B$H\e(B @code{nnvirtual} \e$B$N>e\e(B
+\e$B$G\e(B) \e$B$,2C$($i$l$^$7$?\e(B---@kbd{C-M-d} (@pxref{Really Various Summary
+Commands})\e$B!#\e(B
+
+@item
+\e$B%W%m%;%90u$N@_Dj$,\e(B push \e$B$H\e(B pop \e$B$G$-$k$h$&$K$J$j$^$7$?\e(B (@pxref{Setting
+Process Marks})\e$B!#\e(B
+
+@item
+\e$B?7$7$$%a!<%k$+$i%K%e!<%9$X$N%P%C%/%(%s%I$,\e(B @acronym{NNTP} \e$B%5!<%P!<$,Ej9F\e(B
+\e$B$r5v2D$7$F$$$J$$>l9g$G$b!"Ej9F$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Mail-To-News Gateways})\e$B!#\e(B
+
+@item
+\e$B%&%'%V8!:w%(%s%8\e(B
+\e$B%s\e(B (@dfn{DejaNews}, @dfn{Alta Vista}, @dfn{InReference}) \e$B$+$i$N8!:w7k2L\e(B
+\e$B$rFI$`?7$7$$%P%C%/%(%s%I$,2C$($i$l$^$7$?\e(B (@pxref{Web Searches})\e$B!#\e(B
+
+@item
+\e$BI8=`$NJB$SBX$(4X?t$r;H$C$F%0%k!<%W$NCf$N%H%T%C%/$rJB$SBe$($9$k;v$,$G$-!"\e(B
+\e$B$=$l$>$l$N%H%T%C%/$,FHN)$7$FJB$SBX$($G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Topic Sorting})\e$B!#\e(B
+
+@item
+\e$B%0%k!<%W$N0lItJ,$,FHN)$7$FJB$SBX$($G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@code{Sorting})\e$B!#\e(B
+
+@item
+\e$B%-%c%C%7%e$5$l$?5-;v$,%0%k!<%W$KF~$l$i$l$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Summary Generation Commands})\e$B!#\e(B
+@iftex
+@iflatex
+\marginpar[\mbox{}\hfill\epsfig{figure=ps/fred,width=3cm}]{\epsfig{figure=ps/fred,width=3cm}}
+@end iflatex
+@end iftex
+
+@item
+\e$B%9%3%"%U%!%$%k$,$b$C$H?.Mj$G$-$k=gHV$GE,MQ$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Score Variables})\e$B!#\e(B
+
+@item
+\e$B%a!<%k%a%C%;!<%8$,$I$3$K9T$/$+$NJs9p$r:n@.$9$k;v$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@pxref{Splitting Mail})\e$B!#\e(B
+
+@item
+\e$BF~$C$FMh$?%a!<%k$rJ]B8$9$kA0$K$,$i$/$?$r<h$j=|$/%U%C%/$H4X?t$,$b$C$HDI2C\e(B
+\e$B$5$l$^$7$?\e(B (@pxref{Washing Mail})\e$B!#\e(B
+
+@item
+\e$B6/D4J8$,E,@Z$K%U%)%s%H$,JQ99$5$l$k$h$&$K$J$j$^$7$?\e(B:
+@end itemize
+
+@node Quassia Gnus
+@subsubsection Quassia Gnus
+
+Gnus 5.6 \e$B$N?7$7$$5!G=\e(B:
+
+@itemize @bullet
+
+@item
+Gnus \e$B$r%*%U%i%$%s%K%e!<%9%j!<%@!<$H$7$F;H$&?75!G=$,2C$($i$l$^$7$?!#2a>j\e(B
+\e$B$J$[$I$N?7$7$$L?Na$H%b!<%I$,DI2C$5$l$^$7$?!#40A4$JOC$KIU$$$F\e(B
+\e$B$O\e(B @ref{Gnus Unplugged} \e$B$r8+$F2<$5$$!#\e(B
+
+@item
+@code{nndraft} \e$B%P%C%/%(%s%I$,La$C$F$-$^$7$?$,!"0MA3$H$O0c$&$h$&$KF0:n$9\e(B
+\e$B$k$h$&$K$J$j$^$7$?!#A4$F$N%a%C%;!<%8%P%C%U%!$O\e(B @code{nndraft} \e$B%0%k!<%W$N\e(B
+\e$B5-;v$G$b$"$j!"$=$l$O<+F0E*$K:n@.$5$l$^$9!#\e(B
+
+@item
+@code{gnus-alter-header-function} \e$B$,%X%C%@!<$NCM$rJQ$($k$?$a$K;H$o$l$k$h\e(B
+\e$B$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{gnus-summary-goto-article} \e$B$,\e(B Message-ID \e$B$r<u$1IU$1$k$h$&$K$J$j$^\e(B
+\e$B$7$?!#\e(B
+
+@item
+\e$B%j!<%8%g%s$N30$N%a%C%;!<%8$NK\J8$NJ8>O$r>C5n$9$k$?$a$N?7$7$$%a%C%;!<%8L?\e(B
+\e$BNa$,$"$j$^$9\e(B: @kbd{C-c C-v}\e$B!#\e(B
+
+@item
+@kbd{C-u C-c C-c} \e$B$K$h$C$F\e(B @code{nnvirtual} \e$B%0%k!<%W$r@8@.$7$F$$$k%0%k!<\e(B
+\e$B%W$KEj9F$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{nntp-rlogin-program}---\e$B%+%9%?%^%$%:$r4JC1$K$9$k$?$a$N?7$7$$JQ?t$G\e(B
+\e$B$9!#\e(B
+
+@item
+@code{gnus-article-edit-mode} \e$B$N\e(B @code{C-u C-c C-c} \e$B$O5-;v%P%C%U%!$N:F%O\e(B
+\e$B%$%i%$%H$r6X;_$9$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{gnus-boring-article-headers} \e$B$K?7$7$$MWAG$,$"$j$^\e(B
+\e$B$9\e(B---@code{long-to}\e$B!#\e(B
+
+@item
+@kbd{M-i} \e$B%7%s%\%k@\F,0z?tL?Na$,$"$j$^$9!#>\:Y\e(B
+\e$B$O\e(B @ref{Symbolic Prefixes} \e$B$r8+$F2<$5$$!#\e(B
+
+@item
+\e$B35N,%P%C%U%!$N\e(B @kbd{L} \e$B$H\e(B @kbd{I} \e$B$O\e(B @file{all.SCORE} \e$B%U%!%$%k$K%9%3%"K!\e(B
+\e$BB'$r2C$($k$?$a$K%7%s%\%k@\F,0z?t\e(B @kbd{a} \e$B$r<u$1IU$1$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$BJQ?t\e(B @code{gnus-simplify-subject-functions} \e$B$K$h$jC1=c2=$r$b$C$H@)8f$G$-\e(B
+\e$B$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@kbd{A T}---\e$B8=:_$N%9%l%C%I$r<hF@$9$k$?$a$N?7$7$$L?Na$G$9!#\e(B
+
+@item
+@kbd{/ T}---\e$B8=:_$N%9%l%C%I$r@)8B$K4^$a$k$?$a$N?7$7$$L?Na$G$9!#\e(B
+
+@item
+@kbd{M-RET} \e$B$O0zMQJ8$r;_$a$k$?$a$N?7$7$$%a%C%;!<%8L?Na$G$9!#\e(B
+
+@item
+@samp{\\1} \e$BI=8=$,\e(B @code{nnmail-split-methods} \e$B$GM-8z$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B4X?t\e(B @code{custom-face-lookup} \e$B$,<h$j=|$+$l$^$7$?!#$"$J$?$N=i4|2=%U%!%$\e(B
+\e$B%k$G$3$N4X?t$r;H$C$F$$$k$N$J$i!"Be$o$j$K\e(B @code{face-spec-set} \e$B$r;H$&$h$&\e(B
+\e$B$K=q$-D>$5$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item
+\e$BEj9F<h$j>C$7$O8=:_$NA*BrJ}K!$r;H$&$h$&$K$J$j$^$7$?!#%7%s%\%k@\F,\e(B
+\e$B<-\e(B @kbd{a} \e$B$OIaDL$NEj9FJ}K!$r6/@)$7$^$9!#\e(B
+
+@item
+M******** sm*rtq**t*s \e$B$rE,@Z$JJ8>O$KK]0F$9$k?7$7$$L?Na$,$"$j$^$9\e(B---
+@kbd{W d}\e$B!#\e(B
+
+@item
+@code{nntp} \e$B$N$h$j4JC1$J%G%P%C%0$N$?$a$K!"\e(B
+@code{nntp-record-commands} \e$B$r\e(B @code{nil} \e$B$G$J$$CM$K@_Dj$9$k;v$,$G$-$^$9!#\e(B
+
+@item
+@code{nntp} \e$B$O\e(B @file{~/.authinfo} \e$B$r;H$&$h$&$K$J$j!"$3$l\e(B
+\e$B$O\e(B @file{.netrc} \e$B$N$h$&$J%U%!%$%k$G!"$I$3$G$I$N$h$&\e(B
+\e$B$K\e(B @sc{authinfo} \e$B$r\e(B @acronym{NNTP} \e$B%5!<%P!<$KAw$k$+$r@)8f$9$k$?$a$N$b$N\e(B
+\e$B$G$9!#\e(B
+
+@item
+\e$B35N,%P%C%U%!$N%0%k!<%W%Q%i%a!<%?$rJT=8$9$k$?$a$NL?Na$,2C$($i$l$^$7$?!#\e(B
+
+@item
+\e$B%a!<%k$,$I$3$KJ,3d$5$l$?$+$NMzNr$r;HMQ2DG=$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B?7$7$$5-;vF|IUL?Na$,2C$($i$l$^$7$?\e(B---@code{article-date-iso8601}\e$B!#\e(B
+
+@item
+@code{gnus-score-thread-simplify} \e$B$r@_Dj$9$k;v$K$h$j%9%l%C%I$r:n@.$7$F$$\e(B
+\e$B$k$H$-$OI=Bj$,C1=c2=$5$l$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B%a%C%;!<%8$G0zMQ$r$9$k$?$a$N?7$7$$4X?t$,2C$($i$l$^$7$?\e(B---
+@code{message-cite-original-without-signature}\e$B!#\e(B
+
+@item
+@code{article-strip-all-blank-lines}---\e$B?7$7$$5-;vL?Na$G$9!#\e(B
+
+@item
+\e$B5-;v$N=*$o$j$^$G$r@Z$k?7$7$$%a%C%;!<%8L?Na$,2C$($i$l$^$7$?!#\e(B
+
+@item
+\e$BJQ?t\e(B @code{gnus-adaptive-word-minimum} \e$B$r;H$&;v$K$h$j:G>.8BE,1~%9%3%"$r\e(B
+\e$B;XDj$9$k;v$,$G$-$^$9!#\e(B
+
+@item
+\e$BL?Na\e(B @code{gnus-start-date-timer} \e$B$K$h$j\e(B ``\e$B2a<:F|IU\e(B'' \e$B5-;v%X%C%@!<$,7QB3\e(B
+\e$BE*$K99?7$5$l$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B%&%'%V\e(B listserv \e$B%"!<%+%$%V$,\e(B @code{nnlistserv} \e$B%P%C%/%(%s%I$K$h$jFI$`;v\e(B
+\e$B$,$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B8E$$\e(B dejanews \e$B%"!<%+%$%V$,\e(B @code{nnweb} \e$B$+$iFI$`;v$,$G$-$k$h$&$K$J$j$^$7\e(B
+\e$B$?!#\e(B
+@end itemize
+
+@node Pterodactyl Gnus
+@subsubsection Pterodactyl Gnus
+
+Gnus 5.8 \e$B$N?7$7$$5!G=\e(B:
+
+@itemize @bullet
+
+@item
+\e$B%a!<%k$r<h$j9~$`5!G=$,JQ$o$j$^$7$?!#$?$/$5$s$N>\:Y$K$D$$$F$O%^%K%e%"%k$r\e(B
+\e$B8+$F2<$5$$!#FC$K!"\e(Bprocmail \e$B$G<h$j9~$`$?$a$N$9$Y$F$NJQ?t$,L5$/$J$C$F$$$^\e(B
+\e$B$9!#\e(B
+
+\e$B$3$N$h$&$J\e(B procmail \e$B$N;H$$J}$O\e(B
+
+@lisp
+(setq nnmail-use-procmail t)
+(setq nnmail-spool-file 'procmail)
+(setq nnmail-procmail-directory "~/mail/incoming/")
+(setq nnmail-procmail-suffix "\\.in")
+@end lisp
+
+\e$B8=:_$O<!$N$h$&$KJQ$o$C$F$$$^$9!#\e(B
+
+@lisp
+(setq mail-sources
+      '((directory :path "~/mail/incoming/"
+                   :suffix ".in")))
+@end lisp
+
+@xref{Mail Source Specifiers}.
+
+@item
+Gnus \e$B$O\e(B @acronym{MIME} \e$B$KBP1~$7$?%j!<%@!<$K$J$j$^$7$?!#$3$l$O\e(B Gnus \e$B$NB?\e(B
+\e$B$/$NItJ,$K1F6A$7$F$$$F!"$?$/$5$s$N?7$7$$%3%^%s%I$,DI2C$5$l$F$$$^$9!#>\:Y\e(B
+\e$B$O%^%K%e%"%k$r;2>H$7$F2<$5$$!#\e(B(\e$BLuCm\e(B: T-gnus \e$B$O\e(B @acronym{SEMI} \e$B$*$h\e(B
+\e$B$S\e(B @acronym{FLIM} \e$B$N=t5!G=$K4p$E$$$F$$$^$9!#\e(B)
+
+@item
+Gnus \e$B$O$^$?3F9q8lBP1~$K$J$j$^$7$?!#$3$3$G$OMWLs$G$-$J$$$/$i$$$K\e(B Gnus \e$B$N\e(B
+\e$BB?$/$NItJ,$K1F6A$7$F$$$F!"?7$7$$$?$/$5$s$NJQ?t$,DI2C$5$l$F$$$^$9!#\e(B(\e$BLuCm\e(B:
+T-gnus \e$B$O\e(B @acronym{SEMI} \e$B$*$h$S\e(B @acronym{FLIM} \e$B$N=t5!G=$K4p$E$$$F$$$^$9!#\e(B)
+
+@item
+@code{gnus-auto-select-first} \e$B$,4X?t$G$"$C$F$b$h$/$J$j$^$7$?!#\e(B
+
+@item
+Summary \e$B%P%C%U%!$H\e(B @acronym{NOV} \e$B%U%!%$%k$K4^$a$kDI2C$N%X%C%@!<$r!"%f!<\e(B
+\e$B%6$,7h$a$k$3$H$,$G$-$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+@code{gnus-article-display-hook} \e$B$,:o=|$5$l$^$7$?!#Be$o$j\e(B
+\e$B$K\e(B @code{gnus-treat-} \e$B$G;O$^$k$?$/$5$s$NJQ?t$,DI2C$5$l$^$7$?!#\e(B
+
+@item
+Gnus posting styles \e$B$,:F$S2~Au$5$l$^$7$?!#8=:_$OHyL/$K0c$&5,B'$GF0:n$7$^\e(B
+\e$B$9!#\e(B
+
+@item
+\e$B?7$7$$%&%'%V$K4p$E$$$?%P%C%/%(%s%I$,DI2C$5$l$^$7$?!#\e(B@code{nnslashdot},
+@code{nnwarchive} \e$B$*$h$S\e(B @code{nnultimate} \e$B$G$9!#\e(Bnnweb \e$B$O:F$S2~:n$5$l!"\e(B
+\e$B>o$KJQ2=$9$k9=@.$rB3$1$^$9!#\e(B
+
+@item
+Gnus \e$B$O\e(B @code{nnimap} \e$B$K$h$C$F\e(B @acronym{IMAP} \e$B%a!<%k$rFI$`$3$H$,$G$-$^$9!#\e(B
+@end itemize
+
+@node Oort Gnus
+@subsubsection Oort Gnus
+@cindex Oort Gnus
+
+Gnus 5.10 \e$B$N?7$7$$5!G=\e(B:
+
+\e$BLuCm\e(B: Gnus \e$B$OFH<+$K\e(B @acronym{MIME} \e$B$N5!G=$r;}$C$F$$$k$N$KBP$7$F!"\e(B
+T-gnus \e$B$O\e(B @acronym{SEMI} \e$B$d\e(B @acronym{FLIM} \e$B$KMj$C$F$$$^$9!#$7$?$,$C$F!"\e(B
+\e$B0J2<$G@bL@$5$l$F$$$k$$$/$D$+$N5!G=$O\e(B T-gnus \e$B$G$O;H$($J$$$3$H$KCm0U$7$F2<\e(B
+\e$B$5$$!#\e(B
+
+@itemize @bullet
+
+@item
+@code{gnus-group-read-ephemeral-group} \e$B$r\e(B @kbd{G M} \e$B%-!<$GBPOCE*$K8F$V$3\e(B
+\e$B$H$,$G$-$^$9!#\e(B
+
+@item
+\e$B%I%i%U%H!&%0%k!<%W$G\e(B @kbd{e} \e$B%-!<$,\e(B @code{gnus-draft-edit-message} \e$B%3%^\e(B
+\e$B%s%I$K3d$jEv$F$i$l$^$7$?!#\e(B@code{gnus-summary-edit-article} \e$B%3%^%s%I$K$O!"\e(B
+\e$BBe$o$j$K\e(B @kbd{B w} \e$B%-!<$r;H$C$F2<$5$$!#\e(B
+
+@item
+\e$B2~Dj$5$l$?\e(B Gnus @acronym{FAQ} \e$B$,%^%K%e%"%k$K4^$^$l$F$$$^$9!#\e(B
+@xref{Frequently Asked Questions}. (\e$BLuCm\e(B: T-gnus \e$B$N$?$a\e(B
+\e$B$N\e(B @acronym{FAQ} \e$B$O1J$i$/2~Dj$5$l$F$$$^$;$s!#\e(B)
+
+@item
+Oort \e$B$r;H$C$?$3$H$,$"$k>l9g$N!"0JA0$N\e(B (\e$B0BDj$J\e(B) \e$BHG$+$i$N%0%l!<%I%"%C%W!#\e(B
+
+Oort (\e$B$3$N%j%j!<%9$K@hN)$D0BDj$G$O$J$$\e(B Gnus \e$B$N;^\e(B) \e$B$r;H$C$F$_$?$b$N$N!"0B\e(B
+\e$BDjHG$KLa$7$F$7$^$C$?$J$i$P!"$3$NHG$K%0%l!<%I%"%C%W$9$k$H$-$KCm0U$7$F2<$5\e(B
+\e$B$$!#FC$K!"$*$=$i$/$9$Y$F\e(B
+\e$B$N\e(B @file{.marks} (nnml) \e$B$H\e(B @file{.mrk} (nnfolder) \e$B%U%!%$%k$r>C5n$9$kI,MW\e(B
+\e$B$,$"$k$G$7$g$&!#$3$NHG\e(B (\e$B$N\e(B Gnus) \e$B$,%U%i%0$r3JG<$9\e(B
+\e$B$k\e(B @file{.marks}/@file{.mrk} \e$B%U%!%$%k$G$O$J$/$F\e(B @file{.newsrc.eld} \e$B$+$i\e(B
+\e$B%U%i%0$,FI$^$l$k$h$&$K$J$C$F$$$?$+$i$G$9!#8e=R$N9`L\$G!"0u\e(B (marks) \e$B$K4X\e(B
+\e$B$9$k$h$jB?$/$N>pJs$rFI$s$G2<$5$$!#%0%l!<%I$r2<$2$F$b0lHL$K$O=u$1$K$J$i$J\e(B
+\e$B$$$3$H$KCm0U$7$F2<$5$$!#\e(B
+
+@item
+\e$B5-;v$N%\%?%s\e(B
+
+URL\e$B!"%a!<%k%"%I%l%9!"\e(BMessage-ID\e$B!"\e(BInfo \e$B$X$N%j%s%/!"\e(Bman \e$B%Z!<%8$H\e(B Emacs \e$B$^\e(B
+\e$B$?$O\e(B Gnus \e$B$K4XO"$7$?;29MJ88%$N$?$a$N!"$h$jB?$/$N%\%?%s!#\e(B@xref{Article
+Buttons}. \e$B$9$Y$F$N5-;v$N%\%?%s$N8+1I$($r@)8f$9$k$?$a\e(B
+\e$B$K\e(B @code{gnus-button-@var{*}-level} \e$BJQ?t$r;H$&$3$H$,$G$-$^$9!#\e(B
+@xref{Article Button Levels}.
+
+@item
+Dired \e$B$NE}9g\e(B
+
+@code{gnus-dired-minor-mode} (@ref{Other modes} \e$B;2>H\e(B) \e$B$O!"\e(Bdired \e$B$N%P%C%U%!\e(B
+\e$B$G%-!<@_Dj\e(B -- \e$BE:IU%U%!%$%k$NAw?.!"\e(Bmailcap \e$B$NE,@Z$J9`L\$r;H$C$F%U%!%$%k$r\e(B
+\e$B3+$/!"$=$l$K\e(B mailcap \e$B$N9`L\$r;H$C$F%U%!%$%k$r0u:~$9$k\e(B -- \e$B$r9T$J$$$^$9!#\e(B
+
+@item
+Gnus \e$B$O\e(B RSS \e$B$N%K%e!<%9G[Aw$r!"%K%e!<%9%0%k!<%W$H$7$FI=<($7$^$9!#\e(B
+@xref{RSS}.
+
+@item
+\e$BC10l$N\e(B yenc \e$B$G%(%s%3!<%I$5$l$?E:IU%Q!<%H$,%G%3!<%I$G$-$^$9!#\e(B
+
+@item
+Picons
+
+Picon \e$B$N%3!<%I$,!"\e(BGNU Emacs \e$B$GF0:n$5$;$k$?$a$K:F<BAu$5$l$^$7$?!#0JA0$N$$\e(B
+\e$B$/$D$+$N%*%W%7%g%s$,!":o=|$^$?$O2~L>$5$l$F$$$^$9!#\e(B
+
+Picon \e$B$O!"%f!<%6!<!"%I%a%$%s!"$=$l$K%K%e!<%9%0%k!<%W$rI=8=$9$k$?$a$N!V8D\e(B
+\e$B?ME*$J%"%$%3%s\e(B (personal icons)\e$B!W$G!"5-;v%P%C%U%!$KI=<($9$k$3$H$,$G$-$^\e(B
+\e$B$9!#\e(B@xref{Picons}.
+
+@item
+\e$B?7$7$$%*%W%7%g%s\e(B @code{gnus-treat-body-boundary} \e$B$rHs\e(B-@code{nil} \e$B$K$9$k\e(B
+\e$B$H!"%X%C%@!<$N$*$7$^$$$K6-3&@~$,IA$+$l$^$9!#\e(B
+
+@item
+\e$B7{>O$H%3%s%H%m!<%k%a%C%;!<%8$N<hF@\e(B
+
+\e$BFs$D$N%3%^%s%I\e(B -- \e$B%K%e!<%9%0%k!<%W$N7{>O$r<h$j9~$`\e(B (@kbd{H c})\e$B!"%3%s%H%m!<\e(B
+\e$B%k%a%C%;!<%8$r<hF@\e(B (@kbd{H C}) -- \e$B$,$"$j$^$9!#\e(B
+
+@item
+\e$BCY1d5-;v\e(B
+
+Message \e$B%P%C%U%!$K$*$1$k\e(B @kbd{C-c C-j} \e$B$G!"%a%C%;!<%8$NAw?.$rCY$i$;$k$3\e(B
+\e$B$H$,$G$-$^$9!#%a%C%;!<%8$O;XDj$5$l$?;~9o$KG[Aw$5$l$^$9!#$3$l$O$"$J$?<+?.\e(B
+\e$B$N$?$a$NK:HwO?$H$7$FLr$KN)$D$G$7$g$&!#\e(B@xref{Delayed Articles}.
+
+@item
+@code{auto-compression-mode} \e$B$,M-8z$K$J$C$F$$$k$H!"E:IU%U%!%$%k$r8+$k$H\e(B
+\e$B$-$K<+F0$G05=L$,2r$+$l$^$9!#\e(B
+
+@item
+\e$B?7$7$$%*%W%7%g%s\e(B @code{nnml-use-compressed-files} \e$B$rHs\e(B-@code{nil} \e$B$K$9$k\e(B
+\e$B$3$H$K$h$C$F!"\e(Bnnml \e$B$,05=L$5$l$?%a%C%;!<%8%U%!%$%k$r07$&$3$H$,$G$-$k$h$&\e(B
+\e$B$K$J$j$^$9!#\e(B
+
+@item
+\e$B5-;v$N=pL>%X%C%@!<\e(B (X-PGP-Sig) \e$B$r!"\e(B@kbd{W p} \e$B$GG'>Z$9$k$3$H$,$G$-$^$9!#\e(B
+
+@item
+\e$B35N,%P%C%U%!$O\e(B fringe \e$B$NCf$NLp0u$G8=:_$N5-;v$r<($7$^$9!#$3$l$rL58z$K$9$k\e(B
+\e$B$K$O\e(B @code{(setq gnus-summary-display-arrow nil)} \e$B$r;H$C$F2<$5$$!#\e(B
+
+@item
+\e$B%K%e!<%9$K%a!<%k$GJV?.$7$h$&$H$7$?$i7Y9p\e(B
+
+\e$B4V0c$C$F%K%e!<%9$K%a!<%k$GJV?.$7$h$&$H$7$F$7$^$&$3$H$,!"$7$g$C$A$e$&$"$j\e(B
+\e$B$^$;$s$+\e(B?  \e$B$=$s$J$"$J$?$K?7%*%W%7%g\e(B
+\e$B%s\e(B @code{gnus-confirm-mail-reply-to-news}\e$B!#\e(B
+
+@item
+\e$B?7$7$$%*%W%7%g%s\e(B @code{gnus-summary-display-while-building} \e$B$r\e(B
+\e$BHs\e(B-@code{nil} \e$B$K$9$k$H!"35N,%P%C%U%!$,:n$i$l$F$$$/MM;R$,I=<($5$l$^$9!#\e(B
+
+@item
+\e$B?7$7$$\e(B @code{recent} \e$B0u\e(B @samp{.} \e$B$G!"?75,$KFO$$$?%a%C%;!<%8$r\e(B (\e$BL$FI$@$1\e(B
+\e$B$l$I$b8E$$5-;v$H$O6hJL$7$F\e(B) \e$BI=<($7$^$9!#\e(B
+
+@item
+\e$B?7$7$$%*%W%7%g%s\e(B @code{gnus-gcc-mark-as-read} \e$B$O!"\e(BGcc \e$B$N5-;v$K<+F0E*$K4{\e(B
+\e$BFI$N0u$rIU$1$^$9!#\e(B
+
+@item
+nndoc \e$B%P%C%/%(%s%I$O!"\e(Bmailman \e$B$N$^$H$aAw$j$H\e(B exim \e$B$,CF$$$?%a%C%;!<%8$r%5\e(B
+\e$B%]!<%H$9$k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+Gnus \e$B$O\e(B RFC 2369 \e$B$N%a!<%j%s%0%j%9%H$N%X%C%@!<$r%5%]!<%H$7$^$9!#$^$?!"%a!<\e(B
+\e$B%j%s%0%j%9%H$N%0%k!<%WMQ$K?t!9$N%3%^%s%I$rMQ0U$7$^$7$?!#\e(B@xref{Mailing
+List}.
+
+@item
+\e$BF|IU%X%C%@!<$r!"1Q8l$GH/2;$G$-$k7A<0$GI=<($9$k$3$H$,$G$-$^$9!#\e(B
+@xref{Article Date}.
+
+@item
+Sendmail \e$B$r;H$&$H$-$N%(%s%Y%m!<%WAw?.<T\e(B (envelope sender) \e$B$N%"%I%l%9$,!"\e(B
+\e$B%+%9%?%^%$%:$G$-$k$h$&$K$J$j$^$7$?!#\e(B@xref{Mail Variables, Mail
+Variables,, message-ja, Message Manual}.
+
+@item
+@code{mm-uu-diff-groups-regexp} \e$B$K9gCW$9$k%0%k!<%W$G$O!":9J,\e(B (diffs) \e$B$,\e(B
+\e$B<+F0E*$K%O%$%i%$%H$5$l$^$9!#\e(B
+
+@item
+@acronym{TLS} \e$B%i%C%Q!<$,\e(B Gnus \e$B$KF1:-\e(B
+
+@acronym{TLS}/@acronym{SSL} \e$B$,!"\e(B@file{tls.el} \e$B$H\e(B GNUTLS \e$B$r2p$7\e(B
+\e$B$F\e(B @acronym{IMAP} \e$B$H\e(B @acronym{NNTP} \e$B$G%5%]!<%H$5$l$k$h$&$K$J$j$^$7$?!#\e(B
+(\e$B%5!<%I%Q!<%F%#!<$N\e(B) @file{ssl.el} \e$B$H\e(B OpenSSL \e$B$K$h$k8E\e(B
+\e$B$$\e(B @acronym{TLS}/@acronym{SSL} \e$B$O!"$^$@;H$($^$9!#\e(B
+
+@item
+MS \e$B%&%#%s%I%&%:$G\e(B Gnus \e$B$r%3%s%Q%$%k$7$F%$%s%9%H!<%k$9$k$?$a$N!"?7$7\e(B
+\e$B$$\e(B @file{make.bat}
+
+MS \e$B%&%#%s%I%&%:$G\e(B Gnus \e$B$r%$%s%9%H!<%k$9$k$K$O\e(B @file{make.bat} \e$B$r;H$C$F2<\e(B
+\e$B$5$$!#$3$N%P%C%A!&%W%m%0%i%`$NBh0l0z?t$O%G%#%l%/%H%j$G$9!#$=$3\e(B
+\e$B$G\e(B @file{xemacs.exe} \e$B$H\e(B @file{emacs.exe} \e$B$,=g$KA\$7=P$5$l$^$9!#%3%s%Q%$\e(B
+\e$B%k$7$F$+$i\e(B Gnus \e$B$r%$%s%9%H!<%k$7$?$$$H$-$O!"\e(B@file{make.bat} \e$B$NBhFs0z?t\e(B
+\e$B$K\e(B @code{/copy} \e$B$rM?$($F2<$5$$!#\e(B
+
+@file{make.bat} \e$B$O%<%m$+$i=q$-D>$5$l$^$7$?!#\e(BXEmacs \e$B$H\e(B GNU Emacs \e$B$r<+F0G'\e(B
+\e$B<1$7!"\e(B@file{gnus-load.el} \e$B$r@8@.$7!"%3%s%Q%$%kCf$H\e(B info \e$B%U%!%$%k$N@8@.Cf\e(B
+\e$B$K%(%i!<$,5/$-$?$i9=C[=hM}$N:G8e$KJs9p$7$^$9!#\e(B@code{makeinfo} \e$B$,MxMQ2DG=\e(B
+\e$B$G$"$l$P$=$l$r;H$$!"$5$b$J$1$l$P\e(B @file{infohack.el} \e$B$KMj$j$^$9!#:#\e(B
+\e$B$d\e(B @file{make.bat} \e$B$O\e(B Gnus \e$B$rF0:n$5$;$k$?$a$KI,MW$J$9$Y$F$N%U%!%$%k$r%$\e(B
+\e$B%s%9%H!<%k$9$k$O$:$G!"BgBN$K$*$$$F\e(B Unix \e$B%7%9%F%`$K$*$1\e(B
+\e$B$k\e(B @code{configure; make; make install} \e$B%5%$%/%k$N40A4$JCV$-49$($K$J$j$^\e(B
+\e$B$7$?!#\e(B
+
+\e$B?7$7$$\e(B @file{make.bat} \e$B$O\e(B @file{make-x.bat} \e$B$rITMW$K$7$?$N$G!"$=$l$O:o=|\e(B
+\e$B$5$l$^$7$?!#\e(B
+
+@item
+\e$BHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$N%5%]!<%H\e(B
+
+Message \e$B$O\e(B From:, To: \e$B$*$h$S\e(B Cc: \e$B$K$"$kHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$r%5\e(B
+\e$B%]!<%H$7!"%a%C%;!<%8$NAw?.$r;n$_$k$H$-$K%(%s%3!<%I$9$k$+$I$&$+$r?R$M$^$9!#\e(B
+@code{message-use-idna} \e$BJQ?t$G$3$l$r@)8f$7$^$9!#\e(BGnus \e$B$b$^$?!"%a%C%;!<%8\e(B
+\e$B$r8+$k$H$-$K\e(B From:, To: \e$B$*$h$S\e(B Cc: \e$B$K$"$kHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$r\e(B
+\e$B%G%3!<%I$7$^$9!#$3$l$r@)8f$9$k$N$O\e(B @code{gnus-use-idna} \e$BJQ?t$G$9!#\e(B
+
+@item
+\e$B%^%$%/%m%=%U%H0zMQMM<0$N$h$jNI$$<h$j07$$\e(B
+
+\e$B$$$/$D$+$N%^%$%/%m%=%U%H$N%a%$%i!<$,!"%a%C%;!<%8$N;D$j$NItJ,$,0zMQ$G$"$k\e(B
+\e$B$3$H$r<($9$?$a$K;H$&BfL5$7$K$5$l$?%X%C%@!<%V%m%C%/$r!"$?$H$($=$l$,0zMQId\e(B
+\e$B$G0O$^$l$F$$$J$/$F$b!"\e(BGnus \e$B$OG'<1$7$h$&$H$7$^$9!#JQ\e(B
+\e$B?t\e(B @code{gnus-cite-unsightly-citation-regexp} \e$B$O!"$=$l$i$N0zMQ$N@hF,$K9g\e(B
+\e$BCW$7$^$9!#\e(B
+
+@item
+@code{gnus-article-skip-boring}
+
+@code{gnus-article-skip-boring} \e$B$r\e(B @code{t} \e$B$K@_Dj$9$k$H!"\e(BGnus \e$B$O$&$s$6\e(B
+\e$B$j$9$kJ8$7$+4^$s$G$$$J$$%Z!<%8$r8+$;$k$?$a$K!"2<J}$K%9%/%m!<%k$7$^$;$s!#\e(B
+@code{gnus-article-boring-faces} \e$B$r;H$C$F!"2?$rFI$_Ht$P$7$F$7$^$C$F$bNI\e(B
+\e$B$$$+$r%+%9%?%^%$%:$9$k$3$H$,$G$-$^$9!#\e(B
+
+\e$BD9$/$F4"$j9~$^$l$F$$$J$$0zMQ$,!"$F$C$Z$s$K>/$7$@$1$"$k?75,$JFbMF$KB3$$$F\e(B
+\e$B$$$k$?$/$5$s$N5-;v$rFI$`>l9g$K!"$3$l$OFC$KLr$KN)$A$^$9!#\e(B
+
+@item
+\e$B%]%$%s%H$N0LCV7h$a$N$?$a$N%U%)!<%^%C%H$N;EMM\e(B (format spec) \e$B$G$"\e(B
+\e$B$k\e(B @code{%C} \e$B$O!"\e(B@code{%*} \e$B$KJQ99$5$l$^$7$?!#\e(B
+
+@item
+\e$B?7$7$$JQ?t\e(B @code{gnus-parameters} \e$B$,!"%0%k!<%W%Q%i%a!<%?$r@_Dj$9$k$?$a$K\e(B
+\e$B;H$&$3$H$,$G$-$^$9!#\e(B
+
+\e$B$3$l$O=i4|$K$O!"%Q%i%a!<%?$r\e(B @file{~/.newsrc.eld} \e$B$K3JG<$9$k\e(B @kbd{G p}
+(\e$B$^$?$O\e(B @kbd{G c}) \e$B$G$7$+9T$J$&$3$H$,$G$-$^$;$s$G$7$?$,!"$3$NJQ?t$K$h$C\e(B
+\e$B$F%+%9%?%^%$%:$N0RNO$r4.G=$9$k$3$H$,$G$-$^$9!#$^$?!"$=$NJQ?t\e(B
+\e$B$O\e(B @file{~/.newsrc.eld} \e$B$G$O$J$/$F\e(B @file{~/.emacs} \e$B$G@_Dj$9$k$N$G!"%P%C\e(B
+\e$B%/%"%C%W$,4JC1$K$J$j$^$9!#$=$NJQ?t$O!"%0%k!<%WL>$K9gCW$9$k@55,I=8=$r!"0J\e(B
+\e$B2<$N$h$&$JN.57$G%0%k!<%W%Q%i%a!<%?$K3d$jEv$F$^$9\e(B:
+@lisp
+(setq gnus-parameters
+      '(("mail\\..*"
+         (gnus-show-threads nil)
+         (gnus-use-scoring nil))
+        ("^nnimap:\\(foo.bar\\)$"
+         (to-group . "\\1"))))
+@end lisp
+
+@item
+\e$B%9%^%$%j!<\e(B (@samp{:-)}, @samp{;-)} \e$B$J$I\e(B) \e$B$,\e(B Emacs \e$B$G$b%"%$%3%s2=$5$l$k$h\e(B
+\e$B$&$K$J$j$^$7$?!#\e(B
+
+\e$B$3$l$rF/$+$J$$$h$&$K$9$k$K$O!"\e(B@code{(setq gnus-treat-display-smileys
+nil)} \e$B$r\e(B @file{~/.emacs} \e$B$KCV$$$F2<$5$$!#\e(B
+
+@item
+Gnus \e$B$O:#$G$O\e(B Sender: \e$B%X%C%@!<$r<+F0$G$O@8@.$7$^$;$s!#\e(B
+
+\e$B=i4|$N$3$m!"$=$l$O%f!<%6!<$,@_Dj$G$-$k\e(B email \e$B%"%I%l%9$,!"\e(BGnus \e$B$,A[Dj$7$?\e(B
+\e$B%f!<%6!<$N%G%#%U%)%k%H$N%"%I%l%9$H0c$C$F$$$?>l9g$K@8@.$5$l$^$7$?!#:#F|$G\e(B
+\e$B$O$=$NA[Dj%"%k%4%j%:%`$,@5$7$$$3$H$O$^$l$G!"\e(BSender: \e$B%X%C%@!<$NM#0l$N\e(B (\e$B5D\e(B
+\e$BO@$NE*$K$J$k\e(B) \e$BMQES$O!"%K%e!<%9$r\e(B cancel/supersede \e$B$9$k;q3J$,$"$k$+$I$&$+\e(B
+\e$B$r8!::$9$k$3$H\e(B (\e$B$3$l$OBe$o$j$K!"B>$N9`$G=R$Y$i$l$k\e(B Cancel Locks \e$B$K$h$C$F\e(B
+\e$B2r7h$5$l$?\e(B) \e$B$J$N$G!"$=$N%X%C%@!<$N@8@.$O%G%#%U%)%k%H$GM^@)$5$l$F$$$^$9!#\e(B
+\e$BJQ?t\e(B @code{message-required-headers}\e$B!"\e(B
+@code{message-required-news-headers} \e$B$*$h\e(B
+\e$B$S\e(B @code{message-required-mail-headers} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item
+\e$B%5!<%I%Q!<%F%#!<$K$h$k\e(B @file{message-utils.el} \e$B$N5!G=\e(B
+\e$B$,\e(B @file{message.el} \e$B$K2C$($i$l$^$7$?!#\e(B
+
+Message \e$B$OI=Bj\e(B (subject) \e$B$N9T$+$i\e(B @samp{(was: <old subject>)} \e$B$r:o=|$9$k\e(B
+\e$B$+$I$&$+$r?R$M$k$h$&$K$J$j$^$7\e(B
+\e$B$?\e(B (@code{message-subject-trailing-was-query} \e$B;2>H\e(B)\e$B!#\e(B
+@kbd{C-c M-m} \e$B$H\e(B @kbd{C-c M-f} \e$B$OA^F~$5$l$?%F%-%9%H$r<($90u$rA^F~$7$^$9!#\e(B
+@kbd{C-c C-f a} \e$B$O\e(B X-No-Archive: \e$B%X%C%@!<$rIU$12C$($^$9!#\e(B@kbd{C-c C-f
+x} \e$B$O!"E,@Z$J%X%C%@!<$H!"%/%m%9%]%9%H$H%U%)%m!<@h$K$D$$$F$NCm0U=q$-$rK\\e(B
+\e$BJ8$KA^F~$7$^$9\e(B (@code{message-cross-post-@var{*}} \e$BJQ?t72$r8+$F2<$5$$\e(B)\e$B!#\e(B
+
+@item
+\e$B:#$d\e(B @code{message-generate-headers-first} \e$B$,\e(B @code{nil} \e$B$@$C$?$i!"%a%C\e(B
+\e$B%;!<%8$N:n@.$r;O$a$k$H$-$K\e(B References \e$B$H\e(B X-Draft-Headers \e$B$O@8@.$5$l$^$;\e(B
+\e$B$s!#\e(B
+
+@item
+\e$B2~NI$5$l$?\e(B spam \e$BBP935!G=!#\e(B
+
+Gnus \e$B$OHs>o$KJQ2=$KIY$s$@%W%m%0%i%`$H_I2a$N5,B'$r;H$C$F!"%a!<%k$d%K%e!<\e(B
+\e$B%9$NK[N.$+$i\e(B spam \e$B$rH4$-<h$C$F$7$^$&$3$H$,$G$-$k$h$&$K$J$j$^$7$?!#BP1~$7\e(B
+\e$B$F$$$kJ}<0$O!"\e(BRBL blocklists\e$B!"\e(Bbogofilter \e$B$=$l$K%[%o%$%H\e(B/\e$B%V%i%C%/%j%9%H$G\e(B
+\e$B$9!#$^$?\e(B SpamAssassin \e$B$d\e(B Hashcash \e$B$N$h$&$J30It%Q%C%1!<%8$r4JC1$K;H$&$?$a\e(B
+\e$B$N\e(B hook \e$B$b?7$7$/$J$j$^$7$?!#\e(B@xref{Thwarting Email Spam}.
+
+@item
+X-Faces \e$B%X%C%@!<$NA^F~$,4JC1$K$J$j$^$7$?!#\e(B
+
+@item
+Face \e$B%X%C%@!<$r07$($k$h$&$K$J$j$^$7$?!#\e(B
+
+@item
+\e$B35N,%P%C%U%!$K!"?7$7$$%3%^%s%I\e(B @kbd{/ N} \e$B$O?7Ce%a%C%;!<%8$rA^F~$7!"\e(B
+@kbd{/ o} \e$B$O8E$$%a%C%;!<%8$rA^F~$7$^$9!#\e(B
+
+@item
+@kbd{W m} \e$B$r2!$9$H!"\e(BGnus \e$B$O%b!<%k%9$GId9f2=$5$l$?%a%C%;!<%8$r%G%3!<%I$7\e(B
+\e$B$^$9!#\e(B
+
+@item
+nnimap \e$B$N%0%k!<%W$K$*$1$kL$FI$N?t$,@53N$K$J$j$^$7$?!#\e(B
+
+\e$B%0%k!<%W%P%C%U%!$G!"\e(Bnnimap \e$B%0%k!<%W$NL$FI5-;v$N?t$N8+@Q$j$,@53N$K$J$C$?\e(B
+\e$B$O$:$G$9!#$3$l$O\e(B @code{gnus-setup-news-hook} (\e$B5/F0;~$K8F$P$l\e(B
+\e$B$k\e(B) \e$B$H\e(B @code{gnus-after-getting-new-news-hook} (\e$B?7$7$$%a!<%k$r<hF@$7$?D>\e(B
+\e$B8e$K8F$P$l$k\e(B) \e$B$+$i\e(B @code{nnimap-fixup-unread-after-getting-new-news} \e$B$r\e(B
+\e$B8F$V$3$H$K$h$C$F@.$7?k$2$i$l$^$9!#$3$l$i$NJQ?t$r%G%#%U%)%k%H$+$iJQ$($F$$\e(B
+\e$B$k>l9g$O!":F$S\e(B @code{nnimap-fixup-unread-after-getting-new-news} \e$B$rDI2C\e(B
+\e$B$9$kI,MW$,$"$k$+$b$7$l$^$;$s!#8+@Q$j$KK~B-$7$F$$$F!"?7$7$$%a!<%k$r<hF@$9\e(B
+\e$B$k$H$-$K$$$/$i$+\e(B (\e$B:G>.8BEY$N\e(B) \e$B;~4V$r@aLs$7$?$$$N$G$"$l$P!"$=$N4X?t$r30$7\e(B
+\e$B$F2<$5$$!#\e(B
+
+@item
+\e$B%0%k!<%W%+!<%\%s%3%T!<\e(B (GCC) \e$B$r0zMQId$G0O$`\e(B
+
+\e$B6uGr$dB>$NJQ$JJ8;z$r4^$`%0%k!<%W$r07$($k$h$&$K$9$k$?$a$K!"%0%k!<%W\e(B
+\e$B$O\e(B Gcc: header \e$B$KCV$+$l$kA0$K0zMQId$G0O$^$l$^$9!#$3$l$O!"6uGr$r4^$`%0%k!<\e(B
+\e$B%W$,;H$($k$h$&$K$9$k$?$a$K!"$b$O$d\e(B @code{gnus-message-archive-group} \e$B$N\e(B
+\e$B$h$&$JJQ?t$K0zMQJ8;z$r4^$a$k$Y$-$G$O$J$$$3$H$r0UL#$7$^$9!#$5$i$K!"J8;z\e(B
+\e$BNs\e(B @samp{nnml:foo, nnml:bar} (\e$BFs$D$N%0%k!<%W$K\e(B Gcc \e$B$r3JG<$9$k$3$H$r<(\e(B
+\e$B$9\e(B) \e$B$r;H$C$F$$$k$J$i$P!"%j%9%H\e(B @code{("nnml:foo" "nnml:bar")} \e$B$rJV$9$h$&\e(B
+\e$B$KJQ99$7$J$1$l$P$J$j$^$;$s!#$5$b$J$$$H!"\e(BGcc: \e$B9T$O4V0c$C$?0O$^$lJ}$r$5$l\e(B
+\e$B$F$7$^$&$G$7$g$&!#=i4|$N$3$m$KJ8;zNs\e(B @samp{nnml:foo, nnml:bar} \e$B$rJV$9$h\e(B
+\e$B$&$K$7$?$3$H$,4V0c$$$@$C$?$3$H$KCeL\$7$F2<$5$$!#$=$l$OD>@\A^F~$5$l$?$N$G!"\e(B
+\e$B$^$C$?$/LdBj$r@8$8$^$;$s$G$7$?!#\e(B
+
+@item
+@file{~/News/overview/} \e$B$OITMW!#\e(B
+
+\e$B0J2<$NJQ99$N7k2L!":#8e$O\e(B @file{~/News/overview/} \e$B%G%#%l%/%H%j$OMW$j$^$;\e(B
+\e$B$s!#$9$Y$F$N3,AX$r0BA4$K:o=|$9$k$3$H$,$G$-$^$9!#\e(B
+
+@item
+@code{gnus-agent}
+
+Gnus \e$B%(!<%8%'%s%H$OBg5,LO$J99?7$r7P$F!":#$d%G%#%U%)%k%H$G3h@-2=$5$l$^$9!#\e(B
+\e$B$=$7\e(B
+\e$B$F\e(B @code{gnus-select-method} \e$B$H\e(B @code{gnus-secondary-select-method} \e$B$G;X\e(B
+\e$BDj$5$l$k$9$Y$F$N\e(B nntp \e$B$H\e(B nnimap \e$B$N%5!<%P!<$,!"%G%#%U%)%k%H$G%(!<%8%'%s%H\e(B
+\e$B2=$5$l$^$9!#=i4|$K$*$$$F$O\e(B @code{gnus-select-method} \e$B$N%5!<%P!<$@$1$,%G%#\e(B
+\e$B%U%)%k%H$G%(!<%8%'%s%H2=$5$l!"%(!<%8%'%s%H$O%G%#%U%)%k%H$GIT3h@-2=$5$l$F\e(B
+\e$B$$$^$7$?!#%(!<%8%'%s%H$,3h@-2=$5$l$k$H!"2DG=$J$i$P%P%C%/%(%s%I$KBe$o$C$F\e(B
+\e$B%(!<%8%'%s%H$N%-%c%C%7%e$+$i%X%C%@!<$,<h$j4s$;$i$l$^$9!#=i4|$K$O!"$3$l$O\e(B
+\e$B%*%U%i%$%s\e(B (unplugged) \e$B$N>uBV$G$N$_9T$J$o$l$F$$$^$7$?!#%5!<%P!<%P%C%U%!\e(B
+\e$B$G\e(B @kbd{J a} \e$B$H\e(B @kbd{J r} \e$B$r;H$&$3$H$K$h$C$F!"%5!<%P!<$NEPO?$H:o=|$r9T$J\e(B
+\e$B$&$3$H$,$G$-$^$9!#%0%k!<%W%P%C%U%!$+$i\e(B @kbd{J u} \e$B$+\e(B @kbd{J s} \e$B$r;H$C$FL?\e(B
+\e$BNa$7$J$$8B$j!"\e(BGnus \e$B$O5-;v$r%(!<%8%'%s%H$N%-%c%C%7%e$K%@%&%s%m!<%I$7$^$;\e(B
+\e$B$s!#\e(B@code{(setq gnus-agent nil)} \e$B$G$b$C$F!"%(!<%8%'%s%H$,IT3h@-2=$5$l$F\e(B
+\e$B$$$?@N$N?6$kIq$$$KLa$9$3$H$,$G$-$^$9!#:#8e\e(B
+\e$B$O\e(B @file{~/.gnus.el} \e$B$K\e(B @code{(gnus-agentize)} \e$B$rCV$$$F$*$/I,MW$,L5$$$3\e(B
+\e$B$H$KCm0U$7$F2<$5$$!#\e(B
+
+@item
+@code{gnus-summary-line-format}
+
+\e$B%G%#%U%)%k%HCM$,\e(B @samp{%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n} \e$B$KJQ$o$j$^$7\e(B
+\e$B$?!#$5$i$K!"<u?.<T$NL>A0$+\e(B @acronym{NNTP} \e$B%0%k!<%W$KEj9F$7$?%0%k!<%WL>$G\e(B
+\e$B%f!<%6L>$rCV$-49$($k$?$a$K!"\e(B@code{gnus-extra-headers}\e$B!"\e(B
+@code{nnmail-extra-headers} \e$B$*$h$S\e(B @code{gnus-ignored-from-addresses} \e$B$N\e(B
+\e$B%G%U%)%k%HCM$,JQ$o$j$^$7$?!#\e(B
+
+@item
+@file{deuglify.el} (@code{gnus-article-outlook-deuglify-article})
+
+\e$B$$$+$l$?\e(B Outlook (Express) \e$B$N5-;v$r=9$/$J$/$9$k$?$a$N!"\e(BRaymond Scholz
+@email{rscholz@@zonix.de} \e$B$K$h$C$F?7@_$5$l$?%U%!%$%k$G$9!#\e(B
+
+@item
+@code{(require 'gnus-load)}
+
+\e$BC1FH$GG[I[$5$l$F$$$k\e(B Gnus \e$B$r;H$&>l9g$K$O!"\e(B
+@code{load-path} \e$B$K\e(B Gnus \e$B$N\e(B lisp \e$B%G%#%l%/%H%j$rDI2C$7$F$+$i!"\e(B
+@file{~/.emacs} \e$B$K\e(B @code{(require 'gnus-load)} \e$B$r2C$($k$N$,NI$$$G$9!#\e(B
+
+\e$B%U%!%$%k\e(B @file{gnus-load.el} \e$B$O!"$=$N$&$A$N$$$/$D$+$O\e(B Emacsen \e$B$NG[I[$KF~$C\e(B
+\e$B$F$$$J$$$+$b$7$l$J$$<+F0FI$_9~$_\e(B (autoload) \e$B%3%^%s%I!"4X?t$*$h$SJQ?t$r4^\e(B
+\e$B$s$G$$$^$9!#\e(B
+
+@item
+@code{gnus-slave-unplugged}
+
+\e$B%*%U%i%$%s$N\e(B Gnus \e$B$r%9%l!<%V%b!<%I$G5/F0$9$k?7$7$$%3%^%s%I$G$9!#\e(B
+
+@item
+@code{message-insinuate-rmail}
+
+@code{(message-insinuate-rmail)} \e$B$H\e(B @code{(setq mail-user-agent
+'gnus-user-agent)} \e$B$r\e(B @file{.emacs} \e$B$K2C$($k$3$H$G!"\e(B
+@code{message-mode} \e$B$G%a%C%;!<%8$N:n@.!"JV?.$*$h$SE>Aw$r9T$J$&$h$&\e(B
+\e$B$K\e(B Rmail \e$B$r@bF@$9$k$3$H$,$G$-$^$9!#$=$3$G$O\e(B @acronym{MML} \e$B$N0RNO$r4.G=$G\e(B
+\e$B$-$^$9!#\e(B
+
+@item
+@code{message-minibuffer-local-map}
+
+\e$B2<$N9T$G!"%a%C%;!<%8$r:FAw$9$k$H$-$K\e(B BBDB \e$B$,;H$($^$9\e(B:
+@lisp
+(define-key message-minibuffer-local-map [(tab)]
+  'bbdb-complete-name)
+@end lisp
+
+@item
+\e$BE:IU%U%!%$%k\e(B (attachments) \e$B$N@Z$jN%$7\e(B (externalizing) \e$B$H>C5n!#\e(B
+
+@code{gnus-gcc-externalize-attachments} \e$B$^$?\e(B
+\e$B$O\e(B @code{message-fcc-externalize-attachments} \e$B$,Hs\e(B-@code{nil} \e$B$K$J$C$F$$\e(B
+\e$B$k$H!"%m!<%+%k%U%!%$%k$r30It%Q!<%H$H$7$FE:IU$7$^$9!#\e(B
+
+@code{gnus-mime-save-part-and-strip} \e$B%3%^%s%I\e(B (@acronym{MIME} \e$B%\%?%s>e\e(B
+\e$B$G\e(B @kbd{C-o} \e$B$K3d$jEv$F$i$l$F$$$k\e(B) \e$B$O!"%Q!<%H$r%;!<%V$7$F$+$i30It$N$=$l\e(B
+\e$B$HCV$-49$($^$9!#\e(B@code{gnus-mime-delete-part} (@acronym{MIME} \e$B%\%?%s>e\e(B
+\e$B$G\e(B @kbd{d} \e$B$K3d$jEv$F$i$l$F$$$k\e(B) \e$B$O!"%Q!<%H$r:o=|$7$^$9!#$3$l$OJT=8$r%5\e(B
+\e$B%]!<%H$7$F$$$k%P%C%/%(%s%I$G$@$1F0:n$7$^$9!#\e(B
+
+@item
+@code{gnus-default-charset}
+
+\e$B%G%U%)%k%HCM$O\e(B @code{iso-8859-1} \e$B$KBe$o$C\e(B
+\e$B$F\e(B @code{current-language-environment} \e$BJQ?t$K$h$C$F7hDj$5$l$kCM$K$J$j$^\e(B
+\e$B$9!#$^$?!"\e(B@code{gnus-group-charset-alist} \e$B$K$"$C$?\e(B @samp{.*} \e$B$N9`L\$O:o\e(B
+\e$B=|$5$l$^$7$?!#\e(B
+
+@item
+@code{gnus-posting-styles}
+
+\e$B$3$N$h$&$J9gCW$NMM<0$,2C$o$j$^$7$?!#\e(B
+@lisp
+((header "to" "larsi.*org")
+ (Organization "Somewhere, Inc."))
+@end lisp
+\e$B2<5-$N$h$&$J8E$$MM<0$O;~BeCY$l$K$J$j$^$7$?$,!"$^$@<u$1F~$l$i$l$^$9!#\e(B
+@lisp
+(header "to" "larsi.*org"
+        (Organization "Somewhere, Inc."))
+@end lisp
+
+@item
+@code{message-ignored-news-headers} \e$B$H\e(B @code{message-ignored-mail-headers}
+
+@samp{X-Draft-From} \e$B$H\e(B @samp{X-Gnus-Agent-Meta-Information} \e$B$,!"$3$l$iFs\e(B
+\e$B$D$NJQ?t$K2C$($i$l$F$$$^$9!#$=$l$i$r%+%9%?%^%$%:$9$k>l9g$K!"$b$7$+$9$k$H\e(B
+\e$B$=$l$iFs$D$N%X%C%@!<$r2C$($kI,MW$,$"$j$^$9!#\e(B
+
+@item
+Gnus \e$B$O:9$79~$^$l$F$$$k\e(B (@dfn{plugged}) \e$B$H$-$K!"%(!<%8%'%s%H$+\e(B
+\e$B$i\e(B @acronym{NOV} \e$B$H5-;v$rFI$_9~$_$^$9!#\e(B
+
+\e$B:9$79~$^$l$F$$$k$H$-$K5-;v$rFI$`>l9g$K!"$=$N5-;v$,$9$G$K%(!<%8%'%s%H$K$"\e(B
+\e$B$k$J$i$P!"$b$&0lEY%@%&%s%m!<%I$9$k$3$H$O$"$j$^$;$s!#\e(B@code{(setq
+gnus-agent-cache nil)} \e$B$O5l<0$NF0:n$KLa$7$^$9!#\e(B
+
+@item
+Gnus \e$B$O\e(B ``format=flowed'' (RFC 2646) \e$B%Q%i%a!<%?$r%5%]!<%H$7$^$9!#%a%C%;!<\e(B
+\e$B%8$r:n@.$9$k$H$-$K!"$=$l$O\e(B @code{use-hard-newlines} \e$B$G3h@-2=$5$l$^$9!#\e(B
+format=flowed \e$B$N%G%3!<%I$O0JA0$+$i$G$-$^$7$?$,!"=i4|$NHG$G$O@bL@$NJ8=q$,\e(B
+\e$B$"$j$^$;$s$G$7$?!#\e(B
+
+@item
+Gnus \e$B$O\e(B RFC 2298 \e$B$N3+Iu3NG'MW5a$N@8@.$r%5%]!<%H$7$^$9!#\e(B
+
+\e$B$3$l$O%a%C%;!<%8%b!<%I$N\e(B @kbd{C-c M-n} \e$B%-!<$G5/F0$5$l$^$9!#\e(B
+
+@item
+Gnus \e$B$O\e(B Maildir \e$B%0%k!<%W$r%5%]!<%H$7$^$9!#\e(B
+
+Gnus \e$B$O?7%P%C%/%(%s%I$G$"$k\e(B @file{nnmaildir.el} \e$B$r4^$s$G$$$^$9!#\e(B
+@xref{Maildir}.
+
+@item
+\e$B0u:~$N@-G=$,8~>e$7$^$7$?!#\e(B
+
+Gnus \e$B$O$=$l<+?H$,!"35N,$H5-;v%P%C%U%!$K$*$1$k\e(B @kbd{O P} \e$B$G\e(B Muttprint \e$B$r\e(B
+\e$B%5%]!<%H$7$^$9!#$5$i$K\e(B @acronym{MIME} \e$B%\%?%s>e$G\e(B @kbd{p} \e$B$r;H$&$3$H$K$h$C\e(B
+\e$B$F!"8D!9$N\e(B @acronym{MIME} \e$B%Q!<%H$N$=$l$>$l$r0u:~$9$k$3$H$,$G$-$^$9!#\e(B
+
+@item
+Message \e$B$O\e(B Importance: \e$B%X%C%@!<\e(B (RFC 2156) \e$B$r%5%]!<%H$9$k$h$&$K$J$j$^$7\e(B
+\e$B$?!#\e(B
+
+\e$B%a%C%;!<%8%P%C%U%!$G\e(B @kbd{C-c C-f C-i} \e$B$+\e(B @kbd{C-c C-u} \e$B$r;H$&$H!"2DG=$J\e(B
+\e$BCM$,=[4D$7$^$9!#\e(B
+
+@item
+Gnus \e$B$O%K%e!<%9$N\e(B Cancel Locks \e$B$r%5%]!<%H$7$^$9!#\e(B
+
+\e$BEj9F$9$k%K%e!<%95-;v$K\e(B @samp{Cancel-Lock} \e$B%X%C%@!<$,A^F~$5$l$k$3$H$G$9!#\e(B
+\e$B$3$l$O!"5-;v$r$"$J$?$,=q$$$?$N$+$I$&$+$r3N$+$a$k$?$a$K;H$$$^$9\e(B (\e$B%-%c%s%;\e(B
+\e$B%k$HCV$-49$($N$H$-\e(B)\e$B!#:G=i$K5-;v$rEj9F$9$k$H$-$K!"\e(BGnus \e$B$O%i%s%@%`$J%Q%9%o!<\e(B
+\e$B%IJ8;zNs$r@8@.$7!"%+%9%?%`$N5!9=$r;H$C$F\e(B @file{~/.emacs} \e$B$K%;!<%V$7$^$9!#\e(B
+\e$B$=$NJQ?t$O\e(B @code{canlock-password} \e$B$H8F$P$l$^$9$,!"5!L)$r5$$K$9$k%G!<%?\e(B
+\e$B$G$O$"$j$^$;$s!#%&%'%V>e$G\e(B canlock \e$B$r8x3+$7$F$b!"0JA0$+$iH`=w$,$G$-$J$+$C\e(B
+\e$B$?2?$+$r!"C/$+$,$G$-$k$h$&$K$9$k$b$N$G$O$"$j$^$;$s!#\e(B
+@code{message-insert-canlock} \e$B$r%+%9%?%^%$%:$9$k$3$H$K$h$C$F!"?6$kIq$$$r\e(B
+\e$BJQ99$9$k$,$G$-$^$9!#\e(B
+
+@item
+Gnus \e$B$O\e(B Sieve \e$B$r;H$C$?%5!<%P!<B&$G$N%a!<%k$N_I2a$r%5%]!<%H$7$^$9!#\e(B
+
+Sieve \e$B$N5,B'$O%0%k!<%W%Q%i%a!<%?$H$7$F2C$($k$3$H$,$G$-!"%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{D g} \e$B$r;H$&$H40A4$J\e(B Sieve \e$B%9%/%j%W%H$,@8@.$5$l$^$9!#$=$&$7$?$i!"\e(B
+\e$B@8@.$5$l$?\e(B Sieve \e$B%P%C%U%!$G\e(B @kbd{C-c C-l} \e$B$r;H$C$F!"%5!<%P!<$K%"%C%W%m!<\e(B
+\e$B%I$7$F2<$5$$!#\e(B@ref{Sieve Commands}\e$B!"$=$l$K?7$7$$\e(B Sieve \e$B$N%^%K%e%"\e(B
+\e$B%k\e(B (@pxref{Top, , Top, sieve, Emacs Sieve}) \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item
+\e$B3HD%$5$l$?%U%)!<%^%C%H$N;EMM\e(B (format specs)\e$B!#\e(B
+
+\e$B%U%)!<%^%C%H$N;E\e(B
+\e$BMM\e(B @samp{%&user-date;} \e$B$,\e(B @code{gnus-summary-line-format-alist} \e$B$KDI2C$5\e(B
+\e$B$l$^$7$?!#$=$l$K!"%f!<%6Dj5A$K$h$k3HD%$5$l$?%U%)!<%^%C%H$N;EMM$b%5%]!<%H\e(B
+\e$B$5$l$F$$$^$9!#3HD%$5$l$?%U%)!<%^%C%H$N;EMM$O\e(B @samp{%u&foo;} \e$B$N$h$&$J$b$N\e(B
+\e$B$G!"4X?t\e(B @code{gnus-user-format-function-@var{foo}} \e$B$r5/F0$7$^$9!#\e(B
+@samp{&} \e$B$,%(%9%1!<%WJ8;z$K;H$o$l$F$$$k$N$G!"8E$$%f!<%6Dj5A%U%)!<%^%C%H\e(B
+\e$B$G$"$k\e(B @samp{%u&} \e$B$O:#$d%5%]!<%H$5$l$F$$$^$;$s!#\e(B
+
+@item
+@kbd{/ *} (@code{gnus-summary-limit-include-cached}) \e$B$,=q$-D>$5$l$^$7$?!#\e(B
+
+\e$B$3$l$O\e(B @kbd{Y c} (@code{gnus-summary-insert-cached-articles}) \e$B$NJLL>$G$7\e(B
+\e$B$?\e(B (\e$BLuCm\e(B: \e$B0JA0$O\e(B)\e$B!#?7$7$$4X?t$OB>$N5-;v$r_I2a$7$F=|5n$7$^$9!#\e(B
+
+@item
+\e$B$$$/$D$+$N%3%^%s%I$O\e(B @kbd{C-u} \e$B@\F,<-$G9gCW$NH]Dj$r07$&$3$H$,$G$-$^$9!#\e(B
+
+@kbd{C-u} \e$B$r\e(B subject\e$B!"\e(Bauthor \e$B$^$?$O\e(B extra \e$B%X%C%@!<$r$3$N=g$K;H$&\e(B -- \e$B$9$J\e(B
+\e$B$o$A\e(B @kbd{/ s}\e$B!"\e(B@kbd{/ a} \e$B$*$h\e(B
+\e$B$S\e(B @kbd{/ x} (@code{gnus-summary-limit-to-@{subject,author,extra@}})
+-- \e$B$H!"7k2L$H$7$F$=$NI=8=$K9gCW$7$J$$$9$Y$F$N5-;v$,I=<($5$l$^$9!#\e(B
+
+@item
+\e$B%0%k!<%WL>$O!"%G%#%U%)%k%H$G\e(B UTF-8 \e$B$G$"$k$b$N$H$7$F<h$j07$o$l$^$9!#\e(B
+
+\e$B$3$l$O\e(B USEFOR \e$B$,0\9T$7$h$&$H$7$F$$$k$HA[Dj$5$l$k$b$N$G$9!#%+%9%?%^%$%:$9\e(B
+\e$B$k$K$O\e(B @code{gnus-group-name-charset-group-alist} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-group-name-charset-method-alist} \e$B$r;2>H$7$F2<$5$$!#\e(B
+
+@item
+nnml \e$B$H\e(B nnfolder \e$B%P%C%/%(%s%I$O!"%0%k!<%WKh$K0u\e(B (marks) \e$B$r3JG<$9$k$h$&$K\e(B
+\e$B$J$j$^$7$?!#\e(B
+
+\e$B$3$l$O\e(B nnml/nnfolder \e$B%5!<%P!<\e(B/\e$B%0%k!<%W\e(B \e$B$r\e(B @file{~/.newsrc.eld} \e$B$H@Z$jN%\e(B
+\e$B$7$F!"$7$+$70u$O<i$j$D$D!"%P%C%/%"%C%W$9$k$3$H$r2DG=$K$7$^$9!#$5$i$K!"Nc\e(B
+\e$B$($P8&5f<<$d?&>l$J$I$NAH?%Fb$G!"\e(B(@file{~/.newsrc.eld} \e$B%U%!%$%k$r6&M-$9$k\e(B
+\e$B$3$HL5$7$K\e(B) \e$B%f!<%64V$G5-;v$H0u$r6&M-$9$k$3$H$r$b2DG=$K$7$^$9!#$3$l$O!"\e(B
+@file{~/.newsrc.eld} \e$B$K3JG<$5$l$k0u$r!"%0%k!<%WKh$N\e(B @file{.marks} \e$B%U%!%$\e(B
+\e$B%k\e(B (nnml \e$BMQ\e(B) \e$B$H\e(B @file{@var{groupname}.mrk} \e$B%U%!%$%k\e(B (@var{groupname} \e$B$N\e(B
+\e$BL>A0$r;}$D\e(B nnfolder \e$BMQ\e(B) \e$B$K3JG<$9$k$3$H$K$h$C$FF0:n$7$^$9!#\e(B
+nnml/nnfolder \e$B$rB>$N%^%7%s$K0z$C1[$7$F$b!"\e(B
+Gnus \e$B$O\e(B @file{~/.newsrc.eld} \e$B$K$"$k>pJs$NBe$o$j$K!"<+F0E*\e(B
+\e$B$K\e(B @file{.marks} \e$B$+\e(B @file{.mrk} \e$B%U%!%$%k$r;H$$$^$9!#?7$7$$%5!<%P!<JQ?t$G\e(B
+\e$B$"$k\e(B @code{nnml-marks-is-evil} \e$B$H\e(B @code{nnfolder-marks-is-evil} \e$B$,!"$3$N\e(B
+\e$B5!G=$rM^@)$9$k$?$a$K;H$&$3$H$,$G$-$^$9!#\e(B
+
+@item
+\e$B%0%k!<%W$H35N,%P%C%U%!$N%a%K%e!<9`L\$NL>A0\e(B ``Misc'' \e$B$O\e(B ``Gnus'' \e$B$K2~L>$5\e(B
+\e$B$l$^$7$?!#\e(B
+
+@item
+Message mode \e$B$G\e(B ``@acronym{MML}'' \e$B$HL>IU$1$i$l$?%a%K%e!<9`L\$O!"\e(B
+``Attachments'' \e$B$K2~L>$5$l$^$7$?!#$3$N%a%K%e!<$O!"=pL>$H0E9f\e(B
+\e$B2=\e(B (@pxref{Security, Security,, message-ja, Message Manual}) \e$B$N$h$&$J!"\e(B
+\e$BJ]0B$K4XO"$7$?$b$N$b4^$s$G$$$k$3$H$KCeL\$7$F2<$5$$!#\e(B
+
+@item
+@code{gnus-group-charset-alist} \e$B$H\e(B @code{gnus-group-ignored-charsets-alist}\e$B!#\e(B
+
+\e$B$3$l$i$NJQ?t$K@_Dj$5$l$?@55,I=8=$O!"40A4$J\e(B (full) \e$B%0%k!<%WL>$HHf3S$5$l$^\e(B
+\e$B$9!#\e(BGnus 5.8 \e$B$G$O<B:]$N\e(B (real) \e$B%0%k!<%WL>$,Hf3S$NBP>]$G$7$?!#$7$?$,$C$F!"\e(B
+\e$B$3$l$i$NJQ?t$r%+%9%?%^%$%:$7$F$$$k%f!<%6$O!"@55,I=8=$rJQ99$7$J$1$l$P$J$j\e(B
+\e$B$^$;$s!#Nc$G$9\e(B:
+@lisp
+("^han\\>" euc-kr) -> ("\\(^\\|:\\)han\\>" euc-kr)
+@end lisp
+
+@item
+Gnus \e$B$O\e(B @acronym{PGP} (RFC 1991/2440)\e$B!"\e(B@acronym{PGP/MIME} (RFC
+2015/3156) \e$B$*$h$S\e(B @acronym{S/MIME} (RFC 2630-2633) \e$B$r%5%]!<%H$7$^$9!#\e(B
+
+\e$B$3$l$K$O\e(B @acronym{S/MIME} \e$B$H\e(B OpenPGP \e$B$,<BAu$5$l$F$$$kI,MW$,$"$j$^$9!#$G\e(B
+\e$B$bDI2C$N\e(B Lisp \e$B%i%$%V%i%j$OMW$j$^$;$s!#%a%C%;!<%8$N:n@.;~$K!"$$$/$D$+$N%a\e(B
+\e$B%K%e!<$H\e(B @kbd{C-c RET} \e$B%-!<$N3d$jEv$F$,\e(B Attachments \e$B%a%K%e!<$KDI2C$5$l$^\e(B
+\e$B$9!#$3$l$O$^$?!"\e(B@code{gnus-article-hide-pgp-hook} \e$B$r;~BeCY$l$K$7$^$7$?!#\e(B
+
+@item
+Gnus \e$B$O30It%Q!<%H\e(B (message/external) \e$B$r%$%s%i%$%sI=<($7$^$9!#\e(B
+
+@item
+@acronym{MML} (Mime \e$B:n@.\e(B) \e$B%3%^%s%I$N@\F,%-!<$,!"\e(B@kbd{M-m} \e$B$+$i\e(B @kbd{C-c
+C-m} \e$B$KJQ$o$j$^$7$?!#\e(B
+
+\e$B$3$NJQ99$K$h$C$F!"I8=`%-!<3d$jEv$F$N\e(B @code{back-to-indentation} \e$B$H$N>WFM\e(B
+\e$B$,2sHr$5$l$^$7$?!#$3$N%3%^%s%I$b$^$?!"%a%C%;!<%8%b!<%I$G$OLr$KN)$D$N$G$9!#\e(B
+
+@item
+@code{message-forward-show-mml} \e$B$N%G%#%U%)%k%H$,\e(B @code{best} \e$B$KJQ$o$j$^\e(B
+\e$B$7$?!#\e(B
+
+\e$BCM\e(B @code{best} \e$B$N?6$kIq$$$O!"$=$l$,$U$5$o$7$$>l9g$O\e(B @acronym{MML} \e$B$rI=<(\e(B
+\e$B$9$k\e(B (\e$B$9$J$o$A\e(B @acronym{MIME} \e$B$KJQ49$9$k\e(B) \e$B$3$H$G$9!#JQ49$,%G%#%8%?%k=pL>\e(B
+\e$B$rL58z$K$7$F$7$^$&$N$G!"=pL>$5$l$?!"$^$?$O0E9f2=$5$l$?%a%C%;!<%8$rE>Aw$9\e(B
+\e$B$k$H$-$O\e(B @acronym{MML} \e$B$O;H$o$l$^$;$s!#\e(B
+@end itemize
+
+@iftex
+
+@page
+@node The Manual
+@section \e$B%^%K%e%"%k\e(B
+@cindex colophon
+@cindex manual
+
+\e$B$3$N%^%K%e%"%k$O\e(B TeXinfo \e$B%U%!%$%k$+$i:n@.$5$l!"$=$l$+\e(B
+\e$B$i\e(B @code{texi2dvi}
+@iflatex
+\e$B$b$7$/$O!"\e(BLars \e$B$5$s$N:n$i$l$?\e(B Texinfo to \LaTeX \e$BJQ49$rDL$j!"$=$l$+$i!"\e(B
+@code{latex} \e$B$H\e(B @code{dvips}
+@end iflatex
+\e$B$r<B9T$7$F!"<j85$K$"$k$b$K$J$j$^$7$?!#\e(B
+
+\e$B0J2<$N=,47$,MQ$$$i$l$^$7$?\e(B:
+
+@enumerate
+\e$B$3$l$O\e(B @kbd{\e$B%-!<BG80\e(B} \e$B$G$9!#\e(B
+
+@item
+\e$B$3$l$O\e(B @file{\e$B%U%!%$%k\e(B} \e$B$G$9!#\e(B
+
+@item
+\e$B$3$l$O\e(B @code{\e$B%7%s%\%k\e(B} \e$B$G$9!#\e(B
+
+@end enumerate
+
+\e$B$G$9$+$i!";d$,\e(B ``@code{flargnoze} \e$B$r\e(B @samp{yes} \e$B$K@_Dj$9$k\e(B'' \e$B$H8@$C$?$H\e(B
+\e$B$-$O!"<!$N$h$&$J0UL#$G$9\e(B:
+
+@lisp
+(setq flargnoze "yes")
+@end lisp
+
+\e$B$b$7!";d$,\e(B ``@code{flargnoze} \e$B$r\e(B @code{yes} \e$B$K@_Dj$9$k\e(B'' \e$B$H8@$C$?$H$-$O!"\e(B
+\e$B<!$N$h$&$J0UL#$G$9\e(B:
+
+@lisp
+(setq flumphel 'yes)
+@end lisp
+
+@samp{yes} \e$B$H\e(B @code{yes} \e$B$OFs$D$N\e(B @emph{\e$BA4$/\e(B} \e$B0c$C$?$b$N$G$9\e(B---\e$B@dBP$K:.\e(B
+\e$BF1$7$J$$$G$/$@$5$$!#\e(B
+
+@iflatex
+@c @head
+\e$B$b$A$m$s!"$3$N%^%K%e%"%k$NA4$F$O=EBg$J6=L#$N$"$k$3$H$G$9$N$G!"$"$J$?$OA4\e(B
+\e$B$FFI$`$Y$-$G$9!#2?EY$b!#$7$+$7!"%^%K%e%"%k$r<P$aFI$_$7$?$$$N$G$"$l$P!"$=\e(B
+\e$B$3$N%^!<%8%s$K$"$k%L!<$NF,$r8+$k$Y$-$G$7$g$&\e(B---\e$B$=$l$O$=$3$G5DO@$5$l$F$$\e(B
+\e$B$k$N$,;D$j$N$b$N$h$j=EMW$G$"$k$H$$$&$3$H$G$9!#\e(B(\e$B0lJ}!"A4$F$,L58B$K=EMW$N\e(B
+\e$B$G$"$l$P!"$I$&$9$l$P$=$l$h$j$b$C$H=EMW$J$b$N$,$G$-$k$N$G$7$g$&\e(B? \e$B$3$N@$3&\e(B
+\e$B$N!"IT;W5D$N0l$D$G$7$g$&!"$?$V$s!#\e(B)
+@end iflatex
+
+@end iftex
+
+@node On Writing Manuals
+@section \e$B%^%K%e%"%k$r=q$/\e(B
+
+\e$B$*$=$i$/!"$?$$$F$$$N%^%K%e%"%k$O;v<B$N8e$G=q$+$l$F$$$k$H;W$$$^$9!#$9$G$K\e(B
+\e$B$"$k%W%m%0%i%`$rJ8=q2=$7$F$$$^$9!#$3$N%^%K%e%"%k$O$=$&$$$&J}K!$G=q$+$l$F\e(B
+\e$B$$$^$;$s!#2?$+$r<BAu$9$k$H$-$O!"2?$+$r$=$N$^$^%^%K%e%"%k$N0l@a$K=q$-$^$9!#\e(B
+\e$B$=$l$+$i5!G=$N@bL@$,Fq$7$$$3$H$rH/8+$7$F!"$=$l$,$I$N$h$&$K$"$k$Y$-$G$"$k\e(B
+\e$B$+$r=q$-!"$=$l$+$i<BAu$rJQ99$7$^$9!#J8=q$H%3!<%I$r=q$/$N$O0l=o$K9T$J$o$l\e(B
+\e$B$F$$$-$^$9!#\e(B
+
+\e$B$b$A$m$s!"$3$l$O$3$N%^%K%e%"%k$K$ON.$l9=B$$,$[$H$s$IL5$$$+!"$"$C$F$b>/$7\e(B
+\e$B$@$H$$$&$3$H$G$9!#\e(Bgnus \e$B$N40A4$KA4$F$N$3$H$,@bL@$5$l$F$$$^$9$,!"C5$7$F$$\e(B
+\e$B$k>l=j$G$O$J$$$H$$$&$3$H$,$h$/$"$j$^$9!#$3$l$O%j%U%!%l%s%9%^%K%e%"%k$G$"\e(B
+\e$B$j!"\e(Bgnus \e$B$r;O$a$k$?$a$N<j0z$-$G$O$"$j$^$;$s!#\e(B
+
+\e$B$=$l$O$^$C$?$/0c$C$?K\$K$J$j!"$3$N%j%U%!%l%s%9%^%K%e%"%k$r85$H$7$F;H$C$F\e(B
+\e$B=q$+$l$?$b$N$K$J$k$G$7$g$&!#$H$F$b0c$C$?$b$N$K$J$k$O$:$G$9!#\e(B
+
+@page
+@node Terminology
+@section \e$BMQ8l\e(B
+
+@cindex terminology
+
+@table @dfn
+@item \e$B%K%e!<%9\e(B (news)
+@cindex news
+\e$B$3$l$O$"$J$?$,$=$N$?$a$K$3$N$b$N$r;H$$$?$$$H;W$C$F$$$k$b$N$G$9\e(B---\e$B%K%e!<\e(B
+\e$B%9$rFI$`;v$G$9!#%K%e!<%9$O0lHLE*$K$O6a$/$N\e(B @acronym{NNTP} \e$B%5!<%P!<$+$i<h\e(B
+\e$BF@$5$l!"IaDL$OA4$F$N?M$K9-$/MxMQ2DG=$J$b$N$G$9!#$b$7%K%e!<%9$rEj9F$9$l$P!"\e(B
+\e$BA4@$3&$,$"$J$?$,$A$g$&$I=q$$$?$b$N$rFI$`2DG=@-$,$"$j!"$=$l$i$OA4$F$$$?$:\e(B
+\e$B$i$C$]$/%/%9%/%9>P$o$l$k$G$7$g$&!#$"$J$?$NCN$i$J$$$H$3$m$G!#\e(B
+
+@item \e$B%a!<%k\e(B (mail)
+@cindex mail
+\e$B$"$J$?$K8D?ME*$KG[Aw$5$l$k$b$NA4$F$,%a!<%k$G$9!#$$$/$D$+$N%K%e!<%9\e(B/\e$B%a!<\e(B
+\e$B%k%j!<%@!<\e(B (gnus \e$B$N$h$&$J\e(B) \e$B$O%a!<%k$H%K%e!<%9$N0c$$$r$\$d$1$5$;$^$9$,!"\e(B
+\e$B$=$3$K$O0c$$$OB8:_$7$^$9!#%a!<%k$O;dE*$G$9!#%K%e!<%9$O8xE*$G$9!#%a!<%k$r\e(B
+\e$BAw?.$9$k;v$OEj9F$G$O$J$/!"JV?.$O%U%)%m!<%"%C%W$G$O$"$j$^$;$s!#\e(B
+
+@item \e$BJV?.\e(B (reply)
+@cindex reply
+\e$B$"$J$?$,FI$s$G$$$k$b$N$r=q$$$??M$K%a!<%k$rAw$k;v$G$9!#\e(B
+
+@item \e$B%U%)%m!<%"%C%W\e(B (follow up)
+@cindex follow up
+\e$B$"$J$?$,FI$s$G$$$k5-;v$K1~Ez$7$F8=:_$N%K%e!<%9%0%k!<%W$K5-;v$rEj9F$9$k;v\e(B
+\e$B$G$9!#\e(B
+
+@item \e$B%P%C%/%(%s%I\e(B (back end)
+@cindex back end
+gnus \e$B$O%a!<%k$H%K%e!<%9$,$[$H$s$IF1$8$@$H$_$J$7$^$9!#K\Ev$K!#0c$$$O<B:]\e(B
+\e$B$N5-;v$K$I$N$h$&$K%"%/%;%9$9$k$+$@$1$G$9!#%a!<%k%a%C%;!<%8$O%m!<%+%k%G%#\e(B
+\e$B%9%/$N%U%!%$%k$+$iFI$a$k$N$KBP$7$F!"%K%e!<%95-;v$O0lHL\e(B
+\e$B$K\e(B @acronym{NNTP} \e$B%W%m%H%3%k$G<hF@$7$^$9!#\e(Bgnus \e$B$NFbIt9=B$$O!"$=$l$i$N$?\e(B
+\e$B$a$K\e(B ``\e$B%U%m%s%H%(%s%I\e(B'' \e$B$H?t!9$N\e(B ``\e$B%P%C%/%(%s%I\e(B'' \e$B$+$i@.$jN)$C$F$$$^$9!#\e(B
+\e$BFbItE*$K!"$"$J$?$,%0%k!<%W$KF~$k\e(B (\e$B$=$&!"\e(B@key{RET} \e$B$r$?$?$/\e(B) \e$B$H$-!"$=$N$?\e(B
+\e$B$a$K\e(B gnus \e$B$N%U%m%s%H%(%s%I$N5!G=$r8F$S=P$7$^$9!#%U%m%s%H%(%s%I$O$=$3$G%P%C\e(B
+\e$B%/%(%s%I$K!V\e(Bfoo \e$B%0%k!<%W$N5-;v$N%j%9%H$r$/$l!W$H$+!V\e(B4711 \e$BHV$N5-;v$r8+$;\e(B
+\e$B$F$h!W$H\e(B ``\e$BOC$9\e(B'' \e$B$N$G$9!#\e(B
+
+\e$B$=$&$$$&$o$1$G!"%P%C%/%(%s%I$O<g$K%W%m%H%3%k$+!"%U%!%$%k$N7A<0$H%G%#%l%/\e(B
+\e$B%H%j$NG[CV$rDj5A$7$^$9!#A0<T$O\e(B @code{nntp} \e$B%P%C%/%(%s%I\e(B
+\e$B$,\e(B @acronym{NNTP} \e$B$G%K%e!<%9$K%"%/%;%9$7$?$j\e(B @code{nnimap} \e$B%P%C%/%(%s%I\e(B
+\e$B$,\e(B @acronym{IMAP} \e$B$G%a!<%k$K%"%/%;%9$9$k$3$H$r;X$7$^$9!#$^$?!"8e<T\e(B
+\e$B$O\e(B @code{nnspool} \e$B%P%C%/%(%s%I$,6&DL$N\e(B ``\e$B%9%W!<%k%G%#%l%/%H%j\e(B'' \e$B7A<0$K%"\e(B
+\e$B%/%;%9$7$?$j!"$=$l$H$H$F$b$h$/;w$?\e(B @code{nnml} \e$B%P%C%/%(%s%I$,%U%!%$%k$N\e(B
+\e$B7A<0$H%G%#%l%/%H%j$NG[CV$K$h$C$F%a!<%k$K%"%/%;%9$9$k$3$H$r;X$7$^$9!#\e(B
+
+gnus \e$B$O4pK\E*$J%a%G%#%"$r07$$$^$;$s!#$9$Y$F$O%P%C%/%(%s%I$K$h$C$F9T$J$o\e(B
+\e$B$l$k$H8@$&$3$H$,$G$-$^$9!#%P%C%/%(%s%I$O5-;v$K%"%/%;%9$9$k$?$a$N5!G=$N=8\e(B
+\e$B@.$G$9!#\e(B
+
+\e$B$7$+$7!"\e(B``\e$B%P%C%/%(%s%I\e(B'' \e$B$H$$$&MQ8l$O$7$P$7$P\e(B ``\e$B%5!<%P!<\e(B'' \e$B$H$$$&0UL#$G\e(B
+\e$B$b;H$o$l$F$-$^$7$?!#$=$7$F\e(B ``\e$BA*BrJ}K!\e(B'' (``select method'') \e$B$bF1$80UL#$G\e(B
+\e$B;H$&$3$H$,$G$-$^$9!#$+$h$&$K!"\e(Bgnus \e$B$NMQ8l$O$H$F$b:.Mp$7$F$$$^$9!#\e(B
+
+@item \e$B4pK\\e(B (native)
+@cindex native
+Gnus \e$B$O$$$D$b0l$D$NJ}K!\e(B (\e$B$H%P%C%/%(%s%I\e(B) \e$B$r%K%e!<%9$rF@$k$?$a$N\e(B @dfn{\e$B4p\e(B
+\e$BK\\e(B} \e$B$b$7$/$O=i4|@_Dj$H$7$F;H$$$^$9!#\e(B
+
+@item \e$B30It\e(B (foreign)
+@cindex foreign
+\e$BF1;~$KG$0U$N?t$N30It%0%k!<%W$r3hF0>uBV$K$9$k$3$H$b$G$-$^$9!#$3$l$i$O%K%e!<\e(B
+\e$B%9$r<hF@$9$k$?$a$N!"4pK\$G$J$/!"FsHVL\$G$b$J$$%P%C%/%(%s%I$r;H$&%0%k!<%W\e(B
+\e$B$G$9!#\e(B
+
+@item \e$BFsHVL\\e(B (secondary)
+@cindex secondary
+\e$BFsHVL\$N%P%C%/%(%s%I$O!"4pK\$H30It$N4V$/$i$$$K$"$k%P%C%/%(%s%I$G!"$[$H$s\e(B
+\e$B$I4pK\$HF1$8$h$&$KF0:n$9$k$b$N$G$9!#\e(B
+
+@item \e$B5-;v\e(B (article)
+@cindex article
+\e$B%K%e!<%9$H$7$FEj9F$5$l$?%a%C%;!<%8$G$9!#\e(B
+
+@item \e$B%a!<%k%a%C%;!<%8\e(B (mail message)
+@cindex mail message
+\e$B%a!<%k$GAw$i$l$?%a%C%;!<%8$G$9!#\e(B
+
+@item \e$B%a%C%;!<%8\e(B
+@cindex message
+\e$B%a!<%k%a%C%;!<%8$b$7$/$O%K%e!<%95-;v$G$9!#\e(B
+
+@item \e$B%X%C%I\e(B (head)
+\e$B%a%C%;!<%8$N:G>eIt$G!"G'>Z>pJs\e(B (\e$BEy\e(B) \e$B$,F~$l$i$l$F$$$k$H$3$m$G$9!#\e(B
+
+@item \e$BK\BN\e(B (body)
+@cindex body
+\e$B5-;v$N;D$j$NItJ,$G$9!#%X%C%I$G$J$$$b$N$O$9$Y$FK\BN$G$9!#\e(B
+
+@item \e$B%X%C%@!<\e(B (header)
+@cindex header
+\e$B5-;v$N%X%C%I$+$i$N9T$G$9!#\e(B
+
+@item \e$B%X%C%@!<72\e(B (headers)
+@cindex headers
+\e$B$=$N$h$&$J9T$N=89g$b$7$/$O!"%X%C%I$N=89g$G$9!#$b$7$/$O!"\e(B@acronym{NOV} \e$B9T\e(B
+\e$B$N=89g$G$9!#\e(B
+
+@item @acronym{NOV}
+@cindex @acronym{NOV}
+Gnus \e$B$,%0%k!<%W$KF~$k$H!"%0%k!<%W$NA4$F$NL$FI5-;v$N%X%C%@!<$r%P%C%/%(%s\e(B
+\e$B%I$K5a$a$^$9!#$[$H$s$I$N%5!<%P!<$O\e(B News OverView \e$BMM<0$,;HMQ2DG=$G!"$=$l\e(B
+\e$B$OIaDL$N\e(B @sc{head} \e$BMM<0$h$j$b$C$H<jC;$G$b$C$HB.$/FI$s$G2r@O\e(B (parse) \e$B$9$k\e(B
+\e$B$3$H$,$G$-$^$9!#\e(B
+
+@item \e$B%l%Y%k\e(B (level)
+@cindex levels
+\e$B$=$l$>$l$N%0%k!<%W$O2?$i$+$N\e(B @dfn{\e$B%l%Y%k\e(B} \e$B$+B>$N$b$N\e(B (1-9) \e$B$G9XFI$5$l$F\e(B
+\e$B$$$^$9!#Dc$$%l%Y%k$N$b$N$O9b$$%l%Y%k$N$b$N$h$j\e(B ``\e$B$h$j\e(B'' \e$B9XFI$5$l$F$$$^$9!#\e(B
+\e$B<B:]$N$H$3$m!"%l%Y%k\e(B 1-5 \e$B$N%0%k!<%W$O\e(B @dfn{\e$B9XFI\e(B}; 6-7 \e$B$O\e(B @dfn{\e$BL$9X\e(B
+\e$BFI\e(B}; 8 \e$B$O\e(B @dfn{\e$B%>%s%S\e(B}; 9 \e$B$O\e(B @dfn{\e$B@Z$i$l$?\e(B} \e$B$H8+$J$5$l$^$9!#%0%k!<%W$r%j\e(B
+\e$B%9%H$7$?$j!"?7$7$$%0%k!<%W$rAv::$7$?$j$9$kL?Na$O$9$Y$F?tCM@\F,0z?t\e(B
+\e$B$r\e(B @dfn{\e$BF0:n%l%Y%k\e(B} \e$B$H$7$F;H$$$^$9!#\e(B
+
+@item \e$B@Z$i$l$?%0%k!<%W\e(B (killed groups)
+@cindex killed groups
+\e$B@Z$i$l$?%0%k!<%W$N>pJs$OC_@Q$5$l$?$j99?7$5$l$?$j$7$^$;$s$N$G!"@Z$i$l$?%0\e(B
+\e$B%k!<%W$r9XFI$5$l$?%0%k!<%W$h$j4JC1$K07$($k$h$&$K$J$j$^$9!#\e(B
+
+@item \e$B%>%s%S%0%k!<%W\e(B (zombie groups)
+@cindex zombie groups
+\e$B$[$H$s$I@Z$i$l$?%0%k!<%W$HF1$8$G!"$=$l$h$j>/$7;`$s$G$$$k$@$1$G$9!#\e(B
+
+@item \e$B%"%/%F%#%V%U%!%$%k\e(B (active file)
+@cindex active file
+\e$B%K%e!<%9%5!<%P!<$O$I$N5-;v$r1?$s$G$$$k$+!"$I$N%0%k!<%W$,B8:_$9$k$+$r5-O?\e(B
+\e$B$7$F$*$+$J$1$l$P$J$j$^$;$s!#A4$F$N$3$N>pJs$O8=>u%U%!%$%k$KC_@Q$5$l!"$=$l\e(B
+\e$B$O$"$J$?$,A[A|$9$k$h$&$KHf3SE*Bg$-$$$G$9!#\e(B
+
+@item \e$B56%0%k!<%W\e(B (bogus groups)
+@cindex bogus groups
+\e$B%U%!%$%k\e(B @file{.newsrc} \e$B$KB8:_$9$k%0%k!<%W$G$9$,!"%5!<%P!<$KCN$i$l$F$$$J\e(B
+\e$B$$%0%k!<%W\e(B (\e$B$9$J$o$A!"$=$l$O%"%/%F%#%V%U%!%$%k$K$"$j$^$;$s\e(B) \e$B$O\e(B @emph{\e$B56\e(B
+\e$B%0%k!<%W\e(B} \e$B$G$9!#$3$l$O!"$*$=$i$/\e(B (\e$B$9$G$K\e(B) \e$B$=$N%0%k!<%W$OB8:_$7$F$$$J$$$N\e(B
+\e$B$G$7$g$&!#\e(B
+
+@item \e$B3hF02=\e(B (activating)
+@cindex activating groups
+\e$B%5!<%P!<$K%0%k!<%W$N>pJs$r?R$M!"L$FI5-;v$N?t$r1i;;$9$k9T0Y$O\e(B @dfn{\e$B%0%k!<\e(B
+\e$B%W$r3hF02=$9$k\e(B} \e$B$H8F$P$l$F$$$^$9!#Hs3hF0%0%k!<%W$O%0%k!<%W%P%C%U%!\e(B
+\e$B$K\e(B @samp{*} \e$B$H$H$b$K0lMwI=<($5$l$^$9!#\e(B
+
+@item \e$B%5!<%P!<\e(B (server)
+@cindex server
+\e$B@\B3$7$F!"%K%e!<%9\e(B (\e$B$b$7$/$O%a!<%k\e(B) \e$B$r<hF@$9$k;v$N$G$-$k%0%k!<%W$G$9!#\e(B
+
+@item \e$BA*BrJ}K!\e(B (select method)
+@cindex select method
+\e$B%P%C%/%(%s%I!"%5!<%P!<$H!";v<B>e$N%5!<%P!<@_Dj$r;XDj$9$k9=B$$G$9!#\e(B
+
+@item \e$B;v<B>e$N%5!<%P!<\e(B (virtual server)
+@cindex virtual server
+\e$BL?L>$5$l$?A*BrJ}K!$G$9!#A*BrJ}K!$O\e(B (\e$BJ*M}E*\e(B) \e$B%5!<%P!<$K@\B3$9$k$?$a$KI,MW\e(B
+\e$B$JJ}K!$rDj5A$9$k$?$a!"J*;v$rA4BN$H$7$F<u$1$k$N$O;v<B>e$N%5!<%P!<$K$J$j$^\e(B
+\e$B$9!#\e(B
+
+@item \e$B@vBu\e(B (washing)
+@cindex washing
+\e$B%P%C%U%!$r;}$C$F$-$F!"2?$i$+$N<oN`$NA*JL5!$K$+$1$k;v$G$9!#7k2L$O\e(B (\e$BB?$+$l\e(B
+\e$B>/$J$+$l\e(B) \e$B85$N$b$N$h$j$b$h$j$-$l$$$G4n$P$7$$$b$N$K$J$k$G$7$g$&!#\e(B
+
+@item \e$B0l;~%0%k!<%W\e(B (ephemeral groups)
+@cindex ephemeral groups
+@cindex temporary groups
+\e$B$?$$$F$$$N%0%k!<%W$O$I$N5-;v$rFI$s$@$+$N%G!<%?$rC_@Q$7$^$9!#\e(B
+@dfn{\e$B0l;~\e(B} \e$B%0%k!<%W$O%G!<%?$,N/$a$i$l$J$$%0%k!<%W$G$9\e(B---\e$B%0%k!<%W$r=P$k$H!"\e(B
+\e$B$=$l$OE76u$K>C$(5n$j$^$9!#\e(B
+
+@item \e$B8GDj%0%k!<%W\e(B (solid groups)
+@cindex solid groups
+\e$B$3$l$O0l;~%0%k!<%W$NH?BP$G$9!#%0%k!<%W%P%C%U%!$K5s$2$i$l$F$$$kA4$F$N%0%k!<\e(B
+\e$B%W$O8GDj%0%k!<%W$G$9!#\e(B
+
+@item \e$B$^$P$i5-;v\e(B (sparse articles)
+@cindex sparse articles
+@code{gnus-build-sparse-threads} \e$B$N5!G=$r;HMQ$7$F$$$k$H$-$O!"35N,%P%C%U%!\e(B
+\e$B$K5-;v$NF~$l>l=j$,I=<($5$l$^$9!#\e(B
+
+@item \e$B%9%l%C%I:n$j\e(B (threading)
+@cindex threading
+\e$B$=$l$,1~Ez$7$?5-;v$ND>8e$K$=$N5-;v$X$N1~Ez$rCV$/$3$H$G$9\e(B---\e$B3,AXE*N.57$G!#\e(B
+
+@item \e$B:,\e(B (root)
+@cindex root
+@cindex thread root
+\e$B%9%l%C%I$N:G=i$N5-;v$,:,$G$9!#$=$l$O%9%l%C%I$NA4$F$N5-;v$NAD@h$G$9!#\e(B
+
+@item \e$B?F\e(B (parent)
+@cindex parent
+\e$B1~Ez$N$"$k5-;v$G$9!#\e(B
+
+@item \e$B;R\e(B (child)
+@cindex child
+\e$B0c$C$?5-;v\e(B---\e$B$=$N?F\e(B \e$B$K1~Ez$9$k5-;v$G$9!#\e(B
+
+@item \e$B=8G[\e(B (digest)
+@cindex digest
+\e$BJ#?t$N%a%C%;!<%8$r0l$D$N%U%!%$%k$K=8$a$?$b$N$G$9!#$b$C$H$bIaDL$N=8G[MM<0\e(B
+\e$B$O\e(B RFC1153 \e$B$G;XDj$5$l$F$$$^$9!#\e(B
+
+@item \e$BJ,3d\e(B (splitting)
+@cindex splitting, terminolgy
+@cindex mail sorting
+@cindex mail filtering (splitting)
+\e$B$"$k5,B'$K$h$C$F%a!<%k$rJ,N`$9$k9T0Y$G$9!#$H$-$I$-4V0c$C$F%a!<%k$N_I\e(B
+\e$B2a\e(B (mail filtering) \e$B$H8F$P$l$^$9!#\e(B
+@end table
+
+@page
+@node Customization
+@section \e$B%+%9%?%^%$%:\e(B
+@cindex gerenal customization
+
+\e$BA4$F$NJQ?t$O$3$N%^%K%e%"%k$N$I$3$+JL$N$H$3$m$GE,@Z$K@bL@$5$l$F$$$^$9!#$3\e(B
+\e$B$NItJ,$OHs>o$KNI$/$"$k>u67$G$I$N$h$&$K\e(B gnus \e$B$r%+%9%?%^%$%:$9$l$PNI$$$+$N\e(B
+\e$BAm9gE,;X<(@h$rM?$($k$?$a$K9M0F$5$l$F$$$^$9!#\e(B
+
+@menu
+* Slow/Expensive Connection::   \e$B%m!<%+%k$N\e(B Emacs \e$B$rN)$A>e$2$F!"B>$N$H$3$m$+$i%K%e!<%9$rF@$k;v$,$G$-$k\e(B
+* Slow Terminal Connection::    \e$B1s3V\e(B Emacs \e$B$r<B9T$9$k\e(B
+* Little Disk Space::           \e$BBg$-$J5/F0%U%!%$%k$r;}$D;v$O$^$:$$\e(B
+* Slow Machine::                \e$BB.$$5!3#$rGc$*$&$H46$8$k$G$"$m$&\e(B
+@end menu
+
+@node Slow/Expensive Connection
+@subsection \e$BCY$$\e(B/\e$B9b$$\e(B NNTP \e$B@\B3\e(B
+
+\e$B$b$7\e(B Emacs \e$B$r%m!<%+%k$N%^%7%s$G<B9T$7$F$$$F!"Hs>o$K:Y$$@~$N8~$3$&$N%^%7\e(B
+\e$B%s$+$i%K%e!<%9$r<hF@$7$F$$$k$N$G$"$l$P!"\e(Bgnus \e$B$,\e(B @acronym{NNTP} \e$B%5!<%P!<\e(B
+\e$B$+$i<hF@$9$k%G!<%?$NAmNL$r8:$i$7$?$$$H;W$&$G$7$g$&!#\e(B
+
+@table @code
+@item gnus-read-activie-file
+\e$B$3$l$r\e(B @code{nil} \e$B$K$7$F2<$5$$!#$=$&$9$l$P!"\e(Bgnus \e$B$K%5!<%P!<$+$i%"%/%F%#\e(B
+\e$B%V%U%!%$%kA4BN$rMW5a$9$k;v$r6X;_$G$-$^$9!#$3$N%U%!%$%k$O$7$P$7$PHs>o$KBg\e(B
+\e$B$-$/$J$C$F$$$^$9!#$=$l$K2C$($F!"\e(Bgnus \e$B$,FMA3$H$K$+$/8=>u%U%!%$%k$r<hF@$7\e(B
+\e$B$h$&$H7hDj$7$J$$;v$r3N<B$K$9$k$?$a$K!"\e(B
+@code{gnus-check-new-newsgroups} \e$B$H\e(B @code{gnus-check-bogus-newsgroups} \e$B$b\e(B @code{nil} \e$B$K\e(B
+\e$B@_Dj$7$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item gnus-nov-is-evil
+\e$B$3$l$b\e(B @code{nil} \e$B$K$7$F$$$J$1$l$P$J$j$^$;$s!#$b$7$=$&$G$J$1$l$P!"\e(B
+@acronym{NNTP} \e$B%5!<%P!<$+$i5-;v$N%X%C%@!<$r$D$+$s$G$/$k$N$,$"$^$jB.$/$J\e(B
+\e$B$j$^$;$s!#A4$F$N\e(B @acronym{NNTP} \e$B%5!<%P!<$,\e(B @sc{xover} \e$B$N5!G=$rDs6!$7$F$$\e(B
+\e$B$k$o$1$G$O$"$j$^$;$s!#\e(Bgnus \e$B$,<+J,<+?H$G$=$l$r8!::$7$^$9!#\e(B
+@end table
+
+@node Slow Terminal Connection
+@subsection \e$BCY$$%?!<%_%J%k@\B3!#\e(B
+
+\e$B$"$J$?$O!"%[!<%`%3%s%T%e!<%?!<$r\e(B Emacs \e$B$H\e(B gnus \e$B$r<B9T$7$F$$$k%7%9%F%`$K\e(B
+\e$B%@%$%"%k%"%C%W$9$k$?$a$K;H$C$F$$$k$H$7$^$7$g$&!#$b$7$"$J$?$N%b%G%`$,CY$1\e(B
+\e$B$l$P!"\e(B(\e$B2DG=$J8B$j\e(B) \e$B@~$rEA$C$FAw$i$l$F$$$k%G!<%?$NAmNL$r8:$i$7$?$$$H;W$&\e(B
+\e$B$G$7$g$&!#\e(B
+
+@table @code
+@item gnus-auto-center-summary
+Gnus \e$B$,>o$K35N,%P%C%U%!$rCf?4:F@_Dj$r$9$k$3$H$r6X;_$9$k$?$a$K$3$l\e(B
+\e$B$r\e(B @code{nil} \e$B$K@_Dj$7$F2<$5$$!#$3$l$,\e(B @code{vertical} \e$B$G$"$k$H!"?bD>J}\e(B
+\e$B8~$N\e(B (vertical) \e$BCf?4:F@_Dj$N$_$r$7$^$9!#\e(B@code{nil} \e$B$G\e(B
+\e$B$b\e(B @code{vertical} \e$B$G$bL5$1$l$P!"?eJ?J}8~$H?bD>J}8~$NN>J}$NCf?4:F@_Dj$r\e(B
+\e$B9T$$$^$9!#\e(B
+
+@item gnus-visible-headers
+\e$B5-;v$K4^$^$l$k%X%C%@!<$r:G>.8B$K8:$i$7$^$9!#<B:]$N$H$3$m!"A4It$J$/$7$F$7\e(B
+\e$B$^$C$F$b2?$H$+$J$j$^$9\e(B---\e$B$H$K$+$/!"$?$$$F$$$NLr$KN)$D%G!<%?$O35N,%P%C%U%!\e(B
+\e$B$K$"$j$^$9!#$3$NJQ?t$r\e(B @samp{^NEVVVVER} \e$B$d\e(B @samp{From:} \e$B$d!"2?$G$b9%$-$J\e(B
+\e$B$b$N$K@_Dj$7$F2<$5$$!#\e(B
+
+\e$B$3$N%U%C%/$KA4$F$N;HMQ2DG=$J1#F?L?Na$r@_Dj$7$^$9\e(B:
+@lisp
+(setq gnus-treat-hide-headers 'head
+      gnus-treat-hide-signature t
+      gnus-treat-hide-citation t)
+@end lisp
+
+@item gnus-use-full-window
+\e$B$3$l$r\e(B @code{nil} \e$B$K@_Dj$9$k;v$G!"A4$F$N%&%#%s%I%&$r>.$5$/$9$k;v$,$G$-$^\e(B
+\e$B$9!#$3$l$OAm$8$F$=$s$J$K8:$i$7$^$;$s!#$3$l$O!"5-;v$r$I$C$A$K$7$mFI$_$?$/\e(B
+\e$B$J$$$H$$$&;v$r7hDj$9$kA0$K!">/$7$NItJ,$7$+8+$kI,MW$,L5$$$H$$$&;v$G$9!#\e(B
+
+@item gnus-thread-hide-subtree
+\e$B$3$l$,\e(B @code{nil} \e$B$G$J$1$l$P!"A4$F$N35N,%P%C%U%!$N%9%l%C%I$O=i$a$K1#$5$l\e(B
+\e$B$^$9!#\e(B
+
+@item gnus-updated-mode-lines
+\e$B$3$l$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O%P%C%U%!$N%b!<%I9T$K>pJs$rF~$l$^$;$s\e(B
+\e$B$N$G!";~4V$r@aLs$G$-$k$G$7$g$&!#\e(B
+@end table
+
+@node Little Disk Space
+@subsection \e$B>/$7$N%G%#%9%/MFNL\e(B
+@cindex disk space
+
+\e$B5/F0%U%!%$%k$OHf3SE*Bg$-$/$J$k$N$G!"6u$-MFNL$,>/$J$/$J$C$F$-$F$$$k$H$-$O\e(B
+\e$B$=$NBg$-$5$r>/$7>.$5$/$9$kI,MW$,$"$k$G$7$g$&!#\e(B
+
+@table @code
+@item gnus-save-newsrc-file
+\e$B$3$l$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O7h$7$F\e(B @file{.newsrc} \e$B$rJ]B8$7$^$;\e(B
+\e$B$s\e(B---\e$B$=$l$O\e(B @file{.newsrc.eld} \e$B$N$_$rJ]B8$7$^$9!#$3$l$O!"\e(Bgnus \e$B$NB>$N%K%e!<\e(B
+\e$B%9%j!<%@!<$r;H$($J$$$H$$$&;v$G$9!#$3$NJQ?t$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-read-newsrc-file
+\e$B$3$l$,\e(B @code{nil} \e$B$G$"$l$P!"\e(Bgnus \e$B$O\e(B @file{.newsrc} \e$B$r7h$7$FFI$_$^$;\e(B
+\e$B$s\e(B ---@file{.newsrc.eld} \e$B$@$1$rFI$_$^$9!#$3$l$O!"\e(Bgnus \e$B0J30$N%K%e!<%9%j!<\e(B
+\e$B%@!<$r;H$($J$/$J$k!"$H$$$&$3$H$G$9!#$3$NJQ?t$O=i4|@_Dj$G$O\e(B @code{t} \e$B$G$9!#\e(B
+
+@item gnus-save-killed-list
+\e$B$3$l$,\e(B @code{nil} \e$B$G$"$k$H!"\e(Bgnus \e$B$O;`$s$@%0%k!<%W$N%j%9%H$rJ]B8$7$^$;$s!#\e(B
+\e$B$3$NJQ?t$r\e(B @code{nil} \e$B$K@_Dj$7$?$H$-$O!"\e(B
+@code{gnus-check-new-newsgroups} \e$B$r\e(B @code{ask-server} \e$B$K!"\e(B
+@code{gnus-check-bogus-newsgroups} \e$B$r\e(B @code{nil} \e$B$K@_Dj$9$k$Y$-$G$7$g$&!#\e(B
+\e$B$3$NJQ?t$O=i4|@_Dj$G\e(B @code{t} \e$B$G$9!#\e(B
+@end table
+
+@node Slow Machine
+@subsection \e$BCY$$5!3#\e(B
+@cindex slow machine
+
+\e$B$b$7CY$$5!3#$r;}$C$F$$$k$+!"$b$7$/$OC1$KK\Ev$KG&BQNO$,$J$$;~$O!"\e(Bgnus \e$B$N\e(B
+\e$B<B9T$rGD0.$9$k$?$a$K$G$-$k;v$,>/$7$"$j$^$9!#\e(B
+
+\e$B5/F0$rB.$/$9$k$?$a$K\e(B @code{gnus-check-new-newsgroups} \e$B$*$h\e(B
+\e$B$S\e(B @code{gnus-check-bogus-newsgroups} \e$B$r\e(B @code{nil} \e$B$K@_Dj$7$F2<$5$$!#35\e(B
+\e$BN,%P%C%U%!$KF~$k;v$HH4$1$k;v$rB.$/$9$k$?$a\e(B
+\e$B$K\e(B @code{gnus-show-threads} \e$B$H\e(B @code{gnus-use-cross-reference}\e$B!"$=$l\e(B
+\e$B$K\e(B @code{gnus-nov-is-evil} \e$B$r\e(B @code{nil} \e$B$K@_Dj$7$F2<$5$$!#\e(B
+
+@page
+@node Troubleshooting
+@section \e$BLdBj2r7h\e(B
+@cindex troubleshooting
+
+Gnus \e$B$OH"$+$i=P$7$F$9$0$K\e(B @emph{\e$BHs>o$K\e(B} \e$B$h$/F0:n$7$^$9\e(B---\e$B2?$bLdBj$N5/$3\e(B
+\e$B$k$3$H$OA[A|$G$-$^$;$s!"K\Ev$K!#\e(B
+
+\e$B%*%C%[%s!#\e(B
+
+@enumerate
+
+@item
+\e$B$"$J$?$N%3%s%T%e!<%?$N%9%$%C%A$,F~$C$F$$$k;v$r3N$+$a$F2<$5$$!#\e(B
+
+@item
+\e$BK\Ev$K8=9T$N\e(B gnus \e$BHG$rFI$_9~$s$G$$$k;v$r3NG'$7$F2<$5$$!#:#$^\e(B
+\e$B$G\e(B @sc{gnus} \e$B$r<B9T$7$F$-$?$N$G$"$l$P!"\e(Bgnus \e$B$,F0:n$9$k$h$&$K0l\e(B
+\e$BEY\e(B Emacs \e$B$r=*N;$7$F:F5/F0$9$kI,MW$,$"$j$^$9!#\e(B
+
+@item
+@kbd{M-x gnus-version} \e$B$r;n$7$F2<$5$$!#$b$7!"\e(B
+@samp{T-gnus 6.16.* (based on Gnus v5.10.*; for SEMI 1.1*, FLIM
+1.1*)} \e$B$N$h$&$J$b$N$,=P$F$-$?$J$i!"@5$7$$%U%!%$%k$,FI$_9~$^$l$F$$$^$9!#\e(B
+\e$B$=$&$J$i$J$$>l9g$O!"8E$$\e(B @file{.el} \e$B%U%!%$%k$,;6$i$+$C$F$$$^$9!#$=$l$i$r\e(B
+\e$B>C$7$F2<$5$$!#\e(B
+
+@item
+@acronym{FAQ} \e$B$H\e(B how-to \e$B$rFI$`$?$a$K%X%k%W%0%k!<%W\e(B (\e$B%0%k!<%W%P%C%U%!\e(B
+\e$B$G\e(B @kbd{G h}) \e$B$rFI$s$G2<$5$$!#\e(B
+
+@item
+@vindex max-lisp-eval-depth
+Gnus \e$B$OB?$/$NB?$/$N:F5"9=B$$GF0:n$7!"2?$i$+$N6KC<$J\e(B (\e$B$=$7$FHs>o$K$^$l\e(B
+\e$B$J\e(B) \e$B;vNc$G$O!"\e(Bgnus \e$B$O:F5"$r\e(B ``\e$B$"$^$j$K?<$/\e(B'' \e$B9_$j$9$.$F!"\e(BEmacs \e$B$,$"$J$?\e(B
+\e$B$K%S!<%W2;$rLD$i$9;v$,$"$j$^$9!#$b$7$3$l$,5/$3$C$?$J$i!"\e(B
+@code{max-lisp-eval-depth} \e$B$r\e(B 500 \e$B$+$=$l$/$i$$$NCM$K@_Dj$7$F2<$5$$!#\e(B
+@end enumerate
+
+\e$B$b$7B>$NA4$F$,<:GT$7$?$J$i!"%P%0$H$7$FLdBj$rJs9p$7$F2<$5$$!#\e(B
+
+@cindex bugs
+@cindex reporting bugs
+
+@kindex M-x gnus-bug
+@findex gnus-bug
+\e$B$b$7\e(B gnus \e$B$N%P%0$r8+$D$1$?$J$i!"L?Na\e(B @kbd{M-x gnus-bug} \e$B$K$h$C$F$=$l$rJs\e(B
+\e$B9p$9$k;v$,$G$-$^$9!#\e(B
+@kbd{M-x set-variable RET debug-on-error RET t RET} \e$B$H$7$F!"$=$l$+$i;d$K\e(B
+\e$B%P%C%/%H%l!<%9$rAw$C$F2<$5$$!#;d$O%P%0$r=$@5$7$h$&$H$7$^$9$,!"$"$J$?$,%P\e(B
+\e$B%0$r:F8=$5$;$kJ}K!$r@53N$K=q$$$F$/$l$?$H$-$N$_!"$=$l$r=$@5$9$k;v$,$G$-$^\e(B
+\e$B$9!#\e(B
+
+\e$B%P%0Js9p$G$O!">\:Y$9$.$k$3$H$O7h$7$F$"$j$^$;$s!#%P%0Js9p$r$9$k$H$-$O!"$$\e(B
+\e$B$D$b\e(B @kbd{M-x gnus-bug} \e$BL?Na$r;H$C$F2<$5$$!#$=$l$r;H$&$?$S$K\e(B 10Kb \e$B$N%a!<\e(B
+\e$B%k$,$G$-$F$7$^$C$F$b!"$=$7$F$"$J$?$N4D6-$r0JA0;d$K\e(B 500 \e$B2sAw$C$?$H$7$F$b\e(B
+\e$B$G$9!#\e(B
+
+\e$B;d$O!"5-21$H$$$&<oN`$N$b$N$OA4$/;}$C$F$$$J$$;v$r3P$($F$*$/;v$b=EMW$G$9!#\e(B
+\e$B$b$7$"$J$?$,%P%0Js9p$rAw$k$H!";d$,JVEz$rAw$j$^$9!#$=$7$F!"$=$l$+$i$"$J$?\e(B
+\e$B$,\e(B ``\e$B$$$d!"$=$&$G$O$J$$\e(B! \e$B$3$N$P$+<T\e(B!'' \e$B$H$@$1Aw$jJV$7$F$/$k$H!";d$O$"$J\e(B
+\e$B$?$,2?$KBP$7$F;d$rIn?+$7$F$$$k$+$,$o$+$j$^$;$s!#>o$K!"A4$F$r@bL@$7$9$.$F\e(B
+\e$B2<$5$$!#$=$l$O2f!9A4$F$K$H$C$F$b$C$H4JC1$K$J$j$^$9\e(B---\e$B$b$7;d$,I,MW$JA4$F\e(B
+\e$B$N>pJs$rF@$i$l$J$+$C$?$i!";d$O$"$J$?$K%a!<%k$rAw$C$F$5$i$J$k>pJs$r5a$a!"\e(B
+\e$B$=$N7k2LA4$F$,$h$jB?$/$N;~4V$r<h$k;v$K$J$j$^$9!#\e(B
+
+\e$B$b$7$"$J$?$ND>LL$7$F$$$kLdBj$,Hs>o$K;k3PE*$G!"$=$l$r>e<j$/@bL@$G$-$J$$>l\e(B
+\e$B9g$O!"\e(BEmacs \e$B$N%&%#%s%I%&$r%U%!%$%k$K%3%T!<$7$F\e(B (\e$BNc$($P!"\e(B@kbd{xwd} \e$B$G\e(B)\e$B!"\e(B
+\e$B$=$l$r$I$3$+<j$NFO$/$I$3$+$K$*$$$F!"$=$N2hA|$N\e(B URL \e$B$r%P%0Js9p$K4^$a$F2<\e(B
+\e$B$5$$!#\e(B
+
+@cindex patches
+\e$B$b$7$"$J$?$,%P%0$N=$@5$d2~A1$N$?$a$N%Q%C%A$r4s9F$7$F2<$5$k$N$G$7$?$i!"$9\e(B
+\e$B$_$^$;$s$,$=$N%Q%C%A$O\e(B @samp{diff -u} \e$B$G:n$C$F2<$5$$!#\e(B
+
+@cindex edebug
+\e$BLdBj$rJs9p$9$kA0$K$b$C$H%G%P%C%0$7$?$1$l$P!"$"$J$?<+?H$GLdBj$r2r7h$7$F%Q%C\e(B
+\e$B%A$rAw$k$?$a$K\e(B edebug \e$B$r;H$&$3$H$,$G$-$k$G$7$g$&!#\e(BLisp \e$B%3!<%I$N%G%P%C%0\e(B
+\e$B$K$D$$$F$O\e(B Elisp \e$B%^%K%e%"%k\e(B (@pxref{Debugging, , Debugging Lisp
+Programs, elisp, The GNU Emacs Lisp Reference Manual}) \e$B$K=q$+$l$F$$$^$9!#\e(B
+edebug \e$B$r;O$a$k$K$O!"$b$7\e(B @kbd{c} \e$B$r2!$7$?$H$-$K$"$kJQ$J?6Iq$$$,H/8+$5$l\e(B
+\e$B$k$J$i$P!"Bh0lJb$O\e(B @kbd{C-h k c} \e$B$r%?%$%W$7!"%I%-%e%a%s%F!<%7%g%s!&%P%C\e(B
+\e$B%U%!!<Cf$G%O%$%Q!<%j%s%/$r%/%j%C%/\e(B (Emacs\e$B$N$_\e(B) \e$B$7$F!"$=$N4X?tDj5A$r;2>H\e(B
+\e$B$9$k$3$H$G$9!#$=$7$F$=$N4X?tL>$N>l=j$G\e(B @kbd{M-x edebug-defun RET} \e$B$r%?%$\e(B
+\e$B%W$7$F\e(B gnus \e$B$KLa$j!"$=$N%3!<%I$r5/F0$9$k$?$a$K\e(B @kbd{c} \e$B$r2!$7$^$9!#\e(B
+Lisp \e$B%P%C%U%!!<$G$O!"\e(B@kbd{SPC} \e$B$G%7%s%0%k%9%F%C%WF0:n!"\e(B@kbd{M-:} \e$B$G<0$r\e(B
+\e$BI>2A!"\e(B@kbd{C-h v} \e$B$GJQ?t$r8!::!"\e(B@kbd{q} \e$B$G<B9T$rCfCG!"$"$k$$\e(B
+\e$B$O\e(B @kbd{c} \e$B$+\e(B @kbd{g} \e$B$G<B9T$r:F3+$9$k$3$H$,$G$-$^$9!#\e(B
+
+@cindex elp
+@cindex profile
+@cindex slow
+\e$B$H$-$I$-!"D>@\$K\e(B elisp \e$B$N%(%i!<$r5/$3$5$J$$$b$N$N!"\e(Bgnus \e$B$,Hs>o$KCY$/$J$k\e(B
+\e$B$?$a$KL@$i$+$K$J$kLdBj$,$"$j$^$9!#$=$s$J>l9g$K$O\e(B @kbd{M-x
+toggle-debug-on-quit} \e$B$r;H$C$F!"CY$/$J$C$?$H$-$K\e(B @kbd{C-g} \e$B$r2!$7!"$7$+\e(B
+\e$B$k8e$K%P%C%/%H%l!<%9$r2r@O$7$F2<$5$$\e(B (\e$B$=$N<jB3$-$r7+$jJV$9$3$H$O!"??$NLd\e(B
+\e$BBjNN0h$NJ,N%$KLrN)$A$^$9\e(B)\e$B!#$h$j>eEy$J<h$jAH$_$O\e(B elisp \e$B%W%m%U%!%$%i!<\e(B (\e$BLu\e(B
+\e$BCm\e(B: \e$B%W%m%0%i%`$N<B9T;~$NF0$-$rJ,@O$9$kF;6q\e(B) ELP \e$B$r;HMQ$9$k$3$H$G$9!#%W%m\e(B
+\e$B%U%!%$%i!<$K$D$$$F$O$I$3$+B>$N>l=j$G40A4$KJ8=q2=$5$l$F$$$k$O$:$G$9$,!"$=\e(B
+\e$B$l$r;O$a$k$?$a$KI,MW$J<j=g$r>/!9=q$$$F$*$-$^$7$g$&!#Bh0l$K!"%W%m%U%!%$%k\e(B
+\e$B$7$F$_$?$$\e(B gnus \e$B$NItJ,$r7WB,$9$k$?$a$N@_Dj$r!"Nc$($P\e(B @kbd{M-x
+elp-instrument-package RET gnus} \e$B$d\e(B @kbd{M-x elp-instrument-package RET
+message} \e$B$G9T$J$C$F2<$5$$!#$=$7$F!"CY$$F0:n$r9T$J$o$;$F$+$i\e(B @kbd{M-x
+elp-results} \e$B$r2!$7$^$7$g$&!#$9$k$H!"$I$NF0:n$,;~4V$r?)$C$F$$$k$+$r8+$F!"\e(B
+\e$B8e$G$=$l$i$r%G%P%C%0$9$k$3$H$,$G$-$^$9!#F0:nA4BN$,!"%W%m%U%!%$%i!<$N=PNO\e(B
+\e$B$NCf$G:G$bCY$$4X?t$GHq$d$5$l$?;~4V$h$j$O$k$+$KD9$/$+$+$k$N$O!"$?$V\e(B
+\e$B$s\e(B gnus \e$B$N4V0c$C$F$$$kItJ,$r%W%m%U%!%$%k$7$?$;$$$G$7$g$&!#%W%m%U%!%$%k$N\e(B
+\e$BE}7W$r%j%;%C%H$9$k$K$O\e(B @kbd{M-x elp-reset-all} \e$B$r;H$C$F2<$5$$!#\e(B@kbd{M-x
+elp-restore-all} \e$B$O%W%m%U%!%$%k$9$kF0:n$r<h$j=|$/$3$H$K$J$C$F$$$^$9$,!"\e(B
+gnus \e$B$K$h$C$FJ#;($K$5$l$+$DF0E*$J%3!<%I@8@.$N1F6A$r<u$1$k$?$a!"$=$l$OI,\e(B
+\e$B$:$7$b40A4$KF0:n$9$k$H$O8B$i$J$$$+$b$7$l$^$;$s!#\e(B
+
+\e$B$b$71g=u$,M_$7$$$@$1$G$"$l$P!"\e(B@samp{gnu.emacs.gnus} \e$B$G?R$M$k$N$,NI$$$G$7$g\e(B
+\e$B$&!#;d$O$"$^$jLr$KN)$A$^$;$s!#\e(B
+
+@cindex gnu.emacs.gnus
+@cindex ding mailing list
+\e$B$^$?!"\e(Bding \e$B%a!<%j%s%0%j%9%H\e(B---@email{ding@@gnus.org} \e$B$K?V$M$k;v$b$G$-$^\e(B
+\e$B$9!#9XFI$9$k$?$a$K$O\e(B @email{ding-request@@gnus.org} \e$B$K=q$$$F2<$5$$!#\e(B
+
+@page
+@node Gnus Reference Guide
+@section Gnus \e$B$N;2>H%,%$%I\e(B
+
+\e$B;d$N4j$$$O!"B>$NC/$+$,\e(B gnus \e$B$G$G$-$k2?$+8-$$$b$N$r9M$(=P$7!"$=$N>e$=$N8-\e(B
+\e$B$$$b$N$r=q$$$F$/$l$k$H$$$&$3$H$G$9!#$3$l$rMF0W$K$9$k$?$a$K$O!"\e(Bgnus \e$B$NFb\e(B
+\e$BItF0:n$r5-=R$9$k$N$,NI$$J}K!$@$m$&$H;d$O;W$$$^$7$?!#$"$H!"$=$s$J$KFbIt$8$c\e(B
+\e$B$J$$F0:n$r$$$/$D$+$H!";d$,:#$d$C$F$k$3$H$H!#\e(B
+
+\e$B%W%m%0%i%`$NFbIt9=B$$,JQ99$5$l$k$3$H$O$J$$!"$J$I$H;W$C$F$O$$$1$^$;$s$,!"\e(B
+gnus \e$B$H$=$N%P%C%/%(%s%I4V$N%$%s%?!<%U%'!<%9\e(B (\e$B$3$l$O40A4$K5-=R$5$l$F$$\e(B
+\e$B$k\e(B) \e$B$d!"%9%3%"%U%!%$%k$N7A<0\e(B (\e$B$3$l$bF1MM\e(B)\e$B!"%G!<%?9=B$\e(B (\e$B$3$l$OB>$h$jJQ99\e(B
+\e$B$5$l$d$9$$$b$N$b$"$k\e(B)\e$B!"A`:nMQ$N0lHL%a%=%C%I!"$J$I$r\e(B (\e$B:YIt$K$o$?$C$F\e(B) \e$BDj\e(B
+\e$B5A$7$F$$$-$^$9!#\e(B
+
+@menu
+* Gnus Utility Functions::      \e$B;HMQ$G$-$k6&DL$N4X?t$HJQ?t\e(B
+* Back End Interface::          Gnus \e$B$O$I$&$d$C$F%5!<%P!<$HDL?.$9$k$N$+\e(B
+* Score File Syntax::           \e$B%9%3%"%U%!%$%k5,3J$N\e(B BNF \e$BDj5A\e(B
+* Headers::                     Gnus \e$B$O%X%C%@!<$rFbItE*$K$I$N$h$&$K3JG<$9$k$+\e(B
+* Ranges::                      \e$B$?$/$5$s$N?t$r3JG<$9$kJXMx$J7A<0\e(B
+* Group Info::                  \e$B%0%k!<%W>pJs7A<0\e(B
+* Extended Interactive::        \e$B5-9f@\F,<-$J$I\e(B
+* Emacs/XEmacs Code::           Gnus \e$B$OA4$F$N6aBe\e(B Emacsen \e$B$GF0:n$9$k\e(B
+* Various File Formats::        Gnus \e$B$N;HMQ$9$k%U%!%$%k$N7A<0\e(B
+@end menu
+
+@node Gnus Utility Functions
+@subsection Gnus \e$B$NM-MQ$J4X?t\e(B
+@cindex Gnus utility functions
+@cindex utility functions
+@cindex functions
+@cindex internal variables
+
+\e$B%U%C%/$J$I$+$i<B9T$5$l$k>.$5$J4X?t$r=q$/$H$-$O!"\e(Bgnus \e$B$NFbIt4X?t\e(B
+\e$B$dJQ?t$K%"%/%;%9$9$k$3$H$O@dBPI,MW$G$9!#0J2<$,:G$b$h$/;H$o$l$k$b\e(B
+\e$B$N$N0lMw$G$9!#\e(B
+
+@table @code
+@item gnus-newsgroup-name
+@vindex gnus-newsgroup-name
+\e$B$3$NJQ?t$O8=:_$N%K%e!<%9%0%k!<%W$NL>A0$rJ];}$7$F$$$^$9!#\e(B
+
+@item gnus-find-method-for-group
+@findex gnus-find-method-for-group
+@var{group} \e$B$NA*BrJ}K!$rJV$94X?t$G$9!#\e(B
+
+@item gnus-group-real-name
+@findex gnus-group-real-name
+\e$B@55,$N\e(B (\e$B@\F,<-IU$-$N\e(B) gnus \e$B%0%k!<%WL>$r<u$1<h$j!"@\F,<-L5$7$NL>A0\e(B
+\e$B$rJV$7$^$9!#\e(B
+
+@item gnus-group-prefixed-name
+@findex gnus-group-prefixed-name
+\e$B@\F,<-L5$7$N%0%k!<%WL>$HA*BrJ}K!$r<u$1<h$j!"@55,$N\e(B (\e$B@\F,<-IU$-$N\e(B)
+gnus \e$B%0%k!<%WL>$rJV$7$^$9!#\e(B
+
+@item gnus-get-info
+@findex gnus-get-info
+@var{group} \e$B$N%0%k!<%W>pJs0lMw$rJV$7$^$9!#\e(B
+
+@item gnus-group-unread
+@findex gnus-group-unread
+@var{group} \e$B$NL$FI5-;v$N?t$+!"$b$7$/$O$=$l$,J,$+$i$J$$>l9g$O\e(B @code{t} \e$B$G\e(B
+\e$B$9!#\e(B
+
+@item gnus-active
+@findex gnus-active
+@var{group} \e$B$N3hF0EPO?$G$9!#\e(B
+
+@item gnus-set-active
+@findex gnus-set-active
+@var{group} \e$B$K3hF0EPO?$r@_Dj$7$^$9!#\e(B
+
+@item gnus-add-current-to-buffer-list
+@findex gnus-add-current-to-buffer-list
+Gnus \e$B=*N;;~$K>C5n$9$k%P%C%U%!$N0lMw$K8=:_$N%P%C%U%!$rDI2C$7$^$9!#\e(B
+
+@item gnus-continuum-version
+@findex gnus-continuum-version
+\e$B0z?t$H$7$F\e(B gnus \e$B$N%P!<%8%g%sJ8;zNs$r<u$1<h$j!"IbF0>.?tE@?t$rJV$7\e(B
+\e$B$^$9!#8E$$%P!<%8%g%s$OI,$:?7$7$$%P!<%8%g%s$h$j$b>.$5$$?t$K$J$j$^\e(B
+\e$B$9!#\e(B
+
+@item gnus-group-read-only-p
+@findex gnus-group-read-only-p
+@var{group} \e$B$,FI$_=P$7@lMQ$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-news-group-p
+@findex gnus-news-group-p
+@var{group} \e$B$,%K%e!<%9%P%C%/%(%s%I$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-ephemeral-group-p
+@findex gnus-ephemeral-group-p
+@var{group} \e$B$,C;4|%0%k!<%W$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-server-to-method
+@findex gnus-server-to-method
+@var{server} \e$B$KBP1~$7$F$$$kA*BrJ}K!$rJV$7$^$9!#\e(B
+
+@item gnus-server-equal
+@findex gnus-server-equal
+\e$BFs$D$N2>A[%5!<%P!<$,F10l$N$b$N$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-group-native-p
+@findex gnus-group-native-p
+@var{group} \e$B$,4pK\%0%k!<%W$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-group-secondary-p
+@findex gnus-group-secondary-p
+@var{group} \e$B$,Fs<!%0%k!<%W$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-group-foreign-p
+@findex gnus-group-foreign-p
+@var{group} \e$B$,30It%0%k!<%W$G$"$k$+$I$&$+$r<($7$^$9!#\e(B
+
+@item gnus-group-find-parameter
+@findex gnus-group-find-parameter
+@var{group} \e$B$N%Q%i%a!<%?0lMw$rJV$7$^$9!#Fs$DL\$N0z?t$rM?$($k$H!"\e(B
+@var{group} \e$BMQ$N$=$N%Q%i%a!<%?$NCM$rJV$7$^$9!#\e(B
+
+@item gnus-group-set-parameter
+@findex gnus-group-set-parameter
+\e$B;0$D$N0z?t\e(B @var{group}, @var{parameter}, @var{value} \e$B$r<h$j$^$9!#\e(B
+
+@item gnus-narrow-to-body
+@findex gnus-narrow-to-body
+\e$B8=:_$N%P%C%U%!$N5-;v$NK\J8$r@)8BI=<($7$^$9!#\e(B
+
+@item gnus-check-backend-function
+@findex gnus-check-backend-function
+\e$BFs$D$N0z?t\e(B @var{function}, @var{group} \e$B$r<h$j$^$9!#\e(B@var{group} \e$B%P%C%/%(\e(B
+\e$B%s%I$,\e(B @var{function} \e$B$r%5%]!<%H$7$F$$$k$J$i!"\e(B@code{nil} \e$B0J30$rJV$7$^$9!#\e(B
+
+@lisp
+(gnus-check-backend-function "request-scan" "nnml:misc")
+@result{} t
+@end lisp
+
+@item gnus-read-method
+@findex gnus-read-method
+\e$BMxMQ<T$KA*BrJ}K!$r%W%m%s%W%HF~NO$7$F$b$i$$$^$9!#\e(B
+@end table
+
+@node Back End Interface
+@subsection \e$B%P%C%/%(%s%I%$%s%?!<%U%'!<%9\e(B
+
+Gnus \e$B$O\e(B @acronym{NNTP} \e$B$d%9%W!<%k!"%a!<%k!"2>A[%0%k!<%W$K$D$$$F$O2?$K$b\e(B
+\e$BCN$j$^$;$s!#$?$@2>A[%5!<%P!<\e(B @dfn{virtual servers} \e$B$HBPOC$9$kJ}K!$rCN$C\e(B
+\e$B$F$$$k$@$1$G$9!#2>A[%5!<%P!<$O%P%C%/%(%s%I\e(B @dfn{back end} \e$B$H$$$/$D$+$N%P%C\e(B
+\e$B%/%(%s%IJQ?t\e(B @dfn{back end variables} \e$B$+$i$J$j$^$9!#A0<T$NNc$H$7$F\e(B
+\e$B$O\e(B @code{nntp}, @code{nnspool}, @code{nnmbox} \e$B$J$I$,$"$j$^$9!#8e<T$NNc$H\e(B
+\e$B$7$F$O\e(B @code{nntp-port-number} \e$B$d\e(B @code{nnmbox-directory} \e$B$,$"$j$^$9!#\e(B
+
+Gnus \e$B$,%P%C%/%(%s%I\e(B --- \e$BNc$($P\e(B @code{nntp} --- \e$B$K2?$+$N>pJs$rMW5a$9$k$H\e(B
+\e$B$-$O!"DL>o4X?t$N0z?t$H$7$F2>A[%5!<%P!<L>$r4^$a$^$9!#\e(B(\e$B$b$7$J$1$l$P!"%P%C\e(B
+\e$B%/%(%s%I$O\e(B ``\e$B8=:_$N\e(B'' \e$B2>A[%5!<%P!<$r;HMQ$7$^$9!#\e(B) \e$BNc$($P!"\e(B
+@code{nntp-request-list} \e$B$O$=$NM#0l$N\e(B (\e$B>JN,2DG=$J\e(B) \e$B0z?t$H$7$F2>A[%5!<%P!<\e(B
+\e$B$r<h$j$^$9!#$b$7$3$N2>A[%5!<%P!<$,3+$+$l$F$$$J$1$l$P!"$3$N4X?t$O<:GT$7$^\e(B
+\e$B$9!#\e(B
+
+\e$B2>A[%5!<%P!<L>$O!"J*M}E*$J%5!<%P!<L>$H$O2?$N4X78$bL5$$$3$H$KCm0U$7$F$/$@\e(B
+\e$B$5$$!#$3$NNc$r8+$F$/$@$5$$!#\e(B
+
+@lisp
+(nntp "odd-one"
+      (nntp-address "ifi.uio.no")
+      (nntp-port-number 4324))
+@end lisp
+
+\e$B$3$3$G!"J*M}%5!<%P!<L>$O\e(B @samp{ifi.uio.no} \e$B$G$"$k$N$KBP$7!"2>A[%5!<%P!<\e(B
+\e$BL>$O\e(B @samp{odd-one} \e$B$G$9!#\e(B
+
+\e$B%P%C%/%(%s%I$OJ#?t$N2>A[%5!<%P!<$r@Z$jBX$(2DG=$G$J$1$l$P$J$j$^$;$s!#I8=`\e(B
+\e$B$N%P%C%/%(%s%I$O$3$l$r!"2>A[%5!<%P!<4D6-$rI,MW$J$H$-$K<h$j=P$7!&2!$79~$_\e(B
+\e$B$r9T$J$&O"A[%j%9%H$rJ];}$9$k$3$H$K$h$C$F<B8=$7$F$$$^$9!#\e(B
+
+\e$B%$%s%?!<%U%'!<%94X?t$OFs$D$N%0%k!<%W$,$"$j$^$9!#I,$:B8:_$7$J$1$l$P$J$i$J\e(B
+\e$B$$I,?\4X?t\e(B @dfn{required functions} \e$B$H!"\e(Bgnus \e$B$,8F$S=P$7$r9T$J$&A0$K$=$l\e(B
+\e$B$,B8:_$9$k$+$r>o$K3NG'$9$kG$0U4X?t\e(B @dfn{optional functions} \e$B$G$9!#\e(B
+
+\e$B$3$l$i$N4X?t$OA4$F!"JV5Q%G!<%?\e(B
+\e$B$r\e(B @code{nntp-server-buffer} (@samp{*nntpd*}) \e$B%P%C%U%!!<$KJV$9$3$H$,5a$a\e(B
+\e$B$i$l$^$9!#$3$l$O$A$g$C$HIT1?$JL>A0IU$1$G$9$,!"$3$l$G2fK}$7$J$1$l$P$J$j$^\e(B
+\e$B$;$s!#;d$,7k2L$N%G!<%?\e(B @dfn{resulting data} \e$B$H8@$C$?$H$-$O!"$=$N%P%C%U%!!<\e(B
+\e$B$NCf$N%G!<%?$r;X$7$F$$$^$9!#JV5QCM\e(B @dfn{return value} \e$B$H8@$C$?$H$-$O!"4X\e(B
+\e$B?t8F$S=P$7$K$h$C$FJV$5$l$k4X?t$NCM$N$3$H$r8@$C$F$$$^$9!#4X?t$,<:GT$7$?$H\e(B
+\e$B$-$OJV5QCM$H$7$F\e(B@code{nil} \e$B$rJV$5$J$/$F$O$$$1$^$;$s!#\e(B
+
+\e$B%P%C%/%(%s%I$K$O%5!<%P!<7A<0\e(B @dfn{server-forming} \e$B$N%P%C%/%(%s%I$G$"$k$H\e(B
+\e$B8F$P$l$k$b$N$,$"$j!"$^$?$=$&8F$P$l$J$$$b$N$b$"$j$^$9!#8e<T$O0lHL$K$O!"F1\e(B
+\e$B;~$K$O0l$D$@$1$7$+A`:n$7$J$$%P%C%/%(%s%I$G!"\e(B``\e$B%5!<%P!<\e(B'' \e$B$N35G0$,$"$j$^\e(B
+\e$B$;$s!#$3$N%5!<%P!<$H$O!"%0%k!<%W$r;}$A!"$=$N%0%k!<%W$K>pJs$rG[Aw$9$k$b$N\e(B
+\e$B$G!"$=$l0J>e$N$b$N$G$O$"$j$^$;$s!#\e(B
+
+Gnus \e$B$O%0%k!<%WL>$H5-;vHV9f$K$h$C$F$=$l$>$l$N%a%C%;!<%8$rFCDj$7$^$9!#$=\e(B
+\e$B$l$i5-;vHV9f$K4X$9$k$A$g$C$H$7$?@bL@$r$9$k$3$H$OM-1W$+$b$7$l$^$;$s!#$^$:\e(B
+\e$BBh0l$K!"$=$N?t;z$O@5$N@0?t$G$9!#BhFs$K!"\e(BGnus \e$B$r:.Mp$5$;$k$3$H$J$/8E$$5-\e(B
+\e$B;vHV9f$r8e$G\e(B ``\e$B:F;HMQ\e(B'' \e$B$9$k$3$H$OIaDL$O$G$-$^$;$s!#$=$l$O!"$b$7$"$k%0%k!<\e(B
+\e$B%W$,$+$D$F\e(B 42 \e$BHV$N5-;v$r;}$C$F$$$?$H$7$?$i!"$=$NHV9f$GB>$N5-;v$r;}$D$3$H\e(B
+\e$B$O$G$-$J$$$+!"$^$?$O\e(B Gnus \e$B$,:.Mp$7$F$7$^$&$+$b$7$l$J$$$H$$$&$3$H$G$9!#\e(B
+@footnote{See the function @code{nnchoke-request-update-info},
+@ref{Optional Back End Functions}\e$B!#\e(B} \e$BBh;0$K!"5-;vHV9f$O$=$N%0%k!<%W$G$N\e(B
+\e$BE~Ce=g$K$J$C$F$$$J$1$l$P$J$i$J$$$3$H$G$9!#$H$O8@$(%a%C%;!<%8$NF|IU$bE~Ce\e(B
+\e$B=g$G$"$kI,MW$O$"$j$^$;$s$,!#\e(B
+
+\e$B$9$G$KA0$N@a$G!"5-;vHV9f$O0l2s;H$o$l$?$@$1$GLrL\$r=*$o$i$J$1$l$P$J$i$J\e(B
+\e$B$$\e(B ``\e$B87$7$$\e(B'' \e$B@)8B$K$D$$$F@bL@$7$^$7$?!#$7$+$7!"5-;vHV9f$NJB$S$KH4$1$,$"\e(B
+\e$B$k$H\e(B Gnus \e$B$O$H$F$b:.Mp$7$F$7$^$&$N$G!"\e(B@emph{\e$BDL$7\e(B} \e$BHV9f$rIU$1$k$3$H$,M-MQ\e(B
+\e$B$J$N$+$b$7$l$^$;$s!#$?$@$7\e(B ``\e$B:F;HMQIT2D\e(B'' \e$B$N@)8B$,$"$k$N$G!"$$$D$G$bHV9f\e(B
+\e$B$NH4$1$r2sHr$G$-$k$H$O8B$j$^$;$s!#$^$?!"2DG=$J8B$j5-;vHV9f$r\e(B 1 \e$B$+$i;O$a\e(B
+\e$B$k$3$H$O!"HV9f$r;H$$@Z$C$F$7$^$&$3$H$rHr$1$k$?$a$KLrN)$A$^$9!#\e(B
+
+\e$B47Nc$H$7$F!"%P%C%/%(%s%I$O\e(B @code{nn\e$B$J$s$?$i\e(B} \e$B$HL>IU$1$i$l$^$9$,!"\e(B
+gnus \e$B$K$O\e(B @file{nnheader.el}\e$B!"\e(B@file{nnmail.el} \e$B$*$h$S\e(B @file{nnoo.el} \e$B$N\e(B
+\e$B$h$&$K!"$$$/$D$+$N%P%C%/%(%s%I$G$O$J$$\e(B @code{nn\e$B$+$s$?$i\e(B} \e$B$,$"$k$3$H$KCm\e(B
+\e$B0U$7$F2<$5$$!#\e(B
+
+\e$B$3$3$G$NNc$HDj5A$G$O!"A[A|>e$N%P%C%/%(%s%I\e(B @code{nnchoke} \e$B$r0z$-9g$$$K=P\e(B
+\e$B$9$3$H$K$7$^$9!#\e(B
+
+@cindex @code{nnchoke}
+
+@menu
+* Required Back End Functions::  \e$B<BAu$7$J$1$l$P$J$i$J$$4X?t\e(B
+* Optional Back End Functions::  \e$B<BAu$7$J$/$F$b$h$$4X?t\e(B
+* Error Messaging::             \e$B%a%C%;!<%8$d%(%i!<Js9p$rF@$kJ}K!\e(B
+* Writing New Back Ends::       \e$B8E$$%P%C%/%(%s%I$N3HD%\e(B
+* Hooking New Back Ends Into Gnus::  Gnus \e$BB&$G$7$J$1$l$P$J$i$J$$$3$H\e(B
+* Mail-like Back Ends::         \e$B%a!<%kIw%P%C%/%(%s%I$N$?$a$N=u8@\e(B
+@end menu
+
+@node Required Back End Functions
+@subsubsection \e$BI,?\%P%C%/%(%s%I4X?t\e(B
+
+@table @code
+@item (nnchoke-retrieve-headers ARTICLES &optional GROUP SERVER FETCH-OLD)
+
+@var{articles} \e$B$O5-;vHV9f$NHO0O$+$"$k$$$O\e(B @code{Message-ID} \e$B$N%j%9%H$G$9!#\e(B
+\e$B8=:_$N%P%C%/%(%s%I$G$O$I$A$i$b40A4$K$O%5%]!<%H$7$F$$$^$;$s\e(B --- \e$BO"B3$7$?\e(B
+\e$B5-;vHV9f\e(B (\e$B$N%j%9%H\e(B) \e$B$@$1$G!"B?$/$N%P%C%/%(%s%I$G$O\e(B @code{Message-ID} \e$B$K\e(B
+\e$B$h$k<hF@$O%5%]!<%H$7$F$$$^$;$s!#$G$b$I$A$i$b%5%]!<%H$7$F$$$/$Y$-$G$7$g$&\e(B
+
+\e$B7k2L$N%G!<%?$O\e(B HEAD \e$B$+\e(B @acronym{NOV} \e$B9T$N$$$:$l$+$G$"$j!"JV5QCM$O$3$l$r\e(B
+\e$BH?1G$7$?\e(B @code{headers} \e$B$+\e(B @code{nov} \e$B$N$$$:$l$+$G$J$/$F$O$J$j$^$;$s!#$3\e(B
+\e$B$l$O:#8e!"\e(BHEAD \e$B$H\e(B @acronym{NOV} \e$B9T$,:.:_$9$k\e(B @code{various} \e$B$K3HD%$5$l$k\e(B
+\e$B$+$b$7$l$^$;$s$,!"8=:_$N\e(B gnus \e$B$G$O%5%]!<%H$5$l$F$$$^$;$s!#\e(B
+
+@var{fetch-old} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"$"$k0UL#$G$N\e(B ``\e$BM>J,$J%X%C\e(B
+\e$B%@!<\e(B'' \e$B$r<hF@$7$h$&$H$7$^$9!#$3$l$ODL>o!"\e(B@code{articles} \e$B$NCf$N:G>.HV9f\e(B
+\e$B$N5-;v$h$j$b>.$5$$5-;v$+$i\e(B (\e$B>/$J$/$H$b\e(B) @var{fetch-old} \e$B8D$NM>J,$J%X%C%@!<\e(B
+\e$B$r<hF@$7!"6u=j$rKd$a$k$3$H$r9T$J$$$^$9!#$b$7%P%C%/%(%s%I$,$3$NMW5a$K=>$&\e(B
+\e$B$3$H$rHQ$o$7$$$H;W$C$?>l9g$K$O!"$3$N%Q%i%a!<%?$NB8:_$OL5;k$5$l$k$3$H$b$"\e(B
+\e$B$j$^$9!#$3$NCM$,\e(B @code{nil} \e$B$G$b?t;z$G$b$J$1$l$P!":GBg8B$N<hF@$r9T$J$$$^\e(B
+\e$B$9!#\e(B
+
+\e$B$3$l$,\e(B HEAD \e$B$NNc$G$9!#\e(B
+
+@example
+221 1056 Article retrieved.
+Path: ifi.uio.no!sturles
+From: sturles@@ifi.uio.no (Sturle Sunde)
+Newsgroups: ifi.discussion
+Subject: Re: Something very droll
+Date: 27 Oct 1994 14:02:57 +0100
+Organization: Dept. of Informatics, University of Oslo, Norway
+Lines: 26
+Message-ID: <38o8e1$a0o@@holmenkollen.ifi.uio.no>
+References: <38jdmq$4qu@@visbur.ifi.uio.no>
+NNTP-Posting-Host: holmenkollen.ifi.uio.no
+.
+@end example
+
+\e$B$D$^$j!"JV5QCM$,\e(B @code{headers} \e$B$G$"$k$H$-$O!"%G!<%?%P%C%U%!$K$3$l$i%X%C\e(B
+\e$B%@!<$,$$$/$D$+$"$k$H$$$&$3$H$r0UL#$7$^$9!#\e(B
+
+\e$B$3$l$,$=$N%P%C%U%!!<$N\e(B BNF \e$BDj5A$G$9!#\e(B
+
+@example
+headers        = *head
+head           = error / valid-head
+error-message  = [ "4" / "5" ] 2number " " <error message> eol
+valid-head     = valid-message *header "." eol
+valid-message  = "221 " <number> " Article retrieved." eol
+header         = <text> eol
+@end example
+
+@cindex BNF
+(\e$B$3$3$G;H$C$?\e(B BNF \e$B$NHG$O\e(B RFC822 \e$B$G;H$o$l$F$$$k$b$N$G$9!#\e(B)
+
+\e$B$b$7JV5QCM$,\e(B @code{nov} \e$B$G$"$l$P!"%G!<%?%P%C%U%!!<$K\e(B
+\e$B$O\e(B @dfn{network overview database} \e$B9T$,4^$^$l$F$J$/$F$O$J$j$^$;$s!#\e(B
+\e$B$3$l$O4pK\E*$K$OJ#?t$NMs$r%?%V$G6h@Z$C$?$b$N$G$9!#\e(B
+
+@example
+nov-buffer = *nov-line
+nov-line   = field 7*8[ <TAB> field ] eol
+field      = <text except TAB>
+@end example
+
+\e$B$3$l$i$NMs$K$I$N$h$&$J$b$N$,4^$^$l$k$+$r$h$j>\$7$/8+$?$1$l$P!"\e(B
+@ref{Headers} \e$B$r;2>H$7$F$/$@$5$$!#\e(B
+
+@item (nnchoke-open-server SERVER &optional DEFINITIONS)
+
+\e$B$3$3$G$N\e(B @var{server} \e$B$O2>A[%5!<%P!<L>$G$9!#\e(B@var{definitions} \e$B$O\e(B
+\e$B$3$N2>A[%5!<%P!<$rDj5A$9$k\e(B @code{(VARIABLE VALUE)} \e$BAH$N%j%9%H$G\e(B
+\e$B$9!#\e(B
+
+\e$B$b$7%5!<%P!<$r3+$/$3$H$,$G$-$J$1$l$P!"%(%i!<$O%7%0%J%k$G$ODLCN$5\e(B
+\e$B$l$^$;$s!#$=$7$F%P%C%/%(%s%I$O!"$=$l0J8e$N$3$N%5!<%P!<$X$N@\B3MW\e(B
+\e$B5a$r5qH]$9$k$3$H$b$G$-$^$9!#<B:]!"$=$&$9$Y$-$G$9!#\e(B
+
+\e$B$b$7$=$N%5!<%P!<$,$9$G$K3+$$$F$$$l$P!"$3$N4X?t$O\e(B @code{nil} \e$B0J30\e(B
+\e$B$NCM$rJV5Q$7$J$1$l$P$J$j$^$;$s!#$3$N$H$-!"JV$5$l$k7k2L$N%G!<%?$O\e(B
+\e$B$"$j$^$;$s!#\e(B
+
+@item (nnchoke-close-server &optional SERVER)
+
+@var{server} \e$B$X$N@\B3$rJD$8!"$3$l$K4XO"$9$k$9$Y$F$N;q8;$r3+J|$7\e(B
+\e$B$^$9!#$b$72?$i$+$NM}M3$G%5!<%P!<$rJD$8$k$3$H$,$G$-$J$1$l$P!"\e(B
+@code{nil} \e$B$rJV5Q$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-close)
+
+\e$BA4$F$N%5!<%P!<$N@\B3$rJD$8!"%P%C%/%(%s%I$,J]M-$7$F$$$kA4$F$N;q8;\e(B
+\e$B$r3+J|$7$^$9!#$3$N%P%C%/%(%s%I$K$h$C$F:n@.$5$l$?%P%C%U%!$OA4$F:o\e(B
+\e$B=|$5$l$^$9!#\e(B(@code{nntp-server-buffer} \e$B$O:o=|$5$l$^$;$s$,!#\e(B) \e$B$3\e(B
+\e$B$N4X?t$ODL>o!"\e(Bgnus \e$B$,=*N;$9$k$H$-$K$N$_8F$S=P$5$l$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-server-opened &optional SERVER)
+
+\e$B$b$7\e(B @var{server} \e$B$,8=:_$N2>A[%5!<%P!<$G!"$=$NJ*M}%5!<%P!<$X$N@\\e(B
+\e$BB3$,@8$-$F$$$l$P!"$3$N4X?t$O\e(B @code{nil} \e$B0J30$NCM$rJV$7$^$9!#$3$N\e(B
+\e$B4X?t$O$I$s$J>l9g$G$b!"@\B3$,<:$o$l$?%5!<%P!<$X$N:F@\B3$r9T$J$&$3\e(B
+\e$B$H$O$"$j$^$;$s!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-status-message &optional SERVER)
+
+\e$B$3$N4X?t$O\e(B @var{server} \e$B$+$i$N:G8e$N%(%i!<%a%C%;!<%8$rJV5Q$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-article ARTICLE &optional GROUP SERVER TO-BUFFER)
+
+\e$B$3$N4X?t$N7k2L$N%G!<%?$O!"\e(B@var{article} \e$B$G;XDj$5$l$?5-;v$G$9!#$3$N;XDj\e(B
+\e$B$O\e(B @code{Message-ID} \e$B$+HV9f$N$$$:$l$+$G$9!#\e(B@code{Message-ID} \e$B$K$h$k5-;v\e(B
+\e$B$N<hF@$r<BAu$9$k$+$I$&$+$OG$0U$G$9$,!"2DG=$G$"$k$H4r$7$$$G$9$M!#\e(B
+
+@var{to-buffer} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"7k2L$N%G!<%?$ODL>o$N%G!<%?%P%C\e(B
+\e$B%U%!$NBe$o$j$K!"$3$N%P%C%U%!$KJV$5$l$^$9!#$3$l$K$h$jB?NL$N%G!<%?$r$"$k%P%C\e(B
+\e$B%U%!$+$iJL$N%P%C%U%!$K%3%T!<$9$k$3$H$rHr$1$k$3$H$,$G$-!"$=$7$F\e(B gnus \e$B$ODL\e(B
+\e$B>o!"5-;v%P%C%U%!$KD>@\5-;v$rA^F~$9$k$h$&$KMW5a$7$F$$$^$9!#\e(B
+
+\e$B$b$72DG=$G$"$k$N$J$i!"$3$N4X?t$O!"\e(B@code{car}\e$B$,<hF@$7$?5-;v$N$"$k%0%k!<%W\e(B
+\e$BL>$G!"\e(B@code{cdr} \e$B$,5-;vHV9f$G$"$k\e(B cons \e$B%;%k$rJV$9$Y$-$G$9!#$3$l$K$h\e(B
+\e$B$j\e(B @code{Message-ID} \e$B$K$h$C$F5-;v$r<hF@$7$?$H$-!"\e(Bgnus \e$B$,K\Ev$N%0%k!<%W$H\e(B
+\e$B5-;vHV9f$rCN$k$3$H$,$G$-$k$h$&$K$J$k$G$7$g$&!#$3$l$,IT2DG=$J>l9g$K$O!"5-\e(B
+\e$B;v$N<hF@$,@.8y$7$?$H$-$O\e(B @code{t} \e$B$rJV$7$^$9!#\e(B
+
+@item (nnchoke-request-group GROUP &optional SERVER FAST)
+
+@var{group} \e$B$N%G!<%?$r<hF@$7$^$9!#$3$N4X?t$O!"\e(B@var{group} \e$B$r8=:_$N%0%k!<\e(B
+\e$B%W$K$9$k!"$H$$$&I{:nMQ$b$"$j$^$9!#\e(B
+
+@var{fast} \e$B$,$"$l$P!"JXMx$J%G!<%?$rJV$9LLE]$r9T$J$o$:$K!"C1$K\e(B
+@var{group} \e$B$r8=:_$N%0%k!<%W$K$7$^$9!#\e(B
+
+\e$B$3$l$,7k2L$N%G!<%?$NNc$H!"$=$l$NDj5A$G$9!#\e(B
+
+@example
+211 56 1000 1059 ifi.discussion
+@end example
+
+\e$B:G=i$N?t;z$O>uBV$G!"$3$l$O\e(B 211 \e$B$G$J$/$F$O$J$j$^$;$s!#<!$O$=$N%0%k!<%W$K\e(B
+\e$B$"$k5-;v$NAm?t!":G>.$N5-;vHV9f!":GBg$N5-;vHV9f!"$=$7$F:G8e$,%0%k!<%WL>$G\e(B
+\e$B$9!#5-;v$NAm?t$O!":GBg!&:G>.5-;vHV9f$+$iC1=c$K9M$($i$l$k?t$h$j$b>.$5$$$3\e(B
+\e$B$H$,$"$k$3$H$KCm0U$7$F$/$@$5$$!#$$$/$D$+$N5-;v$O<h$j>C$5$l$F$$$k$+$b$7$l\e(B
+\e$B$^$;$s!#\e(BGnus \e$B$OAm?t$OC1$K<N$F$F$7$^$C$F$$$k$N$G!"\e(B(\e$B$b$7$=$l$,LdBj$H$J$k$H\e(B
+\e$B$-$K\e(B) \e$B@5$7$$CM$r@8@.$9$kLLE]$rIi$&$Y$-$+$I$&$+$O!"FI<T$X$N2]Bj$H$7$F;D$7\e(B
+\e$B$F$"$j$^$9!#$b$7$=$N%0%k!<%W$K5-;v$,L5$1$l$P!":G>.5-;vHV9f$O\e(B 1\e$B!":GBg\e(B
+\e$B$O\e(B 0 \e$B$H$7$FJs9p$5$l$J$1$l$P$J$j$^$;$s!#\e(B
+
+@example
+group-status = [ error / info ] eol
+error        = [ "4" / "5" ] 2<number> " " <Error message>
+info         = "211 " 3* [ <number> " " ] <string>
+@end example
+
+@item (nnchoke-close-group GROUP &optional SERVER)
+
+@var{group} \e$B$rJD$8!"$=$l$K@\B3$5$l$F$$$kA4$F$N;q8;$r3+J|$7$^$9!#$3$l$O$[\e(B
+\e$B$H$s$I$N%P%C%/%(%s%I$G$O2?$b$9$k$3$H$,$J$$$G$7$g$&!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-list &optional SERVER)
+
+@var{server} \e$B>e$GMxMQ2DG=$JA4$F$N%0%k!<%W$N0lMw$rJV$7$^$9!#$3$l\e(B
+\e$B$O\e(B @emph{\e$BA4It\e(B} \e$B$H$$$&0UL#$G$9!#\e(B
+
+\e$B$3$l$,!"$?$C$?Fs$D$7$+%0%k!<%W$r;}$C$F$$$J$$%5!<%P!<$+$i$NNc$G$9!#\e(B
+
+@example
+ifi.test 0000002200 0000002000 y
+ifi.discussion 3324 3300 n
+@end example
+
+\e$B3F9T$K$O%0%k!<%WL>$,$"$j!"$=$7$F$=$N%0%k!<%WFb$N:GBg$N5-;vHV9f!":G>.$N5-\e(B
+\e$B;vHV9f!"$=$7$F:G8e$K%U%i%0$G$9!#$b$7$=$N%0%k!<%W$K5-;v$,L5$1$l$P!":G>.5-\e(B
+\e$B;vHV9f$O\e(B 1\e$B!":GBg$O\e(B 0 \e$B$H$7$FJs9p$5$l$J$1$l$P$J$j$^$;$s!#\e(B
+
+@example
+active-file = *active-line
+active-line = name " " <number> " " <number> " " flags eol
+name        = <string>
+flags       = "n" / "y" / "m" / "x" / "j" / "=" name
+@end example
+
+\e$B%U%i%0$O!"$=$N%0%k!<%W$,FI$_=P$7@lMQ\e(B (@samp{n}) \e$B$G$"$k$+!";J2q<TIU\e(B
+\e$B$-\e(B (@samp{m}) \e$B$G$"$k$+!";`$s$G$$$k\e(B (@samp{x}) \e$B$+!"$I$3$+B>$N%0%k!<%W$NJL\e(B
+\e$BL>\e(B (@samp{=other-group}) \e$B$G$"$k$+!">e5-$N$I$l$G$b$J$$\e(B (@samp{y}) \e$B$+!"$H\e(B
+\e$B$$$&$3$H$r<($7$F$$$^$9!#\e(B
+
+@item (nnchoke-request-post &optional SERVER)
+
+\e$B$3$N4X?t$O!"8=:_$N%P%C%U%!$rEj9F$7$^$9!#$3$l$OEj9F$,@.8y$7$?$+$I$&$+$rJV\e(B
+\e$B5Q$7$F$b9=$$$^$;$s$,!"I,?\$G$O$"$j$^$;$s!#Nc$($P!"Ej9F$,HsF14|$K9T$o$l$k\e(B
+\e$B$N$G$"$l$P!"$3$N4X?t$,=*N;$7$?;~E@$G$OEj9F$OIaDL40N;$7$F$$$^$;$s!#$=$N>l\e(B
+\e$B9g$3$N4X?t$O!"Ej9F$r40N;$5$;$k$3$H$,$G$-$J$$$H$-!"$=$l$r$O$C$-$j$HMxMQ<T\e(B
+\e$B$KCN$i$;$k8+D%$j4X?t$N$h$&$J$b$N$r@_Dj$9$k$Y$-$G$7$g$&!#\e(B
+
+\e$B$3$N4X?t$+$iJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+@end table
+
+@node Optional Back End Functions
+@subsubsection \e$BG$0U%P%C%/%(%s%I4X?t\e(B
+
+@table @code
+@item (nnchoke-retrieve-groups GROUPS &optional SERVER)
+
+@var{groups} \e$B$O%0%k!<%W$N%j%9%H$G$"$j!"$3$N4X?t$O$=$l$iA4It$N%0\e(B
+\e$B%k!<%W$N%G!<%?$rMW5a$7$^$9!#$I$&$d$C$F$=$l$r9T$J$&$+$O\e(B gnus \e$B$NCN$C\e(B
+\e$B$?$3$H$G$O$"$j$^$;$s$,!"$3$l$O$G$-$k$@$1?WB.$JJ}K!$G9T$J$o$J$1$l\e(B
+\e$B$P$J$j$^$;$s!#\e(B
+
+\e$B$3$N4X?t$NJV5QCM$O\e(B @code{active} \e$B$+\e(B @code{group} \e$B$N$$$:$l$+$G!"\e(B
+\e$B7k2L$N%G!<%?$N7A<0$,2?$G$"$k$+$r<($7$^$9!#A0<T\e(B
+\e$B$O\e(B @code{nnchoke-request-list} \e$B$K$h$k%G!<%?$HF1$87A<0$G$"$j!"0lJ}8e\e(B
+\e$B<T$O\e(B @code{nnchoke-request-group} \e$B$,M?$($k$b$N$HF1$87A<0$N9T$G%P%C\e(B
+\e$B%U%!$OKd$a$i$l$^$9!#\e(B
+
+@example
+group-buffer = *active-line / *group-status
+@end example
+
+@item (nnchoke-request-update-info GROUP INFO &optional SERVER)
+
+Gnus \e$B%0%k!<%W>pJs\e(B (@pxref{Group Info}) \e$B$,JQ992U=j$H$7$F%P%C%/%(\e(B
+\e$B%s%I$KEO$5$l$^$9!#$3$l$O%P%C%/%(%s%I$,\e(B (\e$B2>A[%0%k!<%W$d\e(B imap \e$B%0%k!<\e(B
+\e$B%W$N>l9g$N$h$&$K\e(B) \e$BK\Ev$KA4$F$N>pJs$r;}$C$F$$$k>l9g$KJXMx$K$J$j$^\e(B
+\e$B$9!#$3$N4X?t$O!"$=$NMW5a$KE,9g$5$;$k>pJs$rGK2uE*$KCV$-49$(!"\e(B
+@code{nil} \e$B$G$O$J$$CM$rJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$B$3$N4X?t$+$iJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-type GROUP &optional ARTICLE)
+
+\e$BMxMQ<T$,\e(B ``\e$B%K%e!<%9$rAw?.$9$k\e(B'' \e$BL?Na\e(B (\e$BNc$($P!"35N,%P%C%U%!$G\e(B @kbd{F}) \e$B$r\e(B
+\e$B<B9T$7$?$H$-!"\e(Bgnus \e$B$OMxMQ<T$,%U%)%m!<%"%C%W$7$h$&$H$7$F$$$k5-;v$,%K%e!<\e(B
+\e$B%9$G$"$k$+%a!<%k$G$"$k$+$rCN$i$J$/$F$O$J$j$^$;$s!#$3$N4X?t\e(B
+\e$B$O\e(B @var{group} \e$B$NCf$N\e(B @var{article} \e$B$,%K%e!<%9$G$"$l$P\e(B @code{news} \e$B$r!"\e(B
+\e$B%a!<%k$G$"$l$P\e(B @code{mail} \e$B$r!"$=$N<oJL$r7hDj$G$-$J$1$l\e(B
+\e$B$P\e(B @code{unknown} \e$B$rJV5Q$7$^$9!#\e(B(@var{article} \e$B0z?t$O!"%a!<%k%0%k!<%W$H\e(B
+\e$B%K%e!<%9%0%k!<%W$,$4$A$c$^$<$K$J$C$F$k$+$b$7$l$J$$\e(B @code{nnvirtual} \e$B$K$*\e(B
+\e$B$$$FI,MW$G$9!#\e(B) @var{group} \e$B$H\e(B@var{article} \e$B$ON>J}$H$b\e(B @code{nil} \e$B$G$"$k\e(B
+\e$B$+$b$7$l$^$;$s!#\e(B
+
+\e$B$3$N4X?t$+$iJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-set-mark GROUP ACTION &optional SERVER)
+
+\e$B5-;v$N0u$r@_Dj\e(B/\e$B>C5n\e(B/\e$BDI2C$7$^$9!#IaDL$O\e(B gnus \e$B$O5-;v$N0u\e(B (\e$B4{FI!"2D;k!";~8B\e(B
+\e$B>C5n$J$I\e(B) \e$B$rFbIt$G07$$!"\e(B@file{~/.newsrc.eld} \e$B$KJ]B8$7$^$9!#$7$+$7!"%P%C\e(B
+\e$B%/%(%s%I$K$O\e(B (@acronym{IMAP} \e$B$N$h$&$K\e(B) \e$B5-;v$NA4$F$N>pJs$r%5!<%P!<$K<}$a\e(B
+\e$B$k$N$G!"\e(Bgnus \e$B$O0u$N>pJs$r%5!<%P!<$KEAC#$7$J$1$l$P$J$i$J$$$b$N$,$"$j$^$9!#\e(B
+
+@var{action} \e$B$O$3$N$h$&$JMM<0$N0u@_Dj$NMW5a$N%j%9%H$G$9\e(B:
+
+@example
+(RANGE ACTION MARK)
+@end example
+
+@var{range} \e$B$O0u$rIU$1$?$$5-;v$NHO0O$G$9!#\e(B@var{action} \e$B$O\e(B @code{add} \e$B$^\e(B
+\e$B$?$O\e(B @code{del} \e$B$G!"0u$rDI2C$7$?$j>C$7$^$9\e(B (\e$B8@5Z$5$l$F$$$J$$$9$Y$F$N0u$O\e(B
+\e$BJ]B8$7$^$9\e(B)\e$B!"0u$N>C5n\e(B (\e$B8@5Z$5$l$F$$$J$$0u$OJ]B8$7$^$9\e(B) \e$B$G$9!#\e(B
+@var{mark} \e$B$O0u$N%j%9%H$G$9!#$=$l$>$l$N0u$O%7%s%\%k$G$9!#8=:_;H$o$l$F$$\e(B
+\e$B$k0u$O\e(B @code{read}, @code{tick}, @code{reply}, @code{expire},
+@code{killed}, @code{dormant}, @code{save}, @code{download},
+@code{unsend}, @code{forward} \e$B$*$h$S\e(B @code{recent} \e$B$G$9$,!"$b$72DG=$J$i!"\e(B
+\e$B$"$J$?$N%P%C%/%(%s%I$O$3$l$i$K@)8B$r$9$k$Y$-$G$O$"$j$^$;$s!#\e(B
+
+\e$BL7=b$9$kF0:n$,;XDj$5$l$?$H$-!"%j%9%H$N:G8e$NF0:n$,8zNO$r;}$D$b$N$K$J$j$^\e(B
+\e$B$9!#$9$J$o$A!"F0:n$K5-;v\e(B 1 \e$B$K\e(B @code{\e$B2D;k\e(B} \e$B0u$rDI2C$9$kMW5a$,$"$j!"%j%9%H\e(B
+\e$B$N8e$GF1$85-;v$+$i0u$r>C5n$9$k$3$H$rMW5a$7$F$$$l$P!"0u$O<B:]$K>C5n$5$l$k\e(B
+\e$B$Y$-$G$9!#\e(B
+
+\e$BF0:n%j%9%H$NNc$G$9\e(B:
+
+@example
+(((5 12 30) 'del '(tick))
+ ((10 . 90) 'add '(read expire))
+ ((92 94) 'del '(read)))
+@end example
+
+\e$B4X?t$O0u$r@_Dj$G$-$J$+$C$?5-;v$NHO0O$rJV$9$Y$-$G$9\e(B (\e$B8=:_$OA4$/;H$o$l$F$$\e(B
+\e$B$^$;$s\e(B)\e$B!#\e(B
+
+\e$B$3$N4X?t$+$i$O7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-update-mark GROUP ARTICLE MARK)
+
+\e$B$b$7MxMQ<T$,!"$3$N%P%C%/%(%s%I$N5$$KF~$i$J$$0u$r@_Dj$7$h$&$H$7$?$i!"$3$N\e(B
+\e$B4X?t$,0u$rJQ99$9$k$3$H$,$G$-$^$9!#\e(BGnus \e$B$O$b$H$N\e(B @var{mark} \e$B$NBe$o$j$K!"\e(B
+\e$B$3$N4X?t$,JV$7$?$b$N$r\e(B @var{article} \e$B$X$N0u$H$7$F;H$$$^$9!#%P%C%/%(%s%I\e(B
+\e$B$,5$$K$9$k$3$H$,FC$K$J$1$l$P!"85$N\e(B @var{mark} \e$B$rJV$5$J$1$l$P$J$j$^$;$s!#\e(B
+@code{nil} \e$B$d$=$NB>$N%4%_$rJV$7$F$O$$$1$^$;$s!#\e(B
+
+\e$B;d$,CN$C$F$$$k$3$l$N$3$l$NMxMQK!$O!"\e(B@code{nnvirtual} \e$B$,9T$J$C$F$$$k$3$H\e(B
+\e$B$@$1$G$9\e(B --- \e$B$b$79=@.%0%k!<%W$,<+F04|8B@Z$l>C5n2DG=$G$"$l$P!"$3$N2>A[%0\e(B
+\e$B%k!<%W$G4{FI$N0u$rIU$1$k$H!"7k2L$H$7$F$=$N5-;v$K4|8B@Z$l>C5n$N0u$,IU$1$i\e(B
+\e$B$l$^$9!#\e(B
+
+\e$B$3$N4X?t$+$iJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-scan &optional GROUP SERVER)
+
+\e$B$3$N4X?t$O!"%P%C%/%(%s%I$,E~Ce5-;v$r3NG'$9$kMW5a$r9T$J$&$H$-$K$$$D$G\e(B
+\e$B$b\e(B (gnus \e$B$+$=$l0J30$K$h$C$F\e(B)\e$B!"$"$l$d$3$l$d$H8F$S=P$5$l$k$3$H$,$"$j$^$9!#\e(B
+\e$B%a!<%k%P%C%/%(%s%I$O$3$N4X?t$,5/F0$5$l$?$H$-!"E57?E*$K$O%9%W!<%k%U%!%$%k\e(B
+\e$B$rFI$`$+\e(B @acronym{POP} \e$B%5!<%P!<$KLd$$9g$o$;$K$$$-$^$9!#\e(B@var{group} \e$B$OFC\e(B
+\e$B$K5$$KN1$a$kI,MW$O$"$j$^$;$s\e(B --- \e$B$b$7%P%C%/%(%s%I$,!"0l$D$@$1$N%0%k!<%W\e(B
+\e$B$rAv::$9$k$N$OBgJQ$9$.$k$HH=CG$7$?>l9g$K$O!"A4%0%k!<%W$NA4Av::$r9T$J$C$F\e(B
+\e$B$b9=$$$^$;$s!#$G$9$,!"<BMQE*$K$G$-$l$P$=$l$r6I=jE*$KJD$8$F$*$/J}$,NI$$$G\e(B
+\e$B$7$g$&!#\e(B
+
+\e$B$3$N4X?t$KJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-group-description GROUP &optional SERVER)
+
+\e$B$3$N4X?t$K$h$C$FJV$5$l$k7k2L$N%G!<%?$O!"\e(B@var{group} \e$B$N@bL@$G$9!#\e(B
+
+@example
+description-line = name <TAB> description eol
+name             = <string>
+description      = <text>
+@end example
+
+@item (nnchoke-request-list-newsgroups &optional SERVER)
+
+\e$B$3$N4X?t$K$h$C$FJV$5$l$k7k2L$N%G!<%?$O!"%5!<%P!<>e$GMxMQ$G$-$k%0\e(B
+\e$B%k!<%WA4$F$N@bL@$G$9!#\e(B
+
+@example
+description-buffer = *description-line
+@end example
+
+@item (nnchoke-request-newgroups DATE &optional SERVER)
+
+\e$B$3$N4X?t$+$iJV$5$l$k7k2L$N%G!<%?$O!"\e(B@samp{date} \e$B0J9_$K:n@.$5$l$?A4$F$N%0\e(B
+\e$B%k!<%W$G$9!#\e(B@samp{date} \e$B$ODL>o$N?M4V$,FI$a$kF|IU$N7A<0\e(B (\e$B$9$J$o$A!"%a!<%k\e(B
+\e$B$d%K%e!<%9$N%X%C%@!<$G;H$o$l$k7A<0$G!"%G%#%U%)%k%H$G$O4X\e(B
+\e$B?t\e(B @code{message-make-date} \e$B$+$iJV$5$l$?$b$N\e(B) \e$B$G$9!#%G!<%?$O\e(B active \e$B%P%C\e(B
+\e$B%U%!$N7A<0$G$J$1$l$P$J$j$^$;$s!#\e(B
+
+\e$B$3$N4X?t$,\e(B ``\e$BB?$9$.$k\e(B'' \e$B%0%k!<%W$rJV$7$F$b%*!<%1%$$G$9!#$$$/$D$+$N%P%C%/\e(B
+\e$B%(%s%I$O?7$7$$%0%k!<%W$r8+$D$1$k$h$j$b!"3Z$r$7$FA4$F$N%0%k!<%W$N%j%9%H$r\e(B
+\e$BJV$9$+$b$7$l$^$;$s!#$7$+$7%P%C%/%(%s%I$,JV$9B?$/$N%0%k!<%W$KBP$7$F$3\e(B
+\e$B$l\e(B (\e$BLuCm\e(B: \e$B?7$7$$%0%k!<%W$H$7$F07$&$3$H\e(B) \e$B$r$7$F$O$$$1$^$;$s!#IaDL!"%f!<%6!<\e(B
+\e$B<+?H$,:n$C$?%0%k!<%W$J$i$PB?$9$.$k$3$H$O$J$$$G$7$g$&!#$G$9$+\e(B
+\e$B$i\e(B @code{nnml} \e$B$H$=$l$KN`$9$k$b$N$O$?$V$s?4G[$"$j$^$;$s!#$7$+\e(B
+\e$B$7\e(B @code{nntp} \e$B$N$h$&$J%P%C%/%(%s%I$G$O%0%k!<%W$O%5!<%P!<$K$h$C$F:n$i$l\e(B
+\e$B$F$$$^$9$+$i!"B?$/$N%0%k!<%W$,JV$C$F$/$k$3$H$,$"$j$($^$9!#\e(B
+
+@item (nnchoke-request-create-group GROUP &optional SERVER)
+
+\e$B$3$N4X?t$O!"\e(B@var{group} \e$B$H$$$&L>A0$N6u$N%0%k!<%W$r:n@.$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-expire-articles ARTICLES &optional GROUP SERVER FORCE)
+
+\e$B$3$N4X?t$O!"\e(B@var{articles} \e$B$NHO0O$NA4$F$N5-;v$KBP$7$F4|8B@Z$l>C5n=hM}$r\e(B
+\e$B9T$J$$$^$9!#\e(B(@var{articles} \e$B$O8=:_$O5-;vHV9f$NC1=c$J%j%9%H$G$9!#\e(B) \e$B$3$N\e(B
+\e$B4X?t$G>C5n$5$l$kA0$N!"5-;v$,$I$l$@$18E$$5-;v$G$"$k$+$N7hDj$O%P%C%/%(%s%I\e(B
+\e$B$KG$$5$l$F$$$^$9!#\e(B@var{force} \e$B$,\e(B @code{nil} \e$B0J30$G$"$l$P!"$=$l$,$I$s$J$K\e(B
+\e$B?7$7$$$b$N$G$"$C$F$b!"A4$F$N\e(B@var{articles} \e$B$,>C5n$5$l$^$9!#\e(B
+
+\e$B$3$N4X?t$O:o=|$7$J$+$C$?!"$"$k$$$O:o=|$9$k$3$H$,$G$-$J$+$C$?5-;v$N%j%9%H\e(B
+\e$B$rJV$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM &optional LAST)
+
+\e$B$3$N4X?t$O\e(B @var{article} (\e$BHV9f\e(B) \e$B$r!"\e(B@var{group} \e$B$+\e(B
+\e$B$i\e(B @var{accept-form} \e$B$r8F$S=P$7$F0\F0$7$^$9!#\e(B
+
+\e$B$3$N4X?t$O!"LdBj$N5-;v$r0\F0$5$;$k$?$a$N=`Hw$H$7$F!"5-;v$KIU2C$5$l$?%X%C\e(B
+\e$B%@!<9T$rA4$F:o=|$7!"0lHL$K5-;v$r!V$-$l$$$5$C$Q$j!W$K$7$^$9!#$=$7$F\e(B ``\e$B$-\e(B
+\e$B$l$$$J\e(B'' \e$B5-;v$N$"$k%P%C%U%!!<$G\e(B @var{accept-form} \e$B$r\e(B @code{eval} \e$B$7$^$9!#\e(B
+\e$B$3$l$OK\Ev$KJ#@=$r9T$J$$$^$9!#$b$7\e(B @code{eval} \e$B$,\e(B @code{nil} \e$B0J30$NCM$r\e(B
+\e$BJV$7$?$i!"$=$N5-;v$O:o=|$5$l$^$;$s!#\e(B
+
+@var{last} \e$B$,\e(B @code{nil} \e$B$G$"$l$P!"$3$ND>8e$K$5$i$KMW5a$,H/9T$5$l$k8+9~\e(B
+\e$B$_$,9b$$!"$H$$$&0UL#$K$J$j!"$3$l$K$h$C$F:GE,2=$,$$$/$i$+$G$-$k$h$&$K$J$j\e(B
+\e$B$^$9!#\e(B
+
+\e$B$3$N4X?t$O!"%0%k!<%WL>$,\e(B @code{car} \e$B$G!"$=$N5-;v$N0\F0@h$N5-;vHV9f$,\e(B
+@code{cdr} \e$B$G$"$k\e(B cons \e$B%;%k$rJV$7$^$9!#\e(B
+
+\e$B$=$N%0%k!<%W$O!"%P%C%/%(%s%I$,$=$N%0%k!<%W$X$N5-;v$N<}G<$rMW5a$9$kA0$KB8\e(B
+\e$B:_$7$J$1$l$^$J$j$^$;$s!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-accept-article GROUP &optional SERVER LAST)
+
+\e$B$3$N4X?t$O!"8=:_$N%P%C%U%!$r<h$j!"$=$l$r\e(B @var{group} \e$B$NCf$KA^F~$7$^$9!#\e(B
+@var{last} \e$B$,\e(B @code{nil} \e$B$G$"$l$P!"$3$N4X?t$X$N$5$i$J$k8F$S=P$7$,D>$A$K\e(B
+\e$B9T$o$l$k$H$$$&0UL#$G$9!#\e(B
+
+\e$B$3$N4X?t$O%0%k!<%WL>$,\e(B @code{car} \e$B$G!"$=$N5-;v$N0\F0@h$N5-;vHV9f$,\e(B
+@code{cdr} \e$B$G$"$k\e(B cons \e$B%;%k$rJV$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-replace-article ARTICLE GROUP BUFFER)
+
+\e$B$3$N4X?t$O\e(B @var{article} (\e$BHV9f\e(B) \e$B$r\e(B @var{group} \e$B$+$i:o=|$7!"Be$o$j$K\e(B
+@var{buffer} \e$B$r$=$3$KA^F~$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-delete-group GROUP FORCE &optional SERVER)
+
+\e$B$3$N4X?t$O\e(B @var{group} \e$B$r>C5n$7$^$9!#$b$7\e(B @var{force} \e$B$,$"$l$P!"$=$N%0\e(B
+\e$B%k!<%WFb$NA4$F$N5-;v$rK\Ev$K>C5n$7!"$=$7$F$=$N%0%k!<%W<+?H$r>C5n$7$^$9!#\e(B
+(\e$B$b$7\e(B ``\e$B%0%k!<%W<+?H\e(B'' \e$B$H$$$&$b$N$,$"$l$P!#\e(B)
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+
+@item (nnchoke-request-rename-group GROUP NEW-NAME &optional SERVER)
+
+\e$B$3$N4X?t$O\e(B @var{group} \e$B$+$i\e(B @var{new-name} \e$B$KL>A0$rJQ99$7$^$9!#\e(B
+@var{group} \e$BFb$K$"$k5-;v$OA4$F\e(B @var{new-name} \e$B$K0\F0$7$^$9!#\e(B
+
+\e$BJV$5$l$k7k2L$N%G!<%?$O$"$j$^$;$s!#\e(B
+@end table
+
+@node Error Messaging
+@subsubsection \e$B%(%i!<%a%C%;!<%8I=<(\e(B
+
+@findex nnheader-report
+@findex nnheader-get-report
+\e$B%P%C%/%(%s%I$O%(%i!<>u67$rJs9p$9$k$N$K\e(B @code{nnheader-report} \e$B$r;H$o$J$/\e(B
+\e$B$F$O$J$j$^$;$s\e(B --- \e$BMW5a$r<B9T$G$-$J$$$H$-$K%(%i!<$r@85/$5$;$F$O$$$1$^$;\e(B
+\e$B$s!#$3$N4X?t$N:G=i$N0z?t$O%P%C%/%(%s%IL>$N%7%s%\%k$G!";D$j$O!"J#?t$N0z?t\e(B
+\e$B$,$"$l$P\e(B @code{format} \e$B$X$N0z?t$H$7$F2r<a$5$l!"0l$D$G$"$l$P$?$@$NJ8;zNs\e(B
+\e$B$K$J$j$^$9!#$3$N4X?t$O>o$K\e(B@code{nil} \e$B$rJV$5$J$/$F$O$J$j$^$;$s!#\e(B
+
+@lisp
+(nnheader-report 'nnchoke "You did something totally bogus")
+
+(nnheader-report 'nnchoke "Could not request group %s" group)
+@end lisp
+
+\e$B0lJ}\e(B gnus \e$B$O!"%5!<%P!<$+$i\e(B @code{nil} \e$B$rJV$5$l$?$H$-\e(B
+\e$B$K\e(B @code{nnheader-get-report} \e$B$r8F$S=P$7!"$=$7$F$3$N4X?t$,LdBj$N%P%C%/%(\e(B
+\e$B%s%I$KBP$7$F:G8e$KJs9p$5$l$?%a%C%;!<%8$rJV$7$^$9!#$3$N4X?t$O0l$D$N0z\e(B
+\e$B?t\e(B --- \e$B%5!<%P!<$N%7%s%\%k$r<h$j$^$9!#\e(B
+
+\e$BFbItE*$K$O!"$3$l$i$N4X?t$O\e(B @var{back-end}@code{-status-string} \e$B$K%"%/%;\e(B
+\e$B%9$^$9!"$D$^$j\e(B @code{nnchoke} \e$B%P%C%/%(%s%I$O$=$N%(%i!<%a%C%;!<%8\e(B
+\e$B$r\e(B @code{nnchoke-status-string} \e$B$K3JG<$7$^$9!#\e(B
+
+@node Writing New Back Ends
+@subsubsection \e$B?7$7$$%P%C%/%(%s%I$r=q$/\e(B
+
+\e$BB?$/$N%P%C%/%(%s%I$O$H$F$bN`;w$7$F$$$^$9!#\e(B
+@code{nnml} \e$B$O\e(B @code{nnspool} \e$B$K$H$F$b;w$F$$$^$9$,!"%5!<%P!<>e$N5-;v$rJT\e(B
+\e$B=8$9$k$3$H$,$G$-$^$9!#\e(B@code{nnmh} \e$B$O\e(B @code{nnml} \e$B$K$H$F$b;w$F$$$^$9$,!"\e(B
+\e$B$3$l$O%"%/%F%#%V%U%!%$%k$r;H$o$:!"35MW%G!<%?%Y!<%9$bJ];}$7$^$;$s!#\e(B
+@code{nndir} \e$B$O\e(B @code{nnml} \e$B$K$H$F$b;w$F$$$^$9$,!"$3$l$K\e(B
+\e$B$O\e(B ``\e$B%0%k!<%W\e(B'' \e$B$N35G0$O$J$/!"5-;v$N=$@5$O$G$-$^$;$s!#\e(B
+
+\e$B?7$7$$%P%C%/%(%s%I$r=q$/$H$-$KB>$N%P%C%/%(%s%I$+$i4X?t$r\e(B ``\e$B7Q>5\e(B'' \e$B$9$k$3\e(B
+\e$B$H$,2DG=$G$"$C$F$[$7$$!"$H;W$&$N$OM}$KE,$C$F$$$^$9!#$=$7$F$^$5$K!"$"$J$?\e(B
+\e$B$,$=$&$7$?$1$l$P!"$=$l$,$G$-$k$N$G$9!#\e(B(\e$B$"$J$?$,$=$&$7$?$/$J$1$l$P$7$J$/\e(B
+\e$B$F$bNI$$$G$9$h!"$b$A$m$s!#\e(B)
+
+\e$BA4$F$N%P%C%/%(%s%I$O8x3+JQ?t$H8x3+4X?t$r!"\e(B@code{nnoo} \e$B$H8F$P$l$k%Q%C%1!<\e(B
+\e$B%8$r;H$C$F@k8@$7$^$9!#\e(B
+
+\e$BB>$N%P%C%/%(%s%I$+$i4X?t$r7Q>5$9$k$K$O\e(B (\e$B$=$7$F8=:_$N%P%C%/%(%s%I$+$iB>$N\e(B
+\e$B%P%C%/%(%s%I$K4X?t$r7Q>5$G$-$k$h$&$K$9$k$K$O\e(B)\e$B!"0J2<$N%^%/%m$r;HMQ$7$J$1\e(B
+\e$B$l$P$J$j$^$;$s!#\e(B
+
+@table @code
+@item nnoo-declare
+\e$B$3$N%^%/%m$O!":G=i$N0z?t$r!"$=$N8e$KB3$/0z?t$N;R6!$G$"$k$3$H$r@k8@$7$^$9!#\e(B
+\e$BNc$($P!"\e(B
+
+@lisp
+(nnoo-declare nndir
+  nnml nnmh)
+@end lisp
+
+\e$B$3$l$G\e(B @code{nndir}\e$B$O!"\e(B@code{nnml} \e$B$H\e(B @code{nnmh} \e$B$NN>J}$+$i4X?t$r7Q>5$7\e(B
+\e$B$h$&$H$7$F$$$k$3$H$r@k8@$7$^$9!#\e(B
+
+@item defvoo
+\e$B$3$N%^%/%m$O\e(B @code{defvar} \e$B$HF15A$G$9$,!"$=$NJQ?t$r8x3+%5!<%P!<JQ?t$H$7\e(B
+\e$B$FEPO?$7$^$9!#$[$H$s$I$N>uBV;X8~7?$NJQ?t$O\e(B @code{defvar} \e$B$G$O$J\e(B
+\e$B$/\e(B @code{defvoo} \e$B$K$h$C$F@k8@$9$k$Y$-$G$9!#\e(B
+
+\e$BDL>o$N\e(B @code{defvar} \e$B0z?t$K2C$($F!"$3$N%^%/%m$O?F%P%C%/%(%s%I$NJQ?t$N%j\e(B
+\e$B%9%H$r<h$j!"$3$N4X?t$,$=$N%P%C%/%(%s%IFb$G<B9T$5$l$k$H$-$KJQ?t$rCV$-49$(\e(B
+\e$B$^$9!#\e(B
+
+@lisp
+(defvoo nndir-directory nil
+  "Where nndir will look for groups."
+  nnml-current-directory nnmh-current-directory)
+@end lisp
+
+\e$B$3$l$O\e(B @code{nndir} \e$B$N$?$a$K\e(B @code{nnml} \e$B$N4X?t$,8F$S=P$5$l$?$H$-$K!"\e(B
+@code{nnml-current-directory} \e$B$O\e(B @code{nndir-directory} \e$B$K@_Dj$5$l$k$H$$\e(B
+\e$B$&0UL#$G$9!#\e(B(@code{nnmh} \e$B$bF1MM$G$9!#\e(B)
+
+@item nnoo-define-basics
+\e$B$3$N%^%/%m$O!"$[$H$s$IA4It$N%P%C%/%(%s%I$,;}$D$Y$-6&DL4X?t$r$$$/$D$+Dj5A\e(B
+\e$B$7$^$9!#\e(B
+
+@lisp
+(nnoo-define-basics nndir)
+@end lisp
+
+@item deffoo
+\e$B$3$N%^%/%m$O$^$5$K\e(B @code{defun} \e$B$N$h$&$J$b$N$G!"F10l$N0z?t$r<h$j$^$9!#DL\e(B
+\e$B>o$N\e(B @code{defun} \e$B=hM}$K2C$($F!"$3$N%^%/%m$O$=$N4X?t$r8x3+$7$F$$$k$b$N$H\e(B
+\e$B$7$FEPO?$7!"B>$N%P%C%/%(%s%I$,$=$l$r7Q>5$G$-$k$h$&$K$7$^$9!#\e(B
+
+@item nnoo-map-functions
+\e$B$3$N%^%/%m$O8=:_$N%P%C%/%(%s%I$N4X?t$+$i?F%P%C%/%(%s%I$N4X?t$X$NCV$-49$(\e(B
+\e$B$r9T$J$($k$h$&$K$7$^$9!#\e(B
+
+@lisp
+(nnoo-map-functions nndir
+  (nnml-retrieve-headers 0 nndir-current-group 0 0)
+  (nnmh-request-article 0 nndir-current-group 0 0))
+@end lisp
+
+\e$B$3$l$O\e(B @code{nndir-retrieve-headers} \e$B$,8F$S=P$5$l$?$H$-!"0lHVL\!";0HVL\!"\e(B
+\e$B;MHVL\$N0z?t$,\e(B @code{nnml-retrieve-headers} \e$B$KEO$5$l!"0lJ}!"FsHVL\$N0z?t\e(B
+\e$B$O\e(B @code{nndir-current-group} \e$B$NCM$H$7$F@_Dj$5$l$k!"$H$$$&0UL#$G$9!#\e(B
+
+@item nnoo-import
+\e$B$3$N%^%/%m$OB>$N%P%C%/%(%s%I$+$i4X?t$r<h$j9~$_$^$9!#$3$l$OC1$K$^$@Dj5A$5\e(B
+\e$B$l$F$$$J$$4X?t$rDj5A$9$k$@$1$J$N$G!"%=!<%9%U%!%$%k$N:G8e$N=hM}$H$7$F=q$+\e(B
+\e$B$J$1$l$P$J$j$^$;$s!#\e(B
+
+@lisp
+(nnoo-import nndir
+  (nnmh
+   nnmh-request-list
+   nnmh-request-newgroups)
+  (nnml))
+@end lisp
+
+\e$B$3$l$O!"\e(B@code{nndir-request-list} \e$B$X$N8F$S=P$7$OC1\e(B
+\e$B$K\e(B @code{nnmh-request-list} \e$B$K0z$-EO$5$l!"0lJ}!"\e(B@code{nnml} \e$B$N8x3+4X?t$G\e(B
+\e$B$^$@\e(B @code{nndir} \e$B$GDj5A$5$l$F$$$J$$$b$N$r$3$3$GDj5A$7$^$9!#\e(B
+@end table
+
+\e$B0J2<$O\e(B @code{nndir} \e$B%P%C%/%(%s%I$N$A$g$C$HC;=L$7$?HG$G$9!#\e(B
+
+@lisp
+;;; @r{nndir.el --- single directory newsgroup access for Gnus}
+;; @r{Copyright (C) 1995,96 Free Software Foundation, Inc.}
+
+;;; @r{Code:}
+
+(require 'nnheader)
+(require 'nnmh)
+(require 'nnml)
+(require 'nnoo)
+(eval-when-compile (require 'cl))
+
+(nnoo-declare nndir
+  nnml nnmh)
+
+(defvoo nndir-directory nil
+  "Where nndir will look for groups."
+  nnml-current-directory nnmh-current-directory)
+
+(defvoo nndir-nov-is-evil nil
+  "*Non-nil means that nndir will never retrieve NOV headers."
+  nnml-nov-is-evil)
+
+(defvoo nndir-current-group ""
+  nil
+  nnml-current-group nnmh-current-group)
+(defvoo nndir-top-directory nil nil nnml-directory nnmh-directory)
+(defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail)
+
+(defvoo nndir-status-string "" nil nnmh-status-string)
+(defconst nndir-version "nndir 1.0")
+
+;;; @r{Interface functions.}
+
+(nnoo-define-basics nndir)
+
+(deffoo nndir-open-server (server &optional defs)
+  (setq nndir-directory
+        (or (cadr (assq 'nndir-directory defs))
+            server))
+  (unless (assq 'nndir-directory defs)
+    (push `(nndir-directory ,server) defs))
+  (push `(nndir-current-group
+          ,(file-name-nondirectory
+            (directory-file-name nndir-directory)))
+        defs)
+  (push `(nndir-top-directory
+          ,(file-name-directory (directory-file-name nndir-directory)))
+        defs)
+  (nnoo-change-server 'nndir server defs))
+
+(nnoo-map-functions nndir
+  (nnml-retrieve-headers 0 nndir-current-group 0 0)
+  (nnmh-request-article 0 nndir-current-group 0 0)
+  (nnmh-request-group nndir-current-group 0 0)
+  (nnmh-close-group nndir-current-group 0))
+
+(nnoo-import nndir
+  (nnmh
+   nnmh-status-message
+   nnmh-request-list
+   nnmh-request-newgroups))
+
+(provide 'nndir)
+@end lisp
+
+@node Hooking New Back Ends Into Gnus
+@subsubsection \e$B?7$7$$%P%C%/%(%s%I$r\e(B gnus \e$B$K7R$2$k\e(B
+
+@vindex gnus-valid-select-methods
+@findex gnus-declare-backend
+\e$B$"$J$?$N?7$7$$%P%C%/%(%s%I$r\e(B gnus \e$B$G;H$$$O$8$a$k$N$O$H$F$b4JC1$G\e(B
+\e$B$9\e(B --- \e$BC1$K\e(B @code{gnus-declare-backend} \e$B4X?t$G@k8@$9$k$@$1$G$9!#$3$l$O%P%C\e(B
+\e$B%/%(%s%I$r\e(B @code{gnus-valid-select-methods} \e$BJQ?t$KDI2C$7$^$9!#\e(B
+
+@code{gnus-declare-backend} \e$B$OFs$D$N0z?t$r<h$j$^$9\e(B --- \e$B%P%C%/%(%s%I$NL>\e(B
+\e$BA0$HE,Ev$J?t$NG=NO\e(B @dfn{abilities} \e$B$G$9!#\e(B
+
+\e$B$3$l$,Nc$G$9!#\e(B
+
+@lisp
+(gnus-declare-backend "nnchoke" 'mail 'respool 'address)
+@end lisp
+
+\e$B$=$7$F>e5-$N9T$O\e(B @file{nnchoke.el} \e$B%U%!%$%k$KF~$l$^$9!#\e(B
+
+\e$BG=NO$K$O0J2<$N$b$N$,$"$j$^$9!#\e(B
+
+@table @code
+@item mail
+\e$B$3$l$O%a!<%kIw%P%C%/%(%s%I$G$9\e(B --- \e$B%U%)%m!<%"%C%W$O\e(B (\e$B$?$$$F$$$O\e(B) \e$B%a!<%k\e(B
+\e$B$GAw$i$l$^$9!#\e(B
+@item post
+\e$B$3$l$O%K%e!<%9Iw%P%C%/%(%s%I$G$9\e(B --- \e$B%U%)%m!<%"%C%W$O\e(B (\e$B$?$$$F$$$O\e(B) \e$B%K%e!<\e(B
+\e$B%9$GAw$i$l$^$9!#\e(B
+@item post-mail
+\e$B$3$N%P%C%/%(%s%I$O%a!<%k$H%K%e!<%9$NN>J}$r%5%]!<%H$7$^$9!#\e(B
+@item none
+\e$B$3$l$O%K%e!<%9$G$b%a!<%k$G$b$J$$%P%C%/%(%s%I$G$9\e(B --- \e$BA4$/0c$C$?2?$+$G$9!#\e(B
+@item respool
+\e$B$3$l$O:F%9%W!<%k$r%5%]!<%H$7$^$9\e(B --- \e$B$H$$$&$h$j$O!"$=$N85$N5-;v$H%0%k!<\e(B
+\e$B%W$r=$@5$9$k$3$H$,$G$-$^$9!#\e(B
+@item address
+\e$B2>A[%5!<%P!<L>$NCf$K%5!<%P!<$NL>A0$,4^$^$k$H$$$&$3$H$G$9!#$3$l$O$[$H$s$I\e(B
+\e$BA4It$N%P%C%/%(%s%I$GI,MW$K$J$j$^$9!#\e(B
+@item prompt-address
+\e$B%0%k!<%W%P%C%U%!$G\e(B @kbd{B} \e$B$J$I$G$3$NL?Na$r<B9T$7$?$H$-!"%f!<%6$O%"%I%l\e(B
+\e$B%9$N%W%m%s%W%HF~NO$r5a$a$i$l$^$9!#$3$l$ONc$($P!"\e(B@code{nntp} \e$B$N$h$&$J%P%C\e(B
+\e$B%/%(%s%I$G$OI,MW$G!"\e(B@code{nnmbox} \e$B$G$OI,MW$G$O$"$j$^$;$s!#\e(B
+@end table
+
+@node Mail-like Back Ends
+@subsubsection \e$B%a!<%kIw%P%C%/%(%s%I\e(B
+
+\e$B%a!<%k%P%C%/%(%s%I$,$=$NB>$N%P%C%/%(%s%I$KBP$7$F0l@~$r2h$7$F$$$kE@$O!"$[\e(B
+\e$B$H$s$I$N%a!<%k%P%C%/%(%s%I$O\e(B @file{nnmail.el} \e$B$NCf$N6&DL4X?t$K6/$/0MB8$7\e(B
+\e$B$F$$$k$H$$$&E@$G$9!#Nc$($P!"\e(B@code{nnml-request-scan} \e$B$NDj5A$O$3$N$h$&$K\e(B
+\e$B$J$j$^$9!#\e(B
+
+@lisp
+(deffoo nnml-request-scan (&optional group server)
+  (setq nnml-article-file-alist nil)
+  (nnmail-get-new-mail 'nnml 'nnml-save-nov nnml-directory group))
+@end lisp
+
+\e$BC1$K\e(B @code{nnmail-get-new-mail} \e$B$K$$$/$D$+0z?t$rM?$($F8F$S=P$9$@$1$G!"\e(B
+@code{nnmail} \e$B$,%a!<%k$N0\F0$dJ,N%$rA4$F$NLLE]$r8+$F$/$l$^$9!#\e(B
+
+\e$B$3$N4X?t$O;M$D$N0z?t$r<h$j$^$9!#\e(B
+
+@table @var
+@item method
+\e$B$3$l$O!"$3$N8F$S=P$7$r$I$N%P%C%/%(%s%I$,@UG$$rIi$&$+$r;X<($9$k%7%s%\%k$G\e(B
+\e$B$9!#\e(B
+
+@item exit-function
+\e$B$3$N4X?t$OJ,N%$,<B9T$5$l$?8e$K8F$S=P$5$l$^$9!#\e(B
+
+@item temp-directory
+\e$B0l;~%U%!%$%k$r3JG<$9$k>l=j$G$9!#\e(B
+
+@item group
+\e$B$3$N>JN,2DG=$J0z?t$O!"J,N%$,0l$D$N%0%k!<%W$KBP$7$F$N$_<B9T$5$l$k$Y$-$G$"\e(B
+\e$B$k$H$-$N%0%k!<%WL>$G$9!#\e(B
+@end table
+
+@code{nnmail-get-new-mail} \e$B$O3F5-;v$rJ]B8$9$k$?$a\e(B
+\e$B$K\e(B @var{back-end}@code{-save-mail} \e$B$r8F$S=P$7$^$9!#\e(B
+@var{back-end}@code{-active-number} \e$B$O$3$N5-;v$K3d$jEv$F$i$l$?5-;vHV9f$r\e(B
+\e$BD4$Y$k$?$a$K8F$S=P$5$l$^$9!#\e(B
+
+\e$B$3$N4X?t$O<!$NJQ?t$b;HMQ$7$^$9!#\e(B
+@var{back-end}@code{-get-new-mail} (\e$B$3$N%P%C%/%(%s%I$N?7Ce%a!<%k$rD4$Y$k\e(B
+\e$B$+$I$&$+\e(B) \e$B$H!"?7$7$$%"%/%F%#%V%U%!%$%k$r@8@.$9$k$?$a\e(B
+\e$B$N\e(B @var{back-end}@code{-group-alist} \e$B$H\e(B @var{back-end}@code{-active-file} \e$B$G\e(B
+\e$B$9!#\e(B@var{back-end}@code{-group-alist} \e$B%0%k!<%W$N%"%/%F%#%VO"A[%j%9%H$G!"\e(B
+\e$B0J2<$N$h$&$J$b$N$G$9!#\e(B
+
+@example
+(("a-group" (1 . 10))
+ ("some-group" (34 . 39)))
+@end example
+
+@node Score File Syntax
+@subsection \e$B%9%3%"%U%!%$%k$N9=J8\e(B
+
+\e$B%9%3%"%U%!%$%k$O4JC1$KJ,@O2DG=$G!"$7$+$7Hs>o$K=@Fp$J$h$&$K0U?^$5$l$F$$$^\e(B
+\e$B$9!#$=$l$K$O\e(B Emacs Lisp \e$B$N%j%9%H$HF1$8FI$_9~$_9=J8$JMM$J$b$N$,$=$N;XDj$K\e(B
+\e$B9g$&$@$m$&$H$$$&;v$,7hDj$5$l$^$7$?!#\e(B
+
+\e$B$3$l$ONI$/$"$k%9%3%"%U%!%$%k$G$9\e(B:
+
+@lisp
+(("summary"
+  ("win95" -10000 nil s)
+  ("Gnus"))
+ ("from"
+  ("Lars" -1000))
+ (mark -100))
+@end lisp
+
+\e$B%9%3%"%U%!%$%k$N\e(B BNF \e$BDj5A$G$9!#\e(B
+
+@example
+score-file      = "" / "(" *element ")"
+element         = rule / atom
+rule            = string-rule / number-rule / date-rule
+string-rule     = "(" quote string-header quote space *string-match ")"
+number-rule     = "(" quote number-header quote space *number-match ")"
+date-rule       = "(" quote date-header quote space *date-match ")"
+quote           = <ascii 34>
+string-header   = "subject" / "from" / "references" / "message-id" /
+                  "xref" / "body" / "head" / "all" / "followup"
+number-header   = "lines" / "chars"
+date-header     = "date"
+string-match    = "(" quote <string> quote [ "" / [ space score [ "" /
+                  space date [ "" / [ space string-match-t ] ] ] ] ] ")"
+score           = "nil" / <integer>
+date            = "nil" / <natural number>
+string-match-t  = "nil" / "s" / "substring" / "S" / "Substring" /
+                  "r" / "regex" / "R" / "Regex" /
+                  "e" / "exact" / "E" / "Exact" /
+                  "f" / "fuzzy" / "F" / "Fuzzy"
+number-match    = "(" <integer> [ "" / [ space score [ "" /
+                  space date [ "" / [ space number-match-t ] ] ] ] ] ")"
+number-match-t  = "nil" / "=" / "<" / ">" / ">=" / "<="
+date-match      = "(" quote <string> quote [ "" / [ space score [ "" /
+                  space date [ "" / [ space date-match-t ] ] ] ] ")"
+date-match-t    = "nil" / "at" / "before" / "after"
+atom            = "(" [ required-atom / optional-atom ] ")"
+required-atom   = mark / expunge / mark-and-expunge / files /
+                  exclude-files / read-only / touched
+optional-atom   = adapt / local / eval
+mark            = "mark" space nil-or-number
+nil-or-number   = "nil" / <integer>
+expunge         = "expunge" space nil-or-number
+mark-and-expunge = "mark-and-expunge" space nil-or-number
+files           = "files" *[ space <string> ]
+exclude-files   = "exclude-files" *[ space <string> ]
+read-only       = "read-only" [ space "nil" / space "t" ]
+adapt        = "adapt" [ space "ignore" / space "t" / space adapt-rule ]
+adapt-rule      = "(" *[ <string> *[ "(" <string> <integer> ")" ] ")"
+local           = "local" *[ space "(" <string> space <form> ")" ]
+eval            = "eval" space <form>
+space           = *[ " " / <TAB> / <NEWLINE> ]
+@end example
+
+\e$B%9%3%"%U%!%$%k$NG'<1IT2DG=$JMWAG$OL5;k$5$l$k$Y$-$G$9$,!"<N$F$i$l$k$o$1$G\e(B
+\e$B$O$"$j$^$;$s!#\e(B
+
+\e$B$4Mw$NDL$j!"6uGr$,I,MW$G$9$,!"6uGr$NNL$H7?$OL54X78$G$9!#$3$l$O%9%3%"%U%!\e(B
+\e$B%$%k$NMM<0$O%W%m%0%i%^!<$KG$$5$l$F$$$k$H$$$&;v$G$9\e(B---\e$BA4$F$r0l$D$ND9!<!<\e(B
+\e$B$$9T$KEG$-=P$9$N$,4JC1$G$"$l$P!"$=$l$O9=$$$^$;$s!#\e(B
+
+\e$B$$$m$$$m$J%"%H%`$N0UL#$O$3$N%^%K%e%"%k$N$I$3$+$G@bL@$5$l$F$$$^\e(B
+\e$B$9\e(B (@pxref{Score File Format})\e$B!#\e(B
+
+@node Headers
+@subsection \e$B%X%C%@!<\e(B
+
+\e$BFbItE*$K$O\e(B gnus \e$B$OIT;W5D$JN.57$G!"\e(B@acronym{NOV} \e$BMM<0$KBP1~$9$k5-;v$N%X%C\e(B
+\e$B%@!<$rN/$a$F$*$/MM<0$r;H$$$^$9!#$"$k?M$O!":n<T$,\e(B @acronym{NOV} \e$B$N;EMM$r\e(B
+\e$B8+$FCQ$8$k;vL5$/A4$F$r\e(B @emph{\e$BEp$s$@\e(B} \e$B$H;W$&$+$b$7$l$^$;$s$,!"$=$N?M$O@5\e(B
+\e$B$7$$$G$9!#\e(B
+
+@dfn{\e$B%X%C%@!<\e(B} \e$B$OHs>o$KIiC4$N$+$1$i$l$9$.$?8l$G$9!#\e(B
+``\e$B%X%C%@!<\e(B'' \e$B$O\e(B RFC1036 \e$B$G$O5-;v$NF,$N9T$N;v\e(B (\e$BNc$($P!"\e(B@code{From}) \e$B$rOC\e(B
+\e$B$9$N$KMQ$$$i$l$F$$$^$9!#$=$l$OB?$/$N?M$+\e(B
+\e$B$i\e(B ``\e$B%X%C%I\e(B''---``\e$B%X%C%@!<$HK\BN\e(B'' \e$B$NF15A8l$H$7$F;H$o$l$F$$$^$9!#\e(B(\e$B$3$l\e(B
+\e$B$O!";d$N0U8+$G$OHr$1$i$l$k$Y$-$G$9!#\e(B) \e$B$=$7$F!"\e(Bgnus \e$B$OFbIt$G\e(B
+\e$B$O\e(B ``\e$B%X%C%@!<\e(B'' \e$B$H8F$VMM<0$r;H$C$F$*$j!";d$O$3$3$G$=$l$K$D$$$F@bL@$7$^$9!#\e(B
+\e$B$3$l$O6e$D$NMWAG$+$i$J$k%Y%/%H%k$G!"4pK\E*$K!"$=$l$>$l$N%X%C\e(B
+\e$B%@!<\e(B (\e$B$"DK\e(B) \e$B$,0l$D$N6u$->l=j$r@j$a$F$$$^$9!#\e(B
+
+\e$B$3$l$i$N6u$->l=j$O!"=gHV$K\e(B: @code{number}, @code{subject}, @code{from},
+@code{date}, @code{id}, @code{chars}, @code{lines}, @code{xref},
+@code{extra} \e$B$G$9!#$3$l$i$N6u$->l=j$K?($C$F@_Dj$9$k%^%/%m$,$"$j$^\e(B
+\e$B$9\e(B --- \e$B$=$l$i$OA4$F!"$=$l$>\e(B
+\e$B$l\e(B @code{mail-header-} \e$B$H\e(B @code{mail-header-set-} \e$B$$$&M=A[$5$l$kL>A0$r;}$C\e(B
+\e$B$F$$$^$9!#\e(B
+
+@code{extra} \e$B$N>l=j$O%X%C%@!<\e(B/\e$BCM$NBP$NO"A[%j%9%H$G$"$k0J30$O$3$l$i$NA4$F\e(B
+\e$B$N>l=j$OJ8;zNs$G$9\e(B (@pxref{To From Newsgroups})\e$B!#\e(B
+
+@node Ranges
+@subsection \e$BHO0O\e(B
+
+@sc{gnus} \e$B$O;d$K$OHs>o$KLr$KN)$D$H;W$o$l$k35G0$rF3F~$7$^$7$?$N$G!";d$O$=\e(B
+\e$B$l$r$?$/$5$s;H$$!"$+$J$jG0F~$j$K:n$j>e$2$F$-$^$7$?!#\e(B
+
+\e$B<ALd$OC1=c$G$9\e(B: \e$B$b$7$"$J$?$,BgNL$N?t;z$K$h$jF10l@-$rJ]>Z$5$l$k\e(B \e$B$b\e(B
+\e$B$N\e(B (object) (@emph{\e$BMpK=$J\e(B} \e$BNc$r5s$2$k$H!"5-;v$,$=$&$G\e(B
+\e$B$9\e(B) \e$B$r\e(B ``\e$B4^$^$l$F$$$k\e(B'' \e$B$H$7$F8+$J$7$?$$$H$-$O!"IaDL$NO"B3E*9T0Y$O$"$^$j\e(B
+\e$BLr$KN)$A$^$;$s!#\e(B(\e$BD9$5\e(B 200,000 \e$B$NO"B3J*$O>/$7B)$,D9$9$.$^$9!#\e(B)
+
+\e$B$3$l$N2r7h:v$O<ALd$HF1$8$/$i$$C1=c$G$9!#C1$K$=$NO"B3J*$r2u$;$PNI$$$@$1$G\e(B
+\e$B$9!#\e(B
+
+@example
+(1 2 3 4 5 6 10 11 12)
+@end example
+
+\e$B$O<!$N$b$N$KJQ7A$5$l$^$9!#\e(B
+
+@example
+((1 . 6) (10. 12))
+@end example
+
+\e$B$"$N7y$J\e(B @samp{(13. 13)} \e$B$N$h$&$JMWAG$rHr$1$k$?$a$K!"$=$l$N$_$N\e(B \e$B$b\e(B
+\e$B$N\e(B (object) \e$B$r<($9$?$a$K\e(B @samp{13} \e$B$OM-8z$JMWAG$K$J$C$F$$$^$9!#\e(B
+
+@example
+((1 . 6) 7 (10 . 12))
+@end example
+
+\e$B$3$l$OFs$D$NHO0O$rHf3S$7$F$=$l$,Ey2A\e(B (equal) \e$B$G$"$k$+$rD4$Y$k;v$O>/$7<j\e(B
+\e$B$N$3$s$@$3$H$K$J$j$^$9\e(B:
+
+@example
+((1 . 5) 7 8 (10 . 12))
+@end example
+
+\e$B$H\e(B
+
+@example
+((1 . 5) (7. 8) (10 . 12))
+@end example
+
+\e$B$OEy2A$G$9!#<B:]$N$H$3$m!"2<9_$7$J$$%j%9%H$OHO0O$G$9\e(B:
+
+@example
+(1 2 3 4 5)
+@end example
+
+\e$B$O40A4$KM-8z$JHO0O$G$9!#$H$F$bB)$ND9$$$b$N$G$9$,!#$3$l$bM-8z$G$9\e(B:
+
+@example
+(1 . 5)
+@end example
+
+\e$B$=$7$F!"$3$l$OA0$NHO0O$HEy2A$G$9!#\e(B
+
+\e$B$3$l$OHO0O$N\e(B BNF \e$BDj5A$G$9!#$b$A$m$s!"?t;z$N0UL#>e$NMW5a$O2<9_$7$F$$$J$$\e(B
+\e$B$H$$$&;v$O3P$($F$*$/I,MW$,$"$j$^$9!#\e(B(\e$BG$0U$N2s?t$NF1$8?t;z$N7+$jJV$7$O5v\e(B
+\e$B$5$l$F$$$^$9$,!"HO0O$N07$$$+$i$O>C$(5n$k798~$,$"$j$^$9!#\e(B)
+
+@example
+range           = simple-range / normal-range
+simple-range    = "(" number " . " number ")"
+normal-range    = "(" start-contents ")"
+contents        = "" / simple-range *[ " " contents ] /
+                  number *[ " " contents ]
+@end example
+
+Gnus \e$B$O8=:_$N$H$3$m4{FI5-;v$H5-;v$N0u$N>pJs$rIU$1$F$*$/$?$a$KHO0O$r;H$C\e(B
+\e$B$F$$$^$9!#;d$O\e(B \e$B<!$N8"NO<T\e(B \e$B$,;d$K$5$;$F$/$l$k$N$G$"$l$P!"\e(BC \e$B$G?t$NHO0O$N<B\e(B
+\e$BAu$r7W2h$7$F$$$^$9!#\e(B(\e$B;d$O$^$@$=$N?M$K?R$M$F$$$^$;$s!#$H8@$&$N$O!";d$O$=\e(B
+\e$B$l$rIaDL$NO"B3J*$KJQ49$7D>$5$J$$$G@$$NCf$r40A4$KHO0O$K4p$E$$$?$b$N$K$9$k\e(B
+\e$B$?$a$K$b$&>/$79M$($kI,MW$,$"$k$+$i$G$9!#\e(B)
+
+@node Group Info
+@subsection \e$B%0%k!<%W>pJs\e(B
+
+Gnus \e$B$O%0%k!<%W$NA4$F$N1JB3>pJs$r\e(B @dfn{group info} \e$B%j%9%H$KJ]B8$7$^$9!#\e(B
+\e$B$3$N%j%9%H$ND9$5$O\e(B 3 \e$B$+$i\e(B 6 (\e$B$b$7$/$O$b$C$H\e(B) \e$B$NMWAG$GE0DlE*$K%0%k!<%W$r\e(B
+\e$B5-=R$7$^$9!#\e(B
+
+\e$B$3$3$K$"$k$N$O%0%k!<%W>pJs\e(B (group info) \e$B$NFs$D$NNc$G$9!#0l$D$OHs>o$KC1=c\e(B
+\e$B$J%0%k!<%W$G!"Fs$D$a$O$b$C$HJ#;($J$b$N$G$9\e(B:
+
+@example
+("no.group" 5 ((1 . 54324)))
+
+("nnml:my.mail" 3 ((1 . 5) 9 (20 . 55))
+                ((tick (15 . 19)) (replied 3 6 (19 . 3)))
+                (nnml "")
+                ((auto-expire . t) (to-address . "ding@@gnus.org")))
+@end example
+
+\e$B:G=i$NMWAG$O\e(B @dfn{\e$B%0%k!<%WL>\e(B} \e$B$G$9\e(B---\e$B$I$N$h$&$K$7$m!"\e(Bgnus \e$B$,$=$l$K$h$C$F\e(B
+\e$B%0%k!<%W$rCN$C$F$$$k$b$N$G$9!#FsHVL\$NMWAG$O\e(B @dfn{\e$B9XFIEY\e(B} \e$B$G!"IaDL$O>.$5\e(B
+\e$B$J@0?t$G$9!#\e(B(\e$B$=$l$O\e(B @dfn{\e$B3,5i\e(B} \e$B$K$J$k;v$b$G$-$^$9!#$=$l$O!"%3%s%9%;%k$G!"\e(B
+@code{car} \e$B$,%l%Y%k$G!"\e(B@code{cdr} \e$B$,%9%3%"$G$9!#\e(B) \e$B;0HVL\$NMWAG$O4{FI5-;v\e(B
+\e$B$NHO0O$N%j%9%H$G$9!#;MHVL\$NMWAG$O$$$m$$$m$J<oN`$N5-;v$N0u$N%j%9%H$N%j%9\e(B
+\e$B%H$G$9!#8^HVL\$NMWAG$OA*BrJ}K!$G$9\e(B (\e$B$b$7$/$O!"$3$A$i$NJ}$,NI$$$N$G$"$l$P\e(B
+\e$B;v<B>e$N%5!<%P!<$G$9\e(B)\e$B!#O;HVL\$NMWAG$O\e(B @dfn{\e$B%0%k!<%W%Q%i%a!<%?\e(B} \e$B$N%j%9%H\e(B
+\e$B$G!"$3$NItJ,$O$=$N$?$a$K$"$j$^$9!#\e(B
+
+\e$B:G8e$N;0$D$NMWAG$O$I$l$G$b!"I,MW$,L5$1$l$PB8:_$7$J$$;v$b$"$j$^$9!#<B:]!"\e(B
+\e$B%0%k!<%W$NHs>o$KBgItJ,$O:G=i$N;0$D$NMWAG$@$1$r;}$A!"$=$l$O$?$/$5$s$N%3%s\e(B
+\e$B%9%;%k$r@aLs$9$k;v$,$G$-$^$9!#\e(B
+
+\e$B$3$l$O%0%k!<%W>pJsMM<0$N\e(B BNF \e$BDj5A$G$9\e(B:
+
+@example
+info          = "(" group space ralevel space read
+                [ "" / [ space marks-list [ "" / [ space method [ "" /
+                space parameters ] ] ] ] ] ")"
+group         = quote <string> quote
+ralevel       = rank / level
+level         = <integer in the range of 1 to inf>
+rank          = "(" level "." score ")"
+score         = <integer in the range of 1 to inf>
+read          = range
+marks-lists   = nil / "(" *marks ")"
+marks         = "(" <string> range ")"
+method        = "(" <string> *elisp-forms ")"
+parameters    = "(" *elisp-forms ")"
+@end example
+
+\e$B<B$N$H$3$mK!B'\e(B @samp{marks} \e$B$O13$G$9!#\e(B
+@samp{marks} \e$B$O\e(B @samp{<string>} \e$B$,\e(B @samp{range} \e$B$N>e$K9=@.$5$l$F$$$k$b$N\e(B
+\e$B$G$9$,!"5?;w\e(B BNF \e$B$G$=$l$r8=$9$N$OITL{2w$J$b$N$G$9!#\e(B
+
+\e$B$b$7\e(B gnus \e$B>pJs$r;}$C$F$$$F!"MWAG$rD4$Y$?$$$N$H$-$O!"\e(Bgnus \e$B$O$=$l$i$NMWAG\e(B
+\e$B$r<hF@\e(B/\e$B@_Dj\e(B (get/set) \e$B$9$k$?$a$N0lO"$N%^%/%m$rDs6!$7$F$$$^$9!#\e(B
+
+@table @code
+@item gnus-info-group
+@itemx gnus-info-set-group
+@findex gnus-info-group
+@findex gnus-info-set-group
+\e$B%0%k!<%WL>$r<hF@\e(B/\e$B@_Dj\e(B (get/set) \e$B$7$^$9!#\e(B
+
+@item gnus-info-rank
+@itemx gnus-info-set-rank
+@findex gnus-info-rank
+@findex gnus-info-set-rank
+\e$B%0%k!<%W$N3,5i\e(B (rank) \e$B$r<hF@\e(B/\e$B@_Dj$7$^$9\e(B (@pxref{Group Score})\e$B!#\e(B
+
+@item gnus-info-level
+@itemx gnus-info-set-level
+@findex gnus-info-level
+@findex gnus-info-set-level
+\e$B%0%k!<%W$N%l%Y%k$r<hF@\e(B/\e$B@_Dj$7$^$9!#\e(B
+
+@item gnus-info-score
+@itemx gnus-info-set-score
+@findex gnus-info-score
+@findex gnus-info-set-score
+\e$B%0%k!<%W%9%3%"$r<hF@\e(B/\e$B@_Dj$7$^$9\e(B (@pxref{Group Score})\e$B!#\e(B
+
+@item gnus-info-read
+@itemx gnus-info-set-read
+@findex gnus-info-read
+@findex gnus-info-set-read
+\e$B4{FI5-;v$NHO0O$r<hF@\e(B/\e$B@_Dj$7$^$9!#\e(B
+
+@item gnus-info-marks
+@itemx gnus-info-set-marks
+@findex gnus-info-marks
+@findex gnus-info-set-marks
+\e$B0u$7$D$-5-;v$NHO0O$N%j%9%H$r<hF@\e(B/\e$B@_Dj$7$^$9!#\e(B
+
+@item gnus-info-method
+@itemx gnus-info-set-method
+@findex gnus-info-method
+@findex gnus-info-set-method
+\e$B%0%k!<%WA*BrJ}K!$r<hF@\e(B/\e$B@_Dj$7$^$9!#\e(B
+
+@item gnus-info-params
+@itemx gnus-info-set-params
+@findex gnus-info-params
+@findex gnus-info-set-params
+\e$B%0%k!<%W%Q%i%a!<%?$r<hF@\e(B/\e$B@_Dj$7$^$9!#\e(B
+@end table
+
+\e$BA4$F$N<hF@4X?t$O0l$D$N0z?t$r<h$j$^$9\e(B---\e$B>pJs$N%j%9%H$G$9!#@_Dj4X?t$OFs$D\e(B
+\e$B$N0z?t$r<h$j$^$9\e(B---\e$B>pJs%j%9%H$H?7$7$$CM$G$9!#\e(B
+
+\e$B%0%k!<%W>pJs$N:G8e$N;0$D$NMWAG$O6/@)E*$J$b$N$G$O$"$j$^$;$s$N$G!"MWAG$r@_\e(B
+\e$BDj$9$kA0$K%0%k!<%W>pJs$r3HD%$9$kI,MW$,$"$k$+$bCN$l$^$;$s!#$b$7$3$l$,I,MW\e(B
+\e$B$J>l9g$O!"$3$l$,<+F0E*$K5/$3$k$?$a$K\e(B @code{nil} \e$B$G$J$$;0HVL\$N0z?t$r;0$D\e(B
+\e$B$N:G=*@_Dj4X?t$KM?$($k$@$1$G$9!#\e(B
+
+@node Extended Interactive
+@subsection \e$B3HD%BPOC\e(B
+@cindex interactive
+@findex gnus-interactive
+
+Gnus \e$B$O\e(B Emacs \e$B$NI8=`$N\e(B @code{interactive} \e$B;XDj$r%7%s%\%k@\F,<-$r4JC1$K;H\e(B
+\e$B$($k$?$a$K>/$73HD%$7$F$$$^$9\e(B (@pxref{Symbolic Prefixes})\e$B!#$3$l$O$=$N;H$$\e(B
+\e$BJ}$NNc$G$9\e(B:
+
+@lisp
+(defun gnus-summary-increase-score (&optional score symp)
+  (interactive (gnus-interactive "P\ny"))
+  ...
+  )
+@end lisp
+
+\e$B:G>e$NJ}K!$O\e(B @code{gnus-interactive} \e$B$r<0\e(B @code{interactive} \e$B$rJV$9%^%/\e(B
+\e$B%m$H$7$F<BAu$9$k;v$G$7$g$&$,!"$3$l$O\e(B Emacs \e$B$O4X?t$,BPOCE*$G$"$k$+$I$&$+\e(B
+\e$B$r%i%`%@<0$KBP$7$FC1=c$K\e(B @code{assq} \e$B$r9T$&;v$K$h$jD4$Y$k;v$+$iIT2DG=$G\e(B
+\e$B$9!#\e(B
+
+\e$B$3$N4X?t$O\e(B (\e$B$[$H$s$I\e(B) \e$BA4$F$N\e(B @code{interactive} \e$B;XDj$r<uIU$1$^$9$,!"$b$&\e(B
+\e$B>/$72C$($^$9!#\e(B
+
+@table @samp
+@item y
+@vindex gnus-current-prefix-symbol
+\e$B8=:_$N@\F,0z?t%7%s%\%k\e(B---\e$BJQ?t\e(B @code{gnus-current-prefix-symbol} \e$B$G$9!#\e(B
+
+@item Y
+@vindex gnus-current-prefix-symbols
+\e$B8=:_$N@\F,0z?t%7%s%\%k$N%j%9%H$G$9\e(B---\e$BJQ\e(B
+\e$B?t\e(B @code{gnus-current-prefix-symbol} \e$B$G$9!#\e(B
+
+@item A
+\e$B8=:_$N5-;vHV9f$G$9\e(B---\e$B4X?t\e(B @code{gnus-summary-article-number} \e$B$G$9!#\e(B
+
+@item H
+\e$B8=:_$N5-;v%X%C%@!<$G$9\e(B---\e$B4X?t\e(B @code{gnus-summary-article-header} \e$B$G$9!#\e(B
+
+@item g
+\e$B8=:_$N%0%k!<%WL>$G$9\e(B---\e$B4X?t\e(B @code{gnus-group-group-name} \e$B$G$9!#\e(B
+@end table
+
+@node Emacs/XEmacs Code
+@subsection Emacs/XEmacs \e$B%3!<%I\e(B
+@cindex XEmacs
+@cindex Emacsen
+
+Gnus \e$B$O\e(B Emacs, XEmacs \e$B$H\e(B Mule \e$B$GF0:n$7$^$9$N$G!"$=$N$&$A$N0l$D$r<g4D6-$H\e(B
+\e$B$9$k;v$K7h$a$^$7$?!#;d$O\e(B Emacs \e$B$rA*$S$^$7$?!#;d$,\e(B XEmacs \e$B$d\e(B Mule \e$B$r9%$-\e(B
+\e$B$G$O$J$$$H8@$&;v$G$O$J$/!"$=$l$,%"%k%U%!%Y%C%H$G:G=i$KMh$?$+$i$G$9!#\e(B
+
+\e$B$3$l$O\e(B gnus \e$B$O\e(B Emacs \e$B$GA4$/7Y9p$J$/%P%$%H%3%s%Q%$%k$G$-$k$N$KBP$7$F!"\e(B
+XEmacs \e$B$O%P%$%H%3%s%Q%$%k$r$7$F$$$k4V$K%.%,%P%$%H$/$i$$$N7Y9p$r=P$9$H8@\e(B
+\e$B$&;v$G$9!#;d$O:3:Y$J<:GT$r8+$D$1=P$9$3$H$r=u$1$k$?$a$K%P%$%H%3%s%Q%$%k$N\e(B
+\e$B7Y9p$r;H$C$F$$$^$9$N$G!"$=$l$OHs>o$KLr$KN)$A$^$9!#\e(B
+
+\e$B;d$O7QB3E*$K\e(B Emacs \e$B$N4X?t$N3&LL\e(B (interface) \e$B$r;H$C$F$-$^$7$?$,!"4X?t$K\e(B
+\e$B$O\e(B gnus \e$B$NJLL>4X?t\e(B (alias) \e$B$r;H$C$F$-$^$7$?!#Nc$r=P$7$^$7$g$&\e(B: Emacs \e$B$O\e(B
+\e$B4X?t\e(B @code{run-at-time} \e$B$rDj5A$7$F$$$^$9$,!"\e(BXEmacs \e$B$O4X\e(B
+\e$B?t\e(B @code{start-itimer} \e$B$rDj5A$7$F$$$^$9!#$=$3$G;d\e(B
+\e$B$O\e(B @code{gnus-run-at-time} \e$B$H8F$P$l$k4X?t$rDj5A$7!"$=$l\e(B
+\e$B$O\e(B Emacs \e$B$N\e(B @code{run-at-time} \e$B$HF1$80z?t$r<h$j$^$9!#\e(BGnus \e$B$r\e(B Emacs \e$B$G<B\e(B
+\e$B9T$7$F$$$k$H$-$O!"A0$N4X?t$OC1$K8e$N$b$N$NJLL>4X?t\e(B (alias) \e$B$K$J$C$F$$$^\e(B
+\e$B$9!#$7$+$7!"\e(BXEmacs \e$B$G<B9T$7$?$H$-$O!"A0<T$O<!$N4X?t$NJLL>4X?t\e(B (alias) \e$B$H\e(B
+\e$B$J$C$F$$$^$9\e(B:
+
+@lisp
+(defun gnus-xmas-run-at-time (time repeat function &rest args)
+  (start-itimer
+   "gnus-run-at-time"
+   `(lambda ()
+      (,function ,@@args))
+   time repeat))
+@end lisp
+
+\e$B$3$N<oN`$N$b$N$,B?$/$N4X?t$KBP$7$F$J$5$l$F$$$^$9!#\e(BGnus \e$B$O\e(B XEmacs \e$B$G<B9T\e(B
+\e$B$7$F$$$k$H$-$K!"85$+$i$"$k\e(B Emacs \e$B$N4X?t$r:FDj5A$7$^$;$s\e(B---\e$B$=$l$O!"Be$o$j\e(B
+\e$B$K\e(B gnus \e$B$NEy2A$J$b$N$H\e(B @code{defalias} \e$B$r$9$k;v$K$h$C$F<B9T$7$^$9!#A4BN\e(B
+\e$BE*$K!"$h$j$-$l$$$K$J$j$^$9!#\e(B
+
+XEmacs \e$B$N4X?t3&LL$NJ}$,L@$i$+$K$-$l$$$J>l9g$O!";d$OBe$o$j$K$=$l$r;H$$$^\e(B
+\e$B$9!#Nc$($P!"\e(B@code{gnus-region-active-p} \e$B$O\e(B XEmacs \e$B$G\e(B
+\e$B$O\e(B @code{region-active-p} \e$B$NJLL>$G$"$k$N$KBP$7$F!"\e(BEmacs \e$B$G$O4X?t$G$9!#\e(B
+
+\e$B$b$A$m$s!";d$O\e(B XEmacs \e$B$r;d$N4pK\%W%i%C%H%U%)!<%`$KA*$s$G!"4X?t$N3d$jEv$F\e(B
+\e$B$r5U$K$9$k;v$b$G$-$^$7$?!#$G$b!";d$O$=$&$7$^$;$s$G$7$?!#\e(B
+XEmacs \e$B$G\e(B gnus \e$B$r<B9T$9$k$H$-$K!"$3$&$$$&5U8~$-$N$?$a$NB.EYDc2<$O>/$7$G\e(B
+\e$B$7$g$&!#\e(B
+
+@node Various File Formats
+@subsection \e$B$$$m$$$m$J%U%!%$%kMM<0\e(B
+
+@menu
+* Active File Format::          \e$B;HMQ2DG=$J5-;v%0%k!<%W$N>pJs\e(B
+* Newsgroups File Format::      \e$B%0%k!<%W$N5-=R\e(B
+@end menu
+
+@node Active File Format
+@subsubsection \e$B%"%/%F%$%V%U%!%$%kMM<0\e(B
+
+\e$B%"%/%F%#%V%U%!%$%k$OEv$N%5!<%P!<$NA4$F$N;HMQ2DG=$J%0%k!<%W$N0lMw$r5s$2$^\e(B
+\e$B$9!#$=$l$O$=$l$>$l$N%0%k!<%W$N:GDc$H:G9b$N5-;vHV9f$N0lMw$b$"$j$^$9!#\e(B
+
+\e$B$3$l$OIaDL$N%"%/%F%#%V%U%!%$%k$+$i$NH4?h$G$9\e(B:
+
+@example
+soc.motss 296030 293865 y
+alt.binaries.pictures.fractals 3922 3913 n
+comp.sources.unix 1605 1593 m
+comp.binaries.ibm.pc 5097 5089 y
+no.general 1000 900 y
+@end example
+
+\e$B$3$l$O$3$N%U%!%$%k$N5?;w\e(B BNF \e$BDj5A$G$9!#\e(B
+
+@example
+active      = *group-line
+group-line  = group spc high-number spc low-number spc flag <NEWLINE>
+group       = <non-white-space string>
+spc         = " "
+high-number = <non-negative integer>
+low-number  = <positive integer>
+flag        = "y" / "n" / "m" / "j" / "x" / "=" group
+@end example
+
+\e$B$3$N%U%!%$%k$N40A4$J5-=R$rF@$k$?$a$K$O!"\e(B@samp{innd} \e$B$N%^%K%e%"%kJG!"FC\e(B
+\e$B$K\e(B @samp{active(5)} \e$B$r8+$F2<$5$$!#\e(B
+
+@node Newsgroups File Format
+@subsubsection \e$B%K%e!<%9%0%k!<%W%U%!%$%kMM<0\e(B
+
+\e$B%K%e!<%9%0%k!<%W%U%!%$%k$O%0%k!<%W$r$=$N5-=R$H6&$K0lMw$r5s$2$^$9!#%5!<%P!<\e(B
+\e$B$K$"$kA4$F$N%0%k!<%W$,0lMw$K$5$l$J$1$l$P$J$i$J$$$N$G$O$J$/!"$^$?!"%U%!%$\e(B
+\e$B%k$NA4$F$N%0%k!<%W$,%5!<%P!<$KB8:_$7$J$1$l$P$J$i$J$$$N$G$O$"$j$^$;$s!#$3\e(B
+\e$B$N%U%!%$%k$O=c?h$KMxMQ<T$N>pJs$N$?$a$K$"$j$^$9!#\e(B
+
+\e$BMM<0$OHs>o$K4JC1$G$9\e(B: \e$B%0%k!<%WL>!"%?%V!"$=$7$F5-=R$G$9!#$3$l$ODj5A$G$9\e(B:
+
+@example
+newsgroups    = *line
+line          = group tab description <NEWLINE>
+group         = <non-white-space string>
+tab           = <TAB>
+description   = <string>
+@end example
+
+@page
+@node Emacs for Heathens
+@section \e$B0[65EL$X$N\e(B Emacs
+
+\e$B?.$8$k$+$I$&$+$OCN$j$^$;$s$,!"\e(Bgnus \e$B$r;H$&?M$NCf$K$O\e(B Gnus Love Boat \e$B$G$N\e(B
+\e$BN9$KEk>h$9$kA0$K$"$^$j\e(B Emacs \e$B$r;H$C$?;v$,L5$$$H$$$&?M$,$$$^$9!#$b$7$"$J\e(B
+\e$B$?$,\e(B ``@kbd{C-M-a}'' \e$B$d\e(B ``\e$B%j!<%8%g%s$r@Z$k\e(B''\e$B!"$=$7\e(B
+\e$B$F\e(B ``@code{gnus-flargblossen} \e$B$rO"A[%j%9%H$K@_Dj$7$F$/$@$5$$!#$=$N%-!<$O\e(B
+\e$B%0%k!<%WL>$K9gCW$9$k$?$a$K;H$o$l$k@55,I=8=$G$9\e(B'' \e$B$,>/$7$N0UL#$+A4$/0UL#\e(B
+\e$B$NL5$$KbK!$N8@MU$G$"$kIT9,$J?M$G$"$l$P!"$3$NIUO?$O$"$J$?$N$?$a$K$"$j$^$9!#\e(B
+\e$B$b$7$"$J$?$,4{$K\e(B Emacs \e$B$K?F$7$s$G$$$k$N$G$"$l$P!"$3$l$rL5;k$7$F<V$r2D0&\e(B
+\e$B$,$j$K9T$C$F2<$5$$!#\e(B
+
+@menu
+* Keystrokes::                  \e$BJ8>O$rF~NO$7$FL?Na$r<B9T$9$k\e(B
+* Emacs Lisp::                  \e$BHw$(IU$1$N\e(B Emacs \e$B%W%m%0%i%_%s%08@8l\e(B
+@end menu
+
+@node Keystrokes
+@subsection \e$BBG80\e(B
+
+@itemize @bullet
+@item
+Q: \e$B7P83$N$"$k\e(B Emacs \e$B$NMxMQ<T$H$O2?$G$9$+\e(B?
+
+@item
+A: \e$BC<Kv$,%Z%@%k$r;}$C$F$$$?$i$J$!$H4j$&?M$N;v$G$9!#\e(B
+@end itemize
+
+\e$B$O$$!"$"$J$?$,\e(B Emacs \e$B$r;H$&$H!"$"$J$?$O%3%s%H%m!<%k%-!<!"%7%U%H%-!<!"%a\e(B
+\e$B%?%-!<$r$?$/$5$s;H$&$h$&$K$J$k$G$7$g$&!#$3$l$O0lIt$N?M\e(B (\e$B<g$K!"\e(B
+@code{vi} \e$BMxMQ<T\e(B) \e$B$K$OHs>o$K$&$k$5$/46$8$i$l$k$G$7$g$&!#;D$j$N?M!9$O!"$=\e(B
+\e$B$l$K$h$j$b$?$i$5$l$kCO9v$r0&$7$^$9!#$"$-$i$a$FI~=>$7$F2<$5$$!#\e(BEmacs \e$B$OK\\e(B
+\e$BEv$O\e(B ``Escape-Meta-Alt-Control-Shift'' \e$B$NN,$G!"B>$NI>H=$N0-$$=P\e(B
+\e$B=j\e(B (Emacs \e$B$N:n<T$N$h$&$J\e(B) \e$B$+$iJ9$$$?\e(B ``Editing Macros'' \e$B$G$O$"$j$^$;$s!#\e(B
+
+\e$B%7%U%H%-!<$OIaDL$O>.;X$N6a$/$K0LCV$7$F$*$j!"IaDL$OBgJ8;z$d$=$NB>$N$b$rF@\e(B
+\e$B$k$?$a$K;H$o$l$^$9!#$"$J$?$O$:$C$H$=$l$r;H$&;v$G$7$g$&!#%3%s%H%m!<%k%-!<\e(B
+\e$B$OIaDL$O\e(B ``CTRL'' \e$B$d$=$N$h$&$J$b$N$G0u$,IU$$$F$$$^$9!#%a%?%-!<$O!"$*$b$7\e(B
+\e$B$m$$;v$K!"$I$N%-!<%\!<%I$G$b$=$N$h$&$K0u$,IU$1$i$l$F$$$^$;$s!#$=$l$OIaDL\e(B
+\e$B$O%-!<%\!<%I$N:8<jB&$K0LCV$7$F$$$F!"IaDL$O:G2<CJ$K$"$j$^$9!#\e(B
+
+\e$B$3$l$+$i!"2f!9\e(B Emacs \e$B$N?M!9$O!"$=$l$,$"$^$j$KITJX$J$?$a!"\e(B
+``meta-control-m \e$B%-!<$r2!$9\e(B'' \e$B$H$O8@$$$^$;$s!#;d$?$A$O\e(B ``@kbd{C-M-m} \e$B$r\e(B
+\e$B2!$9\e(B'' \e$B$H8@$$$^$9!#\e(B@kbd{M-} \e$B$O\e(B ``\e$B%a%?\e(B'' \e$B$r8=$9@\F,<-$G!"\e(B``C-'' \e$B$O\e(B ``\e$B%3%s\e(B
+\e$B%H%m!<%k\e(B'' \e$B$r0UL#$9$k@\F,<-$G$9!#$G$9$+$i!"\e(B``@kbd{C-k} \e$B$r2!$9\e(B'' \e$B$O\e(B ``\e$B%3\e(B
+\e$B%s%H%m!<%k%-!<$r2<$K2!$7!"\e(B@kbd{k} \e$B$r2!$7$F$$$k4V!"$=$l$r2<$KJ]$A$J$5\e(B
+\e$B$$\e(B'' \e$B$H8@$&;v$G$9!#\e(B``@kbd{C-M-k} \e$B$r2!$9\e(B'' \e$B$O\e(B ``\e$B%a%?%-!<$H%3%s%H%m!<%k%-!<\e(B
+\e$B$r2!$7$F2<$KJ]$C$?8e$G\e(B @kbd{k} \e$B$r2!$9\e(B'' \e$B$H8@$&;v$G$9!#4JC1$G$7$g!#$M\e(B?
+
+\e$B$3$l$OA4$F$N%-!<%\!<%I$,%a%?%-!<$r;}$C$F$$$k$o$1$G$O$J$$$H8@$&;v<B$K$h$j\e(B
+\e$B>/$7J#;($K$J$C$F$$$^$9!#$=$N$h$&$J>l9g$O!"\e(B``\e$B%(%9%1!<%W\e(B'' \e$B%-!<$r;H$&;v$,\e(B
+\e$B$G$-$^$9!#$=$l$O%a%?%-!<$r;}$C$F$$$k$H$-$h$j$b$C$H:n6H$,BgJQ$K$J$j$^$9$N\e(B
+\e$B$G!"$=$&$$$&>l9g$O!";d$O%a%?%-!<$N$"$k%-!<%\!<%I$r<j$KF~$l$k;v$r63$7$/$*\e(B
+\e$B4+$aCW$7$^$9!#$=$lL5$7$G$O@8$-$F9T$1$J$$$G$7$g$&!#\e(B
+
+@node Emacs Lisp
+@subsection Emacs Lisp
+
+Emacs \e$B$O$=$l$,K\Ev$O\e(B Lisp \e$B%$%s%?!<%W%j%?!<$G$"$k;v$+$i!"%(%G%#%?!<$N2&MM\e(B
+\e$B$G$9!#$"$J$?$,C!$/!"$=$l$>$l$NA4$F$N%-!<$O2?$i$+$N\e(B Emacs Lisp \e$B$N%3!<%I$N\e(B
+\e$B>.JR$r<B9T$7!"\e(BEmacs Lisp \e$B$O%$%s%?!<%W%j%?!<$G<B9T$5$l$k8@8l$G$"$k;v$+$i!"\e(B
+\e$B$=$l$O$I$s$J%-!<$G$bG$0U$N$$$m$$$m$J%3!<%I$r<B9T$9$k$h$&$K@_Dj$G$-$k$H8@\e(B
+\e$B$&;v$G$9!#$"$J$?$O!"C1$K!"$=$&$9$l$PNI$$$@$1$G$9!#\e(B
+
+Gnus \e$B$O\e(B Emacs Lisp \e$B$K$h$C$F=q$+$l$F$$$F!"$=$l$O$?$/$5$s$NC`<!2r<a<B9T$5\e(B
+\e$B$l$k4X?t$K$h$j<B9T$5$l$^$9!#\e(B(\e$B$3$l$i$OB.EY$N$?$a$K%P%$%H%3%s%Q%$%k$5$l$F\e(B
+\e$B$$$^$9$,!"$=$l$G$b$^$@C`<!2r<a$5$l$^$9!#\e(B) \e$B$b$7\e(B gnus \e$B$,$9$k$"$k;v$r9%$-$G\e(B
+\e$B$O$J$$$H;W$C$?$J$i!"0c$C$?$h$&$K<B9T$5$;$k$N$O<h$k$KB-$i$J$$;v$G$9!#\e(B(\e$B$(!<\e(B
+\e$B$H!">/$J$/$H$b\e(B Lisp \e$B%3!<%I$N=q$-J}$rCN$C$F$$$l$P!#\e(B) \e$B$7$+$7!"$=$l$O$3$N%^\e(B
+\e$B%K%e%"%k$NHO0O30$J$N$G!"2f!9$OC1$K\e(B gnus \e$B$r%+%9%?%^%$%:$9$k$?$a$K%U%!%$\e(B
+\e$B%k\e(B @file{.emacs} \e$B$GIaDL;H$o$l$k$$$/$D$+$NIaDL$N9=J8$K$D$$$F$@$1OC$r$7$^\e(B
+\e$B$9!#\e(B
+
+\e$B$b$7JQ?t\e(B@code{gnus-florgbnize} \e$B$r;M\e(B (4) \e$B$K@_Dj$7$?$$$N$G$"$l$P!"0J2<$N$b\e(B
+\e$B$N$r=q$-$^$9\e(B:
+
+@lisp
+(setq gnus-florgbnize 4)
+@end lisp
+
+\e$B$3$N4X?t\e(B @code{setq} (\e$BK\Ev$O\e(B ``\e$BFC<l7A<0\e(B'' (special form)) \e$B$r;H$C$F!"JQ?t\e(B
+\e$B$r2?$+$NCM$K@_Dj$9$k;v$,$G$-$^$9!#$3$l$OK\Ev$K$"$J$?$,CN$k$Y$-A4$F$N;v$G\e(B
+\e$B$9!#$3$l$+$i$O\e(B gnus \e$B$NF0:n$rJQ99$9$k$?$a$K!"$?$/$5$s$N$3$N$h$&$J$b$N$G%U%!\e(B
+\e$B%$%k\e(B @file{.emacs} \e$B$rKd$a?T$/$9;v$,$G$-$^$9!#\e(B
+
+\e$B$b$7$"$J$?$,$=$N$h$&$J$b$N$r%U%!%$%k\e(B @file{.emacs} \e$B$KF~$l$?$i!"$=$l$O<!\e(B
+\e$B2s$K\e(B Emacs \e$B$r5/F0$7$?$H$-$KFI$_9~$^$l\e(B @code{\e$BI>2A\e(B} (\e$B$=$l$O\e(B ``\e$B<B\e(B
+\e$B9T\e(B'' \e$B$N\e(B lisp \e$B8l$G$9\e(B) \e$B$5$l$^$9!#$b$7JQ?t$r$9$0$KJQ99$7$?$$$N$G$"$l$P!"JD\e(B
+\e$B$83g8L$N8e$GC1$K\e(B @kbd{C-x C-e} \e$B$H$9$k$@$1$G$9!#$=$l$OA0$K$"\e(B
+\e$B$k\e(B ``\e$B<0\e(B'' \e$B$r\e(B @code{\e$BI>2A\e(B} \e$B$7!"$=$l$O$3$3$G$O4JC1$J\e(B @code{setq} \e$BJ8$G$9!#\e(B
+
+\e$B$,$s$P$C$F\e(B---\e$B$b$7$"$J$?$,\e(B Emacs \e$B$NA0$K$"$k$N$G$"$l$P$A$g$C$H;n$7$F2<$5$$!#\e(B
+@kbd{C-x C-e} \e$B$N8e$G!"H?6A6h0h\e(B (echo area) \e$B$K\e(B @samp{4} \e$B$,8=$o$l$k$N$,8+\e(B
+\e$B$($k$G$7$g$&!#$=$l$O$"$J$?$,\e(B @code{\e$BI>2A\e(B} \e$B$7$?<0$NJV$jCM$G$9!#\e(B
+
+\e$B$$$/$D$+$NMn$H$77j\e(B:
+
+\e$B$b$7%^%K%e%"%k$,\e(B ``@code{gnus-read-active-file} \e$B$r\e(B @code{some} \e$B$K@_Dj$7\e(B
+\e$B$J$5$$\e(B'' \e$B$H8@$C$?$J$i!"$=$l$O\e(B:
+
+@lisp
+(setq gnus-read-active-file 'some)
+@end lisp
+
+\e$B$H8@$&;v$G$9!#\e(B
+
+\e$B0lJ}!"%^%K%e%"%k\e(B
+\e$B$,\e(B ``@code{gnus-nntp-server} \e$B$r\e(B @samp{nntp.ifi.uio.no} \e$B$K@_Dj$7$J$5\e(B
+\e$B$$\e(B'' \e$B$H8@$C$?$J$i!"$=$l$O\e(B:
+
+@lisp
+(setq gnus-nntp-server "nntp.ifi.uio.no")
+@end lisp
+
+\e$B$H8@$&;v$G$9!#\e(B
+
+\e$B$G$9$+$i!"J8;zNs\e(B (\e$B8e<T\e(B) \e$B$r\e(B \e$B%7%s%\%k\e(B (\e$BA0<T\e(B) \e$B$H:.F1$7$J$$$h$&$KCm0U$7$F2<\e(B
+\e$B$5$$!#%^%K%e%"%k$OL@3N$K6hJL$7$F$$$^$9$,!":.Mp$7$d$9$$$+$b$7$l$^$;$s!#\e(B
+
+@page
+@include gnus-faq-ja.texi
+
+@node Index
+@chapter Index
+@printindex cp
+
+@node Key Index
+@chapter Key Index
+@printindex ky
+
+@summarycontents
+@contents
+@bye
+
+@iftex
+@iflatex
+\end{document}
+@end iflatex
+@end iftex
+
+@c Local Variables:
+@c mode: texinfo
+@c coding: iso-2022-7bit
+@c use-kuten-for-period: t
+@c use-touten-for-comma: t
+@c End:
diff --git a/texi/gnus-terms.ja b/texi/gnus-terms.ja
new file mode 100644 (file)
index 0000000..52046f1
--- /dev/null
@@ -0,0 +1,177 @@
+\e$B86J8$HLu8l$N%j%9%H$G$9!#8!F$IT==J,$JE@$b$"$j$^$9!#\e(B
+\e$BJQ99$5$l$k2DG=@-$OBg$$$K$"$j$^$9!#\e(B
+
+\e$BC18l\e(B                             \e$BLu8l\e(B
+
+active                         \e$B:nF0$9$k!":nF0$7$F$$$k\e(B
+active file                    \e$B8=>u%U%!%$%k!"%"%/%F%#%V%U%!%$%k\e(B
+adapt                          \e$BE,MQ\e(B
+adaptive                       \e$BE,1~@-\e(B
+address                                \e$B%"%I%l%9\e(B
+agent                          \e$B%(!<%8%'%s%H\e(B
+alist                          \e$BO"A[%j%9%H\e(B
+alternate                      \e$BBeBX\e(B
+anything group                 \e$B$J$s$G$b%0%k!<%W\e(B
+archive                                \e$B%"!<%+%$%V\e(B
+asterisk                       \e$B%"%9%?%j%9%/\e(B
+auto-save file                 \e$B<+F0J]B8%U%!%$%k\e(B
+backend                                \e$B%P%C%/%(%s%I\e(B
+batch                          \e$B0l3g\e(B
+bogus group                    \e$B56%0%k!<%W\e(B
+browse                         \e$B%V%i%&%:!";2>H!"354Q\e(B
+buffer                         \e$B%P%C%U%!\e(B
+buggy                          \e$B8N>c$,$A\e(B
+category                       \e$BJ,N`\e(B
+collapsed group        name            \e$BC;=L%0%k!<%WL>\e(B
+combined groups                        \e$B7k9g%0%k!<%W\e(B
+command                                \e$BL?Na\e(B
+command line                   \e$B%3%^%s%I9T\e(B
+configure (shell script)       \e$B4D6-@_Dj\e(B
+copy                           \e$B%3%T!<!"J#<L\e(B
+crosspost                      \e$BAj8_Ej9F!"%/%m%9%]%9%H\e(B
+current                                \e$B8=:_$N\e(B
+customize                      \e$B%+%9%?%^%$%:\e(B
+default                                \e$B=i4|@_Dj\e(B/\e$B=i4|@_DjCM\e(B (\e$B%G%#%U%)%k%H\e(B)?
+directory                      \e$B%G%#%l%/%H%j!<\e(B
+dormant article                        \e$BJ]N15-;v\e(B
+dotted pair                    \e$B%I%C%H%Z%"!"%I%C%HBP\e(B
+download                       \e$B%@%&%s%m!<%I\e(B
+draft                          \e$B2<=q$-\e(B
+dribble file                   \e$B%I%j%V%k%U%!%$%k\e(B
+duplicate suppression          \e$B=EJ#M^@)\e(B
+entry                          \e$BEPO?!"EPO?9`L\\e(B
+expire                         \e$B4|8B@Z$l>C5n!"4|8B@Z$l:o=|\e(B
+expunge                                \e$B>C5n\e(B
+field                          \e$B%U%#!<%k%I\e(B
+firewall                       \e$BKIJI\e(B
+flush cache                    \e$B%-%c%C%7%e$r=q$-9~$`\e(B
+follow up                      \e$B%U%)%m!<%"%C%W\e(B
+foreign                                \e$B30It\e(B
+format                         \e$BMM<0!"%U%)!<%^%C%H\e(B
+frame                          \e$B%U%l!<%`\e(B 
+gateway                                \e$B%2!<%H%&%'%$\e(B
+global                         \e$B%0%m!<%P%k\e(B
+Gnus                           gnus
+group buffer                   \e$B%0%k!<%W%P%C%U%!\e(B
+header                         \e$B%X%C%@!<\e(B
+highlight                      \e$B%O%$%i%$%H\e(B
+history                                \e$BMzNr\e(B
+home score file                        \e$B%[!<%`%9%3%"%U%!%$%k\e(B
+hook                           \e$B%U%C%/\e(B
+inbox                          \e$B%$%s%\%C%/%9\e(B
+indentation                    \e$B;z2<$2\e(B
+interactive command            \e$BBPOCL?Na\e(B
+interface                      \e$B%$%s%?!<%U%'!<%9\e(B
+kiboze                         kiboze
+key (alist)                    \e$B%-!<\e(B
+keymap                         \e$B%-!<%^%C%W\e(B
+kiboze                         kiboze
+kill                           \e$B:o=|!"@Z$k!"%-%k\e(B
+kill file                      \e$B:o=|%U%!%$%k!"\e(B(\e$B>C5n%U%!%$%k\e(B)
+level                          \e$B%l%Y%k\e(B
+load                           \e$B%m!<%I\e(B
+local variable                 \e$B6I=jJQ?t!"%m!<%+%kJQ?t\e(B
+lower lebel                    \e$B>.$5$$%l%Y%k\e(B
+mail                           \e$B%a!<%k\e(B
+mailbox                                \e$B%a!<%k%\%C%/%9\e(B
+mail-to-news gateway           \e$B%a!<%k$+$i%K%e!<%:$X$N%2!<%H%&%'%$\e(B
+mark                           \e$B0u\e(B
+meta-variable                  \e$B%a%?JQ?t\e(B
+message                                \e$B%a%C%;!<%8\e(B
+method                         \e$BJ}K!\e(B
+minor mode                     \e$B%^%$%J!<%b!<%I\e(B
+modeline                       \e$B%b!<%I9T\e(B
+moderated                      \e$B%b%G%l!<%F%C%I!"=$@5$5$l$?\e(B
+native                         \e$B4pK\\e(B
+native method                  \e$B4pK\J}K!\e(B
+native server                  \e$B4pK\%5!<%P!<\e(B
+news                           \e$B%K%e!<%9\e(B (\e$B%K%e!<%:\e(B)
+newsgroup                      \e$B%K%e!<%9%0%k!<%W\e(B (\e$B%K%e!<%:%0%k!<%W\e(B)
+news reader                    \e$B%K%e!<%9%j!<%@\e(B
+numeric prefix                 \e$B?t;z@\F,0z?t\e(B
+operator                       \e$B:nMQ;R\e(B
+outgoing                       \e$B:9=PMQ\e(B
+overview                       \e$B354Q%U%!%$%k\e(B
+pack                           \e$B:-Jq$9$k\e(B
+parameter                      \e$B%Q%i%a!<%?\e(B
+plugged                                \e$B:9$79~$_\e(B
+point                          \e$B%]%$%s%H!"%+!<%=%k0LCV\e(B
+predicate function             \e$B=R8l4X?t\e(B
+prefix                         \e$B@\F,0z?t\e(B
+process                                \e$B%W%m%;%9\e(B
+process mark                   (\e$B%W%m%;%9%^!<%/\e(B)\e$B!"%W%m%;%90u\e(B
+process/prefix convention      \e$B%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B (\e$B%W%m%;%9%^!<%/!&%W%l%U%#%C%/%9%k!<%k\e(B)
+prompt                         \e$BF~NOB%?J\e(B
+rank                           \e$B%i%s%/\e(B
+region                         (\e$B%j!<%8%g%s\e(B)
+release                                \e$B%j%j!<%9\e(B
+remote system                  \e$B1s3V%7%9%F%`\e(B
+reply packet                   \e$BJV?.%Q%1%C%H\e(B
+response packet                        \e$BJV?.%Q%1%C%H\e(B
+startup file                   \e$B5/F0%U%!%$%k\e(B
+score                          \e$B%9%3%"\e(B
+score entry                    \e$B%9%3%"EPO?\e(B
+secondary server               \e$BFs<!%5!<%P!<\e(B
+select method                  \e$BA*BrJ}K!\e(B
+server                         \e$B%5!<%P!<\e(B
+sesssion                       \e$B%;%C%7%g%s\e(B
+shortcut                       \e$BC;=LBG80\e(B
+solid group                    \e$B8GDj%0%k!<%W\e(B
+sort                           \e$B%=!<%H\e(B \e$BJB$YBX$(\e(B
+SOUP packets                   SOUP \e$B%Q%1%C%H\e(B
+startup file                   \e$B5/F0%U%!%$%k\e(B
+sub-topic                      \e$BI{%H%T%C%/\e(B
+submap                         \e$B%5%V%^%C%W\e(B
+subscribe                      \e$B9XFI\e(B
+subscribedness                 \e$B9XFIEY\e(B
+summary buffer                 \e$B35N,%P%C%U%!\e(B
+superseding                    \e$BBeBX\e(B
+syntax table                   \e$BJ8K!I=\e(B
+text properties                        \e$B%F%-%9%HB0@-\e(B
+thread                         \e$B%9%l%C%I\e(B
+ticked article                 (\e$B0uIU$-5-;v\e(B)
+toggle                         \e$B%H%0%k\e(B \e$B@Z$jBX$(\e(B
+token
+topic                          \e$B%H%T%C%/\e(B
+unplugged                      \e$B@Z$jN%$7\e(B
+unsubscribe                    \e$BHs9XFI\e(B
+user                           \e$BMxMQ<T\e(B
+value (alist)                  \e$BCM\e(B
+web                            \e$B%&%'%V\e(B
+Web browser                    \e$B%&%'%V%V%i%&%6!<\e(B
+Web search                     \e$B%&%'%V8!:w\e(B
+yank                           \e$BE=$jIU$1\e(B
+zombie                         \e$B%>%s%S\e(B
+
+summary                                \e$B35N,\e(B
+body                           \e$B%\%G%#\e(B
+head                           \e$B%X%C%@!<\e(B
+subject                                \e$BI=Bj\e(B
+match                          \e$B%^%C%A\e(B
+encode                         \e$BId9f2=\e(B
+character set                  \e$BJ8;z=89g\e(B
+hook                           \e$B%U%C%/\e(B
+keystroke                      \e$B%-!<A`:n\e(B
+reply                          \e$BJV?.\e(B
+button                         \e$B%\%?%s\e(B
+buttonizing                    \e$B%\%?%s5!G=\e(B
+syntax table                   \e$B%7%s%?%C%/%9%F!<%V%k\e(B
+format                         \e$BMM<0\e(B
+wash                           \e$B@vBu\e(B
+page breaking                  \e$B2~JG\e(B
+page delimiter                 \e$BJG6h@Z$jJ8;z\e(B
+page                           \e$BJG\e(B
+
+directory                      \e$B%G%#%l%/%H%j!<\e(B
+SOUP packets                   SOUP \e$B%Q%1%C%H\e(B
+auto-save file                 \e$B<+F0J]B8%U%!%$%k\e(B
+predicate function             \e$B=R8l4X?t\e(B
+news reader                    \e$B%K%e!<%9%j!<%@\e(B
+native server                  \e$B4pK\%5!<%P!<\e(B
+
+secondary server               \e$BFs<!%5!<%P!<\e(B
+pack                           \e$B:-Jq$9$k\e(B
+active file                    \e$B%"%/%F%#%V%U%!%$%k\e(B
+incoming                       \e$BF~$C$F$/$k!&F~$C$F$-$?\e(B
+response packet                        \e$BJV?.%Q%1%C%H\e(B
+reply packet                   \e$BJV?.%Q%1%C%H\e(B
index 3d28d62..66ced09 100644 (file)
@@ -1,13 +1,14 @@
-\input texinfo                  @c -*-texinfo-*-
+\input texinfo
 
 @setfilename gnus
-@settitle Quassia Gnus 0.34 Manual
-@synindex fn cp
-@synindex vr cp
-@synindex pg cp
-@c @direntry
-@c * Gnus: (gnus).         The news reader Gnus.
-@c @end direntry
+@settitle T-gnus 6.16 Manual
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex pg cp
+@dircategory Emacs
+@direntry
+* Gnus: (gnus).         The newsreader Gnus.
+@end direntry
 @iftex
 @finalout
 @end iftex
 \usepackage[latin1]{inputenc}
 \usepackage{pagestyle}
 \usepackage{epsfig}
-\usepackage{bembo}
 \usepackage{pixidx}
+\input{gnusconfig.tex}
+
+\ifx\pdfoutput\undefined
+\else
+\usepackage[pdftex,bookmarks,colorlinks=true]{hyperref}
+\usepackage{thumbpdf}
+\pdfcompresslevel=9
+\fi
 
 \makeindex
 \begin{document}
 
+\newcommand{\gnusversionname}{T-gnus v6.16}
 \newcommand{\gnuschaptername}{}
 \newcommand{\gnussectionname}{}
 
 \newcommand{\gnusbackslash}{/}
 
+\newcommand{\gnusref}[1]{``#1'' on page \pageref{#1}}
+\ifx\pdfoutput\undefined
+\newcommand{\gnusuref}[1]{\gnustt{#1}}
+\else
+\newcommand{\gnusuref}[1]{\href{#1}{\gnustt{#1}}}
+\fi
 \newcommand{\gnusxref}[1]{See ``#1'' on page \pageref{#1}}
 \newcommand{\gnuspxref}[1]{see ``#1'' on page \pageref{#1}}
 
 \newcommand{\gnuskindex}[1]{\index{#1}}
 \newcommand{\gnusindex}[1]{\index{#1}}
 
-\newcommand{\gnustt}[1]{{\fontfamily{pfu}\fontsize{10pt}{10}\selectfont #1}}
+\newcommand{\gnustt}[1]{{\gnusselectttfont{}#1}}
 \newcommand{\gnuscode}[1]{\gnustt{#1}}
-\newcommand{\gnussamp}[1]{``{\fontencoding{OT1}\fontfamily{pfu}\fontsize{10pt}{10}\selectfont #1}''}
+\newcommand{\gnusasis}[1]{\gnustt{#1}}
+\newcommand{\gnusurl}[1]{\gnustt{#1}}
+\newcommand{\gnuscommand}[1]{\gnustt{#1}}
+\newcommand{\gnusenv}[1]{\gnustt{#1}}
+\newcommand{\gnussamp}[1]{``{\fontencoding{OT1}\gnusselectttfont{}#1}''}
 \newcommand{\gnuslisp}[1]{\gnustt{#1}}
 \newcommand{\gnuskbd}[1]{`\gnustt{#1}'}
+\newcommand{\gnuskey}[1]{`\gnustt{#1}'}
 \newcommand{\gnusfile}[1]{`\gnustt{#1}'}
 \newcommand{\gnusdfn}[1]{\textit{#1}}
 \newcommand{\gnusi}[1]{\textit{#1}}
+\newcommand{\gnusr}[1]{\textrm{#1}}
 \newcommand{\gnusstrong}[1]{\textbf{#1}}
 \newcommand{\gnusemph}[1]{\textit{#1}}
 \newcommand{\gnusvar}[1]{{\fontsize{10pt}{10}\selectfont\textsl{\textsf{#1}}}}
 \newcommand{\gnussc}[1]{\textsc{#1}}
 \newcommand{\gnustitle}[1]{{\huge\textbf{#1}}}
+\newcommand{\gnusversion}[1]{{\small\textit{#1}}}
 \newcommand{\gnusauthor}[1]{{\large\textbf{#1}}}
+\newcommand{\gnusresult}[1]{\gnustt{=> #1}}
+\newcommand{\gnusacronym}[1]{\textsc{#1}}
+\newcommand{\gnusemail}[1]{\textit{#1}}
 
 \newcommand{\gnusbullet}{{${\bullet}$}}
 \newcommand{\gnusdollar}{\$}
 \newcommand{\gnustilde}{\symbol{"7E}}
 \newcommand{\gnusless}{{$<$}}
 \newcommand{\gnusgreater}{{$>$}}
+\newcommand{\gnusbraceleft}{{$>$}}
+\newcommand{\gnusbraceright}{{$>$}}
 
-\newcommand{\gnushead}{\raisebox{-1cm}{\epsfig{figure=ps/gnus-head.eps,height=1cm}}}
+\newcommand{\gnushead}{\raisebox{-1cm}{\epsfig{figure=ps/gnus-head,height=1cm}}}
 \newcommand{\gnusinteresting}{
 \marginpar[\mbox{}\hfill\gnushead]{\gnushead}
 }
 }
 
 \newcommand{\gnusicon}[1]{
-\marginpar[\mbox{}\hfill\raisebox{-1.5cm}{\epsfig{figure=tmp/#1-up.ps,height=1.5cm}}]{\raisebox{-1cm}{\epsfig{figure=tmp/#1-up.ps,height=1cm}}}
+\marginpar[\mbox{}\hfill\raisebox{-1.5cm}{\epsfig{figure=ps/#1-up,height=1.5cm}}]{\raisebox{-1cm}{\epsfig{figure=ps/#1-up,height=1cm}}}
 }
 
 \newcommand{\gnuspicon}[1]{
 }
 }{\end{list}}
 
+\newenvironment{asislist}%
+{\begin{list}{}{
+}
+}{\end{list}}
+
 \newenvironment{kbdlist}%
 {\begin{list}{}{
 \labelwidth=0cm
 }
 {
 \ifodd\count0
-\mbox{} \hfill 
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \else
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \hfill \mbox{}
 \fi
 }
 }
 {
 \ifodd\count0
-\mbox{} \hfill 
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \else
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \hfill \mbox{}
 \fi
 }
 }
 {
 \ifodd\count0
-\mbox{} \hfill 
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\mbox{} \hfill
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \else
-\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo.eps,height=1cm}}
+\raisebox{-0.5cm}{\epsfig{figure=ps/gnus-big-logo,height=1cm}}
 \hfill \mbox{}
 \fi
 }
 \parindent=0cm
 \addtolength{\textheight}{2cm}
 
-\gnustitle{\gnustitlename}\\
+\gnustitle{\gnustitlename}\hfill\gnusversion{\gnusversionname}\\
 \rule{15cm}{1mm}\\
 \vfill
-\hspace*{0cm}\epsfig{figure=ps/gnus-big-logo.eps,height=15cm}
+\hspace*{0cm}\epsfig{figure=ps/gnus-big-logo,height=15cm}
 \vfill
 \rule{15cm}{1mm}\\
 \gnusauthor{by Lars Magne Ingebrigtsen}
 
 \thispagestyle{empty}
 
-Copyright \copyright{} 1995,96,97 Free Software Foundation, Inc. 
+Copyright \copyright{} 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004
+Free Software Foundation, Inc.
 
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
 
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
 
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions.
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
 
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
 \newpage
 \end{titlepage}
 @end iflatex
 @end iftex
 
-@ifinfo
-
-This file documents Gnus, the GNU Emacs newsreader.
+@ifnottex
 
-Copyright (C) 1995,96 Free Software Foundation, Inc.
+This file documents gnus, the GNU Emacs newsreader.
 
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
+Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+        Free Software Foundation, Inc.
 
-@ignore
-Permission is granted to process this file through Tex and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being none, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
 
-@end ignore
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
 
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions.
-@end ifinfo
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end ifnottex
 
 @tex
 
 @titlepage
-@title Quassia Gnus 0.34 Manual
+@title T-gnus 6.16 Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
 
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1995,96,97 Free Software Foundation, Inc. 
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions.
+Copyright @copyright{} 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003
+        Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
 
 @end titlepage
 @page
@@ -343,16 +388,23 @@ into another language, under the above conditions for modified versions.
 
 
 @node Top
-@top The Gnus Newsreader
+@top The gnus Newsreader
 
 @ifinfo
 
-You can read news (and mail) from within Emacs by using Gnus.  The news
-can be gotten by any nefarious means you can think of---@sc{nntp}, local
+You can read news (and mail) from within Emacs by using T-gnus.  The news
+can be gotten by any nefarious means you can think of---@acronym{NNTP}, local
 spool or your mbox file.  All at the same time, if you want to push your
 luck.
 
-This manual corresponds to Quassia Gnus 0.34.
+T-gnus provides @acronym{MIME} features based on @acronym{SEMI} API.  So
+T-gnus supports your right to read strange messages including big images
+or other various kinds of formats.  T-gnus also supports
+internationalization/localization and multiscript features based on MULE
+API.  So T-gnus does not discriminate various language communities.  Oh,
+if you are a Klingon, please wait Unicode Next Generation.
+
+This manual corresponds to T-gnus 6.16.
 
 @end ifinfo
 
@@ -364,75 +416,599 @@ This manual corresponds to Quassia Gnus 0.34.
 @end iflatex
 
 Gnus is the advanced, self-documenting, customizable, extensible
-unreal-time newsreader for GNU Emacs.  
+unreal-time newsreader for GNU Emacs.
 
 Oops.  That sounds oddly familiar, so let's start over again to avoid
 being accused of plagiarism:
 
 Gnus is a message-reading laboratory.  It will let you look at just
 about anything as if it were a newsgroup.  You can read mail with it,
-you can browse directories with it, you can @code{ftp} with it---you can
-even read news with it!
+you can browse directories with it, you can @code{ftp} with it---you
+can even read news with it!
 
 Gnus tries to empower people who read news the same way Emacs empowers
 people who edit text.  Gnus sets no limits to what the user should be
-allowed to do.  Users are encouraged to extend Gnus to make it behave
+allowed to do.  Users are encouraged to extend gnus to make it behave
 like they want it to behave.  A program should not control people;
 people should be empowered to do what they want by using (or abusing)
 the program.
 
 @end iftex
 
-
 @menu
-* Starting Up::           Finding news can be a pain.
-* The Group Buffer::      Selecting, subscribing and killing groups.
-* The Summary Buffer::    Reading, saving and posting articles.
-* The Article Buffer::    Displaying and handling articles.
-* Composing Messages::    Information on sending mail and news.
-* Select Methods::        Gnus reads all messages from various select methods.
-* Scoring::               Assigning values to articles.
-* Various::               General purpose settings.
-* The End::               Farewell and goodbye.
-* Appendices::            Terminology, Emacs intro, FAQ, History, Internals.
-* Index::                 Variable, function and concept index.
-* Key Index::             Key Index.
+* Starting Up::                 Finding news can be a pain.
+* Group Buffer::                Selecting, subscribing and killing groups.
+* Summary Buffer::              Reading, saving and posting articles.
+* Article Buffer::              Displaying and handling articles.
+* Composing Messages::          Information on sending mail and news.
+* Select Methods::              Gnus reads all messages from various select methods.
+* Scoring::                     Assigning values to articles.
+* Various::                     General purpose settings.
+* The End::                     Farewell and goodbye.
+* Appendices::                  Terminology, Emacs intro, @acronym{FAQ}, History, Internals.
+* Index::                       Variable, function and concept index.
+* Key Index::                   Key Index.
+
+Other related manuals
+
+* Message:(message).            Composing messages.
+* Emacs-MIME:(emacs-mime).      Composing messages; @acronym{MIME}-specific parts.
+* Sieve:(sieve).                Managing Sieve scripts in Emacs.
+* PGG:(pgg).                    @acronym{PGP/MIME} with Gnus.
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Starting Gnus
+
+* Finding the News::            Choosing a method for getting news.
+* The First Time::              What does Gnus do the first time you start it?
+* The Server is Down::          How can I read my mail then?
+* Slave Gnusae::                You can have more than one Gnus active at a time.
+* Fetching a Group::            Starting Gnus just to read a group.
+* New Groups::                  What is Gnus supposed to do with new groups?
+* Changing Servers::            You may want to move from one server to another.
+* Startup Files::               Those pesky startup files---@file{.newsrc}.
+* Auto Save::                   Recovering from a crash.
+* The Active File::             Reading the active file over a slow line Takes Time.
+* Startup Variables::           Other variables you might change.
+
+New Groups
+
+* Checking New Groups::         Determining what groups are new.
+* Subscription Methods::        What Gnus should do with new groups.
+* Filtering New Groups::        Making Gnus ignore certain new groups.
+
+Group Buffer
+
+* Group Buffer Format::         Information listed and how you can change it.
+* Group Maneuvering::           Commands for moving in the group buffer.
+* Selecting a Group::           Actually reading news.
+* Subscription Commands::       Unsubscribing, killing, subscribing.
+* Group Data::                  Changing the info for a group.
+* Group Levels::                Levels? What are those, then?
+* Group Score::                 A mechanism for finding out what groups you like.
+* Marking Groups::              You can mark groups for later processing.
+* Foreign Groups::              Creating and editing groups.
+* Group Parameters::            Each group may have different parameters set.
+* Listing Groups::              Gnus can list various subsets of the groups.
+* Sorting Groups::              Re-arrange the group order.
+* Group Maintenance::           Maintaining a tidy @file{.newsrc} file.
+* Browse Foreign Server::       You can browse a server.  See what it has to offer.
+* Exiting Gnus::                Stop reading news and get some work done.
+* Group Topics::                A folding group mode divided into topics.
+* Misc Group Stuff::            Other stuff that you can to do.
+
+Group Buffer Format
+
+* Group Line Specification::    Deciding how the group buffer is to look.
+* Group Mode Line Specification::  The group buffer mode line.
+* Group Highlighting::          Having nice colors in the group buffer.
+
+Group Topics
+
+* Topic Commands::              Interactive E-Z commands.
+* Topic Variables::             How to customize the topics the Lisp Way.
+* Topic Sorting::               Sorting each topic individually.
+* Topic Topology::              A map of the world.
+* Topic Parameters::            Parameters that apply to all groups in a topic.
+
+Misc Group Stuff
+
+* Scanning New Messages::       Asking Gnus to see whether new messages have arrived.
+* Group Information::           Information and help on groups and Gnus.
+* Group Timestamp::             Making Gnus keep track of when you last read a group.
+* File Commands::               Reading and writing the Gnus files.
+* Sieve Commands::              Managing Sieve scripts.
+
+Summary Buffer
+
+* Summary Buffer Format::       Deciding how the summary buffer is to look.
+* Summary Maneuvering::         Moving around the summary buffer.
+* Choosing Articles::           Reading articles.
+* Paging the Article::          Scrolling the current article.
+* Reply Followup and Post::     Posting articles.
+* Delayed Articles::            Send articles at a later time.
+* Marking Articles::            Marking articles as read, expirable, etc.
+* Limiting::                    You can limit the summary buffer.
+* Threading::                   How threads are made.
+* Sorting the Summary Buffer::  How articles and threads are sorted.
+* Asynchronous Fetching::       Gnus might be able to pre-fetch articles.
+* Article Caching::             You may store articles in a cache.
+* Persistent Articles::         Making articles expiry-resistant.
+* Article Backlog::             Having already read articles hang around.
+* Saving Articles::             Ways of customizing article saving.
+* Decoding Articles::           Gnus can treat series of (uu)encoded articles.
+* Article Treatment::           The article buffer can be mangled at will.
+* MIME Commands::               Doing MIMEy things with the articles.
+* Charsets::                    Character set issues.
+* Article Commands::            Doing various things with the article buffer.
+* Summary Sorting::             Sorting the summary buffer in various ways.
+* Finding the Parent::          No child support? Get the parent.
+* Alternative Approaches::      Reading using non-default summaries.
+* Tree Display::                A more visual display of threads.
+* Mail Group Commands::         Some commands can only be used in mail groups.
+* Various Summary Stuff::       What didn't fit anywhere else.
+* Exiting the Summary Buffer::  Returning to the Group buffer,
+                                or reselecting the current group.
+* Crosspost Handling::          How crossposted articles are dealt with.
+* Duplicate Suppression::       An alternative when crosspost handling fails.
+* Security::                    Decrypt and Verify.
+* Mailing List::                Mailing list minor mode.
+
+Summary Buffer Format
+
+* Summary Buffer Lines::        You can specify how summary lines should look.
+* To From Newsgroups::          How to not display your own name.
+* Summary Buffer Mode Line::    You can say how the mode line should look.
+* Summary Highlighting::        Making the summary buffer all pretty and nice.
+
+Choosing Articles
+
+* Choosing Commands::           Commands for choosing articles.
+* Choosing Variables::          Variables that influence these commands.
+
+Reply, Followup and Post
+
+* Summary Mail Commands::       Sending mail.
+* Summary Post Commands::       Sending news.
+* Summary Message Commands::    Other Message-related commands.
+* Canceling and Superseding::
+
+Marking Articles
+
+* Unread Articles::             Marks for unread articles.
+* Read Articles::               Marks for read articles.
+* Other Marks::                 Marks that do not affect readedness.
+
+Marking Articles
+
+* Setting Marks::             How to set and remove marks.
+* Generic Marking Commands::  How to customize the marking.
+* Setting Process Marks::     How to mark articles for later processing.
+
+Threading
+
+* Customizing Threading::       Variables you can change to affect the threading.
+* Thread Commands::             Thread based commands in the summary buffer.
+
+Customizing Threading
+
+* Loose Threads::               How Gnus gathers loose threads into bigger threads.
+* Filling In Threads::          Making the threads displayed look fuller.
+* More Threading::              Even more variables for fiddling with threads.
+* Low-Level Threading::         You thought it was over@dots{} but you were wrong!
+
+Decoding Articles
+
+* Uuencoded Articles::          Uudecode articles.
+* Shell Archives::              Unshar articles.
+* PostScript Files::            Split PostScript.
+* Other Files::                 Plain save and binhex.
+* Decoding Variables::          Variables for a happy decoding.
+* Viewing Files::               You want to look at the result of the decoding?
+
+Decoding Variables
+
+* Rule Variables::              Variables that say how a file is to be viewed.
+* Other Decode Variables::      Other decode variables.
+* Uuencoding and Posting::      Variables for customizing uuencoding.
+
+Article Treatment
+
+* Article Highlighting::        You want to make the article look like fruit salad.
+* Article Fontisizing::         Making emphasized text look nice.
+* Article Hiding::              You also want to make certain info go away.
+* Article Washing::             Lots of way-neat functions to make life better.
+* Article Header::              Doing various header transformations.
+* Article Buttons::             Click on URLs, Message-IDs, addresses and the like.
+* Article Button Levels::       Controlling appearance of buttons.
+* Article Date::                Grumble, UT!
+* Article Display::             Display various stuff---X-Face, Picons, Smileys
+* Article Signature::           What is a signature?
+* Article Miscellanea::         Various other stuff.
+
+Alternative Approaches
+
+* Pick and Read::               First mark articles and then read them.
+* Binary Groups::               Auto-decode all articles.
+
+Various Summary Stuff
+
+* Summary Group Information::   Information oriented commands.
+* Searching for Articles::      Multiple article commands.
+* Summary Generation Commands::
+* Really Various Summary Commands::  Those pesky non-conformant commands.
+
+Article Buffer
+
+* Hiding Headers::              Deciding what headers should be displayed.
+* Using MIME::                  Pushing articles through @acronym{MIME} before reading them.
+* Customizing Articles::        Tailoring the look of the articles.
+* Article Keymap::              Keystrokes available in the article buffer.
+* Misc Article::                Other stuff.
+
+Composing Messages
+
+* Mail::                        Mailing and replying.
+* Posting Server::              What server should you post and mail via?
+* Mail and Post::               Mailing and posting at the same time.
+* Archived Messages::           Where Gnus stores the messages you've sent.
+* Posting Styles::              An easier way to specify who you are.
+* Drafts::                      Postponing messages and rejected messages.
+* Rejected Articles::           What happens if the server doesn't like your article?
+* Signing and encrypting::      How to compose secure messages.
+
+Select Methods
+
+* Server Buffer::               Making and editing virtual servers.
+* Getting News::                Reading USENET news with Gnus.
+* Getting Mail::                Reading your personal mail with Gnus.
+* Browsing the Web::            Getting messages from a plethora of Web sources.
+* IMAP::                        Using Gnus as a @acronym{IMAP} client.
+* Other Sources::               Reading directories, files, SOUP packets.
+* Combined Groups::             Combining groups into one group.
+* Gnus Unplugged::              Reading news and mail offline.
+
+Server Buffer
+
+* Server Buffer Format::        You can customize the look of this buffer.
+* Server Commands::             Commands to manipulate servers.
+* Example Methods::             Examples server specifications.
+* Creating a Virtual Server::   An example session.
+* Server Variables::            Which variables to set.
+* Servers and Methods::         You can use server names as select methods.
+* Unavailable Servers::         Some servers you try to contact may be down.
+
+Getting News
+
+* NNTP::                        Reading news from an @acronym{NNTP} server.
+* News Spool::                  Reading news from the local spool.
+
+@acronym{NNTP}
+
+* Direct Functions::            Connecting directly to the server.
+* Indirect Functions::          Connecting indirectly to the server.
+* Common Variables::            Understood by several connection functions.
+
+Getting Mail
+
+* Mail in a Newsreader::        Important introductory notes.
+* Getting Started Reading Mail::  A simple cookbook example.
+* Splitting Mail::              How to create mail groups.
+* Mail Sources::                How to tell Gnus where to get mail from.
+* Mail Back End Variables::     Variables for customizing mail handling.
+* Fancy Mail Splitting::        Gnus can do hairy splitting of incoming mail.
+* Group Mail Splitting::        Use group customize to drive mail splitting.
+* Incorporating Old Mail::      What about the old mail you have?
+* Expiring Mail::               Getting rid of unwanted mail.
+* Washing Mail::                Removing cruft from the mail you get.
+* Duplicates::                  Dealing with duplicated mail.
+* Not Reading Mail::            Using mail back ends for reading other files.
+* Choosing a Mail Back End::    Gnus can read a variety of mail formats.
+
+Mail Sources
+
+* Mail Source Specifiers::      How to specify what a mail source is.
+* Mail Source Customization::   Some variables that influence things.
+* Fetching Mail::               Using the mail source specifiers.
+
+Choosing a Mail Back End
+
+* Unix Mail Box::               Using the (quite) standard Un*x mbox.
+* Rmail Babyl::                 Emacs programs use the Rmail Babyl format.
+* Mail Spool::                  Store your mail in a private spool?
+* MH Spool::                    An mhspool-like back end.
+* Maildir::                     Another one-file-per-message format.
+* Mail Folders::                Having one file for each group.
+* Comparing Mail Back Ends::    An in-depth looks at pros and cons.
+
+Browsing the Web
+
+* Archiving Mail::
+* Web Searches::                Creating groups from articles that match a string.
+* Slashdot::                    Reading the Slashdot comments.
+* Ultimate::                    The Ultimate Bulletin Board systems.
+* Web Archive::                 Reading mailing list archived on web.
+* RSS::                         Reading RDF site summary.
+* Customizing w3::              Doing stuff to Emacs/w3 from Gnus.
+
+@acronym{IMAP}
+
+* Splitting in IMAP::           Splitting mail with nnimap.
+* Expiring in IMAP::            Expiring mail with nnimap.
+* Editing IMAP ACLs::           Limiting/enabling other users access to a mailbox.
+* Expunging mailboxes::         Equivalent of a ``compress mailbox'' button.
+* A note on namespaces::        How to (not) use @acronym{IMAP} namespace in Gnus.
+* Debugging IMAP::              What to do when things don't work.
+
+Other Sources
+
+* Directory Groups::            You can read a directory as if it was a newsgroup.
+* Anything Groups::             Dired?  Who needs dired?
+* Document Groups::             Single files can be the basis of a group.
+* SOUP::                        Reading @sc{soup} packets ``offline''.
+* Mail-To-News Gateways::       Posting articles via mail-to-news gateways.
+
+Document Groups
+
+* Document Server Internals::   How to add your own document types.
+
+SOUP
+
+* SOUP Commands::               Commands for creating and sending @sc{soup} packets
+* SOUP Groups::                 A back end for reading @sc{soup} packets.
+* SOUP Replies::                How to enable @code{nnsoup} to take over mail and news.
+
+Combined Groups
+
+* Virtual Groups::              Combining articles from many groups.
+* Kibozed Groups::              Looking through parts of the newsfeed for articles.
+
+Gnus Unplugged
+
+* Agent Basics::                How it all is supposed to work.
+* Agent Categories::            How to tell the Gnus Agent what to download.
+* Agent Commands::              New commands for all the buffers.
+* Agent Visuals::               Ways that the agent may effect your summary buffer.
+* Agent as Cache::              The Agent is a big cache too.
+* Agent Expiry::                How to make old articles go away.
+* Agent Regeneration::          How to recover from lost connections and other accidents.
+* Agent and IMAP::              How to use the Agent with @acronym{IMAP}.
+* Outgoing Messages::           What happens when you post/mail something?
+* Agent Variables::             Customizing is fun.
+* Example Setup::               An example @file{~/.gnus.el} file for offline people.
+* Batching Agents::             How to fetch news from a @code{cron} job.
+* Agent Caveats::               What you think it'll do and what it does.
+
+Agent Categories
+
+* Category Syntax::             What a category looks like.
+* Category Buffer::             A buffer for maintaining categories.
+* Category Variables::          Customize'r'Us.
+
+Agent Commands
+
+* Group Agent Commands::        Configure groups and fetch their contents.
+* Summary Agent Commands::      Manually select then fetch specific articles.
+* Server Agent Commands::       Select the servers that are supported by the agent.
+
+Scoring
+
+* Summary Score Commands::      Adding score entries for the current group.
+* Group Score Commands::        General score commands.
+* Score Variables::             Customize your scoring.  (My, what terminology).
+* Score File Format::           What a score file may contain.
+* Score File Editing::          You can edit score files by hand as well.
+* Adaptive Scoring::            Big Sister Gnus knows what you read.
+* Home Score File::             How to say where new score entries are to go.
+* Followups To Yourself::       Having Gnus notice when people answer you.
+* Scoring On Other Headers::    Scoring on non-standard headers.
+* Scoring Tips::                How to score effectively.
+* Reverse Scoring::             That problem child of old is not problem.
+* Global Score Files::          Earth-spanning, ear-splitting score files.
+* Kill Files::                  They are still here, but they can be ignored.
+* Converting Kill Files::       Translating kill files to score files.
+* GroupLens::                   Getting predictions on what you like to read.
+* Advanced Scoring::            Using logical expressions to build score rules.
+* Score Decays::                It can be useful to let scores wither away.
+
+GroupLens
+
+* Using GroupLens::             How to make Gnus use GroupLens.
+* Rating Articles::             Letting GroupLens know how you rate articles.
+* Displaying Predictions::      Displaying predictions given by GroupLens.
+* GroupLens Variables::         Customizing GroupLens.
+
+Advanced Scoring
+
+* Advanced Scoring Syntax::     A definition.
+* Advanced Scoring Examples::   What they look like.
+* Advanced Scoring Tips::       Getting the most out of it.
+
+Various
+
+* Process/Prefix::              A convention used by many treatment commands.
+* Interactive::                 Making Gnus ask you many questions.
+* Symbolic Prefixes::           How to supply some Gnus functions with options.
+* Formatting Variables::        You can specify what buffers should look like.
+* Window Layout::               Configuring the Gnus buffer windows.
+* Faces and Fonts::             How to change how faces look.
+* Compilation::                 How to speed Gnus up.
+* Mode Lines::                  Displaying information in the mode lines.
+* Highlighting and Menus::      Making buffers look all nice and cozy.
+* Buttons::                     Get tendinitis in ten easy steps!
+* Daemons::                     Gnus can do things behind your back.
+* NoCeM::                       How to avoid spam and other fatty foods.
+* Undo::                        Some actions can be undone.
+* Predicate Specifiers::        Specifying predicates.
+* Moderation::                  What to do if you're a moderator.
+* Image Enhancements::          Modern versions of Emacs/XEmacs can display images.
+* Fuzzy Matching::              What's the big fuzz?
+* Thwarting Email Spam::        A how-to on avoiding unsolicited commercial email.
+* Other modes::                 Interaction with other modes.
+* Various Various::             Things that are really various.
+
+Formatting Variables
+
+* Formatting Basics::           A formatting variable is basically a format string.
+* Mode Line Formatting::        Some rules about mode line formatting variables.
+* Advanced Formatting::         Modifying output in various ways.
+* User-Defined Specs::          Having Gnus call your own functions.
+* Formatting Fonts::            Making the formatting look colorful and nice.
+* Positioning Point::           Moving point to a position after an operation.
+* Tabulation::                  Tabulating your output.
+* Wide Characters::             Dealing with wide characters.
+
+Image Enhancements
+
+* X-Face::                      Display a funky, teensy black-and-white image.
+* Face::                        Display a funkier, teensier colored image.
+* Smileys::                     Show all those happy faces the way they were meant to be shown.
+* Picons::                      How to display pictures of what you're reading.
+* XVarious::                    Other XEmacsy Gnusey variables.
+
+Thwarting Email Spam
+
+* The problem of spam::         Some background, and some solutions
+* Anti-Spam Basics::            Simple steps to reduce the amount of spam.
+* SpamAssassin::                How to use external anti-spam tools.
+* Hashcash::                    Reduce spam by burning CPU time.
+* Filtering Spam Using The Spam ELisp Package::
+* Filtering Spam Using Statistics with spam-stat::
+
+Filtering Spam Using The Spam ELisp Package
+
+* Spam ELisp Package Sequence of Events::  
+* Spam ELisp Package Filtering of Incoming Mail::  
+* Spam ELisp Package Global Variables::  
+* Spam ELisp Package Configuration Examples::  
+* Blacklists and Whitelists::   
+* BBDB Whitelists::             
+* Gmane Spam Reporting::        
+* Anti-spam Hashcash Payments::  
+* Blackholes::                  
+* Regular Expressions Header Matching::  
+* Bogofilter::                  
+* ifile spam filtering::        
+* spam-stat spam filtering::    
+* SpamOracle::                  
+* Extending the Spam ELisp package::  
+
+Filtering Spam Using Statistics with spam-stat
+
+* Creating a spam-stat dictionary::
+* Splitting mail using spam-stat::
+* Low-level interface to the spam-stat dictionary::
+
+Appendices
+
+* XEmacs::                      Requirements for installing under XEmacs.
+* History::                     How Gnus got where it is today.
+* On Writing Manuals::          Why this is not a beginner's guide.
+* Terminology::                 We use really difficult, like, words here.
+* Customization::               Tailoring Gnus to your needs.
+* Troubleshooting::             What you might try if things do not work.
+* Gnus Reference Guide::        Rilly, rilly technical stuff.
+* Emacs for Heathens::          A short introduction to Emacsian terms.
+* Frequently Asked Questions::  The Gnus FAQ
+
+History
+
+* 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.
+
+New Features
+
+* ding Gnus::                   New things in Gnus 5.0/5.1, the first new Gnus.
+* September Gnus::              The Thing Formally Known As Gnus 5.2/5.3.
+* Red Gnus::                    Third time best---Gnus 5.4/5.5.
+* Quassia Gnus::                Two times two is four, or Gnus 5.6/5.7.
+* Pterodactyl Gnus::            Pentad also starts with P, AKA Gnus 5.8/5.9.
+* Oort Gnus::                   It's big.  It's far out.  Gnus 5.10.
+
+Customization
+
+* Slow/Expensive Connection::   You run a local Emacs and get the news elsewhere.
+* Slow Terminal Connection::    You run a remote Emacs.
+* Little Disk Space::           You feel that having large setup files is icky.
+* Slow Machine::                You feel like buying a faster machine.
+
+Gnus Reference Guide
+
+* Gnus Utility Functions::      Common functions and variable to use.
+* Back End Interface::          How Gnus communicates with the servers.
+* Score File Syntax::           A BNF definition of the score file standard.
+* Headers::                     How Gnus stores headers internally.
+* Ranges::                      A handy format for storing mucho numbers.
+* Group Info::                  The group info format.
+* Extended Interactive::        Symbolic prefixes and stuff.
+* Emacs/XEmacs Code::           Gnus can be run under all modern Emacsen.
+* Various File Formats::        Formats of files that Gnus use.
+
+Back End Interface
+
+* Required Back End Functions::  Functions that must be implemented.
+* Optional Back End Functions::  Functions that need not be implemented.
+* Error Messaging::             How to get messages and report errors.
+* Writing New Back Ends::       Extending old back ends.
+* Hooking New Back Ends Into Gnus::  What has to be done on the Gnus end.
+* Mail-like Back Ends::         Some tips on mail back ends.
+
+Various File Formats
+
+* Active File Format::          Information on articles and groups available.
+* Newsgroups File Format::      Group descriptions.
+
+Emacs for Heathens
+
+* Keystrokes::                  Entering text and executing commands.
+* Emacs Lisp::                  The built-in Emacs programming language.
+
+@end detailmenu
 @end menu
 
 @node Starting Up
-@chapter Starting Gnus
+@chapter Starting gnus
 @cindex starting up
 
 @kindex M-x gnus
 @findex gnus
-If your system administrator has set things up properly, starting Gnus
+If your system administrator has set things up properly, starting gnus
 and reading news is extremely easy---you just type @kbd{M-x gnus} in
-your Emacs. 
+your Emacs.
 
 @findex gnus-other-frame
 @kindex M-x gnus-other-frame
-If you want to start Gnus in a different frame, you can use the command
+If you want to start gnus in a different frame, you can use the command
 @kbd{M-x gnus-other-frame} instead.
 
 If things do not go smoothly at startup, you have to twiddle some
-variables in your @file{~/.gnus} file.  This file is similar to
-@file{~/.emacs}, but is read when gnus starts.
+variables in your @file{~/.gnus.el} file.  This file is similar to
+@file{~/.emacs}, but is read when Gnus starts.
 
 If you puzzle at any terms used in this manual, please refer to the
 terminology section (@pxref{Terminology}).
 
 @menu
-* Finding the News::    Choosing a method for getting news.
-* The First Time::      What does Gnus do the first time you start it?
-* The Server is Down::  How can I read my mail then?
-* Slave Gnusae::        You can have more than one Gnus active at a time.
-* Fetching a Group::    Starting Gnus just to read a group.
-* New Groups::          What is Gnus supposed to do with new groups?
-* Startup Files::       Those pesky startup files---@file{.newsrc}.
-* Auto Save::           Recovering from a crash.
-* The Active File::     Reading the active file over a slow line Takes Time.
-* Changing Servers::    You may want to move from one server to another.
-* Startup Variables::   Other variables you might change.
+* Finding the News::            Choosing a method for getting news.
+* The First Time::              What does Gnus do the first time you start it?
+* The Server is Down::          How can I read my mail then?
+* Slave Gnusae::                You can have more than one Gnus active at a time.
+* Fetching a Group::            Starting Gnus just to read a group.
+* New Groups::                  What is Gnus supposed to do with new groups?
+* Changing Servers::            You may want to move from one server to another.
+* Startup Files::               Those pesky startup files---@file{.newsrc}.
+* Auto Save::                   Recovering from a crash.
+* The Active File::             Reading the active file over a slow line Takes Time.
+* Startup Variables::           Other variables you might change.
 @end menu
 
 
@@ -442,13 +1018,13 @@ terminology section (@pxref{Terminology}).
 
 @vindex gnus-select-method
 @c @head
-The @code{gnus-select-method} variable says where Gnus should look for
+The @code{gnus-select-method} variable says where gnus should look for
 news.  This variable should be a list where the first element says
 @dfn{how} and the second element says @dfn{where}.  This method is your
 native method.  All groups not fetched with this method are
 foreign groups.
 
-For instance, if the @samp{news.somewhere.edu} @sc{nntp} server is where
+For instance, if the @samp{news.somewhere.edu} @acronym{NNTP} server is where
 you want to get your daily dosage of news from, you'd say:
 
 @lisp
@@ -462,16 +1038,18 @@ If you want to read directly from the local spool, say:
 @end lisp
 
 If you can use a local spool, you probably should, as it will almost
-certainly be much faster.
+certainly be much faster.  But do not use the local spool if your
+server is running Leafnode; in this case, use @code{(nntp "localhost")}.
 
 @vindex gnus-nntpserver-file
 @cindex NNTPSERVER
-@cindex @sc{nntp} server
-If this variable is not set, Gnus will take a look at the
-@code{NNTPSERVER} environment variable.  If that variable isn't set,
-Gnus will see whether @code{gnus-nntpserver-file}
-(@file{/etc/nntpserver} by default) has any opinions on the matter.  If
-that fails as well, Gnus will try to use the machine running Emacs as an @sc{nntp} server.  That's a long shot, though.
+@cindex @acronym{NNTP} server
+If this variable is not set, gnus will take a look at the
+@env{NNTPSERVER} environment variable.  If that variable isn't set,
+gnus will see whether @code{gnus-nntpserver-file}
+(@file{/etc/nntpserver} by default) has any opinions on the matter.
+If that fails as well, gnus will try to use the machine running Emacs
+as an @acronym{NNTP} server.  That's a long shot, though.
 
 @vindex gnus-nntp-server
 If @code{gnus-nntp-server} is set, this variable will override
@@ -479,15 +1057,19 @@ If @code{gnus-nntp-server} is set, this variable will override
 @code{gnus-nntp-server} to @code{nil}, which is what it is by default.
 
 @vindex gnus-secondary-servers
-You can also make Gnus prompt you interactively for the name of an
-@sc{nntp} server.  If you give a non-numerical prefix to @code{gnus}
-(i.e., @kbd{C-u M-x gnus}), Gnus will let you choose between the servers
+@vindex gnus-nntp-server
+You can also make gnus prompt you interactively for the name of an
+@acronym{NNTP} server.  If you give a non-numerical prefix to @code{gnus}
+(i.e., @kbd{C-u M-x gnus}), gnus will let you choose between the servers
 in the @code{gnus-secondary-servers} list (if any).  You can also just
-type in the name of any server you feel like visiting.
+type in the name of any server you feel like visiting.  (Note that this
+will set @code{gnus-nntp-server}, which means that if you then @kbd{M-x
+gnus} later in the same Emacs session, Gnus will contact the same
+server.)
 
 @findex gnus-group-browse-foreign-server
 @kindex B (Group)
-However, if you use one @sc{nntp} server regularly and are just
+However, if you use one @acronym{NNTP} server regularly and are just
 interested in a couple of groups from a different server, you would be
 better served by using the @kbd{B} command in the group buffer.  It will
 let you have a look at what groups are available, and you can subscribe
@@ -504,8 +1086,8 @@ files during startup (if that's required), and new newsgroups that
 appear on these servers will be subscribed (or not) just as native
 groups are.
 
-For instance, if you use the @code{nnmbox} backend to read your mail, you
-would typically set this variable to
+For instance, if you use the @code{nnmbox} back end to read your mail,
+you would typically set this variable to
 
 @lisp
 (setq gnus-secondary-select-methods '((nnmbox "")))
@@ -516,23 +1098,23 @@ would typically set this variable to
 @section The First Time
 @cindex first time usage
 
-If no startup files exist, Gnus will try to determine what groups should
+If no startup files exist, gnus will try to determine what groups should
 be subscribed by default.
 
 @vindex gnus-default-subscribed-newsgroups
-If the variable @code{gnus-default-subscribed-newsgroups} is set, Gnus
+If the variable @code{gnus-default-subscribed-newsgroups} is set, gnus
 will subscribe you to just those groups in that list, leaving the rest
 killed.  Your system administrator should have set this variable to
 something useful.
 
-Since she hasn't, Gnus will just subscribe you to a few arbitrarily
+Since she hasn't, gnus will just subscribe you to a few arbitrarily
 picked groups (i.e., @samp{*.newusers}).  (@dfn{Arbitrary} is defined
 here as @dfn{whatever Lars thinks you should read}.)
 
-You'll also be subscribed to the Gnus documentation group, which should
-help you with most common problems.  
+You'll also be subscribed to the gnus documentation group, which should
+help you with most common problems.
 
-If @code{gnus-default-subscribed-newsgroups} is @code{t}, Gnus will just
+If @code{gnus-default-subscribed-newsgroups} is @code{t}, gnus will just
 use the normal functions for handling new groups, and not do anything
 special.
 
@@ -541,9 +1123,9 @@ special.
 @section The Server is Down
 @cindex server errors
 
-If the default server is down, Gnus will understandably have some
+If the default server is down, gnus will understandably have some
 problems starting.  However, if you have some mail groups in addition to
-the news groups, you may want to start Gnus anyway.
+the news groups, you may want to start gnus anyway.
 
 Gnus, being the trusting sort of program, will ask whether to proceed
 without a native select method if that server can't be contacted.  This
@@ -558,26 +1140,26 @@ buffer.  But, hey, that's your problem.  Blllrph!
 @c @head
 If you know that the server is definitely down, or you just want to read
 your mail without bothering with the server at all, you can use the
-@code{gnus-no-server} command to start Gnus.  That might come in handy
+@code{gnus-no-server} command to start gnus.  That might come in handy
 if you're in a hurry as well.  This command will not attempt to contact
 your primary server---instead, it will just activate all groups on level
 1 and 2.  (You should preferably keep no native groups on those two
-levels.)
+levels.) Also @pxref{Group Levels}.
 
 
 @node Slave Gnusae
 @section Slave Gnusae
 @cindex slave
 
-You might want to run more than one Emacs with more than one Gnus at the
+You might want to run more than one Emacs with more than one gnus at the
 same time.  If you are using different @file{.newsrc} files (e.g., if you
-are using the two different Gnusae to read from two different servers),
+are using the two different gnusae to read from two different servers),
 that is no problem whatsoever.  You just do it.
 
 The problem appears when you want to run two Gnusae that use the same
-@code{.newsrc} file.
+@file{.newsrc} file.
 
-To work around that problem some, we here at the Think-Tank at the Gnus
+To work around that problem some, we here at the Think-Tank at the gnus
 Towers have come up with a new concept: @dfn{Masters} and
 @dfn{slaves}.  (We have applied for a patent on this concept, and have
 taken out a copyright on those words.  If you wish to use those words in
@@ -585,18 +1167,24 @@ conjunction with each other, you have to send $1 per usage instance to
 me.  Usage of the patent (@dfn{Master/Slave Relationships In Computer
 Applications}) will be much more expensive, of course.)
 
-Anyways, you start one Gnus up the normal way with @kbd{M-x gnus} (or
-however you do it).  Each subsequent slave Gnusae should be started with
+@findex gnus-slave
+Anyway, you start one gnus up the normal way with @kbd{M-x gnus} (or
+however you do it).  Each subsequent slave gnusae should be started with
 @kbd{M-x gnus-slave}.  These slaves won't save normal @file{.newsrc}
 files, but instead save @dfn{slave files} that contain information only
-on what groups have been read in the slave session.  When a master Gnus
+on what groups have been read in the slave session.  When a master gnus
 starts, it will read (and delete) these slave files, incorporating all
 information from them.  (The slave files will be read in the sequence
 they were created, so the latest changes will have precedence.)
 
 Information from the slave files has, of course, precedence over the
-information in the normal (i.e., master) @code{.newsrc} file.
+information in the normal (i.e., master) @file{.newsrc} file.
 
+If the @file{.newsrc*} files have not been saved in the master when the
+slave starts, you may be prompted as to whether to read an auto-save
+file.  If you answer ``yes'', the unsaved changes to the master will be
+incorporated into the slave.  If you answer ``no'', the slave may see some
+messages as unread that have been read in the master.
 
 @node Fetching a Group
 @section Fetching a Group
@@ -604,7 +1192,7 @@ information in the normal (i.e., master) @code{.newsrc} file.
 
 @findex gnus-fetch-group
 It is sometimes convenient to be able to just say ``I want to read this
-group and I don't care whether Gnus has been started or not''.  This is
+group and I don't care whether gnus has been started or not''.  This is
 perhaps more useful for people who write code than for users, but the
 command @code{gnus-fetch-group} provides this functionality in any case.
 It takes the group name as a parameter.
@@ -622,13 +1210,13 @@ also save you some time at startup.  Even if this variable is
 @code{nil}, you can always subscribe to the new groups just by pressing
 @kbd{U} in the group buffer (@pxref{Group Maintenance}).  This variable
 is @code{ask-server} by default.  If you set this variable to
-@code{always}, then Gnus will query the backends for new groups even
+@code{always}, then Gnus will query the back ends for new groups even
 when you do the @kbd{g} command (@pxref{Scanning New Messages}).
 
 @menu
-* Checking New Groups::      Determining what groups are new.
-* Subscription Methods::     What Gnus should do with new groups.
-* Filtering New Groups::     Making Gnus ignore certain new groups.
+* Checking New Groups::         Determining what groups are new.
+* Subscription Methods::        What Gnus should do with new groups.
+* Filtering New Groups::        Making Gnus ignore certain new groups.
 @end menu
 
 
@@ -638,27 +1226,27 @@ when you do the @kbd{g} command (@pxref{Scanning New Messages}).
 Gnus normally determines whether a group is new or not by comparing the
 list of groups from the active file(s) with the lists of subscribed and
 dead groups.  This isn't a particularly fast method.  If
-@code{gnus-check-new-newsgroups} is @code{ask-server}, Gnus will ask the
+@code{gnus-check-new-newsgroups} is @code{ask-server}, gnus will ask the
 server for new groups since the last time.  This is both faster and
 cheaper.  This also means that you can get rid of the list of killed
 groups altogether, so you may set @code{gnus-save-killed-list} to
 @code{nil}, which will save time both at startup, at exit, and all over.
 Saves disk space, too.  Why isn't this the default, then?
-Unfortunately, not all servers support this command. 
+Unfortunately, not all servers support this command.
 
 I bet I know what you're thinking now: How do I find out whether my
 server supports @code{ask-server}?  No?  Good, because I don't have a
 fail-safe answer.  I would suggest just setting this variable to
 @code{ask-server} and see whether any new groups appear within the next
 few days.  If any do, then it works.  If none do, then it doesn't
-work.  I could write a function to make Gnus guess whether the server
+work.  I could write a function to make gnus guess whether the server
 supports @code{ask-server}, but it would just be a guess.  So I won't.
 You could @code{telnet} to the server and say @code{HELP} and see
 whether it lists @samp{NEWGROUPS} among the commands it understands.  If
 it does, then it might work.  (But there are servers that lists
 @samp{NEWGROUPS} without supporting the function properly.)
 
-This variable can also be a list of select methods.  If so, Gnus will
+This variable can also be a list of select methods.  If so, gnus will
 issue an @code{ask-server} command to each of the select methods, and
 subscribe them (or not) using the normal methods.  This might be handy
 if you are monitoring a few servers for new groups.  A side effect is
@@ -670,7 +1258,7 @@ Use the mantra ``dingnusdingnusdingnus'' to achieve permanent bliss.
 @subsection Subscription Methods
 
 @vindex gnus-subscribe-newsgroup-method
-What Gnus does when it encounters a new group is determined by the
+What gnus does when it encounters a new group is determined by the
 @code{gnus-subscribe-newsgroup-method} variable.
 
 This variable should contain a function.  This function will be called
@@ -700,14 +1288,14 @@ Subscribe all new groups in alphabetical order.
 Subscribe all new groups hierarchically.  The difference between this
 function and @code{gnus-subscribe-alphabetically} is slight.
 @code{gnus-subscribe-alphabetically} will subscribe new groups in a strictly
-alphabetical fashion, while this function will enter groups into it's
+alphabetical fashion, while this function will enter groups into its
 hierarchy.  So if you want to have the @samp{rec} hierarchy before the
 @samp{comp} hierarchy, this function will not mess that configuration
 up.  Or something like that.
 
 @item gnus-subscribe-interactively
 @vindex gnus-subscribe-interactively
-Subscribe new groups interactively.  This means that Gnus will ask
+Subscribe new groups interactively.  This means that gnus will ask
 you about @strong{all} new groups.  The groups you choose to subscribe
 to will be subscribed hierarchically.
 
@@ -715,15 +1303,31 @@ to will be subscribed hierarchically.
 @vindex gnus-subscribe-killed
 Kill all new groups.
 
+@item gnus-subscribe-topics
+@vindex gnus-subscribe-topics
+Put the groups into the topic that has a matching @code{subscribe} topic
+parameter (@pxref{Topic Parameters}).  For instance, a @code{subscribe}
+topic parameter that looks like
+
+@example
+"nnslashdot"
+@end example
+
+will mean that all groups that match that regex will be subscribed under
+that topic.
+
+If no topics match the groups, the groups will be subscribed in the
+top-level topic.
+
 @end table
 
 @vindex gnus-subscribe-hierarchical-interactive
 A closely related variable is
 @code{gnus-subscribe-hierarchical-interactive}.  (That's quite a
-mouthful.)  If this variable is non-@code{nil}, Gnus will ask you in a
+mouthful.)  If this variable is non-@code{nil}, gnus will ask you in a
 hierarchical fashion whether to subscribe to new groups or not.  Gnus
 will ask you for each sub-hierarchy whether you want to descend the
-hierarchy or not.  
+hierarchy or not.
 
 One common mistake is to set the variable a few paragraphs above
 (@code{gnus-subscribe-newsgroup-method}) to
@@ -764,13 +1368,14 @@ subscribed, and if it matches the latter, it will be ignored.
 @vindex gnus-auto-subscribed-groups
 Yet another variable that meddles here is
 @code{gnus-auto-subscribed-groups}.  It works exactly like
-@code{gnus-options-subscribe}, and is therefore really superfluous, but I
-thought it would be nice to have two of these.  This variable is more
-meant for setting some ground rules, while the other variable is used
-more for user fiddling.  By default this variable makes all new groups
-that come from mail backends (@code{nnml}, @code{nnbabyl},
-@code{nnfolder}, @code{nnmbox}, and @code{nnmh}) subscribed.  If you
-don't like that, just set this variable to @code{nil}.
+@code{gnus-options-subscribe}, and is therefore really superfluous,
+but I thought it would be nice to have two of these.  This variable is
+more meant for setting some ground rules, while the other variable is
+used more for user fiddling.  By default this variable makes all new
+groups that come from mail back ends (@code{nnml}, @code{nnbabyl},
+@code{nnfolder}, @code{nnmbox}, @code{nnmh}, and @code{nnmaildir})
+subscribed.  If you don't like that, just set this variable to
+@code{nil}.
 
 New groups that match this regexp are subscribed using
 @code{gnus-subscribe-options-newsgroup-method}.
@@ -780,20 +1385,20 @@ New groups that match this regexp are subscribed using
 @section Changing Servers
 @cindex changing servers
 
-Sometimes it is necessary to move from one @sc{nntp} server to another.
+Sometimes it is necessary to move from one @acronym{NNTP} server to another.
 This happens very rarely, but perhaps you change jobs, or one server is
-very flaky and you want to use another.  
+very flaky and you want to use another.
 
 Changing the server is pretty easy, right?  You just change
-@code{gnus-select-method} to point to the new server?  
+@code{gnus-select-method} to point to the new server?
 
 @emph{Wrong!}
 
 Article numbers are not (in any way) kept synchronized between different
-@sc{nntp} servers, and the only way Gnus keeps track of what articles
+@acronym{NNTP} servers, and the only way Gnus keeps track of what articles
 you have read is by keeping track of article numbers.  So when you
 change @code{gnus-select-method}, your @file{.newsrc} file becomes
-worthless.  
+worthless.
 
 Gnus provides a few functions to attempt to translate a @file{.newsrc}
 file from one server to another.  They all have one thing in
@@ -821,6 +1426,19 @@ and read ranges have become worthless.  You can use the @kbd{M-x
 gnus-group-clear-data-on-native-groups} command to clear out all data
 that you have on your native groups.  Use with caution.
 
+@kindex M-x gnus-group-clear-data
+@findex gnus-group-clear-data
+Clear the data from the current group only---nix out marks and the
+list of read articles (@code{gnus-group-clear-data}).
+
+After changing servers, you @strong{must} move the cache hierarchy away,
+since the cached articles will have wrong article numbers, which will
+affect which articles Gnus thinks are read.
+@code{gnus-group-clear-data-on-native-groups} will ask you if you want
+to have it done automatically; for @code{gnus-group-clear-data}, you
+can use @kbd{M-x gnus-cache-move-cache} (but beware, it will move the
+cache for all groups).
+
 
 @node Startup Files
 @section Startup Files
@@ -848,11 +1466,15 @@ never delete the @file{.newsrc.eld} file---it contains much information
 not stored in the @file{.newsrc} file.
 
 @vindex gnus-save-newsrc-file
+@vindex gnus-read-newsrc-file
 You can turn off writing the @file{.newsrc} file by setting
 @code{gnus-save-newsrc-file} to @code{nil}, which means you can delete
-the file and save some space, as well as making exit from Gnus faster.
+the file and save some space, as well as exiting from gnus faster.
 However, this will make it impossible to use other newsreaders than
-Gnus.  But hey, who would want to, right?
+gnus.  But hey, who would want to, right?  Similarly, setting
+@code{gnus-read-newsrc-file} to @code{nil} makes gnus ignore the
+@file{.newsrc} file and any @file{.newsrc-SERVER} files, which is
+convenient if you have a tendency to use Netscape once in a while.
 
 @vindex gnus-save-killed-list
 If @code{gnus-save-killed-list} (default @code{t}) is @code{nil}, Gnus
@@ -868,9 +1490,14 @@ saving.  This can be useful in certain obscure situations that involve
 several servers where not all servers support @code{ask-server}.
 
 @vindex gnus-startup-file
+@vindex gnus-backup-startup-file
+@vindex version-control
 The @code{gnus-startup-file} variable says where the startup files are.
 The default value is @file{~/.newsrc}, with the Gnus (El Dingo) startup
 file being whatever that one is, with a @samp{.eld} appended.
+If you want version control for this file, set
+@code{gnus-backup-startup-file}.  It respects the same values as the
+@code{version-control} variable.
 
 @vindex gnus-save-newsrc-hook
 @vindex gnus-save-quick-newsrc-hook
@@ -881,7 +1508,7 @@ saving the @file{.newsrc.eld} file, and
 @code{gnus-save-standard-newsrc-hook} is called just before saving the
 @file{.newsrc} file.  The latter two are commonly used to turn version
 control on or off.  Version control is on by default when saving the
-startup files.  If you want to turn backup creation off, say something like: 
+startup files.  If you want to turn backup creation off, say something like:
 
 @lisp
 (defun turn-off-backup ()
@@ -892,11 +1519,12 @@ startup files.  If you want to turn backup creation off, say something like:
 @end lisp
 
 @vindex gnus-init-file
-When Gnus starts, it will read the @code{gnus-site-init-file}
+@vindex gnus-site-init-file
+When gnus starts, it will read the @code{gnus-site-init-file}
 (@file{.../site-lisp/gnus} by default) and @code{gnus-init-file}
 (@file{~/.gnus} by default) files.  These are normal Emacs Lisp files
 and can be used to avoid cluttering your @file{~/.emacs} and
-@file{site-init} files with Gnus stuff.  Gnus will also check for files
+@file{site-init} files with gnus stuff.  Gnus will also check for files
 with the same names as these, but with @file{.elc} and @file{.el}
 suffixes.  In other words, if you have set @code{gnus-init-file} to
 @file{~/.gnus}, it will look for @file{~/.gnus.elc}, @file{~/.gnus.el},
@@ -909,27 +1537,31 @@ and finally @file{~/.gnus} (in this order).
 @cindex dribble file
 @cindex auto-save
 
-Whenever you do something that changes the Gnus data (reading articles,
+Whenever you do something that changes the gnus data (reading articles,
 catching up, killing/subscribing groups), the change is added to a
 special @dfn{dribble buffer}.  This buffer is auto-saved the normal
 Emacs way.  If your Emacs should crash before you have saved the
 @file{.newsrc} files, all changes you have made can be recovered from
 this file.
 
-If Gnus detects this file at startup, it will ask the user whether to
+If gnus detects this file at startup, it will ask the user whether to
 read it.  The auto save file is deleted whenever the real startup file is
 saved.
 
 @vindex gnus-use-dribble-file
-If @code{gnus-use-dribble-file} is @code{nil}, Gnus won't create and
+If @code{gnus-use-dribble-file} is @code{nil}, gnus won't create and
 maintain a dribble buffer.  The default is @code{t}.
 
 @vindex gnus-dribble-directory
 Gnus will put the dribble file(s) in @code{gnus-dribble-directory}.  If
-this variable is @code{nil}, which it is by default, Gnus will dribble
+this variable is @code{nil}, which it is by default, gnus will dribble
 into the directory where the @file{.newsrc} file is located.  (This is
 normally the user's home directory.)  The dribble file will get the same
-file permissions as the @code{.newsrc} file.
+file permissions as the @file{.newsrc} file.
+
+@vindex gnus-always-read-dribble-file
+If @code{gnus-always-read-dribble-file} is non-@code{nil}, Gnus will
+read the dribble file on startup without querying the user.
 
 
 @node The Active File
@@ -937,14 +1569,14 @@ file permissions as the @code{.newsrc} file.
 @cindex active file
 @cindex ignored groups
 
-When Gnus starts, or indeed whenever it tries to determine whether new
+When gnus starts, or indeed whenever it tries to determine whether new
 articles have arrived, it reads the active file.  This is a very large
 file that lists all the active groups and articles on the server.
 
 @vindex gnus-ignored-newsgroups
-Before examining the active file, Gnus deletes all lines that match the
+Before examining the active file, gnus deletes all lines that match the
 regexp @code{gnus-ignored-newsgroups}.  This is done primarily to reject
-any groups with bogus names, but you can use this variable to make Gnus
+any groups with bogus names, but you can use this variable to make gnus
 ignore hierarchies you aren't ever interested in.  However, this is not
 recommended.  In fact, it's highly discouraged.  Instead, @pxref{New
 Groups} for an overview of other variables that can be used instead.
@@ -956,16 +1588,16 @@ Groups} for an overview of other variables that can be used instead.
 @vindex gnus-read-active-file
 @c @head
 The active file can be rather Huge, so if you have a slow network, you
-can set @code{gnus-read-active-file} to @code{nil} to prevent Gnus from
+can set @code{gnus-read-active-file} to @code{nil} to prevent gnus from
 reading the active file.  This variable is @code{some} by default.
 
 Gnus will try to make do by getting information just on the groups that
 you actually subscribe to.
 
 Note that if you subscribe to lots and lots of groups, setting this
-variable to @code{nil} will probably make Gnus slower, not faster.  At
-present, having this variable @code{nil} will slow Gnus down
-considerably, unless you read news over a 2400 baud modem.  
+variable to @code{nil} will probably make gnus slower, not faster.  At
+present, having this variable @code{nil} will slow gnus down
+considerably, unless you read news over a 2400 baud modem.
 
 This variable can also have the value @code{some}.  Gnus will then
 attempt to read active info only on the subscribed groups.  On some
@@ -974,13 +1606,21 @@ support the @code{LIST ACTIVE group} command), on others this isn't fast
 at all.  In any case, @code{some} should be faster than @code{nil}, and
 is certainly faster than @code{t} over slow lines.
 
-If this variable is @code{nil}, Gnus will ask for group info in total
+Some news servers (old versions of Leafnode and old versions of INN, for
+instance) do not support the @code{LIST ACTIVE group}.  For these
+servers, @code{nil} is probably the most efficient value for this
+variable.
+
+If this variable is @code{nil}, gnus will ask for group info in total
 lock-step, which isn't very fast.  If it is @code{some} and you use an
-@sc{nntp} server, Gnus will pump out commands as fast as it can, and
+@acronym{NNTP} server, gnus will pump out commands as fast as it can, and
 read all the replies in one swoop.  This will normally result in better
 performance, but if the server does not support the aforementioned
 @code{LIST ACTIVE group} command, this isn't very nice to the server.
 
+If you think that starting up Gnus takes too long, try all the three
+different values for this variable and see what works best for you.
+
 In any case, if you use @code{some} or @code{nil}, you should definitely
 kill all groups that you aren't interested in to speed things up.
 
@@ -995,31 +1635,31 @@ secondary select methods.
 
 @item gnus-load-hook
 @vindex gnus-load-hook
-A hook run while Gnus is being loaded.  Note that this hook will
+A hook run while gnus is being loaded.  Note that this hook will
 normally be run just once in each Emacs session, no matter how many
-times you start Gnus.
+times you start gnus.
 
 @item gnus-before-startup-hook
 @vindex gnus-before-startup-hook
-A hook run after starting up Gnus successfully.
+A hook run after starting up gnus successfully.
 
 @item gnus-startup-hook
 @vindex gnus-startup-hook
-A hook run as the very last thing after starting up Gnus
+A hook run as the very last thing after starting up gnus
 
 @item gnus-started-hook
 @vindex gnus-started-hook
-A hook that is run as the very last thing after starting up Gnus
+A hook that is run as the very last thing after starting up gnus
 successfully.
 
-@item gnus-started-hook
-@vindex gnus-started-hook
+@item gnus-setup-news-hook
+@vindex gnus-setup-news-hook
 A hook that is run after reading the @file{.newsrc} file(s), but before
 generating the group buffer.
 
 @item gnus-check-bogus-newsgroups
 @vindex gnus-check-bogus-newsgroups
-If non-@code{nil}, Gnus will check for and delete all bogus groups at
+If non-@code{nil}, gnus will check for and delete all bogus groups at
 startup.  A @dfn{bogus group} is a group that you have in your
 @file{.newsrc} file, but doesn't exist on the news server.  Checking for
 bogus groups can take quite a while, so to save time and resources it's
@@ -1031,15 +1671,15 @@ in a while from the group buffer instead (@pxref{Group Maintenance}).
 If non-@code{nil}, the startup message won't be displayed.  That way,
 your boss might not notice as easily that you are reading news instead
 of doing your job.  Note that this variable is used before
-@file{.gnus.el} is loaded, so it should be set in @code{.emacs} instead.
+@file{~/.gnus.el} is loaded, so it should be set in @file{.emacs} instead.
 
 @item gnus-no-groups-message
 @vindex gnus-no-groups-message
-Message displayed by Gnus when no groups are available.
+Message displayed by gnus when no groups are available.
 
 @item gnus-play-startup-jingle
 @vindex gnus-play-startup-jingle
-If non-@code{nil}, play the Gnus jingle at startup.
+If non-@code{nil}, play the gnus jingle at startup.
 
 @item gnus-startup-jingle
 @vindex gnus-startup-jingle
@@ -1049,18 +1689,38 @@ default is @samp{Tuxedomoon.Jingle4.au}.
 @end table
 
 
-@node The Group Buffer
-@chapter The Group Buffer
+@node Group Buffer
+@chapter Group Buffer
 @cindex group buffer
 
+@c Alex Schroeder suggests to rearrange this as follows:
+@c
+@c <kensanata> ok, just save it for reference.  I'll go to bed in a minute.
+@c   1. Selecting a Group, 2. (new) Finding a Group, 3. Group Levels,
+@c   4. Subscription Commands, 5. Group Maneuvering, 6. Group Data,
+@c   7. Group Score, 8. Group Buffer Format
+@c <kensanata> Group Levels should have more information on levels 5 to 9.  I
+@c   suggest to split the 4th paragraph ("Gnus considers groups...") as follows:
+@c <kensanata> First, "Gnus considers groups... (default 9)."
+@c <kensanata> New, a table summarizing what levels 1 to 9 mean.
+@c <kensanata> Third, "Gnus treats subscribed ... reasons of efficiency"
+@c <kensanata> Then expand the next paragraph or add some more to it.
+@c    This short one sentence explains levels 1 and 2, therefore I understand
+@c    that I should keep important news at 3 and boring news at 4.
+@c    Say so!  Then go on to explain why I should bother with levels 6 to 9.
+@c    Maybe keep those that you don't want to read temporarily at 6,
+@c    those that you never want to read at 8, those that offend your
+@c    human rights at 9...
+
+
 The @dfn{group buffer} lists all (or parts) of the available groups.  It
-is the first buffer shown when Gnus starts, and will never be killed as
-long as Gnus is active.
+is the first buffer shown when gnus starts, and will never be killed as
+long as gnus is active.
 
 @iftex
 @iflatex
 \gnusfigure{The Group Buffer}{320}{
-\put(75,50){\epsfig{figure=tmp/group.ps,height=9cm}}
+\put(75,50){\epsfig{figure=ps/group,height=9cm}}
 \put(120,37){\makebox(0,0)[t]{Buffer name}}
 \put(120,38){\vector(1,2){10}}
 \put(40,60){\makebox(0,0)[r]{Mode line}}
@@ -1072,33 +1732,33 @@ long as Gnus is active.
 @end iftex
 
 @menu
-* Group Buffer Format::    Information listed and how you can change it.
-* Group Maneuvering::      Commands for moving in the group buffer.
-* Selecting a Group::      Actually reading news.
-* Group Data::             Changing the info for a group.
-* Subscription Commands::  Unsubscribing, killing, subscribing.
-* Group Levels::           Levels? What are those, then?
-* Group Score::            A mechanism for finding out what groups you like.
-* Marking Groups::         You can mark groups for later processing.
-* Foreign Groups::         Creating and editing groups.
-* Group Parameters::       Each group may have different parameters set.
-* Listing Groups::         Gnus can list various subsets of the groups.
-* Sorting Groups::         Re-arrange the group order.
-* Group Maintenance::      Maintaining a tidy @file{.newsrc} file.
-* Browse Foreign Server::  You can browse a server.  See what it has to offer.
-* Exiting Gnus::           Stop reading news and get some work done.
-* Group Topics::           A folding group mode divided into topics.
-* Misc Group Stuff::       Other stuff that you can to do.
+* Group Buffer Format::         Information listed and how you can change it.
+* Group Maneuvering::           Commands for moving in the group buffer.
+* Selecting a Group::           Actually reading news.
+* Subscription Commands::       Unsubscribing, killing, subscribing.
+* Group Data::                  Changing the info for a group.
+* Group Levels::                Levels? What are those, then?
+* Group Score::                 A mechanism for finding out what groups you like.
+* Marking Groups::              You can mark groups for later processing.
+* Foreign Groups::              Creating and editing groups.
+* Group Parameters::            Each group may have different parameters set.
+* Listing Groups::              Gnus can list various subsets of the groups.
+* Sorting Groups::              Re-arrange the group order.
+* Group Maintenance::           Maintaining a tidy @file{.newsrc} file.
+* Browse Foreign Server::       You can browse a server.  See what it has to offer.
+* Exiting Gnus::                Stop reading news and get some work done.
+* Group Topics::                A folding group mode divided into topics.
+* Misc Group Stuff::            Other stuff that you can to do.
 @end menu
 
 
 @node Group Buffer Format
 @section Group Buffer Format
 
-@menu 
-* Group Line Specification::       Deciding how the group buffer is to look.
-* Group Modeline Specification::   The group buffer modeline.
-* Group Highlighting::             Having nice colors in the group buffer.
+@menu
+* Group Line Specification::    Deciding how the group buffer is to look.
+* Group Mode Line Specification::  The group buffer mode line.
+* Group Highlighting::          Having nice colors in the group buffer.
 @end menu
 
 
@@ -1128,15 +1788,15 @@ You can change that format to whatever you want by fiddling with the
 @code{gnus-group-line-format} variable.  This variable works along the
 lines of a @code{format} specification, which is pretty much the same as
 a @code{printf} specifications, for those of you who use (feh!) C.
-@xref{Formatting Variables}. 
+@xref{Formatting Variables}.
 
-@samp{%M%S%5y: %(%g%)\n} is the value that produced those lines above.
+@samp{%M%S%5y:%B%(%g%)\n} is the value that produced those lines above.
 
 There should always be a colon on the line; the cursor always moves to
-the colon after performing an operation.  Nothing else is required---not
-even the group name.  All displayed text is just window dressing, and is
-never examined by Gnus.  Gnus stores all real information it needs using
-text properties.
+the colon after performing an operation.  @xref{Positioning
+Point}.  Nothing else is required---not even the group name.  All
+displayed text is just window dressing, and is never examined by Gnus.
+Gnus stores all real information it needs using text properties.
 
 (Note that if you make a really strange, wonderful, spreadsheet-like
 layout, everybody will believe you are hard at work with the accounting
@@ -1146,13 +1806,13 @@ Here's a list of all available format characters:
 
 @table @samp
 
-@item M    
+@item M
 An asterisk if the group only has marked articles.
 
 @item S
 Whether the group is subscribed.
 
-@item L    
+@item L
 Level of subscribedness.
 
 @item N
@@ -1167,10 +1827,22 @@ Number of ticked articles.
 @item R
 Number of read articles.
 
+@item U
+Number of unseen articles.
+
 @item t
 Estimated total number of articles.  (This is really @var{max-number}
 minus @var{min-number} plus 1.)
 
+Gnus uses this estimation because the @acronym{NNTP} protocol provides
+efficient access to @var{max-number} and @var{min-number} but getting
+the true unread message count is not possible efficiently.  For
+hysterical raisins, even the mail back ends, where the true number of
+unread messages might be available efficiently, use the same limited
+interface.  To remove this restriction from Gnus means that the back
+end interface has to be changed, which is not an easy job.  If you
+want to work on this, please contact the Gnus mailing list.
+
 @item y
 Number of unread, unticked, non-dormant articles.
 
@@ -1183,8 +1855,15 @@ Full group name.
 @item G
 Group name.
 
+@item C
+Group comment (@pxref{Group Parameters}) or group name if there is no
+comment element in the group parameters.
+
 @item D
-Newsgroup description.
+Newsgroup description.  You need to read the group descriptions
+before these will appear, and to do that, you either have to set
+@code{gnus-read-active-file} or use the group buffer @kbd{M-d}
+command.
 
 @item o
 @samp{m} if moderated.
@@ -1195,6 +1874,9 @@ Newsgroup description.
 @item s
 Select method.
 
+@item B
+If the summary buffer for the group is open or not.
+
 @item n
 Select from where.
 
@@ -1203,14 +1885,14 @@ A string that looks like @samp{<%s:%n>} if a foreign select method is
 used.
 
 @item P
-Indentation based on the level of the topic (@pxref{Group Topics}). 
+Indentation based on the level of the topic (@pxref{Group Topics}).
 
 @item c
 @vindex gnus-group-uncollapsed-levels
 Short (collapsed) group name.  The @code{gnus-group-uncollapsed-levels}
 variable says how many levels to leave at the end of the group name.
 The default is 1---this will mean that group names like
-@samp{gnu.emacs.gnus} will be shortened to @samp{g.emacs.gnus}.
+@samp{gnu.emacs.gnus} will be shortened to @samp{g.e.gnus}.
 
 @item m
 @vindex gnus-new-mail-mark
@@ -1218,9 +1900,12 @@ The default is 1---this will mean that group names like
 @samp{%} (@code{gnus-new-mail-mark}) if there has arrived new mail to
 the group lately.
 
+@item p
+@samp{#} (@code{gnus-process-mark}) if the group is process marked.
+
 @item d
 A string that says when you last read the group (@pxref{Group
-Timestamp}). 
+Timestamp}).
 
 @item u
 User defined specifier.  The next character in the format string should
@@ -1238,13 +1923,13 @@ if no info is available---for instance, if it is a non-activated foreign
 group, or a bogus native group.
 
 
-@node Group Modeline Specification
-@subsection Group Modeline Specification
-@cindex group modeline
+@node Group Mode Line Specification
+@subsection Group Mode Line Specification
+@cindex group mode line
 
 @vindex gnus-group-mode-line-format
 The mode line can be changed by setting
-@code{gnus-group-mode-line-format} (@pxref{Formatting Variables}).  It
+@code{gnus-group-mode-line-format} (@pxref{Mode Line Formatting}).  It
 doesn't understand that many format specifiers:
 
 @table @samp
@@ -1263,36 +1948,33 @@ The native select method.
 @vindex gnus-group-highlight
 Highlighting in the group buffer is controlled by the
 @code{gnus-group-highlight} variable.  This is an alist with elements
-that look like @var{(form . face)}.  If @var{form} evaluates to
+that look like @code{(@var{form} . @var{face})}.  If @var{form} evaluates to
 something non-@code{nil}, the @var{face} will be used on the line.
 
 Here's an example value for this variable that might look nice if the
 background is dark:
 
 @lisp
-(face-spec-set 'my-group-face-1 '((t (:foreground "Red" :bold t))))
-(face-spec-set 'my-group-face-2 '((t (:foreground "SeaGreen" :bold t))))
-(face-spec-set 'my-group-face-3 '((t (:foreground "SpringGreen" :bold t))))
-(face-spec-set 'my-group-face-4 '((t (:foreground "SteelBlue" :bold t))))
-(face-spec-set 'my-group-face-5 '((t (:foreground "SkyBlue" :bold t))))
+(cond (window-system
+       (setq custom-background-mode 'light)
+       (defface my-group-face-1
+         '((t (:foreground "Red" :bold t))) "First group face")
+       (defface my-group-face-2
+         '((t (:foreground "DarkSeaGreen4" :bold t)))
+         "Second group face")
+       (defface my-group-face-3
+         '((t (:foreground "Green4" :bold t))) "Third group face")
+       (defface my-group-face-4
+         '((t (:foreground "SteelBlue" :bold t))) "Fourth group face")
+       (defface my-group-face-5
+         '((t (:foreground "Blue" :bold t))) "Fifth group face")))
 
 (setq gnus-group-highlight
       '(((> unread 200) . my-group-face-1)
-       ((and (< level 3) (zerop unread)) . my-group-face-2)
-       ((< level 3) . my-group-face-3)
-       ((zerop unread) . my-group-face-4)
-(setq gnus-group-highlight
-      `(((> unread 200) . 
-         ,(custom-face-lookup "Red" nil nil t nil nil))
-        ((and (< level 3) (zerop unread)) . 
-         ,(custom-face-lookup "SeaGreen" nil nil t nil nil))
-        ((< level 3) . 
-         ,(custom-face-lookup "SpringGreen" nil nil t nil nil))
-        ((zerop unread) . 
-         ,(custom-face-lookup "SteelBlue" nil nil t nil nil))
-        (t . 
-         ,(custom-face-lookup "SkyBlue" nil nil t nil nil))))
-       (t . my-group-face-5)))
+        ((and (< level 3) (zerop unread)) . my-group-face-2)
+        ((< level 3) . my-group-face-3)
+        ((zerop unread) . my-group-face-4)
+        (t . my-group-face-5)))
 @end lisp
 
 Also @pxref{Faces and Fonts}.
@@ -1313,18 +1995,18 @@ Whether the group is a mail group.
 The level of the group.
 @item score
 The score of the group.
-@item ticked 
+@item ticked
 The number of ticked articles in the group.
 @item total
-The total number of articles in the group.  Or rather, MAX-NUMBER minus
-MIN-NUMBER plus one.
+The total number of articles in the group.  Or rather,
+@var{max-number} minus @var{min-number} plus one.
 @item topic
 When using the topic minor mode, this variable is bound to the current
 topic being inserted.
 @end table
 
 When the forms are @code{eval}ed, point is at the beginning of the line
-of the group in question, so you can use many of the normal Gnus
+of the group in question, so you can use many of the normal gnus
 functions for snarfing info on the group.
 
 @vindex gnus-group-update-hook
@@ -1339,7 +2021,7 @@ calls @code{gnus-group-highlight-line} by default.
 @cindex group movement
 
 All movement commands understand the numeric prefix and will behave as
-expected, hopefully. 
+expected, hopefully.
 
 @table @kbd
 
@@ -1367,17 +2049,17 @@ Go to the next group (@code{gnus-group-next-group}).
 @findex gnus-group-prev-group
 Go to the previous group (@code{gnus-group-prev-group}).
 
-@item M-p
-@kindex M-p (Group)
+@item M-n
+@kindex M-n (Group)
 @findex gnus-group-next-unread-group-same-level
 Go to the next unread group on the same (or lower) level
-(@code{gnus-group-next-unread-group-same-level}). 
+(@code{gnus-group-next-unread-group-same-level}).
 
-@item M-n
-@kindex M-n (Group)
+@item M-p
+@kindex M-p (Group)
 @findex gnus-group-prev-unread-group-same-level
 Go to the previous unread group on the same (or lower) level
-(@code{gnus-group-prev-unread-group-same-level}). 
+(@code{gnus-group-prev-unread-group-same-level}).
 @end table
 
 Three commands for jumping to groups:
@@ -1395,13 +2077,13 @@ like living groups.
 @kindex , (Group)
 @findex gnus-group-best-unread-group
 Jump to the unread group with the lowest level
-(@code{gnus-group-best-unread-group}). 
+(@code{gnus-group-best-unread-group}).
 
 @item .
 @kindex . (Group)
 @findex gnus-group-first-unread-group
 Jump to the first group with unread articles
-(@code{gnus-group-first-unread-group}).  
+(@code{gnus-group-first-unread-group}).
 @end table
 
 @vindex gnus-group-goto-unread
@@ -1423,11 +2105,19 @@ is @code{t}.
 Select the current group, switch to the summary buffer and display the
 first unread article (@code{gnus-group-read-group}).  If there are no
 unread articles in the group, or if you give a non-numerical prefix to
-this command, Gnus will offer to fetch all the old articles in this
-group from the server.  If you give a numerical prefix @var{N}, @var{N}
-determines the number of articles Gnus will fetch.  If @var{N} is
-positive, Gnus fetches the @var{N} newest articles, if @var{N} is
-negative, Gnus fetches the @var{abs(N)} oldest articles.
+this command, gnus will offer to fetch all the old articles in this
+group from the server.  If you give a numerical prefix @var{n}, @var{n}
+determines the number of articles Gnus will fetch.  If @var{n} is
+positive, Gnus fetches the @var{n} newest articles, if @var{n} is
+negative, Gnus fetches the @code{abs(@var{n})} oldest articles.
+
+Thus, @kbd{SPC} enters the group normally, @kbd{C-u SPC} offers old
+articles, @kbd{C-u 4 2 SPC} fetches the 42 newest articles, and @kbd{C-u
+- 4 2 SPC} fetches the 42 oldest ones.
+
+When you are in the group (in the Summary buffer), you can type
+@kbd{M-g} to fetch new articles, or @kbd{C-u M-g} to also show the old
+ones.
 
 @item RET
 @kindex RET (Group)
@@ -1436,7 +2126,7 @@ Select the current group and switch to the summary buffer
 (@code{gnus-group-select-group}).  Takes the same arguments as
 @code{gnus-group-read-group}---the only difference is that this command
 does not display the first unread article automatically upon group
-entry. 
+entry.
 
 @item M-RET
 @kindex M-RET (Group)
@@ -1446,7 +2136,7 @@ minimum amount of fuzz (@code{gnus-group-quick-select-group}).  No
 scoring/killing will be performed, there will be no highlights and no
 expunging.  This might be useful if you're in a real hurry and have to
 enter some humongous group.  If you give a 0 prefix to this command
-(i.e., @kbd{0 M-RET}), Gnus won't even generate the summary buffer,
+(i.e., @kbd{0 M-RET}), gnus won't even generate the summary buffer,
 which is useful if you want to toggle threading before generating the
 summary buffer (@pxref{Summary Generation Commands}).
 
@@ -1457,8 +2147,8 @@ This is yet one more command that does the same as the @kbd{RET}
 command, but this one does it without expunging and hiding dormants
 (@code{gnus-group-visible-select-group}).
 
-@item M-C-RET
-@kindex M-C-RET (Group)
+@item C-M-RET
+@kindex C-M-RET (Group)
 @findex gnus-group-select-group-ephemerally
 Finally, this command selects the current group ephemerally without
 doing any processing of its contents
@@ -1469,37 +2159,58 @@ manner will have no permanent effects.
 @end table
 
 @vindex gnus-large-newsgroup
-The @code{gnus-large-newsgroup} variable says what Gnus should consider
-to be a big group.  This is 200 by default.  If the group has more
-(unread and/or ticked) articles than this, Gnus will query the user
-before entering the group.  The user can then specify how many articles
-should be fetched from the server.  If the user specifies a negative
-number (@code{-n}), the @code{n} oldest articles will be fetched.  If it
-is positive, the @code{n} articles that have arrived most recently will
-be fetched.
+The @code{gnus-large-newsgroup} variable says what Gnus should
+consider to be a big group.  If it is @code{nil}, no groups are
+considered big.  The default value is 200.  If the group has more
+(unread and/or ticked) articles than this, gnus will query the user
+before entering the group.  The user can then specify how many
+articles should be fetched from the server.  If the user specifies a
+negative number (@var{-n}), the @var{n} oldest articles will be
+fetched.  If it is positive, the @var{n} articles that have arrived
+most recently will be fetched.
+
+@vindex gnus-large-ephemeral-newsgroup
+@code{gnus-large-ephemeral-newsgroup} is the same as
+@code{gnus-large-newsgroup}, but is only used for ephemeral
+newsgroups.
 
 @vindex gnus-select-group-hook
 @vindex gnus-auto-select-first
-@code{gnus-auto-select-first} control whether any articles are selected
+@vindex gnus-auto-select-subject
+If @code{gnus-auto-select-first} is non-@code{nil}, select an article
 automatically when entering a group with the @kbd{SPACE} command.
+Which article this is is controlled by the
+@code{gnus-auto-select-subject} variable.  Valid values for this
+variable is:
 
 @table @code
 
-@item nil
-Don't select any articles when entering the group.  Just display the
-full summary buffer.
+@item unread
+Place point on the subject line of the first unread article.
 
-@item t
-Select the first unread article when entering the group.  
+@item first
+Place point on the subject line of the first article.
+
+@item unseen
+Place point on the subject line of the first unseen article.
+
+@item unseen-or-unread
+Place point on the subject line of the first unseen article, and if
+there is no such article, place point on the subject line of the first
+unread article.
 
 @item best
-Select the most high-scored article in the group when entering the
-group. 
+Place point on the subject line of the highest-scored unread article.
+
 @end table
-        
+
+This variable can also be a function.  In that case, that function
+will be called to place point on a subject line.
+
 If you want to prevent automatic selection in some group (say, in a
-binary group with Huge articles) you can set this variable to @code{nil}
-in @code{gnus-select-group-hook}, which is called when a group is
+binary group with Huge articles) you can set the
+@code{gnus-auto-select-first} variable to @code{nil} in
+@code{gnus-select-group-hook}, which is called when a group is
 selected.
 
 
@@ -1516,7 +2227,7 @@ selected.
 @findex gnus-group-unsubscribe-current-group
 @c @icon{gnus-group-unsubscribe}
 Toggle subscription to the current group
-(@code{gnus-group-unsubscribe-current-group}).  
+(@code{gnus-group-unsubscribe-current-group}).
 
 @item S s
 @itemx U
@@ -1554,7 +2265,7 @@ kill-and-yank sequence sometimes.
 @kindex S w (Group)
 @kindex C-w (Group)
 @findex gnus-group-kill-region
-Kill all groups in the region (@code{gnus-group-kill-region}). 
+Kill all groups in the region (@code{gnus-group-kill-region}).
 
 @item S z
 @kindex S z (Group)
@@ -1570,7 +2281,7 @@ be used with some caution.  The only time where this command comes in
 really handy is when you have a @file{.newsrc} with lots of unsubscribed
 groups that you want to get rid off.  @kbd{S C-k} on level 7 will
 kill off all unsubscribed groups that do not have message numbers in the
-@file{.newsrc} file.  
+@file{.newsrc} file.
 
 @end table
 
@@ -1596,7 +2307,7 @@ the group buffer.
 @kindex C (Group)
 @findex gnus-group-catchup-current-all
 Mark all articles in this group, even the ticked ones, as read
-(@code{gnus-group-catchup-current-all}).   
+(@code{gnus-group-catchup-current-all}).
 
 @item M-c
 @kindex M-c (Group)
@@ -1607,10 +2318,10 @@ read articles (@code{gnus-group-clear-data}).
 @item M-x gnus-group-clear-data-on-native-groups
 @kindex M-x gnus-group-clear-data-on-native-groups
 @findex gnus-group-clear-data-on-native-groups
-If you have switched from one @sc{nntp} server to another, all your marks
+If you have switched from one @acronym{NNTP} server to another, all your marks
 and read ranges have become worthless.  You can use this command to
 clear out all data that you have on your native groups.  Use with
-caution. 
+caution.
 
 @end table
 
@@ -1622,11 +2333,11 @@ caution.
 
 All groups have a level of @dfn{subscribedness}.  For instance, if a
 group is on level 2, it is more subscribed than a group on level 5.  You
-can ask Gnus to just list groups on a given level or lower
+can ask gnus to just list groups on a given level or lower
 (@pxref{Listing Groups}), or to just check for new articles in groups on
 a given level or lower (@pxref{Scanning New Messages}).
 
-Remember:  The higher the level of the group, the less important it is. 
+Remember:  The higher the level of the group, the less important it is.
 
 @table @kbd
 
@@ -1657,6 +2368,27 @@ reasons of efficiency.
 It is recommended that you keep all your mail groups (if any) on quite
 low levels (e.g. 1 or 2).
 
+Maybe the following description of the default behavior of Gnus helps to
+understand what these levels are all about.  By default, Gnus shows you
+subscribed nonempty groups, but by hitting @kbd{L} you can have it show
+empty subscribed groups and unsubscribed groups, too.  Type @kbd{l} to
+go back to showing nonempty subscribed groups again.  Thus, unsubscribed
+groups are hidden, in a way.
+
+Zombie and killed groups are similar to unsubscribed groups in that they
+are hidden by default.  But they are different from subscribed and
+unsubscribed groups in that Gnus doesn't ask the news server for
+information (number of messages, number of unread messages) on zombie
+and killed groups.  Normally, you use @kbd{C-k} to kill the groups you
+aren't interested in.  If most groups are killed, Gnus is faster.
+
+Why does Gnus distinguish between zombie and killed groups?  Well, when
+a new group arrives on the server, Gnus by default makes it a zombie
+group.  This means that you are normally not bothered with new groups,
+but you can type @kbd{A z} to get a list of all new groups.  Subscribe
+the ones you like and kill the ones you don't want.  (@kbd{A k} shows a
+list of killed groups.)
+
 If you want to play with the level variables, you should show some care.
 Set them once, and don't touch them ever again.  Better yet, don't touch
 them at all unless you know exactly what you're doing.
@@ -1677,6 +2409,9 @@ will go to the next group of the same level (or lower).  This might be
 handy if you want to read the most important groups before you read the
 rest.
 
+If this variable is @code{best}, Gnus will make the next newsgroup the
+one with the best level.
+
 @vindex gnus-group-default-list-level
 All groups with a level less than or equal to
 @code{gnus-group-default-list-level} will be listed in the group buffer
@@ -1686,7 +2421,7 @@ by default.
 If @code{gnus-group-list-inactive-groups} is non-@code{nil}, non-active
 groups will be listed along with the unread groups.  This variable is
 @code{t} by default.  If it is @code{nil}, inactive groups won't be
-listed. 
+listed.
 
 @vindex gnus-group-use-permanent-levels
 If @code{gnus-group-use-permanent-levels} is non-@code{nil}, once you
@@ -1709,15 +2444,16 @@ to 5.  The default is 6.
 You would normally keep important groups on high levels, but that scheme
 is somewhat restrictive.  Don't you wish you could have Gnus sort the
 group buffer according to how often you read groups, perhaps?  Within
-reason?  
+reason?
 
-This is what @dfn{group score} is for.  You can assign a score to each
-group.  You can then sort the group buffer based on this score.
-Alternatively, you can sort on score and then level.  (Taken together,
-the level and the score is called the @dfn{rank} of the group.  A group
-that is on level 4 and has a score of 1 has a higher rank than a group
-on level 5 that has a score of 300.  (The level is the most significant
-part and the score is the least significant part.))
+This is what @dfn{group score} is for.  You can have Gnus assign a score
+to each group through the mechanism described below.  You can then sort
+the group buffer based on this score.  Alternatively, you can sort on
+score and then level.  (Taken together, the level and the score is
+called the @dfn{rank} of the group.  A group that is on level 4 and has
+a score of 1 has a higher rank than a group on level 5 that has a score
+of 300.  (The level is the most significant part and the score is the
+least significant part.))
 
 @findex gnus-summary-bubble-group
 If you want groups you read often to get higher scores than groups you
@@ -1750,7 +2486,7 @@ with the process mark and then execute the command.
 @itemx M m
 @kindex M m (Group)
 @findex gnus-group-mark-group
-Set the mark on the current group (@code{gnus-group-mark-group}). 
+Set the mark on the current group (@code{gnus-group-mark-group}).
 
 @item M-#
 @kindex M-# (Group)
@@ -1758,28 +2494,28 @@ Set the mark on the current group (@code{gnus-group-mark-group}).
 @kindex M u (Group)
 @findex gnus-group-unmark-group
 Remove the mark from the current group
-(@code{gnus-group-unmark-group}). 
+(@code{gnus-group-unmark-group}).
 
 @item M U
 @kindex M U (Group)
 @findex gnus-group-unmark-all-groups
-Remove the mark from all groups (@code{gnus-group-unmark-all-groups}). 
+Remove the mark from all groups (@code{gnus-group-unmark-all-groups}).
 
 @item M w
 @kindex M w (Group)
 @findex gnus-group-mark-region
-Mark all groups between point and mark (@code{gnus-group-mark-region}). 
+Mark all groups between point and mark (@code{gnus-group-mark-region}).
 
 @item M b
 @kindex M b (Group)
 @findex gnus-group-mark-buffer
-Mark all groups in the buffer (@code{gnus-group-mark-buffer}). 
+Mark all groups in the buffer (@code{gnus-group-mark-buffer}).
 
 @item M r
 @kindex M r (Group)
 @findex gnus-group-mark-regexp
 Mark all groups that match some regular expression
-(@code{gnus-group-mark-regexp}).  
+(@code{gnus-group-mark-regexp}).
 @end table
 
 Also @pxref{Process/Prefix}.
@@ -1809,7 +2545,13 @@ consulted.
 @cindex making groups
 Make a new group (@code{gnus-group-make-group}).  Gnus will prompt you
 for a name, a method and possibly an @dfn{address}.  For an easier way
-to subscribe to @sc{nntp} groups, @pxref{Browse Foreign Server}.
+to subscribe to @acronym{NNTP} groups (@pxref{Browse Foreign Server}).
+
+@item G M
+@kindex G M (Group)
+@findex gnus-group-read-ephemeral-group
+Make an ephemeral group (@code{gnus-group-read-ephemeral-group}).  Gnus
+will prompt you for a name, a method and an @dfn{address}.
 
 @item G r
 @kindex G r (Group)
@@ -1818,7 +2560,7 @@ to subscribe to @sc{nntp} groups, @pxref{Browse Foreign Server}.
 Rename the current group to something else
 (@code{gnus-group-rename-group}).  This is valid only on some
 groups---mail groups mostly.  This command might very well be quite slow
-on some backends.
+on some back ends.
 
 @item G c
 @kindex G c (Group)
@@ -1837,7 +2579,7 @@ group (@code{gnus-group-edit-group-method}).
 @kindex G p (Group)
 @findex gnus-group-edit-group-parameters
 Enter a buffer where you can edit the group parameters
-(@code{gnus-group-edit-group-parameters}). 
+(@code{gnus-group-edit-group-parameters}).
 
 @item G E
 @kindex G E (Group)
@@ -1852,11 +2594,11 @@ Enter a buffer where you can edit the group info
 Make a directory group (@pxref{Directory Groups}).  You will be prompted
 for a directory name (@code{gnus-group-make-directory-group}).
 
-@item G h 
+@item G h
 @kindex G h (Group)
 @cindex help group
 @findex gnus-group-make-help-group
-Make the Gnus help group (@code{gnus-group-make-help-group}).
+Make the gnus help group (@code{gnus-group-make-help-group}).
 
 @item G a
 @kindex G a (Group)
@@ -1865,7 +2607,7 @@ Make the Gnus help group (@code{gnus-group-make-help-group}).
 @findex gnus-group-make-archive-group
 @vindex gnus-group-archive-directory
 @vindex gnus-group-recent-archive-directory
-Make a Gnus archive group (@code{gnus-group-make-archive-group}).  By
+Make a gnus archive group (@code{gnus-group-make-archive-group}).  By
 default a group pointing to the most recent articles will be created
 (@code{gnus-group-recent-archive-directory}), but given a prefix, a full
 group will be created from @code{gnus-group-archive-directory}.
@@ -1884,8 +2626,8 @@ strings to match on headers (@code{gnus-group-make-kiboze-group}).
 @findex gnus-group-enter-directory
 @cindex nneething
 Read an arbitrary directory as if it were a newsgroup with the
-@code{nneething} backend (@code{gnus-group-enter-directory}).
-@xref{Anything Groups}. 
+@code{nneething} back end (@code{gnus-group-enter-directory}).
+@xref{Anything Groups}.
 
 @item G f
 @kindex G f (Group)
@@ -1895,26 +2637,45 @@ Read an arbitrary directory as if it were a newsgroup with the
 Make a group based on some file or other
 (@code{gnus-group-make-doc-group}).  If you give a prefix to this
 command, you will be prompted for a file name and a file type.
-Currently supported types are @code{babyl}, @code{mbox}, @code{digest},
-@code{mmdf}, @code{news}, @code{rnews}, @code{clari-briefs},
-@code{rfc934}, @code{rfc822-forward}, and @code{forward}.  If you run
-this command without a prefix, Gnus will guess at the file type.
-@xref{Document Groups}.
+Currently supported types are @code{mbox}, @code{babyl},
+@code{digest}, @code{news}, @code{rnews}, @code{mmdf}, @code{forward},
+@code{rfc934}, @code{rfc822-forward}, @code{mime-parts},
+@code{standard-digest}, @code{slack-digest}, @code{clari-briefs},
+@code{nsmail}, @code{outlook}, @code{oe-dbx}, and @code{mailman}.  If
+you run this command without a prefix, Gnus will guess at the file
+type.  @xref{Document Groups}.
+
+@item G u
+@kindex G u (Group)
+@vindex gnus-useful-groups
+@findex gnus-group-make-useful-group
+Create one of the groups mentioned in @code{gnus-useful-groups}
+(@code{gnus-group-make-useful-group}).
 
 @item G w
 @kindex G w (Group)
 @findex gnus-group-make-web-group
-@cindex DejaNews
-@cindex Alta Vista
-@cindex InReference
+@cindex Google
 @cindex nnweb
+@cindex gmane
 Make an ephemeral group based on a web search
 (@code{gnus-group-make-web-group}).  If you give a prefix to this
 command, make a solid group instead.  You will be prompted for the
 search engine type and the search string.  Valid search engine types
-include @code{dejanews}, @code{altavista} and @code{reference}.
+include @code{google}, @code{dejanews}, and @code{gmane}.
 @xref{Web Searches}.
 
+If you use the @code{google} search engine, you can limit the search
+to a particular group by using a match string like
+@samp{shaving group:alt.sysadmin.recovery}.
+
+@item G R
+@kindex G R (Group)
+@findex gnus-group-make-rss-group
+Make a group based on an @acronym{RSS} feed
+(@code{gnus-group-make-rss-group}).  You will be prompted for an URL.
+@xref{RSS}.
+
 @item G DEL
 @kindex G DEL (Group)
 @findex gnus-group-delete-group
@@ -1923,7 +2684,7 @@ This function will delete the current group
 actually delete all the articles in the group, and forcibly remove the
 group itself from the face of the Earth.  Use a prefix only if you are
 absolutely sure of what you are doing.  This command can't be used on
-read-only groups (like @code{nntp} group), though.
+read-only groups (like @code{nntp} groups), though.
 
 @item G V
 @kindex G V (Group)
@@ -1938,52 +2699,108 @@ Add the current group to an @code{nnvirtual} group
 (@code{gnus-group-add-to-virtual}).  Uses the process/prefix convention.
 @end table
 
-@xref{Select Methods} for more information on the various select
-methods. 
+@xref{Select Methods}, for more information on the various select
+methods.
 
 @vindex gnus-activate-foreign-newsgroups
 If @code{gnus-activate-foreign-newsgroups} is a positive number,
-Gnus will check all foreign groups with this level or lower at startup.
+gnus will check all foreign groups with this level or lower at startup.
 This might take quite a while, especially if you subscribe to lots of
-groups from different @sc{nntp} servers.
+groups from different @acronym{NNTP} servers.  Also @pxref{Group Levels};
+@code{gnus-activate-level} also affects activation of foreign
+newsgroups.
 
 
 @node Group Parameters
 @section Group Parameters
 @cindex group parameters
 
-The group parameters store information local to a particular group:
+The group parameters store information local to a particular group.
+Here's an example group parameter list:
+
+@example
+((to-address . "ding@@gnus.org")
+ (auto-expire . t))
+@end example
+
+We see that each element consists of a ``dotted pair''---the thing before
+the dot is the key, while the thing after the dot is the value.  All the
+parameters have this form @emph{except} local variable specs, which are
+not dotted pairs, but proper lists.
+
+Some parameters have correspondent customizable variables, each of which
+is an alist of regexps and values.
+
+The following group parameters can be used:
 
 @table @code
 @item to-address
 @cindex to-address
-If the group parameter list contains an element that looks like
-@code{(to-address .  "some@@where.com")}, that address will be used by
-the backend when doing followups and posts.  This is primarily useful in
-mail groups that represent closed mailing lists---mailing lists where
-it's expected that everybody that writes to the mailing list is
-subscribed to it.  Since using this parameter ensures that the mail only
-goes to the mailing list itself, it means that members won't receive two
-copies of your followups.
+Address used by when doing followups and new posts.
+
+@example
+(to-address . "some@@where.com")
+@end example
+
+This is primarily useful in mail groups that represent closed mailing
+lists---mailing lists where it's expected that everybody that writes to
+the mailing list is subscribed to it.  Since using this parameter
+ensures that the mail only goes to the mailing list itself, it means
+that members won't receive two copies of your followups.
 
 Using @code{to-address} will actually work whether the group is foreign
 or not.  Let's say there's a group on the server that is called
 @samp{fa.4ad-l}.  This is a real newsgroup, but the server has gotten
 the articles from a mail-to-news gateway.  Posting directly to this
 group is therefore impossible---you have to send mail to the mailing
-list address instead. 
+list address instead.
+
+See also @code{gnus-parameter-to-address-alist}.
 
 @item to-list
 @cindex to-list
-If the group parameter list has an element that looks like
-@code{(to-list . "some@@where.com")}, that address will be used when
-doing a @kbd{a} in that group.  It is totally ignored when doing a
-followup---except that if it is present in a news group, you'll get mail
-group semantics when doing @kbd{f}.
+Address used when doing @kbd{a} in that group.
 
-If you do an @kbd{a} command in a mail group and you don't have a
-@code{to-list} group parameter, one will be added automatically upon
-sending the message.
+@example
+(to-list . "some@@where.com")
+@end example
+
+It is totally ignored
+when doing a followup---except that if it is present in a news group,
+you'll get mail group semantics when doing @kbd{f}.
+
+If you do an @kbd{a} command in a mail group and you have neither a
+@code{to-list} group parameter nor a @code{to-address} group parameter,
+then a @code{to-list} group parameter will be added automatically upon
+sending the message if @code{gnus-add-to-list} is set to @code{t}.
+@vindex gnus-add-to-list
+
+@findex gnus-mailing-list-mode
+@cindex mail list groups
+If this variable is set, @code{gnus-mailing-list-mode} is turned on when
+entering summary buffer.
+
+See also @code{gnus-parameter-to-list-alist}.
+
+@anchor{subscribed}
+@item subscribed
+@cindex subscribed
+@cindex Mail-Followup-To
+@findex gnus-find-subscribed-addresses
+If this parameter is set to @code{t}, Gnus will consider the
+to-address and to-list parameters for this group as addresses of
+mailing lists you are subscribed to.  Giving Gnus this information is
+(only) a first step in getting it to generate correct Mail-Followup-To
+headers for your posts to these lists.  The second step is to put the
+following in your @file{.gnus.el}
+
+@lisp
+(setq message-subscribed-address-functions
+      '(gnus-find-subscribed-addresses))
+@end lisp
+
+@xref{Mailing Lists, ,Mailing Lists, message, The Message Manual}, for
+a complete treatment of available MFT support.
 
 @item visible
 @cindex visible
@@ -1994,31 +2811,37 @@ of whether it has any unread articles.
 @item broken-reply-to
 @cindex broken-reply-to
 Elements like @code{(broken-reply-to . t)} signals that @code{Reply-To}
-headers in this group are to be ignored.  This can be useful if you're
-reading a mailing list group where the listserv has inserted
-@code{Reply-To} headers that point back to the listserv itself.  This is
-broken behavior.  So there!
+headers in this group are to be ignored, and for the header to be hidden
+if @code{reply-to} is part of @code{gnus-boring-article-headers}.  This
+can be useful if you're reading a mailing list group where the listserv
+has inserted @code{Reply-To} headers that point back to the listserv
+itself.  That is broken behavior.  So there!
 
 @item to-group
 @cindex to-group
 Elements like @code{(to-group . "some.group.name")} means that all
-posts in that group will be sent to @code{some.group.name}.  
+posts in that group will be sent to @code{some.group.name}.
 
 @item newsgroup
 @cindex newsgroup
-If this symbol is present in the group parameter list, Gnus will treat
-all responses as if they were responses to news articles.  This can be
-useful if you have a mail group that's really a mirror of a news group. 
+If you have @code{(newsgroup . t)} in the group parameter list, gnus
+will treat all responses as if they were responses to news articles.
+This can be useful if you have a mail group that's really a mirror of a
+news group.
 
 @item gcc-self
 @cindex gcc-self
-If this symbol is present in the group parameter list and set to
-@code{t}, newly composed messages will be @code{Gcc}'d to the current
-group. If it is present and set to @code{none}, no @code{Gcc:} header
-will be generated, if it is present and a string, this string will be
-inserted literally as a @code{gcc} header (this symbol takes precedence
-over any default @code{Gcc} rules as described later).  @xref{Archived
-Messages}
+If @code{(gcc-self . t)} is present in the group parameter list, newly
+composed messages will be @code{Gcc}'d to the current group.  If
+@code{(gcc-self . none)} is present, no @code{Gcc:} header will be
+generated, if @code{(gcc-self . "string")} is present, this string will
+be inserted literally as a @code{gcc} header.  This parameter takes
+precedence over any default @code{Gcc} rules as described later
+(@pxref{Archived Messages}).
+
+@strong{Caveat}: Adding @code{(gcc-self . t)} to the parameter list of
+@code{nntp} groups (or the like) isn't valid.  An @code{nntp} server
+doesn't accept articles.
 
 @item auto-expire
 @cindex auto-expire
@@ -2026,6 +2849,8 @@ If the group parameter has an element that looks like @code{(auto-expire
 . t)}, all articles read will be marked as expirable.  For an
 alternative approach, @pxref{Expiring Mail}.
 
+See also @code{gnus-auto-expirable-newsgroups}.
+
 @item total-expire
 @cindex total-expire
 If the group parameter has an element that looks like
@@ -2034,20 +2859,28 @@ expiry process, even if they are not marked as expirable.  Use with
 caution.  Unread, ticked and dormant articles are not eligible for
 expiry.
 
+See also @code{gnus-total-expirable-newsgroups}.
+
 @item expiry-wait
 @cindex expiry-wait
 @vindex nnmail-expiry-wait-function
-If the group parameter has an element that looks like @code{(expiry-wait
-. 10)}, this value will override any @code{nnmail-expiry-wait} and
-@code{nnmail-expiry-wait-function} when expiring expirable messages.
-The value can either be a number of days (not necessarily an integer) or
-the symbols @code{never} or @code{immediate}.
+If the group parameter has an element that looks like
+@code{(expiry-wait . 10)}, this value will override any
+@code{nnmail-expiry-wait} and @code{nnmail-expiry-wait-function}
+(@pxref{Expiring Mail}) when expiring expirable messages.  The value
+can either be a number of days (not necessarily an integer) or the
+symbols @code{never} or @code{immediate}.
+
+@item expiry-target
+@cindex expiry-target
+Where expired messages end up.  This parameter overrides
+@code{nnmail-expiry-target}.
 
 @item score-file
 @cindex score file group parameter
 Elements that look like @code{(score-file . "file")} will make
-@file{file} into the current adaptive score file for the group in
-question.  All adaptive score entries will be put into this file.
+@file{file} into the current score file for the group in question.  All
+interactive score entries will be put into this file.
 
 @item adapt-file
 @cindex adapt file group parameter
@@ -2056,12 +2889,14 @@ Elements that look like @code{(adapt-file . "file")} will make
 All adaptive score entries will be put into this file.
 
 @item admin-address
+@cindex admin-address
 When unsubscribing from a mailing list you should never send the
 unsubscription notice to the mailing list itself.  Instead, you'd send
 messages to the administrative address.  This parameter allows you to
 put the admin address somewhere convenient.
 
 @item display
+@cindex display
 Elements that look like @code{(display . MODE)} say which articles to
 display on entering the group.  Valid values are:
 
@@ -2069,18 +2904,126 @@ display on entering the group.  Valid values are:
 @item all
 Display all articles, both read and unread.
 
+@item an integer
+Display the last @var{integer} articles in the group.  This is the same as
+entering the group with @kbd{C-u @var{integer}}.
+
 @item default
 Display the default visible articles, which normally includes unread and
 ticked articles.
+
+@item an array
+Display articles that satisfy a predicate.
+
+Here are some examples:
+
+@table @code
+@item [unread]
+Display only unread articles.
+
+@item [not expire]
+Display everything except expirable articles.
+
+@item [and (not reply) (not expire)]
+Display everything except expirable and articles you've already
+responded to.
+@end table
+
+The available operators are @code{not}, @code{and} and @code{or}.
+Predicates include @code{tick}, @code{unsend}, @code{undownload},
+@code{unread}, @code{dormant}, @code{expire}, @code{reply},
+@code{killed}, @code{bookmark}, @code{score}, @code{save},
+@code{cache}, @code{forward}, @code{unseen} and @code{recent}.
+
 @end table
 
+The @code{display} parameter works by limiting the summary buffer to
+the subset specified.  You can pop the limit by using the @kbd{/ w}
+command (@pxref{Limiting}).
+
 @item comment
-Elements that look like @code{(comment . "This is a comment")}
-are arbitrary comments on the group.  They are currently ignored by
-Gnus, but provide a place for you to store information on particular
-groups. 
+@cindex comment
+Elements that look like @code{(comment . "This is a comment")} are
+arbitrary comments on the group.  You can display comments in the
+group line (@pxref{Group Line Specification}).
+
+@item charset
+@cindex charset
+Elements that look like @code{(charset . iso-8859-1)} will make
+@code{iso-8859-1} the default charset; that is, the charset that will be
+used for all articles that do not specify a charset.
+
+See also @code{gnus-group-charset-alist}.
+
+@item ignored-charsets
+@cindex ignored-charset
+Elements that look like @code{(ignored-charsets x-unknown iso-8859-1)}
+will make @code{iso-8859-1} and @code{x-unknown} ignored; that is, the
+default charset will be used for decoding articles.
+
+See also @code{gnus-group-ignored-charsets-alist}.
+
+@item posting-style
+@cindex posting-style
+You can store additional posting style information for this group
+here (@pxref{Posting Styles}).  The format is that of an entry in the
+@code{gnus-posting-styles} alist, except that there's no regexp matching
+the group name (of course).  Style elements in this group parameter will
+take precedence over the ones found in @code{gnus-posting-styles}.
+
+For instance, if you want a funky name and signature in this group only,
+instead of hacking @code{gnus-posting-styles}, you could put something
+like this in the group parameters:
+
+@example
+(posting-style
+  (name "Funky Name")
+  ("X-My-Header" "Funky Value")
+  (signature "Funky Signature"))
+@end example
+
+@item post-method
+@cindex post-method
+If it is set, the value is used as the method for posting message
+instead of @code{gnus-post-method}.
+
+@item banner
+@cindex banner
+An item like @code{(banner . @var{regexp})} causes any part of an article
+that matches the regular expression @var{regexp} to be stripped.  Instead of
+@var{regexp}, you can also use the symbol @code{signature} which strips the
+last signature or any of the elements of the alist
+@code{gnus-article-banner-alist}.
+
+@item sieve
+@cindex sieve
+This parameter contains a Sieve test that should match incoming mail
+that should be placed in this group.  From this group parameter, a
+Sieve @samp{IF} control structure is generated, having the test as the
+condition and @samp{fileinto "group.name";} as the body.
+
+For example, if the @samp{INBOX.list.sieve} group has the @code{(sieve
+address "sender" "sieve-admin@@extundo.com")} group parameter, when
+translating the group parameter into a Sieve script (@pxref{Sieve
+Commands}) the following Sieve code is generated:
+
+@example
+if address \"sender\" \"sieve-admin@@extundo.com\" @{
+        fileinto \"INBOX.list.sieve\";
+@}
+@end example
 
-@item @var{(variable form)}
+The Sieve language is described in RFC 3028.  @xref{Top, Emacs Sieve,
+Top, sieve, Emacs Sieve}.
+
+@item (agent parameters)
+If the agent has been enabled, you can set any of the its parameters
+to control the behavior of the agent in individual groups. See Agent
+Parameters in @ref{Category Syntax}.  Most users will choose to set
+agent parameters in either an agent category or group topic to
+minimize the configuration effort.
+
+@item (@var{variable} @var{form})
 You can use the group parameters to set variables local to the group you
 are entering.  If you want to turn threading off in @samp{news.answers},
 you could put @code{(gnus-show-threads nil)} in the group parameters of
@@ -2088,6 +3031,32 @@ that group.  @code{gnus-show-threads} will be made into a local variable
 in the summary buffer you enter, and the form @code{nil} will be
 @code{eval}ed there.
 
+Note that this feature sets the variable locally to the summary buffer.
+But some variables are evaluated in the article buffer, or in the
+message buffer (of a reply or followup or otherwise newly created
+message).  As a workaround, it might help to add the variable in
+question to @code{gnus-newsgroup-variables}.  @xref{Various Summary
+Stuff}.  So if you want to set @code{message-from-style} via the group
+parameters, then you may need the following statement elsewhere in your
+@file{~/.gnus} file:
+
+@lisp
+(add-to-list 'gnus-newsgroup-variables 'message-from-style)
+@end lisp
+
+@vindex gnus-list-identifiers
+A use for this feature is to remove a mailing list identifier tag in
+the subject fields of articles.  E.g. if the news group
+
+@example
+nntp+news.gnus.org:gmane.text.docbook.apps
+@end example
+
+has the tag @samp{DOC-BOOK-APPS:} in the subject of all articles, this
+tag can be removed from the article subjects in the summary buffer for
+the group by putting @code{(gnus-list-identifiers "DOCBOOK-APPS:")}
+into the group parameters for the group.
+
 This can also be used as a group-specific hook function, if you'd like.
 If you want to hear a beep when you enter a group, you could put
 something like @code{(dummy-variable (ding))} in the parameters of that
@@ -2096,16 +3065,40 @@ group.  @code{dummy-variable} will be set to the result of the
 
 @end table
 
-Use the @kbd{G p} command to edit group parameters of a group.
+Use the @kbd{G p} or the @kbd{G c} command to edit group parameters of a
+group.  (@kbd{G p} presents you with a Lisp-based interface, @kbd{G c}
+presents you with a Customize-like interface.  The latter helps avoid
+silly Lisp errors.)  You might also be interested in reading about topic
+parameters (@pxref{Topic Parameters}).
 
-@pxref{Topic Parameters}.
+@vindex gnus-parameters
+Group parameters can be set via the @code{gnus-parameters} variable too.
+But some variables, such as @code{visible}, have no effect.  For
+example:
 
-Here's an example group parameter list:
+@lisp
+(setq gnus-parameters
+      '(("mail\\..*"
+         (gnus-show-threads nil)
+         (gnus-use-scoring nil)
+         (gnus-summary-line-format
+          "%U%R%z%I%(%[%d:%ub%-23,23f%]%) %s\n")
+         (gcc-self . t)
+         (display . all))
+
+        ("^nnimap:\\(foo.bar\\)$"
+         (to-group . "\\1"))
+
+        ("mail\\.me"
+         (gnus-use-scoring  t))
+
+        ("list\\..*"
+         (total-expire . t)
+         (broken-reply-to . t))))
+@end lisp
 
-@example
-((to-address . "ding@@gnus.org")
- (auto-expiry . t))
-@end example
+String value of parameters will be subjected to regexp substitution, as
+the @code{to-group} example shows.
 
 
 @node Listing Groups
@@ -2124,7 +3117,7 @@ These commands all list various slices of the groups available.
 List all groups that have unread articles
 (@code{gnus-group-list-groups}).  If the numeric prefix is used, this
 command will list only groups of level ARG and lower.  By default, it
-only lists groups of level five (i. e.,
+only lists groups of level five (i.e.,
 @code{gnus-group-default-list-level}) or lower (i.e., just subscribed
 groups).
 
@@ -2163,7 +3156,7 @@ List all zombie groups (@code{gnus-group-list-zombies}).
 @kindex A m (Group)
 @findex gnus-group-list-matching
 List all unread, subscribed groups with names that match a regexp
-(@code{gnus-group-list-matching}). 
+(@code{gnus-group-list-matching}).
 
 @item A M
 @kindex A M (Group)
@@ -2193,6 +3186,32 @@ List all groups that have names that match a regexp
 List all groups that have names or descriptions that match a regexp
 (@code{gnus-group-description-apropos}).
 
+@item A c
+@kindex A c (Group)
+@findex gnus-group-list-cached
+List all groups with cached articles (@code{gnus-group-list-cached}).
+
+@item A ?
+@kindex A ? (Group)
+@findex gnus-group-list-dormant
+List all groups with dormant articles (@code{gnus-group-list-dormant}).
+
+@item A /
+@kindex A / (Group)
+@findex gnus-group-list-limit
+List groups limited within the current selection
+(@code{gnus-group-list-limit}).
+
+@item A f
+@kindex A f (Group)
+@findex gnus-group-list-flush
+Flush groups from the current selection (@code{gnus-group-list-flush}).
+
+@item A p
+@kindex A p (Group)
+@findex gnus-group-list-plus
+List groups plus the current selection (@code{gnus-group-list-plus}).
+
 @end table
 
 @vindex gnus-permanently-visible-groups
@@ -2219,7 +3238,7 @@ groups.  It is @code{t} by default.
 The @kbd{C-c C-s} (@code{gnus-group-sort-groups}) command sorts the
 group buffer according to the function(s) given by the
 @code{gnus-group-sort-function} variable.  Available sorting functions
-include: 
+include:
 
 @table @code
 
@@ -2252,6 +3271,10 @@ Sort by number of unread articles.
 @findex gnus-group-sort-by-method
 Sort alphabetically on the select method.
 
+@item gnus-group-sort-by-server
+@findex gnus-group-sort-by-server
+Sort alphabetically on the Gnus server name.
+
 
 @end table
 
@@ -2268,7 +3291,7 @@ some sorting criteria:
 @kindex G S a (Group)
 @findex gnus-group-sort-groups-by-alphabet
 Sort the group buffer alphabetically by group name
-(@code{gnus-group-sort-groups-by-alphabet}). 
+(@code{gnus-group-sort-groups-by-alphabet}).
 
 @item G S u
 @kindex G S u (Group)
@@ -2280,7 +3303,7 @@ Sort the group buffer by the number of unread articles
 @kindex G S l (Group)
 @findex gnus-group-sort-groups-by-level
 Sort the group buffer by group level
-(@code{gnus-group-sort-groups-by-level}). 
+(@code{gnus-group-sort-groups-by-level}).
 
 @item G S v
 @kindex G S v (Group)
@@ -2297,12 +3320,22 @@ Sort the group buffer by group rank
 @item G S m
 @kindex G S m (Group)
 @findex gnus-group-sort-groups-by-method
-Sort the group buffer alphabetically by backend name
-(@code{gnus-group-sort-groups-by-method}). 
+Sort the group buffer alphabetically by back end name@*
+(@code{gnus-group-sort-groups-by-method}).
+
+@item G S n
+@kindex G S n (Group)
+@findex gnus-group-sort-groups-by-real-name
+Sort the group buffer alphabetically by real (unprefixed) group name
+(@code{gnus-group-sort-groups-by-real-name}).
 
 @end table
 
-When given a prefix, all these commands will sort in reverse order. 
+All the commands below obey the process/prefix convention
+(@pxref{Process/Prefix}).
+
+When given a symbolic prefix (@pxref{Symbolic Prefixes}), all these
+commands will sort in reverse order.
 
 You can also sort a subset of the groups:
 
@@ -2310,41 +3343,54 @@ You can also sort a subset of the groups:
 @item G P a
 @kindex G P a (Group)
 @findex gnus-group-sort-selected-groups-by-alphabet
-Sort the process/prefixed groups in the group buffer alphabetically by
-group name (@code{gnus-group-sort-selected-groups-by-alphabet}).
+Sort the groups alphabetically by group name
+(@code{gnus-group-sort-selected-groups-by-alphabet}).
 
 @item G P u
 @kindex G P u (Group)
 @findex gnus-group-sort-selected-groups-by-unread
-Sort the process/prefixed groups in the group buffer by the number of
-unread articles (@code{gnus-group-sort-selected-groups-by-unread}).
+Sort the groups by the number of unread articles
+(@code{gnus-group-sort-selected-groups-by-unread}).
 
 @item G P l
 @kindex G P l (Group)
 @findex gnus-group-sort-selected-groups-by-level
-Sort the process/prefixed groups in the group buffer by group level
+Sort the groups by group level
 (@code{gnus-group-sort-selected-groups-by-level}).
 
 @item G P v
 @kindex G P v (Group)
 @findex gnus-group-sort-selected-groups-by-score
-Sort the process/prefixed groups in the group buffer by group score
+Sort the groups by group score
 (@code{gnus-group-sort-selected-groups-by-score}).  @xref{Group Score}.
 
 @item G P r
 @kindex G P r (Group)
 @findex gnus-group-sort-selected-groups-by-rank
-Sort the process/prefixed groups in the group buffer by group rank
+Sort the groups by group rank
 (@code{gnus-group-sort-selected-groups-by-rank}).  @xref{Group Score}.
 
 @item G P m
 @kindex G P m (Group)
 @findex gnus-group-sort-selected-groups-by-method
-Sort the process/prefixed groups in the group buffer alphabetically by
-backend name (@code{gnus-group-sort-selected-groups-by-method}).
+Sort the groups alphabetically by back end name@*
+(@code{gnus-group-sort-selected-groups-by-method}).
+
+@item G P n
+@kindex G P n (Group)
+@findex gnus-group-sort-selected-groups-by-real-name
+Sort the groups alphabetically by real (unprefixed) group name
+(@code{gnus-group-sort-selected-groups-by-real-name}).
+
+@item G P s
+@kindex G P s (Group)
+@findex gnus-group-sort-selected-groups
+Sort the groups according to @code{gnus-group-sort-function}.
 
 @end table
 
+And finally, note that you can use @kbd{C-k} and @kbd{C-y} to manually
+move groups around.
 
 
 @node Group Maintenance
@@ -2362,19 +3408,23 @@ Find bogus groups and delete them
 @kindex F (Group)
 @findex gnus-group-find-new-groups
 Find new groups and process them (@code{gnus-group-find-new-groups}).
-If given a prefix, use the @code{ask-server} method to query the server
-for new groups.
+With 1 @kbd{C-u}, use the @code{ask-server} method to query the server
+for new groups.  With 2 @kbd{C-u}'s, use most complete method possible
+to query the server for new groups, and subscribe the new groups as
+zombies.
 
 @item C-c C-x
 @kindex C-c C-x (Group)
 @findex gnus-group-expire-articles
 Run all expirable articles in the current group through the expiry
-process (if any) (@code{gnus-group-expire-articles}).
+process (if any) (@code{gnus-group-expire-articles}).  That is, delete
+all expirable articles in the group that have been around for a while.
+(@pxref{Expiring Mail}).
 
-@item C-c M-C-x
-@kindex C-c M-C-x (Group)
+@item C-c C-M-x
+@kindex C-c C-M-x (Group)
 @findex gnus-group-expire-all-groups
-Run all articles in all groups through the expiry process
+Run all expirable articles in all groups through the expiry process
 (@code{gnus-group-expire-all-groups}).
 
 @end table
@@ -2416,18 +3466,18 @@ Go to the previous group (@code{gnus-group-prev-group}).
 @kindex SPACE (Browse)
 @findex gnus-browse-read-group
 Enter the current group and display the first article
-(@code{gnus-browse-read-group}). 
+(@code{gnus-browse-read-group}).
 
 @item RET
 @kindex RET (Browse)
 @findex gnus-browse-select-group
-Enter the current group (@code{gnus-browse-select-group}). 
+Enter the current group (@code{gnus-browse-select-group}).
 
 @item u
 @kindex u (Browse)
 @findex gnus-browse-unsubscribe-current-group
 Unsubscribe to the current group, or, as will be the case here,
-subscribe to it (@code{gnus-browse-unsubscribe-current-group}). 
+subscribe to it (@code{gnus-browse-unsubscribe-current-group}).
 
 @item l
 @itemx q
@@ -2436,6 +3486,11 @@ subscribe to it (@code{gnus-browse-unsubscribe-current-group}).
 @findex gnus-browse-exit
 Exit browse mode (@code{gnus-browse-exit}).
 
+@item d
+@kindex d (Browse)
+@findex gnus-browse-describe-group
+Describe the current group (@code{gnus-browse-describe-group}).
+
 @item ?
 @kindex ? (Browse)
 @findex gnus-browse-describe-briefly
@@ -2445,16 +3500,16 @@ there) (@code{gnus-browse-describe-briefly}).
 
 
 @node Exiting Gnus
-@section Exiting Gnus
-@cindex exiting Gnus
+@section Exiting gnus
+@cindex exiting gnus
 
-Yes, Gnus is ex(c)iting.
+Yes, gnus is ex(c)iting.
 
 @table @kbd
 @item z
 @kindex z (Group)
 @findex gnus-group-suspend
-Suspend Gnus (@code{gnus-group-suspend}).  This doesn't really exit Gnus,
+Suspend gnus (@code{gnus-group-suspend}).  This doesn't really exit gnus,
 but it kills all buffers except the Group buffer.  I'm not sure why this
 is a gain, but then who am I to judge?
 
@@ -2462,27 +3517,22 @@ is a gain, but then who am I to judge?
 @kindex q (Group)
 @findex gnus-group-exit
 @c @icon{gnus-group-exit}
-Quit Gnus (@code{gnus-group-exit}).
+Quit gnus (@code{gnus-group-exit}).
 
 @item Q
 @kindex Q (Group)
 @findex gnus-group-quit
-Quit Gnus without saving the @file{.newsrc} files (@code{gnus-group-quit}).
+Quit gnus without saving the @file{.newsrc} files (@code{gnus-group-quit}).
 The dribble file will be saved, though (@pxref{Auto Save}).
 @end table
 
 @vindex gnus-exit-gnus-hook
 @vindex gnus-suspend-gnus-hook
-@code{gnus-suspend-gnus-hook} is called when you suspend Gnus and
-@code{gnus-exit-gnus-hook} is called when you quit Gnus, while
+@vindex gnus-after-exiting-gnus-hook
+@code{gnus-suspend-gnus-hook} is called when you suspend gnus and
+@code{gnus-exit-gnus-hook} is called when you quit gnus, while
 @code{gnus-after-exiting-gnus-hook} is called as the final item when
-exiting Gnus.
-
-@findex gnus-unload
-@cindex unloading
-If you wish to completely unload Gnus and all its adherents, you can use
-the @code{gnus-unload} command.  This command is also very handy when
-trying to customize meta-variables.
+exiting gnus.
 
 Note:
 
@@ -2508,7 +3558,7 @@ groups or the sex groups---or both!  Go wild!
 @iftex
 @iflatex
 \gnusfigure{Group Topics}{400}{
-\put(75,50){\epsfig{figure=tmp/group-topic.ps,height=9cm}}
+\put(75,50){\epsfig{figure=ps/group-topic,height=9cm}}
 }
 @end iflatex
 @end iftex
@@ -2535,84 +3585,124 @@ To get this @emph{fab} functionality you simply turn on (ooh!) the
 is a toggling command.)
 
 Go ahead, just try it.  I'll still be here when you get back.  La de
-dum...  Nice tune, that...  la la la...  What, you're back? Yes, and now
-press @kbd{l}.  There.  All your groups are now listed under
-@samp{misc}.  Doesn't that make you feel all warm and fuzzy?  Hot and
-bothered?
+dum@dots{} Nice tune, that@dots{} la la la@dots{} What, you're back?
+Yes, and now press @kbd{l}.  There.  All your groups are now listed
+under @samp{misc}.  Doesn't that make you feel all warm and fuzzy?
+Hot and bothered?
 
 If you want this permanently enabled, you should add that minor mode to
-the hook for the group mode:
+the hook for the group mode.  Put the following line in your
+@file{~/.gnus.el} file:
 
 @lisp
 (add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
 @end lisp
 
-@menu 
-* Topic Variables::    How to customize the topics the Lisp Way.
-* Topic Commands::     Interactive E-Z commands.
-* Topic Sorting::      Sorting each topic individually.
-* Topic Topology::     A map of the world.
-* Topic Parameters::   Parameters that apply to all groups in a topic.
+@menu
+* Topic Commands::              Interactive E-Z commands.
+* Topic Variables::             How to customize the topics the Lisp Way.
+* Topic Sorting::               Sorting each topic individually.
+* Topic Topology::              A map of the world.
+* Topic Parameters::            Parameters that apply to all groups in a topic.
 @end menu
 
 
-@node Topic Variables
-@subsection Topic Variables
-@cindex topic variables
+@node Topic Commands
+@subsection Topic Commands
+@cindex topic commands
 
-Now, if you select a topic, it will fold/unfold that topic, which is
-really neat, I think.
+When the topic minor mode is turned on, a new @kbd{T} submap will be
+available.  In addition, a few of the standard keys change their
+definitions slightly.
 
-@vindex gnus-topic-line-format
-The topic lines themselves are created according to the
-@code{gnus-topic-line-format} variable (@pxref{Formatting Variables}).
-Valid elements are:
+In general, the following kinds of operations are possible on topics.
+First of all, you want to create topics.  Secondly, you want to put
+groups in topics and to move them around until you have an order you
+like.  The third kind of operation is to show/hide parts of the whole
+shebang.  You might want to hide a topic including its subtopics and
+groups, to get a better overview of the other groups.
+
+Here is a list of the basic keys that you might need to set up topics
+the way you like.
+
+@table @kbd
+
+@item T n
+@kindex T n (Topic)
+@findex gnus-topic-create-topic
+Prompt for a new topic name and create it
+(@code{gnus-topic-create-topic}).
+
+@item T TAB
+@itemx TAB
+@kindex T TAB (Topic)
+@kindex TAB (Topic)
+@findex gnus-topic-indent
+``Indent'' the current topic so that it becomes a sub-topic of the
+previous topic (@code{gnus-topic-indent}).  If given a prefix,
+``un-indent'' the topic instead.
+
+@item M-TAB
+@kindex M-TAB (Topic)
+@findex gnus-topic-unindent
+``Un-indent'' the current topic so that it becomes a sub-topic of the
+parent of its current parent (@code{gnus-topic-unindent}).
 
-@table @samp
-@item i
-Indentation.
-@item n
-Topic name.
-@item v
-Visibility.
-@item l
-Level.
-@item g
-Number of groups in the topic.
-@item a
-Number of unread articles in the topic.
-@item A 
-Number of unread articles in the topic and all its subtopics. 
 @end table
 
-@vindex gnus-topic-indent-level
-Each sub-topic (and the groups in the sub-topics) will be indented with
-@code{gnus-topic-indent-level} times the topic level number of spaces.
-The default is 2.
+The following two keys can be used to move groups and topics around.
+They work like the well-known cut and paste.  @kbd{C-k} is like cut and
+@kbd{C-y} is like paste.  Of course, this being Emacs, we use the terms
+kill and yank rather than cut and paste.
 
-@vindex gnus-topic-mode-hook
-@code{gnus-topic-mode-hook} is called in topic minor mode buffers. 
+@table @kbd
 
-@vindex gnus-topic-display-empty-topics
-The @code{gnus-topic-display-empty-topics} says whether to display even
-topics that have no unread articles in them.  The default is @code{t}.
+@item C-k
+@kindex C-k (Topic)
+@findex gnus-topic-kill-group
+Kill a group or topic (@code{gnus-topic-kill-group}).  All groups in the
+topic will be removed along with the topic.
 
+@item C-y
+@kindex C-y (Topic)
+@findex gnus-topic-yank-group
+Yank the previously killed group or topic
+(@code{gnus-topic-yank-group}).  Note that all topics will be yanked
+before all groups.
 
-@node Topic Commands
-@subsection Topic Commands
-@cindex topic commands
+So, to move a topic to the beginning of the list of topics, just hit
+@kbd{C-k} on it.  This is like the ``cut'' part of cut and paste.  Then,
+move the cursor to the beginning of the buffer (just below the ``Gnus''
+topic) and hit @kbd{C-y}.  This is like the ``paste'' part of cut and
+paste.  Like I said -- E-Z.
 
-When the topic minor mode is turned on, a new @kbd{T} submap will be
-available.  In addition, a few of the standard keys change their
-definitions slightly.
+You can use @kbd{C-k} and @kbd{C-y} on groups as well as on topics.  So
+you can move topics around as well as groups.
+
+@end table
+
+After setting up the topics the way you like them, you might wish to
+hide a topic, or to show it again.  That's why we have the following
+key.
 
 @table @kbd
 
-@item T n
-@kindex T n (Topic)
-@findex gnus-topic-create-topic
-Prompt for a new topic name and create it 
-(@code{gnus-topic-create-topic}). 
+@item RET
+@kindex RET (Topic)
+@findex gnus-topic-select-group
+@itemx SPACE
+Either select a group or fold a topic (@code{gnus-topic-select-group}).
+When you perform this command on a group, you'll enter the group, as
+usual.  When done on a topic line, the topic will be folded (if it was
+visible) or unfolded (if it was folded already).  So it's basically a
+toggling command on topics.  In addition, if you give a numerical
+prefix, group on that level (and lower) will be displayed.
+
+@end table
+
+Now for a list of other commands, in no particular order.
+
+@table @kbd
 
 @item T m
 @kindex T m (Topic)
@@ -2621,6 +3711,11 @@ Move the current group to some other topic
 (@code{gnus-topic-move-group}).  This command uses the process/prefix
 convention (@pxref{Process/Prefix}).
 
+@item T j
+@kindex T j (Topic)
+@findex gnus-topic-jump-to-topic
+Go to a topic (@code{gnus-topic-jump-to-topic}).
+
 @item T c
 @kindex T c (Topic)
 @findex gnus-topic-copy-group
@@ -2628,10 +3723,29 @@ Copy the current group to some other topic
 (@code{gnus-topic-copy-group}).  This command uses the process/prefix
 convention (@pxref{Process/Prefix}).
 
+@item T h
+@kindex T h (Topic)
+@findex gnus-topic-hide-topic
+Hide the current topic (@code{gnus-topic-hide-topic}).  If given
+a prefix, hide the topic permanently.
+
+@item T s
+@kindex T s (Topic)
+@findex gnus-topic-show-topic
+Show the current topic (@code{gnus-topic-show-topic}).  If given
+a prefix, show the topic permanently.
+
 @item T D
 @kindex T D (Topic)
 @findex gnus-topic-remove-group
 Remove a group from the current topic (@code{gnus-topic-remove-group}).
+This command is mainly useful if you have the same group in several
+topics and wish to remove it from one of the topics.  You may also
+remove a group from all topics, but in that case, Gnus will add it to
+the root topic the next time you start Gnus.  In fact, all new groups
+(which, naturally, don't belong to any topic) will show up in the root
+topic.
+
 This command uses the process/prefix convention
 (@pxref{Process/Prefix}).
 
@@ -2639,79 +3753,67 @@ This command uses the process/prefix convention
 @kindex T M (Topic)
 @findex gnus-topic-move-matching
 Move all groups that match some regular expression to a topic
-(@code{gnus-topic-move-matching}). 
+(@code{gnus-topic-move-matching}).
 
 @item T C
 @kindex T C (Topic)
 @findex gnus-topic-copy-matching
 Copy all groups that match some regular expression to a topic
-(@code{gnus-topic-copy-matching}). 
+(@code{gnus-topic-copy-matching}).
 
-@item T h
-@kindex T h (Topic)
+@item T H
+@kindex T H (Topic)
 @findex gnus-topic-toggle-display-empty-topics
 Toggle hiding empty topics
-(@code{gnus-topic-toggle-display-empty-topics}). 
+(@code{gnus-topic-toggle-display-empty-topics}).
 
 @item T #
 @kindex T # (Topic)
 @findex gnus-topic-mark-topic
 Mark all groups in the current topic with the process mark
-(@code{gnus-topic-mark-topic}). 
+(@code{gnus-topic-mark-topic}).  This command works recursively on
+sub-topics unless given a prefix.
 
 @item T M-#
 @kindex T M-# (Topic)
 @findex gnus-topic-unmark-topic
 Remove the process mark from all groups in the current topic
-(@code{gnus-topic-unmark-topic}). 
-
-@item RET
-@kindex RET (Topic)
-@findex gnus-topic-select-group
-@itemx SPACE
-Either select a group or fold a topic (@code{gnus-topic-select-group}).
-When you perform this command on a group, you'll enter the group, as
-usual.  When done on a topic line, the topic will be folded (if it was
-visible) or unfolded (if it was folded already).  So it's basically a
-toggling command on topics.  In addition, if you give a numerical
-prefix, group on that level (and lower) will be displayed.
-
-@item T TAB
-@kindex T TAB (Topic)
-@findex gnus-topic-indent
-``Indent'' the current topic so that it becomes a sub-topic of the
-previous topic (@code{gnus-topic-indent}).  If given a prefix,
-``un-indent'' the topic instead.
-
-@item C-k
-@kindex C-k (Topic)
-@findex gnus-topic-kill-group
-Kill a group or topic (@code{gnus-topic-kill-group}).  All groups in the
-topic will be removed along with the topic.
+(@code{gnus-topic-unmark-topic}).  This command works recursively on
+sub-topics unless given a prefix.
 
-@item C-y
-@kindex C-y (Topic)
-@findex gnus-topic-yank-group
-Yank the previously killed group or topic
-(@code{gnus-topic-yank-group}).  Note that all topics will be yanked
-before all groups. 
+@item C-c C-x
+@kindex C-c C-x (Topic)
+@findex gnus-topic-expire-articles
+Run all expirable articles in the current group or topic through the
+expiry process (if any)
+(@code{gnus-topic-expire-articles}).  (@pxref{Expiring Mail}).
 
 @item T r
 @kindex T r (Topic)
 @findex gnus-topic-rename
-Rename a topic (@code{gnus-topic-rename}). 
+Rename a topic (@code{gnus-topic-rename}).
 
 @item T DEL
 @kindex T DEL (Topic)
 @findex gnus-topic-delete
-Delete an empty topic (@code{gnus-topic-delete}). 
+Delete an empty topic (@code{gnus-topic-delete}).
 
 @item A T
 @kindex A T (Topic)
 @findex gnus-topic-list-active
-List all groups that Gnus knows about in a topics-ified way
+List all groups that gnus knows about in a topics-ified way
 (@code{gnus-topic-list-active}).
 
+@item T M-n
+@kindex T M-n (Topic)
+@findex gnus-topic-goto-next-topic
+Go to the next topic (@code{gnus-topic-goto-next-topic}).
+
+@item T M-p
+@kindex T M-p (Topic)
+@findex gnus-topic-goto-previous-topic
+Go to the next topic (@code{gnus-topic-goto-previous-topic}).
+
 @item G p
 @kindex G p (Topic)
 @findex gnus-topic-edit-parameters
@@ -2724,12 +3826,54 @@ Edit the topic parameters (@code{gnus-topic-edit-parameters}).
 @end table
 
 
+@node Topic Variables
+@subsection Topic Variables
+@cindex topic variables
+
+The previous section told you how to tell Gnus which topics to display.
+This section explains how to tell Gnus what to display about each topic.
+
+@vindex gnus-topic-line-format
+The topic lines themselves are created according to the
+@code{gnus-topic-line-format} variable (@pxref{Formatting Variables}).
+Valid elements are:
+
+@table @samp
+@item i
+Indentation.
+@item n
+Topic name.
+@item v
+Visibility.
+@item l
+Level.
+@item g
+Number of groups in the topic.
+@item a
+Number of unread articles in the topic.
+@item A
+Number of unread articles in the topic and all its subtopics.
+@end table
+
+@vindex gnus-topic-indent-level
+Each sub-topic (and the groups in the sub-topics) will be indented with
+@code{gnus-topic-indent-level} times the topic level number of spaces.
+The default is 2.
+
+@vindex gnus-topic-mode-hook
+@code{gnus-topic-mode-hook} is called in topic minor mode buffers.
+
+@vindex gnus-topic-display-empty-topics
+The @code{gnus-topic-display-empty-topics} says whether to display even
+topics that have no unread articles in them.  The default is @code{t}.
+
+
 @node Topic Sorting
 @subsection Topic Sorting
 @cindex topic sorting
 
 You can sort the groups in each topic individually with the following
-commands: 
+commands:
 
 
 @table @kbd
@@ -2737,7 +3881,7 @@ commands:
 @kindex T S a (Topic)
 @findex gnus-topic-sort-groups-by-alphabet
 Sort the current topic alphabetically by group name
-(@code{gnus-topic-sort-groups-by-alphabet}). 
+(@code{gnus-topic-sort-groups-by-alphabet}).
 
 @item T S u
 @kindex T S u (Topic)
@@ -2749,7 +3893,7 @@ Sort the current topic by the number of unread articles
 @kindex T S l (Topic)
 @findex gnus-topic-sort-groups-by-level
 Sort the current topic by group level
-(@code{gnus-topic-sort-groups-by-level}). 
+(@code{gnus-topic-sort-groups-by-level}).
 
 @item T S v
 @kindex T S v (Topic)
@@ -2766,12 +3910,27 @@ Sort the current topic by group rank
 @item T S m
 @kindex T S m (Topic)
 @findex gnus-topic-sort-groups-by-method
-Sort the current topic alphabetically by backend name
-(@code{gnus-topic-sort-groups-by-method}). 
+Sort the current topic alphabetically by back end name
+(@code{gnus-topic-sort-groups-by-method}).
+
+@item T S e
+@kindex T S e (Topic)
+@findex gnus-topic-sort-groups-by-server
+Sort the current topic alphabetically by server name
+(@code{gnus-topic-sort-groups-by-server}).
+
+@item T S s
+@kindex T S s (Topic)
+@findex gnus-topic-sort-groups
+Sort the current topic according to the function(s) given by the
+@code{gnus-group-sort-function} variable
+(@code{gnus-topic-sort-groups}).
 
 @end table
 
-@xref{Sorting Groups} for more information about group sorting. 
+When given a prefix argument, all these commands will sort in reverse
+order.  @xref{Sorting Groups}, for more information about group
+sorting.
 
 
 @node Topic Topology
@@ -2782,6 +3941,7 @@ Sort the current topic alphabetically by backend name
 So, let's have a look at an example group buffer:
 
 @example
+@group
 Gnus
   Emacs -- I wuw it!
      3: comp.emacs
@@ -2792,6 +3952,7 @@ Gnus
   Misc
      8: comp.binaries.fractals
     13: comp.sources.unix
+@end group
 @end example
 
 So, here we have one top-level topic (@samp{Gnus}), two topics under
@@ -2801,7 +3962,7 @@ follows:
 
 @lisp
 (("Gnus" visible)
- (("Emacs -- I wuw it!" visible) 
+ (("Emacs -- I wuw it!" visible)
   (("Naughty Emacs" visible)))
  (("Misc" visible)))
 @end lisp
@@ -2811,7 +3972,7 @@ This is in fact how the variable @code{gnus-topic-topology} would look
 for the display above.  That variable is saved in the @file{.newsrc.eld}
 file, and shouldn't be messed with manually---unless you really want
 to.  Since this variable is read from the @file{.newsrc.eld} file,
-setting it in any other startup files will have no effect.  
+setting it in any other startup files will have no effect.
 
 This topology shows what topics are sub-topics of what topics (right),
 and which topics are visible.  Two settings are currently
@@ -2822,9 +3983,28 @@ allowed---@code{visible} and @code{invisible}.
 @subsection Topic Parameters
 @cindex topic parameters
 
-All groups in a topic will inherit group parameters from the parent (and
-ancestor) topic parameters.  All valid group parameters are valid topic
-parameters (@pxref{Group Parameters}).  
+All groups in a topic will inherit group parameters from the parent
+(and ancestor) topic parameters.  All valid group parameters are valid
+topic parameters (@pxref{Group Parameters}).  When the agent is
+enabled, all agent parameters (See Agent Parameters in @ref{Category
+Syntax}) are also valid topic parameters.
+
+In addition, the following parameters are only valid as topic
+parameters:
+
+@table @code
+@item subscribe
+When subscribing new groups by topic (@pxref{Subscription Methods}), the
+@code{subscribe} topic parameter says what groups go in what topic.  Its
+value should be a regexp to match the groups that should go in that
+topic.
+
+@item subscribe-level
+When subscribing new groups by topic (see the @code{subscribe} parameter),
+the group will be subscribed with the level specified in the
+@code{subscribe-level} instead of @code{gnus-level-default-subscribed}.
+
+@end table
 
 Group parameters (of course) override topic parameters, and topic
 parameters in sub-topics override topic parameters in super-topics.  You
@@ -2832,6 +4012,7 @@ know.  Normal inheritance rules.  (@dfn{Rules} is here a noun, not a
 verb, although you may feel free to disagree with me here.)
 
 @example
+@group
 Gnus
   Emacs
      3: comp.emacs
@@ -2844,13 +4025,14 @@ Gnus
      8: comp.binaries.fractals
     13: comp.sources.unix
    452: alt.sex.emacs
+@end group   
 @end example
 
 The @samp{Emacs} topic has the topic parameter @code{(score-file
 . "emacs.SCORE")}; the @samp{Relief} topic has the topic parameter
 @code{(score-file . "relief.SCORE")}; and the @samp{Misc} topic has the
 topic parameter @code{(score-file . "emacs.SCORE")}.  In addition,
-@samp{alt.religion.emacs} has the group parameter @code{(score-file
+@* @samp{alt.religion.emacs} has the group parameter @code{(score-file
 . "religion.SCORE")}.
 
 Now, when you enter @samp{alt.sex.emacs} in the @samp{Relief} topic, you
@@ -2873,10 +4055,11 @@ happens.  You just have to be careful if you do stuff like that.
 @section Misc Group Stuff
 
 @menu
-* Scanning New Messages:: Asking Gnus to see whether new messages have arrived.
-* Group Information::     Information and help on groups and Gnus.
-* Group Timestamp::       Making Gnus keep track of when you last read a group.
-* File Commands::         Reading and writing the Gnus files.
+* Scanning New Messages::       Asking Gnus to see whether new messages have arrived.
+* Group Information::           Information and help on groups and Gnus.
+* Group Timestamp::             Making Gnus keep track of when you last read a group.
+* File Commands::               Reading and writing the Gnus files.
+* Sieve Commands::              Managing Sieve scripts.
 @end menu
 
 @table @kbd
@@ -2885,18 +4068,38 @@ happens.  You just have to be careful if you do stuff like that.
 @kindex ^ (Group)
 @findex gnus-group-enter-server-mode
 Enter the server buffer (@code{gnus-group-enter-server-mode}).
-@xref{The Server Buffer}.
+@xref{Server Buffer}.
 
 @item a
 @kindex a (Group)
 @findex gnus-group-post-news
-Post an article to a group (@code{gnus-group-post-news}).  If given a
-prefix, the current group name will be used as the default.
+Start composing a message (a news by default)
+(@code{gnus-group-post-news}).  If given a prefix, post to the group
+under the point.  If the prefix is 1, prompt for a group to post to.
+Contrary to what the name of this function suggests, the prepared
+article might be a mail instead of a news, if a mail group is specified
+with the prefix argument.  @xref{Composing Messages}.
 
 @item m
 @kindex m (Group)
 @findex gnus-group-mail
-Mail a message somewhere (@code{gnus-group-mail}).
+Mail a message somewhere (@code{gnus-group-mail}).  If given a prefix,
+use the posting style of the group under the point.  If the prefix is 1,
+prompt for a group name to find the posting style.
+@xref{Composing Messages}.
+
+@item i
+@kindex i (Group)
+@findex gnus-group-news
+Start composing a news (@code{gnus-group-news}).  If given a prefix,
+post to the group under the point.  If the prefix is 1, prompt
+for group to post to.  @xref{Composing Messages}.
+
+This function actually prepares a news even when using mail groups.
+This is useful for ``posting'' messages to mail groups without actually
+sending them over the network: they're just saved directly to the group
+in question.  The corresponding back end must have a request-post method
+for this to work though.
 
 @end table
 
@@ -2907,7 +4110,7 @@ Variables for the group buffer:
 @item gnus-group-mode-hook
 @vindex gnus-group-mode-hook
 is called after the group buffer has been
-created. 
+created.
 
 @item gnus-group-prepare-hook
 @vindex gnus-group-prepare-hook
@@ -2925,8 +4128,32 @@ generated.  It may be used to move point around, for instance.
 Groups matching this regexp will always be listed in the group buffer,
 whether they are empty or not.
 
-@end table
+@item gnus-group-name-charset-method-alist
+@vindex gnus-group-name-charset-method-alist
+An alist of method and the charset for group names.  It is used to show
+non-@acronym{ASCII} group names.
+
+For example:
+@lisp
+(setq gnus-group-name-charset-method-alist
+    '(((nntp "news.com.cn") . cn-gb-2312)))
+@end lisp
+
+@item gnus-group-name-charset-group-alist
+@cindex UTF-8 group names
+@vindex gnus-group-name-charset-group-alist
+An alist of regexp of group name and the charset for group names.  It
+is used to show non-@acronym{ASCII} group names.  @code{((".*"
+utf-8))} is the default value if UTF-8 is supported, otherwise the
+default is @code{nil}.
+
+For example:
+@lisp
+(setq gnus-group-name-charset-group-alist
+    '(("\\.com\\.cn:" . cn-gb-2312)))
+@end lisp
 
+@end table
 
 @node Scanning New Messages
 @subsection Scanning New Messages
@@ -2943,7 +4170,7 @@ Check the server(s) for new articles.  If the numerical prefix is used,
 this command will check only groups of level @var{arg} and lower
 (@code{gnus-group-get-new-news}).  If given a non-numerical prefix, this
 command will force a total re-reading of the active file(s) from the
-backend(s).
+back end(s).
 
 @item M-g
 @kindex M-g (Group)
@@ -2959,20 +4186,20 @@ to move point to the next group or not.  It is @code{t} by default.
 @cindex activating groups
 @item C-c M-g
 @kindex C-c M-g (Group)
-Activate absolutely all groups (@code{gnus-activate-all-groups}). 
+Activate absolutely all groups (@code{gnus-activate-all-groups}).
 
 @item R
 @kindex R (Group)
 @cindex restarting
 @findex gnus-group-restart
-Restart Gnus (@code{gnus-group-restart}).  This saves the @file{.newsrc}
+Restart gnus (@code{gnus-group-restart}).  This saves the @file{.newsrc}
 file(s), closes the connection to all servers, clears up all run-time
-Gnus variables, and then starts Gnus all over again.
+gnus variables, and then starts gnus all over again.
 
 @end table
 
 @vindex gnus-get-new-news-hook
-@code{gnus-get-new-news-hook} is run just before checking for new news. 
+@code{gnus-get-new-news-hook} is run just before checking for new news.
 
 @vindex gnus-after-getting-new-news-hook
 @code{gnus-after-getting-new-news-hook} is run after checking for new
@@ -2993,17 +4220,48 @@ news.
 @vindex gnus-group-faq-directory
 @cindex FAQ
 @cindex ange-ftp
-Try to fetch the FAQ for the current group
-(@code{gnus-group-fetch-faq}).  Gnus will try to get the FAQ from
-@code{gnus-group-faq-directory}, which is usually a directory on a
-remote machine.  This variable can also be a list of directories.  In
-that case, giving a prefix to this command will allow you to choose
-between the various sites.  @code{ange-ftp} (or @code{efs}) will be used
-for fetching the file.
-
-If fetching from the first site is unsuccessful, Gnus will attempt to go
+Try to fetch the @acronym{FAQ} for the current group
+(@code{gnus-group-fetch-faq}).  Gnus will try to get the @acronym{FAQ}
+from @code{gnus-group-faq-directory}, which is usually a directory on
+a remote machine.  This variable can also be a list of directories.
+In that case, giving a prefix to this command will allow you to choose
+between the various sites.  @code{ange-ftp} (or @code{efs}) will be
+used for fetching the file.
+
+If fetching from the first site is unsuccessful, gnus will attempt to go
 through @code{gnus-group-faq-directory} and try to open them one by one.
 
+@item H c
+@kindex H c (Group)
+@findex gnus-group-fetch-charter
+@vindex gnus-group-charter-alist
+@cindex charter
+Try to open the charter for the current group in a web browser
+(@code{gnus-group-fetch-charter}).  Query for a group if given a
+prefix argument.
+
+Gnus will use @code{gnus-group-charter-alist} to find the location of
+the charter.  If no location is known, Gnus will fetch the control
+messages for the group, which in some cases includes the charter.
+
+@item H C
+@kindex H C (Group)
+@findex gnus-group-fetch-control
+@vindex gnus-group-fetch-control-use-browse-url
+@cindex control message
+Fetch the control messages for the group from the archive at
+@code{ftp.isc.org} (@code{gnus-group-fetch-control}).  Query for a
+group if given a prefix argument.
+
+If @code{gnus-group-fetch-control-use-browse-url} is non-@code{nil},
+Gnus will open the control messages in a browser using
+@code{browse-url}.  Otherwise they are fetched using @code{ange-ftp}
+and displayed in an ephemeral group.
+
+Note that the control messages are compressed.  To use this command
+you need to turn on @code{auto-compression-mode} (@pxref{Compressed
+Files, ,Compressed Files, emacs, The Emacs Manual}).
+
 @item H d
 @itemx C-c C-d
 @c @icon{gnus-group-describe-group}
@@ -3019,7 +4277,7 @@ a prefix, force Gnus to re-read the description from the server.
 @kindex M-d (Group)
 @findex gnus-group-describe-all-groups
 Describe all groups (@code{gnus-group-describe-all-groups}).  If given a
-prefix, force Gnus to re-read the description file from the server.
+prefix, force gnus to re-read the description file from the server.
 
 @item H v
 @itemx V
@@ -3027,7 +4285,7 @@ prefix, force Gnus to re-read the description file from the server.
 @kindex H v (Group)
 @cindex version
 @findex gnus-version
-Display current Gnus version numbers (@code{gnus-version}).
+Display current gnus version numbers (@code{gnus-version}).
 
 @item ?
 @kindex ? (Group)
@@ -3039,7 +4297,7 @@ Give a very short help message (@code{gnus-group-describe-briefly}).
 @cindex info
 @cindex manual
 @findex gnus-info-find-node
-Go to the Gnus info node (@code{gnus-info-find-node}).
+Go to the gnus info node (@code{gnus-info-find-node}).
 @end table
 
 
@@ -3048,7 +4306,7 @@ Go to the Gnus info node (@code{gnus-info-find-node}).
 @cindex timestamps
 @cindex group timestamps
 
-It can be convenient to let Gnus keep track of when you last read a
+It can be convenient to let gnus keep track of when you last read a
 group.  To set the ball rolling, you should add
 @code{gnus-group-set-timestamp} to @code{gnus-select-group-hook}:
 
@@ -3062,7 +4320,7 @@ This information can be displayed in various ways---the easiest is to
 use the @samp{%d} spec in the group line format:
 
 @lisp
-(setq gnus-group-line-format 
+(setq gnus-group-line-format
       "%M\%S\%p\%P\%5y: %(%-40,40g%) %d\n")
 @end lisp
 
@@ -3078,10 +4336,24 @@ may be a bit too much, so to just display the date, you could say
 something like:
 
 @lisp
-(setq gnus-group-line-format 
+(setq gnus-group-line-format
       "%M\%S\%p\%P\%5y: %(%-40,40g%) %6,6~(cut 2)d\n")
 @end lisp
 
+If you would like greater control of the time format, you can use a
+user-defined format spec.  Something like the following should do the
+trick:
+
+@lisp
+(setq gnus-group-line-format
+      "%M\%S\%p\%P\%5y: %(%-40,40g%) %ud\n")
+(defun gnus-user-format-function-d (headers)
+  (let ((time (gnus-group-timestamp gnus-tmp-group)))
+    (if time
+        (format-time-string "%b %d  %H:%M" time)
+      "")))
+@end lisp
+
 
 @node File Commands
 @subsection File Commands
@@ -3095,7 +4367,7 @@ something like:
 @vindex gnus-init-file
 @cindex reading init file
 Re-read the init file (@code{gnus-init-file}, which defaults to
-@file{~/.gnus}) (@code{gnus-group-read-init-file}).
+@file{~/.gnus.el}) (@code{gnus-group-read-init-file}).
 
 @item s
 @kindex s (Group)
@@ -3113,15 +4385,77 @@ file(s) whether Gnus thinks it is necessary or not.
 @end table
 
 
-@node The Summary Buffer
-@chapter The Summary Buffer
+@node Sieve Commands
+@subsection Sieve Commands
+@cindex group sieve commands
+
+Sieve is a server-side mail filtering language.  In Gnus you can use
+the @code{sieve} group parameter (@pxref{Group Parameters}) to specify
+sieve rules that should apply to each group.  Gnus provides two
+commands to translate all these group parameters into a proper Sieve
+script that can be transfered to the server somehow.
+
+@vindex gnus-sieve-file
+@vindex gnus-sieve-region-start
+@vindex gnus-sieve-region-end
+The generated Sieve script is placed in @code{gnus-sieve-file} (by
+default @file{~/.sieve}).  The Sieve code that Gnus generate is placed
+between two delimiters, @code{gnus-sieve-region-start} and
+@code{gnus-sieve-region-end}, so you may write additional Sieve code
+outside these delimiters that will not be removed the next time you
+regenerate the Sieve script.
+
+@vindex gnus-sieve-crosspost
+The variable @code{gnus-sieve-crosspost} controls how the Sieve script
+is generated.  If it is non-@code{nil} (the default) articles is
+placed in all groups that have matching rules, otherwise the article
+is only placed in the group with the first matching rule.  For
+example, the group parameter @samp{(sieve address "sender"
+"owner-ding@@hpc.uh.edu")} will generate the following piece of Sieve
+code if @code{gnus-sieve-crosspost} is @code{nil}.  (When
+@code{gnus-sieve-crosspost} is non-@code{nil}, it looks the same
+except that the line containing the call to @code{stop} is removed.)
+
+@example
+if address "sender" "owner-ding@@hpc.uh.edu" @{
+        fileinto "INBOX.ding";
+        stop;
+@}
+@end example
+
+@xref{Top, Emacs Sieve, Top, sieve, Emacs Sieve}.
+
+@table @kbd
+
+@item D g
+@kindex D g (Group)
+@findex gnus-sieve-generate
+@vindex gnus-sieve-file
+@cindex generating sieve script
+Regenerate a Sieve script from the @code{sieve} group parameters and
+put you into the @code{gnus-sieve-file} without saving it.
+
+@item D u
+@kindex D u (Group)
+@findex gnus-sieve-update
+@vindex gnus-sieve-file
+@cindex updating sieve script
+Regenerates the Gnus managed part of @code{gnus-sieve-file} using the
+@code{sieve} group parameters, save the file and upload it to the
+server using the @code{sieveshell} program.
+
+@end table
+
+
+@node Summary Buffer
+@chapter Summary Buffer
 @cindex summary buffer
 
 A line for each article is displayed in the summary buffer.  You can
 move around, read articles, post articles and reply to articles.
 
 The most common way to a summary buffer is to select a group from the
-group buffer (@pxref{Selecting a Group}).  
+group buffer (@pxref{Selecting a Group}).
 
 You can have as many summary buffers open as you wish.
 
@@ -3131,11 +4465,11 @@ You can have as many summary buffers open as you wish.
 * Choosing Articles::           Reading articles.
 * Paging the Article::          Scrolling the current article.
 * Reply Followup and Post::     Posting articles.
-* Canceling and Superseding::   ``Whoops, I shouldn't have called him that.''
+* Delayed Articles::            Send articles at a later time.
 * Marking Articles::            Marking articles as read, expirable, etc.
 * Limiting::                    You can limit the summary buffer.
 * Threading::                   How threads are made.
-* Sorting::                     How articles and threads are sorted.
+* Sorting the Summary Buffer::  How articles and threads are sorted.
 * Asynchronous Fetching::       Gnus might be able to pre-fetch articles.
 * Article Caching::             You may store articles in a cache.
 * Persistent Articles::         Making articles expiry-resistant.
@@ -3143,6 +4477,8 @@ You can have as many summary buffers open as you wish.
 * Saving Articles::             Ways of customizing article saving.
 * Decoding Articles::           Gnus can treat series of (uu)encoded articles.
 * Article Treatment::           The article buffer can be mangled at will.
+* MIME Commands::               Doing MIMEy things with the articles.
+* Charsets::                    Character set issues.
 * Article Commands::            Doing various things with the article buffer.
 * Summary Sorting::             Sorting the summary buffer in various ways.
 * Finding the Parent::          No child support? Get the parent.
@@ -3150,9 +4486,12 @@ You can have as many summary buffers open as you wish.
 * Tree Display::                A more visual display of threads.
 * Mail Group Commands::         Some commands can only be used in mail groups.
 * Various Summary Stuff::       What didn't fit anywhere else.
-* Exiting the Summary Buffer::  Returning to the Group buffer.
+* Exiting the Summary Buffer::  Returning to the Group buffer,
+                                or reselecting the current group.
 * Crosspost Handling::          How crossposted articles are dealt with.
 * Duplicate Suppression::       An alternative when crosspost handling fails.
+* Security::                    Decrypt and Verify.
+* Mailing List::                Mailing list minor mode.
 @end menu
 
 
@@ -3163,16 +4502,17 @@ You can have as many summary buffers open as you wish.
 @iftex
 @iflatex
 \gnusfigure{The Summary Buffer}{180}{
-\put(0,0){\epsfig{figure=tmp/summary.ps,width=7.5cm}}
-\put(445,0){\makebox(0,0)[br]{\epsfig{figure=tmp/summary-article.ps,width=7.5cm}}}
+\put(0,0){\epsfig{figure=ps/summary,width=7.5cm}}
+\put(445,0){\makebox(0,0)[br]{\epsfig{figure=ps/summary-article,width=7.5cm}}}
 }
 @end iflatex
 @end iftex
 
 @menu
-* Summary Buffer Lines::     You can specify how summary lines should look.
-* Summary Buffer Mode Line:: You can say how the mode line should look.
-* Summary Highlighting::     Making the summary buffer all pretty and nice.
+* Summary Buffer Lines::        You can specify how summary lines should look.
+* To From Newsgroups::          How to not display your own name.
+* Summary Buffer Mode Line::    You can say how the mode line should look.
+* Summary Highlighting::        Making the summary buffer all pretty and nice.
 @end menu
 
 @findex mail-extract-address-components
@@ -3180,12 +4520,19 @@ You can have as many summary buffers open as you wish.
 @vindex gnus-extract-address-components
 Gnus will use the value of the @code{gnus-extract-address-components}
 variable as a function for getting the name and address parts of a
-@code{From} header.  Two pre-defined functions exist:
+@code{From} header.  Three pre-defined functions exist:
 @code{gnus-extract-address-components}, which is the default, quite
-fast, and too simplistic solution; and
-@code{mail-extract-address-components}, which works very nicely, but is
-slower.  The default function will return the wrong answer in 5% of the
-cases.  If this is unacceptable to you, use the other function instead.
+fast, and too simplistic solution;
+@code{mail-extract-address-components}, which works nicely, but is
+slower; and @code{std11-extract-address-components}, which works very
+nicely, but is slower.  The default function will return the wrong
+answer in 5% of the cases.  If this is unacceptable to you, use the
+other function instead:
+
+@lisp
+(setq gnus-extract-address-components
+      'mail-extract-address-components)
+@end lisp
 
 @vindex gnus-summary-same-subject
 @code{gnus-summary-same-subject} is a string indicating that the current
@@ -3202,15 +4549,24 @@ the @code{gnus-summary-line-format} variable.  It works along the same
 lines as a normal @code{format} string, with some extensions
 (@pxref{Formatting Variables}).
 
-The default string is @samp{%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n}.
+There should always be a colon or a point position marker on the line;
+the cursor always moves to the point position marker or the colon after
+performing an operation.  (Of course, Gnus wouldn't be Gnus if it wasn't
+possible to change this.  Just write a new function
+@code{gnus-goto-colon} which does whatever you like with the cursor.)
+@xref{Positioning Point}.
 
-The following format specification characters are understood:
+The default string is @samp{%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n}.
+
+The following format specification characters and extended format
+specification(s) are understood:
 
 @table @samp
-@item N 
+@item N
 Article number.
 @item S
-Subject string.
+Subject string.  List identifiers stripped,
+@code{gnus-list-identifies}.  @xref{Article Hiding}.
 @item s
 Subject if the article is the root of the thread or the previous article
 had a different subject, @code{gnus-summary-same-subject} otherwise.
@@ -3219,6 +4575,9 @@ had a different subject, @code{gnus-summary-same-subject} otherwise.
 Full @code{From} header.
 @item n
 The name (from the @code{From} header).
+@item f
+The name, @code{To} header or the @code{Newsgroups} header (@pxref{To
+From Newsgroups}).
 @item a
 The name (from the @code{From} header).  This differs from the @code{n}
 spec in that it uses the function designated by the
@@ -3230,9 +4589,66 @@ the @code{a} spec.
 @item L
 Number of lines in the article.
 @item c
-Number of characters in the article.
+Number of characters in the article.  This specifier is not supported
+in some methods (like nnfolder).
+@item k
+Pretty-printed version of the number of characters in the article;
+for example, @samp{1.2k} or @samp{0.4M}.
 @item I
 Indentation based on thread level (@pxref{Customizing Threading}).
+@item B
+A complex trn-style thread tree, showing response-connecting trace
+lines.  A thread could be drawn like this:
+
+@example
+>
++->
+| +->
+| | \->
+| |   \->
+| \->
++->
+\->
+@end example
+
+You can customize the appearance with the following options.  Note
+that it is possible to make the thread display look really neat by
+replacing the default @acronym{ASCII} characters with graphic
+line-drawing glyphs.
+@table @code
+@item gnus-sum-thread-tree-root
+@vindex gnus-sum-thread-tree-root
+Used for the root of a thread.  If @code{nil}, use subject
+instead.  The default is @samp{> }.
+
+@item gnus-sum-thread-tree-false-root
+@vindex gnus-sum-thread-tree-false-root
+Used for the false root of a thread (@pxref{Loose Threads}).  If
+@code{nil}, use subject instead.  The default is @samp{> }.
+
+@item gnus-sum-thread-tree-single-indent
+@vindex gnus-sum-thread-tree-single-indent
+Used for a thread with just one message.  If @code{nil}, use subject
+instead.  The default is @samp{}.
+
+@item gnus-sum-thread-tree-vertical
+@vindex gnus-sum-thread-tree-vertical
+Used for drawing a vertical line.  The default is @samp{| }.
+
+@item gnus-sum-thread-tree-indent
+@vindex gnus-sum-thread-tree-indent
+Used for indenting.  The default is @samp{  }.
+
+@item gnus-sum-thread-tree-leaf-with-other
+@vindex gnus-sum-thread-tree-leaf-with-other
+Used for a leaf with brothers.  The default is @samp{+-> }.
+
+@item gnus-sum-thread-tree-single-leaf
+@vindex gnus-sum-thread-tree-single-leaf
+Used for a leaf without brothers.  The default is @samp{\-> }
+
+@end table
+
 @item T
 Nothing if the article is a root and lots of spaces if it isn't (it
 pushes everything after it off the screen).
@@ -3247,16 +4663,20 @@ One space for each thread level.
 @item <
 Twenty minus thread level spaces.
 @item U
-Unread.
+Unread.  @xref{Read Articles}.
+
 @item R
-Replied.
+This misleadingly named specifier is the @dfn{secondary mark}.  This
+mark will say whether the article has been replied to, has been cached,
+or has been saved.  @xref{Other Marks}.
+
 @item i
 Score as a number (@pxref{Scoring}).
 @item z
 @vindex gnus-summary-zcore-fuzz
 Zcore, @samp{+} if above the default level and @samp{-} if below the
 default level.  If the difference between
-@code{gnus-summary-default-level} and the score is less than
+@code{gnus-summary-default-score} and the score is less than
 @code{gnus-summary-zcore-fuzz}, this spec will not be used.
 @item V
 Total thread score.
@@ -3282,17 +4702,24 @@ article has any children.
 The line number.
 @item O
 Download mark.
+@item &user-date;
+Age sensitive date format.  Various date format is defined in
+@code{gnus-user-date-format-alist}.
 @item u
 User defined specifier.  The next character in the format string should
 be a letter.  Gnus will call the function
-@code{gnus-user-format-function-}@samp{X}, where @samp{X} is the letter
+@code{gnus-user-format-function-@var{x}}, where @var{x} is the letter
 following @samp{%u}.  The function will be passed the current header as
 argument.  The function should return a string, which will be inserted
 into the summary just like information from any other summary specifier.
 @end table
 
+Text between @samp{%(} and @samp{%)} will be highlighted with
+@code{gnus-mouse-face} when the mouse point is placed inside the area.
+There can only be one such area.
+
 The @samp{%U} (status), @samp{%R} (replied) and @samp{%z} (zcore) specs
-have to be handled with care.  For reasons of efficiency, Gnus will
+have to be handled with care.  For reasons of efficiency, gnus will
 compute what column these characters will end up in, and ``hard-code''
 that.  This means that it is invalid to have these specs after a
 variable-length spec.  Well, you might not be arrested, but your summary
@@ -3301,16 +4728,107 @@ buffer will look strange, which is bad enough.
 The smart choice is to have these specs as far to the left as possible.
 (Isn't that the case with everything, though?  But I digress.)
 
-This restriction may disappear in later versions of Gnus.
+This restriction may disappear in later versions of gnus.
+
+
+@node To From Newsgroups
+@subsection To From Newsgroups
+@cindex To
+@cindex Newsgroups
+
+In some groups (particularly in archive groups), the @code{From} header
+isn't very interesting, since all the articles there are written by
+you.  To display the information in the @code{To} or @code{Newsgroups}
+headers instead, you need to decide three things: What information to
+gather; where to display it; and when to display it.
+
+@enumerate
+@item
+@vindex gnus-extra-headers
+The reading of extra header information is controlled by the
+@code{gnus-extra-headers}.  This is a list of header symbols.  For
+instance:
+
+@lisp
+(setq gnus-extra-headers
+      '(To Newsgroups X-Newsreader))
+@end lisp
+
+This will result in Gnus trying to obtain these three headers, and
+storing it in header structures for later easy retrieval.
+
+@item
+@findex gnus-extra-header
+The value of these extra headers can be accessed via the
+@code{gnus-extra-header} function.  Here's a format line spec that will
+access the @code{X-Newsreader} header:
+
+@example
+"%~(form (gnus-extra-header 'X-Newsreader))@@"
+@end example
+
+@item
+@vindex gnus-ignored-from-addresses
+The @code{gnus-ignored-from-addresses} variable says when the @samp{%f}
+summary line spec returns the @code{To}, @code{Newsreader} or
+@code{From} header.  If this regexp matches the contents of the
+@code{From} header, the value of the @code{To} or @code{Newsreader}
+headers are used instead.
+
+@end enumerate
+
+@vindex nnmail-extra-headers
+A related variable is @code{nnmail-extra-headers}, which controls when
+to include extra headers when generating overview (@acronym{NOV}) files.
+If you have old overview files, you should regenerate them after
+changing this variable, by entering the server buffer using @kbd{^},
+and then @kbd{g} on the appropriate mail server (e.g. nnml) to cause
+regeneration.
+
+@vindex gnus-summary-line-format
+You also have to instruct Gnus to display the data by changing the
+@code{%n} spec to the @code{%f} spec in the
+@code{gnus-summary-line-format} variable.
+
+In summary, you'd typically put something like the following in
+@file{~/.gnus.el}:
+
+@lisp
+(setq gnus-extra-headers
+      '(To Newsgroups))
+(setq nnmail-extra-headers gnus-extra-headers)
+(setq gnus-summary-line-format
+      "%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n")
+(setq gnus-ignored-from-addresses
+      "Your Name Here")
+@end lisp
+
+(The values listed above are the default values in Gnus.  Alter them
+to fit your needs.)
+
+A note for news server administrators, or for users who wish to try to
+convince their news server administrator to provide some additional
+support:
+
+The above is mostly useful for mail groups, where you have control over
+the @acronym{NOV} files that are created.  However, if you can persuade your
+nntp admin to add (in the usual implementation, notably INN):
+
+@example
+Newsgroups:full
+@end example
+
+to the end of her @file{overview.fmt} file, then you can use that just
+as you would the extra headers from the mail groups.
 
 
 @node Summary Buffer Mode Line
 @subsection Summary Buffer Mode Line
 
 @vindex gnus-summary-mode-line-format
-You can also change the format of the summary mode bar.  Set
-@code{gnus-summary-mode-line-format} to whatever you like.  The default
-is @samp{Gnus: %%b [%A] %Z}.  
+You can also change the format of the summary mode bar (@pxref{Mode Line
+Formatting}).  Set @code{gnus-summary-mode-line-format} to whatever you
+like.  The default is @samp{Gnus: %%b [%A] %Z}.
 
 Here are the elements you can play with:
 
@@ -3321,6 +4839,8 @@ Group name.
 Unprefixed group name.
 @item A
 Current article number.
+@item z
+Current article score.
 @item V
 Gnus version.
 @item U
@@ -3335,7 +4855,7 @@ articles, and just as @samp{<%U more>} if there are just unread articles
 and no unselected ones.
 @item g
 Shortish group name.  For instance, @samp{rec.arts.anime} will be
-shortened to @samp{r.a.anime}. 
+shortened to @samp{r.a.anime}.
 @item S
 Subject of the current article.
 @item u
@@ -3347,7 +4867,7 @@ Number of dormant articles (@pxref{Unread Articles}).
 @item t
 Number of ticked articles (@pxref{Unread Articles}).
 @item r
-Number of articles that have been marked as read in this session. 
+Number of articles that have been marked as read in this session.
 @item E
 Number of articles expunged by the score files.
 @end table
@@ -3377,15 +4897,16 @@ highlight the current article in the summary buffer.
 @item gnus-summary-highlight
 @vindex gnus-summary-highlight
 Summary lines are highlighted according to this variable, which is a
-list where the elements are of the format @var{(FORM . FACE)}.  If you
-would, for instance, like ticked articles to be italic and high-scored
-articles to be bold, you could set this variable to something like
+list where the elements are of the format @code{(@var{form}
+. @var{face})}.  If you would, for instance, like ticked articles to be
+italic and high-scored articles to be bold, you could set this variable
+to something like
 @lisp
 (((eq mark gnus-ticked-mark) . italic)
  ((> score default) . bold))
 @end lisp
-As you may have guessed, if @var{FORM} returns a non-@code{nil} value,
-@var{FACE} will be applied to the line.
+As you may have guessed, if @var{form} returns a non-@code{nil} value,
+@var{face} will be applied to the line.
 @end table
 
 
@@ -3394,7 +4915,7 @@ As you may have guessed, if @var{FORM} returns a non-@code{nil} value,
 @cindex summary movement
 
 All the straight movement commands understand the numeric prefix and
-behave pretty much as you'd expect. 
+behave pretty much as you'd expect.
 
 None of these commands select articles.
 
@@ -3405,7 +4926,7 @@ None of these commands select articles.
 @kindex G M-n (Summary)
 @findex gnus-summary-next-unread-subject
 Go to the next summary line of an unread article
-(@code{gnus-summary-next-unread-subject}). 
+(@code{gnus-summary-next-unread-subject}).
 
 @item G M-p
 @itemx M-p
@@ -3413,15 +4934,7 @@ Go to the next summary line of an unread article
 @kindex G M-p (Summary)
 @findex gnus-summary-prev-unread-subject
 Go to the previous summary line of an unread article
-(@code{gnus-summary-prev-unread-subject}). 
-
-@item G j
-@itemx j
-@kindex j (Summary)
-@kindex G j (Summary)
-@findex gnus-summary-goto-article
-Ask for an article number or @code{Message-ID}, and then go to that
-article (@code{gnus-summary-goto-article}).
+(@code{gnus-summary-prev-unread-subject}).
 
 @item G g
 @kindex G g (Summary)
@@ -3430,7 +4943,7 @@ Ask for an article number and then go to the summary line of that article
 without displaying the article (@code{gnus-summary-goto-subject}).
 @end table
 
-If Gnus asks you to press a key to confirm going to the next group, you
+If gnus asks you to press a key to confirm going to the next group, you
 can use the @kbd{C-n} and @kbd{C-p} keys to move around the group
 buffer, searching for the next group to read without actually returning
 to the group buffer.
@@ -3442,25 +4955,27 @@ Variables related to summary movement:
 @vindex gnus-auto-select-next
 @item gnus-auto-select-next
 If you issue one of the movement commands (like @kbd{n}) and there are
-no more unread articles after the current one, Gnus will offer to go to
+no more unread articles after the current one, gnus will offer to go to
 the next group.  If this variable is @code{t} and the next group is
-empty, Gnus will exit summary mode and return to the group buffer.  If
-this variable is neither @code{t} nor @code{nil}, Gnus will select the
-next group, no matter whether it has any unread articles or not.  As a
-special case, if this variable is @code{quietly}, Gnus will select the
-next group without asking for confirmation.  If this variable is
-@code{almost-quietly}, the same will happen only if you are located on
-the last article in the group.  Finally, if this variable is
-@code{slightly-quietly}, the @kbd{Z n} command will go to the next group
-without confirmation.  Also @pxref{Group Levels}.
+empty, gnus will exit summary mode and return to the group buffer.  If
+this variable is neither @code{t} nor @code{nil}, gnus will select the
+next group with unread articles.  As a special case, if this variable
+is @code{quietly}, Gnus will select the next group without asking for
+confirmation.  If this variable is @code{almost-quietly}, the same
+will happen only if you are located on the last article in the group.
+Finally, if this variable is @code{slightly-quietly}, the @kbd{Z n}
+command will go to the next group without confirmation.  Also
+@pxref{Group Levels}.
 
 @item gnus-auto-select-same
 @vindex gnus-auto-select-same
 If non-@code{nil}, all the movement commands will try to go to the next
 article with the same subject as the current.  (@dfn{Same} here might
 mean @dfn{roughly equal}.  See @code{gnus-summary-gather-subject-limit}
-for details (@pxref{Customizing Threading}).)  This variable is not
-particularly useful if you use a threaded display.
+for details (@pxref{Customizing Threading}).)  If there are no more
+articles with the same subject, go to the first unread article.
+
+This variable is not particularly useful if you use a threaded display.
 
 @item gnus-summary-check-current
 @vindex gnus-summary-check-current
@@ -3470,7 +4985,7 @@ Instead, they will choose the current article.
 
 @item gnus-auto-center-summary
 @vindex gnus-auto-center-summary
-If non-@code{nil}, Gnus will keep the point in the summary buffer
+If non-@code{nil}, gnus will keep the point in the summary buffer
 centered at all times.  This makes things quite tidy, but if you have a
 slow network connection, or simply do not like this un-Emacsism, you can
 set this variable to @code{nil} to get the normal Emacs scrolling
@@ -3478,6 +4993,9 @@ action.  This will also inhibit horizontal re-centering of the summary
 buffer, which might make it more inconvenient to read extremely long
 threads.
 
+This variable can also be a number.  In that case, center the window at
+the given number of lines from the top.
+
 @end table
 
 
@@ -3486,8 +5004,8 @@ threads.
 @cindex selecting articles
 
 @menu
-* Choosing Commands::        Commands for choosing articles.
-* Choosing Variables::       Variables that influence these commands.
+* Choosing Commands::           Commands for choosing articles.
+* Choosing Variables::          Variables that influence these commands.
 @end menu
 
 
@@ -3497,6 +5015,9 @@ threads.
 None of the following movement commands understand the numeric prefix,
 and they all select and display an article.
 
+If you want to fetch new articles or redisplay the group, see
+@ref{Exiting the Summary Buffer}.
+
 @table @kbd
 @item SPACE
 @kindex SPACE (Summary)
@@ -3504,6 +5025,10 @@ and they all select and display an article.
 Select the current article, or, if that one's read already, the next
 unread article (@code{gnus-summary-next-page}).
 
+If you have an article window open already and you press @kbd{SPACE}
+again, the article will be scrolled.  This lets you conveniently
+@kbd{SPACE} through an entire newsgroup.  @xref{Paging the Article}.
+
 @item G n
 @itemx n
 @kindex n (Summary)
@@ -3537,13 +5062,13 @@ Go to the previous article (@code{gnus-summary-prev-article}).
 @kindex G C-n (Summary)
 @findex gnus-summary-next-same-subject
 Go to the next article with the same subject
-(@code{gnus-summary-next-same-subject}). 
+(@code{gnus-summary-next-same-subject}).
 
 @item G C-p
 @kindex G C-p (Summary)
 @findex gnus-summary-prev-same-subject
 Go to the previous article with the same subject
-(@code{gnus-summary-prev-same-subject}). 
+(@code{gnus-summary-prev-same-subject}).
 
 @item G f
 @itemx .
@@ -3558,8 +5083,9 @@ Go to the first unread article
 @kindex G b (Summary)
 @kindex , (Summary)
 @findex gnus-summary-best-unread-article
-Go to the article with the highest score
-(@code{gnus-summary-best-unread-article}). 
+Go to the unread article with the highest score
+(@code{gnus-summary-best-unread-article}).  If given a prefix argument,
+go to the first unread article that has a score over the default score.
 
 @item G l
 @itemx l
@@ -3579,6 +5105,15 @@ command above in that you can pop as many previous articles off the
 history as you like, while @kbd{l} toggles the two last read articles.
 For a somewhat related issue (if you use these commands a lot),
 @pxref{Article Backlog}.
+
+@item G j
+@itemx j
+@kindex j (Summary)
+@kindex G j (Summary)
+@findex gnus-summary-goto-article
+Ask for an article number or @code{Message-ID}, and then go to that
+article (@code{gnus-summary-goto-article}).
+
 @end table
 
 
@@ -3598,7 +5133,9 @@ the server and display it in the article buffer.
 @item gnus-select-article-hook
 @vindex gnus-select-article-hook
 This hook is called whenever an article is selected.  By default it
-exposes any threads hidden under the selected article.
+exposes any threads hidden under the selected article.  If you would
+like each article to be saved in the Agent as you read it, putting
+@code{gnus-agent-fetch-selected-article} on this hook will do so.
 
 @item gnus-mark-article-hook
 @vindex gnus-mark-article-hook
@@ -3631,10 +5168,19 @@ Pressing @kbd{SPACE} will scroll the current article forward one page,
 or, if you have come to the end of the current article, will choose the
 next article (@code{gnus-summary-next-page}).
 
+@vindex gnus-article-boring-faces
+@vindex gnus-article-skip-boring
+If @code{gnus-article-skip-boring} is non-@code{nil} and the rest of
+the article consists only of citations and signature, then it will be
+skipped; the next article will be shown instead.  You can customize
+what is considered uninteresting with
+@code{gnus-article-boring-faces}.  You can manually view the article's
+pages, no matter how boring, using @kbd{C-M-v}.
+
 @item DEL
 @kindex DEL (Summary)
 @findex gnus-summary-prev-page
-Scroll the current article back one page (@code{gnus-summary-prev-page}). 
+Scroll the current article back one page (@code{gnus-summary-prev-page}).
 
 @item RET
 @kindex RET (Summary)
@@ -3642,16 +5188,35 @@ Scroll the current article back one page (@code{gnus-summary-prev-page}).
 Scroll the current article one line forward
 (@code{gnus-summary-scroll-up}).
 
+@item M-RET
+@kindex M-RET (Summary)
+@findex gnus-summary-scroll-down
+Scroll the current article one line backward
+(@code{gnus-summary-scroll-down}).
+
 @item A g
 @itemx g
 @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)
@@ -3667,7 +5232,7 @@ Scroll to the beginning of the article
 @findex gnus-summary-end-of-article
 Scroll to the end of the article (@code{gnus-summary-end-of-article}).
 
-@item A s 
+@item A s
 @itemx s
 @kindex A s (Summary)
 @kindex s (Summary)
@@ -3687,8 +5252,10 @@ Select the article buffer (@code{gnus-summary-select-article-buffer}).
 @section Reply, Followup and Post
 
 @menu
-* Summary Mail Commands::            Sending mail.
-* Summary Post Commands::            Sending news.
+* Summary Mail Commands::       Sending mail.
+* Summary Post Commands::       Sending news.
+* Summary Message Commands::    Other Message-related commands.
+* Canceling and Superseding::
 @end menu
 
 
@@ -3709,7 +5276,7 @@ Commands for composing a mail message:
 @c @icon{gnus-summary-mail-reply}
 @c @icon{gnus-summary-reply}
 Mail a reply to the author of the current article
-(@code{gnus-summary-reply}). 
+(@code{gnus-summary-reply}).
 
 @item S R
 @itemx R
@@ -3727,17 +5294,53 @@ command uses the process/prefix convention.
 Mail a wide reply to the author of the current article
 (@code{gnus-summary-wide-reply}).  A @dfn{wide reply} is a reply that
 goes out to all people listed in the @code{To}, @code{From} (or
-@code{Reply-to}) and @code{Cc} headers.
+@code{Reply-to}) and @code{Cc} headers.  If @code{Mail-Followup-To} is
+present, that's used instead.
 
 @item S W
 @kindex S W (Summary)
 @findex gnus-summary-wide-reply-with-original
 Mail a wide reply to the current article and include the original
-message (@code{gnus-summary-reply-with-original}).  This command uses
+message (@code{gnus-summary-wide-reply-with-original}).  This command uses
 the process/prefix convention.
 
+@item S v
+@kindex S v (Summary)
+@findex gnus-summary-very-wide-reply
+Mail a very wide reply to the author of the current article
+(@code{gnus-summary-wide-reply}).  A @dfn{very wide reply} is a reply
+that goes out to all people listed in the @code{To}, @code{From} (or
+@code{Reply-to}) and @code{Cc} headers in all the process/prefixed
+articles.  This command uses the process/prefix convention.
+
+@item S V
+@kindex S V (Summary)
+@findex gnus-summary-very-wide-reply-with-original
+Mail a very wide reply to the author of the current article and include the
+original message (@code{gnus-summary-very-wide-reply-with-original}).  This
+command uses the process/prefix convention.
+
+@item S B r
+@kindex S B r (Summary)
+@findex gnus-summary-reply-broken-reply-to
+Mail a reply to the author of the current article but ignore the
+@code{Reply-To} field (@code{gnus-summary-reply-broken-reply-to}).
+If you need this because a mailing list incorrectly sets a
+@code{Reply-To} header pointing to the list, you probably want to set
+the @code{broken-reply-to} group parameter instead, so things will work
+correctly.  @xref{Group Parameters}.
+
+@item S B R
+@kindex S B R (Summary)
+@findex gnus-summary-reply-broken-reply-to-with-original
+Mail a reply to the author of the current article and include the
+original message but ignore the @code{Reply-To} field
+(@code{gnus-summary-reply-broken-reply-to-with-original}).
+
 @item S o m
+@itemx C-c C-f
 @kindex S o m (Summary)
+@kindex C-c C-f (Summary)
 @findex gnus-summary-mail-forward
 @c @icon{gnus-summary-mail-forward}
 Forward the current article to some other person
@@ -3750,8 +5353,24 @@ headers of the forwarded article.
 @kindex S m (Summary)
 @findex gnus-summary-mail-other-window
 @c @icon{gnus-summary-mail-originate}
-Send a mail to some other person
-(@code{gnus-summary-mail-other-window}).
+Prepare a mail (@code{gnus-summary-mail-other-window}).  By default, use
+the posting style of the current group.  If given a prefix, disable that.
+If the prefix is 1, prompt for a group name to find the posting style.
+
+@item S i
+@itemx i
+@kindex i (Summary)
+@kindex S i (Summary)
+@findex gnus-summary-news-other-window
+Prepare a news (@code{gnus-summary-news-other-window}).  By default,
+post to the current group.  If given a prefix, disable that.  If the
+prefix is 1, prompt for a group to post to.
+
+This function actually prepares a news even when using mail groups.
+This is useful for ``posting'' messages to mail groups without actually
+sending them over the network: they're just saved directly to the group
+in question.  The corresponding back end must have a request-post method
+for this to work though.
 
 @item S D b
 @kindex S D b (Summary)
@@ -3762,7 +5381,7 @@ reason (wrong address, transient failure), you can use this command to
 resend that bounced mail (@code{gnus-summary-resend-bounced-mail}).  You
 will be popped into a mail buffer where you can edit the headers before
 sending the mail off again.  If you give a prefix to this command, and
-the bounced mail is a reply to some other mail, Gnus will try to fetch
+the bounced mail is a reply to some other mail, gnus will try to fetch
 that mail and display it for easy perusal of its headers.  This might
 very well fail, though.
 
@@ -3776,23 +5395,23 @@ headers of the message won't be altered---but lots of headers that say
 @code{Resent-To}, @code{Resent-From} and so on will be added.  This
 means that you actually send a mail to someone that has a @code{To}
 header that (probably) points to yourself.  This will confuse people.
-So, natcherly you'll only do that if you're really eVIl.  
+So, natcherly you'll only do that if you're really eVIl.
 
 This command is mainly used if you have several accounts and want to
 ship a mail to a different account of yours.  (If you're both
 @code{root} and @code{postmaster} and get a mail for @code{postmaster}
 to the @code{root} account, you may want to resend it to
-@code{postmaster}.  Ordnung muß sein!
+@code{postmaster}.  Ordnung muss sein!
 
 This command understands the process/prefix convention
-(@pxref{Process/Prefix}). 
+(@pxref{Process/Prefix}).
 
 @item S O m
 @kindex S O m (Summary)
-@findex gnus-uu-digest-mail-forward
+@findex gnus-summary-digest-mail-forward
 Digest the current series (@pxref{Decoding Articles}) and forward the
-result using mail (@code{gnus-uu-digest-mail-forward}).  This command
-uses the process/prefix convention (@pxref{Process/Prefix}).
+result using mail (@code{gnus-summary-digest-mail-forward}).  This
+command uses the process/prefix convention (@pxref{Process/Prefix}).
 
 @item S M-c
 @kindex S M-c (Summary)
@@ -3800,10 +5419,10 @@ uses the process/prefix convention (@pxref{Process/Prefix}).
 @cindex crossposting
 @cindex excessive crossposting
 Send a complaint about excessive crossposting to the author of the
-current article (@code{gnus-summary-mail-crosspost-complaint}).  
+current article (@code{gnus-summary-mail-crosspost-complaint}).
 
 @findex gnus-crosspost-complaint
-This command is provided as a way to fight back agains the current
+This command is provided as a way to fight back against the current
 crossposting pandemic that's sweeping Usenet.  It will compose a reply
 using the @code{gnus-crosspost-complaint} variable as a preamble.  This
 command understands the process/prefix convention
@@ -3811,6 +5430,9 @@ command understands the process/prefix convention
 
 @end table
 
+Also @xref{Header Commands, ,Header Commands, message, The Message
+Manual}, for more information.
+
 
 @node Summary Post Commands
 @subsection Summary Post Commands
@@ -3826,8 +5448,9 @@ Commands for posting a news article:
 @kindex S p (Summary)
 @findex gnus-summary-post-news
 @c @icon{gnus-summary-post-news}
-Post an article to the current group
-(@code{gnus-summary-post-news}).
+Prepare for posting an article (@code{gnus-summary-post-news}).  By
+default, post to the current group.  If given a prefix, disable that.
+If the prefix is 1, prompt for another group instead.
 
 @item S f
 @itemx f
@@ -3844,7 +5467,7 @@ Post a followup to the current article (@code{gnus-summary-followup}).
 @c @icon{gnus-summary-followup-with-original}
 @findex gnus-summary-followup-with-original
 Post a followup to the current article and include the original message
-(@code{gnus-summary-followup-with-original}).   This command uses the
+(@code{gnus-summary-followup-with-original}).  This command uses the
 process/prefix convention.
 
 @item S n
@@ -3853,9 +5476,9 @@ process/prefix convention.
 Post a followup to the current article via news, even if you got the
 message through mail (@code{gnus-summary-followup-to-mail}).
 
-@item S n
-@kindex S n (Summary)
-@findex gnus-summary-followup-to-mail
+@item S N
+@kindex S N (Summary)
+@findex gnus-summary-followup-to-mail-with-original
 Post a followup to the current article via news, even if you got the
 message through mail and include the original message
 (@code{gnus-summary-followup-to-mail-with-original}).  This command uses
@@ -3870,11 +5493,11 @@ headers of the forwarded article.
 
 @item S O p
 @kindex S O p (Summary)
-@findex gnus-uu-digest-post-forward
+@findex gnus-summary-digest-post-forward
 @cindex digests
 @cindex making digests
 Digest the current series and forward the result to a newsgroup
-(@code{gnus-uu-digest-mail-forward}).  This command uses the
+(@code{gnus-summary-digest-post-forward}).  This command uses the
 process/prefix convention.
 
 @item S u
@@ -3882,12 +5505,30 @@ process/prefix convention.
 @findex gnus-uu-post-news
 @c @icon{gnus-uu-post-news}
 Uuencode a file, split it into parts, and post it as a series
-(@code{gnus-uu-post-news}). (@pxref{Uuencoding and Posting}). 
+(@code{gnus-uu-post-news}).  (@pxref{Uuencoding and Posting}).
+@end table
+
+Also @xref{Header Commands, ,Header Commands, message, The Message
+Manual}, for more information.
+
+
+@node Summary Message Commands
+@subsection Summary Message Commands
+
+@table @kbd
+@item S y
+@kindex S y (Summary)
+@findex gnus-summary-yank-message
+Yank the current article into an already existing Message composition
+buffer (@code{gnus-summary-yank-message}).  This command prompts for
+what message buffer you want to yank into, and understands the
+process/prefix convention (@pxref{Process/Prefix}).
+
 @end table
 
 
 @node Canceling and Superseding
-@section Canceling Articles
+@subsection Canceling Articles
 @cindex canceling articles
 @cindex superseding articles
 
@@ -3909,10 +5550,14 @@ Be aware, however, that not all sites honor cancels, so your article may
 live on here and there, while most sites will delete the article in
 question.
 
-Gnus will use the ``current'' select method when cancelling.  If you
+Gnus will use the ``current'' select method when canceling.  If you
 want to use the standard posting method, use the @samp{a} symbolic
 prefix (@pxref{Symbolic Prefixes}).
 
+Gnus ensures that only you can cancel your own messages using a
+@code{Cancel-Lock} header (@pxref{Canceling News, Canceling News, ,
+message, Message Manual}).
+
 If you discover that you have made some mistakes and want to do some
 corrections, you can post a @dfn{superseding} article that will replace
 your original article.
@@ -3941,6 +5586,103 @@ canceled/superseded.
 
 Just remember, kids: There is no 'c' in 'supersede'.
 
+@node Delayed Articles
+@section Delayed Articles
+@cindex delayed sending
+@cindex send delayed
+
+Sometimes, you might wish to delay the sending of a message.  For
+example, you might wish to arrange for a message to turn up just in time
+to remind your about the birthday of your Significant Other.  For this,
+there is the @code{gnus-delay} package.  Setup is simple:
+
+@lisp
+(gnus-delay-initialize)
+@end lisp
+
+@findex gnus-delay-article
+Normally, to send a message you use the @kbd{C-c C-c} command from
+Message mode.  To delay a message, use @kbd{C-c C-j}
+(@code{gnus-delay-article}) instead.  This will ask you for how long the
+message should be delayed.  Possible answers are:
+
+@itemize @bullet
+@item
+A time span.  Consists of an integer and a letter.  For example,
+@code{42d} means to delay for 42 days.  Available letters are @code{m}
+(minutes), @code{h} (hours), @code{d} (days), @code{w} (weeks), @code{M}
+(months) and @code{Y} (years).
+
+@item
+A specific date.  Looks like @code{YYYY-MM-DD}.  The message will be
+delayed until that day, at a specific time (eight o'clock by default).
+See also @code{gnus-delay-default-hour}.
+
+@item
+A specific time of day.  Given in @code{hh:mm} format, 24h, no am/pm
+stuff.  The deadline will be at that time today, except if that time has
+already passed, then it's at the given time tomorrow.  So if it's ten
+o'clock in the morning and you specify @code{11:15}, then the deadline
+is one hour and fifteen minutes hence.  But if you specify @code{9:20},
+that means a time tomorrow.
+@end itemize
+
+The action of the @code{gnus-delay-article} command is influenced by a
+couple of variables:
+
+@table @code
+@item gnus-delay-default-hour
+@vindex gnus-delay-default-hour
+When you specify a specific date, the message will be due on that hour
+on the given date.  Possible values are integers 0 through 23.
+
+@item gnus-delay-default-delay
+@vindex gnus-delay-default-delay
+This is a string and gives the default delay.  It can be of any of the
+formats described above.
+
+@item gnus-delay-group
+@vindex gnus-delay-group
+Delayed articles will be kept in this group on the drafts server until
+they are due.  You probably don't need to change this.  The default
+value is @code{"delayed"}.
+
+@item gnus-delay-header
+@vindex gnus-delay-header
+The deadline for each article will be stored in a header.  This variable
+is a string and gives the header name.  You probably don't need to
+change this.  The default value is @code{"X-Gnus-Delayed"}.
+@end table
+
+The way delaying works is like this: when you use the
+@code{gnus-delay-article} command, you give a certain delay.  Gnus
+calculates the deadline of the message and stores it in the
+@code{X-Gnus-Delayed} header and puts the message in the
+@code{nndraft:delayed} group.
+
+@findex gnus-delay-send-queue
+And whenever you get new news, Gnus looks through the group for articles
+which are due and sends them.  It uses the @code{gnus-delay-send-queue}
+function for this.  By default, this function is added to the hook
+@code{gnus-get-new-news-hook}.  But of course, you can change this.
+Maybe you want to use the demon to send drafts?  Just tell the demon to
+execute the @code{gnus-delay-send-queue} function.
+
+@table @code
+@item gnus-delay-initialize
+@findex gnus-delay-initialize
+
+By default, this function installs @code{gnus-delay-send-queue} in
+@code{gnus-get-new-news-hook}.  But it accepts the optional second
+argument @code{no-check}.  If it is non-@code{nil},
+@code{gnus-get-new-news-hook} is not changed.  The optional first
+argument is ignored.
+
+For example, @code{(gnus-delay-initialize nil t)} means to do nothing.
+Presumably, you want to use the demon for sending due delayed articles.
+Just don't forget to set that up :-)
+@end table
+
 
 @node Marking Articles
 @section Marking Articles
@@ -3948,7 +5690,7 @@ Just remember, kids: There is no 'c' in 'supersede'.
 @cindex article ticking
 @cindex marks
 
-There are several marks you can set on an article. 
+There are several marks you can set on an article.
 
 You have marks that decide the @dfn{readedness} (whoo, neato-keano
 neologism ohoy!) of the article.  Alphabetic marks generally mean
@@ -3957,9 +5699,9 @@ neologism ohoy!) of the article.  Alphabetic marks generally mean
 In addition, you also have marks that do not affect readedness.
 
 @menu
-* Unread Articles::      Marks for unread articles.
-* Read Articles::        Marks for read articles.
-* Other Marks::          Marks that do not affect readedness.
+* Unread Articles::             Marks for unread articles.
+* Read Articles::               Marks for read articles.
+* Other Marks::                 Marks that do not affect readedness.
 @end menu
 
 @ifinfo
@@ -3967,8 +5709,9 @@ There's a plethora of commands for manipulating these marks:
 @end ifinfo
 
 @menu
-* Setting Marks::           How to set and remove marks.
-* Setting Process Marks::   How to mark articles for later processing.
+* Setting Marks::             How to set and remove marks.
+* Generic Marking Commands::  How to customize the marking.
+* Setting Process Marks::     How to mark articles for later processing.
 @end menu
 
 
@@ -3986,21 +5729,24 @@ Marked as ticked (@code{gnus-ticked-mark}).
 @dfn{Ticked articles} are articles that will remain visible always.  If
 you see an article that you find interesting, or you want to put off
 reading it, or replying to it, until sometime later, you'd typically
-tick it.  However, articles can be expired, so if you want to keep an
-article forever, you'll have to make it persistent (@pxref{Persistent
-Articles}).  
+tick it.  However, articles can be expired (from news servers by the
+news server software, Gnus itself never expires ticked messages), so if
+you want to keep an article forever, you'll have to make it persistent
+(@pxref{Persistent Articles}).
 
 @item ?
 @vindex gnus-dormant-mark
-Marked as dormant (@code{gnus-dormant-mark}).  
+Marked as dormant (@code{gnus-dormant-mark}).
 
 @dfn{Dormant articles} will only appear in the summary buffer if there
 are followups to it.  If you want to see them even if they don't have
 followups, you can use the @kbd{/ D} command (@pxref{Limiting}).
+Otherwise (except for the visibility issue), they are just like ticked
+messages.
 
 @item SPACE
 @vindex gnus-unread-mark
-Markes as unread (@code{gnus-unread-mark}).
+Marked as unread (@code{gnus-unread-mark}).
 
 @dfn{Unread articles} are articles that haven't been read at all yet.
 @end table
@@ -4050,7 +5796,7 @@ Canceled article (@code{gnus-canceled-mark})
 
 @item F
 @vindex gnus-souped-mark
-@sc{SOUP}ed article (@code{gnus-souped-mark}).  @xref{SOUP}.
+@sc{soup}ed article (@code{gnus-souped-mark}).  @xref{SOUP}.
 
 @item Q
 @vindex gnus-sparse-mark
@@ -4060,7 +5806,7 @@ Threading}.
 @item M
 @vindex gnus-duplicate-mark
 Article marked as read by duplicate suppression
-(@code{gnus-duplicated-mark}).  @xref{Duplicate Suppression}.
+(@code{gnus-duplicate-mark}).  @xref{Duplicate Suppression}.
 
 @end table
 
@@ -4077,7 +5823,7 @@ Marked as expirable (@code{gnus-expirable-mark}).
 Marking articles as @dfn{expirable} (or have them marked as such
 automatically) doesn't make much sense in normal groups---a user doesn't
 control expiring of news articles, but in mail groups, for instance,
-articles marked as @dfn{expirable} can be deleted by Gnus at
+articles marked as @dfn{expirable} can be deleted by gnus at
 any time.
 @end table
 
@@ -4092,12 +5838,12 @@ read or not.
 
 @itemize @bullet
 
-@item 
+@item
 You can set a bookmark in the current article.  Say you are reading a
 long thesis on cats' urinary tracts, and have to go home for dinner
 before you've finished reading the thesis.  You can then set a bookmark
-in the article, and Gnus will jump to this bookmark the next time it
-encounters the article.  @xref{Setting Marks}
+in the article, and gnus will jump to this bookmark the next time it
+encounters the article.  @xref{Setting Marks}.
 
 @item
 @vindex gnus-replied-mark
@@ -4105,25 +5851,69 @@ All articles that you have replied to or made a followup to (i.e., have
 answered) will be marked with an @samp{A} in the second column
 (@code{gnus-replied-mark}).
 
-@item 
+@item
+@vindex gnus-forwarded-mark
+All articles that you have forwarded will be marked with an @samp{F} in
+the second column (@code{gnus-forwarded-mark}).
+
+@item
 @vindex gnus-cached-mark
 Articles stored in the article cache will be marked with an @samp{*} in
-the second column (@code{gnus-cached-mark}).  @xref{Article Caching}
+the second column (@code{gnus-cached-mark}).  @xref{Article Caching}.
 
-@item 
+@item
 @vindex gnus-saved-mark
 Articles ``saved'' (in some manner or other; not necessarily
 religiously) are marked with an @samp{S} in the second column
 (@code{gnus-saved-mark}).
 
-@item 
+@item
+@vindex gnus-recent-mark
+Articles that according to the server haven't been shown to the user
+before are marked with a @samp{N} in the second column
+(@code{gnus-recent-mark}).  Note that not all servers support this
+mark, in which case it simply never appears.  Compare with
+@code{gnus-unseen-mark}.
+
+@item
+@vindex gnus-unseen-mark
+Articles that haven't been seen before in Gnus by the user are marked
+with a @samp{.} in the second column (@code{gnus-unseen-mark}).
+Compare with @code{gnus-recent-mark}.
+
+@item
+@vindex gnus-downloaded-mark
+When using the Gnus agent (@pxref{Agent Basics}), articles may be
+downloaded for unplugged (offline) viewing.  If you are using the
+@samp{%O} spec, these articles get the @samp{+} mark in that spec.
+(The variable @code{gnus-downloaded-mark} controls which character to
+use.)
+
+@item
+@vindex gnus-undownloaded-mark
+When using the Gnus agent (@pxref{Agent Basics}), some articles might
+not have been downloaded.  Such articles cannot be viewed while you
+are unplugged (offline).  If you are using the @samp{%O} spec, these
+articles get the @samp{-} mark in that spec.  (The variable
+@code{gnus-undownloaded-mark} controls which character to use.)
+
+@item
+@vindex gnus-downloadable-mark
+The Gnus agent (@pxref{Agent Basics}) downloads some articles
+automatically, but it is also possible to explicitly mark articles for
+download, even if they would not be downloaded automatically.  Such
+explicitly-marked articles get the @samp{%} mark in the first column.
+(The variable @code{gnus-downloadable-mark} controls which character to
+use.)
+
+@item
 @vindex gnus-not-empty-thread-mark
 @vindex gnus-empty-thread-mark
 If the @samp{%e} spec is used, the presence of threads or not will be
 marked with @code{gnus-not-empty-thread-mark} and
 @code{gnus-empty-thread-mark} in the third column, respectively.
 
-@item 
+@item
 @vindex gnus-process-mark
 Finally we have the @dfn{process mark} (@code{gnus-process-mark}).  A
 variety of commands react to the presence of the process mark.  For
@@ -4165,7 +5955,7 @@ article as unread.
 @kindex M t (Summary)
 @findex gnus-summary-tick-article-forward
 Tick the current article (@code{gnus-summary-tick-article-forward}).
-@xref{Article Caching} 
+@xref{Article Caching}.
 
 @item M ?
 @itemx ?
@@ -4173,7 +5963,7 @@ Tick the current article (@code{gnus-summary-tick-article-forward}).
 @kindex M ? (Summary)
 @findex gnus-summary-mark-as-dormant
 Mark the current article as dormant
-(@code{gnus-summary-mark-as-dormant}).  @xref{Article Caching} 
+(@code{gnus-summary-mark-as-dormant}).  @xref{Article Caching}.
 
 @item M d
 @itemx d
@@ -4204,7 +5994,7 @@ and then select the next unread article
 @kindex C-k (Summary)
 @findex gnus-summary-kill-same-subject
 Mark all articles that have the same subject as the current one as read
-(@code{gnus-summary-kill-same-subject}).  
+(@code{gnus-summary-kill-same-subject}).
 
 @item M C
 @kindex M C (Summary)
@@ -4221,14 +6011,20 @@ articles (@code{gnus-summary-catchup-all}).
 @item M H
 @kindex M H (Summary)
 @findex gnus-summary-catchup-to-here
-Catchup the current group to point
-(@code{gnus-summary-catchup-to-here}). 
+Catchup the current group to point (before the point)
+(@code{gnus-summary-catchup-to-here}).
+
+@item M h
+@kindex M h (Summary)
+@findex gnus-summary-catchup-from-here
+Catchup the current group from point (after the point)
+(@code{gnus-summary-catchup-from-here}).
 
 @item C-w
 @kindex C-w (Summary)
 @findex gnus-summary-mark-region-as-read
 Mark all articles between point and mark as read
-(@code{gnus-summary-mark-region-as-read}). 
+(@code{gnus-summary-mark-region-as-read}).
 
 @item M V k
 @kindex M V k (Summary)
@@ -4286,10 +6082,58 @@ one line up or down.  As a special case, if this variable is
 The default is @code{t}.
 
 
+@node Generic Marking Commands
+@subsection Generic Marking Commands
+
+Some people would like the command that ticks an article (@kbd{!}) go to
+the next article.  Others would like it to go to the next unread
+article.  Yet others would like it to stay on the current article.  And
+even though I haven't heard of anybody wanting it to go to the
+previous (unread) article, I'm sure there are people that want that as
+well.
+
+Multiply these five behaviors with five different marking commands, and
+you get a potentially complex set of variable to control what each
+command should do.
+
+To sidestep that mess, Gnus provides commands that do all these
+different things.  They can be found on the @kbd{M M} map in the summary
+buffer.  Type @kbd{M M C-h} to see them all---there are too many of them
+to list in this manual.
+
+While you can use these commands directly, most users would prefer
+altering the summary mode keymap.  For instance, if you would like the
+@kbd{!} command to go to the next article instead of the next unread
+article, you could say something like:
+
+@lisp
+@group
+(add-hook 'gnus-summary-mode-hook 'my-alter-summary-map)
+(defun my-alter-summary-map ()
+  (local-set-key "!" 'gnus-summary-put-mark-as-ticked-next))
+@end group
+@end lisp
+
+@noindent
+or
+
+@lisp
+(defun my-alter-summary-map ()
+  (local-set-key "!" "MM!n"))
+@end lisp
+
+
 @node Setting Process Marks
 @subsection Setting Process Marks
 @cindex setting process marks
 
+Process marks are displayed as @code{#} in the summary buffer, and are
+used for marking articles in such a way that other commands will
+process these articles.  For instance, if you process mark four
+articles and then use the @kbd{*} command, Gnus will enter these four
+commands into the cache.  For more information,
+@pxref{Process/Prefix}.
+
 @table @kbd
 
 @item M P p
@@ -4298,10 +6142,10 @@ The default is @code{t}.
 @kindex M P p (Summary)
 @findex gnus-summary-mark-as-processable
 Mark the current article with the process mark
-(@code{gnus-summary-mark-as-processable}). 
+(@code{gnus-summary-mark-as-processable}).
 @findex gnus-summary-unmark-as-processable
 
-@item M P u 
+@item M P u
 @itemx M-#
 @kindex M P u (Summary)
 @kindex M-# (Summary)
@@ -4312,24 +6156,36 @@ Remove the process mark, if any, from the current article
 @kindex M P U (Summary)
 @findex gnus-summary-unmark-all-processable
 Remove the process mark from all articles
-(@code{gnus-summary-unmark-all-processable}). 
+(@code{gnus-summary-unmark-all-processable}).
 
 @item M P i
 @kindex M P i (Summary)
 @findex gnus-uu-invert-processable
 Invert the list of process marked articles
-(@code{gnus-uu-invert-processable}). 
+(@code{gnus-uu-invert-processable}).
 
 @item M P R
 @kindex M P R (Summary)
 @findex gnus-uu-mark-by-regexp
-Mark articles by a regular expression (@code{gnus-uu-mark-by-regexp}). 
+Mark articles that have a @code{Subject} header that matches a regular
+expression (@code{gnus-uu-mark-by-regexp}).
+
+@item M P G
+@kindex M P G (Summary)
+@findex gnus-uu-unmark-by-regexp
+Unmark articles that have a @code{Subject} header that matches a regular
+expression (@code{gnus-uu-unmark-by-regexp}).
 
 @item M P r
 @kindex M P r (Summary)
 @findex gnus-uu-mark-region
 Mark articles in region (@code{gnus-uu-mark-region}).
 
+@item M P g
+@kindex M P g (Summary)
+@findex gnus-uu-unmark-region
+Unmark articles in region (@code{gnus-uu-unmark-region}).
+
 @item M P t
 @kindex M P t (Summary)
 @findex gnus-uu-mark-thread
@@ -4368,7 +6224,7 @@ Mark all articles in series order (@code{gnus-uu-mark-series}).
 @kindex M P b (Summary)
 @findex gnus-uu-mark-buffer
 Mark all articles in the buffer in the order they appear
-(@code{gnus-uu-mark-buffer}). 
+(@code{gnus-uu-mark-buffer}).
 
 @item M P k
 @kindex M P k (Summary)
@@ -4390,6 +6246,9 @@ Push the current process mark set onto the stack
 
 @end table
 
+Also see the @kbd{&} command in @ref{Searching for Articles}, for how to
+set process marks based on article body contents.
+
 
 @node Limiting
 @section Limiting
@@ -4398,7 +6257,7 @@ Push the current process mark set onto the stack
 It can be convenient to limit the summary buffer to just show some
 subset of the articles currently in the group.  The effect most limit
 commands have is to remove a few (or many) articles from the summary
-buffer. 
+buffer.
 
 All limiting commands work on subsets of the articles already fetched
 from the servers.  None of these commands query the server for
@@ -4411,13 +6270,23 @@ additional articles.
 @kindex / / (Summary)
 @findex gnus-summary-limit-to-subject
 Limit the summary buffer to articles that match some subject
-(@code{gnus-summary-limit-to-subject}). 
+(@code{gnus-summary-limit-to-subject}).  If given a prefix, exclude
+matching articles.
 
 @item / a
 @kindex / a (Summary)
 @findex gnus-summary-limit-to-author
 Limit the summary buffer to articles that match some author
-(@code{gnus-summary-limit-to-author}).
+(@code{gnus-summary-limit-to-author}).  If given a prefix, exclude
+matching articles.
+
+@item / x
+@kindex / x (Summary)
+@findex gnus-summary-limit-to-extra
+Limit the summary buffer to articles that match one of the ``extra''
+headers (@pxref{To From Newsgroups})
+(@code{gnus-summary-limit-to-extra}).  If given a prefix, exclude
+matching articles.
 
 @item / u
 @itemx x
@@ -4432,14 +6301,14 @@ dormant articles will also be excluded.
 @item / m
 @kindex / m (Summary)
 @findex gnus-summary-limit-to-marks
-Ask for a mark and then limit to all articles that have not been marked
+Ask for a mark and then limit to all articles that have been marked
 with that mark (@code{gnus-summary-limit-to-marks}).
 
 @item / t
 @kindex / t (Summary)
 @findex gnus-summary-limit-to-age
 Ask for a number and then limit the summary buffer to articles older than (or equal to) that number of days
-(@code{gnus-summary-limit-to-marks}).  If given a prefix, limit to
+(@code{gnus-summary-limit-to-age}).  If given a prefix, limit to
 articles younger than that number of days.
 
 @item / n
@@ -4456,48 +6325,87 @@ Pop the previous limit off the stack and restore it
 (@code{gnus-summary-pop-limit}).  If given a prefix, pop all limits off
 the stack.
 
+@item / .
+@kindex / . (Summary)
+@findex gnus-summary-limit-to-unseen
+Limit the summary buffer to the unseen articles
+(@code{gnus-summary-limit-to-unseen}).
+
 @item / v
 @kindex / v (Summary)
 @findex gnus-summary-limit-to-score
 Limit the summary buffer to articles that have a score at or above some
 score (@code{gnus-summary-limit-to-score}).
 
+@item / p
+@kindex / p (Summary)
+@findex gnus-summary-limit-to-display-predicate
+Limit the summary buffer to articles that satisfy the @code{display}
+group parameter predicate
+(@code{gnus-summary-limit-to-display-predicate}).  @xref{Group
+Parameters}, for more on this predicate.
+
 @item / E
 @itemx M S
 @kindex M S (Summary)
 @kindex / E (Summary)
 @findex gnus-summary-limit-include-expunged
-Display all expunged articles
-(@code{gnus-summary-limit-include-expunged}). 
+Include all expunged articles in the limit
+(@code{gnus-summary-limit-include-expunged}).
 
 @item / D
 @kindex / D (Summary)
 @findex gnus-summary-limit-include-dormant
-Display all dormant articles (@code{gnus-summary-limit-include-dormant}).
+Include all dormant articles in the limit
+(@code{gnus-summary-limit-include-dormant}).
+
+@item / *
+@kindex / * (Summary)
+@findex gnus-summary-limit-include-cached
+Include all cached articles in the limit
+(@code{gnus-summary-limit-include-cached}).
 
 @item / d
 @kindex / d (Summary)
 @findex gnus-summary-limit-exclude-dormant
-Hide all dormant articles (@code{gnus-summary-limit-exclude-dormant}).
+Exclude all dormant articles from the limit
+(@code{gnus-summary-limit-exclude-dormant}).
+
+@item / M
+@kindex / M (Summary)
+@findex gnus-summary-limit-exclude-marks
+Exclude all marked articles (@code{gnus-summary-limit-exclude-marks}).
 
 @item / T
 @kindex / T (Summary)
 @findex gnus-summary-limit-include-thread
-Include all the articles in the current thread.
+Include all the articles in the current thread in the limit.
 
 @item / c
 @kindex / c (Summary)
 @findex gnus-summary-limit-exclude-childless-dormant
-Hide all dormant articles that have no children
-(@code{gnus-summary-limit-exclude-childless-dormant}). 
+Exclude all dormant articles that have no children from the limit@*
+(@code{gnus-summary-limit-exclude-childless-dormant}).
 
 @item / C
 @kindex / C (Summary)
 @findex gnus-summary-limit-mark-excluded-as-read
 Mark all excluded unread articles as read
-(@code{gnus-summary-limit-mark-excluded-as-read}).   If given a prefix,
+(@code{gnus-summary-limit-mark-excluded-as-read}).  If given a prefix,
 also mark excluded ticked and dormant articles as read.
 
+@item / N
+@kindex / N (Summary)
+@findex gnus-summary-insert-new-articles
+Insert all new articles in the summary buffer.  It scans for new emails
+if @var{back-end}@code{-get-new-mail} is non-@code{nil}.
+
+@item / o
+@kindex / o (Summary)
+@findex gnus-summary-insert-old-articles
+Insert all old articles in the summary buffer.  If given a numbered
+prefix, fetch this number of articles.
+
 @end table
 
 
@@ -4513,10 +6421,10 @@ hierarchical fashion.
 Threading is done by looking at the @code{References} headers of the
 articles.  In a perfect world, this would be enough to build pretty
 trees, but unfortunately, the @code{References} header is often broken
-or simply missing.  Weird news propagration excarcerbates the problem,
+or simply missing.  Weird news propagation exacerbates the problem,
 so one has to employ other heuristics to get pleasing results.  A
 plethora of approaches exists, as detailed in horrible detail in
-@pxref{Customizing Threading}. 
+@ref{Customizing Threading}.
 
 First, a quick overview of the concepts:
 
@@ -4533,7 +6441,7 @@ A small(er) section of this tree-like structure.
 @item loose threads
 Threads often lose their roots due to article expiry, or due to the root
 already having been read in a previous session, and not displayed in the
-summary buffer.  We then typicall have many sub-threads that really
+summary buffer.  We then typically have many sub-threads that really
 belong to one thread, but are without connecting roots.  These are
 called loose threads.
 
@@ -4548,8 +6456,8 @@ displayed as empty lines in the summary buffer.
 
 
 @menu
-* Customizing Threading::     Variables you can change to affect the threading.
-* Thread Commands::           Thread based commands in the summary buffer.
+* Customizing Threading::       Variables you can change to affect the threading.
+* Thread Commands::             Thread based commands in the summary buffer.
 @end menu
 
 
@@ -4558,10 +6466,10 @@ displayed as empty lines in the summary buffer.
 @cindex customizing threading
 
 @menu
-* Loose Threads::        How Gnus gathers loose threads into bigger threads.
-* Filling In Threads::   Making the threads displayed look fuller.
-* More Threading::       Even more variables for fiddling with threads.
-* Low-Level Threading::  You thought it was over... but you were wrong!
+* Loose Threads::               How Gnus gathers loose threads into bigger threads.
+* Filling In Threads::          Making the threads displayed look fuller.
+* More Threading::              Even more variables for fiddling with threads.
+* Low-Level Threading::         You thought it was over@dots{} but you were wrong!
 @end menu
 
 
@@ -4574,22 +6482,22 @@ displayed as empty lines in the summary buffer.
 @table @code
 @item gnus-summary-make-false-root
 @vindex gnus-summary-make-false-root
-If non-@code{nil}, Gnus will gather all loose subtrees into one big tree
+If non-@code{nil}, gnus will gather all loose subtrees into one big tree
 and create a dummy root at the top.  (Wait a minute.  Root at the top?
 Yup.)  Loose subtrees occur when the real root has expired, or you've
 read or killed the root in a previous session.
 
-When there is no real root of a thread, Gnus will have to fudge
-something.  This variable says what fudging method Gnus should use.
+When there is no real root of a thread, gnus will have to fudge
+something.  This variable says what fudging method gnus should use.
 There are four possible values:
 
 @iftex
 @iflatex
 \gnusfigure{The Summary Buffer}{390}{
-\put(0,0){\epsfig{figure=tmp/summary-adopt.ps,width=7.5cm}}
-\put(445,0){\makebox(0,0)[br]{\epsfig{figure=tmp/summary-empty.ps,width=7.5cm}}}
-\put(0,400){\makebox(0,0)[tl]{\epsfig{figure=tmp/summary-none.ps,width=7.5cm}}}
-\put(445,400){\makebox(0,0)[tr]{\epsfig{figure=tmp/summary-dummy.ps,width=7.5cm}}}
+\put(0,0){\epsfig{figure=ps/summary-adopt,width=7.5cm}}
+\put(445,0){\makebox(0,0)[br]{\epsfig{figure=ps/summary-empty,width=7.5cm}}}
+\put(0,400){\makebox(0,0)[tl]{\epsfig{figure=ps/summary-none,width=7.5cm}}}
+\put(445,400){\makebox(0,0)[tr]{\epsfig{figure=ps/summary-dummy,width=7.5cm}}}
 }
 @end iflatex
 @end iftex
@@ -4606,12 +6514,15 @@ square brackets (@samp{[]}).  This is the default method.
 
 @item dummy
 @vindex gnus-summary-dummy-line-format
+@vindex gnus-summary-make-false-root-always
 Gnus will create a dummy summary line that will pretend to be the
 parent.  This dummy line does not correspond to any real article, so
 selecting it will just select the first real article after the dummy
 article.  @code{gnus-summary-dummy-line-format} is used to specify the
 format of the dummy roots.  It accepts only one format spec:  @samp{S},
 which is the subject of the article.  @xref{Formatting Variables}.
+If you want all threads to have a dummy root, even the non-gathered
+ones, set @code{gnus-summary-make-false-root-always} to @code{t}.
 
 @item empty
 Gnus won't actually make any article the parent, but simply leave the
@@ -4630,19 +6541,19 @@ Don't gather loose threads.
 @item gnus-summary-gather-subject-limit
 @vindex gnus-summary-gather-subject-limit
 Loose threads are gathered by comparing subjects of articles.  If this
-variable is @code{nil}, Gnus requires an exact match between the
+variable is @code{nil}, gnus requires an exact match between the
 subjects of the loose threads before gathering them into one big
 super-thread.  This might be too strict a requirement, what with the
 presence of stupid newsreaders that chop off long subject lines.  If
 you think so, set this variable to, say, 20 to require that only the
 first 20 characters of the subjects have to match.  If you set this
-variable to a really low number, you'll find that Gnus will gather
+variable to a really low number, you'll find that gnus will gather
 everything in sight into one thread, which isn't very helpful.
 
 @cindex fuzzy article gathering
-If you set this variable to the special value @code{fuzzy}, Gnus will
+If you set this variable to the special value @code{fuzzy}, gnus will
 use a fuzzy string comparison algorithm on the subjects (@pxref{Fuzzy
-Matching}). 
+Matching}).
 
 @item gnus-simplify-subject-fuzzy-regexp
 @vindex gnus-simplify-subject-fuzzy-regexp
@@ -4658,13 +6569,13 @@ as 10, you might consider setting this variable to something sensible:
 @c Written by Michael Ernst <mernst@cs.rice.edu>
 @lisp
 (setq gnus-simplify-ignored-prefixes
-      (concat 
+      (concat
        "\\`\\[?\\("
-       (mapconcat 
+       (mapconcat
         'identity
         '("looking"
           "wanted" "followup" "summary\\( of\\)?"
-          "help" "query" "problem" "question" 
+          "help" "query" "problem" "question"
           "answer" "reference" "announce"
           "How can I" "How to" "Comparison of"
           ;; ...
@@ -4678,7 +6589,7 @@ as 10, you might consider setting this variable to something sensible:
 @end lisp
 
 All words that match this regexp will be removed before comparing two
-subjects. 
+subjects.
 
 @item gnus-simplify-subject-functions
 @vindex gnus-simplify-subject-functions
@@ -4701,6 +6612,10 @@ Simplify fuzzily.
 @item gnus-simplify-whitespace
 @findex gnus-simplify-whitespace
 Remove excessive whitespace.
+
+@item gnus-simplify-all-whitespace
+@findex gnus-simplify-all-whitespace
+Remove all whitespace.
 @end table
 
 You may also write your own functions, of course.
@@ -4713,7 +6628,7 @@ to many false hits, especially with certain common subjects like
 @samp{} and @samp{(none)}.  To make the situation slightly better,
 you can use the regexp @code{gnus-summary-gather-exclude-subject} to say
 what subjects should be excluded from the gathering process.@*
-The default is @samp{^ *$\\|^(none)$}.  
+The default is @samp{^ *$\\|^(none)$}.
 
 @item gnus-summary-thread-gathering-function
 @vindex gnus-summary-thread-gathering-function
@@ -4754,20 +6669,26 @@ something like:
 @table @code
 @item gnus-fetch-old-headers
 @vindex gnus-fetch-old-headers
-If non-@code{nil}, Gnus will attempt to build old threads by fetching
-more old headers---headers to articles marked as read.  If you
-would like to display as few summary lines as possible, but still
-connect as many loose threads as possible, you should set this variable
-to @code{some} or a number.  If you set it to a number, no more than
-that number of extra old headers will be fetched.  In either case,
-fetching old headers only works if the backend you are using carries
-overview files---this would normally be @code{nntp}, @code{nnspool} and
-@code{nnml}.  Also remember that if the root of the thread has been
-expired by the server, there's not much Gnus can do about that.
+If non-@code{nil}, gnus will attempt to build old threads by fetching
+more old headers---headers to articles marked as read.  If you would
+like to display as few summary lines as possible, but still connect as
+many loose threads as possible, you should set this variable to
+@code{some} or a number.  If you set it to a number, no more than that
+number of extra old headers will be fetched.  In either case, fetching
+old headers only works if the back end you are using carries overview
+files---this would normally be @code{nntp}, @code{nnspool},
+@code{nnml}, and @code{nnmaildir}.  Also remember that if the root of
+the thread has been expired by the server, there's not much Gnus can
+do about that.
 
 This variable can also be set to @code{invisible}.  This won't have any
 visible effects, but is useful if you use the @kbd{A T} command a lot
-(@pxref{Finding the Parent}). 
+(@pxref{Finding the Parent}).
+
+@item gnus-fetch-old-ephemeral-headers
+@vindex gnus-fetch-old-ephemeral-headers
+Same as @code{gnus-fetch-old-headers}, but only used for ephemeral
+newsgroups.
 
 @item gnus-build-sparse-threads
 @vindex gnus-build-sparse-threads
@@ -4775,15 +6696,27 @@ Fetching old headers can be slow.  A low-rent similar effect can be
 gotten by setting this variable to @code{some}.  Gnus will then look at
 the complete @code{References} headers of all articles and try to string
 together articles that belong in the same thread.  This will leave
-@dfn{gaps} in the threading display where Gnus guesses that an article
+@dfn{gaps} in the threading display where gnus guesses that an article
 is missing from the thread.  (These gaps appear like normal summary
-lines.  If you select a gap, Gnus will try to fetch the article in
-question.)  If this variable is @code{t}, Gnus will display all these
+lines.  If you select a gap, gnus will try to fetch the article in
+question.)  If this variable is @code{t}, gnus will display all these
 ``gaps'' without regard for whether they are useful for completing the
-thread or not.  Finally, if this variable is @code{more}, Gnus won't cut
+thread or not.  Finally, if this variable is @code{more}, gnus won't cut
 off sparse leaf nodes that don't lead anywhere.  This variable is
 @code{nil} by default.
 
+@item gnus-read-all-available-headers
+@vindex gnus-read-all-available-headers
+This is a rather obscure variable that few will find useful.  It's
+intended for those non-news newsgroups where the back end has to fetch
+quite a lot to present the summary buffer, and where it's impossible to
+go back to parents of articles.  This is mostly the case in the
+web-based groups, like the @code{nnultimate} groups.
+
+If you don't use those, then it's safe to leave this as the default
+@code{nil}.  If you want to use this variable, it should be a regexp
+that matches the group name, or @code{t} for all groups.
+
 @end table
 
 
@@ -4803,6 +6736,22 @@ slower and more awkward.
 If non-@code{nil}, all threads will be hidden when the summary buffer is
 generated.
 
+This can also be a predicate specifier (@pxref{Predicate Specifiers}).
+Available predicates are @code{gnus-article-unread-p} and
+@code{gnus-article-unseen-p}.
+
+Here's an example:
+
+@lisp
+(setq gnus-thread-hide-subtree
+      '(or gnus-article-unread-p
+           gnus-article-unseen-p))
+@end lisp
+
+(It's a pretty nonsensical example, since all unseen articles are also
+unread, but you get my drift.)
+
+
 @item gnus-thread-expunge-below
 @vindex gnus-thread-expunge-below
 All threads that have a total score (as defined by
@@ -4818,15 +6767,27 @@ will be hidden.
 @item gnus-thread-ignore-subject
 @vindex gnus-thread-ignore-subject
 Sometimes somebody changes the subject in the middle of a thread.  If
-this variable is non-@code{nil}, the subject change is ignored.  If it
-is @code{nil}, which is the default, a change in the subject will result
-in a new thread.
+this variable is non-@code{nil}, which is the default, the subject
+change is ignored.  If it is @code{nil}, a change in the subject will
+result in a new thread.
 
 @item gnus-thread-indent-level
 @vindex gnus-thread-indent-level
 This is a number that says how much each sub-thread should be indented.
 The default is 4.
 
+@item gnus-sort-gathered-threads-function
+@vindex gnus-sort-gathered-threads-function
+Sometimes, particularly with mailing lists, the order in which mails
+arrive locally is not necessarily the same as the order in which they
+arrived on the mailing list.  Consequently, when sorting sub-threads
+using the default @code{gnus-thread-sort-by-number}, responses can end
+up appearing before the article to which they are responding to.
+Setting this variable to an alternate value
+(e.g. @code{gnus-thread-sort-by-date}), in a group's parameters or in an
+appropriate hook (e.g. @code{gnus-summary-generate-hook}) can produce a
+more logical sub-thread ordering in such instances.
+
 @end table
 
 
@@ -4838,9 +6799,9 @@ The default is 4.
 @item gnus-parse-headers-hook
 @vindex gnus-parse-headers-hook
 Hook run before parsing any headers.  The default value is
-@code{(gnus-decode-rfc1522)}, which means that QPized headers will be
-slightly decoded in a hackish way.  This is likely to change in the
-future when Gnus becomes @sc{MIME}ified.
+@code{(gnus-set-summary-default-charset)}, which sets up local value of
+@code{default-mime-charset} in summary buffer based on variable
+@code{gnus-newsgroup-default-charset-alist}.
 
 @item gnus-alter-header-function
 @vindex gnus-alter-header-function
@@ -4874,9 +6835,9 @@ meaningful.  Here's one example:
 @table @kbd
 
 @item T k
-@itemx M-C-k
+@itemx C-M-k
 @kindex T k (Summary)
-@kindex M-C-k (Summary)
+@kindex C-M-k (Summary)
 @findex gnus-summary-kill-thread
 Mark all articles in the current (sub-)thread as read
 (@code{gnus-summary-kill-thread}).  If the prefix argument is positive,
@@ -4884,12 +6845,12 @@ remove all marks instead.  If the prefix argument is negative, tick
 articles instead.
 
 @item T l
-@itemx M-C-l
+@itemx C-M-l
 @kindex T l (Summary)
-@kindex M-C-l (Summary)
+@kindex C-M-l (Summary)
 @findex gnus-summary-lower-thread
 Lower the score of the current (sub-)thread
-(@code{gnus-summary-lower-thread}). 
+(@code{gnus-summary-lower-thread}).
 
 @item T i
 @kindex T i (Summary)
@@ -4917,7 +6878,7 @@ Toggle threading (@code{gnus-summary-toggle-threads}).
 @item T s
 @kindex T s (Summary)
 @findex gnus-summary-show-thread
-Expose the (sub-)thread hidden under the current article, if any
+Expose the (sub-)thread hidden under the current article, if any@*
 (@code{gnus-summary-show-thread}).
 
 @item T h
@@ -4957,11 +6918,19 @@ understand the numeric prefix.
 
 @item T n
 @kindex T n (Summary)
+@itemx C-M-f
+@kindex C-M-n (Summary)
+@itemx M-down
+@kindex M-down (Summary)
 @findex gnus-summary-next-thread
 Go to the next thread (@code{gnus-summary-next-thread}).
 
 @item T p
 @kindex T p (Summary)
+@itemx C-M-b
+@kindex C-M-p (Summary)
+@itemx M-up
+@kindex M-up (Summary)
 @findex gnus-summary-prev-thread
 Go to the previous thread (@code{gnus-summary-prev-thread}).
 
@@ -4981,10 +6950,10 @@ Ascend the thread (@code{gnus-summary-up-thread}).
 Go to the top of the thread (@code{gnus-summary-top-thread}).
 @end table
 
-@vindex gnus-thread-operation-ignore-subject 
+@vindex gnus-thread-operation-ignore-subject
 If you ignore subject while threading, you'll naturally end up with
 threads that have several different subjects in them.  If you then issue
-a command like `T k' (@code{gnus-summary-kill-thread}) you might not
+a command like @kbd{T k} (@code{gnus-summary-kill-thread}) you might not
 wish to kill the entire thread, but just those parts of the thread that
 have the same subject as the current article.  If you like this idea,
 you can fiddle with @code{gnus-thread-operation-ignore-subject}.  If it
@@ -4996,8 +6965,8 @@ that have subjects fuzzily equal will be included (@pxref{Fuzzy
 Matching}).
 
 
-@node Sorting
-@section Sorting
+@node Sorting the Summary Buffer
+@section Sorting the Summary Buffer
 
 @findex gnus-thread-sort-by-total-score
 @findex gnus-thread-sort-by-date
@@ -5005,33 +6974,43 @@ Matching}).
 @findex gnus-thread-sort-by-subject
 @findex gnus-thread-sort-by-author
 @findex gnus-thread-sort-by-number
+@findex gnus-thread-sort-by-random
 @vindex gnus-thread-sort-functions
+@findex gnus-thread-sort-by-most-recent-number
+@findex gnus-thread-sort-by-most-recent-date
 If you are using a threaded summary display, you can sort the threads by
-setting @code{gnus-thread-sort-functions}, which is a list of functions.
+setting @code{gnus-thread-sort-functions}, which can be either a single
+function, a list of functions, or a list containing functions and
+@code{(not some-function)} elements.
+
 By default, sorting is done on article numbers.  Ready-made sorting
 predicate functions include @code{gnus-thread-sort-by-number},
 @code{gnus-thread-sort-by-author}, @code{gnus-thread-sort-by-subject},
-@code{gnus-thread-sort-by-date}, @code{gnus-thread-sort-by-score}, and
+@code{gnus-thread-sort-by-date}, @code{gnus-thread-sort-by-score},
+@code{gnus-thread-sort-by-most-recent-number},
+@code{gnus-thread-sort-by-most-recent-date},
+@code{gnus-thread-sort-by-random} and
 @code{gnus-thread-sort-by-total-score}.
 
 Each function takes two threads and returns non-@code{nil} if the first
 thread should be sorted before the other.  Note that sorting really is
-normally done by looking only at the roots of each thread.  If you use
-more than one function, the primary sort key should be the last function
-in the list.  You should probably always include
+normally done by looking only at the roots of each thread.
+
+If you use more than one function, the primary sort key should be the
+last function in the list.  You should probably always include
 @code{gnus-thread-sort-by-number} in the list of sorting
 functions---preferably first.  This will ensure that threads that are
 equal with respect to the other sort criteria will be displayed in
 ascending article order.
 
-If you would like to sort by score, then by subject, and finally by
-number, you could do something like:
+If you would like to sort by reverse score, then by subject, and finally
+by number, you could do something like:
 
 @lisp
-(setq gnus-thread-sort-functions 
+(setq gnus-thread-sort-functions
       '(gnus-thread-sort-by-number
         gnus-thread-sort-by-subject
-        gnus-thread-sort-by-total-score))
+        (not gnus-thread-sort-by-total-score)))
 @end lisp
 
 The threads that have highest score will be displayed first in the
@@ -5061,20 +7040,24 @@ tickles your fancy.
 @findex gnus-article-sort-by-score
 @findex gnus-article-sort-by-subject
 @findex gnus-article-sort-by-author
+@findex gnus-article-sort-by-random
 @findex gnus-article-sort-by-number
-If you are using an unthreaded display for some strange reason or other,
-you have to fiddle with the @code{gnus-article-sort-functions} variable.
-It is very similar to the @code{gnus-thread-sort-functions}, except that
-it uses slightly different functions for article comparison.  Available
-sorting predicate functions are @code{gnus-article-sort-by-number},
-@code{gnus-article-sort-by-author}, @code{gnus-article-sort-by-subject},
-@code{gnus-article-sort-by-date}, and @code{gnus-article-sort-by-score}.
+If you are using an unthreaded display for some strange reason or
+other, you have to fiddle with the @code{gnus-article-sort-functions}
+variable.  It is very similar to the
+@code{gnus-thread-sort-functions}, except that it uses slightly
+different functions for article comparison.  Available sorting
+predicate functions are @code{gnus-article-sort-by-number},
+@code{gnus-article-sort-by-author},
+@code{gnus-article-sort-by-subject}, @code{gnus-article-sort-by-date},
+@code{gnus-article-sort-by-random}, and
+@code{gnus-article-sort-by-score}.
 
 If you want to sort an unthreaded summary display by subject, you could
 say something like:
 
 @lisp
-(setq gnus-article-sort-functions 
+(setq gnus-article-sort-functions
       '(gnus-article-sort-by-number
         gnus-article-sort-by-subject))
 @end lisp
@@ -5087,33 +7070,33 @@ say something like:
 @cindex article pre-fetch
 @cindex pre-fetch
 
-If you read your news from an @sc{nntp} server that's far away, the
+If you read your news from an @acronym{NNTP} server that's far away, the
 network latencies may make reading articles a chore.  You have to wait
 for a while after pressing @kbd{n} to go to the next article before the
-article appears.  Why can't Gnus just go ahead and fetch the article
+article appears.  Why can't gnus just go ahead and fetch the article
 while you are reading the previous one?  Why not, indeed.
 
 First, some caveats.  There are some pitfalls to using asynchronous
-article fetching, especially the way Gnus does it.  
+article fetching, especially the way gnus does it.
 
 Let's say you are reading article 1, which is short, and article 2 is
 quite long, and you are not interested in reading that.  Gnus does not
 know this, so it goes ahead and fetches article 2.  You decide to read
-article 3, but since Gnus is in the process of fetching article 2, the
+article 3, but since gnus is in the process of fetching article 2, the
 connection is blocked.
 
-To avoid these situations, Gnus will open two (count 'em two)
+To avoid these situations, gnus will open two (count 'em two)
 connections to the server.  Some people may think this isn't a very nice
 thing to do, but I don't see any real alternatives.  Setting up that
-extra connection takes some time, so Gnus startup will be slower.
+extra connection takes some time, so gnus startup will be slower.
 
 Gnus will fetch more articles than you will read.  This will mean that
-the link between your machine and the @sc{nntp} server will become more
+the link between your machine and the @acronym{NNTP} server will become more
 loaded than if you didn't use article pre-fetch.  The server itself will
 also become more loaded---both with the extra article requests, and the
 extra connection.
 
-Ok, so now you know that you shouldn't really use this thing...  unless
+Ok, so now you know that you shouldn't really use this thing@dots{} unless
 you really want to.
 
 @vindex gnus-asynchronous
@@ -5123,21 +7106,23 @@ happen automatically.
 @vindex gnus-use-article-prefetch
 You can control how many articles are to be pre-fetched by setting
 @code{gnus-use-article-prefetch}.  This is 30 by default, which means
-that when you read an article in the group, the backend will pre-fetch
-the next 30 articles.  If this variable is @code{t}, the backend will
+that when you read an article in the group, the back end will pre-fetch
+the next 30 articles.  If this variable is @code{t}, the back end will
 pre-fetch all the articles it can without bound.  If it is
 @code{nil}, no pre-fetching will be done.
 
 @vindex gnus-async-prefetch-article-p
 @findex gnus-async-read-p
 There are probably some articles that you don't want to pre-fetch---read
-articles, for instance.  The @code{gnus-async-prefetch-article-p} variable controls whether an article is to be pre-fetched.  This function should
-return non-@code{nil} when the article in question is to be
-pre-fetched.  The default is @code{gnus-async-read-p}, which returns
-@code{nil} on read articles.  The function is called with an article
-data structure as the only parameter.
+articles, for instance.  The @code{gnus-async-prefetch-article-p}
+variable controls whether an article is to be pre-fetched.  This
+function should return non-@code{nil} when the article in question is
+to be pre-fetched.  The default is @code{gnus-async-read-p}, which
+returns @code{nil} on read articles.  The function is called with an
+article data structure as the only parameter.
 
-If, for instance, you wish to pre-fetch only unread articles shorter than 100 lines, you could say something like:
+If, for instance, you wish to pre-fetch only unread articles shorter
+than 100 lines, you could say something like:
 
 @lisp
 (defun my-async-short-unread-p (data)
@@ -5150,7 +7135,7 @@ If, for instance, you wish to pre-fetch only unread articles shorter than 100 li
 @end lisp
 
 These functions will be called many, many times, so they should
-preferably be short and sweet to avoid slowing down Gnus too much.
+preferably be short and sweet to avoid slowing down gnus too much.
 It's probably a good idea to byte-compile things like this.
 
 @vindex gnus-prefetched-article-deletion-strategy
@@ -5168,9 +7153,9 @@ Remove articles when exiting the group.
 
 The default value is @code{(read exit)}.
 
-@vindex gnus-use-header-prefetch
-If @code{gnus-use-header-prefetch} is non-@code{nil}, prefetch articles
-from the next group.
+@c @vindex gnus-use-header-prefetch
+@c If @code{gnus-use-header-prefetch} is non-@code{nil}, prefetch articles
+@c from the next group.
 
 
 @node Article Caching
@@ -5178,7 +7163,7 @@ from the next group.
 @cindex article caching
 @cindex caching
 
-If you have an @emph{extremely} slow @sc{nntp} connection, you may
+If you have an @emph{extremely} slow @acronym{NNTP} connection, you may
 consider turning article caching on.  Each article will then be stored
 locally under your home directory.  As you may surmise, this could
 potentially use @emph{huge} amounts of disk space, as well as eat up all
@@ -5192,7 +7177,7 @@ Used carefully, though, it could be just an easier way to save articles.
 To turn caching on, set @code{gnus-use-cache} to @code{t}.  By default,
 all articles ticked or marked as dormant will then be copied
 over to your local cache (@code{gnus-cache-directory}).  Whether this
-cache is flat or hierarchal is controlled by the
+cache is flat or hierarchical is controlled by the
 @code{gnus-use-long-file-name} variable, as usual.
 
 When re-selecting a ticked or dormant article, it will be fetched from the
@@ -5219,32 +7204,40 @@ So where does the massive article-fetching and storing come into the
 picture?  The @code{gnus-jog-cache} command will go through all
 subscribed newsgroups, request all unread articles, score them, and
 store them in the cache.  You should only ever, ever ever ever, use this
-command if 1) your connection to the @sc{nntp} server is really, really,
+command if 1) your connection to the @acronym{NNTP} server is really, really,
 really slow and 2) you have a really, really, really huge disk.
 Seriously.  One way to cut down on the number of articles downloaded is
 to score unwanted articles down and have them marked as read.  They will
 not then be downloaded by this command.
 
 @vindex gnus-uncacheable-groups
-It is likely that you do not want caching on some groups.  For instance,
+@vindex gnus-cacheable-groups
+It is likely that you do not want caching on all groups.  For instance,
 if your @code{nnml} mail is located under your home directory, it makes no
 sense to cache it somewhere else under your home directory.  Unless you
-feel that it's neat to use twice as much space.  To limit the caching,
-you could set the @code{gnus-uncacheable-groups} regexp to
-@samp{^nnml}, for instance.  This variable is @code{nil} by
-default.
+feel that it's neat to use twice as much space.
+
+To limit the caching, you could set @code{gnus-cacheable-groups} to a
+regexp of groups to cache, @samp{^nntp} for instance, or set the
+@code{gnus-uncacheable-groups} regexp to @samp{^nnml}, for instance.
+Both variables are @code{nil} by default.  If a group matches both
+variables, the group is not cached.
 
 @findex gnus-cache-generate-nov-databases
 @findex gnus-cache-generate-active
 @vindex gnus-cache-active-file
 The cache stores information on what articles it contains in its active
 file (@code{gnus-cache-active-file}).  If this file (or any other parts
-of the cache) becomes all messed up for some reason or other, Gnus
+of the cache) becomes all messed up for some reason or other, gnus
 offers two functions that will try to set things right.  @kbd{M-x
-gnus-cache-generate-nov-databases} will (re)build all the @sc{nov}
+gnus-cache-generate-nov-databases} will (re)build all the @acronym{NOV}
 files, and @kbd{gnus-cache-generate-active} will (re)generate the active
 file.
 
+@findex gnus-cache-move-cache
+@code{gnus-cache-move-cache} will move your whole
+@code{gnus-cache-directory} to some other location.  You get asked to
+where, isn't that cool?
 
 @node Persistent Articles
 @section Persistent Articles
@@ -5270,17 +7263,17 @@ you use two explicit commands for managing persistent articles:
 @item *
 @kindex * (Summary)
 @findex gnus-cache-enter-article
-Make the current article persistent (@code{gnus-cache-enter-article}). 
+Make the current article persistent (@code{gnus-cache-enter-article}).
 
 @item M-*
 @kindex M-* (Summary)
 @findex gnus-cache-remove-article
 Remove the current article from the persistent articles
 (@code{gnus-cache-remove-article}).  This will normally delete the
-article. 
+article.
 @end table
 
-Both these commands understand the process/prefix convention. 
+Both these commands understand the process/prefix convention.
 
 To avoid having all ticked articles (and stuff) entered into the cache,
 you should set @code{gnus-use-cache} to @code{passive} if you're just
@@ -5298,22 +7291,22 @@ interested in persistent articles:
 
 If you have a slow connection, but the idea of using caching seems
 unappealing to you (and it is, really), you can help the situation some
-by switching on the @dfn{backlog}.  This is where Gnus will buffer
+by switching on the @dfn{backlog}.  This is where gnus will buffer
 already read articles so that it doesn't have to re-fetch articles
 you've already read.  This only helps if you are in the habit of
 re-selecting articles you've recently read, of course.  If you never do
-that, turning the backlog on will slow Gnus down a little bit, and
+that, turning the backlog on will slow gnus down a little bit, and
 increase memory usage some.
 
 @vindex gnus-keep-backlog
-If you set @code{gnus-keep-backlog} to a number @var{n}, Gnus will store
+If you set @code{gnus-keep-backlog} to a number @var{n}, gnus will store
 at most @var{n} old articles in a buffer for later re-fetching.  If this
-variable is non-@code{nil} and is not a number, Gnus will store
+variable is non-@code{nil} and is not a number, gnus will store
 @emph{all} read articles, which means that your Emacs will grow without
 bound before exploding and taking your machine down with you.  I put
-that in there just to keep y'all on your toes.  
+that in there just to keep y'all on your toes.
 
-This variable is @code{nil} by default.
+The default value is 20.
 
 
 @node Saving Articles
@@ -5326,8 +7319,12 @@ processing of the article is done before it is saved).  For a different
 approach (uudecoding, unsharing) you should use @code{gnus-uu}
 (@pxref{Decoding Articles}).
 
+For the commands listed here, the target is a file.  If you want to
+save to a group, see the @kbd{B c} (@code{gnus-summary-copy-article})
+command (@pxref{Mail Group Commands}).
+
 @vindex gnus-save-all-headers
-If @code{gnus-save-all-headers} is non-@code{nil}, Gnus will not delete
+If @code{gnus-save-all-headers} is non-@code{nil}, gnus will not delete
 unwanted headers before saving the article.
 
 @vindex gnus-saved-headers
@@ -5344,44 +7341,44 @@ deleted before saving.
 @findex gnus-summary-save-article
 @c @icon{gnus-summary-save-article}
 Save the current article using the default article saver
-(@code{gnus-summary-save-article}). 
+(@code{gnus-summary-save-article}).
 
 @item O m
 @kindex O m (Summary)
 @findex gnus-summary-save-article-mail
 Save the current article in mail format
-(@code{gnus-summary-save-article-mail}). 
+(@code{gnus-summary-save-article-mail}).
 
 @item O r
 @kindex O r (Summary)
 @findex gnus-summary-save-article-rmail
-Save the current article in rmail format
-(@code{gnus-summary-save-article-rmail}). 
+Save the current article in Rmail format
+(@code{gnus-summary-save-article-rmail}).
 
 @item O f
 @kindex O f (Summary)
 @findex gnus-summary-save-article-file
 @c @icon{gnus-summary-save-article-file}
 Save the current article in plain file format
-(@code{gnus-summary-save-article-file}). 
+(@code{gnus-summary-save-article-file}).
 
 @item O F
 @kindex O F (Summary)
 @findex gnus-summary-write-article-file
 Write the current article in plain file format, overwriting any previous
-file contents (@code{gnus-summary-write-article-file}). 
+file contents (@code{gnus-summary-write-article-file}).
 
 @item O b
 @kindex O b (Summary)
 @findex gnus-summary-save-article-body-file
 Save the current article body in plain file format
-(@code{gnus-summary-save-article-body-file}). 
+(@code{gnus-summary-save-article-body-file}).
 
 @item O h
 @kindex O h (Summary)
 @findex gnus-summary-save-article-folder
 Save the current article in mh folder format
-(@code{gnus-summary-save-article-folder}). 
+(@code{gnus-summary-save-article-folder}).
 
 @item O v
 @kindex O v (Summary)
@@ -5390,10 +7387,25 @@ Save the current article in a VM folder
 (@code{gnus-summary-save-article-vm}).
 
 @item O p
+@itemx |
 @kindex O p (Summary)
+@kindex | (Summary)
 @findex gnus-summary-pipe-output
 Save the current article in a pipe.  Uhm, like, what I mean is---Pipe
 the current article to a process (@code{gnus-summary-pipe-output}).
+If given a symbolic prefix (@pxref{Symbolic Prefixes}), include the
+complete headers in the piped output.
+
+@item O P
+@kindex O P (Summary)
+@findex gnus-summary-muttprint
+@vindex gnus-summary-muttprint-program
+Save the current article into muttprint.  That is, print it using the
+external program @uref{http://muttprint.sourceforge.net/,
+Muttprint}.  The program name and options to use is controlled by the
+variable @code{gnus-summary-muttprint-program}.
+(@code{gnus-summary-muttprint}).
+
 @end table
 
 @vindex gnus-prompt-before-saving
@@ -5408,12 +7420,12 @@ just once for each series of articles you save.  If you like to really
 have Gnus do all your thinking for you, you can even set this variable
 to @code{nil}, which means that you will never be prompted for files to
 save articles in.  Gnus will simply save all the articles in the default
-files. 
+files.
 
 
 @vindex gnus-default-article-saver
 You can customize the @code{gnus-default-article-saver} variable to make
-Gnus do what you want it to.  You can use any of the four ready-made
+gnus do what you want it to.  You can use any of the six ready-made
 functions below, or you can create your own.
 
 @table @code
@@ -5422,7 +7434,7 @@ functions below, or you can create your own.
 @findex gnus-summary-save-in-rmail
 @vindex gnus-rmail-save-name
 @findex gnus-plain-save-name
-This is the default format, @dfn{babyl}.  Uses the function in the
+This is the default format, @dfn{Babyl}.  Uses the function in the
 @code{gnus-rmail-save-name} variable to get a file name to save the
 article in.  The default is @code{gnus-plain-save-name}.
 
@@ -5441,6 +7453,13 @@ Append the article straight to an ordinary file.  Uses the function in
 the @code{gnus-file-save-name} variable to get a file name to save the
 article in.  The default is @code{gnus-numeric-save-name}.
 
+@item gnus-summary-write-to-file
+@findex gnus-summary-write-to-file
+Write the article straight to an ordinary file.  The file is
+overwritten if it exists.  Uses the function in the
+@code{gnus-file-save-name} variable to get a file name to save the
+article in.  The default is @code{gnus-numeric-save-name}.
+
 @item gnus-summary-save-body-in-file
 @findex gnus-summary-save-body-in-file
 Append the article body to an ordinary file.  Uses the function in the
@@ -5469,8 +7488,8 @@ reader to use this setting.
 @vindex gnus-article-save-directory
 All of these functions, except for the last one, will save the article
 in the @code{gnus-article-save-directory}, which is initialized from the
-@code{SAVEDIR} environment variable.  This is @file{~/News/} by
-default. 
+@env{SAVEDIR} environment variable.  This is @file{~/News/} by
+default.
 
 As you can see above, the functions use different functions to find a
 suitable name of a file to save the article in.  Below is a list of
@@ -5493,13 +7512,17 @@ File names like @file{~/News/Alt.andrea-dworkin}.
 @item gnus-plain-save-name
 @findex gnus-plain-save-name
 File names like @file{~/News/alt.andrea-dworkin}.
+
+@item gnus-sender-save-name
+@findex gnus-sender-save-name
+File names like @file{~/News/larsi}.
 @end table
 
 @vindex gnus-split-methods
-You can have Gnus suggest where to save articles by plonking a regexp into
+You can have gnus suggest where to save articles by plonking a regexp into
 the @code{gnus-split-methods} alist.  For instance, if you would like to
-save articles related to Gnus in the file @file{gnus-stuff}, and articles
-related to VM in @code{vm-stuff}, you could set this variable to something
+save articles related to gnus in the file @file{gnus-stuff}, and articles
+related to VM in @file{vm-stuff}, you could set this variable to something
 like:
 
 @lisp
@@ -5525,9 +7548,9 @@ then be prompted for what you really want to use as a name, with file
 name completion over the results from applying this variable.
 
 This variable is @code{((gnus-article-archive-name))} by default, which
-means that Gnus will look at the articles it saves for an
+means that gnus will look at the articles it saves for an
 @code{Archive-name} line and use that as a suggestion for the file
-name. 
+name.
 
 Here's an example function to clean up file names somewhat.  If you have
 lots of mail groups called things like
@@ -5551,7 +7574,7 @@ Finally, you have the @code{gnus-use-long-file-name} variable.  If it is
 @code{nil}, all the preceding functions will replace all periods
 (@samp{.}) in the group names with slashes (@samp{/})---which means that
 the functions will generate hierarchies of directories instead of having
-all the files in the toplevel directory
+all the files in the top level directory
 (@file{~/News/alt/andrea-dworkin} instead of
 @file{~/News/alt.andrea-dworkin}.)  This variable is @code{t} by default
 on most systems.  However, for historical reasons, this is @code{nil} on
@@ -5568,13 +7591,14 @@ If you'd like to save articles in a hierarchy that looks something like
 a spool, you could
 
 @lisp
-(setq gnus-use-long-file-name '(not-save)) ; to get a hierarchy
-(setq gnus-default-article-saver 'gnus-summary-save-in-file) ; no encoding
+(setq gnus-use-long-file-name '(not-save)) ; @r{to get a hierarchy}
+(setq gnus-default-article-saver
+      'gnus-summary-save-in-file)          ; @r{no encoding}
 @end lisp
 
 Then just save with @kbd{o}.  You'd then read this hierarchy with
 ephemeral @code{nneething} groups---@kbd{G D} in the group buffer, and
-the toplevel directory as the argument (@file{~/News/}).  Then just walk
+the top level directory as the argument (@file{~/News/}).  Then just walk
 around to the groups/directories with @code{nneething}.
 
 
@@ -5585,13 +7609,13 @@ around to the groups/directories with @code{nneething}.
 Sometime users post articles (or series of articles) that have been
 encoded in some way or other.  Gnus can decode them for you.
 
-@menu 
-* Uuencoded Articles::    Uudecode articles.
-* Shell Archives::        Unshar articles.
-* PostScript Files::      Split PostScript.
-* Other Files::           Plain save and binhex.
-* Decoding Variables::    Variables for a happy decoding.
-* Viewing Files::         You want to look at the result of the decoding?
+@menu
+* Uuencoded Articles::          Uudecode articles.
+* Shell Archives::              Unshar articles.
+* PostScript Files::            Split PostScript.
+* Other Files::                 Plain save and binhex.
+* Decoding Variables::          Variables for a happy decoding.
+* Viewing Files::               You want to look at the result of the decoding?
 @end menu
 
 @cindex series
@@ -5606,9 +7630,9 @@ Gnus guesses what articles are in the series according to the following
 simplish rule: The subjects must be (nearly) identical, except for the
 last two numbers of the line.  (Spaces are largely ignored, however.)
 
-For example: If you choose a subject called @samp{cat.gif (2/3)}, Gnus
+For example: If you choose a subject called @samp{cat.gif (2/3)}, gnus
 will find all the articles that match the regexp @samp{^cat.gif
-([0-9]+/[0-9]+).*$}.  
+([0-9]+/[0-9]+).*$}.
 
 Subjects that are non-standard, like @samp{cat.gif (2/3) Part 6 of a
 series}, will not be properly recognized by any of the automatic viewing
@@ -5699,7 +7723,7 @@ Unshars and views the current series (@code{gnus-uu-decode-unshar-view}).
 @kindex X v S (Summary)
 @findex gnus-uu-decode-unshar-and-save-view
 Unshars, views and saves the current series
-(@code{gnus-uu-decode-unshar-and-save-view}). 
+(@code{gnus-uu-decode-unshar-and-save-view}).
 @end table
 
 
@@ -5730,7 +7754,7 @@ View the current PostScript series
 @kindex X v P (Summary)
 @findex gnus-uu-decode-postscript-and-save-view
 View and save the current PostScript series
-(@code{gnus-uu-decode-postscript-and-save-view}). 
+(@code{gnus-uu-decode-postscript-and-save-view}).
 @end table
 
 
@@ -5757,10 +7781,10 @@ doesn't really work yet.
 
 Adjective, not verb.
 
-@menu 
-* Rule Variables::          Variables that say how a file is to be viewed.
-* Other Decode Variables::  Other decode variables.
-* Uuencoding and Posting::  Variables for customizing uuencoding.
+@menu
+* Rule Variables::              Variables that say how a file is to be viewed.
+* Other Decode Variables::      Other decode variables.
+* Uuencoding and Posting::      Variables for customizing uuencoding.
 @end menu
 
 
@@ -5770,7 +7794,7 @@ Adjective, not verb.
 
 Gnus uses @dfn{rule variables} to decide how to view a file.  All these
 variables are of the form
-  
+
 @lisp
       (list '(regexp1 command2)
             '(regexp2 command2)
@@ -5783,16 +7807,16 @@ variables are of the form
 @vindex gnus-uu-user-view-rules
 @cindex sox
 This variable is consulted first when viewing files.  If you wish to use,
-for instance, @code{sox} to convert an @samp{.au} sound file, you could
+for instance, @code{sox} to convert an @file{.au} sound file, you could
 say something like:
 @lisp
 (setq gnus-uu-user-view-rules
-      (list '(\"\\\\.au$\" \"sox %s -t .aiff > /dev/audio\")))
+      (list '("\\\\.au$" "sox %s -t .aiff > /dev/audio")))
 @end lisp
 
 @item gnus-uu-user-view-rules-end
 @vindex gnus-uu-user-view-rules-end
-This variable is consulted if Gnus couldn't make any matches from the
+This variable is consulted if gnus couldn't make any matches from the
 user and default view rules.
 
 @item gnus-uu-user-archive-rules
@@ -5838,9 +7862,9 @@ Files with name matching this regular expression won't be viewed.
 
 @item gnus-uu-ignore-files-by-type
 @vindex gnus-uu-ignore-files-by-type
-Files with a @sc{mime} type matching this variable won't be viewed.
+Files with a @acronym{MIME} type matching this variable won't be viewed.
 Note that Gnus tries to guess what type the file is based on the name.
-@code{gnus-uu} is not a @sc{mime} package (yet), so this is slightly
+@code{gnus-uu} is not a @acronym{MIME} package (yet), so this is slightly
 kludgey.
 
 @item gnus-uu-tmp-dir
@@ -5890,7 +7914,7 @@ Hook run before sending a message to @code{uudecode}.
 @vindex gnus-uu-view-with-metamail
 @cindex metamail
 Non-@code{nil} means that @code{gnus-uu} will ignore the viewing
-commands defined by the rule variables and just fudge a @sc{mime}
+commands defined by the rule variables and just fudge a @acronym{MIME}
 content type based on the file name.  The result will be fed to
 @code{metamail} for viewing.
 
@@ -5899,7 +7923,7 @@ content type based on the file name.  The result will be fed to
 Non-@code{nil} means that @code{gnus-uu}, when asked to save without
 decoding, will save in digests.  If this variable is @code{nil},
 @code{gnus-uu} will just save everything in a file without any
-embellishments.  The digesting almost conforms to RFC1153---no easy way
+embellishments.  The digesting almost conforms to RFC 1153---no easy way
 to specify any meaningful volume and issue numbers were found, so I
 simply dropped them.
 
@@ -5929,7 +7953,7 @@ Non-@code{nil} means that @code{gnus-uu} will post the encoded file in a
 thread.  This may not be smart, as no other decoder I have seen is able
 to follow threads when collecting uuencoded articles.  (Well, I have
 seen one package that does that---@code{gnus-uu}, but somehow, I don't
-think that counts...) Default is @code{nil}.
+think that counts@dots{}) Default is @code{nil}.
 
 @item gnus-uu-post-separate-description
 @vindex gnus-uu-post-separate-description
@@ -5947,15 +7971,15 @@ Default is @code{t}.
 @cindex viewing files
 @cindex pseudo-articles
 
-After decoding, if the file is some sort of archive, Gnus will attempt
+After decoding, if the file is some sort of archive, gnus will attempt
 to unpack the archive and see if any of the files in the archive can be
 viewed.  For instance, if you have a gzipped tar file @file{pics.tar.gz}
-containing the files @file{pic1.jpg} and @file{pic2.gif}, Gnus will
+containing the files @file{pic1.jpg} and @file{pic2.gif}, gnus will
 uncompress and de-tar the main file, and then view the two pictures.
 This unpacking process is recursive, so if the archive contains archives
 of archives, it'll all be unpacked.
 
-Finally, Gnus will normally insert a @dfn{pseudo-article} for each
+Finally, gnus will normally insert a @dfn{pseudo-article} for each
 extracted file into the summary buffer.  If you go to these
 ``articles'', you will be prompted for a command to run (usually Gnus
 will make a suggestion), and then the command will be run.
@@ -5970,7 +7994,7 @@ the pseudo-articles into the summary buffer, but view them
 immediately.  If this variable is @code{not-confirm}, the user won't even
 be asked for a confirmation before viewing is done.
 
-@vindex gnus-view-pseudos-separately 
+@vindex gnus-view-pseudos-separately
 If @code{gnus-view-pseudos-separately} is non-@code{nil}, one
 pseudo-article will be created for each file to be viewed.  If
 @code{nil}, all files that use the same viewing command will be given as
@@ -5995,19 +8019,23 @@ writing, so there are tons of functions and variables to make reading
 these articles easier.
 
 @menu
-* Article Highlighting::    You want to make the article look like fruit salad.
-* Article Fontisizing::     Making emphasized text look niced.
-* Article Hiding::          You also want to make certain info go away.
-* Article Washing::         Lots of way-neat functions to make life better.
-* Article Buttons::         Click on URLs, Message-IDs, addresses and the like.
-* Article Date::            Grumble, UT!
-* Article Signature::       What is a signature?
+* Article Highlighting::        You want to make the article look like fruit salad.
+* Article Fontisizing::         Making emphasized text look nice.
+* Article Hiding::              You also want to make certain info go away.
+* Article Washing::             Lots of way-neat functions to make life better.
+* Article Header::              Doing various header transformations.
+* Article Buttons::             Click on URLs, Message-IDs, addresses and the like.
+* Article Button Levels::       Controlling appearance of buttons.
+* Article Date::                Grumble, UT!
+* Article Display::             Display various stuff---X-Face, Picons, Smileys
+* Article Signature::           What is a signature?
+* Article Miscellanea::         Various other stuff.
 @end menu
 
 
 @node Article Highlighting
 @subsection Article Highlighting
-@cindex highlight
+@cindex highlighting
 
 Not only do you want your article buffer to look like fruit salad, but
 you want it to look like technicolor fruit salad.
@@ -6017,7 +8045,10 @@ you want it to look like technicolor fruit salad.
 @item W H a
 @kindex W H a (Summary)
 @findex gnus-article-highlight
-Highlight the current article (@code{gnus-article-highlight}).
+@findex gnus-article-maybe-highlight
+Do much highlighting of the current article
+(@code{gnus-article-highlight}).  This function highlights header, cited
+text, the signature, and adds buttons to the body and the head.
 
 @item W H h
 @kindex W H h (Summary)
@@ -6025,8 +8056,9 @@ Highlight the current article (@code{gnus-article-highlight}).
 @vindex gnus-header-face-alist
 Highlight the headers (@code{gnus-article-highlight-headers}).  The
 highlighting will be done according to the @code{gnus-header-face-alist}
-variable, which is a list where each element has the form @var{(regexp
-name content)}.  @var{regexp} is a regular expression for matching the
+variable, which is a list where each element has the form
+@code{(@var{regexp} @var{name} @var{content})}.
+@var{regexp} is a regular expression for matching the
 header, @var{name} is the face used for highlighting the header name
 (@pxref{Faces and Fonts}) and @var{content} is the face for highlighting
 the header value.  The first match made will be used.  Note that
@@ -6035,7 +8067,7 @@ the header value.  The first match made will be used.  Note that
 @item W H c
 @kindex W H c (Summary)
 @findex gnus-article-highlight-citation
-Highlight cited text (@code{gnus-article-highlight-citation}). 
+Highlight cited text (@code{gnus-article-highlight-citation}).
 
 Some variables to customize the citation highlights:
 
@@ -6044,11 +8076,7 @@ Some variables to customize the citation highlights:
 
 @item gnus-cite-parse-max-size
 If the article size if bigger than this variable (which is 25000 by
-default), no citation highlighting will be performed.  
-
-@item gnus-cite-prefix-regexp
-@vindex gnus-cite-prefix-regexp
-Regexp matching the longest possible citation prefix on a line. 
+default), no citation highlighting will be performed.
 
 @item gnus-cite-max-prefix
 @vindex gnus-cite-max-prefix
@@ -6058,12 +8086,12 @@ Maximum possible length for a citation prefix (default 20).
 @vindex gnus-cite-face-list
 List of faces used for highlighting citations (@pxref{Faces and Fonts}).
 When there are citations from multiple articles in the same message,
-Gnus will try to give each citation from each article its own face.
+gnus will try to give each citation from each article its own face.
 This should make it easier to see who wrote what.
 
 @item gnus-supercite-regexp
 @vindex gnus-supercite-regexp
-Regexp matching normal Supercite attribution lines.  
+Regexp matching normal Supercite attribution lines.
 
 @item gnus-supercite-secondary-regexp
 @vindex gnus-supercite-secondary-regexp
@@ -6103,6 +8131,8 @@ default.
 
 @end table
 
+@xref{Customizing Articles}, for how to highlight articles automatically.
+
 
 @node Article Fontisizing
 @subsection Article Fontisizing
@@ -6112,13 +8142,13 @@ default.
 @findex gnus-article-emphasize
 @kindex W e (Summary)
 People commonly add emphasis to words in news articles by writing things
-like @samp{_this_} or @samp{*this*}.  Gnus can make this look nicer by
-running the article through the @kbd{W e}
+like @samp{_this_} or @samp{*this*} or @samp{/this/}.  Gnus can make
+this look nicer by running the article through the @kbd{W e}
 (@code{gnus-article-emphasize}) command.
 
-@vindex gnus-article-emphasis
+@vindex gnus-emphasis-alist
 How the emphasis is computed is controlled by the
-@code{gnus-article-emphasis} variable.  This is an alist where the first
+@code{gnus-emphasis-alist} variable.  This is an alist where the first
 element is a regular expression to be matched.  The second is a number
 that says what regular expression grouping is used to find the entire
 emphasized word.  The third is a number that says what regexp grouping
@@ -6127,11 +8157,17 @@ groupings will be hidden.)  The fourth is the face used for
 highlighting.
 
 @lisp
-(setq gnus-article-emphasis
+(setq gnus-emphasis-alist
       '(("_\\(\\w+\\)_" 0 1 gnus-emphasis-underline)
         ("\\*\\(\\w+\\)\\*" 0 1 gnus-emphasis-bold)))
 @end lisp
 
+@cindex slash
+@cindex asterisk
+@cindex underline
+@cindex /
+@cindex *
+
 @vindex gnus-emphasis-underline
 @vindex gnus-emphasis-bold
 @vindex gnus-emphasis-italic
@@ -6144,7 +8180,7 @@ By default, there are seven rules, and they use the following faces:
 @code{gnus-emphasis-underline}, @code{gnus-emphasis-bold-italic},
 @code{gnus-emphasis-underline-italic},
 @code{gnus-emphasis-underline-bold}, and
-@code{gnus-emphasis-underline-bold-italic}.  
+@code{gnus-emphasis-underline-bold-italic}.
 
 If you want to change these faces, you can either use @kbd{M-x
 customize}, or you can use @code{copy-face}.  For instance, if you want
@@ -6155,26 +8191,37 @@ say something like:
 (copy-face 'red 'gnus-emphasis-italic)
 @end lisp
 
+@vindex gnus-group-highlight-words-alist
+
+If you want to highlight arbitrary words, you can use the
+@code{gnus-group-highlight-words-alist} variable, which uses the same
+syntax as @code{gnus-emphasis-alist}.  The @code{highlight-words} group
+parameter (@pxref{Group Parameters}) can also be used.
+
+@xref{Customizing Articles}, for how to fontize articles automatically.
+
 
 @node Article Hiding
 @subsection Article Hiding
 @cindex article hiding
 
 Or rather, hiding certain things in each article.  There usually is much
-too much cruft in most articles.  
+too much cruft in most articles.
 
 @table @kbd
 
 @item W W a
 @kindex W W a (Summary)
 @findex gnus-article-hide
-Do maximum hiding on the summary buffer (@kbd{gnus-article-hide}). 
+Do quite a lot of hiding on the article buffer
+(@kbd{gnus-article-hide}).  In particular, this function will hide
+headers, @acronym{PGP}, cited text and the signature.
 
 @item W W h
 @kindex W W h (Summary)
 @findex gnus-article-hide-headers
 Hide headers (@code{gnus-article-hide-headers}).  @xref{Hiding
-Headers}. 
+Headers}.
 
 @item W W b
 @kindex W W b (Summary)
@@ -6186,22 +8233,79 @@ Hide headers that aren't particularly interesting
 @kindex W W s (Summary)
 @findex gnus-article-hide-signature
 Hide signature (@code{gnus-article-hide-signature}).  @xref{Article
-Signature}. 
+Signature}.
+
+@item W W l
+@kindex W W l (Summary)
+@findex gnus-article-hide-list-identifiers
+@vindex gnus-list-identifiers
+Strip list identifiers specified in @code{gnus-list-identifiers}.  These
+are strings some mailing list servers add to the beginning of all
+@code{Subject} headers---for example, @samp{[zebra 4711]}.  Any leading
+@samp{Re: } is skipped before stripping.  @code{gnus-list-identifiers}
+may not contain @code{\\(..\\)}.
+
+@table @code
+
+@item gnus-list-identifiers
+@vindex gnus-list-identifiers
+A regular expression that matches list identifiers to be removed from
+subject.  This can also be a list of regular expressions.
 
-@item W W p
-@kindex W W p (Summary)
-@findex gnus-article-hide-pgp
-@vindex gnus-article-hide-pgp-hook
-Hide @sc{pgp} signatures (@code{gnus-article-hide-pgp}).  The
-@code{gnus-article-hide-pgp-hook} hook will be run after a @sc{pgp}
-signature has been hidden.
+@end table
 
 @item W W P
 @kindex W W P (Summary)
 @findex gnus-article-hide-pem
-Hide @sc{pem} (privacy enhanced messages) cruft
+Hide @acronym{PEM} (privacy enhanced messages) cruft
 (@code{gnus-article-hide-pem}).
 
+@item W W B
+@kindex W W B (Summary)
+@findex gnus-article-strip-banner
+@vindex gnus-article-banner-alist
+@vindex gnus-article-address-banner-alist
+@cindex banner
+@cindex OneList
+@cindex stripping advertisements
+@cindex advertisements
+Strip the banner specified by the @code{banner} group parameter
+(@code{gnus-article-strip-banner}).  This is mainly used to hide those
+annoying banners and/or signatures that some mailing lists and moderated
+groups adds to all the messages.  The way to use this function is to add
+the @code{banner} group parameter (@pxref{Group Parameters}) to the
+group you want banners stripped from.  The parameter either be a string,
+which will be interpreted as a regular expression matching text to be
+removed, or the symbol @code{signature}, meaning that the (last)
+signature should be removed, or other symbol, meaning that the
+corresponding regular expression in @code{gnus-article-banner-alist} is
+used.
+
+Regardless of a group, you can hide things like advertisements only when
+the sender of an article has a certain mail address specified in
+@code{gnus-article-address-banner-alist}.
+
+@table @code
+
+@item gnus-article-address-banner-alist
+@vindex gnus-article-address-banner-alist
+Alist of mail addresses and banners.  Each element has the form
+@code{(@var{address} . @var{banner})}, where @var{address} is a regexp
+matching a mail address in the From header, @var{banner} is one of a
+symbol @code{signature}, an item in @code{gnus-article-banner-alist},
+a regexp and @code{nil}.  If @var{address} matches author's mail
+address, it will remove things like advertisements.  For example, if a
+sender has the mail address @samp{hail@@yoo-hoo.co.jp} and there is a
+banner something like @samp{Do You Yoo-hoo!?} in all articles he
+sends, you can use the following element to remove them:
+
+@lisp
+("@@yoo-hoo\\.co\\.jp\\'" .
+ "\n_+\nDo You Yoo-hoo!\\?\n.*\n.*\n")
+@end lisp
+
+@end table
+
 @item W W c
 @kindex W W c (Summary)
 @findex gnus-article-hide-citation
@@ -6210,36 +8314,51 @@ customizing the hiding:
 
 @table @code
 
-@item gnus-cite-hide-percentage
-@vindex gnus-cite-hide-percentage
-If the cited text is of a bigger percentage than this variable (default
-50), hide the cited text.
-
-@item gnus-cite-hide-absolute
-@vindex gnus-cite-hide-absolute
-The cited text must have at least this length (default 10) before it
-is hidden.
-
-@item gnus-cited-text-button-line-format
-@vindex gnus-cited-text-button-line-format
+@item gnus-cited-opened-text-button-line-format
+@itemx gnus-cited-closed-text-button-line-format
+@vindex gnus-cited-closed-text-button-line-format
+@vindex gnus-cited-opened-text-button-line-format
 Gnus adds buttons to show where the cited text has been hidden, and to
 allow toggle hiding the text.  The format of the variable is specified
-by this format-like variable (@pxref{Formatting Variables}).  These
+by these format-like variable (@pxref{Formatting Variables}).  These
 specs are valid:
 
 @table @samp
 @item b
-Start point of the hidden text.
+Starting point of the hidden text.
 @item e
-End point of the hidden text.
+Ending point of the hidden text.
 @item l
-Length of the hidden text.
+Number of characters in the hidden region.
+@item n
+Number of lines of hidden text.
 @end table
 
 @item gnus-cited-lines-visible
 @vindex gnus-cited-lines-visible
-The number of lines at the beginning of the cited text to leave shown. 
+The number of lines at the beginning of the cited text to leave
+shown.  This can also be a cons cell with the number of lines at the top
+and bottom of the text, respectively, to remain visible.
+
+@end table
+
+@item W W C-c
+@kindex W W C-c (Summary)
+@findex gnus-article-hide-citation-maybe
+
+Hide citation (@code{gnus-article-hide-citation-maybe}) depending on the
+following two variables:
+
+@table @code
+@item gnus-cite-hide-percentage
+@vindex gnus-cite-hide-percentage
+If the cited text is of a bigger percentage than this variable (default
+50), hide the cited text.
 
+@item gnus-cite-hide-absolute
+@vindex gnus-cite-hide-absolute
+The cited text must have at least this length (default 10) before it
+is hidden.
 @end table
 
 @item W W C
@@ -6248,7 +8367,7 @@ The number of lines at the beginning of the cited text to leave shown.
 Hide cited text in articles that aren't roots
 (@code{gnus-article-hide-citation-in-followups}).  This isn't very
 useful as an interactive command, but might be a handy function to stick
-in @code{gnus-article-display-hook} (@pxref{Customizing Articles}). 
+have happen automatically (@pxref{Customizing Articles}).
 
 @end table
 
@@ -6259,6 +8378,9 @@ hidden.  If you give a positive prefix, they will always hide.
 Also @pxref{Article Highlighting} for further variables for
 citation customization.
 
+@xref{Customizing Articles}, for how to hide article elements
+automatically.
+
 
 @node Article Washing
 @subsection Article Washing
@@ -6272,45 +8394,68 @@ We call this ``article washing'' for a really good reason.  Namely, the
 something else'', but normally results in something looking better.
 Cleaner, perhaps.
 
+@xref{Customizing Articles}, if you want to change how Gnus displays
+articles by default.
+
 @table @kbd
 
+@item C-u g
+This is not really washing, it's sort of the opposite of washing.  If
+you type this, you see the article exactly as it exists on disk or on
+the server.
+
+@item g
+Force redisplaying of the current article
+(@code{gnus-summary-show-article}).  This is also not really washing.
+If you type this, you see the article without any previously applied
+interactive Washing functions but with all default treatments
+(@pxref{Customizing Articles}).
+
 @item W l
 @kindex W l (Summary)
 @findex gnus-summary-stop-page-breaking
 Remove page breaks from the current article
-(@code{gnus-summary-stop-page-breaking}).
+(@code{gnus-summary-stop-page-breaking}).  @xref{Misc Article}, for page
+delimiters.
 
 @item W r
 @kindex W r (Summary)
 @findex gnus-summary-caesar-message
 @c @icon{gnus-summary-caesar-message}
 Do a Caesar rotate (rot13) on the article buffer
-(@code{gnus-summary-caesar-message}). 
+(@code{gnus-summary-caesar-message}).
 Unreadable articles that tell you to read them with Caesar rotate or rot13.
 (Typically offensive jokes and such.)
 
 It's commonly called ``rot13'' because each letter is rotated 13
 positions in the alphabet, e. g. @samp{B} (letter #2) -> @samp{O} (letter
 #15).  It is sometimes referred to as ``Caesar rotate'' because Caesar
-is rumoured to have employed this form of, uh, somewhat weak encryption.
+is rumored to have employed this form of, uh, somewhat weak encryption.
+
+@item W m
+@kindex W m (Summary)
+@findex gnus-summary-morse-message
+Morse decode the article buffer (@code{gnus-summary-morse-message}).
 
 @item W t
+@item t
 @kindex W t (Summary)
+@kindex t (Summary)
 @findex gnus-summary-toggle-header
 Toggle whether to display all headers in the article buffer
-(@code{gnus-summary-toggle-header}). 
+(@code{gnus-summary-toggle-header}).
 
 @item W v
 @kindex W v (Summary)
-@findex gnus-summary-verbose-header
+@findex gnus-summary-verbose-headers
 Toggle whether to display all headers in the article buffer permanently
-(@code{gnus-summary-verbose-header}).
+(@code{gnus-summary-verbose-headers}).
 
 @item W m
 @kindex W m (Summary)
 @findex gnus-summary-toggle-mime
-Toggle whether to run the article through @sc{mime} before displaying
-(@code{gnus-summary-toggle-mime}).
+Toggle whether to run the article through @acronym{MIME} before
+displaying (@code{gnus-summary-toggle-mime}).
 
 @item W o
 @kindex W o (Summary)
@@ -6320,72 +8465,186 @@ Treat overstrike (@code{gnus-article-treat-overstrike}).
 @item W d
 @kindex W d (Summary)
 @findex gnus-article-treat-dumbquotes
-Treat M******** sm*rtq**t*s (@code{gnus-article-treat-dumbquotes}).
+@vindex gnus-article-dumbquotes-map
+@cindex Smartquotes
+@cindex M****s*** sm*rtq**t*s
+@cindex Latin 1
+Treat M****s*** sm*rtq**t*s according to
+@code{gnus-article-dumbquotes-map}
+(@code{gnus-article-treat-dumbquotes}).  Note that this function guesses
+whether a character is a sm*rtq**t* or not, so it should only be used
+interactively.
+
+Sm*rtq**t*s are M****s***'s unilateral extension to the character map in
+an attempt to provide more quoting characters.  If you see something
+like @code{\222} or @code{\264} where you're expecting some kind of
+apostrophe or quotation mark, then try this wash.
+
+@item W Y f
+@kindex W Y f (Summary)
+@findex gnus-article-outlook-deuglify-article
+@cindex Outlook Express
+Full deuglify of broken Outlook (Express) articles: Treat dumbquotes,
+unwrap lines, repair attribution and rearrange citation.
+(@code{gnus-article-outlook-deuglify-article}).
+
+@item W Y u
+@kindex W Y u (Summary)
+@findex gnus-article-outlook-unwrap-lines
+@vindex gnus-outlook-deuglify-unwrap-min
+@vindex gnus-outlook-deuglify-unwrap-max
+Unwrap lines that appear to be wrapped citation lines.  You can control
+what lines will be unwrapped by frobbing
+@code{gnus-outlook-deuglify-unwrap-min} and
+@code{gnus-outlook-deuglify-unwrap-max}, indicating the minimum and
+maximum length of an unwrapped citation line.
+(@code{gnus-article-outlook-unwrap-lines}).
+
+@item W Y a
+@kindex W Y a (Summary)
+@findex gnus-article-outlook-repair-attribution
+Repair a broken attribution line.@*
+(@code{gnus-article-outlook-repair-attribution}).
+
+@item W Y c
+@kindex W Y c (Summary)
+@findex gnus-article-outlook-rearrange-citation
+Repair broken citations by rearranging the text.
+(@code{gnus-article-outlook-rearrange-citation}).
 
 @item W w
 @kindex W w (Summary)
 @findex gnus-article-fill-cited-article
-Do word wrap (@code{gnus-article-fill-cited-article}).  If you use this
-function in @code{gnus-article-display-hook}, it should be run fairly
-late and certainly after any highlighting.
+Do word wrap (@code{gnus-article-fill-cited-article}).
 
 You can give the command a numerical prefix to specify the width to use
 when filling.
 
+@item W Q
+@kindex W Q (Summary)
+@findex gnus-article-fill-long-lines
+Fill long lines (@code{gnus-article-fill-long-lines}).
+
+@item W C
+@kindex W C (Summary)
+@findex gnus-article-capitalize-sentences
+Capitalize the first word in each sentence
+(@code{gnus-article-capitalize-sentences}).
+
 @item W c
 @kindex W c (Summary)
 @findex gnus-article-remove-cr
-Remove CR (i. e., @samp{^M}s on the end of the lines)
+Translate CRLF pairs (i. e., @samp{^M}s on the end of the lines) into LF
+(this takes care of DOS line endings), and then translate any remaining
+CRs into LF (this takes care of Mac line endings)
 (@code{gnus-article-remove-cr}).
 
-@item W q
 @kindex W q (Summary)
 @findex gnus-article-de-quoted-unreadable
 Treat quoted-printable (@code{gnus-article-de-quoted-unreadable}).
-Quoted-Printable is one common @sc{mime} encoding employed when sending
-non-ASCII (i. e., 8-bit) articles.  It typically makes strings like
-@samp{déjà vu} look like @samp{d=E9j=E0 vu}, which doesn't look very
-readable to me.
+Quoted-Printable is one common @acronym{MIME} encoding employed when
+sending non-@acronym{ASCII} (i.e., 8-bit) articles.  It typically
+makes strings like @samp{déjà vu} look like @samp{d=E9j=E0 vu}, which
+doesn't look very readable to me.  Note that this is usually done
+automatically by Gnus if the message in question has a
+@code{Content-Transfer-Encoding} header that says that this encoding
+has been done.  If a prefix is given, a charset will be asked for.
+
+@item W 6
+@kindex W 6 (Summary)
+@findex gnus-article-de-base64-unreadable
+Treat base64 (@code{gnus-article-de-base64-unreadable}).  Base64 is
+one common @acronym{MIME} encoding employed when sending
+non-@acronym{ASCII} (i.e., 8-bit) articles.  Note that this is
+usually done automatically by Gnus if the message in question has a
+@code{Content-Transfer-Encoding} header that says that this encoding
+has been done.  If a prefix is given, a charset will be asked for.
+
+@item W Z
+@kindex W Z (Summary)
+@findex gnus-article-decode-HZ
+Treat HZ or HZP (@code{gnus-article-decode-HZ}).  HZ (or HZP) is one
+common encoding employed when sending Chinese articles.  It typically
+makes strings look like @samp{~@{<:Ky2;S@{#,NpJ)l6HK!#~@}}.
+
+@item W u
+@kindex W u (Summary)
+@findex gnus-article-unsplit-urls
+Remove newlines from within URLs.  Some mailers insert newlines into
+outgoing email messages to keep lines short.  This reformatting can
+split long URLs onto multiple lines.  Repair those URLs by removing
+the newlines (@code{gnus-article-unsplit-urls}).
+
+@item W h
+@kindex W h (Summary)
+@findex gnus-article-wash-html
+Treat @acronym{HTML} (@code{gnus-article-wash-html}).  Note that this is
+usually done automatically by Gnus if the message in question has a
+@code{Content-Type} header that says that the message is @acronym{HTML}.
+
+If a prefix is given, a charset will be asked for.
+
+@vindex gnus-article-wash-function
+The default is to use the function specified by
+@code{mm-text-html-renderer} (@pxref{Display Customization, ,Display
+Customization, emacs-mime, The Emacs MIME Manual}) to convert the
+@acronym{HTML}, but this is controlled by the
+@code{gnus-article-wash-function} variable.  Pre-defined functions you
+can use include:
 
-@item W f
-@kindex W f (Summary)
-@cindex x-face
-@findex gnus-article-display-x-face
-@findex gnus-article-x-face-command
-@vindex gnus-article-x-face-command
-@vindex gnus-article-x-face-too-ugly
-@iftex
-@iflatex
-\include{xface}
-@end iflatex
-@end iftex
-Look for and display any X-Face headers
-(@code{gnus-article-display-x-face}).  The command executed by this
-function is given by the @code{gnus-article-x-face-command} variable.
-If this variable is a string, this string will be executed in a
-sub-shell.  If it is a function, this function will be called with the
-face as the argument.  If the @code{gnus-article-x-face-too-ugly} (which
-is a regexp) matches the @code{From} header, the face will not be shown.
-The default action under Emacs is to fork off an @code{xv} to view the
-face; under XEmacs the default action is to display the face before the
-@code{From} header.  (It's nicer if XEmacs has been compiled with X-Face
-support---that will make display somewhat faster.  If there's no native
-X-Face support, Gnus will try to convert the @code{X-Face} header using
-external programs from the @code{pbmplus} package and friends.)  If you
-want to have this function in the display hook, it should probably come
-last.
+@table @code
+@item w3
+Use Emacs/w3.
+
+@item w3m
+Use @uref{http://emacs-w3m.namazu.org/, emacs-w3m}.
+
+@item links
+Use @uref{http://links.sf.net/, Links}.
+
+@item lynx
+Use @uref{http://lynx.isc.org/, Lynx}.
+
+@item html2text
+Use html2text---a simple @acronym{HTML} converter included with Gnus.
+
+@end table
 
 @item W b
 @kindex W b (Summary)
 @findex gnus-article-add-buttons
 Add clickable buttons to the article (@code{gnus-article-add-buttons}).
-@xref{Article Buttons}
+@xref{Article Buttons}.
 
 @item W B
 @kindex W B (Summary)
 @findex gnus-article-add-buttons-to-head
 Add clickable buttons to the article headers
-(@code{gnus-article-add-buttons-to-head}).  
+(@code{gnus-article-add-buttons-to-head}).
+
+@item W p
+@kindex W p (Summary)
+@findex gnus-article-verify-x-pgp-sig
+Verify a signed control message
+(@code{gnus-article-verify-x-pgp-sig}).  Control messages such as
+@code{newgroup} and @code{checkgroups} are usually signed by the
+hierarchy maintainer.  You need to add the @acronym{PGP} public key of
+the maintainer to your keyring to verify the
+message.@footnote{@acronym{PGP} keys for many hierarchies are
+available at @uref{ftp://ftp.isc.org/pub/pgpcontrol/README.html}}
+
+@item W s
+@kindex W s (Summary)
+@findex gnus-summary-force-verify-and-decrypt
+Verify a signed (@acronym{PGP}, @acronym{PGP/MIME} or
+@acronym{S/MIME}) message
+(@code{gnus-summary-force-verify-and-decrypt}). @xref{Security}.
+
+@item W a
+@kindex W a (Summary)
+@findex gnus-article-strip-headers-in-body
+Strip headers like the @code{X-No-Archive} header from the beginning of
+article bodies (@code{gnus-article-strip-headers-in-body}).
 
 @item W E l
 @kindex W E l (Summary)
@@ -6424,6 +8683,47 @@ Remove all blank lines
 Remove all white space from the beginning of all lines of the article
 body (@code{gnus-article-strip-leading-space}).
 
+@item W E e
+@kindex W E e (Summary)
+@findex gnus-article-strip-trailing-space
+Remove all white space from the end of all lines of the article
+body (@code{gnus-article-strip-trailing-space}).
+
+@end table
+
+@xref{Customizing Articles}, for how to wash articles automatically.
+
+
+@node Article Header
+@subsection Article Header
+
+These commands perform various transformations of article header.
+
+@table @kbd
+
+@item W G u
+@kindex W G u (Summary)
+@findex gnus-article-treat-unfold-headers
+Unfold folded header lines (@code{gnus-article-treat-unfold-headers}).
+
+@item W G n
+@kindex W G n (Summary)
+@findex gnus-article-treat-fold-newsgroups
+Fold the @code{Newsgroups} and @code{Followup-To} headers
+(@code{gnus-article-treat-fold-newsgroups}).
+
+@item W G f
+@kindex W G f (Summary)
+@findex gnus-article-treat-fold-headers
+Fold all the message headers
+(@code{gnus-article-treat-fold-headers}).
+
+@item W E w
+@kindex W E w (Summary)
+@findex gnus-article-remove-leading-whitespace
+Remove excessive whitespace from all headers
+(@code{gnus-article-remove-leading-whitespace}).
+
 @end table
 
 
@@ -6436,10 +8736,11 @@ be nice if Gnus could just fetch whatever it is that people talk about
 with the minimum of fuzz when you hit @kbd{RET} or use the middle mouse
 button on these references.
 
+@vindex gnus-button-man-handler
 Gnus adds @dfn{buttons} to certain standard references by default:
-Well-formed URLs, mail addresses and Message-IDs.  This is controlled by
-two variables, one that handles article bodies and one that handles
-article heads:
+Well-formed URLs, mail addresses, Message-IDs, Info links, man pages and
+Emacs or Gnus related references.  This is controlled by two variables,
+one that handles article bodies and one that handles article heads:
 
 @table @code
 
@@ -6448,15 +8749,17 @@ article heads:
 This is an alist where each entry has this form:
 
 @lisp
-(REGEXP BUTTON-PAR USE-P FUNCTION DATA-PAR)
+(@var{regexp} @var{button-par} @var{use-p} @var{function} @var{data-par})
 @end lisp
 
 @table @var
 
 @item regexp
-All text that match this regular expression will be considered an
-external reference.  Here's a typical regexp that matches embedded URLs:
-@samp{<URL:\\([^\n\r>]*\\)>}. 
+All text that match this regular expression (case insensitive) will be
+considered an external reference.  Here's a typical regexp that matches
+embedded URLs: @samp{<URL:\\([^\n\r>]*\\)>}.  This can also be a
+variable containing a regexp, useful variables to use include
+@code{gnus-button-url-regexp} and @code{gnus-button-mid-or-mail-regexp}.
 
 @item button-par
 Gnus has to know which parts of the matches is to be highlighted.  This
@@ -6466,14 +8769,18 @@ highlighted.  If you want it all highlighted, you use 0 here.
 @item use-p
 This form will be @code{eval}ed, and if the result is non-@code{nil},
 this is considered a match.  This is useful if you want extra sifting to
-avoid false matches.
+avoid false matches.  Often variables named
+@code{gnus-button-@var{*}-level} are used here, @xref{Article Button
+Levels}, but any other form may be used too.
+
+@c @code{use-p} is @code{eval}ed only if @code{regexp} matches.
 
 @item function
 This function will be called when you click on this button.
 
 @item data-par
 As with @var{button-par}, this is a sub-expression number, but this one
-says which part of the match is to be sent as data to @var{function}. 
+says which part of the match is to be sent as data to @var{function}.
 
 @end table
 
@@ -6490,16 +8797,77 @@ article head only, and that each entry has an additional element that is
 used to say what headers to apply the buttonize coding to:
 
 @lisp
-(HEADER REGEXP BUTTON-PAR USE-P FUNCTION DATA-PAR)
+(@var{header} @var{regexp} @var{button-par} @var{use-p} @var{function} @var{data-par})
 @end lisp
 
-@var{HEADER} is a regular expression.
+@var{header} is a regular expression.
+@end table
+
+@subsubsection Related variables and functions
+
+@table @code
+@item gnus-button-@var{*}-level
+@xref{Article Button Levels}.
+
+@c Stuff related to gnus-button-browse-level
 
 @item gnus-button-url-regexp
 @vindex gnus-button-url-regexp
 A regular expression that matches embedded URLs.  It is used in the
 default values of the variables above.
 
+@c Stuff related to gnus-button-man-level
+
+@item gnus-button-man-handler
+@vindex gnus-button-man-handler
+The function to use for displaying man pages.  It must take at least one
+argument with a string naming the man page.
+
+@c Stuff related to gnus-button-message-level
+
+@item gnus-button-mid-or-mail-regexp
+@vindex gnus-button-mid-or-mail-regexp
+Regular expression that matches a message ID or a mail address.
+
+@item gnus-button-prefer-mid-or-mail
+@vindex gnus-button-prefer-mid-or-mail
+This variable determines what to do when the button on a string as
+@samp{foo123@@bar.invalid} is pushed.  Strings like this can be either a
+message ID or a mail address.  If it is one of the symbols @code{mid} or
+@code{mail}, Gnus will always assume that the string is a message ID or
+a mail address, respectively.  If this variable is set to the symbol
+@code{ask}, always query the user what do do.  If it is a function, this
+function will be called with the string as its only argument.  The
+function must return @code{mid}, @code{mail}, @code{invalid} or
+@code{ask}.  The default value is the function
+@code{gnus-button-mid-or-mail-heuristic}.
+
+@item gnus-button-mid-or-mail-heuristic
+@findex gnus-button-mid-or-mail-heuristic
+Function that guesses whether its argument is a message ID or a mail
+address.  Returns @code{mid} if it's a message IDs, @code{mail} if
+it's a mail address, @code{ask} if unsure and @code{invalid} if the
+string is invalid.
+
+@item gnus-button-mid-or-mail-heuristic-alist
+@vindex gnus-button-mid-or-mail-heuristic-alist
+An alist of @code{(RATE . REGEXP)} pairs used by the function
+@code{gnus-button-mid-or-mail-heuristic}.
+
+@c Stuff related to gnus-button-tex-level
+
+@item gnus-button-ctan-handler
+@findex gnus-button-ctan-handler
+The function to use for displaying CTAN links.  It must take one
+argument, the string naming the URL.
+
+@item gnus-ctan-url
+@vindex gnus-ctan-url
+Top directory of a CTAN (Comprehensive TeX Archive Network) archive used
+by @code{gnus-button-ctan-handler}.
+
+@c Misc stuff
+
 @item gnus-article-button-face
 @vindex gnus-article-button-face
 Face used on buttons.
@@ -6510,6 +8878,76 @@ Face used when the mouse cursor is over a button.
 
 @end table
 
+@xref{Customizing Articles}, for how to buttonize articles automatically.
+
+
+@node Article Button Levels
+@subsection Article button levels
+@cindex button levels
+The higher the value of the variables @code{gnus-button-@var{*}-level},
+the more buttons will appear.  If the level is zero, no corresponding
+buttons are displayed.  With the default value (which is 5) you should
+already see quite a lot of buttons.  With higher levels, you will see
+more buttons, but you may also get more false positives.  To avoid them,
+you can set the variables @code{gnus-button-@var{*}-level} local to
+specific groups (@pxref{Group Parameters}).  Here's an example for the
+variable @code{gnus-parameters}:
+
+@lisp
+;; @r{increase @code{gnus-button-*-level} in some groups:}
+(setq gnus-parameters
+      '(("\\<\\(emacs\\|gnus\\)\\>" (gnus-button-emacs-level 10))
+        ("\\<unix\\>"               (gnus-button-man-level 10))
+        ("\\<tex\\>"                (gnus-button-tex-level 10))))
+@end lisp
+
+@table @code
+
+@item gnus-button-browse-level
+@vindex gnus-button-browse-level
+Controls the display of references to message IDs, mail addresses and
+news URLs.  Related variables and functions include
+@code{gnus-button-url-regexp}, @code{browse-url}, and
+@code{browse-url-browser-function}.
+
+@item gnus-button-emacs-level
+@vindex gnus-button-emacs-level
+Controls the display of Emacs or Gnus references.  Related functions are
+@code{gnus-button-handle-custom},
+@code{gnus-button-handle-describe-function},
+@code{gnus-button-handle-describe-variable},
+@code{gnus-button-handle-symbol},
+@code{gnus-button-handle-describe-key},
+@code{gnus-button-handle-apropos},
+@code{gnus-button-handle-apropos-command},
+@code{gnus-button-handle-apropos-variable},
+@code{gnus-button-handle-apropos-documentation}, and
+@code{gnus-button-handle-library}.
+
+@item gnus-button-man-level
+@vindex gnus-button-man-level
+Controls the display of references to (Unix) man pages.
+See @code{gnus-button-man-handler}.
+
+@item gnus-button-message-level
+@vindex gnus-button-message-level
+Controls the display of message IDs, mail addresses and news URLs.
+Related variables and functions include
+@code{gnus-button-mid-or-mail-regexp},
+@code{gnus-button-prefer-mid-or-mail},
+@code{gnus-button-mid-or-mail-heuristic}, and
+@code{gnus-button-mid-or-mail-heuristic-alist}.
+
+@item gnus-button-tex-level
+@vindex gnus-button-tex-level
+Controls the display of references to @TeX{} or LaTeX stuff, e.g. for CTAN
+URLs.  See the variables @code{gnus-ctan-url},
+@code{gnus-button-ctan-handler},
+@code{gnus-button-ctan-directory-regexp}, and
+@code{gnus-button-handle-ctan-bogus-regexp}.
+
+@end table
+
 
 @node Article Date
 @subsection Article Date
@@ -6524,7 +8962,7 @@ when the article was sent.
 @kindex W T u (Summary)
 @findex gnus-article-date-ut
 Display the date in UT (aka. GMT, aka ZULU)
-(@code{gnus-article-date-ut}). 
+(@code{gnus-article-date-ut}).
 
 @item W T i
 @kindex W T i (Summary)
@@ -6538,6 +8976,12 @@ Display the date in international format, aka. ISO 8601
 @findex gnus-article-date-local
 Display the date in the local timezone (@code{gnus-article-date-local}).
 
+@item W T p
+@kindex W T p (Summary)
+@findex gnus-article-date-english
+Display the date in a format that's easily pronounceable in English
+(@code{gnus-article-date-english}).
+
 @item W T s
 @kindex W T s (Summary)
 @vindex gnus-article-time-format
@@ -6555,14 +8999,27 @@ for a list of possible format specs.
 @findex gnus-start-date-timer
 @findex gnus-stop-date-timer
 Say how much time has elapsed between the article was posted and now
-(@code{gnus-article-date-lapsed}).  If you want to have this line
-updated continually, you can put
+(@code{gnus-article-date-lapsed}).  It looks something like:
+
+@example
+X-Sent: 6 weeks, 4 days, 1 hour, 3 minutes, 8 seconds ago
+@end example
+
+@vindex gnus-article-date-lapsed-new-header
+The value of @code{gnus-article-date-lapsed-new-header} determines
+whether this header will just be added below the old Date one, or will
+replace it.
+
+An advantage of using Gnus to read mail is that it converts simple bugs
+into wonderful absurdities.
+
+If you want to have this line updated continually, you can put
 
 @lisp
 (gnus-start-date-timer)
 @end lisp
 
-in your @file{.gnus.el} file, or you can run it off of some hook.  If
+in your @file{~/.gnus.el} file, or you can run it off of some hook.  If
 you want to stop the timer, you can use the @code{gnus-stop-date-timer}
 command.
 
@@ -6577,9 +9034,81 @@ that the article was posted in 1854.  Although something like that is
 
 @end table
 
+@xref{Customizing Articles}, for how to display the date in your
+preferred format automatically.
 
-@node Article Signature
-@subsection Article Signature
+
+@node Article Display
+@subsection Article Display
+@cindex picons
+@cindex x-face
+@cindex smileys
+
+These commands add various frivolous display gimmicks to the article
+buffer in Emacs versions that support them.
+
+@code{X-Face} headers are small black-and-white images supplied by the
+message headers (@pxref{X-Face}).
+
+@code{Face} headers are small colored images supplied by the message
+headers (@pxref{Face}).
+
+Smileys are those little @samp{:-)} symbols that people like to litter
+their messages with (@pxref{Smileys}).
+
+Picons, on the other hand, reside on your own system, and Gnus will
+try to match the headers to what you have (@pxref{Picons}).
+
+All these functions are toggles---if the elements already exist,
+they'll be removed.
+
+@table @kbd
+@item W D x
+@kindex W D x (Summary)
+@findex gnus-article-display-x-face
+Display an @code{X-Face} in the @code{From} header.
+(@code{gnus-article-display-x-face}).
+
+@item W D d
+@kindex W D d (Summary)
+@findex gnus-article-display-face
+Display a @code{Face} in the @code{From} header.
+(@code{gnus-article-display-face}).
+
+@item W D s
+@kindex W D s (Summary)
+@findex gnus-treat-smiley
+Display smileys (@code{gnus-treat-smiley}).
+
+@item W D f
+@kindex W D f (Summary)
+@findex gnus-treat-from-picon
+Piconify the @code{From} header (@code{gnus-treat-from-picon}).
+
+@item W D m
+@kindex W D m (Summary)
+@findex gnus-treat-mail-picon
+Piconify all mail headers (i. e., @code{Cc}, @code{To})
+(@code{gnus-treat-mail-picon}).
+
+@item W D n
+@kindex W D n (Summary)
+@findex gnus-treat-newsgroups-picon
+Piconify all news headers (i. e., @code{Newsgroups} and
+@code{Followup-To}) (@code{gnus-treat-newsgroups-picon}).
+
+@item W D D
+@kindex W D D (Summary)
+@findex gnus-article-remove-images
+Remove all images from the article buffer
+(@code{gnus-article-remove-images}).
+
+@end table
+
+
+
+@node Article Signature
+@subsection Article Signature
 @cindex signatures
 @cindex article signature
 
@@ -6595,13 +9124,13 @@ from the end of the body towards the beginning.)  One likely value is:
 
 @lisp
 (setq gnus-signature-separator
-      '("^-- $"         ; The standard
-        "^-- *$"        ; A common mangling
-        "^-------*$"    ; Many people just use a looong 
-                        ; line of dashes.  Shame!
-        "^ *--------*$" ; Double-shame!
-        "^________*$"   ; Underscores are also popular
-        "^========*$")) ; Pervert!
+      '("^-- $"         ; @r{The standard}
+        "^-- *$"        ; @r{A common mangling}
+        "^-------*$"    ; @r{Many people just use a looong}
+                        ; @r{line of dashes.  Shame!}
+        "^ *--------*$" ; @r{Double-shame!}
+        "^________*$"   ; @r{Underscores are also popular}
+        "^========*$")) ; @r{Pervert!}
 @end lisp
 
 The more permissive you are, the more likely it is that you'll get false
@@ -6609,16 +9138,16 @@ positives.
 
 @vindex gnus-signature-limit
 @code{gnus-signature-limit} provides a limit to what is considered a
-signature. 
+signature when displaying articles.
 
 @enumerate
-@item 
+@item
 If it is an integer, no signature may be longer (in characters) than
 that integer.
-@item 
+@item
 If it is a floating point number, no signature may be longer (in lines)
 than that number.
-@item 
+@item
 If it is a function, the function will be called without any parameters,
 and if it returns @code{nil}, there is no signature in the buffer.
 @item
@@ -6640,6 +9169,323 @@ the regular expression @samp{^---*Forwarded article}, then it isn't a
 signature after all.
 
 
+@node Article Miscellanea
+@subsection Article Miscellanea
+
+@table @kbd
+@item A t
+@kindex A t (Summary)
+@findex gnus-article-babel
+Translate the article from one language to another
+(@code{gnus-article-babel}).
+
+@end table
+
+
+@node MIME Commands
+@section MIME Commands
+@cindex MIME decoding
+@cindex attachments
+@cindex viewing attachments
+
+The following commands all understand the numerical prefix.  For
+instance, @kbd{3 b} means ``view the third @acronym{MIME} part''.
+
+@table @kbd
+@item b
+@itemx K v
+@kindex b (Summary)
+@kindex K v (Summary)
+View the @acronym{MIME} part.
+
+@item K o
+@kindex K o (Summary)
+Save the @acronym{MIME} part.
+
+@item K c
+@kindex K c (Summary)
+Copy the @acronym{MIME} part.
+
+@item K e
+@kindex K e (Summary)
+View the @acronym{MIME} part externally.
+
+@item K i
+@kindex K i (Summary)
+View the @acronym{MIME} part internally.
+
+@item K |
+@kindex K | (Summary)
+Pipe the @acronym{MIME} part to an external command.
+@end table
+
+The rest of these @acronym{MIME} commands do not use the numerical prefix in
+the same manner:
+
+@table @kbd
+@item K b
+@kindex K b (Summary)
+Make all the @acronym{MIME} parts have buttons in front of them.  This is
+mostly useful if you wish to save (or perform other actions) on inlined
+parts.
+
+@item K m
+@kindex K m (Summary)
+@findex gnus-summary-repair-multipart
+Some multipart messages are transmitted with missing or faulty headers.
+This command will attempt to ``repair'' these messages so that they can
+be viewed in a more pleasant manner
+(@code{gnus-summary-repair-multipart}).
+
+@item X m
+@kindex X m (Summary)
+@findex gnus-summary-save-parts
+Save all parts matching a @acronym{MIME} type to a directory
+(@code{gnus-summary-save-parts}).  Understands the process/prefix
+convention (@pxref{Process/Prefix}).
+
+@item M-t
+@kindex M-t (Summary)
+@findex gnus-summary-toggle-display-buttonized
+Toggle the buttonized display of the article buffer
+(@code{gnus-summary-toggle-display-buttonized}).
+
+@item W M w
+@kindex W M w (Summary)
+@findex gnus-article-decode-mime-words
+Decode RFC 2047-encoded words in the article headers
+(@code{gnus-article-decode-mime-words}).
+
+@item W M c
+@kindex W M c (Summary)
+@findex gnus-article-decode-charset
+Decode encoded article bodies as well as charsets
+(@code{gnus-article-decode-charset}).
+
+This command looks in the @code{Content-Type} header to determine the
+charset.  If there is no such header in the article, you can give it a
+prefix, which will prompt for the charset to decode as.  In regional
+groups where people post using some common encoding (but do not
+include @acronym{MIME} headers), you can set the @code{charset} group/topic
+parameter to the required charset (@pxref{Group Parameters}).
+
+@item W M v
+@kindex W M v (Summary)
+@findex gnus-mime-view-all-parts
+View all the @acronym{MIME} parts in the current article
+(@code{gnus-mime-view-all-parts}).
+
+@end table
+
+Relevant variables:
+
+@table @code
+@item gnus-ignored-mime-types
+@vindex gnus-ignored-mime-types
+This is a list of regexps.  @acronym{MIME} types that match a regexp from
+this list will be completely ignored by Gnus.  The default value is
+@code{nil}.
+
+To have all Vcards be ignored, you'd say something like this:
+
+@lisp
+(setq gnus-ignored-mime-types
+      '("text/x-vcard"))
+@end lisp
+
+@item gnus-article-loose-mime
+@vindex gnus-article-loose-mime
+If non-@code{nil}, Gnus won't require the @samp{MIME-Version} header
+before interpreting the message as a @acronym{MIME} message.  This helps
+when reading messages from certain broken mail user agents.  The
+default is @code{nil}.
+
+@item gnus-article-emulate-mime
+@vindex gnus-article-emulate-mime
+There are other, non-@acronym{MIME} encoding methods used.  The most common
+is @samp{uuencode}, but yEncode is also getting to be popular.  If
+this variable is non-@code{nil}, Gnus will look in message bodies to
+see if it finds these encodings, and if so, it'll run them through the
+Gnus @acronym{MIME} machinery.  The default is @code{t}.
+
+@item gnus-unbuttonized-mime-types
+@vindex gnus-unbuttonized-mime-types
+This is a list of regexps.  @acronym{MIME} types that match a regexp from
+this list won't have @acronym{MIME} buttons inserted unless they aren't
+displayed or this variable is overridden by
+@code{gnus-buttonized-mime-types}.  The default value is
+@code{(".*/.*")}.  This variable is only used when
+@code{gnus-inhibit-mime-unbuttonizing} is @code{nil}.
+
+@item gnus-buttonized-mime-types
+@vindex gnus-buttonized-mime-types
+This is a list of regexps.  @acronym{MIME} types that match a regexp from
+this list will have @acronym{MIME} buttons inserted unless they aren't
+displayed.  This variable overrides
+@code{gnus-unbuttonized-mime-types}.  The default value is @code{nil}.
+This variable is only used when @code{gnus-inhibit-mime-unbuttonizing}
+is @code{nil}.
+
+To see e.g. security buttons but no other buttons, you could set this
+variable to @code{("multipart/signed")} and leave
+@code{gnus-unbuttonized-mime-types} at the default value.
+
+@item gnus-inhibit-mime-unbuttonizing
+@vindex gnus-inhibit-mime-unbuttonizing
+If this is non-@code{nil}, then all @acronym{MIME} parts get buttons.  The
+default value is @code{nil}.
+
+@item gnus-article-mime-part-function
+@vindex gnus-article-mime-part-function
+For each @acronym{MIME} part, this function will be called with the @acronym{MIME}
+handle as the parameter.  The function is meant to be used to allow
+users to gather information from the article (e. g., add Vcard info to
+the bbdb database) or to do actions based on parts (e. g., automatically
+save all jpegs into some directory).
+
+Here's an example function the does the latter:
+
+@lisp
+(defun my-save-all-jpeg-parts (handle)
+  (when (equal (car (mm-handle-type handle)) "image/jpeg")
+    (with-temp-buffer
+      (insert (mm-get-part handle))
+      (write-region (point-min) (point-max)
+                    (read-file-name "Save jpeg to: ")))))
+(setq gnus-article-mime-part-function
+      'my-save-all-jpeg-parts)
+@end lisp
+
+@vindex gnus-mime-multipart-functions
+@item gnus-mime-multipart-functions
+Alist of @acronym{MIME} multipart types and functions to handle them.
+
+@vindex mm-file-name-rewrite-functions
+@item mm-file-name-rewrite-functions
+List of functions used for rewriting file names of @acronym{MIME} parts.
+Each function takes a file name as input and returns a file name.
+
+Ready-made functions include@*
+@code{mm-file-name-delete-whitespace},
+@code{mm-file-name-trim-whitespace},
+@code{mm-file-name-collapse-whitespace}, and
+@code{mm-file-name-replace-whitespace}.  The later uses the value of
+the variable @code{mm-file-name-replace-whitespace} to replace each
+whitespace character in a file name with that string; default value
+is @code{"_"} (a single underscore).
+@findex mm-file-name-delete-whitespace
+@findex mm-file-name-trim-whitespace
+@findex mm-file-name-collapse-whitespace
+@findex mm-file-name-replace-whitespace
+@vindex mm-file-name-replace-whitespace
+
+The standard functions @code{capitalize}, @code{downcase},
+@code{upcase}, and @code{upcase-initials} may be useful, too.
+
+Everybody knows that whitespace characters in file names are evil,
+except those who don't know.  If you receive lots of attachments from
+such unenlightened users, you can make live easier by adding
+
+@lisp
+(setq mm-file-name-rewrite-functions
+      '(mm-file-name-trim-whitespace
+        mm-file-name-collapse-whitespace
+        mm-file-name-replace-whitespace))
+@end lisp
+
+@noindent
+to your @file{~/.gnus.el} file.
+
+@end table
+
+
+@node Charsets
+@section Charsets
+@cindex charsets
+
+People use different charsets, and we have @acronym{MIME} to let us know what
+charsets they use.  Or rather, we wish we had.  Many people use
+newsreaders and mailers that do not understand or use @acronym{MIME}, and
+just send out messages without saying what character sets they use.  To
+help a bit with this, some local news hierarchies have policies that say
+what character set is the default.  For instance, the @samp{fj}
+hierarchy uses @code{iso-2022-jp-2}.
+
+@vindex gnus-group-charset-alist
+This knowledge is encoded in the @code{gnus-group-charset-alist}
+variable, which is an alist of regexps (use the first item to match full
+group names) and default charsets to be used when reading these groups.
+
+@vindex gnus-newsgroup-ignored-charsets
+In addition, some people do use soi-disant @acronym{MIME}-aware agents that
+aren't.  These blithely mark messages as being in @code{iso-8859-1}
+even if they really are in @code{koi-8}.  To help here, the
+@code{gnus-newsgroup-ignored-charsets} variable can be used.  The
+charsets that are listed here will be ignored.  The variable can be
+set on a group-by-group basis using the group parameters (@pxref{Group
+Parameters}).  The default value is @code{(unknown-8bit x-unknown)},
+which includes values some agents insist on having in there.
+
+@vindex gnus-group-posting-charset-alist
+When posting, @code{gnus-group-posting-charset-alist} is used to
+determine which charsets should not be encoded using the @acronym{MIME}
+encodings.  For instance, some hierarchies discourage using
+quoted-printable header encoding.
+
+This variable is an alist of regexps and permitted unencoded charsets
+for posting.  Each element of the alist has the form @code{(}@var{test
+header body-list}@code{)}, where:
+
+@table @var
+@item test
+is either a regular expression matching the newsgroup header or a
+variable to query,
+@item header
+is the charset which may be left unencoded in the header (@code{nil}
+means encode all charsets),
+@item body-list
+is a list of charsets which may be encoded using 8bit content-transfer
+encoding in the body, or one of the special values @code{nil} (always
+encode using quoted-printable) or @code{t} (always use 8bit).
+@end table
+
+@cindex Russian
+@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 @acronym{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} @acronym{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
 
@@ -6650,10 +9496,11 @@ signature after all.
 @cindex printing
 @kindex A P (Summary)
 @vindex gnus-ps-print-hook
-@findex gnus-summary-print-article 
+@findex gnus-summary-print-article
 Generate and print a PostScript image of the article buffer
-(@code{gnus-summary-print-article}).  @code{gnus-ps-print-hook} will be
-run just before printing the buffer.
+(@code{gnus-summary-print-article}).  @code{gnus-ps-print-hook} will
+be run just before printing the buffer.  An alternative way to print
+article is to use Muttprint (@pxref{Saving Articles}).
 
 @end table
 
@@ -6692,10 +9539,26 @@ Sort by date (@code{gnus-summary-sort-by-date}).
 @findex gnus-summary-sort-by-lines
 Sort by lines (@code{gnus-summary-sort-by-lines}).
 
+@item C-c C-s C-c
+@kindex C-c C-s C-c (Summary)
+@findex gnus-summary-sort-by-chars
+Sort by article length (@code{gnus-summary-sort-by-chars}).
+
 @item C-c C-s C-i
 @kindex C-c C-s C-i (Summary)
 @findex gnus-summary-sort-by-score
 Sort by score (@code{gnus-summary-sort-by-score}).
+
+@item C-c C-s C-r
+@kindex C-c C-s C-r (Summary)
+@findex gnus-summary-sort-by-random
+Randomize (@code{gnus-summary-sort-by-random}).
+
+@item C-c C-s C-o
+@kindex C-c C-s C-o (Summary)
+@findex gnus-summary-sort-by-original
+Sort using the default sorting method
+(@code{gnus-summary-sort-by-original}).
 @end table
 
 These functions will work both when you use threading and when you don't
@@ -6717,7 +9580,7 @@ Commands}).
 @findex gnus-summary-refer-parent-article
 If you'd like to read the parent of the current article, and it is not
 displayed in the summary buffer, you might still be able to.  That is,
-if the current group is fetched by @sc{nntp}, the parent hasn't expired
+if the current group is fetched by @acronym{NNTP}, the parent hasn't expired
 and the @code{References} in the current article are not mangled, you
 can just press @kbd{^} or @kbd{A r}
 (@code{gnus-summary-refer-parent-article}).  If everything goes well,
@@ -6726,10 +9589,10 @@ summary buffer, point will just move to this article.
 
 If given a positive numerical prefix, fetch that many articles back into
 the ancestry.  If given a negative numerical prefix, fetch just that
-ancestor.  So if you say @kbd{3 ^}, Gnus will fetch the parent, the
+ancestor.  So if you say @kbd{3 ^}, gnus will fetch the parent, the
 grandparent and the grandgrandparent of the current article.  If you say
-@kbd{-3 ^}, Gnus will only fetch the grandgrandparent of the current
-article. 
+@kbd{-3 ^}, gnus will only fetch the grandgrandparent of the current
+article.
 
 @item A R (Summary)
 @findex gnus-summary-refer-references
@@ -6760,7 +9623,7 @@ by giving the @kbd{A T} command a numerical prefix.
 @kindex M-^ (Summary)
 @cindex Message-ID
 @cindex fetching by Message-ID
-You can also ask the @sc{nntp} server for an arbitrary article, no
+You can also ask the @acronym{NNTP} server for an arbitrary article, no
 matter what group it belongs to.  @kbd{M-^}
 (@code{gnus-summary-refer-article}) will ask you for a
 @code{Message-ID}, which is one of those long, hard-to-read thingies
@@ -6773,26 +9636,41 @@ The current select method will be used when fetching by
 by giving this command a prefix.
 
 @vindex gnus-refer-article-method
-If the group you are reading is located on a backend that does not
+If the group you are reading is located on a back end that does not
 support fetching by @code{Message-ID} very well (like @code{nnspool}),
-you can set @code{gnus-refer-article-method} to an @sc{nntp} method.  It
-would, perhaps, be best if the @sc{nntp} server you consult is the one
+you can set @code{gnus-refer-article-method} to an @acronym{NNTP} method.  It
+would, perhaps, be best if the @acronym{NNTP} server you consult is the one
 updating the spool you are reading from, but that's not really
 necessary.
 
-Most of the mail backends support fetching by @code{Message-ID}, but do
-not do a particularly excellent job at it.  That is, @code{nnmbox} and
-@code{nnbabyl} are able to locate articles from any groups, while
-@code{nnml} and @code{nnfolder} are only able to locate articles that
-have been posted to the current group.  (Anything else would be too time
-consuming.)  @code{nnmh} does not support this at all.
+It can also be a list of select methods, as well as the special symbol
+@code{current}, which means to use the current select method.  If it
+is a list, Gnus will try all the methods in the list until it finds a
+match.
+
+Here's an example setting that will first try the current method, and
+then ask Google if that fails:
+
+@lisp
+(setq gnus-refer-article-method
+      '(current
+        (nnweb "google" (nnweb-type google))))
+@end lisp
+
+Most of the mail back ends support fetching by @code{Message-ID}, but
+do not do a particularly excellent job at it.  That is, @code{nnmbox},
+@code{nnbabyl}, @code{nnmaildir}, @code{nnml}, are able to locate
+articles from any groups, while @code{nnfolder}, and @code{nnimap} are
+only able to locate articles that have been posted to the current
+group.  (Anything else would be too time consuming.)  @code{nnmh} does
+not support this at all.
 
 
 @node Alternative Approaches
 @section Alternative Approaches
 
 Different people like to read news using different methods.  This being
-Gnus, we offer a small selection of minor modes for the summary buffers.
+gnus, we offer a small selection of minor modes for the summary buffers.
 
 @menu
 * Pick and Read::               First mark articles and then read them.
@@ -6821,10 +9699,13 @@ Here are the available keystrokes when using pick mode:
 @table @kbd
 @item .
 @kindex . (Pick)
-@findex gnus-summary-mark-as-processable
-Pick the article on the current line
-(@code{gnus-summary-mark-as-processable}).  If given a numerical prefix,
-go to that article and pick it.  (The line number is normally displayed
+@findex gnus-pick-article-or-thread
+Pick the article or thread on the current line
+(@code{gnus-pick-article-or-thread}).  If the variable
+@code{gnus-thread-hide-subtree} is true, then this key selects the
+entire thread when used at the first article of the thread.  Otherwise,
+it selects just the article.  If given a numerical prefix, go to that
+thread or article and pick it.  (The line number is normally displayed
 at the beginning of the summary pick lines.)
 
 @item SPACE
@@ -6835,53 +9716,13 @@ at the end of the buffer, start reading the picked articles.
 
 @item u
 @kindex u (Pick)
-@findex gnus-summary-unmark-as-processable
-Unpick the article (@code{gnus-summary-unmark-as-processable}). 
-
-@item U
-@kindex U (Pick)
-@findex gnus-summary-unmark-all-processable
-Unpick all articles (@code{gnus-summary-unmark-all-processable}). 
-
-@item t
-@kindex t (Pick)
-@findex gnus-uu-mark-thread
-Pick the thread (@code{gnus-uu-mark-thread}). 
-
-@item T
-@kindex T (Pick)
-@findex gnus-uu-unmark-thread
-Unpick the thread (@code{gnus-uu-unmark-thread}). 
-
-@item r
-@kindex r (Pick)
-@findex gnus-uu-mark-region
-Pick the region (@code{gnus-uu-mark-region}). 
-
-@item R
-@kindex R (Pick)
-@findex gnus-uu-unmark-region
-Unpick the region (@code{gnus-uu-unmark-region}). 
-
-@item e
-@kindex e (Pick)
-@findex gnus-uu-mark-by-regexp
-Pick articles that match a regexp (@code{gnus-uu-mark-by-regexp}). 
-
-@item E
-@kindex E (Pick)
-@findex gnus-uu-unmark-by-regexp
-Unpick articles that match a regexp (@code{gnus-uu-unmark-by-regexp}). 
-
-@item b
-@kindex b (Pick)
-@findex gnus-uu-mark-buffer
-Pick the buffer (@code{gnus-uu-mark-buffer}). 
-
-@item B
-@kindex B (Pick)
-@findex gnus-uu-unmark-buffer
-Unpick the buffer (@code{gnus-uu-unmark-buffer}). 
+@findex gnus-pick-unmark-article-or-thread.
+Unpick the thread or article
+(@code{gnus-pick-unmark-article-or-thread}).  If the variable
+@code{gnus-thread-hide-subtree} is true, then this key unpicks the
+thread if used at the first article of the thread.  Otherwise it unpicks
+just the article.  You can give this key a numerical prefix to unpick
+the thread or article at that line.
 
 @item RET
 @kindex RET (Pick)
@@ -6894,6 +9735,11 @@ will still be visible when you are reading.
 
 @end table
 
+All the normal summary mode commands are still available in the
+pick-mode, with the exception of @kbd{u}.  However @kbd{!} is available
+which is mapped to the same function
+@code{gnus-summary-tick-article-forward}.
+
 If this sounds like a good idea to you, you could say:
 
 @lisp
@@ -6913,7 +9759,7 @@ standard format.  At the beginning of each line the line number is
 displayed.  The pick mode line format is controlled by the
 @code{gnus-summary-pick-line-format} variable (@pxref{Formatting
 Variables}).  It accepts the same format specs that
-@code{gnus-summary-line-format} does (@pxref{Summary Buffer Lines}). 
+@code{gnus-summary-line-format} does (@pxref{Summary Buffer Lines}).
 
 
 @node Binary Groups
@@ -6926,7 +9772,7 @@ If you spend much time in binary groups, you may grow tired of hitting
 @kbd{X u}, @kbd{n}, @kbd{RET} all the time.  @kbd{M-x gnus-binary-mode}
 is a minor mode for summary buffers that makes all ordinary Gnus article
 selection functions uudecode series of articles and display the result
-instead of just displaying the articles the normal way.  
+instead of just displaying the articles the normal way.
 
 @kindex g (Binary)
 @findex gnus-binary-show-article
@@ -6943,10 +9789,10 @@ command, when you have turned on this mode
 @cindex trees
 
 @vindex gnus-use-trees
-If you don't like the normal Gnus summary display, you might try setting
+If you don't like the normal gnus summary display, you might try setting
 @code{gnus-use-trees} to @code{t}.  This will create (by default) an
 additional @dfn{tree buffer}.  You can execute all summary mode commands
-in the tree buffer.  
+in the tree buffer.
 
 There are a few variables to customize the tree display, of course:
 
@@ -6957,9 +9803,9 @@ A hook called in all tree mode buffers.
 
 @item gnus-tree-mode-line-format
 @vindex gnus-tree-mode-line-format
-A format string for the mode bar in the tree mode buffers.  The default
-is @samp{Gnus: %%b %S %Z}.  For a list of valid specs, @pxref{Summary
-Buffer Mode Line}. 
+A format string for the mode bar in the tree mode buffers (@pxref{Mode
+Line Formatting}).  The default is @samp{Gnus: %%b %S %Z}.  For a list
+of valid specs, @pxref{Summary Buffer Mode Line}.
 
 @item gnus-selected-tree-face
 @vindex gnus-selected-tree-face
@@ -6985,7 +9831,7 @@ The @code{From} header.
 The number of the article.
 @item [
 The opening bracket.
-@item ] 
+@item ]
 The closing bracket.
 @item s
 The subject.
@@ -6999,27 +9845,39 @@ Variables related to the display are:
 @item gnus-tree-brackets
 @vindex gnus-tree-brackets
 This is used for differentiating between ``real'' articles and
-``sparse'' articles.  The format is @var{((real-open . real-close)
-(sparse-open . sparse-close) (dummy-open . dummy-close))}, and the
-default is @code{((?[ . ?]) (?( . ?)) (?@{ . ?@}) (?< . ?>))}.
+``sparse'' articles.  The format is
+@example
+((@var{real-open} . @var{real-close})
+ (@var{sparse-open} . @var{sparse-close})
+ (@var{dummy-open} . @var{dummy-close}))
+@end example
+and the default is @code{((?[ . ?]) (?( . ?)) (?@{ . ?@}) (?< . ?>))}.
 
 @item gnus-tree-parent-child-edges
 @vindex gnus-tree-parent-child-edges
 This is a list that contains the characters used for connecting parent
-nodes to their children.  The default is @code{(?- ?\\ ?|)}. 
+nodes to their children.  The default is @code{(?- ?\\ ?|)}.
 
 @end table
 
 @item gnus-tree-minimize-window
 @vindex gnus-tree-minimize-window
-If this variable is non-@code{nil}, Gnus will try to keep the tree
-buffer as small as possible to allow more room for the other Gnus
+If this variable is non-@code{nil}, gnus will try to keep the tree
+buffer as small as possible to allow more room for the other gnus
 windows.  If this variable is a number, the tree buffer will never be
 higher than that number.  The default is @code{t}.  Note that if you
 have several windows displayed side-by-side in a frame and the tree
 buffer is one of these, minimizing the tree window will also resize all
 other windows displayed next to it.
 
+You may also wish to add the following hook to keep the window minimized
+at all times:
+
+@lisp
+(add-hook 'gnus-configure-windows-hook
+          'gnus-tree-perhaps-minimize)
+@end lisp
+
 @item gnus-generate-tree-function
 @vindex gnus-generate-tree-function
 @findex gnus-generate-horizontal-tree
@@ -7046,6 +9904,7 @@ Here's an example from a horizontal tree buffer:
 Here's the same thread displayed in a vertical tree buffer:
 
 @example
+@group
 @{***@}
   |--------------------------\-----\-----\
 (***)                         [Bjo] [Gun] [Gun]
@@ -7055,11 +9914,12 @@ Here's the same thread displayed in a vertical tree buffer:
 [Gun]       [Eri] [Eri] [odd]
                           |
                         [Paa]
+@end group
 @end example
 
 If you're using horizontal trees, it might be nice to display the trees
 side-by-side with the summary buffer.  You could add something like the
-following to your @file{.gnus.el} file:
+following to your @file{~/.gnus.el} file:
 
 @lisp
 (setq gnus-use-trees t
@@ -7074,7 +9934,7 @@ following to your @file{.gnus.el} file:
              (article 1.0))))
 @end lisp
 
-@xref{Windows Configuration}.
+@xref{Window Layout}.
 
 
 @node Mail Group Commands
@@ -7092,11 +9952,13 @@ process/prefix convention (@pxref{Process/Prefix}).
 @item B e
 @kindex B e (Summary)
 @findex gnus-summary-expire-articles
-Expire all expirable articles in the group
-(@code{gnus-summary-expire-articles}).
+Run all expirable articles in the current group through the expiry
+process (@code{gnus-summary-expire-articles}).  That is, delete all
+expirable articles in the group that have been around for a while.
+(@pxref{Expiring Mail}).
 
-@item B M-C-e
-@kindex B M-C-e (Summary)
+@item B C-M-e
+@kindex B C-M-e (Summary)
 @findex gnus-summary-expire-articles-now
 Delete all the expirable articles in the group
 (@code{gnus-summary-expire-articles-now}).  This means that @strong{all}
@@ -7115,8 +9977,10 @@ disk forever and ever, never to return again.'' Use with caution.
 @kindex B m (Summary)
 @cindex move mail
 @findex gnus-summary-move-article
+@vindex gnus-preserve-marks
 Move the article from one mail group to another
-(@code{gnus-summary-move-article}). 
+(@code{gnus-summary-move-article}).  Marks will be preserved if
+@code{gnus-preserve-marks} is non-@code{nil} (which is the default).
 
 @item B c
 @kindex B c (Summary)
@@ -7124,7 +9988,8 @@ Move the article from one mail group to another
 @findex gnus-summary-copy-article
 @c @icon{gnus-summary-mail-copy}
 Copy the article from one group (mail group or not) to a mail group
-(@code{gnus-summary-copy-article}).
+(@code{gnus-summary-copy-article}).  Marks will be preserved if
+@code{gnus-preserve-marks} is non-@code{nil} (which is the default).
 
 @item B B
 @kindex B B (Summary)
@@ -7142,13 +10007,23 @@ Import an arbitrary file into the current mail newsgroup
 (@code{gnus-summary-import-article}).  You will be prompted for a file
 name, a @code{From} header and a @code{Subject} header.
 
+@item B I
+@kindex B I (Summary)
+@findex gnus-summary-create-article
+Create an empty article in the current mail newsgroups
+(@code{gnus-summary-create-article}).  You will be prompted for a
+@code{From} header and a @code{Subject} header.
+
 @item B r
 @kindex B r (Summary)
 @findex gnus-summary-respool-article
-Respool the mail article (@code{gnus-summary-move-article}).
+@vindex gnus-summary-respool-default-method
+Respool the mail article (@code{gnus-summary-respool-article}).
 @code{gnus-summary-respool-default-method} will be used as the default
 select method when respooling.  This variable is @code{nil} by default,
 which means that the current group select method will be used instead.
+Marks will be preserved if @code{gnus-preserve-marks} is non-@code{nil}
+(which is the default).
 
 @item B w
 @itemx e
@@ -7156,22 +10031,29 @@ which means that the current group select method will be used instead.
 @kindex e (Summary)
 @findex gnus-summary-edit-article
 @kindex C-c C-c (Article)
+@findex gnus-summary-edit-article-done
 Edit the current article (@code{gnus-summary-edit-article}).  To finish
 editing and make the changes permanent, type @kbd{C-c C-c}
-(@kbd{gnus-summary-edit-article-done}).  If you give a prefix to the
-@kbd{C-c C-c} command, Gnus won't re-highlight the article.
+(@code{gnus-summary-edit-article-done}).  If you give a prefix to the
+@kbd{C-c C-c} command, gnus won't re-highlight the article.
 
 @item B q
 @kindex B q (Summary)
 @findex gnus-summary-respool-query
 If you want to re-spool an article, you might be curious as to what group
 the article will end up in before you do the re-spooling.  This command
-will tell you (@code{gnus-summary-respool-query}). 
+will tell you (@code{gnus-summary-respool-query}).
+
+@item B t
+@kindex B t (Summary)
+@findex gnus-summary-respool-trace
+Similarly, this command will display all fancy splitting patterns used
+when respooling, if any (@code{gnus-summary-respool-trace}).
 
 @item B p
 @kindex B p (Summary)
 @findex gnus-summary-article-posted-p
-Some people have a tendency to send you "courtesy" copies when they
+Some people have a tendency to send you ``courtesy'' copies when they
 follow up to articles you have posted.  These usually have a
 @code{Newsgroups} header in them, but not always.  This command
 (@code{gnus-summary-article-posted-p}) will try to fetch the current
@@ -7182,15 +10064,25 @@ it didn't find the article, it may have been posted anyway---mail
 propagation is much faster than news propagation, and the news copy may
 just not have arrived yet.
 
+@item K E
+@kindex K E (Summary)
+@findex gnus-article-encrypt-body
+@vindex gnus-article-encrypt-protocol
+Encrypt the body of an article (@code{gnus-article-encrypt-body}).
+The body is encrypted with the encryption protocol specified by the
+variable @code{gnus-article-encrypt-protocol}.
+
 @end table
 
 @vindex gnus-move-split-methods
 @cindex moving articles
-If you move (or copy) articles regularly, you might wish to have Gnus
+If you move (or copy) articles regularly, you might wish to have gnus
 suggest where to put the articles.  @code{gnus-move-split-methods} is a
 variable that uses the same syntax as @code{gnus-split-methods}
 (@pxref{Saving Articles}).  You may customize that variable to create
-suggestions you find reasonable.
+suggestions you find reasonable.  (Note that
+@code{gnus-move-split-methods} uses group names where
+@code{gnus-split-methods} uses file names.)
 
 @lisp
 (setq gnus-move-split-methods
@@ -7204,13 +10096,25 @@ suggestions you find reasonable.
 @section Various Summary Stuff
 
 @menu
-* Summary Group Information::         Information oriented commands.
-* Searching for Articles::            Multiple article commands.
-* Summary Generation Commands::       (Re)generating the summary buffer.
-* Really Various Summary Commands::   Those pesky non-conformant commands.
+* Summary Group Information::   Information oriented commands.
+* Searching for Articles::      Multiple article commands.
+* Summary Generation Commands::
+* Really Various Summary Commands::  Those pesky non-conformant commands.
 @end menu
 
 @table @code
+@vindex gnus-summary-display-while-building
+@item gnus-summary-display-while-building
+If non-@code{nil}, show and update the summary buffer as it's being
+built.  If @code{t}, update the buffer after every line is inserted.
+If the value is an integer, @var{n}, update the display every @var{n}
+lines.  The default is @code{nil}.
+
+@vindex gnus-summary-display-arrow
+@item gnus-summary-display-arrow
+If non-@code{nil}, display an arrow in the fringe to indicate the
+current article.
+
 @vindex gnus-summary-mode-hook
 @item gnus-summary-mode-hook
 This hook is called when creating a summary mode buffer.
@@ -7229,17 +10133,54 @@ It is called after the summary buffer has been generated.  You might use
 it to, for instance, highlight lines or modify the look of the buffer in
 some other ungodly manner.  I don't care.
 
+@vindex gnus-summary-prepared-hook
+@item gnus-summary-prepared-hook
+A hook called as the very last thing after the summary buffer has been
+generated.
+
 @vindex gnus-summary-ignore-duplicates
 @item gnus-summary-ignore-duplicates
-When Gnus discovers two articles that have the same @code{Message-ID},
+When gnus discovers two articles that have the same @code{Message-ID},
 it has to do something drastic.  No articles are allowed to have the
 same @code{Message-ID}, but this may happen when reading mail from some
 sources.  Gnus allows you to customize what happens with this variable.
-If it is @code{nil} (which is the default), Gnus will rename the
+If it is @code{nil} (which is the default), gnus will rename the
 @code{Message-ID} (for display purposes only) and display the article as
 any other article.  If this variable is @code{t}, it won't display the
 article---it'll be as if it never existed.
 
+@vindex gnus-alter-articles-to-read-function
+@item gnus-alter-articles-to-read-function
+This function, which takes two parameters (the group name and the list
+of articles to be selected), is called to allow the user to alter the
+list of articles to be selected.
+
+For instance, the following function adds the list of cached articles to
+the list in one particular group:
+
+@lisp
+(defun my-add-cached-articles (group articles)
+  (if (string= group "some.group")
+      (append gnus-newsgroup-cached articles)
+    articles))
+@end lisp
+
+@vindex gnus-newsgroup-variables
+@item gnus-newsgroup-variables
+A list of newsgroup (summary buffer) local variables, or cons of
+variables and their default values (when the default values are not
+@code{nil}), that should be made global while the summary buffer is
+active.  These variables can be used to set variables in the group
+parameters while still allowing them to affect operations done in
+other buffers.  For example:
+
+@lisp
+(setq gnus-newsgroup-variables
+      '(message-use-followup-to
+        (gnus-visible-headers .
+ "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^To:")))
+@end lisp
+
 @end table
 
 
@@ -7252,13 +10193,13 @@ article---it'll be as if it never existed.
 @kindex H f (Summary)
 @findex gnus-summary-fetch-faq
 @vindex gnus-group-faq-directory
-Try to fetch the FAQ (list of frequently asked questions) for the
-current group (@code{gnus-summary-fetch-faq}).  Gnus will try to get the
-FAQ from @code{gnus-group-faq-directory}, which is usually a directory
-on a remote machine.  This variable can also be a list of directories.
-In that case, giving a prefix to this command will allow you to choose
-between the various sites.  @code{ange-ftp} or @code{efs} will probably
-be used for fetching the file.
+Try to fetch the @acronym{FAQ} (list of frequently asked questions)
+for the current group (@code{gnus-summary-fetch-faq}).  Gnus will try
+to get the @acronym{FAQ} from @code{gnus-group-faq-directory}, which
+is usually a directory on a remote machine.  This variable can also be
+a list of directories.  In that case, giving a prefix to this command
+will allow you to choose between the various sites.  @code{ange-ftp}
+or @code{efs} will probably be used for fetching the file.
 
 @item H d
 @kindex H d (Summary)
@@ -7276,7 +10217,7 @@ keystrokes (@code{gnus-summary-describe-briefly}).
 @item H i
 @kindex H i (Summary)
 @findex gnus-info-find-node
-Go to the Gnus info node (@code{gnus-info-find-node}).
+Go to the gnus info node (@code{gnus-info-find-node}).
 @end table
 
 
@@ -7288,22 +10229,26 @@ Go to the Gnus info node (@code{gnus-info-find-node}).
 @item M-s
 @kindex M-s (Summary)
 @findex gnus-summary-search-article-forward
-Search through all subsequent articles for a regexp
-(@code{gnus-summary-search-article-forward}). 
+Search through all subsequent (raw) articles for a regexp
+(@code{gnus-summary-search-article-forward}).
 
 @item M-r
 @kindex M-r (Summary)
 @findex gnus-summary-search-article-backward
-Search through all previous articles for a regexp
-(@code{gnus-summary-search-article-backward}). 
+Search through all previous (raw) articles for a regexp
+(@code{gnus-summary-search-article-backward}).
 
 @item &
 @kindex & (Summary)
 @findex gnus-summary-execute-command
-This command will prompt you for a header field, a regular expression to
-match on this field, and a command to be executed if the match is made
-(@code{gnus-summary-execute-command}).  If given a prefix, search
-backward instead.
+This command will prompt you for a header, a regular expression to match
+on this field, and a command to be executed if the match is made
+(@code{gnus-summary-execute-command}).  If the header is an empty
+string, the match is done on the entire article.  If given a prefix,
+search backward instead.
+
+For instance, @kbd{& RET some.*string RET #} will put the process mark on
+all articles that have heads or bodies that match @samp{some.*string}.
 
 @item M-&
 @kindex M-& (Summary)
@@ -7322,12 +10267,18 @@ the process mark (@code{gnus-summary-universal-argument}).
 @findex gnus-summary-prepare
 Regenerate the current summary buffer (@code{gnus-summary-prepare}).
 
-@item Y c 
+@item Y c
 @kindex Y c (Summary)
 @findex gnus-summary-insert-cached-articles
 Pull all cached articles (for the current group) into the summary buffer
 (@code{gnus-summary-insert-cached-articles}).
 
+@item Y d
+@kindex Y d (Summary)
+@findex gnus-summary-insert-dormant-articles
+Pull all dormant articles (for the current group) into the summary buffer
+(@code{gnus-summary-insert-dormant-articles}).
+
 @end table
 
 
@@ -7336,8 +10287,10 @@ Pull all cached articles (for the current group) into the summary buffer
 
 @table @kbd
 
-@item C-d
+@item A D
+@itemx C-d
 @kindex C-d (Summary)
+@kindex A D (Summary)
 @findex gnus-summary-enter-digest-group
 If the current article is a collection of other articles (for instance,
 a digest), you might use this command to enter a group based on the that
@@ -7348,8 +10301,8 @@ whenever you see a message that is a collection of other messages of
 some format, you @kbd{C-d} and read these messages in a more convenient
 fashion.
 
-@item M-C-d
-@kindex M-C-d (Summary)
+@item C-M-d
+@kindex C-M-d (Summary)
 @findex gnus-summary-read-document
 This command is very similar to the one above, but lets you gather
 several documents into one biiig group
@@ -7357,7 +10310,7 @@ several documents into one biiig group
 @code{nndoc} groups for each document, and then opening an
 @code{nnvirtual} group on top of these @code{nndoc} groups.  This
 command understands the process/prefix convention
-(@pxref{Process/Prefix}). 
+(@pxref{Process/Prefix}).
 
 @item C-t
 @kindex C-t (Summary)
@@ -7371,14 +10324,20 @@ to have truncation switched off while reading articles.
 @kindex = (Summary)
 @findex gnus-summary-expand-window
 Expand the summary buffer window (@code{gnus-summary-expand-window}).
-If given a prefix, force an @code{article} window configuration. 
+If given a prefix, force an @code{article} window configuration.
 
-@item M-C-e
-@kindex M-C-e (Summary)
+@item C-M-e
+@kindex C-M-e (Summary)
 @findex gnus-summary-edit-parameters
 Edit the group parameters (@pxref{Group Parameters}) of the current
 group (@code{gnus-summary-edit-parameters}).
 
+@item C-M-a
+@kindex C-M-a (Summary)
+@findex gnus-summary-customize-parameters
+Customize the group parameters (@pxref{Group Parameters}) of the current
+group (@code{gnus-summary-customize-parameters}).
+
 @end table
 
 
@@ -7388,20 +10347,23 @@ group (@code{gnus-summary-edit-parameters}).
 @cindex exiting groups
 
 Exiting from the summary buffer will normally update all info on the
-group and return you to the group buffer. 
+group and return you to the group buffer.
 
 @table @kbd
 
 @item Z Z
+@itemx Z Q
 @itemx q
 @kindex Z Z (Summary)
+@kindex Z Q (Summary)
 @kindex q (Summary)
 @findex gnus-summary-exit
 @vindex gnus-summary-exit-hook
 @vindex gnus-summary-prepare-exit-hook
+@vindex gnus-group-no-more-groups-hook
 @c @icon{gnus-summary-exit}
 Exit the current group and update all information on the group
-(@code{gnus-summary-exit}). @code{gnus-summary-prepare-exit-hook} is
+(@code{gnus-summary-exit}).  @code{gnus-summary-prepare-exit-hook} is
 called before doing much of the exiting, which calls
 @code{gnus-summary-expire-articles} by default.
 @code{gnus-summary-exit-hook} is called after finishing the exit
@@ -7435,10 +10397,12 @@ Mark all articles, even the ticked ones, as read and then exit
 @kindex Z n (Summary)
 @findex gnus-summary-catchup-and-goto-next-group
 Mark all articles as read and go to the next group
-(@code{gnus-summary-catchup-and-goto-next-group}). 
+(@code{gnus-summary-catchup-and-goto-next-group}).
 
 @item Z R
+@itemx C-x C-s
 @kindex Z R (Summary)
+@kindex C-x C-s (Summary)
 @findex gnus-summary-reselect-current-group
 Exit this group, and then enter it again
 (@code{gnus-summary-reselect-current-group}).  If given a prefix, select
@@ -7458,13 +10422,13 @@ articles, both read and unread.
 @kindex Z N (Summary)
 @findex gnus-summary-next-group
 Exit the group and go to the next group
-(@code{gnus-summary-next-group}). 
+(@code{gnus-summary-next-group}).
 
 @item Z P
 @kindex Z P (Summary)
 @findex gnus-summary-prev-group
 Exit the group and go to the previous group
-(@code{gnus-summary-prev-group}). 
+(@code{gnus-summary-prev-group}).
 
 @item Z s
 @kindex Z s (Summary)
@@ -7476,23 +10440,24 @@ command will make exit without updating (the @kbd{Q} command) worthless.
 @end table
 
 @vindex gnus-exit-group-hook
-@code{gnus-exit-group-hook} is called when you exit the current
-group.  
+@code{gnus-exit-group-hook} is called when you exit the current group
+with an ``updating'' exit.  For instance @kbd{Q}
+(@code{gnus-summary-exit-no-update}) does not call this hook.
 
 @findex gnus-summary-wake-up-the-dead
 @findex gnus-dead-summary-mode
 @vindex gnus-kill-summary-on-exit
 If you're in the habit of exiting groups, and then changing your mind
 about it, you might set @code{gnus-kill-summary-on-exit} to @code{nil}.
-If you do that, Gnus won't kill the summary buffer when you exit it.
+If you do that, gnus won't kill the summary buffer when you exit it.
 (Quelle surprise!)  Instead it will change the name of the buffer to
 something like @samp{*Dead Summary ... *} and install a minor mode
 called @code{gnus-dead-summary-mode}.  Now, if you switch back to this
 buffer, you'll find that all keys are mapped to a function called
 @code{gnus-summary-wake-up-the-dead}.  So tapping any keys in a dead
-summary buffer will result in a live, normal summary buffer.  
+summary buffer will result in a live, normal summary buffer.
 
-There will never be more than one dead summary buffer at any one time. 
+There will never be more than one dead summary buffer at any one time.
 
 @vindex gnus-use-cross-reference
 The data on the current group will be updated (which articles you have
@@ -7516,7 +10481,7 @@ posted it to several groups separately.  Posting the same article to
 several groups (not cross-posting) is called @dfn{spamming}, and you are
 by law required to send nasty-grams to anyone who perpetrates such a
 heinous crime.  You may want to try NoCeM handling to filter out spam
-(@pxref{NoCeM}). 
+(@pxref{NoCeM}).
 
 Remember: Cross-posting is kinda ok, but posting the same article
 separately to several groups is not.  Massive cross-posting (aka.
@@ -7526,11 +10491,11 @@ excessive crossposting (@pxref{Summary Mail Commands}).
 
 @cindex cross-posting
 @cindex Xref
-@cindex @sc{nov}
+@cindex @acronym{NOV}
 One thing that may cause Gnus to not do the cross-posting thing
-correctly is if you use an @sc{nntp} server that supports @sc{xover}
+correctly is if you use an @acronym{NNTP} server that supports @sc{xover}
 (which is very nice, because it speeds things up considerably) which
-does not include the @code{Xref} header in its @sc{nov} lines.  This is
+does not include the @code{Xref} header in its @acronym{NOV} lines.  This is
 Evil, but all too common, alas, alack.  Gnus tries to Do The Right Thing
 even with @sc{xover} by registering the @code{Xref} lines of all
 articles you actually read, but if you kill the articles, or just mark
@@ -7540,7 +10505,7 @@ the cross reference mechanism.
 
 @cindex LIST overview.fmt
 @cindex overview.fmt
-To check whether your @sc{nntp} server includes the @code{Xref} header
+To check whether your @acronym{NNTP} server includes the @code{Xref} header
 in its overview files, try @samp{telnet your.nntp.server nntp},
 @samp{MODE READER} on @code{inn} servers, and then say @samp{LIST
 overview.fmt}.  This may not work, but if it does, and the last line you
@@ -7561,24 +10526,24 @@ For an alternative approach, @pxref{Duplicate Suppression}.
 @node Duplicate Suppression
 @section Duplicate Suppression
 
-By default, Gnus tries to make sure that you don't have to read the same
+By default, gnus tries to make sure that you don't have to read the same
 article more than once by utilizing the crossposting mechanism
 (@pxref{Crosspost Handling}).  However, that simple and efficient
 approach may not work satisfactory for some users for various
-reasons.  
+reasons.
 
 @enumerate
-@item 
-The @sc{nntp} server may fail to generate the @code{Xref} header.  This
+@item
+The @acronym{NNTP} server may fail to generate the @code{Xref} header.  This
 is evil and not very common.
 
-@item 
-The @sc{nntp} server may fail to include the @code{Xref} header in the
+@item
+The @acronym{NNTP} server may fail to include the @code{Xref} header in the
 @file{.overview} data bases.  This is evil and all too common, alas.
 
 @item
 You may be reading the same group (or several related groups) from
-different @sc{nntp} servers.
+different @acronym{NNTP} servers.
 
 @item
 You may be getting mail that duplicates articles posted to groups.
@@ -7612,13 +10577,13 @@ If non-@code{nil}, suppress duplicates.
 @vindex gnus-save-duplicate-list
 If non-@code{nil}, save the list of duplicates to a file.  This will
 make startup and shutdown take longer, so the default is @code{nil}.
-However, this means that only duplicate articles read in a single Gnus
+However, this means that only duplicate articles read in a single gnus
 session are suppressed.
 
 @item gnus-duplicate-list-length
 @vindex gnus-duplicate-list-length
 This variable says how many @code{Message-ID}s to keep in the duplicate
-suppression list.  The default is 10000.  
+suppression list.  The default is 10000.
 
 @item gnus-duplicate-file
 @vindex gnus-duplicate-file
@@ -7626,29 +10591,151 @@ The name of the file to store the duplicate suppression list in.  The
 default is @file{~/News/suppression}.
 @end table
 
-If you have a tendency to stop and start Gnus often, setting
+If you have a tendency to stop and start gnus often, setting
 @code{gnus-save-duplicate-list} to @code{t} is probably a good idea.  If
-you leave Gnus running for weeks on end, you may have it @code{nil}.  On
+you leave gnus running for weeks on end, you may have it @code{nil}.  On
 the other hand, saving the list makes startup and shutdown much slower,
-so that means that if you stop and start Gnus often, you should set
+so that means that if you stop and start gnus often, you should set
 @code{gnus-save-duplicate-list} to @code{nil}.  Uhm.  I'll leave this up
 to you to figure out, I think.
 
+@node Security
+@section Security
+
+Gnus is able to verify signed messages or decrypt encrypted messages.
+The formats that are supported are @acronym{PGP}, @acronym{PGP/MIME}
+and @acronym{S/MIME}, however you need some external programs to get
+things to work:
+
+@enumerate
+@item
+To handle @acronym{PGP} and @acronym{PGP/MIME} messages, you have to
+install an OpenPGP implementation such as GnuPG.  The Lisp interface
+to GnuPG included with Gnus is called PGG (@pxref{Top, ,PGG, pgg, PGG
+Manual}), but Mailcrypt and gpg.el are also supported.
+
+@item
+To handle @acronym{S/MIME} message, you need to install OpenSSL.  OpenSSL 0.9.6
+or newer is recommended.
+
+@end enumerate
+
+More information on how to set things up can be found in the message
+manual (@pxref{Security, ,Security, message, Message Manual}).
+
+@table @code
+@item mm-verify-option
+@vindex mm-verify-option
+Option of verifying signed parts.  @code{never}, not verify;
+@code{always}, always verify; @code{known}, only verify known
+protocols.  Otherwise, ask user.
+
+@item mm-decrypt-option
+@vindex mm-decrypt-option
+Option of decrypting encrypted parts.  @code{never}, no decryption;
+@code{always}, always decrypt; @code{known}, only decrypt known
+protocols.  Otherwise, ask user.
+
+@item mml1991-use
+@vindex mml1991-use
+Symbol indicating elisp interface to OpenPGP implementation for
+@acronym{PGP} messages.  The default is @code{pgg}, but
+@code{mailcrypt} and @code{gpg} are also supported although
+deprecated.
+
+@item mml2015-use
+@vindex mml2015-use
+Symbol indicating elisp interface to OpenPGP implementation for
+@acronym{PGP/MIME} messages.  The default is @code{pgg}, but
+@code{mailcrypt} and @code{gpg} are also supported although
+deprecated.
+
+@end table
+
+@cindex snarfing keys
+@cindex importing PGP keys
+@cindex PGP key ring import
+Snarfing OpenPGP keys (i.e., importing keys from articles into your
+key ring) is not supported explicitly through a menu item or command,
+rather Gnus do detect and label keys as @samp{application/pgp-keys},
+allowing you to specify whatever action you think is appropriate
+through the usual @acronym{MIME} infrastructure.  You can use a
+@file{~/.mailcap} entry (@pxref{mailcap, , mailcap, emacs-mime, The
+Emacs MIME Manual}) such as the following to import keys using GNU
+Privacy Guard when you click on the @acronym{MIME} button
+(@pxref{Using MIME}).
+
+@example
+application/pgp-keys; gpg --import --interactive --verbose; needsterminal
+@end example
+@noindent
+This happens to also be the default action defined in
+@code{mailcap-mime-data}.
+
+@node Mailing List
+@section Mailing List
+@cindex mailing list
+@cindex RFC 2396
+
+@kindex A M (summary)
+@findex gnus-mailing-list-insinuate
+Gnus understands some mailing list fields of RFC 2369.  To enable it,
+add a @code{to-list} group parameter (@pxref{Group Parameters}),
+possibly using @kbd{A M} (@code{gnus-mailing-list-insinuate}) in the
+summary buffer.
+
+That enables the following commands to the summary buffer:
+
+@table @kbd
+
+@item C-c C-n h
+@kindex C-c C-n h (Summary)
+@findex gnus-mailing-list-help
+Send a message to fetch mailing list help, if List-Help field exists.
+
+@item C-c C-n s
+@kindex C-c C-n s (Summary)
+@findex gnus-mailing-list-subscribe
+Send a message to subscribe the mailing list, if List-Subscribe field exists.
+
+@item C-c C-n u
+@kindex C-c C-n u (Summary)
+@findex gnus-mailing-list-unsubscribe
+Send a message to unsubscribe the mailing list, if List-Unsubscribe
+field exists.
+
+@item C-c C-n p
+@kindex C-c C-n p (Summary)
+@findex gnus-mailing-list-post
+Post to the mailing list, if List-Post field exists.
+
+@item C-c C-n o
+@kindex C-c C-n o (Summary)
+@findex gnus-mailing-list-owner
+Send a message to the mailing list owner, if List-Owner field exists.
+
+@item C-c C-n a
+@kindex C-c C-n a (Summary)
+@findex gnus-mailing-list-owner
+Browse the mailing list archive, if List-Archive field exists.
 
-@node The Article Buffer
-@chapter The Article Buffer
+@end table
+
+
+@node Article Buffer
+@chapter Article Buffer
 @cindex article buffer
 
 The articles are displayed in the article buffer, of which there is only
 one.  All the summary buffers share the same article buffer unless you
-tell Gnus otherwise.
+tell gnus otherwise.
 
 @menu
-* Hiding Headers::        Deciding what headers should be displayed.
-* Using MIME::            Pushing articles through @sc{mime} before reading them.
-* Customizing Articles::  Tailoring the look of the articles.
-* Article Keymap::        Keystrokes available in the article buffer.
-* Misc Article::          Other stuff.
+* Hiding Headers::              Deciding what headers should be displayed.
+* Using MIME::                  Pushing articles through @acronym{MIME} before reading them.
+* Customizing Articles::        Tailoring the look of the articles.
+* Article Keymap::              Keystrokes available in the article buffer.
+* Misc Article::                Other stuff.
 @end menu
 
 
@@ -7666,7 +10753,7 @@ who wrote the article, the date it was written and the subject of the
 article.  That's well and nice, but there's also lots of information
 most people do not want to see---what systems the article has passed
 through before reaching you, the @code{Message-ID}, the
-@code{References}, etc. ad nauseum---and you'll probably want to get rid
+@code{References}, etc. ad nauseam---and you'll probably want to get rid
 of some of those lines.  If you want to keep all those lines in the
 article buffer, you can set @code{gnus-show-all-headers} to @code{t}.
 
@@ -7697,8 +10784,8 @@ variable is set (and @code{gnus-visible-headers} is @code{nil}), it
 should be a regular expression that matches all lines that you want to
 hide.  All lines that do not match this variable will remain visible.
 
-For instance, if you just want to get rid of the @code{References} line
-and the @code{Xref} line, you might say:
+For instance, if you just want to get rid of the @code{References} field
+and the @code{Xref} field, you might say:
 
 @lisp
 (setq gnus-ignored-headers "^References:\\|^Xref:")
@@ -7729,28 +10816,37 @@ Any headers that are to remain visible, but are not listed in this
 variable, will be displayed in random order after all the headers listed in this variable.
 
 @findex gnus-article-hide-boring-headers
-@vindex gnus-article-display-hook
 @vindex gnus-boring-article-headers
-You can hide further boring headers by entering
-@code{gnus-article-hide-boring-headers} into
-@code{gnus-article-display-hook}.  What this function does depends on
-the @code{gnus-boring-article-headers} variable.  It's a list, but this
-list doesn't actually contain header names.  Instead is lists various
-@dfn{boring conditions} that Gnus can check and remove from sight.
+You can hide further boring headers by setting
+@code{gnus-treat-hide-boring-headers} to @code{head}.  What this function
+does depends on the @code{gnus-boring-article-headers} variable.  It's a
+list, but this list doesn't actually contain header names.  Instead it
+lists various @dfn{boring conditions} that Gnus can check and remove
+from sight.
 
 These conditions are:
 @table @code
 @item empty
 Remove all empty headers.
-@item newsgroups
-Remove the @code{Newsgroups} header if it only contains the current group
-name. 
 @item followup-to
 Remove the @code{Followup-To} header if it is identical to the
 @code{Newsgroups} header.
 @item reply-to
-Remove the @code{Reply-To} header if it lists the same address as the
-@code{From} header.
+Remove the @code{Reply-To} header if it lists the same addresses as
+the @code{From} header, or if the @code{broken-reply-to} group
+parameter is set.
+@item newsgroups
+Remove the @code{Newsgroups} header if it only contains the current group
+name.
+@item to-address
+Remove the @code{To} header if it only contains the address identical to
+the current group's @code{to-address} parameter.
+@item to-list
+Remove the @code{To} header if it only contains the address identical to
+the current group's @code{to-list} parameter.
+@item cc-list
+Remove the @code{CC} header if it only contains the address identical to
+the current group's @code{to-list} parameter.
 @item date
 Remove the @code{Date} header if the article is less than three days
 old.
@@ -7760,92 +10856,234 @@ Remove the @code{To} header if it is very long.
 Remove all @code{To} headers if there are more than one.
 @end table
 
-To include the four first elements, you could say something like;
+To include these three elements, you could say something like:
 
 @lisp
-(setq gnus-boring-article-headers 
-      '(empty newsgroups followup-to reply-to))
+(setq gnus-boring-article-headers
+      '(empty followup-to reply-to))
 @end lisp
 
 This is also the default value for this variable.
 
 
 @node Using MIME
-@section Using @sc{mime}
-@cindex @sc{mime}
+@section Using MIME
+@cindex @acronym{MIME}
 
 Mime is a standard for waving your hands through the air, aimlessly,
 while people stand around yawning.
 
-@sc{mime}, however, is a standard for encoding your articles, aimlessly,
+@acronym{MIME}, however, is a standard for encoding your articles, aimlessly,
 while all newsreaders die of fear.
 
-@sc{mime} may specify what character set the article uses, the encoding
+@acronym{MIME} may specify what character set the article uses, the encoding
 of the characters, and it also makes it possible to embed pictures and
 other naughty stuff in innocent-looking articles.
 
 @vindex gnus-show-mime
-@vindex gnus-show-mime-method
-@vindex gnus-strict-mime
-@findex metamail-buffer
-Gnus handles @sc{mime} by pushing the articles through
-@code{gnus-show-mime-method}, which is @code{metamail-buffer} by
-default.  This function calls the external @code{metamail} program to
-actually do the work.  One common problem with this program is that is
-thinks that it can't display 8-bit things in the Emacs buffer.  To tell
-it the truth, put something like the following in your
-@file{.bash_profile} file.  (You do use @code{bash}, don't you?)
-
-@example
-export MM_CHARSET="iso-8859-1"
-@end example
-
-For more information on @code{metamail}, see its manual page.
+@vindex gnus-article-display-method-for-mime
+@findex gnus-article-display-mime-message
+gnus handles @acronym{MIME} by pushing the articles through
+@code{gnus-article-display-method-for-mime}, which is
+@code{gnus-article-display-mime-message} by default.  This function
+calls the @acronym{SEMI} MIME-View program to actually do the work.  For
+more information on @acronym{SEMI} MIME-View, see its manual page
+(however it is not existed yet, sorry).
 
 Set @code{gnus-show-mime} to @code{t} if you want to use
-@sc{mime} all the time.  However, if @code{gnus-strict-mime} is
-non-@code{nil}, the @sc{mime} method will only be used if there are
-@sc{mime} headers in the article.  If you have @code{gnus-show-mime}
-set, then you'll see some unfortunate display glitches in the article
-buffer.  These can't be avoided.
-
-It might be best to just use the toggling functions from the summary
-buffer to avoid getting nasty surprises. (For instance, you enter the
-group @samp{alt.sing-a-long} and, before you know it, @sc{mime} has
-decoded the sound file in the article and some horrible sing-a-long song
-comes screaming out your speakers, and you can't find the volume
-button, because there isn't one, and people are starting to look at you,
-and you try to stop the program, but you can't, and you can't find the
-program to control the volume, and everybody else in the room suddenly
-decides to look at you disdainfully, and you'll feel rather stupid.)
+@acronym{MIME} all the time.  If you have @code{gnus-show-mime} set,
+then you'll see some unfortunate display glitches in the article buffer.
+These can't be avoided.
+
+In GNUS or Gnus, it might be best to just use the toggling functions
+from the summary buffer to avoid getting nasty surprises. (For instance,
+you enter the group @samp{alt.sing-a-long} and, before you know it,
+@acronym{MIME} has decoded the sound file in the article and some
+horrible sing-a-long song comes screaming out your speakers, and you
+can't find the volume button, because there isn't one, and people are
+starting to look at you, and you try to stop the program, but you can't,
+and you can't find the program to control the volume, and everybody else
+in the room suddenly decides to look at you disdainfully, and you'll
+feel rather stupid.)
 
 Any similarity to real events and people is purely coincidental.  Ahem.
 
+To avoid such kind of situation, gnus stops to use
+@code{metamail-buffer}.  So now, you can set @code{gnus-show-mime} to
+non-@code{nil} every-time, then you can push button in the article
+buffer when there are nobody else.
+
+Also @pxref{MIME Commands}.
+
 
 @node Customizing Articles
 @section Customizing Articles
 @cindex article customization
 
-@vindex gnus-article-display-hook
-The @code{gnus-article-display-hook} is called after the article has
-been inserted into the article buffer.  It is meant to handle all
-treatment of the article before it is displayed. 
+A slew of functions for customizing how the articles are to look like
+exist.  You can call these functions interactively
+(@pxref{Article Washing}), or you can have them
+called automatically when you select the articles.
 
-@findex gnus-article-maybe-highlight
-By default this hook just contains @code{gnus-article-hide-headers},
-@code{gnus-article-treat-overstrike}, and
-@code{gnus-article-maybe-highlight}, but there are thousands, nay
-millions, of functions you can put in this hook.  For an overview of
-functions @pxref{Article Highlighting}, @pxref{Article Hiding},
-@pxref{Article Washing}, @pxref{Article Buttons} and @pxref{Article
-Date}.  Note that the order of functions in this hook might affect
-things, so you may have to fiddle a bit to get the desired results. 
-
-You can, of course, write your own functions.  The functions are called
-from the article buffer, and you can do anything you like, pretty much.
-There is no information that you have to keep in the buffer---you can
-change everything.  However, you shouldn't delete any headers.  Instead
-make them invisible if you want to make them go away.
+To have them called automatically, you should set the corresponding
+``treatment'' variable.  For instance, to have headers hidden, you'd set
+@code{gnus-treat-hide-headers}.  Below is a list of variables that can
+be set, but first we discuss the values these variables can have.
+
+Note: Some values, while valid, make little sense.  Check the list below
+for sensible values.
+
+@enumerate
+@item
+@code{nil}: Don't do this treatment.
+
+@item
+@code{t}: Do this treatment on all body parts.
+
+@item
+@code{head}: Do the treatment on the headers.
+
+@item
+@code{last}: Do this treatment on the last part.
+
+@item
+An integer: Do this treatment on all body parts that have a length less
+than this number.
+
+@item
+A list of strings: Do this treatment on all body parts that are in
+articles that are read in groups that have names that match one of the
+regexps in the list.
+
+@item
+A list where the first element is not a string:
+
+The list is evaluated recursively.  The first element of the list is a
+predicate.  The following predicates are recognized: @code{or},
+@code{and}, @code{not} and @code{typep}.  Here's an example:
+
+@lisp
+(or last
+    (typep "text/x-vcard"))
+@end lisp
+
+@item
+@code{mime}: Do this treatment if the value of @code{gnus-show-mime}' is
+non-nil.
+
+@end enumerate
+
+You may have noticed that the word @dfn{part} is used here.  This refers
+to the fact that some messages are @acronym{MIME} multipart articles that may
+be divided into several parts.  Articles that are not multiparts are
+considered to contain just a single part.
+
+@vindex gnus-article-treat-types
+Are the treatments applied to all sorts of multipart parts?  Yes, if you
+want to, but by default, only @samp{text/plain} parts are given the
+treatment.  This is controlled by the @code{gnus-article-treat-types}
+variable, which is a list of regular expressions that are matched to the
+type of the part.  This variable is ignored if the value of the
+controlling variable is a predicate list, as described above.
+
+The following treatment options are available.  The easiest way to
+customize this is to examine the @code{gnus-article-treat} customization
+group.  Values in parenthesis are suggested sensible values.  Others are
+possible but those listed are probably sufficient for most people.
+
+@table @code
+@item gnus-treat-buttonize (t, integer)
+@item gnus-treat-buttonize-head (head)
+
+@xref{Article Buttons}.
+
+@item gnus-treat-capitalize-sentences (t, integer)
+@item gnus-treat-overstrike (t, integer)
+@item gnus-treat-strip-cr (t, integer)
+@item gnus-treat-strip-headers-in-body (t, integer)
+@item gnus-treat-strip-leading-blank-lines (t, integer)
+@item gnus-treat-strip-multiple-blank-lines (t, integer)
+@item gnus-treat-strip-pem (t, last, integer)
+@item gnus-treat-strip-trailing-blank-lines (t, last, integer)
+@item gnus-treat-unsplit-urls (t, integer)
+@item gnus-treat-wash-html (t, integer)
+@item gnus-treat-decode-article-as-default-mime-charset (t, integer)
+
+@xref{Article Washing}.
+
+@item gnus-treat-date-english (head)
+@item gnus-treat-date-iso8601 (head)
+@item gnus-treat-date-lapsed (head)
+@item gnus-treat-date-local (head)
+@item gnus-treat-date-original (head)
+@item gnus-treat-date-user-defined (head)
+@item gnus-treat-date-ut (head)
+
+@xref{Article Date}.
+
+@item gnus-treat-from-picon (head)
+@item gnus-treat-mail-picon (head)
+@item gnus-treat-newsgroups-picon (head)
+
+@xref{Picons}.
+
+@item gnus-treat-display-smileys (t, integer)
+
+@item gnus-treat-body-boundary (head)
+
+@vindex gnus-body-boundary-delimiter
+Adds a delimiter between header and body, the string used as delimiter
+is controlled by @code{gnus-body-boundary-delimiter}.
+
+@xref{Smileys}.
+
+@item gnus-treat-display-x-face (head)
+
+@xref{X-Face}.
+
+@item gnus-treat-display-face (head)
+
+@xref{Face}.
+
+@item gnus-treat-emphasize (t, head, integer)
+@item gnus-treat-fill-article (t, integer)
+@item gnus-treat-fill-long-lines (t, integer)
+@item gnus-treat-hide-boring-headers (head)
+@item gnus-treat-hide-citation (t, integer)
+@item gnus-treat-hide-citation-maybe (t, integer)
+@item gnus-treat-hide-headers (head)
+@item gnus-treat-hide-signature (t, last)
+@item gnus-treat-strip-banner (t, last)
+@item gnus-treat-strip-list-identifiers (head)
+
+@xref{Article Hiding}.
+
+@item gnus-treat-highlight-citation (t, integer)
+@item gnus-treat-highlight-headers (head)
+@item gnus-treat-highlight-signature (t, last, integer)
+
+@xref{Article Highlighting}.
+
+@item gnus-treat-play-sounds
+@item gnus-treat-translate
+@item gnus-treat-x-pgp-sig (head)
+
+@item gnus-treat-unfold-headers (head)
+@item gnus-treat-fold-headers (head)
+@item gnus-treat-fold-newsgroups (head)
+@item gnus-treat-leading-whitespace (head)
+
+@xref{Article Header}.
+
+
+@end table
+
+@vindex gnus-part-display-hook
+You can, of course, write your own functions to be called from
+@code{gnus-part-display-hook}.  The functions are called narrowed to the
+part, and you can do anything you like, pretty much.  There is no
+information that you have to keep in the buffer---you can change
+everything.
 
 
 @node Article Keymap
@@ -7865,17 +11103,19 @@ A few additional keystrokes are available:
 @kindex SPACE (Article)
 @findex gnus-article-next-page
 Scroll forwards one page (@code{gnus-article-next-page}).
+This is exactly the same as @kbd{h SPACE h}.
 
 @item DEL
 @kindex DEL (Article)
 @findex gnus-article-prev-page
 Scroll backwards one page (@code{gnus-article-prev-page}).
+This is exactly the same as @kbd{h DEL h}.
 
 @item C-c ^
 @kindex C-c ^ (Article)
 @findex gnus-article-refer-article
 If point is in the neighborhood of a @code{Message-ID} and you press
-@kbd{r}, Gnus will try to get that article from the server
+@kbd{C-c ^}, Gnus will try to get that article from the server
 (@code{gnus-article-refer-article}).
 
 @item C-c C-m
@@ -7894,7 +11134,7 @@ Reconfigure the buffers so that the summary buffer becomes visible
 @kindex ? (Article)
 @findex gnus-article-describe-briefly
 Give a very brief description of the available keystrokes
-(@code{gnus-article-describe-briefly}). 
+(@code{gnus-article-describe-briefly}).
 
 @item TAB
 @kindex TAB (Article)
@@ -7905,7 +11145,24 @@ only makes sense if you have buttonizing turned on.
 @item M-TAB
 @kindex M-TAB (Article)
 @findex gnus-article-prev-button
-Go to the previous button, if any (@code{gnus-article-prev-button}).  
+Go to the previous button, if any (@code{gnus-article-prev-button}).
+
+@item R
+@kindex R (Article)
+@findex gnus-article-reply-with-original
+Send a reply to the current article and yank the current article
+(@code{gnus-article-reply-with-original}).  If given a prefix, make a
+wide reply.  If the region is active, only yank the text in the
+region.
+
+@item F
+@kindex F (Article)
+@findex gnus-article-followup-with-original
+Send a followup to the current article and yank the current article
+(@code{gnus-article-followup-with-original}).  If given a prefix, make
+a wide reply.  If the region is active, only yank the text in the
+region.
+
 
 @end table
 
@@ -7921,6 +11178,12 @@ If non-@code{nil}, use the same article buffer for all the groups.
 (This is the default.)  If @code{nil}, each group will have its own
 article buffer.
 
+@vindex gnus-article-decode-hook
+@item gnus-article-decode-hook
+@cindex @acronym{MIME}
+Hook used to decode @acronym{MIME} articles.  The default value is
+@code{(article-decode-charset article-decode-encoded-words)}
+
 @vindex gnus-article-prepare-hook
 @item gnus-article-prepare-hook
 This hook is called right after the article has been inserted into the
@@ -7928,12 +11191,6 @@ article buffer.  It is mainly intended for functions that do something
 depending on the contents; it should probably not be used for changing
 the contents of the article buffer.
 
-@vindex gnus-article-display-hook
-@item gnus-article-display-hook
-This hook is called as the last thing when displaying an article, and is
-intended for modifying the contents of the buffer, doing highlights,
-hiding headers, and the like.
-
 @item gnus-article-mode-hook
 @vindex gnus-article-mode-hook
 Hook called in article mode buffers.
@@ -7941,19 +11198,54 @@ Hook called in article mode buffers.
 @item gnus-article-mode-syntax-table
 @vindex gnus-article-mode-syntax-table
 Syntax table used in article buffers.  It is initialized from
-@code{text-mode-syntax-table}. 
+@code{text-mode-syntax-table}.
+
+@vindex gnus-article-over-scroll
+@item gnus-article-over-scroll
+If non-@code{nil}, allow scrolling the article buffer even when there
+no more new text to scroll in.  The default is @code{nil}.
 
 @vindex gnus-article-mode-line-format
 @item gnus-article-mode-line-format
 This variable is a format string along the same lines as
-@code{gnus-summary-mode-line-format}.  It accepts the same
-format specifications as that variable, with one extension:
+@code{gnus-summary-mode-line-format} (@pxref{Mode Line Formatting}).  It
+accepts the same format specifications as that variable, with two
+extensions:
 
 @table @samp
+
 @item w
 The @dfn{wash status} of the article.  This is a short string with one
 character for each possible article wash operation that may have been
-performed. 
+performed.  The characters and their meaning:
+
+@table @samp
+
+@item c
+Displayed when cited text may be hidden in the article buffer.
+
+@item h
+Displayed when headers are hidden in the article buffer.
+
+@item p
+Displayed when article is digitally signed or encrypted, and Gnus has
+hidden the security headers.  (N.B. does not tell anything about
+security status, i.e. good or bad signature.)
+
+@item s
+Displayed when the signature has been hidden in the Article buffer.
+
+@item o
+Displayed when Gnus has treated overstrike characters in the article buffer.
+
+@item e
+Displayed when Gnus has treated emphasised strings in the article buffer.
+
+@end table
+
+@item m
+The number of @acronym{MIME} parts in the article.
+
 @end table
 
 @vindex gnus-break-pages
@@ -7968,6 +11260,17 @@ paging will not be done.
 @vindex gnus-page-delimiter
 This is the delimiter mentioned above.  By default, it is @samp{^L}
 (formfeed).
+
+@cindex IDNA
+@cindex internationalized domain names
+@vindex gnus-use-idna
+@item gnus-use-idna
+This variable controls whether Gnus performs IDNA decoding of
+internationalized domain names inside @samp{From}, @samp{To} and
+@samp{Cc} headers.  This requires
+@uref{http://www.gnu.org/software/libidn/, GNU Libidn}, and this
+variable is only enabled if you have installed it.
+
 @end table
 
 
@@ -7980,26 +11283,29 @@ This is the delimiter mentioned above.  By default, it is @samp{^L}
 @cindex reply
 @cindex followup
 @cindex post
+@cindex using gpg
+@cindex using s/mime
+@cindex using smime
 
 @kindex C-c C-c (Post)
 All commands for posting and mailing will put you in a message buffer
-where you can edit the article all you like, before you send the article
-by pressing @kbd{C-c C-c}.  @xref{Top, , Top, message, The Message
-Manual}.  If you are in a foreign news group, and you wish to post the
-article using the foreign server, you can give a prefix to @kbd{C-c C-c}
-to make Gnus try to post using the foreign server.
-
-@menu 
-* Mail::                 Mailing and replying.
-* Post::                 Posting and following up.
-* Posting Server::       What server should you post via?
-* Mail and Post::        Mailing and posting at the same time.
-* Archived Messages::    Where Gnus stores the messages you've sent.
-* Drafts::               Postponing messages and rejected messages.
-* Rejected Articles::    What happens if the server doesn't like your article?
+where you can edit the article all you like, before you send the
+article by pressing @kbd{C-c C-c}.  @xref{Top, , Overview, message,
+Message Manual}.  Where the message will be posted/mailed to depends
+on your setup (@pxref{Posting Server}).
+
+@menu
+* Mail::                        Mailing and replying.
+* Posting Server::              What server should you post and mail via?
+* Mail and Post::               Mailing and posting at the same time.
+* Archived Messages::           Where Gnus stores the messages you've sent.
+* Posting Styles::              An easier way to specify who you are.
+* Drafts::                      Postponing messages and rejected messages.
+* Rejected Articles::           What happens if the server doesn't like your article?
+* Signing and encrypting::      How to compose secure messages.
 @end menu
 
-Also see @pxref{Canceling and Superseding} for information on how to
+Also @pxref{Canceling and Superseding} for information on how to
 remove articles you shouldn't have posted.
 
 
@@ -8012,37 +11318,29 @@ Variables for customizing outgoing mail:
 @item gnus-uu-digest-headers
 @vindex gnus-uu-digest-headers
 List of regexps to match headers included in digested messages.  The
-headers will be included in the sequence they are matched.
+headers will be included in the sequence they are matched.  If
+@code{nil} include all headers.
 
 @item gnus-add-to-list
 @vindex gnus-add-to-list
 If non-@code{nil}, add a @code{to-list} group parameter to mail groups
 that have none when you do a @kbd{a}.
 
-@end table
-
-
-@node Post
-@section Post
-
-Variables for composing news articles:
+@item gnus-confirm-mail-reply-to-news
+@vindex gnus-confirm-mail-reply-to-news
+This can also be a function receiving the group name as the only
+parameter which should return non-@code{nil} if a confirmation is
+needed, or a regular expression matching group names, where
+confirmation is should be asked for.
 
-@table @code
-@item gnus-sent-message-ids-file
-@vindex gnus-sent-message-ids-file
-Gnus will keep a @code{Message-ID} history file of all the mails it has
-sent.  If it discovers that it has already sent a mail, it will ask the
-user whether to re-send the mail.  (This is primarily useful when
-dealing with @sc{soup} packets and the like where one is apt to send the
-same packet multiple times.)  This variable says what the name of this
-history file is.  It is @file{~/News/Sent-Message-IDs} by default.  Set
-this variable to @code{nil} if you don't want Gnus to keep a history
-file.
+If you find yourself never wanting to reply to mail, but occasionally
+press R anyway, this variable might be for you.
 
-@item gnus-sent-message-ids-length
-@vindex gnus-sent-message-ids-length
-This variable says how many @code{Message-ID}s to keep in the history
-file.  It is 1000 by default.
+@item gnus-confirm-treat-mail-like-news
+@vindex gnus-confirm-treat-mail-like-news
+If non-@code{nil}, Gnus also requests confirmation according to
+@code{gnus-confirm-mail-reply-to-news} when replying to mail.  This is
+useful for treating mailing lists like newsgroups.
 
 @end table
 
@@ -8055,13 +11353,18 @@ When you press those magical @kbd{C-c C-c} keys to ship off your latest
 
 Thank you for asking.  I hate you.
 
-@vindex gnus-post-method
+It can be quite complicated.
 
-It can be quite complicated.  Normally, Gnus will use the same native
-server.  However.  If your native server doesn't allow posting, just
-reading, you probably want to use some other server to post your
-(extremely intelligent and fabulously interesting) articles.  You can
-then set the @code{gnus-post-method} to some other method:
+@vindex gnus-post-method
+When posting news, Message usually invokes @code{message-send-news}
+(@pxref{News Variables, , News Variables, message, Message Manual}).
+Normally, Gnus will post using the same select method as you're
+reading from (which might be convenient if you're reading lots of
+groups from different private servers).  However.  If the server
+you're reading from doesn't allow posting, just reading, you probably
+want to use some other server to post your (extremely intelligent and
+fabulously interesting) articles.  You can then set the
+@code{gnus-post-method} to some other method:
 
 @lisp
 (setq gnus-post-method '(nnspool ""))
@@ -8070,15 +11373,43 @@ then set the @code{gnus-post-method} to some other method:
 Now, if you've done this, and then this server rejects your article, or
 this server is down, what do you do then?  To override this variable you
 can use a non-zero prefix to the @kbd{C-c C-c} command to force using
-the ``current'' server for posting.
+the ``current'' server, to get back the default behavior, for posting.
 
 If you give a zero prefix (i.e., @kbd{C-u 0 C-c C-c}) to that command,
-Gnus will prompt you for what method to use for posting.  
+gnus will prompt you for what method to use for posting.
 
 You can also set @code{gnus-post-method} to a list of select methods.
-If that's the case, Gnus will always prompt you for what method to use
-for posting. 
+If that's the case, gnus will always prompt you for what method to use
+for posting.
 
+Finally, if you want to always post using the native select method,
+you can set this variable to @code{native}.
+
+When sending mail, Message invokes @code{message-send-mail-function}.
+The default function, @code{message-send-mail-with-sendmail}, pipes
+your article to the @code{sendmail} binary for further queuing and
+sending.  When your local system is not configured for sending mail
+using @code{sendmail}, and you have access to a remote @acronym{SMTP}
+server, you can set @code{message-send-mail-function} to
+@code{smtpmail-send-it} and make sure to setup the @code{smtpmail}
+package correctly.  An example:
+
+@lisp
+(setq message-send-mail-function 'smtpmail-send-it
+      smtpmail-default-smtp-server "YOUR SMTP HOST")
+;; The following variable needs to be set because of the FLIM version of
+;; smtpmail.el.  Which smtpmail.el is used depends on the `load-path'.
+(setq smtp-default-smtp-server "YOUR SMTP HOST")
+@end lisp
+
+To the thing similar to this, there is
+@code{message-smtpmail-send-it}.  It is useful if your ISP requires
+the @acronym{POP}-before-@acronym{SMTP} authentication.  See the
+documentation for the function @code{mail-source-touch-pop}.
+
+Other possible choices for @code{message-send-mail-function} includes
+@code{message-send-mail-with-mh}, @code{message-send-mail-with-qmail},
+and @code{feedmail-send-it}.
 
 @node Mail and Post
 @section Mail and Post
@@ -8092,7 +11423,7 @@ posting:
 @cindex mailing lists
 
 If your news server offers groups that are really mailing lists
-gatewayed to the @sc{nntp} server, you can read those groups without
+gatewayed to the @acronym{NNTP} server, you can read those groups without
 problems, but you can't post/followup to them without some difficulty.
 One solution is to add a @code{to-address} to the group parameters
 (@pxref{Group Parameters}).  An easier thing to do is set the
@@ -8101,6 +11432,18 @@ really are mailing lists.  Then, at least, followups to the mailing
 lists will work most of the time.  Posting to these groups (@kbd{a}) is
 still a pain, though.
 
+@item gnus-user-agent
+@vindex gnus-user-agent
+@cindex User-Agent
+
+This variable controls which information should be exposed in the
+User-Agent header.  It can be one of the symbols @code{gnus} (show only
+Gnus version), @code{emacs-gnus} (show only Emacs and Gnus versions),
+@code{emacs-gnus-config} (same as @code{emacs-gnus} plus system
+configuration), @code{emacs-gnus-type} (same as @code{emacs-gnus} plus
+system type) or a custom string.  If you set it to a string, be sure to
+use a valid format, see RFC 2616.
+
 @end table
 
 You may want to do spell-checking on messages that you send out.  Or, if
@@ -8110,9 +11453,25 @@ spell-checking via the @code{ispell} package:
 @cindex ispell
 @findex ispell-message
 @lisp
-(add-hook 'message-send-hook 'ispell-message) 
+(add-hook 'message-send-hook 'ispell-message)
 @end lisp
 
+If you want to change the @code{ispell} dictionary based on what group
+you're in, you could say something like the following:
+
+@lisp
+(add-hook 'gnus-select-group-hook
+          (lambda ()
+            (cond
+             ((string-match
+               "^de\\." (gnus-group-real-name gnus-newsgroup-name))
+              (ispell-change-dictionary "deutsch"))
+             (t
+              (ispell-change-dictionary "english")))))
+@end lisp
+
+Modify to suit your needs.
+
 
 @node Archived Messages
 @section Archived Messages
@@ -8125,8 +11484,12 @@ store the messages.  If you want to disable this completely, the
 @code{gnus-message-archive-group} variable should be @code{nil}, which
 is the default.
 
+For archiving interesting messages in a group you read, see the
+@kbd{B c} (@code{gnus-summary-copy-article}) command (@pxref{Mail
+Group Commands}).
+
 @vindex gnus-message-archive-method
-@code{gnus-message-archive-method} says what virtual server Gnus is to
+@code{gnus-message-archive-method} says what virtual server gnus is to
 use to store sent messages.  The default is:
 
 @lisp
@@ -8138,13 +11501,13 @@ use to store sent messages.  The default is:
 @end lisp
 
 You can, however, use any mail select method (@code{nnml},
-@code{nnmbox}, etc.).  @code{nnfolder} is a quite likeable select method
+@code{nnmbox}, etc.).  @code{nnfolder} is a quite likable select method
 for doing this sort of thing, though.  If you don't like the default
 directory chosen, you could say something like:
 
 @lisp
 (setq gnus-message-archive-method
-      '(nnfolder "archive" 
+      '(nnfolder "archive"
                  (nnfolder-inhibit-expiry t)
                  (nnfolder-active-file "~/News/sent-mail/active")
                  (nnfolder-directory "~/News/sent-mail/")))
@@ -8154,20 +11517,33 @@ directory chosen, you could say something like:
 @cindex Gcc
 Gnus will insert @code{Gcc} headers in all outgoing messages that point
 to one or more group(s) on that server.  Which group to use is
-determined by the @code{gnus-message-archive-group} variable.  
+determined by the @code{gnus-message-archive-group} variable.
 
 This variable can be used to do the following:
 
-@itemize @bullet
+@table @asis
 @item a string
 Messages will be saved in that group.
+
+Note that you can include a select method in the group name, then the
+message will not be stored in the select method given by
+@code{gnus-message-archive-method}, but in the select method specified
+by the group name, instead.  Suppose @code{gnus-message-archive-method}
+has the default value shown above.  Then setting
+@code{gnus-message-archive-group} to @code{"foo"} means that outgoing
+messages are stored in @samp{nnfolder+archive:foo}, but if you use the
+value @code{"nnml:foo"}, then outgoing messages will be stored in
+@samp{nnml:foo}.
+
 @item a list of strings
 Messages will be saved in all those groups.
+
 @item an alist of regexps, functions and forms
 When a key ``matches'', the result is used.
+
 @item @code{nil}
 No message archiving will take place.  This is the default.
-@end itemize
+@end table
 
 Let's illustrate:
 
@@ -8183,7 +11559,7 @@ Saving to two groups, @samp{MisK} and @samp{safe}:
 
 Save to different groups based on what group you are in:
 @lisp
-(setq gnus-message-archive-group 
+(setq gnus-message-archive-group
       '(("^alt" "sent-to-alt")
         ("mail" "sent-to-mail")
         (".*" "sent-to-misc")))
@@ -8191,11 +11567,11 @@ Save to different groups based on what group you are in:
 
 More complex stuff:
 @lisp
-(setq gnus-message-archive-group 
+(setq gnus-message-archive-group
       '((if (message-news-p)
-            "misc-news" 
+            "misc-news"
           "misc-mail")))
-@end lisp       
+@end lisp
 
 How about storing all news messages in one file, but storing all mail
 messages in one file per month:
@@ -8203,19 +11579,18 @@ messages in one file per month:
 @lisp
 (setq gnus-message-archive-group
       '((if (message-news-p)
-            "misc-news" 
-          (concat "mail." (format-time-string 
-                           "%Y-%m" (current-time))))))
+            "misc-news"
+          (concat "mail." (format-time-string "%Y-%m")))))
 @end lisp
 
-(XEmacs 19.13 doesn't have @code{format-time-string}, so you'll have to
-use a different value for @code{gnus-message-archive-group} there.)
+@c (XEmacs 19.13 doesn't have @code{format-time-string}, so you'll have to
+@c use a different value for @code{gnus-message-archive-group} there.)
 
 Now, when you send a message off, it will be stored in the appropriate
 group.  (If you want to disable storing for just one particular message,
 you can just remove the @code{Gcc} header that has been inserted.)  The
 archive group will appear in the group buffer the next time you start
-Gnus, or the next time you press @kbd{F} in the group buffer.  You can
+gnus, or the next time you press @kbd{F} in the group buffer.  You can
 enter it and read the articles in it just like you'd read any other
 group.  If the group gets really big and annoying, you can simply rename
 if (using @kbd{G r} in the group buffer) to something
@@ -8228,8 +11603,8 @@ case you should set @code{gnus-message-archive-group} to @code{nil};
 this will disable archiving.
 
 @table @code
-@item gnus-outgoing-message-group 
-@vindex gnus-outgoing-message-group 
+@item gnus-outgoing-message-group
+@vindex gnus-outgoing-message-group
 All outgoing messages will be put in this group.  If you want to store
 all your outgoing mail and articles in the group @samp{nnml:archive},
 you set this variable to that value.  This variable can also be a list of
@@ -8242,86 +11617,174 @@ of names).
 
 This variable can be used instead of @code{gnus-message-archive-group},
 but the latter is the preferred method.
+
+@item gnus-gcc-mark-as-read
+@vindex gnus-gcc-mark-as-read
+If non-@code{nil}, automatically mark @code{Gcc} articles as read.
+
+@item gnus-gcc-externalize-attachments
+@vindex gnus-gcc-externalize-attachments
+If @code{nil}, attach files as normal parts in Gcc copies; if a regexp
+and matches the Gcc group name, attach files as external parts; if it is
+@code{all}, attach local files as external parts; if it is other
+non-@code{nil}, the behavior is the same as @code{all}, but it may be
+changed in the future.
+
 @end table
 
 
-@c @node Posting Styles
-@c @section Posting Styles
-@c @cindex posting styles
-@c @cindex styles
-@c 
-@c All them variables, they make my head swim.  
-@c 
-@c So what if you want a different @code{Organization} and signature based
-@c on what groups you post to?  And you post both from your home machine
-@c and your work machine, and you want different @code{From} lines, and so
-@c on? 
-@c 
-@c @vindex gnus-posting-styles
-@c One way to do stuff like that is to write clever hooks that change the
-@c variables you need to have changed.  That's a bit boring, so somebody
-@c came up with the bright idea of letting the user specify these things in
-@c a handy alist.  Here's an example of a @code{gnus-posting-styles}
-@c variable: 
-@c 
-@c @lisp
-@c ((".*" 
-@c   (signature . "Peace and happiness")
-@c   (organization . "What me?"))
-@c  ("^comp" 
-@c   (signature . "Death to everybody"))
-@c  ("comp.emacs.i-love-it" 
-@c   (organization . "Emacs is it")))
-@c @end lisp
-@c 
-@c As you might surmise from this example, this alist consists of several
-@c @dfn{styles}.  Each style will be applicable if the first element
-@c ``matches'', in some form or other.  The entire alist will be iterated
-@c over, from the beginning towards the end, and each match will be
-@c applied, which means that attributes in later styles that match override
-@c the same attributes in earlier matching styles.  So
-@c @samp{comp.programming.literate} will have the @samp{Death to everybody}
-@c signature and the @samp{What me?} @code{Organization} header.
-@c 
-@c The first element in each style is called the @code{match}.  If it's a
-@c string, then Gnus will try to regexp match it against the group name.
-@c If it's a function symbol, that function will be called with no
-@c arguments.  If it's a variable symbol, then the variable will be
-@c referenced.  If it's a list, then that list will be @code{eval}ed.  In
-@c any case, if this returns a non-@code{nil} value, then the style is said
-@c to @dfn{match}.
-@c 
-@c Each style may contain a arbitrary amount of @dfn{attributes}.  Each
-@c attribute consists of a @var{(name . value)} pair.  The attribute name
-@c can be one of @code{signature}, @code{organization} or @code{from}.  The
-@c attribute name can also be a string.  In that case, this will be used as
-@c a header name, and the value will be inserted in the headers of the
-@c article.
-@c 
-@c The attribute value can be a string (used verbatim), a function (the
-@c return value will be used), a variable (its value will be used) or a
-@c list (it will be @code{eval}ed and the return value will be used).
-@c 
-@c So here's a new example:
-@c 
-@c @lisp
-@c (setq gnus-posting-styles
-@c       '((".*" 
-@c           (signature . "~/.signature") 
-@c           (from . "user@@foo (user)")
-@c           ("X-Home-Page" . (getenv "WWW_HOME"))
-@c           (organization . "People's Front Against MWM"))
-@c         ("^rec.humor" 
-@c           (signature . my-funny-signature-randomizer))
-@c         ((equal (system-name) "gnarly")
-@c           (signature . my-quote-randomizer))
-@c         (posting-from-work-p
-@c           (signature . "~/.work-signature")
-@c           (from . "user@@bar.foo (user)")
-@c           (organization . "Important Work, Inc"))
-@c         ("^nn.+:" 
-@c           (signature . "~/.mail-signature"))))
-@c @end lisp
+@node Posting Styles
+@section Posting Styles
+@cindex posting styles
+@cindex styles
+
+All them variables, they make my head swim.
+
+So what if you want a different @code{Organization} and signature based
+on what groups you post to?  And you post both from your home machine
+and your work machine, and you want different @code{From} lines, and so
+on?
+
+@vindex gnus-posting-styles
+One way to do stuff like that is to write clever hooks that change the
+variables you need to have changed.  That's a bit boring, so somebody
+came up with the bright idea of letting the user specify these things in
+a handy alist.  Here's an example of a @code{gnus-posting-styles}
+variable:
+
+@lisp
+((".*"
+  (signature "Peace and happiness")
+  (organization "What me?"))
+ ("^comp"
+  (signature "Death to everybody"))
+ ("comp.emacs.i-love-it"
+  (organization "Emacs is it")))
+@end lisp
+
+As you might surmise from this example, this alist consists of several
+@dfn{styles}.  Each style will be applicable if the first element
+``matches'', in some form or other.  The entire alist will be iterated
+over, from the beginning towards the end, and each match will be
+applied, which means that attributes in later styles that match override
+the same attributes in earlier matching styles.  So
+@samp{comp.programming.literate} will have the @samp{Death to everybody}
+signature and the @samp{What me?} @code{Organization} header.
+
+The first element in each style is called the @code{match}.  If it's a
+string, then Gnus will try to regexp match it against the group name.
+If it is the form @code{(header @var{match} @var{regexp})}, then Gnus
+will look in the original article for a header whose name is
+@var{match} and compare that @var{regexp}.  @var{match} and
+@var{regexp} are strings.  (The original article is the one you are
+replying or following up to.  If you are not composing a reply or a
+followup, then there is nothing to match against.)  If the
+@code{match} is a function symbol, that function will be called with
+no arguments.  If it's a variable symbol, then the variable will be
+referenced.  If it's a list, then that list will be @code{eval}ed.  In
+any case, if this returns a non-@code{nil} value, then the style is
+said to @dfn{match}.
+
+Each style may contain an arbitrary amount of @dfn{attributes}.  Each
+attribute consists of a @code{(@var{name} @var{value})} pair.  The
+attribute name can be one of:
+
+@itemize @bullet
+@item @code{signature}
+@item @code{signature-file}
+@item @code{x-face-file}
+@item @code{address}, overriding @code{user-mail-address}
+@item @code{name}, overriding @code{(user-full-name)}
+@item @code{body}
+@end itemize
+
+The attribute name can also be a string or a symbol.  In that case,
+this will be used as a header name, and the value will be inserted in
+the headers of the article; if the value is @code{nil}, the header
+name will be removed.  If the attribute name is @code{eval}, the form
+is evaluated, and the result is thrown away.
+
+The attribute value can be a string (used verbatim), a function with
+zero arguments (the return value will be used), a variable (its value
+will be used) or a list (it will be @code{eval}ed and the return value
+will be used).  The functions and sexps are called/@code{eval}ed in the
+message buffer that is being set up.  The headers of the current article
+are available through the @code{message-reply-headers} variable, which
+is a vector of the following headers: number subject from date id
+references chars lines xref extra.
+
+@vindex message-reply-headers
+
+If you wish to check whether the message you are about to compose is
+meant to be a news article or a mail message, you can check the values
+of the @code{message-news-p} and @code{message-mail-p} functions.
+
+@findex message-mail-p
+@findex message-news-p
+
+So here's a new example:
+
+@lisp
+(setq gnus-posting-styles
+      '((".*"
+         (signature-file "~/.signature")
+         (name "User Name")
+         ("X-Home-Page" (getenv "WWW_HOME"))
+         (organization "People's Front Against MWM"))
+        ("^rec.humor"
+         (signature my-funny-signature-randomizer))
+        ((equal (system-name) "gnarly")  ;; @r{A form}
+         (signature my-quote-randomizer))
+        (message-news-p        ;; @r{A function symbol}
+         (signature my-news-signature))
+        (window-system         ;; @r{A value symbol}
+         ("X-Window-System" (format "%s" window-system)))
+        ;; @r{If I'm replying to Larsi, set the Organization header.}
+        ((header "from" "larsi.*org")
+         (Organization "Somewhere, Inc."))
+        ((posting-from-work-p) ;; @r{A user defined function}
+         (signature-file "~/.work-signature")
+         (address "user@@bar.foo")
+         (body "You are fired.\n\nSincerely, your boss.")
+         (organization "Important Work, Inc"))
+        ("nnml:.*"
+         (From (save-excursion
+                 (set-buffer gnus-article-buffer)
+                 (message-fetch-field "to"))))
+        ("^nn.+:"
+         (signature-file "~/.mail-signature"))))
+@end lisp
+
+The @samp{nnml:.*} rule means that you use the @code{To} address as the
+@code{From} address in all your outgoing replies, which might be handy
+if you fill many roles.
+
+Setting the @code{gnus-named-posting-styles} variable will make
+posting-styles allow to have distinctive names.  You can specify an
+arbitrary posting-style when article posting with @kbd{S P} in the
+summary buffer.  @code{gnus-named-posting-styles} is an alist which maps
+the names to styles.  Once a posting-style is added to the alist, we can
+import it from @code{gnus-posting-styles}.  If an attribute whose name
+is @code{import} is found, Gnus will look for the attribute value in
+@code{gnus-named-posting-styles} and expand it in place.
+
+Here's an example:
+
+@lisp
+(setq gnus-named-posting-styles
+      '(("Default"
+         (signature-file "~/.signature")
+         (name "User Name")
+         ("X-Home-Page" (getenv "WWW_HOME"))
+         (organization "People's Front Against MWM"))
+        ("Emacs"
+         (import "Default")
+         (organization "The Church of Emacs"))))
+@end lisp
+
+The posting-style named "Emacs" will inherit all the attributes from
+"Default" except @code{organization}.
+
 
 @node Drafts
 @section Drafts
@@ -8334,11 +11797,11 @@ the message you are writing so that you can continue editing it some
 other day, and send it when you feel its finished.
 
 Well, don't worry about it.  Whenever you start composing a message of
-some sort using the Gnus mail and post commands, the buffer you get will
+some sort using the gnus mail and post commands, the buffer you get will
 automatically associate to an article in a special @dfn{draft} group.
 If you save the buffer the normal way (@kbd{C-x C-s}, for instance), the
 article will be saved there.  (Auto-save files also go to the draft
-group.) 
+group.)
 
 @cindex nndraft
 @vindex nndraft-directory
@@ -8351,7 +11814,13 @@ read---all articles in the group are permanently unread.
 
 If the group doesn't exist, it will be created and you'll be subscribed
 to it.  The only way to make it disappear from the Group buffer is to
-unsubscribe it. 
+unsubscribe it.  The special properties of the draft group comes from
+a group property (@pxref{Group Parameters}), and if lost the group
+behaves like any other group.  This means the commands below will not
+be available.  To restore the special properties of the group, the
+simplest way is to kill the group, using @kbd{C-k}, and restart
+Gnus.  The group is automatically created again with the
+correct parameters.  The content of the group is not lost.
 
 @c @findex gnus-dissociate-buffer-from-draft
 @c @kindex C-c M-d (Mail)
@@ -8367,10 +11836,10 @@ unsubscribe it.
 @c (@code{gnus-dissociate-buffer-from-draft}) command does that for you.
 @c If you change your mind and want to turn the auto-saving back on again,
 @c @kbd{C-c C-d} (@code{gnus-associate-buffer-with-draft} does that.
-@c 
+@c
 @c @vindex gnus-use-draft
 @c To leave association with the draft group off by default, set
-@c @code{gnus-use-draft} to @code{nil}.  It is @code{t} by default. 
+@c @code{gnus-use-draft} to @code{nil}.  It is @code{t} by default.
 
 @findex gnus-draft-edit-message
 @kindex D e (Draft)
@@ -8382,7 +11851,9 @@ Rejected articles will also be put in this draft group (@pxref{Rejected
 Articles}).
 
 @findex gnus-draft-send-all-messages
+@kindex D s (Draft)
 @findex gnus-draft-send-message
+@kindex D S (Draft)
 If you have lots of rejected messages you want to post (or mail) without
 doing further editing, you can use the @kbd{D s} command
 (@code{gnus-draft-send-message}).  This command understands the
@@ -8390,6 +11861,8 @@ process/prefix convention (@pxref{Process/Prefix}).  The @kbd{D S}
 command (@code{gnus-draft-send-all-messages}) will ship off all messages
 in the buffer.
 
+@findex gnus-draft-toggle-sending
+@kindex D t (Draft)
 If you have some messages that you wish not to send, you can use the
 @kbd{D t} (@code{gnus-draft-toggle-sending}) command to mark the message
 as unsendable.  This is a toggling command.
@@ -8404,16 +11877,88 @@ doesn't like your face.  Perhaps it just feels miserable.  Perhaps
 @emph{there be demons}.  Perhaps you have included too much cited text.
 Perhaps the disk is full.  Perhaps the server is down.
 
-These situations are, of course, totally beyond the control of Gnus.
+These situations are, of course, totally beyond the control of gnus.
 (Gnus, of course, loves the way you look, always feels great, has angels
 fluttering around inside of it, doesn't care about how much cited text
-you include, never runs full and never goes down.)  So Gnus saves these
+you include, never runs full and never goes down.)  So gnus saves these
 articles until some later time when the server feels better.
 
 The rejected articles will automatically be put in a special draft group
 (@pxref{Drafts}).  When the server comes back up again, you'd then
 typically enter that group and send all the articles off.
 
+@node Signing and encrypting
+@section Signing and encrypting
+@cindex using gpg
+@cindex using s/mime
+@cindex using smime
+
+Gnus can digitally sign and encrypt your messages, using vanilla
+@acronym{PGP} format or @acronym{PGP/MIME} or @acronym{S/MIME}.  For
+decoding such messages, see the @code{mm-verify-option} and
+@code{mm-decrypt-option} options (@pxref{Security}).
+
+@vindex gnus-message-replysign
+@vindex gnus-message-replyencrypt
+@vindex gnus-message-replysignencrypted
+Often, you would like to sign replies to people who send you signed
+messages.  Even more often, you might want to encrypt messages which
+are in reply to encrypted messages.  Gnus offers
+@code{gnus-message-replysign} to enable the former, and
+@code{gnus-message-replyencrypt} for the latter.  In addition, setting
+@code{gnus-message-replysignencrypted} (on by default) will sign
+automatically encrypted messages.
+
+Instructing @acronym{MML} to perform security operations on a
+@acronym{MIME} part is done using the @kbd{C-c C-m s} key map for
+signing and the @kbd{C-c C-m c} key map for encryption, as follows.
+
+@table @kbd
+
+@item C-c C-m s s
+@kindex C-c C-m s s (Message)
+@findex mml-secure-message-sign-smime
+
+Digitally sign current message using @acronym{S/MIME}.
+
+@item C-c C-m s o
+@kindex C-c C-m s o (Message)
+@findex mml-secure-message-sign-pgp
+
+Digitally sign current message using @acronym{PGP}.
+
+@item C-c C-m s p
+@kindex C-c C-m s p (Message)
+@findex mml-secure-message-sign-pgp
+
+Digitally sign current message using @acronym{PGP/MIME}.
+
+@item C-c C-m c s
+@kindex C-c C-m c s (Message)
+@findex mml-secure-message-encrypt-smime
+
+Digitally encrypt current message using @acronym{S/MIME}.
+
+@item C-c C-m c o
+@kindex C-c C-m c o (Message)
+@findex mml-secure-message-encrypt-pgp
+
+Digitally encrypt current message using @acronym{PGP}.
+
+@item C-c C-m c p
+@kindex C-c C-m c p (Message)
+@findex mml-secure-message-encrypt-pgpmime
+
+Digitally encrypt current message using @acronym{PGP/MIME}.
+
+@item C-c C-m C-n
+@kindex C-c C-m C-n (Message)
+@findex mml-unsecure-message
+Remove security related @acronym{MML} tags from message.
+
+@end table
+
+@xref{Security, ,Security, message, Message Manual}, for more information.
 
 @node Select Methods
 @chapter Select Methods
@@ -8422,60 +11967,62 @@ typically enter that group and send all the articles off.
 
 A @dfn{foreign group} is a group not read by the usual (or
 default) means.  It could be, for instance, a group from a different
-@sc{nntp} server, it could be a virtual group, or it could be your own
+@acronym{NNTP} server, it could be a virtual group, or it could be your own
 personal mail group.
 
 A foreign group (or any group, really) is specified by a @dfn{name} and
 a @dfn{select method}.  To take the latter first, a select method is a
-list where the first element says what backend to use (e.g. @code{nntp},
+list where the first element says what back end to use (e.g. @code{nntp},
 @code{nnspool}, @code{nnml}) and the second element is the @dfn{server
 name}.  There may be additional elements in the select method, where the
-value may have special meaning for the backend in question.
+value may have special meaning for the back end in question.
 
 One could say that a select method defines a @dfn{virtual server}---so
-we do just that (@pxref{The Server Buffer}).
+we do just that (@pxref{Server Buffer}).
 
-The @dfn{name} of the group is the name the backend will recognize the
+The @dfn{name} of the group is the name the back end will recognize the
 group as.
 
-For instance, the group @samp{soc.motss} on the @sc{nntp} server
+For instance, the group @samp{soc.motss} on the @acronym{NNTP} server
 @samp{some.where.edu} will have the name @samp{soc.motss} and select
 method @code{(nntp "some.where.edu")}.  Gnus will call this group
 @samp{nntp+some.where.edu:soc.motss}, even though the @code{nntp}
-backend just knows this group as @samp{soc.motss}.
+back end just knows this group as @samp{soc.motss}.
 
 The different methods all have their peculiarities, of course.
 
 @menu
-* The Server Buffer::     Making and editing virtual servers.
-* Getting News::          Reading USENET news with Gnus.
-* Getting Mail::          Reading your personal mail with Gnus.
-* Other Sources::         Reading directories, files, SOUP packets.
-* Combined Groups::       Combining groups into one group.
-* Gnus Unplugged::        Reading news and mail offline.
+* Server Buffer::               Making and editing virtual servers.
+* Getting News::                Reading USENET news with Gnus.
+* Getting Mail::                Reading your personal mail with Gnus.
+* Browsing the Web::            Getting messages from a plethora of Web sources.
+* IMAP::                        Using Gnus as a @acronym{IMAP} client.
+* Other Sources::               Reading directories, files, SOUP packets.
+* Combined Groups::             Combining groups into one group.
+* Gnus Unplugged::              Reading news and mail offline.
 @end menu
 
 
-@node The Server Buffer
-@section The Server Buffer
+@node Server Buffer
+@section Server Buffer
 
 Traditionally, a @dfn{server} is a machine or a piece of software that
 one connects to, and then requests information from.  Gnus does not
 connect directly to any real servers, but does all transactions through
-one backend or other.  But that's just putting one layer more between
+one back end or other.  But that's just putting one layer more between
 the actual media and Gnus, so we might just as well say that each
-backend represents a virtual server.
+back end represents a virtual server.
 
-For instance, the @code{nntp} backend may be used to connect to several
-different actual @sc{nntp} servers, or, perhaps, to many different ports
-on the same actual @sc{nntp} server.  You tell Gnus which backend to
+For instance, the @code{nntp} back end may be used to connect to several
+different actual @acronym{NNTP} servers, or, perhaps, to many different ports
+on the same actual @acronym{NNTP} server.  You tell Gnus which back end to
 use, and what parameters to set by specifying a @dfn{select method}.
 
 These select method specifications can sometimes become quite
 complicated---say, for instance, that you want to read from the
-@sc{nntp} server @samp{news.funet.fi} on port number 13, which
-hangs if queried for @sc{nov} headers and has a buggy select.  Ahem.
-Anyways, if you had to specify that for each group that used this
+@acronym{NNTP} server @samp{news.funet.fi} on port number 13, which
+hangs if queried for @acronym{NOV} headers and has a buggy select.  Ahem.
+Anyway, if you had to specify that for each group that used this
 server, that would be too much work, so Gnus offers a way of naming
 select methods, which is what you do in the server buffer.
 
@@ -8483,13 +12030,13 @@ To enter the server buffer, use the @kbd{^}
 (@code{gnus-group-enter-server-mode}) command in the group buffer.
 
 @menu
-* Server Buffer Format::      You can customize the look of this buffer.
-* Server Commands::           Commands to manipulate servers.
-* Example Methods::           Examples server specifications.
-* Creating a Virtual Server:: An example session.
-* Server Variables::          Which variables to set.
-* Servers and Methods::       You can use server names as select methods.
-* Unavailable Servers::       Some servers you try to contact may be down.
+* Server Buffer Format::        You can customize the look of this buffer.
+* Server Commands::             Commands to manipulate servers.
+* Example Methods::             Examples server specifications.
+* Creating a Virtual Server::   An example session.
+* Server Variables::            Which variables to set.
+* Servers and Methods::         You can use server names as select methods.
+* Unavailable Servers::         Some servers you try to contact may be down.
 @end menu
 
 @vindex gnus-server-mode-hook
@@ -8507,8 +12054,8 @@ variable, with some simple extensions:
 
 @table @samp
 
-@item h 
-How the news is fetched---the backend name.
+@item h
+How the news is fetched---the back end name.
 
 @item n
 The name of this server.
@@ -8522,8 +12069,8 @@ The opened/closed/denied status of the server.
 
 @vindex gnus-server-mode-line-format
 The mode line can also be customized by using the
-@code{gnus-server-mode-line-format} variable.  The following specs are
-understood: 
+@code{gnus-server-mode-line-format} variable (@pxref{Mode Line
+Formatting}).  The following specs are understood:
 
 @table @samp
 @item S
@@ -8587,14 +12134,14 @@ List all servers (@code{gnus-server-list-servers}).
 @findex gnus-server-scan-server
 Request that the server scan its sources for new articles
 (@code{gnus-server-scan-server}).  This is mainly sensible with mail
-servers. 
+servers.
 
 @item g
 @kindex g (Server)
 @findex gnus-server-regenerate-server
 Request that the server regenerate all its data structures
 (@code{gnus-server-regenerate-server}).  This can be useful if you have
-a mail backend that has gotten out of synch.
+a mail back end that has gotten out of sync.
 
 @end table
 
@@ -8602,7 +12149,7 @@ a mail backend that has gotten out of synch.
 @node Example Methods
 @subsection Example Methods
 
-Most select methods are pretty simple and self-explanatory: 
+Most select methods are pretty simple and self-explanatory:
 
 @lisp
 (nntp "news.funet.fi")
@@ -8615,11 +12162,11 @@ Reading directly from the spool is even simpler:
 @end lisp
 
 As you can see, the first element in a select method is the name of the
-backend, and the second is the @dfn{address}, or @dfn{name}, if you
-will. 
+back end, and the second is the @dfn{address}, or @dfn{name}, if you
+will.
 
 After these two elements, there may be an arbitrary number of
-@var{(variable form)} pairs.
+@code{(@var{variable} @var{form})} pairs.
 
 To go back to the first example---imagine that you want to read from
 port 15 on that machine.  This is what the select method should
@@ -8629,10 +12176,10 @@ look like then:
 (nntp "news.funet.fi" (nntp-port-number 15))
 @end lisp
 
-You should read the documentation to each backend to find out what
+You should read the documentation to each back end to find out what
 variables are relevant, but here's an @code{nnmh} example:
 
-@code{nnmh} is a mail backend that reads a spool-like structure.  Say
+@code{nnmh} is a mail back end that reads a spool-like structure.  Say
 you have two structures that you wish to access: One is your private
 mail spool, and the other is a public one.  Here's the possible spec for
 your private mail:
@@ -8647,26 +12194,54 @@ that.)
 Here's the method for a public spool:
 
 @lisp
-(nnmh "public" 
-      (nnmh-directory "/usr/information/spool/") 
+(nnmh "public"
+      (nnmh-directory "/usr/information/spool/")
       (nnmh-get-new-mail nil))
 @end lisp
 
-If you are behind a firewall and only have access to the @sc{nntp}
+@cindex proxy
+@cindex firewall
+
+If you are behind a firewall and only have access to the @acronym{NNTP}
 server from the firewall machine, you can instruct Gnus to @code{rlogin}
-on the firewall machine and telnet from there to the @sc{nntp} server.
+on the firewall machine and telnet from there to the @acronym{NNTP} server.
 Doing this can be rather fiddly, but your virtual server definition
 should probably look something like this:
 
 @lisp
 (nntp "firewall"
-      (nntp-address "the.firewall.machine")
-      (nntp-open-connection-function nntp-open-rlogin)
-      (nntp-end-of-line "\n")
-      (nntp-rlogin-parameters
-       ("telnet" "the.real.nntp.host" "nntp")))
+      (nntp-open-connection-function nntp-open-via-rlogin-and-telnet)
+      (nntp-via-address "the.firewall.machine")
+      (nntp-address "the.real.nntp.host")
+      (nntp-end-of-line "\n"))
+@end lisp
+
+If you want to use the wonderful @code{ssh} program to provide a
+compressed connection over the modem line, you could add the following
+configuration to the example above:
+
+@lisp
+      (nntp-via-rlogin-command "ssh")
+@end lisp
+
+See also @code{nntp-via-rlogin-command-switches}.
+
+If you're behind a firewall, but have direct access to the outside world
+through a wrapper command like "runsocks", you could open a socksified
+telnet connection to the news server as follows:
+
+@lisp
+(nntp "outside"
+      (nntp-pre-command "runsocks")
+      (nntp-open-connection-function nntp-open-via-telnet)
+      (nntp-address "the.news.server")
+      (nntp-end-of-line "\n"))
 @end lisp
 
+This means that you have to have set up @code{ssh-agent} correctly to
+provide automatic authorization, of course.  And to get a compressed
+connection, you have to have the @samp{Compression} option in the
+@code{ssh} @file{config} file.
 
 
 @node Creating a Virtual Server
@@ -8676,27 +12251,26 @@ If you're saving lots of articles in the cache by using persistent
 articles, you may want to create a virtual server to read the cache.
 
 First you need to add a new server.  The @kbd{a} command does that.  It
-would probably be best to use @code{nnspool} to read the cache.  You
-could also use @code{nnml} or @code{nnmh}, though.
+would probably be best to use @code{nnml} to read the cache.  You
+could also use @code{nnspool} or @code{nnmh}, though.
 
-Type @kbd{a nnspool RET cache RET}.
+Type @kbd{a nnml RET cache RET}.
 
-You should now have a brand new @code{nnspool} virtual server called
+You should now have a brand new @code{nnml} virtual server called
 @samp{cache}.  You now need to edit it to have the right definitions.
 Type @kbd{e} to edit the server.  You'll be entered into a buffer that
 will contain the following:
 
 @lisp
-(nnspool "cache")
+(nnml "cache")
 @end lisp
 
 Change that to:
 
 @lisp
-(nnspool "cache"
-         (nnspool-spool-directory "~/News/cache/")
-         (nnspool-nov-directory "~/News/cache/")
-         (nnspool-active-file "~/News/cache/active"))
+(nnml "cache"
+         (nnml-directory "~/News/cache/")
+         (nnml-active-file "~/News/cache/active"))
 @end lisp
 
 Type @kbd{C-c C-c} to return to the server buffer.  If you now press
@@ -8706,12 +12280,14 @@ buffer, and you should be able to enter any of the groups displayed.
 
 @node Server Variables
 @subsection Server Variables
+@cindex server variables
+@cindex server parameters
 
-One sticky point when defining variables (both on backends and in Emacs
+One sticky point when defining variables (both on back ends and in Emacs
 in general) is that some variables are typically initialized from other
 variables when the definition of the variables is being loaded.  If you
-change the "base" variable after the variables have been loaded, you
-won't change the "derived" variables.
+change the ``base'' variable after the variables have been loaded, you
+won't change the ``derived'' variables.
 
 This typically affects directory and file variables.  For instance,
 @code{nnml-directory} is @file{~/Mail/} by default, and all @code{nnml}
@@ -8720,16 +12296,17 @@ directory variables are initialized from that variable, so
 new virtual @code{nnml} server, it will @emph{not} suffice to set just
 @code{nnml-directory}---you have to explicitly set all the file
 variables to be what you want them to be.  For a complete list of
-variables for each backend, see each backend's section later in this
+variables for each back end, see each back end's section later in this
 manual, but here's an example @code{nnml} definition:
 
 @lisp
-(nnml "public" 
+(nnml "public"
       (nnml-directory "~/my-mail/")
       (nnml-active-file "~/my-mail/active")
       (nnml-newsgroups-file "~/my-mail/newsgroups"))
 @end lisp
 
+Server variables are often called @dfn{server parameters}.
 
 @node Servers and Methods
 @subsection Servers and Methods
@@ -8762,7 +12339,7 @@ it will regard that server as ``down''.
 So, what happens if the machine was only feeling unwell temporarily?
 How do you test to see whether the machine has come up again?
 
-You jump to the server buffer (@pxref{The Server Buffer}) and poke it
+You jump to the server buffer (@pxref{Server Buffer}) and poke it
 with the following commands:
 
 @table @kbd
@@ -8783,25 +12360,30 @@ Close the connection (if any) to the server
 @kindex D (Server)
 @findex gnus-server-deny-server
 Mark the current server as unreachable
-(@code{gnus-server-deny-server}). 
+(@code{gnus-server-deny-server}).
 
 @item M-o
 @kindex M-o (Server)
 @findex gnus-server-open-all-servers
 Open the connections to all servers in the buffer
-(@code{gnus-server-open-all-servers}). 
+(@code{gnus-server-open-all-servers}).
 
 @item M-c
 @kindex M-c (Server)
 @findex gnus-server-close-all-servers
 Close the connections to all servers in the buffer
-(@code{gnus-server-close-all-servers}). 
+(@code{gnus-server-close-all-servers}).
 
 @item R
 @kindex R (Server)
 @findex gnus-server-remove-denials
 Remove all marks to whether Gnus was denied connection from any servers
-(@code{gnus-server-remove-denials}). 
+(@code{gnus-server-remove-denials}).
+
+@item L
+@kindex L (Server)
+@findex gnus-server-offline-server
+Set server status to offline (@code{gnus-server-offline-server}).
 
 @end table
 
@@ -8809,27 +12391,27 @@ Remove all marks to whether Gnus was denied connection from any servers
 @node Getting News
 @section Getting News
 @cindex reading news
-@cindex news backends
+@cindex news back ends
 
 A newsreader is normally used for reading news.  Gnus currently provides
-only two methods of getting news---it can read from an @sc{nntp} server,
+only two methods of getting news---it can read from an @acronym{NNTP} server,
 or it can read from a local spool.
 
 @menu
-* NNTP::               Reading news from an @sc{nntp} server.
-* News Spool::         Reading news from the local spool.
+* NNTP::                        Reading news from an @acronym{NNTP} server.
+* News Spool::                  Reading news from the local spool.
 @end menu
 
 
 @node NNTP
-@subsection @sc{nntp}
+@subsection NNTP
 @cindex nntp
 
-Subscribing to a foreign group from an @sc{nntp} server is rather easy.
-You just specify @code{nntp} as method and the address of the @sc{nntp}
+Subscribing to a foreign group from an @acronym{NNTP} server is rather easy.
+You just specify @code{nntp} as method and the address of the @acronym{NNTP}
 server as the, uhm, address.
 
-If the @sc{nntp} server is located at a non-standard port, setting the
+If the @acronym{NNTP} server is located at a non-standard port, setting the
 third element of the select method to this port number should allow you
 to connect to the right port.  You'll have to edit the group info for
 that (@pxref{Foreign Groups}).
@@ -8839,7 +12421,7 @@ fact, you can subscribe to the same group from as many different servers
 you feel like.  There will be no name collisions.
 
 The following variables can be used to create a virtual @code{nntp}
-server: 
+server:
 
 @table @code
 
@@ -8852,31 +12434,38 @@ server:
 @findex nntp-send-authinfo
 @findex nntp-send-mode-reader
 is run after a connection has been made.  It can be used to send
-commands to the @sc{nntp} server after it has been contacted.  By
+commands to the @acronym{NNTP} server after it has been contacted.  By
 default it sends the command @code{MODE READER} to the server with the
 @code{nntp-send-mode-reader} function.  This function should always be
 present in this hook.
 
-@item nntp-authinfo-function 
-@vindex nntp-authinfo-function 
+@item nntp-authinfo-function
+@vindex nntp-authinfo-function
 @findex nntp-send-authinfo
-@vindex nntp-authinforc-file
-This function will be used to send @samp{AUTHINFO} to the @sc{nntp}
+@vindex nntp-authinfo-file
+This function will be used to send @samp{AUTHINFO} to the @acronym{NNTP}
 server.  The default function is @code{nntp-send-authinfo}, which looks
-through your @file{~/.authinforc} (or whatever you've set the
-@code{nntp-authinforc-file} variable to) for applicable entries.  If
-none are found, it will prompt you for a login name and a password.  The
-format of the @file{~/.authinforc} file is the same as the @code{ftp}
-@file{~/.netrc} file, which is defined in the @code{ftp} manual page,
-but here are the salient facts:
+through your @file{~/.authinfo} (or whatever you've set the
+@code{nntp-authinfo-file} variable to) for applicable entries.  If none
+are found, it will prompt you for a login name and a password.  The
+format of the @file{~/.authinfo} file is (almost) the same as the
+@code{ftp} @file{~/.netrc} file, which is defined in the @code{ftp}
+manual page, but here are the salient facts:
 
 @enumerate
 @item
 The file contains one or more line, each of which define one server.
 
 @item
-Each line may contain an arbitrary number of token/value pairs.  The
-valid tokens include @samp{machine}, @samp{login}, and @samp{password}.
+Each line may contain an arbitrary number of token/value pairs.
+
+The valid tokens include @samp{machine}, @samp{login}, @samp{password},
+@samp{default}.  In addition Gnus introduces two new tokens, not present
+in the original @file{.netrc}/@code{ftp} syntax, namely @samp{port} and
+@samp{force}.  (This is the only way the @file{.authinfo} file format
+deviates from the @file{.netrc} file format.)  @samp{port} is used to
+indicate what port on the server the credentials apply to and
+@samp{force} is explained below.
 
 @end enumerate
 
@@ -8884,7 +12473,7 @@ Here's an example file:
 
 @example
 machine news.uio.no login larsi password geheimnis
-machine nntp.ifi.uio.no login larsi
+machine nntp.ifi.uio.no login larsi force yes
 @end example
 
 The token/value pairs may appear in any order; @samp{machine} doesn't
@@ -8892,12 +12481,26 @@ have to be first, for instance.
 
 In this example, both login name and password have been supplied for the
 former server, while the latter has only the login name listed, and the
-user will be prompted for the password.
+user will be prompted for the password.  The latter also has the
+@samp{force} tag, which means that the authinfo will be sent to the
+@var{nntp} server upon connection; the default (i.e., when there is not
+@samp{force} tag) is to not send authinfo to the @var{nntp} server
+until the @var{nntp} server asks for it.
+
+You can also add @samp{default} lines that will apply to all servers
+that don't have matching @samp{machine} lines.
+
+@example
+default force yes
+@end example
+
+This will force sending @samp{AUTHINFO} commands to all servers not
+previously mentioned.
 
-Remember to not leave the @file{~/.authinforc} file world-readable.
+Remember to not leave the @file{~/.authinfo} file world-readable.
 
-@item nntp-server-action-alist 
-@vindex nntp-server-action-alist 
+@item nntp-server-action-alist
+@vindex nntp-server-action-alist
 This is a list of regexps to match on server types and actions to be
 taken when matches are made.  For instance, if you want Gnus to beep
 every time you connect to innd, you could say something like:
@@ -8912,18 +12515,19 @@ You probably don't want to do that, though.
 The default value is
 
 @lisp
-'(("nntpd 1\\.5\\.11t" 
-   (remove-hook 'nntp-server-opened-hook 'nntp-send-mode-reader)))
+'(("nntpd 1\\.5\\.11t"
+   (remove-hook 'nntp-server-opened-hook
+                'nntp-send-mode-reader)))
 @end lisp
 
 This ensures that Gnus doesn't send the @code{MODE READER} command to
-nntpd 1.5.11t, since that command chokes that server, I've been told. 
+nntpd 1.5.11t, since that command chokes that server, I've been told.
 
 @item nntp-maximum-request
 @vindex nntp-maximum-request
-If the @sc{nntp} server doesn't support @sc{nov} headers, this backend
+If the @acronym{NNTP} server doesn't support @acronym{NOV} headers, this back end
 will collect headers by sending a series of @code{head} commands.  To
-speed things up, the backend sends lots of these commands without
+speed things up, the back end sends lots of these commands without
 waiting for reply, and then reads all the replies.  This is controlled
 by the @code{nntp-maximum-request} variable, and is 400 by default.  If
 your network is buggy, you should set this to 1.
@@ -8931,11 +12535,11 @@ your network is buggy, you should set this to 1.
 @item nntp-connection-timeout
 @vindex nntp-connection-timeout
 If you have lots of foreign @code{nntp} groups that you connect to
-regularly, you're sure to have problems with @sc{nntp} servers not
+regularly, you're sure to have problems with @acronym{NNTP} servers not
 responding properly, or being too loaded to reply within reasonable
 time.  This is can lead to awkward problems, which can be helped
 somewhat by setting @code{nntp-connection-timeout}.  This is an integer
-that says how many seconds the @code{nntp} backend should wait for a
+that says how many seconds the @code{nntp} back end should wait for a
 connection before giving up.  If it is @code{nil}, which is the default,
 no timeouts are done.
 
@@ -8945,14 +12549,14 @@ no timeouts are done.
 @c @cindex dynamic IP addresses
 @c If you're running Gnus on a machine that has a dynamically assigned
 @c address, Gnus may become confused.  If the address of your machine
-@c changes after connecting to the @sc{nntp} server, Gnus will simply sit
+@c changes after connecting to the @acronym{NNTP} server, Gnus will simply sit
 @c waiting forever for replies from the server.  To help with this
 @c unfortunate problem, you can set this command to a number.  Gnus will
 @c then, if it sits waiting for a reply from the server longer than that
 @c number of seconds, shut down the connection, start a new one, and resend
 @c the command.  This should hopefully be transparent to the user.  A
 @c likely number is 30 seconds.
-@c 
+@c
 @c @item nntp-retry-on-break
 @c @vindex nntp-retry-on-break
 @c If this variable is non-@code{nil}, you can also @kbd{C-g} if Gnus
@@ -8961,138 +12565,345 @@ no timeouts are done.
 
 @item nntp-server-hook
 @vindex nntp-server-hook
-This hook is run as the last step when connecting to an @sc{nntp}
+This hook is run as the last step when connecting to an @acronym{NNTP}
 server.
 
-@findex nntp-open-rlogin
-@findex nntp-open-telnet
-@findex nntp-open-network-stream
+@item nntp-buggy-select
+@vindex nntp-buggy-select
+Set this to non-@code{nil} if your select routine is buggy.
+
+@item nntp-nov-is-evil
+@vindex nntp-nov-is-evil
+If the @acronym{NNTP} server does not support @acronym{NOV}, you could set this
+variable to @code{t}, but @code{nntp} usually checks automatically whether @acronym{NOV}
+can be used.
+
+@item nntp-xover-commands
+@vindex nntp-xover-commands
+@cindex @acronym{NOV}
+@cindex XOVER
+List of strings used as commands to fetch @acronym{NOV} lines from a
+server.  The default value of this variable is @code{("XOVER"
+"XOVERVIEW")}.
+
+@item nntp-nov-gap
+@vindex nntp-nov-gap
+@code{nntp} normally sends just one big request for @acronym{NOV} lines to
+the server.  The server responds with one huge list of lines.  However,
+if you have read articles 2-5000 in the group, and only want to read
+article 1 and 5001, that means that @code{nntp} will fetch 4999 @acronym{NOV}
+lines that you will not need.  This variable says how
+big a gap between two consecutive articles is allowed to be before the
+@code{XOVER} request is split into several request.  Note that if your
+network is fast, setting this variable to a really small number means
+that fetching will probably be slower.  If this variable is @code{nil},
+@code{nntp} will never split requests.  The default is 5.
+
+@item nntp-prepare-server-hook
+@vindex nntp-prepare-server-hook
+A hook run before attempting to connect to an @acronym{NNTP} server.
+
+@item nntp-warn-about-losing-connection
+@vindex nntp-warn-about-losing-connection
+If this variable is non-@code{nil}, some noise will be made when a
+server closes connection.
+
+@item nntp-record-commands
+@vindex nntp-record-commands
+If non-@code{nil}, @code{nntp} will log all commands it sends to the
+@acronym{NNTP} server (along with a timestamp) in the @samp{*nntp-log*}
+buffer.  This is useful if you are debugging a Gnus/@acronym{NNTP} connection
+that doesn't seem to work.
+
 @item nntp-open-connection-function
 @vindex nntp-open-connection-function
-This function is used to connect to the remote system.  Three pre-made
-functions are @code{nntp-open-network-stream}, which is the default, and
-simply connects to some port or other on the remote system.  The other
-two are @code{nntp-open-rlogin}, which does an @samp{rlogin} on the
-remote system, and then does a @samp{telnet} to the @sc{nntp} server
-available there, and @code{nntp-open-telnet}, which does a @samp{telnet}
-to the remote system and then another @samp{telnet} to get to the
-@sc{nntp} server.
+It is possible to customize how the connection to the nntp server will
+be opened.  If you specify an @code{nntp-open-connection-function}
+parameter, Gnus will use that function to establish the connection.
+Five pre-made functions are supplied.  These functions can be grouped in
+two categories: direct connection functions (three pre-made), and
+indirect ones (two pre-made).
+
+@item nntp-prepare-post-hook
+@vindex nntp-prepare-post-hook
+A hook run just before posting an article.  If there is no
+@code{Message-ID} header in the article and the news server provides the
+recommended ID, it will be added to the article before running this
+hook.  It is useful to make @code{Cancel-Lock} headers even if you
+inhibit Gnus to add a @code{Message-ID} header, you could say:
+
+@lisp
+(add-hook 'nntp-prepare-post-hook 'canlock-insert-header)
+@end lisp
+
+Note that not all servers support the recommended ID.  This works for
+INN versions 2.3.0 and later, for instance.
+
+@item nntp-read-timeout
+@vindex nntp-read-timeout
+How long nntp should wait between checking for the end of output.
+Shorter values mean quicker response, but is more CPU intensive.  The
+default is 0.1 seconds.  If you have a slow line to the server (and
+don't like to see Emacs eat your available CPU power), you might set
+this to, say, 1.
+
+@item nntp-list-options
+@vindex nntp-list-options
+List of newsgroup name used for a option of the LIST command to restrict
+the listing output to only the specified newsgroups.  Each newsgroup name
+can be a shell-style wildcard, for instance, @dfn{fj.*}, @dfn{japan.*},
+etc.  Fortunately, if the server can accept such a option, it will
+probably make gnus run faster.  You may use it as a server variable as
+follows:
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+            (nntp-list-options ("fj.*" "japan.*"))))
+@end lisp
+
+@item nntp-options-subscribe
+@vindex nntp-options-subscribe
+Regexp matching the newsgroup names which will be subscribed
+unconditionally.  Use @dfn{ } instead of @dfn{$} for a regexp string.
+It may be effective as well as @code{nntp-list-options} even though the
+server could not accept a shell-style wildcard as a option of the LIST
+command.  You may use it as a server variable as follows:
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+            (nntp-options-subscribe "^fj\\.\\|^japan\\.")))
+@end lisp
+
+@item nntp-options-not-subscribe
+@vindex nntp-options-not-subscribe
+Regexp matching the newsgroup names which will not be subscribed
+unconditionally.  Use @dfn{ } instead of @dfn{$} for a regexp string.
+It may be effective as well as @code{nntp-list-options} even though the
+server could not accept a shell-style wildcard as a option of the LIST
+command.  You may use it as a server variable as follows:
+
+@lisp
+(setq gnus-select-method
+      '(nntp "news.somewhere.edu"
+            (nntp-options-not-subscribe "\\.binaries\\.")))
+@end lisp
+@end table
+
+@menu
+* Direct Functions::            Connecting directly to the server.
+* Indirect Functions::          Connecting indirectly to the server.
+* Common Variables::            Understood by several connection functions.
+@end menu
+
+
+@node Direct Functions
+@subsubsection Direct Functions
+@cindex direct connection functions
 
-@code{nntp-open-rlogin}-related variables:
+These functions are called direct because they open a direct connection
+between your machine and the @acronym{NNTP} server.  The behavior of these
+functions is also affected by commonly understood variables
+(@pxref{Common Variables}).
 
 @table @code
+@findex nntp-open-network-stream
+@item nntp-open-network-stream
+This is the default, and simply connects to some port or other on the
+remote system.
+
+@findex nntp-open-tls-stream
+@item nntp-open-tls-stream
+Opens a connection to a server over a @dfn{secure} channel.  To use
+this you must have @uref{http://www.gnu.org/software/gnutls/, GNUTLS}
+installed.  You then define a server as follows:
+
+@lisp
+;; @r{"nntps" is port 563 and is predefined in our @file{/etc/services}}
+;; @r{however, @samp{gnutls-cli -p} doesn't like named ports.}
+;;
+(nntp "snews.bar.com"
+      (nntp-open-connection-function nntp-open-tls-stream)
+      (nntp-port-number )
+      (nntp-address "snews.bar.com"))
+@end lisp
+
+@findex nntp-open-ssl-stream
+@item nntp-open-ssl-stream
+Opens a connection to a server over a @dfn{secure} channel.  To use
+this you must have @uref{http://www.openssl.org, OpenSSL} or
+@uref{ftp://ftp.psy.uq.oz.au/pub/Crypto/SSL, SSLeay} installed.  You
+then define a server as follows:
+
+@lisp
+;; @r{"snews" is port 563 and is predefined in our @file{/etc/services}}
+;; @r{however, @samp{openssl s_client -port} doesn't like named ports.}
+;;
+(nntp "snews.bar.com"
+      (nntp-open-connection-function nntp-open-ssl-stream)
+      (nntp-port-number 563)
+      (nntp-address "snews.bar.com"))
+@end lisp
+
+@findex nntp-open-telnet-stream
+@item nntp-open-telnet-stream
+Opens a connection to an @acronym{NNTP} server by simply @samp{telnet}'ing
+it.  You might wonder why this function exists, since we have the
+default @code{nntp-open-network-stream} which would do the job.  (One
+of) the reason(s) is that if you are behind a firewall but have direct
+connections to the outside world thanks to a command wrapper like
+@code{runsocks}, you can use it like this:
+
+@lisp
+(nntp "socksified"
+      (nntp-pre-command "runsocks")
+      (nntp-open-connection-function nntp-open-telnet-stream)
+      (nntp-address "the.news.server"))
+@end lisp
+
+With the default method, you would need to wrap your whole Emacs
+session, which is not a good idea.
+@end table
+
 
-@item nntp-rlogin-program 
-@vindex nntp-rlogin-program 
-Program used to log in on remote machines.  The default is @samp{rsh},
-but @samp{ssh} is a popular alternative.
+@node Indirect Functions
+@subsubsection Indirect Functions
+@cindex indirect connection functions
 
-@item nntp-rlogin-parameters
-@vindex nntp-rlogin-parameters
-This list will be used as the parameter list given to @code{rsh}.
+These functions are called indirect because they connect to an
+intermediate host before actually connecting to the @acronym{NNTP} server.
+All of these functions and related variables are also said to belong to
+the ``via'' family of connection: they're all prefixed with ``via'' to make
+things cleaner.  The behavior of these functions is also affected by
+commonly understood variables (@pxref{Common Variables}).
 
-@item nntp-rlogin-user-name
-@vindex nntp-rlogin-user-name
-User name on the remote system.
+@table @code
+@item nntp-open-via-rlogin-and-telnet
+@findex nntp-open-via-rlogin-and-telnet
+Does an @samp{rlogin} on a remote system, and then does a @samp{telnet}
+to the real @acronym{NNTP} server from there.  This is useful for instance if
+you need to connect to a firewall machine first.
+
+@code{nntp-open-via-rlogin-and-telnet}-specific variables:
 
+@table @code
+@item nntp-via-rlogin-command
+@vindex nntp-via-rlogin-command
+Command used to log in on the intermediate host.  The default is
+@samp{rsh}, but @samp{ssh} is a popular alternative.
+
+@item nntp-via-rlogin-command-switches
+@vindex nntp-via-rlogin-command-switches
+List of strings to be used as the switches to
+@code{nntp-via-rlogin-command}.  The default is @code{nil}.  If you use
+@samp{ssh} for @code{nntp-via-rlogin-command}, you may set this to
+@samp{("-C")} in order to compress all data connections, otherwise set
+this to @samp{("-t" "-e" "none")} or @samp{("-C" "-t" "-e" "none")} if
+the telnet command requires a pseudo-tty allocation on an intermediate
+host.
 @end table
 
-@code{nntp-open-telnet}-related variables:
+@item nntp-open-via-telnet-and-telnet
+@findex nntp-open-via-telnet-and-telnet
+Does essentially the same, but uses @samp{telnet} instead of
+@samp{rlogin} to connect to the intermediate host.
+
+@code{nntp-open-via-telnet-and-telnet}-specific variables:
 
 @table @code
-@item nntp-telnet-command
-@vindex nntp-telnet-command
-Command used to start @code{telnet}.
+@item nntp-via-telnet-command
+@vindex nntp-via-telnet-command
+Command used to @code{telnet} the intermediate host.  The default is
+@samp{telnet}.
+
+@item nntp-via-telnet-switches
+@vindex nntp-via-telnet-switches
+List of strings to be used as the switches to the
+@code{nntp-via-telnet-command} command.  The default is @samp{("-8")}.
+
+@item nntp-via-user-password
+@vindex nntp-via-user-password
+Password to use when logging in on the intermediate host.
+
+@item nntp-via-envuser
+@vindex nntp-via-envuser
+If non-@code{nil}, the intermediate @code{telnet} session (client and
+server both) will support the @code{ENVIRON} option and not prompt for
+login name.  This works for Solaris @code{telnet}, for instance.
+
+@item nntp-via-shell-prompt
+@vindex nntp-via-shell-prompt
+Regexp matching the shell prompt on the intermediate host.  The default
+is @samp{bash\\|\$ *\r?$\\|> *\r?}.
 
-@item nntp-telnet-switches
-@vindex nntp-telnet-switches
-List of strings to be used as the switches to the @code{telnet} command.
+@end table
+
+@end table
 
-@item nntp-telnet-user-name
-@vindex nntp-telnet-user-name
-User name for log in on the remote system.
 
-@item nntp-telnet-passwd
-@vindex nntp-telnet-passwd
-Password to use when logging in.
+Here are some additional variables that are understood by all the above
+functions:
 
-@item nntp-telnet-parameters
-@vindex nntp-telnet-parameters
-A list of strings executed as a command after logging in
-via @code{telnet}.
+@table @code
 
-@item nntp-telnet-shell-prompt
-@vindex nntp-telnet-shell-prompt
-Regexp matching the shell prompt on the remote machine.  The default is
-@samp{bash\\|\$ *\r?$\\|> *\r?}.
+@item nntp-via-user-name
+@vindex nntp-via-user-name
+User name to use when connecting to the intermediate host.
 
-@item nntp-open-telnet-envuser
-@vindex nntp-open-telnet-envuser
-If non-@code{nil}, the @code{telnet} session (client and server both)
-will support the @code{ENVIRON} option and not prompt for login name.
-This works for Solaris @code{telnet}, for instance.
+@item nntp-via-address
+@vindex nntp-via-address
+Address of the intermediate host to connect to.
 
 @end table
 
-@item nntp-end-of-line
-@vindex nntp-end-of-line
-String to use as end-of-line marker when talking to the @sc{nntp}
-server.  This is @samp{\r\n} by default, but should be @samp{\n} when
-using @code{rlogin} to talk to the server.
 
-@item nntp-rlogin-user-name
-@vindex nntp-rlogin-user-name
-User name on the remote system when using the @code{rlogin} connect
-function. 
+@node Common Variables
+@subsubsection Common Variables
+
+The following variables affect the behavior of all, or several of the
+pre-made connection functions.  When not specified, all functions are
+affected.
+
+@table @code
+
+@item nntp-pre-command
+@vindex nntp-pre-command
+A command wrapper to use when connecting through a non native
+connection function (all except @code{nntp-open-network-stream},
+@code{nntp-open-tls-stream}, and @code{nntp-open-ssl-stream}.  This is
+where you would put a @samp{SOCKS} wrapper for instance.
 
 @item nntp-address
 @vindex nntp-address
-The address of the remote system running the @sc{nntp} server.
+The address of the @acronym{NNTP} server.
 
 @item nntp-port-number
 @vindex nntp-port-number
-Port number to connect to when using the @code{nntp-open-network-stream}
-connect function.
-
-@item nntp-buggy-select
-@vindex nntp-buggy-select
-Set this to non-@code{nil} if your select routine is buggy.
-
-@item nntp-nov-is-evil 
-@vindex nntp-nov-is-evil 
-If the @sc{nntp} server does not support @sc{nov}, you could set this
-variable to @code{t}, but @code{nntp} usually checks automatically whether @sc{nov}
-can be used.
-
-@item nntp-xover-commands
-@vindex nntp-xover-commands
-@cindex nov
-@cindex XOVER
-List of strings used as commands to fetch @sc{nov} lines from a
-server.  The default value of this variable is @code{("XOVER"
-"XOVERVIEW")}. 
+Port number to connect to the @acronym{NNTP} server.  The default is
+@samp{nntp}.  If you use @acronym{NNTP} over
+@acronym{TLS}/@acronym{SSL}, you may want to use integer ports rather
+than named ports (i.e, use @samp{563} instead of @samp{snews} or
+@samp{nntps}), because external @acronym{TLS}/@acronym{SSL} tools may
+not work with named ports.
 
-@item nntp-nov-gap
-@vindex nntp-nov-gap
-@code{nntp} normally sends just one big request for @sc{nov} lines to
-the server.  The server responds with one huge list of lines.  However,
-if you have read articles 2-5000 in the group, and only want to read
-article 1 and 5001, that means that @code{nntp} will fetch 4999 @sc{nov}
-lines that you will not need.  This variable says how
-big a gap between two consecutive articles is allowed to be before the
-@code{XOVER} request is split into several request.  Note that if your
-network is fast, setting this variable to a really small number means
-that fetching will probably be slower.  If this variable is @code{nil},
-@code{nntp} will never split requests.  The default is 5.
+@item nntp-end-of-line
+@vindex nntp-end-of-line
+String to use as end-of-line marker when talking to the @acronym{NNTP}
+server.  This is @samp{\r\n} by default, but should be @samp{\n} when
+using a non native connection function.
 
-@item nntp-prepare-server-hook
-@vindex nntp-prepare-server-hook
-A hook run before attempting to connect to an @sc{nntp} server.
+@item nntp-telnet-command
+@vindex nntp-telnet-command
+Command to use when connecting to the @acronym{NNTP} server through
+@samp{telnet}.  This is @emph{not} for an intermediate host.  This is
+just for the real @acronym{NNTP} server.  The default is
+@samp{telnet}.
 
-@item nntp-warn-about-losing-connection
-@vindex nntp-warn-about-losing-connection
-If this variable is non-@code{nil}, some noise will be made when a
-server closes connection.
+@item nntp-telnet-switches
+@vindex nntp-telnet-switches
+A list of switches to pass to @code{nntp-telnet-command}.  The default
+is @samp{("-8")}.
 
 @end table
 
@@ -9105,9 +12916,9 @@ server closes connection.
 Subscribing to a foreign group from the local spool is extremely easy,
 and might be useful, for instance, to speed up reading groups that
 contain very big articles---@samp{alt.binaries.pictures.furniture}, for
-instance. 
+instance.
 
-Anyways, you just specify @code{nnspool} as the method and @code{""} (or
+Anyway, you just specify @code{nnspool} as the method and @code{""} (or
 anything else) as the address.
 
 If you have access to a local spool, you should probably use that as the
@@ -9123,16 +12934,16 @@ Program used to post an article.
 
 @item nnspool-inews-switches
 @vindex nnspool-inews-switches
-Parameters given to the inews program when posting an article. 
+Parameters given to the inews program when posting an article.
 
 @item nnspool-spool-directory
 @vindex nnspool-spool-directory
 Where @code{nnspool} looks for the articles.  This is normally
 @file{/usr/spool/news/}.
 
-@item nnspool-nov-directory 
-@vindex nnspool-nov-directory 
-Where @code{nnspool} will look for @sc{nov} files.  This is normally
+@item nnspool-nov-directory
+@vindex nnspool-nov-directory
+Where @code{nnspool} will look for @acronym{NOV} files.  This is normally@*
 @file{/usr/spool/news/over.view/}.
 
 @item nnspool-lib-dir
@@ -9141,31 +12952,32 @@ Where the news lib dir is (@file{/usr/lib/news/} by default).
 
 @item nnspool-active-file
 @vindex nnspool-active-file
-The path to the active file.
+The name of the active file.
 
 @item nnspool-newsgroups-file
 @vindex nnspool-newsgroups-file
-The path to the group descriptions file.
+The name of the group descriptions file.
 
 @item nnspool-history-file
 @vindex nnspool-history-file
-The path to the news history file.
+The name of the news history file.
 
 @item nnspool-active-times-file
 @vindex nnspool-active-times-file
-The path to the active date file.
+The name of the active date file.
 
 @item nnspool-nov-is-evil
 @vindex nnspool-nov-is-evil
-If non-@code{nil}, @code{nnspool} won't try to use any @sc{nov} files
+If non-@code{nil}, @code{nnspool} won't try to use any @acronym{NOV} files
 that it finds.
 
 @item nnspool-sift-nov-with-sed
 @vindex nnspool-sift-nov-with-sed
 @cindex sed
 If non-@code{nil}, which is the default, use @code{sed} to get the
-relevant portion from the overview file.  If nil, @code{nnspool} will
-load the entire file into a buffer and process it there.
+relevant portion from the overview file.  If @code{nil},
+@code{nnspool} will load the entire file into a buffer and process it
+there.
 
 @end table
 
@@ -9179,38 +12991,104 @@ Reading mail with a newsreader---isn't that just plain WeIrD? But of
 course.
 
 @menu
-* Getting Started Reading Mail:: A simple cookbook example.
-* Splitting Mail::               How to create mail groups.
-* Mail Backend Variables::       Variables for customizing mail handling.
-* Fancy Mail Splitting::         Gnus can do hairy splitting of incoming mail.
-* Mail and Procmail::            Reading mail groups that procmail create.
-* Incorporating Old Mail::       What about the old mail you have?
-* Expiring Mail::                Getting rid of unwanted mail.
-* Washing Mail::                 Removing gruft from the mail you get.
-* Duplicates::                   Dealing with duplicated mail.
-* Not Reading Mail::             Using mail backends for reading other files.
-* Choosing a Mail Backend::      Gnus can read a variety of mail formats.
+* Mail in a Newsreader::        Important introductory notes.
+* Getting Started Reading Mail::  A simple cookbook example.
+* Splitting Mail::              How to create mail groups.
+* Mail Sources::                How to tell Gnus where to get mail from.
+* Mail Back End Variables::     Variables for customizing mail handling.
+* Fancy Mail Splitting::        Gnus can do hairy splitting of incoming mail.
+* Group Mail Splitting::        Use group customize to drive mail splitting.
+* Incorporating Old Mail::      What about the old mail you have?
+* Expiring Mail::               Getting rid of unwanted mail.
+* Washing Mail::                Removing cruft from the mail you get.
+* Duplicates::                  Dealing with duplicated mail.
+* Not Reading Mail::            Using mail back ends for reading other files.
+* Choosing a Mail Back End::    Gnus can read a variety of mail formats.
 @end menu
 
 
-@node Getting Started Reading Mail
-@subsection Getting Started Reading Mail
+@node Mail in a Newsreader
+@subsection Mail in a Newsreader
 
-It's quite easy to use Gnus to read your new mail.  You just plonk the
-mail backend of your choice into @code{gnus-secondary-select-methods},
-and things will happen automatically.
+If you are used to traditional mail readers, but have decided to switch
+to reading mail with Gnus, you may find yourself experiencing something
+of a culture shock.
 
-For instance, if you want to use @code{nnml} (which is a "one file per
-mail" backend), you could put the following in your @file{.gnus} file:
+Gnus does not behave like traditional mail readers.  If you want to make
+it behave that way, you can, but it's an uphill battle.
 
-@lisp
-(setq gnus-secondary-select-methods
-      '((nnml "private")))
+Gnus, by default, handles all its groups using the same approach.  This
+approach is very newsreaderly---you enter a group, see the new/unread
+messages, and when you read the messages, they get marked as read, and
+you don't see them any more.  (Unless you explicitly ask for them.)
+
+In particular, you do not do anything explicitly to delete messages.
+
+Does this mean that all the messages that have been marked as read are
+deleted?  How awful!
+
+But, no, it means that old messages are @dfn{expired} according to some
+scheme or other.  For news messages, the expire process is controlled by
+the news administrator; for mail, the expire process is controlled by
+you.  The expire process for mail is covered in depth in @ref{Expiring
+Mail}.
+
+What many Gnus users find, after using it a while for both news and
+mail, is that the transport mechanism has very little to do with how
+they want to treat a message.
+
+Many people subscribe to several mailing lists.  These are transported
+via @acronym{SMTP}, and are therefore mail.  But we might go for weeks without
+answering, or even reading these messages very carefully.  We may not
+need to save them because if we should need to read one again, they are
+archived somewhere else.
+
+Some people have local news groups which have only a handful of readers.
+These are transported via @acronym{NNTP}, and are therefore news.  But we may need
+to read and answer a large fraction of the messages very carefully in
+order to do our work.  And there may not be an archive, so we may need
+to save the interesting messages the same way we would personal mail.
+
+The important distinction turns out to be not the transport mechanism,
+but other factors such as how interested we are in the subject matter,
+or how easy it is to retrieve the message if we need to read it again.
+
+Gnus provides many options for sorting mail into ``groups'' which behave
+like newsgroups, and for treating each group (whether mail or news)
+differently.
+
+Some users never get comfortable using the Gnus (ahem) paradigm and wish
+that Gnus should grow up and be a male, er, mail reader.  It is possible
+to whip Gnus into a more mailreaderly being, but, as said before, it's
+not easy.  People who prefer proper mail readers should try @sc{vm}
+instead, which is an excellent, and proper, mail reader.
+
+I don't mean to scare anybody off, but I want to make it clear that you
+may be required to learn a new way of thinking about messages.  After
+you've been subjected to The Gnus Way, you will come to love it.  I can
+guarantee it.  (At least the guy who sold me the Emacs Subliminal
+Brain-Washing Functions that I've put into Gnus did guarantee it.  You
+Will Be Assimilated.  You Love Gnus.  You Love The Gnus Mail Way.
+You Do.)
+
+
+@node Getting Started Reading Mail
+@subsection Getting Started Reading Mail
+
+It's quite easy to use Gnus to read your new mail.  You just plonk the
+mail back end of your choice into @code{gnus-secondary-select-methods},
+and things will happen automatically.
+
+For instance, if you want to use @code{nnml} (which is a ``one file per
+mail'' back end), you could put the following in your @file{~/.gnus.el} file:
+
+@lisp
+(setq gnus-secondary-select-methods '((nnml "")))
 @end lisp
 
-Now, the next time you start Gnus, this backend will be queried for new
+Now, the next time you start Gnus, this back end will be queried for new
 articles, and it will move all the messages in your spool file to its
-directory, which is @code{~/Mail/} by default.  The new group that will
+directory, which is @file{~/Mail/} by default.  The new group that will
 be created (@samp{mail.misc}) will be subscribed, and you can read it
 like any other group.
 
@@ -9230,13 +13108,14 @@ last group.
 
 This should be sufficient for reading mail with Gnus.  You might want to
 give the other sections in this part of the manual a perusal, though.
-Especially @pxref{Choosing a Mail Backend} and @pxref{Expiring Mail}. 
+Especially @pxref{Choosing a Mail Back End} and @pxref{Expiring Mail}.
 
 
 @node Splitting Mail
 @subsection Splitting Mail
 @cindex splitting mail
 @cindex mail splitting
+@cindex mail filtering (splitting)
 
 @vindex nnmail-split-methods
 The @code{nnmail-split-methods} variable says how the incoming mail is
@@ -9258,24 +13137,20 @@ contain @samp{\\1} forms, like the ones used by @code{replace-match} to
 insert sub-expressions from the matched text.  For instance:
 
 @lisp
-("list.\\1" "From:.*\\(.*\\)-list@@majordomo.com")
+("list.\\1" "From:.* \\(.*\\)-list@@majordomo.com")
 @end lisp
 
-If the first element is the special symbol @code{junk}, then messages
-that match the regexp will disappear into the aether.  Use with
-extreme caution. 
-
 The second element can also be a function.  In that case, it will be
 called narrowed to the headers with the first element of the rule as the
 argument.  It should return a non-@code{nil} value if it thinks that the
 mail belongs in that group.
 
 The last of these groups should always be a general one, and the regular
-expression should @emph{always} be @samp{} so that it matches any mails
+expression should @emph{always} be @samp{*} so that it matches any mails
 that haven't been matched by any of the other regexps.  (These rules are
 processed from the beginning of the alist toward the end.  The first
-rule to make a match will "win", unless you have crossposting enabled.
-In that case, all matching rules will "win".)
+rule to make a match will ``win'', unless you have crossposting enabled.
+In that case, all matching rules will ``win''.)
 
 If you like to tinker with this yourself, you can set this variable to a
 function of your choice.  This function will be called without any
@@ -9283,16 +13158,16 @@ arguments in a buffer narrowed to the headers of an incoming mail
 message.  The function should return a list of group names that it
 thinks should carry this mail message.
 
-Note that the mail backends are free to maul the poor, innocent,
+Note that the mail back ends are free to maul the poor, innocent,
 incoming headers all they want to.  They all add @code{Lines} headers;
 some add @code{X-Gnus-Group} headers; most rename the Unix mbox
 @code{From<SPACE>} line to something else.
 
 @vindex nnmail-crosspost
-The mail backends all support cross-posting.  If several regexps match,
+The mail back ends all support cross-posting.  If several regexps match,
 the mail will be ``cross-posted'' to all those groups.
 @code{nnmail-crosspost} says whether to use this mechanism or not.  Note
-that no articles are crossposted to the general (@samp{}) group.
+that no articles are crossposted to the general (@samp{*}) group.
 
 @vindex nnmail-crosspost-link-function
 @cindex crosspost
@@ -9301,12 +13176,38 @@ that no articles are crossposted to the general (@samp{}) group.
 the crossposted articles.  However, not all file systems support hard
 links.  If that's the case for you, set
 @code{nnmail-crosspost-link-function} to @code{copy-file}.  (This
-variable is @code{add-name-to-file} by default.)  
+variable is @code{add-name-to-file} by default.)
 
 @kindex M-x nnmail-split-history
-@kindex nnmail-split-history
+@findex nnmail-split-history
 If you wish to see where the previous mail split put the messages, you
-can use the @kbd{M-x nnmail-split-history} command.
+can use the @kbd{M-x nnmail-split-history} command.  If you wish to see
+where re-spooling messages would put the messages, you can use
+@code{gnus-summary-respool-trace} and related commands (@pxref{Mail
+Group Commands}).
+
+@vindex nnmail-split-header-length-limit
+Header lines longer than the value of
+@code{nnmail-split-header-length-limit} are excluded from the split
+function.
+
+@vindex nnmail-mail-splitting-charset
+@vindex nnmail-mail-splitting-decodes
+By default the splitting codes @acronym{MIME} decodes headers so you
+can match on non-@acronym{ASCII} strings.  The
+@code{nnmail-mail-splitting-charset} variable specifies the default
+charset for decoding.  The behaviour can be turned off completely by
+binding @code{nnmail-mail-splitting-decodes} to @code{nil}, which is
+useful if you want to match articles based on the raw header data.
+
+@vindex nnmail-resplit-incoming
+By default, splitting is performed on all incoming messages.  If you
+specify a @code{directory} entry for the variable @code{mail-sources}
+(@pxref{Mail Source Specifiers}), however, then splitting does
+@emph{not} happen by default.  You can set the variable
+@code{nnmail-resplit-incoming} to a non-@code{nil} value to make
+splitting happen even in this case.  (This variable has no effect on
+other kinds of entries.)
 
 Gnus gives you all the opportunity you could possibly want for shooting
 yourself in the foot.  Let's say you create a group that will contain
@@ -9319,1513 +13220,2317 @@ you really should be out collecting empty bottles to save up for next
 month's rent money.
 
 
-@node Mail Backend Variables
-@subsection Mail Backend Variables
+@node Mail Sources
+@subsection Mail Sources
 
-These variables are (for the most part) pertinent to all the various
-mail backends.
+Mail can be gotten from many different sources---the mail spool, from
+a @acronym{POP} mail server, from a procmail directory, or from a
+maildir, for instance.
 
-@table @code
-@vindex nnmail-read-incoming-hook
-@item nnmail-read-incoming-hook
-The mail backends all call this hook after reading new mail.  You can
-use this hook to notify any mail watch programs, if you want to.
+@menu
+* Mail Source Specifiers::      How to specify what a mail source is.
+* Mail Source Customization::   Some variables that influence things.
+* Fetching Mail::               Using the mail source specifiers.
+@end menu
 
-@vindex nnmail-spool-file
-@item nnmail-spool-file
-@cindex POP mail
-@cindex MAILHOST
-@cindex movemail
-@vindex nnmail-pop-password
-@vindex nnmail-pop-password-required
-The backends will look for new mail in this file.  If this variable is
-@code{nil}, the mail backends will never attempt to fetch mail by
-themselves.  If you are using a POP mail server and your name is
-@samp{larsi}, you should set this variable to @samp{po:larsi}.  If
-your name is not @samp{larsi}, you should probably modify that
-slightly, but you may have guessed that already, you smart & handsome
-devil!  You can also set this variable to @code{pop}, and Gnus will try
-to figure out the POP mail string by itself.  In any case, Gnus will
-call @code{movemail} which will contact the POP server named in the
-@code{MAILHOST} environment variable.  If the POP server needs a
-password, you can either set @code{nnmail-pop-password-required} to
-@code{t} and be prompted for the password, or set
-@code{nnmail-pop-password} to the password itself.
-
-@code{nnmail-spool-file} can also be a list of mailboxes.
-
-Your Emacs has to have been configured with @samp{--with-pop} before
-compilation.  This is the default, but some installations have it
-switched off.
-
-When you use a mail backend, Gnus will slurp all your mail from your
-inbox and plonk it down in your home directory.  Gnus doesn't move any
-mail if you're not using a mail backend---you have to do a lot of magic
-invocations first.  At the time when you have finished drawing the
-pentagram, lightened the candles, and sacrificed the goat, you really
-shouldn't be too surprised when Gnus moves your mail.
 
-@vindex nnmail-use-procmail
-@vindex nnmail-procmail-suffix
-@item nnmail-use-procmail
-If non-@code{nil}, the mail backends will look in
-@code{nnmail-procmail-directory} for incoming mail.  All the files in
-that directory that have names ending in @code{nnmail-procmail-suffix}
-will be considered incoming mailboxes, and will be searched for new
-mail.
+@node Mail Source Specifiers
+@subsubsection Mail Source Specifiers
+@cindex POP
+@cindex mail server
+@cindex procmail
+@cindex mail spool
+@cindex mail source
 
-@vindex nnmail-crash-box
-@item nnmail-crash-box
-When a mail backend reads a spool file, mail is first moved to this
-file, which is @file{~/.gnus-crash-box} by default.  If this file
-already exists, it will always be read (and incorporated) before any
-other spool files.
+You tell Gnus how to fetch mail by setting @code{mail-sources}
+(@pxref{Fetching Mail}) to a @dfn{mail source specifier}.
 
-@vindex nnmail-prepare-incoming-hook
-@item nnmail-prepare-incoming-hook
-This is run in a buffer that holds all the new incoming mail, and can be
-used for, well, anything, really.
+Here's an example:
 
-@vindex nnmail-split-hook
-@item nnmail-split-hook
-@findex article-decode-rfc1522
-@findex RFC1522 decoding
-Hook run in the buffer where the mail headers of each message is kept
-just before the splitting based on these headers is done.  The hook is
-free to modify the buffer contents in any way it sees fit---the buffer
-is discarded after the splitting has been done, and no changes performed
-in the buffer will show up in any files.  @code{gnus-article-decode-rfc1522}
-is one likely function to add to this hook.
+@lisp
+(pop :server "pop3.mailserver.com" :user "myname")
+@end lisp
 
-@vindex nnmail-pre-get-new-mail-hook
-@vindex nnmail-post-get-new-mail-hook
-@item nnmail-pre-get-new-mail-hook
-@itemx nnmail-post-get-new-mail-hook
-These are two useful hooks executed when treating new incoming
-mail---@code{nnmail-pre-get-new-mail-hook} (is called just before
-starting to handle the new mail) and
-@code{nnmail-post-get-new-mail-hook} (is called when the mail handling
-is done).  Here's and example of using these two hooks to change the
-default file modes the new mail files get:
+As can be observed, a mail source specifier is a list where the first
+element is a @dfn{mail source type}, followed by an arbitrary number of
+@dfn{keywords}.  Keywords that are not explicitly specified are given
+default values.
+
+The following mail source types are available:
+
+@table @code
+@item file
+Get mail from a single file; typically from the mail spool.
+
+Keywords:
+
+@table @code
+@item :path
+The file name.  Defaults to the value of the @env{MAIL}
+environment variable or the value of @code{rmail-spool-directory}
+(usually something like @file{/usr/mail/spool/user-name}).
+
+@item :prescript
+@itemx :postscript
+Script run before/after fetching mail.
+@end table
+
+An example file mail source:
 
 @lisp
-(add-hook 'gnus-pre-get-new-mail-hook 
-          (lambda () (set-default-file-modes 511)))
+(file :path "/usr/spool/mail/user-name")
+@end lisp
 
-(add-hook 'gnus-post-get-new-mail-hook 
-          (lambda () (set-default-file-modes 551)))
+Or using the default file name:
+
+@lisp
+(file)
 @end lisp
 
-@item nnmail-tmp-directory
-@vindex nnmail-tmp-directory
-This variable says where to move incoming mail to -- while processing
-it.  This is usually done in the same directory that the mail backend
-inhabits (e.g., @file{~/Mail/}), but if this variable is non-@code{nil},
-it will be used instead.
+If the mail spool file is not located on the local machine, it's best
+to use @acronym{POP} or @acronym{IMAP} or the like to fetch the mail.
+You can not use ange-ftp file names here---it has no way to lock the
+mail spool while moving the mail.
 
-@item nnmail-movemail-program
-@vindex nnmail-movemail-program
-This program is executed to move mail from the user's inbox to her home
-directory.  The default is @samp{movemail}.
+If it's impossible to set up a proper server, you can use ssh instead.
 
-This can also be a function.  In that case, the function will be called
-with two parameters -- the name of the inbox, and the file to be moved
-to.
+@lisp
+(setq mail-sources
+      '((file :prescript "ssh host bin/getmail >%t")))
+@end lisp
 
-@item nnmail-delete-incoming
-@vindex nnmail-delete-incoming
-@cindex incoming mail files
-@cindex deleting incoming files
-If non-@code{nil}, the mail backends will delete the temporary incoming
-file after splitting mail into the proper groups.  This is @code{t} by
-default.
+The @samp{getmail} script would look something like the following:
 
-@c This is @code{nil} by
-@c default for reasons of security.
+@example
+#!/bin/sh
+#  getmail - move mail from spool to stdout
+#  flu@@iki.fi
 
-@c Since Red Gnus is an alpha release, it is to be expected to lose mail.
-(No Gnus release since (ding) Gnus 0.10 (or something like that) have
-lost mail, I think, but that's not the point.  (Except certain versions
-of Red Gnus.))  By not deleting the Incoming* files, one can be sure not
-to lose mail -- if Gnus totally whacks out, one can always recover what
-was lost.
+MOVEMAIL=/usr/lib/emacs/20.3/i386-redhat-linux/movemail
+TMP=$HOME/Mail/tmp
+rm -f $TMP; $MOVEMAIL $MAIL $TMP >/dev/null && cat $TMP
+@end example
 
-You may delete the @file{Incoming*} files at will.
+Alter this script to fit find the @samp{movemail} you want to use.
 
-@item nnmail-use-long-file-names
-@vindex nnmail-use-long-file-names
-If non-@code{nil}, the mail backends will use long file and directory
-names.  Groups like @samp{mail.misc} will end up in directories
-(assuming use of @code{nnml} backend) or files (assuming use of
-@code{nnfolder} backend) like @file{mail.misc}.  If it is @code{nil},
-the same group will end up in @file{mail/misc}.
 
-@item nnmail-delete-file-function
-@vindex nnmail-delete-file-function
-@findex delete-file
-Function called to delete files.  It is @code{delete-file} by default. 
+@item directory
+@vindex nnmail-scan-directory-mail-source-once
+Get mail from several files in a directory.  This is typically used
+when you have procmail split the incoming mail into several files.
+That is, there is a one-to-one correspondence between files in that
+directory and groups, so that mail from the file @file{foo.bar.spool}
+will be put in the group @code{foo.bar}.  (You can change the suffix
+to be used instead of @code{.spool}.)  Setting
+@code{nnmail-scan-directory-mail-source-once} to non-@code{nil} forces
+Gnus to scan the mail source only once.  This is particularly useful
+if you want to scan mail groups at a specified level.
 
-@item nnmail-cache-accepted-message-ids
-@vindex nnmail-cache-accepted-message-ids
-If non-@code{nil}, put the @code{Message-ID}s of articles imported into
-the backend (via @code{Gcc}, for instance) into the mail duplication
-discovery cache.  The default is @code{nil}.
+@vindex nnmail-resplit-incoming
+There is also the variable @code{nnmail-resplit-incoming}, if you set
+that to a non-@code{nil} value, then the normal splitting process is
+applied to all the files from the directory, @ref{Splitting Mail}.
 
-@end table
+Keywords:
 
+@table @code
+@item :path
+The name of the directory where the files are.  There is no default
+value.
 
-@node Fancy Mail Splitting
-@subsection Fancy Mail Splitting
-@cindex mail splitting
-@cindex fancy mail splitting
+@item :suffix
+Only files ending with this suffix are used.  The default is
+@samp{.spool}.
 
-@vindex nnmail-split-fancy
-@findex nnmail-split-fancy
-If the rather simple, standard method for specifying how to split mail
-doesn't allow you to do what you want, you can set
-@code{nnmail-split-methods} to @code{nnmail-split-fancy}.  Then you can
-play with the @code{nnmail-split-fancy} variable.
+@item :predicate
+Only files that have this predicate return non-@code{nil} are returned.
+The default is @code{identity}.  This is used as an additional
+filter---only files that have the right suffix @emph{and} satisfy this
+predicate are considered.
 
-Let's look at an example value of this variable first:
+@item :prescript
+@itemx :postscript
+Script run before/after fetching mail.
+
+@end table
+
+An example directory mail source:
 
 @lisp
-;; Messages from the mailer daemon are not crossposted to any of
-;; the ordinary groups.  Warnings are put in a separate group
-;; from real errors.
-(| ("from" mail (| ("subject" "warn.*" "mail.warning")
-                   "mail.misc"))
-   ;; Non-error messages are crossposted to all relevant
-   ;; groups, but we don't crosspost between the group for the
-   ;; (ding) list and the group for other (ding) related mail.
-   (& (| (any "ding@@ifi\\.uio\\.no" "ding.list")
-         ("subject" "ding" "ding.misc"))
-      ;; Other mailing lists...
-      (any "procmail@@informatik\\.rwth-aachen\\.de" "procmail.list")
-      (any "SmartList@@informatik\\.rwth-aachen\\.de" "SmartList.list")
-      ;; People...
-      (any "larsi@@ifi\\.uio\\.no" "people.Lars_Magne_Ingebrigtsen"))
-   ;; Unmatched mail goes to the catch all group.
-   "misc.misc")
+(directory :path "/home/user-name/procmail-dir/"
+           :suffix ".prcml")
 @end lisp
 
-This variable has the format of a @dfn{split}.  A split is a (possibly)
-recursive structure where each split may contain other splits.  Here are
-the five possible split syntaxes:
+@item pop
+Get mail from a @acronym{POP} server.
 
-@enumerate
+Keywords:
 
-@item 
-@samp{group}: If the split is a string, that will be taken as a group name. 
+@table @code
+@item :server
+The name of the @acronym{POP} server.  The default is taken from the
+@env{MAILHOST} environment variable.
+
+@item :port
+The port number of the @acronym{POP} server.  This can be a number (eg,
+@samp{:port 1234}) or a string (eg, @samp{:port "pop3"}).  If it is a
+string, it should be a service name as listed in @file{/etc/services} on
+Unix systems.  The default is @samp{"pop3"}.  On some systems you might
+need to specify it as @samp{"pop-3"} instead.
+
+@item :user
+The user name to give to the @acronym{POP} server.  The default is the login
+name.
 
-@item
-@var{(FIELD VALUE SPLIT)}: If the split is a list, the first element of
-which is a string, then store the message as specified by SPLIT, if
-header FIELD (a regexp) contains VALUE (also a regexp).
+@item :password
+The password to give to the @acronym{POP} server.  If not specified,
+the user is prompted.
 
-@item
-@var{(| SPLIT...)}: If the split is a list, and the first element is
-@code{|} (vertical bar), then process each SPLIT until one of them
-matches.  A SPLIT is said to match if it will cause the mail message to
-be stored in one or more groups.
+@item :program
+The program to use to fetch mail from the @acronym{POP} server.  This
+should be a @code{format}-like string.  Here's an example:
 
-@item
-@var{(& SPLIT...)}: If the split is a list, and the first element is
-@code{&}, then process all SPLITs in the list.
+@example
+fetchmail %u@@%s -P %p %t
+@end example
 
-@item 
-@code{junk}: If the split is the symbol @code{junk}, then don't save
-this message.
+The valid format specifier characters are:
 
-@item
-@var{(: function arg1 arg2 ...)}:  If the split is a list, and the first
-element is @code{:}, then the second element will be called as a
-function with @var{args} given as arguments.  The function should return
-a SPLIT.
+@table @samp
+@item t
+The name of the file the mail is to be moved to.  This must always be
+included in this string.
 
-@end enumerate
+@item s
+The name of the server.
 
-In these splits, @var{FIELD} must match a complete field name.
-@var{VALUE} must match a complete word according to the fundamental mode
-syntax table.  You can use @code{.*} in the regexps to match partial
-field names or words.  In other words, all @var{VALUE}'s are wrapped in
-@samp{\<} and @samp{\>} pairs.
+@item P
+The port number of the server.
 
-@vindex nnmail-split-abbrev-alist
-@var{FIELD} and @var{VALUE} can also be lisp symbols, in that case they
-are expanded as specified by the variable
-@code{nnmail-split-abbrev-alist}.  This is an alist of cons cells, where
-the @code{car} of a cell contains the key, and the @code{cdr} contains the associated
-value.
+@item u
+The user name to use.
 
-@vindex nnmail-split-fancy-syntax-table
-@code{nnmail-split-fancy-syntax-table} is the syntax table in effect
-when all this splitting is performed.
+@item p
+The password to use.
+@end table
 
-If you want to have Gnus create groups dynamically based on some
-information in the headers (i.e., do @code{replace-match}-like
-substitions in the group names), you can say things like:
+The values used for these specs are taken from the values you give the
+corresponding keywords.
 
-@example
-(any "debian-\\(\\w*\\)@@lists.debian.org" "mail.debian.\\1")
-@end example
+@item :prescript
+A script to be run before fetching the mail.  The syntax is the same as
+the @code{:program} keyword.  This can also be a function to be run.
 
-@node Mail and Procmail
-@subsection Mail and Procmail
-@cindex procmail
+@item :postscript
+A script to be run after fetching the mail.  The syntax is the same as
+the @code{:program} keyword.  This can also be a function to be run.
+
+@item :function
+The function to use to fetch mail from the @acronym{POP} server.  The
+function is called with one parameter---the name of the file where the
+mail should be moved to.
+
+@item :authentication
+This can be either the symbol @code{password} or the symbol @code{apop}
+and says what authentication scheme to use.  The default is
+@code{password}.
+
+@item :connection
+What stream to use for connecting to the server, this can be the symbol
+@code{ssl}, the symbol @code{tls} or others.  The default is @code{nil}
+and use insecure connections.  Note that for SSL/TLS, you need external
+programs and libraries:
+
+@itemize @bullet
+@item
+@dfn{ssl:} Connect through SSL@. Requires OpenSSL (the program
+@samp{openssl}) or SSLeay (@samp{s_client}) as well as the external
+library @samp{ssl.el}.
+@item
+@dfn{starttls:} Connect via the STARTTLS extension (similar to SSL)@.
+Requires the external library @samp{starttls.el} and program
+@samp{starttls}.
+@end itemize
+
+@item :leave
+Non-@code{nil} if mail is to be left on the server and UIDL used for
+message retrieval.  The default is @code{nil}.
+
+@end table
 
-@cindex slocal
-@cindex elm
-Many people use @code{procmail} (or some other mail filter program or
-external delivery agent---@code{slocal}, @code{elm}, etc) to split
-incoming mail into groups.  If you do that, you should set
-@code{nnmail-spool-file} to @code{procmail} to ensure that the mail
-backends never ever try to fetch mail by themselves.
+If the @code{:program} and @code{:function} keywords aren't specified,
+@code{pop3-movemail} will be used.
 
-If you have a combined @code{procmail}/POP/mailbox setup, you can do
-something like the following:
+Here are some examples.  Fetch from the default @acronym{POP} server,
+using the default user name, and default fetcher:
 
-@vindex nnmail-use-procmail
 @lisp
-(setq nnmail-use-procmail t)
-(setq nnmail-spool-file
-      '("/usr/spool/mail/my-name" "po:my-name"))
+(pop)
 @end lisp
 
-This also means that you probably don't want to set
-@code{nnmail-split-methods} either, which has some, perhaps, unexpected
-side effects.
-
-When a mail backend is queried for what groups it carries, it replies
-with the contents of that variable, along with any groups it has figured
-out that it carries by other means.  None of the backends, except
-@code{nnmh}, actually go out to the disk and check what groups actually
-exist.  (It's not trivial to distinguish between what the user thinks is
-a basis for a newsgroup and what is just a plain old file or directory.)
+Fetch from a named server with a named user and password:
 
-This means that you have to tell Gnus (and the backends) by hand what
-groups exist.
+@lisp
+(pop :server "my.pop.server"
+     :user "user-name" :password "secret")
+@end lisp
 
-Let's take the @code{nnmh} backend as an example:
+Use @samp{movemail} to move the mail:
 
-The folders are located in @code{nnmh-directory}, say, @file{~/Mail/}.
-There are three folders, @file{foo}, @file{bar} and @file{mail.baz}.
+@lisp
+(pop :program "movemail po:%u %t %p")
+@end lisp
 
-Go to the group buffer and type @kbd{G m}.  When prompted, answer
-@samp{foo} for the name and @samp{nnmh} for the method.  Repeat
-twice for the two other groups, @samp{bar} and @samp{mail.baz}.  Be sure
-to include all your mail groups.
+@item maildir
+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.
 
-That's it.  You are now set to read your mail.  An active file for this
-method will be created automatically.
+Keywords:
 
-@vindex nnmail-procmail-suffix
-@vindex nnmail-procmail-directory
-If you use @code{nnfolder} or any other backend that store more than a
-single article in each file, you should never have procmail add mails to
-the file that Gnus sees.  Instead, procmail should put all incoming mail
-in @code{nnmail-procmail-directory}.  To arrive at the file name to put
-the incoming mail in, append @code{nnmail-procmail-suffix} to the group
-name.  The mail backends will read the mail from these files.
+@table @code
+@item :path
+The name of the directory where the mails are stored.  The default is
+taken from the @env{MAILDIR} environment variable or
+@file{~/Maildir/}.
+@item :subdirs
+The subdirectories of the Maildir.  The default is
+@samp{("new" "cur")}.
+
+@c If you sometimes look at your mail through a pop3 daemon before fetching
+@c them with Gnus, you may also have to fetch your mails from the
+@c @code{cur} directory inside the maildir, like in the first example
+@c below.
+
+You can also get mails from remote hosts (because maildirs don't suffer
+from locking problems).
 
-@vindex nnmail-resplit-incoming
-When Gnus reads a file called @file{mail.misc.spool}, this mail will be
-put in the @code{mail.misc}, as one would expect.  However, if you want
-Gnus to split the mail the normal way, you could set
-@code{nnmail-resplit-incoming} to @code{t}.
+@end table
 
-@vindex nnmail-keep-last-article
-If you use @code{procmail} to split things directly into an @code{nnmh}
-directory (which you shouldn't do), you should set
-@code{nnmail-keep-last-article} to non-@code{nil} to prevent Gnus from
-ever expiring the final article (i.e., the article with the highest
-article number) in a mail newsgroup.  This is quite, quite important.
+Two example maildir mail sources:
 
-Here's an example setup:  The incoming spools are located in
-@file{~/incoming/} and have @samp{""} as suffixes (i.e., the incoming
-spool files have the same names as the equivalent groups).  The
-@code{nnfolder} backend is to be used as the mail interface, and the
-@code{nnfolder} directory is @file{~/fMail/}.
+@lisp
+(maildir :path "/home/user-name/Maildir/"
+         :subdirs ("cur" "new"))
+@end lisp
 
 @lisp
-(setq nnfolder-directory "~/fMail/")
-(setq nnmail-spool-file 'procmail)
-(setq nnmail-procmail-directory "~/incoming/")
-(setq gnus-secondary-select-methods '((nnfolder "")))
-(setq nnmail-procmail-suffix "")
+(maildir :path "/user@@remotehost.org:~/Maildir/"
+         :subdirs ("new"))
 @end lisp
 
+@item imap
+Get mail from a @acronym{IMAP} server.  If you don't want to use
+@acronym{IMAP} as intended, as a network mail reading protocol (ie
+with nnimap), for some reason or other, Gnus let you treat it similar
+to a @acronym{POP} server and fetches articles from a given
+@acronym{IMAP} mailbox.  @xref{IMAP}, for more information.
 
-@node Incorporating Old Mail
-@subsection Incorporating Old Mail
+Note that for the Kerberos, GSSAPI, @acronym{TLS}/@acronym{SSL} and STARTTLS support you
+may need external programs and libraries, @xref{IMAP}.
 
-Most people have lots of old mail stored in various file formats.  If
-you have set up Gnus to read mail using one of the spiffy Gnus mail
-backends, you'll probably wish to have that old mail incorporated into
-your mail groups.
+Keywords:
 
-Doing so can be quite easy.
+@table @code
+@item :server
+The name of the @acronym{IMAP} server.  The default is taken from the
+@env{MAILHOST} environment variable.
 
-To take an example: You're reading mail using @code{nnml}
-(@pxref{Mail Spool}), and have set @code{nnmail-split-methods} to a
-satisfactory value (@pxref{Splitting Mail}).  You have an old Unix mbox
-file filled with important, but old, mail.  You want to move it into
-your @code{nnml} groups.
+@item :port
+The port number of the @acronym{IMAP} server.  The default is @samp{143}, or
+@samp{993} for @acronym{TLS}/@acronym{SSL} connections.
 
-Here's how:
+@item :user
+The user name to give to the @acronym{IMAP} server.  The default is the login
+name.
 
-@enumerate
-@item
-Go to the group buffer.
+@item :password
+The password to give to the @acronym{IMAP} server.  If not specified, the user is
+prompted.
 
-@item 
-Type `G f' and give the path to the mbox file when prompted to create an
-@code{nndoc} group from the mbox file (@pxref{Foreign Groups}).
+@item :stream
+What stream to use for connecting to the server, this is one of the
+symbols in @code{imap-stream-alist}.  Right now, this means
+@samp{gssapi}, @samp{kerberos4}, @samp{starttls}, @samp{tls},
+@samp{ssl}, @samp{shell} or the default @samp{network}.
 
-@item 
-Type `SPACE' to enter the newly created group.
+@item :authentication
+Which authenticator to use for authenticating to the server, this is
+one of the symbols in @code{imap-authenticator-alist}.  Right now,
+this means @samp{gssapi}, @samp{kerberos4}, @samp{digest-md5},
+@samp{cram-md5}, @samp{anonymous} or the default @samp{login}.
 
-@item
-Type `M P b' to process-mark all articles in this group's buffer
-(@pxref{Setting Process Marks}).
+@item :program
+When using the `shell' :stream, the contents of this variable is
+mapped into the @code{imap-shell-program} variable.  This should be a
+@code{format}-like string (or list of strings).  Here's an example:
 
-@item 
-Type `B r' to respool all the process-marked articles, and answer
-@samp{nnml} when prompted (@pxref{Mail Group Commands}).
-@end enumerate
+@example
+ssh %s imapd
+@end example
 
-All the mail messages in the mbox file will now also be spread out over
-all your @code{nnml} groups.  Try entering them and check whether things
-have gone without a glitch.  If things look ok, you may consider
-deleting the mbox file, but I wouldn't do that unless I was absolutely
-sure that all the mail has ended up where it should be.
+The valid format specifier characters are:
 
-Respooling is also a handy thing to do if you're switching from one mail
-backend to another.  Just respool all the mail in the old mail groups
-using the new mail backend.
+@table @samp
+@item s
+The name of the server.
 
+@item l
+User name from @code{imap-default-user}.
 
-@node Expiring Mail
-@subsection Expiring Mail
-@cindex article expiry
+@item p
+The port number of the server.
+@end table
 
-Traditional mail readers have a tendency to remove mail articles when
-you mark them as read, in some way.  Gnus takes a fundamentally
-different approach to mail reading.
+The values used for these specs are taken from the values you give the
+corresponding keywords.
 
-Gnus basically considers mail just to be news that has been received in
-a rather peculiar manner.  It does not think that it has the power to
-actually change the mail, or delete any mail messages.  If you enter a
-mail group, and mark articles as ``read'', or kill them in some other
-fashion, the mail articles will still exist on the system.  I repeat:
-Gnus will not delete your old, read mail.  Unless you ask it to, of
-course.
+@item :mailbox
+The name of the mailbox to get mail from.  The default is @samp{INBOX}
+which normally is the mailbox which receive incoming mail.
 
-To make Gnus get rid of your unwanted mail, you have to mark the
-articles as @dfn{expirable}.  This does not mean that the articles will
-disappear right away, however.  In general, a mail article will be
-deleted from your system if, 1) it is marked as expirable, AND 2) it is
-more than one week old.  If you do not mark an article as expirable, it
-will remain on your system until hell freezes over.  This bears
-repeating one more time, with some spurious capitalizations: IF you do
-NOT mark articles as EXPIRABLE, Gnus will NEVER delete those ARTICLES.
+@item :predicate
+The predicate used to find articles to fetch.  The default, @samp{UNSEEN
+UNDELETED}, is probably the best choice for most people, but if you
+sometimes peek in your mailbox with a @acronym{IMAP} client and mark some
+articles as read (or; SEEN) you might want to set this to @samp{1:*}.
+Then all articles in the mailbox is fetched, no matter what.  For a
+complete list of predicates, see RFC 2060 section 6.4.4.
 
-@vindex gnus-auto-expirable-newsgroups
-You do not have to mark articles as expirable by hand.  Groups that
-match the regular expression @code{gnus-auto-expirable-newsgroups} will
-have all articles that you read marked as expirable automatically.  All
-articles marked as expirable have an @samp{E} in the first
-column in the summary buffer.
+@item :fetchflag
+How to flag fetched articles on the server, the default @samp{\Deleted}
+will mark them as deleted, an alternative would be @samp{\Seen} which
+would simply mark them as read.  These are the two most likely choices,
+but more flags are defined in RFC 2060 section 2.3.2.
 
-By default, if you have auto expiry switched on, Gnus will mark all the
-articles you read as expirable, no matter if they were read or unread
-before.  To avoid having articles marked as read marked as expirable
-automatically, you can put something like the following in your
-@file{.gnus} file:
+@item :dontexpunge
+If non-@code{nil}, don't remove all articles marked as deleted in the
+mailbox after finishing the fetch.
+
+@end table
+
+An example @acronym{IMAP} mail source:
 
-@vindex gnus-mark-article-hook
 @lisp
-(remove-hook 'gnus-mark-article-hook                                
-             'gnus-summary-mark-read-and-unread-as-read)            
-(add-hook 'gnus-mark-article-hook 'gnus-summary-mark-unread-as-read)
+(imap :server "mail.mycorp.com"
+      :stream kerberos4
+      :fetchflag "\\Seen")
 @end lisp
 
-Note that making a group auto-expirable doesn't mean that all read
-articles are expired---only the articles marked as expirable
-will be expired.  Also note that using the @kbd{d} command won't make
-groups expirable---only semi-automatic marking of articles as read will
-mark the articles as expirable in auto-expirable groups.
+@item webmail
+Get mail from a webmail server, such as @uref{http://www.hotmail.com/},
+@uref{http://webmail.netscape.com/}, @uref{http://www.netaddress.com/},
+@uref{http://mail.yahoo.com/}.
 
-Let's say you subscribe to a couple of mailing lists, and you want the
-articles you have read to disappear after a while:
+NOTE: Webmail largely depends on cookies.  A "one-line-cookie" patch is
+required for url "4.0pre.46".
+
+WARNING: Mails may be lost.  NO WARRANTY.
+
+Keywords:
+
+@table @code
+@item :subtype
+The type of the webmail server.  The default is @code{hotmail}.  The
+alternatives are @code{netscape}, @code{netaddress}, @code{my-deja}.
+
+@item :user
+The user name to give to the webmail server.  The default is the login
+name.
+
+@item :password
+The password to give to the webmail server.  If not specified, the user is
+prompted.
+
+@item :dontexpunge
+If non-@code{nil}, only fetch unread articles and don't move them to
+trash folder after finishing the fetch.
+
+@end table
+
+An example webmail source:
 
 @lisp
-(setq gnus-auto-expirable-newsgroups 
-      "mail.nonsense-list\\|mail.nice-list")
+(webmail :subtype 'hotmail
+         :user "user-name"
+         :password "secret")
 @end lisp
+@end table
 
-Another way to have auto-expiry happen is to have the element
-@code{auto-expire} in the group parameters of the group. 
+@table @dfn
+@item Common Keywords
+Common keywords can be used in any type of mail source.
 
-If you use adaptive scoring (@pxref{Adaptive Scoring}) and
-auto-expiring, you'll have problems.  Auto-expiring and adaptive scoring
-don't really mix very well.  
+Keywords:
 
-@vindex nnmail-expiry-wait
-The @code{nnmail-expiry-wait} variable supplies the default time an
-expirable article has to live.  Gnus starts counting days from when the
-message @emph{arrived}, not from when it was sent.  The default is seven
-days.
-
-Gnus also supplies a function that lets you fine-tune how long articles
-are to live, based on what group they are in.  Let's say you want to
-have one month expiry period in the @samp{mail.private} group, a one day
-expiry period in the @samp{mail.junk} group, and a six day expiry period
-everywhere else:
+@table @code
+@item :plugged
+If non-@code{nil}, fetch the mail even when Gnus is unplugged.  If you
+use directory source to get mail, you can specify it as in this
+example:
 
-@vindex nnmail-expiry-wait-function
 @lisp
-(setq nnmail-expiry-wait-function
-      (lambda (group)
-       (cond ((string= group "mail.private")
-               31)
-             ((string= group "mail.junk")
-               1)
-             ((string= group "important")
-               'never)
-             (t
-               6))))
+(setq mail-sources
+      '((directory :path "/home/pavel/.Spool/"
+                   :suffix ""
+                   :plugged t)))
 @end lisp
 
-The group names this function is fed are ``unadorned'' group
-names---no @samp{nnml:} prefixes and the like.
-
-The @code{nnmail-expiry-wait} variable and
-@code{nnmail-expiry-wait-function} function can either be a number (not
-necessarily an integer) or one of the symbols @code{immediate} or
-@code{never}.
+Gnus will then fetch your mail even when you are unplugged.  This is
+useful when you use local mail and news.
 
-You can also use the @code{expiry-wait} group parameter to selectively
-change the expiry period (@pxref{Group Parameters}).
+@end table
+@end table
 
-@vindex nnmail-keep-last-article
-If @code{nnmail-keep-last-article} is non-@code{nil}, Gnus will never
-expire the final article in a mail newsgroup.  This is to make life
-easier for procmail users.
+@subsubsection Function Interface
 
-@vindex gnus-total-expirable-newsgroups
-By the way: That line up there, about Gnus never expiring non-expirable
-articles, is a lie.  If you put @code{total-expire} in the group
-parameters, articles will not be marked as expirable, but all read
-articles will be put through the expiry process.  Use with extreme
-caution.  Even more dangerous is the
-@code{gnus-total-expirable-newsgroups} variable.  All groups that match
-this regexp will have all read articles put through the expiry process,
-which means that @emph{all} old mail articles in the groups in question
-will be deleted after a while.  Use with extreme caution, and don't come
-crying to me when you discover that the regexp you used matched the
-wrong group and all your important mail has disappeared.  Be a
-@emph{man}!  Or a @emph{woman}!  Whatever you feel more comfortable
-with!  So there!
+Some of the above keywords specify a Lisp function to be executed.
+For each keyword @code{:foo}, the Lisp variable @code{foo} is bound to
+the value of the keyword while the function is executing.  For example,
+consider the following mail-source setting:
 
-Most people make most of their mail groups total-expirable, though. 
+@lisp
+(setq mail-sources '((pop :user "jrl"
+                          :server "pophost" :function fetchfunc)))
+@end lisp
 
+While the function @code{fetchfunc} is executing, the symbol @code{user}
+is bound to @code{"jrl"}, and the symbol @code{server} is bound to
+@code{"pophost"}.  The symbols @code{port}, @code{password},
+@code{program}, @code{prescript}, @code{postscript}, @code{function},
+and @code{authentication} are also bound (to their default values).
 
-@node Washing Mail
-@subsection Washing Mail
-@cindex mail washing
-@cindex list server brain damage
-@cindex incoming mail treatment
+See above for a list of keywords for each type of mail source.
 
-Mailers and list servers are notorious for doing all sorts of really,
-really stupid things with mail.  ``Hey, RFC822 doesn't explicitly
-prohibit us from adding the string @code{wE aRe ElItE!!!!!1!!} to the
-end of all lines passing through our server, so let's do that!!!!1!''
-Yes, but RFC822 wasn't designed to be read by morons.  Things that were
-considered to be self-evident were not discussed.  So.  Here we are.
 
-Case in point:  The German version of Microsoft Exchange adds @samp{AW:
-} to the subjects of replies instead of @samp{Re: }.  I could pretend to
-be shocked and dismayed by this, but I haven't got the energy.  It is to
-laugh.
+@node Mail Source Customization
+@subsubsection Mail Source Customization
 
-Gnus provides a plethora of functions for washing articles while
-displaying them, but it might be nicer to do the filtering before
-storing the mail to disc.  For that purpose, we have three hooks and
-various functions that can be put in these hooks.
+The following is a list of variables that influence how the mail is
+fetched.  You would normally not need to set or change any of these
+variables.
 
 @table @code
-@item nnmail-prepare-incoming-hook
-@vindex nnmail-prepare-incoming-hook
-This hook is called before doing anything with the mail and is meant for
-grand, sweeping gestures.  Functions to be used include:
+@item mail-source-crash-box
+@vindex mail-source-crash-box
+File where mail will be stored while processing it.  The default is@*
+@file{~/.emacs-mail-crash-box}.
+
+@item mail-source-delete-incoming
+@vindex mail-source-delete-incoming
+If non-@code{nil}, delete incoming files after handling them.  If
+@code{t}, delete the files immediately, if @code{nil}, never delete any
+files.  If a positive number, delete files older than number of days
+(This will only happen, when receiving new mail).  You may also set
+@code{mail-source-delete-incoming} to @code{nil} and call
+@code{mail-source-delete-old-incoming} from a hook or interactively.
+
+@item mail-source-delete-old-incoming-confirm
+@vindex mail-source-delete-old-incoming-confirm
+If non-@code{nil}, ask for for confirmation before deleting old incoming
+files.  This variable only applies when
+@code{mail-source-delete-incoming} is a positive number.
+
+@item mail-source-ignore-errors
+@vindex mail-source-ignore-errors
+If non-@code{nil}, ignore errors when reading mail from a mail source.
+
+@item mail-source-directory
+@vindex mail-source-directory
+Directory where files (if any) will be stored.  The default is
+@file{~/Mail/}.  At present, the only thing this is used for is to say
+where the incoming files will be stored if the previous variable is
+@code{nil}.
 
-@table @code
-@item nnheader-ms-strip-cr
-@findex nnheader-ms-strip-cr
-Remove trailing carriage returns from each line.  This is default on
-Emacs running on MS machines.
+@item mail-source-incoming-file-prefix
+@vindex mail-source-incoming-file-prefix
+Prefix for file name for storing incoming mail.  The default is
+@file{Incoming}, in which case files will end up with names like
+@file{Incoming30630D_} or @file{Incoming298602ZD}.  This is really only
+relevant if @code{mail-source-delete-incoming} is @code{nil}.
+
+@item mail-source-default-file-modes
+@vindex mail-source-default-file-modes
+All new mail files will get this file mode.  The default is 384.
+
+@item mail-source-movemail-program
+@vindex mail-source-movemail-program
+If non-@code{nil}, name of program for fetching new mail.  If
+@code{nil}, @code{movemail} in @var{exec-directory}.
 
 @end table
 
-@item nnmail-prepare-incoming-header-hook
-@vindex nnmail-prepare-incoming-header-hook
-This hook is called narrowed to each header.  It can be used when
-cleaning up the headers.  Functions that can be used include:
 
-@table @code
-@item nnmail-remove-leading-whitespace
-@findex nnmail-remove-leading-whitespace
-Clear leading white space that ``helpful'' listservs have added to the
-headers to make them look nice.  Aaah.  
+@node Fetching Mail
+@subsubsection Fetching Mail
 
-@item nnmail-remove-list-identifiers
-@findex nnmail-remove-list-identifiers
-Some list servers add an identifier---for example, @samp{(idm)}---to the
-beginning of all @code{Subject} headers.  I'm sure that's nice for
-people who use stone age mail readers.  This function will remove
-strings that match the @code{nnmail-list-identifiers} regexp, which can
-also be a list of regexp.
+@vindex mail-sources
+@vindex nnmail-spool-file
+The way to actually tell Gnus where to get new mail from is to set
+@code{mail-sources} to a list of mail source specifiers
+(@pxref{Mail Source Specifiers}).
 
-For instance, if you want to remove the @samp{(idm)} and the
-@samp{nagnagnag} identifiers:
+If this variable (and the obsolescent @code{nnmail-spool-file}) is
+@code{nil}, the mail back ends will never attempt to fetch mail by
+themselves.
+
+If you want to fetch mail both from your local spool as well as a
+@acronym{POP} mail server, you'd say something like:
 
 @lisp
-(setq nnmail-list-identifiers
-      '("(idm)" "nagnagnag"))
+(setq mail-sources
+      '((file)
+        (pop :server "pop3.mail.server"
+             :password "secret")))
 @end lisp
 
-@item nnmail-remove-tabs
-@findex nnmail-remove-tabs
-Translate all @samp{TAB} characters into @samp{SPACE} characters. 
+Or, if you don't want to use any of the keyword defaults:
 
-@end table
+@lisp
+(setq mail-sources
+      '((file :path "/var/spool/mail/user-name")
+        (pop :server "pop3.mail.server"
+             :user "user-name"
+             :port "pop3"
+             :password "secret")))
+@end lisp
 
-@item nnmail-prepare-incoming-message-hook
-@vindex nnmail-prepare-incoming-message-hook
-This hook is called narrowed to each message.  Functions to be used
-include: 
 
-@table @code
-@item article-de-quoted-unreadable
-@findex article-de-quoted-unreadable
-Decode Quoted Readable encoding.
+When you use a mail back end, Gnus will slurp all your mail from your
+inbox and plonk it down in your home directory.  Gnus doesn't move any
+mail if you're not using a mail back end---you have to do a lot of magic
+invocations first.  At the time when you have finished drawing the
+pentagram, lightened the candles, and sacrificed the goat, you really
+shouldn't be too surprised when Gnus moves your mail.
 
-@end table
-@end table
 
 
-@node Duplicates
-@subsection Duplicates
+@node Mail Back End Variables
+@subsection Mail Back End Variables
 
-@vindex nnmail-treat-duplicates
-@vindex nnmail-message-id-cache-length
-@vindex nnmail-message-id-cache-file
-@cindex duplicate mails
-If you are a member of a couple of mailing lists, you will sometimes
-receive two copies of the same mail.  This can be quite annoying, so
-@code{nnmail} checks for and treats any duplicates it might find.  To do
-this, it keeps a cache of old @code{Message-ID}s---
-@code{nnmail-message-id-cache-file}, which is @file{~/.nnmail-cache} by
-default.  The approximate maximum number of @code{Message-ID}s stored
-there is controlled by the @code{nnmail-message-id-cache-length}
-variable, which is 1000 by default. (So 1000 @code{Message-ID}s will be
-stored.) If all this sounds scary to you, you can set
-@code{nnmail-treat-duplicates} to @code{warn} (which is what it is by
-default), and @code{nnmail} won't delete duplicate mails.  Instead it
-will insert a warning into the head of the mail saying that it thinks
-that this is a duplicate of a different message.
+These variables are (for the most part) pertinent to all the various
+mail back ends.
 
-This variable can also be a function.  If that's the case, the function
-will be called from a buffer narrowed to the message in question with
-the @code{Message-ID} as a parameter.  The function must return either
-@code{nil}, @code{warn}, or @code{delete}.
+@table @code
+@vindex nnmail-read-incoming-hook
+@item nnmail-read-incoming-hook
+The mail back ends all call this hook after reading new mail.  You can
+use this hook to notify any mail watch programs, if you want to.
 
-You can turn this feature off completely by setting the variable to
-@code{nil}.
+@vindex nnmail-split-hook
+@item nnmail-split-hook
+@findex gnus-article-decode-encoded-words
+@cindex RFC 1522 decoding
+@cindex RFC 2047 decoding
+Hook run in the buffer where the mail headers of each message is kept
+just before the splitting based on these headers is done.  The hook is
+free to modify the buffer contents in any way it sees fit---the buffer
+is discarded after the splitting has been done, and no changes performed
+in the buffer will show up in any files.
+@code{gnus-article-decode-encoded-words} is one likely function to add
+to this hook.
 
-If you want all the duplicate mails to be put into a special
-@dfn{duplicates} group, you could do that using the normal mail split
-methods:
+@vindex nnmail-pre-get-new-mail-hook
+@vindex nnmail-post-get-new-mail-hook
+@item nnmail-pre-get-new-mail-hook
+@itemx nnmail-post-get-new-mail-hook
+These are two useful hooks executed when treating new incoming
+mail---@code{nnmail-pre-get-new-mail-hook} (is called just before
+starting to handle the new mail) and
+@code{nnmail-post-get-new-mail-hook} (is called when the mail handling
+is done).  Here's and example of using these two hooks to change the
+default file modes the new mail files get:
 
 @lisp
-(setq nnmail-split-fancy
-      '(| ;; Messages duplicates go to a separate group.
-          ("gnus-warning" "duplication of message" "duplicate")
-          ;; Message from daemons, postmaster, and the like to another.
-          (any mail "mail.misc")
-          ;; Other rules.
-          [ ... ] ))
-@end lisp
+(add-hook 'nnmail-pre-get-new-mail-hook
+          (lambda () (set-default-file-modes 511)))
 
-Or something like:
-@lisp
-(setq nnmail-split-methods 
-      '(("duplicates" "^Gnus-Warning:")
-        ;; Other rules.
-        [...]))
+(add-hook 'nnmail-post-get-new-mail-hook
+          (lambda () (set-default-file-modes 551)))
 @end lisp
 
-Here's a neat feature: If you know that the recipient reads her mail
-with Gnus, and that she has @code{nnmail-treat-duplicates} set to
-@code{delete}, you can send her as many insults as you like, just by
-using a @code{Message-ID} of a mail that you know that she's already
-received.  Think of all the fun!  She'll never see any of it!  Whee!
+@item nnmail-use-long-file-names
+@vindex nnmail-use-long-file-names
+If non-@code{nil}, the mail back ends will use long file and directory
+names.  Groups like @samp{mail.misc} will end up in directories
+(assuming use of @code{nnml} back end) or files (assuming use of
+@code{nnfolder} back end) like @file{mail.misc}.  If it is @code{nil},
+the same group will end up in @file{mail/misc}.
 
+@item nnmail-delete-file-function
+@vindex nnmail-delete-file-function
+@findex delete-file
+Function called to delete files.  It is @code{delete-file} by default.
 
-@node Not Reading Mail
-@subsection Not Reading Mail
+@item nnmail-cache-accepted-message-ids
+@vindex nnmail-cache-accepted-message-ids
+If non-@code{nil}, put the @code{Message-ID}s of articles imported into
+the back end (via @code{Gcc}, for instance) into the mail duplication
+discovery cache.  The default is @code{nil}.
 
-If you start using any of the mail backends, they have the annoying
-habit of assuming that you want to read mail with them.  This might not
-be unreasonable, but it might not be what you want.
+@item nnmail-cache-ignore-groups
+@vindex nnmail-cache-ignore-groups
+This can be a regular expression or a list of regular expressions.
+Group names that match any of the regular expressions will never be
+recorded in the @code{Message-ID} cache.
 
-If you set @code{nnmail-spool-file} to @code{nil}, none of the backends
-will ever attempt to read incoming mail, which should help.
+This can be useful, for example, when using Fancy Splitting
+(@pxref{Fancy Mail Splitting}) together with the function
+@code{nnmail-split-fancy-with-parent}.
 
-@vindex nnbabyl-get-new-mail
-@vindex nnmbox-get-new-mail
-@vindex nnml-get-new-mail
-@vindex nnmh-get-new-mail
-@vindex nnfolder-get-new-mail
-This might be too much, if, for instance, you are reading mail quite
-happily with @code{nnml} and just want to peek at some old @sc{rmail}
-file you have stashed away with @code{nnbabyl}.  All backends have
-variables called backend-@code{get-new-mail}.  If you want to disable
-the @code{nnbabyl} mail reading, you edit the virtual server for the
-group to have a setting where @code{nnbabyl-get-new-mail} to @code{nil}.
+@end table
 
-All the mail backends will call @code{nn}*@code{-prepare-save-mail-hook}
-narrowed to the article to be saved before saving it when reading
-incoming mail.
 
+@node Fancy Mail Splitting
+@subsection Fancy Mail Splitting
+@cindex mail splitting
+@cindex fancy mail splitting
 
-@node Choosing a Mail Backend
-@subsection Choosing a Mail Backend
+@vindex nnmail-split-fancy
+@findex nnmail-split-fancy
+If the rather simple, standard method for specifying how to split mail
+doesn't allow you to do what you want, you can set
+@code{nnmail-split-methods} to @code{nnmail-split-fancy}.  Then you can
+play with the @code{nnmail-split-fancy} variable.
 
-Gnus will read the mail spool when you activate a mail group.  The mail
-file is first copied to your home directory.  What happens after that
-depends on what format you want to store your mail in.
+Let's look at an example value of this variable first:
 
-@menu
-* Unix Mail Box::               Using the (quite) standard Un*x mbox.
-* Rmail Babyl::                 Emacs programs use the rmail babyl format.
-* Mail Spool::                  Store your mail in a private spool?
-* MH Spool::                    An mhspool-like backend.
-* Mail Folders::                Having one file for each group.
-@end menu
+@lisp
+;; @r{Messages from the mailer daemon are not crossposted to any of}
+;; @r{the ordinary groups.  Warnings are put in a separate group}
+;; @r{from real errors.}
+(| ("from" mail (| ("subject" "warn.*" "mail.warning")
+                   "mail.misc"))
+   ;; @r{Non-error messages are crossposted to all relevant}
+   ;; @r{groups, but we don't crosspost between the group for the}
+   ;; @r{(ding) list and the group for other (ding) related mail.}
+   (& (| (any "ding@@ifi\\.uio\\.no" "ding.list")
+         ("subject" "ding" "ding.misc"))
+      ;; @r{Other mailing lists@dots{}}
+      (any "procmail@@informatik\\.rwth-aachen\\.de" "procmail.list")
+      (any "SmartList@@informatik\\.rwth-aachen\\.de" "SmartList.list")
+      ;; @r{Both lists below have the same suffix, so prevent}
+      ;; @r{cross-posting to mkpkg.list of messages posted only to}
+      ;; @r{the bugs- list, but allow cross-posting when the}
+      ;; @r{message was really cross-posted.}
+      (any "bugs-mypackage@@somewhere" "mypkg.bugs")
+      (any "mypackage@@somewhere\" - "bugs-mypackage" "mypkg.list")
+      ;; @r{People@dots{}}
+      (any "larsi@@ifi\\.uio\\.no" "people.Lars_Magne_Ingebrigtsen"))
+   ;; @r{Unmatched mail goes to the catch all group.}
+   "misc.misc")
+@end lisp
 
+This variable has the format of a @dfn{split}.  A split is a
+(possibly) recursive structure where each split may contain other
+splits.  Here are the possible split syntaxes:
 
-@node Unix Mail Box
-@subsubsection Unix Mail Box
-@cindex nnmbox
-@cindex unix mail box
+@table @code
 
-@vindex nnmbox-active-file
-@vindex nnmbox-mbox-file
-The @dfn{nnmbox} backend will use the standard Un*x mbox file to store
-mail.  @code{nnmbox} will add extra headers to each mail article to say
-which group it belongs in.
+@item group 
+If the split is a string, that will be taken as a group name.  Normal
+regexp match expansion will be done.  See below for examples.
+
+@item (@var{field} @var{value} [- @var{restrict} [@dots{}] ] @var{split})
+If the split is a list, the first element of which is a string, then
+store the message as specified by @var{split}, if header @var{field}
+(a regexp) contains @var{value} (also a regexp).  If @var{restrict}
+(yet another regexp) matches some string after @var{field} and before
+the end of the matched @var{value}, the @var{split} is ignored.  If
+none of the @var{restrict} clauses match, @var{split} is processed.
+
+@item (| @var{split} @dots{})
+If the split is a list, and the first element is @code{|} (vertical
+bar), then process each @var{split} until one of them matches.  A
+@var{split} is said to match if it will cause the mail message to be
+stored in one or more groups.
+
+@item (& @var{split} @dots{})
+If the split is a list, and the first element is @code{&}, then
+process all @var{split}s in the list.
+
+@item junk
+If the split is the symbol @code{junk}, then don't save (i.e., delete)
+this message.  Use with extreme caution.
+
+@item (: @var{function} @var{arg1} @var{arg2} @dots{})
+If the split is a list, and the first element is @samp{:}, then the
+second element will be called as a function with @var{args} given as
+arguments.  The function should return a @var{split}.
+
+@cindex body split
+For instance, the following function could be used to split based on the
+body of the messages:
 
-Virtual server settings:
+@lisp
+(defun split-on-body ()
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char (point-min))
+      (when (re-search-forward "Some.*string" nil t)
+        "string.group"))))
+@end lisp
 
-@table @code
-@item nnmbox-mbox-file
-@vindex nnmbox-mbox-file
-The name of the mail box in the user's home directory. 
+The buffer is narrowed to the message in question when @var{function}
+is run.  That's why @code{(widen)} needs to be called after
+@code{save-excursion} and @code{save-restriction} in the example
+above.  Also note that with the nnimap backend, message bodies will
+not be downloaded by default.  You need to set
+@code{nnimap-split-download-body} to t to do that (@pxref{Splitting in
+IMAP}).
 
-@item nnmbox-active-file
-@vindex nnmbox-active-file
-The name of the active file for the mail box.
-
-@item nnmbox-get-new-mail
-@vindex nnmbox-get-new-mail
-If non-@code{nil}, @code{nnmbox} will read incoming mail and split it
-into groups.
-@end table
+@item (! @var{func} @var{split})
+If the split is a list, and the first element is @code{!}, then
+@var{split} will be processed, and @var{func} will be called as a
+function with the result of @var{split} as argument.  @var{func}
+should return a split.
 
+@item nil
+If the split is @code{nil}, it is ignored.
 
-@node Rmail Babyl
-@subsubsection Rmail Babyl
-@cindex nnbabyl
-@cindex rmail mbox
+@end table
 
-@vindex nnbabyl-active-file
-@vindex nnbabyl-mbox-file
-The @dfn{nnbabyl} backend will use a babyl mail box (aka. @dfn{rmail
-mbox}) to store mail. @code{nnbabyl} will add extra headers to each mail
-article to say which group it belongs in.
+In these splits, @var{field} must match a complete field name.
+@var{value} must match a complete word according to the fundamental mode
+syntax table.  You can use @code{.*} in the regexps to match partial
+field names or words.  In other words, all @var{value}'s are wrapped in
+@samp{\<} and @samp{\>} pairs.
 
-Virtual server settings:
+@vindex nnmail-split-abbrev-alist
+@var{field} and @var{value} can also be Lisp symbols, in that case
+they are expanded as specified by the variable
+@code{nnmail-split-abbrev-alist}.  This is an alist of cons cells,
+where the @sc{car} of a cell contains the key, and the @sc{cdr}
+contains the associated value.  Predefined entries in
+@code{nnmail-split-abbrev-alist} include:
 
 @table @code
-@item nnbabyl-mbox-file
-@vindex nnbabyl-mbox-file
-The name of the rmail mbox file.
-
-@item nnbabyl-active-file
-@vindex nnbabyl-active-file
-The name of the active file for the rmail box.
-
-@item nnbabyl-get-new-mail
-@vindex nnbabyl-get-new-mail
-If non-@code{nil}, @code{nnbabyl} will read incoming mail. 
+@item from
+Matches the @samp{From}, @samp{Sender} and @samp{Resent-From} fields.
+@item to
+Matches the @samp{To}, @samp{Cc}, @samp{Apparently-To},
+@samp{Resent-To} and @samp{Resent-Cc} fields.
+@item any
+Is the union of the @code{from} and @code{to} entries.
 @end table
 
+@vindex nnmail-split-fancy-syntax-table
+@code{nnmail-split-fancy-syntax-table} is the syntax table in effect
+when all this splitting is performed.
 
-@node Mail Spool
-@subsubsection Mail Spool
-@cindex nnml
-@cindex mail @sc{nov} spool
-
-The @dfn{nnml} spool mail format isn't compatible with any other known
-format.  It should be used with some caution.
+If you want to have Gnus create groups dynamically based on some
+information in the headers (i.e., do @code{replace-match}-like
+substitutions in the group names), you can say things like:
 
-@vindex nnml-directory
-If you use this backend, Gnus will split all incoming mail into files,
-one file for each mail, and put the articles into the corresponding
-directories under the directory specified by the @code{nnml-directory}
-variable.  The default value is @file{~/Mail/}.
+@example
+(any "debian-\\b\\(\\w+\\)@@lists.debian.org" "mail.debian.\\1")
+@end example
 
-You do not have to create any directories beforehand; Gnus will take
-care of all that.
+In this example, messages sent to @samp{debian-foo@@lists.debian.org}
+will be filed in @samp{mail.debian.foo}.
 
-If you have a strict limit as to how many files you are allowed to store
-in your account, you should not use this backend.  As each mail gets its
-own file, you might very well occupy thousands of inodes within a few
-weeks.  If this is no problem for you, and it isn't a problem for you
-having your friendly systems administrator walking around, madly,
-shouting ``Who is eating all my inodes?! Who? Who!?!'', then you should
-know that this is probably the fastest format to use.  You do not have
-to trudge through a big mbox file just to read your new mail.
+If the string contains the element @samp{\&}, then the previously
+matched string will be substituted.  Similarly, the elements @samp{\\1}
+up to @samp{\\9} will be substituted with the text matched by the
+groupings 1 through 9.
 
-@code{nnml} is probably the slowest backend when it comes to article
-splitting.  It has to create lots of files, and it also generates
-@sc{nov} databases for the incoming mails.  This makes it the fastest
-backend when it comes to reading mail.
+@vindex nnmail-split-fancy-match-partial-words
+@code{nnmail-split-fancy-match-partial-words} controls whether partial
+words are matched during fancy splitting.
 
-Virtual server settings:
+Normally, regular expressions given in @code{nnmail-split-fancy} are
+implicitly surrounded by @code{\<...\>} markers, which are word
+delimiters.  If this variable is true, they are not implicitly
+surrounded by anything.
 
-@table @code
-@item nnml-directory
-@vindex nnml-directory
-All @code{nnml} directories will be placed under this directory. 
+@example
+(any "joe" "joemail")
+@end example
 
-@item nnml-active-file
-@vindex nnml-active-file
-The active file for the @code{nnml} server.
+In this example, messages sent from @samp{joedavis@@foo.org} will
+normally not be filed in @samp{joemail}.  With
+@code{nnmail-split-fancy-match-partial-words} set to t, however, the
+match will happen.  In effect, the requirement of a word boundary is
+removed and instead the match becomes more like a grep.
+
+@findex nnmail-split-fancy-with-parent
+@code{nnmail-split-fancy-with-parent} is a function which allows you to
+split followups into the same groups their parents are in.  Sometimes
+you can't make splitting rules for all your mail.  For example, your
+boss might send you personal mail regarding different projects you are
+working on, and as you can't tell your boss to put a distinguishing
+string into the subject line, you have to resort to manually moving the
+messages into the right group.  With this function, you only have to do
+it once per thread.
+
+To use this feature, you have to set @code{nnmail-treat-duplicates}
+and @code{nnmail-cache-accepted-message-ids} to a non-@code{nil}
+value.  And then you can include @code{nnmail-split-fancy-with-parent}
+using the colon feature, like so:
+@lisp
+(setq nnmail-treat-duplicates 'warn     ; @r{or @code{delete}}
+      nnmail-cache-accepted-message-ids t
+      nnmail-split-fancy
+      '(| (: nnmail-split-fancy-with-parent)
+          ;; @r{other splits go here}
+        ))
+@end lisp
 
-@item nnml-newsgroups-file
-@vindex nnml-newsgroups-file
-The @code{nnml} group descriptions file.  @xref{Newsgroups File
-Format}. 
+This feature works as follows: when @code{nnmail-treat-duplicates} is
+non-@code{nil}, Gnus records the message id of every message it sees
+in the file specified by the variable
+@code{nnmail-message-id-cache-file}, together with the group it is in
+(the group is omitted for non-mail messages).  When mail splitting is
+invoked, the function @code{nnmail-split-fancy-with-parent} then looks
+at the References (and In-Reply-To) header of each message to split
+and searches the file specified by @code{nnmail-message-id-cache-file}
+for the message ids.  When it has found a parent, it returns the
+corresponding group name unless the group name matches the regexp
+@code{nnmail-split-fancy-with-parent-ignore-groups}.  It is
+recommended that you set @code{nnmail-message-id-cache-length} to a
+somewhat higher number than the default so that the message ids are
+still in the cache.  (A value of 5000 appears to create a file some
+300 kBytes in size.)
+@vindex nnmail-cache-accepted-message-ids
+When @code{nnmail-cache-accepted-message-ids} is non-@code{nil}, Gnus
+also records the message ids of moved articles, so that the followup
+messages goes into the new group.
 
-@item nnml-get-new-mail
-@vindex nnml-get-new-mail
-If non-@code{nil}, @code{nnml} will read incoming mail.
+Also see the variable @code{nnmail-cache-ignore-groups} if you don't
+want certain groups to be recorded in the cache.  For example, if all
+outgoing messages are written to an ``outgoing'' group, you could set
+@code{nnmail-cache-ignore-groups} to match that group name.
+Otherwise, answers to all your messages would end up in the
+``outgoing'' group.
 
-@item nnml-nov-is-evil
-@vindex nnml-nov-is-evil
-If non-@code{nil}, this backend will ignore any @sc{nov} files.  
 
-@item nnml-nov-file-name
-@vindex nnml-nov-file-name
-The name of the @sc{nov} files.  The default is @file{.overview}. 
+@node Group Mail Splitting
+@subsection Group Mail Splitting
+@cindex mail splitting
+@cindex group mail splitting
+
+@findex gnus-group-split
+If you subscribe to dozens of mailing lists but you don't want to
+maintain mail splitting rules manually, group mail splitting is for you.
+You just have to set @code{to-list} and/or @code{to-address} in group
+parameters or group customization and set @code{nnmail-split-methods} to
+@code{gnus-group-split}.  This splitting function will scan all groups
+for those parameters and split mail accordingly, i.e., messages posted
+from or to the addresses specified in the parameters @code{to-list} or
+@code{to-address} of a mail group will be stored in that group.
+
+Sometimes, mailing lists have multiple addresses, and you may want mail
+splitting to recognize them all: just set the @code{extra-aliases} group
+parameter to the list of additional addresses and it's done.  If you'd
+rather use a regular expression, set @code{split-regexp}.
+
+All these parameters in a group will be used to create an
+@code{nnmail-split-fancy} split, in which the @var{field} is @samp{any},
+the @var{value} is a single regular expression that matches
+@code{to-list}, @code{to-address}, all of @code{extra-aliases} and all
+matches of @code{split-regexp}, and the @var{split} is the name of the
+group.  @var{restrict}s are also supported: just set the
+@code{split-exclude} parameter to a list of regular expressions.
+
+If you can't get the right split to be generated using all these
+parameters, or you just need something fancier, you can set the
+parameter @code{split-spec} to an @code{nnmail-split-fancy} split.  In
+this case, all other aforementioned parameters will be ignored by
+@code{gnus-group-split}.  In particular, @code{split-spec} may be set to
+@code{nil}, in which case the group will be ignored by
+@code{gnus-group-split}.
+
+@vindex gnus-group-split-default-catch-all-group
+@code{gnus-group-split} will do cross-posting on all groups that match,
+by defining a single @code{&} fancy split containing one split for each
+group.  If a message doesn't match any split, it will be stored in the
+group named in @code{gnus-group-split-default-catch-all-group}, unless
+some group has @code{split-spec} set to @code{catch-all}, in which case
+that group is used as the catch-all group.  Even though this variable is
+often used just to name a group, it may also be set to an arbitrarily
+complex fancy split (after all, a group name is a fancy split), and this
+may be useful to split mail that doesn't go to any mailing list to
+personal mail folders.  Note that this fancy split is added as the last
+element of a @code{|} split list that also contains a @code{&} split
+with the rules extracted from group parameters.
+
+It's time for an example.  Assume the following group parameters have
+been defined:
 
-@item nnml-prepare-save-mail-hook
-@vindex nnml-prepare-save-mail-hook
-Hook run narrowed to an article before saving.
+@example
+nnml:mail.bar:
+((to-address . "bar@@femail.com")
+ (split-regexp . ".*@@femail\\.com"))
+nnml:mail.foo:
+((to-list . "foo@@nowhere.gov")
+ (extra-aliases "foo@@localhost" "foo-redist@@home")
+ (split-exclude "bugs-foo" "rambling-foo")
+ (admin-address . "foo-request@@nowhere.gov"))
+nnml:mail.others:
+((split-spec . catch-all))
+@end example
 
-@end table
+Setting @code{nnmail-split-methods} to @code{gnus-group-split} will
+behave as if @code{nnmail-split-fancy} had been selected and variable
+@code{nnmail-split-fancy} had been set as follows:
 
-@findex nnml-generate-nov-databases
-If your @code{nnml} groups and @sc{nov} files get totally out of whack,
-you can do a complete update by typing @kbd{M-x
-nnml-generate-nov-databases}.  This command will trawl through the
-entire @code{nnml} hierarchy, looking at each and every article, so it
-might take a while to complete.  A better interface to this
-functionality can be found in the server buffer (@pxref{Server
-Commands}). 
+@lisp
+(| (& (any "\\(bar@@femail\\.com\\|.*@@femail\\.com\\)" "mail.bar")
+      (any "\\(foo@@nowhere\\.gov\\|foo@@localhost\\|foo-redist@@home\\)"
+           - "bugs-foo" - "rambling-foo" "mail.foo"))
+   "mail.others")
+@end lisp
 
+@findex gnus-group-split-fancy
+If you'd rather not use group splitting for all your mail groups, you
+may use it for only some of them, by using @code{nnmail-split-fancy}
+splits like this:
 
-@node MH Spool
-@subsubsection MH Spool
-@cindex nnmh
-@cindex mh-e mail spool
+@lisp
+(: gnus-group-split-fancy @var{groups} @var{no-crosspost} @var{catch-all})
+@end lisp
 
-@code{nnmh} is just like @code{nnml}, except that is doesn't generate
-@sc{nov} databases and it doesn't keep an active file.  This makes
-@code{nnmh} a @emph{much} slower backend than @code{nnml}, but it also
-makes it easier to write procmail scripts for.
+@var{groups} may be a regular expression or a list of group names whose
+parameters will be scanned to generate the output split.
+@var{no-crosspost} can be used to disable cross-posting; in this case, a
+single @code{|} split will be output.  @var{catch-all} is the fall back
+fancy split, used like @code{gnus-group-split-default-catch-all-group}.
+If @var{catch-all} is @code{nil}, or if @code{split-regexp} matches the
+empty string in any selected group, no catch-all split will be issued.
+Otherwise, if some group has @code{split-spec} set to @code{catch-all},
+this group will override the value of the @var{catch-all} argument.
+
+@findex gnus-group-split-setup
+Unfortunately, scanning all groups and their parameters can be quite
+slow, especially considering that it has to be done for every message.
+But don't despair!  The function @code{gnus-group-split-setup} can be
+used to enable @code{gnus-group-split} in a much more efficient way.  It
+sets @code{nnmail-split-methods} to @code{nnmail-split-fancy} and sets
+@code{nnmail-split-fancy} to the split produced by
+@code{gnus-group-split-fancy}.  Thus, the group parameters are only
+scanned once, no matter how many messages are split.
+
+@findex gnus-group-split-update
+However, if you change group parameters, you'd have to update
+@code{nnmail-split-fancy} manually.  You can do it by running
+@code{gnus-group-split-update}.  If you'd rather have it updated
+automatically, just tell @code{gnus-group-split-setup} to do it for
+you.  For example, add to your @file{~/.gnus.el}:
 
-Virtual server settings:
+@lisp
+(gnus-group-split-setup @var{auto-update} @var{catch-all})
+@end lisp
 
-@table @code
-@item nnmh-directory
-@vindex nnmh-directory
-All @code{nnmh} directories will be located under this directory.
+If @var{auto-update} is non-@code{nil}, @code{gnus-group-split-update}
+will be added to @code{nnmail-pre-get-new-mail-hook}, so you won't ever
+have to worry about updating @code{nnmail-split-fancy} again.  If you
+don't omit @var{catch-all} (it's optional, equivalent to @code{nil}),
+@code{gnus-group-split-default-catch-all-group} will be set to its
+value.
 
-@item nnmh-get-new-mail
-@vindex nnmh-get-new-mail
-If non-@code{nil}, @code{nnmh} will read incoming mail.
+@vindex gnus-group-split-updated-hook
+Because you may want to change @code{nnmail-split-fancy} after it is set
+by @code{gnus-group-split-update}, this function will run
+@code{gnus-group-split-updated-hook} just before finishing.
 
-@item nnmh-be-safe
-@vindex nnmh-be-safe
-If non-@code{nil}, @code{nnmh} will go to ridiculous lengths to make
-sure that the articles in the folder are actually what Gnus thinks they
-are.  It will check date stamps and stat everything in sight, so
-setting this to @code{t} will mean a serious slow-down.  If you never
-use anything but Gnus to read the @code{nnmh} articles, you do not have
-to set this variable to @code{t}.
-@end table
+@node Incorporating Old Mail
+@subsection Incorporating Old Mail
+@cindex incorporating old mail
+@cindex import old mail
 
+Most people have lots of old mail stored in various file formats.  If
+you have set up Gnus to read mail using one of the spiffy Gnus mail
+back ends, you'll probably wish to have that old mail incorporated into
+your mail groups.
 
-@node Mail Folders
-@subsubsection Mail Folders
-@cindex nnfolder
-@cindex mbox folders
-@cindex mail folders
+Doing so can be quite easy.
 
-@code{nnfolder} is a backend for storing each mail group in a separate
-file.  Each file is in the standard Un*x mbox format.  @code{nnfolder}
-will add extra headers to keep track of article numbers and arrival
-dates.
+To take an example: You're reading mail using @code{nnml}
+(@pxref{Mail Spool}), and have set @code{nnmail-split-methods} to a
+satisfactory value (@pxref{Splitting Mail}).  You have an old Unix mbox
+file filled with important, but old, mail.  You want to move it into
+your @code{nnml} groups.
 
-Virtual server settings:
+Here's how:
 
-@table @code
-@item nnfolder-directory
-@vindex nnfolder-directory
-All the @code{nnfolder} mail boxes will be stored under this directory. 
+@enumerate
+@item
+Go to the group buffer.
 
-@item nnfolder-active-file
-@vindex nnfolder-active-file
-The name of the active file.
+@item
+Type @kbd{G f} and give the file name to the mbox file when prompted to create an
+@code{nndoc} group from the mbox file (@pxref{Foreign Groups}).
 
-@item nnfolder-newsgroups-file
-@vindex nnfolder-newsgroups-file
-The name of the group descriptions file.  @xref{Newsgroups File Format}.
+@item
+Type @kbd{SPACE} to enter the newly created group.
 
-@item nnfolder-get-new-mail
-@vindex nnfolder-get-new-mail
-If non-@code{nil}, @code{nnfolder} will read incoming mail.
-@end table
+@item
+Type @kbd{M P b} to process-mark all articles in this group's buffer
+(@pxref{Setting Process Marks}).
 
-@findex nnfolder-generate-active-file
-@kindex M-x nnfolder-generate-active-file
-If you have lots of @code{nnfolder}-like files you'd like to read with
-@code{nnfolder}, you can use the @kbd{M-x nnfolder-generate-active-file}
-command to make @code{nnfolder} aware of all likely files in
-@code{nnfolder-directory}.
+@item
+Type @kbd{B r} to respool all the process-marked articles, and answer
+@samp{nnml} when prompted (@pxref{Mail Group Commands}).
+@end enumerate
 
+All the mail messages in the mbox file will now also be spread out over
+all your @code{nnml} groups.  Try entering them and check whether things
+have gone without a glitch.  If things look ok, you may consider
+deleting the mbox file, but I wouldn't do that unless I was absolutely
+sure that all the mail has ended up where it should be.
 
-@node Other Sources
-@section Other Sources
+Respooling is also a handy thing to do if you're switching from one mail
+back end to another.  Just respool all the mail in the old mail groups
+using the new mail back end.
 
-Gnus can do more than just read news or mail.  The methods described
-below allow Gnus to view directories and files as if they were
-newsgroups.
 
-@menu
-* Directory Groups::      You can read a directory as if it was a newsgroup.
-* Anything Groups::       Dired?  Who needs dired?
-* Document Groups::       Single files can be the basis of a group.
-* SOUP::                  Reading @sc{SOUP} packets ``offline''.
-* Web Searches::          Creating groups from articles that match a string.
-* Mail-To-News Gateways:: Posting articles via mail-to-news gateways.
-@end menu
+@node Expiring Mail
+@subsection Expiring Mail
+@cindex article expiry
 
+Traditional mail readers have a tendency to remove mail articles when
+you mark them as read, in some way.  Gnus takes a fundamentally
+different approach to mail reading.
 
-@node Directory Groups
-@subsection Directory Groups
-@cindex nndir
-@cindex directory groups
+Gnus basically considers mail just to be news that has been received in
+a rather peculiar manner.  It does not think that it has the power to
+actually change the mail, or delete any mail messages.  If you enter a
+mail group, and mark articles as ``read'', or kill them in some other
+fashion, the mail articles will still exist on the system.  I repeat:
+Gnus will not delete your old, read mail.  Unless you ask it to, of
+course.
 
-If you have a directory that has lots of articles in separate files in
-it, you might treat it as a newsgroup.  The files have to have numerical
-names, of course.
+To make Gnus get rid of your unwanted mail, you have to mark the
+articles as @dfn{expirable}.  (With the default key bindings, this means
+that you have to type @kbd{E}.)  This does not mean that the articles
+will disappear right away, however.  In general, a mail article will be
+deleted from your system if, 1) it is marked as expirable, AND 2) it is
+more than one week old.  If you do not mark an article as expirable, it
+will remain on your system until hell freezes over.  This bears
+repeating one more time, with some spurious capitalizations: IF you do
+NOT mark articles as EXPIRABLE, Gnus will NEVER delete those ARTICLES.
 
-This might be an opportune moment to mention @code{ange-ftp} (and its
-successor @code{efs}), that most wonderful of all wonderful Emacs
-packages.  When I wrote @code{nndir}, I didn't think much about it---a
-backend to read directories.  Big deal.
+You do not have to mark articles as expirable by hand.  Gnus provides
+two features, called ``auto-expire'' and ``total-expire'', that can help you
+with this.  In a nutshell, ``auto-expire'' means that Gnus hits @kbd{E}
+for you when you select an article.  And ``total-expire'' means that Gnus
+considers all articles as expirable that are read.  So, in addition to
+the articles marked @samp{E}, also the articles marked @samp{r},
+@samp{R}, @samp{O}, @samp{K}, @samp{Y} and so on are considered
+expirable.
+
+When should either auto-expire or total-expire be used?  Most people
+who are subscribed to mailing lists split each list into its own group
+and then turn on auto-expire or total-expire for those groups.
+(@xref{Splitting Mail}, for more information on splitting each list
+into its own group.)
+
+Which one is better, auto-expire or total-expire?  It's not easy to
+answer.  Generally speaking, auto-expire is probably faster.  Another
+advantage of auto-expire is that you get more marks to work with: for
+the articles that are supposed to stick around, you can still choose
+between tick and dormant and read marks.  But with total-expire, you
+only have dormant and ticked to choose from.  The advantage of
+total-expire is that it works well with adaptive scoring (@pxref{Adaptive
+Scoring}).  Auto-expire works with normal scoring but not with adaptive
+scoring.
 
-@code{ange-ftp} changes that picture dramatically.  For instance, if you
-enter the @code{ange-ftp} file name
-@file{/ftp.hpc.uh.edu:/pub/emacs/ding-list/} as the directory name,
-@code{ange-ftp} or @code{efs} will actually allow you to read this
-directory over at @samp{sina} as a newsgroup.  Distributed news ahoy!
+@vindex gnus-auto-expirable-newsgroups
+Groups that match the regular expression
+@code{gnus-auto-expirable-newsgroups} will have all articles that you
+read marked as expirable automatically.  All articles marked as
+expirable have an @samp{E} in the first column in the summary buffer.
 
-@code{nndir} will use @sc{nov} files if they are present.
+By default, if you have auto expiry switched on, Gnus will mark all the
+articles you read as expirable, no matter if they were read or unread
+before.  To avoid having articles marked as read marked as expirable
+automatically, you can put something like the following in your
+@file{~/.gnus.el} file:
 
-@code{nndir} is a ``read-only'' backend---you can't delete or expire
-articles with this method.  You can use @code{nnmh} or @code{nnml} for
-whatever you use @code{nndir} for, so you could switch to any of those
-methods if you feel the need to have a non-read-only @code{nndir}.
+@vindex gnus-mark-article-hook
+@lisp
+(remove-hook 'gnus-mark-article-hook
+             'gnus-summary-mark-read-and-unread-as-read)
+(add-hook 'gnus-mark-article-hook 'gnus-summary-mark-unread-as-read)
+@end lisp
 
+Note that making a group auto-expirable doesn't mean that all read
+articles are expired---only the articles marked as expirable
+will be expired.  Also note that using the @kbd{d} command won't make
+articles expirable---only semi-automatic marking of articles as read will
+mark the articles as expirable in auto-expirable groups.
 
-@node Anything Groups
-@subsection Anything Groups
-@cindex nneething
+Let's say you subscribe to a couple of mailing lists, and you want the
+articles you have read to disappear after a while:
 
-From the @code{nndir} backend (which reads a single spool-like
-directory), it's just a hop and a skip to @code{nneething}, which
-pretends that any arbitrary directory is a newsgroup.  Strange, but
-true.
+@lisp
+(setq gnus-auto-expirable-newsgroups
+      "mail.nonsense-list\\|mail.nice-list")
+@end lisp
 
-When @code{nneething} is presented with a directory, it will scan this
-directory and assign article numbers to each file.  When you enter such
-a group, @code{nneething} must create ``headers'' that Gnus can use.
-After all, Gnus is a newsreader, in case you're
-forgetting. @code{nneething} does this in a two-step process.  First, it
-snoops each file in question.  If the file looks like an article (i.e.,
-the first few lines look like headers), it will use this as the head.
-If this is just some arbitrary file without a head (e.g. a C source
-file), @code{nneething} will cobble up a header out of thin air.  It
-will use file ownership, name and date and do whatever it can with these
-elements.
+Another way to have auto-expiry happen is to have the element
+@code{auto-expire} in the group parameters of the group.
 
-All this should happen automatically for you, and you will be presented
-with something that looks very much like a newsgroup.  Totally like a
-newsgroup, to be precise.  If you select an article, it will be displayed
-in the article buffer, just as usual.
+If you use adaptive scoring (@pxref{Adaptive Scoring}) and
+auto-expiring, you'll have problems.  Auto-expiring and adaptive scoring
+don't really mix very well.
 
-If you select a line that represents a directory, Gnus will pop you into
-a new summary buffer for this @code{nneething} group.  And so on.  You can
-traverse the entire disk this way, if you feel like, but remember that
-Gnus is not dired, really, and does not intend to be, either.
+@vindex nnmail-expiry-wait
+The @code{nnmail-expiry-wait} variable supplies the default time an
+expirable article has to live.  Gnus starts counting days from when the
+message @emph{arrived}, not from when it was sent.  The default is seven
+days.
 
-There are two overall modes to this action---ephemeral or solid.  When
-doing the ephemeral thing (i.e., @kbd{G D} from the group buffer), Gnus
-will not store information on what files you have read, and what files
-are new, and so on.  If you create a solid @code{nneething} group the
-normal way with @kbd{G m}, Gnus will store a mapping table between
-article numbers and file names, and you can treat this group like any
-other groups.  When you activate a solid @code{nneething} group, you will
-be told how many unread articles it contains, etc., etc.
+Gnus also supplies a function that lets you fine-tune how long articles
+are to live, based on what group they are in.  Let's say you want to
+have one month expiry period in the @samp{mail.private} group, a one day
+expiry period in the @samp{mail.junk} group, and a six day expiry period
+everywhere else:
 
-Some variables:
+@vindex nnmail-expiry-wait-function
+@lisp
+(setq nnmail-expiry-wait-function
+      (lambda (group)
+       (cond ((string= group "mail.private")
+               31)
+             ((string= group "mail.junk")
+               1)
+             ((string= group "important")
+               'never)
+             (t
+               6))))
+@end lisp
 
-@table @code
-@item nneething-map-file-directory
-@vindex nneething-map-file-directory
-All the mapping files for solid @code{nneething} groups will be stored
-in this directory, which defaults to @file{~/.nneething/}.
+The group names this function is fed are ``unadorned'' group
+names---no @samp{nnml:} prefixes and the like.
 
-@item nneething-exclude-files
-@vindex nneething-exclude-files
-All files that match this regexp will be ignored.  Nice to use to exclude
-auto-save files and the like, which is what it does by default.
+The @code{nnmail-expiry-wait} variable and
+@code{nnmail-expiry-wait-function} function can either be a number (not
+necessarily an integer) or one of the symbols @code{immediate} or
+@code{never}.
 
-@item nneething-map-file
-@vindex nneething-map-file
-Name of the map files.
-@end table
+You can also use the @code{expiry-wait} group parameter to selectively
+change the expiry period (@pxref{Group Parameters}).
 
+@vindex nnmail-expiry-target
+The normal action taken when expiring articles is to delete them.
+However, in some circumstances it might make more sense to move them
+to other groups instead of deleting them.  The variable
+@code{nnmail-expiry-target} (and the @code{expiry-target} group
+parameter) controls this.  The variable supplies a default value for
+all groups, which can be overridden for specific groups by the group
+parameter.  default value is @code{delete}, but this can also be a
+string (which should be the name of the group the message should be
+moved to), or a function (which will be called in a buffer narrowed to
+the message in question, and with the name of the group being moved
+from as its parameter) which should return a target---either a group
+name or @code{delete}.
+
+Here's an example for specifying a group name:
+@lisp
+(setq nnmail-expiry-target "nnml:expired")
+@end lisp
 
-@node Document Groups
-@subsection Document Groups
-@cindex nndoc
-@cindex documentation group
-@cindex help group
+@findex nnmail-fancy-expiry-target
+@vindex nnmail-fancy-expiry-targets
+Gnus provides a function @code{nnmail-fancy-expiry-target} which will
+expire mail to groups according to the variable
+@code{nnmail-fancy-expiry-targets}.  Here's an example:
 
-@code{nndoc} is a cute little thing that will let you read a single file
-as a newsgroup.  Several files types are supported:
+@lisp
+ (setq nnmail-expiry-target 'nnmail-fancy-expiry-target
+       nnmail-fancy-expiry-targets
+       '((to-from "boss" "nnfolder:Work")
+         ("subject" "IMPORTANT" "nnfolder:IMPORTANT.%Y.%b")
+         ("from" ".*" "nnfolder:Archive-%Y")))
+@end lisp
 
-@table @code
-@cindex babyl
-@cindex rmail mbox
+With this setup, any mail that has @code{IMPORTANT} in its Subject
+header and was sent in the year @code{YYYY} and month @code{MMM}, will
+get expired to the group @code{nnfolder:IMPORTANT.YYYY.MMM}.  If its
+From or To header contains the string @code{boss}, it will get expired
+to @code{nnfolder:Work}.  All other mail will get expired to
+@code{nnfolder:Archive-YYYY}.
 
-@item babyl
-The babyl (rmail) mail box.
-@cindex mbox
-@cindex Unix mbox
+@vindex nnmail-keep-last-article
+If @code{nnmail-keep-last-article} is non-@code{nil}, Gnus will never
+expire the final article in a mail newsgroup.  This is to make life
+easier for procmail users.
 
-@item mbox
-The standard Unix mbox file.
+@vindex gnus-total-expirable-newsgroups
+By the way: That line up there, about Gnus never expiring non-expirable
+articles, is a lie.  If you put @code{total-expire} in the group
+parameters, articles will not be marked as expirable, but all read
+articles will be put through the expiry process.  Use with extreme
+caution.  Even more dangerous is the
+@code{gnus-total-expirable-newsgroups} variable.  All groups that match
+this regexp will have all read articles put through the expiry process,
+which means that @emph{all} old mail articles in the groups in question
+will be deleted after a while.  Use with extreme caution, and don't come
+crying to me when you discover that the regexp you used matched the
+wrong group and all your important mail has disappeared.  Be a
+@emph{man}!  Or a @emph{woman}!  Whatever you feel more comfortable
+with!  So there!
 
-@cindex MMDF mail box
-@item mmdf
-The MMDF mail box format.
+Most people make most of their mail groups total-expirable, though.
 
-@item news
-Several news articles appended into a file.
+@vindex gnus-inhibit-user-auto-expire
+If @code{gnus-inhibit-user-auto-expire} is non-@code{nil}, user marking
+commands will not mark an article as expirable, even if the group has
+auto-expire turned on.
 
-@item rnews
-@cindex rnews batch files
-The rnews batch transport format.
-@cindex forwarded messages
 
-@item forward
-Forwarded articles.
+@node Washing Mail
+@subsection Washing Mail
+@cindex mail washing
+@cindex list server brain damage
+@cindex incoming mail treatment
 
-@item mime-digest
-@cindex digest
-@cindex MIME digest
-@cindex 1153 digest
-@cindex RFC 1153 digest
-@cindex RFC 341 digest
-MIME (RFC 1341) digest format.
+Mailers and list servers are notorious for doing all sorts of really,
+really stupid things with mail.  ``Hey, RFC 822 doesn't explicitly
+prohibit us from adding the string @code{wE aRe ElItE!!!!!1!!} to the
+end of all lines passing through our server, so let's do that!!!!1!''
+Yes, but RFC 822 wasn't designed to be read by morons.  Things that were
+considered to be self-evident were not discussed.  So.  Here we are.
 
-@item standard-digest
-The standard (RFC 1153) digest format.
+Case in point:  The German version of Microsoft Exchange adds @samp{AW:
+} to the subjects of replies instead of @samp{Re: }.  I could pretend to
+be shocked and dismayed by this, but I haven't got the energy.  It is to
+laugh.
 
-@item slack-digest
-Non-standard digest format---matches most things, but does it badly. 
-@end table
+Gnus provides a plethora of functions for washing articles while
+displaying them, but it might be nicer to do the filtering before
+storing the mail to disk.  For that purpose, we have three hooks and
+various functions that can be put in these hooks.
 
-You can also use the special ``file type'' @code{guess}, which means
-that @code{nndoc} will try to guess what file type it is looking at.
-@code{digest} means that @code{nndoc} should guess what digest type the
-file is.
+@table @code
+@item nnmail-prepare-incoming-hook
+@vindex nnmail-prepare-incoming-hook
+This hook is called before doing anything with the mail and is meant for
+grand, sweeping gestures.  It is called in a buffer that contains all
+the new, incoming mail.  Functions to be used include:
 
-@code{nndoc} will not try to change the file or insert any extra headers into
-it---it will simply, like, let you use the file as the basis for a
-group.  And that's it.
+@table @code
+@item nnheader-ms-strip-cr
+@findex nnheader-ms-strip-cr
+Remove trailing carriage returns from each line.  This is default on
+Emacs running on MS machines.
 
-If you have some old archived articles that you want to insert into your
-new & spiffy Gnus mail backend, @code{nndoc} can probably help you with
-that.  Say you have an old @file{RMAIL} file with mail that you now want
-to split into your new @code{nnml} groups.  You look at that file using
-@code{nndoc} (using the @kbd{G f} command in the group buffer
-(@pxref{Foreign Groups})), set the process mark on all the articles in
-the buffer (@kbd{M P b}, for instance), and then re-spool (@kbd{B r})
-using @code{nnml}.  If all goes well, all the mail in the @file{RMAIL}
-file is now also stored in lots of @code{nnml} directories, and you can
-delete that pesky @file{RMAIL} file.  If you have the guts!
+@end table
 
-Virtual server variables:
+@item nnmail-prepare-incoming-header-hook
+@vindex nnmail-prepare-incoming-header-hook
+This hook is called narrowed to each header.  It can be used when
+cleaning up the headers.  Functions that can be used include:
 
 @table @code
-@item nndoc-article-type
-@vindex nndoc-article-type
-This should be one of @code{mbox}, @code{babyl}, @code{digest},
-@code{news}, @code{rnews}, @code{mmdf}, @code{forward}, @code{rfc934},
-@code{rfc822-forward}, @code{mime-digest}, @code{standard-digest},
-@code{slack-digest}, @code{clari-briefs} or @code{guess}.
+@item nnmail-remove-leading-whitespace
+@findex nnmail-remove-leading-whitespace
+Clear leading white space that ``helpful'' listservs have added to the
+headers to make them look nice.  Aaah.
 
-@item nndoc-post-type
-@vindex nndoc-post-type
-This variable says whether Gnus is to consider the group a news group or
-a mail group.  There are two valid values:  @code{mail} (the default)
-and @code{news}.
-@end table
+(Note that this function works on both the header on the body of all
+messages, so it is a potentially dangerous function to use (if a body
+of a message contains something that looks like a header line).  So
+rather than fix the bug, it is of course the right solution to make it
+into a feature by documenting it.)
 
-@menu
-* Document Server Internals::   How to add your own document types.
-@end menu
+@item nnmail-remove-list-identifiers
+@findex nnmail-remove-list-identifiers
+Some list servers add an identifier---for example, @samp{(idm)}---to the
+beginning of all @code{Subject} headers.  I'm sure that's nice for
+people who use stone age mail readers.  This function will remove
+strings that match the @code{nnmail-list-identifiers} regexp, which can
+also be a list of regexp.  @code{nnmail-list-identifiers} may not contain
+@code{\\(..\\)}.
 
+For instance, if you want to remove the @samp{(idm)} and the
+@samp{nagnagnag} identifiers:
 
-@node Document Server Internals
-@subsubsection Document Server Internals
+@lisp
+(setq nnmail-list-identifiers
+      '("(idm)" "nagnagnag"))
+@end lisp
 
-Adding new document types to be recognized by @code{nndoc} isn't
-difficult.  You just have to whip up a definition of what the document
-looks like, write a predicate function to recognize that document type,
-and then hook into @code{nndoc}.
+This can also be done non-destructively with
+@code{gnus-list-identifiers}, @xref{Article Hiding}.
 
-First, here's an example document type definition:
+@item nnmail-remove-tabs
+@findex nnmail-remove-tabs
+Translate all @samp{TAB} characters into @samp{SPACE} characters.
 
-@example
-(mmdf 
- (article-begin .  "^\^A\^A\^A\^A\n")
- (body-end .  "^\^A\^A\^A\^A\n"))
-@end example
+@item nnmail-fix-eudora-headers
+@findex nnmail-fix-eudora-headers
+@cindex Eudora
+Eudora produces broken @code{References} headers, but OK
+@code{In-Reply-To} headers.  This function will get rid of the
+@code{References} headers.
 
-The definition is simply a unique @dfn{name} followed by a series of
-regexp pseudo-variable settings.  Below are the possible
-variables---don't be daunted by the number of variables; most document
-types can be defined with very few settings:
+@end table
+
+@item nnmail-prepare-incoming-message-hook
+@vindex nnmail-prepare-incoming-message-hook
+This hook is called narrowed to each message.  Functions to be used
+include:
 
 @table @code
-@item first-article
-If present, @code{nndoc} will skip past all text until it finds
-something that match this regexp.  All text before this will be
-totally ignored. 
+@item article-de-quoted-unreadable
+@findex article-de-quoted-unreadable
+Decode Quoted Readable encoding.
 
-@item article-begin
-This setting has to be present in all document type definitions.  It
-says what the beginning of each article looks like.
+@end table
+@end table
 
-@item head-begin-function
-If present, this should be a function that moves point to the head of
-the article.
 
-@item nndoc-head-begin
-If present, this should be a regexp that matches the head of the
-article. 
+@node Duplicates
+@subsection Duplicates
 
-@item nndoc-head-end
-This should match the end of the head of the article.  It defaults to
-@samp{^$}---the empty line.
+@vindex nnmail-treat-duplicates
+@vindex nnmail-message-id-cache-length
+@vindex nnmail-message-id-cache-file
+@cindex duplicate mails
+If you are a member of a couple of mailing lists, you will sometimes
+receive two copies of the same mail.  This can be quite annoying, so
+@code{nnmail} checks for and treats any duplicates it might find.  To do
+this, it keeps a cache of old @code{Message-ID}s---
+@code{nnmail-message-id-cache-file}, which is @file{~/.nnmail-cache} by
+default.  The approximate maximum number of @code{Message-ID}s stored
+there is controlled by the @code{nnmail-message-id-cache-length}
+variable, which is 1000 by default.  (So 1000 @code{Message-ID}s will be
+stored.) If all this sounds scary to you, you can set
+@code{nnmail-treat-duplicates} to @code{warn} (which is what it is by
+default), and @code{nnmail} won't delete duplicate mails.  Instead it
+will insert a warning into the head of the mail saying that it thinks
+that this is a duplicate of a different message.
 
-@item body-begin-function
-If present, this function should move point to the beginning of the body
-of the article.
+This variable can also be a function.  If that's the case, the function
+will be called from a buffer narrowed to the message in question with
+the @code{Message-ID} as a parameter.  The function must return either
+@code{nil}, @code{warn}, or @code{delete}.
 
-@item body-begin
-This should match the beginning of the body of the article.  It defaults
-to @samp{^\n}.
+You can turn this feature off completely by setting the variable to
+@code{nil}.
 
-@item body-end-function
-If present, this function should move point to the end of the body of
-the article.
+If you want all the duplicate mails to be put into a special
+@dfn{duplicates} group, you could do that using the normal mail split
+methods:
 
-@item body-end
-If present, this should match the end of the body of the article.
+@lisp
+(setq nnmail-split-fancy
+      '(| ;; @r{Messages duplicates go to a separate group.}
+        ("gnus-warning" "duplicat\\(e\\|ion\\) of message" "duplicate")
+        ;; @r{Message from daemons, postmaster, and the like to another.}
+        (any mail "mail.misc")
+        ;; @r{Other rules.}
+        [...] ))
+@end lisp
+@noindent
+Or something like:
+@lisp
+(setq nnmail-split-methods
+      '(("duplicates" "^Gnus-Warning:.*duplicate")
+        ;; @r{Other rules.}
+        [...]))
+@end lisp
 
-@item file-end
-If present, this should match the end of the file.  All text after this
-regexp will be totally ignored. 
+Here's a neat feature: If you know that the recipient reads her mail
+with Gnus, and that she has @code{nnmail-treat-duplicates} set to
+@code{delete}, you can send her as many insults as you like, just by
+using a @code{Message-ID} of a mail that you know that she's already
+received.  Think of all the fun!  She'll never see any of it!  Whee!
 
-@end table
 
-So, using these variables @code{nndoc} is able to dissect a document
-file into a series of articles, each with a head and a body.  However, a
-few more variables are needed since not all document types are all that
-news-like---variables needed to transform the head or the body into
-something that's palatable for Gnus:
+@node Not Reading Mail
+@subsection Not Reading Mail
 
-@table @code
-@item prepare-body-function
-If present, this function will be called when requesting an article.  It
-will be called with point at the start of the body, and is useful if the
-document has encoded some parts of its contents. 
+If you start using any of the mail back ends, they have the annoying
+habit of assuming that you want to read mail with them.  This might not
+be unreasonable, but it might not be what you want.
 
-@item article-transform-function
-If present, this function is called when requesting an article.  It's
-meant to be used for more wide-ranging transformation of both head and
-body of the article.
+If you set @code{mail-sources} and @code{nnmail-spool-file} to
+@code{nil}, none of the back ends will ever attempt to read incoming
+mail, which should help.
 
-@item generate-head-function
-If present, this function is called to generate a head that Gnus can
-understand.  It is called with the article number as a parameter, and is
-expected to generate a nice head for the article in question.  It is
-called when requesting the headers of all articles.
+@vindex nnbabyl-get-new-mail
+@vindex nnmbox-get-new-mail
+@vindex nnml-get-new-mail
+@vindex nnmh-get-new-mail
+@vindex nnfolder-get-new-mail
+This might be too much, if, for instance, you are reading mail quite
+happily with @code{nnml} and just want to peek at some old Rmail
+file you have stashed away with @code{nnbabyl}.  All back ends have
+variables called back-end-@code{get-new-mail}.  If you want to disable
+the @code{nnbabyl} mail reading, you edit the virtual server for the
+group to have a setting where @code{nnbabyl-get-new-mail} to @code{nil}.
 
-@end table
+All the mail back ends will call @code{nn}*@code{-prepare-save-mail-hook}
+narrowed to the article to be saved before saving it when reading
+incoming mail.
 
-Let's look at the most complicated example I can come up with---standard
-digests:
 
-@example
-(standard-digest
- (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
- (article-begin . ,(concat "\n\n" (make-string 30 ?-) "\n\n+"))
- (prepare-body-function . nndoc-unquote-dashes)
- (body-end-function . nndoc-digest-body-end)
- (head-end . "^ ?$")
- (body-begin . "^ ?\n")
- (file-end . "^End of .*digest.*[0-9].*\n\\*\\*\\|^End of.*Digest *$")
- (subtype digest guess))
-@end example
+@node Choosing a Mail Back End
+@subsection Choosing a Mail Back End
 
-We see that all text before a 70-width line of dashes is ignored; all
-text after a line that starts with that @samp{^End of} is also ignored;
-each article begins with a 30-width line of dashes; the line separating
-the head from the body may contain a single space; and that the body is
-run through @code{nndoc-unquote-dashes} before being delivered.
+Gnus will read the mail spool when you activate a mail group.  The mail
+file is first copied to your home directory.  What happens after that
+depends on what format you want to store your mail in.
 
-To hook your own document definition into @code{nndoc}, use the
-@code{nndoc-add-type} function.  It takes two parameters---the first is
-the definition itself and the second (optional) parameter says where in
-the document type definition alist to put this definition.  The alist is
-traversed sequentially, and @code{nndoc-TYPE-type-p} is called for a given type @code{TYPE}.  So @code{nndoc-mmdf-type-p} is called to see whether a document
-is of @code{mmdf} type, and so on.  These type predicates should return
-@code{nil} if the document is not of the correct type; @code{t} if it is
-of the correct type; and a number if the document might be of the
-correct type.  A high number means high probability; a low number means
-low probability with @samp{0} being the lowest valid number.
+There are six different mail back ends in the standard Gnus, and more
+back ends are available separately.  The mail back end most people use
+(because it is possibly the fastest) is @code{nnml} (@pxref{Mail
+Spool}).
 
+@menu
+* Unix Mail Box::               Using the (quite) standard Un*x mbox.
+* Rmail Babyl::                 Emacs programs use the Rmail Babyl format.
+* Mail Spool::                  Store your mail in a private spool?
+* MH Spool::                    An mhspool-like back end.
+* Maildir::                     Another one-file-per-message format.
+* Mail Folders::                Having one file for each group.
+* Comparing Mail Back Ends::    An in-depth looks at pros and cons.
+@end menu
 
-@node SOUP
-@subsection SOUP
-@cindex SOUP
-@cindex offline
 
-In the PC world people often talk about ``offline'' newsreaders.  These
-are thingies that are combined reader/news transport monstrosities.
-With built-in modem programs.  Yecchh!
+@node Unix Mail Box
+@subsubsection Unix Mail Box
+@cindex nnmbox
+@cindex unix mail box
 
-Of course, us Unix Weenie types of human beans use things like
-@code{uucp} and, like, @code{nntpd} and set up proper news and mail
-transport things like Ghod intended.  And then we just use normal
-newsreaders.  
+@vindex nnmbox-active-file
+@vindex nnmbox-mbox-file
+The @dfn{nnmbox} back end will use the standard Un*x mbox file to store
+mail.  @code{nnmbox} will add extra headers to each mail article to say
+which group it belongs in.
 
-However, it can sometimes be convenient to do something a that's a bit
-easier on the brain if you have a very slow modem, and you're not really
-that interested in doing things properly.  
+Virtual server settings:
 
-A file format called @sc{soup} has been developed for transporting news
-and mail from servers to home machines and back again.  It can be a bit
-fiddly.
+@table @code
+@item nnmbox-mbox-file
+@vindex nnmbox-mbox-file
+The name of the mail box in the user's home directory.  Default is
+@file{~/mbox}.
 
-First some terminology:
+@item nnmbox-active-file
+@vindex nnmbox-active-file
+The name of the active file for the mail box.  Default is
+@file{~/.mbox-active}.
 
-@table @dfn
+@item nnmbox-get-new-mail
+@vindex nnmbox-get-new-mail
+If non-@code{nil}, @code{nnmbox} will read incoming mail and split it
+into groups.  Default is @code{t}.
+@end table
 
-@item server
-This is the machine that is connected to the outside world and where you
-get news and/or mail from.
 
-@item home machine
-This is the machine that you want to do the actual reading and responding
-on.  It is typically not connected to the rest of the world in any way.
+@node Rmail Babyl
+@subsubsection Rmail Babyl
+@cindex nnbabyl
+@cindex Rmail mbox
 
-@item packet
-Something that contains messages and/or commands.  There are two kinds
-of packets:
+@vindex nnbabyl-active-file
+@vindex nnbabyl-mbox-file
+The @dfn{nnbabyl} back end will use a Babyl mail box (aka. @dfn{Rmail
+mbox}) to store mail.  @code{nnbabyl} will add extra headers to each
+mail article to say which group it belongs in.
 
-@table @dfn
-@item message packets
-These are packets made at the server, and typically contain lots of
-messages for you to read.  These are called @file{SoupoutX.tgz} by
-default, where @var{X} is a number.
+Virtual server settings:
 
-@item response packets
-These are packets made at the home machine, and typically contains
-replies that you've written.  These are called @file{SoupinX.tgz} by
-default, where @var{X} is a number.
+@table @code
+@item nnbabyl-mbox-file
+@vindex nnbabyl-mbox-file
+The name of the Rmail mbox file.  The default is @file{~/RMAIL}
 
-@end table
+@item nnbabyl-active-file
+@vindex nnbabyl-active-file
+The name of the active file for the rmail box.  The default is
+@file{~/.rmail-active}
 
+@item nnbabyl-get-new-mail
+@vindex nnbabyl-get-new-mail
+If non-@code{nil}, @code{nnbabyl} will read incoming mail.  Default is
+@code{t}
 @end table
 
 
-@enumerate
-
-@item
-You log in on the server and create a @sc{soup} packet.  You can either
-use a dedicated @sc{soup} thingie (like the @code{awk} program), or you
-can use Gnus to create the packet with its @sc{soup} commands (@kbd{O
-s} and/or @kbd{G s b}; and then @kbd{G s p}) (@pxref{SOUP Commands}).
+@node Mail Spool
+@subsubsection Mail Spool
+@cindex nnml
+@cindex mail @acronym{NOV} spool
 
-@item 
-You transfer the packet home.  Rail, boat, car or modem will do fine.
+The @dfn{nnml} spool mail format isn't compatible with any other known
+format.  It should be used with some caution.
 
-@item
-You put the packet in your home directory.
+@vindex nnml-directory
+If you use this back end, Gnus will split all incoming mail into files,
+one file for each mail, and put the articles into the corresponding
+directories under the directory specified by the @code{nnml-directory}
+variable.  The default value is @file{~/Mail/}.
 
-@item
-You fire up Gnus on your home machine using the @code{nnsoup} backend as
-the native or secondary server.
+You do not have to create any directories beforehand; Gnus will take
+care of all that.
 
-@item
-You read articles and mail and answer and followup to the things you
-want (@pxref{SOUP Replies}).
+If you have a strict limit as to how many files you are allowed to store
+in your account, you should not use this back end.  As each mail gets its
+own file, you might very well occupy thousands of inodes within a few
+weeks.  If this is no problem for you, and it isn't a problem for you
+having your friendly systems administrator walking around, madly,
+shouting ``Who is eating all my inodes?! Who? Who!?!'', then you should
+know that this is probably the fastest format to use.  You do not have
+to trudge through a big mbox file just to read your new mail.
 
-@item 
-You do the @kbd{G s r} command to pack these replies into a @sc{soup}
-packet.
+@code{nnml} is probably the slowest back end when it comes to article
+splitting.  It has to create lots of files, and it also generates
+@acronym{NOV} databases for the incoming mails.  This makes it possibly the
+fastest back end when it comes to reading mail.
 
-@item 
-You transfer this packet to the server.  
+@cindex self contained nnml servers
+@cindex marks
+When the marks file is used (which it is by default), @code{nnml}
+servers have the property that you may backup them using @code{tar} or
+similar, and later be able to restore them into Gnus (by adding the
+proper @code{nnml} server) and have all your marks be preserved.  Marks
+for a group is usually stored in the @code{.marks} file (but see
+@code{nnml-marks-file-name}) within each @code{nnml} group's directory.
+Individual @code{nnml} groups are also possible to backup, use @kbd{G m}
+to restore the group (after restoring the backup into the nnml
+directory).
+
+If for some reason you believe your @file{.marks} files are screwed
+up, you can just delete them all.  Gnus will then correctly regenerate
+them next time it starts.
 
-@item
-You use Gnus to mail this packet out with the @kbd{G s s} command.
+Virtual server settings:
 
-@item
-You then repeat until you die.
+@table @code
+@item nnml-directory
+@vindex nnml-directory
+All @code{nnml} directories will be placed under this directory.  The
+default is the value of @code{message-directory} (whose default value
+is @file{~/Mail}).
 
-@end enumerate
+@item nnml-active-file
+@vindex nnml-active-file
+The active file for the @code{nnml} server.  The default is
+@file{~/Mail/active}.
 
-So you basically have a bipartite system---you use @code{nnsoup} for
-reading and Gnus for packing/sending these @sc{soup} packets.
+@item nnml-newsgroups-file
+@vindex nnml-newsgroups-file
+The @code{nnml} group descriptions file.  @xref{Newsgroups File
+Format}.  The default is @file{~/Mail/newsgroups}.
 
-@menu
-* SOUP Commands::     Commands for creating and sending @sc{soup} packets
-* SOUP Groups::       A backend for reading @sc{soup} packets.
-* SOUP Replies::      How to enable @code{nnsoup} to take over mail and news.
-@end menu
+@item nnml-get-new-mail
+@vindex nnml-get-new-mail
+If non-@code{nil}, @code{nnml} will read incoming mail.  The default is
+@code{t}.
 
+@item nnml-nov-is-evil
+@vindex nnml-nov-is-evil
+If non-@code{nil}, this back end will ignore any @acronym{NOV} files.  The
+default is @code{nil}.
 
-@node SOUP Commands
-@subsubsection SOUP Commands
+@item nnml-nov-file-name
+@vindex nnml-nov-file-name
+The name of the @acronym{NOV} files.  The default is @file{.overview}.
 
-These are commands for creating and manipulating @sc{soup} packets.
+@item nnml-prepare-save-mail-hook
+@vindex nnml-prepare-save-mail-hook
+Hook run narrowed to an article before saving.
 
-@table @kbd
-@item G s b
-@kindex G s b (Group)
-@findex gnus-group-brew-soup
-Pack all unread articles in the current group
-(@code{gnus-group-brew-soup}).  This command understands the
-process/prefix convention.
+@item nnml-marks-is-evil
+@vindex nnml-marks-is-evil
+If non-@code{nil}, this back end will ignore any @sc{marks} files.  The
+default is @code{nil}.
 
-@item G s w
-@kindex G s w (Group)
-@findex gnus-soup-save-areas
-Save all @sc{soup} data files (@code{gnus-soup-save-areas}).
+@item nnml-marks-file-name
+@vindex nnml-marks-file-name
+The name of the @dfn{marks} files.  The default is @file{.marks}.
 
-@item G s s
-@kindex G s s (Group)
-@findex gnus-soup-send-replies
-Send all replies from the replies packet
-(@code{gnus-soup-send-replies}). 
+@item nnml-use-compressed-files
+@vindex nnml-use-compressed-files
+If non-@code{nil}, @code{nnml} will allow using compressed message
+files.
 
-@item G s p
-@kindex G s p (Group)
-@findex gnus-soup-pack-packet
-Pack all files into a @sc{soup} packet (@code{gnus-soup-pack-packet}). 
+@end table
 
-@item G s r
-@kindex G s r (Group)
-@findex nnsoup-pack-replies
-Pack all replies into a replies packet (@code{nnsoup-pack-replies}). 
+@findex nnml-generate-nov-databases
+If your @code{nnml} groups and @acronym{NOV} files get totally out of
+whack, you can do a complete update by typing @kbd{M-x
+nnml-generate-nov-databases}.  This command will trawl through the
+entire @code{nnml} hierarchy, looking at each and every article, so it
+might take a while to complete.  A better interface to this
+functionality can be found in the server buffer (@pxref{Server
+Commands}).
 
-@item O s
-@kindex O s (Summary)
-@findex gnus-soup-add-article
-This summary-mode command adds the current article to a @sc{soup} packet
-(@code{gnus-soup-add-article}).  It understands the process/prefix
-convention (@pxref{Process/Prefix}). 
 
-@end table
+@node MH Spool
+@subsubsection MH Spool
+@cindex nnmh
+@cindex mh-e mail spool
 
+@code{nnmh} is just like @code{nnml}, except that is doesn't generate
+@acronym{NOV} databases and it doesn't keep an active file or marks
+file.  This makes @code{nnmh} a @emph{much} slower back end than
+@code{nnml}, but it also makes it easier to write procmail scripts
+for.
 
-There are a few variables to customize where Gnus will put all these
-thingies:  
+Virtual server settings:
 
 @table @code
+@item nnmh-directory
+@vindex nnmh-directory
+All @code{nnmh} directories will be located under this directory.  The
+default is the value of @code{message-directory} (whose default is
+@file{~/Mail})
 
-@item gnus-soup-directory
-@vindex gnus-soup-directory
-Directory where Gnus will save intermediate files while composing
-@sc{soup} packets.  The default is @file{~/SoupBrew/}. 
+@item nnmh-get-new-mail
+@vindex nnmh-get-new-mail
+If non-@code{nil}, @code{nnmh} will read incoming mail.  The default is
+@code{t}.
 
-@item gnus-soup-replies-directory
-@vindex gnus-soup-replies-directory
-This is what Gnus will use as a temporary directory while sending our
-reply packets.  @file{~/SoupBrew/SoupReplies/} is the default.
+@item nnmh-be-safe
+@vindex nnmh-be-safe
+If non-@code{nil}, @code{nnmh} will go to ridiculous lengths to make
+sure that the articles in the folder are actually what Gnus thinks
+they are.  It will check date stamps and stat everything in sight, so
+setting this to @code{t} will mean a serious slow-down.  If you never
+use anything but Gnus to read the @code{nnmh} articles, you do not
+have to set this variable to @code{t}.  The default is @code{nil}.
+@end table
 
-@item gnus-soup-prefix-file
-@vindex gnus-soup-prefix-file
-Name of the file where Gnus stores the last used prefix.  The default is
-@samp{gnus-prefix}. 
 
-@item gnus-soup-packer
-@vindex gnus-soup-packer
-A format string command for packing a @sc{soup} packet.  The default is
-@samp{tar cf - %s | gzip > $HOME/Soupout%d.tgz}. 
+@node Maildir
+@subsubsection Maildir
+@cindex nnmaildir
+@cindex maildir
 
-@item gnus-soup-unpacker
-@vindex gnus-soup-unpacker
-Format string command for unpacking a @sc{soup} packet.  The default is
-@samp{gunzip -c %s | tar xvf -}.
+@code{nnmaildir} stores mail in the maildir format, with each maildir
+corresponding to a group in Gnus.  This format is documented here:
+@uref{http://cr.yp.to/proto/maildir.html} and here:
+@uref{http://www.qmail.org/man/man5/maildir.html}.  @code{nnmaildir}
+also stores extra information in the @file{.nnmaildir/} directory
+within a maildir.
 
-@item gnus-soup-packet-directory
-@vindex gnus-soup-packet-directory
-Where Gnus will look for reply packets.  The default is @file{~/}. 
+Maildir format was designed to allow concurrent deliveries and
+reading, without needing locks.  With other back ends, you would have
+your mail delivered to a spool of some kind, and then you would
+configure Gnus to split mail from that spool into your groups.  You
+can still do that with @code{nnmaildir}, but the more common
+configuration is to have your mail delivered directly to the maildirs
+that appear as group in Gnus.
 
-@item gnus-soup-packet-regexp
-@vindex gnus-soup-packet-regexp
-Regular expression matching @sc{soup} reply packets in
-@code{gnus-soup-packet-directory}. 
+@code{nnmaildir} is designed to be perfectly reliable: @kbd{C-g} will
+never corrupt its data in memory, and @code{SIGKILL} will never
+corrupt its data in the filesystem.
 
+@code{nnmaildir} stores article marks and @acronym{NOV} data in each
+maildir.  So you can copy a whole maildir from one Gnus setup to
+another, and you will keep your marks.
+
+Virtual server settings:
+
+@table @code
+@item directory
+For each of your @code{nnmaildir} servers (it's very unlikely that
+you'd need more than one), you need to create a directory and populate
+it with maildirs or symlinks to maildirs (and nothing else; do not
+choose a directory already used for other purposes).  Each maildir
+will be represented in Gnus as a newsgroup on that server; the
+filename of the symlink will be the name of the group.  Any filenames
+in the directory starting with @samp{.} are ignored.  The directory is
+scanned when you first start Gnus, and each time you type @kbd{g} in
+the group buffer; if any maildirs have been removed or added,
+@code{nnmaildir} notices at these times.
+
+The value of the @code{directory} parameter should be a Lisp form
+which is processed by @code{eval} and @code{expand-file-name} to get
+the path of the directory for this server.  The form is @code{eval}ed
+only when the server is opened; the resulting string is used until the
+server is closed.  (If you don't know about forms and @code{eval},
+don't worry---a simple string will work.)  This parameter is not
+optional; you must specify it.  I don't recommend using
+@code{"~/Mail"} or a subdirectory of it; several other parts of Gnus
+use that directory by default for various things, and may get confused
+if @code{nnmaildir} uses it too.  @code{"~/.nnmaildir"} is a typical
+value.
+
+@item target-prefix
+This should be a Lisp form which is processed by @code{eval} and
+@code{expand-file-name}.  The form is @code{eval}ed only when the
+server is opened; the resulting string is used until the server is
+closed.
+
+When you create a group on an @code{nnmaildir} server, the maildir is
+created with @code{target-prefix} prepended to its name, and a symlink
+pointing to that maildir is created, named with the plain group name.
+So if @code{directory} is @code{"~/.nnmaildir"} and
+@code{target-prefix} is @code{"../maildirs/"}, then when you create
+the group @code{foo}, @code{nnmaildir} will create
+@file{~/.nnmaildir/../maildirs/foo} as a maildir, and will create
+@file{~/.nnmaildir/foo} as a symlink pointing to
+@file{../maildirs/foo}.
+
+You can set @code{target-prefix} to a string without any slashes to
+create both maildirs and symlinks in the same @code{directory}; in
+this case, any maildirs found in @code{directory} whose names start
+with @code{target-prefix} will not be listed as groups (but the
+symlinks pointing to them will be).
+
+As a special case, if @code{target-prefix} is @code{""} (the default),
+then when you create a group, the maildir will be created in
+@code{directory} without a corresponding symlink.  Beware that you
+cannot use @code{gnus-group-delete-group} on such groups without the
+@code{force} argument.
+
+@item directory-files
+This should be a function with the same interface as
+@code{directory-files} (such as @code{directory-files} itself).  It is
+used to scan the server's @code{directory} for maildirs.  This
+parameter is optional; the default is
+@code{nnheader-directory-files-safe} if
+@code{nnheader-directory-files-is-safe} is @code{nil}, and
+@code{directory-files} otherwise.
+(@code{nnheader-directory-files-is-safe} is checked only once when the
+server is opened; if you want to check it each time the directory is
+scanned, you'll have to provide your own function that does that.)
+
+@item get-new-mail
+If non-@code{nil}, then after scanning for new mail in the group
+maildirs themselves as usual, this server will also incorporate mail
+the conventional Gnus way, from @code{mail-sources} according to
+@code{nnmail-split-methods} or @code{nnmail-split-fancy}.  The default
+value is @code{nil}.
+
+Do @emph{not} use the same maildir both in @code{mail-sources} and as
+an @code{nnmaildir} group.  The results might happen to be useful, but
+that would be by chance, not by design, and the results might be
+different in the future.  If your split rules create new groups,
+remember to supply a @code{create-directory} server parameter.
 @end table
 
-@node SOUP Groups
-@subsubsection @sc{soup} Groups
-@cindex nnsoup
+@subsubsection Group parameters
+
+@code{nnmaildir} uses several group parameters.  It's safe to ignore
+all this; the default behavior for @code{nnmaildir} is the same as the
+default behavior for other mail back ends: articles are deleted after
+one week, etc.  Except for the expiry parameters, all this
+functionality is unique to @code{nnmaildir}, so you can ignore it if
+you're just trying to duplicate the behavior you already have with
+another back end.
+
+If the value of any of these parameters is a vector, the first element
+is evaluated as a Lisp form and the result is used, rather than the
+original value.  If the value is not a vector, the value itself is
+evaluated as a Lisp form.  (This is why these parameters use names
+different from those of other, similar parameters supported by other
+back ends: they have different, though similar, meanings.)  (For
+numbers, strings, @code{nil}, and @code{t}, you can ignore the
+@code{eval} business again; for other values, remember to use an extra
+quote and wrap the value in a vector when appropriate.)
 
-@code{nnsoup} is the backend for reading @sc{soup} packets.  It will
-read incoming packets, unpack them, and put them in a directory where
-you can read them at leisure.
+@table @code
+@item expire-age
+An integer specifying the minimum age, in seconds, of an article
+before it will be expired, or the symbol @code{never} to specify that
+articles should never be expired.  If this parameter is not set,
+@code{nnmaildir} falls back to the usual
+@code{nnmail-expiry-wait}(@code{-function}) variables (overrideable by
+the @code{expiry-wait}(@code{-function}) group parameters.  If you
+wanted a value of 3 days, you could use something like @code{[(* 3 24
+60 60)]}; @code{nnmaildir} will evaluate the form and use the result.
+An article's age is measured starting from the article file's
+modification time.  Normally, this is the same as the article's
+delivery time, but editing an article makes it younger.  Moving an
+article (other than via expiry) may also make an article younger.
+
+@item expire-group
+If this is set to a string such as a full Gnus group name, like
+@example
+"backend+server.address.string:group.name"
+@end example
+and if it is not the name of the same group that the parameter belongs
+to, then articles will be moved to the specified group during expiry
+before being deleted.  @emph{If this is set to an @code{nnmaildir}
+group, the article will be just as old in the destination group as it
+was in the source group.}  So be careful with @code{expire-age} in the
+destination group.  If this is set to the name of the same group that
+the parameter belongs to, then the article is not expired at all.  If
+you use the vector form, the first element is evaluated once for each
+article.  So that form can refer to
+@code{nnmaildir-article-file-name}, etc., to decide where to put the
+article.  @emph{If this parameter is not set, @code{nnmaildir} does
+not fall back to the @code{expiry-target} group parameter or the
+@code{nnmail-expiry-target} variable.}
 
-These are the variables you can use to customize its behavior:
+@item read-only
+If this is set to @code{t}, @code{nnmaildir} will treat the articles
+in this maildir as read-only.  This means: articles are not renamed
+from @file{new/} into @file{cur/}; articles are only found in
+@file{new/}, not @file{cur/}; articles are never deleted; articles
+cannot be edited.  @file{new/} is expected to be a symlink to the
+@file{new/} directory of another maildir---e.g., a system-wide mailbox
+containing a mailing list of common interest.  Everything in the
+maildir outside @file{new/} is @emph{not} treated as read-only, so for
+a shared mailbox, you do still need to set up your own maildir (or
+have write permission to the shared mailbox); your maildir just won't
+contain extra copies of the articles.
+
+@item directory-files
+A function with the same interface as @code{directory-files}.  It is
+used to scan the directories in the maildir corresponding to this
+group to find articles.  The default is the function specified by the
+server's @code{directory-files} parameter.
+
+@item distrust-Lines:
+If non-@code{nil}, @code{nnmaildir} will always count the lines of an
+article, rather than use the @code{Lines:} header field.  If
+@code{nil}, the header field will be used if present.
+
+@item always-marks
+A list of mark symbols, such as @code{['(read expire)]}.  Whenever
+Gnus asks @code{nnmaildir} for article marks, @code{nnmaildir} will
+say that all articles have these marks, regardless of whether the
+marks stored in the filesystem say so.  This is a proof-of-concept
+feature that will probably be removed eventually; it ought to be done
+in Gnus proper, or abandoned if it's not worthwhile.
+
+@item never-marks
+A list of mark symbols, such as @code{['(tick expire)]}.  Whenever
+Gnus asks @code{nnmaildir} for article marks, @code{nnmaildir} will
+say that no articles have these marks, regardless of whether the marks
+stored in the filesystem say so.  @code{never-marks} overrides
+@code{always-marks}.  This is a proof-of-concept feature that will
+probably be removed eventually; it ought to be done in Gnus proper, or
+abandoned if it's not worthwhile.
+
+@item nov-cache-size
+An integer specifying the size of the @acronym{NOV} memory cache.  To
+speed things up, @code{nnmaildir} keeps @acronym{NOV} data in memory
+for a limited number of articles in each group.  (This is probably not
+worthwhile, and will probably be removed in the future.)  This
+parameter's value is noticed only the first time a group is seen after
+the server is opened---i.e., when you first start Gnus, typically.
+The @acronym{NOV} cache is never resized until the server is closed
+and reopened.  The default is an estimate of the number of articles
+that would be displayed in the summary buffer: a count of articles
+that are either marked with @code{tick} or not marked with
+@code{read}, plus a little extra.
+@end table
+
+@subsubsection Article identification
+Articles are stored in the @file{cur/} subdirectory of each maildir.
+Each article file is named like @code{uniq:info}, where @code{uniq}
+contains no colons.  @code{nnmaildir} ignores, but preserves, the
+@code{:info} part.  (Other maildir readers typically use this part of
+the filename to store marks.)  The @code{uniq} part uniquely
+identifies the article, and is used in various places in the
+@file{.nnmaildir/} subdirectory of the maildir to store information
+about the corresponding article.  The full pathname of an article is
+available in the variable @code{nnmaildir-article-file-name} after you
+request the article in the summary buffer.
+
+@subsubsection NOV data
+An article identified by @code{uniq} has its @acronym{NOV} data (used
+to generate lines in the summary buffer) stored in
+@code{.nnmaildir/nov/uniq}.  There is no
+@code{nnmaildir-generate-nov-databases} function.  (There isn't much
+need for it---an article's @acronym{NOV} data is updated automatically
+when the article or @code{nnmail-extra-headers} has changed.)  You can
+force @code{nnmaildir} to regenerate the @acronym{NOV} data for a
+single article simply by deleting the corresponding @acronym{NOV}
+file, but @emph{beware}: this will also cause @code{nnmaildir} to
+assign a new article number for this article, which may cause trouble
+with @code{seen} marks, the Agent, and the cache.
+
+@subsubsection Article marks
+An article identified by @code{uniq} is considered to have the mark
+@code{flag} when the file @file{.nnmaildir/marks/flag/uniq} exists.
+When Gnus asks @code{nnmaildir} for a group's marks, @code{nnmaildir}
+looks for such files and reports the set of marks it finds.  When Gnus
+asks @code{nnmaildir} to store a new set of marks, @code{nnmaildir}
+creates and deletes the corresponding files as needed.  (Actually,
+rather than create a new file for each mark, it just creates hard
+links to @file{.nnmaildir/markfile}, to save inodes.)
+
+You can invent new marks by creating a new directory in
+@file{.nnmaildir/marks/}.  You can tar up a maildir and remove it from
+your server, untar it later, and keep your marks.  You can add and
+remove marks yourself by creating and deleting mark files.  If you do
+this while Gnus is running and your @code{nnmaildir} server is open,
+it's best to exit all summary buffers for @code{nnmaildir} groups and
+type @kbd{s} in the group buffer first, and to type @kbd{g} or
+@kbd{M-g} in the group buffer afterwards.  Otherwise, Gnus might not
+pick up the changes, and might undo them.
+
+
+@node Mail Folders
+@subsubsection Mail Folders
+@cindex nnfolder
+@cindex mbox folders
+@cindex mail folders
+
+@code{nnfolder} is a back end for storing each mail group in a
+separate file.  Each file is in the standard Un*x mbox format.
+@code{nnfolder} will add extra headers to keep track of article
+numbers and arrival dates.
+
+@cindex self contained nnfolder servers
+@cindex marks
+When the marks file is used (which it is by default), @code{nnfolder}
+servers have the property that you may backup them using @code{tar} or
+similar, and later be able to restore them into Gnus (by adding the
+proper @code{nnfolder} server) and have all your marks be preserved.
+Marks for a group is usually stored in a file named as the mbox file
+with @code{.mrk} concatenated to it (but see
+@code{nnfolder-marks-file-suffix}) within the @code{nnfolder}
+directory.  Individual @code{nnfolder} groups are also possible to
+backup, use @kbd{G m} to restore the group (after restoring the backup
+into the @code{nnfolder} directory).
+
+Virtual server settings:
 
 @table @code
+@item nnfolder-directory
+@vindex nnfolder-directory
+All the @code{nnfolder} mail boxes will be stored under this
+directory.  The default is the value of @code{message-directory}
+(whose default is @file{~/Mail})
 
-@item nnsoup-tmp-directory
-@vindex nnsoup-tmp-directory
-When @code{nnsoup} unpacks a @sc{soup} packet, it does it in this
-directory.  (@file{/tmp/} by default.)  
+@item nnfolder-active-file
+@vindex nnfolder-active-file
+The name of the active file.  The default is @file{~/Mail/active}.
 
-@item nnsoup-directory
-@vindex nnsoup-directory
-@code{nnsoup} then moves each message and index file to this directory.
-The default is @file{~/SOUP/}.
+@item nnfolder-newsgroups-file
+@vindex nnfolder-newsgroups-file
+The name of the group descriptions file.  @xref{Newsgroups File
+Format}.  The default is @file{~/Mail/newsgroups}
 
-@item nnsoup-replies-directory 
-@vindex nnsoup-replies-directory 
-All replies will be stored in this directory before being packed into a
-reply packet.  The default is @file{~/SOUP/replies/"}.
+@item nnfolder-get-new-mail
+@vindex nnfolder-get-new-mail
+If non-@code{nil}, @code{nnfolder} will read incoming mail.  The
+default is @code{t}
 
-@item nnsoup-replies-format-type
-@vindex nnsoup-replies-format-type
-The @sc{soup} format of the replies packets.  The default is @samp{?n}
-(rnews), and I don't think you should touch that variable.  I probably
-shouldn't even have documented it.  Drats!  Too late!
+@item nnfolder-save-buffer-hook
+@vindex nnfolder-save-buffer-hook
+@cindex backup files
+Hook run before saving the folders.  Note that Emacs does the normal
+backup renaming of files even with the @code{nnfolder} buffers.  If
+you wish to switch this off, you could say something like the
+following in your @file{.emacs} file:
 
-@item nnsoup-replies-index-type
-@vindex nnsoup-replies-index-type
-The index type of the replies packet.  The default is @samp{?n}, which
-means ``none''.  Don't fiddle with this one either!
+@lisp
+(defun turn-off-backup ()
+  (set (make-local-variable 'backup-inhibited) t))
 
-@item nnsoup-active-file
-@vindex nnsoup-active-file
-Where @code{nnsoup} stores lots of information.  This is not an ``active
-file'' in the @code{nntp} sense; it's an Emacs Lisp file.  If you lose
-this file or mess it up in any way, you're dead.  The default is
-@file{~/SOUP/active}.
+(add-hook 'nnfolder-save-buffer-hook 'turn-off-backup)
+@end lisp
 
-@item nnsoup-packer
-@vindex nnsoup-packer
-Format string command for packing a reply @sc{soup} packet.  The default
-is @samp{tar cf - %s | gzip > $HOME/Soupin%d.tgz}. 
+@item nnfolder-delete-mail-hook
+@vindex nnfolder-delete-mail-hook
+Hook run in a buffer narrowed to the message that is to be deleted.
+This function can be used to copy the message to somewhere else, or to
+extract some information from it before removing it.
 
-@item nnsoup-unpacker
-@vindex nnsoup-unpacker
-Format string command for unpacking incoming @sc{soup} packets.  The
-default is @samp{gunzip -c %s | tar xvf -}. 
+@item nnfolder-nov-is-evil
+@vindex nnfolder-nov-is-evil
+If non-@code{nil}, this back end will ignore any @acronym{NOV} files.  The
+default is @code{nil}.
 
-@item nnsoup-packet-directory
-@vindex nnsoup-packet-directory
-Where @code{nnsoup} will look for incoming packets.  The default is
-@file{~/}.  
+@item nnfolder-nov-file-suffix
+@vindex nnfolder-nov-file-suffix
+The extension for @acronym{NOV} files.  The default is @file{.nov}.
 
-@item nnsoup-packet-regexp
-@vindex nnsoup-packet-regexp
-Regular expression matching incoming @sc{soup} packets.  The default is
-@samp{Soupout}.
+@item nnfolder-nov-directory
+@vindex nnfolder-nov-directory
+The directory where the @acronym{NOV} files should be stored.  If
+@code{nil}, @code{nnfolder-directory} is used.
 
-@item nnsoup-always-save
-@vindex nnsoup-always-save
-If non-@code{nil}, save the replies buffer after each posted message.
+@item nnfolder-marks-is-evil
+@vindex nnfolder-marks-is-evil
+If non-@code{nil}, this back end will ignore any @sc{marks} files.  The
+default is @code{nil}.
+
+@item nnfolder-marks-file-suffix
+@vindex nnfolder-marks-file-suffix
+The extension for @sc{marks} files.  The default is @file{.mrk}.
+
+@item nnfolder-marks-directory
+@vindex nnfolder-marks-directory
+The directory where the @sc{marks} files should be stored.  If
+@code{nil}, @code{nnfolder-directory} is used.
 
 @end table
 
 
-@node SOUP Replies
-@subsubsection SOUP Replies
+@findex nnfolder-generate-active-file
+@kindex M-x nnfolder-generate-active-file
+If you have lots of @code{nnfolder}-like files you'd like to read with
+@code{nnfolder}, you can use the @kbd{M-x nnfolder-generate-active-file}
+command to make @code{nnfolder} aware of all likely files in
+@code{nnfolder-directory}.  This only works if you use long file names,
+though.
+
+@node Comparing Mail Back Ends
+@subsubsection Comparing Mail Back Ends
+
+First, just for terminology, the @dfn{back end} is the common word for a
+low-level access method---a transport, if you will, by which something
+is acquired.  The sense is that one's mail has to come from somewhere,
+and so selection of a suitable back end is required in order to get that
+mail within spitting distance of Gnus.
+
+The same concept exists for Usenet itself: Though access to articles is
+typically done by @acronym{NNTP} these days, once upon a midnight dreary, everyone
+in the world got at Usenet by running a reader on the machine where the
+articles lay (the machine which today we call an @acronym{NNTP} server), and
+access was by the reader stepping into the articles' directory spool
+area directly.  One can still select between either the @code{nntp} or
+@code{nnspool} back ends, to select between these methods, if one happens
+actually to live on the server (or can see its spool directly, anyway,
+via NFS).
+
+The goal in selecting a mail back end is to pick one which
+simultaneously represents a suitable way of dealing with the original
+format plus leaving mail in a form that is convenient to use in the
+future.  Here are some high and low points on each:
 
-Just using @code{nnsoup} won't mean that your postings and mailings end
-up in @sc{soup} reply packets automagically.  You have to work a bit
-more for that to happen.
+@table @code
+@item nnmbox
+
+UNIX systems have historically had a single, very common, and well-
+defined format.  All messages arrive in a single @dfn{spool file}, and
+they are delineated by a line whose regular expression matches
+@samp{^From_}.  (My notational use of @samp{_} is to indicate a space,
+to make it clear in this instance that this is not the RFC-specified
+@samp{From:} header.)  Because Emacs and therefore Gnus emanate
+historically from the Unix environment, it is simplest if one does not
+mess a great deal with the original mailbox format, so if one chooses
+this back end, Gnus' primary activity in getting mail from the real spool
+area to Gnus' preferred directory is simply to copy it, with no
+(appreciable) format change in the process.  It is the ``dumbest'' way
+to move mail into availability in the Gnus environment.  This makes it
+fast to move into place, but slow to parse, when Gnus has to look at
+what's where.
+
+@item nnbabyl
+
+Once upon a time, there was the DEC-10 and DEC-20, running operating
+systems called TOPS and related things, and the usual (only?) mail
+reading environment was a thing called Babyl.  I don't know what format
+was used for mail landing on the system, but Babyl had its own internal
+format to which mail was converted, primarily involving creating a
+spool-file-like entity with a scheme for inserting Babyl-specific
+headers and status bits above the top of each message in the file.
+Rmail was Emacs' first mail reader, it was written by Richard Stallman,
+and Stallman came out of that TOPS/Babyl environment, so he wrote Rmail
+to understand the mail files folks already had in existence.  Gnus (and
+VM, for that matter) continue to support this format because it's
+perceived as having some good qualities in those mailer-specific
+headers/status bits stuff.  Rmail itself still exists as well, of
+course, and is still maintained by Stallman.
+
+Both of the above forms leave your mail in a single file on your
+file system, and they must parse that entire file each time you take a
+look at your mail.
+
+@item nnml
+
+@code{nnml} is the back end which smells the most as though you were
+actually operating with an @code{nnspool}-accessed Usenet system.  (In
+fact, I believe @code{nnml} actually derived from @code{nnspool} code,
+lo these years ago.)  One's mail is taken from the original spool file,
+and is then cut up into individual message files, 1:1.  It maintains a
+Usenet-style active file (analogous to what one finds in an INN- or
+CNews-based news system in (for instance) @file{/var/lib/news/active},
+or what is returned via the @samp{NNTP LIST} verb) and also creates
+@dfn{overview} files for efficient group entry, as has been defined for
+@acronym{NNTP} servers for some years now.  It is slower in mail-splitting,
+due to the creation of lots of files, updates to the @code{nnml} active
+file, and additions to overview files on a per-message basis, but it is
+extremely fast on access because of what amounts to the indexing support
+provided by the active file and overviews.
+
+@code{nnml} costs @dfn{inodes} in a big way; that is, it soaks up the
+resource which defines available places in the file system to put new
+files.  Sysadmins take a dim view of heavy inode occupation within
+tight, shared file systems.  But if you live on a personal machine where
+the file system is your own and space is not at a premium, @code{nnml}
+wins big.
+
+It is also problematic using this back end if you are living in a
+FAT16-based Windows world, since much space will be wasted on all these
+tiny files.
+
+@item nnmh
+
+The Rand MH mail-reading system has been around UNIX systems for a very
+long time; it operates by splitting one's spool file of messages into
+individual files, but with little or no indexing support---@code{nnmh}
+is considered to be semantically equivalent to ``@code{nnml} without
+active file or overviews''.  This is arguably the worst choice, because
+one gets the slowness of individual file creation married to the
+slowness of access parsing when learning what's new in one's groups.
+
+@item nnfolder
+
+Basically the effect of @code{nnfolder} is @code{nnmbox} (the first
+method described above) on a per-group basis.  That is, @code{nnmbox}
+itself puts @emph{all} one's mail in one file; @code{nnfolder} provides a
+little bit of optimization to this so that each of one's mail groups has
+a Unix mail box file.  It's faster than @code{nnmbox} because each group
+can be parsed separately, and still provides the simple Unix mail box
+format requiring minimal effort in moving the mail around.  In addition,
+it maintains an ``active'' file making it much faster for Gnus to figure
+out how many messages there are in each separate group.
+
+If you have groups that are expected to have a massive amount of
+messages, @code{nnfolder} is not the best choice, but if you receive
+only a moderate amount of mail, @code{nnfolder} is probably the most
+friendly mail back end all over.
+
+@item nnmaildir
+
+For configuring expiry and other things, @code{nnmaildir} uses
+incompatible group parameters, slightly different from those of other
+mail back ends.
+
+@code{nnmaildir} is largely similar to @code{nnml}, with some notable
+differences.  Each message is stored in a separate file, but the
+filename is unrelated to the article number in Gnus.  @code{nnmaildir}
+also stores the equivalent of @code{nnml}'s overview files in one file
+per article, so it uses about twice as many inodes as @code{nnml}.  (Use
+@code{df -i} to see how plentiful your inode supply is.)  If this slows
+you down or takes up very much space, consider switching to
+@uref{http://www.namesys.com/, ReiserFS} or another non-block-structured
+file system.
+
+Since maildirs don't require locking for delivery, the maildirs you use
+as groups can also be the maildirs your mail is directly delivered to.
+This means you can skip Gnus' mail splitting if your mail is already
+organized into different mailboxes during delivery.  A @code{directory}
+entry in @code{mail-sources} would have a similar effect, but would
+require one set of mailboxes for spooling deliveries (in mbox format,
+thus damaging message bodies), and another set to be used as groups (in
+whatever format you like).  A maildir has a built-in spool, in the
+@code{new/} subdirectory.  Beware that currently, mail moved from
+@code{new/} to @code{cur/} instead of via mail splitting will not
+undergo treatment such as duplicate checking.
+
+@code{nnmaildir} stores article marks for a given group in the
+corresponding maildir, in a way designed so that it's easy to manipulate
+them from outside Gnus.  You can tar up a maildir, unpack it somewhere
+else, and still have your marks.  @code{nnml} also stores marks, but
+it's not as easy to work with them from outside Gnus as with
+@code{nnmaildir}.
+
+@code{nnmaildir} uses a significant amount of memory to speed things up.
+(It keeps in memory some of the things that @code{nnml} stores in files
+and that @code{nnmh} repeatedly parses out of message files.)  If this
+is a problem for you, you can set the @code{nov-cache-size} group
+parameter to something small (0 would probably not work, but 1 probably
+would) to make it use less memory.  This caching will probably be
+removed in the future.
+
+Startup is likely to be slower with @code{nnmaildir} than with other
+back ends.  Everything else is likely to be faster, depending in part
+on your file system.
+
+@code{nnmaildir} does not use @code{nnoo}, so you cannot use @code{nnoo}
+to write an @code{nnmaildir}-derived back end.
 
-@findex nnsoup-set-variables
-The @code{nnsoup-set-variables} command will set the appropriate
-variables to ensure that all your followups and replies end up in the
-@sc{soup} system.
+@end table
 
-In specific, this is what it does:
 
-@lisp
-(setq message-send-news-function 'nnsoup-request-post)
-(setq message-send-mail-function 'nnsoup-request-mail)
-@end lisp
+@node Browsing the Web
+@section Browsing the Web
+@cindex web
+@cindex browsing the web
+@cindex www
+@cindex http
 
-And that's it, really.  If you only want news to go into the @sc{soup}
-system you just use the first line.  If you only want mail to be
-@sc{soup}ed you use the second.
+Web-based discussion forums are getting more and more popular.  On many
+subjects, the web-based forums have become the most important forums,
+eclipsing the importance of mailing lists and news groups.  The reason
+is easy to understand---they are friendly to new users; you just point
+and click, and there's the discussion.  With mailing lists, you have to
+go through a cumbersome subscription procedure, and most people don't
+even know what a news group is.
+
+The problem with this scenario is that web browsers are not very good at
+being newsreaders.  They do not keep track of what articles you've read;
+they do not allow you to score on subjects you're interested in; they do
+not allow off-line browsing; they require you to click around and drive
+you mad in the end.
+
+So---if web browsers suck at reading discussion forums, why not use Gnus
+to do it instead?
+
+Gnus has been getting a bit of a collection of back ends for providing
+interfaces to these sources.
+
+@menu
+* Archiving Mail::
+* Web Searches::                Creating groups from articles that match a string.
+* Slashdot::                    Reading the Slashdot comments.
+* Ultimate::                    The Ultimate Bulletin Board systems.
+* Web Archive::                 Reading mailing list archived on web.
+* RSS::                         Reading RDF site summary.
+* Customizing w3::              Doing stuff to Emacs/w3 from Gnus.
+@end menu
 
+All the web sources require Emacs/w3 and the url library to work.
+
+The main caveat with all these web sources is that they probably won't
+work for a very long time.  Gleaning information from the @acronym{HTML} data
+is guesswork at best, and when the layout is altered, the Gnus back end
+will fail.  If you have reasonably new versions of these back ends,
+though, you should be ok.
+
+One thing all these Web methods have in common is that the Web sources
+are often down, unavailable or just plain too slow to be fun.  In those
+cases, it makes a lot of sense to let the Gnus Agent (@pxref{Gnus
+Unplugged}) handle downloading articles, and then you can read them at
+leisure from your local disk.  No more World Wide Wait for you.
+
+@node Archiving Mail
+@subsection Archiving Mail
+@cindex archiving mail
+@cindex backup of mail
+
+Some of the back ends, notably @code{nnml}, @code{nnfolder}, and
+@code{nnmaildir}, now actually store the article marks with each group.
+For these servers, archiving and restoring a group while preserving
+marks is fairly simple.
+
+(Preserving the group level and group parameters as well still
+requires ritual dancing and sacrifices to the @file{.newsrc.eld} deity
+though.)
+
+To archive an entire @code{nnml}, @code{nnfolder}, or @code{nnmaildir}
+server, take a recursive copy of the server directory.  There is no need
+to shut down Gnus, so archiving may be invoked by @code{cron} or
+similar.  You restore the data by restoring the directory tree, and
+adding a server definition pointing to that directory in Gnus.  The
+@ref{Article Backlog}, @ref{Asynchronous Fetching} and other things
+might interfere with overwriting data, so you may want to shut down Gnus
+before you restore the data.
+
+It is also possible to archive individual @code{nnml},
+@code{nnfolder}, or @code{nnmaildir} groups, while preserving marks.
+For @code{nnml} or @code{nnmaildir}, you copy all files in the group's
+directory.  For @code{nnfolder} you need to copy both the base folder
+file itself (@file{FOO}, say), and the marks file (@file{FOO.mrk} in
+this example).  Restoring the group is done with @kbd{G m} from the Group
+buffer.  The last step makes Gnus notice the new directory.
+@code{nnmaildir} notices the new directory automatically, so @kbd{G m}
+is unnecessary in that case.
 
 @node Web Searches
 @subsection Web Searches
 @cindex nnweb
-@cindex DejaNews
-@cindex Alta Vista
-@cindex InReference
+@cindex Google
+@cindex dejanews
+@cindex gmane
 @cindex Usenet searches
 @cindex searching the Usenet
 
@@ -10835,7 +15540,7 @@ those, like, Web browsers, and you, like, have to, rilly, like, look at
 the commercials, so, like, with Gnus you can do @emph{rad}, rilly,
 searches without having to use a browser.
 
-The @code{nnweb} backend allows an easy interface to the mighty search
+The @code{nnweb} back end allows an easy interface to the mighty search
 engine.  You create an @code{nnweb} group, enter a search pattern, and
 then enter the group and read the articles like you would any normal
 group.  The @kbd{G w} command in the group buffer (@pxref{Foreign
@@ -10848,7 +15553,7 @@ pattern), you are likely to get the articles ordered in a different
 manner.  Not even using duplicate suppression (@pxref{Duplicate
 Suppression}) will help, since @code{nnweb} doesn't even know the
 @code{Message-ID} of the articles before reading them using some search
-engines (DejaNews, for instance).  The only possible way to keep track
+engines (Google, for instance).  The only possible way to keep track
 of which articles you've read is by scoring on the @code{Date}
 header---mark all articles posted before the last date you read the
 group as read.
@@ -10869,8 +15574,8 @@ Virtual server variables:
 @item nnweb-type
 @vindex nnweb-type
 What search engine type is being used.  The currently supported types
-are @code{dejanews}, @code{dejanewsold}, @code{altavista} and
-@code{reference}.
+are @code{google}, @code{dejanews}, and @code{gmane}.  Note that
+@code{dejanews} is an alias to @code{google}.
 
 @item nnweb-search
 @vindex nnweb-search
@@ -10879,28 +15584,28 @@ The search string to feed to the search engine.
 @item nnweb-max-hits
 @vindex nnweb-max-hits
 Advisory maximum number of hits per search to display.  The default is
-100.
+999.
 
 @item nnweb-type-definition
 @vindex nnweb-type-definition
 Type-to-definition alist.  This alist says what @code{nnweb} should do
 with the various search engine types.  The following elements must be
-present: 
+present:
 
 @table @code
 @item article
 Function to decode the article and provide something that Gnus
-understands. 
+understands.
 
 @item map
-Function to create an article number to message header and URL alist. 
+Function to create an article number to message header and URL alist.
 
 @item search
 Function to send the search string to the search engine.
 
 @item address
 The address the aforementioned function should send the search string
-to. 
+to.
 
 @item id
 Format string URL to fetch an article by @code{Message-ID}.
@@ -10909,6403 +15614,10617 @@ Format string URL to fetch an article by @code{Message-ID}.
 @end table
 
 
+@node Slashdot
+@subsection Slashdot
+@cindex Slashdot
+@cindex nnslashdot
 
-@node Mail-To-News Gateways
-@subsection Mail-To-News Gateways
-@cindex mail-to-news gateways
-@cindex gateways
+@uref{http://slashdot.org/, Slashdot} is a popular news site, with
+lively discussion following the news articles.  @code{nnslashdot} will
+let you read this forum in a convenient manner.
 
-If your local @code{nntp} server doesn't allow posting, for some reason
-or other, you can post using one of the numerous mail-to-news gateways.
-The @code{nngateway} backend provides the interface.
+The easiest way to read this source is to put something like the
+following in your @file{~/.gnus.el} file:
 
-Note that you can't read anything from this backend---it can only be
-used to post with.
+@lisp
+(setq gnus-secondary-select-methods
+      '((nnslashdot "")))
+@end lisp
 
-Server variables:
+This will make Gnus query the @code{nnslashdot} back end for new comments
+and groups.  The @kbd{F} command will subscribe each new news article as
+a new Gnus group, and you can read the comments by entering these
+groups.  (Note that the default subscription method is to subscribe new
+groups as zombies.  Other methods are available (@pxref{Subscription
+Methods}).
+
+If you want to remove an old @code{nnslashdot} group, the @kbd{G DEL}
+command is the most handy tool (@pxref{Foreign Groups}).
+
+When following up to @code{nnslashdot} comments (or posting new
+comments), some light @acronym{HTML}izations will be performed.  In
+particular, text quoted with @samp{> } will be quoted with
+@samp{blockquote} instead, and signatures will have @samp{br} added to
+the end of each line.  Other than that, you can just write @acronym{HTML}
+directly into the message buffer.  Note that Slashdot filters out some
+@acronym{HTML} forms.
+
+The following variables can be altered to change its behavior:
 
 @table @code
-@item nngateway-address 
-@vindex nngateway-address 
-This is the address of the mail-to-news gateway.
+@item nnslashdot-threaded
+Whether @code{nnslashdot} should display threaded groups or not.  The
+default is @code{t}.  To be able to display threads, @code{nnslashdot}
+has to retrieve absolutely all comments in a group upon entry.  If a
+threaded display is not required, @code{nnslashdot} will only retrieve
+the comments that are actually wanted by the user.  Threading is nicer,
+but much, much slower than unthreaded.
+
+@item nnslashdot-login-name
+@vindex nnslashdot-login-name
+The login name to use when posting.
+
+@item nnslashdot-password
+@vindex nnslashdot-password
+The password to use when posting.
+
+@item nnslashdot-directory
+@vindex nnslashdot-directory
+Where @code{nnslashdot} will store its files.  The default is
+@file{~/News/slashdot/}.
+
+@item nnslashdot-active-url
+@vindex nnslashdot-active-url
+The @acronym{URL} format string that will be used to fetch the
+information on news articles and comments.  The default is@*
+@samp{http://slashdot.org/search.pl?section=&min=%d}.
+
+@item nnslashdot-comments-url
+@vindex nnslashdot-comments-url
+The @acronym{URL} format string that will be used to fetch comments.
+
+@item nnslashdot-article-url
+@vindex nnslashdot-article-url
+The @acronym{URL} format string that will be used to fetch the news
+article.  The default is
+@samp{http://slashdot.org/article.pl?sid=%s&mode=nocomment}.
+
+@item nnslashdot-threshold
+@vindex nnslashdot-threshold
+The score threshold.  The default is -1.
+
+@item nnslashdot-group-number
+@vindex nnslashdot-group-number
+The number of old groups, in addition to the ten latest, to keep
+updated.  The default is 0.
 
-@item nngateway-header-transformation
-@vindex nngateway-header-transformation
-News headers often have to be transformed in some odd way or other
-for the mail-to-news gateway to accept it.  This variable says what 
-transformation should be called, and defaults to
-@code{nngateway-simple-header-transformation}.  The function is called
-narrowed to the headers to be transformed and with one parameter---the
-gateway address.
+@end table
 
-This default function just inserts a new @code{To} header based on the
-@code{Newsgroups} header and the gateway address.
-For instance, an article with this @code{Newsgroups} header:
 
-@example
-Newsgroups: alt.religion.emacs
-@end example
 
-will get this @code{From} header inserted:
+@node Ultimate
+@subsection Ultimate
+@cindex nnultimate
+@cindex Ultimate Bulletin Board
 
-@example
-To: alt-religion-emacs@@GATEWAY
-@end example
+@uref{http://www.ultimatebb.com/, The Ultimate Bulletin Board} is
+probably the most popular Web bulletin board system used.  It has a
+quite regular and nice interface, and it's possible to get the
+information Gnus needs to keep groups updated.
+
+The easiest way to get started with @code{nnultimate} is to say
+something like the following in the group buffer:  @kbd{B nnultimate RET
+http://www.tcj.com/messboard/ubbcgi/ RET}.  (Substitute the @acronym{URL}
+(not including @samp{Ultimate.cgi} or the like at the end) for a forum
+you're interested in; there's quite a list of them on the Ultimate web
+site.)  Then subscribe to the groups you're interested in from the
+server buffer, and read them from the group buffer.
 
+The following @code{nnultimate} variables can be altered:
+
+@table @code
+@item nnultimate-directory
+@vindex nnultimate-directory
+The directory where @code{nnultimate} stores its files.  The default is@*
+@file{~/News/ultimate/}.
 @end table
 
-So, to use this, simply say something like:
 
-@lisp
-(setq gnus-post-method '(nngateway "GATEWAY.ADDRESS"))
-@end lisp
+@node Web Archive
+@subsection Web Archive
+@cindex nnwarchive
+@cindex Web Archive
 
+Some mailing lists only have archives on Web servers, such as
+@uref{http://www.egroups.com/} and
+@uref{http://www.mail-archive.com/}.  It has a quite regular and nice
+interface, and it's possible to get the information Gnus needs to keep
+groups updated.
 
-@node Combined Groups
-@section Combined Groups
+@findex gnus-group-make-warchive-group
+The easiest way to get started with @code{nnwarchive} is to say
+something like the following in the group buffer: @kbd{M-x
+gnus-group-make-warchive-group RET @var{an_egroup} RET egroups RET
+www.egroups.com RET @var{your@@email.address} RET}.  (Substitute the
+@var{an_egroup} with the mailing list you subscribed, the
+@var{your@@email.address} with your email address.), or to browse the
+back end by @kbd{B nnwarchive RET mail-archive RET}.
 
-Gnus allows combining a mixture of all the other group types into bigger
-groups.
+The following @code{nnwarchive} variables can be altered:
 
-@menu
-* Virtual Groups::     Combining articles from many groups.
-* Kibozed Groups::     Looking through parts of the newsfeed for articles.
-@end menu
+@table @code
+@item nnwarchive-directory
+@vindex nnwarchive-directory
+The directory where @code{nnwarchive} stores its files.  The default is@*
+@file{~/News/warchive/}.
+
+@item nnwarchive-login
+@vindex nnwarchive-login
+The account name on the web server.
+
+@item nnwarchive-passwd
+@vindex nnwarchive-passwd
+The password for your account on the web server.
+@end table
 
+@node RSS
+@subsection RSS
+@cindex nnrss
+@cindex RSS
 
-@node Virtual Groups
-@subsection Virtual Groups
-@cindex nnvirtual
-@cindex virtual groups
+Some web sites have an RDF Site Summary (@acronym{RSS}).
+@acronym{RSS} is a format for summarizing headlines from news related
+sites (such as BBC or CNN).  But basically anything list-like can be
+presented as an @acronym{RSS} feed: weblogs, changelogs or recent
+changes to a wiki (e.g. @url{http://cliki.net/recent-changes.rdf}).
 
-An @dfn{nnvirtual group} is really nothing more than a collection of
-other groups.
+@acronym{RSS} has a quite regular and nice interface, and it's
+possible to get the information Gnus needs to keep groups updated.
 
-For instance, if you are tired of reading many small groups, you can
-put them all in one big group, and then grow tired of reading one
-big, unwieldy group.  The joys of computing!
+@kindex G R (Summary)
+Use @kbd{G R} from the summary buffer to subscribe to a feed---you
+will be prompted for the location of the feed.
 
-You specify @code{nnvirtual} as the method.  The address should be a
-regexp to match component groups.
+An easy way to get started with @code{nnrss} is to say something like
+the following in the group buffer: @kbd{B nnrss RET y}, then
+subscribe to groups.
 
-All marks in the virtual group will stick to the articles in the
-component groups.  So if you tick an article in a virtual group, the
-article will also be ticked in the component group from whence it came.
-(And vice versa---marks from the component groups will also be shown in
-the virtual group.)
+The following @code{nnrss} variables can be altered:
 
-Here's an example @code{nnvirtual} method that collects all Andrea Dworkin
-newsgroups into one, big, happy newsgroup:
+@table @code
+@item nnrss-directory
+@vindex nnrss-directory
+The directory where @code{nnrss} stores its files.  The default is
+@file{~/News/rss/}.
+
+@item nnrss-use-local
+@vindex nnrss-use-local
+@findex nnrss-generate-download-script
+If you set @code{nnrss-use-local} to @code{t}, @code{nnrss} will read
+the feeds from local files in @code{nnrss-directory}.  You can use
+the command @code{nnrss-generate-download-script} to generate a
+download script using @command{wget}.
+@end table
+
+The following code may be helpful, if you want to show the description in
+the summary buffer.
 
 @lisp
-(nnvirtual "^alt\\.fan\\.andrea-dworkin$\\|^rec\\.dworkin.*")
+(add-to-list 'nnmail-extra-headers nnrss-description-field)
+(setq gnus-summary-line-format "%U%R%z%I%(%[%4L: %-15,15f%]%) %s%uX\n")
+
+(defun gnus-user-format-function-X (header)
+  (let ((descr
+         (assq nnrss-description-field (mail-header-extra header))))
+    (if descr (concat "\n\t" (cdr descr)) "")))
 @end lisp
 
-The component groups can be native or foreign; everything should work
-smoothly, but if your computer explodes, it was probably my fault.
+The following code may be useful to open an nnrss url directly from the
+summary buffer.
+@lisp
+(require 'browse-url)
+
+(defun browse-nnrss-url( arg )
+  (interactive "p")
+  (let ((url (assq nnrss-url-field
+                   (mail-header-extra
+                    (gnus-data-header
+                     (assq (gnus-summary-article-number)
+                           gnus-newsgroup-data))))))
+    (if url
+        (progn
+          (browse-url (cdr url))
+          (gnus-summary-mark-as-read-forward 1))
+      (gnus-summary-scroll-up arg))))
+
+(eval-after-load "gnus"
+  #'(define-key gnus-summary-mode-map
+      (kbd "<RET>") 'browse-nnrss-url))
+(add-to-list 'nnmail-extra-headers nnrss-url-field)
+@end lisp
 
-Collecting the same group from several servers might actually be a good
-idea if users have set the Distribution header to limit distribution.
-If you would like to read @samp{soc.motss} both from a server in Japan
-and a server in Norway, you could use the following as the group regexp:
+@node Customizing w3
+@subsection Customizing w3
+@cindex w3
+@cindex html
+@cindex url
+@cindex Netscape
 
-@example
-"^nntp\\+some\\.server\\.jp:soc\\.motss$\\|^nntp\\+some\\.server\\.no:soc\\.motss$"
-@end example
+Gnus uses the url library to fetch web pages and Emacs/w3 to display web
+pages.  Emacs/w3 is documented in its own manual, but there are some
+things that may be more relevant for Gnus users.
 
-(Remember, though, that if you're creating the group with @kbd{G m}, you
-shouldn't double the backslashes, and you should leave off the quote
-characters at the beginning and the end of the string.)
+For instance, a common question is how to make Emacs/w3 follow links
+using the @code{browse-url} functions (which will call some external web
+browser like Netscape).  Here's one way:
 
-This should work kinda smoothly---all articles from both groups should
-end up in this one, and there should be no duplicates.  Threading (and
-the rest) will still work as usual, but there might be problems with the
-sequence of articles.  Sorting on date might be an option here
-(@pxref{Selecting a Group}).
+@lisp
+(eval-after-load "w3"
+  '(progn
+    (fset 'w3-fetch-orig (symbol-function 'w3-fetch))
+    (defun w3-fetch (&optional url target)
+      (interactive (list (w3-read-url-with-default)))
+      (if (eq major-mode 'gnus-article-mode)
+          (browse-url url)
+        (w3-fetch-orig url target)))))
+@end lisp
 
-One limitation, however---all groups included in a virtual
-group have to be alive (i.e., subscribed or unsubscribed).  Killed or
-zombie groups can't be component groups for @code{nnvirtual} groups.
+Put that in your @file{.emacs} file, and hitting links in w3-rendered
+@acronym{HTML} in the Gnus article buffers will use @code{browse-url} to
+follow the link.
 
-@vindex nnvirtual-always-rescan
-If the @code{nnvirtual-always-rescan} is non-@code{nil},
-@code{nnvirtual} will always scan groups for unread articles when
-entering a virtual group.  If this variable is @code{nil} (which is the
-default) and you read articles in a component group after the virtual
-group has been activated, the read articles from the component group
-will show up when you enter the virtual group.  You'll also see this
-effect if you have two virtual groups that have a component group in
-common.  If that's the case, you should set this variable to @code{t}.
-Or you can just tap @code{M-g} on the virtual group every time before
-you enter it---it'll have much the same effect.
 
+@node IMAP
+@section IMAP
+@cindex nnimap
+@cindex @acronym{IMAP}
 
-@node Kibozed Groups
-@subsection Kibozed Groups
-@cindex nnkiboze
-@cindex kibozing
+@acronym{IMAP} is a network protocol for reading mail (or news, or @dots{}),
+think of it as a modernized @acronym{NNTP}.  Connecting to a @acronym{IMAP}
+server is much similar to connecting to a news server, you just
+specify the network address of the server.
 
-@dfn{Kibozing} is defined by @sc{oed} as ``grepping through (parts of)
-the news feed''.  @code{nnkiboze} is a backend that will do this for
-you.  Oh joy!  Now you can grind any @sc{nntp} server down to a halt
-with useless requests!  Oh happiness!
+@acronym{IMAP} has two properties.  First, @acronym{IMAP} can do
+everything that @acronym{POP} can, it can hence be viewed as a
+@acronym{POP++}.  Secondly, @acronym{IMAP} is a mail storage protocol,
+similar to @acronym{NNTP} being a news storage protocol---however,
+@acronym{IMAP} offers more features than @acronym{NNTP} because news
+is more or less read-only whereas mail is read-write.
 
-@kindex G k (Group)
-To create a kibozed group, use the @kbd{G k} command in the group
-buffer. 
+If you want to use @acronym{IMAP} as a @acronym{POP++}, use an imap
+entry in @code{mail-sources}.  With this, Gnus will fetch mails from
+the @acronym{IMAP} server and store them on the local disk.  This is
+not the usage described in this section---@xref{Mail Sources}.
 
-The address field of the @code{nnkiboze} method is, as with
-@code{nnvirtual}, a regexp to match groups to be ``included'' in the
-@code{nnkiboze} group.  That's where most similarities between @code{nnkiboze}
-and @code{nnvirtual} end.
+If you want to use @acronym{IMAP} as a mail storage protocol, use an nnimap
+entry in @code{gnus-secondary-select-methods}.  With this, Gnus will
+manipulate mails stored on the @acronym{IMAP} server.  This is the kind of
+usage explained in this section.
 
-In addition to this regexp detailing component groups, an @code{nnkiboze} group
-must have a score file to say what articles are to be included in
-the group (@pxref{Scoring}).
+A server configuration in @file{~/.gnus.el} with a few @acronym{IMAP}
+servers might look something like the following.  (Note that for
+@acronym{TLS}/@acronym{SSL}, you need external programs and libraries,
+see below.)
 
-@kindex M-x nnkiboze-generate-groups
-@findex nnkiboze-generate-groups
-You must run @kbd{M-x nnkiboze-generate-groups} after creating the
-@code{nnkiboze} groups you want to have.  This command will take time.  Lots of
-time.  Oodles and oodles of time.  Gnus has to fetch the headers from
-all the articles in all the component groups and run them through the
-scoring process to determine if there are any articles in the groups
-that are to be part of the @code{nnkiboze} groups.
+@lisp
+(setq gnus-secondary-select-methods
+      '((nnimap "simpleserver") ; @r{no special configuration}
+        ; @r{perhaps a ssh port forwarded server:}
+        (nnimap "dolk"
+                (nnimap-address "localhost")
+                (nnimap-server-port 1430))
+        ; @r{a UW server running on localhost}
+        (nnimap "barbar"
+                (nnimap-server-port 143)
+                (nnimap-address "localhost")
+                (nnimap-list-pattern ("INBOX" "mail/*")))
+        ; @r{anonymous public cyrus server:}
+        (nnimap "cyrus.andrew.cmu.edu"
+                (nnimap-authenticator anonymous)
+                (nnimap-list-pattern "archive.*")
+                (nnimap-stream network))
+        ; @r{a ssl server on a non-standard port:}
+        (nnimap "vic20"
+                (nnimap-address "vic20.somewhere.com")
+                (nnimap-server-port 9930)
+                (nnimap-stream ssl))))
+@end lisp
 
-Please limit the number of component groups by using restrictive
-regexps.  Otherwise your sysadmin may become annoyed with you, and the
-@sc{nntp} site may throw you off and never let you back in again.
-Stranger things have happened.
+After defining the new server, you can subscribe to groups on the
+server using normal Gnus commands such as @kbd{U} in the Group Buffer
+(@pxref{Subscription Commands}) or via the Server Buffer
+(@pxref{Server Buffer}).
 
-@code{nnkiboze} component groups do not have to be alive---they can be dead,
-and they can be foreign.  No restrictions.
+The following variables can be used to create a virtual @code{nnimap}
+server:
 
-@vindex nnkiboze-directory
-The generation of an @code{nnkiboze} group means writing two files in
-@code{nnkiboze-directory}, which is @file{~/News/} by default.  One
-contains the @sc{nov} header lines for all the articles in the group,
-and the other is an additional @file{.newsrc} file to store information
-on what groups have been searched through to find component articles.
+@table @code
 
-Articles marked as read in the @code{nnkiboze} group will have
-their @sc{nov} lines removed from the @sc{nov} file.
+@item nnimap-address
+@vindex nnimap-address
 
+The address of the remote @acronym{IMAP} server.  Defaults to the virtual
+server name if not specified.
 
-@node Gnus Unplugged
-@section Gnus Unplugged
-@cindex offline
-@cindex unplugged
-@cindex Agent
-@cindex Gnus Agent
-@cindex Gnus Unplugged
+@item nnimap-server-port
+@vindex nnimap-server-port
+Port on server to contact.  Defaults to port 143, or 993 for @acronym{TLS}/@acronym{SSL}.
 
-In olden times (ca. February '88), people used to run their newsreaders
-on big machines with permanent connections to the net.  News transport
-was dealt with by news servers, and all the newsreaders had to do was to
-read news.  Believe it or not.
+Note that this should be an integer, example server specification:
 
-Nowadays most people read news and mail at home, and use some sort of
-modem to connect to the net.  To avoid running up huge phone bills, it
-would be nice to have a way to slurp down all the news and mail, hang up
-the phone, read for several hours, and then upload any responses you
-have to make.  And then you repeat the procedure.
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-server-port 4711))
+@end lisp
 
-Of course, you can use news servers for doing this as well.  I've used
-@code{inn} together with @code{slurp}, @code{pop} and @code{sendmail}
-for some years, but doing that's a bore.  Moving the news server
-functionality up to the newsreader makes sense if you're the only person
-reading news on a machine.
+@item nnimap-list-pattern
+@vindex nnimap-list-pattern
+String or list of strings of mailboxes to limit available groups to.
+This is used when the server has very many mailboxes and you're only
+interested in a few---some servers export your home directory via
+@acronym{IMAP}, you'll probably want to limit the mailboxes to those in
+@file{~/Mail/*} then.
+
+The string can also be a cons of REFERENCE and the string as above, what
+REFERENCE is used for is server specific, but on the University of
+Washington server it's a directory that will be concatenated with the
+mailbox.
+
+Example server specification:
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-list-pattern ("INBOX" "Mail/*" "alt.sex.*"
+                               ("~friend/Mail/" . "list/*"))))
+@end lisp
+
+@item nnimap-stream
+@vindex nnimap-stream
+The type of stream used to connect to your server.  By default, nnimap
+will detect and automatically use all of the below, with the exception
+of @acronym{TLS}/@acronym{SSL}.  (@acronym{IMAP} over
+@acronym{TLS}/@acronym{SSL} is being replaced by STARTTLS, which can
+be automatically detected, but it's not widely deployed yet.)
 
-Using Gnus as an ``offline'' newsreader is quite simple.
+Example server specification:
+
+@lisp
+(nnimap "mail.server.com"
+        (nnimap-stream ssl))
+@end lisp
+
+Please note that the value of @code{nnimap-stream} is a symbol!
 
 @itemize @bullet
 @item
-First, set up Gnus as you would do if you were running it on a machine
-that has full connection to the net.  Go ahead.  I'll still be waiting
-here.
-
+@dfn{gssapi:} Connect with GSSAPI (usually Kerberos 5).  Requires the
+@samp{gsasl} or @samp{imtest} program.
+@item
+@dfn{kerberos4:} Connect with Kerberos 4.  Requires the @samp{imtest} program.
+@item
+@dfn{starttls:} Connect via the STARTTLS extension (similar to
+@acronym{TLS}/@acronym{SSL}).  Requires the external library @samp{starttls.el} and program
+@samp{starttls}.
+@item
+@dfn{tls:} Connect through @acronym{TLS}.  Requires GNUTLS (the program
+@samp{gnutls-cli}).
 @item
-Then, put the following magical incantation at the end of your
-@file{.gnus.el} file:
+@dfn{ssl:} Connect through @acronym{SSL}.  Requires OpenSSL (the program
+@samp{openssl}) or SSLeay (@samp{s_client}).
+@item
+@dfn{shell:} Use a shell command to start @acronym{IMAP} connection.
+@item
+@dfn{network:} Plain, TCP/IP network connection.
+@end itemize
+
+@vindex imap-kerberos4-program
+The @samp{imtest} program is shipped with Cyrus IMAPD.  If you're
+using @samp{imtest} from Cyrus IMAPD < 2.0.14 (which includes version
+1.5.x and 1.6.x) you need to frob @code{imap-process-connection-type}
+to make @code{imap.el} use a pty instead of a pipe when communicating
+with @samp{imtest}.  You will then suffer from a line length
+restrictions on @acronym{IMAP} commands, which might make Gnus seem to hang
+indefinitely if you have many articles in a mailbox.  The variable
+@code{imap-kerberos4-program} contain parameters to pass to the imtest
+program.
+
+For @acronym{TLS} connection, the @code{gnutls-cli} program from GNUTLS is
+needed.  It is available from
+@uref{http://www.gnu.org/software/gnutls/}.
+
+@vindex imap-gssapi-program
+This parameter specifies a list of command lines that invoke a GSSAPI
+authenticated @acronym{IMAP} stream in a subshell.  They are tried
+sequentially until a connection is made, or the list has been
+exhausted.  By default, @samp{gsasl} from GNU SASL, available from
+@uref{http://www.gnu.org/software/gsasl/}, and the @samp{imtest}
+program from Cyrus IMAPD (see @code{imap-kerberos4-program}), are
+tried.
+
+@vindex imap-ssl-program
+For @acronym{SSL} connections, the OpenSSL program is available from
+@uref{http://www.openssl.org/}.  OpenSSL was formerly known as SSLeay,
+and nnimap support it too---although the most recent versions of
+SSLeay, 0.9.x, are known to have serious bugs making it
+useless.  Earlier versions, especially 0.8.x, of SSLeay are known to
+work.  The variable @code{imap-ssl-program} contain parameters to pass
+to OpenSSL/SSLeay.
+
+@vindex imap-shell-program
+@vindex imap-shell-host
+For @acronym{IMAP} connections using the @code{shell} stream, the variable
+@code{imap-shell-program} specify what program to call.
+
+@item nnimap-authenticator
+@vindex nnimap-authenticator
+
+The authenticator used to connect to the server.  By default, nnimap
+will use the most secure authenticator your server is capable of.
+
+Example server specification:
 
 @lisp
-(gnus-agentize)
+(nnimap "mail.server.com"
+        (nnimap-authenticator anonymous))
 @end lisp
-@end itemize
 
-That's it.  Gnus is now an ``offline'' newsreader.
+Please note that the value of @code{nnimap-authenticator} is a symbol!
 
-Of course, to use it as such, you have to learn a few new commands.
+@itemize @bullet
+@item
+@dfn{gssapi:} GSSAPI (usually kerberos 5) authentication.  Requires
+external program @code{gsasl} or @code{imtest}.
+@item
+@dfn{kerberos4:} Kerberos 4 authentication.  Requires external program
+@code{imtest}.
+@item
+@dfn{digest-md5:} Encrypted username/password via DIGEST-MD5.  Requires
+external library @code{digest-md5.el}.
+@item
+@dfn{cram-md5:} Encrypted username/password via CRAM-MD5.
+@item
+@dfn{login:} Plain-text username/password via LOGIN.
+@item
+@dfn{anonymous:} Login as ``anonymous'', supplying your email address as password.
+@end itemize
 
-@menu
-* Agent Basics::           How it all is supposed to work.
-* Agent Categories::       How to tell the Gnus Agent what to download.
-* Agent Commands::         New commands for all the buffers.
-* Outgoing Messages::      What happens when you post/mail something?
-* Agent Variables::        Customizing is fun.
-* Example Setup::          An example @file{.gnus.el} file for offline people.
-* Batching Agents::        How to fetch news from a @code{cron} job.
-@end menu
+@item nnimap-expunge-on-close
+@cindex expunging
+@vindex nnimap-expunge-on-close
+Unlike Parmenides the @acronym{IMAP} designers have decided things that
+don't exist actually do exist.  More specifically, @acronym{IMAP} has
+this concept of marking articles @code{Deleted} which doesn't actually
+delete them, and this (marking them @code{Deleted}, that is) is what
+nnimap does when you delete an article in Gnus (with @kbd{B DEL} or
+similar).
+
+Since the articles aren't really removed when we mark them with the
+@code{Deleted} flag we'll need a way to actually delete them.  Feel like
+running in circles yet?
+
+Traditionally, nnimap has removed all articles marked as @code{Deleted}
+when closing a mailbox but this is now configurable by this server
+variable.
 
+The possible options are:
 
-@node Agent Basics
-@subsection Agent Basics
+@table @code
 
-First, let's get some terminology out of the way.
+@item always
+The default behavior, delete all articles marked as ``Deleted'' when
+closing a mailbox.
+@item never
+Never actually delete articles.  Currently there is no way of showing
+the articles marked for deletion in nnimap, but other @acronym{IMAP} clients
+may allow you to do this.  If you ever want to run the EXPUNGE command
+manually, @xref{Expunging mailboxes}.
+@item ask
+When closing mailboxes, nnimap will ask if you wish to expunge deleted
+articles or not.
 
-The Gnus Agent is said to be @dfn{unplugged} when you have severed the
-connection to the net (and notified the Agent that this is the case).
-When the connection to the net is up again (and Gnus knows this), the
-Agent is @dfn{plugged}.
+@end table
 
-The @dfn{local} machine is the one you're running on, and which isn't
-connected to the net continously.
+@item nnimap-importantize-dormant
+@vindex nnimap-importantize-dormant
 
-@dfn{Downloading} means fetching things from the net to your local
-machine.  @dfn{Uploading} is doing the opposite.
+If non-@code{nil} (the default), marks dormant articles as ticked (as
+well), for other @acronym{IMAP} clients.  Within Gnus, dormant articles will
+naturally still (only) be marked as dormant.  This is to make dormant
+articles stand out, just like ticked articles, in other @acronym{IMAP}
+clients.  (In other words, Gnus has two ``Tick'' marks and @acronym{IMAP}
+has only one.)
 
-Let's take a typical Gnus session using the Agent.
+Probably the only reason for frobing this would be if you're trying
+enable per-user persistent dormant flags, using something like:
 
-@itemize @bullet
+@lisp
+(setcdr (assq 'dormant nnimap-mark-to-flag-alist)
+        (format "gnus-dormant-%s" (user-login-name)))
+(setcdr (assq 'dormant nnimap-mark-to-predicate-alist)
+        (format "KEYWORD gnus-dormant-%s" (user-login-name)))
+@end lisp
 
-@item
-You start Gnus with @code{gnus-unplugged}.  This brings up the Gnus
-Agent in a disconnected state.  You can read all the news that you have
-already fetched while in this mode.
+In this case, you would not want the per-user dormant flag showing up
+as ticked for other users.
 
-@item
-You then decide to see whether any new news has arrived.  You connect
-your machine to the net (using PPP or whatever), and then hit @kbd{J j}
-to make Gnus become @dfn{plugged}.
+@item nnimap-expunge-search-string
+@cindex expunging
+@vindex nnimap-expunge-search-string
 
-@item
-You can then read the new news immediately, or you can download the news
-onto your local machine.  If you want to do the latter, you press @kbd{J
-s} to fetch all the eligible articles in all the groups.  (To let Gnus
-know which articles you want to download, @pxref{Agent Categories}.)
+This variable contain the @acronym{IMAP} search command sent to server when
+searching for articles eligible for expiring.  The default is
+@code{"UID %s NOT SINCE %s"}, where the first @code{%s} is replaced by
+UID set and the second @code{%s} is replaced by a date.
 
-@item
-After fetching the articles, you press @kbd{J j} to make Gnus become
-unplugged again, and you shut down the PPP thing (or whatever).  And
-then you read the news offline.
+Probably the only useful value to change this to is
+@code{"UID %s NOT SENTSINCE %s"}, which makes nnimap use the Date: in
+messages instead of the internal article date.  See section 6.4.4 of
+RFC 2060 for more information on valid strings.
 
-@item
-And then you go to step 2.
-@end itemize
+@item nnimap-authinfo-file
+@vindex nnimap-authinfo-file
 
-Here are some things you should do the first time (or so) that you use
-the Agent.
+A file containing credentials used to log in on servers.  The format is
+(almost) the same as the @code{ftp} @file{~/.netrc} file.  See the
+variable @code{nntp-authinfo-file} for exact syntax; also see
+@ref{NNTP}.
 
-@itemize @bullet
+@item nnimap-need-unselect-to-notice-new-mail
+@vindex nnimap-need-unselect-to-notice-new-mail
 
-@item
-Decide which servers should be covered by the Agent.  If you have a mail
-backend, it would probably be nonsensical to have it covered by the
-Agent.  Go to the server buffer (@kbd{^} in the group buffer) and press
-@kbd{J a} the server (or servers) that you wish to have covered by the
-Agent (@pxref{Server Agent Commands}).  This will typically be only the
-primary select method, which is listed on the bottom in the buffer.
+Unselect mailboxes before looking for new mail in them.  Some servers
+seem to need this under some circumstances; it was reported that
+Courier 1.7.1 did.
 
-@item
-Decide on download policy.  @xref{Agent Categories}
+@end table
 
-@item
-Uhm... that's it.
-@end itemize
+@menu
+* Splitting in IMAP::           Splitting mail with nnimap.
+* Expiring in IMAP::            Expiring mail with nnimap.
+* Editing IMAP ACLs::           Limiting/enabling other users access to a mailbox.
+* Expunging mailboxes::         Equivalent of a ``compress mailbox'' button.
+* A note on namespaces::        How to (not) use @acronym{IMAP} namespace in Gnus.
+* Debugging IMAP::              What to do when things don't work.
+@end menu
 
 
-@node Agent Categories
-@subsection Agent Categories
 
-One of the main reasons to integrate the news transport layer into the
-newsreader is to allow greater control over what articles to download.
-There's not much point in downloading huge amounts of articles, just to
-find out that you're not interested in reading any of them.  It's better
-to be somewhat more conservative in choosing what to download, and then
-mark the articles for downloading manually if it should turn out that
-you're interested in the articles anyway.
+@node Splitting in IMAP
+@subsection Splitting in IMAP
+@cindex splitting imap mail
 
-The main way to control what is to be downloaded is to create a
-@dfn{category} and then assign some (or all) groups to this category. 
-Gnus has its own buffer for creating and managing categories.
+Splitting is something Gnus users have loved and used for years, and now
+the rest of the world is catching up.  Yeah, dream on, not many
+@acronym{IMAP} servers have server side splitting and those that have
+splitting seem to use some non-standard protocol.  This means that
+@acronym{IMAP} support for Gnus has to do its own splitting.
 
-@menu
-* Category Syntax::       What a category looks like.
-* The Category Buffer::   A buffer for maintaining categories.
-* Category Variables::    Customize'r'Us.
-@end menu
+And it does.
 
+(Incidentally, people seem to have been dreaming on, and Sieve has
+gaining a market share and is supported by several IMAP servers.
+Fortunately, Gnus support it too, @xref{Sieve Commands}.)
 
-@node Category Syntax
-@subsubsection Category Syntax
+Here are the variables of interest:
 
-A category consists of two things.
+@table @code
 
-@enumerate
-@item
-A predicate which (generally) gives a rough outline of which articles
-are eligible for downloading; and
+@item nnimap-split-crosspost
+@cindex splitting, crosspost
+@cindex crosspost
+@vindex nnimap-split-crosspost
 
-@item
-a score rule which (generally) gives you a finer granularity when
-deciding what articles to download.  (Note that this @dfn{download
-score} is wholly unrelated to normal scores.)
-@end enumerate
+If non-@code{nil}, do crossposting if several split methods match the
+mail.  If @code{nil}, the first match in @code{nnimap-split-rule}
+found will be used.
 
-A predicate consists of predicates with logical operators sprinkled in
-between.
+Nnmail equivalent: @code{nnmail-crosspost}.
 
-Perhaps some examples are in order.
+@item nnimap-split-inbox
+@cindex splitting, inbox
+@cindex inbox
+@vindex nnimap-split-inbox
 
-Here's a simple predicate.  (It's the default predicate, in fact, used
-for all groups that don't belong to any other category.)
+A string or a list of strings that gives the name(s) of @acronym{IMAP}
+mailboxes to split from.  Defaults to @code{nil}, which means that
+splitting is disabled!
 
 @lisp
-short
+(setq nnimap-split-inbox
+      '("INBOX" ("~/friend/Mail" . "lists/*") "lists.imap"))
 @end lisp
 
-Quite simple, eh?  This predicate is true if and only if the article is
-short (for some value of ``short'').
+No nnmail equivalent.
 
-Here's a more complex predicate:
+@item nnimap-split-rule
+@cindex splitting, rules
+@vindex nnimap-split-rule
+
+New mail found in @code{nnimap-split-inbox} will be split according to
+this variable.
+
+This variable contains a list of lists, where the first element in the
+sublist gives the name of the @acronym{IMAP} mailbox to move articles
+matching the regexp in the second element in the sublist.  Got that?
+Neither did I, we need examples.
 
 @lisp
-(or high
-    (and
-     (not low)
-     (not long)))
+(setq nnimap-split-rule
+      '(("INBOX.nnimap"
+         "^Sender: owner-nnimap@@vic20.globalcom.se")
+        ("INBOX.junk"    "^Subject:.*MAKE MONEY")
+        ("INBOX.private" "")))
 @end lisp
 
-This means that an article should be downloaded if it has a high score,
-or if the score is not low and the article is not long.  You get the
-drift.
+This will put all articles from the nnimap mailing list into mailbox
+INBOX.nnimap, all articles containing MAKE MONEY in the Subject: line
+into INBOX.junk and everything else in INBOX.private.
 
-The available logical operators are @code{or}, @code{and} and
-@code{not}.  (If you prefer, you can use the more ``C''-ish operators
-@samp{|}, @code{&} and @code{!} instead.)
+The first string may contain @samp{\\1} forms, like the ones used by
+replace-match to insert sub-expressions from the matched text.  For
+instance:
 
-The following predicates are pre-defined, but if none of these fit what
-you want to do, you can write your own.
+@lisp
+("INBOX.lists.\\1"     "^Sender: owner-\\([a-z-]+\\)@@")
+@end lisp
 
-@table @code
-@item short
-True iff the article is shorter than @code{gnus-agent-short-article}
-lines; default 100.
+The first element can also be the symbol @code{junk} to indicate that
+matching messages should simply be deleted.  Use with care.
 
-@item long
-True iff the article is longer than @code{gnus-agent-long-article}
-lines; default 200.
+The second element can also be a function.  In that case, it will be
+called with the first element of the rule as the argument, in a buffer
+containing the headers of the article.  It should return a
+non-@code{nil} value if it thinks that the mail belongs in that group.
 
-@item low
-True iff the article has a download score less than
-@code{gnus-agent-low-score}; default 0.
+Nnmail users might recollect that the last regexp had to be empty to
+match all articles (like in the example above).  This is not required in
+nnimap.  Articles not matching any of the regexps will not be moved out
+of your inbox.  (This might affect performance if you keep lots of
+unread articles in your inbox, since the splitting code would go over
+them every time you fetch new mail.)
 
-@item high
-True iff the article has a download score greater than
-@code{gnus-agent-high-score}; default 0.
+These rules are processed from the beginning of the alist toward the
+end.  The first rule to make a match will ``win'', unless you have
+crossposting enabled.  In that case, all matching rules will ``win''.
 
-@item spam
-True iff the Gnus Agent guesses that the article is spam.  The
-heuristics may change over time, but at present it just computes a
-checksum and sees whether articles match.
+This variable can also have a function as its value, the function will
+be called with the headers narrowed and should return a group where it
+thinks the article should be split to.  See @code{nnimap-split-fancy}.
 
-@item true
-Always true.
+The splitting code tries to create mailboxes if it needs to.
 
-@item false
-Always false.
-@end table
+To allow for different split rules on different virtual servers, and
+even different split rules in different inboxes on the same server,
+the syntax of this variable have been extended along the lines of:
 
-If you want to create your own predicate function, here's what you have
-to know:  The functions are called with no parameters, but the
-@code{gnus-headers} and @code{gnus-score} dynamic variables are bound to
-useful values.
+@lisp
+(setq nnimap-split-rule
+      '(("my1server"    (".*" (("ding"    "ding@@gnus.org")
+                               ("junk"    "From:.*Simon"))))
+        ("my2server"    ("INBOX" nnimap-split-fancy))
+        ("my[34]server" (".*" (("private" "To:.*Simon")
+                               ("junk"    my-junk-func))))))
+@end lisp
 
-Now, the syntax of the download score is the same as the syntax of
-normal score files, except that all elements that require actually
-seeing the article itself are verboten.  This means that only the
-following headers can be scored on: @code{From}, @code{Subject},
-@code{Date}, @code{Xref}, @code{Lines}, @code{Chars}, @code{Message-ID},
-and @code{References}.
+The virtual server name is in fact a regexp, so that the same rules
+may apply to several servers.  In the example, the servers
+@code{my3server} and @code{my4server} both use the same rules.
+Similarly, the inbox string is also a regexp.  The actual splitting
+rules are as before, either a function, or a list with group/regexp or
+group/function elements.
 
+Nnmail equivalent: @code{nnmail-split-methods}.
 
-@node The Category Buffer
-@subsubsection The Category Buffer
+@item nnimap-split-predicate
+@cindex splitting
+@vindex nnimap-split-predicate
 
-You'd normally do all category maintenance from the category buffer.
-When you enter it for the first time (with the @kbd{J c} command from
-the group buffer), you'll only see the @code{default} category.
+Mail matching this predicate in @code{nnimap-split-inbox} will be
+split, it is a string and the default is @samp{UNSEEN UNDELETED}.
 
-The following commands are available in this buffer:
+This might be useful if you use another @acronym{IMAP} client to read mail in
+your inbox but would like Gnus to split all articles in the inbox
+regardless of readedness.  Then you might change this to
+@samp{UNDELETED}.
 
-@table @kbd
-@item q
-@kindex q (Category)
-@findex gnus-category-exit
-Return to the group buffer (@code{gnus-category-exit}).
+@item nnimap-split-fancy
+@cindex splitting, fancy
+@findex nnimap-split-fancy
+@vindex nnimap-split-fancy
 
-@item k
-@kindex k (Category)
-@findex gnus-category-kill
-Kill the current category (@code{gnus-category-kill}).
+It's possible to set @code{nnimap-split-rule} to
+@code{nnmail-split-fancy} if you want to use fancy
+splitting.  @xref{Fancy Mail Splitting}.
 
-@item c
-@kindex c (Category)
-@findex gnus-category-copy
-Copy the current category (@code{gnus-category-copy}).
+However, to be able to have different fancy split rules for nnmail and
+nnimap back ends you can set @code{nnimap-split-rule} to
+@code{nnimap-split-fancy} and define the nnimap specific fancy split
+rule in @code{nnimap-split-fancy}.
 
-@item a
-@kindex a (Category)
-@findex gnus-category-add
-Add a new category (@code{gnus-category-add}).
+Example:
 
-@item p
-@kindex p (Category)
-@findex gnus-category-edit-predicate
-Edit the predicate of the current category
-(@code{gnus-category-edit-predicate}).
+@lisp
+(setq nnimap-split-rule 'nnimap-split-fancy
+      nnimap-split-fancy ...)
+@end lisp
 
-@item g
-@kindex g (Category)
-@findex gnus-category-edit-groups
-Edit the list of groups belonging to the current category
-(@code{gnus-category-edit-groups}).
+Nnmail equivalent: @code{nnmail-split-fancy}.
 
-@item s
-@kindex s (Category)
-@findex gnus-category-edit-score
-Edit the download score rule of the current category
-(@code{gnus-category-edit-score}).
+@item nnimap-split-download-body
+@findex nnimap-split-download-body
+@vindex nnimap-split-download-body
 
-@item l
-@kindex l (Category)
-@findex gnus-category-list
-List all the categories (@code{gnus-category-list}).
-@end table
+Set to non-@code{nil} to download entire articles during splitting.
+This is generally not required, and will slow things down
+considerably.  You may need it if you want to use an advanced
+splitting function that analyses the body to split the article.
 
+@end table
 
-@node Category Variables
-@subsubsection Category Variables
+@node Expiring in IMAP
+@subsection Expiring in IMAP
+@cindex expiring imap mail
+
+Even though @code{nnimap} is not a proper @code{nnmail} derived back
+end, it supports most features in regular expiring (@pxref{Expiring
+Mail}).  Unlike splitting in @acronym{IMAP} (@pxref{Splitting in
+IMAP}) it does not clone the @code{nnmail} variables (i.e., creating
+@var{nnimap-expiry-wait}) but reuse the @code{nnmail} variables.  What
+follows below are the variables used by the @code{nnimap} expiry
+process.
+
+A note on how the expire mark is stored on the @acronym{IMAP} server is
+appropriate here as well.  The expire mark is translated into a
+@code{imap} client specific mark, @code{gnus-expire}, and stored on the
+message.  This means that likely only Gnus will understand and treat
+the @code{gnus-expire} mark properly, although other clients may allow
+you to view client specific flags on the message.  It also means that
+your server must support permanent storage of client specific flags on
+messages.  Most do, fortunately.
 
 @table @code
-@item gnus-category-mode-hook
-@vindex gnus-category-mode-hook
-Hook run in category buffers.
 
-@item gnus-category-line-format
-@vindex gnus-category-line-format
-Format of the lines in the category buffer (@pxref{Formatting
-Variables}).  Legal elements are:
+@item nnmail-expiry-wait
+@item nnmail-expiry-wait-function
 
-@table @samp
-@item c
-The name of the category.
+These variables are fully supported.  The expire value can be a
+number, the symbol @code{immediate} or @code{never}.
+
+@item nnmail-expiry-target
+
+This variable is supported, and internally implemented by calling the
+@code{nnmail} functions that handle this.  It contains an optimization
+that if the destination is a @acronym{IMAP} group on the same server, the
+article is copied instead of appended (that is, uploaded again).
 
-@item g
-The number of groups in the category.
 @end table
 
-@item gnus-category-mode-line-format
-@vindex gnus-category-mode-line-format
-Format of the category mode line.
+@node Editing IMAP ACLs
+@subsection Editing IMAP ACLs
+@cindex editing imap acls
+@cindex Access Control Lists
+@cindex Editing @acronym{IMAP} ACLs
+@kindex G l (Group)
+@findex gnus-group-nnimap-edit-acl
 
-@item gnus-agent-short-article 
-@vindex gnus-agent-short-article 
-Articles that have fewer lines than this are short.  Default 100.
+ACL stands for Access Control List.  ACLs are used in @acronym{IMAP} for
+limiting (or enabling) other users access to your mail boxes.  Not all
+@acronym{IMAP} servers support this, this function will give an error if it
+doesn't.
 
-@item gnus-agent-long-article 
-@vindex gnus-agent-long-article 
-Articles that have more lines than this are long.  Default 200.
+To edit an ACL for a mailbox, type @kbd{G l}
+(@code{gnus-group-edit-nnimap-acl}) and you'll be presented with an ACL
+editing window with detailed instructions.
 
-@item gnus-agent-low-score 
-@vindex gnus-agent-low-score 
-Articles that have a score lower than this have a low score.  Default
-0. 
+Some possible uses:
 
-@item gnus-agent-high-score 
-@vindex gnus-agent-high-score 
-Articles that have a score higher than this have a high score.  Default
-0. 
+@itemize @bullet
+@item
+Giving ``anyone'' the ``lrs'' rights (lookup, read, keep seen/unseen flags)
+on your mailing list mailboxes enables other users on the same server to
+follow the list without subscribing to it.
+@item
+At least with the Cyrus server, you are required to give the user
+``anyone'' posting ("p") capabilities to have ``plussing'' work (that is,
+mail sent to user+mailbox@@domain ending up in the @acronym{IMAP} mailbox
+INBOX.mailbox).
+@end itemize
 
-@end table
+@node Expunging mailboxes
+@subsection Expunging mailboxes
+@cindex expunging
+
+@cindex expunge
+@cindex manual expunging
+@kindex G x (Group)
+@findex gnus-group-nnimap-expunge
+
+If you're using the @code{never} setting of @code{nnimap-expunge-on-close},
+you may want the option of expunging all deleted articles in a mailbox
+manually.  This is exactly what @kbd{G x} does.
+
+Currently there is no way of showing deleted articles, you can just
+delete them.
+
+@node A note on namespaces
+@subsection A note on namespaces
+@cindex IMAP namespace
+@cindex namespaces
+
+The @acronym{IMAP} protocol has a concept called namespaces, described
+by the following text in the RFC:
+
+@display
+5.1.2.  Mailbox Namespace Naming Convention
+
+   By convention, the first hierarchical element of any mailbox name
+   which begins with "#" identifies the "namespace" of the remainder of
+   the name.  This makes it possible to disambiguate between different
+   types of mailbox stores, each of which have their own namespaces.
+
+      For example, implementations which offer access to USENET
+      newsgroups MAY use the "#news" namespace to partition the USENET
+      newsgroup namespace from that of other mailboxes.  Thus, the
+      comp.mail.misc newsgroup would have an mailbox name of
+      "#news.comp.mail.misc", and the name "comp.mail.misc" could refer
+      to a different object (e.g. a user's private mailbox).
+@end display
+
+While there is nothing in this text that warrants concern for the
+@acronym{IMAP} implementation in Gnus, some servers use namespace
+prefixes in a way that does not work with how Gnus uses mailbox names.
+
+Specifically, University of Washington's @acronym{IMAP} server uses
+mailbox names like @code{#driver.mbx/read-mail} which are valid only
+in the @sc{create} and @sc{append} commands.  After the mailbox is
+created (or a messages is appended to a mailbox), it must be accessed
+without the namespace prefix, i.e. @code{read-mail}.  Since Gnus do
+not make it possible for the user to guarantee that user entered
+mailbox names will only be used with the CREATE and APPEND commands,
+you should simply not use the namespace prefixed mailbox names in
+Gnus.
+
+See the UoW IMAPD documentation for the @code{#driver.*/} prefix
+for more information on how to use the prefixes.  They are a power
+tool and should be used only if you are sure what the effects are.
+
+@node Debugging IMAP
+@subsection Debugging IMAP
+@cindex IMAP debugging
+@cindex protocol dump (IMAP)
+
+@acronym{IMAP} is a complex protocol, more so than @acronym{NNTP} or
+@acronym{POP3}.  Implementation bugs are not unlikely, and we do our
+best to fix them right away.  If you encounter odd behaviour, chances
+are that either the server or Gnus is buggy.
+
+If you are familiar with network protocols in general, you will
+probably be able to extract some clues from the protocol dump of the
+exchanges between Gnus and the server.  Even if you are not familiar
+with network protocols, when you include the protocol dump in
+@acronym{IMAP}-related bug reports you are helping us with data
+critical to solving the problem.  Therefore, we strongly encourage you
+to include the protocol dump when reporting IMAP bugs in Gnus.
+
+
+@vindex imap-log
+Because the protocol dump, when enabled, generates lots of data, it is
+disabled by default.  You can enable it by setting @code{imap-log} as
+follows: 
 
+@lisp
+(setq imap-log t)
+@end lisp
 
-@node Agent Commands
-@subsection Agent Commands
+This instructs the @code{imap.el} package to log any exchanges with
+the server.  The log is stored in the buffer @samp{*imap-log*}.  Look
+for error messages, which sometimes are tagged with the keyword
+@code{BAD} - but when submitting a bug, make sure to include all the
+data.
 
-All the Gnus Agent commands are on the @kbd{J} submap.  The @kbd{J j}
-(@code{gnus-agent-toggle-plugged} command works in all modes, and
-toggles the plugged/unplugged state of the Gnus Agent.
+@node Other Sources
+@section Other Sources
 
+Gnus can do more than just read news or mail.  The methods described
+below allow Gnus to view directories and files as if they were
+newsgroups.
 
 @menu
-* Group Agent Commands::
-* Summary Agent Commands::
-* Server Agent Commands::
+* Directory Groups::            You can read a directory as if it was a newsgroup.
+* Anything Groups::             Dired?  Who needs dired?
+* Document Groups::             Single files can be the basis of a group.
+* SOUP::                        Reading @sc{soup} packets ``offline''.
+* Mail-To-News Gateways::       Posting articles via mail-to-news gateways.
 @end menu
 
-You can run a complete batch fetch from the command line with the
-following incantation:
 
-@cindex gnus-agent-batch-fetch
-@example
-$ emacs -batch -l ~/.gnus.el -f gnus-agent-batch-fetch
-@end example
+@node Directory Groups
+@subsection Directory Groups
+@cindex nndir
+@cindex directory groups
 
+If you have a directory that has lots of articles in separate files in
+it, you might treat it as a newsgroup.  The files have to have numerical
+names, of course.
 
+This might be an opportune moment to mention @code{ange-ftp} (and its
+successor @code{efs}), that most wonderful of all wonderful Emacs
+packages.  When I wrote @code{nndir}, I didn't think much about it---a
+back end to read directories.  Big deal.
 
-@node Group Agent Commands
-@subsubsection Group Agent Commands
+@code{ange-ftp} changes that picture dramatically.  For instance, if you
+enter the @code{ange-ftp} file name
+@file{/ftp.hpc.uh.edu:/pub/emacs/ding-list/} as the directory name,
+@code{ange-ftp} or @code{efs} will actually allow you to read this
+directory over at @samp{sina} as a newsgroup.  Distributed news ahoy!
 
-@table @kbd
-@item J u 
-@kindex J u (Agent Group)
-@findex gnus-agent-fetch-groups
-Fetch all eligible articles in the current group
-(@code{gnus-agent-fetch-groups}).
+@code{nndir} will use @acronym{NOV} files if they are present.
 
-@item J c
-@kindex J c (Agent Group)
-@findex gnus-enter-category-buffer
-Enter the Agent category buffer (@code{gnus-enter-category-buffer}).
+@code{nndir} is a ``read-only'' back end---you can't delete or expire
+articles with this method.  You can use @code{nnmh} or @code{nnml} for
+whatever you use @code{nndir} for, so you could switch to any of those
+methods if you feel the need to have a non-read-only @code{nndir}.
 
-@item J s
-@kindex J s (Agent Group)
-@findex gnus-agent-fetch-session
-Fetch all eligible articles in all groups
-(@code{gnus-agent-fetch-session}).
 
-@item J S
-@kindex J S (Agent Group)
-@findex gnus-group-send-drafts
-Send all sendable messages in the draft group
-(@code{gnus-agent-fetch-session}).  @xref{Drafts}
+@node Anything Groups
+@subsection Anything Groups
+@cindex nneething
 
-@item J a
-@kindex J a (Agent Group)
-@findex gnus-agent-add-group
-Add the current group to an Agent category
-(@code{gnus-agent-add-group}).
+From the @code{nndir} back end (which reads a single spool-like
+directory), it's just a hop and a skip to @code{nneething}, which
+pretends that any arbitrary directory is a newsgroup.  Strange, but
+true.
 
-@end table
+When @code{nneething} is presented with a directory, it will scan this
+directory and assign article numbers to each file.  When you enter such
+a group, @code{nneething} must create ``headers'' that Gnus can use.
+After all, Gnus is a newsreader, in case you're forgetting.
+@code{nneething} does this in a two-step process.  First, it snoops each
+file in question.  If the file looks like an article (i.e., the first
+few lines look like headers), it will use this as the head.  If this is
+just some arbitrary file without a head (e.g. a C source file),
+@code{nneething} will cobble up a header out of thin air.  It will use
+file ownership, name and date and do whatever it can with these
+elements.
 
+All this should happen automatically for you, and you will be presented
+with something that looks very much like a newsgroup.  Totally like a
+newsgroup, to be precise.  If you select an article, it will be displayed
+in the article buffer, just as usual.
 
-@node Summary Agent Commands
-@subsubsection Summary Agent Commands
+If you select a line that represents a directory, Gnus will pop you into
+a new summary buffer for this @code{nneething} group.  And so on.  You can
+traverse the entire disk this way, if you feel like, but remember that
+Gnus is not dired, really, and does not intend to be, either.
 
-@table @kbd
-@item J #
-@kindex J # (Agent Summary)
-@findex gnus-agent-mark-article
-Mark the article for downloading (@code{gnus-agent-mark-article}).
+There are two overall modes to this action---ephemeral or solid.  When
+doing the ephemeral thing (i.e., @kbd{G D} from the group buffer), Gnus
+will not store information on what files you have read, and what files
+are new, and so on.  If you create a solid @code{nneething} group the
+normal way with @kbd{G m}, Gnus will store a mapping table between
+article numbers and file names, and you can treat this group like any
+other groups.  When you activate a solid @code{nneething} group, you will
+be told how many unread articles it contains, etc., etc.
 
-@item J M-#
-@kindex J M-# (Agent Summary)
-@findex gnus-agent-unmark-article
-Remove the downloading mark from the article
-(@code{gnus-agent-unmark-article}).
+Some variables:
 
-@item @@
-@kindex @@ (Agent Summary)
-@findex gnus-agent-toggle-mark
-Toggle whether to download the article (@code{gnus-agent-toggle-mark}).
+@table @code
+@item nneething-map-file-directory
+@vindex nneething-map-file-directory
+All the mapping files for solid @code{nneething} groups will be stored
+in this directory, which defaults to @file{~/.nneething/}.
 
-@item J c
-@kindex J c (Agent Summary)
-@findex gnus-agent-catchup
-Mark all undownloaded articles as read (@code{gnus-agent-catchup}).
+@item nneething-exclude-files
+@vindex nneething-exclude-files
+All files that match this regexp will be ignored.  Nice to use to exclude
+auto-save files and the like, which is what it does by default.
 
-@end table
+@item nneething-include-files
+@vindex nneething-include-files
+Regexp saying what files to include in the group.  If this variable is
+non-@code{nil}, only files matching this regexp will be included.
 
+@item nneething-map-file
+@vindex nneething-map-file
+Name of the map files.
+@end table
 
-@node Server Agent Commands
-@subsubsection Server Agent Commands
 
-@table @kbd
-@item J a
-@kindex J a (Agent Server)
-@findex gnus-agent-add-server
-Add the current server to the list of servers covered by the Gnus Agent
-(@code{gnus-agent-add-server}).
+@node Document Groups
+@subsection Document Groups
+@cindex nndoc
+@cindex documentation group
+@cindex help group
 
-@item J r
-@kindex J r (Agent Server)
-@findex gnus-agent-remove-server
-Remove the current server from the list of servers covered by the Gnus
-Agent (@code{gnus-agent-remove-server}).
+@code{nndoc} is a cute little thing that will let you read a single file
+as a newsgroup.  Several files types are supported:
 
-@end table
+@table @code
+@cindex Babyl
+@cindex Rmail mbox
 
+@item babyl
+The Babyl (Rmail) mail box.
+@cindex mbox
+@cindex Unix mbox
 
-@node Outgoing Messages
-@subsection Outgoing Messages
+@item mbox
+The standard Unix mbox file.
 
-When Gnus is unplugged, all outgoing messages (both mail and news) are
-stored in the draft groups (@pxref{Drafts}).  You can view them there
-after posting, and edit them at will.
+@cindex MMDF mail box
+@item mmdf
+The MMDF mail box format.
 
-When Gnus is plugged again, you can send the messages either from the
-draft group with the special commands available there, or you can use
-the @kbd{J S} command in the group buffer to send all the sendable
-messages in the draft group.
+@item news
+Several news articles appended into a file.
 
+@item rnews
+@cindex rnews batch files
+The rnews batch transport format.
+@cindex forwarded messages
 
+@item forward
+Forwarded articles.
 
-@node Agent Variables
-@subsection Agent Variables
+@item nsmail
+Netscape mail boxes.
 
-@table @code
-@item gnus-agent-directory
-@vindex gnus-agent-directory
-Where the Gnus Agent will store its files.  The default is
-@file{~/News/agent/}.
+@item mime-parts
+@acronym{MIME} multipart messages.
 
-@item gnus-agent-handle-level
-@vindex gnus-agent-handle-level
-Groups on levels (@pxref{Group Levels}) higher than this variable will
-be ignored by the Agent.  The default is @code{gnus-level-subscribed},
-which means that only subscribed group will be considered by the Agent
-by default.
+@item standard-digest
+The standard (RFC 1153) digest format.
 
-@item gnus-agent-plugged-hook
-@vindex gnus-agent-plugged-hook
-Hook run when connecting to the network.
+@item mime-digest
+A @acronym{MIME} digest of messages.
 
-@item gnus-agent-unplugged-hook
-@vindex gnus-agent-unplugged-hook
-Hook run when disconnecting from the network.
+@item lanl-gov-announce
+Announcement messages from LANL Gov Announce.
 
-@end table
+@item rfc822-forward
+A message forwarded according to RFC822.
 
+@item outlook
+The Outlook mail box.
 
-@node Example Setup
-@subsection Example Setup
+@item oe-dbx
+The Outlook Express dbx mail box.
 
-If you don't want to read this manual, and you have a fairly standard
-setup, you may be able to use something like the following as your
-@file{.gnus.el} file to get started.
+@item exim-bounce
+A bounce message from the Exim MTA.
 
-@lisp
-;;; Define how Gnus is to fetch news.  We do this over NNTP
-;;; from your ISP's server.
-(setq gnus-select-method '(nntp "nntp.your-isp.com"))
+@item forward
+A message forwarded according to informal rules.
 
-;;; Define how Gnus is to read your mail.  We read mail from
-;;; your ISP's POP server.
-(setenv "MAILHOST" "pop.your-isp.com")
-(setq nnmail-spool-file "po:username")
+@item rfc934
+An RFC934-forwarded message.
 
-;;; Say how Gnus is to store the mail.  We use nnml groups.
-(setq gnus-secondary-select-methods '((nnml "")))
+@item mailman
+A mailman digest.
 
-;;; Make Gnus into an offline newsreader.
-(gnus-agentize)
-@end lisp
+@item clari-briefs
+A digest of Clarinet brief news items.
 
-That should be it, basically.  Put that in your @file{~/.gnus.el} file,
-edit to suit your needs, start up PPP (or whatever), and type @kbd{M-x
-gnus}.
+@item slack-digest
+Non-standard digest format---matches most things, but does it badly.
 
-If this is the first time you've run Gnus, you will be subscribed
-automatically to a few default newsgroups.  You'll probably want to
-subscribe to more groups, and to do that, you have to query the
-@sc{nntp} server for a complete list of groups with the @kbd{A A}
-command.  This usually takes quite a while, but you only have to do it
-once.
+@item mail-in-mail
+The last resort.
+@end table
 
-After reading and parsing a while, you'll be presented with a list of
-groups.  Subscribe to the ones you want to read with the @kbd{u}
-command.  @kbd{l} to make all the killed groups disappear after you've
-subscribe to all the groups you want to read.  (@kbd{A k} will bring
-back all the killed groups.)
+You can also use the special ``file type'' @code{guess}, which means
+that @code{nndoc} will try to guess what file type it is looking at.
+@code{digest} means that @code{nndoc} should guess what digest type the
+file is.
 
-You can now read the groups at once, or you can download the articles
-with the @kbd{J s} command.  And then read the rest of this manual to
-find out which of the other gazillion things you want to customize.
+@code{nndoc} will not try to change the file or insert any extra headers into
+it---it will simply, like, let you use the file as the basis for a
+group.  And that's it.
 
+If you have some old archived articles that you want to insert into your
+new & spiffy Gnus mail back end, @code{nndoc} can probably help you with
+that.  Say you have an old @file{RMAIL} file with mail that you now want
+to split into your new @code{nnml} groups.  You look at that file using
+@code{nndoc} (using the @kbd{G f} command in the group buffer
+(@pxref{Foreign Groups})), set the process mark on all the articles in
+the buffer (@kbd{M P b}, for instance), and then re-spool (@kbd{B r})
+using @code{nnml}.  If all goes well, all the mail in the @file{RMAIL}
+file is now also stored in lots of @code{nnml} directories, and you can
+delete that pesky @file{RMAIL} file.  If you have the guts!
 
-@node Batching Agents
-@subsection Batching Agents
+Virtual server variables:
 
-Having the Gnus Agent fetch articles (and post whatever messages you've
-written) is quite easy once you've gotten things set up properly.  The
-following shell script will do everything that is necessary:
+@table @code
+@item nndoc-article-type
+@vindex nndoc-article-type
+This should be one of @code{mbox}, @code{babyl}, @code{digest},
+@code{news}, @code{rnews}, @code{mmdf}, @code{forward}, @code{rfc934},
+@code{rfc822-forward}, @code{mime-parts}, @code{standard-digest},
+@code{slack-digest}, @code{clari-briefs}, @code{nsmail}, @code{outlook},
+@code{oe-dbx}, @code{mailman}, and @code{mail-in-mail} or @code{guess}.
 
-@example
-#!/bin/sh
-emacs -batch -l ~/.emacs -f gnus-agent-batch >/dev/null
-@end example
+@item nndoc-post-type
+@vindex nndoc-post-type
+This variable says whether Gnus is to consider the group a news group or
+a mail group.  There are two valid values:  @code{mail} (the default)
+and @code{news}.
+@end table
 
+@menu
+* Document Server Internals::   How to add your own document types.
+@end menu
 
 
-@node Scoring
-@chapter Scoring
-@cindex scoring
+@node Document Server Internals
+@subsubsection Document Server Internals
 
-Other people use @dfn{kill files}, but we here at Gnus Towers like
-scoring better than killing, so we'd rather switch than fight.  They do
-something completely different as well, so sit up straight and pay
-attention!
+Adding new document types to be recognized by @code{nndoc} isn't
+difficult.  You just have to whip up a definition of what the document
+looks like, write a predicate function to recognize that document type,
+and then hook into @code{nndoc}.
 
-@vindex gnus-summary-mark-below
-All articles have a default score (@code{gnus-summary-default-score}),
-which is 0 by default.  This score may be raised or lowered either
-interactively or by score files.  Articles that have a score lower than
-@code{gnus-summary-mark-below} are marked as read.
+First, here's an example document type definition:
 
-Gnus will read any @dfn{score files} that apply to the current group
-before generating the summary buffer.
+@example
+(mmdf
+ (article-begin .  "^\^A\^A\^A\^A\n")
+ (body-end .  "^\^A\^A\^A\^A\n"))
+@end example
 
-There are several commands in the summary buffer that insert score
-entries based on the current article.  You can, for instance, ask Gnus to
-lower or increase the score of all articles with a certain subject.
+The definition is simply a unique @dfn{name} followed by a series of
+regexp pseudo-variable settings.  Below are the possible
+variables---don't be daunted by the number of variables; most document
+types can be defined with very few settings:
 
-There are two sorts of scoring entries: Permanent and temporary.
-Temporary score entries are self-expiring entries.  Any entries that are
-temporary and have not been used for, say, a week, will be removed
-silently to help keep the sizes of the score files down.
-
-@menu 
-* Summary Score Commands::   Adding score entries for the current group.
-* Group Score Commands::     General score commands.
-* Score Variables::          Customize your scoring.  (My, what terminology).
-* Score File Format::        What a score file may contain.
-* Score File Editing::       You can edit score files by hand as well.
-* Adaptive Scoring::         Big Sister Gnus knows what you read.
-* Home Score File::          How to say where new score entries are to go.
-* Followups To Yourself::    Having Gnus notice when people answer you.
-* Scoring Tips::             How to score effectively.
-* Reverse Scoring::          That problem child of old is not problem.
-* Global Score Files::       Earth-spanning, ear-splitting score files.
-* Kill Files::               They are still here, but they can be ignored.
-* Converting Kill Files::    Translating kill files to score files.
-* GroupLens::                Getting predictions on what you like to read.
-* Advanced Scoring::         Using logical expressions to build score rules.
-* Score Decays::             It can be useful to let scores wither away.
-@end menu
+@table @code
+@item first-article
+If present, @code{nndoc} will skip past all text until it finds
+something that match this regexp.  All text before this will be
+totally ignored.
 
+@item article-begin
+This setting has to be present in all document type definitions.  It
+says what the beginning of each article looks like.
 
-@node Summary Score Commands
-@section Summary Score Commands
-@cindex score commands
+@item head-begin-function
+If present, this should be a function that moves point to the head of
+the article.
 
-The score commands that alter score entries do not actually modify real
-score files.  That would be too inefficient.  Gnus maintains a cache of
-previously loaded score files, one of which is considered the
-@dfn{current score file alist}.  The score commands simply insert
-entries into this list, and upon group exit, this list is saved.
+@item nndoc-head-begin
+If present, this should be a regexp that matches the head of the
+article.
 
-The current score file is by default the group's local score file, even
-if no such score file actually exists.  To insert score commands into
-some other score file (e.g. @file{all.SCORE}), you must first make this
-score file the current one.
+@item nndoc-head-end
+This should match the end of the head of the article.  It defaults to
+@samp{^$}---the empty line.
 
-General score commands that don't actually change the score file:
+@item body-begin-function
+If present, this function should move point to the beginning of the body
+of the article.
 
-@table @kbd
+@item body-begin
+This should match the beginning of the body of the article.  It defaults
+to @samp{^\n}.
 
-@item V s
-@kindex V s (Summary)
-@findex gnus-summary-set-score
-Set the score of the current article (@code{gnus-summary-set-score}).  
+@item body-end-function
+If present, this function should move point to the end of the body of
+the article.
 
-@item V S
-@kindex V S (Summary)
-@findex gnus-summary-current-score
-Display the score of the current article
-(@code{gnus-summary-current-score}).   
+@item body-end
+If present, this should match the end of the body of the article.
 
-@item V t
-@kindex V t (Summary)
-@findex gnus-score-find-trace
-Display all score rules that have been used on the current article
-(@code{gnus-score-find-trace}).   
+@item file-end
+If present, this should match the end of the file.  All text after this
+regexp will be totally ignored.
 
-@item V R
-@kindex V R (Summary)
-@findex gnus-summary-rescore
-Run the current summary through the scoring process
-(@code{gnus-summary-rescore}).  This might be useful if you're playing
-around with your score files behind Gnus' back and want to see the
-effect you're having.
+@end table
 
-@item V a
-@kindex V a (Summary)
-@findex gnus-summary-score-entry
-Add a new score entry, and allow specifying all elements 
-(@code{gnus-summary-score-entry}).
+So, using these variables @code{nndoc} is able to dissect a document
+file into a series of articles, each with a head and a body.  However, a
+few more variables are needed since not all document types are all that
+news-like---variables needed to transform the head or the body into
+something that's palatable for Gnus:
 
-@item V c
-@kindex V c (Summary)
-@findex gnus-score-change-score-file
-Make a different score file the current
-(@code{gnus-score-change-score-file}). 
+@table @code
+@item prepare-body-function
+If present, this function will be called when requesting an article.  It
+will be called with point at the start of the body, and is useful if the
+document has encoded some parts of its contents.
 
-@item V e
-@kindex V e (Summary)
-@findex gnus-score-edit-current-scores
-Edit the current score file (@code{gnus-score-edit-current-scores}).
-You will be popped into a @code{gnus-score-mode} buffer (@pxref{Score
-File Editing}).
+@item article-transform-function
+If present, this function is called when requesting an article.  It's
+meant to be used for more wide-ranging transformation of both head and
+body of the article.
 
-@item V f
-@kindex V f (Summary)
-@findex gnus-score-edit-file
-Edit a score file and make this score file the current one
-(@code{gnus-score-edit-file}).
+@item generate-head-function
+If present, this function is called to generate a head that Gnus can
+understand.  It is called with the article number as a parameter, and is
+expected to generate a nice head for the article in question.  It is
+called when requesting the headers of all articles.
 
-@item V F
-@kindex V F (Summary)
-@findex gnus-score-flush-cache
-Flush the score cache (@code{gnus-score-flush-cache}).  This is useful
-after editing score files.
+@end table
 
-@item V C
-@kindex V C (Summary)
-@findex gnus-score-customize
-Customize a score file in a visually pleasing manner
-(@code{gnus-score-customize}). 
+Let's look at the most complicated example I can come up with---standard
+digests:
 
-@end table
+@example
+(standard-digest
+ (first-article . ,(concat "^" (make-string 70 ?-) "\n\n+"))
+ (article-begin . ,(concat "\n\n" (make-string 30 ?-) "\n\n+"))
+ (prepare-body-function . nndoc-unquote-dashes)
+ (body-end-function . nndoc-digest-body-end)
+ (head-end . "^ ?$")
+ (body-begin . "^ ?\n")
+ (file-end . "^End of .*digest.*[0-9].*\n\\*\\*\\|^End of.*Digest *$")
+ (subtype digest guess))
+@end example
 
-The rest of these commands modify the local score file.
+We see that all text before a 70-width line of dashes is ignored; all
+text after a line that starts with that @samp{^End of} is also ignored;
+each article begins with a 30-width line of dashes; the line separating
+the head from the body may contain a single space; and that the body is
+run through @code{nndoc-unquote-dashes} before being delivered.
 
-@table @kbd
+To hook your own document definition into @code{nndoc}, use the
+@code{nndoc-add-type} function.  It takes two parameters---the first
+is the definition itself and the second (optional) parameter says
+where in the document type definition alist to put this definition.
+The alist is traversed sequentially, and
+@code{nndoc-@var{type}-type-p} is called for a given type @var{type}.
+So @code{nndoc-mmdf-type-p} is called to see whether a document is of
+@code{mmdf} type, and so on.  These type predicates should return
+@code{nil} if the document is not of the correct type; @code{t} if it
+is of the correct type; and a number if the document might be of the
+correct type.  A high number means high probability; a low number
+means low probability with @samp{0} being the lowest valid number.
 
-@item V m
-@kindex V m (Summary)
-@findex gnus-score-set-mark-below
-Prompt for a score, and mark all articles with a score below this as
-read (@code{gnus-score-set-mark-below}).
 
-@item V x
-@kindex V x (Summary)
-@findex gnus-score-set-expunge-below
-Prompt for a score, and add a score rule to the current score file to
-expunge all articles below this score
-(@code{gnus-score-set-expunge-below}).
-@end table
+@node SOUP
+@subsection SOUP
+@cindex SOUP
+@cindex offline
 
-The keystrokes for actually making score entries follow a very regular
-pattern, so there's no need to list all the commands.  (Hundreds of
-them.)  
+In the PC world people often talk about ``offline'' newsreaders.  These
+are thingies that are combined reader/news transport monstrosities.
+With built-in modem programs.  Yecchh!
 
-@findex gnus-summary-increase-score
-@findex gnus-summary-lower-score
+Of course, us Unix Weenie types of human beans use things like
+@code{uucp} and, like, @code{nntpd} and set up proper news and mail
+transport things like Ghod intended.  And then we just use normal
+newsreaders.
 
-@enumerate
-@item
-The first key is either @kbd{I} (upper case i) for increasing the score
-or @kbd{L} for lowering the score. 
-@item
-The second key says what header you want to score on.  The following
-keys are available:
-@table @kbd
+However, it can sometimes be convenient to do something that's a bit
+easier on the brain if you have a very slow modem, and you're not really
+that interested in doing things properly.
 
-@item a
-Score on the author name.
+A file format called @sc{soup} has been developed for transporting news
+and mail from servers to home machines and back again.  It can be a bit
+fiddly.
 
-@item s
-Score on the subject line.
+First some terminology:
 
-@item x
-Score on the Xref line---i.e., the cross-posting line.
+@table @dfn
 
-@item t
-Score on thread---the References line.
+@item server
+This is the machine that is connected to the outside world and where you
+get news and/or mail from.
 
-@item d
-Score on the date.
+@item home machine
+This is the machine that you want to do the actual reading and responding
+on.  It is typically not connected to the rest of the world in any way.
 
-@item l
-Score on the number of lines.
+@item packet
+Something that contains messages and/or commands.  There are two kinds
+of packets:
 
-@item i
-Score on the Message-ID.
+@table @dfn
+@item message packets
+These are packets made at the server, and typically contain lots of
+messages for you to read.  These are called @file{SoupoutX.tgz} by
+default, where @var{x} is a number.
 
-@item f
-Score on followups.
+@item response packets
+These are packets made at the home machine, and typically contains
+replies that you've written.  These are called @file{SoupinX.tgz} by
+default, where @var{x} is a number.
 
-@item b
-Score on the body.
+@end table
 
-@item h
-Score on the head.
 @end table
 
+
+@enumerate
+
 @item
-The third key is the match type.  Which match types are valid depends on
-what headers you are scoring on.
+You log in on the server and create a @sc{soup} packet.  You can either
+use a dedicated @sc{soup} thingie (like the @code{awk} program), or you
+can use Gnus to create the packet with its @sc{soup} commands (@kbd{O
+s} and/or @kbd{G s b}; and then @kbd{G s p}) (@pxref{SOUP Commands}).
 
-@table @code
+@item
+You transfer the packet home.  Rail, boat, car or modem will do fine.
 
-@item strings 
+@item
+You put the packet in your home directory.
 
-@table @kbd
+@item
+You fire up Gnus on your home machine using the @code{nnsoup} back end as
+the native or secondary server.
 
-@item e
-Exact matching.
+@item
+You read articles and mail and answer and followup to the things you
+want (@pxref{SOUP Replies}).
 
-@item s
-Substring matching.
+@item
+You do the @kbd{G s r} command to pack these replies into a @sc{soup}
+packet.
 
-@item f
-Fuzzy matching (@pxref{Fuzzy Matching}).
+@item
+You transfer this packet to the server.
 
-@item r
-Regexp matching
-@end table
+@item
+You use Gnus to mail this packet out with the @kbd{G s s} command.
 
-@item date
-@table @kbd
+@item
+You then repeat until you die.
 
-@item b
-Before date.
+@end enumerate
 
-@item a
-At date.
+So you basically have a bipartite system---you use @code{nnsoup} for
+reading and Gnus for packing/sending these @sc{soup} packets.
 
-@item n
-This date.
-@end table
+@menu
+* SOUP Commands::               Commands for creating and sending @sc{soup} packets
+* SOUP Groups::                 A back end for reading @sc{soup} packets.
+* SOUP Replies::                How to enable @code{nnsoup} to take over mail and news.
+@end menu
 
-@item number
-@table @kbd
 
-@item <
-Less than number.
-
-@item =
-Equal to number.
+@node SOUP Commands
+@subsubsection SOUP Commands
 
-@item >
-Greater than number.
-@end table
-@end table
+These are commands for creating and manipulating @sc{soup} packets.
 
-@item 
-The fourth and final key says whether this is a temporary (i.e., expiring)
-score entry, or a permanent (i.e., non-expiring) score entry, or whether
-it is to be done immediately, without adding to the score file.
 @table @kbd
+@item G s b
+@kindex G s b (Group)
+@findex gnus-group-brew-soup
+Pack all unread articles in the current group
+(@code{gnus-group-brew-soup}).  This command understands the
+process/prefix convention.
 
-@item t
-Temporary score entry.
+@item G s w
+@kindex G s w (Group)
+@findex gnus-soup-save-areas
+Save all @sc{soup} data files (@code{gnus-soup-save-areas}).
 
-@item p
-Permanent score entry.
+@item G s s
+@kindex G s s (Group)
+@findex gnus-soup-send-replies
+Send all replies from the replies packet
+(@code{gnus-soup-send-replies}).
+
+@item G s p
+@kindex G s p (Group)
+@findex gnus-soup-pack-packet
+Pack all files into a @sc{soup} packet (@code{gnus-soup-pack-packet}).
+
+@item G s r
+@kindex G s r (Group)
+@findex nnsoup-pack-replies
+Pack all replies into a replies packet (@code{nnsoup-pack-replies}).
+
+@item O s
+@kindex O s (Summary)
+@findex gnus-soup-add-article
+This summary-mode command adds the current article to a @sc{soup} packet
+(@code{gnus-soup-add-article}).  It understands the process/prefix
+convention (@pxref{Process/Prefix}).
 
-@item i
-Immediately scoring.
 @end table
 
-@end enumerate
 
-So, let's say you want to increase the score on the current author with
-exact matching permanently: @kbd{I a e p}.  If you want to lower the
-score based on the subject line, using substring matching, and make a
-temporary score entry: @kbd{L s s t}.  Pretty easy.
+There are a few variables to customize where Gnus will put all these
+thingies:
 
-To make things a bit more complicated, there are shortcuts.  If you use
-a capital letter on either the second or third keys, Gnus will use
-defaults for the remaining one or two keystrokes.  The defaults are
-``substring'' and ``temporary''.  So @kbd{I A} is the same as @kbd{I a s
-t}, and @kbd{I a R} is the same as @kbd{I a r t}.
+@table @code
 
-These functions take both the numerical prefix and the symbolic prefix
-(@pxref{Symbolic Prefixes}).  A numerical prefix says how much to lower
-(or increase) the score of the article.  A symbolic prefix of @code{a}
-says to use the @file{all.SCORE} file for the command instead of the
-current score file.
+@item gnus-soup-directory
+@vindex gnus-soup-directory
+Directory where Gnus will save intermediate files while composing
+@sc{soup} packets.  The default is @file{~/SoupBrew/}.
 
-@vindex gnus-score-mimic-keymap
-The @code{gnus-score-mimic-keymap} says whether these commands will
-pretend they are keymaps or not.
+@item gnus-soup-replies-directory
+@vindex gnus-soup-replies-directory
+This is what Gnus will use as a temporary directory while sending our
+reply packets.  @file{~/SoupBrew/SoupReplies/} is the default.
 
+@item gnus-soup-prefix-file
+@vindex gnus-soup-prefix-file
+Name of the file where Gnus stores the last used prefix.  The default is
+@samp{gnus-prefix}.
 
-@node Group Score Commands
-@section Group Score Commands
-@cindex group score commands
+@item gnus-soup-packer
+@vindex gnus-soup-packer
+A format string command for packing a @sc{soup} packet.  The default is
+@samp{tar cf - %s | gzip > $HOME/Soupout%d.tgz}.
 
-There aren't many of these as yet, I'm afraid.
+@item gnus-soup-unpacker
+@vindex gnus-soup-unpacker
+Format string command for unpacking a @sc{soup} packet.  The default is
+@samp{gunzip -c %s | tar xvf -}.
 
-@table @kbd
+@item gnus-soup-packet-directory
+@vindex gnus-soup-packet-directory
+Where Gnus will look for reply packets.  The default is @file{~/}.
 
-@item W f
-@kindex W f (Group)
-@findex gnus-score-flush-cache
-Gnus maintains a cache of score alists to avoid having to reload them
-all the time.  This command will flush the cache
-(@code{gnus-score-flush-cache}). 
+@item gnus-soup-packet-regexp
+@vindex gnus-soup-packet-regexp
+Regular expression matching @sc{soup} reply packets in
+@code{gnus-soup-packet-directory}.
 
 @end table
 
-You can do scoring from the command line by saying something like:
 
-@findex gnus-batch-score
-@cindex batch scoring
-@example
-$ emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score
-@end example
+@node SOUP Groups
+@subsubsection SOUP Groups
+@cindex nnsoup
 
+@code{nnsoup} is the back end for reading @sc{soup} packets.  It will
+read incoming packets, unpack them, and put them in a directory where
+you can read them at leisure.
 
-@node Score Variables
-@section Score Variables
-@cindex score variables
+These are the variables you can use to customize its behavior:
 
 @table @code
 
-@item gnus-use-scoring
-@vindex gnus-use-scoring
-If @code{nil}, Gnus will not check for score files, and will not, in
-general, do any score-related work.  This is @code{t} by default.
+@item nnsoup-tmp-directory
+@vindex nnsoup-tmp-directory
+When @code{nnsoup} unpacks a @sc{soup} packet, it does it in this
+directory.  (@file{/tmp/} by default.)
 
-@item gnus-kill-killed
-@vindex gnus-kill-killed
-If this variable is @code{nil}, Gnus will never apply score files to
-articles that have already been through the kill process.  While this
-may save you lots of time, it also means that if you apply a kill file
-to a group, and then change the kill file and want to run it over you
-group again to kill more articles, it won't work.  You have to set this
-variable to @code{t} to do that.  (It is @code{t} by default.)
+@item nnsoup-directory
+@vindex nnsoup-directory
+@code{nnsoup} then moves each message and index file to this directory.
+The default is @file{~/SOUP/}.
 
-@item gnus-kill-files-directory
-@vindex gnus-kill-files-directory
-All kill and score files will be stored in this directory, which is
-initialized from the @code{SAVEDIR} environment variable by default.
-This is @file{~/News/} by default.
+@item nnsoup-replies-directory
+@vindex nnsoup-replies-directory
+All replies will be stored in this directory before being packed into a
+reply packet.  The default is @file{~/SOUP/replies/}.
 
-@item gnus-score-file-suffix
-@vindex gnus-score-file-suffix
-Suffix to add to the group name to arrive at the score file name
-(@samp{SCORE} by default.)
+@item nnsoup-replies-format-type
+@vindex nnsoup-replies-format-type
+The @sc{soup} format of the replies packets.  The default is @samp{?n}
+(rnews), and I don't think you should touch that variable.  I probably
+shouldn't even have documented it.  Drats!  Too late!
 
-@item gnus-score-uncacheable-files
-@vindex gnus-score-uncacheable-files
-@cindex score cache
-All score files are normally cached to avoid excessive re-loading of
-score files.  However, if this might make you Emacs grow big and
-bloated, so this regexp can be used to weed out score files unlikely to be needed again.  It would be a bad idea to deny caching of
-@file{all.SCORE}, while it might be a good idea to not cache
-@file{comp.infosystems.www.authoring.misc.ADAPT}.  In fact, this
-variable is @samp{ADAPT$} by default, so no adaptive score files will
-be cached.
+@item nnsoup-replies-index-type
+@vindex nnsoup-replies-index-type
+The index type of the replies packet.  The default is @samp{?n}, which
+means ``none''.  Don't fiddle with this one either!
 
-@item gnus-save-score
-@vindex gnus-save-score
-If you have really complicated score files, and do lots of batch
-scoring, then you might set this variable to @code{t}.  This will make
-Gnus save the scores into the @file{.newsrc.eld} file.
+@item nnsoup-active-file
+@vindex nnsoup-active-file
+Where @code{nnsoup} stores lots of information.  This is not an ``active
+file'' in the @code{nntp} sense; it's an Emacs Lisp file.  If you lose
+this file or mess it up in any way, you're dead.  The default is
+@file{~/SOUP/active}.
 
-@item gnus-score-interactive-default-score
-@vindex gnus-score-interactive-default-score
-Score used by all the interactive raise/lower commands to raise/lower
-score with.  Default is 1000, which may seem excessive, but this is to
-ensure that the adaptive scoring scheme gets enough room to play with.
-We don't want the small changes from the adaptive scoring to overwrite
-manually entered data.
+@item nnsoup-packer
+@vindex nnsoup-packer
+Format string command for packing a reply @sc{soup} packet.  The default
+is @samp{tar cf - %s | gzip > $HOME/Soupin%d.tgz}.
 
-@item gnus-summary-default-score
-@vindex gnus-summary-default-score
-Default score of an article, which is 0 by default.
+@item nnsoup-unpacker
+@vindex nnsoup-unpacker
+Format string command for unpacking incoming @sc{soup} packets.  The
+default is @samp{gunzip -c %s | tar xvf -}.
 
-@item gnus-summary-expunge-below
-@vindex gnus-summary-expunge-below
-Don't display the summary lines of articles that have scores lower than
-this variable.  This is @code{nil} by default, which means that no
-articles will be hidden.  This variable is local to the summary buffers,
-and has to be set from @code{gnus-summary-mode-hook}.
+@item nnsoup-packet-directory
+@vindex nnsoup-packet-directory
+Where @code{nnsoup} will look for incoming packets.  The default is
+@file{~/}.
 
-@item gnus-score-over-mark
-@vindex gnus-score-over-mark
-Mark (in the third column) used for articles with a score over the
-default.  Default is @samp{+}.
+@item nnsoup-packet-regexp
+@vindex nnsoup-packet-regexp
+Regular expression matching incoming @sc{soup} packets.  The default is
+@samp{Soupout}.
 
-@item gnus-score-below-mark
-@vindex gnus-score-below-mark
-Mark (in the third column) used for articles with a score below the
-default.  Default is @samp{-}.
+@item nnsoup-always-save
+@vindex nnsoup-always-save
+If non-@code{nil}, save the replies buffer after each posted message.
 
-@item gnus-score-find-score-files-function
-@vindex gnus-score-find-score-files-function
-Function used to find score files for the current group.  This function
-is called with the name of the group as the argument. 
+@end table
 
-Predefined functions available are:
-@table @code
 
-@item gnus-score-find-single
-@findex gnus-score-find-single
-Only apply the group's own score file.
+@node SOUP Replies
+@subsubsection SOUP Replies
 
-@item gnus-score-find-bnews
-@findex gnus-score-find-bnews
-Apply all score files that match, using bnews syntax.  This is the
-default.  If the current group is @samp{gnu.emacs.gnus}, for instance, 
-@file{all.emacs.all.SCORE}, @file{not.alt.all.SCORE} and
-@file{gnu.all.SCORE} would all apply.  In short, the instances of
-@samp{all} in the score file names are translated into @samp{.*}, and
-then a regexp match is done.
+Just using @code{nnsoup} won't mean that your postings and mailings end
+up in @sc{soup} reply packets automagically.  You have to work a bit
+more for that to happen.
 
-This means that if you have some score entries that you want to apply to
-all groups, then you put those entries in the @file{all.SCORE} file. 
+@findex nnsoup-set-variables
+The @code{nnsoup-set-variables} command will set the appropriate
+variables to ensure that all your followups and replies end up in the
+@sc{soup} system.
 
-The score files are applied in a semi-random order, although Gnus will
-try to apply the more general score files before the more specific score
-files.  It does this by looking at the number of elements in the score
-file names---discarding the @samp{all} elements.
+In specific, this is what it does:
 
-@item gnus-score-find-hierarchical
-@findex gnus-score-find-hierarchical
-Apply all score files from all the parent groups.  This means that you
-can't have score files like @file{all.SCORE}, but you can have
-@file{SCORE}, @file{comp.SCORE} and @file{comp.emacs.SCORE}.
+@lisp
+(setq message-send-news-function 'nnsoup-request-post)
+(setq message-send-mail-function 'nnsoup-request-mail)
+@end lisp
 
-@end table
-This variable can also be a list of functions.  In that case, all these
-functions will be called, and all the returned lists of score files will
-be applied.  These functions can also return lists of score alists
-directly.  In that case, the functions that return these non-file score
-alists should probably be placed before the ``real'' score file
-functions, to ensure that the last score file returned is the local
-score file.  Phu.
+And that's it, really.  If you only want news to go into the @sc{soup}
+system you just use the first line.  If you only want mail to be
+@sc{soup}ed you use the second.
 
-@item gnus-score-expiry-days
-@vindex gnus-score-expiry-days
-This variable says how many days should pass before an unused score file
-entry is expired.  If this variable is @code{nil}, no score file entries
-are expired.  It's 7 by default.
 
-@item gnus-update-score-entry-dates
-@vindex gnus-update-score-entry-dates
-If this variable is non-@code{nil}, matching score entries will have
-their dates updated.  (This is how Gnus controls expiry---all
-non-matching entries will become too old while matching entries will
-stay fresh and young.)  However, if you set this variable to @code{nil},
-even matching entries will grow old and will have to face that oh-so
-grim reaper.  
-
-@item gnus-score-after-write-file-function
-@vindex gnus-score-after-write-file-function
-Function called with the name of the score file just written.
+@node Mail-To-News Gateways
+@subsection Mail-To-News Gateways
+@cindex mail-to-news gateways
+@cindex gateways
 
-@item gnus-score-thread-simplify
-@vindex gnus-score-thread-simplify
-If this variable is non-@code{nil}, article subjects will be simplified
-for subject scoring purposes in the same manner as with
-threading---according to the current value of
-gnus-simplify-subject-functions.  If the scoring entry uses
-@code{substring} or @code{exact} matching, the match will also be
-simplified in this manner.
+If your local @code{nntp} server doesn't allow posting, for some reason
+or other, you can post using one of the numerous mail-to-news gateways.
+The @code{nngateway} back end provides the interface.
 
-@end table
+Note that you can't read anything from this back end---it can only be
+used to post with.
 
+Server variables:
 
-@node Score File Format
-@section Score File Format
-@cindex score file format
+@table @code
+@item nngateway-address
+@vindex nngateway-address
+This is the address of the mail-to-news gateway.
 
-A score file is an @code{emacs-lisp} file that normally contains just a
-single form.  Casual users are not expected to edit these files;
-everything can be changed from the summary buffer.
+@item nngateway-header-transformation
+@vindex nngateway-header-transformation
+News headers often have to be transformed in some odd way or other
+for the mail-to-news gateway to accept it.  This variable says what
+transformation should be called, and defaults to
+@code{nngateway-simple-header-transformation}.  The function is called
+narrowed to the headers to be transformed and with one parameter---the
+gateway address.
 
-Anyway, if you'd like to dig into it yourself, here's an example:
+This default function just inserts a new @code{To} header based on the
+@code{Newsgroups} header and the gateway address.
+For instance, an article with this @code{Newsgroups} header:
 
-@lisp
-(("from"
-  ("Lars Ingebrigtsen" -10000)
-  ("Per Abrahamsen")
-  ("larsi\\|lmi" -50000 nil R))
- ("subject"
-  ("Ding is Badd" nil 728373))
- ("xref"
-  ("alt.politics" -1000 728372 s))
- ("lines"
-  (2 -100 nil <))
- (mark 0)
- (expunge -1000)
- (mark-and-expunge -10)
- (read-only nil)
- (orphan -10)
- (adapt t)
- (files "/hom/larsi/News/gnu.SCORE")
- (exclude-files "all.SCORE")
- (local (gnus-newsgroup-auto-expire t)
-        (gnus-summary-make-false-root empty))
- (eval (ding)))
-@end lisp
+@example
+Newsgroups: alt.religion.emacs
+@end example
 
-This example demonstrates most score file elements.  For a different
-approach, see @pxref{Advanced Scoring}.
+will get this @code{To} header inserted:
 
-Even though this looks much like lisp code, nothing here is actually
-@code{eval}ed.  The lisp reader is used to read this form, though, so it
-has to be valid syntactically, if not semantically.
+@example
+To: alt-religion-emacs@@GATEWAY
+@end example
 
-Six keys are supported by this alist:
+The following pre-defined functions exist:
 
+@findex nngateway-simple-header-transformation
 @table @code
 
-@item STRING
-If the key is a string, it is the name of the header to perform the
-match on.  Scoring can only be performed on these eight headers:
-@code{From}, @code{Subject}, @code{References}, @code{Message-ID},
-@code{Xref}, @code{Lines}, @code{Chars} and @code{Date}.  In addition to
-these headers, there are three strings to tell Gnus to fetch the entire
-article and do the match on larger parts of the article: @code{Body}
-will perform the match on the body of the article, @code{Head} will
-perform the match on the head of the article, and @code{All} will
-perform the match on the entire article.  Note that using any of these
-last three keys will slow down group entry @emph{considerably}.  The
-final ``header'' you can score on is @code{Followup}.  These score
-entries will result in new score entries being added for all follow-ups
-to articles that matches these score entries.
+@item nngateway-simple-header-transformation
+Creates a @code{To} header that looks like
+@var{newsgroup}@@@code{nngateway-address}.
 
-Following this key is a arbitrary number of score entries, where each
-score entry has one to four elements.
-@enumerate
+@findex nngateway-mail2news-header-transformation
 
-@item 
-The first element is the @dfn{match element}.  On most headers this will
-be a string, but on the Lines and Chars headers, this must be an
-integer. 
+@item nngateway-mail2news-header-transformation
+Creates a @code{To} header that looks like
+@code{nngateway-address}.
+@end table
 
-@item 
-If the second element is present, it should be a number---the @dfn{score
-element}.  This number should be an integer in the neginf to posinf
-interval.  This number is added to the score of the article if the match
-is successful.  If this element is not present, the
-@code{gnus-score-interactive-default-score} number will be used
-instead.  This is 1000 by default.
+@end table
 
-@item 
-If the third element is present, it should be a number---the @dfn{date
-element}.  This date says when the last time this score entry matched,
-which provides a mechanism for expiring the score entries.  It this
-element is not present, the score entry is permanent.  The date is
-represented by the number of days since December 31, 1 BCE.
+Here's an example:
 
-@item 
-If the fourth element is present, it should be a symbol---the @dfn{type
-element}.  This element specifies what function should be used to see
-whether this score entry matches the article.  What match types that can
-be used depends on what header you wish to perform the match on.
-@table @dfn
+@lisp
+(setq gnus-post-method
+      '(nngateway
+        "mail2news@@replay.com"
+        (nngateway-header-transformation
+         nngateway-mail2news-header-transformation)))
+@end lisp
 
-@item From, Subject, References, Xref, Message-ID
-For most header types, there are the @code{r} and @code{R} (regexp), as
-well as @code{s} and @code{S} (substring) types, and @code{e} and
-@code{E} (exact match), and @code{w} (word match) types.  If this
-element is not present, Gnus will assume that substring matching should
-be used.  @code{R}, @code{S}, and @code{E} differ from the others in
-that the matches will be done in a case-sensitive manner.  All these
-one-letter types are really just abbreviations for the @code{regexp},
-@code{string}, @code{exact}, and @code{word} types, which you can use
-instead, if you feel like.
+So, to use this, simply say something like:
 
-@item Lines, Chars
-These two headers use different match types: @code{<}, @code{>},
-@code{=}, @code{>=} and @code{<=}.  When matching on @code{Lines}, be
-careful because some backends (like @code{nndir}) do not generate
-@code{Lines} header, so every article ends up being marked as having 0
-lines.  This can lead to strange results if you happen to lower score of
-the articles with few lines.
+@lisp
+(setq gnus-post-method '(nngateway "GATEWAY.ADDRESS"))
+@end lisp
 
-@item Date
-For the Date header we have three kinda silly match types:
-@code{before}, @code{at} and @code{after}.  I can't really imagine this
-ever being useful, but, like, it would feel kinda silly not to provide
-this function.  Just in case.  You never know.  Better safe than sorry.
-Once burnt, twice shy.  Don't judge a book by its cover.  Never not have
-sex on a first date.  (I have been told that at least one person, and I
-quote, ``found this function indispensable'', however.)
 
-@cindex ISO8601
-@cindex date
-A more useful match type is @code{regexp}.  With it, you can match the
-date string using a regular expression.  The date is normalized to
-ISO8601 compact format first---@var{YYYYMMDD}@code{T}@var{HHMMSS}.  If
-you want to match all articles that have been posted on April 1st in
-every year, you could use @samp{....0401.........} as a match string,
-for instance.  (Note that the date is kept in its original time zone, so
-this will match articles that were posted when it was April 1st where
-the article was posted from.  Time zones are such wholesome fun for the
-whole family, eh?)
 
-@item Head, Body, All
-These three match keys use the same match types as the @code{From} (etc)
-header uses.
+@node Combined Groups
+@section Combined Groups
 
-@item Followup
-This match key is somewhat special, in that it will match the
-@code{From} header, and affect the score of not only the matching
-articles, but also all followups to the matching articles.  This allows
-you e.g. increase the score of followups to your own articles, or
-decrease the score of followups to the articles of some known
-trouble-maker.  Uses the same match types as the @code{From} header
-uses.  (Using this match key will lead to creation of @file{ADAPT}
-files.) 
+Gnus allows combining a mixture of all the other group types into bigger
+groups.
 
-@item Thread
-This match key works along the same lines as the @code{Followup} match
-key.  If you say that you want to score on a (sub-)thread started by an article with a @code{Message-ID} @var{X}, then you add a
-@samp{thread} match.  This will add a new @samp{thread} match for each
-article that has @var{X} in its @code{References} header.  (These new
-@samp{thread} matches will use the @code{Message-ID}s of these matching
-articles.)  This will ensure that you can raise/lower the score of an
-entire thread, even though some articles in the thread may not have
-complete @code{References} headers.  Note that using this may lead to
-undeterministic scores of the articles in the thread.  (Using this match
-key will lead to creation of @file{ADAPT} files.)
-@end table
-@end enumerate
+@menu
+* Virtual Groups::              Combining articles from many groups.
+* Kibozed Groups::              Looking through parts of the newsfeed for articles.
+@end menu
 
-@cindex Score File Atoms
-@item mark
-The value of this entry should be a number.  Any articles with a score
-lower than this number will be marked as read.
 
-@item expunge
-The value of this entry should be a number.  Any articles with a score
-lower than this number will be removed from the summary buffer.
+@node Virtual Groups
+@subsection Virtual Groups
+@cindex nnvirtual
+@cindex virtual groups
+@cindex merging groups
 
-@item mark-and-expunge
-The value of this entry should be a number.  Any articles with a score
-lower than this number will be marked as read and removed from the
-summary buffer.
+An @dfn{nnvirtual group} is really nothing more than a collection of
+other groups.
 
-@item thread-mark-and-expunge
-The value of this entry should be a number.  All articles that belong to
-a thread that has a total score below this number will be marked as read
-and removed from the summary buffer.  @code{gnus-thread-score-function}
-says how to compute the total score for a thread.
+For instance, if you are tired of reading many small groups, you can
+put them all in one big group, and then grow tired of reading one
+big, unwieldy group.  The joys of computing!
 
-@item files
-The value of this entry should be any number of file names.  These files
-are assumed to be score files as well, and will be loaded the same way
-this one was.
+You specify @code{nnvirtual} as the method.  The address should be a
+regexp to match component groups.
 
-@item exclude-files
-The clue of this entry should be any number of files.  These files will
-not be loaded, even though they would normally be so, for some reason or
-other. 
+All marks in the virtual group will stick to the articles in the
+component groups.  So if you tick an article in a virtual group, the
+article will also be ticked in the component group from whence it
+came.  (And vice versa---marks from the component groups will also be
+shown in the virtual group.).  To create an empty virtual group, run
+@kbd{G V} (@code{gnus-group-make-empty-virtual}) in the group buffer
+and edit the method regexp with @kbd{M-e}
+(@code{gnus-group-edit-group-method})
 
-@item eval
-The value of this entry will be @code{eval}el.  This element will be
-ignored when handling global score files. 
+Here's an example @code{nnvirtual} method that collects all Andrea Dworkin
+newsgroups into one, big, happy newsgroup:
 
-@item read-only
-Read-only score files will not be updated or saved.  Global score files
-should feature this atom (@pxref{Global Score Files}).  (Note:
-@dfn{Global} here really means @dfn{global}; not your personal
-apply-to-all-groups score files.)
+@lisp
+(nnvirtual "^alt\\.fan\\.andrea-dworkin$\\|^rec\\.dworkin.*")
+@end lisp
 
-@item orphan
-The value of this entry should be a number.  Articles that do not have
-parents will get this number added to their scores.  Imagine you follow
-some high-volume newsgroup, like @samp{comp.lang.c}.  Most likely you
-will only follow a few of the threads, also want to see any new threads.
+The component groups can be native or foreign; everything should work
+smoothly, but if your computer explodes, it was probably my fault.
 
-You can do this with the following two score file entries:
+Collecting the same group from several servers might actually be a good
+idea if users have set the Distribution header to limit distribution.
+If you would like to read @samp{soc.motss} both from a server in Japan
+and a server in Norway, you could use the following as the group regexp:
 
 @example
-        (orphan -500)
-        (mark-and-expunge -100)
+"^nntp\\+server\\.jp:soc\\.motss$\\|^nntp\\+server\\.no:soc\\.motss$"
 @end example
 
-When you enter the group the first time, you will only see the new
-threads.  You then raise the score of the threads that you find
-interesting (with @kbd{I T} or @kbd{I S}), and ignore (@kbd{C y}) the
-rest.  Next time you enter the group, you will see new articles in the
-interesting threads, plus any new threads.
+(Remember, though, that if you're creating the group with @kbd{G m}, you
+shouldn't double the backslashes, and you should leave off the quote
+characters at the beginning and the end of the string.)
 
-I.e.---the orphan score atom is for high-volume groups where there
-exist a few interesting threads which can't be found automatically by
-ordinary scoring rules.
+This should work kinda smoothly---all articles from both groups should
+end up in this one, and there should be no duplicates.  Threading (and
+the rest) will still work as usual, but there might be problems with the
+sequence of articles.  Sorting on date might be an option here
+(@pxref{Selecting a Group}).
 
-@item adapt
-This entry controls the adaptive scoring.  If it is @code{t}, the
-default adaptive scoring rules will be used.  If it is @code{ignore}, no
-adaptive scoring will be performed on this group.  If it is a list, this
-list will be used as the adaptive scoring rules.  If it isn't present,
-or is something other than @code{t} or @code{ignore}, the default
-adaptive scoring rules will be used.  If you want to use adaptive
-scoring on most groups, you'd set @code{gnus-use-adaptive-scoring} to
-@code{t}, and insert an @code{(adapt ignore)} in the groups where you do
-not want adaptive scoring.  If you only want adaptive scoring in a few
-groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and
-insert @code{(adapt t)} in the score files of the groups where you want
-it. 
+One limitation, however---all groups included in a virtual
+group have to be alive (i.e., subscribed or unsubscribed).  Killed or
+zombie groups can't be component groups for @code{nnvirtual} groups.
 
-@item adapt-file
-All adaptive score entries will go to the file named by this entry.  It
-will also be applied when entering the group.  This atom might be handy
-if you want to adapt on several groups at once, using the same adaptive
-file for a number of groups.
-
-@item local
-@cindex local variables
-The value of this entry should be a list of @code{(VAR VALUE)} pairs.
-Each @var{var} will be made buffer-local to the current summary buffer,
-and set to the value specified.  This is a convenient, if somewhat
-strange, way of setting variables in some groups if you don't like hooks
-much.  Note that the @var{value} won't be evaluated.
-@end table
-
-
-@node Score File Editing
-@section Score File Editing
-
-You normally enter all scoring commands from the summary buffer, but you
-might feel the urge to edit them by hand as well, so we've supplied you
-with a mode for that.  
-
-It's simply a slightly customized @code{emacs-lisp} mode, with these
-additional commands:
-
-@table @kbd
+@vindex nnvirtual-always-rescan
+If the @code{nnvirtual-always-rescan} is non-@code{nil},
+@code{nnvirtual} will always scan groups for unread articles when
+entering a virtual group.  If this variable is @code{nil} (which is the
+default) and you read articles in a component group after the virtual
+group has been activated, the read articles from the component group
+will show up when you enter the virtual group.  You'll also see this
+effect if you have two virtual groups that have a component group in
+common.  If that's the case, you should set this variable to @code{t}.
+Or you can just tap @code{M-g} on the virtual group every time before
+you enter it---it'll have much the same effect.
 
-@item C-c C-c
-@kindex C-c C-c (Score)
-@findex gnus-score-edit-done
-Save the changes you have made and return to the summary buffer
-(@code{gnus-score-edit-done}). 
+@code{nnvirtual} can have both mail and news groups as component groups.
+When responding to articles in @code{nnvirtual} groups, @code{nnvirtual}
+has to ask the back end of the component group the article comes from
+whether it is a news or mail back end.  However, when you do a @kbd{^},
+there is typically no sure way for the component back end to know this,
+and in that case @code{nnvirtual} tells Gnus that the article came from a
+not-news back end.  (Just to be on the safe side.)
 
-@item C-c C-d
-@kindex C-c C-d (Score)
-@findex gnus-score-edit-insert-date
-Insert the current date in numerical format
-(@code{gnus-score-edit-insert-date}).  This is really the day number, if
-you were wondering.
+@kbd{C-c C-n} in the message buffer will insert the @code{Newsgroups}
+line from the article you respond to in these cases.
 
-@item C-c C-p
-@kindex C-c C-p (Score)
-@findex gnus-score-pretty-print
-The adaptive score files are saved in an unformatted fashion.  If you
-intend to read one of these files, you want to @dfn{pretty print} it
-first.  This command (@code{gnus-score-pretty-print}) does that for
-you. 
+@code{nnvirtual} groups do not inherit anything but articles and marks
+from component groups---group parameters, for instance, are not
+inherited.
 
-@end table
 
-Type @kbd{M-x gnus-score-mode} to use this mode.
+@node Kibozed Groups
+@subsection Kibozed Groups
+@cindex nnkiboze
+@cindex kibozing
 
-@vindex gnus-score-mode-hook
-@code{gnus-score-menu-hook} is run in score mode buffers.
+@dfn{Kibozing} is defined by the @acronym{OED} as ``grepping through
+(parts of) the news feed''.  @code{nnkiboze} is a back end that will
+do this for you.  Oh joy!  Now you can grind any @acronym{NNTP} server
+down to a halt with useless requests!  Oh happiness!
 
-In the summary buffer you can use commands like @kbd{V f} and @kbd{V
-e} to begin editing score files.
+@kindex G k (Group)
+To create a kibozed group, use the @kbd{G k} command in the group
+buffer.
 
+The address field of the @code{nnkiboze} method is, as with
+@code{nnvirtual}, a regexp to match groups to be ``included'' in the
+@code{nnkiboze} group.  That's where most similarities between
+@code{nnkiboze} and @code{nnvirtual} end.
 
-@node Adaptive Scoring
-@section Adaptive Scoring
-@cindex adaptive scoring
+In addition to this regexp detailing component groups, an
+@code{nnkiboze} group must have a score file to say what articles are
+to be included in the group (@pxref{Scoring}).
 
-If all this scoring is getting you down, Gnus has a way of making it all
-happen automatically---as if by magic.  Or rather, as if by artificial
-stupidity, to be precise.
+@kindex M-x nnkiboze-generate-groups
+@findex nnkiboze-generate-groups
+You must run @kbd{M-x nnkiboze-generate-groups} after creating the
+@code{nnkiboze} groups you want to have.  This command will take time.
+Lots of time.  Oodles and oodles of time.  Gnus has to fetch the
+headers from all the articles in all the component groups and run them
+through the scoring process to determine if there are any articles in
+the groups that are to be part of the @code{nnkiboze} groups.
 
-@vindex gnus-use-adaptive-scoring
-When you read an article, or mark an article as read, or kill an
-article, you leave marks behind.  On exit from the group, Gnus can sniff
-these marks and add score elements depending on what marks it finds.
-You turn on this ability by setting @code{gnus-use-adaptive-scoring} to
-@code{t} or @code{(line)}.  If you want score adaptively on separate
-words appearing in the subjects, you should set this variable to
-@code{(word)}.  If you want to use both adaptive methods, set this
-variable to @code{(word line)}.
+Please limit the number of component groups by using restrictive
+regexps.  Otherwise your sysadmin may become annoyed with you, and the
+@acronym{NNTP} site may throw you off and never let you back in again.
+Stranger things have happened.
 
-@vindex gnus-default-adaptive-score-alist
-To give you complete control over the scoring process, you can customize
-the @code{gnus-default-adaptive-score-alist} variable.  For instance, it
-might look something like this:
+@code{nnkiboze} component groups do not have to be alive---they can be dead,
+and they can be foreign.  No restrictions.
 
-@lisp
-(defvar gnus-default-adaptive-score-alist
-  '((gnus-unread-mark)
-    (gnus-ticked-mark (from 4))
-    (gnus-dormant-mark (from 5))
-    (gnus-del-mark (from -4) (subject -1))
-    (gnus-read-mark (from 4) (subject 2))
-    (gnus-expirable-mark (from -1) (subject -1))
-    (gnus-killed-mark (from -1) (subject -3))
-    (gnus-kill-file-mark)
-    (gnus-ancient-mark)
-    (gnus-low-score-mark)
-    (gnus-catchup-mark (from -1) (subject -1))))
-@end lisp
+@vindex nnkiboze-directory
+The generation of an @code{nnkiboze} group means writing two files in
+@code{nnkiboze-directory}, which is @file{~/News/kiboze/} by default.
+One contains the @acronym{NOV} header lines for all the articles in
+the group, and the other is an additional @file{.newsrc} file to store
+information on what groups have been searched through to find
+component articles.
 
-As you see, each element in this alist has a mark as a key (either a
-variable name or a ``real'' mark---a character).  Following this key is
-a arbitrary number of header/score pairs.  If there are no header/score
-pairs following the key, no adaptive scoring will be done on articles
-that have that key as the article mark.  For instance, articles with
-@code{gnus-unread-mark} in the example above will not get adaptive score
-entries.
+Articles marked as read in the @code{nnkiboze} group will have
+their @acronym{NOV} lines removed from the @acronym{NOV} file.
 
-Each article can have only one mark, so just a single of these rules
-will be applied to each article.
 
-To take @code{gnus-del-mark} as an example---this alist says that all
-articles that have that mark (i.e., are marked with @samp{D}) will have a
-score entry added to lower based on the @code{From} header by -4, and
-lowered by @code{Subject} by -1.  Change this to fit your prejudices. 
+@node Gnus Unplugged
+@section Gnus Unplugged
+@cindex offline
+@cindex unplugged
+@cindex agent
+@cindex Gnus agent
+@cindex Gnus unplugged
 
-If you have marked 10 articles with the same subject with
-@code{gnus-del-mark}, the rule for that mark will be applied ten times.
-That means that that subject will get a score of ten times -1, which
-should be, unless I'm much mistaken, -10.
+In olden times (ca. February '88), people used to run their newsreaders
+on big machines with permanent connections to the net.  News transport
+was dealt with by news servers, and all the newsreaders had to do was to
+read news.  Believe it or not.
 
-If you have auto-expirable (mail) groups (@pxref{Expiring Mail}), all
-the read articles will be marked with the @samp{E} mark.  This'll
-probably make adaptive scoring slightly impossible, so auto-expiring and
-adaptive scoring doesn't really mix very well.
+Nowadays most people read news and mail at home, and use some sort of
+modem to connect to the net.  To avoid running up huge phone bills, it
+would be nice to have a way to slurp down all the news and mail, hang up
+the phone, read for several hours, and then upload any responses you
+have to make.  And then you repeat the procedure.
 
-The headers you can score on are @code{from}, @code{subject},
-@code{message-id}, @code{references}, @code{xref}, @code{lines},
-@code{chars} and @code{date}.  In addition, you can score on
-@code{followup}, which will create an adaptive score entry that matches
-on the @code{References} header using the @code{Message-ID} of the
-current article, thereby matching the following thread.  
+Of course, you can use news servers for doing this as well.  I've used
+@code{inn} together with @code{slurp}, @code{pop} and @code{sendmail}
+for some years, but doing that's a bore.  Moving the news server
+functionality up to the newsreader makes sense if you're the only person
+reading news on a machine.
 
-You can also score on @code{thread}, which will try to score all
-articles that appear in a thread.  @code{thread} matches uses a
-@code{Message-ID} to match on the @code{References} header of the
-article.  If the match is made, the @code{Message-ID} of the article is
-added to the @code{thread} rule.  (Think about it.  I'd recommend two
-aspirins afterwards.)
+Setting up Gnus as an ``offline'' newsreader is quite simple.  In
+fact, you don't even have to configure anything.
 
-If you use this scheme, you should set the score file atom @code{mark}
-to something small---like -300, perhaps, to avoid having small random
-changes result in articles getting marked as read.
+Of course, to use it as such, you have to learn a few new commands.
 
-After using adaptive scoring for a week or so, Gnus should start to
-become properly trained and enhance the authors you like best, and kill
-the authors you like least, without you having to say so explicitly. 
+@menu
+* Agent Basics::                How it all is supposed to work.
+* Agent Categories::            How to tell the Gnus Agent what to download.
+* Agent Commands::              New commands for all the buffers.
+* Agent Visuals::               Ways that the agent may effect your summary buffer.
+* Agent as Cache::              The Agent is a big cache too.
+* Agent Expiry::                How to make old articles go away.
+* Agent Regeneration::          How to recover from lost connections and other accidents.
+* Agent and IMAP::              How to use the Agent with @acronym{IMAP}.
+* Outgoing Messages::           What happens when you post/mail something?
+* Agent Variables::             Customizing is fun.
+* Example Setup::               An example @file{~/.gnus.el} file for offline people.
+* Batching Agents::             How to fetch news from a @code{cron} job.
+* Agent Caveats::               What you think it'll do and what it does.
+@end menu
 
-You can control what groups the adaptive scoring is to be performed on
-by using the score files (@pxref{Score File Format}).  This will also
-let you use different rules in different groups.
 
-@vindex gnus-adaptive-file-suffix
-The adaptive score entries will be put into a file where the name is the
-group name with @code{gnus-adaptive-file-suffix} appended.  The default
-is @samp{ADAPT}.
+@node Agent Basics
+@subsection Agent Basics
 
-@vindex gnus-score-exact-adapt-limit
-When doing adaptive scoring, substring or fuzzy matching would probably
-give you the best results in most cases.  However, if the header one
-matches is short, the possibility for false positives is great, so if
-the length of the match is less than
-@code{gnus-score-exact-adapt-limit}, exact matching will be used.  If
-this variable is @code{nil}, exact matching will always be used to avoid
-this problem.
+First, let's get some terminology out of the way.
 
-@vindex gnus-default-adaptive-word-score-alist
-As mentioned above, you can adapt either on individual words or entire
-headers.  If you adapt on words, the
-@code{gnus-default-adaptive-word-score-alist} variable says what score
-each instance of a word should add given a mark.
+The Gnus Agent is said to be @dfn{unplugged} when you have severed the
+connection to the net (and notified the Agent that this is the case).
+When the connection to the net is up again (and Gnus knows this), the
+Agent is @dfn{plugged}.
 
-@lisp
-(setq gnus-default-adaptive-word-score-alist  
-      `((,gnus-read-mark . 30)
-        (,gnus-catchup-mark . -10)
-        (,gnus-killed-mark . -20)
-        (,gnus-del-mark . -15)))
-@end lisp
+The @dfn{local} machine is the one you're running on, and which isn't
+connected to the net continuously.
 
-This is the default value.  If you have adaption on words enabled, every
-word that appears in subjects of articles marked with
-@code{gnus-read-mark} will result in a score rule that increase the
-score with 30 points.
+@dfn{Downloading} means fetching things from the net to your local
+machine.  @dfn{Uploading} is doing the opposite.
 
-@vindex gnus-default-ignored-adaptive-words
-@vindex gnus-ignored-adaptive-words
-Words that appear in the @code{gnus-default-ignored-adaptive-words} list
-will be ignored.  If you wish to add more words to be ignored, use the
-@code{gnus-ignored-adaptive-words} list instead.
+You know that Gnus gives you all the opportunity you'd ever want for
+shooting yourself in the foot.  Some people call it flexibility.  Gnus
+is also customizable to a great extent, which means that the user has a
+say on how Gnus behaves.  Other newsreaders might unconditionally shoot
+you in your foot, but with Gnus, you have a choice!
+
+Gnus is never really in plugged or unplugged state.  Rather, it applies
+that state to each server individually.  This means that some servers
+can be plugged while others can be unplugged.  Additionally, some
+servers can be ignored by the Agent altogether (which means that
+they're kinda like plugged always).
+
+So when you unplug the Agent and then wonder why is Gnus opening a
+connection to the Net, the next step to do is to look whether all
+servers are agentized.  If there is an unagentized server, you found
+the culprit.
+
+Another thing is the @dfn{offline} state.  Sometimes, servers aren't
+reachable.  When Gnus notices this, it asks you whether you want the
+server to be switched to offline state.  If you say yes, then the
+server will behave somewhat as if it was unplugged, except that Gnus
+will ask you whether you want to switch it back online again.
 
-@vindex gnus-adaptive-word-syntax-table
-When the scoring is done, @code{gnus-adaptive-word-syntax-table} is the
-syntax table in effect.  It is similar to the standard syntax table, but
-it considers numbers to be non-word-constituent characters.
+Let's take a typical Gnus session using the Agent.
 
-@vindex gnus-adaptive-word-minimum
-If @code{gnus-adaptive-word-minimum} is set to a number, the adaptive
-word scoring process will never bring down the score of an article to
-below this number.  The default is @code{nil}.
+@itemize @bullet
 
-After using this scheme for a while, it might be nice to write a
-@code{gnus-psychoanalyze-user} command to go through the rules and see
-what words you like and what words you don't like.  Or perhaps not.
+@item
+@findex gnus-unplugged
+You start Gnus with @code{gnus-unplugged}.  This brings up the Gnus
+Agent in a disconnected state.  You can read all the news that you have
+already fetched while in this mode.
 
-Note that the adaptive word scoring thing is highly experimental and is
-likely to change in the future.  Initial impressions seem to indicate
-that it's totally useless as it stands.  Some more work (involving more
-rigorous statistical methods) will have to be done to make this useful. 
+@item
+You then decide to see whether any new news has arrived.  You connect
+your machine to the net (using PPP or whatever), and then hit @kbd{J j}
+to make Gnus become @dfn{plugged} and use @kbd{g} to check for new mail
+as usual.  To check for new mail in unplugged mode (@pxref{Mail
+Source Specifiers}).
 
+@item
+You can then read the new news immediately, or you can download the
+news onto your local machine.  If you want to do the latter, you press
+@kbd{g} to check if there are any new news and then @kbd{J s} to fetch
+all the eligible articles in all the groups.  (To let Gnus know which
+articles you want to download, @pxref{Agent Categories}).
 
-@node Home Score File
-@section Home Score File
+@item
+After fetching the articles, you press @kbd{J j} to make Gnus become
+unplugged again, and you shut down the PPP thing (or whatever).  And
+then you read the news offline.
 
-The score file where new score file entries will go is called the
-@dfn{home score file}.  This is normally (and by default) the score file
-for the group itself.  For instance, the home score file for
-@samp{gnu.emacs.gnus} is @file{gnu.emacs.gnus.SCORE}.
+@item
+And then you go to step 2.
+@end itemize
 
-However, this may not be what you want.  It is often convenient to share
-a common home score file among many groups---all @samp{emacs} groups
-could perhaps use the same home score file.
+Here are some things you should do the first time (or so) that you use
+the Agent.
 
-@vindex gnus-home-score-file
-The variable that controls this is @code{gnus-home-score-file}.  It can
-be:
+@itemize @bullet
 
-@enumerate
 @item
-A string.  Then this file will be used as the home score file for all
-groups. 
+Decide which servers should be covered by the Agent.  If you have a mail
+back end, it would probably be nonsensical to have it covered by the
+Agent.  Go to the server buffer (@kbd{^} in the group buffer) and press
+@kbd{J a} on the server (or servers) that you wish to have covered by the
+Agent (@pxref{Server Agent Commands}), or @kbd{J r} on automatically
+added servers you do not wish to have covered by the Agent.  By default,
+all @code{nntp} and @code{nnimap} servers in @code{gnus-select-method} and
+@code{gnus-secondary-select-methods} are agentized.
 
 @item
-A function. The result of this function will be used as the home score
-file.  The function will be called with the name of the group as the
-parameter. 
+Decide on download policy.  It's fairly simple once you decide whether
+you are going to use agent categories, topic parameters, and/or group
+parameters to implement your policy.  If you're new to gnus, it
+is probably best to start with a category, @xref{Agent Categories}.
+
+Both topic parameters (@pxref{Topic Parameters}) and agent categories
+(@pxref{Agent Categories}) provide for setting a policy that applies
+to multiple groups.  Which you use is entirely up to you.  Topic
+parameters do override categories so, if you mix the two, you'll have
+to take that into account.  If you have a few groups that deviate from
+your policy, you can use group parameters (@pxref{Group Parameters}) to
+configure them.
 
 @item
-A list.  The elements in this list can be:
+Uhm@dots{} that's it.
+@end itemize
 
-@enumerate
-@item 
-@var{(regexp file-name)}.  If the @var{regexp} matches the group name,
-the @var{file-name} will will be used as the home score file.
 
-@item 
-A function. If the function returns non-nil, the result will be used as
-the home score file.
+@node Agent Categories
+@subsection Agent Categories
 
-@item 
-A string.  Use the string as the home score file.
-@end enumerate
+One of the main reasons to integrate the news transport layer into the
+newsreader is to allow greater control over what articles to download.
+There's not much point in downloading huge amounts of articles, just to
+find out that you're not interested in reading any of them.  It's better
+to be somewhat more conservative in choosing what to download, and then
+mark the articles for downloading manually if it should turn out that
+you're interested in the articles anyway.
 
-The list will be traversed from the beginning towards the end looking
-for matches.
+One of the more effective methods for controlling what is to be
+downloaded is to create a @dfn{category} and then assign some (or all)
+groups to this category.  Groups that do not belong in any other
+category belong to the @code{default} category.  Gnus has its own
+buffer for creating and managing categories.
+
+If you prefer, you can also use group parameters (@pxref{Group
+Parameters}) and topic parameters (@pxref{Topic Parameters}) for an
+alternative approach to controlling the agent.  The only real
+difference is that categories are specific to the agent (so there is
+less to learn) while group and topic parameters include the kitchen
+sink.
+
+Since you can set agent parameters in several different places we have
+a rule to decide which source to believe.  This rule specifies that
+the parameter sources are checked in the following order: group
+parameters, topic parameters, agent category, and finally customizable
+variables.  So you can mix all of these sources to produce a wide range
+of behavior, just don't blame me if you don't remember where you put
+your settings.
 
-@end enumerate
+@menu
+* Category Syntax::             What a category looks like.
+* Category Buffer::             A buffer for maintaining categories.
+* Category Variables::          Customize'r'Us.
+@end menu
 
-So, if you want to use just a single score file, you could say:
 
-@lisp
-(setq gnus-home-score-file
-      "my-total-score-file.SCORE")
-@end lisp
+@node Category Syntax
+@subsubsection Category Syntax
 
-If you want to use @file{gnu.SCORE} for all @samp{gnu} groups and
-@file{rec.SCORE} for all @samp{rec} groups (and so on), you can say:
+A category consists of a name, the list of groups belonging to the
+category, and a number of optional parameters that override the
+customizable variables.  The complete list of agent parameters are
+listed below.
+
+@cindex Agent Parameters
+@table @code
+@item gnus-agent-cat-name
+The name of the category.
+
+@item gnus-agent-cat-groups
+The list of groups that are in this category.
+
+@item gnus-agent-cat-predicate
+A predicate which (generally) gives a rough outline of which articles
+are eligible for downloading; and
+
+@item gnus-agent-cat-score-file
+a score rule which (generally) gives you a finer granularity when
+deciding what articles to download.  (Note that this @dfn{download
+score} is not necessarily related to normal scores.)
+
+@item gnus-agent-cat-enable-expiration
+a boolean indicating whether the agent should expire old articles in
+this group.  Most groups should be expired to conserve disk space.  In
+fact, its probably safe to say that the gnus.* hierarchy contains the
+only groups that should not be expired.
+
+@item gnus-agent-cat-days-until-old
+an integer indicating the number of days that the agent should wait
+before deciding that a read article is safe to expire.
+
+@item gnus-agent-cat-low-score
+an integer that overrides the value of @code{gnus-agent-low-score}.
+
+@item gnus-agent-cat-high-score
+an integer that overrides the value of @code{gnus-agent-high-score}.
+
+@item gnus-agent-cat-length-when-short
+an integer that overrides the value of
+@code{gnus-agent-short-article}.
+
+@item gnus-agent-cat-length-when-long
+an integer that overrides the value of @code{gnus-agent-long-article}.
+
+@c @item gnus-agent-cat-disable-undownloaded-faces
+@c a symbol indicating whether the summary buffer should @emph{not} display
+@c undownloaded articles using the gnus-summary-*-undownloaded-face
+@c faces.  The symbol nil will enable the use of undownloaded faces while
+@c all other symbols disable them.
+
+@item gnus-agent-cat-enable-undownloaded-faces
+a symbol indicating whether the summary buffer should display
+undownloaded articles using the gnus-summary-*-undownloaded-face
+faces.  The symbol nil will disable the use of undownloaded faces while
+all other symbols enable them.
+@end table
+
+The name of a category can not be changed once the category has been
+created.
+
+Each category maintains a list of groups that are exclusive members of
+that category.  The exclusivity rule is automatically enforced, add a
+group to a new category and it is automatically removed from its old
+category.
+
+A predicate in its simplest form can be a single predicate such as
+@code{true} or @code{false}.  These two will download every available
+article or nothing respectively.  In the case of these two special
+predicates an additional score rule is superfluous.
+
+Predicates of @code{high} or @code{low} download articles in respect of
+their scores in relationship to @code{gnus-agent-high-score} and
+@code{gnus-agent-low-score} as described below.
+
+To gain even finer control of what is to be regarded eligible for
+download a predicate can consist of a number of predicates with logical
+operators sprinkled in between.
+
+Perhaps some examples are in order.
+
+Here's a simple predicate.  (It's the default predicate, in fact, used
+for all groups that don't belong to any other category.)
 
 @lisp
-(setq gnus-home-score-file
-      'gnus-hierarchial-home-score-file)
+short
 @end lisp
 
-This is a ready-made function provided for your convenience.
+Quite simple, eh?  This predicate is true if and only if the article is
+short (for some value of ``short'').
 
-If you want to have one score file for the @samp{emacs} groups and
-another for the @samp{comp} groups, while letting all other groups use
-their own home score files:
+Here's a more complex predicate:
 
 @lisp
-(setq gnus-home-score-file
-      ;; All groups that match the regexp "\\.emacs"
-      '("\\.emacs" "emacs.SCORE")
-      ;; All the comp groups in one score file
-       ("^comp" "comp.SCORE"))
+(or high
+    (and
+     (not low)
+     (not long)))
 @end lisp
-   
-@vindex gnus-home-adapt-file
-@code{gnus-home-adapt-file} works exactly the same way as
-@code{gnus-home-score-file}, but says what the home adaptive score file
-is instead.  All new adaptive file entries will go into the file
-specified by this variable, and the same syntax is allowed.
 
-In addition to using @code{gnus-home-score-file} and
-@code{gnus-home-adapt-file}, you can also use group parameters
-(@pxref{Group Parameters}) and topic parameters (@pxref{Topic
-Parameters}) to achieve much the same.  Group and topic parameters take
-precedence over this variable.
+This means that an article should be downloaded if it has a high score,
+or if the score is not low and the article is not long.  You get the
+drift.
 
+The available logical operators are @code{or}, @code{and} and
+@code{not}.  (If you prefer, you can use the more ``C''-ish operators
+@samp{|}, @code{&} and @code{!} instead.)
 
-@node Followups To Yourself
-@section Followups To Yourself
+The following predicates are pre-defined, but if none of these fit what
+you want to do, you can write your own.
 
-Gnus offers two commands for picking out the @code{Message-ID} header in
-the current buffer.  Gnus will then add a score rule that scores using
-this @code{Message-ID} on the @code{References} header of other
-articles.  This will, in effect, increase the score of all articles that
-respond to the article in the current buffer.  Quite useful if you want
-to easily note when people answer what you've said.
+When evaluating each of these predicates, the named constant will be
+bound to the value determined by calling
+@code{gnus-agent-find-parameter} on the appropriate parameter.  For
+example, gnus-agent-short-article will be bound to
+@code{(gnus-agent-find-parameter group 'agent-short-article)}.  This
+means that you can specify a predicate in your category then tune that
+predicate to individual groups.
 
 @table @code
+@item short
+True iff the article is shorter than @code{gnus-agent-short-article}
+lines; default 100.
 
-@item gnus-score-followup-article
-@findex gnus-score-followup-article
-This will add a score to articles that directly follow up your own
-article. 
-
-@item gnus-score-followup-thread
-@findex gnus-score-followup-thread
-This will add a score to all articles that appear in a thread ``below''
-your own article.
-@end table
+@item long
+True iff the article is longer than @code{gnus-agent-long-article}
+lines; default 200.
 
-@vindex message-sent-hook
-These two functions are both primarily meant to be used in hooks like
-@code{message-sent-hook}.  
+@item low
+True iff the article has a download score less than
+@code{gnus-agent-low-score}; default 0.
 
-If you look closely at your own @code{Message-ID}, you'll notice that
-the first two or three characters are always the same.  Here's two of
-mine:  
+@item high
+True iff the article has a download score greater than
+@code{gnus-agent-high-score}; default 0.
 
-@example
-<x6u3u47icf.fsf@@eyesore.no>
-<x6sp9o7ibw.fsf@@eyesore.no>
-@end example
+@item spam
+True iff the Gnus Agent guesses that the article is spam.  The
+heuristics may change over time, but at present it just computes a
+checksum and sees whether articles match.
 
-So ``my'' ident on this machine is @samp{x6}.  This can be
-exploited---the following rule will raise the score on all followups to
-myself: 
+@item true
+Always true.
 
-@lisp
-("references"
- ("<x6[0-9a-z]+\\.fsf\\(_-_\\)?@@.*eyesore.no>"
-  1000 nil r))
-@end lisp
+@item false
+Always false.
+@end table
 
-Whether it's the first two or first three characters that are ``yours''
-is system-dependent.
+If you want to create your own predicate function, here's what you have
+to know:  The functions are called with no parameters, but the
+@code{gnus-headers} and @code{gnus-score} dynamic variables are bound to
+useful values.
 
+For example, you could decide that you don't want to download articles
+that were posted more than a certain number of days ago (e.g. posted
+more than @code{gnus-agent-expire-days} ago) you might write a function
+something along the lines of the following:
 
-@node Scoring Tips
-@section Scoring Tips
-@cindex scoring tips
+@lisp
+(defun my-article-old-p ()
+  "Say whether an article is old."
+  (< (time-to-days (date-to-time (mail-header-date gnus-headers)))
+     (- (time-to-days (current-time)) gnus-agent-expire-days)))
+@end lisp
 
-@table @dfn
+with the predicate then defined as:
 
-@item Crossposts
-@cindex crossposts
-@cindex scoring crossposts
-If you want to lower the score of crossposts, the line to match on is
-the @code{Xref} header.
 @lisp
-("xref" (" talk.politics.misc:" -1000))
+(not my-article-old-p)
 @end lisp
 
-@item Multiple crossposts
-If you want to lower the score of articles that have been crossposted to
-more than, say, 3 groups:
+or you could append your predicate to the predefined
+@code{gnus-category-predicate-alist} in your @file{~/.gnus.el} or
+wherever.
+
 @lisp
-("xref" ("[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+" -1000 nil r))
+(require 'gnus-agent)
+(setq  gnus-category-predicate-alist
+  (append gnus-category-predicate-alist
+         '((old . my-article-old-p))))
 @end lisp
 
-@item Matching on the body
-This is generally not a very good idea---it takes a very long time.
-Gnus actually has to fetch each individual article from the server.  But
-you might want to anyway, I guess.  Even though there are three match
-keys (@code{Head}, @code{Body} and @code{All}), you should choose one
-and stick with it in each score file.  If you use any two, each article
-will be fetched @emph{twice}.  If you want to match a bit on the
-@code{Head} and a bit on the @code{Body}, just use @code{All} for all
-the matches.  
+and simply specify your predicate as:
 
-@item Marking as read
-You will probably want to mark articles that has a score below a certain
-number as read.  This is most easily achieved by putting the following
-in your @file{all.SCORE} file:
 @lisp
-((mark -100))
+(not old)
 @end lisp
-You may also consider doing something similar with @code{expunge}.  
 
-@item Negated character classes
-If you say stuff like @code{[^abcd]*}, you may get unexpected results.
-That will match newlines, which might lead to, well, The Unknown.  Say
-@code{[^abcd\n]*} instead.
-@end table
+If/when using something like the above, be aware that there are many
+misconfigured systems/mailers out there and so an article's date is not
+always a reliable indication of when it was posted.  Hell, some people
+just don't give a damn.
 
+The above predicates apply to @emph{all} the groups which belong to the
+category.  However, if you wish to have a specific predicate for an
+individual group within a category, or you're just too lazy to set up a
+new category, you can enter a group's individual predicate in its group
+parameters like so:
 
-@node Reverse Scoring
-@section Reverse Scoring
-@cindex reverse scoring
+@lisp
+(agent-predicate . short)
+@end lisp
 
-If you want to keep just articles that have @samp{Sex with Emacs} in the
-subject header, and expunge all other articles, you could put something
-like this in your score file:
+This is the group/topic parameter equivalent of the agent category default.
+Note that when specifying a single word predicate like this, the
+@code{agent-predicate} specification must be in dotted pair notation.
+
+The equivalent of the longer example from above would be:
 
 @lisp
-(("subject"
-  ("Sex with Emacs" 2))
- (mark 1)
- (expunge 1))
+(agent-predicate or high (and (not low) (not long)))
 @end lisp
 
-So, you raise all articles that match @samp{Sex with Emacs} and mark the
-rest as read, and expunge them to boot.
+The outer parenthesis required in the category specification are not
+entered here as, not being in dotted pair notation, the value of the
+predicate is assumed to be a list.
 
 
-@node Global Score Files
-@section Global Score Files
-@cindex global score files
+Now, the syntax of the download score is the same as the syntax of
+normal score files, except that all elements that require actually
+seeing the article itself are verboten.  This means that only the
+following headers can be scored on: @code{Subject}, @code{From},
+@code{Date}, @code{Message-ID}, @code{References}, @code{Chars},
+@code{Lines}, and @code{Xref}.
 
-Sure, other newsreaders have ``global kill files''.  These are usually
-nothing more than a single kill file that applies to all groups, stored
-in the user's home directory.  Bah!  Puny, weak newsreaders!
+As with predicates, the specification of the @code{download score rule}
+to use in respect of a group can be in either the category definition if
+it's to be applicable to all groups in therein, or a group's parameters
+if it's to be specific to that group.
 
-What I'm talking about here are Global Score Files.  Score files from
-all over the world, from users everywhere, uniting all nations in one
-big, happy score file union!  Ange-score!  New and untested!
+In both of these places the @code{download score rule} can take one of
+three forms:
 
-@vindex gnus-global-score-files
-All you have to do to use other people's score files is to set the
-@code{gnus-global-score-files} variable.  One entry for each score file,
-or each score file directory.  Gnus will decide by itself what score
-files are applicable to which group.
+@enumerate
+@item
+Score rule
 
-Say you want to use the score file
-@file{/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE} and
-all score files in the @file{/ftp@@ftp.some-where:/pub/score} directory:
+This has the same syntax as a normal Gnus score file except only a
+subset of scoring keywords are available as mentioned above.
+
+example:
+
+@itemize @bullet
+@item
+Category specification
 
 @lisp
-(setq gnus-global-score-files
-      '("/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE"
-        "/ftp@@ftp.some-where:/pub/score/"))
+(("from"
+       ("Lars Ingebrigtsen" 1000000 nil s))
+("lines"
+       (500 -100 nil <)))
 @end lisp
 
-@findex gnus-score-search-global-directories
-Simple, eh?  Directory names must end with a @samp{/}.  These
-directories are typically scanned only once during each Gnus session.
-If you feel the need to manually re-scan the remote directories, you can
-use the @code{gnus-score-search-global-directories} command.
+@item
+Group/Topic Parameter specification
 
-Note that, at present, using this option will slow down group entry
-somewhat.  (That is---a lot.)
+@lisp
+(agent-score ("from"
+                   ("Lars Ingebrigtsen" 1000000 nil s))
+             ("lines"
+                   (500 -100 nil <)))
+@end lisp
 
-If you want to start maintaining score files for other people to use,
-just put your score file up for anonymous ftp and announce it to the
-world.  Become a retro-moderator!  Participate in the retro-moderator
-wars sure to ensue, where retro-moderators battle it out for the
-sympathy of the people, luring them to use their score files on false
-premises!  Yay!  The net is saved!
+Again, note the omission of the outermost parenthesis here.
+@end itemize
 
-Here are some tips for the would-be retro-moderator, off the top of my
-head: 
+@item
+Agent score file
 
-@itemize @bullet
+These score files must @emph{only} contain the permitted scoring
+keywords stated above.
 
-@item 
-Articles heavily crossposted are probably junk. 
-@item
-To lower a single inappropriate article, lower by @code{Message-ID}.
-@item
-Particularly brilliant authors can be raised on a permanent basis. 
+example:
+
+@itemize @bullet
 @item
-Authors that repeatedly post off-charter for the group can safely be
-lowered out of existence.
+Category specification
+
+@lisp
+("~/News/agent.SCORE")
+@end lisp
+
+or perhaps
+
+@lisp
+("~/News/agent.SCORE" "~/News/agent.group.SCORE")
+@end lisp
+
 @item
-Set the @code{mark} and @code{expunge} atoms to obliterate the nastiest
-articles completely.
+Group Parameter specification
 
-@item 
-Use expiring score entries to keep the size of the file down.  You
-should probably have a long expiry period, though, as some sites keep
-old articles for a long time.
+@lisp
+(agent-score "~/News/agent.SCORE")
+@end lisp
+
+Additional score files can be specified as above.  Need I say anything
+about parenthesis?
 @end itemize
 
-... I wonder whether other newsreaders will support global score files
-in the future.  @emph{Snicker}.  Yup, any day now, newsreaders like Blue
-Wave, xrn and 1stReader are bound to implement scoring.  Should we start
-holding our breath yet?
+@item
+Use @code{normal} score files
 
+If you don't want to maintain two sets of scoring rules for a group, and
+your desired @code{downloading} criteria for a group are the same as your
+@code{reading} criteria then you can tell the agent to refer to your
+@code{normal} score files when deciding what to download.
 
-@node Kill Files
-@section Kill Files
-@cindex kill files
-
-Gnus still supports those pesky old kill files.  In fact, the kill file
-entries can now be expiring, which is something I wrote before Daniel
-Quinlan thought of doing score files, so I've left the code in there.
+These directives in either the category definition or a group's
+parameters will cause the agent to read in all the applicable score
+files for a group, @emph{filtering out} those sections that do not
+relate to one of the permitted subset of scoring keywords.
 
-In short, kill processing is a lot slower (and I do mean @emph{a lot})
-than score processing, so it might be a good idea to rewrite your kill
-files into score files.
+@itemize @bullet
+@item
+Category Specification
 
-Anyway, a kill file is a normal @code{emacs-lisp} file.  You can put any
-forms into this file, which means that you can use kill files as some
-sort of primitive hook function to be run on group entry, even though
-that isn't a very good idea.
+@lisp
+file
+@end lisp
 
-Normal kill files look like this:
+@item
+Group Parameter specification
 
 @lisp
-(gnus-kill "From" "Lars Ingebrigtsen")
-(gnus-kill "Subject" "ding")
-(gnus-expunge "X")
+(agent-score . file)
 @end lisp
+@end itemize
+@end enumerate
 
-This will mark every article written by me as read, and remove the
-marked articles from the summary buffer.  Very useful, you'll agree.
+@node Category Buffer
+@subsubsection Category Buffer
 
-Other programs use a totally different kill file syntax.  If Gnus
-encounters what looks like a @code{rn} kill file, it will take a stab at
-interpreting it. 
+You'd normally do all category maintenance from the category buffer.
+When you enter it for the first time (with the @kbd{J c} command from
+the group buffer), you'll only see the @code{default} category.
 
-Two summary functions for editing a GNUS kill file:
+The following commands are available in this buffer:
 
 @table @kbd
+@item q
+@kindex q (Category)
+@findex gnus-category-exit
+Return to the group buffer (@code{gnus-category-exit}).
 
-@item M-k
-@kindex M-k (Summary)
-@findex gnus-summary-edit-local-kill
-Edit this group's kill file (@code{gnus-summary-edit-local-kill}).
+@item e
+@kindex e (Category)
+@findex gnus-category-customize-category
+Use a customization buffer to set all of the selected category's
+parameters at one time (@code{gnus-category-customize-category}).
 
-@item M-K
-@kindex M-K (Summary)
-@findex gnus-summary-edit-global-kill
-Edit the general kill file (@code{gnus-summary-edit-global-kill}).
-@end table
+@item k
+@kindex k (Category)
+@findex gnus-category-kill
+Kill the current category (@code{gnus-category-kill}).
 
-Two group mode functions for editing the kill files:
+@item c
+@kindex c (Category)
+@findex gnus-category-copy
+Copy the current category (@code{gnus-category-copy}).
 
-@table @kbd
+@item a
+@kindex a (Category)
+@findex gnus-category-add
+Add a new category (@code{gnus-category-add}).
 
-@item M-k
-@kindex M-k (Group)
-@findex gnus-group-edit-local-kill
-Edit this group's kill file (@code{gnus-group-edit-local-kill}).
+@item p
+@kindex p (Category)
+@findex gnus-category-edit-predicate
+Edit the predicate of the current category
+(@code{gnus-category-edit-predicate}).
 
-@item M-K
-@kindex M-K (Group)
-@findex gnus-group-edit-global-kill
-Edit the general kill file (@code{gnus-group-edit-global-kill}).
+@item g
+@kindex g (Category)
+@findex gnus-category-edit-groups
+Edit the list of groups belonging to the current category
+(@code{gnus-category-edit-groups}).
+
+@item s
+@kindex s (Category)
+@findex gnus-category-edit-score
+Edit the download score rule of the current category
+(@code{gnus-category-edit-score}).
+
+@item l
+@kindex l (Category)
+@findex gnus-category-list
+List all the categories (@code{gnus-category-list}).
 @end table
 
-Kill file variables:
 
-@table @code
-@item gnus-kill-file-name
-@vindex gnus-kill-file-name
-A kill file for the group @samp{soc.motss} is normally called
-@file{soc.motss.KILL}.  The suffix appended to the group name to get
-this file name is detailed by the @code{gnus-kill-file-name} variable.
-The ``global'' kill file (not in the score file sense of ``global'', of
-course) is just called @file{KILL}.
+@node Category Variables
+@subsubsection Category Variables
 
-@vindex gnus-kill-save-kill-file
-@item gnus-kill-save-kill-file
-If this variable is non-@code{nil}, Gnus will save the
-kill file after processing, which is necessary if you use expiring
-kills. 
+@table @code
+@item gnus-category-mode-hook
+@vindex gnus-category-mode-hook
+Hook run in category buffers.
 
-@item gnus-apply-kill-hook
-@vindex gnus-apply-kill-hook
-@findex gnus-apply-kill-file-unless-scored
-@findex gnus-apply-kill-file
-A hook called to apply kill files to a group.  It is
-@code{(gnus-apply-kill-file)} by default.  If you want to ignore the
-kill file if you have a score file for the same group, you can set this
-hook to @code{(gnus-apply-kill-file-unless-scored)}.  If you don't want
-kill files to be processed, you should set this variable to @code{nil}.
+@item gnus-category-line-format
+@vindex gnus-category-line-format
+Format of the lines in the category buffer (@pxref{Formatting
+Variables}).  Valid elements are:
 
-@item gnus-kill-file-mode-hook
-@vindex gnus-kill-file-mode-hook
-A hook called in kill-file mode buffers.
+@table @samp
+@item c
+The name of the category.
 
+@item g
+The number of groups in the category.
 @end table
 
+@item gnus-category-mode-line-format
+@vindex gnus-category-mode-line-format
+Format of the category mode line (@pxref{Mode Line Formatting}).
 
-@node Converting Kill Files
-@section Converting Kill Files
-@cindex kill files
-@cindex converting kill files
+@item gnus-agent-short-article
+@vindex gnus-agent-short-article
+Articles that have fewer lines than this are short.  Default 100.
 
-If you have loads of old kill files, you may want to convert them into
-score files.  If they are ``regular'', you can use
-the @file{gnus-kill-to-score.el} package; if not, you'll have to do it
-by hand.
+@item gnus-agent-long-article
+@vindex gnus-agent-long-article
+Articles that have more lines than this are long.  Default 200.
 
-The kill to score conversion package isn't included in Gnus by default.
-You can fetch it from
-@file{http://www.ifi.uio.no/~larsi/ding-other/gnus-kill-to-score}.  
+@item gnus-agent-low-score
+@vindex gnus-agent-low-score
+Articles that have a score lower than this have a low score.  Default
+0.
 
-If your old kill files are very complex---if they contain more
-non-@code{gnus-kill} forms than not, you'll have to convert them by
-hand.  Or just let them be as they are.  Gnus will still use them as
-before. 
+@item gnus-agent-high-score
+@vindex gnus-agent-high-score
+Articles that have a score higher than this have a high score.  Default
+0.
+
+@item gnus-agent-expire-days
+@vindex gnus-agent-expire-days
+The number of days that a @samp{read} article must stay in the agent's
+local disk before becoming eligible for expiration (While the name is
+the same, this doesn't mean expiring the article on the server.  It
+just means deleting the local copy of the article).  What is also
+important to understand is that the counter starts with the time the
+article was written to the local disk and not the time the article was
+read.
+Default 7.
+
+@item gnus-agent-enable-expiration
+@vindex gnus-agent-enable-expiration
+Determines whether articles in a group are, by default, expired or
+retained indefinitely.  The default is @code{ENABLE} which means that
+you'll have to disable expiration when desired.  On the other hand,
+you could set this to @code{DISABLE}.  In that case, you would then
+have to enable expiration in selected groups.
 
+@end table
 
-@node GroupLens
-@section GroupLens
-@cindex GroupLens
 
-GroupLens is a collaborative filtering system that helps you work
-together with other people to find the quality news articles out of the
-huge volume of news articles generated every day.
+@node Agent Commands
+@subsection Agent Commands
+@findex gnus-agent-toggle-plugged
+@kindex J j (Agent)
+
+All the Gnus Agent commands are on the @kbd{J} submap.  The @kbd{J j}
+(@code{gnus-agent-toggle-plugged}) command works in all modes, and
+toggles the plugged/unplugged state of the Gnus Agent.
 
-To accomplish this the GroupLens system combines your opinions about
-articles you have already read with the opinions of others who have done
-likewise and gives you a personalized prediction for each unread news
-article.  Think of GroupLens as a matchmaker.  GroupLens watches how you
-rate articles, and finds other people that rate articles the same way.
-Once it has found some people you agree with it tells you, in the form
-of a prediction, what they thought of the article.  You can use this
-prediction to help you decide whether or not you want to read the
-article.
 
 @menu
-* Using GroupLens::          How to make Gnus use GroupLens.
-* Rating Articles::          Letting GroupLens know how you rate articles.
-* Displaying Predictions::   Displaying predictions given by GroupLens.
-* GroupLens Variables::      Customizing GroupLens.
+* Group Agent Commands::        Configure groups and fetch their contents.
+* Summary Agent Commands::      Manually select then fetch specific articles.
+* Server Agent Commands::       Select the servers that are supported by the agent.
 @end menu
 
 
-@node Using GroupLens
-@subsection Using GroupLens
 
-To use GroupLens you must register a pseudonym with your local Better
-Bit Bureau (BBB).
-@samp{http://www.cs.umn.edu/Research/GroupLens/bbb.html} is the only
-better bit in town at the moment.
 
-Once you have registered you'll need to set a couple of variables.
+@node Group Agent Commands
+@subsubsection Group Agent Commands
 
-@table @code
+@table @kbd
+@item J u
+@kindex J u (Agent Group)
+@findex gnus-agent-fetch-groups
+Fetch all eligible articles in the current group
+(@code{gnus-agent-fetch-groups}).
 
-@item gnus-use-grouplens
-@vindex gnus-use-grouplens
-Setting this variable to a non-@code{nil} value will make Gnus hook into
-all the relevant GroupLens functions.
+@item J c
+@kindex J c (Agent Group)
+@findex gnus-enter-category-buffer
+Enter the Agent category buffer (@code{gnus-enter-category-buffer}).
 
-@item grouplens-pseudonym
-@vindex grouplens-pseudonym
-This variable should be set to the pseudonym you got when registering
-with the Better Bit Bureau.
+@item J s
+@kindex J s (Agent Group)
+@findex gnus-agent-fetch-session
+Fetch all eligible articles in all groups
+(@code{gnus-agent-fetch-session}).
 
-@item grouplens-newsgroups
-@vindex grouplens-newsgroups
-A list of groups that you want to get GroupLens predictions for. 
+@item J S
+@kindex J S (Agent Group)
+@findex gnus-group-send-queue
+Send all sendable messages in the queue group
+(@code{gnus-group-send-queue}).  @xref{Drafts}.
 
-@end table
+@item J a
+@kindex J a (Agent Group)
+@findex gnus-agent-add-group
+Add the current group to an Agent category
+(@code{gnus-agent-add-group}).  This command understands the
+process/prefix convention (@pxref{Process/Prefix}).
 
-That's the minimum of what you need to get up and running with GroupLens.
-Once you've registered, GroupLens will start giving you scores for
-articles based on the average of what other people think.  But, to get
-the real benefit of GroupLens you need to start rating articles
-yourself.  Then the scores GroupLens gives you will be personalized for
-you, based on how the people you usually agree with have already rated.
+@item J r
+@kindex J r (Agent Group)
+@findex gnus-agent-remove-group
+Remove the current group from its category, if any
+(@code{gnus-agent-remove-group}).  This command understands the
+process/prefix convention (@pxref{Process/Prefix}).
 
+@item J Y
+@kindex J Y (Agent Group)
+@findex gnus-agent-synchronize-flags
+Synchronize flags changed while unplugged with remote server, if any.
 
-@node Rating Articles
-@subsection Rating Articles
 
-In GroupLens, an article is rated on a scale from 1 to 5, inclusive.
-Where 1 means something like this article is a waste of bandwidth and 5
-means that the article was really good.  The basic question to ask
-yourself is, "on a scale from 1 to 5 would I like to see more articles
-like this one?"
+@end table
 
-There are four ways to enter a rating for an article in GroupLens.
+
+@node Summary Agent Commands
+@subsubsection Summary Agent Commands
 
 @table @kbd
+@item J #
+@kindex J # (Agent Summary)
+@findex gnus-agent-mark-article
+Mark the article for downloading (@code{gnus-agent-mark-article}).
 
-@item r
-@kindex r (GroupLens)
-@findex bbb-summary-rate-article
-This function will prompt you for a rating on a scale of one to five.
+@item J M-#
+@kindex J M-# (Agent Summary)
+@findex gnus-agent-unmark-article
+Remove the downloading mark from the article
+(@code{gnus-agent-unmark-article}).
 
-@item k
-@kindex k (GroupLens)
-@findex grouplens-score-thread
-This function will prompt you for a rating, and rate all the articles in
-the thread.  This is really useful for some of those long running giant
-threads in rec.humor.
+@cindex %
+@item @@
+@kindex @@ (Agent Summary)
+@findex gnus-agent-toggle-mark
+Toggle whether to download the article
+(@code{gnus-agent-toggle-mark}).  The download mark is @samp{%} by
+default.
 
-@end table
+@item J c
+@kindex J c (Agent Summary)
+@findex gnus-agent-catchup
+Mark all articles as read (@code{gnus-agent-catchup}) that are neither cached, downloaded, nor downloadable.
 
-The next two commands, @kbd{n} and @kbd{,} take a numerical prefix to be
-the score of the article you're reading.
+@item J S
+@kindex J S (Agent Summary)
+@findex gnus-agent-fetch-group
+Download all eligible (@pxref{Agent Categories}) articles in this group.
+(@code{gnus-agent-fetch-group}).
 
-@table @kbd
+@item J s
+@kindex J s (Agent Summary)
+@findex gnus-agent-fetch-series
+Download all processable articles in this group.
+(@code{gnus-agent-fetch-series}).
 
-@item 1-5 n
-@kindex n (GroupLens)
-@findex grouplens-next-unread-article
-Rate the article and go to the next unread article.
-
-@item 1-5 ,
-@kindex , (GroupLens)
-@findex grouplens-best-unread-article
-Rate the article and go to the next unread article with the highest score.
+@item J u
+@kindex J u (Agent Summary)
+@findex gnus-agent-summary-fetch-group
+Download all downloadable articles in the current group
+(@code{gnus-agent-summary-fetch-group}).
 
 @end table
 
-If you want to give the current article a score of 4 and then go to the
-next article, just type @kbd{4 n}.
 
+@node Server Agent Commands
+@subsubsection Server Agent Commands
 
-@node Displaying Predictions
-@subsection Displaying Predictions
+@table @kbd
+@item J a
+@kindex J a (Agent Server)
+@findex gnus-agent-add-server
+Add the current server to the list of servers covered by the Gnus Agent
+(@code{gnus-agent-add-server}).
 
-GroupLens makes a prediction for you about how much you will like a
-news article.  The predictions from GroupLens are on a scale from 1 to
-5, where 1 is the worst and 5 is the best.  You can use the predictions
-from GroupLens in one of three ways controlled by the variable
-@code{gnus-grouplens-override-scoring}.
+@item J r
+@kindex J r (Agent Server)
+@findex gnus-agent-remove-server
+Remove the current server from the list of servers covered by the Gnus
+Agent (@code{gnus-agent-remove-server}).
 
-@vindex gnus-grouplens-override-scoring
-There are three ways to display predictions in grouplens.  You may
-choose to have the GroupLens scores contribute to, or override the
-regular gnus scoring mechanism. override is the default; however, some
-people prefer to see the Gnus scores plus the grouplens scores.  To get
-the separate scoring behavior you need to set
-@code{gnus-grouplens-override-scoring} to @code{'separate}.  To have the
-GroupLens predictions combined with the grouplens scores set it to
-@code{'override} and to combine the scores set
-@code{gnus-grouplens-override-scoring} to @code{'combine}.  When you use
-the combine option you will also want to set the values for
-@code{grouplens-prediction-offset} and
-@code{grouplens-score-scale-factor}.
+@end table
 
-@vindex grouplens-prediction-display
-In either case, GroupLens gives you a few choices for how you would like
-to see your predictions displayed.  The display of predictions is
-controlled by the @code{grouplens-prediction-display} variable.
 
-The following are valid values for that variable.
+@node Agent Visuals
+@subsection Agent Visuals
+
+If you open a summary while unplugged and, Gnus knows from the group's
+active range that there are more articles than the headers currently
+stored in the Agent, you may see some articles whose subject looks
+something like @samp{[Undownloaded article #####]}.  These are
+placeholders for the missing headers.  Aside from setting a mark,
+there is not much that can be done with one of these placeholders.
+When Gnus finally gets a chance to fetch the group's headers, the
+placeholders will automatically be replaced by the actual headers.
+You can configure the summary buffer's maneuvering to skip over the
+placeholders if you care (See @code{gnus-auto-goto-ignores}).
+
+While it may be obvious to all, the only headers and articles
+available while unplugged are those headers and articles that were
+fetched into the Agent while previously plugged.  To put it another
+way, "If you forget to fetch something while plugged, you might have a
+less than satisfying unplugged session".  For this reason, the Agent
+adds two visual effects to your summary buffer.  These effects display
+the download status of each article so that you always know which
+articles will be available when unplugged.
+
+The first visual effect is the @samp{%O} spec.  If you customize
+@code{gnus-summary-line-format} to include this specifier, you will add
+a single character field that indicates an article's download status.
+Articles that have been fetched into either the Agent or the Cache,
+will display @code{gnus-downloaded-mark} (defaults to @samp{+}).  All
+other articles will display @code{gnus-undownloaded-mark} (defaults to
+@samp{-}).  If you open a group that has not been agentized, a space
+(@samp{ }) will be displayed.
+
+The second visual effect are the undownloaded faces.  The faces, there
+are three indicating the article's score (low, normal, high), seem to
+result in a love/hate response from many Gnus users.  The problem is
+that the face selection is controlled by a list of condition tests and
+face names (See @code{gnus-summary-highlight}).  Each condition is
+tested in the order in which it appears in the list so early
+conditions have precedence over later conditions.  All of this means
+that, if you tick an undownloaded article, the article will continue
+to be displayed in the undownloaded face rather than the ticked face.
+
+If you use the Agent as a cache (to avoid downloading the same article
+each time you visit it or to minimize your connection time), the
+undownloaded face will probably seem like a good idea.  The reason
+being that you do all of our work (marking, reading, deleting) with
+downloaded articles so the normal faces always appear.
+
+For occasional Agent users, the undownloaded faces may appear to be an
+absolutely horrible idea.  The issue being that, since most of their
+articles have not been fetched into the Agent, most of the normal
+faces will be obscured by the undownloaded faces.  If this is your
+situation, you have two choices available.  First, you can completely
+disable the undownload faces by customizing
+@code{gnus-summary-highlight} to delete the three cons-cells that
+refer to the @code{gnus-summary-*-undownloaded-face} faces.  Second, if
+you prefer to take a more fine-grained approach, you may set the
+@code{agent-disable-undownloaded-faces} group parameter to t.  This
+parameter, like all other agent parameters, may be set on an Agent
+Category (@pxref{Agent Categories}), a Group Topic (@pxref{Topic
+Parameters}), or an individual group (@pxref{Group Parameters}).
+
+@node Agent as Cache
+@subsection Agent as Cache
+
+When Gnus is plugged, it is not efficient to download headers or
+articles from the server again, if they are already stored in the
+Agent.  So, Gnus normally only downloads headers once, and stores them
+in the Agent.  These headers are later used when generating the summary
+buffer, regardless of whether you are plugged or unplugged.  Articles
+are not cached in the Agent by default though (that would potentially
+consume lots of disk space), but if you have already downloaded an
+article into the Agent, Gnus will not download the article from the
+server again but use the locally stored copy instead.
+
+If you so desire, you can configure the agent (see @code{gnus-agent-cache}
+@pxref{Agent Variables}) to always download headers and articles while
+plugged.  Gnus will almost certainly be slower, but it will be kept
+synchronized with the server.  That last point probably won't make any
+sense if you are using a nntp or nnimap back end.
+
+@node Agent Expiry
+@subsection Agent Expiry
+
+@vindex gnus-agent-expire-days
+@findex gnus-agent-expire
+@kindex M-x gnus-agent-expire
+@kindex M-x gnus-agent-expire-group
+@findex gnus-agent-expire-group
+@cindex agent expiry
+@cindex Gnus agent expiry
+@cindex expiry
+
+The Agent back end, @code{nnagent}, doesn't handle expiry.  Well, at
+least it doesn't handle it like other back ends.  Instead, there are
+special @code{gnus-agent-expire} and @code{gnus-agent-expire-group}
+commands that will expire all read articles that are older than
+@code{gnus-agent-expire-days} days.  They can be run whenever you feel
+that you're running out of space.  Neither are particularly fast or
+efficient, and it's not a particularly good idea to interrupt them (with
+@kbd{C-g} or anything else) once you've started one of them.
+
+Note that other functions, e.g. @code{gnus-request-expire-articles},
+might run @code{gnus-agent-expire} for you to keep the agent
+synchronized with the group.
+
+The agent parameter @code{agent-enable-expiration} may be used to
+prevent expiration in selected groups.
+
+@vindex gnus-agent-expire-all
+If @code{gnus-agent-expire-all} is non-@code{nil}, the agent
+expiration commands will expire all articles---unread, read, ticked
+and dormant.  If @code{nil} (which is the default), only read articles
+are eligible for expiry, and unread, ticked and dormant articles will
+be kept indefinitely.
+
+If you find that some articles eligible for expiry are never expired,
+perhaps some Gnus Agent files are corrupted.  There's are special
+commands, @code{gnus-agent-regenerate} and
+@code{gnus-agent-regenerate-group}, to fix possible problems.
+
+@node Agent Regeneration
+@subsection Agent Regeneration
+
+@cindex agent regeneration
+@cindex Gnus agent regeneration
+@cindex regeneration
+
+The local data structures used by @code{nnagent} may become corrupted
+due to certain exceptional conditions.  When this happens,
+@code{nnagent} functionality may degrade or even fail.  The solution
+to this problem is to repair the local data structures by removing all
+internal inconsistencies.
+
+For example, if your connection to your server is lost while
+downloaded articles into the agent, the local data structures will not
+know about articles successfully downloaded prior to the connection
+failure.  Running @code{gnus-agent-regenerate} or
+@code{gnus-agent-regenerate-group} will update the data structures
+such that you don't need to download these articles a second time.
+
+@findex gnus-agent-regenerate
+@kindex M-x gnus-agent-regenerate
+The command @code{gnus-agent-regenerate} will perform
+@code{gnus-agent-regenerate-group} on every agentized group.  While
+you can run @code{gnus-agent-regenerate} in any buffer, it is strongly
+recommended that you first close all summary buffers.
+
+@findex gnus-agent-regenerate-group
+@kindex M-x gnus-agent-regenerate-group
+The command @code{gnus-agent-regenerate-group} uses the local copies
+of individual articles to repair the local @acronym{NOV}(header) database.  It
+then updates the internal data structures that document which articles
+are stored locally.  An optional argument will mark articles in the
+agent as unread.
+
+@node Agent and IMAP
+@subsection Agent and IMAP
+
+The Agent works with any Gnus back end, including nnimap.  However,
+since there are some conceptual differences between @acronym{NNTP} and
+@acronym{IMAP}, this section (should) provide you with some information to
+make Gnus Agent work smoother as a @acronym{IMAP} Disconnected Mode client.
+
+The first thing to keep in mind is that all flags (read, ticked, etc)
+are kept on the @acronym{IMAP} server, rather than in @file{.newsrc} as is the
+case for nntp.  Thus Gnus need to remember flag changes when
+disconnected, and synchronize these flags when you plug back in.
+
+Gnus keeps track of flag changes when reading nnimap groups under the
+Agent.  When you plug back in, Gnus will check if you have any changed
+any flags and ask if you wish to synchronize these with the server.
+The behavior is customizable by @code{gnus-agent-synchronize-flags}.
+
+@vindex gnus-agent-synchronize-flags
+If @code{gnus-agent-synchronize-flags} is @code{nil}, the Agent will
+never automatically synchronize flags.  If it is @code{ask}, which is
+the default, the Agent will check if you made any changes and if so
+ask if you wish to synchronize these when you re-connect.  If it has
+any other value, all flags will be synchronized automatically.
+
+If you do not wish to synchronize flags automatically when you
+re-connect, you can do it manually with the
+@code{gnus-agent-synchronize-flags} command that is bound to @kbd{J Y}
+in the group buffer.
+
+Some things are currently not implemented in the Agent that you'd might
+expect from a disconnected @acronym{IMAP} client, including:
 
-@table @code
-@item prediction-spot
-The higher the prediction, the further to the right an @samp{*} is
-displayed. 
+@itemize @bullet
 
-@item confidence-interval
-A numeric confidence interval.
+@item
+Copying/moving articles into nnimap groups when unplugged.
 
-@item prediction-bar
-The higher the prediction, the longer the bar.
+@item
+Creating/deleting nnimap groups when unplugged.
 
-@item confidence-bar
-Numerical confidence.
+@end itemize
 
-@item confidence-spot
-The spot gets bigger with more confidence.
+Technical note: the synchronization algorithm does not work by ``pushing''
+all local flags to the server, but rather incrementally update the
+server view of flags by changing only those flags that were changed by
+the user.  Thus, if you set one flag on an article, quit the group and
+re-select the group and remove the flag; the flag will be set and
+removed from the server when you ``synchronize''.  The queued flag
+operations can be found in the per-server @code{flags} file in the Agent
+directory.  It's emptied when you synchronize flags.
 
-@item prediction-num
-Plain-old numeric value.
 
-@item confidence-plus-minus
-Prediction +/- confidence.
+@node Outgoing Messages
+@subsection Outgoing Messages
 
-@end table
+When Gnus is unplugged, all outgoing messages (both mail and news) are
+stored in the draft group ``queue'' (@pxref{Drafts}).  You can view
+them there after posting, and edit them at will.
 
+When Gnus is plugged again, you can send the messages either from the
+draft group with the special commands available there, or you can use
+the @kbd{J S} command in the group buffer to send all the sendable
+messages in the draft group.
 
-@node GroupLens Variables
-@subsection GroupLens Variables
 
-@table @code
 
-@item gnus-summary-grouplens-line-format
-The summary line format used in GroupLens-enhanced summary buffers.  It
-accepts the same specs as the normal summary line format (@pxref{Summary
-Buffer Lines}).  The default is @samp{%U%R%z%l%I%(%[%4L: %-20,20n%]%)
-%s\n}.
+@node Agent Variables
+@subsection Agent Variables
 
-@item grouplens-bbb-host
-Host running the bbbd server.  @samp{grouplens.cs.umn.edu} is the
-default.
+@table @code
+@item gnus-agent-directory
+@vindex gnus-agent-directory
+Where the Gnus Agent will store its files.  The default is
+@file{~/News/agent/}.
 
-@item grouplens-bbb-port
-Port of the host running the bbbd server.  The default is 9000.
+@item gnus-agent-handle-level
+@vindex gnus-agent-handle-level
+Groups on levels (@pxref{Group Levels}) higher than this variable will
+be ignored by the Agent.  The default is @code{gnus-level-subscribed},
+which means that only subscribed group will be considered by the Agent
+by default.
 
-@item grouplens-score-offset
-Offset the prediction by this value.  In other words, subtract the
-prediction value by this number to arrive at the effective score.  The
-default is 0.
+@item gnus-agent-plugged-hook
+@vindex gnus-agent-plugged-hook
+Hook run when connecting to the network.
 
-@item grouplens-score-scale-factor 
-This variable allows the user to magnify the effect of GroupLens scores.
-The scale factor is applied after the offset.  The default is 1.
+@item gnus-agent-unplugged-hook
+@vindex gnus-agent-unplugged-hook
+Hook run when disconnecting from the network.
+
+@item gnus-agent-fetched-hook
+@vindex gnus-agent-fetched-hook
+Hook run when finished fetching articles.
+
+@item gnus-agent-cache
+@vindex gnus-agent-cache
+Variable to control whether use the locally stored @acronym{NOV} and
+articles when plugged, e.g. essentially using the Agent as a cache.
+The default is non-@code{nil}, which means to use the Agent as a cache.
+
+@item gnus-agent-go-online
+@vindex gnus-agent-go-online
+If @code{gnus-agent-go-online} is @code{nil}, the Agent will never
+automatically switch offline servers into online status.  If it is
+@code{ask}, the default, the Agent will ask if you wish to switch
+offline servers into online status when you re-connect.  If it has any
+other value, all offline servers will be automatically switched into
+online status.
+
+@item gnus-agent-mark-unread-after-downloaded
+@vindex gnus-agent-mark-unread-after-downloaded
+If @code{gnus-agent-mark-unread-after-downloaded} is non-@code{nil},
+mark articles as unread after downloading.  This is usually a safe
+thing to do as the newly downloaded article has obviously not been
+read.  The default is t.
+
+@item gnus-agent-consider-all-articles
+@vindex gnus-agent-consider-all-articles
+If @code{gnus-agent-consider-all-articles} is non-@code{nil}, the
+agent will let the agent predicate decide whether articles need to be
+downloaded or not, for all articles.  When @code{nil}, the default,
+the agent will only let the predicate decide whether unread articles
+are downloaded or not.  If you enable this, you may also want to look
+into the agent expiry settings (@pxref{Category Variables}), so that
+the agent doesn't download articles which the agent will later expire,
+over and over again.
+
+@item gnus-agent-max-fetch-size
+@vindex gnus-agent-max-fetch-size
+The agent fetches articles into a temporary buffer prior to parsing
+them into individual files.  To avoid exceeding the max. buffer size,
+the agent alternates between fetching and parsing until all articles
+have been fetched.  @code{gnus-agent-max-fetch-size} provides a size
+limit to control how often the cycling occurs.  A large value improves
+performance.  A small value minimizes the time lost should the
+connection be lost while fetching (You may need to run
+@code{gnus-agent-regenerate-group} to update the group's state.
+However, all articles parsed prior to loosing the connection will be
+available while unplugged).  The default is 10M so it is unusual to
+see any cycling.
+
+@item gnus-server-unopen-status
+@vindex gnus-server-unopen-status
+Perhaps not an Agent variable, but closely related to the Agent, this
+variable says what will happen if Gnus cannot open a server.  If the
+Agent is enabled, the default, @code{nil}, makes Gnus ask the user
+whether to deny the server or whether to unplug the agent.  If the
+Agent is disabled, Gnus always simply deny the server.  Other choices
+for this variable include @code{denied} and @code{offline} the latter
+is only valid if the Agent is used.
+
+@item gnus-auto-goto-ignores
+@vindex gnus-auto-goto-ignores
+Another variable that isn't an Agent variable, yet so closely related
+that most will look for it here, this variable tells the summary
+buffer how to maneuver around undownloaded (only headers stored in the
+agent) and unfetched (neither article nor headers stored) articles.
+
+The legal values are @code{nil} (maneuver to any article),
+@code{undownloaded} (maneuvering while unplugged ignores articles that
+have not been fetched), @code{always-undownloaded} (maneuvering always
+ignores articles that have not been fetched), @code{unfetched}
+(maneuvering ignores articles whose headers have not been fetched).
+
+@item gnus-agent-auto-agentize-methods
+@vindex gnus-agent-auto-agentize-methods
+If you have never used the Agent before (or more technically, if
+@file{~/News/agent/lib/servers} does not exist), Gnus will
+automatically agentize a few servers for you.  This variable control
+which backends should be auto-agentized.  It is typically only useful
+to agentize remote backends.  The auto-agentizing has the same effect
+as running @kbd{J a} on the servers (@pxref{Server Agent Commands}).
+If the file exist, you must manage the servers manually by adding or
+removing them, this variable is only applicable the first time you
+start Gnus.  The default is @samp{(nntp nnimap)}.
 
 @end table
 
 
-@node Advanced Scoring
-@section Advanced Scoring
+@node Example Setup
+@subsection Example Setup
 
-Scoring on Subjects and From headers is nice enough, but what if you're
-really interested in what a person has to say only when she's talking
-about a particular subject?  Or what if you really don't want to
-read what person A has to say when she's following up to person B, but
-want to read what she says when she's following up to person C?
+If you don't want to read this manual, and you have a fairly standard
+setup, you may be able to use something like the following as your
+@file{~/.gnus.el} file to get started.
 
-By using advanced scoring rules you may create arbitrarily complex
-scoring patterns.
+@lisp
+;;; @r{Define how Gnus is to fetch news.  We do this over @acronym{NNTP}}
+;;; @r{from your ISP's server.}
+(setq gnus-select-method '(nntp "news.your-isp.com"))
 
-@menu
-* Advanced Scoring Syntax::     A definition.
-* Advanced Scoring Examples::   What they look like.
-* Advanced Scoring Tips::       Getting the most out of it.
-@end menu
+;;; @r{Define how Gnus is to read your mail.  We read mail from}
+;;; @r{your ISP's @acronym{POP} server.}
+(setq mail-sources '((pop :server "pop.your-isp.com")))
 
+;;; @r{Say how Gnus is to store the mail.  We use nnml groups.}
+(setq gnus-secondary-select-methods '((nnml "")))
 
-@node Advanced Scoring Syntax
-@subsection Advanced Scoring Syntax
+;;; @r{Make Gnus into an offline newsreader.}
+;;; (gnus-agentize) ; @r{The obsolete setting.}
+;;; (setq gnus-agent t) ; @r{Now the default.}
+@end lisp
 
-Ordinary scoring rules have a string as the first element in the rule.
-Advanced scoring rules have a list as the first element.  The second
-element is the score to be applied if the first element evaluated to a
-non-@code{nil} value.
+That should be it, basically.  Put that in your @file{~/.gnus.el} file,
+edit to suit your needs, start up PPP (or whatever), and type @kbd{M-x
+gnus}.
 
-These lists may consist of three logical operators, one redirection
-operator, and various match operators.
+If this is the first time you've run Gnus, you will be subscribed
+automatically to a few default newsgroups.  You'll probably want to
+subscribe to more groups, and to do that, you have to query the
+@acronym{NNTP} server for a complete list of groups with the @kbd{A A}
+command.  This usually takes quite a while, but you only have to do it
+once.
 
-Logical operators:
+After reading and parsing a while, you'll be presented with a list of
+groups.  Subscribe to the ones you want to read with the @kbd{u}
+command.  @kbd{l} to make all the killed groups disappear after you've
+subscribe to all the groups you want to read.  (@kbd{A k} will bring
+back all the killed groups.)
 
-@table @code
-@item &
-@itemx and
-This logical operator will evaluate each of its arguments until it finds
-one that evaluates to @code{false}, and then it'll stop.  If all arguments
-evaluate to @code{true} values, then this operator will return
-@code{true}. 
+You can now read the groups at once, or you can download the articles
+with the @kbd{J s} command.  And then read the rest of this manual to
+find out which of the other gazillion things you want to customize.
 
-@item |
-@itemx or
-This logical operator will evaluate each of its arguments until it finds
-one that evaluates to @code{true}.  If no arguments are @code{true},
-then this operator will return @code{false}.
 
-@item !
-@itemx not
-@itemx Â¬
-This logical operator only takes a single argument.  It returns the
-logical negation of the value of its argument.
+@node Batching Agents
+@subsection Batching Agents
+@findex gnus-agent-batch
 
-@end table
+Having the Gnus Agent fetch articles (and post whatever messages you've
+written) is quite easy once you've gotten things set up properly.  The
+following shell script will do everything that is necessary:
 
-There is an @dfn{indirection operator} that will make its arguments
-apply to the ancestors of the current article being scored.  For
-instance, @code{1-} will make score rules apply to the parent of the
-current article.  @code{2-} will make score rules apply to the
-grandparent of the current article.  Alternatively, you can write
-@code{^^}, where the number of @code{^}s (carets) says how far back into
-the ancestry you want to go.
+You can run a complete batch command from the command line with the
+following incantation:
 
-Finally, we have the match operators.  These are the ones that do the
-real work.  Match operators are header name strings followed by a match
-and a match type.  A typical match operator looks like @samp{("from"
-"Lars Ingebrigtsen" s)}.  The header names are the same as when using
-simple scoring, and the match types are also the same.
+@example
+#!/bin/sh
+emacs -batch -l ~/.emacs -f -l ~/.gnus.el gnus-agent-batch >/dev/null 2>&1
+@end example
 
 
-@node Advanced Scoring Examples
-@subsection Advanced Scoring Examples
+@node Agent Caveats
+@subsection Agent Caveats
 
-Let's say you want to increase the score of articles written by Lars
-when he's talking about Gnus:
+The Gnus Agent doesn't seem to work like most other offline
+newsreaders.  Here are some common questions that some imaginary people
+may ask:
 
-@example
-((& 
-  ("from" "Lars Ingebrigtsen")
-  ("subject" "Gnus"))
- 1000)
-@end example
+@table @dfn
+@item If I read an article while plugged, do they get entered into the Agent?
 
-Quite simple, huh?
+@strong{No}.  If you want this behaviour, add
+@code{gnus-agent-fetch-selected-article} to
+@code{gnus-select-article-hook}.
 
-When he writes long articles, he sometimes has something nice to say: 
+@item If I read an article while plugged, and the article already exists in
+the Agent, will it get downloaded once more?
 
-@example
-((& 
-  ("from" "Lars Ingebrigtsen")
-  (|
-   ("subject" "Gnus")
-   ("lines" 100 >)))
- 1000)
-@end example
+@strong{No}, unless @code{gnus-agent-cache} is @code{nil}.
 
-However, when he responds to things written by Reig Eigil Logge, you
-really don't want to read what he's written:
+@end table
 
-@example
-((&
-  ("from" "Lars Ingebrigtsen")
-  (1- ("from" "Reig Eigir Logge")))
- -100000)
-@end example
+In short, when Gnus is unplugged, it only looks into the locally stored
+articles; when it's plugged, it talks to your ISP and may also use the
+locally stored articles.
 
-Everybody that follows up Redmondo when he writes about disappearing
-socks should have their scores raised, but only when they talk about
-white socks.  However, when Lars talks about socks, it's usually not
-very interesting:
 
-@example
-((&
-  (1-
-   (&
-    ("from" "redmondo@@.*no" r)
-    ("body" "disappearing.*socks" t)))
-  (! ("from" "Lars Ingebrigtsen"))
-  ("body" "white.*socks"))
- 1000)
-@end example
+@node Scoring
+@chapter Scoring
+@cindex scoring
 
-The possibilities are endless.
+Other people use @dfn{kill files}, but we here at Gnus Towers like
+scoring better than killing, so we'd rather switch than fight.  They do
+something completely different as well, so sit up straight and pay
+attention!
 
+@vindex gnus-summary-mark-below
+All articles have a default score (@code{gnus-summary-default-score}),
+which is 0 by default.  This score may be raised or lowered either
+interactively or by score files.  Articles that have a score lower than
+@code{gnus-summary-mark-below} are marked as read.
 
-@node Advanced Scoring Tips
-@subsection Advanced Scoring Tips
+Gnus will read any @dfn{score files} that apply to the current group
+before generating the summary buffer.
 
-The @code{&} and @code{|} logical operators do short-circuit logic.
-That is, they stop processing their arguments when it's clear what the
-result of the operation will be.  For instance, if one of the arguments
-of an @code{&} evaluates to @code{false}, there's no point in evaluating
-the rest of the arguments.  This means that you should put slow matches
-(@samp{body}, @samp{header}) last and quick matches (@samp{from},
-@samp{subject}) first.
+There are several commands in the summary buffer that insert score
+entries based on the current article.  You can, for instance, ask Gnus to
+lower or increase the score of all articles with a certain subject.
 
-The indirection arguments (@code{1-} and so on) will make their
-arguments work on previous generations of the thread.  If you say
-something like:
+There are two sorts of scoring entries: Permanent and temporary.
+Temporary score entries are self-expiring entries.  Any entries that are
+temporary and have not been used for, say, a week, will be removed
+silently to help keep the sizes of the score files down.
 
-@example
-...
-(1-
- (1-
-  ("from" "lars")))
-...
-@end example
+@menu
+* Summary Score Commands::      Adding score entries for the current group.
+* Group Score Commands::        General score commands.
+* Score Variables::             Customize your scoring.  (My, what terminology).
+* Score File Format::           What a score file may contain.
+* Score File Editing::          You can edit score files by hand as well.
+* Adaptive Scoring::            Big Sister Gnus knows what you read.
+* Home Score File::             How to say where new score entries are to go.
+* Followups To Yourself::       Having Gnus notice when people answer you.
+* Scoring On Other Headers::    Scoring on non-standard headers.
+* Scoring Tips::                How to score effectively.
+* Reverse Scoring::             That problem child of old is not problem.
+* Global Score Files::          Earth-spanning, ear-splitting score files.
+* Kill Files::                  They are still here, but they can be ignored.
+* Converting Kill Files::       Translating kill files to score files.
+* GroupLens::                   Getting predictions on what you like to read.
+* Advanced Scoring::            Using logical expressions to build score rules.
+* Score Decays::                It can be useful to let scores wither away.
+@end menu
 
-Then that means "score on the from header of the grandparent of the
-current article".  An indirection is quite fast, but it's better to say:
 
-@example
-(1-
- (& 
-  ("from" "Lars")
-  ("subject" "Gnus")))
-@end example
+@node Summary Score Commands
+@section Summary Score Commands
+@cindex score commands
 
-than it is to say:
+The score commands that alter score entries do not actually modify real
+score files.  That would be too inefficient.  Gnus maintains a cache of
+previously loaded score files, one of which is considered the
+@dfn{current score file alist}.  The score commands simply insert
+entries into this list, and upon group exit, this list is saved.
 
-@example
-(&
- (1- ("from" "Lars"))
- (1- ("subject" "Gnus")))
-@end example
+The current score file is by default the group's local score file, even
+if no such score file actually exists.  To insert score commands into
+some other score file (e.g. @file{all.SCORE}), you must first make this
+score file the current one.
 
+General score commands that don't actually change the score file:
 
-@node Score Decays
-@section Score Decays
-@cindex score decays
-@cindex decays
+@table @kbd
 
-You may find that your scores have a tendency to grow without
-bounds, especially if you're using adaptive scoring.  If scores get too
-big, they lose all meaning---they simply max out and it's difficult to
-use them in any sensible way.
+@item V s
+@kindex V s (Summary)
+@findex gnus-summary-set-score
+Set the score of the current article (@code{gnus-summary-set-score}).
 
-@vindex gnus-decay-scores
-@findex gnus-decay-score
-@vindex gnus-score-decay-function
-Gnus provides a mechanism for decaying scores to help with this problem.
-When score files are loaded and @code{gnus-decay-scores} is
-non-@code{nil}, Gnus will run the score files through the decaying
-mechanism thereby lowering the scores of all non-permanent score rules.
-The decay itself if performed by the @code{gnus-score-decay-function}
-function, which is @code{gnus-decay-score} by default.  Here's the
-definition of that function:
+@item V S
+@kindex V S (Summary)
+@findex gnus-summary-current-score
+Display the score of the current article
+(@code{gnus-summary-current-score}).
 
-@lisp
-(defun gnus-decay-score (score)
-  "Decay SCORE according to `gnus-score-decay-constant' and `gnus-score-decay-scale'."
-  (floor
-   (- score
-      (* (if (< score 0) 1 -1)
-         (min (abs score)
-              (max gnus-score-decay-constant
-                   (* (abs score)
-                      gnus-score-decay-scale)))))))
-@end lisp
+@item V t
+@kindex V t (Summary)
+@findex gnus-score-find-trace
+Display all score rules that have been used on the current article
+(@code{gnus-score-find-trace}).  In the @code{*Score Trace*} buffer, you
+may type @kbd{e} to edit score file corresponding to the score rule on
+current line and @kbd{f} to format (@code{gnus-score-pretty-print}) the
+score file and edit it.
 
-@vindex gnus-score-decay-scale
-@vindex gnus-score-decay-constant
-@code{gnus-score-decay-constant} is 3 by default and
-@code{gnus-score-decay-scale} is 0.05.  This should cause the following:
+@item V w
+@kindex V w (Summary)
+@findex gnus-score-find-favourite-words
+List words used in scoring (@code{gnus-score-find-favourite-words}).
 
-@enumerate
-@item
-Scores between -3 and 3 will be set to 0 when this function is called.
+@item V R
+@kindex V R (Summary)
+@findex gnus-summary-rescore
+Run the current summary through the scoring process
+(@code{gnus-summary-rescore}).  This might be useful if you're playing
+around with your score files behind Gnus' back and want to see the
+effect you're having.
 
-@item
-Scores with magnitudes between 3 and 60 will be shrunk by 3.
+@item V c
+@kindex V c (Summary)
+@findex gnus-score-change-score-file
+Make a different score file the current
+(@code{gnus-score-change-score-file}).
 
-@item
-Scores with magnitudes greater than 60 will be shrunk by 5% of the
-score.
-@end enumerate
+@item V e
+@kindex V e (Summary)
+@findex gnus-score-edit-current-scores
+Edit the current score file (@code{gnus-score-edit-current-scores}).
+You will be popped into a @code{gnus-score-mode} buffer (@pxref{Score
+File Editing}).
 
-If you don't like this decay function, write your own.  It is called
-with the score to be decayed as its only parameter, and it should return
-the new score, which should be an integer.
+@item V f
+@kindex V f (Summary)
+@findex gnus-score-edit-file
+Edit a score file and make this score file the current one
+(@code{gnus-score-edit-file}).
 
-Gnus will try to decay scores once a day.  If you haven't run Gnus for
-four days, Gnus will decay the scores four times, for instance.
+@item V F
+@kindex V F (Summary)
+@findex gnus-score-flush-cache
+Flush the score cache (@code{gnus-score-flush-cache}).  This is useful
+after editing score files.
 
+@item V C
+@kindex V C (Summary)
+@findex gnus-score-customize
+Customize a score file in a visually pleasing manner
+(@code{gnus-score-customize}).
 
-@node Various
-@chapter Various
+@end table
 
-@menu
-* Process/Prefix::             A convention used by many treatment commands.
-* Interactive::                Making Gnus ask you many questions.
-* Symbolic Prefixes::          How to supply some Gnus functions with options.
-* Formatting Variables::       You can specify what buffers should look like.
-* Windows Configuration::      Configuring the Gnus buffer windows.
-* Faces and Fonts::            How to change how faces look.
-* Compilation::                How to speed Gnus up.
-* Mode Lines::                 Displaying information in the mode lines.
-* Highlighting and Menus::     Making buffers look all nice and cozy.
-* Buttons::                    Get tendonitis in ten easy steps!
-* Daemons::                    Gnus can do things behind your back.
-* NoCeM::                      How to avoid spam and other fatty foods.
-* Undo::                       Some actions can be undone.
-* Moderation::                 What to do if you're a moderator.
-* XEmacs Enhancements::        There are more pictures and stuff under XEmacs.
-* Fuzzy Matching::             What's the big fuzz?
-* Thwarting Email Spam::       A how-to on avoiding unsolited commercial email.
-* Various Various::            Things that are really various.
-@end menu
+The rest of these commands modify the local score file.
 
+@table @kbd
 
-@node Process/Prefix
-@section Process/Prefix
-@cindex process/prefix convention
+@item V m
+@kindex V m (Summary)
+@findex gnus-score-set-mark-below
+Prompt for a score, and mark all articles with a score below this as
+read (@code{gnus-score-set-mark-below}).
 
-Many functions, among them functions for moving, decoding and saving
-articles, use what is known as the @dfn{Process/Prefix convention}.
+@item V x
+@kindex V x (Summary)
+@findex gnus-score-set-expunge-below
+Prompt for a score, and add a score rule to the current score file to
+expunge all articles below this score
+(@code{gnus-score-set-expunge-below}).
+@end table
 
-This is a method for figuring out what articles the user wants the
-command to be performed on.
+The keystrokes for actually making score entries follow a very regular
+pattern, so there's no need to list all the commands.  (Hundreds of
+them.)
 
-It goes like this:
+@findex gnus-summary-increase-score
+@findex gnus-summary-lower-score
 
-If the numeric prefix is N, perform the operation on the next N
-articles, starting with the current one.  If the numeric prefix is
-negative, perform the operation on the previous N articles, starting
-with the current one.
+@enumerate
+@item
+The first key is either @kbd{I} (upper case i) for increasing the score
+or @kbd{L} for lowering the score.
+@item
+The second key says what header you want to score on.  The following
+keys are available:
+@table @kbd
 
-@vindex transient-mark-mode
-If @code{transient-mark-mode} in non-@code{nil} and the region is
-active, all articles in the region will be worked upon.
+@item a
+Score on the author name.
 
-If there is no numeric prefix, but some articles are marked with the
-process mark, perform the operation on the articles marked with
-the process mark.
+@item s
+Score on the subject line.
 
-If there is neither a numeric prefix nor any articles marked with the
-process mark, just perform the operation on the current article.
+@item x
+Score on the @code{Xref} line---i.e., the cross-posting line.
 
-Quite simple, really, but it needs to be made clear so that surprises
-are avoided.
+@item r
+Score on the @code{References} line.
 
-Commands that react to the process mark will push the current list of
-process marked articles onto a stack and will then clear all process
-marked articles.  You can restore the previous configuration with the
-@kbd{M P y} command (@pxref{Setting Process Marks}).
+@item d
+Score on the date.
 
-@vindex gnus-summary-goto-unread
-One thing that seems to shock & horrify lots of people is that, for
-instance, @kbd{3 d} does exactly the same as @kbd{d} @kbd{d} @kbd{d}.
-Since each @kbd{d} (which marks the current article as read) by default
-goes to the next unread article after marking, this means that @kbd{3 d}
-will mark the next three unread articles as read, no matter what the
-summary buffer looks like.  Set @code{gnus-summary-goto-unread} to
-@code{nil} for a more straightforward action.
+@item l
+Score on the number of lines.
 
+@item i
+Score on the @code{Message-ID} header.
 
-@node Interactive
-@section Interactive
-@cindex interaction
+@item e
+Score on an ``extra'' header, that is, one of those in gnus-extra-headers,
+if your @acronym{NNTP} server tracks additional header data in overviews.
 
-@table @code
+@item f
+Score on followups---this matches the author name, and adds scores to
+the followups to this author.  (Using this key leads to the creation of
+@file{ADAPT} files.)
 
-@item gnus-novice-user
-@vindex gnus-novice-user
-If this variable is non-@code{nil}, you are either a newcomer to the
-World of Usenet, or you are very cautious, which is a nice thing to be,
-really.  You will be given questions of the type ``Are you sure you want
-to do this?'' before doing anything dangerous.  This is @code{t} by
-default.
+@item b
+Score on the body.
 
-@item gnus-expert-user
-@vindex gnus-expert-user
-If this variable is non-@code{nil}, you will seldom be asked any
-questions by Gnus.  It will simply assume you know what you're doing, no
-matter how strange.
+@item h
+Score on the head.
 
-@item gnus-interactive-catchup
-@vindex gnus-interactive-catchup
-Require confirmation before catching up a group if non-@code{nil}.  It
-is @code{t} by default.
+@item t
+Score on thread.  (Using this key leads to the creation of @file{ADAPT}
+files.)
 
-@item gnus-interactive-exit
-@vindex gnus-interactive-exit
-Require confirmation before exiting Gnus.  This variable is @code{t} by
-default. 
 @end table
 
+@item
+The third key is the match type.  Which match types are valid depends on
+what headers you are scoring on.
 
-@node Symbolic Prefixes
-@section Symbolic Prefixes
-@cindex symbolic prefixes
+@table @code
 
-Quite a lot of Emacs commands react to the (numeric) prefix.  For
-instance, @kbd{C-u 4 C-f} moves point four charaters forward, and
-@kbd{C-u 9 0 0 I s s p} adds a permanent @code{Subject} substring score
-rule of 900 to the current article.
+@item strings
 
-This is all nice and well, but what if you want to give a command some
-additional information?  Well, what most commands do is interpret the
-``raw'' prefix in some special way.  @kbd{C-u 0 C-x C-s} means that one
-doesn't want a backup file to be created when saving the current buffer,
-for instance.  But what if you want to save without making a backup
-file, and you want Emacs to flash lights and play a nice tune at the
-same time?  You can't, and you're probably perfectly happy that way.
+@table @kbd
 
-@kindex M-i (Summary)
-@findex gnus-symbolic-argument
-I'm not, so I've added a second prefix---the @dfn{symbolic prefix}.  The
-prefix key is @kbd{M-i} (@code{gnus-symbolic-argument}), and the next
-character typed in is the value.  You can stack as many @kbd{M-i}
-prefixes as you want.  @kbd{M-i a M-C-u} means ``feed the @kbd{M-C-u}
-command the symbolic prefix @code{a}''.  @kbd{M-i a M-i b M-C-u} means
-``feed the @kbd{M-C-u} command the symbolic prefixes @code{a} and
-@code{b}''.  You get the drift.
-
-Typing in symbolic prefixes to commands that don't accept them doesn't
-hurt, but it doesn't do any good either.  Currently not many Gnus
-functions make use of the symbolic prefix.
+@item e
+Exact matching.
 
-If you're interested in how Gnus implements this, @pxref{Extended
-Interactive}.
+@item s
+Substring matching.
 
+@item f
+Fuzzy matching (@pxref{Fuzzy Matching}).
 
-@node Formatting Variables
-@section Formatting Variables
-@cindex formatting variables
+@item r
+Regexp matching
+@end table
 
-Throughout this manual you've probably noticed lots of variables called things like @code{gnus-group-line-format} and
-@code{gnus-summary-mode-line-format}.  These control how Gnus is to
-output lines in the various buffers.  There's quite a lot of them.
-Fortunately, they all use the same syntax, so there's not that much to
-be annoyed by.
+@item date
+@table @kbd
 
-Here's an example format spec (from the group buffer): @samp{%M%S%5y:
-%(%g%)\n}.  We see that it is indeed extremely ugly, and that there are
-lots of percentages everywhere.  
+@item b
+Before date.
 
-@menu 
-* Formatting Basics::     A formatting variable is basically a format string.
-* Advanced Formatting::   Modifying output in various ways.
-* User-Defined Specs::    Having Gnus call your own functions.
-* Formatting Fonts::      Making the formatting look colorful and nice.
-@end menu
+@item a
+After date.
 
-Currently Gnus uses the following formatting variables:
-@code{gnus-group-line-format}, @code{gnus-summary-line-format},
-@code{gnus-server-line-format}, @code{gnus-topic-line-format},
-@code{gnus-group-mode-line-format},
-@code{gnus-summary-mode-line-format},
-@code{gnus-article-mode-line-format},
-@code{gnus-server-mode-line-format}, and
-@code{gnus-summary-pick-line-format}.
+@item n
+This date.
+@end table
 
-All these format variables can also be arbitrary elisp forms.  In that
-case, they will be @code{eval}ed to insert the required lines.
+@item number
+@table @kbd
 
-@kindex M-x gnus-update-format
-@findex gnus-update-format
-Gnus includes a command to help you while creating your own format
-specs.  @kbd{M-x gnus-update-format} will @code{eval} the current form,
-update the spec in question and pop you to a buffer where you can
-examine the resulting lisp code to be run to generate the line.  
+@item <
+Less than number.
 
+@item =
+Equal to number.
 
+@item >
+Greater than number.
+@end table
+@end table
 
-@node Formatting Basics
-@subsection Formatting Basics
+@item
+The fourth and usually final key says whether this is a temporary (i.e.,
+expiring) score entry, or a permanent (i.e., non-expiring) score entry,
+or whether it is to be done immediately, without adding to the score
+file.
+@table @kbd
 
-Each @samp{%} element will be replaced by some string or other when the
-buffer in question is generated.  @samp{%5y} means ``insert the @samp{y}
-spec, and pad with spaces to get a 5-character field''.
+@item t
+Temporary score entry.
 
-As with normal C and Emacs Lisp formatting strings, the numerical
-modifier between the @samp{%} and the formatting type character will
-@dfn{pad} the output so that it is always at least that long.
-@samp{%5y} will make the field always (at least) five characters wide by
-padding with spaces to the left.  If you say @samp{%-5y}, it will pad to
-the right instead.
+@item p
+Permanent score entry.
 
-You may also wish to limit the length of the field to protect against
-particularly wide values.  For that you can say @samp{%4,6y}, which
-means that the field will never be more than 6 characters wide and never
-less than 4 characters wide.
+@item i
+Immediately scoring.
+@end table
 
+@item
+If you are scoring on `e' (extra) headers, you will then be prompted for
+the header name on which you wish to score.  This must be a header named
+in gnus-extra-headers, and @samp{TAB} completion is available.
 
-@node Advanced Formatting
-@subsection Advanced Formatting
+@end enumerate
 
-It is frequently useful to post-process the fields in some way.
-Padding, limiting, cutting off parts and suppressing certain values can
-be achieved by using @dfn{tilde modifiers}.  A typical tilde spec might
-look like @samp{%~(cut 3)~(ignore "0")y}.
+So, let's say you want to increase the score on the current author with
+exact matching permanently: @kbd{I a e p}.  If you want to lower the
+score based on the subject line, using substring matching, and make a
+temporary score entry: @kbd{L s s t}.  Pretty easy.
 
-These are the valid modifiers:
+To make things a bit more complicated, there are shortcuts.  If you use
+a capital letter on either the second or third keys, Gnus will use
+defaults for the remaining one or two keystrokes.  The defaults are
+``substring'' and ``temporary''.  So @kbd{I A} is the same as @kbd{I a s
+t}, and @kbd{I a R} is the same as @kbd{I a r t}.
 
-@table @code
-@item pad
-@itemx pad-left
-Pad the field to the left with spaces until it reaches the required
-length.
+These functions take both the numerical prefix and the symbolic prefix
+(@pxref{Symbolic Prefixes}).  A numerical prefix says how much to lower
+(or increase) the score of the article.  A symbolic prefix of @code{a}
+says to use the @file{all.SCORE} file for the command instead of the
+current score file.
 
-@item pad-right
-Pad the field to the right with spaces until it reaches the required
-length.
+@vindex gnus-score-mimic-keymap
+The @code{gnus-score-mimic-keymap} says whether these commands will
+pretend they are keymaps or not.
 
-@item max
-@itemx max-left
-Cut off characters from the left until it reaches the specified length.
 
-@item max-right
-Cut off characters from the right until it reaches the specified
-length. 
+@node Group Score Commands
+@section Group Score Commands
+@cindex group score commands
 
-@item cut
-@itemx cut-left
-Cut off the specified number of characters from the left.
+There aren't many of these as yet, I'm afraid.
 
-@item cut-right
-Cut off the specified number of characters from the right.
+@table @kbd
 
-@item ignore
-Return an empty string if the field is equal to the specified value. 
+@item W f
+@kindex W f (Group)
+@findex gnus-score-flush-cache
+Gnus maintains a cache of score alists to avoid having to reload them
+all the time.  This command will flush the cache
+(@code{gnus-score-flush-cache}).
 
-@item form
-Use the specified form as the field value when the @samp{@@} spec is
-used. 
 @end table
 
-Let's take an example.  The @samp{%o} spec in the summary mode lines
-will return a date in compact ISO8601 format---@samp{19960809T230410}.
-This is quite a mouthful, so we want to shave off the century number and
-the time, leaving us with a six-character date.  That would be
-@samp{%~(cut-left 2)~(max-right 6)~(pad 6)o}.  (Cutting is done before
-maxing, and we need the padding to ensure that the date is never less
-than 6 characters to make it look nice in columns.)
-
-Ignoring is done first; then cutting; then maxing; and then as the very
-last operation, padding.  
-
-If you use lots of these advanced thingies, you'll find that Gnus gets
-quite slow.  This can be helped enormously by running @kbd{M-x
-gnus-compile} when you are satisfied with the look of your lines.
-@xref{Compilation}. 
-
+You can do scoring from the command line by saying something like:
 
-@node User-Defined Specs
-@subsection User-Defined Specs
+@findex gnus-batch-score
+@cindex batch scoring
+@example
+$ emacs -batch -l ~/.emacs -l ~/.gnus.el -f gnus-batch-score
+@end example
 
-All the specs allow for inserting user defined specifiers---@samp{u}.
-The next character in the format string should be a letter.  Gnus
-will call the function @code{gnus-user-format-function-}@samp{X}, where
-@samp{X} is the letter following @samp{%u}.  The function will be passed
-a single parameter---what the parameter means depends on what buffer
-it's being called from.  The function should return a string, which will
-be inserted into the buffer just like information from any other
-specifier.  This function may also be called with dummy values, so it
-should protect against that.
 
-You can also use tilde modifiers (@pxref{Advanced Formatting} to achieve
-much the same without defining new functions.  Here's an example:
-@samp{%~(form (count-lines (point-min) (point)))@@}.  The form
-given here will be evaluated to yield the current line number, and then
-inserted.
+@node Score Variables
+@section Score Variables
+@cindex score variables
 
+@table @code
 
-@node Formatting Fonts
-@subsection Formatting Fonts
+@item gnus-use-scoring
+@vindex gnus-use-scoring
+If @code{nil}, Gnus will not check for score files, and will not, in
+general, do any score-related work.  This is @code{t} by default.
 
-There are specs for highlighting, and these are shared by all the format
-variables.  Text inside the @samp{%(} and @samp{%)} specifiers will get
-the special @code{mouse-face} property set, which means that it will be
-highlighted (with @code{gnus-mouse-face}) when you put the mouse pointer
-over it.
+@item gnus-kill-killed
+@vindex gnus-kill-killed
+If this variable is @code{nil}, Gnus will never apply score files to
+articles that have already been through the kill process.  While this
+may save you lots of time, it also means that if you apply a kill file
+to a group, and then change the kill file and want to run it over you
+group again to kill more articles, it won't work.  You have to set this
+variable to @code{t} to do that.  (It is @code{t} by default.)
 
-Text inside the @samp{%[} and @samp{%]} specifiers will have their
-normal faces set using @code{gnus-face-0}, which is @code{bold} by
-default.  If you say @samp{%1[}, you'll get @code{gnus-face-1} instead,
-and so on.  Create as many faces as you wish.  The same goes for the
-@code{mouse-face} specs---you can say @samp{%3(hello%)} to have
-@samp{hello} mouse-highlighted with @code{gnus-mouse-face-3}.
+@item gnus-kill-files-directory
+@vindex gnus-kill-files-directory
+All kill and score files will be stored in this directory, which is
+initialized from the @env{SAVEDIR} environment variable by default.
+This is @file{~/News/} by default.
 
-Here's an alternative recipe for the group buffer:
+@item gnus-score-file-suffix
+@vindex gnus-score-file-suffix
+Suffix to add to the group name to arrive at the score file name
+(@file{SCORE} by default.)
 
-@lisp
-;; Create three face types.
-(setq gnus-face-1 'bold)
-(setq gnus-face-3 'italic)
+@item gnus-score-uncacheable-files
+@vindex gnus-score-uncacheable-files
+@cindex score cache
+All score files are normally cached to avoid excessive re-loading of
+score files.  However, if this might make your Emacs grow big and
+bloated, so this regexp can be used to weed out score files unlikely
+to be needed again.  It would be a bad idea to deny caching of
+@file{all.SCORE}, while it might be a good idea to not cache
+@file{comp.infosystems.www.authoring.misc.ADAPT}.  In fact, this
+variable is @samp{ADAPT$} by default, so no adaptive score files will
+be cached.
 
-;; We want the article count to be in 
-;; a bold and green face.  So we create 
-;; a new face called `my-green-bold'.
-(copy-face 'bold 'my-green-bold)
-;; Set the color.
-(set-face-foreground 'my-green-bold "ForestGreen")
-(setq gnus-face-2 'my-green-bold)
+@item gnus-save-score
+@vindex gnus-save-score
+If you have really complicated score files, and do lots of batch
+scoring, then you might set this variable to @code{t}.  This will make
+Gnus save the scores into the @file{.newsrc.eld} file.
 
-;; Set the new & fancy format.
-(setq gnus-group-line-format 
-      "%M%S%3@{%5y%@}%2[:%] %(%1@{%g%@}%)\n")
-@end lisp
+If you do not set this to @code{t}, then manual scores (like those set
+with @kbd{V s} (@code{gnus-summary-set-score})) will not be preserved
+across group visits.
 
-I'm sure you'll be able to use this scheme to create totally unreadable
-and extremely vulgar displays.  Have fun!
+@item gnus-score-interactive-default-score
+@vindex gnus-score-interactive-default-score
+Score used by all the interactive raise/lower commands to raise/lower
+score with.  Default is 1000, which may seem excessive, but this is to
+ensure that the adaptive scoring scheme gets enough room to play with.
+We don't want the small changes from the adaptive scoring to overwrite
+manually entered data.
 
-Note that the @samp{%(} specs (and friends) do not make any sense on the
-mode-line variables.
+@item gnus-summary-default-score
+@vindex gnus-summary-default-score
+Default score of an article, which is 0 by default.
 
+@item gnus-summary-expunge-below
+@vindex gnus-summary-expunge-below
+Don't display the summary lines of articles that have scores lower than
+this variable.  This is @code{nil} by default, which means that no
+articles will be hidden.  This variable is local to the summary buffers,
+and has to be set from @code{gnus-summary-mode-hook}.
 
-@node Windows Configuration
-@section Windows Configuration
-@cindex windows configuration
+@item gnus-score-over-mark
+@vindex gnus-score-over-mark
+Mark (in the third column) used for articles with a score over the
+default.  Default is @samp{+}.
 
-No, there's nothing here about X, so be quiet.
+@item gnus-score-below-mark
+@vindex gnus-score-below-mark
+Mark (in the third column) used for articles with a score below the
+default.  Default is @samp{-}.
 
-@vindex gnus-use-full-window
-If @code{gnus-use-full-window} non-@code{nil}, Gnus will delete all
-other windows and occupy the entire Emacs screen by itself.  It is
-@code{t} by default.
+@item gnus-score-find-score-files-function
+@vindex gnus-score-find-score-files-function
+Function used to find score files for the current group.  This function
+is called with the name of the group as the argument.
 
-@vindex gnus-buffer-configuration
-@code{gnus-buffer-configuration} describes how much space each Gnus
-buffer should be given.  Here's an excerpt of this variable:
+Predefined functions available are:
+@table @code
 
-@lisp
-((group (vertical 1.0 (group 1.0 point)
-                      (if gnus-carpal (group-carpal 4))))
- (article (vertical 1.0 (summary 0.25 point) 
-                        (article 1.0))))
-@end lisp
+@item gnus-score-find-single
+@findex gnus-score-find-single
+Only apply the group's own score file.
 
-This is an alist.  The @dfn{key} is a symbol that names some action or
-other.  For instance, when displaying the group buffer, the window
-configuration function will use @code{group} as the key.  A full list of
-possible names is listed below.
+@item gnus-score-find-bnews
+@findex gnus-score-find-bnews
+Apply all score files that match, using bnews syntax.  This is the
+default.  If the current group is @samp{gnu.emacs.gnus}, for instance,
+@file{all.emacs.all.SCORE}, @file{not.alt.all.SCORE} and
+@file{gnu.all.SCORE} would all apply.  In short, the instances of
+@samp{all} in the score file names are translated into @samp{.*}, and
+then a regexp match is done.
 
-The @dfn{value} (i.e., the @dfn{split}) says how much space each buffer
-should occupy.  To take the @code{article} split as an example -
+This means that if you have some score entries that you want to apply to
+all groups, then you put those entries in the @file{all.SCORE} file.
 
-@lisp
-(article (vertical 1.0 (summary 0.25 point)
-                       (article 1.0)))
-@end lisp
+The score files are applied in a semi-random order, although Gnus will
+try to apply the more general score files before the more specific score
+files.  It does this by looking at the number of elements in the score
+file names---discarding the @samp{all} elements.
 
-This @dfn{split} says that the summary buffer should occupy 25% of upper
-half of the screen, and that it is placed over the article buffer.  As
-you may have noticed, 100% + 25% is actually 125% (yup, I saw y'all
-reaching for that calculator there).  However, the special number
-@code{1.0} is used to signal that this buffer should soak up all the
-rest of the space available after the rest of the buffers have taken
-whatever they need.  There should be only one buffer with the @code{1.0}
-size spec per split.
+@item gnus-score-find-hierarchical
+@findex gnus-score-find-hierarchical
+Apply all score files from all the parent groups.  This means that you
+can't have score files like @file{all.SCORE}, but you can have
+@file{SCORE}, @file{comp.SCORE} and @file{comp.emacs.SCORE} for each
+server.
 
-Point will be put in the buffer that has the optional third element
-@code{point}. 
+@end table
+This variable can also be a list of functions.  In that case, all
+these functions will be called with the group name as argument, and
+all the returned lists of score files will be applied.  These
+functions can also return lists of lists of score alists directly.  In
+that case, the functions that return these non-file score alists
+should probably be placed before the ``real'' score file functions, to
+ensure that the last score file returned is the local score file.
+Phu.
+
+For example, to do hierarchical scoring but use a non-server-specific
+overall score file, you could use the value
+@example
+(list (lambda (group) ("all.SCORE"))
+      'gnus-score-find-hierarchical)
+@end example
 
-Here's a more complicated example:
+@item gnus-score-expiry-days
+@vindex gnus-score-expiry-days
+This variable says how many days should pass before an unused score file
+entry is expired.  If this variable is @code{nil}, no score file entries
+are expired.  It's 7 by default.
 
-@lisp
-(article (vertical 1.0 (group 4)
-                       (summary 0.25 point)
-                       (if gnus-carpal (summary-carpal 4))
-                       (article 1.0)))
-@end lisp
+@item gnus-update-score-entry-dates
+@vindex gnus-update-score-entry-dates
+If this variable is non-@code{nil}, temporary score entries that have
+been triggered (matched) will have their dates updated.  (This is how Gnus
+controls expiry---all non-matched-entries will become too old while
+matched entries will stay fresh and young.)  However, if you set this
+variable to @code{nil}, even matched entries will grow old and will
+have to face that oh-so grim reaper.
 
-If the size spec is an integer instead of a floating point number, 
-then that number will be used to say how many lines a buffer should
-occupy, not a percentage.
+@item gnus-score-after-write-file-function
+@vindex gnus-score-after-write-file-function
+Function called with the name of the score file just written.
 
-If the @dfn{split} looks like something that can be @code{eval}ed (to be
-precise---if the @code{car} of the split is a function or a subr), this
-split will be @code{eval}ed.  If the result is non-@code{nil}, it will
-be used as a split.  This means that there will be three buffers if
-@code{gnus-carpal} is @code{nil}, and four buffers if @code{gnus-carpal}
-is non-@code{nil}.
+@item gnus-score-thread-simplify
+@vindex gnus-score-thread-simplify
+If this variable is non-@code{nil}, article subjects will be
+simplified for subject scoring purposes in the same manner as with
+threading---according to the current value of
+@code{gnus-simplify-subject-functions}.  If the scoring entry uses
+@code{substring} or @code{exact} matching, the match will also be
+simplified in this manner.
 
-Not complicated enough for you?  Well, try this on for size:
+@end table
+
+
+@node Score File Format
+@section Score File Format
+@cindex score file format
+
+A score file is an @code{emacs-lisp} file that normally contains just a
+single form.  Casual users are not expected to edit these files;
+everything can be changed from the summary buffer.
+
+Anyway, if you'd like to dig into it yourself, here's an example:
 
 @lisp
-(article (horizontal 1.0 
-             (vertical 0.5
-                 (group 1.0)
-                 (gnus-carpal 4))
-             (vertical 1.0
-                 (summary 0.25 point)
-                 (summary-carpal 4)
-                 (article 1.0))))
+(("from"
+  ("Lars Ingebrigtsen" -10000)
+  ("Per Abrahamsen")
+  ("larsi\\|lmi" -50000 nil R))
+ ("subject"
+  ("Ding is Badd" nil 728373))
+ ("xref"
+  ("alt.politics" -1000 728372 s))
+ ("lines"
+  (2 -100 nil <))
+ (mark 0)
+ (expunge -1000)
+ (mark-and-expunge -10)
+ (read-only nil)
+ (orphan -10)
+ (adapt t)
+ (files "/hom/larsi/News/gnu.SCORE")
+ (exclude-files "all.SCORE")
+ (local (gnus-newsgroup-auto-expire t)
+        (gnus-summary-make-false-root empty))
+ (eval (ding)))
 @end lisp
 
-Whoops.  Two buffers with the mystery 100% tag.  And what's that
-@code{horizontal} thingie?  
+This example demonstrates most score file elements.  @xref{Advanced
+Scoring}, for a different approach.
 
-If the first element in one of the split is @code{horizontal}, Gnus will
-split the window horizontally, giving you two windows side-by-side.
-Inside each of these strips you may carry on all you like in the normal
-fashion.  The number following @code{horizontal} says what percentage of
-the screen is to be given to this strip.
+Even though this looks much like Lisp code, nothing here is actually
+@code{eval}ed.  The Lisp reader is used to read this form, though, so it
+has to be valid syntactically, if not semantically.
 
-For each split, there @emph{must} be one element that has the 100% tag.
-The splitting is never accurate, and this buffer will eat any leftover
-lines from the splits.
+Six keys are supported by this alist:
 
-To be slightly more formal, here's a definition of what a valid split
-may look like:
+@table @code
 
-@example
-split       = frame | horizontal | vertical | buffer | form
-frame       = "(frame " size *split ")"
-horizontal  = "(horizontal " size *split ")"
-vertical    = "(vertical " size *split ")"
-buffer      = "(" buffer-name " " size *[ "point" ] ")"
-size        = number | frame-params
-buffer-name = group | article | summary ...
-@end example
+@item STRING
+If the key is a string, it is the name of the header to perform the
+match on.  Scoring can only be performed on these eight headers:
+@code{From}, @code{Subject}, @code{References}, @code{Message-ID},
+@code{Xref}, @code{Lines}, @code{Chars} and @code{Date}.  In addition to
+these headers, there are three strings to tell Gnus to fetch the entire
+article and do the match on larger parts of the article: @code{Body}
+will perform the match on the body of the article, @code{Head} will
+perform the match on the head of the article, and @code{All} will
+perform the match on the entire article.  Note that using any of these
+last three keys will slow down group entry @emph{considerably}.  The
+final ``header'' you can score on is @code{Followup}.  These score
+entries will result in new score entries being added for all follow-ups
+to articles that matches these score entries.
 
-The limitations are that the @code{frame} split can only appear as the
-top-level split.  @var{form} should be an Emacs Lisp form that should
-return a valid split.  We see that each split is fully recursive, and
-may contain any number of @code{vertical} and @code{horizontal} splits. 
+Following this key is an arbitrary number of score entries, where each
+score entry has one to four elements.
+@enumerate
 
-@vindex gnus-window-min-width
-@vindex gnus-window-min-height
-@cindex window height
-@cindex window width
-Finding the right sizes can be a bit complicated.  No window may be less
-than @code{gnus-window-min-height} (default 1) characters high, and all
-windows must be at least @code{gnus-window-min-width} (default 1)
-characters wide.  Gnus will try to enforce this before applying the
-splits.  If you want to use the normal Emacs window width/height limit,
-you can just set these two variables to @code{nil}.
+@item
+The first element is the @dfn{match element}.  On most headers this will
+be a string, but on the Lines and Chars headers, this must be an
+integer.
 
-If you're not familiar with Emacs terminology, @code{horizontal} and
-@code{vertical} splits may work the opposite way of what you'd expect.
-Windows inside a @code{horizontal} split are shown side-by-side, and
-windows within a @code{vertical} split are shown above each other.
+@item
+If the second element is present, it should be a number---the @dfn{score
+element}.  This number should be an integer in the neginf to posinf
+interval.  This number is added to the score of the article if the match
+is successful.  If this element is not present, the
+@code{gnus-score-interactive-default-score} number will be used
+instead.  This is 1000 by default.
 
-@findex gnus-configure-frame
-If you want to experiment with window placement, a good tip is to call
-@code{gnus-configure-frame} directly with a split.  This is the function
-that does all the real work when splitting buffers.  Below is a pretty
-nonsensical configuration with 5 windows; two for the group buffer and
-three for the article buffer.  (I said it was nonsensical.)  If you
-@code{eval} the statement below, you can get an idea of how that would
-look straight away, without going through the normal Gnus channels.
-Play with it until you're satisfied, and then use
-@code{gnus-add-configuration} to add your new creation to the buffer
-configuration list. 
+@item
+If the third element is present, it should be a number---the @dfn{date
+element}.  This date says when the last time this score entry matched,
+which provides a mechanism for expiring the score entries.  It this
+element is not present, the score entry is permanent.  The date is
+represented by the number of days since December 31, 1 BCE.
+
+@item
+If the fourth element is present, it should be a symbol---the @dfn{type
+element}.  This element specifies what function should be used to see
+whether this score entry matches the article.  What match types that can
+be used depends on what header you wish to perform the match on.
+@table @dfn
+
+@item From, Subject, References, Xref, Message-ID
+For most header types, there are the @code{r} and @code{R} (regexp), as
+well as @code{s} and @code{S} (substring) types, and @code{e} and
+@code{E} (exact match), and @code{w} (word match) types.  If this
+element is not present, Gnus will assume that substring matching should
+be used.  @code{R}, @code{S}, and @code{E} differ from the others in
+that the matches will be done in a case-sensitive manner.  All these
+one-letter types are really just abbreviations for the @code{regexp},
+@code{string}, @code{exact}, and @code{word} types, which you can use
+instead, if you feel like.
+
+@item Extra
+Just as for the standard string overview headers, if you are using
+gnus-extra-headers, you can score on these headers' values.  In this
+case, there is a 5th element in the score entry, being the name of the
+header to be scored.  The following entry is useful in your
+@file{all.SCORE} file in case of spam attacks from a single origin
+host, if your @acronym{NNTP} server tracks @samp{NNTP-Posting-Host} in
+overviews:
 
 @lisp
-(gnus-configure-frame
- '(horizontal 1.0
-    (vertical 10
-      (group 1.0)
-      (article 0.3 point))
-    (vertical 1.0
-      (article 1.0)
-      (horizontal 4
-        (group 1.0)
-        (article 10)))))
+("111.222.333.444" -1000 nil s
+ "NNTP-Posting-Host")
 @end lisp
 
-You might want to have several frames as well.  No prob---just use the
-@code{frame} split:
+@item Lines, Chars
+These two headers use different match types: @code{<}, @code{>},
+@code{=}, @code{>=} and @code{<=}.
 
-@lisp
-(gnus-configure-frame
- '(frame 1.0
-         (vertical 1.0
-                   (summary 0.25 point)
-                   (article 1.0))
-         (vertical ((height . 5) (width . 15)
-                    (user-position . t)
-                    (left . -1) (top . 1))
-                   (picon 1.0))))
+These predicates are true if
 
-@end lisp
+@example
+(PREDICATE HEADER MATCH)
+@end example
 
-This split will result in the familiar summary/article window
-configuration in the first (or ``main'') frame, while a small additional
-frame will be created where picons will be shown.  As you can see,
-instead of the normal @code{1.0} top-level spec, each additional split
-should have a frame parameter alist as the size spec.
-@xref{Frame Parameters, , Frame Parameters, elisp, The GNU Emacs Lisp
-Reference Manual}.  Under XEmacs, a frame property list will be
-accepted, too---for instance, @code{(height 5 width 15 left -1 top 1)}
-is such a plist.
-
-Here's a list of all possible keys for
-@code{gnus-buffer-configuration}:
-
-@code{group}, @code{summary}, @code{article}, @code{server},
-@code{browse}, @code{message}, @code{pick}, @code{info},
-@code{summary-faq}, @code{edit-group}, @code{edit-server},
-@code{edit-score}, @code{post}, @code{reply}, @code{forward},
-@code{reply-yank}, @code{mail-bounce}, @code{draft}, @code{pipe},
-@code{bug}, @code{compose-bounce}, and @code{score-trace}.
-
-Note that the @code{message} key is used for both
-@code{gnus-group-mail} and @code{gnus-summary-mail-other-window}.  If
-it is desirable to distinguish between the two, something like this
-might be used:
+evaluates to non-@code{nil}.  For instance, the advanced match
+@code{("lines" 4 <)} (@pxref{Advanced Scoring}) will result in the
+following form:
 
 @lisp
-(message (horizontal 1.0
-                     (vertical 1.0 (message 1.0 point))
-                     (vertical 0.24
-                               (if (buffer-live-p gnus-summary-buffer)
-                                   '(summary 0.5))
-                               (group 1.0)))))
+(< header-value 4)
 @end lisp
 
-@findex gnus-add-configuration
-Since the @code{gnus-buffer-configuration} variable is so long and
-complicated, there's a function you can use to ease changing the config
-of a single setting: @code{gnus-add-configuration}.  If, for instance,
-you want to change the @code{article} setting, you could say:
-
-@lisp
-(gnus-add-configuration
- '(article (vertical 1.0
-               (group 4)
-               (summary .25 point)
-               (article 1.0))))
-@end lisp
+Or to put it another way: When using @code{<} on @code{Lines} with 4 as
+the match, we get the score added if the article has less than 4 lines.
+(It's easy to get confused and think it's the other way around.  But
+it's not.  I think.)
 
-You'd typically stick these @code{gnus-add-configuration} calls in your
-@file{.gnus.el} file or in some startup hook---they should be run after
-Gnus has been loaded.
+When matching on @code{Lines}, be careful because some back ends (like
+@code{nndir}) do not generate @code{Lines} header, so every article ends
+up being marked as having 0 lines.  This can lead to strange results if
+you happen to lower score of the articles with few lines.
 
-@vindex gnus-always-force-window-configuration
-If all windows mentioned in the configuration are already visible, Gnus
-won't change the window configuration.  If you always want to force the
-``right'' window configuration, you can set
-@code{gnus-always-force-window-configuration} to non-@code{nil}.
+@item Date
+For the Date header we have three kinda silly match types:
+@code{before}, @code{at} and @code{after}.  I can't really imagine this
+ever being useful, but, like, it would feel kinda silly not to provide
+this function.  Just in case.  You never know.  Better safe than sorry.
+Once burnt, twice shy.  Don't judge a book by its cover.  Never not have
+sex on a first date.  (I have been told that at least one person, and I
+quote, ``found this function indispensable'', however.)
 
+@cindex ISO8601
+@cindex date
+A more useful match type is @code{regexp}.  With it, you can match the
+date string using a regular expression.  The date is normalized to
+ISO8601 compact format first---@var{YYYYMMDD}@code{T}@var{HHMMSS}.  If
+you want to match all articles that have been posted on April 1st in
+every year, you could use @samp{....0401.........} as a match string,
+for instance.  (Note that the date is kept in its original time zone, so
+this will match articles that were posted when it was April 1st where
+the article was posted from.  Time zones are such wholesome fun for the
+whole family, eh?)
 
-@node Faces and Fonts
-@section Faces and Fonts
-@cindex faces
-@cindex fonts
-@cindex colors
+@item Head, Body, All
+These three match keys use the same match types as the @code{From} (etc)
+header uses.
 
-Fiddling with fonts and faces used to be very difficult, but these days
-it is very simple.  You simply say @kbd{M-x customize-face}, pick out
-the face you want to alter, and alter it via the standard Customize
-interface.  
+@item Followup
+This match key is somewhat special, in that it will match the
+@code{From} header, and affect the score of not only the matching
+articles, but also all followups to the matching articles.  This allows
+you e.g. increase the score of followups to your own articles, or
+decrease the score of followups to the articles of some known
+trouble-maker.  Uses the same match types as the @code{From} header
+uses.  (Using this match key will lead to creation of @file{ADAPT}
+files.)
 
+@item Thread
+This match key works along the same lines as the @code{Followup} match
+key.  If you say that you want to score on a (sub-)thread started by an
+article with a @code{Message-ID} @var{x}, then you add a @samp{thread}
+match.  This will add a new @samp{thread} match for each article that
+has @var{x} in its @code{References} header.  (These new @samp{thread}
+matches will use the @code{Message-ID}s of these matching articles.)
+This will ensure that you can raise/lower the score of an entire thread,
+even though some articles in the thread may not have complete
+@code{References} headers.  Note that using this may lead to
+undeterministic scores of the articles in the thread.  (Using this match
+key will lead to creation of @file{ADAPT} files.)
+@end table
+@end enumerate
 
-@node Compilation
-@section Compilation
-@cindex compilation
-@cindex byte-compilation
+@cindex score file atoms
+@item mark
+The value of this entry should be a number.  Any articles with a score
+lower than this number will be marked as read.
 
-@findex gnus-compile
+@item expunge
+The value of this entry should be a number.  Any articles with a score
+lower than this number will be removed from the summary buffer.
 
-Remember all those line format specification variables?
-@code{gnus-summary-line-format}, @code{gnus-group-line-format}, and so
-on.  Now, Gnus will of course heed whatever these variables are, but,
-unfortunately, changing them will mean a quite significant slow-down.
-(The default values of these variables have byte-compiled functions
-associated with them, while the user-generated versions do not, of
-course.) 
+@item mark-and-expunge
+The value of this entry should be a number.  Any articles with a score
+lower than this number will be marked as read and removed from the
+summary buffer.
 
-To help with this, you can run @kbd{M-x gnus-compile} after you've
-fiddled around with the variables and feel that you're (kind of)
-satisfied.  This will result in the new specs being byte-compiled, and
-you'll get top speed again.  Gnus will save these compiled specs in the
-@file{.newsrc.eld} file.  (User-defined functions aren't compiled by
-this function, though---you should compile them yourself by sticking
-them into the @code{.gnus.el} file and byte-compiling that file.)
+@item thread-mark-and-expunge
+The value of this entry should be a number.  All articles that belong to
+a thread that has a total score below this number will be marked as read
+and removed from the summary buffer.  @code{gnus-thread-score-function}
+says how to compute the total score for a thread.
 
+@item files
+The value of this entry should be any number of file names.  These files
+are assumed to be score files as well, and will be loaded the same way
+this one was.
 
-@node Mode Lines
-@section Mode Lines
-@cindex mode lines
+@item exclude-files
+The clue of this entry should be any number of files.  These files will
+not be loaded, even though they would normally be so, for some reason or
+other.
 
-@vindex gnus-updated-mode-lines
-@code{gnus-updated-mode-lines} says what buffers should keep their mode
-lines updated.  It is a list of symbols.  Supported symbols include
-@code{group}, @code{article}, @code{summary}, @code{server},
-@code{browse}, and @code{tree}.  If the corresponding symbol is present,
-Gnus will keep that mode line updated with information that may be
-pertinent.  If this variable is @code{nil}, screen refresh may be
-quicker.
+@item eval
+The value of this entry will be @code{eval}el.  This element will be
+ignored when handling global score files.
 
-@cindex display-time
+@item read-only
+Read-only score files will not be updated or saved.  Global score files
+should feature this atom (@pxref{Global Score Files}).  (Note:
+@dfn{Global} here really means @dfn{global}; not your personal
+apply-to-all-groups score files.)
 
-@vindex gnus-mode-non-string-length
-By default, Gnus displays information on the current article in the mode
-lines of the summary and article buffers.  The information Gnus wishes
-to display (e.g. the subject of the article) is often longer than the
-mode lines, and therefore have to be cut off at some point.  The
-@code{gnus-mode-non-string-length} variable says how long the other
-elements on the line is (i.e., the non-info part).  If you put
-additional elements on the mode line (e.g. a clock), you should modify
-this variable:
+@item orphan
+The value of this entry should be a number.  Articles that do not have
+parents will get this number added to their scores.  Imagine you follow
+some high-volume newsgroup, like @samp{comp.lang.c}.  Most likely you
+will only follow a few of the threads, also want to see any new threads.
 
-@c Hook written by Francesco Potorti` <pot@cnuce.cnr.it>
-@lisp
-(add-hook 'display-time-hook
-          (lambda () (setq gnus-mode-non-string-length
-                           (+ 21
-                              (if line-number-mode 5 0)
-                              (if column-number-mode 4 0)
-                              (length display-time-string)))))
-@end lisp
+You can do this with the following two score file entries:
 
-If this variable is @code{nil} (which is the default), the mode line
-strings won't be chopped off, and they won't be padded either.  Note
-that the default is unlikely to be desirable, as even the percentage
-complete in the buffer may be crowded off the mode line; the user should
-configure this variable appropriately for her configuration.
+@example
+        (orphan -500)
+        (mark-and-expunge -100)
+@end example
 
+When you enter the group the first time, you will only see the new
+threads.  You then raise the score of the threads that you find
+interesting (with @kbd{I T} or @kbd{I S}), and ignore (@kbd{C y}) the
+rest.  Next time you enter the group, you will see new articles in the
+interesting threads, plus any new threads.
 
-@node Highlighting and Menus
-@section Highlighting and Menus
-@cindex visual
-@cindex highlighting
-@cindex menus
+I.e.---the orphan score atom is for high-volume groups where a few
+interesting threads which can't be found automatically by ordinary
+scoring rules exist.
 
-@vindex gnus-visual
-The @code{gnus-visual} variable controls most of the Gnus-prettifying
-aspects.  If @code{nil}, Gnus won't attempt to create menus or use fancy
-colors or fonts.  This will also inhibit loading the @file{gnus-vis.el}
-file.
+@item adapt
+This entry controls the adaptive scoring.  If it is @code{t}, the
+default adaptive scoring rules will be used.  If it is @code{ignore}, no
+adaptive scoring will be performed on this group.  If it is a list, this
+list will be used as the adaptive scoring rules.  If it isn't present,
+or is something other than @code{t} or @code{ignore}, the default
+adaptive scoring rules will be used.  If you want to use adaptive
+scoring on most groups, you'd set @code{gnus-use-adaptive-scoring} to
+@code{t}, and insert an @code{(adapt ignore)} in the groups where you do
+not want adaptive scoring.  If you only want adaptive scoring in a few
+groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and
+insert @code{(adapt t)} in the score files of the groups where you want
+it.
 
-This variable can be a list of visual properties that are enabled.  The
-following elements are valid, and are all included by default:
+@item adapt-file
+All adaptive score entries will go to the file named by this entry.  It
+will also be applied when entering the group.  This atom might be handy
+if you want to adapt on several groups at once, using the same adaptive
+file for a number of groups.
 
-@table @code
-@item group-highlight
-Do highlights in the group buffer.
-@item summary-highlight
-Do highlights in the summary buffer.
-@item article-highlight
-Do highlights in the article buffer.
-@item highlight
-Turn on highlighting in all buffers.
-@item group-menu
-Create menus in the group buffer.
-@item summary-menu
-Create menus in the summary buffers.
-@item article-menu
-Create menus in the article buffer.
-@item browse-menu
-Create menus in the browse buffer.
-@item server-menu
-Create menus in the server buffer.
-@item score-menu
-Create menus in the score buffers.
-@item menu
-Create menus in all buffers.
+@item local
+@cindex local variables
+The value of this entry should be a list of @code{(@var{var}
+@var{value})} pairs.  Each @var{var} will be made buffer-local to the
+current summary buffer, and set to the value specified.  This is a
+convenient, if somewhat strange, way of setting variables in some
+groups if you don't like hooks much.  Note that the @var{value} won't
+be evaluated.
 @end table
 
-So if you only want highlighting in the article buffer and menus in all
-buffers, you could say something like:
 
-@lisp
-(setq gnus-visual '(article-highlight menu))
-@end lisp
+@node Score File Editing
+@section Score File Editing
 
-If you want highlighting only and no menus whatsoever, you'd say:
+You normally enter all scoring commands from the summary buffer, but you
+might feel the urge to edit them by hand as well, so we've supplied you
+with a mode for that.
 
-@lisp
-(setq gnus-visual '(highlight))
-@end lisp
+It's simply a slightly customized @code{emacs-lisp} mode, with these
+additional commands:
 
-If @code{gnus-visual} is @code{t}, highlighting and menus will be used
-in all Gnus buffers.
+@table @kbd
 
-Other general variables that influence the look of all buffers include:
+@item C-c C-c
+@kindex C-c C-c (Score)
+@findex gnus-score-edit-done
+Save the changes you have made and return to the summary buffer
+(@code{gnus-score-edit-done}).
 
-@table @code
-@item gnus-mouse-face
-@vindex gnus-mouse-face
-This is the face (i.e., font) used for mouse highlighting in Gnus.  No
-mouse highlights will be done if @code{gnus-visual} is @code{nil}.
+@item C-c C-d
+@kindex C-c C-d (Score)
+@findex gnus-score-edit-insert-date
+Insert the current date in numerical format
+(@code{gnus-score-edit-insert-date}).  This is really the day number, if
+you were wondering.
+
+@item C-c C-p
+@kindex C-c C-p (Score)
+@findex gnus-score-pretty-print
+The adaptive score files are saved in an unformatted fashion.  If you
+intend to read one of these files, you want to @dfn{pretty print} it
+first.  This command (@code{gnus-score-pretty-print}) does that for
+you.
 
 @end table
 
-There are hooks associated with the creation of all the different menus:
+Type @kbd{M-x gnus-score-mode} to use this mode.
 
-@table @code
+@vindex gnus-score-mode-hook
+@code{gnus-score-menu-hook} is run in score mode buffers.
 
-@item gnus-article-menu-hook
-@vindex gnus-article-menu-hook
-Hook called after creating the article mode menu.
+In the summary buffer you can use commands like @kbd{V f}, @kbd{V e} and
+@kbd{V t} to begin editing score files.
 
-@item gnus-group-menu-hook
-@vindex gnus-group-menu-hook
-Hook called after creating the group mode menu.
 
-@item gnus-summary-menu-hook
-@vindex gnus-summary-menu-hook
-Hook called after creating the summary mode menu.
+@node Adaptive Scoring
+@section Adaptive Scoring
+@cindex adaptive scoring
 
-@item gnus-server-menu-hook
-@vindex gnus-server-menu-hook
-Hook called after creating the server mode menu.
+If all this scoring is getting you down, Gnus has a way of making it all
+happen automatically---as if by magic.  Or rather, as if by artificial
+stupidity, to be precise.
 
-@item gnus-browse-menu-hook
-@vindex gnus-browse-menu-hook
-Hook called after creating the browse mode menu.
+@vindex gnus-use-adaptive-scoring
+When you read an article, or mark an article as read, or kill an
+article, you leave marks behind.  On exit from the group, Gnus can sniff
+these marks and add score elements depending on what marks it finds.
+You turn on this ability by setting @code{gnus-use-adaptive-scoring} to
+@code{t} or @code{(line)}.  If you want score adaptively on separate
+words appearing in the subjects, you should set this variable to
+@code{(word)}.  If you want to use both adaptive methods, set this
+variable to @code{(word line)}.
 
-@item gnus-score-menu-hook
-@vindex gnus-score-menu-hook
-Hook called after creating the score mode menu.
+@vindex gnus-default-adaptive-score-alist
+To give you complete control over the scoring process, you can customize
+the @code{gnus-default-adaptive-score-alist} variable.  For instance, it
+might look something like this:
 
-@end table
+@lisp
+(setq gnus-default-adaptive-score-alist
+  '((gnus-unread-mark)
+    (gnus-ticked-mark (from 4))
+    (gnus-dormant-mark (from 5))
+    (gnus-del-mark (from -4) (subject -1))
+    (gnus-read-mark (from 4) (subject 2))
+    (gnus-expirable-mark (from -1) (subject -1))
+    (gnus-killed-mark (from -1) (subject -3))
+    (gnus-kill-file-mark)
+    (gnus-ancient-mark)
+    (gnus-low-score-mark)
+    (gnus-catchup-mark (from -1) (subject -1))))
+@end lisp
 
+As you see, each element in this alist has a mark as a key (either a
+variable name or a ``real'' mark---a character).  Following this key is
+a arbitrary number of header/score pairs.  If there are no header/score
+pairs following the key, no adaptive scoring will be done on articles
+that have that key as the article mark.  For instance, articles with
+@code{gnus-unread-mark} in the example above will not get adaptive score
+entries.
 
-@node Buttons
-@section Buttons
-@cindex buttons
-@cindex mouse
-@cindex click
+Each article can have only one mark, so just a single of these rules
+will be applied to each article.
 
-Those new-fangled @dfn{mouse} contraptions is very popular with the
-young, hep kids who don't want to learn the proper way to do things
-these days.  Why, I remember way back in the summer of '89, when I was
-using Emacs on a Tops 20 system.  Three hundred users on one single
-machine, and every user was running Simula compilers.  Bah!
+To take @code{gnus-del-mark} as an example---this alist says that all
+articles that have that mark (i.e., are marked with @samp{e}) will have a
+score entry added to lower based on the @code{From} header by -4, and
+lowered by @code{Subject} by -1.  Change this to fit your prejudices.
 
-Right.
+If you have marked 10 articles with the same subject with
+@code{gnus-del-mark}, the rule for that mark will be applied ten times.
+That means that that subject will get a score of ten times -1, which
+should be, unless I'm much mistaken, -10.
 
-@vindex gnus-carpal
-Well, you can make Gnus display bufferfuls of buttons you can click to
-do anything by setting @code{gnus-carpal} to @code{t}.  Pretty simple,
-really.  Tell the chiropractor I sent you.
+If you have auto-expirable (mail) groups (@pxref{Expiring Mail}), all
+the read articles will be marked with the @samp{E} mark.  This'll
+probably make adaptive scoring slightly impossible, so auto-expiring and
+adaptive scoring doesn't really mix very well.
 
+The headers you can score on are @code{from}, @code{subject},
+@code{message-id}, @code{references}, @code{xref}, @code{lines},
+@code{chars} and @code{date}.  In addition, you can score on
+@code{followup}, which will create an adaptive score entry that matches
+on the @code{References} header using the @code{Message-ID} of the
+current article, thereby matching the following thread.
 
-@table @code
+If you use this scheme, you should set the score file atom @code{mark}
+to something small---like -300, perhaps, to avoid having small random
+changes result in articles getting marked as read.
 
-@item gnus-carpal-mode-hook
-@vindex gnus-carpal-mode-hook
-Hook run in all carpal mode buffers.
+After using adaptive scoring for a week or so, Gnus should start to
+become properly trained and enhance the authors you like best, and kill
+the authors you like least, without you having to say so explicitly.
 
-@item gnus-carpal-button-face
-@vindex gnus-carpal-button-face
-Face used on buttons.
+You can control what groups the adaptive scoring is to be performed on
+by using the score files (@pxref{Score File Format}).  This will also
+let you use different rules in different groups.
 
-@item gnus-carpal-header-face
-@vindex gnus-carpal-header-face
-Face used on carpal buffer headers.
+@vindex gnus-adaptive-file-suffix
+The adaptive score entries will be put into a file where the name is the
+group name with @code{gnus-adaptive-file-suffix} appended.  The default
+is @file{ADAPT}.
 
-@item gnus-carpal-group-buffer-buttons
-@vindex gnus-carpal-group-buffer-buttons
-Buttons in the group buffer.
+@vindex gnus-score-exact-adapt-limit
+When doing adaptive scoring, substring or fuzzy matching would probably
+give you the best results in most cases.  However, if the header one
+matches is short, the possibility for false positives is great, so if
+the length of the match is less than
+@code{gnus-score-exact-adapt-limit}, exact matching will be used.  If
+this variable is @code{nil}, exact matching will always be used to avoid
+this problem.
 
-@item gnus-carpal-summary-buffer-buttons
-@vindex gnus-carpal-summary-buffer-buttons
-Buttons in the summary buffer.
+@vindex gnus-default-adaptive-word-score-alist
+As mentioned above, you can adapt either on individual words or entire
+headers.  If you adapt on words, the
+@code{gnus-default-adaptive-word-score-alist} variable says what score
+each instance of a word should add given a mark.
 
-@item gnus-carpal-server-buffer-buttons
-@vindex gnus-carpal-server-buffer-buttons
-Buttons in the server buffer.
+@lisp
+(setq gnus-default-adaptive-word-score-alist
+      `((,gnus-read-mark . 30)
+        (,gnus-catchup-mark . -10)
+        (,gnus-killed-mark . -20)
+        (,gnus-del-mark . -15)))
+@end lisp
 
-@item gnus-carpal-browse-buffer-buttons
-@vindex gnus-carpal-browse-buffer-buttons
-Buttons in the browse buffer.
-@end table
+This is the default value.  If you have adaption on words enabled, every
+word that appears in subjects of articles marked with
+@code{gnus-read-mark} will result in a score rule that increase the
+score with 30 points.
 
-All the @code{buttons} variables are lists.  The elements in these list
-are either cons cells where the @code{car} contains a text to be displayed and
-the @code{cdr} contains a function symbol, or a simple string.
+@vindex gnus-default-ignored-adaptive-words
+@vindex gnus-ignored-adaptive-words
+Words that appear in the @code{gnus-default-ignored-adaptive-words} list
+will be ignored.  If you wish to add more words to be ignored, use the
+@code{gnus-ignored-adaptive-words} list instead.
 
+@vindex gnus-adaptive-word-length-limit
+Some may feel that short words shouldn't count when doing adaptive
+scoring.  If so, you may set @code{gnus-adaptive-word-length-limit} to
+an integer.  Words shorter than this number will be ignored.  This
+variable defaults to @code{nil}.
 
-@node Daemons
-@section Daemons
-@cindex demons
-@cindex daemons
+@vindex gnus-adaptive-word-syntax-table
+When the scoring is done, @code{gnus-adaptive-word-syntax-table} is the
+syntax table in effect.  It is similar to the standard syntax table, but
+it considers numbers to be non-word-constituent characters.
 
-Gnus, being larger than any program ever written (allegedly), does lots
-of strange stuff that you may wish to have done while you're not
-present.  For instance, you may want it to check for new mail once in a
-while.  Or you may want it to close down all connections to all servers
-when you leave Emacs idle.  And stuff like that.
+@vindex gnus-adaptive-word-minimum
+If @code{gnus-adaptive-word-minimum} is set to a number, the adaptive
+word scoring process will never bring down the score of an article to
+below this number.  The default is @code{nil}.
 
-Gnus will let you do stuff like that by defining various
-@dfn{handlers}.  Each handler consists of three elements:  A
-@var{function}, a @var{time}, and an @var{idle} parameter.
+@vindex gnus-adaptive-word-no-group-words
+If @code{gnus-adaptive-word-no-group-words} is set to @code{t}, gnus
+won't adaptively word score any of the words in the group name.  Useful
+for groups like @samp{comp.editors.emacs}, where most of the subject
+lines contain the word @samp{emacs}.
 
-Here's an example of a handler that closes connections when Emacs has
-been idle for thirty minutes:
+After using this scheme for a while, it might be nice to write a
+@code{gnus-psychoanalyze-user} command to go through the rules and see
+what words you like and what words you don't like.  Or perhaps not.
 
-@lisp
-(gnus-demon-close-connections nil 30)
-@end lisp
+Note that the adaptive word scoring thing is highly experimental and is
+likely to change in the future.  Initial impressions seem to indicate
+that it's totally useless as it stands.  Some more work (involving more
+rigorous statistical methods) will have to be done to make this useful.
 
-Here's a handler that scans for PGP headers every hour when Emacs is
-idle: 
 
-@lisp
-(gnus-demon-scan-pgp 60 t)
-@end lisp
+@node Home Score File
+@section Home Score File
 
-This @var{time} parameter and than @var{idle} parameter work together
-in a strange, but wonderful fashion.  Basically, if @var{idle} is
-@code{nil}, then the function will be called every @var{time} minutes.
+The score file where new score file entries will go is called the
+@dfn{home score file}.  This is normally (and by default) the score file
+for the group itself.  For instance, the home score file for
+@samp{gnu.emacs.gnus} is @file{gnu.emacs.gnus.SCORE}.
 
-If @var{idle} is @code{t}, then the function will be called after
-@var{time} minutes only if Emacs is idle.  So if Emacs is never idle,
-the function will never be called.  But once Emacs goes idle, the
-function will be called every @var{time} minutes.
+However, this may not be what you want.  It is often convenient to share
+a common home score file among many groups---all @samp{emacs} groups
+could perhaps use the same home score file.
 
-If @var{idle} is a number and @var{time} is a number, the function will
-be called every @var{time} minutes only when Emacs has been idle for
-@var{idle} minutes.
+@vindex gnus-home-score-file
+The variable that controls this is @code{gnus-home-score-file}.  It can
+be:
 
-If @var{idle} is a number and @var{time} is @code{nil}, the function
-will be called once every time Emacs has been idle for @var{idle}
-minutes.  
+@enumerate
+@item
+A string.  Then this file will be used as the home score file for all
+groups.
 
-And if @var{time} is a string, it should look like @samp{07:31}, and
-the function will then be called once every day somewhere near that
-time.  Modified by the @var{idle} parameter, of course.
+@item
+A function.  The result of this function will be used as the home score
+file.  The function will be called with the name of the group as the
+parameter.
 
-@vindex gnus-demon-timestep
-(When I say ``minute'' here, I really mean @code{gnus-demon-timestep}
-seconds.  This is 60 by default.  If you change that variable,
-all the timings in the handlers will be affected.)
+@item
+A list.  The elements in this list can be:
 
-@vindex gnus-use-demon
-To set the whole thing in motion, though, you have to set
-@code{gnus-use-demon} to @code{t}.
+@enumerate
+@item
+@code{(@var{regexp} @var{file-name})}.  If the @var{regexp} matches the
+group name, the @var{file-name} will be used as the home score file.
 
-So, if you want to add a handler, you could put something like this in
-your @file{.gnus} file:
+@item
+A function.  If the function returns non-@code{nil}, the result will
+be used as the home score file.
 
-@findex gnus-demon-add-handler
-@lisp
-(gnus-demon-add-handler 'gnus-demon-close-connections 30 t)
-@end lisp
-
-@findex gnus-demon-add-nocem
-@findex gnus-demon-add-scanmail
-@findex gnus-demon-add-rescan
-@findex gnus-demon-add-scan-timestamps
-@findex gnus-demon-add-disconnection
-Some ready-made functions to do this have been created:
-@code{gnus-demon-add-nocem}, @code{gnus-demon-add-disconnection},
-@code{gnus-demon-add-nntp-close-connection}, 
-@code{gnus-demon-add-scan-timestamps}, @code{gnus-demon-add-rescan}, and
-@code{gnus-demon-add-scanmail}.  Just put those functions in your
-@file{.gnus} if you want those abilities.
+@item
+A string.  Use the string as the home score file.
+@end enumerate
 
-@findex gnus-demon-init
-@findex gnus-demon-cancel
-@vindex gnus-demon-handlers
-If you add handlers to @code{gnus-demon-handlers} directly, you should
-run @code{gnus-demon-init} to make the changes take hold.  To cancel all
-daemons, you can use the @code{gnus-demon-cancel} function.
+The list will be traversed from the beginning towards the end looking
+for matches.
 
-Note that adding daemons can be pretty naughty if you overdo it.  Adding
-functions that scan all news and mail from all servers every two seconds
-is a sure-fire way of getting booted off any respectable system.  So
-behave.
+@end enumerate
 
+So, if you want to use just a single score file, you could say:
 
-@node NoCeM
-@section NoCeM
-@cindex nocem
-@cindex spam
+@lisp
+(setq gnus-home-score-file
+      "my-total-score-file.SCORE")
+@end lisp
 
-@dfn{Spamming} is posting the same article lots and lots of times.
-Spamming is bad.  Spamming is evil.  
+If you want to use @file{gnu.SCORE} for all @samp{gnu} groups and
+@file{rec.SCORE} for all @samp{rec} groups (and so on), you can say:
 
-Spamming is usually canceled within a day or so by various anti-spamming
-agencies.  These agencies usually also send out @dfn{NoCeM} messages.
-NoCeM is pronounced ``no see-'em'', and means what the name
-implies---these are messages that make the offending articles, like, go
-away.  
+@findex gnus-hierarchial-home-score-file
+@lisp
+(setq gnus-home-score-file
+      'gnus-hierarchial-home-score-file)
+@end lisp
 
-What use are these NoCeM messages if the articles are canceled anyway?
-Some sites do not honor cancel messages and some sites just honor cancels
-from a select few people.  Then you may wish to make use of the NoCeM
-messages, which are distributed in the @samp{alt.nocem.misc} newsgroup.
+This is a ready-made function provided for your convenience.
+Other functions include
 
-Gnus can read and parse the messages in this group automatically, and
-this will make spam disappear.  
+@table @code
+@item gnus-current-home-score-file
+@findex gnus-current-home-score-file
+Return the ``current'' regular score file.  This will make scoring
+commands add entry to the ``innermost'' matching score file.
 
-There are some variables to customize, of course:
+@end table
 
-@table @code
-@item gnus-use-nocem
-@vindex gnus-use-nocem
-Set this variable to @code{t} to set the ball rolling.  It is @code{nil}
-by default. 
+If you want to have one score file for the @samp{emacs} groups and
+another for the @samp{comp} groups, while letting all other groups use
+their own home score files:
 
-@item gnus-nocem-groups
-@vindex gnus-nocem-groups
-Gnus will look for NoCeM messages in the groups in this list.  The
-default is @code{("news.lists.filters" "news.admin.net-abuse.bulletins"
-"alt.nocem.misc" "news.admin.net-abuse.announce")}. 
+@lisp
+(setq gnus-home-score-file
+      ;; @r{All groups that match the regexp @code{"\\.emacs"}}
+      '(("\\.emacs" "emacs.SCORE")
+        ;; @r{All the comp groups in one score file}
+        ("^comp" "comp.SCORE")))
+@end lisp
 
-@item gnus-nocem-issuers
-@vindex gnus-nocem-issuers
-There are many people issuing NoCeM messages.  This list says what
-people you want to listen to.  The default is @code{("Automoose-1"
-"rbraver@@ohww.norman.ok.us" "clewis@@ferret.ocunix.on.ca"
-"jem@@xpat.com" "snowhare@@xmission.com" "red@@redpoll.mrfs.oh.us
-(Richard E. Depew)")}; fine, upstanding citizens all of them.
+@vindex gnus-home-adapt-file
+@code{gnus-home-adapt-file} works exactly the same way as
+@code{gnus-home-score-file}, but says what the home adaptive score file
+is instead.  All new adaptive file entries will go into the file
+specified by this variable, and the same syntax is allowed.
 
-Known despammers that you can put in this list include:
+In addition to using @code{gnus-home-score-file} and
+@code{gnus-home-adapt-file}, you can also use group parameters
+(@pxref{Group Parameters}) and topic parameters (@pxref{Topic
+Parameters}) to achieve much the same.  Group and topic parameters take
+precedence over this variable.
 
-@table @samp
-@item clewis@@ferret.ocunix.on.ca;
-@cindex Chris Lewis
-Chris Lewis---Major Canadian despammer who has probably canceled more
-usenet abuse than anybody else.
-
-@item Automoose-1
-@cindex CancelMoose[tm]
-The CancelMoose[tm] on autopilot.  The CancelMoose[tm] is reputed to be
-Norwegian, and was the person(s) who invented NoCeM.  
-
-@item jem@@xpat.com;
-@cindex Jem
-John Milburn---despammer located in Korea who is getting very busy these
-days.
 
-@item red@@redpoll.mrfs.oh.us (Richard E. Depew)
-Richard E. Depew---lone American despammer.  He mostly cancels binary
-postings to non-binary groups and removes spews (regurgitated articles).
-@end table
+@node Followups To Yourself
+@section Followups To Yourself
 
-You do not have to heed NoCeM messages from all these people---just the
-ones you want to listen to.  You also don't have to accept all NoCeM
-messages from the people you like.  Each NoCeM message has a @dfn{type}
-header that gives the message a (more or less, usually less) rigorous
-definition.  Common types are @samp{spam}, @samp{spew}, @samp{mmf},
-@samp{binary}, and @samp{troll}.  To specify this, you have to use
-@var{(issuer conditions ...)} elements in the list.  Each condition is
-either a string (which is a regexp that matches types you want to use)
-or a list on the form @code{(not STRING)}, where @var{string} is a
-regexp that matches types you don't want to use.
+Gnus offers two commands for picking out the @code{Message-ID} header in
+the current buffer.  Gnus will then add a score rule that scores using
+this @code{Message-ID} on the @code{References} header of other
+articles.  This will, in effect, increase the score of all articles that
+respond to the article in the current buffer.  Quite useful if you want
+to easily note when people answer what you've said.
 
-For instance, if you want all NoCeM messages from Chris Lewis except his
-@samp{troll} messages, you'd say:
+@table @code
 
-@lisp
-("clewis@@ferret.ocunix.on.ca" ".*" (not "troll"))
-@end lisp
+@item gnus-score-followup-article
+@findex gnus-score-followup-article
+This will add a score to articles that directly follow up your own
+article.
 
-On the other hand, if you just want nothing but his @samp{spam} and
-@samp{spew} messages, you'd say:
+@item gnus-score-followup-thread
+@findex gnus-score-followup-thread
+This will add a score to all articles that appear in a thread ``below''
+your own article.
+@end table
 
+@vindex message-sent-hook
+These two functions are both primarily meant to be used in hooks like
+@code{message-sent-hook}, like this:
 @lisp
-("clewis@@ferret.ocunix.on.ca" (not ".*") "spew" "spam")
+(add-hook 'message-sent-hook 'gnus-score-followup-thread)
 @end lisp
 
-The specs are applied left-to-right.
 
+If you look closely at your own @code{Message-ID}, you'll notice that
+the first two or three characters are always the same.  Here's two of
+mine:
 
-@item gnus-nocem-verifyer
-@vindex gnus-nocem-verifyer
-@findex mc-verify
-This should be a function for verifying that the NoCeM issuer is who she
-says she is.  The default is @code{mc-verify}, which is a Mailcrypt
-function.  If this is too slow and you don't care for verification
-(which may be dangerous), you can set this variable to @code{nil}.
+@example
+<x6u3u47icf.fsf@@eyesore.no>
+<x6sp9o7ibw.fsf@@eyesore.no>
+@end example
 
-If you want signed NoCeM messages to be verified and unsigned messages
-not to be verified (but used anyway), you could do something like:
+So ``my'' ident on this machine is @samp{x6}.  This can be
+exploited---the following rule will raise the score on all followups to
+myself:
 
 @lisp
-(setq gnus-nocem-verifyer 'my-gnus-mc-verify)
-
-(defun my-gnus-mc-verify ()
-  (not (eq 'forged
-           (ignore-errors
-             (if (mc-verify)
-                 t
-               'forged)))))
+("references"
+ ("<x6[0-9a-z]+\\.fsf\\(_-_\\)?@@.*eyesore\\.no>"
+  1000 nil r))
 @end lisp
 
-This might be dangerous, though.
-
-@item gnus-nocem-directory
-@vindex gnus-nocem-directory
-This is where Gnus will store its NoCeM cache files.  The default is
-@file{~/News/NoCeM/}. 
-
-@item gnus-nocem-expiry-wait
-@vindex gnus-nocem-expiry-wait
-The number of days before removing old NoCeM entries from the cache.
-The default is 15.  If you make it shorter Gnus will be faster, but you
-might then see old spam.
+Whether it's the first two or first three characters that are ``yours''
+is system-dependent.
 
-@end table
 
-Using NoCeM could potentially be a memory hog.  If you have many living
-(i. e., subscribed or unsubscribed groups), your Emacs process will grow
-big.  If this is a problem, you should kill off all (or most) of your
-unsubscribed groups (@pxref{Subscription Commands}).
+@node Scoring On Other Headers
+@section Scoring On Other Headers
+@cindex scoring on other headers
 
+Gnus is quite fast when scoring the ``traditional''
+headers---@samp{From}, @samp{Subject} and so on.  However, scoring
+other headers requires writing a @code{head} scoring rule, which means
+that Gnus has to request every single article from the back end to find
+matches.  This takes a long time in big groups.
 
-@node Undo
-@section Undo
-@cindex undo
+Now, there's not much you can do about this for news groups, but for
+mail groups, you have greater control.  In @ref{To From Newsgroups},
+it's explained in greater detail what this mechanism does, but here's
+a cookbook example for @code{nnml} on how to allow scoring on the
+@samp{To} and @samp{Cc} headers.
 
-It is very useful to be able to undo actions one has done.  In normal
-Emacs buffers, it's easy enough---you just push the @code{undo} button.
-In Gnus buffers, however, it isn't that simple.
+Put the following in your @file{~/.gnus.el} file.
 
-The things Gnus displays in its buffer is of no value whatsoever to
-Gnus---it's all just data designed to look nice to the user.
-Killing a group in the group buffer with @kbd{C-k} makes the line
-disappear, but that's just a side-effect of the real action---the
-removal of the group in question from the internal Gnus structures.
-Undoing something like that can't be done by the normal Emacs
-@code{undo} function.
+@lisp
+(setq gnus-extra-headers '(To Cc Newsgroups Keywords)
+      nnmail-extra-headers gnus-extra-headers)
+@end lisp
 
-Gnus tries to remedy this somewhat by keeping track of what the user
-does and coming up with actions that would reverse the actions the user
-takes.  When the user then presses the @code{undo} key, Gnus will run
-the code to reverse the previous action, or the previous actions.
-However, not all actions are easily reversible, so Gnus currently offers
-a few key functions to be undoable.  These include killing groups,
-yanking groups, and changing the list of read articles of groups.
-That's it, really.  More functions may be added in the future, but each
-added function means an increase in data to be stored, so Gnus will
-never be totally undoable.
+Restart Gnus and rebuild your @code{nnml} overview files with the
+@kbd{M-x nnml-generate-nov-databases} command.  This will take a long
+time if you have much mail.
 
-@findex gnus-undo-mode
-@vindex gnus-use-undo
-@findex gnus-undo
-The undoability is provided by the @code{gnus-undo-mode} minor mode.  It
-is used if @code{gnus-use-undo} is non-@code{nil}, which is the
-default.  The @kbd{M-C-_} key performs the @code{gnus-undo} command
-command, which should feel kinda like the normal Emacs @code{undo}
-command. 
+Now you can score on @samp{To} and @samp{Cc} as ``extra headers'' like
+so: @kbd{I e s p To RET <your name> RET}.
 
+See?  Simple.
 
-@node Moderation
-@section Moderation
-@cindex moderation
 
-If you are a moderator, you can use the @file{gnus-mdrtn.el} package.
-It is not included in the standard Gnus package.  Write a mail to
-@samp{larsi@@gnus.org} and state what group you moderate, and you'll
-get a copy.
+@node Scoring Tips
+@section Scoring Tips
+@cindex scoring tips
 
-The moderation package is implemented as a minor mode for summary
-buffers.  Put
+@table @dfn
 
+@item Crossposts
+@cindex crossposts
+@cindex scoring crossposts
+If you want to lower the score of crossposts, the line to match on is
+the @code{Xref} header.
 @lisp
-(add-hook 'gnus-summary-mode-hook 'gnus-moderate)
+("xref" (" talk.politics.misc:" -1000))
 @end lisp
 
-in your @file{.gnus.el} file.
+@item Multiple crossposts
+If you want to lower the score of articles that have been crossposted to
+more than, say, 3 groups:
+@lisp
+("xref"
+  ("[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+ +[^:\n]+:[0-9]+"
+   -1000 nil r))
+@end lisp
 
-If you are the moderator of @samp{rec.zoofle}, this is how it's
-supposed to work:
+@item Matching on the body
+This is generally not a very good idea---it takes a very long time.
+Gnus actually has to fetch each individual article from the server.  But
+you might want to anyway, I guess.  Even though there are three match
+keys (@code{Head}, @code{Body} and @code{All}), you should choose one
+and stick with it in each score file.  If you use any two, each article
+will be fetched @emph{twice}.  If you want to match a bit on the
+@code{Head} and a bit on the @code{Body}, just use @code{All} for all
+the matches.
 
-@enumerate
-@item 
-You split your incoming mail by matching on
-@samp{Newsgroups:.*rec.zoofle}, which will put all the to-be-posted
-articles in some mail group---for instance, @samp{nnml:rec.zoofle}.
+@item Marking as read
+You will probably want to mark articles that have scores below a certain
+number as read.  This is most easily achieved by putting the following
+in your @file{all.SCORE} file:
+@lisp
+((mark -100))
+@end lisp
+You may also consider doing something similar with @code{expunge}.
 
-@item
-You enter that group once in a while and post articles using the @kbd{e}
-(edit-and-post) or @kbd{s} (just send unedited) commands.
+@item Negated character classes
+If you say stuff like @code{[^abcd]*}, you may get unexpected results.
+That will match newlines, which might lead to, well, The Unknown.  Say
+@code{[^abcd\n]*} instead.
+@end table
 
-@item
-If, while reading the @samp{rec.zoofle} newsgroup, you happen upon some
-articles that weren't approved by you, you can cancel them with the
-@kbd{c} command.
-@end enumerate
 
-To use moderation mode in these two groups, say:
+@node Reverse Scoring
+@section Reverse Scoring
+@cindex reverse scoring
+
+If you want to keep just articles that have @samp{Sex with Emacs} in the
+subject header, and expunge all other articles, you could put something
+like this in your score file:
 
 @lisp
-(setq gnus-moderated-list
-      "^nnml:rec.zoofle$\\|^rec.zoofle$")
+(("subject"
+  ("Sex with Emacs" 2))
+ (mark 1)
+ (expunge 1))
 @end lisp
 
+So, you raise all articles that match @samp{Sex with Emacs} and mark the
+rest as read, and expunge them to boot.
 
-@node XEmacs Enhancements
-@section XEmacs Enhancements
-@cindex XEmacs
-
-XEmacs is able to display pictures and stuff, so Gnus has taken
-advantage of that.
-
-@menu
-* Picons::    How to display pictures of what your reading.
-* Smileys::   Show all those happy faces the way they were meant to be shown.
-* Toolbar::   Click'n'drool.
-* XVarious::  Other XEmacsy Gnusey variables.
-@end menu
-
-
-@node Picons
-@subsection Picons
-
-@iftex
-@iflatex
-\include{picons}
-@end iflatex
-@end iftex
 
-So...  You want to slow down your news reader even more!  This is a
-good way to do so.  Its also a great way to impress people staring
-over your shoulder as you read news.
+@node Global Score Files
+@section Global Score Files
+@cindex global score files
 
-@menu
-* Picon Basics::           What are picons and How do I get them.
-* Picon Requirements::     Don't go further if you aren't using XEmacs.
-* Easy Picons::            Displaying Picons---the easy way.
-* Hard Picons::            The way you should do it.  You'll learn something.
-* Picon Useless Configuration:: Other variables you can trash/tweak/munge/play with.
-@end menu
+Sure, other newsreaders have ``global kill files''.  These are usually
+nothing more than a single kill file that applies to all groups, stored
+in the user's home directory.  Bah!  Puny, weak newsreaders!
 
+What I'm talking about here are Global Score Files.  Score files from
+all over the world, from users everywhere, uniting all nations in one
+big, happy score file union!  Ange-score!  New and untested!
 
-@node Picon Basics
-@subsubsection Picon Basics
+@vindex gnus-global-score-files
+All you have to do to use other people's score files is to set the
+@code{gnus-global-score-files} variable.  One entry for each score file,
+or each score file directory.  Gnus will decide by itself what score
+files are applicable to which group.
 
-What are Picons?  To quote directly from the Picons Web site:
+To use the score file
+@file{/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE} and
+all score files in the @file{/ftp@@ftp.some-where:/pub/score} directory,
+say this:
 
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
+@lisp
+(setq gnus-global-score-files
+      '("/ftp@@ftp.gnus.org:/pub/larsi/ding/score/soc.motss.SCORE"
+        "/ftp@@ftp.some-where:/pub/score/"))
+@end lisp
 
-@quotation 
-@dfn{Picons} is short for ``personal icons''.  They're small,
-constrained images used to represent users and domains on the net,
-organized into databases so that the appropriate image for a given
-e-mail address can be found.  Besides users and domains, there are picon
-databases for Usenet newsgroups and weather forecasts.  The picons are
-in either monochrome @code{XBM} format or color @code{XPM} and
-@code{GIF} formats.
-@end quotation
+@findex gnus-score-search-global-directories
+@noindent
+Simple, eh?  Directory names must end with a @samp{/}.  These
+directories are typically scanned only once during each Gnus session.
+If you feel the need to manually re-scan the remote directories, you can
+use the @code{gnus-score-search-global-directories} command.
 
-@vindex gnus-picons-piconsearch-url
-If you have a permanent connection to the Internet you can use Steve
-Kinzler's Picons Search engine by setting
-@code{gnus-picons-piconsearch-url} to the string
-@file{http://www.cs.indiana.edu/picons/search.html}.
+Note that, at present, using this option will slow down group entry
+somewhat.  (That is---a lot.)
 
-@vindex gnus-picons-database
-Otherwise you need a local copy of his database.  For instructions on
-obtaining and installing the picons databases, point your Web browser at
-@file{http://www.cs.indiana.edu/picons/ftp/index.html}.  Gnus expects
-picons to be installed into a location pointed to by
-@code{gnus-picons-database}.
+If you want to start maintaining score files for other people to use,
+just put your score file up for anonymous ftp and announce it to the
+world.  Become a retro-moderator!  Participate in the retro-moderator
+wars sure to ensue, where retro-moderators battle it out for the
+sympathy of the people, luring them to use their score files on false
+premises!  Yay!  The net is saved!
 
+Here are some tips for the would-be retro-moderator, off the top of my
+head:
 
-@node Picon Requirements
-@subsubsection Picon Requirements
+@itemize @bullet
 
-To have Gnus display Picons for you, you must be running XEmacs
-19.13 or greater since all other versions of Emacs aren't yet able to
-display images.
+@item
+Articles heavily crossposted are probably junk.
+@item
+To lower a single inappropriate article, lower by @code{Message-ID}.
+@item
+Particularly brilliant authors can be raised on a permanent basis.
+@item
+Authors that repeatedly post off-charter for the group can safely be
+lowered out of existence.
+@item
+Set the @code{mark} and @code{expunge} atoms to obliterate the nastiest
+articles completely.
 
-Additionally, you must have @code{x} support compiled into XEmacs.  To
-display color picons which are much nicer than the black & white one,
-you also need one of @code{xpm} or @code{gif} compiled into XEmacs.
+@item
+Use expiring score entries to keep the size of the file down.  You
+should probably have a long expiry period, though, as some sites keep
+old articles for a long time.
+@end itemize
 
-@vindex gnus-picons-convert-x-face
-If you want to display faces from @code{X-Face} headers, you should have
-the @code{xface} support compiled into XEmacs.  Otherwise you must have
-the @code{netpbm} utilities installed, or munge the
-@code{gnus-picons-convert-x-face} variable to use something else.
+@dots{} I wonder whether other newsreaders will support global score files
+in the future.  @emph{Snicker}.  Yup, any day now, newsreaders like Blue
+Wave, xrn and 1stReader are bound to implement scoring.  Should we start
+holding our breath yet?
 
 
-@node Easy Picons
-@subsubsection Easy Picons
+@node Kill Files
+@section Kill Files
+@cindex kill files
 
-To enable displaying picons, simply put the following line in your
-@file{~/.gnus} file and start Gnus.
+Gnus still supports those pesky old kill files.  In fact, the kill file
+entries can now be expiring, which is something I wrote before Daniel
+Quinlan thought of doing score files, so I've left the code in there.
 
-@lisp
-(setq gnus-use-picons t)
-(add-hook 'gnus-article-display-hook 'gnus-article-display-picons t)
-(add-hook 'gnus-summary-prepare-hook 'gnus-group-display-picons t)
-(add-hook 'gnus-article-display-hook 'gnus-picons-article-display-x-face)
-@end lisp
+In short, kill processing is a lot slower (and I do mean @emph{a lot})
+than score processing, so it might be a good idea to rewrite your kill
+files into score files.
 
-and make sure @code{gnus-picons-database} points to the directory
-containing the Picons databases.
+Anyway, a kill file is a normal @code{emacs-lisp} file.  You can put any
+forms into this file, which means that you can use kill files as some
+sort of primitive hook function to be run on group entry, even though
+that isn't a very good idea.
 
-Alternatively if you want to use the web piconsearch engine add this:
+Normal kill files look like this:
 
 @lisp
-(setq gnus-picons-piconsearch-url "http://www.cs.indiana.edu:800/piconsearch")
+(gnus-kill "From" "Lars Ingebrigtsen")
+(gnus-kill "Subject" "ding")
+(gnus-expunge "X")
 @end lisp
 
+This will mark every article written by me as read, and remove the
+marked articles from the summary buffer.  Very useful, you'll agree.
 
-@node Hard Picons
-@subsubsection Hard Picons 
-
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
-
-Gnus can display picons for you as you enter and leave groups and
-articles.  It knows how to interact with three sections of the picons
-database.  Namely, it can display the picons newsgroup pictures,
-author's face picture(s), and the authors domain.  To enable this
-feature, you need to select where to get the picons from, and where to
-display them.
-
-@table @code 
+Other programs use a totally different kill file syntax.  If Gnus
+encounters what looks like a @code{rn} kill file, it will take a stab at
+interpreting it.
 
-@item gnus-picons-database
-@vindex gnus-picons-database
-The location of the picons database.  Should point to a directory
-containing the @file{news}, @file{domains}, @file{users} (and so on)
-subdirectories.  This is only useful if
-@code{gnus-picons-piconsearch-url} is @code{nil}.  Defaults to
-@file{/usr/local/faces/}.
-
-@item gnus-picons-piconsearch-url
-@vindex gnus-picons-piconsearch-url
-The URL for the web picons search engine.  The only currently known
-engine is @file{http://www.cs.indiana.edu:800/piconsearch}.  To
-workaround network delays, icons will be fetched in the background.  If
-this is @code{nil} 'the default), then picons are fetched from local
-database indicated by @code{gnus-picons-database}.
-
-@item gnus-picons-display-where 
-@vindex gnus-picons-display-where 
-Where the picon images should be displayed.  It is @code{picons} by
-default (which by default maps to the buffer @samp{*Picons*}).  Other
-valid places could be @code{article}, @code{summary}, or
-@samp{*scratch*} for all I care.  Just make sure that you've made the
-buffer visible using the standard Gnus window configuration
-routines---@pxref{Windows Configuration}.
-
-@item gnus-picons-group-excluded-groups
-@vindex gnus-picons-group-excluded-groups
-Groups that are matched by this regexp won't have their group icons
-displayed. 
-
-@end table
-
-Note: If you set @code{gnus-use-picons} to @code{t}, it will set up your
-window configuration for you to include the @code{picons} buffer.
-
-Now that you've made those decision, you need to add the following
-functions to the appropriate hooks so these pictures will get displayed
-at the right time.
-
-@vindex gnus-article-display-hook
-@vindex gnus-picons-display-where
-@table @code
-@item gnus-article-display-picons
-@findex gnus-article-display-picons
-Looks up and displays the picons for the author and the author's domain
-in the @code{gnus-picons-display-where} buffer.  Should be added to the
-@code{gnus-article-display-hook}.
+Two summary functions for editing a @sc{gnus} kill file:
 
-@item gnus-group-display-picons
-@findex gnus-article-display-picons
-Displays picons representing the current group.  This function should
-be added to the @code{gnus-summary-prepare-hook} or to the
-@code{gnus-article-display-hook} if @code{gnus-picons-display-where}
-is set to @code{article}.
+@table @kbd
 
-@item gnus-picons-article-display-x-face
-@findex gnus-article-display-picons
-Decodes and displays the X-Face header if present.  This function
-should be added to @code{gnus-article-display-hook}.
+@item M-k
+@kindex M-k (Summary)
+@findex gnus-summary-edit-local-kill
+Edit this group's kill file (@code{gnus-summary-edit-local-kill}).
 
+@item M-K
+@kindex M-K (Summary)
+@findex gnus-summary-edit-global-kill
+Edit the general kill file (@code{gnus-summary-edit-global-kill}).
 @end table
 
-Note:  You must append them to the hook, so make sure to specify 't'
-for the append flag of @code{add-hook}:
-
-@lisp
-(add-hook 'gnus-article-display-hook 'gnus-article-display-picons t)
-@end lisp
+Two group mode functions for editing the kill files:
 
+@table @kbd
 
-@node Picon Useless Configuration
-@subsubsection Picon Useless Configuration
+@item M-k
+@kindex M-k (Group)
+@findex gnus-group-edit-local-kill
+Edit this group's kill file (@code{gnus-group-edit-local-kill}).
 
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
+@item M-K
+@kindex M-K (Group)
+@findex gnus-group-edit-global-kill
+Edit the general kill file (@code{gnus-group-edit-global-kill}).
+@end table
 
-The following variables offer further control over how things are
-done, where things are located, and other useless stuff you really
-don't need to worry about.
+Kill file variables:
 
 @table @code
+@item gnus-kill-file-name
+@vindex gnus-kill-file-name
+A kill file for the group @samp{soc.motss} is normally called
+@file{soc.motss.KILL}.  The suffix appended to the group name to get
+this file name is detailed by the @code{gnus-kill-file-name} variable.
+The ``global'' kill file (not in the score file sense of ``global'', of
+course) is just called @file{KILL}.
 
-@item gnus-picons-news-directories
-@vindex gnus-picons-news-directories
-List of subdirectories to search in @code{gnus-picons-database} for
-newsgroups faces.  @code{("news")} is the default.
+@vindex gnus-kill-save-kill-file
+@item gnus-kill-save-kill-file
+If this variable is non-@code{nil}, Gnus will save the
+kill file after processing, which is necessary if you use expiring
+kills.
 
-@item gnus-picons-user-directories
-@vindex gnus-picons-user-directories
-List of subdirectories to search in @code{gnus-picons-database} for user
-faces.  @code{("local" "users" "usenix" "misc")} is the default.
+@item gnus-apply-kill-hook
+@vindex gnus-apply-kill-hook
+@findex gnus-apply-kill-file-unless-scored
+@findex gnus-apply-kill-file
+A hook called to apply kill files to a group.  It is
+@code{(gnus-apply-kill-file)} by default.  If you want to ignore the
+kill file if you have a score file for the same group, you can set this
+hook to @code{(gnus-apply-kill-file-unless-scored)}.  If you don't want
+kill files to be processed, you should set this variable to @code{nil}.
 
-@item gnus-picons-domain-directories
-@vindex gnus-picons-domain-directories
-List of subdirectories to search in @code{gnus-picons-database} for
-domain name faces.  Defaults to @code{("domains")}.  Some people may
-want to add @samp{"unknown"} to this list.
+@item gnus-kill-file-mode-hook
+@vindex gnus-kill-file-mode-hook
+A hook called in kill-file mode buffers.
 
-@item gnus-picons-convert-x-face
-@vindex gnus-picons-convert-x-face
-If you don't have @code{xface} support builtin XEmacs, this is the
-command to use to convert the @code{X-Face} header to an X bitmap
-(@code{xbm}).  Defaults to @code{(format "@{ echo '/* Width=48,
-Height=48 */'; uncompface; @} | icontopbm | pbmtoxbm > %s"
-gnus-picons-x-face-file-name)}
-
-@item gnus-picons-x-face-file-name
-@vindex gnus-picons-x-face-file-name
-Names a temporary file to store the @code{X-Face} bitmap in.  Defaults
-to @code{(format "/tmp/picon-xface.%s.xbm" (user-login-name))}.
-
-@item gnus-picons-has-modeline-p
-@vindex gnus-picons-has-modeline-p
-If you have set @code{gnus-picons-display-where} to @code{picons}, your
-XEmacs frame will become really cluttered.  To alleviate this a bit you
-can set @code{gnus-picons-has-modeline-p} to @code{nil}; this will
-remove the mode line from the Picons buffer.  This is only useful if
-@code{gnus-picons-display-where} is @code{picons}.
-
-@item gnus-picons-refresh-before-display
-@vindex gnus-picons-refresh-before-display
-If non-nil, display the article buffer before computing the picons.
-Defaults to @code{nil}.
-
-@item gnus-picons-display-as-address
-@vindex gnus-picons-display-as-address
-If @code{t} display textual email addresses along with pictures.
-Defaults to @code{t}.
-
-@item gnus-picons-file-suffixes
-@vindex gnus-picons-file-suffixes
-Ordered list of suffixes on picon file names to try.  Defaults to
-@code{("xpm" "gif" "xbm")} minus those not builtin your XEmacs.
-
-@item gnus-picons-display-article-move-p
-@vindex gnus-picons-display-article-move-p
-Whether to move point to first empty line when displaying picons.  This
-has only an effect if `gnus-picons-display-where' has value `article'.
-
-@item gnus-picons-clear-cache-on-shutdown
-@vindex gnus-picons-clear-cache-on-shutdown
-Whether to clear the picons cache when exiting gnus.  Gnus caches every
-picons it finds while it is running.  This saves some time in the search
-process but eats some memory.  If this variable is set to @code{nil},
-Gnus will never clear the cache itself; you will have to manually call
-@code{gnus-picons-clear-cache} to clear it.  Otherwise the cache will be
-cleared every time you exit Gnus.  Defaults to @code{t}.
+@end table
 
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
 
-@end table
+@node Converting Kill Files
+@section Converting Kill Files
+@cindex kill files
+@cindex converting kill files
 
-@node Smileys
-@subsection Smileys
-@cindex smileys
+If you have loads of old kill files, you may want to convert them into
+score files.  If they are ``regular'', you can use
+the @file{gnus-kill-to-score.el} package; if not, you'll have to do it
+by hand.
 
-@iftex
-@iflatex
-\gnusfig{-3cm}{0.5cm}{\epsfig{figure=tmp/BigFace.ps,height=20cm}}
-\input{smiley}
-@end iflatex
-@end iftex
+The kill to score conversion package isn't included in Gnus by default.
+You can fetch it from
+@uref{http://www.stud.ifi.uio.no/~larsi/ding-various/gnus-kill-to-score.el}.
 
-@dfn{Smiley} is a package separate from Gnus, but since Gnus is
-currently the only package that uses Smiley, it is documented here.
+If your old kill files are very complex---if they contain more
+non-@code{gnus-kill} forms than not, you'll have to convert them by
+hand.  Or just let them be as they are.  Gnus will still use them as
+before.
 
-In short---to use Smiley in Gnus, put the following in your
-@file{.gnus.el} file:
 
-@lisp
-(add-hook 'gnus-article-display-hook 'gnus-smiley-display t)
-@end lisp
+@node GroupLens
+@section GroupLens
+@cindex GroupLens
 
-Smiley maps text smiley faces---@samp{:-)}, @samp{:-=}, @samp{:-(} and
-the like---to pictures and displays those instead of the text smiley
-faces.  The conversion is controlled by a list of regexps that matches
-text and maps that to file names.
+@sc{Note:} Unfortunately the GroupLens system seems to have shut down,
+so this section is mostly of historical interest.
 
-@vindex smiley-nosey-regexp-alist
-@vindex smiley-deformed-regexp-alist
-Smiley supplies two example conversion alists by default:
-@code{smiley-deformed-regexp-alist} (which matches @samp{:)}, @samp{:(}
-and so on), and @code{smiley-nosey-regexp-alist} (which matches
-@samp{:-)}, @samp{:-(} and so on).
+@uref{http://www.cs.umn.edu/Research/GroupLens/, GroupLens} is a
+collaborative filtering system that helps you work together with other
+people to find the quality news articles out of the huge volume of
+news articles generated every day.
 
-The alist used is specified by the @code{smiley-regexp-alist} variable,
-which defaults to the value of @code{smiley-deformed-regexp-alist}.
+To accomplish this the GroupLens system combines your opinions about
+articles you have already read with the opinions of others who have done
+likewise and gives you a personalized prediction for each unread news
+article.  Think of GroupLens as a matchmaker.  GroupLens watches how you
+rate articles, and finds other people that rate articles the same way.
+Once it has found some people you agree with it tells you, in the form
+of a prediction, what they thought of the article.  You can use this
+prediction to help you decide whether or not you want to read the
+article.
 
-The first item in each element is the regexp to be matched; the second
-element is the regexp match group that is to be replaced by the picture;
-and the third element is the name of the file to be displayed.
+@menu
+* Using GroupLens::             How to make Gnus use GroupLens.
+* Rating Articles::             Letting GroupLens know how you rate articles.
+* Displaying Predictions::      Displaying predictions given by GroupLens.
+* GroupLens Variables::         Customizing GroupLens.
+@end menu
 
-The following variables customize where Smiley will look for these
-files, as well as the color to be used and stuff:
 
-@table @code
+@node Using GroupLens
+@subsection Using GroupLens
 
-@item smiley-data-directory
-@vindex smiley-data-directory
-Where Smiley will look for smiley faces files.
+To use GroupLens you must register a pseudonym with your local
+@uref{http://www.cs.umn.edu/Research/GroupLens/bbb.html, Better Bit
+Bureau (BBB)} is the only better bit in town at the moment.
 
-@item smiley-flesh-color
-@vindex smiley-flesh-color
-Skin color.  The default is @samp{yellow}, which is really racist.
+Once you have registered you'll need to set a couple of variables.
 
-@item smiley-features-color
-@vindex smiley-features-color
-Color of the features of the face.  The default is @samp{black}.
+@table @code
 
-@item smiley-tongue-color
-@vindex smiley-tongue-color
-Color of the tongue.  The default is @samp{red}.
+@item gnus-use-grouplens
+@vindex gnus-use-grouplens
+Setting this variable to a non-@code{nil} value will make Gnus hook into
+all the relevant GroupLens functions.
 
-@item smiley-circle-color
-@vindex smiley-circle-color
-Color of the circle around the face.  The default is @samp{black}.
+@item grouplens-pseudonym
+@vindex grouplens-pseudonym
+This variable should be set to the pseudonym you got when registering
+with the Better Bit Bureau.
 
-@item smiley-mouse-face
-@vindex smiley-mouse-face
-Face used for mouse highlighting over the smiley face.
+@item grouplens-newsgroups
+@vindex grouplens-newsgroups
+A list of groups that you want to get GroupLens predictions for.
 
 @end table
 
+That's the minimum of what you need to get up and running with GroupLens.
+Once you've registered, GroupLens will start giving you scores for
+articles based on the average of what other people think.  But, to get
+the real benefit of GroupLens you need to start rating articles
+yourself.  Then the scores GroupLens gives you will be personalized for
+you, based on how the people you usually agree with have already rated.
 
-@node Toolbar
-@subsection Toolbar
-
-@table @code
 
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
+@node Rating Articles
+@subsection Rating Articles
 
-@item gnus-use-toolbar
-@vindex gnus-use-toolbar
-If @code{nil}, don't display toolbars.  If non-@code{nil}, it should be
-one of @code{default-toolbar}, @code{top-toolbar}, @code{bottom-toolbar},
-@code{right-toolbar}, or @code{left-toolbar}.
+In GroupLens, an article is rated on a scale from 1 to 5, inclusive.
+Where 1 means something like this article is a waste of bandwidth and 5
+means that the article was really good.  The basic question to ask
+yourself is, ``on a scale from 1 to 5 would I like to see more articles
+like this one?''
 
-@item gnus-group-toolbar
-@vindex gnus-group-toolbar
-The toolbar in the group buffer.
+There are four ways to enter a rating for an article in GroupLens.
 
-@item gnus-summary-toolbar
-@vindex gnus-summary-toolbar
-The toolbar in the summary buffer.
+@table @kbd
 
-@item gnus-summary-mail-toolbar
-@vindex gnus-summary-mail-toolbar
-The toolbar in the summary buffer of mail groups.
+@item r
+@kindex r (GroupLens)
+@findex bbb-summary-rate-article
+This function will prompt you for a rating on a scale of one to five.
+
+@item k
+@kindex k (GroupLens)
+@findex grouplens-score-thread
+This function will prompt you for a rating, and rate all the articles in
+the thread.  This is really useful for some of those long running giant
+threads in rec.humor.
 
 @end table
 
+The next two commands, @kbd{n} and @kbd{,} take a numerical prefix to be
+the score of the article you're reading.
 
-@node XVarious
-@subsection Various XEmacs Variables
+@table @kbd
 
-@table @code
-@item gnus-xmas-glyph-directory
-@vindex gnus-xmas-glyph-directory
-This is where Gnus will look for pictures.  Gnus will normally
-auto-detect this directory, but you may set it manually if you have an
-unusual directory structure.
+@item 1-5 n
+@kindex n (GroupLens)
+@findex grouplens-next-unread-article
+Rate the article and go to the next unread article.
 
-@item gnus-xmas-logo-color-alist
-@vindex gnus-xmas-logo-color-alist
-This is an alist where the key is a type symbol and the values are the
-foreground and background color of the splash page glyph.
+@item 1-5 ,
+@kindex , (GroupLens)
+@findex grouplens-best-unread-article
+Rate the article and go to the next unread article with the highest score.
 
-@item gnus-xmas-logo-color-style
-@vindex gnus-xmas-logo-color-style
-This is the key used to look up the color in the alist described above.
-Legal values include @code{flame}, @code{pine}, @code{moss},
-@code{irish}, @code{sky}, @code{tin}, @code{velvet}, @code{grape},
-@code{labia}, @code{berry}, @code{neutral}, and @code{september}.
+@end table
 
-@item gnus-xmas-modeline-glyph
-@vindex gnus-xmas-modeline-glyph
-A glyph displayed in all Gnus mode lines.  It is a tiny gnu head by
-default. 
+If you want to give the current article a score of 4 and then go to the
+next article, just type @kbd{4 n}.
 
-@iftex
-@iflatex
-\margindex{}
-@end iflatex
-@end iftex
 
-@end table
+@node Displaying Predictions
+@subsection Displaying Predictions
 
+GroupLens makes a prediction for you about how much you will like a
+news article.  The predictions from GroupLens are on a scale from 1 to
+5, where 1 is the worst and 5 is the best.  You can use the predictions
+from GroupLens in one of three ways controlled by the variable
+@code{gnus-grouplens-override-scoring}.
 
+@vindex gnus-grouplens-override-scoring
+There are three ways to display predictions in grouplens.  You may
+choose to have the GroupLens scores contribute to, or override the
+regular Gnus scoring mechanism.  override is the default; however, some
+people prefer to see the Gnus scores plus the grouplens scores.  To get
+the separate scoring behavior you need to set
+@code{gnus-grouplens-override-scoring} to @code{'separate}.  To have the
+GroupLens predictions combined with the grouplens scores set it to
+@code{'override} and to combine the scores set
+@code{gnus-grouplens-override-scoring} to @code{'combine}.  When you use
+the combine option you will also want to set the values for
+@code{grouplens-prediction-offset} and
+@code{grouplens-score-scale-factor}.
 
+@vindex grouplens-prediction-display
+In either case, GroupLens gives you a few choices for how you would like
+to see your predictions displayed.  The display of predictions is
+controlled by the @code{grouplens-prediction-display} variable.
 
-@node Fuzzy Matching
-@section Fuzzy Matching
-@cindex fuzzy matching
+The following are valid values for that variable.
 
-Gnus provides @dfn{fuzzy matching} of @code{Subject} lines when doing
-things like scoring, thread gathering and thread comparison.  
+@table @code
+@item prediction-spot
+The higher the prediction, the further to the right an @samp{*} is
+displayed.
 
-As opposed to regular expression matching, fuzzy matching is very fuzzy.
-It's so fuzzy that there's not even a definition of what @dfn{fuzziness}
-means, and the implementation has changed over time.
+@item confidence-interval
+A numeric confidence interval.
 
-Basically, it tries to remove all noise from lines before comparing.
-@samp{Re: }, parenthetical remarks, white space, and so on, are filtered
-out of the strings before comparing the results.  This often leads to
-adequate results---even when faced with strings generated by text
-manglers masquerading as newsreaders.
+@item prediction-bar
+The higher the prediction, the longer the bar.
 
+@item confidence-bar
+Numerical confidence.
 
-@node Thwarting Email Spam
-@section Thwarting Email Spam
-@cindex email spam
-@cindex spam
-@cindex UCE
-@cindex unsolicited commercial email
+@item confidence-spot
+The spot gets bigger with more confidence.
 
-In these last days of the Usenet, commercial vultures are hanging about
-and grepping through news like crazy to find email addresses they can
-foist off their scams and products to.  As a reaction to this, many
-people have started putting nonsense addresses into their @code{From}
-lines.  I think this is counterproductive---it makes it difficult for
-people to send you legitimate mail in response to things you write, as
-well as making it difficult to see who wrote what.  This rewriting may
-perhaps be a bigger menace than the unsolicited commercial email itself
-in the end.
+@item prediction-num
+Plain-old numeric value.
 
-The biggest problem I have with email spam is that it comes in under
-false pretenses.  I press @kbd{g} and Gnus merrily informs me that I
-have 10 new emails.  I say ``Golly gee!  Happy is me!'' and select the
-mail group, only to find two pyramid schemes, seven advertisements
-(``New!  Miracle tonic for growing full, lustrouos hair on your toes!'')
-and one mail asking me to repent and find some god.
+@item confidence-plus-minus
+Prediction +/- confidence.
 
-This is annoying.
+@end table
 
-The way to deal with this is having Gnus split out all spam into a
-@samp{spam} mail group (@pxref{Splitting Mail}).
 
-First, pick one (1) valid mail address that you can be reached at, and
-put it in your @code{From} header of all your news articles.  (I've
-chosen @samp{larsi@@trym.ifi.uio.no}, but for many addresses on the form
-@samp{larsi+usenet@@ifi.uio.no} will be a better choice.  Ask your
-sysadm whether your sendmail installation accepts keywords in the local
-part of the mail address.)
+@node GroupLens Variables
+@subsection GroupLens Variables
 
-@lisp
-(setq message-default-news-headers
-      "From: Lars Magne Ingebrigtsen <larsi@@trym.ifi.uio.no>\n")
-@end lisp
+@table @code
 
-Then put the following split rule in @code{nnmail-split-fancy}
-(@pxref{Fancy Mail Splitting}):
+@item gnus-summary-grouplens-line-format
+The summary line format used in GroupLens-enhanced summary buffers.  It
+accepts the same specs as the normal summary line format (@pxref{Summary
+Buffer Lines}).  The default is @samp{%U%R%z%l%I%(%[%4L: %-23,23n%]%)
+%s\n}.
 
-@lisp
-(
- ...
- (to "larsi@@trym.ifi.uio.no"
-      (| ("subject" "re:.*" "misc")
-         ("references" ".*@@.*" "misc")
-         "spam"))
- ...
-)
-@end lisp
+@item grouplens-bbb-host
+Host running the bbbd server.  @samp{grouplens.cs.umn.edu} is the
+default.
 
-This says that all mail to this address is suspect, but if it has a
-@code{Subject} that starts with a @samp{Re:} or has a @code{References}
-header, it's probably ok.  All the rest goes to the @samp{spam} group.
-(This idea probably comes from Tim Pierce.)
+@item grouplens-bbb-port
+Port of the host running the bbbd server.  The default is 9000.
 
-In addition, many mail spammers talk directly to your @code{smtp} server
-and do not include your email address explicitly in the @code{To}
-header.  Why they do this is unknown---perhaps it's to thwart this
-twarting scheme?  In any case, this is trivial to deal with---you just
-put anything not addressed to you in the @samp{spam} group by ending
-your fancy split rule in this way:
+@item grouplens-score-offset
+Offset the prediction by this value.  In other words, subtract the
+prediction value by this number to arrive at the effective score.  The
+default is 0.
 
-@lisp
-(
- ...
- (to "larsi" "misc")
- "spam")
-@end lisp
+@item grouplens-score-scale-factor
+This variable allows the user to magnify the effect of GroupLens scores.
+The scale factor is applied after the offset.  The default is 1.
 
-In my experience, this will sort virtually everything into the right
-group.  You still have to check the @samp{spam} group from time to time to
-check for legitimate mail, though.  If you feel like being a good net
-citizen, you can even send off complaints to the proper authorities on
-each unsolicited commercial email---at your leisure.
+@end table
 
-If you are also a lazy net citizen, you will probably prefer complaining
-automatically with the @file{gnus-junk.el} package, availiable FOR FREE
-at @file{<URL:http://stud2.tuwien.ac.at/~e9426626/gnus-junk.html>}.
-Since most e-mail spam is sent automatically, this may reconcile the
-cosmic balance somewhat.
 
-This works for me.  It allows people an easy way to contact me (they can
-just press @kbd{r} in the usual way), and I'm not bothered at all with
-spam.  It's a win-win situation.  Forging @code{From} headers to point
-to non-existant domains is yucky, in my opinion.
+@node Advanced Scoring
+@section Advanced Scoring
 
+Scoring on Subjects and From headers is nice enough, but what if you're
+really interested in what a person has to say only when she's talking
+about a particular subject?  Or what if you really don't want to
+read what person A has to say when she's following up to person B, but
+want to read what she says when she's following up to person C?
 
-@node Various Various
-@section Various Various
-@cindex mode lines
-@cindex highlights
+By using advanced scoring rules you may create arbitrarily complex
+scoring patterns.
 
-@table @code
+@menu
+* Advanced Scoring Syntax::     A definition.
+* Advanced Scoring Examples::   What they look like.
+* Advanced Scoring Tips::       Getting the most out of it.
+@end menu
 
-@item gnus-home-directory
-All Gnus path variables will be initialized from this variable, which
-defaults to @file{~/}.
 
-@item gnus-directory
-@vindex gnus-directory
-Most Gnus storage path variables will be initialized from this variable,
-which defaults to the @samp{SAVEDIR} environment variable, or
-@file{~/News/} if that variable isn't set.
+@node Advanced Scoring Syntax
+@subsection Advanced Scoring Syntax
 
-@item gnus-default-directory
-@vindex gnus-default-directory
-Not related to the above variable at all---this variable says what the
-default directory of all Gnus buffers should be.  If you issue commands
-like @kbd{C-x C-f}, the prompt you'll get starts in the current buffer's
-default directory.  If this variable is @code{nil} (which is the
-default), the default directory will be the default directory of the
-buffer you were in when you started Gnus.
+Ordinary scoring rules have a string as the first element in the rule.
+Advanced scoring rules have a list as the first element.  The second
+element is the score to be applied if the first element evaluated to a
+non-@code{nil} value.
 
-@item gnus-verbose
-@vindex gnus-verbose
-This variable is an integer between zero and ten.  The higher the value,
-the more messages will be displayed.  If this variable is zero, Gnus
-will never flash any messages, if it is seven (which is the default),
-most important messages will be shown, and if it is ten, Gnus won't ever
-shut up, but will flash so many messages it will make your head swim.
+These lists may consist of three logical operators, one redirection
+operator, and various match operators.
 
-@item gnus-verbose-backends
-@vindex gnus-verbose-backends
-This variable works the same way as @code{gnus-verbose}, but it applies
-to the Gnus backends instead of Gnus proper.
+Logical operators:
 
-@item nnheader-max-head-length
-@vindex nnheader-max-head-length
-When the backends read straight heads of articles, they all try to read
-as little as possible.  This variable (default 4096) specifies
-the absolute max length the backends will try to read before giving up
-on finding a separator line between the head and the body.  If this
-variable is @code{nil}, there is no upper read bound.  If it is
-@code{t}, the backends won't try to read the articles piece by piece,
-but read the entire articles.  This makes sense with some versions of
-@code{ange-ftp} or @code{efs}. 
+@table @code
+@item &
+@itemx and
+This logical operator will evaluate each of its arguments until it finds
+one that evaluates to @code{false}, and then it'll stop.  If all arguments
+evaluate to @code{true} values, then this operator will return
+@code{true}.
 
-@item nnheader-head-chop-length
-@vindex nnheader-head-chop-length
-This variable (default 2048) says how big a piece of each article to
-read when doing the operation described above.
+@item |
+@itemx or
+This logical operator will evaluate each of its arguments until it finds
+one that evaluates to @code{true}.  If no arguments are @code{true},
+then this operator will return @code{false}.
 
-@item nnheader-file-name-translation-alist 
-@vindex nnheader-file-name-translation-alist 
-@cindex file names
-@cindex invalid characters in file names
-@cindex characters in file names
-This is an alist that says how to translate characters in file names.
-For instance, if @samp{:} is invalid as a file character in file names
-on your system (you OS/2 user you), you could say something like:
+@item !
+@itemx not
+@itemx Â¬
+This logical operator only takes a single argument.  It returns the
+logical negation of the value of its argument.
 
-@lisp
-(setq nnheader-file-name-translation-alist 
-      '((?: . ?_)))
-@end lisp
+@end table
 
-In fact, this is the default value for this variable on OS/2 and MS
-Windows (phooey) systems.
+There is an @dfn{indirection operator} that will make its arguments
+apply to the ancestors of the current article being scored.  For
+instance, @code{1-} will make score rules apply to the parent of the
+current article.  @code{2-} will make score rules apply to the
+grandparent of the current article.  Alternatively, you can write
+@code{^^}, where the number of @code{^}s (carets) says how far back into
+the ancestry you want to go.
 
-@item gnus-hidden-properties
-@vindex gnus-hidden-properties
-This is a list of properties to use to hide ``invisible'' text.  It is
-@code{(invisible t intangible t)} by default on most systems, which
-makes invisible text invisible and intangible.
+Finally, we have the match operators.  These are the ones that do the
+real work.  Match operators are header name strings followed by a match
+and a match type.  A typical match operator looks like @samp{("from"
+"Lars Ingebrigtsen" s)}.  The header names are the same as when using
+simple scoring, and the match types are also the same.
 
-@item gnus-parse-headers-hook
-@vindex gnus-parse-headers-hook
-A hook called before parsing headers.  It can be used, for instance, to
-gather statistics on the headers fetched, or perhaps you'd like to prune
-some headers.  I don't see why you'd want that, though.
 
-@item gnus-shell-command-separator
-@vindex gnus-shell-command-separator
-String used to separate two shell commands.  The default is @samp{;}. 
+@node Advanced Scoring Examples
+@subsection Advanced Scoring Examples
 
+Please note that the following examples are score file rules.  To
+make a complete score file from them, surround them with another pair
+of parentheses.
 
-@end table
+Let's say you want to increase the score of articles written by Lars
+when he's talking about Gnus:
 
+@example
+@group
+((&
+  ("from" "Lars Ingebrigtsen")
+  ("subject" "Gnus"))
+ 1000)
+@end group
+@end example
 
-@node The End
-@chapter The End
+Quite simple, huh?
 
-Well, that's the manual---you can get on with your life now.  Keep in
-touch.  Say hello to your cats from me.  
+When he writes long articles, he sometimes has something nice to say:
 
-My @strong{ghod}---I just can't stand goodbyes.  Sniffle.
+@example
+((&
+  ("from" "Lars Ingebrigtsen")
+  (|
+   ("subject" "Gnus")
+   ("lines" 100 >)))
+ 1000)
+@end example
 
-Ol' Charles Reznikoff said it pretty well, so I leave the floor to him:
+However, when he responds to things written by Reig Eigil Logge, you
+really don't want to read what he's written:
 
-@quotation
-@strong{Te Deum}
+@example
+((&
+  ("from" "Lars Ingebrigtsen")
+  (1- ("from" "Reig Eigir Logge")))
+ -100000)
+@end example
 
-@sp 1
-Not because of victories @*
-I sing,@*
-having none,@*
-but for the common sunshine,@*
-the breeze,@*
-the largess of the spring.
+Everybody that follows up Redmondo when he writes about disappearing
+socks should have their scores raised, but only when they talk about
+white socks.  However, when Lars talks about socks, it's usually not
+very interesting:
 
-@sp 1
-Not for victory@*
-but for the day's work done@*
-as well as I was able;@*
-not for a seat upon the dais@*
-but at the common table.@*
-@end quotation
+@example
+((&
+  (1-
+   (&
+    ("from" "redmondo@@.*no" r)
+    ("body" "disappearing.*socks" t)))
+  (! ("from" "Lars Ingebrigtsen"))
+  ("body" "white.*socks"))
+ 1000)
+@end example
 
+The possibilities are endless.
 
-@node Appendices
-@chapter Appendices
 
-@menu
-* History::                        How Gnus got where it is today.
-* Terminology::                    We use really difficult, like, words here.
-* Customization::                  Tailoring Gnus to your needs.
-* Troubleshooting::                What you might try if things do not work.
-* A Programmers Guide to Gnus::    Rilly, rilly technical stuff.
-* Emacs for Heathens::             A short introduction to Emacsian terms.
-* Frequently Asked Questions::     A question-and-answer session.
-@end menu
+@node Advanced Scoring Tips
+@subsection Advanced Scoring Tips
 
+The @code{&} and @code{|} logical operators do short-circuit logic.
+That is, they stop processing their arguments when it's clear what the
+result of the operation will be.  For instance, if one of the arguments
+of an @code{&} evaluates to @code{false}, there's no point in evaluating
+the rest of the arguments.  This means that you should put slow matches
+(@samp{body}, @samp{header}) last and quick matches (@samp{from},
+@samp{subject}) first.
 
-@node History
-@section History
+The indirection arguments (@code{1-} and so on) will make their
+arguments work on previous generations of the thread.  If you say
+something like:
 
-@cindex history
-@sc{gnus} was written by Masanobu @sc{Umeda}.  When autumn crept up in
-'94, Lars Magne Ingebrigtsen grew bored and decided to rewrite Gnus.
+@example
+...
+(1-
+ (1-
+  ("from" "lars")))
+...
+@end example
 
-If you want to investigate the person responsible for this outrage, you
-can point your (feh!) web browser to
-@file{http://www.ifi.uio.no/~larsi/}.  This is also the primary
-distribution point for the new and spiffy versions of Gnus, and is known
-as The Site That Destroys Newsrcs And Drives People Mad.
+Then that means "score on the from header of the grandparent of the
+current article".  An indirection is quite fast, but it's better to say:
 
-During the first extended alpha period of development, the new Gnus was
-called ``(ding) Gnus''.  @dfn{(ding)} is, of course, short for
-@dfn{ding is not Gnus}, which is a total and utter lie, but who cares?
-(Besides, the ``Gnus'' in this abbreviation should probably be
-pronounced ``news'' as @sc{Umeda} intended, which makes it a more
-appropriate name, don't you think?)
+@example
+(1-
+ (&
+  ("from" "Lars")
+  ("subject" "Gnus")))
+@end example
 
-In any case, after spending all that energy on coming up with a new and
-spunky name, we decided that the name was @emph{too} spunky, so we
-renamed it back again to ``Gnus''.  But in mixed case.  ``Gnus'' vs.
-``@sc{gnus}''.  New vs. old.
+than it is to say:
 
-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).
+@example
+(&
+ (1- ("from" "Lars"))
+ (1- ("subject" "Gnus")))
+@end example
 
-In May 1996 the next Gnus generation (aka. ``September Gnus'' (after 99
-releases)) was released under the name ``Gnus 5.2'' (40 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''.
+@node Score Decays
+@section Score Decays
+@cindex score decays
+@cindex decays
 
-If you happen upon a version of Gnus that has a prefixed name --
-``(ding) Gnus'', ``September Gnus'', ``Red Gnus'', ``Quassia Gnus'' --
-don't panic.  Don't let it know that you're frightened.  Back away.
-Slowly.  Whatever you do, don't run.  Walk away, calmly, until you're
-out of its reach.  Find a proper released version of Gnus and snuggle up
-to that instead.
+You may find that your scores have a tendency to grow without
+bounds, especially if you're using adaptive scoring.  If scores get too
+big, they lose all meaning---they simply max out and it's difficult to
+use them in any sensible way.
 
-@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.
-* 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
+@vindex gnus-decay-scores
+@findex gnus-decay-score
+@vindex gnus-decay-score-function
+Gnus provides a mechanism for decaying scores to help with this problem.
+When score files are loaded and @code{gnus-decay-scores} is
+non-@code{nil}, Gnus will run the score files through the decaying
+mechanism thereby lowering the scores of all non-permanent score rules.
+The decay itself if performed by the @code{gnus-decay-score-function}
+function, which is @code{gnus-decay-score} by default.  Here's the
+definition of that function:
 
+@lisp
+(defun gnus-decay-score (score)
+  "Decay SCORE according to `gnus-score-decay-constant'
+and `gnus-score-decay-scale'."
+  (let ((n (- score
+              (* (if (< score 0) -1 1)
+                 (min (abs score)
+                      (max gnus-score-decay-constant
+                           (* (abs score)
+                              gnus-score-decay-scale)))))))
+    (if (and (featurep 'xemacs)
+             ;; XEmacs' floor can handle only the floating point
+             ;; number below the half of the maximum integer.
+             (> (abs n) (lsh -1 -2)))
+        (string-to-number
+         (car (split-string (number-to-string n) "\\.")))
+      (floor n))))
+@end lisp
 
-@node Why?
-@subsection Why?
+@vindex gnus-score-decay-scale
+@vindex gnus-score-decay-constant
+@code{gnus-score-decay-constant} is 3 by default and
+@code{gnus-score-decay-scale} is 0.05.  This should cause the following:
 
-What's the point of Gnus?  
+@enumerate
+@item
+Scores between -3 and 3 will be set to 0 when this function is called.
 
-I want to provide a ``rad'', ``happening'', ``way cool'' and ``hep''
-newsreader, that lets you do anything you can think of.  That was my
-original motivation, but while working on Gnus, it has become clear to
-me that this generation of newsreaders really belong in the stone age.
-Newsreaders haven't developed much since the infancy of the net.  If the
-volume continues to rise with the current rate of increase, all current
-newsreaders will be pretty much useless.  How do you deal with
-newsgroups that have thousands of new articles each day?  How do you
-keep track of millions of people who post?
+@item
+Scores with magnitudes between 3 and 60 will be shrunk by 3.
 
-Gnus offers no real solutions to these questions, but I would very much
-like to see Gnus being used as a testing ground for new methods of
-reading and fetching news.  Expanding on @sc{Umeda}-san's wise decision
-to separate the newsreader from the backends, Gnus now offers a simple
-interface for anybody who wants to write new backends for fetching mail
-and news from different sources.  I have added hooks for customizations
-everywhere I could imagine it being useful.  By doing so, I'm inviting
-every one of you to explore and invent.
+@item
+Scores with magnitudes greater than 60 will be shrunk by 5% of the
+score.
+@end enumerate
 
-May Gnus never be complete. @kbd{C-u 100 M-x all-hail-emacs} and
-@kbd{C-u 100 M-x all-hail-xemacs}.
+If you don't like this decay function, write your own.  It is called
+with the score to be decayed as its only parameter, and it should return
+the new score, which should be an integer.
 
+Gnus will try to decay scores once a day.  If you haven't run Gnus for
+four days, Gnus will decay the scores four times, for instance.
 
-@node Compatibility
-@subsection Compatibility
+@iftex
+@iflatex
+@chapter Message
+@include message.texi
+@chapter Emacs MIME
+@include emacs-mime.texi
+@chapter Sieve
+@include sieve.texi
+@c @chapter PGG
+@c @include pgg.texi
+@end iflatex
+@end iftex
 
-@cindex compatibility
-Gnus was designed to be fully compatible with @sc{gnus}.  Almost all key
-bindings have been kept.  More key bindings have been added, of course,
-but only in one or two obscure cases have old bindings been changed.
+@node Various
+@chapter Various
 
-Our motto is:
-@quotation
-@cartouche
-@center In a cloud bones of steel.
-@end cartouche
-@end quotation
+@menu
+* Process/Prefix::              A convention used by many treatment commands.
+* Interactive::                 Making Gnus ask you many questions.
+* Symbolic Prefixes::           How to supply some Gnus functions with options.
+* Formatting Variables::        You can specify what buffers should look like.
+* Window Layout::               Configuring the Gnus buffer windows.
+* Faces and Fonts::             How to change how faces look.
+* Compilation::                 How to speed Gnus up.
+* Mode Lines::                  Displaying information in the mode lines.
+* Highlighting and Menus::      Making buffers look all nice and cozy.
+* Buttons::                     Get tendinitis in ten easy steps!
+* Daemons::                     Gnus can do things behind your back.
+* NoCeM::                       How to avoid spam and other fatty foods.
+* Undo::                        Some actions can be undone.
+* Predicate Specifiers::        Specifying predicates.
+* Moderation::                  What to do if you're a moderator.
+* Image Enhancements::          Modern versions of Emacs/XEmacs can display images.
+* Fuzzy Matching::              What's the big fuzz?
+* Thwarting Email Spam::        A how-to on avoiding unsolicited commercial email.
+* Other modes::                 Interaction with other modes.
+* Various Various::             Things that are really various.
+@end menu
 
-All commands have kept their names.  Some internal functions have changed
-their names.
 
-The @code{gnus-uu} package has changed drastically. @xref{Decoding
-Articles}. 
+@node Process/Prefix
+@section Process/Prefix
+@cindex process/prefix convention
 
-One major compatibility question is the presence of several summary
-buffers.  All variables relevant while reading a group are
-buffer-local to the summary buffer they belong in.  Although many
-important variables have their values copied into their global
-counterparts whenever a command is executed in the summary buffer, this
-change might lead to incorrect values being used unless you are careful.
+Many functions, among them functions for moving, decoding and saving
+articles, use what is known as the @dfn{Process/Prefix convention}.
 
-All code that relies on knowledge of @sc{gnus} internals will probably
-fail.  To take two examples: Sorting @code{gnus-newsrc-alist} (or
-changing it in any way, as a matter of fact) is strictly verboten.  Gnus
-maintains a hash table that points to the entries in this alist (which
-speeds up many functions), and changing the alist directly will lead to
-peculiar results.
+This is a method for figuring out what articles the user wants the
+command to be performed on.
 
-@cindex hilit19
-@cindex highlighting
-Old hilit19 code does not work at all.  In fact, you should probably
-remove all hilit code from all Gnus hooks
-(@code{gnus-group-prepare-hook} and @code{gnus-summary-prepare-hook}).
-Gnus provides various integrated functions for highlighting.  These are
-faster and more accurate.  To make life easier for everybody, Gnus will
-by default remove all hilit calls from all hilit hooks.  Uncleanliness!
-Away!
+It goes like this:
 
-Packages like @code{expire-kill} will no longer work.  As a matter of
-fact, you should probably remove all old @sc{gnus} packages (and other
-code) when you start using Gnus.  More likely than not, Gnus already
-does what you have written code to make @sc{gnus} do.  (Snicker.)
+If the numeric prefix is N, perform the operation on the next N
+articles, starting with the current one.  If the numeric prefix is
+negative, perform the operation on the previous N articles, starting
+with the current one.
 
-Even though old methods of doing things are still supported, only the
-new methods are documented in this manual.  If you detect a new method of
-doing something while reading this manual, that does not mean you have
-to stop doing it the old way.
+@vindex transient-mark-mode
+If @code{transient-mark-mode} in non-@code{nil} and the region is
+active, all articles in the region will be worked upon.
 
-Gnus understands all @sc{gnus} startup files.
+If there is no numeric prefix, but some articles are marked with the
+process mark, perform the operation on the articles marked with
+the process mark.
 
-@kindex M-x gnus-bug
-@findex gnus-bug
-@cindex reporting bugs
-@cindex bugs
-Overall, a casual user who hasn't written much code that depends on
-@sc{gnus} internals should suffer no problems.  If problems occur,
-please let me know by issuing that magic command @kbd{M-x gnus-bug}.
+If there is neither a numeric prefix nor any articles marked with the
+process mark, just perform the operation on the current article.
 
+Quite simple, really, but it needs to be made clear so that surprises
+are avoided.
 
-@node Conformity
-@subsection Conformity
+Commands that react to the process mark will push the current list of
+process marked articles onto a stack and will then clear all process
+marked articles.  You can restore the previous configuration with the
+@kbd{M P y} command (@pxref{Setting Process Marks}).
 
-No rebels without a clue here, ma'am.  We conform to all standards known
-to (wo)man.  Except for those standards and/or conventions we disagree
-with, of course.
+@vindex gnus-summary-goto-unread
+One thing that seems to shock & horrify lots of people is that, for
+instance, @kbd{3 d} does exactly the same as @kbd{d} @kbd{d} @kbd{d}.
+Since each @kbd{d} (which marks the current article as read) by default
+goes to the next unread article after marking, this means that @kbd{3 d}
+will mark the next three unread articles as read, no matter what the
+summary buffer looks like.  Set @code{gnus-summary-goto-unread} to
+@code{nil} for a more straightforward action.
 
-@table @strong
+Many commands do not use the process/prefix convention.  All commands
+that do explicitly say so in this manual.  To apply the process/prefix
+convention to commands that do not use it, you can use the @kbd{M-&}
+command.  For instance, to mark all the articles in the group as
+expirable, you could say @kbd{M P b M-& E}.
 
-@item RFC 822
-@cindex RFC 822
-There are no known breaches of this standard.
 
-@item RFC 1036
-@cindex RFC 1036
-There are no known breaches of this standard, either.
+@node Interactive
+@section Interactive
+@cindex interaction
 
-@item Son-of-RFC 1036
-@cindex Son-of-RFC 1036
-We do have some breaches to this one.
+@table @code
 
-@table @emph
+@item gnus-novice-user
+@vindex gnus-novice-user
+If this variable is non-@code{nil}, you are either a newcomer to the
+World of Usenet, or you are very cautious, which is a nice thing to be,
+really.  You will be given questions of the type ``Are you sure you want
+to do this?'' before doing anything dangerous.  This is @code{t} by
+default.
 
-@item MIME
-Gnus does no MIME handling, and this standard-to-be seems to think that
-MIME is the bees' knees, so we have major breakage here.
+@item gnus-expert-user
+@vindex gnus-expert-user
+If this variable is non-@code{nil}, you will seldom be asked any
+questions by Gnus.  It will simply assume you know what you're doing, no
+matter how strange.
 
-@item X-Newsreader
-This is considered to be a ``vanity header'', while I consider it to be
-consumer information.  After seeing so many badly formatted articles
-coming from @code{tin} and @code{Netscape} I know not to use either of
-those for posting articles.  I would not have known that if it wasn't
-for the @code{X-Newsreader} header.
-@end table
+@item gnus-interactive-catchup
+@vindex gnus-interactive-catchup
+Require confirmation before catching up a group if non-@code{nil}.  It
+is @code{t} by default.
 
+@item gnus-interactive-exit
+@vindex gnus-interactive-exit
+Require confirmation before exiting Gnus.  This variable is @code{t} by
+default.
 @end table
 
-If you ever notice Gnus acting non-compliant with regards to the texts
-mentioned above, don't hesitate to drop a note to Gnus Towers and let us
-know.
 
+@node Symbolic Prefixes
+@section Symbolic Prefixes
+@cindex symbolic prefixes
 
-@node Emacsen
-@subsection Emacsen
-@cindex Emacsen
-@cindex XEmacs
-@cindex Mule
-@cindex Emacs
+Quite a lot of Emacs commands react to the (numeric) prefix.  For
+instance, @kbd{C-u 4 C-f} moves point four characters forward, and
+@kbd{C-u 9 0 0 I s s p} adds a permanent @code{Subject} substring score
+rule of 900 to the current article.
 
-Gnus should work on :
+This is all nice and well, but what if you want to give a command some
+additional information?  Well, what most commands do is interpret the
+``raw'' prefix in some special way.  @kbd{C-u 0 C-x C-s} means that one
+doesn't want a backup file to be created when saving the current buffer,
+for instance.  But what if you want to save without making a backup
+file, and you want Emacs to flash lights and play a nice tune at the
+same time?  You can't, and you're probably perfectly happy that way.
 
-@itemize @bullet 
+@kindex M-i (Summary)
+@findex gnus-symbolic-argument
+I'm not, so I've added a second prefix---the @dfn{symbolic prefix}.  The
+prefix key is @kbd{M-i} (@code{gnus-symbolic-argument}), and the next
+character typed in is the value.  You can stack as many @kbd{M-i}
+prefixes as you want.  @kbd{M-i a C-M-u} means ``feed the @kbd{C-M-u}
+command the symbolic prefix @code{a}''.  @kbd{M-i a M-i b C-M-u} means
+``feed the @kbd{C-M-u} command the symbolic prefixes @code{a} and
+@code{b}''.  You get the drift.
 
-@item
-Emacs 19.32 and up.
+Typing in symbolic prefixes to commands that don't accept them doesn't
+hurt, but it doesn't do any good either.  Currently not many Gnus
+functions make use of the symbolic prefix.
 
-@item
-XEmacs 19.14 and up.
+If you're interested in how Gnus implements this, @pxref{Extended
+Interactive}.
 
-@item 
-Mule versions based on Emacs 19.32 and up.
 
-@end itemize
+@node Formatting Variables
+@section Formatting Variables
+@cindex formatting variables
 
-Gnus will absolutely not work on any Emacsen older than that.  Not
-reliably, at least. 
+Throughout this manual you've probably noticed lots of variables called
+things like @code{gnus-group-line-format} and
+@code{gnus-summary-mode-line-format}.  These control how Gnus is to
+output lines in the various buffers.  There's quite a lot of them.
+Fortunately, they all use the same syntax, so there's not that much to
+be annoyed by.
 
-There are some vague differences between Gnus on the various
-platforms---XEmacs features more graphics (a logo and a toolbar)---but
-other than that, things should look pretty much the same under all
-Emacsen. 
+Here's an example format spec (from the group buffer): @samp{%M%S%5y:
+%(%g%)\n}.  We see that it is indeed extremely ugly, and that there are
+lots of percentages everywhere.
 
+@menu
+* Formatting Basics::           A formatting variable is basically a format string.
+* Mode Line Formatting::        Some rules about mode line formatting variables.
+* Advanced Formatting::         Modifying output in various ways.
+* User-Defined Specs::          Having Gnus call your own functions.
+* Formatting Fonts::            Making the formatting look colorful and nice.
+* Positioning Point::           Moving point to a position after an operation.
+* Tabulation::                  Tabulating your output.
+* Wide Characters::             Dealing with wide characters.
+@end menu
 
-@node Contributors
-@subsection Contributors
-@cindex contributors
+Currently Gnus uses the following formatting variables:
+@code{gnus-group-line-format}, @code{gnus-summary-line-format},
+@code{gnus-server-line-format}, @code{gnus-topic-line-format},
+@code{gnus-group-mode-line-format},
+@code{gnus-summary-mode-line-format},
+@code{gnus-article-mode-line-format},
+@code{gnus-server-mode-line-format}, and
+@code{gnus-summary-pick-line-format}.
 
-The new Gnus version couldn't have been done without the help of all the
-people on the (ding) mailing list.  Every day for over a year I have
-gotten billions of nice bug reports from them, filling me with joy,
-every single one of them.  Smooches.  The people on the list have been
-tried beyond endurance, what with my ``oh, that's a neat idea <type
-type>, yup, I'll release it right away <ship off> no wait, that doesn't
-work at all <type type>, yup, I'll ship that one off right away <ship
-off> no, wait, that absolutely does not work'' policy for releases.
-Micro$oft---bah.  Amateurs.  I'm @emph{much} worse.  (Or is that
-``worser''? ``much worser''?  ``worsest''?)
+All these format variables can also be arbitrary elisp forms.  In that
+case, they will be @code{eval}ed to insert the required lines.
 
-I would like to take this opportunity to thank the Academy for...  oops,
-wrong show.
+@kindex M-x gnus-update-format
+@findex gnus-update-format
+Gnus includes a command to help you while creating your own format
+specs.  @kbd{M-x gnus-update-format} will @code{eval} the current form,
+update the spec in question and pop you to a buffer where you can
+examine the resulting Lisp code to be run to generate the line.
 
-@itemize @bullet
 
-@item 
-Masanobu @sc{Umeda}---the writer of the original @sc{gnus}.
 
-@item 
-Per Abrahamsen---custom, scoring, highlighting and @sc{soup} code (as
-well as numerous other things).
+@node Formatting Basics
+@subsection Formatting Basics
 
-@item 
-Luis Fernandes---design and graphics.
+Each @samp{%} element will be replaced by some string or other when the
+buffer in question is generated.  @samp{%5y} means ``insert the @samp{y}
+spec, and pad with spaces to get a 5-character field''.
 
-@item
-Erik Naggum---help, ideas, support, code and stuff.
+As with normal C and Emacs Lisp formatting strings, the numerical
+modifier between the @samp{%} and the formatting type character will
+@dfn{pad} the output so that it is always at least that long.
+@samp{%5y} will make the field always (at least) five characters wide by
+padding with spaces to the left.  If you say @samp{%-5y}, it will pad to
+the right instead.
 
-@item 
-Wes Hardaker---@file{gnus-picon.el} and the manual section on
-@dfn{picons} (@pxref{Picons}).
+You may also wish to limit the length of the field to protect against
+particularly wide values.  For that you can say @samp{%4,6y}, which
+means that the field will never be more than 6 characters wide and never
+less than 4 characters wide.
 
-@item
-Kim-Minh Kaplan---further work on the picon code.
+Also Gnus supports some extended format specifications, such as
+@samp{%&user-date;}.
 
-@item 
-Brad Miller---@file{gnus-gl.el} and the GroupLens manual section
-(@pxref{GroupLens}).
 
-@item 
-Sudish Joseph---innumerable bug fixes.
+@node Mode Line Formatting
+@subsection Mode Line Formatting
 
-@item 
-Ilja Weis---@file{gnus-topic.el}.
+Mode line formatting variables (e.g.,
+@code{gnus-summary-mode-line-format}) follow the same rules as other,
+buffer line oriented formatting variables (@pxref{Formatting Basics})
+with the following two differences:
 
-@item 
-Steven L. Baur---lots and lots and lots of bugs detections and fixes.
+@enumerate
 
-@item 
-Vladimir Alexiev---the refcard and reference booklets.
+@item
+There must be no newline (@samp{\n}) at the end.
 
-@item 
-Felix Lee & Jamie Zawinsky---I stole some pieces from the XGnus
-distribution by Felix Lee and JWZ.
+@item
+The special @samp{%%b} spec can be used to display the buffer name.
+Well, it's no spec at all, really---@samp{%%} is just a way to quote
+@samp{%} to allow it to pass through the formatting machinery unmangled,
+so that Emacs receives @samp{%b}, which is something the Emacs mode line
+display interprets to mean ``show the buffer name''.  For a full list of
+mode line specs Emacs understands, see the documentation of the
+@code{mode-line-format} variable.
 
-@item 
-Scott Byer---@file{nnfolder.el} enhancements & rewrite.
+@end enumerate
 
-@item 
-Peter Mutsaers---orphan article scoring code.
 
-@item 
-Ken Raeburn---POP mail support.
+@node Advanced Formatting
+@subsection Advanced Formatting
 
-@item 
-Hallvard B Furuseth---various bits and pieces, especially dealing with
-.newsrc files.
+It is frequently useful to post-process the fields in some way.
+Padding, limiting, cutting off parts and suppressing certain values can
+be achieved by using @dfn{tilde modifiers}.  A typical tilde spec might
+look like @samp{%~(cut 3)~(ignore "0")y}.
 
-@item 
-Brian Edmonds---@file{gnus-bbdb.el}.
+These are the valid modifiers:
+
+@table @code
+@item pad
+@itemx pad-left
+Pad the field to the left with spaces until it reaches the required
+length.
+
+@item pad-right
+Pad the field to the right with spaces until it reaches the required
+length.
+
+@item max
+@itemx max-left
+Cut off characters from the left until it reaches the specified length.
+
+@item max-right
+Cut off characters from the right until it reaches the specified
+length.
+
+@item cut
+@itemx cut-left
+Cut off the specified number of characters from the left.
+
+@item cut-right
+Cut off the specified number of characters from the right.
+
+@item ignore
+Return an empty string if the field is equal to the specified value.
+
+@item form
+Use the specified form as the field value when the @samp{@@} spec is
+used.
+
+Here's an example:
+
+@lisp
+"~(form (current-time-string))@@"
+@end lisp
+
+@end table
+
+Let's take an example.  The @samp{%o} spec in the summary mode lines
+will return a date in compact ISO8601 format---@samp{19960809T230410}.
+This is quite a mouthful, so we want to shave off the century number and
+the time, leaving us with a six-character date.  That would be
+@samp{%~(cut-left 2)~(max-right 6)~(pad 6)o}.  (Cutting is done before
+maxing, and we need the padding to ensure that the date is never less
+than 6 characters to make it look nice in columns.)
+
+Ignoring is done first; then cutting; then maxing; and then as the very
+last operation, padding.
+
+@vindex gnus-compile-user-specs
+If @code{gnus-compile-user-specs} is set to @code{nil} (@code{t} by
+default) with your strong personality, and use a lots of these advanced
+thingies, you'll find that Gnus gets quite slow.  This can be helped
+enormously by running @kbd{M-x gnus-compile} when you are satisfied with
+the look of your lines.
+@xref{Compilation}.
+
+
+@node User-Defined Specs
+@subsection User-Defined Specs
+
+All the specs allow for inserting user defined specifiers---@samp{u}.
+The next character in the format string should be a letter.  Gnus
+will call the function @code{gnus-user-format-function-}@samp{X}, where
+@samp{X} is the letter following @samp{%u}.  The function will be passed
+a single parameter---what the parameter means depends on what buffer
+it's being called from.  The function should return a string, which will
+be inserted into the buffer just like information from any other
+specifier.  This function may also be called with dummy values, so it
+should protect against that.
+
+Also Gnus supports extended user-defined specs, such as @samp{%u&foo;}.
+Gnus will call the function @code{gnus-user-format-function-}@samp{foo}.
+
+You can also use tilde modifiers (@pxref{Advanced Formatting} to achieve
+much the same without defining new functions.  Here's an example:
+@samp{%~(form (count-lines (point-min) (point)))@@}.  The form
+given here will be evaluated to yield the current line number, and then
+inserted.
+
+
+@node Formatting Fonts
+@subsection Formatting Fonts
+
+There are specs for highlighting, and these are shared by all the format
+variables.  Text inside the @samp{%(} and @samp{%)} specifiers will get
+the special @code{mouse-face} property set, which means that it will be
+highlighted (with @code{gnus-mouse-face}) when you put the mouse pointer
+over it.
+
+Text inside the @samp{%@{} and @samp{%@}} specifiers will have their
+normal faces set using @code{gnus-face-0}, which is @code{bold} by
+default.  If you say @samp{%1@{}, you'll get @code{gnus-face-1} instead,
+and so on.  Create as many faces as you wish.  The same goes for the
+@code{mouse-face} specs---you can say @samp{%3(hello%)} to have
+@samp{hello} mouse-highlighted with @code{gnus-mouse-face-3}.
+
+Text inside the @samp{%<<} and @samp{%>>} specifiers will get the
+special @code{balloon-help} property set to
+@code{gnus-balloon-face-0}.  If you say @samp{%1<<}, you'll get
+@code{gnus-balloon-face-1} and so on.  The @code{gnus-balloon-face-*}
+variables should be either strings or symbols naming functions that
+return a string.  When the mouse passes over text with this property
+set, a balloon window will appear and display the string.  Please
+refer to @ref{Tooltips, ,Tooltips, emacs, The Emacs Manual},
+(in GNU Emacs) or the doc string of @code{balloon-help-mode} (in
+XEmacs) for more information on this.  (For technical reasons, the
+guillemets have been approximated as @samp{<<} and @samp{>>} in this
+paragraph.)
+
+Here's an alternative recipe for the group buffer:
+
+@lisp
+;; @r{Create three face types.}
+(setq gnus-face-1 'bold)
+(setq gnus-face-3 'italic)
+
+;; @r{We want the article count to be in}
+;; @r{a bold and green face.  So we create}
+;; @r{a new face called @code{my-green-bold}.}
+(copy-face 'bold 'my-green-bold)
+;; @r{Set the color.}
+(set-face-foreground 'my-green-bold "ForestGreen")
+(setq gnus-face-2 'my-green-bold)
+
+;; @r{Set the new & fancy format.}
+(setq gnus-group-line-format
+      "%M%S%3@{%5y%@}%2[:%] %(%1@{%g%@}%)\n")
+@end lisp
+
+I'm sure you'll be able to use this scheme to create totally unreadable
+and extremely vulgar displays.  Have fun!
+
+Note that the @samp{%(} specs (and friends) do not make any sense on the
+mode-line variables.
+
+@node Positioning Point
+@subsection Positioning Point
+
+Gnus usually moves point to a pre-defined place on each line in most
+buffers.  By default, point move to the first colon character on the
+line.  You can customize this behaviour in three different ways.
+
+You can move the colon character to somewhere else on the line.
+
+@findex gnus-goto-colon
+You can redefine the function that moves the point to the colon.  The
+function is called @code{gnus-goto-colon}.
+
+But perhaps the most convenient way to deal with this, if you don't want
+to have a colon in your line, is to use the @samp{%*} specifier.  If you
+put a @samp{%*} somewhere in your format line definition, Gnus will
+place point there.
+
+
+@node Tabulation
+@subsection Tabulation
+
+You can usually line up your displays by padding and cutting your
+strings.  However, when combining various strings of different size, it
+can often be more convenient to just output the strings, and then worry
+about lining up the following text afterwards.
+
+To do that, Gnus supplies tabulator specs---@samp{%=}.  There are two
+different types---@dfn{hard tabulators} and @dfn{soft tabulators}.
+
+@samp{%50=} will insert space characters to pad the line up to column
+50.  If the text is already past column 50, nothing will be inserted.
+This is the soft tabulator.
+
+@samp{%-50=} will insert space characters to pad the line up to column
+50.  If the text is already past column 50, the excess text past column
+50 will be removed.  This is the hard tabulator.
+
+
+@node Wide Characters
+@subsection Wide Characters
+
+Fixed width fonts in most countries have characters of the same width.
+Some countries, however, use Latin characters mixed with wider
+characters---most notable East Asian countries.
+
+The problem is that when formatting, Gnus assumes that if a string is 10
+characters wide, it'll be 10 Latin characters wide on the screen.  In
+these countries, that's not true.
+
+@vindex gnus-use-correct-string-widths
+To help fix this, you can set @code{gnus-use-correct-string-widths} to
+@code{t}.  This makes buffer generation slower, but the results will be
+prettier.  The default value under XEmacs is @code{t} but @code{nil}
+for Emacs.
+
+
+@node Window Layout
+@section Window Layout
+@cindex window layout
+
+No, there's nothing here about X, so be quiet.
+
+@vindex gnus-use-full-window
+If @code{gnus-use-full-window} non-@code{nil}, Gnus will delete all
+other windows and occupy the entire Emacs screen by itself.  It is
+@code{t} by default.
+
+Setting this variable to @code{nil} kinda works, but there are
+glitches.  Use at your own peril.
+
+@vindex gnus-buffer-configuration
+@code{gnus-buffer-configuration} describes how much space each Gnus
+buffer should be given.  Here's an excerpt of this variable:
+
+@lisp
+((group (vertical 1.0 (group 1.0 point)
+                      (if gnus-carpal (group-carpal 4))))
+ (article (vertical 1.0 (summary 0.25 point)
+                        (article 1.0))))
+@end lisp
+
+This is an alist.  The @dfn{key} is a symbol that names some action or
+other.  For instance, when displaying the group buffer, the window
+configuration function will use @code{group} as the key.  A full list of
+possible names is listed below.
+
+The @dfn{value} (i.e., the @dfn{split}) says how much space each buffer
+should occupy.  To take the @code{article} split as an example -
+
+@lisp
+(article (vertical 1.0 (summary 0.25 point)
+                       (article 1.0)))
+@end lisp
+
+This @dfn{split} says that the summary buffer should occupy 25% of upper
+half of the screen, and that it is placed over the article buffer.  As
+you may have noticed, 100% + 25% is actually 125% (yup, I saw y'all
+reaching for that calculator there).  However, the special number
+@code{1.0} is used to signal that this buffer should soak up all the
+rest of the space available after the rest of the buffers have taken
+whatever they need.  There should be only one buffer with the @code{1.0}
+size spec per split.
+
+Point will be put in the buffer that has the optional third element
+@code{point}.  In a @code{frame} split, the last subsplit having a leaf
+split where the tag @code{frame-focus} is a member (i.e. is the third or
+fourth element in the list, depending on whether the @code{point} tag is
+present) gets focus.
+
+Here's a more complicated example:
+
+@lisp
+(article (vertical 1.0 (group 4)
+                       (summary 0.25 point)
+                       (if gnus-carpal (summary-carpal 4))
+                       (article 1.0)))
+@end lisp
+
+If the size spec is an integer instead of a floating point number,
+then that number will be used to say how many lines a buffer should
+occupy, not a percentage.
+
+If the @dfn{split} looks like something that can be @code{eval}ed (to be
+precise---if the @code{car} of the split is a function or a subr), this
+split will be @code{eval}ed.  If the result is non-@code{nil}, it will
+be used as a split.  This means that there will be three buffers if
+@code{gnus-carpal} is @code{nil}, and four buffers if @code{gnus-carpal}
+is non-@code{nil}.
+
+Not complicated enough for you?  Well, try this on for size:
+
+@lisp
+(article (horizontal 1.0
+             (vertical 0.5
+                 (group 1.0)
+                 (gnus-carpal 4))
+             (vertical 1.0
+                 (summary 0.25 point)
+                 (summary-carpal 4)
+                 (article 1.0))))
+@end lisp
+
+Whoops.  Two buffers with the mystery 100% tag.  And what's that
+@code{horizontal} thingie?
+
+If the first element in one of the split is @code{horizontal}, Gnus will
+split the window horizontally, giving you two windows side-by-side.
+Inside each of these strips you may carry on all you like in the normal
+fashion.  The number following @code{horizontal} says what percentage of
+the screen is to be given to this strip.
+
+For each split, there @emph{must} be one element that has the 100% tag.
+The splitting is never accurate, and this buffer will eat any leftover
+lines from the splits.
+
+To be slightly more formal, here's a definition of what a valid split
+may look like:
+
+@example
+@group
+split      = frame | horizontal | vertical | buffer | form
+frame      = "(frame " size *split ")"
+horizontal = "(horizontal " size *split ")"
+vertical   = "(vertical " size *split ")"
+buffer     = "(" buf-name " " size *[ "point" ] *[ "frame-focus"] ")"
+size       = number | frame-params
+buf-name   = group | article | summary ...
+@end group
+@end example
+
+The limitations are that the @code{frame} split can only appear as the
+top-level split.  @var{form} should be an Emacs Lisp form that should
+return a valid split.  We see that each split is fully recursive, and
+may contain any number of @code{vertical} and @code{horizontal} splits.
+
+@vindex gnus-window-min-width
+@vindex gnus-window-min-height
+@cindex window height
+@cindex window width
+Finding the right sizes can be a bit complicated.  No window may be less
+than @code{gnus-window-min-height} (default 1) characters high, and all
+windows must be at least @code{gnus-window-min-width} (default 1)
+characters wide.  Gnus will try to enforce this before applying the
+splits.  If you want to use the normal Emacs window width/height limit,
+you can just set these two variables to @code{nil}.
+
+If you're not familiar with Emacs terminology, @code{horizontal} and
+@code{vertical} splits may work the opposite way of what you'd expect.
+Windows inside a @code{horizontal} split are shown side-by-side, and
+windows within a @code{vertical} split are shown above each other.
+
+@findex gnus-configure-frame
+If you want to experiment with window placement, a good tip is to call
+@code{gnus-configure-frame} directly with a split.  This is the function
+that does all the real work when splitting buffers.  Below is a pretty
+nonsensical configuration with 5 windows; two for the group buffer and
+three for the article buffer.  (I said it was nonsensical.)  If you
+@code{eval} the statement below, you can get an idea of how that would
+look straight away, without going through the normal Gnus channels.
+Play with it until you're satisfied, and then use
+@code{gnus-add-configuration} to add your new creation to the buffer
+configuration list.
+
+@lisp
+(gnus-configure-frame
+ '(horizontal 1.0
+    (vertical 10
+      (group 1.0)
+      (article 0.3 point))
+    (vertical 1.0
+      (article 1.0)
+      (horizontal 4
+        (group 1.0)
+        (article 10)))))
+@end lisp
+
+You might want to have several frames as well.  No prob---just use the
+@code{frame} split:
+
+@lisp
+(gnus-configure-frame
+ '(frame 1.0
+         (vertical 1.0
+                   (summary 0.25 point frame-focus)
+                   (article 1.0))
+         (vertical ((height . 5) (width . 15)
+                    (user-position . t)
+                    (left . -1) (top . 1))
+                   (picon 1.0))))
+
+@end lisp
+
+This split will result in the familiar summary/article window
+configuration in the first (or ``main'') frame, while a small additional
+frame will be created where picons will be shown.  As you can see,
+instead of the normal @code{1.0} top-level spec, each additional split
+should have a frame parameter alist as the size spec.
+@xref{Frame Parameters, , Frame Parameters, elisp, The GNU Emacs Lisp
+Reference Manual}.  Under XEmacs, a frame property list will be
+accepted, too---for instance, @code{(height 5 width 15 left -1 top 1)}
+is such a plist.
+The list of all possible keys for @code{gnus-buffer-configuration} can
+be found in its default value.
+
+Note that the @code{message} key is used for both
+@code{gnus-group-mail} and @code{gnus-summary-mail-other-window}.  If
+it is desirable to distinguish between the two, something like this
+might be used:
+
+@lisp
+(message (horizontal 1.0
+                     (vertical 1.0 (message 1.0 point))
+                     (vertical 0.24
+                               (if (buffer-live-p gnus-summary-buffer)
+                                   '(summary 0.5))
+                               (group 1.0))))
+@end lisp
+
+One common desire for a multiple frame split is to have a separate frame
+for composing mail and news while leaving the original frame intact.  To
+accomplish that, something like the following can be done:
+
+@lisp
+(message
+  (frame 1.0
+         (if (not (buffer-live-p gnus-summary-buffer))
+             (car (cdr (assoc 'group gnus-buffer-configuration)))
+           (car (cdr (assoc 'summary gnus-buffer-configuration))))
+         (vertical ((user-position . t) (top . 1) (left . 1)
+                    (name . "Message"))
+                   (message 1.0 point))))
+@end lisp
+
+@findex gnus-add-configuration
+Since the @code{gnus-buffer-configuration} variable is so long and
+complicated, there's a function you can use to ease changing the config
+of a single setting: @code{gnus-add-configuration}.  If, for instance,
+you want to change the @code{article} setting, you could say:
+
+@lisp
+(gnus-add-configuration
+ '(article (vertical 1.0
+               (group 4)
+               (summary .25 point)
+               (article 1.0))))
+@end lisp
+
+You'd typically stick these @code{gnus-add-configuration} calls in your
+@file{~/.gnus.el} file or in some startup hook---they should be run after
+Gnus has been loaded.
+
+@vindex gnus-always-force-window-configuration
+If all windows mentioned in the configuration are already visible, Gnus
+won't change the window configuration.  If you always want to force the
+``right'' window configuration, you can set
+@code{gnus-always-force-window-configuration} to non-@code{nil}.
+
+If you're using tree displays (@pxref{Tree Display}), and the tree
+window is displayed vertically next to another window, you may also want
+to fiddle with @code{gnus-tree-minimize-window} to avoid having the
+windows resized.
+
+@subsection Example Window Configurations
+
+@itemize @bullet
+@item
+Narrow left hand side occupied by group buffer.  Right hand side split
+between summary buffer (top one-sixth) and article buffer (bottom).
+
+@ifinfo
+@example
++---+---------+
+| G | Summary |
+| r +---------+
+| o |         |
+| u | Article |
+| p |         |
++---+---------+
+@end example
+@end ifinfo
+
+@lisp
+(gnus-add-configuration
+ '(article
+   (horizontal 1.0
+               (vertical 25 (group 1.0))
+               (vertical 1.0
+                         (summary 0.16 point)
+                         (article 1.0)))))
+
+(gnus-add-configuration
+ '(summary
+   (horizontal 1.0
+               (vertical 25 (group 1.0))
+               (vertical 1.0 (summary 1.0 point)))))
+@end lisp
+
+@end itemize
+
+
+@node Faces and Fonts
+@section Faces and Fonts
+@cindex faces
+@cindex fonts
+@cindex colors
+
+Fiddling with fonts and faces used to be very difficult, but these days
+it is very simple.  You simply say @kbd{M-x customize-face}, pick out
+the face you want to alter, and alter it via the standard Customize
+interface.
+
+
+@node Compilation
+@section Compilation
+@cindex compilation
+@cindex byte-compilation
+
+@findex gnus-compile
+
+Remember all those line format specification variables?
+@code{gnus-summary-line-format}, @code{gnus-group-line-format}, and so
+on.  By default, T-gnus will use the byte-compiled codes of these
+variables and we can keep a slow-down to a minimum.  However, if you set
+@code{gnus-compile-user-specs} to @code{nil} (@code{t} by default),
+unfortunately, changing them will mean a quite significant slow-down.
+(The default values of these variables have byte-compiled functions
+associated with them, while the user-generated versions do not, of
+course.)
+
+To help with this, you can run @kbd{M-x gnus-compile} after you've
+fiddled around with the variables and feel that you're (kind of)
+satisfied.  This will result in the new specs being byte-compiled, and
+you'll get top speed again.  Note that T-gnus will not save these
+compiled specs in the @file{.newsrc.eld} file.
+
+@table @code
+@item gnus-compile-user-specs
+@vindex gnus-compile-user-specs
+If it is non-nil, the user-defined format specs will be byte-compiled
+automatically.  The default value of this variable is @code{t}.  It has
+an effect on the values of @code{gnus-*-line-format-spec}.
+@end table
+
+
+@node Mode Lines
+@section Mode Lines
+@cindex mode lines
+
+@vindex gnus-updated-mode-lines
+@code{gnus-updated-mode-lines} says what buffers should keep their mode
+lines updated.  It is a list of symbols.  Supported symbols include
+@code{group}, @code{article}, @code{summary}, @code{server},
+@code{browse}, and @code{tree}.  If the corresponding symbol is present,
+Gnus will keep that mode line updated with information that may be
+pertinent.  If this variable is @code{nil}, screen refresh may be
+quicker.
+
+@cindex display-time
+
+@vindex gnus-mode-non-string-length
+By default, Gnus displays information on the current article in the mode
+lines of the summary and article buffers.  The information Gnus wishes
+to display (e.g. the subject of the article) is often longer than the
+mode lines, and therefore have to be cut off at some point.  The
+@code{gnus-mode-non-string-length} variable says how long the other
+elements on the line is (i.e., the non-info part).  If you put
+additional elements on the mode line (e.g. a clock), you should modify
+this variable:
+
+@c Hook written by Francesco Potorti` <pot@cnuce.cnr.it>
+@lisp
+(add-hook 'display-time-hook
+          (lambda () (setq gnus-mode-non-string-length
+                           (+ 21
+                              (if line-number-mode 5 0)
+                              (if column-number-mode 4 0)
+                              (length display-time-string)))))
+@end lisp
+
+If this variable is @code{nil} (which is the default), the mode line
+strings won't be chopped off, and they won't be padded either.  Note
+that the default is unlikely to be desirable, as even the percentage
+complete in the buffer may be crowded off the mode line; the user should
+configure this variable appropriately for her configuration.
+
+
+@node Highlighting and Menus
+@section Highlighting and Menus
+@cindex visual
+@cindex highlighting
+@cindex menus
+
+@vindex gnus-visual
+The @code{gnus-visual} variable controls most of the Gnus-prettifying
+aspects.  If @code{nil}, Gnus won't attempt to create menus or use fancy
+colors or fonts.  This will also inhibit loading the @file{gnus-vis.el}
+file.
+
+This variable can be a list of visual properties that are enabled.  The
+following elements are valid, and are all included by default:
+
+@table @code
+@item group-highlight
+Do highlights in the group buffer.
+@item summary-highlight
+Do highlights in the summary buffer.
+@item article-highlight
+Do highlights in the article buffer.
+@item highlight
+Turn on highlighting in all buffers.
+@item group-menu
+Create menus in the group buffer.
+@item summary-menu
+Create menus in the summary buffers.
+@item article-menu
+Create menus in the article buffer.
+@item browse-menu
+Create menus in the browse buffer.
+@item server-menu
+Create menus in the server buffer.
+@item score-menu
+Create menus in the score buffers.
+@item menu
+Create menus in all buffers.
+@end table
+
+So if you only want highlighting in the article buffer and menus in all
+buffers, you could say something like:
+
+@lisp
+(setq gnus-visual '(article-highlight menu))
+@end lisp
+
+If you want highlighting only and no menus whatsoever, you'd say:
+
+@lisp
+(setq gnus-visual '(highlight))
+@end lisp
+
+If @code{gnus-visual} is @code{t}, highlighting and menus will be used
+in all Gnus buffers.
+
+Other general variables that influence the look of all buffers include:
+
+@table @code
+@item gnus-mouse-face
+@vindex gnus-mouse-face
+This is the face (i.e., font) used for mouse highlighting in Gnus.  No
+mouse highlights will be done if @code{gnus-visual} is @code{nil}.
+
+@end table
+
+There are hooks associated with the creation of all the different menus:
+
+@table @code
+
+@item gnus-article-menu-hook
+@vindex gnus-article-menu-hook
+Hook called after creating the article mode menu.
+
+@item gnus-group-menu-hook
+@vindex gnus-group-menu-hook
+Hook called after creating the group mode menu.
+
+@item gnus-summary-menu-hook
+@vindex gnus-summary-menu-hook
+Hook called after creating the summary mode menu.
+
+@item gnus-server-menu-hook
+@vindex gnus-server-menu-hook
+Hook called after creating the server mode menu.
+
+@item gnus-browse-menu-hook
+@vindex gnus-browse-menu-hook
+Hook called after creating the browse mode menu.
+
+@item gnus-score-menu-hook
+@vindex gnus-score-menu-hook
+Hook called after creating the score mode menu.
+
+@end table
+
+
+@node Buttons
+@section Buttons
+@cindex buttons
+@cindex mouse
+@cindex click
+
+Those new-fangled @dfn{mouse} contraptions is very popular with the
+young, hep kids who don't want to learn the proper way to do things
+these days.  Why, I remember way back in the summer of '89, when I was
+using Emacs on a Tops 20 system.  Three hundred users on one single
+machine, and every user was running Simula compilers.  Bah!
+
+Right.
+
+@vindex gnus-carpal
+Well, you can make Gnus display bufferfuls of buttons you can click to
+do anything by setting @code{gnus-carpal} to @code{t}.  Pretty simple,
+really.  Tell the chiropractor I sent you.
+
+
+@table @code
+
+@item gnus-carpal-mode-hook
+@vindex gnus-carpal-mode-hook
+Hook run in all carpal mode buffers.
+
+@item gnus-carpal-button-face
+@vindex gnus-carpal-button-face
+Face used on buttons.
+
+@item gnus-carpal-header-face
+@vindex gnus-carpal-header-face
+Face used on carpal buffer headers.
+
+@item gnus-carpal-group-buffer-buttons
+@vindex gnus-carpal-group-buffer-buttons
+Buttons in the group buffer.
+
+@item gnus-carpal-summary-buffer-buttons
+@vindex gnus-carpal-summary-buffer-buttons
+Buttons in the summary buffer.
+
+@item gnus-carpal-server-buffer-buttons
+@vindex gnus-carpal-server-buffer-buttons
+Buttons in the server buffer.
+
+@item gnus-carpal-browse-buffer-buttons
+@vindex gnus-carpal-browse-buffer-buttons
+Buttons in the browse buffer.
+@end table
+
+All the @code{buttons} variables are lists.  The elements in these list
+are either cons cells where the @code{car} contains a text to be displayed and
+the @code{cdr} contains a function symbol, or a simple string.
+
+
+@node Daemons
+@section Daemons
+@cindex demons
+@cindex daemons
+
+Gnus, being larger than any program ever written (allegedly), does lots
+of strange stuff that you may wish to have done while you're not
+present.  For instance, you may want it to check for new mail once in a
+while.  Or you may want it to close down all connections to all servers
+when you leave Emacs idle.  And stuff like that.
+
+Gnus will let you do stuff like that by defining various
+@dfn{handlers}.  Each handler consists of three elements:  A
+@var{function}, a @var{time}, and an @var{idle} parameter.
+
+Here's an example of a handler that closes connections when Emacs has
+been idle for thirty minutes:
+
+@lisp
+(gnus-demon-close-connections nil 30)
+@end lisp
+
+Here's a handler that scans for @acronym{PGP} headers every hour when
+Emacs is idle:
+
+@lisp
+(gnus-demon-scan-pgp 60 t)
+@end lisp
+
+This @var{time} parameter and that @var{idle} parameter work together
+in a strange, but wonderful fashion.  Basically, if @var{idle} is
+@code{nil}, then the function will be called every @var{time} minutes.
+
+If @var{idle} is @code{t}, then the function will be called after
+@var{time} minutes only if Emacs is idle.  So if Emacs is never idle,
+the function will never be called.  But once Emacs goes idle, the
+function will be called every @var{time} minutes.
+
+If @var{idle} is a number and @var{time} is a number, the function will
+be called every @var{time} minutes only when Emacs has been idle for
+@var{idle} minutes.
+
+If @var{idle} is a number and @var{time} is @code{nil}, the function
+will be called once every time Emacs has been idle for @var{idle}
+minutes.
+
+And if @var{time} is a string, it should look like @samp{07:31}, and
+the function will then be called once every day somewhere near that
+time.  Modified by the @var{idle} parameter, of course.
+
+@vindex gnus-demon-timestep
+(When I say ``minute'' here, I really mean @code{gnus-demon-timestep}
+seconds.  This is 60 by default.  If you change that variable,
+all the timings in the handlers will be affected.)
+
+So, if you want to add a handler, you could put something like this in
+your @file{~/.gnus.el} file:
+
+@findex gnus-demon-add-handler
+@lisp
+(gnus-demon-add-handler 'gnus-demon-close-connections 30 t)
+@end lisp
+
+@findex gnus-demon-add-nocem
+@findex gnus-demon-add-scanmail
+@findex gnus-demon-add-rescan
+@findex gnus-demon-add-scan-timestamps
+@findex gnus-demon-add-disconnection
+Some ready-made functions to do this have been created:
+@code{gnus-demon-add-nocem}, @code{gnus-demon-add-disconnection},
+@code{gnus-demon-add-nntp-close-connection},
+@code{gnus-demon-add-scan-timestamps}, @code{gnus-demon-add-rescan}, and
+@code{gnus-demon-add-scanmail}.  Just put those functions in your
+@file{~/.gnus.el} if you want those abilities.
+
+@findex gnus-demon-init
+@findex gnus-demon-cancel
+@vindex gnus-demon-handlers
+If you add handlers to @code{gnus-demon-handlers} directly, you should
+run @code{gnus-demon-init} to make the changes take hold.  To cancel all
+daemons, you can use the @code{gnus-demon-cancel} function.
+
+Note that adding daemons can be pretty naughty if you over do it.  Adding
+functions that scan all news and mail from all servers every two seconds
+is a sure-fire way of getting booted off any respectable system.  So
+behave.
+
+
+@node NoCeM
+@section NoCeM
+@cindex nocem
+@cindex spam
+
+@dfn{Spamming} is posting the same article lots and lots of times.
+Spamming is bad.  Spamming is evil.
+
+Spamming is usually canceled within a day or so by various anti-spamming
+agencies.  These agencies usually also send out @dfn{NoCeM} messages.
+NoCeM is pronounced ``no see-'em'', and means what the name
+implies---these are messages that make the offending articles, like, go
+away.
+
+What use are these NoCeM messages if the articles are canceled anyway?
+Some sites do not honor cancel messages and some sites just honor cancels
+from a select few people.  Then you may wish to make use of the NoCeM
+messages, which are distributed in the @samp{alt.nocem.misc} newsgroup.
+
+Gnus can read and parse the messages in this group automatically, and
+this will make spam disappear.
+
+There are some variables to customize, of course:
+
+@table @code
+@item gnus-use-nocem
+@vindex gnus-use-nocem
+Set this variable to @code{t} to set the ball rolling.  It is @code{nil}
+by default.
+
+@item gnus-nocem-groups
+@vindex gnus-nocem-groups
+Gnus will look for NoCeM messages in the groups in this list.  The
+default is
+@lisp
+("news.lists.filters" "news.admin.net-abuse.bulletins"
+ "alt.nocem.misc" "news.admin.net-abuse.announce")
+@end lisp
+
+@item gnus-nocem-issuers
+@vindex gnus-nocem-issuers
+There are many people issuing NoCeM messages.  This list says what
+people you want to listen to.  The default is
+@lisp
+("Automoose-1" "clewis@@ferret.ocunix.on.ca"
+ "cosmo.roadkill" "SpamHippo" "hweede@@snafu.de")
+@end lisp
+fine, upstanding citizens all of them.
+
+Known despammers that you can put in this list are listed at@*
+@uref{http://www.xs4all.nl/~rosalind/nocemreg/nocemreg.html}.
+
+You do not have to heed NoCeM messages from all these people---just the
+ones you want to listen to.  You also don't have to accept all NoCeM
+messages from the people you like.  Each NoCeM message has a @dfn{type}
+header that gives the message a (more or less, usually less) rigorous
+definition.  Common types are @samp{spam}, @samp{spew}, @samp{mmf},
+@samp{binary}, and @samp{troll}.  To specify this, you have to use
+@code{(@var{issuer} @var{conditions} @dots{})} elements in the list.
+Each condition is either a string (which is a regexp that matches types
+you want to use) or a list on the form @code{(not @var{string})}, where
+@var{string} is a regexp that matches types you don't want to use.
+
+For instance, if you want all NoCeM messages from Chris Lewis except his
+@samp{troll} messages, you'd say:
+
+@lisp
+("clewis@@ferret.ocunix.on.ca" ".*" (not "troll"))
+@end lisp
+
+On the other hand, if you just want nothing but his @samp{spam} and
+@samp{spew} messages, you'd say:
+
+@lisp
+("clewis@@ferret.ocunix.on.ca" (not ".*") "spew" "spam")
+@end lisp
+
+The specs are applied left-to-right.
+
+
+@item gnus-nocem-verifyer
+@vindex gnus-nocem-verifyer
+@findex mc-verify
+This should be a function for verifying that the NoCeM issuer is who she
+says she is.  The default is @code{mc-verify}, which is a Mailcrypt
+function.  If this is too slow and you don't care for verification
+(which may be dangerous), you can set this variable to @code{nil}.
+
+If you want signed NoCeM messages to be verified and unsigned messages
+not to be verified (but used anyway), you could do something like:
+
+@lisp
+(setq gnus-nocem-verifyer 'my-gnus-mc-verify)
+
+(defun my-gnus-mc-verify ()
+  (not (eq 'forged
+           (ignore-errors
+             (if (mc-verify)
+                 t
+               'forged)))))
+@end lisp
+
+This might be dangerous, though.
+
+@item gnus-nocem-directory
+@vindex gnus-nocem-directory
+This is where Gnus will store its NoCeM cache files.  The default is@*
+@file{~/News/NoCeM/}.
+
+@item gnus-nocem-expiry-wait
+@vindex gnus-nocem-expiry-wait
+The number of days before removing old NoCeM entries from the cache.
+The default is 15.  If you make it shorter Gnus will be faster, but you
+might then see old spam.
+
+@item gnus-nocem-check-from
+@vindex gnus-nocem-check-from
+Non-@code{nil} means check for valid issuers in message bodies.
+Otherwise don't bother fetching articles unless their author matches a
+valid issuer; that is much faster if you are selective about the
+issuers.
+
+@item gnus-nocem-check-article-limit
+@vindex gnus-nocem-check-article-limit
+If non-@code{nil}, the maximum number of articles to check in any NoCeM
+group.  NoCeM groups can be huge and very slow to process.
+
+@end table
+
+Using NoCeM could potentially be a memory hog.  If you have many living
+(i. e., subscribed or unsubscribed groups), your Emacs process will grow
+big.  If this is a problem, you should kill off all (or most) of your
+unsubscribed groups (@pxref{Subscription Commands}).
+
+
+@node Undo
+@section Undo
+@cindex undo
+
+It is very useful to be able to undo actions one has done.  In normal
+Emacs buffers, it's easy enough---you just push the @code{undo} button.
+In Gnus buffers, however, it isn't that simple.
+
+The things Gnus displays in its buffer is of no value whatsoever to
+Gnus---it's all just data designed to look nice to the user.
+Killing a group in the group buffer with @kbd{C-k} makes the line
+disappear, but that's just a side-effect of the real action---the
+removal of the group in question from the internal Gnus structures.
+Undoing something like that can't be done by the normal Emacs
+@code{undo} function.
+
+Gnus tries to remedy this somewhat by keeping track of what the user
+does and coming up with actions that would reverse the actions the user
+takes.  When the user then presses the @code{undo} key, Gnus will run
+the code to reverse the previous action, or the previous actions.
+However, not all actions are easily reversible, so Gnus currently offers
+a few key functions to be undoable.  These include killing groups,
+yanking groups, and changing the list of read articles of groups.
+That's it, really.  More functions may be added in the future, but each
+added function means an increase in data to be stored, so Gnus will
+never be totally undoable.
+
+@findex gnus-undo-mode
+@vindex gnus-use-undo
+@findex gnus-undo
+The undoability is provided by the @code{gnus-undo-mode} minor mode.  It
+is used if @code{gnus-use-undo} is non-@code{nil}, which is the
+default.  The @kbd{C-M-_} key performs the @code{gnus-undo}
+command, which should feel kinda like the normal Emacs @code{undo}
+command.
+
+
+@node Predicate Specifiers
+@section Predicate Specifiers
+@cindex predicate specifiers
+
+Some Gnus variables are @dfn{predicate specifiers}.  This is a special
+form that allows flexible specification of predicates without having
+to type all that much.
+
+These specifiers are lists consisting of functions, symbols and lists.
+
+Here's an example:
+
+@lisp
+(or gnus-article-unseen-p
+    gnus-article-unread-p)
+@end lisp
+
+The available symbols are @code{or}, @code{and} and @code{not}.  The
+functions all take one parameter.
+
+@findex gnus-make-predicate
+Internally, Gnus calls @code{gnus-make-predicate} on these specifiers
+to create a function that can be called.  This input parameter to this
+function will be passed along to all the functions in the predicate
+specifier.
+
+
+@node Moderation
+@section Moderation
+@cindex moderation
+
+If you are a moderator, you can use the @file{gnus-mdrtn.el} package.
+It is not included in the standard Gnus package.  Write a mail to
+@samp{larsi@@gnus.org} and state what group you moderate, and you'll
+get a copy.
+
+The moderation package is implemented as a minor mode for summary
+buffers.  Put
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'gnus-moderate)
+@end lisp
+
+in your @file{~/.gnus.el} file.
+
+If you are the moderator of @samp{rec.zoofle}, this is how it's
+supposed to work:
+
+@enumerate
+@item
+You split your incoming mail by matching on
+@samp{Newsgroups:.*rec.zoofle}, which will put all the to-be-posted
+articles in some mail group---for instance, @samp{nnml:rec.zoofle}.
+
+@item
+You enter that group once in a while and post articles using the @kbd{e}
+(edit-and-post) or @kbd{s} (just send unedited) commands.
+
+@item
+If, while reading the @samp{rec.zoofle} newsgroup, you happen upon some
+articles that weren't approved by you, you can cancel them with the
+@kbd{c} command.
+@end enumerate
+
+To use moderation mode in these two groups, say:
+
+@lisp
+(setq gnus-moderated-list
+      "^nnml:rec.zoofle$\\|^rec.zoofle$")
+@end lisp
+
+
+@node Image Enhancements
+@section Image Enhancements
+
+XEmacs, as well as Emacs 21@footnote{Emacs 21 on MS Windows doesn't
+support images yet.}, is able to display pictures and stuff, so Gnus has
+taken advantage of that.
+
+@menu
+* X-Face::                      Display a funky, teensy black-and-white image.
+* Face::                        Display a funkier, teensier colored image.
+* Smileys::                     Show all those happy faces the way they were meant to be shown.
+* Picons::                      How to display pictures of what you're reading.
+* XVarious::                    Other XEmacsy Gnusey variables.
+@end menu
+
+
+@node X-Face
+@subsection X-Face
+@cindex x-face
+
+@code{X-Face} headers describe a 48x48 pixel black-and-white (1 bit
+depth) image that's supposed to represent the author of the message.
+It seems to be supported by an ever-growing number of mail and news
+readers.
+
+@cindex x-face
+@findex gnus-article-display-x-face
+@vindex gnus-article-x-face-command
+@vindex gnus-article-x-face-too-ugly
+@iftex
+@iflatex
+\include{xface}
+@end iflatex
+@end iftex
+@c @anchor{X-Face}
+
+Decoding an @code{X-Face} header either requires an Emacs that has
+@samp{compface} support (which most XEmacs versions has), or that you
+have @samp{compface} installed on your system.  If either is true,
+Gnus will default to displaying @code{X-Face} headers.
+
+The variable that controls this is the
+@code{gnus-article-x-face-command} variable.  If this variable is a
+string, this string will be executed in a sub-shell.  If it is a
+function, this function will be called with the face as the argument.
+If the @code{gnus-article-x-face-too-ugly} (which is a regexp) matches
+the @code{From} header, the face will not be shown.
+
+The default action under Emacs 20 is to fork off the @code{display}
+program@footnote{@code{display} is from the ImageMagick package.  For
+the @code{uncompface} and @code{icontopbm} programs look for a package
+like @code{compface} or @code{faces-xface} on a GNU/Linux system.}  to
+view the face.
+
+Under XEmacs or Emacs 21+ with suitable image support, the default
+action is to display the face before the @code{From} header.  (It's
+nicer if XEmacs has been compiled with @code{X-Face} support---that
+will make display somewhat faster.  If there's no native @code{X-Face}
+support, Gnus will try to convert the @code{X-Face} header using
+external programs from the @code{pbmplus} package and
+friends.@footnote{On a GNU/Linux system look for packages with names
+like @code{netpbm}, @code{libgr-progs} and @code{compface}.})
+
+(Note: @code{x-face} is used in the variable/function names, not
+@code{xface}).
+
+Gnus provides a few convenience functions and variables to allow
+easier insertion of X-Face headers in outgoing messages.
+
+@findex gnus-random-x-face
+@vindex gnus-convert-pbm-to-x-face-command
+@vindex gnus-x-face-directory
+@code{gnus-random-x-face} goes through all the @samp{pbm} files in
+@code{gnus-x-face-directory} and picks one at random, and then
+converts it to the X-Face format by using the
+@code{gnus-convert-pbm-to-x-face-command} shell command.  The
+@samp{pbm} files should be 48x48 pixels big.  It returns the X-Face
+header data as a string.
+
+@findex gnus-insert-random-x-face-header
+@code{gnus-insert-random-x-face-header} calls
+@code{gnus-random-x-face} and inserts a @samp{X-Face} header with the
+randomly generated data.
+
+@findex gnus-x-face-from-file
+@vindex gnus-convert-image-to-x-face-command
+@code{gnus-x-face-from-file} takes a GIF file as the parameter, and then
+converts the file to X-Face format by using the
+@code{gnus-convert-image-to-x-face-command} shell command.
+
+Here's how you would typically use the first function.  Put something
+like the following in your @file{~/.gnus.el} file:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(X-Face . gnus-random-x-face))))
+@end lisp
+
+Using the last function would be something like this:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(X-Face . (lambda ()
+                                (gnus-x-face-from-file
+                                 "~/My-face.gif"))))))
+@end lisp
+
+
+@node Face
+@subsection Face
+@cindex face
+
+@c #### FIXME: faces and x-faces'implementations should really be harmonized.
+
+@code{Face} headers are essentially a funkier version of @code{X-Face}
+ones. They describe a 48x48 pixel colored image that's supposed to
+represent the author of the message.
+
+@cindex face
+@findex gnus-article-display-face
+The contents of a @code{Face} header must be a base64 encoded PNG image.
+See @uref{http://quimby.gnus.org/circus/face/} for the precise
+specifications.
+
+Gnus provides a few convenience functions and variables to allow
+easier insertion of Face headers in outgoing messages.
+
+@findex gnus-convert-png-to-face
+@code{gnus-convert-png-to-face} takes a 48x48 PNG image, no longer than
+726 bytes long, and converts it to a face.
+
+@findex gnus-face-from-file
+@vindex gnus-convert-image-to-face-command
+@code{gnus-face-from-file} takes a JPEG file as the parameter, and then
+converts the file to Face format by using the
+@code{gnus-convert-image-to-face-command} shell command.
+
+Here's how you would typically use this function. Put something like the
+following in your @file{~/.gnus.el} file:
+
+@lisp
+(setq message-required-news-headers
+      (nconc message-required-news-headers
+             (list '(Face . (lambda ()
+                              (gnus-face-from-file "~/face.jpg"))))))
+@end lisp
+
+
+@node Smileys
+@subsection Smileys
+@cindex smileys
+
+@iftex
+@iflatex
+\gnusfig{-3cm}{0.5cm}{\epsfig{figure=ps/BigFace,height=20cm}}
+\input{smiley}
+@end iflatex
+@end iftex
+
+@dfn{Smiley} is a package separate from Gnus, but since Gnus is
+currently the only package that uses Smiley, it is documented here.
+
+In short---to use Smiley in Gnus, put the following in your
+@file{~/.gnus.el} file:
+
+@lisp
+(setq gnus-treat-display-smileys t)
+@end lisp
+
+Smiley maps text smiley faces---@samp{:-)}, @samp{8-)}, @samp{:-(} and
+the like---to pictures and displays those instead of the text smiley
+faces.  The conversion is controlled by a list of regexps that matches
+text and maps that to file names.
+
+@vindex smiley-regexp-alist
+The alist used is specified by the @code{smiley-regexp-alist}
+variable.  The first item in each element is the regexp to be matched;
+the second element is the regexp match group that is to be replaced by
+the picture; and the third element is the name of the file to be
+displayed.
+
+The following variables customize where Smiley will look for these
+files:
+
+@table @code
+
+@item smiley-data-directory
+@vindex smiley-data-directory
+Where Smiley will look for smiley faces files.
+
+@item gnus-smiley-file-types
+@vindex gnus-smiley-file-types
+List of suffixes on smiley file names to try.
+
+@end table
+
+
+@node Picons
+@subsection Picons
+
+@iftex
+@iflatex
+\include{picons}
+@end iflatex
+@end iftex
+
+So@dots{}  You want to slow down your news reader even more!  This is a
+good way to do so.  It's also a great way to impress people staring
+over your shoulder as you read news.
+
+What are Picons?  To quote directly from the Picons Web site:
+
+@iftex
+@iflatex
+\margindex{}
+@end iflatex
+@end iftex
+
+@quotation
+@dfn{Picons} is short for ``personal icons''.  They're small,
+constrained images used to represent users and domains on the net,
+organized into databases so that the appropriate image for a given
+e-mail address can be found.  Besides users and domains, there are picon
+databases for Usenet newsgroups and weather forecasts.  The picons are
+in either monochrome @code{XBM} format or color @code{XPM} and
+@code{GIF} formats.
+@end quotation
+
+@vindex gnus-picon-databases
+For instructions on obtaining and installing the picons databases,
+point your Web browser at
+@uref{http://www.cs.indiana.edu/picons/ftp/index.html}.
+
+If you are using Debian GNU/Linux, saying @samp{apt-get install
+picons.*} will install the picons where Gnus can find them.
+
+To enable displaying picons, simply make sure that
+@code{gnus-picon-databases} points to the directory containing the
+Picons databases.
+
+The following variables offer control over where things are located.
+
+@table @code
+
+@item gnus-picon-databases
+@vindex gnus-picon-databases
+The location of the picons database.  This is a list of directories
+containing the @file{news}, @file{domains}, @file{users} (and so on)
+subdirectories.  Defaults to @code{("/usr/lib/picon"
+"/usr/local/faces")}.
+
+@item gnus-picon-news-directories
+@vindex gnus-picon-news-directories
+List of subdirectories to search in @code{gnus-picon-databases} for
+newsgroups faces.  @code{("news")} is the default.
+
+@item gnus-picon-user-directories
+@vindex gnus-picon-user-directories
+List of subdirectories to search in @code{gnus-picon-databases} for user
+faces.  @code{("users" "usenix" "local" "misc")} is the default.
+
+@item gnus-picon-domain-directories
+@vindex gnus-picon-domain-directories
+List of subdirectories to search in @code{gnus-picon-databases} for
+domain name faces.  Defaults to @code{("domains")}.  Some people may
+want to add @samp{"unknown"} to this list.
+
+@item gnus-picon-file-types
+@vindex gnus-picon-file-types
+Ordered list of suffixes on picon file names to try.  Defaults to
+@code{("xpm" "gif" "xbm")} minus those not built-in your Emacs.
+
+@end table
+
+
+@node XVarious
+@subsection Various XEmacs Variables
+
+@table @code
+@item gnus-xmas-glyph-directory
+@vindex gnus-xmas-glyph-directory
+This is where Gnus will look for pictures.  Gnus will normally
+auto-detect this directory, but you may set it manually if you have an
+unusual directory structure.
+
+@item gnus-xmas-logo-color-alist
+@vindex gnus-xmas-logo-color-alist
+This is an alist where the key is a type symbol and the values are the
+foreground and background color of the splash page glyph.
+
+@item gnus-xmas-logo-color-style
+@vindex gnus-xmas-logo-color-style
+This is the key used to look up the color in the alist described above.
+Valid values include @code{flame}, @code{pine}, @code{moss},
+@code{irish}, @code{sky}, @code{tin}, @code{velvet}, @code{grape},
+@code{labia}, @code{berry}, @code{neutral}, and @code{september}.
+
+@item gnus-xmas-modeline-glyph
+@vindex gnus-xmas-modeline-glyph
+A glyph displayed in all Gnus mode lines.  It is a tiny gnu head by
+default.
+
+@end table
+
+@subsubsection Toolbar
+
+@table @code
+
+@item gnus-use-toolbar
+@vindex gnus-use-toolbar
+If @code{nil}, don't display toolbars.  If non-@code{nil}, it should be
+one of @code{default-toolbar}, @code{top-toolbar}, @code{bottom-toolbar},
+@code{right-toolbar}, or @code{left-toolbar}.
+
+@item gnus-group-toolbar
+@vindex gnus-group-toolbar
+The toolbar in the group buffer.
+
+@item gnus-summary-toolbar
+@vindex gnus-summary-toolbar
+The toolbar in the summary buffer.
+
+@item gnus-summary-mail-toolbar
+@vindex gnus-summary-mail-toolbar
+The toolbar in the summary buffer of mail groups.
+
+@end table
+
+@iftex
+@iflatex
+\margindex{}
+@end iflatex
+@end iftex
+
+
+@node Fuzzy Matching
+@section Fuzzy Matching
+@cindex fuzzy matching
+
+Gnus provides @dfn{fuzzy matching} of @code{Subject} lines when doing
+things like scoring, thread gathering and thread comparison.
+
+As opposed to regular expression matching, fuzzy matching is very fuzzy.
+It's so fuzzy that there's not even a definition of what @dfn{fuzziness}
+means, and the implementation has changed over time.
+
+Basically, it tries to remove all noise from lines before comparing.
+@samp{Re: }, parenthetical remarks, white space, and so on, are filtered
+out of the strings before comparing the results.  This often leads to
+adequate results---even when faced with strings generated by text
+manglers masquerading as newsreaders.
+
+
+@node Thwarting Email Spam
+@section Thwarting Email Spam
+@cindex email spam
+@cindex spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+In these last days of the Usenet, commercial vultures are hanging about
+and grepping through news like crazy to find email addresses they can
+foist off their scams and products to.  As a reaction to this, many
+people have started putting nonsense addresses into their @code{From}
+lines.  I think this is counterproductive---it makes it difficult for
+people to send you legitimate mail in response to things you write, as
+well as making it difficult to see who wrote what.  This rewriting may
+perhaps be a bigger menace than the unsolicited commercial email itself
+in the end.
+
+The biggest problem I have with email spam is that it comes in under
+false pretenses.  I press @kbd{g} and Gnus merrily informs me that I
+have 10 new emails.  I say ``Golly gee!  Happy is me!'' and select the
+mail group, only to find two pyramid schemes, seven advertisements
+(``New!  Miracle tonic for growing full, lustrous hair on your toes!'')
+and one mail asking me to repent and find some god.
+
+This is annoying.  Here's what you can do about it.
+
+@menu
+* The problem of spam::         Some background, and some solutions
+* Anti-Spam Basics::            Simple steps to reduce the amount of spam.
+* SpamAssassin::                How to use external anti-spam tools.
+* Hashcash::                    Reduce spam by burning CPU time.
+* Filtering Spam Using The Spam ELisp Package::
+* Filtering Spam Using Statistics with spam-stat::
+@end menu
+
+@node The problem of spam
+@subsection The problem of spam
+@cindex email spam
+@cindex spam filtering approaches
+@cindex filtering approaches, spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+First, some background on spam.
+
+If you have access to e-mail, you are familiar with spam (technically
+termed @acronym{UCE}, Unsolicited Commercial E-mail).  Simply put, it
+exists because e-mail delivery is very cheap compared to paper mail,
+so only a very small percentage of people need to respond to an UCE to
+make it worthwhile to the advertiser.  Ironically, one of the most
+common spams is the one offering a database of e-mail addresses for
+further spamming.  Senders of spam are usually called @emph{spammers},
+but terms like @emph{vermin}, @emph{scum}, @emph{sociopaths}, and
+@emph{morons} are in common use as well.
+
+Spam comes from a wide variety of sources.  It is simply impossible to
+dispose of all spam without discarding useful messages.  A good
+example is the TMDA system, which requires senders
+unknown to you to confirm themselves as legitimate senders before
+their e-mail can reach you.  Without getting into the technical side
+of TMDA, a downside is clearly that e-mail from legitimate sources may
+be discarded if those sources can't or won't confirm themselves
+through the TMDA system.  Another problem with TMDA is that it
+requires its users to have a basic understanding of e-mail delivery
+and processing.
+
+The simplest approach to filtering spam is filtering, at the mail
+server or when you sort through incoming mail.  If you get 200 spam
+messages per day from @samp{random-address@@vmadmin.com}, you block
+@samp{vmadmin.com}.  If you get 200 messages about @samp{VIAGRA}, you
+discard all messages with @samp{VIAGRA} in the message.  If you get
+lots of spam from China, for example, you try to filter all mail from
+Chinese IPs.
+
+This, unfortunately, is a great way to discard legitimate e-mail.  For
+instance, the very informative and useful RISKS digest has been
+blocked by overzealous mail filters because it @strong{contained}
+words that were common in spam messages.  The risks of blocking a
+whole country from contacting you should also be obvious, so don't do
+it if you have the choice.  Nevertheless, in isolated cases, with
+great care, direct filtering of mail can be useful.
+
+Another approach to filtering e-mail is the distributed spam
+processing, for instance DCC implements such a system.  In essence,
+@var{N} systems around the world agree that a machine @var{X} in
+Ghana, Estonia, or California is sending out spam e-mail, and these
+@var{N} systems enter @var{X} or the spam e-mail from @var{X} into a
+database.  The criteria for spam detection vary---it may be the number
+of messages sent, the content of the messages, and so on.  When a user
+of the distributed processing system wants to find out if a message is
+spam, he consults one of those @var{N} systems.
+
+Distributed spam processing works very well against spammers that send
+a large number of messages at once, but it requires the user to set up
+fairly complicated checks.  There are commercial and free distributed
+spam processing systems.  Distributed spam processing has its risks as
+well.  For instance legitimate e-mail senders have been accused of
+sending spam, and their web sites and mailing lists have been shut
+down for some time because of the incident.
+
+The statistical approach to spam filtering is also popular.  It is
+based on a statistical analysis of previous spam messages.  Usually
+the analysis is a simple word frequency count, with perhaps pairs of
+words or 3-word combinations thrown into the mix.  Statistical
+analysis of spam works very well in most of the cases, but it can
+classify legitimate e-mail as spam in some cases.  It takes time to
+run the analysis, the full message must be analyzed, and the user has
+to store the database of spam analyses.  Statistical analysis on the
+server is gaining popularity.  This has the advantage of letting the
+user Just Read Mail, but has the disadvantage that it's harder to tell
+the server that it has misclassified mail.
+
+Fighting spam is not easy, no matter what anyone says.  There is no
+magic switch that will distinguish Viagra ads from Mom's e-mails.
+Even people are having a hard time telling spam apart from non-spam,
+because spammers are actively looking to fool us into thinking they
+are Mom, essentially.  Spamming is irritating, irresponsible, and
+idiotic behavior from a bunch of people who think the world owes them
+a favor.  We hope the following sections will help you in fighting the
+spam plague.
+
+@node Anti-Spam Basics
+@subsection Anti-Spam Basics
+@cindex email spam
+@cindex spam
+@cindex UCE
+@cindex unsolicited commercial email
+
+One way of dealing with spam is having Gnus split out all spam into a
+@samp{spam} mail group (@pxref{Splitting Mail}).
+
+First, pick one (1) valid mail address that you can be reached at, and
+put it in your @code{From} header of all your news articles.  (I've
+chosen @samp{larsi@@trym.ifi.uio.no}, but for many addresses on the form
+@samp{larsi+usenet@@ifi.uio.no} will be a better choice.  Ask your
+sysadmin whether your sendmail installation accepts keywords in the local
+part of the mail address.)
+
+@lisp
+(setq message-default-news-headers
+      "From: Lars Magne Ingebrigtsen <larsi@@trym.ifi.uio.no>\n")
+@end lisp
+
+Then put the following split rule in @code{nnmail-split-fancy}
+(@pxref{Fancy Mail Splitting}):
+
+@lisp
+(...
+ (to "larsi@@trym.ifi.uio.no"
+     (| ("subject" "re:.*" "misc")
+        ("references" ".*@@.*" "misc")
+        "spam"))
+ ...)
+@end lisp
+
+This says that all mail to this address is suspect, but if it has a
+@code{Subject} that starts with a @samp{Re:} or has a @code{References}
+header, it's probably ok.  All the rest goes to the @samp{spam} group.
+(This idea probably comes from Tim Pierce.)
+
+In addition, many mail spammers talk directly to your @acronym{SMTP} server
+and do not include your email address explicitly in the @code{To}
+header.  Why they do this is unknown---perhaps it's to thwart this
+thwarting scheme?  In any case, this is trivial to deal with---you just
+put anything not addressed to you in the @samp{spam} group by ending
+your fancy split rule in this way:
+
+@lisp
+(
+ ...
+ (to "larsi" "misc")
+ "spam")
+@end lisp
+
+In my experience, this will sort virtually everything into the right
+group.  You still have to check the @samp{spam} group from time to time to
+check for legitimate mail, though.  If you feel like being a good net
+citizen, you can even send off complaints to the proper authorities on
+each unsolicited commercial email---at your leisure.
+
+This works for me.  It allows people an easy way to contact me (they can
+just press @kbd{r} in the usual way), and I'm not bothered at all with
+spam.  It's a win-win situation.  Forging @code{From} headers to point
+to non-existent domains is yucky, in my opinion.
+
+Be careful with this approach.  Spammers are wise to it.
+
+
+@node SpamAssassin
+@subsection SpamAssassin, Vipul's Razor, DCC, etc
+@cindex SpamAssassin
+@cindex Vipul's Razor
+@cindex DCC
+
+The days where the hints in the previous section were sufficient in
+avoiding spam are coming to an end.  There are many tools out there
+that claim to reduce the amount of spam you get.  This section could
+easily become outdated fast, as new products replace old, but
+fortunately most of these tools seem to have similar interfaces.  Even
+though this section will use SpamAssassin as an example, it should be
+easy to adapt it to most other tools.
+
+Note that this section does not involve the @code{spam.el} package,
+which is discussed in the next section.  If you don't care for all
+the features of @code{spam.el}, you can make do with these simple
+recipes.
+
+If the tool you are using is not installed on the mail server, you
+need to invoke it yourself.  Ideas on how to use the
+@code{:postscript} mail source parameter (@pxref{Mail Source
+Specifiers}) follow.
+
+@lisp
+(setq mail-sources
+      '((file :prescript "formail -bs spamassassin < /var/mail/%u")
+        (pop :user "jrl"
+             :server "pophost"
+             :postscript
+             "mv %t /tmp/foo; formail -bs spamc < /tmp/foo > %t")))
+@end lisp
+
+Once you manage to process your incoming spool somehow, thus making
+the mail contain e.g.@: a header indicating it is spam, you are ready to
+filter it out.  Using normal split methods (@pxref{Splitting Mail}):
+
+@lisp
+(setq nnmail-split-methods '(("spam"  "^X-Spam-Flag: YES")
+                             ...))
+@end lisp
+
+Or using fancy split methods (@pxref{Fancy Mail Splitting}):
+
+@lisp
+(setq nnmail-split-methods 'nnmail-split-fancy
+      nnmail-split-fancy '(| ("X-Spam-Flag" "YES" "spam")
+                             ...))
+@end lisp
+
+Some people might not like the idea of piping the mail through various
+programs using a @code{:prescript} (if some program is buggy, you
+might lose all mail).  If you are one of them, another solution is to
+call the external tools during splitting.  Example fancy split method:
+
+@lisp
+(setq nnmail-split-fancy '(| (: kevin-spamassassin)
+                             ...))
+(defun kevin-spamassassin ()
+  (save-excursion
+    (save-restriction
+      (widen)
+      (if (eq 1 (call-process-region (point-min) (point-max)
+                                     "spamc" nil nil nil "-c"))
+          "spam"))))
+@end lisp
+
+Note that with the nnimap backend, message bodies will not be
+downloaded by default.  You need to set
+@code{nnimap-split-download-body} to t to do that (@pxref{Splitting in
+IMAP}).
+
+That is about it.  As some spam is likely to get through anyway, you
+might want to have a nifty function to call when you happen to read
+spam.  And here is the nifty function:
+
+@lisp
+ (defun my-gnus-raze-spam ()
+  "Submit SPAM to Vipul's Razor, then mark it as expirable."
+  (interactive)
+  (gnus-summary-show-raw-article)
+  (gnus-summary-save-in-pipe "razor-report -f -d")
+  (gnus-summary-mark-as-expirable 1))
+@end lisp
+
+@node Hashcash
+@subsection Hashcash
+@cindex hashcash
+
+A novel technique to fight spam is to require senders to do something
+costly for each message they send.  This has the obvious drawback that
+you cannot rely on everyone in the world using this technique,
+since it is not part of the Internet standards, but it may be useful
+in smaller communities.
+
+While the tools in the previous section work well in practice, they
+work only because the tools are constantly maintained and updated as
+new form of spam appears.  This means that a small percentage of spam
+will always get through.  It also means that somewhere, someone needs
+to read lots of spam to update these tools.  Hashcash avoids that, but
+instead prefers that everyone you contact through e-mail supports the
+scheme.  You can view the two approaches as pragmatic vs dogmatic.
+The approaches have their own advantages and disadvantages, but as
+often in the real world, a combination of them is stronger than either
+one of them separately.
+
+@cindex X-Hashcash
+The ``something costly'' is to burn CPU time, more specifically to
+compute a hash collision up to a certain number of bits.  The
+resulting hashcash cookie is inserted in a @samp{X-Hashcash:}
+header.  For more details, and for the external application
+@code{hashcash} you need to install to use this feature, see
+@uref{http://www.cypherspace.org/~adam/hashcash/}.  Even more
+information can be found at @uref{http://www.camram.org/}.
+
+If you wish to call hashcash for each message you send, say something
+like:
+
+@lisp
+(require 'hashcash)
+(add-hook 'message-send-hook 'mail-add-payment)
+@end lisp
+
+The @file{hashcash.el} library can be found in the Gnus development
+contrib directory or at
+@uref{http://users.actrix.gen.nz/mycroft/hashcash.el}.
+
+You will need to set up some additional variables as well:
+
+@table @code
+
+@item hashcash-default-payment
+@vindex hashcash-default-payment
+This variable indicates the default number of bits the hash collision
+should consist of.  By default this is 0, meaning nothing will be
+done.  Suggested useful values include 17 to 29.
+
+@item hashcash-payment-alist
+@vindex hashcash-payment-alist
+Some receivers may require you to spend burn more CPU time than the
+default.  This variable contains a list of @samp{(@var{addr}
+@var{amount})} cells, where @var{addr} is the receiver (email address
+or newsgroup) and @var{amount} is the number of bits in the collision
+that is needed.  It can also contain @samp{(@var{addr} @var{string}
+@var{amount})} cells, where the @var{string} is the string to use
+(normally the email address or newsgroup name is used).
+
+@item hashcash
+@vindex hashcash
+Where the @code{hashcash} binary is installed.
+
+@end table
+
+Currently there is no built in functionality in Gnus to verify
+hashcash cookies, it is expected that this is performed by your hand
+customized mail filtering scripts.  Improvements in this area would be
+a useful contribution, however.
+
+@node Filtering Spam Using The Spam ELisp Package
+@subsection Filtering Spam Using The Spam ELisp Package
+@cindex spam filtering
+@cindex spam
+
+The idea behind @file{spam.el} is to have a control center for spam detection
+and filtering in Gnus.  To that end, @file{spam.el} does two things: it
+filters new mail, and it analyzes mail known to be spam or ham.
+@dfn{Ham} is the name used throughout @file{spam.el} to indicate
+non-spam messages.
+
+First of all, you @strong{must} run the function
+@code{spam-initialize} to autoload @code{spam.el} and to install the
+@code{spam.el} hooks.  There is one exception: if you use the
+@code{spam-use-stat} (@pxref{spam-stat spam filtering}) setting, you
+should turn it on before @code{spam-initialize}:
+
+@example
+(setq spam-use-stat t) ;; if needed
+(spam-initialize)
+@end example
+
+So, what happens when you load @file{spam.el}?
+
+First, some hooks will get installed by @code{spam-initialize}.  There
+are some hooks for @code{spam-stat} so it can save its databases, and
+there are hooks so interesting things will happen when you enter and
+leave a group.  More on the sequence of events later (@pxref{Spam
+ELisp Package Sequence of Events}).
+
+You get the following keyboard commands:
+
+@table @kbd
+
+@item M-d
+@itemx M s x
+@itemx S x
+@kindex M-d
+@kindex S x
+@kindex M s x
+@findex gnus-summary-mark-as-spam
+@code{gnus-summary-mark-as-spam}.
+
+Mark current article as spam, showing it with the @samp{$} mark.
+Whenever you see a spam article, make sure to mark its summary line
+with @kbd{M-d} before leaving the group.  This is done automatically
+for unread articles in @emph{spam} groups.
+
+@item M s t
+@itemx S t
+@kindex M s t
+@kindex S t
+@findex spam-bogofilter-score
+@code{spam-bogofilter-score}.
+
+You must have Bogofilter installed for that command to work properly.
+
+@xref{Bogofilter}.
+
+@end table
+
+Also, when you load @file{spam.el}, you will be able to customize its
+variables.  Try @code{customize-group} on the @samp{spam} variable
+group.
+
+@menu
+* Spam ELisp Package Sequence of Events::  
+* Spam ELisp Package Filtering of Incoming Mail::  
+* Spam ELisp Package Global Variables::  
+* Spam ELisp Package Configuration Examples::  
+* Blacklists and Whitelists::   
+* BBDB Whitelists::             
+* Gmane Spam Reporting::        
+* Anti-spam Hashcash Payments::  
+* Blackholes::                  
+* Regular Expressions Header Matching::  
+* Bogofilter::                  
+* ifile spam filtering::        
+* spam-stat spam filtering::    
+* SpamOracle::                  
+* Extending the Spam ELisp package::  
+@end menu 
+
+@node Spam ELisp Package Sequence of Events
+@subsubsection Spam ELisp Package Sequence of Events
+@cindex spam filtering
+@cindex spam filtering sequence of events
+@cindex spam
+
+You must read this section to understand how @code{spam.el} works.
+Do not skip, speed-read, or glance through this section.
+
+There are two @emph{contact points}, if you will, between
+@code{spam.el} and the rest of Gnus: checking new mail for spam, and
+leaving a group.
+
+Getting new mail is done in one of two ways.  You can either split
+your incoming mail or you can classify new articles as ham or spam
+when you enter the group.
+
+Splitting incoming mail is better suited to mail backends such as
+@code{nnml} or @code{nnimap} where new mail appears in a single file
+called a @dfn{Spool File}.  See @xref{Spam ELisp Package Filtering of
+Incoming Mail}.
+
+For backends such as @code{nntp} there is no incoming mail spool, so
+an alternate mechanism must be used.  This may also happen for
+backends where the server is in charge of splitting incoming mail, and
+Gnus does not do further splitting.  The @code{spam-autodetect} and
+@code{spam-autodetect-methods} group parameters (accessible with
+@kbd{G c} and @kbd{G p} as usual), and the corresponding variables
+@code{gnus-spam-autodetect-methods} and
+@code{gnus-spam-autodetect-methods} (accessible with @kbd{M-x
+customize-variable} as usual).
+
+When @code{spam-autodetect} is used, it hooks into the process of
+entering a group.  Thus, entering a group with unseen or unread
+articles becomes the substitute for checking incoming mail.  Whether
+only unseen articles or all unread articles will be processed is
+determined by the @code{spam-autodetect-recheck-messages}.  When set
+to t, unread messages will be rechecked.
+
+@code{spam-autodetect} grants the user at once more and less control
+of spam filtering.  The user will have more control over each group's
+spam methods, so for instance the @samp{ding} group may have
+@code{spam-use-BBDB} as the autodetection method, while the
+@samp{suspect} group may have the @code{spam-use-blacklist} and
+@code{spam-use-bogofilter} methods enabled.  Every article detected to
+be spam will be marked with the spam mark @samp{$} and processed on
+exit from the group as normal spam.  The user has less control over
+the @emph{sequence} of checks, as he might with @code{spam-split}.
+
+When the newly split mail goes into groups, or messages are
+autodetected to be ham or spam, those groups must be exited (after
+entering, if needed) for further spam processing to happen.  It
+matters whether the group is considered a ham group, a spam group, or
+is unclassified, based on its @code{spam-content} parameter
+(@pxref{Spam ELisp Package Global Variables}).  Spam groups have the
+additional characteristic that, when entered, any unseen or unread
+articles (depending on the @code{spam-mark-only-unseen-as-spam}
+variable) will be marked as spam.  Thus, mail split into a spam group
+gets automatically marked as spam when you enter the group.
+
+So, when you exit a group, the @code{spam-processors} are applied, if
+any are set, and the processed mail is moved to the
+@code{ham-process-destination} or the @code{spam-process-destination}
+depending on the article's classification.  If the
+@code{ham-process-destination} or the @code{spam-process-destination},
+whichever is appropriate, are nil, the article is left in the current
+group.
+
+If a spam is found in any group (this can be changed to only non-spam
+groups with @code{spam-move-spam-nonspam-groups-only}), it is
+processed by the active @code{spam-processors} (@pxref{Spam ELisp
+Package Global Variables}) when the group is exited.  Furthermore, the
+spam is moved to the @code{spam-process-destination} (@pxref{Spam
+ELisp Package Global Variables}) for further training or deletion.
+You have to load the @code{gnus-registry.el} package and enable the
+@code{spam-log-to-registry} variable if you want spam to be processed
+no more than once.  Thus, spam is detected and processed everywhere,
+which is what most people want.  If the
+@code{spam-process-destination} is nil, the spam is marked as
+expired, which is usually the right thing to do.
+
+If spam can not be moved - because of a read-only backend such as NNTP,
+for example, it will be copied.
+
+If a ham mail is found in a ham group, as determined by the
+@code{ham-marks} parameter, it is processed as ham by the active ham
+@code{spam-processor} when the group is exited.  With the variables
+@code{spam-process-ham-in-spam-groups} and
+@code{spam-process-ham-in-nonham-groups} the behavior can be further
+altered so ham found anywhere can be processed.  You have to load the
+@code{gnus-registry.el} package and enable the
+@code{spam-log-to-registry} variable if you want ham to be processed
+no more than once.  Thus, ham is detected and processed only when
+necessary, which is what most people want.  More on this in
+@xref{Spam ELisp Package Configuration Examples}.
+
+If ham can not be moved - because of a read-only backend such as NNTP,
+for example, it will be copied.
+
+If all this seems confusing, don't worry.  Soon it will be as natural
+as typing Lisp one-liners on a neural interface... err, sorry, that's
+50 years in the future yet.  Just trust us, it's not so bad.
+
+@node Spam ELisp Package Filtering of Incoming Mail
+@subsubsection Spam ELisp Package Filtering of Incoming Mail
+@cindex spam filtering
+@cindex spam filtering incoming mail
+@cindex spam
+
+To use the @file{spam.el} facilities for incoming mail filtering, you
+must add the following to your fancy split list
+@code{nnmail-split-fancy} or @code{nnimap-split-fancy}:
+
+@example
+(: spam-split)
+@end example
+
+Note that the fancy split may be called @code{nnmail-split-fancy} or
+@code{nnimap-split-fancy}, depending on whether you use the nnmail or
+nnimap back ends to retrieve your mail.
+
+The @code{spam-split} function will process incoming mail and send the
+mail considered to be spam into the group name given by the variable
+@code{spam-split-group}.  By default that group name is @samp{spam},
+but you can customize @code{spam-split-group}.  Make sure the contents
+of @code{spam-split-group} are an @emph{unqualified} group name, for
+instance in an @code{nnimap} server @samp{your-server} the value
+@samp{spam} will turn out to be @samp{nnimap+your-server:spam}.  The
+value @samp{nnimap+server:spam}, therefore, is wrong and will
+actually give you the group
+@samp{nnimap+your-server:nnimap+server:spam} which may or may not
+work depending on your server's tolerance for strange group names.
+
+You can also give @code{spam-split} a parameter,
+e.g. @samp{'spam-use-regex-headers} or @samp{"maybe-spam"}.  Why is
+this useful?
+
+Take these split rules (with @code{spam-use-regex-headers} and
+@code{spam-use-blackholes} set):
+
+@example
+ nnimap-split-fancy '(|
+                      (any "ding" "ding")
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail")
+@end example
+
+Now, the problem is that you want all ding messages to make it to the
+ding folder.  But that will let obvious spam (for example, spam
+detected by SpamAssassin, and @code{spam-use-regex-headers}) through,
+when it's sent to the ding list.  On the other hand, some messages to
+the ding list are from a mail server in the blackhole list, so the
+invocation of @code{spam-split} can't be before the ding rule.
+
+You can let SpamAssassin headers supersede ding rules, but all other
+@code{spam-split} rules (including a second invocation of the
+regex-headers check) will be after the ding rule:
+
+@example
+ nnimap-split-fancy '(|
+;;; all spam detected by spam-use-regex-headers goes to "regex-spam"
+                      (: spam-split "regex-spam" 'spam-use-regex-headers)
+                      (any "ding" "ding")
+;;; all other spam detected by spam-split goes to spam-split-group
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail")
+@end example
+
+This lets you invoke specific @code{spam-split} checks depending on
+your particular needs, and to target the results of those checks to a
+particular spam group.  You don't have to throw all mail into all the
+spam tests.  Another reason why this is nice is that messages to
+mailing lists you have rules for don't have to have resource-intensive
+blackhole checks performed on them.  You could also specify different
+spam checks for your nnmail split vs. your nnimap split.  Go crazy.
+
+You should still have specific checks such as
+@code{spam-use-regex-headers} set to @code{t}, even if you
+specifically invoke @code{spam-split} with the check.  The reason is
+that when loading @file{spam.el}, some conditional loading is done
+depending on what @code{spam-use-xyz} variables you have set.  This
+is usually not critical, though.
+
+@emph{Note for IMAP users}
+
+The boolean variable @code{nnimap-split-download-body} needs to be
+set, if you want to split based on the whole message instead of just
+the headers.  By default, the nnimap back end will only retrieve the
+message headers.  If you use @code{spam-check-bogofilter},
+@code{spam-check-ifile}, or @code{spam-check-stat} (the splitters that
+can benefit from the full message body), you should set this variable.
+It is not set by default because it will slow @acronym{IMAP} down, and
+that is not an appropriate decision to make on behalf of the user.
+
+@xref{Splitting in IMAP}.
+
+@emph{TODO: spam.el needs to provide a uniform way of training all the
+statistical databases.  Some have that functionality built-in, others
+don't.}
+
+@node Spam ELisp Package Global Variables
+@subsubsection Spam ELisp Package Global Variables
+@cindex spam filtering
+@cindex spam filtering variables
+@cindex spam variables
+@cindex spam
+
+@vindex gnus-spam-process-newsgroups
+The concepts of ham processors and spam processors are very important.
+Ham processors and spam processors for a group can be set with the
+@code{spam-process} group parameter, or the
+@code{gnus-spam-process-newsgroups} variable.  Ham processors take
+mail known to be non-spam (@emph{ham}) and process it in some way so
+that later similar mail will also be considered non-spam.  Spam
+processors take mail known to be spam and process it so similar spam
+will be detected later.
+
+The format of the spam or ham processor entry used to be a symbol,
+but now it is a cons cell.  See the individual spam processor entries
+for more information.
+
+@vindex gnus-spam-newsgroup-contents
+Gnus learns from the spam you get.  You have to collect your spam in
+one or more spam groups, and set or customize the variable
+@code{spam-junk-mailgroups} as appropriate.  You can also declare
+groups to contain spam by setting their group parameter
+@code{spam-contents} to @code{gnus-group-spam-classification-spam}, or
+by customizing the corresponding variable
+@code{gnus-spam-newsgroup-contents}.  The @code{spam-contents} group
+parameter and the @code{gnus-spam-newsgroup-contents} variable can
+also be used to declare groups as @emph{ham} groups if you set their
+classification to @code{gnus-group-spam-classification-ham}.  If
+groups are not classified by means of @code{spam-junk-mailgroups},
+@code{spam-contents}, or @code{gnus-spam-newsgroup-contents}, they are
+considered @emph{unclassified}.  All groups are unclassified by
+default.
+
+@vindex gnus-spam-mark
+@cindex $
+In spam groups, all messages are considered to be spam by default:
+they get the @samp{$} mark (@code{gnus-spam-mark}) when you enter the
+group.  If you have seen a message, had it marked as spam, then
+unmarked it, it won't be marked as spam when you enter the group
+thereafter.  You can disable that behavior, so all unread messages
+will get the @samp{$} mark, if you set the
+@code{spam-mark-only-unseen-as-spam} parameter to @code{nil}.  You
+should remove the @samp{$} mark when you are in the group summary
+buffer for every message that is not spam after all.  To remove the
+@samp{$} mark, you can use @kbd{M-u} to ``unread'' the article, or
+@kbd{d} for declaring it read the non-spam way.  When you leave a
+group, all spam-marked (@samp{$}) articles are sent to a spam
+processor which will study them as spam samples.
+
+Messages may also be deleted in various other ways, and unless
+@code{ham-marks} group parameter gets overridden below, marks @samp{R}
+and @samp{r} for default read or explicit delete, marks @samp{X} and
+@samp{K} for automatic or explicit kills, as well as mark @samp{Y} for
+low scores, are all considered to be associated with articles which
+are not spam.  This assumption might be false, in particular if you
+use kill files or score files as means for detecting genuine spam, you
+should then adjust the @code{ham-marks} group parameter.
+
+@defvar ham-marks
+You can customize this group or topic parameter to be the list of
+marks you want to consider ham.  By default, the list contains the
+deleted, read, killed, kill-filed, and low-score marks (the idea is
+that these articles have been read, but are not spam).  It can be
+useful to also include the tick mark in the ham marks.  It is not
+recommended to make the unread mark a ham mark, because it normally
+indicates a lack of classification.  But you can do it, and we'll be
+happy for you.
+@end defvar
+
+@defvar spam-marks
+You can customize this group or topic parameter to be the list of
+marks you want to consider spam.  By default, the list contains only
+the spam mark.  It is not recommended to change that, but you can if
+you really want to.
+@end defvar
+
+When you leave @emph{any} group, regardless of its
+@code{spam-contents} classification, all spam-marked articles are sent
+to a spam processor, which will study these as spam samples.  If you
+explicit kill a lot, you might sometimes end up with articles marked
+@samp{K} which you never saw, and which might accidentally contain
+spam.  Best is to make sure that real spam is marked with @samp{$},
+and nothing else.
+
+@vindex gnus-ham-process-destinations
+When you leave a @emph{spam} group, all spam-marked articles are
+marked as expired after processing with the spam processor.  This is
+not done for @emph{unclassified} or @emph{ham} groups.  Also, any
+@strong{ham} articles in a spam group will be moved to a location
+determined by either the @code{ham-process-destination} group
+parameter or a match in the @code{gnus-ham-process-destinations}
+variable, which is a list of regular expressions matched with group
+names (it's easiest to customize this variable with
+@code{customize-variable gnus-ham-process-destinations}).  Each
+newsgroup specification has the format (REGEXP PROCESSOR) in a
+standard Lisp list, if you prefer to customize the variable manually.
+The ultimate location is a group name or names.  If the
+@code{ham-process-destination} parameter is not set, ham articles are
+left in place.  If the
+@code{spam-mark-ham-unread-before-move-from-spam-group} parameter is
+set, the ham articles are marked as unread before being moved.  
+
+If ham can not be moved - because of a read-only backend such as NNTP,
+for example, it will be copied.
+
+Note that you can use multiples destinations per group or regular
+expression!  This enables you to send your ham to a regular mail
+group and to a @emph{ham training} group.
+
+When you leave a @emph{ham} group, all ham-marked articles are sent to
+a ham processor, which will study these as non-spam samples.
+
+@vindex spam-process-ham-in-spam-groups
+By default the variable @code{spam-process-ham-in-spam-groups} is
+@code{nil}.  Set it to @code{t} if you want ham found in spam groups
+to be processed.  Normally this is not done, you are expected instead
+to send your ham to a ham group and process it there.
+
+@vindex spam-process-ham-in-nonham-groups
+By default the variable @code{spam-process-ham-in-nonham-groups} is
+@code{nil}.  Set it to @code{t} if you want ham found in non-ham (spam
+or unclassified) groups to be processed.  Normally this is not done,
+you are expected instead to send your ham to a ham group and process
+it there.
+
+@vindex gnus-spam-process-destinations
+When you leave a @emph{ham} or @emph{unclassified} group, all
+@strong{spam} articles are moved to a location determined by either
+the @code{spam-process-destination} group parameter or a match in the
+@code{gnus-spam-process-destinations} variable, which is a list of
+regular expressions matched with group names (it's easiest to
+customize this variable with @code{customize-variable
+gnus-spam-process-destinations}).  Each newsgroup specification has
+the repeated format (REGEXP GROUP) and they are all in a standard Lisp
+list, if you prefer to customize the variable manually.  The ultimate
+location is a group name or names.  If the
+@code{spam-process-destination} parameter is not set, the spam
+articles are only expired.  The group name is fully qualified, meaning
+that if you see @samp{nntp:servername} before the group name in the
+group buffer then you need it here as well.  
+
+If spam can not be moved - because of a read-only backend such as NNTP,
+for example, it will be copied.
+
+Note that you can use multiples destinations per group or regular
+expression!  This enables you to send your spam to multiple @emph{spam
+training} groups.
+
+@vindex spam-log-to-registry
+The problem with processing ham and spam is that Gnus doesn't track
+this processing by default.  Enable the @code{spam-log-to-registry}
+variable so @code{spam.el} will use @code{gnus-registry.el} to track
+what articles have been processed, and avoid processing articles
+multiple times.  Keep in mind that if you limit the number of registry
+entries, this won't work as well as it does without a limit.
+
+@vindex spam-mark-only-unseen-as-spam
+Set this variable if you want only unseen articles in spam groups to
+be marked as spam.  By default, it is set.  If you set it to nil,
+unread articles will also be marked as spam.
+
+@vindex spam-mark-ham-unread-before-move-from-spam-group
+Set this variable if you want ham to be unmarked before it is moved
+out of the spam group.  This is very useful when you use something
+like the tick mark @samp{!} to mark ham - the article will be placed
+in your ham-process-destination, unmarked as if it came fresh from
+the mail server.
+
+@vindex spam-autodetect-recheck-messages
+When autodetecting spam, this variable tells @code{spam.el} whether
+only unseen articles or all unread articles should be checked for
+spam.  It is recommended that you leave it off.
+
+@node Spam ELisp Package Configuration Examples
+@subsubsection Spam ELisp Package Configuration Examples
+@cindex spam filtering
+@cindex spam filtering configuration examples
+@cindex spam configuration examples
+@cindex spam
+
+@subsubheading Ted's setup
+
+From Ted Zlatanov <tzz@@lifelogs.com>.
+@example
+
+;; for gnus-registry-split-fancy-with-parent and spam autodetection
+;; see gnus-registry.el for more information
+(gnus-registry-initialize)
+(spam-initialize)
+
+;; I like control-S for marking spam
+(define-key gnus-summary-mode-map "\C-s" 'gnus-summary-mark-as-spam)
+
+(setq
+ spam-log-to-registry t ;; for spam autodetection
+ spam-use-BBDB t
+ spam-use-regex-headers t               ; catch X-Spam-Flag (SpamAssassin)
+ ;; all groups with "spam" in the name contain spam
+ gnus-spam-newsgroup-contents '(("spam" gnus-group-spam-classification-spam))
+ ;; see documentation for these
+ spam-move-spam-nonspam-groups-only nil
+ spam-mark-only-unseen-as-spam t
+ spam-mark-ham-unread-before-move-from-spam-group t
+ nnimap-split-rule 'nnimap-split-fancy
+ ;; understand what this does before you copy it to your own setup!
+ nnimap-split-fancy '(|
+                      ;; trace references to parents and put in their group
+                      (: gnus-registry-split-fancy-with-parent)
+                      ;; this will catch server-side SpamAssassin tags
+                      (: spam-split 'spam-use-regex-headers)
+                      (any "ding" "ding")
+                      ;; note that spam by default will go to "spam"
+                      (: spam-split)
+                      ;; default mailbox
+                      "mail"))
+
+;; my parameters, set with `G p'
+
+;; all nnml groups, and all nnimap groups except
+;; "nnimap+mail.lifelogs.com:train" and
+;; "nnimap+mail.lifelogs.com:spam": any spam goes to nnimap training,
+;; because it must have been detected manually
+
+((spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; all NNTP groups
+;; autodetect spam with the blacklist and ham with the BBDB
+((spam-autodetect-methods spam-use-blacklist spam-use-BBDB)
+;; send all spam to the training group
+ (spam-process-destination . "nnimap+mail.lifelogs.com:train"))
+
+;; only some NNTP groups, where I want to autodetect spam
+((spam-autodetect . t))
+
+;; my nnimap "nnimap+mail.lifelogs.com:spam" group
+
+;; this is a spam group
+((spam-contents gnus-group-spam-classification-spam)
+
+ ;; any spam (which happens when I enter for all unseen messages,
+ ;; because of the gnus-spam-newsgroup-contents setting above), goes to
+ ;; "nnimap+mail.lifelogs.com:train" unless I mark it as ham
+
+ (spam-process-destination "nnimap+mail.lifelogs.com:train")
+
+ ;; any ham goes to my "nnimap+mail.lifelogs.com:mail" folder, but
+ ;; also to my "nnimap+mail.lifelogs.com:trainham" folder for training
+
+ (ham-process-destination "nnimap+mail.lifelogs.com:mail" 
+                          "nnimap+mail.lifelogs.com:trainham")
+ ;; in this group, only '!' marks are ham
+ (ham-marks
+  (gnus-ticked-mark))
+ ;; remembers senders in the blacklist on the way out - this is
+ ;; definitely not needed, it just makes me feel better
+ (spam-process (gnus-group-spam-exit-processor-blacklist)))
+
+;; Later, on the IMAP server I use the "train" group for training
+;; SpamAssassin to recognize spam, and the "trainham" group for
+;; recognizing ham - but Gnus has nothing to do with it.
+
+@end example
+
+@subsubheading Using @file{spam.el} on an IMAP server with a statistical filter on the server
+
+From Reiner Steib <reiner.steib@@gmx.de>.
+
+My provider has set up bogofilter (in combination with @acronym{DCC}) on
+the mail server (@acronym{IMAP}).  Recognized spam goes to
+@samp{spam.detected}, the rest goes through the normal filter rules,
+i.e. to @samp{some.folder} or to @samp{INBOX}.  Training on false
+positives or negatives is done by copying or moving the article to
+@samp{training.ham} or @samp{training.spam} respectively.  A cron job on
+the server feeds those to bogofilter with the suitable ham or spam
+options and deletes them from the @samp{training.ham} and
+@samp{training.spam} folders.
+
+With the following entries in @code{gnus-parameters}, @code{spam.el}
+does most of the job for me:
+
+@lisp
+   ("nnimap:spam\\.detected"
+    (gnus-article-sort-functions '(gnus-article-sort-by-chars))
+    (ham-process-destination "nnimap:INBOX" "nnimap:training.ham")
+    (spam-contents gnus-group-spam-classification-spam))
+   ("nnimap:\\(INBOX\\|other-folders\\)"
+    (spam-process-destination . "nnimap:training.spam")
+    (spam-contents gnus-group-spam-classification-ham))
+@end lisp
+
+@itemize 
+
+@item @b{The Spam folder:}
+
+In the folder @samp{spam.detected}, I have to check for false positives
+(i.e. legitimate mails, that were wrongly judged as spam by
+bogofilter or DCC).
+
+Because of the @code{gnus-group-spam-classification-spam} entry, all
+messages are marked as spam (with @code{$}).  When I find a false
+positive, I mark the message with some other ham mark (@code{ham-marks},
+@ref{Spam ELisp Package Global Variables}).  On group exit, those
+messages are copied to both groups, @samp{INBOX} (were I want to have
+the article) and @samp{training.ham} (for training bogofilter) and
+deleted from the @samp{spam.detected} folder.
+
+The @code{gnus-article-sort-by-chars} entry simplifies detection of
+false positives for me.  I receive lots of worms (sweN, @dots{}), that all
+have a similar size.  Grouping them by size (i.e. chars) makes finding
+other false positives easier.  (Of course worms aren't @i{spam}
+(@acronym{UCE}, @acronym{UBE}) strictly speaking.  Anyhow, bogofilter is
+an excellent tool for filtering those unwanted mails for me.)
+
+@item @b{Ham folders:}
+
+In my ham folders, I just hit @kbd{S x}
+(@code{gnus-summary-mark-as-spam}) whenever I see an unrecognized spam
+mail (false negative).  On group exit, those messages are moved to
+@samp{training.ham}.
+@end itemize
+
+@subsubheading Reporting spam articles in Gmane groups with @code{spam-report.el}
+
+From Reiner Steib <reiner.steib@@gmx.de>.
+
+With following entry in @code{gnus-parameters}, @kbd{S x}
+(@code{gnus-summary-mark-as-spam}) marks articles in @code{gmane.*}
+groups as spam and reports the to Gmane at group exit:
+
+@lisp
+   ("^gmane\\."
+    (spam-process (gnus-group-spam-exit-processor-report-gmane)))
+@end lisp
+
+Additionally, I use `(setq spam-report-gmane-use-article-number nil)'
+because I don't read the groups directly from news.gmane.org, but
+through my local news server (leafnode).  I.e. the article numbers are
+not the same as on news.gmane.org, thus @code{spam-report.el} has to check
+the @code{X-Report-Spam} header to find the correct number.
+
+@node Blacklists and Whitelists
+@subsubsection Blacklists and Whitelists
+@cindex spam filtering
+@cindex whitelists, spam filtering
+@cindex blacklists, spam filtering
+@cindex spam
+
+@defvar spam-use-blacklist
+
+Set this variable to @code{t} if you want to use blacklists when
+splitting incoming mail.  Messages whose senders are in the blacklist
+will be sent to the @code{spam-split-group}.  This is an explicit
+filter, meaning that it acts only on mail senders @emph{declared} to
+be spammers.
+
+@end defvar
+
+@defvar spam-use-whitelist
+
+Set this variable to @code{t} if you want to use whitelists when
+splitting incoming mail.  Messages whose senders are not in the
+whitelist will be sent to the next spam-split rule.  This is an
+explicit filter, meaning that unless someone is in the whitelist, their
+messages are not assumed to be spam or ham.
+
+@end defvar
+
+@defvar spam-use-whitelist-exclusive
+
+Set this variable to @code{t} if you want to use whitelists as an
+implicit filter, meaning that every message will be considered spam
+unless the sender is in the whitelist.  Use with care.
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-blacklist
+
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the senders of
+spam-marked articles will be added to the blacklist.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-spam-exit-processor-blacklist}, it is recommended
+that you use @code{'(spam spam-use-blacklist)}.  Everything will work
+the same way, we promise.
+
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-whitelist
+
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the senders of
+ham-marked articles in @emph{ham} groups will be added to the
+whitelist.  Note that this ham processor has no effect in @emph{spam}
+or @emph{unclassified} groups.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-ham-exit-processor-whitelist}, it is recommended
+that you use @code{'(ham spam-use-whitelist)}.  Everything will work
+the same way, we promise.
+
+@end defvar
+
+Blacklists are lists of regular expressions matching addresses you
+consider to be spam senders.  For instance, to block mail from any
+sender at @samp{vmadmin.com}, you can put @samp{vmadmin.com} in your
+blacklist.  You start out with an empty blacklist.  Blacklist entries
+use the Emacs regular expression syntax.
+
+Conversely, whitelists tell Gnus what addresses are considered
+legitimate.  All messages from whitelisted addresses are considered
+non-spam.  Also see @ref{BBDB Whitelists}.  Whitelist entries use the
+Emacs regular expression syntax.
+
+The blacklist and whitelist file locations can be customized with the
+@code{spam-directory} variable (@file{~/News/spam} by default), or
+the @code{spam-whitelist} and @code{spam-blacklist} variables
+directly.  The whitelist and blacklist files will by default be in the
+@code{spam-directory} directory, named @file{whitelist} and
+@file{blacklist} respectively.
+
+@node BBDB Whitelists
+@subsubsection BBDB Whitelists
+@cindex spam filtering
+@cindex BBDB whitelists, spam filtering
+@cindex BBDB, spam filtering
+@cindex spam
+
+@defvar spam-use-BBDB
+
+Analogous to @code{spam-use-whitelist} (@pxref{Blacklists and
+Whitelists}), but uses the BBDB as the source of whitelisted
+addresses, without regular expressions.  You must have the BBDB loaded
+for @code{spam-use-BBDB} to work properly.  Messages whose senders are
+not in the BBDB will be sent to the next spam-split rule.  This is an
+explicit filter, meaning that unless someone is in the BBDB, their
+messages are not assumed to be spam or ham.
+
+@end defvar
+
+@defvar spam-use-BBDB-exclusive
+
+Set this variable to @code{t} if you want to use the BBDB as an
+implicit filter, meaning that every message will be considered spam
+unless the sender is in the BBDB.  Use with care.  Only sender
+addresses in the BBDB will be allowed through; all others will be
+classified as spammers.
+
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-BBDB
+
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the senders of
+ham-marked articles in @emph{ham} groups will be added to the
+BBDB.  Note that this ham processor has no effect in @emph{spam}
+or @emph{unclassified} groups.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-ham-exit-processor-BBDB}, it is recommended
+that you use @code{'(ham spam-use-BBDB)}.  Everything will work
+the same way, we promise.
+
+@end defvar
+
+@node Gmane Spam Reporting
+@subsubsection Gmane Spam Reporting
+@cindex spam reporting
+@cindex Gmane, spam reporting
+@cindex Gmane, spam reporting
+@cindex spam
+
+@defvar gnus-group-spam-exit-processor-report-gmane
+
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the spam-marked
+articles groups will be reported to the Gmane administrators via a
+HTTP request.
+
+Gmane can be found at @uref{http://gmane.org}.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-spam-exit-processor-report-gmane}, it is recommended
+that you use @code{'(spam spam-use-gmane)}.  Everything will work the
+same way, we promise.
+
+@end defvar
+
+@defvar spam-report-gmane-use-article-number
+
+This variable is @code{t} by default.  Set it to @code{nil} if you are
+running your own news server, for instance, and the local article
+numbers don't correspond to the Gmane article numbers.  When
+@code{spam-report-gmane-use-article-number} is @code{nil},
+@code{spam-report.el} will use the @code{X-Report-Spam} header that
+Gmane provides.
+
+@end defvar
+
+@node Anti-spam Hashcash Payments
+@subsubsection Anti-spam Hashcash Payments
+@cindex spam filtering
+@cindex hashcash, spam filtering
+@cindex spam
+
+@defvar spam-use-hashcash
+
+Similar to @code{spam-use-whitelist} (@pxref{Blacklists and
+Whitelists}), but uses hashcash tokens for whitelisting messages
+instead of the sender address.  You must have the @code{hashcash.el}
+package loaded for @code{spam-use-hashcash} to work properly.
+Messages without a hashcash payment token will be sent to the next
+spam-split rule.  This is an explicit filter, meaning that unless a
+hashcash token is found, the messages are not assumed to be spam or
+ham.
+
+@end defvar
+
+@node Blackholes
+@subsubsection Blackholes
+@cindex spam filtering
+@cindex blackholes, spam filtering
+@cindex spam
+
+@defvar spam-use-blackholes
+
+This option is disabled by default.  You can let Gnus consult the
+blackhole-type distributed spam processing systems (DCC, for instance)
+when you set this option.  The variable @code{spam-blackhole-servers}
+holds the list of blackhole servers Gnus will consult.  The current
+list is fairly comprehensive, but make sure to let us know if it
+contains outdated servers.
+
+The blackhole check uses the @code{dig.el} package, but you can tell
+@file{spam.el} to use @code{dns.el} instead for better performance if
+you set @code{spam-use-dig} to @code{nil}.  It is not recommended at
+this time to set @code{spam-use-dig} to @code{nil} despite the
+possible performance improvements, because some users may be unable to
+use it, but you can try it and see if it works for you.
+
+@end defvar
+
+@defvar spam-blackhole-servers
+
+The list of servers to consult for blackhole checks.
+
+@end defvar
+
+@defvar spam-blackhole-good-server-regex
+
+A regular expression for IPs that should not be checked against the
+blackhole server list.  When set to @code{nil}, it has no effect.
+
+@end defvar
+
+@defvar spam-use-dig
+
+Use the @code{dig.el} package instead of the @code{dns.el} package.
+The default setting of @code{t} is recommended.
+
+@end defvar
+
+Blackhole checks are done only on incoming mail.  There is no spam or
+ham processor for blackholes.
+
+@node Regular Expressions Header Matching
+@subsubsection Regular Expressions Header Matching
+@cindex spam filtering
+@cindex regular expressions header matching, spam filtering
+@cindex spam
+
+@defvar spam-use-regex-headers
+
+This option is disabled by default.  You can let Gnus check the
+message headers against lists of regular expressions when you set this
+option.  The variables @code{spam-regex-headers-spam} and
+@code{spam-regex-headers-ham} hold the list of regular expressions.
+Gnus will check against the message headers to determine if the
+message is spam or ham, respectively.
+
+@end defvar
+
+@defvar spam-regex-headers-spam
+
+The list of regular expressions that, when matched in the headers of
+the message, positively identify it as spam.
+
+@end defvar
+
+@defvar spam-regex-headers-ham
+
+The list of regular expressions that, when matched in the headers of
+the message, positively identify it as ham.
+
+@end defvar
+
+Regular expression header checks are done only on incoming mail.
+There is no specific spam or ham processor for regular expressions.
+
+@node Bogofilter
+@subsubsection Bogofilter
+@cindex spam filtering
+@cindex bogofilter, spam filtering
+@cindex spam
+
+@defvar spam-use-bogofilter
+
+Set this variable if you want @code{spam-split} to use Eric Raymond's
+speedy Bogofilter.
+
+With a minimum of care for associating the @samp{$} mark for spam
+articles only, Bogofilter training all gets fairly automatic.  You
+should do this until you get a few hundreds of articles in each
+category, spam or not.  The command @kbd{S t} in summary mode, either
+for debugging or for curiosity, shows the @emph{spamicity} score of
+the current article (between 0.0 and 1.0).
+
+Bogofilter determines if a message is spam based on a specific
+threshold.  That threshold can be customized, consult the Bogofilter
+documentation.
+
+If the @code{bogofilter} executable is not in your path, Bogofilter
+processing will be turned off.
+
+You should not enable this if you use @code{spam-use-bogofilter-headers}.
+
+@end defvar
+
+@defvar spam-use-bogofilter-headers
+
+Set this variable if you want @code{spam-split} to use Eric Raymond's
+speedy Bogofilter, looking only at the message headers.  It works
+similarly to @code{spam-use-bogofilter}, but the @code{X-Bogosity} header
+must be in the message already.  Normally you would do this with a
+procmail recipe or something similar; consult the Bogofilter
+installation documents for details.
+
+You should not enable this if you use @code{spam-use-bogofilter}.
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-bogofilter
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, spam-marked articles
+will be added to the Bogofilter spam database.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-spam-exit-processor-bogofilter}, it is recommended
+that you use @code{'(spam spam-use-bogofilter)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-bogofilter
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the ham-marked
+articles in @emph{ham} groups will be added to the Bogofilter database
+of non-spam messages.  Note that this ham processor has no effect in
+@emph{spam} or @emph{unclassified} groups.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-ham-exit-processor-bogofilter}, it is recommended
+that you use @code{'(ham spam-use-bogofilter)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+@defvar spam-bogofilter-database-directory
+
+This is the directory where Bogofilter will store its databases.  It
+is not specified by default, so Bogofilter will use its own default
+database directory.
+
+@end defvar
+
+The Bogofilter mail classifier is similar to @command{ifile} in intent and
+purpose.  A ham and a spam processor are provided, plus the
+@code{spam-use-bogofilter} and @code{spam-use-bogofilter-headers}
+variables to indicate to spam-split that Bogofilter should either be
+used, or has already been used on the article.  The 0.9.2.1 version of
+Bogofilter was used to test this functionality.
+
+@node ifile spam filtering
+@subsubsection ifile spam filtering
+@cindex spam filtering
+@cindex ifile, spam filtering
+@cindex spam
+
+@defvar spam-use-ifile
+
+Enable this variable if you want @code{spam-split} to use @command{ifile}, a
+statistical analyzer similar to Bogofilter.
+
+@end defvar
+
+@defvar spam-ifile-all-categories
+
+Enable this variable if you want @code{spam-use-ifile} to give you all
+the ifile categories, not just spam/non-spam.  If you use this, make
+sure you train ifile as described in its documentation.
+
+@end defvar
+
+@defvar spam-ifile-spam-category
+
+This is the category of spam messages as far as ifile is concerned.
+The actual string used is irrelevant, but you probably want to leave
+the default value of @samp{spam}.
+@end defvar
+
+@defvar spam-ifile-database-path
+
+This is the filename for the ifile database.  It is not specified by
+default, so ifile will use its own default database name.
+
+@end defvar
+
+The ifile mail classifier is similar to Bogofilter in intent and
+purpose.  A ham and a spam processor are provided, plus the
+@code{spam-use-ifile} variable to indicate to spam-split that ifile
+should be used.  The 1.2.1 version of ifile was used to test this
+functionality.
+
+@node spam-stat spam filtering
+@subsubsection spam-stat spam filtering
+@cindex spam filtering
+@cindex spam-stat, spam filtering
+@cindex spam-stat
+@cindex spam
+
+@xref{Filtering Spam Using Statistics with spam-stat}.
+
+@defvar spam-use-stat
+
+Enable this variable if you want @code{spam-split} to use
+spam-stat.el, an Emacs Lisp statistical analyzer.
+
+@end defvar
+
+@defvar gnus-group-spam-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the spam-marked
+articles will be added to the spam-stat database of spam messages.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-spam-exit-processor-stat}, it is recommended
+that you use @code{'(spam spam-use-stat)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-stat
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameters or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is
+added to a group's @code{spam-process} parameter, the ham-marked
+articles in @emph{ham} groups will be added to the spam-stat database
+of non-spam messages.  Note that this ham processor has no effect in
+@emph{spam} or @emph{unclassified} groups.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-ham-exit-processor-stat}, it is recommended
+that you use @code{'(ham spam-use-stat)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+This enables @file{spam.el} to cooperate with @file{spam-stat.el}.
+@file{spam-stat.el} provides an internal (Lisp-only) spam database,
+which unlike ifile or Bogofilter does not require external programs.
+A spam and a ham processor, and the @code{spam-use-stat} variable for
+@code{spam-split} are provided.
+
+@node SpamOracle
+@subsubsection Using SpamOracle with Gnus
+@cindex spam filtering
+@cindex SpamOracle
+@cindex spam
+
+An easy way to filter out spam is to use SpamOracle.  SpamOracle is an
+statistical mail filtering tool written by Xavier Leroy and needs to be
+installed separately.
+
+There are several ways to use SpamOracle with Gnus.  In all cases, your
+mail is piped through SpamOracle in its @emph{mark} mode.  SpamOracle will
+then enter an @samp{X-Spam} header indicating whether it regards the
+mail as a spam mail or not.
+
+One possibility is to run SpamOracle as a @code{:prescript} from the
+@xref{Mail Source Specifiers}, (@pxref{SpamAssassin}).  This method has
+the advantage that the user can see the @emph{X-Spam} headers.
+
+The easiest method is to make @file{spam.el} (@pxref{Filtering Spam
+Using The Spam ELisp Package}) call SpamOracle.
+
+@vindex spam-use-spamoracle
+To enable SpamOracle usage by @file{spam.el}, set the variable
+@code{spam-use-spamoracle} to @code{t} and configure the
+@code{nnmail-split-fancy} or @code{nnimap-split-fancy} as described in
+the section @xref{Filtering Spam Using The Spam ELisp Package}.  In
+this example the @samp{INBOX} of an nnimap server is filtered using
+SpamOracle.  Mails recognized as spam mails will be moved to
+@code{spam-split-group}, @samp{Junk} in this case.  Ham messages stay
+in @samp{INBOX}:
+
+@example
+(setq spam-use-spamoracle t
+      spam-split-group "Junk"
+      nnimap-split-inbox '("INBOX")
+      nnimap-split-rule 'nnimap-split-fancy
+      nnimap-split-fancy '(| (: spam-split) "INBOX"))
+@end example
+
+@defvar spam-use-spamoracle
+Set to @code{t} if you want Gnus to enable spam filtering using
+SpamOracle.
+@end defvar
+
+@defvar spam-spamoracle-binary
+Gnus uses the SpamOracle binary called @file{spamoracle} found in the
+user's PATH.  Using the variable @code{spam-spamoracle-binary}, this
+can be customized.
+@end defvar
+
+@defvar spam-spamoracle-database
+By default, SpamOracle uses the file @file{~/.spamoracle.db} as a database to
+store its analyses.  This is controlled by the variable
+@code{spam-spamoracle-database} which defaults to @code{nil}.  That means
+the default SpamOracle database will be used.  In case you want your
+database to live somewhere special, set
+@code{spam-spamoracle-database} to this path.
+@end defvar
+
+SpamOracle employs a statistical algorithm to determine whether a
+message is spam or ham.  In order to get good results, meaning few
+false hits or misses, SpamOracle needs training.  SpamOracle learns the
+characteristics of your spam mails.  Using the @emph{add} mode
+(training mode) one has to feed good (ham) and spam mails to
+SpamOracle.  This can be done by pressing @kbd{|} in the Summary buffer
+and pipe the mail to a SpamOracle process or using @file{spam.el}'s
+spam- and ham-processors, which is much more convenient.  For a
+detailed description of spam- and ham-processors, @xref{Filtering Spam
+Using The Spam ELisp Package}.
+
+@defvar gnus-group-spam-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is added
+to a group's @code{spam-process} parameter, spam-marked articles will be
+sent to SpamOracle as spam samples.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-spam-exit-processor-spamoracle}, it is recommended
+that you use @code{'(spam spam-use-spamoracle)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+@defvar gnus-group-ham-exit-processor-spamoracle
+Add this symbol to a group's @code{spam-process} parameter by
+customizing the group parameter or the
+@code{gnus-spam-process-newsgroups} variable.  When this symbol is added
+to a grup's @code{spam-process} parameter, the ham-marked articles in
+@emph{ham} groups will be sent to the SpamOracle as samples of ham
+messages.  Note that this ham processor has no effect in @emph{spam} or
+@emph{unclassified} groups.
+
+@emph{WARNING} 
+
+Instead of the obsolete
+@code{gnus-group-ham-exit-processor-spamoracle}, it is recommended
+that you use @code{'(ham spam-use-spamoracle)}.  Everything will work
+the same way, we promise.
+@end defvar
+
+@emph{Example:} These are the Group Parameters of a group that has been
+classified as a ham group, meaning that it should only contain ham
+messages.
+@example
+ ((spam-contents gnus-group-spam-classification-ham)
+  (spam-process ((ham spam-use-spamoracle)
+                 (spam spam-use-spamoracle))))
+@end example
+For this group the @code{spam-use-spamoracle} is installed for both
+ham and spam processing.  If the group contains spam message
+(e.g. because SpamOracle has not had enough sample messages yet) and
+the user marks some messages as spam messages, these messages will be
+processed by SpamOracle.  The processor sends the messages to
+SpamOracle as new samples for spam.
+
+@node Extending the Spam ELisp package
+@subsubsection Extending the Spam ELisp package
+@cindex spam filtering
+@cindex spam elisp package, extending
+@cindex extending the spam elisp package
+
+Say you want to add a new back end called blackbox.  For filtering
+incoming mail, provide the following:
+
+@enumerate
+
+@item
+code
+
+@lisp
+(defvar spam-use-blackbox nil
+  "True if blackbox should be used.")
+@end lisp
+
+Add
+@example
+    (spam-use-blackbox   . spam-check-blackbox)
+@end example
+to @code{spam-list-of-checks}.
+
+Add
+@example
+    (gnus-group-ham-exit-processor-blackbox     ham spam-use-blackbox)
+    (gnus-group-spam-exit-processor-blackbox    spam spam-use-blackbox)
+@end example
+to @code{spam-list-of-processors}.
+
+Add
+@example
+    (spam-use-blackbox  spam-blackbox-register-routine
+                 nil
+                 spam-blackbox-unregister-routine
+                 nil)
+@end example
+to @code{spam-registration-functions}.  Write the register/unregister
+routines using the bogofilter register/unregister routines as a
+start, or other restister/unregister routines more appropriate to
+Blackbox.
+
+@item
+functionality
+
+Write the @code{spam-check-blackbox} function.  It should return
+@samp{nil} or @code{spam-split-group}, observing the other
+conventions.  See the existing @code{spam-check-*} functions for
+examples of what you can do, and stick to the template unless you
+fully understand the reasons why you aren't.
+
+Make sure to add @code{spam-use-blackbox} to
+@code{spam-list-of-statistical-checks} if Blackbox is a statistical
+mail analyzer that needs the full message body to operate.
+
+@end enumerate
+
+For processing spam and ham messages, provide the following:
+
+@enumerate
+
+@item
+code
+
+Note you don't have to provide a spam or a ham processor.  Only
+provide them if Blackbox supports spam or ham processing.
+
+Also, ham and spam processors are being phased out as single
+variables.  Instead the form @code{'(spam spam-use-blackbox)} or 
+@code{'(ham spam-use-blackbox)} is favored.  For now, spam/ham
+processor variables are still around but they won't be for long.
+
+@lisp
+(defvar gnus-group-spam-exit-processor-blackbox "blackbox-spam"
+  "The Blackbox summary exit spam processor.
+Only applicable to spam groups.")
+
+(defvar gnus-group-ham-exit-processor-blackbox "blackbox-ham"
+  "The whitelist summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+@end lisp
 
 @item
-David Moore---rewrite of @file{nnvirtual.el} and many other things. 
+Gnus parameters
+
+Add
+@example
+                   (const :tag "Spam: Blackbox"   (spam spam-use-blackbox))
+                   (const :tag "Ham: Blackbox"    (ham spam-use-blackbox))
+@end example
+to the @code{spam-process} group parameter in @code{gnus.el}.  Make
+sure you do it twice, once for the parameter and once for the
+variable customization.
+
+Add
+@example
+          (variable-item spam-use-blackbox)
+@end example
+to the @code{spam-autodetect-methods} group parameter in
+@code{gnus.el}.
+
+@end enumerate
+
+
+@node Filtering Spam Using Statistics with spam-stat
+@subsection Filtering Spam Using Statistics with spam-stat
+@cindex Paul Graham
+@cindex Graham, Paul
+@cindex naive Bayesian spam filtering
+@cindex Bayesian spam filtering, naive
+@cindex spam filtering, naive Bayesian
+
+Paul Graham has written an excellent essay about spam filtering using
+statistics: @uref{http://www.paulgraham.com/spam.html,A Plan for
+Spam}.  In it he describes the inherent deficiency of rule-based
+filtering as used by SpamAssassin, for example: Somebody has to write
+the rules, and everybody else has to install these rules.  You are
+always late.  It would be much better, he argues, to filter mail based
+on whether it somehow resembles spam or non-spam.  One way to measure
+this is word distribution.  He then goes on to describe a solution
+that checks whether a new mail resembles any of your other spam mails
+or not.
+
+The basic idea is this:  Create a two collections of your mail, one
+with spam, one with non-spam.  Count how often each word appears in
+either collection, weight this by the total number of mails in the
+collections, and store this information in a dictionary.  For every
+word in a new mail, determine its probability to belong to a spam or a
+non-spam mail.  Use the 15 most conspicuous words, compute the total
+probability of the mail being spam.  If this probability is higher
+than a certain threshold, the mail is considered to be spam.
+
+Gnus supports this kind of filtering.  But it needs some setting up.
+First, you need two collections of your mail, one with spam, one with
+non-spam.  Then you need to create a dictionary using these two
+collections, and save it.  And last but not least, you need to use
+this dictionary in your fancy mail splitting rules.
+
+@menu
+* Creating a spam-stat dictionary::
+* Splitting mail using spam-stat::
+* Low-level interface to the spam-stat dictionary::
+@end menu
+
+@node Creating a spam-stat dictionary
+@subsubsection Creating a spam-stat dictionary
+
+Before you can begin to filter spam based on statistics, you must
+create these statistics based on two mail collections, one with spam,
+one with non-spam.  These statistics are then stored in a dictionary
+for later use.  In order for these statistics to be meaningful, you
+need several hundred emails in both collections.
+
+Gnus currently supports only the nnml back end for automated dictionary
+creation.  The nnml back end stores all mails in a directory, one file
+per mail.  Use the following:
+
+@defun spam-stat-process-spam-directory
+Create spam statistics for every file in this directory.  Every file
+is treated as one spam mail.
+@end defun
+
+@defun spam-stat-process-non-spam-directory
+Create non-spam statistics for every file in this directory.  Every
+file is treated as one non-spam mail.
+@end defun
+
+Usually you would call @code{spam-stat-process-spam-directory} on a
+directory such as @file{~/Mail/mail/spam} (this usually corresponds
+the the group @samp{nnml:mail.spam}), and you would call
+@code{spam-stat-process-non-spam-directory} on a directory such as
+@file{~/Mail/mail/misc} (this usually corresponds the the group
+@samp{nnml:mail.misc}).
+
+When you are using @acronym{IMAP}, you won't have the mails available
+locally, so that will not work.  One solution is to use the Gnus Agent
+to cache the articles.  Then you can use directories such as
+@file{"~/News/agent/nnimap/mail.yourisp.com/personal_spam"} for
+@code{spam-stat-process-spam-directory}.  @xref{Agent as Cache}.
+
+@defvar spam-stat
+This variable holds the hash-table with all the statistics---the
+dictionary we have been talking about.  For every word in either
+collection, this hash-table stores a vector describing how often the
+word appeared in spam and often it appeared in non-spam mails.
+@end defvar
+
+If you want to regenerate the statistics from scratch, you need to
+reset the dictionary.
+
+@defun spam-stat-reset
+Reset the @code{spam-stat} hash-table, deleting all the statistics.
+@end defun
+
+When you are done, you must save the dictionary.  The dictionary may
+be rather large.  If you will not update the dictionary incrementally
+(instead, you will recreate it once a month, for example), then you
+can reduce the size of the dictionary by deleting all words that did
+not appear often enough or that do not clearly belong to only spam or
+only non-spam mails.
+
+@defun spam-stat-reduce-size
+Reduce the size of the dictionary.  Use this only if you do not want
+to update the dictionary incrementally.
+@end defun
+
+@defun spam-stat-save
+Save the dictionary.
+@end defun
+
+@defvar spam-stat-file
+The filename used to store the dictionary.  This defaults to
+@file{~/.spam-stat.el}.
+@end defvar
+
+@node Splitting mail using spam-stat
+@subsubsection Splitting mail using spam-stat
+
+In order to use @code{spam-stat} to split your mail, you need to add the
+following to your @file{~/.gnus.el} file:
+
+@lisp
+(require 'spam-stat)
+(spam-stat-load)
+@end lisp
+
+This will load the necessary Gnus code, and the dictionary you
+created.
+
+Next, you need to adapt your fancy splitting rules:  You need to
+determine how to use @code{spam-stat}.  The following examples are for
+the nnml back end.  Using the nnimap back end works just as well.  Just
+use @code{nnimap-split-fancy} instead of @code{nnmail-split-fancy}.
+
+In the simplest case, you only have two groups, @samp{mail.misc} and
+@samp{mail.spam}.  The following expression says that mail is either
+spam or it should go into @samp{mail.misc}.  If it is spam, then
+@code{spam-stat-split-fancy} will return @samp{mail.spam}.
+
+@lisp
+(setq nnmail-split-fancy
+      `(| (: spam-stat-split-fancy)
+          "mail.misc"))
+@end lisp
+
+@defvar spam-stat-split-fancy-spam-group
+The group to use for spam.  Default is @samp{mail.spam}.
+@end defvar
+
+If you also filter mail with specific subjects into other groups, use
+the following expression.  Only mails not matching the regular
+expression are considered potential spam.
+
+@lisp
+(setq nnmail-split-fancy
+      `(| ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          (: spam-stat-split-fancy)
+          "mail.misc"))
+@end lisp
+
+If you want to filter for spam first, then you must be careful when
+creating the dictionary.  Note that @code{spam-stat-split-fancy} must
+consider both mails in @samp{mail.emacs} and in @samp{mail.misc} as
+non-spam, therefore both should be in your collection of non-spam
+mails, when creating the dictionary!
+
+@lisp
+(setq nnmail-split-fancy
+      `(| (: spam-stat-split-fancy)
+          ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          "mail.misc"))
+@end lisp
+
+You can combine this with traditional filtering.  Here, we move all
+HTML-only mails into the @samp{mail.spam.filtered} group.  Note that since
+@code{spam-stat-split-fancy} will never see them, the mails in
+@samp{mail.spam.filtered} should be neither in your collection of spam mails,
+nor in your collection of non-spam mails, when creating the
+dictionary!
+
+@lisp
+(setq nnmail-split-fancy
+      `(| ("Content-Type" "text/html" "mail.spam.filtered")
+          (: spam-stat-split-fancy)
+          ("Subject" "\\bspam-stat\\b" "mail.emacs")
+          "mail.misc"))
+@end lisp
+
+
+@node Low-level interface to the spam-stat dictionary
+@subsubsection Low-level interface to the spam-stat dictionary
+
+The main interface to using @code{spam-stat}, are the following functions:
+
+@defun spam-stat-buffer-is-spam
+Called in a buffer, that buffer is considered to be a new spam mail.
+Use this for new mail that has not been processed before.
+@end defun
+
+@defun spam-stat-buffer-is-no-spam
+Called in a buffer, that buffer is considered to be a new non-spam
+mail.  Use this for new mail that has not been processed before.
+@end defun
+
+@defun spam-stat-buffer-change-to-spam
+Called in a buffer, that buffer is no longer considered to be normal
+mail but spam.  Use this to change the status of a mail that has
+already been processed as non-spam.
+@end defun
+
+@defun spam-stat-buffer-change-to-non-spam
+Called in a buffer, that buffer is no longer considered to be spam but
+normal mail.  Use this to change the status of a mail that has already
+been processed as spam.
+@end defun
+
+@defun spam-stat-save
+Save the hash table to the file.  The filename used is stored in the
+variable @code{spam-stat-file}.
+@end defun
+
+@defun spam-stat-load
+Load the hash table from a file.  The filename used is stored in the
+variable @code{spam-stat-file}.
+@end defun
+
+@defun spam-stat-score-word
+Return the spam score for a word.
+@end defun
+
+@defun spam-stat-score-buffer
+Return the spam score for a buffer.
+@end defun
+
+@defun spam-stat-split-fancy
+Use this function for fancy mail splitting.  Add the rule @samp{(:
+spam-stat-split-fancy)} to @code{nnmail-split-fancy}
+@end defun
+
+Make sure you load the dictionary before using it.  This requires the
+following in your @file{~/.gnus.el} file:
+
+@lisp
+(require 'spam-stat)
+(spam-stat-load)
+@end lisp
 
-@item 
-Kevin Davidson---came up with the name @dfn{ding}, so blame him.
+Typical test will involve calls to the following functions:
+
+@smallexample
+Reset: (setq spam-stat (make-hash-table :test 'equal))
+Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+Save table: (spam-stat-save)
+File size: (nth 7 (file-attributes spam-stat-file))
+Number of words: (hash-table-count spam-stat)
+Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+Reduce table size: (spam-stat-reduce-size)
+Save table: (spam-stat-save)
+File size: (nth 7 (file-attributes spam-stat-file))
+Number of words: (hash-table-count spam-stat)
+Test spam: (spam-stat-test-directory "~/Mail/mail/spam")
+Test non-spam: (spam-stat-test-directory "~/Mail/mail/misc")
+@end smallexample
+
+Here is how you would create your dictionary:
+
+@smallexample
+Reset: (setq spam-stat (make-hash-table :test 'equal))
+Learn spam: (spam-stat-process-spam-directory "~/Mail/mail/spam")
+Learn non-spam: (spam-stat-process-non-spam-directory "~/Mail/mail/misc")
+Repeat for any other non-spam group you need...
+Reduce table size: (spam-stat-reduce-size)
+Save table: (spam-stat-save)
+@end smallexample
+
+@node Other modes
+@section Interaction with other modes
+
+@subsection Dired
+@cindex dired
+
+@code{gnus-dired-minor-mode} provided some useful functions for dired
+buffers.  It is enabled with
+@lisp
+(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
+@end lisp
 
-@item
-François Pinard---many, many interesting and thorough bug reports.
+@table @kbd
+@item C-c C-m C-a
+@findex gnus-dired-attach
+Send dired's marked files as an attachment (@code{gnus-dired-attach}).
+You will be prompted for a message buffer.
+
+@item C-c C-m C-l
+@findex gnus-dired-find-file-mailcap
+Visit a file according to the appropriate mailcap entry
+(@code{gnus-dired-find-file-mailcap}).  With prefix, open file in a new
+buffer.
 
-@end itemize
+@item C-c C-m C-p
+@findex gnus-dired-print
+Print file according to the mailcap entry (@code{gnus-dired-print}).  If
+there is no print command, print in a PostScript image.
+@end table
 
-This manual was proof-read by Adrian Aichner, with Ricardo Nassif, Mark
-Borges, and Jost Krieger proof-reading parts of the manual.
+@node Various Various
+@section Various Various
+@cindex mode lines
+@cindex highlights
 
-The following people have contributed many patches and suggestions: 
+@table @code
 
-Christopher Davis,
-Andrew Eskilsson,
-Kai Grossjohann,
-David KÃ¥gedal,
-Richard Pieri,
-Fabrice Popineau, 
-Daniel Quinlan, 
-Jason L. Tibbitts, III,
-and
-Jack Vinson.
+@item gnus-home-directory
+@vindex gnus-home-directory
+All Gnus file and directory variables will be initialized from this
+variable, which defaults to @file{~/}.
 
-Also thanks to the following for patches and stuff:
+@item gnus-directory
+@vindex gnus-directory
+Most Gnus storage file and directory variables will be initialized from
+this variable, which defaults to the @env{SAVEDIR} environment
+variable, or @file{~/News/} if that variable isn't set.
 
-Jari Aalto,
-Adrian Aichner,
-Russ Allbery,
-Peter Arius, 
-Matt Armstrong,
-Marc Auslander,
-Robert Bihlmeyer,
-Chris Bone,
-Mark Borges,
-Mark Boyns,
-Lance A. Brown,
-Kees de Bruin,
-Martin Buchholz,
-Kevin Buhr,
-Alastair Burt,
-Joao Cachopo,
-Zlatko Calusic,
-Massimo Campostrini,
-Dan Christensen,
-Michael R. Cook,
-Glenn Coombs, 
-Frank D. Cringle, 
-Geoffrey T. Dairiki,
-Andre Deparade,
-Ulrik Dickow,
-Dave Disser,
-Joev Dubach,
-Michael Welsh Duggan,
-Dave Edmondson,
-Paul Eggert,
-Enami Tsugutomo, @c Enami
-Michael Ernst,
-Luc Van Eycken,
-Sam Falkner,
-Nelson Jose dos Santos Ferreira,
-Sigbjorn Finne,
-Gary D. Foster,
-Paul Franklin, 
-Guy Geens,
-Arne Georg Gleditsch,
-David S. Goldberg,
-Michelangelo Grigni,
-D. Hall, 
-Magnus Hammerin,
-Kenichi Handa, @c Handa
-Raja R. Harinath,
-Hisashige Kenji, @c Hisashige
-Marc Horowitz,
-Gunnar Horrigmo,
-Richard Hoskins,
-Brad Howes,
-François Felix Ingrand,
-Ishikawa Ichiro, @c Ishikawa
-Lee Iverson, 
-Iwamuro Motonori, @c Iwamuro
-Rajappa Iyer,
-Andreas Jaeger,
-Randell Jesup,
-Fred Johansen, 
-Simon Josefsson,
-Greg Klanderman,
-Karl Kleinpaste,
-Peter Skov Knudsen,
-Shuhei Kobayashi, @c Kobayashi
-Thor Kristoffersen,
-Jens Lautenbacher,
-Seokchan Lee, @c Lee
-Carsten Leonhardt,
-James LewisMoss,
-Christian Limpach,
-Markus Linnala,
-Dave Love,
-Tonny Madsen,
-Shlomo Mahlab,
-Nat Makarevitch,
-Istvan Marko,
-David Martin,
-Gordon Matzigkeit,
-Timo Metzemakers,
-Richard Mlynarik,
-Lantz Moore,
-Morioka Tomohiko, @c Morioka
-Erik Toubro Nielsen,
-Hrvoje Niksic,
-Andy Norman,
-Fred Oberhauser,
-C. R. Oldham,
-Alexandre Oliva,
-Ken Olstad,
-Masaharu Onishi, @c Onishi
-Hideki Ono, @c Ono
-William Perry,
-Stephen Peters,
-Ulrich Pfeifer,
-John McClary Prevost,
-Colin Rafferty,
-Lars Balker Rasmussen,
-Joe Reiss,
-Renaud Rioboo,
-Roland B. Roberts,
-Bart Robinson,
-Christian von Roques,
-Jason Rumney,
-Jay Sachs,
-Dewey M. Sasser,
-Loren Schall,
-Dan Schmidt,
-Ralph Schleicher,
-Philippe Schnoebelen,
-Randal L. Schwartz,
-Justin Sheehy,
-Danny Siu, 
-Matt Simmons,
-Paul D. Smith,
-Jeff Sparkes,
-Toby Speight,
-Michael Sperber,
-Darren Stalder,
-Richard Stallman,
-Greg Stark, 
-Paul Stodghill,
-Kurt Swanson,
-Samuel Tardieu, 
-Teddy,
-Chuck Thompson,
-Philippe Troin,
-James Troup,
-Aaron M. Ucko, 
-Aki Vehtari,
-Didier Verna,
-Jan Vroonhof,
-Stefan Waldherr,
-Pete Ware,
-Barry A. Warsaw,
-Christoph Wedler,
-Joe Wells,
-and
-Katsumi Yamaoka. @c Yamaoka
+Note that gnus is mostly loaded when the @file{.gnus.el} file is read.
+This means that other directory variables that are initialized from this
+variable won't be set properly if you set this variable in
+@file{.gnus.el}.  Set this variable in @file{.emacs} instead.
 
-For a full overview of what each person has done, the ChangeLogs
-included in the Gnus alpha distributions should give ample reading
-(550kB and counting).
+@item gnus-default-directory
+@vindex gnus-default-directory
+Not related to the above variable at all---this variable says what the
+default directory of all Gnus buffers should be.  If you issue commands
+like @kbd{C-x C-f}, the prompt you'll get starts in the current buffer's
+default directory.  If this variable is @code{nil} (which is the
+default), the default directory will be the default directory of the
+buffer you were in when you started Gnus.
 
-Apologies to everybody that I've forgotten, of which there are many, I'm
-sure.  
+@item gnus-verbose
+@vindex gnus-verbose
+This variable is an integer between zero and ten.  The higher the value,
+the more messages will be displayed.  If this variable is zero, Gnus
+will never flash any messages, if it is seven (which is the default),
+most important messages will be shown, and if it is ten, Gnus won't ever
+shut up, but will flash so many messages it will make your head swim.
 
-Gee, that's quite a list of people.  I guess that must mean that there
-actually are people who are using Gnus.  Who'd'a thunk it!
+@item gnus-verbose-backends
+@vindex gnus-verbose-backends
+This variable works the same way as @code{gnus-verbose}, but it applies
+to the Gnus back ends instead of Gnus proper.
 
+@item nnheader-max-head-length
+@vindex nnheader-max-head-length
+When the back ends read straight heads of articles, they all try to read
+as little as possible.  This variable (default 4096) specifies
+the absolute max length the back ends will try to read before giving up
+on finding a separator line between the head and the body.  If this
+variable is @code{nil}, there is no upper read bound.  If it is
+@code{t}, the back ends won't try to read the articles piece by piece,
+but read the entire articles.  This makes sense with some versions of
+@code{ange-ftp} or @code{efs}.
 
-@node New Features
-@subsection New Features
-@cindex new features
+@item nnheader-head-chop-length
+@vindex nnheader-head-chop-length
+This variable (default 2048) says how big a piece of each article to
+read when doing the operation described above.
 
-@menu
-* ding Gnus::          New things in Gnus 5.0/5.1, the first new Gnus.
-* September Gnus::     The Thing Formally Known As Gnus 5.3/5.3.
-* Red Gnus::           Third time best---Gnus 5.4/5.5.
-@end menu
+@item nnheader-file-name-translation-alist
+@vindex nnheader-file-name-translation-alist
+@cindex file names
+@cindex invalid characters in file names
+@cindex characters in file names
+This is an alist that says how to translate characters in file names.
+For instance, if @samp{:} is invalid as a file character in file names
+on your system (you OS/2 user you), you could say something like:
 
-These lists are, of course, just @emph{short} overviews of the
-@emph{most} important new features.  No, really.  There are tons more.
-Yes, we have feeping creaturism in full effect.
+@lisp
+@group
+(setq nnheader-file-name-translation-alist
+      '((?: . ?_)))
+@end group
+@end lisp
 
+In fact, this is the default value for this variable on OS/2 and MS
+Windows (phooey) systems.
 
-@node ding Gnus
-@subsubsection (ding) Gnus
+@item gnus-hidden-properties
+@vindex gnus-hidden-properties
+This is a list of properties to use to hide ``invisible'' text.  It is
+@code{(invisible t intangible t)} by default on most systems, which
+makes invisible text invisible and intangible.
 
-New features in Gnus 5.0/5.1:
+@item gnus-parse-headers-hook
+@vindex gnus-parse-headers-hook
+A hook called before parsing headers.  It can be used, for instance, to
+gather statistics on the headers fetched, or perhaps you'd like to prune
+some headers.  I don't see why you'd want that, though.
 
-@itemize @bullet
+@item gnus-shell-command-separator
+@vindex gnus-shell-command-separator
+String used to separate two shell commands.  The default is @samp{;}.
 
-@item
-The look of all buffers can be changed by setting format-like variables
-(@pxref{Group Buffer Format} and @pxref{Summary Buffer Format}). 
-@item 
-Local spool and several @sc{nntp} servers can be used at once
-(@pxref{Select Methods}).  
+@item gnus-invalid-group-regexp
+@vindex gnus-invalid-group-regexp
 
-@item 
-You can combine groups into virtual groups (@pxref{Virtual Groups}).
+Regexp to match ``invalid'' group names when querying user for a group
+name.  The default value catches some @strong{really} invalid group
+names who could possibly mess up Gnus internally (like allowing
+@samp{:} in a group name, which is normally used to delimit method and
+group).
 
-@item 
-You can read a number of different mail formats (@pxref{Getting Mail}).
-All the mail backends implement a convenient mail expiry scheme
-(@pxref{Expiring Mail}). 
+@acronym{IMAP} users might want to allow @samp{/} in group names though.
 
-@item
-Gnus can use various strategies for gathering threads that have lost
-their roots (thereby gathering loose sub-threads into one thread) or it
-can go back and retrieve enough headers to build a complete thread
-(@pxref{Customizing Threading}).
 
-@item 
-Killed groups can be displayed in the group buffer, and you can read
-them as well (@pxref{Listing Groups}).
+@end table
+
+@node The End
+@chapter The End
+
+Well, that's the manual---you can get on with your life now.  Keep in
+touch.  Say hello to your cats from me.
+
+My @strong{ghod}---I just can't stand goodbyes.  Sniffle.
+
+Ol' Charles Reznikoff said it pretty well, so I leave the floor to him:
+
+@quotation
+@strong{Te Deum}
+
+@sp 1
+Not because of victories @*
+I sing,@*
+having none,@*
+but for the common sunshine,@*
+the breeze,@*
+the largess of the spring.
+
+@sp 1
+Not for victory@*
+but for the day's work done@*
+as well as I was able;@*
+not for a seat upon the dais@*
+but at the common table.@*
+@end quotation
+
 
-@item 
-Gnus can do partial group updates---you do not have to retrieve the
-entire active file just to check for new articles in a few groups
-(@pxref{The Active File}).
+@node Appendices
+@chapter Appendices
 
-@item 
-Gnus implements a sliding scale of subscribedness to groups
-(@pxref{Group Levels}).
+@menu
+* XEmacs::                      Requirements for installing under XEmacs.
+* History::                     How Gnus got where it is today.
+* On Writing Manuals::          Why this is not a beginner's guide.
+* Terminology::                 We use really difficult, like, words here.
+* Customization::               Tailoring Gnus to your needs.
+* Troubleshooting::             What you might try if things do not work.
+* Gnus Reference Guide::        Rilly, rilly technical stuff.
+* Emacs for Heathens::          A short introduction to Emacsian terms.
+* Frequently Asked Questions::  The Gnus FAQ
+@end menu
 
-@item 
-You can score articles according to any number of criteria
-(@pxref{Scoring}).  You can even get Gnus to find out how to score
-articles for you (@pxref{Adaptive Scoring}).
 
-@item 
-Gnus maintains a dribble buffer that is auto-saved the normal Emacs
-manner, so it should be difficult to lose much data on what you have
-read if your machine should go down (@pxref{Auto Save}). 
+@node XEmacs
+@section XEmacs
+@cindex XEmacs
+@cindex installing under XEmacs
 
-@item 
-Gnus now has its own startup file (@file{.gnus}) to avoid cluttering up
-the @file{.emacs} file.
+XEmacs is distributed as a collection of packages.  You should install
+whatever packages the Gnus XEmacs package requires.  The current
+requirements are @samp{gnus}, @samp{mail-lib}, @samp{xemacs-base},
+@samp{eterm}, @samp{sh-script}, @samp{net-utils}, @samp{os-utils},
+@samp{dired}, @samp{mh-e}, @samp{sieve}, @samp{ps-print}, @samp{w3},
+@samp{pgg}, @samp{mailcrypt}, @samp{ecrypto}, and @samp{sasl}.
 
-@item 
-You can set the process mark on both groups and articles and perform
-operations on all the marked items (@pxref{Process/Prefix}).
 
-@item 
-You can grep through a subset of groups and create a group from the
-results (@pxref{Kibozed Groups}). 
+@node History
+@section History
 
-@item 
-You can list subsets of groups according to, well, anything
-(@pxref{Listing Groups}). 
+@cindex history
+@sc{gnus} was written by Masanobu @sc{Umeda}.  When autumn crept up in
+'94, Lars Magne Ingebrigtsen grew bored and decided to rewrite Gnus.
 
-@item 
-You can browse foreign servers and subscribe to groups from those
-servers (@pxref{Browse Foreign Server}). 
+If you want to investigate the person responsible for this outrage,
+you can point your (feh!) web browser to
+@uref{http://quimby.gnus.org/}.  This is also the primary
+distribution point for the new and spiffy versions of Gnus, and is
+known as The Site That Destroys Newsrcs And Drives People Mad.
 
-@item 
-Gnus can fetch articles, asynchronously, on a second connection to the
-server (@pxref{Asynchronous Fetching}).
+During the first extended alpha period of development, the new Gnus was
+called ``(ding) Gnus''.  @dfn{(ding)} is, of course, short for
+@dfn{ding is not Gnus}, which is a total and utter lie, but who cares?
+(Besides, the ``Gnus'' in this abbreviation should probably be
+pronounced ``news'' as @sc{Umeda} intended, which makes it a more
+appropriate name, don't you think?)
 
-@item 
-You can cache articles locally (@pxref{Article Caching}). 
+In any case, after spending all that energy on coming up with a new and
+spunky name, we decided that the name was @emph{too} spunky, so we
+renamed it back again to ``Gnus''.  But in mixed case.  ``Gnus'' vs.
+``@sc{gnus}''.  New vs. old.
 
-@item 
-The uudecode functions have been expanded and generalized
-(@pxref{Decoding Articles}). 
+@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.
+@end menu
 
-@item
-You can still post uuencoded articles, which was a little-known feature
-of @sc{gnus}' past (@pxref{Uuencoding and Posting}). 
 
-@item
-Fetching parents (and other articles) now actually works without
-glitches (@pxref{Finding the Parent}). 
+@node Gnus Versions
+@subsection Gnus Versions
+@cindex ding Gnus
+@cindex September Gnus
+@cindex Red Gnus
+@cindex Quassia Gnus
+@cindex Pterodactyl Gnus
+@cindex Oort Gnus
+@cindex No Gnus
+@cindex Gnus versions
 
-@item
-Gnus can fetch FAQs and group descriptions (@pxref{Group Information}).
+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).
 
-@item
-Digests (and other files) can be used as the basis for groups
-(@pxref{Document Groups}).
+In May 1996 the next Gnus generation (aka. ``September Gnus'' (after 99
+releases)) was released under the name ``Gnus 5.2'' (40 releases).
 
-@item 
-Articles can be highlighted and customized (@pxref{Customizing
-Articles}). 
+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).
 
-@item 
-URLs and other external references can be buttonized (@pxref{Article
-Buttons}). 
+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).
 
-@item
-You can do lots of strange stuff with the Gnus window & frame
-configuration (@pxref{Windows Configuration}).
+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.
 
-@item
-You can click on buttons instead of using the keyboard
-(@pxref{Buttons}). 
+On the 26th of October 2000, Oort Gnus was begun.
 
-@end itemize
+If you happen upon a version of Gnus that has a prefixed name --
+``(ding) Gnus'', ``September Gnus'', ``Red Gnus'', ``Quassia Gnus'',
+``Pterodactyl Gnus'', ``Oort Gnus'' -- don't panic.  Don't let it know
+that you're frightened.  Back away.  Slowly.  Whatever you do, don't
+run.  Walk away, calmly, until you're out of its reach.  Find a proper
+released version of Gnus and snuggle up to that instead.
 
 
-@node September Gnus
-@subsubsection September Gnus
+@node Other Gnus Versions
+@subsection Other Gnus Versions
+@cindex Semi-gnus
 
-@iftex
-@iflatex
-\gnusfig{-28cm}{0cm}{\epsfig{figure=tmp/september.ps,height=20cm}}
-@end iflatex
-@end iftex
+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 @acronym{SEMI}, which provides
+@acronym{MIME} capabilities.
 
-New features in Gnus 5.2/5.3:
+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
+@acronym{MIME} and multilingualization things, especially important for
+Japanese users.
 
-@itemize @bullet
 
-@item
-A new message composition mode is used.  All old customization variables
-for @code{mail-mode}, @code{rnews-reply-mode} and @code{gnus-msg} are
-now obsolete.
+@node Why?
+@subsection Why?
 
-@item
-Gnus is now able to generate @dfn{sparse} threads---threads where
-missing articles are represented by empty nodes (@pxref{Customizing
-Threading}). 
+What's the point of Gnus?
 
-@lisp
-(setq gnus-build-sparse-threads 'some)
-@end lisp
+I want to provide a ``rad'', ``happening'', ``way cool'' and ``hep''
+newsreader, that lets you do anything you can think of.  That was my
+original motivation, but while working on Gnus, it has become clear to
+me that this generation of newsreaders really belong in the stone age.
+Newsreaders haven't developed much since the infancy of the net.  If the
+volume continues to rise with the current rate of increase, all current
+newsreaders will be pretty much useless.  How do you deal with
+newsgroups that have thousands of new articles each day?  How do you
+keep track of millions of people who post?
 
-@item
-Outgoing articles are stored on a special archive server
-(@pxref{Archived Messages}). 
+Gnus offers no real solutions to these questions, but I would very much
+like to see Gnus being used as a testing ground for new methods of
+reading and fetching news.  Expanding on @sc{Umeda}-san's wise decision
+to separate the newsreader from the back ends, Gnus now offers a simple
+interface for anybody who wants to write new back ends for fetching mail
+and news from different sources.  I have added hooks for customizations
+everywhere I could imagine it being useful.  By doing so, I'm inviting
+every one of you to explore and invent.
 
-@item
-Partial thread regeneration now happens when articles are
-referred. 
+May Gnus never be complete.  @kbd{C-u 100 M-x all-hail-emacs} and
+@kbd{C-u 100 M-x all-hail-xemacs}.
 
-@item
-Gnus can make use of GroupLens predictions (@pxref{GroupLens}).
 
-@item
-Picons (personal icons) can be displayed under XEmacs (@pxref{Picons}). 
+@node Compatibility
+@subsection Compatibility
 
-@item
-A @code{trn}-like tree buffer can be displayed (@pxref{Tree Display}).
+@cindex compatibility
+Gnus was designed to be fully compatible with @sc{gnus}.  Almost all key
+bindings have been kept.  More key bindings have been added, of course,
+but only in one or two obscure cases have old bindings been changed.
 
-@lisp
-(setq gnus-use-trees t)
-@end lisp
+Our motto is:
+@quotation
+@cartouche
+@center In a cloud bones of steel.
+@end cartouche
+@end quotation
 
-@item
-An @code{nn}-like pick-and-read minor mode is available for the summary
-buffers (@pxref{Pick and Read}).
+All commands have kept their names.  Some internal functions have changed
+their names.
 
-@lisp
-(add-hook 'gnus-summary-mode-hook 'gnus-pick-mode)
-@end lisp
+The @code{gnus-uu} package has changed drastically.  @xref{Decoding
+Articles}.
 
-@item
-In binary groups you can use a special binary minor mode (@pxref{Binary
-Groups}). 
+One major compatibility question is the presence of several summary
+buffers.  All variables relevant while reading a group are
+buffer-local to the summary buffer they belong in.  Although many
+important variables have their values copied into their global
+counterparts whenever a command is executed in the summary buffer, this
+change might lead to incorrect values being used unless you are careful.
 
-@item
-Groups can be grouped in a folding topic hierarchy (@pxref{Group
-Topics}).
+All code that relies on knowledge of @sc{gnus} internals will probably
+fail.  To take two examples: Sorting @code{gnus-newsrc-alist} (or
+changing it in any way, as a matter of fact) is strictly verboten.  Gnus
+maintains a hash table that points to the entries in this alist (which
+speeds up many functions), and changing the alist directly will lead to
+peculiar results.
 
-@lisp
-(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
-@end lisp
+@cindex hilit19
+@cindex highlighting
+Old hilit19 code does not work at all.  In fact, you should probably
+remove all hilit code from all Gnus hooks
+(@code{gnus-group-prepare-hook} and @code{gnus-summary-prepare-hook}).
+Gnus provides various integrated functions for highlighting.  These are
+faster and more accurate.  To make life easier for everybody, Gnus will
+by default remove all hilit calls from all hilit hooks.  Uncleanliness!
+Away!
 
-@item
-Gnus can re-send and bounce mail (@pxref{Summary Mail Commands}).
+Packages like @code{expire-kill} will no longer work.  As a matter of
+fact, you should probably remove all old @sc{gnus} packages (and other
+code) when you start using Gnus.  More likely than not, Gnus already
+does what you have written code to make @sc{gnus} do.  (Snicker.)
 
-@item
-Groups can now have a score, and bubbling based on entry frequency
-is possible (@pxref{Group Score}).
+Even though old methods of doing things are still supported, only the
+new methods are documented in this manual.  If you detect a new method of
+doing something while reading this manual, that does not mean you have
+to stop doing it the old way.
 
-@lisp
-(add-hook 'gnus-summary-exit-hook 'gnus-summary-bubble-group)
-@end lisp
+Gnus understands all @sc{gnus} startup files.
 
-@item
-Groups can be process-marked, and commands can be performed on
-groups of groups (@pxref{Marking Groups}).
+@kindex M-x gnus-bug
+@findex gnus-bug
+@cindex reporting bugs
+@cindex bugs
+Overall, a casual user who hasn't written much code that depends on
+@sc{gnus} internals should suffer no problems.  If problems occur,
+please let me know by issuing that magic command @kbd{M-x gnus-bug}.
 
-@item
-Caching is possible in virtual groups.
+@vindex gnus-bug-create-help-buffer
+If you are in the habit of sending bug reports @emph{very} often, you
+may find the helpful help buffer annoying after a while.  If so, set
+@code{gnus-bug-create-help-buffer} to @code{nil} to avoid having it pop
+up at you.
 
-@item
-@code{nndoc} now understands all kinds of digests, mail boxes, rnews
-news batches, ClariNet briefs collections, and just about everything
-else (@pxref{Document Groups}).
 
-@item
-Gnus has a new backend (@code{nnsoup}) to create/read SOUP packets
-(@pxref{SOUP}).
+@node Conformity
+@subsection Conformity
 
-@item
-The Gnus cache is much faster.
+No rebels without a clue here, ma'am.  We conform to all standards known
+to (wo)man.  Except for those standards and/or conventions we disagree
+with, of course.
 
-@item
-Groups can be sorted according to many criteria (@pxref{Sorting
-Groups}).
+@table @strong
 
-@item
-New group parameters have been introduced to set list-addresses and
-expiry times (@pxref{Group Parameters}).
+@item RFC (2)822
+@cindex RFC 822
+@cindex RFC 2822
+There are no known breaches of this standard.
 
-@item
-All formatting specs allow specifying faces to be used
-(@pxref{Formatting Fonts}).
+@item RFC 1036
+@cindex RFC 1036
+There are no known breaches of this standard, either.
 
-@item
-There are several more commands for setting/removing/acting on process
-marked articles on the @kbd{M P} submap (@pxref{Setting Process Marks}).
+@item Son-of-RFC 1036
+@cindex Son-of-RFC 1036
+We do have some breaches to this one.
 
-@item
-The summary buffer can be limited to show parts of the available
-articles based on a wide range of criteria.  These commands have been
-bound to keys on the @kbd{/} submap (@pxref{Limiting}).
+@table @emph
 
-@item
-Articles can be made persistent with the @kbd{*} command
-(@pxref{Persistent Articles}).
+@item X-Newsreader
+@itemx User-Agent
+These are considered to be ``vanity headers'', while I consider them
+to be consumer information.  After seeing so many badly formatted
+articles coming from @code{tin} and @code{Netscape} I know not to use
+either of those for posting articles.  I would not have known that if
+it wasn't for the @code{X-Newsreader} header.
+@end table
 
-@item
-All functions for hiding article elements are now toggles.
+@item USEFOR
+@cindex USEFOR
+USEFOR is an IETF working group writing a successor to RFC 1036, based
+on Son-of-RFC 1036.  They have produced a number of drafts proposing
+various changes to the format of news articles.  The Gnus towers will
+look into implementing the changes when the draft is accepted as an RFC.
+
+@item MIME - RFC 2045-2049 etc
+@cindex @acronym{MIME}
+All the various @acronym{MIME} RFCs are supported.
+
+@item Disposition Notifications - RFC 2298
+Message Mode is able to request notifications from the receiver.
+
+@item PGP - RFC 1991 and RFC 2440
+@cindex RFC 1991
+@cindex RFC 2440
+RFC 1991 is the original @acronym{PGP} message specification,
+published as an informational RFC.  RFC 2440 was the follow-up, now
+called Open PGP, and put on the Standards Track.  Both document a
+non-@acronym{MIME} aware @acronym{PGP} format.  Gnus supports both
+encoding (signing and encryption) and decoding (verification and
+decryption).
+
+@item PGP/MIME - RFC 2015/3156
+RFC 2015 (superseded by 3156 which references RFC 2440 instead of RFC
+1991) describes the @acronym{MIME}-wrapping around the RF 1991/2440 format.
+Gnus supports both encoding and decoding.
+
+@item S/MIME - RFC 2633
+RFC 2633 describes the @acronym{S/MIME} format.
+
+@item IMAP - RFC 1730/2060, RFC 2195, RFC 2086, RFC 2359, RFC 2595, RFC 1731
+RFC 1730 is @acronym{IMAP} version 4, updated somewhat by RFC 2060
+(@acronym{IMAP} 4 revision 1).  RFC 2195 describes CRAM-MD5
+authentication for @acronym{IMAP}.  RFC 2086 describes access control
+lists (ACLs) for @acronym{IMAP}.  RFC 2359 describes a @acronym{IMAP}
+protocol enhancement.  RFC 2595 describes the proper @acronym{TLS}
+integration (STARTTLS) with @acronym{IMAP}.  RFC 1731 describes the
+GSSAPI/Kerberos4 mechanisms for @acronym{IMAP}.
 
-@item
-Article headers can be buttonized (@pxref{Article Washing}).
+@end table
 
-@lisp
-(add-hook 'gnus-article-display-hook 
-          'gnus-article-add-buttons-to-head)
-@end lisp
+If you ever notice Gnus acting non-compliant with regards to the texts
+mentioned above, don't hesitate to drop a note to Gnus Towers and let us
+know.
 
-@item
-All mail backends support fetching articles by @code{Message-ID}.
 
-@item
-Duplicate mail can now be treated properly (@pxref{Duplicates}).
+@node Emacsen
+@subsection Emacsen
+@cindex Emacsen
+@cindex XEmacs
+@cindex Mule
+@cindex Emacs
 
-@item
-All summary mode commands are available directly from the article
-buffer (@pxref{Article Keymap}). 
+Gnus should work on:
 
-@item
-Frames can be part of @code{gnus-buffer-configuration} (@pxref{Windows
-Configuration}).
+@itemize @bullet
 
 @item
-Mail can be re-scanned by a daemonic process (@pxref{Daemons}).
-@iftex
-@iflatex
-\marginpar[\mbox{}\hfill\epsfig{figure=tmp/fseptember.ps,height=5cm}]{\epsfig{figure=tmp/fseptember.ps,height=5cm}}
-@end iflatex
-@end iftex
+Emacs 20.3 and up.
 
 @item
-Gnus can make use of NoCeM files to weed out spam (@pxref{NoCeM}).
+XEmacs 21.1.1 and up.
 
-@lisp
-(setq gnus-use-nocem t)
-@end lisp
+@end itemize
 
-@item
-Groups can be made permanently visible (@pxref{Listing Groups}).
+This Gnus version will absolutely not work on any Emacsen older than
+that.  Not reliably, at least.  Older versions of Gnus may work on older
+Emacs versions.  However, T-gnus does support ``Mule 2.3 based on Emacs
+19.34'' and possibly the versions of XEmacs prior to 21.1.1, e.g. 20.4.
+See the file ``README'' in the T-gnus distribution for more details.
 
-@lisp
-(setq gnus-permanently-visible-groups "^nnml:")
-@end lisp
+There are some vague differences between Gnus on the various
+platforms---XEmacs features more graphics (a logo and a toolbar)---but
+other than that, things should look pretty much the same under all
+Emacsen.
+
+
+@node Gnus Development
+@subsection Gnus Development
+
+Gnus is developed in a two-phased cycle.  The first phase involves much
+discussion on the @samp{ding@@gnus.org} mailing list, where people
+propose changes and new features, post patches and new back ends.  This
+phase is called the @dfn{alpha} phase, since the Gnusae released in this
+phase are @dfn{alpha releases}, or (perhaps more commonly in other
+circles) @dfn{snapshots}.  During this phase, Gnus is assumed to be
+unstable and should not be used by casual users.  Gnus alpha releases
+have names like ``Red Gnus'' and ``Quassia Gnus''.
+
+After futzing around for 50-100 alpha releases, Gnus is declared
+@dfn{frozen}, and only bug fixes are applied.  Gnus loses the prefix,
+and is called things like ``Gnus 5.6.32'' instead.  Normal people are
+supposed to be able to use these, and these are mostly discussed on the
+@samp{gnu.emacs.gnus} newsgroup.
+
+@cindex Incoming*
+@vindex mail-source-delete-incoming
+Some variable defaults differ between alpha Gnusae and released Gnusae.
+In particular, @code{mail-source-delete-incoming} defaults to @code{nil} in
+alpha Gnusae and @code{t} in released Gnusae.  This is to prevent
+lossage of mail if an alpha release hiccups while handling the mail.
+
+The division of discussion between the ding mailing list and the Gnus
+newsgroup is not purely based on publicity concerns.  It's true that
+having people write about the horrible things that an alpha Gnus release
+can do (sometimes) in a public forum may scare people off, but more
+importantly, talking about new experimental features that have been
+introduced may confuse casual users.  New features are frequently
+introduced, fiddled with, and judged to be found wanting, and then
+either discarded or totally rewritten.  People reading the mailing list
+usually keep up with these rapid changes, while people on the newsgroup
+can't be assumed to do so.
 
-@item
-Many new hooks have been introduced to make customizing easier. 
 
-@item
-Gnus respects the @code{Mail-Copies-To} header.
 
-@item
-Threads can be gathered by looking at the @code{References} header
-(@pxref{Customizing Threading}).
+@node Contributors
+@subsection Contributors
+@cindex contributors
 
-@lisp
-(setq gnus-summary-thread-gathering-function 
-      'gnus-gather-threads-by-references)
-@end lisp
+The new Gnus version couldn't have been done without the help of all the
+people on the (ding) mailing list.  Every day for over a year I have
+gotten billions of nice bug reports from them, filling me with joy,
+every single one of them.  Smooches.  The people on the list have been
+tried beyond endurance, what with my ``oh, that's a neat idea <type
+type>, yup, I'll release it right away <ship off> no wait, that doesn't
+work at all <type type>, yup, I'll ship that one off right away <ship
+off> no, wait, that absolutely does not work'' policy for releases.
+Micro$oft---bah.  Amateurs.  I'm @emph{much} worse.  (Or is that
+``worser''? ``much worser''?  ``worsest''?)
 
-@item
-Read articles can be stored in a special backlog buffer to avoid
-refetching (@pxref{Article Backlog}).  
+I would like to take this opportunity to thank the Academy for@dots{}  oops,
+wrong show.
 
-@lisp
-(setq gnus-keep-backlog 50)
-@end lisp
+@itemize @bullet
 
 @item
-A clean copy of the current article is always stored in a separate
-buffer to allow easier treatment.
+Masanobu @sc{Umeda}---the writer of the original @sc{gnus}.
 
 @item
-Gnus can suggest where to save articles (@pxref{Saving Articles}).
+Shenghuo Zhu---uudecode.el, mm-uu.el, rfc1843.el, webmail.el,
+nnwarchive and many, many other things connected with @acronym{MIME} and
+other types of en/decoding, as well as general bug fixing, new
+functionality and stuff.
 
 @item
-Gnus doesn't have to do as much prompting when saving (@pxref{Saving
-Articles}). 
-
-@lisp
-(setq gnus-prompt-before-saving t)
-@end lisp
+Per Abrahamsen---custom, scoring, highlighting and @sc{soup} code (as
+well as numerous other things).
 
 @item
-@code{gnus-uu} can view decoded files asynchronously while fetching
-articles (@pxref{Other Decode Variables}). 
-
-@lisp
-(setq gnus-uu-grabbed-file-functions 'gnus-uu-grab-view)
-@end lisp
+Luis Fernandes---design and graphics.
 
 @item
-Filling in the article buffer now works properly on cited text
-(@pxref{Article Washing}).
+Joe Reiss---creator of the smiley faces.
 
 @item
-Hiding cited text adds buttons to toggle hiding, and how much
-cited text to hide is now customizable (@pxref{Article Hiding}).
-
-@lisp
-(setq gnus-cited-lines-visible 2)
-@end lisp
+Justin Sheehy---the @acronym{FAQ} maintainer.
 
 @item
-Boring headers can be hidden (@pxref{Article Hiding}).
-
-@lisp
-(add-hook 'gnus-article-display-hook 
-          'gnus-article-hide-boring-headers t)
-@end lisp
+Erik Naggum---help, ideas, support, code and stuff.
 
 @item
-Default scoring values can now be set from the menu bar.
+Wes Hardaker---@file{gnus-picon.el} and the manual section on
+@dfn{picons} (@pxref{Picons}).
 
 @item
-Further syntax checking of outgoing articles have been added.
-
-@end itemize
-
-
-@node Red Gnus
-@subsubsection Red Gnus
-
-New features in Gnus 5.4/5.5:
-
-@iftex
-@iflatex
-\gnusfig{-5.5cm}{-4cm}{\epsfig{figure=tmp/red.ps,height=20cm}}
-@end iflatex
-@end iftex
-
-@itemize @bullet
+Kim-Minh Kaplan---further work on the picon code.
 
 @item
-@file{nntp.el} has been totally rewritten in an asynchronous fashion.
+Brad Miller---@file{gnus-gl.el} and the GroupLens manual section
+(@pxref{GroupLens}).
 
 @item
-Article prefetching functionality has been moved up into 
-Gnus (@pxref{Asynchronous Fetching}).  
+Sudish Joseph---innumerable bug fixes.
 
 @item
-Scoring can now be performed with logical operators like @code{and},
-@code{or}, @code{not}, and parent redirection (@pxref{Advanced
-Scoring}).
+Ilja Weis---@file{gnus-topic.el}.
 
 @item
-Article washing status can be displayed in the
-article mode line (@pxref{Misc Article}).
+Steven L. Baur---lots and lots and lots of bugs detections and fixes.
 
 @item
-@file{gnus.el} has been split into many smaller files.
+Vladimir Alexiev---the refcard and reference booklets.
 
 @item
-Suppression of duplicate articles based on Message-ID can be done
-(@pxref{Duplicate Suppression}).
-
-@lisp
-(setq gnus-suppress-duplicates t)
-@end lisp
+Felix Lee & Jamie Zawinski---I stole some pieces from the XGnus
+distribution by Felix Lee and JWZ.
 
 @item
-New variables for specifying what score and adapt files are to be
-considered home score and adapt files (@pxref{Home Score File}) have
-been added.
+Scott Byer---@file{nnfolder.el} enhancements & rewrite.
 
 @item
-@code{nndoc} was rewritten to be easily extendable (@pxref{Document
-Server Internals}). 
+Peter Mutsaers---orphan article scoring code.
 
 @item
-Groups can inherit group parameters from parent topics (@pxref{Topic
-Parameters}).
+Ken Raeburn---POP mail support.
 
 @item
-Article editing has been revamped and is now actually usable.
+Hallvard B Furuseth---various bits and pieces, especially dealing with
+.newsrc files.
 
 @item
-Signatures can be recognized in more intelligent fashions
-(@pxref{Article Signature}).
+Brian Edmonds---@file{gnus-bbdb.el}.
 
 @item
-Summary pick mode has been made to look more @code{nn}-like.  Line
-numbers are displayed and the @kbd{.} command can be used to pick
-articles (@code{Pick and Read}).
+David Moore---rewrite of @file{nnvirtual.el} and many other things.
 
 @item
-Commands for moving the @file{.newsrc.eld} from one server to
-another have been added (@pxref{Changing Servers}).
+Kevin Davidson---came up with the name @dfn{ding}, so blame him.
 
 @item
-There's a way now to specify that ``uninteresting'' fields be suppressed
-when generating lines in buffers (@pxref{Advanced Formatting}).
+François Pinard---many, many interesting and thorough bug reports, as
+well as autoconf support.
 
-@item
-Several commands in the group buffer can be undone with @kbd{M-C-_}
-(@pxref{Undo}).
+@end itemize
 
-@item
-Scoring can be done on words using the new score type @code{w}
-(@pxref{Score File Format}).
+This manual was proof-read by Adrian Aichner, with Ricardo Nassif, Mark
+Borges, and Jost Krieger proof-reading parts of the manual.
 
-@item
-Adaptive scoring can be done on a Subject word-by-word basis
-(@pxref{Adaptive Scoring}). 
+The following people have contributed many patches and suggestions:
+
+Christopher Davis,
+Andrew Eskilsson,
+Kai Grossjohann,
+Kevin Greiner,
+Jesper Harder,
+Paul Jarc,
+Simon Josefsson,
+David KÃ¥gedal,
+Richard Pieri,
+Fabrice Popineau,
+Daniel Quinlan,
+Michael Shields,
+Reiner Steib,
+Jason L. Tibbitts, III,
+Jack Vinson,
+Katsumi Yamaoka, @c Yamaoka
+and
+Teodor Zlatanov.
+
+Also thanks to the following for patches and stuff:
+
+Jari Aalto,
+Adrian Aichner,
+Vladimir Alexiev,
+Russ Allbery,
+Peter Arius,
+Matt Armstrong,
+Marc Auslander,
+Miles Bader,
+Alexei V. Barantsev,
+Frank Bennett,
+Robert Bihlmeyer,
+Chris Bone,
+Mark Borges,
+Mark Boyns,
+Lance A. Brown,
+Rob Browning,
+Kees de Bruin,
+Martin Buchholz,
+Joe Buehler,
+Kevin Buhr,
+Alastair Burt,
+Joao Cachopo,
+Zlatko Calusic,
+Massimo Campostrini,
+Castor,
+David Charlap,
+Dan Christensen,
+Kevin Christian,
+Jae-you Chung, @c ?
+James H. Cloos, Jr.,
+Laura Conrad,
+Michael R. Cook,
+Glenn Coombs,
+Andrew J. Cosgriff,
+Neil Crellin,
+Frank D. Cringle,
+Geoffrey T. Dairiki,
+Andre Deparade,
+Ulrik Dickow,
+Dave Disser,
+Rui-Tao Dong, @c ?
+Joev Dubach,
+Michael Welsh Duggan,
+Dave Edmondson,
+Paul Eggert,
+Mark W. Eichin,
+Karl Eichwalder,
+Enami Tsugutomo, @c Enami
+Michael Ernst,
+Luc Van Eycken,
+Sam Falkner,
+Nelson Jose dos Santos Ferreira,
+Sigbjorn Finne,
+Sven Fischer,
+Paul Fisher,
+Decklin Foster,
+Gary D. Foster,
+Paul Franklin,
+Guy Geens,
+Arne Georg Gleditsch,
+David S. Goldberg,
+Michelangelo Grigni,
+Dale Hagglund,
+D. Hall,
+Magnus Hammerin,
+Kenichi Handa, @c Handa
+Raja R. Harinath,
+Yoshiki Hayashi, @c Hayashi
+P. E. Jareth Hein,
+Hisashige Kenji, @c Hisashige
+Scott Hofmann,
+Marc Horowitz,
+Gunnar Horrigmo,
+Richard Hoskins,
+Brad Howes,
+Miguel de Icaza,
+François Felix Ingrand,
+Tatsuya Ichikawa, @c Ichikawa
+Ishikawa Ichiro, @c Ishikawa
+Lee Iverson,
+Iwamuro Motonori, @c Iwamuro
+Rajappa Iyer,
+Andreas Jaeger,
+Adam P. Jenkins,
+Randell Jesup,
+Fred Johansen,
+Gareth Jones,
+Greg Klanderman,
+Karl Kleinpaste,
+Michael Klingbeil,
+Peter Skov Knudsen,
+Shuhei Kobayashi, @c Kobayashi
+Petr Konecny,
+Koseki Yoshinori, @c Koseki
+Thor Kristoffersen,
+Jens Lautenbacher,
+Martin Larose,
+Seokchan Lee, @c Lee
+Joerg Lenneis,
+Carsten Leonhardt,
+James LewisMoss,
+Christian Limpach,
+Markus Linnala,
+Dave Love,
+Mike McEwan,
+Tonny Madsen,
+Shlomo Mahlab,
+Nat Makarevitch,
+Istvan Marko,
+David Martin,
+Jason R. Mastaler,
+Gordon Matzigkeit,
+Timo Metzemakers,
+Richard Mlynarik,
+Lantz Moore,
+Morioka Tomohiko, @c Morioka
+Erik Toubro Nielsen,
+Hrvoje Niksic,
+Andy Norman,
+Fred Oberhauser,
+C. R. Oldham,
+Alexandre Oliva,
+Ken Olstad,
+Masaharu Onishi, @c Onishi
+Hideki Ono, @c Ono
+Ettore Perazzoli,
+William Perry,
+Stephen Peters,
+Jens-Ulrik Holger Petersen,
+Ulrich Pfeifer,
+Matt Pharr,
+Andy Piper,
+John McClary Prevost,
+Bill Pringlemeir,
+Mike Pullen,
+Jim Radford,
+Colin Rafferty,
+Lasse Rasinen,
+Lars Balker Rasmussen,
+Joe Reiss,
+Renaud Rioboo,
+Roland B. Roberts,
+Bart Robinson,
+Christian von Roques,
+Markus Rost,
+Jason Rumney,
+Wolfgang Rupprecht,
+Jay Sachs,
+Dewey M. Sasser,
+Conrad Sauerwald,
+Loren Schall,
+Dan Schmidt,
+Ralph Schleicher,
+Philippe Schnoebelen,
+Andreas Schwab,
+Randal L. Schwartz,
+Danny Siu,
+Matt Simmons,
+Paul D. Smith,
+Jeff Sparkes,
+Toby Speight,
+Michael Sperber,
+Darren Stalder,
+Richard Stallman,
+Greg Stark,
+Sam Steingold,
+Paul Stevenson,
+Jonas Steverud,
+Paul Stodghill,
+Kiyokazu Suto, @c Suto
+Kurt Swanson,
+Samuel Tardieu,
+Teddy,
+Chuck Thompson,
+Tozawa Akihiko, @c Tozawa
+Philippe Troin,
+James Troup,
+Trung Tran-Duc,
+Jack Twilley,
+Aaron M. Ucko,
+Aki Vehtari,
+Didier Verna,
+Vladimir Volovich,
+Jan Vroonhof,
+Stefan Waldherr,
+Pete Ware,
+Barry A. Warsaw,
+Christoph Wedler,
+Joe Wells,
+Lee Willis,
+and
+Lloyd Zusman.
 
-@lisp
-(setq gnus-use-adaptive-scoring '(word))
-@end lisp
 
-@item
-Scores can be decayed (@pxref{Score Decays}).
-@lisp
-(setq gnus-decay-scores t)
-@end lisp
+For a full overview of what each person has done, the ChangeLogs
+included in the Gnus alpha distributions should give ample reading
+(550kB and counting).
 
-@item
-Scoring can be performed using a regexp on the Date header.  The Date is
-normalized to compact ISO 8601 format first (@pxref{Score File Format}).
+Apologies to everybody that I've forgotten, of which there are many, I'm
+sure.
 
-@item
-A new command has been added to remove all data on articles from
-the native server (@pxref{Changing Servers}).
+Gee, that's quite a list of people.  I guess that must mean that there
+actually are people who are using Gnus.  Who'd'a thunk it!
 
-@item
-A new command for reading collections of documents
-(@code{nndoc} with @code{nnvirtual} on top) has been added---@kbd{M-C-d}
-(@pxref{Really Various Summary Commands}). 
 
-@item
-Process mark sets can be pushed and popped (@pxref{Setting Process
-Marks}).
+@node New Features
+@subsection New Features
+@cindex new features
 
-@item
-A new mail-to-news backend makes it possible to post even when the NNTP
-server doesn't allow posting (@pxref{Mail-To-News Gateways}).
+@menu
+* ding Gnus::                   New things in Gnus 5.0/5.1, the first new Gnus.
+* September Gnus::              The Thing Formally Known As Gnus 5.2/5.3.
+* Red Gnus::                    Third time best---Gnus 5.4/5.5.
+* Quassia Gnus::                Two times two is four, or Gnus 5.6/5.7.
+* Pterodactyl Gnus::            Pentad also starts with P, AKA Gnus 5.8/5.9.
+* Oort Gnus::                   It's big.  It's far out.  Gnus 5.10.
+@end menu
 
-@item
-A new backend for reading searches from Web search engines
-(@dfn{DejaNews}, @dfn{Alta Vista}, @dfn{InReference}) has been added
-(@pxref{Web Searches}).
+These lists are, of course, just @emph{short} overviews of the
+@emph{most} important new features.  No, really.  There are tons more.
+Yes, we have feeping creaturism in full effect.
 
-@item
-Groups inside topics can now be sorted using the standard sorting
-functions, and each topic can be sorted independently (@pxref{Topic
-Sorting}).
+@node ding Gnus
+@subsubsection (ding) Gnus
 
-@item
-Subsets of the groups can be sorted independently (@code{Sorting
-Groups}).
+New features in Gnus 5.0/5.1:
 
-@item
-Cached articles can be pulled into the groups (@pxref{Summary Generation
-Commands}).
-@iftex
-@iflatex
-\marginpar[\mbox{}\hfill\epsfig{figure=tmp/fred.ps,width=3cm}]{\epsfig{figure=tmp/fred.ps,width=3cm}}
-@end iflatex
-@end iftex
+@itemize @bullet
 
 @item
-Score files are now applied in a more reliable order (@pxref{Score
-Variables}).
+The look of all buffers can be changed by setting format-like variables
+(@pxref{Group Buffer Format} and @pxref{Summary Buffer Format}).
 
 @item
-Reports on where mail messages end up can be generated (@pxref{Splitting
-Mail}).
+Local spool and several @acronym{NNTP} servers can be used at once
+(@pxref{Select Methods}).
 
 @item
-More hooks and functions have been added to remove junk from incoming
-mail before saving the mail (@pxref{Washing Mail}).
+You can combine groups into virtual groups (@pxref{Virtual Groups}).
 
 @item
-Emphasized text can be properly fontisized:
-
-@lisp
-(add-hook 'gnus-article-display-hook 'gnus-article-emphasize)
-@end lisp
-@end itemize
-
-
-@node Newest Features
-@subsection Newest Features
-@cindex todo
-
-Also known as the @dfn{todo list}.  Sure to be implemented before the
-next millennium. 
-
-Be afraid.  Be very afraid.
-
-(That a feature appears in this list doesn't necessarily mean that I've
-decided to actually implement it.  It just means that I think it sounds
-interesting.)
-
-(Yes, this is the actual, up-to-the-second todo list.)
-
-@itemize @bullet
+You can read a number of different mail formats (@pxref{Getting Mail}).
+All the mail back ends implement a convenient mail expiry scheme
+(@pxref{Expiring Mail}).
 
 @item
-Native @sc{mime} support is something that should be done.  
+Gnus can use various strategies for gathering threads that have lost
+their roots (thereby gathering loose sub-threads into one thread) or it
+can go back and retrieve enough headers to build a complete thread
+(@pxref{Customizing Threading}).
 
 @item
-Really do unbinhexing.
+Killed groups can be displayed in the group buffer, and you can read
+them as well (@pxref{Listing Groups}).
 
 @item
- I would like the zombie-page to contain an URL to the source of the
-latest version of gnus or some explanation on where to find it.
+Gnus can do partial group updates---you do not have to retrieve the
+entire active file just to check for new articles in a few groups
+(@pxref{The Active File}).
 
 @item
- A way to continue editing the latest Message composition.
+Gnus implements a sliding scale of subscribedness to groups
+(@pxref{Group Levels}).
 
 @item
- http://www.sonicnet.com/feature/ari3/
+You can score articles according to any number of criteria
+(@pxref{Scoring}).  You can even get Gnus to find out how to score
+articles for you (@pxref{Adaptive Scoring}).
 
 @item
- facep is not declared.
+Gnus maintains a dribble buffer that is auto-saved the normal Emacs
+manner, so it should be difficult to lose much data on what you have
+read if your machine should go down (@pxref{Auto Save}).
 
 @item
- Include a section in the manual on why the number of articles
-isn't the same in the group buffer and on the SPC prompt.
+Gnus now has its own startup file (@file{~/.gnus.el}) to avoid
+cluttering up the @file{.emacs} file.
 
 @item
- Interacting with rmail fcc isn't easy.
+You can set the process mark on both groups and articles and perform
+operations on all the marked items (@pxref{Process/Prefix}).
 
 @item
-@example
- Hypermail:
-<URL:http://www.falch.no/people/pepper/DSSSL-Lite/archives/>
-<URL:http://www.eit.com/software/hypermail/hypermail.html>
-<URL:http://homer.ncm.com/>
-<URL:http://www.yahoo.com/Computers_and_Internet/Internet/World_Wide_Web/HTML_Converters/>
-http://www.uwsg.indiana.edu/hypermail/linux/kernel/9610/index.html
-<URL:http://union.ncsa.uiuc.edu/HyperNews/get/www/html/converters.html>
-http://www.miranova.com/gnus-list/
-
-@end example
+You can grep through a subset of groups and create a group from the
+results (@pxref{Kibozed Groups}).
 
 @item
-@samp{^-- } is made into - in LaTeX.
+You can list subsets of groups according to, well, anything
+(@pxref{Listing Groups}).
 
 @item
- gnus-kill is much slower than it was in GNUS 4.1.3.
+You can browse foreign servers and subscribe to groups from those
+servers (@pxref{Browse Foreign Server}).
 
 @item
- when expunging articles on low score, the sparse nodes keep hanging on?
-@item
- starting the first time seems to hang Gnus on some systems.  Does
-NEWGROUPS answer too fast?
-@item
- nndir doesn't read gzipped files.
-@item
- FAQ doesn't have an up node?
-@item
- when moving mail from a procmail spool to the crash-box,
-the crash-box is only appropriate to one specific group.
-@item
- `t' `t' makes X-Faces disappear.
-@item
- nnmh-be-safe means that crossposted articles will
-be marked as unread.
-@item
- Orphan score entries dont show on "V t" score trace
-@item
- when clearing out data, the cache data should also be reset.
-@item
- rewrite gnus-summary-limit-children to be non-recursive
-to avoid exceeding lisp nesting on huge groups.
-@item
- expinged articles are counted when computing scores.
-@item
- implement gnus-batch-brew-soup
-@item
- ticked articles aren't easy to read in pick mode -- `n' and
-stuff just skips past them.  Read articles are the same.
-@item
- topics that contain just groups with ticked
-articles aren't displayed.
-@item
- nndoc should always allocate unique Message-IDs.
-@item
- implement gnus-score-thread
-@item
- If there are mail groups the first time you use Gnus, Gnus'll
-make the mail groups killed. 
-@item
- no "no news is good news" when using topics.
-@item
- when doing crosspost marking, the cache has to be consulted
-and articles have to be removed.
-@item
- nnweb should fetch complete articles when they are split into several
-parts.
-@item
- scoring on head immediate doesn't work.
-@item
- finding short score file names takes forever.
-@item
- canceling articles in foreign groups.
-@item
- nntp-open-rlogin no longer works.
-@item
- C-u C-x C-s (Summary) switches to the group buffer.
-@item
- move nnmail-split-history out to the backends.
-@item
- nnweb doesn't work properly.
-@item
- using a virtual server name as `gnus-select-method' doesn't work?
-@item
- when killing/yanking a group from one topic to another in a slave, the 
-master will yank it first to one topic and then add it to another.  
-Perhaps.
+Gnus can fetch articles, asynchronously, on a second connection to the
+server (@pxref{Asynchronous Fetching}).
 
 @item
- warn user about `=' redirection of a group in the active file?
-@item
- really unbinhex binhex files.
-@item
- take over the XEmacs menubar and offer a toggle between the XEmacs
-bar and the Gnus bar.
-@item
-@example
- push active file and NOV file parsing down into C code.
-`(canonize-message-id id)'
-`(mail-parent-message-id references n)'
-`(parse-news-nov-line &optional dependency-hashtb)'
-`(parse-news-nov-region beg end &optional dependency-hashtb fullp)'
-`(parse-news-active-region beg end hashtb)'
-
-@end example
+You can cache articles locally (@pxref{Article Caching}).
 
 @item
- nnml .overview directory with splits.
-@item
- asynchronous cache
-@item
- postponed commands.
-@item
- the selected article show have its Subject displayed in its summary line.
-@item
- when entering groups, get the real number of unread articles from
-the server?  
-@item
- sort after gathering threads -- make false roots have the
-headers of the oldest orhpan with a 0 article number?
-@item
- nndoc groups should inherit the score files of their parents?  Also
-inherit copy prompts and save files.
-@item
- command to start up Gnus (if not running) and enter a mail mode buffer.
-@item
- allow editing the group description from the group buffer
-for backends that support that.
-@item
-gnus-hide,show-all-topics
-@item
- groups and sub-topics should be allowed to mingle inside each topic,
-and not just list all subtopics at the end.
-@item
- a command to remove all read articles that are not needed to connect
-threads -- `gnus-summary-limit-to-sparse-unread'?
-@item
- a variable to turn off limiting/cutting of threads in the tree buffer.
-@item
- a variable to limit how many files are uudecoded.
-@item
- add zombie groups to a special "New Groups" topic.
-@item
- server mode command: close/open all connections
-@item
- put a file date in gnus-score-alist and check whether the file
-has been changed before using it.
-@item
- on exit from a digest group, go to the next article in the parent group.
-@item
- hide (sub)threads with low score.
-@item
- when expiring, remove all marks from expired articles.
-@item
- gnus-summary-limit-to-body
-@item
- a regexp alist that says what level groups are to be subscribed
-on.  Eg. -- `(("nnml:" . 1))'.
-@item
- easier interface to nnkiboze to create ephemeral groups that
-contaion groups that match a regexp.
-@item
- allow newlines in <URL:> urls, but remove them before using
-the URL.
-@item
- If there is no From line, the mail backends should fudge one from the
-"From " line.
-@item
- fuzzy simplifying should strip all non-alpha-numerical info
-from subject lines.
-@item
- gnus-soup-brew-soup-with-high-scores.
-@item
- nntp-ping-before-connect
-@item
- command to check whether NOV is evil.  "list overview.fmt".
-@item
- when entering a group, Gnus should look through the score
-files very early for `local' atoms and set those local variables.
-@item
- message annotations.
-@item
- topics are always yanked before groups, and that's not good.
-@item
- (set-extent-property extent 'help-echo "String to display in minibuf")
-to display help in the minibuffer on buttons under XEmacs.
-@item
- allow group line format spec to say how many articles there
-are in the cache.
-@item
- AUTHINFO GENERIC
-@item
- support qmail maildir spools
-@item
- `run-with-idle-timer' in gnus-demon.
-@item
- stop using invisible text properties and start using overlays instead
-@item
- C-c C-f C-e to add an Expires header.
-@item
- go from one group to the next; everything is expunged; go to the
-next group instead of going to the group buffer.
-@item
- gnus-renumber-cache -- to renumber the cache using "low" numbers.
-@item
- record topic changes in the dribble buffer.
-@item
- `nnfolder-generate-active-file' should look at the folders it
-finds and generate proper active ranges.
-@item
- nneething-look-in-files-for-article-heads variable to control
-whether nneething should sniff all files in the directories.
-@item
- gnus-fetch-article -- start Gnus, enter group, display article
-@item
- gnus-dont-move-articles-to-same-group variable when respooling.
-@item
- when messages are crossposted between several auto-expirable groups, 
-articles aren't properly marked as expirable.
-@item
- nneething should allow deletion/moving.
-@item
- TAB on the last button should go to the first button.
-@item
- if the car of an element in `mail-split-methods' is a function,
-and the function returns non-nil, use that as the name of the group(s) to 
-save mail in.
-@item
- command for listing all score files that have been applied.
-@item
- a command in the article buffer to return to `summary' config.
-@item
- `gnus-always-post-using-current-server' -- variable to override
-`C-c C-c' when posting.
-@item
- nnmail-group-spool-alist -- says where each group should use
-as a spool file.
-@item
- when an article is crossposted to an auto-expirable group, the article 
-should be marker as expirable.
-@item
- article mode command/menu for "send region as URL to browser".
-@item
- on errors, jump to info nodes that explain the error.  For instance,
-on invalid From headers, or on error messages from the nntp server.
-@item
- when gathering threads, make the article that has no "Re: " the parent.
-Also consult Date headers.
-@item
- a token in splits to call shrink-window-if-larger-than-buffer
-@item
- `1 0 A M' to do matches on the active hashtb.
-@item
- duplicates -- command to remove Gnus-Warning header, use the read 
-Message-ID, delete the "original".
-@item
- when replying to several messages at once, put the "other" message-ids
-into a See-Also header.
-@item
- support setext: URL:http://www.bsdi.com/setext/
-@item
- support ProleText: <URL:http://proletext.clari.net/prole/proletext.html>
-@item
- when browsing a foreign server, the groups that are already subscribed
-should be listed as such and not as "K".
-@item
- generate font names dynamically.
-@item
- score file mode auto-alist.
-@item
- allow nndoc to change/add/delete things from documents.  Implement
-methods for each format for adding an article to the document.
-@item
- `gnus-fetch-old-headers' `all' value to incorporate
-absolutely all headers there is.
-@item
- function like `|', but concatenate all marked articles
-and pipe them to the process.
-@item
- cache the list of killed (or active) groups in a separate file.  Update
-the file whenever we read the active file or the list
-of killed groups in the .eld file reaches a certain length.
-@item
- function for starting to edit a file to put into 
-the current mail group.
-@item
- score-find-trace should display the total score of the article. 
-@item
- "ghettozie" -- score on Xref header and nix it out after using it 
-to avoid marking as read in other groups it has been crossposted to.
-@item
- look at procmail splitting.  The backends should create
-the groups automatically if a spool file exists for that group.
-@item
- function for backends to register themselves with Gnus.
-@item
- when replying to several process-marked articles, 
-have all the From end up in Cc headers?  Variable to toggle.
-@item
- command to delete a crossposted mail article from all 
-groups it has been mailed to.
-@item
- `B c' and `B m' should be crosspost aware.  
-@item
- hide-pgp should also hide PGP public key blocks.
-@item
- Command in the group buffer to respoll process-marked groups.
-@item
- `gnus-summary-find-matching' should accept
-pseudo-"headers" like "body", "head" and "all"
-@item
- When buttifying <URL: > things, all white space (including
-newlines) should be ignored.
+The uudecode functions have been expanded and generalized
+(@pxref{Decoding Articles}).
+
 @item
- Process-marking all groups in a topic should process-mark
-groups in subtopics as well.
+You can still post uuencoded articles, which was a little-known feature
+of @sc{gnus}' past (@pxref{Uuencoding and Posting}).
+
 @item
- Add non-native groups to the list of killed groups when killing them. 
+Fetching parents (and other articles) now actually works without
+glitches (@pxref{Finding the Parent}).
+
 @item
- nntp-suggest-kewl-config to probe the nntp server and suggest
-variable settings.
+Gnus can fetch @acronym{FAQ}s and group descriptions (@pxref{Group Information}).
+
 @item
- add edit and forward secondary marks.
+Digests (and other files) can be used as the basis for groups
+(@pxref{Document Groups}).
+
 @item
- nnml shouldn't visit its .overview files.
+Articles can be highlighted and customized (@pxref{Customizing
+Articles}).
+
 @item
- allow customizing sorting within gathered threads.
+URLs and other external references can be buttonized (@pxref{Article
+Buttons}).
+
 @item
- `B q' shouldn't select the current article.
+You can do lots of strange stuff with the Gnus window & frame
+configuration (@pxref{Window Layout}).
+
 @item
- nnmbox should support a newsgroups file for descriptions.
+You can click on buttons instead of using the keyboard
+(@pxref{Buttons}).
+
+@end itemize
+
+
+@node September Gnus
+@subsubsection September Gnus
+
+@iftex
+@iflatex
+\gnusfig{-28cm}{0cm}{\epsfig{figure=ps/september,height=20cm}}
+@end iflatex
+@end iftex
+
+New features in Gnus 5.2/5.3:
+
+@itemize @bullet
+
 @item
- allow fetching mail from several pop servers.
+A new message composition mode is used.  All old customization variables
+for @code{mail-mode}, @code{rnews-reply-mode} and @code{gnus-msg} are
+now obsolete.
+
 @item
- Be able to specify whether the saving commands save the original
-or the formatted article.
+Gnus is now able to generate @dfn{sparse} threads---threads where
+missing articles are represented by empty nodes (@pxref{Customizing
+Threading}).
+
+@lisp
+(setq gnus-build-sparse-threads 'some)
+@end lisp
+
 @item
- a command to reparent with the child process-marked (cf. `T ^'.).
+Outgoing articles are stored on a special archive server
+(@pxref{Archived Messages}).
+
 @item
- I think the possibility to send a password with nntp-open-rlogin
-should be a feature in Red Gnus.
+Partial thread regeneration now happens when articles are
+referred.
+
 @item
- The `Z n' command should be possible to execute from a mouse click.
+Gnus can make use of GroupLens predictions (@pxref{GroupLens}).
+
 @item
- more limiting functions -- date, etc.
+Picons (personal icons) can be displayed under XEmacs (@pxref{Picons}).
+
 @item
- be able to limit on a random header; on body; using reverse matches.
+A @code{trn}-like tree buffer can be displayed (@pxref{Tree Display}).
+
+@lisp
+(setq gnus-use-trees t)
+@end lisp
+
 @item
- a group parameter (`absofucking-total-expiry') that will make Gnus expire
-even unread articles.
+An @code{nn}-like pick-and-read minor mode is available for the summary
+buffers (@pxref{Pick and Read}).
+
+@lisp
+(add-hook 'gnus-summary-mode-hook 'gnus-pick-mode)
+@end lisp
+
 @item
- a command to print the article buffer as postscript.
+In binary groups you can use a special binary minor mode (@pxref{Binary
+Groups}).
+
 @item
- variable to disable password fetching when opening by nntp-open-telnet.
+Groups can be grouped in a folding topic hierarchy (@pxref{Group
+Topics}).
+
+@lisp
+(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
+@end lisp
+
 @item
- manual: more example servers -- nntp with rlogin, telnet
+Gnus can re-send and bounce mail (@pxref{Summary Mail Commands}).
+
 @item
- checking for bogus groups should clean topic alists as well.
+Groups can now have a score, and bubbling based on entry frequency
+is possible (@pxref{Group Score}).
+
+@lisp
+(add-hook 'gnus-summary-exit-hook 'gnus-summary-bubble-group)
+@end lisp
+
 @item
- cancelling articles in foreign groups.
+Groups can be process-marked, and commands can be performed on
+groups of groups (@pxref{Marking Groups}).
+
 @item
- article number in folded topics isn't properly updated by
-Xref handling.
+Caching is possible in virtual groups.
+
 @item
- Movement in the group buffer to the next unread group should go to the
-next closed topic with unread messages if no group can be found.
+@code{nndoc} now understands all kinds of digests, mail boxes, rnews
+news batches, ClariNet briefs collections, and just about everything
+else (@pxref{Document Groups}).
+
 @item
- Extensive info pages generated on the fly with help everywhere --
-in the "*Gnus edit*" buffers, for instance.
+Gnus has a new back end (@code{nnsoup}) to create/read SOUP packets
+(@pxref{SOUP}).
+
 @item
- Topic movement commands -- like thread movement.  Up, down, forward, next.
+The Gnus cache is much faster.
+
 @item
- a way to tick/mark as read Gcc'd articles.
+Groups can be sorted according to many criteria (@pxref{Sorting
+Groups}).
+
 @item
- a way to say that all groups within a specific topic comes
-from a particular server?  Hm.
+New group parameters have been introduced to set list-addresses and
+expiry times (@pxref{Group Parameters}).
+
 @item
- `gnus-article-fill-if-long-lines' -- a function to fill
-the article buffer if there are any looong lines there.
+All formatting specs allow specifying faces to be used
+(@pxref{Formatting Fonts}).
+
 @item
- `T h' should jump to the parent topic and fold it.
+There are several more commands for setting/removing/acting on process
+marked articles on the @kbd{M P} submap (@pxref{Setting Process Marks}).
+
 @item
- a command to create an ephemeral nndoc group out of a file,
-and then splitting it/moving it to some other group/backend.
+The summary buffer can be limited to show parts of the available
+articles based on a wide range of criteria.  These commands have been
+bound to keys on the @kbd{/} submap (@pxref{Limiting}).
+
 @item
- a group parameter for nnkiboze groups that says that
-all kibozed articles should be entered into the cache.
+Articles can be made persistent with the @kbd{*} command
+(@pxref{Persistent Articles}).
+
 @item
- It should also probably be possible to delimit what
-`gnus-jog-cache' does -- for instance, work on just some groups, or on
-some levels, and entering just articles that have a score higher than
-a certain number.
+All functions for hiding article elements are now toggles.
+
 @item
- nnfolder should append to the folder instead of re-writing
-the entire folder to disk when accepting new messages.
+Article headers can be buttonized (@pxref{Article Washing}).
+
 @item
- allow all backends to do the proper thing with .gz files.
+All mail back ends support fetching articles by @code{Message-ID}.
+
 @item
- a backend for reading collections of babyl files nnbabylfolder?
+Duplicate mail can now be treated properly (@pxref{Duplicates}).
+
 @item
- a command for making the native groups into foreign groups. 
+All summary mode commands are available directly from the article
+buffer (@pxref{Article Keymap}).
+
 @item
- server mode command for clearing read marks from all groups
-from a server.
+Frames can be part of @code{gnus-buffer-configuration} (@pxref{Window
+Layout}).
+
 @item
- when following up mulitple articles, include all To, Cc, etc headers
-from all articles.
+Mail can be re-scanned by a daemonic process (@pxref{Daemons}).
+@iftex
+@iflatex
+\marginpar[\mbox{}\hfill\epsfig{figure=ps/fseptember,height=5cm}]{\epsfig{figure=ps/fseptember,height=5cm}}
+@end iflatex
+@end iftex
+
 @item
- a command for deciding what the total score of the current
-thread is.  Also a way to highlight based on this.
+Gnus can make use of NoCeM files to weed out spam (@pxref{NoCeM}).
+
+@lisp
+(setq gnus-use-nocem t)
+@end lisp
+
 @item
- command to show and edit group scores
+Groups can be made permanently visible (@pxref{Listing Groups}).
+
+@lisp
+(setq gnus-permanently-visible-groups "^nnml:")
+@end lisp
+
 @item
- a gnus-tree-minimize-horizontal to minimize tree buffers
-horizontally.
+Many new hooks have been introduced to make customizing easier.
+
 @item
- command to generate nnml overview file for one group.
+Gnus respects the @code{Mail-Copies-To} header.
+
 @item
- `C-u C-u a' -- prompt for many crossposted groups.
+Threads can be gathered by looking at the @code{References} header
+(@pxref{Customizing Threading}).
+
+@lisp
+(setq gnus-summary-thread-gathering-function
+      'gnus-gather-threads-by-references)
+@end lisp
+
 @item
- keep track of which mail groups have received new articles (in this session).
-Be able to generate a report and perhaps do some marking in the group
-buffer.
+Read articles can be stored in a special backlog buffer to avoid
+refetching (@pxref{Article Backlog}).
+
+@lisp
+(setq gnus-keep-backlog 50)
+@end lisp
+
 @item
- gnus-build-sparse-threads to a number -- build only sparse threads
-that are of that length.
+A clean copy of the current article is always stored in a separate
+buffer to allow easier treatment.
+
 @item
- have nnmh respect mh's unseen sequence in .mh_profile.
+Gnus can suggest where to save articles (@pxref{Saving Articles}).
+
 @item
- cache the newsgroups descriptions locally.
+Gnus doesn't have to do as much prompting when saving (@pxref{Saving
+Articles}).
+
+@lisp
+(setq gnus-prompt-before-saving t)
+@end lisp
+
 @item
- asynchronous posting under nntp.
+@code{gnus-uu} can view decoded files asynchronously while fetching
+articles (@pxref{Other Decode Variables}).
+
+@lisp
+(setq gnus-uu-grabbed-file-functions 'gnus-uu-grab-view)
+@end lisp
+
 @item
- be able to control word adaptive scoring from the score files.
+Filling in the article buffer now works properly on cited text
+(@pxref{Article Washing}).
+
 @item
- a variable to make `C-c C-c' post using the "current" select method. 
+Hiding cited text adds buttons to toggle hiding, and how much
+cited text to hide is now customizable (@pxref{Article Hiding}).
+
+@lisp
+(setq gnus-cited-lines-visible 2)
+@end lisp
+
 @item
- `limit-exclude-low-scored-articles'.
+Boring headers can be hidden (@pxref{Article Hiding}).
+
 @item
- if `gnus-summary-show-thread' is a number, hide threads that have
-a score lower than this number.
+Default scoring values can now be set from the menu bar.
+
 @item
- split newsgroup subscription variable up into "order" and "method".
+Further syntax checking of outgoing articles have been added.
+
+@end itemize
+
+
+@node Red Gnus
+@subsubsection Red Gnus
+
+New features in Gnus 5.4/5.5:
+
+@iftex
+@iflatex
+\gnusfig{-5.5cm}{-4cm}{\epsfig{figure=ps/red,height=20cm}}
+@end iflatex
+@end iftex
+
+@itemize @bullet
+
 @item
- buttonize ange-ftp file names.
+@file{nntp.el} has been totally rewritten in an asynchronous fashion.
+
 @item
- a command to make a duplicate copy of the current article
-so that each copy can be edited separately.
+Article prefetching functionality has been moved up into
+Gnus (@pxref{Asynchronous Fetching}).
+
 @item
- nnweb should allow fetching from the local nntp server.
+Scoring can now be performed with logical operators like @code{and},
+@code{or}, @code{not}, and parent redirection (@pxref{Advanced
+Scoring}).
+
 @item
- record the sorting done in the summary buffer so that
-it can be repeated when limiting/regenerating the buffer.
+Article washing status can be displayed in the
+article mode line (@pxref{Misc Article}).
+
 @item
- nnml-generate-nov-databses should generate for
-all nnml servers.
+@file{gnus.el} has been split into many smaller files.
+
 @item
- when the user does commands in the group buffer, check
-the modification time of the .newsrc.eld file and use
-ask-user-about-supersession-threat.  Also warn when trying
-to save .newsrc.eld and it has changed.
+Suppression of duplicate articles based on Message-ID can be done
+(@pxref{Duplicate Suppression}).
+
+@lisp
+(setq gnus-suppress-duplicates t)
+@end lisp
+
 @item
- M-g on a topic will display all groups with 0 articles in
-the topic.
+New variables for specifying what score and adapt files are to be
+considered home score and adapt files (@pxref{Home Score File}) have
+been added.
+
 @item
- command to remove all topic stuff.
+@code{nndoc} was rewritten to be easily extendable (@pxref{Document
+Server Internals}).
+
 @item
- allow exploding incoming digests when reading incoming mail
-and splitting the resulting digests.
+Groups can inherit group parameters from parent topics (@pxref{Topic
+Parameters}).
+
 @item
- nnsoup shouldn't set the `message-' variables.
+Article editing has been revamped and is now actually usable.
+
 @item
- command to nix out all nnoo state information.
+Signatures can be recognized in more intelligent fashions
+(@pxref{Article Signature}).
+
 @item
- nnmail-process-alist that calls functions if group names 
-matches an alist -- before saving.
+Summary pick mode has been made to look more @code{nn}-like.  Line
+numbers are displayed and the @kbd{.} command can be used to pick
+articles (@code{Pick and Read}).
+
 @item
- use buffer-invisibility-spec everywhere for hiding text.
+Commands for moving the @file{.newsrc.eld} from one server to
+another have been added (@pxref{Changing Servers}).
+
 @item
- variable to activate each group before entering them
-to get the (new) number of articles.  `gnus-activate-before-entering'.
+There's a way now to specify that ``uninteresting'' fields be suppressed
+when generating lines in buffers (@pxref{Advanced Formatting}).
+
 @item
- command to fetch a Message-ID from any buffer, even
-starting Gnus first if necessary.
+Several commands in the group buffer can be undone with @kbd{C-M-_}
+(@pxref{Undo}).
+
 @item
- when posting and checking whether a group exists or not, just 
-ask the nntp server instead of relying on the active hashtb.
+Scoring can be done on words using the new score type @code{w}
+(@pxref{Score File Format}).
+
 @item
- buttonize the output of `C-c C-a' in an apropos-like way.
+Adaptive scoring can be done on a Subject word-by-word basis
+(@pxref{Adaptive Scoring}).
+
+@lisp
+(setq gnus-use-adaptive-scoring '(word))
+@end lisp
+
 @item
- `G p' should understand process/prefix, and allow editing
-of several groups at once.
+Scores can be decayed (@pxref{Score Decays}).
+
+@lisp
+(setq gnus-decay-scores t)
+@end lisp
+
 @item
- command to create an ephemeral nnvirtual group that
-matches some regexp(s).
+Scoring can be performed using a regexp on the Date header.  The Date is
+normalized to compact ISO 8601 format first (@pxref{Score File Format}).
+
 @item
- nndoc should understand "Content-Type: message/rfc822" forwarded messages. 
+A new command has been added to remove all data on articles from
+the native server (@pxref{Changing Servers}).
+
 @item
- it should be possible to score "thread" on the From header.
+A new command for reading collections of documents
+(@code{nndoc} with @code{nnvirtual} on top) has been added---@kbd{C-M-d}
+(@pxref{Really Various Summary Commands}).
+
 @item
- hitting RET on a "gnus-uu-archive" pseudo article should unpack it.
+Process mark sets can be pushed and popped (@pxref{Setting Process
+Marks}).
+
 @item
- `B i' should display the article at once in the summary buffer.
+A new mail-to-news back end makes it possible to post even when the @acronym{NNTP}
+server doesn't allow posting (@pxref{Mail-To-News Gateways}).
+
 @item
- remove the "*" mark at once when unticking an article.
+A new back end for reading searches from Web search engines
+(@dfn{DejaNews}, @dfn{Alta Vista}, @dfn{InReference}) has been added
+(@pxref{Web Searches}).
+
 @item
- `M-s' should highlight the matching text.
+Groups inside topics can now be sorted using the standard sorting
+functions, and each topic can be sorted independently (@pxref{Topic
+Sorting}).
+
 @item
- when checking for duplicated mails, use Resent-Message-ID if present.
+Subsets of the groups can be sorted independently (@code{Sorting
+Groups}).
+
 @item
- killing and yanking groups in topics should be better.  If killing one copy
-of a group that exists in multiple topics, only that copy should
-be removed.  Yanking should insert the copy, and yanking topics
-should be possible to be interspersed with the other yankings.
+Cached articles can be pulled into the groups (@pxref{Summary Generation
+Commands}).
+@iftex
+@iflatex
+\marginpar[\mbox{}\hfill\epsfig{figure=ps/fred,width=3cm}]{\epsfig{figure=ps/fred,width=3cm}}
+@end iflatex
+@end iftex
+
 @item
- command for enter a group just to read the cached articles.  A way to say
-"ignore the nntp connection; just read from the cache."
+Score files are now applied in a more reliable order (@pxref{Score
+Variables}).
+
 @item
- `X u' should decode base64 articles.
+Reports on where mail messages end up can be generated (@pxref{Splitting
+Mail}).
+
 @item
- a way to hide all "inner" cited text, leaving just the most
-recently cited text.
+More hooks and functions have been added to remove junk from incoming
+mail before saving the mail (@pxref{Washing Mail}).
+
 @item
- nnvirtual should be asynchronous.
+Emphasized text can be properly fontisized:
+
+@end itemize
+
+
+@node Quassia Gnus
+@subsubsection Quassia Gnus
+
+New features in Gnus 5.6:
+
+@itemize @bullet
+
 @item
- after editing an article, gnus-original-article-buffer should
-be invalidated.
+New functionality for using Gnus as an offline newsreader has been
+added.  A plethora of new commands and modes have been added.
+@xref{Gnus Unplugged}, for the full story.
+
 @item
- there should probably be a way to make Gnus not connect to the
-server and just read the articles in the server
+The @code{nndraft} back end has returned, but works differently than
+before.  All Message buffers are now also articles in the @code{nndraft}
+group, which is created automatically.
+
 @item
- allow a `set-default' (or something) to change the default
-value of nnoo variables.
+@code{gnus-alter-header-function} can now be used to alter header
+values.
+
 @item
- a command to import group infos from a .newsrc.eld file.
+@code{gnus-summary-goto-article} now accept Message-ID's.
+
 @item
- groups from secondary servers have the entire select method
-listed in each group info.
+A new Message command for deleting text in the body of a message
+outside the region: @kbd{C-c C-v}.
+
 @item
- a command for just switching from the summary buffer to the group
-buffer.
+You can now post to component group in @code{nnvirtual} groups with
+@kbd{C-u C-c C-c}.
+
 @item
- a way to specify that some incoming mail washing functions
-should only be applied to some groups.
+ @code{nntp-rlogin-program}---new variable to ease customization.
+
 @item
- Message `C-f C-t' should ask the user whether to heed
-mail-copies-to: never.
+@code{C-u C-c C-c} in @code{gnus-article-edit-mode} will now inhibit
+re-highlighting of the article buffer.
+
 @item
- new group parameter -- `post-to-server' that says to post
-using the current server.  Also a variable to do the same.
+New element in @code{gnus-boring-article-headers}---@code{long-to}.
+
 @item
- the slave dribble files should autosave to the slave file names.
+@kbd{M-i} symbolic prefix command.  @xref{Symbolic Prefixes}, for
+details.
+
 @item
- a group parameter that says what articles to display on group entry, based
-on article marks.
+@kbd{L} and @kbd{I} in the summary buffer now take the symbolic prefix
+@kbd{a} to add the score rule to the @file{all.SCORE} file.
+
 @item
- a way to visually distinguish slave Gnusae from masters.  (Whip instead
-of normal logo?)
+@code{gnus-simplify-subject-functions} variable to allow greater
+control over simplification.
+
 @item
- Use DJ Bernstein "From " quoting/dequoting, where appliccable.
+@kbd{A T}---new command for fetching the current thread.
+
 @item
- Why is hide-citation-maybe and hide-citation different?  Also
-clear up info.
+@kbd{/ T}---new command for including the current thread in the
+limit.
+
 @item
- group user-defined meta-parameters.
+@kbd{M-RET} is a new Message command for breaking cited text.
 
+@item
+@samp{\\1}-expressions are now valid in @code{nnmail-split-methods}.
 
+@item
+The @code{custom-face-lookup} function has been removed.
+If you used this function in your initialization files, you must
+rewrite them to use @code{face-spec-set} instead.
 
-From: John Griffith <griffith@@sfs.nphil.uni-tuebingen.de>
 @item
- I like the option for trying to retrieve the FAQ for a group and I was
-thinking it would be great if for those newsgroups that had archives
-you could also try to read the archive for that group.  Part of the
-problem is that archives are spread all over the net, unlike FAQs.
-What would be best I suppose is to find the one closest to your site.
+Canceling now uses the current select method.  Symbolic prefix
+@kbd{a} forces normal posting method.
 
-In any case, there is a list of general news group archives at
-ftp://ftp.neosoft.com/pub/users/claird/news.lists/newsgroup_archives.html
+@item
+New command to translate M******** sm*rtq**t*s into proper
+text---@kbd{W d}.
 
+@item
+For easier debugging of @code{nntp}, you can set
+@code{nntp-record-commands} to a non-@code{nil} value.
 
+@item
+@code{nntp} now uses @file{~/.authinfo}, a @file{.netrc}-like file, for
+controlling where and how to send @sc{authinfo} to @acronym{NNTP} servers.
 
+@item
+A command for editing group parameters from the summary buffer
+has been added.
 
 @item
-@example
-From: Jason L Tibbitts III <tibbs@@hpc.uh.edu>
-(add-hook 'gnus-select-group-hook
-  (lambda ()
-    (gnus-group-add-parameter group
-       (cons 'gnus-group-date-last-entered (list (current-time-string))))))
+A history of where mails have been split is available.
 
-(defun gnus-user-format-function-d (headers)
-  "Return the date the group was last read."
-  (cond ((car (gnus-group-get-parameter gnus-tmp-group 'gnus-group-date-last-entered)))
-      (t "")))
-@end example
+@item
+A new article date command has been added---@code{article-date-iso8601}.
 
 @item
- tanken var at nÃ¥r du bruker `gnus-startup-file' som prefix (FOO) til Ã¥ lete
-opp en fil FOO-SERVER, FOO-SERVER.el, FOO-SERVER.eld, kan du la den være en
-liste hvor du bruker hvert element i listen som FOO, istedet.  da kunne man
-hatt forskjellige serveres startup-filer forskjellige steder.
+Subjects can be simplified when threading by setting
+@code{gnus-score-thread-simplify}.
 
+@item
+A new function for citing in Message has been
+added---@code{message-cite-original-without-signature}.
 
 @item
-LMI> Well, nnbabyl could alter the group info to heed labels like
-LMI> answered and read, I guess.  
+@code{article-strip-all-blank-lines}---new article command.
 
-It could also keep them updated (the same for the Status: header of
-unix mbox files).
+@item
+A new Message command to kill to the end of the article has
+been added.
 
-They could be used like this:
+@item
+A minimum adaptive score can be specified by using the
+@code{gnus-adaptive-word-minimum} variable.
 
+@item
+The ``lapsed date'' article header can be kept continually
+updated by the @code{gnus-start-date-timer} command.
 
-@example
-`M l <name> RET' add label <name> to current message.
-`M u <name> RET' remove label <name> from current message.
-`/ l <expr> RET' limit summary buffer according to <expr>.
+@item
+Web listserv archives can be read with the @code{nnlistserv} back end.
 
-<expr> would be a boolean expression on the labels, e.g. 
+@item
+Old dejanews archives can now be read by @code{nnweb}.
 
-       `/ l bug & !fixed RET'
-@end example
+@end itemize
 
-would show all the messages which are labeled `bug' but not labeled
-`fixed'. 
+@node Pterodactyl Gnus
+@subsubsection Pterodactyl Gnus
 
-One could also immagine the labels being used for highliting, or
-affect the summary line format.
+New features in Gnus 5.8:
 
+@itemize @bullet
 
 @item
-Sender: abraham@@dina.kvl.dk
+The mail-fetching functions have changed.  See the manual for the
+many details.  In particular, all procmail fetching variables are gone.
 
-I'd like a gnus-find-file which work like find file, except that it
-would recognize things that looks like messages or folders:
+If you used procmail like in
 
-- If it is a directory containing numbered files, create an nndir
-summary buffer.
-
-- For other directories, create a nneething summaru buffer.
+@lisp
+(setq nnmail-use-procmail t)
+(setq nnmail-spool-file 'procmail)
+(setq nnmail-procmail-directory "~/mail/incoming/")
+(setq nnmail-procmail-suffix "\\.in")
+@end lisp
 
-- For files matching "\\`From ", create a nndoc/mbox summary.
+this now has changed to
 
-- For files matching "\\`BABYL OPTIONS:", create a nndoc/baby summary.
+@lisp
+(setq mail-sources
+      '((directory :path "~/mail/incoming/"
+                   :suffix ".in")))
+@end lisp
 
-- For files matching "\\`[^ \t\n]+:", create an *Article* buffer.
+@xref{Mail Source Specifiers}.
 
-- For other files, just find them normally.
+@item
+Gnus is now a @acronym{MIME}-capable reader.  This affects many parts of
+Gnus, and adds a slew of new commands.  See the manual for details.
 
-I'd like `nneething' to use this function, so it would work on a
-directory potentially containing mboxes or babyl files.
+@item
+Gnus has also been multilingualized.  This also affects too
+many parts of Gnus to summarize here, and adds many new variables.
 
 @item
-Please send a mail to bwarsaw@@cnri.reston.va.us (Barry A. Warsaw) and
-tell him what you are doing.
+@code{gnus-auto-select-first} can now be a function to be
+called to position point.
 
 @item
-Currently, I get prompted:
+The user can now decide which extra headers should be included in
+summary buffers and @acronym{NOV} files.
 
-decend into sci?
-- type y
-decend into sci.something ?
-- type n
-decend into ucd?
+@item
+@code{gnus-article-display-hook} has been removed.  Instead, a number
+of variables starting with @code{gnus-treat-} have been added.
 
-The problem above is that since there is really only one subsection of
-science, shouldn't it prompt you for only decending sci.something?  If
-there was a sci.somethingelse group or section, then it should prompt
-for sci? first the sci.something? then sci.somethingelse?...
+@item
+The Gnus posting styles have been redone again and now works in a
+subtly different manner.
 
 @item
-Ja, det burde være en mÃ¥te Ã¥ si slikt.  Kanskje en ny variabel?
-`gnus-use-few-score-files'?  SÃ¥ kunne score-regler legges til den
-"mest" lokale score-fila.  F. eks. ville no-gruppene betjenes av
-"no.all.SCORE", osv.
+New web-based back ends have been added: @code{nnslashdot},
+@code{nnwarchive} and @code{nnultimate}.  nnweb has been revamped,
+again, to keep up with ever-changing layouts.
 
 @item
-What i want is for Gnus to treat any sequence or combination of the following
-as a single spoiler warning and hide it all, replacing it with a "Next Page"
-button:
+Gnus can now read @acronym{IMAP} mail via @code{nnimap}.
 
-       ^L's
+@end itemize
 
-       more than n blank lines
-       
-       more than m identical lines 
-       (which should be replaced with button to show them)
+@node Oort Gnus
+@subsubsection Oort Gnus
+@cindex Oort Gnus
 
-       any whitespace surrounding any of the above
+New features in Gnus 5.10:
 
+@itemize @bullet
 
 @item
-Well, we could allow a new value to `gnus-thread-ignore-subject' --
-`spaces', or something.  (We could even default to that.)  And then
-subjects that differ in white space only could be considered the
-"same" subject for threading purposes. 
+@code{gnus-group-read-ephemeral-group} can be called interactively,
+using @kbd{G M}.
 
 @item
-Modes to preprocess the contents (e.g. jka-compr) use the second form
-"(REGEXP FUNCTION NON-NIL)" while ordinary modes (e.g. tex) use the first
-form "(REGEXP . FUNCTION)", so you could use it to distinguish between
-those two types of modes. (auto-modes-alist, insert-file-contents-literally.)
+In draft groups, @kbd{e} is now bound to @code{gnus-draft-edit-message}.
+Use @kbd{B w} for @code{gnus-summary-edit-article} instead.
 
 @item
- Under XEmacs -- do funny article marks:
-tick - thumb tack
-killed - skull
-soup - bowl of soup
-score below - dim light bulb
-score over - bright light bulb
+The revised Gnus @acronym{FAQ} is included in the manual,
+@xref{Frequently Asked Questions}.
 
 @item
-Yes. I think the algorithm is as follows:
+Upgrading from previous (stable) version if you have used Oort.
 
-@example
-Group-mode
-
-   show-list-of-articles-in-group
-       if (key-pressed == SPACE) 
-               if (no-more-articles-in-group-to-select) 
-                       if (articles-selected)
-                               start-reading-selected-articles;
-                       junk-unread-articles;
-                       next-group;
-                else 
-                       show-next-page;
-               
-        else if (key-pressed = '.') 
-               if (consolidated-menus)         # same as hide-thread in Gnus
-                       select-thread-under-cursor;
-               else
-                       select-article-under-cursor;
-       
-
-Article-mode
-       if (key-pressed == SPACE) 
-               if (more-pages-in-article)
-                       next-page;
-               else if (more-selected-articles-to-read)
-                       next-article;
-               else 
-                       next-group;
-@end example
+If you have tried Oort (the unstable Gnus branch leading to this
+release) but went back to a stable version, be careful when upgrading to
+this version.  In particular, you will probably want to remove all
+@file{.marks} (nnml) and @file{.mrk} (nnfolder) files, so that flags are
+read from your @file{.newsrc.eld} instead of from the
+@file{.marks}/@file{.mrk} file where this release store flags.  See a
+later entry for more information about marks.  Note that downgrading
+isn't save in general.
 
 @item
-My precise need here would have been to limit files to Incoming*.
-One could think of some `nneething-only-files' variable, but I guess
-it would have been unacceptable if one was using many unrelated such
-nneething groups.
+Article Buttons
 
-A more useful approach would be to, in response to the `G D' prompt, be
-allowed to say something like: `~/.mail/Incoming*', somewhat limiting
-the top-level directory only (in case directories would be matched by
-the wildcard expression).
+More buttons for URLs, mail addresses, Message-IDs, Info links, man
+pages and Emacs or Gnus related references.  @xref{Article Buttons}.  The
+variables @code{gnus-button-@var{*}-level} can be used to control the
+appearance of all article buttons.  @xref{Article Button Levels}.
 
 @item
-It would be nice if it also handled 
-
-       <URL:news://sunsite.auc.dk/>
-
-which should correspond to `B nntp RET sunsite.auc.dk' in *Group*.
+Dired integration
 
+@code{gnus-dired-minor-mode} (see @ref{Other modes}) installs key
+bindings in dired buffers to send a file as an attachment, open a file
+using the appropriate mailcap entry, and print a file using the mailcap
+entry.
 
 @item
+Gnus can display RSS newsfeeds as a newsgroup.  @xref{RSS}.
 
-  Take a look at w3-menu.el in the Emacs-W3 distribution - this works out
-really well.  Each menu is 'named' by a symbol that would be on a
-gnus-*-menus (where * would be whatever, but at least group, summary, and
-article versions) variable.
+@item
+Single-part yenc encoded attachments can be decoded.
 
-  So for gnus-summary-menus, I would set to '(sort mark dispose ...)
+@item
+Picons
 
-  A value of '1' would just put _all_ the menus in a single 'GNUS' menu in
-the main menubar.  This approach works really well for Emacs-W3 and VM.
+The picons code has been reimplemented to work in GNU Emacs---some of
+the previous options have been removed or renamed.
 
+Picons are small ``personal icons'' representing users, domain and
+newsgroups, which can be displayed in the Article buffer.
+@xref{Picons}.
 
 @item
- nndoc should take care to create unique Message-IDs for all its
-articles.
-@item
- gnus-score-followup-article only works when you have a summary buffer
-active.  Make it work when posting from the group buffer as well.
-(message-sent-hook).
-@item
- rewrite gnus-demon to use run-with-idle-timers.
+If the new option @code{gnus-treat-body-boundary} is non-@code{nil}, a
+boundary line is drawn at the end of the headers.
 
 @item
- * Enhancements to Gnus:
-
-  Add two commands:
-
-  * gnus-servers (gnus-start-server-buffer?)--enters Gnus and goes
-    straight to the server buffer, without opening any connections to
-    servers first.
+Retrieval of charters and control messages
 
-  * gnus-server-read-server-newsrc--produces a buffer very similar to
-    the group buffer, but with only groups from that server listed;
-    quitting this buffer returns to the server buffer.
+There are new commands for fetching newsgroup charters (@kbd{H c}) and
+control messages (@kbd{H C}).
 
 @item
- add a command to check the integrity of an nnfolder folder --
-go through the article numbers and see that there are no duplicates,
-and stuff.
+Delayed articles
 
-@item
- `unsmileyfy-buffer' to undo smileification.
+You can delay the sending of a message with @kbd{C-c C-j} in the Message
+buffer.  The messages are delivered at specified time.  This is useful
+for sending yourself reminders.  @xref{Delayed Articles}.
 
 @item
- a command to give all relevant info on an article, including all
-secondary marks.
+If @code{auto-compression-mode} is enabled, attachments are automatically
+decompressed when activated.
 
 @item
- when doing `-request-accept-article', the backends should do
-the nnmail duplicate checking.
+If the new option @code{nnml-use-compressed-files} is non-@code{nil},
+the nnml back end allows compressed message files.
 
 @item
- allow `message-signature-file' to be a function to return the
-value of the signature file.
+Signed article headers (X-PGP-Sig) can be verified with @kbd{W p}.
 
 @item
- In addition, I would love it if I could configure message-tab so that it
-could call `bbdb-complete-name' in other headers.  So, some sort of
-interface like
+The Summary Buffer uses an arrow in the fringe to indicate the current
+article.  Use @code{(setq gnus-summary-display-arrow nil)} to disable it.
 
-(setq message-tab-alist
-      '((message-header-regexp message-expand-group)
-        ("^\\(To\\|[cC]c\\|[bB]cc\\)"  bbdb-complete-name)))
+@item
+Warn about email replies to news
 
-then you could run the relevant function to complete the information in
-the header
+Do you often find yourself replying to news by email by mistake?  Then
+the new option @code{gnus-confirm-mail-reply-to-news} is just the thing for
+you.
 
 @item
- cache the newsgroups file locally to avoid reloading it all the time.
+If the new option @code{gnus-summary-display-while-building} is
+non-@code{nil}, the summary buffer is shown and updated as it's being
+built.
 
 @item
- a command to import a buffer into a group.
+The new @code{recent} mark @samp{.} indicates newly arrived messages (as
+opposed to old but unread messages).
 
 @item
- nnweb should allow fetching by Message-ID from servers.
+The new option @code{gnus-gcc-mark-as-read} automatically marks
+Gcc articles as read.
 
 @item
- point in the article buffer doesn't always go to the
-beginning of the buffer when selecting new articles.
+The nndoc back end now supports mailman digests and exim bounces.
 
 @item
- a command to process mark all unread articles.
+Gnus supports RFC 2369 mailing list headers, and adds a number of
+related commands in mailing list groups.  @xref{Mailing List}.
 
 @item
- `gnus-gather-threads-by-references-and-subject' -- first
-do gathering by references, and then go through the dummy roots and
-do more gathering by subject.
+The Date header can be displayed in a format that can be read aloud
+in English.  @xref{Article Date}.
 
 @item
- gnus-uu-mark-in-numerical-order -- process mark articles in
-article numerical order.
+The envelope sender address can be customized when using Sendmail.
+@xref{Mail Variables, Mail Variables,, message, Message Manual}.
 
 @item
- (gnus-thread-total-score
- (gnus-id-to-thread (mail-header-id (gnus-summary-article-header))))
-bind to a key.
+diffs are automatically highlighted in groups matching
+@code{mm-uu-diff-groups-regexp}
 
 @item
- sorting by score is wrong when using sparse threads.
+@acronym{TLS} wrapper shipped with Gnus
 
-@item
- a command to fetch an arbitrary article -- without having to be
-in the summary buffer.
+@acronym{TLS}/@acronym{SSL} is now supported in @acronym{IMAP} and
+@acronym{NNTP} via @file{tls.el} and GNUTLS.  The old
+@acronym{TLS}/@acronym{SSL} support via (external third party)
+@file{ssl.el} and OpenSSL still works.
 
 @item
- a new nncvs backend.  Each group would show an article, using
-version branches as threading, checkin date as the date, etc.
+New @file{make.bat} for compiling and installing Gnus under MS Windows
 
-@item
- http://www.dejanews.com/forms/dnsetfilter_exp.html ?
-This filter allows one to construct advance queries on the Dejanews
-database such as specifying start and end dates, subject, author,
-and/or newsgroup name.
+Use @file{make.bat} if you want to install Gnus under MS Windows, the
+first argument to the batch-program should be the directory where
+@file{xemacs.exe} respectively @file{emacs.exe} is located, iff you want
+to install Gnus after compiling it, give @file{make.bat} @code{/copy} as
+the second parameter.
 
-@item
- new Date header scoring type -- older, newer
+@file{make.bat} has been rewritten from scratch, it now features
+automatic recognition of XEmacs and GNU Emacs, generates
+@file{gnus-load.el}, checks if errors occur while compilation and
+generation of info files and reports them at the end of the build
+process.  It now uses @code{makeinfo} if it is available and falls
+back to @file{infohack.el} otherwise.  @file{make.bat} should now
+install all files which are necessary to run Gnus and be generally a
+complete replacement for the @code{configure; make; make install}
+cycle used under Unix systems.
 
-@item
- use the summary toolbar in the article buffer.
+The new @file{make.bat} makes @file{make-x.bat} superfluous, so it has
+been removed.
 
 @item
- a command to fetch all articles that are less than X days old.
+Support for non-@acronym{ASCII} domain names
+
+Message supports non-@acronym{ASCII} domain names in From:, To: and
+Cc: and will query you whether to perform encoding when you try to
+send a message.  The variable @code{message-use-idna} controls this.
+Gnus will also decode non-@acronym{ASCII} domain names in From:, To:
+and Cc: when you view a message.  The variable @code{gnus-use-idna}
+controls this.
 
 @item
- in pick mode, `q' should save the list of selected articles in the
-group info.  The next time the group is selected, these articles
-will automatically get the process mark.
+Better handling of Microsoft citation styles
+
+Gnus now tries to recognize the mangled header block that some Microsoft
+mailers use to indicate that the rest of the message is a citation, even
+though it is not quoted in any way.  The variable
+@code{gnus-cite-unsightly-citation-regexp} matches the start of these
+citations.
 
 @item
- Isn't it possible to (also?) allow M-^ to automatically try the
-default server if it fails on the current server?  (controlled by a
-user variable, (nil, t, 'ask)).
+@code{gnus-article-skip-boring}
+
+If you set @code{gnus-article-skip-boring} to @code{t}, then Gnus will
+not scroll down to show you a page that contains only boring text,
+which by default means cited text and signature.  You can customize
+what is skippable using @code{gnus-article-boring-faces}.
+
+This feature is especially useful if you read many articles that
+consist of a little new content at the top with a long, untrimmed
+message cited below.
 
 @item
- make it possible to cancel articles using the select method for the
-current group.
+The format spec @code{%C} for positioning point has changed to @code{%*}.
 
 @item
- `gnus-summary-select-article-on-entry' or something.  It'll default
-to t and will select whatever article decided by `gnus-auto-select-first'.
+The new variable @code{gnus-parameters} can be used to set group parameters.
+
+Earlier this was done only via @kbd{G p} (or @kbd{G c}), which stored
+the parameters in @file{~/.newsrc.eld}, but via this variable you can
+enjoy the powers of customize, and simplified backups since you set the
+variable in @file{~/.emacs} instead of @file{~/.newsrc.eld}.  The
+variable maps regular expressions matching group names to group
+parameters, a'la:
+@lisp
+(setq gnus-parameters
+      '(("mail\\..*"
+         (gnus-show-threads nil)
+         (gnus-use-scoring nil))
+        ("^nnimap:\\(foo.bar\\)$"
+         (to-group . "\\1"))))
+@end lisp
 
 @item
- a new variable to control which selection commands should be unselecting.
-`first', `best', `next', `prev', `next-unread', `prev-unread' are
-candidates.
+Smileys (@samp{:-)}, @samp{;-)} etc) are now iconized for Emacs too.
+
+Put @code{(setq gnus-treat-display-smileys nil)} in @file{~/.emacs} to
+disable it.
 
 @item
- be able to select groups that have no articles in them
-to be able to post in them (using the current select method).
+Gnus no longer generate the Sender: header automatically.
+
+Earlier it was generated iff the user configurable email address was
+different from the Gnus guessed default user address.  As the guessing
+algorithm is rarely correct these days, and (more controversially) the
+only use of the Sender: header was to check if you are entitled to
+cancel/supersede news (which is now solved by Cancel Locks instead,
+see another entry), generation of the header has been disabled by
+default.  See the variables @code{message-required-headers},
+@code{message-required-news-headers}, and
+@code{message-required-mail-headers}.
 
 @item
- be able to post via DejaNews.
+Features from third party @file{message-utils.el} added to @file{message.el}.
+
+Message now asks if you wish to remove @samp{(was: <old subject>)} from
+subject lines (see @code{message-subject-trailing-was-query}).  @kbd{C-c
+M-m} and @kbd{C-c M-f} inserts markers indicating included text.
+@kbd{C-c C-f a} adds a X-No-Archive: header.  @kbd{C-c C-f x} inserts
+appropriate headers and a note in the body for cross-postings and
+followups (see the variables @code{message-cross-post-@var{*}}).
 
 @item
- `x' should retain any sortings that have been performed.
+References and X-Draft-Headers are no longer generated when you start
+composing messages and @code{message-generate-headers-first} is
+@code{nil}.
 
 @item
- allow the user to specify the presedence of the secondary marks.  Also
-allow them to be displayed separately.
+Improved anti-spam features.
+
+Gnus is now able to take out spam from your mail and news streams
+using a wide variety of programs and filter rules.  Among the supported
+methods are RBL blocklists, bogofilter and white/blacklists.  Hooks
+for easy use of external packages such as SpamAssassin and Hashcash
+are also new.  @xref{Thwarting Email Spam}.
 
 @item
- gnus-summary-save-in-pipe should concatenate the results from
-the processes when doing a process marked pipe.
+Easy inclusion of X-Faces headers.
 
 @item
- a new match type, like Followup, but which adds Thread matches on all
-articles that match a certain From header.
+Face headers handling.
 
 @item
- a function that can be read from kill-emacs-query-functions to offer
-saving living summary buffers.
+In the summary buffer, the new command @kbd{/ N} inserts new messages
+and @kbd{/ o} inserts old messages.
 
 @item
- a function for selecting a particular group which will contain
-the articles listed in a list of article numbers/id's.
+Gnus decodes morse encoded messages if you press @kbd{W m}.
 
 @item
- a battery of character translation functions to translate common
-Mac, MS (etc) characters into ISO 8859-1.
+Unread count correct in nnimap groups.
 
-@example
-(defun article-fix-m$word ()
-  "Fix M$Word smartquotes in an article."
-  (interactive)
-  (save-excursion
-    (let ((buffer-read-only nil))
-      (goto-char (point-min))
-      (while (search-forward "\221" nil t)
-       (replace-match "`" t t))
-      (goto-char (point-min))
-      (while (search-forward "\222" nil t)
-       (replace-match "'" t t))
-      (goto-char (point-min))
-      (while (search-forward "\223" nil t)
-       (replace-match "\"" t t))
-      (goto-char (point-min))
-      (while (search-forward "\224" nil t)
-       (replace-match "\"" t t)))))
-@end example
+The estimated number of unread articles in the group buffer should now
+be correct for nnimap groups.  This is achieved by calling
+@code{nnimap-fixup-unread-after-getting-new-news} from the
+@code{gnus-setup-news-hook} (called on startup) and
+@code{gnus-after-getting-new-news-hook}. (called after getting new
+mail).  If you have modified those variables from the default, you may
+want to add @code{nnimap-fixup-unread-after-getting-new-news} again.  If
+you were happy with the estimate and want to save some (minimal) time
+when getting new mail, remove the function.
 
 @item
-@example
- (add-hook 'gnus-exit-query-functions
-'(lambda ()
-   (if (and (file-exists-p nnmail-spool-file)
-           (> (nnheader-file-size nnmail-spool-file) 0))
-       (yes-or-no-p "New mail has arrived.  Quit Gnus anyways? ")
-       (y-or-n-p "Are you sure you want to quit Gnus? "))))
-@end example
+Group Carbon Copy (GCC) quoting
 
-@item
- allow message-default-headers to be a function.
+To support groups that contains SPC and other weird characters, groups
+are quoted before they are placed in the Gcc: header.  This means
+variables such as @code{gnus-message-archive-group} should no longer
+contain quote characters to make groups containing SPC work.  Also, if
+you are using the string @samp{nnml:foo, nnml:bar} (indicating Gcc
+into two groups) you must change it to return the list
+@code{("nnml:foo" "nnml:bar")}, otherwise the Gcc: line will be quoted
+incorrectly.  Note that returning the string @samp{nnml:foo, nnml:bar}
+was incorrect earlier, it just didn't generate any problems since it
+was inserted directly.
 
 @item
- new Date score match types -- < > = (etc) that take floating point
-numbers and match on the age of the article.
+@file{~/News/overview/} not used.
 
-@item
- gnus-cacheable-groups
+As a result of the following change, the @file{~/News/overview/}
+directory is not used any more.  You can safely delete the entire
+hierarchy.
 
 @item
-@example
->  > > If so, I've got one gripe: It seems that when I fire up gnus 5.2.25
->  > > under xemacs-19.14, it's creating a new frame, but is erasing the
->  > > buffer in the frame that it was called from =:-O
-> 
->  > Hm.  How do you start up Gnus?  From the toolbar or with
->  > `M-x gnus-other-frame'?  
-> 
->    I normally start it up from the toolbar; at
-> least that's the way I've caught it doing the
-> deed before.
-@end example
+@code{gnus-agent}
 
-@item
- all commands that react to the process mark should push
-the current process mark set onto the stack.
+The Gnus Agent has seen a major updated and is now enabled by default,
+and all nntp and nnimap servers from @code{gnus-select-method} and
+@code{gnus-secondary-select-method} are agentized by default.  Earlier
+only the server in @code{gnus-select-method} was agentized by the
+default, and the agent was disabled by default.  When the agent is
+enabled, headers are now also retrieved from the Agent cache instead
+of the back ends when possible.  Earlier this only happened in the
+unplugged state.  You can enroll or remove servers with @kbd{J a} and
+@kbd{J r} in the server buffer.  Gnus will not download articles into
+the Agent cache, unless you instruct it to do so, though, by using
+@kbd{J u} or @kbd{J s} from the Group buffer.  You revert to the old
+behaviour of having the Agent disabled with @code{(setq gnus-agent
+nil)}.  Note that putting @code{(gnus-agentize)} in @file{~/.gnus.el}
+is not needed any more.
 
 @item
- gnus-article-hide-pgp
-Selv ville jeg nok ha valgt Ã¥ slette den dersom teksten matcher
-@example
-"\\(This\s+\\)?[^ ]+ has been automatically signed by"
-@end example
-og det er maks hundre tegn mellom match-end og ----linja.  Men -det-
-er min type heuristikk og langt fra alles.
+@code{gnus-summary-line-format}
 
-@item
- `gnus-subscribe-sorted' -- insert new groups where they would have been
-sorted to if `gnus-group-sort-function' were run.
+The default value changed to @samp{%U%R%z%I%(%[%4L: %-23,23f%]%)
+%s\n}.  Moreover @code{gnus-extra-headers},
+@code{nnmail-extra-headers} and @code{gnus-ignored-from-addresses}
+changed their default so that the users name will be replaced by the
+recipient's name or the group name posting to for @acronym{NNTP}
+groups.
 
 @item
- gnus-(group,summary)-highlight should respect any `face' text props set
-on the lines.
+@file{deuglify.el} (@code{gnus-article-outlook-deuglify-article})
+
+A new file from Raymond Scholz @email{rscholz@@zonix.de} for deuglifying
+broken Outlook (Express) articles.
 
 @item
- use run-with-idle-timer for gnus-demon instead of the
-home-brewed stuff for better reliability.
+@code{(require 'gnus-load)}
+
+If you use a stand-alone Gnus distribution, you'd better add
+@code{(require 'gnus-load)} into your @file{~/.emacs} after adding the Gnus
+lisp directory into load-path.
+
+File @file{gnus-load.el} contains autoload commands, functions and variables,
+some of which may not be included in distributions of Emacsen.
 
 @item
- add a way to select which NoCeM type to apply -- spam, troll, etc.
+@code{gnus-slave-unplugged}
+
+A new command which starts Gnus offline in slave mode.
 
 @item
- nndraft-request-group should tally autosave files.
+@code{message-insinuate-rmail}
+
+Adding @code{(message-insinuate-rmail)} and @code{(setq
+mail-user-agent 'gnus-user-agent)} in @file{.emacs} convinces Rmail to
+compose, reply and forward messages in message-mode, where you can
+enjoy the power of @acronym{MML}.
 
 @item
- implement nntp-retry-on-break and nntp-command-timeout.
+@code{message-minibuffer-local-map}
+
+The line below enables BBDB in resending a message:
+@lisp
+(define-key message-minibuffer-local-map [(tab)]
+  'bbdb-complete-name)
+@end lisp
 
 @item
- gnus-article-highlight-limit that says when not to highlight (long)
-articles.
+Externalizing and deleting of attachments.
+
+If @code{gnus-gcc-externalize-attachments} or
+@code{message-fcc-externalize-attachments} is non-@code{nil}, attach
+local files as external parts.
+
+The command @code{gnus-mime-save-part-and-strip} (bound to @kbd{C-o}
+on @acronym{MIME} buttons) saves a part and replaces the part with an
+external one.  @code{gnus-mime-delete-part} (bound to @kbd{d} on
+@acronym{MIME} buttons) removes a part.  It works only on back ends
+that support editing.
 
 @item
- (nnoo-set SERVER VARIABLE VALUE)
+@code{gnus-default-charset}
+
+The default value is determined from the
+@code{current-language-environment} variable, instead of
+@code{iso-8859-1}.  Also the @samp{.*} item in
+@code{gnus-group-charset-alist} is removed.
 
 @item
- nn*-spool-methods
+@code{gnus-posting-styles}
+
+Add a new format of match like
+@lisp
+((header "to" "larsi.*org")
+ (Organization "Somewhere, Inc."))
+@end lisp
+The old format like the lines below is obsolete, but still accepted.
+@lisp
+(header "to" "larsi.*org"
+        (Organization "Somewhere, Inc."))
+@end lisp
 
 @item
- interrupitng agent fetching of articles should save articles.
+@code{message-ignored-news-headers} and @code{message-ignored-mail-headers}
+
+@samp{X-Draft-From} and @samp{X-Gnus-Agent-Meta-Information} have been
+added into these two variables.  If you customized those, perhaps you
+need add those two headers too.
 
 @item
- command to open a digest group, and copy all the articles there to the
-current group.
+Gnus reads the @acronym{NOV} and articles in the Agent if plugged.
+
+If one reads an article while plugged, and the article already exists
+in the Agent, it won't get downloaded once more.  @code{(setq
+gnus-agent-cache nil)} reverts to the old behavior.
 
 @item
- a variable to disable article body highlights if there's more than
-X characters in the body.
+Gnus supports the ``format=flowed'' (RFC 2646) parameter.  On
+composing messages, it is enabled by @code{use-hard-newlines}.
+Decoding format=flowed was present but not documented in earlier
+versions.
 
 @item
- handle 480/381 authinfo requests separately.
+Gnus supports the generation of RFC 2298 Disposition Notification requests.
+
+This is invoked with the @kbd{C-c M-n} key binding from message mode.
 
 @item
- include the texi/dir file in the distribution.
+Gnus supports Maildir groups.
+
+Gnus includes a new back end @file{nnmaildir.el}.  @xref{Maildir}.
 
 @item
- format spec to "tab" to a position.
+Printing capabilities are enhanced.
+
+Gnus supports Muttprint natively with @kbd{O P} from the Summary and
+Article buffers.  Also, each individual @acronym{MIME} part can be
+printed using @kbd{p} on the @acronym{MIME} button.
 
 @item
- Move all prompting to the new `M-n' default style.
+Message supports the Importance: (RFC 2156) header.
+
+In the message buffer, @kbd{C-c C-f C-i} or @kbd{C-c C-u} cycles through
+the valid values.
 
 @item
- command to display all dormant articles.
+Gnus supports Cancel Locks in News.
+
+This means a header @samp{Cancel-Lock} is inserted in news posting.  It is
+used to determine if you wrote an article or not (for canceling and
+superseding).  Gnus generates a random password string the first time
+you post a message, and saves it in your @file{~/.emacs} using the Custom
+system.  While the variable is called @code{canlock-password}, it is not
+security sensitive data.  Publishing your canlock string on the web
+will not allow anyone to be able to anything she could not already do.
+The behaviour can be changed by customizing @code{message-insert-canlock}.
 
 @item
- gnus-auto-select-next makeover -- list of things it should do.
+Gnus supports server-side mail filtering using Sieve.
+
+Sieve rules can be added as Group Parameters for groups, and the
+complete Sieve script is generated using @kbd{D g} from the Group
+buffer, and then uploaded to the server using @kbd{C-c C-l} in the
+generated Sieve buffer.  @xref{Sieve Commands}, and the new Sieve
+manual @ref{Top, , Top, sieve, Emacs Sieve}.
 
 @item
- a score match type that adds scores matching on From if From has replied
-to something someone else has said.
+Extended format specs.
+
+Format spec @samp{%&user-date;} is added into
+@code{gnus-summary-line-format-alist}.  Also, user defined extended
+format specs are supported.  The extended format specs look like
+@samp{%u&foo;}, which invokes function
+@code{gnus-user-format-function-@var{foo}}.  Because @samp{&} is used as the
+escape character, old user defined format @samp{%u&} is no longer supported.
 
 @item
- Read Netscape discussion groups:
-snews://secnews.netscape.com/netscape.communicator.unix 
+@kbd{/ *} (@code{gnus-summary-limit-include-cached}) is rewritten.
+
+It was aliased to @kbd{Y c}
+(@code{gnus-summary-insert-cached-articles}).  The new function filters
+out other articles.
+
+@item Some limiting commands accept a @kbd{C-u} prefix to negate the match.
+
+If @kbd{C-u} is used on subject, author or extra headers, i.e., @kbd{/
+s}, @kbd{/ a}, and @kbd{/ x}
+(@code{gnus-summary-limit-to-@{subject,author,extra@}}) respectively, the
+result will be to display all articles that do not match the expression.
 
 @item
-One command to edit the original version if an article, and one to edit
-the displayed version.
+Group names are treated as UTF-8 by default.
+
+This is supposedly what USEFOR wanted to migrate to.  See
+@code{gnus-group-name-charset-group-alist} and
+@code{gnus-group-name-charset-method-alist} for customization.
 
 @item
-@kbd{T v} -- make all process-marked articles the children of the
-current article.
+The nnml and nnfolder back ends store marks for each groups.
+
+This makes it possible to take backup of nnml/nnfolder servers/groups
+separately of @file{~/.newsrc.eld}, while preserving marks.  It also
+makes it possible to share articles and marks between users (without
+sharing the @file{~/.newsrc.eld} file) within e.g. a department.  It
+works by storing the marks stored in @file{~/.newsrc.eld} in a per-group
+file @file{.marks} (for nnml) and @file{@var{groupname}.mrk} (for
+nnfolder, named @var{groupname}).  If the nnml/nnfolder is moved to
+another machine, Gnus will automatically use the @file{.marks} or
+@file{.mrk} file instead of the information in @file{~/.newsrc.eld}.
+The new server variables @code{nnml-marks-is-evil} and
+@code{nnfolder-marks-is-evil} can be used to disable this feature.
 
 @item
-Switch from initial text to the new default text mechanism.
+The menu bar item (in Group and Summary buffer) named ``Misc'' has
+been renamed to ``Gnus''.
 
 @item
-How about making it possible to expire local articles?  Will it be
-possible to make various constraints on when an article can be
-expired, e.g. (read), (age > 14 days), or the more interesting (read
-& age > 14 days)?
+The menu bar item (in Message mode) named ``@acronym{MML}'' has been
+renamed to ``Attachments''.  Note that this menu also contains security
+related stuff, like signing and encryption (@pxref{Security, Security,,
+message, Message Manual}).
 
 @item
-New limit command---limit to articles that have a certain string
-in the head or body.
+@code{gnus-group-charset-alist} and
+@code{gnus-group-ignored-charsets-alist}.
+
+The regexps in these variables are compared with full group names
+instead of real group names in 5.8.  Users who customize these
+variables should change those regexps accordingly.  For example:
+@lisp
+("^han\\>" euc-kr) -> ("\\(^\\|:\\)han\\>" euc-kr)
+@end lisp
 
 @item
-Allow breaking lengthy NNTP commands.
+Gnus supports @acronym{PGP} (RFC 1991/2440), @acronym{PGP/MIME} (RFC
+2015/3156) and @acronym{S/MIME} (RFC 2630-2633).
+
+It needs an external @acronym{S/MIME} and OpenPGP implementation, but no
+additional Lisp libraries.  This add several menu items to the
+Attachments menu, and @kbd{C-c RET} key bindings, when composing
+messages.  This also obsoletes @code{gnus-article-hide-pgp-hook}.
 
 @item
-gnus-article-highlight-limit, to disable highlighting in big articles. 
+Gnus inlines external parts (message/external).
 
 @item
-Editing an article should put the article to be edited
-in a special, unique buffer.
+@acronym{MML} (Mime compose) prefix changed from @kbd{M-m} to @kbd{C-c
+C-m}.
+
+This change was made to avoid conflict with the standard binding of
+@code{back-to-indentation}, which is also useful in message mode.
 
 @item
-Solve the halting problem.
+The default for @code{message-forward-show-mml} changed to symbol @code{best}.
 
-@c TODO
+The behaviour for the @code{best} value is to show @acronym{MML} (i.e.,
+convert to @acronym{MIME}) when appropriate.  @acronym{MML} will not be
+used when forwarding signed or encrypted messages, as the conversion
+invalidate the digital signature.
 @end itemize
 
 @iftex
@@ -17320,7 +26239,7 @@ This manual was generated from a TeXinfo file and then run through
 either @code{texi2dvi}
 @iflatex
 or my own home-brewed TeXinfo to \LaTeX\ transformer,
-and then run through @code{latex} and @code{dvips} 
+and then run through @code{latex} and @code{dvips}
 @end iflatex
 to get what you hold in your hands now.
 
@@ -17337,7 +26256,7 @@ This is a @kbd{keystroke}
 @item
 This is a @file{file}
 
-@item 
+@item
 This is a @code{symbol}
 
 @end enumerate
@@ -17372,6 +26291,26 @@ of the mysteries of this world, I guess.)
 @end iftex
 
 
+@node On Writing Manuals
+@section On Writing Manuals
+
+I guess most manuals are written after-the-fact; documenting a program
+that's already there.  This is not how this manual is written.  When
+implementing something, I write the manual entry for that something
+straight away.  I then see that it's difficult to explain the
+functionality, so I write how it's supposed to be, and then I change the
+implementation.  Writing the documentation and writing the code goes
+hand in hand.
+
+This, of course, means that this manual has no, or little, flow.  It
+documents absolutely everything in Gnus, but often not where you're
+looking for it.  It is a reference manual, and not a guide to how to get
+started with Gnus.
+
+That would be a totally different book, that should be written using the
+reference manual as source material.  It would look quite differently.
+
+
 @page
 @node Terminology
 @section Terminology
@@ -17382,7 +26321,7 @@ of the mysteries of this world, I guess.)
 @item news
 @cindex news
 This is what you are supposed to use this thing for---reading news.
-News is generally fetched from a nearby @sc{nntp} server, and is
+News is generally fetched from a nearby @acronym{NNTP} server, and is
 generally publicly available to everybody.  If you post news, the entire
 world is likely to read just what you have written, and they'll all
 snigger mischievously.  Behind your back.
@@ -17403,26 +26342,49 @@ Send a mail to the person who has written what you are reading.
 Post an article to the current newsgroup responding to the article you
 are reading.
 
-@item backend
-@cindex backend
-Gnus gets fed articles from a number of backends, both news and mail
-backends.  Gnus does not handle the underlying media, so to speak---this
-is all done by the backends.
+@item back end
+@cindex back end
+Gnus considers mail and news to be mostly the same, really.  The only
+difference is how to access the actual articles.  News articles are
+commonly fetched via the protocol @acronym{NNTP}, whereas mail
+messages could be read from a file on the local disk.  The internal
+architecture of Gnus thus comprises a ``front end'' and a number of
+``back ends''.  Internally, when you enter a group (by hitting
+@key{RET}, say), you thereby invoke a function in the front end in
+Gnus.  The front end then ``talks'' to a back end and says things like
+``Give me the list of articles in the foo group'' or ``Show me article
+number 4711''.
+
+So a back end mainly defines either a protocol (the @code{nntp} back
+end accesses news via @acronym{NNTP}, the @code{nnimap} back end
+accesses mail via @acronym{IMAP}) or a file format and directory
+layout (the @code{nnspool} back end accesses news via the common
+``spool directory'' format, the @code{nnml} back end access mail via a
+file format and directory layout that's quite similar).
+
+Gnus does not handle the underlying media, so to speak---this is all
+done by the back ends.  A back end is a collection of functions to
+access the articles.
+
+However, sometimes the term ``back end'' is also used where ``server''
+would have been more appropriate.  And then there is the term ``select
+method'' which can mean either.  The Gnus terminology can be quite
+confusing.
 
 @item native
 @cindex native
-Gnus will always use one method (and backend) as the @dfn{native}, or
+Gnus will always use one method (and back end) as the @dfn{native}, or
 default, way of getting news.
 
 @item foreign
 @cindex foreign
 You can also have any number of foreign groups active at the same time.
-These are groups that use non-native non-secondary backends for getting
+These are groups that use non-native non-secondary back ends for getting
 news.
 
 @item secondary
 @cindex secondary
-Secondary backends are somewhere half-way between being native and being
+Secondary back ends are somewhere half-way between being native and being
 foreign, but they mostly act like they are native.
 
 @item article
@@ -17433,7 +26395,7 @@ A message that has been posted as news.
 @cindex mail message
 A message that has been mailed.
 
-@item message 
+@item message
 @cindex message
 A mail message or news article
 
@@ -17445,20 +26407,20 @@ put.
 @item body
 @cindex body
 The rest of an article.  Everything not in the head is in the
-body. 
+body.
 
 @item header
 @cindex header
-A line from the head of an article. 
+A line from the head of an article.
 
 @item headers
 @cindex headers
 A collection of such lines, or a collection of heads.  Or even a
-collection of @sc{nov} lines.
+collection of @acronym{NOV} lines.
 
-@item @sc{nov}
-@cindex nov
-When Gnus enters a group, it asks the backend for the headers of all
+@item @acronym{NOV}
+@cindex @acronym{NOV}
+When Gnus enters a group, it asks the back end for the headers of all
 unread articles in the group.  Most servers support the News OverView
 format, which is more compact and much faster to read and parse than the
 normal @sc{head} format.
@@ -17499,13 +26461,13 @@ The act of asking the server for info on a group and computing the
 number of unread articles is called @dfn{activating the group}.
 Un-activated groups are listed with @samp{*} in the group buffer.
 
-@item server 
+@item server
 @cindex server
 A machine one can connect to and get news (or mail) from.
 
 @item select method
 @cindex select method
-A structure that specifies the backend, the server and the virtual
+A structure that specifies the back end, the server and the virtual
 server settings.
 
 @item virtual server
@@ -17518,13 +26480,14 @@ whole is a virtual server.
 @cindex washing
 Taking a buffer and running it through a filter of some sort.  The
 result will (more often than not) be cleaner and more pleasing than the
-original. 
+original.
 
 @item ephemeral groups
 @cindex ephemeral groups
+@cindex temporary groups
 Most groups store data on what articles you have read.  @dfn{Ephemeral}
 groups are groups that will have no data stored---when you exit the
-group, it'll disappear into the aether.  
+group, it'll disappear into the aether.
 
 @item solid groups
 @cindex solid groups
@@ -17558,7 +26521,14 @@ An article that responds to a different article---its parent.
 @item digest
 @cindex digest
 A collection of messages in one file.  The most common digest format is
-specified by RFC1153.
+specified by RFC 1153.
+
+@item splitting
+@cindex splitting, terminolgy
+@cindex mail sorting
+@cindex mail filtering (splitting)
+The action of sorting your emails according to certain rules. Sometimes
+incorrectly called mail filtering.
 
 @end table
 
@@ -17573,19 +26543,19 @@ section is designed to give general pointers on how to customize Gnus
 for some quite common situations.
 
 @menu
-* Slow/Expensive Connection:: You run a local Emacs and get the news elsewhere.
-* Slow Terminal Connection::  You run a remote Emacs.
-* Little Disk Space::         You feel that having large setup files is icky.
-* Slow Machine::              You feel like buying a faster machine.
+* Slow/Expensive Connection::   You run a local Emacs and get the news elsewhere.
+* Slow Terminal Connection::    You run a remote Emacs.
+* Little Disk Space::           You feel that having large setup files is icky.
+* Slow Machine::                You feel like buying a faster machine.
 @end menu
 
 
 @node Slow/Expensive Connection
-@subsection Slow/Expensive @sc{nntp} Connection
+@subsection Slow/Expensive NNTP Connection
 
 If you run Emacs on a machine locally, and get your news from a machine
 over some very thin strings, you want to cut down on the amount of data
-Gnus has to get from the @sc{nntp} server.
+Gnus has to get from the @acronym{NNTP} server.
 
 @table @code
 
@@ -17598,7 +26568,7 @@ doesn't suddenly decide to fetch the active file anyway.
 
 @item gnus-nov-is-evil
 This one has to be @code{nil}.  If not, grabbing article headers from
-the @sc{nntp} server will not be very fast.  Not all @sc{nntp} servers
+the @acronym{NNTP} server will not be very fast.  Not all @acronym{NNTP} servers
 support @sc{xover}; Gnus will detect this by itself.
 @end table
 
@@ -17624,12 +26594,11 @@ minimum.  You can, in fact, make do without them altogether---most of the
 useful data is in the summary buffer, anyway.  Set this variable to
 @samp{^NEVVVVER} or @samp{From:}, or whatever you feel you need.
 
-@item gnus-article-display-hook
 Set this hook to all the available hiding commands:
 @lisp
-(setq gnus-article-display-hook 
-      '(gnus-article-hide-headers gnus-article-hide-signature
-        gnus-article-hide-citation))
+(setq gnus-treat-hide-headers 'head
+      gnus-treat-hide-signature t
+      gnus-treat-hide-citation t)
 @end lisp
 
 @item gnus-use-full-window
@@ -17642,6 +26611,7 @@ want to read them anyway.
 If this is non-@code{nil}, all threads in the summary buffer will be
 hidden initially.
 
+
 @item gnus-updated-mode-lines
 If this is @code{nil}, Gnus will not put information in the buffer mode
 lines, which might save some time.
@@ -17661,7 +26631,13 @@ sizes a bit if you are running out of space.
 If this is @code{nil}, Gnus will never save @file{.newsrc}---it will
 only save @file{.newsrc.eld}.  This means that you will not be able to
 use any other newsreaders than Gnus.  This variable is @code{t} by
-default. 
+default.
+
+@item gnus-read-newsrc-file
+If this is @code{nil}, Gnus will never read @file{.newsrc}---it will
+only read @file{.newsrc.eld}.  This means that you will not be able to
+use any other newsreaders than Gnus.  This variable is @code{t} by
+default.
 
 @item gnus-save-killed-list
 If this is @code{nil}, Gnus will not save the list of dead groups.  You
@@ -17686,9 +26662,6 @@ Set @code{gnus-show-threads}, @code{gnus-use-cross-reference} and
 @code{gnus-nov-is-evil} to @code{nil} to make entering and exiting the
 summary buffer faster.
 
-Set @code{gnus-article-display-hook} to @code{nil} to make article
-processing a bit faster.
-
 
 @page
 @node Troubleshooting
@@ -17712,13 +26685,13 @@ Gnus will work.
 
 @item
 Try doing an @kbd{M-x gnus-version}.  If you get something that looks
-like @samp{Gnus v5.46; nntp 4.0} you have the right files loaded.  If,
-on the other hand, you get something like @samp{NNTP 3.x} or @samp{nntp
-flee}, you have some old @file{.el} files lying around.  Delete these.
+like @samp{T-gnus 6.16.* (based on Gnus v5.10.*; for SEMI 1.1*, FLIM
+1.1*)} you have the right files loaded.  Otherwise you have some old
+@file{.el} files lying around.  Delete these.
 
 @item
-Read the help group (@kbd{G h} in the group buffer) for a FAQ and a
-how-to. 
+Read the help group (@kbd{G h} in the group buffer) for a
+@acronym{FAQ} and a how-to.
 
 @item
 @vindex max-lisp-eval-depth
@@ -17736,7 +26709,7 @@ If all else fails, report the problem as a bug.
 @kindex M-x gnus-bug
 @findex gnus-bug
 If you find a bug in Gnus, you can report it with the @kbd{M-x gnus-bug}
-command. @kbd{M-x set-variable RET debug-on-error RET t RET}, and send
+command.  @kbd{M-x set-variable RET debug-on-error RET t RET}, and send
 me the backtrace.  I will fix bugs, but I can only fix them if you send
 me a precise description as to how to reproduce the bug.
 
@@ -17744,7 +26717,7 @@ You really can never be too detailed in a bug report.  Always use the
 @kbd{M-x gnus-bug} command when you make bug reports, even if it creates
 a 10Kb mail each time you use it, and even if you have sent me your
 environment 500 times before.  I don't care.  I want the full info each
-time.  
+time.
 
 It is also important to remember that I have no memory whatsoever.  If
 you send a bug report, and I send you a reply, and then you just send
@@ -17758,18 +26731,61 @@ it, copy the Emacs window to a file (with @code{xwd}, for instance), put
 it somewhere it can be reached, and include the URL of the picture in
 the bug report.
 
-If you just need help, you are better off asking on
-@samp{gnu.emacs.gnus}.  I'm not very helpful.
+@cindex patches
+If you would like to contribute a patch to fix bugs or make
+improvements, please produce the patch using @samp{diff -u}.
+
+@cindex edebug
+If you want to debug your problem further before reporting, possibly
+in order to solve the problem yourself and send a patch, you can use
+edebug.  Debugging Lisp code is documented in the Elisp manual
+(@pxref{Debugging, , Debugging Lisp Programs, elisp, The GNU Emacs
+Lisp Reference Manual}).  To get you started with edebug, consider if
+you discover some weird behaviour when pressing @kbd{c}, the first
+step is to do @kbd{C-h k c} and click on the hyperlink (Emacs only) in
+the documentation buffer that leads you to the function definition,
+then press @kbd{M-x edebug-defun RET} with point inside that function,
+return to Gnus and press @kbd{c} to invoke the code.  You will be
+placed in the lisp buffer and can single step using @kbd{SPC} and
+evaluate expressions using @kbd{M-:} or inspect variables using
+@kbd{C-h v}, abort execution with @kbd{q}, and resume execution with
+@kbd{c} or @kbd{g}.
+
+@cindex elp
+@cindex profile
+@cindex slow
+Sometimes, a problem do not directly generate an elisp error but
+manifests itself by causing Gnus to be very slow.  In these cases, you
+can use @kbd{M-x toggle-debug-on-quit} and press @kbd{C-g} when things are
+slow, and then try to analyze the backtrace (repeating the procedure
+helps isolating the real problem areas).
+
+A fancier approach is to use the elisp profiler, ELP.  The profiler is
+(or should be) fully documented elsewhere, but to get you started
+there are a few steps that need to be followed.  First, instrument the
+part of Gnus you are interested in for profiling, e.g. @kbd{M-x
+elp-instrument-package RET gnus} or @kbd{M-x elp-instrument-package
+RET message}.  Then perform the operation that is slow and press
+@kbd{M-x elp-results}.  You will then see which operations that takes
+time, and can debug them further.  If the entire operation takes much
+longer than the time spent in the slowest function in the profiler
+output, you probably profiled the wrong part of Gnus.  To reset
+profiling statistics, use @kbd{M-x elp-reset-all}.  @kbd{M-x
+elp-restore-all} is supposed to remove profiling, but given the
+complexities and dynamic code generation in Gnus, it might not always
+work perfectly.
 
 @cindex gnu.emacs.gnus
 @cindex ding mailing list
-You can also ask on the ding mailing list---@samp{ding@@gnus.org}.
-Write to @samp{ding-request@@gnus.org} to subscribe.
+If you just need help, you are better off asking on
+@samp{gnu.emacs.gnus}.  I'm not very helpful.  You can also ask on
+@email{ding@@gnus.org, the ding mailing list}.  Write to
+@email{ding-request@@gnus.org} to subscribe.
 
 
 @page
-@node A Programmers Guide to Gnus
-@section A Programmer@'s Guide to Gnus
+@node Gnus Reference Guide
+@section Gnus Reference Guide
 
 It is my hope that other people will figure out smart stuff that Gnus
 can do, and that other people will write those smart things as well.  To
@@ -17779,20 +26795,20 @@ it.
 
 You can never expect the internals of a program not to change, but I
 will be defining (in some details) the interface between Gnus and its
-backends (this is written in stone), the format of the score files
+back ends (this is written in stone), the format of the score files
 (ditto), data structures (some are less likely to change than others)
 and general methods of operation.
 
-@menu 
-* Gnus Utility Functions::   Common functions and variable to use.
-* Backend Interface::        How Gnus communicates with the servers.
-* Score File Syntax::        A BNF definition of the score file standard.
-* Headers::                  How Gnus stores headers internally.
-* Ranges::                   A handy format for storing mucho numbers.
-* Group Info::               The group info format.
-* Extended Interactive::     Symbolic prefixes and stuff.
-* Emacs/XEmacs Code::        Gnus can be run under all modern Emacsen.
-* Various File Formats::     Formats of files that Gnus use.
+@menu
+* Gnus Utility Functions::      Common functions and variable to use.
+* Back End Interface::          How Gnus communicates with the servers.
+* Score File Syntax::           A BNF definition of the score file standard.
+* Headers::                     How Gnus stores headers internally.
+* Ranges::                      A handy format for storing mucho numbers.
+* Group Info::                  The group info format.
+* Extended Interactive::        Symbolic prefixes and stuff.
+* Emacs/XEmacs Code::           Gnus can be run under all modern Emacsen.
+* Various File Formats::        Formats of files that Gnus use.
 @end menu
 
 
@@ -17831,6 +26847,19 @@ Takes an unprefixed group name and a select method, and returns the full
 @findex gnus-get-info
 Returns the group info list for @var{group}.
 
+@item gnus-group-unread
+@findex gnus-group-unread
+The number of unread articles in @var{group}, or @code{t} if that is
+unknown.
+
+@item gnus-active
+@findex gnus-active
+The active entry for @var{group}.
+
+@item gnus-set-active
+@findex gnus-set-active
+Set the active entry for @var{group}.
+
 @item gnus-add-current-to-buffer-list
 @findex gnus-add-current-to-buffer-list
 Adds the current buffer to the list of buffers to be killed on Gnus
@@ -17848,7 +26877,7 @@ Says whether @var{group} is read-only or not.
 
 @item gnus-news-group-p
 @findex gnus-news-group-p
-Says whether @var{group} came from a news backend.
+Says whether @var{group} came from a news back end.
 
 @item gnus-ephemeral-group-p
 @findex gnus-ephemeral-group-p
@@ -17874,8 +26903,8 @@ Says whether @var{group} is secondary or not.
 @findex gnus-group-foreign-p
 Says whether @var{group} is foreign or not.
 
-@item group-group-find-parameter
-@findex group-group-find-parameter
+@item gnus-group-find-parameter
+@findex gnus-group-find-parameter
 Returns the parameter list of @var{group}.  If given a second parameter,
 returns the value of that parameter for @var{group}.
 
@@ -17889,12 +26918,12 @@ Narrows the current buffer to the body of the article.
 
 @item gnus-check-backend-function
 @findex gnus-check-backend-function
-Takes two parameters, @var{function} and @var{group}.  If the backend
+Takes two parameters, @var{function} and @var{group}.  If the back end
 @var{group} comes from supports @var{function}, return non-@code{nil}.
 
 @lisp
 (gnus-check-backend-function "request-scan" "nnml:misc")
-=> t
+@result{} t
 @end lisp
 
 @item gnus-read-method
@@ -17904,19 +26933,19 @@ Prompts the user for a select method.
 @end table
 
 
-@node Backend Interface
-@subsection Backend Interface
+@node Back End Interface
+@subsection Back End Interface
 
-Gnus doesn't know anything about @sc{nntp}, spools, mail or virtual
+Gnus doesn't know anything about @acronym{NNTP}, spools, mail or virtual
 groups.  It only knows how to talk to @dfn{virtual servers}.  A virtual
-server is a @dfn{backend} and some @dfn{backend variables}.  As examples
+server is a @dfn{back end} and some @dfn{back end variables}.  As examples
 of the first, we have @code{nntp}, @code{nnspool} and @code{nnmbox}.  As
 examples of the latter we have @code{nntp-port-number} and
 @code{nnmbox-directory}.
 
-When Gnus asks for information from a backend---say @code{nntp}---on
+When Gnus asks for information from a back end---say @code{nntp}---on
 something, it will normally include a virtual server name in the
-function parameters.  (If not, the backend should use the ``current''
+function parameters.  (If not, the back end should use the ``current''
 virtual server.)  For instance, @code{nntp-request-list} takes a virtual
 server as its only (optional) parameter.  If this virtual server hasn't
 been opened, the function should fail.
@@ -17925,17 +26954,17 @@ Note that a virtual server name has no relation to some physical server
 name.  Take this example:
 
 @lisp
-(nntp "odd-one" 
-      (nntp-address "ifi.uio.no") 
+(nntp "odd-one"
+      (nntp-address "ifi.uio.no")
       (nntp-port-number 4324))
 @end lisp
 
 Here the virtual server name is @samp{odd-one} while the name of
-the physical server is @samp{ifi.uio.no}. 
+the physical server is @samp{ifi.uio.no}.
 
-The backends should be able to switch between several virtual servers.
-The standard backends implement this by keeping an alist of virtual
-server environments that they pull down/push up when needed.  
+The back ends should be able to switch between several virtual servers.
+The standard back ends implement this by keeping an alist of virtual
+server environments that they pull down/push up when needed.
 
 There are two groups of interface functions: @dfn{required functions},
 which must be present, and @dfn{optional functions}, which Gnus will
@@ -17949,49 +26978,72 @@ talk about @dfn{return value}, I talk about the function value returned by
 the function call.  Functions that fail should return @code{nil} as the
 return value.
 
-Some backends could be said to be @dfn{server-forming} backends, and
-some might be said not to be.  The latter are backends that generally
+Some back ends could be said to be @dfn{server-forming} back ends, and
+some might be said not to be.  The latter are back ends that generally
 only operate on one group at a time, and have no concept of ``server''
--- they have a group, and they deliver info on that group and nothing
+---they have a group, and they deliver info on that group and nothing
 more.
 
-In the examples and definitions I will refer to the imaginary backend
-@code{nnchoke}. 
+Gnus identifies each message by way of group name and article number.  A
+few remarks about these article numbers might be useful.  First of all,
+the numbers are positive integers.  Secondly, it is normally not
+possible for later articles to ``re-use'' older article numbers without
+confusing Gnus.  That is, if a group has ever contained a message
+numbered 42, then no other message may get that number, or Gnus will get
+mightily confused.@footnote{See the function
+@code{nnchoke-request-update-info}, @ref{Optional Back End Functions}.}
+Third, article numbers must be assigned in order of arrival in the
+group; this is not necessarily the same as the date of the message.
+
+The previous paragraph already mentions all the ``hard'' restrictions that
+article numbers must fulfill.  But it seems that it might be useful to
+assign @emph{consecutive} article numbers, for Gnus gets quite confused
+if there are holes in the article numbering sequence.  However, due to
+the ``no-reuse'' restriction, holes cannot be avoided altogether.  It's
+also useful for the article numbers to start at 1 to avoid running out
+of numbers as long as possible.
+
+Note that by convention, back ends are named @code{nnsomething}, but
+Gnus also comes with some @code{nnnotbackends}, such as
+@file{nnheader.el}, @file{nnmail.el} and @file{nnoo.el}.
+
+In the examples and definitions I will refer to the imaginary back end
+@code{nnchoke}.
 
 @cindex @code{nnchoke}
 
 @menu
-* Required Backend Functions::        Functions that must be implemented.
-* Optional Backend Functions::        Functions that need not be implemented.
-* Error Messaging::                   How to get messages and report errors.
-* Writing New Backends::              Extending old backends.
-* Hooking New Backends Into Gnus::    What has to be done on the Gnus end.
-* Mail-like Backends::                Some tips on mail backends.
+* Required Back End Functions::  Functions that must be implemented.
+* Optional Back End Functions::  Functions that need not be implemented.
+* Error Messaging::             How to get messages and report errors.
+* Writing New Back Ends::       Extending old back ends.
+* Hooking New Back Ends Into Gnus::  What has to be done on the Gnus end.
+* Mail-like Back Ends::         Some tips on mail back ends.
 @end menu
 
 
-@node Required Backend Functions
-@subsubsection Required Backend Functions
+@node Required Back End Functions
+@subsubsection Required Back End Functions
 
 @table @code
 
 @item (nnchoke-retrieve-headers ARTICLES &optional GROUP SERVER FETCH-OLD)
 
 @var{articles} is either a range of article numbers or a list of
-@code{Message-ID}s.  Current backends do not fully support either---only
-sequences (lists) of article numbers, and most backends do not support
-retrieval of @code{Message-ID}s.  But they should try for both. 
+@code{Message-ID}s.  Current back ends do not fully support either---only
+sequences (lists) of article numbers, and most back ends do not support
+retrieval of @code{Message-ID}s.  But they should try for both.
 
-The result data should either be HEADs or NOV lines, and the result
+The result data should either be HEADs or @acronym{NOV} lines, and the result
 value should either be @code{headers} or @code{nov} to reflect this.
 This might later be expanded to @code{various}, which will be a mixture
-of HEADs and NOV lines, but this is currently not supported by Gnus.  
+of HEADs and @acronym{NOV} lines, but this is currently not supported by Gnus.
 
-If @var{fetch-old} is non-@code{nil} it says to try fetching "extra
-headers", in some meaning of the word.  This is generally done by
+If @var{fetch-old} is non-@code{nil} it says to try fetching ``extra
+headers'', in some meaning of the word.  This is generally done by
 fetching (at most) @var{fetch-old} extra headers less than the smallest
 article number in @code{articles}, and filling the gaps as well.  The
-presence of this parameter can be ignored if the backend finds it
+presence of this parameter can be ignored if the back end finds it
 cumbersome to follow the request.  If this is non-@code{nil} and not a
 number, do maximum fetches.
 
@@ -18026,28 +27078,31 @@ valid-message  = "221 " <number> " Article retrieved." eol
 header         = <text> eol
 @end example
 
+@cindex BNF
+(The version of BNF used here is the one used in RFC822.)
+
 If the return value is @code{nov}, the data buffer should contain
 @dfn{network overview database} lines.  These are basically fields
-separated by tabs. 
+separated by tabs.
 
 @example
 nov-buffer = *nov-line
-nov-line   = 8*9 [ field <TAB> ] eol
+nov-line   = field 7*8[ <TAB> field ] eol
 field      = <text except TAB>
 @end example
 
 For a closer look at what should be in those fields,
-@pxref{Headers}. 
+@pxref{Headers}.
 
 
 @item (nnchoke-open-server SERVER &optional DEFINITIONS)
 
 @var{server} is here the virtual server name.  @var{definitions} is a
-list of @code{(VARIABLE VALUE)} pairs that define this virtual server. 
+list of @code{(VARIABLE VALUE)} pairs that define this virtual server.
 
-If the server can't be opened, no error should be signaled.  The backend
+If the server can't be opened, no error should be signaled.  The back end
 may then choose to refuse further attempts at connecting to this
-server.  In fact, it should do so. 
+server.  In fact, it should do so.
 
 If the server is opened already, this function should return a
 non-@code{nil} value.  There should be no data returned.
@@ -18064,19 +27119,19 @@ There should be no data returned.
 
 @item (nnchoke-request-close)
 
-Close connection to all servers and free all resources that the backend
-have reserved.  All buffers that have been created by that backend
+Close connection to all servers and free all resources that the back end
+have reserved.  All buffers that have been created by that back end
 should be killed.  (Not the @code{nntp-server-buffer}, though.)  This
 function is generally only called when Gnus is shutting down.
 
-There should be no data returned. 
+There should be no data returned.
 
 
 @item (nnchoke-server-opened &optional SERVER)
 
 If @var{server} is the current virtual server, and the connection to the
 physical server is alive, then this function should return a
-non-@code{nil} vlue.  This function should under no circumstances
+non-@code{nil} value.  This function should under no circumstances
 attempt to reconnect to a server we have lost connection to.
 
 There should be no data returned.
@@ -18084,7 +27139,7 @@ There should be no data returned.
 
 @item (nnchoke-status-message &optional SERVER)
 
-This function should return the last error message from @var{server}. 
+This function should return the last error message from @var{server}.
 
 There should be no data returned.
 
@@ -18113,9 +27168,9 @@ on successful article retrieval.
 @item (nnchoke-request-group GROUP &optional SERVER FAST)
 
 Get data on @var{group}.  This function also has the side effect of
-making @var{group} the current group. 
+making @var{group} the current group.
 
-If @var{FAST}, don't bother to return useful data, just make @var{group}
+If @var{fast}, don't bother to return useful data, just make @var{group}
 the current group.
 
 Here's an example of some result data and a definition of the same:
@@ -18131,7 +27186,9 @@ number of articles may be less than one might think while just
 considering the highest and lowest article numbers, but some articles
 may have been canceled.  Gnus just discards the total-number, so
 whether one should take the bother to generate it properly (if that is a
-problem) is left as an exercise to the reader.
+problem) is left as an exercise to the reader.  If the group contains no
+articles, the lowest article number should be reported as 1 and the
+highest as 0.
 
 @example
 group-status = [ error / info ] eol
@@ -18143,7 +27200,7 @@ info         = "211 " 3* [ <number> " " ] <string>
 @item (nnchoke-close-group GROUP &optional SERVER)
 
 Close @var{group} and free any resources connected to it.  This will be
-a no-op on most backends. 
+a no-op on most back ends.
 
 There should be no data returned.
 
@@ -18151,7 +27208,7 @@ There should be no data returned.
 @item (nnchoke-request-list &optional SERVER)
 
 Return a list of all groups available on @var{server}.  And that means
-@emph{all}. 
+@emph{all}.
 
 Here's an example from a server that only carries two groups:
 
@@ -18161,7 +27218,9 @@ ifi.discussion 3324 3300 n
 @end example
 
 On each line we have a group name, then the highest article number in
-that group, the lowest article number, and finally a flag.
+that group, the lowest article number, and finally a flag.  If the group
+contains no articles, the lowest article number should be reported as 1
+and the highest as 0.
 
 @example
 active-file = *active-line
@@ -18172,7 +27231,7 @@ flags       = "n" / "y" / "m" / "x" / "j" / "=" name
 
 The flag says whether the group is read-only (@samp{n}), is moderated
 (@samp{m}), is dead (@samp{x}), is aliased to some other group
-(@samp{=other-group}) or none of the above (@samp{y}). 
+(@samp{=other-group}) or none of the above (@samp{y}).
 
 
 @item (nnchoke-request-post &optional SERVER)
@@ -18184,13 +27243,13 @@ completed by the time this function concludes.  In that case, this
 function should set up some kind of sentinel to beep the user loud and
 clear if the posting could not be completed.
 
-There should be no result data from this function. 
+There should be no result data from this function.
 
 @end table
 
 
-@node Optional Backend Functions
-@subsubsection Optional Backend Functions
+@node Optional Back End Functions
+@subsubsection Optional Back End Functions
 
 @table @code
 
@@ -18213,11 +27272,11 @@ group-buffer = *active-line / *group-status
 
 @item (nnchoke-request-update-info GROUP INFO &optional SERVER)
 
-A Gnus group info (@pxref{Group Info}) is handed to the backend for
-alterations.  This comes in handy if the backend really carries all the
-information (as is the case with virtual and imap groups).  This
+A Gnus group info (@pxref{Group Info}) is handed to the back end for
+alterations.  This comes in handy if the back end really carries all
+the information (as is the case with virtual and imap groups).  This
 function should destructively alter the info to suit its needs, and
-should return the (altered) group info.
+should return a non-@code{nil} value.
 
 There should be no result data from this function.
 
@@ -18236,18 +27295,59 @@ and @var{article} may be @code{nil}.
 There should be no result data from this function.
 
 
+@item (nnchoke-request-set-mark GROUP ACTION &optional SERVER)
+
+Set/remove/add marks on articles.  Normally Gnus handles the article
+marks (such as read, ticked, expired etc) internally, and store them in
+@file{~/.newsrc.eld}.  Some back ends (such as @acronym{IMAP}) however carry
+all information about the articles on the server, so Gnus need to
+propagate the mark information to the server.
+
+@var{action} is a list of mark setting requests, having this format:
+
+@example
+(RANGE ACTION MARK)
+@end example
+
+@var{range} is a range of articles you wish to update marks on.
+@var{action} is @code{add} or @code{del}, used to add marks or remove
+marks (preserving all marks not mentioned).  @var{mark} is a list of
+marks; where each mark is a symbol.  Currently used marks are
+@code{read}, @code{tick}, @code{reply}, @code{expire}, @code{killed},
+@code{dormant}, @code{save}, @code{download}, @code{unsend},
+@code{forward} and @code{recent}, but your back end should, if
+possible, not limit itself to these.
+
+Given contradictory actions, the last action in the list should be the
+effective one.  That is, if your action contains a request to add the
+@code{tick} mark on article 1 and, later in the list, a request to
+remove the mark on the same article, the mark should in fact be removed.
+
+An example action list:
+
+@example
+(((5 12 30) 'del '(tick))
+ ((10 . 90) 'add '(read expire))
+ ((92 94) 'del '(read)))
+@end example
+
+The function should return a range of articles it wasn't able to set the
+mark on (currently not used for anything).
+
+There should be no result data from this function.
+
 @item (nnchoke-request-update-mark GROUP ARTICLE MARK)
 
-If the user tries to set a mark that the backend doesn't like, this
+If the user tries to set a mark that the back end doesn't like, this
 function may change the mark.  Gnus will use whatever this function
 returns as the mark for @var{article} instead of the original
-@var{mark}.  If the backend doesn't care, it must return the original
-@var{mark}, and not @code{nil} or any other type of garbage.  
+@var{mark}.  If the back end doesn't care, it must return the original
+@var{mark}, and not @code{nil} or any other type of garbage.
 
 The only use for this I can see is what @code{nnvirtual} does with
 it---if a component group is auto-expirable, marking an article as read
 in the virtual group should result in the article being marked as
-expirable. 
+expirable.
 
 There should be no result data from this function.
 
@@ -18255,12 +27355,13 @@ There should be no result data from this function.
 @item (nnchoke-request-scan &optional GROUP SERVER)
 
 This function may be called at any time (by Gnus or anything else) to
-request that the backend check for incoming articles, in one way or
-another.  A mail backend will typically read the spool file or query the
-POP server when this function is invoked.  The @var{group} doesn't have
-to be heeded---if the backend decides that it is too much work just
-scanning for a single group, it may do a total scan of all groups.  It
-would be nice, however, to keep things local if that's practical.
+request that the back end check for incoming articles, in one way or
+another.  A mail back end will typically read the spool file or query
+the @acronym{POP} server when this function is invoked.  The
+@var{group} doesn't have to be heeded---if the back end decides that
+it is too much work just scanning for a single group, it may do a
+total scan of all groups.  It would be nice, however, to keep things
+local if that's practical.
 
 There should be no result data from this function.
 
@@ -18268,7 +27369,7 @@ There should be no result data from this function.
 @item (nnchoke-request-group-description GROUP &optional SERVER)
 
 The result data from this function should be a description of
-@var{group}. 
+@var{group}.
 
 @example
 description-line = name <TAB> description eol
@@ -18289,13 +27390,23 @@ description-buffer = *description-line
 @item (nnchoke-request-newgroups DATE &optional SERVER)
 
 The result data from this function should be all groups that were
-created after @samp{date}, which is in normal human-readable date
-format.  The data should be in the active buffer format.
+created after @samp{date}, which is in normal human-readable date format
+(i.e., the date format used in mail and news headers, and returned by
+the function @code{message-make-date} by default).  The data should be
+in the active buffer format.
+
+It is okay for this function to return ``too many'' groups; some back ends
+might find it cheaper to return the full list of groups, rather than
+just the new groups.  But don't do this for back ends with many groups.
+Normally, if the user creates the groups herself, there won't be too
+many groups, so @code{nnml} and the like are probably safe.  But for
+back ends like @code{nntp}, where the groups have been created by the
+server, it is quite likely that there can be many groups.
 
 
 @item (nnchoke-request-create-group GROUP &optional SERVER)
 
-This function should create an empty group with name @var{group}.  
+This function should create an empty group with name @var{group}.
 
 There should be no return data.
 
@@ -18304,10 +27415,10 @@ There should be no return data.
 
 This function should run the expiry process on all articles in the
 @var{articles} range (which is currently a simple list of article
-numbers.)  It is left up to the backend to decide how old articles
+numbers.)  It is left up to the back end to decide how old articles
 should be before they are removed by this function.  If @var{force} is
 non-@code{nil}, all @var{articles} should be deleted, no matter how new
-they are. 
+they are.
 
 This function should return a list of articles that it did not/was not
 able to delete.
@@ -18315,11 +27426,10 @@ able to delete.
 There should be no result data returned.
 
 
-@item (nnchoke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM
-&optional LAST)
+@item (nnchoke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM &optional LAST)
 
 This function should move @var{article} (which is a number) from
-@var{group} by calling @var{accept-form}.  
+@var{group} by calling @var{accept-form}.
 
 This function should ready the article in question for moving by
 removing any header lines it has added to the article, and generally
@@ -18330,12 +27440,15 @@ non-@code{nil} value, the article should be removed.
 
 If @var{last} is @code{nil}, that means that there is a high likelihood
 that there will be more requests issued shortly, so that allows some
-optimizations. 
+optimizations.
 
 The function should return a cons where the @code{car} is the group name and
 the @code{cdr} is the article number that the article was entered as.
 
-There should be no data returned. 
+The group should exist before the back end is asked to accept the
+article for that group.
+
+There should be no data returned.
 
 
 @item (nnchoke-request-accept-article GROUP &optional SERVER LAST)
@@ -18382,9 +27495,9 @@ There should be no data returned.
 
 @findex nnheader-report
 @findex nnheader-get-report
-The backends should use the function @code{nnheader-report} to report
+The back ends should use the function @code{nnheader-report} to report
 error conditions---they should not raise errors when they aren't able to
-perform a request.  The first argument to this function is the backend
+perform a request.  The first argument to this function is the back end
 symbol, and the rest are interpreted as arguments to @code{format} if
 there are multiple of them, or just a string if there is one of them.
 This function must always returns @code{nil}.
@@ -18397,18 +27510,18 @@ This function must always returns @code{nil}.
 
 Gnus, in turn, will call @code{nnheader-get-report} when it gets a
 @code{nil} back from a server, and this function returns the most
-recently reported message for the backend in question.  This function
+recently reported message for the back end in question.  This function
 takes one argument---the server symbol.
 
-Internally, these functions access @var{backend}@code{-status-string},
-so the @code{nnchoke} backend will have its error message stored in
+Internally, these functions access @var{back-end}@code{-status-string},
+so the @code{nnchoke} back end will have its error message stored in
 @code{nnchoke-status-string}.
 
 
-@node Writing New Backends
-@subsubsection Writing New Backends
+@node Writing New Back Ends
+@subsubsection Writing New Back Ends
 
-Many backends are quite similar.  @code{nnml} is just like
+Many back ends are quite similar.  @code{nnml} is just like
 @code{nnspool}, but it allows you to edit the articles on the server.
 @code{nnmh} is just like @code{nnml}, but it doesn't use an active file,
 and it doesn't maintain overview databases.  @code{nndir} is just like
@@ -18416,14 +27529,14 @@ and it doesn't maintain overview databases.  @code{nndir} is just like
 editing articles.
 
 It would make sense if it were possible to ``inherit'' functions from
-backends when writing new backends.  And, indeed, you can do that if you
-want to.  (You don't have to if you don't want to, of course.)  
+back ends when writing new back ends.  And, indeed, you can do that if you
+want to.  (You don't have to if you don't want to, of course.)
 
-All the backends declare their public variables and functions by using a
-package called @code{nnoo}.  
+All the back ends declare their public variables and functions by using a
+package called @code{nnoo}.
 
-To inherit functions from other backends (and allow other backends to
-inherit functions from the current backend), you should use the
+To inherit functions from other back ends (and allow other back ends to
+inherit functions from the current back end), you should use the
 following macros:
 
 @table @code
@@ -18443,11 +27556,11 @@ both @code{nnml} and @code{nnmh}.
 @item defvoo
 This macro is equivalent to @code{defvar}, but registers the variable as
 a public server variable.  Most state-oriented variables should be
-declared with @code{defvoo} instead of @code{defvar}.  
+declared with @code{defvoo} instead of @code{defvar}.
 
 In addition to the normal @code{defvar} parameters, it takes a list of
-variables in the parent backends to map the variable to when executing
-a function in those backends.
+variables in the parent back ends to map the variable to when executing
+a function in those back ends.
 
 @lisp
 (defvoo nndir-directory nil
@@ -18457,30 +27570,30 @@ a function in those backends.
 
 This means that @code{nnml-current-directory} will be set to
 @code{nndir-directory} when an @code{nnml} function is called on behalf
-of @code{nndir}.  (The same with @code{nnmh}.)  
+of @code{nndir}.  (The same with @code{nnmh}.)
 
 @item nnoo-define-basics
-This macro defines some common functions that almost all backends should
+This macro defines some common functions that almost all back ends should
 have.
 
-@example
+@lisp
 (nnoo-define-basics nndir)
-@end example
+@end lisp
 
 @item deffoo
 This macro is just like @code{defun} and takes the same parameters.  In
 addition to doing the normal @code{defun} things, it registers the
-function as being public so that other backends can inherit it.
+function as being public so that other back ends can inherit it.
 
 @item nnoo-map-functions
-This macro allows mapping of functions from the current backend to
-functions from the parent backends.
+This macro allows mapping of functions from the current back end to
+functions from the parent back ends.
 
-@example
+@lisp
 (nnoo-map-functions nndir
   (nnml-retrieve-headers 0 nndir-current-group 0 0)
   (nnmh-request-article 0 nndir-current-group 0 0))
-@end example
+@end lisp
 
 This means that when @code{nndir-retrieve-headers} is called, the first,
 third, and fourth parameters will be passed on to
@@ -18488,17 +27601,17 @@ third, and fourth parameters will be passed on to
 value of @code{nndir-current-group}.
 
 @item nnoo-import
-This macro allows importing functions from backends.  It should be the
+This macro allows importing functions from back ends.  It should be the
 last thing in the source file, since it will only define functions that
 haven't already been defined.
 
-@example
+@lisp
 (nnoo-import nndir
   (nnmh
    nnmh-request-list
    nnmh-request-newgroups)
   (nnml))
-@end example
+@end lisp
 
 This means that calls to @code{nndir-request-list} should just be passed
 on to @code{nnmh-request-list}, while all public functions from
@@ -18507,13 +27620,13 @@ defined now.
 
 @end table
 
-Below is a slightly shortened version of the @code{nndir} backend.
+Below is a slightly shortened version of the @code{nndir} back end.
 
 @lisp
-;;; nndir.el --- single directory newsgroup access for Gnus
-;; Copyright (C) 1995,96 Free Software Foundation, Inc.
+;;; @r{nndir.el --- single directory newsgroup access for Gnus}
+;; @r{Copyright (C) 1995,96 Free Software Foundation, Inc.}
 
-;;; Code:
+;;; @r{Code:}
 
 (require 'nnheader)
 (require 'nnmh)
@@ -18532,14 +27645,16 @@ Below is a slightly shortened version of the @code{nndir} backend.
   "*Non-nil means that nndir will never retrieve NOV headers."
   nnml-nov-is-evil)
 
-(defvoo nndir-current-group "" nil nnml-current-group nnmh-current-group)
+(defvoo nndir-current-group ""
+  nil
+  nnml-current-group nnmh-current-group)
 (defvoo nndir-top-directory nil nil nnml-directory nnmh-directory)
 (defvoo nndir-get-new-mail nil nil nnml-get-new-mail nnmh-get-new-mail)
 
 (defvoo nndir-status-string "" nil nnmh-status-string)
 (defconst nndir-version "nndir 1.0")
 
-;;; Interface functions.
+;;; @r{Interface functions.}
 
 (nnoo-define-basics nndir)
 
@@ -18550,7 +27665,8 @@ Below is a slightly shortened version of the @code{nndir} backend.
   (unless (assq 'nndir-directory defs)
     (push `(nndir-directory ,server) defs))
   (push `(nndir-current-group
-          ,(file-name-nondirectory (directory-file-name nndir-directory)))
+          ,(file-name-nondirectory
+            (directory-file-name nndir-directory)))
         defs)
   (push `(nndir-top-directory
           ,(file-name-directory (directory-file-name nndir-directory)))
@@ -18573,15 +27689,16 @@ Below is a slightly shortened version of the @code{nndir} backend.
 @end lisp
 
 
-@node Hooking New Backends Into Gnus
-@subsubsection Hooking New Backends Into Gnus
+@node Hooking New Back Ends Into Gnus
+@subsubsection Hooking New Back Ends Into Gnus
 
 @vindex gnus-valid-select-methods
-Having Gnus start using your new backend is rather easy---you just
+@findex gnus-declare-backend
+Having Gnus start using your new back end is rather easy---you just
 declare it with the @code{gnus-declare-backend} functions.  This will
-enter the backend into the @code{gnus-valid-select-methods} variable.
+enter the back end into the @code{gnus-valid-select-methods} variable.
 
-@code{gnus-declare-backend} takes two parameters---the backend name and
+@code{gnus-declare-backend} takes two parameters---the back end name and
 an arbitrary number of @dfn{abilities}.
 
 Here's an example:
@@ -18590,38 +27707,40 @@ Here's an example:
 (gnus-declare-backend "nnchoke" 'mail 'respool 'address)
 @end lisp
 
+The above line would then go in the @file{nnchoke.el} file.
+
 The abilities can be:
 
 @table @code
 @item mail
-This is a mailish backend---followups should (probably) go via mail.
+This is a mailish back end---followups should (probably) go via mail.
 @item post
-This is a newsish backend---followups should (probably) go via news. 
+This is a newsish back end---followups should (probably) go via news.
 @item post-mail
-This backend supports both mail and news.
+This back end supports both mail and news.
 @item none
-This is neither a post nor mail backend---it's something completely
-different. 
+This is neither a post nor mail back end---it's something completely
+different.
 @item respool
 It supports respooling---or rather, it is able to modify its source
 articles and groups.
 @item address
 The name of the server should be in the virtual server name.  This is
-true for almost all backends.
+true for almost all back ends.
 @item prompt-address
 The user should be prompted for an address when doing commands like
-@kbd{B} in the group buffer.  This is true for backends like
-@code{nntp}, but not @code{nnmbox}, for instance. 
+@kbd{B} in the group buffer.  This is true for back ends like
+@code{nntp}, but not @code{nnmbox}, for instance.
 @end table
 
 
-@node Mail-like Backends
-@subsubsection Mail-like Backends
+@node Mail-like Back Ends
+@subsubsection Mail-like Back Ends
 
-One of the things that separate the mail backends from the rest of the
-backends is the heavy dependence by the mail backends on common
-functions in @file{nnmail.el}.  For instance, here's the definition of
-@code{nnml-request-scan}: 
+One of the things that separate the mail back ends from the rest of the
+back ends is the heavy dependence by most of the mail back ends on
+common functions in @file{nnmail.el}.  For instance, here's the
+definition of @code{nnml-request-scan}:
 
 @lisp
 (deffoo nnml-request-scan (&optional group server)
@@ -18631,13 +27750,13 @@ functions in @file{nnmail.el}.  For instance, here's the definition of
 
 It simply calls @code{nnmail-get-new-mail} with a few parameters,
 and @code{nnmail} takes care of all the moving and splitting of the
-mail.  
+mail.
 
 This function takes four parameters.
 
 @table @var
 @item method
-This should be a symbol to designate which backend is responsible for
+This should be a symbol to designate which back end is responsible for
 the call.
 
 @item exit-function
@@ -18651,15 +27770,15 @@ This optional argument should be a group name if the splitting is to be
 performed for one group only.
 @end table
 
-@code{nnmail-get-new-mail} will call @var{backend}@code{-save-mail} to
-save each article.  @var{backend}@code{-active-number} will be called to
-find the article number assigned to this article.  
+@code{nnmail-get-new-mail} will call @var{back-end}@code{-save-mail} to
+save each article.  @var{back-end}@code{-active-number} will be called to
+find the article number assigned to this article.
 
 The function also uses the following variables:
-@var{backend}@code{-get-new-mail} (to see whether to get new mail for
-this backend); and @var{backend}@code{-group-alist} and
-@var{backend}@code{-active-file} to generate the new active file.
-@var{backend}@code{-group-alist} should be a group-active alist, like
+@var{back-end}@code{-get-new-mail} (to see whether to get new mail for
+this back end); and @var{back-end}@code{-group-alist} and
+@var{back-end}@code{-active-file} to generate the new active file.
+@var{back-end}@code{-group-alist} should be a group-active alist, like
 this:
 
 @example
@@ -18671,8 +27790,8 @@ this:
 @node Score File Syntax
 @subsection Score File Syntax
 
-Score files are meant to be easily parsable, but yet extremely
-mallable.   It was decided that something that had the same read syntax
+Score files are meant to be easily parseable, but yet extremely
+mallable.  It was decided that something that had the same read syntax
 as an Emacs Lisp list would fit that spec.
 
 Here's a typical score file:
@@ -18689,51 +27808,51 @@ Here's a typical score file:
 BNF definition of a score file:
 
 @example
-score-file       = "" / "(" *element ")"
-element          = rule / atom
-rule             = string-rule / number-rule / date-rule
-string-rule      = "(" quote string-header quote space *string-match ")"
-number-rule      = "(" quote number-header quote space *number-match ")"
-date-rule        = "(" quote date-header quote space *date-match ")"
-quote            = <ascii 34>
-string-header    = "subject" / "from" / "references" / "message-id" / 
-                   "xref" / "body" / "head" / "all" / "followup"
-number-header    = "lines" / "chars"
-date-header      = "date"
-string-match     = "(" quote <string> quote [ "" / [ space score [ "" / 
-                   space date [ "" / [ space string-match-t ] ] ] ] ] ")"
-score            = "nil" / <integer>
-date             = "nil" / <natural number>
-string-match-t   = "nil" / "s" / "substring" / "S" / "Substring" / 
-                   "r" / "regex" / "R" / "Regex" /
-                   "e" / "exact" / "E" / "Exact" /
-                   "f" / "fuzzy" / "F" / "Fuzzy"
-number-match     = "(" <integer> [ "" / [ space score [ "" / 
-                   space date [ "" / [ space number-match-t ] ] ] ] ] ")"
-number-match-t   = "nil" / "=" / "<" / ">" / ">=" / "<="
-date-match       = "(" quote <string> quote [ "" / [ space score [ "" / 
-                   space date [ "" / [ space date-match-t ] ] ] ] ")"
-date-match-t     = "nil" / "at" / "before" / "after"
-atom             = "(" [ required-atom / optional-atom ] ")"
-required-atom    = mark / expunge / mark-and-expunge / files /
-                   exclude-files / read-only / touched
-optional-atom    = adapt / local / eval 
-mark             = "mark" space nil-or-number
-nil-or-number    = "nil" / <integer>
-expunge          = "expunge" space nil-or-number
+score-file      = "" / "(" *element ")"
+element         = rule / atom
+rule            = string-rule / number-rule / date-rule
+string-rule     = "(" quote string-header quote space *string-match ")"
+number-rule     = "(" quote number-header quote space *number-match ")"
+date-rule       = "(" quote date-header quote space *date-match ")"
+quote           = <ascii 34>
+string-header   = "subject" / "from" / "references" / "message-id" /
+                  "xref" / "body" / "head" / "all" / "followup"
+number-header   = "lines" / "chars"
+date-header     = "date"
+string-match    = "(" quote <string> quote [ "" / [ space score [ "" /
+                  space date [ "" / [ space string-match-t ] ] ] ] ] ")"
+score           = "nil" / <integer>
+date            = "nil" / <natural number>
+string-match-t  = "nil" / "s" / "substring" / "S" / "Substring" /
+                  "r" / "regex" / "R" / "Regex" /
+                  "e" / "exact" / "E" / "Exact" /
+                  "f" / "fuzzy" / "F" / "Fuzzy"
+number-match    = "(" <integer> [ "" / [ space score [ "" /
+                  space date [ "" / [ space number-match-t ] ] ] ] ] ")"
+number-match-t  = "nil" / "=" / "<" / ">" / ">=" / "<="
+date-match      = "(" quote <string> quote [ "" / [ space score [ "" /
+                  space date [ "" / [ space date-match-t ] ] ] ] ")"
+date-match-t    = "nil" / "at" / "before" / "after"
+atom            = "(" [ required-atom / optional-atom ] ")"
+required-atom   = mark / expunge / mark-and-expunge / files /
+                  exclude-files / read-only / touched
+optional-atom   = adapt / local / eval
+mark            = "mark" space nil-or-number
+nil-or-number   = "nil" / <integer>
+expunge         = "expunge" space nil-or-number
 mark-and-expunge = "mark-and-expunge" space nil-or-number
-files            = "files" *[ space <string> ]
-exclude-files    = "exclude-files" *[ space <string> ]
-read-only        = "read-only" [ space "nil" / space "t" ]
-adapt            = "adapt" [ space "ignore" / space "t" / space adapt-rule ]
-adapt-rule       = "(" *[ <string> *[ "(" <string> <integer> ")" ] ")"
-local            = "local" *[ space "(" <string> space <form> ")" ]
-eval             = "eval" space <form>
-space            = *[ " " / <TAB> / <NEWLINE> ]
+files           = "files" *[ space <string> ]
+exclude-files   = "exclude-files" *[ space <string> ]
+read-only       = "read-only" [ space "nil" / space "t" ]
+adapt        = "adapt" [ space "ignore" / space "t" / space adapt-rule ]
+adapt-rule      = "(" *[ <string> *[ "(" <string> <integer> ")" ] ")"
+local           = "local" *[ space "(" <string> space <form> ")" ]
+eval            = "eval" space <form>
+space           = *[ " " / <TAB> / <NEWLINE> ]
 @end example
 
 Any unrecognized elements in a score file should be ignored, but not
-discarded.  
+discarded.
 
 As you can see, white space is needed, but the type and amount of white
 space is irrelevant.  This means that formatting of the score file is
@@ -18748,12 +27867,12 @@ manual (@pxref{Score File Format}).
 @subsection Headers
 
 Internally Gnus uses a format for storing article headers that
-corresponds to the @sc{nov} format in a mysterious fashion.  One could
-almost suspect that the author looked at the @sc{nov} specification and
+corresponds to the @acronym{NOV} format in a mysterious fashion.  One could
+almost suspect that the author looked at the @acronym{NOV} specification and
 just shamelessly @emph{stole} the entire thing, and one would be right.
 
 @dfn{Header} is a severely overloaded term.  ``Header'' is used in
-RFC1036 to talk about lines in the head of an article (e.g.,
+RFC 1036 to talk about lines in the head of an article (e.g.,
 @code{From}).  It is used by many people as a synonym for
 ``head''---``the header and the body''.  (That should be avoided, in my
 opinion.)  And Gnus uses a format internally that it calls ``header'',
@@ -18762,19 +27881,19 @@ basically, with each header (ouch) having one slot.
 
 These slots are, in order: @code{number}, @code{subject}, @code{from},
 @code{date}, @code{id}, @code{references}, @code{chars}, @code{lines},
-@code{xref}.  There are macros for accessing and setting these
-slots---they all have predictable names beginning with
+@code{xref}, and @code{extra}.  There are macros for accessing and
+setting these slots---they all have predictable names beginning with
 @code{mail-header-} and @code{mail-header-set-}, respectively.
 
-The @code{xref} slot is really a @code{misc} slot.  Any extra info will
-be put in there.
+All these slots contain strings, except the @code{extra} slot, which
+contains an alist of header/value pairs (@pxref{To From Newsgroups}).
 
 
 @node Ranges
 @subsection Ranges
 
 @sc{gnus} introduced a concept that I found so useful that I've started
-using it a lot and have elaborated on it greatly. 
+using it a lot and have elaborated on it greatly.
 
 The question is simple: If you have a large amount of objects that are
 identified by numbers (say, articles, to take a @emph{wild} example)
@@ -18782,7 +27901,7 @@ that you want to qualify as being ``included'', a normal sequence isn't
 very useful.  (A 200,000 length sequence is a bit long-winded.)
 
 The solution is as simple as the question: You just collapse the
-sequence. 
+sequence.
 
 @example
 (1 2 3 4 5 6 10 11 12)
@@ -18838,7 +27957,7 @@ range handling.)
 range           = simple-range / normal-range
 simple-range    = "(" number " . " number ")"
 normal-range    = "(" start-contents ")"
-contents        = "" / simple-range *[ " " contents ] / 
+contents        = "" / simple-range *[ " " contents ] /
                   number *[ " " contents ]
 @end example
 
@@ -18847,7 +27966,7 @@ marks.  I plan on implementing a number of range operators in C if The
 Powers That Be are willing to let me.  (I haven't asked yet, because I
 need to do some more thinking on what operators I need to make life
 totally range-based without ever having to convert back to normal
-sequences.) 
+sequences.)
 
 
 @node Group Info
@@ -18861,12 +27980,12 @@ Here are two example group infos; one is a very simple group while the
 second is a more complex one:
 
 @example
-("no.group" 5 (1 . 54324))
+("no.group" 5 ((1 . 54324)))
 
 ("nnml:my.mail" 3 ((1 . 5) 9 (20 . 55))
                 ((tick (15 . 19)) (replied 3 6 (19 . 3)))
                 (nnml "")
-                (auto-expire (to-address "ding@@gnus.org")))
+                ((auto-expire . t) (to-address . "ding@@gnus.org")))
 @end example
 
 The first element is the @dfn{group name}---as Gnus knows the group,
@@ -18886,9 +28005,9 @@ three elements, which saves quite a lot of cons cells.
 Here's a BNF definition of the group info format:
 
 @example
-info          = "(" group space ralevel space read 
+info          = "(" group space ralevel space read
                 [ "" / [ space marks-list [ "" / [ space method [ "" /
-                space parameters ] ] ] ] ] ")" 
+                space parameters ] ] ] ] ] ")"
 group         = quote <string> quote
 ralevel       = rank / level
 level         = <integer in the range of 1 to inf>
@@ -19007,15 +28126,15 @@ A list of the current symbolic prefixes---the
 
 @item A
 The current article number---the @code{gnus-summary-article-number}
-function. 
+function.
 
 @item H
 The current article header---the @code{gnus-summary-article-header}
-function. 
+function.
 
 @item g
 The current group name---the @code{gnus-group-group-name}
-function. 
+function.
 
 @end table
 
@@ -19032,7 +28151,7 @@ like XEmacs or Mule, but because it comes first alphabetically.
 This means that Gnus will byte-compile under Emacs with nary a warning,
 while XEmacs will pump out gigabytes of warnings while byte-compiling.
 As I use byte-compilation warnings to help me root out trivial errors in
-Gnus, that's very useful.  
+Gnus, that's very useful.
 
 I've also consistently used Emacs function interfaces, but have used
 Gnusey aliases for the functions.  To take an example:  Emacs defines a
@@ -19070,8 +28189,8 @@ hit these indirections impose on Gnus under XEmacs should be slight.
 @subsection Various File Formats
 
 @menu
-* Active File Format::      Information on articles and groups available.
-* Newsgroups File Format::  Group descriptions.
+* Active File Format::          Information on articles and groups available.
+* Newsgroups File Format::      Group descriptions.
 @end menu
 
 
@@ -19080,7 +28199,7 @@ hit these indirections impose on Gnus under XEmacs should be slight.
 
 The active file lists all groups available on the server in
 question.  It also lists the highest and lowest current article numbers
-in each group.  
+in each group.
 
 Here's an excerpt from a typical active file:
 
@@ -19096,9 +28215,9 @@ Here's a pseudo-BNF definition of this file:
 
 @example
 active      = *group-line
-group-line  = group space high-number space low-number space flag <NEWLINE>
+group-line  = group spc high-number spc low-number spc flag <NEWLINE>
 group       = <non-white-space string>
-space       = " "
+spc         = " "
 high-number = <non-negative integer>
 low-number  = <positive integer>
 flag        = "y" / "n" / "m" / "j" / "x" / "=" group
@@ -19134,7 +28253,7 @@ description   = <string>
 
 Believe it or not, but some people who use Gnus haven't really used
 Emacs much before they embarked on their journey on the Gnus Love Boat.
-If you are one of those unfortunates whom ``@kbd{M-C-a}'', ``kill the
+If you are one of those unfortunates whom ``@kbd{C-M-a}'', ``kill the
 region'', and ``set @code{gnus-flargblossen} to an alist where the key
 is a regexp that is used for matching on the group name'' are magical
 phrases with little or no meaning, then this appendix is for you.  If
@@ -19142,8 +28261,8 @@ you are already familiar with Emacs, just ignore this and go fondle your
 cat instead.
 
 @menu
-* Keystrokes::      Entering text and executing commands.
-* Emacs Lisp::      The built-in Emacs programming language.
+* Keystrokes::                  Entering text and executing commands.
+* Emacs Lisp::                  The built-in Emacs programming language.
 @end menu
 
 
@@ -19154,7 +28273,7 @@ cat instead.
 @item
 Q: What is an experienced Emacs user?
 
-@item 
+@item
 A: A person who wishes that the terminal had pedals.
 @end itemize
 
@@ -19174,11 +28293,11 @@ which is the meta key on this keyboard.  It's usually located somewhere
 to the left hand side of the keyboard, usually on the bottom row.
 
 Now, us Emacs people don't say ``press the meta-control-m key'',
-because that's just too inconvenient.  We say ``press the @kbd{M-C-m}
+because that's just too inconvenient.  We say ``press the @kbd{C-M-m}
 key''.  @kbd{M-} is the prefix that means ``meta'' and ``C-'' is the
 prefix that means ``control''.  So ``press @kbd{C-k}'' means ``press
 down the control key, and hold it down while you press @kbd{k}''.
-``Press @kbd{M-C-k}'' means ``press down and hold down the meta key and
+``Press @kbd{C-M-k}'' means ``press down and hold down the meta key and
 the control key and then press @kbd{k}''.  Simple, ay?
 
 This is somewhat complicated by the fact that not all keyboards have a
@@ -19216,10 +28335,10 @@ write the following:
 
 This function (really ``special form'') @code{setq} is the one that can
 set a variable to some value.  This is really all you need to know.  Now
-you can go and fill your @code{.emacs} file with lots of these to change
+you can go and fill your @file{.emacs} file with lots of these to change
 how Gnus works.
 
-If you have put that thing in your @code{.emacs} file, it will be read
+If you have put that thing in your @file{.emacs} file, it will be read
 and @code{eval}ed (which is lisp-ese for ``run'') the next time you
 start Emacs.  If you want to change the variable right away, simply say
 @kbd{C-x C-e} after the closing parenthesis.  That will @code{eval} the
@@ -19269,5 +28388,7 @@ former).  The manual is unambiguous, but it can be confusing.
 @end iflatex
 @end iftex
 
+@c Local Variables:
+@c mode: texinfo
+@c coding: iso-8859-1
 @c End:
-
diff --git a/texi/gnusconfig.tex.in b/texi/gnusconfig.tex.in
new file mode 100644 (file)
index 0000000..4989104
--- /dev/null
@@ -0,0 +1,11 @@
+@WITH_FONTS_bembo@\usepackage{bembo}
+@WITH_FONTS_pfu@\newcommand{\gnusselectttfont}{\fontfamily{pfu}\fontsize{10pt}{10}\selectfont}
+@WITH_FONTS_bcr@\def\verbatim@font{\fontfamily{bcr}\fontsize{10pt}{10}\selectfont}
+@WITHOUT_FONTS_pfu@\newcommand{\gnusselectttfont}{\fontfamily{cmss}\fontsize{10pt}{10}\selectfont\hyphenchar\font45}
+
+\newcommand{\gnususefonts}{@USE_FONTS@}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 
diff --git a/texi/gnuslogo-booklet.eps b/texi/gnuslogo-booklet.eps
new file mode 100644 (file)
index 0000000..95408ba
--- /dev/null
@@ -0,0 +1,1055 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: gnuslogo1.ps
+%%Creator: XV Version 3.00  Rev: 3/30/93  -  by John Bradley
+%%BoundingBox: 0 0 493 505
+%%Pages: 1
+%%DocumentFonts:
+%%EndComments
+%%EndProlog
+
+%%Page: 1 1
+
+% remember original state
+/origstate save def
+
+% build a temporary dictionary
+20 dict begin
+
+% define string to hold a scanline's worth of data
+/pix 62 string def
+
+% lower left corner
+0 0 translate
+
+% size of image (on paper, in 1/72inch coords)
+493.0 505.0 scale
+
+% dimensions of data
+493 505 1
+
+% mapping matrix
+[493 0 0 -505 0 505]
+
+{currentfile pix readhexstring pop}
+image
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff01fffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff8003ffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff0000ffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff8000007ffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff0000003ffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffe0000000ffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff000000003fff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff000000000fff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffc0000000007ff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffff80000000003ff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffff00000000001ff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffe00000000000ff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffc00000000000ff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffff8000000000007f8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffff0000000000003f8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffff0000000000003f8
+fffffffffffffffffffffffffff800ffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffe0000000000001f8
+fffffffffffffffffffffffffff0001fffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffc0000000000000f8
+ffffffffffffffffffffffffffc00007ffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffc0000000000000f8
+ffffffffffffffffffffffffff000001ffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff8000000000000078
+fffffffffffffffffffffffffe0000003ffffffffffff0001fffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffff0000000000000038
+fffffffffffffffffffffffffc0000001fffffffffffe00007ffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffe0000000000000038
+fffffffffffffffffffffffff800000007ffffffffff800001ffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffe0000000000000038
+fffffffffffffffffffffffff000000003fffffffffe0000003fffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffc0000000000000018
+ffffffffffffffffffffffffe000000001fffffffff80000000fffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffc0000000000000018
+ffffffffffffffffffffffffc000000000ffffffffe000000003ffffffffffffffffffff
+fffffffffffffffffffffffffffffffffff80000000000000018
+ffffffffffffffffffffffff80000000007fffffff8000000000ffffffffffffffffffff
+fffffffffffffffffffffffffffffffffff80000000000000008
+ffffffffffffffffffffffff00000000003fffffff00000000007fffffffffffffffffff
+fffffffffffffffffffffffffffffffffff00000000000000008
+fffffffffffffffffffffffe00000000001ffffffe00000000001fffffffffffffffffff
+fffffffffffffffffffffffffffffffffff00000000000000008
+fffffffffffffffffffffffc00000000000ffffff8000000000007ffffffffffffffffff
+ffffffffffffffffffffffffffffffffffe00000000000000008
+fffffffffffffffffffffff8000000000007fffff0000000000007ffffffffffffffffff
+ffffffffffffffffffffffffffffffffffe00000000000000008
+fffffffffffffffffffffff0000000000001ffffe0000000000000ffffffffffffffffff
+ffffffffffffffffffffffffffffffffffc00000000000000000
+ffffffffffffffffffffffe0000000000000ffffc00000000000007fffffffffffffffff
+ffffffffffffffffffffffffffffffffffc00000000000000000
+ffffffffffffffffffffffc00000000000007fff800000000000001fffffffffffffffff
+ffffffffffffffffffffffffffffffffff800000000000000000
+ffffffffffffffffffffff800000000000003fff000000000000000fffffffffffffffff
+ffffffffffffffffffffffffffffffffff800000000000000000
+ffffffffffffffffffffff000000000000003fff0000000000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffff000040000000000000
+fffffffffffffffffffffe000000000000000ffe0000000000000001ffffffffffffffff
+ffffffffffffffffffffffffffffffffff0007ffc00000000000
+fffffffffffffffffffffc000000000000000ffc0000000000000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffe001ffffc0000000000
+fffffffffffffffffffffc0000000000000007fc00000000000000007fffffffffffffff
+fffffffffffffffffffffffffffffffffc003ffffe0000000000
+fffffffffffffffffffff80000000000000007f800000000000000003fffffffffffffff
+fffffffffffffffffffffffffffffffffc007fffffc000000000
+fffffffffffffffffffff00000000000000001f000000000000000001fffffffffffffff
+fffffffffffffffffffffffffffffffff800fffffff000000000
+ffffffffffffffffffffe00000000000000001f000000000000000000fffffffffffffff
+fffffffffffffffffffffffffffffffff801fffffff800000000
+ffffffffffffffffffffc00000000000000000e0000000000000000007ffffffffffffff
+fffffffffffffffffffffffffffffffff003ffffffff00000000
+ffffffffffffffffffff800000000000000000c0000000000000000003ffffffffffffff
+fffffffffffffffffffffffffffffffff007ffffffff00000000
+ffffffffffffffffffff00000000000000000000000000000000000000ffffffffffffff
+ffffffffffffffffffffffffffffffffe00fffffffff80000000
+fffffffffffffffffffe00000000000000000000000000000000000000ffffffffffffff
+ffffffffffffffffffffffffffffffffe01fffffffffc0000008
+fffffffffffffffffffc000000000000000000000000000000000000007fffffffffffff
+ffffffffffffffffffffffffffffffffc03fffffffffc0000008
+fffffffffffffffffff8000000000000000000000000000000000000001fffffffffffff
+ffffffffffffffffffffffffffffffffc07ffffffffff0000000
+fff9fffffffffffffff800000fe00000000000000000000000000000001fffffffffffff
+ffffffffffffffffffffffffffffffff807ffffffffff0000000
+fff9fffffffffffffff000001ff80000000000000000000000000000000fffffffffffff
+ffffffffffffffffffffffffffffffff80fffffffffff0000008
+fff0ffffffffffffffc000007ffc00000000000000000000000000000007ffffffffffff
+ffffffffffffffffffffffffffffffff81fffffffffff8000008
+fff0ffffffffffffffc00000fffc00000000000000000000000000000003ffffffffffff
+ffffffffffffffffffffffffffffffff01fffffffffff8000008
+ffe07fffffffffffff800001ffff00000000000000000000000000000001ffffffffffff
+ffffffffffffffffffffffffffffffff03fffffffffffc000008
+ffe07fffffffffffff00000fffffc0000000000000000000000000000000ffffffffffff
+fffffffffffffffffffffffffffffffe03fffffffffffc000008
+ffe03ffffffffffffc00001fffffe00000000000000000000000000000007fffffffffff
+fffffffffffffffffffffffffffffffe07fffffffffffe000008
+ffe03ffffffffffff800003ffffff00000000000000000000000000000003fffffffffff
+fffffffffffffffffffffffffffffffe07fffffffffffe000008
+ffc03ffffffffffff000007ffffff80000000000000f80000000000000003fffffffffff
+fffffffffffffffffffffffffffffffe0ffffffffffffe000008
+ffc01fffffffffffe00001fffffffe000000000000fffe000000000000001fffffffffff
+fffffffffffffffffffffffffffffffc0ffffffffffffe000008
+ffc00fffffffffffc00003ffffffff000000000001ffff800000000000000fffffffffff
+fffffffffffffffffffffffffffffffc1fffffffffffff000008
+ff800fffffffffff800003ffffffff800000000007ffffc000000000000007ffffffffff
+fffffffffffffffffffffffffffffffc3fffffffffffff000008
+ff8007fffffffffe00000fffffffffc0000000001ffffffc00000000000003ffffffffff
+fffffffffffffffffffffffffffffff87fffffffffffff000008
+ff8007fffffffffc00000fffffffffe0000000005ffffffe00000000000001ffffffffff
+fffffffffffffffffffffffffffffff87fffffffffffff000008
+ff8003fffffffff800001ffffffffff000000000ffffffffc0000000000000ffffffffff
+fffffffffffffffffffffffffffffff87fffffffffffff000008
+ff0001fffffffff000003ffffffffffc00000007fffffffff80000000000007fffffffff
+fffffffffffffffffffffffffffffff8ffffffffffffff000008
+ff0000ffffffffe000003ffffffffffc0000000ffffffffffc0000000000007fffffffff
+fffffffffffffffffffffffffffffffcffffffffffffff000008
+fe00007fffffff800000ffffffffffff0000001ffffffffffe0000000000001fffffffff
+ffffffffffffffffffffffffffffe7fdffffffffffffff000008
+fe00007fffffff000001ffffffffffff8000003fffffffffff0000000000001fffffffff
+ffffffffffffffffffffffffffffe7fdffffffffffffff000008
+fc00001ffffffc000003ffffffffffffc000007fffffffffffe0000000000007ffffffff
+ffffffffffffffffffffffffffffc7ffffffffffffffff000008
+fc00001ffffff0000003ffffffffffffe00000fffffffffffff0000000000007ffffffff
+fffffffffeffffffffffffffffff87ffffffffffffffff000008
+f800000fffffe0000007fffffffffffff00000fffffffffffff8000000000003ffffffff
+fffffffffcffffffffffffffffff87ffffffffffffffff000008
+f8000003ffff0000000ffffffffffffff80001fffffffffffffc000000000001ffffffff
+fffffffff8ffffffffffffffffff07ffffffffffffffff000008
+f8000001fffe0000001ffffffffffffff80001ffffffffffffff000000000000ffffffff
+fffffffff8fffffffffffffffffe0fffffffffffffffff000008
+f0000000fff00000003ffffffffffffffc0001ffffffffffffff8000000000007fffffff
+fffffffff0fffffffffffffffffe0fffffffffffffffff000018
+e00000001a000000007ffffffffffffffe0003ffffffffffffffc000000000003fffffff
+fffffffff0fffffffffffffffffc0fffffffffffffffff000018
+e000000000000000007fffffffffffffff0003ffffffffffffffc000000000003fffffff
+ffffffffe0fffffffffffffffffc1fffffffffffffffff000018
+c00000000000000000ffffffffffffffff0007ffffffffffffffe000000000001fffffff
+ffffffffe0fffffffffffffffff81fffffffffffffffff000018
+c00000000000000001ffffffffffffffff0007fffffffffffffff0000000000007ffffff
+ffffffffc0fffffffffffffffff83fffffffffffffffff000018
+800000000000000007ffffffffffffffff800ffffffffffffffffc000000000003ffffff
+ffffffff01fffffffffffffffff03fffffffffffffffff000038
+800000000000000007ffffffffffffffff800ffffffffffffffffe000000000001ffffff
+ffffffff01fffffffffffffffff03fffffffffffffffff800038
+00000000000000000fffffffffffffffffc00fffffffffffffffff000000000000ffffff
+fffffffe03ffffffffffffffffe07fffffffffffffffff800038
+00000000000000001fffffffffffffffffc01fffffffffffffffff8000000000007fffff
+fffffffc03ffffffffffffffffe07fffffffffffffffff800038
+00000000000000003fffffffffffffffffe03fffffffffffffffffc000000000003fffff
+fffffff803ffffffffffffffffc07fffffffffffffffff800038
+00000000000000007ffffffffffffffffff03fffffffffffffffffe000000000000fffff
+fffffff007ffffffffffffffffc0ffffffffffffffffff800038
+0000000000000000fffffffffffffffffff07ffffffffffffffffff000000000000fffff
+fffffff007ffffffffffffffff80ffffffffffffffffff800078
+0000000000000003ffffffffffffffff8ff87ffffffffffffffffff8000000000001ffff
+ffffffc00fffffffffffffffff81ffffffffffffffffff800078
+8000000000000007ffffffffffffffff0ff8fffffffffffffffffffc000000000000ffff
+ffffffc00fffffffffffffffff01ffffffffffffffffff8000f8
+8000000000000007fffffffffffffffe0ffffffffffffffffffffffe0000000000007fff
+ffffff801fffffffffffffffff03ffffffffffffffffff8000f8
+c00000000000001ffffffffffffffffc0fffffffffffffffffffffff0000000000001fff
+fffffe001ffffffffffffffffe07ffffffffffffffffff8000f8
+e00000000000007ffffffffffffffff83fffffffffffffffffffffffc0000000000007ff
+fffff8003ffffffffffffffffc07ffffffffffffffffff8000f8
+f00000000000007ffffffffffffffff03fffffffffffffffffffffffc0000000000001ff
+fffff0003ffffffffffffffff80fffffffffffffffffff8000f8
+f0000000000000fffffffffffffffff07fffffffffffffffffffffffe0000000000000ff
+ffffe0003ffffffffffffffff00fffffffffffffffffff8001f8
+f8000000000003ffffffffffffffffe07ffffffffffffffffffffffff00000000000000f
+ffff00007fffffffffffffffe01fffffffffffffffffff0001f8
+fc000000000007ffffffffffffffffc07ffffffffffffffffffffffff800000000000007
+fffc00007fffffffffffffffc01fffffffffffffffffff0001f8
+fc000000000007ffffffffffffffffc0fffffffffffffffffffffffff800000000000000
+ffe000007ffffbffffffffff801fffffffffffffffffff0001f8
+fe00000000001fffffffffffffffff03fffffffffffffffffffffffffe00000000000000
+00000000fffff3ffffffffff003fffffffffffffffffff0001f8
+fe00000000003fffffffffffffffff03ffffffffffffffffffffffffff00000000000000
+00000001fffff1fffffffffe003fffffffffffffffffff0003f8
+ff00000000007ffffffffffffffffe03ffffffffffffffffffffffffff00000000000000
+00000001ffffe1fffffffffc007fffffffffffffffffff0003f8
+ff8000000001fffffffffffffffffc07ffffffffffffffffffffffffff80000000000000
+00000003ffffe0fffffffff0007fffffffffffffffffff0003f8
+ffc000000003fffffffffffffffffc0fffffffffffffffffffffffffffc0000000000000
+00000003ffffc0ffffffffe0007fffffffffffffffffff0003f8
+ffe00000000ffffffffffffffffff81fffffffffffffffffffffffffffe0000000000000
+00000007ffffc07fffffff8000ffffffffffffffffffff0003f8
+fff00000003ffffffffffffffffff01ffffffffffffffffffffffffffff0000000000000
+00000007ffff803fffffff0000fffffffffffffffffffe0007f8
+fff8000000ffffffffffffffffffe03ffffffffffffffffffffffffffff8000000000000
+00000007ffff801ffffffc0001fffffffffffffffffffe0007f8
+fffc000001ffffffffffffffffffe07ffffffffffffffffffffffffffffc000000000000
+0000000fffff000ffffff80003fffffffffffffffffffe0007f8
+fffe00000fffffffffffffffffffc07ffffffffffffffffffffffffffffc000000000000
+0000000fffff0007ffffe00003fffffffffffffffffffe0007f8
+ffff80007fffffffffffffffffff80fffffffffffffffffffffffffffffe000000000000
+0000001ffffe0001ffff800007fffffffffffffffffffe000ff8
+ffffe007ffffffffffffffffffff80ffffffffffffffffffffffffffffff000000000000
+0000001ffffe0000fffc000007fffffffffffffffffffe000ff8
+ffffffffffffffffffffffffffff01ffffffffffffffffffffffffffffff800000000000
+0000003ffffe0000000000000ffffffffffffffffffffe000ff8
+fffffffffffffffffffffffffffe03ffffffffffffffffffffffffffffffc00000000000
+0000003ffffc0000000000000ffffffffffffffffffffe000ff8
+fffffffffffffffffffffffffffe03ffffffffffffffffffffffffffffffe00000000000
+0000007ffff80000000000001ffffffffffffffffffffe001ff8
+fffffffffffffffffffffffffffc07fffffffffffffffffffffffffffffff00000000000
+0000007ffff80000000000001ffffffffffffffffffffe001ff8
+fffffffffffffffffffffffffff807fffffffffffffffffffffffffffffff80000000000
+000000fffff80000000000003ffffffffffffffffffffc001ff8
+fffffffffffffffffffffffffff80ffffffffffffffffffffffffffffffffc0000000000
+000003fffff00000000000007ffffffffffffffffffffc001ff8
+fffffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffe0000000000
+000007ffffe00000000000007ffffffffffffffffffffe003ff8
+fffffffffffffffffffffffffff01fffffffffffffffffffffffffffffffff0000000000
+000007ffffe0000000000000fffffffffffffffffffffc003ff8
+ffffffffffffffffffffffffffc07fffffffffffffffffffffffffffffffff8000000000
+00001fffffc0000000000001fffffffffffffffffffffc003ff8
+ffffffffffffffffffffffffffc07fffffffffffffffffffffffffffffffffe000000000
+00001fffffc0000000000003fffffffffffffffffffffc003ff8
+ffffffffffffffffffffffffffc07ffffffffffffffffffffffffffffffffff000000000
+00003fffff80000000000003fffffffffffffffffffffc007ff8
+ffffffffffffffffffffffffff01fffffffffffffffffffffffffffffffffff800000000
+00007fffff80000000000007fffffffffffffffffffffc007ff8
+ffffffffffffffffffffffffff03fffffffffffffffffffffffffffffffffffc00000000
+0000ffffff0000000000000ffffffffffffffffffffffc007ff8
+fffffffffffffffffffffffffe03fffffffffffffffffffffffffffffffffffc00000000
+0001ffffff0000000000001ffffffffffffffffffffffc007ff8
+fffffffffffffffffffffffffc07ffffffffffffffffffffffffffffffffffff00000000
+0003fffffe0000000000001ffffffffffffffffffffff800fff8
+fffffffffffffffffffffffff80fffffffffffffffffffffffffffffffffffff80000000
+0007fffffe0000000000003ffffffffffffffffffffff800fff8
+fffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffffffff0000000
+001ffffffc0000000000007ffffffffffffffffffffff800fff8
+fffffffffffffffffffffffff03ffffffffffffffffffffffffffffffffffffff8000000
+003ffffffc000000000000fffffffffffffffffffffff800fff8
+ffffffffffffffffffffffffe07ffffffffffffffffffffffffffffffffffffffe000000
+00fffffff8000000000003fffffffffffffffffffffff001fff8
+ffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffff800000
+03fffffff8000000000003fffffffffffffffffffffff001fff8
+ffffffffffffffffffffffffc0ffffffffffffffffffffffffffffffffffffffffc00000
+07fffffff0000000000007fffffffffffffffffffffff001fff8
+ffffffffffffffffffffffff80fffffffffffffffffffffffffffffffffffffffffc0000
+3ffffffff000000000000ffffffffffffffffffffffff003fff8
+ffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffffffffffffe03f
+fffffffff000000000003ffffffffffffffffffffffff003fff8
+ffffffffffffffffffffffff01ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffff800000000007ffffffffffffffffffffffff003fff8
+fffffffffffffffffffffffe03ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffff80000000000ffffffffffffffffffffffffe003fff8
+fffffffffffffffffffffffc07ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffc0000000003ffffffffffffffffffffffffe007fff8
+fffffffffffffffffffffffc0fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffe0000000007ffffffffffffffffffffffffe007fff8
+fffffffffffffffffffffff81fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffe000000000fffffffffffffffffffffffffe00ffff8
+fffffffffffffffffffffff01fffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffff000000001fffffffffffffffffffffffffe00ffff8
+ffffffffffffffffffffffe03ffffffffffffffffffffffffbffffffffffffffffffffff
+ffffffffff800000007fffffffffffffffffffffffffc00ffff8
+ffffffffffffffffffffffe07ffffffffffffffffffdfffff1ffffffffffffffffffffff
+ffffffffffc0000000ffffffffffffffffffffffffffc00ffff8
+ffffffffffffffffffffffe07ffffffffffffffffff9fffff07fffffffffffffffffffff
+ffffffffffe0000001ffffffffffffffffffffffffffc00ffff8
+ffffffffffffffffffffffc0ffffffffffffffffffe3ffffe03fffffffffffffffffffff
+fffffffffff800001fffffffffffffffffffffffffffc01ffff8
+ffffffffffffffffffffff81ffffffffffffffffffc7ffffc00fffffffffffffffffffff
+fffffffffffe00007fffffffffffffffffffffffffffc01ffff8
+ffffffffffffffffffffff81ffffffffffffffffff87ffffc007ffffffffffffffffffff
+ffffffffffff8003ffffffffffffffffffffffffffff801ffff8
+ffffffffffffffffffffff03ffffffffffffffffff0fffff8007ffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff803ffff8
+fffffffffffffffffffffe07fffffffffffffffffe0fffff8001ffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff803ffff8
+fffffffffffffffffffffe07fffffffffffffffffc1fffff0000ffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff803ffff8
+fffffffffffffffffffffc0ffffffffffffffffff83ffffe00007fffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff007ffff8
+fffffffffffffffffffff81fffffffffffffffffe03ffffe00007fffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff007ffff8
+fffffffffffffffffffff83fffffffffffffffffc07ffffc00003fffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffff007ffff8
+fffffffffffffffffffff03fffffffffffffffff80fffff800001fffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffe00fffff8
+ffffffffffffffffffffe07fffffffffffffffff00fffff800000fffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffe00fffff8
+ffffffffffffffffffffe0fffffffffffffffffe01fffff0000007ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffe00fffff8
+ffffffffffffffffffffc0fffffffffffffffffc01ffffe0000003ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffe00fffff8
+ffffffffffffffffffff81fffffffffffffffff803ffffe0000003ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffe01fffff8
+ffffffffffffffffffff81ffffffffffffffffe007ffffc0000003ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffc01fffff8
+ffffffffffffffffffff83ffffffffffffffffe007ffffc0000001ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffc01fffff8
+ffffffffffffffffffff07ffffffffffffffff800fffff80000000ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffc01fffff8
+fffffffffffffffffffe07ffffffffffffffff800fffff00000000ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffc03fffff8
+fffffffffffffffffffc0ffffffffffffffffe001fffff00000000ffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffff803fffff8
+fffffffffffffffffffc0ffffffffffffffffc003ffffe000000007fffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffff803fffff8
+fffffffffffffffffff81ffffffffffffffff0003ffffc000000007fffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffff007fffff8
+fffffffffffffffffff01fffffffffffffffe0007ffffc000000003fffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffff007fffff8
+fffffffffffffffffff03fffffffffffffffe000fffff8000000001fffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffff007fffff8
+ffffffffffffffffffe07fffffffffffffff8000fffff0000000001fffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffe00ffffff8
+ffffffffffffffffffc07fffffffffffffff0001fffff0000000001fffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffe00ffffff8
+ffffffffffffffffffc0fffffffffffffffe0001ffffe0000000000fffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffe00ffffff8
+ffffffffffffffffff80fffffffffffffff80003ffffe0000000000fffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffe01ffffff8
+ffffffffffffffffff81fffffffffffffff00007ffffc0000000000fffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffc01ffffff8
+ffffffffffffffffff81ffffffffffffffe00007ffffc00000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffc01ffffff8
+ffffffffffffffffff03ffffffffffffffc0000fffffc00000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffc03ffffff8
+fffffffffffffffffe03ffffffffffffff00000fffffe00000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff803ffffff8
+fffffffffffffffffc07fffffffffffffe00001ffffff00000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff803ffffff8
+fffffffffffffffffc07fffffffffffffc00007ffffffc0000000007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff807ffffff8
+fffffffffffffffff807fffffffffffff00001fffffffe0000000003ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff807ffffff8
+fffffffffffffffff807ffffffffffffe00003ffffffff0000000003ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff007ffffff8
+fffffffffffffffff00fffffffffffff800007ffffffff8000000003ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff00fffffff8
+fffffffffffffffff00fffffffffffff00000fffffffffc000000001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffff00fffffff8
+ffffffffffffffffe00ffffffffffffc00003fffffffffe000000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffe01fffffff8
+ffffffffffffffffe00ffffffffffff800007ffffffffff000000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffe01fffffff8
+ffffffffffffffffc00ffffffffffff00000fffffffffff800000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffe01fffffff8
+ffffffffffffffff800fffffffffffc00001fffffffffffc00000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffe03fffffff8
+ffffffffffffffff800fffffffffff000007fffffffffffe00000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffe03fffffff8
+ffffffffffffffff001ffffffffffe00000fffffffffffff00000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffc07fffffff8
+ffffffffffffffff001ffffffffffc00001fffffffffffff80000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffc07fffffff8
+fffffffffffffffe000fffffffffe000003fffffffffffff80000001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff807fffffff8
+fffffffffffffffe000fffffffffc000007fffffffffffffc0000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff807fffffff8
+fffffffffffffffc000fffffffff800000ffffffffffffffe0000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff80ffffffff8
+fffffffffffffffc0007fffffffe000001fffffffffffffff0000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff80ffffffff8
+fffffffffffffffc0003fffffffc000003fffffffffffffff0000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff01ffffffff8
+fffffffffffffff80001fffffff8000007fffffffffffffff8000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff01ffffffff8
+fffffffffffffff80000ffffffc000001ffffffffffffffff8000000ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffff01ffffffff8
+fffffffffffffff800003fffff0000003ffffffffffffffffc000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffe01ffffffff8
+fffffffffffffff000000000000000007ffffffffffffffffc000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffe03ffffffff8
+ffffffffffffffe00000000000000000fffffffffffffffffe000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffe03ffffffff8
+ffffffffffffffe00000000000000001fffffffffffffffffe000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffc07ffffffff8
+ffffffffffffffc00000000000000003fffffffffffffffffe000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffc07ffffffff8
+ffffffffffffffc00000000000000007ffffffffffffffffff000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffc07ffffffff8
+ffffffffffffffc0000000000000000fffffffffffffffffff000000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffc0fffffffff8
+ffffffffffffff80000000000000003fffffffffffffffffff800000ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffc0fffffffff8
+ffffffffffffff80000000000000007fffffffffffffffffff800001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff80fffffffff8
+ffffffffffffff8000000000000001ffffffffffffffffffff800001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff81fffffffff8
+ffffffffffffff8000000000000001ffffffffffffffffffffc00001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff81fffffffff8
+ffffffffffffff8000000000000003ffffffffffffffffffffe00001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff01fffffffff8
+ffffffffffffff000000000000000fffffffffffffffffffffe00001ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffff03fffffffff8
+ffffffffffffff000000000000001ffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffe03fffffffff8
+fffffffffffffe000000000000003ffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffe03fffffffff8
+fffffffffffffe000000000000007ffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffe03fffffffff8
+fffffffffffffc00000000000001fffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffe07fffffffff8
+fffffffffffffc00000000000007fffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffc07fffffffff8
+fffffffffffffc00000000000007fffffffffffffffffffffff00001ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffc07fffffffff8
+fffffffffffffc0000000000003ffffffffffffffffffffffff80003ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffc0ffffffffff8
+fffffffffffffc0000000000007ffffffffffffffffffffffff80003ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffc0ffffffffff8
+fffffffffffffc000000000000fffffffffffffffffffffffff80003ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff80ffffffffff8
+fffffffffffffc000000000003fffffffffffffffffffffffff80003ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff80ffffffffff8
+fffffffffffffc000000000007fffffffffffffffffffffffff80003ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff00ffffffffff8
+fffffffffffffc00000000001ffffffffffffffffffffffffff80007ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff01ffffffffff8
+fffffffffffffe00000000001ffffffffffffffffffffffffff80007ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffff01ffffffffff8
+fffffffffffffe0000000000fffffffffffffffffffffffffff80007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffe01ffffffffff8
+ffffffffffffff0000000001fffffffffffffffffffffffffff80007ffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffe03ffffffffff8
+ffffffffffffff000000000ffffffffffffffffffffffffffff80007ffffffffffffffff
+fffffffffffffffffffdffffffffffffffffffe03ffffffffff8
+ffffffffffffff800000003ffffffffffffffffffffffffffff80007ffffffffffffffff
+fffffffffffffffffff9ffffffffffffffffffc03ffffffffff8
+ffffffffffffffe0000001fffffffffffffffffffffffffffff80007ffffffffffffffff
+fffffffffffffffffff1ffffffffffffffffff807ffffffffff8
+fffffffffffffff0000001fffffffffffffffffffffffffffff8000fffffffffffffffff
+fffffffffffffffffff1ffffffffffffffffff807ffffffffff8
+fffffffffffffff800000ffffffffffffffffffffffffffffffc000fffffffffffffffff
+fffffffffffffffffff1ffffffffffffffffff807ffffffffff8
+fffffffffffffffe0003fffffffffffffffffffffffffffffffc000fffffffffffffffff
+ffffffffffffffffffe1ffffffffffffffffff807ffffffffff8
+ffffffffffffffff4007fffffffffffffffffffffffffffffffc001fffffffffffffffff
+ffffffffffffffffffc1ffffffffffffffffff00fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc001fffffffffffffffff
+ffffffffffffffffff83ffffffffffffffffff00fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc001fffffffffffffffff
+ffffffffffffffffff83ffffffffffffffffff00fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc001fffffffffffffffff
+ffffffffffffffffff03ffffffffffffffffff00fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc001fffffffffffffffff
+ffffffffffffffffff03ffffffffffffffffff01fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc003fffffffffffffffff
+ffffffffffffffffff07ffffffffffffffffff01fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc003fffffffffffffffff
+fffffffffffffffffe07fffffffffffffffffe01fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc003fffffffffffffffff
+fffffffffffffffffc07fffffffffffffffffe03fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc007fffffffffffffffff
+fffffffffffffffffc07fffffffffffffffffc03fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc007fffffffffffffffff
+fffffffffffffffff80ffffffffffffffffffc03fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe007fffffffffffffffff
+fffffffffffffffff80ffffffffffffffffffc03fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe007fffffffffffffffff
+fffffffffffffffff80ffffffffffffffffffc03fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe00ffffffffffffffffff
+fffffffffffffffff03ffffffffffffffffff807fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe00ffffffffffffffffff
+ffffffffffffffffe01ffffffffffffffffff807fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe01ffffffffffffffffff
+ffffffffffffffffe03ffffffffffffffffff807fffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe01ffffffffffffffffff
+ffffffffffffffffc07ffffffffffffffffff00ffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe03ffffffffffffffffff
+ffffffffffffffffc07ffffffffffffffffff00ffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe03ffffffffffffffffff
+ffffffffffffffff80fffffffffffffffffff00ffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe07ffffffffffffffffff
+ffffffffffffffff80fffffffffffffffffff00ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff07ffffffffffffffffff
+ffffffffffffffff00ffffffffffffffffffe01ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff07ffffffffffffffffff
+fffffffffffffffe00ffffffffffffffffffe01ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff0fffffffffffffffffff
+fffffffffffffffe00ffffffffffffffffffe01ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff0fffffffffffffffffff
+fffffffffffffffc01ffffffffffffffffffc01ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff1fffffffffffffffffff
+fffffffffffffffc03ffffffffffffffffffc01ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff3fffffffffffffffffff
+fffffffffffffffc03ffffffffffffffffffc03ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffff
+fffffffffffffff807ffffffffffffffffffc03ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffff807ffffffffffffffffff803ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffff00fffffffffffffffffff803ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffff00fffffffffffffffffff807ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffe01fffffffffffffffffff807ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffe03fffffffffffffffffff807ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffc03fffffffffffffffffff807ffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffff807fffffffffffffffffff00fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffff807fffffffffffffffffff00fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffff00ffffffffffffffffffff00fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffff00fffffffffffffffffffe00fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffe01fffffffffffffffffffe01fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffe03fffffffffffffffffffe01fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffc03fffffffffffffffffffc01fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffc07fffffffffffffffffffc01fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffff807fffffffffffffffffffc03fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffff00ffffffffffffffffffffc03fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffff00ffffffffffffffffffff803fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffe01ffffffffffffffffffff803fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffe01ffffffffffffffffffff803fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffc03ffffffffffffffffffff807fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffc03ffffffffffffffffffff007fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff807ffffffffffffffffffff007fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff807ffffffffffffffffffff007fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffff00fffffffffffffffffffff007fffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffe00ffffffffffffffffffffe00ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffe01ffffffffffffffffffffe00ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9fffffffffffff
+fffffffffffc01ffffffffffffffffffffe00ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1fffffffffffff
+fffffffffffc03ffffffffffffffffffffe00ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1fffffffffffff
+fffffffffff803ffffffffffffffffffffc00ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1fffffffffffff
+fffffffffff807ffffffffffffffffffffc00ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1fffffffffffff
+fffffffffff00fffffffffffffffffffffc01ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3fffffffffffff
+fffffffffff00fffffffffffffffffffffc01ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffff83fffffffffffff
+ffffffffffc01fffffffffffffffffffffc01ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffff07fffffffffffff
+ffffffffffc01fffffffffffffffffffffc01ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffff07fffffffffffff
+ffffffffff801fffffffffffffffffffff801ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffff07fffffffffffff
+ffffffffff803fffffffffffffffffffff801ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffff
+ffffffffff003fffffffffffffffffffff803ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0ffffffffffffff
+fffffffffe007fffffffffffffffffffff803ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1ffffffffffffff
+fffffffffc007fffffffffffffffffffff003ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81ffffffffffffff
+fffffffffc00ffffffffffffffffffffff003ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffffffffffffff
+fffffffff800ffffffffffffffffffffff003ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffffffffffffff
+fffffffff801ffffffffffffffffffffff003ffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffff03ffffffffffffff
+fffffffff803ffffffffffffffffffffff007ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffe07ffffffffffffff
+fffffffff003fffffffffffffffffffffe007ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffc07ffffffffffffff
+ffffffffe007fffffffffffffffffffffe007ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffff807ffffffffffffff
+ffffffffc007fffffffffffffffffffffe007ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffff007ffffffffffffff
+ffffffffc007fffffffffffffffffffffe007ffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffff
+ffffffff800ffffffffffffffffffffffe00fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffff
+ffffffff000ffffffffffffffffffffffe00fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe00fffffffffffffff
+fffffffe001ffffffffffffffffffffffe00fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffc01fffffffffffffff
+fffffffc003ffffffffffffffffffffffe00fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffc01fffffffffffffff
+9ffffffc003ffffffffffffffffffffffe00fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffff803fffffffffffffff
+0ffffff8003ffffffffffffffffffffffc01fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffffffffe
+07fffff0007ffffffffffffffffffffffc01fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffffffffe
+07ffffe000fffffffffffffffffffffffc01fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffe007ffffffffffffff8
+03ffffc000fffffffffffffffffffffffc01fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffe007ffffffffffffff0
+03ffff8001fffffffffffffffffffffff801fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffffc007ffffffffffffff0
+01ffff0003fffffffffffffffffffffff803fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffff800ffffffffffffffe0
+00fffe0003fffffffffffffffffffffff803fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffff800ffffffffffffffe0
+00fffe0003fffffffffffffffffffffff803fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffff001ffffffffffffffc0
+003ffc0007fffffffffffffffffffffff003fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffe003ffffffffffffff80
+001fe0001ffffffffffffffffffffffff003fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffe003ffffffffffffff00
+000fc0001ffffffffffffffffffffffff007fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffffc007fffffffffffffe00
+000000001ffffffffffffffffffffffff007fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff8007fffffffffffffe00
+000000003ffffffffffffffffffffffff007fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff800ffffffffffffffc00
+000000003ffffffffffffffffffffffff007fffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffff000ffffffffffffff800
+000000007fffffffffffffffffffffffe007fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe001ffffffffffffff800
+000000007fffffffffffffffffffffffe007fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffe001ffffffffffffff000
+00000001ffffffffffffffffffffffffe007fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc003ffffffffffffff000
+00000001ffffffffffffffffffffffffe007fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffffc007fffffffffffffe000
+00000001ffffffffffffffffffffffffe007fffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffff0007fffffffffffffc000
+00000003ffffffffffffffffffffffffc00ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffff000ffffffffffffffc000
+00000003ffffffffffffffffffffffffc00ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffe000ffffffffffffff8000
+00000007ffffffffffffffffffffffffc00ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffc001ffffffffffffff0000
+0000000fffffffffffffffffffffffffc01ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffffc003ffffffffffffff0000
+0000001fffffffffffffffffffffffffc01ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffff8003fffffffffffffe0000
+0000001fffffffffffffffffffffffffc01ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffff0007fffffffffffffe0000
+0000003fffffffffffffffffffffffffc01ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffe000ffffffffffffffc0000
+0000007fffffffffffffffffffffffff801ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffe000ffffffffffffff80000
+0000007fffffffffffffffffffffffff801ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffffc001ffffffffffffff80000
+000000ffffffffffffffffffffffffff801ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffff8001ffffffffffffff00000
+000001ffffffffffffffffffffffffff801ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffff0003ffffffffffffff00000
+000001ffffffffffffffffffffffffff801ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffff0003ffffffffffffff00000
+000003ffffffffffffffffffffffffff801ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffe0007fffffffffffffe00000
+000003ffffffffffffffffffffffffff801ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffe000ffffffffffffffe00000
+000007ffffffffffffffffffffffffff803ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffffc000ffffffffffffffc00000
+00000fffffffffffffffffffffffffff003ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffff8001ffffffffffffff800000
+00000fffffffffffffffffffffffffff803ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffff0003ffffffffffffff800000
+00001fffffffffffffffffffffffffff803ffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffff0007ffffffffffffff000200
+00003fffffffffffffffffffffffffff007ffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffe0007fffffffffffffe000700
+00007fffffffffffffffffffffffffff00fffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffffc000ffffffffffffffe001f80
+0000ffffffffffffffffffffffffffff00fffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffff8000ffffffffffffffe001f80
+0001ffffffffffffffffffffffffffff00fffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffff8000ffffffffffffffc003fc0
+0001ffffffffffffffffffffffffffff00fffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffff0001ffffffffffffff8007fe0
+0003ffffffffffffffffffffffffffff01fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffe0003ffffffffffffff0007fe0
+0007ffffffffffffffffffffffffffff01fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffe0007ffffffffffffff000fff0
+0007ffffffffffffffffffffffffffff01fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffffc000ffffffffffffffe003fff8
+001fffffffffffffffffffffffffffff07fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffff8000ffffffffffffffe003fffc
+007fffffffffffffffffffffffffffff07fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffff8000ffffffffffffffe003fffe
+00ffffffffffffffffffffffffffffff07fffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffff0001ffffffffffffffc007ffff
+dfffffffffffffffffffffffffffffff0ffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffe0003ffffffffffffff800fffff
+fffffffffffffffffffffffffffffffe1ffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffc0007ffffffffffffff800fffff
+fffffffffffffffffffffffffffffffe1ffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffffc0007ffffffffffffff001fffff
+fffffffffffffffffffffffffffffffe1ffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffff8000fffffffffffffff003fffff
+fffffffffffffffffffffffffffffffe3ffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffe003fffff
+ffffffffffffffffffffffffffffffff3ffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffe0001ffffffffffffffc007fffff
+ffffffffffffffffffffffffffffffff3ffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffe0003ffffffffffffffc007fffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffffc0007ffffffffffffffc00ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffff8000fffffffffffffff800ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffff8000fffffffffffffff801ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffe0000fffffffffffffff001ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffc0001fffffffffffffff003ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffffc0003ffffffffffffffe007ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffff80007ffffffffffffffe007ffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffff0000fffffffffffffffc00fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffff0000fffffffffffffffc00fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffe0001fffffffffffffffc00fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffc0001fffffffffffffff801fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffffc0003fffffffffffffff801fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffff80003fffffffffffffff003fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff007fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffe0000ffffffffffffffff007fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffc0001fffffffffffffffc007fffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffffc0001fffffffffffffffc00ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffff80003fffffffffffffffc01ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff801ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffe0001ffffffffffffffff801ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffc0001ffffffffffffffff803ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffffc0003ffffffffffffffff803ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffff80003fffffffffffffffe007ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffff80007fffffffffffffffe007ffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffe00fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffc00fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffffc0001ffffffffffffffff801fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffff80003ffffffffffffffff803fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffff80003ffffffffffffffff003fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffff00007ffffffffffffffff003fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffe0000ffffffffffffffffe007fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffe0000ffffffffffffffffc007fffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffffc0001ffffffffffffffffc00ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffff80007ffffffffffffffffc00ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffff00007ffffffffffffffff801ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffff00007ffffffffffffffff801ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffe0000fffffffffffffffff003ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffffc0001fffffffffffffffff003ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffff80003ffffffffffffffffe007ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffff80003ffffffffffffffffe007ffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffe00007ffffffffffffffffc00fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffe0000fffffffffffffffffc00fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffffe0000fffffffffffffffffc00fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffff80001fffffffffffffffff801fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffff00003fffffffffffffffff801fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffff00007fffffffffffffffff003fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffe00007fffffffffffffffff007fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffc0000ffffffffffffffffff007fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffffc0001fffffffffffffffffc007fffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffff80003fffffffffffffffffc00ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffff80007fffffffffffffffffc01ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffff00007fffffffffffffffff801ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffff0000ffffffffffffffffff801ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffffc0001ffffffffffffffffff803ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffff80003ffffffffffffffffff803ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffff00007ffffffffffffffffff007ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffff00007ffffffffffffffffff007ffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffe0000ffffffffffffffffffe00fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffc0000ffffffffffffffffffe00fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffffc0001ffffffffffffffffffe01fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffff80003ffffffffffffffffffc03fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffff00007ffffffffffffffffffc03fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffe00007ffffffffffffffffffc03fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffe00007ffffffffffffffffffc07fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffffc0001fffffffffffffffffff807fffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffff80003fffffffffffffffffff80ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffff80003fffffffffffffffffff80ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffff00007fffffffffffffffffff81ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffe0000ffffffffffffffffffff01ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffe0001ffffffffffffffffffff03ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffffc0003ffffffffffffffffffff03ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffff80003fffffffffffffffffffe07ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffff00007fffffffffffffffffffe07ffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffe00007fffffffffffffffffffe0fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffe0000ffffffffffffffffffffc0fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffe0000ffffffffffffffffffffc1fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffffc0001ffffffffffffffffffffc1fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffff80007ffffffffffffffffffff83fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffff00007ffffffffffffffffffff83fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffe00007ffffffffffffffffffff83fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffe0000fffffffffffffffffffff87fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffc0001fffffffffffffffffffff87fffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffffc0001fffffffffffffffffffff0ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffff80003fffffffffffffffffffff0ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffff00007fffffffffffffffffffff0ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffff0000ffffffffffffffffffffff1ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffe0000fffffffffffffffffffffe1ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffffc0001fffffffffffffffffffffe3ffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffff80003fffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffff00007fffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffe0001ffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffe0001ffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffc0003ffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffffc0007ffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffff0000fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffff0000fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffe0001fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffc0003fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffc0003fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffffc0007fffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffff8000ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffff8001ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffff0001ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffff0003ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffff0003ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffe0007ffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffffc000fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff8001fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff8001fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff8003fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff8007fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff8007fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffff0007fffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffe000ffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffe001ffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffc001ffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffc007ffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffc00fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffffc01fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffff801fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffff003fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffff003fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffe00ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffe01ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffc03ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffffc03ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffff807ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffff807ffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffff80fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffff00fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+fffffffffffffffffffffff01fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffe03fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffc1ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffc1ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffffc3ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff83ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff87ffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff8fffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff8fffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff1fffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff1fffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+ffffffffffffffffffffff3fffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffff8
+
+
+showpage
+
+% stop using temporary dictionary
+end
+
+% restore original state
+origstate restore
+
+%%Trailer
diff --git a/texi/gnuslogo-refcard.eps b/texi/gnuslogo-refcard.eps
new file mode 100644 (file)
index 0000000..41f1979
--- /dev/null
@@ -0,0 +1,242 @@
+%!PS-Adobe-2.0 EPSF-1.2
+%%Creator: Adobe Illustrator 88(TM) format generated by CorelTRACE Version 2.0C
+%%Title:  /home/menja/c/larsi/gnus.eps
+%%BoundingBox: 17 11 127 122
+%%CreationDate: Tue Feb 20 01:51:37 1996
+%%DocumentFonts:
+%%ColorUsage: B & W
+%%TileBox: 17 11 127 122
+%%EndComments
+% Copyright 1992 Corel Corporation.
+
+% All rights reserved.
+.15 .15 scale
+
+/wPSMDict 150 dict def
+wPSMDict begin
+/bd {bind def} bind def
+/ld {load def} bd
+/xd {exch def} bd
+/_ null def
+/$c 0 def
+/$m 0 def
+/$y 0 def
+/$k 0 def
+/$t 1 def
+/$n _ def
+/$o 0 def
+/$C 0 def
+/$M 0 def
+/$Y 0 def
+/$K 0 def
+/$T 1 def
+/$N _ def
+/$O 0 def
+/$h false def
+/$al 0 def
+/$tr 0 def
+/$le 0 def
+/$lx 0 def
+/$ly 0 def
+/$ctm matrix currentmatrix def
+/@cp /closepath ld
+/@gs /gsave ld
+/@gr /grestore ld
+/@MN {2 copy le{pop}{exch pop}ifelse}bd
+/setcmykcolor where {pop}{/setcmykcolor{4 1 roll
+3 {3 index add 1 @MN 1 exch sub 3 1 roll} repeat
+setrgbcolor
+pop}bd}ifelse
+/@tc{dup 1 ge{pop}{4 {dup
+6 -1 roll
+mul
+exch}repeat
+pop}ifelse}bd
+/@scc{$c $m $y $k $t @tc setcmykcolor true}bd
+/@SCC{$C $M $Y $K $T @tc setcmykcolor true}bd
+/@sm{/$ctm $ctm currentmatrix def}bd
+/x {/$t xd /$n xd
+/$k xd /$y xd /$m xd /$c xd}bd
+/X {/$T xd /$N xd
+/$K xd /$Y xd /$M xd /$C xd}bd
+/g {1 exch sub 0 0 0
+4 -1 roll
+_ 1 x}bd
+/G {1 exch sub 0 0 0
+4 -1 roll
+_ 1 X}bd
+/k {_ 1 x}bd
+/K {_ 1 X}bd
+/d /setdash ld
+/i {dup 0 ne {setflat} {pop} ifelse}bd
+/j /setlinejoin ld
+/J /setlinecap ld
+/M /setmiterlimit ld
+/w /setlinewidth ld
+/O {/$o xd}bd
+/R {/$O xd}bd
+/c /curveto ld
+/C /c ld
+/l /lineto ld
+/L /l ld
+/m /moveto ld
+/n /newpath ld
+/N /newpath ld
+/F {@scc{eofill}if n} bd
+/f {@cp F}bd
+/S {@SCC{stroke}if n} bd
+/s {@cp
+S}bd
+/B {@gs F @gr
+S}bd
+/b {@cp B }bd
+/u {}bd
+/U {}bd
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+1 i
+2 J
+0 j
+4 M
+[]0 d
+
+%%Note: traced as Normal_Outline
+0 g
+259.2 78.2 m
+327.3 178.5 L
+327.8 179.0 328.3 180.0 329.7 180.4 C
+373.4 241.9 L
+388.8 263.5 L
+389.2 264.0 390.7 264.4 391.6 265.4 C
+413.7 298.0 453.6 351.8 468.0 404.6 C
+467.5 405.6 467.5 407.0 467.5 407.0 C
+442.0 367.6 411.3 319.2 379.2 279.3 C
+372.0 267.3 366.7 265.9 361.9 254.8 C
+333.1 216.0 L
+323.5 207.3 311.0 185.2 302.8 175.6 C
+298.0 165.6 293.2 164.1 288.9 154.0 C
+282.2 147.8 282.2 139.6 276.4 132.4 C
+258.2 77.7 L
+258.2 77.7 259.2 78.2 259.2 78.2 C
+f
+0 g
+470.8 211.6 m
+470.8 211.6 472.3 212.1 472.3 212.1 C
+518.8 305.2 L
+531.3 317.2 L
+537.6 314.8 539.0 300.9 548.6 301.9 C
+555.8 301.9 554.8 302.8 561.6 306.2 C
+595.2 357.1 L
+595.6 358.0 597.6 358.5 598.5 360.0 C
+615.8 398.4 650.8 450.7 657.6 483.8 C
+658.0 486.2 658.0 488.1 658.0 489.6 C
+654.2 489.1 656.1 485.2 650.4 479.5 C
+634.5 446.8 611.5 402.2 592.8 377.2 C
+588.0 370.0 581.7 365.7 577.4 358.5 C
+570.2 355.6 568.3 351.3 560.1 356.6 C
+554.8 360.0 553.9 364.8 550.0 370.0 C
+548.1 371.5 550.0 370.5 547.2 371.0 C
+541.4 365.2 L
+511.2 319.6 484.3 276.0 471.8 220.3 C
+470.8 215.5 471.3 215.5 469.4 212.1 C
+469.4 212.1 470.8 211.6 470.8 211.6 C
+f
+0 g
+731.0 292.8 m
+756.0 351.3 751.6 407.0 771.3 468.0 C
+783.3 520.8 809.7 582.2 822.2 635.0 C
+829.4 684.4 855.8 732.0 825.1 789.1 C
+811.6 797.7 799.6 805.4 784.8 802.0 C
+757.9 792.0 732.9 743.0 726.2 712.8 C
+727.6 708.4 727.2 707.0 730.0 704.6 C
+731.0 704.1 732.9 704.1 734.4 704.6 C
+737.2 709.9 L
+754.0 747.3 L
+758.8 755.0 771.8 754.0 781.9 751.2 C
+788.1 748.3 791.5 745.9 797.7 744.0 C
+831.8 680.1 800.6 611.0 784.3 542.8 C
+765.6 478.5 748.3 431.5 739.2 370.5 C
+733.9 347.5 729.1 318.7 730.0 292.8 C
+730.0 292.8 731.0 292.8 731.0 292.8 C
+f
+0 g
+434.4 462.7 m
+460.3 496.8 462.2 532.8 458.4 575.5 C
+456.4 588.0 451.2 599.0 445.4 609.1 C
+435.3 620.1 435.3 622.5 421.9 630.7 C
+411.8 619.6 398.4 604.8 391.6 586.0 C
+393.6 581.7 396.4 584.1 401.7 577.9 C
+403.2 577.4 404.6 576.9 404.6 576.9 C
+407.0 574.5 406.0 573.6 410.4 571.2 C
+414.2 564.0 418.5 558.2 424.3 545.7 C
+437.2 526.5 428.1 489.6 433.9 462.2 C
+433.9 462.2 434.4 462.7 434.4 462.7 C
+f
+0 g
+226.0 482.4 m
+281.7 485.7 311.0 531.3 357.1 565.9 C
+362.8 572.1 364.8 574.0 368.6 580.3 C
+368.6 581.7 369.1 582.7 369.6 584.6 C
+370.0 585.6 371.5 587.0 372.9 588.0 C
+381.6 606.2 L
+377.2 605.2 374.8 602.8 371.0 597.6 C
+346.0 576.4 316.8 552.0 289.9 536.1 C
+288.9 535.2 288.0 534.2 288.0 534.2 C
+273.6 528.0 263.5 527.5 247.6 530.8 C
+242.4 535.2 239.0 536.1 238.0 544.3 C
+239.5 572.1 266.8 600.0 281.2 624.9 C
+293.7 637.9 300.4 650.4 311.5 668.1 C
+312.0 669.1 313.9 669.6 314.8 671.0 C
+319.6 679.6 L
+319.6 680.1 319.6 681.6 319.2 682.0 C
+285.6 649.4 258.7 601.4 229.9 555.8 C
+216.4 529.9 205.4 511.2 210.2 491.0 C
+212.6 483.8 218.8 484.8 226.0 482.4 C
+f
+0 g
+624.9 600.4 m
+645.1 606.2 L
+676.3 622.5 694.5 658.0 710.8 698.4 C
+710.4 704.1 711.3 704.6 712.3 709.4 C
+696.9 685.9 693.6 667.6 662.4 653.7 C
+654.7 651.3 649.4 650.4 639.3 650.8 C
+633.1 654.2 625.4 659.0 621.6 670.5 C
+597.6 620.6 L
+600.9 612.4 604.3 607.2 613.4 603.8 C
+617.2 603.3 621.1 601.4 624.9 600.4 C
+f
+0 g
+528.4 619.2 m
+548.6 617.2 564.9 629.2 578.8 645.6 C
+584.1 651.8 586.5 662.8 591.8 671.0 C
+593.2 681.6 603.8 690.2 601.9 704.1 C
+598.5 705.1 599.0 698.8 594.7 694.0 C
+581.7 679.6 L
+569.7 668.6 545.7 663.8 532.8 673.9 C
+487.2 697.9 467.5 754.5 413.2 772.8 C
+393.1 778.0 387.3 771.8 367.2 760.3 C
+360.9 755.5 357.6 744.9 351.3 740.6 C
+347.0 740.6 349.9 743.5 344.6 747.3 C
+344.1 748.8 343.6 750.2 343.6 750.2 C
+322.5 770.8 L
+312.9 775.2 300.9 784.3 287.0 779.0 C
+283.6 777.1 281.7 776.1 279.3 775.2 C
+250.0 750.7 229.4 705.6 181.4 697.4 C
+165.6 705.1 160.3 715.2 150.7 733.9 C
+130.5 685.4 L
+142.5 663.3 L
+147.3 661.9 147.3 660.4 151.2 655.6 C
+160.8 650.4 169.9 649.4 182.8 655.2 C
+212.1 676.8 L
+213.1 677.7 214.0 678.7 216.0 679.2 C
+238.5 695.5 250.5 727.6 279.3 735.3 C
+296.1 727.2 312.4 715.6 326.8 695.5 C
+330.2 688.3 331.6 684.9 335.5 681.1 C
+345.1 694.5 352.8 717.6 372.9 721.9 C
+423.3 726.7 453.6 670.5 498.2 631.6 C
+510.7 624.4 517.4 621.1 528.4 619.2 C
+f
+%%Trailer
+end
+showpage
diff --git a/texi/gnuslogo.refcard b/texi/gnuslogo.refcard
deleted file mode 100644 (file)
index aacf40e..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-%!PS-Adobe-2.0 EPSF-1.2
-%%Creator: Adobe Illustrator 88(TM) format generated by CorelTRACE Version 2.0C
-%%Title:  /home/menja/c/larsi/gnus.eps
-%%BoundingBox: 0 0 924.5 907.2
-%%CreationDate: Tue Feb 20 01:51:37 1996
-%%DocumentFonts:
-%%ColorUsage: B & W
-%%TileBox: 0 0 924.5 907.2
-%%EndComments
-%%BeginProcSet:Adobe_Illustrator_1.1 0 0
-% Copyright 1992 Corel Corporation.
-
-% All rights reserved.
-.15 .15 scale
-
-/wPSMDict 150 dict def
-wPSMDict begin
-/bd {bind def} bind def
-/ld {load def} bd
-/xd {exch def} bd
-/_ null def
-/$c 0 def
-/$m 0 def
-/$y 0 def
-/$k 0 def
-/$t 1 def
-/$n _ def
-/$o 0 def
-/$C 0 def
-/$M 0 def
-/$Y 0 def
-/$K 0 def
-/$T 1 def
-/$N _ def
-/$O 0 def
-/$h false def
-/$al 0 def
-/$tr 0 def
-/$le 0 def
-/$lx 0 def
-/$ly 0 def
-/$ctm matrix currentmatrix def
-/@cp /closepath ld
-/@gs /gsave ld
-/@gr /grestore ld
-/@MN {2 copy le{pop}{exch pop}ifelse}bd
-/setcmykcolor where {pop}{/setcmykcolor{4 1 roll
-3 {3 index add 1 @MN 1 exch sub 3 1 roll} repeat
-setrgbcolor
-pop}bd}ifelse
-/@tc{dup 1 ge{pop}{4 {dup
-6 -1 roll
-mul
-exch}repeat
-pop}ifelse}bd
-/@scc{$c $m $y $k $t @tc setcmykcolor true}bd
-/@SCC{$C $M $Y $K $T @tc setcmykcolor true}bd
-/@sm{/$ctm $ctm currentmatrix def}bd
-/x {/$t xd /$n xd
-/$k xd /$y xd /$m xd /$c xd}bd
-/X {/$T xd /$N xd
-/$K xd /$Y xd /$M xd /$C xd}bd
-/g {1 exch sub 0 0 0
-4 -1 roll
-_ 1 x}bd
-/G {1 exch sub 0 0 0
-4 -1 roll
-_ 1 X}bd
-/k {_ 1 x}bd
-/K {_ 1 X}bd
-/d /setdash ld
-/i {dup 0 ne {setflat} {pop} ifelse}bd
-/j /setlinejoin ld
-/J /setlinecap ld
-/M /setmiterlimit ld
-/w /setlinewidth ld
-/O {/$o xd}bd
-/R {/$O xd}bd
-/c /curveto ld
-/C /c ld
-/l /lineto ld
-/L /l ld
-/m /moveto ld
-/n /newpath ld
-/N /newpath ld
-/F {@scc{eofill}if n} bd
-/f {@cp F}bd
-/S {@SCC{stroke}if n} bd
-/s {@cp
-S}bd
-/B {@gs F @gr
-S}bd
-/b {@cp B }bd
-/u {}bd
-/U {}bd
-%%EndProlog
-%%BeginSetup
-%%EndSetup
-1 i
-2 J
-0 j
-4 M
-[]0 d
-
-%%Note: traced as Normal_Outline
-0 g
-259.2 78.2 m
-327.3 178.5 L
-327.8 179.0 328.3 180.0 329.7 180.4 C
-373.4 241.9 L
-388.8 263.5 L
-389.2 264.0 390.7 264.4 391.6 265.4 C
-413.7 298.0 453.6 351.8 468.0 404.6 C
-467.5 405.6 467.5 407.0 467.5 407.0 C
-442.0 367.6 411.3 319.2 379.2 279.3 C
-372.0 267.3 366.7 265.9 361.9 254.8 C
-333.1 216.0 L
-323.5 207.3 311.0 185.2 302.8 175.6 C
-298.0 165.6 293.2 164.1 288.9 154.0 C
-282.2 147.8 282.2 139.6 276.4 132.4 C
-258.2 77.7 L
-258.2 77.7 259.2 78.2 259.2 78.2 C
-f
-0 g
-470.8 211.6 m
-470.8 211.6 472.3 212.1 472.3 212.1 C
-518.8 305.2 L
-531.3 317.2 L
-537.6 314.8 539.0 300.9 548.6 301.9 C
-555.8 301.9 554.8 302.8 561.6 306.2 C
-595.2 357.1 L
-595.6 358.0 597.6 358.5 598.5 360.0 C
-615.8 398.4 650.8 450.7 657.6 483.8 C
-658.0 486.2 658.0 488.1 658.0 489.6 C
-654.2 489.1 656.1 485.2 650.4 479.5 C
-634.5 446.8 611.5 402.2 592.8 377.2 C
-588.0 370.0 581.7 365.7 577.4 358.5 C
-570.2 355.6 568.3 351.3 560.1 356.6 C
-554.8 360.0 553.9 364.8 550.0 370.0 C
-548.1 371.5 550.0 370.5 547.2 371.0 C
-541.4 365.2 L
-511.2 319.6 484.3 276.0 471.8 220.3 C
-470.8 215.5 471.3 215.5 469.4 212.1 C
-469.4 212.1 470.8 211.6 470.8 211.6 C
-f
-0 g
-731.0 292.8 m
-756.0 351.3 751.6 407.0 771.3 468.0 C
-783.3 520.8 809.7 582.2 822.2 635.0 C
-829.4 684.4 855.8 732.0 825.1 789.1 C
-811.6 797.7 799.6 805.4 784.8 802.0 C
-757.9 792.0 732.9 743.0 726.2 712.8 C
-727.6 708.4 727.2 707.0 730.0 704.6 C
-731.0 704.1 732.9 704.1 734.4 704.6 C
-737.2 709.9 L
-754.0 747.3 L
-758.8 755.0 771.8 754.0 781.9 751.2 C
-788.1 748.3 791.5 745.9 797.7 744.0 C
-831.8 680.1 800.6 611.0 784.3 542.8 C
-765.6 478.5 748.3 431.5 739.2 370.5 C
-733.9 347.5 729.1 318.7 730.0 292.8 C
-730.0 292.8 731.0 292.8 731.0 292.8 C
-f
-0 g
-434.4 462.7 m
-460.3 496.8 462.2 532.8 458.4 575.5 C
-456.4 588.0 451.2 599.0 445.4 609.1 C
-435.3 620.1 435.3 622.5 421.9 630.7 C
-411.8 619.6 398.4 604.8 391.6 586.0 C
-393.6 581.7 396.4 584.1 401.7 577.9 C
-403.2 577.4 404.6 576.9 404.6 576.9 C
-407.0 574.5 406.0 573.6 410.4 571.2 C
-414.2 564.0 418.5 558.2 424.3 545.7 C
-437.2 526.5 428.1 489.6 433.9 462.2 C
-433.9 462.2 434.4 462.7 434.4 462.7 C
-f
-0 g
-226.0 482.4 m
-281.7 485.7 311.0 531.3 357.1 565.9 C
-362.8 572.1 364.8 574.0 368.6 580.3 C
-368.6 581.7 369.1 582.7 369.6 584.6 C
-370.0 585.6 371.5 587.0 372.9 588.0 C
-381.6 606.2 L
-377.2 605.2 374.8 602.8 371.0 597.6 C
-346.0 576.4 316.8 552.0 289.9 536.1 C
-288.9 535.2 288.0 534.2 288.0 534.2 C
-273.6 528.0 263.5 527.5 247.6 530.8 C
-242.4 535.2 239.0 536.1 238.0 544.3 C
-239.5 572.1 266.8 600.0 281.2 624.9 C
-293.7 637.9 300.4 650.4 311.5 668.1 C
-312.0 669.1 313.9 669.6 314.8 671.0 C
-319.6 679.6 L
-319.6 680.1 319.6 681.6 319.2 682.0 C
-285.6 649.4 258.7 601.4 229.9 555.8 C
-216.4 529.9 205.4 511.2 210.2 491.0 C
-212.6 483.8 218.8 484.8 226.0 482.4 C
-f
-0 g
-624.9 600.4 m
-645.1 606.2 L
-676.3 622.5 694.5 658.0 710.8 698.4 C
-710.4 704.1 711.3 704.6 712.3 709.4 C
-696.9 685.9 693.6 667.6 662.4 653.7 C
-654.7 651.3 649.4 650.4 639.3 650.8 C
-633.1 654.2 625.4 659.0 621.6 670.5 C
-597.6 620.6 L
-600.9 612.4 604.3 607.2 613.4 603.8 C
-617.2 603.3 621.1 601.4 624.9 600.4 C
-f
-0 g
-528.4 619.2 m
-548.6 617.2 564.9 629.2 578.8 645.6 C
-584.1 651.8 586.5 662.8 591.8 671.0 C
-593.2 681.6 603.8 690.2 601.9 704.1 C
-598.5 705.1 599.0 698.8 594.7 694.0 C
-581.7 679.6 L
-569.7 668.6 545.7 663.8 532.8 673.9 C
-487.2 697.9 467.5 754.5 413.2 772.8 C
-393.1 778.0 387.3 771.8 367.2 760.3 C
-360.9 755.5 357.6 744.9 351.3 740.6 C
-347.0 740.6 349.9 743.5 344.6 747.3 C
-344.1 748.8 343.6 750.2 343.6 750.2 C
-322.5 770.8 L
-312.9 775.2 300.9 784.3 287.0 779.0 C
-283.6 777.1 281.7 776.1 279.3 775.2 C
-250.0 750.7 229.4 705.6 181.4 697.4 C
-165.6 705.1 160.3 715.2 150.7 733.9 C
-130.5 685.4 L
-142.5 663.3 L
-147.3 661.9 147.3 660.4 151.2 655.6 C
-160.8 650.4 169.9 649.4 182.8 655.2 C
-212.1 676.8 L
-213.1 677.7 214.0 678.7 216.0 679.2 C
-238.5 695.5 250.5 727.6 279.3 735.3 C
-296.1 727.2 312.4 715.6 326.8 695.5 C
-330.2 688.3 331.6 684.9 335.5 681.1 C
-345.1 694.5 352.8 717.6 372.9 721.9 C
-423.3 726.7 453.6 670.5 498.2 631.6 C
-510.7 624.4 517.4 621.1 528.4 619.2 C
-f
-%%Trailer
-end
-showpage
diff --git a/texi/gnusref-ja.tex b/texi/gnusref-ja.tex
new file mode 100644 (file)
index 0000000..23c0947
--- /dev/null
@@ -0,0 +1,924 @@
+% -*- mode:LaTeX; eval:(set (make-local-variable 'LaTeX-version) "2"); truncate-lines:t; -*-
+% include file for the Gnus refcard and booklet
+\def\version{5.5}
+\def\date{2 May 1998}
+\def\author{Vladimir Alexiev $<$vladimir@cs.ualberta.ca$>$}
+\raggedbottom\raggedright
+\newlength{\logowidth}\setlength{\logowidth}{6.861in}
+\newlength{\logoheight}\setlength{\logoheight}{7.013in}
+\newlength{\keycolwidth}
+\newenvironment{keys}[1]% #1 is the widest key
+  {\nopagebreak%\noindent%
+   \settowidth{\keycolwidth}{#1}%
+   \addtolength{\keycolwidth}{\tabcolsep}%
+   \addtolength{\keycolwidth}{-\columnwidth}%
+   \begin{tabular}{@{}l@{\hspace{\tabcolsep}}p{-\keycolwidth}@{}}}%
+  {\end{tabular}\\}
+\catcode`\^=12 % allow ^ to be typed literally
+\catcode`\~=12 % allow ~ to be typed literally
+\newcommand{\B}[1]{{\bf#1})}    % bold l)etter
+
+\def\Title{
+\begin{center}
+{\bf\LARGE Gnus \version\ Reference \Guide\\}
+%{\normalsize \Guide\ version \refver}
+\end{center}
+}
+
+\newcommand\Logo[1]{\centerline{
+\makebox[\logoscale\logowidth][l]{\vbox to \logoscale\logoheight
+{\vfill\special{psfile=gnuslogo.#1}}\vspace{-\baselineskip}}}}
+
+\def\CopyRight{
+\begin{center}
+Copyright \copyright\ 1995 Free Software Foundation, Inc.\\*
+Copyright \copyright\ 1995-97 \author.\\*
+Created from the Gnus manual Copyright \copyright\ 1994-97 Lars Magne
+Ingebrigtsen.\\*
+and the Emacs Help Bindings feature (C-h b).\\*
+Gnus logo copyright \copyright\ 1995 Luis Fernandes.\\*
+\end{center}
+
+Permission is granted to make and distribute copies of this reference
+\guide{} provided the copyright notice and this permission are preserved on
+all copies.  Please send corrections, additions and suggestions to the
+above email address. \Guide{} last edited on \date.
+}
+
+\def\Notes{
+\subsec{Notes}
+{\samepage
+Gnus \e$B$O5pBg$G$9\e(B. \e$B8=:_$O\e(B 633 \e$B$b$NBPOCE*\e(B (\e$BMxMQ<T$N;HMQ$G$-$k\e(B) \e$BL?Na$,$"$j\e(B
+\e$B$^$9\e(B.  \e$B$3$l$i$NL?Na$NB?$/$O0l$D$rD6$($k%-!<B+G{$,$"$j$^$9\e(B. 40 \% \e$B$N>l\e(B
+\e$B=j$N@aLs$N$?$a$K\e(B, \e$B$3$N\e(B \guide \e$B$G$OA4$F$N4X?t$O\e(B ``\e$B$h$jO@M}E*\e(B'' \e$B$JB+G{$G\e(B
+\e$B0lEY$@$1I=<($5$l$F$$$^$9\e(B. \e$BB>$NB+G{$O5-=R$N:G=i$K3g8L$NCf$GM?$($i$l$F$$\e(B
+\e$B$^$9\e(B. \e$B$3$N\e(B \guide{} \e$B$O%-!<B+G{$@$1$r@bL@$7$F$$$^$9$N$G\e(B, \e$BB?$/$N$9$P$i$7\e(B
+\e$B$$5!G=$r8+$D$1$k$?$a$K$O\e(B, \e$B>/$/$H$b$r%^%K%e%"%k$r$6$C$HD/$a$k\e(B {\em \e$BI,MW\e(B
+\/} \e$B$,$"$j$^$9\e(B.
+
+\e$BB?$/$N\e(B gnus \e$B$NL?Na$O?tCM0z?t$r;H$$$^$9\e(B. \e$BIaDL$O%a%?%-!<$r2!$7$F$$$k\e(B
+\e$B4V$K@\F,0z?t$rF~NO$7$^$9$,\e(B, \e$B$?$$$F$$$N\e(B gnus \e$B$N%b!<%I$G$O\e(B, \e$B?t;z$,<+J,<+\e(B
+\e$B?H$rA^F~$7$J$$$?$a\e(B, \e$B%a%?$r;H$&I,MW$O$"$j$^$;$s\e(B. \e$B@\F,0z?t$NIU$$$?$H$-$N\e(B
+\e$B?6$kIq$$$O\e(B [\e$B3Q3g8L\e(B] \e$B$G=q$+$l$F$$$^$9\e(B. \e$B@\F,0z?t$O$7$P$7$P$3$l$i$r;XDj$9\e(B
+\e$B$k$N$KMQ$$$i$l$^$9\e(B:
+
+\quad [\e$B5wN%\e(B] \e$B%]%$%s%H$,$I$N$/$i$$$N%*%V%8%'%/%H$rHt$P$9$+\e(B.
+
+\quad [\e$BHO0O\e(B] \e$B$I$N$/$i$$$N%*%V%8%'%/%H$,:nMQ$5$l$k$+\e(B (\e$B8=:_$NJ*$r4^$`\e(B).
+
+\quad [p/p] ``\e$B%W%m%;%9\e(B/\e$B@\F,0z?t$N=,47\e(B'': \e$B@\F,0z?t$,M?$($i$l$k$H\e(B, \e$B:nMQ\e(B
+\e$B$9$kBP>]$N?t$r7hDj$7$^$9\e(B (\e$BIi$O5U8~$-$H$$$&0UL#$G$9\e(B).
+transient-mark-mode \e$B$+\e(B zmacs-region \e$B$,@_Dj$5$l$F$$$F%j!<%8%g%s$,\e(Bactive
+\e$B$G$"$k$H\e(B, \e$B$=$N%j!<%8%g%s$rA`:n$7$^$9\e(B. \e$B%W%m%;%90u\e(B \# \e$B$G0u$NIU$$$?BP>]$,\e(B
+\e$B$"$l$P\e(B, \e$B$=$l$i$rA`:n$7$^$9\e(B. \e$B$=$&$G$J$1$l$P\e(B, \e$B8=:_$NBP>]$@$1$rA`:n$7$^$9\e(B.
+
+\quad [\e$B%l%Y%k\e(B] \e$B%0%k!<%W9VFIEY%l%Y%k$G$9\e(B. \e$BF1Ey$+$=$l$h$jDc$$%0%k!<%W$N\e(B
+\e$B$_$,:nMQ$N1F6A$r<u$1$^$9\e(B. \e$B@\F,0z?t$,M?$($i$l$J$$$H\e(B,
+`gnus-group-default-list-level' \e$B$,;H$o$l$^$9\e(B.
+`gnus-group-use-permanent-levels' \e$B$,??$G$"$k$H\e(B, `g' \e$B$H\e(B `l' \e$BL?Na$X$N@\\e(B
+\e$BF,0z?t$O=i4|%l%Y%k$b@_Dj$7$^$9\e(B.
+
+\quad [score] \e$B5-;v$N%9%3%"$G$9\e(B. \e$B@\F,0z?t$,M?$($i$l$J$$$H\e(B,
+`gnus-summary-default-score' \e$B$,;H$o$l$^$9\e(B.
+
+\quad [GL \e$BEY?t\e(B] GroupLens \e$B$NEY?t\e(B (1-5) \e$B$r\e(B, \e$BJL$N5-;v$K0\F0$9$kA0$K8=:_\e(B
+\e$B$N5-;v$KM?$($^$9\e(B.
+
+%Some functions were not yet documented at the time of creating this
+%\guide and are clearly indicated as such.
+}}
+
+\def\GroupLevels{
+\subsec{\e$B%0%k!<%W9VFIEY%l%Y%k\e(B}{\samepage
+\e$B2<$NI=$O=i4|\e(B gnus \e$B%l%Y%k$r;H$C$F$$$k$3$H$r2>Dj$7$F$$$^$9\e(B. \e$BMxMQ<TMQ%l%Y\e(B
+\e$B%k$r6u$NMs$K=q$$$F$/$@$5$$\e(B. \\*
+
+\begin{tabular}{|c|l|l|}
+\hline
+\e$B%l%Y%k\e(B & \e$B%0%k!<%W\e(B & \e$B>uBV\e(B \\
+\hline
+1 & \e$B%a!<%k%0%k!<%W\e(B &             \\
+2 & \e$B%a!<%k%0%k!<%W\e(B &             \\
+3 & \e$B=i4|9VFI%l%Y%k\e(B & \e$B9VFI\e(B        \\
+4 &                &             \\
+5 & \e$B=i4|0lMw%l%Y%k\e(B &             \\
+\hline
+6 & \e$B=i4|Hs9VFI%l%Y%k\e(B & \e$BHs9VFI\e(B    \\
+7 &                  &           \\
+\hline
+8 &                  & \e$B%>%s%S\e(B    \\
+\hline
+9 &                  & \e$B:o=|\e(B      \\
+\hline
+\end{tabular}
+}}
+
+\def\Marks{\subsec{\e$B0u;X<(J8;z\e(B}{\samepage
+\e$BL?Na$,D>@\0u$rIU$1$k>l9g$O\e(B, \e$B3g8L$GI=<($5$l$F$$$^$9\e(B. \\*
+\newlength{\markcolwidth}
+\settowidth{\markcolwidth}{` '}% widest character
+\addtolength{\markcolwidth}{4\tabcolsep}
+\addtolength{\markcolwidth}{-\columnwidth}
+\newlength{\markdblcolwidth}
+\setlength{\markdblcolwidth}{\columnwidth}
+\addtolength{\markdblcolwidth}{-2\tabcolsep}
+\begin{tabular}{|c|p{-\markcolwidth}|}
+\hline
+\multicolumn{2}{|p{\markdblcolwidth}|}
+{{\bf ``\e$B4{FI\e(B'' \e$B0u\e(B.}
+  \e$B$3$l$i$N0u$NA4$F$O35N,9T$N:G=i$N7e$K8=$l$^$9$N$G\e(B, \e$B6&B8$9$k$3$H$O$G$-\e(B
+  \e$B$^$;$s\e(B.}\\
+\hline
+` ' & (M-u, M SPC, M c) \e$BL$FI\e(B.\\
+!   & (!, M t) \e$B2D;k\e(B (\e$B6=L#?<$$\e(B).\\ %(M !)
+?   & (?, M ?) \e$BJ]N1\e(B (\e$B%U%)%m!<%"%C%W$N$_$K6=L#$,$"$k\e(B).\\
+E   & (E, M e) {\bf \e$B;~8B>C5n2DG=\e(B}. \e$B%a!<%k%0%k!<%W$G$N$_0UL#$,$"$k\e(B.\\ %(M x)
+\hline\hline
+\multicolumn{2}{|p{\markdblcolwidth}|}{\e$B2<$N0u$O5-;v$,4{FI\e(B (\e$B@Z$i$l$?\e(B,
+  \e$B6=L#$N$J$$\e(B) \e$B$H$$$&$3$H$r0UL#$7\e(B, \e$BBgBNF1MM$J8z2L$r;}$A$^$9\e(B. \e$B$7$+$7L?Na\e(B
+  \e$B$K$O$=$l$i$GL@$i$+$J0c$$$,$"$k$b$N$b$"$j$^$9\e(B (\e$BNc\e(B.{} M M-C-r, \e$BE,1~%9%3\e(B
+  \e$B%"\e(B).}\\
+\hline
+r   & (d, M d, M r) \e$B>C5n\e(B (\e$B4{FI\e(B ({\bf read}) \e$B$H$7$F0uIU$1$i$l$?\e(B).\\
+C   & (M C; M C-c; M H; c, Z c; Z n; Z C) {\bf catch-up} \e$B$G@Z$i$l$?\e(B.\\
+F   & (O s; G s b) SOUP \e$B$5$l$F$$$k\e(B.\\
+G   & (S C, C) \e$B<h$j>C$7:Q$_\e(B (\e$B<+J,<+?H$N5-;v$N$_\e(B).\\
+O   & \e$B8E$$\e(B ({\bf old}) (\e$BA02s$N%;%C%7%g%s$G4{FI$N0u$,IU$$$?\e(B).\\
+K   & (k, M k; C-k, M K) \e$B@Z$i$l$?\e(B ({\bf Killed}).\\
+M   & \e$B=EJ#>C5n$K$h$C$F0u$,IU$$$?\e(B.\\
+Q   & \e$B$^$P$i%9%l%C%I$N:n@.Cf$KJ,$1$i$l$?\e(B.\\
+R   & \e$B4{FI\e(B ({\bf read}) (\e$B<B:]$K1\Mw$5$l$?\e(B).\\
+X   & \e$B%-%k%U%!%$%k$G@Z$i$l$?\e(B.\\
+Y   & \e$BDc%9%3%"$K$h$C$F@Z$i$l$?\e(B.\\
+\hline\hline
+\multicolumn{2}{|p{\markdblcolwidth}|}
+{{\bf \e$BB>$N0u\e(B}}\\
+\hline
+\#  & (\#, M \#, M P p) \e$B<B9T2DG=\e(B (\e$B<!$N:nMQ$G1F6A$r<u$1$k\e(B).\\ %(M \#)
+*   & (*) \e$B1JB3\e(B (\e$B$b$7$/$OB>$NM}M3$G%-%c%C%7%e$5$l$F$$$k\e(B).\\
+A   & \e$B1~Ez:Q$_\e(B ({\bf answered}) (\e$B%U%)%m!<%"%C%W$b$7$/$OJVEz$r$7$?\e(B).\\
+S   & (O {\bf x}) \e$BJ]B8:Q$_\e(B {\bf Saved}.\\
++   & \e$B=i4|%9%3%"$h$j>e\e(B.\\
+$-$ & \e$B=i4|%9%3%"$h$j2<\e(B.\\
+=   & \e$B;R$r;}$D\e(B (\e$B$=$N2<$K%9%l%C%I$r\e(B). `\%e' `gnus-summary-line-format'
+\e$B$r2C$($^$9\e(B.\\
+\hline
+\end{tabular}
+}}
+
+
+\def\General{\sec{(H) \e$B0lHLE*$J%3%^%s%I$H%X%k%W%3%^%s%I\e(B}{\samepage
+\e$B$3$l$i$NL?Na$O$I$3$G$bF0:n$7$^$9\e(B.
+\begin{keys}{C-c C-i}
+C-c C-i & Gnus \e$B$N%*%s%i%$%s\e(B {\bf info} \e$B$K0\F0$7$^$9\e(B.\\
+C-c C-b & Gnus \e$B$N\e(B {\bf bug} \e$BJs9p$rAw$j$^$9\e(B.\\
+\end{keys}
+
+\e$B$3$l$i$NL?Na$O35N,%b!<%I$GF0:n$7\e(B, \e$B$[$H$s$I$O%0%k!<%W%b!<%I$G$bF0:n$7$^\e(B
+\e$B$9\e(B.\\*
+\begin{keys}{H d}
+H d     & (C-c C-d) \e$B$3$N%0%k!<%W$N@bL@\e(B ({\bf Describe}) \e$B$r$7$^$9\e(B. [\e$B@\\e(B
\e$BF,<-\e(B: \e$B%5!<%P!<$+$i@bL@$r:FEYFI$_9~$_$^$9\e(B.]\\
+H f     & ange-ftp \e$B$r;H$C$F\e(B, \e$B$3$N%0%k!<%W$N\e(B {\bf FAQ} \e$B$r<hF@$7$h$&$H$7\e(B
\e$B$^$9\e(B.\\
+H h     & \e$BHs>o$KC;$$%X%k%W\e(B ({\bf help}) \e$B%a%C%;!<%8$rI=<($7$^$9\e(B.\\
+
+H i     & (C-c C-i) Gnus \e$B$N%*%s%i%$%s\e(B {\bf info} \e$B$K0\F0$7$^$9\e(B.\\
+H v     & Gnus \e$B$N%P!<%8%g%s\e(B ({\bf version}) \e$BHV9f$rI=<($7$^$9\e(B.\\
+\end{keys}}}
+
+\def\GroupMode{\sec{\e$B%0%k!<%W%b!<%I\e(B}
+\begin{keys}{C-c M-C-x}
+RET     & (=) \e$B$3$N%0%k!<%W$rA*Br$7$^$9\e(B [\e$B@\F,0z?t\e(B: \e$B$I$l$/$i$$$N\e(B (\e$B4{FI\e(B)
+          \e$B5-;v$r<hF@$9$k$+\e(B. \e$B@5\e(B: \e$B:G?7$N5-;v\e(B, \e$BIi\e(B: \e$B:G8E$N$b$N\e(B, C-u: \e$BHV9f\e(B
+          \e$B$r?R$M$^$9\e(B]. \e$B2C$($F\e(B: \e$B%H%T%C%/$N@^$jJV$7$r@Z$j49$($^$9\e(B.\\
+SPC     & \e$B$3$N%0%k!<%W$rA*Br$7$F\e(B, \e$B:G=i$NL$FI5-;v$rI=<($7$^$9\e(B. [\e$B@\F,0z\e(B
+\e$B?t$O>e$HF1$8$G$9\e(B.]\\
+?       & \e$BHs>o$KC;$$%X%k%W%a%C%;!<%8$rM?$($^$9\e(B.\\
+$<$     & \e$B%0%k!<%W%P%C%U%!$N:G=i$K0\F0$7$^$9\e(B.\\
+$>$     & \e$B%0%k!<%W%P%C%U%!$N:G8e$K0\F0$7$^$9\e(B.\\
+,       & \e$B:GDc%l%Y%k$NL$FI5-;v$KHt$S$^$9\e(B.\\
+.       & \e$B:G=i$NL$FI5-;v$N$"$k%0%k!<%W$KHt$S$^$9\e(B.\\
+^       & \e$B%5!<%P!<%P%C%U%!%b!<%I$KF~$j$^$9\e(B.\\
+a       & \e$B5-;v\e(B ({\bf article}) \e$B$r%0%k!<%W$KEj9F$7$^$9\e(B.\\
+b       & \e$B56\e(B ({\bf bogus}) \e$B%0%k!<%W$r8+$D$1$F>C5n$7$^$9\e(B.\\
+c       & \e$BA4$F$NL$0u5-;v$K4{FI$N0u$rIU$1$^$9\e(B ({\bf catch-up}). [p/p]\\
+g       & \e$B?7$7$$5-;v$,$"$k$+\e(B, \e$B%5!<%P!<$rD4$Y$^$9\e(B ({\bf get}). [\e$B%l%Y%k\e(B]\\
+j       & \e$B;XDj$5$l$?%0%k!<%W$KHt$S$^$9\e(B ({\bf jump}) (\e$B$b$7$+$7$?$i@Z$i\e(B
+          \e$B$l$F$$$k$+$b$7$l$^$;$s\e(B).\\
+m       & \e$BC/$+$K%a!<%k\e(B ({\bf mail}) \e$B$rAw$j$^$9\e(B.\\
+n       & \e$BL$FI5-;v$N$"$k<!\e(B ({\bf next}) \e$B$N%0%k!<%W$K0\F0$7$^$9\e(B.
+[\e$B5wN%\e(B]\\
+p       & (DEL) \e$BL$FI5-;v$N$"$kA0\e(B ({\bf previous}) \e$B$N%0%k!<%W$K0\F0$7$^\e(B
+\e$B$9\e(B.
+[\e$B5wN%\e(B]\\
+q       & Gnus \e$B$r=*N;\e(B ({\bf Quit}) \e$B$7$^$9\e(B. \e$B%a%b%j!<$+$i>C5n$9$k$K$O\e(B
+          M-x gnus-unload \e$B$r<B9T$7$F$/$@$5$$\e(B.\\
+r       & \e$B=i4|2=%U%!%$%k\e(B `.gnus' \e$B$r:FEYFI$_9~$_$^$9\e(B ({\bf Re-read}).\\
+s       & `.newsrc.eld' \e$B%U%!%$%k$rJ]B8\e(B ({\bf save}) \e$B$7$^$9\e(B (\e$B$=$l$H\e(B,
+`gnus-save-newsrc-file' \e$B$,??$G$"$l$P\e(B `.newsrc' \e$B$bJ]B8$7$^$9\e(B.)\\
+t       & {\bf Topic} \e$B%b!<%I$r@Z$j49$($^$9\e(B. \e$B%H%T%C%/$O%0%k!<%W$N3,AX9=\e(B
+          \e$BB$$G$9\e(B.\\
+z       & Gnus \e$B$r0l;~Dd;_$7$^$9\e(B (\e$B%0%k!<%W%P%C%U%!0J30$N%P%C%U%!$r@Z$j\e(B
+          \e$B$^$9\e(B).\\
+B       & \e$B30It%5!<%P!<$r354Q\e(B ({\bf browse}) \e$B$7$^$9\e(B (\e$BJ}K!$HL>A0$r;XDj$7\e(B
+          \e$B$^$9\e(B).\\
+C       & \e$B$3$N%0%k!<%W$NA4$F$N5-;v$r4{FI$H$7$F0uIU$1$^$9\e(B ({\bf
+          Catch-up}). [p/p]\\
+F       & \e$B?7$7$$%0%k!<%W$r8+$D$1\e(B ({\bf find}) \e$B$=$l$i$K:n6H$r<B9T$7$^$9\e(B.
+          [\e$B@\F,<-\e(B: \e$B%5!<%P!<$K?R$M$^$9\e(B]\\
+N       & \e$B<!\e(B ({\bf next}) \e$B$N%0%k!<%W$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+P       & \e$BA0\e(B ({\bf previous}) \e$B$N%0%k!<%W$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+Q       & .newsrc \e$B%U%!%$%k$rJ]B8$;$:$K\e(B Gnus \e$B$r=*N;\e(B ({\bf Quit})\e$B$7$^$9\e(B.\\
+R       & Gnus \e$B$r:F5/F0\e(B ({\bf Restart}) \e$B$7$^$9\e(B.\\
+V       & Gnus \e$B%P!<%8%g%s\e(B ({\bf version}) \e$BHV9f$rI=<($7$^$9\e(B.\\
+W f     & \e$BA4$F$N%0%k!<%W$N%9%3%"%-%c%C%7%e$r=q$-9~$_$^$9\e(B ({\bf Flush}).\\
+Z       & \e$B%I%j%V%k%P%C%U%!$r>C5n$7$^$9\e(B.\\
+C-c C-s & `gnus-group-sort-function'. \e$B$K=>$C$FJB$S49$(\e(B({\bf Sort}) \e$B$^$9\e(B.\\
+C-c C-x & \e$B$3$N%0%k!<%W$NA4$F$N;~8B>C5n2DG=5-;v$r;~8B>C5n\e(B ({\bf
+expiry}) \e$B$N2aDx$K$+$1$^$9\e(B.\\
+C-c M-C-x & \e$B$3$N%0%k!<%W$NA4$F$N5-;v$r;~8B>C5n\e(B ({\bf expiry}) \e$B$N2aDx$K\e(B
+\e$B$+$1$^$9\e(B.\\
+C-c M-g & \e$B40A4$KA4$F$N%0%k!<%W$r3hF02=$7$^$9\e(B.\\
+C-x C-t & 2\e$B$D$N%0%k!<%W$N0LCV$rJQ99$7$^$9\e(B ({\bf transpose}).\\
+M-\&    & \e$B<B9T0u$NIU$$$?A4$F$N%0%k!<%W$KL?Na$r<B9T$7$^$9\e(B.\\
+M-c     & \e$B$3$N%0%k!<%W$N%G!<%?$r>C5n\e(B ({\bf clear}) \e$B$7$^$9\e(B (\e$B4{FI$dB>$N\e(B
+          \e$B0u\e(B). [p/p] \e$B%5!<%P!<$rJQ99$7$F\e(B, \e$B5-;vHV9f$,9gCW$7$J$$$H$-$O\e(B
+          M-x gnus-group-clear-data-on-native-groups \e$B$r;H$C$F$/$@$5$$\e(B.
+          \e$B$b$7$/$O\e(B, \e$B5-;v$K:FHV9fIU$1$r$9$k$?$a$K\e(B M-x gnus-chage-server
+          \e$B$r;H$C$F$/$@$5$$\e(B. \e$B$G$b\e(B, \e$B$3$l$OCY$$$G$9\e(B.\\
+\end{keys}
+\begin{keys}{C-c M-C-x}
+\newlength{\keywidth}\settowidth{\keywidth}{C-c M-C-x}%
+\makebox[\keywidth][l]%
+{M-d}   & {\em \e$BA4$F\e(B\/} \e$B$N%0%k!<%W$N@bL@\e(B ({\bf describe}) \e$B$r$7$^$9\e(B. [\e$B@\F,0z?t\e(B:
+\e$B%5!<%P!<$+$i@bL@$r:FFI$_9~$_$7$^$9\e(B]\\
+M-f     & \e$B$3$N%0%k!<%W$N\e(B {\bf FAQ} \e$B$r\e(B (ange-ftp \e$B$r;H$C$F\e(B) \e$B<hF@$7$^$9\e(B.\\
+M-g     & \e$B$3$N%0%k!<%W$K?7$7$$5-;v$,$"$k$+$I$&$+\e(B, \e$B%5!<%P!<$rD4$Y$^$9\e(B.
+({\bf get}). [p/p]\\
+M-n     & \e$BA0\e(B ({\bf previous}) \e$B$NF1$8$+Dc$$%l%Y%k$NL$FI%0%k!<%W$X0\F0$7\e(B
+\e$B$^$9\e(B. [\e$B5wN%\e(B]\\
+M-p     & \e$B<!\e(B ({\bf next}) \e$B$NF1$8$+Dc$$%l%Y%k$NL$FI%0%k!<%W$X0\F0$7$^$9\e(B.
+[\e$B5wN%\e(B]\\
+\end{keys}}
+
+\def\ListGroups{\subsec{(A) \e$B%0%k!<%W$N0lMwI=<(\e(B}{\samepage
+{\samepage
+\begin{keys}{A m}
+A a     & (C-c C-a) \e$B@55,I=8=$K9g$&A4$F$N%0%k!<%W$r0lMwI=<($7$^$9\e(B ({\bf
+apropos}).\\
+A d     & \e$BL>A0$+@bL@\e(B ({\bf descriptions}) \e$B$,@55,I=8=$K9g$&A4$F$N%0%k!<\e(B
+\e$B%W$r0lMwI=<($7$^$9\e(B.\\
+A k     & \e$BA4$F$N:o=|$5$l$?\e(B ({\bf killed}) \e$B%0%k!<%W$r0lMwI=<($7$^$9\e(B.
+[\e$B@\F,<-\e(B: [\e$BHs\e(B]\e$B9XFI$r=|$/A4$F$N%0%k!<%W\e(B]\\
+A l     & \e$B;XDj$5$l$?%l%Y%k\e(B {\bf level} \e$B$NL$FI%0%k!<%W$r0lMwI=<($7$^$9\e(B.
+[\e$B@\F,<-\e(B: \e$B4{FI%0%k!<%W$b\e(B]\\
+A m     & \e$B@55,I=8=$K9g$$\e(B ({\bf match}), \e$BL$FI5-;v$r;}$D%0%k!<%W$r0lMwI=\e(B
+\e$B<($7$^$9\e(B. [\e$B%l%Y%k\e(B]\\
+A s     & (l) \e$BL$FI5-;v$N$"$k9VFI%0%k!<%W\e(B {\bf subscribed} \e$B$r0lMwI=<($7\e(B
+\e$B$^$9\e(B. [\e$B%l%Y%k\e(B]\\
+A u     & (L) \e$BA4$F$N%0%k!<%W\e(B (\e$BHs9VFI\e(B ({\bf unsubscribed}) \e$B$r4^$`\e(B) \e$B$r0l\e(B
+\e$BMwI=<($7$^$9\e(B. [\e$B%l%Y%k\e(B, \e$B=i4|CM$O\e(B7]\\
+A z     & \e$B%>%s%S\e(B ({\bf zombie}) \e$B%0%k!<%W$r0lMwI=<($7$^$9\e(B.\\
+A A     & \e$BA4$F$N%5!<%P!<$NA4$F$N2DG=$J3hF0\e(B ({\bf active}) \e$B%0%k!<%W$r0l\e(B
+\e$BMwI=<($7$^$9\e(B (\e$BCY$$$+$b$7$l$^$;$s\e(B).\\
+A M     & \e$B@55,I=8=$K9g$&\e(B ({\bf match}) \e$BA4$F$N%0%k!<%W$r0lMwI=<($7$^$9\e(B.\\
+A T     & \e$B%H%T%C%/\e(B ({\bf topic}) \e$B$GJT;<$5$l$F$$$kA4$F$N3hF0%0%k!<%W$r\e(B
+\e$B0lMwI=<($7$^$9\e(B.\\
+\end{keys}}}}
+
+\def\CreateGroups{\subsec{(G) \e$B30It%0%k!<%W$N:n@.\e(B/\e$BJT=8\e(B}{\samepage
+\e$BA*BrJ}K!$O3g8L$NCf$K<($5$l$F$$$^$9\e(B.\\*
+\begin{keys}{G DEL}
+G DEL   & \e$B$3$N%0%k!<%W$r>C5n\e(B ({\bf Delete}) \e$B$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B5-;v$b\e(B
+          {\bf \e$BA4$F\e(B} \e$B>C5n$7$^$9\e(B]\\
+G a     & Gnus \e$B%j%9%H\e(B {\bf archive} \e$B%0%k!<%W$r:n$j$^$9\e(B. (ange-ftp \e$B$rDL\e(B
+          \e$B$8$F$N\e(B nndir)\\
+G c     & \e$B$3$N%0%k!<%W$N%Q%i%a!<%?$r\e(B {\bf customize} \e$B$7$^$9\e(B.\\
+G d     & \e$B%G%#%l%/%H%j!<\e(B ({\bf directory}) \e$B%0%k!<%W\e(B \e$B$r:n$j$^$9\e(B (\e$BA4$F$N\e(B
+          \e$B%U%!%$%k$O?t;z$NL>A0$NEj9F$G$9\e(B). (nndir)\\
+G e     & \e$B$3$N%0%k!<%W$NA*BrJ}K!$rJT=8\e(B ({\bf edit}) \e$B$7$^$9\e(B.\\
+G f     & \e$B%U%!%$%k\e(B ({\bf file}) \e$B$K4p$E$$$?%0%k!<%W$r:n$j$^$9\e(B.
+          (nndoc: mbox, babyl, digest, mmdf, news, rnews,
+          clari-briefs, rfc934,rfc822, forward) [\e$B@\F,<-\e(B: \e$B$I$N7A<0$+$r\e(B
+          \e$B?dB,$7$^$;$s\e(B]\\
+G h     & Gnus \e$B$N%X%k%W\e(B ({\bf help}) (\e$B@bL@\e(B/\e$B%A%e!<%H%j%"%k\e(B) \e$B%0%k!<%W$r\e(B
+          \e$B:n@.$7$^$9\e(B. (nndoc)\\
+G k     & {\bf kiboze} \e$B%0%k!<%W$r:n@.$7$^$9\e(B. (\e$BL>A0\e(B, \e$B%0%k!<%W\e(B, \e$B@55,I=8=\e(B
+          \e$B$r;XDj$7$^$9\e(B). (nnkiboze)\\
+G m     & \e$B?7$7$$%0%k!<%W$r:n@.\e(B ({\bf make}) \e$B$7$^$9\e(B (\e$BL>A0\e(B, \e$BJ}K!\e(B, \e$B%"%I%l\e(B
+          \e$B%9$r;XDj$7$^$9\e(B).\\
+G p     & \e$B$3$N%0%k!<%W\e(B/\e$B%H%T%C%/$N%Q%i%a!<%?\e(B ({\bf parameters}) \e$B$rJT=8\e(B
+          \e$B$7$^$9\e(B.\\
+G r     & \e$B$3$N%0%k!<%W$r2~L>\e(B ({\bf rename}) \e$B$7$^$9\e(B (\e$B%a!<%k%0%k!<%W$N$_\e(B).\\
+G v     & \e$B$3$N%0%k!<%W$r2>A[\e(B ({\bf virtual}) \e$B%0%k!<%W$KDI2C$7$^$9\e(B. [p/p]\\
+G w     & {\bf web} \e$B$K4p$$$?%0%k!<%W$r:n@.$7$^$9\e(B. (nnweb: dejanews,
+          altavista, reference) [\e$B@\F,<-\e(B: \e$B%0%k!<%W$r1JB3$K\e(B]\\
+G D     & \e$B%G%#%l%/%H%j!<\e(B ({\bf directory}) \e$B$K\e(B (\e$B0l;~\e(B) \e$B%0%k!<%W$H$7$FF~\e(B
+\e$B$j$^$9\e(B. (\e$B4{FI0u$r5-O?$7$J$$\e(B nneething.)\\
+G E     & \e$B$3$N%0%k!<%W$N>pJs\e(B (\e$BA*BrJ}K!\e(B, \e$B5-;v$N4{FI\e(B, \e$B$J$I$J$I\e(B) \e$B$rJT=8\e(B
+({\bf edit}) \e$B$7$^$9\e(B.\\
+G V     & \e$B6u$N2>A[\e(B ({\bf virtual}) \e$B%0%k!<%W$r:n@.$7$^$9\e(B.
+(nnvirtual)\\
+\end{keys}
+\e$B%a!<%k%0%k!<%W$r:n@.$7$F%a!<%k$r\e(B nnmbox, nnbabyl, nnml, nnmh, nnfolder
+\e$B$N\e(B1\e$B$D$NJ}K!$r;H$C$F\e(BGnus \e$B$GFI$`$3$H$b$G$-$^$9\e(B (\e$B%a!<%j%0%j%9%H$r9VFI$7$F\e(B
+\e$B$$$k$HHs>o$KLr$KN)$A$^$9\e(B). \e$B%*%s%i%$%s\e(B info \e$B$GFI$s$G$/$@$5$$\e(B (C-c C-i g
+Reading Mail RET).
+}}
+
+\def\SortGroups{\subsubsec{(G S) \e$B%0%k!<%W$NJB$S49$(\e(B}{\samepage
+\e$BJ#?t$N4p=`$GJB$S49$($r$9$k$?$a$K$O\e(B, \e$B$^$:$"$^$j=EMW$G$J$$$b$N$rE,MQ$7\e(B,
+\e$B:G8e$K0lHV=EMW$J$b$N$rE,MQ$7$^$9\e(B.\\*
+\begin{keys}{G P \bf x}
+G S a     & \e$B%0%k!<%WL>$r%"%k%U%!%C%Y%H=g\e(B ({\bf Alphabetically}) \e$B$KJB$S\e(B
+\e$B49$($^$9\e(B. [\e$B@\F,<-\e(B: \e$B5U$N=gHV\e(B]\\
+G S l     & \e$B%l%Y%k$G\e(B ({\bf level}) \e$BJB$S49$($^$9\e(B. [\e$B@\F,<-\e(B: \e$B5U$N=gHV\e(B]\\
+G S m     & \e$BJ}K!\e(B ({\bf method}) \e$BL>$GJB$S49$($^$9\e(B. [\e$B@\F,<-\e(B: \e$B5U$N=gHV\e(B]\\
+G S r     & \e$B3,5i\e(B (\e$B%l%Y%k$H%9%3%"\e(B) \e$B$GJB$S49$($^$9\e(B. [\e$B@\F,<-\e(B: \e$B5U$N=gHV\e(B]\\
+G S u     & \e$BL$FI\e(B ({\bf unread}) \e$B5-;v$N?t$GJB$S49$($^$9\e(B. [\e$B@\F,<-\e(B: \e$B5U$N\e(B
+\e$B=gHV\e(B]\\
+G S v     & \e$B%0%k!<%W%9%3%"\e(B (\e$BCM\e(B ({\bf value})) \e$B$GJB$S49$($^$9\e(B. [\e$B@\F,<-\e(B:
+\e$B5U$N=gHV\e(B]\\
+\end{keys}
+\e$B$3$3$G\e(B, {\bf x} \e$B$O\e(B a,l,m,r,u,v \e$B$N$I$l$+$G$9\e(B:\\*
+\begin{keys}{G P \bf x}
+G P \bf x & [p/p] \e$B$GA*Br$5$l$?%0%k!<%W$N$_$rJB$S49$($^$9\e(B.\\
+T S \bf x & \e$B8=:_$N%H%T%C%/$N$_$GJB$S49$($^$9\e(B.\\
+\end{keys}
+}}
+
+\def\SOUP{\subsubsec{(G s) SOUP \e$B%3%^%s%I\e(B}{\samepage
+SOUP \e$B$OB?$/$N5-;v\e(B/\e$BJVEz$r%Q%1%C%H$KF~$l$F\e(B, \e$B0lEY$KE>Aw$7\e(B, \e$B$=$l$i$r%*%U%i\e(B
+\e$B%$%s$GFI$_9~$_\e(B/\e$B:n@.$9$k%W%m%H%3%k$G$9\e(B. \e$B%Q%1%C%H$NA`:n$K$O0J2<$NL?Na$r\e(B
+\e$B;H$$\e(B, \e$BFI$`$?$a$K$O\e(B nnsoup \e$BJ}K!$r;HMQ$7$F$/$@$5$$\e(B.\\*
+\begin{keys}{G s w}
+G s b   & \e$BA4$F$N5-;v$r:-Jq$7$^$9\e(B (soup \e$B$r:n$j$^$9\e(B ({\bf
+brew})). [p/p]\\
+G s p   & \e$BA4$F$N\e(B SOUP \e$B%G!<%?$r\e(B SOUP \e$B%Q%1%C%H$K:-Jq\e(B ({\bf pack}) \e$B$7$^$9\e(B.\\
+G s r   & \e$BA4$F$NJVEz\e(B ({\bf replies}) \e$B$rJVEz%Q%1%C%H$K:-Jq$7$^$9\e(B.\\
+G s s   & \e$BJVEz%Q%1%C%H$KF~$l$?A4$F$NJVEz$rAw?.\e(B ({\bf send}) \e$B$7$^$9\e(B.\\
+G s w   & \e$BA4$F$N\e(B SOUP \e$B%G!<%?%U%!%$%k$r=q$-$^$9\e(B ({\bf Write}).\\
+\end{keys}}}
+
+\def\MarkGroups{\subsec{(M) \e$B%0%k!<%W$N0uIU$1\e(B}{\samepage
+\begin{keys}{M m}
+M b     & \e$B%P%C%U%!\e(B ({\bf buffer}) \e$B$NA4$F$N%0%k!<%W$K%W%m%;%90u$rIU$1$^\e(B
+\e$B$9\e(B.\\
+M r     & \e$B@55,I=8=\e(B ({\bf regexp}) \e$B$K9gCW$9$kA4$F$N%0%k!<%W$K0u$rIU$1$^\e(B
+\e$B$9\e(B.\\
+M m     & (\#) \e$B$3$N%0%k!<%W$K0u\e(B {\bf mark} \e$B$rIU$1$^$9\e(B. [\e$BHO0O\e(B]\\
+M u     & (M-\#) \e$B$3$N%0%k!<%W$+$i0u$r<h$j=|$-$^$9\e(B ({\bf unmark}). [\e$BHO0O\e(B]\\
+M w     & \e$B8=:_$N%j!<%8%g%s$NA4$F$N%0%k!<%W$K0u$rIU$1$^$9\e(B.\\
+M U     & \e$B%P%C%U%!$NA4$F$N%0%k!<%W$N0u$r<h$j=|$-$^$9\e(B ({\bf Unmark}).\\
+\end{keys}}}
+
+\def\Unsubscribe{\subsec{(S) (\e$BHs\e(B)\e$B9VFI\e(B, \e$B%0%k!<%W$r@Z$jE=$j$9$k\e(B}{\samepage
+\begin{keys}{S C-k}
+S C-k   & \e$BFCDj$N%l%Y%k$NA4$F$N%0%k!<%W$r@Z$j$^$9\e(B ({\kill}).\\
+S k     & (C-k) \e$B$3$N%0%k!<%W\e(B/\e$B%H%T%C%/\e(B (\e$B$H$=$l$NA4$F$N%0%k!<%W\e(B)\e$B$r@Z$j$^\e(B
+\e$B$9\e(B ({\bf kill}).\\
+S l     & \e$B$3$N%0%k!<%W$N%l%Y%k\e(B ({\bf level}) \e$B$r@_Dj$7$^$9\e(B. [p/p]\\
+S s     & (U) \e$B%0%k!<%W$NF~NO$rB%?J$7$F$=$N9VFI\e(B ({\bf subscription}) \e$B$r\e(B
+\e$B@Z$jBX$($^$9\e(B.\\
+S t     & (u) \e$B$3$N%0%k!<%W$N9VFI$r@Z$jBX$(\e(B ({\bf toggle}) \e$B$^$9\e(B.
+[p/p]\\
+S w     & (C-w) \e$B%j!<%8%g%s$NA4$F$N%0%k!<%W$r@Z$j$^$9\e(B.\\
+S y     & (C-y) \e$B:G8e$K\e(B kill \e$B$5$l$?%0%k!<%W\e(B/\e$B%H%T%C%/$rE=$j$^$9\e(B ({\bf yank}) .\\
+S z     & \e$BA4$F$N%>%s%S\e(B ({\bf zombie}) \e$B%0%k!<%W$r@Z$j$^$9\e(B.\\
+\end{keys}}}
+
+\def\GroupTopics{\subsec{(T) \e$B%0%k!<%W%H%T%C%/\e(B}{\samepage
+\e$B%H%T%C%/$OFI$s$@$j4IM}$7$?$j$9$k$N$r4JC1$K$9$k$?$a$N%0%k!<%W$N3,AXE*$J\e(B
+\e$BAH9g$;$G$9\e(B.
+\begin{keys}{T TAB}
+T TAB   & \e$B$3$N%H%T%C%/$r0JA0$N$b$N$NI{%H%T%C%/$K$J$k$h$&$K;z2<$2$r$7$^\e(B
+          \e$B$9\e(B. [\e$B@\F,<-\e(B: \e$B;z2<$2$rLa$7$$$^$9\e(B]\\
+T DEL   & \e$B6u$N%H%T%C%/$r>C5n\e(B ({\bf delete}) \e$B$7$^$9\e(B.\\
+T \#    & \e$B$3$N%H%T%C%/$NA4$F$N%0%k!<%W$K<B9T0u$rIU$1$^$9\e(B.\\
+T M-\#  & \e$B$3$N%H%T%C%/$N<B9T0u$NIU$$$F$$$kA4$F$N%0%k!<%W$+$i0u$r<h$j=|\e(B
+          \e$B$-$^$9\e(B.\\
+T c     & \e$B$3$N%0%k!<%W$rB>$N%H%T%C%/$KJ#@=\e(B ({\bf copy}) \e$B$7$^$9\e(B.
+          [p/p]\\
+T h     & \e$B6u$N%H%T%C%/$r1#$9\e(B ({\bf hiding}) \e$B$+$r@Z$j49$($^$9\e(B.\\
+T m     & \e$B$3$N%0%k!<%W$rB>$N%H%T%C%/$K0\F0\e(B ({\bf move}) \e$B$7$^$9\e(B.
+          [p/p]\\
+T n     & \e$B?7$7$$\e(B ({\bf new}) \e$B%H%T%C%/$r:n@.$7$^$9\e(B.\\
+T r     & \e$B%H%T%C%/$r2~L>\e(B ({\bf rename}) \e$B$7$^$9\e(B.\\
+T C     & \e$B@55,I=8=$K9gCW$9$kA4$F$N%0%k!<%W$r%H%T%C%/$KJ#@=\e(B ({\bf
+          copy}) \e$B$7$^$9\e(B.\\
+T D     & \e$B$3$N%H%T%C%/$r$3$N%0%k!<%W$+$i>C5n\e(B ({\bf delete}) \e$B$7$^$9\e(B. [p/p]\\
+T M     & \e$B@55,I=8=$K9gCW$9$kA4$F$N%0%k!<%W$r%H%T%C%/$K0\F0\e(B ({\bf
+          move}) \e$B$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\SummaryMode{\sec{\e$B35N,%b!<%I\e(B}{\samepage
+\begin{keys}{M-C-d}
+SPC     & \e$B5-;v$NA*Br\e(B, 1\e$B%Z!<%8%9%/%m!<%k\e(B, \e$B<!$N5-;v$X$N0\F0\e(B,
+\e$B$G$9\e(B.\\
+% (A SPC, A n)
+DEL     & (b) \e$B$3$N5-;v$r\e(B1\e$B%Z!<%8%9%/%m!<%k$7$FLa$7$^$9\e(B. [\e$B5w\e(B
+\e$BN%\e(B]\\ %(A DEL, A p)
+RET     & \e$B$3$N5-;v$r0l9T@h$K%9%/%m!<%k$7$^$9\e(B. [\e$B5wN%\e(B]\\
+=       & \e$B35N,$N%&%#%s%I%&$r3HD%$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B5-;v%&%#%s%I%&$rI=<(\e(B
+\e$B$9$k$h$&$K=L$a$^$9\e(B]\\
+$<$     & (A $<$) \e$B$3$N5-;v$N:G=i$K%9%/%m!<%k$7$^$9\e(B.\\ %(A b)
+$>$     & (A $>$) \e$B$3$N5-;v$N:G8e$K%9%/%m!<%k$7$^$9\e(B.\\ %(A e)
+\&      & \e$B@55,I=8=$K9g$&A4$F$N5-;v$KL?Na$r<B9T$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B8e$m$K\e(B
+\e$B0\F0$7$^$9\e(B.]\\
+k       & \e$B$3$N%9%l%C%I$K\e(B GroupLens \e$B$N3,5i\e(B (rating) (1-5) \e$B$rM?$($^$9\e(B.\\
+r       & \e$B$3$N5-;v$K\e(B GroupLens \e$B$N3,5i\e(B (rating) (1-5) \e$B$rM?$($^$9\e(B.\\
+Y g     & \e$B35N,%P%C%U%!$r:F:n@.\e(B (re{\bf generate}) \e$B$7$^$9\e(B.\\
+Y c     & \e$BA4$F$N%-%c%C%7%e$7$F$$$k\e(B ({\bf cached}) \e$B5-;v$r$r$r35N,$KF~$l\e(B
+\e$B$^$9\e(B.\\
+C-t     & \e$B35N,9T$N@Z$j<h$j\e(B ({\bf truncation}) \e$B$r@Z$j49$($^$9\e(B.\\
+C-d     & \e$B$3$l$rJL$N%0%k!<%W$K%@%$%8%'%9%H$NE83+\e(B (un-{\bf digestify})
+\e$B$7$^$9\e(B.\\
+M-C-d   & \e$BA4$F$NA*Br$7$F$$$k5-;v$r0l$D$N%0%k!<%W$K%@%$%8%'%9%H$rE83+$7\e(B
+\e$B$^$9\e(B (un-{\bf digestify}).\\
+M-k     & \e$B$3$N%0%k!<%W$N\e(B {\bf kill} \e$B%U%!%$%k$rJT=8$7$^$9\e(B.\\
+M-r     & \e$B@55,I=8=$GA0$N5-;v$r8!:w$7$^$9\e(B.\\
+M-s     & \e$B@55,I=8=$GB3$/5-;v$r8!:w\e(B ({\bf search}) \e$B$7$^$9\e(B.\\
+M-K     & \e$BAm9g\e(B {\bf kill} \e$B%U%!%$%k$rJT=8$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\SortSummary{\subsec{(C-c C-s) \e$B35N,%P%C%U%!$NJB$S49$(\e(B}{\samepage
+\e$B%9%l%C%I%b!<%I$G$O\e(B, \e$B$3$l$i$NL?Na$O%9%l%C%I$N:,$@$1$rJB$S49$($^$9\e(B.\\*
+\begin{keys}{C-c C-s C-a}
+C-c C-s C-a & \e$BCx<T\e(B ({\bf author}) \e$B$G35N,$rJB$S49$($^$9\e(B.\\
+C-c C-s C-d & \e$BF|IU$1\e(B ({\bf date}) \e$B$G35N,$rJB$S49$($^$9\e(B.\\
+C-c C-s C-i & \e$B5-;v$N%9%3%"$G35N,$rJB$S49$($^$9\e(B.\\
+C-c C-s C-l & \e$B9T?t\e(B ({\bf line}) \e$B$GJB$S49$($^$9\e(B.\\
+C-c C-s C-n & \e$B5-;v$NHV9f\e(B ({\bf number}) \e$B$G35N,$rJB$S49$($^$9\e(B.\\
+C-c C-s C-s & \e$BI=Bj\e(B ({\bf subject}) \e$B$G35N,$rJB$S49$($^$9\e(B.\\
+\end{keys}}}
+
+\def\Article{\subsec{(A) \e$B5-;vL?Na\e(B}{\samepage
+\begin{keys}{A m}
+A g     & (g) \e$B$3$N5-;v$r\e(B(\e$B:F\e(B)\e$B<hF@$7$^$9\e(B ({\bf get}). [\e$B@\F,<-\e(B: \e$B2?$b<B9T\e(B
+\e$B$7$^$;$s\e(B.]\\
+A r     & (^) \e$B$3$N5-;v$N?F$K0\F0$7$^$9\e(B ({\bf References} \e$B%X%C%@!<\e(B
+\e$B$G$9\e(B.) [\e$B@\F,<-\e(B: \e$B$I$N$/$i$$@h$KLa$k$+\e(B; \e$BIi\e(B: $n$ \e$BHVL\$NAD@h$@$1\e(B].\\  %(A ^)
+M-^     & \e$BM?$($i$l$?\e(B Message-ID \e$B$N5-;v$K0\F0$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$BJ}K!$b;X\e(B
+\e$BDj$7$^$9\e(B.]\\
+A s     & (s) \e$B5-;v%P%C%U%!$G\e(B i{\bf search} \e$B$r<B9T$7$^$9\e(B.\\
+A P     & \e$B5-;v$r%]%9%H%9%/%j%W%H$H$7$F0u:~\e(B ({\bf print}) \e$B$7$^$9\e(B.\\
+A R     & \e$B$3$N5-;v$NA4$F$NAD@h\e(B ({\bf References}) \e$B$r<hF@$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\MailGroup{\subsec{(B) \e$B%a!<%k%0%k!<%WL?Na\e(B}{\samepage
+\e$B$3$l$i$NL?Na\e(B (`B c' \e$B$r=|$/\e(B) \e$B$O%a!<%k%0%k!<%W$G$N$_M-8z$G$9\e(B.\\*
+\begin{keys}{B M-C-e}
+B DEL   & {\e$B%a!<%k5-;v$r%G%#%9%/$+$i>C5n\e(B (\bf delete}) \e$B$7$^$9\e(B. [p/p]\\
+B c     & \e$B$3$N5-;v$r$I$3$+$N%0%k!<%W$+$i%a!<%k%0%k!<%W$KJ#@=\e(B ({\bf
+copy}) \e$B$7$^$9\e(B. [p/p]\\
+B e     & \e$B$3$N%0%k!<%W$NA4$F$N;~8B>C5n2DG=5-;v$r;~8B>C5n\e(B ({\bf
+expire}) \e$B$7$^$9\e(B. [p/p]\\
+B i     & \e$BG$0U$N%U%!%$%k$r$3$N%a!<%k%0%k!<%W$N<h$j9~$_\e(B ({\bf import}) \e$B$^\e(B
+\e$B$9\e(B (From \e$B$H\e(B Subject \e$B$rM?$($^$9\e(B).\\
+B m     & \e$B$"$k%a!<%k%0%k!<%W$+$iJL$N%0%k!<%W$X5-;v$r0\F0\e(B ({\bf move})
+\e$B$7$^$9\e(B. [p/p]\\
+B p     & \e$B$I$3$K%a%C%;!<%8$N9%0U$NJ#@=$bEj9F$5$l$?\e(B ({\bf posted}) \e$B$+$I\e(B
+\e$B$&$+$rD4$Y$^$9\e(B.\\
+B q     & \e$B:F%9%W!<%k$5$l$?$H$-$K\e(B, \e$B5-;v$,$I$3$K9T$/$+$r?R$M$^$9\e(B ({\bf
+query}).\\
+B r     & \e$B$3$N%a!<%k5-;v$r:F%9%W!<%k\e(B ({\bf respool}) \e$B$7$^$9\e(B. [p/p]\\
+B w     & (e) \e$B$3$N%a!<%k5-;v$rJT=8$7$^$9\e(B.\\
+B M-C-e & \e$B$3$N%0%k!<%W$NA4$F$N;~8B>C5n2DG=5-;v$r:o=|\e(B ({\bf expunge})
+(\e$B%G%#%9%/$+$i>C$7$^$9\e(B). [p/p]\\
+B C     & \e$B$3$N5-;v$rJL$N%0%k!<%W$KAj8_Ej9F\e(B ({\bf crosspost}) \e$B$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\GotoArticle{\subsec{(G) \e$B5-;v$X$N0\F0\e(B}{\samepage
+\e$B$3$l$i$NL?Na$OBP>]5-;v$rA*Br$7$^$9\e(B. \e$B@\F,0z?t$OM}2r$7$^$;$s\e(B. \\*
+\begin{keys}{G C-n}
+G b     & (,) \e$B:G9b\e(B ({\bf best}) \e$B$N5-;v$K0\F0$7$^$9\e(B (\e$B:G9b%9%3%"$N$b$N$G\e(B
+\e$B$9\e(B). [GL rating]\\
+G f     & (.) \e$B:G=i\e(B ({\bf first}) \e$B$NL$FI5-;v$K0\F0$7$^$9\e(B.\\
+G g     & \e$B5-;vHV9f$r?V$$$F$+$i$=$N35N,9T$X0\F0\e(B ({\bf go to}) \e$B$7$^$9\e(B.\\
+G j     & (j) \e$B5-;vHV9f$r?V$$$F$+$i$=$N5-;v$XHt$S$^$9\e(B ({\bf jump}).\\
+G l     & (l) \e$B:G8e\e(B ({\bf last}) \e$B$N4{FI5-;v$K0\F0$7$^$9\e(B.\\
+G o     & \e$B35N,$NMzNr$+$i5-;v$r<h$j=P$7\e(B, \e$B$=$l$K0\F0$7$^$9\e(B.\\
+G n     & (n) \e$B<!\e(B ({\bf next}) \e$B$NL$FI5-;v$K0\F0$7$^$9\e(B.\\
+G p     & (p) \e$BA0\e(B ({\bf previous}) \e$B$NL$FI5-;v$K0\F0$7$^$9\e(B.\\
+G N     & (N) \e$B<!\e(B ({\bf next}) \e$B$N5-;v$K0\F0$7$^$9\e(B\\
+G P     & (P) \e$BA0\e(B ({\bf previous}) \e$B$N5-;v$K0\F0$7$^$9\e(B.\\
+G C-n   & (M-C-n) \e$BF1$8I=Bj$N<!\e(B ({\bf next}) \e$B$N5-;v$K0\F0$7$^$9\e(B.\\
+G C-p   & (M-C-p) \e$BF1$8I=Bj$NA0\e(B ({\bf previous}) \e$B$N5-;v$K0\F0$7$^$9\e(B.\\
+G M-n   & (M-n) \e$B35N,9T$G<!\e(B ({\bf next}) \e$B$NL$FI5-;v$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+G M-p   & (M-p) \e$B35N,9T$GA0\e(B ({\bf previous}) \e$B$NL$FI5-;v$K0\F0$7$^$9\e(B.
+[\e$B5wN%\e(B]\\
+\end{keys}}}
+
+\def\MarkArticles{\subsec{(M) \e$B5-;v$K0u$rIU$1$k\e(B}{\samepage
+\begin{keys}{M M-C-r}
+d       & (M d, M r) \e$B$3$N5-;v$K4{FI\e(B ({\bf read}) (\e$B$=$l$N>C5n\e(B ({\bf
+delete})) \e$B$N0u$rIU$1$F\e(B, \e$B<!$N$b$N$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\
+D       & \e$B$3$N5-;v$K4{FI$N0u$rIU$1$F\e(B, \e$BA0$N$b$N$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\
+u       & (!, M t) \e$B$3$N5-;v$K2D;k0u\e(B ({\bf Tick}) (\e$B6=L#?<$$$H$7$F0u$rIU\e(B
+\e$B$1\e(B) \e$B<!$N$b$N$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\ %(M !)
+U       & \e$B$3$N5-;v$K2D;k0u$rIU$1\e(B, \e$BA0$N$b$N$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\
+M-u     & (M SPC, M c) \e$B$3$N5-;v$NA4$F$N0u$r>C5n$7\e(B ({\bf Clear}), \e$B<!$N\e(B
+\e$B5-;v$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\
+M-U     & \e$B$3$N5-;v$NA4$F$N0u$r>C5n$7\e(B, \e$BA0$N5-;v$K0\F0$7$^$9\e(B. [\e$BHO0O\e(B]\\
+M ?     & (?) \e$B$3$N5-;v$KJ]N1$N0u$rIU$1$^$9\e(B (\e$B%U%)%m!<%"%C%W$K$@$16=L#$,\e(B
+\e$B$"$k\e(B). [\e$BHO0O\e(B]\\
+*       & \e$B%-%c%C%7%e$K5-;v$rF~$l$^$9\e(B (\e$B1JB3$K$7$^$9\e(B). [p/p]\\
+M-*     & \e$B$3$N5-;v$r%-%c%C%7%e$+$i<h$j=|$-$^$9\e(B (\e$B1JB3$GL5$/$7$^$9\e(B).
+[p/p]\\
+M b     & \e$B$3$N5-;v$K$7$*$j\e(B ({\bf bookmark}) \e$B$r@_Dj$7$^$9\e(B.\\
+M e     & (E) \e$B$3$N5-;v$r;~8B>C5n2DG=\e(B ({\bf expirable}) \e$B$H$7$F0u$rIU$1\e(B
+\e$B$^$9\e(B. [\e$BHO0O\e(B]\\ %(M x)
+M k     & (k) \e$BF1$8I=Bj$NA4$F$N5-;v$r@Z$j\e(B ({\bf kill}), \e$B<!$N5-;v$rA*Br\e(B
+\e$B$7$^$9\e(B.\\
+M B     & \e$B$3$N5-;v$+$i$7$*$j\e(B ({\bf bookmark}) \e$B$r<h$j=|$-$^$9\e(B.\\
+M C     & \e$B2D;k0u$G$J$$5-;v$r%-%c%C%A%"%C%W\e(B ({\bf catch-up}) (\e$B4{FI$N0u\e(B
+\e$B$rIU$1$k\e(B) \e$B$7$^$9\e(B.\\
+M D     & \e$BA4$F$NJ]N1\e(B ({\bf dormant}) \e$B5-;v$rI=<($7$^$9\e(B (\e$BIaDL$O%U%)%m!<\e(B
+\e$B%"%C%W$,$J$$8B$j1#$5$l$F$$$^$9\e(B).\\
+M H     & \e$B$3$N%0%k!<%W$G$3$3\e(B ({\bf here}) \e$B$^$G%-%c%C%A%"%C%W\e(B (\e$B4{FI$N0u\e(B
+\e$B$rIU$1$k\e(B) \e$B$7$^$9\e(B.\\
+M K     & (C-k) \e$B$3$N5-;v$HF1$8I=Bj$NA4$F$N5-;v$r\e(B {\bf kill} \e$B$7$^$9\e(B.\\
+C-w     & \e$B%]%$%s%H$H%^!<%/$N4V$NA4$F$N5-;v$K4{FI$N0u$rIU$1$^$9\e(B.\\
+M S     & (C-c M-C-s) \e$BA4$F$N:o=|5-;v$rI=<(\e(B ({\bf show}) \e$B$7$^$9\e(B.\\
+M C-c   & \e$B$3$N%0%k!<%W$NA4$F$N5-;v$r%-%c%C%A%"%C%W\e(B ({\bf catch-up}) \e$B$7\e(B
+\e$B$^$9\e(B.\\
+M M-r   & (x) \e$B$3$N%0%k!<%W$NA4$F$N4{FI\e(B ({\bf read}) \e$B5-;v$r>C5n$7$^$9\e(B.\\
+M M-D   & \e$BA4$F$NJ]N1\e(B ({\bf dormant}) \e$B5-;v$r1#$7$^$9\e(B.\\
+M M-C-r & \e$BM?$($i$l$?0u$NA4$F$N5-;v$r>C5n$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\MarkScore{\subsubsec{(M V) \e$B%9%3%"\e(B (\e$BCM\e(B) \e$B$K4p$E$$$?0u\e(B}{\samepage
+\begin{keys}{M s m}
+M V c   & \e$BA4$F$N9b%9%3%"$N5-;v$+$iA4$F$N0u$r>C5n\e(B ({\bf clear}) \e$B$7$^$9\e(B.
+[score]\\
+M V k   & \e$BA4$F$NDc%9%3%"$N5-;v$r@Z$j$^$9\e(B ({\bf kill}). [score]\\
+M V m   & \e$BA4$F$N9b%9%3%"$N5-;v$KM?$($i$($l$?0u\e(B ({\bf mark}) \e$B$rIU$1$^$9\e(B.
+[score]\\
+M V u   & \e$BA4$F$N9b%9%3%"$N5-;v$r$*$b$7$m$$$H$7$F0u$rIU$1$^$9\e(B (\e$B2D;k0u$r\e(B
+\e$BIU$1$^$9\e(B). [score]\\
+\end{keys}}}
+
+\def\ProcessMark{\subsubsec{(M P) \e$B%W%m%;%90u\e(B}{\samepage
+\e$B$3$l$i$NL?Na$O%W%m%;%90u\e(B \# \e$B$rIU$1$?$j>C5n$7$?$j$7$^$9\e(B. \e$BA`:n$7$?$$5-;v\e(B
+\e$B$,O"B3$7$F$$$J$$$H$-$@$1$=$l$r;H$&I,MW$,$"$k$G$7$g$&\e(B. \e$B$=$&$G$J$1$l$P?t\e(B
+\e$BCM0z?t$r;H$$$^$9\e(B.\\*
+\begin{keys}{M P R}
+M P a   & \e$BA4$F\e(B ({\bf all}) \e$B$N5-;v$K0u$rIU$1$^$9\e(B (\e$B=gHV$K\e(B).\\
+M P b   & \e$B%P%C%U%!\e(B ({\bf buffer}) \e$B$K8=$l$?=g$KA4$F$N5-;v$K0u$rIU$1$^$9\e(B.\\
+M P i   & \e$BA4$F$N<B9T0u$r5U$K$7$^$9\e(B ({\bf invert}).\\
+M P k   & \e$BA4$F$N0u$r%9%?%C%/$K@Q$s$G\e(B, \e$B$=$l$+$i@Z$j$^$9\e(B ({\bf kill}).\\
+M P p   & (\#) \e$B$3$N5-;v$K0u$rIU$1$^$9\e(B.\\ %(M \#)
+M P r   & \e$B6h0h\e(B ({\bf region}) \e$B$NA4$F$N5-;v$K0u$rIU$1$^$9\e(B.\\
+M P s   & \e$B8=:_$NO"B3J*\e(B ({\bf series}) \e$B$NA4$F$K0u$rIU$1$^$9\e(B.\\
+M P t   & \e$B$3$N\e(B (\e$BI{\e(B)\e$B%9%l%C%I\e(B ({\bf thread}) \e$B$NA4$F$N5-;v$K0u$rIU$1$^$9\e(B.\\
+M P u   & (M-\#) \e$B$3$N5-;v$+$i0u$r>C$7$^$9\e(B ({\bf unmark}).\\ %(M M-\#)
+M P v   & \e$BA4$F$N9b$$%9%3%"$N5-;v\e(B (\e$BCM\e(B ({\bf value})) \e$B$K0u$rIU$1$^$9\e(B.
+[score]\\
+M P w   & \e$BA4$F$N0u$r%9%?%C%/$K@Q$_$^$9\e(B.\\
+M P y   & `M P y', `M P w' \e$B$d0u$r>C5n$9$kA`:n$N8e$G%9%?%C%/$+$i0u$rE=\e(B
+\e$B$j\e(B ({\bf yank}), \e$BI|85$7$^$9\e(B.\\
+M P R   & \e$B@55,I=8=\e(B ({\bf regexp}) \e$B$K9g$&A4$F$N5-;v$K0u$rIU$1$^$9\e(B.\\
+M P S   & \e$B0uIU$-$N5-;v$r4^$`A4$F$NO"B3$7$?5-;v\e(B ({\bf series}) \e$B$K0u$rIU\e(B
+\e$B$1$^$9\e(B.\\
+M P T   & \e$B$3$N\e(B (\e$BI{\e(B)\e$B%9%l%C%I\e(B ({\bf thread}) \e$B$K$"$kA4$F$N5-;v$N0u$r<h$j\e(B
+\e$B=|$-$^$9\e(B.\\
+M P U   & \e$BA4$F$N5-;v$+$i0u$r>C$7$^$9\e(B ({\bf unmark}).\\
+\end{keys}}}
+
+\def\OutputArticles{\subsec{(O) \e$B5-;v$N=PNO\e(B}{\samepage
+\begin{keys}{O m}
+O b     & \e$B5-;v$NK\BN\e(B ({bf body} \e$B$r%W%l%$%s%U%!%$%k7A<0$GJ]B8$7$^$9\e(B.
+[p/p]\\
+O f     & \e$B$3$N5-;v$r%W%l%$%s%U%!%$%k\e(B ({\bf file}) \e$B7A<0$GJ]B8$7$^$9\e(B.
+[p/p]\\
+O h     & \e$B$3$N5-;v$r\e(B {\bf mh} \e$B%U%)%k%@!<$N7A<0$GJ]B8$7$^$9\e(B. [p/p]\\
+O m     & \e$B$3$N5-;v$r%a!<%k\e(B ({\bf mail}) \e$B7A<0$GJ]B8$7$^$9\e(B. [p/p]\\
+O o     & (o, C-o) \e$B$3$N5-;v$r\e(B gnus-default-article-saver \e$B$r;H$C$FJ]B8\e(B
+\e$B$7$^$9\e(B. [p/p]\\
+O p     & ($\mid$) \e$B$3$N5-;v$r%7%'%k%3%^%s%I$K%Q%$%W$GAw$j$^$9\e(B. [p/p]\\
+O r     & \e$B$3$N5-;v$r\e(B {\bf RMAIL} \e$B7A<0$GJ]B8$7$^$9\e(B. [p/p]\\
+O s     & \e$B$3$N5-;v$r\e(B {\bf SOUP} \e$B%Q%1%C%H$r5-;v$KDI2C$7$^$9\e(B. [p/p]\\
+O v     & \e$B$3$N5-;v$r\e(B {\bf vm} \e$B$N7A<0$GJ]B8$7$^$9\e(B. [p/p]\\
+O F     & \e$B$3$N5-;v$r\e(B, \e$BB8:_$9$k%U%!%$%k$r>e=q$-$7$F\e(B, \e$B%W%l%$%s%U%!%$%k\e(B
+({\bf file}) \e$B$KJ]B8$7$^$9\e(B. [p/p]\\
+\end{keys}}}
+
+\def\Send{\subsec{(S) \e$BEj9F\e(B, \e$B%U%)%m!<%"%C%W\e(B, \e$BJVEz\e(B, \e$BE>Aw\e(B, \e$B<h$j>C$7\e(B}{\samepage
+\e$B$3$l$i$NL?Na$OJL$N\e(B Message \e$B%P%C%U%!$K9T$-$^$9\e(B. \e$B5-;v$rJT=8$7$?8e\e(B,
+C-c C-c \e$B$r2!$7$FAw?.$7$^$9\e(B. \e$B30It%0%k!<%W$K$$$F\e(B, \e$B30It%5!<%P!<$r;H$C$F5-\e(B
+\e$B;v$rEj9F$7$?$$$J$i\e(B, C-c C-c \e$B$K@\F,<-$rM?$($F$/$@$5$$\e(B. [\e$B0l;~E*\e(B] \e$B$K%5!<\e(B
+\e$B%P!<$,Ej9F$G$-$J$$$J$/$F\e(B, \e$B%a!<%k$+$i%K%e!<%9$X$N%2!<%H%&%'%$$r;H$C$FEj\e(B
+\e$B9F$7$?$$$H$-$K$O\e(B, `gnus-post-method' \e$B$r\e(B `nngateway' \e$B$K@_Dj$7$F$/$@$5$$\e(B.
+\\*
+\begin{keys}{S O m}
+%S b     & \e$B$3$N5-;v$X$N%U%)%m!<%"%C%W$NEj9F$H\e(B, \e$BJVEz$NAw?.$NN>J}\e(B ({\bf
+%both}) \e$B$r$7$^$9\e(B.\\
+S c     & (C) \e$B$3$N5-;v$r<h$j>C$7$^$9\e(B ({\bf cancel}) (\e$B<+J,<+?H$N$b$N$K\e(B
+\e$B$N$_F0:n$7$^$9\e(B).\\
+S f     & (f) \e$B$3$N5-;v$X$N%U%)%m!<%"%C%W\e(B ({\bf followup}) \e$B$rEj9F$7$^$9\e(B.
+[\e$B@\F,<-\e(B: \e$B855-;v$r4^$a$^$9\e(B]\\
+S m     & (m) \e$BC/$+$K%a!<%k\e(B {\bf mail} \e$B$rAw$j$^$9\e(B.\\
+S n     & \e$B%a!<%k$G<u$1<h$C$?%a%C%;!<%8$K\e(B, \e$B%K%e!<%9%0%k!<%W\e(B ({\bf
+newsgroup}) \e$B$G%U%)%m!<%"%C%W$7$^$9\e(B.\\
+S o m   & (C-c C-f) \e$B$3$N5-;v$r0l$K%a!<%k$rAw$k\e(B ({\bf mail}) \e$B$3$H$GE>Aw\e(B
+\e$B$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B40A4$J%X%C%@!<$r4^$a$^$9\e(B]\\
+S o p   & \e$B$3$N5-;v$r%K%e!<%9%0%k!<%W$X$NEj9F\e(B ({\bf post}) \e$B$H$7$FE>Aw$7\e(B
+\e$B$^$9\e(B.\\
+S p     & (a) \e$B$3$N%0%k!<%W$K5-;v$rEj9F\e(B ({\bf post}) \e$B$7$^$9\e(B.\\
+S r     & (r) \e$B$3$N5-;v$NCx<T$K%a!<%k$GJVEz\e(B ({\bf reply}) \e$B$7$^$9\e(B. [\e$B@\F,\e(B
+\e$B<-\e(B: \e$B855-;v$r4^$_$^$9\e(B]\\
+S s     & \e$B$3$N5-;v$r?7$7$$5-;v$GBeBX$7$^$9\e(B ({\bf supersede}) (\e$B<+J,$N5-\e(B
+\e$B;v$N$_\e(B).\\
+S u     & \e$B%U%!%$%k$r\e(B {\bf uuencode} \e$B$7\e(B, \e$BO"B3J*$KJ,3d$7$FEj9F$7$^$9\e(B.\\
+S w     & \e$B5-;v$N:n<T$H<u$1<h$j<j$K9-$$\e(B ({\bf wide}) \e$BJVEz$r%a!<%k$GAw$j\e(B
+\e$B$^$9\e(B. [\e$B@\F,<-\e(B: \e$B855-;v$r4^$_$^$9\e(B]\\
+S B     & \e$B855-;v$r0zMQ$7$F%U%)%m!<%"%C%W$NEj9F\e(B, \e$BJVEz$NAw?.$NN>J}\e(B ({\bf
+both}) \e$B$r$7$^$9\e(B. [p/p]\\
+S D b   & \e$B<:GT$7$?\e(B ({\bf bounced}) \e$B%a!<%k$r<u$1<h$j<j$N%"%I%l%9$r=$@5\e(B
+\e$B$7$?8e$G:FAw$7$^$9\e(B.  [\e$B@\F,<-\e(B:  \e$B$3$l$,JVEz$K$J$C$F$$$k%a%C%;!<%8$N%X%C\e(B
+\e$B%@!<$rI=<($7$^$9\e(B]\\
+S D r   & \e$BC/$+$K$3$N%a%C%;!<%8$r:FAw\e(B ({\bf Resend}) \e$B$7$^$9\e(B. [p/p]\\
+S F     & (F) \e$B855-;v$r0zMQ$7$F%U%)%m!<%"%C%W\e(B ({\bf followup}) \e$B$rEj9F$7\e(B
+\e$B$^$9\e(B. [p/p]\\
+S N     & \e$B%K%e!<%9%0%k!<%W\e(B ({\bf newsgroup}) \e$B$N%U%)%m!<%"%C%W$r%a!<%k\e(B
+\e$B%a%C%;!<%8$G$7\e(B, \e$B855-;v$r4^$_$^$9\e(B.  [p/p]\\
+S O m   & \e$B$3$l$i$NO"B3$r=8G[7A<0$K$7$F%a!<%k\e(B ({\bf mail}) \e$B$GE>Aw$7$^$9\e(B.
+[p/p]\\
+S O p   & \e$B$3$l$i$NO"B3$r=8G[7A<0$K$7$F%K%e!<%9%0%k!<%W$KEj9F\e(B ({\bf
+post}) \e$B$7$^$9\e(B. [p/p]\\
+S R     & (R) \e$B855-;v$r0zMQ$7$F%a!<%k$GJVEz\e(B ({\bf reply}) \e$B$7$^$9\e(B.
+[p/p]\\
+S W     & \e$B855-;v$r0zMQ$7$F9-$$\e(B ({\bf wide}) \e$BJVEz$r%a!<%k$GAw$j$^$9\e(B.
+[p/p]\\
+S W-c   & \e$B2a>jAj8_Ej9F\e(B ({\bf crossposting}) \e$B$X$NJ86g\e(B ({\bf complaint})
+\e$B$rAw?.$7$^$9\e(B. [p/p]\\
+\end{keys}
+\e$B$?$C$?:#Ej9F$7$?5-;v$r<h$j>C$7$?$jBeBX$7$?$1$l$P\e(B (\e$B%5!<%P!<$K8=$l$kA0$K\e(B),
+*sent \ldots* \e$B%P%C%U%!$K0\F0$7$F\e(B, `Message-ID' \e$B$r\e(B `Cancel' \e$B$+\e(B
+`Supersedes' \e$B$K49$($F\e(B C-c C-c \e$B$G$b$&0lEYAw?.$7$F$/$@$5$$\e(B.
+}}
+
+\def\Thread{\subsec{(T) \e$B%9%l%C%IL?Na\e(B}{\samepage
+\begin{keys}{T M-\#}
+T ^     & \e$B$3$N5-;v$rA0$N$b$N$+<B9T0u$NIU$$$?$b$N$N;R6!$K$7$^$9\e(B. \\
+T \#    & \e$B$3$N\e(B(\e$BI{\e(B)\e$B%9%l%C%I$K%W%m%;%90u$rIU$1$^$9\e(B.\\
+T M-\#  & \e$B$3$N\e(B(\e$BI{\e(B)\e$B%9%C%I$+$i<B9T0u$r>C5n$7$^$9\e(B.\\
+T d     & \e$B$3$N%9%l%C%I$r2<$,$j$^$9\e(B ({\bf down}). [\e$B5wN%\e(B]\\
+T h     & \e$B$3$N\e(B (\e$BI{\e(B)\e$B%9%l%C%I$r1#$7$^$9\e(B ({\bf hide}).\\
+T i     & \e$B$3$N%9%l%C%I$N%9%3%"$r>e$2$^$9\e(B ({\bf increase}).  [\e$B%9%3%"\e(B]\\
+T k     & (M-C-k) \e$B8=:_$N\e(B (\e$BI{\e(B)\e$B%9%l%C%I$r@Z$j$^$9\e(B ({\bf kill}). [\e$B0z?t\e(B:
+\e$BIi\e(B--\e$B2D;k0u\e(B, \e$B@5\e(B: \e$B0u$r>C$9\e(B.]\\
+T l     & (M-C-l) \e$B$3$N%9%l%C%I$N%9%3%"$r2<$2$^$9\e(B ({\bf lower}). [\e$B%9%3\e(B
+\e$B%"\e(B]\\
+T n     & (M-C-f) \e$B<!\e(B ({\bf next}) \e$B$N%9%l%C%I$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+T o     & \e$B$3$N%9%l%C%I$N@hF,\e(B ({\bf top}) \e$B$K0\F0$7$^$9\e(B.\\
+T p     & (M-C-b) \e$BA0\e(B ({\bf previous}) \e$B$N%9%l%C%I$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+T s     & \e$B$3$N5-;v$G1#$l$F$$$k%9%l%C%I$rI=<(\e(B ({\bf show}) \e$B$7$^$9\e(B.\\
+T t     & \e$B$3$N%9%l%C%I$r:F%9%l%C%I\e(B ({\bf thread}) \e$B$7$^$9\e(B.\\
+T u     & \e$B$3$N%9%l%C%I$N>e$,$j$^$9\e(B ({\bf up}). [\e$B5wN%\e(B]\\
+T H     & \e$BA4$F$N%9%l%C%I$r1#$7$^$9\e(B ({\bf hide}).\\
+T S     & \e$BA4$F$N1#$5$l$?%9%l%C%I$rI=<(\e(B ({\bf show}) \e$B$7$^$9\e(B.\\
+T T     & (M-C-t) \e$B%9%l%C%II=<($r@Z$jBX$($^$9\e(B ({\bf toggle}).\\
+\end{keys}}}
+
+\def\Score{\subsec{(V) \e$B%9%3%"\e(B (\e$BCM\e(B) \e$BL?Na\e(B}{\samepage
+\e$B%*%s%i%$%s\e(B info \e$B$GE,1~%9%3%"$rFI$s$G$/$@$5$$\e(B.\\*
+\begin{keys}{\bf A p m l}
+V a     & \e$BA4$F$NMWAG$r;XDj$7$F?7$7$$%9%3%"EPO?$r2C$(\e(B ({\bf add}) \e$B$^$9\e(B.\\
+V c     & \e$B?7$7$$%9%3%"%U%!%$%k$r8=:_$N$b$N\e(B ({\bf current}) \e$B$H$7$FA*Br\e(B
+\e$B$7$^$9\e(B.\\
+V e     & \e$B8=:_$N%9%3%"%U%!%$%k$rJT=8\e(B ({\bf edit}) \e$B$7$^$9\e(B.\\
+V f     & \e$B%9%3%"%U%!%$%k\e(B ({\bf file}) \e$B$rJT=8$7$F8=:_$N$b$N$H$7$^$9\e(B.\\
+V m     & \e$BM?$($i$l$?%9%3%"$h$j2<$N5-;v$K4{FI$K0u\e(B ({\bf mark}) \e$B$rIU$1$^\e(B
+\e$B$9\e(B. [\e$B%9%3%"\e(B]\\
+V s     & \e$B$3$N5-;v$N%9%3%"$r@_Dj\e(B ({\bf set}) \e$B$7$^$9\e(B.\\
+V t     & \e$B$3$N5-;v$KE,MQ$5$l$?A4$F$N%9%3%"5,B'$rDI@W\e(B ({\bf trace}) \e$B$7\e(B
+\e$B$^$9\e(B.\\
+V x     & \e$BA4$F$NDc%9%3%"$N5-;v$r>C5n\e(B ({\bf expunge}) \e$B$7$^$9\e(B. [score]\\
+V C     & \e$B8=:_$N%9%3%"%U%!%$%k$rMxMQ<T$KJ,$+$j$d$9$$%$%s%?!<%U%'!<%9$r\e(B
+\e$B;H$C$F%+%9%?%^%$%:\e(B ({\bf customize}) \e$B$7$^$9\e(B.\\
+V F     & \e$B%U%!%$%k$HF14|$r<h$k$?$a$K%9%3%"%-%c%C%7%e$r=q$-=P$7$^$9\e(B
+({\bf Flush}).\\
+V R     & \e$B%<%m$+$i$3$N35N,%P%C%U%!$r:F$S%9%3%"IU$1$7$^$9\e(B ({\bf
+re-score}).\\
+V S     & \e$B$3$N5-;v$N%9%3%"$rI=<(\e(B ({\bf show}) \e$B$7$^$9\e(B.\\
+I C-i   & \e$B$3$N5-;v$N%9%3%"$rA}2C\e(B ({\bf increase}) \e$B$7$^$9\e(B.\\
+L C-i   & \e$B$3$N5-;v$N%9%3%"$r2<$2\e(B ({\bf lower}) \e$B$^$9\e(B.\\
+\bf A p m l& \e$B$3$N5-;v$K4p$E$$$?%9%3%"EPO?$r:n$j$^$9\e(B.\\
+\end{keys}
+
+4\e$B$D$NJ8;z$O0J2<$N0UL#$G$9\e(B:\\*
+\quad \B{A}ction: I)ncrease, L)ower;\\*
+\quad \B{p}art: a)uthor (from), b)ody, d)ate, f)ollowups, h)ead (\e$BA4$F$N%X%C%@!<\e(B),
+message-i)d, l)ines, s)ubject, t)hread (references), x)refs (cross-posting);\\*
+\quad \B{m}atch type:\\*
+\qquad string: e)xact, f)uzzy, r)egexp, s)ubstring\\*
+\qquad date: a)t, b)efore, n)this,\\*
+\qquad number: $<$, =, $>$;\\*
+\quad \B{l}ifetime: t)emporary, p)ermanent, i)mmediate.
+
+2/3\e$BHVL\$NJ8;z$rBgJ8;z$GF~NO$9$k$H\e(B, \e$B;D$j$NJ8;z$O\e(B s)ubstring \e$B$H\e(B t)emporary
+\e$B$G$"$k$H$_$J$5$l$^$9\e(B. 3\e$BHVL\$NJ8;z$rBgJ8;z$GF~NO$9$k$H\e(B, \e$B:G8e$N$b$N$O\e(B
+t)emporary \e$B$G$"$k$H$_$J$5$l$^$9\e(B.
+
+\quad \e$B%9%3%"%U%!%$%k$N<j$G$NJT=8$N$?$a$NDI2C$N%-!<\e(B:\\*
+\begin{keys}{C-c C-c}
+C-c C-c & \e$B%9%3%"%U%!%$%k$NJT=8$r=*$($^$9\e(B.\\
+C-c C-d & \e$B8=:_$NF|IU$1\e(B ({\bf date}) \e$B$rF|?t$H$7$FA^F~$7$^$9\e(B.\\
+C-c C-p & [\e$BE,1~\e(B] \e$B%9%3%"%U%!%$%k$r$-$l$$$K0u;z\e(B ({\bf pretty-print}) \e$B$7\e(B
+\e$B$^$9\e(B.\\
+\end{keys}}}
+
+\def\Wash{\subsec{(W) \e$B5-;v%P%C%U%!$N@vBu\e(B}{\samepage
+\begin{keys}{W C-c}
+W b     & \e$B5-;v$NCf$N\e(B Message-ID \e$B$H\e(B URL \e$B$H0zMQ$H=pL>$r%^%&%9$G%/%j%C%/\e(B
+\e$B2DG=$J%\%?%s$K\e(B ({\bf buttons}) \e$B$7$^$9\e(B.\\
+W c     & \e$BM>J,$J\e(B {\bf CR} (^M) \e$B$r<h$j=|$-$^$9\e(B.\\
+W e     & \e$B6/D4$5$l$?\e(B ({\bf emphasized}) \e$B%F%-%9%H\e(B, \e$B$?$H$($P\e(B, *this* \e$B$d\e(B
+\_that\_). \e$B$r$-$l$$$K8+$;$^$9\e(B.\\
+W f     & X-{\bf Face} \e$B%X%C%@!<$rI=<($7$^$9\e(B.\\
+W h     & HTML \e$B$r%F%-%9%H$H$7$FI=<($7$^$9\e(B.\\
+W l     & (w) \e$B5-;v$+$i%Z!<%8$N6h@Z$j\e(B ({\bf^L}) \e$B$r<h$j=|$-$^$9\e(B.\\
+W m     & {\bf MIME} \e$B$N<B9T$r@Z$j49$($^$9\e(B.\\
+W o     & \e$B5-;v$N\e(B {\bf overstrike} \e$B$+\e(B \e$B2<@~\e(B(^H\_) \e$B$r07$$$^$9\e(B.\\
+W q     & \e$B5-;v$N\e(B {\bf quoted}-printable \e$B$r07$$$^$9\e(B.\\
+W r     & (C-c C-r) \e$B5-;v$K%+%(%5%k2sE>\e(B ({\bf rotate}) (rot13) \e$B$r9T$$$^$9\e(B.\\
+W t     & (t) \e$BA4$F$N%X%C%@!<I=<($r@Z$jBX$($^$9\e(B ({\bf toggle}).\\
+v       & \e$BA4$F$N%X%C%@!<$N>iD9$J\e(B ({\bf verbose}) \e$BI=<($r@Z$jBX$($^$9\e(B.\\
+W w     & \e$B5-;v$N8l$N@^$jJV$7\e(B ({\bf wrap}) \e$B$r9T$$$^$9\e(B.\\
+W T e   & \e$B5-;v$N;~9o$rAw$i$l$?;~$+$i7P2a$7$?\e(B ({\bf elapsed}) \e$B;~4V$KJQ\e(B
+  \e$B49$7$^$9\e(B.\\
+W T l   & \e$B5-;v$N;~9o$r%m!<%+%k\e(B ({\bf local}) \e$BI8=`;~9oBS$KJQ49$7$^$9\e(B.\\
+W T u   & (W T z) \e$B5-;v$N;~9o$r\e(B {\bf UTC} ({\bf Zulu}, GMT) \e$B$KJQ49$7$^\e(B
+  \e$B$9\e(B.\\
+\end{keys}}}
+
+\def\Hide{\subsubsec{(W W) \e$B5-;v$NItJ,$r1#$9\e(B/\e$B%O%$%i%$%H$9$k\e(B}{\samepage
+\e$B@\F,<-$,L5$$$H!"$3$l$i$NL?Na$O1#$9$+$I$&$+$r@Z$j49$($^$9!#@5$N0z?t$O1#\e(B
+\e$B$7!"Ii$N0z?t$OI=<($7$^$9\e(B.\\*
+\begin{keys}{W W C-c}
+W W C-c & \e$BB0@-9T$r;}$D0zMQ$5$l$?\e(B  ({\bf cited}) \e$B%F%-%9%H$r1#$7$^$9\e(B.\\
+W W a   & \e$BA4$F$N\e(B ({\bf all}) \e$BK>$^$7$/$J$$ItJ,$r1#$7$^$9\e(B.\\
+W W b   & \e$BB`6~$J\e(B ({\bf boring}) \e$B%X%C%@!<$r1#$7$^$9\e(B.\\
+W W c   & \e$B0zMQ$5$l$?\e(B ({\bf cited}) \e$B%F%-%9%H$r1#$7$^$9\e(B.\\
+W W h   & (t, W t) \e$BK>$^$7$/$J$$%X%C%@!<\e(B ({\bf headers}) \e$B$r1#$7$^$9\e(B.\\
+W W p   & {\bf PGP} \e$B$N%X%C%@!<$H=pL>$r1#$7$^$9\e(B.\\
+W W s   & \e$B=pL>\e(B ({\bf signature}) \e$B$r1#$7$^$9\e(B.\\
+W W P   & {\bf PEM} \e$B%X%C%@!<$H=pL>$r1#$7$^$9\e(B.
+\end{keys}}}
+
+\def\Highlight{\subsubsec{(W H) \e$B5-;v$N0lItJ,$r%O%$%i%$%H$9$k\e(B}{\samepage
+\begin{keys}{W H A}
+W H a   & \e$BA4$F\e(B ({\bf all}) \e$B$NItJ,$r1#$7$^$9\e(B.\\
+W H c   & \e$B0zMQ$5$l$?\e(B ({\bf cited}) \e$B%F%-%9%H$r%O%$%i%$%H$7$^$9\e(B.\\
+W H h   & \e$B%X%C%@!<\e(B ({\bf headers}) \e$B$r%O%$%i%$%H$7$^$9\e(B.\\
+W H s   & \e$B=pL>\e(B ({\bf signature}) \e$B$r%O%$%i%$%H$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\Extract{\subsec{(X) \e$BO"B3$NE83+\e(B (Uudecode \e$B$J$I\e(B)}{\samepage
+Gnus \e$B$O8=:_$N5-;v$,O"B3J*\e(B (\e$B$=$l$>$l$NItJ,$,I=Bj$K$*$$$F\e(B, \e$BNc$($P\e(B
+{}1/10\dots10/10 \e$B$N$h$&$K\e(B, \e$B?t;z$GF1Dj$5$l$kJ#?t$NEj9F\e(B) \e$B$N0lIt$G$"$k$H\e(B,
+\e$B$=$l$rG'<1$7$^$9\e(B. 1\e$B$D0J>e$NO"B3J*$K0u$rIU$1$F<B9T$9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B. \e$BEj9F$,%"!<%+%$%V$r4^$s$G$$$l$P\e(B, \e$B?7$7$$%0%k!<%W$GE83+$5$l\e(B, \e$B=8$a$i$l\e(B
+\e$B$^$9\e(B.\\*
+\begin{keys}{X p}
+X b     & \e$BO"B3J*$r\e(B {\bf binhex} \e$B$GE83+$7$^$9\e(B. [p/p]\\
+X o     & \e$BC1$KO"B3J*$r=PNO\e(B ({\bf output}) \e$B$7$^$9\e(B (\e$BI|9f2=$O$7$^$;$s\e(B).
+[p/p]\\
+X p     & \e$B%]%9%H%9%/%j%W%H\e(B ({\bf postscript}) \e$B$NO"B3J*$rE83+$7$^$9\e(B.
+[p/p]\\
+X s     & \e$BO"B3J*$r\e(B {\bf shar} \e$B$GE83+$7$^$9\e(B. [p/p]\\
+X u     & \e$BO"B3J*$r\e(B {\bf uudecode} \e$B$7$^$9\e(B. [p/p]\\
+\end{keys}
+
+\e$B$3$l$i$N$=$l$>$l$K$O\e(B4\e$B$D$N0[7A$,$"$j$^$9\e(B:\\*
+\begin{keys}{X v \bf Z}
+X   \bf z & \e$BO"B3J*$rI|9f2=$7$^$9\e(B. [p/p]\\
+X   \bf Z & \e$BO"B3J*$rI|9f2=$7$FJ]B8$7$^$9\e(B. [p/p]\\
+X v \bf z & \e$BO"B3J*$rI|9f2=$7$F1\Mw$7$^$9\e(B. [p/p]\\
+X v \bf Z & \e$BO"B3J*$rI|9f2=$7\e(B, \e$BJ]B8$7\e(B, \e$B1\Mw$7$^$9\e(B. [p/p]\\
+\end{keys}
+{\bf z} \e$B$d\e(B {\bf Z} \e$B$OI|9f2=$NJ}K!$r<($7$^$9\e(B (b, o, p, s, u).
+
+\e$B$3$l$i$NL?Na$G:G$bNI$/;H$o$l$kJL$NB+G{$O\e(B\\*
+\begin{keys}{C-c C-v C-v}
+C-c C-v C-v & (X v u) \e$BO"B3J*$r\e(B uudecode \e$B$71\Mw$7$^$9\e(B. [p/p]\\
+\end{keys}
+\e$BI|9f2=$r<+F0E*$K9T$J$&$K$O\e(B, `M-x gnus-binary-mode' \e$B$r;H$C$F$/$@$5$$\e(B
+(\e$B$=$l$+$i5-;v$N85$N%F%-%9%H$r8+$k$?$a$K\e(B `g' \e$B$r;H$C$F$/$@$5$$\e(B).
+}}
+
+\def\Exit{\subsec{(Z) \e$B8=:_$N%0%k!<%W$r=P$k\e(B}{\samepage
+\begin{keys}{Z G}
+Z c     & (c) \e$BA4$F$N2D;k0uIU$-$G$J$$5-;v$K4{FI$N0u$rIU$1\e(B ({\bf
+catch-up}, \e$B%-%c%C%A%"%C%W\e(B) \e$B=*N;$7$^$9\e(B.\\
+Z n     & \e$BA4$F$N5-;v$K4{FI$N0u$rIU$1\e(B, \e$B<!\e(B ({\bf next}) \e$B$N%0%k!<%W$K0\F0\e(B
+\e$B$7$^$9\e(B.\\
+Z s     & (\e$B$3$N%0%k!<%W$N>pJs$r%I%j%V%k%U%!%$%k$KJ]B8\e(B {\bf save}) \e$B$7$^\e(B
+\e$B$9\e(B. [\e$B@\F,<-\e(B: .newsrc \e$B$bJ]B8$7$^$9\e(B]\\
+Z C     & \e$BA4$F$N5-;v$K4{FI$N0u$rIU$1\e(B ({\bf catch-up}, \e$B%-%c%C%A%"%C%W\e(B)
+\e$B=*N;$7$^$9\e(B.\\
+Z E     & (Q) \e$B%0%k!<%W>pJs$r99?7$;$:$K=*N;\e(B ({\bf Exit}) \e$B$7$^$9\e(B.\\
+Z G     & (M-g) \e$B%0%k!<%W$N?7$7$$5-;v$rD4$Y$^$9\e(B ({\bf get}, \e$B<hF@\e(B).\\
+Z N     & \e$B=*N;$7$F<!$N\e(B ({\bf next}) \e$B%0%k!<%W$X0\F0$7$^$9\e(B.\\
+Z P     & \e$B=*N;$7$FA0$N\e(B ( {\bf previous}) \e$B%0%k!<%W$K0\F0$7$^$9\e(B.\\
+Z R     & \e$B%0%k!<%W$r=*N;$7$F\e(B, \e$B:F$SF~$j$^$9\e(B ({\bf reenter}).
+[\e$B@\F,0z?t\e(B: \e$BL$FI$b4{FI$bA4$F$N5-;v$rA*Br$7$^$9\e(B.]\\
+Z Z     & (q, Z Q) \e$B%0%k!<%W$r=*N;$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\Limit{\subsec{(/) \e$B35N,$N@)8B\e(B}{\samepage
+\begin{keys}{/ D}
+/ a  & \e$BM?$($i$l$?Cx<T\e(B ({\bf author}) \e$B$N@55,I=8=$K@)8B$7$^$9\e(B.\\
+/ c  & \e$B$3$I$b\e(B ({\bf children}) (follow-up) \e$B$r;}$?$J$$J]N15-;v$r1#$7$^$9\e(B.\\
+/ d  & \e$BA4$F$NJ]N1\e(B ({\bf dormant}) \e$B5-;v$r1#$7$^$9\e(B.\\
+/ m  & \e$BM?$($i$l$?0u\e(B ({\bf mark}) \e$B$r;}$D5-;v$K@)8B$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B0u$r\e(B
+\e$B;}$?$J$$$N$b$N$K$7$^$9\e(B]\\
+/ n  & \e$B8=:_$N5-;v$K@)8B$7$^$9\e(B.[p/p]\\
+/ s  & (/ /) \e$BM?$($i$l$?I=Bj\e(B ({\bf subject}) \e$B$N@55,I=8=$K@)8B$7$^$9\e(B.\\
+/ t  & \e$B;~4V\e(B ({\bf time}) (\e$BM?$($i$l$?F|IU$h$j$b8E$$$b$N\e(B).
+[\e$B@\F,<-\e(B: \e$B?7$7$$$b$N\e(B]\\
+/ u  & (x) \e$BL$FI\e(B ({\bf unread}) \e$B5-;v$K@)8B$7$^$9\e(B. [\e$B@\F,<-\e(B: ! \e$B$H\e(B ? \e$B5-;v\e(B
+\e$B$b>C5n$7$^$9\e(B]\\
+/ v  & \e$B%9%3%"$N9b$$5-;v$K@)8B$7$^$9\e(B(\e$BCM\e(B ({\bf value})). [\e$B%9%3%"\e(B]\\
+/ w  & \e$BA0$N@)8B$r%9%?%C%/$+$i<h$j=P$7$FI|85$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$BA4$F$N@)8B\e(B
+\e$B$r<h$j=P$7$^$9\e(B]\\
+/ C  & \e$B@)8B$N30$NA4$F$NL$FI5-;v$r4{FI$K$7$^$9\e(B ({\bf catch-up}). [\e$B@\F,\e(B
+\e$B<-\e(B: ! \e$B$H\e(B ? \e$B5-;v$b\e(B]\\
+/ D  & \e$BA4$F$NJ]N1\e(B ({\bf dormant}) \e$B5-;v$rI=<($7$^$9\e(B.\\
+/ E  & (M S, C-c M-C-s) \e$BA4$F$N:o=|$5$l$?5-;v$rI=<(\e(B ({\bf show}) \e$B$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\PickAndRead{\subsec{\e$BA*Br\e(B-\e$BFI=q%b!<%I\e(B}{\samepage
+\e$B$^$:9%$-$J5-;v$r$rA*Br$7$F\e(B, \e$B8e$K$N$_FI$`$H$-$@$1\e(B `M-x gnus-pick-mode'
+\e$B$r;H$C$F$/$@$5$$\e(B.\\*
+\begin{keys}{SPC}
+SPC  & \e$BFI$_;O$a$k:G8e$J$i35N,$r%9%/%m!<%k$7$^$9\e(B.\\
+RET  & \e$BFI$_;O$a$^$9\e(B. [\e$B@\F,<-\e(B: \e$BA*Br$5$l$?$F$$$J$$A4$F$N5-;v$r4{FI$K$7$^\e(B
+\e$B$9\e(B]\\
+.    & \e$B$3$N5-;v$rA*Br$7$^$9\e(B. [\e$B@\F,<-\e(B: \e$B$=$NHV9f$N5-;v$rA*Br$7$^$9\e(B]\\
+r    & \e$B%j!<%8%g%s\e(B ({\bf region}) \e$B$NA4$F$N5-;v$rA*Br$7$^$9\e(B.\\
+R    & \e$B%j!<%8%g%s\e(B ({\bf region}) \e$B$NA4$F$N5-;v$rL$A*Br$K$7$^$9\e(B.\\
+t    & \e$B$3$N%9%l%C%I\e(B ({\bf thread}) \e$B$rA*Br$7$^$9\e(B.\\
+u    & \e$B$3$N5-;v$rL$A*Br\e(B ({\bf unpick}) \e$B$K$7$^$9\e(B.\\
+T    & \e$B$3$N%9%l%C%I$r\e(B ({\bf thread}) \e$BL$A*Br$K$7$^$9\e(B.\\
+U    & \e$BA4$F$N5-;v$rL$A*Br\e(B ({\bf unpick}) \e$B$K$7$^$9\e(B.\\
+e    & \e$B@55,I=8=$K9gCW$9$k5-;v$rA*Br$7$^$9\e(B.\\
+b    & \e$B%P%C%U%!\e(B ({\bf buffer}) \e$B$NA4$F$N5-;v$rA*Br$7$^$9\e(B.\\
+B    & \e$B%P%C%U%!\e(B ({\bf buffer}) \e$B$NA4$F$N5-;v$rL$A*Br$K$7$^$9\e(B.\\
+\end{keys}}}
+
+\def\ArticleMode{\sec{\e$B5-;v%b!<%I\e(B}{\samepage
+\e$B35N,%b!<%I$NA4$F$N%-!<$O5-;v%b!<%I$G$bF0:n$7$^$9\e(B.(\e$B$b$A$m$s\e(B,
+\e$BIaDL$NA`:n%-!<$O5-;v%P%C%U%!$rA`:n$7$^$9\e(B.)
+\e$BDI2C$N%-!<$O\e(B:\\*
+\begin{keys}{C-c C-m}
+RET     & (\e$B??Cf$N%^%&%9%\%?%s\e(B) \e$B%]%$%s%H$N$"$k%\%?%s$r3hF02=$7$F\e(B, URL
+\e$B$d\e(B Message-ID \e$B$K0\F0$7$?$j\e(B, \e$B0zMQ\e(B/\e$B=pL>\e(B, \e$B$J$I$r1#$7$?$j$7$^$9\e(B.\\
+TAB     & \e$B%]%$%s%H$r<!$N%\%?%s$K0\F0$7$^$9\e(B.\\
+M-TAB   & \e$B%]%$%s%H$rA0$N%\%?%s$K0\F0$7$^$9\e(B.\\
+?       & \e$BC;$$%X%k%W%a%C%;!<%8$rI=<($7$^$9\e(B.\\
+h       & (s) {\bf \e$B35N,\e(B} \e$B%P%C%U%!$N5-;v$N%X%C%@!<\e(B ({\bf header}) \e$B9T$K\e(B
+\e$B0\F0$7$^$9\e(B.\\
+C-c ^   & (r) \e$B%]%$%s%H$N6a$/$N\e(B Message-ID \e$B$N5-;v$r<hF@$7$^$9\e(B. (\e$B;2>H\e(B
+({\bf refer}))\\
+C-c C-m & \e$B%]%$%s%H$N6a$/$N%"%I%l%9$K%a!<%k\e(B ({\bf mail}) \e$B$GJVEz$7$^$9\e(B
+(\e$B@\F,0z?t\e(B: \e$B5-;v$r0zMQ$7$^$9\e(B).\\
+\end{keys}}}
+
+\def\ServerMode{\sec{\e$B%5!<%P!<%b!<%I\e(B}{\samepage
+\e$B$3$N%b!<%I$KF~$k$?$a$K$O\e(B, \e$B%0%k!<%W%b!<%I$G\e(B `^' \e$B$r2!$7$F$/$@$5$$\e(B.\\*
+\begin{keys}{SPC}
+SPC     & (RET) \e$B$3$N%5!<%P!<$r354Q$7$^$9\e(B.\\
+a       & \e$B?7$7$$%5!<%P!<$rDI2C\e(B {\bf add} \e$B$7$^$9\e(B.\\
+c       & \e$B$3$N%5!<%P!<$rJ#<L\e(B {\bf copy} \e$B$7$^$9\e(B.\\
+e       & \e$B%5!<%P!<$rJT=8\e(B {\bf edit} \e$B$7$^$9\e(B.\\
+g       & \e$BA4$F$N%G!<%?9=B$$r:F:n@.\e(B ({\bf generate}) \e$B$9$k$h$&$K%5!<%P!<\e(B
+\e$B$K?R$M$^$9\e(B.\\
+k       & \e$B$3$N%5!<%P!<$r@Z$j$^$9\e(B {\bf kill}. [\e$BHO0O\e(B]\\
+l       & \e$BA4$F$N%5!<%P!<$r0lMwI=<(\e(B {\bf list} \e$B$7$^$9\e(B.\\
+q       & \e$B%0%k!<%W%P%C%U%!$KLa$j$^$9\e(B (\e$B=*N;\e(B {\bf quit}).\\
+s       & \e$B?7$7$$%a%C%;!<%8$rD4$Y$k\e(B ({\bf scan}) \e$B$h$&$K%5!<%P!<$K?R$M$^\e(B
+\e$B$9\e(B.\\
+y       & \e$B0JA0$K@Z$C$?%5!<%P!<$rE=$jIU$1\e(B {\bf yank} \e$B$^$9\e(B.\\
+c       & \e$B$3$N%5!<%P!<$X$N@\B3$rJD$8$^$9\e(B ({\bf close}).\\
+O       & \e$B$3$N%5!<%P!<$X$N@\B3$r\e(B(\e$B:F$S\e(B)\e$B3+$-$^$9\e(B ({\bf open}).\\
+D       & \e$B$3$N%5!<%P!<$r;HMQIT2DG=$H$7$F0u$rIU$1$^$9\e(B (\e$B5qH]$7$^$9\e(B ({\bf
+deny})).\\
+R       & \e$BA4$F$N;HMQIT2DG=\e(B (\e$B5qH]\e(B) \e$B0u$r:F@_Dj$7$^$9\e(B ({\bf reset}).\\
+M-c     & \e$BA4$F$N%5!<%P!<$X$N@\B3$rJD$8$^$9\e(B ({\bf close}).\\
+M-o     & \e$BA4$F$N%5!<%P$X$N@\B3$r\e(B(\e$B:F$S\e(B)\e$B3+$-$^$9\e(B ({\bf open}).\\
+\end{keys}}}
+
+\def\BrowseServer{\sec{\e$B%5!<%P!<354Q%b!<%I\e(B}{\samepage
+\e$B$3$N%b!<%I$KF~$k$?$a$K$O\e(B, \e$B%0%k!<%W%b!<%I$G\e(B `B' \e$B$r2!$7$F$/$@$5$$\e(B.\\*
+\begin{keys}{RET}
+RET     & \e$B8=:_$N%0%k!<%W$KF~$j$^$9\e(B.\\
+SPC     & \e$B8=:_$N%0%k!<%W$KF~$C$F:G=i$N5-;v$rI=<($7$^$9\e(B.\\
+?       & \e$B$H$F$bC;$$%X%k%W%a%C%;!<%8$rI=<($7$^$9\e(B.\\
+n       & {\bf \e$B<!\e(B} \e$B$N%0%k!<%W$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+p       & {\bf \e$BA0\e(B} \e$B$N%0%k!<%W$K0\F0$7$^$9\e(B. [\e$B5wN%\e(B]\\
+q       & (l) \e$B354Q%b!<%I$r\e(B {\bf \e$B=*N;\e(B} \e$B$7$^$9\e(B.\\
+u       & \e$B8=:_$N%0%k!<%W$r\e(B[\e$BHs\e(B]\e$B9VFI\e(B ({\bf [Un]subscribe})\e$B$7$^$9\e(B. [\e$BHO0O\e(B]\\
+\end{keys}}}
index da186fe..0ddecd6 100644 (file)
-% include file for the Gnus refcard and booklet
-\def\progver{5.0}\def\refver{5.0} % program and refcard versions
-\def\date{16 September 1995}
-\def\author{Vladimir Alexiev $<$vladimir@cs.ualberta.ca$>$}
-\raggedbottom\raggedright
-\newlength{\logowidth}\setlength{\logowidth}{6.861in}
-\newlength{\logoheight}\setlength{\logoheight}{7.013in}
+%% include file for the Gnus refcard and booklet
+
+\def\progver{5.10}\def\refver{5.10-1} % program and refcard versions
+\def\date{Oct, 2003}
+\def\author{Gnus Bugfixing Girls + Boys $<$bugs@gnus.org$>$}
+
+%%
 \newlength{\keycolwidth}
 \newenvironment{keys}[1]% #1 is the widest key
-  {\nopagebreak%\noindent%
-   \settowidth{\keycolwidth}{#1}%
-   \addtolength{\keycolwidth}{\tabcolsep}%
-   \addtolength{\keycolwidth}{-\columnwidth}%
-   \begin{tabular}{@{}l@{\hspace{\tabcolsep}}p{-\keycolwidth}@{}}}%
-  {\end{tabular}\\}
-\catcode`\^=12 % allow ^ to be typed literally
-\newcommand{\B}[1]{{\bf#1})}    % bold l)etter
-
-\def\Title{
-\begin{center}
-{\bf\LARGE Gnus \progver\ Reference \Guide\\}
-%{\normalsize \Guide\ version \refver}
-\end{center}
-}
-
-\newcommand\Logo[1]{\centerline{
-\makebox[\logoscale\logowidth][l]{\vbox to \logoscale\logoheight
-{\vfill\special{psfile=gnuslogo.#1}}\vspace{-\baselineskip}}}}
-
-\def\CopyRight{
-\begin{center}
-Copyright \copyright\ 1995 Free Software Foundation, Inc.\\*
-Copyright \copyright\ 1995 \author.\\*
-Created from the Gnus manual Copyright \copyright\ 1994 Lars Magne
-Ingebrigtsen.\\*
-and the Emacs Help Bindings feature (C-h b).\\*
-Gnus logo copyright \copyright\ 1995 Luis Fernandes.\\*
-\end{center}
-
-Permission is granted to make and distribute copies of this reference
-\guide{} provided the copyright notice and this permission are preserved on
-all copies.  Please send corrections, additions and suggestions to the
-above email address. \Guide{} last edited on \date.
-}
-
-\def\Notes{
-\subsec{Notes}
-{\samepage
-Gnus is complex. Currently it has some 346 interactive (user-callable)
-functions. Of these 279 are in the two major modes (Group and
-Summary/Article). Many of these functions have more than one binding, some
-have 3 or even 4 bindings. The total number of keybindings is 389. So in
-order to save 40\% space, every function is listed only once on this
-\guide, under the ``more logical'' binding. Alternative bindings are given
-in parentheses in the beginning of the description.
-
-Many Gnus commands are affected by the numeric prefix. Normally you enter a
-prefix by holding the Meta key and typing a number, but in most Gnus modes
-you don't need to use Meta since the digits are not self-inserting. The
-prefixed behavior of commands is given in [brackets]. Often the prefix is
-used to specify:
-
-\quad [distance] How many objects to move the point over.
-
-\quad [scope] How many objects to operate on (including the current one).
-
-\quad [p/p] The ``Process/Prefix Convention'': If a prefix is given then it
-determines how many objects to operate on. Else if there are some objects
-marked with the process mark \#, these are operated on. Else only the
-current object is affected.
-
-\quad [level] A group subscribedness level. Only groups with a lower or
-equal level will be affected by the operation. If no prefix is given,
-`gnus-group-default-list-level' is used.  If
-`gnus-group-use-permanent-levels', then a prefix to the `g' and `l'
-commands will also set the default level.
-
-\quad [score] An article score. If no prefix is given,
-`gnus-summary-default-score' is used.
-%Some functions were not yet documented at the time of creating this
-%\guide and are clearly indicated as such.
-\\*[\baselineskip]
-\begin{keys}{C-c C-i}
-C-c C-i & Go to the Gnus online {\bf info}.\\
-C-c C-b & Send a Gnus {\bf bug} report.\\
-\end{keys}
-}}
-
-\def\GroupLevels{
-\subsec{Group Subscribedness Levels}
-The table below assumes that you use the default Gnus levels.
-Fill your user-specific levels in the blank cells.\\[1\baselineskip]
-
-\begin{tabular}{|c|l|l|}
-\hline
-Level & Groups & Status \\
-\hline
-1 & mail groups   &              \\
-2 & mail groups   &              \\
-3 &               & subscribed   \\
-4 &               &              \\
-5 & default list level &         \\
-\hline
-6 &               & unsubscribed \\
-7 &               &              \\
-\hline
-8 &               & zombies      \\
-\hline
-9 &               & killed       \\
-\hline
-\end{tabular}
-}
-
-\def\Marks{
-\subsec{Mark Indication Characters}
-{\samepage If a command directly sets a mark, it is shown in parentheses.\\*
-\newlength{\markcolwidth}
-\settowidth{\markcolwidth}{` '}% widest character
-\addtolength{\markcolwidth}{4\tabcolsep}
-\addtolength{\markcolwidth}{-\columnwidth}
-\newlength{\markdblcolwidth}
-\setlength{\markdblcolwidth}{\columnwidth}
-\addtolength{\markdblcolwidth}{-2\tabcolsep}
-\begin{tabular}{|c|p{-\markcolwidth}|}
-\hline
-\multicolumn{2}{|p{\markdblcolwidth}|}{{\bf ``Read'' Marks.}
-  All these marks appear in the first column of the summary line, and so
-  are mutually exclusive.}\\ 
-\hline
-` ' & (M-u, M SPC, M c) Not read.\\
-!   & (!, M !, M t) Ticked (interesting).\\
-?   & (?, M ?) Dormant (only followups are interesting).\\
-C   & (C, S c) {\bf Canceled} (only for your own articles).\\
-E   & (E, M e, M x) {\bf Expirable}. Only has effect in mail groups.\\
-\hline\hline
-\multicolumn{2}{|p{\markdblcolwidth}|}{The marks below mean that the article
-  is read (killed, uninteresting), and have more or less the same effect.
-  Some commands however explicitly differentiate between them (e.g.\ M
-  M-C-r, adaptive scoring).}\\
-\hline
-r   & (d, M d, M r) Deleted (marked as {\bf read}).\\
-C   & (M C; M C-c; M H; c, Z c; Z n; Z C) Killed by {\bf catch-up}.\\
-O   & {\bf Old} (marked read in a previous session).\\
-K   & (k, M k; C-k, M K) {\bf Killed}.\\
-R   & {\bf Read} (viewed in actuality).\\
-X   & Killed by a kill file.\\
-Y   & Killed due to low score.\\
-\hline\multicolumn{2}{c}{\vspace{1ex}}\\\hline
-\multicolumn{2}{|p{\markdblcolwidth}|}{{\bf Other marks}}\\
-\hline
-\#  & (\#, M \#, M P p) Processable (will be affected by the next operation).\\
-A   & {\bf Answered} (followed-up or replied).\\
-+   & Over default score.\\
-$-$ & Under default score.\\
-=   & Has children (thread underneath it). Add `\%e' to
-      `gnus-summary-line-format'.\\
-\hline
-\end{tabular}
-}}
-
-\def\GroupMode{
-\sec{Group Mode}
-\begin{keys}{C-c M-C-x}
-RET     & (=) Select this group. [Prefix: how many (read) articles to fetch.
-Positive: newest articles, negative: oldest ones.]\\
-SPC     & Select this group and display the first unread article. [Same
-prefix as above.]\\ 
-?       & Give a very short help message.\\
-$<$     & Go to the beginning of the Group buffer.\\
-$>$     & Go to the end of the Group buffer.\\
-,       & Jump to the lowest-level group with unread articles.\\
-.       & Jump to the first group with unread articles.\\
-^       & Enter the Server buffer mode.\\
-a       & Post an {\bf article} to a group.\\
-b       & Find {\bf bogus} groups and delete them.\\
-c       & Mark all unticked articles in this group as read ({\bf catch-up}).
-[p/p]\\ 
-g       & Check the server for new articles ({\bf get}). [level]\\
-j       & {\bf Jump} to a group.\\
-m       & {\bf Mail} a message to someone.\\
-n       & Go to the {\bf next} group with unread articles. [distance]\\
-p       & (DEL) Go to the {\bf previous} group with unread articles.
-[distance]\\ 
-q       & {\bf Quit} Gnus.\\
-r       & Read the init file ({\bf reset}).\\
-s       & {\bf Save} the `.newsrc.eld' file (and `.newsrc' if
-`gnus-save-newsrc-file').\\ 
-z       & Suspend (kill all buffers of) Gnus.\\
-B       & {\bf Browse} a foreign server.\\
-C       & Mark all articles in this group as read ({\bf Catch-up}). [p/p]\\
-F       & {\bf Find} new groups and process them.\\
-N       & Go to the {\bf next} group. [distance]\\
-P       & Go to the {\bf previous} group. [distance]\\
-Q       & {\bf Quit} Gnus without saving any startup (.newsrc) files.\\
-R       & {\bf Restart} Gnus.\\
-V       & Display the Gnus {\bf version} number.\\
-Z       & Clear the dribble buffer.\\
-C-c C-d & Show the {\bf description} of this group. [Prefix: re-read it
-from the server.]\\ 
-C-c C-s & {\bf Sort} the groups by name, number of unread articles, or level
-(depending on `gnus-group-sort-function').\\
-C-c C-x & Run all expirable articles in this group through the {\bf expiry} 
-process.\\
-C-c M-C-x & Run all articles in all groups through the {\bf expiry} process.\\
-C-x C-t & {\bf Transpose} two groups.\\
-M-d     & {\bf Describe} ALL groups. [Prefix: re-read the description from the
-server.]\\
-M-f     & Fetch this group's {\bf FAQ} (using ange-ftp).\\
-M-g     & Check the server for new articles in this group ({\bf get}). [p/p]\\
-M-n     & Go to the {\bf previous} unread group on the same or lower level.
-[distance]\\ 
-M-p     & Go to the {\bf next} unread group on the same or lower level.
-[distance]\\ 
-\end{keys}
-}
-
-\def\GroupCommands{
-\subsec{List Groups}
-{\samepage
-\begin{keys}{A m}
-A a     & (C-c C-a) List all groups whose names match a regexp ({\bf
-apropos}).\\ 
-A d     & List all groups whose names or {\bf descriptions} match a regexp.\\ 
-A k     & (C-c C-l) List all {\bf killed} groups.\\
-A m     & List groups that {\bf match} a regexp and have unread articles.
-[level]\\ 
-A s     & (l) List {\bf subscribed} groups with unread articles. [level]\\
-A u     & (L) List all groups (including {\bf unsubscribed}). [If no prefix
-is given, level 7 is the default]\\ 
-A z     & List the {\bf zombie} groups.\\
-A M     & List groups that {\bf match} a regexp.\\
-\end{keys}
-}
-
-\subsec{Create/Edit Foreign Groups}
-{\samepage
-The select methods are indicated in parentheses.\\*
-\begin{keys}{G m}
-G a     & Make the Gnus list {\bf archive} group. (nndir over ange-ftp)\\
-G d     & Make a {\bf directory} group (every file must be a posting and files
-must have numeric names). (nndir)\\
-G e     & (M-e) {\bf Edit} this group's select method.\\
-G f     & Make a group based on a {\bf file}. (nndoc)\\
-G h     & Make the Gnus {\bf help} (documentation) group. (nndoc)\\
-G k     & Make a {\bf kiboze} group. (nnkiboze)\\
-G m     & {\bf Make} a new group.\\
-G p     & Edit this group's {\bf parameters}.\\
-G v     & Add this group to a {\bf virtual} group. [p/p]\\
-G D     & Enter a {\bf directory} as a (temporary) group. (nneething without
-recording articles read.)\\
-G E     & {\bf Edit} this group's info (select method, articles read, etc).\\
-G V     & Make a new empty {\bf virtual} group. (nnvirtual)\\
-\end{keys}
-You can also create mail-groups and read your mail with Gnus (very useful
-if you are subscribed to any mailing lists), using one of the methods
-nnmbox, nnbabyl, nnml, nnmh, or nnfolder. Read about it in the online info
-(C-c C-i g Reading Mail RET).
-}
-
-%\subsubsec{Soup Commands}
-%\begin{keys}{G s w}
-%G s b   & gnus-group-brew-soup: not documented.\\
-%G s p   & gnus-soup-pack-packet: not documented.\\
-%G s r   & nnsoup-pack-replies: not documented.\\
-%G s s   & gnus-soup-send-replies: not documented.\\
-%G s w   & gnus-soup-save-areas: not documented.\\
-%\end{keys}
-
-\subsec{Mark Groups}
-\begin{keys}{M m}
-M m     & (\#) Set the process {\bf mark} on this group. [scope]\\
-M u     & (M-\#) Remove the process mark from this group ({\bf unmark}).
-[scope]\\ 
-M w     & Mark all groups in the current region.\\
-\end{keys}
-
-\subsec{Unsubscribe, Kill and Yank Groups}
-\begin{keys}{S w}
-S k     & (C-k) {\bf Kill} this group.\\
-S l     & Set the {\bf level} of this group. [p/p]\\
-S s     & (U) Prompt for a group and toggle its {\bf subscription}.\\
-S t     & (u) {\bf Toggle} subscription to this group. [p/p]\\
-S w     & (C-w) Kill all groups in the region.\\
-S y     & (C-y) {\bf Yank} the last killed group.\\
-S z     & Kill all {\bf zombie} groups.\\
-\end{keys}
-}
-
-\def\SummaryMode{
-\sec{Summary Mode}  %{Summary and Article Modes}
-\begin{keys}{SPC}
-SPC     & (A SPC, A n) Select an article, scroll it one page, move to the
-next one.\\ 
-DEL     & (A DEL, A p, b) Scroll this article one page back. [distance]\\
-RET     & Scroll this article one line forward. [distance]\\
-=       & Expand the Summary window. [Prefix: shrink it to display the
-Article window]\\
-$<$     & (A $<$, A b) Scroll to the beginning of this article.\\
-$>$     & (A $>$, A e) Scroll to the end of this article.\\
-\&      & Execute a command on all articles matching a regexp.
-[Prefix: move backwards.]\\
-j       & (G g) Ask for an article number and then {\bf jump} to that summary
-line.\\ 
-C-t     & Toggle {\bf truncation} of summary lines.\\
-M-\&    & Execute a command on all articles having the process mark.\\
-M-k     & Edit this group's {\bf kill} file.\\
-M-n     & (G M-n) Go to the {\bf next} summary line of an unread article.
-[distance]\\ 
-M-p     & (G M-p) Go to the {\bf previous} summary line of an unread article. 
-[distance]\\ 
-M-r     & Search through all previous articles for a regexp.\\
-M-s     & {\bf Search} through all subsequent articles for a regexp.\\
-M-K     & Edit the general {\bf kill} file.\\
-\end{keys}
-}
-
-\def\SortSummary{
-\subsec{Sort the Summary Buffer}
-\begin{keys}{C-c C-s C-a}
-C-c C-s C-a & Sort the summary by {\bf author}.\\
-C-c C-s C-d & Sort the summary by {\bf date}.\\
-C-c C-s C-i & Sort the summary by article score.\\
-C-c C-s C-n & Sort the summary by article {\bf number}.\\
-C-c C-s C-s & Sort the summary by {\bf subject}.\\
-\end{keys}
-}
-
-\def\Asubmap{
-\subsec{Article Buffer Commands}
-\begin{keys}{A m}
-A g     & (g) (Re)fetch this article ({\bf get}). [Prefix: just show the
-article.]\\ 
-A r     & (^, A ^) Go to the parent of this article (the {\bf References}
-header).\\ 
-M-^     & Fetch the article with a given Message-ID.\\
-A s     & (s) Perform an i{\bf search} in the article buffer.\\
-A D     & (C-d) Un{\bf digestify} this article into a separate group.\\
-\end{keys}
-}
-
-\def\Bsubmap{
-\subsec{Mail-Group Commands}
-{\samepage
-These commands (except `B c') are only valid in a mail group.\\*
-\begin{keys}{B M-C-e}
-B DEL   & {\bf Delete} the mail article from disk (!). [p/p]\\
-B c     & {\bf Copy} this article from any group to a mail group. [p/p]\\
-B e     & {\bf Expire} all expirable articles in this group. [p/p]\\
-B i     & {\bf Import} a random file into this group.\\
-B m     & {\bf Move} the article from one mail group to another. [p/p]\\
-B q     & {\bf Query} where will the article go during fancy splitting\\
-B r     & {\bf Respool} this mail article. [p/p]\\
-B w     & (e) Edit this article.\\
-B M-C-e & {\bf Expunge} (delete from disk) all expirable articles in this group
-(!). [p/p]\\ 
-\end{keys}
-}}
-
-\def\Gsubmap{
-\subsec{Select Articles}
-{\samepage
-These commands select the target article. They do not understand the prefix.\\*
-\begin{keys}{G C-n}
-G b     & (,) Go to the {\bf best} article (the one with highest score).\\
-G f     & (.) Go to the {\bf first} unread article.\\
-G l     & (l) Go to the {\bf last} article read.\\
-G n     & (n) Go to the {\bf next} unread article.\\
-p       & Go to the {\bf previous} unread article.\\
-G p     & {\bf Pop} an article off the summary history and go to it.\\
-G N     & (N) Go to {\bf the} next article.\\
-G P     & (P) Go to the {\bf previous} article.\\
-G C-n   & (M-C-n) Go to the {\bf next} article with the same subject.\\
-G C-p   & (M-C-p) Go to the {\bf previous} article with the same subject.\\
-\end{keys}
-}}
-
-\def\Hsubmap{
-\subsec{Help Commands}
-\begin{keys}{H d}
-H d     & (C-c C-d) {\bf Describe} this group. [Prefix: re-read the description
-from the server.]\\
-H f     & Try to fetch the {\bf FAQ} for this group using ange-ftp.\\
-H h     & Give a very short {\bf help} message.\\
-H i     & (C-c C-i) Go to the Gnus online {\bf info}.\\
-H v     & Display the Gnus {\bf version} number.\\
-\end{keys}
-}
-
-\def\Msubmap{
-\subsec{Mark Articles}
-\begin{keys}{M M-C-r}
-d       & (M d, M r) Mark this article as read and move to the next one.
-[scope]\\ 
-D       & Mark this article as read and move to the previous one. [scope]\\
-u       & (!, M !, M t) Tick this article (mark it as interesting) and move
-to the next one. [scope]\\
-U       & Tick this article and move to the previous one. [scope]\\ 
-M-u     & (M SPC, M c) Clear all marks from this article and move to the next
-one. [scope]\\ 
-M-U     & Clear all marks from this article and move to the previous one.
-[scope]\\ 
-M ?     & (?) Mark this article as dormant (only followups are
-interesting). [scope]\\ 
-M b     & Set a {\bf bookmark} in this article.\\
-M e     & (E, M x) Mark this article as {\bf expirable}. [scope]\\
-M k     & (k) {\bf Kill} all articles with the same subject then select the
-next one.\\ 
-M B     & Remove the {\bf bookmark} from this article.\\
-M C     & {\bf Catch-up} the articles that are not ticked.\\
-M D     & Show all {\bf dormant} articles (normally they are hidden unless they
-have any followups).\\
-M H     & Catch-up (mark read) this group to point ({\bf here}).\\
-M K     & (C-k) {\bf Kill} all articles with the same subject as this one.\\
-C-w     & Mark all articles between point and mark as read.\\
-M S     & (C-c M-C-s) {\bf Show} all expunged articles.\\
-M C-c   & {\bf Catch-up} all articles in this group.\\
-M M-r   & (x) Expunge all {\bf read} articles from this group.\\
-M M-D   & Hide all {\bf dormant} articles.\\
-M M-C-r & Expunge all articles having a given mark.\\
-\end{keys}
-
-\subsubsec{Mark Based on Score}
-\begin{keys}{M s m}
-M V c   & {\bf Clear} all marks from all high-scored articles. [score]\\
-M V k   & {\bf Kill} all low-scored articles. [score]\\
-M V m   & Mark all high-scored articles with a given {\bf mark}. [score]\\
-M V u   & Mark all high-scored articles as interesting (tick them). [score]\\
-\end{keys}
-
-\subsubsec{The Process Mark}
-{\samepage 
-These commands set and remove the process mark \#. You only need to use
-it if the set of articles you want to operate on is non-contiguous. Else
-use a numeric prefix.\\*
-\begin{keys}{M P R}
-M P a   & Mark {\bf all} articles (in series order).\\
-M P p   & (\#, M \#) Mark this article.\\
-M P r   & Mark all articles in the {\bf region}.\\
-M P s   & Mark all articles in the current {\bf series}.\\
-M P t   & Mark all articles in this (sub){\bf thread}.\\
-M P u   & (M-\#, M M-\#) {\bf Unmark} this article.\\
-M P R   & Mark all articles matching a {\bf regexp}.\\
-M P S   & Mark all {\bf series} that already contain a marked article.\\
-M P U   & {\bf Unmark} all articles.\\
-\end{keys}
-}}
-
-\def\Osubmap{
-\subsec{Output Articles}
-\begin{keys}{O m}
-O f     & Save this article in plain {\bf file} format. [p/p]\\
-O h     & Save this article in {\bf mh} folder format. [p/p]\\
-O m     & Save this article in {\bf mail} format. [p/p]\\
-O o     & (o, C-o) Save this article using the default article saver. [p/p]\\
-O p     & ($\mid$) Pipe this article to a shell command. [p/p]\\
-O r     & Save this article in {\bf rmail} format. [p/p]\\
-O v     & Save this article in {\bf vm} format. [p/p]\\
-\end{keys}
-}
-
-\def\Ssubmap{
-\subsec{Post, Followup, Reply, Forward, Cancel}
-{\samepage
-These commands put you in a separate post or mail buffer. After
-editing the article, send it by pressing C-c C-c.  If you are in a
-foreign group and want to post the article using the foreign server, give
-a prefix to C-c C-c.\\* 
-\begin{keys}{S O m}
-S b     & {\bf Both} post a followup to this article, and send a reply.\\
-S c     & (C) {\bf Cancel} this article (only works if it is your own).\\
-S f     & (f) Post a {\bf followup} to this article.\\
-S m     & (m) Send {\bf a} mail to some other person.\\
-S o m   & (C-c C-f) Forward this article by {\bf mail} to a person.\\
-S o p   & Forward this article as a {\bf post} to a newsgroup.\\
-S p     & (a) {\bf Post} an article to this group.\\
-S r     & (r) Mail a {\bf reply} to the author of this article.\\
-S s     & {\bf Supersede} this article with a new one (only for own
-articles).\\ 
-S u     & {\bf Uuencode} a file and post it as a series.\\
-S B     & {\bf Both} post a followup, send a reply, and include the
-original. [p/p]\\ 
-S F     & (F) Post a {\bf followup} and include the original. [p/p]\\
-S O m   & Digest these series and forward by {\bf mail}. [p/p]\\
-S O p   & Digest these series and forward as a {\bf post} to a newsgroup.
-[p/p]\\ 
-S R     & (R) Mail a {\bf reply} and include the original. [p/p]\\
-\end{keys}
-If you want to cancel or supersede an article you just posted (before it
-has appeared on the server), go to the *post-news* buffer, change
-`Message-ID' to `Cancel' or `Supersedes' and send it again with C-c C-c.
-}}
-
-\def\Tsubmap{
-\subsec{Thread Commands}
-\begin{keys}{T \#}
-T \#    & Mark this thread with the process mark.\\
-T d     & Move to the next article in this thread ({\bf down}). [distance]\\
-T h     & {\bf Hide} this (sub)thread.\\
-T i     & {\bf Increase} the score of this thread.\\
-T k     & (M-C-k) {\bf Kill} the current (sub)thread. [Negative prefix:
-tick it, positive prefix: unmark it.]\\
-T l     & (M-C-l) {\bf Lower} the score of this thread.\\
-T n     & (M-C-f) Go to the {\bf next} thread. [distance]\\
-T p     & (M-C-b) Go to the {\bf previous} thread. [distance]\\
-T s     & {\bf Show} the thread hidden under this article.\\
-T u     & Move to the previous article in this thread ({\bf up}). [distance]\\
-T H     & {\bf Hide} all threads.\\
-T S     & {\bf Show} all hidden threads.\\
-T T     & (M-C-t) {\bf Toggle} threading.\\
-\end{keys}
-}
-
-\def\Vsubmap{
-\subsec{Score (Value) Commands}
-{\samepage
-Read about Adaptive Scoring in the online info.\\*
-\begin{keys}{\bf A p m l}
-V a     & {\bf Add} a new score entry, specifying all elements.\\
-V c     & Specify a new score file as {\bf current}.\\
-V e     & {\bf Edit} the current score alist.\\
-V f     & Edit a score {\bf file} and make it the current one.\\
-V m     & {\bf Mark} all articles below a given score as read.\\
-V s     & Set the {\bf score} of this article.\\
-V t     & Display all score rules applied to this article ({\bf track}).\\
-V x     & {\bf Expunge} all low-scored articles. [score]\\
-V C     & {\bf Customize} the current score file through a user-friendly
-interface.\\ 
-V S     & Display the {\bf score} of this article.\\
-\bf A p m l& Make a scoring entry based on this article.\\
-\end{keys}
-
-The four letters stand for:\\*
-\quad \B{A}ction: I)ncrease, L)ower;\\*
-\quad \B{p}art: a)utor (from), s)ubject, x)refs (cross-posting), d)ate, l)ines,
-message-i)d, t)references (parent), f)ollowup, b)ody, h)ead (all headers);\\*
-\quad \B{m}atch type:\\*
-\qquad string: s)ubstring, e)xact, r)egexp, f)uzzy,\\*
-\qquad date: b)efore, a)t, n)this,\\*
-\qquad number: $<$, =, $>$;\\*
-\quad \B{l}ifetime: t)emporary, p)ermanent, i)mmediate.
-
-If you type the second letter in uppercase, the remaining two are assumed
-to be s)ubstring and t)emporary. 
-If you type the third letter in uppercase, the last one is assumed to be 
-t)emporary.
-
-\quad Extra keys for manual editing of a score file:\\*
-\begin{keys}{C-c C-c}
-C-c C-c & Finish editing the score file.\\
-C-c C-d & Insert the current {\bf date} as number of days.\\
-\end{keys}
-}}
-
-\def\Wsubmap{
-\subsec{Wash the Article Buffer}
-\begin{keys}{W C-c}
-W b     & Make Message-IDs and URLs in the article to mouse-clickable {\bf
-  buttons}.\\  
-W c     & Remove extra {\bf CRs} (^M) from the article.\\
-W f     & Look for and display any X-{\bf Face} headers.\\
-W l     & (w) Remove page breaks ({\bf^L}) from the article.\\
-W m     & Toggle {\bf MIME} processing.\\
-W o     & Treat {\bf overstrike} or underline (^H\_) in the article.\\
-W q     & Treat {\bf quoted}-printable in the article.\\
-W r     & (C-c C-r) Do a Caesar {\bf rotate} (rot13) on the article.\\
-W t     & (t) {\bf Toggle} the displaying of all headers.\\
-v       & Toggle permanent {\bf verbose} displaying of all headers.\\
-W w     & Do word {\bf wrap} in the article.\\
-W T e   & Convert the article timestamp to time {\bf elapsed} since sent.\\
-W T l   & Convert the article timestamp to the {\bf local} timezone.\\
-W T u   & (W T z) Convert the article timestamp to {\bf UTC} ({\bf Zulu},
-GMT).\\ 
-\end{keys}
-
-\subsubsec{Hide/Highlight Parts of the Article}
-\begin{keys}{W W C-c}
-W W a   & Hide {\bf all} unwanted parts. Calls W W h, W W s, W W C-c.\\
-W W c   & Hide article {\bf citation}.\\
-W W h   & Hide article {\bf headers}.\\
-W W s   & Hide article {\bf signature}.\\
-W W C-c & Hide article {\bf citation} using a more intelligent algorithm.\\
-%\end{keys}
-%
-%\subsubsec{Highlight Parts of the Article}
-%\begin{keys}{W H A}
-W H a   & Highlight {\bf all} parts. Calls W b, W H c, W H h, W H s.\\
-W H c   & Highlight article {\bf citation}.\\
-W H h   & Highlight article {\bf headers}.\\
-W H s   & Highlight article {\bf signature}.\\
-\end{keys}
-}
-
-\def\Xsubmap{
-\subsec{Extract Series (Uudecode etc)}
-{\samepage
-Gnus recognizes if the current article is part of a series (multipart
-posting whose parts are identified by numbers in their subjects, e.g.{}
-1/10\dots10/10) and processes the series accordingly. You can mark and
-process more than one series at a time. If the posting contains any
-archives, they are expanded and gathered in a new group.\\*
-\begin{keys}{X p}
-X b     & Un-{\bf binhex} these series. [p/p]\\
-X o     & Simply {\bf output} these series (no decoding). [p/p]\\ 
-X p     & Unpack these {\bf postscript} series. [p/p]\\
-X s     & Un-{\bf shar} these series. [p/p]\\
-X u     & {\bf Uudecode} these series. [p/p]\\
-\end{keys}
-
-Each one of these commands has four variants:\\*
-\begin{keys}{X v \bf Z}
-X   \bf z & Decode these series. [p/p]\\
-X   \bf Z & Decode and save these series. [p/p]\\
-X v \bf z & Decode and view these series. [p/p]\\
-X v \bf Z & Decode, save and view these series. [p/p]\\
-\end{keys}
-where {\bf z} or {\bf Z} identifies the decoding method (b, o, p, s, u).
-
-An alternative binding for the most-often used of these commands is\\*
-\begin{keys}{C-c C-v C-v}
-C-c C-v C-v & (X v u) Uudecode and view these series. [p/p]\\
-\end{keys}
-}}
-
-\def\Zsubmap{
-\subsec{Exit the Current Group}
-\begin{keys}{Z G}
-Z c     & (c) Mark all unticked articles as read ({\bf catch-up}) and exit.\\
-Z n     & Mark all articles as read and go to the {\bf next} group.\\
-Z C     & Mark all articles as read ({\bf catch-up}) and exit.\\
-Z E     & (Q) {\bf Exit} without updating the group information.\\
-Z G     & (M-g) Check for new articles in this group ({\bf get}).\\
-Z N     & Exit and go to {\bf the} next group.\\
-Z P     & Exit and go to the {\bf previous} group.\\
-Z R     & Exit this group, and then enter it again ({\bf reenter}).
-[Prefix: select all articles, read and unread.]\\
-Z Z     & (q, Z Q) Exit this group.\\
-\end{keys}
-}
-
-\def\ArticleMode{
-\sec{Article Mode}
-{\samepage
-% All keys for Summary mode also work in Article mode.
-The normal navigation keys work in Article mode.
-Some additional keys are:\\*
-\begin{keys}{C-c C-m}
-RET     & (middle mouse button) Activate the button at point to follow
-an URL or Message-ID.\\
-TAB     & Move the point to the next button.\\
-h       & (s) Go to the {\bf header} line of the article in the {\bf
-summary} buffer.\\ 
-C-c ^   & Get the article with the Message-ID near point.\\
-C-c C-m & {\bf Mail} reply to the address near point (prefix: include the
-original).\\ 
-\end{keys}
-}}
-
-\def\ServerMode{
-\sec{Server Mode}
-{\samepage
-To enter this mode, press `^' while in Group mode.\\*
-\begin{keys}{SPC}
-SPC     & (RET) Browse this server.\\
-a       & {\bf Add} a new server.\\
-c       & {\bf Copy} this server.\\
-e       & {\bf Edit} a server.\\
-k       & {\bf Kill} this server. [scope]\\
-l       & {\bf List} all servers.\\
-q       & Return to the group buffer ({\bf quit}).\\
-y       & {\bf Yank} the previously killed server.\\
-\end{keys}
-}}
-
-\def\BrowseServer{
-\sec{Browse Server Mode}
-{\samepage
-To enter this mode, press `B' while in Group mode.\\*
-\begin{keys}{RET}
-RET     & Enter the current group.\\
-SPC     & Enter the current group and display the first article.\\
-?       & Give a very short help message.\\
-n       & Go to the {\bf next} group. [distance]\\
-p       & Go to the {\bf previous} group. [distance]\\
-q       & (l) {\bf Quit} browse mode.\\
-u       & Subscribe to the current group. [scope]\\
-\end{keys}
-}}
+{\nopagebreak%\noindent%
+  \settowidth{\keycolwidth}{#1}%
+  \addtolength{\keycolwidth}{\tabcolsep}%
+  \addtolength{\keycolwidth}{-\columnwidth}%
+  \begin{supertabular}{@{}l@{\hspace{\tabcolsep}}p{-\keycolwidth}@{}}}%
+  {\end{supertabular}\\}
+
+%% uncomment the first definition if you do not want pagebreaks in maps
+%%\newcommand{\esamepage}{\samepage}
+\newcommand{\esamepage}{}
+
+\newcommand*{\B}[1]{{\bf#1})}    % bold l)etter
+
+\newcommand{\Title}{%
+  \begin{center}
+    {\bf\LARGE Gnus \progver\ Reference \Guide\\}
+                                %{\normalsize \Guide\ version \refver}
+  \end{center}
+  }
+
+\newcommand*{\Logo}[1]{\centerline{%
+    \makebox[\logoscale\logowidth][l]{\vbox to \logoscale\logoheight
+      {\vfill\epsfig{figure=gnuslogo-#1}}\vspace{-\baselineskip}}}}
+
+\newcommand{\Copyright}{%
+  \begin{center}
+    Copyright \copyright\ 1995 Free Software Foundation, Inc.\\*
+    Copyright \copyright\ 1995 Vladimir Alexiev
+    $<$vladimir@cs.ualberta.ca$>$.\\*
+    Copyright \copyright\ 2000 Felix Natter $<$fnatter@gmx.net$>$.\\*
+    Copyright \copyright\ 2001, 2002, 2003 \author.\\*
+    Created from the Gnus manual Copyright \copyright\ 1994 Lars Magne
+    Ingebrigtsen.\\*
+    and the Emacs Help Bindings feature (C-h b).\\*
+    Gnus logo copyright \copyright\ 1995 Luis Fernandes.\\*
+  \end{center}
+
+  Permission is granted to make and distribute copies of this reference
+  \guide{} provided the copyright notice and this permission are preserved on
+  all copies.  Please send corrections, additions and suggestions to the
+  current maintainer's email address. \Guide{} last edited on \date.
+  }
+
+\newcommand{\Notes}{%
+  \subsection*{Notes}
+  {\esamepage
+    Gnus is complex. Currently it has some 876 interactive (user-callable)
+    functions. Of these 618 are in the two major modes (Group and
+    Summary/Article). Many of these functions have more than one binding, some
+    have 3 or even 4 bindings. The total number of keybindings is 677. So in
+    order to save 40\% space, every function is listed only once on this
+    \guide, under the ``more logical'' binding. Alternative bindings are given
+    in parentheses in the beginning of the description.
+
+    Many Gnus commands are affected by the numeric prefix. Normally you enter a
+    prefix by holding the Meta key and typing a number, but in most Gnus modes
+    you don't need to use Meta since the digits are not self-inserting. The
+    prefixed behavior of commands is given in [brackets]. Often the prefix is
+    used to specify:
+
+    \quad [distance] How many objects to move the point over.
+
+    \quad [scope] How many objects to operate on (including the current one).
+
+    \quad [p/p] The ``Process/Prefix Convention'': If a prefix is given then it
+    determines how many objects to operate on. Else if there are some objects
+    marked with the process mark \#, these are operated on. Else only the
+    current object is affected.
+
+    \quad [level] A group subscribedness level. Only groups with a lower or
+    equal level will be affected by the operation. If no prefix is given,
+    `gnus-group-default-list-level' is used.  If
+    `gnus-group-use-permanent-levels', then a prefix to the `g' and `l'
+    commands will also set the default level.
+
+    \quad [score] An article score. If no prefix is given,
+    `gnus-summary-default-score' is used. \\*[\baselineskip]
+                                % some keys
+    Gnus startup-commands:
+    \begin{keys}{M-x gnus-unplugged}
+      M-x gnus           & start Gnus. \\
+      M-x gnus-no-server & start Gnus without connecting to server
+      (i.e. to read mail). \\
+    \end{keys}
+    Additionally, there are the two commands \texttt{gnus-plugged} and
+    \texttt{gnus-unplugged}, which are only used if you want to download
+    news and/or read previously downloaded news offline (see C-c C-i g Gnus
+    Unplugged RET). Note: \texttt{gnus-no-server} ignores the stuff in
+    \texttt{gnus-agent-directory}, and thus does not allow you to use Gnus
+    Unplugged.
+                                %
+    \begin{keys}{C-c C-i}
+      C-c C-i & Go to the Gnus online {\bf info}.\\
+      C-c C-b & Send a Gnus {\bf bug} report.\\
+    \end{keys}
+    }}
+
+\newcommand{\GroupLevels}{%
+  The table below assumes that you use the default Gnus levels.
+  Fill your user-specific levels in the blank cells.\\[1\baselineskip]
+  \begin{tabular}{|c|l|l|}
+    \hline
+    Level & Groups & Status \\
+    \hline
+    1 & draft/mail groups   &              \\
+    2 & mail groups         &              \\
+    3 &                     & subscribed   \\
+    4 &                     &              \\
+    5 & default list level  &              \\
+    \hline
+    6 &                     & unsubscribed \\
+    7 &                     &              \\
+    \hline
+    8 &                     & zombies      \\
+    \hline
+    9 &                     & killed       \\
+    \hline
+  \end{tabular}}
+
+\newcommand{\MarkCharacters}{%
+  {\esamepage If a command directly sets a mark, it is shown in parentheses.\\*
+    \newlength{\markcolwidth}
+    \settowidth{\markcolwidth}{` '}% widest character
+    \addtolength{\markcolwidth}{4\tabcolsep}
+    \addtolength{\markcolwidth}{-\columnwidth}
+    \newlength{\markdblcolwidth}
+    \setlength{\markdblcolwidth}{\columnwidth}
+    \addtolength{\markdblcolwidth}{-2\tabcolsep}
+    \begin{tabular}{|c|p{-\markcolwidth}|}
+      \hline
+      \multicolumn{2}{|p{\markdblcolwidth}|}{{\bf ``Read'' Marks.}
+        All these marks appear in the first column of the summary line, and so
+        are mutually exclusive.}\\ 
+      \hline
+      ` ' & (M-u, M SPC, M c) Not read.\\
+      !   & (!, M !, M t) Ticked (interesting).\\
+      ?   & (?, M ?) Dormant (only followups are interesting).\\
+      E   & (E, M e, M x) {\bf Expirable}. Only has effect in mail groups.\\
+      G   & (C, B DEL) Canceled article (or deleted in mailgroups).\\
+      \$  & (M-d, M s x, S x).  Marked as spam.\\
+      \hline\hline
+      \multicolumn{2}{|p{\markdblcolwidth}|}
+      {The marks below mean that the article
+        is read (killed, uninteresting), and have more or less the same effect.
+        Some commands however explicitly differentiate between them (e.g.\ M
+        M-C-r, adaptive scoring).}\\
+      \hline
+      r   & (d, M d, M r) Deleted (marked as {\bf read}).\\
+      C   & (M C; M C-c; M H; c, Z c; Z n; Z C) Killed by {\bf catch-up}.\\
+      F   & SOUPed article. See the manual.\\
+      O   & {\bf Old} (read in a previous session).\\
+      K   & (k, M k; C-k, M K) {\bf Killed}.\\
+      M   & Article marked as read by duplicate suppression.\\
+      Q   & Article is part of a sparse thread (see ``Threading''
+      in the manual).\\
+      R   & {\bf Read} (viewed in actuality).\\
+      X   & Killed by a kill file.\\
+      Y   & Killed due to low score.\\
+      \hline\multicolumn{2}{c}{\vspace{1ex}}\\\hline
+      \multicolumn{2}{|p{\markdblcolwidth}|}
+      {{\bf Marks not affecting visibility}}\\
+      \hline
+      \#  & (\#, M \#, M P p) Processable (will be affected by the next operation).
+      [2]\\
+      A   & {\bf Answered} (followed-up or replied). [2]\\
+      F   & Forwarded. [2]\\
+      $\ast$  & Cached. [2]\\
+      S   & Saved. [2]\\
+      N   & Recently arrived. [2]\\
+      .   & Unseen. [2]\\
+      +   & Over default score. [3]\\
+      $-$ & Under default score. [3]\\
+      $=$ & Has children (thread underneath it). Add `\%e' to
+      `gnus-summary-line-format'. [3]\\
+      \hline
+    \end{tabular}
+    }}
+
+\newcommand{\GroupModeGeneral}{%
+  \begin{keys}{C-c M-C-x}
+    RET     & (=) Enter this group. [Prefix: how many (read) articles to fetch.
+    Positive: newest articles, negative: oldest ones; non-numerical:
+    view all articles, not just unread]\\
+    M-RET   & Enter group quickly.\\
+    M-SPC   & Same as RET but does not expunge and hide dormants.\\
+    M-C-RET & Enter group without any processing, changes will not be permanent.\\
+    SPC     & Select this group and display the first (unread) article. [Same
+    prefix as above.]\\
+    ?       & Give a very short help message.\\
+    $<$     & Go to the beginning of the Group buffer.\\
+    $>$     & Go to the end of the Group buffer.\\
+    ,       & Jump to the lowest-level group with unread articles.\\
+    .       & Jump to the first group with unread articles.\\
+    \^{}      & Enter the Server buffer mode.\\
+    a       & Post an {\bf article} to a group
+              [Prefix: use group under point to find posting-style].\\
+    b       & Find {\bf bogus} groups and delete them.\\
+    c       & Mark all unticked articles in this group as read ({\bf catch-up}).
+    [p/p]\\ 
+    g       & Check the server for new articles ({\bf get}). [level]\\
+    M-g     & Check the server for new articles in this group ({\bf get}). [p/p]\\
+    j       & {\bf Jump} to a group.\\
+    m       & {\bf Mail} a message to someone
+              [Prefix: use group under point to find posting-style].\\
+    n       & Go to the {\bf next} group with unread articles. [distance]\\
+    M-n     & Go to the {\bf next} group on the same or lower level.
+    [distance]\\ 
+    p       & (DEL) Go to the {\bf previous} group with unread articles.
+    [distance]\\ 
+    M-p     & Go to the {\bf previous} group on the same or lower level. [distance]\\ 
+    q       & {\bf Quit} Gnus.\\
+    r       & Re-read the init file ({\bf reset}).\\
+    s       & {\bf Save} the `.newsrc.eld' file (and `.newsrc' if
+    `gnus-save-newsrc-file').\\ 
+    z       & Suspend (kill all buffers of) Gnus.\\
+    B       & {\bf Browse} a foreign server.\\
+    C       & Mark all articles in this group as read ({\bf Catch-up}). [p/p]\\
+    F       & {\bf Find} new groups and process them.\\
+    N       & Go to the {\bf next} group. [distance]\\
+    P       & Go to the {\bf previous} group. [distance]\\
+    Q       & {\bf Quit} Gnus without saving any startup (.newsrc) files.\\
+    R       & {\bf Restart} Gnus.\\
+    Z       & Clear the dribble buffer.\\
+    M-c     & Clear data from group (marks and list of read articles). \\
+    C-c C-s & {\bf Sort} the groups by name, number of unread articles, or level
+    (depending on `gnus-group-sort-function').\\
+    C-c C-x & Run all expirable articles in this group through the {\bf expiry} 
+    process.\\
+    C-c M-C-x & Run all articles in all groups through the {\bf expiry} process.\\
+    C-c M-g & Activate all {\bf groups}.\\
+    C-c C-i & Gnus online-manual ({\bf info}).\\
+    C-x C-t & {\bf Transpose} two groups.\\
+    H f     & Fetch this group's {\bf FAQ} (using ange-ftp).\\
+    H c     & Display this group's {\bf charter}. [Prefix: query for group]\\
+    H C     & Display this group's {\bf control message} (using
+    ange-ftp). [Prefix: query for group]\\
+    H v     & (V) Display the Gnus {\bf version} number.\\
+    H d     & (C-c C-d) Show the {\bf description} of this group
+    [Prefix: re-read from server].\\ 
+    M-d     & {\bf Describe} all groups. [Prefix: re-read from server]\\
+    D g     & Regenerate a Sieve script from group parameters.\\
+    D u     & Regenerate Sieve script and {\bf upload} to server.\\
+  \end{keys}
+  }
+
+\newcommand{\ListGroups}{%
+  {\esamepage
+    \begin{keys}{A M}
+      A d     & (C-c C-M-a) List all groups whose names or {\bf descriptions} match a regexp.\\ 
+      A k     & (C-c C-l) List all {\bf killed} groups.
+      [Prefix: look at active-file from server]\\
+      A l     & List all groups on a specific level.
+      [Prefix: also list groups with no unread articles]\\
+      A a     & (C-c C-a) List all groups whose names match a regexp
+      ({\bf apropos}).\\ 
+      A A     & List the server's active-file.\\
+      A M     & List groups that {\bf match} a regexp.\\
+      A m     & List groups that {\bf match} a regexp and have unread articles. 
+      [level]\\ 
+      A s     & (l) List all {\bf subscribed} groups with unread articles.
+      [level; 5 and lower is the default]\\
+      A u     & (L) List all groups (including read and {\bf unsubscribed}).
+      [level; 7 and lower is the default]\\
+      A z     & List all {\bf zombie} groups.\\
+      A c     & List all groups with cached articles. [level]\\
+      A ?     & List all groups with dormant articles. [level]\\
+    \end{keys}
+    }
+
+  \newcommand{\CreateEditGroups}{%
+    {\esamepage
+      The select methods are indicated in parentheses.\\*
+      \begin{keys}{G DEL}
+        G a     & Make the Gnus list {\bf archive} group. (nndir over ange-ftp)\\
+        G c     & {\bf Customize} this group's parameters.\\
+        G d     & Make a {\bf directory} group (every file must be a posting and files
+        must have numeric names). (nndir)\\
+        G D     & Enter a {\bf directory} as a (temporary) group.
+        (nneething without recording articles read)\\
+        G e     & (M-e) {\bf Edit} this group's select method.\\
+        G E     & {\bf Edit} this group's info (select method, articles read, etc).\\
+        G f     & Make a group based on a {\bf file}. (nndoc)\\
+        G h     & Make the Gnus {\bf help} (documentation) group. (nndoc)\\
+        G k     & Make a {\bf kiboze} group. (nnkiboze)\\
+        G m     & {\bf Make} a new group.\\
+        G p     & Edit this group's {\bf parameters}.\\
+        G r     & Rename this group (does not work with read-only groups!).\\
+        G u     & Create one of the groups mentioned in gnus-{\bf useful}-groups.\\
+        G v     & Add this group to a {\bf virtual} group. [p/p]\\
+        G V     & Make a new empty {\bf virtual} group. (nnvirtual)\\
+        G w     & Create ephemeral group based on web-search. [Prefix: make solid group
+        instead]\\
+        G R     & Make an {\bf RSS} group.\\
+        G DEL   & {\bf Delete} group [Prefix: delete all articles as well].\\
+        G x     & Expunge all deleted articles in an nnimap mailbox.\\
+        G l     & Edit ACL (Access Control {\bf List}) for an nnimap mailbox.\\
+      \end{keys}
+      You can also create mail-groups and read your mail with Gnus (very useful
+      if you are subscribed to mailing lists), using one of the methods
+      nnmbox, nnbabyl, nnml, nnmh, or nnfolder. Read about it in the online info
+      (C-c C-i g Reading Mail RET).
+      }}
+
+                                % TODO:
+  \newcommand{\SoupCommands}{%
+    \begin{keys}{G s w}
+      G s b   & gnus-group-brew-soup: not documented.\\
+      G s p   & gnus-soup-pack-packet: not documented.\\
+      G s r   & nnsoup-pack-replies: not documented.\\
+      G s s   & gnus-soup-send-replies: not documented.\\
+      G s w   & gnus-soup-save-areas: not documented.\\
+    \end{keys}}
+
+  \newcommand{\MarkGroups}{%
+    \begin{keys}{M m}
+      M m     & (\#) Set the process {\bf mark} on this group. [scope]\\
+      M r     & Mark all groups matching regular expression.\\
+      M u     & (M-\#) Remove the process mark from this group ({\bf unmark}).
+      [scope]\\ 
+      M U     & Remove the process mark from all groups (\textbf{umark all}).\\
+      M w     & Mark all groups in the current region. [prefix: unmark]\\
+      M b     & Mark all groups in the {\bf buffer}. [prefix: unmark]\\
+    \end{keys}}
+
+  \newcommand{\GroupTopicsGeneral}{%
+    {\esamepage
+      Topics are ``categories'' for groups. Press t in the group-buffer to
+      toggle gnus-topic-mode (C-c C-i g Group Topics RET).\\*
+      \begin{keys}{C-c C-x}
+        T n     & Prompt for topic {\bf name} and create it.\\
+        T m     & {\bf Move} the current group to some other topic [p/p].\\
+        T j     & {\bf Jump} to a topic.\\
+        T c     & {\bf Copy} the current group to some other topic [p/p].\\
+        T D     & Remove (not delete) the current group [p/p].\\
+        T M     & {\bf Move} all groups matching a regexp to a topic.\\
+        T C     & {\bf Copy} all groups matching a regexp to a topic.\\
+        T H     & Toggle {\bf hiding} of empty topics.\\
+        T r     & {\bf Rename} a topic.\\
+        T DEL   & Delete an empty topic.\\
+        T \#    & Mark all groups in the current topic with the process-mark.\\
+        T M-\#  & Remove the process-mark from all groups in the current topic.\\
+        T TAB   & (TAB) Indent current topic [Prefix: unindent].\\ 
+        M-TAB   & Unindent the current topic.\\
+        RET     & (SPC) Either unfold topic or enter group [level].\\
+        T s     & {\bf Show} the current topic. [Prefix: show permanently]\\
+        T h     & {\bf Hide} the current topic. [Prefix: hide permanently]\\
+        C-c C-x & Expire all articles in current group or topic.\\
+        C-k     & {\bf Kill} a group or topic.\\
+        C-y     & {\bf Yank} a group or topic.\\
+        A T     & List active-file using {\bf topics}.\\
+        G p     & Edit topic-{\bf parameters}.\\
+        T M-n   & Go to {\bf next} topic. [distance]\\
+        T M-p   & Go to {\bf previous} topic. [distance]\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\TopicSorting}{%
+    {\esamepage
+      \begin{keys}{T S m}
+        T S a  & Sort {\bf alphabetically}.\\
+        T S u  & Sort by number of {\bf unread} articles.\\
+        T S l  & Sort by group {\bf level}.\\
+        T S v  & Sort by group score ({\bf value}).\\
+        T S r  & Sort by group {\bf rank}.\\
+        T S m  & Sort by {\bf method}.\\
+        T S e  & Sort by {\bf server} name.\\
+        T S s  & Sort according to `gnus-group-sort-function'.\\
+      \end{keys}
+      With a prefix these commands will sort in reverse order.
+      }
+    }
+
+  \newcommand{\SubscribeKillYankGroups}{%
+    {\esamepage
+      \begin{keys}{S C-k}
+        S k     & (C-k) {\bf Kill} this group.\\
+        S l     & Set the {\bf level} of this group. [p/p]\\
+        S s     & (U) Prompt for a group and toggle its {\bf subscription}.\\
+        S t     & (u) {\bf Toggle} subscription to this group. [p/p]\\
+        S w     & (C-w) Kill all groups in the region.\\
+        S y     & (C-y) {\bf Yank} the last killed group.\\
+        S z     & Kill all {\bf zombie} groups.\\
+        S C-k   & Kill all groups on a certain level.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\SummaryModeGeneral}{%
+    {\esamepage
+      \begin{keys}{M-RET}
+        SPC     & (A SPC, A n) Select an article, scroll it one page, move to the
+        next one.\\ 
+        DEL     & (A DEL, A p, b) Scroll this article one page back. [distance]\\
+        RET     & (A RET) Scroll this article one line forward. [distance]\\
+        M-RET   & (A M-RET) Scroll this article one line backward. [distance]\\
+        =       & Expand the Summary window (fullsize).
+        [Prefix: shrink to display article window]\\
+                                %
+        \&      & Execute a command on all articles whose header matches a regexp.
+        [Prefix: move backwards]\\
+        M-\&    & Execute a command on all articles having the process mark.\\
+                                %
+        M-n     & (G M-n) Go to the {\bf next} summary line of an unread article.
+        [distance]\\ 
+        M-p     & (G M-p) Go to the {\bf previous} summary line of an unread article. 
+        [distance]\\ 
+        M-s     & {\bf Search} through all subsequent articles for a regexp.\\
+        M-r     & Search through all previous articles for a regexp.\\
+                                %
+        A P     & {\bf Postscript}-print current buffer.\\
+                                %
+        M-k     & Edit this group's {\bf kill} file.\\
+        M-K     & Edit the general {\bf kill} file.\\
+                                %
+        C-t     & Toggle {\bf truncation} of summary lines.\\
+        Y g     & Regenerate the summary-buffer.\\
+        Y c     & Insert all cached articles into the summary-buffer.\\
+                                %
+        M-C-e   & {\bf Edit} the group-parameters.\\
+        M-C-a   & Customize the group-parameters.\\
+                                %
+                                % article handling
+                                %
+        A $<$   & ($<$, A b) Scroll to the beginning of this article.\\
+        A $>$   & ($>$, A e) Scroll to the end of this article.\\
+        A s     & (s) Perform an i{\bf search} in the article buffer.\\
+                                %
+        A D     & (C-d) Un{\bf digestify} this article into a separate group.
+        [Prefix: force digest]\\
+        M-C-d   & Like C-d, but open several documents in nndoc-groups, wrapped
+        in an nnvirtual group [p/p]\\
+                                %
+        A g     & (g) (Re)fetch this article ({\bf get}). [Prefix: get raw version]\\ 
+        A r     & (\^{}, A \^{}) Fetch the parent(s) of this article.
+        [Prefix: if positive fetch \textit{n} ancestors;
+        negative: fetch only the \textit{n}th ancestor]\\
+        A t     & {\bf Translate} this article.\\
+        A R     & Fetch all articles mentioned in the {\bf References}-header.\\
+        A T     & Fetch full \textbf{thread} in which the current article appears.\\
+        M-\^{}  & Fetch the article with a given Message-ID.\\
+        S y     & {\bf Yank} the current article into an existing message-buffer.
+        [p/p]\\
+        A M     & Setup group parameters for {\bf mailing} lists from
+        headers. [Prefix: replace old settings]\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\MIMESummary}{%
+    {\esamepage
+      For the commands operating on one MIME part (a subset of gnus-article-*), a
+      prefix selects which part to operate on. If the point is placed over a
+      MIME button in the article buffer, use the corresponding bindings for the
+      article buffer instead.
+      \begin{keys}{W M w}
+        K v      & (b, W M b) {\bf View} the MIME-part.\\
+        K o      & {\bf Save} the MIME part.\\
+        K c      & {\bf Copy} the MIME part.\\
+        K e      & View the MIME part {\bf externally}.\\
+        K i      & View the MIME part {\bf internally}.\\
+        K $\mid$ & Pipe the MIME part to an external command.\\
+        K b      & Make all the MIME parts have buttons in front of them.\\
+        K m      & Try to repair {\bf multipart-headers}.\\
+        K C      & View the MIME part using a different {\bf charset}.\\
+        X m      & Save all parts matching a MIME type to a directory. [p/p]\\
+        M-t      & Toggle the buttonized display of the article buffer.\\
+        W M w    & Decode RFC2047-encoded words in the article headers.\\
+        W M c    & Decode encoded article bodies. [Prefix: prompt for charset]\\
+        W M v    & View all MIME parts in the current article.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\SortSummary}{%
+    {\esamepage
+      \begin{keys}{C-c C-s C-a}
+        C-c C-s C-a & Sort the summary-buffer by {\bf author}.\\
+        C-c C-s C-d & Sort the summary-buffer by {\bf date}.\\
+        C-c C-s C-i & Sort the summary-buffer by article score.\\
+        C-c C-s C-l & Sort the summary-buffer by amount of {\bf lines}.\\
+        C-c C-s C-c & Sort the summary-buffer by length.\\
+        C-c C-s C-n & Sort the summary-buffer by article {\bf number}.\\
+        C-c C-s C-s & Sort the summary-buffer by {\bf subject}.\\
+        C-c C-s C-r & Sort the summary-buffer {\bf randomly}.\\
+        C-c C-s C-o & Sort the summary-buffer using the default method.\\
+      \end{keys}
+      With a prefix these functions sort in reverse order.
+      }
+    }
+
+  \newcommand{\MailGroups}{% formerly \Bsubmap
+    {\esamepage
+      These commands (except `B c') are only valid in a mail group.\\*
+      \begin{keys}{B M-C-e}
+        B DEL   & (B backspace, B delete) {\bf Delete} the mail article from disk (!).
+        [p/p]\\
+        B B     & Crosspost this article to another group.\\
+        B c     & {\bf Copy} this article from any group to a mail group. [p/p]\\
+        B e     & {\bf Expire} all expirable articles in this group. [p/p]\\
+        B i     & {\bf Import} a random file into this group.\\
+        B I     & Create an empty article in this group.\\
+        B m     & {\bf Move} the article from one mail group to another. [p/p]\\
+        B p     & Query whether the article was {\bf posted} as well.\\
+        B q     & {\bf Query} where the article will end up after fancy splitting\\
+        B r     & {\bf Respool} this mail article. [p/p]\\
+        B t     & {\bf Trace} the fancy splitting patterns applied to this article.\\
+        B w     & (e) Edit this article.\\
+        B M-C-e & {\bf Expunge} (delete from disk) all expirable articles in this group
+        (!). [p/p]\\ 
+        K E     & {\bf Encrypt} article body. [p/p]\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\DraftGroup}{% formerly \Dsubmap
+    {\esamepage
+      The ``drafts''-group contains messages that have been saved but not sent
+      and rejected articles. \\*
+      \begin{keys}{B DEL}
+        D e      & \textbf{edit} message.\\
+        D s      & \textbf{Send} message. [p/p]\\
+        D S      & \textbf{Send} all messages.\\
+        D t      & \textbf{Toggle} sending (mark as unsendable).\\
+        B DEL    & \textbf{Delete} message (like in mailgroup).\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\SelectArticles}{% formerly \Gsubmap
+    {\esamepage
+      These commands select the target article. They do not understand the prefix.\\*
+      \begin{keys}{G C-n}
+        h       & Enter article-buffer.\\
+        G b     & (,) Go to the {\bf best} article (the one with highest score).\\
+        G f     & (.) Go to the {\bf first} unread article.\\
+        G n     & (n) Go to the {\bf next} unread article.\\
+        G p     & (p) Go to the {\bf previous} unread article.\\
+                                %
+        G N     & (N) Go to {\bf the} next article.\\
+        G P     & (P) Go to the {\bf previous} article.\\
+                                %
+        G C-n   & (M-C-n) Go to the {\bf next} article with the same subject.\\
+        G C-p   & (M-C-p) Go to the {\bf previous} article with the same subject.\\
+                                %
+        G l     & (l) Go to the previously read article ({\bf last-read-article}).\\
+        G o     & Pop an article off the summary history and go to it.\\
+                                %
+        G g     & Search an article via subject.\\
+        G j     & (j) Search an article via Message-Id or subject.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\ArticleModeGeneral}{%
+    {\esamepage
+      The normal navigation keys work in Article mode. Some additional keys are:\\
+      \begin{keys}{C-c RET}
+        C-c \^{} & Get the article with the Message-ID near point.\\
+        C-c RET & Send reply to address near point.\\
+        h       & Go to the \textbf{header}-line of the article in the
+        summary-buffer.\\
+        s       & Go to \textbf{summary}-buffer.\\
+        RET     & (middle mouse button) Activate the button at point to follow
+        an URL or Message-ID.\\
+        TAB     & Move the point to the next button.\\
+        M-TAB   & Move point to previous button.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\WashArticle}{% formerly \Wsubmap
+    {\esamepage
+      \begin{keys}{W W H}
+        W 6     & Translate a base64 article.\\
+        W a     & Strip certain {\bf headers} from body.\\
+        W b     & Make Message-IDs and URLs in the article mouse-clickable
+        {\bf buttons}.\\  
+        W c     & Translate CRLF-pairs to LF and then the remaining CR's to LF's.\\
+        W d     & Treat {\bf dumbquotes}.\\
+        W e     & Treat {\bf emphasized} text.\\
+        W h     & Treat {\bf HTML}.\\
+        W l     & (w) Remove page breaks ({\bf\^{}L}) from the article.\\
+        W m     & {\bf Morse} decode article.\\
+        W o     & Treat {\bf overstrike} or underline (\^{}H\_) in the article.\\
+        W p     & Verify X-{\bf PGP}-Sig header.\\
+        W q     & Treat {\bf quoted}-printable in the article.\\
+        W r     & (C-c C-r) Do a Caesar {\bf rotate} (rot13) on the article.\\
+        W s     & Verify (and decrypt) a {\bf signed} message.\\
+        W t     & (t) {\bf Toggle} display of all headers.\\
+        W u     & {\bf Unsplit} broken URLs.\\
+        W v     & (v) Toggle permanent {\bf verbose} displaying of all headers.\\
+        W w     & Do word {\bf wrap} in the article.\\
+        W B     & Add clickable {\bf buttons} to the article headers.\\
+        W C     & {\bf Capitalize} first word in each sentence.\\
+        W Q     & Fill long lines.\\
+        W Z     & Translate a HZ-encoded article.\\
+                                %
+        W G u   & {\bf Unfold} folded header lines.\\
+        W G f   & {\bf Fold} all header lines.\\
+        W G n   & Unfold {\bf Newsgroups:} and Follow-Up-To:.\\
+                                %
+        W Y c   & Repair broken {\bf citations}.\\
+        W Y a   & Repair broken {\bf attribution} lines.\\
+        W Y u   & {\bf Unwrap} broken citation lines.\\
+        W Y f   & Do a {\bf full} deuglification (W Y c, W Y a, W Y u).\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\BlankAndWhitespace}{% 
+    {\esamepage
+      \begin{keys}{W E w}
+        W E l   & Strip blank {\bf lines} from the beginning of the article.\\
+        W E m   & Replace blank lines with empty lines and remove {\bf multiple}
+        blank lines.\\
+        W E t   & Remove {\bf trailing} blank lines.\\
+        W E a   & Strip blank lines at the beginning and the end
+        (W E l, W E m and W E t).\\
+        W E A   & Strip {\bf all} blank lines.\\
+        W E s   & Strip leading blank lines from the article body.\\
+        W E e   & Strip trailing blank lines from the article body.\\
+        W E w   & Remove leading {\bf whitespace} from all headers.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\Picons}{% 
+    {\esamepage
+      \begin{keys}{W D D}
+        W D s   & (W g) Display {\bf smilies}.\\
+        W D x   & (W f) Look for and display any X-{\bf Face} headers.\\
+        W D d   & Display any Face headers.\\
+        W D n   & Toggle picons in {\bf Newsgroups} and Followup-To.\\
+        W D m   & Toggle picons in {\bf mail} headers (To and Cc).\\
+        W D f   & Toggle picons in {\bf From}.\\
+        W D D   & Remove all images from the article buffer.\\
+      \end{keys}
+      }
+    }
+
+  \newcommand{\TimeAndDate}{% 
+    {\esamepage
+      \begin{keys}{W T u}
+        W T u   & (W T z) Display the article timestamp in GMT ({\bf UT, ZULU}).\\
+        W T i   & Display the article timestamp in {\bf ISO} 8601.\\
+        W T l   & Display the article timestamp in the {\bf local} timezone.\\
+        W T s   & Display according to `gnus-article-time-format'.\\
+        W T e   & Display the time {\bf elapsed} since it was sent.\\
+        W T o   & Display the {\bf original} timestamp.\\
+        W T p   & Display the date in format that's {\bf
+          pronounceable} in English.\\        
+      \end{keys}
+      }
+    }
+
+  \newcommand{\HideHighlightArticle}{%
+    {\esamepage
+      \begin{keys}{W W C-c}
+        W W a   & Hide {\bf all} unwanted parts. Calls W W h, W W s, W W C-c.\\
+        W W h   & Hide article {\bf headers}.\\
+        W W b   & Hide {\bf boring} headers.\\
+        W W s   & Hide {\bf signature}.\\
+        W W l   & Hide {\bf list} identifiers in subject-header.\\
+        W W P   & Hide {\bf PEM} (privacy enhanced messages).\\
+        W W B   & Hide banner specified by group parameter.\\
+        W W c   & Hide {\bf citation}.\\
+        W W C-c & Hide {\bf citation} using a more intelligent algorithm.\\
+        W W C   & Hide cited text in articles that aren't roots.\\
+        W H a   & Highlight {\bf all} parts. Calls W b, W H c, W H h, W H s.\\
+        W H c   & Highlight article {\bf citations}.\\
+        W H h   & Highlight article {\bf headers}.\\
+        W H s   & Highlight article {\bf signature}.\\
+      \end{keys}
+      For all hiding-commands: A positive prefix always hides, and a negative
+      prefix will show what was previously hidden.
+      }}
+
+  \newcommand{\MIMEArticleMode}{%
+    {\esamepage
+      \begin{keys}{RET}
+        RET     & (BUTTON-2) Toggle display of the MIME object.\\
+        v       & Prompt for a method and then view object using this method.\\
+        o       & Prompt for a filename and save the MIME object.\\
+        C-o     & Prompt for a filename to save the MIME object to and remove it.\\
+        d       & {\bf Delete} the MIME object.\\
+        c       & {\bf Copy} the MIME object to a new buffer and display this buffer.\\
+        i       & Display the MIME object in this buffer.\\
+        C       & Copy the MIME object to a new buffer and display this buffer using {\bf Charset} \\
+        E       & View internally. \\
+        e       & View {\bf externally}. \\
+        t       & View the MIME object as a different {\bf type}.\\
+        p       & {\bf Print} the MIME object.\\
+        $\mid$  & Pipe the MIME object to a process.\\
+        .       & Take action on the MIME object.\\
+      \end{keys}
+      }
+    }
+
+  %% end of article mode for reading ..........................................
+
+  \newcommand{\MarkArticlesGeneral}{% formerly \Msubmap
+    {\esamepage
+      \begin{keys}{M M-C-r}
+        d       & (M d, M r) Mark this article as read and move to the next one.
+        [scope]\\ 
+        D       & Mark this article as read and move to the previous one. [scope]\\
+        !       & (u, M !, M t) Tick this article (mark it as interesting) and move
+        to the next one. [scope]\\
+        U       & Tick this article and move to the previous one. [scope]\\ 
+        M ?     & (?) Mark this article as dormant (only followups are
+        interesting). [scope]\\ 
+        M D     & Show all {\bf dormant} articles (normally they are hidden unless they
+        have any followups).\\
+        M M-D   & Hide all {\bf dormant} articles.\\
+        C-w     & Mark all articles between point and mark as read.\\
+        M-u     & (M SPC, M c) Clear all marks from this article and move to the next
+        one. [scope]\\ 
+        M-U     & Clear all marks from this article and move to the previous one.
+        [scope]\\
+                                %
+        M e     & (E, M x) Mark this article as {\bf expirable}. [scope]\\
+                                %
+        M k     & (k) {\bf Kill} all articles with the same subject then select the
+        next unread one.\\ 
+        M K     & (C-k) {\bf Kill} all articles with the same subject as this one.\\
+                                %
+        M C     & {\bf Catch-up} the articles that are not ticked and not dormant.\\
+        M C-c   & {\bf Catch-up} all articles in this group.\\
+        M H     & {\bf Catch-up} (mark read) this group to point (to-{\bf here}).\\
+                                %
+        M b     & Set a {\bf bookmark} in this article.\\
+        M B     & Remove the {\bf bookmark} from this article.\\
+                                %
+        M M-r   & (x) Expunge all {\bf read} articles from this group.\\
+        M M-C-r & Expunge all articles having a given mark.\\
+        M S     & (C-c M-C-s) {\bf Show} all expunged articles.\\
+        M M C-h & Displays some more keys doing ticking slightly differently.\\
+      \end{keys}
+      The variable `gnus-summary-goto-unread' controls what happens after a mark
+      has been set (C-x C-i g Setting Marks RET)
+      }}
+
+  \newcommand{\MarkByScore}{%
+    \begin{keys}{M V m}
+      M V c   & {\bf Clear} all marks from all high-scored articles. [score]\\
+      M V k   & {\bf Kill} all low-scored articles. [score]\\
+      M V m   & Mark all high-scored articles with a given {\bf mark}. [score]\\
+      M V u   & Mark all high-scored articles as interesting (tick them). [score]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\ProcessMark}{%
+  {\esamepage 
+    These commands set and remove the process mark (\#). You only need to use
+    it if the set of articles you want to operate on is non-contiguous. Else
+    use a numeric prefix.\\*
+    \begin{keys}{M P R}
+      M P p   & (\#, M \#) Mark this article.\\
+      M P u   & (M-\#, M M-\#) \textbf{unmark} this article.\\
+      M P b   & Mark all articles in {\bf buffer}.\\
+      M P r   & Mark all articles in the {\bf region}.\\
+      M P g   & Unmark all articles in the region.\\
+      M P R   & Mark all articles matching a {\bf regexp}.\\
+      M P G   & Unmark all articles matching a regexp.\\
+      M P t   & Mark all articles in this (sub){\bf thread}.\\
+      M P T   & Unmark all articles in this (sub){\bf thread}.\\
+      M P s   & Mark all articles in the current {\bf series}.\\
+      M P S   & Mark all {\bf series} that already contain a marked article.\\
+      M P a   & Mark {\bf all} articles (in series order).\\
+      M P U   & \textbf{unmark} all articles.\\
+      M P i   & {\bf Invert} the list of process-marked articles.\\
+      M P k   & Push the current process-mark set onto stack and unmark
+      all articles.\\
+      M P y   & Pop process-mark set from stack and restore it.\\
+      M P w   & Push process-mark set on the stack.\\
+      M P v   & Mark all articles with score over the default score. [Prefix: score]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\Limiting}{%
+  {\esamepage
+    \begin{keys}{/M}
+      //   & (/s) Limit the summary-buffer to articles matching {\bf subject}.\\
+      /a   & Limit the summary-buffer to articles matching {\bf author}.\\
+      /x   & Limit depending on ``extra'' headers.\\
+      /u   & (x) Limit to {\bf unread} articles.
+      [Prefix: also exclude ticked and dormant articles]\\
+      /.   & Limit to unseen articles.\\
+      /m   & Limit to articles marked with specified {\bf mark}.\\
+      /t   & Ask for a number and exclude articles younger than that many days.
+      [Prefix: exclude older articles]\\
+      /n   & Limit to current article. [p/p]\\
+      /w   & Pop the previous limit off the stack and restore it.
+      [Prefix: pop all limits]\\
+      /v   & Limit to score. [score]\\
+      /E   & (M S) Include all expunged articles in the limit.\\
+      /D   & Include all dormant articles in the limit.\\
+      /*   & Limit to cached articles.\\
+      Y C  & Include all cached articles in the limit.\\
+      /d   & Exclude all dormant articles from the limit.\\
+      /M   & Exclude all marked articles.\\
+      /T   & Include all articles from the current thread in the limit.\\
+      /c   & Exclude all dormant articles that have no children from the limit.\\
+      /C   & Mark all excluded unread articles as read.
+      [Prefix: also mark ticked and dormant articles]\\
+      /o   & Insert all {\bf old} articles. [Prefix: how many]\\
+      /N   & Insert all {\bf new} articles.\\
+      /p   & Limit to articles {\bf predicated} in the `display' group parameter.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\OutputArticles}{% formerly \Osubmap
+  {\esamepage
+    \begin{keys}{O m}
+      O o     & (o, C-o) Save this article using the default article saver. [p/p]\\
+      O b     & Save this article's {\bf body} in plain file format [p/p]\\
+      O f     & Save this article in plain {\bf file} format. [p/p]\\
+      O F     & like O f, but overwrite file's contents. [p/p]\\
+      O h     & Save this article in {\bf mh} folder format. [p/p]\\
+      O m     & Save this article in {\bf mail} format. [p/p]\\
+      O r     & Save this article in {\bf rmail} format. [p/p]\\
+      O v     & Save this article in {\bf vm} format. [p/p]\\
+      O p     & ($\mid$) {\bf Pipe} this article to a shell command. [p/p]\\
+      O P     & \textbf{Print} this article using Muttprint. [p/p]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\PostReplyetc}{% formerly \Ssubmap
+  {\esamepage
+    These commands put you in a separate news or mail buffer. See the section
+    about composing messages for more information.\\*
+                                %After
+                                %editing the article, send it by pressing C-c C-c.  If you are in a
+                                %foreign group and want to post the article using the foreign server, give
+                                %a prefix to C-c C-c.\\* 
+    \begin{keys}{S O m}
+      S p     & (a) {\bf Post} an article to this group.\\
+      S f     & (f) Post a {\bf followup} to this article.\\
+      S F     & (F) Post a {\bf followup} and include the original. [p/p]\\
+      S o p   & Forward this article as a {\bf post} to a newsgroup.\\
+      S M-c   & Send a complaint about excessive crossposting to the author of this
+      article. [p/p]\\
+                                %
+      S m     & (m) Send a {\bf mail} to some other person.\\
+      S r     & (r) Mail a {\bf reply} to the author of this article.\\
+      S R     & (R) Mail a {\bf reply} and include the original. [p/p]\\
+      S B r   & Like S r but ignore the Reply-To: header.\\
+      S B R   & Like S R but ignore the Reply-To: header.\\
+      S w     & Mail a {\bf wide} reply to this article.\\
+      S W     & Mail a {\bf wide} reply to this article and include
+      the original.\\
+      S v     & Mail a {\bf very} wide reply to this article.\\
+      S V     & Mail a {\bf very} wide reply to this article and include the original.\\
+      S o m   & (C-c C-f) Forward this article by {\bf mail} to a person.\\
+      S D b   & Resend {\bf bounced} mail.\\
+      S D r   & {\bf Resend} mail to a different person.\\
+      S D e   & {\bf Edit} and resend.\\
+                                %
+      S n     & Post a followup via {\bf news} even if you got the message
+      through mail.\\
+      S N     & Post a followup via {\bf news} and include the original mail.
+      [p/p]\\
+                                %
+      S c     & (C) {\bf Cancel} this article (only works if it is
+      your own). [p/p]\\
+      S s     & {\bf Supersede} this article with a new one (only for own
+      articles).\\
+                                %
+      S O m   & Digest these series and forward by {\bf mail}. [p/p]\\
+      S O p   & Digest these series and forward as a {\bf post} to a newsgroup.
+      [p/p]\\ 
+                                %
+      S u     & {\bf Uuencode} a file and post it as a series.\\
+    \end{keys}
+    If you want to cancel or supersede an article you just posted (before it
+    has appeared on the server), go to the *post-news* buffer, change
+    `Message-ID' to `Cancel' or `Supersedes' and send it again with C-c C-c.
+    }}
+
+\newcommand{\Threading}{% formerly \Tsubmap
+  {\esamepage
+    \begin{keys}{T M-\#}
+      T \#    & Mark this thread with the process mark.\\
+      T M-\#  & Remove process-marks from this thread.\\
+                                %
+      T t     & Re-{\bf thread} the current article's thread.\\
+      T \^{}  & Make the current article child of the marked (or previous) article.\\
+                                % movement
+      T n     & (M-C-f, M-down) Go to the {\bf next} thread. [distance]\\
+      T p     & (M-C-b, M-up) Go to the {\bf previous} thread. [distance]\\
+      T d     & {\bf Descend} this thread. [distance]\\
+      T u     & Ascend this thread ({\bf up}-thread). [distance]\\
+      T o     & Go to the top of this thread.\\
+                                %
+      T s     & {\bf Show} the thread hidden under this article.\\
+      T h     & {\bf Hide} this (sub)thread.\\
+                                %
+      T i     & {\bf Increase} the score of this thread.\\
+      T l     & (M-C-l) {\bf Lower} the score of this thread.\\
+                                %
+      T k     & (M-C-k) {\bf Kill} the current (sub)thread. [Negative prefix:
+      tick it, positive prefix: unmark it.]\\
+                                %
+      T H     & {\bf Hide} all threads.\\
+      T S     & {\bf Show} all hidden threads.\\
+      T T     & (M-C-t) {\bf Toggle} threading.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\Scoring}{% formerly \Vsubmap
+  {\esamepage
+    Read about Adaptive Scoring in the online info.\\*
+    \begin{keys}{\bf A p m l}
+      V a     & {\bf Add} a new score entry, specifying all elements.\\
+      V c     & Specify a new score file as {\bf current}.\\
+      V e     & {\bf Edit} the current score alist.\\
+      V f     & Edit a score {\bf file} and make it the current one.\\
+      V m     & {\bf Mark} all articles below a given score as read.\\
+      V s     & Set the {\bf score} of this article.\\
+      V t     & Display all score rules applied to this article ({\bf track}).\\
+      W w     & List {\bf words} used in scoring.\\
+      V x     & {\bf Expunge} all low-scored articles. [score]\\
+      V C     & {\bf Customize} the current score file through a user-friendly
+      interface.\\
+      V F     & {\bf Flush} the cache of score files.\\
+      V R     & {\bf Re-score} the summary buffer.\\
+      V S     & Display the {\bf score} of this article.\\
+      \bf A p m l& Make a scoring entry based on this article.\\
+    \end{keys}
+    The four letters stand for:\\*
+    \quad \B{A}ction: I)ncrease, L)ower;\\*
+    \quad \B{p}art: a)uthor (from), s)ubject, x)refs (cross-posting), d)ate, l)ines,
+    message-i)d, t)references (parent), f)ollowup, b)ody, h)ead (all headers);\\*
+    \quad \B{m}atch type:\\*
+    \qquad string: s)ubstring, e)xact, r)egexp, f)uzzy,\\*
+    \qquad date: b)efore, a)t, n)this,\\*
+    \qquad number: $<$, =, $>$;\\*
+    \quad \B{l}ifetime: t)emporary, p)ermanent, i)mmediate.
+
+    If you type the second letter in uppercase, the remaining two are assumed
+    to be s)ubstring and t)emporary. 
+    If you type the third letter in uppercase, the last one is assumed to be 
+    t)emporary.
+
+    \quad Extra keys for manual editing of a score file:\\*
+    \begin{keys}{C-c C-c}
+      C-c C-c & Finish editing the score file.\\
+      C-c C-d & Insert the current {\bf date} as number of days.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\ExtractSeries}{% formerly \Xsubmap
+  {\esamepage
+    Gnus recognizes if the current article is part of a series (multipart
+    posting whose parts are identified by numbers in their subjects, e.g.{}
+    1/10\dots10/10) and processes the series accordingly. You can mark and
+    process more than one series at a time. If the posting contains any
+    archives, they are expanded and gathered in a new group.\\*
+    \begin{keys}{X p}
+      X b     & Un-{\bf binhex} these series. [p/p]\\
+      X o     & Simply {\bf output} these series (no decoding). [p/p]\\ 
+      X p     & Unpack these {\bf postscript} series. [p/p]\\
+      X s     & Un-{\bf shar} these series. [p/p]\\
+      X u     & {\bf Uudecode} these series. [p/p]\\
+    \end{keys}
+
+    Each one of these commands has four variants:\\*
+    \begin{keys}{X v \bf Z}
+      X   \bf z & Decode these series. [p/p]\\
+      X   \bf Z & Decode and save these series. [p/p]\\
+      X v \bf z & Decode and view these series. [p/p]\\
+      X v \bf Z & Decode, save and view these series. [p/p]\\
+    \end{keys}
+    where {\bf z} or {\bf Z} identifies the decoding method (b, o, p, s, u).
+
+    An alternative binding for the most-often used of these commands is\\*
+    \begin{keys}{C-c C-v C-v}
+      C-c C-v C-v & (X v u) Uudecode and view these series. [p/p]\\
+    \end{keys}
+    }}
+
+\newcommand{\ExitSummary}{% formerly \Zsubmap
+  {\esamepage
+    \begin{keys}{Z G}
+      Z Z     & (q, Z Q) Exit this group.\\
+      Z E     & (Q) {\bf Exit} without updating the group information.\\
+                                %
+      Z c     & (c) Mark all unticked articles as read ({\bf catch-up}) and exit.\\
+      Z C     & Mark all articles as read ({\bf catch-up}) and exit.\\
+                                %
+      Z n     & Mark all articles as read and go to the {\bf next} group.\\
+      Z N     & Exit and go to {\bf the} next group.\\
+      Z P     & Exit and go to the {\bf previous} group.\\
+                                %
+      Z G     & (M-g) Check for new articles in this group ({\bf get}).\\
+      Z R     & (C-x C-s) Exit this group, and then enter it again ({\bf reenter}).
+      [Prefix: select all articles, read and unread.]\\
+      Z s     & Update and save the dribble buffer. [Prefix: save .newsrc* as well]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\MsgCompositionGeneral}{%
+  Press C-c ? in the composition-buffer to get this information.\\*
+  {\esamepage
+    \begin{keys}{C-c C-m}
+                                % sending
+      C-c C-c & Send message and exit. [Prefix: send via foreign server]\\
+      C-c C-s & Send message. [Prefix: send via foreign server]\\
+      C-c C-d & Don't send message (save as \textbf{draft}).\\
+      C-c C-k & \textbf{Kill} message-buffer.\\
+      C-c C-m & {\bf Mail} reply to the address near point.
+      [Prefix: include the original]\\
+                                % modify headers/body
+      C-c C-o & Sort headers.\\
+      C-c C-e & \textbf{Elide} region.\\
+      C-c C-v & Kill everything outside region.\\
+      C-c C-r & Do a \textbf{Rot-13} on the body.\\
+      C-c C-w & Insert signature (from `message-signature-file').\\
+      C-c C-z & Kill everything up to signature.\\
+      C-c C-y & \textbf{Yank} original message.\\
+      C-c C-q & Fill the yanked message.\\
+      C-c M-C-y & \textbf{Yank} a buffer and quote it.\\
+      M-RET   & Insert four newlines and format quoted text. [Prefix:
+      justify as well]\\
+      C-c M-r & \textbf{Rename} message buffer. [Prefix: ask for new name]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\MsgCompositionMovementArticle}{%
+  The following functions create the header-field if necessary.\\*
+  {\esamepage
+    \begin{keys}{C-c C-f C-u}
+      C-c TAB & Move to \textbf{signature}.\\
+      C-c C-b & Move to \textbf{body}.\\
+      C-c C-f C-t & (C-c C-t) Move to \textbf{To:}.\\
+      C-c C-f C-c & Move to \textbf{Cc:}.\\
+      C-c C-f C-b & Move to \textbf{Bcc:}.\\
+      C-c C-f C-w & Move to \textbf{Fcc:}.\\
+      C-c C-f C-s & Move to \textbf{Subject:}.\\
+      C-c C-f C-r & Move to \textbf{Reply-To:}.\\
+      C-c C-f C-f & Move to \textbf{Followup-To:}.\\
+      C-c C-f C-n & (C-c C-n) Move to \textbf{Newsgroups:}.\\
+      C-c C-f C-u & Move to \textbf{Summary:}.\\
+      C-c C-f C-k & Move to \textbf{Keywords:}.\\
+      C-c C-f C-d & Move to \textbf{Distribution:}.\\
+      C-c C-f C-m & Move to \textbf{Mail-Followup-To:}.\\
+      C-c C-f C-o & Move to \textbf{From:}.\\
+      C-c C-f C-a & Insert a reasonable \textbf{Mail-Followup-To:} for
+      an unsubscribed list. [Prefix: include addresses in \textbf{Cc:}]\\
+      C-c C-f TAB & (C-c C-u) Move to \textbf{Importance:}.\\
+      C-c M-n     & Insert \textbf{Disposition-Notification-To:}
+      (request receipt).\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\MsgCompositionMML}{%
+  {\esamepage
+    \begin{keys}{C-c C-m P}
+      C-c C-m f   & (C-c C-a) Attach \textbf{file}.\\
+      C-c C-m b   & Attach contents of \textbf{buffer}.\\
+      C-c C-m e   & Attach \textbf{external} file (ftp..).\\
+      C-c C-m P   & Create MIME-\textbf{preview} (new
+      buffer). [Prefix: show raw MIME preview]\\
+      C-c C-m v   & \textbf{Validate} article.\\
+      C-c C-m p   & Insert \textbf{part}.\\
+      C-c C-m m   & Insert \textbf{multi}-part.\\
+      C-c C-m q   & \textbf{Quote} region.\\
+      C-c C-m c s & Encrypt message using \textbf{S/MIME}.\\
+      C-c C-m c o & Encrypt message using PGP.\\
+      C-c C-m c p & Encrypt message using \textbf{PGP/MIME}.\\
+      C-c C-m s s & Sign message using \textbf{S/MIME}.\\
+      C-c C-m s o & Sign message using PGP.\\
+      C-c C-m s p & Sign message using \textbf{PGP/MIME}.\\
+      C-c C-m C-n & Remove security related MML tags from message.\\
+                                % TODO: narrow headers (C-c C-m n) ?
+    \end{keys}
+    }
+  }
+
+%% TODO:
+\newcommand{\ServerMode}{%
+  {\esamepage
+    To enter this mode, press \^{} while in Group mode.\\*
+    \begin{keys}{SPC}
+      SPC     & (RET) Browse this server.\\
+      a       & {\bf Add} a new server.\\
+      c       & {\bf Copy} this server.\\
+      e       & {\bf Edit} a server.\\
+      k       & {\bf Kill} this server. [scope]\\
+      l       & {\bf List} all servers.\\
+      q       & Return to the group buffer ({\bf quit}).\\
+      s       & Request that the server scan its sources for new articles.\\
+      g       & Request that the server regenerate its data.\\
+      y       & {\bf Yank} the previously killed server.\\
+      O       & Try to {\bf open} a connection to this server.\\
+      C       & {\bf Close} connection to this server.\\
+      D       & Mark this server as unreachable ({\bf deny}).\\
+      M-o     & {\bf Open} the connection to all servers.\\
+      M-c     & {\bf Close} the connection to all servers.\\
+      R       & Make all denied servers into closed servers.\\
+      L       & Set server status to offline.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\BrowseServer}{%
+  {\esamepage
+    To enter this mode, press `B' while in Group mode.\\*
+    \begin{keys}{RET}
+      RET     & Enter the current group.\\
+      SPC     & Enter the current group and display the first article.\\
+      ?       & Give a very short help message.\\
+      n       & Go to the {\bf next} group. [distance]\\
+      p       & Go to the {\bf previous} group. [distance]\\
+      q       & (l) {\bf Quit} browse mode.\\
+      u       & Subscribe to the current group. [scope]\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\GroupUnplugged}{%
+  {\esamepage
+    \begin{keys}{J S}
+      J j & Toggle plugged-state.\\
+      J s & Fetch articles from all groups for offline-reading.\\
+      J u & Fetch all eligible articles from this group.\\
+      J S & \textbf{Send} all sendable messages in the drafts group.\\
+                                %
+      J c & Enter \textbf{category} buffer.\\
+      J a & \textbf{Add} this group to an Agent category [p/p].\\
+      J r & \textbf{Remove} this group from its Agent category [p/p].\\
+      J Y & Synchronize flags changed while unplugged with remote server.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\SummaryUnplugged}{%
+  {\esamepage
+    \begin{keys}{J M-\#}
+      J \#   & \textbf{Mark} the article for downloading.\\
+      J M-\# & \textbf{Unmark} the article for downloading.\\
+      @      & \textbf{Toggle} whether to download the article.\\
+      J c    & Mark all undownloaded articles as read (\textbf{catch-up}).\\
+      J u    & Download all downloadable articles from group.\\
+    \end{keys}
+    }
+  }
+
+\newcommand{\ServerUnplugged}{%
+  {\esamepage
+    \begin{keys}{J a}
+      J a & \textbf{Add} the current server to the list of servers covered
+      by the agent.\\
+      J r & \textbf{Remove} the current server from the list of servers covered
+      by the agent.\\
+    \end{keys}
+    }
+  }
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "refcard.tex"
+%%% End:
diff --git a/texi/herds/convol11.pnm b/texi/herds/convol11.pnm
new file mode 100644 (file)
index 0000000..2f21812
--- /dev/null
@@ -0,0 +1,14 @@
+P2
+11 11
+242
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
+122 122 122 122 122 122 122 122 122 122 122 
diff --git a/texi/herds/convol5.pnm b/texi/herds/convol5.pnm
new file mode 100644 (file)
index 0000000..e164bd9
--- /dev/null
@@ -0,0 +1,8 @@
+P2
+5 5
+50
+26 26 26 26 26
+26 26 26 26 26
+26 26 26 26 26
+26 26 26 26 26
+26 26 26 26 26
diff --git a/texi/herds/gnus-herd-bw.png b/texi/herds/gnus-herd-bw.png
new file mode 100644 (file)
index 0000000..8ed5904
Binary files /dev/null and b/texi/herds/gnus-herd-bw.png differ
diff --git a/texi/herds/gnus-herd-new.png b/texi/herds/gnus-herd-new.png
new file mode 100644 (file)
index 0000000..b0dacd1
Binary files /dev/null and b/texi/herds/gnus-herd-new.png differ
diff --git a/texi/herds/new-herd-1.png b/texi/herds/new-herd-1.png
new file mode 100644 (file)
index 0000000..775d493
Binary files /dev/null and b/texi/herds/new-herd-1.png differ
diff --git a/texi/herds/new-herd-2.png b/texi/herds/new-herd-2.png
new file mode 100644 (file)
index 0000000..19b2fbc
Binary files /dev/null and b/texi/herds/new-herd-2.png differ
diff --git a/texi/herds/new-herd-3.png b/texi/herds/new-herd-3.png
new file mode 100644 (file)
index 0000000..1d36d23
Binary files /dev/null and b/texi/herds/new-herd-3.png differ
diff --git a/texi/herds/new-herd-4.png b/texi/herds/new-herd-4.png
new file mode 100644 (file)
index 0000000..23ccb23
Binary files /dev/null and b/texi/herds/new-herd-4.png differ
diff --git a/texi/herds/new-herd-5.png b/texi/herds/new-herd-5.png
new file mode 100644 (file)
index 0000000..aa85f31
Binary files /dev/null and b/texi/herds/new-herd-5.png differ
diff --git a/texi/herds/new-herd-6.png b/texi/herds/new-herd-6.png
new file mode 100644 (file)
index 0000000..df103ed
Binary files /dev/null and b/texi/herds/new-herd-6.png differ
diff --git a/texi/herds/new-herd-7.png b/texi/herds/new-herd-7.png
new file mode 100644 (file)
index 0000000..c5e29a7
Binary files /dev/null and b/texi/herds/new-herd-7.png differ
diff --git a/texi/herds/new-herd-8.png b/texi/herds/new-herd-8.png
new file mode 100644 (file)
index 0000000..94dea5a
Binary files /dev/null and b/texi/herds/new-herd-8.png differ
diff --git a/texi/herds/new-herd-9.png b/texi/herds/new-herd-9.png
new file mode 100644 (file)
index 0000000..dc26eb4
Binary files /dev/null and b/texi/herds/new-herd-9.png differ
diff --git a/texi/herds/new-herd-section.png b/texi/herds/new-herd-section.png
new file mode 100644 (file)
index 0000000..662a982
Binary files /dev/null and b/texi/herds/new-herd-section.png differ
diff --git a/texi/herds/new-herd.png b/texi/herds/new-herd.png
new file mode 100644 (file)
index 0000000..c021e9b
Binary files /dev/null and b/texi/herds/new-herd.png differ
diff --git a/texi/herds/new-herd2.png b/texi/herds/new-herd2.png
new file mode 100644 (file)
index 0000000..6e1a8fd
Binary files /dev/null and b/texi/herds/new-herd2.png differ
diff --git a/texi/infohack.el b/texi/infohack.el
new file mode 100644 (file)
index 0000000..89bad3f
--- /dev/null
@@ -0,0 +1,200 @@
+;;; infohack.el --- a hack to format info file.
+;; Copyright (C)  2001  Free Software Foundation, Inc.
+
+;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
+;; Keywords: info
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; Code:
+
+(let ((default-directory (expand-file-name "../lisp/")))
+  ;; Adjust `load-path' for APEL.
+  (load-file "dgnushack.el")
+  ;; Replace "./" with "../lisp/" in `load-path'.
+  (setq load-path (mapcar 'expand-file-name load-path)))
+(load-file (expand-file-name "ptexinfmt.el" "./"))
+
+(defun infohack-remove-unsupported ()
+  (goto-char (point-min))
+  (while (re-search-forward "@\\(end \\)?ifnottex" nil t)
+    (replace-match ""))
+  (goto-char (point-min))
+  (while (search-forward "\n@iflatex\n" nil t)
+    (delete-region (1+ (match-beginning 0))
+                  (search-forward "\n@end iflatex\n"))))
+
+(defun infohack (file)
+  (let ((dest-directory default-directory)
+       (max-lisp-eval-depth (max max-lisp-eval-depth 600))
+       coding-system)
+    (find-file file)
+    (setq buffer-read-only nil)
+    (setq coding-system (if (boundp 'buffer-file-coding-system)
+                           buffer-file-coding-system
+                         file-coding-system))
+    (infohack-remove-unsupported)
+    (texinfo-every-node-update)
+    (texinfo-format-buffer t) ;; Don't save any file.
+    (setq default-directory dest-directory)
+    (setq buffer-file-name
+         (expand-file-name (file-name-nondirectory buffer-file-name)
+                           default-directory))
+    (setq buffer-file-coding-system coding-system
+         file-coding-system coding-system)
+    (if (> (buffer-size) 100000)
+       (Info-split))
+    (save-buffer)))
+
+(eval-and-compile
+  (when (string-match "windows-nt\\|os/2\\|emx\\|cygwin"
+                      (symbol-name system-type))
+    (defun subst-char-in-region (START END FROMCHAR TOCHAR &optional NOUNDO)
+      "From START to END, replace FROMCHAR with TOCHAR each time it occurs.
+If optional arg NOUNDO is non-nil, don't record this change for undo
+and don't mark the buffer as really changed.
+Both characters must have the same length of multi-byte form."
+      (let ((original-buffer-undo-list buffer-undo-list)
+            (modified (buffer-modified-p)))
+        (if NOUNDO
+            (setq buffer-undo-list t))
+        (goto-char START)
+        (let ((from (char-to-string FROMCHAR))
+              (to (char-to-string TOCHAR)))
+          (while (search-forward from END t)
+            (replace-match to t t)))
+        (if NOUNDO
+            (progn (setq buffer-undo-list original-buffer-undo-list)
+                   (set-buffer-modidifed-p modified)))))))
+
+(defun batch-makeinfo ()
+  "Emacs makeinfo in batch mode."
+  (infohack-texi-format (car command-line-args-left)
+                       (car (cdr command-line-args-left)))
+  (setq command-line-args-left nil))
+
+\f
+(require 'bytecomp)
+
+(defun infohack-texi-format (file &optional addsuffix)
+  (let ((auto-save-default nil)
+       (find-file-run-dired nil)
+       coding-system-for-write
+       output-coding-system
+       (error 0))
+    (condition-case err
+       (progn
+         (find-file file)
+         (setq buffer-read-only nil)
+         (buffer-disable-undo (current-buffer))
+         (if (boundp 'MULE)
+             (setq output-coding-system file-coding-system)
+           (setq coding-system-for-write buffer-file-coding-system))
+         ;; process @include before updating node
+         ;; This might produce some problem if we use @lowersection or
+         ;; such.
+         (let ((input-directory default-directory)
+               (texinfo-command-end))
+           (while (re-search-forward "^@include" nil t)
+             (setq texinfo-command-end (point))
+             (let ((filename (concat input-directory
+                                     (texinfo-parse-line-arg))))
+               (re-search-backward "^@include")
+               (delete-region (point) (save-excursion
+                                        (forward-line 1)
+                                        (point)))
+               (message "Reading included file: %s" filename)
+               (save-excursion
+                 (save-restriction
+                   (narrow-to-region
+                    (point) (+ (point)
+                               (car (cdr (insert-file-contents filename)))))
+                   (goto-char (point-min))
+                   ;; Remove `@setfilename' line from included file,
+                   ;; if any, so @setfilename command not duplicated.
+                   (if (re-search-forward "^@setfilename"
+                                          (save-excursion
+                                            (forward-line 100)
+                                            (point))
+                                          t)
+                       (progn
+                         (beginning-of-line)
+                         (delete-region (point) (save-excursion
+                                                  (forward-line 1)
+                                                  (point))))))))))
+         ;; Remove ignored areas.
+         (goto-char (point-min))
+         (while (re-search-forward "^@ignore[\t\r ]*$" nil t)
+           (delete-region (match-beginning 0)
+                          (if (re-search-forward
+                               "^@end[\t ]+ignore[\t\r ]*$" nil t)
+                              (1+ (match-end 0))
+                            (point-max))))
+         ;; Remove unsupported commands.
+         (infohack-remove-unsupported)
+         ;; Add suffix if it is needed.
+         (goto-char (point-min))
+         (when (and addsuffix
+                    (re-search-forward "^@setfilename[\t ]+\\([^\t\n ]+\\)"
+                                       nil t)
+                    (not (string-match "\\.info$" (match-string 1))))
+           (insert ".info"))
+         (texinfo-mode)
+         (texinfo-every-node-update)
+         (set-buffer-modified-p nil)
+         (message "texinfo formatting %s..." file)
+         (if (featurep 'mule)
+             ;; Encode messages to terminal.
+             (let ((si:message (symbol-function 'message)))
+               (fset 'message
+                     (byte-compile
+                      (if (boundp 'MULE)
+                          `(lambda (fmt &rest args)
+                             (funcall ,si:message "%s"
+                                      (code-convert-string
+                                       (apply 'format fmt args)
+                                       '*internal* '*junet*)))
+                        `(lambda (fmt &rest args)
+                           (funcall ,si:message "%s"
+                                    (encode-coding-string
+                                     (apply 'format fmt args)
+                                     'iso-2022-7bit))))))
+               (unwind-protect
+                   (texinfo-format-buffer nil)
+                 (fset 'message si:message)))
+           (texinfo-format-buffer nil))
+         (if (buffer-modified-p)
+             (progn (message "Saving modified %s" (buffer-file-name))
+                    (save-buffer))))
+      (error
+       (message ">> Error: %s" (prin1-to-string err))
+       (message ">>  point at")
+       (let ((s (buffer-substring (point) (min (+ (point) 100) (point-max))))
+            (tem 0))
+        (while (setq tem (string-match "\n+" s tem))
+          (setq s (concat (substring s 0 (match-beginning 0))
+                          "\n>>  "
+                          (substring s (match-end 0)))
+                tem (1+ tem)))
+        (message ">>  %s" s))
+       (setq error 1)))
+    (kill-emacs error)))
+
+;;; infohack.el ends here
diff --git a/texi/message-ja.texi b/texi/message-ja.texi
new file mode 100644 (file)
index 0000000..ee6233d
--- /dev/null
@@ -0,0 +1,2263 @@
+\input texinfo
+
+@setfilename message-ja
+@settitle T-gnus 6.16 Message Manual
+@synindex fn cp
+@synindex vr cp
+@synindex pg cp
+@dircategory Emacs
+@direntry
+* Message-ja: (message-ja).   Mail and news composition mode that goes
+                              with Gnus (Japanese).
+@end direntry
+@iftex
+@finalout
+@end iftex
+@setchapternewpage odd
+
+@ifnottex
+
+This file documents Message, the Emacs message composition mode.
+
+\e$B$3$N%U%!%$%k$O\e(B Emacs \e$B$N%a%C%;!<%8:n@.%b!<%I$G$"$k\e(B Message \e$B$K4X$9$k@bL@J8\e(B
+\e$B=q$G$9!#\e(B
+
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License''.
+
+\e$B$3$NJ8=q$r!"%U%j!<%=%U%H%&%'%":bCDH/9T$N\e(B GNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q\e(B
+\e$BBh\e(B 1.1 \e$BHG$^$?$O$=$l0J9_$NHG$,Dj$a$k>r7o$N2<$GJ#@=!"G[I[!"$"$k$$$OJQ99$9\e(B
+\e$B$k$3$H$r5v2D$7$^$9!#JQ99IT2DItJ,$O;XDj$7$^$;$s!#!V\e(BA GNU Manual\e$B!W$OI=I=;f\e(B
+\e$B%F%-%9%H!"0J2<$N\e(B (a) \e$B$ON"I=;f%F%-%9%H$G$9!#$3$NMxMQ5vBz7@Ls=q$NJ#<L$O\e(B
+\e$B!V\e(BEmacs manual\e$B!W$N!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$H$$$&>O$K4^$^$l$F$$$^\e(B
+\e$B$9!#\e(B
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+(a) FSF \e$B$NN"I=;f%F%-%9%H\e(B:\e$B!V$"$J$?$K$O$3$N\e(B GNU Manual \e$B$r\e(B GNU \e$B%=%U%H%&%'%"\e(B
+\e$B$N$h$&$KJ#@=$7$?$jJQ99$9$k<+M3$,$"$j$^$9!#J#@=$O%U%j!<%=%U%H%&%'%":bCD$K\e(B
+\e$B$h$C$F=PHG$5$l$^$7$?!#\e(B(\e$B%U%j!<%=%U%H%&%'%":bCD$O\e(B) GNU \e$B$N3+H/$N$?$a$KI,MW\e(B
+\e$B$J;q6b$r=8$a$F$$$^$9!#!W\e(B
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+
+\e$B$3$NJ8=q$O!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$K4p$E$$$FG[I[$5$l$?<}=8Cx:nJ*\e(B
+\e$B$N0lIt$G$9!#$b$7$"$J$?$,$3$NJ8=q$r<}=8Cx:nJ*$+$iJ,N%$7$FG[I[$7$?$$$H$-$O!"\e(B
+\e$B7@Ls=q$NBh\e(B 6 \e$B9`$K5-=R$5$l$F$$$k$h$&$K!"J8=q$K7@Ls=q$NJ#<L$rIU2C$9$k$3$H\e(B
+\e$B$K$h$C$F!"9T$J$&$3$H$,$G$-$^$9!#\e(B
+@end ifnottex
+
+@tex
+
+@titlepage
+@title T-gnus 6.16 Message Manual
+
+@author by Lars Magne Ingebrigtsen
+@translated by members of Semi-gnus mailing-list
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+     Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being none, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+\e$B$3$NJ8=q$r!"%U%j!<%=%U%H%&%'%":bCDH/9T$N\e(B GNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q\e(B
+\e$BBh\e(B 1.1 \e$BHG$^$?$O$=$l0J9_$NHG$,Dj$a$k>r7o$N2<$GJ#@=!"G[I[!"$"$k$$$OJQ99$9\e(B
+\e$B$k$3$H$r5v2D$7$^$9!#JQ99IT2DItJ,$O;XDj$7$^$;$s!#!V\e(BA GNU Manual\e$B!W$OI=I=;f\e(B
+\e$B%F%-%9%H!"0J2<$N\e(B (a) \e$B$ON"I=;f%F%-%9%H$G$9!#$3$NMxMQ5vBz7@Ls=q$NJ#<L$O\e(B
+\e$B!V\e(BEmacs manual\e$B!W$N!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$H$$$&>O$K4^$^$l$F$$$^\e(B
+\e$B$9!#\e(B
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+(a) FSF \e$B$NN"I=;f%F%-%9%H\e(B:\e$B!V$"$J$?$K$O$3$N\e(B GNU Manual \e$B$r\e(B GNU \e$B%=%U%H%&%'%"\e(B
+\e$B$N$h$&$KJ#@=$7$?$jJQ99$9$k<+M3$,$"$j$^$9!#J#@=$O%U%j!<%=%U%H%&%'%":bCD$K\e(B
+\e$B$h$C$F=PHG$5$l$^$7$?!#\e(B(\e$B%U%j!<%=%U%H%&%'%":bCD$O\e(B) GNU \e$B$N3+H/$N$?$a$KI,MW\e(B
+\e$B$J;q6b$r=8$a$F$$$^$9!#!W\e(B
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+
+\e$B$3$NJ8=q$O!V\e(BGNU \e$B%U%j!<J8=qMxMQ5vBz7@Ls=q!W$K4p$E$$$FG[I[$5$l$?<}=8Cx:nJ*\e(B
+\e$B$N0lIt$G$9!#$b$7$"$J$?$,$3$NJ8=q$r<}=8Cx:nJ*$+$iJ,N%$7$FG[I[$7$?$$$H$-$O!"\e(B
+\e$B7@Ls=q$NBh\e(B 6 \e$B9`$K5-=R$5$l$F$$$k$h$&$K!"J8=q$K7@Ls=q$NJ#<L$rIU2C$9$k$3$H\e(B
+\e$B$K$h$C$F!"9T$J$&$3$H$,$G$-$^$9!#\e(B
+@end titlepage
+@page
+@end tex
+
+@node Top
+@top Message
+
+Gnus \e$B$NA4$F$N%a%C%;!<%8$N:n@.\e(B (\e$B%a!<%k$H%K%e!<%9$NN>J}\e(B) \e$B$O%a%C%;!<%8%b!<\e(B
+\e$B%I%P%C%U%!$G9T$o$l$^$9!#\e(B
+
+@menu
+* Interface::         \e$B%a%C%;!<%8%P%C%U%!$r@_Dj$9$k\e(B
+* Commands::          \e$B%a%C%;!<%8%b!<%I%P%C%U%!$G<B9T$G$-$kL?Na\e(B
+* Variables::         \e$B%a%C%;!<%8%P%C%U%!$r%+%9%?%^%$%:$9$k\e(B
+* Compatibility::     \e$B%a%C%;!<%8$r2<0L8_49$K$9$k\e(B
+* Appendices::        \e$B$b$C$H5;=QE*$J;v\e(B
+* Index::             \e$BJQ?t!"4X?t!"35G0$N:w0z\e(B
+* Key Index::         \e$B%a%C%;!<%8%b!<%I%-!<$N0lMw\e(B
+@end menu
+
+\e$B$3$N%^%K%e%"%k$O\e(B T-gnus 6.16 Message \e$B$KBP1~$7$^$9!#\e(BMessage \e$B$O$3$N%^%K%e\e(B
+\e$B%"%k$HF1$8HGHV9f$N\e(B Gnus \e$B$NG[I[$H6&$KG[I[$5$l$^$9!#\e(B
+
+@node Interface
+@chapter \e$B3&LL\e(B
+
+\e$B%W%m%0%i%`\e(B (\e$B$b$7$/$O?M\e(B) \e$B$,%a%C%;!<%8$KH?1~$7$?$$$H$-\e(B -- \e$BJVEz!"%U%)%m!<%"%C\e(B
+\e$B%W!"E>Aw!"<h$j>C$7\e(B -- \e$B$=$N%W%m%0%i%`\e(B (\e$B$b$7$/$O?M\e(B) \e$B$O%a%C%;!<%8$,$"$k%P%C\e(B
+\e$B%U%!$K%]%$%s%H$rF~$l$FI,MW$JL?Na$r8F$S=P$9$@$1$GNI$$$Y$-$G$9!#$=$&$9$k\e(B
+\e$B$H\e(B @code{Message} \e$B$O?7$7$$\e(B @code{message} \e$B%b!<%I%P%C%U%!$rE,@Z$J%X%C%@!<\e(B
+\e$B$rF~$l$F:n$j=P$7!"MxMQ<T$O%a%C%;!<%8$rAw$kA0$K$=$l$rJT=8$G$-$^$9!#\e(B
+
+@menu
+* New News Message::     \e$BA4$/?7$7$$%K%e!<%9%a%C%;!<%8$rJT=8$9$k\e(B
+* Reply::                \e$B%a!<%k$GJVEz$9$k\e(B
+* Wide Reply::           \e$BA4$F$N?M$K%a!<%k$G1~Ez$9$k\e(B
+* Followup::             \e$B%K%e!<%9$G%U%)%m!<%"%C%W$9$k\e(B
+* Canceling News::       \e$B?7$7$$5-;v$r<h$j>C$9\e(B
+* Superseding::          \e$B%a%C%;!<%8$NBeBX\e(B
+* Forwarding::           \e$B%a%C%;!<%8$r%K%e!<%9$b$7$/$O%a!<%k$GE>Aw$9$k\e(B
+* Resending::            \e$B%a!<%k%a%C%;!<%8$r:FAw$9$k\e(B
+* Bouncing::             \e$B%a!<%k%a%C%;!<%8$N<:GT$r:FAw$9$k\e(B
+* Mailing Lists::        \e$B%a!<%j%s%0%j%9%H$K%a!<%k$rAw$k\e(B
+@end menu
+
+@node New Mail Message
+@section \e$B?7$7$$%a!<%k%a%C%;!<%8\e(B
+
+@findex message-mail
+@code{message-mail} \e$BL?Na$O?7$7$$%P%C%U%!$r:n$jI=<($7$^$9!#\e(B
+
+2\e$B$D$NA*Br<+M3$J0z?t$,<u$1IU$1$i$l$^$9\e(B: \e$B:G=i$N$b$N$O\e(B @code{To} \e$B%X%C%@!<$H\e(B
+\e$B$7$F!"\e(B2\e$BHVL\$O\e(B @code{Subject} \e$B%X%C%@!<$H$7$F;H$o$l$k!#$b$7$3$l$i\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$k$J$i!"$=$l$i$N\e(B2\e$B$D$N%X%C%@!<$O6u$K$J$j$^$9!#\e(B
+
+@node New News Message
+@section \e$B?7$7$$%K%e!<%9%a%C%;!<%8\e(B
+
+@findex message-news
+\e$BL?Na\e(B @code{message-news} \e$B$O?7$7$$%a%C%;!<%8%P%C%U%!$r:n$j!"I=<($7$^$9!#\e(B
+
+\e$B$3$N4X?t$O\e(B2\e$B$D$NA*Br<+M3$J0z?t$r<u$1IU$1$^$9!#:G=i$N$b$N\e(B
+\e$B$O\e(B @code{Newsgroups} \e$B%X%C%@!<$H$7$F!"\e(B2\e$B$D$a$N$b$N$O\e(B @code{Subject} \e$B%X%C%@!<\e(B
+\e$B$H$7$F;H$o$l$^$9!#$b$7$3$l$i$,\e(B @code{nil} \e$B$G$"$k$J$i!"$=$l$i$N\e(B2\e$B$D$N%X%C\e(B
+\e$B%@!<$O6u$K$J$j$^$9!#\e(B
+
+@node Reply
+@section \e$BJVEz\e(B
+
+@findex message-reply
+\e$B4X?t\e(B @code{message-reply} \e$B$O8=:_$N%P%C%U%!$N%a%C%;!<%8$X$NJVEz$N%a%C%;!<\e(B
+\e$B%8%P%C%U%!$r:n$j!"I=<($7$^$9!#\e(B
+
+@vindex message-reply-to-function
+Message \e$B$O2?=h$KJVEz$,9T$/$+$rIaDL$NJ}K!\e(B (@pxref{Responses}) \e$B$G7hDj$7$^\e(B
+\e$B$9$,!"JQ?t\e(B @code{message-reply-to-function} \e$B$rO.$k$3$H$G$"$J$?$NMW5a$K9g\e(B
+\e$B$&$h$&$K$=$N?6$kIq$$$rJQ$($k;v$,$G$-$^$9!#\e(B
+
+@code{From} \e$B$NBe$o$j$K\e(B @code{Sender} \e$B$KJVEz$rAw$j$?$$$N$G$"$l$P!"$3$N$h\e(B
+\e$B$&$J;v$,$G$-$^$9\e(B:
+
+@lisp
+(setq message-reply-to-function
+      (lambda ()
+       (cond ((equal (mail-fecth-field "from") "somebody")
+               (mail-fetch-field "sender"))
+             (t
+              nil))))
+@end lisp
+
+\e$B$3$N4X?t$O$=$l$,JVEz$7$h$&$H$9$k5-;v$N%X%C%@!<ItJ,$K8BDj$5$l$?HO0O$G8F$P\e(B
+\e$B$l$^$9!#\e(B
+
+\e$B$4Mw$NDL$j!"$3$N4X?t$O$=$l$,\e(B To \e$B%X%C%@!<$,$I$N$h$&$G$"$k$Y$-$+$K4V$9$k<g\e(B
+\e$BD%$,$"$l$P!"J8;zNs$rJV$9$Y$-$G$9!#$b$7$=$&$G$J$1$l$P!"$=$l$O\e(B @code{nil}
+\e$B$rJV$9$@$1$G!"$=$&$9$l$P\e(B To \e$B%X%C%@!<$r7hDj$9$kIaDL$NJ}K!$,;H$o$l$k$G$7$g\e(B
+\e$B$&!#\e(B
+
+\e$B$3$N4X?t$O%j%9%H$rJV$9;v$b$G$-$^$9!#$=$N$h$&$J>l9g$O!"$=$l$>$l$NMWAG\e(B
+\e$B$O\e(B cons \e$B%;%k$G$"$k$Y$-$G!"$=$l$N\e(B @sc{car} \e$B$O%X%C%@!<$NL>\e(B
+\e$BA0\e(B (\e$BNc\e(B @code{Cc}) \e$B$G!"\e(B@sc{cdr} \e$B$,%X%C%@!<$N\e(B
+\e$BCM\e(B (\e$BNc\e(B @samp{larsi@@ifi.uio.no}) \e$B$G$"$k$Y$-$G$9!#$9$Y$F$N$3$l$i$N%X%C%@!<\e(B
+\e$B$O=P$F9T$/%a!<%k$N%X%C%@!<$KA^F~$5$l$^$9!#\e(B
+
+@node Wide Reply
+@section \e$B9-$/JVEz\e(B
+
+@findex message-wide-reply
+@code{message-wide-reply} \e$B$O8=:_$N%P%C%U%!$N%a%C%;!<%8$X$N9-$$JVEz$N%a%C\e(B
+\e$B%;!<%8%P%C%U%!$r:n$C$FI=<($7$^$9!#\e(B@dfn{\e$B9-$$JVEz\e(B} \e$B$O\e(B @code{To}\e$B!"\e(B
+@code{From}\e$B!"\e(B(\e$B$b$7$/$O\e(B @code{Reply-to}) \e$B$H\e(B @code{Cc} \e$B%X%C%@!<$K5s$2$i$l\e(B
+\e$B$F$$$kA4$F$N?M!9$KFO$/JVEz$G$9!#\e(B
+
+@vindex message-wide-reply-to-function
+Message \e$B$OJVEz$,2?=h$K9T$/$+$r7hDj$9$k$?$a$KIaDL$NJ}K!$r;H$$$^$9$,!"\e(B
+@code{message-wide-reply} \e$B$rO.$k;v$G!"?6$kIq$$$r$"$J$?$NMW5a$K9g$&$h$&$K\e(B
+\e$BJQ99$9$k;v$,$G$-$^$9!#$=$l$O\e(B @code{message-reply-to-function} \e$B$HF1$8$h$&\e(B
+\e$B$K;H$o$l$^$9\e(B (@pxref{Reply})\e$B!#\e(B
+
+@vindex message-dont-reply-to-names
+\e$B@55,I=8=\e(B @code{rmail-dont-reply-to-names} \e$B$K9gCW$9$k%"%I%l%9$O\e(B @code{Cc}
+\e$B%X%C%@!<$+$i<h$j=|$+$l$^$9!#\e(B
+
+@vindex message-wide-reply-confirm-recipients
+@code{message-wide-reply-confirm-recipients} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?$i!"\e(B
+\e$BJ#?t$N<u<h?M$KJV?.$9$k$+$I$&$+$N3NG'$r5a$a$i$l$^$9!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+@node Followup
+@section \e$B%U%)%m!<%"%C%W\e(B
+
+@findex message-followup
+\e$BL?Na\e(B @code{message-followup} \e$B$O8=:_$N%P%C%U%!$N%a%C%;!<%8$X$N%U%)%m!<%"%C\e(B
+\e$B%W$G$"$k%a%C%;!<%8%P%C%U%!$r:n$jI=<($7$^$9!#\e(B
+
+@vindex message-followup-to-function
+Message \e$B$O%U%)%m!<%"%C%W$,$I$3$K9T$/$+$rIaDL$NJ}K!$r;H$C$F7hDj$7$^$9$,!"\e(B
+@code{message-followup-to-function} \e$B$rO.$k;v$G!"$"$J$?$NMW5a$K9g$&$h$&$K\e(B
+\e$B?6$kIq$$$rJQ99$9$k;v$,$G$-$^$9!#$=$l$O\e(B @code{message-reply-to-function}
+\e$B$HF1$8$h$&$K;H$o$l$^$9\e(B (@pxref{Reply})\e$B!#\e(B
+
+@vindex message-use-followup-to
+\e$BJQ?t\e(B @code{message-use-followup-to} \e$B$O\e(B @code{Followup-To} \e$B%X%C%@!<$K4X$7\e(B
+\e$B$F$I$&$9$k$+$r;XDj$7$^$9!#$=$l$,\e(B @code{use} \e$B$G$"$l$P!"$$$D$bCM$r;H$$$^$9!#\e(B
+\e$B$b$7$=$l$,\e(B @code{ask} \e$B$G$"$l$P\e(B (\e$B$3$l$,=i4|@_Dj$G$9\e(B)\e$B!"CM$r;H$&$+$I$&$+$r\e(B
+\e$B?R$M$^$9!#$b$7\e(B @code{t} \e$B$G$"$k$H!"$=$l$,\e(B @samp{\e$BEj9F<T\e(B} \e$B$G$J$$8B$j!"CM$r\e(B
+\e$B;H$$$^$9!#\e(B@code{nil} \e$B$G$"$l$P!"CM$r;H$$$^$;$s!#\e(B
+
+@node Canceling News
+@section \e$B%K%e!<%9$r<h$j>C$9\e(B
+
+@findex message-cancel-news
+\e$BL?Na\e(B @code{message-cancel-news} \e$B$O8=:_$N%P%C%U%!$N5-;v$r<h$j>C$7$^$9!#\e(B
+
+@vindex message-cancel-message
+@code{message-cancel-message} \e$B$NCM$,<h$j>C$75-;v$NK\J8$KA^F~$5$l$^$9!#%G%#\e(B
+\e$B%U%)%k%H$O\e(B @samp{I am canceling my own article.} \e$B$G$9!#\e(B
+
+@cindex Cancel Locks
+@vindex message-insert-canlock
+@cindex canlock
+Message \e$B$,%K%e!<%95-;v$r%]%9%H$9$k$H$-!"%G%#%U%)%k%H\e(B
+\e$B$G\e(B @code{Cancel-Lock} \e$B%X%C%@!<$rA^F~$7$^$9!#$3$l$O0E9f2=$5$l$?%X%C%@!<$G!"\e(B
+\e$B$"$J$?<+?H$,=q$$$?%a!<%C%;!<%8$r$"$J$?$@$1$,<h$j>C$9$3$H$,$G$-$k$3$H$rJ]\e(B
+\e$B>Z$9$k!"$9$0$l$b$N$G$9!#7gE@$O!"\e(B@file{.emacs} \e$B%U%!%$%k\e(B (gnus \e$B$,HkL)\e(B
+\e$B$N\e(B cancel lock \e$B%Q%9%o!<%I\e(B (\e$B:G=i$N$3$N5!G=$r;H$&$H$-$K<+F0E*$K@8@.$5$l\e(B
+\e$B$k\e(B) \e$B$r3JG<$9$k>l=j\e(B) \e$B$r$J$/$7$F$7$^$&$H!"%a%C%;!<%8$r<h$j>C$9$3$H$,$G$-$J\e(B
+\e$B$$$G$"$m$&$3$H$G$9!#\e(B
+
+\e$B$=$N%X%C%@!<$rA^F~$9$k$+$I$&$+$O!"\e(B@code{message-insert-canlock} \e$BJQ?t$K$h$C\e(B
+\e$B$F@)8f$5$l$^$9!#\e(B
+
+\e$B$^$@B?$/$N%K%e!<%9%5!<%P!<$,\e(B @code{Cancel-Lock} \e$B%X%C%@!<$r=EMW;k$7$F$$$^\e(B
+\e$B$;$s$,!">-Mh$OJQ$o$k$3$H$,4|BT$5$l$^$9!#\e(B
+
+@node Superseding
+@section \e$BBeBX\e(B
+
+@findex message-supersede
+\e$BL?Na\e(B @code{message-supersede} \e$B$O8=:_$N%P%C%U%!$N%a%C%;!<%8$rBeBX$9$k%a%C\e(B
+\e$B%;!<%8%P%C%U%!$r:n$jI=<($7$^$9!#\e(B
+
+@vindex message-ignored-supersede-headers
+@code{message-ignored-supersedes-headers} \e$B$K9gCW$9$k%X%C%@!<$O?7$7$$%a%C\e(B
+\e$B%;!<%8%P%C%U%!$r:n$j>e$2$kA0$K<h$j=|$+$l$^$9!#=i4|CM\e(B
+\e$B$O\e(B @*@samp{^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|@*
+^Received:\\|^X-From-Line:\\|Return-Path:\\|^Supersedes:} \e$B$G$9!#\e(B
+
+@node Forwarding
+@section \e$BE>Aw\e(B
+
+@findex message-forward
+\e$BL?Na\e(B @code{message-forward} \e$B$O8=:_$N%P%C%U%!$N%a%C%;!<%8$rE>Aw$9$k$?$a$N\e(B
+\e$B%a%C%;!<%8%P%C%U%!$r:n$jI=<($7$^$9!#$b$7@\F,0z?t$rM?$($i$l$k$H!"E>Aw$O\e(B
+\e$B%K%e!<%9$r;H$$$^$9!#\e(B
+
+@table @code
+@item message-forward-ignored-headers
+@vindex message-forward-ignored-headers
+\e$B$3$N@55,I=8=$K9gCW$9$k$9$Y$F$N%X%C%@!<$,!"E>Aw$5$l$k%a%C%;!<%8$+$i:o=|$5\e(B
+\e$B$l$^$9!#\e(B
+
+@ignore
+@item message-make-forward-subject-function
+@vindex message-make-forward-subject-function
+A list of functions that are called to generate a subject header for
+forwarded messages.  The subject generated by the previous function is
+passed into each successive function.
+
+The provided functions are:
+
+@table @code
+@item message-forward-subject-author-subject
+@findex message-forward-subject-author-subject
+Source of article (author or newsgroup), in brackets followed by the
+subject.
+
+@item message-forward-subject-fwd
+Subject of article with @samp{Fwd:} prepended to it.
+@end table
+
+@item message-wash-forwarded-subjects
+@vindex message-wash-forwarded-subjects
+If this variable is @code{t}, the subjects of forwarded messages have
+the evidence of previous forwards (such as @samp{Fwd:}, @samp{Re:},
+@samp{(fwd)}) removed before the new subject is
+constructed.  The default value is @code{nil}.
+
+@item message-forward-as-mime
+@vindex message-forward-as-mime
+If this variable is @code{t} (the default), forwarded messages are
+included as inline @acronym{MIME} RFC822 parts.  If it's @code{nil}, forwarded
+messages will just be copied inline to the new message, like previous,
+non @acronym{MIME}-savvy versions of Gnus would do.
+
+@end ignore
+@item message-forward-before-signature
+@vindex message-forward-before-signature
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i=pL>$NA0$K!"$=$l0J30$@$C$?$i8e$K!"E>Aw$9$k%a%C%;!<\e(B
+\e$B%8$rCV$-$^$9!#\e(B
+@end table
+
+@node Resending
+@section \e$B:FAw\e(B
+
+@findex message-resend
+\e$BL?Na\e(B @code{message-resend} \e$B$OMxMQ<T$K%"%I%l%9$NF~NO$rB%?J$7!"8=:_$N%P%C\e(B
+\e$B%U%!$N%a%C%;!<%8$r$=$N%"%I%l%9$K:FAw$7$^$9!#\e(B
+
+@vindex message-ignored-resent-headers
+\e$B@55,I=8=\e(B @code{message-ignored-resent-headers} \e$B$K9gCW$9$k%X%C%@!<$O%a%C\e(B
+\e$B%;!<%8$rAw$kA0$K<h$j=|$+$l$^$9!#=i4|CM$O\e(B @code{^Return-receipt} \e$B$G$9!#\e(B
+
+@node Bouncing
+@section \e$B<:GT\e(B
+
+@findex message-bounce
+\e$BL?Na\e(B @code{message-bounce} \e$B$O!"$b$78=:_$N%P%C%U%!$,<:GT$7$?%a!<%k%a%C%;!<\e(B
+\e$B%8$G$"$l$P!"<:GT>pJs$r<h$j=|$$$?%a%C%;!<%8%P%C%U%!$r:n$jI=<($7$^$9!#\e(B
+@dfn{\e$B<:GT%a%C%;!<%8\e(B} \e$B$OIaDL$O\e(B @code{mailer-daemon} \e$B$+$iG[AwIT2D$H$7$FJV\e(B
+\e$BAw$5$l$?%a!<%k$G$9!#\e(B
+
+@vindex message-ignored-bounced-headers
+\e$B@55,I=8=\e(B @code{message-ignored-bounced-headers} \e$B$K9gCW$9$k%X%C%@!<$O%P%C\e(B
+\e$B%U%!$r:n$j>e$2$kA0$K<h$j=|$+$l$^$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{^\\(Received\\|Return-Path\\):} \e$B$G$9!#\e(B
+
+@node Mailing Lists
+@section \e$B%a!<%j%s%0%j%9%H\e(B
+
+@cindex Mail-Followup-To
+\e$B%a!<%j%s%0%j%9%H$KEj9F$9$k$H$-!"Ej9F$9$k?M$,$=$N5-;v$KBP$9$k%U%)%m!<%"%C\e(B
+\e$B%W5-;v$N08@h$r;XDj$7$?$$$3$H$,$"$j$^$9!#\e(BMail-Followup-To (MFT) \e$B$O$^$5$K\e(B
+\e$B$3$l$r2DG=$K$9$k$?$a$K:n$i$l$^$7$?!#$3$l$,Lr$KN)$D>l9g$NNc$rFs$D\e(B:
+
+@itemize @bullet
+@item
+\e$B%a!<%j%s%0%j%9%H$KEj9F$9$k?M$O!"JV;v$rEj9F<T$r4^$a$:$KC1$K%a!<%j%s%0%j%9\e(B
+\e$B%H$@$1$KAw?.$9$Y$-$G$"$k$3$H$r!"\e(BMFT \e$B$r;H$C$FI=8=$9$k$3$H$,$G$-$^$9!#$3$l\e(B
+\e$B$O!"Ej9F<T$,$9$G$K$=$N%a!<%j%s%0%j%9%H$r9XFI$7$F$$$k>l9g$,3:Ev$7$^$9!#\e(B
+
+@item
+\e$B%a!<%j%s%0%j%9%H$KEj9F$9$k?M$O!"JV;v$r%a!<%j%s%0%j%9%H$HEj9F<T$K$bAw?.$9\e(B
+\e$B$Y$-$G$"$k$3$H$r!"\e(BMFT \e$B$r;H$C$FI=8=$9$k$3$H$,$G$-$^$9!#$3$l$O!"Ej9F<T$,$=\e(B
+\e$B$N%a!<%j%s%0%j%9%H$r9XFI$7$F$$$J$$>l9g$,3:Ev$7$^$9!#\e(B
+
+@item
+\e$B%a%C%;!<%8$,$$$/$D$+$N%a!<%j%s%0%j%9%H$KEj9F$5$l$F$$$k>l9g$K!"$=$l0J9_$N\e(B
+\e$B5DO@$r0l$D$N%a!<%j%s%0%j%9%H$@$1$G9T$J$&$3$H$r;XDj$9$k$?$a$K$b\e(B MFT \e$B$O;H\e(B
+\e$B$o$l$^$9!#5DO@$,$$$/$D$+$N%a!<%j%s%0%j%9%H$G9T$J$o$l$F$7$^$&$H$P$i$P$i$K\e(B
+\e$B$J$j$d$9$$$7!"%U%)%m!<$9$k$N$,Fq$7$/$J$C$F$7$^$$$^$9$+$i!#\e(B
+@end itemize
+
+gnus \e$B$OB>$N?M$N%a%C%;!<%8$K$"$k\e(B MFT \e$B%X%C%@!<$rB:=E$7\e(B (\e$B$9$J$o$A!"$@$l$+JL\e(B
+\e$B$N?M$NEj9F$K%U%)%m!<%"%C%W$9$k$H$-\e(B)\e$B!"$^$?!"30$K=P$F$$$/%a%C%;!<%8$N$?$a\e(B
+\e$B$K!"F;M}$K$+$J$C$?\e(B MFT \e$B%X%C%@!<$r:n@.$9$k$3$H$N%5%]!<%H$bDs6!$7$^$9!#\e(B
+
+@c @menu
+@c * Honoring an MFT post::        What to do when one already exists
+@c * Composing with a MFT header:: Creating one from scratch.
+@c @end menu
+
+@c @node Composing with a MFT header
+@subsection  \e$B@5$7$$\e(B MFT \e$B%X%C%@!<$r<+F0E*$K:n$k\e(B
+
+\e$BEj9F$9$k5-;v$KBP$7$F\e(B gnus \e$B$,<+F0E*$K\e(B MFT \e$B%X%C%@!<$r:n$C$F$/$l$k$h$&$K$9\e(B
+\e$B$k$?$a$K9T$J$&$3$H$NBh0lJb$O!"$"$J$?$,9XFI$7$F$$$k%a!<%j%s%0%j%9%H$N%"%I\e(B
+\e$B%l%9$N%j%9%H$r\e(B gnus \e$B$KM?$($k$3$H$G$9!#0l$D0J>e$NJ}K!$G$3$l$r9T$J$&$3$H$,\e(B
+\e$B$G$-$^$9!#0J2<$NJQ?t$,<j$4$m$G$7$g$&!#\e(B
+
+@table @code
+@vindex message-subscribed-addresses
+@item message-subscribed-addresses
+\e$B$3$l$O9XFI$7$F$$$k%a!<%j%s%0%j%9%H$N%"%I%l%9$N%j%9%H$G$J$1$l$P$J$j$^$;$s!#\e(B
+\e$B%G%#%U%)%k%HCM$O\e(B @code{nil} \e$B$G$9!#Nc\e(B:
+
+@lisp
+(setq message-subscribed-addresses
+      '("ding@@gnus.org" "bing@@noose.org"))
+@end lisp
+
+@vindex message-subscribed-regexps
+@item message-subscribed-regexps
+\e$B$3$l$O9XFI$7$F$$$k%a!<%j%s%0%j%9%H$N%"%I%l%9$r<($9@55,I=8=$N%j%9%H$G$J$1\e(B
+\e$B$l$P$J$j$^$;$s!#%G%#%U%)%k%HCM$O\e(B @code{nil} \e$B$G$9!#>e5-$HF1$87k2L$r@.$7?k\e(B
+\e$B$2$?$$>l9g$NNc\e(B:
+
+@lisp
+(setq message-subscribed-regexps
+      '("\\(ding@@gnus\\)\\|\\(bing@@noose\\)\\.org")
+@end lisp
+
+@vindex message-subscribed-address-functions
+@item message-subscribed-address-functions
+\e$B$3$l$O\e(B MFT \e$B%X%C%@!<$NCM$r7h$a$k$?$a$K\e(B (\e$B0lEY$K0l2s\e(B!!) \e$B8F$P$l$k4X?t$N%j%9\e(B
+\e$B%H$G$"$k$3$H$,$G$-$^$9!#$=$l$i$N4X?t$K$O0z?t$,L5$$$3$H$rCi9p$7$F$*$-$^$9!#\e(B
+\e$B%G%#%U%)%k%HCM$O\e(B @code{nil} \e$B$G$9!#\e(B
+
+gnus \e$B$K$O$3$NJQ?t$N9%E,$J8uJd$G$"$k$H$3$m$N!"$"$i$+$8$aDj5A$5$l$F$$$k4X\e(B
+\e$B?t$,$"$j$^$9!#4X?t\e(B @code{gnus-find-subscribed-addresses} \e$B$O!"\e(B
+@code{subscribed} (@pxref{Group Parameters, ,Group Parameters, gnus, The
+Gnus Manual}) \e$B%0%k!<%W%Q%i%a!<%?$,Hs\e(B-@code{nil} \e$B$K@_Dj$5$l$F$$$k%0%k!<%W\e(B
+\e$B$KBP1~$9$k%"%I%l%9$N%j%9%H$rJV$7$^$9!#$3$s$J$U$&$K$7$^$7$g$&!#\e(B
+
+@lisp
+(setq message-subscribed-address-functions
+      '(gnus-find-subscribed-addresses))
+@end lisp
+
+@vindex message-subscribed-address-file
+@item message-subscribed-address-file
+\e$B$"$J$?$O$b$7$+$7$?$i?l68$J?M\e(B (\e$B86E5\e(B: one organised human freak) \e$B$G!"9XFI\e(B
+\e$B$7$F$$$k$9$Y$F$N%a!<%j%s%0%j%9%H$N%"%I%l%9$N%j%9%H$rJL%U%!%$%k$G;}$C$F$$\e(B
+\e$B$k$+$b$7$l$^$;$s\e(B! \e$B$=$&$J$i$P!"C1$K$3$NJQ?t$r$=$N%U%!%$%kL>$K$9$k$3$H$K$h$C\e(B
+\e$B$F!"?M@8$ONI$-$b$N$K$J$k$G$7$g$&!#\e(B
+@end table
+
+\e$B>e5-0J30$K0l$D0J>e$NJQ?t$r;H$&$3$H$,$G$-$^$9!#$9$Y$F$=$l$i$NCM$O2?$i$+$N\e(B
+\e$BJ}K!$G!V2C$($i$l$k!W$3$H$GF0:n$7$^$9\e(B :-)
+
+\e$B$5$"MQ0U$,$G$-$^$7$?!#$$$D$b$N$h$&$K%a%C%;!<%8$N:n@.$r;O$a$^$7$g$&!#$=$7\e(B
+\e$B$F$$$D$bDL$j$KAw?.$7$^$7$g$&!#%a%C%;!<%8$,Aw=P$5$l$kD>A0\e(B
+\e$B$K\e(B gnus \e$B$N\e(B MFT \e$B$r:n$k;E3]$1$,F0:n$7$F!"%a%C%;!<%8$,$9$G$K\e(B MFT \e$B%U%#!<%k%I\e(B
+\e$B$r;}$C$F$$$k$+$I$&$+$rD4$Y$^$9!#$b$7$=$l$,0l$D$J$i!"$=$l$OJ|$C$F$*$+$l$^\e(B
+\e$B$9\e(B (\e$B$?$@$7$=$N>l9g$K$=$l$,6u$C$]$@$C$?$i!"$=$N%U%#!<%k%I$O:o=|$5$l<+F0@8\e(B
+\e$B@.$5$l$?$b$N$GCV$-49$($i$l$k$3$H$b$"$j$^$;$s!#$3$l$O8D!9$N%a%C%;!<%8$K$D\e(B
+\e$B$$$F\e(B MFT \e$B$N@8@.$r6X;_$5$;$k4pK\$G$9\e(B)\e$B!#L5$+$C$?>l9g$O<u<h?M$N%"%I%l%9$N%j\e(B
+\e$B%9%H\e(B (To: \e$B$H\e(B Cc: \e$B%X%C%@!<$K$"$k\e(B) \e$B$r!"$=$l$i$N0l$D$,9XFI$7$F$$$k%a!<%j%s\e(B
+\e$B%0%j%9%H$N%"%I%l%9$+$I$&$+$rD4$Y$^$9!#$=$l$i$N$I$l$b$,%a!<%j%s%0%j%9%H$N\e(B
+\e$B%"%I%l%9$G$J$+$C$?$i!"\e(BMFT \e$B$O:n$i$l$^$;$s!#$=$l0J30$N>l9g$K$O\e(B MFT \e$B$,$=$N\e(B
+\e$BB>$N%X%C%@!<$KIU$12C$($i$l!"$=$NCM$O\e(B To: \e$B$H\e(B Cc: \e$B$K$"$k$9$Y$F$N%"%I%l%9$K\e(B
+\e$B@_Dj$5$l$^$9!#\e(B
+
+@kindex C-c C-f C-a
+@findex message-generate-unsubscribed-mail-followup-to
+@kindex C-c C-f C-m
+@findex message-goto-mail-followup-to
+\e$B$&!<$`!#$=$&$9$k$H$"$J$?$O!V9XFI$7$F$$$J$$%a!<%j%s%0%j%9%H$K%a!<%k$rAw?.\e(B
+\e$B$9$k$H$-$O$I$&$J$k$N\e(B?  \e$B;d$OM>J,$N%3%T!<$,M_$7$$$3$H$r\e(B MFT \e$B$G8@$$$?$$!W$H\e(B
+\e$B?R$M$^$9$M\e(B (\e$B$?$V$sB>$N?M$O\e(B MFT \e$B$,L5$+$C$?>l9g$HF1MM$K=hM}$7$F$7$^$&$@$m\e(B
+\e$B$&$1$l$I!"C/$+$N\e(B to-address \e$B%0%k!<%W%Q%i%a!<%?$r>e=q$-$9$k$?$a$K!"L@<(E*\e(B
+\e$B$J\e(B MFT \e$B$r;H$&$3$H$,$G$-$k$N$G$9\e(B)\e$B!#4X\e(B
+\e$B?t\e(B @code{message-generate-unsubscribed-mail-followup-to} \e$B$,Lr$KN)$D$3$H\e(B
+\e$B$,$"$k$G$7$g$&!#$3$l$O%G%#%U%)%k%H$G\e(B @kbd{C-c C-f C-a} \e$B$K3d$jEv$F$i$l$F\e(B
+\e$B$$$^$9!#$I$s$J>l9g$G$b!"$"$J$?$O<+J,$,A*$s$@\e(B MFT \e$B$rA^F~$9$k$3$H$,$G$-$^\e(B
+\e$B$9\e(B; \e$B$=$l$r;O$a$k$N\e(B
+\e$B$K\e(B @kbd{C-c C-f C-m} (@code{message-goto-mail-followup-to}) \e$B$,=u$1$F$/$l\e(B
+\e$B$k$G$7$g$&!#\e(B
+
+@c @node Honoring an MFT post
+@subsection MFT \e$BEj9F$NB:=E\e(B
+
+@vindex message-use-mail-followup-to
+\e$B%a!<%j%s%0%j%9%H$KEj9F$5$l$?5-;v$K%U%)%m!<%"%C%W$9$k$H$-!"$=$N5-;v\e(B
+\e$B$,\e(B MFT \e$B%X%C%@!<$r;}$C$F$$$?$i!"\e(Bgnus \e$B$NF0:n$OJQ\e(B
+\e$B?t\e(B @code{message-use-mail-followup-to} \e$B$NCM$K$h$C$F7h$^$j$^$9!#$3$NCM$O\e(B
+\e$B0J2<$N$I$l$+$K$J$j$^$9\e(B:
+
+@table @code
+@item use
+\e$B>o$K\e(B MFT \e$B$rB:=E$7$^$9!#%U%)%m!<%"%C%W5-;v$N\e(B To: \e$B$H\e(B Cc: \e$B%X%C%@!<$O!"85$N\e(B
+\e$B5-;v$N\e(B MFT \e$B%X%C%@!<$+$i0z$-=P$7$^$9!#$3$l$,%G%#%U%)%k%H$G$9!#\e(B
+
+@item nil
+\e$B>o$K\e(B MFT \e$B$rB:=E$7$^$;$s\e(B (\e$B40`z$KL5;k\e(B)\e$B!#\e(B
+
+@item ask
+\e$B$I$&$9$k$+?R$M$^$9!#\e(B
+@end table
+
+MFT \e$B$rB:=E$9$k$3$H$ONI$$%M%A%1%C%H\e(B (netiquette) \e$B$G$"$k$H9M$($i$l$F$$$^$9!#\e(B
+\e$B$=$l$O!"$I$3$K%U%)%m!<%"%C%W$9$kI,MW$,$"$k$+$r!"%a%C%;!<%8$rEj9F$7$??M$O\e(B
+\e$B$"$J$?$h$j$h$/CN$C$F$$$k!"$H;W$o$l$k$+$i$G$9!#\e(B
+
+@node Commands
+@chapter \e$BL?Na\e(B
+
+@menu
+* Buffer Entry::        \e$B%a%C%;!<%8%P%C%U%!$KF~$C$?8e$NL?Na\e(B
+* Header Commands::     \e$B%X%C%@!<$K0\F0$^$?$O%X%C%@!<$rJQ99$9$k$?$a$NL?Na\e(B
+* Movement::            \e$B%a%C%;!<%8%P%C%U%!$rF0$-2s$k\e(B
+* Insertion::           \e$B%a%C%;!<%8%P%C%U%!$KJ*;v$rA^F~$9$k\e(B
+@c * MIME::                @acronym{MIME} considerations.
+* IDNA::                \e$BHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$K4X$9$k9M;!\e(B
+@c * Security::            Signing and encrypting messages.
+* Various Commands::    \e$B$$$m$$$m$J;v\e(B
+* Sending::             \e$B<B:]$K%a%C%;!<%8$rAw$k\e(B
+* Mail Aliases::        \e$B$I$N$h$&$K$7$F%a!<%k$NJLL>$r;H$&$+\e(B
+* Spelling::            Emacs \e$B$K%9%Z%k%A%'%C%/$5$;$k\e(B
+@end menu
+
+@node Buffer Entry
+@section \e$B%P%C%U%!$KF~$k\e(B
+@cindex undo
+@kindex C-_
+
+\e$B2?$+B>$N%a%C%;!<%8$KJVEz$9$k$H$-!"$?$$$F$$$O%a%C%;!<%8%P%C%U%!$G=q$->e$2\e(B
+\e$B$^$9$h$M!#\e(BMessage \e$B$OB?$/$N0zMQJ8$r07$$!"=pL>$N:o=|$dJ8>O$N@07A$r$7$?$j!"\e(B
+\e$B$"$k$$$O$"$J$?$,;H$C$F$$$k@_Dj$K0MB8$7$F$$$^$9!#\e(BMessage \e$B$OIaDL$O$&$^$/F0\e(B
+\e$B:n$7$^$9$,!"$H$-$I$-4V0c$($b$7$^$9!#$=$l$i$N4V0c$$$r%f!<%6$,@5$9$3$H$,$G\e(B
+\e$B$-$k$h$&$K!"\e(BMessage \e$B$O$=$l$>$l<gMW$JF0:n$r9T$J$&A0$K%"%s%I%%$N6-3&$r@_Dj\e(B
+\e$B$7$^$9!#2?2s$+%"%s%I%%$N%-!<\e(B (\e$BDL>o\e(B @kbd{C-_}) \e$B$r2!$;$P!"L$JT=8$N%a%C%;!<\e(B
+\e$B%8$KLa$9$3$H$,$G$-$^$9!#\e(B
+
+@node Header Commands
+@section \e$B%X%C%@!<L?Na\e(B
+
+@subsection \e$B%X%C%@!<$K0\F0$9$k$?$a$NL?Na\e(B
+
+\e$B0J2<$NL?Na$OEv$N%X%C%@!<$K0\F0$7$^$9!#B8:_$7$J$1$l$PA^F~$5$l$^$9!#\e(B
+
+@table @kbd
+
+@item C-c ?
+@kindex C-c ?
+@findex describe-mode
+\e$B%a%C%;!<%8%b!<%I$N5-=R$G$9!#\e(B
+
+@item C-c C-r C-t
+@kindex C-c C-f C-t
+@findex message-goto-to
+@code{To} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-to})\e$B!#\e(B
+
+@item C-c C-f C-o
+@kindex C-c C-f C-o
+@findex message-goto-from
+@code{From} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-from})\e$B!#\e(B(\e$B%-!<%P%$%s%I\e(B
+\e$BCf$N\e(B ``o'' \e$B$OAO:n<T\e(B (Originator) \e$B$KM3Mh$7$F$$$^$9!#\e(B)
+
+@item C-c C-f C-b
+@kindex C-c C-f C-b
+@findex message-goto-bcc
+@code{Bcc} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-bcc})\e$B!#\e(B
+
+@item C-c C-f C-f
+@kindex C-c C-f C-f
+@findex message-goto-fcc
+@code{Fcc} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-fcc})\e$B!#\e(B
+
+@item C-c C-f C-c
+@kindex C-c C-f C-c
+@findex message-goto-cc
+@code{Cc} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-cc})\e$B!#\e(B
+
+@item C-c C-f C-s
+@kindex C-c C-f C-s
+@findex message-goto-subject
+@code{Subject} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-subject})\e$B!#\e(B
+
+@item C-c C-f C-r
+@kindex C-c C-f C-r
+@findex message-goto-reply-to
+@code{Reply-To} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-reply-to})\e$B!#\e(B
+
+@item C-c C-f C-n
+@kindex C-c C-f C-n
+@code{Neswsgroups} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-newsgroups})\e$B!#\e(B
+
+@item C-c C-f C-d
+@kindex C-c C-f C-d
+@findex message-goto-distribution
+@code{Distribution} \e$B%X%C%@!<$K9T$-$^\e(B
+\e$B$9\e(B (@code{message-goto-distribution})\e$B!#\e(B
+
+@item C-c C-f C-o
+@kindex C-c C-f C-o
+@findex message-goto-followup-to
+@code{Followup-To} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-followup-to})\e$B!#\e(B
+
+@item C-c C-f C-k
+@kindex C-c C-f C-k
+@findex message-goto-keywords
+@code{Keywords} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-keywords})\e$B!#\e(B
+
+@item C-c C-f C-u
+@kindex C-c C-f C-u
+@findex message-goto-summary
+@code{Summary} \e$B%X%C%@!<$K9T$-$^$9\e(B (@code{message-goto-summary})\e$B!#\e(B
+
+@item C-c C-f C-i
+@kindex C-c C-f C-i
+@findex message-insert-or-toggle-importance
+\e$BCM\e(B @samp{high} \e$B$r;}$D\e(B @samp{Importance:} \e$B%X%C%@!<$rA^F~$7$^$9!#$3$N%X%C\e(B
+\e$B%@!<$O<u?.<T$K$=$N%a%C%;!<%8$N=EMW@-$rCN$i$;$k$?$a$K;H$o$l$k$b$N$G$9!#$b\e(B
+\e$B$7%P%C%U%!$K$9$G$K$3$N%X%C%@!<$,$"$k>l9g$O!"\e(BRFC 1376 \e$B$K=`$8$?;0$D$N\e(B
+\e$BCM\e(B @samp{low}\e$B!"\e(B@samp{normal} \e$B$*$h$S\e(B @samp{high} \e$B$r=[4D$5$;$^$9!#\e(B
+
+@item C-c C-f C-a
+@kindex C-c C-f C-a
+@findex message-generate-unsubscribed-mail-followup-to
+\e$B9VFI$7$F$$$J$$%a!<%j%s%0%j%9%H$KEj9F$9$k>l9g$K8+9g$C\e(B
+\e$B$?\e(B @samp{Mail-Followup-To:} \e$B%X%C%@!<$rA^F~$7$^$9!#9VFI$7$F$$$J$$%a!<%j%s\e(B
+\e$B%0%j%9%H$KK\5-;v$rEj9F$9$k$H$-$O!"\e(B@samp{Mail-Followup-To:} \e$B$r<j$G=q$+$J\e(B
+\e$B$1$l$P$J$j$^$;$s!#FbMF$O!"$U$D$&$O%a!<%j%s%0%j%9%H$N%"%I%l%9$H$"$J$?<+?H\e(B
+\e$B$N%"%I%l%9$G$9!#$3$N4X?t$O$=$N$h$&$J%X%C%@!<$r<+F0E*$KA^F~$7$^$9!#$3$l$O\e(B
+\e$B8=:_$N%a!<%k$N%P%C%U%!$+$i\e(B @samp{To:} \e$B%X%C%@!<$NFbMF$rH4$-=P$7!"$=$l$K8=\e(B
+\e$B:_$N\e(B @code{user-mail-address} \e$B$rDI2C$7$^$9!#\e(B
+
+\e$BG$0U$N0z?t$G$"$k\e(B @code{include-cc} \e$B$,Hs\e(B-@code{nil} \e$B$@$C$?>l9g$O!"\e(B
+@samp{Cc:} \e$B%X%C%@!<$K$"$k%"%I%l%9$b\e(B @samp{Mail-Followup-To:} \e$B%X%C%@!<$K\e(B
+\e$BCV$+$l$^$9!#\e(B
+@end table
+
+@subsection \e$B%X%C%@!<$rJQ99$9$k$?$a$NL?Na\e(B
+
+@table @kbd
+
+@item C-c C-o
+@kindex C-c C-o
+@findex message-sort-headers
+@vindex message-header-format-alist
+@code{message-header-format-alist} \e$B$K=>$C$F%X%C%@!<$rJB$YBX$($^\e(B
+\e$B$9\e(B (@code{message-sort-headers})\e$B!#\e(B
+
+@item C-c C-t
+@kindex C-c C-t
+@findex message-insert-to
+\e$B%U%)%m!<%"%C%W$7$h$&$H$9$k%a%C%;!<%8$N\e(B @code{Reply-To} \e$B$b$7$/\e(B
+\e$B$O\e(B @code{From} \e$B%X%C%@!<$r4^$`\e(B @code{To} \e$B%X%C%@!<$rA^F~$7$^\e(B
+\e$B$9\e(B (@code{message-insert-to})\e$B!#\e(B
+
+@item C-c C-n
+@kindex C-c C-n
+@findex message-insert-newsgroups
+\e$BJVEz$7$F$$$k5-;v$N\e(B @code{Followup-To} \e$B$b$7$/$O!"\e(B@code{Nesgroups} \e$B%X%C%@!<\e(B
+\e$B$rH?1G$7$?\e(B @code{Newsgroups} \e$B%X%C%@!<$rA^F~$7$^\e(B
+\e$B$9\e(B (@code{message-insert-newsgroups})\e$B!#\e(B
+
+@item C-c C-l
+@kindex C-c C-l
+@findex message-to-list-only
+\e$B%a!<%j%s%0%j%9%H08$F$@$1$K%a%C%;!<%8$rAw$j$^$9!#\e(B
+@code{To:} \e$B$H\e(B @code{Cc:} \e$B%X%C%@!<$+$i!"$=$N%a!<%j%s%0%j%9%H0J30$N%"%I%l\e(B
+\e$B%9$r:o=|$7$^$9!#\e(B
+
+@item C-c M-n
+@kindex C-c M-n
+@findex message-insert-disposition-notification-to
+\e$B3+Iu3NG'MW5a$rA^F~$7$^$9!#\e(B
+(@code{message-insert-disposition-notification-to})\e$B!#$3$l$O!"$b$7<u?.<T\e(B
+\e$B$,\e(B RFC 2298 \e$B$r%5%]!<%H$7$F$$$?$i!"H`=w$K$=$N%a%C%;!<%8$r<u$1<h$C$?$3$H$r\e(B
+\e$BCN$i$;$FM_$7$$$3$H$r0UL#$7$^$9!#\e(B
+
+@item M-x message-insert-importance-high
+@kindex M-x message-insert-importance-high
+@findex message-insert-importance-high
+@cindex Importance
+\e$BCM\e(B @samp{high} \e$B$r;}$D\e(B @samp{Importance} \e$B%X%C%@!<$rA^F~$7$^$9!#I,MW$J\e(B
+\e$B$i\e(B (\e$B$9$G$K$"$k\e(B) \e$B%X%C%@!<$r>C5n$7$F$+$i!#\e(B
+
+@item M-x message-insert-importance-low
+@kindex M-x message-insert-importance-low
+@findex message-insert-importance-low
+@cindex Importance
+\e$BCM\e(B @samp{low} \e$B$r;}$D\e(B @samp{Importance} \e$B%X%C%@!<$rA^F~$7$^$9!#I,MW$J\e(B
+\e$B$i\e(B (\e$B$9$G$K$"$k\e(B) \e$B%X%C%@!<$r>C5n$7$F$+$i!#\e(B
+
+@item C-c C-f s
+@kindex C-c C-f s
+@findex message-change-subject
+@cindex Subject
+\e$B8=:_$N\e(B @samp{Subject} \e$B%X%C%@!<$rJQ99$7$^$9!#?7$7$$\e(B @samp{Subject} \e$B$r?R$M\e(B
+\e$B$F\e(B @samp{(was: <\e$B8E$$BjL>\e(B>)} \e$B$rDI2C$7$^$9!#8E$$BjL>$OJV?.$9$k$H$-$K:o=|$9\e(B
+\e$B$k$3$H$,$G$-$^$9!#\e(B@code{message-subject-trailing-was-query}
+(@pxref{Message Headers}) \e$B$r8+$F2<$5$$!#\e(B
+
+@item C-c C-f x
+@kindex C-c C-f x
+@findex message-cross-post-followup-to
+@vindex message-cross-post-default
+@cindex X-Post
+@cindex cross-post
+\e$B%/%m%9%]%9%H$9$k$?$a$KDI2C$9\e(B
+\e$B$k\e(B @samp{Newsgroups} \e$B$H\e(B @samp{FollowUp-To} \e$B$r?R$M$^$9!#\e(B
+@code{message-cross-post-followup-to} \e$B$O\e(B @samp{FollowUp-To} \e$B$*$h\e(B
+\e$B$S\e(B @samp{Newsgroups} \e$B$r!"%0%k!<%W$r;X$7<($9$h$&$K@Z$jNv$-$^$9!#\e(B
+@code{message-cross-post-default} \e$B$,\e(B @code{nil} \e$B$@$C$?$j@\F,0z\e(B
+\e$B?t\e(B @samp{Follow-Up} \e$BIU$-$G8F$P$l$k$H!"%a%C%;!<%8$O%/%m%9%]%9%H$5$l$^$;\e(B
+\e$B$s!#\e(B
+
+@item C-c C-f t
+@kindex C-c C-f t
+@findex message-reduce-to-to-cc
+@samp{To} \e$B%X%C%@!<$NFbMF$r\e(B @samp{Cc} \e$B$+\e(B @samp{Bcc} \e$B%X%C%@!<$NFbMF$GCV$-\e(B
+\e$B49$($^$9!#\e(B
+
+@item C-c C-f w
+@kindex C-c C-f w
+@findex message-insert-wide-reply
+\e$B9-$$JVEz$r$7$?$h$&$K\e(B @samp{To} \e$B$H\e(B @samp{Cc} \e$B%X%C%@!<$rA^F~$7$^$9!#\e(B
+
+@item C-c C-f a
+@kindex C-c C-f a
+@findex message-add-archive-header
+@vindex message-archive-header
+@vindex message-archive-note
+@cindex X-No-Archive
+@samp{X-No-Archive: Yes} \e$B$r%X%C%@!<$KA^F~$7$F!"K\J8$KCm0U=q$-$rF~$l$^$9!#\e(B
+\e$B%X%C%@!<$HCm0U=q$-\e(B
+\e$B$O\e(B @code{message-archive-header} \e$B$H\e(B @code{message-archive-note} \e$B$G%+%9%?\e(B
+\e$B%^%$%:$9$k$3$H$,$G$-$^$9!#@\F,0z?tIU$-$G8F$P$l$k$H!"A^F~$9$k%F%-%9%H$rMW\e(B
+\e$B5a$7$^$9!#K\J8$KCm0U=q$-$rF~$l$?$/$J$$>l9g$O!"\e(B
+@code{message-archive-note} \e$B$r\e(B @code{nil} \e$B$K$7$F2<$5$$!#\e(B
+@end table
+
+@node Movement
+@section \e$B0\F0\e(B
+
+@table @kbd
+@item C-c C-b
+@kindex C-c C-b
+@findex message-goto-body
+\e$B%a%C%;!<%8$NK\BN$N@hF,$K0\F0$7$^$9\e(B (@code{message-goto-body})\e$B!#\e(B
+
+@item C-c C-i
+@kindex C-c C-i
+@findex message-goto-signature
+\e$B%a%C%;!<%8$N=pL>$K0\F0$7$^$9\e(B (@code{message-goto-signature})\e$B!#\e(B
+
+@item C-a
+@kindex C-a
+@findex message-beginning-of-line
+@vindex message-beginning-of-line
+\e$B%X%C%@!<$NCM$N$H$3$m$K$$$k$H$-$O9T$N@hF,$K0\F0$7!"$=$&$G$J$$$H$-$O%X%C%@!<\e(B
+\e$B$NCM$N@hF,$K0\F0$7$^$9!#\e(B(\e$B%X%C%@!<$NCM$O%X%C%@!<L>$H%3%m%s$N8e$KMh$^\e(B
+\e$B$9!#\e(B) \e$B$3$NF0:n$OJQ?t\e(B @code{message-beginning-of-line} \e$B$r%H%0%k$9$k$3$H$K\e(B
+\e$B$h$C$FL58z$K$9$k$3$H$,$G$-$^$9!#\e(B
+@end table
+
+@node Insertion
+@section \e$BA^F~\e(B
+
+@table @kbd
+
+@item C-c C-y
+@kindex C-c C-y
+@findex message-yank-original
+\e$B%P%C%U%!\e(B @code{gnus-article-copy} \e$B$K$"$k%a%C%;!<%8$r%a%C%;!<%8%P%C%U%!$K\e(B
+\e$BE=$jIU$1$^$9!#IaDL$O\e(B @code{gnus-article-copy} \e$B$OJVEz$7$h$&$H$7$F$$$k%a%C\e(B
+\e$B%;!<%8$G$9\e(B (@code{messsage-yank-original})\e$B!#\e(B
+
+@item C-c C-M-y
+@kindex C-c C-M-y
+@findex message-yank-buffer
+\e$B%P%C%U%!L>$r?R$M$F!"$=$N%P%C%U%!$NFbMF$r%a%C%;!<%8%P%C%U%!$KE=$jIU$1$^\e(B
+\e$B$9\e(B (@code{message-yank-buffer})\e$B!#\e(B
+
+@item C-c C-q
+@kindex C-c C-q
+@findex message-fill-yanked-message
+\e$BE=$jIU$1$i$l$?%a%C%;!<%8$r@^$jJV$7$^\e(B
+\e$B$9\e(B (@code{message-fill-yanked-message})\e$B!#7Y9p\e(B: \e$B$b$7!"0zMQ$N=,47$,JQ$G$"\e(B
+\e$B$k$J$i!"E=$jIU$1$i$l$?J8>O$r$R$I$/$0$A$c$0$A$c$K$7$F$7$^$&$+$b$7$l$^$;$s!#\e(B
+\e$B$=$l$,0BA4$G$"$k$HCN$k$H!"$9$0$K?M?4CO$D$/$G$7$g$&$,!#$H$K$+$/!"\e(B
+@kbd{C-x u} (@code{undo}) \e$B$,;HMQ2DG=$G!"Bg>fIW$G$"$k$H8@$&;v$r3P$($F$*$$\e(B
+\e$B$F2<$5$$!#\e(B
+
+@item C-c C-w
+@kindex C-c C-w
+@findex message-insert-signature
+\e$B%P%C%U%!$N:G8e$K=pL>$rA^F~$7$^$9\e(B (@code{message-insert-signature})\e$B!#\e(B
+
+@item C-c M-h
+@kindex C-c M-h
+@findex message-insert-headers
+\e$B%a%C%;!<%8$N%X%C%@!<$rA^F~$7$^$9\e(B (@code{message-insert-headers})\e$B!#\e(B
+
+@item C-c M-m
+@kindex C-c M-m
+@findex message-mark-inserted-region
+\e$B8=:_$N5-;v$N$$$/$D$+$NNN0h$r!"$=$l$i$r0O$`$?$a$N%?%0$G0u$rIU$1$^$9!#\e(B
+@code{message-mark-insert-begin} \e$B$H\e(B @code{message-mark-insert-end} \e$B$r8+\e(B
+\e$B$F2<$5$$!#\e(B
+
+@item C-c M-f
+@kindex C-c M-f
+@findex message-mark-insert-file
+\e$B8=:_$N5-;v$K!"%?%0$G0O$^$l$?%U%!%$%k$rA^F~$7$^$9!#\e(B
+@code{message-mark-insert-begin} \e$B$H\e(B @code{message-mark-insert-end} \e$B$r8+\e(B
+\e$B$F2<$5$$!#\e(B
+@end table
+
+@c FIXTGNUS We should provide MIME manual.
+@ignore
+@node MIME
+@section MIME
+@cindex MML
+@cindex MIME
+@cindex multipart
+@cindex attachment
+
+Message is a @acronym{MIME}-compliant posting agent.  The user generally
+doesn't have to do anything to make the @acronym{MIME} happen---Message will
+automatically add the @code{Content-Type} and
+@code{Content-Transfer-Encoding} headers.
+
+The most typical thing users want to use the multipart things in
+@acronym{MIME} for is to add ``attachments'' to mail they send out.  This can
+be done with the @kbd{C-c C-a} command, which will prompt for a file
+name and a @acronym{MIME} type.
+
+You can also create arbitrarily complex multiparts using the @acronym{MML}
+language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME
+Manual}).
+
+@end ignore
+@node IDNA
+@section \e$B9q:]2=%I%a%$%sL>\e(B
+@cindex IDNA
+@cindex internationalized domain names
+@cindex non-ascii domain names
+
+Message \e$B$O\e(B @acronym{IDNA} \e$B$K=`5r$7$?Aw?.%(!<%8%'%s%H$G$9!#%f!<%6\e(B
+\e$B$O\e(B @acronym{IDNA} \e$B$N$?$a$K0lHL$K$O2?$b$9$kI,MW$,$"$j$^$;$s!#\e(B
+Message \e$B$O\e(B @code{From}\e$B!"\e(B@code{To} \e$B$*$h$S\e(B @code{Cc} \e$B%X%C%@!<$K$"$k\e(B
+\e$BHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$r<+F0E*$K%(%s%3!<%I$7$^$9!#\e(B
+
+\e$B$b$C$H\e(B @acronym{IDNA} \e$B$,M-L>$K$J$k$^$G$O!"<B:]$K%I%a%$%sL>\e(B
+\e$B$r\e(B @acronym{IDNA} \e$B%(%s%3!<%I$9$Y$->l9g$G$b\e(B Message \e$B$O3NG'$r5a$a$^$9!#8=\e(B
+\e$B:_$G$O%I%a%$%sL>$KHs\e(B-@acronym{ASCII} \e$BJ8;z$r4^$`$3$H$,$G$-$k$3$H$K%f!<%6\e(B
+\e$B$N4v?M$+$O5$$E$$$F$$$J$$$+$b$7$l$J$$$N$G!"H`$i$,6vA3$K\e(B
+\e$BHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$r%?%$%W$7$F$7$^$C$?$H$-$N$?$a$K0BA4%M%C%H\e(B
+\e$B$rD%$C$F$$$k$o$1$G$9!#\e(B
+
+@vindex message-use-idna
+\e$BJQ?t\e(B @code{message-use-idna} \e$B$O\e(B @acronym{IDNA} \e$B$r;H$&$+$I$&$+$r@)8f$7$^\e(B
+\e$B$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$@$C$?$i\e(B @acronym{IDNA} \e$B%(%s%3!<%I$O9T$J$o$l$^\e(B
+\e$B$;$s!#%7%s%\%k\e(B @code{ask} \e$B$K@_Dj$5$l$F$$$k\e(B (\e$B%G%#%U%)%k%H\e(B) \e$B$H%f!<%6$O3NG'\e(B
+\e$B$r5a$a$i$l$^$9!#$=$7$F\e(B @code{t} \e$B$K@_Dj$5$l$F$$$k$H!"<+F0E*\e(B
+\e$B$K\e(B @acronym{IDNA} \e$B%(%s%3!<%I$,9T$J$o$l$^$9!#\e(B
+
+@findex message-idna-to-ascii-rhs
+\e$B<B83E*$K\e(B @acronym{IDNA} \e$B%(%s%3!<%I$r9T$J$$$?$$$J$i$P!"\e(B(\e$B%(%s%3!<%I$5$l$?\e(B
+\e$BHs\e(B-@acronym{ASCII} \e$B%I%a%$%sL>$rF@$k$?$a$K\e(B) \e$B%a%C%;!<%8$NJT=8Cf\e(B
+\e$B$K\e(B @kbd{M-x message-idna-to-ascii-rhs RET} \e$B$r%?%$%W$7$F2<$5$$!#\e(B
+
+\e$B$3$N5!G=$r;H$&$K$O\e(B @uref{http://www.gnu.org/software/libidn/, GNU
+Libidn} \e$B$r%$%s%9%H!<%k$7$F$*$/I,MW$,$"$j$^$9!#\e(B
+
+@ignore
+@node Security
+@section Security
+@cindex Security
+@cindex S/MIME
+@cindex PGP
+@cindex PGP/MIME
+@cindex sign
+@cindex encrypt
+@cindex secure
+
+Using the @acronym{MML} language, Message is able to create digitally
+signed and digitally encrypted messages.  Message (or rather
+@acronym{MML}) currently support @acronym{PGP} (RFC 1991),
+@acronym{PGP/MIME} (RFC 2015/3156) and @acronym{S/MIME}.  Instructing
+@acronym{MML} to perform security operations on a @acronym{MIME} part is
+done using the @kbd{C-c C-m s} key map for signing and the @kbd{C-c C-m
+c} key map for encryption, as follows.
+
+@table @kbd
+
+@item C-c C-m s s
+@kindex C-c C-m s s
+@findex mml-secure-message-sign-smime
+
+Digitally sign current message using @acronym{S/MIME}.
+
+@item C-c C-m s o
+@kindex C-c C-m s o
+@findex mml-secure-message-sign-pgp
+
+Digitally sign current message using @acronym{PGP}.
+
+@item C-c C-m s p
+@kindex C-c C-m s p
+@findex mml-secure-message-sign-pgpmime
+
+Digitally sign current message using @acronym{PGP/MIME}.
+
+@item C-c C-m c s
+@kindex C-c C-m c s
+@findex mml-secure-message-encrypt-smime
+
+Digitally encrypt current message using @acronym{S/MIME}.
+
+@item C-c C-m c o
+@kindex C-c C-m c o
+@findex mml-secure-message-encrypt-pgp
+
+Digitally encrypt current message using @acronym{PGP}.
+
+@item C-c C-m c p
+@kindex C-c C-m c p
+@findex mml-secure-message-encrypt-pgpmime
+
+Digitally encrypt current message using @acronym{PGP/MIME}.
+
+@item C-c C-m C-n
+@kindex C-c C-m C-n
+@findex mml-unsecure-message
+Remove security related @acronym{MML} tags from message.
+
+@end table
+
+These commands do not immediately sign or encrypt the message, they
+merely insert the proper @acronym{MML} secure tag to instruct the
+@acronym{MML} engine to perform that operation when the message is
+actually sent.  They may perform other operations too, such as locating
+and retrieving a @acronym{S/MIME} certificate of the person you wish to
+send encrypted mail to.  When the mml parsing engine converts your
+@acronym{MML} into a properly encoded @acronym{MIME} message, the secure
+tag will be replaced with either a part or a multipart tag.  If your
+message contains other mml parts, a multipart tag will be used; if no
+other parts are present in your message a single part tag will be used.
+This way, message mode will do the Right Thing (TM) with
+signed/encrypted multipart messages.
+
+Since signing and especially encryption often is used when sensitive
+information is sent, you may want to have some way to ensure that your
+mail is actually signed or encrypted.  After invoking the above
+sign/encrypt commands, it is possible to preview the raw article by
+using @kbd{C-u C-c RET P} (@code{mml-preview}).  Then you can
+verify that your long rant about what your ex-significant other or
+whomever actually did with that funny looking person at that strange
+party the other night, actually will be sent encrypted.
+
+@emph{Note!}  Neither @acronym{PGP/MIME} nor @acronym{S/MIME} encrypt/signs
+RFC822 headers.  They only operate on the @acronym{MIME} object.  Keep this
+in mind before sending mail with a sensitive Subject line.
+
+By default, when encrypting a message, Gnus will use the
+``signencrypt'' mode, which means the message is both signed and
+encrypted.  If you would like to disable this for a particular
+message, give the @code{mml-secure-message-encrypt-*} command a prefix
+argument, e.g., @kbd{C-u C-c C-m c p}.
+
+Actually using the security commands above is not very difficult.  At
+least not compared with making sure all involved programs talk with each
+other properly.  Thus, we now describe what external libraries or
+programs are required to make things work, and some small general hints.
+
+@subsection Using S/MIME
+
+@emph{Note!}  This section assume you have a basic familiarity with
+modern cryptography, @acronym{S/MIME}, various PKCS standards, OpenSSL and
+so on.
+
+The @acronym{S/MIME} support in Message (and @acronym{MML}) require
+OpenSSL.  OpenSSL performs the actual @acronym{S/MIME} sign/encrypt
+operations.  OpenSSL can be found at @uref{http://www.openssl.org/}.
+OpenSSL 0.9.6 and later should work.  Version 0.9.5a cannot extract mail
+addresses from certificates, and it insert a spurious CR character into
+@acronym{MIME} separators so you may wish to avoid it if you would like
+to avoid being regarded as someone who send strange mail.  (Although by
+sending @acronym{S/MIME} messages you've probably already lost that
+contest.)
+
+To be able to send encrypted mail, a personal certificate is not
+required.  Message (@acronym{MML}) need a certificate for the person to whom you
+wish to communicate with though.  You're asked for this when you type
+@kbd{C-c C-m c s}.  Currently there are two ways to retrieve this
+certificate, from a local file or from DNS.  If you chose a local
+file, it need to contain a X.509 certificate in @acronym{PEM} format.
+If you chose DNS, you're asked for the domain name where the
+certificate is stored, the default is a good guess.  To my belief,
+Message (@acronym{MML}) is the first mail agent in the world to support
+retrieving @acronym{S/MIME} certificates from DNS, so you're not
+likely to find very many certificates out there.  At least there
+should be one, stored at the domain @code{simon.josefsson.org}.  LDAP
+is a more popular method of distributing certificates, support for it
+is planned.  (Meanwhile, you can use @code{ldapsearch} from the
+command line to retrieve a certificate into a file and use it.)
+
+As for signing messages, OpenSSL can't perform signing operations
+without some kind of configuration.  Especially, you need to tell it
+where your private key and your certificate is stored.  @acronym{MML}
+uses an Emacs interface to OpenSSL, aptly named @code{smime.el}, and it
+contain a @code{custom} group used for this configuration.  So, try
+@kbd{M-x customize-group RET smime RET} and look around.
+
+Currently there is no support for talking to a CA (or RA) to create
+your own certificate.  None is planned either.  You need to do this
+manually with OpenSSL or using some other program.  I used Netscape
+and got a free @acronym{S/MIME} certificate from one of the big CA's on the
+net.  Netscape is able to export your private key and certificate in
+PKCS #12 format.  Use OpenSSL to convert this into a plain X.509
+certificate in PEM format as follows.
+
+@example
+$ openssl pkcs12 -in ns.p12 -clcerts -nodes > key+cert.pem
+@end example
+
+The @file{key+cert.pem} file should be pointed to from the
+@code{smime-keys} variable.  You should now be able to send signed mail.
+
+@emph{Note!}  Your private key is now stored unencrypted in the file,
+so take care in handling it.  Storing encrypted keys on the disk are
+supported, and Gnus will ask you for a passphrase before invoking
+OpenSSL.  Read the OpenSSL documentation for how to achieve this.  If
+you use unencrypted keys (e.g., if they are on a secure storage, or if
+you are on a secure single user machine) simply press @code{RET} at
+the passphrase prompt.
+
+@subsection Using PGP/MIME
+
+@acronym{PGP/MIME} requires an external OpenPGP implementation, such
+as @uref{http://www.gnupg.org/, GNU Privacy Guard}.  Pre-OpenPGP
+implementations such as PGP 2.x and PGP 5.x are also supported.  One
+Emacs interface to the PGP implementations, PGG (@pxref{Top, ,PGG,
+pgg, PGG Manual}), is included, but Mailcrypt and Florian Weimer's
+@code{gpg.el} are also supported.
+
+@vindex gpg-temp-directory
+Note, if you are using the @code{gpg.el} you must make sure that the
+directory specified by @code{gpg-temp-directory} have permissions
+0700.
+
+Creating your own key is described in detail in the documentation of
+your PGP implementation, so we refer to it.
+
+If you have imported your old PGP 2.x key into GnuPG, and want to send
+signed and encrypted messages to your fellow PGP 2.x users, you'll
+discover that the receiver cannot understand what you send. One
+solution is to use PGP 2.x instead (i.e., if you use @code{pgg}, set
+@code{pgg-default-scheme} to @code{pgp}).  If you do want to use
+GnuPG, you can use a compatibility script called @code{gpg-2comp}
+available from
+@uref{http://muppet.faveve.uni-stuttgart.de/~gero/gpg-2comp/}.  You
+could also convince your fellow PGP 2.x users to convert to GnuPG.
+@vindex mml-signencrypt-style-alist
+As a final workaround, you can make the sign and encryption work in
+two steps; separately sign, then encrypt a message.  If you would like
+to change this behavior you can customize the
+@code{mml-signencrypt-style-alist} variable.  For example:
+
+@lisp
+(setq mml-signencrypt-style-alist '(("smime" separate)
+                                    ("pgp" separate)
+                                    ("pgpauto" separate)
+                                    ("pgpmime" separate)))
+@end lisp
+
+This causes to sign and encrypt in two passes, thus generating a
+message that can be understood by PGP version 2.
+
+(Refer to @uref{http://www.gnupg.org/gph/en/pgp2x.html} for more
+information about the problem.)
+
+@end ignore
+@node Various Commands
+@section \e$B$$$m$$$m$JL?Na\e(B
+
+@table @kbd
+
+@item C-c C-r
+@kindex C-c C-r
+@findex message-caesar-buffer-body
+\e$B8=:_$N%a%C%;!<%8$r%7!<%6!<JQ49\e(B (\e$BJLL>\e(B rot13) \e$B$7$^\e(B
+\e$B$9\e(B (@code{message-caesar-buffer-body})\e$B!#$b$7HO0O8BDj$,<B9T$5$l$F$$$?$i!"\e(B
+\e$B%P%C%U%!$N8+$($kItJ,$@$1$rJQ49$7$^$9!#?tCM@\F,0z?t$OJ8$r$I$N$/$i$$2sE>$5\e(B
+\e$B$;$k$+$r;XDj$7$^$9!#=i4|CM$O\e(B 13 \e$B$G$9!#\e(B
+
+@item C-c C-e
+@kindex C-c C-e
+@findex message-elide-region
+@vindex message-elide-ellipsis
+\e$B%]%$%s%H$H%^!<%/$N4V$NJ8$r>J$-$^$9\e(B (@code{message-elide-region})\e$B!#J8>O$O\e(B
+\e$B@Z$i$l$F\e(B (killed) \e$BJQ?t\e(B @code{message-elide-ellipsis} \e$B$NCM$GCV$-49$($i$l\e(B
+\e$B$^$9!#%G%#%U%)%k%H$N>JN,Id9f$H$7$F;H$o$l$kCM$O\e(B (@samp{[...]}) \e$B$G$9!#\e(B
+
+@item C-c C-z
+@kindex C-c C-x
+@findex message-kill-to-signature
+\e$B=pL>$^$G$+!"$=$l$,L5$1$l$P5-;v$N:G8e$^$G$NA4$F$NJ8$r@Z$j$^\e(B
+\e$B$9\e(B (@code{message-kill-to-signature})\e$B!#\e(B
+
+@item C-c C-v
+@kindex C-c C-v
+@findex message-delete-not-region
+\e$B%a%C%;!<%8$NK\BN$N%j!<%8%g%s$N30$NA4$F$NJ8$r>C5n$7$^\e(B
+\e$B$9\e(B (@code{message-delete-not-region})\e$B!#\e(B
+
+@item M-RET
+@kindex M-RET
+@findex message-newline-and-reformat
+4\e$B$D$N?7$7$$9T$rA^F~$7!"$b$7%]%$%s%H$,0zMQJ8$N4V$K$"$k$J$i$P!":F@07A$7$^\e(B
+\e$B$9!#\e(B
+
+\e$B$3$l$ONc$G$9\e(B:
+
+@example
+> \e$B$3$l$O2?$+$N0zMQJ8$G$9!#\e(B \e$B$=$7$F!"$3$3$K$O$b$C$H0zMQJ8$,$"$j$^$9!#\e(B
+@end example
+
+\e$B$b$7!"%]%$%s%H$,\e(B @samp{\e$B$=$7$F\e(B} \e$B$NA0$K$"$j!"\e(B@kbd{M-RET} \e$B$r2!$7$?$J$i!"0J\e(B
+\e$B2<$N$h$&$J$b$N$rF@$^$9\e(B:
+
+@example
+> \e$B$3$l$O2?$+$N0zMQJ8$G$9!#\e(B
+
+*
+
+> \e$B$=$7$F!"$3$3$K$O$b$C$H0zMQJ8$,$"$j$^$9!#\e(B
+@end example
+
+@samp{*} \e$B$O%]%$%s%H$,CV$+$l$F$$$k>l=j$G$9!#\e(B
+
+@item C-c M-r
+@kindex C-c M-r
+@findex message-rename-buffer
+\e$B%P%C%U%!$NL>A0$rJQ99$7$^$9\e(B (@code{message-rename-buffer})\e$B!#@\F,0z?t$rM?\e(B
+\e$B$($i$l$l$P!"?7$7$$%P%C%U%!L>$NF~NO$rB%?J$7$^$9!#\e(B
+
+@item TAB
+@kindex TAB
+@findex message-tab
+@vindex message-tab-body-function
+@code{message-tab-body-function} \e$B$K@_Dj$5$l$F$$$k4X?t$r<B9T$7$^$9!#$5$b\e(B
+\e$B$J$1$l$P\e(B (\e$B$=$l$,\e(B @code{nil} \e$B$@$C$?$i\e(B)\e$B!"\e(B
+@code{text-mode-map} \e$B$+\e(B @code{global-map} \e$B$N\e(B @kbd{TAB} \e$B%-!<$K3d$jEv$F$i\e(B
+\e$B$l$F$$$k%3%^%s%I$r;H$$$^$9!#\e(B
+@end table
+
+@node Sending
+@section \e$BAw?.\e(B
+
+@table @kbd
+@item C-c C-c
+@kindex C-c C-c
+@findex message-send-and-exit
+\e$B%a%C%;!<%8$rAw?.$7!"8=:_$N%P%C%U%!$rKd$a$^\e(B
+\e$B$9\e(B (@code{message-send-and-exit})\e$B!#\e(B
+
+@item C-c C-s
+@kindex C-c C-s
+@findex message-send
+\e$B%a%C%;!<%8$rAw?.$7$^$9\e(B (@code{message-send})\e$B!#\e(B
+
+@item C-c C-d
+@kindex C-c C-d
+@findex message-dong-send
+\e$B%a%C%;!<%8%P%C%U%!$rKd$a$F=*N;$7$^$9\e(B (@code{message-dont-send})\e$B!#\e(B
+
+@item C-c C-k
+@kindex C-c C-k
+@findex message-kill-buffer
+@vindex message-kill-buffer-and-remove-file
+\e$B%a%C%;!<%8%P%C%U%!$r@Z$C$F=*N;$7$^$9\e(B (@code{message-kill-buffer})\e$B!#$=$N\e(B
+\e$B%U%l!<%`$,%a%C%;!<%8@lMQ$K:n$i$l$?$b$N$@$C$?>l9g$O!"%U%l!<%`$r:o=|$7$^$9!#\e(B
+@code{message-kill-buffer-and-remove-file} \e$B$,Hs\e(B-@code{nil} \e$B$G!"$+$D%P%C\e(B
+\e$B%/%"%C%W%U%!%$%k$,$G$-$F$$$?$i!"%f!<%6$K3NG'$7$F$+$i$=$l$b:o=|$7$^$9!#\e(B
+
+@item C-x k
+@kindex C-x k
+@findex message-mimic-kill-buffer
+@vindex message-kill-buffer-and-remove-file
+@code{kill-buffer} \e$B$N%$%_%F!<%7%g%s$G\e(B
+\e$B$9\e(B (@code{message-mimic-kill-buffer})\e$B!#\e(B
+@code{message-kill-buffer-and-remove-file} \e$B$r0l;~E*$K\e(B @code{nil} \e$B$KB+G{\e(B
+\e$B$7$F\e(B @code{message-kill-buffer} \e$B$r8F$S$^$9!#\e(B
+@end table
+
+@node Mail Aliases
+@section \e$B%a!<%kJLL>\e(B
+@cindex mail aliases
+@cindex aliases
+
+@vindex message-mail-alias-type
+\e$BJQ?t\e(B @code{message-mail-alias-type} \e$B$O$I$N$h$&$J7?$N%a!<%kJLL>\e(B (mail
+alias) \e$B?-D%$r;H$&$+$r@)8f$7$^$9!#8=:_$G$O!"0l$D$NMM<0$@$1$,;HMQ2DG=$G\e(B
+\e$B$9\e(B---Message \e$B$O%a!<%kJLL>$r07$&$?$a$K\e(B @code{mailabbrev} \e$B$r;H$$$^$9!#$b$7\e(B
+\e$B$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$J$i!"%a!<%kJLL>?-D%$O<B9T$5$l$^$;$s!#\e(B
+
+@code{Mailabbrev} \e$B$O\e(B @file{/etc/mailrc} \e$B$H\e(B @file{~/.mailrc} \e$B%U%!%$%k$r2r\e(B
+\e$B@O$9$k;v$K$h$jF0:n$7$^$9!#%U%!%$%k$O<!$N$h$&$K$J$C$F$$$^$9\e(B:
+
+@example
+alias lmi "Lars Magne Ingebrigtsen <larsi@@ifi.uio.no>"
+alias ding "ding@@ifi.uio.no (ding mailing list)"
+@end example
+
+\e$B$3$N$h$&$J9T$r\e(B @file{~/.mailrc} \e$B%U%!%$%k$KDI2C$7$?8e$G!"\e(B
+@code{To} \e$B$d\e(B @code{Cc} (\e$BEy$J$I\e(B) \e$B$N%X%C%@!<$G\e(B @samp{lmi} \e$B$H=q$$$F!"\e(B
+@kbd{SPC} \e$B$r2!$9$@$1$GJLL>$r?-D%$7$^$9!#\e(B
+
+\e$B%a%C%;!<%8$rAw$k$H$-$K$O?-D%$O9T$o$l$^$;$s\e(B---\e$BA4$F$N?-D%$OL@<(E*$K9T$o$l\e(B
+\e$B$J$/$F$O$J$j$^$;$s!#\e(B
+
+@node Spelling
+@section Emacs \e$B$K%9%Z%k%A%'%C%/$5$;$k\e(B
+@cindex spelling
+@findex ispell-message
+
+Emacs \e$B$G%9%Z%k%A%'%C%/$9$k$?$a$KIa5Z$7$F$$$kFs$D$NJ}K!!"\e(B
+@code{ispell} \e$B$H\e(B @code{flyspell} \e$B$,$"$j$^$9!#\e(B@code{ispell} \e$B$NJ}$O@N$+$i\e(B
+\e$B$"$C$F!"$?$V$s$h$j0lHLE*$J%Q%C%1!<%8$G$9!#$"$J$?$ONc$K$h$C$F:G=i$K%a%C%;!<\e(B
+\e$B%8$r=q$$$F$+$iA4BN$r\e(B @code{ispell} \e$B$KDL$7!"$9$Y$F$N=q$-B;$8$r=$@5$7$^$9!#\e(B
+\e$B%a%C%;!<%8$rAw?.$9$k$H$-$K$=$l$r<+F0E*$K9T$J$&$?$a$K$O!"\e(B.emacs \e$B%U%!%$%k\e(B
+\e$B$K0J2<$N$h$&$J$b$N$rF~$l$F2<$5$$!#\e(B
+
+@lisp
+(add-hook 'message-send-hook 'ispell-message)
+@end lisp
+
+@vindex ispell-message-dictionary-alist
+\e$B$b$7$"$J$?$,0c$&8@8l$G=q$/=,47$J$i$P!"$=$l$OJQ\e(B
+\e$B?t\e(B @code{ispell-message-dictionary-alist} \e$B$G@)8f$G$-$^$9!#\e(B
+
+@lisp
+(setq ispell-message-dictionary-alist
+      '(("^Newsgroups:.*\\bde\\." . "deutsch8")
+        (".*" . "default")))
+@end lisp
+
+@code{ispell} \e$B$O%$%s%9%H!<%k$5$l$?\e(B @samp{ispell} \e$B%3%^%s%I$K0MB8$7$F$$$^\e(B
+\e$B$9!#\e(B
+
+\e$B$b$&0lJ}$NIa5Z$7$F$$$kJ}K!$O\e(B @code{flyspell} \e$B$r;H$&$3$H$G$9!#$3$N%Q%C%1!<\e(B
+\e$B%8$O$"$J$?$,=q$$$F$$$k:GCf$K%9%Z%k%A%'%C%/$r9T$J$$!"$$$m$s$JJ}K!$G4V0c$C\e(B
+\e$B$?%9%Z%k$N8l$r;XE&$7$F$/$l$^$9!#\e(B
+
+@code{flyspell} \e$B$r;H$&$K$O!"0J2<$N$h$&$J$b$N$r\e(B .emacs \e$B%U%!%$%k$KF~$l$F2<\e(B
+\e$B$5$$!#\e(B
+
+@lisp
+(defun my-message-setup-routine ()
+  (flyspell-mode 1))
+(add-hook 'message-setup-hook 'my-message-setup-routine)
+@end lisp
+
+@code{flyspell} \e$B$O%$%s%9%H!<%k$5$l$?\e(B @samp{ispell} \e$B%3%^%s%I$K0MB8$7$F$$\e(B
+\e$B$^$9!#\e(B
+
+@node Variables
+@chapter \e$BJQ?t\e(B
+
+@menu
+* Message Headers::             \e$B0lHLE*$J%a%C%;!<%8%X%C%@!<$N$h$&$J$b$N\e(B
+* Mail Headers::                \e$B%a!<%k%X%C%@!<$r%+%9%?%^%$%:$9$k\e(B
+* Mail Variables::              \e$BB>$N%a!<%kJQ?t\e(B
+* News Headers::                \e$B%K%e!<%9%X%C%@!<$r%+%9%?%^%$%:$9$k\e(B
+* News Variables::              \e$BB>$N%K%e!<%9JQ?t\e(B
+* Insertion Variables::         \e$BA^F~$N$5$lJ}$r%+%9%?%^%$%:$9$k\e(B
+* Various Message Variables::   \e$BB>$N%a%C%;!<%8JQ?t\e(B
+* Sending Variables::           \e$BAw?.$9$k$?$a$NJQ?t\e(B
+* Message Buffers::             Message \e$B$,$=$N%P%C%U%!$NL>A0$rIU$1$kJ}K!\e(B
+* Message Actions::             \e$B=*N;$9$k$H$-$K<B9T$5$l$kF0:n\e(B
+@end menu
+
+@node Message Headers
+@section \e$B%a%C%;!<%8%X%C%@!<\e(B
+
+Message \e$B$O%a%C%;!<%8:n@.ItJ,$K4X$7$F$OHs>o$K@Q6KE*$G$9!#$=$l$O<!$N$h$&$G\e(B
+\e$B$J$1$l$P$J$j$^$;$s\e(B -- \e$B$=$l$O%K%e!<%9$H%a!<%k$NJ#9gBeM}$G$9!#J#9g%a%C%;!<\e(B
+\e$B%8$rAw$k;v$,$G$-$k$h$&$K!"$^$?!"$=$l$O%a%C%;!<%8$N%a!<%k$H%K%e!<%9$NJ#@=\e(B
+\e$B$,==J,$KF1$8$h$&$K8+$($k$h$&$K!"A4$F$N%X%C%@!<$r$=$l<+?H$G:n@.$7$^$9!#\e(B
+
+@table @code
+
+@item message-generate-headers-first
+@vindex message-generate-headers-first
+@code{t} \e$B$J$i$P!"%a%C%;!<%8$N:n@.$r;O$a$kA0$KA4$F$NI,MW$J%X%C%@!<$r:n@.\e(B
+\e$B$7$^$9!#$3$l$O:n@.$9$k%X%C%@!<$N%j%9%H$G$"$k$3$H$b$G$-$^$9\e(B:
+
+@lisp
+(setq message-generate-headers-first
+      '(References))
+@end lisp
+
+@vindex message-required-headers
+\e$BJQ?t\e(B @code{message-required-headers}\e$B!"\e(B
+@code{message-required-mail-headers} \e$B$*$h\e(B
+\e$B$S\e(B @code{message-required-news-headers} \e$B$G!"$I$N%X%C%@!<$,I,MW$+$r;XDj$7\e(B
+\e$B$^$9!#\e(B
+
+\e$B$$$/$D$+$N%X%C%@!<$O!"Aw?.$9$kA0$K>C$5$l$?$j:n$jD>$5$l$?$j$7$^$9!#$3$l$K\e(B
+\e$B$OJQ?t\e(B @code{message-deletable-headers} (\e$B8e=R\e(B) \e$B$,4X78$7$^$9!#\e(B
+
+@item message-draft-headers
+@vindex message-draft-headers
+Message \e$B$,\e(B gnus \e$B>e$GAv$C$F$$$k>l9g!"%a%C%;!<%8%P%C%U%!$O%I%i%U%H%0%k!<%W\e(B
+\e$B$H4XO"IU$1$i$l$F$$$^$9!#\e(B@code{message-draft-headers} \e$B$O!"$=$N%I%i%U%H%0\e(B
+\e$B%k!<%W$K%I%i%U%H$,5-O?$5$l$k$H$-$K!"$I$N%X%C%@!<$,:n@.$5$l$k$Y$-$+$r;X<(\e(B
+\e$B$7$^$9!#\e(B
+
+@item message-from-style
+@vindex message-from-style
+@code{From} \e$B%X%C%@!<$,$I$N$h$&$K8+$($k$+$r;XDj$7$^$9!#0J2<$N#4$D$NCM$,;H\e(B
+\e$B$($^$9\e(B:
+
+@table @code
+@item nil
+\e$B%"%I%l%9$@$1$G$9\e(B -- @samp{king@@grassland.com}.
+
+@item parens
+@samp{king@@granssland.com (Elvis Parsley)}.
+
+@item angles
+@samp{Elvis Parsley <king@@grassland.com>}.
+
+@item default
+\e$B$=$l$,0zMQId9f$rMW5a$7$J$1$l$P\e(B @code{angles} \e$B$N$h$&$K8+$(!"$b$70zMQId9f\e(B
+\e$B$,MW5a$5$l$k>l9g$O\e(B @code{parens} \e$B$N$h$&$K8+$($^$9!#\e(B@code{parens} \e$B$,0zMQ\e(B
+\e$BId9f$rMW5a$7$?$H$7$F$b!"$H$K$+$/\e(B @code{angles} \e$B$r;H$$$^$9!#\e(B
+@end table
+
+@item message-deletable-headers
+@vindex message-deletable-headers
+\e$B$3$N%j%9%H$K$"$k!"0JA0$K\e(B Message \e$B$K$h$j:n@.$5$l$?%X%C%@!<$OEj9F$9$kA0$K\e(B
+\e$B:o=|$5$l$^$9!#5-;v$rEj9F$9$k$H$7$^$7$g$&!#$=$l$+$i!"$o$s$Q$/K7<g$J$"$J$?\e(B
+\e$B$O$=$l$r2?$+B>$N%0%k!<%W$K:F$SEj9F$9$k;v$K7hDj$7$?$N$G!"\e(B
+@code{*post-buf*} \e$B%P%C%U%!$KLa$j!"\e(B@code{Newsgroups} \e$B9T$rJT=8$7!":F$SAw$j\e(B
+\e$B=P$7$?$H$7$^$9!#=i4|@_Dj$G$O!"$3$NJQ?t$OA0$K:n@.$5$l$?8E\e(B
+\e$B$$\e(B @code{Message-ID} \e$B$,<h$j=|$+$l!"?7$7$$$b$N$,:n@.$5$l$k;v$r3N<B$K$7$F\e(B
+\e$B$$$^$9!#$b$7$3$l$,$J$5$l$J$$$H!"Dk9qA4BN$O$*$=$i$/Jx2u$7!"L5@/I\<g5A$,?;\e(B
+\e$BF)$7!"G-$,\e(B2\e$BK\$NB-$GJb$-;O$a!"@$3&$r;YG[$9$k$G$7$g$&!#J9$/$H$3$m$K0M$l$P!#\e(B
+
+@item message-default-headers
+@vindex message-default-headers
+\e$B$3$NJ8;zNs$OA4$F$N%a%C%;!<%8%P%C%U%!$N%X%C%@!<$N:G8e$KA^F~$5$l$^$9!#\e(B
+
+@item message-subject-re-regexp
+@vindex message-subject-re-regexp
+@cindex Aw
+@cindex Sv
+@cindex Re
+\e$B%a%C%;!<%8$X$N1~Ez$O\e(B @samp{Re: } \e$B$G;O$^$j$^$9!#$3$l$O1Q8l\e(B
+\e$B$N\e(B ``response'' \e$B$NN,$G$O\e(B @emph{\e$B$"$j$^$;$s\e(B} \e$B$,!"%i%F%s8l$G!"\e(B``\e$B$=$l$K1~Ez\e(B
+\e$B$7$F\e(B'' (in response to) \e$B$H8@$&0UL#$G$9!#$$$/$D$+$NL53X$NGO</$O$3$N;v<B$r\e(B
+\e$BF@$k;v$K<:GT$7!"H`$i$N%=%U%H%&%'%"$r4w$^$o$7\e(B
+\e$B$$\e(B @samp{Aw: } (``antwort'') \e$B$d\e(B @samp{Sv: } (``svar'') \e$B$rBe$o$j$K;H$&$h\e(B
+\e$B$&$K\e(B ``\e$B9q:]2=\e(B'' \e$B$7$^$7$?!#$=$l$O0UL#$,L5$/!"<Y0-$G$9!#$7$+$7!"$3$l$i$N<Y\e(B
+\e$B0-$JF;6q$r;H$C$?MxMQ<T$r07$o$J$1$l$P$J$i$J$$$+$b$7$l$^$;$s$N$G!"$=$N$h$&\e(B
+\e$B$J>l9g$O$3$NJQ?t$r$3$l$i$N@\F,8l$K9g$&$h$&$J@55,I=8=$K@_Dj$9$k$G$7$g$&!#\e(B
+\e$B;d<+?H$O!"$=$N$h$&$J5,3J$K=>$o$J$$%a!<%k$O$?$@<N$F5n$C$F$$$k$@$1$G$9!#\e(B
+
+\e$B$3$l$O!"JV;v$r$9$k$H$-$K$3$l$i$N%X%C%@!<$r=hM}$9$kCM$NNc$G$9\e(B:
+
+@lisp
+(setq message-subject-re-regexp
+      (concat
+       "^[ \t]*"
+         "\\("
+           "\\("
+             "[Aa][Nn][Tt][Ww]\\.?\\|"     ; antw
+             "[Aa][Ww]\\|"                 ; aw
+             "[Ff][Ww][Dd]?\\|"            ; fwd
+             "[Oo][Dd][Pp]\\|"             ; odp
+             "[Rr][Ee]\\|"                 ; re
+             "[Rr][\311\351][Ff]\\.?\\|"   ; ref
+             "[Ss][Vv]"                    ; sv
+           "\\)"
+           "\\(\\[[0-9]*\\]\\)"
+           "*:[ \t]*"
+         "\\)"
+       "*[ \t]*"
+       ))
+@end lisp
+
+@item message-subject-trailing-was-query
+@vindex message-subject-trailing-was-query
+@vindex message-subject-trailing-was-ask-regexp
+@vindex message-subject-trailing-was-regexp
+\e$BBjL>$N9T$KB3$1$k\e(B @samp{(was: <\e$B8E$$BjL>\e(B>)} \e$B$r$I$&$9$k$+$r@)8f$7$^$9!#\e(B
+@code{nil} \e$B$@$C$?$iBjL>$r$=$N$^$^$K$7$F$*$-$^$9!#\e(B@code{ask} \e$B$H$$$&%7%s%\\e(B
+\e$B%k$@$C$?$i!"$I$&$9$k$+$r%f!<%6$K?R$M$^$9!#BjL>\e(B
+\e$B$,\e(B @code{message-subject-trailing-was-ask-regexp} \e$B$K9gCW$9$k>l9g$@$1$G$9\e(B
+\e$B$,!#\e(B@code{message-subject-trailing-was-query} \e$B$,\e(B @code{t} \e$B$@$C$?$i!">o$K\e(B
+\e$B$V$i2<$,$C$?8E$$BjL>$r$O$.<h$j$^$9!#$=$N>l9g\e(B
+\e$B$O\e(B @code{message-subject-trailing-was-regexp} \e$B$,;H$o$l$^$9!#\e(B
+
+@item message-alternative-emails
+@vindex message-alternative-emails
+\e$BBe$o$j$N%a!<%k%"%I%l%9$K9gCW$9$k@55,I=8=$G$9!#:G=i$K%^%C%A$7$?\e(B (\e$BBh0l5A$G\e(B
+\e$B$O$J$$\e(B) \e$B%"%I%l%9$,\e(B @code{From} \e$B%U%#!<%k%I$G;H$o$l$^$9!#\e(B
+(\e$BLuCm\e(B: To \e$B$+\e(B Cc \e$B$K$"$k%"%I%l%9$G!":G=i$K$3$N@55,I=8=$K9gCW$7!"\e(B
+\e$B$+$D\e(B @code{user-mail-address} \e$B$H$O0c$&$b$N$,!"\e(B@code{From} \e$B%U%#!<%k%I$N%a!<\e(B
+\e$B%k%"%I%l%9$H$7$F;H$o$l$^$9!#\e(B)
+
+@item message-allow-no-recipients
+@vindex message-allow-no-recipients
+@code{Gcc} \e$B$H\e(B @code{Fcc} \e$B0J30$K<u<h?M$,$$$J$+$C$?>l9g$K!"2?$r$9$k$+$r@_\e(B
+\e$BDj$7$^$9!#\e(B@code{always} \e$B$@$C$?$i$H$K$+$/Aw?.$7!"\e(B@code{never} \e$B$@$C$?$iAw\e(B
+\e$B?.$7$^$;$s!#\e(B@code{ask} (\e$B$=$l$,%G%#%U%)%k%H\e(B) \e$B$@$C$?$i!"$I$&$9$k$+?R$M$i$l\e(B
+\e$B$^$9!#\e(B
+
+@item message-hidden-headers
+@vindex message-hidden-headers
+\e$B@55,I=8=!"@55,I=8=$N%j%9%H!"$^$?$O:G=i$NMWAG$,\e(B @code{not} \e$B$G;D$j$,@55,I=\e(B
+\e$B8=$G$"$k%j%9%H!#%a%C%;!<%8$N:n@.Cf$K$I$N%X%C%@!<$r1#$7$?$^$^$K$7$F$*$/$+\e(B
+\e$B$r7h$a$^$9!#\e(B
+
+@lisp
+(setq message-hidden-headers
+      '(not "From" "Subject" "To" "Cc" "Newsgroups"))
+@end lisp
+
+@item message-header-synonyms
+@vindex message-header-synonyms
+\e$B%X%C%@!<F10U8l%j%9%H$N%j%9%H!#Nc$($P$3$N%j%9%H\e(B
+\e$B$,\e(B @code{Cc} \e$B$H\e(B @code{To} \e$B$N%a%s%P!<!&%j%9%H$r4^$s$G$$$k$H!"%a%C%;!<%8$,\e(B
+\e$B$9$G$K<u?.<T$K\e(B @code{Cc} \e$B$5$l$F$$$k>l9g!"\e(B
+@code{message-carefully-insert-headers} \e$B$O\e(B @code{To} \e$B%X%C%@!<$rA^F~$7$^\e(B
+\e$B$;$s!#\e(B
+@end table
+
+@node Mail Headers
+@section \e$B%a!<%k%X%C%@!<\e(B
+
+@table @code
+@item message-required-mail-headers
+@vindex message-required-mail-headers
+\e$B$3$NJQ?t$N9=J8$rCN$j$?$1$l$P!"\e(B@xref{News Headers} \e$B$r;2>H$7$F2<$5$$!#$=$l\e(B
+\e$B$N=i4|CM$O\e(B @code{(From Date Subject (optional . In-Reply-To) Message-ID
+Lines (optional . User-Agent))} \e$B$G$9!#\e(B
+
+@item message-ignored-mail-headers
+@vindex message-ignored-mail-headers
+\e$B%a!<%k$r=P$9A0$K<h$j=|$+$l$k%X%C%@!<$N@55,I=8=$G$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{^[GF]cc:\\|^Resent-Fcc:\\|^Xref:\\|^X-Draft-From:} \e$B$G$9!#\e(B
+
+@item message-default-mail-headers
+@vindex message-default-mail-headers
+\e$B$3$NJ8;zNs$O%a!<%k$H$7$F=i4|2=$5$l$?A4$F$N%a%C%;!<%8%P%C%U%!$N%X%C%@!<$N\e(B
+\e$B:G8e$NA^F~$5$l$^$9!#\e(B
+@end table
+
+@node Mail Variables
+@section \e$B%a!<%kJQ?t\e(B
+
+@table @code
+@item message-send-mail-function
+@vindex message-send-mail-function
+@findex message-send-mail-with-sendmail
+@findex message-send-mail-with-mh
+@findex message-send-mail-with-qmail
+@findex message-send-mail-with-smtp
+@findex message-smtpmail-send-it
+@findex smtpmail-send-it
+@findex feedmail-send-it
+\e$B8=:_$N%P%C%U%!$r%a!<%k$H$7$FAw$k$?$a$K;H$o$l$k4X?t$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{message-send-mail-with-sendmail} \e$B$G$9!#B>\e(B
+\e$B$K\e(B @code{message-send-mail-with-mh},
+@code{message-send-mail-with-qmail}, @code{message-send-mail-with-smtp},
+@code{message-smtpmail-send-it}, @code{smtpmail-send-it} \e$B$*$h\e(B
+\e$B$S\e(B @code{feedmail-send-it} \e$B$,;H$($^$9!#\e(B
+
+@item message-mh-deletable-headers
+@vindex message-mh-deletable-headers
+\e$B$[$H$s$I$NHG$N\e(B MH \e$B$O$3$NJQ?t$N%X%C%@!<$r4^$`%a%C%;!<%8$r?)$o$5$l$k$N$r7y\e(B
+\e$B$$$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$J$$$J$i\e(B (\e$B$3$l$,=i4|@_Dj$G$9$,\e(B)\e$B!"$3$l$i\e(B
+\e$B$N%X%C%@!<$O\e(B MH \e$B$r;H$C$F%a%C%;!<%8$rAw$C$F$$$k$H$-$K$O<h$j=|$+$l$^$9!#$"\e(B
+\e$B$J$?$N\e(B MH \e$B$,$3$l$i$N%X%C%@!<$r07$($k$N$G$"$l$P!"$=$l$r\e(B @code{nil} \e$B$K@_Dj\e(B
+\e$B$7$F2<$5$$!#\e(B
+
+@item message-qmail-inject-program
+@vindex message-qmail-inject-program
+@cindex qmail
+qmail-inject \e$B%W%m%0%i%`$G$9!#\e(B
+
+@item message-qmail-inject-args
+@vindex message-qmail-inject-args
+qmail-inject \e$B%W%m%0%i%`$KEO$90z?t$G$9!#$3$l$OJ8;zNs$N%j%9%H$G!"$=$l$>$l\e(B
+\e$B$N0z?t$O0l$D$NJ8;zNs$G$J$1$l$P$J$j$^$;$s!#$3$l$O4X?t$G$bNI$$$G$9!#\e(B
+
+\e$BNc$($P!"@5$7$$>l=j$KD7$MJV$7$?$j!"%a!<%j%s%0%j%9%H$N47=,$K=>$&$?$a\e(B
+\e$B$K\e(B envelope sender \e$B$N%"%I%l%9$r@_Dj$7$?$$>l9g$O!"$3$NJQ?t\e(B
+\e$B$r\e(B @code{'("-f" "you@@some.where")} \e$B$K@_Dj$9$l$PNI$$$G$7$g$&!#\e(B
+
+@item message-sendmail-f-is-evil
+@vindex message-sendmail-f-is-evil
+@cindex sendmail
+\e$BHs\e(B-@code{nil} \e$B$G\e(B sendmail \e$B$N%3%^%s%I9T$K\e(B @samp{-f username} \e$B$rIU2C$7$^$;\e(B
+\e$B$s!#$=$&$9$k$3$H$O!"IU2C$7$J$$$h$j<Y0-$G$9$i$"$k$G$7$g$&!#\e(B
+
+@item message-sendmail-envelope-from
+@vindex message-sendmail-envelope-from
+@code{message-sendmail-f-is-evil} \e$B$,\e(B @code{nil} \e$B$N$H$-!"$3$l\e(B
+\e$B$G\e(B @acronym{SMTP} \e$B%(%s%Y%m!<%W$G;H$&%"%I%l%9$r;XDj$7$^$9!#\e(B@code{nil} \e$B$@$C\e(B
+\e$B$?$i\e(B @code{user-mail-address} \e$B$r;H$$$^$9!#%7%s%\%k\e(B @code{header} \e$B$@$C$?\e(B
+\e$B$i!"%a%C%;!<%8$N\e(B @samp{From} \e$B%X%C%@!<$r;H$$$^$9!#\e(B
+
+@item message-mailer-swallows-blank-line
+@vindex message-mailer-swallows-blank-line
+\e$B%7%9%F%`$N%a%$%i!<$,%X%C%@!<$HK\J8$r0l=o$K$7$F$7$^$&>l9g$O!"\e(B
+\e$BHs\e(B-@code{nil} \e$B$K@_Dj$7$F2<$5$$!#\e(B(SunOS 4 \e$B$G\e(B sendmail \e$B$,%j%b!<%H%b!<%I$G\e(B
+\e$BF0:n$9$k>l9g$,3:Ev$7$^$9!#\e(B) \e$BCM$O!">c32$,<B:]$K5/$-$k$+$I$&$+$r%F%9%H$9$k\e(B
+\e$B$?$a$N<0$K$9$Y$-$G$9!#\e(B
+
+@c @item message-send-mail-partially-limit
+@c @vindex message-send-mail-partially-limit
+@c @cindex split large message
+@c The limitation of messages sent as message/partial.
+@c The lower bound of message size in characters, beyond which the message
+@c should be sent in several parts. If it is nil, the size is unlimited.
+@end table
+
+@node News Headers
+@section \e$B%K%e!<%9%X%C%@!<\e(B
+
+@vindex message-required-news-headers
+@code{message-required-news-headers} \e$B$O%X%C%@!<%7%s%\%k$N%j%9%H$G$9!#$3\e(B
+\e$B$l$i$N%X%C%@!<$O<+F0E*$K:n@.$5$l$k$+!"$b$7$/$O$=$l$,IT2DG=$G$"$l$P!"F~NO\e(B
+\e$B$rB%?J$7$^$9!#0J2<$N%7%s%\%k$,;H$($^$9\e(B:
+
+@table @code
+
+@item From
+@cindex From
+@findex user-full-name
+@findex user-mail-address
+\e$B$3$NI,MW$J%X%C%@!<$O4X?t\e(B @code{message-make-from} \e$B4X?t$N7k2L$K$h$j:n$i$l!"\e(B
+\e$B$=$l$OJQ?t\e(B @code{message-from-style}, @code{user-full-name},
+@code{user-mail-address} \e$B$K0MB8$7$^$9!#\e(B
+
+@item Subject
+@cindex Subject
+\e$B$3$NI,MW$J%X%C%@!<$O!"$^$@B8:_$7$J$$>l9g$OF~NO$rB%?J$5$l$^$9!#\e(B
+
+@item Newsgroups
+@cindex Newsgroups
+\e$B$3$NI,MW$J%X%C%@!<$O$I$N%K%e!<%9%0%k!<%W$K5-;v$,Ej9F$5$l$k;v$K$J$k$+$r;X\e(B
+\e$BDj$7$^$9!#$b$7$^$@B8:_$7$F$$$J$$$J$i!"F~NO$rB%?J$5$l$^$9!#\e(B
+
+@item Organization
+@cindex organization
+@vindex message-user-organization
+@vindex message-user-organization-file
+\e$B$3$NA*BrG$0U$J%X%C%@!<$OJQ?t\e(B @code{message-user-organization} \e$B$K0MB8$7$F\e(B
+\e$B:n@.$5$l$^$9!#$b$7$3$NJQ?t$,\e(B @code{t} \e$B$G$"$l$P!"\e(B
+@code{message-user-organization-file} \e$B$,;H$o$l$^$9!#$3$NJQ?t$OJ8;zNs$G$"\e(B
+\e$B$k;v$b$G$-\e(B (\e$B$=$N>l9g$O$=$NJ8;zNs$,;H$o$l$^$9\e(B)\e$B!"4X?t$G$"$k;v$b$G$-$^\e(B
+\e$B$9\e(B (\e$B$=$N4X?t$O0z?tL5$7$G8F$P$l!";H$o$l$kJ8;zNs$rJV$9I,MW$,$"$j$^$9\e(B)\e$B!#\e(B
+
+@item Lines
+@cindex Lines
+\e$B$3$NA*BrG$0U$J%X%C%@!<$O\e(B Message \e$B$K$h$j7W;;$5$l$^$9!#\e(B
+
+@item Message-ID
+@cindex Message-ID
+@vindex message-user-fqdn
+@vindex mail-host-address
+@vindex user-mail-address
+@findex system-name
+@cindex Sun
+@cindex i-did-not-set--mail-host-address--so-tickle-me
+\e$B$3$NI,MW$J%X%C%@!<$O\e(B Message \e$B$K$h$j:n@.$5$l$^$9!#F|IU!";~4V!"MxMQ<TL>!"\e(B
+\e$B%7%9%F%`L>$K4p$E$$$?B>$KL5$$\e(B ID \e$B$,:n@.$5$l$^$9!#%I%a%$%s$N9`$K$D$$$F$O!"\e(B
+\e$BM-8z$J\e(B FQDN (\e$B40A4$K>r7o$rK~$?$7$?%I%a%$%sL>\e(B) \e$B$i$7$$$b$N$,8+$D$+$i$J$$>l\e(B
+\e$B9g!"\e(Bmessage \e$B$O\e(B @code{message-user-fqdn}, @code{system-name},
+@code{mail-host-address} \e$B$*$h$S\e(B @code{message-user-mail-address} (\e$B$9$J$o\e(B
+\e$B$A\e(B @code{user-mail-address}) \e$B$r\e(B (\e$B$3$N=g$G\e(B) \e$BC5$7$^$9!#\e(B
+
+@item User-Agent
+@cindex User-Agent
+\e$B$3$NA*Br<+M3$J%X%C%@!<$O%m!<%+%kJQ?t\e(B @code{message-newsreader} \e$B$K$7$?$,$C\e(B
+\e$B$F:n$i$l$^$9!#\e(B
+
+@item In-Reply-To
+\e$B$3$NA*Br<+M3$J%X%C%@!<$OJVEz$7$F$$$k5-;v$N\e(B @code{Date} \e$B$H\e(B @code{From} \e$B%X%C\e(B
+\e$B%@!<$r;H$C$F:n$i$l$^$9!#\e(B
+
+@item Expires
+@cindex Expires
+@vindex message-expires
+\e$B$3$NHs>o$KA*Br<+M3$J%X%C%@!<$OJQ?t\e(B @code{message-expires} \e$B$K$7$?$,$C$FA^\e(B
+\e$BF~$5$l$^$9!#$3$l$O<+J,$,2?$r$7$F$$$k$+$rCN$i$J$$8B$j!";HMQ$OA4$/4+$a$i$l\e(B
+\e$B$^$;$s!#\e(B
+
+@item Distribution
+@cindex Distribution
+@vindex message-distribution-function
+\e$B$3$NA*Br<+M3$J%X%C%@!<$OJQ?t\e(B @code{message-distribution-function} \e$B$K$7$?\e(B
+\e$B$,$C$F:n$i$l$^$9!#$=$l$OHs?d>)$G!"Hs>o$K8m2r$5$l$?%X%C%@!<$G$9!#\e(B
+
+@item Path
+@cindex path
+@vindex message-user-path
+\e$B$3$NHs>o$KA*Br<+M3$J%X%C%@!<$O$*$=$i$/7h$7$F;H$o$l$F$O$J$i$J$$$G$7$g$&!#\e(B
+\e$B$7$+$7$$$/$D$+$N\e(B @emph{\e$B$H$F$b\e(B} \e$B8E$$%5!<%P!<$O$3$N%X%C%@!<$,B8:_$9$k;v$r\e(B
+\e$BMW5a$7$^$9!#\e(B@code{message-user-path} \e$B$,$3$N\e(B @code{Path} \e$B%X%C%@!<$,$I$N$h\e(B
+\e$B$&$K8+$($k$+$r$5$i$K@)8f$7$^$9!#$b$7$=$l$,\e(B @code{nil} \e$B$G$"$l$P!"%5!<%P!<\e(B
+\e$BL>$r\e(B leaf \e$B@a$H$7$F;H$$$^$9!#$b$7$=$l$,J8;zNs$G$"$l$P!"$=$NJ8;zNs$r;H$$$^\e(B
+\e$B$9!#$b$7$=$l$,J8;zNs$G$b\e(B @code{nil} \e$B$G$b$J$1$l$P!"MxMQ<T$NL>A0$@$1$r;H$$\e(B
+\e$B$^$9!#$7$+$7!"2?$i$+$N7A$G$3$NJQ?t$rO.$i$J$1$l$P$J$i$J$$I,MW@-$OHs>o$K>/\e(B
+\e$B$J$$$G$7$g$&!#\e(B
+@end table
+
+@findex yow
+@cindex Mime-Version
+\e$B2C$($F\e(B cons \e$B$r%j%9%H$KF~$l$k;v$,$G$-$^$9!#$3$N\e(B cons \e$B$N\e(B @sc{car} \e$B$O%7%s%\\e(B
+\e$B%k$G$"$k$Y$-$G$9!#$3$N%7%s%\%kL>$O%X%C%@!<L>$G!"\e(B@sc{cdr} \e$B$O$3$N%X%C%@!<\e(B
+\e$B$NCM$H$7$F$=$N$^$^F~$l$i$l$k$3$H$K$J$kJ8;zNs$+!"8F$P$l$k4X?t$N$I$A$i$+$G\e(B
+\e$B$"$k;v$,$G$-$^$9!#Nc$($P!"$b$7\e(B @code{Mime-Version: 1.0} \e$B$rA^F~$7$?$$$J$i!"\e(B
+@code{(Mime-Version . "1.0")} \e$B$r%j%9%H$KF~$l$k$Y$-$G$7$g$&!#$b$7$*$b$7$m\e(B
+\e$B$$0zMQ$rA^F~$7$?$$$J$i!"\e(B@code{(X-Yow . yow)} \e$B$N$h$&$J$b$N$r%j%9%H$KF~$l\e(B
+\e$B$k;v$,$G$-$k$G$7$g$&!#4X?t\e(B @code{yow} \e$B$O$=$N8e$G0z?tL5$7$G8F$P$l$^$9!#\e(B
+
+\e$B$b$7%j%9%H$,\e(B cons \e$B$N\e(B @sc{car} \e$B$,\e(B @code{optional} \e$B$G$"$k\e(B cons \e$B$r4^$s$G$$\e(B
+\e$B$k$J$i!"$3$N\e(B cons \e$B$N\e(B @sc{cdr} \e$B$O\e(B @code{nil} \e$B$G$J$$$H$-$@$1A^F~$5$l$^$9!#\e(B
+
+\e$B$3$N%j%9%H$+$i$"$k9`L\$r>C$7$?$$$J$i$P!"0J2<$N\e(B Lisp \e$B$N@Z$lC<$,Lr$KN)$D$G\e(B
+\e$B$7$g$&!#B>$NMWAG$r:o=|$7$?$$$H$-$O$=$l$K9g$o$;$F2<$5$$!#\e(B
+
+@lisp
+(setq message-required-news-headers
+      (delq 'Message-ID message-required-news-headers))
+@end lisp
+
+\e$B=P$F9T$/%K%e!<%95-;v$r%+%9%?%^%$%:$9$k$?$a$NB>$NJQ?t\e(B:
+
+@table @code
+
+@item message-syntax-checks
+@vindex message-syntax-checks
+@code{nil} \e$B$G$J$1$l$P!"\e(BMessage \e$B$OEj9F$NA0$K!"%X%C%@!<$HB>$N$b$N$N9gK!@-\e(B
+\e$B$rD4$Y$^$9!#$3$N%j%9%H$KMWAG$rIU$12C$($?$j<h$j=|$$$?$j$9$k;v$G!"D4$Y$kN3\e(B
+\e$B$NBg$-$5$r@)8f$9$k;v$,$G$-$^$9!#;H$($kMWAG$O\e(B:
+
+@table @code
+@item subject-cmsg
+\e$BL?Na$N$?$a$NI=Bj$rD4$Y$^$9!#\e(B
+@item sender
+@cindex Sender
+@code{From} \e$B%X%C%@!<$,JQ$K8+$($l$P!"?7$7$$\e(B @code{Sender} \e$B%X%C%@!<$rA^F~\e(B
+\e$B$7$^$9!#\e(B
+@item multiple-headers
+\e$BJ#?t$NEy2A$J%X%C%@!<$NB8:_$rD4$Y$^$9!#\e(B
+@item sendsys
+@cindex sendsys
+\e$BHGHV9f$H\e(B sendsys \e$BL?Na$NB8:_$rD4$Y$^$9!#\e(B
+@item message-id
+@code{Message-ID} \e$B$,Bg>fIW$+$I$&$+D4$Y$^$9!#\e(B
+@item from
+@code{From} \e$B%X%C%@!<$,$h$/8+$($k$+$I$&$+$rD4$Y$^$9!#\e(B
+@item long-lines
+\e$B$"$^$j$KD9$$9T$rD4$Y$^$9!#\e(B
+@item control-chars
+\e$B;H$C$F$O$$$1$J$$J8;z$rD4$Y$^$9!#\e(B
+@item size
+\e$B2a>j$JBg$-$5$rD4$Y$^$9!#\e(B
+@item new-text
+\e$B%a%C%;!<%8$K?7$7$$J8$,$"$k$+$I$&$+$rD4$Y$^$9!#\e(B
+@item signature
+\e$B=pL>$ND9$5$rD4$Y$^$9!#\e(B
+@item approved
+@cindex approved
+\e$B5-;v$,\e(B @code{Approved} \e$B%X%C%@!<$r;}$C$F$$$k$+$I$&$+$rD4$Y$^$9!#$=$l$O;J\e(B
+\e$B2q<T$@$1$,4^$`$Y$-J*$G$9!#\e(B
+@item empty
+\e$B5-;v$,6u$+$I$&$+$rD4$Y$^$9!#\e(B
+@item invisible-text
+\e$B%P%C%U%!$KIT2D;k$N%F%-%9%H$,$"$k$+$I$&$+$rD4$Y$^$9!#\e(B
+@item empty-headers
+\e$B%X%C%@!<$N$I$l$+$,6u$G$"$k$+$rD4$Y$^$9!#\e(B
+@item existing-newsgroups
+@code{Newsgroups} \e$B$H\e(B @code{Follouup-to} \e$B$G=q$+$l$F$$$k%K%e!<%9%0%k!<%W$,\e(B
+\e$BB8:_$9$k$+$I$&$+$rD4$Y$^$9!#\e(B
+@item valid-newsgroups
+@code{Newsgroups} \e$B$H\e(B @code{Followup-to} \e$B%X%C%@!<$,9=J8E*$K@5$7$$$+$rD4$Y\e(B
+\e$B$^$9!#\e(B
+@item repeated-newsgroups
+@code{Newsgroups} \e$B$H\e(B @code{Followup-to} \e$B%X%C%@!<$K7+$jJV$5$l$?%0%k!<%WL>\e(B
+\e$B$,L5$$$+$rD4$Y$^$9!#\e(B
+@item shorten-followup-to
+\e$BEj9F$9$k%0%k!<%W$N?t$r\e(B @code{Followup-to} \e$B%X%C%@!<$rIU$12C$($k;v$G>/$J$/\e(B
+\e$B$9$k$+$rD4$Y$^$9!#\e(B
+@end table
+
+\e$B$3$l$iA4$F$N>uBV$O=i4|@_Dj$G$OD4$Y$i$l$^$9!#\e(B
+
+@item message-ignored-news-headers
+@vindex message-ignored-news-headers
+\e$BEj9F$9$kA0$K<h$j=|$+$l$k%X%C%@!<$N@55,I=8=$G$9!#=i4|CM$O\e(B @*
+@samp{^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:}
+\e$B$G$9!#\e(B
+
+@item message-default-news-headers
+@vindex message-default-news-headers
+\e$B$3$NJ8;zNs$O%K%e!<%9$H$7$F=i4|2=$5$l$?$9$Y$F$N%a%C%;!<%8%P%C%U%!$N%X%C%@!<\e(B
+\e$B$N:G8e$KA^F~$5$l$^$9!#\e(B
+@end table
+
+@node News Variables
+@section \e$B?7$7$$JQ?t\e(B
+
+@table @code
+@item message-send-news-function
+@vindex message-send-news-function
+\e$B8=:_$N%P%C%U%!$r%K%e!<%9$H$7$FAw$k$?$a$K;H$o$l$k4X?t$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{mesage-send-news} \e$B$G$9!#\e(B
+
+@item message-post-method
+@vindex message-post-method
+\e$B=`Hw$5$l$?%K%e!<%9%a%C%;!<%8$rEj9F$9$k$N$K;H$o$l$k\e(B gnus \e$B$N\e(B @dfn{\e$BA*BrJ}K!\e(B}
+(\e$B>\:Y$O\e(B gnus \e$B%^%K%e%"%k$r8+$F2<$5$$\e(B) \e$B$G$9!#\e(B
+@end table
+
+@node Insertion Variables
+@section \e$BA^F~$9$k$?$a$NJQ?t\e(B
+
+@table @code
+@item message-ignored-cited-headers
+\e$B$3$N@55,I=8=$K9gCW$9$kA4$F$N%X%C%@!<$OE=$jIU$1$i$l$?%a%C%;!<%8$+$i<h$j=|\e(B
+\e$B$+$l$^$9!#=i4|CM$O\e(B @samp{.} \e$B$G!"$3$l$OA4$F$N%X%C%@!<$,<h$j=|$+$l$k$H8@$&\e(B
+\e$B;v$G$9!#\e(B
+
+@item message-cite-prefix-regexp
+@vindex message-cite-prefix-regexp
+\e$B$"$k9T$,<h$jF@$k:GBg$N0zMQ@\F,8l$K9gCW$9$k@55,I=8=$G$9!#\e(B
+
+@item message-citation-line-function
+@vindex message-citation-line-function
+@cindex attribution line
+\e$B0zMQ9T$rA^F~$9$k$?$a$K8F$P$l$k4X?t$G$9!#=i4|CM\e(B
+\e$B$O\e(B @code{message-insert-citation-line} \e$B$G!"$3$l$O0zMQ9T$r<!$N$h$&$K$7$^\e(B
+\e$B$9\e(B:
+
+@example
+Hallvard B Furuseth <h.b.furuseth@@usit.uio.no> writes:
+@end example
+
+\e$B$3$N4X?t$,8F$P$l$?$H$-!"%]%$%s%H$O%a%C%;!<%8$NK\BN$N@hF,$K$"$k$G$7$g$&!#\e(B
+
+\e$B$J$*\e(B gnus \e$B$K$O!"\e(B`writes:' \e$B$N>e$G%/%j%C%/$9$k$H0zMQ$5$l$?%F%-%9%H$r1#$95!\e(B
+\e$BG=$,$"$j$^$9!#$b$7$"$J$?$,EY$r1[$7$F0zMQ9T$rJQ99$7$F$7$^$&$H!"$=$l$rFI$`\e(B
+\e$B?M$?$A$bH`$i$N\e(B gnus \e$B$rBP1~$5$;$J$1$l$P$J$i$J$/$J$k$G$7$g$&!#JQ\e(B
+\e$B?t\e(B @code{gnus-cite-attribution-suffix} \e$B$r;2>H$7$F2<$5$$!#>\:Y\e(B
+\e$B$O\e(B @xref{Article Highlighting, , \e$B5-;v$N%O%$%i%$%H\e(B, gnus-ja, The Gnus
+Manual}, \e$B$K$"$j$^$9!#\e(B
+
+@item message-yank-prefix
+@vindex message-yank-prefix
+@cindex yanking
+@cindex quoting
+\e$B5-;v$KJVEz$+%U%)%m!<%"%C%W$r$9$k$H$-$O!"IaDL$O$"$J$?$,1~Ez$7$F$$$k?M$N$b\e(B
+\e$B$N$K0zMQId$rIU$1$?$$$G$7$g$&!#0zMQJ8$NA^F~$O\e(B @dfn{\e$BE=$jIU$1\e(B} \e$B$K$h$C$F$J$5\e(B
+\e$B$l\e(B (\e$B$9$G$K0zMQId$,IU$$$F$$$k$b$N$H6u9T$OBP>]30!"\e(B
+@code{message-yank-cited-prefix} \e$B$r;2>H$N$3$H\e(B)\e$B!"$=$l$>$l$NE=$jIU$1$i$l$?\e(B
+\e$B9T$O$=$NA0$K\e(B @code{message-yank-prefix} \e$B$rIU$1$i$l$^$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{> } \e$B$G$9!#\e(B
+
+@item message-yank-cited-prefix
+@vindex message-yank-cited-prefix
+@cindex yanking
+@cindex cited
+@cindex quoting
+\e$B5-;v$+$i0zMQ$5$l$?%F%-%9%H$,$9$G$K0zMQ$5$l$?$b$N$@$C$?$j6u$@$C$?>l9g!"$=\e(B
+\e$B$l$>$l$N9T$K$O$3$NJQ?t$NCM$,A0CV$5$l$^$9!#=i4|CM$O\e(B @samp{>} \e$B$G$9!#\e(B
+@code{message-yank-prefix} \e$B$b;2>H$7$F2<$5$$!#\e(B
+
+@item message-yank-add-new-references
+@vindex message-yank-add-new-references
+@cindex yanking
+\e$B%3%^%s%I\e(B @code{message-yank-original} \e$B$rBPOCE*$K;H$C$?$H$-$K!"$3$NCM\e(B
+\e$B$,\e(B @code{nil} \e$B$G$J$+$C$?$i!"\e(BReferences \e$B%U%#!<%k%I$K\e(B ID \e$B$,DI2C$5$l$^$9!#\e(B
+\e$B$b$7CM$,%7%s%\%k\e(B @code{message-id-only} \e$B$@$C$?$i\e(B Message-ID \e$B%U%#!<%k%I\e(B
+\e$B$N\e(B ID \e$B$@$1$,;H$o$l$^$9$,!"$=$&$G$J$1$l$P\e(B References\e$B!"\e(BIn-Reply-To \e$B$*$h\e(B
+\e$B$S\e(B Message-ID \e$B%U%#!<%k%I$+$iCj=P$5$l$?\e(B ID \e$B$,;H$o$l$^$9!#\e(B
+
+@item message-list-references-add-position
+@vindex message-list-references-add-position
+@cindex yanking
+\e$B%3%^%s%I\e(B @code{message-yank-original} \e$B$rBPOCE*$K;H$C$?$H$-$K!"$3$NCM$,\e(B
+\e$B@5$N@0?t$@$C$?$i!"$9$G$K$"$k\e(B References \e$B%U%#!<%k%I$N:G8e$+$i$=$N8D?t\e(B
+\e$B$N\e(B ID \e$B$@$1N%$l$?>l=j$K?7$7$$\e(B ID \e$B$,A^F~$5$l$^$9!#$=$l0J30$N>l9g$O:G8e$KA^\e(B
+\e$BF~$5$l$^$9!#\e(B
+
+@item message-indentation-spaces
+@vindex message-indentation-spaces
+\e$BE=$jIU$1$i$l$?%a%C%;!<%8$r;z2<$2$9$k$?$a$N6uGr$N?t$G$9!#\e(B
+
+@item message-cite-function
+@vindex message-cite-function
+@findex message-cite-original
+@findex sc-cite-original
+@findex message-cite-original-without-signature
+@cindex Supercite
+\e$BK\5-;v$r0zMQ$9$k$?$a$N4X?t$G$9!#=i4|CM$O\e(B @code{message-cite-original} \e$B$G!"\e(B
+\e$B$3$l$OC1=c$K$b$H$N%a%C%;!<%8$rA^F~$7!"$=$l$>$l$N9T$NF,$K\e(B @samp{> } \e$B$r$/$C\e(B
+\e$B$D$1$^$9!#\e(B@code{message-cite-original-without-signature} \e$B$OF1MM$N;v$r$7\e(B
+\e$B$^$9$,!"=pL>$O>J$-$^$9!#\e(BSupercite \e$B$r;H$&$?$a$K!"$=$l\e(B
+\e$B$r\e(B @code{sc-cite-original} \e$B$K@_Dj$9$k;v$b$G$-$^$9!#\e(B
+
+@item message-suspend-font-lock-when-citing
+@vindex message-suspend-font-lock-when-citing
+@code{nil} \e$B$G$J$1$l$P!"K\5-;v$r0zMQ$7$F$$$k4V\e(B font-lock \e$B$NF0:n$r;_$a$^$9!#\e(B
+\e$B$$$/$D$+$N!"\e(BEmacs \e$B$,2K$J$H$-$KCY$l$FF0:n$9$k\e(B font-lock \e$B$N$?$a$N%D!<\e(B
+\e$B%k\e(B (\e$B$^$?$O\e(B Emacs \e$B<+?H\e(B) \e$B$K$O%P%0$,$"$j!"$=$l$i$O$7$P$7$P\e(B font-lock \e$B$NF0:n\e(B
+\e$B$r9T$J$&BP>]$H$J$k%P%C%U%!$r<h$j0c$($^$9!#$=$l$O$?$$$F$$\e(B Emacs \e$B$,%_%K%P%C\e(B
+\e$B%U%!$G%f!<%6$K2?$+$NF~NO$rB%$9$H$-$K5/$3$j$^$9!#$3$l$O$=$N>l$7$N$.$NBP:v\e(B
+\e$B$G$O$"$k$N$G$9$,!"$3$N%*%W%7%g%s$rHs\e(B-@code{nil} \e$B$K$9$k$3$H$K$h$C$F!"$"$J\e(B
+\e$B$?$OITL{2w$J%(%i!<$r2sHr$G$-$k$+$b$7$l$^$;$s!#\e(B
+
+@item message-indent-citation-function
+@vindex message-indent-citation-function
+\e$B$A$g$&$I%a!<%k%P%C%U%!$KA^F~$5$l$?0zMQJ8$r=$@5$9$k$?$a$N4X?t$G$9!#$3$l$O\e(B
+\e$B4X?t$N%j%9%H$G$"$k;v$b$G$-$^$9!#$=$l$>$l$N4X?t\e(B
+\e$B$O\e(B @code{(point)} \e$B$H\e(B @code{(mark t)} \e$B$N4V$G0zMQ$rH/8+$9$k;v$,$G$-$^$9!#\e(B
+\e$B$=$7$F!"$=$l$>$l$N4X?t$O0zMQJ8$,=$@5$5$l$k$H!"$=$N<~$j$K%]%$%s%H$H%^!<%/\e(B
+\e$B$r;D$5$J$1$l$P$J$j$^$;$s!#\e(B
+
+@item message-mark-insert-begin
+@vindex message-mark-insert-begin
+\e$B$$$/$D$+$NA^F~$5$l$?%F%-%9%H$N;O$^$j$K0u$rIU$1$k$?$a$NJ8;zNs$G$9!#\e(B
+
+@item message-mark-insert-end
+@vindex message-mark-insert-end
+\e$B$$$/$D$+$NA^F~$5$l$?%F%-%9%H$N=*$j$K0u$rIU$1$k$?$a$NJ8;zNs$G$9!#\e(B
+
+@item message-signature
+@vindex message-signature
+\e$B%a%C%;!<%8%P%C%U%!$N:G8e$KA^F~$5$l$kJ8;zNs$G$9!#$b$7\e(B @code{t} (\e$B$3$l$,=i\e(B
+\e$B4|@_Dj$G$9\e(B) \e$B$G$"$l$P!"%U%!%$%k\e(B @code{message-signature-file} \e$B$,Be$o$j$K\e(B
+\e$BA^F~$5$l$^$9!#$b$74X?t$G$"$l$P!"4X?t$N7k2L$,Be$o$j$K;H$o$l$^$9!#$b$7<0$G\e(B
+\e$B$"$l$P!"<0$N7k2L$,JQ$o$j$K;H$o$l$^$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$l$P!"=p\e(B
+\e$BL>$OA4$/A^F~$5$l$^$;$s!#\e(B
+
+@item message-signature-file
+@vindex message-signature-file
+\e$B%P%C%U%!$N:G8e$KA^F~$5$l$k=pL>$NF~$C$F$$$k%U%!%$%k$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/.signature} \e$B$G$9!#\e(B
+
+@item message-signature-insert-empty-line
+@vindex message-signature-insert-empty-line
+@code{t} (\e$B%G%#%U%)%k%H\e(B) \e$B$@$C$?$i!"=pL>$HK\BN$rJ,N%$9$k5-9f$NA0$K6u9T$,A^\e(B
+\e$BF~$5$l$^$9!#\e(B
+@end table
+
+RFC1036bis \e$B$O!"=pL>$O$=$NA0$K\e(B @samp{-- } \e$B$N\e(B3\e$BJ8;z$@$1$N9T$,$"$k$Y$-$G$"$k\e(B
+\e$B$H8@$C$F$$$k;v$KCm0U$7$F2<$5$$!#$3$l$O<u$1<j$,<+F0E*$K=pL>$rG'<1$7$F!"=h\e(B
+\e$BM}$r$9$k;v$r4JC1$K$9$k$?$a$G$9!#$G$9$+$i!"$"$J$?$NH~$7$$%G%6%$%s$r$=$l$,!"\e(B
+\e$B$"$N!"40A4$KGK2u$7$F$$$k$H46$8$F$b$=$l$i$NJ8;z$r<h$j=|$+$J$$$G$/$@$5$$!#\e(B
+
+\e$B=pL>$O\e(B4\e$B9T$h$jB?$/$J$k$Y$-$G$OL5$$$H8@$&;v$bCm0U$7$F2<$5$$!#\e(B
+@acronym{ASCII} \e$B$N3($rF~$l$k;v$O!"3'$K$"$J$?$,GO</$G2?$b=EMW$J;v$O8@$o$J\e(B
+\e$B$$$H$$$&;v$r?.$8$5$;$k$?$a$N8z2LE*$JJ}K!$G$9!#\e(B
+
+@node Various Message Variables
+@section \e$B$$$m$$$m$J%a%C%;!<%8JQ?t\e(B
+
+@table @code
+@ignore
+@item message-default-charset
+@vindex message-default-charset
+@cindex charset
+Symbol naming a @acronym{MIME} charset.  Non-@acronym{ASCII}
+characters in messages are assumed to be encoded using this charset.
+The default is @code{nil}, which means ask the user.  (This variable
+is used only on non-@sc{mule} Emacsen.  @xref{Charset Translation, ,
+Charset Translation, emacs-mime, Emacs MIME Manual}, for details on
+the @sc{mule}-to-@acronym{MIME} translation process.
+
+@end ignore
+@item message-signature-separator
+@vindex message-signature-separator
+\e$B=pL>$HK\BN$rJ,N%$9$k5-9f$K9gCW$9$k@55,I=8=$G$9!#=i4|CM\e(B
+\e$B$O\e(B @samp{^-- *$} \e$B$G$9!#\e(B
+
+@item mail-header-separator
+@vindex mail-header-separator
+\e$B%X%C%@!<$rK\BN$+$iJ,$1$k$N$K;H$o$l$kJ8;zNs$G$9!#=i4|CM$O\e(B @samp{--text
+follows this line--} \e$B$G$9!#\e(B
+
+@item message-directory
+@vindex message-directory
+\e$BB?$/$N%a!<%k$N$b$N$+$i;H$o$l$k%G%#%l%/%H%j!<$G$9!#=i4|CM\e(B
+\e$B$O\e(B @file{~/Mail/} \e$B$G$9!#\e(B
+
+@item message-auto-save-directory
+@vindex message-auto-save-directory
+gnus \e$B$,F0:n$7$F$$$J$$$H$-$K\e(B Message \e$B$,%P%C%U%!$r<+F0J]B8$9$k%G%#%l%/%H%j\e(B
+\e$B$G$9!#\e(B@code{nil} \e$B$@$C$?$i\e(B Message \e$B$O<+F0J]B8$r9T$J$$$^$;$s!#%G%#%U%)%k%H\e(B
+\e$B$O\e(B @file{~/Mail/drafts/} \e$B$G$9!#\e(B
+
+@item message-signature-setup-hook
+@vindex message-signature-setup-hook
+\e$B%a%C%;!<%8%P%C%U%!$r=i4|2=$9$k$H$-$K<B9T$5$l$k%U%C%/$G$9!#$=$l$O%X%C%@!<\e(B
+\e$B$,A^F~$5$l$F$$$k$,!"=pL>$,A^F~$5$l$kA0$K<B9T$5$l$^$9!#\e(B
+
+@item message-setup-hook
+@vindex message-setup-hook
+\e$B%a%C%;!<%8%P%C%U%!$,=i4|2=$5$l$?$H$-$N:G8e$G$9$,!"E=$jIU$1$i$l$kJ8>O$,A^\e(B
+\e$BF~$5$l$kA0$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item message-header-setup-hook
+@vindex message-header-setup-hook
+\e$B%X%C%@!<$r=i4|2=$7$?8e$K!"%X%C%@!<$KHO0O$r8BDj$7$F8F$P$l$k%U%C%/$G$9!#\e(B
+
+\e$BNc$($P!"\e(Bgnus \e$B$r<B9T$7$F$$$F!"$9$Y$F$N%K%e!<%95-;v$H%a!<%j%s%0%j%9%H$KAw\e(B
+\e$B$kA4$F$N%a%C%;!<%8$K\e(B @samp{Mail-Copies-To} \e$B%X%C%@!<$rA^F~$7$?$$$N$G$"$l\e(B
+\e$B$P!"0J2<$N$h$&$J;v$,$G$-$^$9\e(B:
+
+@lisp
+(defun my-message-header-setup-hook ()
+  (let ((group (or gnus-newsgroup-name "")))
+    (when (or (message-fetch-field "newsgroups")
+              (gnus-group-find-parameter group 'to-address)
+              (gnus-group-find-parameter group 'to-list))
+      (insert "Mail-Copies-To: never\n"))))
+
+(add-hook 'message-header-setup-hook
+          'my-message-header-setup-hook)
+@end lisp
+
+@item message-send-hook
+@vindex message-send-hook
+\e$B%a%C%;!<%8$rAw$kA0$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+\e$B$b$7Aw$kA0$KFCDj$N%X%C%@!<$r2C$($?$$$N$G$"$l$P!"4X\e(B
+\e$B?t\e(B @code{message-add-header} \e$B$r$3$N%U%C%/$K;H$&;v$,$G$-$^$9!#Nc$($P\e(B:
+@findex message-add-header
+
+@lisp
+(add-hook 'message-send-hook 'my-message-add-content)
+(defun my-message-add-content ()
+  (message-add-header "X-In-No-Sense: Nonsense")
+  (message-add-header "X-Whatever: no"))
+@end lisp
+
+\e$B$3$N4X?t$O!"%X%C%@!<$,4{$KB8:_$7$F$$$k>l9g$O%X%C%@!<$r2C$($^$;$s!#\e(B
+
+@item message-send-mail-hook
+@vindex message-send-mail-hook
+\e$B%a!<%k%a%C%;!<%8$rAw$kA0$K<B9T$5$l$k%U%C%/$G$9!#$3$N%U%C%/$OHs>o$KCY$$;~\e(B
+\e$B4|\e(B - \e$B%a%C%;!<%8$,%a!<%k$H$7$F<B:]$KAw?.$5$l$kD>A0\e(B -- \e$B$K<B9T$5$l$^$9!#\e(B
+
+@item message-send-news-hook
+@vindex message-send-news-hook
+\e$B%K%e!<%9%a%C%;!<%8$rAw$kA0$K<B9T$5$l$k%U%C%/$G$9!#$3$N%U%C%/$OHs>o$KCY$$\e(B
+\e$B;~4|\e(B - \e$B%a%C%;!<%8$,%K%e!<%9$H$7$F<B:]$KAw?.$5$l$kD>A0\e(B -- \e$B$K<B9T$5$l$^$9!#\e(B
+
+@item message-sent-hook
+@vindex message-sent-hook
+\e$B%a%C%;!<%8$rAw$k8e$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item message-cancel-hook
+@vindex message-cancel-hook
+\e$B%K%e!<%95-;v$r<h$j>C$9$H$-$K<B9T$5$l$k%U%C%/$G$9!#\e(B
+
+@item message-mode-syntax-table
+@vindex message-mode-syntax-table
+\e$B%a%C%;!<%8%b!<%I%P%C%U%!$G;H$o$l$k9=J8%F!<%V%k$G$9!#\e(B
+
+@item message-strip-special-text-properties
+@vindex message-strip-special-text-properties
+Emacs \e$B$O%a%C%;!<%8:n@.$r$$$m$$$m$K2u$7$F$7$^$&$3$H$,$G$-$kB?$/$N%F%-%9%H\e(B
+\e$BB0@-\e(B (text properties) \e$B$r;}$C$F$$$^$9!#$3$l$,@_Dj$5$l$F$$$k$H\e(B message \e$B$O\e(B
+\e$B$=$l$i$NB0@-$r%a%C%;!<%8$r:n@.$9$k%P%C%U%!$+$iGm$.<h$j$^$9!#$7$+$7$$$/$D\e(B
+\e$B$+$N%Q%C%1!<%8$O!"F0:n$9$k$?$a$K$=$l$i$NB0@-$,$"$k$3$H$,I,MW$G$9!#$=$l$i\e(B
+\e$B$N%Q%C%1!<%8$N0l$D$r;H$&$J$i$P!"$3$N%*%W%7%g%s$r\e(B off \e$B$K$7$F!"%a%C%;!<%8\e(B
+\e$B$,2u$l$F$7$^$o$J$$$3$H$r5'$C$F2<$5$$!#\e(B
+
+@item message-send-method-alist
+@vindex message-send-method-alist
+
+\e$B=P$F9T$/%a%C%;!<%8$rAw$k$?$a$NJ}K!$NO"A[%j%9%H$G$9!#$=$l$>$l$NMWAG$O<!$N\e(B
+\e$B<0$r;}$C$F$$$^$9\e(B
+
+@lisp
+(@var{type} @var{predicate} @var{function})
+@end lisp
+
+@table @var
+@item type
+\e$BJ}K!$r;XDj$9$k%7%s%\%k$G$9!#\e(B
+
+@item predicate
+\e$B%a%C%;!<%8$O\e(B @var{type} \e$B$N%a%C%;!<%8$G$"$k$+$I$&$+$r7hDj$9$k$?$a$K0z?tL5\e(B
+\e$B$7$G8F$P$l$k4X?t$G$9!#\e(B
+
+@item function
+@var{predicate} \e$B$,\e(B @code{nil} \e$B$G$J$$CM$r5"$7$?$H$-$K8F$P$l$k4X?t$G$9!#\e(B
+@var{function} \e$B$O0l$D$N0z?t\e(B -- \e$B@\F,<-\e(B \e$B$H6&$K8F$P$l$^$9!#\e(B
+@end table
+
+@lisp
+((news message-news-p message-send-via-news)
+ (mail message-mail-p message-send-via-mail))
+@end lisp
+@end table
+
+@node Sending Variables
+@section \e$BAw$k$?$a$NJQ?t\e(B
+
+@table @code
+
+@item message-fcc-handler-function
+@vindex message-fcc-handler-function
+\e$B=P$F$$$/5-;v$rJ]B8$9$k$?$a$K8F$P$l$k4X?t$G$9!#$3$N4X?t$O5-;v$rC_@Q$9$k$?\e(B
+\e$B$a$N%U%!%$%kL>$H6&$K8F$P$l$^$9!#=i4|@_Dj$N4X?t$O\e(B @code{message-output}
+\e$B$G!"$=$l$O\e(B Unix mailbox \e$BMM<0$GJ]B8$7$^$9!#\e(B
+
+@item message-courtesy-message
+@vindex messsage-courtesy-messsage
+\e$BJ#9g%a%C%;!<%8$rAw$k$H$-$O!"$3$NJ8;zNs$O%a!<%k$GAw$i$l$?J#@=$NJ}$N:G=i$K\e(B
+\e$BA^F~$5$l$^$9!#$b$7$=$NJ8;zNs$,=qK!;EMM;XDj\e(B @samp{%s} \e$B$r4^$s$G$$$l$P!"5-\e(B
+\e$B;v$,Ej9F$5$l$?%K%e!<%9%0%k!<%W$,$=$3$KA^F~$5$l$^$9!#$b$7$3$NJQ?t\e(B
+\e$B$,\e(B @code{nil} \e$B$G$"$l$P!"$=$N$h$&$J?F@Z%a%C%;!<%8$O2C$($i$l$^$;$s!#=i4|CM\e(B
+\e$B$O\e(B @samp{"The following message is a courtesy copy of an article\nthat has
+been posted to %s as well.\n\n"} \e$B$G$9!#\e(B
+
+@c @item message-fcc-externalize-attachments
+@c @vindex message-fcc-externalize-attachments
+@c If @code{nil}, attach files as normal parts in Fcc copies; if it is
+@c non-@code{nil}, attach local files as external parts.
+
+@item message-interactive
+@vindex message-interactive
+\e$BHs\e(B-@code{nil} \e$B$G!"%a%C%;!<%8$rAw?.$9$k$H$-$K%(%i!<$,=P$k$N$rBT$C$F$rI=<(\e(B
+\e$B$7$^$9!#\e(B@code{nil} \e$B$@$C$?$i!"%a%$%i!<$K%(%i!<$NJs9p$r%a!<%k$G9T$J$o$;$^\e(B
+\e$B$9!#\e(B
+@end table
+
+@node Message Buffers
+@section \e$B%a%C%;!<%8%P%C%U%!\e(B
+
+Message \e$B$O$"$J$?$,%a%C%;!<%8%P%C%U%!$rMW5a$7$?$H$-$K!"B>$KL5$$M#0l$N%P%C\e(B
+\e$B%U%!L>$G?7$7$$%P%C%U%!$r$D$/$j$^$9!#%a%C%;!<%8$rAw$C$?$H$-$K!"%P%C%U%!$O\e(B
+\e$BIaDL$O:o=|$5$l$^$;$s!#$=$NL>A0$OJQ99$5$l$F!"FCDj$N?t$N8E$$%a%C%;!<%8%P%C\e(B
+\e$B%U%!$O@8$-$?$^$^$K$J$j$^$9!#\e(B
+
+@table @code
+@item message-generate-new-buffers
+@vindex message-generate-new-buffers
+@code{nil} \e$B$G$J$1$l$P!"?7$7$$%P%C%U%!$r:n@.$7$^$9!#=i4|CM$O\e(B @code{t} \e$B$G\e(B
+\e$B$9!#$b$7$3$l$,4X?t$J$i!"$=$N4X?t$r\e(B3\e$B$D$N0z?t$H6&$K8F$S$^$9\e(B: \e$B7?!"Aw$j@h%"\e(B
+\e$B%I%l%9!"%0%k!<%WL>\e(B \e$B$G$9!#\e(B (\e$B$3$l$i$N$I$l$G$b\e(B @code{nil} \e$B$G$"$k$+$b$7$l$^\e(B
+\e$B$;$s!#\e(B) \e$B4X?t$O?7$7$$%P%C%U%!L>$rJV$9$Y$-$G$9!#\e(B
+
+@item message-use-multi-frames
+@vindex message-use-multi-frames
+@code{nil} \e$B$G$J$1$l$P!"?7$7$$%U%l!<%`$r:n@.$7$^$9!#=i4|CM$O\e(B @code{nil}
+\e$B$G$9!#\e(B
+
+@item message-delete-frame-on-exit
+@vindex messgae-delete-frame-on-exit
+\e$BJQ?t\e(B @code{message-delete-frame-on-exit} \e$B$O%a%C%;!<%8$rAw?.$7$?$H$-$H!"\e(B
+\e$B%P%C%U%!$r@Z$C$?$H$-$K%U%l!<%`$r>C5n$9$k$+$r7hDj$7$^$9!#\e(B@code{nil} \e$B$G$"\e(B
+\e$B$l$P!"\e(B(\e$B$3$l$,=i4|@_Dj$G$9$,\e(B) \e$B%U%l!<%`$r>C5n$7$^$;$s!#\e(B@code{ask} \e$B$G$"$l$P!"\e(B
+\e$B>C5n$9$k$+$I$&$+$rMxMQ<T$K?R$M$^$9!#\e(B@code{t} \e$B$G$"$l$P!">o$K>C5n$7$^$9!#\e(B
+
+@item message-max-buffers
+@vindex message-max-buffers
+\e$B$3$NJQ?t$O$I$N$/$i$$8E$$%a%C%;!<%8%P%C%U%!$rJ]$C$F$*$/$+$r;XDj$7$^$9!#$3\e(B
+\e$B$l$h$jB?$$%a%C%;!<%8%P%C%U%!$,$"$l$P!"0lHV8E$$%P%C%U%!$,:o=|$5$l$^$9!#=i\e(B
+\e$B4|CM$O\e(B10\e$B$G$9!#$3$NJQ?t$,\e(B @code{nil} \e$B$G$"$k$H!"8E$$%a%C%;!<%8%P%C%U%!$O:o\e(B
+\e$B=|$5$l$^$;$s!#\e(B
+
+@item message-send-rename-function
+@vindex message-send-rename-function
+\e$B%a%C%;!<%8$rAw$C$?8e$G!"%P%C%U%!$NL>A0$O!"Nc$($P!"\e(B@samp{*reply to Lars*}
+\e$B$+$i\e(B @samp{*sent reply to Lars*} \e$B$KJQ99$5$l$^$9!#$b$7$3$l$r9%$^$J$$$J$i!"\e(B
+\e$B$3$NJQ?t$r$"$J$?$N9%$-$JJ}K!$G%P%C%U%!$NL>A0$rJQ99$9$k4X?t$K@_Dj$7$F2<$5\e(B
+\e$B$$!#$=$b$=$b%P%C%U%!L>$rJQ99$9$k;v$r9%$^$J$$$N$G$"$l$P!"<!$N$h$&$K$G$-$^\e(B
+\e$B$9\e(B:
+
+@lisp
+(setq message-send-rename-function 'ignore)
+@end lisp
+
+@item message-kill-buffer-on-exit
+@vindex message-kill-buffer-on-exit
+@code{nil} \e$B$G$J$1$l$P!"=*N;;~$K$9$0$K%P%C%U%!$r:o=|$7$^$9!#\e(B
+
+@item message-kill-buffer-query-function
+@vindex message-kill-buffer-query-function
+@findex message-kill-buffer
+@findex message-mimic-kill-buffer
+\e$B%3%^%s\e(B
+\e$B%I\e(B @code{message-kill-buffer} \e$B$d\e(B @code{message-mimic-kill-buffer} \e$B$G!"%P%C\e(B
+\e$B%U%!$r:o=|$9$k$+$I$&$+$r%f!<%6$K?R$M$k$H$-$K;H$&4X?t$N;XDj$G$9!#%G%#%U%)\e(B
+\e$B%k%H$O\e(B @code{yes-or-no-p} \e$B$G$9$,!"\e(B
+@code{y-or-n-p} \e$B$d\e(B @code{nnheader-Y-or-n-p} \e$B$J$I$r;H$&$3$H$b$G$-$^$9!#\e(B
+@code{t} \e$B$K$9$k$HL5>r7o$K%P%C%U%!$r:o=|$7$^$9!#\e(B
+
+@item message-kill-buffer-and-remove-file
+@vindex message-kill-buffer-and-remove-file
+@findex message-kill-buffer
+@findex message-mimic-kill-buffer
+\e$BHs\e(B-@code{nil} \e$B$@$C$?$i!"%P%C%U%!$r:o=|$7$?8e$G$b$7%P%C%/%"%C%W%U%!%$%k$,\e(B
+\e$B$"$C$?$i!"%f!<%6$K3NG'$7$F$+$i$=$l$b:o=|$7$^$9!#\e(B@code{nil} \e$B$G$O%U%!%$%k\e(B
+\e$B$r:o=|$7$^$;$s!#%G%#%U%)%k%H$O\e(B @code{t} \e$B$G$9!#$?$@$7!"%3%^%s\e(B
+\e$B%I\e(B @code{message-mimic-kill-buffer} \e$B$O$3$l$,\e(B @code{nil} \e$B$G$"$k$b$N$H$7$F\e(B
+\e$BF0:n$7$^$9!#\e(B
+@end table
+
+@node Message Actions
+@section \e$B%a%C%;!<%8$NF0:n\e(B
+
+Message \e$B$,%K%e!<%9\e(B/\e$B%a!<%k%j!<%@!<$+$i;H$o$l$?$H$-!"%j!<%@!<$O%a%C%;!<%8\e(B
+\e$B$,Aw$i$l$?8e$N2?$i$+$N;E;v$r<B9T$7$?$,$k798~$,$"$j$^$9!#$*$=$i$/!"A0$N%&%#\e(B
+\e$B%s%I%&@_Dj$KLa$k$+!"5-;v$KJVEz$5$l$?$H8@$&0u$rIU$1$k$J$I$r$7$?$$$N$G$7$g\e(B
+\e$B$&!#\e(B
+
+@vindex message-kill-actions
+@vindex message-postpone-actions
+@vindex message-exit-actions
+@vindex message-send-actions
+\e$BMxMQ<T$O$$$m$$$m$JJ}K!$G%a%C%;!<%8%P%C%U%!$+$i=P$k$+$b$7$l$^$;$s!#0lHVNI\e(B
+\e$B$/$"$k$N$O\e(B @kbd{C-c C-c} \e$B$G!"$=$l$O%a%C%;!<%8$rAw$C$F=*N;$7$^$9!#B>$N2D\e(B
+\e$BG=@-$K$O\e(B @kbd{C-c C-s} \e$B$,$"$j!"$3$l$O%a%C%;!<%8$rAw$k$@$1$G$"$j!"\e(B
+@kbd{C-c C-d} \e$B$O%a%C%;!<%8$NJT=8$r@h$K1d$P$7$F%a%C%;!<%8%P%C%U%!$rKd$a!"\e(B
+@kbd{C-c C-k} \e$B$O%a%C%;!<%8%P%C%U%!$r:o=|$7$^$9!#$3$l$i$NF0:n$O$=$l$>$l$=\e(B
+\e$B$l$H4XO"IU$1$i$l$?%j%9%H$r;}$C$F$$$F!"$=$l$O<B9T$5$l$kF0:n$r4^$s$G$$$^$9\e(B:
+@code{message-send-actions}, @code{message-exit-actions},
+@code{message-postpone-actions}, and @code{message-kill-actions} \e$B$G$9!#\e(B
+
+Message \e$B$O$3$l$i$N%j%9%H$H:nMQ$9$k4X?t$rDs6!$7$F$$$^$9\e(B:
+@code{message-add-action} \e$B$G$9!#:G=i$N0z?t$O2C$($i$l$kF0:n$G!";D$j$N0z?t\e(B
+\e$B$O$I$N%j%9%H$K$3$NF0:n$r2C$($k$+$G$9!#$3$l$O\e(B gnus \e$B$+$i$NNc$G$9\e(B:
+
+@lisp
+  (message-add-action
+   `(set-window-configuration ,(current-window-configuration))
+   'exit 'postpone 'kill)
+@end lisp
+
+\e$B$3$l$O!"%a%C%;!<%8%P%C%U%!$,:o=|!"1d4|!"=*N;$5$l$?$H$-$K\e(B gnus \e$B$N%&%#%s\e(B
+\e$B%I%&@_Dj$rI|3h$5$;$^$9!#\e(B
+
+@dfn{\e$BF0:n\e(B} \e$B$O<!$N$I$l$+$G$9\e(B: \e$BIaDL$N4X?t!"$b$7$/$O\e(B @code{car} \e$B$,4X?t$G!"\e(B
+@sc{cdr} \e$B$,0z?t$N%j%9%H$G$"$k%j%9%H$+!"\e(B@code{\e$BI>2A\e(B} \e$B$5$l$k<0$G$9!#\e(B
+
+@node Compatibility
+@chapter \e$B8_49@-\e(B
+@cindex compatibility
+
+Message \e$B$O;v<B>e!"$=$l<+?H$NJQ?t$7$+;H$$$^$;$s\e(B---\e$B8E$$\e(B @code{mail-} \e$B$NJQ\e(B
+\e$B?t$O9MN8$5$l$^$;$s!#\e(BMessage \e$B$K$3$l$i$NJQ?t$r7W;;$KF~$l$5$;$?$$$N$G$"$l$P!"\e(B
+\e$B0J2<$N$b$N$r\e(B @file{.emacs} \e$B%U%!%$%k$KF~$l$k;v$,$G$-$^$9\e(B:
+
+@lisp
+(require 'messcompat)
+@end lisp
+
+\e$B$3$l$OB?$/$N\e(B Message \e$BJQ?t$rBP1~$9$k%a!<%kJQ?t$+$i=i4|2=$7$^$9!#\e(B
+
+@node Appendices
+@chapter \e$BIU5-\e(B
+
+@menu
+* Responses:: \e$B1~Ez$,2?=h$K9T$/$+$r7hDj$9$kI8=`$NK!B'!#\e(B
+@end menu
+
+@node Responses
+@section \e$B1~Ez\e(B
+
+\e$B%a%C%;!<%8$,2?=h$K9T$/$+$r7hDj$9$k$?$a$K!"=i4|@_Dj$G$O0J2<$N%"%k%4%j%:%`\e(B
+\e$B$,;H$o$l$^$9!#\e(B
+
+@table @dfn
+@item reply
+@dfn{\e$BJVEz\e(B} (reply) \e$B$O%a%C%;!<%8$rAw$C$??M\e(B @emph{\e$B$@$1\e(B} \e$B$K%a!<%k$G1~Ez$7$?\e(B
+\e$B$$$H$-$N$b$N$G$9!#<u<h?M$O0l?M$7$+$$$^$;$s!#<u<h?M$,C/$G$"$k$+$r7hDj$9$k\e(B
+\e$B$?$a$K!"0J2<$N%X%C%@!<$,=gHV$K9MN8$5$l$^$9\e(B:
+
+@table @code
+@item Reply-To
+
+@item From
+@end table
+
+@item wide reply
+@dfn{\e$B9-$$JVEz\e(B} (wide reply) \e$B$O1~Ez$7$h$&$H$7$F$$$k%a%C%;!<%8$K=q$+$l$F$$\e(B
+\e$B$?\e(B @emph{\e$BA4$F$N\e(B} \e$B<BBN$r4^$`%a!<%k$K$h$k1~Ez$G$9!#0J2<$N%X%C%@!<$+$i$NA4\e(B
+\e$B$F$N%a!<%k%\%C%/%9$,O"7k$5$l$F!"=P$F$$$/\e(B @code{To}/@code{Cc} \e$B%X%C%@!<$r\e(B
+\e$B$D$/$j$^$9\e(B:
+
+@table @code
+@item From
+(@code{Reply-To} \e$B$,L5$$8B$j!"$3$l$,;H$o$l!"$=$l$,$"$k>l9g$O$=$l$,Be$o$j\e(B
+\e$B$K;H$o$l$^$9\e(B)\e$B!#\e(B
+
+@item Cc
+
+@item To
+@end table
+
+@code{Mail-Copies-To} \e$B%X%C%@!<$,B8:_$7$F$$$k$H!"$=$l$b%a!<%k%\%C%/%9$N%j\e(B
+\e$B%9%H$K2C$($i$l$k$G$7$g$&!#$3$N%X%C%@!<$,\e(B @samp{never} \e$B$G$"$l$P!"$=$l\e(B
+\e$B$O\e(B @code{From} (\e$B$b$7$/$O\e(B @code{Reply-To}) \e$B%a!<%k%\%C%/%9$,M^@)$5$l$k$H8@\e(B
+\e$B$&;v$G$9!#\e(B
+
+@item followup
+@dfn{\e$B%U%)%m!<%"%C%W\e(B} (followup) \e$B$O%K%e!<%9$K$h$k1~Ez$G$9!#0J2<$N%X%C\e(B
+\e$B%@!<\e(B (\e$BM%@h=g0L$N9b$$$b$N$+$i5s$2$i$l$F$$$^$9\e(B) \e$B$,2?=h$K1~Ez$,Aw$i$l$k$+$r\e(B
+\e$B7hDj$7$^$9\e(B:
+
+@table @code
+
+@item Followup-To
+
+@item Newsgroups
+@end table
+
+\e$B$b$7\e(B @code{Mail-Copies-To} \e$B%X%C%@!<$,B8:_$9$k$H!"$=$l$,\e(B @samp{never} \e$B$G\e(B
+\e$B$J$1$l$P!"?7$7$$\e(B @code{Cc} \e$B%X%C%@!<$N4p$H$7$F;H$o$l$^$9!#\e(B
+@end table
+
+@node Index
+@chapter Index
+@printindex cp
+
+@node Key Index
+@chapter Key Index
+@printindex ky
+
+@summarycontents
+@contents
+@bye
+
+@c Local Variables:
+@c mode: texinfo
+@c coding: iso-2022-7bit
+@c End:
index f9142e4..9842735 100644 (file)
@@ -1,67 +1,72 @@
 \input texinfo                  @c -*-texinfo-*-
 
 @setfilename message
-@settitle Message 0.34 Manual
+@settitle T-gnus 6.16 Message Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
-@c @direntry
-@c * Message: (message).   Mail and news composition mode that goes with Gnus.
-@c @end direntry
+@dircategory Emacs
+@direntry
+* Message: (message).   Mail and news composition mode that goes with Gnus.
+@end direntry
 @iftex
 @finalout
 @end iftex
 @setchapternewpage odd
 
-@ifinfo
+@ifnottex
 
 This file documents Message, the Emacs message composition mode.
 
-Copyright (C) 1996 Free Software Foundation, Inc.
+Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 
+Free Software Foundation, Inc.
 
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
 
-@ignore
-Permission is granted to process this file through Tex and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
 
-@end ignore
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions.
-@end ifinfo
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end ifnottex
 
 @tex
 
 @titlepage
-@title Message 0.34 Manual
+@title T-gnus 6.16 Message Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
 
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1996 Free Software Foundation, Inc. 
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions.
-
+Copyright @copyright{} 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+     Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being none, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
 @end titlepage
 @page
 
@@ -83,9 +88,9 @@ Message mode buffers.
 * Key Index::         List of Message mode keys.
 @end menu
 
-This manual corresponds to Message 0.34.  Message is distributed with
-the Gnus distribution bearing the same version number as this manual
-has. 
+This manual corresponds to T-gnus 6.16 Message.  Message is distributed
+with the Gnus distribution bearing the same version number as this
+manual.
 
 
 @node Interface
@@ -109,6 +114,7 @@ sending it.
 * Forwarding::           Forwarding a message via news or mail.
 * Resending::            Resending a mail message.
 * Bouncing::             Bouncing a mail message.
+* Mailing Lists::        Send mail to mailing lists.
 @end menu
 
 
@@ -116,7 +122,7 @@ sending it.
 @section New Mail Message
 
 @findex message-mail
-The @code{message-mail} command pops up a new message buffer.  
+The @code{message-mail} command pops up a new message buffer.
 
 Two optional parameters are accepted: The first will be used as the
 @code{To} header and the second as the @code{Subject} header.  If these
@@ -127,7 +133,7 @@ are @code{nil}, those two headers will be empty.
 @section New News Message
 
 @findex message-news
-The @code{message-news} command pops up a new message buffer.  
+The @code{message-news} command pops up a new message buffer.
 
 This function accepts two optional parameters.  The first will be used
 as the @code{Newsgroups} header and the second as the @code{Subject}
@@ -153,8 +159,8 @@ If you want the replies to go to the @code{Sender} instead of the
 (setq message-reply-to-function
       (lambda ()
        (cond ((equal (mail-fetch-field "from") "somebody")
-               (mail-fetch-field "sender"))     
-             (t 
+               (list (cons 'To (mail-fetch-field "sender"))))
+             (t
               nil))))
 @end lisp
 
@@ -167,10 +173,10 @@ just return @code{nil}, and the normal methods for determining the To
 header will be used.
 
 This function can also return a list.  In that case, each list element
-should be a cons, where the car should be the name of an header
-(eg. @code{Cc}) and the cdr should be the header value
-(eg. @samp{larsi@@ifi.uio.no}).  All these headers will be inserted into
-the head of the outgoing mail. 
+should be a cons, where the @sc{car} should be the name of a header
+(e.g. @code{Cc}) and the @sc{cdr} should be the header value
+(e.g. @samp{larsi@@ifi.uio.no}).  All these headers will be inserted into
+the head of the outgoing mail.
 
 
 @node Wide Reply
@@ -186,12 +192,16 @@ reply that goes out to all people listed in the @code{To}, @code{From}
 Message uses the normal methods to determine where wide replies are to go,
 but you can change the behavior to suit your needs by fiddling with the
 @code{message-wide-reply-to-function}.  It is used in the same way as
-@code{message-reply-to-function} (@pxref{Reply}). 
+@code{message-reply-to-function} (@pxref{Reply}).
 
-@findex rmail-dont-reply-to-names
-Addresses that match the @code{rmail-dont-reply-to-names} regular
+@vindex message-dont-reply-to-names
+Addresses that match the @code{message-dont-reply-to-names} regular
 expression will be removed from the @code{Cc} header.
 
+@vindex message-wide-reply-confirm-recipients
+If @code{message-wide-reply-confirm-recipients} is non-@code{nil} you
+will be asked to confirm that you want to reply to multiple
+recipients.  The default is @code{nil}.
 
 @node Followup
 @section Followup
@@ -221,6 +231,28 @@ it is @code{nil}, don't use the value.
 The @code{message-cancel-news} command cancels the article in the
 current buffer.
 
+@vindex message-cancel-message
+The value of @code{message-cancel-message} is inserted in the body of
+the cancel message.  The default is @samp{I am canceling my own
+article.}.
+
+@cindex Cancel Locks
+@vindex message-insert-canlock
+@cindex canlock
+When Message posts news messages, it inserts @code{Cancel-Lock}
+headers by default.  This is a cryptographic header that ensures that
+only you can cancel your own messages, which is nice.  The downside
+is that if you lose your @file{.emacs} file (which is where Gnus
+stores the secret cancel lock password (which is generated
+automatically the first time you use this feature)), you won't be
+able to cancel your message.
+
+Whether to insert the header or not is controlled by the
+@code{message-insert-canlock} variable.
+
+Not many news servers respect the @code{Cancel-Lock} header yet, but
+this is expected to change in the future.
+
 
 @node Superseding
 @section Superseding
@@ -246,26 +278,45 @@ the message in the current buffer.  If given a prefix, forward using
 news.
 
 @table @code
-@item message-forward-start-separator
-@vindex message-forward-start-separator
-Delimiter inserted before forwarded messages.  The default is@*
-@samp{------- Start of forwarded message -------\n}. 
-
-@vindex message-forward-end-separator
-@item message-forward-end-separator
-@vindex message-forward-end-separator
-Delimiter inserted after forwarded messages.  The default is@*
-@samp{------- End of forwarded message -------\n}. 
-
-@item message-signature-before-forwarded-message
-@vindex message-signature-before-forwarded-message
-If this variable is @code{t}, which it is by default, your personal
-signature will be inserted before the forwarded message.  If not, the
-forwarded message will be inserted first in the new mail.
-
-@item message-included-forward-headers
-@vindex message-included-forward-headers
-Regexp matching header lines to be included in forwarded messages.  
+@item message-forward-ignored-headers
+@vindex message-forward-ignored-headers
+All headers that match this regexp will be deleted when forwarding a message.
+
+@item message-make-forward-subject-function
+@vindex message-make-forward-subject-function
+A list of functions that are called to generate a subject header for
+forwarded messages.  The subject generated by the previous function is
+passed into each successive function.
+
+The provided functions are:
+
+@table @code
+@item message-forward-subject-author-subject
+@findex message-forward-subject-author-subject
+Source of article (author or newsgroup), in brackets followed by the
+subject.
+
+@item message-forward-subject-fwd
+Subject of article with @samp{Fwd:} prepended to it.
+@end table
+
+@item message-wash-forwarded-subjects
+@vindex message-wash-forwarded-subjects
+If this variable is @code{t}, the subjects of forwarded messages have
+the evidence of previous forwards (such as @samp{Fwd:}, @samp{Re:},
+@samp{(fwd)}) removed before the new subject is
+constructed.  The default value is @code{nil}.
+
+@item message-forward-as-mime
+@vindex message-forward-as-mime
+If this variable is @code{t} (the default), forwarded messages are
+included as inline @acronym{MIME} RFC822 parts.  If it's @code{nil}, forwarded
+messages will just be copied inline to the new message, like previous,
+non @acronym{MIME}-savvy versions of Gnus would do.
+
+@item message-forward-before-signature
+@vindex message-forward-before-signature
+If non-@code{nil}, put forwarded message before signature, else after.
 
 @end table
 
@@ -280,7 +331,7 @@ and resend the message in the current buffer to that address.
 @vindex message-ignored-resent-headers
 Headers that match the @code{message-ignored-resent-headers} regexp will
 be removed before sending the message.  The default is
-@samp{^Return-receipt}. 
+@samp{^Return-receipt}.
 
 
 @node Bouncing
@@ -291,7 +342,7 @@ The @code{message-bounce} command will, if the current buffer contains a
 bounced mail message, pop up a message buffer stripped of the bounce
 information.  A @dfn{bounced message} is typically a mail you've sent
 out that has been returned by some @code{mailer-daemon} as
-undeliverable. 
+undeliverable.
 
 @vindex message-ignored-bounced-headers
 Headers that match the @code{message-ignored-bounced-headers} regexp
@@ -299,87 +350,388 @@ will be removed before popping up the buffer.  The default is
 @samp{^\\(Received\\|Return-Path\\):}.
 
 
+@node Mailing Lists
+@section Mailing Lists
+
+@cindex Mail-Followup-To
+Sometimes while posting to mailing lists, the poster needs to direct
+followups to the post to specific places.  The Mail-Followup-To (MFT)
+was created to enable just this.  Two example scenarios where this is
+useful:
+
+@itemize @bullet
+@item
+A mailing list poster can use MFT to express that responses should be
+sent to just the list, and not the poster as well.  This will happen
+if the poster is already subscribed to the list.
+
+@item
+A mailing list poster can use MFT to express that responses should be
+sent to the list and the poster as well.  This will happen if the poster
+is not subscribed to the list.
+
+@item
+If a message is posted to several mailing lists, MFT may also be used
+to direct the following discussion to one list only, because
+discussions that are spread over several lists tend to be fragmented
+and very difficult to follow.
+
+@end itemize
+
+Gnus honors the MFT header in other's messages (i.e. while following
+up to someone else's post) and also provides support for generating
+sensible MFT headers for outgoing messages as well.
+
+@c @menu
+@c * Honoring an MFT post::        What to do when one already exists
+@c * Composing with a MFT header:: Creating one from scratch.
+@c @end menu
+
+@c @node Composing with a MFT header
+@subsection  Composing a correct MFT header automagically
+
+The first step in getting Gnus to automagically generate a MFT header
+in posts you make is to give Gnus a list of the mailing lists
+addresses you are subscribed to.  You can do this in more than one
+way.  The following variables would come in handy.
+
+@table @code
+
+@vindex message-subscribed-addresses
+@item message-subscribed-addresses
+This should be a list of addresses the user is subscribed to.  Its
+default value is @code{nil}.  Example:
+@lisp
+(setq message-subscribed-addresses
+      '("ding@@gnus.org" "bing@@noose.org"))
+@end lisp
+
+@vindex message-subscribed-regexps
+@item message-subscribed-regexps
+This should be a list of regexps denoting the addresses of mailing
+lists subscribed to.  Default value is @code{nil}.  Example: If you
+want to achieve the same result as above:
+@lisp
+(setq message-subscribed-regexps
+      '("\\(ding@@gnus\\)\\|\\(bing@@noose\\)\\.org")
+@end lisp
+
+@vindex message-subscribed-address-functions
+@item message-subscribed-address-functions
+This can be a list of functions to be called (one at a time!!) to
+determine the value of MFT headers.  It is advisable that these
+functions not take any arguments.  Default value is @code{nil}.
+
+There is a pre-defined function in Gnus that is a good candidate for
+this variable.  @code{gnus-find-subscribed-addresses} is a function
+that returns a list of addresses corresponding to the groups that have
+the @code{subscribed} (@pxref{Group Parameters, ,Group Parameters,
+gnus, The Gnus Manual}) group parameter set to a non-@code{nil} value.
+This is how you would do it.
+
+@lisp
+(setq message-subscribed-address-functions
+      '(gnus-find-subscribed-addresses))
+@end lisp
+
+@vindex message-subscribed-address-file
+@item message-subscribed-address-file
+You might be one organised human freak and have a list of addresses of
+all subscribed mailing lists in a separate file!  Then you can just
+set this variable to the name of the file and life would be good.
+
+@end table
+
+You can use one or more of the above variables.  All their values are
+``added'' in some way that works :-)
+
+Now you are all set.  Just start composing a message as you normally do.
+And just send it; as always.  Just before the message is sent out, Gnus'
+MFT generation thingy kicks in and checks if the message already has a
+MFT field.  If there is one, it is left alone.  (Except if it's empty -
+in that case, the field is removed and is not replaced with an
+automatically generated one.  This lets you disable MFT generation on a
+per-message basis.)  If there is none, then the list of recipient
+addresses (in the To: and Cc: headers) is checked to see if one of them
+is a list address you are subscribed to.  If none of them is a list
+address, then no MFT is generated; otherwise, a MFT is added to the
+other headers and set to the value of all addresses in To: and Cc:
+
+@kindex C-c C-f C-a
+@findex message-generate-unsubscribed-mail-followup-to
+@kindex C-c C-f C-m
+@findex message-goto-mail-followup-to
+Hm.  ``So'', you ask, ``what if I send an email to a list I am not
+subscribed to?  I want my MFT to say that I want an extra copy.''  (This
+is supposed to be interpreted by others the same way as if there were no
+MFT, but you can use an explicit MFT to override someone else's
+to-address group parameter.)  The function
+@code{message-generate-unsubscribed-mail-followup-to} might come in
+handy.  It is bound to @kbd{C-c C-f C-a} by default.  In any case, you
+can insert a MFT of your own choice; @kbd{C-c C-f C-m}
+(@code{message-goto-mail-followup-to}) will help you get started.
+
+@c @node Honoring an MFT post
+@subsection Honoring an MFT post
+
+@vindex message-use-mail-followup-to
+When you followup to a post on a mailing list, and the post has a MFT
+header, Gnus' action will depend on the value of the variable
+@code{message-use-mail-followup-to}.  This variable can be one of:
+
+@table @code
+@item use
+ Always honor MFTs.  The To: and Cc: headers in your followup will be
+ derived from the MFT header of the original post.  This is the default.
+
+@item nil
+ Always dishonor MFTs (just ignore the darned thing)
+
+@item ask
+Gnus will prompt you for an action.
+
+@end table
+
+It is considered good netiquette to honor MFT, as it is assumed the
+fellow who posted a message knows where the followups need to go
+better than you do.
+
 @node Commands
 @chapter Commands
 
 @menu
-* Header Commands::     Commands for moving to headers.
+* Buffer Entry::        Commands after entering a Message buffer.
+* Header Commands::     Commands for moving headers or changing headers.
 * Movement::            Moving around in message buffers.
 * Insertion::           Inserting things into message buffers.
+* MIME::                @acronym{MIME} considerations.
+* IDNA::                Non-@acronym{ASCII} domain name considerations.
+* Security::            Signing and encrypting messages.
 * Various Commands::    Various things.
 * Sending::             Actually sending the message.
 * Mail Aliases::        How to use mail aliases.
+* Spelling::            Having Emacs check your spelling.
 @end menu
 
 
+@node Buffer Entry
+@section Buffer Entry
+@cindex undo
+@kindex C-_
+
+You most often end up in a Message buffer when responding to some other
+message of some sort.  Message does lots of handling of quoted text, and
+may remove signatures, reformat the text, or the like---depending on
+which used settings you're using.  Message usually gets things right,
+but sometimes it stumbles.  To help the user unwind these stumblings,
+Message sets the undo boundary before each major automatic action it
+takes.  If you press the undo key (usually located at @kbd{C-_}) a few
+times, you will get back the un-edited message you're responding to.
+
+
 @node Header Commands
 @section Header Commands
 
-All these commands move to the header in question.  If it doesn't exist,
-it will be inserted.
+@subsection Commands for moving to headers
+
+These following commands move to the header in question.  If it doesn't
+exist, it will be inserted.
 
 @table @kbd
 
 @item C-c ?
 @kindex C-c ?
-@findex message-goto-to
+@findex describe-mode
 Describe the message mode.
 
 @item C-c C-f C-t
-@kindex C-c C-f C-t 
+@kindex C-c C-f C-t
 @findex message-goto-to
 Go to the @code{To} header (@code{message-goto-to}).
 
+@item C-c C-f C-o
+@kindex C-c C-f C-o
+@findex message-goto-from
+Go to the @code{From} header (@code{message-goto-from}).  (The ``o''
+in the key binding is for Originator.)
+
 @item C-c C-f C-b
-@kindex C-c C-f C-b 
+@kindex C-c C-f C-b
 @findex message-goto-bcc
 Go to the @code{Bcc} header (@code{message-goto-bcc}).
 
 @item C-c C-f C-f
-@kindex C-c C-f C-f 
+@kindex C-c C-f C-f
 @findex message-goto-fcc
 Go to the @code{Fcc} header (@code{message-goto-fcc}).
 
 @item C-c C-f C-c
-@kindex C-c C-f C-c 
+@kindex C-c C-f C-c
 @findex message-goto-cc
 Go to the @code{Cc} header (@code{message-goto-cc}).
 
 @item C-c C-f C-s
-@kindex C-c C-f C-s 
+@kindex C-c C-f C-s
 @findex message-goto-subject
 Go to the @code{Subject} header (@code{message-goto-subject}).
 
 @item C-c C-f C-r
-@kindex C-c C-f C-r 
+@kindex C-c C-f C-r
 @findex message-goto-reply-to
 Go to the @code{Reply-To} header (@code{message-goto-reply-to}).
 
 @item C-c C-f C-n
-@kindex C-c C-f C-n 
+@kindex C-c C-f C-n
 @findex message-goto-newsgroups
 Go to the @code{Newsgroups} header (@code{message-goto-newsgroups}).
 
 @item C-c C-f C-d
-@kindex C-c C-f C-d 
+@kindex C-c C-f C-d
 @findex message-goto-distribution
 Go to the @code{Distribution} header (@code{message-goto-distribution}).
 
 @item C-c C-f C-o
-@kindex C-c C-f C-o 
+@kindex C-c C-f C-o
 @findex message-goto-followup-to
 Go to the @code{Followup-To} header (@code{message-goto-followup-to}).
 
 @item C-c C-f C-k
-@kindex C-c C-f C-k 
+@kindex C-c C-f C-k
 @findex message-goto-keywords
 Go to the @code{Keywords} header (@code{message-goto-keywords}).
 
 @item C-c C-f C-u
-@kindex C-c C-f C-u 
+@kindex C-c C-f C-u
 @findex message-goto-summary
 Go to the @code{Summary} header (@code{message-goto-summary}).
 
+@item C-c C-f C-i
+@kindex C-c C-f C-i
+@findex message-insert-or-toggle-importance
+This inserts the @samp{Importance:} header with a value of
+@samp{high}.  This header is used to signal the importance of the
+message to the receiver.  If the header is already present in the
+buffer, it cycles between the three valid values according to RFC
+1376: @samp{low}, @samp{normal} and @samp{high}.
+
+@item C-c C-f C-a
+@kindex C-c C-f C-a
+@findex message-generate-unsubscribed-mail-followup-to
+Insert a reasonable @samp{Mail-Followup-To:} header
+(@pxref{Mailing Lists}) in a post to an
+unsubscribed list.  When making original posts to a mailing list you are
+not subscribed to, you have to type in a @samp{Mail-Followup-To:} header
+by hand.  The contents, usually, are the addresses of the list and your
+own address.  This function inserts such a header automatically.  It
+fetches the contents of the @samp{To:} header in the current mail
+buffer, and appends the current @code{user-mail-address}.
+
+If the optional argument @code{include-cc} is non-@code{nil}, the
+addresses in the @samp{Cc:} header are also put into the
+@samp{Mail-Followup-To:} header.
+
+@end table
+
+@subsection  Commands to change headers
+
+@table @kbd
+
+@item C-c C-o
+@kindex C-c C-o
+@findex message-sort-headers
+@vindex message-header-format-alist
+Sort headers according to @code{message-header-format-alist}
+(@code{message-sort-headers}).
+
+@item C-c C-t
+@kindex C-c C-t
+@findex message-insert-to
+Insert a @code{To} header that contains the @code{Reply-To} or
+@code{From} header of the message you're following up
+(@code{message-insert-to}).
+
+@item C-c C-n
+@kindex C-c C-n
+@findex message-insert-newsgroups
+Insert a @code{Newsgroups} header that reflects the @code{Followup-To}
+or @code{Newsgroups} header of the article you're replying to
+(@code{message-insert-newsgroups}).
+
+@item C-c C-l
+@kindex C-c C-l
+@findex message-to-list-only
+Send a message to the list only.  Remove all addresses but the list
+address from @code{To:} and @code{Cc:} headers.
+
+@item C-c M-n
+@kindex C-c M-n
+@findex message-insert-disposition-notification-to
+Insert a request for a disposition
+notification.  (@code{message-insert-disposition-notification-to}).
+This means that if the recipient support RFC 2298 she might send you a
+notification that she received the message.
+
+@item M-x message-insert-importance-high
+@kindex M-x message-insert-importance-high
+@findex message-insert-importance-high
+@cindex Importance
+Insert an @samp{Importance} header with a value of @samp{high},
+deleting headers if necessary.
+
+@item M-x message-insert-importance-low
+@kindex M-x message-insert-importance-low
+@findex message-insert-importance-low
+@cindex Importance
+Insert an @samp{Importance} header with a value of @samp{low}, deleting
+headers if necessary.
+
+@item C-c C-f s
+@kindex C-c C-f s
+@findex message-change-subject
+@cindex Subject
+Change the current @samp{Subject} header.  Ask for new @samp{Subject}
+header and append @samp{(was: <Old Subject>)}.  The old subject can be
+stripped on replying, see @code{message-subject-trailing-was-query}
+(@pxref{Message Headers}).
+
+@item C-c C-f x
+@kindex C-c C-f x
+@findex message-cross-post-followup-to
+@vindex message-cross-post-default
+@cindex X-Post
+@cindex cross-post
+Ask for an additional @samp{Newsgroups} and @samp{FollowUp-To} for a
+cross-post.  @code{message-cross-post-followup-to} mangles
+@samp{FollowUp-To} and @samp{Newsgroups} header to point to group.
+If @code{message-cross-post-default} is @code{nil} or if called with a
+prefix-argument @samp{Follow-Up} is set, but the message is not
+cross-posted.
+
+@item C-c C-f t
+@kindex C-c C-f t
+@findex message-reduce-to-to-cc
+Replace contents of @samp{To} header with contents of @samp{Cc} or
+@samp{Bcc} header.
+
+@item C-c C-f w
+@kindex C-c C-f w
+@findex message-insert-wide-reply
+Insert @samp{To} and @samp{Cc} headers as if you were doing a wide
+reply.
+
+@item C-c C-f a
+@kindex C-c C-f a
+@findex message-add-archive-header
+@vindex message-archive-header
+@vindex message-archive-note
+@cindex X-No-Archive
+Insert @samp{X-No-Archive: Yes} in the header and a note in the body.
+The header and the note can be customized using
+@code{message-archive-header} and @code{message-archive-note}.  When
+called with a prefix argument, ask for a text to insert.  If you don't
+want the note in the body, set @code{message-archive-note} to
+@code{nil}.
+
 @end table
 
 
@@ -388,16 +740,25 @@ Go to the @code{Summary} header (@code{message-goto-summary}).
 
 @table @kbd
 @item C-c C-b
-@kindex C-c C-b 
+@kindex C-c C-b
 @findex message-goto-body
 Move to the beginning of the body of the message
-(@code{message-goto-body}). 
+(@code{message-goto-body}).
 
 @item C-c C-i
-@kindex C-c C-i 
+@kindex C-c C-i
 @findex message-goto-signature
 Move to the signature of the message (@code{message-goto-signature}).
 
+@item C-a
+@kindex C-a
+@findex message-beginning-of-line
+@vindex message-beginning-of-line
+If at beginning of header value, go to beginning of line, else go to
+beginning of header value.  (The header value comes after the header
+name and the colon.)  This behaviour can be disabled by toggling
+the variable @code{message-beginning-of-line}.
+
 @end table
 
 
@@ -407,13 +768,20 @@ Move to the signature of the message (@code{message-goto-signature}).
 @table @kbd
 
 @item C-c C-y
-@kindex C-c C-y 
+@kindex C-c C-y
 @findex message-yank-original
-Yank the message that's being replied to into the message buffer
-(@code{message-yank-original}). 
+Yank the message in the buffer @code{gnus-article-copy} into the message
+buffer.  Normally @code{gnus-article-copy} is what you are replying to
+(@code{message-yank-original}).
+
+@item C-c C-M-y
+@kindex C-c C-M-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}).
 
 @item C-c C-q
-@kindex C-c C-q 
+@kindex C-c C-q
 @findex message-fill-yanked-message
 Fill the yanked message (@code{message-fill-yanked-message}).  Warning:
 Can severely mess up the yanked text if its quoting conventions are
@@ -421,95 +789,291 @@ strange.  You'll quickly get a feel for when it's safe, though.  Anyway,
 just remember that @kbd{C-x u} (@code{undo}) is available and you'll be
 all right.
 
-
 @item C-c C-w
-@kindex C-c C-w 
+@kindex C-c C-w
 @findex message-insert-signature
 Insert a signature at the end of the buffer
-(@code{message-insert-signature}).  
+(@code{message-insert-signature}).
+
+@item C-c M-h
+@kindex C-c M-h
+@findex message-insert-headers
+Insert the message headers (@code{message-insert-headers}).
+
+@item C-c M-m
+@kindex C-c M-m
+@findex message-mark-inserted-region
+Mark some region in the current article with enclosing tags.
+See @code{message-mark-insert-begin} and @code{message-mark-insert-end}.
+
+@item C-c M-f
+@kindex C-c M-f
+@findex message-mark-insert-file
+Insert a file in the current article with enclosing tags.
+See @code{message-mark-insert-begin} and @code{message-mark-insert-end}.
 
 @end table
 
-@table @code
-@item message-ignored-cited-headers
-@vindex message-ignored-cited-headers
-All headers that match this regexp will be removed from yanked
-messages.  The default is @samp{.}, which means that all headers will be
-removed.
 
-@item message-citation-line-function
-@vindex message-citation-line-function
-Function called to insert the citation line.  The default is
-@code{message-insert-citation-line}, which will lead to citation lines
-that look like:
+@node MIME
+@section MIME
+@cindex MML
+@cindex MIME
+@cindex multipart
+@cindex attachment
+
+Message is a @acronym{MIME}-compliant posting agent.  The user generally
+doesn't have to do anything to make the @acronym{MIME} happen---Message will
+automatically add the @code{Content-Type} and
+@code{Content-Transfer-Encoding} headers.
+
+The most typical thing users want to use the multipart things in
+@acronym{MIME} for is to add ``attachments'' to mail they send out.  This can
+be done with the @kbd{C-c C-a} command, which will prompt for a file
+name and a @acronym{MIME} type.
+
+You can also create arbitrarily complex multiparts using the @acronym{MML}
+language (@pxref{Composing, , Composing, emacs-mime, The Emacs MIME
+Manual}).
+
+@node IDNA
+@section IDNA
+@cindex IDNA
+@cindex internationalized domain names
+@cindex non-ascii domain names
+
+Message is a @acronym{IDNA}-compliant posting agent.  The user
+generally doesn't have to do anything to make the @acronym{IDNA}
+happen---Message will encode non-@acronym{ASCII} domain names in @code{From},
+@code{To}, and @code{Cc} headers automatically.
+
+Until @acronym{IDNA} becomes more well known, Message queries you
+whether @acronym{IDNA} encoding of the domain name really should
+occur.  Some users might not be aware that domain names can contain
+non-@acronym{ASCII} now, so this gives them a safety net if they accidently
+typed a non-@acronym{ASCII} domain name.
+
+@vindex message-use-idna
+The @code{message-use-idna} variable control whether @acronym{IDNA} is
+used.  If the variable is @code{nil} no @acronym{IDNA} encoding will
+ever happen, if it is set to the symbol @code{ask} the user will be
+queried (the default), and if set to @code{t} @acronym{IDNA} encoding
+happens automatically.
+
+@findex message-idna-to-ascii-rhs
+If you want to experiment with the @acronym{IDNA} encoding, you can
+invoke @kbd{M-x message-idna-to-ascii-rhs RET} in the message buffer
+to have the non-@acronym{ASCII} domain names encoded while you edit the message.
+
+Note that you must have @uref{http://www.gnu.org/software/libidn/, GNU
+Libidn} installed in order to use this functionality.
+
+@node Security
+@section Security
+@cindex Security
+@cindex S/MIME
+@cindex PGP
+@cindex PGP/MIME
+@cindex sign
+@cindex encrypt
+@cindex secure
+
+Using the @acronym{MML} language, Message is able to create digitally
+signed and digitally encrypted messages.  Message (or rather
+@acronym{MML}) currently support @acronym{PGP} (RFC 1991),
+@acronym{PGP/MIME} (RFC 2015/3156) and @acronym{S/MIME}.  Instructing
+@acronym{MML} to perform security operations on a @acronym{MIME} part is
+done using the @kbd{C-c C-m s} key map for signing and the @kbd{C-c C-m
+c} key map for encryption, as follows.
 
-@example
-Hallvard B Furuseth <h.b.furuseth@@usit.uio.no> writes:
-@end example
+@table @kbd
 
-Point will be at the beginning of the body of the message when this
-function is called.
+@item C-c C-m s s
+@kindex C-c C-m s s
+@findex mml-secure-message-sign-smime
 
-@item message-yank-prefix
-@vindex message-yank-prefix
-@cindex yanking
-@cindex quoting
-When you are replying to or following up an article, you normally want
-to quote the person you are answering.  Inserting quoted text is done by
-@dfn{yanking}, and each quoted line you yank will have
-@code{message-yank-prefix} prepended to it.  The default is @samp{> }.
-If it is @code{nil}, just indent the message.
+Digitally sign current message using @acronym{S/MIME}.
 
-@item message-indentation-spaces
-@vindex message-indentation-spaces
-Number of spaces to indent yanked messages.
+@item C-c C-m s o
+@kindex C-c C-m s o
+@findex mml-secure-message-sign-pgp
 
-@item message-cite-function
-@vindex message-cite-function
-@findex message-cite-original
-@findex sc-cite-original
-@findex message-cite-original-without-signature
-@cindex Supercite
-Function for citing an original message.  The default is
-@code{message-cite-original}, which simply inserts the original message
-and prepends @samp{> } to each line.
-@code{message-cite-original-without-signature} does the same, but elides
-the signature.  You can also set it to @code{sc-cite-original} to use
-Supercite.
+Digitally sign current message using @acronym{PGP}.
 
-@item message-indent-citation-function
-@vindex message-indent-citation-function
-Function for modifying a citation just inserted in the mail buffer.
-This can also be a list of functions.  Each function can find the
-citation between @code{(point)} and @code{(mark t)}.  And each function
-should leave point and mark around the citation text as modified.
+@item C-c C-m s p
+@kindex C-c C-m s p
+@findex mml-secure-message-sign-pgpmime
 
-@item message-signature
-@vindex message-signature
-String to be inserted at the end of the message buffer.  If @code{t}
-(which is the default), the @code{message-signature-file} file will be
-inserted instead.  If a function, the result from the function will be
-used instead.  If a form, the result from the form will be used instead.
-If this variable is @code{nil}, no signature will be inserted at all.
+Digitally sign current message using @acronym{PGP/MIME}.
 
-@item message-signature-file
-@vindex message-signature-file
-File containing the signature to be inserted at the end of the buffer.
-The default is @samp{~/.signature}.
+@item C-c C-m c s
+@kindex C-c C-m c s
+@findex mml-secure-message-encrypt-smime
+
+Digitally encrypt current message using @acronym{S/MIME}.
+
+@item C-c C-m c o
+@kindex C-c C-m c o
+@findex mml-secure-message-encrypt-pgp
+
+Digitally encrypt current message using @acronym{PGP}.
+
+@item C-c C-m c p
+@kindex C-c C-m c p
+@findex mml-secure-message-encrypt-pgpmime
+
+Digitally encrypt current message using @acronym{PGP/MIME}.
+
+@item C-c C-m C-n
+@kindex C-c C-m C-n
+@findex mml-unsecure-message
+Remove security related @acronym{MML} tags from message.
 
 @end table
 
-Note that RFC1036bis says that a signature should be preceded by the three
-characters @samp{-- } on a line by themselves.  This is to make it
-easier for the recipient to automatically recognize and process the
-signature.  So don't remove those characters, even though you might feel
-that they ruin your beautiful design, like, totally.
+These commands do not immediately sign or encrypt the message, they
+merely insert the proper @acronym{MML} secure tag to instruct the
+@acronym{MML} engine to perform that operation when the message is
+actually sent.  They may perform other operations too, such as locating
+and retrieving a @acronym{S/MIME} certificate of the person you wish to
+send encrypted mail to.  When the mml parsing engine converts your
+@acronym{MML} into a properly encoded @acronym{MIME} message, the secure
+tag will be replaced with either a part or a multipart tag.  If your
+message contains other mml parts, a multipart tag will be used; if no
+other parts are present in your message a single part tag will be used.
+This way, message mode will do the Right Thing (TM) with
+signed/encrypted multipart messages.
+
+Since signing and especially encryption often is used when sensitive
+information is sent, you may want to have some way to ensure that your
+mail is actually signed or encrypted.  After invoking the above
+sign/encrypt commands, it is possible to preview the raw article by
+using @kbd{C-u C-c RET P} (@code{mml-preview}).  Then you can
+verify that your long rant about what your ex-significant other or
+whomever actually did with that funny looking person at that strange
+party the other night, actually will be sent encrypted.
+
+@emph{Note!}  Neither @acronym{PGP/MIME} nor @acronym{S/MIME} encrypt/signs
+RFC822 headers.  They only operate on the @acronym{MIME} object.  Keep this
+in mind before sending mail with a sensitive Subject line.
+
+By default, when encrypting a message, Gnus will use the
+``signencrypt'' mode, which means the message is both signed and
+encrypted.  If you would like to disable this for a particular
+message, give the @code{mml-secure-message-encrypt-*} command a prefix
+argument, e.g., @kbd{C-u C-c C-m c p}.
+
+Actually using the security commands above is not very difficult.  At
+least not compared with making sure all involved programs talk with each
+other properly.  Thus, we now describe what external libraries or
+programs are required to make things work, and some small general hints.
+
+@subsection Using S/MIME
+
+@emph{Note!}  This section assume you have a basic familiarity with
+modern cryptography, @acronym{S/MIME}, various PKCS standards, OpenSSL and
+so on.
+
+The @acronym{S/MIME} support in Message (and @acronym{MML}) require
+OpenSSL.  OpenSSL performs the actual @acronym{S/MIME} sign/encrypt
+operations.  OpenSSL can be found at @uref{http://www.openssl.org/}.
+OpenSSL 0.9.6 and later should work.  Version 0.9.5a cannot extract mail
+addresses from certificates, and it insert a spurious CR character into
+@acronym{MIME} separators so you may wish to avoid it if you would like
+to avoid being regarded as someone who send strange mail.  (Although by
+sending @acronym{S/MIME} messages you've probably already lost that
+contest.)
+
+To be able to send encrypted mail, a personal certificate is not
+required.  Message (@acronym{MML}) need a certificate for the person to whom you
+wish to communicate with though.  You're asked for this when you type
+@kbd{C-c C-m c s}.  Currently there are two ways to retrieve this
+certificate, from a local file or from DNS.  If you chose a local
+file, it need to contain a X.509 certificate in @acronym{PEM} format.
+If you chose DNS, you're asked for the domain name where the
+certificate is stored, the default is a good guess.  To my belief,
+Message (@acronym{MML}) is the first mail agent in the world to support
+retrieving @acronym{S/MIME} certificates from DNS, so you're not
+likely to find very many certificates out there.  At least there
+should be one, stored at the domain @code{simon.josefsson.org}.  LDAP
+is a more popular method of distributing certificates, support for it
+is planned.  (Meanwhile, you can use @code{ldapsearch} from the
+command line to retrieve a certificate into a file and use it.)
+
+As for signing messages, OpenSSL can't perform signing operations
+without some kind of configuration.  Especially, you need to tell it
+where your private key and your certificate is stored.  @acronym{MML}
+uses an Emacs interface to OpenSSL, aptly named @code{smime.el}, and it
+contain a @code{custom} group used for this configuration.  So, try
+@kbd{M-x customize-group RET smime RET} and look around.
+
+Currently there is no support for talking to a CA (or RA) to create
+your own certificate.  None is planned either.  You need to do this
+manually with OpenSSL or using some other program.  I used Netscape
+and got a free @acronym{S/MIME} certificate from one of the big CA's on the
+net.  Netscape is able to export your private key and certificate in
+PKCS #12 format.  Use OpenSSL to convert this into a plain X.509
+certificate in PEM format as follows.
 
-Also note that no signature should be more than four lines long.
-Including ASCII graphics is an efficient way to get everybody to believe
-that you are silly and have nothing important to say.
+@example
+$ openssl pkcs12 -in ns.p12 -clcerts -nodes > key+cert.pem
+@end example
 
+The @file{key+cert.pem} file should be pointed to from the
+@code{smime-keys} variable.  You should now be able to send signed mail.
+
+@emph{Note!}  Your private key is now stored unencrypted in the file,
+so take care in handling it.  Storing encrypted keys on the disk are
+supported, and Gnus will ask you for a passphrase before invoking
+OpenSSL.  Read the OpenSSL documentation for how to achieve this.  If
+you use unencrypted keys (e.g., if they are on a secure storage, or if
+you are on a secure single user machine) simply press @code{RET} at
+the passphrase prompt.
+
+@subsection Using PGP/MIME
+
+@acronym{PGP/MIME} requires an external OpenPGP implementation, such
+as @uref{http://www.gnupg.org/, GNU Privacy Guard}.  Pre-OpenPGP
+implementations such as PGP 2.x and PGP 5.x are also supported.  One
+Emacs interface to the PGP implementations, PGG (@pxref{Top, ,PGG,
+pgg, PGG Manual}), is included, but Mailcrypt and Florian Weimer's
+@code{gpg.el} are also supported.
+
+@vindex gpg-temp-directory
+Note, if you are using the @code{gpg.el} you must make sure that the
+directory specified by @code{gpg-temp-directory} have permissions
+0700.
+
+Creating your own key is described in detail in the documentation of
+your PGP implementation, so we refer to it.
+
+If you have imported your old PGP 2.x key into GnuPG, and want to send
+signed and encrypted messages to your fellow PGP 2.x users, you'll
+discover that the receiver cannot understand what you send. One
+solution is to use PGP 2.x instead (i.e., if you use @code{pgg}, set
+@code{pgg-default-scheme} to @code{pgp}).  If you do want to use
+GnuPG, you can use a compatibility script called @code{gpg-2comp}
+available from
+@uref{http://muppet.faveve.uni-stuttgart.de/~gero/gpg-2comp/}.  You
+could also convince your fellow PGP 2.x users to convert to GnuPG.
+@vindex mml-signencrypt-style-alist
+As a final workaround, you can make the sign and encryption work in
+two steps; separately sign, then encrypt a message.  If you would like
+to change this behavior you can customize the
+@code{mml-signencrypt-style-alist} variable.  For example:
 
+@lisp
+(setq mml-signencrypt-style-alist '(("smime" separate)
+                                    ("pgp" separate)
+                                    ("pgpauto" separate)
+                                    ("pgpmime" separate)))
+@end lisp
+
+This causes to sign and encrypt in two passes, thus generating a
+message that can be understood by PGP version 2.
+
+(Refer to @uref{http://www.gnupg.org/gph/en/pgp2x.html} for more
+information about the problem.)
 
 @node Various Commands
 @section Various Commands
@@ -517,7 +1081,7 @@ that you are silly and have nothing important to say.
 @table @kbd
 
 @item C-c C-r
-@kindex C-c C-r 
+@kindex C-c C-r
 @findex message-caesar-buffer-body
 Caesar rotate (aka. rot13) the current message
 (@code{message-caesar-buffer-body}).  If narrowing is in effect, just
@@ -527,9 +1091,11 @@ many places to rotate the text.  The default is 13.
 @item C-c C-e
 @kindex C-c C-e
 @findex message-elide-region
+@vindex message-elide-ellipsis
 Elide the text between point and mark (@code{message-elide-region}).
-The text is killed and an ellipsis (@samp{[...]}) will be inserted in
-its place.
+The text is killed and replaced with the contents of the variable
+@code{message-elide-ellipsis}.  The default value is to use an ellipsis
+(@samp{[...]}).
 
 @item C-c C-z
 @kindex C-c C-x
@@ -545,7 +1111,7 @@ Delete all text in the body of the message that is outside the region
 
 @item M-RET
 @kindex M-RET
-@kindex message-newline-and-reformat
+@findex message-newline-and-reformat
 Insert four newlines, and then reformat if inside quoted text.
 
 Here's an example:
@@ -564,21 +1130,7 @@ If point is before @samp{And} and you press @kbd{M-RET}, you'll get:
 > And here's more quoted text.
 @end example
 
-@samp{*} says where point will be placed.  
-
-@item C-c C-t
-@kindex C-c C-t 
-@findex message-insert-to
-Insert a @code{To} header that contains the @code{Reply-To} or
-@code{From} header of the message you're following up
-(@code{message-insert-to}). 
-
-@item C-c C-n
-@kindex C-c C-n 
-@findex message-insert-newsgroups
-Insert a @code{Newsgroups} header that reflects the @code{Followup-To}
-or @code{Newsgroups} header of the article you're replying to
-(@code{message-insert-newsgroups}).
+@samp{*} says where point will be placed.
 
 @item C-c M-r
 @kindex C-c M-r
@@ -586,6 +1138,14 @@ or @code{Newsgroups} header of the article you're replying to
 Rename the buffer (@code{message-rename-buffer}).  If given a prefix,
 prompt for a new buffer name.
 
+@item TAB
+@kindex TAB
+@findex message-tab
+@vindex message-tab-body-function
+If non-@code{nil} execute the function specified in
+@code{message-tab-body-function}.  Otherwise use the function bound to
+@kbd{TAB} in @code{text-mode-map} or @code{global-map}.
+
 @end table
 
 
@@ -594,15 +1154,15 @@ prompt for a new buffer name.
 
 @table @kbd
 @item C-c C-c
-@kindex C-c C-c 
+@kindex C-c C-c
 @findex message-send-and-exit
 Send the message and bury the current buffer
-(@code{message-send-and-exit}). 
+(@code{message-send-and-exit}).
 
 @item C-c C-s
-@kindex C-c C-s 
+@kindex C-c C-s
 @findex message-send
-Send the message (@code{message-send}). 
+Send the message (@code{message-send}).
 
 @item C-c C-d
 @kindex C-c C-d
@@ -612,7 +1172,21 @@ Bury the message buffer and exit (@code{message-dont-send}).
 @item C-c C-k
 @kindex C-c C-k
 @findex message-kill-buffer
-Kill the message buffer and exit (@code{message-kill-buffer}).
+Kill the message buffer and exit (@code{message-kill-buffer}).  It will
+delete the message frame if it has been created exclusively for the
+message buffer.  If the option
+@code{message-kill-buffer-and-remove-file} is non-@code{nil} and the
+backup file has been created for the message buffer, it will also remove
+the file after prompting to the user.
+
+@item C-x k
+@kindex C-x k
+@findex message-mimic-kill-buffer
+@vindex message-kill-buffer-and-remove-file
+This is an imitation for @code{kill-buffer}
+(@code{message-mimic-kill-buffer}).  It dynamically binds the variable
+@code{message-kill-buffer-and-remove-file} to @code{nil} and calls the
+function @code{message-kill-buffer}.
 
 @end table
 
@@ -645,6 +1219,51 @@ No expansion will be performed upon sending of the message---all
 expansions have to be done explicitly.
 
 
+@node Spelling
+@section Spelling
+@cindex spelling
+@findex ispell-message
+
+There are two popular ways to have Emacs spell-check your messages:
+@code{ispell} and @code{flyspell}.  @code{ispell} is the older and
+probably more popular package.  You typically first write the message,
+and then run the entire thing through @code{ispell} and fix all the
+typos.  To have this happen automatically when you send a message, put
+something like the following in your @file{.emacs} file:
+
+@lisp
+(add-hook 'message-send-hook 'ispell-message)
+@end lisp
+
+@vindex ispell-message-dictionary-alist
+If you're in the habit of writing in different languages, this can be
+controlled by the @code{ispell-message-dictionary-alist} variable:
+
+@lisp
+(setq ispell-message-dictionary-alist
+      '(("^Newsgroups:.*\\bde\\." . "deutsch8")
+        (".*" . "default")))
+@end lisp
+
+@code{ispell} depends on having the external @samp{ispell} command
+installed.
+
+The other popular method is using @code{flyspell}.  This package checks
+your spelling while you're writing, and marks any mis-spelled words in
+various ways.
+
+To use @code{flyspell}, put something like the following in your
+@file{.emacs} file:
+
+@lisp
+(defun my-message-setup-routine ()
+  (flyspell-mode 1))
+(add-hook 'message-setup-hook 'my-message-setup-routine)
+@end lisp
+
+@code{flyspell} depends on having the external @samp{ispell} command
+installed.
+
 
 @node Variables
 @chapter Variables
@@ -655,6 +1274,7 @@ expansions have to be done explicitly.
 * Mail Variables::              Other mail variables.
 * News Headers::                Customizing news headers.
 * News Variables::              Other news variables.
+* Insertion Variables::         Customizing how things are inserted.
 * Various Message Variables::   Other message variables.
 * Sending Variables::           Variables for sending.
 * Message Buffers::             How Message names its buffers.
@@ -675,12 +1295,32 @@ look sufficiently similar.
 
 @item message-generate-headers-first
 @vindex message-generate-headers-first
-If non-@code{nil}, generate all headers before starting to compose the
-message.  
+If @code{t}, generate all required headers before starting to
+compose the message.  This can also be a list of headers to generate:
+
+@lisp
+(setq message-generate-headers-first
+      '(References))
+@end lisp
+
+@vindex message-required-headers
+The variables @code{message-required-headers},
+@code{message-required-mail-headers} and
+@code{message-required-news-headers} specify which headers are
+required.
+
+Note that some headers will be removed and re-generated before posting,
+because of the variable @code{message-deletable-headers} (see below).
+
+@item message-draft-headers
+@vindex message-draft-headers
+When running Message from Gnus, the message buffers are associated
+with a draft group.  @code{message-draft-headers} says which headers
+should be generated when a draft is written to the draft group.
 
 @item message-from-style
 @vindex message-from-style
-Specifies how @code{From} headers should look.  There are four legal
+Specifies how @code{From} headers should look.  There are four valid
 values:
 
 @table @code
@@ -710,13 +1350,94 @@ ship it off again.  By default, this variable makes sure that the old
 generated @code{Message-ID} is deleted, and a new one generated.  If
 this isn't done, the entire empire would probably crumble, anarchy would
 prevail, and cats would start walking on two legs and rule the world.
-Allegedly.  
+Allegedly.
 
 @item message-default-headers
 @vindex message-default-headers
 This string is inserted at the end of the headers in all message
 buffers.
 
+@item message-subject-re-regexp
+@vindex message-subject-re-regexp
+@cindex Aw
+@cindex Sv
+@cindex Re
+Responses to messages have subjects that start with @samp{Re: }.  This
+is @emph{not} an abbreviation of the English word ``response'', but is
+Latin, and means ``in response to''.  Some illiterate nincompoops have
+failed to grasp this fact, and have ``internationalized'' their software
+to use abominations like @samp{Aw: } (``antwort'') or @samp{Sv: }
+(``svar'') instead, which is meaningless and evil.  However, you may
+have to deal with users that use these evil tools, in which case you may
+set this variable to a regexp that matches these prefixes.  Myself, I
+just throw away non-compliant mail.
+
+Here's an example of a value to deal with these headers when
+responding to a message:
+
+@lisp
+(setq message-subject-re-regexp
+      (concat
+       "^[ \t]*"
+         "\\("
+           "\\("
+             "[Aa][Nn][Tt][Ww]\\.?\\|"     ; antw
+             "[Aa][Ww]\\|"                 ; aw
+             "[Ff][Ww][Dd]?\\|"            ; fwd
+             "[Oo][Dd][Pp]\\|"             ; odp
+             "[Rr][Ee]\\|"                 ; re
+             "[Rr][\311\351][Ff]\\.?\\|"   ; ref
+             "[Ss][Vv]"                    ; sv
+           "\\)"
+           "\\(\\[[0-9]*\\]\\)"
+           "*:[ \t]*"
+         "\\)"
+       "*[ \t]*"
+       ))
+@end lisp
+
+@item message-subject-trailing-was-query
+@vindex message-subject-trailing-was-query
+@vindex message-subject-trailing-was-ask-regexp
+@vindex message-subject-trailing-was-regexp
+Controls what to do with trailing @samp{(was: <old subject>)} in subject
+lines.  If @code{nil}, leave the subject unchanged.  If it is the symbol
+@code{ask}, query the user what do do.  In this case, the subject is
+matched against @code{message-subject-trailing-was-ask-regexp}.  If
+@code{message-subject-trailing-was-query} is t, always strip the
+trailing old subject.  In this case,
+@code{message-subject-trailing-was-regexp} is used.
+
+@item message-alternative-emails
+@vindex message-alternative-emails
+A regexp to match the alternative email addresses.  The first matched
+address (not primary one) is used in the @code{From} field.
+
+@item message-allow-no-recipients
+@vindex message-allow-no-recipients
+Specifies what to do when there are no recipients other than
+@code{Gcc} or @code{Fcc}.  If it is @code{always}, the posting is
+allowed.  If it is @code{never}, the posting is not allowed.  If it is
+@code{ask} (the default), you are prompted.
+
+@item message-hidden-headers
+@vindex message-hidden-headers
+A regexp, a list of regexps, or a list where the first element is
+@code{not} and the rest are regexps.  It says which headers to keep
+hidden when composing a message.
+
+@lisp
+(setq message-hidden-headers
+      '(not "From" "Subject" "To" "Cc" "Newsgroups"))
+@end lisp
+
+@item message-header-synonyms
+@vindex message-header-synonyms
+A list of lists of header synonyms.  E.g., if this list contains a
+member list with elements @code{Cc} and @code{To}, then
+@code{message-carefully-insert-headers} will not insert a @code{To}
+header when the message is already @code{Cc}ed to the recipient.
+
 @end table
 
 
@@ -728,12 +1449,12 @@ buffers.
 @vindex message-required-mail-headers
 @xref{News Headers}, for the syntax of this variable.  It is
 @code{(From Date Subject (optional . In-Reply-To) Message-ID Lines
-(optional . X-Mailer))} by default.
+(optional . User-Agent))} by default.
 
 @item message-ignored-mail-headers
 @vindex message-ignored-mail-headers
 Regexp of headers to be removed before mailing.  The default is
-@samp{^[GF]cc:\\|^Resent-Fcc:}.
+@samp{^[GF]cc:\\|^Resent-Fcc:\\|^Xref:\\|^X-Draft-From:}.
 
 @item message-default-mail-headers
 @vindex message-default-mail-headers
@@ -744,14 +1465,22 @@ buffers that are initialized as mail.
 
 
 @node Mail Variables
-@section Mail Variables 
+@section Mail Variables
 
 @table @code
 @item message-send-mail-function
 @vindex message-send-mail-function
+@findex message-send-mail-with-sendmail
+@findex message-send-mail-with-mh
+@findex message-send-mail-with-qmail
+@findex message-smtpmail-send-it
+@findex smtpmail-send-it
+@findex feedmail-send-it
 Function used to send the current buffer as mail.  The default is
-@code{message-send-mail-with-sendmail}.   If you prefer using MH
-instead, set this variable to @code{message-send-mail-with-mh}.
+@code{message-send-mail-with-sendmail}.  Other valid values include
+@code{message-send-mail-with-mh}, @code{message-send-mail-with-qmail},
+@code{message-smtpmail-send-it}, @code{smtpmail-send-it} and
+@code{feedmail-send-it}.
 
 @item message-mh-deletable-headers
 @vindex message-mh-deletable-headers
@@ -761,6 +1490,48 @@ the default), these headers will be removed before mailing when sending
 messages via MH.  Set it to @code{nil} if your MH can handle these
 headers.
 
+@item message-qmail-inject-program
+@vindex message-qmail-inject-program
+@cindex qmail
+Location of the qmail-inject program.
+
+@item message-qmail-inject-args
+@vindex message-qmail-inject-args
+Arguments passed to qmail-inject programs.
+This should be a list of strings, one string for each argument.  It
+may also be a function.
+
+For e.g., if you wish to set the envelope sender address so that bounces
+go to the right place or to deal with listserv's usage of that address, you
+might set this variable to @code{'("-f" "you@@some.where")}.
+
+@item message-sendmail-f-is-evil
+@vindex message-sendmail-f-is-evil
+@cindex sendmail
+Non-@code{nil} means don't add @samp{-f username} to the sendmail
+command line.  Doing so would be even more evil than leaving it out.
+
+@item message-sendmail-envelope-from
+@vindex message-sendmail-envelope-from
+When @code{message-sendmail-f-is-evil} is @code{nil}, this specifies
+the address to use in the @acronym{SMTP} envelope.  If it is
+@code{nil}, use @code{user-mail-address}.  If it is the symbol
+@code{header}, use the @samp{From} header of the message.
+
+@item message-mailer-swallows-blank-line
+@vindex message-mailer-swallows-blank-line
+Set this to non-@code{nil} if the system's mailer runs the header and
+body together.  (This problem exists on SunOS 4 when sendmail is run
+in remote mode.)  The value should be an expression to test whether
+the problem will actually occur.
+
+@item message-send-mail-partially-limit
+@vindex message-send-mail-partially-limit
+@cindex split large message
+The limitation of messages sent as message/partial.  The lower bound
+of message size in characters, beyond which the message should be sent
+in several parts.  If it is @code{nil}, the size is unlimited.
+
 @end table
 
 
@@ -770,7 +1541,7 @@ headers.
 @vindex message-required-news-headers
 @code{message-required-news-headers} a list of header symbols.  These
 headers will either be automatically generated, or, if that's
-impossible, they will be prompted for.  The following symbols are legal:
+impossible, they will be prompted for.  The following symbols are valid:
 
 @table @code
 
@@ -785,7 +1556,7 @@ This required header will be filled out with the result of the
 
 @item Subject
 @cindex Subject
-This required header will be prompted for if not present already. 
+This required header will be prompted for if not present already.
 
 @item Newsgroups
 @cindex Newsgroups
@@ -794,6 +1565,8 @@ to.  If it isn't present already, it will be prompted for.
 
 @item Organization
 @cindex organization
+@vindex message-user-organization
+@vindex message-user-organization-file
 This optional header will be filled out depending on the
 @code{message-user-organization} variable.
 @code{message-user-organization-file} will be used if this variable is
@@ -807,44 +1580,45 @@ This optional header will be computed by Message.
 
 @item Message-ID
 @cindex Message-ID
+@vindex message-user-fqdn
 @vindex mail-host-address
+@vindex user-mail-address
 @findex system-name
 @cindex Sun
+@cindex i-did-not-set--mail-host-address--so-tickle-me
 This required header will be generated by Message.  A unique ID will be
-created based on the date, time, user name and system name.  Message will
-use @code{mail-host-address} as the fully qualified domain name (FQDN)
-of the machine if that variable is defined.  If not, it will use
-@code{system-name}, which doesn't report a FQDN on some machines --
-notably Suns.
-
-@item X-Newsreader
-@cindex X-Newsreader
+created based on the date, time, user name and system name.  For the
+domain part, message will look (in this order) at
+@code{message-user-fqdn}, @code{system-name}, @code{mail-host-address}
+and @code{message-user-mail-address} (i.e. @code{user-mail-address})
+until a probably valid fully qualified domain name (FQDN) was found.
+
+@item User-Agent
+@cindex User-Agent
 This optional header will be filled out according to the
 @code{message-newsreader} local variable.
 
-@item X-Mailer
-This optional header will be filled out according to the
-@code{message-mailer} local variable, unless there already is an
-@code{X-Newsreader} header present.
-
 @item In-Reply-To
 This optional header is filled out using the @code{Date} and @code{From}
 header of the article being replied to.
 
 @item Expires
 @cindex Expires
+@vindex message-expires
 This extremely optional header will be inserted according to the
 @code{message-expires} variable.  It is highly deprecated and shouldn't
 be used unless you know what you're doing.
 
 @item Distribution
 @cindex Distribution
+@vindex message-distribution-function
 This optional header is filled out according to the
 @code{message-distribution-function} variable.  It is a deprecated and
 much misunderstood header.
 
 @item Path
 @cindex path
+@vindex message-user-path
 This extremely optional header should probably never be used.
 However, some @emph{very} old servers require that this header is
 present.  @code{message-user-path} further controls how this
@@ -856,9 +1630,9 @@ unlikely that you should need to fiddle with this variable at all.
 
 @findex yow
 @cindex Mime-Version
-In addition, you can enter conses into this list.  The car of this cons
+In addition, you can enter conses into this list.  The @sc{car} of this cons
 should be a symbol.  This symbol's name is the name of the header, and
-the cdr can either be a string to be entered verbatim as the value of
+the @sc{cdr} can either be a string to be entered verbatim as the value of
 this header, or it can be a function to be called.  This function should
 return a string to be inserted.  For instance, if you want to insert
 @code{Mime-Version: 1.0}, you should enter @code{(Mime-Version . "1.0")}
@@ -866,41 +1640,56 @@ into the list.  If you want to insert a funny quote, you could enter
 something like @code{(X-Yow . yow)} into the list.  The function
 @code{yow} will then be called without any arguments.
 
-If the list contains a cons where the car of the cons is
-@code{optional}, the cdr of this cons will only be inserted if it is
+If the list contains a cons where the @sc{car} of the cons is
+@code{optional}, the @sc{cdr} of this cons will only be inserted if it is
 non-@code{nil}.
 
+If you want to delete an entry from this list, the following Lisp
+snippet might be useful.  Adjust accordingly if you want to remove
+another element.
+
+@lisp
+(setq message-required-news-headers
+      (delq 'Message-ID message-required-news-headers))
+@end lisp
+
 Other variables for customizing outgoing news articles:
 
 @table @code
 
 @item message-syntax-checks
 @vindex message-syntax-checks
-If non-@code{nil}, Message will attempt to check the legality of the
-headers, as well as some other stuff, before posting.  You can control
-the granularity of the check by adding or removing elements from this
-list.  Legal elements are:
+Controls what syntax checks should not be performed on outgoing posts.
+To disable checking of long signatures, for instance, add
+
+@lisp
+(signature . disabled)
+@end lisp
+
+to this list.
+
+Valid checks are:
 
 @table @code
-@item subject-cmsg 
+@item subject-cmsg
 Check the subject for commands.
 @item sender
 @cindex Sender
-Insert a new @code{Sender} header if the @code{From} header looks odd. 
-@item multiple-headers 
+Insert a new @code{Sender} header if the @code{From} header looks odd.
+@item multiple-headers
 Check for the existence of multiple equal headers.
-@item sendsys 
+@item sendsys
 @cindex sendsys
 Check for the existence of version and sendsys commands.
 @item message-id
 Check whether the @code{Message-ID} looks ok.
 @item from
 Check whether the @code{From} header seems nice.
-@item long-lines 
+@item long-lines
 @cindex long lines
 Check for too long lines.
 @item control-chars
-Check for illegal characters.
+Check for invalid characters.
 @item size
 Check for excessive size.
 @item new-text
@@ -913,10 +1702,12 @@ Check whether the article has an @code{Approved} header, which is
 something only moderators should include.
 @item empty
 Check whether the article is empty.
+@item invisible-text
+Check whether there is any invisible text in the buffer.
 @item empty-headers
 Check whether any of the headers are empty.
 @item existing-newsgroups
-Check whether the newsgroups mentioned in the @code{Newsgroups} and 
+Check whether the newsgroups mentioned in the @code{Newsgroups} and
 @code{Followup-To} headers exist.
 @item valid-newsgroups
 Check whether the @code{Newsgroups} and @code{Followup-to} headers
@@ -934,7 +1725,7 @@ All these conditions are checked by default.
 @item message-ignored-news-headers
 @vindex message-ignored-news-headers
 Regexp of headers to be removed before posting.  The default is@*
-@samp{^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:}.
+@samp{^NNTP-Posting-Host:\\|^Xref:\\|^[BGF]cc:\\|^Resent-Fcc:\\|^X-Draft-From:}.
 
 @item message-default-news-headers
 @vindex message-default-news-headers
@@ -951,7 +1742,7 @@ buffers that are initialized as news.
 @item message-send-news-function
 @vindex message-send-news-function
 Function used to send the current buffer as news.  The default is
-@code{message-send-news}. 
+@code{message-send-news}.
 
 @item message-post-method
 @vindex message-post-method
@@ -961,14 +1752,168 @@ posting a prepared news message.
 @end table
 
 
+@node Insertion Variables
+@section Insertion Variables
+
+@table @code
+@item message-ignored-cited-headers
+@vindex message-ignored-cited-headers
+All headers that match this regexp will be removed from yanked
+messages.  The default is @samp{.}, which means that all headers will be
+removed.
+
+@item message-cite-prefix-regexp
+@vindex message-cite-prefix-regexp
+Regexp matching the longest possible citation prefix on a line.
+
+@item message-citation-line-function
+@vindex message-citation-line-function
+@cindex attribution line
+Function called to insert the citation line.  The default is
+@code{message-insert-citation-line}, which will lead to citation lines
+that look like:
+
+@example
+Hallvard B Furuseth <h.b.furuseth@@usit.uio.no> writes:
+@end example
+
+Point will be at the beginning of the body of the message when this
+function is called.
+
+Note that Gnus provides a feature where clicking on `writes:' hides the
+cited text.  If you change the citation line too much, readers of your
+messages will have to adjust their Gnus, too.  See the variable
+@code{gnus-cite-attribution-suffix}.  @xref{Article Highlighting, ,
+Article Highlighting, gnus, The Gnus Manual}, for details.
+
+@item message-yank-prefix
+@vindex message-yank-prefix
+@cindex yanking
+@cindex quoting
+When you are replying to or following up an article, you normally want
+to quote the person you are answering.  Inserting quoted text is done
+by @dfn{yanking}, and each line you yank will have
+@code{message-yank-prefix} prepended to it (except for quoted and
+empty lines which uses @code{message-yank-cited-prefix}).  The default
+is @samp{> }.
+
+@item message-yank-cited-prefix
+@vindex message-yank-cited-prefix
+@cindex yanking
+@cindex cited
+@cindex quoting
+When yanking text from an article which contains no text or already
+cited text, each line will be prefixed with the contents of this
+variable.  The default is @samp{>}.  See also
+@code{message-yank-prefix}.
+
+@item message-yank-add-new-references
+@vindex message-yank-add-new-references
+@cindex yanking
+Non-@code{nil} means new IDs will be added to References field when an
+article is yanked by the command @code{message-yank-original}
+interactively.  If it is a symbol @code{message-id-only}, only an ID
+from Message-ID field is used, otherwise IDs extracted from References,
+In-Reply-To and Message-ID fields are used.
+
+@item message-list-references-add-position
+@vindex message-list-references-add-position
+@cindex yanking
+Integer value means position for adding to References field when an
+article is yanked by the command @code{message-yank-original}
+interactively.
+
+@item message-indentation-spaces
+@vindex message-indentation-spaces
+Number of spaces to indent yanked messages.
+
+@item message-cite-function
+@vindex message-cite-function
+@findex message-cite-original
+@findex sc-cite-original
+@findex message-cite-original-without-signature
+@cindex Supercite
+Function for citing an original message.  The default is
+@code{message-cite-original}, which simply inserts the original message
+and prepends @samp{> } to each line.
+@code{message-cite-original-without-signature} does the same, but elides
+the signature.  You can also set it to @code{sc-cite-original} to use
+Supercite.
+
+@item message-suspend-font-lock-when-citing
+@vindex message-suspend-font-lock-when-citing
+If non-@code{nil}, suspend font-lock'ing while citing an original
+message.  Some lazy demand-driven fontification tools (or Emacs itself)
+have a bug that they often miss a buffer to be fontified.  It will
+mostly occur when Emacs prompts user for any inputs in the minibuffer.
+Setting this option to non-@code{nil} may help you to avoid unpleasant
+errors even if it is an add-hoc expedient.
+
+@item message-indent-citation-function
+@vindex message-indent-citation-function
+Function for modifying a citation just inserted in the mail buffer.
+This can also be a list of functions.  Each function can find the
+citation between @code{(point)} and @code{(mark t)}.  And each function
+should leave point and mark around the citation text as modified.
+
+@item message-mark-insert-begin
+@vindex message-mark-insert-begin
+String to mark the beginning of some inserted text.
+
+@item message-mark-insert-end
+@vindex message-mark-insert-end
+String to mark the end of some inserted text.
+
+@item message-signature
+@vindex message-signature
+String to be inserted at the end of the message buffer.  If @code{t}
+(which is the default), the @code{message-signature-file} file will be
+inserted instead.  If a function, the result from the function will be
+used instead.  If a form, the result from the form will be used instead.
+If this variable is @code{nil}, no signature will be inserted at all.
+
+@item message-signature-file
+@vindex message-signature-file
+File containing the signature to be inserted at the end of the buffer.
+The default is @file{~/.signature}.
+
+@item message-signature-insert-empty-line
+@vindex message-signature-insert-empty-line
+If @code{t} (the default value) an empty line is inserted before the
+signature separator.
+
+@end table
+
+Note that RFC1036bis says that a signature should be preceded by the three
+characters @samp{-- } on a line by themselves.  This is to make it
+easier for the recipient to automatically recognize and process the
+signature.  So don't remove those characters, even though you might feel
+that they ruin your beautiful design, like, totally.
+
+Also note that no signature should be more than four lines long.
+Including @acronym{ASCII} graphics is an efficient way to get
+everybody to believe that you are silly and have nothing important to
+say.
+
+
 @node Various Message Variables
 @section Various Message Variables
 
 @table @code
+@item message-default-charset
+@vindex message-default-charset
+@cindex charset
+Symbol naming a @acronym{MIME} charset.  Non-@acronym{ASCII}
+characters in messages are assumed to be encoded using this charset.
+The default is @code{nil}, which means ask the user.  (This variable
+is used only on non-@sc{mule} Emacsen.  @xref{Charset Translation, ,
+Charset Translation, emacs-mime, Emacs MIME Manual}, for details on
+the @sc{mule}-to-@acronym{MIME} translation process.
+
 @item message-signature-separator
 @vindex message-signature-separator
 Regexp matching the signature separator.  It is @samp{^-- *$} by
-default. 
+default.
 
 @item mail-header-separator
 @vindex mail-header-separator
@@ -977,16 +1922,17 @@ follows this line--} by default.
 
 @item message-directory
 @vindex message-directory
-Directory used by many mailey things.  The default is @file{~/Mail/}. 
+Directory used by many mailey things.  The default is @file{~/Mail/}.
 
-@item message-autosave-directory
-@vindex message-autosave-directory
-Directory where message buffers will be autosaved to.
+@item message-auto-save-directory
+@vindex message-auto-save-directory
+Directory where Message auto-saves buffers if Gnus isn't running.  If
+@code{nil}, Message won't auto-save.  The default is @file{~/Mail/drafts/}.
 
 @item message-signature-setup-hook
 @vindex message-signature-setup-hook
 Hook run when initializing the message buffer.  It is run after the
-headers have been inserted but before the signature has been inserted. 
+headers have been inserted but before the signature has been inserted.
 
 @item message-setup-hook
 @vindex message-setup-hook
@@ -995,7 +1941,7 @@ but before yanked text is inserted.
 
 @item message-header-setup-hook
 @vindex message-header-setup-hook
-Hook called narrowed to the headers after initializing the headers. 
+Hook called narrowed to the headers after initializing the headers.
 
 For instance, if you're running Gnus and wish to insert a
 @samp{Mail-Copies-To} header in all your news articles and all messages
@@ -1024,37 +1970,50 @@ If you want to add certain headers before sending, you can use the
 @lisp
 (add-hook 'message-send-hook 'my-message-add-content)
 (defun my-message-add-content ()
-  (message-add-header
-   "Mime-Version: 1.0"
-   "Content-Type: text/plain"
-   "Content-Transfer-Encoding: 7bit"))
+  (message-add-header "X-In-No-Sense: Nonsense")
+  (message-add-header "X-Whatever: no"))
 @end lisp
 
 This function won't add the header if the header is already present.
 
 @item message-send-mail-hook
 @vindex message-send-mail-hook
-Hook run before sending mail messages.
+Hook run before sending mail messages.  This hook is run very late --
+just before the message is actually sent as mail.
 
 @item message-send-news-hook
 @vindex message-send-news-hook
-Hook run before sending news messages.
+Hook run before sending news messages.  This hook is run very late --
+just before the message is actually sent as news.
 
 @item message-sent-hook
 @vindex message-sent-hook
 Hook run after sending messages.
 
+@item message-cancel-hook
+@vindex message-cancel-hook
+Hook run when canceling news articles.
+
 @item message-mode-syntax-table
 @vindex message-mode-syntax-table
 Syntax table used in message mode buffers.
 
+@item message-strip-special-text-properties
+@vindex message-strip-special-text-properties
+Emacs has a number of special text properties which can break message
+composing in various ways.  If this option is set, message will strip
+these properties from the message composition buffer.  However, some
+packages requires these properties to be present in order to work.  If
+you use one of these packages, turn this option off, and hope the
+message composition doesn't break too bad.
+
 @item message-send-method-alist
 @vindex message-send-method-alist
 
 Alist of ways to send outgoing messages.  Each element has the form
 
 @lisp
-(TYPE PREDICATE FUNCTION)
+(@var{type} @var{predicate} @var{function})
 @end lisp
 
 @table @var
@@ -1086,10 +2045,10 @@ A function to be called if @var{predicate} returns non-@code{nil}.
 
 @table @code
 
-@item message-fcc-handler-function 
-@vindex message-fcc-handler-function 
+@item message-fcc-handler-function
+@vindex message-fcc-handler-function
 A function called to save outgoing articles.  This function will be
-called with the name of the file to store the article in. The default
+called with the name of the file to store the article in.  The default
 function is @code{message-output} which saves in Unix mailbox format.
 
 @item message-courtesy-message
@@ -1099,7 +2058,17 @@ the mailed copy.  If the string contains the format spec @samp{%s}, the
 newsgroups the article has been posted to will be inserted there.  If
 this variable is @code{nil}, no such courtesy message will be added.
 The default value is @samp{"The following message is a courtesy copy of
-an article\nthat has been posted to %s as well.\n\n"}. 
+an article\\nthat has been posted to %s as well.\\n\\n"}.
+
+@item message-fcc-externalize-attachments
+@vindex message-fcc-externalize-attachments
+If @code{nil}, attach files as normal parts in Fcc copies; if it is
+non-@code{nil}, attach local files as external parts.
+
+@item message-interactive
+@vindex message-interactive
+If non-@code{nil} wait for and display errors when sending a message;
+if @code{nil} let the mailer mail back a message to report errors.
 
 @end table
 
@@ -1120,6 +2089,18 @@ this is a function, call that function with three parameters: The type,
 the to address and the group name.  (Any of these may be @code{nil}.)
 The function should return the new buffer name.
 
+@item message-use-multi-frames
+@vindex message-use-multi-frames
+If non-@code{nil}, generate new frames. The default is @code{nil}.
+
+@item message-delete-frame-on-exit
+@vindex message-delete-frame-on-exit
+The @code{message-delete-frame-on-exit} variable says whether to delete
+the frame after sending the message or killing the message buffer. If it
+is @code{nil} (which is the default), don't delete the frame. If it is
+@code{ask}, ask wheter to delete the frame. If it is @code{t}, always
+delete the frame.
+
 @item message-max-buffers
 @vindex message-max-buffers
 This variable says how many old message buffers to keep.  If there are
@@ -1140,9 +2121,28 @@ say:
 @end lisp
 
 @item message-kill-buffer-on-exit
-@findex message-kill-buffer-on-exit
+@vindex message-kill-buffer-on-exit
 If non-@code{nil}, kill the buffer immediately on exit.
 
+@item message-kill-buffer-query-function
+@vindex message-kill-buffer-query-function
+@findex message-kill-buffer
+@findex message-mimic-kill-buffer
+Function used to prompt user whether to kill the message buffer when the
+command @code{message-kill-buffer} or @code{message-mimic-kill-buffer}
+is used.  It defaults to @code{yes-or-no-p}.  You may alter the value to
+@code{y-or-n-p}, @code{nnheader-Y-or-n-p}, etc.  If it is @code{t}, the
+buffer will be killed without query.
+
+@item message-kill-buffer-and-remove-file
+@vindex message-kill-buffer-and-remove-file
+@findex message-kill-buffer
+@findex message-mimic-kill-buffer
+If it is non-@code{nil}, remove the backup file if it exists with a
+query to the user, after the message buffer is killed.  Otherwise the
+file won't be removed.  It defaults to @code{t}.  However, it is treated
+as @code{nil} when the command `message-mimic-kill-buffer' is used.
+
 @end table
 
 
@@ -1152,7 +2152,7 @@ If non-@code{nil}, kill the buffer immediately on exit.
 When Message is being used from a news/mail reader, the reader is likely
 to want to perform some task after the message has been sent.  Perhaps
 return to the previous window configuration or mark an article as
-replied.  
+replied.
 
 @vindex message-kill-actions
 @vindex message-postpone-actions
@@ -1165,7 +2165,7 @@ C-d} which postpones the message editing and buries the message buffer,
 and @kbd{C-c C-k} which kills the message buffer.  Each of these actions
 have lists associated with them that contains actions to be executed:
 @code{message-send-actions}, @code{message-exit-actions},
-@code{message-postpone-actions}, and @code{message-kill-actions}.  
+@code{message-postpone-actions}, and @code{message-kill-actions}.
 
 Message provides a function to interface with these lists:
 @code{message-add-action}.  The first parameter is the action to be
@@ -1182,7 +2182,7 @@ This restores the Gnus window configuration when the message buffer is
 killed, postponed or exited.
 
 An @dfn{action} can be either: a normal function, or a list where the
-@code{car} is a function and the @code{cdr} is the list of arguments, or
+@sc{car} is a function and the @sc{cdr} is the list of arguments, or
 a form to be @code{eval}ed.
 
 
@@ -1192,7 +2192,7 @@ a form to be @code{eval}ed.
 
 Message uses virtually only its own variables---older @code{mail-}
 variables aren't consulted.  To force Message to take those variables
-into account, you can put the following in your @code{.emacs} file:
+into account, you can put the following in your @file{.emacs} file:
 
 @lisp
 (require 'messcompat)
diff --git a/texi/misc/ered.tif b/texi/misc/ered.tif
new file mode 100644 (file)
index 0000000..4b64018
Binary files /dev/null and b/texi/misc/ered.tif differ
diff --git a/texi/misc/eseptember.tif b/texi/misc/eseptember.tif
new file mode 100644 (file)
index 0000000..b75ae6c
Binary files /dev/null and b/texi/misc/eseptember.tif differ
diff --git a/texi/misc/fred.tif b/texi/misc/fred.tif
new file mode 100644 (file)
index 0000000..e04f262
Binary files /dev/null and b/texi/misc/fred.tif differ
diff --git a/texi/misc/fseptember.tif b/texi/misc/fseptember.tif
new file mode 100644 (file)
index 0000000..6583c2b
Binary files /dev/null and b/texi/misc/fseptember.tif differ
diff --git a/texi/misc/larsi.png b/texi/misc/larsi.png
new file mode 100644 (file)
index 0000000..d8b5b27
Binary files /dev/null and b/texi/misc/larsi.png differ
diff --git a/texi/misc/red.png b/texi/misc/red.png
new file mode 100644 (file)
index 0000000..e646e00
Binary files /dev/null and b/texi/misc/red.png differ
diff --git a/texi/misc/red.ps b/texi/misc/red.ps
new file mode 100644 (file)
index 0000000..26148e9
--- /dev/null
@@ -0,0 +1,2809 @@
+%!PS-Adobe-2.0
+%%Creator: dvipsk 5.58f Copyright 1986, 1994 Radical Eye Software
+%%Pages: 1
+%%PageOrder: Ascend
+%%BoundingBox: 0 0 596 842
+%%DocumentFonts: cmcsc8 cmcsc10 cmcsc9
+%%DocumentPaperSizes: a4
+%%EndComments
+%DVIPSCommandLine: dvips -f
+%DVIPSParameters: dpi=300, compressed, comments removed
+%DVIPSSource:  TeX output 1996.10.29:2011
+%%BeginProcSet: texc.pro
+/TeXDict 250 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N
+/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72
+mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1}
+ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale
+isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div
+hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul
+TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if}
+forall round exch round exch]setmatrix}N /@landscape{/isls true N}B
+/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B
+/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{
+/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N
+string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N
+end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{
+/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]
+N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup
+length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{
+128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub
+get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data
+dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N
+/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup
+/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx
+0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff
+setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff
+.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N
+/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id
+gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp
+add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add
+/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{
+dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1
+adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2
+idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string
+putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval
+adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg}
+{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{
+adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2
+chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{]
+}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup
+length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{
+cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin
+0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul
+add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict
+/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook
+known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X
+/IE 256 array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for
+65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N /RMat[1 0 0 -1 0
+0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X /rulex X V}B /V
+{}B /RV statusdict begin /product where{pop product dup length 7 ge{0 7
+getinterval dup(Display)eq exch 0 4 getinterval(NeXT)eq or}{pop false}
+ifelse}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false
+RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1
+false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform
+round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg
+rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail
+{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M}
+B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{
+4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{
+p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p
+a}B /bos{/SS save N}B /eos{SS restore}B end
+%%EndProcSet
+%%BeginFont: cmcsc8
+% T1FMT-V2.0, Copyright (c) 1993,1994, Basil K. Malyshev. All rights reserved.
+12 dict begin
+/FontInfo 13 dict dup begin
+ /version (1.1/12-Nov-94) readonly def
+ /Notice (Copyright \(C\) 1994, Basil K. Malyshev. All Rights Reserved.\012BaKoMa Fonts Collection, Level-B.) readonly def
+ /FullName (cmcsc8) readonly def
+ /FamilyName (cmcsc8) readonly def
+ /Weight (Regular) readonly def
+ /ItalicAngle  0 def
+ /isFixedPitch  false def
+ /UnderlinePosition  -133 def
+ /UnderlineThickness  20 def
+ /Descender  -194 def
+ /CapHeight  683 def
+ /XHeight  506 def
+ /Ascender  694 def
+end readonly def
+/FontName /cmcsc8 def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedblright put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quoteright put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /quotedblleft put
+dup 93 /bracketright put
+dup 94 /circumflex put
+dup 95 /dotaccent put
+dup 96 /quoteleft put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /endash put
+dup 124 /emdash put
+dup 125 /hungarumlaut put
+dup 126 /tilde put
+dup 160 /space put
+dup 161 /Gamma put
+dup 162 /Delta put
+dup 163 /Theta put
+dup 164 /Lambda put
+dup 165 /Xi put
+dup 166 /Pi put
+dup 167 /Sigma put
+dup 168 /Upsilon put
+dup 169 /Phi put
+dup 170 /Psi put
+dup 173 /Omega put
+dup 174 /arrowup put
+dup 175 /arrowdown put
+dup 176 /quotesingle put
+dup 177 /exclamdown put
+dup 178 /questiondown put
+dup 179 /dotlessi put
+dup 180 /dotlessj put
+dup 181 /grave put
+dup 182 /acute put
+dup 183 /caron put
+dup 184 /breve put
+dup 185 /macron put
+dup 186 /ring put
+dup 187 /cedilla put
+dup 188 /germandbls put
+dup 189 /ae put
+dup 190 /oe put
+dup 191 /oslash put
+dup 192 /AE put
+dup 193 /OE put
+dup 194 /Oslash put
+dup 195 /suppress put
+dup 196 /dieresis put
+dup dup 161 10 getinterval 0 exch putinterval dup dup 173 23 getinterval 10 exch putinterval dup dup 127 exch 196 get put readonly def
+/PaintType  0 def
+/FontType  1 def
+/FontMatrix [0.001 0 0 0.001 0 0] readonly def
+/FontBBox [0 -250 1142 750] readonly def
+/UniqueID  4701552 def
+/StrokeWidth  0 def
+currentdict end
+currentfile eexec
+9B9C0887DB83FB1ECD8335B0BB39CEF0AF64F656FC6E5C230CC9D3A7346AAC7A
+06BD9A40393CA15D3773A21E06B9B4254D3050E90726BBB09120935A8D448CDB
+C799D90205A21291254FA633CC0C2ED88781EF21A5D45B72445C284FA44F8F39
+CF566976075A92E9E2947A6FC93D879C29EB26809ECB4409CBC8666526CCED92
+65DE661A2F8B0A16BE45A9DA17EEAF89B0E023DE2B0373DCAB997D60B7D7DC1B
+4F7E650A2A9F13CA0543F3B080AE33D65F2802B8C6F032ED6E6DCCE8BDCA96E0
+7ACBDA80BD4CD2ECDDBA9F2153A5830B911EF4A2B2759509074BBB7EF4647A84
+A7D80486A975F887C24E3B91C13DCA84013E21D22732074711E18BF909EB19E0
+17003B8DDC9A09B7DCA54C0683A0301A22EB83147467E02063122C43B4084720
+DD14D09F869DB8BF36651E182AB50EAABD5374B4765E7BB0DBBAA6F1745B0EAE
+3CD63C9913A9AB7ACA280E94078158263D7DA75FBA9944B33A681993B009FFEC
+04291CA8E1DCCAF55D1FB9B4C630E378EB500EA97B07B6F3F3A66820CA68656F
+AE47789E6C164A26FC1C2525E4247A4AE5D0B9202A92EE3090FB25093B2E68F4
+DDD3DC598A87914782AA1B79AA31505752F8A47D2DCB51ACF6EF0832B9C1020C
+2761DB6E6AB9749D4D7993682371D9BEE6684D1EFFCB0F1465672DB9769673E8
+2435B28D8BD3E4AECCBF2B127E146415B15066D39103B20C8B415B3C6A640FE3
+5934F1A1E8256A6FDF9208A56E65A7C94A960923889D592CCD9C94DE37C1448A
+09D876F58C506924D478BFE724329AF64157543A5263A8652FD2E852BC07FF57
+E438C93BCE2B0E219EC1A8E2C8A6DC708C990810A536877369A477D7E7D12355
+434A7A99CCECAA340329044B79B33AEA924E95AE898442A7FD06F7E73948F535
+A8556534730B981547A9ED3D5BBAD6AFD08BDC8FCAE6A46F63644D5BFE139A0D
+EA380C737C228832FCB4DCD0BB8208D3050E5CDF7C194835E9770D1F60F4B78D
+910E195BDC30653EE5BE7DACD166F2BEC6698CD2D355BD9605795E6EDA8462A2
+BA319945113FDF8DF0C629532064726133522021D21B033DFCA23EC2F71CA591
+2ED8FF78703FFB2422C2E38283AAA99B9A7BA72C3124957D172BBD55C6FEAB07
+6CCD143228A63253BA4BE92E32FCB72E150BD00CD5B2A1427B1C4901B0CE4479
+A763497DCE9904F4C02D440646725A28B897AA2524D9CD05C2A2F21919F22378
+88131B729ABF1FEFE219D93FC16C55C37CBF7DBEFF403220AF82CA530052F476
+7C140370CC7E73AF028A152494B4AE330BB66ADD4ABC6D74BA1CAAD743E9969C
+7EB9C94D56448B8C1A5D65199C45E746B8D9498C836043282600FF0A4AA0DA2A
+93362A65B9AC53679BBE3DF9C46A56B252C39D0E4C6C475AB50B0F6077DF0E51
+6E2B629AB0D7F4B8916309BBFD04EFEB53B2A887CD71E2F2E7C5546FFF3D6807
+2E1700F1FC8BA07F7DB6DA818D981284D05459161CB626165708B665399B0C44
+B20BDDD6FF4747C9539F3A9D1B2F6E198CA21D61F8030C56DB55B72210CEE1BD
+783030A32B7109F317B75885C90DED2ED25F1497F9BF7CB750618565D8B9F7BC
+B14D5770240396CD2D3E22225E76FD0222F2DE79615ED0EDFE19D7B8940BF147
+974EA060EDE6142D3A98E86F3BF92021D63BC13E79D2D7BF12C4285BC9805E0F
+B330DF7CFC283BD744CFA70BA34025E2F9C4F613B4AAD255F7D6493105253E37
+A88678147D7F1B600E611813BE2866B827ACF70FCFFC2BB331639D8B212D48B4
+285BB430B120820CF07C849B8C4742F60408D69E9E5A3A062DDD616AEA5D65F7
+B6BE3CD8672561678462F38142B6DA16BE3E8E1DA1C49E5E1E447F9068ED7813
+C406B262E01434885E0A0EB5EADCCD01D09229C801257F7C400EC7FA7384F138
+816CB2D68571A14FFE15DA71206EAB82A9CCF44CBEB5F1CF80EF5EDFAF70088E
+0315677C806D87112A0F1F5387204C2172B3551B48297EC3C0987EA47E561BB0
+D1A59CD20A0A8950420006CE3E8F2E89131ED3BF235753440A31322420321948
+50A91ABF95D81A7333903852994489482C760D8E6ABCB90D4BC76E59A7D77543
+18DF8DA712C2886272C388129B9DE91E139EAA28D4F8E628F66F8CB82EFC63B7
+4DE99680B0A40D2E8D27F2EFC4D3F84B5D4E2664438C23EADD2432A078F0615A
+1B168BE016AA5EB1BBAD70B50EB6BBDD98AA46035E177CA3B5D2C0B19430236D
+E42DD05E4C5CADAA36F9F2B59163C0AE31FCC8FF0ED40666E7C409F2DE49D54E
+9AD3AB0BA8DC7917A5A11D5553F3C5C3AA761C71AF6FA03E74FA0A8CBDC00C58
+5BC44EA557734457D1C3017BD8215486F4A912B6CD5B7F5293641CA5E18CE696
+94439509E39668443555D82D48982CD86A72307F9181561F4A48713B18F7F414
+D62BCC15ED2130C3C3A12147C340C5CF16441C6B1C287D2952EE64D4524C67EC
+6685D7110F55DF79006467C567F450C058C47495B54EC7D8AA9E54EAD272A6A6
+3985B7EFFC7F1374EF726AF07995774F42BB910F6B93275C81481E69CBB062D7
+48DFD3A8F7867FBC0777174D1645EFF68737E152BAFFCA6D11E9E047D23B5DC0
+AA510CB028F7BBAEA876B4D80A8863BB0307813D6CB051F001665EAB2AA77687
+F1E5381BC3A60884510091A6C8A065C5255CFF31CD5129A33EF4A2A1F29B0B29
+081076B795D99B052F5152231D63BC2542661943D1771CF0BBD5255851C467E3
+017AB1CF41E127F90AEB0D465E70DF088A1D1B72B8AE8DDD08E72B5C8CCB7CB9
+004B39BAD93E3E8D3EBC1254CE7C047788C46D9826E2C444F1E0FF2401FF7DF7
+6A202BC1878BBC6DCEC3B17DC323125E4D75024B4A08E92F0C1B97D9EBF895E4
+1E384FA8D6C66E19E39C8A26FD1E0E5A5905B152DD7F617058F9A880623A9B4E
+9F1737EC61D00C576ED8306ACB625E1AD85A809CDE751A34B83F04F89817D627
+E34844FD56719626BAF81FDF2BC4815F7AD55833E17021161AC6CA9B2393721A
+C39323754978C27F0A19D3DB3DC517D4322FB3B673C26B1FFB093590EB133DF2
+3D30AE05EA926A43FD3579EDB1E9D402203ED0A0694E258CFF6B136CFA2BF757
+E7EC2C9C1332B998DD86E7467F522883AB5E9D01C948402E3814415E0DF6362F
+D29616D861AB88D3AFF5EFF233552DCCB301AC00C57A8CC3A75544C3F1FA92D1
+D13888FDF0597E8EC842C0C6DAFFA6F5FD36AFD0EE385A87BCE628AD3C963B98
+5E66712EB1EBB886C8C7AAC776C41F4CD1D1B2F1207C2D0499E8911CF17EBF06
+DB261EF1A9F73C487D0B1AF98C26E3ADDE84678CE54F6877440511D21BFBE304
+98A6ACA6AA32775BE50C603EFC86509D1078AD952502E1E0ACBDBB1134F5DCDE
+4B423463E37FA01D0233C049CC9A61EC5A0A9373070CB6431798186C116145AC
+20AC07CA60DDD0CFAA838674E889ECBA7CDD700CC6FB02C4BF018A0675798A14
+BC3F97B7A0C256711C9983DD7C465364504C1C14C51288692FCD0DE3F26CA406
+7E4D7CFC45D7C4DDE97A61423185C0FE7B9960B396028B532D52016A497CE87B
+5A5B35136246646601B5BECE7E380F3F3A2EB428CDBEFD4EDB6018AE34A441DA
+7CFD700D66527EDDB47091A64696275096DF98B4B9178159A0FDADADE7515C26
+F97C12422D031F8D230FE2082B11AD582F2BD054053E2E8DA0F4DE167A354241
+F9758A06B11379CD99F3129DD37DCBCA5F765478D682110E848AF83E63B3EF27
+AD0F2F23CEF688EC5A4811D1E73292D940005DBF7DF19524E33593AA0CA9B030
+926DE55A6E8384D006632F5900D00F851708CB7EFA5D0B227DBEAE710F3CA02A
+890482C433ADDFACF2960EF914F9651A47FAD819A4C17FEFF30ADA059D9CAECA
+C143AA3E92AEADBA92D85BAF433344FC16EC00BCCC90DB42660EFB6EA2D68E42
+37D4083FEA72FEBC845C7814FD8F50A0687F93C26E32661D5C6C5888259FCDF5
+C70464929FA36D2E59FCE1AE85AC3C5D733726DC92600AE606C878CED4706F8B
+1ACFD0DCEC65DB23179B3E08E456AF6FDE3027C44F3CA86FD02D30E1FC8F3450
+BFFB18CACB0CA334D6D6C11B4DF63EDE14012995916E9965ACB3575ED07BEE18
+BCEE5D634EFA1E9DBED3817F10957D957900E6AC120D2A0578CEB6FE9888ED01
+BAE8869A8DD42E447E29BAAC8E025F63B64E90F055B7D3D7BA91914B55C58E1A
+E6F984CD73413E494BBE8F20A2030B92E103874B7854804744EA67F34BB32D26
+CEB4FFBBF4F5C53ADF745F9F2108F28E6E9BD346B677D7D81D29BE9D41EDC105
+AAAE4C65004BFC8ADE14673D816512A81C1720B2A4FDD19690303A284472BDCD
+23D6A1890FB40B476123038F1AF5D2679BEED1C037F5532D32202AA8BCE983C3
+AE95E4A4407AA55ED9365D8326B1BCD5977E4BF09DDF76423E94848331642C6A
+3E1F48AC45A3957638ED5E147DEC4C195EFAF416F2A9AB07765F972111D96271
+DF49CD50F562E18E44309B86079A015AEC2654F5D30E387C8222B264428A6C51
+AFB024147B909E6598AA3A6085234A6DF6EE4F8B7C6D9D5A4C7428E7634C13C9
+EBA54B692234201F6DE0DA56ED76D4951D0D89A53431B83089FE196262525784
+F218B390E3FDE1F7DF139E876887A4EC4C7C7337DE070482E60765358688BD73
+61B84BD08A31BF1AB5F833E155079A130F5039DC39970BDA24C9F89206D6BC13
+31BCE613202E817404403EAC748D4BE72CE82B4ED24E33A45F39091E0D33E7AE
+D961B0CEBF6A0187769F43BC921AE7FFCF3F933E8D4B6B0896B46FE843E0F783
+8D7531622D72B135F34F5DABAD6120E290CF281A38A1D22FC12FDF58C9655848
+B045CF758DB113D61303EF62C4D9228D58E60726921686B4DA64E64C970AFFCA
+63C0D672A9C28B88D1194AF22328E0A4DA9A65C11CB59B5F55F0CABE32AC729E
+119AA07D135D97C8FE90A213D466C5A02CB2E0CB78EC1EC67CADA027ED6588EA
+17410FF368DF29A2D36E0F2CD43DA29BF6E0BD9FCD56A0F509B4A1BB0D35BA2D
+E0A09400BD5E557058E3E168400F2F34E33CDC252E76FC7D252E8CED53A265BF
+02B05A11D432E17E5E496A14F7AF41AD237372C22D0FCA183DA4A87B191A282D
+ABBAA8C292E9CAEEB5722A98BF39639DA0232F80F624C667DFD9AA8C7B210401
+D65F6D88A8DD33211B1C58D12DE7A6024C6CE7F62C7530C050C35DBDB3E4B7AE
+8686CDBB7FC13D2A16A064A00AC7FA37B3DF11D5E6AB7B26D70F7097DD1A463C
+F199861DCB273D8BD27DA5E4C01F64D59D6C6301CF85F9C100F182EFE7824A0A
+AE6AD44811F9E31F21ABFF320823FF6416F9524C408BEF52D6565AFB590AF48B
+787BF5CC4ACD76DB049F807F4AE0C1410446960392EB1F897E308918ED11A2D2
+2165CA9DD631673F608D1D2594D8D2003E9EC77E8B4FBEFDBCD9114E39042556
+EDEB5D66C755966A1EF4607F283B0E604C7A611ED7FB30AFF1AC48A3C9E8443E
+AB020C1C274BD90D476076FD1D7119B80CA4BF14AEF63288C58C17D533935EEE
+C69CD5F16C27953155C5111E49A8F0BCED4F0638AA63424266037220120AE497
+28C1511E3CDDF8AAB7BD45E32ADB2368A111F4280FA7D77D4331C116578B34CD
+DF024F7ECCC04E2A79C5EE039A647AF7F8B6B50CF477CE0F1C6513FED5A4A28E
+6919C2507F0FB9B8A1FEAEF739FB2F76B27BC63148FA3893731CD2C07A2EAEF4
+32F8A9E0B60DCCBA2625203285DB22DFE6331D47114CFF282A832B49C6DFA41D
+EB713891FAFEFDDD35B8977035FECA00118D0B449C849807F3834AAC455ED857
+E44ECEC289E7C2A97D184E253C24D2DAA1E2D5B5A18DB7013A549C5ADDA2FB58
+AA6FC4E2BF2D66FA37F1D70BDA8BDE834FBF7492EC522A7E7CB1578C47497E16
+6D350795FD7A40BBE85C437B60605AFF8595DB6591BDF61C56588E774227E1E2
+EDDC27AEA4A1CB6EFEB85D4C9CB1BBC60AB12C6452BBD70796F443A86E797E15
+293E6CC2C90245FE60C8039B25DF068C08C0101CFD6D00D1F7035DBB0490C0A1
+30ED4BAB83002DDAF4AF4DD4D00DE5329C79120E11D962F896AAEA17FE0090C2
+7F72A7FAC06374FE210246CA064A418F41BF71DC8B24848D1C8FBB1B7DDBAA66
+E698FCF9C6772A48B2AE1A1C4B48E17BABC6F2ECACED6A2D93C1C88E25B24F35
+B2CEB9791B56FFFF0744D78789F08E6C18F2067B1333B65A1A7D0E17042EF669
+B654DE023F51138863C399367CAF2A24DBA556FC96EF83931B159EDD23936643
+5AC3AEB5B1B0D55970F95574AC6D28221B4C4A6EF2C79245D479B654999FE261
+35D105EB8238D449AA347D0E5C1DDF8E864D64F8B5A30B3BA8D45A056BD44EBA
+9D3187EB5A0DE2C180C23A7E67C9D4FC406DD2DD65311D4AEBB248F808250F62
+6554BCE687198D3C7F17E05A135CA32F78653917966DBB5CD1D0A5AC853D21C3
+6E12A327B2C266A6F6E68172B8CB7554EEE21FAEA90CA9B23C3522AAE3DA7A0D
+636DD7E95F360524FC45404491F77B86B4C556D291C43EBE93B02470C5AC926F
+DE1DF486C33410BA8A180C733198FF6D395CB1FACD0230AC8D4AA0BFED92EC39
+5854F3D9703A22B10797848921BC020ED3DCD1995FD7BB958B5D1C4EBDF64417
+0E6436D6627769786331A57EAD7F8CF003CF9F9B91D67CE861B914F6F76043AA
+F98C977CFDD7AE978DB14C1003EFD6E20758D14E89AB901583DD6FEF25AEC853
+2E605D4C061600A63CA2C6EE608E075EC86FDF5A59DF5097FC79C206307CA74F
+60C6973E73DC392464A7A367986E55E63BFA4E60FCE12CDAA7751875E2F986A0
+8C6E1B992F925FB8A36BC28A5F2A505E24BE752E7D88F8CFF3A0B9018598050F
+D3EC8E2188FBD2264C8676E9CDE54F6E1537BB7F3DC61330ED9E165E5285EFC5
+5209BD7A8AD120015F03A2CF3772FCD1B4AAFD01F080046EDF1970A5024698EA
+07CE1F1F98C272DA4DE32232520574727B76C1B1137F9F1934310E7CAFECC814
+27281B334C132764A015C4D1D1DEF7460AAD063228C346896105018A5F78CC4D
+AF70ECB26B0C210DBAFF76BF479920809C35120721B2BFE5E95C50CBF3892339
+A78088197FD12BB712138515CCF50D09C6790E0FA678EA80C9B73AAC450280B4
+F6FF5D55F85BF9FE7927F29E74CA6A7023C55D761E7312A842137079A0420095
+9E54938344973FA3F6AACF978E861C800C97103EA952113A79C0088557216D10
+F55EECA021975695F68E36E51F229AF292E40069A167DDB66EFD5E5E5B113F75
+DC4CAE95D6E2F2B46410FC0DF2EDB3C9E4525FB3035D276608805A2410F475C7
+C02FDB7627619F34510299C03E8EF22D82C0F0BA848E4D63DCEB84BC5239E860
+A01980A898E7406F2C2C2683D864182EB055D5401A6BE0C51CA23382A25F3B77
+96FA4AF27212794228074676D53CC7ADE248B87B6DEAA00653DC7515D5D68A12
+E3CAB1CC1D4828ED42132EE31BFA2454DB21DDAB9871588D40153E879CBAA641
+EC670FC30C476BC40843BC52D06B65D3E21206393419C2A3B80EFCAFB9A8D945
+A8865633F5480A44D9E54E4B30A0DEF43D2686ABA55FC2ABE38751ADA14AF090
+AA086B564CDF2AD272700CBE7014C34747EDB454A6E1C3D4F89C1864D12D00AB
+980A73884FB915D4BCD7AE17FD70414E1E4156CB64EBEE3C1F1B65C7C07FD457
+528024B5C5F54CF00F5B3003B7819D4F8D52C770B555A428C0D8AEB1ECB5E1AD
+56097BB4953D5C4F9071A781B59186C198EB18A55B23B88A8122151F14BBEEBD
+AC9F98F7F5C2C98544832514B5F55F38B007463783C8A35A17C3B9643C299D8A
+9B3B7B5AC937E5D84C3350FAE832D03EDF33C947001111FA191853F980F94A2F
+B0C1B5373E3D8D7812E56D0533CB81105634DBE5A3E1ADAE4892E63C6DD415DF
+94FC71C47D50B09A07240AD792B982D2EBE06B07A5DEAEB00111BA1E801D9D47
+A972E4CF59018FC24056BD3312E7F2F0767DD96DBEF430626B4BBB97B1B4795C
+A2A07F77E676C019F56BE0D97DE82D9FDB145B6F26B6158D61C308940B41EDDA
+49ED20605D0D8CAC1D388F9458C627A791E5D6E214F1BFBA154D0F8FB70FA297
+0E2B98DC3FCE351E8B9F0EE20FE6528856C02FE91DC5D83C8C52B3A1D7AB4025
+F5379C5A590570D228FBD7BDB243A9B95C6D156F7051930F0F112B57242EFCBB
+545A55D8568F3272D94BBDBB9B5DAB351C9940B42C11E1D2B860A2ADD4D9F914
+E4C1A513D3EC036D749DB0D652AE6AFD99C886BB65234E75E985ED5775595662
+B3953D1B90C2D841483A4D937352271E311C17ADD47FF0652EC281C30A7E00D5
+95FBD22A2D57B768B1A6402AC2BDA87049F299EF3BE8C76F8472901ECD10ECAE
+1F77615A9A76FDCB3ACFC8C1A0BBC9207CEDE059C11B452981DE849AA5361BF9
+EC51F7ACD2C1C3CF2E36C67AB294EC1DF145FDFB87D8FEE3CE8C6F744D089C5E
+8CAC6EF70BA2E6862F44F0792426E85DE0F2987AA239B371B00F3E2F4027079C
+11D40FC16ABF28EE96848C97B0CD695BEC0F961C96BC744DC6D7D08D2E1B9F97
+78DA68012F7E1DA1F2CA72000B4E807F22A0D77272E00F44478F1EE69882BD4E
+3C58EAD4BF9269DB275069750017D84B460772B9F25D6AD78D0B32A33FD9B748
+37E0E166FE9AF15EC12486939626FB4AF31D503F9DD3E71B1D31ABFCED334C4D
+F58A03DA6A641D5DF8D6E5CAD1927BDD0C9F32B970C4E7539089C66D107D8757
+31C513230C44FF66883CB7C46EBD1F635F8A2BEB78A08AEDFB8E165050C8BFBF
+05A259BD655B2AEE4BA2DD04935BE78AA36151A76D3DEC7B16BEB5C7439FA66C
+D18F0EA8B0FD1FDBB2C7718C6D6F60B8B26FE85C808D109C9E4F62DCE099D218
+9CEECA5985E6A930F8A78DC2BFB09CFADE3EE6EE1A71C735DAEC2EB01FAD7C81
+71CBF28E6D4459CBE917D87B80D6ECD20FADE383146A4E75A5AA65E1A8E60AD3
+51E91BF11B524E39C2727A6C0D355F44C913C4DB4243D07532966D5C4D364BB4
+543CD6929DA2B626048DA05A1B7843A4544F855ED61804D0317AF029BAFD2AB4
+876B1513CE3D795808FA0BD050E2DB4630BCF0A3F2AECCC5CCD584B955279170
+8C7F30532110312D0CA374E53E63F68545B7EAD07EC04F1C75539E850E649779
+6F0B5278F1BE0979BA2B969FAC22F6811E0B9133FCFF0CECCADDA634296DE080
+F693EA18A2461D9422E2823C51ABFF572D332909F1752C6312A57ACE6CCCD9FA
+17411A598F7E830984DCAE07AC4BB0229D60AA03B0A4D874FED1A864377D6EC3
+6F5B70E2FE39A0EE4B2E8DCC3056216DE2415F6725D54C15C8B2B7B3E4E3E3A7
+6F9E42CFB7FB5CF8AFAFAF8A3FDA4DF46C04EA9AA8F36E1848509F0850B6D221
+6F31A27F335334E79BD776A88B1DFF7CD00EC614CBBD6E53A889A32BBD9111E5
+C7342C9F425147907E55FD1F15E723571952DE7655D43505E38F10BFC81DFE36
+1C62330FF3CDF15E345A089C369E40730AC7A716F79218AB308B12FA82717EBA
+693FD49A020D7BC6E19A7FFAA773A9A91BA436579B72D7ECEAB4665F2D00396E
+C14BB34699D454AFB879A61380308618855B5502B3EE358BA7AF8F8C7C793DBD
+90BC9F4086E996CC98ED5AF7905E46F2B331E1FA496DE6EE4C3805EF90045364
+D9CC995CF2A903A07A05D95F3A070D863962F45B62C911A530A4EF67407F41F9
+4E6AFFC26C752A841FF5057E6D855F120D9D28F5886DE77A2D300A70BF15EF6F
+6A5FBCED92F9A01800668B37141405B50D2361A5DDB12537032C000140BB4F55
+40239833345D9A6536CC04D9BBA6F2D3172347E5B9D763553F5F5219E20D3122
+4069388532E29926355F1CB6644713F864B2B62D7611657E1FB52A8E7B4178B3
+766FAFE9CAB2F1BFC41BD2AD1AAA8F44D51C843C75FC23BC48860B04F2C752E8
+BB379C86980ECE56FC5712E98C7C2E7870EB1E878F5D72B1C620A6B46629799D
+B341ED8D9E6B830336C4E690626849E1CFFD66DDB2DAC99DB493A5DF24BA7DE1
+C1C88AABBC6AD77E5240B37E42C1F76C640D9554C2A7AD7C214FF2AD422016DB
+035CB47A085F195A5EC0D456AE3AFCE12FBBB1487F1A9FC289FC856A855F3B79
+3967F8FBF57C5F5C540D6DF14371B140C0DF167143684CEDF0596F661F3C1E5E
+69AB7A3282D918A9DC6165F1D2F04937ACEAD13F50A11485445567C5BDAAFE0F
+F00891D2389171D7A62B631FE53A50FE55262B70B2B5E267996316FA2D89B094
+95F0C36181E2BA08180C7DA957C7ADA62B2BDA2F175F620DA7474138B19B691C
+2ABD0B87EC5983F28A53B4E1602F656DBDA57484E58FA00E3E1113CAC39A46A8
+D323A4EF0BD4C397C814A148EA3F6BFAA1F1AEFD89FFFC3C0D4CC652A6EED5D2
+0250E59F13B2963996B23F5A202BAB3804F861050A1A68352273B5FC03AA6C98
+A02B4E1A77351A3D22DAB1B863B1CB8EC6A7C30857C661CE7866516D3D4D423C
+83B9DB0960FEE729D01F1350932304804E1760CA4318AA8C4172C11A1E370E41
+F0553D4CD81A4009385BD900C7281597795AC3E1588955552935ADB5945333AA
+AD58E9664E6CC32BB2E00EFF6C495285B079F4C43D3A4C522A7ACB09EAB4B414
+DAACD32F9FEFB5500B60CEB1A36B865849DD999A42CA0BA0FA143CB5E2526195
+4081072B5519457C5292DE0C9EAB3334CD0B4FE28EB5FA9EEF554DEE92EB4EE9
+54531661F4F89E620A928587ABB62D3E5487AFF152FADF2FA795AB4A15B064F6
+D12F241997234C85504DBBBC087E7D78C3A1D76670AEE02A359ABB380CB660C4
+2282A5151A26D912C47EE8DD6C17F77755A668FC07AD983F14DCE16EC1AAFDCA
+14C0A35FC2696DD3639D5465EDCD6141422E98AD6B62337D746DE9AF1396B52E
+7A8AE4DAED9A4F7857A8E536AB6902E1C641967570D4272181F25B428CACCE8B
+386CB4FD821DBCFA2DFE97D7A16648D6D2256ACF48752B6E4CA82164B1BC574F
+171C814D8684206A07976818A428872B24010876B9D491DDD8202B87999D1634
+53ABAA96B7C04D089ECFD3124ED13EC092BEAF8600D4E2FFA48F494A72144BC8
+B26A5CA15776034BCC26026476E62C27DA349F822194E48C42B76195FE81E4A5
+0CB66E8E5E63AB49814B854A1AA3B6488A543AB56152BD814313290DFC3D55B7
+33E61EA591430BE394B95B1C9BC783135394EF1983CA53467E8A32B5D8538655
+365FD7E9B01C77CDCD033A71FD8D122674820BD3A4BA0675CE5C977EA21B08BC
+C2F7C1F95D83B43C523C00E66AF5DB996DA1B73CD07DA13B686186DE3292DB9E
+663EE1C7A30D6805A678A5B312F9232C934D63F563042C4C7F4C5C4B5CD21E1A
+B4474AFC32B431E4D0990378803221116D1C86049F297CAD0DC4E12D0FBDF3B5
+F799FBED0BBE17872DE2CB6C0EF8DD486A29F1993DE0ACB7AF4B7AD9C2A85A69
+1225142F2539C2B2AED28766FE59B80CDA8797210B455C33099CB57AB5FA7FED
+1C31D97684EC4AFCCB4C4D60C4F7DB9D865685FDA1E76FF6A5DFB4108D0FC241
+B12B498763CA32F80D6F409BD43905403651A9ED8E96AF0BE8CB1CC8820532AA
+C1546708749FCECD26C5D2A945BAD576F05FEDBF218C6B31141591E19DF929B0
+96859553E674BF96790551776BE307FAD2DB22777C96B9A9C79990BC6E3AD6BC
+7C20FFF0B0FDBDEC1975AF03BF403D9103C602243A075744BFFFFC2024DF2C20
+BB3D29F6DC452EF438AB28077E811EC9EB5D754446CFA84AEDB7DA8EBF4BD9A0
+3646589848D03478BAD908E2D4C57DDCB79A4FBD1AB25E6252329E0080AB0D19
+D4A46BA8FBCCDA054202DD292B72C1FCCCAF1DF3D4F4C876B90FF0F8D561F258
+4FCF9DF03CA5AE7CB73F693D2823D2330C5045F3DB1177FCF6C942D283A35641
+78B16DC23E77FBD518B7350267B9586048EFAF77ACC9EB7C997184743AFEBDA2
+F256FA18702A7183A71D155FD8830DDDE49B6F87458F529C89BD1E945EBF1DA7
+1EFDE6B4CF75057ADF17D27DB378976546C566710D03B2961B50FFEF8BB1BFF4
+C05788E35E770F8F6C949F611DA80180414F772E69338BFA2C91F6C2145A706E
+32005A67C14E81AEDDCC608D976DC9D48D965DDF9A9E49FC698B6978DE5A8272
+4EBDBD28D88F2E6213C5CCB8DE3C41C83D38DE92355914111692A23B79EB6DDD
+E77E007AFDA2E05A25899E4DCB623000FE379C01287643A4CAE92766333023C9
+3421919877F8560496B5358A059205B6B6D1BC4583D5AFF288596F5147F10063
+A06FA6B05B7DB4586975C91F0056E5FF02B91FFB592EE7F0DF7D9550C6803A75
+8D67460C8B03D77307B8E78302B763ECE3B6C4FE27B67AC8457E2F8DF4D200D3
+9B16611B64E2CD331B8F305CC4A2539C505E59D74CCB52A0377DFB314E742818
+AFD337E5D63451CC1977C27812F2769CC962EBDE87872EB976B10F0FA39ABC9A
+571E179A2E483F6195EFD04C67D8F901513945D7768398D5D7478E0897B11DDB
+1EC1E2CF588003F5B607398D8D1D9A72D5E6BA532E88CC0465B8A360801932C6
+8F369F408FB349941BB008B44BAFF709F68F9E2449889E1584A5D2060C337BA7
+AA37BDB8E5F2BD43FED0FB1872DFFDD3C31DEF34450FB51BB82105805C42D8A3
+1F4BBA3D13D7F54B830C4E5F4E273DE222E42AE811CC33458D7B7FE64E4C9737
+47DDF60CB4D69373762FBABF14C823A4AB38C84869C25B5467A427FC6DEEAFA4
+A71F39A4395D774818C0CE55938B9964074E74D6269D08A53AEDE785D4534604
+DF78B7FB9508ED6496BA8ACE6B300818BD98F8F608CC2B5F059999E39EA90DE3
+800A785BBAEE0321A82AE8B961FDA35E7847324546E90FCF4AB8D8E8DAAC0D0D
+B097D610511BF1397B0092EE04A4FC63B3780AE89F9985D8A88AE771480E2954
+EDA2E11E90EBCFFCAF67AD39F4B30A07883424B87D8173167F7BD687BD56868E
+874466ECD90952640A5500FB8A6D9B0CBB4CB8D3D8D024BBB350E280D9E7C030
+8F696EC68212BFB9F011D4D488047C2C1CC1148BD12D42DCC1502544EC1FFF1C
+800718511EE52FD767C7D0A22B029F4FF65C793106B074534B6D1BCBBB3B2C3C
+7549844A1B650C8C75841A60715BD200FDC87E307E8560BAE1FC4F0847F3FE75
+AE58F0A450A58359B833BB2294DBE5F4280E25432C75423A8C2DFD44FEE88B48
+462F09E1A2B6C70C18EB90365B83490E7A04019E9EEB5A8C5E58B3A01C8FD097
+BBC859B0A1C8242A7C2B82CD807742109F11DAD2CB5647C63C81F851C2B14795
+E0CEDE0ABDE6707B642C1C4B1F20791571DEC7224C649004575C3E24C6EAAD76
+20CFEDC819AC43646193ACAA5B63B7AF7B1A9729332E52964A987DE0C0D2FA79
+1A96D1EF7BE3B5128FFDB1CCB99CF807D8FD4988E2E500A8C46E2ABA59CC2A7E
+801EF8542FEBB42201D4902E6C048D9A4AD5B6E94C12973A84FB9B3EEC507EB2
+06EC66901F9D6611C8F8CA1799DB484DD6F5BEE0EEE8FB1C3CC126177773759B
+2111037691278483BED2535C9CDFF72F7E021FF9D8B3B1A0C551996EE303BE7D
+5C46941EB329CA3C9B697502A6AC8A31828594C245B97DD5ADFE11CE9EA8D0C7
+9C8CEF26DC2E0BA66448A48C14AB1847DAC1B280A45CDBB22566F4BFA55DAFFD
+2A690EE0E3945B3E1A681D567442F9C97E69DF75E02226FEB227DDC03AC61325
+BD610D5AA573FF089B750EA0CE8A40F85CCE600870DF84F8C62B929A87BC6E05
+606D135A4964617A3CCABF68DA95C06945370A99A717B01F58E015E37E61618E
+AC70989C4F9AC115144394ABCEEA424A92EBC1E7EFD8A192CF4F0A10AA6E46F6
+EC1B6C43B0A775B10B0FEAAE02BFAE9C6DB22C3E962F1B5C7973CA9ACE819DCB
+049FF86A25A8E82AC985F5F5292EC815FE136DDA92F925E2CE07DF5FB7676E7B
+4C69FB443DF2EE5B66E740D4FC512AA688638CA3B3FFA24A33523D8363E9B70C
+F10A460A87CAD9CFE89A387A4452EA7330FAD5DEFA019C6C8ABC8A125EC2809A
+555BF63067F8883CE40A5F1FABF7E3C9E851C097401CE2AC81070D11B0898349
+030C9E0870B2660EC8FF9432F8189940CC98EB41E462675E7FB51FB3FD4170D0
+7082D61DE12AC74AFFF649981F54AEC4E19F5EA6AEEFD49F64DCA9EDC4BE766A
+6D10E707F824817F9719696682A365FCF6AD757C3C9E49600F7A545B1762E062
+1A68204E542F97FA1175E3C783CBD94E04FC9940BEB21C5D44FB8D54DAD2BA1A
+DE36763C370B130AE75B1775CD356D07B0D62195BC5590B27216DCA74DD58B8C
+E54623200578CE733126174E81064C8D23AD976E3E8852ABCED7DB7AAC1FE718
+A8F21683BA14A3631982AC240B4928C144F8D85D1CAF20FF1CDC26D7C5862E99
+E8E95F5A718140D07684F7C64B985C8A09A46925C63256D6FD52B9B8B281949C
+0E80954D268ACD63CC83771DCDF145DCE797FCC032C3DE1C800BBCF7888C47DA
+74CA25D3728E656B6D8FD74D49EB9A6D7DACB2248A246E8E554D8557F5D3D084
+B324123B3B73D8ABBAF1723B65B1245D66F0BAB39178B78AD9AFC0B5FDC30F79
+B93E93D6866C2C25061D715F9A76E0738E34D4BF913B7E4F32673767AE33C2D9
+4A40BB55AAC77651BB765285CFBF741D107CA559BD7584E0E0550E7CE08FE176
+46A41DD674DC5FA4580A3DA9C240312F90D0FC594B983C3FADA4FFDA483F75B1
+1609CB77FB02D446F1059457FCE06B8A5CA3EC0EE3C0BE1F5AE441625A31C835
+79AD3A0E560B3A37721A8A6BD55BDB82ABECA2F242D59A902297BC968FD5BBFC
+F9C26D07A6B9EBFB3E9D1604FD7B959DBDE994CFD70E765C5106C7DE7F413F98
+90BBCB666FE4EAD6ACEB2CAE3A412F0287B44088C24E97CFAB96E18FCEA499D9
+890AD04C419774DF3683D95CC3A67EFFDC717D9094E247AA250DCB6C54BDDEDF
+B4FB572A0B8D49790D5DC10F75DE1421149EECD00177AF315A2CEB014DAA9ABD
+F117C29C4A029C66D8076AF44D24B4FAC9167C2BD692DA0D53D4C551F69B1E16
+60C6709D70E11544C2322989E83EEDE0F7B23654CCF2E2BE5571F9DC1F97FEDA
+3766D62D8DD76D51F8FF9A2C95FA97D72C36F35A4D9B9E1F10FF1451B8A45937
+9C07B6651A171F259F5932457EFE5FA6A760696F56A4135E9947F36557B3FC24
+4C5F534C8FEA30F2F8AC526E5F69C12C2972FBB448E79CD3E2F326EEA2E796A4
+0635A5DB40D18E4095F7DD966C71B9A60A322AD0DB0A2A9AF24BF04B08224ADA
+32E394F0165EC9752E7395EF268755888FB73572B1B74A60C7305DAAFDD9F281
+11425CBE9D25DE6573AB27EF3099D51A85DF5EF4C9BE135FA380E945A8D32E35
+3F37E378AC231C48F01BE161A1532FADC9A9AEE85C457EF6BA291DA53EE915A4
+208A681520E770D04CBD5EB0159711A141BED8C410583689BB5760FF00385D89
+656753137F77FAE1ACF3AD77A13EB3136B7F1A16D9D5C33648CCDE23704C4F87
+ADE05DF8CA690B95D66EBDD3F6D05494BB6CB7E67AB22418124E2C8F512B64E7
+07FEA1132401AC327C3413B36B36433C2F40BCB656EB15DCD30BD886CFC46745
+E13F83C491B125848620FADDB360F1CC30F25BA7CE242ED619F8F385898567BF
+EF84D301D215E4D508B50A25D4AC9343C947A8BEC153F9470B5B6AA29D2C0391
+535B58F6ACEABA8B5C3B622F992498341C1CF3309FD79C181515F015F46615ED
+2F2C1FCAAB740C411DF3F0FCB4EDD2ED62C5EE15BBA256C1E95165A1420E70CA
+06B1E41773201B36262DB83A2836BCA7E957ADC940579A916EBECDFA7A677375
+18BA68A70882BACDBF795B95684DF840906409FA57EBA076BFBF1828505C1245
+0AD3B405E2DB8F45C11F9183D58A08570638D95F746DD4849961CDB3D48447C6
+B8023594D21007D5CD223602212F6D8DF8A41540AE32949CDCAD1B27A798E25D
+8DDC05BD296F8229AA69FA8B9460D2C2F5630E77EFA90A212DD6910A5B855E02
+86893291441DD506C58CD89927417B077890DC1FF3ADDD4CED8EA9F1BA0EAF98
+873BC628A7AD36349549A217E452D3368E8530795BB77F1E756FCDE2040C5F9E
+DCA72CD0D807CA1FD7B607C53B5FED45CCA47DAEDC6927600C1315D2C57D0DCA
+6CE850A080CA0B2530D8B33D1424B884BCE550B6AA8BA4EFE6A65656D1C02547
+454E34A790CFC21D3BA6965DFD0B87DF98DDF41D15E5856A3AC663B9369D611A
+E2ED221BB8731D2090E2DFAD0CC282903636766D86CE859601DCFAF54662E280
+8347A3FDB3B37F0FE340606EEE2B8E7C93B41C2DE4E845C9952347A8D1A0F194
+4B7E637C48BF2A479844E7BDABA3261EA98B159DB0BED746910D4785ED3287C1
+0F46EFDB4C813E895C5C60B111D2343793F673C57FA42DA5CB401FA1682CE5C3
+4AA9E05901B57004078742A8CCBA353AE845716CF0D5ABA5C255C90408D322D9
+F21F14DCFC28639AF0A884A38C93A2B54402A7161B059608F8A10DE341A684CE
+6D225C8A715014413B07104C029F63C8B2A788FA68E6DCA985CE5186EF75C806
+10A23B0B39FDB386CB0B5B1FA847972B79E0645B878F211EEA2A14B4F245C319
+DFD827702307C47117AB2AF7FB207354DE283352C29010241B4F57890314C0FC
+9FF918034F77D93F2EECABBE5EE2F421261FA34EF7B40E955EEE55ABA18CD355
+27A99A522FCFBD1D9BEF3BF40C7BA74CAF58ACDD01148345D4E109D6336FABD7
+4BE82B89759A486687EF3D8735422708FE0F80DD1034CA9740B85CEA71A2D9D0
+D0084CDBFDC99E0219A18C69BEFD1DCFFF6B5D97263D1A331AE0DA2A56A4C5D3
+FBAC1DB7289A34157D25A8C41FDA4C3A66BFBE90EA5F6371E94D69427FA0016E
+C2E9DC906DBE094A05B35546F28B5DD2BB668AF85F96D00A5556A6DD51E5FD54
+F7F77B6BD39FE1A99FC26B0085E1EDD50912E1F1585DE9C7233942B0AC4E2504
+F5841A727459F80434CEDDD3CF5156B36BE6F4B09AAAECF546B1F6CED3601D94
+28EA6E3EF0456C7398A78380214BA07B7F73091BA85969B07F4EA13F2B294B40
+56F684D834681053266D8466ED3EDAB77E4F93A5BA9F32D8D4DAA968B4C41EDD
+317284A980A3ABDE9FC7F153C8BC5C073A47D2BF75B2F724E90E520123A413F7
+80B4CF9BFE0C5BB596331D7E39505582AB6519E34EED28A009B66F8CFAD3E204
+81D12C62A5FDC8DA03D1F8E5301DC6894C4CBD3CEBAAC76CEDB31566FD7545F6
+6A68D2441AB9AB9BD353B51DCEED28DBC90352ABA3D249A05C00C299928AE6E8
+886E8A5DC68D75B642E78D8E16A1B8BBF871381516D1835421533A49FE4EA891
+512FE6949FBBE31256DF1348C3EAE50FC45A865E5725F1ED7D5F50D2A5EF1C1F
+5D0E4E86E362C7060D8A3DB71D46B224D5B5868F34084BD408C7EECA270DCBA2
+DB170405493E82AD7E8B31708EF61421EC37DCA5871E39D7FA29E43F6FA45DB4
+68C07CDE5F7549E07A185B095453346351D974462340F64FF04EE1C037871B81
+FC1E8B6BA4F6CB9E486B8A7DB086A59FA4AFE5C74460F08A9163EA3ACD1380FC
+A7AF2CA22D2D4CF17FF9870E206CFFD0C5CB90BC4626C74B983536EA9E31F0BB
+7B3E9AB8FEC135687C0C1B69AD5134C6CD428DFB9FC8C56829F9D828693DD3AC
+9FD5C72378B33696BA7BBE392CE047E06114DE1CD7C9AC966013C65514EB2D60
+6349F094D44C1D248F4BA48DA7C3B8ADBFF14DCEED6B1E8C704464A7045E467F
+5E3A7756E2B7971332DE09A2178F46323B8D3C3904FC2814E3E2A21D8BEC6CD6
+C5383201CBE12ECA055417675F8BA96C4E9A799679743E5D012DA2B570CCB7B9
+0BD0520CB34297F64F93B674B7A5D2116B2138B75E7DA175F75F7139296537B0
+1D9595B65CA7AF585CEBE5B5DE485854D9F67DC07D0F6091D98EAF57EC3F8656
+ADEE982416918DAB7B6B7F611F7DF87C9C77755611E91A0A309F05961FD6A43F
+4DB6F0714BB448A20DC223DF13CC87DF53220A292F64285A12C8FD0AC7E3D962
+7BBA836968A2EC6BB70B5667A1DD8E218696E105998434E7CD32D31235E0B44F
+7A7D65A8FD4D2846F0E36DE450160B7FF81C63C2310372B91DE5D10DF21CE43D
+E9D8C3911F0AD72D28110E3D27B71B531FBB6FCF9C1A9B91F84AAF4DFCB2631D
+3C2B53E79AB919D5D99BA18B2614A0C8B2D161BB42795B06E53CE266EAEC37A4
+B562A6B036B397227D35AFF001CDAC7107DA54B1CE20DB7624E0EEC86A02EDB2
+B2A5B84018DDD021D05B28C4BB97306C73473CA4C28C8AF6BF2CE161D0E6DE5D
+F6F249335C2E34FAA98420B7D8189A00F20910BC96626BA663F4B571B565EEE3
+9A8CAB423E3E17A3F95DFD08F690363986129799E2DC1E7289C50DD3651BA8E2
+F53689FFC4B02C015F34CFA75555FE47E644F44CE9BCFDCC29DCE7E7DC7208B5
+CC3404C23D893B343E7291A10909F9B5FE3D25AD1FB79E82F837DB3AF819792B
+4617085B18A6B217954AE93730AEA3FF8D6C6E5579529C02D6DD393AE864285C
+1C8E4F8BBB5E958A030B897C43754839029BA98C735A65C55933A0C7983AD8DB
+D3B012BB2FD73038960FE1B9E350FAF7E3471288665F360383A15D95350B174C
+288E5B4A2F1ACEDB40505A1838444BC3ECBE6B1168B1F7387BAE186C97A06208
+B3A1A738CFEFFA3F65AB9F79B8C8AFC39438B5801BA60DD8C3F2742D902FBF1C
+A8074228728D9D58F7FC064EFA50047B7A1C6C88459E0291636F4301E3036309
+78DDF621FA5792483CF8A16306759C464ECBD54421EBB846895DD87183DEA62E
+68273455B5FCD7FC6422C8197DEFDCE70F9C115CA0C91D3C77F7C9C36E830047
+7590DE3316BE60FB421E6117D2F8672142805A013FAB0466C2CABAA7D16E972F
+D1AD0B8BA1F55CCC039B54050160724ECACC8408AD8C51C9BFC2E9268C110A3F
+FEC30ABA268CA1FC27F64EF99DD11524AFFD45A8AE403B825A08692DE234AEEF
+26AFBD9E79441D77B945FCDC5A431214D4A96BD49BD129C158110A6E2BC07A86
+E32E552BD34F1AE95A393491783771115DDC38979BC54A63F3E3FFCF033990AE
+4A9DD1A72CDC770805906CA92828EAA19D03A0EBCABE364A22F890F594068825
+EA2E6E3040314066813ADED10C18A2A9B0BE5CAA131B690EEA54DA92A25E9B5F
+2A2781FBD1BB43DDDFB3FEB28BD448D0E2C799A063A72E9BF3850E2B418BFA5C
+8B3A81EE6A2457AACBC6CFF8AC361816C238259E3F58B85FB88B1E36AD752D13
+5CF751ABDA364A09648DCA8E213C1AC42190D511CC94F2C1BB6481DC1EAAF88D
+90ADA407872803CE33AFEC63DFD75BF25D8ED8521BA47B4D434891C5FE4C2659
+9AA517D3D5AC7FDE576BB42B2DAD5280D64764AE205A33BC84EAFFAF69AEFCB1
+188BA530C45B2BF97BCE61638429ABC6391D95A8B04006F4B01D8D01A4718976
+005A5EEF09DC4DE93298F0CC4FDDB8C110C3F3D9BB84626777CFEB7EB1AC1C36
+156D7F2B251DA2F0EACC39AE291919B427A075FE6C6A65A4A3836C3D459A9252
+99014F5E7033339393E500D28B832EFDA4B0A9850AB252B3C9EE7ACB3B4CA00A
+5598F2609D5625944F7ACD52C51FEC9F64D6F32E38E3BC252BE7AD555D016EA9
+28E77FA9D7C73988C580EA283F82E5297F2F6798AF229B24C8E72F1D1AD0D18A
+C09E78E299A4C09C978B4898D7680FC3AB917E6CFEC4911225B2EAA9A116F15F
+392FE72F3E1AF52C67A0DD488B2443844AFA127E78E92416ED5A72D61E92B9C4
+F604C63A69CD33237108D1EC3D62CE43404FDA456542C1C21CF0C0646D67F879
+1B1D53BE8D243862C3A86B9F3AA44D327BC5FEDCFDA066153B87EE4FF6F177FC
+39711E874CBF31A5984E971F86240F7F4A60C2C81A07E972D7DBD34204F0653D
+DA8DC7284A4CBDB19BC6A1CB75E9786568144833682DE7E107D639DE7B293E0E
+F08F418C970FEA42075F93C77FAED3DE64B1FD30564937013D36F7980139F968
+06D02F6481577A41414FF4FC9B1C99AAD2B3E9013F6AE7E96F782F3FAB4FB272
+FCC783CA282B79E88608409BBF8AA3DCFAEE4AA0A4F4E143D8D62175D2CC25EF
+21CC2E6F0EFAFAE0BE6BE6583B624F35994BB75A886883C4429A154E15315068
+22CEA98F0E9346E1FB0A5C0BC2F5F08547F366367C6AEAF0FA2171FBCDE51EB6
+DC13D8E07798020CF02AE39E860B1E7B5A957214F2E88FB51615FF10CB0FDBDC
+4DD3F7E32E4B7F3ED59A15F279C678ACD0DF52FB6A376453124FB9E911941496
+A1C95943D464B633EC8F8003182D4E3705D4C3C12D2D8A6D2E85EBFC38507CEA
+4CBBC55843A9687E012894D9486F76EC3455B92702BE56E68B47AB3EAE17FE59
+83789C8714CF93C38AE2D10F71EAE95E275A007073B4495329DF0E6F625FEF0C
+8FE78B98F219D7428EAA2BE973612F80A0EF2577FAF84CD3D33CCC9B8C9E2E46
+1A3884A6D69A044DA7AC615E7756880D9F91ECF9CF24F64F15AD989CF31AA443
+8AE71ED33BABE92A2CEB2EE12037AEEC7DFEDB8ADB45ABC1E85BB021153F4977
+DC71F5C38099B9D7AA63D8569FE519B523843FB8241F80113C6498ECE38D92A8
+5199F8A0BDA219D9CD946D41E0BCA398B63442FBDF3548C7B0F46AD4DABF54FB
+D0B0835EA5341476510BF67481C40FF5CDC918A128AAE12C8F0D02B1F058A283
+7E5A09279F8B9E0F0E0549386C3C6DABDB173D30E9D3B07EDE6A7D406CFAE95C
+AE2FF542AB24BF4E96CB7097C38A5DD350FE9FED91CD5F6316B64BEB6D4AD015
+DB75B25AB2280FA089FED6A5CB57A24E404CC12951B2746345977A58CD25C32D
+FF9474A3EB149536C07620C74122F5F54FE24735B35A34478A5D721F15C1BB43
+BD57FB09175F2F24997BED9DF769507F0BB9B87D8396C8CED5DBD4F175789AA2
+511FF8E569F3F2DBF7C0EEDBD447E20EBB09ED273DF7632720672C19204D9813
+C965B05D0C11EEADD78B291A5D8F3CE48302BB4DEEC92C5D679F1D23696F4832
+A0064CF3462EC8D6AC28980641DCB2681ECE09EF60A62BA321260BAF201FEC58
+CCFB371B9041BB950AE000B329E877A54B4B83F52E98D26C531556D53E0806B2
+37CC3AE746B108D927DBC45ED2123D46BC46E0772810A4EE3E8FC8809372493C
+22D7991EB737BF28C6D7887F74D344A26E79F6D1156952A377B9AC0B66211173
+7AABE45A309A546406ABDBFA7431E1CCBDF11214F77D10D352B54CE23B14D88A
+688CEBAA621A014EFD89D5B905D39CD2BD85D6804141A58A2C38E861963CFF5D
+C7BB188E879A541A302C3A4D99BF2B1778398ACE1DC335BAFD7D7643DACB1E3B
+781BE43BFCBA8BBEC6BF280F76DB418D4FBE3C36A2F9ECDEAC32E3602B01D7EC
+47CBF2427EFD8EBB5E4F7CC16884A67C8ACEDFD3397CA8C2943FB0F5050DE719
+5F45D15DB1AF12BEC29ED5DA5A987B384D2EC7B432C6BDB3F6D22D4A4FECCA71
+CD1ABA35626C274AF44F748DD9DA3763E6E1BD19A7C07822DA6211193DBB375E
+AEE59CD426FC9F42D569E75164AEAAE43D2940E18BE46C23FE5722F51D4F42A4
+1F560EF7A01B4F2EBBF2A61FAEE03CFA912E644A7BC7BEEBC5724415BA43C322
+70705C5159EDF059AC6CF2DC896EBC3F35C3DD5A29DB44CB86E4F6BE9670AF74
+6319337435A00688940B3C24475870D2F46F91379E5F3CEEF23073E44C02BC51
+905FFB8E529521DA74FC123C31F4745999BF51D38B0AA7CAF9C169455CDD05AB
+0913159BB7E28F6D0106B50E32CCD0340A2E41B2C66ED74DD370AB5E0EB5B0CB
+93A07EB9182ECC683E6503832680CF2914D054D3BB768A3F0E3693F5402B120F
+C0941273A0E3D6E620A90B94E186097965E5B2EA44D0F8CE8CF0CF290AD96228
+A26E6CA3CDD35B919FAE5798E55493640EDEB67FACBEE713A0EE055D9A18C3EB
+9D90E7869E36B749F58C0B5AE89DA856DEA4122B05A35A863FB6BB74AFAAA182
+052AB4D8F033F9F800200B547F736D32018BB4B64157D12C8268FB2C6E9C60ED
+C3902382BAF7E12A562048E9B28563E70D4A52121B40AC2171592A710A9EA19D
+1A0FA11A0E9A6FCE9FD2BCD8CA488F65B45EBD61F17EB8C6213B3077B6A9295F
+B184234F6B37C4760BEDFE16A31CDEB901480A556186CDA8F4A623F8352E29AB
+9FC29DA356817866C11AB07202AB6C2034D8E463E026CF59FEC872BEB71E64DB
+0A79022780C38ED86FC17A2EB552E9D6C23C55F205A05E4E198F560F7C1A277B
+3B4EFA96655F8A5E9D8E7E257EE59C734445E864598A74B7F6400E05EB0264FD
+DC3AF61560ACAF131DD490B2FE9DA7DC956182B5CDCC177F3CB48FB6E7D8D47F
+F984C53A1104D657BDC7723E995FF55B87FEC6A0DF25D87987BBEBFFFDD9E6AC
+A945B06553668DDEF15CB7298E4BE637FAD0AF624171EF49345464A266CF2BE1
+544588BAC063DACDD4691111ED9C754A4E0D8AE88AD4DD3100DB9C0C9E1BA676
+61AC53AB391E9C9BCD240C9A9D565DB67D0169B90C629CD46600687E93A544F2
+0A67B9E084D40B657F259F1C500D7D05CE3F059DB9084B8C9B492C4908E38199
+9F6E1E625D7FC73505B47D4335A7ABDDA2F196C1AE0C41870B7A38C09644641E
+6EE2686B487D9CE20239EBF677CFDF215190EE0A1CB439A13AA4CEAD30A4FB31
+25B9039B7AFEA7345D3DD1F321B61D4D52FD3ED5642F98DB54A848F838E340E1
+0490E93101C49B734294D14E714ED2A7B0CD79CEC04AE6B69EC188C252B98E00
+DECF96DAF3A8614294968F426CA0F5DD945EFEE6449E2EBBDF124452AD854E3E
+B58FFCF836944A34B90540073A745658B426CF444B36F335DC2CDC9866F906CB
+E4CDA4A7A3334D764CB27B2B4CDF8EF5F466ED44DD6C6CFF642F252B24A267B8
+B8788E1272EB5DE03CDD7D02ABDEDCD22A18441DBDDFC77284E88AE70E1521F4
+7C49CEC8C25BEA8EF8C160B9A6C75E8B12D9DDC391E60CF7D6CF02EECD7630DD
+24393C4DA80B1F3EB35CFCCEE03675514A9E110946E65B123E19427D8FFE99D4
+19E440CCA4BD1834CBBA0178F9C98BC97F5C7FE1DB69DA5946B0464E9E333E75
+8F0E46DDD9D7BC7A8939463AF2EE83B387F14A3CF49F80F62BF8667E23F702B0
+3E6F507420BF6EB2C5C37BA7B24332BE2A34F3274184F544311BD53ED0560BBC
+3991A25AD90C14181A274F84CA7DD21741167F2B38A54C80B61DD740A4F6384D
+42695C64DE34E0073E390550599C26B6DCB8557D09C1287CB90575993AF500E4
+CD3F8EAB3B908A3EF3D49B0DDCE08490BCFDAA4CA491F7EB9177400487C58FC2
+1EA33E22D11600F2E752738BE59936B8E911BD8820D4F7F687667B32CE884EA3
+7569A82B0C53A3213848D6C973B9C3293FF022491E40F0A5BEFA80DB18531FC6
+7CB7A19B7A7E46AB761618BE20FC4742E7BE854071C3F7BB7F6F23DA29B0FC27
+9348A6E9D29B8949C1085AE229902A95A672DB5410DD239A4DE9B2A7B2A499D8
+4B3D82EAF8A8BE17151086314C9F07BBF1E0443BC59F82126658057BED615C69
+7D23057253F8561D11C6270BE79912E6240BA5E6DB8CD7D7E86103BF5068DB42
+6D1F769CBBF97DFF3BC3F5F0E64F133D0F3D4DBBC55B7EA5641F0D8F2F7B7467
+7F1211238EC7062C69951E0A25A77A7E7FA45660182BCB1B0EC3950735C1C539
+708A37BE3B4D617FC2D7C4D5BED4E1103D70923AD70FB028E23C11046DD5141D
+CE3BB80A706F2D66068A8B8CDAF22CBE1CE71925825A10829193B8F1C6F5675B
+5311B57E876E70CDD11D1212DE8833C5F44E07701C7E2E63605AEF8BD30F81C1
+1B88B6EDCB47B6DCDF3E466FEC04680A83250145C0ADFF58CED2EF0006371568
+854831945C23BE79C2655E512C967DD3924EA56B8F99368F32379924FFE75680
+C8C31A75B2733359DA01FEA8634B5396A3AD53601FEB7B897BF927812A2F5614
+7C65D725DD636C20EA6E69F3214D37E461605D6C42C024F69201C8BF91B3BE00
+75D73471A2A6BC927F2F91A183AEBC0CA04A2ABF291A0F10DE90EBD6C34EAB53
+F31F148FC4EFB7C68AAA772414D9C114088476B504886D3FDBBB664E56536621
+639060388A3E98431C06F9CED067AB46695486E2C88F2BDF55D7ACC588EB7F49
+02630F2A0852C8243B9D2ECB518BC69C547764D612A60EEAD68F3C06AD2E221B
+CA8C4F56FC8ED071C5F074F90809A344F58D01CB89CC467BB90F4C400D11E515
+032D783C341BEDD3B1C08125196731805033B3769DBA1A62478E0224FD81C7A4
+0458E97E0E4620371EF311E740825B3A499A1C2FEEB4CB0644526E66FABA78E1
+AB93208CB5BF6E78D32331F55DC98C11A1F56592CF133BD05C8E4AF0AB80F1B4
+BA021BE93BA047B7EEDD39EF35441D2EE71F0CEADE691DBD0077A34AAA5BA616
+69410DD5A4D71DBD12EE5981C06A14CCE062ECFAC63C37DF155F9D5E7BFED397
+E0B51DBAECA7347F70E7B68157B0D2615C661F5F791C9439A934EB2C60C53EF9
+9A300F2531FE810C143DE75C50222CF7A540A9F2E443BC5474A80FF59339E6A9
+E90C6386C7B54A266FCE858121DA7F4BF33D46844E0A8CB60A002B204AEFCC42
+2410ECA4EA45869CA0956607156FE879ECA490A6E839FB735E20F11FDBC24CAE
+B300F6771E7DCBCEFB3AC249E0B521946438E56FEF6050289B40A9B3FDDB659D
+721704D110DE1FABB9851A703B34ACD49516B00C44EB17C30A8BE7CA8442FFE4
+3FDB259233CC0468E9F3548D4086A955CC1854B9D12D42E799659BA8381BDD7D
+FA07D1F08701D584701AD888F86D86D7F11A1AAA21A92CE24C125CEA937C3C4C
+923422498D766E050E0E75AFAD1DBCC9CF3B812FAA5C9CCD2326FB8A0C171FE9
+1637A15145FFD0A10085BBD051A92E5625817CB6DFC30880604BA6E124F4DD80
+2DE36A68F0C5D015B8E58B5EF991DD9D41FD823BE3652515A75959F5A991C5E5
+BA8E0649E15F231ED5C5B02E2EE1B5A478DE7DFDFFE1A604F3AA191B6A03ED1C
+7AC466B8B0BAC7154165273202DAB004F72CCB18192EA9AE584F1F19DB8DF12D
+5A6D9BED63F0E1155ED35B92A262D8851BE35570F5FA295AD30B28585F680306
+0791BA62FB631F7CBC850FA21D81E471B866F2037AD63E055953D2901AD88826
+854440E87D587F49854812962EC7C0B97DB8997C8EE0DE9C79F93D2BCFF8ED3A
+309F3D204B86DF1643C49FBD97EB6D3B0AA2B216CA0A9FD37D3A6F77C8E6AC98
+FA4C1A31BE6346E6E44FFF1B490C6C15049894F660E477FBB9501263D6A71F82
+E113AAB2D88A921FE0B40794C6C99C05DBB0822440B269CA52813CC324287120
+97137CDB0CE241CF06C43BAC889E4830896178FCBF881D497D4CB81E1882F252
+6AB05648DD5D95ECDB86704A85968EE36D99D24955D3535B28E65D10646FD7C7
+6F3C73ECA74ADA8EF43DF9D8187343FD240508664F0F4CC5AD394597F37B99B5
+1FC55E4045EA9139DE57F5FC345DDFD75E7F103FBB724DE84D8F2F21D816514B
+EECFE2166F544287ADE9F591A2244EA4332C2BEF8C37CBE5BD34ACDF480C59E4
+DD8970AE26B0DE389BD7535DEF80318F3F60C0199AD6024EE6B8BB0276BD969A
+783F9C3FAB57EFBD352B324BB8B36F818AE14338CF0D91B72590DC58ECCC1E61
+87A2D943C9A50396E2B334A36378BB3494E850111A84468DAB82744883DDBC44
+A1BE11334AB52EBCB2B1FBA36D96A97E5AE9C8E57E7FAE936DA892CF999C02B5
+95D6A2FFCF12CF643C435A6FE3E0D80C9A48B2971484233F8CDC79A6835DE776
+89BC0458C78B376401CB78509AC77BEC9656968B9F0B8E123CDE9B7E88B09F96
+E9E89ED4760EBE0ACCA2A6559002524B5519505A3EC5F905712989736B5AFAB9
+372A6384303FB43A02F8AC415BCEF9DC4ADB4AF280E08751A1FB7A804C1331AB
+D2C8A7AF8825A46D70D74E3ADCE5D752A5037EB630E745A329E29F51B6D5FB23
+C402E998CE580EE780DB5AED32832EA7B03668D0341B03B5E50E501A77278389
+A1529ADFC3313B8703E3B1DC34024D68F2EF91D58FEF9F50113B5AB5F6A38DED
+AAE24D20A5156E6D6B7090FAFE5AC41BF075D0E2A18119C3B9F62753AA121B6D
+4375A1024CA1E013440024BCF744FA30C4618C01568AC03C166407334C052EF6
+5AB4F37068E5D7D219413408B55F4DD41E827106CB1577EF12CADF21B0AE096C
+26399F9B3261B793E5165B35B93C7A0FB0DB9E19F7F8C255674EB64FC319D547
+1528F3E529510FEF4B949EAEC2B8BA1D45BCDA7478A3BD684D8EE00FC62B477B
+97A5007D99A4B14E080450BC08E62D80A406D6049E981DBD5DD2A9EDFE12F65D
+5B159F468862F9780DEF12CC9069225BFDCC9045F6F73A0AAF103448A076E3C7
+5A9415B0B8153DB4D7899FCCFDB3096CBBBC66F2787FC8521743F2596CFF4DD1
+1460A98705EC377588E77FD757C13DE2C5AFB1C9CDF5A9EE71E0334B0924B402
+B59D2185F08264356F4CF388D77C7F62234133A1D16085B357702298F0F6A253
+6D4248D29667E5B8EF31E991B42065F7E48658EA33F89240754186DEAD4C1D50
+5B983A6BBA42B9D70076897DBCAD22F924D55EADD270A7BD8450A4571CF092C6
+6F2150733DD7DDEF2095EE1F7B503C2A1E1FB3DE3254A4030A188E5AE4F309F3
+C3DB5235F55D128A6CA2BF8277F7F78129B057BC6E4EFDA79A097CAAAD25B712
+BFAE1193168F1A31BEDF3D07B733806FBC04543C73F506A8D137C722C47D9867
+AB220F99B2889BA49F990A932CCCAD8A0AEE05D13C625F539AE40E08EC0B8905
+45143BF51E92AB3191369F66604CF5A8E3608DFBFF28D1CBE2EA332E4616B8A5
+BFDF99A0F2188515148A2642547FBD837AD94A9EB63B9452FC714C83B5FEC391
+9AE7F79918458FDC90286E32FDB8B3D62787DA1F842466E306B849C9F16118CD
+B4F9A49D7BC027F941EF553C98CBB8178FC70334DC01640790D28A0A50FE9B10
+60018A930F231FE699BA8AC6EA3EF567B2AA462BAECE9A44B23A898D346EB7D0
+44022A11CFC50AAB2F3F54FE76F9CBE7E196B3EBA06C2222CD7F35A410A40E3B
+4E610FAC688CFB9EF5BF8DB068C4E52D5CBAC9637835C3DF3B36D00647C20A33
+D9AA954658D804EA6F833484187C7CD7A0256577FF7ADF9B8A43990EB8B3E82B
+D0C548D1AEECF7DB7B7DCA6B95E1AEB3F000598353FE8699026BC5624786DE3F
+A76D00CFD5B01DF639F2DD45C25091ADE1C86D52605E6746DF888DA05776C57E
+6E9527BD77C19573FDA86B38B75F650B23AAE3366C12D76B206E8865B2C5B3E0
+AA14E4F5177648626E7D383376BB203A4759C213BFE13AC26E34EBDC2D270E19
+2F4B54C1AD2970B8E2D98CEE84606D64C0CF19D7D4F08753D9B23093DD9F9641
+BB4064D2B4C7D0C1FA3E46ABC3095A4ED55A967646615CEFBBADE1254ECE0C91
+E783330727A8E28C0DEDE751369EE1E732806FFB0CBB1F1CA63AE49FF9DC17C2
+1702E2E75CF2B93C991EE82B635A362829D0D11733F89443F602AEDAF12391B7
+0133CD6C104FD7083F58894D269366222A127C25DFE29D934F72502274A1290F
+9D9DD6896E18157AABE670E482F6E02A646E6605E6D30FCCA15FEA0D496EF19C
+5559180A369189FD1D7E2F6918816D608092A138B34570A796B53F730E376D27
+605F5FEEBB0F36D1B1467D39A2D45AB5A297E92B6C6F2083E51FC933F5AB76E4
+A7434ACADB103C75CD4852D5CC7D101231036B240CEAEF30AA611A7003000ED8
+EE51D8668F3BEC852BA813B863111B95E6302CC213058749EC0D561B747FFDEE
+415BB66F819281E60D688ECE2C51F84989A49832DA326F36A20EB118FF530CDC
+4A332BA4F4C5329EF09D2B27B09D6A9F528F156ADC1F0ADF3F2A2B4715903E29
+6C9E9DAC22AC38F70B4E14EBA3F2E126527AF1D5E38E39F9BD601492B018FA73
+7591AAF7848CE01A35EBF654AD7D5F70BF0372F747EBBF55EC96ECFDD69507B4
+6B66E610281C71D408C680B914D522B43DF0173CFEC0F686E3D66227047A9E9A
+A884F6F7FFA624316FEEDF90DD3079969F6A9D96107D158743C1DB86D2A0355D
+34739B660D94EE61BBE52EC11ED84FFECAC5EC06910DFBBC7F6EB7AE3F117535
+B64F45507CBE6EE035268327F31F9D01A0DC853E0A8FACD0FF3E4746AACFAD40
+5FDBE45325E085463E3B5C48D7238A9B642F3234AF975352448563F8626E8200
+996A97DCD0F83128EEFD4528862C232D909C771C3B9CDD316BBD025613
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+%%EndFont
+%%BeginFont: cmcsc10
+% T1FMT-V2.0, Copyright (c) 1993,1994, Basil K. Malyshev. All rights reserved.
+12 dict begin
+/FontInfo 13 dict dup begin
+ /version (1.1/12-Nov-94) readonly def
+ /Notice (Copyright \(C\) 1994, Basil K. Malyshev. All Rights Reserved.\012BaKoMa Fonts Collection, Level-B.) readonly def
+ /FullName (cmcsc10) readonly def
+ /FamilyName (cmcsc10) readonly def
+ /Weight (Regular) readonly def
+ /ItalicAngle  0 def
+ /isFixedPitch  false def
+ /UnderlinePosition  -133 def
+ /UnderlineThickness  20 def
+ /CapHeight  683 def
+ /XHeight  514 def
+ /Ascender  694 def
+ /Descender  -194 def
+end readonly def
+/FontName /cmcsc10 def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedblright put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quoteright put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /quotedblleft put
+dup 93 /bracketright put
+dup 94 /circumflex put
+dup 95 /dotaccent put
+dup 96 /quoteleft put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /endash put
+dup 124 /emdash put
+dup 125 /hungarumlaut put
+dup 126 /tilde put
+dup 160 /space put
+dup 161 /Gamma put
+dup 162 /Delta put
+dup 163 /Theta put
+dup 164 /Lambda put
+dup 165 /Xi put
+dup 166 /Pi put
+dup 167 /Sigma put
+dup 168 /Upsilon put
+dup 169 /Phi put
+dup 170 /Psi put
+dup 173 /Omega put
+dup 174 /arrowup put
+dup 175 /arrowdown put
+dup 176 /quotesingle put
+dup 177 /exclamdown put
+dup 178 /questiondown put
+dup 179 /dotlessi put
+dup 180 /dotlessj put
+dup 181 /grave put
+dup 182 /acute put
+dup 183 /caron put
+dup 184 /breve put
+dup 185 /macron put
+dup 186 /ring put
+dup 187 /cedilla put
+dup 188 /germandbls put
+dup 189 /ae put
+dup 190 /oe put
+dup 191 /oslash put
+dup 192 /AE put
+dup 193 /OE put
+dup 194 /Oslash put
+dup 195 /suppress put
+dup 196 /dieresis put
+dup dup 161 10 getinterval 0 exch putinterval dup dup 173 23 getinterval 10 exch putinterval dup dup 127 exch 196 get put readonly def
+/PaintType  0 def
+/FontType  1 def
+/FontMatrix [0.001 0 0 0.001 0 0] readonly def
+/FontBBox [0 -250 1077 750] readonly def
+/UniqueID  4701554 def
+/StrokeWidth  0 def
+currentdict end
+currentfile eexec
+9B9C0887DB83FB1ECD8335B0BB39CEF0AF64F656FC6E5C230CC9D3A7346AAC7A
+06BD9A40393CA15D3773A21E06B9B4254D3050E90726BBB09120935A8D448CDB
+C799D90205A21291254FA633CC0C2ED88781EF21A5D45B72445C284FA44F8F39
+CF566976075A92E9E2947A6FC93D879C29EB26809ECB4409CBC8666526CCED92
+65DE661A2F8B0A16BE45A9DA17EEAF89B0E023DE2B0373DCAB997D60B7D7DC1B
+4F7E650A2A9F13CA0543F3B080AE33D65F2802B8C5214D5B61835338CC208D61
+05501307FEC48CCF5B84971F31AD8A4F0D23FA9336F6689DC2A56B553F5B2A4C
+407D9378280A95C0045B3F9D8F7CB131CF4AD2EE859810319EED4082B193FB63
+E16EA0D69C0CDB5275814CE04C6558465A99B8CB4BA8BBF2B568FE1A857FA569
+3CD90069E5A446B86F82FBAC48B6C25F332FFF0FAFB04725D227FC28C2031D90
+5095F829EA6F1D8497077F2FC51BE3F59280623EA7A7A961565AA29ED4BA0899
+E22FF1EA9ED97089659AC56818A44A585772405409885F335E48C73A173CBE5D
+52152759C8F30DAFB9E62407BD9AA3E1BD0CF45922AAC1982E7CA503AFDBC369
+2D62F68D07D83728E48C6B20B03890E45C5704A1E39127CF6525C4B951EC968A
+3374ECC8D7AA22C66B5B00BBE6843E1C544AB9E97B4787707080A58921C1928D
+0710C0F6A84CB91045F715CADEDD49CD06B2803654179785E07652E16B5D5347
+8F3393187212A3E98A5D13D77841CC9958AD5E0F96B23CD331659840A36A407D
+D2E7A6E58C08ED171D327E376E1B0A4ED61611F2BD7BB7AE16C36A1DE466E8CF
+69023E818FDC75ADB6BB6584ADBBF8C5632015F42F7E948CCF12A5F28A092035
+D201571888EF8CBFB5EF8AD472767422BB58A773C50505058BEF8E03D6EDF29A
+3A32EA06AB032E65B65571D32FA8992D89D53C8220F05421BE0AF7A63CF828A7
+533CDCA7E445BD866989F908E8BD5C9EBAFC11F109EA1FE0B99B6E755486A034
+036F4A7D0B7167C1D8437F7E6817384A2BA7C492E76C313F168D1CD69268A02B
+493FFC076A52F79D41EF492A59CBA939ECD8418F58F76686E3648342F8D81968
+96419988BCE8A7473D29C44704AF1F54A61185621626B5ECA3D9DC1ABCA4B82E
+8421467F921FF8BCE016A893DC9823E33E774015A09E9DF2685B2597811E73AD
+417166CE24E3D97280546EA2B5A8B53281D40EC512E3D913B57E8A6666918875
+B0CA655AA42838BFAC8BAAEFA380299850C490A109B38B4F462DF9915CFDD4C8
+F4725200960631339DE99F9738D8366E70792A26F07177CA728ADB9FF8090BC4
+4309BF3058308991B3FAC3973C1F1C3B1C19C87A6A1562979939705520F7C977
+7D1ECFE515C9E31C1C6D7F403299CFD8547DF23D2A84AEE11336C362BDC205E8
+6BC7AE696DDB26B324631A831848FC92786C8A81458881C2C732A7683E26AD34
+0141B9DA73EF291762C2F608CD983ADFD59F30A73DB961B7346BBD89730D3031
+3839A4F389B2113EBE554CEBC6F1A4BDA35F2D6042D8470CF5DCFB4F0C3ED526
+D45748AD4BC5220A633B630DD00C64D870632E4CFE4A2FEBEEE69381B0D35CD9
+080EC8CD097706040DD8579BBE9D3736912001CBD48F4F163F4FDC4A83D91441
+0FFA6368FEDBCC957FD46266D2D53C066DDD86698A3BDCFC757B126938B58BE2
+AFEEC58928C85BCAB2670C92B733058038A4E539E9F3BEA9374D6EF35A53007F
+83943AFD91F8DAA041EFF63F01CE340FB0C6BA796FE2ED4DAAB762CC0BC47761
+7E267E09460DB657B2BD4799814630E492F23223D1366923C561C3D0D2ECC1AA
+F298A4B8A384AAB52E55C19AE8D79A918893061EADD1751E3F8248677AFC7BA7
+6513391CBCB6756040B61C68AD1F4F54D372A950EB7286A530292EB17ACBC846
+3517C69AD8A41021401A72E09CAC9868DE0DD1FD2425FAB79D488E95294B58CC
+346A0F8B4DD79BDC32CB28E686589FE9C87A120CB1982DF7F8436D6E9F01C1F4
+71751F33736DB9F50750BADE226432BFD95334492ADB192FDABBD4F38256106D
+34FE08D59AF5DE367F68F6F8AD3E47F274B3713385AE527BF52445A6CF07310A
+A50B99493F05B148559A0B2EF7BD5850A5B1A04D769B0190B933E5834FC93663
+70BD77D73E68F5556B8BA3E7778D161B8B4C4B1887D27C0E9BBE13365FD4FC82
+D6EA2A86E2CB687A3624B8F72AEEDD6EF2EB23DAC77B64B737AC748F8473851A
+081C5CF12A66E5F8A815731EC8662A4C825CDC15BC157693B6057E22A2AA71D3
+83289A9EFE6F9337ED542A3F6AE0CA2321780130626668B9603ACEB9566E7737
+8D94316FD1B86B580D028465C06FF7A27821218D54ADEDAE796553063E2F52D2
+9552A0C89E4AC8EE8119E1F70FCC9AFA8C01171B252BAB99A05FD03EF9DCD523
+8C7B6210A11B3D4C4A45404160A65A9DA97D2086E33078C52C75AB63485197D1
+B37588CD7F3D190A3BF96588778D022A3B025747499505EE3377818EE8FC074C
+B79216C996F1C504B1B4FCD987721331035FA4C8A0CE71F59D07313A237DC76E
+A4E4C4C8DD418150981492277D12D17F034D363BFE9817E57A363B1E5A1672F3
+2F81856FC2AD67A26E506D69FD2E12ADD96410F2637C29B0F9EF7754CB05C4B8
+9B87148C40D213F6E4C6C78EA84D6D667FE31741983F34C969944CD736BE6A36
+C48A9D5C80B62F86DE19613EF0FB94947581C6CF37F7ECA9F2286A6415B99850
+226323FE559ABE8509BB8DFEFC3EA7623D0E9DE6B070FA1694D47678BE925872
+5663CA0D4B6EBC6CFD7509FF764C4BEA479F6A7FEFAF0FB04030B3E1FA569202
+461A7B21ED453E81357C2502E60D6A195347A9B1E48B1F10CA3AE9FE6E3B3F9B
+6F4653002E78D5FF531D64B6E607508C1272E32AF385481FE48E16A04E917A17
+455506F5819A825B9EFF14495DF6C1D879655441C14371217F675F966F6B3863
+8A588E8F1C22C829B66931087F54C13C30981C64616731F08136A1F2E94443F1
+161A599BF0AA225C55C558562C1ECB69CB6479F61C43BDF0366ED8EFA2C6A93E
+7E03777D43AAA368D1B897547F6F3EF7A4662B942D32E57DBFC4E243E8B7249D
+DEA0AEC4F28E74D68E68D098673DFE170F3689EEB88D296EB8B86EC84C0B6FC7
+A8C7701443C93F402B09D63D8D88E67E70A9685DD00355D4F97D924625326C45
+7783C9B3422EFE74302C88FC682C7ECBB818235469BDD6B108B6EC44ADC9092F
+2C132416D4B439EC1858E8810F1A50E358744AA78156F5F77CB23D8A7FC7872E
+F9422DA51220BC41242CEC90D1199D11E6935E70415F246687D015AF165EF4FE
+75F07B7FB28A860A8DFD786D972896E0E7B094DCD9D0D933D2CF264A71CB6B35
+809EAE5C0B0D75C271B6C6F22484191265F2D73D41B88291AC42E5FE2DB59D92
+8C3E33338DBA7116CA2F045770D459F9D28E44496B63F1F6D991BF0F9ADCEC85
+D6CF54F4DBE12BCDFD5305D5E9A27BDD5C24893B74B81F287608A07526C6859B
+B174C70DBCA2A8C3EA5AA711F337772C4FC741E4C0C46786B05D31E39AB20EC8
+CF6FFC52BFEF692F1B02F1CF3F79DCBBE675BE1DD6F4974F0586900E4AF4D900
+38EB160DB1BAF23650DB009270F4A679B8751626A5F15D3880813DBD574A1B8D
+8CF16E050DCD582AC7A90118F2756B106AF2775AE90769E862E684A1C12E73C9
+EDFE5A79612C54EB7D66FB2C142626A308ABB7F81902B231DAE57B34476323F5
+23B830DF72A6BD7E42799DB042952B8AC854B47230F2CD171546E5218F37FD87
+C8513642DB167A394914C6037ACFE16CF47E783285B6CB322E5247416A4931D3
+70CAB792E72D00934FC826E99050CE6F1D7BD5892064E1682053B34270525F5D
+3A6A4B2C35CA1F0179C9D342C0C996144412C3E1C283B52705FE9134018B4093
+D391AD7F44665D3EFD2353B07A8C3310E92D17459EDE74CE0C9283E34341A7CC
+56D472C6971A260B156DF12547DAB727F4E8F9131F6CBF5D60E63EE56A580C15
+49AC12A9CEF939E0B26678C4BD5FD00A29F832899A1F28C75EB58F32F5CE54C5
+3F12E668F0F04AB9E546FCC2140858496EE9A200011CCFED62B3AC24EFE8C2FE
+AAEB3F62F9FB23CCDE8A1258027FB3F0C42862C1F2C556955082C3EDBEE42616
+80EFC22916B3DF99A38D533B5975B1856FE7B879B9C22EC41309B753F4DF65CE
+1A39398D3A8AA078B243BBE33706B9D3318045F966F25DFB4CBF912DCF522C0A
+1A139C6720967118EE918A3868D2CCD1328EF16C4FD0DCE6479E5BFB64B040A6
+0116EE6127473D81203C797BBBF0F1E4623FFCC67087B34DCF95DB749D0907A9
+D682754AE5CD3A69C3E2B95306123626C81CC107C4E8733EC4B7FB2D43131921
+DA5D058200AFEB96C2443FC5BB2133A4EF1172F418ABE3B52E0D79628576BCCE
+A05FE6B149FD919FD0CDDE55A4FF25314F9254CDA6C901ABFEA25EE6E125AB35
+FC588345FB72F54D62FAEB54802741195EFD57EA07FBA9331160F74A29FC38FE
+6CC5E6ADD81D2DC02579ED33CD48860B9F45DB77AF8276B4C6F5B55787EF4AD8
+80E3908A6A1E424559B7473171BF79E2C3F8ABB541C7A5676F8180147EF946F8
+FF62844DA2C70D75AE3FF568C256FCF65887BF3864458E8D389E7495C4E381B7
+F22A4A035E3058546A1F201079A3E6024F68B462C28A955801BF1CD3E62D9E0C
+DDDB36DCEE6D03094BF61424B15D4C316B6F6BEF8AC813D3F0CB7262B3CAD2F7
+B71DD33C0A63C9A04049BE954BD41DAAB34ADBADADC92421676A2D39BDFF2AE3
+41977E42350537754799026504B8157E6AFB8427EC8908E6D8AA659C6B21C79D
+B4D39C720565990FF48B76ACBC0E49FE661570F3B7244AE0405C683E8B264087
+84378B700CF8C69E8CC9AE677A3F49E7E65C7EC49B5A379CEE5CB21F8D90CCED
+A236D850313F93867253105E6BC79DA26FECDEA83D0A7029F2AA4C0B3EA3AA34
+980CD60428BADB0FEA87B2C8445BE826F7FFF50E51F6868923638A63621406EF
+14F98248E24E0A3CF6665E7C52876B2A26B76E54980659AB15F5B8D590B462A2
+3EE48BC7AB5FF8AC9327498FAA52158E10E002F17E573309E64F14488F32D523
+06B4B263A1BBD5F5F6267396AA1556007F77FE0D473438CDA6BC8A550C448A22
+88762A7EB57601A5C6803A84499900E1346FA5D33E1B1D008CC6B8705C90EA25
+8F7A7E2F08C7B3E6542D137327D6C941E4884A4CD9E9CD488D1529A9A7B495DC
+4E3193C6FFDB6BD763559C6E9DF8616804AE881A03169708B122C22A0F6DD0DB
+BC2D86D0A8F1C3AE748A7052178A05FE8200E43FB229D6AF37A409732CBFFA56
+D3A4F163036D2E8A80D62430379AACA3A66753D47F441E31C1444382E6E874EE
+1206E550A7BD2487E7D3646E1AA4D57BE3FDD563824932F04490617FF3369B7B
+473863FB3FF702A47A2FCD0CE3E845ED8335DC453F2FA794840715B0A14FC657
+0F0ECA578B03E637EC62933409C72DFA5A8449A00F7D5B119961E503984CD2EB
+FB1786FA33B2C5EF5DE334A853625654AE4261757C5E3AA266E727407232D218
+118F29CFF96BD99464DDAFF8295DDF7FFCD59F2E7390DC253049CEED080689D6
+E0E7C962C61B4153375BB4FC24C5E08911DF431AB37A08A85EE0B7CBAAA01270
+F7CED06BEF56DB2A663C63EC03B5931D7B7AC47601BEC3FEA830A32E6EC8FAEC
+043808693211A6021B2F28D9A0BFFC744ABEA27445773C74FDB94BFA3A28C9FD
+B7E531304D95F04C4EB9EF7F8F1AC756CB1D3F335BA3F5E52339BB218C21130D
+7B982020571F7D604140E8CE8D6343380D52AEA18B707F0397946F8E07CCF8E1
+1E18237AE9A3680920EF6D0B9F6D4B1B34BF867B1DA878219E712BAEE8A5A25B
+95D0CDF979246C5E63486640CF469E8F505DD0E0518D672F4051F0A327458370
+542DE27BF723CB894D7AD17F38E914E093FAA5DAEFA82A1BF6C83DCFC41FE4E9
+D1980B1D500FE754707C02B98BEADB0BE51E6BA92F87ACBFF7F8E75B5CA48378
+DFDC891F71DA637551A4187A509C9DA6E618C613A341EC5660C12B33B22843AA
+7CE398AAA35292C5034572F79BC10F4101E0E54AE77EDCD507C970CFE5FCB4C5
+ACEFD84B48FAC3BDC999517A4E309D8DCD5AA52C6A7015AB4AB6518D015D3CF9
+4EFF7808C5C3C05388681C40983F330C8FDCD93D2874C24C40C248AC57B42493
+DAA88995F1CA7ABF74B13E3CA08F4A4739E043F5DF3435069FB184F8765A183B
+4314EF9CDAB127701347CFBB88E4F6F89B91518BEBB8E594C5ED80CED72EB401
+87241DD0C0F4CBAA5E6AC53402642F85E57BED30739B81AB79D16F7135BF8298
+18D251507D91D9967A974FF10055BBE63F3726CD7E388148F28C2B3800737FAB
+302E6877372AB1CFC5EC66C8753D946517217F60A5FC40B00E95A650E592478D
+5C8A8CF1BC1E4F7E86099E56CB00096EE6A9CD98703B4CA172ABA8FB16B3077A
+4B109AB0A6E4C0CDCFE7742EAB4965DD666BC474C966653556693C4290434F23
+184882BD6534ED0AD8F9D298D520C077D7488AF8077B1968F0CACD6111A5B1B7
+C7BE9586520108B932920EEC6F98EEF2036D6826EF1FF61DF6B2A5E7B847A3E2
+D2E83E69A98B826F806A67B193AE07A1D16F12965D34FE1662CCEA459A27063E
+84B223AF04E1D4DB52B894AC4AC2FAC3714EA4482481BA5CCDB7D0303386C753
+4BF3846B5D3731AFE6CB28E7CA2229205AB9365A28C5A362BE242AE06F8DD5FE
+C2471A010AE748F4A48026AEE972FE804BB7773E15EC36F766ED5F5342AF93B5
+D21A7585466641A6A4ACAB3F4F5DFF71514C105691AB636E3071E46956BDB6E8
+9258ED606AAF78BF1CFBF5280D4A039F96464648DA76495804D2BFB2B452078C
+7AD1A80CA94DB4086314AF1F6953C0A8742E6DC577AB32C3389BBFCCD2893C97
+9ADAE394ECDBC855CFF5A7FCE17E32803AC7869E8AEBE94E8256DC6468FD2646
+31B730547958DF3C878F6DBDC65D048285F296D3D6FA067528B4663116FF4BE6
+2C3578668B3F3BEA1FFD3B142D4073C746231D8558A9F4F1A1AFE478DBC2EDE4
+78CB7795BB80F32A0D266E222D0AB34DCB18E17ACBEDA779623E09481D8AB1DA
+3A6EB42BD7C7BD071269BB3FF0E5BB1483A9D250F07E19B4C1E2504288E6A034
+A7246343B50E1FDD622AFD081C3285BB5130390FBBD5547CE34EE80DCB810208
+C0B2B86FC15F494EC25310182FD011CB1837107484572294CF2E2C0F3F55B2BD
+F2BBBEA761B8D9DB29A91B0906961ECF6DA690DC768D9F937F933C23668F0F7B
+D8E69756AD43B7DD15268BB206F9D797607DAF18700A786C5CB449CE6D66F221
+BF281175340D508490AC5930D0D6B7DDA6646227D126BD9B7A50A134034B7D64
+DE1CA653847AD3CFF5001ECBAAFFFE074E356499D21D0ADCB3CD5BF3CCFB4D79
+BD72F8EFF9EBFAE629CB45BB1776AED53AB18CB7E515A101BADE4C24C3ECD09B
+F0E010653DE7F5911C69888D0804E01EA353741B7E1FAE1281D9EC7D821B2255
+FD6C8F3E243027E60152937C777EB4C0DC62F9F0D8D4EE96875407D8ACC7AA34
+779AE87E41C49DEDFD6304D703121AC25D6E9A0E3006D423922AB6F58B7FE0CD
+B7F5BE05BE5F499777FC4FB5BEFEFD1235629C788D4AF8EED596942AB3909826
+421B649434BC2673F9659119222DDFCEC623238DD0CA0ADB662B94568326E522
+C25EB48763D44DFFC79CADF6AD816A3BA2D42B9C1D6E2ECF5BE5B0D2B3766EC2
+9BF5048EA59E18DBF4C91AA748FE18E4AB6B768BCB4955580CF98528D97C87F2
+4439955D9D5E73D0CE50240FDC7C0A3A437A1C8733CBC829FD911C6FCFB27F35
+38B61C235172F755F2720447C62B0F20CFE9D5EB611661BC391934F883F473AB
+31600207A21FCD9C4F48113E5075523E84081706D6FCA70D54C7E5389B9A66D7
+ADAABDD0616E07B2579E997502A4208060371D61E957FE380B6B48802D88666C
+B29EED98F3AC3C2AEF3ECD10A363306534BD86F645E512BC6D97BA51D621F022
+603B3ADCFE7C2EF109D0AAF094C2B29CA2DF77B8AE90BDF43F7A376D8002AA72
+517F75E08179F67819308E9E76448791EC8B0C9FDFD07B43D4BF1D71388C3427
+594860D084A34586BA8E662942FFB8E97A08DE31F764BE4B1B01D83416EBE660
+609E22B574376FD7886DBF1C5D350C6A1A0F148D139F9301BEF6F4BFE796C9DC
+35EBB8B9849B03CD46BF3DFE996B12DF256B0FA8AE190203501F06BD2741977E
+61D1FFE8775434C85E58207770B177C1125408DE5BE4F4755CDDFD10EB300123
+2E380128086D7F6FFA2C7E9F898B1F76EFB5DC121F134378683C1836F800362D
+DE7582775D12FE54A80EA4721C85E7FE23141DC2649F9CD7A22C8838B82659AF
+1C227D10234F298E5DA1125FEE1C42F924E5A341D8E548872E15DB3CA1D0006C
+4543383D7870236090B6B151AF797B803D802F56512D5433DF9F863532A70448
+8988F959A3E10D2A7B8F7C1349362B97E9FF96BD60F4C01C7280058EB3D6D3A4
+D2EE22AD1945156C0DD0ACBD1BC7BA2F28DBE12C6E8CD8C7B9FC376F46369E1F
+7A1D948EC5C1C5CB03CA6F8DD19BD2450E3132052304B82016A521157CE0C085
+264555869BDBD9C4EA06A6E2305C3F8DF8B48267A7B216BD321671BD7E781EEC
+1567787D43895DB5556D0099162FAB3709F108BB6A51B249B7CFFEB2ADC25EEA
+26DE7DE905BC52BED055684C12D1651DBB3AA3EACE20AF48BEA6BDD6B1BE1B80
+E2D365E7C1FB662086F4D51CD4798EFE99B5910CAFD0A9901B9424693771CDFC
+19567ED5E003EB523495410B810B3EFDADDE0D2F66C27E9B7E1CFD6D5EB49C5A
+63F239C964EADAF9B6C0994BF5773BDA6448F69DF078CACF8660D9AB8BBAEBD2
+6EAA6B503BC4742685A99689F46BC0FF50AF35909EFC978A523851C099974B64
+9CD59766246A7F7E1CFD36C16B3459CEA533ACD5D718884E11A8DCFF9B6CCD43
+D53ADEC4BFA36F9D878C18FA48FA538CB47AFC1366AE1CEC893466D8713CDA39
+1A08E2A32A495E692FDF4061DDEF5FF716ADD8ADFB1F85E2F150A7CF2A4A01BD
+1C93C833EFB20DCCC429E35493E603A7A2B0246AB0936003DBAE7800EF36B25F
+7A7CBD50AC4A5863320D891CFC05509F6A3AEC29A2B21565077D23DD03363A81
+703C15D72627F8DC414C3B445B7AA0023253215DEA15ABC2C1F159481AAAF9C0
+AE4D4FACBB48CF83A3480B79D9F2E2CB98C606D78ABFF4F94B2C09752A31EBBC
+946FDC415AEBE73C1A85D379A0B99016B6480AE27EA95A83CA35A7992AAD4183
+C42BDBD6190B2198CC0B48450CB65C22CCFCE1A81C0620712E8332F17C48BBF2
+BEF35A67F0840ABFA1B40FF14B0F217D071C5B37FDDEAC519139B88AC04C52E8
+52D057FABF743C849DC6D3F6B1275D5FD173F0F25C31D55DFF6498C8161FAD22
+57837BDB4FD169A17F45D9214420AA797D44A1E33F7F242BB6ADA2E838E217FC
+8F85CF785146CCF4759747F549E5F8BF5828EB86264D67617B912F3B1B6CD5D3
+CC1D33F5C15F0D5B23F48C4DC40FFEC56D01D78B2D6BF18D77421EFFF9525E34
+00F389B6FACFA172351DFAD20E84FD7A9371BE9A5BFEE4AD8EAA458CD66FB6BB
+6776DC59E59FAB1B8CE9389220992E18AC7CF1CCE49BAFA7A0B401E300B8BD7F
+83E6551504899EAF9A7338D8DF4218A541CA447AC234FFB0C5F08540F9994B8F
+3B6CB6D3F821D60BF3E6378737857435189325F3DC8ABB3E95A3FA19276BE44A
+B17C282CCB5FD2ABB61CD73A6DEC44F25034DC4C153F436E1FA799CDFE808620
+D3C80EDD9BAEF48E730B37EB2CABEE4565DE8844B48F2B041F4528F78795FB88
+E7EAD240C1E5A985AAE1C45EAA9AEE4C76E05610124A3B703C710F414C5597FC
+B9DB61B13B758D4DB6AA9EB57885A07C751EEC98195F02CF945BA2BFA521422A
+47628F63D14308D514EDC92691AB271FC52570687836C84B8DAE44FF6253B3DB
+DADDDD9093745EAD3672817CD27D5C97B4ED800200E0017216DC8C3966D146DF
+65ECC0E35E6B670178B9554BAC4AD0A0CCDE4B271359D8AB712E2CCA8ED74DC5
+CF438CE8A6C70F6E7FAFAC10F4C8FF6928160439A610E744281D00F99642B856
+AC663CA99600BE0903801237EF19F5C699E3D5B076A645618BC8C19A5DC3E690
+E39F5F582FADE9D140688E3E79704CBC2BC655D796F2C15883E09BD61A700FF0
+292860D5BF7E3E0EC99CFE409C8CBBD0753C48A938DA8D08B43AF97D89D4EBCE
+798848195356F095FE6B0319A93F1DAF482B3B1E3ED67236215CB10D85673224
+CD4CA72E5CA213D81971C1B689F72FC341EFFA8BFB27B98676A3F58F96722B81
+552D0C57BB4EB64D6671DDCFDDEF9183BCA627625608C711FF8D593B4904CD1D
+30B4C4F0BEB010624219D0AE0FECE41E77059D811CF34770FED28EFA0D7226D9
+ED3A5FF296B8B7DADB600E9D378169CB20D03E155CD67A27F253BC32886730F2
+F2CD5EFB2DF7ECA8B7DE116FF113EFDE8D1A279F785350ABB361D228D7D45565
+0808F17A2A7E9F96876CB0645659143D92F24D2BAB519E6503B6556ED4C8BC6A
+8FEC9773CB8A0EFDF598FA19650209E15548139CEC8D888F4FB9A3F7B5E35F58
+C28E344A9A73AE19E0E3990195C58AAA29A3C64DA97FA0FAA27585ECEDE23743
+62AAFD6431AAE6185D8611C4F7EBD607D488BE416D56603CF7BB11CD77472500
+435C40A75D06145000FEAAC8A946B2AFD2A971E8FDD34092919DC6CF3606DC83
+4BAFF20C1B9D2E5903BD17322F43B797458D910C7C68B233A0B8B40EE1B6969A
+E6F12D44B94B98CB3EDF44824497290B609037645C85E55F6E6494A44ECA5DD2
+FCFD98F8007F396672044E1468D92D1B06A3597D2FBEB32202DFD3C495C7696E
+21504A670558F6E6190E319BCC7D84FBB7D8E4F35C7E6BDF380F4B1F0A0CE29B
+784A102B950925884792A042463013C98AA2105E957CC0FBA0A8BF5A04B0F99F
+6EB15362711FDC8759731B6871FB1E60E47EC0396151041B701677A38D0A4ED4
+B9606D5012EA315459677B3C55604E2FA8D3D47AE694FC7FDD0D056749A2E1CE
+BB69C67A55E7042F533F17D672E42C8E0C010D72CC08363552342FAD57E22A59
+758E895487BB7FC03D3864F34C3AD10DCE31A2F56BDF06DE3B7DC2E32BDD4207
+CE39BEEC5AF69B1E1660DC2DD8944E750CBF2EEFF15CCB968AF9BF337766F3BB
+9DD9251B3CE43968B6227C0F6806101AEB98444154D645CBE85B9E65FDDFA14B
+684BBA8BFF7A1601C6A7DDDB7516F2A69B9F5D542FF78730CAF42E71C8A1FE42
+105B27283E8AE999A8EDF8F9AEFE51ADE5B2091AA0C5EC78585869B7D50C06F0
+9BC5901017DBA6761725CF639A01A969AFE8129BBE7D1CD34F338EAEDF1A91F6
+5A21DD9C507D0C27CC2DF65C2A83D4C4C1E6B57A4F5EC799FF44D3AE7057D243
+AF16232894EA0C963790D3278351CB0EFF42AD43DB987F9047B0CC063A64E04C
+E05D8F2C4E74DFE899B61BE66CAA5CA613BA0EDB91494B9B613B1609A0F8F6D8
+83062887E7B863FC2E97E1D97EE99B6930F42DF9E1928140BCFE3E5E933B826B
+3F537F38B8E7565FE1EEF802D30F588427413D54D8A39933BE75001B4B770468
+EFC6393F6810D02E5DB1A7348118052A00D6E4C1D4745D21ACD12C2516FDA833
+EBD94168C54B1359AB670CF86F1CD00ADBB64A5E7E88C701FDBB10419C8ED9A0
+1D262210A0DB2E03A9FB7F82332966876EF675CB4E0619E84163DD97EE146B8A
+B0115C7700C337F637563B6B7DC304FAE6CA5D0E903E9FBA76068B9F3C72EFDB
+6C9B1E5F14D88DCEB689984A0D2552B881FCDBEA55F7366BF7964839CAD1DB43
+C0F2386818F1AF73F2177C2480BAD174DEFB2327E750E0F50B4FAA3CE579CEAC
+B01380D55FD25812DB806997A5446628BDBFF77ED68F3C16C016542AACFFCC0A
+FC2684CBB5E77AA8451DF512EAB8F15DB7219957231198870DBCBD035C69CF28
+26FF833F889EA78DD18F4C14E1DC1016EE22E529800BD8C879BC142EFE38DB92
+6CC07F8370D946E174B6CE530BF7B717ADC5B4E78381E1B144B1098770189BEE
+00984781EA356F451A59F161A2C8588778776C66F82C8C2E6923ACEDA5806E91
+2BBA20C568F69F6AE3946F3333608E8FD2494B194BECF0D300D5E4E909FBD60B
+FA894A54A62D00CA2A46F5B4DC2D9A9F3A5B0F04A0A9E535EFF3EFF7344F14CD
+5C9296B6AE2E3DEFC7D3DAA5E652A3C0F22A8F6EC1AA8B0FA785675AFD4CF431
+C35D26A7035FF7B72129DD48E7FE6A838113E1A09E47A35B2F8EFAF2A1A8C215
+9E4ACD754E6284D36716118FFE3AABD8139E57E9030DC0DA9FE790736DD0A67C
+03D492652B66E0CE6A6500691D8BD0EEED0435533AA31D4DBCA3DA5D117E7E95
+0EC20BA7052CEDBD9BBA30AFC68900E998EE69E1B72778287A233B2BD3CA15E0
+F989DA35E66A602AFCEE90C6E8D877A430486B8C000717CCCA9E3FE551A08E7C
+E9023114FFE56A1DBFEC17E59165DA7FFE1D7C43793B7DCD3E40A79E35E417C1
+E10A9DABCE129A79A9B3060C6583FF5FC3F34D5A519D33C4A9E1DA84E492DF7D
+3EDD178FEB9764D0D26C4CE8A87D77A3B4BB682E3534A4D31E7D25DBAB922222
+FADC2B82BB2F5A4265E09D55B0701AA802563B427A1DF4403F083C75401208A4
+EA2B0A03F9A798BCED351A28F946B47797764372FD63084563CBBDF0B2B84E21
+5A3FB819F9591F3181243151B333690B57D65A1CCE64130EAE728DC69ADD89AD
+2CACC21122660A4E7FCE87038ED4FC02C62CF03B602EC2ED65CED0FAFC3A4D5F
+5B953122FF091BDFC0CFF121893141A1770B64631CCE4016304C14313399248B
+29FD2750972DB466A7A7ED56BC2A7C991753F138348ACC1BED3A1B8BF0B74146
+CB09D777D2145A6341C88F44CBCD6D0E100576403CF176AC66B80414174B2D46
+09256E4A8873623EE92C2A3E3F8EC40824424B9F09CEEF598A84049C3002A73C
+A68607519E4599F35DA4E8FAC8DD6D3C7DB490B188C6BF0490D9456A3BED1A8E
+13BF001015D9BFA3ABBDF88BC4F3582210B6BC71B83D93E0713AC5512D70E61E
+1F96FAC3E1F313C5D29F0BAC11667E5B28243B9E5AA35E597A5B03969E65BC7A
+8DA8D07A049B2C69F2BB6F163C1ED5794AE03DCE4660A48952622C48AC96F662
+A5DC8D7676EFA86C5CDD3E4D5C0AB0FF68DB756530CA204A8FB55955F953C29D
+70530C6445418A198991E043C57D214A3065B420B679E35D086241B2BB48B210
+1659E53C636A90F01E0F7AFB94DC41C2E83C1D320E6AD0D61DC18FC87C2AFC33
+7F2338D2E71A5B99832280DC3B27FED7A86731C106CA68BAADEEF1A8E77C8B43
+71D51D0C898772AF1233D8AD8372698A603FA2762EFE64BC81E1F7E98A3209CB
+1912D11373A35E9A80397CB8B15A35B42C819A9A174E07C28E6D660D3A622DD7
+2AA79930B7061541C6208DF061A923A60F7480827C47D78513C6D0A6F382EA11
+AF29E6836129DD7F8B0243B3FF3C9AF10F75147F96C854EA54B7DC37AA412E9D
+C2468C7737BF72F2FF771E104E2A9D24293C9A0DC0CFA723226DEB7EBA09F317
+B68D8A70853D708757EEC9941A4A07122D5E2CEF04A9746CE4995476511D6BE4
+6F0F6AFAACEF56297051C1DF6780FDB649A641340A61CF83A8FA93A2D03EFD66
+A7D5693AC165508FE169C41C8B697ACEFF39BF22E1E23B0E7B5C72CE2B487DEA
+961EB3D1371137F66AF4B380802780C0FC4E68DAA86EDBB71647AE0E31C88B84
+B87CF2A69AF1B151B73F299042C5F7703DCB2CC8629678320DBAB9C2ECA249E6
+0AB435853082E93BD5C019C88010F6CF82B46C6C7F2B31AE88CF62948D76EC98
+09871BE5549478FA43F147EB95A52CED2AA23AF858CEF90A2ACAE74C54C23554
+DAF59756360CABCB2474A85A441552BA3FB47377EC29F2C6A1F67659584E3B51
+9792D29657A8C6C1C4BC8BAA96ADCB7D2AA8ABC3C66EF8BE6DBB304549D764C2
+2CB9210342CDCDDF877EB7F2A73CDB19E5D05B11C480B9120547A987B87169C5
+15E8210A9FFDB7283511F50701528BB8DE8D55BE050D477CBD3FE4B1E6911CA1
+853F58089C8010B2601D67E2189C29227CA593139B00ED3E403761A9CDA9BCA1
+339BF77815D94F2F5D9072186F2FAB3B80A30073BE14FB29B7CC6496FA892FE9
+8EB51E24AA615D5F3772E03C6A87DA211D3B86702648300AB8905E7C3AEECD2C
+2FA61500207DF72B2837F20505278C11C572BBFB172F5461AF07E1A88903C9EF
+CF7275A02E81B7038F1ED00DDFE60A90E0B3BFF35502FD370BBE91D2E0E5CCA6
+79971E4C339B8CF337D2FDF4CF0C084AA58E6AF16C06F4034DCD6048C58DDF2F
+E51DAD62C29D34CB13FBB16E7FF581514E16742B183D6CB6F12B21C3B2758823
+52CF4573322140D0D5C4E2024F7ACE5F6E327CBBAE1563C64975FD808648B267
+57B7FF03B1BD5593F52EAD3E595D3E85A7B9AFE10EB2BD6D787D52C0BFF0C457
+4116CCF971FF5F22FFB1024FF769895E29815F17C28B7CB8431BF3CBE155B03D
+C44E79D4C4E7E35039F148B7FA4E9A87C77182AC4331988339E75C1FD5669C70
+FCF70587309F57E3B78C65514339BDD15B2AA34BBF811A077D7E8934AF90933F
+97F756FEE92BE903E79F1E6BB0FE32F8A5CCA55C297B3091A171E3428A86B4C6
+83C908A4639B3C62663A381602FFC26B7B5ADD53412B22DF596611C7A6F2223E
+348447A4C6D59A79E35B0095A384B60C7139670ABFA34F2C6E3C6FD2556301FE
+4F81639E880398A8E1262EA015D130D94C499D276FB6720D3778EB3528442EC4
+6B5E5194EAE81B27F85C0698A8A3DC0BC930DFF2B8861121CC8EB6DCCD42FE6B
+4F93DEC21926DB179C7B12697883B6BED238FA532F0436A35D66582AC7A84C05
+0FD404C7F5BFA680285D4EF124B3EA4C72365EAC1CEE50DFFDFCA168B52E240A
+D020D8AAA3823BDB5B5657112783F8275389508E83EA84B88B89BB3C5D3AB188
+370ADC7530A31DEBFE2720706487DDEE12289B0E24222D7390F78AE4457A20C1
+50815ABF6C307C40D790DD668EF01EB5D6021DBE4FA8FA8A78227EFD3E3B0B7A
+026520B0788856B162DC3763E4224DCEFBE3017AB563C430EA4C649C8D32D73D
+5C960AE91A4A778E53FF136B2F1DAE45C48B3A99B52DD75930DD0CC565A41811
+48F2C3598F425631610F564349D3DB66306AD281051A2C7C48966D724DA6F715
+CD8C8D6E900FC3355525D960110AEF5591F8B28254B9606993020277D85C13D4
+E1E1F10FD0092A08B94D0D50334C044AF133B84BACCDD2C955721991229E8106
+0585D939E21539FE657A7A76F64D146D7457D17CE2A0445BDB6C185D4B3B052D
+4ABC81D4135D5F268DBA4259DEDEE96464AC15A526E6F29F99F8233E18E658BA
+905040FDFA76895DC1372FE3A4E04C524CFC0D3C33293BDC735A382A37DCEACA
+C6D00452DB9DEE563D955F2C8AC385934DB4E90686C04B7885F8949623D2449F
+6EDA0B985BFE44D1A9DDC475CA1F13FEEEA4B9B001614E44325595BA50110617
+35AE26253194D9D456DE030EA08AA398B7EB5153A527158889251310DB2402C9
+E5976DCE7F676B09ADDAB43FA4E9F1B497D31AFC6CE39F6D5E6F0AB328F63C8E
+A568BC3885866A0B67359CD4A8DC75A5D9B9C15D4DA7C9157B374DC46D06E86A
+09C3CA2016D3BD5A2B052A387BDB4B4F0D82C3F68A245855D415F8ADFCFBD327
+50CD63D609E698C6DBB78C6FC83DC60FCB5AAEBA38EA0F3DA6CC277244C76C8F
+FB5505666C0D7EB22968602134F7985B486330CD9E3231DFB5ADD4DA83AEAD0D
+8275235AB4FAB360B84B224A3C09E74B9AB16B1F53DABDAE08940A60ED0C1254
+DADC1CB72CFA17C4567838C313D9FB20D28088093BD3066F914F60F9B5C9C998
+C353E6EE80619CB44D4F14C33FC7980CB714FE80CF77BF1AC21947A39E5EA799
+B6563BEE8A7F3178C9576247A8C6D34CB084CCD110D637903079AD7115D549D5
+D2C7700391A2AF356E65C5268966CF36C0EC24FB19465D34068C8B52E18D2D5E
+856A34E6E428BCBD900CF6003EDE92E9C8C39EC4702BDA42B21668606E15D287
+2F75318F622364BCF0B7FA78481770743BC00FECAA671F7B9E4728421CA3961B
+EE2A5A39F1BFEDEEB81379D1E1051C25A3855A65BE5DB29B00A2A2E9011B5C19
+C767AB6D6AB8F4C472F365DF2459B48D596896E5B14A5FD33BEE895B8E9FF27F
+7CD6AEE3BA14F0ECFCD35C6F70157A95060E61BAC21DA35073F99409EF29FF7D
+04AEE73AFF5409B42F664CCD0C48A3380148244C23B1C87A9248A7261D50FEF7
+6795EFBC848997B444870A6A7012D59E02C699E191441D06880D7D946EC867FB
+38A8FC7A0BC46E6248E65E6FFBCB908E919EA5694B8405061133B2F19AF55A6A
+A7871172DE904F4623C5F9394E8914F173EFAA59912DF5CBF7EAD8427FEB267D
+497915C16B744A575428AB2C9A43FDCC0AD6BD9A1112E2F8D76B9DCC54DD110F
+A68B914F2DAABE310FA95BE489055AF8D1291DF1107B614FAF5A48AFD82EB0F6
+A662EBB941875D666B61C6745CB3D28B32397699279EA0AA49D62D724B6B041B
+B981EF79C0802D2883C816CAA52FA9F5A94E55CEFA031DEC3788E625DD5B1382
+2906B63C2B56C82BF192403287D99337C95749883EA18220DB2692F40FDB09BA
+2A58523D80230DF9DC3CDF7616D34C5327D252053B57E4831C81FB09EE450670
+289BF355FF46855B4DC2C2A9ED1FD973205FAB0DD7EB4A1CE8C7082613C194B9
+A69594CADC6F2B71C901450B706D916C548A7E09FB64C21C7E7905AE4003E533
+E05CCED6F23DA81AD48BA724A739C8EB94663A71E4AE5EC1108BA0C3139C16EE
+E56F28F3F394A799F0CB8FF2E740D2AC516C02293EE062CD063CA928B477BBCD
+1E2DFA98C99A0DC25CAE46F255CDB0FC678981BF19F04317F7FE4571C268BA9D
+A31E0821E183BDF3A043F263C9CACDAE461B1CA2B3FC55D24EA5CCE2C0C5FA4C
+EEF68B2C0EE9F69B2061B5B4F758D5075F77779C4543A856F7620745F29D71F1
+93A32505D54467EC581C635A7430BA296351F8D44A56DACA2105894A5FB1AEB9
+B2D157326A7F71003C6EC3802CF11DF323B847DE7D7030560E31B5413CA7DAFF
+1A17969D3C9278719ED826BF730ADC9DF64737B2BBF46F470BEB18F4B52A29C4
+15900BB7E845BC78A6D6BCAAD9B05C62C21AC3914E54721799414BA11D4BB40F
+C79B29830DE8E350FD105FC9828580C62AFD23476B502645CA83F29B1EC19509
+B6273AD95A48DF76743938B9E2D00DD0C1719C7C442D19CD783443146FA59AD5
+97018FE5719AD51E80BDA7113D84480D6970DEF24567991D4F492D2AEC3A095E
+0639D44674B2EAF1246F3A3E303FF2B13752E6E13CD456B24476075C76728B9D
+1552090B701B68E0403159E45646FD29A5C6D90F2B47DB998999549BBAD27099
+4CBD8884E5BED487BD252DB0F5673430AD279CE4DF33DA4554BEB667253C152F
+87043A6ED2EBFD1598983EAAB807658163F9255CE2B06FB1B4BE4C4DEF5DD970
+4B86C44F9BB4F001B81FC96487C8F098183877AE2D11F1E3E95D6C4177AFB9E7
+29D222D2AE4B367B0CBC99C136B169BAF121EEDDE32153D5B5E91EF1B1863B5A
+77D9843C6964851321957CBF79AC95F9AEB4208F57F95C20DA6E1AAFD2719DCF
+9ED3B35DD6824327609456107D27476BE90C44630C6516C86B089B33E2316A72
+918D5ABC5A103317374AA4ADA7B2A4D6878D5BBE65D9C7944856560B05BE7154
+806A0EDBD994D43EE7B64317BEA051AFEC63F754C3AD10596C8B7DF44B613E4D
+665F355F4E925BD3F472BF4347F07CBD53FFFBCC9CB3EB91A70CD383471A9CEE
+315ABCA987921A3DDABF5929234EFF02776D92043A5772E75C9F34B9FB963642
+E9829993651DC23C9920F3062284EDD73A1903BBCC7970CF7C73107876B23B95
+87165CD429D5FEECCA3604B342F52F2354135EDBD61F72E44B1EFE66C4AEBDB7
+8D1396624279B6C79E8496742DD7A6AF9C02DFD4EAEE12ED7C9B6D4958A4B249
+9A7118C7EFFBA274A9569891B46DD0D3CDBC4C9D2B4CC72C641A24CE48708D21
+7722D044F801DE0E656B921751A3D60DD7F9229AC79C3715A2E44BA32A73E57F
+259092AC8E10CF35E239F272B8466E17D9738B55CB9C64A8DE2AA60AA95F7454
+0F29A380D4E735BCD50D3EF5BC74720A900E45840AE0EFBCD625F1BF8C784E82
+C896C1762E9DAB2965276F32DCEF063C6F64709284BBD1E4AF6E5D399C423302
+58B780F6A32E20E04E03FD959180D6DF0FC6982D0100CE4194FC3C345011E0E2
+6860DFB77B5E3067AEC5EBAE0AF4639F8F5F3E8E8722B6F734C1AAE6107B673E
+5E033E584C9A9A0B8BEE57E186E1AD27963DF9632A331327F125896E7E9803FB
+5FAD92FC6817B00B4E6DF907F82930782DBCFC9EDDD068471915AC7F7CC71877
+13023744C8CA717AAE350564E617B4DB858FAB9226A87874FCC226C2C0EAA971
+1FBB9ABE5FB5B4D5871FBA18787DCEE2998400F921566CD6C973C28C11C31D25
+1E1124939FE891037BFC37FEC0CABE8F844318EAE1D440687F45045E0767E18C
+500CDE3638733035FA968CEB5D2382F40C64D01403D77597069F5FEE8C51EEBF
+2857DF09D89A33BB5E144524BAD6A793796650CBE101D82B2D44D17ECB9B15D5
+9CBDA1644868CF80A1BDFCCC7B2D3A8CA94AF695916204CE74B44975CCAF8006
+91A6FC73F8116645AC29180E43261236832E3F6AB757E39149BF0F47D148308C
+284B50B0A8270B6220CF99203FF58E2D81CD5956C1DF67CF3B0B03033F07DA60
+771C11EDF277DFBA346E60B0122C659D8BCD1F7FCF3850972487C3D4A5ED6D96
+33F8DBED21E07F478B3C1F2324330599EB6570D0A5392C0387B21BCA8197C258
+1725F14551ACDEDB213AEEA9357BA9A8AA1280406B8FCE04D1D7F4C8FF8CA79B
+207C56D9641624C54BD75A384F9FB7FF0B12C534FBD0B30B29AFDC8BD1FCB465
+065BBFD6C41521E9D542FD57F6C37914CB27CA8FD99A6F6DCFF9809B7CBC5540
+89C527E0ED1DE3A3828C7DF788D412C0065EA9599EB8C400D3DEBD8B52D5886A
+8BA648163E2BE838E522E7265BD101058B47B85C6B5196EEED9D26435E3797BB
+B9659BECB66CC4DD4BEC03B393BD825A0919566D8E4446C21207C3030F9E3574
+A492FE5E2CA3B1F01253413EF8180BA2F53F7E978F41EBA2C7AC61353E71F3CC
+9E4AF0BBA32846567A27F7BBE11D29D48FA8938E04A802A2C231C9EFC761F826
+D889E0425CCF0889490B2C0014E4AD7764905290084EABB39E50274F5EBE180D
+C62349CB820CE7E3577430C01C322C044152FCB5F7CC786755B992D2E3ACBC9A
+8A592AD0266B0391576BFAA177A32123E633638575986048F093975E50611C9C
+930882643B12B6E13C2EFBF9BF582A539AABBDA7CBCA4B3CDFAA70B0AEBD7D92
+25B94EFFFB52F5E7917F93816E80DDED78CE01F93702587936B585D21B6D08F9
+A14443C0F9CA4F106D35B296B5B3818248389381BDFED56A8C7E1A3F26E14937
+718C587DFD611CC547B8BDC2126CB8BFC6193BD14D0E0BC0C325F75049647AEF
+EE4277382899C8A2E08B603AC686F6F5ACF2BDAB6665F7F0D7F179822C7B6386
+9670A5D8E57568EBA3C024B845A12C8C8E7065F92F34A3167A0E436CB22F4200
+621B558813CBB8E2EE2AD842CAFF4830E587634344B0B55FEF1DBAD0AC5891DD
+8AF6F0DB42E2ACC4254FB9A5A34C7F72CF9259C0B72F4772F18F722B1A28B18F
+BF01757EF7D210D2FB0678B5BBAF2C73194C94A06A2A31C4CFDE6B825E474AE9
+EB2B1F87A18E659E9CBE882076271C83A823D671748DE7780184426F20D997B9
+1EF4305D74C2350462820FB57B7A5CF5B5114EE771491149CF01EF5C5DF73B97
+BF1D27BA0F9CC59F2FF3DC7D8FF34B6F39A6ED770F9402D0C4FB5B8655AE9BA2
+DFAB14DFBE3420F9E3D7C612BD5B339B2B5E6EEF02D98209C836A4E20E1F927F
+055261228D83DCB2F61393FB34CE5191645D09EE0DD03C70E6B07D3083A38181
+30CE3DB58B9BA3922A9EE272060C2F1275DC2B902673798B6AF8F481B6C89299
+996B69D32AA1EA559BC0E8EA45DC6D0674D505C8B8460FFC5FDB5D9CDC59433B
+A49321478C0AD3C52A5DBE6C60B565FBD1A121BD223BB21AFA0D138E0970C793
+3C9699791E9F4DADB833EA67766D8D6C185719A5EA284CBDA1A740B00DCAECC5
+8C34515236F6FF7C3D579263468986FE19577777BFB1109F398EF749CB223404
+75A0E3146C5DE422F09B89A8818DDE7A202F5F0F77BE91B1B5A77DEEBD312A30
+377DE334CD5B0D45F65123E722DEB09F67EBE17F8794BD7BB239A2ED9F68C024
+FD46810FBC33965DB3AA59C8D45A247D8611EC7DB4242C64E7DF74A5036250BF
+675A3EFBC57BA3B045E9EE219E5740A2F42F6A97849C847FECFABC10D08612CC
+9F9D369F2811E3F83E526BF5DC45AF2138146FEC19B1A1D55431FC1D1E9C2A54
+79A56A473B4BDCC9D349F3550F8398E411E23B28CA187AA9185F70FB41CCA800
+72C7D018FB807132C678575F9EEB429537ADCDBE901C5BCDCB02C8536E2E4DC5
+FF7779D13B00D7FC14509DBDD73CE400E71892028DF6E0F6873F8C5470C4E189
+DB0CF99138158B3A434D678AC518357980944C83EA57922E05BE21B5C6EE15BA
+AABB7032B4E5265FAF9568A2D625E6FBD3AA735F56D3E0861D187F487C1D43DC
+5893D8AD8DBEDAD725F0B27823D212DA832EB5B1B9DB09960CADE299AFC1C288
+DD42E6CBAC72AFE3B901B5ECE04AA60025142717E0BAA99EA46CABF138E1D537
+B870D2C54DA448BFE1A52F7F65838EC14E194AC3318045566983CBD9A623D211
+5E00EC7A016F44F9F6F01995CD6F29D1F0EF5055DED50269E4959FFDC6A431B5
+C368DE86301C8F11D22269A1CC17FA32F2DF75E25BE046ED84A8EFD316B5C837
+A8751E59908AFCDAA287A5F3207C4962F834863F9324034ECE5E52E853B03D4C
+555C068676DC506FA61692CC611409D6E391D47003CEF855614C8BE747CFF0D3
+F812DD4D00CA4808E6181F48C47BF05669A7BF6FFB8086A15400DD7DE5504907
+8E986ACB7E6BC1D7527C07C183FBD67770819DBDAACD2A42F92383891B1308A8
+0ECEAA7CBF251FB093463E5E04073D11CE549445BDA44B899136658907809B09
+F982DFE90E838F7DAF616A149920084EAD2631A70FFAE1D79355CC1ED7471671
+9F9443CF76633EBF302D8FF5A52FAC37739647FFC0BDE2253B78A4D3FB1B4516
+45F6E3939D0AAE2D7C58265FEF253958230A392F6A3F0EC15A86725BFCC3CD4D
+04D987D92532A34DE1D5EA52C3DB52467D0EF321F7482DA56F5510DCD2E4530B
+BE8B241AA58E45C66C491184C2BF9E7DB86DDE442BA31A23F9051E94B6BE2FB9
+C50645AC4424D9DEB70EF3AA31A629238B51B0AEF2671BA206F996002BD41EF9
+975C6339C00FCDC2069F8199BB2999CDE805B144DFAEA00BC593E2751C6CA957
+5095DB3B3F07431FABD85675A1933F416D60DD31BC70E50721B5D9AF5D36593B
+4E42DB695B6BAE14DC1A34B480731D0AB8DAAFC7AF10F9A1F8E16D757BED3DDD
+62AA54B68463A1B4FA1D2349AD8C6B581B52373C444FC9FC57CD5903C76BF3EA
+C052B511D96A620A11D6533093483ABD264E795B7B2B2773C1DFB8B412E3D8B9
+AB3BDC5ACCEFAC42B1ADEA8C534EF7020860FA9A63BB9E3ED8B4AC4D5221F795
+66F9ABE68CE5F160F2F4A7E247CCEDA43BBC2FDDE31FE7A2B4EC56C294E42D11
+EC3E75166A0486F7B8652F2BBA9C3856A20BA4C2FDB58EF7C4ABD9EC4312C5F5
+A41566EB5611FF52FFE11DF40218EB1FE8C13B0FC8149CC417AB2029E3CB9B52
+79B55459A2EDC81AEF8EB54D13F8235607B5105F4EA77D49589629EF70A8D5D1
+BBD7836D5C402476D1AFB6E196A89BB3F7AEA1597792D37D370F4BC19EEA41EA
+00D9B2ABEE8EDA8641DB1AC5AE2FD29C208D1A0ADB4C465E3A8A5EAE18544697
+04279C6A0D5D93E408BE2CCE8D75FE2A35CFB8D7B4F9AC5424723A38E7D8F37C
+16C8B712A7EF6CE4E27D6E2E9DDB6D41C9E7289388BED91FDAF09CF6C9BE401F
+94D39963A38A5EEC4C937026170E0EE9271C9549F19FDADD2DF72B13A00D7A8A
+44BC326794CE776AF89CBD474A645947FBFB29EC431E9DFE81370F3ECF9A848E
+E31FD0F505D86928C3FB81380B7EF2E4592442455041810157FAE45BE7280CD3
+6DB6A062213220A520C146CB60D1135BBA697B789C98640585AC0876EEB9010F
+A1415719E0C652604A118B54F7C629DD8B881D71756F3701002A469D62B23279
+B94E3E63A62B10EFC7190F9961F37CCDF48B36275B0CFE086E341287610BAEBF
+8C8FEDB5E28BFB3BA6EB6EE3F1052CDBCA9014F0D7ECB292F44D4427BEA3F39C
+6A432213F7658B4FC0E2D78A98DD30927664D1EB4F2BD071B73938AF86B5F52A
+2452415DA9B20C472C6A28B0A0B3ED925AA20E8009EB21C158FC2B1EE3AF3DBB
+CD24F94211A8A93C9F2EB74C46353E60D0AA8AFB5E428324481A9DA336B021BA
+28891331E6FE0254CEB6706A193106D5CFBAD1A8EA4F7BF13DEAA63DE0F48533
+4DDFFC0B14764FB2DD3397D0E3F39DCFA3396AA1922C08EE331B2B758C83EF4A
+5E9C39CD869AE5545817F70BF0FD41C047B635CC5D5592C6BDC563D3214CD19C
+F926EE1F1817C88BA1370C72FACCA14AE14EA0517D9500BD0E5ED727CF0BBFEF
+BB314830AB7A3F4C0E3814711A67E4E3952ACA56FF20548566012E24B02C7CCF
+DD70718413FD054C4FC92B390B4424930CB273106DDD53B736B894619D9D200E
+CDE1B27CD05D4BE4F935C5F3DDEB4C9CC9BFBAF603ADE044824476230DBB51C7
+83E37262D67D9470A064DBE4AF8E4262CF2B43ED064D86502C05DEA86EE9E1A5
+A4142870B680AD40258204BCBD6728509E15F78FAB2BBECB5D571FC630F1DEC0
+A8A341B7E330C9A0053A166BE474E8CBCAD139FFAB6EFF4938C98CADF2B6B64C
+EAA37E9A72C0321EEEA55B35906B957C3C2511FF2000DD33BB7C9C58DE3E4F82
+4EC7E2A0F2E272305AA0EFAB70C545B5B3B7C9B7C2D2F52F2C9DA8C099E7CFAC
+B101EE39D0D65C89689646EC6B74055D0F6CBDDB1F7A53895FEF5353706726BB
+586FC64B77AC5C3AB5CC581D58E8627910497562D277879CBFC3156438144CFB
+97D28D067C73207C30F101210FDB2E0B6097D435FD2197B1AEA0DAFAD83B786C
+735762234838EA2FFA35C39F367982A19DDF17F5ED297DBF970B9FF0043586F6
+7BE81E18A34252B718F1EEFF2BCC9232D355C7F5D154F48BF7BA9AC0787B2750
+E5C1E646D8266153C44DF306B130809EC984DF94A2D0554B6CECD04D7ED6BDA7
+72A56328F0390CFBBE36B2580AA83E6987D26AE4C58123088CAAD46E25D55CB8
+FBFBA3CCAAB74958A4F40F0A608574013C70B4C2730B1CC8298E2F40981E48C4
+6408E167D696237F9899C84F1EE227C371982652CEBF0EAC169BECC25AD7EA3C
+ABF0F7B5A14674D9DC0F8159E57DB19E31964FA8D2646F514DB963B22240DDC3
+51C3399785F8153CE5FBB6D499E97BECF1A24F0FA1210EC51CC5F2042FD09317
+EF5E641E17C501309AC0BFB11700CCC7740A59A8D2BA6D7A9A414273A3C98A07
+B9419BD6F9DE4E85381BF876276D2C13A73E81488D856BFEF9DF4593106B0D51
+D4665CA073BBDCD3D4F301954E46DC913DE49A9EBBA24F0CB075A282B0DFAE50
+6C18914EC448E3DAF27D2DB066626D47497FD893E324B468F2A13BD6E814EB07
+8323C7C2AA87071251B909FFFB5DCA4E1B892297D765788F4E938A52D205FC10
+C55C0A3B6DAF8D3133F46117D9E71C8CB16A6D981AA84393D852BFB5FADC5D5E
+8CB2B91EA1530116F9C81FF31E4F3A20197CAAB7279F0568EFBA2EE67F933338
+789C24BA3E74DDAFCDF6F01A8ACA489715C0EEFA0FDC5A826B38342FCBA7025F
+3EAC9F6C65BBC6753BFB4F7D300020F90195BAB56722889792199ACD4494EBA2
+72A36829572DF2C72EF2E61F95D603B80491832B3E8C8D8EA2E6A71B5F00F7C7
+574A3C863612630323732596044F042BB94710672E1069D0157840363AEF8F1E
+D480693DF69F705A3CD64A700650F61182B36A95DC4877B12C37E2268DF855CA
+2538FBD173F362C8BBC7C33AAF04A6E9A882CDF6F950D12DF7F04D4985940CDD
+60F7B5225328E63228D4316DA03B1F4819EB374565B51DF1073AF7ABF0AF43A7
+98C8245758C942D45BD8D59BCF0E833ADF180470D3ACDF163AC926ED7FDA99C8
+450D986A7C7433A25D5970787F13D820A6199D8453059D59E4F381530574E1E5
+8A72986FACD57CEA0719DB404BAA0FA0EC5A707206B8F68226B081173D52D61E
+9E1D33FCB54D826CC4C1517D5C4E8661A6EAD9C8785ABEFDBEEC616C588F0C96
+822CDF5F15C7C32CF4E3594EC06F129AE00E92E84862E8F89220D34E99C610B8
+FB97FE59471F86749AA569BC8D13B17614E019F16EEBC6FA52A0D5717F305D8B
+C4B5624A7C448FB7E603DEF678B3C2727D101243454CD0482C6FD5B1C8C7A339
+CA270A5936B1C9AAA00C8DBFE3A35DB168DE88157ED9B4AF8D8EF9884A4AE6A4
+61CB141C9753C039B3F805CA4C0DA2BC23D6072AB95C73F68C5C043B791E00BE
+3F307EEFFE7425317DF44936E16A28DFA3D29DD391BFEC352A77C1B5596D2A5E
+E59AE2D3FE0008FAC30A19694F41A491E50994756E0422B7D911146896D1128D
+B0C51AA29A40DF79781BFC9B65AEC8AC9F8D5ABA6623096E8FA6E500B7FA183D
+475001CDE84C6F37DF6CBCD0587BBD40F91052324CD82D3167704B77E4AB7CB7
+23D65748640420B3512A97A3F2BA94AE5CDA4F354A7D1F4B4602D5B287CFF92B
+89989D5FB7BCF6E90FF511A33CC436146A90C05575EE1D83EBBC87CA4099D15C
+EC51034C4965AED230A9C17A9AC20FE1CDBAE57B5D2910941A03315D2826C8FC
+8C5A04C1D601EABDCED9B77B9977F3B78C6A43AD8E38681F64832C22AA0B2584
+46A86A6D1889446C6AC4E04AE220274D1FC389A68CFB19801FCD07F99943112B
+A67CD3AA77D6D51DF9E4D87D86A722C0F5F1FB88EFA80DEDCE56F1CE41600A41
+FFACECFD8EF1D33831FF44C120A52D0D6014D9BEF28D2DB07AB166BD091BA956
+AB54D02410632D892EE7FC47660740A4FE92D7CE736FA5F80D1B6E1267D7801A
+67AB4DAD9F30D061E3DFB67B6FABF4B3BAE9D65C6F78B379B3C9C29E838B569D
+D74A3B4C01A5857C61EE3AF17E89DDF576746843B3C4A3663E59170D9BA20892
+BE4106C1ED10F127373B6010A99B148A7EBA061FD9F9423CA8FC89AA0AE434D4
+BFD47987917E1BE0E78B61759C635CC812877047009DD777315B67A6A319A12F
+9F77928E2D76C191B49ACCECB996584FD390DA101B4E4FE25DA8CE592A90C71F
+FB7D10B954CD8BC8C79EC06D5EC1507D096C83A4BE59403C1B47294F62223AB9
+B398A6A9171269D7B540C50927159791060EBD9313B28B63A2B1BBA724D9E13E
+AD00F85DD841D5FABE1D74F94A7AAEB1DFD291AD6FDFE21BABDFC105F3DFB700
+89C119DB049F7D16B616BDEDD6486A2FF06F32036BF0B5DD79B3A01B4EA3A53E
+914A237B0F1C41BAFA69CD5B914DAE06B9F3EAC7D558878A5454CFBE2D38525B
+253CF5C058F661C67A652DDBC984A68F4DD866EC683DA31EBFAD03EE80BA7091
+01438BD3A3F8C65064BC3AC98909D6979A515B572FB0517CE383A154C90C430C
+E06768A3F6566C043B8605AC5DF1562B788A411FE73F5C5D11564934D4471019
+0C515D6198569C88D3CBB7A72111D09C5DC5FF3F50BB84CE196652BD1FF3D97D
+95E9C715EF9A3BF183D16C275572467A02A4B1CCFFAB98EB4C1F914C7800DA51
+52565CF08B3BDB3277851C966A14D9E9328E4D78F11FECAF8E71B6A3684A0282
+BDA7C8BA0FEA41162E2114F63E78B7E596FB6D545F77D904B2D9B32A0F666C26
+0186C4375B079F29372CB394082F5A43E137C096D1A599DE985FC5CD47C18C41
+7021800451593B50D8CA08739801C5535C4E3264E6CADA9CFBA4B05987C21F15
+F81AAE21DC8C9B437F53C90F92483E1CCA54F924EE5EA259B261FEB009292CDD
+5C355B84449B4AC913B4FCD5EB71A8D3EE7D77952562878C5166A1C9E4FF22FC
+167DE9CD2179B69AAB8B0AA9CEF53B792315CBAEC0D513B5FAE89323A5CADC6A
+2B32859C5281D6A740A36CC63FFAFA1255E55A9895A76CB7CF71F432E49956C4
+FABC749C776B3B8C6A03FE0588339798B41F8F5E484A58263236E6186652653A
+B2D7735ECDBA6DE201856DE24C2F4BCC42CD9D51F6F42FA283909FBC9063D619
+B9B257089A9327E438FFCCD4AC70F59068D26FBE8B8EE6E788C6AB9E7E29203F
+9DFD3525AF79025F16E5DA7D94BA86F2143A7157F6A03D70571CBA724A0D2BCA
+F2AB22B9FBC1A20594D0C9FA7F49CBB3A629A548886AB3845DE4434FD9A4EA01
+83C5C78F5330426DDAB35B4FD402012C0B05C2FD3673151384BFDA297FEF8E74
+54DC6742A24756E1FDC69B9D7E5A961A16093EE4AB04DD4B877497D7A8144A2C
+3A80501705CDA7877D1D50B8EE2B2C97549AE0AEBDA9F4352E1B6BF512D5B6A0
+CEC79DC26443A400CA3DA85D1D038C176E67241C6983080E7ADDC7806DC058DA
+FEDFCA543A07A625B1CA963C9578BD5DEC6FFB468852C545EC4904B01BBEAA4B
+E6CEC3D395091573260867CA11D0E04301B94C80B9EEA7B160B9667BDC2E2761
+CBC3B87D3E8E0A409B3763BF2788ABED367483E68E4D37BA44752631B106D8A7
+4760921ED93EB618E188FE8DE96C3D9152D7CE8492C3B9A044A812DA092ACCA3
+1DFA29C59E39C5384548A7C9B6F2F91BFDE6C35EC1A969C3A4ED066F40510574
+94F25777B103A1E7ADBBDF8E09F174FAEE2909D52AF5F1DC7CB3FB0659BEDB3A
+B99D62939070E00570CD6EF89C4687F536BB72FE7AB0FF741833BB0A60E6BE13
+E1C5DC0FD20420877FD4C39412DCB19E738D6D405A03C568F82BC72EE475A482
+FD6A8D6EF13997AD8643B84F46CBAF446A1EA1653F40CFAF3843A03E010FD3AE
+FD09AB97CB5016589A9812814A4A6EA108332D569FE4854765CC72C161D64B8A
+E14971088EFD968C0BDAC607137FC3C7B1438D2EAA3E12A7923250989F6192AB
+B712B2A90F3CA5A9EF3747769E16AE7BE14D08688BC96002CC2AEF87A67E0AAD
+4F12C061F097B736D464AA0CD842C792C1EA19D37D243B675FC3484C1707BEDC
+B2C46B0EFFADCCC9F6A9C9DEDC2970DBF831FC1C99B0F108BFEDC284F64FA5DA
+628691BED049FAA82F7DEF60C3C975A452D75D49B36F3159219E26D0984EE42C
+5DBDF0853A101F4D2835F315C64F727838A75B13DF8103578BE466015EF7ECC5
+0700522F94EE04C0253BAFF927B3DF27E641AB961ED9454A4304F87BD22D6C49
+21707DF91D903F3C68ECA78721E77F26099A10C303DD6FDF636AD9FD1E648584
+5A5ADE21B279028054EC9085A18C9DE16B8E263BBF3CCDB15D4DF0CF2ADA4236
+3FC37A4CCC959B5502247D2652B231BF0B4604041509DE8CF5D59B58224A4FA9
+B322420A266B2EEABDCB846C9162D4B490E0EEC0E21C3FFB978754976F8F3F44
+8600BB14B959D50E0A3C729431567F825BF7B8372061B3C96CBA50A4A3132C06
+1CD2AF617180B9EF00DE426E23800F6C452F9DEAE99B4587CABFFF621A6EF786
+5D423A8415A250A7B676DB846A31524A783A407988C79414C7A6855FB35F04DC
+EAE0D9F9C559D60A1C16E41825B80FD203A7816E4F93991DB0C2A1D45548443C
+642D7BC114E133DD21628F4E455A4905127CC85965A4CB2896B713570AB76B57
+BA46D1C9914D5E90B9908F72CCEF290418B00EC22794619A951D4513DEABD376
+D80B71669B683D8BAFF3A86487F8F83B77379CE0C1356F16DBE8468B05B5A4DD
+8A8A3FAE67
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+%%EndFont
+%%BeginFont: cmcsc9
+% T1FMT-V2.0, Copyright (c) 1993,1994, Basil K. Malyshev. All rights reserved.
+12 dict begin
+/FontInfo 13 dict dup begin
+ /version (1.1/12-Nov-94) readonly def
+ /Notice (Copyright \(C\) 1994, Basil K. Malyshev. All Rights Reserved.\012BaKoMa Fonts Collection, Level-B.) readonly def
+ /FullName (cmcsc9) readonly def
+ /FamilyName (cmcsc9) readonly def
+ /Weight (Regular) readonly def
+ /ItalicAngle  0 def
+ /isFixedPitch  false def
+ /UnderlinePosition  -133 def
+ /UnderlineThickness  20 def
+ /XHeight  526 def
+ /Ascender  694 def
+ /Descender  -194 def
+ /CapHeight  683 def
+end readonly def
+/FontName /cmcsc9 def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedblright put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quoteright put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /quotedblleft put
+dup 93 /bracketright put
+dup 94 /circumflex put
+dup 95 /dotaccent put
+dup 96 /quoteleft put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /endash put
+dup 124 /emdash put
+dup 125 /hungarumlaut put
+dup 126 /tilde put
+dup 160 /space put
+dup 161 /Gamma put
+dup 162 /Delta put
+dup 163 /Theta put
+dup 164 /Lambda put
+dup 165 /Xi put
+dup 166 /Pi put
+dup 167 /Sigma put
+dup 168 /Upsilon put
+dup 169 /Phi put
+dup 170 /Psi put
+dup 173 /Omega put
+dup 174 /arrowup put
+dup 175 /arrowdown put
+dup 176 /quotesingle put
+dup 177 /exclamdown put
+dup 178 /questiondown put
+dup 179 /dotlessi put
+dup 180 /dotlessj put
+dup 181 /grave put
+dup 182 /acute put
+dup 183 /caron put
+dup 184 /breve put
+dup 185 /macron put
+dup 186 /ring put
+dup 187 /cedilla put
+dup 188 /germandbls put
+dup 189 /ae put
+dup 190 /oe put
+dup 191 /oslash put
+dup 192 /AE put
+dup 193 /OE put
+dup 194 /Oslash put
+dup 195 /suppress put
+dup 196 /dieresis put
+dup dup 161 10 getinterval 0 exch putinterval dup dup 173 23 getinterval 10 exch putinterval dup dup 127 exch 196 get put readonly def
+/PaintType  0 def
+/FontType  1 def
+/FontMatrix [0.001 0 0 0.001 0 0] readonly def
+/FontBBox [0 -251 1076 750] readonly def
+/UniqueID  4701553 def
+/StrokeWidth  0 def
+currentdict end
+currentfile eexec
+9B9C0887DB83FB1ECD8335B0BB39CEF0AF64F656FC6E5C230CC9D3A7346AAC7A
+06BD9A40393CA15D3773A21E06B9B4254D3050E90726BBB09120935A8D448CDB
+C799D90205A21291254FA633CC0C2ED88781EF21A5D45B72445C284FA44F8F39
+CF566976075A92E9E2947A6FC93D879C29EB26809ECB4409CBC8666526CCED92
+65DE661A2F8B0A16BE45A9DA17EEAF89B0E023DE2B0373DCAB997D60B7D7DC1B
+4F7E650A2A9F13CA0543F3B080AE33D65F2802B8C5214D5B6180CD886ECCD253
+99CC16C5BA51CD8C2F5943EF3B7FEBBC41F6951EBBB60991342E76B6E286261D
+E282B144F558FC13E776427AF8A7B2589A50121C4E28CFD74A2F2AAD8F44B6CC
+8D2FC6C09B196FF2F3B57580F2D92F0ACD7DDE415F2830567CE4B6560BE25202
+D9D4886AF231510823457D00E29D865CAEEE2F697EFF80BB5BFF89DB01218A17
+F1FE570DD273492DB3AF7ACF86529ADABBE036A7437E7CA91DCB2E644C563D67
+0EF57503EEE64158B375AC18F3039284C1E3A18EFA72C0FF89FB1648F8ED3984
+C8D3862EC8C644C3EAB25B86127E6DC4399F9A9AB476B5E5A534E17E1118B4C4
+3D135A1207A11ABB75446E7003B42FAEDCF12EB2C53850AEAF1BD0A4041FB4E4
+0DA8565C86E80AC45F75F52779133381BF75A036572BFCD7E4576B1BF7F62C5B
+FB1652CA0DF458AD89456F5F941CF4BC558CBE68D17F1EC76BE523EF2708DA7F
+5FA9663586861AC907752524F88C1BC49F115BA3D24D0D7572A0344F761A7E29
+37E137614460C6BADF3720A004E277E7A0A618ED0D58C38A0EB68AAA09CBB481
+3C9E2073A5D5D38FDD0A31E3CB2399AD9DA6FC16CBA9A6792D02982A2C390398
+8D4AC5E33E7E91662D06AEA787ED73A95D7FA1112D074686F4DC2DC754D7C84A
+4640F61821067DE9C04E4E431300D7347C2E8161C050DCC61F298437A0F95A77
+19D1606BA794F6EFE48A250174C266746411C4603B4CA9CAFC536D180F40ED24
+3B45A3FE2501AA662247145ECF864EBFBF8D0A08DA4940F4EC99EC3CE2789A73
+259C061EDA69AE360BF94588A0165315DCF3FD644E74A6CCFE477C2D422D4C7F
+237E8FEAE77A96BC99C160B54EF4BED62AAB709007664BA919686F4415D1CA02
+1F0D4BCBA91257E1EDBC90496DDFB478109EF36B0363363064461028D2BC8DFA
+013D2DBA456B2809A488595590BA5738A7FD971FDF2F5D20B33BBF008B957D63
+C4B0506DB39F0C609802C6F7AFDEE93383BC960FFAEB5713C8ED2459FC4A855F
+8B57EA91CE30F65D1872AFBB811F3D9BD15732641AA0CE1206D8CEE3DDB0F2A0
+708A56802B0C5B375AFA45610C507D5393E9C627D728340DB00D37EEB59E1427
+3EC105AD1D5CB55F5C1A77B2CF839C857AB62998C6CCBA2614614373A1B8F1C6
+F77D706B3FDF49B0C40E292B40B113724184BB36B8BD2A0F6866A34DCA624228
+189F6C161F80208C85CB721AD37B4ADF8E9669149B5D4B3CA903B4AF073B8749
+DA249AF5E7D2B421954F5BEC85E7750025D592CA10B7F10FAB381D7CF988AF29
+5C5AA2AFDC912CB95827D0A4BB558399ABA21ACAAAF7C829B25DCAA9DC5A8D54
+EEE83F52514C59DDF8E0CD72AAFE759520385BDFB077BB65BD91EEBEC28F21C9
+A74EE3917466D6EC4EEF2112259792B429BB0DCFFBA39690027620EE62BC8122
+676389EFB15385AA00B7A163CF872254C315805D34B4F2F2FF3ECACE5457D66F
+FFC2B68E45D8AE5B7AA8F8BA683A485DDCC20BCBEAD17A058514C887172C9811
+F2848607636A78C4C061815F523AEFAE128910D3A1368A56C1590D63DBA8DB95
+4A057427D5F676D96174A8251034A396F5A23FCA205A4FD1A221DC2E8A652A57
+957F6F91AAB9A1A498DAED793244971396903D8F2640A68E4799F6B65314B714
+6954C59C1CAD073C968FA30522FB0BC9384BF02BE6446A0F924A133AA4651F5F
+78AE452288AB82E6BAC74C269001C3C84F3F2A8AC186C94D78529218CE820484
+AF9630B17ADC5A9D775DE51FB915265B6A1E5BB85B8C798FDB6FE8A6B6F8BDED
+B587380049A581A4F39CC45B1F4A5D686018E627ADCEE4F9F670361C6F708E1D
+B6F8A95DCC1048EEA22E28E0C311A394A9AEEE405320400A8B2B0A615E2B36E8
+A177871AABD0895C92BF702527576A3491BF02229B28F89BF837FD36955EF049
+FB8C0AA830E7A86678A69A87383F10715BD1494482034ADA7198A1B1A897D32F
+811B500CD638E3FFAC6EDD67052C3CD2F3B11CFAB8C804FFE72DC4E55138B701
+BFDBD227A50C355B07689A3BB3B6BDE072DE9F98FF0352434FB04DCCC619AA17
+127C0DCC6244BD9086EDDBA102D5C67610004657570182F7900878C8877537C4
+58B1E0FEDBE52F4671BF057B897B8C17AA1D8FA79B8DF2DEC5FB4CED9753E8FA
+C5494FFED4283833B2F92A94D7890AE116E99D75BAF8C78C4C2CF45482571064
+E9E589D7C5E195BE5C2C391AED066CE4F180000006312E6AF84BBF6388AC006E
+EB97A12F239140BDCB4B782FFA4EC629C1BAF71C61AF96CA5278F83B9609A86C
+83774F66C3FEF89CF200092982A44C1B882B8F50F1778639F6C1AE966B2B36EA
+1CE494AD85A64F52CC6C9532DEDF57843A4282EB59EFB7FE94927EC7598EA30F
+8F6A2D0F916C1DA7757CEA370EE057967220E61474C71D1CEFD958F816F0991A
+7747B0AD5EB94D31030172C36518DEDED362753FF1C79B4F08247F6567E2614C
+F390AE7B78FFCE142077F01BB297B89C655AF5E6CF89B22B42B975F7A6CFA3B4
+17E90FD3F71AABD1955905A37C66F94141285398FB31AC9BAB1A1135DF1F9748
+247734D6BA8F945D8ACB8FBBD8C879D23D31E216662D16A3CC3AF875C96A39B3
+EE96904DD2E49534791D1772796FCA4129D97E9DBF14D8840261561EF1FBF602
+9966CE0B30FD010B07026B7ACD566D374220ACA7BC884595F95DAEE27A818849
+810982488090BAAED7F0B768417E510BADFD4ADB569FA3C879A5AA8474B600DA
+FD7F986BE65759614BFDD55645B11D66378C490BAB8FD660E27E5B3762D9C0B9
+235D771CC51207FACADED47894F0AE075E3696214C9FB7F2456260B5FB02155E
+C724F5C00CCF06892F076C90DDD6378DF26AC341EF6E54AFF0DACBDB989406BF
+E43BCA29754B6BB39158142624DFBF332337F2B100FABF6CBC8EA7FEBF987145
+767CA5532273E7AABBD4678596FE8E0C4073DB776C16E0D28F941D0C0EB1019A
+F6D14DC0F67CDEFC136FF2379DD5684AF943D9F75734496F42E1E58AA9EA2EF0
+B767A58726A5E5E3A7A8EB1068A0EF9A2CBFD99064A1E5066006D70046BD5BFF
+AE8E7392ADEEC401E99610ECA89C3BEE5AB4FFC1B9D1EEAD033F049CD50B2DDA
+499192D92E0253470EACA68E52D96E747C172473A95E49D33A4FE6C23C490580
+F92AE6BDA56D0F1B6AFFAFF1F6BB81BB4B09587A562C3BCFA2F6F4D3A5974DA4
+8C686F32193C2849CD9E179D7C632B9B456B1A87CBE4A6DB0AA09607E9FFEFAF
+8D8A4B9397ABAA9EE484D097D9826F5207B5D8ADEEC4F0F38782C06340470479
+A7A569A8AD45A806AF0F772CDD520263CE87E39EFF08BA7450711FAE22046FD9
+EB1ED2053C120EC0915A2C19A32AF1432FCED97C336EDAC578869E74F0A0A124
+2D37720702FCEB5C9DED771A5272604EF0CD3BF23191E5F494122440BCD4C996
+432DA0B3951B7930F2EAADD5D7DEB960932ECC2428C28FA44288F2B53E16ABCB
+FE274DB85F462DD0A4F4A0C2960A6197ACF687C5AAF43E49DAD91996E2E194C9
+D7E6F2A050C41F87F98AA906B9AE85E95FDF7523D24965AA42BD255EEE0AFEA7
+91677C5363865A87138D5B9493EAD2802C78431D69225023E4C3147D7964B59C
+4769D96EB3813ADA3E77F4EF7CF90146A3E6CF7420F90EDF5661CD384086CAE8
+F5FE0A7619493F3BCC50998E0DCC31966EF0F799A5CFFA8EBB6065C4DBE04C5F
+ADE2D8499E00127D66331CE7F876BB343C333EE043A2565E1C834EBED857AE21
+6A9811EA5F44A402DFFBEA1613C43F766A6823DFA260F01CEF9A2F90C903AFAC
+3C76084F93716F1D2FEEAE9319168E049C9480B0E91631F41CB630C6AB4CE308
+3F24247F024114A8D1D758DF0F3543657C9FEC08BBEF2A8E62DF26A72230DF5A
+A0FF9C1EBD45F8F3A06DF0FF8B712313BF804F4DD2E7F9266BB53106A7C9446D
+8E301E3485E423BF6327544F41A8CCDF71CEC9F3D41DA616D23B489AA4E7A987
+CE859DC75C8C52F91D91A58DBB09ABAD54580C13E403273454C6785675EB8211
+15AC407D7C1B80F7E29EF25BF53571D39F6B474D7146560702C87EF9AB0FE893
+9551C7038E09A77AD011E940907C622BB9E5F21B42DF2051912104BEAFD0E739
+2D8B2C0E0B2308CD7DBBC551D77F50AE17E744FF4CCA83ECC6E7473DBA2AC0D0
+2925FE52660A776D8B714F5258E8D42CBB01185753B46F61A29095FCCA403846
+572D0B929980C2B39A573D00BA26CA79672BCB1ECAFC64E2A24774F63117653F
+28BDC06AF30555410CD372B30027C2D1E0F6DBED51BAEC760E11BC846996B4FF
+01E741E6AEA7B404DDE81485896280EA2D7A97D47887EF7356A11CFFB7D1EFA5
+4DAEB1A11D6734F10499A98331263F93B1FA059D3992563C5460B34960AC0FB7
+D17680B7D52B2D29E0264081DB8A099361A331958833EAD0CA131989125B1759
+FA11CF20319C4FC8EFBD0BA1A157AC84FE92F9D68D19CB2752B7241025E26C19
+2207A525F4B883FAF3B59AF4C61065FAA43B334491F668CFA3F94F2D9956FF29
+5BFD3DE321A6449432F7279D563D937FDCDD27463C60D6152CE655E01CCC30F6
+4ED119E8633A164BE26D90151DD17F8A3D55EF562762D6B685B7D9F6D4EE0233
+63DCE5418E180D69BA1F40C431E49DA720769A528920E2480FF747F9251CC964
+5FEC318DA8738DA93A187BC7FC35F4CCCACC31AE4B1DCDE8A0E52AE65C389C30
+548683D6CE11F6CF3A8881935DD81F9893D7E511EE7EAB5369AD6FFB2E54A3D3
+25E0B992FA47E99CA2E85EDA0C81099818AD2B223BE7CA6C166835D027E2FBC8
+B4F531440A95FAB954DD729F85C4C5A2ECF6D35CB33265F2B2EAEB5C49DD7CCA
+87F0B7241A0D4A4597EB4ACFFD3E9F1A30DEC256A6CC0001332886CB7AFE56D1
+FE2DDD6BB7DE61972C222BD34B923B4A3EFA3559D50F88F3542FC218B50B2AE3
+8B88A89F8198482BDED47894F09B78C368A05064913D072C63070CD9DA18780C
+3D88EF3C0068515474834D5AE97DB3FAAE42D682CEF1E51F73765805A2EFA642
+1B2BB41D2A3D66A25A8001323DECADEDFF2BD679B6BABF72D3102B1E80FE0B6F
+53934A43DA1DE91844C8E4FEC9E3872E72EB5323268E034A37447F387EF4254B
+8F8F868A9F9C2521499FD08A9D22ADDE6F5C7396F1E728857B23CFE9636EC910
+2CC746A0A615E7F135C53CA869739FDD8445290BA39387B9501BEB2A9C5F7B24
+AA732F91FC13E5DF75CA853C1D8A294AA417C62094CC1AA3605D0BB8C023CD49
+A4DFC1C5BD848D143922A2B9193384D51496FF5D0C3D9EE3CE30B48A90EB221A
+83A203BD05BC57ECBCA6D27FAE87F83842E78CA500E1752499622445194399FE
+28C671ACE2EFFCB86E61A8221F1593BB1D37801CF5AC4EBE8A85F26ABBE47E52
+9768463D454144213196E693F47E40C40A16AF5010912CA50B005FAB47F3E9CD
+C18198AE197D5AE8C68E3FB2762DEA5696261423E824CB99A5C6CE8870E8FDA7
+19F19FA1BA6C88ECDDB603E2624AAB64CA5D817E19F463E3C54984FBD31797D5
+96E261351EA9B8D0CA9F6156040180EAD73A630DC2DF9BC7288E83B5DD9895B8
+36BE5D0EC05F57BD0DB6B73F05415B1C0389C9857D387842D31DDEFAD60888BD
+1A877FBFA1618A813DA8B984B1124DFE780CADC7E1D849A58EB1482E15F38115
+3ADFDE10CB4C5B266E947AAB42E0A02A98443A8B4F277442A16159BB190DB252
+C8E27456C09A219EC0B9D057190B7B882E9408F25B0C48126E32764BC781B358
+83D9BEACE2F1AD015A477D109F850E3E5C083F12EFD87D3DD7ED2536546D8033
+0C64B26E61BB8A969AC4D28D1F6BB51C4217D4D8211B5BB33CA1B5AF6F842836
+EDB4417744FED0E89EE95001E7D191EA2743A43E317EF272CE15CDC234E5F6BE
+680A41E4B58D84676AF3FB9790CBF98A8FDC3CA10203C0F0E4EB1B64968BBAFE
+1D03DA2CB88AB3044D2EFEA94B0992D2E07C6849C9E86C39CD4D964B5B1045CD
+5D58A77B0E73D1796DC07A4FCD6607262A11B4F55CD672F49F65D6E9CBB55519
+7AD359DECB1FB493E84AE5ADFADFE069735E828B9D4F44BAA6E298BA6F98DB29
+B1D4F9F6956C8B2BE8846574B50A1B2D06EC392C60429B762F1336472E768497
+D70D9DC9D0D4C121F0723E1D725F8A669AE44B2891F2AC0CE16BB0E65BC7C549
+4D15D8CAB38682E60E6FBD74AF35473E7877F7E0739A1D2F1DF39A1CEEB9AEBB
+1BC5564802FE41A783C7997512EED5A00767D3FCC384B8C7DA97CAC37E547D1B
+ED70138287183F8AE4F5877E16066825A8DE41377C93CE53DADD5C7FBC3A288E
+23D7C1A5EEE3B0ABD70EDB1BD1CA86BBF083803DA04ED7603195733BB51D1952
+0269192362B338E9F6AB3DFD1384A9BA22E16E2E160C621D20C16DDA5BB93C63
+ABF409EE25B160835D7E55409A7A7B65B4F519248CACE4DE7E326FAC6E9D79E8
+9197B6384B806ECCABD44388C7A911BF60F03084131C2EEFB53F75C4868EC380
+5B8F7264061333F2F236DE20E59DB052CC7057AA867B49EE9343296241C6CB6C
+C1F3664F3D4680A4F337DA52FD775CFDD5250384D0E17CA46B3A32B6F6E91182
+B7D7C16230AEA9016133DEB70543C068F4CF66BC94EC6E35AB48E87690E7180D
+2D79B85E57F3AEE86A4C240B417B3A278A66615EE97C96CE6652CD87289A7B93
+0509DDB0BE2B9F10CCAD247ABB6BD9C4A1536CC2BB71316371A3CC92EF2891B0
+0D2B73EE9C177B82D7F3FD6C097DC9A80D12665F8B8DE6972D877995EAB5686E
+32E43D1B3E1166F8A54BC121FB6768C75010CD7A06B7CC246E01957160FB6D1E
+0F560DF3E13870D29E69473F1E160A83F58DADF487C91587DA03FE3DBECC4BD7
+47463A6AED62657358BDE5FA2FE64A830CFD7D2E1A1A62BC6ED64D7E3411CF8B
+3F64DF1FF713CA0D4335FB6BBFB3FD81DA8DCF889A17786378758E473A8E1915
+8B2E746F9F4B6C437CF316BAB7A803416FF656D498593995A161EAAD1A5C3F66
+33D8306FD30F1A99E555D7E5BA9F105190971A5CC51940BB3EC5BD7E9BA0BFB8
+9509200B67475C4B62C78D2F7258323192634CD895EBB4FBB6ADB0604E1ABC9E
+CD365097B29E4C7695BE1FEA9BE8BDBCD40A7796E64874997EFB8B89EA18CDC9
+AFE589BC15ED790281A05C9AE9D38B439E16B7897CE9AAEF3E00FECF70C7C963
+7558BEC2F70DC3180A651918B6BCEAB07E14D48D561257659CDA05DB9EE7F00D
+BABC069746EDCD19BE906C1A8A77BCA105EA54E562974AB08FA2433663F286EB
+E80C4EC07B34D0D122EDFECFC0D3E089B4593AD63FEA93C545FD63D195E6C68C
+979DC2D454A6D185418DCC5822040496206F87FE0C83642F97568F2F2EA2B945
+252446BC1412AC181025E6B1B0FDB6B1382C6BEB199F9A104DA7415E90990B26
+6B2AE09B0BE58A8D3134FA2E4D2DBE49A25A988379323E26C26691F98AAFA77B
+95422519DAB484F35ECC882808741496CD5C71EE374DC97F1B5B0369DE48DFF8
+9CC61303D6FBCE95FB2EBAD303046D3375B91129F13C30ECD0F352B29AA73B8E
+9BBA5F849AE43B2BFA5DCBD05E645734A3E1F5DEAC5BE34B19E3B68B886A72C7
+460A773DF3604F5FB744EA9905AC65D756B9FC47745670E7858C83266BEE1C5F
+A2CC250CA59D8B04DE66BCF41487631D7E978C27E0BB998B8EB54208F0B21FEF
+D172AACD3F8E6FABC60E51FC105D3F6EBF19A2E1E73295AC49CE66B9F2F1BF5D
+0A1D8CEBF89121A4587E39BB62167DC15F4D32648AF0A43D8929CA8FBC78621D
+C3DB61C2498974A02CC340CC4A574F0E60152A0D4102B55318B07857C57D13BD
+B6111D8D8E9852274B7E649AC22B893A21508372648557FA2CD28C95F472B7D5
+3673874130AF14C7B9326ADECEA73DEE7BAA3AD842DAD823A041438935FB3D47
+FC8B4DE75CB449A90D1F5D94703C3B12F3B8FD016D95D7068A8F6C93FA932880
+2DDBEBFD7F36FCE1927547617121D03B1C6A7F496615B1868253594D03DB6375
+F6B77864C29C663AC6FDCB34B0ABBF559BB29BCAE4A8B726F01B38CBCFCDF626
+DCFB584F055E41DD29917297001147E074A3822B0B41DFCF1ED12A0FC69B3A1E
+2B2985125FA3AB6051E61FAD0B66DAEA287BC9C91EBA95E01055C0FFF4B811B8
+629B8D9D4E0D85653D64F9AE567EAA910EB8E9CE8CE260974ECC02E279AF8156
+6B8096F83FC9CB9B902EDF5B926FB8C8E86EB9C3A36CB8DFDF10F9605331963E
+2F4AD2F1F64554C1EE470E5E96BEF1E0CDFD4107B302B33BB7935B54C9CBA6B1
+EEA2A586FB09768C66DD48009E3C3D4C28AE2E4B9FAF12387889EF05061BC7B3
+CACDDE65F50DE176B15DCD15418173126CFD3F68093537DD43BB658216BCF65E
+A32358F888B0271A06DB84AA5BC03B10F67B7FF921689837D62591530D7E2F5C
+E4E34E0D3ACC218BD2793EB6C5C7FD31F0B2D40FB0C60EDB0C9883A4883892B3
+EFA7A3685991CA4E9765F6C0EB6231D89CE48C917E632C79681369BE19C7BFC9
+9B70F6333CB91C160545F827BFF527D201CCBA409DF6F61CF6860B378C64C57C
+19644BB9F05604A198EAB9371F5E16A17E610AE4908A76A739CD587C2FBFB87C
+7872C2DD74D5D313D22B33EE2F64A5062193B969720560FED6D2E6F284179D43
+6157B02BCB075FBD34D68335D8C6E190DED3AA46B9F57664F5F4EB7D3734DD79
+7CE8B85E8D2DF7205C6D92BC2946320D21FFC0E89F7832B21B3FFC04B495E015
+9A741644AA80DA77673CA09453DCB54DFD8A7CCB0C179F8A87F8809FE19EC6E1
+489AF10ABCDC8F1FC85AD101D40F186234306EF0BD631B896D4BE6F475A22820
+B9F4358C1E58936C8085B216FEF406CBE8C010E9024D4AF9282F18A927838F96
+C72C75935E67FE707A728821855622B393F54C2E5C6512795ACC687F028276A0
+E6022C7C48A73DE8E1364E6EC7E9109B9FD3596002E9DABCB9985E9298DEFB1E
+A6E649AD2745FB77257C1F6A61846C35CC7DEF4207EBCDDD6F76398CA95AB7D1
+A5A88EC11A0709467CB39F287AF7A10108630CAA9615DC227AE76ACA2E53233D
+AE2C4177A18FE832AB80EDDCFE61045790DAE39365E6CCCDC8E38378FE947C86
+6B6DA30DEAC6DD565550174023A2859820771B1854A2E9FCEE82BCD94F2B914E
+C4011E7B4AFBF1FC211340C8E5A66E4DC1ACF66C83C2E3841434F4EB2D76F0ED
+C1A62DD5891F809A5B8C6D7269E8165122FB4E8EDBDA9DE3BCA562DEA2098A96
+5D2DB6E41DAADE6F69C0F02AF0E05E74AB2163371E10E4E199256ECDDAF9FF5A
+8AAC829B9105B79BA863DADCE4ACAAE5351A31543794C4BA54C862DC73A4BB42
+213CC668576C3D6D8D42D99340B491402F0B712FA4580922694DF0A8A463D3FC
+051CF050C124BD1F730D762BA23EE523D95AAED4FAB9392153E8C6B5D75818C9
+2093D642AC8627DCB3E287F45D62D1AAA4BB6153CCC54F2504437CCAF1AE406F
+919E2B51F6F76AC51987935574DB4A6109CABB006EBEC482662A344C2E72DF86
+049AAB12F3016FAD368106BB0A969B85BF152405EB5589E4BD6385B1BA3010C7
+D7FE6A651A1DC4B732C61E084B4BBCB50B5F4165FCDD3B7D384D61C592E65770
+3EC9A658429C3E96C940C2A2A7CF4BFDC5E61CDFA533BE7BF3B5154B3DAE5441
+9B3133B96D0CB64D8E55E89590A50E12B57C27FD5EC65D7632E9861FD029DC0B
+B05CB0E6222371D7D2D0D6661BB041F234A114BD422526385F52FDAFC016792E
+283EEAAAE1F6AFDCB46A9051085BA0FE0EAC7F6B812F5A6D65E9DA6713AF8788
+F4D14C3EE931021F8332D282A933E95C4882A3E12C4A2BBB7BCADBDDFC1F2662
+6A610B79E0B7740342A2317271E931E4D1C7B5B8AB4E9FC40AF2E67B93D540E8
+45DCF039564AB39151F4EACE7BB432929B5735CB12D731DD3995A2EB3E919CC9
+D79E0E329D5B8483229E013330DC6A324C83C685144D411803CA09D4A36887DA
+3D030AC820EDAA1AA767F49215730076C47C5263EB5061B4B9B5A49B7F2F325B
+1FE2A972A31909451F9611DEF3D1131476204E0FD5E25E90D34BCB9518301FA3
+FD005EEBDEA8A1D0F808C85FF5088D6253CB8AB3B5C5D8EC41C97406A79ABC33
+21436BD15791BD249489F00546E3DF4083820504B941C6191BBEF6AC989F2C43
+CAAFB1124873C0B35278C4463251867DE9E646E13195827A92D83E762D3FE521
+8FF5D7EDB2E2B246AD90B2B09A0E073D1709AB0D1CEDC286AF63400E645F7FB8
+40F98C20954FBBA5ED1A0ACBADDD0F5907B5696D54ED5280B1EFFF068DB13534
+B071D44C77DCA8C17D0BB95AE85B2510B79452062CD296ED62F7034C95736F0D
+3CB5A9B287787BF8C5738F5868CA3570DE56BA0502D55DEC9E9A3046377F2D59
+FC237ADAD36C22EEEC7B0222F45D6DE06486D165A9548E07FC8875957DCACD7F
+648C447D3442DF9A9F23768E796FC85221BBD079BBA01A939D82F2489F083734
+A8FECE716AD90C4800BB8853D1C726A81031EC6DC519DB16C631445511DBF211
+CB3A67E9B51E8D2CD8305B4E914C0DF2B6526122984747F23CAE19750D5D2894
+1D6788A75DBFC42F0EC87030924BB94E8A3597DCA4372A2DDFC181EDB7C145AF
+E4D24DB8DD7C36B0580C1EE70A741DDBFB49802E4C07CF1BC6A2C21801B1F8FE
+8C6CB6EC5F5ED20B93BC0CE0D9AF0AF29806B6E4551F0D5F585BAAD42E1205B6
+69E6B1959D4A86DD6895DED94327ABD889C3FA7FEEB7C240237BFEA12F24B5C4
+C9CBC9A3515FEEC3960F9EAC4122FDA903BDB15E2D70BE4E67329B293F10A07A
+031BE8633FE9DD33A5535E20CFAC263F614A00B24A9242BCF9DAE873116758A1
+6B42014BD0EB77652A4347478C4D5B28FF5AB11D794E00E4E95AA410E148F7E1
+F72BA05EA82F288E0D0DDB272F19B2EACD00C7CD37E057244C8FE2D6A992941F
+CA5C6C6B513635BCE0F313A1A81D62CBBEC88047D9E212FD671B033110EFBE7D
+28E2D03A41816F34BA815C39E3299B633DF2E6190D48F4EB8B9BB89FF99910E0
+8FC04444078109B1F5FDDFA32258341E1AE5D75260BA66A34CD4FB28F04DFAF9
+5DD3EEEC0837510CA2BF79D0024CDDA6217015152622534B85F0766E5A864976
+87EB1F38BB1395AA59D9F646D719894161F910D56E091585C76D273E3702BF39
+E7384252EF2BBAF3884898E6368FE9B625C2ABE7568367813BEF7B3B28149A94
+29FF02A4B0AD0B1FBEB0248634363B0EAF5D6F4BAF883BD554C374A3B02E756C
+6B087B042F2EF748DF70A2C48E22AB22FA00224E0B365C10ACC1F228556D3D88
+3DAFFE829A494CC8CF586D75458A4CAB86D157243AA3F3BAAFBF3FF594603299
+CB7D5ABF8D40F87B09BF449E93F1CA7C0AE4438980D2C98F738EC831FB992A5C
+C2A2699F8CD5F1B302F1AAB3C3151F06D50502CBBDC36E9D7CE45BC18DC591CA
+54BEABDB09BE80119755D0AC6D91356FAD5F76060ED0C66D353C96E2C3DB7086
+B16A6BECEF6A2502E997D4FE16B390F5D1C96C54C6EDAF3D80368FE691162F0F
+0BEE1CCBF682C480C3FC98CDCE768D5C237DF828389B31F15FAA56C017DCC9FA
+2619E2160CC66399F1AD974357B7B5E5972F8DFCB3034CFA59040F08FE1E419A
+193137024AD752B54EC86108596477C9C1BEACF049CB9D69C244F26C4FE5826E
+8D1094868DE869C35A2B58806A8533C8EF5D2DF21890F1A3BE3EA6C70D6D769A
+9F5549A9E965772B9D40F2A51A8CB350C82CAA20F7861C153EA82D52199A7C08
+39E8C6327D058593E0CAD9B32E9E69B8550C467EF83EDD211B00410C192B3119
+BFD6274B74DC63197584026A3940DFF551094608C824B0E66B4A95A58890AF4E
+934B3D39BABFCDA26D874F03E143E0BFDFE605512B46ADF223B3C9AA2A3957AF
+E4A47605B76B38F3076DBF918295678E85FD29C67E3FA09862DC663E58A594BC
+8B6E30C53A4BE967F11B97B26B5D554BC9954C0895A71EF8B4616832A428099D
+41F4340CA96DD09B612B4DE6B20EB05D7F7CC114E939D0A01049EA6B364E8A6B
+53111F3C842748CEE526342CC681CCDEE7ABD7F30C26D5FFDD279306142EDB19
+06C9A0ED4E8ED6FCFCD43776C4A6AA6F0604E5A5020743721EE05E71C6881DE4
+2BEA1C904693FA973D15FDF0636283D637F6C4D23E8D1C095501E6BC593AAE7A
+A53EDBDDCF4062A1AA8BC844278EE7CF540B3F4AFCC6659B5715DBBFF1C7173D
+F592920E68A0EDA7F176288572978DE52691ECAE3BD85FB91AFD10556CA2016A
+89BEB737C074E702A77765F4352EA49F9C7B1B8E5F981F5DB31ADD485213C190
+881036128F226EDE4D2D064374A6F66057C19A0580C2D928533053B2E3C42858
+46775EC712046DAE4650A6A64CE241341219FD92642570C85B4919CE4D2791A2
+67B29AE13C26699D4777C02C74CAF87D6CF0ED3D08AB508447192811B0E7F3EC
+F5032BBC3EFD618824D974AD5665904AFBB92FC18BF534691CE94346142FB2D4
+F28A3DC5B7569D48F2AF29466F6000574939EB8F3DDC6A3A618CA47446E95CBE
+0E6D95302D70C96FF92B7608BB3E18AC48AB71232D871772D17E3E8D0A3D1D99
+08DF0AEC4316CE34B72358BCF67F08DC71FBFDD4413C2C787679C5D4E983392C
+F21632FE23E5A6C2C6B6E11D3B225E852CAD35C85EFD2E4FED06B68EA1F8BA00
+488833B4CBE54763DF428D292032983115990F56CBD856D8CF4962B29E128268
+1720D2F2CCEC2EA69723BFED46ABC56F041E058B60027B5C3A66C355E8238805
+FBA5DD981FB3808F7F800E69A6B85B011B9F9B391E8AE835DE4BD5AF0880AF94
+ECF195F5B2BFC0A4B1911A421560FA20F6300DCC9E0885716CC42EDFB59F7F2F
+37CA82280D820D549B416CC00FB89E963D5861C8748CA729D4D37463E871A1CB
+5AFF926DFB7D2028F74A1561FDD799611EADD2417859B5D6963BABCA1D1B0AF3
+D3EFA530A87C144D18C7156DC85EFFDA40B2A77D41BDD3DA3950E0C5B677E3BF
+D0A50CF0E9DBEB3182F0CC7C7812B91CC5F057964E15B7639B6D99F7E65040EB
+9CFB300081ACE78FE5EC8E37837BA85009B2690D0B14C0AC1D1E6C1919900B6E
+84A2806FE2D603206FC48C743B1E8D7540EFCA33BDDADD5940D1E3D5B809314F
+7642C4124CF94D47B5EFC6174CDC00553C23123C24B53FE0979E7C83704A6381
+B0DB9AA8AA605DBC5B00EFB651B94FFBB3856544A9F0E05720728B5A79A447BF
+CF9825B926CF8503A0A46B837319080D7AF5C022A3E7D1F2C3C29E0D902E9AC0
+3F6931705301B1574510EA3A509981603B519EE5DFB8241D0D6C63F7FA8EC16B
+DE2FB14871FD6787FBEF560591456E8B26116A4CFD5214ABE046B18001DFF34F
+15A7E5A5BB7B6073BAFD8D65D31E59AA94985115F267A04FF7C2AFEBD64412CA
+8CD7B1B7899C53E7BC32F72B3A944D4A356495F9561153083C4C20F9BD23201E
+7BAFE0A6E059BE96D5EDFE1DD4CBA0B40F7E209E91DC7AAE8ADFE9E84C127281
+6437682C1457C7176E9B51F011FBF1B17911E7AA71A97BD55D920FDCCA9ABBA0
+D412F31EE501BFA7A2FE0BE47A98DCD0A36E7CCD8AFCC1608E0C27BB54B65416
+2FD4659120CCF13A28AA5DDE86C584AFD57EC9B257E55C40A4978F9FF17B9780
+A8C156D598F4DE7283C223A58EF896657E84577E60F1F702CC13E4464ED4C60A
+88B8A97AC870F8555578FFF82BD7063B2CAE4440C1DC4243ACE088FFB428E51C
+49641AAA53F1281DD70FA1E0DD48F790F181DFC912C8E9D749BE8E8F8B03612D
+24AD5D8E4AD5701149711CA838B238D487FA136A81D02378C0599ADEEFD8004A
+0ED71E38761224CFE7B69CDC20887AF19D5FE8177CE7091696BCB549A11E10A6
+B62FE410F38A1A71BF67EDBF86CFA498876E1D142524AF5A70D5973B3D83804E
+EBA95FD7529DFCE967FF96D2383ADAD1F8A5698E6455BF455BB23C0A5C07F6E1
+97DE6D8E2FC9462A82138BBE55045BD8257D6D1AF0D814D0D947505F4CA1C10D
+8ACF8824E299A7EB6363DCF86F76AFD3F41FBDA69A31568F88A7F6DD34FB6FA1
+2EA495E4DF6E34E1E954C223BD7FE152DEA01E7201DB986B83EC02E75B5D1A83
+2C267E10C43A2B989F1E667038743A4DC4533AD5EBB61954A8588F1AD914BFAA
+F8D9C091E36B87B6CA569FDE501FFCBE27BCB1432DC80584FE0F91AFD0C0073D
+E3EDEF55352D28BA680DBA8D33AF1BC8DA2124F7BFAA04D5179097AFFD9FF7B8
+634FE29D0DF784FBFB203EDFA739B305D5AD1DDD6A22330AA8A4F2663718F4DB
+F085555883A9F3BFBCD85BED2E5B88FCF16D122DFA6F52DC4F3A308EBFBF8EFF
+DF709C45B3306F9EB696E7DC0FC58B81D5E194FCB518E4AD4DFA8381D7CBBFC4
+3DDCBCC0BA3E5D448B12AFE9871CF7FB59612C487139E0B103881D46CA4F6E6B
+E0E462DACB8A69EBDE728E64D862A877DA51FD28D53F5C52D110D92C5B6E3D45
+636BBA91C29D7BF02B860128720FFF314776A1B96CC723D81122BAE381588AA7
+BB8F735C6A36692225ADE3AC1AA16EE8856B186BA7AA1A556CACE500B7245623
+25A374A4F01BCE3BF9A165CF37781606342E283BFF0C061D64771ADA815C76A3
+E946EBCE12695206BB0EA396AB34BD2DCF91C20D897D7A99754602ECEC561FE0
+7146CE351F1B9A9BE8CCF721CEE7579777FFF825ED8C808FD403F2E48DC8A9C7
+E98151E3D14E4D4FE68A39A56843B809CD654BEC9571FD596209EF0EA4D37CF4
+9BF85DC713CEF655311D57D6021F6D2FDC39B0E9A6CB3D3C07335CBD05A7A627
+4920FAA1C97E8A7B77590DE191D192CCA2C531DCD616A4DF0D5E345AFAE474D0
+A002546774F400F97E024BD19888026F8A7D78C5B64DBB572ECDC18B7427B824
+7247B7558D1B8F2DD30BE801D3295E6891B299CBF49F881A5E4F4EEE2FACE0C0
+3A73837D4FE5A0C48AD40EAE396C7C40041DCEBB76199BBD7FBA6142389988F3
+14CC7B3E7CFF331CE17718DF98D5868C7F20AE8E2853052E839700A3C8BBBD60
+8CEF9837F931475BCD6D7AF2835E89426356CE9BA42BAC4610A6666974FC333C
+0C28837E35B539D95F213698039C831677B011E74BADEEF03226A345FA69755E
+C79DEB00F894D86A3A6F6F25FF2FC808AB5EDC3DB4A0335B3374AFB993F131C5
+FB2C27097A4AC85648AB44DC2951DF5BE1E302B848EF900D15388DFE816C6CD2
+AFC28CC0953DEDA40FF5BA1BA22FEF0ABBB6B9C5886F5BCF37D39F871DFED145
+B751288DC682026E117A01EE06CC3A4448F6971E51585B89D2375FF336BEE56C
+32D5F31433ED3C32740A69DB94B50ABB3E8ADB24CC074CF6A00484CD811D78DF
+45BA57A7CDCE0B8FF5BAF56411CC9B654D5728CA3D6A90AF167975B4D6074371
+851FA80294C87B0B7A95C8BC7196084D86BDE2BF4015BBDDFAB4DE2C31BBB2C8
+C4DE9094993531657CA80286D4879A8D46BDFE0D151C2A2A11B6A68002C5FF2C
+D8C23BF5015BBD62BFB861037C64A5E354CF40BC04DF03D9C61640EBFFE1226B
+3E9BE0191532918B0679B55E3C958A9BBABE8A214A2E584B6674254C1C5842A4
+C7052454227737C9CC71FF2F201169038BDF4DFA4F65DF78C9AAD96939955F56
+A2C06DB97C2C6265B2BD4F8872257CCCFC7F5E1FB86D811DE77C684A89A1EB75
+F3F2536EF3688E57781000979D965DB1876C3BD55B9386BD9FCC5EEA596DAA33
+BFDC3BC5CF96EEAB5F4635F33A8083F45E79344E73B53D8A405D6AE48A9588C9
+04FF42ECD98CFA387F985F2C8698BC31E4A878C95BC5E62A262D2F5CBAFCAB3C
+9F3BA8EBE08BF93D73E95775D08C570B9AB080D4D9BC312A745B7EB455C1D6E0
+90A7072AAF3D7B7FD5114B7581DD0F46B32F020924995C71908B1E4EC322BED5
+0DEA3E62D5F00FBB0E354E836E3AE75AA46537FD2177DDA5E5C6DA4CAE9B390B
+D174DC84F24AC05703F640EE578567AC1583FF85CCE936E0499D822838E6D0BB
+F82DB5453A0C91FB323FFE8B7289ACE64885D2C7C5C0DF075C52FC1E738B5D57
+1A34A52C52C3E4FF0F16F6EAA0861048B3BC2FC588C05449F5A42602A77EC4F0
+4CF19DFEF5510099E7470D1254B0BD864FA634B7FDA7918BA63F2B88B43F92A3
+77F37D3BF6FEB38DA67776DE4743720F1920EC6723074C49AC14F4DAB91BC9DC
+F2D7337637D73157A8C7BD0FF88D0880C2F410B5A5F53D4F241C45C5576F9785
+A9D810A9B8F241DB4697E22362F4526294EE15FB193FD29F52A63EC4094E656A
+06A6E84347E4D47BCAA15BFF7D3DB02175CFAFE291CE225A613002EE6D8162AC
+6CAD256A8637172A4469B9CB3D570957E87E0817957BD75B2051858D7579D09C
+54EF49C2027BD532477B730CE703EC14C54FA2497712140E53BF25A4AC45A344
+DF16D5D824542E3EEC6D3326607C0EF862205F82844DE7E6B982D8C84981E142
+DC5C0FB44AB80BFDA0D3FC28474437E45C3B41457B19C6F1173ECECA4826D19D
+7A191D76BD376641C2EF99E1A9C848BD8CA250C9912BE5FC5877B88818D876E3
+6C095EF01D860C40B0FC7169FBB5AD992121EE6EF9BADA5B067E452D8FEA72CA
+20D4673D2E6310233BB66D52BA5E893A3177B20B1AA94AF16230482DA18CC020
+61A48695FB2DD30D83762595FDEDD1F21290871B1A2E82FD1E75396A2BE737E3
+6DD792306C62AA7E3A1B3541795F3322BA72A00061DD925A03244121CBF9D572
+BF4658620DAB84F46680086DD757D07EB4CFFA4D5A7F3D5DEE1D3156A9AEB636
+320AC7B07504607C15436B91C47EB7773755B51FAA977CB4F794A6CCCE04F0DF
+94DA510BD515FA0557BB2109B6A838BB28B761463429E801738CB4B76D5DF6CF
+2F36EA51D1247AA166E825D08CDA5F268E98639A79C721CA23D266294248E865
+ACFC113882E78FE7C7385F0E2C913A7E8838AD9C3A2E4C5C728237C2481388A5
+0A0869D6DFEA19FE7759C0D5D64266443529A1EC6C8F2661F72269D7343552A0
+01181BC161D5426BED82212DD9CECF208480E74ABEEBF9556A66DB3902E6A372
+A0AB02CBFF66B8FD896D8884084B271115C3D2F86D4BAB0783BE0D3B9BAF948C
+82054A87C5A1DD328E9215D3B8CDE33E978099595F6F2740679C200211580C31
+771C0F803B8B733D9716AF3B27970D473062F22C9742BAB029754903E0DED238
+CBE1F3B66E79584E19114B651A6F45C4E525157E425D34FFB976C7768EF8C0FD
+205F9B01AAC142ABD1AA336529005FB1091B6E00385BCBBAFB5E3C81BF3CDAD1
+6FF605F4069A34DC90A388FDFF1456826A7DF07B1F471DF49931C9635E8F214B
+967695E1E14FF05F743F43E359BCFCCA1153F7F253C1BE5AA6DBE0652B46ED43
+C0F3178A201D5C7E05E8B8BFAAC30E134B163E233176BA3FA06FEE966BC81F55
+80B2DF00322AFAAFFB56A986C3D6E50C87A73BA1148E8321693B65F64DE9C39C
+07729C7360AF458FA59717A71E142856DA36A9C6A0E78D8BF66B0CC66B4A702D
+70A0EAE80D3C75228C2E066445963073D4828019069420EB5C721A1CE57769C4
+48A3BD0DF632B4A4DB2E0012E0F7F546A54E4517FDA34E7B4469636B9CAAAFD5
+1753CCEDF14532414D6716F0DD4B297F294DCDF134511E8FE759114D739BDF9F
+FF77562EDC820D911924BFA9E7B537319EAE887CEADEBF0896F036BFAD4AED46
+657431DF132C3CA4596AE94C66ADEA665C779150356C0311F9DAA29D237D68B8
+D89D6AEA3363AEDAB0F7D8E49688AA561AAB9A751D0011BADE0388DD291D7299
+3CEEFFA3CB0241667BF429766C1C89C914DF3A7D4B97330BDB48E4256351B625
+DEAD87082F9A0E717F03251B4D53F33975DD7088AAF0ED1DB80E3B3851225D2D
+29A1F8B70579A39E097BC2254C55875232A33AC19FB8F86049C3FE21474FD90A
+B4F84D5E1D20F3B6A89B3EF996AE0108DFA485CB21F656F8D8930B5EA6F4C37B
+C25CADB2FD4C905E979CD8C498E42D68DB0285B121B4B38C7F3843492E27FE91
+72530B1BEE8CBFBE64F2FD1C83A46C7C8A106DCB5F3C9D205645DBDE03144508
+1F8F079761966F98A71E85A52D0BFBAE15CED8B6FE420BD485ACFB8350D561A7
+40DAC589FED2C8D53ACB63E8F5A0F00624409153E1ED583BFCAA3591BC7FC228
+966BAA1751CBB4AE1BDC8E025EA16DA2DBEED6F5E89FB8718781C0C70E5019C5
+36114763FAC3DD323F5354072E82D16B6F6C70335084D42C13A04E7BBF57F32B
+93A1EA17E434EF1E73F71449C9A2E3A4531C353F76DEF46085ED58B41FC60D52
+E8680297FB957792C40192A36F9D6B9EB12F30C7DC07EB51356CD557374C61DE
+3D2FCEC478CF4560DB80C80B5BAF1734BEF0E27B7A38557262444910B46560DE
+055EC7C6239E0FE8A1FD7658F4AC643C6FCFA2D3385F2C693374FCBDB8FD25AA
+91EFDDCFF35612832891CD2F565D1DD25040BA1F0A7DD668BAE0817A0CED19F7
+D6589866C55A79B2C31252001FF084D67141F87DCFAE18DCD8676E4F8018656A
+756805E4481A46D4EBB73A39DB6B4B9A8DAC28E83C8EFC69C4543A91726C4894
+CEDA62456A10F7C28C2839606EE19E711ADFE93C87107012F88419DA67677A1A
+94D25B1BE2BAF610869F56CC76BFE6857066A2338EEEEF0C4B3132E6F2261A7F
+0FE2F74BB2514EEAE92A1A211A2085D50C2CD914914ADDB5CB265C47E0EB99FC
+4480EAB881DFF9A41771DCC43CDE19E798B5DBCADDB39A91F6D4CD893C90D1D4
+5EF749FC2618918311286B8096E1A33019FCAD5EBBE9AF6AE8460529A5EB9725
+11EC7D9ADA84FA3B73CC02DEC5F18CF56929E3EBE7D634AA05260066B7DD1305
+E7B446C6706F3E71ABAD3403163EA42347E82DC3008DE044B861830BC306EE5E
+C9EAC9EBF6CC25336A5AA4B3FC86705C1110EAA31F4621996F56D084EB44DCE0
+012CD0D04861020DF932A40936212FB9B62344FF2E5205320795A2CEB3A93A7C
+953C2460B10F9FAE53813F641ADB94911A98B4CA88C44D07BF3A449C5FD061D1
+6E6F6278978E06AA7FEF976F6DE9090AAB7C85508AF36717503FBF12EED980E0
+95D309B901A928B40E564ED0385251493B93C8A1B1A2E0C2864E7FA56C70997D
+82173EE1F1D1E2DE91D122712601B075E81F60C8D807DAF40A6A2DB86FBF67C0
+C6A67E5AB96978EB78F45E588EC5CA78FAF8D3938DAF7574BD0C8A1E72CD4F53
+BD815C55D81BC99B9AFF67763EDE8233600361E8E47628D313DC5C8434659F18
+452BC080040371C3B49C6D3D8CDAC2E073D4A6C84E4510842B37E825188DE876
+B73F723A54FDDC3444C21E84486B65B184E446206AC6C8C488B0951D9B67E22B
+5FCF7D99E5E3BC571913AC5A2D2403F6BBA9CF20D9971F088669F500EF79E271
+598D63A40B87FF1DD53E432B2B8ABF0C42E5A51D418A6D38C1234A174DDEDA0A
+C2E412BDCE094ED780562DE0649914F8A4F5CE902EB34AF0B7373DB2D18A832D
+4484210678266D233EB9E67831E828A207E05F7589AFB820ADAF62D9ABB375DE
+114CE744527FCE2FA35D1D872F30208B331B4327B972341D027745C4B4CB20DC
+A7EC2686D157BAAF7524C901CD082BA51FC8F17E0B35743E189412F12B05E3FB
+16F26ED75CF6C2BD355974749B4C3625C070D0E16A2494AD1EBBD2A37AA3BAD2
+87B57CC1DB4F0A8854776559B3827220CE8F7CE17A0191507C40B2A72C0A5564
+1DBD6577DF18D4BB71BBEE0357389341A8FC781509BA47B505C9CF359C0DDDF1
+F809E0825F1C0675C44F998F857CD91B1B27C2E8FFE99D6437C502ECB4F66E7C
+7758154B03C3E44658F70AB0DB50DBD2759222D060CC79E1A0CA8D0481EBC65C
+FE1914118D893016D71F37B0C3E753B16993A00C8F7F994E46A73C7BA5262386
+B6D39491B2F18DB30F7DFF061AEBB847DCD6E6326BA7615E3DDDC8BE861C348D
+7ABE34E045BFA565905C868E95133041B57FA080F7508FE421EAC29F2F13B5B0
+7223B1F963788E1AAF42D5E441B06FF1B7A2467B86E05C4C90D94A824E23C529
+B06B3075CD6FDEA67E6D4D65696B577A4A05A4663BF4A11585819B85B6810EA2
+E005D5669A9988F9B287C981364555F5211DCE3A175DBD8E7A322E31B69C966A
+BE89551B84FB04652290AA1CC07260EA4E5814CE910D2C7DD48357813D9EB9D4
+C220157B43C1091E128EFDFDA97F0402F999E02EDEAB0E643201D8AC884B7E4E
+6A92433A0EBA2524635770EC9140F7112354CC63F4476F7DA470050D7811A921
+02DBFDC954E9ACC0994394F7306B0BAF5C015BEB89EADBBE52BC4992B8773C3F
+B0725E8EDAC8CF90935AF853B1C2B4CA867AEE5D067C60C1F6D18027222943DC
+87B308A212FB59551A0AC3066D66A1752382783A9CC9A6F775FFB0F6A55E9399
+22CC038DDFA2AD6A039311631B4BF037124E0259ADA79B854CDA381078ECA286
+72E9816250187A5B4760117549FB06628728F671F499E5749FA2B21E105ED5CA
+EFF970B731B58715F9228E9E9CBD1E0565E633234857051AD219A5BC14380C9F
+5F8F61EF0D98D68AC4A62320FE8B7876E3DCC43147578B875A4E8B59A8EF6304
+6DECF0505CF4A4F589A3C28448B3F67998FF4F2E9CE81077B77D0D71982CFC7E
+E4DC174F9C3EDEB3C8491C61B150982F32293EC9CF9DE7105AEB479FD69F36D7
+54F3B381DAFB7A65BD6100F155A30A513BB79FEB24A03292811A04517937AAEE
+D183ABF019493C2874E140399D11FAF10B772671419838AD0A12CAF0BE290415
+169D746C20BDCAF5737036AC853F9D81E3E90DD553395AA400140A0EB0836D81
+192941B3577E8A72638AA275B92F9D48A45C265E5C059BA852026483FF7D8205
+06A19DB05F3BE1BD0466D20BAC9A054010538D76BB5F92061DA0F051011CB541
+5CF6E15FCED73C545F238346DF521AA3EB09131C03002EE06B72421E9E63E00C
+EEFDD453EDEC1DEBC8870641E88A3BF8B1DFF18DC0F55D896BBF710CF1FD01B7
+DD06F726DD6046E83E6E108599E8B23405390106EA8D86C78E48F80C00908FC0
+E8AFB264586F836B39924AE1CA69E386A00B6892425EA270900AFC5B0ACA1116
+B3DF99A3AD62A1007EFE59BA4E9C2B9AA1B65F355916508BBC8C071A3316975B
+ED7BBC94A92DB5E1A64A9374B1F713FE9C95694CF30ACE7DDE8DBEED3EB0D3F1
+A41C7FE9FDB9EC5DFA674A7CAF99F16C79042441F4886CD41CF9F55C936D670E
+032D70395CD358119925A395976EAFA0ED0A22B1578DF7BD3366FF6EFE369964
+8ADFBFB8B0D3C5C9BF586BE6DB0954EDF3D839085D5C0AA31EBD97F5A5E09FD2
+20910D7D4A54728905ED6CAD86C92F71503822A8C874E93F82EF9BA0E35C94F9
+CF342D28D65A89258E3258414DB504229E81E7298DAAE6848C2495EFFF169FB0
+6EAD806218418C918EF588932AE1E44E6AD0DF2D9684455E3EDBE66363C2B3B0
+5D1A78916120D57C45EDE32F49D9520E01A24610BCF47C2360A6D70CE9ABCDE5
+97F38A7464D2E75602E99B7BD5D01B882CC8D706BF1250FD2B1DEFE66B7ED82C
+EC38581CB9165B6B52FBD615F786DAB51BD78D846B2B19DFA59C562B071A2932
+94AEFA3F158571C5BC8E1C436109E3D2BFF6D266A8FB589FD343583F9E3B2C64
+026ACA216B2FBDCA13C6CFD91A0CD2D3712D79ADF4AC85AFCD6C6B09839C8165
+151B93F5F9A2799A0BAC2A14794D1FD7F6891925FEFD6643A5F25DDE4E09344B
+64F0A51B07095AC2379C84328BDCF83599DD68FD8A0825DFE26BC9CC84C9C5C5
+21A85554971A9C200F6386542F9C8DFA7C6F89F572CDFB96821DD0FA18821B0F
+3D113C3D1B6E19381C1634B4F578D261B5DC34B1F64EE30A701746AB4F90AD37
+E96607528C15EFCB75BA7C67093A962299B7B194C8918DF3E41D1ECA02A0AD4E
+CCCCC8201D0F9433C8824893F73945FE0CFE366DEDADB3F4268A827AAFFF3B11
+6773FD03D79678EA7F23E047B2D04B529E317AFE568E22C8125DD6CADF28B718
+4EE8E6C06C01E1B0F45D778D819922785EBC883657B4FA4F1D98CB6D04C95101
+D219A319FC407C9EFBC9A6676289820903E876F620819BFD6CBE1FAB37AB04CC
+50AB16636D1FA22A5C2937D924EA82A344CBA0C1EDE1141734713AB2F42F48A5
+51E078217142A320ADFEDCCAC3D3CF7C1789660ED052E87A65D91B586C0073EB
+3581F4F52D08B5A4E2FB8D8FF91F607683D6E1C9197213F8E83E250BD9D6AFF4
+54E44444C42128A7898C2847FFC33CBCAD468FBBD2EF4BB8332395643C9E4DFF
+5424F837D7C2CAE52890A9F22064FB926E15C1D4DDEF9A4A32E02F55357F21E1
+48ACA7E663AFED067C76BFEE9AEF65E8160EAE749A42EFF6CD71074AFF8394B4
+EAE419A2344DEB603CD292DB6961395642116AD61E984E4756F4670A03741FBE
+9A959BF0052834558CF6A73CB6E21BAFD9FFA803EF2473C6FE789FBB1F0C81BE
+78850AE8EF6D53C94579E27BECA5C520F21B12B45137016DD802531F5C9A3599
+861A916BB47DBFA14A32150C4C681CAA5BADACB937953D2799984DFDA1386538
+300DC63D6C99549A90A5E9A8106D80D23DBAF785ED21E0745B5DF6A94F67E9B6
+48A26A297B334F38059CB9AF0B6E6A898E9B29615CE41E32C06D1D867705CB28
+207726EB3818FE9E1C833DB148783E64F8B0577D423718E345A689D8748656DE
+CA58F072B948C0B54BD6A889F4A1225D460A0552B9175BB6733DF157F87D664B
+1C9B914A28A6120A1FF23C2B6DCB270190D90DBD838D0759A59995BB96F260C5
+B7C49DC66FCF17620ABD269053F742707EB2F27FAC805F0684B0A6C0B5853E3D
+E5647817168DC16096E8962E3C14ADDF49DE7449225C729B4830F4D0651A45D8
+F5ABA98F7FECBE3FB02F49D3BCEDC8E366769DE821FDBA3840F55F47E4101C37
+67B327475461583F56B9D4DAD9AAB899FFB4DA3D4F6AF0FEC0A0241860BAB912
+543D9E51370EFA9F882FB277E446937F861AE2DA4F138BE19BE5BAF338E349EE
+A3F8E5BA85EC9EE02AEDD271BE768B35F65191F7658EE41DB5B79EA49A206992
+41E6F081EAA7D086BDD111077B9BD20A418528F1A2BA20218185C624A12A71F3
+120C4DC70AA0FD1CBCBF9BBBBB5465C99F176BF72021C26A0C6E780467EA8808
+753206AAD430C6CAE5130C0FFAEEF6C43056CF13EC9267F4884FCE8B189A0DA9
+DBDA730C3D1BAB2D794BBCFD07A8F7894E20DD3086AAA31E299CAFEE29C5DDF3
+1B0D041E6B1905F54EBD72DEBB284186E7EC9866B733005A062CFB8ED79B7B75
+9B01674DCA7C5E2E479BE170C4C0BB57DA2F171A4996FBDC2D622A99CFDCDA5B
+F8EF6C270D52714145BA799D7B35987D2971ED9A3E490D5CEFEBD56BCDE9F441
+029CE3E560F02E2D39ACE9FC3F767B85410A6460A36538A9B926959B0CC879FD
+88D293D99B657C87A7F971064ACC371A7F2CB25FEE8A33EF7701108FF0DFA2AB
+AD56906F6225098D8063E05E3B75AE082106926044FA59C169CFC05502C69DFB
+F2B259C1740B2DC23F3568DDE0487FA5D7F1C53BCD605ED98E07F6CD774FFC8D
+3DE5E7535561E6EBE582766B5396A869F8A1AF2388AF309969BC5762599B04F0
+18CCCD57C6031F2543D266B247342B6F9B4CE9C8CF05314F5127EB6D0ED697E3
+7E7D6EFC6D3665700050A5F8865319EA2690EB056AFB14D13F069AFB0BE3C86F
+85367D422EC94CBC4D0C009746817DE55D2B6CF09754F22CBD9C7EA621C55C79
+DBB3AA440322CEA7A3841AB5FC7054B2E6683EA055437A35D42C2962A60EFAAB
+858EBB6D57D48FE75D97E6D7A0CDE3F4A19367A4B6E4BD1E678686CFC071F002
+51C3884CD5E95D2640181D2DD73A62EE2D7FD5CFDB30C5648CD090D3E889D65B
+D9BB799FE98CCC57D0B40FBC0813A6BFDE8CE8B38A56AEB3F34EAC849A6BA649
+7A14714C4351CC04883E6581C7926323441D716BC23D202AF22DE6C4FDB4D727
+971D6DEB55C6F57A9C42CCFAB724800E4CE936C40A254C2205FCA94C98521C40
+C12D11E1A4C0F2FDC14B2B341A5262C6C83B20C97400BAE5DE986A063442B3C3
+C7B9F127BE5810AA39BF50795B16F0C5CBD9DB827DD0B8F8F0EAC4B0C9349270
+6B045BC9079B8FA2044EA69063E035C69737BBEF0FD946545D7F664C3A4A1471
+19CF2BAC3EC3F5878C129ED81DAA9B92B295450A9DF2BE084071058EE434906D
+A1AF4CDE9D7E478DACCCB10B48CA31BA88D3851A7E5EA2CF2FB932EEABF237A2
+BD93C7A092BA7FA570AF2DE43EAB43599081AF5F3318D56D8F4C2B2EFC1AF6F8
+051C754779ED01EA030414B190A081645505DE0F4D0A3B66AC353F81CBB06370
+F33C788FD6EECD9ACDE798B479A2102C269BD62052478BA0C5BD7936E9E1EC95
+2062D2AA3DE8A04438CAAAC857805586DB0A4231F34A61B05441ABC93325166C
+EE085FEF2DB62147DE3CBB8D2F24687E4E7977F4C3136A458C5752598C83F616
+729D130787F6E2A6AE62FA4EE63B005AC66B57B4043A9DEE58004A8B70E576A5
+39B6675834258F0A803E798EF7DC0E5FE1BB5EE995FBF365F8B5CEFB56084E1F
+77548CA35FA2A28D007FF110D47CAED5E962E5A367B3882A75E867DE736050B0
+AC18034B8C561BE4E2F06EE92CED884CEB0D09A0C7707C2B1AD3163CC4F07BE6
+D0ACD9244E5C9EF238407D0743BD972892B53BA71489AD43F7E67312A1E21ACD
+9BEB69DD7617738168CE0C440CEC9A462737CA8FF67ACE5CAEDF0D642645F09D
+3BF2C8FDADD94B70298A9A89C6D3691F483CE233D726C9184E1B74ACB8C2598A
+183709AA4968F4E66014681DD5A70DB3599940455BFE78AFE566052482E0A17D
+D5BF829F24C47A1AD30F20ED91BAC83A7C001BCF8B22F7CCADD43D7075E865C4
+71D996C4641D9E96F0E5C4D38B07F29A96F19EFC4FF4147F1B31180866E52EDD
+654143D390587D23409B0D7CBFB0DB3D33200FF7F6815ADF70011FA2C6E9BB2A
+E0D01F904B0E036DBA77BA8B535E44D91DDA9CC7F10124C06AFC898CC8D26BAD
+A7D285A200C0175152A60ED12F0475BAFC54EA03F2854A48A312A61333F161F7
+23298F782A8AF7E5998AD7F22DDBCF54C7A9ECFECEADF1B78CFF915DF5F73D26
+8D700A26CE9FB11CBEEE1629E9F75AEA98E1392B27766B0E1A51A95811DDB2FE
+F23694BFCB3E979587BD26315BAAED9FF607AECBA762A41945D182BD0688CE81
+C29F4863EC028E24FA005F32071B505BA717CE0B55013EC2797F6F373282F265
+4BFC2A76411F1A7F01F9192B773B2FA06F9DEDD90C89873765AC901204A1118A
+FFBE854DA9D5A1E9588C7746B14DF8D413C4FF0B7C08CEBCA150C92244281E87
+FE02CCA9168E4C61866601B65EA3002B7195CC48D22D097C01DBB678746E9492
+CC304EF0AB198FF208291340585F5F44C2EC444E41DE5B5E3A7EAD4F69BE3324
+3DFF06CB1574798D339D47D84741B3F69550A41ED7C6FAC82344D7955E5B1BDC
+3416FE4118134F7723DA0B74B45338BBC60E94E88BBB0BC9033775DF75C39A76
+F19C9760DA504EC51890E78959DE4E0113F12E8A945FDD184973A92962E265C8
+3EDFD94DE761E6B576071E8CA62C32DA8748A849C9249EDA7C6382DA73FCF59E
+1BCE44E5F1E515E222C19314A58F7D4A1B9B40B3645F4CFB930E9DCDF00FDEE2
+92602A89B82A8314ECDA526DF40660A5B621BFAAE228514596194147AB8ADBA3
+E311A419B473040F02EACEEC7E082CF966E929E5F72A2CA143DA16390194F538
+D688F5AD85AE3F937E94C47359C650CDBF1269EF91341B2FD1846D3AD289AB49
+4F5AE12CFBD5FCE7E3CDBD3B03ADB70EE2FAD7FE76BBB323672FF66852023B37
+40388D56EDBCCF43EEAB3786DACE8FBDE47F9FD2ED0D15F4CD195D11CB1617D7
+8E2D6D1268358F69F5BF6E0CDF1E58AB4E502A8784200EA9761043543D55960B
+940EF24176D8F7678A62280DA8A26787132759FB02735C4D282996DAD1C9BAF5
+CD38D1A7CE454D4F5484FDBD9E7E903531AA0BCC507B9E03220E99B2C80F3DB3
+3F92AE097A972397EFFFCFF3321DB15C4D582770E8901603C25A8E47A724E96C
+06B1C3F12720A9D0659AE5D59C0D3F161127FCED30C17E6EC31EC5DAD844CCA7
+E4D83C9A3A867E5D6E70E2D149B8D54AD9348B5E38506E09314ABD82971078FF
+1C4FCCF17982DAACD827E63CDE25DEE4B3B21E516BAAB03AD4CC7E6E5C817398
+3FB83CCC12A3FEA6E0118F5AF6EEB8BD7EFFF500BF321FE73563590C21D83890
+509EE77E1E9BDD98DE7B5F61A67242004D545DD6E41ADA0DA16ED098518122C1
+7B2F99FB3E365134601E93173C548FBE7994FD7963344468E295C9252AEBBC7D
+3CD82A14EA2F5E0E9D45928CCFB4F5D74473FC49217628BA3F72EDCF42E4E303
+6467CF6251D05732D19170BDF9C763D9BE69D6F98CF945241390DBCE620E296E
+88000CFD20A6714DB1311B66AD5618BC5FD3D53FAC8515A383CBC7B353324499
+AFDC81CBF4C5937FD3BC77F9F4DC0BDBC6F1330D71F7279BDFEE228087961EB0
+C4B84086ECBA1DFC2BC9F76DA5EC1D3656A2DAB41E125553C5052A73E57F25A8
+1C114F2F40563A3FCDA80B99AEE9F509214ECBED0B55CB051563E5B90F3F8167
+64FA9A4E837BECB98C0804C82B011656E674036CEF570CCB31587F5A93AAC20B
+10B63B2E5AD83C153D8A25A4F0440610A1513AEC5E4A3317F4AD0EF3098F22FA
+32DEEDB0ECF8D997EDBF37FF554B4DCFB8D3159F04BD7B4492472466AC082CA0
+F15ED01BBD7B879208F71BAE66031082288A7F927D6A5DBABB3743CE064D03AC
+111FB99CB37E3F0279B9D2AE4EE389BBD63BC1C099F4A2A80CB405E627F785ED
+7B723382187CFE71C5138135A1CAD9319B8B2E73DE4D39DDB2E6673ECA7447B2
+B9F81C70D1A11C72DDBF2579DCC6CFD28DBE42AF2C21022A0E5109DD1ABEDC90
+73EC0900094863170F873A2F7FB719D485725D6125FCF00CE71F7B9D0AB0D5E9
+8F7587B2DD27F44A1970EED04C44CAC776DCD485E8D39DFA752627FE33937610
+B69BF261C38F26C7F55523BEC338BB0805C2F1DE28F2081FB1A23865F8603273
+37D4595A7AFB8F7B1FC5B68E63E0FC65C58E238E6E924A7A5A9F57EC89A397EF
+7C13FC02D965CE8C7BC577911A8B85C5D20CCF3CAB829C621697F0C9D6507E70
+06A14BBB40A3993F59C035833F8DD35A1453DF39659F72D169BEA31CE0AF3A08
+AEF10E19DA566EAF4E627305E072611795EAC4875B4919FDFAB74D7961D2F10E
+3350A868C38CD8D23658D46582DC397DC868A4299BA2CD2F953EC146658EB7C6
+A46B6B1F5DCE2EDA407BE98592407DA2C1618FB5AC32587F6D5AE7187FCD4919
+868F47583E51A9981B202C03BBD1AC359799EE08D39A0C0876754C0F9DDA31B8
+48C195D00E16F1C13EE3A3261F684E8B95EEECA768393B932C77A850D94F6980
+DC05F8000A9B6C368FE60BC3A880127598A22B7AB9FD791A66D2854341822493
+828DEBA62F669D1BCA3CF912E4CD616E5D8AB8729B05D147D545983ECBBB17FB
+ACBD731A17EE08CD89AB3FBFEC9E08C364168390A1E49FB4AA0C65836F578E2F
+1879E1FD1B100EE39AF490B2004CEE8E425BE6DB29E1D964A37FC8E8021B4967
+168FFE7DFCF8E8181F299922900855C7797A252C7A83C369DBD6D6A652A1F9D0
+D73FD5AB7F368CB83D0DC51A00EC74B54A406B5D83FC366C4BF7FC3E8AB8BB7E
+78569D4577267AB2CBD872BD190338A277FC0637FF571D8CAED2BCBC5BE6B537
+C2A72894AC2091B778493428D5EF1A238E77E7AB585BBCCDFC1F987CAA34F729
+ADB3BC05ACA3DD01B7C3B975149507F2EAA6DC2E76A933AE14FAF54DEDA6B605
+DAEAD123D80B6A952F6504F0B48EC88554156CAC701391793F230CF8B2C0FB91
+065CDD2D45733D
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+%%EndFont
+%%BeginProcSet: texps.pro
+TeXDict begin /rf{findfont dup length 1 add dict begin{1 index /FID ne 2
+index /UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll
+exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics
+exch def dict begin Encoding{exch dup type /integertype ne{pop pop 1 sub
+dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}
+ifelse}forall Metrics /Metrics currentdict end def[2 index currentdict
+end definefont 3 -1 roll makefont /setfont load]cvx def}def
+/ObliqueSlant{dup sin S cos div neg}B /SlantFont{4 index mul add}def
+/ExtendFont{3 -1 roll mul exch}def /ReEncodeFont{/Encoding exch def}def
+end
+%%EndProcSet
+%%BeginProcSet: special.pro
+TeXDict begin /SDict 200 dict N SDict begin /@SpecialDefaults{/hs 612 N
+/vs 792 N /ho 0 N /vo 0 N /hsc 1 N /vsc 1 N /ang 0 N /CLIP 0 N /rwiSeen
+false N /rhiSeen false N /letter{}N /note{}N /a4{}N /legal{}N}B
+/@scaleunit 100 N /@hscale{@scaleunit div /hsc X}B /@vscale{@scaleunit
+div /vsc X}B /@hsize{/hs X /CLIP 1 N}B /@vsize{/vs X /CLIP 1 N}B /@clip{
+/CLIP 2 N}B /@hoffset{/ho X}B /@voffset{/vo X}B /@angle{/ang X}B /@rwi{
+10 div /rwi X /rwiSeen true N}B /@rhi{10 div /rhi X /rhiSeen true N}B
+/@llx{/llx X}B /@lly{/lly X}B /@urx{/urx X}B /@ury{/ury X}B /magscale
+true def end /@MacSetUp{userdict /md known{userdict /md get type
+/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup
+length 20 add dict copy def}if end md begin /letter{}N /note{}N /legal{}
+N /od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath
+clippath mark{transform{itransform moveto}}{transform{itransform lineto}
+}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{
+itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{
+closepath}}pathforall newpath counttomark array astore /gc xdf pop ct 39
+0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}N
+/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1
+scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get
+ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip
+not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0
+TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{noflips{TR
+pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1
+-1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg
+TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg
+sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr
+0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add
+2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N /cp
+{pop pop showpage pm restore}N end}if}if}N /normalscale{Resolution 72
+div VResolution 72 div neg scale magscale{DVImag dup scale}if 0 setgray}
+N /psfts{S 65781.76 div N}N /startTexFig{/psf$SavedState save N userdict
+maxlength dict begin /magscale true def normalscale currentpoint TR
+/psf$ury psfts /psf$urx psfts /psf$lly psfts /psf$llx psfts /psf$y psfts
+/psf$x psfts currentpoint /psf$cy X /psf$cx X /psf$sx psf$x psf$urx
+psf$llx sub div N /psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy
+scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR
+/showpage{}N /erasepage{}N /copypage{}N /p 3 def @MacSetUp}N /doclip{
+psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2
+roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath
+moveto}N /endTexFig{end psf$SavedState restore}N /@beginspecial{SDict
+begin /SpecialSave save N gsave normalscale currentpoint TR
+@SpecialDefaults count /ocount X /dcount countdictstack N}N /@setspecial
+{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto
+closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx
+sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR
+}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse
+CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury
+lineto closepath clip}if /showpage{}N /erasepage{}N /copypage{}N newpath
+}N /@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{
+end}repeat grestore SpecialSave restore end}N /@defspecial{SDict begin}
+N /@fedspecial{end}B /li{lineto}B /rl{rlineto}B /rc{rcurveto}B /np{
+/SaveX currentpoint /SaveY X N 1 setlinecap newpath}N /st{stroke SaveX
+SaveY moveto}N /fil{fill SaveX SaveY moveto}N /ellipse{/endangle X
+/startangle X /yrad X /xrad X /savematrix matrix currentmatrix N TR xrad
+yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end
+%%EndProcSet
+TeXDict begin 39158280 55380996 1000 300 300 () @start
+/Fa 136
+[32 2
+  [23 18 23 1
+    [21 24 1
+      [28 20 2
+       [12 3
+          [21 24 23 1
+           [23 16
+             [28 1
+                [31 9
+                 [31 28
+                   [12 39 [{} 17 37.708344 /cmcsc9 rf
+
+/Fb 138 [84 1 [63 4 [84 8 [76 86 17 [110 10 [117 71 [{} 7 137.500000 /cmcsc10 rf
+
+/Fc 137 [21 21 21 1 [21 1 [19 22 21 26 18 6 [19 22 21 1 [21 16 [26 11 [29 28 15 [19 19 14 [32 35 [{} 19 33.583321 /cmcsc8 rf
+
+end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 300dpi
+TeXDict begin
+%%PaperSize: a4
+%%BeginPaperSize: a4
+a4
+%%EndPaperSize
+
+%%EndSetup
+%%Page: 1 1
+1 0 bop -158 2763 a @beginspecial 0 @llx 0 @lly 890.299988
+@urx 909.700012 @ury 5102 @rwi @setspecial
+%%BeginDocument: ../texi/gnus-big-logo.eps
+% Copyright 1992 Corel Corporation.
+
+% All rights reserved.
+/wPSMDict 150 dict def
+wPSMDict begin
+/bd {bind def} bind def
+/ld {load def} bd
+/xd {exch def} bd
+/_ null def
+/$c 0 def
+/$m 0 def
+/$y 0 def
+/$k 0 def
+/$t 1 def
+/$n _ def
+/$o 0 def
+/$C 0 def
+/$M 0 def
+/$Y 0 def
+/$K 0 def
+/$T 1 def
+/$N _ def
+/$O 0 def
+/$h false def
+/$al 0 def
+/$tr 0 def
+/$le 0 def
+/$lx 0 def
+/$ly 0 def
+/$ctm matrix currentmatrix def
+/@cp /closepath ld
+/@gs /gsave ld
+/@gr /grestore ld
+/@MN {2 copy le{pop}{exch pop}ifelse}bd
+/setcmykcolor where {pop}{/setcmykcolor{4 1 roll
+3 {3 index add 1 @MN 1 exch sub 3 1 roll} repeat
+setrgbcolor
+pop}bd}ifelse
+/@tc{dup 1 ge{pop}{4 {dup
+6 -1 roll
+mul
+exch}repeat
+pop}ifelse}bd
+/@scc{$c $m $y $k $t @tc setcmykcolor true}bd
+/@SCC{$C $M $Y $K $T @tc setcmykcolor true}bd
+/@sm{/$ctm $ctm currentmatrix def}bd
+/x {/$t xd /$n xd
+/$k xd /$y xd /$m xd /$c xd}bd
+/X {/$T xd /$N xd
+/$K xd /$Y xd /$M xd /$C xd}bd
+/g {1 exch sub 0 0 0
+4 -1 roll
+_ 1 x}bd
+/G {1 exch sub 0 0 0
+4 -1 roll
+_ 1 X}bd
+/k {_ 1 x}bd
+/K {_ 1 X}bd
+/d /setdash ld
+/i {dup 0 ne {setflat} {pop} ifelse}bd
+/j /setlinejoin ld
+/J /setlinecap ld
+/M /setmiterlimit ld
+/w /setlinewidth ld
+/O {/$o xd}bd
+/R {/$O xd}bd
+/c /curveto ld
+/C /c ld
+/l /lineto ld
+/L /l ld
+/m /moveto ld
+/n /newpath ld
+/N /newpath ld
+/F {@scc{eofill}if n} bd
+/f {@cp F}bd
+/S {@SCC{stroke}if n} bd
+/s {@cp
+S}bd
+/B {@gs F @gr
+S}bd
+/b {@cp B }bd
+/u {}bd
+/U {}bd
+1 i
+2 J
+0 j
+4 M
+[]0 d
+
+0 g
+163.4 2.9 m
+197.1 51.5 223.7 94.3 251.6 130.7 C
+283.4 176.1 312.0 216.3 342.8 256.8 C
+373.2 303.2 401.1 342.1 420.0 396.9 C
+421.2 403.1 425.1 408.9 424.5 413.5 C
+395.6 371.6 368.4 326.2 337.2 285.0 C
+306.1 247.4 276.3 199.4 244.5 161.5 C
+212.1 116.7 182.9 79.1 168.6 20.4 C
+166.3 13.9 164.7 8.1 162.4 2.2 C
+162.4 2.2 163.4 2.9 163.4 2.9 C
+f
+0 g
+428.1 170.2 m
+428.1 170.2 429.7 170.2 430.0 170.5 C
+454.7 211.4 474.8 275.6 504.0 301.9 C
+512.1 300.6 515.0 280.8 527.3 283.1 C
+534.8 284.4 536.4 284.1 542.9 288.9 C
+571.4 331.1 600.3 374.5 623.6 423.2 C
+640.2 454.7 661.6 492.9 663.5 517.6 C
+660.3 515.6 L
+633.7 468.6 613.2 419.6 582.4 378.4 C
+572.1 367.1 566.5 352.8 550.7 348.3 C
+543.2 348.3 536.1 354.4 530.5 363.8 C
+528.9 367.1 528.9 368.1 525.4 369.7 C
+495.5 333.7 466.7 282.8 446.5 233.5 C
+436.2 206.2 433.2 190.0 427.4 170.5 C
+427.4 170.5 428.1 170.2 428.1 170.2 C
+f
+0 g
+754.7 271.7 m
+783.8 345.7 780.3 386.2 794.2 447.5 C
+806.2 497.1 819.2 543.8 843.5 614.9 C
+869.5 690.4 875.0 731.0 888.0 787.1 C
+892.5 826.7 892.8 865.9 869.5 898.7 C
+853.9 908.7 841.9 912.3 822.1 909.4 C
+785.5 890.2 764.1 846.4 749.8 799.7 C
+750.4 793.6 750.8 791.3 755.0 788.1 C
+755.6 788.1 756.9 788.1 757.9 788.1 C
+772.8 803.3 773.8 842.9 796.8 849.0 C
+817.6 849.0 826.3 847.7 840.3 834.8 C
+855.8 799.7 856.2 789.4 858.1 755.0 C
+855.2 687.5 836.7 643.7 819.8 576.9 C
+801.7 513.7 781.9 454.3 772.8 406.7 C
+766.3 361.6 755.0 332.4 754.0 271.7 C
+754.0 271.7 754.7 271.7 754.7 271.7 C
+f
+0 g
+383.0 484.8 m
+421.2 539.0 420.6 593.1 405.4 650.9 C
+395.0 674.5 382.7 683.6 367.7 695.0 C
+354.8 681.0 339.2 664.2 330.1 640.2 C
+330.1 640.2 330.1 638.5 330.4 638.2 C
+351.5 628.8 372.3 592.2 378.1 567.2 C
+381.0 544.5 378.8 505.2 382.3 484.8 C
+382.3 484.8 383.0 484.8 383.0 484.8 C
+f
+0 g
+120.6 509.8 m
+171.2 511.7 215.0 550.7 255.8 589.6 C
+283.4 609.7 302.2 627.8 315.8 663.5 C
+280.8 636.9 238.3 595.7 192.6 571.7 C
+179.6 566.2 162.4 565.6 147.8 570.4 C
+139.4 578.2 136.2 580.5 136.5 588.6 C
+144.6 635.3 192.3 684.3 217.6 724.8 C
+223.4 738.1 235.7 745.9 238.3 758.9 C
+204.3 726.8 174.1 677.1 147.5 634.3 C
+127.1 600.3 95.3 560.1 102.1 520.5 C
+107.0 510.8 111.8 513.7 120.6 509.8 C
+f
+0 g
+621.7 657.7 m
+669.0 661.2 703.4 716.1 724.8 769.6 C
+730.7 779.0 728.7 785.5 731.3 792.9 C
+711.8 758.5 695.0 728.4 656.7 720.9 C
+638.2 720.3 635.0 721.9 624.9 732.6 C
+621.7 736.5 620.4 739.4 618.1 744.3 C
+588.6 683.0 L
+593.1 671.6 598.3 665.5 608.1 661.9 C
+612.0 661.6 617.8 659.0 621.7 657.7 C
+f
+0 g
+502.0 681.0 m
+526.7 680.4 547.7 694.7 565.2 716.1 C
+576.0 734.9 583.1 755.0 592.2 775.4 C
+592.2 779.6 591.5 783.2 592.8 786.8 C
+582.4 775.7 571.4 752.7 549.7 746.5 C
+520.8 736.2 500.7 751.4 481.6 766.7 C
+440.4 802.3 416.7 847.7 366.8 868.5 C
+346.3 878.2 335.0 875.6 319.1 869.5 C
+300.3 862.7 292.8 850.7 279.2 833.8 C
+285.0 838.3 271.7 828.6 277.2 833.5 C
+268.5 845.8 244.2 875.3 220.8 881.1 C
+168.6 888.3 147.5 809.8 96.3 789.4 C
+83.3 784.8 72.0 776.7 61.2 781.6 C
+41.5 794.2 38.2 804.6 27.5 824.1 C
+2.2 764.7 L
+9.0 751.1 16.8 730.3 32.1 725.1 C
+45.0 720.3 55.1 721.6 68.1 727.1 C
+91.1 745.2 116.4 758.9 132.0 779.3 C
+140.1 789.4 146.5 797.5 157.6 808.5 C
+166.3 816.6 176.1 823.1 187.7 827.0 C
+219.2 813.0 240.6 789.7 259.1 759.5 C
+275.3 782.5 284.7 815.0 321.4 810.1 C
+373.9 801.4 405.0 751.7 443.6 715.1 C
+462.8 694.7 478.3 687.2 502.0 681.0 C
+f
+end
+showpage
+%%EndDocument
+ @endspecial
+/OJ {
+       currentgray
+       1 setgray
+       3 index 3 index 3 index cvx exec
+       setgray
+       gsave
+       -1 1 scale 
+       cvx exec
+       grestore
+    } def
+
+/OJ2 {
+       currentgray
+       1 setgray
+       2 index 2 index cvx exec
+       setgray
+       gsave
+       -1 1 scale 
+       cvx exec
+       grestore
+    } def
+
+/OJ3 {
+ 2 -17 rmoveto 1 -1 scale
+ show
+ 1 -1 scale
+ 0 17 rmoveto 
+} def
+
+/OJ4 {
+ 2 -25.5 rmoveto 1 -1 scale
+ show
+ 1 -1 scale
+ 0 25.5 rmoveto 
+} def
+
+/OJ5 {
+ 2 -71 rmoveto 1 -1 scale
+ show
+ 1 -1 scale
+ 0 71 rmoveto 
+} def
+
+/lars 1030 def
+
+lars 2223 a
+Fc
+  (Developme)p
+  (n) OJ3
+  (t)14 b
+  (P)p
+  (r) /o OJ2
+  (oletcul)n
+  (t)e
+  (Cad)n
+  (r) /r OJ2
+  (e)h
+  (#23)lars 2330 y
+Fb
+  (R) 0 /b OJ
+  (ed)51 b
+  (G)p
+  (n) OJ5
+  (us)lars 2367 y
+Fa
+  (People's)14 b
+  (Democ)p
+  (r) /r OJ2
+  (a)m
+  (tic)h
+  (N) OJ4
+  (ews)p
+  (r) /r OJ2
+  (eade)p
+  (r) /r OJ2
+eop
+%%Trailer
+end
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/texi/misc/september.png b/texi/misc/september.png
new file mode 100644 (file)
index 0000000..1e5539e
Binary files /dev/null and b/texi/misc/september.png differ
diff --git a/texi/pagestyle.sty b/texi/pagestyle.sty
new file mode 100644 (file)
index 0000000..d434821
--- /dev/null
@@ -0,0 +1,83 @@
+
+\catcode `\÷ = \active
+\def Ã·{\penalty10000\hskip0.001pt-\penalty\hyphenpenalty\hskip0.001pt\relax}
+
+\def \newpagestyle#1#2#3{\@namedef{ps@#1}{\def\@oddhead{#2}\def\@oddfoot{#3}%
+        \let\@evenhead\@oddhead \let\@evenfoot\@oddfoot}}
+\def \newdoublepagestyle#1#2#3#4#5{\@namedef{ps@#1}{\def\@evenhead{#2}%
+        \def\@oddhead{#3}%
+        \def\@evenfoot{#4}%
+        \def\@oddfoot{#5}}}
+
+\newlength{\headtextwidth}
+\setlength{\headtextwidth}{\textwidth}
+\addtolength{\headtextwidth}{2cm}
+\newlength{\headetextwidth}
+\setlength{\headetextwidth}{\headtextwidth}
+\addtolength{\headetextwidth}{-0.5cm}
+\newlength{\headotextwidth}
+\setlength{\headotextwidth}{\headtextwidth}
+\addtolength{\headotextwidth}{-0.35cm}
+\def\outputpage{%
+  \let \protect \noexpand
+  \shipout \vbox{%
+    \set@typeset@protect
+    \aftergroup\set@typeset@protect
+    \@shipoutsetup
+    \@begindvi
+    \vskip \topmargin
+    \moveright\@themargin \vbox {%
+      \setbox\@tempboxa \vbox to\headheight{%
+        \vfil
+        \color@hbox
+          \normalcolor
+          \hb@xt@ \headtextwidth {%
+            \let \label \@gobble
+            \let \index \@gobble
+            \let \glossary \@gobble %% 21 Jun 91
+            \@thehead
+            }%
+        \color@endbox
+        }%                        %% 22 Feb 87
+      \ifodd\c@page
+         \dp\@tempboxa \z@
+         \box\@tempboxa \mbox{} \\
+         \ifx \@oddhead\@empty\else
+   %      \rule{\headotextwidth}{0.5pt}
+         \fi
+      \else
+         \hskip -2.2cm
+         \dp\@tempboxa \z@
+         \box\@tempboxa \mbox{}
+        \\\mbox{}
+         \vskip 2pt
+         \hskip -2.0cm 
+         \ifx \@oddhead\@empty\else
+    %     \rule{\headetextwidth}{0.5pt}
+         \fi
+      \fi  
+      \vskip \headsep
+      \box\@outputbox
+      \baselineskip \footskip
+      \color@hbox
+        \normalcolor
+        \hb@xt@\textwidth{%
+          \let \label \@gobble
+          \let \index \@gobble      %% 22 Feb 87
+          \let \glossary \@gobble   %% 21 Jun 91
+          \@thefoot
+          }%
+      \color@endbox
+      }%
+    }%
+  \global \@colht \textheight
+  \stepcounter{page}%
+  \let\firstmark\botmark
+}
+
+\def\@makechapterhead#1{\gnuspagechapter{#1}}
+
+\setcounter{tocdepth}{3}
+\setcounter{secnumdepth}{3}
+
diff --git a/texi/picons/att.png b/texi/picons/att.png
new file mode 100644 (file)
index 0000000..f0473ee
Binary files /dev/null and b/texi/picons/att.png differ
diff --git a/texi/picons/berkeley.png b/texi/picons/berkeley.png
new file mode 100644 (file)
index 0000000..e22efcb
Binary files /dev/null and b/texi/picons/berkeley.png differ
diff --git a/texi/picons/caltech.png b/texi/picons/caltech.png
new file mode 100644 (file)
index 0000000..68ae3e9
Binary files /dev/null and b/texi/picons/caltech.png differ
diff --git a/texi/picons/canada.png b/texi/picons/canada.png
new file mode 100644 (file)
index 0000000..2c747a8
Binary files /dev/null and b/texi/picons/canada.png differ
diff --git a/texi/picons/cr.png b/texi/picons/cr.png
new file mode 100644 (file)
index 0000000..d53d2db
Binary files /dev/null and b/texi/picons/cr.png differ
diff --git a/texi/picons/cygnus.xbm b/texi/picons/cygnus.xbm
new file mode 100644 (file)
index 0000000..c69b5ae
--- /dev/null
@@ -0,0 +1,27 @@
+#define cygnus_width 48
+#define cygnus_height 48
+static char cygnus_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00,
+   0x60, 0x34, 0xf7, 0x34, 0x36, 0x0e, 0x30, 0x30, 0xdb, 0x6c, 0x36, 0x03,
+   0x30, 0x60, 0xd9, 0x6c, 0x36, 0x07, 0x30, 0x60, 0xd9, 0x6c, 0x36, 0x0e,
+   0x60, 0xc4, 0xd8, 0x6c, 0x36, 0x0c, 0xc0, 0xc3, 0xf0, 0x6c, 0x2c, 0x07,
+   0x00, 0x60, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x78, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xdf, 0x0e, 0x00,
+   0x00, 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf0, 0x6e, 0x15, 0x00,
+   0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/gnu.xbm b/texi/picons/gnu.xbm
new file mode 100644 (file)
index 0000000..b540df5
--- /dev/null
@@ -0,0 +1,27 @@
+#define gnu_width 48
+#define gnu_height 48
+static char gnu_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x03,
+   0x00, 0x03, 0x00, 0x1c, 0x80, 0x07, 0x80, 0x01, 0x70, 0x77, 0x00, 0x0d,
+   0xc0, 0x01, 0xcf, 0xc1, 0x00, 0x0d, 0xe0, 0xc0, 0x87, 0x81, 0x01, 0x09,
+   0xe0, 0xc0, 0x03, 0x01, 0x83, 0x09, 0x70, 0xe0, 0x01, 0x00, 0xc2, 0x0c,
+   0x58, 0xf0, 0x38, 0xe0, 0x6e, 0x0c, 0x4c, 0xf8, 0x8c, 0xff, 0x3f, 0x06,
+   0x44, 0x7c, 0xcc, 0xf1, 0xf8, 0x07, 0x44, 0x3c, 0x76, 0x40, 0x01, 0x0f,
+   0xc4, 0x20, 0x1b, 0x80, 0x06, 0x10, 0x84, 0x99, 0x0d, 0x55, 0xf5, 0x3f,
+   0x0c, 0xcf, 0xf6, 0xaa, 0x8e, 0x0a, 0x18, 0x60, 0x3a, 0x55, 0x0d, 0x00,
+   0x38, 0x38, 0x5b, 0xae, 0x1a, 0x00, 0xe0, 0x8d, 0xad, 0x59, 0x1d, 0x00,
+   0xc0, 0x83, 0x2d, 0xad, 0x1a, 0x00, 0x80, 0xc1, 0xec, 0x5d, 0x1d, 0x00,
+   0x40, 0x78, 0xc6, 0xa9, 0x1a, 0x00, 0xf0, 0x7f, 0x06, 0x52, 0x3d, 0x00,
+   0x50, 0x5d, 0xc5, 0xab, 0x3a, 0x00, 0x00, 0x5c, 0x8d, 0x59, 0x35, 0x00,
+   0x00, 0x96, 0x1a, 0xa0, 0x3a, 0x00, 0x00, 0xb7, 0x2a, 0x60, 0x75, 0x00,
+   0x00, 0xe7, 0xc9, 0xc0, 0x7a, 0x00, 0x00, 0x6f, 0x19, 0x01, 0x75, 0x00,
+   0x00, 0x4f, 0x55, 0xfb, 0xda, 0x00, 0x80, 0x4f, 0xb3, 0x8a, 0x8f, 0x00,
+   0x80, 0x5f, 0xae, 0x0a, 0xee, 0x00, 0x00, 0xdf, 0x64, 0x4f, 0xe4, 0x00,
+   0x00, 0x9f, 0xdd, 0x9d, 0x65, 0x00, 0x00, 0x7e, 0x9b, 0x3d, 0x71, 0x00,
+   0x00, 0x7e, 0xb7, 0xff, 0x70, 0x00, 0x00, 0x7c, 0x6c, 0x3f, 0x7f, 0x00,
+   0x00, 0xf4, 0xcb, 0x79, 0x30, 0x00, 0x00, 0xf0, 0x93, 0x79, 0x18, 0x00,
+   0x00, 0xe0, 0xbf, 0xfd, 0x1f, 0x00, 0x00, 0xa0, 0x3f, 0x87, 0x0f, 0x00,
+   0x00, 0x80, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/gov.xbm b/texi/picons/gov.xbm
new file mode 100644 (file)
index 0000000..99f2449
--- /dev/null
@@ -0,0 +1,27 @@
+#define gov_width 48
+#define gov_height 48
+static char gov_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00,
+   0x00, 0xc0, 0xc1, 0x07, 0x07, 0x00, 0x00, 0x20, 0x30, 0x18, 0x08, 0x00,
+   0x00, 0x18, 0xc8, 0x26, 0x30, 0x00, 0x00, 0x04, 0xe8, 0x2f, 0x40, 0x00,
+   0x00, 0x02, 0x54, 0x55, 0x80, 0x00, 0x00, 0x11, 0xf4, 0x5f, 0x20, 0x01,
+   0x80, 0x30, 0xb4, 0x5a, 0x30, 0x02, 0x80, 0x60, 0xf4, 0x5f, 0x18, 0x02,
+   0x40, 0xe0, 0x54, 0x55, 0x1c, 0x04, 0x20, 0xc0, 0xe8, 0x2f, 0x0c, 0x08,
+   0x20, 0x81, 0xc9, 0x26, 0x06, 0x0a, 0xa0, 0x0f, 0x37, 0x98, 0xc3, 0x0f,
+   0x10, 0x3f, 0xce, 0xc7, 0xf1, 0x13, 0x10, 0xff, 0x1c, 0xe0, 0xfc, 0x13,
+   0x10, 0xfe, 0x11, 0x20, 0xfe, 0x11, 0x08, 0xfc, 0x8b, 0x23, 0xff, 0x20,
+   0x08, 0xfc, 0x4b, 0x65, 0xff, 0x20, 0x08, 0xf8, 0xb3, 0x34, 0x7f, 0x20,
+   0x08, 0xf8, 0x83, 0x0c, 0x7f, 0x20, 0x08, 0xf8, 0x43, 0x04, 0x7f, 0x20,
+   0x08, 0xf0, 0xc7, 0x87, 0x3f, 0x20, 0x08, 0xf0, 0x57, 0xd5, 0x3f, 0x20,
+   0x88, 0xf0, 0xaf, 0xea, 0x3f, 0x20, 0x88, 0xe0, 0x57, 0xd5, 0x1f, 0x20,
+   0x90, 0xc3, 0xaf, 0xea, 0x0f, 0x10, 0xd0, 0x81, 0xaf, 0xea, 0x07, 0x10,
+   0x90, 0x0f, 0xa8, 0x2a, 0x00, 0x13, 0xa0, 0x17, 0xac, 0x6a, 0xc0, 0x0b,
+   0x20, 0x3f, 0xac, 0x6a, 0xe0, 0x09, 0x20, 0x1e, 0xae, 0xea, 0xe0, 0x09,
+   0x40, 0x3e, 0xaf, 0xea, 0x73, 0x04, 0x80, 0xf4, 0xb7, 0xda, 0x3f, 0x02,
+   0x80, 0x10, 0xf0, 0x1f, 0x0c, 0x02, 0x00, 0x21, 0xd0, 0x17, 0x0e, 0x01,
+   0x00, 0x22, 0xa8, 0x2a, 0x86, 0x00, 0x00, 0x04, 0xa8, 0x2a, 0x40, 0x00,
+   0x00, 0x18, 0xf0, 0x1e, 0x30, 0x00, 0x00, 0x20, 0x00, 0x01, 0x08, 0x00,
+   0x00, 0xc0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00,
+   0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/laurie.png b/texi/picons/laurie.png
new file mode 100644 (file)
index 0000000..0793f9a
Binary files /dev/null and b/texi/picons/laurie.png differ
diff --git a/texi/picons/mit.png b/texi/picons/mit.png
new file mode 100644 (file)
index 0000000..e297591
Binary files /dev/null and b/texi/picons/mit.png differ
diff --git a/texi/picons/nasa.png b/texi/picons/nasa.png
new file mode 100644 (file)
index 0000000..1679857
Binary files /dev/null and b/texi/picons/nasa.png differ
diff --git a/texi/picons/qmw.xbm b/texi/picons/qmw.xbm
new file mode 100644 (file)
index 0000000..1eb5621
--- /dev/null
@@ -0,0 +1,27 @@
+#define qmw_width 48
+#define qmw_height 48
+static char qmw_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc1, 0xff, 0xe0, 0x7f,
+   0xff, 0xff, 0x81, 0x7f, 0xe0, 0x7f, 0x3f, 0xf8, 0x80, 0x7f, 0xc0, 0x7f,
+   0x0f, 0xe0, 0x00, 0x3f, 0xc0, 0x7f, 0x07, 0x40, 0x00, 0x3f, 0x80, 0x7f,
+   0x03, 0x00, 0x18, 0x1e, 0x86, 0x7f, 0xc1, 0x07, 0x18, 0x1e, 0x0e, 0x7f,
+   0xf1, 0x1f, 0x3c, 0x0c, 0x0f, 0x7f, 0xf8, 0x3f, 0x3c, 0x0c, 0x1f, 0x7e,
+   0xf8, 0x3f, 0x7e, 0x80, 0x1f, 0x7e, 0xfc, 0x7f, 0x7e, 0x80, 0x3f, 0x7c,
+   0xfc, 0x7f, 0xff, 0xc0, 0x3f, 0x7c, 0xfe, 0x7f, 0xff, 0xc0, 0x7f, 0x78,
+   0xfe, 0xff, 0xff, 0xe1, 0x7f, 0x78, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f,
+   0xfe, 0x7f, 0xf8, 0x1f, 0xfc, 0x07, 0xfe, 0x7f, 0xf0, 0x1f, 0xfc, 0x07,
+   0xfc, 0x79, 0xf0, 0x0f, 0xf8, 0x07, 0x7c, 0x70, 0xe0, 0x0f, 0xf8, 0x03,
+   0xf8, 0x30, 0xe0, 0x07, 0xf0, 0x03, 0xf0, 0x00, 0xc2, 0x87, 0xf0, 0x43,
+   0xe1, 0x01, 0xc3, 0xc3, 0xe1, 0x61, 0x83, 0x81, 0x87, 0xc3, 0xe1, 0x61,
+   0x07, 0xc0, 0x87, 0xe1, 0xc3, 0x70, 0x0f, 0xc0, 0x0f, 0xe1, 0xc3, 0x70,
+   0x3f, 0x80, 0x0f, 0xf0, 0x03, 0x78, 0xff, 0x87, 0x1f, 0xf0, 0x07, 0x78,
+   0xff, 0x0f, 0x1f, 0xf8, 0x07, 0x7c, 0xff, 0x0f, 0x3f, 0xf8, 0x0f, 0x7c,
+   0xff, 0x1f, 0x3e, 0xfc, 0x0f, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xaa, 0x7b, 0xd7, 0x15, 0x73,
+   0xb5, 0xaa, 0x48, 0x91, 0x9c, 0x14, 0xd5, 0xaa, 0x3b, 0x97, 0x88, 0x74,
+   0x95, 0xaa, 0x28, 0x94, 0x88, 0x14, 0x97, 0xb2, 0x4b, 0x97, 0x08, 0x13,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc7, 0x98, 0x0f, 0x1f, 0x63,
+   0xe3, 0xcf, 0x99, 0x9f, 0x3f, 0x67, 0x63, 0xcc, 0x9b, 0x99, 0x31, 0x6f,
+   0x63, 0xcc, 0x9f, 0x99, 0x31, 0x7f, 0x63, 0xcc, 0x9e, 0x99, 0x31, 0x7b,
+   0xef, 0xcf, 0x9c, 0x9f, 0x3f, 0x73, 0xcf, 0xc7, 0x98, 0x0f, 0x1f, 0x63,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/rms.png b/texi/picons/rms.png
new file mode 100644 (file)
index 0000000..10dfc25
Binary files /dev/null and b/texi/picons/rms.png differ
diff --git a/texi/picons/ruu.xbm b/texi/picons/ruu.xbm
new file mode 100644 (file)
index 0000000..c44ebcb
--- /dev/null
@@ -0,0 +1,27 @@
+#define ruu_width 48
+#define ruu_height 48
+static char ruu_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x83, 0x03, 0x00,
+   0x00, 0x20, 0x80, 0x81, 0x04, 0x00, 0x00, 0xe0, 0xc3, 0x02, 0x03, 0x00,
+   0x00, 0x1e, 0x02, 0x40, 0x7a, 0x00, 0x00, 0xd2, 0x11, 0x88, 0xcb, 0x00,
+   0x00, 0x23, 0x30, 0x0d, 0xc8, 0x00, 0x40, 0x12, 0xa2, 0x21, 0x7a, 0x02,
+   0xc0, 0x9e, 0xa4, 0x35, 0x01, 0x07, 0x00, 0x83, 0xac, 0x35, 0x81, 0x01,
+   0xf0, 0x13, 0xb1, 0xa6, 0xcc, 0x00, 0x20, 0x60, 0x6a, 0x6e, 0x86, 0x00,
+   0xc0, 0xc4, 0x4a, 0xe6, 0x23, 0x01, 0x00, 0x48, 0x4e, 0x60, 0x1a, 0x00,
+   0x00, 0xb0, 0x08, 0x00, 0x0d, 0x20, 0x00, 0xc0, 0x01, 0x00, 0x73, 0x38,
+   0x60, 0xfe, 0x01, 0x80, 0x1f, 0x0e, 0x3c, 0x18, 0xf8, 0x3f, 0x18, 0x00,
+   0x28, 0x61, 0x08, 0x20, 0xec, 0x61, 0x70, 0xfc, 0x18, 0x20, 0x0e, 0x7c,
+   0x40, 0x60, 0x38, 0x20, 0x3c, 0x0c, 0x40, 0x0e, 0x78, 0x20, 0xe0, 0x78,
+   0x60, 0x38, 0xf8, 0x20, 0x0e, 0x00, 0x3c, 0xe0, 0xf8, 0x21, 0x1e, 0x34,
+   0x54, 0x7e, 0xf8, 0x23, 0xc4, 0x75, 0x7c, 0x10, 0xf8, 0x37, 0x18, 0x5c,
+   0x00, 0xf8, 0xe3, 0x8f, 0x7f, 0x2c, 0x80, 0x9c, 0x01, 0x01, 0x07, 0x00,
+   0xe8, 0xe0, 0x08, 0x20, 0x0a, 0x27, 0x38, 0x90, 0x0c, 0xe4, 0x32, 0x3f,
+   0x10, 0x49, 0x4f, 0x66, 0x07, 0x10, 0x90, 0x42, 0xe2, 0xae, 0x8c, 0x10,
+   0x80, 0x24, 0xd2, 0x2e, 0x81, 0x03, 0xa0, 0x05, 0x49, 0x62, 0x01, 0x06,
+   0xc0, 0x91, 0x28, 0x49, 0x32, 0x04, 0x80, 0x9c, 0x28, 0x49, 0x60, 0x02,
+   0x00, 0x52, 0x24, 0x09, 0xc4, 0x01, 0x00, 0x99, 0x21, 0x09, 0x8d, 0x00,
+   0x00, 0x88, 0x1d, 0x70, 0x59, 0x00, 0x00, 0xc8, 0xd0, 0xe8, 0x31, 0x00,
+   0x00, 0x40, 0xd8, 0xe0, 0x00, 0x00, 0x00, 0x40, 0xc8, 0xb0, 0x00, 0x00,
+   0x00, 0x00, 0x48, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/seuu.xbm b/texi/picons/seuu.xbm
new file mode 100644 (file)
index 0000000..341f175
--- /dev/null
@@ -0,0 +1,27 @@
+#define uu_width 48
+#define uu_height 48
+static char uu_bits[] = {
+   0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00,
+   0x00, 0xc0, 0x81, 0x81, 0x03, 0x00, 0x00, 0x30, 0x7e, 0x7e, 0x0c, 0x00,
+   0x00, 0x88, 0x01, 0x80, 0x11, 0x00, 0x00, 0x66, 0x60, 0x06, 0x66, 0x00,
+   0x00, 0x79, 0xb0, 0x0d, 0x9f, 0x00, 0x80, 0x14, 0x4e, 0x72, 0x21, 0x01,
+   0x40, 0x66, 0x54, 0x2a, 0x46, 0x02, 0x20, 0x89, 0x24, 0xa4, 0xf1, 0x04,
+   0xa0, 0x71, 0x93, 0xc9, 0x4c, 0x05, 0x50, 0xe5, 0x7c, 0x3e, 0x33, 0x0a,
+   0x48, 0x2a, 0x8a, 0x4b, 0x94, 0x13, 0xa8, 0x98, 0x15, 0x89, 0x49, 0x16,
+   0x24, 0x49, 0x2c, 0xe5, 0x52, 0x26, 0xd4, 0xab, 0xa5, 0xd5, 0xd4, 0x28,
+   0x94, 0x64, 0xf3, 0x8f, 0x26, 0x28, 0x0a, 0x95, 0xfd, 0x7f, 0xaf, 0x50,
+   0x2a, 0xaa, 0x7f, 0xfe, 0x56, 0x5f, 0x5a, 0xeb, 0x7a, 0x5e, 0x51, 0x55,
+   0xba, 0x0a, 0xff, 0xff, 0x50, 0x53, 0xca, 0x0a, 0xf5, 0xaf, 0xd0, 0x50,
+   0x0a, 0xfa, 0xff, 0xff, 0x5f, 0x50, 0x05, 0x47, 0xb7, 0x2e, 0xe3, 0xaf,
+   0xf5, 0x47, 0xb3, 0x74, 0xe1, 0xa9, 0x0a, 0x8a, 0xd6, 0xd4, 0x51, 0x56,
+   0x8a, 0xfa, 0xff, 0xff, 0x5f, 0x50, 0x8a, 0x4a, 0xe9, 0x97, 0xd2, 0x51,
+   0xfa, 0x6a, 0x57, 0x6a, 0xd3, 0x5e, 0x0a, 0xda, 0x4a, 0xd6, 0xd5, 0x5a,
+   0x0a, 0x55, 0xac, 0x35, 0x2a, 0x58, 0x94, 0xa4, 0xf3, 0xce, 0xe5, 0x28,
+   0x54, 0x29, 0x9b, 0xc9, 0x14, 0x29, 0xe4, 0x4b, 0x32, 0x54, 0xb2, 0x27,
+   0x28, 0x9c, 0x89, 0xbd, 0xc9, 0x14, 0x48, 0x32, 0x8a, 0x49, 0x94, 0x12,
+   0xd0, 0xc4, 0x7c, 0x3e, 0x2b, 0x0a, 0xa0, 0x33, 0xd3, 0xcb, 0x4d, 0x05,
+   0x20, 0x59, 0x1c, 0xf8, 0x8a, 0x04, 0x40, 0x2a, 0x23, 0xa4, 0x4c, 0x02,
+   0x80, 0x94, 0x45, 0x42, 0x29, 0x01, 0x00, 0x99, 0x26, 0x04, 0x99, 0x00,
+   0x00, 0xe6, 0x92, 0xc9, 0x66, 0x00, 0x00, 0x88, 0xe9, 0x97, 0x11, 0x00,
+   0x00, 0x30, 0x7e, 0x7e, 0x0c, 0x00, 0x00, 0xc0, 0x81, 0x81, 0x03, 0x00,
+   0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00};
diff --git a/texi/picons/stanford.png b/texi/picons/stanford.png
new file mode 100644 (file)
index 0000000..b3f5dec
Binary files /dev/null and b/texi/picons/stanford.png differ
diff --git a/texi/picons/sun.png b/texi/picons/sun.png
new file mode 100644 (file)
index 0000000..f010f16
Binary files /dev/null and b/texi/picons/sun.png differ
diff --git a/texi/picons/ubc.xbm b/texi/picons/ubc.xbm
new file mode 100644 (file)
index 0000000..51dda39
--- /dev/null
@@ -0,0 +1,27 @@
+#define ubc_width 48
+#define ubc_height 48
+static char ubc_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x80, 0xc3, 0x10, 0xf8, 0x80, 0x03,
+   0x80, 0xe7, 0x39, 0x73, 0x8c, 0x03, 0x80, 0xe7, 0x39, 0x67, 0xbe, 0x03,
+   0x80, 0xe7, 0x39, 0x27, 0xff, 0x03, 0x80, 0xe7, 0x39, 0x33, 0xff, 0x03,
+   0x80, 0xe7, 0x39, 0x38, 0xff, 0x03, 0x80, 0xe7, 0x39, 0x33, 0xff, 0x03,
+   0x80, 0xe7, 0x39, 0x27, 0xff, 0x03, 0x80, 0xe7, 0x39, 0x67, 0xbe, 0x03,
+   0x80, 0xcf, 0x3c, 0x73, 0x8c, 0x03, 0x80, 0x1f, 0x1e, 0xf8, 0xc0, 0x03,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x03,
+   0x80, 0xff, 0x7f, 0xfc, 0xff, 0x03, 0x80, 0x07, 0x8e, 0xe3, 0xc0, 0x03,
+   0x80, 0xfb, 0xf1, 0x1f, 0xbf, 0x03, 0x80, 0xff, 0x7f, 0xfc, 0xff, 0x03,
+   0x80, 0x07, 0x8e, 0xe3, 0xc0, 0x03, 0x80, 0xfb, 0xf1, 0x1f, 0xbf, 0x03,
+   0x80, 0xff, 0x7f, 0xfc, 0xff, 0x03, 0x80, 0x07, 0x8e, 0xe3, 0xc0, 0x03,
+   0x80, 0xfb, 0xf1, 0x1f, 0xbf, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01,
+   0x00, 0xff, 0xff, 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0xfe, 0xff, 0x00,
+   0x00, 0xfe, 0xef, 0xee, 0xff, 0x00, 0x00, 0xfc, 0xce, 0xe6, 0x7e, 0x00,
+   0x00, 0xec, 0xcd, 0x66, 0x6f, 0x00, 0x00, 0xd8, 0xd9, 0x36, 0x37, 0x00,
+   0x00, 0x98, 0x99, 0x32, 0x33, 0x00, 0x00, 0x30, 0x13, 0x90, 0x19, 0x00,
+   0x00, 0x60, 0x02, 0x80, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x06, 0x00,
+   0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0x00,
+   0x00, 0x00, 0x06, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x00,
+   0x00, 0x00, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00,
+   0x00, 0x00, 0xe0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/ufl.png b/texi/picons/ufl.png
new file mode 100644 (file)
index 0000000..9521710
Binary files /dev/null and b/texi/picons/ufl.png differ
diff --git a/texi/picons/uio.png b/texi/picons/uio.png
new file mode 100644 (file)
index 0000000..66ff8b0
Binary files /dev/null and b/texi/picons/uio.png differ
diff --git a/texi/picons/unit.png b/texi/picons/unit.png
new file mode 100644 (file)
index 0000000..1dea18d
Binary files /dev/null and b/texi/picons/unit.png differ
diff --git a/texi/picons/upenn.xbm b/texi/picons/upenn.xbm
new file mode 100644 (file)
index 0000000..c9b8894
--- /dev/null
@@ -0,0 +1,27 @@
+#define upenn_width 48
+#define upenn_height 48
+static char upenn_bits[] = {
+   0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00,
+   0x00, 0xfd, 0xff, 0xff, 0xbf, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xbf, 0x00,
+   0x00, 0xad, 0xfa, 0x5f, 0xb5, 0x00, 0x00, 0xf5, 0xff, 0xff, 0xaf, 0x00,
+   0x00, 0x5d, 0x1a, 0x5a, 0xba, 0x00, 0x00, 0x95, 0xde, 0x76, 0xa9, 0x00,
+   0x00, 0x5d, 0x2a, 0x55, 0xba, 0x00, 0x00, 0x95, 0xee, 0x79, 0xa9, 0x00,
+   0x00, 0x5d, 0xfa, 0x5f, 0xba, 0x00, 0x00, 0xf5, 0xff, 0xff, 0xaf, 0x00,
+   0x00, 0xad, 0xfa, 0x5f, 0xb5, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xbf, 0x00,
+   0x00, 0xfd, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x05, 0x80, 0x01, 0xa0, 0x00,
+   0x00, 0x05, 0xc0, 0x03, 0xa0, 0x00, 0x00, 0x05, 0xe0, 0x07, 0xa0, 0x00,
+   0x00, 0x05, 0xf0, 0x0f, 0xa0, 0x00, 0x00, 0x05, 0x78, 0x1e, 0xa0, 0x00,
+   0x00, 0x05, 0x3c, 0x3c, 0xa0, 0x00, 0x00, 0x05, 0x1e, 0x78, 0xa0, 0x00,
+   0x00, 0x09, 0x1f, 0xf8, 0x90, 0x00, 0x00, 0x8a, 0x3f, 0xfc, 0x51, 0x00,
+   0x00, 0xca, 0x79, 0x9e, 0x53, 0x00, 0x00, 0xea, 0xf0, 0x0f, 0x57, 0x00,
+   0x00, 0x72, 0xe0, 0x07, 0x4e, 0x00, 0x00, 0x74, 0xe0, 0x07, 0x2e, 0x00,
+   0x00, 0xe4, 0x70, 0x0e, 0x27, 0x00, 0x00, 0xe8, 0x39, 0x9c, 0x17, 0x00,
+   0x00, 0xc8, 0x1f, 0xf8, 0x13, 0x00, 0x00, 0xd0, 0x0f, 0xf0, 0x0b, 0x00,
+   0x00, 0x90, 0x07, 0xe0, 0x09, 0x00, 0x00, 0xa0, 0x03, 0xc0, 0x05, 0x00,
+   0x00, 0x20, 0x01, 0x80, 0x04, 0x00, 0x1b, 0x47, 0x02, 0x40, 0xe2, 0xd8,
+   0xf5, 0x88, 0x04, 0x20, 0x11, 0xaf, 0x1d, 0x09, 0x19, 0x98, 0x90, 0xb8,
+   0xc5, 0x05, 0x62, 0x46, 0xa0, 0xa3, 0xe7, 0x0b, 0x8c, 0x31, 0xd0, 0xe7,
+   0x58, 0x39, 0x30, 0x0c, 0x9c, 0x1a, 0x70, 0xed, 0xc3, 0xc3, 0xb7, 0x0e,
+   0x00, 0x11, 0x3c, 0x3c, 0x88, 0x00, 0x00, 0xf2, 0xc1, 0x83, 0x4f, 0x00,
+   0x00, 0x4c, 0x15, 0xa8, 0x32, 0x00, 0x00, 0xf0, 0x72, 0x4d, 0x0f, 0x00,
+   0x00, 0x80, 0x07, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00};
diff --git a/texi/picons/wesleyan.xbm b/texi/picons/wesleyan.xbm
new file mode 100644 (file)
index 0000000..e3b7a86
--- /dev/null
@@ -0,0 +1,27 @@
+#define wesleyan_width 48
+#define wesleyan_height 48
+static char wesleyan_bits[] = {
+   0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00,
+   0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0xf8, 0x0f, 0xe0, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0x00,
+   0x00, 0xff, 0x01, 0x10, 0xfc, 0x01, 0x80, 0x9f, 0x00, 0x30, 0xf0, 0x03,
+   0xc0, 0x8f, 0x00, 0x48, 0xe0, 0x07, 0xc0, 0x47, 0x00, 0x84, 0xc0, 0x07,
+   0xe0, 0x43, 0x00, 0x84, 0x80, 0x0f, 0xf0, 0x21, 0x00, 0x02, 0x01, 0x1f,
+   0xf0, 0x20, 0x00, 0x02, 0x01, 0x1e, 0xf8, 0x20, 0x00, 0x42, 0x01, 0x3e,
+   0x78, 0x10, 0x00, 0x81, 0x00, 0x3c, 0x7c, 0x10, 0x00, 0xa1, 0x00, 0x7c,
+   0x3c, 0x10, 0x00, 0x21, 0x01, 0x78, 0x3c, 0x08, 0x80, 0x00, 0x02, 0x78,
+   0x3c, 0x08, 0x80, 0x00, 0x04, 0x78, 0x1e, 0x08, 0x80, 0x00, 0x08, 0xf0,
+   0x1e, 0x04, 0x40, 0x00, 0x08, 0xf0, 0x1e, 0x04, 0x40, 0xc0, 0x07, 0xf0,
+   0x1e, 0x04, 0x40, 0x80, 0x00, 0xf0, 0x1e, 0x02, 0x20, 0xc0, 0x00, 0xf0,
+   0x1e, 0x02, 0x10, 0x80, 0x00, 0xf0, 0x1e, 0x02, 0x10, 0x40, 0x00, 0xf0,
+   0x1e, 0x01, 0x10, 0x20, 0x00, 0xf0, 0x9e, 0x02, 0x10, 0x40, 0x00, 0xf0,
+   0xbc, 0x18, 0x10, 0x40, 0x00, 0x78, 0xbc, 0x40, 0x10, 0x40, 0x00, 0x78,
+   0xbc, 0x01, 0x12, 0x3e, 0x00, 0x78, 0x7c, 0x0e, 0xf8, 0x03, 0x00, 0x7c,
+   0x78, 0x70, 0x24, 0x06, 0x00, 0x3c, 0xf8, 0x80, 0xe2, 0x0e, 0x00, 0x3e,
+   0xf0, 0x3e, 0x21, 0x16, 0x00, 0x1e, 0xf0, 0xc1, 0xf0, 0x23, 0x00, 0x1f,
+   0xe0, 0x1b, 0x13, 0x49, 0x80, 0x0f, 0xc0, 0x67, 0x74, 0x51, 0xc0, 0x07,
+   0xc0, 0x8f, 0x13, 0x55, 0xe0, 0x07, 0x80, 0x1f, 0x14, 0xa5, 0xf0, 0x03,
+   0x00, 0x7f, 0xe4, 0x8a, 0xfc, 0x01, 0x00, 0xfe, 0x21, 0x92, 0xff, 0x00,
+   0x00, 0xf8, 0xaf, 0xe3, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00,
+   0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/texi/picons/yale.xbm b/texi/picons/yale.xbm
new file mode 100644 (file)
index 0000000..9915964
--- /dev/null
@@ -0,0 +1,27 @@
+#define yale_width 48
+#define yale_height 48
+static char yale_bits[] = {
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0x55, 0x55, 0x55, 0x55, 0xd5,
+   0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x57, 0x55, 0x55, 0x55, 0x55, 0xd5,
+   0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x17, 0x00, 0x55, 0x55, 0x01, 0xd4,
+   0xab, 0x3f, 0xa8, 0xaa, 0xf8, 0xea, 0x07, 0xc1, 0x01, 0x00, 0x8e, 0xc0,
+   0x33, 0x01, 0xfe, 0xfe, 0x81, 0xcc, 0x2b, 0x01, 0x00, 0x01, 0x80, 0xd4,
+   0xab, 0x01, 0x00, 0x01, 0x80, 0xd5, 0x4b, 0x35, 0x6e, 0xbd, 0xa5, 0xd2,
+   0x2b, 0x6d, 0x6e, 0xbd, 0xad, 0xd4, 0x93, 0x49, 0x4a, 0x21, 0x99, 0xc9,
+   0xe3, 0x49, 0x4a, 0x21, 0x99, 0xc6, 0x07, 0x49, 0x4a, 0x21, 0xb5, 0xe0,
+   0x0b, 0x75, 0x4b, 0x21, 0xa5, 0xd0, 0x07, 0x01, 0x00, 0x01, 0x80, 0xe0,
+   0x33, 0x41, 0x00, 0x11, 0x80, 0xcc, 0x2b, 0x81, 0x33, 0xe1, 0x8c, 0xd4,
+   0xab, 0x81, 0x27, 0xe1, 0x89, 0xd5, 0x4b, 0x81, 0x04, 0x21, 0x81, 0xd2,
+   0x2b, 0x81, 0x04, 0x21, 0x81, 0xd4, 0x93, 0x81, 0x07, 0xe1, 0x81, 0xc9,
+   0x63, 0x01, 0x00, 0x01, 0x80, 0xc6, 0x07, 0xff, 0x7f, 0xfd, 0xff, 0xe0,
+   0x2e, 0xfe, 0xff, 0xff, 0x7f, 0x6a, 0x56, 0x00, 0x80, 0x01, 0x00, 0x75,
+   0xac, 0xaa, 0x2a, 0xa8, 0xaa, 0x3a, 0x5c, 0x55, 0x55, 0x55, 0x55, 0x1d,
+   0xb8, 0xaa, 0xaa, 0xaa, 0xaa, 0x0e, 0x70, 0x55, 0x55, 0x55, 0x55, 0x07,
+   0xe0, 0xaa, 0xaa, 0xaa, 0xaa, 0x03, 0x80, 0x57, 0x55, 0x55, 0xd5, 0x01,
+   0x00, 0xae, 0xaa, 0xaa, 0x7a, 0x00, 0x00, 0x78, 0x55, 0x55, 0x1d, 0x00,
+   0x00, 0xe0, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x80, 0x57, 0xf5, 0x01, 0x00,
+   0x00, 0x00, 0xbc, 0x3a, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0xcc, 0x30, 0x0c, 0x7e, 0x00,
+   0x00, 0xcc, 0x30, 0x0c, 0x06, 0x00, 0x00, 0x78, 0x78, 0x0c, 0x06, 0x00,
+   0x00, 0x30, 0x58, 0x0c, 0x3e, 0x00, 0x00, 0x30, 0xfc, 0x0c, 0x06, 0x00,
+   0x00, 0x30, 0x8c, 0x0c, 0x06, 0x00, 0x00, 0x30, 0x8e, 0xfd, 0x7e, 0x00};
index 3b5f803..f4f6bf3 100644 (file)
 \thispagestyle{empty}
 \vfill
 
-\begin{picture}(10,10)
-\put(90,-10){\makebox(0,0)[tr]{\epsfig{figure=tmp/larsi.ps,height=3cm}}}
-\end{picture}
-
-\hspace*{4cm}\parbox[t]{10cm}{
-This manual was written by Lars Magne Ingebrigtsen (b. 1968) who
+This manual was written by Lars Magne Ingebrigtsen (1968 --- ) who
 resides in Oslo, Norway and poses as a student, but doesn't get much
 studying done, for some strange reason or other.  When not worshipping
 at the altar of Emacs, he can often be found slouching on his couch
 reading while bopping his head gently to some obscure music.  He does
 not have a cat.
 
-Graphics by Luis Fernandes.  Set in Bembo and Futura.
-}
+\marginpar[\vspace*{-2.5cm}\epsfig{figure=ps/larsi,height=2cm}]{\vspace*{-2.2cm}\epsfig{figure=ps/larsi,height=2.5cm}}
+
+Graphics by Luis Fernandes.  \gnususefonts{}
 
 \clearpage
 \mbox{}
 \thispagestyle{empty}
 \begin{picture}(500,500)(0,0)
-\put(-35,325){\makebox(480,350)[tr]{\epsfig{figure=tmp/new-herd-section.ps}}}
+\put(-35,325){\makebox(480,350)[tr]{\epsfig{figure=ps/new-herd-section}}}
 \end{picture}
 
 \end{document}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 
diff --git a/texi/ps/Makefile.in b/texi/ps/Makefile.in
new file mode 100644 (file)
index 0000000..644ad50
--- /dev/null
@@ -0,0 +1,213 @@
+infodir = @infodir@
+prefix = @prefix@
+srcdir = @srcdir@
+subdir = texi/ps
+top_srcdir = @top_srcdir@
+
+SCREEN_PS= group-topic.ps group.ps server.ps summary-adopt.ps          \
+summary-article-c-ug.ps summary-article.ps summary-dummy.ps            \
+summary-empty.ps summary-none.ps summary-unthreaded.ps summary.ps
+
+HERDS_PS= gnus-herd-bw.ps gnus-herd-new.ps new-herd-1.ps               \
+ new-herd-2.ps new-herd-3.ps new-herd-4.ps new-herd-5.ps       \
+new-herd-6.ps new-herd-7.ps new-herd-8.ps new-herd-9.ps                        \
+new-herd-section.ps new-herd.ps new-herd2.ps
+
+MISC_PS= ered.ps eseptember.ps fred.ps fseptember.ps larsi.ps red.ps   \
+september.ps
+
+ETC_PS= bar.ps gnus-group-catchup-current-up.ps                                \
+gnus-group-catchup-current.ps gnus-group-describe-group-up.ps          \
+gnus-group-exit-up.ps gnus-group-get-new-news-this-group-up.ps         \
+gnus-group-get-new-news-up.ps gnus-group-kill-group-up.ps              \
+gnus-group-subscribe-up.ps gnus-group-unsubscribe-up.ps                        \
+gnus-summary-caesar-message-up.ps gnus-summary-cancel-article-up.ps    \
+gnus-summary-catchup-and-exit-up.ps gnus-summary-catchup-up.ps         \
+gnus-summary-exit-up.ps gnus-summary-followup-up.ps                    \
+gnus-summary-followup-with-original-up.ps gnus-summary-mail-copy-up.ps \
+gnus-summary-mail-delete-up.ps gnus-summary-mail-forward-up.ps         \
+gnus-summary-mail-get-up.ps gnus-summary-mail-originate-up.ps          \
+gnus-summary-mail-reply-up.ps gnus-summary-mail-save-up.ps             \
+gnus-summary-next-unread-up.ps gnus-summary-post-news-up.ps            \
+gnus-summary-prev-unread-up.ps gnus-summary-reply-up.ps                        \
+gnus-summary-reply-with-original-up.ps                                 \
+gnus-summary-save-article-file-up.ps gnus-summary-save-article-up.ps   \
+gnus-uu-decode-uu-up.ps gnus-uu-post-news-up.ps gnus.ps
+
+PICONS_PS= picons-att.ps picons-berkeley.ps picons-caltech.ps  \
+picons-canada.ps picons-cr.ps picons-cygnus.ps picons-gnu.ps   \
+picons-gov.ps picons-laurie.ps picons-mit.ps picons-nasa.ps    \
+picons-qmw.ps picons-rms.ps picons-ruu.ps picons-seuu.ps       \
+picons-stanford.ps picons-sun.ps picons-ubc.ps picons-ufl.ps   \
+picons-uio.ps picons-unit.ps picons-upenn.ps picons-wesleyan.ps        \
+picons-yale.ps
+
+XFACE_PS= xface-abrahamsen.ps xface-aichner.ps xface-blanks.ps         \
+xface-cosgriff.ps xface-drazen.ps xface-gertzfield.ps                  \
+xface-goldberg.ps xface-graf.ps xface-hardaker.ps xface-hedbor.ps      \
+xface-ingrand.ps xface-kaplan.ps xface-karlheg.ps xface-kleinpaste.ps  \
+xface-kyle.ps xface-love.ps xface-moll.ps xface-niksic.ps              \
+xface-olsen.ps xface-patch.ps xface-petersen.ps xface-pjf.ps           \
+xface-riocreux.ps xface-schauer.ps xface-simmonmt.ps xface-simmons.ps  \
+xface-siu.ps xface-smb.ps xface-sobek.ps xface-thomas.ps               \
+xface-valdis.ps xface-verna1.ps xface-verna2.ps xface-yamaoka.ps
+
+SMILIES_PS= BigFace.ps smiley-FaceAngry.ps smiley-FaceDevilish.ps      \
+smiley-FaceGoofy.ps smiley-FaceGrinning.ps smiley-FaceHappy.ps         \
+smiley-FaceIronic.ps smiley-FaceKOed.ps smiley-FaceNyah.ps             \
+smiley-FaceSad.ps smiley-FaceStartled.ps smiley-FaceStraight.ps                \
+smiley-FaceTalking.ps smiley-FaceTasty.ps smiley-FaceWinking.ps                \
+smiley-FaceWry.ps smiley-FaceYukky.ps smiley-WideFaceAse1.ps           \
+smiley-WideFaceAse2.ps smiley-WideFaceAse3.ps smiley-WideFaceSmile.ps  \
+smiley-WideFaceWeep.ps
+
+EPS= gnus-big-logo.ps  gnus-head.ps
+
+PSFILES= $(SCREEN_PS) $(HERDS_PS) $(ETC_PS) $(PICONS_PS) $(XFACE_PS)   \
+$(SMILIES_PS) $(MISC_PS) $(EPS)
+
+SCREEN_PDF= group-topic.pdf group.pdf server.pdf summary-adopt.pdf     \
+summary-article-c-ug.pdf summary-article.pdf summary-dummy.pdf         \
+summary-empty.pdf summary-none.pdf summary-unthreaded.pdf summary.pdf
+
+HERDS_PDF= gnus-herd-bw.pdf gnus-herd-new.pdf new-herd-1.pdf   \
+ new-herd-2.pdf new-herd-3.pdf new-herd-4.pdf  \
+new-herd-5.pdf new-herd-6.pdf new-herd-7.pdf new-herd-8.pdf    \
+new-herd-9.pdf new-herd-section.pdf new-herd.pdf new-herd2.pdf
+
+MISC_PDF= ered.pdf eseptember.pdf fred.pdf fseptember.pdf larsi.pdf    \
+red.pdf september.pdf
+
+ETC_PDF= bar.pdf gnus-group-catchup-current-up.pdf                     \
+gnus-group-catchup-current.pdf gnus-group-describe-group-up.pdf                \
+gnus-group-exit-up.pdf gnus-group-get-new-news-this-group-up.pdf       \
+gnus-group-get-new-news-up.pdf gnus-group-kill-group-up.pdf            \
+gnus-group-subscribe-up.pdf gnus-group-unsubscribe-up.pdf              \
+gnus-summary-caesar-message-up.pdf gnus-summary-cancel-article-up.pdf  \
+gnus-summary-catchup-and-exit-up.pdf gnus-summary-catchup-up.pdf       \
+gnus-summary-exit-up.pdf gnus-summary-followup-up.pdf                  \
+gnus-summary-followup-with-original-up.pdf                             \
+gnus-summary-mail-copy-up.pdf gnus-summary-mail-delete-up.pdf          \
+gnus-summary-mail-forward-up.pdf gnus-summary-mail-get-up.pdf          \
+gnus-summary-mail-originate-up.pdf gnus-summary-mail-reply-up.pdf      \
+gnus-summary-mail-save-up.pdf gnus-summary-next-unread-up.pdf          \
+gnus-summary-post-news-up.pdf gnus-summary-prev-unread-up.pdf          \
+gnus-summary-reply-up.pdf gnus-summary-reply-with-original-up.pdf      \
+gnus-summary-save-article-file-up.pdf gnus-summary-save-article-up.pdf \
+gnus-uu-decode-uu-up.pdf gnus-uu-post-news-up.pdf gnus.pdf
+
+PICONS_PDF= picons-att.pdf picons-berkeley.pdf picons-caltech.pdf      \
+picons-canada.pdf picons-cr.pdf picons-cygnus.pdf picons-gnu.pdf       \
+picons-gov.pdf picons-laurie.pdf picons-mit.pdf picons-nasa.pdf                \
+picons-qmw.pdf picons-rms.pdf picons-ruu.pdf picons-seuu.pdf           \
+picons-stanford.pdf picons-sun.pdf picons-ubc.pdf picons-ufl.pdf       \
+picons-uio.pdf picons-unit.pdf picons-upenn.pdf picons-wesleyan.pdf    \
+picons-yale.pdf
+
+XFACE_PDF= xface-abrahamsen.pdf xface-aichner.pdf xface-blanks.pdf     \
+xface-cosgriff.pdf xface-drazen.pdf xface-gertzfield.pdf               \
+xface-goldberg.pdf xface-graf.pdf xface-hardaker.pdf xface-hedbor.pdf  \
+xface-ingrand.pdf xface-kaplan.pdf xface-karlheg.pdf                   \
+xface-kleinpaste.pdf xface-kyle.pdf xface-love.pdf xface-moll.pdf      \
+xface-niksic.pdf xface-olsen.pdf xface-patch.pdf xface-petersen.pdf    \
+xface-pjf.pdf xface-riocreux.pdf xface-schauer.pdf xface-simmonmt.pdf  \
+xface-simmons.pdf xface-siu.pdf xface-smb.pdf xface-sobek.pdf          \
+xface-thomas.pdf xface-valdis.pdf xface-verna1.pdf xface-verna2.pdf    \
+xface-yamaoka.pdf
+
+SMILIES_PDF= BigFace.pdf smiley-FaceAngry.pdf smiley-FaceDevilish.pdf  \
+smiley-FaceGoofy.pdf smiley-FaceGrinning.pdf smiley-FaceHappy.pdf      \
+smiley-FaceIronic.pdf smiley-FaceKOed.pdf smiley-FaceNyah.pdf          \
+smiley-FaceSad.pdf smiley-FaceStartled.pdf smiley-FaceStraight.pdf     \
+smiley-FaceTalking.pdf smiley-FaceTasty.pdf smiley-FaceWinking.pdf     \
+smiley-FaceWry.pdf smiley-FaceYukky.pdf smiley-WideFaceAse1.pdf                \
+smiley-WideFaceAse2.pdf smiley-WideFaceAse3.pdf                                \
+smiley-WideFaceSmile.pdf smiley-WideFaceWeep.pdf
+
+EPS_PDF= gnus-big-logo.pdf  gnus-head.pdf
+
+PDFFILES= $(SCREEN_PDF) $(HERDS_PDF) $(ETC_PDF) $(PICONS_PDF)  \
+$(XFACE_PDF) $(SMILIES_PDF) $(MISC_PDF) $(EPS_PDF)
+
+all: $(PSFILES) $(EPS)
+
+pdf: $(PDFFILES)
+
+.ps.pdf:
+       epstopdf $<
+
+.SUFFIXES: .pdf .ps .eps .xbm .xpm .png .tif .gif 
+
+clean:
+       rm -f $(PSFILES)
+       rm -f $(PDFFILES)
+
+veryclean: clean
+
+distclean: clean
+
+install:
+
+new-herd-section.ps: $(srcdir)/../herds/new-herd-section.png $(srcdir)/../herds/convol11.pnm
+       pngtopnm $< | pnmscale 4 | pnmconvol $(srcdir)/../herds/convol11.pnm |\
+       ppmtopgm | pnmdepth 255 | \
+       pnmtops -noturn -width 100 -height 100 > $@ || rm -f $@
+
+%.ps: $(srcdir)/../herds/%.png $(srcdir)/../herds/convol5.pnm
+       pngtopnm $< | pnmcrop -white | pnmmargin -white 9 | pnmscale 2 | \
+       pnmconvol $(srcdir)/../herds/convol5.pnm  | ppmtopgm | \
+       pnmdepth 255 | pnmtops -width 100 -height 100 -noturn > $@ || rm -f $@
+
+
+%.ps: $(srcdir)/../screen/%.png
+       pngtopnm $< | pnmmargin -black 1 | ppmtopgm | \
+       pnmtops -width 100 -height 100 -noturn > $@ || rm -f $@
+
+larsi.ps: $(srcdir)/../misc/larsi.png
+       pngtopnm $< | ppmtopgm | pnmtops -noturn > $@ || rm -f $@
+
+september.ps: $(srcdir)/../misc/eseptember.tif
+       tifftopnm $< | pnmscale 4 | ppmtopgm | \
+       pnmtops -noturn  -width 100 -height 100 > $@ || rm -f $@
+
+red.ps: $(srcdir)/../misc/ered.tif
+       tifftopnm $< | pnmscale 2 | ppmtopgm | \
+       pnmtops -noturn  -width 100 -height 100 > $@ || rm -f $@
+
+%.ps: $(srcdir)/../misc/%.tif
+       tifftopnm $< | pnmscale 2 | ppmtopgm |  \
+       pnmtops -noturn  -width 100 -height 100 > $@ || rm -f $@
+
+%.ps: $(srcdir)/../etc/%.xpm
+       xpmtoppm $< | ppmtopgm | pnmdepth 255 | \
+       pnmtops -noturn > $@ || rm -f $@
+
+picons-%.ps: $(srcdir)/../picons/%.xbm
+       xbmtopbm $< | pnmtops -noturn > $@ || rm -f $@
+
+picons-%.ps: $(srcdir)/../picons/%.png
+       pngtopnm $< | ppmtopgm | pnmtops -noturn > $@ || rm -f $@
+
+xface-%.ps: $(srcdir)/../xface/%.png
+       pngtopnm $< | ppmtopgm | pnmtops -noturn > $@ || rm -f $@
+
+%.ps: $(srcdir)/../smilies/%.tif
+       tifftopnm $< | ppmtopgm | pnmtops > $@ || rm -f $@
+
+smiley-%.ps: $(srcdir)/../smilies/%.xpm
+       sed "s/none/#FFFFFF/" $< | xpmtoppm | ppmtopgm | pnmdepth 255 | \
+       pnmtops > $@ || rm -f $@
+
+smiley-%.ps: $(srcdir)/../smilies/%.xbm
+       xbmtopbm $< | pnmdepth 255 | pnmtops > $@ || rm -f $@
+
+%.ps: $(srcdir)/%.eps
+       cp $< $@
+
+Makefile: $(srcdir)/Makefile.in ../../config.status
+       cd ../.. \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/texi/ps/gnus-big-logo.eps b/texi/ps/gnus-big-logo.eps
new file mode 100644 (file)
index 0000000..ea713d8
--- /dev/null
@@ -0,0 +1,212 @@
+%!PS-Adobe-2.0 EPSF-1.2
+%%Creator: Adobe Illustrator 88(TM) format generated by CorelTRACE Version 2.0C
+%%Title:  /home/menja/c/larsi/rgnus/texi/ps/eegnu.eps
+%%BoundingBox: 0 0 890.3 909.7
+%%CreationDate: Fri Oct 11 14:59:05 1996
+%%DocumentFonts:
+%%ColorUsage: B & W
+%%TileBox: 0 0 890.3 909.7
+%%EndComments
+% Copyright 1992 Corel Corporation.
+
+% All rights reserved.
+/wPSMDict 150 dict def
+wPSMDict begin
+/bd {bind def} bind def
+/ld {load def} bd
+/xd {exch def} bd
+/_ null def
+/$c 0 def
+/$m 0 def
+/$y 0 def
+/$k 0 def
+/$t 1 def
+/$n _ def
+/$o 0 def
+/$C 0 def
+/$M 0 def
+/$Y 0 def
+/$K 0 def
+/$T 1 def
+/$N _ def
+/$O 0 def
+/$h false def
+/$al 0 def
+/$tr 0 def
+/$le 0 def
+/$lx 0 def
+/$ly 0 def
+/$ctm matrix currentmatrix def
+/@cp /closepath ld
+/@gs /gsave ld
+/@gr /grestore ld
+/@MN {2 copy le{pop}{exch pop}ifelse}bd
+/setcmykcolor where {pop}{/setcmykcolor{4 1 roll
+3 {3 index add 1 @MN 1 exch sub 3 1 roll} repeat
+setrgbcolor
+pop}bd}ifelse
+/@tc{dup 1 ge{pop}{4 {dup
+6 -1 roll
+mul
+exch}repeat
+pop}ifelse}bd
+/@scc{$c $m $y $k $t @tc setcmykcolor true}bd
+/@SCC{$C $M $Y $K $T @tc setcmykcolor true}bd
+/@sm{/$ctm $ctm currentmatrix def}bd
+/x {/$t xd /$n xd
+/$k xd /$y xd /$m xd /$c xd}bd
+/X {/$T xd /$N xd
+/$K xd /$Y xd /$M xd /$C xd}bd
+/g {1 exch sub 0 0 0
+4 -1 roll
+_ 1 x}bd
+/G {1 exch sub 0 0 0
+4 -1 roll
+_ 1 X}bd
+/k {_ 1 x}bd
+/K {_ 1 X}bd
+/d /setdash ld
+/i {dup 0 ne {setflat} {pop} ifelse}bd
+/j /setlinejoin ld
+/J /setlinecap ld
+/M /setmiterlimit ld
+/w /setlinewidth ld
+/O {/$o xd}bd
+/R {/$O xd}bd
+/c /curveto ld
+/C /c ld
+/l /lineto ld
+/L /l ld
+/m /moveto ld
+/n /newpath ld
+/N /newpath ld
+/F {@scc{eofill}if n} bd
+/f {@cp F}bd
+/S {@SCC{stroke}if n} bd
+/s {@cp
+S}bd
+/B {@gs F @gr
+S}bd
+/b {@cp B }bd
+/u {}bd
+/U {}bd
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+1 i
+2 J
+0 j
+4 M
+[]0 d
+
+%%Note: traced as Normal_Outline
+0 g
+163.4 2.9 m
+197.1 51.5 223.7 94.3 251.6 130.7 C
+283.4 176.1 312.0 216.3 342.8 256.8 C
+373.2 303.2 401.1 342.1 420.0 396.9 C
+421.2 403.1 425.1 408.9 424.5 413.5 C
+395.6 371.6 368.4 326.2 337.2 285.0 C
+306.1 247.4 276.3 199.4 244.5 161.5 C
+212.1 116.7 182.9 79.1 168.6 20.4 C
+166.3 13.9 164.7 8.1 162.4 2.2 C
+162.4 2.2 163.4 2.9 163.4 2.9 C
+f
+0 g
+428.1 170.2 m
+428.1 170.2 429.7 170.2 430.0 170.5 C
+454.7 211.4 474.8 275.6 504.0 301.9 C
+512.1 300.6 515.0 280.8 527.3 283.1 C
+534.8 284.4 536.4 284.1 542.9 288.9 C
+571.4 331.1 600.3 374.5 623.6 423.2 C
+640.2 454.7 661.6 492.9 663.5 517.6 C
+660.3 515.6 L
+633.7 468.6 613.2 419.6 582.4 378.4 C
+572.1 367.1 566.5 352.8 550.7 348.3 C
+543.2 348.3 536.1 354.4 530.5 363.8 C
+528.9 367.1 528.9 368.1 525.4 369.7 C
+495.5 333.7 466.7 282.8 446.5 233.5 C
+436.2 206.2 433.2 190.0 427.4 170.5 C
+427.4 170.5 428.1 170.2 428.1 170.2 C
+f
+0 g
+754.7 271.7 m
+783.8 345.7 780.3 386.2 794.2 447.5 C
+806.2 497.1 819.2 543.8 843.5 614.9 C
+869.5 690.4 875.0 731.0 888.0 787.1 C
+892.5 826.7 892.8 865.9 869.5 898.7 C
+853.9 908.7 841.9 912.3 822.1 909.4 C
+785.5 890.2 764.1 846.4 749.8 799.7 C
+750.4 793.6 750.8 791.3 755.0 788.1 C
+755.6 788.1 756.9 788.1 757.9 788.1 C
+772.8 803.3 773.8 842.9 796.8 849.0 C
+817.6 849.0 826.3 847.7 840.3 834.8 C
+855.8 799.7 856.2 789.4 858.1 755.0 C
+855.2 687.5 836.7 643.7 819.8 576.9 C
+801.7 513.7 781.9 454.3 772.8 406.7 C
+766.3 361.6 755.0 332.4 754.0 271.7 C
+754.0 271.7 754.7 271.7 754.7 271.7 C
+f
+0 g
+383.0 484.8 m
+421.2 539.0 420.6 593.1 405.4 650.9 C
+395.0 674.5 382.7 683.6 367.7 695.0 C
+354.8 681.0 339.2 664.2 330.1 640.2 C
+330.1 640.2 330.1 638.5 330.4 638.2 C
+351.5 628.8 372.3 592.2 378.1 567.2 C
+381.0 544.5 378.8 505.2 382.3 484.8 C
+382.3 484.8 383.0 484.8 383.0 484.8 C
+f
+0 g
+120.6 509.8 m
+171.2 511.7 215.0 550.7 255.8 589.6 C
+283.4 609.7 302.2 627.8 315.8 663.5 C
+280.8 636.9 238.3 595.7 192.6 571.7 C
+179.6 566.2 162.4 565.6 147.8 570.4 C
+139.4 578.2 136.2 580.5 136.5 588.6 C
+144.6 635.3 192.3 684.3 217.6 724.8 C
+223.4 738.1 235.7 745.9 238.3 758.9 C
+204.3 726.8 174.1 677.1 147.5 634.3 C
+127.1 600.3 95.3 560.1 102.1 520.5 C
+107.0 510.8 111.8 513.7 120.6 509.8 C
+f
+0 g
+621.7 657.7 m
+669.0 661.2 703.4 716.1 724.8 769.6 C
+730.7 779.0 728.7 785.5 731.3 792.9 C
+711.8 758.5 695.0 728.4 656.7 720.9 C
+638.2 720.3 635.0 721.9 624.9 732.6 C
+621.7 736.5 620.4 739.4 618.1 744.3 C
+588.6 683.0 L
+593.1 671.6 598.3 665.5 608.1 661.9 C
+612.0 661.6 617.8 659.0 621.7 657.7 C
+f
+0 g
+502.0 681.0 m
+526.7 680.4 547.7 694.7 565.2 716.1 C
+576.0 734.9 583.1 755.0 592.2 775.4 C
+592.2 779.6 591.5 783.2 592.8 786.8 C
+582.4 775.7 571.4 752.7 549.7 746.5 C
+520.8 736.2 500.7 751.4 481.6 766.7 C
+440.4 802.3 416.7 847.7 366.8 868.5 C
+346.3 878.2 335.0 875.6 319.1 869.5 C
+300.3 862.7 292.8 850.7 279.2 833.8 C
+285.0 838.3 271.7 828.6 277.2 833.5 C
+268.5 845.8 244.2 875.3 220.8 881.1 C
+168.6 888.3 147.5 809.8 96.3 789.4 C
+83.3 784.8 72.0 776.7 61.2 781.6 C
+41.5 794.2 38.2 804.6 27.5 824.1 C
+2.2 764.7 L
+9.0 751.1 16.8 730.3 32.1 725.1 C
+45.0 720.3 55.1 721.6 68.1 727.1 C
+91.1 745.2 116.4 758.9 132.0 779.3 C
+140.1 789.4 146.5 797.5 157.6 808.5 C
+166.3 816.6 176.1 823.1 187.7 827.0 C
+219.2 813.0 240.6 789.7 259.1 759.5 C
+275.3 782.5 284.7 815.0 321.4 810.1 C
+373.9 801.4 405.0 751.7 443.6 715.1 C
+462.8 694.7 478.3 687.2 502.0 681.0 C
+f
+%%Trailer
+end
+showpage
diff --git a/texi/ps/gnus-head.eps b/texi/ps/gnus-head.eps
new file mode 100644 (file)
index 0000000..cb74c10
--- /dev/null
@@ -0,0 +1,149 @@
+%!PS-Adobe-2.0 EPSF-1.2
+%%Creator: Adobe Illustrator 88(TM) format generated by CorelTRACE Version 2.0C
+%%Title:  /home/menja/c/larsi/gnus-head.eps
+%%BoundingBox: 0 0 430.6 312.5
+%%CreationDate: Sat Feb  3 13:06:12 1996
+%%DocumentFonts:
+%%ColorUsage: B & W
+%%TileBox: 0 0 430.6 312.5
+%%EndComments
+% Copyright 1992 Corel Corporation.
+
+% All rights reserved.
+/wPSMDict 150 dict def
+wPSMDict begin
+/bd {bind def} bind def
+/ld {load def} bd
+/xd {exch def} bd
+/_ null def
+/$c 0 def
+/$m 0 def
+/$y 0 def
+/$k 0 def
+/$t 1 def
+/$n _ def
+/$o 0 def
+/$C 0 def
+/$M 0 def
+/$Y 0 def
+/$K 0 def
+/$T 1 def
+/$N _ def
+/$O 0 def
+/$h false def
+/$al 0 def
+/$tr 0 def
+/$le 0 def
+/$lx 0 def
+/$ly 0 def
+/$ctm matrix currentmatrix def
+/@cp /closepath ld
+/@gs /gsave ld
+/@gr /grestore ld
+/@MN {2 copy le{pop}{exch pop}ifelse}bd
+/setcmykcolor where {pop}{/setcmykcolor{4 1 roll
+3 {3 index add 1 @MN 1 exch sub 3 1 roll} repeat
+setrgbcolor
+pop}bd}ifelse
+/@tc{dup 1 ge{pop}{4 {dup
+6 -1 roll
+mul
+exch}repeat
+pop}ifelse}bd
+/@scc{$c $m $y $k $t @tc setcmykcolor true}bd
+/@SCC{$C $M $Y $K $T @tc setcmykcolor true}bd
+/@sm{/$ctm $ctm currentmatrix def}bd
+/x {/$t xd /$n xd
+/$k xd /$y xd /$m xd /$c xd}bd
+/X {/$T xd /$N xd
+/$K xd /$Y xd /$M xd /$C xd}bd
+/g {1 exch sub 0 0 0
+4 -1 roll
+_ 1 x}bd
+/G {1 exch sub 0 0 0
+4 -1 roll
+_ 1 X}bd
+/k {_ 1 x}bd
+/K {_ 1 X}bd
+/d /setdash ld
+/i {dup 0 ne {setflat} {pop} ifelse}bd
+/j /setlinejoin ld
+/J /setlinecap ld
+/M /setmiterlimit ld
+/w /setlinewidth ld
+/O {/$o xd}bd
+/R {/$O xd}bd
+/c /curveto ld
+/C /c ld
+/l /lineto ld
+/L /l ld
+/m /moveto ld
+/n /newpath ld
+/N /newpath ld
+/F {@scc{eofill}if n} bd
+/f {@cp F}bd
+/S {@SCC{stroke}if n} bd
+/s {@cp
+S}bd
+/B {@gs F @gr
+S}bd
+/b {@cp B }bd
+/u {}bd
+/U {}bd
+%%EndProlog
+%%BeginSetup
+%%EndSetup
+1 i
+2 J
+0 j
+4 M
+[]0 d
+
+%%Note: traced as Normal_Outline
+0 g
+267.8 10.0 m
+291.8 50.8 294.2 95.0 278.8 136.8 C
+270.2 147.3 264.9 154.5 252.4 156.9 C
+227.0 119.5 L
+256.3 98.8 267.3 63.3 264.0 12.4 C
+264.4 10.5 265.9 9.1 265.9 9.1 C
+265.9 9.1 267.8 10.0 267.8 10.0 C
+f
+0 g
+79.2 40.3 m
+116.6 43.6 150.2 75.3 180.9 103.6 C
+197.2 121.4 204.0 133.4 217.9 150.7 C
+216.4 151.2 215.0 152.1 213.1 152.1 C
+178.0 128.6 147.3 81.1 102.2 86.8 C
+98.4 88.8 95.0 89.2 92.6 92.1 C
+87.3 120.4 126.2 159.8 141.1 182.8 C
+148.8 193.4 159.3 203.0 159.8 217.4 C
+131.0 190.0 98.8 140.6 71.5 90.7 C
+65.2 76.3 58.0 67.6 63.3 53.7 C
+68.6 45.1 70.5 43.2 79.2 40.3 C
+f
+0 g
+355.6 161.2 m
+376.3 159.3 388.3 171.8 404.6 184.3 C
+412.3 201.1 422.4 223.2 423.3 237.6 C
+416.6 234.2 410.8 229.4 405.1 217.4 C
+399.8 211.6 386.8 206.8 378.7 207.8 C
+334.0 206.4 308.1 288.4 252.4 297.1 C
+236.1 299.5 229.9 291.8 214.5 285.6 C
+203.0 270.2 L
+193.4 281.7 175.2 306.7 147.8 303.3 C
+115.2 279.8 101.2 238.5 57.6 230.8 C
+42.7 235.2 26.8 240.9 21.1 253.4 C
+19.6 257.7 19.6 260.1 16.8 262.5 C
+14.4 259.2 12.9 257.7 11.5 253.4 C
+20.1 231.8 12.4 207.8 31.6 190.5 C
+45.6 184.8 60.4 188.1 74.8 201.6 C
+103.6 220.3 113.2 256.3 142.5 259.2 C
+164.1 248.1 178.5 237.1 189.1 214.0 C
+208.8 241.9 L
+225.6 253.4 243.8 250.0 262.0 241.4 C
+294.2 215.0 325.9 167.5 355.6 161.2 C
+f
+%%Trailer
+end
+showpage
diff --git a/texi/ptexinfmt.el b/texi/ptexinfmt.el
new file mode 100644 (file)
index 0000000..66a507f
--- /dev/null
@@ -0,0 +1,892 @@
+;;; ptexinfmt.el -- portable Texinfo formatter.
+
+;; Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993,
+;;               1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1999 Yoshiki Hayashi <yoshiki@xemacs.org>
+;; Copyright (C) 2000, 2001, 2002 TAKAHASHI Kaoru <kaoru@kaisei.org>
+
+;; Author: TAKAHASHI Kaoru <kaoru@kaisei.org>
+;;     Yoshiki Hayashi <yoshiki@xemacs.org>
+;;     Katsumi Yamaoka <yamaoka@jpl.org>
+;; Maintainer: TAKAHASHI Kaoru <kaoru@kaisei.org>
+;; Created: 7 Jul 2000
+;; Keywords: maint, tex, docs, emulation, compatibility
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Original code: Yoshiki Hayashi <yoshiki@xemacs.org>
+;;     makeinfo.el (gnujdoc project)
+
+;; Support texinfmt.el 2.32 or later.
+
+;; Modified by Yamaoka not to use APEL functions.
+
+;;; Code:
+
+(require 'backquote)
+(require 'texinfmt)
+
+;;; Broken
+(defvar ptexinfmt-disable-broken-notice-flag t
+  "If non-nil disable notice, when call `ptexinfmt-broken-facility'.
+This is last argument in `ptexinfmt-broken-facility'.")
+
+(put 'ptexinfmt-broken-facility 'lisp-indent-function 'defun)
+(defmacro ptexinfmt-broken-facility (facility docstring assertion
+                                             &optional dummy)
+  "Declare a symbol FACILITY is broken if ASSERTION is nil.
+DOCSTRING will be printed if ASSERTION is nil and
+`ptexinfmt-disable-broken-notice-flag' is nil."
+  (` (let ((facility '(, facility))
+          (docstring (, docstring))
+          (assertion (eval '(, assertion))))
+       (put facility 'broken (not assertion))
+       (if assertion
+          nil
+        (put facility 'broken-docstring docstring)
+        (if ptexinfmt-disable-broken-notice-flag
+            nil
+          (message "BROKEN FACILITY DETECTED: %s" docstring))))))
+
+(put 'ptexinfmt-defun-if-broken 'lisp-indent-function 'defun)
+(defmacro ptexinfmt-defun-if-broken (&rest args)
+  "Redefine a function just like `defun' if it is considered broken."
+  (let ((name (list 'quote (car args))))
+    (setq args (cdr args))
+    (` (prog1
+          (, name)
+        (if (get (, name) 'broken)
+            (defalias (, name)
+              (function (lambda (,@ args)))))))))
+
+(put 'ptexinfmt-defun-if-void 'lisp-indent-function 'defun)
+(defmacro ptexinfmt-defun-if-void (&rest args)
+  "Define a function just like `defun' unless it is already defined."
+  (let ((name (list 'quote (car args))))
+    (setq args (cdr args))
+    (` (prog1
+          (, name)
+        (if (fboundp (, name))
+            nil
+          (defalias (, name)
+            (function (lambda (,@ args)))))))))
+
+(put 'ptexinfmt-defvar-if-void 'lisp-indent-function 'defun)
+(defmacro ptexinfmt-defvar-if-void (&rest args)
+  "Define a variable just like `defvar' unless it is already defined."
+  (let ((name (car args)))
+    (setq args (cdr args))
+    (` (prog1
+          (defvar (, name))
+        (if (boundp '(, name))
+            nil
+          (defvar (, name) (,@ args)))))))
+
+;; sort -fd
+(ptexinfmt-broken-facility texinfo-format-printindex
+  "Can't sort on Mule for Windows."
+  (if (and (memq system-type '(windows-nt ms-dos))
+;;; I don't know version threshold.
+;;;       (string< texinfmt-version "2.37 of 24 May 1997")
+          (boundp 'MULE) (not (featurep 'meadow))) ; Mule for Windows
+      nil
+    t))
+
+;; @var
+(ptexinfmt-broken-facility texinfo-format-var
+  "Don't perse @var argument."
+  (condition-case nil
+      (with-temp-buffer
+       (let (texinfo-enclosure-list texinfo-alias-list)
+         (texinfo-mode)
+         (insert "@var{@asis{foo}}\n")
+         (texinfo-format-expand-region (point-min) (point-max))
+         t))
+    (error nil)))
+
+;; @xref
+(ptexinfmt-broken-facility texinfo-format-xref
+  "Can't format @xref, 1st argument is empty."
+  (condition-case nil
+      (with-temp-buffer
+       (let (texinfo-enclosure-list texinfo-alias-list)
+         (texinfo-mode)
+         (insert "@xref{, xref, , file}\n")
+         (texinfo-format-expand-region (point-min) (point-max))
+         t))
+    (error nil)))
+
+;; @uref
+(ptexinfmt-broken-facility texinfo-format-uref
+  "Parse twice @uref argument."
+  (condition-case nil
+      (with-temp-buffer
+       (let (texinfo-enclosure-list texinfo-alias-list)
+         (texinfo-mode)
+         (insert "@uref{mailto:foo@@noncommand.example.com}\n")
+         (texinfo-format-expand-region (point-min) (point-max))
+         t))
+    (error nil)))
+
+;; @multitable
+(ptexinfmt-broken-facility texinfo-multitable-widths
+  "`texinfo-multitable-widths' unsupport wide-char."
+  (if (fboundp 'texinfo-multitable-widths)
+      (with-temp-buffer
+       (let ((str "\e$BI}9-J8;z\e(B"))
+         (texinfo-mode)
+         (insert (format " {%s}\n" str))
+         (goto-char (point-min))
+         (if (= (car (texinfo-multitable-widths)) (length str))
+             nil
+           t)))
+    ;; function definition is void
+    t))
+
+(ptexinfmt-broken-facility texinfo-multitable-item
+  "`texinfo-multitable-item' unsupport wide-char."
+  (not (get 'texinfo-multitable-widths 'broken)))
+
+
+;;; Hardcopy and HTML (discard)
+;; html
+(put 'documentlanguage 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'documentencoding 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'documentdescription 'texinfo-format 'texinfo-discard-line-with-args)
+
+;; size
+(put 'smallbook 'texinfo-format 'texinfo-discard-line)
+(put 'letterpaper 'texinfo-format 'texinfo-discard-line)
+(put 'afourpaper 'texinfo-format 'texinfo-discard-line)
+(put 'afourlatex 'texinfo-format 'texinfo-discard-line)
+(put 'afourwide 'texinfo-format 'texinfo-discard-line)
+(put 'afivepaper 'texinfo-format 'texinfo-discard-line)
+(put 'pagesizes 'texinfo-format 'texinfo-discard-line-with-args)
+
+;; style
+(put 'setchapternewpage 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'kbdinputstyle 'texinfo-format 'texinfo-discard-line-with-args)
+
+;; flags
+(put 'setcontentsaftertitlepage 'texinfo-format 'texinfo-discard-line)
+(put 'setshortcontentsaftertitlepage 'texinfo-format 'texinfo-discard-line)
+(put 'novalidate 'texinfo-format 'texinfo-discard-line-with-args)
+
+;; head & foot
+(put 'headings 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'evenfooting 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'evenheading 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'oddfooting 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'oddheading 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'everyfooting 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'everyheading 'texinfo-format 'texinfo-discard-line-with-args)
+
+;; misc
+(put 'page 'texinfo-format 'texinfo-discard-line)
+(put 'hyphenation 'texinfo-format 'texinfo-discard-command-and-arg)
+
+;; @tie{} (makeinfo 4.3 or later)
+(put 'tie 'texinfo-format 'texinfo-format-tie)
+(ptexinfmt-defun-if-void texinfo-format-tie ()
+  (texinfo-parse-arg-discard)
+  (insert " "))
+
+\f
+;;; Directory File
+;; @direcategory
+(put 'dircategory 'texinfo-format 'texinfo-format-dircategory)
+(ptexinfmt-defun-if-void texinfo-format-dircategory ()
+  (let ((str (texinfo-parse-arg-discard)))
+    (delete-region (point)
+                  (progn
+                    (skip-chars-forward " ")
+                    (point)))
+    (insert "INFO-DIR-SECTION " str "\n")))
+
+;; @direntry
+(put 'direntry 'texinfo-format 'texinfo-format-direntry)
+(ptexinfmt-defun-if-void texinfo-format-direntry ()
+  (texinfo-push-stack 'direntry nil)
+  (texinfo-discard-line)
+  (insert "START-INFO-DIR-ENTRY\n"))
+
+(put 'direntry 'texinfo-end 'texinfo-end-direntry)
+(ptexinfmt-defun-if-void texinfo-end-direntry ()
+  (texinfo-discard-command)
+  (insert "END-INFO-DIR-ENTRY\n\n")
+  (texinfo-pop-stack 'direntry))
+
+
+;;; Block Enclosing
+;; @detailmenu ... @end detailmenu
+(put 'detailmenu 'texinfo-format 'texinfo-discard-line)
+(put 'detailmenu 'texinfo-end 'texinfo-discard-command)
+
+;; @smalldisplay ... @end smalldisplay
+(put 'smalldisplay 'texinfo-format 'texinfo-format-example)
+(put 'smalldisplay 'texinfo-end 'texinfo-end-example)
+
+;; @smallformat ... @end smallformat
+(put 'smallformat 'texinfo-format 'texinfo-format-flushleft)
+(put 'smallformat 'texinfo-end 'texinfo-end-flushleft)
+
+;; @cartouche  ... @end cartouche
+(put 'cartouche 'texinfo-format 'texinfo-discard-line)
+(put 'cartouche 'texinfo-end 'texinfo-discard-command)
+
+
+;;; Conditional
+;; @ifnottex ... @end ifnottex (makeinfo 3.11 or later)
+(put 'ifnottex 'texinfo-format 'texinfo-discard-line)
+(put 'ifnottex 'texinfo-end 'texinfo-discard-command)
+
+;; @ifnothtml ... @end ifnothtml (makeinfo 3.11 or later)
+(put 'ifnothtml 'texinfo-format 'texinfo-discard-line)
+(put 'ifnothtml 'texinfo-end 'texinfo-discard-command)
+
+;; @ifnotplaintext ... @end ifnotplaintext (makeinfo 4.2 or later)
+(put 'ifnotplaintext 'texinfo-format 'texinfo-discard-line)
+(put 'ifnotplaintext 'texinfo-end 'texinfo-discard-command)
+
+
+;; @ifnotinfo ... @end ifnotinfo (makeinfo 3.11 or later)
+(put 'ifnotinfo 'texinfo-format 'texinfo-format-ifnotinfo)
+(ptexinfmt-defun-if-void texinfo-format-ifnotinfo ()
+  (delete-region texinfo-command-start
+                (progn (re-search-forward "@end ifnotinfo[ \t]*\n")
+                       (point))))
+
+;; @html ... @end html (makeinfo 3.11 or later)
+(put 'html 'texinfo-format 'texinfo-format-html)
+(ptexinfmt-defun-if-void texinfo-format-html ()
+  (delete-region texinfo-command-start
+                (progn (re-search-forward "@end html[ \t]*\n")
+                       (point))))
+
+;; @ifhtml ... @end ifhtml (makeinfo 3.8 or later)
+(put 'ifhtml 'texinfo-format 'texinfo-format-ifhtml)
+(defun texinfo-format-ifhtml ()
+  (delete-region texinfo-command-start
+                (progn (re-search-forward "@end ifhtml[ \t]*\n")
+                       (point))))
+
+;; @ifplaintext ... @end ifplaintext (makeinfo 4.2 or later)
+(put 'ifplaintext 'texinfo-format 'texinfo-format-ifplaintext)
+(ptexinfmt-defun-if-void texinfo-format-ifplaintext ()
+  (delete-region texinfo-command-start
+                (progn (re-search-forward "@end ifplaintext[ \t]*\n")
+                       (point))))
+
+
+\f
+;;; Marking
+;; @url, @env, @command
+(put 'url 'texinfo-format 'texinfo-format-code)
+(put 'env 'texinfo-format 'texinfo-format-code)
+(put 'command 'texinfo-format 'texinfo-format-code)
+
+;; @acronym
+(put 'acronym 'texinfo-format 'texinfo-format-var)
+
+(ptexinfmt-defun-if-broken texinfo-format-var ()
+  (let ((arg (texinfo-parse-expanded-arg)))
+    (texinfo-discard-command)
+    (insert (upcase arg))))
+
+;; @key
+(put 'key 'texinfo-format 'texinfo-format-key)
+(ptexinfmt-defun-if-void texinfo-format-key ()
+  (insert (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @email{EMAIL-ADDRESS[, DISPLAYED-TEXT]}
+(put 'email 'texinfo-format 'texinfo-format-email)
+(ptexinfmt-defun-if-void texinfo-format-email ()
+  "Format EMAIL-ADDRESS and optional DISPLAYED-TXT.
+Insert < ... > around EMAIL-ADDRESS."
+  (let ((args (texinfo-format-parse-args)))
+  (texinfo-discard-command)
+    ;; if displayed-text
+    (if (nth 1 args)
+       (insert (nth 1 args) " <" (nth 0 args) ">")
+      (insert "<" (nth 0 args) ">"))))
+
+;; @option
+(put 'option 'texinfo-format 'texinfo-format-option)
+(ptexinfmt-defun-if-void texinfo-format-option ()
+  "Insert ` ... ' around arg unless inside a table; in that case, no quotes."
+  ;; `looking-at-backward' not available in v. 18.57, 20.2
+  ;; searched-for character is a control-H
+  (if (not (search-backward "\010"
+                           (save-excursion (beginning-of-line) (point))
+                           t))
+      (insert "`" (texinfo-parse-arg-discard) "'")
+    (insert (texinfo-parse-arg-discard)))
+  (goto-char texinfo-command-start))
+
+;; @verb{<char>TEXT<char>}  (makeinfo 4.1 or later)
+(put 'verb 'texinfo-format 'texinfo-format-verb)
+(ptexinfmt-defun-if-void texinfo-format-verb ()
+  "Format text between non-quoted unique delimiter characters verbatim.
+Enclose the verbatim text, including the delimiters, in braces.  Print
+text exactly as written (but not the delimiters) in a fixed-width.
+
+For example, @verb\{|@|\} results in @ and
+@verb\{+@'e?`!`+} results in @'e?`!`."
+
+  (let ((delimiter (buffer-substring-no-properties
+                   (1+ texinfo-command-end) (+ 2 texinfo-command-end))))
+    (unless (looking-at "{")
+      (error "Not found: @verb start brace"))
+    (delete-region texinfo-command-start (+ 2 texinfo-command-end))
+    (search-forward  delimiter))
+  (delete-backward-char 1)
+  (unless (looking-at "}")
+    (error "Not found: @verb end brace"))
+  (delete-char 1))
+
+\f
+;;; Accents and Special characters
+;; @pounds{}   ==>     #       Pounds Sterling
+(put 'pounds 'texinfo-format 'texinfo-format-pounds)
+(ptexinfmt-defun-if-void texinfo-format-pounds ()
+  (texinfo-parse-arg-discard)
+  (insert "#"))
+
+;; @OE{}       ==>     OE      French-OE-ligature
+(put 'OE 'texinfo-format 'texinfo-format-French-OE-ligature)
+(ptexinfmt-defun-if-void texinfo-format-French-OE-ligature ()
+  (insert "OE" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @oe{}       ==>     oe
+(put 'oe 'texinfo-format 'texinfo-format-French-oe-ligature)
+(ptexinfmt-defun-if-void texinfo-format-French-oe-ligature () ; lower case
+  (insert "oe" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @AA{}       ==>     AA      Scandinavian-A-with-circle
+(put 'AA 'texinfo-format 'texinfo-format-Scandinavian-A-with-circle)
+(ptexinfmt-defun-if-void texinfo-format-Scandinavian-A-with-circle ()
+  (insert "AA" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @aa{}       ==>     aa
+(put 'aa 'texinfo-format 'texinfo-format-Scandinavian-a-with-circle)
+(ptexinfmt-defun-if-void texinfo-format-Scandinavian-a-with-circle () ; lower case
+  (insert "aa" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @AE{}       ==>     AE      Latin-Scandinavian-AE
+(put 'AE 'texinfo-format 'texinfo-format-Latin-Scandinavian-AE)
+(ptexinfmt-defun-if-void texinfo-format-Latin-Scandinavian-AE ()
+  (insert "AE" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @ae{}       ==>     ae
+(put 'ae 'texinfo-format 'texinfo-format-Latin-Scandinavian-ae)
+(ptexinfmt-defun-if-void texinfo-format-Latin-Scandinavian-ae () ; lower case
+  (insert "ae" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @ss{}       ==>     ss      German-sharp-S
+(put 'ss 'texinfo-format 'texinfo-format-German-sharp-S)
+(ptexinfmt-defun-if-void texinfo-format-German-sharp-S ()
+  (insert "ss" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @questiondown{}     ==>     ?       upside-down-question-mark
+(put 'questiondown 'texinfo-format 'texinfo-format-upside-down-question-mark)
+(ptexinfmt-defun-if-void texinfo-format-upside-down-question-mark ()
+  (insert "?" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @exclamdown{}       ==>     !       upside-down-exclamation-mark
+(put 'exclamdown 'texinfo-format 'texinfo-format-upside-down-exclamation-mark)
+(ptexinfmt-defun-if-void texinfo-format-upside-down-exclamation-mark ()
+  (insert "!" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @L{}                ==>     L/      Polish suppressed-L (Lslash)
+(put 'L 'texinfo-format 'texinfo-format-Polish-suppressed-L)
+(ptexinfmt-defun-if-void texinfo-format-Polish-suppressed-L ()
+  (insert (texinfo-parse-arg-discard) "/L")
+  (goto-char texinfo-command-start))
+
+;; @l{}                ==>     l/      Polish suppressed-L (Lslash) (lower case)
+(put 'l 'texinfo-format 'texinfo-format-Polish-suppressed-l-lower-case)
+(ptexinfmt-defun-if-void texinfo-format-Polish-suppressed-l-lower-case ()
+  (insert (texinfo-parse-arg-discard) "/l")
+  (goto-char texinfo-command-start))
+
+;; @O{}                ==>     O/      Scandinavian O-with-slash
+(put 'O 'texinfo-format 'texinfo-format-Scandinavian-O-with-slash)
+(ptexinfmt-defun-if-void texinfo-format-Scandinavian-O-with-slash ()
+  (insert (texinfo-parse-arg-discard) "O/")
+  (goto-char texinfo-command-start))
+
+;; @o{}                ==>     o/      Scandinavian O-with-slash (lower case)
+(put 'o 'texinfo-format 'texinfo-format-Scandinavian-o-with-slash-lower-case)
+(ptexinfmt-defun-if-void texinfo-format-Scandinavian-o-with-slash-lower-case ()
+  (insert (texinfo-parse-arg-discard) "o/")
+  (goto-char texinfo-command-start))
+
+;; @,{c}       ==>     c,      cedilla accent
+(put ', 'texinfo-format 'texinfo-format-cedilla-accent)
+(ptexinfmt-defun-if-void texinfo-format-cedilla-accent ()
+  (insert (texinfo-parse-arg-discard) ",")
+  (goto-char texinfo-command-start))
+
+
+;; @dotaccent{o}       ==>     .o      overdot-accent
+(put 'dotaccent 'texinfo-format 'texinfo-format-overdot-accent)
+(ptexinfmt-defun-if-void texinfo-format-overdot-accent ()
+  (insert "." (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @ubaraccent{o}      ==>     _o      underbar-accent
+(put 'ubaraccent 'texinfo-format 'texinfo-format-underbar-accent)
+(ptexinfmt-defun-if-void texinfo-format-underbar-accent ()
+  (insert "_" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @udotaccent{o}      ==>     o-.     underdot-accent
+(put 'udotaccent 'texinfo-format 'texinfo-format-underdot-accent)
+(ptexinfmt-defun-if-void texinfo-format-underdot-accent ()
+  (insert (texinfo-parse-arg-discard) "-.")
+  (goto-char texinfo-command-start))
+
+;; @H{o}       ==>     ""o     long Hungarian umlaut
+(put 'H 'texinfo-format 'texinfo-format-long-Hungarian-umlaut)
+(ptexinfmt-defun-if-void texinfo-format-long-Hungarian-umlaut ()
+  (insert "\"\"" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @ringaccent{o}      ==>     *o      ring accent
+(put 'ringaccent 'texinfo-format 'texinfo-format-ring-accent)
+(ptexinfmt-defun-if-void texinfo-format-ring-accent ()
+  (insert "*" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @tieaccent{oo}      ==>     [oo     tie after accent
+(put 'tieaccent 'texinfo-format 'texinfo-format-tie-after-accent)
+(ptexinfmt-defun-if-void texinfo-format-tie-after-accent ()
+  (insert "[" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @u{o}       ==>     (o      breve accent
+(put 'u 'texinfo-format 'texinfo-format-breve-accent)
+(ptexinfmt-defun-if-void texinfo-format-breve-accent ()
+  (insert "(" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @v{o}       ==>     <o      hacek accent
+(put 'v 'texinfo-format 'texinfo-format-hacek-accent)
+(ptexinfmt-defun-if-void texinfo-format-hacek-accent ()
+  (insert "<" (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @dotless{i} ==>     i       dotless i and dotless j
+(put 'dotless 'texinfo-format 'texinfo-format-dotless)
+(ptexinfmt-defun-if-void texinfo-format-dotless ()
+  (insert (texinfo-parse-arg-discard))
+  (goto-char texinfo-command-start))
+
+;; @.
+(put '\. 'texinfo-format 'texinfo-format-\.)
+(ptexinfmt-defun-if-void texinfo-format-\. ()
+  (texinfo-discard-command)
+  (insert "."))
+
+;; @:
+(put '\: 'texinfo-format 'texinfo-format-\:)
+(ptexinfmt-defun-if-void texinfo-format-\: ()
+  (texinfo-discard-command))
+
+;; @-
+(put '\- 'texinfo-format 'texinfo-format-soft-hyphen)
+(ptexinfmt-defun-if-void texinfo-format-soft-hyphen ()
+  (texinfo-discard-command))
+
+;; @/
+(put '\/ 'texinfo-format 'texinfo-format-\/)
+(ptexinfmt-defun-if-void texinfo-format-\/ ()
+  (texinfo-discard-command))
+
+\f
+;;; Cross References
+;; @ref, @xref
+(put 'ref 'texinfo-format 'texinfo-format-xref)
+
+(ptexinfmt-defun-if-broken texinfo-format-xref ()
+  (let ((args (texinfo-format-parse-args)))
+    (texinfo-discard-command)
+    (insert "*Note ")
+    (let ((fname (or (nth 1 args) (nth 2 args))))
+      (if (null (or fname (nth 3 args)))
+         (insert (nth 0 args) "::")
+       (insert (or fname (nth 0 args)) ": ")
+       (if (nth 3 args)
+           (insert "(" (nth 3 args) ")"))
+       (unless (null (nth 0 args))
+         (insert (nth 0 args)))))))
+
+;; @uref{URL [,TEXT] [,REPLACEMENT]}
+(put 'uref 'texinfo-format 'texinfo-format-uref)
+(ptexinfmt-defun-if-broken texinfo-format-uref ()
+  "Format URL and optional URL-TITLE.
+Insert ` ... ' around URL if no URL-TITLE argument;
+otherwise, insert URL-TITLE followed by URL in parentheses."
+  (let ((args (texinfo-format-parse-args)))
+    (texinfo-discard-command)
+    ;; if url-title
+    (if (nth 1 args)
+       (insert  (nth 1 args) " (" (nth 0 args) ")")
+      (insert "`" (nth 0 args) "'"))))
+
+;; @inforef
+(put 'inforef 'texinfo-format 'texinfo-format-inforef)
+(ptexinfmt-defun-if-void texinfo-format-inforef ()
+  (let ((args (texinfo-format-parse-args)))
+    (texinfo-discard-command)
+    (if (nth 1 args)
+       (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args))
+      (insert "*Note " "(" (nth 2 args) ")" (car args) "::"))))
+
+
+;; @anchor
+;; don't emulation
+;; If support @anchor for Mule 2.3, We must fix informat.el and info.el:
+;;  - Info-tagify suport @anthor-*-refill.
+;;  - info.el support Ref in Tag table.
+(unless (get 'anchor 'texinfo-format)
+  (put 'anchor 'texinfo-format 'texinfo-discard-command-and-arg))
+
+
+\f
+;;; New command definition
+;; @alias NEW=EXISTING
+(put 'alias 'texinfo-format 'texinfo-alias)
+(ptexinfmt-defun-if-void texinfo-alias ()
+  (let ((start (1- (point)))
+       args)
+    (skip-chars-forward " ")
+    (save-excursion (end-of-line) (setq texinfo-command-end (point)))
+    (if (not (looking-at "\\([^=]+\\)=\\(.*\\)"))
+       (error "Invalid alias command")
+      (setq texinfo-alias-list
+           (cons
+            (cons
+             (buffer-substring (match-beginning 1) (match-end 1))
+             (buffer-substring (match-beginning 2) (match-end 2)))
+            texinfo-alias-list))
+      (texinfo-discard-command))))
+
+\f
+;;; Indent
+;; @exampleindent INDENT  (makeinfo 4.0 or later)
+
+;; @paragraphindent INDENT  (makeinfo 4.0 or later)
+;; INDENT: asis, 0, n
+
+;; @firstparagraphindent WORD   (makeinfo 4.6 or later)
+;; WORD: none, insert
+
+
+\f
+;;; Special
+;; @image{FILENAME [, WIDTH] [, HEIGHT]}
+(put 'image 'texinfo-format 'texinfo-format-image)
+(ptexinfmt-defun-if-void texinfo-format-image ()
+  ;; I don't know makeinfo parse FILENAME.
+  (let ((args (texinfo-format-parse-args))
+       filename)
+    (when (null (nth 0 args))
+      (error "Invalid image command"))
+    (texinfo-discard-command)
+    ;; makeinfo uses FILENAME.txt
+    (setq filename (format "%s.txt" (nth 0 args)))
+    (message "Reading included file: %s" filename)
+    ;; verbatim for Info output
+    (goto-char (+ (point) (cadr (insert-file-contents filename))))
+    (message "Reading included file: %s...done" filename)))
+
+;; @hyphenation command discards an argument within braces
+(put 'hyphenation 'texinfo-format 'texinfo-discard-command-and-arg)
+(ptexinfmt-defun-if-void texinfo-discard-command-and-arg ()
+  "Discard both @-command and its argument in braces."
+  (goto-char texinfo-command-end)
+  (forward-list 1)
+  (setq texinfo-command-end (point))
+  (delete-region texinfo-command-start texinfo-command-end))
+
+\f
+;;; @multitable ... @end multitable
+(ptexinfmt-defvar-if-void texinfo-extra-inter-column-width 0
+  "*Number of extra spaces between entries (columns) in @multitable.")
+
+(ptexinfmt-defvar-if-void texinfo-multitable-buffer-name
+  "*multitable-temporary-buffer*")
+(ptexinfmt-defvar-if-void texinfo-multitable-rectangle-name
+  "texinfo-multitable-temp-")
+
+;; These commands are defined in texinfo.tex for printed output.
+(put 'multitableparskip 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitableparindent 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitablecolmargin 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitablelinespace 'texinfo-format 'texinfo-discard-line-with-args)
+
+(put 'multitable 'texinfo-format 'texinfo-multitable)
+
+(ptexinfmt-defun-if-void texinfo-multitable ()
+  "Produce multi-column tables."
+
+;; This function pushes information onto the `texinfo-stack'.
+;; A stack element consists of:
+;;   - type-of-command, i.e., multitable
+;;   - the information about column widths, and
+;;   - the position of texinfo-command-start.
+;; e.g., ('multitable (1 2 3 4) 123)
+;; The command line is then deleted.
+  (texinfo-push-stack
+   'multitable
+   ;; push width information on stack
+   (texinfo-multitable-widths))
+  (texinfo-discard-line-with-args))
+
+(put 'multitable 'texinfo-end 'texinfo-end-multitable)
+(ptexinfmt-defun-if-void texinfo-end-multitable ()
+  "Discard the @end multitable line and pop the stack of multitable."
+  (texinfo-discard-command)
+  (texinfo-pop-stack 'multitable))
+
+(ptexinfmt-defun-if-broken texinfo-multitable-widths ()
+  "Return list of widths of each column in a multi-column table."
+  (let (texinfo-multitable-width-list)
+    ;; Fractions format:
+    ;;  @multitable @columnfractions .25 .3 .45
+    ;;
+    ;; Template format:
+    ;;  @multitable {Column 1 template} {Column 2} {Column 3 example}
+    ;; Place point before first argument
+    (skip-chars-forward " \t")
+    (cond
+     ;; Check for common misspelling
+     ((looking-at "@columnfraction ")
+      (error "In @multitable, @columnfractions misspelled"))
+     ;; Case 1: @columnfractions .25 .3 .45
+     ((looking-at "@columnfractions")
+      (forward-word 1)
+      (while (not (eolp))
+       (setq texinfo-multitable-width-list
+             (cons
+              (truncate
+               (1-
+                (* fill-column (read (get-buffer (current-buffer))))))
+              texinfo-multitable-width-list))))
+     ;;
+     ;; Case 2: {Column 1 template} {Column 2} {Column 3 example}
+     ((looking-at "{")
+      (let ((start-of-templates (point)))
+       (while (not (eolp))
+         (skip-chars-forward " \t")
+         (let* ((start-of-template (1+ (point)))
+                (end-of-template
+                 ;; forward-sexp works with braces in Texinfo mode
+                 (progn (forward-sexp 1) (1- (point)))))
+           (setq texinfo-multitable-width-list
+                 (cons (- (progn
+                            (goto-char end-of-template)
+                            (current-column))
+                          (progn
+                            (goto-char start-of-template)
+                            (current-column)))
+                       texinfo-multitable-width-list))
+           ;; Remove carriage return from within a template, if any.
+           ;; This helps those those who want to use more than
+           ;; one line's worth of words in @multitable line.
+           (narrow-to-region start-of-template end-of-template)
+           (goto-char (point-min))
+           (while (search-forward "\n" nil t)
+             (delete-char -1))
+           (goto-char (point-max))
+           (widen)
+           (forward-char 1)))))
+     ;;
+     ;; Case 3: Trouble
+     (t
+      (error "\
+You probably need to specify column widths for @multitable correctly")))
+    ;; Check whether columns fit on page.
+    (let ((desired-columns
+          (+
+           ;; between column spaces
+           (length texinfo-multitable-width-list)
+           ;; additional between column spaces, if any
+           texinfo-extra-inter-column-width
+           ;; sum of spaces for each entry
+           (apply '+ texinfo-multitable-width-list))))
+      (if (> desired-columns fill-column)
+         (error (format "\
+Multi-column table width, %d chars, is greater than page width, %d chars."
+                        desired-columns fill-column))))
+    texinfo-multitable-width-list))
+
+;; @item  A1  @tab  A2  @tab  A3
+(ptexinfmt-defun-if-void texinfo-multitable-extract-row ()
+  "Return multitable row, as a string.
+End of row is beginning of next @item or beginning of @end.
+Cells within rows are separated by @tab."
+  (skip-chars-forward " \t")
+  (let* ((start (point))
+        (end (progn
+               (re-search-forward "@item\\|@end")
+               (match-beginning 0)))
+        (row (progn (goto-char end)
+                    (skip-chars-backward " ")
+                    ;; remove whitespace at end of argument
+                    (delete-region (point) end)
+                    (buffer-substring start (point)))))
+    (delete-region texinfo-command-start end)
+    row))
+
+(put 'multitable 'texinfo-item 'texinfo-multitable-item)
+(ptexinfmt-defun-if-void texinfo-multitable-item ()
+  "Format a row within a multicolumn table.
+Cells in row are separated by @tab.
+Widths of cells are specified by the arguments in the @multitable line.
+All cells are made to be the same height.
+This command is executed when texinfmt sees @item inside @multitable."
+  (let ((original-buffer (current-buffer))
+       (table-widths (reverse (car (cdr (car texinfo-stack)))))
+       (existing-fill-column fill-column)
+       start
+       end
+       (table-column       0)
+       (table-entry-height 0)
+       ;; unformatted row looks like:  A1  @tab  A2  @tab  A3
+       ;; extract-row command deletes the source line in the table.
+       (unformated-row (texinfo-multitable-extract-row)))
+    ;; Use a temporary buffer
+    (set-buffer (get-buffer-create texinfo-multitable-buffer-name))
+    (delete-region (point-min) (point-max))
+    (insert unformated-row)
+    (goto-char (point-min))
+;; 1. Check for correct number of @tab in line.
+    (let ((tab-number 1)) ;; one @tab between two columns
+      (while (search-forward "@tab" nil t)
+       (setq tab-number (1+ tab-number)))
+      (if (/= tab-number (length table-widths))
+         (error "Wrong number of @tab's in a @multitable row")))
+    (goto-char (point-min))
+;; 2. Format each cell, and copy to a rectangle
+    ;; buffer looks like this:    A1  @tab  A2  @tab  A3
+    ;; Cell #1: format up to @tab
+    ;; Cell #2: format up to @tab
+    ;; Cell #3: format up to eob
+    (while (not (eobp))
+      (setq start (point))
+      (setq end (save-excursion
+                 (if (search-forward "@tab" nil 'move)
+                     ;; Delete the @tab command, including the @-sign
+                     (delete-region
+                      (point)
+                      (progn (forward-word -1) (1- (point)))))
+                 (point)))
+      ;; Set fill-column *wider* than needed to produce inter-column space
+      (setq fill-column (+ 1
+                          texinfo-extra-inter-column-width
+                          (nth table-column table-widths)))
+      (narrow-to-region start end)
+      ;; Remove whitespace before and after entry.
+      (skip-chars-forward " ")
+      (delete-region (point) (save-excursion (beginning-of-line) (point)))
+      (goto-char (point-max))
+      (skip-chars-backward " ")
+      (delete-region (point) (save-excursion (end-of-line) (point)))
+      ;; Temorarily set texinfo-stack to nil so texinfo-format-scan
+      ;; does not see an unterminated @multitable.
+      (let (texinfo-stack) ;; nil
+       (texinfo-format-scan))
+      (let (fill-prefix) ;; no fill prefix
+       (fill-region (point-min) (point-max)))
+      (setq table-entry-height
+           (max table-entry-height (count-lines (point-min) (point-max))))
+;; 3. Move point to end of bottom line, and pad that line to fill column.
+      (goto-char (point-min))
+      (forward-line (1- table-entry-height))
+      (let* ((beg (point)) ;; beginning of line
+            ;; add one more space for inter-column spacing
+            (needed-whitespace
+             (1+
+              (- fill-column
+                 (progn
+                   (end-of-line)
+                   (current-column)))))) ;; end of existing line
+       (insert (make-string
+                (if (> needed-whitespace 0) needed-whitespace 1)
+                ? )))
+      ;; now, put formatted cell into a rectangle
+      (set (intern (concat texinfo-multitable-rectangle-name
+                          (int-to-string table-column)))
+          (extract-rectangle (point-min) (point)))
+      (delete-region (point-min) (point))
+      (goto-char (point-max))
+      (setq table-column (1+ table-column))
+      (widen))
+;; 4. Add extra lines to rectangles so all are of same height
+    (let ((total-number-of-columns table-column)
+         (column-number 0)
+         here)
+      (while (> table-column 0)
+       (let ((this-rectangle (int-to-string table-column)))
+         (while (< (length this-rectangle) table-entry-height)
+           (setq this-rectangle (append this-rectangle '("")))))
+       (setq table-column (1- table-column)))
+;; 5. Insert formatted rectangles in original buffer
+      (switch-to-buffer original-buffer)
+      (open-line table-entry-height)
+      (while (< column-number total-number-of-columns)
+       (setq here (point))
+       (insert-rectangle
+        (eval (intern
+               (concat texinfo-multitable-rectangle-name
+                       (int-to-string column-number)))))
+       (goto-char here)
+       (end-of-line)
+       (setq column-number (1+ column-number))))
+    (kill-buffer texinfo-multitable-buffer-name)
+    (setq fill-column existing-fill-column)))
+
+\f
+(ptexinfmt-defun-if-broken texinfo-format-printindex ()
+  (let ((indexelts (symbol-value
+                   (cdr (assoc (texinfo-parse-arg-discard)
+                               texinfo-indexvar-alist))))
+       opoint)
+    (insert "\n* Menu:\n\n")
+    (setq opoint (point))
+    (texinfo-print-index nil indexelts)
+
+    (if (memq system-type '(vax-vms windows-nt ms-dos))
+       (texinfo-sort-region opoint (point))
+      (shell-command-on-region opoint (point) "sort -fd" 1))))
+
+(provide 'ptexinfmt)
+
+;;; ptexinfmt.el ends here
diff --git a/texi/refcard-ja.tex b/texi/refcard-ja.tex
new file mode 100644 (file)
index 0000000..fdd8d6e
--- /dev/null
@@ -0,0 +1,83 @@
+% Reference Card for (ding) Gnus, 3 twocolumn pages.
+% To be processed with latex 2.09
+\def\Guide{Card}\def\guide{card}
+\def\logoscale{0.25}
+\def\sec{\section*}
+\def\subsec{\subsection*}
+\def\subsubsec{\subsubsection*}
+\documentstyle{article}
+\textwidth 7.26in \textheight 10.3in \topmargin -1.2in
+% the same settings work for A4, although there is a bit of space at the
+% top and bottom of the page.
+\oddsidemargin -0.5in \evensidemargin -0.5in
+\begin{document}
+\twocolumn\footnotesize\pagestyle{empty}
+\input{gnusref-ja}
+
+\vspace*{\fill}
+\Title
+\vspace*{2ex}
+\Logo{refcard}
+\vspace*{\fill}
+\Marks
+\GroupLevels
+\pagebreak
+
+\Notes
+\General
+\ArticleMode
+\vspace*{\fill}
+\CopyRight
+\pagebreak
+
+\GroupMode
+\SOUP
+\pagebreak
+
+\ListGroups
+\CreateGroups
+\SortGroups
+\MarkGroups
+\pagebreak
+
+\Unsubscribe
+\GroupTopics
+\vspace*{\fill}
+\SummaryMode
+\SortSummary
+\Article
+\pagebreak
+
+\MailGroup
+\GotoArticle
+\Score
+\pagebreak
+
+\MarkArticles
+%\vspace*{-0.5ex}
+\MarkScore
+%\vspace*{-0.5ex}
+\ProcessMark
+%\vspace*{-0.5ex}
+\OutputArticles
+\pagebreak
+
+\Send
+%\vspace*{-1.1ex}
+\Thread
+%\vspace*{-1.1ex}
+\Exit
+\pagebreak
+
+\Wash
+\Hide
+\Highlight
+\Extract
+\pagebreak
+
+\Limit
+\PickAndRead
+\ServerMode
+\BrowseServer
+
+\end{document}
index a701cd4..8028687 100644 (file)
-% Reference Card for (ding) Gnus, 3 twocolumn pages.
-% To be processed with latex 2.09
+% Reference Card for Oort Gnus: to be processed with LaTeX2e
+\documentclass{article}
+
+\usepackage{supertabular}
+
 \def\Guide{Card}\def\guide{card}
 \def\logoscale{0.25}
-\def\sec{\section*}
-\def\subsec{\subsection*}
-\def\subsubsec{\subsubsection*}
-\documentstyle{article}
-\textwidth 7.26in \textheight 10in \topmargin -1.0in
+\newlength{\logowidth} \setlength{\logowidth}{6.861in}
+\newlength{\logoheight} \setlength{\logoheight}{7.013in}
+
+\raggedbottom\raggedright
+
+\usepackage{epsfig}
+
+\setlength{\textwidth}{7.26in} \setlength{\textheight}{10in}
+\setlength{\topmargin}{-1.0in}
 % the same settings work for A4, although there is a bit of space at the
 % top and bottom of the page. 
-\oddsidemargin -0.5in \evensidemargin -0.5in
+\setlength{\oddsidemargin}{-0.5in} \setlength{\evensidemargin}{-0.5in}
+
+
+% README (for refcard + booklet)
+% This is a 5+ page reference card. In addition there is a booklet
+% (bk-a4.tex for A4 and bk-lt.tex for Letter).
+%
+% *** files for the refcard
+% refcard.tex (this file), gnusref.tex ("include"-file) and
+% gnuslogo-refcard.eps (Gnus logo).
+%
+% *** printing (about 5 pages now: write me if you can make it shorter..)
+% if you are using latex-mode, you do C-c C-f (process with latex),
+% C-c C-v (view using xdvi/dvi2tty) and C-c C-p (print)
+% the original author has set up the page dimensions cleverly so that this
+% should print on both letter and a4 (see note above)
+% $latex refcard.tex
+% this creates a file refcard.dvi which you can preview using
+% $xdvi refcard.dvi [C-c C-v]
+% and print using something like
+% $dvips refcard.dvi 
+%
+% If you want to print the booklet, you need to use `pstops' from the
+% `psutils' package (TODO: somebody write a howto ?)
+%
+% *** customization:
+
+% the part following \begin{document} in this file consists of a macro for
+% each section and section-headers (\section*{..}). It should be easy to
+% reorder things and/or remove sections (put '%' at the beginning of the line).
+% (i.e. you might want to omit \notes in the printed version)
+% The same goes for the booklet: Its contents are defined in booklet.tex.
+% If you think that the order is not logical and you have ideas for
+% improvements, please send mail to the current maintainer.
+
+% *** TODO:
+% o some things might not be updated: scoring and server modes, maybe more
+% o Gnus Unplugged category-buffer commands need to be written
+
 \begin{document}
-\twocolumn\scriptsize\pagestyle{empty}
+
+\def\progver{5.10}\def\refver{5.10-1} % program and refcard versions
+\def\date{Mar 23rd, 2002}
+\def\author{Gnus Bugfixing Girls + Boys $<$bugs@gnus.org$>$}
+\raggedbottom\raggedright
+
+\twocolumn
+% use \tiny to shrink it to 4 pages (needs a high-resolution printer though)
+%\tiny
+\scriptsize
+\pagestyle{plain}
+
+% this contains a set of commands containing the actual sections
+% (and some explanations).
 \input{gnusref}
 
-% page 1, left column
 \Title
 \par
-\vspace{0.5\baselineskip}
 \Logo{refcard}
-\vspace*{\fill}
-\GroupLevels
-\GroupMode
-\pagebreak
-
-% page 1, right column
 \Notes
-\vspace*{\fill}
-\GroupCommands
-\pagebreak
-
-% page 2, left column
-\SummaryMode
-\Asubmap
-\Bsubmap
-\Gsubmap
-\Hsubmap
-\Tsubmap
-\pagebreak
-
-% page 2, right column
-\Msubmap
-\Marks
-\pagebreak
-
-% page 3
-\Osubmap
-\Ssubmap
-\Xsubmap
-\Vsubmap
-\SortSummary
-\Wsubmap
-\Zsubmap
-\ArticleMode
+%
+%
+\section*{Group-Mode}
+\GroupModeGeneral
+    \subsection*{Group Subscribedness-Levels}
+    \GroupLevels
+    \subsection*{List Groups}
+    \ListGroups
+    \subsection*{Create/Edit Foreign Groups}
+    \CreateEditGroups
+    \subsection*{Unsubscribe, Kill and Yank Groups}
+    \SubscribeKillYankGroups
+    \subsection*{Mark Groups}
+    \MarkGroups
+    \subsection*{Group-Unplugged}
+    \GroupUnplugged
+% topics in group-mode
+    \subsection*{Group Topics}
+    \GroupTopicsGeneral
+    \subsubsection*{Topic Sorting}
+    \TopicSorting
+%
+% summary-mode
+\section*{Summary-Mode}
+\SummaryModeGeneral
+    \subsection*{Select Articles}
+    \SelectArticles
+%
+    \subsection*{Threading}
+    \Threading
+%
+    \subsection*{Limiting}
+    \Limiting
+    \subsection*{Sort the Summary-Buffer}
+    \SortSummary
+    \subsection*{Score (Value) Commands}
+    \Scoring
+    \subsection*{Output Articles}
+    \OutputArticles
+    \subsection*{Extract Series (Uudecode etc)}
+    \ExtractSeries
+    \subsection*{MIME operations from the Summary-Buffer}
+    \MIMESummary     
+%
+    \subsection*{Post, Followup, Reply, Forward, Cancel}
+    \PostReplyetc
+    \newpage
+      \subsection*{Message Composition}
+      \MsgCompositionGeneral
+        \subsubsection*{Jumping in message-buffer}
+        \MsgCompositionMovementArticle
+        \subsubsection*{Attachments/MML}
+        \MsgCompositionMML
+% marking articles
+    \subsection*{Mark Articles}
+    \MarkArticlesGeneral
+        \subsubsection*{Mark Based on Score}
+        \MarkByScore
+        \subsubsection*{The Process Mark}
+        \ProcessMark
+        \subsubsection*{Mark Indication-Characters}
+        \MarkCharacters
+%
+    \subsection*{Summary-Unplugged}
+    \SummaryUnplugged
+    \subsection*{Mail-Group Commands}
+    \MailGroups
+    \subsection*{Draft-Group Commands}
+    \DraftGroup
+% exiting
+    \subsection*{Exit the Summary-Buffer}
+    \ExitSummary
+%
+%
+\section*{Article Mode (reading)}
+\ArticleModeGeneral
+    \subsection*{Wash the Article-Buffer}
+    \WashArticle
+    \subsubsection*{Blank Lines and Whitespace}
+    \BlankAndWhitespace
+    \subsubsection*{Picons, X-faces, Smileys}
+    \Picons
+    \subsubsection*{Time and Date}
+    \TimeAndDate
+    \subsection*{Hide/Highlight Parts of the Article}
+    \HideHighlightArticle
+    \subsection*{MIME operations from the Article-Buffer (reading)}
+    \MIMEArticleMode
+%
+%
+\section*{Server Mode}
 \ServerMode
-
-% page 4
+    \subsection*{Unplugged-Server}
+    \ServerUnplugged
+%
+%
+\section*{Browse Server Mode}
 \BrowseServer
-\pagebreak
-\onecolumn
+
+%\pagebreak
 \vspace*{\fill}
-\CopyRight
+\Copyright
 
 \end{document}
+
+%%% Local Variables:
+%%% mode: latex
+%%% End:
diff --git a/texi/screen/group-topic.png b/texi/screen/group-topic.png
new file mode 100644 (file)
index 0000000..6f4ad01
Binary files /dev/null and b/texi/screen/group-topic.png differ
diff --git a/texi/screen/group.png b/texi/screen/group.png
new file mode 100644 (file)
index 0000000..4b4620f
Binary files /dev/null and b/texi/screen/group.png differ
diff --git a/texi/screen/server.png b/texi/screen/server.png
new file mode 100644 (file)
index 0000000..67f2bd4
Binary files /dev/null and b/texi/screen/server.png differ
diff --git a/texi/screen/summary-adopt.png b/texi/screen/summary-adopt.png
new file mode 100644 (file)
index 0000000..54e508f
Binary files /dev/null and b/texi/screen/summary-adopt.png differ
diff --git a/texi/screen/summary-article-c-ug.png b/texi/screen/summary-article-c-ug.png
new file mode 100644 (file)
index 0000000..8f224bf
Binary files /dev/null and b/texi/screen/summary-article-c-ug.png differ
diff --git a/texi/screen/summary-article.png b/texi/screen/summary-article.png
new file mode 100644 (file)
index 0000000..d265dca
Binary files /dev/null and b/texi/screen/summary-article.png differ
diff --git a/texi/screen/summary-dummy.png b/texi/screen/summary-dummy.png
new file mode 100644 (file)
index 0000000..308f244
Binary files /dev/null and b/texi/screen/summary-dummy.png differ
diff --git a/texi/screen/summary-empty.png b/texi/screen/summary-empty.png
new file mode 100644 (file)
index 0000000..2f2ec6a
Binary files /dev/null and b/texi/screen/summary-empty.png differ
diff --git a/texi/screen/summary-none.png b/texi/screen/summary-none.png
new file mode 100644 (file)
index 0000000..9f8f43e
Binary files /dev/null and b/texi/screen/summary-none.png differ
diff --git a/texi/screen/summary-unthreaded.png b/texi/screen/summary-unthreaded.png
new file mode 100644 (file)
index 0000000..2e5ddbb
Binary files /dev/null and b/texi/screen/summary-unthreaded.png differ
diff --git a/texi/screen/summary.png b/texi/screen/summary.png
new file mode 100644 (file)
index 0000000..7cfcc0e
Binary files /dev/null and b/texi/screen/summary.png differ
diff --git a/texi/sieve.texi b/texi/sieve.texi
new file mode 100644 (file)
index 0000000..6bfcf2f
--- /dev/null
@@ -0,0 +1,379 @@
+\input texinfo                  @c -*-texinfo-*-
+
+@setfilename sieve
+@settitle Emacs Sieve Manual
+@synindex fn cp
+@synindex vr cp
+@synindex pg cp
+@dircategory Emacs
+@direntry
+* Sieve: (sieve).               Managing Sieve scripts in Emacs.
+@end direntry
+@iftex
+@finalout
+@end iftex
+@setchapternewpage odd
+
+@ifnottex
+
+This file documents the Emacs Sieve package.
+
+Copyright (C) 2001 Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end ifnottex
+
+@tex
+
+@titlepage
+@title Emacs Sieve Manual
+
+@author by Simon Josefsson
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 2001 Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being none, with the Front-Cover texts being ``A GNU
+Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the
+license is included in the section entitled ``GNU Free Documentation
+License'' in the Emacs manual.
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
+this GNU Manual, like GNU software.  Copies published by the Free
+Software Foundation raise funds for GNU development.''
+
+This document is part of a collection distributed under the GNU Free
+Documentation License.  If you want to distribute this document
+separately from the collection, you can do so by adding a copy of the
+license to the document, as described in section 6 of the license.
+@end titlepage
+@page
+
+@end tex
+
+@node Top
+@top Sieve Support for Emacs
+
+This manual documents the Emacs Sieve package.
+
+It is intended as a users manual for Sieve Mode and Manage Sieve, and
+as a reference manual for the @samp{sieve-manage} protocol Emacs Lisp
+API.
+
+Sieve is a language for server-side filtering of mail.  The language
+is documented in RFC 3028.  This manual does not attempt to document
+the language, so keep RFC 3028 around.
+
+A good online Sieve resources is @uref{http://www.cyrusoft.com/sieve/}.
+
+@menu
+* Installation::          Getting ready to use the package.
+* Sieve Mode::            Editing Sieve scripts.
+* Managing Sieve::        Managing Sieve scripts on a remote server.
+* Examples ::             A few Sieve code snippets.
+* Manage Sieve API ::     Interfacing to the Manage Sieve Protocol API.
+* Standards::             A summary of RFCs and working documents used.
+* Index::                 Function and variable index.
+@end menu
+
+
+@node Installation
+@chapter Installation
+@cindex Install
+@cindex Setup
+
+The Sieve package should come with your Emacs version, and should be
+ready for use directly.
+
+However, to manually set up the package you can put the following
+commands in your @code{~/.emacs}:
+
+@lisp
+(autoload 'sieve-mode "sieve-mode")
+@end lisp
+@lisp
+(setq auto-mode-alist (cons '("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode)
+                            auto-mode-alist))
+@end lisp
+
+
+@node Sieve Mode
+@chapter Sieve Mode
+
+Sieve mode provides syntax-based indentation, font-locking support and
+other handy functions to make editing Sieve scripts easier.
+
+Use @samp{M-x sieve-mode} to switch to this major mode.  This command
+runs the hook @code{sieve-mode-hook}.
+
+@vindex sieve-mode-map
+@vindex sieve-mode-syntax-table
+Sieve mode is derived from @code{c-mode}, and is very similar except
+for the syntax of comments.  The keymap (@code{sieve-mode-map}) is
+inherited from @code{c-mode}, as are the variables for customizing
+indentation.  Sieve mode has its own abbrev table
+(@code{sieve-mode-abbrev-table}) and syntax table
+(@code{sieve-mode-syntax-table}).
+
+In addition to the editing utility functions, Sieve mode also contains
+bindings to manage Sieve scripts remotely. @xref{Managing Sieve}.
+
+@table @kbd
+
+@item C-c RET
+@kindex C-c RET
+@findex sieve-manage
+@cindex manage remote sieve script
+Open a connection to a remote server using the Managesieve protocol.
+
+@item C-c C-l
+@kindex C-c C-l
+@findex sieve-upload
+@cindex upload sieve script
+Upload the Sieve script to the currently open server.
+
+@end table
+
+
+@node Managing Sieve
+@chapter Managing Sieve
+
+Manage Sieve is a special mode used to display Sieve scripts available
+on a remote server.  It can be invoked with @kbd{M-x sieve-manage
+RET}, which queries the user for a server and if necessary, user
+credentials to use.
+
+When a server has been successfully contacted, the Manage Sieve buffer
+looks something like:
+
+@example
+Server  : mailserver:2000
+
+2 scripts on server, press RET on a script name edits it, or
+press RET on <new script> to create a new script.
+        <new script>
+ ACTIVE .sieve
+        template.siv
+@end example
+
+One of the scripts are highlighted, and standard point navigation
+commands (@kbd{<up>}, @kbd{<down>} etc) can be used to navigate the
+list.
+
+The following commands are available in the Manage Sieve buffer:
+
+@table @kbd
+
+@item m
+@kindex m
+@findex sieve-activate
+Activates the currently highlighted script.
+
+@item u
+@kindex u
+@findex sieve-deactivate
+Deactivates the currently highlighted script.
+
+@item C-M-?
+@kindex C-M-?
+@findex sieve-deactivate-all
+Deactivates all scripts.
+
+@item r
+@kindex r
+@findex sieve-remove
+Remove currently highlighted script.
+
+@item RET
+@item mouse-2
+@item f
+@kindex RET
+@kindex mouse-2
+@kindex f
+@findex sieve-edit-script
+Bury the server buffer and download the currently highlighted script
+into a new buffer for editing in Sieve mode (@pxref{Sieve Mode}).
+
+@item o
+@kindex o
+@findex sieve-edit-script-other-window
+Create a new buffer in another window containing the currently
+highlighted script for editing in Sieve mode (@pxref{Sieve Mode}).
+
+@item q
+@kindex q
+@findex sieve-bury-buffer
+Bury the Manage Sieve buffer without closing the connection.
+
+@item ?
+@item h
+@kindex ?
+@kindex h
+@findex sieve-help
+Displays help in the minibuffer. 
+
+@end table
+
+@node Examples
+@chapter Examples
+
+If you are not familiar with Sieve, this chapter contains a few simple
+code snippets that you can cut'n'paste and modify at will, until you
+feel more comfortable with the Sieve language to write the rules from
+scratch.
+
+The following complete Sieve script places all messages with a matching
+@samp{Sender:} header into the given mailbox.  Many mailing lists uses
+this format.  The first line makes sure your Sieve server understands
+the @code{fileinto} command.
+
+@example
+require "fileinto";
+
+if address "sender" "owner-w3-beta@@xemacs.org" @{
+       fileinto "INBOX.w3-beta";
+@}
+@end example
+
+A few mailing lists do not use the @samp{Sender:} header, but does
+contain some unique identifier in some other header.  The following is
+not a complete script, it assumes that @code{fileinto} has already been
+required.
+
+@example
+if header :contains "Delivered-To" "auc-tex@@sunsite.dk" @{
+       fileinto "INBOX.auc-tex";
+@}
+@end example
+
+At last, we have the hopeless mailing lists that does not have any
+unique identifier and you are forced to match on the @samp{To:} and
+@samp{Cc} headers.  As before, this snippet assumes that @code{fileinto}
+has been required.
+
+@example
+if address ["to", "cc"] "kerberos@@mit.edu" @{
+       fileinto "INBOX.kerberos";
+@}
+@end example
+
+@node Manage Sieve API
+@chapter Manage Sieve API
+
+The @file{sieve-manage.el} library contains low-level functionality
+for talking to a server with the @sc{managesieve} protocol.
+
+A number of user-visible variables exist, which all can be customized
+in the @code{sieve} group (@kbd{M-x customize-group RET sieve RET}):
+
+@table @code
+
+@item sieve-manage-default-user
+@vindex sieve-manage-default-user
+Sets the default username.
+
+@item sieve-manage-default-port
+@vindex sieve-manage-default-port
+Sets the default port to use, the suggested port number is @code{2000}.
+
+@item sieve-manage-log
+@vindex sieve-manage-log
+If non-nil, should be a string naming a buffer where a protocol trace
+is dumped (for debugging purposes).
+
+@end table
+
+The API functions include:
+
+@table @code
+
+@item sieve-manage-open
+@findex sieve-manage-open
+Open connection to managesieve server, returning a buffer to be used
+by all other API functions.
+
+@item sieve-manage-opened
+@findex sieve-manage-opened
+Check if a server is open or not.
+
+@item sieve-manage-close
+@findex sieve-manage-close
+Close a server connection.
+
+@item sieve-manage-authenticate
+@findex sieve-manage-authenticate
+Authenticate to the server.
+
+@item sieve-manage-capability
+@findex sieve-manage-capability
+Return a list of capabilities the server support.
+
+@item sieve-manage-listscripts
+@findex sieve-manage-listscripts
+List scripts on the server.
+
+@item sieve-manage-havespace
+@findex sieve-manage-havespace
+Returns non-nil iff server have roam for a script of given size.
+
+@item sieve-manage-getscript
+@findex sieve-manage-getscript
+Download script from server.
+
+@item sieve-manage-putscript
+@findex sieve-manage-putscript
+Upload script to server.
+
+@item sieve-manage-setactive
+@findex sieve-manage-setactive
+Indicate which script on the server should be active.
+
+@end table
+
+@node Standards
+@chapter Standards
+
+The Emacs Sieve package implements all or parts of a small but
+hopefully growing number of RFCs and drafts documents.  This chapter
+lists the relevant ones.  They can all be fetched from
+@uref{http://quimby.gnus.org/notes/}.
+
+@table @dfn
+
+@item RFC3028
+Sieve: A Mail Filtering Language.
+
+@item draft-martin-managesieve-03
+A Protocol for Remotely Managing Sieve Scripts
+
+@end table
+
+
+@node Index
+@chapter Index
+@printindex cp
+
+@summarycontents
+@contents
+@bye
+
+@c End:
diff --git a/texi/smilies/BigFace.tif b/texi/smilies/BigFace.tif
new file mode 100644 (file)
index 0000000..e073e01
Binary files /dev/null and b/texi/smilies/BigFace.tif differ
diff --git a/texi/smilies/FaceAngry.xpm b/texi/smilies/FaceAngry.xpm
new file mode 100644 (file)
index 0000000..32fec93
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E.X....X.E ",
+"E...X..X...E",
+"E...X..X...E",
+"E..........E",
+"E...XXXX...E",
+" E.X....X.E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceDevilish.xpm b/texi/smilies/FaceDevilish.xpm
new file mode 100644 (file)
index 0000000..ee88aed
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"..E EEEE E..",
+"E..E....E..E",
+" E........E ",
+" E.. .....E ",
+"E..XX..XX..E",
+"E..........E",
+"E.X......X.E",
+"E..X....X..E",
+" E..XXXX..E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceGoofy.xpm b/texi/smilies/FaceGoofy.xpm
new file mode 100644 (file)
index 0000000..62d7de8
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E.X......X.E",
+"E.XXXXXXXX.E",
+" E........E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceGrinning.xpm b/texi/smilies/FaceGrinning.xpm
new file mode 100644 (file)
index 0000000..072d505
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E..XXXXXX..E",
+"E..X....X..E",
+" E..X..X..E ",
+" E...XX...E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceHappy.xpm b/texi/smilies/FaceHappy.xpm
new file mode 100644 (file)
index 0000000..07f1214
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c #FFFFFF",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E.X......X.E",
+"E..XXXXXX..E",
+" E..XXXX..E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceIronic.xpm b/texi/smilies/FaceIronic.xpm
new file mode 100644 (file)
index 0000000..677ee25
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E........X.E",
+"E...XXXXX..E",
+" E.X......E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceKOed.xpm b/texi/smilies/FaceKOed.xpm
new file mode 100644 (file)
index 0000000..ed51b19
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E.X.XX.X.E ",
+"E...X..X...E",
+"E..X.XX.X..E",
+"E..........E",
+"E..........E",
+" E.XXXXXX.E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceNyah.xpm b/texi/smilies/FaceNyah.xpm
new file mode 100644 (file)
index 0000000..320cfe0
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E........E ",
+"E..XX..XX..E",
+"E..........E",
+"E..........E",
+"E...XXXX...E",
+" E..oooX..E ",
+" E...oo...E ",
+"  EE.Xo.EE  ",
+"    EEEE    .Xo.",
diff --git a/texi/smilies/FaceSad.xpm b/texi/smilies/FaceSad.xpm
new file mode 100644 (file)
index 0000000..ced9a02
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E..........E",
+"E...XXXX...E",
+" E.X....X.E ",
+" EX......XE ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceStartled.xpm b/texi/smilies/FaceStartled.xpm
new file mode 100644 (file)
index 0000000..75739c9
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E...XXXX...E",
+"E..X....X..E",
+" E.X....X.E ",
+" E..XXXX..E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceStraight.xpm b/texi/smilies/FaceStraight.xpm
new file mode 100644 (file)
index 0000000..4298065
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E..........E",
+"E...XXXX...E",
+" E........E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceTalking.xpm b/texi/smilies/FaceTalking.xpm
new file mode 100644 (file)
index 0000000..2295be8
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E..........E",
+"E...XXXXX..E",
+" E....XXX.E ",
+" E....XX..E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceTasty.xpm b/texi/smilies/FaceTasty.xpm
new file mode 100644 (file)
index 0000000..968e493
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E...o......E",
+"E..ooo.....E",
+" E.XXXXX..E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceWinking.xpm b/texi/smilies/FaceWinking.xpm
new file mode 100644 (file)
index 0000000..25d62ef
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X.....E ",
+"E...X.XXX..E",
+"E..........E",
+"E.X......X.E",
+"E..XXXXXX..E",
+" E..XXXX..E ",
+" E........E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceWry.xpm b/texi/smilies/FaceWry.xpm
new file mode 100644 (file)
index 0000000..db6010d
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E..X..X..E ",
+"E...X..X...E",
+"E..........E",
+"E..........E",
+"E.....XXX..E",
+" E..XX....E ",
+" E....XX..E ",
+"  EE....EE  ",
+"    EEEE    ....",
diff --git a/texi/smilies/FaceYukky.xpm b/texi/smilies/FaceYukky.xpm
new file mode 100644 (file)
index 0000000..0d3de33
--- /dev/null
@@ -0,0 +1,20 @@
+/* XPM */
+static char * image_name[] = {
+"12 12 5 1",
+"      c none",
+".     c #FFFF00 s flesh",
+"X     c #000000000000 s features",
+"E      c #000000000000 s circle",
+"o     c #555555555555 s tongue",
+"    EEEE    ",
+"  EE....EE  ",
+" E........E ",
+" E.X....X.E ",
+"E...X..X...E",
+"E..........E",
+"E..........E",
+"E..XXXXX...E",
+" E..oooX..E ",
+" E...oo...E ",
+"  EE.Xo.EE  ",
+"    EEEE    .Xo.",
diff --git a/texi/smilies/WideFaceAse1.xbm b/texi/smilies/WideFaceAse1.xbm
new file mode 100644 (file)
index 0000000..1a5a589
--- /dev/null
@@ -0,0 +1,19 @@
+#define Face_ase_width 24
+#define Face_ase_height 16
+static char Face_ase_bits[] = {
+  0x00,0x00,0x00,
+  0xf8,0xc1,0x0f,
+  0x04,0x22,0x10,
+  0x00,0x00,0x00,
+  0xf0,0xc0,0x03,
+  0x68,0xa1,0x05,
+  0x68,0xa1,0x05,
+  0x68,0xa1,0x05,
+  0xf0,0xc0,0x23,
+  0x00,0x00,0x20,
+  0x00,0x00,0x50,
+  0x50,0x40,0x52,
+  0x00,0x00,0x50,
+  0x20,0x91,0x20,
+  0x00,0x0e,0x00,
+  0x00,0x00,0x00};
diff --git a/texi/smilies/WideFaceAse2.xbm b/texi/smilies/WideFaceAse2.xbm
new file mode 100644 (file)
index 0000000..4c7fcb6
--- /dev/null
@@ -0,0 +1,19 @@
+#define Face_ase2_width 32
+#define Face_ase2_height 16
+static char Face_ase2_bits[] = {
+  0x00,0x00,0x00,0x00,
+  0xf0,0x83,0x1f,0x00,
+  0x08,0x44,0x20,0x00,
+  0x00,0x00,0x00,0x00,
+  0xe0,0x81,0x07,0x00,
+  0xd0,0x42,0x0b,0x00,
+  0xd0,0x42,0x0b,0x00,
+  0xd0,0x42,0x0b,0x00,
+  0xe0,0x81,0x87,0x10,
+  0x00,0x00,0x80,0x10,
+  0x00,0x00,0x40,0x29,
+  0xa0,0x80,0x44,0x29,
+  0x00,0x00,0x40,0x29,
+  0x40,0x22,0x81,0x10,
+  0x00,0x1c,0x00,0x00,
+  0x00,0x00,0x00,0x00};
diff --git a/texi/smilies/WideFaceAse3.xbm b/texi/smilies/WideFaceAse3.xbm
new file mode 100644 (file)
index 0000000..0960e77
--- /dev/null
@@ -0,0 +1,20 @@
+#define Face_ase3_width 24
+#define Face_ase3_height 16
+static char Face_ase3_bits[] = {
+  0x00,0x00,0x00,
+  0xf8,0xc1,0x0f,
+  0x04,0x22,0x10,
+  0x00,0x00,0x00,
+  0x18,0x00,0x07,
+  0xe0,0xe0,0x00,
+  0xfc,0xf3,0x0f,
+  0xc0,0xe1,0x00,
+  0x38,0x00,0x27,
+  0x00,0x00,0x20,
+  0x00,0x00,0x50,
+  0x50,0x40,0x52,
+  0x00,0x00,0x50,
+  0x20,0x91,0x20,
+  0x00,0x0e,0x00,
+  0x00,0x00,0x00
+};
diff --git a/texi/smilies/WideFaceSmile.xbm b/texi/smilies/WideFaceSmile.xbm
new file mode 100644 (file)
index 0000000..c4cc3bc
--- /dev/null
@@ -0,0 +1,19 @@
+#define Face_smile_width 24
+#define Face_smile_height 16
+static char Face_smile_bits[] = {
+  0x00,0x00,0x00,
+  0xf8,0xc1,0x0f,
+  0x04,0x22,0x10,
+  0x00,0x00,0x00,
+  0xf0,0xc0,0x07,
+  0x68,0xa1,0x09,
+  0x68,0xa1,0x09,
+  0x68,0xa1,0x09,
+  0xf0,0xc0,0x07,
+  0x00,0x00,0x00,
+  0x00,0x00,0x00,
+  0x50,0x80,0x04,
+  0x00,0x00,0x00,
+  0x20,0x22,0x01,
+  0x00,0x1c,0x00,
+  0x00,0x00,0x00};
diff --git a/texi/smilies/WideFaceWeep.xbm b/texi/smilies/WideFaceWeep.xbm
new file mode 100644 (file)
index 0000000..4353148
--- /dev/null
@@ -0,0 +1,20 @@
+#define Face_weep_width 24
+#define Face_weep_height 16
+static char Face_weep_bits[] = {
+  0x1c,0x00,0x3c,
+  0xe2,0x80,0x43,
+  0x00,0x63,0x00,
+  0x18,0x00,0x18,
+  0x60,0x00,0x07,
+  0x80,0xe3,0x00,
+  0xfc,0xf7,0x3f,
+  0x80,0xe3,0x00,
+  0x60,0x00,0x07,
+  0x58,0x00,0x1a,
+  0x40,0x00,0x02,
+  0xa0,0x00,0x05,
+  0xa0,0x00,0x05,
+  0xa0,0x1c,0x05,
+  0x40,0x22,0x02,
+  0x00,0x00,0x00
+};
diff --git a/texi/splitindex b/texi/splitindex
new file mode 100755 (executable)
index 0000000..cfd568c
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+match='M-x |(Group)|(Summary)|(Article)|(Server)|(Browse)|(Post)|(Mail)|(Score)|(Binary)|(Topic)|(Pick)'
+fun='\{gnus-|\{nn.*-|\{grouplens-'
+egrep "$match" gnus.idx > gnus.kidx
+egrep "$fun" gnus.idx > gnus.gidx
+egrep -v "$match|$fun" gnus.idx > gnus.cidx
diff --git a/texi/texi2latex.el b/texi/texi2latex.el
new file mode 100644 (file)
index 0000000..a5e5a26
--- /dev/null
@@ -0,0 +1,386 @@
+;;; texi2latex.el --- convert a texi file into a LaTeX file.
+;; Copyright (C) 1996 Lars Magne Ingebrigtsen
+
+(require 'cl)
+
+(defun latexi-discard-until (string)
+  (let ((beg (match-beginning 0)))
+    (unless (re-search-forward (concat "^@end +" string "[ \t]*\n") nil t)
+      (error "No end: %s" string))
+    (delete-region beg (match-end 0))))
+
+(defun latexi-strip-line ()
+  (delete-region (progn (beginning-of-line) (point))
+                (progn (forward-line 1) (point))))
+
+(defun latexi-switch-line (command arg)
+  (latexi-strip-line)
+  (insert (format "\\%s{%s}\n" command arg)))
+
+(defun latexi-index-command (command arg)
+  (latexi-strip-line)
+  (insert (format "\\gnus%sindex{%s}\n" 
+                 (if (equal command "kindex") "k" "")
+                 arg)))
+
+(defun latexi-begin-command (command)
+  (latexi-strip-line)
+  (insert (format "\\begin{%s}\n" command)))
+
+(defun latexi-exchange-command (command arg)
+  (delete-region (match-beginning 0) (match-end 0))
+  (insert (format "\\%s{%s}" command arg)))
+
+(defun latexi-translate ()
+  "Translate."
+  (interactive)
+  (latexi-translate-file "gnus")
+  (latexi-translate-file "gnus-faq")
+  (latexi-translate-file "message" t)
+  (latexi-translate-file "emacs-mime" t)
+  (latexi-translate-file "sieve" t))
+
+(defun latexi-translate-file (file &optional as-a-chapter)
+  "Translate file a LaTeX file."
+  (let ((item-string "")
+       (item-stack nil)
+       (list-stack nil)
+       (latexi-buffer (get-buffer-create "*LaTeXi*"))
+       verbatim
+       (regexp 
+        (concat 
+           "@\\([^{} \t\n]+\\)"
+           "\\(\\( +\\(.*$\\)\\|[ \t]*$\\)\\|{\\([^}]*\\)}\\)"))
+       (cur (find-file-noselect (concat (or (getenv "srcdir") ".") 
+                                        "/" file ".texi")))
+       (times 3)
+       (chapter 0)
+       command arg)
+    (pop-to-buffer latexi-buffer)
+    (buffer-disable-undo)
+    (erase-buffer)
+    (insert-buffer-substring cur)
+    (goto-char (point-min))
+    (latexi-strip-line)
+    (latexi-translate-string "%@{" "\\gnuspercent{}\\gnusbraceleft{}")
+    (latexi-translate-string "%@}" "\\gnuspercent{}\\gnusbraceright{}")
+    (latexi-translate-string "%1@{" "\\gnuspercent{}1\\gnusbraceright{}")
+    (latexi-translate-string "@*" "\\newline{}")
+    (latexi-translate-string "S@{" "S\\gnusbraceleft{}")
+    (latexi-translate-string "@code{\\222}" "@code{\\gnusbackslash{}222}")
+    (latexi-translate-string "@code{\\264}" "@code{\\gnusbackslash{}264}")
+    (latexi-translate-string "@samp{\\Deleted}" "@samp{\\gnusbackslash{}Deleted}")
+    (latexi-translate-string "@samp{\\Seen}" "@samp{\\gnusbackslash{}Seen}")
+    (latexi-translate-string "@file{c:\\myhome}" "@file{c:\\gnusbackslash{}myhome}")
+;    (while (re-search-forward "{\"[^\"]*\\(\\\\\\)[^\"]*\"}\\\\" nil t)
+;      (replace-match "\\verb+\\\\+ " t t))
+    (while (not (zerop (decf times)))
+      (goto-char (point-min))
+      (while (re-search-forward regexp nil t)
+       (setq command (match-string 1))
+       (if (match-beginning 3)
+           (progn
+             (setq arg (or (match-string 4) ""))
+             (save-match-data
+               (when (string-match "[ \t]+$" arg)
+                 (setq arg (substring arg 0 (match-beginning 0)))))
+             (cond 
+              ((member command '("c" "comment"))
+               (if (string-match "@icon" (or arg ""))
+                   (progn
+                     (beginning-of-line)
+                     (delete-region (point) (+ (point) 4))
+                     (insert "\\gnus"))
+                 (delete-region (match-beginning 0) 
+                                (progn (end-of-line) (point))))
+               (if (equal arg "@head")
+                   (insert "\\gnusinteresting")))
+              ((member command '("setfilename" "set"
+                                 "synindex" "setchapternewpage"
+                                 "summarycontents" "bye"
+                                 "top" "iftex" "cartouche" 
+                                 "iflatex" "finalout" "vskip"
+                                 "dircategory" "group" "syncodeindex"))
+               (latexi-strip-line))
+              ((member command '("menu" "tex" "ifinfo" "ignore" 
+                                 "ifnottex" "direntry"))
+               (latexi-discard-until command))
+              ((member command '("subsection" "subsubsection"))
+               (if as-a-chapter
+                   (latexi-switch-line (format "sub%s" command) arg)
+                 (latexi-switch-line command arg)))
+              ((member command '("heading"))
+               (if as-a-chapter
+                   (latexi-switch-line "subsection*" arg)
+                 (latexi-switch-line "section*" arg)))
+              ((member command '("subheading"))
+               (if as-a-chapter
+                   (latexi-switch-line "subsubsection*" arg)
+                 (latexi-switch-line "subsection*" arg)))
+              ((member command '("subsubheading"))
+               (if as-a-chapter
+                   (latexi-switch-line "subsubsubsection*" arg)
+                 (latexi-switch-line "subsubsection*" arg)))
+              ((member command '("chapter"))
+               (if (string-match "Index" arg)
+                   (latexi-strip-line)
+                 (if as-a-chapter
+                     (latexi-switch-line "gnussection" arg)
+                   (latexi-switch-line 
+                    (format 
+                     "gnus%s{%s}" command
+                     (format "\\epsfig{figure=ps/new-herd-%d,scale=.5}"
+                             (if (> (incf chapter) 9) 9 chapter)))
+                    arg))))
+              ((member command '("section"))
+               (if as-a-chapter
+                   (latexi-switch-line "subsection" arg)
+                 (latexi-switch-line (format "gnus%s" command) arg)))
+              ((member command '("cindex" "findex" "kindex" "vindex"))
+               (latexi-index-command command arg))
+              ((member command '("*"))
+               (delete-char -2)
+               (insert "\\\\"))
+              ((equal command "sp")
+               (replace-match "" t t))
+              ((equal command ":")
+               (replace-match "" t t))
+              ((member command '("deffn" "defvar" "defun"))
+               (replace-match "" t t))
+              ((equal command "node")
+               (latexi-strip-line)
+               (unless (string-match "Index" arg)
+                 (insert (format "\\label{%s}\n" arg))))
+              ((equal command "contents")
+               (latexi-strip-line)
+               ;;(insert (format "\\tableofcontents\n" arg))
+               )
+              ((member command '("titlepage"))
+               (latexi-begin-command command))
+              ((member command '("lisp" "example" "smallexample" "display"))
+               (latexi-strip-line)
+               (insert (format "\\begin{verbatim}\n"))
+               (setq verbatim (point)))
+              ((member command '("center"))
+               (latexi-strip-line)
+               (insert (format "\\begin{%s}%s\\end{%s}\n"
+                               command arg command)))
+              ((member command '("end"))
+               (cond
+                ((member arg '("titlepage"))
+                 (latexi-strip-line)
+                 (insert (format "\\end{%s}\n" arg)))
+                ((equal arg "quotation")
+                 (latexi-strip-line)
+                 (insert (format "\\end{verse}\n")))
+                ((member arg '("lisp" "example" "smallexample" "display"))
+                 (latexi-strip-line)
+                 (save-excursion
+                   (save-restriction
+                     (narrow-to-region verbatim (point))
+                     (goto-char (point-min))
+                     (while (search-forward "@{" nil t)
+                       (replace-match "{" t t))
+                     (goto-char (point-min))
+                     (while (search-forward "@}" nil t)
+                       (replace-match "}" t t))))
+                 (setq verbatim nil)
+                 (insert "\\end{verbatim}\n"))
+                ((member arg '("table"))
+                 (setq item-string (pop item-stack))
+                 (latexi-strip-line)
+                 (insert (format "\\end{%slist}\n" (pop list-stack))))
+                ((member arg '("itemize" "enumerate"))
+                 (setq item-string (pop item-stack))
+                 (latexi-strip-line)
+                 (insert (format "\\end{%s}\n" arg)))
+                ((member arg '("iflatex" "iftex" "cartouche" "group"))
+                 (latexi-strip-line))
+                ((member arg '("deffn" "defvar" "defun"))
+                 (latexi-strip-line))
+                (t
+                 (error "Unknown end arg: %s" arg))))
+              ((member command '("table"))
+               (push item-string item-stack)
+               (push (substring arg 1) list-stack)
+               (setq item-string 
+                     (format "[@%s{%%s}]" (car list-stack)))
+               (latexi-strip-line)
+               (insert (format "\\begin{%slist}\n" (car list-stack))))
+              ((member command '("itemize" "enumerate"))
+               (push item-string item-stack)
+               (cond 
+                ((member arg '("@bullet"))
+                 (setq item-string "[\\gnusbullet]"))
+                (t
+                 (setq item-string "")))
+               (latexi-strip-line)
+               (insert (format "\\begin{%s}\n" command)))
+              ((member command '("item"))
+               (latexi-strip-line)
+               (insert (format "\\%s%s\n" command (format item-string arg))))
+              ((equal command "itemx")
+               (latexi-strip-line)
+               (insert (format "\\gnusitemx{%s}\n" (format item-string arg))))
+              ((eq (aref command 0) ?@)
+               (goto-char (match-beginning 0))
+               (delete-char 2)
+               (insert "duppat{}"))
+              ((equal command "settitle")
+               (latexi-strip-line)
+               (if (not as-a-chapter)
+                   (insert 
+                    (format "\\newcommand{\\gnustitlename}{%s}\n" arg))))
+              ((equal command "title")
+               (latexi-strip-line)
+               (insert (format "\\gnustitlename{%s}\n" arg)))
+              ((equal command "author")
+               (latexi-strip-line)
+               (insert (format "\\gnusauthor{%s}\n" arg)))
+              ((equal command "quotation")
+               (latexi-begin-command "verse"))
+              ((equal command "page")
+               (latexi-strip-line)
+               (insert (format "\\newpage\n" arg)))
+              ((equal command "'s")
+               (goto-char (match-beginning 0))
+               (delete-char 1))
+              ((equal command "include")
+               (latexi-strip-line)
+               (string-match "\\.texi" arg)
+               (insert (format "\\input{%s.latexi}\n" 
+                               (substring arg 0 (match-beginning 0)))))
+              ((equal command "noindent")
+               (latexi-strip-line)
+               (insert "\\noindent\n"))
+              ((equal command "printindex")
+               (latexi-strip-line)
+               ;;(insert 
+               ;; (format 
+               ;;  "\\begin{theindex}\\input{gnus.%s}\\end{theindex}\n" arg))
+               )
+              (t
+               (error "Unknown command (file %s line %d): %s"
+                      file
+                      (save-excursion
+                        (widen)
+                        (1+ (count-lines (point-min) (progn
+                                                       (beginning-of-line)
+                                                       (point)))))
+                      command))))
+         ;; These are commands with {}.
+         (setq arg (match-string 5))
+         (cond 
+          ((member command '("anchor"))
+           (latexi-strip-line))
+          ((member command '("ref" "xref" "pxref"))
+           (latexi-exchange-command (concat "gnus" command) arg))
+          ((member command '("sc" "file" "dfn" "emph" "kbd" "key" "uref"
+                             "code" "samp" "var" "strong" "i"
+                             "result" "email" "env" "r" "command" "asis"
+                             "url"))
+           (goto-char (match-beginning 0))
+           (delete-char 1)
+           (insert "\\gnus"))
+          ((member command '("acronym"))
+           (latexi-exchange-command (concat "gnus" command) (downcase arg)))
+          ((member command '("copyright" "footnote" "TeX"))
+           (goto-char (match-beginning 0))
+           (delete-char 1)
+           (insert "\\"))
+          ((member command '("dots"))
+           (goto-char (match-beginning 0))
+           (delete-region (match-beginning 0) (match-end 0))
+           (insert "..."))
+          ((eq (aref command 0) ?@)
+           (goto-char (match-beginning 0))
+           (delete-char 2)
+           (insert "duppat{}"))
+          (t
+           (error "Unknown command (file %s line %d): %s"
+                  file
+                  (save-excursion
+                    (widen)
+                    (1+ (count-lines (point-min) (progn
+                                                   (beginning-of-line)
+                                                   (point)))))
+                  command))))))
+    (latexi-translate-string "$" "\\gnusdollar{}")
+    (latexi-translate-string "&" "\\gnusampersand{}")
+    (latexi-translate-string "%" "\\gnuspercent{}")
+    (latexi-translate-string "#" "\\gnushash{}")
+    (latexi-translate-string "^" "\\gnushat{}")
+    (latexi-translate-string "~" "\\gnustilde{}")
+    (latexi-translate-string "_" "\\gnusunderline{}")
+    (latexi-translate-string "¬" "\\gnusnot{}")
+    (goto-char (point-min))
+    (while (search-forward "duppat{}" nil t)
+      (replace-match "@" t t))
+    (latexi-translate-string "@@" "@")
+    (latexi-translate-string "<" "\\gnusless{}")
+    (latexi-translate-string ">" "\\gnusgreater{}")
+    (goto-char (point-min))
+    (search-forward "label{Top}" nil t)
+    (while (re-search-forward "\\\\[ntr]\\b" nil t)
+      (when (save-match-data
+             (or (not (save-excursion
+                        (search-backward "begin{verbatim}" nil t)))
+                 (> (save-excursion
+                      (search-backward "end{verbatim"))
+                    (save-excursion
+                      (search-backward "begin{verbatim}")))))
+       (goto-char (match-beginning 0))
+       (delete-char 1)
+       (insert "\\gnusbackslash{}")))
+    (latexi-translate-string "\\\\" "\\gnusbackslash{}")
+    (goto-char (point-min))
+    (while (re-search-forward "\\\\[][{}]" nil t)
+      (goto-char (match-beginning 0))
+      (delete-char 1))
+    (latexi-contributors)
+    (let ((coding-system-for-write 'iso-8859-1))
+      (write-region (point-min) (point-max) (concat file ".latexi")))))
+
+(defun latexi-translate-string (in out)
+  (let (yes)
+    (goto-char (point-min))
+    (search-forward "label{Top}" nil t)
+    (while (search-forward in nil t)
+      (when (save-match-data
+             (or (not (save-excursion
+                        (search-backward "begin{verbatim}" nil t)))
+                 (> (save-excursion
+                      (re-search-backward "end{verbatim}\\|end{verse}"))
+                    (save-excursion
+                      (re-search-backward
+                       "begin{verbatim}\\|begin{verse}")))))
+       (replace-match out t t)))))
+
+(defun latexi-contributors ()
+  (goto-char (point-min))
+  (when (re-search-forward "^Also thanks to the following" nil t)
+    (forward-line 2)
+    (narrow-to-region
+     (point)
+     (1- (search-forward "\n\n")))
+    (when (re-search-backward "^and" nil t)
+      (latexi-strip-line))
+    (goto-char (point-min))
+    (while (re-search-forward "[.,] *$" nil t)
+      (replace-match "" t t))
+    (goto-char (point-min))
+    (let (names)
+      (while (not (eobp))
+       (push (buffer-substring (point) (progn (end-of-line) (point)))
+             names)
+       (forward-line 1))
+      (delete-region (point-min) (point-max))
+      (insert "\\begin{tabular}{lll}\n")
+      (setq names (nreverse (delete "" names)))
+      (while names
+       (insert (pop names) " & " (or (pop names) "\\mbox{}") 
+               " & " (or (pop names) "\\mbox{}") 
+               "\\\\\n"))
+      (insert "\\end{tabular}\n")
+      (widen))))
+       
diff --git a/texi/widget.texi b/texi/widget.texi
deleted file mode 100644 (file)
index b733a78..0000000
+++ /dev/null
@@ -1,1432 +0,0 @@
-\input texinfo.tex
-
-@c %**start of header
-@setfilename widget
-@settitle The Emacs Widget Library
-@iftex
-@afourpaper
-@headings double
-@end iftex
-@c %**end of header
-
-@node Top, Introduction, (dir), (dir)
-@comment  node-name,  next,  previous,  up
-@top The Emacs Widget Library
-
-Version: 1.82
-
-@menu
-* Introduction::                
-* User Interface::              
-* Programming Example::         
-* Setting Up the Buffer::       
-* Basic Types::                 
-* Sexp Types::                  
-* Widget Properties::           
-* Defining New Widgets::        
-* Widget Wishlist.::            
-@end menu
-
-@node  Introduction, User Interface, Top, Top
-@comment  node-name,  next,  previous,  up
-@section Introduction
-
-Most graphical user interface toolkits, such as Motif and XView, provide
-a number of standard user interface controls (sometimes known as
-`widgets' or `gadgets').  Emacs doesn't really support anything like
-this, except for an incredible powerful text ``widget''.  On the other
-hand, Emacs does provide the necessary primitives to implement many
-other widgets within a text buffer.  The @code{widget} package
-simplifies this task.
-
-The basic widgets are:
-
-@table @code
-@item link
-Areas of text with an associated action.  Intended for hypertext links
-embedded in text.
-@item push-button 
-Like link, but intended for stand-alone buttons.
-@item editable-field
-An editable text field.  It can be either variable or fixed length.
-@item menu-choice
-Allows the user to choose one of multiple options from a menu, each
-option is itself a widget.  Only the selected option will be visible in
-the buffer.
-@item radio-button-choice
-Allows the user to choose one of multiple options by pushing radio
-buttons.  The options are implemented as widgets.  All options will be
-visible in the buffer.
-@item item
-A simple constant widget intended to be used in the @code{menu-choice} and
-@code{radio-button-choice} widgets. 
-@item choice-item
-An button item only intended for use in choices.  When pushed, the user
-will be asked to select another option from the choice widget.
-@item toggle
-A simple @samp{on}/@samp{off} switch.
-@item checkbox
-A checkbox (@samp{[ ]}/@samp{[X]}). 
-@item editable-list
-Create an editable list.  The user can insert or delete items in the
-list.  Each list item is itself a widget.
-@end table
-
-Now of what possible use can support for widgets be in a text editor?
-I'm glad you asked.  The answer is that widgets are useful for
-implementing forms.  A @dfn{form} in emacs is a buffer where the user is
-supposed to fill out a number of fields, each of which has a specific
-meaning.  The user is not supposed to change or delete any of the text
-between the fields.  Examples of forms in Emacs are the @file{forms}
-package (of course), the customize buffers, the mail and news compose
-modes, and the @sc{html} form support in the @file{w3} browser.  
-
-The advantages for a programmer of using the @code{widget} package to
-implement forms are:
-
-@enumerate
-@item
-More complex field than just editable text are supported. 
-@item
-You can give the user immediate feedback if he enters invalid data in a
-text field, and sometimes prevent entering invalid data.
-@item 
-You can have fixed sized fields, thus allowing multiple field to be
-lined up in columns.
-@item
-It is simple to query or set the value of a field. 
-@item 
-Editing happens in buffer, not in the mini-buffer.
-@item 
-Packages using the library get a uniform look, making them easier for
-the user to learn.
-@item 
-As support for embedded graphics improve, the widget library will
-extended to support it.  This means that your code using the widget
-library will also use the new graphic features by automatic.
-@end enumerate
-
-In order to minimize the code that is loaded by users who does not
-create any widgets, the code has been split in two files:
-
-@table @file
-@item widget.el
-This will declare the user variables, define the function
-@code{widget-define}, and autoload the function @code{widget-create}. 
-@item wid-edit.el
-Everything else is here, there is no reason to load it explicitly, as
-it will be autoloaded when needed.
-@end table
-
-@node User Interface, Programming Example, Introduction, Top
-@comment  node-name,  next,  previous,  up
-@section User Interface
-
-A form consist of read only text for documentation and some fields,
-where each the fields contain two parts, as tag and a value.  The tags
-are used to identify the fields, so the documentation can refer to the
-foo field, meaning the field tagged with @samp{Foo}. Here is an example
-form:
-
-@example
-Here is some documentation.
-
-Name: @i{My Name}     @strong{Choose}: This option
-Address:  @i{Some Place
-In some City
-Some country.}
-
-See also @b{_other work_} for more information.
-
-Numbers: count to three below
-@b{[INS]} @b{[DEL]} @i{One}
-@b{[INS]} @b{[DEL]} @i{Eh, two?}
-@b{[INS]} @b{[DEL]} @i{Five!}
-@b{[INS]} 
-
-Select multiple:
-
-@b{[X]} This
-@b{[ ]} That
-@b{[X]} Thus
-
-Select one:
-
-@b{(*)} One
-@b{( )} Another One.
-@b{( )} A Final One.
-
-@b{[Apply Form]} @b{[Reset Form]}
-@end example
-
-The top level widgets in is example are tagged @samp{Name},
-@samp{Choose}, @samp{Address}, @samp{_other work_}, @samp{Numbers},
-@samp{Select multiple}, @samp{Select one}, @samp{[Apply Form]}, and
-@samp{[Reset Form]}.  There are basically two thing the user can do within
-a form, namely editing the editable text fields and activating the
-buttons.
-
-@subsection Editable Text Fields
-
-In the example, the value for the @samp{Name} is most likely displayed
-in an editable text field, and so are values for each of the members of
-the @samp{Numbers} list.  All the normal Emacs editing operations are
-available for editing these fields.  The only restriction is that each
-change you make must be contained within a single editable text field.
-For example, capitalizing all text from the middle of one field to the
-middle of another field is prohibited.
-
-Editing text fields are created by the @code{editable-field} widget.
-
-The editing text fields are highlighted with the
-@code{widget-field-face} face, making them easy to find.
-
-@deffn Face widget-field-face
-Face used for other editing fields.
-@end deffn
-
-@subsection Buttons
-
-Some portions of the buffer have an associated @dfn{action}, which can
-be @dfn{activated} by a standard key or mouse command.  These portions
-are called @dfn{buttons}.  The default commands for activating a button
-are:
-
-@table @kbd
-@item @key{RET}
-@deffn Command widget-button-press @var{pos} &optional @var{event}
-Activate the button at @var{pos}, defaulting to point.
-If point is not located on a button, activate the binding in
-@code{widget-global-map} (by default the global map).
-@end deffn
-
-@item mouse-2
-@deffn Command widget-button-click @var{event}
-Activate the button at the location of the mouse pointer.  If the mouse
-pointer is located in an editable text field, activate the binding in
-@code{widget-global-map} (by default the global map).
-@end deffn
-@end table
-
-There are several different kind of buttons, all of which are present in
-the example:
-
-@table @emph
-@item The Option Field Tags.
-When you activate one of these buttons, you will be asked to choose
-between a number of different options.  This is how you edit an option
-field.  Option fields are created by the @code{menu-choice} widget.  In
-the example, @samp{@b{Choose}} is an option field tag.
-@item The @samp{@b{[INS]}} and @samp{@b{[DEL]}} buttons.
-Activating these will insert or delete elements from a editable list.
-The list is created by the @code{editable-list} widget. 
-@item Embedded Buttons.
-The @samp{@b{_other work_}} is an example of an embedded
-button. Embedded buttons are not associated with a fields, but can serve
-any purpose, such as implementing hypertext references.  They are
-usually created by the @code{link} widget.
-@item The @samp{@b{[ ]}} and @samp{@b{[X]}} buttons.
-Activating one of these will convert it to the other.  This is useful
-for implementing multiple-choice fields.  You can create it wit
-@item The @samp{@b{( )}} and @samp{@b{(*)}} buttons.
-Only one radio button in a @code{radio-button-choice} widget can be selected at any
-time.  When you push one of the unselected radio buttons, it will be
-selected and the previous selected radio button will become unselected. 
-@item The @samp{@b{[Apply Form]}} @samp{@b{[Reset Form]}} buttons.
-These are explicit buttons made with the @code{push-button} widget.  The main
-difference from the @code{link} widget is that the buttons are will be
-displayed as GUI buttons when possible.
-enough. 
-@end table
-
-To make them easier to locate, buttons are emphasized in the buffer.  
-
-@deffn Face widget-button-face
-Face used for buttons.
-@end deffn
-
-@defopt widget-mouse-face
-Face used for buttons when the mouse pointer is above it.
-@end defopt
-
-@subsection Navigation
-
-You can use all the normal Emacs commands to move around in a form
-buffer, plus you will have these additional commands:
-
-@table @kbd
-@item @key{TAB}
-@deffn Command widget-forward &optional count
-Move point @var{count} buttons or editing fields forward.
-@end deffn
-@item @key{M-TAB}
-@deffn Command widget-backward &optional count
-Move point @var{count} buttons or editing fields backward.
-@end deffn
-@end table
-
-@node Programming Example, Setting Up the Buffer, User Interface, Top
-@comment  node-name,  next,  previous,  up
-@section Programming Example
-
-Here is the code to implement the user interface example (see @ref{User
-Interface}).
-
-@lisp
-(require 'widget)
-
-(eval-when-compile
-  (require 'wid-edit))
-
-(defvar widget-example-repeat)
-
-(defun widget-example ()
-  "Create the widgets from the Widget manual."
-  (interactive)
-  (switch-to-buffer "*Widget Example*")
-  (kill-all-local-variables)
-  (make-local-variable 'widget-example-repeat)
-  (let ((inhibit-read-only t))
-    (erase-buffer))
-  (widget-insert "Here is some documentation.\n\nName: ")
-  (widget-create 'editable-field
-                :size 13
-                "My Name")
-  (widget-create 'menu-choice
-                :tag "Choose"
-                :value "This"
-                :help-echo "Choose me, please!"
-                :notify (lambda (widget &rest ignore)
-                          (message "%s is a good choice!"
-                                   (widget-value widget)))
-                '(item :tag "This option" :value "This")
-                '(choice-item "That option")
-                '(editable-field :menu-tag "No option" "Thus option"))
-  (widget-insert "Address: ")
-  (widget-create 'editable-field
-                "Some Place\nIn some City\nSome country.")
-  (widget-insert "\nSee also ")
-  (widget-create 'link
-                :notify (lambda (&rest ignore)
-                          (widget-value-set widget-example-repeat 
-                                            '("En" "To" "Tre"))
-                          (widget-setup))
-                "other work")
-  (widget-insert " for more information.\n\nNumbers: count to three below\n")
-  (setq widget-example-repeat
-       (widget-create 'editable-list
-                      :entry-format "%i %d %v"
-                      :notify (lambda (widget &rest ignore)
-                                (let ((old (widget-get widget
-                                                       ':example-length))
-                                      (new (length (widget-value widget))))
-                                  (unless (eq old new)
-                                    (widget-put widget ':example-length new)
-                                    (message "You can count to %d." new))))
-                      :value '("One" "Eh, two?" "Five!")
-                      '(editable-field :value "three")))
-  (widget-insert "\n\nSelect multiple:\n\n")
-  (widget-create 'checkbox t)
-  (widget-insert " This\n")
-  (widget-create 'checkbox nil)
-  (widget-insert " That\n")
-  (widget-create 'checkbox
-                :notify (lambda (&rest ignore) (message "Tickle"))
-                t)
-  (widget-insert " Thus\n\nSelect one:\n\n")
-  (widget-create 'radio-button-choice
-                :value "One"
-                :notify (lambda (widget &rest ignore)
-                          (message "You selected %s"
-                                   (widget-value widget)))
-                '(item "One") '(item "Anthor One.") '(item "A Final One."))
-  (widget-insert "\n")
-  (widget-create 'push-button
-                :notify (lambda (&rest ignore) 
-                          (if (= (length (widget-value widget-example-repeat))
-                                 3)
-                              (message "Congratulation!")
-                            (error "Three was the count!")))
-                "Apply Form")
-  (widget-insert " ")
-  (widget-create 'push-button
-                :notify (lambda (&rest ignore)
-                          (widget-example))
-                "Reset Form")
-  (widget-insert "\n")
-  (use-local-map widget-keymap)
-  (widget-setup))
-@end lisp
-
-@node Setting Up the Buffer, Basic Types, Programming Example, Top
-@comment  node-name,  next,  previous,  up
-@section Setting Up the Buffer
-
-Widgets are created with @code{widget-create}, which returns a
-@dfn{widget} object.  This object can be queried and manipulated by
-other widget functions, until it is deleted with @code{widget-delete}.
-After the widgets have been created, @code{widget-setup} must be called
-to enable them.
-
-@defun widget-create type [ keyword argument ]@dots{}
-Create and return a widget of type @var{type}.
-The syntax for the @var{type} argument is described in @ref{Basic Types}.
-
-The keyword arguments can be used to overwrite the keyword arguments
-that are part of @var{type}.
-@end defun
-
-@defun widget-delete widget
-Delete @var{widget} and remove it from the buffer.
-@end defun
-
-@defun widget-setup 
-Setup a buffer to support widgets. 
-
-This should be called after creating all the widgets and before allowing
-the user to edit them.
-@refill
-@end defun
-
-If you want to insert text outside the widgets in the form, the
-recommended way to do that is with @code{widget-insert}.
-
-@defun widget-insert 
-Insert the arguments, either strings or characters, at point.
-The inserted text will be read only.
-@end defun
-
-There is a standard widget keymap which you might find useful.
-
-@defvr Const widget-keymap
-A keymap with the global keymap as its parent.@*
-@key{TAB} and @kbd{C-@key{TAB}} are bound to @code{widget-forward} and
-@code{widget-backward}, respectively.  @kbd{@key{RET}} and @kbd{mouse-2}
-are bound to @code{widget-button-press} and
-@code{widget-button-}.@refill
-@end defvr
-
-@defvar widget-global-map
-Keymap used by @code{widget-button-press} and @code{widget-button-click}
-when not on a button.  By default this is @code{global-map}.
-@end defvar
-
-@node Basic Types, Sexp Types, Setting Up the Buffer, Top
-@comment  node-name,  next,  previous,  up
-@section Basic Types
-
-The syntax of a type specification is given below:
-
-@example
-NAME ::= (NAME [KEYWORD ARGUMENT]... ARGS)
-     |   NAME
-@end example
-
-Where, @var{name} is a widget name, @var{keyword} is the name of a
-property, @var{argument} is the value of the property, and @var{args}
-are interpreted in a widget specific way.
-
-There following keyword arguments that apply to all widgets:
-
-@table @code
-@item :value
-The initial value for widgets of this type.
-
-@item :format
-This string will be inserted in the buffer when you create a widget.
-The following @samp{%} escapes are available:
-
-@table @samp
-@item %[
-@itemx %]
-The text inside will be marked as a button.
-
-@item %@{
-@itemx %@}
-The text inside will be displayed with the face specified by
-@code{:sample-face}. 
-
-@item %v
-This will be replaces with the buffer representation of the widgets
-value.  What this is depends on the widget type.
-
-@item %d
-Insert the string specified by @code{:doc} here.
-
-@item %h
-Like @samp{%d}, with the following modifications: If the documentation
-string is more than one line, it will add a button which will toggle
-between showing only the first line, and showing the full text.
-Furthermore, if there is no @code{:doc} property in the widget, it will
-instead examine the @code{:documentation-property} property.  If it is a
-lambda expression, it will be called with the widget's value as an
-argument, and the result will be used as the documentation text.
-
-@item %t
-Insert the string specified by @code{:tag} here, or the @code{princ}
-representation of the value if there is no tag.
-
-@item %%
-Insert a literal @samp{%}. 
-@end table
-
-@item :button-face
-Face used to highlight text inside %[ %] in the format.
-
-@item :doc
-The string inserted by the @samp{%d} escape in the format
-string.  
-
-@item :tag
-The string inserted by the @samp{%t} escape in the format
-string.  
-
-@item :tag-glyph
-Name of image to use instead of the string specified by `:tag' on
-Emacsen that supports it.
-
-@item :help-echo
-Message displayed whenever you move to the widget with either
-@code{widget-forward} or @code{widget-backward}.
-
-@item :indent
-An integer indicating the absolute number of spaces to indent children
-of this widget.
-
-@item :offset
-An integer indicating how many extra spaces to add to the widget's
-grandchildren compared to this widget.
-
-@item :extra-offset
-An integer indicating how many extra spaces to add to the widget's
-children compared to this widget.
-
-@item :notify
-A function called each time the widget or a nested widget is changed.
-The function is called with two or three arguments.  The first argument
-is the widget itself, the second argument is the widget that was
-changed, and the third argument is the event leading to the change, if
-any. 
-
-@item :menu-tag
-Tag used in the menu when the widget is used as an option in a
-@code{menu-choice} widget.
-
-@item :menu-tag-get
-Function used for finding the tag when the widget is used as an option
-in a @code{menu-choice} widget.  By default, the tag used will be either the
-@code{:menu-tag} or @code{:tag} property if present, or the @code{princ}
-representation of the @code{:value} property if not.
-
-@item :match
-Should be a function called with two arguments, the widget and a value,
-and returning non-nil if the widget can represent the specified value.
-
-@item :validate
-A function which takes a widget as an argument, and return nil if the
-widgets current value is valid for the widget.  Otherwise, it should
-return the widget containing the invalid data, and set that widgets
-@code{:error} property to a string explaining the error.
-
-@item :tab-order
-Specify the order in which widgets are traversed with
-@code{widget-forward} or @code{widget-backward}.  This is only partially
-implemented.
-
-@enumerate a
-@item
-Widgets with tabbing order @code{-1} are ignored.
-
-@item 
-(Unimplemented) When on a widget with tabbing order @var{n}, go to the
-next widget in the buffer with tabbing order @var{n+1} or @code{nil},
-whichever comes first.
-
-@item
-When on a widget with no tabbing order specified, go to the next widget
-in the buffer with a positive tabbing order, or @code{nil}
-@end enumerate
-
-@item :parent
-The parent of a nested widget (e.g. a @code{menu-choice} item or an
-element of a @code{editable-list} widget).
-
-@item :sibling-args
-This keyword is only used for members of a @code{radio-button-choice} or
-@code{checklist}.  The value should be a list of extra keyword
-arguments, which will be used when creating the @code{radio-button} or
-@code{checkbox} associated with this item.
-
-@end table
-
-@deffn {User Option} widget-glyph-directory
-Directory where glyphs are found.  
-Widget will look here for a file with the same name as specified for the
-image, with either a @samp{.xpm} (if supported) or @samp{.xbm} extension.
-@end deffn
-
-@deffn{User Option} widget-glyph-enable
-If non-nil, allow glyphs to appear on displayes where they are supported.
-@end deffn
-
-
-@menu
-* link::                        
-* url-link::                    
-* info-link::                   
-* push-button::                 
-* editable-field::              
-* text::                        
-* menu-choice::                 
-* radio-button-choice::         
-* item::                        
-* choice-item::                 
-* toggle::                      
-* checkbox::                    
-* checklist::                   
-* editable-list::               
-@end menu
-
-@node link, url-link, Basic Types, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{link} Widget
-
-Syntax:
-
-@example
-TYPE ::= (link [KEYWORD ARGUMENT]...  [ VALUE ])
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property.  The value should be a string, which will be inserted in the
-buffer. 
-
-@node url-link, info-link, link, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{url-link} Widget
-
-Syntax:
-
-@example
-TYPE ::= (url-link [KEYWORD ARGUMENT]...  URL)
-@end example
-
-When this link is activated, the @sc{www} browser specified by
-@code{browse-url-browser-function} will be called with @var{url}. 
-
-@node info-link, push-button, url-link, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{info-link} Widget
-
-Syntax:
-
-@example
-TYPE ::= (info-link [KEYWORD ARGUMENT]...  ADDRESS)
-@end example
-
-When this link is activated, the build-in info browser is started on
-@var{address}. 
-
-@node  push-button, editable-field, info-link, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{push-button} Widget
-
-Syntax:
-
-@example
-TYPE ::= (push-button [KEYWORD ARGUMENT]...  [ VALUE ])
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property. The value should be a string, which will be inserted in the
-buffer. 
-
-The following extra properties are recognized.
-
-@table @code
-@item :text-format
-The format string used when the push button cannot be displayed
-graphically.  There are two escapes, @code{%s}, which must be present
-exactly once, will be substituted with the tag, and @code{%%} will be
-substituted with a singe @samp{%}.
-@end table
-
-By default the tag will be shown in brackets.
-
-@node editable-field, text, push-button, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{editable-field} Widget
-
-Syntax:
-
-@example
-TYPE ::= (editable-field [KEYWORD ARGUMENT]... [ VALUE ])
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property.  The value should be a string, which will be inserted in
-field.  This widget will match all string values.
-
-The following extra properties are recognized.
-
-@table @code
-@item :size
-The width of the editable field.@*
-By default the field will reach to the end of the line.
-
-@item :value-face
-Face used for highlighting the editable field.  Default is
-@code{widget-field-face}. 
-
-@item :secret
-Character used to display the value.  You can set this to e.g. @code{?*}
-if the field contains a password or other secret information.  By
-default, the value is not secret.
-
-@item :valid-regexp
-By default the @code{:validate} function will match the content of the
-field with the value of this attribute.  The default value is @code{""}
-which matches everything.
-
-@item :keymap
-Keymap used in the editable field.  The default value is
-@code{widget-field-keymap}, which allows you to use all the normal
-editing commands, even if the buffers major mode supress some of them.
-Pressing return activates the function specified by @code{:activate}. 
-
-@item :hide-front-space
-@itemx :hide-rear-space
-In order to keep track of the editable field, emacs places an invisible
-space character in front of the field, and for fixed sized fields also
-in the rear end of the field.  For fields that extent to the end of the
-line, the terminating linefeed serves that purpose instead.  
-
-Emacs will try to make the spaces intangible when it is safe to do so.
-Intangible means that the cursor motion commands will skip over the
-character as if it didn't exist.  This is safe to do when the text
-preceding or following the widget cannot possible change during the
-lifetime of the @code{editable-field} widget.  The preferred way to tell
-Emacs this, is to add text to the @code{:format} property around the
-value.  For example @code{:format "Tag: %v "}.  
-
-You can overwrite the internal safety check by setting the
-@code{:hide-front-space} or @code{:hide-rear-space} properties to
-non-nil.  This is not recommended.  For example, @emph{all} text that
-belongs to a widget (i.e. is created from its @code{:format} string) will
-change whenever the widget changes its value.
-
-@end table
-
-@node text, menu-choice, editable-field, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{text} Widget
-
-This is just like @code{editable-field}, but intended for multiline text
-fields.  The default @code{:keymap} is @code{widget-text-keymap}, which
-does not rebind the return key.
-
-@node menu-choice, radio-button-choice, text, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{menu-choice} Widget
-
-Syntax:
-
-@example
-TYPE ::= (menu-choice [KEYWORD ARGUMENT]... TYPE ... )
-@end example
-
-The @var{type} arguments represents each possible choice.  The widgets
-value of will be the value of the chosen @var{type} argument.  This
-widget will match any value that matches at least one of the specified
-@var{type} arguments.
-
-@table @code
-@item :void 
-Widget type used as a fallback when the value does not match any of the
-specified @var{type} arguments.
-
-@item :case-fold
-Set this to nil if you don't want to ignore case when prompting for a
-choice through the minibuffer.
-
-@item :children
-A list whose car is the widget representing the currently chosen type in
-the buffer. 
-
-@item :choice
-The current chosen type
-
-@item :args 
-The list of types. 
-@end table
-
-@node radio-button-choice, item, menu-choice, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{radio-button-choice} Widget
-
-Syntax:
-
-@example
-TYPE ::= (radio-button-choice [KEYWORD ARGUMENT]...  TYPE ... )
-@end example
-
-The @var{type} arguments represents each possible choice.  The widgets
-value of will be the value of the chosen @var{type} argument.  This
-widget will match any value that matches at least one of the specified
-@var{type} arguments.
-
-The following extra properties are recognized.
-
-@table @code
-@item :entry-format
-This string will be inserted for each entry in the list.
-The following @samp{%} escapes are available:
-@table @samp
-@item %v
-Replaced with the buffer representation of the @var{type} widget.
-@item %b
-Replace with the radio button.
-@item %%
-Insert a literal @samp{%}. 
-@end table
-
-@item button-args
-A list of keywords to pass to the radio buttons.  Useful for setting
-e.g. the @samp{:help-echo} for each button.
-
-@item :buttons
-The widgets representing the radio buttons.
-
-@item :children
-The widgets representing each type.
-
-@item :choice
-The current chosen type
-
-@item :args 
-The list of types. 
-@end table
-
-You can add extra radio button items to a @code{radio-button-choice}
-widget after it has been created with the function
-@code{widget-radio-add-item}. 
-
-@defun widget-radio-add-item widget type
-Add to @code{radio-button-choice} widget @var{widget} a new radio button item of type
-@var{type}. 
-@end defun
-
-Please note that such items added after the @code{radio-button-choice}
-widget has been created will @strong{not} be properly destructed when
-you call @code{widget-delete}.
-
-@node item, choice-item, radio-button-choice, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{item} Widget
-
-Syntax:
-
-@example
-ITEM ::= (item [KEYWORD ARGUMENT]... VALUE)
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property.  The value should be a string, which will be inserted in the
-buffer.  This widget will only match the specified value.
-
-@node choice-item, toggle, item, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{choice-item} Widget
-
-Syntax:
-
-@example
-ITEM ::= (choice-item [KEYWORD ARGUMENT]... VALUE)
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property.  The value should be a string, which will be inserted in the
-buffer as a button.  Activating the button of a @code{choice-item} is
-equivalent to activating the parent widget.  This widget will only match
-the specified value. 
-
-@node toggle, checkbox, choice-item, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{toggle} Widget
-
-Syntax:
-
-@example
-TYPE ::= (toggle [KEYWORD ARGUMENT]...)
-@end example
-
-The widget has two possible states, `on' and `off', which corresponds to
-a @code{t} or @code{nil} value.
-
-The following extra properties are recognized.
-
-@table @code
-@item :on
-String representing the `on' state.  By default the string @samp{on}.
-@item :off 
-String representing the `off' state.  By default the string @samp{off}.
-@item :on-glyph
-Name of a glyph to be used instead of the `:on' text string, on emacsen
-that supports it.
-@item :off-glyph
-Name of a glyph to be used instead of the `:off' text string, on emacsen
-that supports it.
-@end table
-
-@node checkbox, checklist, toggle, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{checkbox} Widget
-
-The widget has two possible states, `selected' and `unselected', which
-corresponds to a @code{t} or @code{nil} value.
-
-Syntax:
-
-@example
-TYPE ::= (checkbox [KEYWORD ARGUMENT]...)
-@end example
-
-@node checklist, editable-list, checkbox, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{checklist} Widget
-
-Syntax:
-
-@example
-TYPE ::= (checklist [KEYWORD ARGUMENT]...  TYPE ... )
-@end example
-
-The @var{type} arguments represents each checklist item.  The widgets
-value of will be a list containing the value of each ticked @var{type}
-argument.  The checklist widget will match a list whose elements all
-matches at least one of the specified @var{type} arguments.
-
-The following extra properties are recognized.
-
-@table @code
-@item :entry-format
-This string will be inserted for each entry in the list.
-The following @samp{%} escapes are available:
-@table @samp
-@item %v
-Replaced with the buffer representation of the @var{type} widget.
-@item %b
-Replace with the checkbox.
-@item %%
-Insert a literal @samp{%}. 
-@end table
-
-@item button-args
-A list of keywords to pass to the checkboxes.  Useful for setting
-e.g. the @samp{:help-echo} for each checkbox.
-
-@item :buttons
-The widgets representing the checkboxes.
-
-@item :children
-The widgets representing each type.
-
-@item :args 
-The list of types. 
-@end table
-
-@node editable-list,  , checklist, Basic Types
-@comment  node-name,  next,  previous,  up
-@subsection The @code{editable-list} Widget
-
-Syntax:
-
-@example
-TYPE ::= (editable-list [KEYWORD ARGUMENT]... TYPE)
-@end example
-
-The value is a list, where each member represent one widget of type
-@var{type}. 
-
-The following extra properties are recognized.
-
-@table @code
-@item :entry-format
-This string will be inserted for each entry in the list.
-The following @samp{%} escapes are available:
-@table @samp
-@item %v
-This will be replaced with the buffer representation of the @var{type}
-widget.
-@item %i
-Insert the @b{[INS]} button.
-@item %d
-Insert the @b{[DEL]} button.
-@item %%
-Insert a literal @samp{%}. 
-@end table
-
-@item :insert-button-args
-A list of keyword arguments to pass to the insert buttons.
-
-@item :delete-button-args
-A list of keyword arguments to pass to the delete buttons.
-
-@item :append-button-args
-A list of keyword arguments to pass to the trailing insert button.
-
-
-@item :buttons
-The widgets representing the insert and delete buttons.
-
-@item :children
-The widgets representing the elements of the list.
-
-@item :args
-List whose car is the type of the list elements.
-
-@end table
-
-@node Sexp Types, Widget Properties, Basic Types, Top
-@comment
-@section Sexp Types
-
-A number of widgets for editing s-expressions (lisp types) are also
-available.  These basically fall in three categories: @dfn{atoms},
-@dfn{composite types}, and @dfn{generic}.
-
-@menu
-* generic::                     
-* atoms::                       
-* composite::                   
-@end menu
-
-@node generic, atoms, Sexp Types, Sexp Types
-@comment  node-name,  next,  previous,  up
-@subsection The Generic Widget.
-
-The @code{const} and @code{sexp} widgets can contain any lisp
-expression.  In the case of the @code{const} widget the user is
-prohibited from editing edit it, which is mainly useful as a component
-of one of the composite widgets.
-
-The syntax for the generic widgets is
-
-@example
-TYPE ::= (const [KEYWORD ARGUMENT]...  [ VALUE ])
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property and can be any s-expression.
-
-@deffn Widget const
-This will display any valid s-expression in an immutable part of the
-buffer. 
-@end deffn
-
-@deffn Widget sexp
-This will allow you to edit any valid s-expression in an editable buffer
-field. 
-
-The @code{sexp} widget takes the same keyword arguments as the
-@code{editable-field} widget.
-@end deffn
-
-@node atoms, composite, generic, Sexp Types
-@comment  node-name,  next,  previous,  up
-@subsection Atomic Sexp Widgets.
-
-The atoms are s-expressions that does not consist of other
-s-expressions.  A string is an atom, while a list is a composite type.
-You can edit the value of an atom with the following widgets.  
-
-The syntax for all the atoms are
-
-@example
-TYPE ::= (NAME [KEYWORD ARGUMENT]...  [ VALUE ])
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property and must be an expression of the same type as the widget.
-I.e. the string widget can only be initialized with a string.
-
-All the atom widgets take the same keyword arguments as the @code{editable-field}
-widget.
-
-@deffn Widget string
-Allows you to edit a string in an editable field.
-@end deffn
-
-@deffn Widget file
-Allows you to edit a file name in an editable field.  You you activate
-the tag button, you can edit the file name in the mini-buffer with
-completion. 
-
-Keywords:
-@table @code
-@item :must-match
-If this is set to non-nil, only existing file names will be allowed in
-the minibuffer.
-@end table
-@end deffn
-
-@deffn Widget directory
-Allows you to edit a directory name in an editable field.
-Similar to the @code{file} widget.
-@end deffn
-
-@deffn Widget symbol
-Allows you to edit a lisp symbol in an editable field.
-@end deffn
-
-@deffn Widget integer
-Allows you to edit an integer in an editable field.
-@end deffn
-
-@deffn Widget number
-Allows you to edit a number in an editable field.
-@end deffn
-
-@deffn Widget boolean
-Allows you to edit a boolean.  In lisp this means a variable which is
-either nil meaning false, or non-nil meaning true.
-@end deffn
-
-
-@node composite,  , atoms, Sexp Types
-@comment  node-name,  next,  previous,  up
-@subsection Composite Sexp Widgets.
-
-The syntax for the composite are
-
-@example
-TYPE ::= (NAME [KEYWORD ARGUMENT]...  COMPONENT...)
-@end example
-
-Where each @var{component} must be a widget type.  Each component widget
-will be displayed in the buffer, and be editable to the user.
-
-@deffn Widget cons
-The value of a @code{cons} widget is a cons-cell where the car is the
-value of the first component and the cdr is the value of the second
-component.  There must be exactly two components. 
-@end deffn
-
-@deffn Widget lisp
-The value of a @code{lisp} widget is a list containing the value of
-each of its component.
-@end deffn
-
-@deffn Widget vector
-The value of a @code{vector} widget is a vector containing the value of
-each of its component.
-@end deffn
-
-The above suffice for specifying fixed size lists and vectors.  To get
-variable length lists and vectors, you can use a @code{choice},
-@code{set} or @code{repeat} widgets together with the @code{:inline}
-keywords.  If any component of a composite widget has the @code{:inline}
-keyword set, its value must be a list which will then be spliced into
-the composite.  For example, to specify a list whose first element must
-be a file name, and whose remaining arguments should either by the
-symbol @code{t} or two files, you can use the following widget
-specification:
-
-@example
-(list file
-      (choice (const t)
-              (list :inline t
-                    :value ("foo" "bar")
-                    string string)))
-@end example
-
-The value of a widget of this type will either have the form 
-@samp{(file t)} or @code{(file string string)}.
-
-This concept of inline is probably hard to understand.  It was certainly
-hard to implement so instead of confuse you more by trying to explain it
-here, I'll just suggest you meditate over it for a while.
-
-@deffn Widget choice
-Allows you to edit a sexp which may have one of fixed set of types.  It
-is currently implemented with the @code{choice-menu} basic widget, and
-has a similar syntax.
-@end deffn
-
-@deffn Widget set
-Allows you to specify a type which must be a list whose elements all
-belong to given set.  The elements of the list is not significant.  This
-is implemented on top of the @code{checklist} basic widget, and has a
-similar syntax. 
-@end deffn
-
-@deffn Widget repeat
-Allows you to specify a variable length list whose members are all of
-the same type.  Implemented on top of the `editable-list' basic widget,
-and has a similar syntax.
-@end deffn
-
-@node Widget Properties, Defining New Widgets, Sexp Types, Top
-@comment  node-name,  next,  previous,  up
-@section Properties
-
-You can examine or set the value of a widget by using the widget object
-that was returned by @code{widget-create}.
-
-@defun widget-value widget
-Return the current value contained in @var{widget}.
-It is an error to call this function on an uninitialized widget.
-@end defun
-
-@defun widget-value-set widget value
-Set the value contained in @var{widget} to @var{value}.
-It is an error to call this function with an invalid @var{value}.
-@end defun
-
-@strong{Important:} You @emph{must} call @code{widget-setup} after
-modifying the value of a widget before the user is allowed to edit the
-widget again.  It is enough to call @code{widget-setup} once if you
-modify multiple widgets.  This is currently only necessary if the widget
-contains an editing field, but may be necessary for other widgets in the
-future. 
-
-If your application needs to associate some information with the widget
-objects, for example a reference to the item being edited, it can be
-done with @code{widget-put} and @code{widget-get}.  The property names
-must begin with a @samp{:}.
-
-@defun widget-put widget property value
-In @var{widget} set @var{property} to @var{value}.
-@var{property} should be a symbol, while @var{value} can be anything.
-@end defun
-
-@defun widget-get widget property
-In @var{widget} return the value for @var{property}.
-@var{property} should be a symbol, the value is what was last set by
-@code{widget-put} for @var{property}.
-@end defun
-
-@defun widget-member widget property
-Non-nil if @var{widget} has a value (even nil) for property @var{property}.
-@end defun
-
-Occasionally it can be useful to know which kind of widget you have,
-i.e. the name of the widget type you gave when the widget was created. 
-
-@defun widget-type widget
-Return the name of @var{widget}, a symbol.
-@end defun
-
-Widgets can be in two states: active, which means they are modifiable by
-the user, or inactive, which means they cannot be modified by the user.
-You can query or set the state with the following code:
-
-@lisp
-;; Examine if @var{widget} is active or not.
-(if (widget-apply @var{widget} :active)
-    (message "Widget is active.")
-  (message "Widget is inactive.")
-
-;; Make @var{widget} inactive.
-(widget-apply @var{widget} :deactivate)
-
-;; Make @var{widget} active.
-(widget-apply @var{widget} :activate)
-@end lisp
-
-A widget is inactive if itself, or any of its ancestors (found by
-following the @code{:parent} link) have been deactivated.  To make sure
-a widget is really active, you must therefore activate both itself, and
-all its ancestors.
-
-@lisp
-(while widget 
-  (widget-apply widget :activate)
-  (setq widget (widget-get widget :parent)))
-@end lisp
-
-You can check if a widget has been made inactive by examining the value
-of @code{:inactive} keyword.  If this is non-nil, the widget itself has
-been deactivated.  This is different from using the @code{:active}
-keyword, in that the later tell you if the widget @strong{or} any of its
-ancestors have been deactivated.   Do not attempt to set the
-@code{:inactive} keyword directly.  Use the @code{:activate}
-@code{:deactivated} keywords instead.
-
-
-@node Defining New Widgets, Widget Wishlist., Widget Properties, Top
-@comment  node-name,  next,  previous,  up
-@section Defining New Widgets
-
-You can define specialized widgets with @code{define-widget}.  It allows
-you to create a shorthand for more complex widgets, including specifying
-component widgets and default new default values for the keyword
-arguments. 
-
-@defun widget-define name class doc &rest args
-Define a new widget type named @var{name} from @code{class}.
-
-@var{name} and class should both be symbols, @code{class} should be one
-of the existing widget types. 
-
-The third argument @var{DOC} is a documentation string for the widget.
-
-After the new widget has been defined, the following two calls will
-create identical widgets:
-
-@itemize @bullet
-@item
-@lisp
-(widget-create @var{name})
-@end lisp
-
-@item
-@lisp
-(apply widget-create @var{class} @var{args})
-@end lisp
-@end itemize
-
-@end defun
-
-Using @code{widget-define} does just store the definition of the widget
-type in the @code{widget-type} property of @var{name}, which is what
-@code{widget-create} uses.
-
-If you just want to specify defaults for keywords with no complex
-conversions, you can use @code{identity} as your conversion function.
-
-The following additional keyword arguments are useful when defining new
-widgets: 
-@table @code
-@item :convert-widget
-Function to convert a widget type before creating a widget of that
-type.  It takes a widget type as an argument, and returns the converted
-widget type.  When a widget is created, this function is called for the
-widget type and all the widgets parent types, most derived first. 
-
-@item :value-to-internal
-Function to convert the value to the internal format.  The function
-takes two arguments, a widget and an external value, and returns the
-internal value.  The function is called on the present @code{:value}
-when the widget is created, and on any value set later with
-@code{widget-value-set}.
-
-@item :value-to-external
-Function to convert the value to the external format.  The function
-takes two arguments, a widget and an internal value, and returns the
-internal value.  The function is called on the present @code{:value}
-when the widget is created, and on any value set later with
-@code{widget-value-set}.
-
-@item :create
-Function to create a widget from scratch.  The function takes one
-argument, a widget type, and create a widget of that type, insert it in
-the buffer, and return a widget object.
-
-@item :delete
-Function to delete a widget.  The function takes one argument, a widget,
-and should remove all traces of the widget from the buffer.
-
-@item :value-create
-Function to expand the @samp{%v} escape in the format string.  It will
-be called with the widget as its argument.  Should
-insert a representation of the widgets value in the buffer.
-
-@item :value-delete
-Should remove the representation of the widgets value from the buffer.
-It will be called with the widget as its argument.  It doesn't have to
-remove the text, but it should release markers and delete nested widgets
-if such has been used.
-
-@item :format-handler
-Function to handle unknown @samp{%} escapes in the format string.  It
-will be called with the widget and the escape character as arguments.
-You can set this to allow your widget to handle non-standard escapes.
-
-You should end up calling @code{widget-default-format-handler} to handle
-unknown escape sequences, which will handle the @samp{%h} and any future
-escape sequences, as well as give an error for unknown escapes.
-@end table
-
-If you want to define a new widget from scratch, use the @code{default}
-widget as its base.
-
-@deffn Widget default [ keyword argument ]
-Widget used as a base for other widgets. 
-
-It provides most of the functionality that is referred to as ``by
-default'' in this text. 
-@end deffn
-
-@node  Widget Wishlist.,  , Defining New Widgets, Top
-@comment  node-name,  next,  previous,  up
-@section Wishlist.
-
-@itemize @bullet
-@item 
-It should be possible to add or remove items from a list with @kbd{C-k}
-and @kbd{C-o} (suggested by @sc{rms}).
-
-@item 
-The @samp{[INS]} and @samp{[DEL]} buttons should be replaced by a single
-dash (@samp{-}).  The dash should be a button that, when activated, ask
-whether you want to add or delete an item (@sc{rms} wanted to git rid of
-the ugly buttons, the dash is my idea).
-
-@item
-Widgets such as @code{file} and @code{symbol} should prompt with completion. 
-
-@item
-The @code{menu-choice} tag should be prettier, something like the abbreviated
-menus in Open Look.
-
-@item
-The functions used in many widgets, like
-@code{widget-item-convert-widget}, should not have names that are
-specific to the first widget where I happended to use them.
-
-@item
-Flag to make @code{widget-move} skip a specified button.
-
-@item
-Document `helper' functions for defining new widgets.
-
-@item
-Activate the item this is below the mouse when the button is
-released, not the item this is below the mouse when the button is
-pressed.  Dired and grep gets this right.  Give feedback if possible.
-
-@item
-Use @samp{@@deffn Widget} to document widgets. 
-
-@item
-Document global keywords in one place.  
-
-Document keywords particular to a specific widget in the widget
-definition.
-
-Document the `default' widget first. 
-
-Split, when needed, keywords into those useful for normal
-customization, those primarily useful when deriving, and those who
-represent runtime information. 
-
-@item
-Figure out terminology and @sc{api} for the class/type/object/super
-stuff. 
-
-Perhaps the correct model is delegation?
-
-@item
-Document @code{widget-browse}.
-
-@item
-Make indentation work with glyphs and propertional fonts.
-
-@item
-Add object and class hierarchies to the browser.
-
-@end itemize
-
-@contents
-@bye
diff --git a/texi/xface/abrahamsen.png b/texi/xface/abrahamsen.png
new file mode 100644 (file)
index 0000000..20a1206
Binary files /dev/null and b/texi/xface/abrahamsen.png differ
diff --git a/texi/xface/aichner.png b/texi/xface/aichner.png
new file mode 100644 (file)
index 0000000..1636565
Binary files /dev/null and b/texi/xface/aichner.png differ
diff --git a/texi/xface/blanks.png b/texi/xface/blanks.png
new file mode 100644 (file)
index 0000000..0776a29
Binary files /dev/null and b/texi/xface/blanks.png differ
diff --git a/texi/xface/cosgriff.png b/texi/xface/cosgriff.png
new file mode 100644 (file)
index 0000000..59acc3f
Binary files /dev/null and b/texi/xface/cosgriff.png differ
diff --git a/texi/xface/drazen.png b/texi/xface/drazen.png
new file mode 100644 (file)
index 0000000..dffeffe
Binary files /dev/null and b/texi/xface/drazen.png differ
diff --git a/texi/xface/gertzfield.png b/texi/xface/gertzfield.png
new file mode 100644 (file)
index 0000000..576789e
Binary files /dev/null and b/texi/xface/gertzfield.png differ
diff --git a/texi/xface/goldberg.png b/texi/xface/goldberg.png
new file mode 100644 (file)
index 0000000..e2fe139
Binary files /dev/null and b/texi/xface/goldberg.png differ
diff --git a/texi/xface/graf.png b/texi/xface/graf.png
new file mode 100644 (file)
index 0000000..d2e19d3
Binary files /dev/null and b/texi/xface/graf.png differ
diff --git a/texi/xface/hardaker.png b/texi/xface/hardaker.png
new file mode 100644 (file)
index 0000000..ac88bd8
Binary files /dev/null and b/texi/xface/hardaker.png differ
diff --git a/texi/xface/hedbor.png b/texi/xface/hedbor.png
new file mode 100644 (file)
index 0000000..5672039
Binary files /dev/null and b/texi/xface/hedbor.png differ
diff --git a/texi/xface/ingrand.png b/texi/xface/ingrand.png
new file mode 100644 (file)
index 0000000..2403259
Binary files /dev/null and b/texi/xface/ingrand.png differ
diff --git a/texi/xface/kaplan.png b/texi/xface/kaplan.png
new file mode 100644 (file)
index 0000000..106bb5e
Binary files /dev/null and b/texi/xface/kaplan.png differ
diff --git a/texi/xface/karlheg.png b/texi/xface/karlheg.png
new file mode 100644 (file)
index 0000000..022eb68
Binary files /dev/null and b/texi/xface/karlheg.png differ
diff --git a/texi/xface/kleinpaste.png b/texi/xface/kleinpaste.png
new file mode 100644 (file)
index 0000000..e25e698
Binary files /dev/null and b/texi/xface/kleinpaste.png differ
diff --git a/texi/xface/kyle.png b/texi/xface/kyle.png
new file mode 100644 (file)
index 0000000..7354ebc
Binary files /dev/null and b/texi/xface/kyle.png differ
diff --git a/texi/xface/love.png b/texi/xface/love.png
new file mode 100644 (file)
index 0000000..cc28c3b
Binary files /dev/null and b/texi/xface/love.png differ
diff --git a/texi/xface/moll.png b/texi/xface/moll.png
new file mode 100644 (file)
index 0000000..b50e97f
Binary files /dev/null and b/texi/xface/moll.png differ
diff --git a/texi/xface/niksic.png b/texi/xface/niksic.png
new file mode 100644 (file)
index 0000000..9e3839a
Binary files /dev/null and b/texi/xface/niksic.png differ
diff --git a/texi/xface/olsen.png b/texi/xface/olsen.png
new file mode 100644 (file)
index 0000000..45df40e
Binary files /dev/null and b/texi/xface/olsen.png differ
diff --git a/texi/xface/patch.png b/texi/xface/patch.png
new file mode 100644 (file)
index 0000000..33af321
Binary files /dev/null and b/texi/xface/patch.png differ
diff --git a/texi/xface/petersen.png b/texi/xface/petersen.png
new file mode 100644 (file)
index 0000000..2a83017
Binary files /dev/null and b/texi/xface/petersen.png differ
diff --git a/texi/xface/pjf.png b/texi/xface/pjf.png
new file mode 100644 (file)
index 0000000..e3d7f09
Binary files /dev/null and b/texi/xface/pjf.png differ
diff --git a/texi/xface/riocreux.png b/texi/xface/riocreux.png
new file mode 100644 (file)
index 0000000..fa4c915
Binary files /dev/null and b/texi/xface/riocreux.png differ
diff --git a/texi/xface/schauer.png b/texi/xface/schauer.png
new file mode 100644 (file)
index 0000000..a776767
Binary files /dev/null and b/texi/xface/schauer.png differ
diff --git a/texi/xface/simmonmt.png b/texi/xface/simmonmt.png
new file mode 100644 (file)
index 0000000..b3df919
Binary files /dev/null and b/texi/xface/simmonmt.png differ
diff --git a/texi/xface/simmons.png b/texi/xface/simmons.png
new file mode 100644 (file)
index 0000000..39e52fd
Binary files /dev/null and b/texi/xface/simmons.png differ
diff --git a/texi/xface/siu.png b/texi/xface/siu.png
new file mode 100644 (file)
index 0000000..d140e31
Binary files /dev/null and b/texi/xface/siu.png differ
diff --git a/texi/xface/smb.png b/texi/xface/smb.png
new file mode 100644 (file)
index 0000000..e890698
Binary files /dev/null and b/texi/xface/smb.png differ
diff --git a/texi/xface/sobek.png b/texi/xface/sobek.png
new file mode 100644 (file)
index 0000000..3c838ef
Binary files /dev/null and b/texi/xface/sobek.png differ
diff --git a/texi/xface/thomas.png b/texi/xface/thomas.png
new file mode 100644 (file)
index 0000000..0c42c8f
Binary files /dev/null and b/texi/xface/thomas.png differ
diff --git a/texi/xface/valdis.png b/texi/xface/valdis.png
new file mode 100644 (file)
index 0000000..715d08d
Binary files /dev/null and b/texi/xface/valdis.png differ
diff --git a/texi/xface/verna1.png b/texi/xface/verna1.png
new file mode 100644 (file)
index 0000000..d84f149
Binary files /dev/null and b/texi/xface/verna1.png differ
diff --git a/texi/xface/verna2.png b/texi/xface/verna2.png
new file mode 100644 (file)
index 0000000..fc2f5e5
Binary files /dev/null and b/texi/xface/verna2.png differ
diff --git a/texi/xface/yamaoka.png b/texi/xface/yamaoka.png
new file mode 100644 (file)
index 0000000..f406744
Binary files /dev/null and b/texi/xface/yamaoka.png differ
diff --git a/todo b/todo
new file mode 100644 (file)
index 0000000..92ff87e
--- /dev/null
+++ b/todo
@@ -0,0 +1,1523 @@
+;; Also know as the "wish list".  Some are done. For the others, no
+;; promise when to be implemented.
+
+* gnus-topic-kill-region
+  From Colin Marquardt <colin.marquardt@usa.alcatel.com>
+  
+  I noticed that when re-arranging topics, C-k yanks a topic just fine
+  (runs gnus-topic-kill-group).
+
+  However, my habit is to do marking and the yanking the region, so I
+  would run C-w on the marked topic. But C-w runs
+  gnus-group-kill-region and doesn't yank the topic (for groups it
+  works fine).
+
+  So could we have a gnus-topic-kill-region, or a
+  gnus-group-kill-region which handles topics as well?
+
+* Speed up sorting in summary buffer if there is a limit.
+  
+  Suggested by Daniel Ortmann <ortmann@isl.net>.
+
+* Investigate the memory usage of Gnus. 
+
+  But it does seem strange that Gnus would use some 15meg for this.  I
+  think that is worth investigating.  I suspect that bugs or bad
+  design are causing waste; they could be in Gnus, or in Emacs. -- RMS
+
+* Google group digest
+  
+  The result of Google group search return a thread. Is it a digest
+  format?
+
+* NOV caching.
+  
+  Implement NOV caching with Gnus Agent.
+
+* Multiple charsets for topic names.
+  
+  [Done]
+
+* Allow specification of server in Newsgroups header
+  
+  [Kai wrote]
+
+  WIBNI I could put `Newsgroups: nntp+quimby:bla' into a message and
+  Gnus would know to post this message on my server `nntp:quimby' into
+  the group bla?  I think this would be way cool.
+
+  But Gnus would have to rewrite the Newsgroups header before actually
+  sending the posting.
+
+  Thanks for Micha Wiedenmann for this suggestion.
+
+* Understand mail-user-agent. Maybe gnus-mail-user-agent.
+  
+  [Done]
+
+* Emphasis delimiters show when `W W c'.
+
+  [Fixed]
+
+* Parsing of the common list confirmation requests so that Gnus can
+   prepare the response with a single command.  Including LISTSERV
+   periodic ping messages and the like.
+
+* Parsing of the various List-* headers to enable automatic commands
+   like "send help message," "send unsubscribe message," and the like.
+
+   [done, see gnus-ml.el]
+
+* Parsing of the subscription notice to stash away details like what
+   address you're subscribed to the list under (and automatically send
+   mail to the list using that address, when you send mail inside the list
+   group), what address to mail to unsubscribe, and the list info message
+   if available.  Hitting the "get FAQ" command inside a mailing list
+   group should display that stashed copy of the info message.
+
+* Some help in coming up with good split rules for mailing lists, as
+   automated as possible.  Splitting on To and Cc is almost always not
+   what I want, since it can misfile messages and since if I'm cc'd on
+   list mail I want to get both copies, one in my personal mailbox and one
+   in the list mailbox.  I know other people handle it other ways, but I
+   prefer it that way.  Accordingly, some way to semi-automatically
+   generate split rules based on Sender, Mailing-List, Return-Path,
+   X-Loop, and all of the other random headers that often work would be
+   very cool.
+
+* Support for zipped folders for all backends this makes sense for.
+  Most likely using jka-compr. (It has been suggested that this do
+  work but I think it should be verified for all backends.)
+
+* Support for RFC2015, PGP-MIME. Probably has to involve the people in
+  the Mailcrypt project.
+
+  [done]
+
+* Agent (Can someone write some subtopics here? I don't use it myself
+  so I don't know what is lacking.)
+
+* Support for encrypted folders. Even if the mail arrives unencrypted
+  Gnus should be able to encrypt the *folder* for added safety. This
+  should go for both Gnus' own folders and the folders Gnus reads from
+  (e.g. /var/spool/mail/${USER}). All backends this makes sense for.
+
+  [John Wiegley's article <200011030445.VAA08277@localhost.dynodns.net>,
+   posted on gnu.emacs.gnus does this.
+   Also, gnus-article-encrypt `K E' encrypts the article body.]
+
+* The stuff on "Newest Features" in the manual should be implemented
+  and the node updated (it maybe is?).
+
+* Splitting .newsrc.eld so the history is in one file and the
+  configuration is in another. To help those that reads at two
+  locations (e.g. work and home) and want to have the same
+  configuration.
+
+* gnus-uu-decode should complain if one or more parts of a series post
+  (ie, "part N of X") is missing, and optionally tick what parts are
+  there for decoding in a later session.
+
+* Additional article marking, and an ability to affect marks placed
+  during e.g. mail acquisition.  I want to be able to notice the
+  subject "fast money" or "web traffic", automatically mark it with a
+  `$', and score it into oblivion.  (But I fear that wanting to change
+  marks with mail-source-* and nnmail-* functions will represent a
+  philosophical conflict with the rest of Gnus' management of article
+  marks.  mail-source-* and nnmail-* currently hack around with files
+  under ~/Mail and leave traces in ~/Mail/active, but don't affect
+  things stored in .newsrc.eld.)
+
+* A much better interface to nnmail-split-methods.  I don't know how
+  I'd like this done, but I know that the current method of manually
+  hacking regexps is pretty untenable for new users.  My boss, who is
+  tenured faculty at CMU and CEO & CTO at JPRC, and whose research
+  work has involved Lisp for the last 25 years, is trying to implant
+  himself in a Gnus mail environment, and this is a big sticking point
+  even for him.
+
+* PGP-supported encryption of entire nnml & nnmh groups.  There are
+  people with whom I exchange mail routinely who don't send w/PGP, but
+  I'd really rather that the content not be left lying around
+  unencrypted.  Hook into article acquisition the way jka-compr
+  supposedly does, to auto-decrypt every message read.
+
+  [See Support for encrypted folders.]
+
+* Baby's First Mail In Gnus.  Some set of functions that the
+  new-to-mail-in-Gnus user can invoke which will query the user
+  appropriately for the basic information required to establish mail
+  handling, leaving the appropriate traces in .gnus.  Perhaps a
+  customize buffer would be appropriate.
+  - Where does your mail come from?
+  - If some server, what is your POP/IMAP protocol identity?
+  - What is your identity when sending mail, as opposed to posting to
+    Usenet?
+  - Here are some basic concepts of mail groups (list a few:
+    personal mail, company-wide mail, mailing lists, garbage dumps,
+    receptacles for outbound copies of what one sends; which ones do
+    you want to instantiate, and what mail should land in each?
+    [/viz./ problem of nnmail-split-methods interface.]
+
+* Full integration of nnir into Gnus.  Generic hooks for adding new
+  external nnir sources.  I use a couple experimental, in-house tools
+  (JPRC is a research lab, occupied with document analysis and machine
+  learning) and adding new search engines to nnir by hacking the main
+  nnir.el module is rather clunky.
+
+* Manual ordering of articles in an nnml folder.
+
+  That is, keystrokes to move articles (or whole threads) up or down
+  in the *Summary* buffer relative to the other articles.  The order
+  would be persistent (e.g., across gnus sessions).
+
+  With this ability, an nnml folder would make for a good to-do list.
+
+* Since many uses Gnus to store to do lists I think it is time for an
+  nntodo. (I know Kai already written one, maybe use that for a start?)
+
+* nnsql backend, which would allow messages or folders to be imported
+  in a local (My|Postgre|?)SQL RDBMS.
+
+* "posting profiles" ideally accessible from a popup menu; allowing
+  choice between predefined profiles of
+  from,name,organization,etc. Example: I'm at home, but need to reply
+  to a work mail; i can hit 'R', then use this command to switch to my
+  'work' profile for purposes of this one reply. (This might already
+  be possible with current Gnus, but I don't think so.)
+
+* Better handling of the mail retrieving / splitting feature:
+  - the variables <backend>-get-new-mail should not exist anymore. Mail
+    retrieving should be a separate matter.
+  - we should be able to split mails to groups AND backends at the same time.
+  - meanwhile, we should still be able to associate certain mail sources with
+    certain backends.
+
+* A better interface to the agent download scoring rules, like the one
+  for the other scoring rules.
+
+* Editing of messages in the agents cache.
+
+* More article marks (like '!' or '?').
+  Maybe user defined marks that can be displayed as any choosen charakter,
+  so one could do things like limiting on, to do whatever one likes with
+  these articles.
+
+* A possibility to add notes to messages. If thouse could include links
+  to other (stored) messages this would be very practical.
+
+* A nnfolder like backend with .overview files.
+  This would not only speed up things, but also allow nnir to work on it.
+
+  [done]
+
+* Allow article editing in groups which do not support it, but
+  emulating it via deleting the old article and entering the new one
+  into the group.  This would be very useful to support `T ^' (say) in
+  nnimap groups.
+
+* Allow user to specify which kinds of groups should be displayed.
+  For example, I want to display all the groups that are displayed
+  now, plus those which have cached messages in them.  (Gnus does
+  display those with ticked messages but not those with
+  cached-but-unticked ones.)  This would become even more important
+  when we allow labels.
+
+* Go through the todo list and remove items already done.
+
+* Create new data type `article identifier' and use that instead of
+  article numbers.  A first implementation could offer something like
+  (num . 4711) but this could be extended.  This would be useful for
+  using servers with *really* large numbers -- there we could have a
+  bignum type.  It might also be useful for the nnweb and nnultimate
+  thingies where article identifiers are not really numbers.
+
+* Allow use of digests to keep related articles.  Normally, you use
+  groups to group together articles which are thematically related.
+  But sometimes, you have so many themes that this becomes
+  impractical.  WIBNI I could have digests in a group, and there was a
+  way to add a new article to one of the digests in that group?
+
+  Or maybe what I really want is a way to tell Gnus that a specific
+  thread should always be hidden (as in `T h') by default, while most
+  other threads are not hidden by default.  Hm.
+
+* New backend between nnfolder and nnml: have more than one article
+  per file, but more than one file per group.  With .overview files.
+
+  [done. nnfolder has .overview.  Backward- and forward-compatible
+   between 1.0 and 2.0. (setq nnfolder-nov-is-evil t) disables the
+   feature]
+
+* .overview files for nnfolder?
+  
+  [done]
+
+* New backend nnbabylfolder.  There is also nnbabyl which is like
+  nnmbox but uses babyl format, but there is no babyl format
+  equivalent of nnfolder.
+
+* Make movement commands in summary buffer independent of `move after
+  mark' behavior when marking articles.  Currently, if you don't want
+  `E' to move to the next unread article, you have to set
+  gnus-summary-goto-unread to nil, and then there is no way to move to
+  the next or previous unread article.
+
+  This one has two sub-tasks.  Providing the commands is one thing,
+  finding out useful key bindings for them is another.  I think we
+  could provide the commands first while not changing the behavior of
+  the key bindings; then different people can experiment with
+  different key binding schemes until we find something which suits
+  many people.
+
+* `Move to next/previous/first article' is a misnomer, since ticked
+  articles are also unread but not moved to by these commands.  Should
+  the terminology be fixed or the documentation, or what?
+
+* Allow sorting of threads by newest article rather than by root of
+  thread.  Consider the following thread structure:
+
+    root1       Jan 1
+      leaf1     Jan 4
+    root2       Jan 2
+      leaf2     Jan 3
+
+  These two threads are sorted this way because root1 is older than
+  root2.  I want an option to sort them the other way round because
+  leaf1 is newer than leaf2.
+
+* Improve editing of MIME messages.  I would like to use html-mode to
+  edit the body of a text/html message, and enriched-mode for
+  text/enriched messages, and so on.  This should go for multipart
+  messages as well.  This is probably a hard one since Emacs currently
+  does not allow several major modes per buffer.  But maybe it would
+  be nice to hack Emacs to provide this infrastructure so that Gnus
+  can make use of it?  This would also make it possible to provide
+  nifty commands for editing the headers, for example, rather than
+  relying on commands which do the same thing everywhere.
+  message-x.el is really just a half-assed attempt at doing it, and
+  while it is useful, that's not the way it should be done.
+
+  I think Francisco Potort\e,Al\e(B already did something like this?
+
+* Provide commands for editing MML tags.  For example, there could be
+  a command mml-add-tag-attribute which prompts me for an attribute
+  name (with completion, from the set filename, type, ...), and then
+  for a value.  (This is like `C-c +' in psgml.)  Or there could be a
+  command which showed me all the attributes in an MML tag and allows
+  me to use TAB to move between them, and then to edit each attribute
+  value.  (This is like `C-c C-a' in psgml.)
+
+* Have Gnus automagically set group parameters for mailing list
+  groups.  For example, if I have a splitting rule that automatically
+  sorts ding@gnus.org into mail.ding, then Gnus should clue in, set
+  the to-list parameter to 'ding@gnus.org', and set total-expire.
+  (This is probably Hard (TM).  And of course the user should be able
+  to configure what parameters exactly get set.)
+
+* Along the same lines, automagically detect broken reply-to's.  (But
+  don't auto-detect users legitimately setting a reply-to header that
+  points back to the list.)
+
+* Make it easier to change parameters on a set of groups,
+  e.g. set/clear gcc-self on process-marked groups.
+
+* Make it easier/possible to migrate between primary select-methods,
+  if that concept is going to be kept.  Right now I have only one
+  group on my primary server, and I'd kind of like to change from nntp
+  to nnml, but apparently this doesn't work well.
+
+* Make it possible to refer to uniquely-named groups without
+  select-method prefix (e.g. mail.misc instead of nnml:mail.misc).
+
+* Allow a user-defined picons directory for personal groups.
+
+* Annotations as discussed last autumn. Be able to make comments to
+  articles for all bakends. The comments amybe should go into a
+  seperate "backend", like nndraft.
+
+* Catchup on a topic and all its subtopics. I.e. do "c y" when on a
+  topic line in *Group*.
+
+* Better/more advanced subject washing in *Summary*, see my
+  js-gnus-simplify-subject-function I posted earlier this winter.
+
+;; From Newest Features node. Some are not done.
+
+* I would like the zombie-page to contain an URL to the source of the
+latest version of gnus or some explanation on where to find it.
+
+*  A way to continue editing the latest Message composition.
+
+*  http://www.sonicnet.com/feature/ari3/
+
+   [N/A]
+
+*  facep is not declared.
+
+* Include a section in the manual on why the number of articles isn't
+the same in the group buffer and on the SPC prompt.
+
+*  Interacting with rmail fcc isn't easy.
+
+*       Hypermail:
+      [N/A]<URL:http://www.falch.no/people/pepper/DSSSL-Lite/archives/>
+      [N/A]<URL:http://www.eit.com/software/hypermail/hypermail.html>
+      [N/A]<URL:http://homer.ncm.com/>
+      [N/A]<URL:http://www.yahoo.com/Computers_and_Internet/Internet/World_Wide_Web/HTML_Converters/>
+      http://www.uwsg.indiana.edu/hypermail/linux/kernel/9610/index.html
+      [N/A]<URL:http://union.ncsa.uiuc.edu/HyperNews/get/www/html/converters.html>
+      [N/A]http://www.miranova.com/gnus-list/
+
+   [w3 or nnwarchive?]
+
+* `^-- ' is made into - in LaTeX.
+
+*  gnus-kill is much slower than it was in GNUS 4.1.3.
+
+*  when expunging articles on low score, the sparse nodes keep
+ hanging on?
+
+*  starting the first time seems to hang Gnus on some systems.  Does
+ NEWGROUPS answer too fast?
+
+*  nndir doesn't read gzipped files.
+
+*  FAQ doesn't have an up node?
+
+*  when moving mail from a procmail spool to the crash-box, the
+ crash-box is only appropriate to one specific group.
+
+*  `t' `t' makes X-Faces disappear.
+
+*  nnmh-be-safe means that crossposted articles will be marked as
+ unread.
+
+*  Orphan score entries don't show on "V t" score trace
+
+*  when clearing out data, the cache data should also be reset.
+
+* rewrite gnus-summary-limit-children to be non-recursive to avoid
+exceeding lisp nesting on huge groups.
+
+*  expunged articles are counted when computing scores.
+
+*  implement gnus-batch-brew-soup
+
+*  ticked articles aren't easy to read in pick mode - `n' and stuff
+ just skips past them.  Read articles are the same.
+
+*  topics that contain just groups with ticked articles aren't
+ displayed.
+
+*  nndoc should always allocate unique Message-IDs.
+
+*  If there are mail groups the first time you use Gnus, Gnus'll
+ make the mail groups killed.
+
+*  no "no news is good news" when using topics.
+
+*  when doing crosspost marking, the cache has to be consulted and
+ articles have to be removed.
+
+*  nnweb should fetch complete articles when they are split into
+ several parts.
+
+*  scoring on head immediate doesn't work.
+
+*  finding short score file names takes forever.
+
+*  canceling articles in foreign groups.
+
+*  nntp-open-rlogin no longer works.
+
+*  C-u C-x C-s (Summary) switches to the group buffer.
+
+*  move nnmail-split-history out to the backends.
+
+*  nnweb doesn't work properly.
+
+*  using a virtual server name as `gnus-select-method' doesn't work?
+
+*  when killing/yanking a group from one topic to another in a
+ slave, the master will yank it first to one topic and then add it
+ to another.  Perhaps.
+
+*  warn user about `=' redirection of a group in the active file?
+
+*  take over the XEmacs menubar and offer a toggle between the XEmacs
+ bar and the Gnus bar.
+
+*       push active file and NOV file parsing down into C code.
+      `(canonize-message-id id)'
+      `(mail-parent-message-id references n)'
+      `(parse-news-nov-line &optional dependency-hashtb)'
+      `(parse-news-nov-region beg end &optional dependency-hashtb fullp)'
+      `(parse-news-active-region beg end hashtb)'
+
+*  nnml .overview directory with splits.
+
+*  asynchronous cache
+
+*  postponed commands.
+
+*  the selected article show have its Subject displayed in its
+ summary line.
+
+*  when entering groups, get the real number of unread articles from
+ the server?
+
+*  sort after gathering threads - make false roots have the headers
+ of the oldest orphan with a 0 article number?
+
+*  nndoc groups should inherit the score files of their parents?
+ Also inherit copy prompts and save files.
+
+*  command to start up Gnus (if not running) and enter a mail mode
+ buffer.
+
+*  allow editing the group description from the group buffer for
+ backends that support that.
+
+* gnus-hide,show-all-topics
+
+*  groups and sub-topics should be allowed to mingle inside each
+ topic, and not just list all subtopics at the end.
+
+*  a command to remove all read articles that are not needed to
+ connect threads - `gnus-summary-limit-to-sparse-unread'?
+
+*  a variable to turn off limiting/cutting of threads in the tree
+ buffer.
+
+*  a variable to limit how many files are uudecoded.
+
+*  add zombie groups to a special "New Groups" topic.
+
+*  server mode command: close/open all connections
+
+*  put a file date in gnus-score-alist and check whether the file
+ has been changed before using it.
+
+*  on exit from a digest group, go to the next article in the parent
+ group.
+
+*  hide (sub)threads with low score.
+
+*  when expiring, remove all marks from expired articles.
+
+*  gnus-summary-limit-to-body
+
+*  a regexp alist that says what level groups are to be subscribed
+ on.  Eg. - `(("nnml:" . 1))'.
+
+*  easier interface to nnkiboze to create ephemeral groups that
+ contain groups that match a regexp.
+
+*  allow newlines in <URL:> urls, but remove them before using the
+ URL.
+
+*  If there is no From line, the mail backends should fudge one from
+ the "From " line.
+
+*  fuzzy simplifying should strip all non-alpha-numerical info from
+ subject lines.
+
+*  gnus-soup-brew-soup-with-high-scores.
+
+*  nntp-ping-before-connect
+
+*  command to check whether NOV is evil.  "list overview.fmt".
+
+*  when entering a group, Gnus should look through the score files
+ very early for `local' atoms and set those local variables.
+
+*  message annotations.
+
+*  topics are always yanked before groups, and that's not good.
+
+*  (set-extent-property extent 'help-echo "String to display in
+ minibuf") to display help in the minibuffer on buttons under
+ XEmacs.
+
+*  allow group line format spec to say how many articles there are
+ in the cache.
+
+*  AUTHINFO GENERIC
+
+*  `run-with-idle-timer' in gnus-demon.
+
+*  stop using invisible text properties and start using overlays
+ instead
+
+*  C-c C-f C-e to add an Expires header.
+
+*  go from one group to the next; everything is expunged; go to the
+ next group instead of going to the group buffer.
+
+*  gnus-renumber-cache - to renumber the cache using "low" numbers.
+
+*  record topic changes in the dribble buffer.
+
+*  `nnfolder-generate-active-file' should look at the folders it
+ finds and generate proper active ranges.
+
+*  nneething-look-in-files-for-article-heads variable to control
+ whether nneething should sniff all files in the directories.
+
+*  gnus-fetch-article - start Gnus, enter group, display article
+
+*  gnus-dont-move-articles-to-same-group variable when respooling.
+
+*  when messages are crossposted between several auto-expirable
+ groups, articles aren't properly marked as expirable.
+
+*  nneething should allow deletion/moving.
+
+*  TAB on the last button should go to the first button.
+
+*  if the car of an element in `mail-split-methods' is a function,
+ and the function returns non-nil, use that as the name of the
+ group(s) to save mail in.
+
+*  command for listing all score files that have been applied.
+
+*  a command in the article buffer to return to `summary' config.
+
+*  `gnus-always-post-using-current-server' - variable to override
+ `C-c C-c' when posting.
+
+*  nnmail-group-spool-alist - says where each group should use as a
+ spool file.
+
+*  when an article is crossposted to an auto-expirable group, the
+ article should be marker as expirable.
+
+*  article mode command/menu for "send region as URL to browser".
+
+*  on errors, jump to info nodes that explain the error.  For
+ instance, on invalid From headers, or on error messages from the
+ nntp server.
+
+*  when gathering threads, make the article that has no "Re: " the
+ parent.  Also consult Date headers.
+
+*  a token in splits to call shrink-window-if-larger-than-buffer
+
+*  `1 0 A M' to do matches on the active hashtb.
+
+*  duplicates - command to remove Gnus-Warning header, use the read
+ Message-ID, delete the "original".
+
+*  when replying to several messages at once, put the "other"
+ message-ids into a See-Also header.
+
+*  support setext: URL:http://www.bsdi.com/setext/
+
+*  support ProleText:
+ <URL:http://proletext.clari.net/prole/proletext.html>
+
+*  when browsing a foreign server, the groups that are already
+ subscribed should be listed as such and not as "K".
+
+ [done]
+
+*  generate font names dynamically.
+
+*  score file mode auto-alist.
+
+*  allow nndoc to change/add/delete things from documents.  Implement
+ methods for each format for adding an article to the document.
+
+*  `gnus-fetch-old-headers' `all' value to incorporate absolutely
+ all headers there is.
+
+*  function like `|', but concatenate all marked articles and pipe
+ them to the process.
+
+*  cache the list of killed (or active) groups in a separate file.
+ Update the file whenever we read the active file or the list of
+ killed groups in the .eld file reaches a certain length.
+
+*  function for starting to edit a file to put into the current mail
+ group.
+
+*  score-find-trace should display the total score of the article.
+
+*  "ghettozie" - score on Xref header and nix it out after using it
+ to avoid marking as read in other groups it has been crossposted
+ to.
+
+*  look at procmail splitting.  The backends should create the
+ groups automatically if a spool file exists for that group.
+
+*  function for backends to register themselves with Gnus.
+
+*  when replying to several process-marked articles, have all the
+ From end up in Cc headers?  Variable to toggle.
+
+*  command to delete a crossposted mail article from all groups it
+ has been mailed to.
+
+*  `B c' and `B m' should be crosspost aware.
+
+*  hide-pgp should also hide PGP public key blocks.
+
+*  Command in the group buffer to respool process-marked groups.
+
+*  `gnus-summary-find-matching' should accept pseudo-"headers" like
+ "body", "head" and "all"
+
+*  When buttifying <URL: > things, all white space (including
+ newlines) should be ignored.
+
+*  Process-marking all groups in a topic should process-mark groups
+ in subtopics as well.
+
+*  Add non-native groups to the list of killed groups when killing
+ them.
+
+*  nntp-suggest-kewl-config to probe the nntp server and suggest
+ variable settings.
+
+*  add edit and forward secondary marks.
+
+*  nnml shouldn't visit its .overview files.
+
+*  allow customizing sorting within gathered threads.
+
+*  `B q' shouldn't select the current article.
+
+*  nnmbox should support a newsgroups file for descriptions.
+
+*  allow fetching mail from several pop servers.
+
+  [done]
+
+*  Be able to specify whether the saving commands save the original
+ or the formatted article.
+
+*  a command to reparent with the child process-marked (cf. `T ^'.).
+
+*  I think the possibility to send a password with nntp-open-rlogin
+ should be a feature in Red Gnus.
+
+*  The `Z n' command should be possible to execute from a mouse
+ click.
+
+*  more limiting functions - date, etc.
+
+*  be able to limit on a random header; on body; using reverse
+ matches.
+
+*  a group parameter (`absofucking-total-expiry') that will make
+ Gnus expire even unread articles.
+
+*  a command to print the article buffer as postscript.
+
+*  variable to disable password fetching when opening by
+ nntp-open-telnet.
+
+*  manual: more example servers - nntp with rlogin, telnet
+
+*  checking for bogus groups should clean topic alists as well.
+
+*  canceling articles in foreign groups.
+
+*  article number in folded topics isn't properly updated by Xref
+ handling.
+
+*  Movement in the group buffer to the next unread group should go
+ to the next closed topic with unread messages if no group can be
+ found.
+
+*  Extensive info pages generated on the fly with help everywhere -
+ in the "*Gnus edit*" buffers, for instance.
+
+*  Topic movement commands - like thread movement.  Up, down,
+ forward, next.
+
+*  a way to tick/mark as read Gcc'd articles.
+
+   [done, (setq gnus-inews-mark-gcc-as-read t)]
+
+*  a way to say that all groups within a specific topic comes from a
+ particular server?  Hm.
+
+*  `gnus-article-fill-if-long-lines' - a function to fill the
+ article buffer if there are any looong lines there.
+
+*  `T h' should jump to the parent topic and fold it.
+
+*  a command to create an ephemeral nndoc group out of a file, and
+ then splitting it/moving it to some other group/backend.
+
+*  a group parameter for nnkiboze groups that says that all kibozed
+ articles should be entered into the cache.
+
+*  It should also probably be possible to delimit what
+ `gnus-jog-cache' does - for instance, work on just some groups, or
+ on some levels, and entering just articles that have a score
+ higher than a certain number.
+
+*  nnfolder should append to the folder instead of re-writing the
+ entire folder to disk when accepting new messages.
+
+*  allow all backends to do the proper thing with .gz files.
+
+*  a backend for reading collections of babyl files nnbabylfolder?
+
+*  a command for making the native groups into foreign groups.
+
+*  server mode command for clearing read marks from all groups from
+ a server.
+
+*  when following up multiple articles, include all To, Cc, etc
+ headers from all articles.
+
+*  a command for deciding what the total score of the current thread
+ is.  Also a way to highlight based on this.
+
+*  command to show and edit group scores
+
+*  a gnus-tree-minimize-horizontal to minimize tree buffers
+ horizontally.
+
+*  command to generate nnml overview file for one group.
+
+*  `C-u C-u a' - prompt for many crossposted groups.
+
+*  keep track of which mail groups have received new articles (in
+ this session).  Be able to generate a report and perhaps do some
+ marking in the group buffer.
+
+*  gnus-build-sparse-threads to a number - build only sparse threads
+ that are of that length.
+
+*  have nnmh respect mh's unseen sequence in .mh_profile.
+
+*  cache the newsgroups descriptions locally.
+
+*  asynchronous posting under nntp.
+
+*  be able to control word adaptive scoring from the score files.
+
+*  a variable to make `C-c C-c' post using the "current" select
+ method.
+
+*  `limit-exclude-low-scored-articles'.
+
+*  if `gnus-summary-show-thread' is a number, hide threads that have
+ a score lower than this number.
+
+*  split newsgroup subscription variable up into "order" and
+ "method".
+
+*  buttonize ange-ftp file names.
+
+*  a command to make a duplicate copy of the current article so that
+ each copy can be edited separately.
+
+*  nnweb should allow fetching from the local nntp server.
+
+*  record the sorting done in the summary buffer so that it can be
+ repeated when limiting/regenerating the buffer.
+
+*  nnml-generate-nov-databses should generate for all nnml servers.
+
+*  when the user does commands in the group buffer, check the
+ modification time of the .newsrc.eld file and use
+ ask-user-about-supersession-threat.  Also warn when trying to save
+ .newsrc.eld and it has changed.
+
+*  M-g on a topic will display all groups with 0 articles in the
+ topic.
+
+*  command to remove all topic stuff.
+
+*  allow exploding incoming digests when reading incoming mail and
+ splitting the resulting digests.
+
+*  nnsoup shouldn't set the `message-' variables.
+
+*  command to nix out all nnoo state information.
+
+*  nnmail-process-alist that calls functions if group names matches
+ an alist - before saving.
+
+*  use buffer-invisibility-spec everywhere for hiding text.
+
+*  variable to activate each group before entering them to get the
+ (new) number of articles.  `gnus-activate-before-entering'.
+
+*  command to fetch a Message-ID from any buffer, even starting Gnus
+ first if necessary.
+
+*  when posting and checking whether a group exists or not, just ask
+ the nntp server instead of relying on the active hashtb.
+
+*  buttonize the output of `C-c C-a' in an apropos-like way.
+
+*  `G p' should understand process/prefix, and allow editing of
+ several groups at once.
+
+*  command to create an ephemeral nnvirtual group that matches some
+ regexp(s).
+
+*  nndoc should understand "Content-Type: message/rfc822" forwarded
+ messages.
+
+ [done]
+
+*  it should be possible to score "thread" on the From header.
+
+*  hitting RET on a "gnus-uu-archive" pseudo article should unpack
+ it.
+
+*  `B i' should display the article at once in the summary buffer.
+
+*  remove the "*" mark at once when unticking an article.
+
+*  `M-s' should highlight the matching text.
+
+*  when checking for duplicated mails, use Resent-Message-ID if
+ present.
+
+*  killing and yanking groups in topics should be better.  If
+ killing one copy of a group that exists in multiple topics, only
+ that copy should be removed.  Yanking should insert the copy, and
+ yanking topics should be possible to be interspersed with the
+ other yankings.
+
+*  command for enter a group just to read the cached articles.  A
+ way to say "ignore the nntp connection; just read from the cache."
+
+*  `X u' should decode base64 articles.
+
+   [`X m' does so.]
+
+*  a way to hide all "inner" cited text, leaving just the most
+ recently cited text.
+
+*  nnvirtual should be asynchronous.
+
+*  after editing an article, gnus-original-article-buffer should be
+ invalidated.
+
+*  there should probably be a way to make Gnus not connect to the
+ server and just read the articles in the server
+
+*  allow a `set-default' (or something) to change the default value
+ of nnoo variables.
+
+*  a command to import group infos from a .newsrc.eld file.
+
+*  groups from secondary servers have the entire select method
+ listed in each group info.
+
+*  a command for just switching from the summary buffer to the group
+ buffer.
+
+*  a way to specify that some incoming mail washing functions should
+ only be applied to some groups.
+
+*  Message `C-f C-t' should ask the user whether to heed
+ mail-copies-to: never.
+
+*  new group parameter - `post-to-server' that says to post using
+ the current server.  Also a variable to do the same.
+
+*  the slave dribble files should auto-save to the slave file names.
+
+*  a group parameter that says what articles to display on group
+ entry, based on article marks.
+
+*  a way to visually distinguish slave Gnusae from masters.  (Whip
+ instead of normal logo?)
+
+*  Use DJ Bernstein "From " quoting/dequoting, where applicable.
+
+*  Why is hide-citation-maybe and hide-citation different?  Also
+ clear up info.
+
+*  group user-defined meta-parameters.
+
+ From: John Griffith <griffith@sfs.nphil.uni-tuebingen.de>
+
+*  I like the option for trying to retrieve the FAQ for a group and
+ I was thinking it would be great if for those newsgroups that had
+ archives you could also try to read the archive for that group.
+ Part of the problem is that archives are spread all over the net,
+ unlike FAQs.  What would be best I suppose is to find the one
+ closest to your site.
+
+ In any case, there is a list of general news group archives at
+ ftp://ftp.neosoft.com/pub/users/claird/news.lists/newsgroup_archives.html
+
+*      From: Jason L Tibbitts III <tibbs@hpc.uh.edu>
+      (add-hook 'gnus-select-group-hook
+       (lambda ()
+         (gnus-group-add-parameter group
+            (cons 'gnus-group-date-last-entered (list (current-time-string))))))
+
+      (defun gnus-user-format-function-d (headers)
+       "Return the date the group was last read."
+       (cond ((car (gnus-group-get-parameter gnus-tmp-group 'gnus-group-date-last-entered)))
+           (t "")))
+
+*  tanken var at n\e,Ae\e(Br du bruker `gnus-startup-file' som prefix (FOO)
+ til \e,Ae\e(B lete opp en fil FOO-SERVER, FOO-SERVER.el, FOO-SERVER.eld,
+ kan du la den v\e,Af\e(Bre en liste hvor du bruker hvert element i listen
+ som FOO, istedet.  da kunne man hatt forskjellige serveres
+ startup-filer forskjellige steder.
+
+* LMI> Well, nnbabyl could alter the group info to heed labels like
+ LMI> answered and read, I guess.
+
+ It could also keep them updated (the same for the Status: header of
+ unix mbox files).
+
+ They could be used like this:
+
+      `M l <name> RET' add label <name> to current message.
+      `M u <name> RET' remove label <name> from current message.
+      `/ l <expr> RET' limit summary buffer according to <expr>.
+
+      <expr> would be a boolean expression on the labels, e.g.
+
+      `/ l bug & !fixed RET'
+
+ would show all the messages which are labeled `bug' but not labeled
+ `fixed'.
+
+ One could also imagine the labels being used for highlighting, or
+ affect the summary line format.
+
+* Sender: abraham@dina.kvl.dk
+
+ I'd like a gnus-find-file which work like find file, except that it
+ would recognize things that looks like messages or folders:
+
+ - If it is a directory containing numbered files, create an nndir
+ summary buffer.
+
+ - For other directories, create a nneething summary buffer.
+
+ - For files matching "\\`From ", create a nndoc/mbox summary.
+
+ - For files matching "\\`BABYL OPTIONS:", create a nndoc/baby
+ summary.
+
+ - For files matching "\\`[^ \t\n]+:", create an *Article* buffer.
+
+ - For other files, just find them normally.
+
+ I'd like `nneething' to use this function, so it would work on a
+ directory potentially containing mboxes or babyl files.
+
+* Please send a mail to bwarsaw@cnri.reston.va.us (Barry A. Warsaw)
+ and tell him what you are doing.
+
+* Currently, I get prompted:
+
+ decend into sci?  - type y decend into sci.something ?  - type n
+ decend into ucd?
+
+ The problem above is that since there is really only one
+ subsection of science, shouldn't it prompt you for only descending
+ sci.something?  If there was a sci.somethingelse group or section,
+ then it should prompt for sci? first the sci.something? then
+ sci.somethingelse?...
+
+* Ja, det burde v\e,Af\e(Bre en m\e,Ae\e(Bte \e,Ae\e(B si slikt.  Kanskje en ny variabel?
+ `gnus-use-few-score-files'?  S\e,Ae\e(B kunne score-regler legges til den
+ "mest" lokale score-fila.  F. eks. ville no-gruppene betjenes av
+ "no.all.SCORE", osv.
+
+* What i want is for Gnus to treat any sequence or combination of
+ the following as a single spoiler warning and hide it all,
+ replacing it with a "Next Page" button:
+
+ ^L's
+
+ more than n blank lines
+
+ more than m identical lines (which should be replaced with button
+ to show them)
+
+ any whitespace surrounding any of the above
+
+* Well, we could allow a new value to `gnus-thread-ignore-subject' -
+ `spaces', or something.  (We could even default to that.)  And then
+ subjects that differ in white space only could be considered the
+ "same" subject for threading purposes.
+
+* Modes to preprocess the contents (e.g. jka-compr) use the second
+ form "(REGEXP FUNCTION NON-NIL)" while ordinary modes (e.g. tex)
+ use the first form "(REGEXP . FUNCTION)", so you could use it to
+ distinguish between those two types of modes. (auto-modes-alist,
+ insert-file-contents-literally.)
+
+*  Under XEmacs - do funny article marks: tick - thumb tack killed -
+ skull soup - bowl of soup score below - dim light bulb score over
+ - bright light bulb
+
+* Yes. I think the algorithm is as follows:
+
+      Group-mode
+
+        show-list-of-articles-in-group
+             if (key-pressed == SPACE)
+                     if (no-more-articles-in-group-to-select)
+                             if (articles-selected)
+                                     start-reading-selected-articles;
+                             junk-unread-articles;
+                             next-group;
+                      else
+                             show-next-page;
+
+              else if (key-pressed = '.')
+                     if (consolidated-menus)         # same as hide-thread in Gnus
+                             select-thread-under-cursor;
+                     else
+                             select-article-under-cursor;
+
+
+      Article-mode
+             if (key-pressed == SPACE)
+                     if (more-pages-in-article)
+                             next-page;
+                     else if (more-selected-articles-to-read)
+                             next-article;
+                     else
+                             next-group;
+
+* My precise need here would have been to limit files to Incoming*.
+ One could think of some `nneething-only-files' variable, but I
+ guess it would have been unacceptable if one was using many
+ unrelated such nneething groups.
+
+ A more useful approach would be to, in response to the `G D'
+ prompt, be allowed to say something like: `~/.mail/Incoming*',
+ somewhat limiting the top-level directory only (in case
+ directories would be matched by the wildcard expression).
+
+* It would be nice if it also handled
+
+ <URL:news://sunsite.auc.dk/>
+
+ which should correspond to `B nntp RET sunsite.auc.dk' in *Group*.
+
+ [done]
+
+*    Take a look at w3-menu.el in the Emacs-W3 distribution - this
+ works out really well.  Each menu is 'named' by a symbol that
+ would be on a gnus-*-menus (where * would be whatever, but at
+ least group, summary, and article versions) variable.
+
+ So for gnus-summary-menus, I would set to '(sort mark dispose ...)
+
+ A value of '1' would just put _all_ the menus in a single 'GNUS'
+ menu in the main menubar.  This approach works really well for
+ Emacs-W3 and VM.
+
+*  nndoc should take care to create unique Message-IDs for all its
+ articles.
+
+*  gnus-score-followup-article only works when you have a summary
+ buffer active.  Make it work when posting from the group buffer as
+ well.  (message-sent-hook).
+
+*  rewrite gnus-demon to use run-with-idle-timers.
+
+*  * Enhancements to Gnus:
+
+ Add two commands:
+
+ * gnus-servers (gnus-start-server-buffer?)-enters Gnus and goes
+ straight to the server buffer, without opening any connections to
+    servers first.
+
+ * gnus-server-read-server-newsrc-produces a buffer very similar to
+    the group buffer, but with only groups from that server listed;
+    quitting this buffer returns to the server buffer.
+
+*  add a command to check the integrity of an nnfolder folder - go
+ through the article numbers and see that there are no duplicates,
+ and stuff.
+
+*  `unsmileyfy-buffer' to undo smileification.
+
+*  a command to give all relevant info on an article, including all
+ secondary marks.
+
+*  when doing `-request-accept-article', the backends should do the
+ nnmail duplicate checking.
+
+*  allow `message-signature-file' to be a function to return the
+ value of the signature file.
+
+*  In addition, I would love it if I could configure message-tab so
+ that it could call `bbdb-complete-name' in other headers.  So,
+ some sort of interface like
+
+ (setq message-tab-alist       '((message-header-regexp
+ message-expand-group)         ("^\\(To\\|[cC]c\\|[bB]cc\\)"
+ bbdb-complete-name)))
+
+ then you could run the relevant function to complete the
+ information in the header
+
+*  cache the newsgroups file locally to avoid reloading it all the
+ time.
+
+*  a command to import a buffer into a group.
+
+*  nnweb should allow fetching by Message-ID from servers.
+
+*  point in the article buffer doesn't always go to the beginning of
+ the buffer when selecting new articles.
+
+*  a command to process mark all unread articles.
+
+*  `gnus-gather-threads-by-references-and-subject' - first do
+ gathering by references, and then go through the dummy roots and
+ do more gathering by subject.
+
+*  gnus-uu-mark-in-numerical-order - process mark articles in
+ article numerical order.
+
+*  (gnus-thread-total-score  (gnus-id-to-thread (mail-header-id
+ (gnus-summary-article-header)))) bind to a key.
+
+*  sorting by score is wrong when using sparse threads.
+
+*  a command to fetch an arbitrary article - without having to be in
+ the summary buffer.
+
+*  a new nncvs backend.  Each group would show an article, using
+ version branches as threading, checkin date as the date, etc.
+
+*  http://www.dejanews.com/forms/dnsetfilter_exp.html ?  This filter
+ allows one to construct advance queries on the Dejanews database
+ such as specifying start and end dates, subject, author, and/or
+ newsgroup name.
+
+*  new Date header scoring type - older, newer
+
+*  use the summary toolbar in the article buffer.
+
+*  a command to fetch all articles that are less than X days old.
+
+*  in pick mode, `q' should save the list of selected articles in the
+ group info.  The next time the group is selected, these articles
+ will automatically get the process mark.
+
+*  Isn't it possible to (also?) allow M-^ to automatically try the
+ default server if it fails on the current server?  (controlled by a
+ user variable, (nil, t, 'ask)).
+
+*  make it possible to cancel articles using the select method for
+ the current group.
+
+*  `gnus-summary-select-article-on-entry' or something.  It'll
+ default to t and will select whatever article decided by
+ `gnus-auto-select-first'.
+
+*  a new variable to control which selection commands should be
+ unselecting.  `first', `best', `next', `prev', `next-unread',
+ `prev-unread' are candidates.
+
+*  be able to select groups that have no articles in them to be able
+ to post in them (using the current select method).
+
+*  be able to post via DejaNews.
+
+*  `x' should retain any sortings that have been performed.
+
+*  allow the user to specify the precedence of the secondary marks.
+ Also allow them to be displayed separately.
+
+*  gnus-summary-save-in-pipe should concatenate the results from the
+ processes when doing a process marked pipe.
+
+*  a new match type, like Followup, but which adds Thread matches on
+ all articles that match a certain From header.
+
+*  a function that can be read from kill-emacs-query-functions to
+ offer saving living summary buffers.
+
+*  a function for selecting a particular group which will contain
+ the articles listed in a list of article numbers/id's.
+
+*  a battery of character translation functions to translate common
+ Mac, MS (etc) characters into ISO 8859-1.
+
+      (defun article-fix-m$word ()
+       "Fix M$Word smartquotes in an article."
+       (interactive)
+       (save-excursion
+         (let ((buffer-read-only nil))
+           (goto-char (point-min))
+           (while (search-forward "\221" nil t)
+             (replace-match "`" t t))
+           (goto-char (point-min))
+           (while (search-forward "\222" nil t)
+             (replace-match "'" t t))
+           (goto-char (point-min))
+           (while (search-forward "\223" nil t)
+             (replace-match "\"" t t))
+           (goto-char (point-min))
+           (while (search-forward "\224" nil t)
+             (replace-match "\"" t t)))))
+
+  [done]
+
+*       (add-hook 'gnus-exit-query-functions
+      '(lambda ()
+        (if (and (file-exists-p nnmail-spool-file)
+                 (> (nnheader-file-size nnmail-spool-file) 0))
+            (yes-or-no-p "New mail has arrived.  Quit Gnus anyways? ")
+            (y-or-n-p "Are you sure you want to quit Gnus? "))))
+
+*  allow message-default-headers to be a function.
+
+*  new Date score match types - < > = (etc) that take floating point
+ numbers and match on the age of the article.
+
+*      >  > > If so, I've got one gripe: It seems that when I fire up gnus 5.2.25
+      >  > > under xemacs-19.14, it's creating a new frame, but is erasing the
+      >  > > buffer in the frame that it was called from =:-O
+      >
+      >  > Hm.  How do you start up Gnus?  From the toolbar or with
+      >  > `M-x gnus-other-frame'?
+      >
+      >    I normally start it up from the toolbar; at
+      > least that's the way I've caught it doing the
+      > deed before.
+
+*  all commands that react to the process mark should push the
+ current process mark set onto the stack.
+
+*  gnus-article-hide-pgp Selv ville jeg nok ha valgt \e,Ae\e(B slette den
+ dersom teksten matcher
+      "\\(This\s+\\)?[^ ]+ has been automatically signed by"
+ og det er maks hundre tegn mellom match-end og ---linja.  Men -det-
+ er min type heuristikk og langt fra alles.
+
+*  `gnus-subscribe-sorted' - insert new groups where they would have
+ been sorted to if `gnus-group-sort-function' were run.
+
+*  gnus-(group,summary)-highlight should respect any `face' text
+ props set on the lines.
+
+*  use run-with-idle-timer for gnus-demon instead of the home-brewed
+ stuff for better reliability.
+
+*  add a way to select which NoCeM type to apply - spam, troll, etc.
+
+*  nndraft-request-group should tally auto-save files.
+
+*  implement nntp-retry-on-break and nntp-command-timeout.
+
+*  gnus-article-highlight-limit that says when not to highlight
+ (long) articles.
+
+*  (nnoo-set SERVER VARIABLE VALUE)
+
+   [done]
+
+*  nn*-spool-methods
+
+*  interrupitng agent fetching of articles should save articles.
+
+*  command to open a digest group, and copy all the articles there
+ to the current group.
+
+*  a variable to disable article body highlights if there's more than
+ X characters in the body.
+
+*  handle 480/381 authinfo requests separately.
+
+*  include the texi/dir file in the distribution.
+
+*  format spec to "tab" to a position.
+
+*  Move all prompting to the new `M-n' default style.
+
+*  command to display all dormant articles.
+
+*  gnus-auto-select-next makeover - list of things it should do.
+
+*  a score match type that adds scores matching on From if From has
+ replied to something someone else has said.
+
+*  Read Netscape discussion groups:
+ snews://secnews.netscape.com/netscape.communicator.unix
+
+* One command to edit the original version if an article, and one to
+ edit the displayed version.
+
+* `T v' - make all process-marked articles the children of the
+ current article.
+
+* Switch from initial text to the new default text mechanism.
+
+* How about making it possible to expire local articles?  Will it be
+ possible to make various constraints on when an article can be
+ expired, e.g. (read), (age > 14 days), or the more interesting
+ (read & age > 14 days)?
+
+* New limit command--limit to articles that have a certain string in
+ the head or body.
+
+* Allow breaking lengthy NNTP commands.
+
+* gnus-article-highlight-limit, to disable highlighting in big
+ articles.
+
+* Editing an article should put the article to be edited in a
+ special, unique buffer.
+
+* A command to send a mail to the admin-address group param.
+
+* A Date scoring type that will match if the article is less than a
+ certain number of days old.
+
+* New spec: %~(tab 56) to put point on column 56
+
+* Allow Gnus Agent scoring to use normal score files.
+
+* Rething the Agent active file thing.  `M-g' doesn't update the
+ active file, for instance.
+
+* With dummy roots, `^' and then selecing the first article in any
+ other dummy thread will make Gnus highlight the dummy root instead
+ of the first article.
+
+* Propagate all group properties (marks, article numbers, etc) up to
+ the topics for displaying.
+
+* `n' in the group buffer with topics should go to the next group
+ with unread articles, even if that group is hidden in a topic.
+
+* gnus-posting-styles doesn't work in drafts.
+
+* gnus-summary-limit-include-cached is slow when there are many
+ articles in the cache, since it regenerates big parts of the
+ summary buffer for each article.
+
+* Implement gnus-batch-brew-soup.
+
+* Group parameters and summary commands for un/subscribing to mailing
+ lists.
+
+* Introduce nnmail-home-directory.
+
+* gnus-fetch-group and friends should exit Gnus when the user exits
+ the group.
+
+* The jingle is only played on the second invocation of Gnus.
+
+* Bouncing articles should do MIME.
+
+  [done]
+
+* Crossposted articles should "inherit" the % or  mark from the other
+ groups it has been crossposted to, or something.  (Agent.)
+
+* If point is on a group that appears multiple times in topics, and
+ you press `l', point will move to the first instance of the group.
+
+* A spec for the group line format to display the number of
+ agent-downloaded articles in the group.
+
+* Some nntp servers never respond when posting, so there should be a
+ timeout for all commands.
+
+* When stading on a topic line and `t'-ing, point goes to the last
+ line.  It should go somewhere else.
+
+* I'm having trouble accessing a newsgroup with a "+" in its name
+ with Gnus.  There is a new newsgroup on msnews.microsoft.com named
+ "microsoft.public.multimedia.directx.html+time" that I'm trying to
+ access as
+ "nntp+msnews.microsoft.com:microsoft.public.multimedia.directx.html+time"
+ but it gives an error that it cant access the group.
+
+ Is the "+" character illegal in newsgroup names?  Is there any way
+ in Gnus to work around this?  (gnus 5.6.45 - XEmacs 20.4)
+
+ [It works in 5.8.8.]
+
+*  When `#F', do:
+
+      Subject: Answer to your mails 01.01.1999-01.05.1999
+       --text follows this line--
+      Sorry I killfiled you...
+
+      Under the subject "foo", you wrote on 01.01.1999:
+      > bar
+      Under the subject "foo1", you wrote on 01.01.1999:
+      > bar 1
+
+* Allow "orphan" scores in the Agent scoring.
+
+  [done?]
+
+*          - Edit article's summary line.
+         - End edit
+         - Sort lines in buffer by subject
+
+         --> the old subject line appears in Summary buffer, not the one that was
+         just changed to.
+
+* Remove list identifiers from the subject in the summary when doing
+ `^' and the like.
+
+* Have the Agent write out articles, one by one, as it retrieves
+ them, to avoid having to re-fetch them all if Emacs should crash
+ while fetching.
+
+* Be able to forward groups of messages as MIME digests.
+
+ [done]
+
+* nnweb should include the "get whole article" article when getting
+ articles.
+
+* When I type W W c (gnus-article-hide-citation) in the summary
+ buffer, the citations are revealed, but the [+] buttons don't turn
+ into [-] buttons.  (If I click on one of the [+] buttons, it does
+ turn into a [-] button.)
+
+ [fixed]
+
+* Perhaps there should be a command to "attach" a buffer of comments
+ to a message?  That is, `B WHATEVER', you're popped into a buffer,
+ write something, end with `C-c C-c', and then the thing you've
+ written gets to be the child of the message you're commenting.
+
+* Handle external-body parts.
+
+  [done for some access types]
+
+* When renaming a group name, nnmail-split-history does not get the
+ group name renamed.
+
+* Allow mail splitting on bodies when using advanced mail splitting.
+
+       (body "whatever.text")
+
+* Be able to run `J u' from summary buffers.
+
+  [Done]
+
+* Solve the halting problem.
+
+\f
+;; Local Variables:
+;; mode: outline
+;; coding: iso-2022-7bit
+;; paragraph-separate: "[      \f]*$"
+;; End: